Compare commits

..

48 Commits

Author SHA1 Message Date
Dan Ribbens
ba2702cfca chore(release): v3.0.0-alpha.45 [skip ci] 2024-03-11 14:53:31 -04:00
James
eba1f6327d Merge branch 'alpha' of github.com:payloadcms/payload into alpha 2024-03-11 14:41:37 -04:00
James Mikrut
1ba0b4037c Merge pull request #5293 from payloadcms/fix/auth-schema-and-client-side
fix (alpha): `auth.strategies` schema and removal of auth functions from client config
2024-03-11 14:40:43 -04:00
James
49daa75bc4 chore: fixes race condition in payload hmr 2024-03-11 14:39:41 -04:00
PatrikKozak
fea1eb1149 fix: removes auth strategies & forgotPassword & verify functions from client side 2024-03-11 13:56:50 -04:00
PatrikKozak
9a58f6c454 fix: updates auth schema to match updated auth types 2024-03-11 13:54:54 -04:00
James
66cefe6bb5 chore: removes auth cache, sets overrideAccess false 2024-03-11 12:21:13 -04:00
Jarrod Flesch
23510acf40 chore: sets bg on templates (#5289) 2024-03-10 23:10:37 -04:00
Jarrod Flesch
faa49f36e7 fix(alpha): correctly set redirect route when logout is triggered (#5288) 2024-03-10 22:35:06 -04:00
James
a5fb8b20a1 Merge branch 'alpha' of github.com:payloadcms/payload into alpha 2024-03-10 22:18:56 -04:00
James
e14b303609 chore: int tests 2024-03-10 22:18:48 -04:00
Dan Ribbens
2ec3df6680 chore(release): v3.0.0-alpha.44 [skip ci] 2024-03-10 22:07:16 -04:00
Elliot DeNolf
1f4b6001ef chore: run eslint on pre-commit hook 2024-03-10 22:01:15 -04:00
James
6e7c9cc6a3 Merge branch 'alpha' of github.com:payloadcms/payload into alpha 2024-03-10 21:56:06 -04:00
James
2db385c6a5 chore: requires drizzle-kit within func 2024-03-10 21:54:31 -04:00
Elliot DeNolf
bd27f48eae test: remove component test suite 2024-03-10 21:19:04 -04:00
Dan Ribbens
98a33250f6 chore(release): v3.0.0-alpha.43 [skip ci] 2024-03-10 21:11:46 -04:00
Elliot DeNolf
8f9729a928 ci: remove component tests 2024-03-10 21:10:19 -04:00
James
1a8564bc35 chore: safely import drizzle-kit 2024-03-10 19:03:15 -04:00
James
76c9632417 Merge branch 'alpha' of github.com:payloadcms/payload into alpha 2024-03-10 18:18:32 -04:00
James
2370361b43 chore: stops excluding pino and pino-pretty in webpack config 2024-03-10 18:17:57 -04:00
Dan Ribbens
cb63095d3f chore(release): v3.0.0-alpha.42 [skip ci] 2024-03-10 14:28:05 -04:00
Dan Ribbens
601f2fb450 chore: add building plugins to release 2024-03-10 14:16:45 -04:00
Alessio Gravili
e746f17167 fix: incorrect TypeScript type for getPayload() props, throw proper error if config doesn't exist 2024-03-10 14:14:29 -04:00
James
5f76097562 chore: merge playwright revisions 2024-03-10 14:08:52 -04:00
James Mikrut
03756c4210 Merge pull request #5286 from payloadcms/feat/pre-compile-css
Feat/pre compile css
2024-03-10 14:06:10 -04:00
James
5e1e158414 chore: add exports for css 2024-03-10 14:05:22 -04:00
James
76d2525fd2 chore: cleanup 2024-03-10 13:57:28 -04:00
James
ec8c7e5c2c chore: finishes css pre-compilation 2024-03-10 13:53:37 -04:00
Elliot DeNolf
0a4cbe1a08 chore: remove unused directive 2024-03-10 13:52:48 -04:00
Dan Ribbens
c228421a38 chore(plugin-form-builder): esm imports 2024-03-10 12:12:49 -04:00
Dan Ribbens
a742f82370 chore: plugins peerDependencies payload workspace 2024-03-10 11:43:13 -04:00
Dan Ribbens
213678ca3e chore(plugin-redirects): esm imports 2024-03-10 11:42:14 -04:00
Dan Ribbens
e1b7ad6a71 chore(plugin-nested-docs): esm imports 2024-03-10 11:39:41 -04:00
Dan Ribbens
8b9985a92c chore(plugin-search): payload peer dependency workspace 2024-03-10 11:32:05 -04:00
Dan Ribbens
f276826b09 chore(plugin-search): esm imports 2024-03-10 11:28:54 -04:00
geisterfurz007
8c1df551ef chore: fix typescript hallucinations (#4559) 2024-03-10 01:53:59 -05:00
Akhil Naidu
b62cb157e1 docs: improve naming for afterForgotPassword hook example code (#5062) 2024-03-10 00:23:29 -05:00
Max Morozov
045c74ce67 docs: fix typo (#5052) 2024-03-10 00:13:09 -05:00
madaxen86
911e902da4 feat: add support for displaying AVIF images (#5227) 2024-03-10 00:00:26 -05:00
Alessio Gravili
4e0d90d720 WIP 2024-03-09 18:20:32 -05:00
James
7b62705cc0 chore: restores webpack config, still broken 2024-03-09 15:55:26 -05:00
James
bdf02bebaa chore: adds spawn process to playwright tests as well 2024-03-09 14:53:53 -05:00
James
94aa309910 chore: avoids importing config into playwright tests 2024-03-09 14:41:00 -05:00
Elliot DeNolf
499a0a782a chore: adjust tgz specifier in pnpm lock 2024-03-08 21:05:00 -05:00
Elliot DeNolf
1e5a531a83 ci: add alpha branch to main workflow 2024-03-08 20:57:14 -05:00
Elliot DeNolf
3e6a4073c4 chore(scripts): cleanup release script 2024-03-08 20:56:39 -05:00
Alessio Gravili
e7cb6abd1f chore: add new obliterate-playwright-cache 2024-03-08 19:48:26 -05:00
95 changed files with 2390 additions and 529 deletions

View File

@@ -4,7 +4,7 @@ on:
pull_request:
types: [ opened, reopened, synchronize ]
push:
branches: ['main', 'feat/next-poc']
branches: ['main', 'alpha']
jobs:
changes:
@@ -196,9 +196,6 @@ jobs:
echo "POSTGRES_URL=postgresql://postgres:postgres@127.0.0.1:54322/postgres" >> $GITHUB_ENV
if: matrix.database == 'supabase'
- name: Component Tests
run: pnpm test:components
- name: Integration Tests
run: pnpm test:int
env:

1
.gitignore vendored
View File

@@ -288,3 +288,4 @@ $RECYCLE.BIN/
# End of https://www.toptal.com/developers/gitignore/api/node,macos,windows,webstorm,sublimetext,visualstudiocode
/build
.swc

15
.swcrc Normal file
View File

@@ -0,0 +1,15 @@
{
"$schema": "https://json.schemastore.org/swcrc",
"sourceMaps": "inline",
"jsc": {
"target": "esnext",
"parser": {
"syntax": "typescript",
"tsx": true,
"dts": true
}
},
"module": {
"type": "es6"
}
}

View File

@@ -292,13 +292,11 @@ For auth-enabled Collections, this hook runs after successful `forgotPassword` o
```ts
import { CollectionAfterForgotPasswordHook } from 'payload/types'
const afterLoginHook: CollectionAfterForgotPasswordHook = async ({
req, // full express request
user, // user being logged in
token, // user token
}) => {
return user
}
const afterForgotPasswordHook: CollectionAfterForgotPasswordHook = async ({
args, // arguments passed into the operation
context,
collection, // The collection which this hook is being run on
}) => {...}
```
## TypeScript

View File

@@ -290,5 +290,5 @@ If you've configured tests for your package, integrate them into your workf
The best way to share and allow others to use your plugin once it is complete is to publish an NPM package. This process is straightforward and well documented, find out more about [creating and publishing a NPM package here](https://docs.npmjs.com/creating-and-publishing-scoped-public-packages/).
##### Add payload-plugin topic tag:
Apply the tag **payload-plugin** to your GitHub repository. This will boost the visibility of your plugin and ensure it gets listed with [existing payload plugins](https://github.com/topics/payload-plugin).
##### Use [Semantic Versioning](https://semver.org/) (SemVar):
With the SemVar system you release version numbers that reflect the nature of changes (major, minor, patch). Ensure all major versions reference their Payload compatibility.
##### Use [Semantic Versioning](https://semver.org/) (SemVer):
With the SemVer system you release version numbers that reflect the nature of changes (major, minor, patch). Ensure all major versions reference their Payload compatibility.

1
emptyModule.js Normal file
View File

@@ -0,0 +1 @@
export default {}

View File

@@ -1,16 +0,0 @@
module.exports = {
moduleNameMapper: {
'\\.(css|scss)$': '<rootDir>/packages/payload/src/bundlers/mocks/emptyModule.js',
'\\.(jpg|jpeg|png|gif|eot|otf|webp|svg|ttf|woff|woff2|mp4|webm|wav|mp3|m4a|aac|oga)$':
'<rootDir>/packages/payload/src/bundlers/mocks/fileMock.js',
},
setupFilesAfterEnv: ['./test/componentsSetup.js'],
testEnvironment: 'jsdom',
testPathIgnorePatterns: ['node_modules', 'dist'],
testRegex: '(/src/admin/.*\\.(test|spec))\\.[jt]sx?$',
testTimeout: 15000,
transform: {
'^.+\\.(t|j)sx?$': ['@swc/jest'],
},
verbose: true,
}

View File

@@ -1,6 +1,6 @@
{
"name": "payload-monorepo",
"version": "3.0.0-alpha.41",
"version": "3.0.0-alpha.45",
"private": true,
"type": "module",
"workspaces:": [
@@ -8,9 +8,10 @@
],
"scripts": {
"build": "pnpm run build:core",
"obliterate-playwright-cache": "rm -rf ~/Library/Caches/ms-playwright && find /System/Volumes/Data/private/var/folders -type d -name 'playwright*' -exec rm -rf {} ++ && npx playwright install",
"build:all": "turbo build",
"build:core": "turbo build --filter \"!@payloadcms/plugin-*\"",
"build:plugins": "turbo build --filter \"@payloadcms/plugin-*\" --filter \"!@payloadcms/plugin-search\" --filter \"!@payloadcms/plugin-redirects\" --filter \"!@payloadcms/plugin-nested-docs\"",
"build:plugins": "turbo build --filter \"@payloadcms/plugin-*\"",
"build:app": "next build",
"build:app:analyze": "cross-env ANALYZE=true next build",
"build:create-payload-app": "turbo build --filter create-payload-app",
@@ -71,7 +72,7 @@
"@next/bundle-analyzer": "^14.1.0",
"@octokit/core": "^5.1.0",
"@payloadcms/eslint-config": "workspace:*",
"@playwright/test": "1.42.1",
"@playwright/test": "^1.42.1",
"@swc/cli": "^0.1.62",
"@swc/jest": "0.2.36",
"@testing-library/jest-dom": "6.4.2",
@@ -123,8 +124,8 @@
"nodemon": "3.0.3",
"pino": "8.15.0",
"pino-pretty": "10.2.0",
"playwright": "file:playwright-1.43.0-next.tgz",
"playwright-core": "file:playwright-core-1.43.0-next.tgz",
"playwright": "^1.42.1",
"playwright-core": "^1.42.1",
"prettier": "^3.0.3",
"prompts": "2.4.2",
"qs": "6.11.2",
@@ -156,7 +157,8 @@
},
"lint-staged": {
"*.{js,jsx,ts,tsx}": [
"prettier --write"
"prettier --write",
"eslint --cache --fix"
]
},
"dependencies": {
@@ -172,9 +174,7 @@
"graphql": "^16.8.1",
"react": "$react",
"react-dom": "$react-dom",
"typescript": "$typescript",
"playwright": "file:playwright-1.43.0-next.tgz",
"playwright-core": "file:playwright-core-1.43.0-next.tgz"
"typescript": "$typescript"
},
"allowedDeprecatedVersions": {
"uuid": "3.4.0",

View File

@@ -1,6 +1,6 @@
{
"$schema": "https://json.schemastore.org/swcrc",
"sourceMaps": "inline",
"sourceMaps": true,
"jsc": {
"target": "esnext",
"parser": {

View File

@@ -1,6 +1,6 @@
{
"$schema": "https://json.schemastore.org/swcrc",
"sourceMaps": "inline",
"sourceMaps": true,
"jsc": {
"target": "esnext",
"parser": {

View File

@@ -1,6 +1,6 @@
{
"name": "@payloadcms/db-mongodb",
"version": "3.0.0-alpha.41",
"version": "3.0.0-alpha.45",
"description": "The officially supported MongoDB database adapter for Payload - Update 2",
"repository": "https://github.com/payloadcms/payload",
"license": "MIT",

View File

@@ -1,6 +1,6 @@
{
"$schema": "https://json.schemastore.org/swcrc",
"sourceMaps": "inline",
"sourceMaps": true,
"jsc": {
"target": "esnext",
"parser": {

View File

@@ -1,6 +1,6 @@
{
"name": "@payloadcms/db-postgres",
"version": "3.0.0-alpha.41",
"version": "3.0.0-alpha.45",
"description": "The officially supported Postgres database adapter for Payload",
"repository": "https://github.com/payloadcms/payload",
"license": "MIT",

View File

@@ -3,10 +3,13 @@ import type { DrizzleSnapshotJSON } from 'drizzle-kit/payload'
import type { CreateMigration } from 'payload/database'
import fs from 'fs'
import { createRequire } from 'module'
import prompts from 'prompts'
import type { PostgresAdapter } from './types.js'
const require = createRequire(import.meta.url)
const migrationTemplate = (
upSQL?: string,
downSQL?: string,
@@ -60,7 +63,7 @@ export const createMigration: CreateMigration = async function createMigration(
fs.mkdirSync(dir)
}
const { generateDrizzleJson, generateMigration } = await import('drizzle-kit/payload')
const { generateDrizzleJson, generateMigration } = require('drizzle-kit/payload')
const [yyymmdd, hhmmss] = new Date().toISOString().split('T')
const formattedDate = yyymmdd.replace(/\D/g, '')

View File

@@ -3,6 +3,7 @@ import type { Payload } from 'payload'
import type { Migration } from 'payload/database'
import type { PayloadRequest } from 'payload/types'
import { createRequire } from 'module'
import {
commitTransaction,
initTransaction,
@@ -17,6 +18,8 @@ import { createMigrationTable } from './utilities/createMigrationTable.js'
import { migrationTableExists } from './utilities/migrationTableExists.js'
import { parseError } from './utilities/parseError.js'
const require = createRequire(import.meta.url)
export async function migrate(this: PostgresAdapter): Promise<void> {
const { payload } = this
const migrationFiles = await readMigrationFiles({ payload })
@@ -82,7 +85,7 @@ export async function migrate(this: PostgresAdapter): Promise<void> {
}
async function runMigrationFile(payload: Payload, migration: Migration, batch: number) {
const { generateDrizzleJson } = await import('drizzle-kit/payload')
const { generateDrizzleJson } = require('drizzle-kit/payload')
const start = Date.now()
const req = { payload } as PayloadRequest

View File

@@ -1,10 +1,11 @@
import { eq } from 'drizzle-orm'
import { numeric, timestamp, varchar } from 'drizzle-orm/pg-core'
import { createRequire } from 'module'
import prompts from 'prompts'
import type { PostgresAdapter } from '../types.js'
const { pushSchema } = await import('drizzle-kit/payload')
const require = createRequire(import.meta.url)
/**
* Pushes the development schema to the database using Drizzle.
@@ -13,6 +14,8 @@ const { pushSchema } = await import('drizzle-kit/payload')
* @returns {Promise<void>} - A promise that resolves once the schema push is complete.
*/
export const pushDevSchema = async (db: PostgresAdapter) => {
const { pushSchema } = require('drizzle-kit/payload')
// This will prompt if clarifications are needed for Drizzle to push new schema
const { apply, hasDataLoss, statementsToExecute, warnings } = await pushSchema(
db.schema,

View File

@@ -1,6 +1,6 @@
{
"$schema": "https://json.schemastore.org/swcrc",
"sourceMaps": "inline",
"sourceMaps": true,
"jsc": {
"target": "esnext",
"parser": {

View File

@@ -1,6 +1,6 @@
{
"name": "@payloadcms/graphql",
"version": "3.0.0-alpha.41",
"version": "3.0.0-alpha.45",
"main": "./src/index.ts",
"types": "./src/index.d.ts",
"type": "module",

View File

@@ -1,6 +1,6 @@
{
"$schema": "https://json.schemastore.org/swcrc",
"sourceMaps": "inline",
"sourceMaps": true,
"jsc": {
"target": "esnext",
"parser": {

View File

@@ -1,6 +1,6 @@
{
"$schema": "https://json.schemastore.org/swcrc",
"sourceMaps": "inline",
"sourceMaps": true,
"jsc": {
"target": "esnext",
"parser": {

View File

@@ -1,12 +1,22 @@
{
"$schema": "https://json.schemastore.org/swcrc",
"sourceMaps": "inline",
"sourceMaps": true,
"jsc": {
"target": "esnext",
"parser": {
"syntax": "typescript",
"tsx": true,
"dts": true
},
"experimental": {
"plugins": [
[
"swc-plugin-transform-remove-imports",
{
"test": "\\.(scss|css)$"
}
]
]
}
},
"module": {

View File

@@ -1,6 +1,6 @@
{
"name": "@payloadcms/next",
"version": "3.0.0-alpha.41",
"version": "3.0.0-alpha.45",
"main": "./src/index.ts",
"types": "./src/index.d.ts",
"type": "module",
@@ -8,9 +8,10 @@
"@payloadcms/next": "./dist/bin/index.js"
},
"scripts": {
"build": "pnpm copyfiles && pnpm build:swc && pnpm build:types",
"build": "pnpm copyfiles && pnpm build:swc && pnpm build:types && pnpm build:webpack && rm dist/prod/index.js",
"build:swc": "swc ./src -d ./dist --config-file .swcrc",
"build:types": "tsc --emitDeclarationOnly --outDir dist",
"build:webpack": "webpack --config webpack.config.js",
"clean": "rimraf {dist,*.tsbuildinfo}",
"copyfiles": "copyfiles -u 1 \"src/**/*.{html,css,scss,ttf,woff,woff2,eot,svg,jpg,png,json}\" \"src/app/api/**\" dist/ && pnpm copyfiles:api",
"copyfiles:api": "copyfiles -u 1 \"src/app/(payload)/**\" dist/template",
@@ -50,7 +51,18 @@
"@types/react": "18.2.15",
"@types/react-dom": "18.2.7",
"@types/ws": "^8.5.10",
"payload": "workspace:*"
"css-loader": "^6.10.0",
"css-minimizer-webpack-plugin": "^6.0.0",
"mini-css-extract-plugin": "1.6.2",
"payload": "workspace:*",
"postcss-loader": "^8.1.1",
"postcss-preset-env": "^9.5.0",
"sass-loader": "^14.1.1",
"swc-loader": "^0.2.6",
"swc-plugin-transform-remove-imports": "^1.12.1",
"terser-webpack-plugin": "^5.3.10",
"webpack": "^5.78.0",
"webpack-cli": "^5.1.4"
},
"dependencies": {
"@dnd-kit/core": "6.0.8",
@@ -79,6 +91,11 @@
"main": "./dist/exports/index.js",
"types": "./dist/exports/index.d.ts",
"exports": {
"./css": {
"import": "./dist/prod/styles.css",
"require": "./dist/prod/styles.css",
"default": "./dist/prod/styles.css"
},
"./withPayload": {
"import": "./dist/withPayload.js",
"require": "./dist/withPayload.js",

View File

@@ -1,6 +1,5 @@
import type { SanitizedConfig } from 'payload/types'
import { auth } from '@payloadcms/next/utilities/auth'
import { translations } from '@payloadcms/translations/client'
import { RootProvider, buildComponentMap } from '@payloadcms/ui'
import '@payloadcms/ui/scss/app.scss'
@@ -11,6 +10,7 @@ import React from 'react'
import 'react-toastify/dist/ReactToastify.css'
import { ClearRouteCache } from '../../elements/ClearRouteCache/index.js'
import { auth } from '../../utilities/auth.js'
import { getPayload } from '../../utilities/getPayload.js'
import { getRequestLanguage } from '../../utilities/getRequestLanguage.js'
import { DefaultEditView } from '../../views/Edit/Default/index.js'
@@ -38,7 +38,7 @@ export const RootLayout = async ({
const payload = await getPayload({ config: configPromise })
const { cookies, permissions, user } = await auth({
const { cookies, permissions } = await auth({
headers,
payload,
})

View File

@@ -1,5 +1,5 @@
@import 'fonts';
@import 'styles';
@import './fonts.scss';
@import './styles.scss';
@import './toastify.scss';
@import './colors.scss';

View File

@@ -1,34 +1,36 @@
import type { Payload, PayloadRequest } from 'payload/types'
import { getAccessResults, getAuthenticatedUser, parseCookies } from 'payload/auth'
import { cache } from 'react'
export const auth = cache(
async ({ headers, payload }: { headers: Request['headers']; payload: Payload }) => {
const cookies = parseCookies(headers)
type Args = {
headers: Request['headers']
payload: Payload
}
const user = await getAuthenticatedUser({
cookies,
export const auth = async ({ headers, payload }: Args) => {
const cookies = parseCookies(headers)
const user = await getAuthenticatedUser({
cookies,
headers,
payload,
})
const permissions = await getAccessResults({
req: {
context: {},
headers,
i18n: undefined,
payload,
})
const permissions = await getAccessResults({
req: {
context: {},
headers,
i18n: undefined,
payload,
payloadAPI: 'REST',
t: undefined,
user,
} as PayloadRequest,
})
return {
cookies,
permissions,
payloadAPI: 'REST',
t: undefined,
user,
}
},
)
} as PayloadRequest,
})
return {
cookies,
permissions,
user,
}
}

View File

@@ -8,15 +8,22 @@ let cached = global._payload
if (!cached) {
// eslint-disable-next-line no-multi-assign
cached = global._payload = { payload: null, promise: null }
cached = global._payload = { payload: null, promise: null, reload: false }
}
export const getPayload = async (options: InitOptions): Promise<Payload> => {
if (!options?.config) {
throw new Error('Error: the payload config is required for getPayload to work.')
}
if (cached.payload) {
const config = await options.config
if (cached.reload) {
cached.reload = false
if (cached.reload === true) {
let resolve
cached.reload = new Promise((res) => (resolve = res))
if (typeof cached.payload.db.destroy === 'function') {
await cached.payload.db.destroy()
}
@@ -33,6 +40,11 @@ export const getPayload = async (options: InitOptions): Promise<Payload> => {
await cached.payload.db.init()
await cached.payload.db.connect({ hotReload: true })
resolve()
}
if (cached.reload instanceof Promise) {
await cached.reload
}
return cached.payload
@@ -47,7 +59,8 @@ export const getPayload = async (options: InitOptions): Promise<Payload> => {
if (process.env.NODE_ENV !== 'production') {
try {
const ws = new WebSocket('ws://localhost:3000/_next/webpack-hmr')
const port = process.env.PORT || '3000'
const ws = new WebSocket(`ws://localhost:${port}/_next/webpack-hmr`)
ws.onmessage = (event) => {
if (typeof event.data === 'string') {

View File

@@ -22,8 +22,8 @@ export { generateAccountMetadata } from './meta.js'
export const Account: React.FC<AdminViewProps> = async ({ initPageResult, searchParams }) => {
const {
permissions,
locale,
permissions,
req: {
i18n,
payload,
@@ -53,6 +53,7 @@ export const Account: React.FC<AdminViewProps> = async ({ initPageResult, search
id: user.id,
collection: userSlug,
depth: 0,
overrideAccess: false,
user,
})
} catch (error) {

View File

@@ -106,6 +106,7 @@ export const Document: React.FC<AdminViewProps> = async ({
collection: collectionSlug,
depth: 0,
locale: locale.code,
overrideAccess: false,
user,
})
} catch (error) {} // eslint-disable-line no-empty
@@ -148,6 +149,7 @@ export const Document: React.FC<AdminViewProps> = async ({
slug: globalSlug,
depth: 0,
locale: locale.code,
overrideAccess: false,
user,
})
} catch (error) {} // eslint-disable-line no-empty

View File

@@ -1,172 +0,0 @@
import { render } from '@testing-library/react'
import React from 'react'
import type { BlockField, DateField, SelectField } from 'payload/types'
import { BlocksCell } from './fields/Blocks'
import { Checkbox } from './fields/Checkbox'
import { DateCell } from './fields/Date'
import { Select } from './fields/Select'
import { Textarea } from './fields/Textarea'
jest.mock('../../../../utilities/Config', () => ({
useConfig: () => ({ admin: { dateFormat: 'MMMM do yyyy, h:mm a' } }),
}))
jest.mock('../../../../providers/Translation', () => ({
useTranslation: () => ({ t: (string) => string }),
}))
describe('Cell Types', () => {
describe('Blocks', () => {
const field: BlockField = {
blocks: [
{
fields: [],
labels: {
plural: 'Numbers',
singular: 'Number',
},
slug: 'number',
},
],
label: 'Blocks Content',
labels: {
plural: 'Blocks Content',
singular: 'Block',
},
name: 'blocks',
type: 'blocks',
}
it('renders multiple', () => {
const data = [{ blockType: 'number' }, { blockType: 'number' }]
const { container } = render(<BlocksCell data={data} field={field} />)
const el = container.querySelector('span')
expect(el).toHaveTextContent('2 Blocks Content - Number, Number')
})
it('renders zero', () => {
const data = []
const { container } = render(<BlocksCell data={data} field={field} />)
const el = container.querySelector('span')
expect(el).toHaveTextContent('0 Blocks Content')
})
it('renders "and X more" if over maximum of 5', () => {
const data = [
{ blockType: 'number' },
{ blockType: 'number' },
{ blockType: 'number' },
{ blockType: 'number' },
{ blockType: 'number' },
{ blockType: 'number' },
]
const { container } = render(<BlocksCell data={data} field={field} />)
const el = container.querySelector('span')
expect(el).toHaveTextContent('fields:itemsAndMore')
})
})
describe('Date', () => {
const field: DateField = {
admin: {
date: {
pickerAppearance: 'dayOnly',
},
},
name: 'dayOnly',
type: 'date',
}
it('renders date', () => {
const timeStamp = '2020-10-06T14:07:39.033Z'
const { container } = render(<DateCell data={timeStamp} field={field} />)
const dateMatch = /October\s6th\s2020,\s\d{1,2}:07\s[A|P]M/ // Had to account for timezones in CI
const el = container.querySelector('span')
expect(el.textContent).toMatch(dateMatch)
})
it('handles undefined', () => {
const timeStamp = undefined
const { container } = render(<DateCell data={timeStamp} field={field} />)
const el = container.querySelector('span')
expect(el.textContent).toBe('')
})
})
describe('Checkbox', () => {
it('renders true', () => {
const { container } = render(<Checkbox data />)
const el = container.querySelector('span')
expect(el).toHaveTextContent('true')
})
it('renders false', () => {
const { container } = render(<Checkbox data={false} />)
const el = container.querySelector('span')
expect(el).toHaveTextContent('false')
})
})
describe('Textarea', () => {
it('renders data', () => {
const { container } = render(<Textarea data="data" />)
const el = container.querySelector('span')
expect(el).toHaveTextContent('data')
})
it('handle undefined - bug/13', () => {
const { container } = render(<Textarea data={undefined} />)
const el = container.querySelector('span')
expect(el).toHaveTextContent('')
})
})
describe('Select', () => {
const fieldWithOptionsObject: SelectField = {
name: 'selectObject',
options: [
{
label: 'One',
value: 'one',
},
{
label: 'Two',
value: 'two',
},
],
type: 'select',
}
const fieldWithStringsOptions: SelectField = {
name: 'selectString',
options: ['blue', 'green', 'yellow'],
type: 'select',
}
it('renders options objects', () => {
const { container } = render(<Select data="one" field={fieldWithOptionsObject} />)
const el = container.querySelector('span')
expect(el).toHaveTextContent('One')
})
it('renders option strings', () => {
const { container } = render(<Select data="blue" field={fieldWithStringsOptions} />)
const el = container.querySelector('span')
expect(el).toHaveTextContent('blue')
})
describe('HasMany', () => {
it('renders options objects', () => {
const { container } = render(
<Select data={['one', 'two']} field={fieldWithOptionsObject} />,
)
const el = container.querySelector('span')
expect(el).toHaveTextContent('One, Two')
})
it('renders option strings', () => {
const { container } = render(
<Select data={['blue', 'green']} field={fieldWithStringsOptions} />,
)
const el = container.querySelector('span')
expect(el).toHaveTextContent('blue, green')
})
})
})
})

View File

@@ -72,6 +72,7 @@ export const ListView: React.FC<AdminViewProps> = async ({ initPageResult, searc
collection: collectionSlug,
depth: 0,
limit,
overrideAccess: false,
user,
})

View File

@@ -15,7 +15,7 @@ export const VersionView: React.FC = async (props: ServerSideEditViewProps) => {
docID: id,
globalConfig,
permissions,
req: { payload, payload: { config } = {} } = {},
req: { payload, payload: { config } = {}, user } = {},
} = initPageResult
// /entityType/:entitySlug/:id/versions/:versionID
@@ -43,6 +43,8 @@ export const VersionView: React.FC = async (props: ServerSideEditViewProps) => {
collection: slug,
depth: 1,
locale: '*',
overrideAccess: false,
user,
})
publishedDoc = await payload.findByID({
@@ -51,6 +53,8 @@ export const VersionView: React.FC = async (props: ServerSideEditViewProps) => {
depth: 1,
draft: false,
locale: '*',
overrideAccess: false,
user,
})
mostRecentDoc = await payload.findByID({
@@ -59,6 +63,8 @@ export const VersionView: React.FC = async (props: ServerSideEditViewProps) => {
depth: 1,
draft: true,
locale: '*',
overrideAccess: false,
user,
})
} catch (error) {
return notFound()
@@ -75,6 +81,8 @@ export const VersionView: React.FC = async (props: ServerSideEditViewProps) => {
slug,
depth: 1,
locale: '*',
overrideAccess: false,
user,
})
publishedDoc = payload.findGlobal({
@@ -82,6 +90,8 @@ export const VersionView: React.FC = async (props: ServerSideEditViewProps) => {
depth: 1,
draft: false,
locale: '*',
overrideAccess: false,
user,
})
mostRecentDoc = payload.findGlobal({
@@ -89,6 +99,8 @@ export const VersionView: React.FC = async (props: ServerSideEditViewProps) => {
depth: 1,
draft: true,
locale: '*',
overrideAccess: false,
user,
})
} catch (error) {
return notFound()

View File

@@ -43,6 +43,7 @@ export const VersionsView: React.FC<ServerSideEditViewProps> = async (props) =>
collection: collectionSlug,
depth: 0,
limit: limit ? parseInt(limit?.toString(), 10) : undefined,
overrideAccess: false,
page: page ? parseInt(page.toString(), 10) : undefined,
sort: sort as string,
user,
@@ -62,6 +63,7 @@ export const VersionsView: React.FC<ServerSideEditViewProps> = async (props) =>
versionsData = await payload.findGlobalVersions({
slug: globalSlug,
depth: 0,
overrideAccess: false,
page: page ? parseInt(page as string, 10) : undefined,
sort: sort as string,
user,

View File

@@ -33,8 +33,6 @@ const withPayload = (nextConfig = {}) => {
...(incomingWebpackConfig?.externals || []),
'drizzle-kit',
'drizzle-kit/payload',
'pino',
'pino-pretty',
'sharp',
'libsql',
],

View File

@@ -0,0 +1,107 @@
import OptimizeCSSAssetsPlugin from 'css-minimizer-webpack-plugin'
import MiniCSSExtractPlugin from 'mini-css-extract-plugin'
import path from 'path'
import TerserJSPlugin from 'terser-webpack-plugin'
import { fileURLToPath } from 'url'
import webpack from 'webpack'
const filename = fileURLToPath(import.meta.url)
const dirname = path.dirname(filename)
const componentWebpackConfig = {
entry: path.resolve(dirname, './src/index.ts'),
externals: ['react', 'react-dom', 'payload', 'payload/config', 'react-image-crop'],
mode: 'production',
module: {
rules: [
{
oneOf: [
{
// exclude: /node_modules/,
test: /\.(t|j)sx?$/,
use: [
{
loader: 'swc-loader',
options: {
jsc: {
experimental: {
plugins: [
// clear the plugins used in .swcrc
],
},
parser: {
syntax: 'typescript',
tsx: true,
},
},
},
},
],
},
{
sideEffects: true,
test: /\.(scss|css)$/,
use: [
MiniCSSExtractPlugin.loader,
'css-loader',
{
loader: 'postcss-loader',
options: {
postcssOptions: {
plugins: ['postcss-preset-env'],
},
},
},
'sass-loader',
],
},
{
type: 'asset/resource',
generator: {
filename: 'payload/[name][ext]',
},
test: [/\.bmp$/, /\.gif$/, /\.jpe?g$/, /\.png$/, /\.svg$/, /\.woff$/, /\.woff2$/],
},
],
},
],
},
optimization: {
minimizer: [
new TerserJSPlugin({
extractComments: false,
}),
new OptimizeCSSAssetsPlugin({}),
],
},
output: {
filename: 'index.js',
libraryTarget: 'commonjs2',
path: path.resolve(dirname, './dist/prod'),
publicPath: '/',
},
plugins: [
new MiniCSSExtractPlugin({
filename: 'styles.css',
ignoreOrder: true,
}),
new webpack.optimize.LimitChunkCountPlugin({
maxChunks: 1,
}),
],
resolve: {
extensionAlias: {
'.js': ['.ts', '.tsx', '.js', '.scss', '.css'],
'.mjs': ['.mts', '.mjs'],
},
extensions: ['.js', '.ts', '.tsx', '.scss', '.css'],
modules: [
'node_modules',
path.resolve(dirname, '../../node_modules'),
path.resolve(dirname, './node_modules'),
],
},
stats: 'errors-only',
}
export default componentWebpackConfig

View File

@@ -1,6 +1,6 @@
{
"$schema": "https://json.schemastore.org/swcrc",
"sourceMaps": "inline",
"sourceMaps": true,
"jsc": {
"target": "esnext",
"parser": {

View File

@@ -1,6 +1,6 @@
{
"name": "payload",
"version": "3.0.0-alpha.41",
"version": "3.0.0-alpha.45",
"description": "Node, React and MongoDB Headless CMS and Application Framework",
"license": "MIT",
"main": "./src/index.js",

View File

@@ -94,16 +94,10 @@ const collectionSchema = joi.object().keys({
maxLoginAttempts: joi.number(),
removeTokenFromResponses: joi.boolean().valid(true),
strategies: joi.array().items(
joi.alternatives().try(
strategyBaseSchema.keys({
name: joi.string().required(),
strategy: joi.func().maxArity(1).required(),
}),
strategyBaseSchema.keys({
name: joi.string(),
strategy: joi.object().required(),
}),
),
joi.object().keys({
name: joi.string().required(),
authenticate: joi.func().required(),
}),
),
tokenExpiration: joi.number(),
useAPIKey: joi.boolean(),

View File

@@ -85,6 +85,13 @@ const sanitizeCollections = (
delete sanitized.upload.handlers
}
if ('auth' in sanitized && typeof sanitized.auth === 'object') {
sanitized.auth = { ...sanitized.auth }
delete sanitized.auth.strategies
delete sanitized.auth.forgotPassword
delete sanitized.auth.verify
}
if ('admin' in sanitized) {
sanitized.admin = { ...sanitized.admin }

View File

@@ -273,13 +273,6 @@ export class BasePayload<TGeneratedTypes extends GeneratedTypes> {
[slug: string]: any // TODO: Type this
} = {}
delete<T extends keyof TGeneratedTypes['collections']>(
options: DeleteOptions<T>,
): Promise<BulkOperationResult<T> | TGeneratedTypes['collections'][T]> {
const { deleteLocal } = localOperations
return deleteLocal<T>(this, options)
}
/**
* @description delete one or more documents
* @param options
@@ -293,12 +286,22 @@ export class BasePayload<TGeneratedTypes extends GeneratedTypes> {
options: DeleteManyOptions<T>,
): Promise<BulkOperationResult<T>>
delete<T extends keyof TGeneratedTypes['collections']>(
options: DeleteOptions<T>,
): Promise<BulkOperationResult<T> | TGeneratedTypes['collections'][T]> {
const { deleteLocal } = localOperations
return deleteLocal<T>(this, options)
}
/**
* @description Initializes Payload
* @param options
*/
// @ts-expect-error // TODO: TypeScript hallucinating again. fix later
async init(options: InitOptions): Promise<Payload> {
if (!options?.config) {
throw new Error('Error: the payload config is required to initialize payload.')
}
this.logger = Logger('payload', options.loggerOptions, options.loggerDestination)
this.config = await options.config
@@ -421,7 +424,11 @@ if (!cached) {
cached = global._payload = { payload: null, promise: null }
}
export const getPayload = async (options?: InitOptions): Promise<BasePayload<GeneratedTypes>> => {
export const getPayload = async (options: InitOptions): Promise<BasePayload<GeneratedTypes>> => {
if (!options?.config) {
throw new Error('Error: the payload config is required for getPayload to work.')
}
if (cached.payload) {
return cached.payload
}

View File

@@ -38,7 +38,6 @@ async function deleteOperation(args: PreferenceRequest): Promise<Document> {
where,
})
// @ts-expect-error // TODO: fix later
if (result.docs.length === 1) {
return result.docs[0]
}

View File

@@ -1,5 +1,7 @@
export default function isImage(mimeType: string): boolean {
return (
['image/jpeg', 'image/png', 'image/gif', 'image/svg+xml', 'image/webp'].indexOf(mimeType) > -1
['image/jpeg', 'image/png', 'image/gif', 'image/svg+xml', 'image/webp', 'image/avif'].indexOf(
mimeType,
) > -1
)
}

View File

@@ -1,6 +1,6 @@
{
"$schema": "https://json.schemastore.org/swcrc",
"sourceMaps": "inline",
"sourceMaps": true,
"jsc": {
"target": "esnext",
"parser": {

View File

@@ -1,7 +1,7 @@
{
"name": "@payloadcms/plugin-cloud-storage",
"description": "The official cloud storage plugin for Payload CMS",
"version": "3.0.0-alpha.41",
"version": "3.0.0-alpha.45",
"main": "dist/index.js",
"types": "dist/index.d.ts",
"type": "module",

View File

@@ -1,6 +1,6 @@
{
"$schema": "https://json.schemastore.org/swcrc",
"sourceMaps": "inline",
"sourceMaps": true,
"exclude": ["/**/*.spec.ts", "/**/mocks"],
"jsc": {
"target": "esnext",

View File

@@ -1,7 +1,7 @@
{
"name": "@payloadcms/plugin-cloud",
"description": "The official Payload Cloud plugin",
"version": "3.0.0-alpha.41",
"version": "3.0.0-alpha.45",
"main": "dist/index.js",
"types": "dist/index.d.ts",
"license": "MIT",

View File

@@ -1,6 +1,6 @@
{
"$schema": "https://json.schemastore.org/swcrc",
"sourceMaps": "inline",
"sourceMaps": true,
"exclude": ["/**/mocks"],
"jsc": {
"target": "esnext",

View File

@@ -18,7 +18,7 @@
"test": "echo \"No tests available.\""
},
"peerDependencies": {
"payload": "^0.18.5 || ^1.0.0 || ^2.0.0",
"payload": "workspace:*",
"react": "^16.8.0 || ^17.0.0 || ^18.0.0"
},
"dependencies": {

View File

@@ -1,4 +1,4 @@
import type { PluginConfig } from '../../../types'
import type { PluginConfig } from '../../../types.js'
const createCharge = async (beforeChangeData: any, formConfig: PluginConfig): Promise<any> => {
const { data, operation } = beforeChangeData

View File

@@ -1,8 +1,8 @@
import type { Email, FormattedEmail, PluginConfig } from '../../../types'
import type { Email, FormattedEmail, PluginConfig } from '../../../types.js'
import { serializeLexical } from '../../../utilities/lexical/serializeLexical'
import { replaceDoubleCurlys } from '../../../utilities/replaceDoubleCurlys'
import { serializeSlate } from '../../../utilities/slate/serializeSlate'
import { serializeLexical } from '../../../utilities/lexical/serializeLexical.js'
import { replaceDoubleCurlys } from '../../../utilities/replaceDoubleCurlys.js'
import { serializeSlate } from '../../../utilities/slate/serializeSlate.js'
const sendEmail = async (beforeChangeData: any, formConfig: PluginConfig): Promise<any> => {
const { data, operation, req } = beforeChangeData

View File

@@ -1,9 +1,9 @@
import type { CollectionConfig } from 'payload/types'
import type { PluginConfig } from '../../types'
import type { PluginConfig } from '../../types.js'
import createCharge from './hooks/createCharge'
import sendEmail from './hooks/sendEmail'
import createCharge from './hooks/createCharge.js'
import sendEmail from './hooks/sendEmail.js'
// all settings can be overridden by the config
export const generateSubmissionCollection = (formConfig: PluginConfig): CollectionConfig => {
@@ -31,7 +31,7 @@ export const generateSubmissionCollection = (formConfig: PluginConfig): Collecti
},
relationTo: formSlug,
required: true,
validate: async (value, { payload, req }) => {
validate: async (value, { req: { payload }, req }) => {
/* Don't run in the client side */
if (!payload) return true

View File

@@ -34,5 +34,7 @@ export const DynamicFieldSelector: React.FC<TextField> = (props) => {
}
}, [fields, getDataByPath])
// TODO: label from config is Record<string, string> | false | string
// but the FormFieldBase type has only label?: string, changing FormFieldBase breaks other ui components
return <Select {...props} options={options} />
}

View File

@@ -1,39 +1,41 @@
import type { Block, Field } from 'payload/types'
import type { FieldConfig, PaymentFieldConfig } from '../../types'
import type { FieldConfig, PaymentFieldConfig } from '../../types.js'
import { DynamicFieldSelector } from './DynamicFieldSelector'
import { DynamicPriceSelector } from './DynamicPriceSelector'
import { DynamicFieldSelector } from './DynamicFieldSelector.js'
import { DynamicPriceSelector } from './DynamicPriceSelector.js'
const name: Field = {
name: 'name',
type: 'text',
label: 'Name (lowercase, no special characters)',
required: true,
type: 'text',
}
const label: Field = {
name: 'label',
type: 'text',
label: 'Label',
localized: true,
type: 'text',
}
const required: Field = {
name: 'required',
label: 'Required',
type: 'checkbox',
label: 'Required',
}
const width: Field = {
name: 'width',
label: 'Field Width (percentage)',
type: 'number',
label: 'Field Width (percentage)',
}
const Select: Block = {
slug: 'select',
fields: [
{
type: 'row',
fields: [
{
...name,
@@ -48,9 +50,9 @@ const Select: Block = {
},
},
],
type: 'row',
},
{
type: 'row',
fields: [
{
...width,
@@ -60,42 +62,42 @@ const Select: Block = {
},
{
name: 'defaultValue',
type: 'text',
admin: {
width: '50%',
},
label: 'Default Value',
localized: true,
type: 'text',
},
],
type: 'row',
},
{
name: 'options',
type: 'array',
fields: [
{
type: 'row',
fields: [
{
name: 'label',
type: 'text',
admin: {
width: '50%',
},
label: 'Label',
localized: true,
required: true,
type: 'text',
},
{
name: 'value',
type: 'text',
admin: {
width: '50%',
},
label: 'Value',
required: true,
type: 'text',
},
],
type: 'row',
},
],
label: 'Select Attribute Options',
@@ -103,7 +105,6 @@ const Select: Block = {
plural: 'Options',
singular: 'Option',
},
type: 'array',
},
required,
],
@@ -111,12 +112,13 @@ const Select: Block = {
plural: 'Select Fields',
singular: 'Select',
},
slug: 'select',
}
const Text: Block = {
slug: 'text',
fields: [
{
type: 'row',
fields: [
{
...name,
@@ -131,9 +133,9 @@ const Text: Block = {
},
},
],
type: 'row',
},
{
type: 'row',
fields: [
{
...width,
@@ -143,15 +145,14 @@ const Text: Block = {
},
{
name: 'defaultValue',
type: 'text',
admin: {
width: '50%',
},
label: 'Default Value',
localized: true,
type: 'text',
},
],
type: 'row',
},
required,
],
@@ -159,12 +160,13 @@ const Text: Block = {
plural: 'Text Fields',
singular: 'Text',
},
slug: 'text',
}
const TextArea: Block = {
slug: 'textarea',
fields: [
{
type: 'row',
fields: [
{
...name,
@@ -179,9 +181,9 @@ const TextArea: Block = {
},
},
],
type: 'row',
},
{
type: 'row',
fields: [
{
...width,
@@ -191,15 +193,14 @@ const TextArea: Block = {
},
{
name: 'defaultValue',
type: 'text',
admin: {
width: '50%',
},
label: 'Default Value',
localized: true,
type: 'text',
},
],
type: 'row',
},
required,
],
@@ -207,12 +208,13 @@ const TextArea: Block = {
plural: 'Text Area Fields',
singular: 'Text Area',
},
slug: 'textarea',
}
const Number: Block = {
slug: 'number',
fields: [
{
type: 'row',
fields: [
{
...name,
@@ -227,9 +229,9 @@ const Number: Block = {
},
},
],
type: 'row',
},
{
type: 'row',
fields: [
{
...width,
@@ -239,14 +241,13 @@ const Number: Block = {
},
{
name: 'defaultValue',
type: 'number',
admin: {
width: '50%',
},
label: 'Default Value',
type: 'number',
},
],
type: 'row',
},
required,
],
@@ -254,12 +255,13 @@ const Number: Block = {
plural: 'Number Fields',
singular: 'Number',
},
slug: 'number',
}
const Email: Block = {
slug: 'email',
fields: [
{
type: 'row',
fields: [
{
...name,
@@ -274,7 +276,6 @@ const Email: Block = {
},
},
],
type: 'row',
},
width,
required,
@@ -283,12 +284,13 @@ const Email: Block = {
plural: 'Email Fields',
singular: 'Email',
},
slug: 'email',
}
const State: Block = {
slug: 'state',
fields: [
{
type: 'row',
fields: [
{
...name,
@@ -303,7 +305,6 @@ const State: Block = {
},
},
],
type: 'row',
},
width,
required,
@@ -312,12 +313,13 @@ const State: Block = {
plural: 'State Fields',
singular: 'State',
},
slug: 'state',
}
const Country: Block = {
slug: 'country',
fields: [
{
type: 'row',
fields: [
{
...name,
@@ -332,7 +334,6 @@ const Country: Block = {
},
},
],
type: 'row',
},
width,
required,
@@ -341,12 +342,13 @@ const Country: Block = {
plural: 'Country Fields',
singular: 'Country',
},
slug: 'country',
}
const Checkbox: Block = {
slug: 'checkbox',
fields: [
{
type: 'row',
fields: [
{
...name,
@@ -361,9 +363,9 @@ const Checkbox: Block = {
},
},
],
type: 'row',
},
{
type: 'row',
fields: [
{
...width,
@@ -378,19 +380,17 @@ const Checkbox: Block = {
},
},
],
type: 'row',
},
{
name: 'defaultValue',
label: 'Default Value',
type: 'checkbox',
label: 'Default Value',
},
],
labels: {
plural: 'Checkbox Fields',
singular: 'Checkbox',
},
slug: 'checkbox',
}
const Payment = (fieldConfig: PaymentFieldConfig): Block => {
@@ -398,16 +398,18 @@ const Payment = (fieldConfig: PaymentFieldConfig): Block => {
if (fieldConfig?.paymentProcessor) {
paymentProcessorField = {
name: 'paymentProcessor',
type: 'select',
label: 'Payment Processor',
options: [],
type: 'select',
...fieldConfig.paymentProcessor,
}
}
const fields = {
slug: 'payment',
fields: [
{
type: 'row',
fields: [
{
...name,
@@ -422,9 +424,9 @@ const Payment = (fieldConfig: PaymentFieldConfig): Block => {
},
},
],
type: 'row',
},
{
type: 'row',
fields: [
{
...width,
@@ -434,30 +436,31 @@ const Payment = (fieldConfig: PaymentFieldConfig): Block => {
},
{
name: 'basePrice',
type: 'number',
admin: {
width: '50%',
},
label: 'Base Price',
type: 'number',
},
],
type: 'row',
},
paymentProcessorField,
{
name: 'priceConditions',
type: 'array',
fields: [
{
name: 'fieldToUse',
type: 'text',
admin: {
components: {
Field: DynamicFieldSelector,
},
},
type: 'text',
},
{
name: 'condition',
type: 'select',
defaultValue: 'hasValue',
label: 'Condition',
options: [
@@ -474,19 +477,19 @@ const Payment = (fieldConfig: PaymentFieldConfig): Block => {
value: 'notEquals',
},
],
type: 'select',
},
{
name: 'valueForCondition',
type: 'text',
admin: {
condition: (_: any, { condition }: any) =>
condition === 'equals' || condition === 'notEquals',
},
label: 'Value',
type: 'text',
},
{
name: 'operator',
type: 'select',
defaultValue: 'add',
options: [
{
@@ -506,10 +509,10 @@ const Payment = (fieldConfig: PaymentFieldConfig): Block => {
value: 'divide',
},
],
type: 'select',
},
{
name: 'valueType',
type: 'radio',
admin: {
width: '100%',
},
@@ -525,17 +528,16 @@ const Payment = (fieldConfig: PaymentFieldConfig): Block => {
value: 'valueOfField',
},
],
type: 'radio',
},
{
name: 'valueForOperator',
type: 'text',
admin: {
components: {
Field: DynamicPriceSelector,
},
},
label: 'Value',
type: 'text',
},
],
label: 'Price Conditions',
@@ -543,7 +545,6 @@ const Payment = (fieldConfig: PaymentFieldConfig): Block => {
plural: 'Price Conditions',
singular: 'Price Condition',
},
type: 'array',
},
required,
].filter(Boolean) as Field[],
@@ -551,25 +552,24 @@ const Payment = (fieldConfig: PaymentFieldConfig): Block => {
plural: 'Payment Fields',
singular: 'Payment',
},
slug: 'payment',
}
return fields
}
const Message: Block = {
slug: 'message',
fields: [
{
name: 'message',
localized: true,
type: 'richText',
localized: true,
},
],
labels: {
plural: 'Message Blocks',
singular: 'Message',
},
slug: 'message',
}
// eslint-disable-next-line @typescript-eslint/consistent-type-assertions

View File

@@ -2,14 +2,15 @@ import type { Block, CollectionConfig, Field } from 'payload/types'
import merge from 'deepmerge'
import type { FieldConfig, PluginConfig } from '../../types'
import type { FieldConfig, PluginConfig } from '../../types.js'
import { fields } from './fields'
import { fields } from './fields.js'
// all settings can be overridden by the config
export const generateFormCollection = (formConfig: PluginConfig): CollectionConfig => {
const redirect: Field = {
name: 'redirect',
type: 'group',
admin: {
condition: (_, siblingData) => siblingData?.confirmationType === 'redirect',
hideGutter: true,
@@ -17,17 +18,17 @@ export const generateFormCollection = (formConfig: PluginConfig): CollectionConf
fields: [
{
name: 'url',
type: 'text',
label: 'URL to redirect to',
required: true,
type: 'text',
},
],
type: 'group',
}
if (formConfig.redirectRelationships) {
redirect.fields.unshift({
name: 'reference',
type: 'relationship',
admin: {
condition: (_, siblingData) => siblingData?.type === 'reference',
},
@@ -35,11 +36,11 @@ export const generateFormCollection = (formConfig: PluginConfig): CollectionConf
maxDepth: 2,
relationTo: formConfig.redirectRelationships,
required: true,
type: 'relationship',
})
redirect.fields.unshift({
name: 'type',
type: 'radio',
admin: {
layout: 'horizontal',
},
@@ -54,7 +55,6 @@ export const generateFormCollection = (formConfig: PluginConfig): CollectionConf
value: 'custom',
},
],
type: 'radio',
})
if (redirect.fields[2].type !== 'row') redirect.fields[2].label = 'Custom URL'
@@ -66,6 +66,7 @@ export const generateFormCollection = (formConfig: PluginConfig): CollectionConf
const config: CollectionConfig = {
...(formConfig?.formOverrides || {}),
slug: formConfig?.formOverrides?.slug || 'forms',
access: {
read: () => true,
...(formConfig?.formOverrides?.access || {}),
@@ -78,11 +79,12 @@ export const generateFormCollection = (formConfig: PluginConfig): CollectionConf
fields: [
{
name: 'title',
required: true,
type: 'text',
required: true,
},
{
name: 'fields',
type: 'blocks',
blocks: Object.entries(formConfig?.fields || {})
.map(([fieldKey, fieldConfig]) => {
// let the config enable/disable fields with either boolean values or objects
@@ -109,15 +111,15 @@ export const generateFormCollection = (formConfig: PluginConfig): CollectionConf
return null
})
.filter(Boolean) as Block[],
type: 'blocks',
},
{
name: 'submitButtonLabel',
localized: true,
type: 'text',
localized: true,
},
{
name: 'confirmationType',
type: 'radio',
admin: {
description:
'Choose whether to display an on-page message or redirect to a different page after they submit the form.',
@@ -134,101 +136,99 @@ export const generateFormCollection = (formConfig: PluginConfig): CollectionConf
value: 'redirect',
},
],
type: 'radio',
},
{
name: 'confirmationMessage',
type: 'richText',
admin: {
condition: (_, siblingData) => siblingData?.confirmationType === 'message',
},
localized: true,
required: true,
type: 'richText',
},
redirect,
{
name: 'emails',
type: 'array',
admin: {
description:
"Send custom emails when the form submits. Use comma separated lists to send the same email to multiple recipients. To reference a value from this form, wrap that field's name with double curly brackets, i.e. {{firstName}}.",
},
fields: [
{
type: 'row',
fields: [
{
name: 'emailTo',
type: 'text',
admin: {
placeholder: '"Email Sender" <sender@email.com>',
width: '100%',
},
label: 'Email To',
type: 'text',
},
{
name: 'cc',
type: 'text',
admin: {
width: '50%',
},
label: 'CC',
type: 'text',
},
{
name: 'bcc',
type: 'text',
admin: {
width: '50%',
},
label: 'BCC',
type: 'text',
},
],
type: 'row',
},
{
type: 'row',
fields: [
{
name: 'replyTo',
type: 'text',
admin: {
placeholder: '"Reply To" <reply-to@email.com>',
width: '50%',
},
label: 'Reply To',
type: 'text',
},
{
name: 'emailFrom',
type: 'text',
admin: {
placeholder: '"Email From" <email-from@email.com>',
width: '50%',
},
label: 'Email From',
type: 'text',
},
],
type: 'row',
},
{
name: 'subject',
type: 'text',
defaultValue: "You've received a new message.",
label: 'Subject',
localized: true,
required: true,
type: 'text',
},
{
name: 'message',
type: 'richText',
admin: {
description: 'Enter the message that should be sent in this email.',
},
label: 'Message',
localized: true,
type: 'richText',
},
],
type: 'array',
},
...(formConfig?.formOverrides?.fields || []),
],
slug: formConfig?.formOverrides?.slug || 'forms',
}
return config

View File

@@ -1,6 +1,6 @@
{
"$schema": "https://json.schemastore.org/swcrc",
"sourceMaps": "inline",
"sourceMaps": true,
"jsc": {
"target": "esnext",
"parser": {

View File

@@ -1,6 +1,6 @@
{
"name": "@payloadcms/plugin-nested-docs",
"version": "1.0.12",
"version": "3.0.0-alpha.45",
"description": "The official Nested Docs plugin for Payload",
"repository": "https://github.com/payloadcms/payload",
"license": "MIT",
@@ -22,7 +22,7 @@
"payload": "workspace:*"
},
"peerDependencies": {
"payload": "^0.18.5 || ^1.0.0 || ^2.0.0"
"payload": "workspace:*"
},
"exports": {
".": {

View File

@@ -1,8 +1,8 @@
import type { CollectionAfterChangeHook, CollectionConfig, PayloadRequest } from 'payload/types'
import type { PluginConfig } from '../types'
import type { PluginConfig } from '../types.js'
import populateBreadcrumbs from '../utilities/populateBreadcrumbs'
import populateBreadcrumbs from '../utilities/populateBreadcrumbs.js'
type ResaveArgs = {
collection: CollectionConfig

View File

@@ -1,6 +1,6 @@
import type { CollectionAfterChangeHook, CollectionConfig } from 'payload/types'
import type { PluginConfig } from '../types'
import type { PluginConfig } from '../types.js'
// This hook automatically re-saves a document after it is created
// so that we can build its breadcrumbs with the newly created document's ID.

View File

@@ -1,14 +1,14 @@
import type { Plugin } from 'payload/config'
import type { SingleRelationshipField } from 'payload/types'
import type { PluginConfig } from './types'
import type { PluginConfig } from './types.js'
import createBreadcrumbsField from './fields/breadcrumbs'
import createParentField from './fields/parent'
import parentFilterOptions from './fields/parentFilterOptions'
import resaveChildren from './hooks/resaveChildren'
import resaveSelfAfterCreate from './hooks/resaveSelfAfterCreate'
import populateBreadcrumbs from './utilities/populateBreadcrumbs'
import createBreadcrumbsField from './fields/breadcrumbs.js'
import createParentField from './fields/parent.js'
import parentFilterOptions from './fields/parentFilterOptions.js'
import resaveChildren from './hooks/resaveChildren.js'
import resaveSelfAfterCreate from './hooks/resaveSelfAfterCreate.js'
import populateBreadcrumbs from './utilities/populateBreadcrumbs.js'
const nestedDocs =
(pluginConfig: PluginConfig): Plugin =>

View File

@@ -1,6 +1,6 @@
import type { CollectionConfig } from 'payload/types'
import type { Breadcrumb, PluginConfig } from '../types'
import type { Breadcrumb, PluginConfig } from '../types.js'
const formatBreadcrumb = (
pluginConfig: PluginConfig,
@@ -24,9 +24,9 @@ const formatBreadcrumb = (
}
return {
doc: lastDoc.id as string,
label,
url,
doc: lastDoc.id as string,
}
}

View File

@@ -1,6 +1,6 @@
import type { CollectionConfig } from 'payload/types'
import type { PluginConfig } from '../types'
import type { PluginConfig } from '../types.js'
const getParents = async (
req: any,

View File

@@ -1,9 +1,9 @@
import type { CollectionConfig } from 'payload/types'
import type { PluginConfig } from '../types'
import type { PluginConfig } from '../types.js'
import formatBreadcrumb from './formatBreadcrumb'
import getParents from './getParents'
import formatBreadcrumb from './formatBreadcrumb.js'
import getParents from './getParents.js'
const populateBreadcrumbs = async (
req: any,

View File

@@ -1,6 +1,6 @@
{
"$schema": "https://json.schemastore.org/swcrc",
"sourceMaps": "inline",
"sourceMaps": true,
"jsc": {
"target": "esnext",
"parser": {

View File

@@ -1,6 +1,6 @@
{
"name": "@payloadcms/plugin-redirects",
"version": "1.0.1",
"version": "3.0.0-alpha.45",
"homepage:": "https://payloadcms.com",
"repository": "git@github.com:payloadcms/plugin-redirects.git",
"description": "Redirects plugin for Payload",
@@ -27,7 +27,7 @@
"author": "dev@payloadcms.com",
"license": "MIT",
"peerDependencies": {
"payload": "^0.18.5 || ^1.0.0 || ^2.0.0"
"payload": "workspace:*"
},
"devDependencies": {
"@payloadcms/eslint-config": "workspace:*",

View File

@@ -1,8 +1,8 @@
import type { Config } from 'payload/config'
import type { PluginConfig } from './types'
import type { PluginConfig } from './types.js'
import deepMerge from './deepMerge'
import deepMerge from './deepMerge.js'
const redirects =
(pluginConfig: PluginConfig) =>
@@ -12,6 +12,7 @@ const redirects =
...(incomingConfig?.collections || []),
deepMerge(
{
slug: 'redirects',
access: {
read: (): boolean => true,
},
@@ -21,16 +22,18 @@ const redirects =
fields: [
{
name: 'from',
type: 'text',
index: true,
label: 'From URL',
required: true,
type: 'text',
},
{
name: 'to',
type: 'group',
fields: [
{
name: 'type',
type: 'radio',
admin: {
layout: 'horizontal',
},
@@ -46,33 +49,30 @@ const redirects =
value: 'custom',
},
],
type: 'radio',
},
{
name: 'reference',
type: 'relationship',
admin: {
condition: (_, siblingData) => siblingData?.type === 'reference',
},
label: 'Document to redirect to',
relationTo: pluginConfig?.collections || [],
required: true,
type: 'relationship',
},
{
name: 'url',
type: 'text',
admin: {
condition: (_, siblingData) => siblingData?.type === 'custom',
},
label: 'Custom URL',
required: true,
type: 'text',
},
],
label: false,
type: 'group',
},
],
slug: 'redirects',
},
pluginConfig?.overrides || {},
),

View File

@@ -1,6 +1,6 @@
{
"$schema": "https://json.schemastore.org/swcrc",
"sourceMaps": "inline",
"sourceMaps": true,
"jsc": {
"target": "esnext",
"parser": {

View File

@@ -1,6 +1,6 @@
{
"name": "@payloadcms/plugin-search",
"version": "1.1.0",
"version": "3.0.0-alpha.45",
"homepage:": "https://payloadcms.com",
"repository": "git@github.com:payloadcms/plugin-search.git",
"description": "Search plugin for Payload",
@@ -27,12 +27,12 @@
"author": "dev@trbl.design",
"license": "MIT",
"peerDependencies": {
"payload": "^0.18.5 || ^1.0.0 || ^2.0.0",
"payload": "workspace:*",
"react": "^16.8.0 || ^17.0.0 || ^18.0.0"
},
"dependencies": {
"@payloadcms/ui": "workspace:*",
"ts-deepmerge": "^2.0.1"
"deepmerge": "4.3.1"
},
"devDependencies": {
"@payloadcms/eslint-config": "workspace:*",

View File

@@ -1,4 +1,4 @@
import type { DocToSync, SearchConfig, SyncWithSearch } from '../../types'
import type { DocToSync, SearchConfig, SyncWithSearch } from '../../types.js'
const syncWithSearch: SyncWithSearch = async (args) => {
const {

View File

@@ -1,15 +1,16 @@
import type { CollectionConfig } from 'payload/types'
import deepMerge from 'ts-deepmerge'
import deepMerge from 'deepmerge'
import type { SearchConfig } from '../types'
import type { SearchConfig } from '../types.js'
import { LinkToDoc } from './ui'
import { LinkToDoc } from './ui/index.js'
// all settings can be overridden by the config
export const generateSearchCollection = (searchConfig: SearchConfig): CollectionConfig =>
deepMerge(
{
slug: 'search',
access: {
create: (): boolean => false,
read: (): boolean => true,
@@ -24,20 +25,21 @@ export const generateSearchCollection = (searchConfig: SearchConfig): Collection
fields: [
{
name: 'title',
type: 'text',
admin: {
readOnly: true,
},
type: 'text',
},
{
name: 'priority',
type: 'number',
admin: {
position: 'sidebar',
},
type: 'number',
},
{
name: 'doc',
type: 'relationship',
admin: {
position: 'sidebar',
readOnly: true,
@@ -46,24 +48,22 @@ export const generateSearchCollection = (searchConfig: SearchConfig): Collection
maxDepth: 0,
relationTo: searchConfig?.collections || [],
required: true,
type: 'relationship',
},
{
name: 'docUrl',
type: 'ui',
admin: {
components: {
Field: LinkToDoc,
},
position: 'sidebar',
},
type: 'ui',
},
],
labels: {
plural: 'Search Results',
singular: 'Search Result',
},
slug: 'search',
},
searchConfig?.searchOverrides || {},
)

View File

@@ -1,5 +1,4 @@
import type { FormState } from '@payloadcms/ui'
import type { UIField } from 'payload/types'
import type { FormState, UIField } from 'payload/types'
import { useConfig, useWatchForm } from '@payloadcms/ui'
import React from 'react'

View File

@@ -1,10 +1,10 @@
import type { Config } from 'payload/config'
import type { SearchConfig } from './types'
import type { SearchConfig } from './types.js'
import { generateSearchCollection } from './Search'
import deleteFromSearch from './Search/hooks/deleteFromSearch'
import syncWithSearch from './Search/hooks/syncWithSearch'
import deleteFromSearch from './Search/hooks/deleteFromSearch.js'
import syncWithSearch from './Search/hooks/syncWithSearch.js'
import { generateSearchCollection } from './Search/index.js'
const Search =
(incomingSearchConfig: SearchConfig) =>

View File

@@ -1,6 +1,6 @@
{
"$schema": "https://json.schemastore.org/swcrc",
"sourceMaps": "inline",
"sourceMaps": true,
"exclude": ["/**/*.spec.ts"],
"jsc": {
"target": "esnext",

View File

@@ -28,7 +28,7 @@
"dist"
],
"peerDependencies": {
"payload": "^1.10.1 || ^2.0.0",
"payload": "workspace:*",
"react": "^16.8.0 || ^17.0.0 || ^18.0.0"
},
"dependencies": {

View File

@@ -1,6 +1,6 @@
{
"$schema": "https://json.schemastore.org/swcrc",
"sourceMaps": "inline",
"sourceMaps": true,
"jsc": {
"target": "esnext",
"parser": {

View File

@@ -1,6 +1,6 @@
{
"name": "@payloadcms/plugin-seo",
"version": "3.0.0-alpha.41",
"version": "3.0.0-alpha.45",
"homepage:": "https://payloadcms.com",
"repository": "git@github.com:payloadcms/plugin-seo.git",
"description": "SEO plugin for Payload",

View File

@@ -1,6 +1,6 @@
{
"$schema": "https://json.schemastore.org/swcrc",
"sourceMaps": "inline",
"sourceMaps": true,
"jsc": {
"target": "esnext",
"parser": {

View File

@@ -29,7 +29,7 @@
"author": "dev@payloadcms.com",
"license": "MIT",
"peerDependencies": {
"payload": "^1.1.8 || ^2.0.0"
"payload": "workspace:*"
},
"dependencies": {
"@payloadcms/ui": "workspace:*",

View File

@@ -1,6 +1,6 @@
{
"$schema": "https://json.schemastore.org/swcrc",
"sourceMaps": "inline",
"sourceMaps": true,
"jsc": {
"target": "esnext",
"parser": {

View File

@@ -1,6 +1,6 @@
{
"name": "@payloadcms/richtext-lexical",
"version": "3.0.0-alpha.41",
"version": "3.0.0-alpha.45",
"description": "The officially supported Lexical richtext adapter for Payload",
"repository": "https://github.com/payloadcms/payload",
"license": "MIT",

View File

@@ -1,6 +1,6 @@
{
"$schema": "https://json.schemastore.org/swcrc",
"sourceMaps": "inline",
"sourceMaps": true,
"jsc": {
"target": "esnext",
"parser": {

View File

@@ -1,6 +1,6 @@
{
"name": "@payloadcms/richtext-slate",
"version": "3.0.0-alpha.41",
"version": "3.0.0-alpha.45",
"description": "The officially supported Slate richtext adapter for Payload",
"repository": "https://github.com/payloadcms/payload",
"license": "MIT",

View File

@@ -1,6 +1,6 @@
{
"$schema": "https://json.schemastore.org/swcrc",
"sourceMaps": "inline",
"sourceMaps": true,
"jsc": {
"target": "esnext",
"parser": {

View File

@@ -1,6 +1,6 @@
{
"name": "@payloadcms/translations",
"version": "3.0.0-alpha.41",
"version": "3.0.0-alpha.45",
"main": "./dist/exports/index.ts",
"types": "./dist/types.d.ts",
"type": "module",

View File

@@ -1,12 +1,22 @@
{
"$schema": "https://json.schemastore.org/swcrc",
"sourceMaps": "inline",
"sourceMaps": true,
"jsc": {
"target": "esnext",
"parser": {
"syntax": "typescript",
"tsx": true,
"dts": true
},
"experimental": {
"plugins": [
[
"swc-plugin-transform-remove-imports",
{
"test": "\\.(scss|css)$"
}
]
]
}
},
"module": {

View File

@@ -1,13 +1,14 @@
{
"name": "@payloadcms/ui",
"version": "3.0.0-alpha.41",
"version": "3.0.0-alpha.45",
"main": "./src/index.ts",
"types": "./dist/index.d.ts",
"type": "module",
"scripts": {
"build": "pnpm copyfiles && pnpm build:swc && pnpm build:types",
"build": "pnpm copyfiles && pnpm build:swc && pnpm build:types && pnpm build:webpack && rm dist/prod/index.js",
"build:swc": "swc ./src -d ./dist --config-file .swcrc",
"build:types": "tsc --emitDeclarationOnly --outDir dist",
"build:webpack": "webpack --config webpack.config.js",
"clean": "rimraf {dist,*.tsbuildinfo}",
"copyfiles": "copyfiles -u 1 \"src/**/*.{html,css,scss,ttf,woff,woff2,eot,svg,jpg,png,json}\" dist/",
"fix": "eslint \"src/**/*.{ts,tsx}\" --fix",
@@ -37,6 +38,11 @@
"require": "./dist/exports/*.js",
"types": "./dist/exports/*.d.ts"
},
"./css": {
"import": "./dist/prod/styles.css",
"require": "./dist/prod/styles.css",
"default": "./dist/prod/styles.css"
},
"./scss": {
"import": "./dist/scss.scss",
"require": "./dist/scss.scss",
@@ -54,7 +60,18 @@
"@types/react-datepicker": "4.11.2",
"@types/react-dom": "18.2.7",
"@types/uuid": "8.3.4",
"payload": "workspace:*"
"postcss-loader": "^8.1.1",
"postcss-preset-env": "^9.5.0",
"sass-loader": "^14.1.1",
"swc-loader": "^0.2.6",
"swc-plugin-transform-remove-imports": "^1.12.1",
"css-loader": "^6.10.0",
"css-minimizer-webpack-plugin": "^6.0.0",
"mini-css-extract-plugin": "1.6.2",
"payload": "workspace:*",
"terser-webpack-plugin": "^5.3.10",
"webpack": "^5.78.0",
"webpack-cli": "^5.1.4"
},
"dependencies": {
"@dnd-kit/core": "6.0.8",

View File

@@ -51,9 +51,7 @@ export const AuthProvider: React.FC<{ children: React.ReactNode }> = ({ children
const redirectToInactivityRoute = useCallback(() => {
if (window.location.pathname.startsWith(admin)) {
const redirectParam = `?redirect=${encodeURIComponent(
window.location.pathname.replace(admin, ''),
)}`
const redirectParam = `?redirect=${encodeURIComponent(window.location.pathname)}`
router.replace(`${admin}${logoutInactivityRoute}${redirectParam}`)
} else {
router.replace(`${admin}${logoutInactivityRoute}`)

View File

@@ -1,8 +1,10 @@
@import '../../scss/styles.scss';
.template-default {
[dir='rtl']
&__nav-toggler-wrapper {
background-color: var(--theme-bg);
color: var(--theme-text);
[dir='rtl'] &__nav-toggler-wrapper {
left: unset;
right: 0;
}

View File

@@ -9,6 +9,8 @@
margin-left: auto;
margin-right: auto;
min-height: 100%;
background-color: var(--theme-bg-color);
color: var(--theme-text);
&--width-normal {
.template-minimal__wrap {

View File

@@ -0,0 +1,107 @@
import OptimizeCSSAssetsPlugin from 'css-minimizer-webpack-plugin'
import MiniCSSExtractPlugin from 'mini-css-extract-plugin'
import path from 'path'
import TerserJSPlugin from 'terser-webpack-plugin'
import { fileURLToPath } from 'url'
import webpack from 'webpack'
const filename = fileURLToPath(import.meta.url)
const dirname = path.dirname(filename)
const componentWebpackConfig = {
entry: path.resolve(dirname, './src/index.ts'),
externals: ['react', 'react-dom', 'payload', 'payload/config', 'react-image-crop'],
mode: 'production',
module: {
rules: [
{
oneOf: [
{
// exclude: /node_modules/,
test: /\.(t|j)sx?$/,
use: [
{
loader: 'swc-loader',
options: {
jsc: {
experimental: {
plugins: [
// clear the plugins used in .swcrc
],
},
parser: {
syntax: 'typescript',
tsx: true,
},
},
},
},
],
},
{
sideEffects: true,
test: /\.(scss|css)$/,
use: [
MiniCSSExtractPlugin.loader,
'css-loader',
{
loader: 'postcss-loader',
options: {
postcssOptions: {
plugins: ['postcss-preset-env'],
},
},
},
'sass-loader',
],
},
{
type: 'asset/resource',
generator: {
filename: 'payload/[name][ext]',
},
test: [/\.bmp$/, /\.gif$/, /\.jpe?g$/, /\.png$/, /\.svg$/, /\.woff$/, /\.woff2$/],
},
],
},
],
},
optimization: {
minimizer: [
new TerserJSPlugin({
extractComments: false,
}),
new OptimizeCSSAssetsPlugin({}),
],
},
output: {
filename: 'index.js',
libraryTarget: 'commonjs2',
path: path.resolve(dirname, './dist/prod'),
publicPath: '/',
},
plugins: [
new MiniCSSExtractPlugin({
filename: 'styles.css',
ignoreOrder: true,
}),
new webpack.optimize.LimitChunkCountPlugin({
maxChunks: 1,
}),
],
resolve: {
extensionAlias: {
'.js': ['.ts', '.tsx', '.js', '.scss', '.css'],
'.mjs': ['.mts', '.mjs'],
},
extensions: ['.js', '.ts', '.tsx', '.scss', '.css'],
modules: [
'node_modules',
path.resolve(dirname, '../../node_modules'),
path.resolve(dirname, './node_modules'),
],
},
stats: 'errors-only',
}
export default componentWebpackConfig

Binary file not shown.

Binary file not shown.

1796
pnpm-lock.yaml generated

File diff suppressed because it is too large Load Diff

View File

@@ -1,18 +1,18 @@
import type { ExecSyncOptions } from 'child_process'
import { execSync } from 'child_process'
import chalk from 'chalk'
import { execSync } from 'child_process'
import execa from 'execa'
import fse from 'fs-extra'
import minimist from 'minimist'
import { fileURLToPath } from 'node:url'
import path from 'path'
import prompts from 'prompts'
import semver from 'semver'
import simpleGit from 'simple-git'
import { simpleGit } from 'simple-git'
import { getPackageDetails } from './lib/getPackageDetails'
import { updateChangelog } from './utils/updateChangelog'
import { fileURLToPath } from 'url'
import { getPackageDetails } from './lib/getPackageDetails.js'
import { updateChangelog } from './utils/updateChangelog.js'
// Update this list with any packages to publish
const packageWhitelist = [
@@ -27,7 +27,13 @@ const packageWhitelist = [
'richtext-lexical',
'plugin-cloud',
'plugin-cloud-storage',
// 'plugin-form-builder',
'plugin-nested-docs',
'plugin-redirects',
'plugin-search',
// 'plugin-sentry',
'plugin-seo',
// 'plugin-stripe',
]
const __filename = fileURLToPath(import.meta.url)
@@ -37,6 +43,8 @@ const cwd = path.resolve(__dirname, '..')
const git = simpleGit(cwd)
const execOpts: ExecSyncOptions = { stdio: 'inherit' }
const execaOpts: execa.Options = { stdio: 'inherit' }
const args = minimist(process.argv.slice(2))
const {
@@ -128,8 +136,6 @@ async function main() {
// Prebuild all packages
header(`\n🔨 Prebuilding all packages...`)
const execaOpts: execa.Options = { ...execOpts, stdio: 'inherit' }
await execa('pnpm', ['install'], execaOpts)
const buildResult = await execa('pnpm', ['build:core', '--output-logs=errors-only'], execaOpts)

View File

@@ -7,7 +7,6 @@ import { fileURLToPath } from 'url'
import { initPageConsoleErrorCatch } from '../helpers.js'
import { AdminUrlUtil } from '../helpers/adminUrlUtil.js'
import { initPayloadE2E } from '../helpers/configHelpers.js'
import config from './config.js'
const filename = fileURLToPath(import.meta.url)
const dirname = path.dirname(filename)
@@ -19,7 +18,7 @@ describe('Admin Panel', () => {
let url: AdminUrlUtil
beforeAll(async ({ browser }) => {
const { serverURL } = await initPayloadE2E({ config, dirname })
const { serverURL } = await initPayloadE2E({ dirname })
url = new AdminUrlUtil(serverURL, 'posts')
const context = await browser.newContext()

View File

@@ -1 +0,0 @@
import '@testing-library/jest-dom'

View File

@@ -1,37 +1,60 @@
import { spawn } from 'child_process'
import getPort from 'get-port'
//import { nextDev } from 'next/dist/cli/next-dev.js'
import { nextDev } from 'next/dist/cli/next-dev.js'
import path from 'path'
import type { SanitizedConfig } from '../../packages/payload/src/config/types.js'
import type { Payload } from '../../packages/payload/src/index.js'
import wait from '../../packages/payload/src/utilities/wait.js'
import { getPayload } from '../../packages/payload/src/index.js'
import { bootAdminPanel } from './bootAdminPanel.mjs'
type InitializedPayload = { payload: Payload; serverURL: string }
export async function initPayloadE2E(args: {
config: Promise<SanitizedConfig>
type Args = {
dirname: string
}): Promise<InitializedPayload> {
const { config, dirname } = args
}
console.log('dirname', dirname)
type Result = {
serverURL: string
}
// process.env.TURBOPACK = '1' // Not working due to turbopack pulling in mongoose, pg
export async function initPayloadE2E({ dirname }: Args): Promise<Result> {
const port = await getPort()
const serverURL = `http://localhost:${port}`
process.env.PAYLOAD_CONFIG_PATH = path.resolve(dirname, './config.js')
process.env.PAYLOAD_DROP_DATABASE = 'true'
//process.env.NODE_ENV = 'test'
process.env.PORT = String(port)
const payload = await getPayload({ config })
// @ts-expect-error
process.env.NODE_ENV = 'test'
nextDev({
_: [path.resolve(dirname, '../../')],
'--port': port,
// Turbo doesn't seem to be reading
// our tsconfig paths, commented out for now
// '--turbo': '1',
})
await wait(3000)
return { serverURL }
}
export async function initPayloadSpawn({ dirname }: Args): Promise<Result> {
const port = await getPort()
const serverURL = `http://localhost:${port}`
//process.env.APP_ENV = 'test'
//process.env.__NEXT_TEST_MODE = 'jest'
// Tried using a child process to get
// turbopack to pick up our tsconfig aliases
// but this didn't make a difference.
// Keeping it here so we can continue to try.
spawn('pnpm', ['dev', '--turbo'], {
cwd: path.resolve(dirname, '../../'),
env: {
...process.env,
NODE_ENV: 'test',
PORT: String(port),
PAYLOAD_CONFIG_PATH: path.resolve(dirname, '../../config.js'),
PAYLOAD_DROP_DATABASE: 'true',
},
})
//await nextDev({ _: [path.resolve(dirname, '../../')], port }) // Running nextDev directly does not work for ports other than 3000
await bootAdminPanel({ port, appDir: path.resolve(dirname, '../../') })
return { serverURL, payload }
await wait(3000)
return { serverURL }
}