feat: match next.js env file loading behavior in bin scripts & importConfig, clean up installed packages & mismatching package versions (#6601)

This commit is contained in:
Alessio Gravili
2024-06-03 17:23:05 -04:00
committed by GitHub
parent 1aece399f7
commit 59cde0dbb3
33 changed files with 503 additions and 939 deletions

View File

@@ -1,15 +0,0 @@
{
"$schema": "https://json.schemastore.org/nodemon.json",
"exec": "ts-node ./test/dev.ts -- -I",
"ext": "ts,js,json",
"ignore": [
".git",
"node_modules",
"node_modules/**/node_modules",
"packages/payload/src/admin",
"packages/payload/src/**/*.spec.ts",
"test/**/payload-types.ts"
],
"watch": ["./test/", "./packages/**/*.ts"],
"stdin": false
}

View File

@@ -65,13 +65,13 @@
"script:pack": "tsx scripts/pack-all-to-dest.ts", "script:pack": "tsx scripts/pack-all-to-dest.ts",
"pretest": "pnpm build", "pretest": "pnpm build",
"test": "pnpm test:int && pnpm test:components && pnpm test:e2e", "test": "pnpm test:int && pnpm test:components && pnpm test:e2e",
"test:components": "cross-env NODE_OPTIONS=--no-deprecation jest --config=jest.components.config.js", "test:components": "cross-env NODE_OPTIONS=\"--experimental-vm-modules --no-deprecation\" jest --config=jest.components.config.js",
"test:e2e": "cross-env NODE_OPTIONS=--no-deprecation NODE_NO_WARNINGS=1 tsx ./test/runE2E.ts", "test:e2e": "cross-env NODE_OPTIONS=--no-deprecation NODE_NO_WARNINGS=1 tsx ./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: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:headed": "cross-env NODE_OPTIONS=--no-deprecation NODE_NO_WARNINGS=1 DISABLE_LOGGING=true playwright test --headed",
"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": "cross-env NODE_OPTIONS=\"--experimental-vm-modules --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:int:postgres": "cross-env NODE_OPTIONS=\"--experimental-vm-modules --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", "test:unit": "cross-env NODE_OPTIONS=\"--experimental-vm-modules --no-deprecation\" NODE_NO_WARNINGS=1 DISABLE_LOGGING=true jest --forceExit --detectOpenHandles --config=jest.config.js --runInBand",
"translateNewKeys": "pnpm --filter payload run translateNewKeys" "translateNewKeys": "pnpm --filter payload run translateNewKeys"
}, },
"lint-staged": { "lint-staged": {
@@ -84,18 +84,15 @@
"tsconfig.json": "node scripts/reset-tsconfig.js" "tsconfig.json": "node scripts/reset-tsconfig.js"
}, },
"devDependencies": { "devDependencies": {
"@aws-sdk/client-s3": "^3.525.0", "@jest/globals": "29.7.0",
"@next/bundle-analyzer": "^14.1.0", "@next/bundle-analyzer": "^14.1.0",
"@octokit/core": "^5.1.0",
"@payloadcms/eslint-config": "workspace:*", "@payloadcms/eslint-config": "workspace:*",
"@payloadcms/live-preview-react": "workspace:*", "@payloadcms/live-preview-react": "workspace:*",
"@playwright/test": "1.43.0", "@playwright/test": "1.43.0",
"@sentry/react": "^7.77.0",
"@swc/cli": "^0.1.62", "@swc/cli": "^0.1.62",
"@swc/jest": "0.2.36", "@swc/jest": "0.2.36",
"@testing-library/jest-dom": "6.4.2", "@testing-library/jest-dom": "6.4.2",
"@testing-library/react": "14.2.1", "@testing-library/react": "14.2.1",
"@types/concat-stream": "^2.0.1",
"@types/fs-extra": "^11.0.2", "@types/fs-extra": "^11.0.2",
"@types/jest": "29.5.12", "@types/jest": "29.5.12",
"@types/minimist": "1.2.5", "@types/minimist": "1.2.5",
@@ -106,14 +103,12 @@
"@types/react-dom": "npm:types-react-dom@19.0.0-beta.2", "@types/react-dom": "npm:types-react-dom@19.0.0-beta.2",
"@types/semver": "^7.5.3", "@types/semver": "^7.5.3",
"@types/shelljs": "0.8.15", "@types/shelljs": "0.8.15",
"add-stream": "^1.0.0",
"chalk": "^4.1.2", "chalk": "^4.1.2",
"changelogen": "^0.5.5", "changelogen": "^0.5.5",
"comment-json": "^4.2.3", "comment-json": "^4.2.3",
"concat-stream": "^2.0.0",
"copyfiles": "2.4.1", "copyfiles": "2.4.1",
"cross-env": "7.0.3", "cross-env": "7.0.3",
"dotenv": "8.6.0", "dotenv": "16.4.5",
"drizzle-kit": "0.20.14-1f2c838", "drizzle-kit": "0.20.14-1f2c838",
"drizzle-orm": "0.29.4", "drizzle-orm": "0.29.4",
"escape-html": "^1.0.3", "escape-html": "^1.0.3",
@@ -121,20 +116,15 @@
"execa": "5.1.1", "execa": "5.1.1",
"form-data": "3.0.1", "form-data": "3.0.1",
"fs-extra": "10.1.0", "fs-extra": "10.1.0",
"get-port": "5.1.1",
"get-stream": "6.0.1",
"glob": "8.1.0", "glob": "8.1.0",
"globby": "11.1.0", "globby": "11.1.0",
"husky": "^8.0.3", "husky": "^8.0.3",
"jest": "29.7.0", "jest": "29.7.0",
"jest-environment-jsdom": "29.7.0", "jest-environment-jsdom": "29.7.0",
"jwt-decode": "4.0.0",
"lint-staged": "^14.0.1", "lint-staged": "^14.0.1",
"minimist": "1.2.8", "minimist": "1.2.8",
"mongodb-memory-server": "^9.0", "mongodb-memory-server": "^9.0",
"next": "15.0.0-rc.0", "next": "15.0.0-rc.0",
"node-mocks-http": "^1.14.1",
"nodemon": "3.0.3",
"open": "^10.1.0", "open": "^10.1.0",
"p-limit": "^5.0.0", "p-limit": "^5.0.0",
"pino": "8.15.0", "pino": "8.15.0",
@@ -146,14 +136,11 @@
"qs": "6.11.2", "qs": "6.11.2",
"react": "^19.0.0-rc-f994737d14-20240522", "react": "^19.0.0-rc-f994737d14-20240522",
"react-dom": "^19.0.0-rc-f994737d14-20240522", "react-dom": "^19.0.0-rc-f994737d14-20240522",
"read-stream": "^2.1.1",
"rimraf": "3.0.2", "rimraf": "3.0.2",
"semver": "^7.5.4", "semver": "^7.5.4",
"sharp": "0.32.6", "sharp": "0.32.6",
"shelljs": "0.8.5", "shelljs": "0.8.5",
"simple-git": "^3.24.0",
"slash": "3.0.0", "slash": "3.0.0",
"slate": "0.91.4",
"sort-package-json": "^2.10.0", "sort-package-json": "^2.10.0",
"swc-plugin-transform-remove-imports": "^1.12.1", "swc-plugin-transform-remove-imports": "^1.12.1",
"tempfile": "^3.0.0", "tempfile": "^3.0.0",
@@ -162,8 +149,7 @@
"tsx": "^4.7.1", "tsx": "^4.7.1",
"turbo": "^1.13.3", "turbo": "^1.13.3",
"typescript": "5.4.5", "typescript": "5.4.5",
"uuid": "^9.0.1", "uuid": "^9.0.1"
"yocto-queue": "^1.0.0"
}, },
"peerDependencies": { "peerDependencies": {
"react": "^19.0.0 || ^19.0.0-rc-f994737d14-20240522", "react": "^19.0.0 || ^19.0.0-rc-f994737d14-20240522",

View File

@@ -51,7 +51,7 @@
"@types/degit": "^2.8.3", "@types/degit": "^2.8.3",
"@types/esprima": "^4.0.6", "@types/esprima": "^4.0.6",
"@types/fs-extra": "^9.0.12", "@types/fs-extra": "^9.0.12",
"@types/jest": "^27.0.3", "@types/jest": "29.5.12",
"@types/node": "20.12.5", "@types/node": "20.12.5",
"temp-dir": "2.0.0" "temp-dir": "2.0.0"
} }

