return t('fields:addLabel')
},
diff --git a/docs/configuration/localization.mdx b/docs/configuration/localization.mdx
index 32bc1c529c..a03961e111 100644
--- a/docs/configuration/localization.mdx
+++ b/docs/configuration/localization.mdx
@@ -17,7 +17,8 @@ import { buildConfig } from 'payload'
export default buildConfig({
// ...
- localization: { // highlight-line
+ localization: {
+ // highlight-line
// ...
},
})
@@ -71,18 +72,18 @@ export default buildConfig({
```
- **Tip:**
- Localization works very well alongside [I18n](/docs/configuration/i18n).
+ **Tip:** Localization works very well alongside
+ [I18n](/docs/configuration/i18n).
The following options are available:
| Option | Description |
-|------------------------------|-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
+| ---------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| **`locales`** | Array of all the languages that you would like to support. [More details](#locales) |
| **`defaultLocale`** | Required string that matches one of the locale codes from the array provided. By default, if no locale is specified, documents will be returned in this locale. |
| **`fallback`** | Boolean enabling "fallback" locale functionality. If a document is requested in a locale, but a field does not have a localized value corresponding to the requested locale, then if this property is enabled, the document will automatically fall back to the fallback locale value. If this property is not enabled, the value will not be populated unless a fallback is explicitly provided in the request. True by default. |
-| **`filterAvailableLocales`** | A function that is called with the array of `locales` and the `req`, it should return locales to show in admin UI selector. [See more](#filter-available-options). |
+| **`filterAvailableLocales`** | A function that is called with the array of `locales` and the `req`, it should return locales to show in admin UI selector. [See more](#filter-available-options). |
### Locales
@@ -94,14 +95,15 @@ The locale codes do not need to be in any specific format. It's up to you to def
| Option | Description |
| -------------------- | ------------------------------------------------------------------------------------------------------------------------------ |
-| **`code`** * | Unique code to identify the language throughout the APIs for `locale` and `fallbackLocale` |
+| **`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. |
| **`fallbackLocale`** | The code for this language to fallback to when properties of a document are not present. |
-_* An asterisk denotes that a property is required._
+_\* An asterisk denotes that a property is required._
#### Filter Available Options
+
In some projects you may want to filter the available locales shown in the admin UI selector. You can do this by providing a `filterAvailableLocales` function in your Payload Config. This is called on the server side and is passed the array of locales. This means that you can determine what locales are visible in the localizer selection menu at the top of the admin panel. You could do this per user, or implement a function that scopes these to tenants and more. Here is an example using request headers in a multi-tenant application:
```ts
@@ -129,7 +131,6 @@ localization: {
Since the filtering happens at the root level of the application and its result is not calculated every time you navigate to a new page, you may want to call `router.refresh` in a custom component that watches when values that affect the result change. In the example above, you would want to do this when `supportedLocales` changes on the tenant document.
-
## Field Localization
Payload Localization works on a **field** level—not a document level. In addition to configuring the base Payload Config to support Localization, you need to specify each field that you would like to localize.
@@ -151,18 +152,18 @@ With the above configuration, the `title` field will now be saved in the databas
All field types with a `name` property support the `localized` property—even the more complex field types like `array`s and `block`s.
- **Note:**
- Enabling Localization for field types that support nested fields will automatically create
- localized "sets" of all fields contained within the field. For example, if you have a page layout
- using a blocks field type, you have the choice of either localizing the full layout, by enabling
- Localization on the top-level blocks field, or only certain fields within the layout.
+ **Note:** Enabling Localization for field types that support nested fields
+ will automatically create localized "sets" of all fields contained within the
+ field. For example, if you have a page layout using a blocks field type, you
+ have the choice of either localizing the full layout, by enabling Localization
+ on the top-level blocks field, or only certain fields within the layout.
- **Important:**
- When converting an existing field to or from `localized: true` the data structure in the document
- will change for this field and so existing data for this field will be lost. Before changing the
- Localization setting on fields with existing data, you may need to consider a field migration
+ **Important:** When converting an existing field to or from `localized: true`
+ the data structure in the document will change for this field and so existing
+ data for this field will be lost. Before changing the Localization setting on
+ fields with existing data, you may need to consider a field migration
strategy.
@@ -213,9 +214,10 @@ query {
```
- In GraphQL, specifying the locale at the top level of a query will automatically apply it
- throughout all nested relationship fields. You can override this behavior by re-specifying locale
- arguments in nested related document queries.
+ In GraphQL, specifying the locale at the top level of a query will
+ automatically apply it throughout all nested relationship fields. You can
+ override this behavior by re-specifying locale arguments in nested related
+ document queries.
#### Local API
@@ -235,8 +237,8 @@ const posts = await payload.find({
```
- **Tip:**
- The REST and Local APIs can return all Localization data in one request by passing 'all' or '*' as
- the **locale** parameter. The response will be structured so that field values come
- back as the full objects keyed for each locale instead of the single, translated value.
+ **Tip:** The REST and Local APIs can return all Localization data in one
+ request by passing 'all' or '*' as the **locale** parameter. The response will
+ be structured so that field values come back as the full objects keyed for
+ each locale instead of the single, translated value.
diff --git a/docs/configuration/overview.mdx b/docs/configuration/overview.mdx
index c51de58e2b..f2720bb7fd 100644
--- a/docs/configuration/overview.mdx
+++ b/docs/configuration/overview.mdx
@@ -23,8 +23,8 @@ export default buildConfig({
The Payload Config is strongly typed and ties directly into Payload's TypeScript codebase. This means your IDE (such as VSCode) will provide helpful information like type-ahead suggestions while you write your config.
- **Tip:**
- The location of your Payload Config can be customized. [More details](#customizing-the-config-location).
+ **Tip:** The location of your Payload Config can be customized. [More
+ details](#customizing-the-config-location).
## Config Options
@@ -48,17 +48,19 @@ export default buildConfig({
fields: [
{
name: 'title',
- type: 'text'
- }
- ]
- }
+ type: 'text',
+ },
+ ],
+ },
],
})
```
- **Note:**
- For more complex examples, see the [Templates](https://github.com/payloadcms/payload/tree/main/templates) and [Examples](https://github.com/payloadcms/payload/tree/main/examples) directories in the Payload repository.
+ **Note:** For more complex examples, see the
+ [Templates](https://github.com/payloadcms/payload/tree/main/templates) and
+ [Examples](https://github.com/payloadcms/payload/tree/main/examples)
+ directories in the Payload repository.
The following options are available:
@@ -68,7 +70,7 @@ The following options are available:
| **`admin`** | The configuration options for the Admin Panel, including Custom Components, Live Preview, etc. [More details](../admin/overview#admin-options). |
| **`bin`** | Register custom bin scripts for Payload to execute. [More Details](#custom-bin-scripts). |
| **`editor`** | The Rich Text Editor which will be used by `richText` fields. [More details](../rich-text/overview). |
-| **`db`** * | The Database Adapter which will be used by Payload. [More details](../database/overview). |
+| **`db`** \* | The Database Adapter which will be used by Payload. [More details](../database/overview). |
| **`serverURL`** | A string used to define the absolute URL of your app. This includes the protocol, for example `https://example.com`. No paths allowed, only protocol, domain and (optionally) port. |
| **`collections`** | An array of Collections for Payload to manage. [More details](./collections). |
| **`compatibility`** | Compatibility flags for earlier versions of Payload. [More details](#compatibility-flags). |
@@ -95,15 +97,15 @@ The following options are available:
| **`endpoints`** | An array of Custom Endpoints added to the Payload router. [More details](../rest-api/overview#custom-endpoints). |
| **`custom`** | Extension point for adding custom data (e.g. for plugins). |
| **`i18n`** | Internationalization configuration. Pass all i18n languages you'd like the admin UI to support. Defaults to English-only. [More details](./i18n). |
-| **`secret`** * | A secure, unguessable string that Payload will use for any encryption workflows - for example, password salt / hashing. |
+| **`secret`** \* | A secure, unguessable string that Payload will use for any encryption workflows - for example, password salt / hashing. |
| **`sharp`** | If you would like Payload to offer cropping, focal point selection, and automatic media resizing, install and pass the Sharp module to the config here. |
| **`typescript`** | Configure TypeScript settings here. [More details](#typescript). |
-_* An asterisk denotes that a property is required._
+_\* An asterisk denotes that a property is required._
- **Note:**
- Some properties are removed from the client-side bundle. [More details](../custom-components/overview#accessing-the-payload-config).
+ **Note:** Some properties are removed from the client-side bundle. [More
+ details](../custom-components/overview#accessing-the-payload-config).
### Typescript Config
@@ -117,33 +119,36 @@ import { buildConfig } from 'payload'
export default buildConfig({
// ...
- typescript: { // highlight-line
+ typescript: {
+ // highlight-line
// ...
- }
+ },
})
```
The following options are available:
-| Option | Description |
-| --------------- | --------------------- |
+| Option | Description |
+| ------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| **`autoGenerate`** | By default, Payload will auto-generate TypeScript interfaces for all collections and globals that your config defines. Opt out by setting `typescript.autoGenerate: false`. [More details](../typescript/overview). |
-| **`declare`** | By default, Payload adds a `declare` block to your generated types, which makes sure that Payload uses your generated types for all Local API methods. Opt out by setting `typescript.declare: false`. |
-| **`outputFile`** | Control the output path and filename of Payload's auto-generated types by defining the `typescript.outputFile` property to a full, absolute path. |
+| **`declare`** | By default, Payload adds a `declare` block to your generated types, which makes sure that Payload uses your generated types for all Local API methods. Opt out by setting `typescript.declare: false`. |
+| **`outputFile`** | Control the output path and filename of Payload's auto-generated types by defining the `typescript.outputFile` property to a full, absolute path. |
## Config Location
For Payload command-line scripts, we need to be able to locate your Payload Config. We'll check a variety of locations for the presence of `payload.config.ts` by default, including:
1. The root current working directory
-1. The `compilerOptions` in your `tsconfig`*
-1. The `dist` directory*
+1. The `compilerOptions` in your `tsconfig`\*
+1. The `dist` directory\*
-_* Config location detection is different between development and production environments. See below for more details._
+_\* Config location detection is different between development and production environments. See below for more details._
- **Important:**
- Ensure your `tsconfig.json` is properly configured for Payload to auto-detect your config location. If if does not exist, or does not specify the proper `compilerOptions`, Payload will default to the current working directory.
+ **Important:** Ensure your `tsconfig.json` is properly configured for Payload
+ to auto-detect your config location. If if does not exist, or does not specify
+ the proper `compilerOptions`, Payload will default to the current working
+ directory.
**Development Mode**
@@ -194,8 +199,8 @@ To use a custom config location, set the `PAYLOAD_CONFIG_PATH` environment varia
```
- **Tip:**
- `PAYLOAD_CONFIG_PATH` can be either an absolute path, or path relative to your current working directory.
+ **Tip:** `PAYLOAD_CONFIG_PATH` can be either an absolute path, or path
+ relative to your current working directory.
## Telemetry
@@ -208,10 +213,10 @@ For more information about what we track, take a look at our [privacy policy](/p
Cross-origin resource sharing (CORS) can be configured with either a whitelist array of URLS to allow CORS requests from, a wildcard string (`*`) to accept incoming requests from any domain, or a object with the following properties:
-| Option | Description |
-| --------- | --------------------------------------------------------------------------------------------------------------------------------------- |
+| Option | Description |
+| ------------- | --------------------------------------------------------------------------------------------------------------------------------------- |
| **`origins`** | Either a whitelist array of URLS to allow CORS requests from, or a wildcard string (`'*'`) to accept incoming requests from any domain. |
-| **`headers`** | A list of allowed headers that will be appended in `Access-Control-Allow-Headers`. |
+| **`headers`** | A list of allowed headers that will be appended in `Access-Control-Allow-Headers`. |
Here's an example showing how to allow incoming requests from any domain:
@@ -220,7 +225,7 @@ import { buildConfig } from 'payload'
export default buildConfig({
// ...
- cors: '*' // highlight-line
+ cors: '*', // highlight-line
})
```
@@ -266,13 +271,11 @@ Payload localization works on a field-by-field basis. As you can nest fields wit
By default, Payload will remove the `localized: true` property from sub-fields if a parent field is localized. Set this compatibility flag to `true` only if you have an existing Payload MongoDB database from pre-3.0, and you have nested localized fields that you would like to maintain without migrating.
-
## Custom bin scripts
Using the `bin` configuration property, you can inject your own scripts to `npx payload`.
Example for `pnpm payload seed`:
-
Step 1: create `seed.ts` file in the same folder with `payload.config.ts` with:
```ts
@@ -283,13 +286,17 @@ import payload from 'payload'
// Script must define a "script" function export that accepts the sanitized config
export const script = async (config: SanitizedConfig) => {
await payload.init({ config })
- await payload.create({ collection: 'pages', data: { title: 'my title' } })
+ await payload.create({
+ collection: 'pages',
+ data: { title: 'my title' },
+ })
payload.logger.info('Succesffully seeded!')
process.exit(0)
}
```
Step 2: add the `seed` script to `bin`:
+
```ts
export default buildConfig({
bin: [
@@ -302,6 +309,7 @@ export default buildConfig({
```
Now you can run the command using:
+
```sh
pnpm payload seed
-```
\ No newline at end of file
+```
diff --git a/docs/custom-components/custom-providers.mdx b/docs/custom-components/custom-providers.mdx
index 26abe74fd1..18d1f6a220 100644
--- a/docs/custom-components/custom-providers.mdx
+++ b/docs/custom-components/custom-providers.mdx
@@ -32,11 +32,7 @@ import React, { createContext, use } from 'react'
const MyCustomContext = React.createContext(myCustomValue)
export function MyProvider({ children }: { children: React.ReactNode }) {
- return (
-
- {children}
-
- )
+ return {children}
}
export const useMyCustomContext = () => use(MyCustomContext)
@@ -45,5 +41,8 @@ export const useMyCustomContext = () => use(MyCustomContext)
_For details on how to build Custom Components, see [Building Custom Components](./overview#building-custom-components)._
- **Reminder:** React Context exists only within Client Components. This means they must include the `use client` directive at the top of their files and cannot contain server-only code. To use a Server Component here, simply _wrap_ your Client Component with it.
+ **Reminder:** React Context exists only within Client Components. This means
+ they must include the `use client` directive at the top of their files and
+ cannot contain server-only code. To use a Server Component here, simply _wrap_
+ your Client Component with it.
diff --git a/docs/custom-components/custom-views.mdx b/docs/custom-components/custom-views.mdx
index df5cb885c3..a976c48e1e 100644
--- a/docs/custom-components/custom-views.mdx
+++ b/docs/custom-components/custom-views.mdx
@@ -38,26 +38,26 @@ const config = buildConfig({
// highlight-start
dashboard: {
Component: '/path/to/MyCustomDashboard',
- }
+ },
// highlight-end
- }
- }
- }
+ },
+ },
+ },
})
```
For more granular control, pass a configuration object instead. Payload exposes the following properties for each view:
-| Property | Description |
-| ------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
-| `Component` * | Pass in the component path that should be rendered when a user navigates to this route. |
-| `path` * | Any valid URL path or array of paths that [`path-to-regexp`](https://www.npmjs.com/package/path-to-regex) understands. |
-| `exact` | Boolean. When true, will only match if the path matches the `usePathname()` exactly. |
+| Property | Description |
+| -------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
+| `Component` \* | Pass in the component path that should be rendered when a user navigates to this route. |
+| `path` \* | Any valid URL path or array of paths that [`path-to-regexp`](https://www.npmjs.com/package/path-to-regex) understands. |
+| `exact` | Boolean. When true, will only match if the path matches the `usePathname()` exactly. |
| `strict` | When true, a path that has a trailing slash will only match a `location.pathname` with a trailing slash. This has no effect when there are additional URL segments in the pathname. |
-| `sensitive` | When true, will match if the path is case sensitive.|
-| `meta` | Page metadata overrides to apply to this view within the Admin Panel. [More details](./metadata). |
+| `sensitive` | When true, will match if the path is case sensitive. |
+| `meta` | Page metadata overrides to apply to this view within the Admin Panel. [More details](./metadata). |
-_* An asterisk denotes that a property is required._
+_\* An asterisk denotes that a property is required._
### Adding New Views
@@ -86,14 +86,12 @@ const config = buildConfig({
```
- **Note:**
- Routes are cascading, so 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, define your nested route _before_ your parent
- route.
+ **Note:** Routes are cascading, so 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, define your nested route _before_ your parent route.
-
## Building Custom Views
Custom Views are simply [Custom Components](./overview) rendered at the page-level. Custom Views can either [replace existing views](#replacing-views) or [add entirely new ones](#adding-new-views). The process is generally the same regardless of the type of view you are customizing.
@@ -110,8 +108,8 @@ export const MyCollectionConfig: CollectionConfig = {
views: {
// highlight-start
edit: {
- Component: '/path/to/MyCustomView' // highlight-line
- }
+ Component: '/path/to/MyCustomView', // highlight-line
+ },
// highlight-end
},
},
@@ -123,20 +121,21 @@ export const MyCollectionConfig: CollectionConfig = {
Your Custom Views will be provided with the following props:
-| Prop | Description |
-| ------------------------- | ---------------------------------------------------------------------------------------------------------------------------------- |
-| `initPageResult` | An object containing `req`, `payload`, `permissions`, etc. |
-| `clientConfig` | The Client Config object. [More details](./overview#accessing-the-payload-config). |
-| `importMap` | The import map object. |
-| `params` | An object containing the [Dynamic Route Parameters](https://nextjs.org/docs/app/building-your-application/routing/dynamic-routes). |
-| `searchParams` | An object containing the [Search Parameters](https://developer.mozilla.org/docs/Learn/Common_questions/What_is_a_URL#parameters). |
-| `doc` | The document being edited. Only available in Document Views. [More details](./document-views). |
-| `i18n` | The [i18n](../configuration/i18n) object. |
-| `payload` | The [Payload](../local-api/overview) class. |
+| Prop | Description |
+| ---------------- | ---------------------------------------------------------------------------------------------------------------------------------- |
+| `initPageResult` | An object containing `req`, `payload`, `permissions`, etc. |
+| `clientConfig` | The Client Config object. [More details](./overview#accessing-the-payload-config). |
+| `importMap` | The import map object. |
+| `params` | An object containing the [Dynamic Route Parameters](https://nextjs.org/docs/app/building-your-application/routing/dynamic-routes). |
+| `searchParams` | An object containing the [Search Parameters](https://developer.mozilla.org/docs/Learn/Common_questions/What_is_a_URL#parameters). |
+| `doc` | The document being edited. Only available in Document Views. [More details](./document-views). |
+| `i18n` | The [i18n](../configuration/i18n) object. |
+| `payload` | The [Payload](../local-api/overview) class. |
- **Note:**
- Some views may receive additional props, such as [Collection Views](#collection-views) and [Global Views](#global-views). See the relevant section for more details.
+ **Note:** Some views may receive additional props, such as [Collection
+ Views](#collection-views) and [Global Views](#global-views). See the relevant
+ section for more details.
Here is an example of a Custom View component:
@@ -158,8 +157,8 @@ export function MyCustomView(props: AdminViewServerProps) {
```
- **Tip:**
- For consistent layout and navigation, you may want to wrap your Custom View with one of the built-in [Template](./overview#templates).
+ **Tip:** For consistent layout and navigation, you may want to wrap your
+ Custom View with one of the built-in [Template](./overview#templates).
### View Templates
@@ -212,13 +211,9 @@ import type { AdminViewServerProps } from 'payload'
import { Gutter } from '@payloadcms/ui'
import React from 'react'
-export function MyCustomView({
- initPageResult
-}: AdminViewServerProps) {
+export function MyCustomView({ initPageResult }: AdminViewServerProps) {
const {
- req: {
- user
- }
+ req: { user },
} = initPageResult
if (!user) {
@@ -251,7 +246,7 @@ const config = buildConfig({
// highlight-start
dashboard: {
Component: '/path/to/Dashboard',
- }
+ },
// highlight-end
// Other options include:
// - account
@@ -267,11 +262,11 @@ _For details on how to build Custom Views, including all available props, see [B
The following options are available:
-| 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. |
-| `[key]` | Any other key can be used to add a completely new Root View. [More details](#adding-new-views). |
+| 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. |
+| `[key]` | Any other key can be used to add a completely new Root View. [More details](#adding-new-views). |
## Collection Views
@@ -291,8 +286,8 @@ export const MyCollectionConfig: CollectionConfig = {
edit: {
default: {
Component: '/path/to/MyCustomCollectionView',
- }
- }
+ },
+ },
// highlight-end
// Other options include:
// - list
@@ -305,17 +300,18 @@ export const MyCollectionConfig: CollectionConfig = {
```
- **Reminder:**
- The `edit` key is comprised of various nested views, known as Document Views, that relate to the same Collection Document. [More details](./document-views).
+ **Reminder:** The `edit` key is comprised of various nested views, known as
+ Document Views, that relate to the same Collection Document. [More
+ details](./document-views).
The following options are available:
-| Property | Description |
-| ---------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------- |
-| `edit` | The Edit View corresponds to a single Document for any given Collection and consists of various nested views. [More details](./document-views). |
-| `list` | The List View is used to show a list of Documents for any given Collection. [More details](#list-view). |
-| `[key]` | Any other key can be used to add a completely new Collection View. [More details](#adding-new-views). |
+| Property | Description |
+| -------- | ----------------------------------------------------------------------------------------------------------------------------------------------- |
+| `edit` | The Edit View corresponds to a single Document for any given Collection and consists of various nested views. [More details](./document-views). |
+| `list` | The List View is used to show a list of Documents for any given Collection. [More details](#list-view). |
+| `[key]` | Any other key can be used to add a completely new Collection View. [More details](#adding-new-views). |
_For details on how to build Custom Views, including all available props, see [Building Custom Views](#building-custom-views)._
@@ -337,8 +333,8 @@ export const MyGlobalConfig: SanitizedGlobalConfig = {
edit: {
default: {
Component: '/path/to/MyCustomGlobalView',
- }
- }
+ },
+ },
// highlight-end
// Other options include:
// - [key: string]
@@ -350,15 +346,16 @@ export const MyGlobalConfig: SanitizedGlobalConfig = {
```
- **Reminder:**
- The `edit` key is comprised of various nested views, known as Document Views, that relate to the same Global Document. [More details](./document-views).
+ **Reminder:** The `edit` key is comprised of various nested views, known as
+ Document Views, that relate to the same Global Document. [More
+ details](./document-views).
The following options are available:
-| Property | Description |
-| ---------- | ----------------------------------------------------------------------------------------------------------------------------------------------- |
-| `edit` | The Edit View represents a single Document for any given Global and consists of various nested views. [More details](./document-views). |
-| `[key]` | Any other key can be used to add a completely new Global View. [More details](#adding-new-views). |
+| Property | Description |
+| -------- | --------------------------------------------------------------------------------------------------------------------------------------- |
+| `edit` | The Edit View represents a single Document for any given Global and consists of various nested views. [More details](./document-views). |
+| `[key]` | Any other key can be used to add a completely new Global View. [More details](#adding-new-views). |
_For details on how to build Custom Views, including all available props, see [Building Custom Views](#building-custom-views)._
diff --git a/docs/custom-components/document-views.mdx b/docs/custom-components/document-views.mdx
index 2e880ad1ab..0680b7cf5f 100644
--- a/docs/custom-components/document-views.mdx
+++ b/docs/custom-components/document-views.mdx
@@ -45,15 +45,15 @@ export const MyCollectionOrGlobalConfig: CollectionConfig = {
The following options are available:
-| Property | Description |
-| ----------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------- |
-| `root` | The Root View overrides all other nested views and routes. No document controls or tabs are rendered when this key is set. [More details](#document-root). |
-| `default` | The Default View is the primary view in which your document is edited. It is rendered within the "Edit" tab. [More details](./edit-view). |
+| Property | Description |
+| ------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------- |
+| `root` | The Root View overrides all other nested views and routes. No document controls or tabs are rendered when this key is set. [More details](#document-root). |
+| `default` | The Default View is the primary view in which your document is edited. It is rendered within the "Edit" tab. [More details](./edit-view). |
| `versions` | The Versions View is used to navigate the version history of a single document. It is rendered within the "Versions" tab. [More details](../versions/overview). |
| `version` | The Version View is used to edit a single version of a document. It is rendered within the "Version" tab. [More details](../versions/overview). |
| `api` | The API View is used to display the REST API JSON response for a given document. It is rendered within the "API" tab. |
| `livePreview` | The LivePreview view is used to display the Live Preview interface. It is rendered within the "Live Preview" tab. [More details](../live-preview/overview). |
-| `[key]` | Any other key can be used to add a completely new Document View. |
+| `[key]` | Any other key can be used to add a completely new Document View. |
_For details on how to build Custom Views, including all available props, see [Building Custom Views](./custom-views#building-custom-views)._
@@ -112,8 +112,8 @@ export const MyCollection: CollectionConfig = {
path: '/my-custom-tab',
// highlight-start
tab: {
- Component: '/path/to/MyCustomTabComponent'
- }
+ Component: '/path/to/MyCustomTabComponent',
+ },
// highlight-end
},
anotherCustomTab: {
@@ -123,7 +123,7 @@ export const MyCollection: CollectionConfig = {
tab: {
label: 'Another Custom View',
href: '/another-custom-view',
- }
+ },
// highlight-end
},
},
@@ -134,16 +134,15 @@ export const MyCollection: CollectionConfig = {
```
- **Note:**
- This applies to _both_ Collections _and_ Globals.
+ **Note:** This applies to _both_ Collections _and_ Globals.
The following options are available for tabs:
-| Property | Description |
-| ----------- | ----------------------------------------------------------------------------------------------------- |
-| `label` | The label to display in the tab. |
-| `href` | The URL to navigate to when the tab is clicked. This is optional and defaults to the tab's `path`. |
+| Property | Description |
+| ----------- | ------------------------------------------------------------------------------------------------------------- |
+| `label` | The label to display in the tab. |
+| `href` | The URL to navigate to when the tab is clicked. This is optional and defaults to the tab's `path`. |
| `Component` | The component to render in the tab. This can be a Server or Client component. [More details](#tab-components) |
### Tab Components
@@ -161,9 +160,7 @@ import { Link } from '@payloadcms/ui'
export function MyCustomTabComponent(props: DocumentTabServerProps) {
return (
-
- This is a custom Document Tab (Server)
-
+ This is a custom Document Tab (Server)
)
}
```
@@ -178,9 +175,7 @@ import { Link } from '@payloadcms/ui'
export function MyCustomTabComponent(props: DocumentTabClientProps) {
return (
-
- This is a custom Document Tab (Client)
-
+ This is a custom Document Tab (Client)
)
}
```
diff --git a/docs/custom-components/edit-view.mdx b/docs/custom-components/edit-view.mdx
index dea4501a72..6b4660afd7 100644
--- a/docs/custom-components/edit-view.mdx
+++ b/docs/custom-components/edit-view.mdx
@@ -11,8 +11,9 @@ The Edit View is where users interact with individual [Collection](../collection
The Edit View can be swapped out in its entirety for a Custom View, or it can be injected with a number of Custom Components to add additional functionality or presentational elements without replacing the entire view.
- **Note:**
- The Edit View is one of many [Document Views](./document-views) in the Payload Admin Panel. Each Document View is responsible for a different aspect of the interacting with a single Document.
+ **Note:** The Edit View is one of many [Document Views](./document-views) in
+ the Payload Admin Panel. Each Document View is responsible for a different
+ aspect of the interacting with a single Document.
## Custom Edit View
@@ -33,7 +34,7 @@ const config = buildConfig({
Component: '/path/to/MyCustomEditViewComponent',
},
// highlight-end
- }
+ },
},
},
},
@@ -49,11 +50,7 @@ import React from 'react'
import type { DocumentViewServerProps } from 'payload'
export function MyCustomServerEditView(props: DocumentViewServerProps) {
- return (
-
- This is a custom Edit View (Server)
-
- )
+ return This is a custom Edit View (Server)
}
```
@@ -65,11 +62,7 @@ import React from 'react'
import type { DocumentViewClientProps } from 'payload'
export function MyCustomClientEditView(props: DocumentViewClientProps) {
- return (
-
- This is a custom Edit View (Client)
-
- )
+ return This is a custom Edit View (Client)
}
```
@@ -80,8 +73,9 @@ _For details on how to build Custom Views, including all available props, see [B
In addition to swapping out the entire Edit View with a [Custom View](./custom-views), you can also override individual components. This allows you to customize specific parts of the Edit View without swapping out the entire view.
- **Important:**
- Collection and Globals are keyed to a different property in the `admin.components` object have slightly different options. Be sure to use the correct key for the entity you are working with.
+ **Important:** Collection and Globals are keyed to a different property in the
+ `admin.components` object have slightly different options. Be sure to use the
+ correct key for the entity you are working with.
#### Collections
@@ -107,14 +101,14 @@ export const MyCollection: CollectionConfig = {
The following options are available:
-| Path | Description |
-|-----------------------|-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
-| `SaveButton` | A button that saves the current document. [More details](#SaveButton). |
-| `SaveDraftButton` | A button that saves the current document as a draft. [More details](#SaveDraftButton). |
-| `PublishButton` | A button that publishes the current document. [More details](#PublishButton). |
-| `PreviewButton` | A button that previews the current document. [More details](#PreviewButton). |
-| `Description` | A description of the Collection. [More details](#Description). |
-| `Upload` | A file upload component. [More details](#Upload). |
+| Path | Description |
+| ----------------- | -------------------------------------------------------------------------------------- |
+| `SaveButton` | A button that saves the current document. [More details](#SaveButton). |
+| `SaveDraftButton` | A button that saves the current document as a draft. [More details](#SaveDraftButton). |
+| `PublishButton` | A button that publishes the current document. [More details](#PublishButton). |
+| `PreviewButton` | A button that previews the current document. [More details](#PreviewButton). |
+| `Description` | A description of the Collection. [More details](#Description). |
+| `Upload` | A file upload component. [More details](#Upload). |
#### Globals
@@ -139,13 +133,13 @@ export const MyGlobal: GlobalConfig = {
The following options are available:
-| Path | Description |
-|-----------------------|-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
-| `SaveButton` | A button that saves the current document. [More details](#SaveButton). |
-| `SaveDraftButton` | A button that saves the current document as a draft. [More details](#SaveDraftButton). |
-| `PublishButton` | A button that publishes the current document. [More details](#PublishButton). |
-| `PreviewButton` | A button that previews the current document. [More details](#PreviewButton). |
-| `Description` | A description of the Global. [More details](#Description). |
+| Path | Description |
+| ----------------- | -------------------------------------------------------------------------------------- |
+| `SaveButton` | A button that saves the current document. [More details](#SaveButton). |
+| `SaveDraftButton` | A button that saves the current document as a draft. [More details](#SaveDraftButton). |
+| `PublishButton` | A button that publishes the current document. [More details](#PublishButton). |
+| `PreviewButton` | A button that previews the current document. [More details](#PreviewButton). |
+| `Description` | A description of the Global. [More details](#Description). |
### SaveButton
@@ -164,7 +158,7 @@ export const MyCollection: CollectionConfig = {
// highlight-start
SaveButton: '/path/to/MySaveButton',
// highlight-end
- }
+ },
},
},
}
@@ -180,9 +174,7 @@ import { SaveButton } from '@payloadcms/ui'
import type { SaveButtonServerProps } from 'payload'
export function MySaveButton(props: SaveButtonServerProps) {
- return (
-
- )
+ return
}
```
@@ -195,9 +187,7 @@ import { SaveButton } from '@payloadcms/ui'
import type { SaveButtonClientProps } from 'payload'
export function MySaveButton(props: SaveButtonClientProps) {
- return (
-
- )
+ return
}
```
@@ -218,7 +208,7 @@ export const MyCollection: CollectionConfig = {
// highlight-start
SaveDraftButton: '/path/to/MySaveDraftButton',
// highlight-end
- }
+ },
},
},
}
@@ -234,9 +224,7 @@ import { SaveDraftButton } from '@payloadcms/ui'
import type { SaveDraftButtonServerProps } from 'payload'
export function MySaveDraftButton(props: SaveDraftButtonServerProps) {
- return (
-
- )
+ return
}
```
@@ -249,9 +237,7 @@ import { SaveDraftButton } from '@payloadcms/ui'
import type { SaveDraftButtonClientProps } from 'payload'
export function MySaveDraftButton(props: SaveDraftButtonClientProps) {
- return (
-
- )
+ return
}
```
@@ -272,7 +258,7 @@ export const MyCollection: CollectionConfig = {
// highlight-start
PublishButton: '/path/to/MyPublishButton',
// highlight-end
- }
+ },
},
},
}
@@ -288,9 +274,7 @@ import { PublishButton } from '@payloadcms/ui'
import type { PublishButtonClientProps } from 'payload'
export function MyPublishButton(props: PublishButtonServerProps) {
- return (
-
- )
+ return
}
```
@@ -303,9 +287,7 @@ import { PublishButton } from '@payloadcms/ui'
import type { PublishButtonClientProps } from 'payload'
export function MyPublishButton(props: PublishButtonClientProps) {
- return (
-
- )
+ return
}
```
@@ -326,7 +308,7 @@ export const MyCollection: CollectionConfig = {
// highlight-start
PreviewButton: '/path/to/MyPreviewButton',
// highlight-end
- }
+ },
},
},
}
@@ -342,9 +324,7 @@ import { PreviewButton } from '@payloadcms/ui'
import type { PreviewButtonServerProps } from 'payload'
export function MyPreviewButton(props: PreviewButtonServerProps) {
- return (
-
- )
+ return
}
```
@@ -357,9 +337,7 @@ import { PreviewButton } from '@payloadcms/ui'
import type { PreviewButtonClientProps } from 'payload'
export function MyPreviewButton(props: PreviewButtonClientProps) {
- return (
-
- )
+ return
}
```
@@ -385,8 +363,8 @@ export const MyCollection: CollectionConfig = {
```
- **Note:**
- The `Description` component is shared between the Edit View and the [List View](./list-view).
+ **Note:** The `Description` component is shared between the Edit View and the
+ [List View](./list-view).
Here's an example of a custom `Description` component:
@@ -398,11 +376,7 @@ import React from 'react'
import type { ViewDescriptionServerProps } from 'payload'
export function MyDescriptionComponent(props: ViewDescriptionServerProps) {
- return (
-
- This is a custom description component (Server)
-
- )
+ return This is a custom description component (Server)
}
```
@@ -414,11 +388,7 @@ import React from 'react'
import type { ViewDescriptionClientProps } from 'payload'
export function MyDescriptionComponent(props: ViewDescriptionClientProps) {
- return (
-
- This is a custom description component (Client)
-
- )
+ return This is a custom description component (Client)
}
```
@@ -439,15 +409,14 @@ export const MyCollection: CollectionConfig = {
// highlight-start
Upload: '/path/to/MyUploadComponent',
// highlight-end
- }
+ },
},
},
}
```
- **Note:**
- The Upload component is only available for Collections.
+ **Note:** The Upload component is only available for Collections.
Here's an example of a custom `Upload` component:
@@ -456,8 +425,6 @@ Here's an example of a custom `Upload` component:
import React from 'react'
export function MyUploadComponent() {
- return (
-
- )
+ return
}
```
diff --git a/docs/custom-components/list-view.mdx b/docs/custom-components/list-view.mdx
index db954520fa..d2ce84d6e3 100644
--- a/docs/custom-components/list-view.mdx
+++ b/docs/custom-components/list-view.mdx
@@ -11,8 +11,9 @@ The List View is where users interact with a list of [Collection](../collections
The List View can be swapped out in its entirety for a Custom View, or it can be injected with a number of Custom Components to add additional functionality or presentational elements without replacing the entire view.
- **Note:**
- Only [Collections](../collections/overview) have a List View. [Globals](../globals/overview) do not have a List View as they are single documents.
+ **Note:** Only [Collections](../collections/overview) have a List View.
+ [Globals](../globals/overview) do not have a List View as they are single
+ documents.
## Custom List View
@@ -46,11 +47,7 @@ import type { ListViewServerProps } from 'payload'
import { DefaultListView } from '@payloadcms/ui'
export function MyCustomServerListView(props: ListViewServerProps) {
- return (
-
- This is a custom List View (Server)
-
- )
+ return This is a custom List View (Server)
}
```
@@ -62,11 +59,7 @@ import React from 'react'
import type { ListViewClientProps } from 'payload'
export function MyCustomClientListView(props: ListViewClientProps) {
- return (
-
- This is a custom List View (Client)
-
- )
+ return This is a custom List View (Client)
}
```
@@ -95,13 +88,13 @@ export const MyCollection: CollectionConfig = {
The following options are available:
-| Path | Description |
-|-----------------------|----------------------------------------------------------------------------------------------------------------------------- |
-| `beforeList` | An array of custom components to inject before the list of documents in the List View. [More details](#beforeList). |
-| `beforeListTable` | An array of custom components to inject before the table of documents in the List View. [More details](#beforeListTable). |
-| `afterList` | An array of custom components to inject after the list of documents in the List View. [More details](#afterList). |
-| `afterListTable` | An array of custom components to inject after the table of documents in the List View. [More details](#afterListTable). |
-| `Description` | A component to render a description of the Collection. [More details](#Description). |
+| Path | Description |
+| ----------------- | ------------------------------------------------------------------------------------------------------------------------- |
+| `beforeList` | An array of custom components to inject before the list of documents in the List View. [More details](#beforeList). |
+| `beforeListTable` | An array of custom components to inject before the table of documents in the List View. [More details](#beforeListTable). |
+| `afterList` | An array of custom components to inject after the list of documents in the List View. [More details](#afterList). |
+| `afterListTable` | An array of custom components to inject after the table of documents in the List View. [More details](#afterListTable). |
+| `Description` | A component to render a description of the Collection. [More details](#Description). |
### beforeList
@@ -117,9 +110,7 @@ export const MyCollection: CollectionConfig = {
admin: {
components: {
// highlight-start
- beforeList: [
- '/path/to/MyBeforeListComponent',
- ],
+ beforeList: ['/path/to/MyBeforeListComponent'],
// highlight-end
},
},
@@ -135,11 +126,7 @@ import React from 'react'
import type { BeforeListServerProps } from 'payload'
export function MyBeforeListComponent(props: BeforeListServerProps) {
- return (
-
- This is a custom beforeList component (Server)
-
- )
+ return This is a custom beforeList component (Server)
}
```
@@ -151,11 +138,7 @@ import React from 'react'
import type { BeforeListClientProps } from 'payload'
export function MyBeforeListComponent(props: BeforeListClientProps) {
- return (
-
- This is a custom beforeList component (Client)
-
- )
+ return This is a custom beforeList component (Client)
}
```
@@ -173,9 +156,7 @@ export const MyCollection: CollectionConfig = {
admin: {
components: {
// highlight-start
- beforeListTable: [
- '/path/to/MyBeforeListTableComponent',
- ],
+ beforeListTable: ['/path/to/MyBeforeListTableComponent'],
// highlight-end
},
},
@@ -191,11 +172,7 @@ import React from 'react'
import type { BeforeListTableServerProps } from 'payload'
export function MyBeforeListTableComponent(props: BeforeListTableServerProps) {
- return (
-
- This is a custom beforeListTable component (Server)
-
- )
+ return This is a custom beforeListTable component (Server)
}
```
@@ -207,11 +184,7 @@ import React from 'react'
import type { BeforeListTableClientProps } from 'payload'
export function MyBeforeListTableComponent(props: BeforeListTableClientProps) {
- return (
-
- This is a custom beforeListTable component (Client)
-
- )
+ return This is a custom beforeListTable component (Client)
}
```
@@ -229,9 +202,7 @@ export const MyCollection: CollectionConfig = {
admin: {
components: {
// highlight-start
- afterList: [
- '/path/to/MyAfterListComponent',
- ],
+ afterList: ['/path/to/MyAfterListComponent'],
// highlight-end
},
},
@@ -247,11 +218,7 @@ import React from 'react'
import type { AfterListServerProps } from 'payload'
export function MyAfterListComponent(props: AfterListServerProps) {
- return (
-
- This is a custom afterList component (Server)
-
- )
+ return This is a custom afterList component (Server)
}
```
@@ -263,11 +230,7 @@ import React from 'react'
import type { AfterListClientProps } from 'payload'
export function MyAfterListComponent(props: AfterListClientProps) {
- return (
-
- This is a custom afterList component (Client)
-
- )
+ return This is a custom afterList component (Client)
}
```
@@ -285,9 +248,7 @@ export const MyCollection: CollectionConfig = {
admin: {
components: {
// highlight-start
- afterListTable: [
- '/path/to/MyAfterListTableComponent',
- ],
+ afterListTable: ['/path/to/MyAfterListTableComponent'],
// highlight-end
},
},
@@ -303,11 +264,7 @@ import React from 'react'
import type { AfterListTableServerProps } from 'payload'
export function MyAfterListTableComponent(props: AfterListTableServerProps) {
- return (
-
- This is a custom afterListTable component (Server)
-
- )
+ return This is a custom afterListTable component (Server)
}
```
@@ -319,11 +276,7 @@ import React from 'react'
import type { AfterListTableClientProps } from 'payload'
export function MyAfterListTableComponent(props: AfterListTableClientProps) {
- return (
-
- This is a custom afterListTable component (Client)
-
- )
+ return This is a custom afterListTable component (Client)
}
```
@@ -349,8 +302,8 @@ export const MyCollection: CollectionConfig = {
```
- **Note:**
- The `Description` component is shared between the List View and the [Edit View](./edit-view).
+ **Note:** The `Description` component is shared between the List View and the
+ [Edit View](./edit-view).
Here's an example of a custom `Description` component:
@@ -362,11 +315,7 @@ import React from 'react'
import type { ViewDescriptionServerProps } from 'payload'
export function MyDescriptionComponent(props: ViewDescriptionServerProps) {
- return (
-
- This is a custom Collection description component (Server)
-
- )
+ return This is a custom Collection description component (Server)
}
```
@@ -378,10 +327,6 @@ import React from 'react'
import type { ViewDescriptionClientProps } from 'payload'
export function MyDescriptionComponent(props: ViewDescriptionClientProps) {
- return (
-
- This is a custom Collection description component (Client)
-
- )
+ return This is a custom Collection description component (Client)
}
```
diff --git a/docs/custom-components/overview.mdx b/docs/custom-components/overview.mdx
index 9ab42d1d56..3ea36e3149 100644
--- a/docs/custom-components/overview.mdx
+++ b/docs/custom-components/overview.mdx
@@ -11,8 +11,12 @@ The Payload [Admin Panel](../admin/overview) is designed to be as minimal and st
All Custom Components in Payload are [React Server Components](https://react.dev/reference/rsc/server-components) by default. This enables the use of the [Local API](../local-api/overview) directly on the front-end. Custom Components are available for nearly every part of the Admin Panel for extreme granularity and control.
- **Note:**
- Client Components continue to be fully supported. To use Client Components in your app, simply include the `'use client'` directive. Payload will automatically detect and remove all [non-serializable](https://react.dev/reference/rsc/use-client#serializable-types) default props before rendering your component. [More details](#client-components).
+ **Note:** Client Components continue to be fully supported. To use Client
+ Components in your app, simply include the `'use client'` directive. Payload
+ will automatically detect and remove all
+ [non-serializable](https://react.dev/reference/rsc/use-client#serializable-types)
+ default props before rendering your component. [More
+ details](#client-components).
There are four main types of Custom Components in Payload:
@@ -38,16 +42,17 @@ const config = buildConfig({
admin: {
components: {
logout: {
- Button: '/src/components/Logout#MyComponent' // highlight-line
- }
- }
+ Button: '/src/components/Logout#MyComponent', // highlight-line
+ },
+ },
},
})
```
- **Note:**
- All Custom Components can be either Server Components or Client Components, depending on the presence of the `'use client'` directive at the top of the file.
+ **Note:** All Custom Components can be either Server Components or Client
+ Components, depending on the presence of the `'use client'` directive at the
+ top of the file.
### Component Paths
@@ -73,9 +78,9 @@ const config = buildConfig({
},
components: {
logout: {
- Button: '/components/Logout#MyComponent' // highlight-line
- }
- }
+ Button: '/components/Logout#MyComponent', // highlight-line
+ },
+ },
},
})
```
@@ -98,10 +103,10 @@ const config = buildConfig({
Button: {
path: '/src/components/Logout',
exportName: 'MyComponent',
- }
+ },
// highlight-end
- }
- }
+ },
+ },
},
})
```
@@ -109,10 +114,10 @@ const config = buildConfig({
The following options are available:
| Property | Description |
-|---------------|-------------------------------------------------------------------------------------------------------------------------------|
-| `clientProps` | Props to be passed to the Custom Components if it's a Client Component. [More details](#custom-props). |
+| ------------- | ----------------------------------------------------------------------------------------------------------------------------- |
+| `clientProps` | Props to be passed to the Custom Components if it's a Client Component. [More details](#custom-props). |
| `exportName` | Instead of declaring named exports using `#` in the component path, you can also omit them from `path` and pass them in here. |
-| `path` | File path to the Custom Component. Named exports can be appended to the end of the path, separated by a `#`. |
+| `path` | File path to the Custom Component. Named exports can be appended to the end of the path, separated by a `#`. |
| `serverProps` | Props to be passed to the Custom Component if it's a Server Component. [More details](#custom-props). |
For details on how to build Custom Components, see [Building Custom Components](#building-custom-components).
@@ -139,7 +144,12 @@ const config = buildConfig({
admin: {
importMap: {
baseDir: path.resolve(dirname, 'src'),
- importMapFile: path.resolve(dirname, 'app', '(payload)', 'custom-import-map.js'), // highlight-line
+ importMapFile: path.resolve(
+ dirname,
+ 'app',
+ '(payload)',
+ 'custom-import-map.js',
+ ), // highlight-line
},
},
})
@@ -159,7 +169,8 @@ export default buildConfig({
admin: {
// ...
dependencies: {
- myTestComponent: { // myTestComponent is the key - can be anything
+ myTestComponent: {
+ // myTestComponent is the key - can be anything
path: '/components/TestComponent.js#TestComponent',
type: 'component',
clientProps: {
@@ -167,7 +178,7 @@ export default buildConfig({
},
},
},
- }
+ },
})
```
@@ -186,7 +197,7 @@ import React from 'react'
import type { Payload } from 'payload'
async function MyServerComponent({
- payload // highlight-line
+ payload, // highlight-line
}: {
payload: Payload
}) {
@@ -195,22 +206,25 @@ async function MyServerComponent({
id: '123',
})
- return (
- {page.title}
- )
+ return {page.title}
}
```
Each Custom Component receives the following props by default:
-| Prop | Description |
-| ------------------------- | ----------------------------------------------------------------------------------------------------- |
-| `payload` | The [Payload](../local-api/overview) class. |
-| `i18n` | The [i18n](../configuration/i18n) object. |
+| Prop | Description |
+| --------- | ------------------------------------------- |
+| `payload` | The [Payload](../local-api/overview) class. |
+| `i18n` | The [i18n](../configuration/i18n) object. |
- **Reminder:**
- All Custom Components also receive various other props that are specific to the component being rendered. See [Root Components](#root-components), [Collection Components](../configuration/collections#custom-components), [Global Components](../configuration/globals#custom-components), or [Field Components](../fields/overview#custom-components) for a complete list of all default props per component.
+ **Reminder:** All Custom Components also receive various other props that are
+ specific to the component being rendered. See [Root
+ Components](#root-components), [Collection
+ Components](../configuration/collections#custom-components), [Global
+ Components](../configuration/globals#custom-components), or [Field
+ Components](../fields/overview#custom-components) for a complete list of all
+ default props per component.
### Custom Props
@@ -222,17 +236,18 @@ import { buildConfig } from 'payload'
const config = buildConfig({
// ...
- admin: { // highlight-line
+ admin: {
+ // highlight-line
components: {
logout: {
Button: {
path: '/src/components/Logout#MyComponent',
clientProps: {
- myCustomProp: 'Hello, World!' // highlight-line
+ myCustomProp: 'Hello, World!', // highlight-line
},
- }
- }
- }
+ },
+ },
+ },
},
})
```
@@ -244,9 +259,7 @@ import React from 'react'
import { Link } from '@payloadcms/ui'
export function MyComponent({ myCustomProp }: { myCustomProp: string }) {
- return (
- {myCustomProp}
- )
+ return {myCustomProp}
}
```
@@ -264,16 +277,16 @@ export function MyClientComponent() {
const [count, setCount] = useState(0)
return (
- setCount(count + 1)}>
- Clicked {count} times
-
+ setCount(count + 1)}>Clicked {count} times
)
}
```
- **Reminder:**
- Client Components cannot be passed [non-serializable props](https://react.dev/reference/rsc/use-client#serializable-types). If you are rendering your Client Component _from within_ a Server Component, ensure that its props are serializable.
+ **Reminder:** Client Components cannot be passed [non-serializable
+ props](https://react.dev/reference/rsc/use-client#serializable-types). If you
+ are rendering your Client Component _from within_ a Server Component, ensure
+ that its props are serializable.
### Accessing the Payload Config
@@ -285,14 +298,10 @@ import React from 'react'
export default async function MyServerComponent({
payload: {
- config // highlight-line
- }
+ config, // highlight-line
+ },
}) {
- return (
-
- Go Home
-
- )
+ return Go Home
}
```
@@ -307,14 +316,12 @@ import { useConfig } from '@payloadcms/ui'
export function MyClientComponent() {
// highlight-start
- const { config: { serverURL } } = useConfig()
+ const {
+ config: { serverURL },
+ } = useConfig()
// highlight-end
- return (
-
- Go Home
-
- )
+ return Go Home
}
```
@@ -330,12 +337,10 @@ Within Server Components, this prop is named `field`:
import React from 'react'
import type { TextFieldServerComponent } from 'payload'
-export const MyClientFieldComponent: TextFieldServerComponent = ({ field: { name } }) => {
- return (
-
- {`This field's name is ${name}`}
-
- )
+export const MyClientFieldComponent: TextFieldServerComponent = ({
+ field: { name },
+}) => {
+ return {`This field's name is ${name}`}
}
```
@@ -346,12 +351,10 @@ Within Client Components, this prop is named `clientField` because its non-seria
import React from 'react'
import type { TextFieldClientComponent } from 'payload'
-export const MyClientFieldComponent: TextFieldClientComponent = ({ clientField: { name } }) => {
- return (
-
- {`This field's name is ${name}`}
-
- )
+export const MyClientFieldComponent: TextFieldClientComponent = ({
+ clientField: { name },
+}) => {
+ return {`This field's name is ${name}`}
}
```
@@ -370,9 +373,7 @@ import { getTranslation } from '@payloadcms/translations'
export default async function MyServerComponent({ i18n }) {
const translatedTitle = getTranslation(myTranslation, i18n) // highlight-line
- return (
- {translatedTitle}
- )
+ return {translatedTitle}
}
```
@@ -397,7 +398,8 @@ export function MyClientComponent() {
```
- See the [Hooks](../admin/react-hooks) documentation for a full list of available hooks.
+ See the [Hooks](../admin/react-hooks) documentation for a full list of
+ available hooks.
### Getting the Current Locale
@@ -416,9 +418,7 @@ export default async function MyServerComponent({ payload, locale }) {
locale,
})
- return (
- {localizedPage.title}
- )
+ return {localizedPage.title}
}
```
@@ -437,14 +437,13 @@ function Greeting() {
es: 'Hola',
}
- return (
- {trans[locale.code]}
- )
+ return {trans[locale.code]}
}
```
- See the [Hooks](../admin/react-hooks) documentation for a full list of available hooks.
+ See the [Hooks](../admin/react-hooks) documentation for a full list of
+ available hooks.
### Using Hooks
@@ -459,14 +458,13 @@ import { useDocumentInfo } from '@payloadcms/ui'
export function MyClientComponent() {
const { slug } = useDocumentInfo() // highlight-line
- return (
- {`Entity slug: ${slug}`}
- )
+ return {`Entity slug: ${slug}`}
}
```
- See the [Hooks](../admin/react-hooks) documentation for a full list of available hooks.
+ See the [Hooks](../admin/react-hooks) documentation for a full list of
+ available hooks.
### Adding Styles
@@ -479,11 +477,7 @@ To apply custom styles, simply import your own `.css` or `.scss` file into your
import './index.scss'
export function MyComponent() {
- return (
-
- My Custom Component
-
- )
+ return My Custom Component
}
```
@@ -508,6 +502,6 @@ Payload also exports its [SCSS](https://sass-lang.com) library for reuse which i
```
- **Note:**
- You can also drill into Payload's own component styles, or easily apply global, app-wide CSS. More on that [here](../admin/customizing-css).
+ **Note:** You can also drill into Payload's own component styles, or easily
+ apply global, app-wide CSS. More on that [here](../admin/customizing-css).
diff --git a/docs/custom-components/root-components.mdx b/docs/custom-components/root-components.mdx
index f924fa74f0..cb4523b0e3 100644
--- a/docs/custom-components/root-components.mdx
+++ b/docs/custom-components/root-components.mdx
@@ -31,28 +31,30 @@ export default buildConfig({
The following options are available:
-| Path | Description |
-|-----------------------|-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
-| `actions` | An array of Custom Components to be rendered _within_ the header of the Admin Panel, providing additional interactivity and functionality. [More details](#actions). |
-| `afterDashboard` | An array of Custom Components to inject into the built-in Dashboard, _after_ the default dashboard contents. [More details](#afterdashboard). |
-| `afterLogin` | An array of Custom Components to inject into the built-in Login, _after_ the default login form. [More details](#afterlogin). |
-| `afterNavLinks` | An array of Custom Components to inject into the built-in Nav, _after_ the links. [More details](#afternavlinks). |
-| `beforeDashboard` | An array of Custom Components to inject into the built-in Dashboard, _before_ the default dashboard contents. [More details](#beforedashboard). |
-| `beforeLogin` | An array of Custom Components to inject into the built-in Login, _before_ the default login form. [More details](#beforelogin). |
-| `beforeNavLinks` | An array of Custom Components to inject into the built-in Nav, _before_ the links themselves. [More details](#beforenavlinks). |
-| `graphics.Icon` | The simplified logo used in contexts like the the `Nav` component. [More details](#graphicsicon). |
-| `graphics.Logo` | The full logo used in contexts like the `Login` view. [More details](#graphicslogo). |
-| `header` | An array of Custom Components to be injected above the Payload header. [More details](#header). |
-| `logout.Button` | The button displayed in the sidebar that logs the user out. [More details](#logoutbutton). |
-| `Nav` | Contains the sidebar / mobile menu in its entirety. [More details](#nav). |
-| `providers` | Custom [React Context](https://react.dev/learn/scaling-up-with-reducer-and-context) providers that will wrap the entire Admin Panel. [More details](./custom-providers). |
-| `views` | Override or create new views within the Admin Panel. [More details](./custom-views). |
+| Path | Description |
+| ----------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
+| `actions` | An array of Custom Components to be rendered _within_ the header of the Admin Panel, providing additional interactivity and functionality. [More details](#actions). |
+| `afterDashboard` | An array of Custom Components to inject into the built-in Dashboard, _after_ the default dashboard contents. [More details](#afterdashboard). |
+| `afterLogin` | An array of Custom Components to inject into the built-in Login, _after_ the default login form. [More details](#afterlogin). |
+| `afterNavLinks` | An array of Custom Components to inject into the built-in Nav, _after_ the links. [More details](#afternavlinks). |
+| `beforeDashboard` | An array of Custom Components to inject into the built-in Dashboard, _before_ the default dashboard contents. [More details](#beforedashboard). |
+| `beforeLogin` | An array of Custom Components to inject into the built-in Login, _before_ the default login form. [More details](#beforelogin). |
+| `beforeNavLinks` | An array of Custom Components to inject into the built-in Nav, _before_ the links themselves. [More details](#beforenavlinks). |
+| `graphics.Icon` | The simplified logo used in contexts like the the `Nav` component. [More details](#graphicsicon). |
+| `graphics.Logo` | The full logo used in contexts like the `Login` view. [More details](#graphicslogo). |
+| `header` | An array of Custom Components to be injected above the Payload header. [More details](#header). |
+| `logout.Button` | The button displayed in the sidebar that logs the user out. [More details](#logoutbutton). |
+| `Nav` | Contains the sidebar / mobile menu in its entirety. [More details](#nav). |
+| `providers` | Custom [React Context](https://react.dev/learn/scaling-up-with-reducer-and-context) providers that will wrap the entire Admin Panel. [More details](./custom-providers). |
+| `views` | Override or create new views within the Admin Panel. [More details](./custom-views). |
_For details on how to build Custom Components, see [Building Custom Components](./overview#building-custom-components)._
- **Note:**
- You can also use set [Collection Components](../configuration/collections#custom-components) and [Global Components](../configuration/globals#custom-components) in their respective configs.
+ **Note:** You can also use set [Collection
+ Components](../configuration/collections#custom-components) and [Global
+ Components](../configuration/globals#custom-components) in their respective
+ configs.
## Components
@@ -71,9 +73,7 @@ export default buildConfig({
admin: {
// highlight-start
components: {
- actions: [
- '/path/to/your/component',
- ],
+ actions: ['/path/to/your/component'],
},
// highlight-end
},
@@ -93,8 +93,8 @@ export default function MyCustomAction() {
```
- **Note:**
- You can also use add Actions to the [Edit View](./edit-view) and [List View](./list-view) in their respective configs.
+ **Note:** You can also use add Actions to the [Edit View](./edit-view) and
+ [List View](./list-view) in their respective configs.
### beforeDashboard
@@ -111,9 +111,7 @@ export default buildConfig({
admin: {
// highlight-start
components: {
- beforeDashboard: [
- '/path/to/your/component',
- ],
+ beforeDashboard: ['/path/to/your/component'],
},
// highlight-end
},
@@ -124,11 +122,7 @@ Here is an example of a simple `beforeDashboard` component:
```tsx
export default function MyBeforeDashboardComponent() {
- return (
-
- This is a custom component injected before the Dashboard.
-
- )
+ return This is a custom component injected before the Dashboard.
}
```
@@ -146,9 +140,7 @@ export default buildConfig({
admin: {
// highlight-start
components: {
- afterDashboard: [
- '/path/to/your/component',
- ],
+ afterDashboard: ['/path/to/your/component'],
},
// highlight-end
},
@@ -159,11 +151,7 @@ Here is an example of a simple `afterDashboard` component:
```tsx
export default function MyAfterDashboardComponent() {
- return (
-
- This is a custom component injected after the Dashboard.
-
- )
+ return This is a custom component injected after the Dashboard.
}
```
@@ -181,9 +169,7 @@ export default buildConfig({
admin: {
// highlight-start
components: {
- beforeLogin: [
- '/path/to/your/component',
- ],
+ beforeLogin: ['/path/to/your/component'],
},
// highlight-end
},
@@ -194,11 +180,7 @@ Here is an example of a simple `beforeLogin` component:
```tsx
export default function MyBeforeLoginComponent() {
- return (
-
- This is a custom component injected before the Login form.
-
- )
+ return This is a custom component injected before the Login form.
}
```
@@ -216,9 +198,7 @@ export default buildConfig({
admin: {
// highlight-start
components: {
- afterLogin: [
- '/path/to/your/component',
- ],
+ afterLogin: ['/path/to/your/component'],
},
// highlight-end
},
@@ -229,11 +209,7 @@ Here is an example of a simple `afterLogin` component:
```tsx
export default function MyAfterLoginComponent() {
- return (
-
- This is a custom component injected after the Login form.
-
- )
+ return This is a custom component injected after the Login form.
}
```
@@ -251,9 +227,7 @@ export default buildConfig({
admin: {
// highlight-start
components: {
- beforeNavLinks: [
- '/path/to/your/component',
- ],
+ beforeNavLinks: ['/path/to/your/component'],
},
// highlight-end
},
@@ -264,11 +238,7 @@ Here is an example of a simple `beforeNavLinks` component:
```tsx
export default function MyBeforeNavLinksComponent() {
- return (
-
- This is a custom component injected before the Nav links.
-
- )
+ return This is a custom component injected before the Nav links.
}
```
@@ -286,9 +256,7 @@ export default buildConfig({
admin: {
// highlight-start
components: {
- afterNavLinks: [
- '/path/to/your/component',
- ],
+ afterNavLinks: ['/path/to/your/component'],
},
// highlight-end
},
@@ -299,9 +267,7 @@ Here is an example of a simple `afterNavLinks` component:
```tsx
export default function MyAfterNavLinksComponent() {
- return (
- This is a custom component injected after the Nav links.
- )
+ return This is a custom component injected after the Nav links.
}
```
@@ -336,9 +302,7 @@ export default function MyCustomNav() {
-
- Dashboard
-
+ Dashboard
@@ -373,9 +337,7 @@ Here is an example of a simple `Icon` component:
```tsx
export default function MyCustomIcon() {
- return (
-
- )
+ return
}
```
@@ -406,9 +368,7 @@ Here is an example of a simple `Logo` component:
```tsx
export default function MyCustomLogo() {
- return (
-
- )
+ return
}
```
@@ -428,9 +388,7 @@ export default buildConfig({
admin: {
// highlight-start
components: {
- Header: [
- '/path/to/your/component'
- ],
+ Header: ['/path/to/your/component'],
},
// highlight-end
},
@@ -465,7 +423,7 @@ export default buildConfig({
components: {
logout: {
Button: '/path/to/your/component',
- }
+ },
},
// highlight-end
},
@@ -476,10 +434,6 @@ Here is an example of a simple `logout.Button` component:
```tsx
export default function MyCustomLogoutButton() {
- return (
- alert('Logging out!')}>
- Log Out
-
- )
+ return alert('Logging out!')}>Log Out
}
```
diff --git a/docs/database/migrations.mdx b/docs/database/migrations.mdx
index 083fea0c13..40b7852eb9 100644
--- a/docs/database/migrations.mdx
+++ b/docs/database/migrations.mdx
@@ -20,8 +20,9 @@ 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
@@ -62,15 +63,23 @@ transaction gets aborted. This way no change is made to the database if the migr
Additionally, you can bypass Payload's layer entirely and perform operations directly on your underlying database within the active transaction:
### MongoDB:
+
```ts
import { type MigrateUpArgs } from '@payloadcms/db-mongodb'
-export async function up({ session, payload, req }: MigrateUpArgs): Promise {
- const posts = await payload.db.collections.posts.collection.find({ session }).toArray()
+export async function up({
+ session,
+ payload,
+ req,
+}: MigrateUpArgs): Promise {
+ const posts = await payload.db.collections.posts.collection
+ .find({ session })
+ .toArray()
}
```
### Postgres:
+
```ts
import { type MigrateUpArgs, sql } from '@payloadcms/db-postgres'
@@ -80,7 +89,9 @@ export async function up({ db, payload, req }: MigrateUpArgs): Promise {
```
### SQLite:
+
In SQLite, transactions are disabled by default. [More](./transactions).
+
```ts
import { type MigrateUpArgs, sql } from '@payloadcms/db-sqlite'
@@ -119,8 +130,9 @@ npm run payload migrate:create optional-name-here
```
Flags:
-* `--skip-empty`: with Postgres, it skips the "no schema changes detected. Would you like to create a blank migration file?" prompt which can be useful for generating migration in CI.
-* `--force-accept-warning`: accepts any command prompts, creates a blank migration even if there weren't any changes to the schema.
+
+- `--skip-empty`: with Postgres, it skips the "no schema changes detected. Would you like to create a blank migration file?" prompt which can be useful for generating migration in CI.
+- `--force-accept-warning`: accepts any command prompts, creates a blank migration even if there weren't any changes to the schema.
### Status
@@ -200,9 +212,10 @@ The typical workflow in Payload is to build out your Payload configs, install pl
But importantly, you do not need to run migrations against your development database, because Drizzle will have already pushed your changes to your database for you.
- 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.
**2 - create a migration**
@@ -217,7 +230,10 @@ But once you're ready, you can run `pnpm payload migrate:create`, which will per
We won't immediately run this migration for you, however.
- Tip: migrations created by Payload are relatively programmatic in nature, so there should not be any surprises, but before you check in the created migration it's a good idea to always double-check the contents of the migration files.
+ Tip: migrations created by Payload are relatively programmatic in nature, so
+ there should not be any surprises, but before you check in the created
+ migration it's a good idea to always double-check the contents of the
+ migration files.
**3 - set up your build process to run migrations**
@@ -270,13 +286,15 @@ export default buildConfig({
// your config here
db: postgresAdapter({
// your adapter config here
- prodMigrations: migrations
- })
+ prodMigrations: migrations,
+ }),
})
```
Passing your migrations as shown above will tell Payload, in production only, to execute any migrations that need to be run prior to completing the initialization of Payload. This is ideal for long-running services where Payload will only be initialized at startup.
- **Warning:** if Payload is instructed to run migrations in production, this may slow down serverless cold starts on platforms such as Vercel. Generally, this option should only be used for long-running servers / containers.
+ **Warning:** if Payload is instructed to run migrations in production, this
+ may slow down serverless cold starts on platforms such as Vercel. Generally,
+ this option should only be used for long-running servers / containers.
diff --git a/docs/database/mongodb.mdx b/docs/database/mongodb.mdx
index 18172e1aad..bb8e0ecf3d 100644
--- a/docs/database/mongodb.mdx
+++ b/docs/database/mongodb.mdx
@@ -53,9 +53,10 @@ You can access Mongoose models as follows:
- Versions model (both collections and globals) - `payload.db.versions[myEntitySlug]`
## Using other MongoDB implementations
+
Limitations with [DocumentDB](https://aws.amazon.com/documentdb/) and [Azure Cosmos DB](https://azure.microsoft.com/en-us/products/cosmos-db):
-* For Azure Cosmos DB you must pass `transactionOptions: false` to the adapter options. Azure Cosmos DB does not support transactions that update two and more documents in different collections, which is a common case when using Payload (via hooks).
-* For Azure Cosmos DB the root config property `indexSortableFields` must be set to `true`.
-* The [Join Field](../fields/join) is not supported in DocumentDB and Azure Cosmos DB, as we internally use MongoDB aggregations to query data for that field, which are limited there. This can be changed in the future.
-* For DocumentDB pass `disableIndexHints: true` to disable hinting to the DB to use `id` as index which can cause problems with DocumentDB.
\ No newline at end of file
+- For Azure Cosmos DB you must pass `transactionOptions: false` to the adapter options. Azure Cosmos DB does not support transactions that update two and more documents in different collections, which is a common case when using Payload (via hooks).
+- For Azure Cosmos DB the root config property `indexSortableFields` must be set to `true`.
+- The [Join Field](../fields/join) is not supported in DocumentDB and Azure Cosmos DB, as we internally use MongoDB aggregations to query data for that field, which are limited there. This can be changed in the future.
+- For DocumentDB pass `disableIndexHints: true` to disable hinting to the DB to use `id` as index which can cause problems with DocumentDB.
diff --git a/docs/database/overview.mdx b/docs/database/overview.mdx
index efcdfb829f..c808399542 100644
--- a/docs/database/overview.mdx
+++ b/docs/database/overview.mdx
@@ -31,8 +31,10 @@ export default buildConfig({
```
- **Reminder:**
- The Database Adapter is an external dependency and must be installed in your project separately from Payload. You can find the installation instructions for each Database Adapter in their respective documentation.
+ **Reminder:** The Database Adapter is an external dependency and must be
+ installed in your project separately from Payload. You can find the
+ installation instructions for each Database Adapter in their respective
+ documentation.
## Selecting a Database
diff --git a/docs/database/postgres.mdx b/docs/database/postgres.mdx
index 88a7cc5571..bc1b78b335 100644
--- a/docs/database/postgres.mdx
+++ b/docs/database/postgres.mdx
@@ -44,31 +44,38 @@ export default buildConfig({
// Optionally, can accept the same options as the @vercel/postgres package.
db: vercelPostgresAdapter({
pool: {
- connectionString: process.env.DATABASE_URL
+ connectionString: process.env.DATABASE_URL,
},
}),
})
```
- **Note:**
- If you're using `vercelPostgresAdapter` your `process.env.POSTGRES_URL` or `pool.connectionString` points to a local database (e.g hostname has `localhost` or `127.0.0.1`) we use the `pg` module for pooling instead of `@vercel/postgres`. This is because `@vercel/postgres` doesn't work with local databases, if you want to disable that behavior, you can pass `forceUseVercelPostgres: true` to the adapter's args and follow [Vercel guide](https://vercel.com/docs/storage/vercel-postgres/local-development#option-2:-local-postgres-instance-with-docker) for a Docker Neon DB setup.
+ **Note:** If you're using `vercelPostgresAdapter` your
+ `process.env.POSTGRES_URL` or `pool.connectionString` points to a local
+ database (e.g hostname has `localhost` or `127.0.0.1`) we use the `pg` module
+ for pooling instead of `@vercel/postgres`. This is because `@vercel/postgres`
+ doesn't work with local databases, if you want to disable that behavior, you
+ can pass `forceUseVercelPostgres: true` to the adapter's args and follow
+ [Vercel
+ guide](https://vercel.com/docs/storage/vercel-postgres/local-development#option-2:-local-postgres-instance-with-docker)
+ for a Docker Neon DB setup.
## 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` or to `@vercel/postgres` |
+| `pool` \* | [Pool connection options](https://orm.drizzle.team/docs/quick-postgresql/node-postgres) that will be passed to Drizzle and `node-postgres` or to `@vercel/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. |
| `schemaName` (experimental) | A string for the postgres schema to use, defaults to 'public'. |
| `idType` | A string of 'serial', or 'uuid' that is used for the data type given to id columns. |
| `transactionOptions` | A PgTransactionConfig object for transactions, or set to `false` to disable using transactions. [More details](https://orm.drizzle.team/docs/transactions) |
| `disableCreateDatabase` | Pass `true` to disable auto database creation if it doesn't exist. Defaults to `false`. |
-| `localesSuffix` | A string appended to the end of table names for storing localized fields. Default is '_locales'. |
-| `relationshipsSuffix` | A string appended to the end of table names for storing relationships. Default is '_rels'. |
-| `versionsSuffix` | A string appended to the end of table names for storing versions. Defaults to '_v'. |
+| `localesSuffix` | A string appended to the end of table names for storing localized fields. Default is '\_locales'. |
+| `relationshipsSuffix` | A string appended to the end of table names for storing relationships. Default is '\_rels'. |
+| `versionsSuffix` | A string appended to the end of table names for storing versions. Defaults to '\_v'. |
| `beforeSchemaInit` | Drizzle schema hook. Runs before the schema is built. [More Details](#beforeschemainit) |
| `afterSchemaInit` | Drizzle schema hook. Runs after the schema is built. [More Details](#afterschemainit) |
| `generateSchemaOutputFile` | Override generated schema from `payload generate:db-schema` file path. Defaults to `{CWD}/src/payload-generated.schema.ts` |
@@ -78,11 +85,13 @@ export default buildConfig({
After Payload is initialized, this adapter will expose the full power of Drizzle to you for use if you need it.
To ensure type-safety, you need to generate Drizzle schema first with:
+
```sh
npx payload generate:db-schema
```
Then, you can access Drizzle as follows:
+
```ts
import { posts } from './payload-generated-schema'
// To avoid installing Drizzle, you can import everything that drizzle has from our re-export path.
@@ -91,7 +100,12 @@ import { eq, sql, and } from '@payloadcms/db-postgres/drizzle'
// Drizzle's Querying API: https://orm.drizzle.team/docs/rqb
const posts = await payload.db.drizzle.query.posts.findMany()
// Drizzle's Select API https://orm.drizzle.team/docs/select
-const result = await payload.db.drizzle.select().from(posts).where(and(eq(posts.id, 50), sql`lower(${posts.title}) = 'example post title'`))
+const result = await payload.db.drizzle
+ .select()
+ .from(posts)
+ .where(
+ and(eq(posts.id, 50), sql`lower(${posts.title}) = 'example post title'`),
+ )
```
## Tables, relations, and enums
@@ -126,7 +140,11 @@ Runs before the schema is built. You can use this hook to extend your database s
```ts
import { postgresAdapter } from '@payloadcms/db-postgres'
-import { integer, pgTable, serial } from '@payloadcms/db-postgres/drizzle/pg-core'
+import {
+ integer,
+ pgTable,
+ serial,
+} from '@payloadcms/db-postgres/drizzle/pg-core'
postgresAdapter({
beforeSchemaInit: [
@@ -150,7 +168,13 @@ To quickly generate the Drizzle schema from your database you can use [Drizzle I
You should get the `schema.ts` file which may look like this:
```ts
-import { pgTable, uniqueIndex, serial, varchar, text } from 'drizzle-orm/pg-core'
+import {
+ pgTable,
+ uniqueIndex,
+ serial,
+ varchar,
+ text,
+} from 'drizzle-orm/pg-core'
export const users = pgTable('users', {
id: serial('id').primaryKey(),
@@ -170,7 +194,6 @@ export const countries = pgTable(
}
},
)
-
```
You can import them into your config and append to the schema with the `beforeSchemaInit` hook like this:
@@ -187,7 +210,7 @@ postgresAdapter({
tables: {
...schema.tables,
users,
- countries
+ countries,
},
}
},
@@ -197,7 +220,6 @@ postgresAdapter({
Make sure Payload doesn't overlap table names with its collections. For example, if you already have a collection with slug "users", you should either change the slug or `dbName` to change the table name for this collection.
-
### afterSchemaInit
Runs after the Drizzle schema is built. You can use this hook to modify the schema with features that aren't supported by Payload, or if you want to add a column that you don't want to be in the Payload config.
@@ -234,10 +256,9 @@ export default buildConfig({
extraIntegerColumn: integer('extra_integer_column'),
},
extraConfig: (table) => ({
- country_city_composite_index: index('country_city_composite_index').on(
- table.country,
- table.city,
- ),
+ country_city_composite_index: index(
+ 'country_city_composite_index',
+ ).on(table.country, table.city),
}),
})
@@ -246,10 +267,10 @@ export default buildConfig({
],
}),
})
-
```
### Note for generated schema:
+
Columns and tables, added in schema hooks won't be added to the generated via `payload generate:db-schema` Drizzle schema.
If you want them to be there, you either have to edit this file manually or mutate the internal Payload "raw" SQL schema in the `beforeSchemaInit`:
@@ -266,9 +287,9 @@ postgresAdapter({
my_id: {
name: 'my_id',
type: 'serial',
- primaryKey: true
- }
- }
+ primaryKey: true,
+ },
+ },
}
// Add a new column to generated by Payload table:
@@ -276,13 +297,13 @@ postgresAdapter({
name: 'custom_column',
// Note that Payload SQL doesn't support everything that Drizzle does.
type: 'integer',
- notNull: true
+ notNull: true,
}
// Add a new index to generated by Payload table:
adapter.rawTables.posts.indexes.customColumnIdx = {
name: 'custom_column_idx',
unique: true,
- on: ['custom_column']
+ on: ['custom_column'],
}
return schema
diff --git a/docs/database/sqlite.mdx b/docs/database/sqlite.mdx
index 93cd338e37..34f72ab766 100644
--- a/docs/database/sqlite.mdx
+++ b/docs/database/sqlite.mdx
@@ -27,7 +27,7 @@ export default buildConfig({
client: {
url: process.env.DATABASE_URL,
authToken: process.env.DATABASE_AUTH_TOKEN,
- }
+ },
}),
})
```
@@ -36,15 +36,15 @@ export default buildConfig({
| Option | Description |
| -------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
-| `client` * | [Client connection options](https://orm.drizzle.team/docs/get-started-sqlite#turso) that will be passed to `createClient` from `@libsql/client`. |
+| `client` \* | [Client connection options](https://orm.drizzle.team/docs/get-started-sqlite#turso) that will be passed to `createClient` from `@libsql/client`. |
| `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. |
| `logger` | The instance of the logger to be passed to drizzle. By default Payload's will be used. |
| `idType` | A string of 'number', or 'uuid' that is used for the data type given to id columns. |
| `transactionOptions` | A SQLiteTransactionConfig object for transactions, or set to `false` to disable using transactions. [More details](https://orm.drizzle.team/docs/transactions) |
-| `localesSuffix` | A string appended to the end of table names for storing localized fields. Default is '_locales'. |
-| `relationshipsSuffix` | A string appended to the end of table names for storing relationships. Default is '_rels'. |
-| `versionsSuffix` | A string appended to the end of table names for storing versions. Defaults to '_v'. |
+| `localesSuffix` | A string appended to the end of table names for storing localized fields. Default is '\_locales'. |
+| `relationshipsSuffix` | A string appended to the end of table names for storing relationships. Default is '\_rels'. |
+| `versionsSuffix` | A string appended to the end of table names for storing versions. Defaults to '\_v'. |
| `beforeSchemaInit` | Drizzle schema hook. Runs before the schema is built. [More Details](#beforeschemainit) |
| `afterSchemaInit` | Drizzle schema hook. Runs after the schema is built. [More Details](#afterschemainit) |
| `generateSchemaOutputFile` | Override generated schema from `payload generate:db-schema` file path. Defaults to `{CWD}/src/payload-generated.schema.ts` |
@@ -55,11 +55,13 @@ export default buildConfig({
After Payload is initialized, this adapter will expose the full power of Drizzle to you for use if you need it.
To ensure type-safety, you need to generate Drizzle schema first with:
+
```sh
npx payload generate:db-schema
```
Then, you can access Drizzle as follows:
+
```ts
// Import table from the generated file
import { posts } from './payload-generated-schema'
@@ -69,7 +71,12 @@ import { eq, sql, and } from '@payloadcms/db-sqlite/drizzle'
// Drizzle's Querying API: https://orm.drizzle.team/docs/rqb
const posts = await payload.db.drizzle.query.posts.findMany()
// Drizzle's Select API https://orm.drizzle.team/docs/select
-const result = await payload.db.drizzle.select().from(posts).where(and(eq(posts.id, 50), sql`lower(${posts.title}) = 'example post title'`))
+const result = await payload.db.drizzle
+ .select()
+ .from(posts)
+ .where(
+ and(eq(posts.id, 50), sql`lower(${posts.title}) = 'example post title'`),
+ )
```
## Tables and relations
@@ -127,12 +134,17 @@ To quickly generate the Drizzle schema from your database you can use [Drizzle I
You should get the `schema.ts` file which may look like this:
```ts
-import { sqliteTable, text, uniqueIndex, integer } from 'drizzle-orm/sqlite-core'
+import {
+ sqliteTable,
+ text,
+ uniqueIndex,
+ integer,
+} from 'drizzle-orm/sqlite-core'
export const users = sqliteTable('users', {
id: integer('id').primaryKey({ autoIncrement: true }),
fullName: text('full_name'),
- phone: text('phone', {length: 256}),
+ phone: text('phone', { length: 256 }),
})
export const countries = sqliteTable(
@@ -147,7 +159,6 @@ export const countries = sqliteTable(
}
},
)
-
```
You can import them into your config and append to the schema with the `beforeSchemaInit` hook like this:
@@ -164,7 +175,7 @@ sqliteAdapter({
tables: {
...schema.tables,
users,
- countries
+ countries,
},
}
},
@@ -174,7 +185,6 @@ sqliteAdapter({
Make sure Payload doesn't overlap table names with its collections. For example, if you already have a collection with slug "users", you should either change the slug or `dbName` to change the table name for this collection.
-
### afterSchemaInit
Runs after the Drizzle schema is built. You can use this hook to modify the schema with features that aren't supported by Payload, or if you want to add a column that you don't want to be in the Payload config.
@@ -211,10 +221,9 @@ export default buildConfig({
extraIntegerColumn: integer('extra_integer_column'),
},
extraConfig: (table) => ({
- country_city_composite_index: index('country_city_composite_index').on(
- table.country,
- table.city,
- ),
+ country_city_composite_index: index(
+ 'country_city_composite_index',
+ ).on(table.country, table.city),
}),
})
@@ -223,10 +232,10 @@ export default buildConfig({
],
}),
})
-
```
### Note for generated schema:
+
Columns and tables, added in schema hooks won't be added to the generated via `payload generate:db-schema` Drizzle schema.
If you want them to be there, you either have to edit this file manually or mutate the internal Payload "raw" SQL schema in the `beforeSchemaInit`:
@@ -237,15 +246,15 @@ sqliteAdapter({
beforeSchemaInit: [
({ schema, adapter }) => {
// Add a new table
- adapter.rawTables.myTable = {
+ adapter.rawTables.myTable = {
name: 'my_table',
columns: {
my_id: {
name: 'my_id',
type: 'integer',
- primaryKey: true
- }
- }
+ primaryKey: true,
+ },
+ },
}
// Add a new column to generated by Payload table:
@@ -253,13 +262,13 @@ sqliteAdapter({
name: 'custom_column',
// Note that Payload SQL doesn't support everything that Drizzle does.
type: 'integer',
- notNull: true
+ notNull: true,
}
// Add a new index to generated by Payload table:
adapter.rawTables.posts.indexes.customColumnIdx = {
name: 'custom_column_idx',
unique: true,
- on: ['custom_column']
+ on: ['custom_column'],
}
return schema
diff --git a/docs/database/transactions.mdx b/docs/database/transactions.mdx
index 99ed2fdc7d..f6ea77250a 100644
--- a/docs/database/transactions.mdx
+++ b/docs/database/transactions.mdx
@@ -13,13 +13,15 @@ By default, Payload will use transactions for all data changing operations, as l
**Note:**
- MongoDB requires a connection to a replicaset in order to make use of transactions.
+MongoDB requires a connection to a replicaset in order to make use of transactions.
+
**Note:**
- Transactions in SQLite are disabled by default. You need to pass `transactionOptions: {}` to enable them.
+Transactions in SQLite are disabled by default. You need to pass `transactionOptions: {}` to enable them.
+
The initial request made to Payload will begin a new transaction and attach it to the `req.transactionID`. If you have a `hook` that interacts with the database, you can opt in to using the same transaction by passing the `req` in the arguments. For example:
@@ -96,7 +98,7 @@ const standalonePayloadScript = async () => {
some: 'data',
},
where: {
- slug: { equals: 'my-slug' }
+ slug: { equals: 'my-slug' },
},
req: { transactionID },
})
@@ -130,7 +132,7 @@ await payload.update({
some: 'data',
},
where: {
- slug: { equals: 'my-slug' }
+ slug: { equals: 'my-slug' },
},
disableTransaction: true,
})
diff --git a/docs/email/overview.mdx b/docs/email/overview.mdx
index 6ecf46b6d0..5dff8bcf45 100644
--- a/docs/email/overview.mdx
+++ b/docs/email/overview.mdx
@@ -16,7 +16,7 @@ The email adapter should be passed into the `email` property of the Payload Conf
### Default Configuration
-When email is not needed or desired, Payload will log a warning on startup notifying that email is not configured. A warning message will also be logged on any attempt to send an email.
+When email is not needed or desired, Payload will log a warning on startup notifying that email is not configured. A warning message will also be logged on any attempt to send an email.
### Email Adapter
@@ -24,9 +24,8 @@ An email adapter will require at least the following fields:
| Option | Description |
| --------------------------- | -------------------------------------------------------------------------------- |
-| **`defaultFromName`** * | The name part of the From field that will be seen on the delivered email |
-| **`defaultFromAddress`** * | The email address part of the From field that will be used when delivering email |
-
+| **`defaultFromName`** \* | The name part of the From field that will be seen on the delivered email |
+| **`defaultFromAddress`** \* | The email address part of the From field that will be used when delivering email |
### Official Email Adapters
@@ -97,13 +96,11 @@ export default buildConfig({
You also have the ability to bring your own nodemailer transport. This is an example of using the SendGrid nodemailer transport.
-
```ts
import { buildConfig } from 'payload'
import { nodemailerAdapter } from '@payloadcms/email-nodemailer'
import nodemailerSendgrid from 'nodemailer-sendgrid'
-
export default buildConfig({
email: nodemailerAdapter({
defaultFromAddress: 'info@payloadcms.com',
diff --git a/docs/fields/array.mdx b/docs/fields/array.mdx
index 4febd8509d..d85426cbd0 100644
--- a/docs/fields/array.mdx
+++ b/docs/fields/array.mdx
@@ -41,9 +41,9 @@ export const MyArrayField: Field = {
| Option | Description |
| ---------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
-| **`name`** * | To be used as the property name when stored and retrieved from the database. [More](/docs/fields/overview#field-names) |
+| **`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 the heading in the [Admin Panel](../admin/overview) or an object with keys for each language. Auto-generated from name if not defined. |
-| **`fields`** * | Array of field types to correspond to each row of the Array. |
+| **`fields`** \* | Array of field types to correspond to each row of the Array. |
| **`validate`** | Provide a custom validation function that will be executed on both the [Admin Panel](../admin/overview) and the backend. [More](/docs/fields/overview#validation) |
| **`minRows`** | A number for the fewest allowed items during validation when a value is present. |
| **`maxRows`** | A number for the most allowed items during validation when a value is present. |
@@ -62,7 +62,7 @@ export const MyArrayField: Field = {
| **`typescriptSchema`** | Override field type generation with providing a JSON schema |
| **`virtual`** | Provide `true` to disable field in the database. See [Virtual Fields](https://payloadcms.com/blog/learn-how-virtual-fields-can-help-solve-common-cms-challenges) |
-_* An asterisk denotes that a property is required._
+_\* An asterisk denotes that a property is required._
## Admin Options
@@ -73,7 +73,8 @@ import type { Field } from 'payload'
export const MyArrayField: Field = {
// ...
- admin: { // highlight-line
+ admin: {
+ // highlight-line
// ...
},
}
@@ -81,11 +82,11 @@ export const MyArrayField: Field = {
The Array Field inherits all of the default options from the base [Field Admin Config](./overview#admin-options), plus the following additional options:
-| Option | Description |
-| ------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------- |
-| **`initCollapsed`** | Set the initial collapsed state |
-| **`components.RowLabel`** | React component to be rendered as the label on the array row. [Example](#row-label) |
-| **`isSortable`** | Disable order sorting by setting this value to `false` |
+| Option | Description |
+| ------------------------- | ----------------------------------------------------------------------------------- |
+| **`initCollapsed`** | Set the initial collapsed state |
+| **`components.RowLabel`** | React component to be rendered as the label on the array row. [Example](#row-label) |
+| **`isSortable`** | Disable order sorting by setting this value to `false` |
## Example
@@ -145,7 +146,7 @@ export const CustomArrayFieldServer: ArrayFieldServerComponent = ({
clientField,
path,
schemaPath,
- permissions
+ permissions,
}) => {
return (
{
return (
- **Tip:**
- If you customize the way your block is rendered in Lexical, you can import utility components to easily edit / remove your block - so that you don't have to build all of this yourself.
+ **Tip:** If you customize the way your block is rendered in Lexical, you can
+ import utility components to easily edit / remove your block - so that you
+ don't have to build all of this yourself.
To import these utility components for one of your custom blocks, you can import the following:
@@ -127,7 +129,6 @@ import {
// The default "collapsible" UI that is rendered for a regular block
// if you want to re-use it
BlockCollapsible,
-
} from '@payloadcms/richtext-lexical/client'
```
@@ -136,18 +137,18 @@ import {
Blocks are defined as separate configs of their own.
- **Tip:**
- Best practice is to define each block config in its own file, and then import them into your
- Blocks field as necessary. This way each block config can be easily shared between fields. For
- instance, using the "layout builder" example, you might want to feature a few of the same blocks
- in a Post collection as well as a Page collection. Abstracting into their own files trivializes
- their reusability.
+ **Tip:** Best practice is to define each block config in its own file, and
+ then import them into your Blocks field as necessary. This way each block
+ config can be easily shared between fields. For instance, using the "layout
+ builder" example, you might want to feature a few of the same blocks in a Post
+ collection as well as a Page collection. Abstracting into their own files
+ trivializes their reusability.
| Option | Description |
| -------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
-| **`slug`** * | Identifier for this block type. Will be saved on each block as the `blockType` property. |
-| **`fields`** * | Array of fields to be stored in this block. |
+| **`slug`** \* | Identifier for this block type. Will be saved on each block as the `blockType` property. |
+| **`fields`** \* | Array of fields to be stored in this block. |
| **`labels`** | Customize the block labels that appear in the Admin dashboard. Auto-generated from slug if not defined. |
| **`imageURL`** | Provide a custom image thumbnail to help editors identify this block in the Admin UI. |
| **`imageAltText`** | Customize this block's image thumbnail alt text. |
@@ -226,10 +227,11 @@ export const CustomBlocksFieldServer: BlocksFieldServerComponent = ({
clientField,
path,
schemaPath,
- permissions
+ permissions,
}) => {
return (
-
+1. The block config cannot be modified or extended in the collection config. It will be identical everywhere it's referenced.
+2. Access control for blocks referenced in the `blockReferences` are run only once - data from the collection will not be available in the block's access control.
+
## TypeScript
diff --git a/docs/fields/checkbox.mdx b/docs/fields/checkbox.mdx
index 1ecb564a0e..bb256fccae 100644
--- a/docs/fields/checkbox.mdx
+++ b/docs/fields/checkbox.mdx
@@ -30,7 +30,7 @@ export const MyCheckboxField: Field = {
| Option | Description |
| ---------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
-| **`name`** * | To be used as the property name when stored and retrieved from the database. [More](/docs/fields/overview#field-names) |
+| **`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. |
@@ -41,12 +41,12 @@ export const MyCheckboxField: Field = {
| **`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. [More details](./overview#admin-options). |
+| **`admin`** | Admin-specific configuration. [More details](./overview#admin-options). |
| **`custom`** | Extension point for adding custom data (e.g. for plugins) |
| **`typescriptSchema`** | Override field type generation with providing a JSON schema |
| **`virtual`** | Provide `true` to disable field in the database. See [Virtual Fields](https://payloadcms.com/blog/learn-how-virtual-fields-can-help-solve-common-cms-challenges) |
-_* An asterisk denotes that a property is required._
+_\* An asterisk denotes that a property is required._
## Example
@@ -104,7 +104,9 @@ import React from 'react'
import { CheckboxField } from '@payloadcms/ui'
import type { CheckboxFieldClientComponent } from 'payload'
-export const CustomCheckboxFieldClient: CheckboxFieldClientComponent = (props) => {
+export const CustomCheckboxFieldClient: CheckboxFieldClientComponent = (
+ props,
+) => {
return
}
```
@@ -118,18 +120,16 @@ import React from 'react'
import { FieldLabel } from '@payloadcms/ui'
import type { CheckboxFieldLabelServerComponent } from 'payload'
-export const CustomCheckboxFieldLabelServer: CheckboxFieldLabelServerComponent = ({
- clientField,
- path,
-}) => {
- return (
-
- )
-}
+export const CustomCheckboxFieldLabelServer: CheckboxFieldLabelServerComponent =
+ ({ clientField, path }) => {
+ return (
+
+ )
+ }
```
#### Client Component
@@ -140,17 +140,14 @@ import React from 'react'
import { FieldLabel } from '@payloadcms/ui'
import type { CheckboxFieldLabelClientComponent } from 'payload'
-export const CustomCheckboxFieldLabelClient: CheckboxFieldLabelClientComponent = ({
- label,
- path,
- required,
-}) => {
- return (
-
-)
-}
+export const CustomCheckboxFieldLabelClient: CheckboxFieldLabelClientComponent =
+ ({ label, path, required }) => {
+ return (
+
+ )
+ }
```
diff --git a/docs/fields/code.mdx b/docs/fields/code.mdx
index bf20c2fecf..26cc9abb39 100644
--- a/docs/fields/code.mdx
+++ b/docs/fields/code.mdx
@@ -31,7 +31,7 @@ export const MyBlocksField: Field = {
| Option | Description |
| ---------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
-| **`name`** * | To be used as the property name when stored and retrieved from the database. [More](/docs/fields/overview#field-names) |
+| **`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. |
@@ -50,7 +50,7 @@ export const MyBlocksField: Field = {
| **`typescriptSchema`** | Override field type generation with providing a JSON schema |
| **`virtual`** | Provide `true` to disable field in the database. See [Virtual Fields](https://payloadcms.com/blog/learn-how-virtual-fields-can-help-solve-common-cms-challenges) |
-_* An asterisk denotes that a property is required._
+_\* An asterisk denotes that a property is required._
## Admin Options
@@ -61,7 +61,8 @@ import type { Field } from 'payload'
export const MyCodeField: Field = {
// ...
- admin: { // highlight-line
+ admin: {
+ // highlight-line
// ...
},
}
@@ -114,7 +115,12 @@ export const CustomCodeFieldServer: CodeFieldServerComponent = ({
permissions,
}) => {
return (
-
+
)
}
```
@@ -176,4 +182,3 @@ export const CustomCodeFieldLabelClient: CodeFieldLabelClientComponent = ({
)
}
```
-
diff --git a/docs/fields/collapsible.mdx b/docs/fields/collapsible.mdx
index 5e5c009c8e..ad746b0907 100644
--- a/docs/fields/collapsible.mdx
+++ b/docs/fields/collapsible.mdx
@@ -35,12 +35,12 @@ export const MyCollapsibleField: Field = {
| Option | Description |
| --------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
-| **`label`** * | A label to render within the header of the collapsible component. This can be a string, function or react component. Function/components receive `({ data, path })` as args. |
-| **`fields`** * | Array of field types to nest within this Collapsible. |
-| **`admin`** | Admin-specific configuration. [More details](#admin-options). |
+| **`label`** \* | A label to render within the header of the collapsible component. This can be a string, function or react component. Function/components receive `({ data, path })` as args. |
+| **`fields`** \* | Array of field types to nest within this Collapsible. |
+| **`admin`** | Admin-specific configuration. [More details](#admin-options). |
| **`custom`** | Extension point for adding custom data (e.g. for plugins) |
-_* An asterisk denotes that a property is required._
+_\* An asterisk denotes that a property is required._
## Admin Options
@@ -51,7 +51,8 @@ import type { Field } from 'payload'
export const MyCollapsibleField: Field = {
// ...
- admin: { // highlight-line
+ admin: {
+ // highlight-line
// ...
},
}
diff --git a/docs/fields/date.mdx b/docs/fields/date.mdx
index 93bf5d6085..de939f53a3 100644
--- a/docs/fields/date.mdx
+++ b/docs/fields/date.mdx
@@ -30,7 +30,7 @@ export const MyDateField: Field = {
| Option | Description |
| ---------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
-| **`name`** * | To be used as the property name when stored and retrieved from the database. [More](/docs/fields/overview#field-names) |
+| **`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) |
@@ -43,11 +43,11 @@ export const MyDateField: Field = {
| **`required`** | Require this field to have a value. |
| **`admin`** | Admin-specific configuration. [More details](#admin-options). |
| **`custom`** | Extension point for adding custom data (e.g. for plugins) |
-| **`timezone`** * | Set to `true` to enable timezone selection on this field. [More details](#timezones). |
+| **`timezone`** \* | Set to `true` to enable timezone selection on this field. [More details](#timezones). |
| **`typescriptSchema`** | Override field type generation with providing a JSON schema |
| **`virtual`** | Provide `true` to disable field in the database. See [Virtual Fields](https://payloadcms.com/blog/learn-how-virtual-fields-can-help-solve-common-cms-challenges) |
-_* An asterisk denotes that a property is required._
+_\* An asterisk denotes that a property is required._
## Admin Options
@@ -58,7 +58,8 @@ import type { Field } from 'payload'
export const MyDateField: Field = {
// ...
- admin: { // highlight-line
+ admin: {
+ // highlight-line
// ...
},
}
@@ -71,17 +72,17 @@ The Date Field inherits all of the default options from the base [Field Admin Co
| **`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'`. |
+| **`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)._
+_\* This property is passed directly to [react-datepicker](https://github.com/Hacker0x01/react-datepicker/blob/master/docs/datepicker.md)._
### Display Format and Picker Appearance
@@ -243,5 +244,6 @@ You can customise the available list of timezones in the [global admin config](.
**Good to know:**
The date itself will be stored in UTC so it's up to you to handle the conversion to the user's timezone when displaying the date in your frontend.
- Dates without a specific time are normalised to 12:00 in the selected timezone.
+Dates without a specific time are normalised to 12:00 in the selected timezone.
+
diff --git a/docs/fields/email.mdx b/docs/fields/email.mdx
index 5d5f677d7a..befa1019fd 100644
--- a/docs/fields/email.mdx
+++ b/docs/fields/email.mdx
@@ -30,7 +30,7 @@ export const MyEmailField: Field = {
| Option | Description |
| ---------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
-| **`name`** * | To be used as the property name when stored and retrieved from the database. [More](/docs/fields/overview#field-names) |
+| **`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. |
@@ -47,7 +47,7 @@ export const MyEmailField: Field = {
| **`typescriptSchema`** | Override field type generation with providing a JSON schema |
| **`virtual`** | Provide `true` to disable field in the database. See [Virtual Fields](https://payloadcms.com/blog/learn-how-virtual-fields-can-help-solve-common-cms-challenges) |
-_* An asterisk denotes that a property is required._
+_\* An asterisk denotes that a property is required._
## Admin Options
@@ -58,7 +58,8 @@ import type { Field } from 'payload'
export const MyEmailField: Field = {
// ...
- admin: { // highlight-line
+ admin: {
+ // highlight-line
// ...
},
}
@@ -66,10 +67,10 @@ export const MyEmailField: Field = {
The Email Field inherits all of the default options from the base [Field Admin Config](./overview#admin-options), plus the following additional options:
-| Property | Description |
-| ------------------------------ | -------------------------------------------------------------------------------------------------------------------------------------- |
-| **`placeholder`** | Set this property to define a placeholder string for the field. |
-| **`autoComplete`** | Set this property to a string that will be used for browser autocomplete. |
+| Property | Description |
+| ------------------ | ------------------------------------------------------------------------- |
+| **`placeholder`** | Set this property to define a placeholder string for the field. |
+| **`autoComplete`** | Set this property to a string that will be used for browser autocomplete. |
## Example
@@ -109,7 +110,12 @@ export const CustomEmailFieldServer: EmailFieldServerComponent = ({
permissions,
}) => {
return (
-
+
)
}
```
@@ -168,5 +174,6 @@ export const CustomEmailFieldLabelClient: EmailFieldLabelClientComponent = ({
path={path}
required={field?.required}
/>
- )}
+ )
+}
```
diff --git a/docs/fields/group.mdx b/docs/fields/group.mdx
index 28c894b33a..9062dc6f5d 100644
--- a/docs/fields/group.mdx
+++ b/docs/fields/group.mdx
@@ -35,8 +35,8 @@ export const MyGroupField: Field = {
| Option | Description |
| ---------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
-| **`name`** * | To be used as the property name when stored and retrieved from the database. [More](/docs/fields/overview#field-names) |
-| **`fields`** * | Array of field types to nest within this Group. |
+| **`name`** \* | To be used as the property name when stored and retrieved from the database. [More](/docs/fields/overview#field-names) |
+| **`fields`** \* | Array of field types to nest within this Group. |
| **`label`** | Used as a heading in the Admin Panel and to name the generated GraphQL type. |
| **`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/overview), include its data in the user JWT. |
@@ -51,7 +51,7 @@ export const MyGroupField: Field = {
| **`typescriptSchema`** | Override field type generation with providing a JSON schema |
| **`virtual`** | Provide `true` to disable field in the database. See [Virtual Fields](https://payloadcms.com/blog/learn-how-virtual-fields-can-help-solve-common-cms-challenges) |
-_* An asterisk denotes that a property is required._
+_\* An asterisk denotes that a property is required._
## Admin Options
@@ -62,7 +62,8 @@ import type { Field } from 'payload'
export const MyGroupField: Field = {
// ...
- admin: { // highlight-line
+ admin: {
+ // highlight-line
// ...
},
}
@@ -70,9 +71,9 @@ export const MyGroupField: Field = {
The Group Field inherits all of the default options from the base [Field Admin Config](./overview#admin-options), plus the following additional options:
-| Option | Description |
-| ------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
-| **`hideGutter`** | Set this property to `true` to hide this field's gutter within the Admin Panel. The field gutter is rendered as a vertical line and padding, but often if this field is nested within a Group, Block, or Array, you may want to hide the gutter. |
+| Option | Description |
+| ---------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
+| **`hideGutter`** | Set this property to `true` to hide this field's gutter within the Admin Panel. The field gutter is rendered as a vertical line and padding, but often if this field is nested within a Group, Block, or Array, you may want to hide the gutter. |
## Example
diff --git a/docs/fields/join.mdx b/docs/fields/join.mdx
index 6c006a03e0..64ff7ea169 100644
--- a/docs/fields/join.mdx
+++ b/docs/fields/join.mdx
@@ -21,10 +21,10 @@ The Join field is useful in scenarios including:
- Displaying where a document or upload is used in other documents
For the Join field to work, you must have an existing [relationship](./relationship) or [upload](./upload) field in the
@@ -59,11 +59,18 @@ are related to the Category are populated for you. This is extremely powerful an
of relationship types in an easy manner.
- The Join field is extremely performant and does not add additional query overhead to your API responses until you add depth of 1 or above. It works in all database adapters. In MongoDB, we use **aggregations** to automatically join in related documents, and in relational databases, we use joins.
+ The Join field is extremely performant and does not add additional query
+ overhead to your API responses until you add depth of 1 or above. It works in
+ all database adapters. In MongoDB, we use **aggregations** to automatically
+ join in related documents, and in relational databases, we use joins.
- The Join Field is not supported in [DocumentDB](https://aws.amazon.com/documentdb/) and [Azure Cosmos DB](https://azure.microsoft.com/en-us/products/cosmos-db), as we internally use MongoDB aggregations to query data for that field, which are limited there. This can be changed in the future.
+ The Join Field is not supported in
+ [DocumentDB](https://aws.amazon.com/documentdb/) and [Azure Cosmos
+ DB](https://azure.microsoft.com/en-us/products/cosmos-db), as we internally
+ use MongoDB aggregations to query data for that field, which are limited
+ there. This can be changed in the future.
### Schema advice
@@ -99,7 +106,8 @@ architecture. You might not want to have that `_rels` table, and would prefer to
table design.
- With the Join field, you can control your own junction table design, and avoid Payload's automatic _rels table creation.
+ With the Join field, you can control your own junction table design, and avoid
+ Payload's automatic _rels table creation.
The `join` field can be used in conjunction with _any_ collection - and if you wanted to define your own "junction"
@@ -127,9 +135,9 @@ powerful Admin UI.
| Option | Description |
| ---------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
-| **`name`** * | To be used as the property name when retrieved from the database. [More](./overview#field-names) |
-| **`collection`** * | The `slug`s having the relationship field or an array of collection slugs. |
-| **`on`** * | The name of the relationship or upload field that relates to the collection document. Use dot notation for nested paths, like 'myGroup.relationName'. If `collection` is an array, this field must exist for all specified collections |
+| **`name`** \* | To be used as the property name when retrieved from the database. [More](./overview#field-names) |
+| **`collection`** \* | The `slug`s having the relationship field or an array of collection slugs. |
+| **`on`** \* | The name of the relationship or upload field that relates to the collection document. Use dot notation for nested paths, like 'myGroup.relationName'. If `collection` is an array, this field must exist for all specified collections |
| **`where`** | A `Where` query to hide related documents from appearing. Will be merged with any `where` specified in the request. |
| **`maxDepth`** | Default is 1, Sets a maximum population depth for this field, regardless of the remaining depth when this field is reached. [Max Depth](../queries/depth#max-depth). |
| **`label`** | Text used as a field label in the Admin Panel or an object with keys for each language. |
@@ -142,18 +150,17 @@ powerful Admin UI.
| **`typescriptSchema`** | Override field type generation with providing a JSON schema. |
| **`graphQL`** | Custom graphQL configuration for the field. [More details](/docs/graphql/overview#field-complexity) |
-_* An asterisk denotes that a property is required._
-
+_\* An asterisk denotes that a property is required._
## Admin Config Options
You can control the user experience of the join field using the `admin` config properties. The following options are supported:
-| Option | Description |
-|------------------------|---------------------------------------------------------------------------------------------------------------------------|
+| Option | Description |
+| ---------------------- | -------------------------------------------------------------------------------------------------------------------------- |
| **`defaultColumns`** | Array of field names that correspond to which columns to show in the relationship table. Default is the collection config. |
-| **`allowCreate`** | Set to `false` to remove the controls for making new related documents from this field. |
-| **`components.Label`** | Override the default Label of the Field Component. [More details](./overview#label) |
+| **`allowCreate`** | Set to `false` to remove the controls for making new related documents from this field. |
+| **`components.Label`** | Override the default Label of the Field Component. [More details](./overview#label) |
## Join Field Data
@@ -177,7 +184,7 @@ object with:
// { ... }
],
"hasNextPage": false,
- "totalDocs": 10, // if count: true is passed
+ "totalDocs": 10 // if count: true is passed
}
// other fields...
}
@@ -201,14 +208,14 @@ object with:
"relationTo": "posts",
"value": {
"id": "66e3431a3f23e684075aaeb9",
- // other fields...
+ // other fields...
"category": "66e3431a3f23e684075aae9c"
}
}
// { ... }
],
"hasNextPage": false,
- "totalDocs": 10, // if count: true is passed
+ "totalDocs": 10 // if count: true is passed
}
// other fields...
}
@@ -240,25 +247,27 @@ const result = await payload.find({
collection: 'categories',
where: {
title: {
- equals: 'My Category'
- }
+ equals: 'My Category',
+ },
},
joins: {
relatedPosts: {
limit: 5,
where: {
title: {
- equals: 'My Post'
- }
+ equals: 'My Post',
+ },
},
- sort: 'title'
- }
- }
+ sort: 'title',
+ },
+ },
})
```
- Currently, `Where` query support on joined documents for join fields with an array of `collection` is limited and not supported for fields inside arrays and blocks.
+ Currently, `Where` query support on joined documents for join fields with an
+ array of `collection` is limited and not supported for fields inside arrays
+ and blocks.
@@ -300,11 +309,7 @@ query {
relatedPosts(
sort: "createdAt"
limit: 5
- where: {
- author: {
- equals: "66e3431a3f23e684075aaeb9"
- }
- }
+ where: { author: { equals: "66e3431a3f23e684075aaeb9" } }
) {
docs {
title
diff --git a/docs/fields/json.mdx b/docs/fields/json.mdx
index f8633b7d91..23d443ea37 100644
--- a/docs/fields/json.mdx
+++ b/docs/fields/json.mdx
@@ -31,7 +31,7 @@ export const MyJSONField: Field = {
| Option | Description |
| ---------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
-| **`name`** * | To be used as the property name when stored and retrieved from the database. [More](/docs/fields/overview#field-names) |
+| **`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. |
@@ -49,7 +49,7 @@ export const MyJSONField: Field = {
| **`typescriptSchema`** | Override field type generation with providing a JSON schema |
| **`virtual`** | Provide `true` to disable field in the database. See [Virtual Fields](https://payloadcms.com/blog/learn-how-virtual-fields-can-help-solve-common-cms-challenges) |
-_* An asterisk denotes that a property is required._
+_\* An asterisk denotes that a property is required._
## Admin Options
@@ -60,7 +60,8 @@ import type { Field } from 'payload'
export const MyJSONField: Field = {
// ...
- admin: { // highlight-line
+ admin: {
+ // highlight-line
// ...
},
}
@@ -90,13 +91,13 @@ export const ExampleCollection: CollectionConfig = {
],
}
```
+
## JSON Schema Validation
Payload JSON fields fully support the [JSON schema](https://json-schema.org/) standard. By providing a schema in your field config, the editor will be guided in the admin UI, getting typeahead for properties and their formats automatically. When the document is saved, the default validation will prevent saving any invalid data in the field according to the schema in your config.
If you only provide a URL to a schema, Payload will fetch the desired schema if it is publicly available. If not, it is recommended to add the schema directly to your config or import it from another file so that it can be implemented consistently in your project.
-
### Local JSON Schema
`collections/ExampleCollection.ts`
@@ -118,11 +119,10 @@ export const ExampleCollection: CollectionConfig = {
properties: {
foo: {
enum: ['bar', 'foobar'],
- }
+ },
},
},
},
-
},
],
}
diff --git a/docs/fields/number.mdx b/docs/fields/number.mdx
index f73e3803e9..49cb8bf632 100644
--- a/docs/fields/number.mdx
+++ b/docs/fields/number.mdx
@@ -30,7 +30,7 @@ export const MyNumberField: Field = {
| Option | Description |
| ---------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
-| **`name`** * | To be used as the property name when stored and retrieved from the database. [More](/docs/fields/overview#field-names) |
+| **`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. |
@@ -52,7 +52,7 @@ export const MyNumberField: Field = {
| **`typescriptSchema`** | Override field type generation with providing a JSON schema |
| **`virtual`** | Provide `true` to disable field in the database. See [Virtual Fields](https://payloadcms.com/blog/learn-how-virtual-fields-can-help-solve-common-cms-challenges) |
-_* An asterisk denotes that a property is required._
+_\* An asterisk denotes that a property is required._
## Admin Options
@@ -63,7 +63,8 @@ import type { Field } from 'payload'
export const MyNumberField: Field = {
// ...
- admin: { // highlight-line
+ admin: {
+ // highlight-line
// ...
},
}
@@ -71,11 +72,11 @@ export const MyNumberField: Field = {
The Number Field inherits all of the default options from the base [Field Admin Config](./overview#admin-options), plus the following additional options:
-| Property | Description |
-| ------------------------------ | -------------------------------------------------------------------------------------------------------------------------------------- |
-| **`step`** | Set a value for the number field to increment / decrement using browser controls. |
-| **`placeholder`** | Set this property to define a placeholder string for the field. |
-| **`autoComplete`** | Set this property to a string that will be used for browser autocomplete. |
+| Property | Description |
+| ------------------ | --------------------------------------------------------------------------------- |
+| **`step`** | Set a value for the number field to increment / decrement using browser controls. |
+| **`placeholder`** | Set this property to define a placeholder string for the field. |
+| **`autoComplete`** | Set this property to a string that will be used for browser autocomplete. |
## Example
diff --git a/docs/fields/overview.mdx b/docs/fields/overview.mdx
index 2552819670..5b8b0bf463 100644
--- a/docs/fields/overview.mdx
+++ b/docs/fields/overview.mdx
@@ -19,9 +19,10 @@ import type { CollectionConfig } from 'payload'
export const Page: CollectionConfig = {
// ...
- fields: [ // highlight-line
+ fields: [
+ // highlight-line
// ...
- ]
+ ],
}
```
@@ -41,14 +42,16 @@ export const Page: CollectionConfig = {
{
name: 'field',
type: 'text',
- }
- ]
+ },
+ ],
// highlight-end
}
```
- **Reminder:** Each field is an object with at least the `type` property. This matches the field to its corresponding Field Type. [More details](#field-options).
+ **Reminder:** Each field is an object with at least the `type` property. This
+ matches the field to its corresponding Field Type. [More
+ details](#field-options).
There are three main categories of fields in Payload:
@@ -104,7 +107,11 @@ Here are the available Virtual Fields:
- [Join](../fields/join) - achieves two-way data binding between fields
- **Tip:** Don't see a built-in field type that you need? Build it! Using a combination of [Field Validations](#validation) and [Custom Components](../custom-components/overview), you can override the entirety of how a component functions within the [Admin Panel](../admin/overview) to effectively create your own field type.
+ **Tip:** Don't see a built-in field type that you need? Build it! Using a
+ combination of [Field Validations](#validation) and [Custom
+ Components](../custom-components/overview), you can override the entirety of
+ how a component functions within the [Admin Panel](../admin/overview) to
+ effectively create your own field type.
## Field Options
@@ -123,7 +130,8 @@ export const MyField: Field = {
```
- For a full list of configuration options, see the documentation for each [Field Type](#field-types).
+ For a full list of configuration options, see the documentation for each
+ [Field Type](#field-types).
### Field Names
@@ -165,7 +173,7 @@ export const MyField: Field = {
// highlight-start
hooks: {
// ...
- }
+ },
// highlight-end
}
```
@@ -187,7 +195,7 @@ export const MyField: Field = {
// highlight-start
access: {
// ...
- }
+ },
// highlight-end
}
```
@@ -239,7 +247,8 @@ export const myField: Field = {
```
- **Tip:** You can use async `defaultValue` functions to fill fields with data from API requests or Local API using `req.payload`.
+ **Tip:** You can use async `defaultValue` functions to fill fields with data
+ from API requests or Local API using `req.payload`.
### Validation
@@ -254,7 +263,7 @@ import type { Field } from 'payload'
export const MyField: Field = {
type: 'text',
name: 'myField',
- validate: value => Boolean(value) || 'This field is required' // highlight-line
+ validate: (value) => Boolean(value) || 'This field is required', // highlight-line
}
```
@@ -262,10 +271,10 @@ Custom validation functions should return either `true` or a `string` representi
The following arguments are provided to the `validate` function:
-| Argument | Description |
-| --- | --- |
-| `value` | The value of the field being validated. |
-| `ctx` | An object with additional data and context. [More details](#validation-context) |
+| Argument | Description |
+| -------- | ------------------------------------------------------------------------------- |
+| `value` | The value of the field being validated. |
+| `ctx` | An object with additional data and context. [More details](#validation-context) |
#### Validation Context
@@ -286,15 +295,15 @@ export const MyField: Field = {
The following additional properties are provided in the `ctx` object:
-| Property | Description |
-| --- | --- |
-| `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. |
-| `operation` | Will be `create` or `update` depending on the UI action or API call. |
-| `path` | The full path to the field in the schema, represented as an array of string segments, including array indexes. I.e `['group', 'myArray', '1', 'textField']`. |
-| `id` | The `id` of the current document being edited. `id` is `undefined` during the `create` operation. |
-| `req` | The current HTTP request object. Contains `payload`, `user`, etc. |
-| `event` | Either `onChange` or `submit` depending on the current action. Used as a performance opt-in. [More details](#async-field-validations). |
+| Property | Description |
+| ------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------ |
+| `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. |
+| `operation` | Will be `create` or `update` depending on the UI action or API call. |
+| `path` | The full path to the field in the schema, represented as an array of string segments, including array indexes. I.e `['group', 'myArray', '1', 'textField']`. |
+| `id` | The `id` of the current document being edited. `id` is `undefined` during the `create` operation. |
+| `req` | The current HTTP request object. Contains `payload`, `user`, etc. |
+| `event` | Either `onChange` or `submit` depending on the current action. Used as a performance opt-in. [More details](#async-field-validations). |
#### Reusing Default Field Validations
@@ -400,7 +409,9 @@ export const MyCollection: CollectionConfig = {
```
- **Reminder:** The Custom ID Fields can only be of type [`Number`](./number) or [`Text`](./text). Custom ID fields with type `text` must not contain `/` or `.` characters.
+ **Reminder:** The Custom ID Fields can only be of type [`Number`](./number) or
+ [`Text`](./text). Custom ID fields with type `text` must not contain `/` or
+ `.` characters.
## Admin Options
@@ -417,31 +428,32 @@ export const CollectionConfig: CollectionConfig = {
{
name: 'myField',
type: 'text',
- admin: { // highlight-line
+ admin: {
+ // highlight-line
// ...
},
- }
- ]
+ },
+ ],
}
```
The following options are available:
-| Option | Description |
-| --- | --- |
-| **`condition`** | Programmatically show / hide fields based on other fields. [More details](#conditional-logic). |
-| **`components`** | All Field Components can be swapped out for [Custom Components](../custom-components/overview) that you define. |
-| **`description`** | Helper text to display alongside the field to provide more information for the editor. [More details](#description). |
-| **`position`** | Specify if the field should be rendered in the sidebar by defining `position: 'sidebar'`. |
-| **`width`** | Restrict the width of a field. You can pass any string-based value here, be it pixels, percentages, etc. This property is especially useful when fields are nested within a `Row` type where they can be organized horizontally. |
-| **`style`** | [CSS Properties](https://developer.mozilla.org/en-US/docs/Web/CSS) to inject into the root element of the field. |
-| **`className`** | Attach a [CSS class attribute](https://developer.mozilla.org/en-US/docs/Web/CSS/Class_selectors) to the root DOM element of a field. |
-| **`readOnly`** | Setting a field to `readOnly` has no effect on the API whatsoever but disables the admin component's editability to prevent editors from modifying the field's value. |
-| **`disabled`** | If a field is `disabled`, it is completely omitted from the [Admin Panel](../admin/overview) entirely. |
-| **`disableBulkEdit`** | Set `disableBulkEdit` to `true` to prevent fields from appearing in the select options when making edits for multiple documents. Defaults to `true` for UI fields. |
-| **`disableListColumn`** | Set `disableListColumn` to `true` to prevent fields from appearing in the list view column selector. |
-| **`disableListFilter`** | Set `disableListFilter` to `true` to prevent fields from appearing in the list view filter options. |
-| **`hidden`** | Will transform the field into a `hidden` input type. Its value will still submit with requests in the Admin Panel, but the field itself will not be visible to editors. |
+| Option | Description |
+| ----------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
+| **`condition`** | Programmatically show / hide fields based on other fields. [More details](#conditional-logic). |
+| **`components`** | All Field Components can be swapped out for [Custom Components](../custom-components/overview) that you define. |
+| **`description`** | Helper text to display alongside the field to provide more information for the editor. [More details](#description). |
+| **`position`** | Specify if the field should be rendered in the sidebar by defining `position: 'sidebar'`. |
+| **`width`** | Restrict the width of a field. You can pass any string-based value here, be it pixels, percentages, etc. This property is especially useful when fields are nested within a `Row` type where they can be organized horizontally. |
+| **`style`** | [CSS Properties](https://developer.mozilla.org/en-US/docs/Web/CSS) to inject into the root element of the field. |
+| **`className`** | Attach a [CSS class attribute](https://developer.mozilla.org/en-US/docs/Web/CSS/Class_selectors) to the root DOM element of a field. |
+| **`readOnly`** | Setting a field to `readOnly` has no effect on the API whatsoever but disables the admin component's editability to prevent editors from modifying the field's value. |
+| **`disabled`** | If a field is `disabled`, it is completely omitted from the [Admin Panel](../admin/overview) entirely. |
+| **`disableBulkEdit`** | Set `disableBulkEdit` to `true` to prevent fields from appearing in the select options when making edits for multiple documents. Defaults to `true` for UI fields. |
+| **`disableListColumn`** | Set `disableListColumn` to `true` to prevent fields from appearing in the list view column selector. |
+| **`disableListFilter`** | Set `disableListFilter` to `true` to prevent fields from appearing in the list view filter options. |
+| **`hidden`** | Will transform the field into a `hidden` input type. Its value will still submit with requests in the Admin Panel, but the field itself will not be visible to editors. |
### Field Descriptions
@@ -466,22 +478,24 @@ export const MyCollectionConfig: CollectionConfig = {
name: 'myField',
type: 'text',
admin: {
- description: 'Hello, world!' // highlight-line
+ description: 'Hello, world!', // highlight-line
},
},
- ]
+ ],
}
```
- **Reminder:** To replace the Field Description with a [Custom Component](../custom-components/overview), use the `admin.components.Description` property. [More details](#description).
+ **Reminder:** To replace the Field Description with a [Custom
+ Component](../custom-components/overview), use the
+ `admin.components.Description` property. [More details](#description).
#### Description Functions
Custom Descriptions can also be defined as a function. Description Functions are executed on the server and can be used to format simple descriptions based on the user's current [Locale](../configuration/localization).
-To add a Description Function to a field, set the `admin.description` property to a *function* in your Field Config:
+To add a Description Function to a field, set the `admin.description` property to a _function_ in your Field Config:
```ts
import type { CollectionConfig } from 'payload'
@@ -494,40 +508,41 @@ export const MyCollectionConfig: CollectionConfig = {
name: 'myField',
type: 'text',
admin: {
- description: ({ t }) => `${t('Hello, world!')}` // highlight-line
+ description: ({ t }) => `${t('Hello, world!')}`, // highlight-line
},
},
- ]
+ ],
}
```
All Description Functions receive the following arguments:
-| Argument | Description |
-| --- | --- |
-| **`t`** | The `t` function used to internationalize the Admin Panel. [More details](../configuration/i18n) |
+| Argument | Description |
+| -------- | ------------------------------------------------------------------------------------------------ |
+| **`t`** | The `t` function used to internationalize the Admin Panel. [More details](../configuration/i18n) |
- **Note:** If you need to subscribe to live updates within your form, use a Description Component instead. [More details](#description).
+ **Note:** If you need to subscribe to live updates within your form, use a
+ Description Component instead. [More details](#description).
### Conditional Logic
You can show and hide fields based on what other fields are doing by utilizing conditional logic on a field by field basis. The `condition` property on a field's admin config accepts a function which takes the following arguments:
-| Argument | Description |
-| --- | --- |
-| **`data`** | The entire document's data that is currently being edited. |
-| **`siblingData`** | Only the fields that are direct siblings to the field with the condition. |
-| **`ctx`** | An object containing additional information about the field’s location and user. |
+| Argument | Description |
+| ----------------- | -------------------------------------------------------------------------------- |
+| **`data`** | The entire document's data that is currently being edited. |
+| **`siblingData`** | Only the fields that are direct siblings to the field with the condition. |
+| **`ctx`** | An object containing additional information about the field’s location and user. |
The `ctx` object:
-| Property | Description |
-| --- | --- |
-| **`blockData`** | The nearest parent block's data. If the field is not inside a block, this will be `undefined`. |
-| **`path`** | The full path to the field in the schema, represented as an array of string segments, including array indexes. I.e `['group', 'myArray', '1', 'textField']`. |
-| **`user`** | The currently authenticated user object. |
+| Property | Description |
+| --------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------ |
+| **`blockData`** | The nearest parent block's data. If the field is not inside a block, this will be `undefined`. |
+| **`path`** | The full path to the field in the schema, represented as an array of string segments, including array indexes. I.e `['group', 'myArray', '1', 'textField']`. |
+| **`user`** | The currently authenticated user object. |
The `condition` function should return a boolean that will control if the field should be displayed or not.
@@ -581,28 +596,29 @@ export const CollectionConfig: CollectionConfig = {
{
// ...
admin: {
- components: { // highlight-line
+ components: {
+ // highlight-line
// ...
},
},
- }
- ]
+ },
+ ],
}
```
The following options are available:
-| Component | Description |
-| --- | --- |
-| **`Field`** | The form field rendered of the Edit View. [More details](#field). |
-| **`Cell`** | The table cell rendered of the List View. [More details](#cell). |
-| **`Filter`** | The filter component rendered in the List View. [More details](#filter). |
-| **`Label`** | Override the default Label of the Field Component. [More details](#label). |
-| **`Error`** | Override the default Error of the Field Component. [More details](#error). |
-| **`Diff`** | Override the default Diff component rendered in the Version Diff View. [More details](#diff). |
-| **`Description`** | Override the default Description of the Field Component. [More details](#description). |
-| **`beforeInput`** | An array of elements that will be added before the input of the Field Component. [More details](#afterinput-and-beforeinput). |
-| **`afterInput`** | An array of elements that will be added after the input of the Field Component. [More details](#afterinput-and-beforeinput). |
+| Component | Description |
+| ----------------- | ----------------------------------------------------------------------------------------------------------------------------- |
+| **`Field`** | The form field rendered of the Edit View. [More details](#field). |
+| **`Cell`** | The table cell rendered of the List View. [More details](#cell). |
+| **`Filter`** | The filter component rendered in the List View. [More details](#filter). |
+| **`Label`** | Override the default Label of the Field Component. [More details](#label). |
+| **`Error`** | Override the default Error of the Field Component. [More details](#error). |
+| **`Diff`** | Override the default Diff component rendered in the Version Diff View. [More details](#diff). |
+| **`Description`** | Override the default Description of the Field Component. [More details](#description). |
+| **`beforeInput`** | An array of elements that will be added before the input of the Field Component. [More details](#afterinput-and-beforeinput). |
+| **`afterInput`** | An array of elements that will be added after the input of the Field Component. [More details](#afterinput-and-beforeinput). |
#### Field
@@ -624,46 +640,49 @@ export const CollectionConfig: CollectionConfig = {
Field: '/path/to/MyFieldComponent', // highlight-line
},
},
- }
- ]
+ },
+ ],
}
```
-*For details on how to build Custom Components, see [Building Custom Components](../custom-components/overview#building-custom-components).*
+_For details on how to build Custom Components, see [Building Custom Components](../custom-components/overview#building-custom-components)._
- Instead of replacing the entire Field Component, you can alternately replace or slot-in only specific parts by using the [`Label`](#label), [`Error`](#error), [`beforeInput`](#afterinput-and-beforinput), and [`afterInput`](#afterinput-and-beforinput) properties.
+ Instead of replacing the entire Field Component, you can alternately replace
+ or slot-in only specific parts by using the [`Label`](#label),
+ [`Error`](#error), [`beforeInput`](#afterinput-and-beforinput), and
+ [`afterInput`](#afterinput-and-beforinput) properties.
##### Default Props
All Field Components receive the following props by default:
-| Property | Description |
-| --- | --- |
-| **`docPreferences`** | An object that contains the [Preferences](../admin/preferences) for the document. |
-| **`field`** | In Client Components, this is the sanitized Client Field Config. In Server Components, this is the original Field Config. Server Components will also receive the sanitized field config through the`clientField` prop (see below). |
-| **`locale`** | The locale of the field. [More details](../configuration/localization). |
-| **`readOnly`** | A boolean value that represents if the field is read-only or not. |
-| **`user`** | The currently authenticated user. [More details](../authentication/overview). |
-| **`validate`** | A function that can be used to validate the field. |
-| **`path`** | A string representing the direct, dynamic path to the field at runtime, i.e. `myGroup.myArray.0.myField`. |
-| **`schemaPath`** | A string representing the direct, static path to the Field Config, i.e. `posts.myGroup.myArray.myField`. |
-| **`indexPath`** | A hyphen-notated string representing the path to the field *within the nearest named ancestor field*, i.e. `0-0` |
+| Property | Description |
+| -------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
+| **`docPreferences`** | An object that contains the [Preferences](../admin/preferences) for the document. |
+| **`field`** | In Client Components, this is the sanitized Client Field Config. In Server Components, this is the original Field Config. Server Components will also receive the sanitized field config through the`clientField` prop (see below). |
+| **`locale`** | The locale of the field. [More details](../configuration/localization). |
+| **`readOnly`** | A boolean value that represents if the field is read-only or not. |
+| **`user`** | The currently authenticated user. [More details](../authentication/overview). |
+| **`validate`** | A function that can be used to validate the field. |
+| **`path`** | A string representing the direct, dynamic path to the field at runtime, i.e. `myGroup.myArray.0.myField`. |
+| **`schemaPath`** | A string representing the direct, static path to the Field Config, i.e. `posts.myGroup.myArray.myField`. |
+| **`indexPath`** | A hyphen-notated string representing the path to the field _within the nearest named ancestor field_, i.e. `0-0` |
In addition to the above props, all Server Components will also receive the following props:
-| Property | Description |
-| --- | --- |
-| **`clientField`** | The serializable Client Field Config. |
-| **`field`** | The Field Config. |
-| **`data`** | The current document being edited. |
-| **`i18n`** | The [i18n](../configuration/i18n) object. |
-| **`payload`** | The [Payload](../local-api/overview) class. |
-| **`permissions`** | The field permissions based on the currently authenticated user. |
-| **`siblingData`** | The data of the field's siblings. |
-| **`user`** | The currently authenticated user. [More details](../authentication/overview). |
-| **`value`** | The value of the field at render-time. |
+| Property | Description |
+| ----------------- | ----------------------------------------------------------------------------- |
+| **`clientField`** | The serializable Client Field Config. |
+| **`field`** | The Field Config. |
+| **`data`** | The current document being edited. |
+| **`i18n`** | The [i18n](../configuration/i18n) object. |
+| **`payload`** | The [Payload](../local-api/overview) class. |
+| **`permissions`** | The field permissions based on the currently authenticated user. |
+| **`siblingData`** | The data of the field's siblings. |
+| **`user`** | The currently authenticated user. [More details](../authentication/overview). |
+| **`value`** | The value of the field at render-time. |
##### Sending and receiving values from the form
@@ -678,17 +697,14 @@ import { useField } from '@payloadcms/ui'
export const CustomTextField: React.FC = () => {
const { value, setValue } = useField() // highlight-line
- return (
- setValue(e.target.value)}
- value={value}
- />
- )
+ return setValue(e.target.value)} value={value} />
}
```
- For a complete list of all available React hooks, see the [Payload React Hooks](../admin/react-hooks) documentation. For additional help, see [Building Custom Components](../custom-components/overview#building-custom-components).
+ For a complete list of all available React hooks, see the [Payload React
+ Hooks](../admin/react-hooks) documentation. For additional help, see [Building
+ Custom Components](../custom-components/overview#building-custom-components).
##### TypeScript#field-component-types
@@ -729,10 +745,10 @@ export const myField: Field = {
All Cell Components receive the same [Default Field Component Props](#field), plus the following:
-| Property | Description |
-| --- | --- |
-| **`link`** | A boolean representing whether this cell should be wrapped in a link. |
-| **`onClick`** | A function that is called when the cell is clicked. |
+| Property | Description |
+| ------------- | --------------------------------------------------------------------- |
+| **`link`** | A boolean representing whether this cell should be wrapped in a link. |
+| **`onClick`** | A function that is called when the cell is clicked. |
For details on how to build Custom Components themselves, see [Building Custom Components](../custom-components/overview#building-custom-components).
@@ -815,10 +831,10 @@ export const MyCollectionConfig: CollectionConfig = {
admin: {
components: {
Description: '/path/to/MyCustomDescriptionComponent', // highlight-line
- }
- }
- }
- ]
+ },
+ },
+ },
+ ],
}
```
@@ -912,7 +928,7 @@ import type {
#### afterInput and beforeInput
-With these properties you can add multiple components *before* and *after* the input element, as their name suggests. This is useful when you need to render additional elements alongside the field without replacing the entire field component.
+With these properties you can add multiple components _before_ and _after_ the input element, as their name suggests. This is useful when you need to render additional elements alongside the field without replacing the entire field component.
To add components before and after the input element, use the `admin.components.beforeInput` and `admin.components.afterInput` properties in your Field Config:
@@ -932,10 +948,10 @@ export const MyCollectionConfig: CollectionConfig = {
beforeInput: ['/path/to/MyCustomComponent'],
afterInput: ['/path/to/MyOtherCustomComponent'],
// highlight-end
- }
- }
- }
- ]
+ },
+ },
+ },
+ ],
}
```
diff --git a/docs/fields/point.mdx b/docs/fields/point.mdx
index 68f0ebda6e..7c8e39f712 100644
--- a/docs/fields/point.mdx
+++ b/docs/fields/point.mdx
@@ -27,15 +27,14 @@ export const MyPointField: Field = {
```
- **Important:**
- The Point Field currently is not supported in SQLite.
+ **Important:** The Point Field currently is not supported in SQLite.
## Config
| Option | Description |
| ---------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
-| **`name`** * | To be used as the property name when stored and retrieved from the database. [More](/docs/fields/overview#field-names) |
+| **`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`. |
@@ -47,12 +46,12 @@ export const MyPointField: Field = {
| **`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. [More details](./overview#admin-options). |
+| **`admin`** | Admin-specific configuration. [More details](./overview#admin-options). |
| **`custom`** | Extension point for adding custom data (e.g. for plugins) |
| **`typescriptSchema`** | Override field type generation with providing a JSON schema |
| **`virtual`** | Provide `true` to disable field in the database. See [Virtual Fields](https://payloadcms.com/blog/learn-how-virtual-fields-can-help-solve-common-cms-challenges) |
-_* An asterisk denotes that a property is required._
+_\* An asterisk denotes that a property is required._
## Example
@@ -81,6 +80,7 @@ In order to do query based on the distance to another point, you can use the `ne
In order to do query based on whether points are within a specific area defined in GeoJSON, you can use the `within` operator.
Example:
+
```ts
const polygon: Point[] = [
[9.0, 19.0], // bottom-left
@@ -91,7 +91,7 @@ const polygon: Point[] = [
]
payload.find({
- collection: "points",
+ collection: 'points',
where: {
point: {
within: {
@@ -103,11 +103,11 @@ payload.find({
})
```
-
## Querying - intersects
In order to do query based on whether points intersect a specific area defined in GeoJSON, you can use the `intersects` operator.
Example:
+
```ts
const polygon: Point[] = [
[9.0, 19.0], // bottom-left
@@ -118,7 +118,7 @@ const polygon: Point[] = [
]
payload.find({
- collection: "points",
+ collection: 'points',
where: {
point: {
intersects: {
@@ -148,7 +148,12 @@ export const CustomPointFieldServer: PointFieldServerComponent = ({
permissions,
}) => {
return (
-
+
)
}
```
diff --git a/docs/fields/radio.mdx b/docs/fields/radio.mdx
index 4ddfbb29f0..385f20abf2 100644
--- a/docs/fields/radio.mdx
+++ b/docs/fields/radio.mdx
@@ -26,43 +26,44 @@ export const MyRadioField: Field = {
type: 'radio',
options: [
// ...
- ]
+ ],
// highlight-end
}
```
## Config Options
-| 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/overview), include its data in the user JWT. |
-| **`hooks`** | Provide Field Hooks to control logic for this field. [More details](../hooks/fields). |
-| **`access`** | Provide Field Access Control to denote what users can see and do with this field's data. [More details](../access-control/fields). |
-| **`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. [More details](#admin-options). |
-| **`custom`** | Extension point for adding custom data (e.g. for plugins) |
-| **`enumName`** | Custom enum name for this field when using SQL Database Adapter ([Postgres](/docs/database/postgres)). Auto-generated from name if not defined. |
-| **`interfaceName`** | Create a top level, reusable [Typescript interface](/docs/typescript/generating-types#custom-field-interfaces) & [GraphQL type](/docs/graphql/graphql-schema#custom-field-schemas). |
-| **`typescriptSchema`** | Override field type generation with providing a JSON schema |
-| **`virtual`** | Provide `true` to disable field in the database. See [Virtual Fields](https://payloadcms.com/blog/learn-how-virtual-fields-can-help-solve-common-cms-challenges) |
+| 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/overview), include its data in the user JWT. |
+| **`hooks`** | Provide Field Hooks to control logic for this field. [More details](../hooks/fields). |
+| **`access`** | Provide Field Access Control to denote what users can see and do with this field's data. [More details](../access-control/fields). |
+| **`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. [More details](#admin-options). |
+| **`custom`** | Extension point for adding custom data (e.g. for plugins) |
+| **`enumName`** | Custom enum name for this field when using SQL Database Adapter ([Postgres](/docs/database/postgres)). Auto-generated from name if not defined. |
+| **`interfaceName`** | Create a top level, reusable [Typescript interface](/docs/typescript/generating-types#custom-field-interfaces) & [GraphQL type](/docs/graphql/graphql-schema#custom-field-schemas). |
+| **`typescriptSchema`** | Override field type generation with providing a JSON schema |
+| **`virtual`** | Provide `true` to disable field in the database. See [Virtual Fields](https://payloadcms.com/blog/learn-how-virtual-fields-can-help-solve-common-cms-challenges) |
-_* An asterisk denotes that a property is required._
+_\* An asterisk denotes that a property is required._
**Important:**
- Option values should be strings that do not contain hyphens or special characters due to GraphQL
- enumeration naming constraints. Underscores are allowed. If you determine you need your option
- values to be non-strings or contain special characters, they will be formatted accordingly before
- being used as a GraphQL enum.
+Option values should be strings that do not contain hyphens or special characters due to GraphQL
+enumeration naming constraints. Underscores are allowed. If you determine you need your option
+values to be non-strings or contain special characters, they will be formatted accordingly before
+being used as a GraphQL enum.
+
## Admin Options
@@ -74,7 +75,8 @@ import type { Field } from 'payload'
export const MyRadioField: Field = {
// ...
- admin: { // highlight-line
+ admin: {
+ // highlight-line
// ...
},
}
@@ -82,9 +84,9 @@ export const MyRadioField: Field = {
The Radio Field inherits all of the default options from the base [Field Admin Config](./overview#admin-options), plus the following additional options:
-| Property | Description |
-| ------------------------------ | -------------------------------------------------------------------------------------------------------------------------------------- |
-| **`layout`** | Allows for the radio group to be styled as a horizontally or vertically distributed list. The default value is `horizontal`. |
+| Property | Description |
+| ------------ | ---------------------------------------------------------------------------------------------------------------------------- |
+| **`layout`** | Allows for the radio group to be styled as a horizontally or vertically distributed list. The default value is `horizontal`. |
## Example
diff --git a/docs/fields/relationship.mdx b/docs/fields/relationship.mdx
index 6d524d3936..201a7993f7 100644
--- a/docs/fields/relationship.mdx
+++ b/docs/fields/relationship.mdx
@@ -37,40 +37,41 @@ export const MyRelationshipField: Field = {
## Config Options
-| 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 maximum population depth for this field, regardless of the remaining depth when this field is reached. [Max Depth](/docs/queries/depth#max-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/overview), include its data in the user JWT. |
-| **`hooks`** | Provide Field Hooks to control logic for this field. [More details](../hooks/fields). |
-| **`access`** | Provide Field Access Control to denote what users can see and do with this field's data. [More details](../access-control/fields). |
-| **`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. [More details](#admin-options). |
-| **`custom`** | Extension point for adding custom data (e.g. for plugins) |
-| **`typescriptSchema`** | Override field type generation with providing a JSON schema |
-| **`virtual`** | Provide `true` to disable field in the database. See [Virtual Fields](https://payloadcms.com/blog/learn-how-virtual-fields-can-help-solve-common-cms-challenges) |
-| **`graphQL`** | Custom graphQL configuration for the field. [More details](/docs/graphql/overview#field-complexity) |
+| 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 maximum population depth for this field, regardless of the remaining depth when this field is reached. [Max Depth](/docs/queries/depth#max-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/overview), include its data in the user JWT. |
+| **`hooks`** | Provide Field Hooks to control logic for this field. [More details](../hooks/fields). |
+| **`access`** | Provide Field Access Control to denote what users can see and do with this field's data. [More details](../access-control/fields). |
+| **`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. [More details](#admin-options). |
+| **`custom`** | Extension point for adding custom data (e.g. for plugins) |
+| **`typescriptSchema`** | Override field type generation with providing a JSON schema |
+| **`virtual`** | Provide `true` to disable field in the database. See [Virtual Fields](https://payloadcms.com/blog/learn-how-virtual-fields-can-help-solve-common-cms-challenges) |
+| **`graphQL`** | Custom graphQL configuration for the field. [More details](/docs/graphql/overview#field-complexity) |
-_* An asterisk denotes that a property is required._
+_\* An asterisk denotes that a property is required._
- **Tip:**
- The [Depth](../queries/depth) parameter can be used to automatically populate related documents that are returned by the API.
+ **Tip:** The [Depth](../queries/depth) parameter can be used to automatically
+ populate related documents that are returned by the API.
## Admin Options
+
To the appearance and behavior of the Relationship Field in the [Admin Panel](../admin/overview), you can use the `admin` option:
```ts
@@ -78,7 +79,8 @@ import type { Field } from 'payload'
export const MyRelationshipField: Field = {
// ...
- admin: { // highlight-line
+ admin: {
+ // highlight-line
// ...
},
}
@@ -86,12 +88,12 @@ export const MyRelationshipField: Field = {
The Relationship Field inherits all of the default options from the base [Field Admin Config](./overview#admin-options), plus the following additional options:
-| Property | Description |
-| ------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------- |
-| **`isSortable`** | Set to `true` if you'd like this field to be sortable within the Admin UI using drag and drop (only works when `hasMany` is set to `true`). |
-| **`allowCreate`** | Set to `false` if you'd like to disable the ability to create new documents from within the relationship field. |
-| **`allowEdit`** | Set to `false` if you'd like to disable the ability to edit documents from within the relationship field. |
-| **`sortOptions`** | Define a default sorting order for the options within a Relationship field's dropdown. [More](#sort-options) |
+| Property | Description |
+| ----------------- | ------------------------------------------------------------------------------------------------------------------------------------------- |
+| **`isSortable`** | Set to `true` if you'd like this field to be sortable within the Admin UI using drag and drop (only works when `hasMany` is set to `true`). |
+| **`allowCreate`** | Set to `false` if you'd like to disable the ability to create new documents from within the relationship field. |
+| **`allowEdit`** | Set to `false` if you'd like to disable the ability to edit documents from within the relationship field. |
+| **`sortOptions`** | Define a default sorting order for the options within a Relationship field's dropdown. [More](#sort-options) |
### Sort Options
@@ -141,7 +143,7 @@ The `filterOptions` property can either be a `Where` query, or a function return
| Property | Description |
| ------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
-| `blockData` | The data of the nearest parent block. Will be `undefined` if the field is not within a block or when called on a `Filter` component within the list view. |
+| `blockData` | The data of the nearest parent block. Will be `undefined` if the field is not within a block or when called on a `Filter` component within the list view. |
| `data` | An object containing the full collection or global document currently being edited. Will be an empty object when called on a `Filter` component within the list view. |
| `id` | The `id` of the current document being edited. Will be `undefined` during the `create` operation or when called on a `Filter` component within the list view. |
| `relationTo` | The collection `slug` to filter against, limited to this field's `relationTo` property. |
@@ -185,10 +187,11 @@ You can learn more about writing queries [here](/docs/queries/overview).
**Note:**
- When a relationship field has both **filterOptions** and a custom
- **validate** function, the api will not validate **filterOptions**
- unless you call the default relationship field validation function imported from
- **payload/shared** in your validate function.
+When a relationship field has both **filterOptions** and a custom
+**validate** function, the api will not validate **filterOptions**
+unless you call the default relationship field validation function imported from
+**payload/shared** in your validate function.
+
## Bi-directional relationships
@@ -367,8 +370,9 @@ 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.
+
## Custom Components
@@ -382,21 +386,17 @@ import type React from 'react'
import { RelationshipField } from '@payloadcms/ui'
import type { RelationshipFieldServerComponent } from 'payload'
-export const CustomRelationshipFieldServer: RelationshipFieldServerComponent = ({
- clientField,
- path,
- schemaPath,
- permissions,
-}) => {
- return (
-
- )
-}
+export const CustomRelationshipFieldServer: RelationshipFieldServerComponent =
+ ({ clientField, path, schemaPath, permissions }) => {
+ return (
+
+ )
+ }
```
#### Client Component
@@ -407,7 +407,9 @@ import React from 'react'
import { RelationshipField } from '@payloadcms/ui'
import type { RelationshipFieldClientComponent } from 'payload'
-export const CustomRelationshipFieldClient: RelationshipFieldClientComponent = (props) => {
+export const CustomRelationshipFieldClient: RelationshipFieldClientComponent = (
+ props,
+) => {
return
}
```
@@ -421,18 +423,16 @@ import React from 'react'
import { FieldLabel } from '@payloadcms/ui'
import type { RelationshipFieldLabelServerComponent } from 'payload'
-export const CustomRelationshipFieldLabelServer: RelationshipFieldLabelServerComponent = (
- clientField,
- path
-) => {
- return (
-
- )
-}
+export const CustomRelationshipFieldLabelServer: RelationshipFieldLabelServerComponent =
+ (clientField, path) => {
+ return (
+
+ )
+ }
```
#### Client Component
@@ -443,16 +443,14 @@ import React from 'react'
import { FieldLabel } from '@payloadcms/ui'
import type { RelationshipFieldLabelClientComponent } from 'payload'
-export const CustomRelationshipFieldLabelClient: RelationshipFieldLabelClientComponent = ({
- field,
- path,
-}) => {
- return (
-
- )
-}
+export const CustomRelationshipFieldLabelClient: RelationshipFieldLabelClientComponent =
+ ({ field, path }) => {
+ return (
+
+ )
+ }
```
diff --git a/docs/fields/rich-text.mdx b/docs/fields/rich-text.mdx
index 8a53e04fc5..4e9cc8fe6b 100644
--- a/docs/fields/rich-text.mdx
+++ b/docs/fields/rich-text.mdx
@@ -12,29 +12,34 @@ Consistent with Payload's goal of making you learn as little of Payload as possi
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 Options
-| Option | Description |
-| --- | --- |
-| **`name`** * | To be used as the property name when stored and retrieved from the database. [More](./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](./overview#validation) |
-| **`saveToJWT`** | If this field is top-level and nested in a config supporting [Authentication](../authentication/overview), include its data in the user JWT. |
-| **`hooks`** | Provide Field Hooks to control logic for this field. [More details](../hooks/fields). |
-| **`access`** | Provide Field Access Control to denote what users can see and do with this field's data. [More details](../access-control/fields). |
-| **`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](./overview#default-values) |
-| **`localized`** | Enable localization for this field. Requires [localization to be enabled](../configuration/localization) in the Base config. |
-| **`required`** | Require this field to have a value. |
-| **`admin`** | Admin-specific configuration. [More details](#admin-options). |
-| **`editor`** | Customize or override the rich text editor. [More details](../rich-text/overview). |
-| **`custom`** | Extension point for adding custom data (e.g. for plugins) |
-| **`typescriptSchema`** | Override field type generation with providing a JSON schema |
-| **`virtual`** | Provide `true` to disable field in the database. See [Virtual Fields](https://payloadcms.com/blog/learn-how-virtual-fields-can-help-solve-common-cms-challenges) |
+| Option | Description |
+| ---------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------- |
+| **`name`** \* | To be used as the property name when stored and retrieved from the database. [More](./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](./overview#validation) |
+| **`saveToJWT`** | If this field is top-level and nested in a config supporting [Authentication](../authentication/overview), include its data in the user JWT. |
+| **`hooks`** | Provide Field Hooks to control logic for this field. [More details](../hooks/fields). |
+| **`access`** | Provide Field Access Control to denote what users can see and do with this field's data. [More details](../access-control/fields). |
+| **`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](./overview#default-values) |
+| **`localized`** | Enable localization for this field. Requires [localization to be enabled](../configuration/localization) in the Base config. |
+| **`required`** | Require this field to have a value. |
+| **`admin`** | Admin-specific configuration. [More details](#admin-options). |
+| **`editor`** | Customize or override the rich text editor. [More details](../rich-text/overview). |
+| **`custom`** | Extension point for adding custom data (e.g. for plugins) |
+| **`typescriptSchema`** | Override field type generation with providing a JSON schema |
+| **`virtual`** | Provide `true` to disable field in the database. See [Virtual Fields](https://payloadcms.com/blog/learn-how-virtual-fields-can-help-solve-common-cms-challenges) |
-** An asterisk denotes that a property is required.*
+\*_ An asterisk denotes that a property is required._
## Admin Options
@@ -45,7 +50,8 @@ import type { Field } from 'payload'
export const MyRichTextField: Field = {
// ...
- admin: { // highlight-line
+ admin: {
+ // highlight-line
// ...
},
}
diff --git a/docs/fields/row.mdx b/docs/fields/row.mdx
index a0deda5a1e..6a2262d4b6 100644
--- a/docs/fields/row.mdx
+++ b/docs/fields/row.mdx
@@ -26,20 +26,20 @@ export const MyRowField: Field = {
type: 'row',
fields: [
// ...
- ]
+ ],
// highlight-end
}
```
## Config Options
-| Option | Description |
-| --------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
-| **`fields`** * | Array of field types to nest within this Row. |
+| Option | Description |
+| --------------- | ------------------------------------------------------------------------------------------------------------------------- |
+| **`fields`** \* | Array of field types to nest within this Row. |
| **`admin`** | Admin-specific configuration excluding `description`, `readOnly`, and `hidden`. [More details](./overview#admin-options). |
-| **`custom`** | Extension point for adding custom data (e.g. for plugins) |
+| **`custom`** | Extension point for adding custom data (e.g. for plugins) |
-_* An asterisk denotes that a property is required._
+_\* An asterisk denotes that a property is required._
## Example
diff --git a/docs/fields/select.mdx b/docs/fields/select.mdx
index 7495ead495..2c53847984 100644
--- a/docs/fields/select.mdx
+++ b/docs/fields/select.mdx
@@ -26,45 +26,45 @@ export const MySelectField: Field = {
type: 'select',
options: [
// ...
- ]
+ ],
// highlight-end
}
```
## Config Options
-| 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/overview), include its data in the user JWT. |
-| **`hooks`** | Provide Field Hooks to control logic for this field. [More details](../hooks/fields). |
-| **`access`** | Provide Field Access Control to denote what users can see and do with this field's data. [More details](../access-control/fields). |
-| **`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-options) for more details. |
-| **`custom`** | Extension point for adding custom data (e.g. for plugins) |
-| **`enumName`** | Custom enum name for this field when using SQL Database Adapter ([Postgres](/docs/database/postgres)). Auto-generated from name if not defined. |
-| **`dbName`** | Custom table name (if `hasMany` set to `true`) for this field when using SQL Database Adapter ([Postgres](/docs/database/postgres)). Auto-generated from name if not defined. |
-| **`interfaceName`** | Create a top level, reusable [Typescript interface](/docs/typescript/generating-types#custom-field-interfaces) & [GraphQL type](/docs/graphql/graphql-schema#custom-field-schemas). |
-| **`typescriptSchema`** | Override field type generation with providing a JSON schema |
-| **`virtual`** | Provide `true` to disable field in the database. See [Virtual Fields](https://payloadcms.com/blog/learn-how-virtual-fields-can-help-solve-common-cms-challenges) |
+| 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/overview), include its data in the user JWT. |
+| **`hooks`** | Provide Field Hooks to control logic for this field. [More details](../hooks/fields). |
+| **`access`** | Provide Field Access Control to denote what users can see and do with this field's data. [More details](../access-control/fields). |
+| **`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-options) for more details. |
+| **`custom`** | Extension point for adding custom data (e.g. for plugins) |
+| **`enumName`** | Custom enum name for this field when using SQL Database Adapter ([Postgres](/docs/database/postgres)). Auto-generated from name if not defined. |
+| **`dbName`** | Custom table name (if `hasMany` set to `true`) for this field when using SQL Database Adapter ([Postgres](/docs/database/postgres)). Auto-generated from name if not defined. |
+| **`interfaceName`** | Create a top level, reusable [Typescript interface](/docs/typescript/generating-types#custom-field-interfaces) & [GraphQL type](/docs/graphql/graphql-schema#custom-field-schemas). |
+| **`typescriptSchema`** | Override field type generation with providing a JSON schema |
+| **`virtual`** | Provide `true` to disable field in the database. See [Virtual Fields](https://payloadcms.com/blog/learn-how-virtual-fields-can-help-solve-common-cms-challenges) |
-_* An asterisk denotes that a property is required._
+_\* An asterisk denotes that a property is required._
- **Important:**
- Option values should be strings that do not contain hyphens or special characters due to GraphQL
- enumeration naming constraints. Underscores are allowed. If you determine you need your option
- values to be non-strings or contain special characters, they will be formatted accordingly before
- being used as a GraphQL enum.
+ **Important:** Option values should be strings that do not contain hyphens or
+ special characters due to GraphQL enumeration naming constraints. Underscores
+ are allowed. If you determine you need your option values to be non-strings or
+ contain special characters, they will be formatted accordingly before being
+ used as a GraphQL enum.
## Admin Options
@@ -76,7 +76,8 @@ import type { Field } from 'payload'
export const MySelectField: Field = {
// ...
- admin: { // highlight-line
+ admin: {
+ // highlight-line
// ...
},
}
@@ -84,10 +85,10 @@ export const MySelectField: Field = {
The Select Field inherits all of the default options from the base [Field Admin Config](./overview#admin-options), plus the following additional options:
-| Property | Description |
-| ------------------------------ | ---------------------------------------------------------------------------------------------------------------------------------------- |
-| **`isClearable`** | Set to `true` if you'd like this field to be clearable within the Admin UI. |
-| **`isSortable`** | Set to `true` if you'd like this field to be sortable within the Admin UI using drag and drop. (Only works when `hasMany` is set to `true`) |
+| Property | Description |
+| ----------------- | ------------------------------------------------------------------------------------------------------------------------------------------- |
+| **`isClearable`** | Set to `true` if you'd like this field to be clearable within the Admin UI. |
+| **`isSortable`** | Set to `true` if you'd like this field to be sortable within the Admin UI using drag and drop. (Only works when `hasMany` is set to `true`) |
## Example
diff --git a/docs/fields/tabs.mdx b/docs/fields/tabs.mdx
index a98d748e28..cdbb01620c 100644
--- a/docs/fields/tabs.mdx
+++ b/docs/fields/tabs.mdx
@@ -26,18 +26,18 @@ export const MyTabsField: Field = {
type: 'tabs',
tabs: [
// ...
- ]
+ ],
// highlight-end
}
```
## Config Options
-| Option | Description |
-| ------------- | ------------------------------------------------------------------------------------------------------------------------ |
-| **`tabs`** * | Array of tabs to render within this Tabs field. |
+| Option | Description |
+| ------------- | ----------------------------------------------------------------------- |
+| **`tabs`** \* | Array of tabs to render within this Tabs field. |
| **`admin`** | Admin-specific configuration. [More details](./overview#admin-options). |
-| **`custom`** | Extension point for adding custom data (e.g. for plugins) |
+| **`custom`** | Extension point for adding custom data (e.g. for plugins) |
### Tab-specific Config
@@ -47,12 +47,12 @@ Each tab must have either a `name` or `label` and the required `fields` array. Y
| ------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| **`name`** | Groups field data into an object when stored and retrieved from the database. [More](/docs/fields/overview#field-names) |
| **`label`** | The label to render on the tab itself. Required when name is undefined, defaults to name converted to words. |
-| **`fields`** * | The fields to render within this tab. |
+| **`fields`** \* | The fields to render within this tab. |
| **`description`** | Optionally render a description within this tab to describe the contents of the tab itself. |
| **`interfaceName`** | Create a top level, reusable [Typescript interface](/docs/typescript/generating-types#custom-field-interfaces) & [GraphQL type](/docs/graphql/graphql-schema#custom-field-schemas). (`name` must be present) |
| **`virtual`** | Provide `true` to disable field in the database (`name` must be present). See [Virtual Fields](https://payloadcms.com/blog/learn-how-virtual-fields-can-help-solve-common-cms-challenges) |
-_* An asterisk denotes that a property is required._
+_\* An asterisk denotes that a property is required._
## Example
diff --git a/docs/fields/text.mdx b/docs/fields/text.mdx
index b8b7bd1c04..18d52809d3 100644
--- a/docs/fields/text.mdx
+++ b/docs/fields/text.mdx
@@ -30,7 +30,7 @@ export const MyTextField: Field = {
| Option | Description |
| ---------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
-| **`name`** * | To be used as the property name when stored and retrieved from the database. [More](/docs/fields/overview#field-names) |
+| **`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. |
@@ -52,7 +52,7 @@ export const MyTextField: Field = {
| **`typescriptSchema`** | Override field type generation with providing a JSON schema |
| **`virtual`** | Provide `true` to disable field in the database. See [Virtual Fields](https://payloadcms.com/blog/learn-how-virtual-fields-can-help-solve-common-cms-challenges) |
-_* An asterisk denotes that a property is required._
+_\* An asterisk denotes that a property is required._
## Admin Options
@@ -63,7 +63,8 @@ import type { Field } from 'payload'
export const MyTextField: Field = {
// ...
- admin: { // highlight-line
+ admin: {
+ // highlight-line
// ...
},
}
@@ -71,11 +72,11 @@ export const MyTextField: Field = {
The Text Field inherits all of the default options from the base [Field Admin Config](./overview#admin-options), plus the following additional options:
-| Option | Description |
-| -------------- | ---------------------------------------------------------------------------------------------------------------- |
-| **`placeholder`** | Set this property to define a placeholder string in the text input. |
-| **`autoComplete`** | Set this property to a string that will be used for browser autocomplete. |
-| **`rtl`** | Override the default text direction of the Admin Panel for this field. Set to `true` to force right-to-left text direction. |
+| Option | Description |
+| ------------------ | --------------------------------------------------------------------------------------------------------------------------- |
+| **`placeholder`** | Set this property to define a placeholder string in the text input. |
+| **`autoComplete`** | Set this property to a string that will be used for browser autocomplete. |
+| **`rtl`** | Override the default text direction of the Admin Panel for this field. Set to `true` to force right-to-left text direction. |
## Example
@@ -114,7 +115,12 @@ export const CustomTextFieldServer: TextFieldServerComponent = ({
permissions,
}) => {
return (
-
+
)
}
```
diff --git a/docs/fields/textarea.mdx b/docs/fields/textarea.mdx
index 383202b567..e9754cd9b7 100644
--- a/docs/fields/textarea.mdx
+++ b/docs/fields/textarea.mdx
@@ -30,7 +30,7 @@ export const MyTextareaField: Field = {
| Option | Description |
| ---------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
-| **`name`** * | To be used as the property name when stored and retrieved from the database. [More](/docs/fields/overview#field-names) |
+| **`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. |
@@ -49,7 +49,7 @@ export const MyTextareaField: Field = {
| **`typescriptSchema`** | Override field type generation with providing a JSON schema |
| **`virtual`** | Provide `true` to disable field in the database. See [Virtual Fields](https://payloadcms.com/blog/learn-how-virtual-fields-can-help-solve-common-cms-challenges) |
-_* An asterisk denotes that a property is required._
+_\* An asterisk denotes that a property is required._
## Admin Options
@@ -60,7 +60,8 @@ import type { Field } from 'payload'
export const MyTextareaField: Field = {
// ...
- admin: { // highlight-line
+ admin: {
+ // highlight-line
// ...
},
}
@@ -130,7 +131,9 @@ import React from 'react'
import { TextareaField } from '@payloadcms/ui'
import type { TextareaFieldClientComponent } from 'payload'
-export const CustomTextareaFieldClient: TextareaFieldClientComponent = (props) => {
+export const CustomTextareaFieldClient: TextareaFieldClientComponent = (
+ props,
+) => {
return
}
```
@@ -144,18 +147,16 @@ import React from 'react'
import { FieldLabel } from '@payloadcms/ui'
import type { TextareaFieldLabelServerComponent } from 'payload'
-export const CustomTextareaFieldLabelServer: TextareaFieldLabelServerComponent = ({
- clientField,
- path,
-}) => {
- return (
-
- )
-}
+export const CustomTextareaFieldLabelServer: TextareaFieldLabelServerComponent =
+ ({ clientField, path }) => {
+ return (
+
+ )
+ }
```
#### Client Component
@@ -166,16 +167,14 @@ import React from 'react'
import { FieldLabel } from '@payloadcms/ui'
import type { TextareaFieldLabelClientComponent } from 'payload'
-export const CustomTextareaFieldLabelClient: TextareaFieldLabelClientComponent = ({
- field,
- path,
-}) => {
- return (
-
- )
-}
+export const CustomTextareaFieldLabelClient: TextareaFieldLabelClientComponent =
+ ({ field, path }) => {
+ return (
+
+ )
+ }
```
diff --git a/docs/fields/ui.mdx b/docs/fields/ui.mdx
index dac3ba732f..98133a224e 100644
--- a/docs/fields/ui.mdx
+++ b/docs/fields/ui.mdx
@@ -28,16 +28,16 @@ export const MyUIField: Field = {
## Config Options
-| Option | Description |
-| ------------------------------- | ------------------------------------------------------------------------------------------------------------------- |
-| **`name`** * | A unique identifier for this field. |
-| **`label`** | Human-readable label for this UI field. |
-| **`admin.components.Field`** * | React component to be rendered for this field within the Edit View. [More](./overview#field) |
-| **`admin.components.Cell`** | React component to be rendered as a Cell within collection List views. [More](./overview#cell) |
-| **`admin.disableListColumn`** | Set `disableListColumn` to `true` to prevent the UI field from appearing in the list view column selector. |
-| **`custom`** | Extension point for adding custom data (e.g. for plugins) |
+| Option | Description |
+| ------------------------------- | ---------------------------------------------------------------------------------------------------------- |
+| **`name`** \* | A unique identifier for this field. |
+| **`label`** | Human-readable label for this UI field. |
+| **`admin.components.Field`** \* | React component to be rendered for this field within the Edit View. [More](./overview#field) |
+| **`admin.components.Cell`** | React component to be rendered as a Cell within collection List views. [More](./overview#cell) |
+| **`admin.disableListColumn`** | Set `disableListColumn` to `true` to prevent the UI field from appearing in the list view column selector. |
+| **`custom`** | Extension point for adding custom data (e.g. for plugins) |
-_* An asterisk denotes that a property is required._
+_\* An asterisk denotes that a property is required._
## Example
diff --git a/docs/fields/upload.mdx b/docs/fields/upload.mdx
index 6da44127f3..f8aefb4e53 100644
--- a/docs/fields/upload.mdx
+++ b/docs/fields/upload.mdx
@@ -16,10 +16,10 @@ Upload fields are useful for a variety of use cases, such as:
- To give a layout building block the ability to feature a background image
To create an Upload Field, set the `type` to `upload` in your [Field Config](./overview):
@@ -37,16 +37,17 @@ export const MyUploadField: Field = {
```
- **Important:**
- To use the Upload Field, you must have a [Collection](../configuration/collections) configured to allow [Uploads](../upload/overview).
+ **Important:** To use the Upload Field, you must have a
+ [Collection](../configuration/collections) configured to allow
+ [Uploads](../upload/overview).
## Config Options
| 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.** |
+| ---------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
+| **`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). |
| **`hasMany`** | Boolean which, 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. |
@@ -64,13 +65,13 @@ export const MyUploadField: Field = {
| **`displayPreview`** | Enable displaying preview of the uploaded file. Overrides related Collection's `displayPreview` option. [More](/docs/upload/overview#collection-upload-options). |
| **`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. [Admin Options](./overview#admin-options). |
+| **`admin`** | Admin-specific configuration. [Admin Options](./overview#admin-options). |
| **`custom`** | Extension point for adding custom data (e.g. for plugins) |
| **`typescriptSchema`** | Override field type generation with providing a JSON schema |
| **`virtual`** | Provide `true` to disable field in the database. See [Virtual Fields](https://payloadcms.com/blog/learn-how-virtual-fields-can-help-solve-common-cms-challenges) |
| **`graphQL`** | Custom graphQL configuration for the field. [More details](/docs/graphql/overview#field-complexity) |
-_* An asterisk denotes that a property is required._
+_\* An asterisk denotes that a property is required._
## Example
@@ -102,7 +103,7 @@ 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 |
@@ -128,10 +129,11 @@ You can learn more about writing queries [here](/docs/queries/overview).
**Note:**
- When an upload field has both **filterOptions** and a custom
- **validate** function, the api will not validate **filterOptions**
- unless you call the default upload field validation function imported from
- **payload/shared** in your validate function.
+When an upload field has both **filterOptions** and a custom
+**validate** function, the api will not validate **filterOptions**
+unless you call the default upload field validation function imported from
+**payload/shared** in your validate function.
+
## Bi-directional relationships
diff --git a/docs/getting-started/concepts.mdx b/docs/getting-started/concepts.mdx
index 76ed219508..5a07e9f6f7 100644
--- a/docs/getting-started/concepts.mdx
+++ b/docs/getting-started/concepts.mdx
@@ -53,8 +53,8 @@ Everything Payload does (create, read, update, delete, login, logout, etc.) is e
- [GraphQL](#graphql-api) - A full GraphQL API with a GraphQL Playground
- **Note:**
- All of these APIs share the exact same query language. [More details](../queries/overview).
+ **Note:** All of these APIs share the exact same query language. [More
+ details](../queries/overview).
### Local API
@@ -127,8 +127,9 @@ You can use any GraphQL client with Payload's GraphQL endpoint. Here are a few p
Payload is abstracted into a set of dedicated packages to keep the core `payload` package as lightweight as possible. This allows you to only install the parts of Payload based on your unique project requirements.
- **Important:**
- Version numbers of all official Payload packages are always published in sync. You should make sure that you always use matching versions for all official Payload packages.
+ **Important:** Version numbers of all official Payload packages are always
+ published in sync. You should make sure that you always use matching versions
+ for all official Payload packages.
`payload`
@@ -166,6 +167,6 @@ You can choose which Database Adapter you'd like to use for your project, and no
Payload's Rich Text functionality is abstracted into separate packages and if you want to enable Rich Text in your project, you'll need to install one of these packages. We recommend Lexical for all new projects, and this is where Payload will focus its efforts on from this point, but Slate is still supported if you have already built with it.
- **Note:**
- Rich Text is entirely optional and you may not need it for your project.
+ **Note:** Rich Text is entirely optional and you may not need it for your
+ project.
diff --git a/docs/getting-started/installation.mdx b/docs/getting-started/installation.mdx
index aa2410eaad..7fc8e0ac53 100644
--- a/docs/getting-started/installation.mdx
+++ b/docs/getting-started/installation.mdx
@@ -15,8 +15,8 @@ Payload requires the following software:
- Any [compatible database](/docs/database/overview) (MongoDB, Postgres or SQLite)
- **Important:**
- Before proceeding any further, please ensure that you have the above requirements met.
+ **Important:** Before proceeding any further, please ensure that you have the
+ above requirements met.
## Quickstart with create-payload-app
@@ -48,8 +48,8 @@ pnpm i payload @payloadcms/next @payloadcms/richtext-lexical sharp graphql
```
- **Note:**
- Swap out `pnpm` for your package manager. If you are using npm, you might need to install using legacy peer deps: `npm i --legacy-peer-deps`.
+ **Note:** Swap out `pnpm` for your package manager. If you are using npm, you
+ might need to install using legacy peer deps: `npm i --legacy-peer-deps`.
Next, install a [Database Adapter](/docs/database/overview). Payload requires a Database Adapter to establish a database connection. Payload works with all types of databases, but the most common are MongoDB and Postgres.
@@ -57,23 +57,25 @@ Next, install a [Database Adapter](/docs/database/overview). Payload requires a
To install a Database Adapter, you can run **one** of the following commands:
- To install the [MongoDB Adapter](../database/mongodb), run:
- ```bash
- pnpm i @payloadcms/db-mongodb
- ```
+
+ ```bash
+ pnpm i @payloadcms/db-mongodb
+ ```
- To install the [Postgres Adapter](../database/postgres), run:
- ```bash
- pnpm i @payloadcms/db-postgres
- ```
+ ```bash
+ pnpm i @payloadcms/db-postgres
+ ```
- **Note:**
- New [Database Adapters](/docs/database/overview) are becoming available every day. Check the docs for the most up-to-date list of what's available.
+ **Note:** New [Database Adapters](/docs/database/overview) are becoming
+ available every day. Check the docs for the most up-to-date list of what's
+ available.
#### 2. Copy Payload files into your Next.js app folder
-Payload installs directly in your Next.js `/app` folder, and you'll need to place some files into that folder for Payload to run. You can copy these files from the [Blank Template](https://github.com/payloadcms/payload/tree/main/templates/blank/src/app/(payload)) on GitHub. Once you have the required Payload files in place in your `/app` folder, you should have something like this:
+Payload installs directly in your Next.js `/app` folder, and you'll need to place some files into that folder for Payload to run. You can copy these files from the [Blank Template]() on GitHub. Once you have the required Payload files in place in your `/app` folder, you should have something like this:
```plaintext
app/
@@ -86,7 +88,10 @@ app/
_For an exact reference of the `(payload)` directory, see [Project Structure](../admin/overview#project-structure)._
- You may need to copy all of your existing frontend files, including your existing root layout, into its own newly created [Route Group](https://nextjs.org/docs/app/building-your-application/routing/route-groups), i.e. `(my-app)`.
+ You may need to copy all of your existing frontend files, including your
+ existing root layout, into its own newly created [Route
+ Group](https://nextjs.org/docs/app/building-your-application/routing/route-groups),
+ i.e. `(my-app)`.
The files that Payload needs to have in your `/app` folder do not regenerate, and will never change. Once you slot them in, you never have to revisit them. They are not meant to be edited and simply import Payload dependencies from `@payloadcms/next` for the REST / GraphQL API and Admin Panel.
@@ -106,8 +111,8 @@ import { withPayload } from '@payloadcms/next/withPayload'
const nextConfig = {
// Your Next.js config here
experimental: {
- reactCompiler: false
- }
+ reactCompiler: false,
+ },
}
// Make sure you wrap your `nextConfig`
@@ -116,8 +121,8 @@ export default withPayload(nextConfig) // highlight-line
```
- **Important:**
- Payload is a fully ESM project, and that means the `withPayload` function is an ECMAScript module.
+ **Important:** Payload is a fully ESM project, and that means the
+ `withPayload` function is an ECMAScript module.
To import the Payload Plugin, you need to make sure your `next.config` file is set up to use ESM.
@@ -171,11 +176,9 @@ Once you have a Payload Config, update your `tsconfig` to include a `path` that
{
"compilerOptions": {
"paths": {
- "@payload-config": [
- "./payload.config.ts"
- ]
+ "@payload-config": ["./payload.config.ts"]
}
- },
+ }
}
```
diff --git a/docs/getting-started/what-is-payload.mdx b/docs/getting-started/what-is-payload.mdx
index f965930d5a..6883268a49 100644
--- a/docs/getting-started/what-is-payload.mdx
+++ b/docs/getting-started/what-is-payload.mdx
@@ -53,7 +53,10 @@ Payload has restored a little love back into the dev / marketer equation with fe
If you're building a website and your frontend is on Next.js, then Payload is a no-brainer.
- Instead of going out and signing up for a SaaS vendor that makes it so you have to manage two completely separate concerns, with little to no native connection back and forth, just install Payload in your existing Next.js repo and instantly get a full CMS.
+ Instead of going out and signing up for a SaaS vendor that makes it so you
+ have to manage two completely separate concerns, with little to no native
+ connection back and forth, just install Payload in your existing Next.js repo
+ and instantly get a full CMS.
Get started with Payload as a CMS using our official Website template:
diff --git a/docs/graphql/extending.mdx b/docs/graphql/extending.mdx
index 363ffd22f5..03298c91aa 100644
--- a/docs/graphql/extending.mdx
+++ b/docs/graphql/extending.mdx
@@ -115,10 +115,10 @@ import { GraphQL } from '@payloadcms/graphql/types'
```
- For queries, mutations and handlers make sure you use the `GraphQL` and `payload` instances provided via arguments.
+ For queries, mutations and handlers make sure you use the `GraphQL` and
+ `payload` instances provided via arguments.
-
**`buildPaginatedListType`**
This is a utility function that allows you to build a new GraphQL type for a paginated result similar to the Payload's generated schema.
@@ -134,7 +134,10 @@ export const getMyPosts = (GraphQL, payload) => {
args: {},
resolve: Resolver,
// The name of your new type has to be unique
- type: buildPaginatedListType('AuthorPosts', payload.collections['posts'].graphQL?.type),
+ type: buildPaginatedListType(
+ 'AuthorPosts',
+ payload.collections['posts'].graphQL?.type,
+ ),
}
}
```
diff --git a/docs/graphql/graphql-schema.mdx b/docs/graphql/graphql-schema.mdx
index e58c15e857..ae238cd9e4 100644
--- a/docs/graphql/graphql-schema.mdx
+++ b/docs/graphql/graphql-schema.mdx
@@ -67,7 +67,8 @@ The above example outputs all your definitions to a file relative from your payl
**Important**
- Payload needs to be able to find your config to generate your GraphQL schema.
+Payload needs to be able to find your config to generate your GraphQL schema.
+
Payload will automatically try and locate your config, but might not always be able to find it. For example, if you are working in a `/src` directory or similar, you need to tell Payload where to find your config manually by using an environment variable.
diff --git a/docs/graphql/overview.mdx b/docs/graphql/overview.mdx
index 0e4b48ec2c..a31b8b5ad8 100644
--- a/docs/graphql/overview.mdx
+++ b/docs/graphql/overview.mdx
@@ -43,17 +43,17 @@ export const PublicUser: CollectionConfig = {
**Payload will automatically open up the following queries:**
-| Query Name | Operation |
-| ------------------- | ------------------- |
-| `PublicUser` | `findByID` |
-| `PublicUsers` | `find` |
-| `countPublicUsers` | `count` |
-| `mePublicUser` | `me` auth operation |
+| Query Name | Operation |
+| ------------------ | ------------------- |
+| `PublicUser` | `findByID` |
+| `PublicUsers` | `find` |
+| `countPublicUsers` | `count` |
+| `mePublicUser` | `me` auth operation |
**And the following mutations:**
-| Query Name | Operation |
-| ------------------------------ | ------------------------------- |
+| Query Name | Operation |
+| -------------------------- | ------------------------------- |
| `createPublicUser` | `create` |
| `updatePublicUser` | `update` |
| `deletePublicUser` | `delete` |
@@ -82,14 +82,14 @@ const Header: GlobalConfig = {
**Payload will open the following query:**
-| Query Name | Operation |
-| ------------ | --------- |
-| `Header` | `findOne` |
+| Query Name | Operation |
+| ---------- | --------- |
+| `Header` | `findOne` |
**And the following mutation:**
-| Query Name | Operation |
-| ------------------ | --------- |
+| Query Name | Operation |
+| -------------- | --------- |
| `updateHeader` | `update` |
## Preferences
@@ -98,14 +98,14 @@ User [preferences](../admin/preferences) for the [Admin Panel](../admin/overview
**Payload will open the following query:**
-| Query Name | Operation |
-| ---------------- | --------- |
+| Query Name | Operation |
+| ------------ | --------- |
| `Preference` | `findOne` |
**And the following mutations:**
-| Query Name | Operation |
-| ---------------------- | --------- |
+| Query Name | Operation |
+| ------------------ | --------- |
| `updatePreference` | `update` |
| `deletePreference` | `delete` |
@@ -118,11 +118,12 @@ You can even log in using the `login[collection-singular-label-here]` mutation t
**Tip:**
- To see more regarding how the above queries and mutations are used, visit your GraphQL playground
- (by default at
- [`${SERVER_URL}/api/graphql-playground`](http://localhost:3000/api/graphql-playground))
- while your server is running. There, you can use the "Schema" and "Docs" buttons on the right to
- see a ton of detail about how GraphQL operates within Payload.
+To see more regarding how the above queries and mutations are used, visit your GraphQL playground
+(by default at
+[`${SERVER_URL}/api/graphql-playground`](http://localhost:3000/api/graphql-playground))
+while your server is running. There, you can use the "Schema" and "Docs" buttons on the right to
+see a ton of detail about how GraphQL operates within Payload.
+
## Custom Validation Rules
@@ -136,9 +137,7 @@ import { buildConfig } from 'payload'
export default buildConfig({
// ...
graphQL: {
- validationRules: (args) => [
- NoProductionIntrospection
- ]
+ validationRules: (args) => [NoProductionIntrospection],
},
// ...
})
@@ -150,12 +149,12 @@ const NoProductionIntrospection: GraphQL.ValidationRule = (context) => ({
context.reportError(
new GraphQL.GraphQLError(
'GraphQL introspection is not allowed, but the query contained __schema or __type',
- { nodes: [node] }
- )
- );
+ { nodes: [node] },
+ ),
+ )
}
}
- }
+ },
})
```
@@ -174,6 +173,6 @@ const fieldWithComplexity = {
relationship: 'authors',
graphQL: {
complexity: 100, // highlight-line
- }
+ },
}
```
diff --git a/docs/hooks/collections.mdx b/docs/hooks/collections.mdx
index b1f71c4cdf..202db20369 100644
--- a/docs/hooks/collections.mdx
+++ b/docs/hooks/collections.mdx
@@ -11,19 +11,20 @@ Collection Hooks are [Hooks](./overview) that run on Documents within a specific
To add Hooks to a Collection, use the `hooks` property in your [Collection Config](../configuration/collections):
```ts
-import type { CollectionConfig } from 'payload';
+import type { CollectionConfig } from 'payload'
export const CollectionWithHooks: CollectionConfig = {
// ...
- hooks: { // highlight-line
+ hooks: {
+ // highlight-line
// ...
},
}
```
- **Tip:**
- You can also set hooks on the field-level to isolate hook logic to specific fields. [More details](./fields).
+ **Tip:** You can also set hooks on the field-level to isolate hook logic to
+ specific fields. [More details](./fields).
## Config Options
@@ -82,12 +83,12 @@ const beforeOperationHook: CollectionBeforeOperationHook = async ({
The following arguments are provided to the `beforeOperation` hook:
-| Option | Description |
-| ------------------------ | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
-| **`collection`** | The [Collection](../configuration/collections) in which this Hook is running against. |
-| **`context`** | Custom context passed between Hooks. [More details](./context). |
-| **`operation`** | The name of the operation that this hook is running within. |
-| **`req`** | The [Web Request](https://developer.mozilla.org/en-US/docs/Web/API/Request) object. This is mocked for [Local API](../local-api/overview) operations. |
+| Option | Description |
+| ---------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------- |
+| **`collection`** | The [Collection](../configuration/collections) in which this Hook is running against. |
+| **`context`** | Custom context passed between Hooks. [More details](./context). |
+| **`operation`** | The name of the operation that this hook is running within. |
+| **`req`** | The [Web Request](https://developer.mozilla.org/en-US/docs/Web/API/Request) object. This is mocked for [Local API](../local-api/overview) operations. |
### beforeValidate
@@ -102,23 +103,21 @@ Please do note that this does not run before client-side validation. If you rend
```ts
import type { CollectionBeforeValidateHook } from 'payload'
-const beforeValidateHook: CollectionBeforeValidateHook = async ({
- data,
-}) => {
+const beforeValidateHook: CollectionBeforeValidateHook = async ({ data }) => {
return data
}
```
The following arguments are provided to the `beforeValidate` hook:
-| Option | Description |
-| ------------------------ | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
-| **`collection`** | The [Collection](../configuration/collections) in which this Hook is running against. |
-| **`context`** | Custom context passed between Hooks. [More details](./context). |
-| **`data`** | The incoming data passed through the operation. |
-| **`operation`** | The name of the operation that this hook is running within. |
-| **`originalDoc`** | The Document before changes are applied. |
-| **`req`** | The [Web Request](https://developer.mozilla.org/en-US/docs/Web/API/Request) object. This is mocked for [Local API](../local-api/overview) operations. |
+| Option | Description |
+| ----------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------- |
+| **`collection`** | The [Collection](../configuration/collections) in which this Hook is running against. |
+| **`context`** | Custom context passed between Hooks. [More details](./context). |
+| **`data`** | The incoming data passed through the operation. |
+| **`operation`** | The name of the operation that this hook is running within. |
+| **`originalDoc`** | The Document before changes are applied. |
+| **`req`** | The [Web Request](https://developer.mozilla.org/en-US/docs/Web/API/Request) object. This is mocked for [Local API](../local-api/overview) operations. |
### beforeChange
@@ -127,23 +126,21 @@ Immediately following validation, `beforeChange` hooks will run within `create`
```ts
import type { CollectionBeforeChangeHook } from 'payload'
-const beforeChangeHook: CollectionBeforeChangeHook = async ({
- data,
-}) => {
+const beforeChangeHook: CollectionBeforeChangeHook = async ({ data }) => {
return data
}
```
The following arguments are provided to the `beforeChange` hook:
-| Option | Description |
-| ------------------------ | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
-| **`collection`** | The [Collection](../configuration/collections) in which this Hook is running against. |
-| **`context`** | Custom context passed between hooks. [More details](./context). |
-| **`data`** | The incoming data passed through the operation. |
-| **`operation`** | The name of the operation that this hook is running within. |
-| **`originalDoc`** | The Document before changes are applied. |
-| **`req`** | The [Web Request](https://developer.mozilla.org/en-US/docs/Web/API/Request) object. This is mocked for [Local API](../local-api/overview) operations. |
+| Option | Description |
+| ----------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------- |
+| **`collection`** | The [Collection](../configuration/collections) in which this Hook is running against. |
+| **`context`** | Custom context passed between hooks. [More details](./context). |
+| **`data`** | The incoming data passed through the operation. |
+| **`operation`** | The name of the operation that this hook is running within. |
+| **`originalDoc`** | The Document before changes are applied. |
+| **`req`** | The [Web Request](https://developer.mozilla.org/en-US/docs/Web/API/Request) object. This is mocked for [Local API](../local-api/overview) operations. |
### afterChange
@@ -152,23 +149,21 @@ After a document is created or updated, the `afterChange` hook runs. This hook i
```ts
import type { CollectionAfterChangeHook } from 'payload'
-const afterChangeHook: CollectionAfterChangeHook = async ({
- doc,
-}) => {
+const afterChangeHook: CollectionAfterChangeHook = async ({ doc }) => {
return doc
}
```
The following arguments are provided to the `afterChange` hook:
-| Option | Description |
-| ------------------------ | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
-| **`collection`** | The [Collection](../configuration/collections) in which this Hook is running against. |
-| **`context`** | Custom context passed between hooks. [More details](./context). |
-| **`doc`** | The resulting Document after changes are applied. |
-| **`operation`** | The name of the operation that this hook is running within. |
-| **`previousDoc`** | The Document before changes were applied. |
-| **`req`** | The [Web Request](https://developer.mozilla.org/en-US/docs/Web/API/Request) object. This is mocked for [Local API](../local-api/overview) operations. |
+| Option | Description |
+| ----------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------- |
+| **`collection`** | The [Collection](../configuration/collections) in which this Hook is running against. |
+| **`context`** | Custom context passed between hooks. [More details](./context). |
+| **`doc`** | The resulting Document after changes are applied. |
+| **`operation`** | The name of the operation that this hook is running within. |
+| **`previousDoc`** | The Document before changes were applied. |
+| **`req`** | The [Web Request](https://developer.mozilla.org/en-US/docs/Web/API/Request) object. This is mocked for [Local API](../local-api/overview) operations. |
### beforeRead
@@ -177,9 +172,7 @@ Runs before `find` and `findByID` operations are transformed for output by `afte
```ts
import type { CollectionBeforeReadHook } from 'payload'
-const beforeReadHook: CollectionBeforeReadHook = async ({
- doc,
-}) => {
+const beforeReadHook: CollectionBeforeReadHook = async ({ doc }) => {
return doc
}
```
@@ -201,9 +194,7 @@ Runs as the last step before documents are returned. Flattens locales, hides pro
```ts
import type { CollectionAfterReadHook } from 'payload'
-const afterReadHook: CollectionAfterReadHook = async ({
- doc,
-}) => {
+const afterReadHook: CollectionAfterReadHook = async ({ doc }) => {
return doc
}
```
@@ -233,12 +224,12 @@ const beforeDeleteHook: CollectionBeforeDeleteHook = async ({
The following arguments are provided to the `beforeDelete` hook:
-| Option | Description |
-| ------------------------ | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
-| **`collection`** | The [Collection](../configuration/collections) in which this Hook is running against. |
-| **`context`** | Custom context passed between hooks. [More details](./context). |
-| **`id`** | The ID of the Document being deleted. |
-| **`req`** | The [Web Request](https://developer.mozilla.org/en-US/docs/Web/API/Request) object. This is mocked for [Local API](../local-api/overview) operations. |
+| Option | Description |
+| ---------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------- |
+| **`collection`** | The [Collection](../configuration/collections) in which this Hook is running against. |
+| **`context`** | Custom context passed between hooks. [More details](./context). |
+| **`id`** | The ID of the Document being deleted. |
+| **`req`** | The [Web Request](https://developer.mozilla.org/en-US/docs/Web/API/Request) object. This is mocked for [Local API](../local-api/overview) operations. |
### afterDelete
@@ -256,13 +247,13 @@ const afterDeleteHook: CollectionAfterDeleteHook = async ({
The following arguments are provided to the `afterDelete` hook:
-| Option | Description |
-| ------------------------ | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
-| **`collection`** | The [Collection](../configuration/collections) in which this Hook is running against. |
-| **`context`** | Custom context passed between hooks. [More details](./context). |
-| **`doc`** | The resulting Document after changes are applied. |
-| **`id`** | The ID of the Document that was deleted. |
-| **`req`** | The [Web Request](https://developer.mozilla.org/en-US/docs/Web/API/Request) object. This is mocked for [Local API](../local-api/overview) operations. |
+| Option | Description |
+| ---------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------- |
+| **`collection`** | The [Collection](../configuration/collections) in which this Hook is running against. |
+| **`context`** | Custom context passed between hooks. [More details](./context). |
+| **`doc`** | The resulting Document after changes are applied. |
+| **`id`** | The ID of the Document that was deleted. |
+| **`req`** | The [Web Request](https://developer.mozilla.org/en-US/docs/Web/API/Request) object. This is mocked for [Local API](../local-api/overview) operations. |
### afterOperation
@@ -273,22 +264,20 @@ Available Collection operations include `create`, `find`, `findByID`, `update`,
```ts
import type { CollectionAfterOperationHook } from 'payload'
-const afterOperationHook: CollectionAfterOperationHook = async ({
- result,
-}) => {
+const afterOperationHook: CollectionAfterOperationHook = async ({ result }) => {
return result
}
```
The following arguments are provided to the `afterOperation` hook:
-| Option | Description |
-| ------------------------ | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
-| **`args`** | The arguments passed into the operation. |
-| **`collection`** | The [Collection](../configuration/collections) in which this Hook is running against. |
-| **`req`** | The [Web Request](https://developer.mozilla.org/en-US/docs/Web/API/Request) object. This is mocked for [Local API](../local-api/overview) operations. |
-| **`operation`** | The name of the operation that this hook is running within. |
-| **`result`** | The result of the operation, before modifications. |
+| Option | Description |
+| ---------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------- |
+| **`args`** | The arguments passed into the operation. |
+| **`collection`** | The [Collection](../configuration/collections) in which this Hook is running against. |
+| **`req`** | The [Web Request](https://developer.mozilla.org/en-US/docs/Web/API/Request) object. This is mocked for [Local API](../local-api/overview) operations. |
+| **`operation`** | The name of the operation that this hook is running within. |
+| **`result`** | The result of the operation, before modifications. |
### afterError
@@ -303,6 +292,7 @@ const afterDeleteHook: CollectionAfterErrorHook = async ({
doc,
}) => {...}
```
+
The following arguments are provided to the `afterError` Hook:
| Argument | Description |
@@ -321,21 +311,19 @@ For [Auth-enabled Collections](../authentication/overview), this hook runs durin
```ts
import type { CollectionBeforeLoginHook } from 'payload'
-const beforeLoginHook: CollectionBeforeLoginHook = async ({
- user,
-}) => {
+const beforeLoginHook: CollectionBeforeLoginHook = async ({ user }) => {
return user
}
```
The following arguments are provided to the `beforeLogin` hook:
-| Option | Description |
-| ------------------------ | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
-| **`collection`** | The [Collection](../configuration/collections) in which this Hook is running against. |
-| **`context`** | Custom context passed between hooks. [More details](./context). |
-| **`req`** | The [Web Request](https://developer.mozilla.org/en-US/docs/Web/API/Request) object. This is mocked for [Local API](../local-api/overview) operations. |
-| **`user`** | The user being logged in. |
+| Option | Description |
+| ---------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------- |
+| **`collection`** | The [Collection](../configuration/collections) in which this Hook is running against. |
+| **`context`** | Custom context passed between hooks. [More details](./context). |
+| **`req`** | The [Web Request](https://developer.mozilla.org/en-US/docs/Web/API/Request) object. This is mocked for [Local API](../local-api/overview) operations. |
+| **`user`** | The user being logged in. |
### afterLogin
@@ -352,13 +340,13 @@ const afterLoginHook: CollectionAfterLoginHook = async ({
The following arguments are provided to the `afterLogin` hook:
-| Option | Description |
-| ------------------------ | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
-| **`collection`** | The [Collection](../configuration/collections) in which this Hook is running against. |
-| **`context`** | Custom context passed between hooks. [More details](./context). |
-| **`req`** | The [Web Request](https://developer.mozilla.org/en-US/docs/Web/API/Request) object. This is mocked for [Local API](../local-api/overview) operations. |
-| **`token`** | The token generated for the user. |
-| **`user`** | The user being logged in. |
+| Option | Description |
+| ---------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------- |
+| **`collection`** | The [Collection](../configuration/collections) in which this Hook is running against. |
+| **`context`** | Custom context passed between hooks. [More details](./context). |
+| **`req`** | The [Web Request](https://developer.mozilla.org/en-US/docs/Web/API/Request) object. This is mocked for [Local API](../local-api/overview) operations. |
+| **`token`** | The token generated for the user. |
+| **`user`** | The user being logged in. |
### afterLogout
@@ -374,11 +362,11 @@ const afterLogoutHook: CollectionAfterLogoutHook = async ({
The following arguments are provided to the `afterLogout` hook:
-| Option | Description |
-| ------------------------ | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
-| **`collection`** | The [Collection](../configuration/collections) in which this Hook is running against. |
-| **`context`** | Custom context passed between hooks. [More details](./context). |
-| **`req`** | The [Web Request](https://developer.mozilla.org/en-US/docs/Web/API/Request) object. This is mocked for [Local API](../local-api/overview) operations. |
+| Option | Description |
+| ---------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------- |
+| **`collection`** | The [Collection](../configuration/collections) in which this Hook is running against. |
+| **`context`** | Custom context passed between hooks. [More details](./context). |
+| **`req`** | The [Web Request](https://developer.mozilla.org/en-US/docs/Web/API/Request) object. This is mocked for [Local API](../local-api/overview) operations. |
### afterMe
@@ -395,12 +383,12 @@ const afterMeHook: CollectionAfterMeHook = async ({
The following arguments are provided to the `afterMe` hook:
-| Option | Description |
-| ------------------------ | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
-| **`collection`** | The [Collection](../configuration/collections) in which this Hook is running against. |
-| **`context`** | Custom context passed between hooks. [More details](./context). |
-| **`req`** | The [Web Request](https://developer.mozilla.org/en-US/docs/Web/API/Request) object. This is mocked for [Local API](../local-api/overview) operations. |
-| **`response`** | The response to return. |
+| Option | Description |
+| ---------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------- |
+| **`collection`** | The [Collection](../configuration/collections) in which this Hook is running against. |
+| **`context`** | Custom context passed between hooks. [More details](./context). |
+| **`req`** | The [Web Request](https://developer.mozilla.org/en-US/docs/Web/API/Request) object. This is mocked for [Local API](../local-api/overview) operations. |
+| **`response`** | The response to return. |
### afterRefresh
@@ -416,13 +404,13 @@ const afterRefreshHook: CollectionAfterRefreshHook = async ({
The following arguments are provided to the `afterRefresh` hook:
-| Option | Description |
-| ------------------------ | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
-| **`collection`** | The [Collection](../configuration/collections) in which this Hook is running against. |
-| **`context`** | Custom context passed between hooks. [More details](./context). |
-| **`exp`** | The expiration time of the token. |
-| **`req`** | The [Web Request](https://developer.mozilla.org/en-US/docs/Web/API/Request) object. This is mocked for [Local API](../local-api/overview) operations. |
-| **`token`** | The newly refreshed user token. |
+| Option | Description |
+| ---------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------- |
+| **`collection`** | The [Collection](../configuration/collections) in which this Hook is running against. |
+| **`context`** | Custom context passed between hooks. [More details](./context). |
+| **`exp`** | The expiration time of the token. |
+| **`req`** | The [Web Request](https://developer.mozilla.org/en-US/docs/Web/API/Request) object. This is mocked for [Local API](../local-api/overview) operations. |
+| **`token`** | The newly refreshed user token. |
### afterForgotPassword
@@ -440,11 +428,11 @@ const afterForgotPasswordHook: CollectionAfterForgotPasswordHook = async ({
The following arguments are provided to the `afterForgotPassword` hook:
-| Option | Description |
-| ------------------------ | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
-| **`args`** | The arguments passed into the operation. |
-| **`collection`** | The [Collection](../configuration/collections) in which this Hook is running against. |
-| **`context`** | Custom context passed between hooks. [More details](./context). |
+| Option | Description |
+| ---------------- | ------------------------------------------------------------------------------------- |
+| **`args`** | The arguments passed into the operation. |
+| **`collection`** | The [Collection](../configuration/collections) in which this Hook is running against. |
+| **`context`** | Custom context passed between hooks. [More details](./context). |
### refresh
@@ -461,10 +449,10 @@ const myRefreshHook: CollectionRefreshHook = async ({
The following arguments are provided to the `afterRefresh` hook:
-| Option | Description |
-| ------------------------ | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
-| **`args`** | The arguments passed into the operation. |
-| **`user`** | The user being logged in. |
+| Option | Description |
+| ---------- | ---------------------------------------- |
+| **`args`** | The arguments passed into the operation. |
+| **`user`** | The user being logged in. |
### me
@@ -481,10 +469,10 @@ const meHook: CollectionMeHook = async ({
The following arguments are provided to the `me` hook:
-| Option | Description |
-| ------------------------ | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
-| **`args`** | The arguments passed into the operation. |
-| **`user`** | The user being logged in. |
+| Option | Description |
+| ---------- | ---------------------------------------- |
+| **`args`** | The arguments passed into the operation. |
+| **`user`** | The user being logged in. |
## TypeScript
diff --git a/docs/hooks/fields.mdx b/docs/hooks/fields.mdx
index fa2cd76a9f..1c8e91ced0 100644
--- a/docs/hooks/fields.mdx
+++ b/docs/hooks/fields.mdx
@@ -11,11 +11,12 @@ Field Hooks are [Hooks](./overview) that run on Documents on a per-field basis.
To add Hooks to a Field, use the `hooks` property in your [Field Config](../fields/overview):
```ts
-import type { Field } from 'payload';
+import type { Field } from 'payload'
export const FieldWithHooks: Field = {
// ...
- hooks: { // highlight-line
+ hooks: {
+ // highlight-line
// ...
},
}
@@ -26,8 +27,11 @@ export const FieldWithHooks: Field = {
All Field Hooks accept an array of synchronous or asynchronous functions. These functions can optionally modify the return value of the field before the operation continues. All Field Hooks are formatted to accept the same arguments, although some arguments may be `undefined` based the specific hook type.
- **Important:**
- Due to GraphQL's typed nature, changing the type of data that you return from a field will produce errors in the [GraphQL API](../graphql/overview). If you need to change the shape or type of data, consider [Collection Hooks](./collections) or [Global Hooks](./globals) instead.
+ **Important:** Due to GraphQL's typed nature, changing the type of data that
+ you return from a field will produce errors in the [GraphQL
+ API](../graphql/overview). If you need to change the shape or type of data,
+ consider [Collection Hooks](./collections) or [Global Hooks](./globals)
+ instead.
To add hooks to a Field, use the `hooks` property in your [Field Config](../fields/overview):
@@ -52,31 +56,33 @@ const FieldWithHooks: Field = {
The following arguments are provided to all Field Hooks:
-| Option | Description |
-| ------------------------ | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
-| **`collection`** | The [Collection](../configuration/collections) in which this Hook is running against. If the field belongs to a Global, this will be `null`. |
-| **`context`** | Custom context passed between Hooks. [More details](./context). |
-| **`data`** | In the `afterRead` hook this is the full Document. In the `create` and `update` operations, this is the incoming data passed through the operation. |
-| **`field`** | The [Field](../fields/overview) which the Hook is running against. |
-| **`findMany`** | Boolean to denote if this hook is running against finding one, or finding many within the `afterRead` hook. |
-| **`global`** | The [Global](../configuration/globals) in which this Hook is running against. If the field belongs to a Collection, this will be `null`. |
-| **`operation`** | The name of the operation that this hook is running within. Useful within `beforeValidate`, `beforeChange`, and `afterChange` hooks to differentiate between `create` and `update` operations. |
-| **`originalDoc`** | In the `update` operation, this is the Document before changes were applied. In the `afterChange` hook, this is the resulting Document. |
-| **`overrideAccess`** | A boolean to denote if the current operation is overriding [Access Control](../access-control/overview). |
-| **`path`** | The path to the [Field](../fields/overview) in the schema. |
-| **`previousDoc`** | In the `afterChange` Hook, this is the Document before changes were applied. |
-| **`previousSiblingDoc`** | The sibling data of the Document before changes being applied, only in `beforeChange` and `afterChange` hook. |
-| **`previousValue`** | The previous value of the field, before changes, only in `beforeChange` and `afterChange` hooks. |
-| **`req`** | The [Web Request](https://developer.mozilla.org/en-US/docs/Web/API/Request) object. This is mocked for [Local API](../local-api/overview) operations. |
-| **`schemaPath`** | The path of the [Field](../fields/overview) in the schema. |
-| **`siblingData`** | The data of sibling fields adjacent to the field that the Hook is running against. |
-| **`siblingDocWithLocales`** | The sibling data of the Document with all [Locales](../configuration/localization). |
-| **`siblingFields`** | The sibling fields of the field which the hook is running against. |
-| **`value`** | The value of the [Field](../fields/overview). |
+| Option | Description |
+| --------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
+| **`collection`** | The [Collection](../configuration/collections) in which this Hook is running against. If the field belongs to a Global, this will be `null`. |
+| **`context`** | Custom context passed between Hooks. [More details](./context). |
+| **`data`** | In the `afterRead` hook this is the full Document. In the `create` and `update` operations, this is the incoming data passed through the operation. |
+| **`field`** | The [Field](../fields/overview) which the Hook is running against. |
+| **`findMany`** | Boolean to denote if this hook is running against finding one, or finding many within the `afterRead` hook. |
+| **`global`** | The [Global](../configuration/globals) in which this Hook is running against. If the field belongs to a Collection, this will be `null`. |
+| **`operation`** | The name of the operation that this hook is running within. Useful within `beforeValidate`, `beforeChange`, and `afterChange` hooks to differentiate between `create` and `update` operations. |
+| **`originalDoc`** | In the `update` operation, this is the Document before changes were applied. In the `afterChange` hook, this is the resulting Document. |
+| **`overrideAccess`** | A boolean to denote if the current operation is overriding [Access Control](../access-control/overview). |
+| **`path`** | The path to the [Field](../fields/overview) in the schema. |
+| **`previousDoc`** | In the `afterChange` Hook, this is the Document before changes were applied. |
+| **`previousSiblingDoc`** | The sibling data of the Document before changes being applied, only in `beforeChange` and `afterChange` hook. |
+| **`previousValue`** | The previous value of the field, before changes, only in `beforeChange` and `afterChange` hooks. |
+| **`req`** | The [Web Request](https://developer.mozilla.org/en-US/docs/Web/API/Request) object. This is mocked for [Local API](../local-api/overview) operations. |
+| **`schemaPath`** | The path of the [Field](../fields/overview) in the schema. |
+| **`siblingData`** | The data of sibling fields adjacent to the field that the Hook is running against. |
+| **`siblingDocWithLocales`** | The sibling data of the Document with all [Locales](../configuration/localization). |
+| **`siblingFields`** | The sibling fields of the field which the hook is running against. |
+| **`value`** | The value of the [Field](../fields/overview). |
- **Tip:**
- It's a good idea to conditionally scope your logic based on which operation is executing. For example, if you are writing a `beforeChange` hook, you may want to perform different logic based on if the current `operation` is `create` or `update`.
+ **Tip:** It's a good idea to conditionally scope your logic based on which
+ operation is executing. For example, if you are writing a `beforeChange` hook,
+ you may want to perform different logic based on if the current `operation` is
+ `create` or `update`.
### beforeValidate
@@ -220,10 +226,12 @@ const numberField: Field = {
type: 'number',
hooks: {
// increment existing value by 1
- beforeDuplicate: [({ value }) => {
- return (value ?? 0) + 1
- }],
- }
+ beforeDuplicate: [
+ ({ value }) => {
+ return (value ?? 0) + 1
+ },
+ ],
+ },
}
```
diff --git a/docs/hooks/globals.mdx b/docs/hooks/globals.mdx
index e5e1a0d3b2..b14f28503e 100644
--- a/docs/hooks/globals.mdx
+++ b/docs/hooks/globals.mdx
@@ -11,19 +11,20 @@ Global Hooks are [Hooks](./overview) that run on [Global](../configuration/globa
To add Hooks to a Global, use the `hooks` property in your [Global Config](../configuration/globals):
```ts
-import type { GlobalConfig } from 'payload';
+import type { GlobalConfig } from 'payload'
export const GlobalWithHooks: GlobalConfig = {
// ...
- hooks: { // highlight-line
+ hooks: {
+ // highlight-line
// ...
},
}
```
- **Tip:**
- You can also set hooks on the field-level to isolate hook logic to specific fields. [More details](./fields).
+ **Tip:** You can also set hooks on the field-level to isolate hook logic to
+ specific fields. [More details](./fields).
## Config Options
@@ -71,13 +72,13 @@ const beforeValidateHook: GlobalBeforeValidateHook = async ({
The following arguments are provided to the `beforeValidate` hook:
-| Option | Description |
-| ------------------------ | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
-| **`global`** | The [Global](../configuration/globals) in which this Hook is running against. |
-| **`context`** | Custom context passed between Hooks. [More details](./context). |
-| **`data`** | The incoming data passed through the operation. |
-| **`originalDoc`** | The Document before changes are applied. |
-| **`req`** | The [Web Request](https://developer.mozilla.org/en-US/docs/Web/API/Request) object. This is mocked for [Local API](../local-api/overview) operations. |
+| Option | Description |
+| ----------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------- |
+| **`global`** | The [Global](../configuration/globals) in which this Hook is running against. |
+| **`context`** | Custom context passed between Hooks. [More details](./context). |
+| **`data`** | The incoming data passed through the operation. |
+| **`originalDoc`** | The Document before changes are applied. |
+| **`req`** | The [Web Request](https://developer.mozilla.org/en-US/docs/Web/API/Request) object. This is mocked for [Local API](../local-api/overview) operations. |
### beforeChange
@@ -97,13 +98,13 @@ const beforeChangeHook: GlobalBeforeChangeHook = async ({
The following arguments are provided to the `beforeChange` hook:
-| Option | Description |
-| ------------------------ | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
-| **`global`** | The [Global](../configuration/globals) in which this Hook is running against. |
-| **`context`** | Custom context passed between hooks. [More details](./context). |
-| **`data`** | The incoming data passed through the operation. |
-| **`originalDoc`** | The Document before changes are applied. |
-| **`req`** | The [Web Request](https://developer.mozilla.org/en-US/docs/Web/API/Request) object. This is mocked for [Local API](../local-api/overview) operations. |
+| Option | Description |
+| ----------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------- |
+| **`global`** | The [Global](../configuration/globals) in which this Hook is running against. |
+| **`context`** | Custom context passed between hooks. [More details](./context). |
+| **`data`** | The incoming data passed through the operation. |
+| **`originalDoc`** | The Document before changes are applied. |
+| **`req`** | The [Web Request](https://developer.mozilla.org/en-US/docs/Web/API/Request) object. This is mocked for [Local API](../local-api/overview) operations. |
### afterChange
@@ -123,13 +124,13 @@ const afterChangeHook: GlobalAfterChangeHook = async ({
The following arguments are provided to the `afterChange` hook:
-| Option | Description |
-| ------------------------ | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
-| **`global`** | The [Global](../configuration/globals) in which this Hook is running against. |
-| **`context`** | Custom context passed between hooks. [More details](./context). |
-| **`doc`** | The resulting Document after changes are applied. |
-| **`previousDoc`** | The Document before changes were applied. |
-| **`req`** | The [Web Request](https://developer.mozilla.org/en-US/docs/Web/API/Request) object. This is mocked for [Local API](../local-api/overview) operations. |
+| Option | Description |
+| ----------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------- |
+| **`global`** | The [Global](../configuration/globals) in which this Hook is running against. |
+| **`context`** | Custom context passed between hooks. [More details](./context). |
+| **`doc`** | The resulting Document after changes are applied. |
+| **`previousDoc`** | The Document before changes were applied. |
+| **`req`** | The [Web Request](https://developer.mozilla.org/en-US/docs/Web/API/Request) object. This is mocked for [Local API](../local-api/overview) operations. |
### beforeRead
@@ -146,12 +147,12 @@ const beforeReadHook: GlobalBeforeReadHook = async ({
The following arguments are provided to the `beforeRead` hook:
-| Option | Description |
-| ------------------------ | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
-| **`global`** | The [Global](../configuration/globals) in which this Hook is running against. |
-| **`context`** | Custom context passed between hooks. [More details](./context). |
-| **`doc`** | The resulting Document after changes are applied. |
-| **`req`** | The [Web Request](https://developer.mozilla.org/en-US/docs/Web/API/Request) object. This is mocked for [Local API](../local-api/overview) operations. |
+| Option | Description |
+| ------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------- |
+| **`global`** | The [Global](../configuration/globals) in which this Hook is running against. |
+| **`context`** | Custom context passed between hooks. [More details](./context). |
+| **`doc`** | The resulting Document after changes are applied. |
+| **`req`** | The [Web Request](https://developer.mozilla.org/en-US/docs/Web/API/Request) object. This is mocked for [Local API](../local-api/overview) operations. |
### afterRead
diff --git a/docs/hooks/overview.mdx b/docs/hooks/overview.mdx
index 82533ec3f3..c1601e8578 100644
--- a/docs/hooks/overview.mdx
+++ b/docs/hooks/overview.mdx
@@ -26,8 +26,10 @@ There are four main types of Hooks in Payload:
- [Field Hooks](/docs/hooks/fields)
- **Reminder:**
- Payload also ships a set of _React_ hooks that you can use in your frontend application. Although they share a common name, these are very different things and should not be confused. [More details](../admin/react-hooks).
+ **Reminder:** Payload also ships a set of _React_ hooks that you can use in
+ your frontend application. Although they share a common name, these are very
+ different things and should not be confused. [More
+ details](../admin/react-hooks).
## Root Hooks
@@ -51,9 +53,9 @@ export default buildConfig({
The following options are available:
-| Option | Description |
-|--------------|-----------------------------------------------------------------------------------------------|
-| **`afterError`** | Runs after an error occurs in the Payload application. |
+| Option | Description |
+| ---------------- | ------------------------------------------------------ |
+| **`afterError`** | Runs after an error occurs in the Payload application. |
### afterError
@@ -65,9 +67,11 @@ import { buildConfig } from 'payload'
export default buildConfig({
// ...
hooks: {
- afterError: [async ({ error }) => {
- // Do something
- }]
+ afterError: [
+ async ({ error }) => {
+ // Do something
+ },
+ ],
},
})
```
@@ -82,6 +86,7 @@ The following arguments are provided to the `afterError` Hook:
| **`req`** | The `PayloadRequest` object that extends [Web Request](https://developer.mozilla.org/en-US/docs/Web/API/Request). Contains currently authenticated `user` and the Local API instance `payload`. |
| **`collection`** | The [Collection](../configuration/collections) in which this Hook is running against. This will be `undefined` if the hook is executed from a non-collection endpoint or GraphQL. |
| **`result`** | The formatted error result object, available if the hook is executed from a REST context. |
+
## Async vs. Synchronous
All Hooks can be written as either synchronous or asynchronous functions. Choosing the right type depends on your use case, but switching between the two is as simple as adding or removing the `async` keyword.
diff --git a/docs/integrations/vercel-content-link.mdx b/docs/integrations/vercel-content-link.mdx
index 1afb3abf3d..fb33a876ca 100644
--- a/docs/integrations/vercel-content-link.mdx
+++ b/docs/integrations/vercel-content-link.mdx
@@ -11,9 +11,10 @@ keywords: vercel, vercel content link, content link, visual editing, content sou

- Vercel Content Link is an enterprise-only feature and only available for deployments hosted on
- Vercel. If you are an existing enterprise customer, [contact our sales
- team](https://payloadcms.com/for-enterprise) for help with your integration.
+ Vercel Content Link is an enterprise-only feature and only available for
+ deployments hosted on Vercel. If you are an existing enterprise customer,
+ [contact our sales team](https://payloadcms.com/for-enterprise) for help with
+ your integration.
## How it works
diff --git a/docs/jobs-queue/jobs.mdx b/docs/jobs-queue/jobs.mdx
index 2ecc1125a7..8b24a86859 100644
--- a/docs/jobs-queue/jobs.mdx
+++ b/docs/jobs-queue/jobs.mdx
@@ -9,7 +9,9 @@ keywords: jobs queue, application framework, typescript, node, react, nextjs
Now that we have covered Tasks and Workflows, we can tie them together with a concept called a Job.
- Whereas you define Workflows and Tasks, which control your business logic, a **Job** is an individual instance of either a Task or a Workflow which contains many tasks.
+ Whereas you define Workflows and Tasks, which control your business logic, a
+ **Job** is an individual instance of either a Task or a Workflow which
+ contains many tasks.
For example, let's say we have a Workflow or Task that describes the logic to sync information from Payload to a third-party system. This is how you'd declare how to sync that info, but it wouldn't do anything on its own. In order to run that task or workflow, you'd create a Job that references the corresponding Task or Workflow.
diff --git a/docs/jobs-queue/queues.mdx b/docs/jobs-queue/queues.mdx
index a60b4d37de..df93e8c5d8 100644
--- a/docs/jobs-queue/queues.mdx
+++ b/docs/jobs-queue/queues.mdx
@@ -9,7 +9,8 @@ keywords: jobs queue, application framework, typescript, node, react, nextjs
Queues are the final aspect of Payload's Jobs Queue and deal with how to _run your jobs_. Up to this point, all we've covered is how to queue up jobs to run, but so far, we aren't actually running any jobs.
- A **Queue** is a grouping of jobs that should be executed in order of when they were added.
+ A **Queue** is a grouping of jobs that should be executed in order of when
+ they were added.
When you go to run jobs, Payload will query for any jobs that are added to the queue and then run them. By default, all queued jobs are added to the `default` queue.
@@ -52,12 +53,15 @@ export default buildConfig({
// This function will be invoked each time Payload goes to pick up and run jobs.
// If this function ever returns false, the cron schedule will be stopped.
return true
- }
+ },
},
})
```
-autoRun is intended for use with a dedicated server that is always running, and should not be used on serverless platforms like Vercel.
+
+ autoRun is intended for use with a dedicated server that is always running,
+ and should not be used on serverless platforms like Vercel.
+
#### Endpoint
@@ -69,9 +73,9 @@ You can execute jobs by making a fetch request to the `/api/payload-jobs/run` en
await fetch('/api/payload-jobs/run?limit=100&queue=nightly', {
method: 'GET',
headers: {
- 'Authorization': `Bearer ${token}`,
+ Authorization: `Bearer ${token}`,
},
-});
+})
```
This endpoint is automatically mounted for you and is helpful in conjunction with serverless platforms like Vercel, where you might want to use Vercel Cron to invoke a serverless function that executes your jobs.
@@ -113,12 +117,12 @@ export default buildConfig({
// If there is no logged in user, then check
// for the Vercel Cron secret to be present as an
// Authorization header:
- const authHeader = req.headers.get('authorization');
- return authHeader === `Bearer ${process.env.CRON_SECRET}`;
+ const authHeader = req.headers.get('authorization')
+ return authHeader === `Bearer ${process.env.CRON_SECRET}`
},
},
// Other job configurations...
- }
+ },
})
```
@@ -139,14 +143,16 @@ const results = await payload.jobs.run()
await payload.jobs.run({ queue: 'nightly', limit: 100 })
// You can provide a where clause to filter the jobs that should be run:
-await payload.jobs.run({ where: { 'input.message': { equals: 'secret' } } })
+await payload.jobs.run({
+ where: { 'input.message': { equals: 'secret' } },
+})
```
**Run a single job:**
```ts
const results = await payload.jobs.runByID({
- id: myJobID
+ id: myJobID,
})
```
diff --git a/docs/jobs-queue/tasks.mdx b/docs/jobs-queue/tasks.mdx
index a2a76beadb..399ed0a6ed 100644
--- a/docs/jobs-queue/tasks.mdx
+++ b/docs/jobs-queue/tasks.mdx
@@ -7,7 +7,8 @@ keywords: jobs queue, application framework, typescript, node, react, nextjs
---
- A **"Task"** is a function definition that performs business logic and whose input and output are both strongly typed.
+ A **"Task"** is a function definition that performs business logic and whose
+ input and output are both strongly typed.
You can register Tasks on the Payload config, and then create [Jobs](/docs/jobs-queue/jobs) or [Workflows](/docs/jobs-queue/workflows) that use them. Think of Tasks like tidy, isolated "functions that do one specific thing".
@@ -20,17 +21,17 @@ Tasks can either be defined within the `jobs.tasks` array in your payload config
Simply add a task to the `jobs.tasks` array in your Payload config. A task consists of the following fields:
-| Option | Description |
-| --------------------------- | -------------------------------------------------------------------------------- |
-| `slug` | Define a slug-based name for this job. This slug needs to be unique among both tasks and workflows.|
-| `handler` | The function that should be responsible for running the job. You can either pass a string-based path to the job function file, or the job function itself. If you are using large dependencies within your job, you might prefer to pass the string path because that will avoid bundling large dependencies in your Next.js app. Passing a string path is an advanced feature that may require a sophisticated build pipeline in order to work. |
-| `inputSchema` | Define the input field schema - payload will generate a type for this schema. |
-| `interfaceName` | You can use interfaceName to change the name of the interface that is generated for this task. By default, this is "Task" + the capitalized task slug. |
-| `outputSchema` | Define the output field schema - payload will generate a type for this schema. |
-| `label` | Define a human-friendly label for this task. |
-| `onFail` | Function to be executed if the task fails. |
-| `onSuccess` | Function to be executed if the task succeeds. |
-| `retries` | Specify the number of times that this step should be retried if it fails. If this is undefined, the task will either inherit the retries from the workflow or have no retries. If this is 0, the task will not be retried. By default, this is undefined. |
+| Option | Description |
+| --------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
+| `slug` | Define a slug-based name for this job. This slug needs to be unique among both tasks and workflows. |
+| `handler` | The function that should be responsible for running the job. You can either pass a string-based path to the job function file, or the job function itself. If you are using large dependencies within your job, you might prefer to pass the string path because that will avoid bundling large dependencies in your Next.js app. Passing a string path is an advanced feature that may require a sophisticated build pipeline in order to work. |
+| `inputSchema` | Define the input field schema - payload will generate a type for this schema. |
+| `interfaceName` | You can use interfaceName to change the name of the interface that is generated for this task. By default, this is "Task" + the capitalized task slug. |
+| `outputSchema` | Define the output field schema - payload will generate a type for this schema. |
+| `label` | Define a human-friendly label for this task. |
+| `onFail` | Function to be executed if the task fails. |
+| `onSuccess` | Function to be executed if the task succeeds. |
+| `retries` | Specify the number of times that this step should be retried if it fails. If this is undefined, the task will either inherit the retries from the workflow or have no retries. If this is 0, the task will not be retried. By default, this is undefined. |
The logic for the Task is defined in the `handler` - which can be defined as a function, or a path to a function. The `handler` will run once a worker picks picks up a Job that includes this task.
@@ -86,8 +87,8 @@ export default buildConfig({
}
},
} as TaskConfig<'createPost'>,
- ]
- }
+ ],
+ },
})
```
@@ -112,10 +113,12 @@ export default buildConfig({
{
// ...
// The #createPostHandler is a named export within the `createPost.ts` file
- handler: path.resolve(dirname, 'src/tasks/createPost.ts') + '#createPostHandler',
- }
- ]
- }
+ handler:
+ path.resolve(dirname, 'src/tasks/createPost.ts') +
+ '#createPostHandler',
+ },
+ ],
+ },
})
```
@@ -126,7 +129,11 @@ Then, the `createPost` file itself:
```ts
import type { TaskHandler } from 'payload'
-export const createPostHandler: TaskHandler<'createPost'> = async ({ input, job, req }) => {
+export const createPostHandler: TaskHandler<'createPost'> = async ({
+ input,
+ job,
+ req,
+}) => {
const newPost = await req.payload.create({
collection: 'post',
req,
@@ -165,11 +172,11 @@ export default buildConfig({
slug: 'myTask',
retries: {
shouldRestore: false,
- }
+ },
// ...
} as TaskConfig<'myTask'>,
- ]
- }
+ ],
+ },
})
```
@@ -191,16 +198,16 @@ export default buildConfig({
],
retries: {
shouldRestore: ({ input }) => {
- if(new Date(input.someDate) > new Date()) {
+ if (new Date(input.someDate) > new Date()) {
return false
}
return true
},
- }
+ },
// ...
} as TaskConfig<'myTask'>,
- ]
- }
+ ],
+ },
})
```
@@ -208,7 +215,6 @@ export default buildConfig({
You can run sub-tasks within an existing task, by using the `tasks` or `ìnlineTask` arguments passed to the task `handler` function:
-
```ts
export default buildConfig({
// ...
@@ -222,11 +228,10 @@ export default buildConfig({
inputSchema: [
{
name: 'text',
- type: 'text'
+ type: 'text',
},
],
handler: async ({ input, req, tasks, inlineTask }) => {
-
await inlineTask('Sub Task 1', {
task: () => {
// Do something
@@ -243,9 +248,9 @@ export default buildConfig({
return {
output: {},
}
- }
+ },
} as TaskConfig<'parentTask'>,
- ]
- }
+ ],
+ },
})
```
diff --git a/docs/jobs-queue/workflows.mdx b/docs/jobs-queue/workflows.mdx
index e66c689bfe..e41a5cdc45 100644
--- a/docs/jobs-queue/workflows.mdx
+++ b/docs/jobs-queue/workflows.mdx
@@ -7,7 +7,8 @@ keywords: jobs queue, application framework, typescript, node, react, nextjs
---
- A **"Workflow"** is an optional way to *combine multiple tasks together* in a way that can be gracefully retried from the point of failure.
+ A **"Workflow"** is an optional way to *combine multiple tasks together* in a
+ way that can be gracefully retried from the point of failure.
They're most helpful when you have multiple tasks in a row, and you want to configure each task to be able to be retried if they fail.
@@ -22,15 +23,15 @@ However, importantly, tasks that have successfully been completed will simply re
To define a JS-based workflow, simply add a workflow to the `jobs.workflows` array in your Payload config. A workflow consists of the following fields:
-| Option | Description |
-| --------------------------- | -------------------------------------------------------------------------------- |
-| `slug` | Define a slug-based name for this workflow. This slug needs to be unique among both tasks and workflows.|
-| `handler` | The function that should be responsible for running the workflow. You can either pass a string-based path to the workflow function file, or workflow job function itself. If you are using large dependencies within your workflow, you might prefer to pass the string path because that will avoid bundling large dependencies in your Next.js app. Passing a string path is an advanced feature that may require a sophisticated build pipeline in order to work. |
-| `inputSchema` | Define the input field schema - payload will generate a type for this schema. |
-| `interfaceName` | You can use interfaceName to change the name of the interface that is generated for this workflow. By default, this is "Workflow" + the capitalized workflow slug. |
-| `label` | Define a human-friendly label for this workflow. |
-| `queue` | Optionally, define the queue name that this workflow should be tied to. Defaults to "default". |
-| `retries` | You can define `retries` on the workflow level, which will enforce that the workflow can only fail up to that number of retries. If a task does not have retries specified, it will inherit the retry count as specified on the workflow. You can specify `0` as `workflow` retries, which will disregard all `task` retry specifications and fail the entire workflow on any task failure. You can leave `workflow` retries as undefined, in which case, the workflow will respect what each task dictates as their own retry count. By default this is undefined, meaning workflows retries are defined by their tasks |
+| Option | Description |
+| --------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
+| `slug` | Define a slug-based name for this workflow. This slug needs to be unique among both tasks and workflows. |
+| `handler` | The function that should be responsible for running the workflow. You can either pass a string-based path to the workflow function file, or workflow job function itself. If you are using large dependencies within your workflow, you might prefer to pass the string path because that will avoid bundling large dependencies in your Next.js app. Passing a string path is an advanced feature that may require a sophisticated build pipeline in order to work. |
+| `inputSchema` | Define the input field schema - payload will generate a type for this schema. |
+| `interfaceName` | You can use interfaceName to change the name of the interface that is generated for this workflow. By default, this is "Workflow" + the capitalized workflow slug. |
+| `label` | Define a human-friendly label for this workflow. |
+| `queue` | Optionally, define the queue name that this workflow should be tied to. Defaults to "default". |
+| `retries` | You can define `retries` on the workflow level, which will enforce that the workflow can only fail up to that number of retries. If a task does not have retries specified, it will inherit the retry count as specified on the workflow. You can specify `0` as `workflow` retries, which will disregard all `task` retry specifications and fail the entire workflow on any task failure. You can leave `workflow` retries as undefined, in which case, the workflow will respect what each task dictates as their own retry count. By default this is undefined, meaning workflows retries are defined by their tasks |
Example:
diff --git a/docs/live-preview/client.mdx b/docs/live-preview/client.mdx
index 5c107c20e7..9dd2784a50 100644
--- a/docs/live-preview/client.mdx
+++ b/docs/live-preview/client.mdx
@@ -7,7 +7,9 @@ keywords: live preview, frontend, react, next.js, vue, nuxt.js, svelte, hook, us
---
- If your front-end application supports Server Components like the [Next.js App Router](https://nextjs.org/docs/app), etc., we suggest setting up [server-side Live Preview](./server) instead.
+ If your front-end application supports Server Components like the [Next.js App
+ Router](https://nextjs.org/docs/app), etc., we suggest setting up [server-side
+ Live Preview](./server) instead.
While using Live Preview, the [Admin Panel](../admin/overview) emits a new `window.postMessage` event every time your document has changed. Your front-end application can listen for these events and re-render accordingly.
@@ -18,12 +20,12 @@ By default, all hooks accept the following args:
| Path | Description |
| ------------------ | -------------------------------------------------------------------------------------- |
-| **`serverURL`** * | The URL of your Payload server. |
+| **`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._
+_\* An asterisk denotes that a property is required._
And return the following values:
@@ -33,15 +35,19 @@ And return the following values:
| **`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`.
- It 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](../queries/depth) for more information.
+ It 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](../queries/depth) for
+ more information.
## Frameworks
@@ -89,8 +95,9 @@ export const PageClient: React.FC<{
```
- **Reminder:**
- If you are using [React Server Components](https://react.dev/reference/rsc/server-components), we strongly suggest setting up [server-side Live Preview](./server) instead.
+ **Reminder:** If you are using [React Server
+ Components](https://react.dev/reference/rsc/server-components), we strongly
+ suggest setting up [server-side Live Preview](./server) instead.
### Vue
@@ -140,19 +147,19 @@ 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. |
-| **`isLivePreviewEvent`** | Checks if a `MessageEvent` originates from the Admin Panel and is a Live Preview event, i.e. debounced form state. |
+| 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. |
+| **`isLivePreviewEvent`** | Checks if a `MessageEvent` originates from the Admin Panel and is a Live Preview event, i.e. debounced form state. |
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. |
+| **`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`. |
@@ -233,8 +240,9 @@ 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
diff --git a/docs/live-preview/frontend.mdx b/docs/live-preview/frontend.mdx
index 14416e3ce7..8cae270f1c 100644
--- a/docs/live-preview/frontend.mdx
+++ b/docs/live-preview/frontend.mdx
@@ -12,5 +12,7 @@ There are two ways to use Live Preview in your own application depending on whet
- [Client-side Live Preview](./client)
- We suggest using server-side Live Preview if your framework supports Server Components, it is both simpler to setup and more performant to run than the client-side alternative.
+ We suggest using server-side Live Preview if your framework supports Server
+ Components, it is both simpler to setup and more performant to run than the
+ client-side alternative.
diff --git a/docs/live-preview/overview.mdx b/docs/live-preview/overview.mdx
index 6a940f8c86..74556e0a66 100644
--- a/docs/live-preview/overview.mdx
+++ b/docs/live-preview/overview.mdx
@@ -22,16 +22,19 @@ const config = buildConfig({
// highlight-start
livePreview: {
url: 'http://localhost:3000',
- collections: ['pages']
+ collections: ['pages'],
},
// highlight-end
- }
+ },
})
```
- **Reminder:**
- Alternatively, you can define the `admin.livePreview` property on individual [Collection Admin Configs](../configuration/collections#admin-options) and [Global Admin Configs](../configuration/globals#admin-options). Settings defined here will be merged into the top-level as overrides.
+ **Reminder:** Alternatively, you can define the `admin.livePreview` property
+ on individual [Collection Admin
+ Configs](../configuration/collections#admin-options) and [Global Admin
+ Configs](../configuration/globals#admin-options). Settings defined here will
+ be merged into the top-level as overrides.
## Options
@@ -42,12 +45,12 @@ The following options are available:
| 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). |
+| **`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._
+_\* An asterisk denotes that a property is required._
### URL
@@ -66,7 +69,7 @@ const config = buildConfig({
url: 'http://localhost:3000', // highlight-line
collections: ['pages'],
},
- }
+ },
})
```
@@ -101,13 +104,13 @@ const config = buildConfig({
The following arguments are provided to the `url` function:
-| Path | Description |
-| ------------------ | ----------------------------------------------------------------------------------------------------------------- |
-| **`data`** | The data of the Document being edited. This includes changes that have not yet been saved. |
-| **`locale`** | The locale currently being edited (if applicable). [More details](../configuration/localization). |
-| **`collectionConfig`** | The Collection Admin Config of the Document being edited. [More details](../configuration/collections#admin-options). |
-| **`globalConfig`** | The Global Admin Config of the Document being edited. [More details](../configuration/globals#admin-options). |
-| **`req`** | The Payload Request object. |
+| Path | Description |
+| ---------------------- | --------------------------------------------------------------------------------------------------------------------- |
+| **`data`** | The data of the Document being edited. This includes changes that have not yet been saved. |
+| **`locale`** | The locale currently being edited (if applicable). [More details](../configuration/localization). |
+| **`collectionConfig`** | The Collection Admin Config of the Document being edited. [More details](../configuration/collections#admin-options). |
+| **`globalConfig`** | The Global Admin Config of the Document being edited. [More details](../configuration/globals#admin-options). |
+| **`req`** | The Payload Request object. |
You can return either an absolute URL or relative URL from this function. If you don't know the URL of your frontend at build-time, you can return a relative URL, and in that case, Payload will automatically construct an absolute URL by injecting the protocol, domain, and port from your browser window. Returning a relative URL is helpful for platforms like Vercel where you may have preview deployment URLs that are unknown at build time.
@@ -143,7 +146,7 @@ const config = buildConfig({
],
// highlight-end
},
- }
+ },
})
```
@@ -151,12 +154,12 @@ The following options are available for each breakpoint:
| 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. |
+| **`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._
+_\* An asterisk denotes that a property is required._
The "Responsive" option is always available in the drop-down and requires no additional configuration. This is the default breakpoint that will be used on initial load. This option styles the iframe with a width and height of `100%` so that it fills the screen at its maximum size and automatically resizes as the window changes size.
diff --git a/docs/live-preview/server.mdx b/docs/live-preview/server.mdx
index 6a754ffdff..48745ac3e8 100644
--- a/docs/live-preview/server.mdx
+++ b/docs/live-preview/server.mdx
@@ -7,13 +7,20 @@ keywords: live preview, frontend, react, next.js, vue, nuxt.js, svelte, hook, us
---
- Server-side Live Preview is only for front-end frameworks that support the concept of Server Components, i.e. [React Server Components](https://react.dev/reference/rsc/server-components). If your front-end application is built with a client-side framework like the [Next.js Pages Router](https://nextjs.org/docs/pages), [React Router](https://reactrouter.com), [Vue 3](https://vuejs.org), etc., see [client-side Live Preview](./client).
+ Server-side Live Preview is only for front-end frameworks that support the
+ concept of Server Components, i.e. [React Server
+ Components](https://react.dev/reference/rsc/server-components). If your
+ front-end application is built with a client-side framework like the [Next.js
+ Pages Router](https://nextjs.org/docs/pages), [React
+ Router](https://reactrouter.com), [Vue 3](https://vuejs.org), etc., see
+ [client-side Live Preview](./client).
Server-side Live Preview works by making a roundtrip to the server every time your document is saved, i.e. draft save, autosave, or publish. While using Live Preview, the Admin Panel emits a new `window.postMessage` event which your front-end application can use to invoke this process. In Next.js, this means simply calling `router.refresh()` which will hydrate the HTML using new data straight from the [Local API](../local-api/overview).
- It is recommended that you enable [Autosave](../versions/autosave) alongside Live Preview to make the experience feel more responsive.
+ It is recommended that you enable [Autosave](../versions/autosave) alongside
+ Live Preview to make the experience feel more responsive.
If your front-end application is built with [React](#react), you can use the `RefreshRouteOnChange` function that Payload provides. In the future, all other major frameworks like Vue and Svelte will be officially supported. If you are using any of these frameworks today, you can still integrate with Live Preview yourself using the underlying tooling that Payload provides. See [building your own router refresh component](#building-your-own-router-refresh-component) for more information.
@@ -43,7 +50,7 @@ export default async function Page() {
const page = await payload.findByID({
collection: 'pages',
id: '123',
- draft: true
+ draft: true,
})
return (
@@ -87,10 +94,10 @@ npm install @payloadcms/live-preview
This package provides the following functions:
-| Path | Description |
-| --------------------- | ------------------------------------------------------------------------------------------------------------------------------------------ |
-| **`ready`** | Sends a `window.postMessage` event to the Admin Panel to indicate that the front-end is ready to receive messages. |
-| **`isDocumentEvent`** | Checks if a `MessageEvent` originates from the Admin Panel and is a document-level event, i.e. draft save, autosave, publish, etc. |
+| Path | Description |
+| --------------------- | ---------------------------------------------------------------------------------------------------------------------------------- |
+| **`ready`** | Sends a `window.postMessage` event to the Admin Panel to indicate that the front-end is ready to receive messages. |
+| **`isDocumentEvent`** | Checks if a `MessageEvent` originates from the Admin Panel and is a document-level event, i.e. draft save, autosave, publish, etc. |
With these functions, you can build your own hook using your front-end framework of choice:
diff --git a/docs/local-api/outside-nextjs.mdx b/docs/local-api/outside-nextjs.mdx
index 70c5418207..4b2758c193 100644
--- a/docs/local-api/outside-nextjs.mdx
+++ b/docs/local-api/outside-nextjs.mdx
@@ -9,9 +9,9 @@ keywords: local api, config, configuration, documentation, Content Management Sy
Payload can be used completely outside of Next.js which is helpful in cases like running scripts, using Payload in a separate backend service, or using Payload's Local API to fetch your data directly from your database in other frontend frameworks like SvelteKit, Remix, Nuxt, and similar.
- **Note:**
-
- Payload and all of its official packages are fully ESM. If you want to use Payload within your own projects, make sure you are writing your scripts in ESM format or dynamically importing the Payload Config.
+ **Note:** Payload and all of its official packages are fully ESM. If you want
+ to use Payload within your own projects, make sure you are writing your
+ scripts in ESM format or dynamically importing the Payload Config.
## Importing the Payload Config outside of Next.js
@@ -32,8 +32,8 @@ const seed = async () => {
collection: 'users',
data: {
email: 'dev@payloadcms.com',
- password: 'some-password'
- }
+ password: 'some-password',
+ },
})
const page = await payload.create({
@@ -41,7 +41,7 @@ const seed = async () => {
data: {
title: 'My Homepage',
// other data to seed here
- }
+ },
})
}
@@ -67,6 +67,7 @@ If you encounter import-related errors, you have 2 options:
#### Option 1: enable swc mode by appending `--use-swc` to the `payload` command:
Example:
+
```sh
payload run src/seed.ts --use-swc
```
diff --git a/docs/local-api/overview.mdx b/docs/local-api/overview.mdx
index fd4601e2e7..fd3b746de7 100644
--- a/docs/local-api/overview.mdx
+++ b/docs/local-api/overview.mdx
@@ -11,7 +11,8 @@ The Payload Local API gives you the ability to execute the same operations that
**Tip:**
- The Local API is incredibly powerful when used in React Server Components and other similar server-side contexts. With other headless CMS, you need to request your data from third-party servers via an HTTP layer, which can add significant loading time to your server-rendered pages. With Payload, you don't have to leave your server to gather the data you need. It can be incredibly fast and is definitely a game changer.
+The Local API is incredibly powerful when used in React Server Components and other similar server-side contexts. With other headless CMS, you need to request your data from third-party servers via an HTTP layer, which can add significant loading time to your server-rendered pages. With Payload, you don't have to leave your server to gather the data you need. It can be incredibly fast and is definitely a game changer.
+
Here are some common examples of how you can use the Local API:
@@ -32,7 +33,9 @@ In most places within Payload itself, you can access `payload` directly from the
Example:
```ts
-const afterChangeHook: CollectionAfterChangeHook = async ({ req: { payload } }) => {
+const afterChangeHook: CollectionAfterChangeHook = async ({
+ req: { payload },
+}) => {
const posts = await payload.find({
collection: 'posts',
})
@@ -94,8 +97,9 @@ const post = await payload.find({
**Note:**
- By default, all access control checks are disabled in the Local API, but you can re-enable them if
- you'd like, as well as pass a specific user to run the operation with.
+By default, all access control checks are disabled in the Local API, but you can re-enable them if
+you'd like, as well as pass a specific user to run the operation with.
+
## Collections
@@ -325,7 +329,7 @@ available:
// responseHeaders: { ... } // returned headers from the response
// }
-const result = await payload.auth({headers})
+const result = await payload.auth({ headers })
```
### Login
diff --git a/docs/migration-guide/overview.mdx b/docs/migration-guide/overview.mdx
index fa3687d011..16d57fb944 100644
--- a/docs/migration-guide/overview.mdx
+++ b/docs/migration-guide/overview.mdx
@@ -42,88 +42,89 @@ For more details, see the [Documentation](https://payloadcms.com/docs/getting-st
1. **Install new dependencies of Payload, Next.js and React**:
- Refer to the package.json file made in the create-payload-app, including peerDependencies, devDependencies, and dependencies. The core package and plugins require all versions to be synced. Previously, on 2.x it was possible to be running the latest version of payload 2.x with an older version of db-mongodb for example. This is no longer the case.
+ Refer to the package.json file made in the create-payload-app, including peerDependencies, devDependencies, and dependencies. The core package and plugins require all versions to be synced. Previously, on 2.x it was possible to be running the latest version of payload 2.x with an older version of db-mongodb for example. This is no longer the case.
- ```bash
- pnpm i next react react-dom payload @payloadcms/ui @payloadcms/next
- ```
+ ```bash
+ pnpm i next react react-dom payload @payloadcms/ui @payloadcms/next
+ ```
- Also install the other @payloadcms packages specific to the plugins and adapters you are using. Depending on your project, these may include:
- - @payloadcms/db-mongodb
- - @payloadcms/db-postgres
- - @payloadcms/richtext-slate
- - @payloadcms/richtext-lexical
- - @payloadcms/plugin-form-builder
- - @payloadcms/plugin-nested-docs
- - @payloadcms/plugin-redirects
- - @payloadcms/plugin-relationship
- - @payloadcms/plugin-search
- - @payloadcms/plugin-sentry
- - @payloadcms/plugin-seo
- - @payloadcms/plugin-stripe
- - @payloadcms/plugin-cloud-storage - Read [More](#@payloadcms/plugin-cloud-storage).
+ Also install the other @payloadcms packages specific to the plugins and adapters you are using. Depending on your project, these may include:
+
+ - @payloadcms/db-mongodb
+ - @payloadcms/db-postgres
+ - @payloadcms/richtext-slate
+ - @payloadcms/richtext-lexical
+ - @payloadcms/plugin-form-builder
+ - @payloadcms/plugin-nested-docs
+ - @payloadcms/plugin-redirects
+ - @payloadcms/plugin-relationship
+ - @payloadcms/plugin-search
+ - @payloadcms/plugin-sentry
+ - @payloadcms/plugin-seo
+ - @payloadcms/plugin-stripe
+ - @payloadcms/plugin-cloud-storage - Read [More](#@payloadcms/plugin-cloud-storage).
1. Uninstall deprecated packages:
- ```bash
- pnpm remove express nodemon @payloadcms/bundler-webpack @payloadcms/bundler-vite
- ```
+ ```bash
+ pnpm remove express nodemon @payloadcms/bundler-webpack @payloadcms/bundler-vite
+ ```
1. Database Adapter Migrations
- _If you have existing data_ and are using the MongoDB or Postgres adapters, you will need to run the database migrations to ensure your database schema is up-to-date.
+ _If you have existing data_ and are using the MongoDB or Postgres adapters, you will need to run the database migrations to ensure your database schema is up-to-date.
- - [postgres](https://github.com/payloadcms/payload/releases/tag/v3.0.0-beta.39)
- - [mongodb](https://github.com/payloadcms/payload/releases/tag/v3.0.0-beta.131)
+ - [postgres](https://github.com/payloadcms/payload/releases/tag/v3.0.0-beta.39)
+ - [mongodb](https://github.com/payloadcms/payload/releases/tag/v3.0.0-beta.131)
-2. For Payload Cloud users, the plugin has changed.
+1. For Payload Cloud users, the plugin has changed.
- Uninstall the old package:
+ Uninstall the old package:
- ```bash
- pnpm remove @payloadcms/plugin-cloud
- ```
+ ```bash
+ pnpm remove @payloadcms/plugin-cloud
+ ```
- Install the new package:
+ Install the new package:
- ```bash
- pnpm i @payloadcms/payload-cloud
- ```
+ ```bash
+ pnpm i @payloadcms/payload-cloud
+ ```
- ```diff
- // payload.config.ts
- - import { payloadCloud } from '@payloadcms/plugin-cloud'
- + import { payloadCloudPlugin } from '@payloadcms/payload-cloud'
+ ```diff
+ // payload.config.ts
+ - import { payloadCloud } from '@payloadcms/plugin-cloud'
+ + import { payloadCloudPlugin } from '@payloadcms/payload-cloud'
- buildConfig({
- // ...
- plugins: [
- - payloadCloud()
- + payloadCloudPlugin()
- ]
- })
- ```
+ buildConfig({
+ // ...
+ plugins: [
+ - payloadCloud()
+ + payloadCloudPlugin()
+ ]
+ })
+ ```
-3. **Optional** sharp dependency
+1. **Optional** sharp dependency
If you have upload enabled collections that use `formatOptions`, `imageSizes`, or `resizeOptions`—payload expects to have `sharp` installed. In 2.0 this was a dependency was installed for you. Now it is only installed if needed. If you have any of these options set, you will need to install `sharp` and add it to your payload.config.ts:
- ```bash
- pnpm i sharp
- ```
+ ```bash
+ pnpm i sharp
+ ```
- ```diff
- // payload.config.ts
- import sharp from 'sharp'
- buildConfig({
- // ...
- + sharp,
- })
- ```
+ ```diff
+ // payload.config.ts
+ import sharp from 'sharp'
+ buildConfig({
+ // ...
+ + sharp,
+ })
+ ```
## Breaking Changes
-1. Delete the `admin.bundler` property from your Payload Config. Payload no longer bundles the Admin Panel. Instead, we rely directly on Next.js for bundling.
+1. Delete the `admin.bundler` property from your Payload Config. Payload no longer bundles the Admin Panel. Instead, we rely directly on Next.js for bundling.
```diff
// payload.config.ts
@@ -140,7 +141,7 @@ For more details, see the [Documentation](https://payloadcms.com/docs/getting-st
This also means that the `@payloadcms/bundler-webpack` and `@payloadcms/bundler-vite` packages have been deprecated. You can completely uninstall those from your project by removing them from your `package.json` file and re-running your package manager’s installation process, i.e. `pnpm i`.
-1. Add the `secret` property to your Payload Config. This used to be set in the `payload.init()` function of your `server.ts` file. Instead, move it to `payload.config.ts`:
+1. Add the `secret` property to your Payload Config. This used to be set in the `payload.init()` function of your `server.ts` file. Instead, move it to `payload.config.ts`:
```diff
// payload.config.ts
@@ -151,7 +152,7 @@ For more details, see the [Documentation](https://payloadcms.com/docs/getting-st
})
```
-1. Environment variables prefixed with `PAYLOAD_PUBLIC` will no longer be available on the client. In order to access them on the client, those will now have to be prefixed with `NEXT_PUBLIC` instead.
+1. Environment variables prefixed with `PAYLOAD_PUBLIC` will no longer be available on the client. In order to access them on the client, those will now have to be prefixed with `NEXT_PUBLIC` instead.
```diff
'use client'
@@ -161,14 +162,14 @@ For more details, see the [Documentation](https://payloadcms.com/docs/getting-st
For more details, see the [Documentation](https://payloadcms.com/docs/configuration/environment-vars).
-1. The `req` object used to extend the [Express Request](https://expressjs.com/), but now extends the [Web Request](https://developer.mozilla.org/en-US/docs/Web/API/Request). You may need to update your code accordingly to reflect this change. For example:
+1. The `req` object used to extend the [Express Request](https://expressjs.com/), but now extends the [Web Request](https://developer.mozilla.org/en-US/docs/Web/API/Request). You may need to update your code accordingly to reflect this change. For example:
```diff
- req.headers['content-type']
+ req.headers.get('content-type')
```
-1. The `admin.css` and `admin.scss` properties in the Payload Config have been removed.
+1. The `admin.css` and `admin.scss` properties in the Payload Config have been removed.
```diff
// payload.config.ts
@@ -188,35 +189,35 @@ For more details, see the [Documentation](https://payloadcms.com/docs/getting-st
1. For most use cases, you can simply customize the file located at `(payload)/custom.scss`. You can import or add your own styles here, such as for Tailwind.
1. For plugins author, you can use a Custom Provider at `admin.components.providers` to import your stylesheet:
- ```tsx
- // payload.config.js
+ ```tsx
+ // payload.config.js
- //...
- admin: {
- components: {
- providers: [
- MyProvider: './providers/MyProvider.tsx'
- ]
- }
- },
- //...
+ //...
+ admin: {
+ components: {
+ providers: [
+ MyProvider: './providers/MyProvider.tsx'
+ ]
+ }
+ },
+ //...
- // providers/MyProvider.tsx
+ // providers/MyProvider.tsx
- 'use client'
- import React from 'react'
- import './globals.css'
+ 'use client'
+ import React from 'react'
+ import './globals.css'
- export const MyProvider: React.FC<{children?: any}= ({ children }) ={
- return (
-
- {children}
-
- )
- }
- ```
+ export const MyProvider: React.FC<{children?: any}= ({ children }) ={
+ return (
+
+ {children}
+
+ )
+ }
+ ```
-1. The `admin.indexHTML` property has been removed. Delete this from your Payload Config.
+1. The `admin.indexHTML` property has been removed. Delete this from your Payload Config.
```diff
// payload.config.ts
@@ -230,7 +231,7 @@ For more details, see the [Documentation](https://payloadcms.com/docs/getting-st
})
```
-1. The `collection.admin.hooks` property has been removed. Instead, use the new `beforeDuplicate` field-level hook which take the usual field hook arguments.
+1. The `collection.admin.hooks` property has been removed. Instead, use the new `beforeDuplicate` field-level hook which take the usual field hook arguments.
```diff
// collections/Posts.ts
@@ -262,9 +263,9 @@ For more details, see the [Documentation](https://payloadcms.com/docs/getting-st
}
```
-1. Fields with `unique: true` now automatically be appended with “- Copy” through the new `admin.beforeDuplicate` field hooks (see previous bullet).
+1. Fields with `unique: true` now automatically be appended with “- Copy” through the new `admin.beforeDuplicate` field hooks (see previous bullet).
-1. The `upload.staticDir` property must now be an absolute path. Before it would attempt to use the location of the Payload Config and merge the relative path set for staticDir.
+1. The `upload.staticDir` property must now be an absolute path. Before it would attempt to use the location of the Payload Config and merge the relative path set for staticDir.
```diff
// collections/Media.ts
@@ -284,7 +285,7 @@ For more details, see the [Documentation](https://payloadcms.com/docs/getting-st
}
```
-1. The `upload.staticURL` property has been removed. If you were using this format URLs when using an external provider, you can leverage the `generateFileURL` functions in order to do the same.
+1. The `upload.staticURL` property has been removed. If you were using this format URLs when using an external provider, you can leverage the `generateFileURL` functions in order to do the same.
```diff
// collections/Media.ts
@@ -298,7 +299,7 @@ For more details, see the [Documentation](https://payloadcms.com/docs/getting-st
}
```
-1. The `admin.favicon` property is now `admin.icons` and the types have changed:
+1. The `admin.favicon` property is now `admin.icons` and the types have changed:
```diff
// payload.config.ts
@@ -318,7 +319,7 @@ For more details, see the [Documentation](https://payloadcms.com/docs/getting-st
For more details, see the [Documentation](https://payloadcms.com/docs/admin/metadata#icons).
-1. The `admin.meta.ogImage` property has been replaced by `admin.meta.openGraph.images`:
+1. The `admin.meta.ogImage` property has been replaced by `admin.meta.openGraph.images`:
```diff
// payload.config.ts
@@ -339,7 +340,7 @@ For more details, see the [Documentation](https://payloadcms.com/docs/getting-st
For more details, see the [Documentation](https://payloadcms.com/docs/admin/metadata#open-graph).
-1. The args of the `admin.livePreview.url` function have changed. It no longer receives `documentInfo` as an arg, and instead, now has `collectionConfig` and `globalConfig`.
+1. The args of the `admin.livePreview.url` function have changed. It no longer receives `documentInfo` as an arg, and instead, now has `collectionConfig` and `globalConfig`.
```diff
// payload.config.ts
@@ -358,7 +359,7 @@ For more details, see the [Documentation](https://payloadcms.com/docs/getting-st
})
```
-1. The `admin.logoutRoute` and `admin.inactivityRoute` properties have been consolidated into a single `admin.routes` property. To migrate, simply move those two keys as follows:
+1. The `admin.logoutRoute` and `admin.inactivityRoute` properties have been consolidated into a single `admin.routes` property. To migrate, simply move those two keys as follows:
```diff
// payload.config.ts
@@ -377,7 +378,7 @@ For more details, see the [Documentation](https://payloadcms.com/docs/getting-st
})
```
-1. The `custom` property in the Payload Config, i.e. Collections, Globals, and Fields is now **server only** and will **not** appear in the client-side bundle. To add custom properties to the client bundle, use the new `admin.custom` property, which will be available on _both_ the server and the client.
+1. The `custom` property in the Payload Config, i.e. Collections, Globals, and Fields is now **server only** and will **not** appear in the client-side bundle. To add custom properties to the client bundle, use the new `admin.custom` property, which will be available on _both_ the server and the client.
```diff
// payload.config.ts
@@ -395,7 +396,7 @@ For more details, see the [Documentation](https://payloadcms.com/docs/getting-st
})
```
-1. `hooks.afterError` is now an array of functions instead of a single function. The args have also been expanded. Read [More](https://payloadcms.com/docs/hooks/overview#root-hooks).
+1. `hooks.afterError` is now an array of functions instead of a single function. The args have also been expanded. Read [More](https://payloadcms.com/docs/hooks/overview#root-hooks).
```diff
// payload.config.ts
@@ -412,502 +413,503 @@ For more details, see the [Documentation](https://payloadcms.com/docs/getting-st
}
})
```
-1. The `./src/public` directory is now located directly at root level `./public` [see Next.js docs for details](https://nextjs.org/docs/pages/building-your-application/optimizing/static-assets)
+
+1. The `./src/public` directory is now located directly at root level `./public` [see Next.js docs for details](https://nextjs.org/docs/pages/building-your-application/optimizing/static-assets)
1. Payload now automatically removes `localized: true` property from sub-fields if a parent is localized, as it's redunant and unnecessary. If you have some existing data in this structure and you want to disable that behavior, you need to enable `allowLocalizedWithinLocalized` flag in your payload.config [read more in documentation](https://payloadcms.com/docs/configuration/overview#compatibility-flags), or create a migration script that aligns your data.
-Mongodb example for a link in a page layout.
-
- ```diff
- - layout.columns.en.link.en.type.en
- + layout.columns.en.link.type
- ```
+ Mongodb example for a link in a page layout.
+ ```diff
+ - layout.columns.en.link.en.type.en
+ + layout.columns.en.link.type
+ ```
## Custom Components
1. All Payload React components have been moved from the `payload` package to `@payloadcms/ui`. If you were previously importing components into your app from the `payload` package, for example to create Custom Components, you will need to change your import paths:
- ```diff
- - import { TextField, useField, etc. } from 'payload'
- + import { TextField, useField, etc. } from '@payloadcms/ui'
- ```
- *Note: for brevity, not _all_ modules are listed here*
+ ```diff
+ - import { TextField, useField, etc. } from 'payload'
+ + import { TextField, useField, etc. } from '@payloadcms/ui'
+ ```
+
+ _Note: for brevity, not *all* modules are listed here_
1. All Custom Components are now defined as _file paths_ instead of direct imports. If you are using Custom Components in your Payload Config, remove the imported module and point to the file's path instead:
- ```diff
- import { buildConfig } from 'payload'
- - import { MyComponent } from './src/components/Logout'
+ ```diff
+ import { buildConfig } from 'payload'
+ - import { MyComponent } from './src/components/Logout'
- const config = buildConfig({
- // ...
- admin: {
- components: {
- logout: {
- - Button: MyComponent,
- + Button: '/src/components/Logout#MyComponent'
- }
- }
- },
- })
- ```
+ const config = buildConfig({
+ // ...
+ admin: {
+ components: {
+ logout: {
+ - Button: MyComponent,
+ + Button: '/src/components/Logout#MyComponent'
+ }
+ }
+ },
+ })
+ ```
- For more details, see the [Documentation](https://payloadcms.com/docs/custom-components/overview#component-paths).
+ For more details, see the [Documentation](https://payloadcms.com/docs/custom-components/overview#component-paths).
1. All Custom Components are now server-rendered by default, and therefore, cannot use state or hooks directly. If you’re using Custom Components in your app that requires state or hooks, add the `'use client'` directive at the top of the file.
- ```diff
- // components/MyClientComponent.tsx
- + 'use client'
- import React, { useState } from 'react'
+ ```diff
+ // components/MyClientComponent.tsx
+ + 'use client'
+ import React, { useState } from 'react'
- export const MyClientComponent = () => {
- const [state, setState] = useState()
+ export const MyClientComponent = () => {
+ const [state, setState] = useState()
- return (
-
- {state}
-
- )
- }
- ```
+ return (
+
+ {state}
+
+ )
+ }
+ ```
- For more details, see the [Documentation](https://payloadcms.com/docs/custom-components/overview#client-components).
+ For more details, see the [Documentation](https://payloadcms.com/docs/custom-components/overview#client-components).
1. The `admin.description` property within Collection, Globals, and Fields no longer accepts a React Component. Instead, you must define it as a Custom Component.
- 1. For Collections, use the `admin.components.edit.Description` key:
+ 1. For Collections, use the `admin.components.edit.Description` key:
- ```diff
- // collections/Posts.ts
- import type { CollectionConfig } from 'payload'
- - import { MyCustomDescription } from '../components/MyCustomDescription'
+ ```diff
+ // collections/Posts.ts
+ import type { CollectionConfig } from 'payload'
+ - import { MyCustomDescription } from '../components/MyCustomDescription'
- export const PostsCollection: CollectionConfig = {
- slug: 'posts',
- admin: {
- - description: MyCustomDescription,
- + components: {
- + edit: {
- + Description: 'path/to/MyCustomDescription'
- + }
- + }
- }
- }
- ```
+ export const PostsCollection: CollectionConfig = {
+ slug: 'posts',
+ admin: {
+ - description: MyCustomDescription,
+ + components: {
+ + edit: {
+ + Description: 'path/to/MyCustomDescription'
+ + }
+ + }
+ }
+ }
+ ```
- 2. For Globals, use the `admin.components.elements.Description` key:
+ 2. For Globals, use the `admin.components.elements.Description` key:
- ```diff
- // globals/Site.ts
- import type { GlobalConfig } from 'payload'
- - import { MyCustomDescription } from '../components/MyCustomDescription'
+ ```diff
+ // globals/Site.ts
+ import type { GlobalConfig } from 'payload'
+ - import { MyCustomDescription } from '../components/MyCustomDescription'
- export const SiteGlobal: GlobalConfig = {
- slug: 'site',
- admin: {
- - description: MyCustomDescription,
- + components: {
- + elements: {
- + Description: 'path/to/MyCustomDescription'
- + }
- + }
- }
- }
- ```
+ export const SiteGlobal: GlobalConfig = {
+ slug: 'site',
+ admin: {
+ - description: MyCustomDescription,
+ + components: {
+ + elements: {
+ + Description: 'path/to/MyCustomDescription'
+ + }
+ + }
+ }
+ }
+ ```
- 3. For Fields, use the `admin.components.Description` key:
+ 3. For Fields, use the `admin.components.Description` key:
- ```diff
- // fields/MyField.ts
- import type { FieldConfig } from 'payload'
- - import { MyCustomDescription } from '../components/MyCustomDescription'
+ ```diff
+ // fields/MyField.ts
+ import type { FieldConfig } from 'payload'
+ - import { MyCustomDescription } from '../components/MyCustomDescription'
- export const MyField: FieldConfig = {
- type: 'text',
- admin: {
- - description: MyCustomDescription,
- + components: {
- + Description: 'path/to/MyCustomDescription'
- + }
- }
- }
- ```
+ export const MyField: FieldConfig = {
+ type: 'text',
+ admin: {
+ - description: MyCustomDescription,
+ + components: {
+ + Description: 'path/to/MyCustomDescription'
+ + }
+ }
+ }
+ ```
1. Array Field row labels and Collapsible Field label now _only_ accepts a React Component, and no longer accepts a plain string or record:
- ```diff
- // file: Collection.tsx
- import type { CollectionConfig } from 'payload'
- - import { MyCustomRowLabel } from './components/MyCustomRowLabel.tsx'
+ ```diff
+ // file: Collection.tsx
+ import type { CollectionConfig } from 'payload'
+ - import { MyCustomRowLabel } from './components/MyCustomRowLabel.tsx'
- export const MyCollection: CollectionConfig = {
- slug: 'my-collection',
- fields: [
- {
- name: 'my-array',
- type: 'array',
- admin: {
- components: {
- - RowLabel: 'My Array Row Label,
- + RowLabel: './components/RowLabel.ts'
- }
- },
- fields: [...]
- },
- {
- name: 'my-collapsible',
- type: 'collapsible',
- admin: {
- components: {
- - Label: 'My Collapsible Label',
- + Label: './components/RowLabel.ts'
- }
- },
- fields: [...]
- }
- ]
- }
- ```
+ export const MyCollection: CollectionConfig = {
+ slug: 'my-collection',
+ fields: [
+ {
+ name: 'my-array',
+ type: 'array',
+ admin: {
+ components: {
+ - RowLabel: 'My Array Row Label,
+ + RowLabel: './components/RowLabel.ts'
+ }
+ },
+ fields: [...]
+ },
+ {
+ name: 'my-collapsible',
+ type: 'collapsible',
+ admin: {
+ components: {
+ - Label: 'My Collapsible Label',
+ + Label: './components/RowLabel.ts'
+ }
+ },
+ fields: [...]
+ }
+ ]
+ }
+ ```
1. All default view keys are now camelcase:
- For example, for Root Views:
+ For example, for Root Views:
- ```diff
- // file: payload.config.ts
+ ```diff
+ // file: payload.config.ts
- import { buildConfig } from 'payload'
+ import { buildConfig } from 'payload'
- export default buildConfig({
- admin: {
- views: {
- - Account: ...
- + account: ...
- }
- })
- ```
+ export default buildConfig({
+ admin: {
+ views: {
+ - Account: ...
+ + account: ...
+ }
+ })
+ ```
- Or Document Views:
+ Or Document Views:
- ```diff
- // file: Collection.tsx
+ ```diff
+ // file: Collection.tsx
- import type { CollectionConfig } from 'payload'
+ import type { CollectionConfig } from 'payload'
- export const MyCollection: CollectionConfig = {
- slug: 'my-collection',
- admin: {
- views: {
- - Edit: {
- - Default: ...
- - }
- + edit: {
- + default: ...
- + }
- }
- }
- }
- ```
+ export const MyCollection: CollectionConfig = {
+ slug: 'my-collection',
+ admin: {
+ views: {
+ - Edit: {
+ - Default: ...
+ - }
+ + edit: {
+ + default: ...
+ + }
+ }
+ }
+ }
+ ```
1. Custom Views within the config no longer accept React Components directly, instead, you must use their `Component` property:
- ```diff
- // file: Collection.tsx
- import type { CollectionConfig } from 'payload'
- - import { MyCustomView } from './components/MyCustomView.tsx'
+ ```diff
+ // file: Collection.tsx
+ import type { CollectionConfig } from 'payload'
+ - import { MyCustomView } from './components/MyCustomView.tsx'
- export const MyCollection: CollectionConfig = {
- slug: 'my-collection',
- admin: {
- views: {
- - Edit: MyCustomView
- + edit: {
- + Component: './components/MyCustomView.tsx'
- + }
- }
- }
- }
- ```
+ export const MyCollection: CollectionConfig = {
+ slug: 'my-collection',
+ admin: {
+ views: {
+ - Edit: MyCustomView
+ + edit: {
+ + Component: './components/MyCustomView.tsx'
+ + }
+ }
+ }
+ }
+ ```
- This also means that Custom Root Views are no longer defined on the `edit` key. Instead, use the new `views.root` key:
+ This also means that Custom Root Views are no longer defined on the `edit` key. Instead, use the new `views.root` key:
- ```diff
- // file: Collection.tsx
- import type { CollectionConfig } from 'payload'
- - import { MyCustomRootView } from './components/MyCustomRootView.tsx'
+ ```diff
+ // file: Collection.tsx
+ import type { CollectionConfig } from 'payload'
+ - import { MyCustomRootView } from './components/MyCustomRootView.tsx'
- export const MyCollection: CollectionConfig = {
- slug: 'my-collection',
- admin: {
- views: {
- - Edit: MyCustomRootView
- edit: {
- + root: {
- + Component: './components/MyCustomRootView.tsx'
- + }
- }
- }
- }
- }
- ```
+ export const MyCollection: CollectionConfig = {
+ slug: 'my-collection',
+ admin: {
+ views: {
+ - Edit: MyCustomRootView
+ edit: {
+ + root: {
+ + Component: './components/MyCustomRootView.tsx'
+ + }
+ }
+ }
+ }
+ }
+ ```
1. The `href` and `isActive` functions on View Tabs no longer includes the `match` or `location` arguments. This is is a property specific to React Router, not Next.js. If you need to do URL matching similar to this, use a custom tab that fires of some hooks, i.e. `usePathname()` and run it through your own utility functions:
- ```diff
- // collections/Posts.ts
- import type { CollectionConfig } from 'payload'
+ ```diff
+ // collections/Posts.ts
+ import type { CollectionConfig } from 'payload'
- export const PostsCollection: CollectionConfig = {
- slug: 'posts',
- admin: {
- components: {
- views: {
- - Edit: {
- - Tab: {
- - isActive: ({ href, location, match }) => true,
- - href: ({ href, location, match }) => ''
- - },
- - },
- + edit: {
- + tab: {
- + isActive: ({ href }) => true,
- + href: ({ href }) => '' // or use a Custom Component (see below)
- + // Component: './path/to/CustomComponent.tsx'
- + }
- + },
- },
- },
- },
- }
- ```
+ export const PostsCollection: CollectionConfig = {
+ slug: 'posts',
+ admin: {
+ components: {
+ views: {
+ - Edit: {
+ - Tab: {
+ - isActive: ({ href, location, match }) => true,
+ - href: ({ href, location, match }) => ''
+ - },
+ - },
+ + edit: {
+ + tab: {
+ + isActive: ({ href }) => true,
+ + href: ({ href }) => '' // or use a Custom Component (see below)
+ + // Component: './path/to/CustomComponent.tsx'
+ + }
+ + },
+ },
+ },
+ },
+ }
+ ```
1. The `admin.components.views[key].Tab.pillLabel` has been replaced with `admin.components.views[key].tab.Pill`:
- ```diff
- // collections/Posts.ts
- import type { CollectionConfig } from 'payload'
+ ```diff
+ // collections/Posts.ts
+ import type { CollectionConfig } from 'payload'
- export const PostsCollection: CollectionConfig = {
- slug: 'posts',
- admin: {
- components: {
- - views: {
- - Edit: {
- - Tab: {
- - pillLabel: 'Hello, world!',
- - },
- - },
- + edit: {
- + tab: {
- + Pill: './path/to/CustomPill.tsx',
- + }
- + },
- },
- },
- },
- }
- ```
+ export const PostsCollection: CollectionConfig = {
+ slug: 'posts',
+ admin: {
+ components: {
+ - views: {
+ - Edit: {
+ - Tab: {
+ - pillLabel: 'Hello, world!',
+ - },
+ - },
+ + edit: {
+ + tab: {
+ + Pill: './path/to/CustomPill.tsx',
+ + }
+ + },
+ },
+ },
+ },
+ }
+ ```
1. `react-i18n` was removed, the `Trans` component from `react-i18n` has been replaced with a Payload-provided solution:
- ```diff
- 'use client'
- - import { Trans } from "react-i18n"
- + import { Translation } from "@payloadcms/ui"
+ ```diff
+ 'use client'
+ - import { Trans } from "react-i18n"
+ + import { Translation } from "@payloadcms/ui"
- // Example string to translate:
- // "loggedInChangePassword": "To change your password, go to your <0>account0> and edit your password there."
+ // Example string to translate:
+ // "loggedInChangePassword": "To change your password, go to your <0>account0> and edit your password there."
- export const MyComponent = () => {
- return (
- -
- - account
- -
+ export const MyComponent = () => {
+ return (
+ -
+ - account
+ -
- + ,
- + }}
- + />
- )
- }
- ```
+ + ,
+ + }}
+ + />
+ )
+ }
+ ```
## Endpoints
1. All endpoint handlers have changed. The args no longer include `res`, and `next`, and the return type now expects a valid HTTP [`Response`](https://developer.mozilla.org/en-US/docs/Web/API/Response) instead of `res.json`, `res.send`, etc.:
- ```diff
- // collections/Posts.ts
- import type { CollectionConfig } from 'payload'
+ ```diff
+ // collections/Posts.ts
+ import type { CollectionConfig } from 'payload'
- export const PostsCollection: CollectionConfig = {
- slug: 'posts',
- endpoints: [
- - {
- - path: '/whoami/:parameter',
- - method: 'post',
- - handler: (req, res) => {
- - res.json({
- - parameter: req.params.parameter,
- - name: req.body.name,
- - age: req.body.age,
- - })
- - }
- - },
- + {
- + path: '/whoami/:parameter',
- + method: 'post',
- + handler: (req) => {
- + return Response.json({
- + parameter: req.routeParams.parameter,
- + // ^^ `params` is now `routeParams`
- + name: req.data.name,
- + age: req.data.age,
- + })
- + }
- + }
- ]
- }
- ```
+ export const PostsCollection: CollectionConfig = {
+ slug: 'posts',
+ endpoints: [
+ - {
+ - path: '/whoami/:parameter',
+ - method: 'post',
+ - handler: (req, res) => {
+ - res.json({
+ - parameter: req.params.parameter,
+ - name: req.body.name,
+ - age: req.body.age,
+ - })
+ - }
+ - },
+ + {
+ + path: '/whoami/:parameter',
+ + method: 'post',
+ + handler: (req) => {
+ + return Response.json({
+ + parameter: req.routeParams.parameter,
+ + // ^^ `params` is now `routeParams`
+ + name: req.data.name,
+ + age: req.data.age,
+ + })
+ + }
+ + }
+ ]
+ }
+ ```
1. Endpoint handlers no longer resolves `data`, `locale`, or `fallbackLocale` for you on the request. Instead, you must resolve them yourself or use the Payload-provided utilities:
- ```diff
- // collections/Posts.ts
- import type { CollectionConfig } from 'payload'
- + import { addDataAndFileToRequest } from '@payloadcms/next/utilities'
- + import { addLocalesToRequest } from '@payloadcms/next/utilities'
+ ```diff
+ // collections/Posts.ts
+ import type { CollectionConfig } from 'payload'
+ + import { addDataAndFileToRequest } from '@payloadcms/next/utilities'
+ + import { addLocalesToRequest } from '@payloadcms/next/utilities'
- export const PostsCollection: CollectionConfig = {
- slug: 'posts',
- endpoints: [
- - {
- - path: '/whoami/:parameter',
- - method: 'post',
- - handler: async (req) => {
- - return Response.json({
- - name: req.data.name, // data will be undefined
- - })
- - }
- - },
- + {
- + path: '/whoami/:parameter',
- + method: 'post',
- + handler: async (req) => {
- + // mutates req, must be awaited
- + await addDataAndFileToRequest(req)
- + await addLocalesToRequest(req)
- +
- + return Response.json({
- + name: req.data.name, // data is now available
- + fallbackLocale: req.fallbackLocale,
- + locale: req.locale,
- + })
- + }
- + }
- ]
- }
- ```
+ export const PostsCollection: CollectionConfig = {
+ slug: 'posts',
+ endpoints: [
+ - {
+ - path: '/whoami/:parameter',
+ - method: 'post',
+ - handler: async (req) => {
+ - return Response.json({
+ - name: req.data.name, // data will be undefined
+ - })
+ - }
+ - },
+ + {
+ + path: '/whoami/:parameter',
+ + method: 'post',
+ + handler: async (req) => {
+ + // mutates req, must be awaited
+ + await addDataAndFileToRequest(req)
+ + await addLocalesToRequest(req)
+ +
+ + return Response.json({
+ + name: req.data.name, // data is now available
+ + fallbackLocale: req.fallbackLocale,
+ + locale: req.locale,
+ + })
+ + }
+ + }
+ ]
+ }
+ ```
## React Hooks
1. The `useTitle` hook has been consolidated into the `useDocumentInfo` hook. Instead, you can get title directly from document info context:
- ```diff
- 'use client'
- - import { useTitle } from 'payload'
- + import { useDocumentInfo } from '@payloadcms/ui'
+ ```diff
+ 'use client'
+ - import { useTitle } from 'payload'
+ + import { useDocumentInfo } from '@payloadcms/ui'
- export const MyComponent = () => {
- - const title = useTitle()
- + const { title } = useDocumentInfo()
+ export const MyComponent = () => {
+ - const title = useTitle()
+ + const { title } = useDocumentInfo()
- // ...
- }
- ```
+ // ...
+ }
+ ```
1. The `useDocumentInfo` hook no longer returns `collection` or `global`. Instead, various properties of the config are passed, like `collectionSlug` and `globalSlug`. You can use these to access a client-side config, if needed, through the `useConfig` hook (see next bullet).
- ```diff
- 'use client'
- import { useDocumentInfo } from '@payloadcms/ui'
+ ```diff
+ 'use client'
+ import { useDocumentInfo } from '@payloadcms/ui'
- export const MyComponent = () => {
- const {
- - collection,
- - global,
- + collectionSlug,
- + globalSlug
- } = useDocumentInfo()
+ export const MyComponent = () => {
+ const {
+ - collection,
+ - global,
+ + collectionSlug,
+ + globalSlug
+ } = useDocumentInfo()
- // ...
- }
- ```
+ // ...
+ }
+ ```
1. The `useConfig` hook now returns a `ClientConfig` and not a `SanitizedConfig`. This is because the config itself is not serializable and so it is not able to be thread through to the client. This means that all non-serializable props have been omitted from the Client Config, such as `db`, `bundler`, etc.
- ```diff
- 'use client'
- - import { useConfig } from 'payload'
- + import { useConfig } from '@payloadcms/ui'
+ ```diff
+ 'use client'
+ - import { useConfig } from 'payload'
+ + import { useConfig } from '@payloadcms/ui'
- export const MyComponent = () => {
- - const config = useConfig() // used to be a 'SanitizedConfig'
- + const { config } = useConfig() // now is a 'ClientConfig'
+ export const MyComponent = () => {
+ - const config = useConfig() // used to be a 'SanitizedConfig'
+ + const { config } = useConfig() // now is a 'ClientConfig'
- // ...
- }
- ```
+ // ...
+ }
+ ```
- For more details, see the [Documentation](https://payloadcms.com/docs/admin/custom-components/overview#accessing-the-payload-config).
+ For more details, see the [Documentation](https://payloadcms.com/docs/admin/custom-components/overview#accessing-the-payload-config).
1. The `useCollapsible` hook has had slight changes to its property names. `collapsed` is now `isCollapsed` and `withinCollapsible` is now `isWithinCollapsible`.
- ```diff
- 'use client'
- import { useCollapsible } from '@payloadcms/ui'
+ ```diff
+ 'use client'
+ import { useCollapsible } from '@payloadcms/ui'
- export const MyComponent = () => {
- - const { collapsed, withinCollapsible } = useCollapsible()
- + const { isCollapsed, isWithinCollapsible } = useCollapsible()
- }
- ```
+ export const MyComponent = () => {
+ - const { collapsed, withinCollapsible } = useCollapsible()
+ + const { isCollapsed, isWithinCollapsible } = useCollapsible()
+ }
+ ```
1. The `useTranslation` hook no longer takes any options, any translations using shorthand accessors will need to use the entire `group:key`
- ```diff
- 'use client'
- - import { useTranslation } from 'payload'
- + import { useTranslation } from '@payloadcms/ui'
+ ```diff
+ 'use client'
+ - import { useTranslation } from 'payload'
+ + import { useTranslation } from '@payloadcms/ui'
- export const MyComponent = () => {
- - const { i18n, t } = useTranslation('general')
- + const { i18n, t } = useTranslation()
+ export const MyComponent = () => {
+ - const { i18n, t } = useTranslation('general')
+ + const { i18n, t } = useTranslation()
- - return {t('cancel')}
- + return {t('general:cancel')}
- }
- ```
+ - return {t('cancel')}
+ + return {t('general:cancel')}
+ }
+ ```
## Types
1. The `Fields` type was renamed to `FormState` for improved semantics. If you were previously importing this type in your own application, simply change the import name:
- ```diff
- - import type { Fields } from 'payload'
- + import type { FormState } from 'payload'
- ```
+ ```diff
+ - import type { Fields } from 'payload'
+ + import type { FormState } from 'payload'
+ ```
1. The `BlockField` and related types have been renamed to `BlocksField` for semantic accuracy.
- ```diff
- - import type { BlockField, BlockFieldProps } from 'payload'
- + import type { BlocksField, BlocksFieldProps } from 'payload'
- ```
+ ```diff
+ - import type { BlockField, BlockFieldProps } from 'payload'
+ + import type { BlocksField, BlocksFieldProps } from 'payload'
+ ```
## Email Adapters
@@ -975,22 +977,22 @@ export default buildConfig({
## Plugins
-1. *All* plugins have been standardized to use _named exports_ (as opposed to default exports). Most also have a suffix of `Plugin` to make it clear what is being imported.
+1. _All_ plugins have been standardized to use _named exports_ (as opposed to default exports). Most also have a suffix of `Plugin` to make it clear what is being imported.
- ```diff
- - import seo from '@payloadcms/plugin-seo'
- + import { seoPlugin } from '@payloadcms/plugin-seo'
+ ```diff
+ - import seo from '@payloadcms/plugin-seo'
+ + import { seoPlugin } from '@payloadcms/plugin-seo'
- - import stripePlugin from '@payloadcms/plugin-stripe'
- + import { stripePlugin } from '@payloadcms/plugin-stripe'
+ - import stripePlugin from '@payloadcms/plugin-stripe'
+ + import { stripePlugin } from '@payloadcms/plugin-stripe'
- // and so on for every plugin
- ```
+ // and so on for every plugin
+ ```
## `@payloadcms/plugin-cloud-storage`
- The adapters that are exported from `@payloadcms/plugin-cloud-storage` (ie. `@payloadcms/plugin-cloud-storage/s3`) package have been removed.
-- New *standalone* packages have been created for each of the existing adapters. Please see the documentation for the one that you use.
+- New _standalone_ packages have been created for each of the existing adapters. Please see the documentation for the one that you use.
- `@payloadcms/plugin-cloud-storage` is still fully supported but should only to be used if you are providing a custom adapter that does not have a dedicated package.
- If you have created a custom adapter, the type must now provide a `name` property.
@@ -1051,63 +1053,63 @@ plugins: [
1. Field overrides for form and form submission collections now accept a function with a `defaultFields` inside the args instead of an array of config
- ```diff
- // payload.config.ts
- import { buildConfig } from 'payload'
- import { formBuilderPlugin } from '@payloadcms/plugin-form-builder'
+ ```diff
+ // payload.config.ts
+ import { buildConfig } from 'payload'
+ import { formBuilderPlugin } from '@payloadcms/plugin-form-builder'
- const config = buildConfig({
- // ...
- plugins: formBuilderPlugin({
- - fields: [
- - {
- - name: 'custom',
- - type: 'text',
- - }
- - ],
- + fields: ({ defaultFields }) => {
- + return [
- + ...defaultFields,
- + {
- + name: 'custom',
- + type: 'text',
- + },
- + ]
- + }
- })
- })
- ```
+ const config = buildConfig({
+ // ...
+ plugins: formBuilderPlugin({
+ - fields: [
+ - {
+ - name: 'custom',
+ - type: 'text',
+ - }
+ - ],
+ + fields: ({ defaultFields }) => {
+ + return [
+ + ...defaultFields,
+ + {
+ + name: 'custom',
+ + type: 'text',
+ + },
+ + ]
+ + }
+ })
+ })
+ ```
## `@payloadcms/plugin-redirects`
1. Field overrides for the redirects collection now accepts a function with a `defaultFields` inside the args instead of an array of config
- ```diff
- // payload.config.ts
- import { buildConfig } from 'payload'
- import { redirectsPlugin } from '@payloadcms/plugin-redirects'
+ ```diff
+ // payload.config.ts
+ import { buildConfig } from 'payload'
+ import { redirectsPlugin } from '@payloadcms/plugin-redirects'
- const config = buildConfig({
- // ...
- plugins: redirectsPlugin({
- - fields: [
- - {
- - name: 'custom',
- - type: 'text',
- - }
- - ],
- + fields: ({ defaultFields }) => {
- + return [
- + ...defaultFields,
- + {
- + name: 'custom',
- + type: 'text',
- + },
- + ]
- + }
- })
- })
- ```
+ const config = buildConfig({
+ // ...
+ plugins: redirectsPlugin({
+ - fields: [
+ - {
+ - name: 'custom',
+ - type: 'text',
+ - }
+ - ],
+ + fields: ({ defaultFields }) => {
+ + return [
+ + ...defaultFields,
+ + {
+ + name: 'custom',
+ + type: 'text',
+ + },
+ + ]
+ + }
+ })
+ })
+ ```
## `@payloadcms/richtext-lexical`
@@ -1134,6 +1136,7 @@ Payload reserves certain field names for internal use. Using any of the followin
### Auth-Related Reserved Names
These are restricted if your collection uses `auth: true` and does not have `disableAuthStrategy: true`:
+
- `salt`
- `hash`
- `apiKey` (when `auth.useAPIKey: true` is enabled)
diff --git a/docs/plugins/build-your-own.mdx b/docs/plugins/build-your-own.mdx
index 9c99082d4c..31ee685a1a 100644
--- a/docs/plugins/build-your-own.mdx
+++ b/docs/plugins/build-your-own.mdx
@@ -9,8 +9,8 @@ keywords: plugins, template, config, configuration, extensions, custom, document
Building your own [Payload Plugin](./overview) 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 [Plugin Template](#plugin-template) to get up and running quickly.
- To use the template, run `npx create-payload-app@latest --template plugin` directly in
- your terminal.
+ To use the template, run `npx create-payload-app@latest --template plugin`
+ directly in your terminal.
Our plugin template includes everything you need to build a full life-cycle plugin:
@@ -162,7 +162,6 @@ export const seed = async (payload: Payload): Promise => {
Now that we have our environment setup and dev project ready to go - it's time to build the plugin!
-
```
import type { Config } from 'payload'
@@ -210,7 +209,6 @@ export const samplePlugin =
To reiterate, the essence of a [Payload Plugin](./overview) is simply to extend the [Payload Config](../configuration/overview) - and that is exactly what we are doing in this file.
-
### 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,6 +242,7 @@ config.hooks = {
```
### Extending functions
+
Function properties cannot use spread syntax. The way to extend them is to execute the existing function if it exists and then run your additional functionality.
Here is an example extending the `onInit` property:
diff --git a/docs/plugins/form-builder.mdx b/docs/plugins/form-builder.mdx
index 641df8c52f..b87c2da29f 100644
--- a/docs/plugins/form-builder.mdx
+++ b/docs/plugins/form-builder.mdx
@@ -16,9 +16,10 @@ Forms can be as simple or complex as you need, from a basic contact form, to a m
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
+ 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.
@@ -124,10 +125,13 @@ For full types with `beforeChangeParams`, you can import the types from the plug
```ts
import type { BeforeEmail } from '@payloadcms/plugin-form-builder'
// Your generated FormSubmission type
-import type {FormSubmission} from '@payload-types'
+import type { FormSubmission } from '@payload-types'
// Pass it through and 'data' or 'originalDoc' will now be typed
-const beforeEmail: BeforeEmail = (emailsToSend, beforeChangeParams) => {
+const beforeEmail: BeforeEmail = (
+ emailsToSend,
+ beforeChangeParams,
+) => {
// modify the emails in any way before they are sent
return emails.map((email) => ({
...email,
@@ -155,7 +159,11 @@ Override anything on the `forms` collection by sending a [Payload Collection Con
Note that the `fields` property is a function that receives the default fields and returns an array of fields. This is because the `fields` property is a special case that is merged with the default fields, rather than replacing them. This allows you to map over default fields and modify them as needed.
-Good to know: The form collection is publicly available to read by default. The emails field is locked for authenticated users only. If you have any frontend users you should override the access permissions for both the collection and the emails field to make sure you don't leak out any private emails.
+ Good to know: The form collection is publicly available to read by default.
+ The emails field is locked for authenticated users only. If you have any
+ frontend users you should override the access permissions for both the
+ collection and the emails field to make sure you don't leak out any private
+ emails.
```ts
@@ -187,10 +195,11 @@ Override anything on the `form-submissions` collection by sending a [Payload Col
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 once it has been created, or read a submission unless they have permission. You can
+ 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 once
+ it has been created, or read a submission unless they have permission. You can
override this behavior or any other property as needed.
@@ -232,7 +241,9 @@ formBuilderPlugin({
// ...
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,
@@ -248,9 +259,9 @@ formBuilderPlugin({
Each field represents a form input. To override default settings pass either a boolean value or a partial [Payload Block](https://payloadcms.com/docs/fields/blocks) _keyed to the block's slug_. See [Field Overrides](#field-overrides) for more details on how to do this.
- **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`.
+ **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`.
### Text
@@ -458,7 +469,6 @@ Below are some common troubleshooting tips. To help other developers, please con

-


diff --git a/docs/plugins/multi-tenant.mdx b/docs/plugins/multi-tenant.mdx
index 85ee3de109..2e72a33ad7 100644
--- a/docs/plugins/multi-tenant.mdx
+++ b/docs/plugins/multi-tenant.mdx
@@ -10,12 +10,12 @@ keywords: plugins, multi-tenant, multi-tenancy, plugin, payload, cms, seo, index
This plugin sets up multi-tenancy for your application from within your [Admin Panel](../admin/overview). It does so by adding a `tenant` field to all specified collections. Your front-end application can then query data by tenant. You must add the Tenants collection so you control what fields are available for each tenant.
-
This plugin is completely open-source and the [source code can be found
- here](https://github.com/payloadcms/payload/tree/main/packages/plugin-multi-tenant). 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
+ here](https://github.com/payloadcms/payload/tree/main/packages/plugin-multi-tenant).
+ 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%multi-tenant&template=bug_report.md&title=plugin-multi-tenant%3A)
with as much detail as possible.
@@ -32,10 +32,11 @@ This plugin sets up multi-tenancy for your application from within your [Admin P
**Warning**
- By default this plugin cleans up documents when a tenant is deleted. You should ensure you have
- strong access control on your tenants collection to prevent deletions by unauthorized users.
+By default this plugin cleans up documents when a tenant is deleted. You should ensure you have
+strong access control on your tenants collection to prevent deletions by unauthorized users.
+
+You can disabled this behavior by setting `cleanupAfterTenantDelete` to `false` in the plugin options.
- You can disabled this behavior by setting `cleanupAfterTenantDelete` to `false` in the plugin options.
## Installation
@@ -253,7 +254,6 @@ export default config
The plugin scaffolds out everything you will need to separate data by tenant. You can use the `tenant` field to filter data from enabled collections in your front-end application.
-
In your frontend you can query and constrain data by tenant with the following:
```tsx
@@ -332,15 +332,17 @@ type ContextType = {
setPreventRefreshOnChange: React.Dispatch>
/**
* Sets the selected tenant ID
- *
+ *
* @param args.id - The ID of the tenant to select
* @param args.refresh - Whether to refresh the page after changing the tenant
*/
- setTenant: (args: { id: number | string | undefined; refresh?: boolean }) => void
+ setTenant: (args: {
+ id: number | string | undefined
+ refresh?: boolean
+ }) => void
}
```
-
## Examples
The [Examples Directory](https://github.com/payloadcms/payload/tree/main/examples) also contains an official [Multi-Tenant](https://github.com/payloadcms/payload/tree/main/examples/multi-tenant) example.
diff --git a/docs/plugins/nested-docs.mdx b/docs/plugins/nested-docs.mdx
index a941ce2721..630a5143a6 100644
--- a/docs/plugins/nested-docs.mdx
+++ b/docs/plugins/nested-docs.mdx
@@ -26,9 +26,10 @@ 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
+ 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.
@@ -79,7 +80,8 @@ const config = buildConfig({
nestedDocsPlugin({
collections: ['pages'],
generateLabel: (_, doc) => doc.title,
- generateURL: (docs) => docs.reduce((url, doc) => `${url}/${doc.slug}`, ''),
+ generateURL: (docs) =>
+ docs.reduce((url, doc) => `${url}/${doc.slug}`, ''),
}),
],
})
@@ -165,9 +167,10 @@ 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
@@ -217,8 +220,9 @@ const examplePageConfig: CollectionConfig = {
**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
@@ -232,7 +236,11 @@ the [Localization](https://payloadcms.com/docs/configuration/localization) docs.
All types can be directly imported:
```ts
-import { PluginConfig, GenerateURL, GenerateLabel } from '@payloadcms/plugin-nested-docs/types'
+import {
+ PluginConfig,
+ GenerateURL,
+ GenerateLabel,
+} from '@payloadcms/plugin-nested-docs/types'
```
## Examples
diff --git a/docs/plugins/overview.mdx b/docs/plugins/overview.mdx
index 8fe3447c19..96b2430896 100644
--- a/docs/plugins/overview.mdx
+++ b/docs/plugins/overview.mdx
@@ -28,9 +28,9 @@ const config = buildConfig({
Writing Plugins is no more complex than writing regular JavaScript. If you know the basic concept of [callback functions](https://developer.mozilla.org/en-US/docs/Glossary/Callback_function) or how [spread syntax](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Spread_syntax) works, and are up to speed with Payload concepts, then writing a plugin will be a breeze.
- Because we rely on a simple config-based structure, Payload Plugins simply take in an
- existing config and returns a _modified_ config with new fields, hooks, collections, admin views, or
- anything else you can think of.
+ Because we rely on a simple config-based structure, Payload Plugins simply
+ take in an existing config and returns a _modified_ config with new fields,
+ hooks, collections, admin views, or anything else you can think of.
**Example use cases:**
@@ -61,7 +61,9 @@ You can also [build your own plugin](./build-your-own) to easily extend Payload'
Plugins are changing every day, so be sure to check back often to see what new plugins may have been added. If you have a specific plugin you would like to see, please feel free to start a new [Discussion](https://github.com/payloadcms/payload/discussions).
- For a complete list of Official Plugins, visit the [Packages Directory](https://github.com/payloadcms/payload/tree/main/packages) of the [Payload Monorepo](https://github.com/payloadcms/payload).
+ For a complete list of Official Plugins, visit the [Packages
+ Directory](https://github.com/payloadcms/payload/tree/main/packages) of the
+ [Payload Monorepo](https://github.com/payloadcms/payload).
## Community Plugins
@@ -71,7 +73,9 @@ Community Plugins are those that are maintained entirely by outside contributors
Some plugins have become so widely used that they are adopted as an [Official Plugin](#official-plugins), such as the [Lexical Plugin](https://github.com/AlessioGr/payload-plugin-lexical). If you have a plugin that you think should be an Official Plugin, please feel free to start a new [Discussion](https://github.com/payloadcms/payload/discussions).
- For maintainers building plugins for others to use, please add the `payload-plugin` topic on [GitHub](https://github.com/topics/payload-plugin) to help others find it.
+ For maintainers building plugins for others to use, please add the
+ `payload-plugin` topic on [GitHub](https://github.com/topics/payload-plugin)
+ to help others find it.
## Example
@@ -85,15 +89,15 @@ import { addLastModified } from './addLastModified.ts'
const config = buildConfig({
// ...
// highlight-start
- plugins: [
- addLastModified,
- ],
+ plugins: [addLastModified],
// highlight-end
})
```
- Payload Plugins are executed _after_ the incoming config is validated, but before it is sanitized and has had default options merged in. After all plugins are executed, the full config with all plugins will be sanitized.
+ Payload Plugins are executed _after_ the incoming config is validated, but
+ before it is sanitized and has had default options merged in. After all
+ plugins are executed, the full config with all plugins will be sanitized.
Here is an example what the `addLastModified` plugin from above might look like. It adds a `lastModifiedBy` field to all Payload collections. For full details, see [how to build your own plugin](./build-your-own).
@@ -105,8 +109,8 @@ export const addLastModified: Plugin = (incomingConfig: Config): Config => {
// Find all incoming auth-enabled collections
// so we can create a lastModifiedBy relationship field
// to all auth collections
- const authEnabledCollections = incomingConfig.collections.filter((collection) =>
- Boolean(collection.auth),
+ const authEnabledCollections = incomingConfig.collections.filter(
+ (collection) => Boolean(collection.auth),
)
// Spread the existing config
@@ -147,6 +151,6 @@ export const addLastModified: Plugin = (incomingConfig: Config): Config => {
```
- **Reminder:**
- See [how to build your own plugin](./build-your-own) for a more in-depth explication on how create your own Payload Plugin.
+ **Reminder:** See [how to build your own plugin](./build-your-own) for a more
+ in-depth explication on how create your own Payload Plugin.
diff --git a/docs/plugins/redirects.mdx b/docs/plugins/redirects.mdx
index acd74b9a55..3fbc624d58 100644
--- a/docs/plugins/redirects.mdx
+++ b/docs/plugins/redirects.mdx
@@ -14,9 +14,10 @@ For example, if you have a page at `/about` and you want to change it to `/about
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
+ 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.
@@ -62,12 +63,12 @@ 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. |
-| `redirectTypes` | `string[]` | Provide an array of redirects if you want to provide options for the type of redirects to be supported. |
-| `redirectTypeFieldOverride` | `Field` | A partial Field config that allows you to override the Redirect Type field if enabled above. |
+| 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. |
+| `redirectTypes` | `string[]` | Provide an array of redirects if you want to provide options for the type of redirects to be supported. |
+| `redirectTypeFieldOverride` | `Field` | A partial Field config that allows you to override the Redirect Type field if enabled above. |
Note that the fields in overrides take a function that receives the default fields and returns an array of fields. This allows you to add fields to the collection.
diff --git a/docs/plugins/search.mdx b/docs/plugins/search.mdx
index 24413b77fc..868e87b5b7 100644
--- a/docs/plugins/search.mdx
+++ b/docs/plugins/search.mdx
@@ -18,9 +18,10 @@ This plugin is a great way to implement a fast, immersive search experience such
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
+ 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.
diff --git a/docs/plugins/sentry.mdx b/docs/plugins/sentry.mdx
index 2c800452f9..b23e97330b 100644
--- a/docs/plugins/sentry.mdx
+++ b/docs/plugins/sentry.mdx
@@ -15,7 +15,8 @@ This plugin allows you to integrate [Sentry](https://sentry.io/) seamlessly with
Sentry is a powerful error tracking and performance monitoring tool that helps developers identify, diagnose, and resolve issues in their applications.
- Sentry does smart stuff with error data to make bugs easier to find and fix. - [sentry.io](https://sentry.io/)
+ Sentry does smart stuff with error data to make bugs easier to find and fix. -
+ [sentry.io](https://sentry.io/)
This multi-faceted software offers a range of features that will help you manage errors with greater ease and ultimately ensure your application is running smoothly:
@@ -31,7 +32,13 @@ This multi-faceted software offers a range of features that will help you manage
- **Integrations**: Connects with various tools and services for enhanced workflow and issue management
- This plugin is completely open-source and the [source code can be found here](https://github.com/payloadcms/payload/tree/main/packages/plugin-sentry). 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-sentry%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-sentry).
+ 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-sentry%3A)
+ with as much detail as possible.
## Installation
@@ -43,12 +50,15 @@ Install the plugin using any JavaScript package manager like [pnpm](https://pnpm
```
## Sentry for Next.js setup
+
This plugin requires to complete the [Sentry + Next.js setup](https://docs.sentry.io/platforms/javascript/guides/nextjs/) before.
You can use either the [automatic setup](https://docs.sentry.io/platforms/javascript/guides/nextjs/#install) with the installation wizard:
+
```sh
npx @sentry/wizard@latest -i nextjs
```
+
Or the [Manual Setup](https://docs.sentry.io/platforms/javascript/guides/nextjs/manual-setup/)
## Basic Usage
@@ -81,7 +91,8 @@ export default config
The `Sentry` instance
- Make sure to complete the [Sentry for Next.js Setup](#sentry-for-nextjs-setup) before.
+ Make sure to complete the [Sentry for Next.js Setup](#sentry-for-nextjs-setup)
+ before.
- `enabled`: boolean | optional
diff --git a/docs/plugins/seo.mdx b/docs/plugins/seo.mdx
index 4804d31279..bacf884211 100644
--- a/docs/plugins/seo.mdx
+++ b/docs/plugins/seo.mdx
@@ -15,7 +15,13 @@ 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 the 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
@@ -96,8 +102,8 @@ A function that takes in the default fields via an object and expects an array o
{
name: 'customField',
type: 'text',
- }
- ]
+ },
+ ],
})
}
```
@@ -111,7 +117,10 @@ 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](../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`
@@ -130,25 +139,25 @@ A function that allows you to return any meta title, including from the document
All "generate" functions receive the following arguments:
-| Argument | Description |
-| --- | --- |
-| **`collectionConfig`** | The configuration of the collection. |
-| **`collectionSlug`** | The slug of the collection. |
-| **`doc`** | The data of the current document. |
-| **`docPermissions`** | The permissions of the document. |
-| **`globalConfig`** | The configuration of the global. |
-| **`globalSlug`** | The slug of the global. |
-| **`hasPublishPermission`** | Whether the user has permission to publish the document. |
-| **`hasSavePermission`** | Whether the user has permission to save the document. |
-| **`id`** | The ID of the document. |
-| **`initialData`** | The initial data of the document. |
-| **`initialState`** | The initial state of the document. |
-| **`locale`** | The locale of the document. |
-| **`preferencesKey`** | The preferences key of the document. |
-| **`publishedDoc`** | The published document. |
-| **`req`** | The Payload request object containing `user`, `payload`, `i18n`, etc. |
-| **`title`** | The title of the document. |
-| **`versionsCount`** | The number of versions of the document. |
+| Argument | Description |
+| -------------------------- | --------------------------------------------------------------------- |
+| **`collectionConfig`** | The configuration of the collection. |
+| **`collectionSlug`** | The slug of the collection. |
+| **`doc`** | The data of the current document. |
+| **`docPermissions`** | The permissions of the document. |
+| **`globalConfig`** | The configuration of the global. |
+| **`globalSlug`** | The slug of the global. |
+| **`hasPublishPermission`** | Whether the user has permission to publish the document. |
+| **`hasSavePermission`** | Whether the user has permission to save the document. |
+| **`id`** | The ID of the document. |
+| **`initialData`** | The initial data of the document. |
+| **`initialState`** | The initial state of the document. |
+| **`locale`** | The locale of the document. |
+| **`preferencesKey`** | The preferences key of the document. |
+| **`publishedDoc`** | The published document. |
+| **`req`** | The Payload request object containing `user`, `payload`, `i18n`, etc. |
+| **`title`** | The title of the document. |
+| **`versionsCount`** | The number of versions of the document. |
##### `generateDescription`
@@ -218,11 +227,20 @@ Rename the meta group interface name that is generated for TypeScript and GraphQ
There is the option to directly import any of the fields from the plugin so that you can include them anywhere as needed.
- You will still need to configure the plugin in the Payload Config in order to configure the generation functions. Since these fields are imported and used directly, they don't have access to the plugin config so they may need additional arguments to work the same way.
+ You will still need to configure the plugin in the Payload Config in order to
+ configure the generation functions. Since these fields are imported and used
+ directly, they don't have access to the plugin config so they may need
+ additional arguments to work the same way.
```ts
-import { MetaDescriptionField, MetaImageField, MetaTitleField, OverviewField, PreviewField } from '@payloadcms/plugin-seo/fields'
+import {
+ MetaDescriptionField,
+ MetaImageField,
+ MetaTitleField,
+ OverviewField,
+ PreviewField,
+} from '@payloadcms/plugin-seo/fields'
// Used as fields
MetaImageField({
@@ -261,7 +279,9 @@ OverviewField({
```
- Tip: You can override the length rules by changing the minLength and maxLength props on the fields. In the case of the OverviewField you can use `titleOverrides` and `descriptionOverrides` to override the length rules.
+ Tip: You can override the length rules by changing the minLength and maxLength
+ props on the fields. In the case of the OverviewField you can use
+ `titleOverrides` and `descriptionOverrides` to override the length rules.
## TypeScript
@@ -280,9 +300,9 @@ import type {
You can then pass the collections from your generated Payload types into the generation types, for example:
```ts
-import type { Page } from './payload-types.ts';
+import type { Page } from './payload-types.ts'
-import type { GenerateTitle } from '@payloadcms/plugin-seo/types';
+import type { GenerateTitle } from '@payloadcms/plugin-seo/types'
const generateTitle: GenerateTitle = async ({ doc, locale }) => {
return `Website.com — ${doc?.title}`
@@ -295,4 +315,4 @@ The [Templates Directory](https://github.com/payloadcms/payload/tree/main/templa
## Screenshots
-
\ No newline at end of file
+
diff --git a/docs/plugins/stripe.mdx b/docs/plugins/stripe.mdx
index 5b3edb9d37..bb7a4141a8 100644
--- a/docs/plugins/stripe.mdx
+++ b/docs/plugins/stripe.mdx
@@ -18,9 +18,10 @@ The beauty of this plugin is the entirety of your application's content and busi
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
+ 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.
@@ -65,14 +66,14 @@ export default config
| Option | Type | Default | Description |
| ------------------------------ | ------------------ | ----------- | ------------------------------------------------------------------------------------------------------------------------ |
-| `stripeSecretKey` * | string | `undefined` | Your Stripe secret key |
+| `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 or 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._
+_\* An asterisk denotes that a property is required._
## Endpoints
@@ -111,14 +112,16 @@ If you need to proxy the API server-side, use the [stripeProxy](#node) function.
**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.
+
**Warning:**
- Opening the REST proxy endpoint in production is a potential security risk. Authenticated users will have open access to the Stripe REST API. In production, open your own endpoint and use the [stripeProxy](#node) function to proxy the Stripe API server-side.
+Opening the REST proxy endpoint in production is a potential security risk. Authenticated users will have open access to the Stripe REST API. In production, open your own endpoint and use the [stripeProxy](#node) function to proxy the Stripe API server-side.
+
## Webhooks
@@ -182,7 +185,9 @@ On the server you should interface with Stripe directly using the [stripe](https
import Stripe from 'stripe'
const stripeSecretKey = process.env.STRIPE_SECRET_KEY
-const stripe = new Stripe(stripeSecretKey, { apiVersion: '2022-08-01' })
+const stripe = new Stripe(stripeSecretKey, {
+ apiVersion: '2022-08-01',
+})
export const MyFunction = async () => {
try {
@@ -234,8 +239,9 @@ 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
@@ -270,10 +276,11 @@ 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:
diff --git a/docs/production/deployment.mdx b/docs/production/deployment.mdx
index a89f5557da..018f290e78 100644
--- a/docs/production/deployment.mdx
+++ b/docs/production/deployment.mdx
@@ -7,8 +7,8 @@ keywords: deployment, production, config, configuration, documentation, Content
---
- So you've developed a Payload app, it's fully tested, and running great locally. Now it's time to
- launch. **Awesome! Great work!** Now, what's next?
+ So you've developed a Payload app, it's fully tested, and running great
+ locally. Now it's time to launch. **Awesome! Great work!** Now, what's next?
There are many ways to deploy Payload to a production environment. When evaluating how you will deploy Payload, you need
@@ -62,11 +62,12 @@ wield that power responsibly before deploying to Production.
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
- **
+**
+only appropriate users
+**
+
+to perform appropriate actions.
- to perform appropriate actions.
### Running in Production
@@ -134,8 +135,9 @@ perpetually.
**Warning:**
- If you rely on Payload's **Upload** functionality, make sure you either use a host
- with a persistent filesystem or have an integration with a third-party file host like Amazon S3.
+If you rely on Payload's **Upload** functionality, make sure you either use a host
+with a persistent filesystem or have an integration with a third-party file host like Amazon S3.
+
### Using cloud storage providers
diff --git a/docs/queries/depth.mdx b/docs/queries/depth.mdx
index b5ace9b5cd..0fe9a128e6 100644
--- a/docs/queries/depth.mdx
+++ b/docs/queries/depth.mdx
@@ -34,8 +34,8 @@ But with a `depth` of `1`, the response might look like this:
```
- **Important:**
- Depth has no effect in the [GraphQL API](../graphql/overview), because there, depth is based on the shape of your queries.
+ **Important:** Depth has no effect in the [GraphQL API](../graphql/overview),
+ because there, depth is based on the shape of your queries.
## Local API
@@ -56,8 +56,8 @@ const getPosts = async (payload: Payload) => {
```
- **Reminder:**
- This is the same for [Globals](../configuration/globals) using the `findGlobal` operation.
+ **Reminder:** This is the same for [Globals](../configuration/globals) using
+ the `findGlobal` operation.
## REST API
@@ -71,8 +71,8 @@ fetch('https://localhost:3000/api/posts?depth=2') // highlight-line
```
- **Reminder:**
- This is the same for [Globals](../configuration/globals) using the `/api/globals` endpoint.
+ **Reminder:** This is the same for [Globals](../configuration/globals) using
+ the `/api/globals` endpoint.
## Max Depth
diff --git a/docs/queries/overview.mdx b/docs/queries/overview.mdx
index 30cbd7631d..b3354d65af 100644
--- a/docs/queries/overview.mdx
+++ b/docs/queries/overview.mdx
@@ -31,35 +31,36 @@ const query: Where = {
_The exact query syntax will depend on the API you are using, but the concepts are the same across all APIs. [More details](#writing-queries)._
- **Tip:**
- You can also use queries within [Access Control](../access-control/overview) functions.
+ **Tip:** You can also use queries within [Access
+ Control](../access-control/overview) functions.
## Operators
The following operators are available for use in queries:
-| Operator | Description |
-| -------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
-| `equals` | The value must be exactly equal. |
-| `not_equals` | The query will return all documents where the value is not equal. |
-| `greater_than` | For numeric or date-based fields. |
-| `greater_than_equal` | For numeric or date-based fields. |
-| `less_than` | For numeric or date-based fields. |
-| `less_than_equal` | For numeric or date-based fields. |
-| `like` | Case-insensitive string must be present. If string of words, all words must be present, in any order. |
-| `contains` | Must contain the value entered, case-insensitive. |
-| `in` | The value must be found within the provided comma-delimited list of values. |
-| `not_in` | The value must NOT be within the provided comma-delimited list of values. |
-| `all` | The value must contain all values provided in the comma-delimited list. Note: currently this operator is supported only with the MongoDB adapter. |
-| `exists` | Only return documents where the value either exists (`true`) or does not exist (`false`). |
-| `near` | For distance related to a [Point Field](../fields/point) comma separated as `, , , `. |
-| `within` | For [Point Fields](../fields/point) to filter documents based on whether points are inside of the given area defined in GeoJSON. [Example](../fields/point#querying-within) |
-| `intersects` | For [Point Fields](../fields/point) to filter documents based on whether points intersect with the given area defined in GeoJSON. [Example](../fields/point#querying-intersects) |
+| Operator | Description |
+| -------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
+| `equals` | The value must be exactly equal. |
+| `not_equals` | The query will return all documents where the value is not equal. |
+| `greater_than` | For numeric or date-based fields. |
+| `greater_than_equal` | For numeric or date-based fields. |
+| `less_than` | For numeric or date-based fields. |
+| `less_than_equal` | For numeric or date-based fields. |
+| `like` | Case-insensitive string must be present. If string of words, all words must be present, in any order. |
+| `contains` | Must contain the value entered, case-insensitive. |
+| `in` | The value must be found within the provided comma-delimited list of values. |
+| `not_in` | The value must NOT be within the provided comma-delimited list of values. |
+| `all` | The value must contain all values provided in the comma-delimited list. Note: currently this operator is supported only with the MongoDB adapter. |
+| `exists` | Only return documents where the value either exists (`true`) or does not exist (`false`). |
+| `near` | For distance related to a [Point Field](../fields/point) comma separated as `, , , `. |
+| `within` | For [Point Fields](../fields/point) to filter documents based on whether points are inside of the given area defined in GeoJSON. [Example](../fields/point#querying-within) |
+| `intersects` | For [Point Fields](../fields/point) to filter documents based on whether points intersect with the given area defined in GeoJSON. [Example](../fields/point#querying-intersects) |
- **Tip:**
- If you know your users will be querying on certain fields a lot, add `index: true` to the Field Config. This will speed up searches using that field immensely.
+ **Tip:** If you know your users will be querying on certain fields a lot, add
+ `index: true` to the Field Config. This will speed up searches using that
+ field immensely.
### And / Or Logic
@@ -72,14 +73,16 @@ To join queries, use the `and` or `or` keys in your query object:
import type { Where } from 'payload'
const query: Where = {
- or: [ // highlight-line
+ or: [
+ // highlight-line
{
color: {
equals: 'mint',
},
},
{
- and: [ // highlight-line
+ and: [
+ // highlight-line
{
color: {
equals: 'white',
@@ -183,7 +186,9 @@ const getPosts = async () => {
{ addQueryPrefix: true },
)
- const response = await fetch(`http://localhost:3000/api/posts${stringifiedQuery}`)
+ const response = await fetch(
+ `http://localhost:3000/api/posts${stringifiedQuery}`,
+ )
// Continue to handle the response below...
}
```
diff --git a/docs/queries/select.mdx b/docs/queries/select.mdx
index ed0535cb6b..abc8a516bb 100644
--- a/docs/queries/select.mdx
+++ b/docs/queries/select.mdx
@@ -25,7 +25,7 @@ const getPosts = async (payload: Payload) => {
text: true,
// select a specific field from group
group: {
- number: true
+ number: true,
},
// select all fields from array
array: true,
@@ -43,8 +43,8 @@ const getPosts = async (payload: Payload) => {
select: {
array: false,
group: {
- number: false
- }
+ number: false,
+ },
}, // highlight-line
})
@@ -52,20 +52,23 @@ const getPosts = async (payload: Payload) => {
}
```
-
- **Important:**
- To perform querying with `select` efficiently, Payload implements your `select` query on the database level. Because of that, your `beforeRead` and `afterRead` hooks may not receive the full `doc`.
- To ensure that some fields are always selected for your hooks / access control, regardless of the `select` query you can use `forceSelect` collection config property.
+ **Important:** To perform querying with `select` efficiently, Payload
+ implements your `select` query on the database level. Because of that, your
+ `beforeRead` and `afterRead` hooks may not receive the full `doc`. To ensure
+ that some fields are always selected for your hooks / access control,
+ regardless of the `select` query you can use `forceSelect` collection config
+ property.
-
## REST API
To specify select in the [REST API](../rest-api/overview), you can use the `select` parameter in your query:
```ts
-fetch('https://localhost:3000/api/posts?select[color]=true&select[group][number]=true') // highlight-line
+fetch(
+ 'https://localhost:3000/api/posts?select[color]=true&select[group][number]=true',
+) // highlight-line
.then((res) => res.json())
.then((data) => console.log(data))
```
@@ -81,8 +84,8 @@ import type { Where } from 'payload'
const select: Where = {
text: true,
group: {
- number: true
- }
+ number: true,
+ },
// This query could be much more complex
// and QS would handle it beautifully
}
@@ -95,17 +98,18 @@ const getPosts = async () => {
{ addQueryPrefix: true },
)
- const response = await fetch(`http://localhost:3000/api/posts${stringifiedQuery}`)
+ const response = await fetch(
+ `http://localhost:3000/api/posts${stringifiedQuery}`,
+ )
// Continue to handle the response below...
}
```
- **Reminder:**
- This is the same for [Globals](../configuration/globals) using the `/api/globals` endpoint.
+ **Reminder:** This is the same for [Globals](../configuration/globals) using
+ the `/api/globals` endpoint.
-
## defaultPopulate collection config property
The `defaultPopulate` property allows you specify which fields to select when populating the collection from another document.
@@ -139,8 +143,10 @@ export const Pages: CollectionConfig<'pages'> = {
```
- **Important:**
- When using `defaultPopulate` on a collection with [Uploads](/docs/fields/upload) enabled and you want to select the `url` field, it is important to specify `filename: true` as well, otherwise Payload will not be able to construct the correct file URL, instead returning `url: null`.
+ **Important:** When using `defaultPopulate` on a collection with
+ [Uploads](/docs/fields/upload) enabled and you want to select the `url` field,
+ it is important to specify `filename: true` as well, otherwise Payload will
+ not be able to construct the correct file URL, instead returning `url: null`.
## populate
@@ -175,4 +181,4 @@ const getPosts = async (payload: Payload) => {
fetch('https://localhost:3000/api/posts?populate[pages][text]=true') // highlight-line
.then((res) => res.json())
.then((data) => console.log(data))
-```
\ No newline at end of file
+```
diff --git a/docs/queries/sort.mdx b/docs/queries/sort.mdx
index b2985c3dc3..01ecfc076c 100644
--- a/docs/queries/sort.mdx
+++ b/docs/queries/sort.mdx
@@ -11,8 +11,8 @@ Documents in Payload can be easily sorted by a specific [Field](../fields/overvi
Because sorting is handled by the database, the field cannot be a [Virtual Field](https://payloadcms.com/blog/learn-how-virtual-fields-can-help-solve-common-cms-challenges). It must be stored in the database to be searchable.
- **Tip:**
- For performance reasons, it is recommended to enable `index: true` for the fields that will be sorted upon. [More details](../fields/overview).
+ **Tip:** For performance reasons, it is recommended to enable `index: true`
+ for the fields that will be sorted upon. [More details](../fields/overview).
## Local API
diff --git a/docs/rest-api/overview.mdx b/docs/rest-api/overview.mdx
index 11b7b2f747..35dc101dfa 100644
--- a/docs/rest-api/overview.mdx
+++ b/docs/rest-api/overview.mdx
@@ -7,7 +7,8 @@ keywords: rest, api, documentation, Content Management System, cms, headless, ja
---
- A fully functional REST API is automatically generated from your Collection and Global configs.
+ A fully functional REST API is automatically generated from your Collection
+ and Global configs.
The REST API is a fully functional HTTP client that allows you to interact with your Documents in a RESTful manner. It supports all CRUD operations and is equipped with automatic pagination, depth, and sorting.
@@ -60,195 +61,195 @@ Note: Collection slugs must be formatted in kebab-case
The \`find\` endpoint supports the following additional query parameters:
-- [sort](/docs/queries/overview#sort) - sort by field
-- [where](/docs/queries/overview) - pass a where query to constrain returned documents
-- [limit](/docs/queries/pagination#pagination-controls) - limit the returned documents to a certain number
-- [page](/docs/queries/pagination#pagination-controls) - get a specific page of documents
- `
- },
- },
- {
- operation: "Find By ID",
- method: "GET",
- path: "/api/{collection-slug}/{id}",
- description: "Find a specific document by ID",
- example: {
- slug: "findByID",
- req: true,
- res: {
- id: "644a5c24cc1383022535fc7c",
- title: "Home",
- content: "REST API examples",
- slug: "home",
- createdAt: "2023-04-27T11:27:32.419Z",
- updatedAt: "2023-04-27T11:27:32.419Z",
- },
- },
- },
- {
- operation: "Count",
- method: "GET",
- path: "/api/{collection-slug}/count",
- description: "Count the documents",
- example: {
- slug: "count",
- req: true,
- res: {
- totalDocs: 10
- },
- },
- },
- {
- operation: "Create",
- method: "POST",
- path: "/api/{collection-slug}",
- description: "Create a new document",
- example: {
- slug: "createDocument",
- req: {
- credentials: true,
- headers: true,
- body: {
- title: "New page",
- content: "Here is some content",
- },
- },
- res: {
- message: "Page successfully created.",
- doc: {
- id: "644ba34c86359864f9535932",
- title: "New page",
- content: "Here is some content",
- slug: "new-page",
- createdAt: "2023-04-28T10:43:24.466Z",
- updatedAt: "2023-04-28T10:43:24.466Z",
- },
- },
- },
- },
- {
- operation: "Update",
- method: "PATCH",
- path: "/api/{collection-slug}",
- description: "Update all documents matching the where query",
- example: {
- slug: "updateDocument",
- req: {
- credentials: true,
- query: true,
- headers: true,
- body: {
- title: "I have been updated!",
- },
- },
- res: {
- docs: [
- {
- id: "644ba34c86359864f9535932",
- title: "I have been updated!",
- content: "Here is some content",
- slug: "new-page",
- createdAt: "2023-04-28T10:43:24.466Z",
- updatedAt: "2023-04-28T10:45:23.724Z",
- },
- ],
- errors: [],
- },
- },
- },
- {
- operation: "Update By ID",
- method: "PATCH",
- path: "/api/{collection-slug}/{id}",
- description: "Update a document by ID",
- example: {
- slug: "updateDocumentByID",
- req: {
- credentials: true,
- headers: true,
- body: {
- title: "I have been updated by ID!",
- categories: "example-uuid",
- tags: {
- relationTo: "location",
- value: "another-example-uuid",
- },
- },
- },
- res: {
- message: "Updated successfully.",
- doc: {
- id: "644a5c24cc1383022535fc7c",
- title: "I have been updated by ID!",
- content: "REST API examples",
- categories: {
- id: "example-uuid",
- name: "Test Category",
- },
- tags: [
- {
- relationTo: "location",
- value: {
- id: "another-example-uuid",
- name: "Test Location",
- },
- },
- ],
- slug: "home",
- createdAt: "2023-04-27T11:27:32.419Z",
- updatedAt: "2023-04-28T10:47:59.259Z",
- },
- },
- },
- },
- {
- operation: "Delete",
- method: "DELETE",
- path: "/api/{collection-slug}",
- description: "Delete all documents matching the where query",
- example: {
- slug: "deleteDocuments",
- req: {
- credentials: true,
- query: true,
- headers: true,
- },
- res: {
- docs: [
- {
- id: "644ba4cf86359864f953594b",
- title: "New page",
- content: "Here is some content",
- slug: "new-page",
- createdAt: "2023-04-28T10:49:51.359Z",
- updatedAt: "2023-04-28T10:49:51.359Z",
- },
- ],
- errors: [],
- },
- },
- },
- {
- operation: "Delete by ID",
- method: "DELETE",
- path: "/api/{collection-slug}/{id}",
- description: "Delete an existing document by ID",
- example: {
- slug: "deleteByID",
- req: {
- credentials: true,
- headers: true,
- },
- res: {
- id: "644ba51786359864f9535954",
- title: "New page",
- content: "Here is some content",
- slug: "new-page",
- createdAt: "2023-04-28T10:51:03.028Z",
- updatedAt: "2023-04-28T10:51:03.028Z",
- },
- },
- },
+- [sort](/docs/queries/overview#sort) - sort by field
+- [where](/docs/queries/overview) - pass a where query to constrain returned documents
+- [limit](/docs/queries/pagination#pagination-controls) - limit the returned documents to a certain number
+- [page](/docs/queries/pagination#pagination-controls) - get a specific page of documents
+ `
+ },
+ },
+ {
+ operation: "Find By ID",
+ method: "GET",
+ path: "/api/{collection-slug}/{id}",
+ description: "Find a specific document by ID",
+ example: {
+ slug: "findByID",
+ req: true,
+ res: {
+ id: "644a5c24cc1383022535fc7c",
+ title: "Home",
+ content: "REST API examples",
+ slug: "home",
+ createdAt: "2023-04-27T11:27:32.419Z",
+ updatedAt: "2023-04-27T11:27:32.419Z",
+ },
+ },
+ },
+ {
+ operation: "Count",
+ method: "GET",
+ path: "/api/{collection-slug}/count",
+ description: "Count the documents",
+ example: {
+ slug: "count",
+ req: true,
+ res: {
+ totalDocs: 10
+ },
+ },
+ },
+ {
+ operation: "Create",
+ method: "POST",
+ path: "/api/{collection-slug}",
+ description: "Create a new document",
+ example: {
+ slug: "createDocument",
+ req: {
+ credentials: true,
+ headers: true,
+ body: {
+ title: "New page",
+ content: "Here is some content",
+ },
+ },
+ res: {
+ message: "Page successfully created.",
+ doc: {
+ id: "644ba34c86359864f9535932",
+ title: "New page",
+ content: "Here is some content",
+ slug: "new-page",
+ createdAt: "2023-04-28T10:43:24.466Z",
+ updatedAt: "2023-04-28T10:43:24.466Z",
+ },
+ },
+ },
+ },
+ {
+ operation: "Update",
+ method: "PATCH",
+ path: "/api/{collection-slug}",
+ description: "Update all documents matching the where query",
+ example: {
+ slug: "updateDocument",
+ req: {
+ credentials: true,
+ query: true,
+ headers: true,
+ body: {
+ title: "I have been updated!",
+ },
+ },
+ res: {
+ docs: [
+ {
+ id: "644ba34c86359864f9535932",
+ title: "I have been updated!",
+ content: "Here is some content",
+ slug: "new-page",
+ createdAt: "2023-04-28T10:43:24.466Z",
+ updatedAt: "2023-04-28T10:45:23.724Z",
+ },
+ ],
+ errors: [],
+ },
+ },
+ },
+ {
+ operation: "Update By ID",
+ method: "PATCH",
+ path: "/api/{collection-slug}/{id}",
+ description: "Update a document by ID",
+ example: {
+ slug: "updateDocumentByID",
+ req: {
+ credentials: true,
+ headers: true,
+ body: {
+ title: "I have been updated by ID!",
+ categories: "example-uuid",
+ tags: {
+ relationTo: "location",
+ value: "another-example-uuid",
+ },
+ },
+ },
+ res: {
+ message: "Updated successfully.",
+ doc: {
+ id: "644a5c24cc1383022535fc7c",
+ title: "I have been updated by ID!",
+ content: "REST API examples",
+ categories: {
+ id: "example-uuid",
+ name: "Test Category",
+ },
+ tags: [
+ {
+ relationTo: "location",
+ value: {
+ id: "another-example-uuid",
+ name: "Test Location",
+ },
+ },
+ ],
+ slug: "home",
+ createdAt: "2023-04-27T11:27:32.419Z",
+ updatedAt: "2023-04-28T10:47:59.259Z",
+ },
+ },
+ },
+ },
+ {
+ operation: "Delete",
+ method: "DELETE",
+ path: "/api/{collection-slug}",
+ description: "Delete all documents matching the where query",
+ example: {
+ slug: "deleteDocuments",
+ req: {
+ credentials: true,
+ query: true,
+ headers: true,
+ },
+ res: {
+ docs: [
+ {
+ id: "644ba4cf86359864f953594b",
+ title: "New page",
+ content: "Here is some content",
+ slug: "new-page",
+ createdAt: "2023-04-28T10:49:51.359Z",
+ updatedAt: "2023-04-28T10:49:51.359Z",
+ },
+ ],
+ errors: [],
+ },
+ },
+ },
+ {
+ operation: "Delete by ID",
+ method: "DELETE",
+ path: "/api/{collection-slug}/{id}",
+ description: "Delete an existing document by ID",
+ example: {
+ slug: "deleteByID",
+ req: {
+ credentials: true,
+ headers: true,
+ },
+ res: {
+ id: "644ba51786359864f9535954",
+ title: "New page",
+ content: "Here is some content",
+ slug: "new-page",
+ createdAt: "2023-04-28T10:51:03.028Z",
+ updatedAt: "2023-04-28T10:51:03.028Z",
+ },
+ },
+ },
]}
/>
@@ -568,10 +569,10 @@ In addition to the dynamically generated endpoints above Payload also has REST e
Additional REST API endpoints can be added to your application by providing an array of `endpoints` in various places within a Payload Config. Custom endpoints are useful for adding additional middleware on existing routes or for building custom functionality into Payload apps and plugins. Endpoints can be added at the top of the Payload Config, `collections`, and `globals` and accessed respective of the api and slugs you have configured.
- Custom endpoints are not authenticated by default. You are responsible for securing your own endpoints.
+ Custom endpoints are not authenticated by default. You are responsible for
+ securing your own endpoints.
-
Each endpoint object needs to have:
| Property | Description |
@@ -602,7 +603,7 @@ export const Orders: CollectionConfig = {
const tracking = await getTrackingInfo(req.routeParams.id)
if (!tracking) {
- return Response.json({ error: 'not found' }, { status: 404})
+ return Response.json({ error: 'not found' }, { status: 404 })
}
return Response.json({
@@ -622,12 +623,12 @@ export const Orders: CollectionConfig = {
collection: 'tracking',
data: {
// data to update the document with
- }
+ },
})
return Response.json({
- message: 'successfully updated tracking info'
+ message: 'successfully updated tracking info',
})
- }
+ },
},
{
path: '/:id/forbidden',
@@ -641,21 +642,24 @@ export const Orders: CollectionConfig = {
// do something
return Response.json({
- message: 'successfully updated tracking info'
+ message: 'successfully updated tracking info',
})
- }
- }
+ },
+ },
],
// highlight-end
}
```
- **Note:**
- **req** will have the **payload** object and can be used inside your endpoint handlers for making calls like req.payload.find() that will make use of [Access Control](../access-control/overview) and [Hooks](../hooks/overview).
+ **Note:** **req** will have the **payload** object and can be used inside your
+ endpoint handlers for making calls like req.payload.find() that will make use
+ of [Access Control](../access-control/overview) and
+ [Hooks](../hooks/overview).
#### Helpful tips
+
`req.data`
Data is not automatically appended to the request. You can read the body data by calling `await req.json()`.
diff --git a/docs/rich-text/converters.mdx b/docs/rich-text/converters.mdx
index 6614b426ef..4437b4e3cb 100644
--- a/docs/rich-text/converters.mdx
+++ b/docs/rich-text/converters.mdx
@@ -18,16 +18,16 @@ import { RichText } from '@payloadcms/richtext-lexical/react'
import { SerializedEditorState } from '@payloadcms/richtext-lexical/lexical'
export const MyComponent = ({ data }: { data: SerializedEditorState }) => {
- return (
-
- )
+ return
}
```
The `RichText` component includes built-in serializers for common Lexical nodes but allows customization through the `converters` prop. In our [website template](https://github.com/payloadcms/payload/blob/main/templates/website/src/components/RichText/index.tsx) you have an example of how to use `converters` to render custom blocks, custom nodes and override existing converters.
- When fetching data, ensure your `depth` setting is high enough to fully populate Lexical nodes such as uploads. The JSX converter requires fully populated data to work correctly.
+ When fetching data, ensure your `depth` setting is high enough to fully
+ populate Lexical nodes such as uploads. The JSX converter requires fully
+ populated data to work correctly.
### Converting Internal Links
@@ -37,7 +37,10 @@ By default, Payload doesn't know how to convert **internal** links to JSX, as it
To fix this, you need to pass the `internalDocToHref` prop to `LinkJSXConverter`. This prop is a function that receives the link node and returns the URL of the document.
```tsx
-import type { DefaultNodeTypes, SerializedLinkNode } from '@payloadcms/richtext-lexical'
+import type {
+ DefaultNodeTypes,
+ SerializedLinkNode,
+} from '@payloadcms/richtext-lexical'
import type { SerializedEditorState } from '@payloadcms/richtext-lexical/lexical'
import {
@@ -56,7 +59,9 @@ const internalDocToHref = ({ linkNode }: { linkNode: SerializedLinkNode }) => {
return relationTo === 'posts' ? `/posts/${slug}` : `/${slug}`
}
-const jsxConverters: JSXConvertersFunction = ({ defaultConverters }) => ({
+const jsxConverters: JSXConvertersFunction = ({
+ defaultConverters,
+}) => ({
...defaultConverters,
...LinkJSXConverter({ internalDocToHref }),
})
@@ -82,7 +87,10 @@ import type {
} from '@payloadcms/richtext-lexical'
import type { SerializedEditorState } from '@payloadcms/richtext-lexical/lexical'
-import { type JSXConvertersFunction, RichText } from '@payloadcms/richtext-lexical/react'
+import {
+ type JSXConvertersFunction,
+ RichText,
+} from '@payloadcms/richtext-lexical/react'
import React from 'react'
// Extend the default node types with your custom blocks for full type safety
@@ -91,12 +99,16 @@ type NodeTypes =
| SerializedBlockNode
| SerializedInlineBlockNode
-const jsxConverters: JSXConvertersFunction = ({ defaultConverters }) => ({
+const jsxConverters: JSXConvertersFunction = ({
+ defaultConverters,
+}) => ({
...defaultConverters,
blocks: {
// Each key should match your block's slug
myNumberBlock: ({ node }) => {node.fields.number}
,
- myTextBlock: ({ node }) => {node.fields.text}
,
+ myTextBlock: ({ node }) => (
+ {node.fields.text}
+ ),
},
inlineBlocks: {
// Each key should match your inline block's slug
@@ -119,10 +131,16 @@ Example - overriding the upload node converter to use next/image:
```tsx
'use client'
-import type { DefaultNodeTypes, SerializedUploadNode } from '@payloadcms/richtext-lexical'
+import type {
+ DefaultNodeTypes,
+ SerializedUploadNode,
+} from '@payloadcms/richtext-lexical'
import type { SerializedEditorState } from '@payloadcms/richtext-lexical/lexical'
-import { type JSXConvertersFunction, RichText } from '@payloadcms/richtext-lexical/react'
+import {
+ type JSXConvertersFunction,
+ RichText,
+} from '@payloadcms/richtext-lexical/react'
import Image from 'next/image'
import React from 'react'
@@ -144,7 +162,9 @@ const CustomUploadComponent: React.FC<{
return null
}
-const jsxConverters: JSXConvertersFunction = ({ defaultConverters }) => ({
+const jsxConverters: JSXConvertersFunction = ({
+ defaultConverters,
+}) => ({
...defaultConverters,
// Override the default upload converter
upload: ({ node }) => {
@@ -163,7 +183,6 @@ export const MyComponent: React.FC<{
If you don't have a React-based frontend, or if you need to send the content to a third-party service, you can convert lexical to HTML. There are two ways to do this:
-
1. **Generating HTML in your frontend** Convert JSON to HTML on-demand wherever you need it (Recommended).
2. **Outputting HTML from the Collection:** Create a new field in your collection to convert saved JSON content to HTML. Payload generates and outputs the HTML for use in your frontend. This is not recommended, as this approach adds additional overhead to the Payload API and may not work with live preview.
@@ -231,7 +250,11 @@ import React from 'react'
import config from '../../config.js'
-export const MyRSCComponent = async ({ data }: { data: SerializedEditorState }) => {
+export const MyRSCComponent = async ({
+ data,
+}: {
+ data: SerializedEditorState
+}) => {
const payload = await getPayload({
config,
})
@@ -273,7 +296,9 @@ type NodeTypes =
| SerializedBlockNode
| SerializedInlineBlockNode
-const htmlConverters: HTMLConvertersFunction = ({ defaultConverters }) => ({
+const htmlConverters: HTMLConvertersFunction = ({
+ defaultConverters,
+}) => ({
...defaultConverters,
blocks: {
// Each key should match your block's slug
@@ -359,7 +384,9 @@ const Pages: CollectionConfig = {
myTextBlock: ({ node, providedCSSString }) =>
`${node.fields.text}
`,
},
- })) as HTMLConvertersFunction>,
+ })) as HTMLConvertersFunction<
+ DefaultNodeTypes | SerializedBlockNode
+ >,
}),
],
}
@@ -375,7 +402,8 @@ Here is some "base" CSS you can use to ensure that nested lists render correctly
```css
/* Base CSS for Lexical HTML */
-.nestedListItem, .list-check {
+.nestedListItem,
+.list-check {
list-style-type: none;
}
```
@@ -392,13 +420,18 @@ A headless editor can perform such conversions outside of the main editor instan
```ts
import { createHeadlessEditor } from '@payloadcms/richtext-lexical/lexical/headless'
-import { getEnabledNodes, editorConfigFactory } from '@payloadcms/richtext-lexical'
+import {
+ getEnabledNodes,
+ editorConfigFactory,
+} from '@payloadcms/richtext-lexical'
const payloadConfig // <= your Payload Config here
const headlessEditor = createHeadlessEditor({
nodes: getEnabledNodes({
- editorConfig: await editorConfigFactory.default({config: payloadConfig})
+ editorConfig: await editorConfigFactory.default({
+ config: payloadConfig,
+ }),
}),
})
```
@@ -432,7 +465,10 @@ const yourEditorConfig2 = editorConfigFactory.fromField({
// Version 3 - create a new editor config - behaves just like instantiating a new `lexicalEditor`
const yourEditorConfig3 = await editorConfigFactory.fromFeatures({
config,
- features: ({ defaultFeatures }) => [...defaultFeatures, FixedToolbarFeature()],
+ features: ({ defaultFeatures }) => [
+ ...defaultFeatures,
+ FixedToolbarFeature(),
+ ],
})
// Version 4 - if you have instantiated a lexical editor and are accessing it outside a field (=> this is the unsanitized editor),
@@ -441,7 +477,10 @@ const yourEditorConfig3 = await editorConfigFactory.fromFeatures({
// This is the least efficient way to get the editor config, and not recommended. It is recommended to extract the `features` arg
// into a separate variable and use `fromFeatures` instead.
const editor = lexicalEditor({
- features: ({ defaultFeatures }) => [...defaultFeatures, FixedToolbarFeature()],
+ features: ({ defaultFeatures }) => [
+ ...defaultFeatures,
+ FixedToolbarFeature(),
+ ],
})
const yourEditorConfig4 = await editorConfigFactory.fromEditor({
@@ -457,7 +496,11 @@ If you have access to the sanitized collection config, you can get access to the
```ts
import type { CollectionConfig, RichTextField } from 'payload'
-import { editorConfigFactory, getEnabledNodes, lexicalEditor } from '@payloadcms/richtext-lexical'
+import {
+ editorConfigFactory,
+ getEnabledNodes,
+ lexicalEditor,
+} from '@payloadcms/richtext-lexical'
import { createHeadlessEditor } from '@payloadcms/richtext-lexical/lexical/headless'
export const MyCollection: CollectionConfig = {
@@ -504,7 +547,10 @@ export const MyCollection: CollectionConfig = {
If you have access to the Payload Config and the lexical editor config, you can convert HTML to the lexical editor state with the following:
```ts
-import { convertHTMLToLexical, editorConfigFactory } from '@payloadcms/richtext-lexical'
+import {
+ convertHTMLToLexical,
+ editorConfigFactory,
+} from '@payloadcms/richtext-lexical'
// Make sure you have jsdom and @types/jsdom installed
import { JSDOM } from 'jsdom'
@@ -522,14 +568,20 @@ const html = convertHTMLToLexical({
Convert markdown content to the Lexical editor format with the following:
```ts
-import { $convertFromMarkdownString, editorConfigFactory } from '@payloadcms/richtext-lexical'
+import {
+ $convertFromMarkdownString,
+ editorConfigFactory,
+} from '@payloadcms/richtext-lexical'
const yourEditorConfig = await editorConfigFactory.default({ config })
const markdown = `# Hello World`
headlessEditor.update(
() => {
- $convertFromMarkdownString(markdown, yourEditorConfig.features.markdownTransformers)
+ $convertFromMarkdownString(
+ markdown,
+ yourEditorConfig.features.markdownTransformers,
+ )
},
{ discrete: true },
)
@@ -545,8 +597,9 @@ 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.
+
## Lexical => Markdown
@@ -571,7 +624,9 @@ const yourEditorState: SerializedEditorState // <= your current editor state her
try {
headlessEditor.update(
() => {
- headlessEditor.setEditorState(headlessEditor.parseEditorState(yourEditorState))
+ headlessEditor.setEditorState(
+ headlessEditor.parseEditorState(yourEditorState),
+ )
},
{ discrete: true }, // This should commit the editor state immediately
)
@@ -582,7 +637,9 @@ try {
// Export to markdown
let markdown: string
headlessEditor.getEditorState().read(() => {
- markdown = $convertToMarkdownString(yourEditorConfig?.features?.markdownTransformers)
+ markdown = $convertToMarkdownString(
+ yourEditorConfig?.features?.markdownTransformers,
+ )
})
```
@@ -605,7 +662,9 @@ const yourEditorState: SerializedEditorState // <= your current editor state her
try {
headlessEditor.update(
() => {
- headlessEditor.setEditorState(headlessEditor.parseEditorState(yourEditorState))
+ headlessEditor.setEditorState(
+ headlessEditor.parseEditorState(yourEditorState),
+ )
},
{ discrete: true }, // This should commit the editor state immediately
)
diff --git a/docs/rich-text/custom-features.mdx b/docs/rich-text/custom-features.mdx
index ec6bdf8162..8f31ae0fe2 100644
--- a/docs/rich-text/custom-features.mdx
+++ b/docs/rich-text/custom-features.mdx
@@ -18,7 +18,8 @@ That way, we still maintain a clear boundary between server and client code, whi
**Important:**
Do not import directly from core lexical packages - this may break in minor Payload version bumps.
- Instead, import the re-exported versions from `@payloadcms/richtext-lexical`. For example, change `import { $insertNodeToNearestRoot } from '@lexical/utils'` to `import { $insertNodeToNearestRoot } from '@payloadcms/richtext-lexical/lexical/utils'`
+Instead, import the re-exported versions from `@payloadcms/richtext-lexical`. For example, change `import { $insertNodeToNearestRoot } from '@lexical/utils'` to `import { $insertNodeToNearestRoot } from '@payloadcms/richtext-lexical/lexical/utils'`
+
## Do I need a custom feature?
@@ -120,7 +121,9 @@ export const Code: React.FC = ({
const languageField = useFormFields(([fields]) => fields['language'])
const language: Language =
- (languageField?.value as Language) || (languageField?.initialValue as Language) || 'ts'
+ (languageField?.value as Language) ||
+ (languageField?.initialValue as Language) ||
+ 'ts'
const label = languages[language]
@@ -164,11 +167,10 @@ Custom Blocks are not enough? To start building a custom feature, you should sta
**Example myFeature/feature.server.ts:**
```ts
-import { createServerFeature } from '@payloadcms/richtext-lexical';
+import { createServerFeature } from '@payloadcms/richtext-lexical'
export const MyFeature = createServerFeature({
- feature: {
- },
+ feature: {},
key: 'myFeature',
})
```
@@ -200,8 +202,7 @@ By default, this server feature does nothing - you haven't added any functionali
Each feature can register their own translations, which are automatically scoped to the feature key:
```ts
-import { createServerFeature } from '@payloadcms/richtext-lexical';
-
+import { createServerFeature } from '@payloadcms/richtext-lexical'
export const MyFeature = createServerFeature({
feature: {
@@ -225,13 +226,9 @@ This allows you to add i18n translations scoped to your feature. This specific e
The Server Feature, just like the Client Feature, allows you to add markdown transformers. Markdown transformers on the server are used when [converting the editor from or to markdown](/docs/rich-text/converters#markdown-lexical).
```ts
-import { createServerFeature } from '@payloadcms/richtext-lexical';
+import { createServerFeature } from '@payloadcms/richtext-lexical'
import type { ElementTransformer } from '@payloadcms/richtext-lexical/lexical/markdown'
-import {
- $createMyNode,
- $isMyNode,
- MyNode
-} from './nodes/MyNode'
+import { $createMyNode, $isMyNode, MyNode } from './nodes/MyNode'
const MyMarkdownTransformer: ElementTransformer = {
type: 'element',
@@ -252,7 +249,6 @@ const MyMarkdownTransformer: ElementTransformer = {
},
}
-
export const MyFeature = createServerFeature({
feature: {
markdownTransformers: [MyMarkdownTransformer],
@@ -266,6 +262,7 @@ In this example, the node will be outputted as `+++` in Markdown, and the markdo
### Nodes#server-feature-nodes
While nodes added to the server feature do not control how the node is rendered in the editor, they control other aspects of the node:
+
- HTML conversion
- Node Hooks
- Sub fields
@@ -274,14 +271,11 @@ While nodes added to the server feature do not control how the node is rendered
The `createNode` helper function is used to create nodes with proper typing. It is recommended to use this function to create nodes.
```ts
-import { createServerFeature, createNode } from '@payloadcms/richtext-lexical';
-import {
- MyNode
-} from './nodes/MyNode'
+import { createServerFeature, createNode } from '@payloadcms/richtext-lexical'
+import { MyNode } from './nodes/MyNode'
export const MyFeature = createServerFeature({
feature: {
-
nodes: [
// Use the createNode helper function to more easily create nodes with proper typing
createNode({
@@ -307,7 +301,7 @@ export const MyFeature = createServerFeature({
While nodes in the client feature are added by themselves to the nodes array, nodes in the server feature can be added together with the following sibling options:
| Option | Description |
-|---------------------------------|---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
+| ------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| **`getSubFields`** | If a node includes sub-fields (e.g. block and link nodes), passing the subFields schema here will make Payload automatically populate & run hooks for them. |
| **`getSubFieldsData`** | If a node includes sub-fields, the sub-fields data needs to be returned here, alongside `getSubFields` which returns their schema. |
| **`graphQLPopulationPromises`** | Allows you to run population logic when a node's data was requested from GraphQL. While `getSubFields` and `getSubFieldsData` automatically handle populating sub-fields (since they run hooks on them), those are only populated in the Rest API. This is because the Rest API hooks do not have access to the 'depth' property provided by GraphQL. In order for them to be populated correctly in GraphQL, the population logic needs to be provided here. |
@@ -321,16 +315,22 @@ While nodes in the client feature are added by themselves to the nodes array, no
Server features can also accept a function as the `feature` property (useful for sanitizing props, as mentioned below). This function will be called when the feature is loaded during the Payload sanitization process:
```ts
-import { createServerFeature } from '@payloadcms/richtext-lexical';
+import { createServerFeature } from '@payloadcms/richtext-lexical'
createServerFeature({
//...
- feature: async ({ config, isRoot, props, resolvedFeatures, unSanitizedEditorConfig, featureProviderMap }) => {
-
+ feature: async ({
+ config,
+ isRoot,
+ props,
+ resolvedFeatures,
+ unSanitizedEditorConfig,
+ featureProviderMap,
+ }) => {
return {
//Actual server feature here...
}
- }
+ },
})
```
@@ -342,7 +342,7 @@ Within lexical, one example where this is done are our list features. Both `Unor
Here is how we do it:
```ts
-import { createServerFeature, createNode } from '@payloadcms/richtext-lexical';
+import { createServerFeature, createNode } from '@payloadcms/richtext-lexical'
export const OrderedListFeature = createServerFeature({
feature: ({ featureProviderMap }) => {
@@ -366,7 +366,7 @@ export const OrderedListFeature = createServerFeature({
If you wanted to make sure a feature is loaded before another feature, you can use the `dependenciesPriority` property:
```ts
-import { createServerFeature } from '@payloadcms/richtext-lexical';
+import { createServerFeature } from '@payloadcms/richtext-lexical'
export const MyFeature = createServerFeature({
feature: ({ featureProviderMap }) => {
@@ -380,7 +380,7 @@ export const MyFeature = createServerFeature({
```
| Option | Description |
-|----------------------------|-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
+| -------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| **`dependenciesSoft`** | Keys of soft-dependencies needed for this feature. These are optional. Payload will attempt to load them before this feature, but doesn't throw an error if that's not possible. |
| **`dependencies`** | Keys of dependencies needed for this feature. These dependencies do not have to be loaded first, but they have to exist, otherwise an error will be thrown. |
| **`dependenciesPriority`** | Keys of priority dependencies needed for this feature. These dependencies have to be loaded first AND have to exist, otherwise an error will be thrown. They will be available in the `feature` property. |
@@ -400,11 +400,9 @@ To set up your client-side feature, follow these three steps:
```ts
'use client'
-import { createClientFeature } from '@payloadcms/richtext-lexical/client';
+import { createClientFeature } from '@payloadcms/richtext-lexical/client'
-export const MyClientFeature = createClientFeature({
-
-})
+export const MyClientFeature = createClientFeature({})
```
Explore the APIs available through ClientFeature to add the specific functionality you need. Remember, do not import directly from `'@payloadcms/richtext-lexical'` when working on the client-side, as it will cause errors with webpack or turbopack. Instead, use `'@payloadcms/richtext-lexical/client'` for all client-side imports. Type-imports are excluded from this rule and can always be imported.
@@ -414,7 +412,7 @@ Explore the APIs available through ClientFeature to add the specific functionali
Inside of your server feature, you can provide an [import path](/docs/admin/custom-components/overview#component-paths) to the client feature like this:
```ts
-import { createServerFeature } from '@payloadcms/richtext-lexical';
+import { createServerFeature } from '@payloadcms/richtext-lexical'
export const MyFeature = createServerFeature({
feature: {
@@ -436,11 +434,11 @@ Example:
```ts
'use client'
-import { createClientFeature } from '@payloadcms/richtext-lexical/client';
-import { MyNode } from './nodes/MyNode';
+import { createClientFeature } from '@payloadcms/richtext-lexical/client'
+import { MyNode } from './nodes/MyNode'
export const MyClientFeature = createClientFeature({
- nodes: [MyNode]
+ nodes: [MyNode],
})
```
@@ -593,11 +591,11 @@ To add a plugin, simply add it to the `plugins` array in your client feature:
```ts
'use client'
-import { createClientFeature } from '@payloadcms/richtext-lexical/client';
-import { MyPlugin } from './plugin';
+import { createClientFeature } from '@payloadcms/richtext-lexical/client'
+import { MyPlugin } from './plugin'
export const MyClientFeature = createClientFeature({
- plugins: [MyPlugin]
+ plugins: [MyPlugin],
})
```
@@ -605,15 +603,13 @@ Example plugin.tsx:
```ts
'use client'
-import type {
- LexicalCommand,
-} from '@payloadcms/richtext-lexical/lexical'
+import type { LexicalCommand } from '@payloadcms/richtext-lexical/lexical'
import {
createCommand,
$getSelection,
$isRangeSelection,
- COMMAND_PRIORITY_EDITOR
+ COMMAND_PRIORITY_EDITOR,
} from '@payloadcms/richtext-lexical/lexical'
import { useLexicalComposerContext } from '@payloadcms/richtext-lexical/lexical/react/LexicalComposerContext'
@@ -622,9 +618,7 @@ import { useEffect } from 'react'
import type { PluginComponent } from '@payloadcms/richtext-lexical' // type imports can be imported from @payloadcms/richtext-lexical - even on the client
-import {
- $createMyNode,
-} from '../nodes/MyNode'
+import { $createMyNode } from '../nodes/MyNode'
import './index.scss'
export const INSERT_MYNODE_COMMAND: LexicalCommand = createCommand(
@@ -634,7 +628,7 @@ export const INSERT_MYNODE_COMMAND: LexicalCommand = createCommand(
/**
* Plugin which registers a lexical command to insert a new MyNode into the editor
*/
-export const MyNodePlugin: PluginComponent= () => {
+export const MyNodePlugin: PluginComponent = () => {
// The useLexicalComposerContext hook can be used to access the lexical editor instance
const [editor] = useLexicalComposerContext()
@@ -669,9 +663,10 @@ In this example, we register a lexical command, which simply inserts a new MyNod
### Toolbar groups
-Toolbar groups are visual containers which hold toolbar items. There are different toolbar group types which determine *how* a toolbar item is displayed: `dropdown` and `buttons`.
+Toolbar groups are visual containers which hold toolbar items. There are different toolbar group types which determine _how_ a toolbar item is displayed: `dropdown` and `buttons`.
All the default toolbar groups are exported from `@payloadcms/richtext-lexical/client`. You can use them to add your own toolbar items to the editor:
+
- Dropdown: `toolbarAddDropdownGroupWithItems`
- Dropdown: `toolbarTextDropdownGroupWithItems`
- Buttons: `toolbarFormatGroupWithItems`
@@ -682,17 +677,23 @@ Within dropdown groups, items are positioned vertically when the dropdown is ope
#### Custom buttons toolbar group
| Option | Description |
-|-------------|--------------------------------------------------------------------------------------------------------------------------------------------------------|
+| ----------- | ------------------------------------------------------------------------------------------------------------------------------------------------------ |
| **`items`** | All toolbar items part of this toolbar group need to be added here. |
| **`key`** | Each toolbar group needs to have a unique key. Groups with the same keys will have their items merged together. |
| **`order`** | Determines where the toolbar group will be. |
| **`type`** | Controls the toolbar group type. Set to `buttons` to create a buttons toolbar group, which displays toolbar items horizontally using only their icons. |
Example:
-```ts
-import type { ToolbarGroup, ToolbarGroupItem } from '@payloadcms/richtext-lexical'
-export const toolbarFormatGroupWithItems = (items: ToolbarGroupItem[]): ToolbarGroup => {
+```ts
+import type {
+ ToolbarGroup,
+ ToolbarGroupItem,
+} from '@payloadcms/richtext-lexical'
+
+export const toolbarFormatGroupWithItems = (
+ items: ToolbarGroupItem[],
+): ToolbarGroup => {
return {
type: 'buttons',
items,
@@ -705,7 +706,7 @@ export const toolbarFormatGroupWithItems = (items: ToolbarGroupItem[]): ToolbarG
#### Custom dropdown toolbar group
| Option | Description |
-|----------------------|--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
+| -------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| **`items`** | All toolbar items part of this toolbar group need to be added here. |
| **`key`** | Each toolbar group needs to have a unique key. Groups with the same keys will have their items merged together. |
| **`order`** | Determines where the toolbar group will be. |
@@ -713,12 +714,18 @@ export const toolbarFormatGroupWithItems = (items: ToolbarGroupItem[]): ToolbarG
| **`ChildComponent`** | The dropdown toolbar ChildComponent allows you to pass in a React Component which will be displayed within the dropdown button. |
Example:
+
```ts
-import type { ToolbarGroup, ToolbarGroupItem } from '@payloadcms/richtext-lexical'
+import type {
+ ToolbarGroup,
+ ToolbarGroupItem,
+} from '@payloadcms/richtext-lexical'
import { MyIcon } from './icons/MyIcon'
-export const toolbarAddDropdownGroupWithItems = (items: ToolbarGroupItem[]): ToolbarGroup => {
+export const toolbarAddDropdownGroupWithItems = (
+ items: ToolbarGroupItem[],
+): ToolbarGroup => {
return {
type: 'dropdown',
ChildComponent: MyIcon,
@@ -744,14 +751,17 @@ To add a toolbar item to either the floating or the inline toolbar, you can add
```ts
'use client'
-import { createClientFeature, toolbarAddDropdownGroupWithItems } from '@payloadcms/richtext-lexical/client';
-import { IconComponent } from './icon';
-import { $isHorizontalRuleNode } from './nodes/MyNode';
-import { INSERT_MYNODE_COMMAND } from './plugin';
+import {
+ createClientFeature,
+ toolbarAddDropdownGroupWithItems,
+} from '@payloadcms/richtext-lexical/client'
+import { IconComponent } from './icon'
+import { $isHorizontalRuleNode } from './nodes/MyNode'
+import { INSERT_MYNODE_COMMAND } from './plugin'
import { $isNodeSelection } from '@payloadcms/richtext-lexical/lexical'
export const MyClientFeature = createClientFeature({
- toolbarFixed: {
+ toolbarFixed: {
groups: [
toolbarAddDropdownGroupWithItems([
{
@@ -783,7 +793,7 @@ You will have to provide a toolbar group first, and then the items for that tool
A `ToolbarItem` various props you can use to customize its behavior:
| Option | Description |
-|----------------------|--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
+| -------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| **`ChildComponent`** | A React component which is rendered within your toolbar item's default button component. Usually, you want this to be an icon. |
| **`Component`** | A React component which is rendered in place of the toolbar item's default button component, thus completely replacing it. The `ChildComponent` and `onSelect` properties will be ignored. |
| **`label`** | The label will be displayed in your toolbar item, if it's within a dropdown group. To make use of i18n, this can be a function. |
@@ -805,11 +815,13 @@ import type {
SlashMenuItem,
} from '@payloadcms/richtext-lexical'
-export function mwnSlashMenuGroupWithItems(items: SlashMenuItem[]): SlashMenuGroup {
+export function mwnSlashMenuGroupWithItems(
+ items: SlashMenuItem[],
+): SlashMenuGroup {
return {
items,
key: 'myGroup',
- label: 'My Group' // <= This can be a function to make use of i18n
+ label: 'My Group', // <= This can be a function to make use of i18n
}
}
```
@@ -817,12 +829,11 @@ export function mwnSlashMenuGroupWithItems(items: SlashMenuItem[]): SlashMenuGro
By creating a helper function like this, you can easily re-use it and add items to it. All Slash Menu groups with the same keys will have their items merged together.
| Option | Description |
-|-------------|---------------------------------------------------------------------------------------------------------------------------------------|
+| ----------- | ------------------------------------------------------------------------------------------------------------------------------------- |
| **`items`** | An array of `SlashMenuItem`'s which will be displayed in the slash menu. |
| **`label`** | The label will be displayed before your Slash Menu group. In order to make use of i18n, this can be a function. |
| **`key`** | Used for class names and, if label is not provided, for display. Slash menus with the same key will have their items merged together. |
-
### Slash Menu items
The API for adding items to the slash menu is similar. There are slash menu groups, and each slash menu groups has items. Here is an example:
@@ -830,9 +841,12 @@ The API for adding items to the slash menu is similar. There are slash menu grou
```ts
'use client'
-import { createClientFeature, slashMenuBasicGroupWithItems } from '@payloadcms/richtext-lexical/client';
-import { INSERT_MYNODE_COMMAND } from './plugin';
-import { IconComponent } from './icon';
+import {
+ createClientFeature,
+ slashMenuBasicGroupWithItems,
+} from '@payloadcms/richtext-lexical/client'
+import { INSERT_MYNODE_COMMAND } from './plugin'
+import { IconComponent } from './icon'
export const MyClientFeature = createClientFeature({
slashMenu: {
@@ -856,26 +870,21 @@ export const MyClientFeature = createClientFeature({
```
| Option | Description |
-|----------------|-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
+| -------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| **`Icon`** | The icon which is rendered in your slash menu item. |
| **`label`** | The label will be displayed in your slash menu item. In order to make use of i18n, this can be a function. |
| **`key`** | Each slash menu item needs to have a unique key. The key will be matched when typing, displayed if no `label` property is set, and used for classNames. |
| **`onSelect`** | A function which is called when the slash menu item is selected. |
| **`keywords`** | Keywords are used to match the item for different texts typed after the '/'. E.g. you might want to show a horizontal rule item if you type both /hr, /separator, /horizontal etc. In addition to the keywords, the label and key will be used to find the right slash menu item. |
-
### Markdown Transformers#client-feature-markdown-transformers
The Client Feature, just like the Server Feature, allows you to add markdown transformers. Markdown transformers on the client are used to create new nodes when a certain markdown pattern is typed in the editor.
```ts
-import { createClientFeature } from '@payloadcms/richtext-lexical/client';
+import { createClientFeature } from '@payloadcms/richtext-lexical/client'
import type { ElementTransformer } from '@payloadcms/richtext-lexical/lexical/markdown'
-import {
- $createMyNode,
- $isMyNode,
- MyNode
-} from './nodes/MyNode'
+import { $createMyNode, $isMyNode, MyNode } from './nodes/MyNode'
const MyMarkdownTransformer: ElementTransformer = {
type: 'element',
@@ -896,7 +905,6 @@ const MyMarkdownTransformer: ElementTransformer = {
},
}
-
export const MyFeature = createClientFeature({
markdownTransformers: [MyMarkdownTransformer],
})
@@ -911,11 +919,11 @@ You can add providers to your client feature, which will be nested below the `Ed
```ts
'use client'
-import { createClientFeature } from '@payloadcms/richtext-lexical/client';
-import { TableContext } from './context';
+import { createClientFeature } from '@payloadcms/richtext-lexical/client'
+import { TableContext } from './context'
export const MyClientFeature = createClientFeature({
- providers: [TableContext],
+ providers: [TableContext],
})
```
@@ -945,14 +953,21 @@ To sanitize those in the server feature, you can pass a function to `feature` in
```ts
createServerFeature({
//...
- feature: async ({ config, isRoot, props, resolvedFeatures, unSanitizedEditorConfig, featureProviderMap }) => {
+ feature: async ({
+ config,
+ isRoot,
+ props,
+ resolvedFeatures,
+ unSanitizedEditorConfig,
+ featureProviderMap,
+ }) => {
const sanitizedProps = doSomethingWithProps(props)
return {
sanitizedServerFeatureProps: sanitizedProps,
//Actual server feature here...
}
- }
+ },
})
```
@@ -962,10 +977,16 @@ In the client feature, it works similarly:
```ts
createClientFeature(
- ({ clientFunctions, featureProviderMap, props, resolvedFeatures, unSanitizedEditorConfig }) => {
+ ({
+ clientFunctions,
+ featureProviderMap,
+ props,
+ resolvedFeatures,
+ unSanitizedEditorConfig,
+ }) => {
const sanitizedProps = doSomethingWithProps(props)
return {
- sanitizedClientFeatureProps: sanitizedProps,
+ sanitizedClientFeatureProps: sanitizedProps,
//Actual client feature here...
}
},
@@ -985,9 +1006,9 @@ createServerFeature({
//...
feature: {
clientFeatureProps: {
- test: 'myValue'
- }
- }
+ test: 'myValue',
+ },
+ },
})
```
diff --git a/docs/rich-text/migration.mdx b/docs/rich-text/migration.mdx
index c9b0241444..69b2fa2c7a 100644
--- a/docs/rich-text/migration.mdx
+++ b/docs/rich-text/migration.mdx
@@ -15,6 +15,7 @@ While both Slate and Lexical save the editor state in JSON, the structure of the
Just import the `migrateSlateToLexical` function we provide, pass it the `payload` object and run it. Depending on the amount of collections, this might take a while.
IMPORTANT: This will overwrite all slate data. We recommend doing the following first:
+
1. Take a backup of your entire database. If anything goes wrong and you do not have a backup, you are on your own and will not receive any support.
2. Make every richText field a lexical editor. This script will only convert lexical richText fields with old Slate data.
3. Add the SlateToLexicalFeature (as seen below) first, and test it out by loading up the Admin Panel, to see if the migrator works as expected. You might have to build some custom converters for some fields first in order to convert custom Slate nodes. The SlateToLexicalFeature is where the converters are stored. Only fields with this feature added will be migrated.
@@ -45,7 +46,10 @@ const Pages: CollectionConfig = {
name: 'nameOfYourRichTextField',
type: 'richText',
editor: lexicalEditor({
- features: ({ defaultFeatures }) => [...defaultFeatures, SlateToLexicalFeature({})],
+ features: ({ defaultFeatures }) => [
+ ...defaultFeatures,
+ SlateToLexicalFeature({}),
+ ],
}),
},
],
@@ -97,7 +101,7 @@ When using the `SlateToLexicalFeature`, you can add your custom converters to th
```ts
import type { CollectionConfig } from 'payload'
-import { lexicalEditor } from '@payloadcms/richtext-lexical'
+import { lexicalEditor } from '@payloadcms/richtext-lexical'
import {
SlateToLexicalFeature,
defaultSlateConverters,
diff --git a/docs/rich-text/overview.mdx b/docs/rich-text/overview.mdx
index 878579fba5..e11d5900cc 100644
--- a/docs/rich-text/overview.mdx
+++ b/docs/rich-text/overview.mdx
@@ -8,19 +8,18 @@ title: Rich Text Editor
- This documentation is about our new editor, based on Lexical (Meta's rich text editor). The previous default
- editor was based on Slate and is still supported. You can read [its documentation](/docs/rich-text/slate),
- or the optional [migration guide](/docs/rich-text/migration) to migrate from Slate to Lexical (recommended).
+This documentation is about our new editor, based on Lexical (Meta's rich text editor). The previous default
+editor was based on Slate and is still supported. You can read [its documentation](/docs/rich-text/slate),
+or the optional [migration guide](/docs/rich-text/migration) to migrate from Slate to Lexical (recommended).
The editor is the most important property of the [rich text field](/docs/fields/rich-text).
-As a key part of Payload, we are proud to offer you the best editing experience you can imagine. With healthy
-defaults out of the box, but also with the flexibility to customize every detail: from the “/” menu
+As a key part of Payload, we are proud to offer you the best editing experience you can imagine. With healthy
+defaults out of the box, but also with the flexibility to customize every detail: from the “/” menu
and toolbars (whether inline or fixed) to inserting any component or subfield you can imagine.
-
To use the rich text editor, first you need to install it:
```bash
@@ -134,41 +133,41 @@ import { CallToAction } from '../blocks/CallToAction'
`features` can be both an array of features, or a function returning an array of features. The function provides the following props:
-| Prop | Description |
-| --- | --- |
-| **`defaultFeatures`** | This opinionated array contains all "recommended" default features. You can see which features are included in the default features in the table below. |
-| **`rootFeatures`** | This array contains all features that are enabled in the root richText editor (the one defined in the payload.config.ts). If this field is the root richText editor, or if the root richText editor is not a lexical editor, this array will be empty. |
+| Prop | Description |
+| --------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
+| **`defaultFeatures`** | This opinionated array contains all "recommended" default features. You can see which features are included in the default features in the table below. |
+| **`rootFeatures`** | This array contains all features that are enabled in the root richText editor (the one defined in the payload.config.ts). If this field is the root richText editor, or if the root richText editor is not a lexical editor, this array will be empty. |
## Features overview
Here's an overview of all the included features:
-| Feature Name | Included by default | Description |
-| --- | --- | --- |
-| **`BoldFeature`** | Yes | Handles the bold text format |
-| **`ItalicFeature`** | Yes | Handles the italic text format |
-| **`UnderlineFeature`** | Yes | Handles the underline text format |
-| **`StrikethroughFeature`** | Yes | Handles the strikethrough text format |
-| **`SubscriptFeature`** | Yes | Handles the subscript text format |
-| **`SuperscriptFeature`** | Yes | Handles the superscript text format |
-| **`InlineCodeFeature`** | Yes | Handles the inline-code text format |
-| **`ParagraphFeature`** | Yes | Handles paragraphs. Since they are already a key feature of lexical itself, this Feature mainly handles the Slash and Add-Block menu entries for paragraphs |
-| **`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) |
-| **`OrderedListFeature`** | Yes | Adds ordered lists (ol) |
-| **`ChecklistFeature`** | Yes | Adds checklists |
-| **`LinkFeature`** | Yes | Allows you to create internal and external links |
-| **`RelationshipFeature`** | Yes | Allows you to create block-level (not inline) relationships to other documents |
-| **`BlockquoteFeature`** | Yes | Allows you to create block-level quotes |
-| **`UploadFeature`** | Yes | Allows you to create block-level upload nodes - this supports all kinds of uploads, not just images |
-| **`HorizontalRuleFeature`** | Yes | Horizontal rules / separators. Basically displays an ` ` element |
-| **`InlineToolbarFeature`** | Yes | The inline toolbar is the floating toolbar which appears when you select text. This toolbar only contains actions relevant for selected text |
-| **`FixedToolbarFeature`** | No | This classic toolbar is pinned to the top and always visible. Both inline and fixed toolbars can be enabled at the same time. |
-| **`BlocksFeature`** | No | Allows you to use Payload's [Blocks Field](../fields/blocks) directly inside your editor. In the feature props, you can specify the allowed blocks - just like in the Blocks field. |
-| **`TreeViewFeature`** | No | Adds a debug box under the editor, which allows you to see the current editor state live, the dom, as well as time travel. Very useful for debugging |
-| **`EXPERIMENTAL_TableFeature`** | No | Adds support for tables. This feature may be removed or receive breaking changes in the future - even within a stable lexical release, without needing a major release. |
+| Feature Name | Included by default | Description |
+| ------------------------------- | ------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
+| **`BoldFeature`** | Yes | Handles the bold text format |
+| **`ItalicFeature`** | Yes | Handles the italic text format |
+| **`UnderlineFeature`** | Yes | Handles the underline text format |
+| **`StrikethroughFeature`** | Yes | Handles the strikethrough text format |
+| **`SubscriptFeature`** | Yes | Handles the subscript text format |
+| **`SuperscriptFeature`** | Yes | Handles the superscript text format |
+| **`InlineCodeFeature`** | Yes | Handles the inline-code text format |
+| **`ParagraphFeature`** | Yes | Handles paragraphs. Since they are already a key feature of lexical itself, this Feature mainly handles the Slash and Add-Block menu entries for paragraphs |
+| **`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) |
+| **`OrderedListFeature`** | Yes | Adds ordered lists (ol) |
+| **`ChecklistFeature`** | Yes | Adds checklists |
+| **`LinkFeature`** | Yes | Allows you to create internal and external links |
+| **`RelationshipFeature`** | Yes | Allows you to create block-level (not inline) relationships to other documents |
+| **`BlockquoteFeature`** | Yes | Allows you to create block-level quotes |
+| **`UploadFeature`** | Yes | Allows you to create block-level upload nodes - this supports all kinds of uploads, not just images |
+| **`HorizontalRuleFeature`** | Yes | Horizontal rules / separators. Basically displays an ` ` element |
+| **`InlineToolbarFeature`** | Yes | The inline toolbar is the floating toolbar which appears when you select text. This toolbar only contains actions relevant for selected text |
+| **`FixedToolbarFeature`** | No | This classic toolbar is pinned to the top and always visible. Both inline and fixed toolbars can be enabled at the same time. |
+| **`BlocksFeature`** | No | Allows you to use Payload's [Blocks Field](../fields/blocks) directly inside your editor. In the feature props, you can specify the allowed blocks - just like in the Blocks field. |
+| **`TreeViewFeature`** | No | Adds a debug box under the editor, which allows you to see the current editor state live, the dom, as well as time travel. Very useful for debugging |
+| **`EXPERIMENTAL_TableFeature`** | No | Adds support for tables. This feature may be removed or receive breaking changes in the future - even within a stable lexical release, without needing a major release. |
Notice how even the toolbars are features? That's how extensible our lexical editor is - you could theoretically create your own toolbar if you wanted to!
@@ -247,9 +246,7 @@ const editorState: TypedEditorState<
Alternatively, you can use the `DefaultTypedEditorState` type, which includes all types for all nodes included in the `defaultFeatures`:
```ts
-import type {
- DefaultTypedEditorState
-} from '@payloadcms/richtext-lexical'
+import type { DefaultTypedEditorState } from '@payloadcms/richtext-lexical'
const editorState: DefaultTypedEditorState = {
root: {
@@ -301,12 +298,11 @@ Lexical does not generate accurate type definitions for your richText fields for
The Rich Text Field editor configuration has an `admin` property with the following options:
-| Property | Description |
-| --- | --- |
-| **`placeholder`** | Set this property to define a placeholder string for the field. |
-| **`hideGutter`** | Set this property to `true` to hide this field's gutter within the Admin Panel. |
-| **`hideInsertParagraphAtEnd`** | Set this property to `true` to hide the "+" button that appears at the end of the editor |
-
+| Property | Description |
+| ------------------------------ | ---------------------------------------------------------------------------------------- |
+| **`placeholder`** | Set this property to define a placeholder string for the field. |
+| **`hideGutter`** | Set this property to `true` to hide this field's gutter within the Admin Panel. |
+| **`hideInsertParagraphAtEnd`** | Set this property to `true` to hide the "+" button that appears at the end of the editor |
### Disable the gutter
diff --git a/docs/rich-text/slate.mdx b/docs/rich-text/slate.mdx
index 7ab2219914..dbe6c792ae 100644
--- a/docs/rich-text/slate.mdx
+++ b/docs/rich-text/slate.mdx
@@ -8,9 +8,9 @@ keywords: slatejs, slate, rich text, editor, headless cms
- The [default Payload editor](/docs/rich-text/overview) is currently based on Lexical. This documentation
- is about our old Slate-based editor. You can continue using it because it is still supported, or you can
- see the optional [migration guide](/docs/rich-text/migration) to migrate from Slate to Lexical (recommended).
+The [default Payload editor](/docs/rich-text/overview) is currently based on Lexical. This documentation
+is about our old Slate-based editor. You can continue using it because it is still supported, or you can
+see the optional [migration guide](/docs/rich-text/migration) to migrate from Slate to Lexical (recommended).
@@ -129,10 +129,11 @@ Similar to the `relationship` element, the `upload` element is a user-friendly w
**Tip:**
- Collections are automatically allowed to be selected within the Rich Text relationship and upload
- elements by default. If you want to disable a collection from being able to be referenced in Rich
- Text fields, set the collection admin options of **enableRichTextLink** and
- **enableRichTextRelationship** to false.
+Collections are automatically allowed to be selected within the Rich Text relationship and upload
+elements by default. If you want to disable a collection from being able to be referenced in Rich
+Text fields, set the collection admin options of **enableRichTextLink** and
+**enableRichTextRelationship** to false.
+
Relationship and Upload elements are populated dynamically into your Rich Text field' content. Within the REST and Local APIs, any present RichText `relationship` or `upload` elements will respect the `depth` option that you pass, and will be populated accordingly. In GraphQL, each `richText` field accepts an argument of `depth` for you to utilize.
@@ -155,8 +156,8 @@ Once you're up to speed with the general concepts involved, you can pass in your
| Property | Description |
| --------------- | ---------------------------------------------------------- |
-| **`name`** * | The default name to be used as a `type` for this element. |
-| **`Button`** * | A React component to be rendered in the Rich Text toolbar. |
+| **`name`** \* | The default name to be used as a `type` for this element. |
+| **`Button`** \* | A React component to be rendered in the Rich Text toolbar. |
| **`plugins`** | An array of plugins to provide to the Rich Text editor. |
| **`type`** | A type that overrides the default type used by `name` |
@@ -312,8 +313,9 @@ const serialize = (children) =>
**Note:**
- The above example is for how to render to JSX, although for plain HTML the pattern is similar.
- Just remove the JSX and return HTML strings instead!
+The above example is for how to render to JSX, although for plain HTML the pattern is similar.
+Just remove the JSX and return HTML strings instead!
+
### Built-in SlateJS Plugins
@@ -360,5 +362,8 @@ The plugin itself extends Payload's built-in `shouldBreakOutOnEnter` Slate funct
If you are building your own custom Rich Text elements or leaves, you may benefit from importing the following types:
```ts
-import type { RichTextCustomElement, RichTextCustomLeaf } from '@payloadcms/richtext-slate'
+import type {
+ RichTextCustomElement,
+ RichTextCustomLeaf,
+} from '@payloadcms/richtext-slate'
```
diff --git a/docs/troubleshooting/troubleshooting.mdx b/docs/troubleshooting/troubleshooting.mdx
index 14f3e2ec2c..3137d930e0 100644
--- a/docs/troubleshooting/troubleshooting.mdx
+++ b/docs/troubleshooting/troubleshooting.mdx
@@ -12,7 +12,7 @@ keywords: admin, components, custom, customize, documentation, Content Managemen
This means that your auth cookie is not being set or accepted correctly upon logging in. To resolve check the following settings in your Payload Config:
-- CORS - If you are using the '*', try to explicitly only allow certain domains instead including the one you have specified.
+- CORS - If you are using the '\*', try to explicitly only allow certain domains instead including the one you have specified.
- CSRF - Do you have this set? if so, make sure your domain is whitelisted within the csrf domains. If not, probably not the issue, but probably can't hurt to whitelist it anyway.
- Cookie settings. If these are completely undefined, then that's fine. but if you have cookie domain set, or anything similar, make sure you don't have the domain misconfigured
diff --git a/docs/typescript/generating-types.mdx b/docs/typescript/generating-types.mdx
index 2603884f7e..19e5feac07 100644
--- a/docs/typescript/generating-types.mdx
+++ b/docs/typescript/generating-types.mdx
@@ -90,9 +90,9 @@ Payload generates your types based on a JSON schema. You can extend that JSON sc
// This will generate the following type in your payload-types.ts:
export interface Test {
- title: string;
- content: string;
- [k: string]: unknown;
+ title: string
+ content: string
+ [k: string]: unknown
}
```
@@ -118,8 +118,8 @@ const config: Config = {
name: 'name',
type: 'text',
required: true,
- }
- ]
+ },
+ ],
},
{
slug: 'posts',
@@ -136,9 +136,9 @@ const config: Config = {
type: 'relationship',
relationTo: 'users',
},
- ]
- }
- ]
+ ],
+ },
+ ],
}
```
@@ -203,10 +203,11 @@ export interface Collection1 {
**Naming Collisions**
- Since these types are hoisted to the top level, you need to be aware that naming collisions can
- occur. For example, if you have a collection with the name of `Meta` and you also create a
- interface with the name `Meta` they will collide. It is recommended to scope your interfaces by
- appending the field type to the end, i.e. `MetaGroup` or similar.
+Since these types are hoisted to the top level, you need to be aware that naming collisions can
+occur. For example, if you have a collection with the name of `Meta` and you also create a
+interface with the name `Meta` they will collide. It is recommended to scope your interfaces by
+appending the field type to the end, i.e. `MetaGroup` or similar.
+
## Using your types
@@ -218,7 +219,8 @@ Now that your types have been generated, payloads local API will now be typed. I
**Important**
- Payload needs to be able to find your config to generate your types.
+Payload needs to be able to find your config to generate your types.
+
Payload will automatically try and locate your config, but might not always be able to find it. For example, if you are working in a `/src` directory or similar, you need to tell Payload where to find your config manually by using an environment variable. If this applies to you, you can create an npm script to make generating your types easier.
diff --git a/docs/upload/overview.mdx b/docs/upload/overview.mdx
index f12a06160e..6e86b41e7a 100644
--- a/docs/upload/overview.mdx
+++ b/docs/upload/overview.mdx
@@ -7,8 +7,9 @@ keywords: uploads, images, media, overview, documentation, Content Management Sy
---
- Payload provides everything you need to enable file upload, storage, and management directly
- on your server—including extremely powerful file [access control](#access-control).
+ Payload provides everything you need to enable file upload, storage, and
+ management directly on your server—including extremely powerful file [access
+ control](#access-control).
**Tip:**
- A common pattern is to create a **"media"** collection and enable **upload** on that collection.
+A common pattern is to create a **"media"** collection and enable **upload** on that collection.
+
```ts
@@ -88,30 +90,29 @@ export const Media: CollectionConfig = {
_An asterisk denotes that an option is required._
-| Option | Description |
-|--------------------------------|-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
-| **`adminThumbnail`** | Set the way that the [Admin Panel](../admin/overview) will display thumbnails for this Collection. [More](#admin-thumbnails) |
-| **`bulkUpload`** | Allow users to upload in bulk from the list view, default is true |
-| **`cacheTags`** | Set to `false` to disable the cache tag set in the UI for the admin thumbnail component. Useful for when CDNs don't allow certain cache queries. |
-| **`crop`** | Set to `false` to disable the cropping tool in the [Admin Panel](../admin/overview). Crop is enabled by default. [More](#crop-and-focal-point-selector) |
-| **`disableLocalStorage`** | Completely disable uploading files to disk locally. [More](#disabling-local-upload-storage) |
-| **`displayPreview`** | Enable displaying preview of the uploaded file in Upload fields related to this Collection. Can be locally overridden by `displayPreview` option in Upload field. [More](/docs/fields/upload#config-options). |
-| **`externalFileHeaderFilter`** | Accepts existing headers and returns the headers after filtering or modifying. |
-| **`filesRequiredOnCreate`** | Mandate file data on creation, default is true. |
-| **`filenameCompoundIndex`** | Field slugs to use for a compound index instead of the default filename index. |
-| **`focalPoint`** | Set to `false` to disable the focal point selection tool in the [Admin Panel](../admin/overview). 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 Request handlers to execute when fetching a file, if a handler returns a Response it will be sent to the client. Otherwise Payload will retrieve and send back the file. |
-| **`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) |
+| Option | Description |
+| ------------------------------ | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
+| **`adminThumbnail`** | Set the way that the [Admin Panel](../admin/overview) will display thumbnails for this Collection. [More](#admin-thumbnails) |
+| **`bulkUpload`** | Allow users to upload in bulk from the list view, default is true |
+| **`cacheTags`** | Set to `false` to disable the cache tag set in the UI for the admin thumbnail component. Useful for when CDNs don't allow certain cache queries. |
+| **`crop`** | Set to `false` to disable the cropping tool in the [Admin Panel](../admin/overview). Crop is enabled by default. [More](#crop-and-focal-point-selector) |
+| **`disableLocalStorage`** | Completely disable uploading files to disk locally. [More](#disabling-local-upload-storage) |
+| **`displayPreview`** | Enable displaying preview of the uploaded file in Upload fields related to this Collection. Can be locally overridden by `displayPreview` option in Upload field. [More](/docs/fields/upload#config-options). |
+| **`externalFileHeaderFilter`** | Accepts existing headers and returns the headers after filtering or modifying. |
+| **`filesRequiredOnCreate`** | Mandate file data on creation, default is true. |
+| **`filenameCompoundIndex`** | Field slugs to use for a compound index instead of the default filename index. |
+| **`focalPoint`** | Set to `false` to disable the focal point selection tool in the [Admin Panel](../admin/overview). 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 Request handlers to execute when fetching a file, if a handler returns a Response it will be sent to the client. Otherwise Payload will retrieve and send back the file. |
+| **`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) |
| **`pasteURL`** | Controls whether files can be uploaded from remote URLs by pasting them into the Upload field. **Enabled by default.** Accepts `false` to disable or an object with an `allowList` of valid remote URLs. [More](#uploading-files-from-remote-urls) |
-| **`resizeOptions`** | An object passed to the the Sharp image library to resize the uploaded file. [More](https://sharp.pixelplumbing.com/api-resize) |
-| **`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. Defaults to your collection slug |
-| **`trimOptions`** | An object passed to the the Sharp image library to trim the uploaded file. [More](https://sharp.pixelplumbing.com/api-resize#trim) |
-| **`withMetadata`** | If specified, appends metadata to the output image file. Accepts a boolean or a function that receives `metadata` and `req`, returning a boolean. |
-| **`hideFileInputOnCreate`** | Set to `true` to prevent the admin UI from showing file inputs during document creation, useful for programmatic file generation. |
-| **`hideRemoveFile`** | Set to `true` to prevent the admin UI having a way to remove an existing file while editing. |
-
+| **`resizeOptions`** | An object passed to the the Sharp image library to resize the uploaded file. [More](https://sharp.pixelplumbing.com/api-resize) |
+| **`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. Defaults to your collection slug |
+| **`trimOptions`** | An object passed to the the Sharp image library to trim the uploaded file. [More](https://sharp.pixelplumbing.com/api-resize#trim) |
+| **`withMetadata`** | If specified, appends metadata to the output image file. Accepts a boolean or a function that receives `metadata` and `req`, returning a boolean. |
+| **`hideFileInputOnCreate`** | Set to `true` to prevent the admin UI from showing file inputs during document creation, useful for programmatic file generation. |
+| **`hideRemoveFile`** | Set to `true` to prevent the admin UI having a way to remove an existing file while editing. |
### Payload-wide Upload Options
@@ -206,8 +207,9 @@ When an uploaded image is smaller than the defined image size, we have 3 options
**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.
+
#### Custom file name per size
@@ -243,10 +245,11 @@ If you are using a plugin to send your files off to a third-party file storage h
**Note:**
- This is a fairly advanced feature. If you do disable local file storage, by default, your admin
- panel's thumbnails will be broken as you will not have stored a file. It will be totally up to you
- to use either a plugin or your own hooks to store your files in a permanent manner, as well as
- provide your own admin thumbnail using **upload.adminThumbnail**.
+This is a fairly advanced feature. If you do disable local file storage, by default, your admin
+panel's thumbnails will be broken as you will not have stored a file. It will be totally up to you
+to use either a plugin or your own hooks to store your files in a permanent manner, as well as
+provide your own admin thumbnail using **upload.adminThumbnail**.
+
## Admin Thumbnails
@@ -276,9 +279,9 @@ export const Media: CollectionConfig = {
fit: 'cover',
height: 600,
width: 1800,
- }
- ]
- }
+ },
+ ],
+ },
}
```
@@ -291,9 +294,10 @@ export const Media: CollectionConfig = {
slug: 'media',
upload: {
// 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
- }
+ },
}
```
@@ -321,8 +325,9 @@ export const Media: CollectionConfig = {
**Important:**
- Uploading files is currently only possible through the REST and Local APIs due to how GraphQL
- works. It's difficult and fairly nonsensical to support uploading files through GraphQL.
+Uploading files is currently only possible through the REST and Local APIs due to how GraphQL
+works. It's difficult and fairly nonsensical to support uploading files through GraphQL.
+
To upload a file, use your collection's [`create`](/docs/rest-api/overview#collections) endpoint. Send it all the data that your Collection requires, as well as a `file` key containing the file that you'd like to upload.
@@ -330,10 +335,10 @@ To upload a file, use your collection's [`create`](/docs/rest-api/overview#colle
Send your request as a `multipart/form-data` request, using [`FormData`](https://developer.mozilla.org/en-US/docs/Web/API/FormData) if possible.
```ts
-const fileInput = document.querySelector('#your-file-input') ;
-const formData = new FormData();
+const fileInput = document.querySelector('#your-file-input')
+const formData = new FormData()
-formData.append('file', fileInput.files[0]);
+formData.append('file', fileInput.files[0])
fetch('api/:upload-slug', {
method: 'POST',
@@ -371,8 +376,9 @@ The `data` property should still include all the required fields of your `media`
**Important:**
- Remember that all custom hooks attached to the `media` collection will still trigger.
- Ensure that files match the specified mimeTypes or sizes defined in the collection's `formatOptions` or custom `hooks`.
+Remember that all custom hooks attached to the `media` collection will still trigger.
+Ensure that files match the specified mimeTypes or sizes defined in the collection's `formatOptions` or custom `hooks`.
+
## Uploading Files from Remote URLs
@@ -424,14 +430,13 @@ export const Media: CollectionConfig = {
_An asterisk denotes that an option is required._
-| Option | Description | Example |
-| ---------------- | ---------------------------------------------------------------------------------------------------- | ------------- |
-| **`hostname`** * | The hostname of the allowed URL. This is required to ensure the URL is coming from a trusted source. | `example.com` |
-| **`pathname`** | The path portion of the URL. Supports wildcards to match multiple paths. | `/images/*` |
-| **`port`** | The port number of the URL. If not specified, the default port for the protocol will be used. | `3000` |
-| **`protocol`** | The protocol to match. Must be either `http` or `https`. Defaults to `https`. | `https` |
-| **`search`** | The query string of the URL. If specified, the URL must match this exact query string. | `?version=1` |
-
+| Option | Description | Example |
+| ----------------- | ---------------------------------------------------------------------------------------------------- | ------------- |
+| **`hostname`** \* | The hostname of the allowed URL. This is required to ensure the URL is coming from a trusted source. | `example.com` |
+| **`pathname`** | The path portion of the URL. Supports wildcards to match multiple paths. | `/images/*` |
+| **`port`** | The port number of the URL. If not specified, the default port for the protocol will be used. | `3000` |
+| **`protocol`** | The protocol to match. Must be either `http` or `https`. Defaults to `https`. | `https` |
+| **`search`** | The query string of the URL. If specified, the URL must match this exact query string. | `?version=1` |
## Access Control
diff --git a/docs/upload/storage-adapters.mdx b/docs/upload/storage-adapters.mdx
index af93715e66..35c29d9d64 100644
--- a/docs/upload/storage-adapters.mdx
+++ b/docs/upload/storage-adapters.mdx
@@ -9,7 +9,7 @@ keywords: uploads, images, media, storage, adapters, s3, vercel, google cloud, a
Payload offers additional storage adapters to handle file uploads. These adapters allow you to store files in different locations, such as Amazon S3, Vercel Blob Storage, Google Cloud Storage, and more.
| Service | Package |
-| -------------------- |-------------------------------------------------------------------------------------------------------------------|
+| -------------------- | ----------------------------------------------------------------------------------------------------------------- |
| Vercel Blob | [`@payloadcms/storage-vercel-blob`](https://github.com/payloadcms/payload/tree/main/packages/storage-vercel-blob) |
| AWS S3 | [`@payloadcms/storage-s3`](https://github.com/payloadcms/payload/tree/main/packages/storage-s3) |
| Azure | [`@payloadcms/storage-azure`](https://github.com/payloadcms/payload/tree/main/packages/storage-azure) |
@@ -17,6 +17,7 @@ Payload offers additional storage adapters to handle file uploads. These adapter
| Uploadthing | [`@payloadcms/storage-uploadthing`](https://github.com/payloadcms/payload/tree/main/packages/storage-uploadthing) |
## Vercel Blob Storage
+
[`@payloadcms/storage-vercel-blob`](https://www.npmjs.com/package/@payloadcms/storage-vercel-blob)
### Installation#vercel-blob-installation
@@ -68,6 +69,7 @@ export default buildConfig({
| `clientUploads` | Do uploads directly on the client to bypass limits on Vercel. | |
## S3 Storage
+
[`@payloadcms/storage-s3`](https://www.npmjs.com/package/@payloadcms/storage-s3)
### Installation#s3-installation
@@ -117,6 +119,7 @@ export default buildConfig({
See the the [AWS SDK Package](https://github.com/aws/aws-sdk-js-v3) and [`S3ClientConfig`](https://docs.aws.amazon.com/AWSJavaScriptSDK/v3/latest/client/s3) object for guidance on AWS S3 configuration.
## Azure Blob Storage
+
[`@payloadcms/storage-azure`](https://www.npmjs.com/package/@payloadcms/storage-azure)
### Installation#azure-installation
@@ -146,7 +149,8 @@ export default buildConfig({
prefix,
},
},
- allowContainerCreate: process.env.AZURE_STORAGE_ALLOW_CONTAINER_CREATE === 'true',
+ allowContainerCreate:
+ process.env.AZURE_STORAGE_ALLOW_CONTAINER_CREATE === 'true',
baseURL: process.env.AZURE_STORAGE_ACCOUNT_BASEURL,
connectionString: process.env.AZURE_STORAGE_CONNECTION_STRING,
containerName: process.env.AZURE_STORAGE_CONTAINER_NAME,
@@ -168,6 +172,7 @@ export default buildConfig({
| `clientUploads` | Do uploads directly on the client to bypass limits on Vercel. | |
## Google Cloud Storage
+
[`@payloadcms/storage-gcs`](https://www.npmjs.com/package/@payloadcms/storage-gcs)
### Installation#gcs-installation
@@ -218,8 +223,8 @@ export default buildConfig({
| `acl` | Access control list for files that are uploaded | `Private` |
| `clientUploads` | Do uploads directly on the client to bypass limits on Vercel. | |
-
## Uploadthing Storage
+
[`@payloadcms/storage-uploadthing`](https://www.npmjs.com/package/@payloadcms/storage-uploadthing)
### Installation#uploadthing-installation
@@ -263,7 +268,6 @@ export default buildConfig({
| `defaultKeyType` | Default key type for file operations | `fileKey` |
| `clientUploads` | Do uploads directly on the client to bypass limits on Vercel. | |
-
## Custom Storage Adapters
If you need to create a custom storage adapter, you can use the [`@payloadcms/plugin-cloud-storage`](https://www.npmjs.com/package/@payloadcms/plugin-cloud-storage) package. This package is used internally by the storage adapters mentioned above.
@@ -318,14 +322,14 @@ This plugin is configurable to work across many different Payload collections. A
| Option | Type | Description |
| ---------------- | ----------------------------------- | --------------------------------------------------------------------------------------------------------------------------------- |
-| `collections` * | `Record` | Object with keys set to the slug of collections you want to enable the plugin for, and values set to collection-specific options. |
+| `collections` \* | `Record` | Object with keys set to the slug of collections you want to enable the plugin for, and values set to collection-specific options. |
| `enabled` | `boolean` | To conditionally enable/disable plugin. Default: `true`. |
## Collection-specific options
| Option | Type | Description |
| ----------------------------- | ----------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
-| `adapter` * | [Adapter](https://github.com/payloadcms/payload/blob/main/packages/plugin-cloud-storage/src/types.ts#L49) | Pass in the adapter that you'd like to use for this collection. You can also set this field to `null` for local development if you'd like to bypass cloud storage in certain scenarios and use local storage. |
+| `adapter` \* | [Adapter](https://github.com/payloadcms/payload/blob/main/packages/plugin-cloud-storage/src/types.ts#L49) | Pass in the adapter that you'd like to use for this collection. You can also set this field to `null` for local development if you'd like to bypass cloud storage in certain scenarios and use local storage. |
| `disableLocalStorage` | `boolean` | Choose to disable local storage on this collection. Defaults to `true`. |
| `disablePayloadAccessControl` | `true` | Set to `true` to disable Payload's Access Control. [More](#payload-access-control) |
| `prefix` | `string` | Set to `media/images` to upload files inside `media/images` folder in the bucket. |
diff --git a/docs/versions/autosave.mdx b/docs/versions/autosave.mdx
index 6841c42f46..077c473259 100644
--- a/docs/versions/autosave.mdx
+++ b/docs/versions/autosave.mdx
@@ -69,7 +69,8 @@ When `autosave` is enabled, all `update` operations within Payload expose a new
If we created a new version for each autosave, you'd quickly find a ton of autosaves that clutter up your `_versions` collection within the database. That would be messy quick because `autosave` is typically set to save a document at ~800ms intervals.
- Instead of creating a new version each time a document is autosaved, Payload smartly only creates
- **one** autosave version, and then updates that specific version with each autosave
- performed. This makes sure that your versions remain nice and tidy.
+ Instead of creating a new version each time a document is autosaved, Payload
+ smartly only creates **one** autosave version, and then updates that specific
+ version with each autosave performed. This makes sure that your versions
+ remain nice and tidy.
diff --git a/docs/versions/drafts.mdx b/docs/versions/drafts.mdx
index e8f215cb30..35a0f4c218 100644
--- a/docs/versions/drafts.mdx
+++ b/docs/versions/drafts.mdx
@@ -8,7 +8,9 @@ keywords: version history, drafts, preview, draft, restore, publish, autosave, C
Payload's Draft functionality builds on top of the Versions functionality to allow you to make changes to your collection documents and globals, but publish only when you're ready. This functionality allows you to build powerful Preview environments for your data, where you can make sure your changes look good before publishing documents.
-Drafts rely on Versions being enabled in order to function.
+
+ Drafts rely on Versions being enabled in order to function.
+
By enabling Versions with Drafts, your collections and globals can maintain _newer_, and _unpublished_ versions of your documents. It's perfect for cases where you might want to work on a document, update it and save your progress, but not necessarily make it publicly published right away. Drafts are extremely helpful when building preview implementations.
@@ -42,9 +44,9 @@ Within the Admin UI, if drafts are enabled, a document can be shown with one of
## Draft API
- If drafts are enabled on your collection or global, important and powerful changes are made to
- your REST, GraphQL, and Local APIs that allow you to specify if you are interacting with drafts or
- with live documents.
+ If drafts are enabled on your collection or global, important and powerful
+ changes are made to your REST, GraphQL, and Local APIs that allow you to
+ specify if you are interacting with drafts or with live documents.
#### Updating or creating drafts
@@ -74,15 +76,20 @@ If you simply fetch your created document using a `find` or `findByID` operation
But, if you specify `draft` as `true`, Payload will automatically replace your published document's content with content coming from the most recently saved `version`. In this case, as we have created _two_ versions in the above scenario, Payload will send back data from the newest (second) draft and your document will appear as the most recently drafted version instead of the published version.
- **Important:** the `draft` argument on its own will not restrict documents with `_status: 'draft'` from being returned from the API. You need to use Access Control to prevent documents with `_status: 'draft'` from being returned to unauthenticated users. Read below for more information on how this works.
+ **Important:** the `draft` argument on its own will not restrict documents
+ with `_status: 'draft'` from being returned from the API. You need to use
+ Access Control to prevent documents with `_status: 'draft'` from being
+ returned to unauthenticated users. Read below for more information on how this
+ works.
## Controlling who can see Collection drafts
- If you're using the **drafts** feature, it's important for you to consider who can
- view your drafts, and who can view only published documents. Luckily, Payload makes this extremely
- simple and puts the power completely in your hands.
+ If you're using the **drafts** feature, it's important for you to consider who
+ can view your drafts, and who can view only published documents. Luckily,
+ Payload makes this extremely simple and puts the power completely in your
+ hands.
#### Restricting draft access
@@ -122,13 +129,14 @@ export const Pages: CollectionConfig = {
**Note regarding adding versions to an existing collection**
- If you already have a collection with documents, and you *opt in* to draft functionality
- after you have already created existing documents, all of your old documents
- *will not have a `_status` field* until you resave them. For this reason, if you are
- *adding* versions into an existing collection, you might want to write your Access Control
- function to allow for users to read both documents where
- **`_status` is equal to `"published"`** as well as where
- **`_status` does not exist**.
+If you already have a collection with documents, and you _opt in_ to draft functionality
+after you have already created existing documents, all of your old documents
+_will not have a `_status` field_ until you resave them. For this reason, if you are
+_adding_ versions into an existing collection, you might want to write your Access Control
+function to allow for users to read both documents where
+**`_status` is equal to `"published"`** as well as where
+**`_status` does not exist**.
+
Here is an example for how to write an [Access Control](../access-control/overview) function that grants access to both documents where `_status` is equal to "published" and where `_status` does not exist:
@@ -178,7 +186,12 @@ Payload provides for an ability to schedule publishing / unpublishing events in
You can enable this functionality on both collections and globals via the `versions.drafts.schedulePublish: true` property.
- **Important:** if you are going to enable scheduled publish / unpublish, you need to make sure your Payload app is set up to process [Jobs](/docs/jobs-queue/overview). This feature works by creating a Job in the background, which will be picked up after the job becomes available. If you do not have any mechanism in place to run jobs, your scheduled publish / unpublish jobs will never be executed.
+ **Important:** if you are going to enable scheduled publish / unpublish, you
+ need to make sure your Payload app is set up to process
+ [Jobs](/docs/jobs-queue/overview). This feature works by creating a Job in the
+ background, which will be picked up after the job becomes available. If you do
+ not have any mechanism in place to run jobs, your scheduled publish /
+ unpublish jobs will never be executed.
## Unpublishing drafts
diff --git a/docs/versions/overview.mdx b/docs/versions/overview.mdx
index 801d20ed04..6573d835f8 100644
--- a/docs/versions/overview.mdx
+++ b/docs/versions/overview.mdx
@@ -7,8 +7,8 @@ keywords: version history, revisions, audit log, draft, publish, restore, autosa
---
- Payload's powerful Versions functionality allows you to keep a running history of changes over
- time and extensible to fit any content publishing workflow.
+ Payload's powerful Versions functionality allows you to keep a running history
+ of changes over time and extensible to fit any content publishing workflow.
When enabled, Payload will automatically scaffold a new Collection in your database to store versions of your document(s) over time, and the Admin UI will be extended with additional views that allow you to browse document versions, view diffs in order to see exactly what has changed in your documents (and when they changed), and restore documents back to prior versions easily.
@@ -26,9 +26,9 @@ _Comparing an old version to a newer version of a document_
- Build a powerful publishing schedule mechanism to create documents and have them become publicly readable automatically at a future date
- Versions are extremely performant and totally opt-in. They don't change the shape of your data at
- all. All versions are stored in a separate Collection and can be turned on and off easily at your
- discretion.
+ Versions are extremely performant and totally opt-in. They don't change the
+ shape of your data at all. All versions are stored in a separate Collection
+ and can be turned on and off easily at your discretion.
## Options
diff --git a/package.json b/package.json
index dcc131f739..1fbb16f943 100644
--- a/package.json
+++ b/package.json
@@ -159,7 +159,7 @@
"p-limit": "^5.0.0",
"playwright": "1.50.0",
"playwright-core": "1.50.0",
- "prettier": "3.3.3",
+ "prettier": "3.5.3",
"react": "19.0.0",
"react-dom": "19.0.0",
"rimraf": "6.0.1",
diff --git a/packages/translations/package.json b/packages/translations/package.json
index 658d1964b4..572abb612f 100644
--- a/packages/translations/package.json
+++ b/packages/translations/package.json
@@ -63,7 +63,7 @@
"@types/react": "19.0.10",
"@types/react-dom": "19.0.4",
"dotenv": "16.4.7",
- "prettier": "3.3.3",
+ "prettier": "3.5.3",
"typescript": "5.7.3"
},
"publishConfig": {
diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml
index 531d2a7ef7..7140481870 100644
--- a/pnpm-lock.yaml
+++ b/pnpm-lock.yaml
@@ -149,8 +149,8 @@ importers:
specifier: 1.50.0
version: 1.50.0
prettier:
- specifier: 3.3.3
- version: 3.3.3
+ specifier: 3.5.3
+ version: 3.5.3
react:
specifier: 19.0.0
version: 19.0.0
@@ -1538,8 +1538,8 @@ importers:
specifier: 16.4.7
version: 16.4.7
prettier:
- specifier: 3.3.3
- version: 3.3.3
+ specifier: 3.5.3
+ version: 3.5.3
typescript:
specifier: 5.7.3
version: 5.7.3
@@ -8796,6 +8796,11 @@ packages:
engines: {node: '>=14'}
hasBin: true
+ prettier@3.5.3:
+ resolution: {integrity: sha512-QQtaxnoDJeAkDvDKWCLiwIXkTgRhwYDEQCghU9Z6q03iyek/rxRh/2lC3HB7P8sWT2xC/y5JDctPLBIGzHKbhw==}
+ engines: {node: '>=14'}
+ hasBin: true
+
pretty-format@29.7.0:
resolution: {integrity: sha512-Pdlw/oPxN+aXdmM9R00JVC9WVFoCLTKJvDVLgmJ+qAffBMxsV85l/Lu7sNx4zSzPyoL2euImuEwHhOXdEgNFZQ==}
engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0}
@@ -18784,6 +18789,8 @@ snapshots:
prettier@3.3.3: {}
+ prettier@3.5.3: {}
+
pretty-format@29.7.0:
dependencies:
'@jest/schemas': 29.6.3