Skip to content
Permalink

Comparing changes

Choose two branches to see what’s changed or to start a new pull request. If you need to, you can also or learn more about diff comparisons.

Open a pull request

Create a new pull request by comparing changes across two branches. If you need to, you can also . Learn more about diff comparisons here.
base repository: payloadcms/payload
Failed to load repositories. Confirm that selected base ref is valid, then try again.
Loading
base: v3.84.1
Choose a base ref
...
head repository: payloadcms/payload
Failed to load repositories. Confirm that selected head ref is valid, then try again.
Loading
compare: v3.85.0
Choose a head ref
  • 19 commits
  • 194 files changed
  • 8 contributors

Commits on Apr 29, 2026

  1. fix(richtext-lexical): drag/drop image into rich text fails when a fi…

    …eld name matches the collection slug (#16409)
    
    ## Summary
    
    Backport of #16397 to 3.x.
    
    When a top-level rich text field has the same `name` as the collection's
    `slug`, dragging or pasting an image into the editor opens a blank bulk
    upload drawer. The lexical field and the document layout both mount a
    `BulkUploadProvider`; when the field path equals the collection slug
    they compute the same drawer slug and render two drawers for it, one
    with empty state (blank), which is what the user sees.
    
    The fix is a 1-line change: namespace the lexical field's nested
    `BulkUploadProvider` with a `lexical-` prefix so its drawer slug can
    never collide with the document-level provider.
    
    ```diff
    - <BulkUploadProvider drawerSlugPrefix={path}>
    + <BulkUploadProvider drawerSlugPrefix={`lexical-${path}`}>
    ```
    
    The rest of the diff is a new e2e test.
    
    ## Test plan
    
    Added
    `test/lexical/collections/LexicalSlugFieldNameCollision/e2e.spec.ts`,
    which asserts that dropping a file into a rich text editor opens exactly
    one bulk upload drawer when the field name equals the collection slug.
    Verified that the test fails without the production change (`Expected:
    1, Received: 2`) and passes with it.
    
    Co-authored-by: German Jablonski <GermanJablo@users.noreply.github.com>
    GermanJablo and GermanJablo authored Apr 29, 2026
    Configuration menu
    Copy the full SHA
    d6f7b47 View commit details
    Browse the repository at this point in the history

Commits on May 4, 2026

  1. Configuration menu
    Copy the full SHA
    3cd4a64 View commit details
    Browse the repository at this point in the history
  2. Configuration menu
    Copy the full SHA
    695df3c View commit details
    Browse the repository at this point in the history
  3. Configuration menu
    Copy the full SHA
    0facc44 View commit details
    Browse the repository at this point in the history
  4. Configuration menu
    Copy the full SHA
    caf9150 View commit details
    Browse the repository at this point in the history

Commits on May 5, 2026

  1. Configuration menu
    Copy the full SHA
    931a349 View commit details
    Browse the repository at this point in the history

Commits on May 6, 2026

  1. Configuration menu
    Copy the full SHA
    64b2860 View commit details
    Browse the repository at this point in the history

Commits on May 7, 2026

  1. Configuration menu
    Copy the full SHA
    8d14915 View commit details
    Browse the repository at this point in the history
  2. Configuration menu
    Copy the full SHA
    c31f4ef View commit details
    Browse the repository at this point in the history
  3. templates: bumps next.js to 16.2.6 (#16538)

    This bumps the Next.js version in our templates and monorepo to 16.2.6.
    It also bumps the minimum supported Next.js 16 version to 16.2.6, to
    discourage people from using a Next.js version with known CVEs.
    AlessioGr authored May 7, 2026
    Configuration menu
    Copy the full SHA
    9b36063 View commit details
    Browse the repository at this point in the history

Commits on May 8, 2026

  1. fix: bump uuid package to 13.0.2 (#16545)

    Fixes #16459
    
    Bumps the uuid package from 11.1.0 to 13.0.2 to fix
    [GHSA-w5hq-g745-h8pq](GHSA-w5hq-g745-h8pq).
    
    Can't bump to v14, as v14 drops support for node 18.
    AlessioGr authored May 8, 2026
    Configuration menu
    Copy the full SHA
    274af06 View commit details
    Browse the repository at this point in the history
  2. docs: adds relevant videos to docs sections (#16516)

    - modular dashboard
    - ecommerce plugin
    - hooks
    - import-export plugin
    - mcp plugin
    - multi-tenant plugin
    - production deployment (vercel, cloudflare)
    zubricks authored May 8, 2026
    Configuration menu
    Copy the full SHA
    d17298f View commit details
    Browse the repository at this point in the history

Commits on May 11, 2026

  1. feat(plugin-import-export): out of beta and added support for collect…

    …ion-level and field-level hooks (#16556)
    
    ### Plugin out of beta
    
    The import export plugin is now marked as stable and will be moved out
    of beta. For v4 we will be removing the deprecated APIs but for v3 they
    will remain supported.
    
    ### Why
    
    Field-level hooks are essential because:
    
    1. **Co-location** — the transform behavior lives next to the field
    definition, not in a separate collection config
    2. **Reusability** — a shared field config carries its hooks to every
    collection that uses it, zero duplication
    3. **Deeply nested fields** — transforming
    `group.tabs.namedTab.array[0].field` in a collection-level hook requires
    manually navigating the full document structure; field-level hooks
    handle this transparently
    
    This PR keeps both levels: field-level hooks for per-field transforms,
    collection-level hooks for batch-wide operations (masking, logging,
    filtering).
    
    
    ## Field-level hooks
    
    Defined per-field via `custom['plugin-import-export'].hooks`:
    
    ```ts
    import type { FieldBeforeExportHook } from '@payloadcms/plugin-import-export'
    
    const authorField = {
      name: 'author',
      type: 'relationship',
      relationTo: 'users',
      custom: {
        'plugin-import-export': {
          hooks: {
            // Runs before the field value is written to the export file
            beforeExport: (({ value, columnName, row, format }) => {
              if (format === 'csv' && value && typeof value === 'object' && 'id' in value) {
                row[`${columnName}_id`] = value.id
                row[`${columnName}_email`] = value.email
                return undefined // let row mutation take effect
              }
              return value
            }) satisfies FieldBeforeExportHook,
    
            // Runs before the field value is written to the database
            beforeImport: ({ value, columnName, data, format }) => {
              if (format === 'csv') {
                return data[`${columnName}_id`] ?? undefined
              }
              return value
            },
          },
        },
      },
    }
    ```
    
    ## Collection-level hooks
    Defined in the plugin config:
    
    ```ts
    importExportPlugin({
      collections: [
        {
          slug: 'users',
          export: {
            hooks: {
              before: ({ data, format }) => {
                // Mask sensitive fields from the entire batch
                return data.map(({ passwordHash, ssn, ...safe }) => safe)
              },
              after: ({ batchNumber, totalBatches, req }) => {
                req.payload.logger.info(`Export batch ${batchNumber}/${totalBatches} written`)
              },
            },
          },
        },
      ],
    })
    ```
    
    #### Execution order
    
    field-level `hooks.beforeExport` / `hooks.beforeImport` run first
    (per-field, per-document), then collection-level `hooks.before` /
    `hooks.after` run on the already-transformed batch.
    
    #### Migration from toCSV / fromCSV
    
    toCSV and fromCSV remain fully functional but are deprecated — removed
    in v4.0. Migration is a 1:1 rename plus the new format parameter:
    
    
    ```ts
    // Before (deprecated)
    custom: {
      'plugin-import-export': {
        toCSV: ({ value, row }) => { ... },
        fromCSV: ({ value, data }) => { ... },
      },
    }
    
    // After
    custom: {
      'plugin-import-export': {
        hooks: {
          beforeExport: ({ value, row, format }) => { ... },
          beforeImport: ({ value, data, format }) => { ... },
        },
      },
    }
    
    ```
    
    ## What changed
    
    ### New types
    
    `FieldBeforeExportHook` — field-level export hook type (same args as
    ToCSVFunction + format)
    `FieldBeforeImportHook` — field-level import hook type (same args as
    FromCSVFunction + format)
    `ToCSVFunction` / `FromCSVFunction` — now deprecated aliases
    
    #### JSON format support (new)
    
    - Field-level hooks now fire for JSON exports/imports, not just CSV
    - New applyFieldExportHooks / applyFieldImportHooks utilities traverse
    nested JSON documents and apply field hooks at each position
    - Preview handlers also apply field hooks for both CSV and JSON
    
    ## Bug fixes
    
    - [x] Fixed parentPath key computation in getExportFieldFunctions /
    getImportFieldFunctions — named tabs inside groups now produce correct
    underscore-separated keys (pre-existing bug)
    - [x] Fixed slice(-0) bug in import batchProcessor.ts — ImportAfterHook
    was receiving all accumulated errors instead of per-batch errors when a
    batch had zero failures
    - [x] Removed unused fs import from hooks.int.spec.ts
    
    ## Renamed internals
    
    - toCSVFunctions → exportFieldHooks throughout all source files
    - fromCSVFunctions → importFieldHooks throughout all source files
    - Error messages updated from "toCSVFunction" to "field export hook"
    
    ## Checklist
    - [x] Documentation updated with new API, migration guide, execution
    order
    - [x]  Test collection PostsWithFieldHooks with field-level hooks
    - [x] 12 new integration tests (CSV export, JSON export, format
    parameter, deeply nested fields, CSV import, JSON import, backward
    compatibility with toCSV, backward compatibility with fromCSV, execution
    order, reusable field config, priority, default behaviour)
    paulpopus authored May 11, 2026
    Configuration menu
    Copy the full SHA
    cf9252d View commit details
    Browse the repository at this point in the history

Commits on May 18, 2026

  1. chore(deps): bump nodemailer minimum version to 8.0.5 (#16664)

    Supersedes #16501.
    
    Related: #16651.
    
    Bumps `nodemailer` to `^8.0.5` and `@types/nodemailer` to `^8.0.0`
    throughout the monorepo.
    
    The `nodemailer@7.0.12` package has known advisories that are fixed in
    >= 8.0.5.
    - GHSA-vvjj-xcjg-gr5g
    - GHSA-c7w3-x93f-qmm8
    
    Note: `nodemailer` v8 widened the `Mail.Options['from']` type to also
    accept an array. This is considered a breaking change in Payload's
    `SendEmailOptions` type, if a project code relies on the previous shape.
    
    For backwards compatibility, we pin `SendEmailOptions['from']` back to
    v7's `string | Address` shape, then normalize this at runtime, so email
    adapters and consumer code stay source-compatible.
    
    ---
    - To see the specific tasks where the Asana app for GitHub is being
    used, see below:
      - https://app.asana.com/0/0/1214892618463672
    
    ---------
    
    Co-authored-by: Andrea Barani <andrea.barani@vubai.com>
    jacobsfletch and abarani authored May 18, 2026
    Configuration menu
    Copy the full SHA
    efa4afe View commit details
    Browse the repository at this point in the history

Commits on May 19, 2026

  1. fix(db-mongodb): bump mongoose to 8.22.1 for GHSA-wpg9-53fq-2r8h (#16688

    )
    
    Identical to #16672,
    back-ported for 3.x.
    jacobsfletch authored May 19, 2026
    Configuration menu
    Copy the full SHA
    4baba91 View commit details
    Browse the repository at this point in the history

Commits on May 20, 2026

  1. Configuration menu
    Copy the full SHA
    055c508 View commit details
    Browse the repository at this point in the history

Commits on May 21, 2026

  1. ci: use postgres 15 for content api tests (#16706)

    Content API Tests are currently failing because this job boots the
    latest Figma-hosted Content API image against `postgres:13`. The latest
    image includes https://github.com/figma/figma/pull/776922, which added
    PG15-only `UNIQUE NULLS NOT DISTINCT` index syntax, so Content API
    migrations fail before Payload tests run. cc @asalani-figma
    
    Failed job example:
    - Content API Tests on #16702:
    https://github.com/payloadcms/payload/actions/runs/26216770563/job/77142295149?pr=16702
    
    This updates only the ephemeral database used by the Content API service
    in Payload CI. That database belongs to Figma-hosted Content API, not
    Payload or the database adapter, so matching Content API's Postgres
    requirement is the intended fix here.
    
    ---------
    
    Co-authored-by: German Jablonski <GermanJablo@users.noreply.github.com>
    GermanJablo and GermanJablo authored May 21, 2026
    Configuration menu
    Copy the full SHA
    99d4930 View commit details
    Browse the repository at this point in the history
  2. docs: fix links in admin faq (#16711)

    fixes broken links in admin overview FAQ section 
    - `[/customizing-location]` (wrong)
    - `[/admin-panel-location]`(right)
    zubricks authored May 21, 2026
    Configuration menu
    Copy the full SHA
    7e4f7af View commit details
    Browse the repository at this point in the history

Commits on May 26, 2026

  1. Configuration menu
    Copy the full SHA
    957a92e View commit details
    Browse the repository at this point in the history
Loading