diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index de204ffd0b6..3388affeb7e 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -18,7 +18,7 @@ concurrency: env: NODE_VERSION: 18.20.2 - PNPM_VERSION: 9.7.0 + PNPM_VERSION: 9.7.1 DO_NOT_TRACK: 1 # Disable Turbopack telemetry NEXT_TELEMETRY_DISABLED: 1 # Disable Next telemetry @@ -207,6 +207,9 @@ jobs: AWS_REGION: us-east-1 steps: + - uses: actions/checkout@v4 + with: + fetch-depth: 25 # https://github.com/actions/virtual-environments/issues/1187 - name: tune linux network run: sudo ethtool -K eth0 tx off rx off @@ -222,12 +225,7 @@ jobs: version: ${{ env.PNPM_VERSION }} run_install: false - - name: Restore build - uses: actions/cache@v4 - timeout-minutes: 10 - with: - path: ./* - key: ${{ github.sha }}-${{ github.run_number }} + - run: pnpm install - name: Start LocalStack run: pnpm docker:start @@ -371,7 +369,7 @@ jobs: run: pnpm exec playwright install-deps chromium - name: E2E Tests - run: PLAYWRIGHT_JSON_OUTPUT_NAME=results_${{ matrix.suite }}.json pnpm test:e2e ${{ matrix.suite }} + run: PLAYWRIGHT_JSON_OUTPUT_NAME=results_${{ matrix.suite }}.json pnpm test:e2e:prod:ci ${{ matrix.suite }} env: PLAYWRIGHT_JSON_OUTPUT_NAME: results_${{ matrix.suite }}.json NEXT_TELEMETRY_DISABLED: 1 diff --git a/.github/workflows/release-canary.yml b/.github/workflows/release-canary.yml index 83da3460549..1aa7b0e4c06 100644 --- a/.github/workflows/release-canary.yml +++ b/.github/workflows/release-canary.yml @@ -7,7 +7,7 @@ on: env: NODE_VERSION: 18.20.2 - PNPM_VERSION: 9.7.0 + PNPM_VERSION: 9.7.1 DO_NOT_TRACK: 1 # Disable Turbopack telemetry NEXT_TELEMETRY_DISABLED: 1 # Disable Next telemetry diff --git a/.gitignore b/.gitignore index 192cd271019..394fa989477 100644 --- a/.gitignore +++ b/.gitignore @@ -5,7 +5,7 @@ dist !/.idea/runConfigurations !/.idea/payload.iml - +test/packed test-results .devcontainer .localstack @@ -306,3 +306,6 @@ test/live-preview/app/(payload)/admin/importMap.js /test/live-preview/app/(payload)/admin/importMap.js test/admin-root/app/(payload)/admin/importMap.js /test/admin-root/app/(payload)/admin/importMap.js +test/app/(payload)/admin/importMap.js +/test/app/(payload)/admin/importMap.js +test/pnpm-lock.yaml diff --git a/package.json b/package.json index e217c60f48d..e63e9f51497 100644 --- a/package.json +++ b/package.json @@ -53,7 +53,7 @@ "clean:all": "node ./scripts/delete-recursively.js '@node_modules' 'media/*' '**/dist/' '**/.cache/*' '**/.next/*' '**/.turbo/*' '**/tsconfig.tsbuildinfo' '**/payload*.tgz' '**/meta_*.json'", "clean:build": "node ./scripts/delete-recursively.js 'media/' '**/dist/' '**/.cache/' '**/.next/' '**/.turbo/' '**/tsconfig.tsbuildinfo' '**/payload*.tgz' '**/meta_*.json'", "clean:cache": "node ./scripts/delete-recursively.js node_modules/.cache! packages/payload/node_modules/.cache! .next/*", - "dev": "pnpm runts ./test/dev.ts", + "dev": "tsx ./test/dev.ts", "dev:generate-graphql-schema": "pnpm runts ./test/generateGraphQLSchema.ts", "dev:generate-importmap": "pnpm runts ./test/generateImportMap.ts", "dev:generate-types": "pnpm runts ./test/generateTypes.ts", @@ -81,6 +81,8 @@ "test:e2e": "pnpm runts ./test/runE2E.ts", "test:e2e:debug": "cross-env NODE_OPTIONS=--no-deprecation NODE_NO_WARNINGS=1 PWDEBUG=1 DISABLE_LOGGING=true playwright test", "test:e2e:headed": "cross-env NODE_OPTIONS=--no-deprecation NODE_NO_WARNINGS=1 DISABLE_LOGGING=true playwright test --headed", + "test:e2e:prod": "pnpm bf && rm -rf test/packed && rm -rf test/node_modules && rm -f test/pnpm-lock.yaml && pnpm run script:pack --all --no-build --dest test/packed && pnpm runts test/setupProd.ts && cd test && pnpm i --ignore-workspace && cd .. && pnpm runts ./test/runE2E.ts --prod", + "test:e2e:prod:ci": "rm -rf test/node_modules && rm -f test/pnpm-lock.yaml && pnpm run script:pack --all --no-build --dest test/packed && pnpm runts test/setupProd.ts && cd test && pnpm i --ignore-workspace && cd .. && pnpm runts ./test/runE2E.ts --prod", "test:int": "cross-env NODE_OPTIONS=\"--no-deprecation\" NODE_NO_WARNINGS=1 DISABLE_LOGGING=true jest --forceExit --detectOpenHandles --config=test/jest.config.js --runInBand", "test:int:postgres": "cross-env NODE_OPTIONS=\"--no-deprecation\" NODE_NO_WARNINGS=1 PAYLOAD_DATABASE=postgres DISABLE_LOGGING=true jest --forceExit --detectOpenHandles --config=test/jest.config.js --runInBand", "test:unit": "cross-env NODE_OPTIONS=\"--no-deprecation\" NODE_NO_WARNINGS=1 DISABLE_LOGGING=true jest --forceExit --detectOpenHandles --config=jest.config.js --runInBand", @@ -162,7 +164,6 @@ "react": "^19.0.0 || ^19.0.0-rc-06d0b89e-20240801", "react-dom": "^19.0.0 || ^19.0.0-rc-06d0b89e-20240801" }, - "packageManager": "pnpm@9.7.0", "engines": { "node": "^18.20.2 || >=20.9.0", "pnpm": "^9.7.0" diff --git a/packages/graphql/package.json b/packages/graphql/package.json index 12ab35cb862..d9f24aca266 100644 --- a/packages/graphql/package.json +++ b/packages/graphql/package.json @@ -43,8 +43,8 @@ "dependencies": { "graphql-scalars": "1.22.2", "pluralize": "8.0.0", - "tsx": "4.17.0", - "ts-essentials": "7.0.3" + "ts-essentials": "7.0.3", + "tsx": "4.17.0" }, "devDependencies": { "@payloadcms/eslint-config": "workspace:*", diff --git a/packages/next/src/utilities/getPayloadHMR.ts b/packages/next/src/utilities/getPayloadHMR.ts index c1a34a80e87..1c6a72139f4 100644 --- a/packages/next/src/utilities/getPayloadHMR.ts +++ b/packages/next/src/utilities/getPayloadHMR.ts @@ -14,7 +14,11 @@ if (!cached) { cached = global._payload = { payload: null, promise: null, reload: false, ws: null } } -export const reload = async (config: SanitizedConfig, payload: Payload): Promise => { +export const reload = async ( + config: SanitizedConfig, + payload: Payload, + skipImportMapGeneration?: boolean, +): Promise => { if (typeof payload.db.destroy === 'function') { await payload.db.destroy() } @@ -46,7 +50,7 @@ export const reload = async (config: SanitizedConfig, payload: Payload): Promise } // Generate component map - if (config.admin?.importMap?.autoGenerate !== false) { + if (skipImportMapGeneration !== true && config.admin?.importMap?.autoGenerate !== false) { await generateImportMap(config, { log: true, }) @@ -87,6 +91,7 @@ export const getPayloadHMR = async (options: InitOptions): Promise => { return cached.payload } + // eslint-disable-next-line @typescript-eslint/no-misused-promises if (!cached.promise) { // no need to await options.config here, as it's already awaited in the BasePayload.init cached.promise = new BasePayload().init(options) diff --git a/packages/payload/package.json b/packages/payload/package.json index 0f804355dad..906c04938b5 100644 --- a/packages/payload/package.json +++ b/packages/payload/package.json @@ -86,7 +86,6 @@ "dependencies": { "@next/env": "^15.0.0-canary.104", "@payloadcms/translations": "workspace:*", - "tsx": "4.17.0", "ajv": "8.14.0", "bson-objectid": "2.0.4", "ci-info": "^4.0.0", @@ -108,6 +107,7 @@ "sanitize-filename": "1.6.3", "scmp": "2.1.0", "ts-essentials": "7.0.3", + "tsx": "4.17.0", "uuid": "10.0.0" }, "devDependencies": { diff --git a/packages/payload/src/exports/shared.ts b/packages/payload/src/exports/shared.ts index 1f53ce1f17d..bd66604b6d9 100644 --- a/packages/payload/src/exports/shared.ts +++ b/packages/payload/src/exports/shared.ts @@ -42,7 +42,6 @@ export { export { fieldSchemaToJSON } from '../utilities/fieldSchemaToJSON.js' export { getDataByPath } from '../utilities/getDataByPath.js' - export { getSiblingData } from '../utilities/getSiblingData.js' export { getUniqueListBy } from '../utilities/getUniqueListBy.js' diff --git a/packages/richtext-lexical/babel.config.cjs b/packages/richtext-lexical/babel.config.cjs new file mode 100644 index 00000000000..2a16d755486 --- /dev/null +++ b/packages/richtext-lexical/babel.config.cjs @@ -0,0 +1,36 @@ +const fs = require('fs') + +// Plugin options can be found here: https://github.com/facebook/react/blob/main/compiler/packages/babel-plugin-react-compiler/src/Entrypoint/Options.ts#L38 +const ReactCompilerConfig = { + sources: (filename) => { + const isInNodeModules = filename.includes('node_modules') + if (isInNodeModules || ( !filename.endsWith('.tsx') && !filename.endsWith('.jsx') && !filename.endsWith('.js'))) { + return false + } + + // Only compile files with 'use client' directives. We do not want to + // accidentally compile React Server Components + const file = fs.readFileSync(filename, 'utf8') + if (file.includes("'use client'")) { + return true + } + console.log('React compiler - skipping file: ' + filename) + return false + }, +} + +module.exports = function (api) { + api.cache(false) + + return { + plugins: [ + ['babel-plugin-react-compiler', ReactCompilerConfig], // must run first! + /* [ + 'babel-plugin-transform-remove-imports', + { + test: '\\.(scss|css)$', + }, + ],*/ + ], + } +} diff --git a/packages/richtext-lexical/bundle.js b/packages/richtext-lexical/bundle.js index 49263f5cc8d..201adcb460a 100644 --- a/packages/richtext-lexical/bundle.js +++ b/packages/richtext-lexical/bundle.js @@ -24,15 +24,20 @@ async function build() { entryPoints: ['src/exports/client/index.ts'], bundle: true, minify: true, - outdir: 'dist/field', + outdir: 'dist/bundled_scss', loader: { '.svg': 'dataurl' }, packages: 'external', //external: ['*.svg'], plugins: [sassPlugin({ css: 'external' })], }) + //create empty dist/exports/client_optimized dir + fs.mkdirSync('dist/exports/client_optimized') + try { - fs.renameSync('dist/field/index.css', 'dist/exports/client/bundled.css') + fs.renameSync('dist/bundled_scss/index.css', 'dist/field/bundled.css') + fs.copyFileSync('dist/field/bundled.css', 'dist/exports/client_optimized/bundled.css') + fs.rmSync('dist/bundled_scss', { recursive: true }) } catch (err) { console.error(`Error while renaming index.css: ${err}`) throw err @@ -42,11 +47,11 @@ async function build() { // Bundle `client.ts` const resultClient = await esbuild.build({ - entryPoints: ['src/exports/client/index.ts'], + entryPoints: ['dist/exports/client/index.js'], bundle: true, platform: 'browser', format: 'esm', - outdir: 'dist/exports/client', + outdir: 'dist/exports/client_optimized', //outfile: 'index.js', // IMPORTANT: splitting the client bundle means that the `use client` directive will be lost for every chunk splitting: true, diff --git a/packages/richtext-lexical/eslint.config.js b/packages/richtext-lexical/eslint.config.js index 61c3429846b..e865522c17f 100644 --- a/packages/richtext-lexical/eslint.config.js +++ b/packages/richtext-lexical/eslint.config.js @@ -1,5 +1,7 @@ import lexical from '@lexical/eslint-plugin' import { rootEslintConfig, rootParserOptions } from '../../eslint.config.js' +import reactCompiler from 'eslint-plugin-react-compiler' +const { rules } = reactCompiler /** @typedef {import('eslint').Linter.FlatConfig} */ let FlatConfig @@ -20,6 +22,16 @@ export const index = [ }, rules: lexical.configs.recommended.rules, }, + { + plugins: { + 'react-compiler': { + rules, + }, + }, + rules: { + 'react-compiler/react-compiler': 'error', + }, + }, ] export default index diff --git a/packages/richtext-lexical/package.json b/packages/richtext-lexical/package.json index ab274285444..4f791c4d223 100644 --- a/packages/richtext-lexical/package.json +++ b/packages/richtext-lexical/package.json @@ -36,11 +36,14 @@ "dist" ], "scripts": { - "build": "rm -rf dist && rm -rf tsconfig.tsbuildinfo && pnpm copyfiles && pnpm build:types && pnpm build:swc && pnpm build:esbuild", + "build": "pnpm build:reactcompiler", + "build:babel": "rm -rf dist_optimized && babel dist --out-dir dist_optimized --source-maps --extensions .ts,.js,.tsx,.jsx,.cjs,.mjs && rm -rf dist && mv dist_optimized dist", "build:clean": "find . \\( -type d \\( -name build -o -name dist -o -name .cache \\) -o -type f -name tsconfig.tsbuildinfo \\) -exec rm -rf {} + && pnpm build", - "build:esbuild": "node bundle.js", + "build:esbuild": "node bundle.js && rm -rf dist/exports/client && mv dist/exports/client_optimized dist/exports/client", + "build:reactcompiler": "rm -rf dist && rm -rf tsconfig.tsbuildinfo && pnpm build:swc && pnpm build:babel && pnpm copyfiles && pnpm build:esbuild && pnpm build:types", "build:swc": "swc ./src -d ./dist --config-file .swcrc --strip-leading-paths", "build:types": "tsc --emitDeclarationOnly --outDir dist", + "build_without_reactcompiler": "rm -rf dist && rm -rf tsconfig.tsbuildinfo && pnpm copyfiles && pnpm build:types && pnpm build:swc && pnpm build:esbuild && rm -rf dist/exports/client && mv dist/exports/client_unoptimized dist/exports/client", "clean": "rimraf {dist,*.tsbuildinfo}", "copyfiles": "copyfiles -u 1 \"src/**/*.{html,css,ttf,woff,woff2,eot,svg,jpg,png,json}\" dist/", "prepublishOnly": "pnpm clean && pnpm turbo build", @@ -64,6 +67,11 @@ "uuid": "10.0.0" }, "devDependencies": { + "@babel/cli": "^7.24.5", + "@babel/core": "^7.24.5", + "@babel/preset-env": "^7.24.5", + "@babel/preset-react": "^7.24.1", + "@babel/preset-typescript": "^7.24.1", "@lexical/eslint-plugin": "0.17.0", "@payloadcms/eslint-config": "workspace:*", "@payloadcms/next": "workspace:*", @@ -73,8 +81,11 @@ "@types/node": "20.12.5", "@types/react": "npm:types-react@19.0.0-rc.0", "@types/react-dom": "npm:types-react-dom@19.0.0-rc.0", + "babel-plugin-react-compiler": "0.0.0-experimental-1cd8995-20240814", + "babel-plugin-transform-remove-imports": "^1.8.0", "esbuild": "0.23.0", "esbuild-sass-plugin": "3.3.1", + "eslint-plugin-react-compiler": "0.0.0-experimental-d0e920e-20240815", "payload": "workspace:*", "swc-plugin-transform-remove-imports": "1.15.0" }, diff --git a/packages/richtext-lexical/src/features/align/client/toolbarAlignGroup.ts b/packages/richtext-lexical/src/features/align/client/toolbarAlignGroup.ts index 4f49c2ee2c1..7439f70b3f1 100644 --- a/packages/richtext-lexical/src/features/align/client/toolbarAlignGroup.ts +++ b/packages/richtext-lexical/src/features/align/client/toolbarAlignGroup.ts @@ -1,3 +1,4 @@ +'use client' import type { ToolbarGroup, ToolbarGroupItem } from '../../toolbars/types.js' import { AlignLeftIcon } from '../../../lexical/ui/icons/AlignLeft/index.js' diff --git a/packages/richtext-lexical/src/features/blocks/client/component/BlockContent.tsx b/packages/richtext-lexical/src/features/blocks/client/component/BlockContent.tsx index 54dcd104bf5..0c849823024 100644 --- a/packages/richtext-lexical/src/features/blocks/client/component/BlockContent.tsx +++ b/packages/richtext-lexical/src/features/blocks/client/component/BlockContent.tsx @@ -1,3 +1,4 @@ +'use client' import type { ClientBlock, ClientField, CollapsedPreferences, FormState } from 'payload' import { useLexicalComposerContext } from '@lexical/react/LexicalComposerContext.js' diff --git a/packages/richtext-lexical/src/features/blocks/client/component/FormSavePlugin.tsx b/packages/richtext-lexical/src/features/blocks/client/component/FormSavePlugin.tsx index 28bd107a282..2894333c33e 100644 --- a/packages/richtext-lexical/src/features/blocks/client/component/FormSavePlugin.tsx +++ b/packages/richtext-lexical/src/features/blocks/client/component/FormSavePlugin.tsx @@ -1,3 +1,4 @@ +'use client' import type { Data, FormState } from 'payload' import type React from 'react' diff --git a/packages/richtext-lexical/src/features/blocks/client/component/removeEmptyArrayValues.ts b/packages/richtext-lexical/src/features/blocks/client/component/removeEmptyArrayValues.ts index 7d2216a7ed6..b54849aab4c 100644 --- a/packages/richtext-lexical/src/features/blocks/client/component/removeEmptyArrayValues.ts +++ b/packages/richtext-lexical/src/features/blocks/client/component/removeEmptyArrayValues.ts @@ -1,3 +1,4 @@ +'use client' import type { FormState } from 'payload' /** diff --git a/packages/richtext-lexical/src/features/blocks/client/nodes/BlocksNode.tsx b/packages/richtext-lexical/src/features/blocks/client/nodes/BlocksNode.tsx index 2e641b5c114..901947b7a3f 100644 --- a/packages/richtext-lexical/src/features/blocks/client/nodes/BlocksNode.tsx +++ b/packages/richtext-lexical/src/features/blocks/client/nodes/BlocksNode.tsx @@ -1,3 +1,4 @@ +'use client' import type { EditorConfig, LexicalEditor, LexicalNode } from 'lexical' import ObjectID from 'bson-objectid' diff --git a/packages/richtext-lexical/src/features/blocks/client/nodes/InlineBlocksNode.tsx b/packages/richtext-lexical/src/features/blocks/client/nodes/InlineBlocksNode.tsx index a14ba8f04df..85ab045fd4d 100644 --- a/packages/richtext-lexical/src/features/blocks/client/nodes/InlineBlocksNode.tsx +++ b/packages/richtext-lexical/src/features/blocks/client/nodes/InlineBlocksNode.tsx @@ -1,3 +1,4 @@ +'use client' import type { EditorConfig, LexicalEditor, diff --git a/packages/richtext-lexical/src/features/blocks/client/plugin/commands.ts b/packages/richtext-lexical/src/features/blocks/client/plugin/commands.ts index 5b7ed183569..ffbc8fe5afc 100644 --- a/packages/richtext-lexical/src/features/blocks/client/plugin/commands.ts +++ b/packages/richtext-lexical/src/features/blocks/client/plugin/commands.ts @@ -1,3 +1,4 @@ +'use client' import type { LexicalCommand } from 'lexical' import { createCommand } from 'lexical' diff --git a/packages/richtext-lexical/src/features/experimental_table/client/plugins/TableHoverActionsPlugin/index.tsx b/packages/richtext-lexical/src/features/experimental_table/client/plugins/TableHoverActionsPlugin/index.tsx index c59a66976e0..2c565092ab2 100644 --- a/packages/richtext-lexical/src/features/experimental_table/client/plugins/TableHoverActionsPlugin/index.tsx +++ b/packages/richtext-lexical/src/features/experimental_table/client/plugins/TableHoverActionsPlugin/index.tsx @@ -1,10 +1,4 @@ -/** - * Copyright (c) Meta Platforms, Inc. and affiliates. - * - * This source code is licensed under the MIT license found in the - * LICENSE file in the root directory of this source tree. - * - */ +'use client' import type { TableCellNode, TableRowNode } from '@lexical/table' import type { EditorConfig, NodeKey } from 'lexical' diff --git a/packages/richtext-lexical/src/features/experimental_table/client/utils/debounce.ts b/packages/richtext-lexical/src/features/experimental_table/client/utils/debounce.ts index e8001352211..31df557e604 100644 --- a/packages/richtext-lexical/src/features/experimental_table/client/utils/debounce.ts +++ b/packages/richtext-lexical/src/features/experimental_table/client/utils/debounce.ts @@ -1,3 +1,4 @@ +'use client' // Copied & modified from https://github.com/lodash/lodash/blob/main/src/debounce.ts /* The MIT License diff --git a/packages/richtext-lexical/src/features/experimental_table/client/utils/useDebounce.ts b/packages/richtext-lexical/src/features/experimental_table/client/utils/useDebounce.ts index b30588a1029..169bbfec6e9 100644 --- a/packages/richtext-lexical/src/features/experimental_table/client/utils/useDebounce.ts +++ b/packages/richtext-lexical/src/features/experimental_table/client/utils/useDebounce.ts @@ -1,3 +1,4 @@ +'use client' import { useMemo, useRef } from 'react' import debounce from './debounce.js' diff --git a/packages/richtext-lexical/src/features/experimental_table/plugins/TableHoverActionsPlugin/index.tsx b/packages/richtext-lexical/src/features/experimental_table/plugins/TableHoverActionsPlugin/index.tsx deleted file mode 100644 index ae5b8f998a9..00000000000 --- a/packages/richtext-lexical/src/features/experimental_table/plugins/TableHoverActionsPlugin/index.tsx +++ /dev/null @@ -1,243 +0,0 @@ -/** - * Copyright (c) Meta Platforms, Inc. and affiliates. - * - * This source code is licensed under the MIT license found in the - * LICENSE file in the root directory of this source tree. - * - */ - -import type { TableCellNode, TableRowNode } from '@lexical/table' -import type { EditorConfig, NodeKey } from 'lexical' -import type { JSX } from 'react' - -import { useLexicalComposerContext } from '@lexical/react/LexicalComposerContext' -import { - $getTableColumnIndexFromTableCellNode, - $getTableRowIndexFromTableCellNode, - $insertTableColumn__EXPERIMENTAL, - $insertTableRow__EXPERIMENTAL, - $isTableCellNode, - $isTableNode, - TableNode, -} from '@lexical/table' -import { $findMatchingParent, mergeRegister } from '@lexical/utils' -import { $getNearestNodeFromDOMNode } from 'lexical' -import { useEffect, useRef, useState } from 'react' -import * as React from 'react' -import { createPortal } from 'react-dom' - -import { useEditorConfigContext } from '../../../../lexical/config/client/EditorConfigProvider.js' -import { useDebounce } from '../../client/utils/useDebounce.js' - -const BUTTON_WIDTH_PX = 20 - -function TableHoverActionsContainer({ anchorElem }: { anchorElem: HTMLElement }): JSX.Element { - const [editor] = useLexicalComposerContext() - const editorConfig = useEditorConfigContext() - const [isShownRow, setShownRow] = useState(false) - const [isShownColumn, setShownColumn] = useState(false) - const [shouldListenMouseMove, setShouldListenMouseMove] = useState(false) - const [position, setPosition] = useState({}) - const codeSetRef = useRef>(new Set()) - const tableDOMNodeRef = useRef(null) - - const debouncedOnMouseMove = useDebounce( - (event: MouseEvent) => { - const { isOutside, tableDOMNode } = getMouseInfo(event, editorConfig.editorConfig?.lexical) - - if (isOutside) { - setShownRow(false) - setShownColumn(false) - return - } - - if (!tableDOMNode) { - return - } - - tableDOMNodeRef.current = tableDOMNode - - let hoveredRowNode: TableCellNode | null = null - let hoveredColumnNode: TableCellNode | null = null - let tableDOMElement: HTMLElement | null = null - - editor.update(() => { - const maybeTableCell = $getNearestNodeFromDOMNode(tableDOMNode) - - if ($isTableCellNode(maybeTableCell)) { - const table = $findMatchingParent(maybeTableCell, (node) => $isTableNode(node)) - if (!$isTableNode(table)) { - return - } - - tableDOMElement = editor.getElementByKey(table?.getKey()) - - if (tableDOMElement) { - const rowCount = table.getChildrenSize() - const colCount = - // eslint-disable-next-line @typescript-eslint/no-unnecessary-type-assertion - ((table as TableNode).getChildAtIndex(0) as TableRowNode)?.getChildrenSize() - - const rowIndex = $getTableRowIndexFromTableCellNode(maybeTableCell) - const colIndex = $getTableColumnIndexFromTableCellNode(maybeTableCell) - - if (rowIndex === rowCount - 1) { - hoveredRowNode = maybeTableCell - } else if (colIndex === colCount - 1) { - hoveredColumnNode = maybeTableCell - } - } - } - }) - - if (tableDOMElement) { - const { - bottom: tableElemBottom, - height: tableElemHeight, - right: tableElemRight, - width: tableElemWidth, - x: tableElemX, - y: tableElemY, - } = (tableDOMElement as HTMLTableElement).getBoundingClientRect() - - const { left: editorElemLeft, y: editorElemY } = anchorElem.getBoundingClientRect() - - if (hoveredRowNode) { - setShownColumn(false) - setShownRow(true) - setPosition({ - height: BUTTON_WIDTH_PX, - left: tableElemX - editorElemLeft, - top: tableElemBottom - editorElemY + 5, - width: tableElemWidth, - }) - } else if (hoveredColumnNode) { - setShownColumn(true) - setShownRow(false) - setPosition({ - height: tableElemHeight, - left: tableElemRight - editorElemLeft + 5, - top: tableElemY - editorElemY, - width: BUTTON_WIDTH_PX, - }) - } - } - }, - 50, - 250, - ) - - useEffect(() => { - if (!shouldListenMouseMove) { - return - } - - document.addEventListener('mousemove', debouncedOnMouseMove) - - return () => { - setShownRow(false) - setShownColumn(false) - - document.removeEventListener('mousemove', debouncedOnMouseMove) - } - }, [shouldListenMouseMove, debouncedOnMouseMove]) - - useEffect(() => { - return mergeRegister( - editor.registerMutationListener( - TableNode, - (mutations) => { - editor.getEditorState().read(() => { - for (const [key, type] of mutations) { - switch (type) { - case 'created': - codeSetRef.current.add(key) - setShouldListenMouseMove(codeSetRef.current.size > 0) - break - - case 'destroyed': - codeSetRef.current.delete(key) - setShouldListenMouseMove(codeSetRef.current.size > 0) - break - - default: - break - } - } - }) - }, - { skipInitialization: false }, - ), - ) - }, [editor]) - - const insertAction = (insertRow: boolean) => { - editor.update(() => { - if (tableDOMNodeRef.current) { - const maybeTableNode = $getNearestNodeFromDOMNode(tableDOMNodeRef.current) - maybeTableNode?.selectEnd() - if (insertRow) { - $insertTableRow__EXPERIMENTAL() - setShownRow(false) - } else { - $insertTableColumn__EXPERIMENTAL() - setShownColumn(false) - } - } - }) - } - - return ( - <> - {isShownRow && ( - - diff --git a/packages/ui/src/elements/Gutter/index.tsx b/packages/ui/src/elements/Gutter/index.tsx index 6c2331b833a..3e926705309 100644 --- a/packages/ui/src/elements/Gutter/index.tsx +++ b/packages/ui/src/elements/Gutter/index.tsx @@ -1,3 +1,4 @@ +'use client' import React, { forwardRef } from 'react' import './index.scss' diff --git a/packages/ui/src/elements/ListControls/getTextFieldsToBeSearched.ts b/packages/ui/src/elements/ListControls/getTextFieldsToBeSearched.ts index 4008606f16c..e76f555ece0 100644 --- a/packages/ui/src/elements/ListControls/getTextFieldsToBeSearched.ts +++ b/packages/ui/src/elements/ListControls/getTextFieldsToBeSearched.ts @@ -1,3 +1,4 @@ +'use client' import type { ClientField } from 'payload' import { fieldAffectsData } from 'payload/shared' diff --git a/packages/ui/src/elements/LoadingOverlay/reducer.ts b/packages/ui/src/elements/LoadingOverlay/reducer.ts index 78f8b48fa58..23e26f36597 100644 --- a/packages/ui/src/elements/LoadingOverlay/reducer.ts +++ b/packages/ui/src/elements/LoadingOverlay/reducer.ts @@ -1,3 +1,4 @@ +'use client' import type { Action, State } from './types.js' export const defaultLoadingOverlayState = { diff --git a/packages/ui/src/elements/Modal/index.tsx b/packages/ui/src/elements/Modal/index.tsx index f6118b3f81f..dc739db69aa 100644 --- a/packages/ui/src/elements/Modal/index.tsx +++ b/packages/ui/src/elements/Modal/index.tsx @@ -1,2 +1,3 @@ +'use client' import { Modal, useModal } from '@faceless-ui/modal' export { Modal, useModal } diff --git a/packages/ui/src/elements/StepNav/context.tsx b/packages/ui/src/elements/StepNav/context.tsx index 85b3d627cdd..5708e3475a7 100644 --- a/packages/ui/src/elements/StepNav/context.tsx +++ b/packages/ui/src/elements/StepNav/context.tsx @@ -1,3 +1,4 @@ +'use client' import React, { createContext, useContext, useState } from 'react' import type { ContextType } from './types.js' diff --git a/packages/ui/src/elements/TableColumns/buildColumnState.tsx b/packages/ui/src/elements/TableColumns/buildColumnState.tsx index 02f809bcdb9..e7d96753f46 100644 --- a/packages/ui/src/elements/TableColumns/buildColumnState.tsx +++ b/packages/ui/src/elements/TableColumns/buildColumnState.tsx @@ -11,12 +11,12 @@ import React from 'react' import type { ColumnPreferences } from '../../providers/ListInfo/index.js' import type { Column } from '../Table/index.js' -import { DefaultCell } from '../../elements/Table/DefaultCell/index.js' import { FieldLabel } from '../../fields/FieldLabel/index.js' import { flattenFieldMap } from '../../utilities/flattenFieldMap.js' import { SelectAll } from '../SelectAll/index.js' import { SelectRow } from '../SelectRow/index.js' import { SortColumn } from '../SortColumn/index.js' +import { DefaultCell } from '../Table/DefaultCell/index.js' type Args = { cellProps: Partial[] diff --git a/packages/ui/src/elements/TableColumns/getInitialColumns.ts b/packages/ui/src/elements/TableColumns/getInitialColumns.ts index b1bbf15d61a..834b45c8338 100644 --- a/packages/ui/src/elements/TableColumns/getInitialColumns.ts +++ b/packages/ui/src/elements/TableColumns/getInitialColumns.ts @@ -1,3 +1,4 @@ +'use client' import type { ClientField } from 'payload' import { fieldAffectsData } from 'payload/shared' diff --git a/packages/ui/src/elements/Translation/index.tsx b/packages/ui/src/elements/Translation/index.tsx index 4ffe680b09c..5f5ce14935a 100644 --- a/packages/ui/src/elements/Translation/index.tsx +++ b/packages/ui/src/elements/Translation/index.tsx @@ -1,3 +1,4 @@ +'use client' import type { ClientTranslationKeys, TFunction } from '@payloadcms/translations' import * as React from 'react' diff --git a/packages/ui/src/elements/WhereBuilder/Condition/Relationship/optionsReducer.ts b/packages/ui/src/elements/WhereBuilder/Condition/Relationship/optionsReducer.ts index 6931aa90644..56c34fa8523 100644 --- a/packages/ui/src/elements/WhereBuilder/Condition/Relationship/optionsReducer.ts +++ b/packages/ui/src/elements/WhereBuilder/Condition/Relationship/optionsReducer.ts @@ -1,3 +1,4 @@ +'use client' import { getTranslation } from '@payloadcms/translations' import type { Action, Option } from './types.js' diff --git a/packages/ui/src/elements/WhereBuilder/field-types.tsx b/packages/ui/src/elements/WhereBuilder/field-types.tsx index 55598af8626..4067189f124 100644 --- a/packages/ui/src/elements/WhereBuilder/field-types.tsx +++ b/packages/ui/src/elements/WhereBuilder/field-types.tsx @@ -1,3 +1,4 @@ +'use client' const boolean = [ { label: 'equals', diff --git a/packages/ui/src/elements/WhereBuilder/index.tsx b/packages/ui/src/elements/WhereBuilder/index.tsx index c1c3f781a5e..275d9858fa4 100644 --- a/packages/ui/src/elements/WhereBuilder/index.tsx +++ b/packages/ui/src/elements/WhereBuilder/index.tsx @@ -7,7 +7,6 @@ import React, { useEffect, useState } from 'react' import type { WhereBuilderProps } from './types.js' import { useListQuery } from '../../providers/ListQuery/index.js' -import { useLocale } from '../../providers/Locale/index.js' import { useSearchParams } from '../../providers/SearchParams/index.js' import { useTranslation } from '../../providers/Translation/index.js' import { Button } from '../Button/index.js' @@ -28,7 +27,6 @@ export { WhereBuilderProps } export const WhereBuilder: React.FC = (props) => { const { collectionPluralLabel, fields } = props const { i18n, t } = useTranslation() - const { code: currentLocale } = useLocale() const [reducedFields, setReducedColumns] = useState(() => reduceClientFields({ fields, i18n })) @@ -116,8 +114,9 @@ export const WhereBuilder: React.FC = (props) => { } if (JSON.stringify(existingRowCondition) !== JSON.stringify(newRowCondition)) { - conditions[orIndex].and[andIndex] = newRowCondition - setConditions(conditions) + const newConditions = [...conditions] + newConditions[orIndex].and[andIndex] = newRowCondition + setConditions(newConditions) if (![null, undefined].includes(value)) { // only update query when field/operator/value are filled out setShouldUpdateQuery(true) diff --git a/packages/ui/src/elements/WhereBuilder/transformWhereQuery.ts b/packages/ui/src/elements/WhereBuilder/transformWhereQuery.ts index 48546de0940..f61ca5f27ca 100644 --- a/packages/ui/src/elements/WhereBuilder/transformWhereQuery.ts +++ b/packages/ui/src/elements/WhereBuilder/transformWhereQuery.ts @@ -1,3 +1,4 @@ +'use client' import type { Where } from 'payload' /** diff --git a/packages/ui/src/elements/WhereBuilder/validateWhereQuery.ts b/packages/ui/src/elements/WhereBuilder/validateWhereQuery.ts index 90a8d8c11ee..796e570bcf3 100644 --- a/packages/ui/src/elements/WhereBuilder/validateWhereQuery.ts +++ b/packages/ui/src/elements/WhereBuilder/validateWhereQuery.ts @@ -1,3 +1,4 @@ +'use client' import type { Operator, Where } from 'payload' import { validOperators } from 'payload/shared' diff --git a/packages/ui/src/elements/WindowInfo/index.tsx b/packages/ui/src/elements/WindowInfo/index.tsx index 629f66d6d29..91c3aa9036e 100644 --- a/packages/ui/src/elements/WindowInfo/index.tsx +++ b/packages/ui/src/elements/WindowInfo/index.tsx @@ -1,2 +1,3 @@ +'use client' import { WindowInfoProvider, useWindowInfo } from '@faceless-ui/window-info' export { WindowInfoProvider, useWindowInfo } diff --git a/packages/ui/src/fields/Number/Input.tsx b/packages/ui/src/fields/Number/Input.tsx deleted file mode 100644 index e69de29bb2d..00000000000 diff --git a/packages/ui/src/fields/Relationship/AddNew/useRelatedCollections.ts b/packages/ui/src/fields/Relationship/AddNew/useRelatedCollections.ts index 02b85068842..82997a8ca38 100644 --- a/packages/ui/src/fields/Relationship/AddNew/useRelatedCollections.ts +++ b/packages/ui/src/fields/Relationship/AddNew/useRelatedCollections.ts @@ -1,3 +1,4 @@ +'use client' import type { ClientCollectionConfig } from 'payload' import { useState } from 'react' diff --git a/packages/ui/src/fields/Relationship/createRelationMap.ts b/packages/ui/src/fields/Relationship/createRelationMap.ts index 59fa5452385..479b39740cf 100644 --- a/packages/ui/src/fields/Relationship/createRelationMap.ts +++ b/packages/ui/src/fields/Relationship/createRelationMap.ts @@ -1,3 +1,4 @@ +'use client' import type { Value } from './types.js' type RelationMap = { diff --git a/packages/ui/src/fields/Relationship/findOptionsByValue.ts b/packages/ui/src/fields/Relationship/findOptionsByValue.ts index 9b6b8a86fd4..6f23a195508 100644 --- a/packages/ui/src/fields/Relationship/findOptionsByValue.ts +++ b/packages/ui/src/fields/Relationship/findOptionsByValue.ts @@ -1,3 +1,4 @@ +'use client' import type { Option } from '../../elements/ReactSelect/types.js' import type { OptionGroup, Value } from './types.js' diff --git a/packages/ui/src/fields/Relationship/optionsReducer.ts b/packages/ui/src/fields/Relationship/optionsReducer.ts index b350ac3c50e..ef7911a0b8e 100644 --- a/packages/ui/src/fields/Relationship/optionsReducer.ts +++ b/packages/ui/src/fields/Relationship/optionsReducer.ts @@ -1,3 +1,4 @@ +'use client' import { getTranslation } from '@payloadcms/translations' import type { Action, Option, OptionGroup } from './types.js' diff --git a/packages/ui/src/fields/RichText/index.tsx b/packages/ui/src/fields/RichText/index.tsx index d70123ea8d7..8f878d327e7 100644 --- a/packages/ui/src/fields/RichText/index.tsx +++ b/packages/ui/src/fields/RichText/index.tsx @@ -1,3 +1,4 @@ +'use client' import type { RichTextFieldProps } from 'payload' import type React from 'react' diff --git a/packages/ui/src/fields/UI/index.tsx b/packages/ui/src/fields/UI/index.tsx index 8e7dc81f115..e8f2a2fd97e 100644 --- a/packages/ui/src/fields/UI/index.tsx +++ b/packages/ui/src/fields/UI/index.tsx @@ -1,3 +1,4 @@ +'use client' import type React from 'react' export const UIField: React.FC = () => { diff --git a/packages/ui/src/fields/index.tsx b/packages/ui/src/fields/index.tsx index e8518ca75a9..990cb009425 100644 --- a/packages/ui/src/fields/index.tsx +++ b/packages/ui/src/fields/index.tsx @@ -1,3 +1,4 @@ +'use client' import type { FieldTypes } from 'payload' import type React from 'react' diff --git a/packages/ui/src/fields/shared/index.tsx b/packages/ui/src/fields/shared/index.tsx index 72636104426..ac988a8e022 100644 --- a/packages/ui/src/fields/shared/index.tsx +++ b/packages/ui/src/fields/shared/index.tsx @@ -1,3 +1,4 @@ +'use client' import type { Locale, SanitizedLocalizationConfig } from 'payload' export const fieldBaseClass = 'field-type' diff --git a/packages/ui/src/forms/Form/createNestedClientFieldPath.ts b/packages/ui/src/forms/Form/createNestedClientFieldPath.ts index 86908b3d3de..4eda1ae2a19 100644 --- a/packages/ui/src/forms/Form/createNestedClientFieldPath.ts +++ b/packages/ui/src/forms/Form/createNestedClientFieldPath.ts @@ -1,3 +1,4 @@ +'use client' import type { ClientField } from 'payload' import { fieldAffectsData } from 'payload/shared' diff --git a/packages/ui/src/forms/Form/errorMessages.ts b/packages/ui/src/forms/Form/errorMessages.ts index ee90a6e3e0b..2df0db5ca63 100644 --- a/packages/ui/src/forms/Form/errorMessages.ts +++ b/packages/ui/src/forms/Form/errorMessages.ts @@ -1,3 +1,4 @@ +'use client' export const errorMessages = { 413: 'Your request was too large to submit successfully.', } diff --git a/packages/ui/src/forms/Form/fieldReducer.ts b/packages/ui/src/forms/Form/fieldReducer.ts index 121249de03c..ae74a6ad50b 100644 --- a/packages/ui/src/forms/Form/fieldReducer.ts +++ b/packages/ui/src/forms/Form/fieldReducer.ts @@ -1,3 +1,4 @@ +'use client' import type { FormField, FormState, Row } from 'payload' import ObjectIdImport from 'bson-objectid' diff --git a/packages/ui/src/forms/Form/initContextState.ts b/packages/ui/src/forms/Form/initContextState.ts index 33991e0bd05..78b821e0a45 100644 --- a/packages/ui/src/forms/Form/initContextState.ts +++ b/packages/ui/src/forms/Form/initContextState.ts @@ -1,3 +1,4 @@ +'use client' import type { Data, FormField, FormState } from 'payload' import type { diff --git a/packages/ui/src/forms/Form/mergeErrorPaths.ts b/packages/ui/src/forms/Form/mergeErrorPaths.ts index f2864e0e816..9384ed1565a 100644 --- a/packages/ui/src/forms/Form/mergeErrorPaths.ts +++ b/packages/ui/src/forms/Form/mergeErrorPaths.ts @@ -1,3 +1,4 @@ +'use client' import { arraysHaveSameStrings } from '../../utilities/arraysHaveSameStrings.js' export const mergeErrorPaths = ( diff --git a/packages/ui/src/forms/Form/mergeServerFormState.ts b/packages/ui/src/forms/Form/mergeServerFormState.ts index 4d4df278848..77240c9773f 100644 --- a/packages/ui/src/forms/Form/mergeServerFormState.ts +++ b/packages/ui/src/forms/Form/mergeServerFormState.ts @@ -1,3 +1,4 @@ +'use client' import type { FormState } from 'payload' import { dequal } from 'dequal/lite' // lite: no need for Map and Set support diff --git a/packages/ui/src/forms/Form/rowHelpers.ts b/packages/ui/src/forms/Form/rowHelpers.ts index 60a582db7a8..08c52629e4d 100644 --- a/packages/ui/src/forms/Form/rowHelpers.ts +++ b/packages/ui/src/forms/Form/rowHelpers.ts @@ -1,3 +1,4 @@ +'use client' import type { Row } from 'payload' export const extractRowsAndCollapsedIDs = ({ diff --git a/packages/ui/src/forms/Form/rows.ts b/packages/ui/src/forms/Form/rows.ts index 17b45fec833..129e4491ddf 100644 --- a/packages/ui/src/forms/Form/rows.ts +++ b/packages/ui/src/forms/Form/rows.ts @@ -1,3 +1,4 @@ +'use client' import type { FormState } from 'payload' type Result = { diff --git a/packages/ui/src/forms/RowLabel/Context/index.tsx b/packages/ui/src/forms/RowLabel/Context/index.tsx index fb4d1e9d259..ab08192cc6c 100644 --- a/packages/ui/src/forms/RowLabel/Context/index.tsx +++ b/packages/ui/src/forms/RowLabel/Context/index.tsx @@ -21,6 +21,7 @@ type Props = { } & Omit, 'data'> export const RowLabelProvider: React.FC> = ({ children, path, rowNumber }) => { + 'use no memo' const { getDataByPath, getSiblingData } = useWatchForm() const collapsibleData = getSiblingData(path) const arrayData = getDataByPath(path) diff --git a/packages/ui/src/forms/RowLabel/index.tsx b/packages/ui/src/forms/RowLabel/index.tsx index 94ca124967c..70e461c6b22 100644 --- a/packages/ui/src/forms/RowLabel/index.tsx +++ b/packages/ui/src/forms/RowLabel/index.tsx @@ -1,3 +1,4 @@ +'use client' import { getTranslation } from '@payloadcms/translations' import React from 'react' diff --git a/packages/ui/src/forms/WatchChildErrors/buildPathSegments.ts b/packages/ui/src/forms/WatchChildErrors/buildPathSegments.ts index cce9875e1e3..87e0c1070d4 100644 --- a/packages/ui/src/forms/WatchChildErrors/buildPathSegments.ts +++ b/packages/ui/src/forms/WatchChildErrors/buildPathSegments.ts @@ -1,3 +1,4 @@ +'use client' import type { ClientField } from 'payload' import { fieldAffectsData } from 'payload/shared' diff --git a/packages/ui/src/forms/WatchChildErrors/getFieldStateFromPaths.ts b/packages/ui/src/forms/WatchChildErrors/getFieldStateFromPaths.ts index 000d9d6e815..e47df2e51a7 100644 --- a/packages/ui/src/forms/WatchChildErrors/getFieldStateFromPaths.ts +++ b/packages/ui/src/forms/WatchChildErrors/getFieldStateFromPaths.ts @@ -1,3 +1,4 @@ +'use client' import type { FormState } from 'payload' export const getFieldStateFromPaths = ({ diff --git a/packages/ui/src/forms/WatchChildErrors/getNestedFieldState.ts b/packages/ui/src/forms/WatchChildErrors/getNestedFieldState.ts index 1f3eaeadaf4..87fa7ed95f5 100644 --- a/packages/ui/src/forms/WatchChildErrors/getNestedFieldState.ts +++ b/packages/ui/src/forms/WatchChildErrors/getNestedFieldState.ts @@ -1,3 +1,4 @@ +'use client' import type { Field, FormState } from 'payload' // import { buildPathSegments } from './buildPathSegments' diff --git a/packages/ui/src/forms/WatchChildErrors/index.tsx b/packages/ui/src/forms/WatchChildErrors/index.tsx index 4a11f642a45..c0265d7237c 100644 --- a/packages/ui/src/forms/WatchChildErrors/index.tsx +++ b/packages/ui/src/forms/WatchChildErrors/index.tsx @@ -1,5 +1,5 @@ 'use client' -import type { ClientField } from 'packages/payload/src/index.js' +import type { ClientField } from 'payload' import type React from 'react' import { useThrottledEffect } from '../../hooks/useThrottledEffect.js' diff --git a/packages/ui/src/hooks/useDebouncedCallback.ts b/packages/ui/src/hooks/useDebouncedCallback.ts index b2cd97ee856..d5cac66f28b 100644 --- a/packages/ui/src/hooks/useDebouncedCallback.ts +++ b/packages/ui/src/hooks/useDebouncedCallback.ts @@ -1,3 +1,4 @@ +'use client' import { useCallback, useRef } from 'react' /** diff --git a/packages/ui/src/hooks/useDebouncedEffect.ts b/packages/ui/src/hooks/useDebouncedEffect.ts index 853ee7f0fdd..027302b35a3 100644 --- a/packages/ui/src/hooks/useDebouncedEffect.ts +++ b/packages/ui/src/hooks/useDebouncedEffect.ts @@ -1,3 +1,4 @@ +'use client' import type { DependencyList } from 'react' import { useEffect, useState } from 'react' diff --git a/packages/ui/src/hooks/useDelay.ts b/packages/ui/src/hooks/useDelay.ts index 6cef0c34dde..d30b46c194c 100644 --- a/packages/ui/src/hooks/useDelay.ts +++ b/packages/ui/src/hooks/useDelay.ts @@ -1,3 +1,4 @@ +'use client' import * as React from 'react' type Result = [boolean, () => void] diff --git a/packages/ui/src/hooks/useDelayedRender.ts b/packages/ui/src/hooks/useDelayedRender.ts index 649d9983bdb..e163b9522de 100644 --- a/packages/ui/src/hooks/useDelayedRender.ts +++ b/packages/ui/src/hooks/useDelayedRender.ts @@ -1,3 +1,4 @@ +'use client' import * as React from 'react' import { useDelay } from './useDelay.js' diff --git a/packages/ui/src/hooks/useIntersect.ts b/packages/ui/src/hooks/useIntersect.ts index 732e78d4879..7782551e0e1 100644 --- a/packages/ui/src/hooks/useIntersect.ts +++ b/packages/ui/src/hooks/useIntersect.ts @@ -1,5 +1,7 @@ 'use client' +import type React from 'react' + import { useEffect, useRef, useState } from 'react' type Intersect = [ diff --git a/packages/ui/src/hooks/usePayloadAPI.ts b/packages/ui/src/hooks/usePayloadAPI.ts index 64b17937cee..ee81c88a2cd 100644 --- a/packages/ui/src/hooks/usePayloadAPI.ts +++ b/packages/ui/src/hooks/usePayloadAPI.ts @@ -1,4 +1,6 @@ 'use client' +import type React from 'react' + import * as qs from 'qs-esm' import { useEffect, useRef, useState } from 'react' diff --git a/packages/ui/src/hooks/useResize.ts b/packages/ui/src/hooks/useResize.ts index 228a8e5869c..f8468888c37 100644 --- a/packages/ui/src/hooks/useResize.ts +++ b/packages/ui/src/hooks/useResize.ts @@ -1,5 +1,4 @@ 'use client' -import type React from 'react' import { useEffect, useState } from 'react' diff --git a/packages/ui/src/hooks/useThrottledEffect.ts b/packages/ui/src/hooks/useThrottledEffect.ts index 243dd8f08a8..a0a68474d14 100644 --- a/packages/ui/src/hooks/useThrottledEffect.ts +++ b/packages/ui/src/hooks/useThrottledEffect.ts @@ -1,3 +1,6 @@ +'use client' +import type React from 'react' + import { useEffect, useRef } from 'react' type useThrottledEffect = ( diff --git a/packages/ui/src/hooks/useUseAsTitle.ts b/packages/ui/src/hooks/useUseAsTitle.ts index e8f8e10e44b..df50fc52987 100644 --- a/packages/ui/src/hooks/useUseAsTitle.ts +++ b/packages/ui/src/hooks/useUseAsTitle.ts @@ -1,3 +1,4 @@ +'use client' import type { ClientCollectionConfig, ClientField } from 'payload' import { flattenFieldMap } from '../utilities/flattenFieldMap.js' diff --git a/packages/ui/src/providers/Actions/SetViewActions/index.tsx b/packages/ui/src/providers/Actions/SetViewActions/index.tsx index 39319e5a7c1..1f533bf859d 100644 --- a/packages/ui/src/providers/Actions/SetViewActions/index.tsx +++ b/packages/ui/src/providers/Actions/SetViewActions/index.tsx @@ -1,8 +1,10 @@ 'use client' -import React, { useEffect } from 'react' +import type { MappedComponent } from 'payload' +import type React from 'react' + +import { useEffect } from 'react' import { useActions } from '../index.js' -import type { MappedComponent } from 'payload' export const SetViewActions: React.FC<{ actions: MappedComponent[] }> = ({ actions }) => { const { setViewActions } = useActions() diff --git a/packages/ui/src/providers/ScrollInfo/index.tsx b/packages/ui/src/providers/ScrollInfo/index.tsx index 0b0dc5e1483..73ba6a36a5f 100644 --- a/packages/ui/src/providers/ScrollInfo/index.tsx +++ b/packages/ui/src/providers/ScrollInfo/index.tsx @@ -1,3 +1,4 @@ +'use client' import * as facelessUIImport from '@faceless-ui/scroll-info' const { ScrollInfoProvider } = facelessUIImport && 'ScrollInfoProvider' in facelessUIImport diff --git a/packages/ui/src/providers/ToastContainer/icons/Error.tsx b/packages/ui/src/providers/ToastContainer/icons/Error.tsx index 6dc8acb0b53..3d406abf884 100644 --- a/packages/ui/src/providers/ToastContainer/icons/Error.tsx +++ b/packages/ui/src/providers/ToastContainer/icons/Error.tsx @@ -1,3 +1,4 @@ +'use client' import React from 'react' export const Error: React.FC = () => { diff --git a/packages/ui/src/providers/ToastContainer/icons/Info.tsx b/packages/ui/src/providers/ToastContainer/icons/Info.tsx index f368a9753d4..fa87d4fa3e8 100644 --- a/packages/ui/src/providers/ToastContainer/icons/Info.tsx +++ b/packages/ui/src/providers/ToastContainer/icons/Info.tsx @@ -1,3 +1,4 @@ +'use client' import React from 'react' export const Info: React.FC = () => { diff --git a/packages/ui/src/providers/ToastContainer/icons/Success.tsx b/packages/ui/src/providers/ToastContainer/icons/Success.tsx index 40fca2a08fb..250d60a82ca 100644 --- a/packages/ui/src/providers/ToastContainer/icons/Success.tsx +++ b/packages/ui/src/providers/ToastContainer/icons/Success.tsx @@ -1,3 +1,4 @@ +'use client' import React from 'react' export const Success: React.FC = () => { diff --git a/packages/ui/src/providers/ToastContainer/icons/Warning.tsx b/packages/ui/src/providers/ToastContainer/icons/Warning.tsx index e5f15978c14..efdba8a6d35 100644 --- a/packages/ui/src/providers/ToastContainer/icons/Warning.tsx +++ b/packages/ui/src/providers/ToastContainer/icons/Warning.tsx @@ -1,3 +1,4 @@ +'use client' import React from 'react' export const Warning: React.FC = () => { diff --git a/packages/ui/src/providers/UploadEdits/index.tsx b/packages/ui/src/providers/UploadEdits/index.tsx index 46083495069..2fb82354400 100644 --- a/packages/ui/src/providers/UploadEdits/index.tsx +++ b/packages/ui/src/providers/UploadEdits/index.tsx @@ -1,3 +1,4 @@ +'use client' import type { UploadEdits } from 'payload' import React from 'react' diff --git a/packages/ui/src/providers/WindowInfo/index.tsx b/packages/ui/src/providers/WindowInfo/index.tsx index e24842bc581..88d174925f5 100644 --- a/packages/ui/src/providers/WindowInfo/index.tsx +++ b/packages/ui/src/providers/WindowInfo/index.tsx @@ -1,3 +1,4 @@ +'use client' import * as facelessUIImport from '@faceless-ui/window-info' const { WindowInfoProvider } = facelessUIImport && 'WindowInfoProvider' in facelessUIImport diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index b61ce3ed543..4349a02e78a 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -143,7 +143,7 @@ importers: version: 9.4.1(@aws-sdk/credential-providers@3.630.0(@aws-sdk/client-sso-oidc@3.629.0(@aws-sdk/client-sts@3.629.0))) next: specifier: 15.0.0-canary.104 - version: 15.0.0-canary.104(@babel/core@7.25.2)(@playwright/test@1.46.0)(babel-plugin-macros@3.1.0)(babel-plugin-react-compiler@0.0.0-experimental-592953e-20240517)(react-dom@19.0.0-rc-06d0b89e-20240801(react@19.0.0-rc-06d0b89e-20240801))(react@19.0.0-rc-06d0b89e-20240801)(sass@1.77.4) + version: 15.0.0-canary.104(@playwright/test@1.46.0)(babel-plugin-macros@3.1.0)(babel-plugin-react-compiler@0.0.0-experimental-1cd8995-20240814)(react-dom@19.0.0-rc-06d0b89e-20240801(react@19.0.0-rc-06d0b89e-20240801))(react@19.0.0-rc-06d0b89e-20240801)(sass@1.77.4) open: specifier: ^10.1.0 version: 10.1.0 @@ -668,7 +668,7 @@ importers: version: 1.6.2 next: specifier: ^15.0.0-canary.104 - version: 15.0.0-canary.104(@babel/core@7.25.2)(@playwright/test@1.46.0)(babel-plugin-macros@3.1.0)(babel-plugin-react-compiler@0.0.0-experimental-592953e-20240517)(react-dom@19.0.0-rc-06d0b89e-20240801(react@19.0.0-rc-06d0b89e-20240801))(react@19.0.0-rc-06d0b89e-20240801)(sass@1.77.4) + version: 15.0.0-canary.104(@playwright/test@1.46.0)(babel-plugin-macros@3.1.0)(babel-plugin-react-compiler@0.0.0-experimental-1cd8995-20240814)(react-dom@19.0.0-rc-06d0b89e-20240801(react@19.0.0-rc-06d0b89e-20240801))(react@19.0.0-rc-06d0b89e-20240801)(sass@1.77.4) path-to-regexp: specifier: ^6.2.1 version: 6.2.2 @@ -1232,6 +1232,21 @@ importers: specifier: 10.0.0 version: 10.0.0 devDependencies: + '@babel/cli': + specifier: ^7.24.5 + version: 7.24.8(@babel/core@7.25.2) + '@babel/core': + specifier: ^7.24.5 + version: 7.25.2 + '@babel/preset-env': + specifier: ^7.24.5 + version: 7.25.3(@babel/core@7.25.2) + '@babel/preset-react': + specifier: ^7.24.1 + version: 7.24.7(@babel/core@7.25.2) + '@babel/preset-typescript': + specifier: ^7.24.1 + version: 7.24.7(@babel/core@7.25.2) '@lexical/eslint-plugin': specifier: 0.17.0 version: 0.17.0(eslint@9.6.0) @@ -1259,12 +1274,21 @@ importers: '@types/react-dom': specifier: npm:types-react-dom@19.0.0-rc.0 version: types-react-dom@19.0.0-rc.0 + babel-plugin-react-compiler: + specifier: 0.0.0-experimental-1cd8995-20240814 + version: 0.0.0-experimental-1cd8995-20240814 + babel-plugin-transform-remove-imports: + specifier: ^1.8.0 + version: 1.8.0(@babel/core@7.25.2) esbuild: specifier: 0.23.0 version: 0.23.0 esbuild-sass-plugin: specifier: 3.3.1 version: 3.3.1(esbuild@0.23.0)(sass-embedded@1.77.8) + eslint-plugin-react-compiler: + specifier: 0.0.0-experimental-d0e920e-20240815 + version: 0.0.0-experimental-d0e920e-20240815(eslint@9.6.0) payload: specifier: workspace:* version: link:../payload @@ -1463,7 +1487,7 @@ importers: version: 2.3.0 next: specifier: ^15.0.0-canary.104 - version: 15.0.0-canary.104(@babel/core@7.25.2)(@playwright/test@1.46.0)(babel-plugin-macros@3.1.0)(babel-plugin-react-compiler@0.0.0-experimental-592953e-20240517)(react-dom@19.0.0-rc-06d0b89e-20240801(react@19.0.0-rc-06d0b89e-20240801))(react@19.0.0-rc-06d0b89e-20240801)(sass@1.77.4) + version: 15.0.0-canary.104(@babel/core@7.25.2)(@playwright/test@1.46.0)(babel-plugin-macros@3.1.0)(babel-plugin-react-compiler@0.0.0-experimental-1cd8995-20240814)(react-dom@19.0.0-rc-06d0b89e-20240801(react@19.0.0-rc-06d0b89e-20240801))(react@19.0.0-rc-06d0b89e-20240801)(sass@1.77.4) object-to-formdata: specifier: 4.5.1 version: 4.5.1 @@ -1541,14 +1565,17 @@ importers: specifier: 10.0.0 version: 10.0.0 babel-plugin-react-compiler: - specifier: 0.0.0-experimental-592953e-20240517 - version: 0.0.0-experimental-592953e-20240517 + specifier: 0.0.0-experimental-1cd8995-20240814 + version: 0.0.0-experimental-1cd8995-20240814 esbuild: specifier: 0.23.0 version: 0.23.0 esbuild-sass-plugin: specifier: 3.3.1 version: 3.3.1(esbuild@0.23.0)(sass-embedded@1.77.8) + eslint-plugin-react-compiler: + specifier: 0.0.0-experimental-d0e920e-20240815 + version: 0.0.0-experimental-d0e920e-20240815(eslint@9.6.0) payload: specifier: workspace:* version: link:../payload @@ -1667,8 +1694,8 @@ importers: specifier: npm:types-react-dom@19.0.0-rc.0 version: types-react-dom@19.0.0-rc.0 babel-plugin-react-compiler: - specifier: 0.0.0-experimental-592953e-20240517 - version: 0.0.0-experimental-592953e-20240517 + specifier: 0.0.0-experimental-1cd8995-20240814 + version: 0.0.0-experimental-1cd8995-20240814 comment-json: specifier: ^4.2.3 version: 4.2.5 @@ -1699,12 +1726,21 @@ importers: lexical: specifier: 0.17.0 version: 0.17.0 + next: + specifier: 15.0.0-canary.104 + version: 15.0.0-canary.104(@playwright/test@1.46.0)(babel-plugin-macros@3.1.0)(babel-plugin-react-compiler@0.0.0-experimental-1cd8995-20240814)(react-dom@19.0.0-rc-06d0b89e-20240801(react@19.0.0-rc-06d0b89e-20240801))(react@19.0.0-rc-06d0b89e-20240801)(sass@1.77.4) payload: specifier: workspace:* version: link:../packages/payload qs-esm: specifier: 7.0.2 version: 7.0.2 + react: + specifier: 19.0.0-rc-06d0b89e-20240801 + version: 19.0.0-rc-06d0b89e-20240801 + react-dom: + specifier: 19.0.0-rc-06d0b89e-20240801 + version: 19.0.0-rc-06d0b89e-20240801(react@19.0.0-rc-06d0b89e-20240801) server-only: specifier: ^0.0.1 version: 0.0.1 @@ -2131,6 +2167,13 @@ packages: peerDependencies: '@babel/core': ^7.0.0 + '@babel/plugin-proposal-private-methods@7.18.6': + resolution: {integrity: sha512-nutsvktDItsNn4rpGItSNV2sz1XwS+nfU0Rg8aCx3W3NOKVzdMjJRu0O5OkgDp3ZGICSTbgRpxZoWsxoKRvbeA==} + engines: {node: '>=6.9.0'} + deprecated: This proposal has been merged to the ECMAScript standard and thus this plugin is no longer maintained. Please use @babel/plugin-transform-private-methods instead. + peerDependencies: + '@babel/core': ^7.0.0-0 + '@babel/plugin-proposal-private-property-in-object@7.21.0-placeholder-for-preset-env.2': resolution: {integrity: sha512-SOSkfJDddaM7mak6cPEpswyTRnuRltl429hMraQEglW+OkovnCzsiszTmsrlY//qLFjCpQDFRvjdm2wA5pPm9w==} engines: {node: '>=6.9.0'} @@ -4781,8 +4824,13 @@ packages: peerDependencies: '@babel/core': ^7.4.0 || ^8.0.0-0 <8.0.0 - babel-plugin-react-compiler@0.0.0-experimental-592953e-20240517: - resolution: {integrity: sha512-OjG1SVaeQZaJrqkMFJatg8W/MTow8Ak5rx2SI0ETQBO1XvOk/XZGMbltNCPdFJLKghBYoBjC+Y3Ap/Xr7B01mA==} + babel-plugin-react-compiler@0.0.0-experimental-1cd8995-20240814: + resolution: {integrity: sha512-4DWAliKzk3ACtvOn0pbUStj8DRy//bA9Icze8u/8+hCYNR2xNWupnocP+FpoCC8tDNkFDSAzQyrQZS5uBeyH9A==} + + babel-plugin-transform-remove-imports@1.8.0: + resolution: {integrity: sha512-QdE5ZnIjON1pSgTPU8KzLnl/LEzdq9PLmZNuHgGKTx0LOI9PBrHBj0fz9uCg2CdssiTw7v/zVRYs8GJxbvhKnQ==} + peerDependencies: + '@babel/core': ^7.0.0-0 babel-preset-current-node-syntax@1.1.0: resolution: {integrity: sha512-ldYss8SbBlWva1bs28q78Ju5Zq1F+8BrqBZZ0VFhLBvhh6lCpC2o3gDJi/5DRLs9FgYZCnmPYIVFU4lRXCkyUw==} @@ -5787,6 +5835,12 @@ packages: eslint-plugin-jest: optional: true + eslint-plugin-react-compiler@0.0.0-experimental-d0e920e-20240815: + resolution: {integrity: sha512-ICIcejquXmO2ednUy2wZ1I0i8NgExZeS+eYMQmygTpUEihxw0pxsKCCzIVBcwzdHYqPzrgkP/GLUEYgPQn2iQA==} + engines: {node: ^14.17.0 || ^16.0.0 || >= 18.0.0} + peerDependencies: + eslint: '>=7' + eslint-plugin-react-debug@1.5.25-next.4: resolution: {integrity: sha512-xdv36T0Fyh1mlLrE8k+Mw+6wq/YTowuI45lGqKySKQEuQ1IhNu/LmBpf9K/OW9FU7tOPaTvK4RYl+QBT0zuJHg==} engines: {bun: '>=1.0.15', node: '>=18.18.0'} @@ -6391,6 +6445,12 @@ packages: help-me@5.0.0: resolution: {integrity: sha512-7xgomUX6ADmcYzFik0HzAxh/73YlKR9bmFzf51CZwR+b6YtzU2m0u49hQCqV6SvlqIqsaxovfwdvbnsw3b/zpg==} + hermes-estree@0.20.1: + resolution: {integrity: sha512-SQpZK4BzR48kuOg0v4pb3EAGNclzIlqMj3Opu/mu7bbAoFw6oig6cEt/RAi0zTFW/iW6Iz9X9ggGuZTAZ/yZHg==} + + hermes-parser@0.20.1: + resolution: {integrity: sha512-BL5P83cwCogI8D7rrDCgsFY0tdYUtmFP9XaXtl2IQjC+2Xo+4okjfXintlTxcIwl4qeGddEl28Z11kbVIw0aNA==} + hoist-non-react-statics@3.3.2: resolution: {integrity: sha512-/gGivxi8JPKWNm/W0jSmzcMPpfpPLc3dY/6GxhX2hQ9iGj3aDfklV4ET7NjKpSinLpJ5vafa9iiGIEZg10SfBw==} @@ -9489,6 +9549,12 @@ packages: peerDependencies: zod: ^3.18.0 + zod-validation-error@3.3.1: + resolution: {integrity: sha512-uFzCZz7FQis256dqw4AhPQgD6f3pzNca/Zh62RNELavlumQB3nDIUFbF5JQfFLcMbO1s02Q7Xg/gpcOBlEnYZA==} + engines: {node: '>=18.0.0'} + peerDependencies: + zod: ^3.18.0 + zod@3.23.8: resolution: {integrity: sha512-XBx9AXhXktjUqnepgTiE5flcKIYWi/rme0Eaj+5Y0lftuGBq+jyRu/md4WnuxqgP1ubdpNCsYEYPxrzVHD8d6g==} @@ -10423,6 +10489,14 @@ snapshots: transitivePeerDependencies: - supports-color + '@babel/plugin-proposal-private-methods@7.18.6(@babel/core@7.25.2)': + dependencies: + '@babel/core': 7.25.2 + '@babel/helper-create-class-features-plugin': 7.25.0(@babel/core@7.25.2) + '@babel/helper-plugin-utils': 7.24.8 + transitivePeerDependencies: + - supports-color + '@babel/plugin-proposal-private-property-in-object@7.21.0-placeholder-for-preset-env.2(@babel/core@7.25.2)': dependencies: '@babel/core': 7.25.2 @@ -13569,7 +13643,7 @@ snapshots: transitivePeerDependencies: - supports-color - babel-plugin-react-compiler@0.0.0-experimental-592953e-20240517: + babel-plugin-react-compiler@0.0.0-experimental-1cd8995-20240814: dependencies: '@babel/generator': 7.2.0 '@babel/types': 7.25.2 @@ -13579,6 +13653,10 @@ snapshots: zod: 3.23.8 zod-validation-error: 2.1.0(zod@3.23.8) + babel-plugin-transform-remove-imports@1.8.0(@babel/core@7.25.2): + dependencies: + '@babel/core': 7.25.2 + babel-preset-current-node-syntax@1.1.0(@babel/core@7.25.2): dependencies: '@babel/core': 7.25.2 @@ -14702,6 +14780,18 @@ snapshots: optionalDependencies: eslint-plugin-jest: 28.6.0(@typescript-eslint/eslint-plugin@7.16.0(@typescript-eslint/parser@7.16.0(eslint@9.6.0)(typescript@5.5.4))(eslint@9.6.0)(typescript@5.5.4))(eslint@9.6.0)(jest@29.7.0(@types/node@20.12.5)(babel-plugin-macros@3.1.0))(typescript@5.5.4) + eslint-plugin-react-compiler@0.0.0-experimental-d0e920e-20240815(eslint@9.6.0): + dependencies: + '@babel/core': 7.25.2 + '@babel/parser': 7.25.3 + '@babel/plugin-proposal-private-methods': 7.18.6(@babel/core@7.25.2) + eslint: 9.6.0 + hermes-parser: 0.20.1 + zod: 3.23.8 + zod-validation-error: 3.3.1(zod@3.23.8) + transitivePeerDependencies: + - supports-color + eslint-plugin-react-debug@1.5.25-next.4(eslint@9.6.0)(typescript@5.5.4): dependencies: '@eslint-react/ast': 1.5.25-next.4(eslint@9.6.0)(typescript@5.5.4) @@ -15487,6 +15577,12 @@ snapshots: help-me@5.0.0: {} + hermes-estree@0.20.1: {} + + hermes-parser@0.20.1: + dependencies: + hermes-estree: 0.20.1 + hoist-non-react-statics@3.3.2: dependencies: react-is: 16.13.1 @@ -16755,7 +16851,7 @@ snapshots: next-tick@1.1.0: {} - next@15.0.0-canary.104(@babel/core@7.25.2)(@playwright/test@1.46.0)(babel-plugin-macros@3.1.0)(babel-plugin-react-compiler@0.0.0-experimental-592953e-20240517)(react-dom@19.0.0-rc-06d0b89e-20240801(react@19.0.0-rc-06d0b89e-20240801))(react@19.0.0-rc-06d0b89e-20240801)(sass@1.77.4): + next@15.0.0-canary.104(@babel/core@7.25.2)(@playwright/test@1.46.0)(babel-plugin-macros@3.1.0)(babel-plugin-react-compiler@0.0.0-experimental-1cd8995-20240814)(react-dom@19.0.0-rc-06d0b89e-20240801(react@19.0.0-rc-06d0b89e-20240801))(react@19.0.0-rc-06d0b89e-20240801)(sass@1.77.4): dependencies: '@next/env': 15.0.0-canary.104 '@swc/counter': 0.1.3 @@ -16778,7 +16874,37 @@ snapshots: '@next/swc-win32-ia32-msvc': 15.0.0-canary.104 '@next/swc-win32-x64-msvc': 15.0.0-canary.104 '@playwright/test': 1.46.0 - babel-plugin-react-compiler: 0.0.0-experimental-592953e-20240517 + babel-plugin-react-compiler: 0.0.0-experimental-1cd8995-20240814 + sass: 1.77.4 + sharp: 0.33.4 + transitivePeerDependencies: + - '@babel/core' + - babel-plugin-macros + + next@15.0.0-canary.104(@playwright/test@1.46.0)(babel-plugin-macros@3.1.0)(babel-plugin-react-compiler@0.0.0-experimental-1cd8995-20240814)(react-dom@19.0.0-rc-06d0b89e-20240801(react@19.0.0-rc-06d0b89e-20240801))(react@19.0.0-rc-06d0b89e-20240801)(sass@1.77.4): + dependencies: + '@next/env': 15.0.0-canary.104 + '@swc/counter': 0.1.3 + '@swc/helpers': 0.5.12 + busboy: 1.6.0 + caniuse-lite: 1.0.30001651 + graceful-fs: 4.2.11 + postcss: 8.4.31 + react: 19.0.0-rc-06d0b89e-20240801 + react-dom: 19.0.0-rc-06d0b89e-20240801(react@19.0.0-rc-06d0b89e-20240801) + styled-jsx: 5.1.6(@babel/core@7.25.2)(babel-plugin-macros@3.1.0)(react@19.0.0-rc-06d0b89e-20240801) + optionalDependencies: + '@next/swc-darwin-arm64': 15.0.0-canary.104 + '@next/swc-darwin-x64': 15.0.0-canary.104 + '@next/swc-linux-arm64-gnu': 15.0.0-canary.104 + '@next/swc-linux-arm64-musl': 15.0.0-canary.104 + '@next/swc-linux-x64-gnu': 15.0.0-canary.104 + '@next/swc-linux-x64-musl': 15.0.0-canary.104 + '@next/swc-win32-arm64-msvc': 15.0.0-canary.104 + '@next/swc-win32-ia32-msvc': 15.0.0-canary.104 + '@next/swc-win32-x64-msvc': 15.0.0-canary.104 + '@playwright/test': 1.46.0 + babel-plugin-react-compiler: 0.0.0-experimental-1cd8995-20240814 sass: 1.77.4 sharp: 0.33.4 transitivePeerDependencies: @@ -18573,7 +18699,7 @@ snapshots: std-env: 3.7.0 optionalDependencies: express: 4.19.2 - next: 15.0.0-canary.104(@babel/core@7.25.2)(@playwright/test@1.46.0)(babel-plugin-macros@3.1.0)(babel-plugin-react-compiler@0.0.0-experimental-592953e-20240517)(react-dom@19.0.0-rc-06d0b89e-20240801(react@19.0.0-rc-06d0b89e-20240801))(react@19.0.0-rc-06d0b89e-20240801)(sass@1.77.4) + next: 15.0.0-canary.104(@playwright/test@1.46.0)(babel-plugin-macros@3.1.0)(babel-plugin-react-compiler@0.0.0-experimental-1cd8995-20240814)(react-dom@19.0.0-rc-06d0b89e-20240801(react@19.0.0-rc-06d0b89e-20240801))(react@19.0.0-rc-06d0b89e-20240801)(sass@1.77.4) uri-js@4.4.1: dependencies: @@ -18833,4 +18959,8 @@ snapshots: dependencies: zod: 3.23.8 + zod-validation-error@3.3.1(zod@3.23.8): + dependencies: + zod: 3.23.8 + zod@3.23.8: {} diff --git a/scripts/lib/getPackageDetails.ts b/scripts/lib/getPackageDetails.ts index 7d57f19a16f..971fa038027 100644 --- a/scripts/lib/getPackageDetails.ts +++ b/scripts/lib/getPackageDetails.ts @@ -35,7 +35,9 @@ export const getPackageDetails = async (packages: string[]): Promise { }) async function main() { + const all = process.argv.includes('--all') + process.argv = process.argv.filter((arg) => arg !== '--all') + + const noBuild = process.argv.includes('--no-build') + process.argv = process.argv.filter((arg) => arg !== '--no-build') + const args = minimist(process.argv.slice(2)) const { dest } = args if (!dest) throw new Error('--dest is required') const resolvedDest = path.resolve(dest) - const packageWhitelist = [ - 'payload', - 'ui', - 'next', - 'db-mongodb', - 'drizzle', - 'db-sqlite', - 'db-postgres', - 'richtext-lexical', - 'translations', - 'plugin-cloud', - 'graphql', - ] + const packageWhitelist = all + ? null + : [ + 'payload', + 'ui', + 'next', + 'db-mongodb', + 'drizzle', + 'db-sqlite', + 'db-postgres', + 'richtext-lexical', + 'translations', + 'plugin-cloud', + 'graphql', + ] const packageDetails = await getPackageDetails(packageWhitelist) @@ -58,8 +66,9 @@ async function main() { ${chalk.white.bold(filtered.map((p) => p.name).join('\n'))} `) - - execSync('pnpm build:all --output-logs=errors-only', { stdio: 'inherit' }) + if (!noBuild) { + execSync('pnpm build:all --output-logs=errors-only', { stdio: 'inherit' }) + } header(`\n 📦 Packing all packages to ${dest}...`) diff --git a/templates/website/package.json b/templates/website/package.json index 93631b22bb1..fcc0f44ac74 100644 --- a/templates/website/package.json +++ b/templates/website/package.json @@ -8,14 +8,14 @@ "build": "cross-env NODE_OPTIONS=--no-deprecation next build", "dev": "cross-env NODE_OPTIONS=--no-deprecation next dev", "dev:prod": "cross-env NODE_OPTIONS=--no-deprecation rm -rf .next && pnpm build && pnpm start", + "generate:importmap": "payload generate:importmap", + "generate:types": "payload generate:types", "ii": "cross-env NODE_OPTIONS=--no-deprecation pnpm --ignore-workspace install", "lint": "cross-env NODE_OPTIONS=--no-deprecation next lint", "lint:fix": "cross-env NODE_OPTIONS=--no-deprecation next lint --fix", - "reinstall": "cross-env NODE_OPTIONS=--no-deprecation rm -rf node_modules && rm pnpm-lock.yaml && pnpm --ignore-workspace install", - "start": "cross-env NODE_OPTIONS=--no-deprecation next start", "payload": "payload", - "generate:types": "payload generate:types", - "generate:importmap": "payload generate:importmap" + "reinstall": "cross-env NODE_OPTIONS=--no-deprecation rm -rf node_modules && rm pnpm-lock.yaml && pnpm --ignore-workspace install", + "start": "cross-env NODE_OPTIONS=--no-deprecation next start" }, "dependencies": { "@payloadcms/db-mongodb": "3.0.0-beta.84", diff --git a/test/app/(app)/layout.tsx b/test/app/(app)/layout.tsx new file mode 100644 index 00000000000..dd4142d17fb --- /dev/null +++ b/test/app/(app)/layout.tsx @@ -0,0 +1,14 @@ +import React from 'react' + +export const metadata = { + description: 'Generated by Next.js', + title: 'Next.js', +} + +export default function RootLayout({ children }: { children: React.ReactNode }) { + return ( + + {children} + + ) +} diff --git a/test/app/(app)/test/page.tsx b/test/app/(app)/test/page.tsx new file mode 100644 index 00000000000..3ddab66cb5d --- /dev/null +++ b/test/app/(app)/test/page.tsx @@ -0,0 +1,11 @@ +import configPromise from '@payload-config' +import { getPayloadHMR } from '@payloadcms/next/utilities' + +export const Page = async ({ params, searchParams }) => { + const payload = await getPayloadHMR({ + config: configPromise, + }) + return
test ${payload?.config?.collections?.length}
+} + +export default Page diff --git a/test/app/(payload)/admin/[[...segments]]/not-found.tsx b/test/app/(payload)/admin/[[...segments]]/not-found.tsx new file mode 100644 index 00000000000..f2492a309d5 --- /dev/null +++ b/test/app/(payload)/admin/[[...segments]]/not-found.tsx @@ -0,0 +1,25 @@ +/* THIS FILE WAS GENERATED AUTOMATICALLY BY PAYLOAD. */ +import type { Metadata } from 'next' + +import config from '@payload-config' +/* DO NOT MODIFY IT BECAUSE IT COULD BE REWRITTEN AT ANY TIME. */ +import { NotFoundPage, generatePageMetadata } from '@payloadcms/next/views' + +import { importMap } from '../importMap.js' + +type Args = { + params: { + segments: string[] + } + searchParams: { + [key: string]: string | string[] + } +} + +export const generateMetadata = ({ params, searchParams }: Args): Promise => + generatePageMetadata({ config, params, searchParams }) + +const NotFound = ({ params, searchParams }: Args) => + NotFoundPage({ config, importMap, params, searchParams }) + +export default NotFound diff --git a/test/app/(payload)/admin/[[...segments]]/page.tsx b/test/app/(payload)/admin/[[...segments]]/page.tsx new file mode 100644 index 00000000000..0bfe410796e --- /dev/null +++ b/test/app/(payload)/admin/[[...segments]]/page.tsx @@ -0,0 +1,25 @@ +/* THIS FILE WAS GENERATED AUTOMATICALLY BY PAYLOAD. */ +import type { Metadata } from 'next' + +import config from '@payload-config' +/* DO NOT MODIFY IT BECAUSE IT COULD BE REWRITTEN AT ANY TIME. */ +import { RootPage, generatePageMetadata } from '@payloadcms/next/views' + +import { importMap } from '../importMap.js' + +type Args = { + params: { + segments: string[] + } + searchParams: { + [key: string]: string | string[] + } +} + +export const generateMetadata = ({ params, searchParams }: Args): Promise => + generatePageMetadata({ config, params, searchParams }) + +const Page = ({ params, searchParams }: Args) => + RootPage({ config, importMap, params, searchParams }) + +export default Page diff --git a/test/app/(payload)/api/[...slug]/route.ts b/test/app/(payload)/api/[...slug]/route.ts new file mode 100644 index 00000000000..52caec96ad5 --- /dev/null +++ b/test/app/(payload)/api/[...slug]/route.ts @@ -0,0 +1,10 @@ +/* THIS FILE WAS GENERATED AUTOMATICALLY BY PAYLOAD. */ +/* DO NOT MODIFY it because it could be re-written at any time. */ +import config from '@payload-config' +import { REST_DELETE, REST_GET, REST_OPTIONS, REST_PATCH, REST_POST } from '@payloadcms/next/routes' + +export const GET = REST_GET(config) +export const POST = REST_POST(config) +export const DELETE = REST_DELETE(config) +export const PATCH = REST_PATCH(config) +export const OPTIONS = REST_OPTIONS(config) diff --git a/test/app/(payload)/api/graphql-playground/route.ts b/test/app/(payload)/api/graphql-playground/route.ts new file mode 100644 index 00000000000..7b7f279983f --- /dev/null +++ b/test/app/(payload)/api/graphql-playground/route.ts @@ -0,0 +1,6 @@ +/* THIS FILE WAS GENERATED AUTOMATICALLY BY PAYLOAD. */ +/* DO NOT MODIFY it because it could be re-written at any time. */ +import config from '@payload-config' +import { GRAPHQL_PLAYGROUND_GET } from '@payloadcms/next/routes' + +export const GET = GRAPHQL_PLAYGROUND_GET(config) diff --git a/test/app/(payload)/api/graphql/route.ts b/test/app/(payload)/api/graphql/route.ts new file mode 100644 index 00000000000..c2723e439fb --- /dev/null +++ b/test/app/(payload)/api/graphql/route.ts @@ -0,0 +1,6 @@ +/* THIS FILE WAS GENERATED AUTOMATICALLY BY PAYLOAD. */ +/* DO NOT MODIFY it because it could be re-written at any time. */ +import config from '@payload-config' +import { GRAPHQL_POST } from '@payloadcms/next/routes' + +export const POST = GRAPHQL_POST(config) diff --git a/test/app/(payload)/custom.scss b/test/app/(payload)/custom.scss new file mode 100644 index 00000000000..ddfc972f495 --- /dev/null +++ b/test/app/(payload)/custom.scss @@ -0,0 +1,8 @@ +#custom-css { + font-family: monospace; + background-image: url('/placeholder.png'); +} + +#custom-css::after { + content: 'custom-css'; +} diff --git a/test/app/(payload)/layout.tsx b/test/app/(payload)/layout.tsx new file mode 100644 index 00000000000..5767ca6c3c3 --- /dev/null +++ b/test/app/(payload)/layout.tsx @@ -0,0 +1,24 @@ +/* THIS FILE WAS GENERATED AUTOMATICALLY BY PAYLOAD. */ +import configPromise from '@payload-config' +import '@payloadcms/next/css' +import { RootLayout } from '@payloadcms/next/layouts' + +import { importMap } from './admin/importMap.js' + +// import '@payloadcms/ui/styles.css' // Uncomment this line if `@payloadcms/ui` in `tsconfig.json` points to `/ui/dist` instead of `/ui/src` +/* DO NOT MODIFY IT BECAUSE IT COULD BE REWRITTEN AT ANY TIME. */ +import React from 'react' + +import './custom.scss' + +type Args = { + children: React.ReactNode +} + +const Layout = ({ children }: Args) => ( + + {children} + +) + +export default Layout diff --git a/test/app/my-route/route.ts b/test/app/my-route/route.ts new file mode 100644 index 00000000000..6a705ad240b --- /dev/null +++ b/test/app/my-route/route.ts @@ -0,0 +1,5 @@ +export const GET = () => { + return Response.json({ + hello: 'elliot', + }) +} diff --git a/test/dev.ts b/test/dev.ts index 336b5dc5cd7..d00d440f01f 100644 --- a/test/dev.ts +++ b/test/dev.ts @@ -7,10 +7,16 @@ import { fileURLToPath } from 'node:url' import open from 'open' import { loadEnv } from 'payload/node' -import { getNextJSRootDir } from './helpers/getNextJSRootDir.js' +import { getNextRootDir } from './helpers/getNextRootDir.js' import { runInit } from './runInit.js' import { createTestHooks } from './testHooks.js' +const prod = process.argv.includes('--prod') +process.argv = process.argv.filter((arg) => arg !== '--prod') +if (prod) { + process.env.PAYLOAD_TEST_PROD = 'true' +} + loadEnv() const filename = fileURLToPath(import.meta.url) @@ -35,7 +41,7 @@ if (args.turbo === true) { const { beforeTest } = await createTestHooks(testSuiteArg) await beforeTest() -const { rootDir, adminRoute } = getNextJSRootDir(testSuiteArg) +const { rootDir, adminRoute } = getNextRootDir(testSuiteArg) await runInit(testSuiteArg, true) diff --git a/test/fields/int.spec.ts b/test/fields/int.spec.ts index 1ba82538764..a060f8db357 100644 --- a/test/fields/int.spec.ts +++ b/test/fields/int.spec.ts @@ -967,7 +967,7 @@ describe('Fields', () => { collection: tabsFieldsSlug, }) - await reload(payload.config, payload) + await reload(payload.config, payload, true) const testDoc2 = await payload.findByID({ id: document.id, diff --git a/test/getDatabaseAdapter.js b/test/getDatabaseAdapter.js new file mode 100644 index 00000000000..669bef5f137 --- /dev/null +++ b/test/getDatabaseAdapter.js @@ -0,0 +1,61 @@ +export const allDatabaseAdapters = { + mongodb: ` + import { mongooseAdapter } from '@payloadcms/db-mongodb' + + export const databaseAdapter = mongooseAdapter({ + url: + process.env.MONGODB_MEMORY_SERVER_URI || + process.env.DATABASE_URI || + 'mongodb://127.0.0.1/payloadtests', + collation: { + strength: 1, + }, + })`, + postgres: ` + import { postgresAdapter } from '@payloadcms/db-postgres' + + export const databaseAdapter = postgresAdapter({ + pool: { + connectionString: process.env.POSTGRES_URL || 'postgres://127.0.0.1:5432/payloadtests', + }, + })`, + 'postgres-custom-schema': ` + import { postgresAdapter } from '@payloadcms/db-postgres' + + export const databaseAdapter = postgresAdapter({ + pool: { + connectionString: process.env.POSTGRES_URL || 'postgres://127.0.0.1:5432/payloadtests', + }, + schemaName: 'custom', + })`, + 'postgres-uuid': ` + import { postgresAdapter } from '@payloadcms/db-postgres' + + export const databaseAdapter = postgresAdapter({ + idType: 'uuid', + pool: { + connectionString: process.env.POSTGRES_URL || 'postgres://127.0.0.1:5432/payloadtests', + }, + })`, + sqlite: ` + import { sqliteAdapter } from '@payloadcms/db-sqlite' + + export const databaseAdapter = sqliteAdapter({ + client: { + url: process.env.SQLITE_URL || 'file:./payloadtests.db', + }, + })`, + supabase: ` + import { postgresAdapter } from '@payloadcms/db-postgres' + + export const databaseAdapter = postgresAdapter({ + pool: { + connectionString: + process.env.POSTGRES_URL || 'postgresql://postgres:postgres@127.0.0.1:54322/postgres', + }, + })`, +} + +export function getDatabaseAdapter(dbAdapter) { + return allDatabaseAdapters[dbAdapter] +} diff --git a/test/helpers/getNextJSRootDir.js b/test/helpers/getNextJSRootDir.js deleted file mode 100644 index 8e3e8f287d3..00000000000 --- a/test/helpers/getNextJSRootDir.js +++ /dev/null @@ -1,41 +0,0 @@ -import fs from 'fs' -import { dirname, resolve } from 'path' -import { fileURLToPath } from 'url' - -import { adminRoute as rootAdminRoute } from '../admin-root/shared.js' - -const _filename = fileURLToPath(import.meta.url) -const _dirname = dirname(_filename) - -export const getNextJSRootDir = (testSuite) => { - const testSuiteDir = resolve(_dirname, `../${testSuite}`) - - let hasNextConfig = false - - try { - fs.accessSync(`${testSuiteDir}/next.config.mjs`, fs.constants.F_OK) - hasNextConfig = true - } catch (err) { - // Swallow err - no config found - } - - let adminRoute = '/admin' - - if (testSuite === 'admin-root') { - adminRoute = rootAdminRoute - } - - if (hasNextConfig) { - return { - rootDir: testSuiteDir, - adminRoute, - } - } - - // If no next config found in test suite, - // return monorepo root dir - return { - rootDir: resolve(_dirname, '../../'), - adminRoute, - } -} diff --git a/test/helpers/getNextRootDir.ts b/test/helpers/getNextRootDir.ts new file mode 100644 index 00000000000..81f1de753fa --- /dev/null +++ b/test/helpers/getNextRootDir.ts @@ -0,0 +1,57 @@ +import fs from 'fs' +import path, { resolve } from 'path' +import { fileURLToPath } from 'url' + +import { adminRoute as rootAdminRoute } from '../admin-root/shared.js' + +const filename = fileURLToPath(import.meta.url) +const dirname = path.dirname(filename) + +/** + * The root directory for e2e tests is either the monorepo root (normal e2e) or the test directory (test e2e). + */ +export function getNextRootDir(testSuite?: string) { + let adminRoute = '/admin' + + /* + * Handle test suites that have their own app directory + */ + if (testSuite) { + const testSuiteDir = resolve(dirname, `../${testSuite}`) + + let hasNextConfig = false + + try { + fs.accessSync(`${testSuiteDir}/next.config.mjs`, fs.constants.F_OK) + hasNextConfig = true + } catch (err) { + // Swallow err - no config found + } + + if (testSuite === 'admin-root') { + adminRoute = rootAdminRoute + } + + if (hasNextConfig) { + return { + rootDir: testSuiteDir, + adminRoute, + } + } + } + + /* + * Handle normal cases + */ + if (process.env.PAYLOAD_TEST_PROD === 'true') { + return { + rootDir: path.resolve(dirname, '..'), + adminRoute, + } + } + + return { + rootDir: path.resolve(dirname, '..', '..'), + adminRoute, + } +} diff --git a/test/helpers/initPayloadE2ENoConfig.ts b/test/helpers/initPayloadE2ENoConfig.ts index aa467e09b43..df1fa1a46f0 100644 --- a/test/helpers/initPayloadE2ENoConfig.ts +++ b/test/helpers/initPayloadE2ENoConfig.ts @@ -9,7 +9,7 @@ import type { GeneratedTypes } from './sdk/types.js' import { runInitSeparateProcess } from '../runInitSeparateProcess.js' import { createTestHooks } from '../testHooks.js' -import { getNextJSRootDir } from './getNextJSRootDir.js' +import { getNextRootDir } from './getNextRootDir.js' import { PayloadTestSDK } from './sdk/index.js' import startMemoryDB from './startMemoryDB.js' @@ -45,7 +45,7 @@ export async function initPayloadE2ENoConfig>({ await startMemoryDB() - const { rootDir } = getNextJSRootDir(testSuiteName) + const { rootDir } = getNextRootDir(testSuiteName) if (prebuild) { await new Promise((res, rej) => { diff --git a/test/helpers/initPayloadInt.ts b/test/helpers/initPayloadInt.ts index 87b8ca77ffa..9514a4691f9 100644 --- a/test/helpers/initPayloadInt.ts +++ b/test/helpers/initPayloadInt.ts @@ -1,7 +1,7 @@ import type { Payload, SanitizedConfig } from 'payload' +import { getPayloadHMR } from '@payloadcms/next/utilities' import path from 'path' -import { getPayload } from 'payload' import { runInit } from '../runInit.js' import { NextRESTClient } from './NextRESTClient.js' @@ -19,7 +19,9 @@ export async function initPayloadInt( const { default: config } = await import(path.resolve(dirname, 'config.ts')) console.log('starting payload') - const payload = await getPayload({ config }) + // need to use getPayloadHMR and not getPayload, as getPayloadHMR will be used in next handlers. If we use getPayload + // here, payload would be cached somewhere else + const payload = await getPayloadHMR({ config }) console.log('initializing rest client') const restClient = new NextRESTClient(payload.config) console.log('initPayloadInt done') diff --git a/test/initDevAndTest.ts b/test/initDevAndTest.ts index c6eff1105a3..d9304ecf265 100644 --- a/test/initDevAndTest.ts +++ b/test/initDevAndTest.ts @@ -3,100 +3,38 @@ import path from 'node:path' import { fileURLToPath } from 'node:url' import { type SanitizedConfig, generateImportMap } from 'payload' +import type { allDatabaseAdapters } from './getDatabaseAdapter.js' + +import { getDatabaseAdapter } from './getDatabaseAdapter.js' +import { getNextRootDir } from './helpers/getNextRootDir.js' + const filename = fileURLToPath(import.meta.url) const dirname = path.dirname(filename) const runImmediately = process.argv[2] -const databaseAdapters = { - mongodb: ` - import { mongooseAdapter } from '@payloadcms/db-mongodb' - - export const databaseAdapter = mongooseAdapter({ - url: - process.env.MONGODB_MEMORY_SERVER_URI || - process.env.DATABASE_URI || - 'mongodb://127.0.0.1/payloadtests', - collation: { - strength: 1, - }, - })`, - postgres: ` - import { postgresAdapter } from '@payloadcms/db-postgres' - - export const databaseAdapter = postgresAdapter({ - pool: { - connectionString: process.env.POSTGRES_URL || 'postgres://127.0.0.1:5432/payloadtests', - }, - })`, - 'postgres-custom-schema': ` - import { postgresAdapter } from '@payloadcms/db-postgres' - - export const databaseAdapter = postgresAdapter({ - pool: { - connectionString: process.env.POSTGRES_URL || 'postgres://127.0.0.1:5432/payloadtests', - }, - schemaName: 'custom', - })`, - 'postgres-uuid': ` - import { postgresAdapter } from '@payloadcms/db-postgres' - - export const databaseAdapter = postgresAdapter({ - idType: 'uuid', - pool: { - connectionString: process.env.POSTGRES_URL || 'postgres://127.0.0.1:5432/payloadtests', - }, - })`, - sqlite: ` - import { sqliteAdapter } from '@payloadcms/db-sqlite' - - export const databaseAdapter = sqliteAdapter({ - client: { - url: process.env.SQLITE_URL || 'file:./payloadtests.db', - }, - })`, - supabase: ` - import { postgresAdapter } from '@payloadcms/db-postgres' - - export const databaseAdapter = postgresAdapter({ - pool: { - connectionString: - process.env.POSTGRES_URL || 'postgresql://postgres:postgres@127.0.0.1:54322/postgres', - }, - })`, -} - export async function initDevAndTest( testSuiteArg: string, writeDBAdapter: string, skipGenImportMap: string, ): Promise { - let appPath: string - - switch (testSuiteArg) { - case 'live-preview': - appPath = './live-preview/app/(payload)/admin/importMap.js' - break - case 'admin-root': - appPath = './admin-root/app/(payload)/admin/importMap.js' - break - default: - appPath = '../app/(payload)/admin/importMap.js' - break - } + const importMapPath: string = path.resolve( + getNextRootDir(testSuiteArg).rootDir, + './app/(payload)/admin/importMap.js', + ) try { - fs.writeFileSync(path.resolve(dirname, appPath), 'export const importMap = {}') + fs.writeFileSync(importMapPath, 'export const importMap = {}') } catch (error) { console.log('Error writing importMap.js', error) } if (writeDBAdapter === 'true') { - const dbAdapter: keyof typeof databaseAdapters = - (process.env.PAYLOAD_DATABASE as keyof typeof databaseAdapters) || 'mongodb' + const dbAdapter: keyof typeof allDatabaseAdapters = + (process.env.PAYLOAD_DATABASE as keyof typeof allDatabaseAdapters) || 'mongodb' // Generate databaseAdapter.ts - const databaseAdapter = databaseAdapters[dbAdapter] + const databaseAdapter = getDatabaseAdapter(dbAdapter) // Write to databaseAdapter.ts fs.writeFileSync( @@ -124,10 +62,7 @@ export async function initDevAndTest( const config: SanitizedConfig = await (await import(pathWithConfig)).default - process.env.ROOT_DIR = - testSuiteArg === 'live-preview' || testSuiteArg === 'admin-root' - ? testDir - : path.resolve(dirname, '..') + process.env.ROOT_DIR = getNextRootDir(testSuiteArg).rootDir await generateImportMap(config, { log: true, force: true }) diff --git a/test/jest.setup.js b/test/jest.setup.js index 6b4cf21c2c8..eceb320a89a 100644 --- a/test/jest.setup.js +++ b/test/jest.setup.js @@ -1,6 +1,7 @@ import fs from 'fs' import path from 'node:path' import { fileURLToPath } from 'node:url' +import { getDatabaseAdapter } from './getDatabaseAdapter.js' process.env.PAYLOAD_DISABLE_ADMIN = 'true' process.env.PAYLOAD_DROP_DATABASE = 'true' @@ -10,70 +11,13 @@ process.env.PAYLOAD_PUBLIC_CLOUD_STORAGE_ADAPTER = 's3' process.env.NODE_OPTIONS = '--no-deprecation' process.env.PAYLOAD_DISABLE_DEPENDENCY_CHECKER = 'true' -const databaseAdapters = { - mongodb: ` - import { mongooseAdapter } from '@payloadcms/db-mongodb' - - export const databaseAdapter = mongooseAdapter({ - url: - process.env.MONGODB_MEMORY_SERVER_URI || - process.env.DATABASE_URI || - 'mongodb://127.0.0.1/payloadtests', - collation: { - strength: 1, - }, - })`, - postgres: ` - import { postgresAdapter } from '@payloadcms/db-postgres' - - export const databaseAdapter = postgresAdapter({ - pool: { - connectionString: process.env.POSTGRES_URL || 'postgres://127.0.0.1:5432/payloadtests', - }, - })`, - 'postgres-custom-schema': ` - import { postgresAdapter } from '@payloadcms/db-postgres' - - export const databaseAdapter = postgresAdapter({ - pool: { - connectionString: process.env.POSTGRES_URL || 'postgres://127.0.0.1:5432/payloadtests', - }, - schemaName: 'custom', - })`, - 'postgres-uuid': ` - import { postgresAdapter } from '@payloadcms/db-postgres' - - export const databaseAdapter = postgresAdapter({ - idType: 'uuid', - pool: { - connectionString: process.env.POSTGRES_URL || 'postgres://127.0.0.1:5432/payloadtests', - }, - })`, - sqlite: ` - import { sqliteAdapter } from '@payloadcms/db-sqlite' - - export const databaseAdapter = sqliteAdapter({ - client: { - url: process.env.SQLITE_URL || 'file:./payloadtests.db', - }, - })`, - supabase: ` - import { postgresAdapter } from '@payloadcms/db-postgres' - - export const databaseAdapter = postgresAdapter({ - pool: { - connectionString: - process.env.POSTGRES_URL || 'postgresql://postgres:postgres@127.0.0.1:54322/postgres', - }, - })`, -} const filename = fileURLToPath(import.meta.url) const dirname = path.dirname(filename) const dbAdapter = process.env.PAYLOAD_DATABASE || 'mongodb' // Generate databaseAdapter.ts -const databaseAdapter = databaseAdapters[dbAdapter] +const databaseAdapter = getDatabaseAdapter(dbAdapter) // Write to databaseAdapter.ts fs.writeFileSync( diff --git a/test/next.config.mjs b/test/next.config.mjs new file mode 100644 index 00000000000..0ce7911fc9e --- /dev/null +++ b/test/next.config.mjs @@ -0,0 +1,49 @@ +import bundleAnalyzer from '@next/bundle-analyzer' + +import { withPayload } from '@payloadcms/next/withPayload' +import path from 'path' +import { fileURLToPath } from 'url' + +const __filename = fileURLToPath(import.meta.url) +const dirname = path.dirname(__filename) + +const withBundleAnalyzer = bundleAnalyzer({ + enabled: process.env.ANALYZE === 'true', +}) + +// eslint-disable-next-line no-restricted-exports +export default withBundleAnalyzer( + withPayload({ + eslint: { + ignoreDuringBuilds: true, + }, + typescript: { + ignoreBuildErrors: true, + }, + env: { + PAYLOAD_CORE_DEV: 'true', + ROOT_DIR: path.resolve(dirname), + }, + async redirects() { + return [ + { + destination: '/admin', + permanent: true, + source: '/', + }, + ] + }, + images: { + domains: ['localhost'], + }, + webpack: (webpackConfig) => { + webpackConfig.resolve.extensionAlias = { + '.cjs': ['.cts', '.cjs'], + '.js': ['.ts', '.tsx', '.js', '.jsx'], + '.mjs': ['.mts', '.mjs'], + } + + return webpackConfig + }, + }), +) diff --git a/test/package.json b/test/package.json index 643793b4404..e7abdd479d4 100644 --- a/test/package.json +++ b/test/package.json @@ -59,21 +59,24 @@ "@sentry/react": "^7.77.0", "@types/react": "npm:types-react@19.0.0-rc.0", "@types/react-dom": "npm:types-react-dom@19.0.0-rc.0", - "babel-plugin-react-compiler": "0.0.0-experimental-592953e-20240517", + "babel-plugin-react-compiler": "0.0.0-experimental-1cd8995-20240814", "comment-json": "^4.2.3", "create-payload-app": "workspace:*", "dotenv": "16.4.5", + "drizzle-kit": "0.23.2-df9e596", "eslint-plugin-playwright": "1.6.2", "execa": "5.1.1", "file-type": "17.1.6", "http-status": "1.6.2", "jwt-decode": "4.0.0", "lexical": "0.17.0", + "next": "15.0.0-canary.104", "payload": "workspace:*", "qs-esm": "7.0.2", + "react": "19.0.0-rc-06d0b89e-20240801", + "react-dom": "19.0.0-rc-06d0b89e-20240801", "server-only": "^0.0.1", "slate": "0.91.4", - "drizzle-kit": "0.23.2-df9e596", "tempy": "^1.0.1", "ts-essentials": "7.0.3", "typescript": "5.5.4", diff --git a/test/runE2E.ts b/test/runE2E.ts index 571d84a5d42..9bd32a8302c 100644 --- a/test/runE2E.ts +++ b/test/runE2E.ts @@ -10,6 +10,13 @@ const dirname = path.dirname(__filename) shelljs.env.DISABLE_LOGGING = 'true' +const prod = process.argv.includes('--prod') +process.argv = process.argv.filter((arg) => arg !== '--prod') +if (prod) { + process.env.PAYLOAD_TEST_PROD = 'true' + shelljs.env.PAYLOAD_TEST_PROD = 'true' +} + const playwrightBin = path.resolve(dirname, '../node_modules/.bin/playwright') const testRunCodes: { code: number; suiteName: string }[] = [] diff --git a/test/setupProd.ts b/test/setupProd.ts new file mode 100644 index 00000000000..65ba4997e45 --- /dev/null +++ b/test/setupProd.ts @@ -0,0 +1,91 @@ +import fs from 'fs' +import path from 'node:path' +import { fileURLToPath } from 'node:url' + +const filename = fileURLToPath(import.meta.url) +const dirname = path.dirname(filename) + +export const tgzToPkgNameMap = { + payload: 'payload-*', + '@payloadcms/db-mongodb': 'payloadcms-db-mongodb-*', + '@payloadcms/db-postgres': 'payloadcms-db-postgres-*', + '@payloadcms/db-sqlite': 'payloadcms-db-sqlite-*', + '@payloadcms/drizzle': 'payloadcms-drizzle-*', + '@payloadcms/email-nodemailer': 'payloadcms-email-nodemailer-*', + '@payloadcms/email-resend': 'payloadcms-email-resend-*', + '@payloadcms/eslint-config': 'payloadcms-eslint-config-*', + '@payloadcms/eslint-plugin': 'payloadcms-eslint-plugin-*', + '@payloadcms/graphql': 'payloadcms-graphql-*', + '@payloadcms/live-preview': 'payloadcms-live-preview-*', + '@payloadcms/live-preview-react': 'payloadcms-live-preview-react-*', + '@payloadcms/next': 'payloadcms-next-*', + '@payloadcms/plugin-cloud': 'payloadcms-plugin-cloud-*', + '@payloadcms/plugin-cloud-storage': 'payloadcms-plugin-cloud-storage-*', + '@payloadcms/plugin-form-builder': 'payloadcms-plugin-form-builder-*', + '@payloadcms/plugin-nested-docs': 'payloadcms-plugin-nested-docs-*', + '@payloadcms/plugin-redirects': 'payloadcms-plugin-redirects-*', + '@payloadcms/plugin-relationship-object-ids': 'payloadcms-plugin-relationship-object-ids-*', + '@payloadcms/plugin-search': 'payloadcms-plugin-search-*', + '@payloadcms/plugin-sentry': 'payloadcms-plugin-sentry-*', + '@payloadcms/plugin-seo': 'payloadcms-plugin-seo-*', + '@payloadcms/plugin-stripe': 'payloadcms-plugin-stripe-*', + '@payloadcms/richtext-lexical': 'payloadcms-richtext-lexical-*', + '@payloadcms/richtext-slate': 'payloadcms-richtext-slate-*', + '@payloadcms/storage-azure': 'payloadcms-storage-azure-*', + '@payloadcms/storage-gcs': 'payloadcms-storage-gcs-*', + '@payloadcms/storage-s3': 'payloadcms-storage-s3-*', + '@payloadcms/storage-uploadthing': 'payloadcms-storage-uploadthing-*', + '@payloadcms/storage-vercel-blob': 'payloadcms-storage-vercel-blob-*', + '@payloadcms/translations': 'payloadcms-translations-*', + '@payloadcms/ui': 'payloadcms-ui-*', + 'create-payload-app': 'create-payload-app-*', +} + +function findActualTgzName(pattern: string) { + const packedDir = path.resolve(dirname, 'packed') + const files = fs.readdirSync(packedDir) + const matchingFile = files.find((file) => file.startsWith(pattern.replace('*', ''))) + return matchingFile ? `file:packed/${matchingFile}` : null +} + +/** + * This does the following: + * - installs all packages from test/packed to test/package.json + */ +export function setupProd() { + const packageJsonString = fs.readFileSync(path.resolve(dirname, 'package.json'), 'utf8') + const packageJson = JSON.parse(packageJsonString) + + const allDependencies = {} + // Go through all the dependencies and devDependencies, replace the normal package entry with the tgz entry + for (const key of ['dependencies', 'devDependencies']) { + const dependencies = packageJson[key] + if (dependencies) { + for (const [packageName, _packageVersion] of Object.entries(dependencies)) { + if (tgzToPkgNameMap[packageName]) { + const actualTgzPath = findActualTgzName(tgzToPkgNameMap[packageName]) + if (actualTgzPath) { + dependencies[packageName] = actualTgzPath + allDependencies[packageName] = actualTgzPath + } else { + console.warn(`Warning: No matching tgz found for ${packageName}`) + } + } + } + } + } + + // now add them all to overrides and pnpm.overrides as well + packageJson.pnpm = packageJson.pnpm || {} + packageJson.pnpm.overrides = packageJson.pnpm.overrides || {} + packageJson.overrides = packageJson.overrides || {} + for (const [packageName, packageVersion] of Object.entries(allDependencies)) { + packageJson.pnpm.overrides[packageName] = packageVersion + packageJson.overrides[packageName] = packageVersion + } + + // write it out + fs.writeFileSync(path.resolve(dirname, 'package.json'), JSON.stringify(packageJson, null, 2)) +} + +setupProd() diff --git a/test/testHooks.js b/test/testHooks.ts similarity index 69% rename from test/testHooks.js rename to test/testHooks.ts index 18c450f8d5a..4a99f9b3b34 100644 --- a/test/testHooks.js +++ b/test/testHooks.ts @@ -1,17 +1,16 @@ -// @ts-check - -import { existsSync, promises } from 'fs' import { parse, stringify } from 'comment-json' - +import { existsSync, promises } from 'fs' import path from 'path' import { fileURLToPath } from 'url' +import { getNextRootDir } from './helpers/getNextRootDir.js' + const { readFile, writeFile, rm } = promises const filename = fileURLToPath(import.meta.url) const dirname = path.dirname(filename) export const createTestHooks = async (testSuiteName = '_community') => { - const tsConfigPath = path.resolve(dirname, '../tsconfig.json') + const tsConfigPath = path.resolve(getNextRootDir().rootDir, './tsconfig.json') const tsConfigContent = await readFile(tsConfigPath, 'utf8') const tsConfig = parse(tsConfigContent) @@ -21,7 +20,7 @@ export const createTestHooks = async (testSuiteName = '_community') => { */ beforeTest: async () => { // Delete entire .next cache folder - const nextCache = path.resolve(dirname, '../.next') + const nextCache = path.resolve(getNextRootDir().rootDir, './.next') if (existsSync(nextCache)) { await rm(nextCache, { recursive: true }) } @@ -29,7 +28,11 @@ export const createTestHooks = async (testSuiteName = '_community') => { // Set '@payload-config' in tsconfig.json // @ts-expect-error - tsConfig.compilerOptions.paths['@payload-config'] = [`./test/${testSuiteName}/config.ts`] + tsConfig.compilerOptions.paths['@payload-config'] = [ + process.env.PAYLOAD_TEST_PROD === 'true' + ? `./${testSuiteName}/config.ts` + : `./test/${testSuiteName}/config.ts`, + ] await writeFile(tsConfigPath, stringify(tsConfig, null, 2) + '\n') process.env.PAYLOAD_CONFIG_PATH = path.resolve(dirname, testSuiteName, 'config.ts') diff --git a/test/tsconfig.json b/test/tsconfig.json index 521767276ee..8f337ab7671 100644 --- a/test/tsconfig.json +++ b/test/tsconfig.json @@ -27,30 +27,7 @@ ], "baseUrl": ".", "paths": { - "@payloadcms/ui": ["../packages/ui/src/exports/client/index.ts"], - "@payloadcms/ui/shared": ["../packages/ui/src/exports/shared/index.ts"], - "@payloadcms/ui/scss": ["../packages/ui/src/scss.scss"], - "@payloadcms/ui/scss/app.scss": ["../packages/ui/src/scss/app.scss"], - "@payloadcms/next/*": ["./packages/next/src/exports/*.ts"], - "@payloadcms/richtext-lexical/client": [ - "./packages/richtext-lexical/src/exports/client/index.ts" - ], - "@payloadcms/richtext-lexical/generateComponentMap": [ - "./packages/richtext-lexical/src/utilities/generateComponentMap.tsx" - ], - "@payloadcms/richtext-slate/client": [ - "./packages/richtext-slate/src/exports/client/index.ts" - ], - "@payloadcms/richtext-slate/generateComponentMap": [ - "./packages/richtext-slate/src/generateComponentMap.tsx" - ], - "@payload-config": ["./_community/config.ts", "./versions/config.ts"], - "@payloadcms/plugin-seo/client": ["./packages/plugin-seo/src/exports/client.ts"], - "@payloadcms/plugin-stripe/client": ["./packages/plugin-stripe/src/exports/client.ts"], - "@payloadcms/plugin-search/client": ["./packages/plugin-search/src/exports/client.ts"], - "@payloadcms/plugin-form-builder/client": [ - "./packages/plugin-form-builder/src/exports/client.ts" - ] + "@payload-config": ["./_community/config.ts"] } }, "exclude": [ diff --git a/tsconfig.json b/tsconfig.json index fdef1fc52cc..ae27597fb03 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -37,7 +37,7 @@ ], "paths": { "@payload-config": [ - "./test/admin/config.ts" + "./test/_community/config.ts" ], "@payloadcms/live-preview": [ "./packages/live-preview/src"