Commit Graph

1011 Commits

Author SHA1 Message Date
Alessio Gravili
c07c9e9129 perf: optimize getEntityConfig lookups (#10665)
Replaces array-based lookups in `getEntityConfig` with a map, reducing
time complexity from O(n) to O(1).
2025-01-20 12:32:38 -07:00
Boyan Bratvanov
ef44bddca9 docs: react hooks - update useForm import path (#10658)
The `addFieldRow` / `removeFieldRow` / `replaceFieldRow` code examples
in the docs drawers still used the v2(?) import paths for `useForm`.

https://payloadcms.com/docs/admin/hooks#useform
2025-01-18 16:32:53 +02:00
Jacob Fletcher
64fc2df878 docs: removes live preview image placeholder comment (#10643)
There was a rogue `{/* IMAGE OF LIVE PREVIEW HERE */}` comment being
rendered in the live preview docs. Comments in this format used to be
hidden, but since moving to a new rendering pattern they now appear.
2025-01-17 13:38:52 -05:00
Patrik
38a06e7bd3 feat: adds support for both client-side and server-side remote URL uploads fetching (#10004)
### What?

The `pasteURL` feature for Upload fields has been updated to support
both **client-side** and **server-side** URL fetching. Previously, users
could only paste URLs from the same domain as their Payload instance
(internal) or public domains, which led to **CORS** errors when trying
to fetch files from external URLs.

Now, users can choose between **client-side fetching** (default) and
**server-side fetching** using the new `pasteURL` option in the Upload
collection config.

### How?

- By default, Payload will attempt to fetch the file client-side
directly in the browser.
- To enable server-side fetching, you can configure the new `pasteURL`
option with an `allowList` of trusted domains.
- The new `/api/:collectionSlug/paste-url` endpoint is used to fetch
files server-side and stream them back to the browser.

#### Example

```
import type { CollectionConfig } from 'payload'

export const Media: CollectionConfig = {
  slug: 'media',
  upload: {
    // pasteURL: false, // Can now disable the pasteURL option entirely by passing "false".
    pasteURL: {
      allowList: [
        {
          hostname: 'payloadcms.com', // required
          pathname: '',
          port: '',
          protocol: 'https', // defaults to https - options: "https" | "http"
          search: ''
        },
        {
          hostname: 'example.com',
          pathname: '/images/*',
        },
      ],
    },
  },
}
```

### Why

This update provides more flexibility for users to paste URLs into
Upload fields without running into **CORS errors** and allows Payload to
securely fetch files from trusted domains.
2025-01-17 09:16:29 -05:00
Greg Presland
22f3c79dc0 docs: update wording for sentence (#10599)
### What?

Updating wording for a sentence.

### Why?

I believe it was missing a word as it read a bit off without it and
causes a reread.

### How?

Doesn't feel like it reads right and causes a reread.

Fixes #

- "If you are building a website that fits within the limits _of_ a tool
like Webflow or Framer"
2025-01-15 13:32:21 -07:00
Jarrod Flesch
813e70be1f feat: adds multi-tenant plugin (#10447)
### Multi Tenant Plugin
This PR adds a `@payloadcms/plugin-multi-tenant` package. The goal is to
consolidate a source of truth for multi-tenancy. Currently we are
maintaining different implementations for clients, users in discord and
our examples repo. When updates or new paradigms arise we need to
communicate this with everyone and update code examples which is hard to
maintain.

### What does it do?
- adds a tenant selector to the sidebar, above the nav links
- adds a hidden tenant field to every collection that you specify
- adds an array field to your users collection, allowing you to assign
users to tenants
- by default combines the access control (to enabled collections) that
you define, with access control based on the tenants assigned to user on
the request
- by default adds a baseListFilter that filters the documents shown in
the list view with the selected tenant in the admin panel

### What does it not do?
- it does not implement multi-tenancy for your frontend. You will need
to query data for specific tenants to build your website/application
- it does not add a tenants collection, you **NEED** to add a tenants
collection, where you can define what types of fields you would like on
it

### The plugin config

Most of the options listed below are _optional_, but it is easier to
just lay out all of the configuration options.

**TS Type**
```ts
type MultiTenantPluginConfig<ConfigTypes = unknown> = {
  /**
   * After a tenant is deleted, the plugin will attempt to clean up related documents
   * - removing documents with the tenant ID
   * - removing the tenant from users
   *
   * @default true
   */
  cleanupAfterTenantDelete?: boolean
  /**
   * Automatically
   */
  collections: {
    [key in CollectionSlug]?: {
      /**
       * Set to `true` if you want the collection to behave as a global
       *
       * @default false
       */
      isGlobal?: boolean
      /**
       * Set to `false` if you want to manually apply the baseListFilter
       *
       * @default true
       */
      useBaseListFilter?: boolean
      /**
       * Set to `false` if you want to handle collection access manually without the multi-tenant constraints applied
       *
       * @default true
       */
      useTenantAccess?: boolean
    }
  }
  /**
   * Enables debug mode
   * - Makes the tenant field visible in the admin UI within applicable collections
   *
   * @default false
   */
  debug?: boolean
  /**
   * Enables the multi-tenant plugin
   *
   * @default true
   */
  enabled?: boolean
  /**
   * Field configuration for the field added to all tenant enabled collections
   */
  tenantField?: {
    access?: RelationshipField['access']
    /**
     * The name of the field added to all tenant enabled collections
     *
     * @default 'tenant'
     */
    name?: string
  }
  /**
   * Field configuration for the field added to the users collection
   *
   * If `includeDefaultField` is `false`, you must include the field on your users collection manually
   * This is useful if you want to customize the field or place the field in a specific location
   */
  tenantsArrayField?:
    | {
        /**
         * Access configuration for the array field
         */
        arrayFieldAccess?: ArrayField['access']
        /**
         * When `includeDefaultField` is `true`, the field will be added to the users collection automatically
         */
        includeDefaultField?: true
        /**
         * Additional fields to include on the tenants array field
         */
        rowFields?: Field[]
        /**
         * Access configuration for the tenant field
         */
        tenantFieldAccess?: RelationshipField['access']
      }
    | {
        arrayFieldAccess?: never
        /**
         * When `includeDefaultField` is `false`, you must include the field on your users collection manually
         */
        includeDefaultField?: false
        rowFields?: never
        tenantFieldAccess?: never
      }
  /**
   * The slug for the tenant collection
   *
   * @default 'tenants'
   */
  tenantsSlug?: string
  /**
   * Function that determines if a user has access to _all_ tenants
   *
   * Useful for super-admin type users
   */
  userHasAccessToAllTenants?: (
    user: ConfigTypes extends { user: User } ? ConfigTypes['user'] : User,
  ) => boolean
}
```

**Example usage**
```ts
import type { Config } from './payload-types'
import { buildConfig } from 'payload'

export default buildConfig({
  plugins: [
    multiTenantPlugin<Config>({
      collections: {
        pages: {},
      },
      userHasAccessToAllTenants: (user) => isSuperAdmin(user),
    }),
  ],
})
```


### How to configure Collections as Globals for multi-tenant

When using multi-tenant, globals need to actually be configured as
collections so the content can be specific per tenant.
To do that, you can mark a collection with `isGlobal` and it will behave
like a global and users will not see the list view.

```ts
multiTenantPlugin({
  collections: {
    navigation: {
      isGlobal: true,
    },
  },
})
```
2025-01-15 14:47:46 -05:00
Jessica Chowdhury
8217842bb3 docs: add section on localized access control (#10567) 2025-01-14 08:36:46 -05:00
Alessio Gravili
6757f7d459 feat(richtext-lexical): add new paragraph button below the editor (#10530)
Fixes https://github.com/payloadcms/payload/issues/10448


https://github.com/user-attachments/assets/dfcd4ab6-8e41-4a1b-b642-876a0737d9ae
2025-01-13 19:08:00 +00:00
Ben Löffel
5043a8a43f docs: improves grammar in vercel postgres usage note (#10365)
Refined the grammar and structure of the usage note for
`vercelPostgresAdapter`. Replaced the ambiguous phrase "If when using"
with "If you are using" for better readability and clarity.
2025-01-13 13:36:39 -05:00
Jarrod Flesch
43b40f0b00 docs: updates docs to reflect correct array hook usage (#10546)
### What?
The documentation for `addFieldRow` and `replaceFieldRow` was not
updated during the v2 -> v3 update.

### How?
Updates the documentation for `addFieldRow` and `replaceFieldRow`.

Fixes #9244
2025-01-13 13:00:40 -05:00
Paul
6b051bd59e feat: add ability to disable cache tags for admin thumbnails (#10319)
This PR adds `cacheTags: boolean` (default `true`) to allow users to
disable the appended document updatedAt value in the case of hosting
with third party CDNs which may not allow additional search params and
throw an error.

It also fixes how we append this value to consider the case where the
URL already contains parameters and appends it with `&` instead.

In the future `cacheTags` can be made an object to allow granularity for
disabling `eTag` headers used for caching as well.

The cache tag control should help with these two issues:
- Fixes https://github.com/payloadcms/payload/issues/9880
- Fixes https://github.com/payloadcms/payload/issues/9993

The appending of the value correctly addresses this:
- Fixes https://github.com/payloadcms/payload/issues/10139
2025-01-13 15:26:47 +00:00
Steve Kuznetsov
21eec876c4 docs: update beforeValidate documentation (#10367)
docs: update beforeValidate documentation

These hooks operate similarly across the different contexts they can be
registered in, but were not sufficiently documented as such.

Signed-off-by: Steve Kuznetsov <stekuznetsov@microsoft.com>
2025-01-10 08:15:44 +00:00
Steve Kuznetsov
a8d6f3f543 docs: update draft doc for formatting (#10393)
I think some automatic formatter added the `{' '}` styling, it doesn't
render correctly. Update the formatting for this banner to remove it and
correctly refer to the `_status` field.

---------

Signed-off-by: Steve Kuznetsov <stekuznetsov@microsoft.com>
2025-01-10 08:14:29 +00:00
Adrian Maj
83bd0e2e4c docs: removed unnecessary visible <br/> tag in fields/blocks (#10456)
There was a `<br/>` tag, which was visible on the docs page. Also, I
removed spacing from the second tip box, to keep in consistent with tips
in other places in docs.
2025-01-10 08:10:31 +00:00
Germán Jabloñski
c0dc0cca37 feat: autoRun jobs (#10401)
This pull request introduces the ability to configure cron jobs for
automatically running tasks in the job queue.
2025-01-08 14:51:26 -05:00
Jacob Fletcher
b09275419a fix: deprecates admin.disable property (#10429)
Fixes #10284. The `admin.disable` property is no longer supported as of
v3. Instead, to opt-out of serving the Admin Panel, REST API, or GraphQL
API, you must delete their corresponding directories within your Next.js
app. For example, to opt-out of everything, delete the `/app/(payload)`
directory entirely. Or to remove specifically the Admin Panel or API
routes, delete the `/app/(payload)/admin` or `/app/(payload)/api`
directories, respectively. Note: if you've modified the default paths
for these routes via `admin.routes`, delete those directories instead.
2025-01-07 20:28:05 +00:00
Alessio Gravili
08fb159943 feat: allow running sub-tasks from tasks (#10373)
Task handlers now receive `inlineTask` as an arg, which can be used to
run inline sub-tasks. In the task log, those inline tasks will have a
`parent` property that points to the parent task.

Example:

```ts
{
        slug: 'subTask',
        inputSchema: [
          {
            name: 'message',
            type: 'text',
            required: true,
          },
        ],
        handler: async ({ job, inlineTask }) => {
          await inlineTask('create two docs', {
            task: async ({ input, inlineTask }) => {
            
              const { newSimple } = await inlineTask('create doc 1', {
                task: async ({ req }) => {
                  const newSimple = await req.payload.create({
                    collection: 'simple',
                    req,
                    data: {
                      title: input.message,
                    },
                  })
                  return {
                    output: {
                      newSimple,
                    },
                  }
                },
              })

              const { newSimple2 } = await inlineTask('create doc 2', {
                task: async ({ req }) => {
                  const newSimple2 = await req.payload.create({
                    collection: 'simple',
                    req,
                    data: {
                      title: input.message,
                    },
                  })
                  return {
                    output: {
                      newSimple2,
                    },
                  }
                },
              })
              return {
                output: {
                  simpleID1: newSimple.id,
                  simpleID2: newSimple2.id,
                },
              }
            },
            input: {
              message: job.input.message,
            },
          })
        },
      } as WorkflowConfig<'subTask'>
```

Job log example:

```ts
[
  {
    executedAt: '2025-01-06T03:55:44.682Z',
    completedAt: '2025-01-06T03:55:44.684Z',
    taskSlug: 'inline',
    taskID: 'create doc 1',
    output: { newSimple: [Object] },
    parent: { taskSlug: 'inline', taskID: 'create two docs' }, // <= New
    state: 'succeeded',
    id: '677b5440ba35d345d1214d1b'
  },
  {
    executedAt: '2025-01-06T03:55:44.690Z',
    completedAt: '2025-01-06T03:55:44.692Z',
    taskSlug: 'inline',
    taskID: 'create doc 2',
    output: { newSimple2: [Object] },
    parent: { taskSlug: 'inline', taskID: 'create two docs' }, // <= New
    state: 'succeeded',
    id: '677b5440ba35d345d1214d1c'
  },
  {
    executedAt: '2025-01-06T03:55:44.681Z',
    completedAt: '2025-01-06T03:55:44.697Z',
    taskSlug: 'inline',
    taskID: 'create two docs',
    input: { message: 'hello!' },
    output: {
      simpleID1: '677b54401e34772cc63c8693',
      simpleID2: '677b54401e34772cc63c8697'
    },
    parent: {},
    state: 'succeeded',
    id: '677b5440ba35d345d1214d1d'
  }
]
```
2025-01-07 17:24:00 +00:00
Alessio Gravili
b774f557be docs: minor lexical docs improvements (#10414) 2025-01-07 16:22:40 +00:00
Boyan Bratvanov
53aea622f9 docs: fix all other links to live-preview example (#10385)
Continuation of #10380.
2025-01-06 10:15:25 -05:00
Danilo Lemes
fd52de6d8f docs: fix CORS anchor link (#10333) 2025-01-06 08:26:49 -05:00
Boyan Bratvanov
1e247f8509 docs: fix link to live-preview example and remove empty placeholder (#10380) 2025-01-06 08:22:53 -05:00
Alessio Gravili
5ba477b810 chore(examples): remove outdated testing example (#10370)
This deletes the outdated testing example, as it has not been updated to
Payload v3 yet.

We can add it back in the future once we updated it. Generally, the
Next.js testing docs should now be valid:
https://nextjs.org/docs/app/building-your-application/testing. However,
it might still make sense to provide a v3 testing example to showcase
things like booting up an in-memory db
2025-01-06 00:43:53 +00:00
Said Akhrarov
5e4e27460e docs: fix links and formatting (#10346)
### What?
This PR fixes numerous links across the docs, both internal docs links
and external links. This PR also fixes some minor formatting issues in
some places, as well as optically aligns the markdown tables in tables
that had broken links.

### Why?
To properly link readers to the correct location in the docs, and for
better formatting and easier consumption.

### How?
Changes to many `.mdx` files in the `docs` folder.

Notes:
- There are duplicative section id's in `docs/authentication/email.mdx`,
I've fixed one such link, but have left it as is for now.
2025-01-03 21:41:33 -07:00
Angel P.
d6d9edc304 docs: warn when using defaultPopulate on collections with uploads enabled (#10138)
When `defaultPopulate` is enabled without specifying `filename: true`
and `url: true` for collections with an upload field. The upload will
not have a valid URL when returned from Payload APIs and will instead be
returned with a value of `null`

<!--

Thank you for the PR! Please go through the checklist below and make
sure you've completed all the steps.

Please review the
[CONTRIBUTING.md](https://github.com/payloadcms/payload/blob/main/CONTRIBUTING.md)
document in this repository if you haven't already.

The following items will ensure that your PR is handled as smoothly as
possible:

- PR Title must follow conventional commits format. For example, `feat:
my new feature`, `fix(plugin-seo): my fix`.
- Minimal description explained as if explained to someone not
immediately familiar with the code.
- Provide before/after screenshots or code diffs if applicable.
- Link any related issues/discussions from GitHub or Discord.
- Add review comments if necessary to explain to the reviewer the logic
behind a change

### What?

### Why?

### How?

Fixes #

-->

---------

Co-authored-by: Sasha <64744993+r1tsuu@users.noreply.github.com>
2025-01-02 23:08:07 +00:00
Alexander Cato
b2042c5754 docs: fix typo in join.mdx (#10190) 2025-01-02 19:44:25 +00:00
Sasha
76e44024cc docs: explicit payload usage from req to avoid import payload confusion (#10291) 2025-01-01 01:49:20 +00:00
Said Akhrarov
b6de432ab2 docs: fix all missing vertical lines in tables (#10288) 2024-12-31 14:11:47 -07:00
Boyan Bratvanov
950f8ce80a docs: add missing vertical line to Collection Upload options table (#10282)
The missing line doesn't break Github's markdown table row rendering,
but it does break it on the website.
2024-12-31 20:06:56 +00:00
Jacob Fletcher
be87ba0ecd docs: adds useListQuery to list of React hooks and updates useDocumentInfo (#10186)
The `useListQuery` was currently undocumented and the `useDocumentInfo`
hook was out of date.
2024-12-31 16:31:23 +00:00
Alessio Gravili
182eaa3433 feat(richtext-lexical): ability to override default placeholder (#10278)
![CleanShot 2024-12-30 at 23 28
01@2x](https://github.com/user-attachments/assets/0bab3a2a-bded-440f-9bfe-cb8bf5b74e2a)

![CleanShot 2024-12-30 at 23 28
08@2x](https://github.com/user-attachments/assets/589b7be0-f662-4c4a-b66b-66f9b88ee7c6)
2024-12-31 07:09:03 +00:00
Alessio Gravili
943798a784 docs(richtext-lexical): minor improvements (#10280) 2024-12-31 00:04:27 -07:00
Alessio Gravili
6e19e8288f docs(richtext-lexical): improve building custom feature docs, add example for custom blocks (code field within lexical) (#10279) 2024-12-31 06:56:33 +00:00
Said Akhrarov
313b4ba535 docs: fix dispatch actions link for useFormFields and useAllFormFields (#10273) 2024-12-30 19:28:15 -07:00
Alessio Gravili
5b4730d13c docs: fix incorrect escaping of * (#10274) 2024-12-30 17:02:13 -07:00
James Mikrut
7a59e7da46 feat: adds more control over how to disable graphql for collections /… (#10265)
Adds more control over how you can disable GraphQL queries / mutations
for collections and globals.

For example, you might want to disable all GraphQL queries and mutations
for a given collection, but you still have relationship fields that
relate to that collection, therefore depend on the types being
generated.

Now, instead of passing `graphQL: false` (which completely disables
everything, including types, which would break relationship fields) you
can now specify `graphQL.disableQueries: true` and
`graphQL.disableMutations: true`to keep the types, but disable just the
queries / mutations.

Closes #9893
2024-12-30 22:20:31 +00:00
James Mikrut
fe010b9373 Update drafts.mdx 2024-12-30 11:26:21 -05:00
Sasha
63bca12f87 docs: fix docs for generate db schema (#10251)
<!--

Thank you for the PR! Please go through the checklist below and make
sure you've completed all the steps.

Please review the
[CONTRIBUTING.md](https://github.com/payloadcms/payload/blob/main/CONTRIBUTING.md)
document in this repository if you haven't already.

The following items will ensure that your PR is handled as smoothly as
possible:

- PR Title must follow conventional commits format. For example, `feat:
my new feature`, `fix(plugin-seo): my fix`.
- Minimal description explained as if explained to someone not
immediately familiar with the code.
- Provide before/after screenshots or code diffs if applicable.
- Link any related issues/discussions from GitHub or Discord.
- Add review comments if necessary to explain to the reviewer the logic
behind a change

### What?

### Why?

### How?

Fixes #

-->
2024-12-30 16:03:46 +00:00
James Mikrut
6af6e44683 docs: adds notes about importance of serverURL for verify / forgot-pa… (#10248)
Fixes #10235
2024-12-30 10:20:28 -05:00
James Mikrut
363a24cea5 docs: add clarity about forgot-password and verify tokens (#10247)
Adds clarity to `verifyEmail` docs, noting that the token for
`forgotPassword` is different.

Fixes #10236
2024-12-30 10:04:54 -05:00
Alessio Gravili
3218b0dcb6 docs: fix backtick escaping in TableWithDrawers blocks (#10220) 2024-12-28 06:39:55 +00:00
Alessio Gravili
466ea292b9 docs: correctly escape backticks (#10217) 2024-12-28 05:18:15 +00:00
Alessio Gravili
3278f450c7 docs: correctly escape backticks (#10216) 2024-12-28 04:57:29 +00:00
Seno
da518f53e8 docs: fix typo (#10214) 2024-12-28 04:40:20 +00:00
Alessio Gravili
78b6d51e58 docs: fix incorrect docs for complex mdx components (#10212) 2024-12-27 19:57:00 -07:00
Alessio Gravili
29c5bcdc18 docs: fix syntax that couldn't be parsed (#10207) 2024-12-27 15:12:14 -07:00
James Mikrut
37d1f2d04b feat: scheduled publish / unpublish (#10203)
Adds a feature to allow editors to schedule publish / unpublish events
in the future. Must be enabled by setting
`versions.drafts.schedulePublish: true` in your Collection / Global
configs.


https://github.com/user-attachments/assets/ca1d7a8b-946a-4eac-b911-c2177dbe3b1c

Todo:

- [x] Translate new i18n keys
- [x] Wire up locale-specific scheduled publish / unpublish actions
2024-12-27 16:52:18 -05:00
James Mikrut
cf8c0ae959 feat: adds req to filterOptions args (#10204)
Adds `req` to `filterOptions` arguments.
2024-12-27 21:38:14 +00:00
Alessio Gravili
bb0c8a8c62 docs: fix incorrect mdx (#10201) 2024-12-27 20:18:31 +00:00
Sasha
6b4842d44d feat(cpa): create project from example using --example CLI arg (#10172)
Adds the ability to create a project using an existing in the Payload
repo example through `create-payload-app`:

For example:
`pnpx create-payload-app --example custom-server` - creates a project
from the
[custom-server](https://github.com/payloadcms/payload/tree/main/examples/custom-server)
example.

This is much easier and faster then downloading the whole repo and
copying the example to another folder.
Note that we don't configure the payload config with the storage / DB
adapter there because examples can be very specific.
2024-12-27 20:16:34 +02:00
Tobias Arends
a49e63cd7a docs: fix arg name in live preview code example (#10127)
Updates outdated code example to match the current docs and api.
2024-12-27 09:53:54 -05:00