View File

@@ -5,6 +5,7 @@ import { createProject } from './create-project.js'
import { dbReplacements } from './packages.js' import { dbReplacements } from './packages.js'
import { getValidTemplates } from './templates.js' import { getValidTemplates } from './templates.js'
import globby from 'globby' import globby from 'globby'
import { jest } from '@jest/globals'
import tempDirectory from 'temp-dir' import tempDirectory from 'temp-dir'

View File

@@ -1,5 +1,6 @@
import { parseAndModifyConfigContent, withPayloadStatement } from './wrap-next-config.js' import { parseAndModifyConfigContent, withPayloadStatement } from './wrap-next-config.js'
import * as p from '@clack/prompts' import * as p from '@clack/prompts'
import { jest } from '@jest/globals'
const esmConfigs = { const esmConfigs = {
defaultNextConfig: `/** @type {import('next').NextConfig} */ defaultNextConfig: `/** @type {import('next').NextConfig} */

View File

@@ -35,12 +35,11 @@
"dependencies": { "dependencies": {
"bson-objectid": "2.0.4", "bson-objectid": "2.0.4",
"deepmerge": "4.3.1", "deepmerge": "4.3.1",
"get-port": "5.1.1",
"http-status": "1.6.2", "http-status": "1.6.2",
"mongoose": "6.12.3", "mongoose": "6.12.3",
"mongoose-paginate-v2": "1.7.22", "mongoose-paginate-v2": "1.7.22",
"prompts": "2.4.2", "prompts": "2.4.2",
"uuid": "9.0.0" "uuid": "^9.0.1"
}, },
"devDependencies": { "devDependencies": {
"@payloadcms/eslint-config": "workspace:*", "@payloadcms/eslint-config": "workspace:*",

View File

@@ -50,7 +50,7 @@
"pg": "8.11.3", "pg": "8.11.3",
"prompts": "2.4.2", "prompts": "2.4.2",
"to-snake-case": "1.0.0", "to-snake-case": "1.0.0",
"uuid": "9.0.0" "uuid": "^9.0.1"
}, },
"devDependencies": { "devDependencies": {
"@payloadcms/eslint-config": "workspace:*", "@payloadcms/eslint-config": "workspace:*",

View File

@@ -1,5 +1,6 @@
import { resendAdapter } from './index.js' import { resendAdapter } from './index.js'
import { Payload } from 'payload/types' import { Payload } from 'payload/types'
import { jest } from '@jest/globals'
describe('email-resend', () => { describe('email-resend', () => {
const defaultFromAddress = 'dev@payloadcms.com' const defaultFromAddress = 'dev@payloadcms.com'

View File

@@ -46,9 +46,7 @@
"@payloadcms/graphql": "workspace:*", "@payloadcms/graphql": "workspace:*",
"@payloadcms/translations": "workspace:*", "@payloadcms/translations": "workspace:*",
"@payloadcms/ui": "workspace:*", "@payloadcms/ui": "workspace:*",
"@types/busboy": "^1.5.3",
"busboy": "^1.6.0", "busboy": "^1.6.0",
"deep-equal": "2.2.2",
"file-type": "19.0.0 || 19.0.0-rc-f994737d14-20240522", "file-type": "19.0.0 || 19.0.0-rc-f994737d14-20240522",
"graphql-http": "^1.22.0", "graphql-http": "^1.22.0",
"graphql-playground-html": "1.6.30", "graphql-playground-html": "1.6.30",
@@ -57,12 +55,13 @@
"qs": "6.11.2", "qs": "6.11.2",
"react-diff-viewer-continued": "3.2.6", "react-diff-viewer-continued": "3.2.6",
"react-toastify": "10.0.5", "react-toastify": "10.0.5",
"sass": "^1.71.1", "sass": "1.77.4",
"ws": "^8.16.0" "ws": "^8.16.0"
}, },
"devDependencies": { "devDependencies": {
"@next/eslint-plugin-next": "^14.1.0", "@next/eslint-plugin-next": "^14.1.0",
"@payloadcms/eslint-config": "workspace:*", "@payloadcms/eslint-config": "workspace:*",
"@types/busboy": "^1.5.3",
"@types/react": "npm:types-react@19.0.0-beta.2", "@types/react": "npm:types-react@19.0.0-beta.2",
"@types/react-dom": "npm:types-react-dom@19.0.0-beta.2", "@types/react-dom": "npm:types-react-dom@19.0.0-beta.2",
"@types/ws": "^8.5.10", "@types/ws": "^8.5.10",
@@ -71,8 +70,8 @@
"mini-css-extract-plugin": "1.6.2", "mini-css-extract-plugin": "1.6.2",
"payload": "workspace:*", "payload": "workspace:*",
"postcss-loader": "^8.1.1", "postcss-loader": "^8.1.1",
"postcss-preset-env": "^9.5.0", "postcss-preset-env": "^9.5.14",
"sass-loader": "^14.1.1", "sass-loader": "14.2.1",
"swc-loader": "^0.2.6", "swc-loader": "^0.2.6",
"swc-plugin-transform-remove-imports": "^1.12.1", "swc-plugin-transform-remove-imports": "^1.12.1",
"terser-webpack-plugin": "^5.3.10", "terser-webpack-plugin": "^5.3.10",

View File

@@ -1,3 +1,4 @@
import type { Locale } from 'payload/config'
import type { import type {
Data, Data,
PayloadRequestWithData, PayloadRequestWithData,

View File

@@ -69,22 +69,19 @@
"build": "pnpm copyfiles && pnpm build:swc && pnpm build:types", "build": "pnpm copyfiles && pnpm build:swc && pnpm build:types",
"build:swc": "swc ./src -d ./dist --config-file .swcrc", "build:swc": "swc ./src -d ./dist --config-file .swcrc",
"build:types": "tsc --emitDeclarationOnly --outDir dist", "build:types": "tsc --emitDeclarationOnly --outDir dist",
"build:watch": "nodemon --watch 'src/**' --ext 'ts,tsx' --exec \"pnpm build:tsc\"",
"clean": "rimraf {dist,*.tsbuildinfo}", "clean": "rimraf {dist,*.tsbuildinfo}",
"clean:cache": "rimraf node_modules/.cache", "clean:cache": "rimraf node_modules/.cache",
"copyfiles": "copyfiles -u 1 \"src/**/*.{html,ttf,woff,woff2,eot,svg,jpg,png,json}\" dist/", "copyfiles": "copyfiles -u 1 \"src/**/*.{html,ttf,woff,woff2,eot,svg,jpg,png,json}\" dist/",
"dev": "nodemon",
"dev:postgres": "cross-env PAYLOAD_DATABASE=postgres nodemon",
"fix": "eslint \"src/**/*.ts\" --fix", "fix": "eslint \"src/**/*.ts\" --fix",
"lint": "eslint \"src/**/*.ts\"", "lint": "eslint \"src/**/*.ts\"",
"prepublishOnly": "pnpm clean && pnpm turbo build", "prepublishOnly": "pnpm clean && pnpm turbo build",
"pretest": "pnpm build" "pretest": "pnpm build"
}, },
"dependencies": { "dependencies": {
"@next/env": "^15.0.0-rc.0",
"@payloadcms/translations": "workspace:*", "@payloadcms/translations": "workspace:*",
"@swc-node/core": "^1.13.0", "@swc-node/core": "^1.13.0",
"@swc-node/sourcemap-support": "^0.5.0", "@swc-node/sourcemap-support": "^0.5.0",
"@types/probe-image-size": "^7.2.4",
"ajv": "^8.12.0", "ajv": "^8.12.0",
"bson-objectid": "2.0.4", "bson-objectid": "2.0.4",
"ci-info": "^4.0.0", "ci-info": "^4.0.0",
@@ -92,9 +89,8 @@
"console-table-printer": "2.11.2", "console-table-printer": "2.11.2",
"dataloader": "2.2.2", "dataloader": "2.2.2",
"deepmerge": "4.3.1", "deepmerge": "4.3.1",
"dotenv": "8.6.0",
"file-type": "16.5.4", "file-type": "16.5.4",
"find-up": "4.1.0", "find-up": "7.0.0",
"get-tsconfig": "^4.7.2", "get-tsconfig": "^4.7.2",
"http-status": "1.6.2", "http-status": "1.6.2",
"image-size": "^1.1.1", "image-size": "^1.1.1",
@@ -115,41 +111,19 @@
"devDependencies": { "devDependencies": {
"@monaco-editor/react": "4.5.1", "@monaco-editor/react": "4.5.1",
"@payloadcms/eslint-config": "workspace:*", "@payloadcms/eslint-config": "workspace:*",
"@types/asap": "2.0.0",
"@types/body-parser": "1.19.2",
"@types/compression": "1.7.2",
"@types/express-fileupload": "1.4.1", "@types/express-fileupload": "1.4.1",
"@types/express-rate-limit": "5.1.3",
"@types/express-serve-static-core": "4.17.35",
"@types/hapi__joi": "17.1.9",
"@types/ignore-styles": "5.0.0",
"@types/joi": "14.3.4", "@types/joi": "14.3.4",
"@types/json-schema": "7.0.12", "@types/json-schema": "7.0.12",
"@types/jsonwebtoken": "8.5.9", "@types/jsonwebtoken": "8.5.9",
"@types/method-override": "0.0.32",
"@types/mime": "2.0.3",
"@types/minimist": "1.2.2", "@types/minimist": "1.2.2",
"@types/mkdirp": "1.0.2", "@types/mkdirp": "1.0.2",
"@types/node-fetch": "2.6.4",
"@types/nodemailer": "6.4.14", "@types/nodemailer": "6.4.14",
"@types/passport": "1.0.12",
"@types/passport-anonymous": "1.0.3",
"@types/passport-jwt": "3.0.9",
"@types/passport-local": "1.0.35",
"@types/pluralize": "0.0.33", "@types/pluralize": "0.0.33",
"@types/react-datepicker": "4.11.2", "@types/react-datepicker": "6.2.0",
"confusing-browser-globals": "1.0.11", "@types/uuid": "^9.0.8",
"copyfiles": "2.4.1", "copyfiles": "2.4.1",
"cross-env": "7.0.3", "cross-env": "7.0.3",
"file-loader": "6.2.0",
"form-data": "3.0.1",
"get-port": "5.1.1",
"graphql-http": "^1.22.0", "graphql-http": "^1.22.0",
"mini-css-extract-plugin": "1.6.2",
"nodemon": "3.0.3",
"object.assign": "4.1.4",
"object.entries": "1.1.6",
"passport-strategy": "1.0.0",
"rimraf": "3.0.2", "rimraf": "3.0.2",
"sharp": "0.32.6" "sharp": "0.32.6"
}, },

View File

@@ -1,22 +1,25 @@
import dotenv from 'dotenv' import nextEnvImport from '@next/env'
import findUp from 'find-up' const { loadEnvConfig } = nextEnvImport
import fs from 'fs' import { findUpStop, findUpSync } from 'find-up'
import path from 'path'
/** /**
* Try to find user's .env and load it * Try to find user's env files and load it. Uses the same algorithm next.js uses to parse env files, meaning this also supports .env.local, .env.development, .env.production, etc.
*/ */
export function loadEnv() { export function loadEnv(path?: string) {
const envPath = findUp.sync('.env') if (path?.length) {
loadEnvConfig(path, true)
return
}
if (envPath) { const { loadedEnvFiles } = loadEnvConfig(process.cwd(), true) // assuming this won't run in production
dotenv.config({ path: envPath })
} else { if (!loadedEnvFiles?.length) {
const cwdPath = path.resolve(process.cwd(), '.env') // use findUp to find the env file. So, run loadEnvConfig for every directory upwards
if (fs.existsSync(cwdPath)) { findUpSync((dir) => {
dotenv.config({ const { loadedEnvFiles } = loadEnvConfig(dir, true)
path: cwdPath, if (loadedEnvFiles?.length) {
}) return findUpStop
} }
})
} }
} }

View File

@@ -1,4 +1,4 @@
import findUp from 'find-up' import { findUpSync, pathExistsSync } from 'find-up'
import fs from 'fs' import fs from 'fs'
import path from 'path' import path from 'path'
@@ -13,7 +13,7 @@ const getTSConfigPaths = (): {
rootPath?: string rootPath?: string
srcPath?: string srcPath?: string
} => { } => {
const tsConfigPath = findUp.sync('tsconfig.json') const tsConfigPath = findUpSync('tsconfig.json')
if (!tsConfigPath) { if (!tsConfigPath) {
return { return {
@@ -79,17 +79,17 @@ export const findConfig = (): string => {
for (const searchPath of searchPaths) { for (const searchPath of searchPaths) {
if (!searchPath) continue if (!searchPath) continue
const configPath = findUp.sync( const configPath = findUpSync(
(dir) => { (dir) => {
const tsPath = path.join(dir, 'payload.config.ts') const tsPath = path.join(dir, 'payload.config.ts')
const hasTS = findUp.sync.exists(tsPath) const hasTS = pathExistsSync(tsPath)
if (hasTS) { if (hasTS) {
return tsPath return tsPath
} }
const jsPath = path.join(dir, 'payload.config.js') const jsPath = path.join(dir, 'payload.config.js')
const hasJS = findUp.sync.exists(jsPath) const hasJS = pathExistsSync(jsPath)
if (hasJS) { if (hasJS) {
return jsPath return jsPath
@@ -108,13 +108,13 @@ export const findConfig = (): string => {
// If no config file is found in the directories defined by tsconfig.json, // If no config file is found in the directories defined by tsconfig.json,
// try searching in the 'src' and 'dist' directory as a last resort, as they are most commonly used // try searching in the 'src' and 'dist' directory as a last resort, as they are most commonly used
if (process.env.NODE_ENV === 'production') { if (process.env.NODE_ENV === 'production') {
const distConfigPath = findUp.sync(['payload.config.js', 'payload.config.ts'], { const distConfigPath = findUpSync(['payload.config.js', 'payload.config.ts'], {
cwd: path.resolve(process.cwd(), 'dist'), cwd: path.resolve(process.cwd(), 'dist'),
}) })
if (distConfigPath) return distConfigPath if (distConfigPath) return distConfigPath
} else { } else {
const srcConfigPath = findUp.sync(['payload.config.js', 'payload.config.ts'], { const srcConfigPath = findUpSync(['payload.config.js', 'payload.config.ts'], {
cwd: path.resolve(process.cwd(), 'src'), cwd: path.resolve(process.cwd(), 'src'),
}) })

View File

@@ -1,10 +1,11 @@
import type { ValidateOptions } from './config/types.js' import type { ValidateOptions } from './config/types.js'
import { jest } from '@jest/globals'
import { number, password, point, relationship, select, text, textarea } from './validations.js' import { number, password, point, relationship, select, text, textarea } from './validations.js'
const t = jest.fn((string) => string) const t = jest.fn((string) => string)
let options: ValidateOptions<any, any> = { let options: ValidateOptions<any, any, any> = {
data: undefined, data: undefined,
operation: 'create', operation: 'create',
siblingData: undefined, siblingData: undefined,

View File

@@ -4,6 +4,8 @@ import path from 'path'
import type { SanitizedConfig } from '../config/types.js' import type { SanitizedConfig } from '../config/types.js'
import { loadEnv } from '../bin/loadEnv.js'
const filename = fileURLToPath(import.meta.url) const filename = fileURLToPath(import.meta.url)
const dirname = path.dirname(filename) const dirname = path.dirname(filename)
@@ -20,6 +22,7 @@ export const importWithoutClientFiles = async <T = unknown>(filePath: string) =>
* Resolve and load Payload config from either a relative or absolute path * Resolve and load Payload config from either a relative or absolute path
*/ */
export const importConfig = async (configPath: string) => { export const importConfig = async (configPath: string) => {
loadEnv() // loadConfig would usually be run outside of next. This means they will not get next's automatic env loading here. In order to not force them to install dotenv and set it up manually, we can load the env for them here
const isAbsolutePath = path.isAbsolute(configPath) const isAbsolutePath = path.isAbsolute(configPath)
if (isAbsolutePath) { if (isAbsolutePath) {
const config = await importWithoutClientFiles<{ default: Promise<SanitizedConfig> }>(configPath) const config = await importWithoutClientFiles<{ default: Promise<SanitizedConfig> }>(configPath)

View File

@@ -2,7 +2,7 @@ import { execSync } from 'child_process'
import ciInfo from 'ci-info' import ciInfo from 'ci-info'
import ConfImport from 'conf' import ConfImport from 'conf'
import { randomBytes } from 'crypto' import { randomBytes } from 'crypto'
import findUp from 'find-up' import { findUp } from 'find-up'
import fs from 'fs' import fs from 'fs'
import path from 'path' import path from 'path'
import { fileURLToPath } from 'url' import { fileURLToPath } from 'url'

View File

@@ -41,7 +41,7 @@
"resend": "^0.17.2" "resend": "^0.17.2"
}, },
"devDependencies": { "devDependencies": {
"@types/jest": "^29.5.1", "@types/jest": "29.5.12",
"@types/nodemailer": "6.4.14", "@types/nodemailer": "6.4.14",
"payload": "workspace:*", "payload": "workspace:*",
"ts-jest": "^29.1.0" "ts-jest": "^29.1.0"

View File

@@ -1,6 +1,7 @@
import type { Config } from 'payload/config' import type { Config } from 'payload/config'
import type { Payload } from 'payload' import type { Payload } from 'payload'
import nodemailer from 'nodemailer' import nodemailer from 'nodemailer'
import { jest } from '@jest/globals'
import { defaults } from 'payload/config' import { defaults } from 'payload/config'
@@ -11,7 +12,7 @@ describe('email', () => {
const skipVerify = true const skipVerify = true
const defaultDomain = 'test.com' const defaultDomain = 'test.com'
const apiKey = 'test' const apiKey = 'test'
let createTransportSpy: jest.SpyInstance let createTransportSpy: jest.Spied<any>
const mockedPayload: Payload = jest.fn() as unknown as Payload const mockedPayload: Payload = jest.fn() as unknown as Payload

View File

@@ -1,5 +1,6 @@
import type { Config } from 'payload/config' import type { Config } from 'payload/config'
import type { Payload } from 'payload' import type { Payload } from 'payload'
import { jest } from '@jest/globals'
import nodemailer from 'nodemailer' import nodemailer from 'nodemailer'
import { defaults } from 'payload/config' import { defaults } from 'payload/config'
@@ -10,7 +11,7 @@ import { nodemailerAdapter } from '@payloadcms/email-nodemailer'
const mockedPayload: Payload = jest.fn() as unknown as Payload const mockedPayload: Payload = jest.fn() as unknown as Payload
describe('plugin', () => { describe('plugin', () => {
let createTransportSpy: jest.SpyInstance let createTransportSpy: jest.Spied<any>
const skipVerify = true const skipVerify = true

View File

@@ -45,14 +45,13 @@
"devDependencies": { "devDependencies": {
"@payloadcms/eslint-config": "workspace:*", "@payloadcms/eslint-config": "workspace:*",
"@types/express": "^4.17.9", "@types/express": "^4.17.9",
"@types/jest": "^29.5.2", "@types/jest": "29.5.12",
"@types/node": "20.12.5", "@types/node": "20.12.5",
"@types/react": "npm:types-react@19.0.0-beta.2", "@types/react": "npm:types-react@19.0.0-beta.2",
"@types/react-dom": "npm:types-react-dom@19.0.0-beta.2", "@types/react-dom": "npm:types-react-dom@19.0.0-beta.2",
"copyfiles": "^2.4.1", "copyfiles": "^2.4.1",
"cross-env": "^7.0.3", "cross-env": "^7.0.3",
"dotenv": "^8.2.0", "jest": "^29.7.0",
"jest": "^29.5.0",
"nodemon": "3.0.3", "nodemon": "3.0.3",
"payload": "workspace:*", "payload": "workspace:*",
"ts-jest": "^29.1.0", "ts-jest": "^29.1.0",

View File

@@ -63,7 +63,7 @@
"@types/lodash.get": "^4.4.7", "@types/lodash.get": "^4.4.7",
"@types/react": "npm:types-react@19.0.0-beta.2", "@types/react": "npm:types-react@19.0.0-beta.2",
"@types/react-dom": "npm:types-react-dom@19.0.0-beta.2", "@types/react-dom": "npm:types-react-dom@19.0.0-beta.2",
"@types/uuid": "^9.0.0", "@types/uuid": "^9.0.8",
"payload": "workspace:*" "payload": "workspace:*"
}, },
"peerDependencies": { "peerDependencies": {

View File

@@ -40,7 +40,7 @@
"@types/react": "npm:types-react@19.0.0-beta.2", "@types/react": "npm:types-react@19.0.0-beta.2",
"@types/react-dom": "npm:types-react-dom@19.0.0-beta.2", "@types/react-dom": "npm:types-react-dom@19.0.0-beta.2",
"date-fns": "3.3.1", "date-fns": "3.3.1",
"dotenv": "8.6.0", "dotenv": "16.4.5",
"prettier": "^3.0.3", "prettier": "^3.0.3",
"typescript": "5.4.5" "typescript": "5.4.5"
}, },

View File

@@ -5,119 +5,119 @@ export const importDateFNSLocale = async (locale: string): Promise<Locale> => {
switch (locale) { switch (locale) {
case 'ar': case 'ar':
result = await import('date-fns/locale/ar') result = (await import('date-fns/locale/ar')).ar
break break
case 'az': case 'az':
result = await import('date-fns/locale/az') result = (await import('date-fns/locale/az')).az
break break
case 'bg': case 'bg':
result = await import('date-fns/locale/bg') result = (await import('date-fns/locale/bg')).bg
break break
case 'cs': case 'cs':
result = await import('date-fns/locale/cs') result = (await import('date-fns/locale/cs')).cs
break break
case 'de': case 'de':
result = await import('date-fns/locale/de') result = (await import('date-fns/locale/de')).de
break break
case 'en-US': case 'en-US':
result = await import('date-fns/locale/en-US') result = (await import('date-fns/locale/en-US')).enUS
break break
case 'es': case 'es':
result = await import('date-fns/locale/es') result = (await import('date-fns/locale/es')).es
break break
case 'fa-IR': case 'fa-IR':
result = await import('date-fns/locale/fa-IR') result = (await import('date-fns/locale/fa-IR')).faIR
break break
case 'fr': case 'fr':
result = await import('date-fns/locale/fr') result = (await import('date-fns/locale/fr')).fr
break break
case 'he': case 'he':
result = await import('date-fns/locale/he') result = (await import('date-fns/locale/he')).he
break break
case 'hr': case 'hr':
result = await import('date-fns/locale/hr') result = (await import('date-fns/locale/hr')).hr
break break
case 'hu': case 'hu':
result = await import('date-fns/locale/hu') result = (await import('date-fns/locale/hu')).hu
break break
case 'it': case 'it':
result = await import('date-fns/locale/it') result = (await import('date-fns/locale/it')).it
break break
case 'ja': case 'ja':
result = await import('date-fns/locale/ja') result = (await import('date-fns/locale/ja')).ja
break break
case 'ko': case 'ko':
result = await import('date-fns/locale/ko') result = (await import('date-fns/locale/ko')).ko
break break
case 'nb': case 'nb':
result = await import('date-fns/locale/nb') result = (await import('date-fns/locale/nb')).nb
break break
case 'nl': case 'nl':
result = await import('date-fns/locale/nl') result = (await import('date-fns/locale/nl')).nl
break break
case 'pl': case 'pl':
result = await import('date-fns/locale/pl') result = (await import('date-fns/locale/pl')).pl
break break
case 'pt': case 'pt':
result = await import('date-fns/locale/pt') result = (await import('date-fns/locale/pt')).pt
break break
case 'ro': case 'ro':
result = await import('date-fns/locale/ro') result = (await import('date-fns/locale/ro')).ro
break break
case 'ru': case 'ru':
result = await import('date-fns/locale/ru') result = (await import('date-fns/locale/ru')).ru
break break
case 'sk': case 'sk':
result = await import('date-fns/locale/sk') result = (await import('date-fns/locale/sk')).sk
break break
case 'sv': case 'sv':
result = await import('date-fns/locale/sv') result = (await import('date-fns/locale/sv')).sv
break break
case 'th': case 'th':
result = await import('date-fns/locale/th') result = (await import('date-fns/locale/th')).th
break break
case 'tr': case 'tr':
result = await import('date-fns/locale/tr') result = (await import('date-fns/locale/tr')).tr
break break
case 'uk': case 'uk':
result = await import('date-fns/locale/uk') result = (await import('date-fns/locale/uk')).uk
break break
case 'vi': case 'vi':
result = await import('date-fns/locale/vi') result = (await import('date-fns/locale/vi')).vi
break break
case 'zh-CN': case 'zh-CN':
result = await import('date-fns/locale/zh-CN') result = (await import('date-fns/locale/zh-CN')).zhCN
break break
case 'zh-TW': case 'zh-TW':
result = await import('date-fns/locale/zh-TW') result = (await import('date-fns/locale/zh-TW')).zhTW
break break
} }

View File

@@ -114,9 +114,9 @@
"react-image-crop": "10.1.8", "react-image-crop": "10.1.8",
"react-select": "5.8.0", "react-select": "5.8.0",
"react-toastify": "10.0.5", "react-toastify": "10.0.5",
"scheduler": "0.23.0", "scheduler": "0.25.0-rc-f994737d14-20240522",
"use-context-selector": "1.4.1", "use-context-selector": "2.0.0",
"uuid": "9.0.1" "uuid": "^9.0.1"
}, },
"devDependencies": { "devDependencies": {
"@babel/cli": "^7.24.5", "@babel/cli": "^7.24.5",
@@ -130,7 +130,7 @@
"@types/react": "npm:types-react@19.0.0-beta.2", "@types/react": "npm:types-react@19.0.0-beta.2",
"@types/react-datepicker": "6.2.0", "@types/react-datepicker": "6.2.0",
"@types/react-dom": "npm:types-react-dom@19.0.0-beta.2", "@types/react-dom": "npm:types-react-dom@19.0.0-beta.2",
"@types/uuid": "8.3.4", "@types/uuid": "^9.0.8",
"babel-plugin-react-compiler": "0.0.0-experimental-592953e-20240517", "babel-plugin-react-compiler": "0.0.0-experimental-592953e-20240517",
"babel-plugin-transform-remove-imports": "^1.7.1", "babel-plugin-transform-remove-imports": "^1.7.1",
"css-loader": "^6.10.0", "css-loader": "^6.10.0",
@@ -138,8 +138,8 @@
"mini-css-extract-plugin": "1.6.2", "mini-css-extract-plugin": "1.6.2",
"payload": "workspace:*", "payload": "workspace:*",
"postcss-loader": "^8.1.1", "postcss-loader": "^8.1.1",
"postcss-preset-env": "^9.5.0", "postcss-preset-env": "^9.5.14",
"sass-loader": "^14.1.1", "sass-loader": "14.2.1",
"swc-loader": "^0.2.6", "swc-loader": "^0.2.6",
"swc-plugin-transform-remove-imports": "^1.12.1", "swc-plugin-transform-remove-imports": "^1.12.1",
"terser-webpack-plugin": "^5.3.10", "terser-webpack-plugin": "^5.3.10",

View File

@@ -77,7 +77,6 @@ const DateTime: React.FC<Props> = (props) => {
monthsShown: Math.min(2, monthsToShow), monthsShown: Math.min(2, monthsToShow),
onChange, onChange,
placeholderText, placeholderText,
// @ts-expect-error // TODO Fix this - Broke with React 19 types
popperPlacement: 'bottom-start', popperPlacement: 'bottom-start',
selected: value && new Date(value), selected: value && new Date(value),
showMonthYearPicker: pickerAppearance === 'monthOnly', showMonthYearPicker: pickerAppearance === 'monthOnly',

View File

@@ -11,7 +11,7 @@ import type { ClientConfig, LanguageOptions } from 'payload/types'
import { t } from '@payloadcms/translations' import { t } from '@payloadcms/translations'
import { importDateFNSLocale } from '@payloadcms/translations' import { importDateFNSLocale } from '@payloadcms/translations'
import enUS from 'date-fns/locale/en-US' import { enUS } from 'date-fns/locale/en-US'
import React, { createContext, useContext, useEffect, useState } from 'react' import React, { createContext, useContext, useEffect, useState } from 'react'
import { useRouteCache } from '../RouteCache/index.js' import { useRouteCache } from '../RouteCache/index.js'

View File

@@ -1,29 +1,29 @@
import ar from 'date-fns/locale/ar' import { ar } from 'date-fns/locale/ar'
import az from 'date-fns/locale/az' import { az } from 'date-fns/locale/az'
import bg from 'date-fns/locale/bg' import { bg } from 'date-fns/locale/bg'
import cs from 'date-fns/locale/cs' import { cs } from 'date-fns/locale/cs'
import de from 'date-fns/locale/de' import { de } from 'date-fns/locale/de'
import enUS from 'date-fns/locale/en-US' import { enUS } from 'date-fns/locale/en-US'
import es from 'date-fns/locale/es' import { es } from 'date-fns/locale/es'
import faIR from 'date-fns/locale/fa-IR' import { faIR } from 'date-fns/locale/fa-IR'
import fr from 'date-fns/locale/fr' import { fr } from 'date-fns/locale/fr'
import hr from 'date-fns/locale/hr' import { hr } from 'date-fns/locale/hr'
import hu from 'date-fns/locale/hu' import { hu } from 'date-fns/locale/hu'
import it from 'date-fns/locale/it' import { it } from 'date-fns/locale/it'
import ja from 'date-fns/locale/ja' import { ja } from 'date-fns/locale/ja'
import ko from 'date-fns/locale/ko' import { ko } from 'date-fns/locale/ko'
import nb from 'date-fns/locale/nb' import { nb } from 'date-fns/locale/nb'
import nl from 'date-fns/locale/nl' import { nl } from 'date-fns/locale/nl'
import pl from 'date-fns/locale/pl' import { pl } from 'date-fns/locale/pl'
import pt from 'date-fns/locale/pt' import { pt } from 'date-fns/locale/pt'
import ro from 'date-fns/locale/ro' import { ro } from 'date-fns/locale/ro'
import ru from 'date-fns/locale/ru' import { ru } from 'date-fns/locale/ru'
import sv from 'date-fns/locale/sv' import { sv } from 'date-fns/locale/sv'
import th from 'date-fns/locale/th' import { th } from 'date-fns/locale/th'
import tr from 'date-fns/locale/tr' import { tr } from 'date-fns/locale/tr'
import vi from 'date-fns/locale/vi' import { vi } from 'date-fns/locale/vi'
import zhCN from 'date-fns/locale/zh-CN' import { zhCN } from 'date-fns/locale/zh-CN'
import zhTW from 'date-fns/locale/zh-TW' import { zhTW } from 'date-fns/locale/zh-TW'
export const dateLocales = { export const dateLocales = {
ar, ar,

1118
pnpm-lock.yaml generated

File diff suppressed because it is too large Load Diff

View File

@@ -1,5 +1,6 @@
import type { Payload } from 'payload' import type { Payload } from 'payload'
import { fileURLToPath } from 'node:url'
import path from 'path' import path from 'path'
import { getFileByPath } from 'payload/uploads' import { getFileByPath } from 'payload/uploads'
import { mapAsync } from 'payload/utilities' import { mapAsync } from 'payload/utilities'
@@ -16,6 +17,9 @@ const title = 'title'
let restClient: NextRESTClient let restClient: NextRESTClient
let payload: Payload let payload: Payload
const filename = fileURLToPath(import.meta.url)
const dirname = path.dirname(filename)
describe('collections-graphql', () => { describe('collections-graphql', () => {
beforeAll(async () => { beforeAll(async () => {
;({ payload, restClient } = await initPayloadInt(config)) ;({ payload, restClient } = await initPayloadInt(config))
@@ -1077,7 +1081,7 @@ describe('collections-graphql', () => {
}) })
it('should query upload enabled docs', async () => { it('should query upload enabled docs', async () => {
const file = await getFileByPath(path.resolve(__dirname, '../uploads/test-image.jpg')) const file = await getFileByPath(path.resolve(dirname, '../uploads/test-image.jpg'))
const mediaDoc = await payload.create({ const mediaDoc = await payload.create({
collection: 'media', collection: 'media',

View File

@@ -30,7 +30,7 @@ describe('create-payload-app', () => {
const projectDir = tempy.directory() const projectDir = tempy.directory()
beforeEach(async () => { beforeEach(async () => {
if (fs.existsSync(projectDir)) { if (fs.existsSync(projectDir)) {
fs.rmdirSync(projectDir, { recursive: true }) fs.rmSync(projectDir, { recursive: true })
} }
// Create dir for Next.js project // Create dir for Next.js project
@@ -57,7 +57,7 @@ describe('create-payload-app', () => {
afterEach(() => { afterEach(() => {
if (fs.existsSync(projectDir)) { if (fs.existsSync(projectDir)) {
fs.rmdirSync(projectDir, { recursive: true }) fs.rmSync(projectDir, { recursive: true })
} }
}) })

View File

@@ -575,6 +575,14 @@ describe('lexicalBlocks', () => {
// reload page and assert again // reload page and assert again
await page.reload() await page.reload()
await wait(300) await wait(300)
await newSubLexicalAndUploadBlock.scrollIntoViewIfNeeded()
await expect(newSubLexicalAndUploadBlock).toBeVisible()
await newSubLexicalAndUploadBlock
.locator('.field-type.upload .file-meta__url a')
.scrollIntoViewIfNeeded()
await expect(
newSubLexicalAndUploadBlock.locator('.field-type.upload .file-meta__url a'),
).toBeVisible()
await expect( await expect(
newSubLexicalAndUploadBlock.locator('.field-type.upload .file-meta__url a'), newSubLexicalAndUploadBlock.locator('.field-type.upload .file-meta__url a'),

View File

@@ -42,19 +42,22 @@
"@payloadcms/storage-vercel-blob": "workspace:*", "@payloadcms/storage-vercel-blob": "workspace:*",
"@payloadcms/translations": "workspace:*", "@payloadcms/translations": "workspace:*",
"@payloadcms/ui": "workspace:*", "@payloadcms/ui": "workspace:*",
"@sentry/react": "^7.77.0",
"@types/react": "npm:types-react@19.0.0-beta.2", "@types/react": "npm:types-react@19.0.0-beta.2",
"@types/react-dom": "npm:types-react-dom@19.0.0-beta.2", "@types/react-dom": "npm:types-react-dom@19.0.0-beta.2",
"babel-plugin-react-compiler": "0.0.0-experimental-592953e-20240517", "babel-plugin-react-compiler": "0.0.0-experimental-592953e-20240517",
"comment-json": "^4.2.3", "comment-json": "^4.2.3",
"create-payload-app": "workspace:*", "create-payload-app": "workspace:*",
"dotenv": "8.6.0", "dotenv": "16.4.5",
"eslint-plugin-payload": "workspace:*", "eslint-plugin-payload": "workspace:*",
"eslint-plugin-playwright": "1.5.3", "eslint-plugin-playwright": "1.5.3",
"execa": "5.1.1", "execa": "5.1.1",
"http-status": "1.6.2", "http-status": "1.6.2",
"jwt-decode": "4.0.0",
"lexical": "0.15.0", "lexical": "0.15.0",
"payload": "workspace:*", "payload": "workspace:*",
"server-only": "^0.0.1", "server-only": "^0.0.1",
"slate": "0.91.4",
"tempy": "^1.0.1", "tempy": "^1.0.1",
"ts-essentials": "7.0.3", "ts-essentials": "7.0.3",
"typescript": "5.4.5", "typescript": "5.4.5",

View File

@@ -1,5 +1,8 @@
import { relationshipsAsObjectID } from '@payloadcms/plugin-relationship-object-ids' import { relationshipsAsObjectID } from '@payloadcms/plugin-relationship-object-ids'
import path from 'path' import path from 'path'
const filename = fileURLToPath(import.meta.url)
const dirname = path.dirname(filename)
import { fileURLToPath } from 'node:url'
import { buildConfigWithDefaults } from '../buildConfigWithDefaults.js' import { buildConfigWithDefaults } from '../buildConfigWithDefaults.js'
@@ -99,7 +102,7 @@ export default buildConfigWithDefaults({
const upload = await payload.create({ const upload = await payload.create({
collection: 'uploads', collection: 'uploads',
data: {}, data: {},
filePath: path.resolve(__dirname, './payload-logo.png'), filePath: path.resolve(dirname, './payload-logo.png'),
}) })
await payload.create({ await payload.create({