WARNING: THIS SITE IS A MIRROR OF GITHUB.COM / IT CANNOT LOGIN OR REGISTER ACCOUNTS / THE CONTENTS ARE PROVIDED AS-IS / THIS SITE ASSUMES NO RESPONSIBILITY FOR ANY DISPLAYED CONTENT OR LINKS / IF YOU FOUND SOMETHING MAY NOT GOOD FOR EVERYONE, CONTACT ADMIN AT ilovescratch@foxmail.com
Skip to content

v3.62.0

Choose a tag to compare

@denolfe denolfe released this 30 Oct 18:09
· 169 commits to main since this release
d401424

v3.62.0 (2025-10-30)

🚀 Features

Jobs Access Control

Adds role-based access control for job queue and cancel operations, allowing you to restrict who can manage background jobs in your application. Both operations now support overrideAccess parameter and respect custom access control functions defined in your jobs configuration. #14404

// Configure access control
jobs: {
  access: {
    queue: ({ req }) => req.user?.roles?.includes('admin'),
    cancel: ({ req }) => req.user?.roles?.includes('admin'),
  }
}

// Use in Local API
await payload.jobs.cancel({
  where: { workflowSlug: { equals: 'sync' } },
  overrideAccess: false,
  req,
})

Per-Field Timezone Configuration

Date fields can now have individual timezone settings, allowing different date fields to support their own list of supported timezones with custom default values. This enables more flexible date handling across your application. #14410

{
  name: 'date',
  type: 'date',
  timezone: {
    defaultTimezone: 'America/New_York',
    supportedTimezones: [
      { label: 'New York', value: 'America/New_York' },
      { label: 'Los Angeles', value: 'America/Los_Angeles' },
      { label: 'London', value: 'Europe/London' },
    ],
  },
}

You can also enforce a specific timezone by specifying just one with a default value:

{
  name: 'date',
  type: 'date',
  timezone: {
    defaultTimezone: 'Europe/London',
    supportedTimezones: [
      { label: 'London', value: 'Europe/London' },
    ],
  },
}

KV Storage Adapters

Introduces a new key-value storage system with multiple adapter options (Database, In-Memory, Redis) for enhanced data persistence and performance. This provides the foundation for the upcoming Realtime API and other features requiring fast key-value access. #9913

Access the KV store via payload.kv with the following interface:

interface KVAdapter {
  /**
   * Clears all entries in the store.
   * @returns A promise that resolves once the store is cleared.
   */
  clear(): Promise<void>

  /**
   * Deletes a value from the store by its key.
   * @param key - The key to delete.
   * @returns A promise that resolves once the key is deleted.
   */
  delete(key: string): Promise<void>

  /**
   * Retrieves a value from the store by its key.
   * @param key - The key to look up.
   * @returns A promise that resolves to the value, or `null` if not found.
   */
  get(key: string): Promise<KVStoreValue | null>

  /**
   * Checks if a key exists in the store.
   * @param key - The key to check.
   * @returns A promise that resolves to `true` if the key exists, otherwise `false`.
   */
  has(key: string): Promise<boolean>

  /**
   * Retrieves all the keys in the store.
   * @returns A promise that resolves to an array of keys.
   */
  keys(): Promise<string[]>

  /**
   * Sets a value in the store with the given key.
   * @param key - The key to associate with the value.
   * @param value - The value to store.
   * @returns A promise that resolves once the value is stored.
   */
  set(key: string, value: KVStoreValue): Promise<void>
}

Configure the adapter using the kv property:

buildConfig({
  kv: adapter()
})

Database KV adapter (default) - Uses your existing database with a hidden payload-kv collection:

import { databaseKVAdapter } from 'payload'

buildConfig({
  kv: databaseKVAdapter({
    kvCollectionOverrides: {
      slug: 'custom-kv',
      ...(process.env.DEBUG === 'true' && {
        admin: { hidden: false },
        access: {},
      }),
    },
  }),
})

In Memory KV adapter - Fast memory-based storage for development:

import { inMemoryKVAdapter } from 'payload'

buildConfig({
  kv: inMemoryKVAdapter(),
})

Redis KV Adapter - Production-ready Redis integration:

pnpm add @payloadcms/kv-redis
import { redisKVAdapter } from '@payloadcms/kv-redis'

buildConfig({
  kv: redisKVAdapter({
    keyPrefix: "custom-prefix:", // defaults to 'payload-kv:'
    redisURL: "redis://127.0.0.1:6379" // defaults to process.env.REDIS_URL
  }),
})

Configurable Toast Position

Toast notifications can now be positioned anywhere on the screen (top-left, top-center, top-right, bottom-left, bottom-center, bottom-right), giving you control over where important messages appear to your users. This is particularly useful for applications with large screens or specific UI layouts. #14405

The position configuration is a direct pass-through of the Sonner library's position options, with 'bottom-right' remaining the default.

Feature PRs

🐛 Bug Fixes

  • globals with versions return _status field when access denied (#14406) (b766ae6)
  • custom dashboard component causes runtime error on create-first-user and account views (#14393) (d5f4e72)
  • claude: remove invalid frontmatter fields (#14411) (118d005)
  • db-*: findMigrationDir in projects without src folder (#14381) (059185f)
  • db-mongodb: migration fails for cosmosDB (#14401) (10a640c)
  • db-mongodb: type error with prodMigrations (#14394) (8e5e23a)
  • db-mongodb: duplicate ids in sanitizeQueryValue (#11905) (36bb188)
  • db-postgres: hasMany relationship/number/text fields inside blocks are incorrectly returned when using select (#14399) (850cc38)
  • drizzle: number fields in generated schema with defaultValue (#14365) (8996b35)
  • plugin-multi-tenant: remove unused syncTenants from useEffect deps (#14362) (906a3dc)
  • richtext-lexical: do not run json.parse if value is undefined or null (#14385) (09a6140)
  • richtext-lexical: prevent TS CodeBlocks from sharing Monaco model (useId) (#14351) (5caebd1)
  • storage-*: update the client cache to use a map instead with cache keys per bucket config (#14267) (38f2e1f)
  • ui: where builder crashing with invalid queries (#14342) (6c83046)

🛠 Refactors

  • deprecate job queue depth property (#14402) (1341f69)
  • ui: simplify ConfigProvider, improve useControllableState types and defaultValue fallback (#14409) (255320e)

⚙️ CI

  • add claude as valid scope (560f2f3)

🤝 Contributors