@payloadcms/codemod 4.0.0-internal.2f0d313 → 4.0.0-internal.31ba7ee
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +69 -39
- package/dist/cli.d.ts.map +1 -1
- package/dist/cli.js +28 -9
- package/dist/cli.js.map +1 -1
- package/dist/cli.parseFlags.d.ts +10 -1
- package/dist/cli.parseFlags.d.ts.map +1 -1
- package/dist/cli.parseFlags.js +16 -8
- package/dist/cli.parseFlags.js.map +1 -1
- package/dist/registry.d.ts.map +1 -1
- package/dist/registry.js +15 -1
- package/dist/registry.js.map +1 -1
- package/dist/runbook/payload-v4-upgrade.md +2 -2
- package/dist/runbook/v4.mdx +556 -31
- package/dist/transforms/add-override-access-true/basic.input.js +41 -0
- package/dist/transforms/add-override-access-true/basic.input.js.map +1 -0
- package/dist/transforms/add-override-access-true/basic.output.js +50 -0
- package/dist/transforms/add-override-access-true/basic.output.js.map +1 -0
- package/dist/transforms/add-override-access-true/comment-between-properties.input.js +11 -0
- package/dist/transforms/add-override-access-true/comment-between-properties.input.js.map +1 -0
- package/dist/transforms/add-override-access-true/comment-between-properties.output.js +12 -0
- package/dist/transforms/add-override-access-true/comment-between-properties.output.js.map +1 -0
- package/dist/transforms/add-override-access-true/index.d.ts +20 -0
- package/dist/transforms/add-override-access-true/index.d.ts.map +1 -0
- package/dist/transforms/add-override-access-true/index.js +208 -0
- package/dist/transforms/add-override-access-true/index.js.map +1 -0
- package/dist/transforms/add-override-access-true/javascript.input.d.ts +6 -0
- package/dist/transforms/add-override-access-true/javascript.input.d.ts.map +1 -0
- package/dist/transforms/add-override-access-true/javascript.input.js +24 -0
- package/dist/transforms/add-override-access-true/javascript.input.js.map +1 -0
- package/dist/transforms/add-override-access-true/javascript.output.d.ts +6 -0
- package/dist/transforms/add-override-access-true/javascript.output.d.ts.map +1 -0
- package/dist/transforms/add-override-access-true/javascript.output.js +26 -0
- package/dist/transforms/add-override-access-true/javascript.output.js.map +1 -0
- package/dist/transforms/add-override-access-true/non-matching.input.js +42 -0
- package/dist/transforms/add-override-access-true/non-matching.input.js.map +1 -0
- package/dist/transforms/add-override-access-true/non-matching.output.js +42 -0
- package/dist/transforms/add-override-access-true/non-matching.output.js.map +1 -0
- package/dist/transforms/add-override-access-true/single-line.input.js +13 -0
- package/dist/transforms/add-override-access-true/single-line.input.js.map +1 -0
- package/dist/transforms/add-override-access-true/single-line.output.js +17 -0
- package/dist/transforms/add-override-access-true/single-line.output.js.map +1 -0
- package/dist/transforms/add-override-access-true/trailing-comment.input.js +10 -0
- package/dist/transforms/add-override-access-true/trailing-comment.input.js.map +1 -0
- package/dist/transforms/add-override-access-true/trailing-comment.output.js +12 -0
- package/dist/transforms/add-override-access-true/trailing-comment.output.js.map +1 -0
- package/dist/transforms/migrate-aliased-exports/index.d.ts.map +1 -1
- package/dist/transforms/migrate-aliased-exports/index.js +6 -5
- package/dist/transforms/migrate-aliased-exports/index.js.map +1 -1
- package/dist/transforms/migrate-aliased-exports/request.input.js +6 -0
- package/dist/transforms/migrate-aliased-exports/request.input.js.map +1 -0
- package/dist/transforms/migrate-aliased-exports/request.output.js +5 -0
- package/dist/transforms/migrate-aliased-exports/request.output.js.map +1 -0
- package/dist/transforms/migrate-authorship-default/already-set.input.js +15 -0
- package/dist/transforms/migrate-authorship-default/already-set.input.js.map +1 -0
- package/dist/transforms/migrate-authorship-default/already-set.output.js +15 -0
- package/dist/transforms/migrate-authorship-default/already-set.output.js.map +1 -0
- package/dist/transforms/migrate-authorship-default/basic.input.js +16 -0
- package/dist/transforms/migrate-authorship-default/basic.input.js.map +1 -0
- package/dist/transforms/migrate-authorship-default/basic.output.js +18 -0
- package/dist/transforms/migrate-authorship-default/basic.output.js.map +1 -0
- package/dist/transforms/migrate-authorship-default/build-config.input.js +32 -0
- package/dist/transforms/migrate-authorship-default/build-config.input.js.map +1 -0
- package/dist/transforms/migrate-authorship-default/build-config.output.js +35 -0
- package/dist/transforms/migrate-authorship-default/build-config.output.js.map +1 -0
- package/dist/transforms/migrate-authorship-default/globals.input.js +16 -0
- package/dist/transforms/migrate-authorship-default/globals.input.js.map +1 -0
- package/dist/transforms/migrate-authorship-default/globals.output.js +17 -0
- package/dist/transforms/migrate-authorship-default/globals.output.js.map +1 -0
- package/dist/transforms/migrate-authorship-default/index.d.ts +11 -0
- package/dist/transforms/migrate-authorship-default/index.d.ts.map +1 -0
- package/dist/transforms/migrate-authorship-default/index.js +141 -0
- package/dist/transforms/migrate-authorship-default/index.js.map +1 -0
- package/dist/transforms/migrate-authorship-default/non-matching.input.js +18 -0
- package/dist/transforms/migrate-authorship-default/non-matching.input.js.map +1 -0
- package/dist/transforms/migrate-authorship-default/non-matching.output.js +18 -0
- package/dist/transforms/migrate-authorship-default/non-matching.output.js.map +1 -0
- package/dist/transforms/migrate-authorship-default/satisfies.input.js +11 -0
- package/dist/transforms/migrate-authorship-default/satisfies.input.js.map +1 -0
- package/dist/transforms/migrate-authorship-default/satisfies.output.js +13 -0
- package/dist/transforms/migrate-authorship-default/satisfies.output.js.map +1 -0
- package/dist/transforms/migrate-field-component-types/basic.input.js +8 -0
- package/dist/transforms/migrate-field-component-types/basic.input.js.map +1 -0
- package/dist/transforms/migrate-field-component-types/basic.output.js +8 -0
- package/dist/transforms/migrate-field-component-types/basic.output.js.map +1 -0
- package/dist/transforms/migrate-field-component-types/index.d.ts +3 -0
- package/dist/transforms/migrate-field-component-types/index.d.ts.map +1 -0
- package/dist/transforms/migrate-field-component-types/index.js +616 -0
- package/dist/transforms/migrate-field-component-types/index.js.map +1 -0
- package/dist/transforms/migrate-payload-request-creation/aliases.input.js +8 -0
- package/dist/transforms/migrate-payload-request-creation/aliases.input.js.map +1 -0
- package/dist/transforms/migrate-payload-request-creation/aliases.output.js +31 -0
- package/dist/transforms/migrate-payload-request-creation/aliases.output.js.map +1 -0
- package/dist/transforms/migrate-payload-request-creation/collision.input.js +9 -0
- package/dist/transforms/migrate-payload-request-creation/collision.input.js.map +1 -0
- package/dist/transforms/migrate-payload-request-creation/comments.input.js +9 -0
- package/dist/transforms/migrate-payload-request-creation/comments.input.js.map +1 -0
- package/dist/transforms/migrate-payload-request-creation/comments.output.js +34 -0
- package/dist/transforms/migrate-payload-request-creation/comments.output.js.map +1 -0
- package/dist/transforms/migrate-payload-request-creation/empty.input.js +5 -0
- package/dist/transforms/migrate-payload-request-creation/empty.input.js.map +1 -0
- package/dist/transforms/migrate-payload-request-creation/empty.output.js +7 -0
- package/dist/transforms/migrate-payload-request-creation/empty.output.js.map +1 -0
- package/dist/transforms/migrate-payload-request-creation/evaluation-order.input.js +10 -0
- package/dist/transforms/migrate-payload-request-creation/evaluation-order.input.js.map +1 -0
- package/dist/transforms/migrate-payload-request-creation/expression.input.js +8 -0
- package/dist/transforms/migrate-payload-request-creation/expression.input.js.map +1 -0
- package/dist/transforms/migrate-payload-request-creation/expression.output.js +8 -0
- package/dist/transforms/migrate-payload-request-creation/expression.output.js.map +1 -0
- package/dist/transforms/migrate-payload-request-creation/getters.input.js +52 -0
- package/dist/transforms/migrate-payload-request-creation/getters.input.js.map +1 -0
- package/dist/transforms/migrate-payload-request-creation/index.d.ts +3 -0
- package/dist/transforms/migrate-payload-request-creation/index.d.ts.map +1 -0
- package/dist/transforms/migrate-payload-request-creation/index.js +236 -0
- package/dist/transforms/migrate-payload-request-creation/index.js.map +1 -0
- package/dist/transforms/migrate-payload-request-creation/internal.input.js +6 -0
- package/dist/transforms/migrate-payload-request-creation/internal.input.js.map +1 -0
- package/dist/transforms/migrate-payload-request-creation/internal.output.js +6 -0
- package/dist/transforms/migrate-payload-request-creation/internal.output.js.map +1 -0
- package/dist/transforms/migrate-payload-request-creation/non-matching.input.js +5 -0
- package/dist/transforms/migrate-payload-request-creation/non-matching.input.js.map +1 -0
- package/dist/transforms/migrate-payload-request-creation/populated.input.js +7 -0
- package/dist/transforms/migrate-payload-request-creation/populated.input.js.map +1 -0
- package/dist/transforms/migrate-payload-request-creation/populated.output.js +30 -0
- package/dist/transforms/migrate-payload-request-creation/populated.output.js.map +1 -0
- package/dist/transforms/migrate-payload-request-creation/shadowed.input.js +7 -0
- package/dist/transforms/migrate-payload-request-creation/shadowed.input.js.map +1 -0
- package/dist/transforms/migrate-payload-request-creation/shadowed.output.js +9 -0
- package/dist/transforms/migrate-payload-request-creation/shadowed.output.js.map +1 -0
- package/dist/transforms/migrate-payload-request-creation/shorthand.input.js +12 -0
- package/dist/transforms/migrate-payload-request-creation/shorthand.input.js.map +1 -0
- package/dist/transforms/migrate-payload-request-creation/shorthand.output.js +12 -0
- package/dist/transforms/migrate-payload-request-creation/shorthand.output.js.map +1 -0
- package/dist/transforms/migrate-payload-request-creation/unsupported.input.js +9 -0
- package/dist/transforms/migrate-payload-request-creation/unsupported.input.js.map +1 -0
- package/dist/transforms/migrate-versions-default/index.js +5 -5
- package/dist/transforms/migrate-versions-default/index.js.map +1 -1
- package/dist/transforms/remove-default-locale-publish-option/all-value.input.js +13 -0
- package/dist/transforms/remove-default-locale-publish-option/all-value.input.js.map +1 -0
- package/dist/transforms/remove-default-locale-publish-option/basic.input.js +13 -0
- package/dist/transforms/remove-default-locale-publish-option/basic.input.js.map +1 -0
- package/dist/transforms/remove-default-locale-publish-option/basic.output.js +12 -0
- package/dist/transforms/remove-default-locale-publish-option/basic.output.js.map +1 -0
- package/dist/transforms/remove-default-locale-publish-option/dynamic.input.js +17 -0
- package/dist/transforms/remove-default-locale-publish-option/dynamic.input.js.map +1 -0
- package/dist/transforms/remove-default-locale-publish-option/index.d.ts +10 -0
- package/dist/transforms/remove-default-locale-publish-option/index.d.ts.map +1 -0
- package/dist/transforms/remove-default-locale-publish-option/index.js +103 -0
- package/dist/transforms/remove-default-locale-publish-option/index.js.map +1 -0
- package/dist/transforms/remove-default-locale-publish-option/no-match.input.js +10 -0
- package/dist/transforms/remove-default-locale-publish-option/no-match.input.js.map +1 -0
- package/dist/transforms/remove-default-locale-publish-option/no-match.output.js +10 -0
- package/dist/transforms/remove-default-locale-publish-option/no-match.output.js.map +1 -0
- package/dist/transforms/remove-default-locale-publish-option/reassigned.input.js +22 -0
- package/dist/transforms/remove-default-locale-publish-option/reassigned.input.js.map +1 -0
- package/dist/transforms/remove-default-locale-publish-option/shorthand.input.js +14 -0
- package/dist/transforms/remove-default-locale-publish-option/shorthand.input.js.map +1 -0
- package/dist/transforms/remove-default-locale-publish-option/shorthand.output.js +13 -0
- package/dist/transforms/remove-default-locale-publish-option/shorthand.output.js.map +1 -0
- package/dist/transforms/remove-publish-specific-locale/index.d.ts.map +1 -1
- package/dist/transforms/remove-publish-specific-locale/index.js.map +1 -1
- package/dist/transforms/remove-storage-always-insert-fields/aliased.input.js +11 -0
- package/dist/transforms/remove-storage-always-insert-fields/aliased.input.js.map +1 -0
- package/dist/transforms/remove-storage-always-insert-fields/aliased.output.js +10 -0
- package/dist/transforms/remove-storage-always-insert-fields/aliased.output.js.map +1 -0
- package/dist/transforms/remove-storage-always-insert-fields/basic.input.js +54 -0
- package/dist/transforms/remove-storage-always-insert-fields/basic.input.js.map +1 -0
- package/dist/transforms/remove-storage-always-insert-fields/basic.output.js +48 -0
- package/dist/transforms/remove-storage-always-insert-fields/basic.output.js.map +1 -0
- package/dist/transforms/remove-storage-always-insert-fields/index.d.ts +3 -0
- package/dist/transforms/remove-storage-always-insert-fields/index.d.ts.map +1 -0
- package/dist/transforms/remove-storage-always-insert-fields/index.js +71 -0
- package/dist/transforms/remove-storage-always-insert-fields/index.js.map +1 -0
- package/dist/transforms/remove-storage-always-insert-fields/no-match.input.js +27 -0
- package/dist/transforms/remove-storage-always-insert-fields/no-match.input.js.map +1 -0
- package/dist/transforms/remove-storage-always-insert-fields/no-match.output.js +27 -0
- package/dist/transforms/remove-storage-always-insert-fields/no-match.output.js.map +1 -0
- package/dist/transforms/remove-versions-true/index.js +4 -4
- package/dist/transforms/remove-versions-true/index.js.map +1 -1
- package/dist/transforms/rename-experimental-table-feature/alias.input.js +6 -0
- package/dist/transforms/rename-experimental-table-feature/alias.input.js.map +1 -0
- package/dist/transforms/rename-experimental-table-feature/alias.output.js +6 -0
- package/dist/transforms/rename-experimental-table-feature/alias.output.js.map +1 -0
- package/dist/transforms/rename-experimental-table-feature/basic.input.js +19 -0
- package/dist/transforms/rename-experimental-table-feature/basic.input.js.map +1 -0
- package/dist/transforms/rename-experimental-table-feature/basic.output.js +19 -0
- package/dist/transforms/rename-experimental-table-feature/basic.output.js.map +1 -0
- package/dist/transforms/rename-experimental-table-feature/collision.input.js +7 -0
- package/dist/transforms/rename-experimental-table-feature/collision.input.js.map +1 -0
- package/dist/transforms/rename-experimental-table-feature/index.d.ts +3 -0
- package/dist/transforms/rename-experimental-table-feature/index.d.ts.map +1 -0
- package/dist/transforms/rename-experimental-table-feature/index.js +44 -0
- package/dist/transforms/rename-experimental-table-feature/index.js.map +1 -0
- package/dist/transforms/rename-experimental-table-feature/no-match.input.js +9 -0
- package/dist/transforms/rename-experimental-table-feature/no-match.input.js.map +1 -0
- package/dist/upgrade/defaultTag.d.ts +9 -0
- package/dist/upgrade/defaultTag.d.ts.map +1 -0
- package/dist/upgrade/defaultTag.js +25 -0
- package/dist/upgrade/defaultTag.js.map +1 -0
- package/dist/upgrade/dispatch.d.ts +38 -0
- package/dist/upgrade/dispatch.d.ts.map +1 -0
- package/dist/upgrade/dispatch.js +132 -0
- package/dist/upgrade/dispatch.js.map +1 -0
- package/dist/upgrade/index.d.ts +2 -1
- package/dist/upgrade/index.d.ts.map +1 -1
- package/dist/upgrade/index.js +49 -24
- package/dist/upgrade/index.js.map +1 -1
- package/dist/upgrade/prompt.d.ts +6 -3
- package/dist/upgrade/prompt.d.ts.map +1 -1
- package/dist/upgrade/prompt.js +11 -9
- package/dist/upgrade/prompt.js.map +1 -1
- package/dist/upgrade/report.d.ts +3 -0
- package/dist/upgrade/report.d.ts.map +1 -1
- package/dist/upgrade/report.js +8 -2
- package/dist/upgrade/report.js.map +1 -1
- package/dist/upgrade/rewritePackageJson.d.ts +7 -0
- package/dist/upgrade/rewritePackageJson.d.ts.map +1 -1
- package/dist/upgrade/rewritePackageJson.js +24 -7
- package/dist/upgrade/rewritePackageJson.js.map +1 -1
- package/dist/upgrade/selectAgent.d.ts +45 -0
- package/dist/upgrade/selectAgent.d.ts.map +1 -0
- package/dist/upgrade/selectAgent.js +54 -0
- package/dist/upgrade/selectAgent.js.map +1 -0
- package/dist/upgrade/selfCommand.d.ts +13 -0
- package/dist/upgrade/selfCommand.d.ts.map +1 -0
- package/dist/upgrade/selfCommand.js +17 -0
- package/dist/upgrade/selfCommand.js.map +1 -0
- package/dist/upgrade/types.d.ts +5 -0
- package/dist/upgrade/types.d.ts.map +1 -1
- package/dist/upgrade/types.js +4 -0
- package/dist/upgrade/types.js.map +1 -1
- package/package.json +4 -3
- package/dist/cli.parseFlags.spec.d.ts +0 -2
- package/dist/cli.parseFlags.spec.d.ts.map +0 -1
- package/dist/cli.parseFlags.spec.js +0 -121
- package/dist/cli.parseFlags.spec.js.map +0 -1
- package/dist/runner.spec.d.ts +0 -2
- package/dist/runner.spec.d.ts.map +0 -1
- package/dist/runner.spec.js +0 -88
- package/dist/runner.spec.js.map +0 -1
- package/dist/transforms/example-noop/index.spec.d.ts +0 -2
- package/dist/transforms/example-noop/index.spec.d.ts.map +0 -1
- package/dist/transforms/example-noop/index.spec.js +0 -29
- package/dist/transforms/example-noop/index.spec.js.map +0 -1
- package/dist/transforms/globals-components-edit/index.spec.d.ts +0 -2
- package/dist/transforms/globals-components-edit/index.spec.d.ts.map +0 -1
- package/dist/transforms/globals-components-edit/index.spec.js +0 -37
- package/dist/transforms/globals-components-edit/index.spec.js.map +0 -1
- package/dist/transforms/migrate-after-operation-read/index.spec.d.ts +0 -2
- package/dist/transforms/migrate-after-operation-read/index.spec.d.ts.map +0 -1
- package/dist/transforms/migrate-after-operation-read/index.spec.js +0 -62
- package/dist/transforms/migrate-after-operation-read/index.spec.js.map +0 -1
- package/dist/transforms/migrate-aliased-exports/index.spec.d.ts +0 -2
- package/dist/transforms/migrate-aliased-exports/index.spec.d.ts.map +0 -1
- package/dist/transforms/migrate-aliased-exports/index.spec.js +0 -55
- package/dist/transforms/migrate-aliased-exports/index.spec.js.map +0 -1
- package/dist/transforms/migrate-azure-chunk-large-files/index.spec.d.ts +0 -2
- package/dist/transforms/migrate-azure-chunk-large-files/index.spec.d.ts.map +0 -1
- package/dist/transforms/migrate-azure-chunk-large-files/index.spec.js +0 -67
- package/dist/transforms/migrate-azure-chunk-large-files/index.spec.js.map +0 -1
- package/dist/transforms/migrate-block-references-to-blocks/index.spec.d.ts +0 -2
- package/dist/transforms/migrate-block-references-to-blocks/index.spec.d.ts.map +0 -1
- package/dist/transforms/migrate-block-references-to-blocks/index.spec.js +0 -45
- package/dist/transforms/migrate-block-references-to-blocks/index.spec.js.map +0 -1
- package/dist/transforms/migrate-build-script/index.spec.d.ts +0 -2
- package/dist/transforms/migrate-build-script/index.spec.d.ts.map +0 -1
- package/dist/transforms/migrate-build-script/index.spec.js +0 -81
- package/dist/transforms/migrate-build-script/index.spec.js.map +0 -1
- package/dist/transforms/migrate-db-types-subpath/index.spec.d.ts +0 -2
- package/dist/transforms/migrate-db-types-subpath/index.spec.d.ts.map +0 -1
- package/dist/transforms/migrate-db-types-subpath/index.spec.js +0 -46
- package/dist/transforms/migrate-db-types-subpath/index.spec.js.map +0 -1
- package/dist/transforms/migrate-disabled-fields/index.spec.d.ts +0 -2
- package/dist/transforms/migrate-disabled-fields/index.spec.d.ts.map +0 -1
- package/dist/transforms/migrate-disabled-fields/index.spec.js +0 -73
- package/dist/transforms/migrate-disabled-fields/index.spec.js.map +0 -1
- package/dist/transforms/migrate-document-title-context/index.spec.d.ts +0 -2
- package/dist/transforms/migrate-document-title-context/index.spec.d.ts.map +0 -1
- package/dist/transforms/migrate-document-title-context/index.spec.js +0 -86
- package/dist/transforms/migrate-document-title-context/index.spec.js.map +0 -1
- package/dist/transforms/migrate-force-select/index.spec.d.ts +0 -2
- package/dist/transforms/migrate-force-select/index.spec.d.ts.map +0 -1
- package/dist/transforms/migrate-force-select/index.spec.js +0 -107
- package/dist/transforms/migrate-force-select/index.spec.js.map +0 -1
- package/dist/transforms/migrate-hide-api-url/index.spec.d.ts +0 -2
- package/dist/transforms/migrate-hide-api-url/index.spec.d.ts.map +0 -1
- package/dist/transforms/migrate-hide-api-url/index.spec.js +0 -118
- package/dist/transforms/migrate-hide-api-url/index.spec.js.map +0 -1
- package/dist/transforms/migrate-import-export-hooks/index.spec.d.ts +0 -2
- package/dist/transforms/migrate-import-export-hooks/index.spec.d.ts.map +0 -1
- package/dist/transforms/migrate-import-export-hooks/index.spec.js +0 -65
- package/dist/transforms/migrate-import-export-hooks/index.spec.js.map +0 -1
- package/dist/transforms/migrate-list-view-select-api/index.spec.d.ts +0 -2
- package/dist/transforms/migrate-list-view-select-api/index.spec.d.ts.map +0 -1
- package/dist/transforms/migrate-list-view-select-api/index.spec.js +0 -37
- package/dist/transforms/migrate-list-view-select-api/index.spec.js.map +0 -1
- package/dist/transforms/migrate-next-generate-viewport-export/index.spec.d.ts +0 -2
- package/dist/transforms/migrate-next-generate-viewport-export/index.spec.d.ts.map +0 -1
- package/dist/transforms/migrate-next-generate-viewport-export/index.spec.js +0 -41
- package/dist/transforms/migrate-next-generate-viewport-export/index.spec.js.map +0 -1
- package/dist/transforms/migrate-next-subpath-exports/index.spec.d.ts +0 -2
- package/dist/transforms/migrate-next-subpath-exports/index.spec.d.ts.map +0 -1
- package/dist/transforms/migrate-next-subpath-exports/index.spec.js +0 -46
- package/dist/transforms/migrate-next-subpath-exports/index.spec.js.map +0 -1
- package/dist/transforms/migrate-slug-field/index.spec.d.ts +0 -2
- package/dist/transforms/migrate-slug-field/index.spec.d.ts.map +0 -1
- package/dist/transforms/migrate-slug-field/index.spec.js +0 -47
- package/dist/transforms/migrate-slug-field/index.spec.js.map +0 -1
- package/dist/transforms/migrate-storage-adapters-to-config/index.spec.d.ts +0 -2
- package/dist/transforms/migrate-storage-adapters-to-config/index.spec.d.ts.map +0 -1
- package/dist/transforms/migrate-storage-adapters-to-config/index.spec.js +0 -85
- package/dist/transforms/migrate-storage-adapters-to-config/index.spec.js.map +0 -1
- package/dist/transforms/migrate-versions-default/index.spec.d.ts +0 -2
- package/dist/transforms/migrate-versions-default/index.spec.d.ts.map +0 -1
- package/dist/transforms/migrate-versions-default/index.spec.js +0 -81
- package/dist/transforms/migrate-versions-default/index.spec.js.map +0 -1
- package/dist/transforms/remove-group-by-true/index.spec.d.ts +0 -2
- package/dist/transforms/remove-group-by-true/index.spec.d.ts.map +0 -1
- package/dist/transforms/remove-group-by-true/index.spec.js +0 -47
- package/dist/transforms/remove-group-by-true/index.spec.js.map +0 -1
- package/dist/transforms/remove-localize-status-config/index.spec.d.ts +0 -2
- package/dist/transforms/remove-localize-status-config/index.spec.d.ts.map +0 -1
- package/dist/transforms/remove-localize-status-config/index.spec.js +0 -38
- package/dist/transforms/remove-localize-status-config/index.spec.js.map +0 -1
- package/dist/transforms/remove-publish-specific-locale/index.spec.d.ts +0 -2
- package/dist/transforms/remove-publish-specific-locale/index.spec.d.ts.map +0 -1
- package/dist/transforms/remove-publish-specific-locale/index.spec.js +0 -47
- package/dist/transforms/remove-publish-specific-locale/index.spec.js.map +0 -1
- package/dist/transforms/remove-versions-true/index.spec.d.ts +0 -2
- package/dist/transforms/remove-versions-true/index.spec.d.ts.map +0 -1
- package/dist/transforms/remove-versions-true/index.spec.js +0 -38
- package/dist/transforms/remove-versions-true/index.spec.js.map +0 -1
- package/dist/transforms/rename-storage-adapters-to-storage/index.spec.d.ts +0 -2
- package/dist/transforms/rename-storage-adapters-to-storage/index.spec.d.ts.map +0 -1
- package/dist/transforms/rename-storage-adapters-to-storage/index.spec.js +0 -55
- package/dist/transforms/rename-storage-adapters-to-storage/index.spec.js.map +0 -1
- package/dist/transforms/rename-typescript-schema-to-json-schema/index.spec.d.ts +0 -2
- package/dist/transforms/rename-typescript-schema-to-json-schema/index.spec.d.ts.map +0 -1
- package/dist/transforms/rename-typescript-schema-to-json-schema/index.spec.js +0 -45
- package/dist/transforms/rename-typescript-schema-to-json-schema/index.spec.js.map +0 -1
- package/dist/upgrade/detectPackageManager.spec.d.ts +0 -2
- package/dist/upgrade/detectPackageManager.spec.d.ts.map +0 -1
- package/dist/upgrade/detectPackageManager.spec.js +0 -41
- package/dist/upgrade/detectPackageManager.spec.js.map +0 -1
- package/dist/upgrade/index.spec.d.ts +0 -2
- package/dist/upgrade/index.spec.d.ts.map +0 -1
- package/dist/upgrade/index.spec.js +0 -132
- package/dist/upgrade/index.spec.js.map +0 -1
- package/dist/upgrade/packaging.spec.d.ts +0 -2
- package/dist/upgrade/packaging.spec.d.ts.map +0 -1
- package/dist/upgrade/packaging.spec.js +0 -29
- package/dist/upgrade/packaging.spec.js.map +0 -1
- package/dist/upgrade/prompt.spec.d.ts +0 -2
- package/dist/upgrade/prompt.spec.d.ts.map +0 -1
- package/dist/upgrade/prompt.spec.js +0 -51
- package/dist/upgrade/prompt.spec.js.map +0 -1
- package/dist/upgrade/report.spec.d.ts +0 -2
- package/dist/upgrade/report.spec.d.ts.map +0 -1
- package/dist/upgrade/report.spec.js +0 -87
- package/dist/upgrade/report.spec.js.map +0 -1
- package/dist/upgrade/resolveVersions.spec.d.ts +0 -2
- package/dist/upgrade/resolveVersions.spec.d.ts.map +0 -1
- package/dist/upgrade/resolveVersions.spec.js +0 -82
- package/dist/upgrade/resolveVersions.spec.js.map +0 -1
- package/dist/upgrade/rewritePackageJson.spec.d.ts +0 -2
- package/dist/upgrade/rewritePackageJson.spec.d.ts.map +0 -1
- package/dist/upgrade/rewritePackageJson.spec.js +0 -108
- package/dist/upgrade/rewritePackageJson.spec.js.map +0 -1
- package/dist/upgrade/runInstall.spec.d.ts +0 -2
- package/dist/upgrade/runInstall.spec.d.ts.map +0 -1
- package/dist/upgrade/runInstall.spec.js +0 -48
- package/dist/upgrade/runInstall.spec.js.map +0 -1
- package/dist/utils/packageJson.spec.d.ts +0 -2
- package/dist/utils/packageJson.spec.d.ts.map +0 -1
- package/dist/utils/packageJson.spec.js +0 -41
- package/dist/utils/packageJson.spec.js.map +0 -1
package/dist/runbook/v4.mdx
CHANGED
|
@@ -22,10 +22,259 @@ The codemod is idempotent and safe to run on a partially-migrated project.
|
|
|
22
22
|
|
|
23
23
|
## Breaking Changes
|
|
24
24
|
|
|
25
|
+
### Payload request creation is consolidated
|
|
26
|
+
|
|
27
|
+
Payload request creation now uses `createPayloadRequest` for local contexts and `createPayloadRequestFromWebRequest` to convert a Web `Request`. Admin context setup is exposed as `initAdminContext`.
|
|
28
|
+
|
|
29
|
+
| Old name | New name |
|
|
30
|
+
| --------------------------------------- | ------------------------------------------- |
|
|
31
|
+
| `createLocalReq` | `createPayloadRequest` |
|
|
32
|
+
| `CreateLocalReqOptions` (internal type) | `Omit<CreatePayloadRequestArgs, 'payload'>` |
|
|
33
|
+
| `createPayloadRequest` | `createPayloadRequestFromWebRequest` |
|
|
34
|
+
| `initReq` | `initAdminContext` |
|
|
35
|
+
| `InitReqArgs` | `InitAdminContextArgs` |
|
|
36
|
+
| `InitReqResult` | `AdminContext` |
|
|
37
|
+
| `InitReqCache` | `AdminContextCache` |
|
|
38
|
+
| `InitReqPartialResult` | `PartialAdminContext` |
|
|
39
|
+
|
|
40
|
+
`initAdminContext` and its cache types are primarily contracts for framework adapters. Custom Root layout adapters must rename their injected `initReq` callback to `initAdminContext`.
|
|
41
|
+
|
|
42
|
+
Local request creation now takes a single object argument containing `payload`. For a request without options:
|
|
43
|
+
|
|
44
|
+
```diff
|
|
45
|
+
-import { createLocalReq } from 'payload'
|
|
46
|
+
+import { createPayloadRequest } from 'payload'
|
|
47
|
+
|
|
48
|
+
-const req = await createLocalReq({}, payload)
|
|
49
|
+
+const req = await createPayloadRequest({ payload })
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
`CreatePayloadRequestArgs` is exported from `payload` and requires `payload`. Options-only values should use `Omit<CreatePayloadRequestArgs, 'payload'>`. The old `CreateLocalReqOptions` type was declared in the internal request utility, not exported from the package root; relative/private imports of that type require manual migration. The codemod handles an existing named import of that type only when its source is `payload`.
|
|
53
|
+
|
|
54
|
+
Web request conversion uses its new role-specific name:
|
|
55
|
+
|
|
56
|
+
```diff
|
|
57
|
+
-import { createPayloadRequest } from 'payload'
|
|
58
|
+
+import { createPayloadRequestFromWebRequest } from 'payload'
|
|
59
|
+
|
|
60
|
+
-const req = await createPayloadRequest({ config, request })
|
|
61
|
+
+const req = await createPayloadRequestFromWebRequest({ config, request })
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
#### Codemod
|
|
65
|
+
|
|
66
|
+
To migrate automatically, there's a codemod for this change available by running:
|
|
67
|
+
|
|
68
|
+
```bash
|
|
69
|
+
npx @payloadcms/codemod --transform migrate-payload-request-creation
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
Automatic call migration requires a plain identifier payload argument and either `{}` or an initialized local `const` options identifier. The options type must expose all seven old option properties, or be `any`. For that identifier form, the generated argument captures payload first and uses forwarding getters for `context`, `depth`, `fallbackLocale`, `locale`, `req`, `urlSuffix`, and `user`. This preserves inherited getters, their read order, and rejected promises from throwing getters without reading unrelated properties. Complex expressions, mutable/unresolved options bindings, narrow option types, collisions, and unsupported type usages are left unchanged with notes for manual migration.
|
|
73
|
+
|
|
74
|
+
### JWT authentication is versioned without moving token data
|
|
75
|
+
|
|
76
|
+
Payload 4 keeps the decoded JWT payload flat, so integrations can continue reading `id`, `collection`, `sid`, `email`, and fields selected by `saveToJWT` from the same paths as Payload 3.
|
|
77
|
+
|
|
78
|
+
Payload now reserves `id`, `collection`, `email`, `sid`, `iat`, and `exp`. A `saveToJWT` alias using one of those names is ignored, and Payload writes the trusted value after collecting fields configured with `saveToJWT`. This prevents an alias such as `saveToJWT: 'id'` or `saveToJWT: 'collection'` from changing which user or collection the signed token authenticates as.
|
|
79
|
+
|
|
80
|
+
The token's signed protected header now contains `authVersion: 1`. This marker identifies tokens issued by the fixed authentication format. It lives in the header, rather than the payload, because earlier configurations could alias a field to any payload key. Payload rejects tokens that do not contain the supported header version.
|
|
81
|
+
|
|
82
|
+
```ts
|
|
83
|
+
// Decoded payload: unchanged paths
|
|
84
|
+
{
|
|
85
|
+
id: 'user-id',
|
|
86
|
+
collection: 'users',
|
|
87
|
+
sid: 'session-id',
|
|
88
|
+
email: 'user@example.com',
|
|
89
|
+
role: 'super-admin', // from saveToJWT
|
|
90
|
+
iat: 1750000000,
|
|
91
|
+
exp: 1750007200,
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
// Signed protected header
|
|
95
|
+
{
|
|
96
|
+
alg: 'HS256',
|
|
97
|
+
typ: 'JWT',
|
|
98
|
+
authVersion: 1,
|
|
99
|
+
}
|
|
100
|
+
```
|
|
101
|
+
|
|
102
|
+
Tokens issued by a patched Payload 3 release already contain the same `authVersion: 1` protected-header marker and remain valid after upgrading to Payload 4, provided the signing secrets and authentication collection configuration remain compatible.
|
|
103
|
+
|
|
104
|
+
Tokens issued by an unpatched Payload release do not contain the marker and are rejected. There is no safe compatibility fallback because a legacy token might have been signed after its trusted identity fields were overwritten. When upgrading directly from an unpatched release:
|
|
105
|
+
|
|
106
|
+
- Users must sign in again after deployment.
|
|
107
|
+
- Integrations must reissue stored bearer tokens.
|
|
108
|
+
- Expect a temporary spike in `401` responses until clients discard their stored tokens.
|
|
109
|
+
|
|
110
|
+
Raw-token consumers do not need to change token data paths, and `/me` returns the same data for a valid new token. External validators and integrations that mint Payload-compatible JWTs must set and check the protected-header version. Import Payload's shared version instead of hardcoding it:
|
|
111
|
+
|
|
112
|
+
```ts
|
|
113
|
+
import { decodeProtectedHeader } from 'jose'
|
|
114
|
+
import { JWT_AUTH_VERSION } from 'payload'
|
|
115
|
+
|
|
116
|
+
if (decodeProtectedHeader(token).authVersion !== JWT_AUTH_VERSION) {
|
|
117
|
+
throw new Error('Unsupported Payload token')
|
|
118
|
+
}
|
|
119
|
+
```
|
|
120
|
+
|
|
121
|
+
A token is also rejected if its `collection` is not auth-enabled or has `disableLocalStrategy` enabled.
|
|
122
|
+
|
|
123
|
+
See [Token Data](../authentication/token-data) for the full token data shape.
|
|
124
|
+
|
|
125
|
+
### `overrideAccess` now defaults to `false` on Local API operations
|
|
126
|
+
|
|
127
|
+
Local API operations whose optional `overrideAccess` value previously defaulted to `true` now default it to `false`, so omitting it respects Access Control instead. Operations that do not expose `overrideAccess`, and operations such as `resetPassword` where it was already required or did not default to `true`, are unaffected by this change.
|
|
128
|
+
|
|
129
|
+
```diff
|
|
130
|
+
const posts = await payload.find({
|
|
131
|
+
collection: 'posts',
|
|
132
|
+
+ overrideAccess: true, // preserves the Payload 3 default
|
|
133
|
+
})
|
|
134
|
+
```
|
|
135
|
+
|
|
136
|
+
- `overrideAccess: false` (the new default) — respect Access Control. Use this whenever the operation acts on behalf of a user, and pass `user` alongside it.
|
|
137
|
+
- `overrideAccess: true` — bypass Access Control. Use this for trusted server-side work such as cron jobs, seeding, and migrations.
|
|
138
|
+
|
|
139
|
+
The property stays optional on the affected operations, and there is no compile error for either TypeScript or JavaScript projects — a call that omitted `overrideAccess` before still compiles after upgrading, it just behaves differently: it now enforces Access Control instead of skipping it. Run the codemod to find every affected call site and restore the previous behavior explicitly:
|
|
140
|
+
|
|
141
|
+
```bash
|
|
142
|
+
npx @payloadcms/codemod
|
|
143
|
+
```
|
|
144
|
+
|
|
145
|
+
Review the results afterwards. Leave the property off, or set it to `overrideAccess: false`, wherever the operation acts on behalf of a user — that is the more secure outcome and is now the default.
|
|
146
|
+
|
|
147
|
+
#### Cases the codemod leaves behind
|
|
148
|
+
|
|
149
|
+
Run a typecheck after the codemod. Three patterns it cannot resolve:
|
|
150
|
+
|
|
151
|
+
- **Spread arguments** — `payload.find({ ...args })`. The codemod cannot tell whether `args` already supplies the property.
|
|
152
|
+
- **Aliased or cast receivers** — `const db = payload; db.find({ ... })` and `(payload as any).find({ ... })`. It matches `payload`, `.payload`, and their `.jobs` properties only.
|
|
153
|
+
- **Non-literal arguments** — `payload.find(options)`. The codemod cannot safely modify the value at the call site.
|
|
154
|
+
|
|
155
|
+
#### Jobs operations use the same default
|
|
156
|
+
|
|
157
|
+
`payload.jobs.queue`, `run`, `runByID`, `cancel`, and `cancelByID` now also default `overrideAccess` to `false`. The option remains optional, but omitting it runs the corresponding `jobs.access.queue`, `jobs.access.run`, or `jobs.access.cancel` function. The codemod adds `overrideAccess: true` to these calls—including zero-argument `payload.jobs.run()` calls—to preserve Payload 3 behavior for review.
|
|
158
|
+
|
|
25
159
|
### Collection and Global Access Control callbacks receive `slug`
|
|
26
160
|
|
|
27
161
|
Collection and Global Access Control callback arguments now include the document's `slug`. This additive property is unlikely to affect most projects, but code that manually invokes access callbacks or `executeAccess` must now pass `slug`. Code that validates, enumerates, or compares the exact callback argument shape may also need updating.
|
|
28
162
|
|
|
163
|
+
### Custom bin scripts replaced by native CLI commands
|
|
164
|
+
|
|
165
|
+
The `config.bin` API has been removed. Custom commands are now registered through `config.cli.commands` and use the same schema-backed CLI API as Payload's built-in commands.
|
|
166
|
+
|
|
167
|
+
In Payload 3.x, config entries connected a command name to a script path:
|
|
168
|
+
|
|
169
|
+
```ts
|
|
170
|
+
// payload.config.ts
|
|
171
|
+
export default buildConfig({
|
|
172
|
+
bin: [
|
|
173
|
+
{
|
|
174
|
+
key: 'seed',
|
|
175
|
+
scriptPath: path.resolve(dirname, 'seed.ts'),
|
|
176
|
+
},
|
|
177
|
+
],
|
|
178
|
+
})
|
|
179
|
+
```
|
|
180
|
+
|
|
181
|
+
The imported module had to expose a specially named `script` function:
|
|
182
|
+
|
|
183
|
+
```ts
|
|
184
|
+
// seed.ts
|
|
185
|
+
import type { SanitizedConfig } from 'payload'
|
|
186
|
+
|
|
187
|
+
import payload from 'payload'
|
|
188
|
+
|
|
189
|
+
export const script = async (config: SanitizedConfig) => {
|
|
190
|
+
await payload.init({ config })
|
|
191
|
+
// Seed the database...
|
|
192
|
+
process.exit(0)
|
|
193
|
+
}
|
|
194
|
+
```
|
|
195
|
+
|
|
196
|
+
In Payload 4.0, define a real CLI command instead:
|
|
197
|
+
|
|
198
|
+
```ts
|
|
199
|
+
// seed.ts
|
|
200
|
+
import { strictObject, z } from 'payload'
|
|
201
|
+
import { defineCLICommand } from 'payload/cli'
|
|
202
|
+
|
|
203
|
+
export const seedCommand = defineCLICommand({
|
|
204
|
+
description: 'Seed the database.',
|
|
205
|
+
input: strictObject({
|
|
206
|
+
clear: z
|
|
207
|
+
._default(z.boolean(), false)
|
|
208
|
+
.check(z.describe('Delete existing documents first.')),
|
|
209
|
+
}),
|
|
210
|
+
handler: async ({ args, getPayload }) => {
|
|
211
|
+
const payload = await getPayload()
|
|
212
|
+
|
|
213
|
+
if (args.clear) {
|
|
214
|
+
// Delete existing documents...
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
// Seed the database...
|
|
218
|
+
payload.logger.info('Successfully seeded!')
|
|
219
|
+
},
|
|
220
|
+
})
|
|
221
|
+
```
|
|
222
|
+
|
|
223
|
+
Register the command export in your Payload config:
|
|
224
|
+
|
|
225
|
+
```ts
|
|
226
|
+
// payload.config.ts
|
|
227
|
+
export default buildConfig({
|
|
228
|
+
cli: {
|
|
229
|
+
commands: {
|
|
230
|
+
seed: './seed.js#seedCommand',
|
|
231
|
+
},
|
|
232
|
+
},
|
|
233
|
+
})
|
|
234
|
+
```
|
|
235
|
+
|
|
236
|
+
When migrating custom scripts:
|
|
237
|
+
|
|
238
|
+
- Replace `bin` entries with entries in the `cli.commands` map. The map key becomes the command name.
|
|
239
|
+
- Replace the exported `script(config)` function with a schema-backed command created by `defineCLICommand`.
|
|
240
|
+
- Register commands by import path to keep them out of the Payload config's module graph. Paths use the existing `PayloadComponent` syntax, resolve relative to `payload.config.ts`, and support default or named exports. Direct `CLICommand` values are also accepted.
|
|
241
|
+
- Define the handler's semantic input with a Standard Schema implementation such as Zod. Supported top-level properties become options automatically; use `cli` only to mark positional arguments, hide fields, or override unusual shell syntax.
|
|
242
|
+
- Use the provided `getPayload()` function so Payload can shut down database connections after the command finishes.
|
|
243
|
+
- Return an exit code from the handler when needed. Do not call `process.exit()` from the command.
|
|
244
|
+
|
|
245
|
+
Payload adds built-in command import references to `cli.commands` while sanitizing the config, then applies project entries over those defaults. All built-ins are named exports from `payload/cli/builtin`, and Payload imports a referenced module only once even when it provides several commands. The sanitized map therefore contains the complete local CLI, and built-in and custom commands use the same loader. Custom commands appear in `payload --help` and receive Standard Schema validation and generated shell help. A command with the same map key as a built-in command replaces it, while `false` disables that command. Set `cli: false` to disable the entire Payload CLI. Command names are case-sensitive. Because custom commands must be registered before the CLI parses input, the Payload config is now loaded before displaying root CLI help.
|
|
246
|
+
|
|
247
|
+
See the [Payload CLI documentation](../configuration/cli) for the complete API.
|
|
248
|
+
|
|
249
|
+
### `migrateCLI` removed
|
|
250
|
+
|
|
251
|
+
The undocumented `migrateCLI` export has been removed. It accepted an already-sanitized config, a minimist-shaped `parsedArgs` object, and a special `migrationDir` override. This duplicated migration command registration and kept the old argument format alive after the main CLI moved to Commander.
|
|
252
|
+
|
|
253
|
+
If application code needs migration behavior rather than command-line parsing, call the database adapter directly through an initialized Payload instance:
|
|
254
|
+
|
|
255
|
+
```ts
|
|
256
|
+
await payload.db.migrate()
|
|
257
|
+
```
|
|
258
|
+
|
|
259
|
+
The adapter also exposes the corresponding `migrateDown`, `migrateFresh`, `migrateRefresh`, `migrateReset`, `migrateStatus`, and `createMigration` methods.
|
|
260
|
+
|
|
261
|
+
If you need to execute the real CLI from JavaScript, use the existing generic `payload.bin()` method. It starts the same CLI process a user would run in a terminal and returns its exit code:
|
|
262
|
+
|
|
263
|
+
```ts
|
|
264
|
+
import payload from 'payload'
|
|
265
|
+
|
|
266
|
+
const { code } = await payload.bin({
|
|
267
|
+
args: ['migrate:create', '--file', migrationPath],
|
|
268
|
+
cwd: projectDirectory,
|
|
269
|
+
})
|
|
270
|
+
```
|
|
271
|
+
|
|
272
|
+
The spawned CLI discovers the Payload config from `cwd` or `PAYLOAD_CONFIG_PATH`. Configure a custom migration directory through your database adapter instead of passing it as a programmatic CLI override.
|
|
273
|
+
|
|
274
|
+
### Generator helpers now return result objects
|
|
275
|
+
|
|
276
|
+
`generateTypes` now returns `{ types, outputFile, written }` instead of returning the generated source directly when using `returnString: true`. `generateImportMap` now returns `{ outputFile, written }`, and `payload.db.generateSchema()` returns `{ outputFile }`. Code that ignores these return values does not need to change.
|
|
277
|
+
|
|
29
278
|
### Default query depth reduced to `1`
|
|
30
279
|
|
|
31
280
|
Queries that omit `depth` now populate one relationship level instead of two. This reduces database work and response size by default.
|
|
@@ -35,6 +284,7 @@ If your application relies on two populated levels, prefer specifying `depth: 2`
|
|
|
35
284
|
```ts
|
|
36
285
|
const posts = await payload.find({
|
|
37
286
|
collection: 'posts',
|
|
287
|
+
overrideAccess: true,
|
|
38
288
|
depth: 2,
|
|
39
289
|
})
|
|
40
290
|
```
|
|
@@ -83,6 +333,56 @@ Run `migrate-versions-default` if you want zero schema changes — it adds `vers
|
|
|
83
333
|
|
|
84
334
|
Run `remove-versions-true` to clean up any bare `versions: true` that is now the default.
|
|
85
335
|
|
|
336
|
+
### Version read access inherits collection and global read access
|
|
337
|
+
|
|
338
|
+
When `readVersions` is not configured, version access now inherits the Collection or Global `read` Access Control instead of requiring an authenticated user by default.
|
|
339
|
+
|
|
340
|
+
This means a public `read` function can make historical and unpublished versions publicly readable, while a query constraint returned by `read` is also applied to version documents. If you want to preserve the previous authenticated-only behavior, configure `readVersions` explicitly:
|
|
341
|
+
|
|
342
|
+
```ts
|
|
343
|
+
export const Posts: CollectionConfig = {
|
|
344
|
+
slug: 'posts',
|
|
345
|
+
access: {
|
|
346
|
+
read: () => true,
|
|
347
|
+
readVersions: ({ req: { user } }) => Boolean(user),
|
|
348
|
+
},
|
|
349
|
+
fields: [],
|
|
350
|
+
}
|
|
351
|
+
```
|
|
352
|
+
|
|
353
|
+
### Authorship (`createdBy` / `updatedBy`) is now enabled by default
|
|
354
|
+
|
|
355
|
+
Collections and globals now track authorship by default: Payload injects `createdBy` and `updatedBy` polymorphic relationship fields (related to every auth-enabled collection) and stamps them from `req.user` on each write. Previously there was no authorship tracking; you now opt out with `authorship: false`.
|
|
356
|
+
|
|
357
|
+
**What changes:**
|
|
358
|
+
|
|
359
|
+
- Every non-internal collection and global gains `createdBy` and `updatedBy` when your config has at least one auth collection. On SQL adapters this adds relationship rows (stored in each entity's `_rels` table), so existing projects need a database migration. In development the schema is pushed automatically; in production, generate a migration with `payload migrate:create` and run `payload migrate`. Existing documents are backfilled with `null`.
|
|
360
|
+
- `createdBy` is only derived on a document's first write, so editing a document whose `createdBy` is `null` (for example a migrated or anonymously created document) does not backfill the editor as the creator.
|
|
361
|
+
- Payload's internal system collections and globals are excluded automatically: `payload-jobs`, `payload-jobs-stats`, `payload-preferences`, `payload-locked-documents`, `payload-migrations`, `payload-query-presets`, and the KV collection.
|
|
362
|
+
|
|
363
|
+
**Plugins:** plugin-injected collections also receive authorship unless the plugin opts out. In this release:
|
|
364
|
+
|
|
365
|
+
- **Opted out** (no authorship): `@payloadcms/plugin-search`, `@payloadcms/payload-cloud`, and all `@payloadcms/plugin-ecommerce` collections.
|
|
366
|
+
- **Kept on** (they gain `createdBy` / `updatedBy`): `@payloadcms/plugin-redirects`, `@payloadcms/plugin-form-builder` (forms and form submissions), and `@payloadcms/plugin-import-export` (imports and exports). Existing projects using these plugins on a SQL adapter need a migration for those collections too. To opt one out, set `authorship: false` through that plugin's collection-override option.
|
|
367
|
+
|
|
368
|
+
**To opt out for an existing collection or global:**
|
|
369
|
+
|
|
370
|
+
```diff
|
|
371
|
+
export const Posts: CollectionConfig = {
|
|
372
|
+
slug: 'posts',
|
|
373
|
+
fields: [],
|
|
374
|
+
+ authorship: false,
|
|
375
|
+
}
|
|
376
|
+
```
|
|
377
|
+
|
|
378
|
+
**A codemod is available** to preserve the previous behaviour:
|
|
379
|
+
|
|
380
|
+
```bash
|
|
381
|
+
npx @payloadcms/codemod --transform migrate-authorship-default
|
|
382
|
+
```
|
|
383
|
+
|
|
384
|
+
`migrate-authorship-default` adds `authorship: false` to every `CollectionConfig` and `GlobalConfig` in your source that does not already set `authorship`, so your own collections have zero schema changes. It only rewrites your config files — it cannot reach plugin-injected collections, so any plugin that keeps authorship on (above) still gains the fields and requires a migration (or an explicit `authorship: false` override).
|
|
385
|
+
|
|
86
386
|
### List View Select API is now the default
|
|
87
387
|
|
|
88
388
|
The `admin.enableListViewSelectAPI` Collection Config property has been removed. The List View now always uses the [Select API](../queries/select) to query only the active columns, which was previously opt-in.
|
|
@@ -178,20 +478,20 @@ Several types and utilities that were re-exported from `@payloadcms/ui` and `@pa
|
|
|
178
478
|
|
|
179
479
|
**Pass-through re-exports** — same name, new source:
|
|
180
480
|
|
|
181
|
-
| Symbol | Old source | New source
|
|
182
|
-
| ----------------------------- | ---------------------------- |
|
|
183
|
-
| `Column` | `@payloadcms/ui` | `payload`
|
|
184
|
-
| `ListViewSlots` | `@payloadcms/ui` | `payload`
|
|
185
|
-
| `ListViewClientProps` | `@payloadcms/ui` | `payload`
|
|
186
|
-
| `EntityType` | `@payloadcms/ui/shared` | `payload/shared`
|
|
187
|
-
| `formatAdminURL` | `@payloadcms/ui/shared` | `payload/shared`
|
|
188
|
-
| `mergeListSearchAndWhere` | `@payloadcms/ui/shared` | `payload/shared`
|
|
189
|
-
| `mergeHeaders` | `@payloadcms/next/utilities` | `payload`
|
|
190
|
-
| `headersWithCors` | `@payloadcms/next/utilities` | `payload`
|
|
191
|
-
| `createPayloadRequest` | `@payloadcms/next/utilities` | `payload`
|
|
192
|
-
| `addDataAndFileToRequest` | `@payloadcms/next/utilities` | `payload`
|
|
193
|
-
| `sanitizeLocales` | `@payloadcms/next/utilities` | `payload`
|
|
194
|
-
| `addLocalesToRequestFromData` | `@payloadcms/next/utilities` | `payload`
|
|
481
|
+
| Symbol | Old source | New source |
|
|
482
|
+
| ----------------------------- | ---------------------------- | ------------------------------------------------- |
|
|
483
|
+
| `Column` | `@payloadcms/ui` | `payload` |
|
|
484
|
+
| `ListViewSlots` | `@payloadcms/ui` | `payload` |
|
|
485
|
+
| `ListViewClientProps` | `@payloadcms/ui` | `payload` |
|
|
486
|
+
| `EntityType` | `@payloadcms/ui/shared` | `payload/shared` |
|
|
487
|
+
| `formatAdminURL` | `@payloadcms/ui/shared` | `payload/shared` |
|
|
488
|
+
| `mergeListSearchAndWhere` | `@payloadcms/ui/shared` | `payload/shared` |
|
|
489
|
+
| `mergeHeaders` | `@payloadcms/next/utilities` | `payload` |
|
|
490
|
+
| `headersWithCors` | `@payloadcms/next/utilities` | `payload` |
|
|
491
|
+
| `createPayloadRequest` | `@payloadcms/next/utilities` | `createPayloadRequestFromWebRequest` in `payload` |
|
|
492
|
+
| `addDataAndFileToRequest` | `@payloadcms/next/utilities` | `payload` |
|
|
493
|
+
| `sanitizeLocales` | `@payloadcms/next/utilities` | `payload` |
|
|
494
|
+
| `addLocalesToRequestFromData` | `@payloadcms/next/utilities` | `payload` |
|
|
195
495
|
|
|
196
496
|
**Renamed types** — use the new canonical name from `payload`:
|
|
197
497
|
|
|
@@ -210,7 +510,53 @@ Several types and utilities that were re-exported from `@payloadcms/ui` and `@pa
|
|
|
210
510
|
+ import { headersWithCors, mergeHeaders } from 'payload'
|
|
211
511
|
```
|
|
212
512
|
|
|
213
|
-
|
|
513
|
+
Running `npx @payloadcms/codemod --transform migrate-aliased-exports` preserves old local bindings by importing renamed symbols with an `as` alias (e.g. `import type { CollectionPreferences as ListPreferences } from 'payload'` or `import { createPayloadRequestFromWebRequest as createPayloadRequest } from 'payload'`). Run `migrate-payload-request-creation` to complete the request helper's identifier and call-site migration, or drop the other aliases and rename their usages manually if you want to fully commit to the new names.
|
|
514
|
+
|
|
515
|
+
### Field component types replaced by props types
|
|
516
|
+
|
|
517
|
+
Field component aliases that wrapped props in `React.ComponentType<Props>` have been removed. Import the props type directly so each component can use `React.FC<Props>` or a function declaration.
|
|
518
|
+
|
|
519
|
+
```diff
|
|
520
|
+
- import type { TextFieldClientComponent } from 'payload'
|
|
521
|
+
+ import type { TextFieldClientProps } from 'payload'
|
|
522
|
+
+ import type React from 'react'
|
|
523
|
+
|
|
524
|
+
- export const CustomTextField: TextFieldClientComponent = (props) => {
|
|
525
|
+
+ export const CustomTextField: React.FC<TextFieldClientProps> = (props) => {
|
|
526
|
+
// ...
|
|
527
|
+
}
|
|
528
|
+
```
|
|
529
|
+
|
|
530
|
+
Generic type arguments move to the props type:
|
|
531
|
+
|
|
532
|
+
```diff
|
|
533
|
+
- import type { FieldErrorClientComponent, TextFieldClient } from 'payload'
|
|
534
|
+
+ import type { FieldErrorClientProps, TextFieldClient } from 'payload'
|
|
535
|
+
+ import type React from 'react'
|
|
536
|
+
|
|
537
|
+
- const Error: FieldErrorClientComponent<TextFieldClient> = (props) => null
|
|
538
|
+
+ const Error: React.FC<FieldErrorClientProps<TextFieldClient>> = (props) => null
|
|
539
|
+
```
|
|
540
|
+
|
|
541
|
+
Function declarations can annotate their parameter without a component wrapper:
|
|
542
|
+
|
|
543
|
+
```tsx
|
|
544
|
+
import type { TextFieldServerProps } from 'payload'
|
|
545
|
+
|
|
546
|
+
export default async function CustomTextField(props: TextFieldServerProps) {
|
|
547
|
+
// ...
|
|
548
|
+
}
|
|
549
|
+
```
|
|
550
|
+
|
|
551
|
+
This covers main field components, labels, descriptions, errors, diffs, and block row labels. Admin-view types such as `AdminViewComponent` and `DocumentTabComponent` are separate.
|
|
552
|
+
|
|
553
|
+
#### Codemod
|
|
554
|
+
|
|
555
|
+
To migrate automatically, there's a codemod for this change available by running:
|
|
556
|
+
|
|
557
|
+
```bash
|
|
558
|
+
npx @payloadcms/codemod --transform migrate-field-component-types
|
|
559
|
+
```
|
|
214
560
|
|
|
215
561
|
### `DefaultValue` function variant is now typed to allow returning a `Promise` ([#17522](https://github.com/payloadcms/payload/pull/17522))
|
|
216
562
|
|
|
@@ -240,10 +586,9 @@ If you only use `DefaultValue` to type a `defaultValue` property passed into a C
|
|
|
240
586
|
|
|
241
587
|
`SanitizedCollectionConfig` and its auth type no longer use `DeepRequired`. This reduces TypeScript checker work and makes optionality match runtime defaults.
|
|
242
588
|
|
|
243
|
-
Properties Payload does not default, such as `
|
|
589
|
+
Properties Payload does not default, such as `auth.cookies.domain`, `auth.useAPIKey`, and `auth.depth`, now require undefined handling:
|
|
244
590
|
|
|
245
591
|
```ts
|
|
246
|
-
if (collection.access.readVersions) await collection.access.readVersions(args)
|
|
247
592
|
const useAPIKey = collection.auth.useAPIKey ?? false
|
|
248
593
|
```
|
|
249
594
|
|
|
@@ -264,12 +609,11 @@ Properties filled during sanitization, including `auth.jwtOrder`, root routes, G
|
|
|
264
609
|
|
|
265
610
|
### Sanitized global config types now match runtime defaults
|
|
266
611
|
|
|
267
|
-
`SanitizedGlobalConfig` no longer uses `DeepRequired`. This reduces TypeScript checker work and preserves optionality for values global sanitization does not populate, such as `
|
|
612
|
+
`SanitizedGlobalConfig` no longer uses `DeepRequired`. This reduces TypeScript checker work and preserves optionality for values global sanitization does not populate, such as `admin.components`, `graphQL`, `lockDocuments`, and `typescript`.
|
|
268
613
|
|
|
269
614
|
Code that consumes these properties may now need to handle `undefined`:
|
|
270
615
|
|
|
271
616
|
```ts
|
|
272
|
-
if (global.access.readVersions) await global.access.readVersions(args)
|
|
273
617
|
const views = global.admin.components?.views
|
|
274
618
|
const interfaceName = global.typescript?.interface
|
|
275
619
|
```
|
|
@@ -481,6 +825,36 @@ If you only used `useDocumentInfo` for `title` / `setDocumentTitle`, drop the im
|
|
|
481
825
|
|
|
482
826
|
Run `npx @payloadcms/codemod --transform migrate-document-title-context` to migrate automatically. The codemod splits mixed destructures, removes the `useDocumentInfo` import when no other properties are still used, and preserves any rename aliases (e.g. `{ title: docTitle }`).
|
|
483
827
|
|
|
828
|
+
### `useLocale` returns `null` without an active locale
|
|
829
|
+
|
|
830
|
+
The return type of `useLocale` is now `Locale | null`. It returns `null` when localization is disabled or configured without any locales. In Payload 3, the hook was typed as `Locale` and returned an empty object when localization was unavailable.
|
|
831
|
+
|
|
832
|
+
Custom Client Components that read locale properties directly must handle the nullable value:
|
|
833
|
+
|
|
834
|
+
```diff
|
|
835
|
+
'use client'
|
|
836
|
+
import { useLocale } from '@payloadcms/ui'
|
|
837
|
+
|
|
838
|
+
const Greeting: React.FC = () => {
|
|
839
|
+
- const { code } = useLocale()
|
|
840
|
+
+ const locale = useLocale()
|
|
841
|
+
+
|
|
842
|
+
+ if (!locale) {
|
|
843
|
+
+ return null
|
|
844
|
+
+ }
|
|
845
|
+
+
|
|
846
|
+
+ const { code } = locale
|
|
847
|
+
|
|
848
|
+
return <span>{code}</span>
|
|
849
|
+
}
|
|
850
|
+
```
|
|
851
|
+
|
|
852
|
+
When a missing locale is already valid for the receiving API, optional chaining is sufficient:
|
|
853
|
+
|
|
854
|
+
```ts
|
|
855
|
+
const locale = useLocale()?.code
|
|
856
|
+
```
|
|
857
|
+
|
|
484
858
|
### RichText adapter `i18n` property removed
|
|
485
859
|
|
|
486
860
|
The `i18n` property on `RichTextAdapter` (and its return type from adapter provider functions) has been removed. It was deprecated in v3 in favour of merging translations directly into `config.i18n.translations` inside the adapter provider.
|
|
@@ -713,9 +1087,9 @@ The deprecated `isHTMLElement` utility has been removed from `@payloadcms/richte
|
|
|
713
1087
|
|
|
714
1088
|
`lexical`'s built-in `isHTMLElement` is the canonical implementation and narrows against the node's owning-document `HTMLElement`, so it is also safe across iframes and other realms.
|
|
715
1089
|
|
|
716
|
-
### Lexical: vendored `@lexical/markdown` fork removed and lexical upgraded to `0.
|
|
1090
|
+
### Lexical: vendored `@lexical/markdown` fork removed and lexical upgraded to `0.52.0`
|
|
717
1091
|
|
|
718
|
-
`@payloadcms/richtext-lexical` no longer ships a vendored copy of `@lexical/markdown`. The package is now a direct dependency, every `@lexical/*` package was upgraded from `0.41.0` to `0.
|
|
1092
|
+
`@payloadcms/richtext-lexical` no longer ships a vendored copy of `@lexical/markdown`. The package is now a direct dependency, every `@lexical/*` package was upgraded from `0.41.0` to `0.52.0`, and `@payloadcms/richtext-lexical/lexical/markdown` is a pure passthrough of `@lexical/markdown`.
|
|
719
1093
|
|
|
720
1094
|
Most projects use markdown through the editor or through `convertMarkdownToLexical` / `convertLexicalToMarkdown` and need no changes. You are only affected if you import from `@payloadcms/richtext-lexical/lexical/markdown` directly.
|
|
721
1095
|
|
|
@@ -739,7 +1113,16 @@ If you keep calling `$convertFromMarkdownString` directly, pass `editorConfig.fe
|
|
|
739
1113
|
|
|
740
1114
|
**Whitespace-only markdown table cells now import as an empty paragraph** instead of a text node of padding spaces. This comes from the lexical upgrade, not Payload's own code. No action is required unless you assert on those padding spaces in stored content.
|
|
741
1115
|
|
|
742
|
-
If you import lexical APIs directly through `@payloadcms/richtext-lexical/lexical/*`, also review the [lexical breaking changes](https://github.com/facebook/lexical/releases) between `0.41.0` and `0.
|
|
1116
|
+
If you import lexical APIs directly through `@payloadcms/richtext-lexical/lexical/*`, also review the [lexical breaking changes](https://github.com/facebook/lexical/releases) between `0.41.0` and `0.52.0`. None of them require action for typical Payload usage.
|
|
1117
|
+
|
|
1118
|
+
If your app imports Lexical types or adds custom features, check these changes from `0.50.0`. They also apply to imports through `@payloadcms/richtext-lexical/lexical` and its subpaths:
|
|
1119
|
+
|
|
1120
|
+
- Lexical packages are ESM only. Use ESM imports; CommonJS `require()` needs Node.js 20.19 or later.
|
|
1121
|
+
- `SELECTION_CHANGE_COMMAND` now runs before DOM reconciliation. Defer DOM lookups and floating UI positioning with `$onUpdate(() => editor.read('latest', callback))`, or use an update listener for work that should run after every commit.
|
|
1122
|
+
- Call `node.getLatest().exportJSON()` when serializing a node reference retained across an update. Payload continues to write the full JSON format; compact export is not enabled.
|
|
1123
|
+
- `SerializedEditorState<T>`, `SerializedElementNode<T>`, and `SerializedRootNode<T>` no longer accept a type argument. Remove `<T>` if you only need the base node type. For a document with your own node types, use Payload's `TypedEditorState<T>` instead. Without a type argument, Lexical's `children` are still typed as `SerializedLexicalNode[]`.
|
|
1124
|
+
- `ReturnType<Node['exportJSON']>` can now infer partial JSON, making fields such as `version` and `url` optional. If your code expects the full format, use the node's explicit serialized type, such as `SerializedLinkNode`. A normal `node.exportJSON()` call still returns the full format.
|
|
1125
|
+
- `LexicalNode.getCommonAncestor` was removed. Use `$getCommonAncestor(a, b)?.commonAncestor ?? null`; pass the parents of non-element nodes if you need the old method's behavior.
|
|
743
1126
|
|
|
744
1127
|
### Lexical: `EXPERIMENTAL_TableFeature` renamed to `TableFeature`
|
|
745
1128
|
|
|
@@ -988,6 +1371,32 @@ And update any `$ref` pointers you wrote by hand to point at `$defs`:
|
|
|
988
1371
|
|
|
989
1372
|
Do not keep your additions on `definitions` while new ones land on `$defs`.
|
|
990
1373
|
|
|
1374
|
+
### Jobs: access is enforced by default
|
|
1375
|
+
|
|
1376
|
+
The generated `payload-jobs` collection now denies generic create, read, update, and delete access by default. This affects REST and GraphQL CRUD, plus Local API collection operations because `overrideAccess` now defaults to `false`.
|
|
1377
|
+
|
|
1378
|
+
Dedicated operations such as `payload.jobs.queue()`, `payload.jobs.run()`, `payload.jobs.runByID()`, `payload.jobs.cancel()`, and `payload.jobs.cancelByID()` also default `overrideAccess` to `false`. They now run the corresponding `jobs.access.queue`, `jobs.access.run`, or `jobs.access.cancel` function when the option is omitted. Add `overrideAccess: true` to trusted server-side calls that must preserve the Payload 3 behavior of bypassing Jobs access control.
|
|
1379
|
+
|
|
1380
|
+
If your application intentionally exposes the internal payload-jobs collection, configure only the access it needs through `jobsCollectionOverrides`. For example, the following enables read-only Admin Panel access for trusted administrators:
|
|
1381
|
+
|
|
1382
|
+
```ts
|
|
1383
|
+
jobs: {
|
|
1384
|
+
jobsCollectionOverrides: ({ defaultJobsCollection }) => ({
|
|
1385
|
+
...defaultJobsCollection,
|
|
1386
|
+
access: {
|
|
1387
|
+
...defaultJobsCollection.access,
|
|
1388
|
+
read: ({ req }) => Boolean(req.user?.roles?.includes('admin')),
|
|
1389
|
+
},
|
|
1390
|
+
admin: {
|
|
1391
|
+
...defaultJobsCollection.admin,
|
|
1392
|
+
hidden: false,
|
|
1393
|
+
},
|
|
1394
|
+
}),
|
|
1395
|
+
}
|
|
1396
|
+
```
|
|
1397
|
+
|
|
1398
|
+
Job documents can contain inputs, outputs, logs, and execution state, so avoid enabling write access unless your application specifically requires it.
|
|
1399
|
+
|
|
991
1400
|
### Jobs: `jobs.depth` and `jobs.runHooks` have been removed ([#16414](https://github.com/payloadcms/payload/pull/16414))
|
|
992
1401
|
|
|
993
1402
|
The deprecated `jobs.depth` and `jobs.runHooks` config options have been removed. Job operations now always use direct database calls with depth `0`.
|
|
@@ -1158,6 +1567,28 @@ The same change applies to `upload` fields with `hasMany: true`.
|
|
|
1158
1567
|
- Remove the `compatibility` block from your config. If your MongoDB data still has the redundant nested-localized shape, flatten the config and run a data migration.
|
|
1159
1568
|
- Replace any direct `field.localized` reads in custom code with `fieldShouldBeLocalized({ field, parentIsLocalized })` from `payload/shared`.
|
|
1160
1569
|
|
|
1570
|
+
### Admin UI Publish button now defaults to the active locale, and `localization.defaultLocalePublishOption` has been removed
|
|
1571
|
+
|
|
1572
|
+
The Admin UI Publish button now always defaults to publishing only the active locale when a collection or global has localized fields and you have publish permission. "Publish all locales" is available as a secondary option in the Publish button's dropdown. This previously required opting in via `localization.defaultLocalePublishOption: 'active'`; the config option has been removed since active-locale-only is now the permanent default.
|
|
1573
|
+
|
|
1574
|
+
**What changes:**
|
|
1575
|
+
|
|
1576
|
+
- `localization.defaultLocalePublishOption` no longer exists as a config property or type — remove it from your config.
|
|
1577
|
+
- If you had it set to `'active'`, there is no change in Admin UI behavior.
|
|
1578
|
+
- If you had it set to `'all'`, or left it unset, the Publish button now publishes only the active locale by default. Use the "Publish all locales" option in the button's dropdown to publish every locale at once.
|
|
1579
|
+
|
|
1580
|
+
```diff
|
|
1581
|
+
export default buildConfig({
|
|
1582
|
+
localization: {
|
|
1583
|
+
defaultLocale: 'en',
|
|
1584
|
+
- defaultLocalePublishOption: 'active',
|
|
1585
|
+
locales: ['en', 'es'],
|
|
1586
|
+
},
|
|
1587
|
+
})
|
|
1588
|
+
```
|
|
1589
|
+
|
|
1590
|
+
Run `npx @payloadcms/codemod --transform remove-default-locale-publish-option` to remove the property automatically. The codemod surfaces a note for any config that had it set to `'all'`, since that combination previously changed the default and now has no config equivalent.
|
|
1591
|
+
|
|
1161
1592
|
### Storage adapters must be declared under `storage`, not `plugins` ([#16596](https://github.com/payloadcms/payload/pull/16596))
|
|
1162
1593
|
|
|
1163
1594
|
Storage adapter packages (`@payloadcms/storage-s3`, `-azure`, `-gcs`, `-r2`, `-vercel-blob`) must now be placed under the top-level `storage` key in your Payload config instead of inside `plugins`.
|
|
@@ -1383,6 +1814,21 @@ azureStorage({
|
|
|
1383
1814
|
|
|
1384
1815
|
Run `npx @payloadcms/codemod --transform migrate-azure-chunk-large-files` to remove the flag automatically (it collapses `clientUploads: { chunkLargeFiles: true }` to `clientUploads: true` and keeps any other `clientUploads` options).
|
|
1385
1816
|
|
|
1817
|
+
### Storage adapters always insert the `prefix` field now — `alwaysInsertFields` removed
|
|
1818
|
+
|
|
1819
|
+
The `alwaysInsertFields` option (on `cloudStoragePlugin` and every `storage-*` adapter: `-s3`, `-azure`, `-gcs`, `-r2`, `-vercel-blob`) has been removed. The behavior it used to opt into — always inserting the hidden `prefix` field into the collection schema — is now unconditional, so the schema stays consistent whether or not a collection configures a `prefix` and whether or not the plugin is `enabled`.
|
|
1820
|
+
|
|
1821
|
+
**Who is affected:**
|
|
1822
|
+
|
|
1823
|
+
- Anyone with an upload collection that uses a storage adapter or `cloudStoragePlugin`. Every such collection now gets a hidden `prefix` field, including collections that never configured a `prefix` and collections where the plugin is disabled (`enabled: false`).
|
|
1824
|
+
- Anyone who set `alwaysInsertFields` explicitly — the option no longer exists on any storage adapter or plugin option type.
|
|
1825
|
+
- Postgres, SQLite, and D1 users: the new field is a new database column. Running `payload migrate:create` will generate a migration that adds a `prefix` column to every affected collection's table.
|
|
1826
|
+
|
|
1827
|
+
**How to migrate:**
|
|
1828
|
+
|
|
1829
|
+
- Remove `alwaysInsertFields` from your storage adapter or `cloudStoragePlugin` config — it has no effect and no longer exists on the option types.
|
|
1830
|
+
- For Postgres, SQLite, or D1 projects, run `payload migrate:create` to generate the migration that adds the `prefix` column, then run `payload migrate` to apply it.
|
|
1831
|
+
|
|
1386
1832
|
### `FileSizeImproved` removed — use `FileSize` ([#16593](https://github.com/payloadcms/payload/pull/16593))
|
|
1387
1833
|
|
|
1388
1834
|
`FileSizeImproved` has been merged into `FileSize`. The `url`, `width`, `height`, `filesize`, `mimeType`, and `filename` properties now accept `null` directly on `FileSize`, matching what the database stores for sizes that were not generated.
|
|
@@ -1468,7 +1914,7 @@ createAPIKeyFields({
|
|
|
1468
1914
|
|
|
1469
1915
|
The MCP plugin was refactored. The public config API, the built-in tool inputs, and API-key authentication changed. Update your plugin config and recreate MCP credentials as user API keys.
|
|
1470
1916
|
|
|
1471
|
-
**Collections and globals are now opt-out.** Drop the `enabled` flag. Every collection and global is exposed by default through the generic built-in tools. For collections, this includes tools like `getCollectionSchema`, `findDocuments`, `countDocuments`, `
|
|
1917
|
+
**Collections and globals are now opt-out.** Drop the `enabled` flag. Every collection and global is exposed by default through the generic built-in tools. For collections, this includes tools like `getCollectionSchema`, `findDocuments`, `countDocuments`, `createDocuments`, `updateDocument`, `deleteDocuments`, `duplicateDocument`, and `findDistinct`, plus version tools when versions are enabled. For globals, this includes `getGlobalSchema`, `findGlobal`, and `updateGlobal`, plus version tools when versions are enabled. Turn individual operations off via simple config keys like `tools: { create: false }`.
|
|
1472
1918
|
|
|
1473
1919
|
```diff
|
|
1474
1920
|
mcpPlugin({
|
|
@@ -1533,7 +1979,9 @@ const result = await req.payload.find({
|
|
|
1533
1979
|
})
|
|
1534
1980
|
```
|
|
1535
1981
|
|
|
1536
|
-
|
|
1982
|
+
Collection and global tool calls now use `slug` instead of `collectionSlug` or `globalSlug`. Update saved tool inputs and any code that calls these tools directly.
|
|
1983
|
+
|
|
1984
|
+
For custom collection and global tools, do not add `slug` yourself. Payload adds it to the MCP schema automatically, and the handler receives the resolved slug as a top-level argument.
|
|
1537
1985
|
|
|
1538
1986
|
```ts
|
|
1539
1987
|
defineCollectionTool({
|
|
@@ -1541,24 +1989,41 @@ defineCollectionTool({
|
|
|
1541
1989
|
input: z.object({
|
|
1542
1990
|
id: z.string(),
|
|
1543
1991
|
}),
|
|
1544
|
-
}).handler(async ({
|
|
1545
|
-
//
|
|
1992
|
+
}).handler(async ({ slug, input, req }) => {
|
|
1993
|
+
// slug is resolved from the tool call
|
|
1546
1994
|
})
|
|
1547
1995
|
```
|
|
1548
1996
|
|
|
1549
|
-
**Built-in collection tools are now generic.** Per-collection names like `createPosts` / `updatePosts` were replaced by `
|
|
1997
|
+
**Built-in collection tools are now generic.** Per-collection names like `createPosts` / `updatePosts` were replaced by `createDocuments` / `updateDocument`. Pass the target collection as `slug`. For creates, pass a `documents` array whose items contain `data` and an optional `file`; for updates, pass `data` with an `id` or `where` at the top level. Options such as `depth`, `draft`, and `locale` also remain at the top level. `_status`, `id`, `createdAt`, and `updatedAt` are no longer accepted inside `data`; set publish state with a custom tool if you need to.
|
|
1550
1998
|
|
|
1551
1999
|
```ts
|
|
1552
|
-
// arguments to a `
|
|
2000
|
+
// arguments to a `createDocuments` tool call
|
|
1553
2001
|
|
|
1554
2002
|
// before
|
|
1555
2003
|
{ title: 'Hello', _status: 'draft', draft: true, depth: 2 }
|
|
1556
2004
|
|
|
1557
2005
|
// after
|
|
1558
|
-
{
|
|
2006
|
+
{
|
|
2007
|
+
slug: 'posts',
|
|
2008
|
+
documents: [{ data: { title: 'Hello' } }],
|
|
2009
|
+
draft: true,
|
|
2010
|
+
depth: 2,
|
|
2011
|
+
}
|
|
2012
|
+
```
|
|
2013
|
+
|
|
2014
|
+
`createDocuments` and `updateDocument` now return affected document IDs instead of complete documents by default. Add `returning: true` to preserve the previous response. If the call uses `select`, it must also set `returning: true`.
|
|
2015
|
+
|
|
2016
|
+
**MCP URL uploads require an explicit allow-list.** Previously, MCP could download a URL when the upload collection's `pasteURL` was unset. Configure `upload.pasteURL.allowList` for collections that accept MCP URL uploads. The initial URL and any redirect targets must match; `skipSafeFetch` does not bypass this requirement. Base64 and upload-reference inputs are unaffected.
|
|
2017
|
+
|
|
2018
|
+
```ts
|
|
2019
|
+
upload: {
|
|
2020
|
+
pasteURL: {
|
|
2021
|
+
allowList: [{ hostname: 'cdn.example.com', protocol: 'https' }],
|
|
2022
|
+
},
|
|
2023
|
+
}
|
|
1559
2024
|
```
|
|
1560
2025
|
|
|
1561
|
-
**Auth tools are per-collection and opt-in.** The old `experimental.tools.auth` block is gone. Opt in per auth collection via its `tools` map, and pass the target auth collection as `
|
|
2026
|
+
**Auth tools are per-collection and opt-in.** The old `experimental.tools.auth` block is gone. Opt in per auth collection via its `tools` map, and pass the target auth collection as `slug`. Like every MCP item, auth tools now use default MCP access unless you provide an `access` callback, so unauthenticated auth tools such as `login` need `access: () => true`.
|
|
1562
2027
|
|
|
1563
2028
|
```diff
|
|
1564
2029
|
- mcpPlugin({ experimental: { tools: { auth: { enabled: true } } } })
|
|
@@ -1616,7 +2081,7 @@ Because the `payload-mcp-api-keys` collection config was removed, run your norma
|
|
|
1616
2081
|
|
|
1617
2082
|
By default, MCP items require an authenticated user. Built-in collection and global tools also include Payload permission checks in their default `access` callbacks. If you provide an `access` callback for a built-in tool, it replaces the default callback.
|
|
1618
2083
|
|
|
1619
|
-
**Dependencies.** The plugin now builds on `@modelcontextprotocol/server` instead of `@modelcontextprotocol/sdk` + `mcp-handler
|
|
2084
|
+
**Dependencies.** The plugin now builds on `@modelcontextprotocol/server` instead of `@modelcontextprotocol/sdk` + `mcp-handler`. It no longer depends on Zod directly; its built-in tools use the Zod Mini export from `payload`. If your custom tools use regular Zod, install Zod v4 in your project and import it directly.
|
|
1620
2085
|
|
|
1621
2086
|
### `@payloadcms/ui/scss` export removed and legacy `--theme-*` tokens retired
|
|
1622
2087
|
|
|
@@ -1650,3 +2115,63 @@ The Admin UI styles were migrated from SCSS to plain CSS. The `@payloadcms/ui/sc
|
|
|
1650
2115
|
The `--theme-elevation-*` scale was removed. Use the semantic `--color-*` tokens (e.g. `--color-bg`, `--color-text`, `--color-border`, `--color-icon`) or the raw `--ramp-*` palette instead. See [Customizing CSS](../admin/customizing-css) for the full list of available tokens.
|
|
1651
2116
|
|
|
1652
2117
|
Any custom component `.scss` files you authored should be renamed to `.css` and updated to plain CSS syntax — Payload no longer ships a SCSS toolchain.
|
|
2118
|
+
|
|
2119
|
+
### Ecommerce Stripe confirmations use an atomic transaction claim
|
|
2120
|
+
|
|
2121
|
+
Stripe confirmation now atomically claims the existing ecommerce transaction before creating an order,
|
|
2122
|
+
marking the cart as purchased, and decrementing inventory. Retries return the canonical order only when
|
|
2123
|
+
the succeeded transaction and order are linked in both directions. Ambiguous state fails closed.
|
|
2124
|
+
|
|
2125
|
+
PostgreSQL users must generate and run a database migration that adds `processing` to the ecommerce
|
|
2126
|
+
transaction status enum. No order field, unique index, or data backfill is required. The public
|
|
2127
|
+
`confirm-order` response continues to include `transactionID`, including on retries. This is a breaking
|
|
2128
|
+
security change for custom payment adapters: after provider validation, they must call the new
|
|
2129
|
+
`finalizeOrder` argument instead of creating orders themselves. The bundled Stripe adapter is updated in
|
|
2130
|
+
the same release. See the [payment confirmation guidance](../ecommerce/payments#confirmation-retries) for
|
|
2131
|
+
transactionless database failure behavior and reconciliation guidance.
|
|
2132
|
+
|
|
2133
|
+
### Stripe REST proxy requires an explicit method allowlist
|
|
2134
|
+
|
|
2135
|
+
`@payloadcms/plugin-stripe` no longer accepts `rest: true`. To enable the REST proxy in v4, use
|
|
2136
|
+
an object with a non-empty `allowedMethods` array of exact Stripe SDK method names, such as
|
|
2137
|
+
`subscriptions.list`:
|
|
2138
|
+
|
|
2139
|
+
```diff
|
|
2140
|
+
stripePlugin({
|
|
2141
|
+
- rest: true,
|
|
2142
|
+
+ rest: {
|
|
2143
|
+
+ allowedMethods: ['subscriptions.list'],
|
|
2144
|
+
+ },
|
|
2145
|
+
})
|
|
2146
|
+
```
|
|
2147
|
+
|
|
2148
|
+
Wildcards are not supported. The optional `rest.access` callback can further restrict the
|
|
2149
|
+
endpoint. Without it, the proxy requires an authenticated user allowed to access the Payload
|
|
2150
|
+
admin panel. See the [Stripe REST proxy documentation](../plugins/stripe#stripe-rest-proxy) for
|
|
2151
|
+
configuration and security guidance.
|
|
2152
|
+
|
|
2153
|
+
If you previously used `rest: false`, remove the property; omitting `rest` disables the proxy.
|
|
2154
|
+
|
|
2155
|
+
### API keys: v4-only changes on top of the shared 3.x/4 security fix
|
|
2156
|
+
|
|
2157
|
+
- `apiKeyLast4` is a new persisted field on every `auth.useAPIKey` collection. Generate and run a schema migration. Legacy rows backfill on the next successful API-key authentication.
|
|
2158
|
+
- `enableAPIKey` is removed. Revoke by setting `apiKey: null`.
|
|
2159
|
+
- `hasAPIKey` (3.x virtual field) is removed. Use `apiKeyLast4` and `docPermissions.fields.apiKey`.
|
|
2160
|
+
- Custom `access.read` on the generated `apiKey` field is inert — reads are hardcoded to deny.
|
|
2161
|
+
|
|
2162
|
+
### Upload `abortOnLimit` now defaults to `true`
|
|
2163
|
+
|
|
2164
|
+
The Payload-wide [`upload.abortOnLimit`](../upload/overview#payload-wide-upload-options) option now defaults to `true`. A file that is bigger than the configured `fileSize` limit now returns an HTTP 413 error by default. Previously, the file was truncated to the limit without any error, and the upload continued.
|
|
2165
|
+
|
|
2166
|
+
If your application depends on the old truncate-on-limit behavior, set `abortOnLimit: false` explicitly:
|
|
2167
|
+
|
|
2168
|
+
```diff
|
|
2169
|
+
export default buildConfig({
|
|
2170
|
+
upload: {
|
|
2171
|
+
+ abortOnLimit: false,
|
|
2172
|
+
limits: {
|
|
2173
|
+
fileSize: 5000000,
|
|
2174
|
+
},
|
|
2175
|
+
},
|
|
2176
|
+
})
|
|
2177
|
+
```
|