Merge branch '2.0' of github.com:payloadcms/payload into 2.0
This commit is contained in:
@@ -18,14 +18,10 @@
|
|||||||
"fix": "eslint \"packages/**/*.ts\" --fix",
|
"fix": "eslint \"packages/**/*.ts\" --fix",
|
||||||
"lint": "eslint \"packages/**/*.ts\"",
|
"lint": "eslint \"packages/**/*.ts\"",
|
||||||
"lint-staged": "lint-staged",
|
"lint-staged": "lint-staged",
|
||||||
"release:beta": "release-it pre --preReleaseId=beta --npm.tag=beta --config .release-it.pre.json",
|
|
||||||
"release:canary": "release-it pre --preReleaseId=canary --npm.tag=canary --config .release-it.pre.json",
|
|
||||||
"release:major": "release-it major",
|
|
||||||
"release:minor": "release-it minor",
|
|
||||||
"release:patch": "release-it patch",
|
|
||||||
"pretest": "pnpm build",
|
"pretest": "pnpm build",
|
||||||
"reinstall": "./scripts/reinstall.sh",
|
"reinstall": "./scripts/reinstall.sh",
|
||||||
"release:list:beta": "./scripts/list_published_packages.sh beta",
|
"release:list:beta": "./scripts/list_published_packages.sh beta",
|
||||||
|
"script:release:beta": "./scripts/release_beta.sh",
|
||||||
"test": "pnpm test:int && pnpm test:components && pnpm test:e2e",
|
"test": "pnpm test:int && pnpm test:components && pnpm test:e2e",
|
||||||
"test:components": "cross-env jest --config=jest.components.config.js",
|
"test:components": "cross-env jest --config=jest.components.config.js",
|
||||||
"test:e2e": "npx playwright install --with-deps && ts-node -T ./test/runE2E.ts",
|
"test:e2e": "npx playwright install --with-deps && ts-node -T ./test/runE2E.ts",
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@payloadcms/bundler-vite",
|
"name": "@payloadcms/bundler-vite",
|
||||||
"version": "0.1.0-beta.4",
|
"version": "0.1.0-beta.6",
|
||||||
"description": "The officially supported Vite bundler adapter for Payload",
|
"description": "The officially supported Vite bundler adapter for Payload",
|
||||||
"repository": "https://github.com/payloadcms/payload",
|
"repository": "https://github.com/payloadcms/payload",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
@@ -44,6 +44,7 @@
|
|||||||
"types": "./dist/index.d.ts"
|
"types": "./dist/index.d.ts"
|
||||||
},
|
},
|
||||||
"files": [
|
"files": [
|
||||||
"dist"
|
"dist",
|
||||||
|
"mock.js"
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -9,7 +9,6 @@ import getPort from 'get-port'
|
|||||||
import path from 'path'
|
import path from 'path'
|
||||||
import virtual from 'vite-plugin-virtual'
|
import virtual from 'vite-plugin-virtual'
|
||||||
|
|
||||||
const bundlerPath = path.resolve(__dirname, './')
|
|
||||||
const mockModulePath = path.resolve(__dirname, './mocks/emptyModule.js')
|
const mockModulePath = path.resolve(__dirname, './mocks/emptyModule.js')
|
||||||
const mockDotENVPath = path.resolve(__dirname, './mocks/dotENV.js')
|
const mockDotENVPath = path.resolve(__dirname, './mocks/dotENV.js')
|
||||||
|
|
||||||
@@ -26,11 +25,10 @@ export const getViteConfig = async (payloadConfig: SanitizedConfig): Promise<Inl
|
|||||||
|
|
||||||
const hmrPort = await getPort()
|
const hmrPort = await getPort()
|
||||||
|
|
||||||
const absoluteAliases = {
|
const absoluteAliases = {}
|
||||||
[`${bundlerPath}`]: path.resolve(__dirname, './mock.js'),
|
|
||||||
}
|
|
||||||
|
|
||||||
const alias = [
|
const alias = [
|
||||||
|
{ find: '@payloadcms/bundler-vite', replacement: path.resolve(__dirname, '../mock.js') },
|
||||||
{ find: 'path', replacement: require.resolve('path-browserify') },
|
{ find: 'path', replacement: require.resolve('path-browserify') },
|
||||||
{ find: 'payload-config', replacement: payloadConfig.paths.rawConfig },
|
{ find: 'payload-config', replacement: payloadConfig.paths.rawConfig },
|
||||||
{ find: /payload$/, replacement: mockModulePath },
|
{ find: /payload$/, replacement: mockModulePath },
|
||||||
@@ -89,7 +87,9 @@ export const getViteConfig = async (payloadConfig: SanitizedConfig): Promise<Inl
|
|||||||
exclude: [
|
exclude: [
|
||||||
// Dependencies that need aliases should be excluded
|
// Dependencies that need aliases should be excluded
|
||||||
// from pre-bundling
|
// from pre-bundling
|
||||||
|
'@payloadcms/bundler-vite',
|
||||||
],
|
],
|
||||||
|
include: ['payload/components/root'],
|
||||||
},
|
},
|
||||||
plugins: [
|
plugins: [
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@payloadcms/db-mongodb",
|
"name": "@payloadcms/db-mongodb",
|
||||||
"version": "1.0.0-beta.3",
|
"version": "1.0.0-beta.4",
|
||||||
"description": "The officially supported MongoDB database adapter for Payload",
|
"description": "The officially supported MongoDB database adapter for Payload",
|
||||||
"repository": "https://github.com/payloadcms/payload",
|
"repository": "https://github.com/payloadcms/payload",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
@@ -40,6 +40,7 @@
|
|||||||
"types": "./dist/index.d.ts"
|
"types": "./dist/index.d.ts"
|
||||||
},
|
},
|
||||||
"files": [
|
"files": [
|
||||||
"dist"
|
"dist",
|
||||||
|
"mock.js"
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|||||||
19
packages/db-mongodb/src/extendViteConfig.ts
Normal file
19
packages/db-mongodb/src/extendViteConfig.ts
Normal file
@@ -0,0 +1,19 @@
|
|||||||
|
import type { SanitizedConfig } from 'payload/config'
|
||||||
|
|
||||||
|
export const vite = (config) => {
|
||||||
|
return {
|
||||||
|
...config,
|
||||||
|
optimizeDeps: {
|
||||||
|
...config.optimizeDeps,
|
||||||
|
exclude: [...config.optimizeDeps.exclude, '@payloadcms/db-mongodb'],
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export const extendViteConfig = (config: SanitizedConfig) => {
|
||||||
|
const existingViteConfig = config.admin.vite ? config.admin.vite : (viteConfig) => viteConfig
|
||||||
|
|
||||||
|
config.admin.vite = (webpackConfig) => {
|
||||||
|
return vite(existingViteConfig(webpackConfig))
|
||||||
|
}
|
||||||
|
}
|
||||||
28
packages/db-mongodb/src/extendWebpackConfig.ts
Normal file
28
packages/db-mongodb/src/extendWebpackConfig.ts
Normal file
@@ -0,0 +1,28 @@
|
|||||||
|
import type { SanitizedConfig } from 'payload/config'
|
||||||
|
|
||||||
|
import path from 'path'
|
||||||
|
|
||||||
|
export const webpack = (config) => {
|
||||||
|
const aliasPath = path.resolve(__dirname, '../mock.js')
|
||||||
|
|
||||||
|
return {
|
||||||
|
...config,
|
||||||
|
resolve: {
|
||||||
|
...(config.resolve || {}),
|
||||||
|
alias: {
|
||||||
|
...(config.resolve?.alias || {}),
|
||||||
|
'@payloadcms/db-mongodb': aliasPath,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export const extendWebpackConfig = (config: SanitizedConfig) => {
|
||||||
|
const existingWebpackConfig = config.admin.webpack
|
||||||
|
? config.admin.webpack
|
||||||
|
: (webpackConfig) => webpackConfig
|
||||||
|
|
||||||
|
config.admin.webpack = (webpackConfig) => {
|
||||||
|
return webpack(existingWebpackConfig(webpackConfig))
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -19,6 +19,8 @@ import { deleteMany } from './deleteMany'
|
|||||||
import { deleteOne } from './deleteOne'
|
import { deleteOne } from './deleteOne'
|
||||||
import { deleteVersions } from './deleteVersions'
|
import { deleteVersions } from './deleteVersions'
|
||||||
import { destroy } from './destroy'
|
import { destroy } from './destroy'
|
||||||
|
import { extendViteConfig } from './extendViteConfig'
|
||||||
|
import { extendWebpackConfig } from './extendWebpackConfig'
|
||||||
import { find } from './find'
|
import { find } from './find'
|
||||||
import { findGlobal } from './findGlobal'
|
import { findGlobal } from './findGlobal'
|
||||||
import { findGlobalVersions } from './findGlobalVersions'
|
import { findGlobalVersions } from './findGlobalVersions'
|
||||||
@@ -33,7 +35,6 @@ import { updateGlobal } from './updateGlobal'
|
|||||||
import { updateGlobalVersion } from './updateGlobalVersion'
|
import { updateGlobalVersion } from './updateGlobalVersion'
|
||||||
import { updateOne } from './updateOne'
|
import { updateOne } from './updateOne'
|
||||||
import { updateVersion } from './updateVersion'
|
import { updateVersion } from './updateVersion'
|
||||||
import { webpack } from './webpack'
|
|
||||||
|
|
||||||
export interface Args {
|
export interface Args {
|
||||||
/** Set to false to disable auto-pluralization of collection names, Defaults to true */
|
/** Set to false to disable auto-pluralization of collection names, Defaults to true */
|
||||||
@@ -88,6 +89,9 @@ export function mongooseAdapter({
|
|||||||
function adapter({ payload }: { payload: Payload }) {
|
function adapter({ payload }: { payload: Payload }) {
|
||||||
mongoose.set('strictQuery', false)
|
mongoose.set('strictQuery', false)
|
||||||
|
|
||||||
|
extendWebpackConfig(payload.config)
|
||||||
|
extendViteConfig(payload.config)
|
||||||
|
|
||||||
return createDatabaseAdapter<MongooseAdapter>({
|
return createDatabaseAdapter<MongooseAdapter>({
|
||||||
autoPluralization,
|
autoPluralization,
|
||||||
beginTransaction,
|
beginTransaction,
|
||||||
@@ -126,7 +130,6 @@ export function mongooseAdapter({
|
|||||||
updateVersion,
|
updateVersion,
|
||||||
url,
|
url,
|
||||||
versions: {},
|
versions: {},
|
||||||
webpack,
|
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,19 +0,0 @@
|
|||||||
import type { Webpack } from 'payload/database'
|
|
||||||
|
|
||||||
import path from 'path'
|
|
||||||
|
|
||||||
export const webpack: Webpack = (config) => {
|
|
||||||
const aliasPath = path.resolve(__dirname, 'mock.js')
|
|
||||||
|
|
||||||
return {
|
|
||||||
...config,
|
|
||||||
resolve: {
|
|
||||||
...(config.resolve || {}),
|
|
||||||
alias: {
|
|
||||||
...(config.resolve?.alias || {}),
|
|
||||||
'@payloadcms/db-mongodb': aliasPath,
|
|
||||||
[path.resolve(__dirname, './index')]: aliasPath,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@payloadcms/db-postgres",
|
"name": "@payloadcms/db-postgres",
|
||||||
"version": "0.1.0-beta.8",
|
"version": "0.1.0-beta.10",
|
||||||
"description": "The officially supported Postgres database adapter for Payload",
|
"description": "The officially supported Postgres database adapter for Payload",
|
||||||
"repository": "https://github.com/payloadcms/payload",
|
"repository": "https://github.com/payloadcms/payload",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
@@ -43,6 +43,7 @@
|
|||||||
"types": "./dist/index.d.ts"
|
"types": "./dist/index.d.ts"
|
||||||
},
|
},
|
||||||
"files": [
|
"files": [
|
||||||
"dist"
|
"dist",
|
||||||
|
"mock.js"
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|||||||
19
packages/db-postgres/src/extendViteConfig.ts
Normal file
19
packages/db-postgres/src/extendViteConfig.ts
Normal file
@@ -0,0 +1,19 @@
|
|||||||
|
import type { SanitizedConfig } from 'payload/config'
|
||||||
|
|
||||||
|
export const vite = (config) => {
|
||||||
|
return {
|
||||||
|
...config,
|
||||||
|
optimizeDeps: {
|
||||||
|
...config.optimizeDeps,
|
||||||
|
exclude: [...config.optimizeDeps.exclude, '@payloadcms/db-postgres'],
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export const extendViteConfig = (config: SanitizedConfig) => {
|
||||||
|
const existingViteConfig = config.admin.vite ? config.admin.vite : (viteConfig) => viteConfig
|
||||||
|
|
||||||
|
config.admin.vite = (webpackConfig) => {
|
||||||
|
return vite(existingViteConfig(webpackConfig))
|
||||||
|
}
|
||||||
|
}
|
||||||
28
packages/db-postgres/src/extendWebpackConfig.ts
Normal file
28
packages/db-postgres/src/extendWebpackConfig.ts
Normal file
@@ -0,0 +1,28 @@
|
|||||||
|
import type { SanitizedConfig } from 'payload/config'
|
||||||
|
|
||||||
|
import path from 'path'
|
||||||
|
|
||||||
|
export const webpack = (config) => {
|
||||||
|
const aliasPath = path.resolve(__dirname, '../mock.js')
|
||||||
|
|
||||||
|
return {
|
||||||
|
...config,
|
||||||
|
resolve: {
|
||||||
|
...(config.resolve || {}),
|
||||||
|
alias: {
|
||||||
|
...(config.resolve?.alias || {}),
|
||||||
|
'@payloadcms/db-postgres': aliasPath,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export const extendWebpackConfig = (config: SanitizedConfig) => {
|
||||||
|
const existingWebpackConfig = config.admin.webpack
|
||||||
|
? config.admin.webpack
|
||||||
|
: (webpackConfig) => webpackConfig
|
||||||
|
|
||||||
|
config.admin.webpack = (webpackConfig) => {
|
||||||
|
return webpack(existingWebpackConfig(webpackConfig))
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -17,6 +17,8 @@ import { deleteMany } from './deleteMany'
|
|||||||
import { deleteOne } from './deleteOne'
|
import { deleteOne } from './deleteOne'
|
||||||
import { deleteVersions } from './deleteVersions'
|
import { deleteVersions } from './deleteVersions'
|
||||||
import { destroy } from './destroy'
|
import { destroy } from './destroy'
|
||||||
|
import { extendViteConfig } from './extendViteConfig'
|
||||||
|
import { extendWebpackConfig } from './extendWebpackConfig'
|
||||||
import { find } from './find'
|
import { find } from './find'
|
||||||
import { findGlobal } from './findGlobal'
|
import { findGlobal } from './findGlobal'
|
||||||
import { findGlobalVersions } from './findGlobalVersions'
|
import { findGlobalVersions } from './findGlobalVersions'
|
||||||
@@ -33,11 +35,14 @@ import { updateOne } from './update'
|
|||||||
import { updateGlobal } from './updateGlobal'
|
import { updateGlobal } from './updateGlobal'
|
||||||
import { updateGlobalVersion } from './updateGlobalVersion'
|
import { updateGlobalVersion } from './updateGlobalVersion'
|
||||||
import { updateVersion } from './updateVersion'
|
import { updateVersion } from './updateVersion'
|
||||||
import { webpack } from './webpack'
|
|
||||||
|
|
||||||
export function postgresAdapter(args: Args): PostgresAdapterResult {
|
export function postgresAdapter(args: Args): PostgresAdapterResult {
|
||||||
function adapter({ payload }: { payload: Payload }) {
|
function adapter({ payload }: { payload: Payload }) {
|
||||||
const migrationDir = args.migrationDir || path.resolve(process.cwd(), 'src/migrations')
|
const migrationDir = args.migrationDir || path.resolve(process.cwd(), 'src/migrations')
|
||||||
|
|
||||||
|
extendWebpackConfig(payload.config)
|
||||||
|
extendViteConfig(payload.config)
|
||||||
|
|
||||||
return createDatabaseAdapter<PostgresAdapter>({
|
return createDatabaseAdapter<PostgresAdapter>({
|
||||||
...args,
|
...args,
|
||||||
name: 'postgres',
|
name: 'postgres',
|
||||||
@@ -81,7 +86,6 @@ export function postgresAdapter(args: Args): PostgresAdapterResult {
|
|||||||
updateGlobalVersion,
|
updateGlobalVersion,
|
||||||
updateOne,
|
updateOne,
|
||||||
updateVersion,
|
updateVersion,
|
||||||
webpack,
|
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -14,11 +14,7 @@ export const init: Init = async function init(this: PostgresAdapter) {
|
|||||||
if (this.payload.config.localization) {
|
if (this.payload.config.localization) {
|
||||||
this.enums.enum__locales = pgEnum(
|
this.enums.enum__locales = pgEnum(
|
||||||
'_locales',
|
'_locales',
|
||||||
// TODO: types out of sync with core, monorepo please
|
this.payload.config.localization.locales.map(({ code }) => code) as [string, ...string[]],
|
||||||
// this.payload.config.localization.localeCodes,
|
|
||||||
(this.payload.config.localization.locales as unknown as { code: string }[]).map(
|
|
||||||
({ code }) => code,
|
|
||||||
) as [string, ...string[]],
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -28,6 +24,7 @@ export const init: Init = async function init(this: PostgresAdapter) {
|
|||||||
buildTable({
|
buildTable({
|
||||||
adapter: this,
|
adapter: this,
|
||||||
buildRelationships: true,
|
buildRelationships: true,
|
||||||
|
collectionIndexes: collection.indexes,
|
||||||
disableUnique: false,
|
disableUnique: false,
|
||||||
fields: collection.fields,
|
fields: collection.fields,
|
||||||
tableName,
|
tableName,
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
/* eslint-disable no-param-reassign */
|
/* eslint-disable no-param-reassign */
|
||||||
import type { Relation } from 'drizzle-orm'
|
import type { Relation } from 'drizzle-orm'
|
||||||
import type { IndexBuilder, PgColumnBuilder, UniqueConstraintBuilder } from 'drizzle-orm/pg-core'
|
import type { IndexBuilder, PgColumnBuilder, UniqueConstraintBuilder } from 'drizzle-orm/pg-core'
|
||||||
import type { Field } from 'payload/types'
|
import type { Field, SanitizedCollectionConfig } from 'payload/types'
|
||||||
|
|
||||||
import { relations } from 'drizzle-orm'
|
import { relations } from 'drizzle-orm'
|
||||||
import {
|
import {
|
||||||
@@ -27,6 +27,7 @@ type Args = {
|
|||||||
baseColumns?: Record<string, PgColumnBuilder>
|
baseColumns?: Record<string, PgColumnBuilder>
|
||||||
baseExtraConfig?: Record<string, (cols: GenericColumns) => IndexBuilder | UniqueConstraintBuilder>
|
baseExtraConfig?: Record<string, (cols: GenericColumns) => IndexBuilder | UniqueConstraintBuilder>
|
||||||
buildRelationships?: boolean
|
buildRelationships?: boolean
|
||||||
|
collectionIndexes?: SanitizedCollectionConfig['indexes']
|
||||||
disableUnique: boolean
|
disableUnique: boolean
|
||||||
fields: Field[]
|
fields: Field[]
|
||||||
rootRelationsToBuild?: Map<string, string>
|
rootRelationsToBuild?: Map<string, string>
|
||||||
@@ -45,6 +46,7 @@ export const buildTable = ({
|
|||||||
baseColumns = {},
|
baseColumns = {},
|
||||||
baseExtraConfig = {},
|
baseExtraConfig = {},
|
||||||
buildRelationships,
|
buildRelationships,
|
||||||
|
collectionIndexes = [],
|
||||||
disableUnique = false,
|
disableUnique = false,
|
||||||
fields,
|
fields,
|
||||||
rootRelationsToBuild,
|
rootRelationsToBuild,
|
||||||
@@ -96,6 +98,7 @@ export const buildTable = ({
|
|||||||
} = traverseFields({
|
} = traverseFields({
|
||||||
adapter,
|
adapter,
|
||||||
buildRelationships,
|
buildRelationships,
|
||||||
|
collectionIndexes,
|
||||||
columns,
|
columns,
|
||||||
disableUnique,
|
disableUnique,
|
||||||
fields,
|
fields,
|
||||||
|
|||||||
@@ -5,13 +5,22 @@ import type { GenericColumn } from '../types'
|
|||||||
|
|
||||||
type CreateIndexArgs = {
|
type CreateIndexArgs = {
|
||||||
columnName: string
|
columnName: string
|
||||||
name: string
|
name: string | string[]
|
||||||
unique?: boolean
|
unique?: boolean
|
||||||
}
|
}
|
||||||
|
|
||||||
export const createIndex = ({ name, columnName, unique }: CreateIndexArgs) => {
|
export const createIndex = ({ name, columnName, unique }: CreateIndexArgs) => {
|
||||||
return (table: { [x: string]: GenericColumn }) => {
|
return (table: { [x: string]: GenericColumn }) => {
|
||||||
if (unique) return uniqueIndex(`${columnName}_idx`).on(table[name])
|
let columns
|
||||||
return index(`${columnName}_idx`).on(table[name])
|
if (Array.isArray(name)) {
|
||||||
|
columns = name
|
||||||
|
.map((columnName) => table[columnName])
|
||||||
|
// exclude fields were included in compound indexes but do not exist on the table
|
||||||
|
.filter((col) => typeof col !== 'undefined')
|
||||||
|
} else {
|
||||||
|
columns = [table[name]]
|
||||||
|
}
|
||||||
|
if (unique) return uniqueIndex(`${columnName}_idx`).on(columns[0], ...columns.slice(1))
|
||||||
|
return index(`${columnName}_idx`).on(columns[0], ...columns.slice(1))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
/* eslint-disable no-param-reassign */
|
/* eslint-disable no-param-reassign */
|
||||||
import type { Relation } from 'drizzle-orm'
|
import type { Relation } from 'drizzle-orm'
|
||||||
import type { IndexBuilder, PgColumnBuilder, UniqueConstraintBuilder } from 'drizzle-orm/pg-core'
|
import type { IndexBuilder, PgColumnBuilder, UniqueConstraintBuilder } from 'drizzle-orm/pg-core'
|
||||||
import type { Field, TabAsField } from 'payload/types'
|
import type { Field, SanitizedCollectionConfig, TabAsField } from 'payload/types'
|
||||||
|
|
||||||
import { relations } from 'drizzle-orm'
|
import { relations } from 'drizzle-orm'
|
||||||
import {
|
import {
|
||||||
@@ -33,6 +33,7 @@ import { validateExistingBlockIsIdentical } from './validateExistingBlockIsIdent
|
|||||||
type Args = {
|
type Args = {
|
||||||
adapter: PostgresAdapter
|
adapter: PostgresAdapter
|
||||||
buildRelationships: boolean
|
buildRelationships: boolean
|
||||||
|
collectionIndexes: SanitizedCollectionConfig['indexes']
|
||||||
columnPrefix?: string
|
columnPrefix?: string
|
||||||
columns: Record<string, PgColumnBuilder>
|
columns: Record<string, PgColumnBuilder>
|
||||||
disableUnique?: boolean
|
disableUnique?: boolean
|
||||||
@@ -61,6 +62,7 @@ type Result = {
|
|||||||
export const traverseFields = ({
|
export const traverseFields = ({
|
||||||
adapter,
|
adapter,
|
||||||
buildRelationships,
|
buildRelationships,
|
||||||
|
collectionIndexes,
|
||||||
columnPrefix,
|
columnPrefix,
|
||||||
columns,
|
columns,
|
||||||
disableUnique = false,
|
disableUnique = false,
|
||||||
@@ -109,6 +111,24 @@ export const traverseFields = ({
|
|||||||
targetIndexes = localesIndexes
|
targetIndexes = localesIndexes
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const collectionIndex = collectionIndexes
|
||||||
|
? collectionIndexes.findIndex((index) => {
|
||||||
|
return Object.keys(index.fields).some((indexField) => indexField === fieldName)
|
||||||
|
})
|
||||||
|
: -1
|
||||||
|
|
||||||
|
if (collectionIndex > -1) {
|
||||||
|
const name = toSnakeCase(
|
||||||
|
`${Object.keys(collectionIndexes[collectionIndex].fields).join('_')}`,
|
||||||
|
)
|
||||||
|
targetIndexes[`${name}Idx`] = createIndex({
|
||||||
|
name: Object.keys(collectionIndexes[collectionIndex].fields),
|
||||||
|
columnName: name,
|
||||||
|
unique: collectionIndexes[collectionIndex].options.unique,
|
||||||
|
})
|
||||||
|
collectionIndexes.splice(collectionIndex)
|
||||||
|
}
|
||||||
|
|
||||||
if (
|
if (
|
||||||
(field.unique || field.index) &&
|
(field.unique || field.index) &&
|
||||||
!['array', 'blocks', 'group', 'point', 'relationship', 'upload'].includes(field.type) &&
|
!['array', 'blocks', 'group', 'point', 'relationship', 'upload'].includes(field.type) &&
|
||||||
@@ -415,6 +435,7 @@ export const traverseFields = ({
|
|||||||
} = traverseFields({
|
} = traverseFields({
|
||||||
adapter,
|
adapter,
|
||||||
buildRelationships,
|
buildRelationships,
|
||||||
|
collectionIndexes,
|
||||||
columnPrefix,
|
columnPrefix,
|
||||||
columns,
|
columns,
|
||||||
disableUnique,
|
disableUnique,
|
||||||
@@ -448,6 +469,7 @@ export const traverseFields = ({
|
|||||||
} = traverseFields({
|
} = traverseFields({
|
||||||
adapter,
|
adapter,
|
||||||
buildRelationships,
|
buildRelationships,
|
||||||
|
collectionIndexes,
|
||||||
columnPrefix: `${columnName}_`,
|
columnPrefix: `${columnName}_`,
|
||||||
columns,
|
columns,
|
||||||
disableUnique,
|
disableUnique,
|
||||||
@@ -482,6 +504,7 @@ export const traverseFields = ({
|
|||||||
} = traverseFields({
|
} = traverseFields({
|
||||||
adapter,
|
adapter,
|
||||||
buildRelationships,
|
buildRelationships,
|
||||||
|
collectionIndexes,
|
||||||
columnPrefix,
|
columnPrefix,
|
||||||
columns,
|
columns,
|
||||||
disableUnique,
|
disableUnique,
|
||||||
@@ -518,6 +541,7 @@ export const traverseFields = ({
|
|||||||
} = traverseFields({
|
} = traverseFields({
|
||||||
adapter,
|
adapter,
|
||||||
buildRelationships,
|
buildRelationships,
|
||||||
|
collectionIndexes,
|
||||||
columnPrefix,
|
columnPrefix,
|
||||||
columns,
|
columns,
|
||||||
disableUnique,
|
disableUnique,
|
||||||
|
|||||||
@@ -69,7 +69,7 @@ export type MigrateDownArgs = { payload: Payload }
|
|||||||
|
|
||||||
declare module 'payload' {
|
declare module 'payload' {
|
||||||
export interface DatabaseAdapter extends Args {
|
export interface DatabaseAdapter extends Args {
|
||||||
db: DrizzleDB
|
drizzle: DrizzleDB
|
||||||
enums: Record<string, GenericEnum>
|
enums: Record<string, GenericEnum>
|
||||||
pool: Pool
|
pool: Pool
|
||||||
relations: Record<string, GenericRelation>
|
relations: Record<string, GenericRelation>
|
||||||
|
|||||||
@@ -1,19 +0,0 @@
|
|||||||
import type { Webpack } from 'payload/database'
|
|
||||||
|
|
||||||
import path from 'path'
|
|
||||||
|
|
||||||
export const webpack: Webpack = (config) => {
|
|
||||||
const aliasPath = path.resolve(__dirname, 'mock.js')
|
|
||||||
|
|
||||||
return {
|
|
||||||
...config,
|
|
||||||
resolve: {
|
|
||||||
...(config.resolve || {}),
|
|
||||||
alias: {
|
|
||||||
...(config.resolve?.alias || {}),
|
|
||||||
'@payloadcms/db-postgres': aliasPath,
|
|
||||||
[path.resolve(__dirname, './index')]: aliasPath,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
}
|
|
||||||
}
|
|
||||||
2
packages/payload/database.d.ts
vendored
2
packages/payload/database.d.ts
vendored
@@ -1,4 +1,4 @@
|
|||||||
export { BaseDatabaseAdapter, BeginTransaction, CommitTransaction, Connect, Create, CreateArgs, CreateGlobal, CreateGlobalArgs, CreateGlobalVersion, CreateGlobalVersionArgs, CreateMigration, CreateVersion, CreateVersionArgs, DeleteMany, DeleteManyArgs, DeleteOne, DeleteOneArgs, DeleteVersions, DeleteVersionsArgs, Destroy, Find, FindArgs, FindGlobal, FindGlobalArgs, FindGlobalVersions, FindGlobalVersionsArgs, FindOne, FindOneArgs, FindVersions, FindVersionsArgs, Init, Migration, MigrationData, PaginatedDocs, QueryDrafts, QueryDraftsArgs, RollbackTransaction, Transaction, TypeWithVersion, UpdateGlobal, UpdateGlobalArgs, UpdateGlobalVersion, UpdateGlobalVersionArgs, UpdateOne, UpdateOneArgs, UpdateVersion, UpdateVersionArgs, Webpack, } from './dist/database/types';
|
export { BaseDatabaseAdapter, BeginTransaction, CommitTransaction, Connect, Create, CreateArgs, CreateGlobal, CreateGlobalArgs, CreateGlobalVersion, CreateGlobalVersionArgs, CreateMigration, CreateVersion, CreateVersionArgs, DeleteMany, DeleteManyArgs, DeleteOne, DeleteOneArgs, DeleteVersions, DeleteVersionsArgs, Destroy, Find, FindArgs, FindGlobal, FindGlobalArgs, FindGlobalVersions, FindGlobalVersionsArgs, FindOne, FindOneArgs, FindVersions, FindVersionsArgs, Init, Migration, MigrationData, PaginatedDocs, QueryDrafts, QueryDraftsArgs, RollbackTransaction, Transaction, TypeWithVersion, UpdateGlobal, UpdateGlobalArgs, UpdateGlobalVersion, UpdateGlobalVersionArgs, UpdateOne, UpdateOneArgs, UpdateVersion, UpdateVersionArgs, } from './dist/database/types';
|
||||||
export * from './dist/database/queryValidation/types';
|
export * from './dist/database/queryValidation/types';
|
||||||
export { combineQueries } from './dist/database/combineQueries';
|
export { combineQueries } from './dist/database/combineQueries';
|
||||||
export { createDatabaseAdapter } from './dist/database/createDatabaseAdapter';
|
export { createDatabaseAdapter } from './dist/database/createDatabaseAdapter';
|
||||||
|
|||||||
File diff suppressed because one or more lines are too long
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "payload",
|
"name": "payload",
|
||||||
"version": "2.0.0-beta.7",
|
"version": "2.0.0-beta.11",
|
||||||
"description": "Node, React and MongoDB Headless CMS and Application Framework",
|
"description": "Node, React and MongoDB Headless CMS and Application Framework",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"main": "./src/index.ts",
|
"main": "./src/index.ts",
|
||||||
|
|||||||
@@ -105,6 +105,9 @@ export const Routes: React.FC = () => {
|
|||||||
if (initialized === true && !isLoadingUser) {
|
if (initialized === true && !isLoadingUser) {
|
||||||
return (
|
return (
|
||||||
<Switch>
|
<Switch>
|
||||||
|
<Route path={`${match.url}/create-first-user`}>
|
||||||
|
<Redirect to={`${match.url}/`} />
|
||||||
|
</Route>
|
||||||
{customRoutes({
|
{customRoutes({
|
||||||
canAccessAdmin,
|
canAccessAdmin,
|
||||||
customRoutes: customRoutesConfig,
|
customRoutes: customRoutesConfig,
|
||||||
|
|||||||
@@ -9,7 +9,7 @@ import baseAPIKeyFields from '../../auth/baseFields/apiKey'
|
|||||||
import baseAuthFields from '../../auth/baseFields/auth'
|
import baseAuthFields from '../../auth/baseFields/auth'
|
||||||
import baseVerificationFields from '../../auth/baseFields/verification'
|
import baseVerificationFields from '../../auth/baseFields/verification'
|
||||||
import TimestampsRequired from '../../errors/TimestampsRequired'
|
import TimestampsRequired from '../../errors/TimestampsRequired'
|
||||||
import sanitizeFields from '../../fields/config/sanitize'
|
import { sanitizeFields } from '../../fields/config/sanitize'
|
||||||
import { fieldAffectsData } from '../../fields/config/types'
|
import { fieldAffectsData } from '../../fields/config/types'
|
||||||
import mergeBaseFields from '../../fields/mergeBaseFields'
|
import mergeBaseFields from '../../fields/mergeBaseFields'
|
||||||
import { extractTranslations } from '../../translations/extractTranslations'
|
import { extractTranslations } from '../../translations/extractTranslations'
|
||||||
@@ -142,7 +142,7 @@ const sanitizeCollection = (
|
|||||||
// Sanitize fields
|
// Sanitize fields
|
||||||
// /////////////////////////////////
|
// /////////////////////////////////
|
||||||
|
|
||||||
const validRelationships = config.collections.map((c) => c.slug)
|
const validRelationships = config.collections.map((c) => c.slug) || []
|
||||||
sanitized.fields = sanitizeFields({
|
sanitized.fields = sanitizeFields({
|
||||||
config,
|
config,
|
||||||
fields: sanitized.fields,
|
fields: sanitized.fields,
|
||||||
|
|||||||
@@ -1,6 +1,5 @@
|
|||||||
/* eslint-disable no-param-reassign */
|
/* eslint-disable no-param-reassign */
|
||||||
import type { MarkOptional } from 'ts-essentials'
|
import type { MarkOptional } from 'ts-essentials'
|
||||||
import type { Configuration } from 'webpack'
|
|
||||||
|
|
||||||
import type {
|
import type {
|
||||||
BaseDatabaseAdapter,
|
BaseDatabaseAdapter,
|
||||||
@@ -35,16 +34,6 @@ export function createDatabaseAdapter<T extends BaseDatabaseAdapter>(
|
|||||||
| 'transaction'
|
| 'transaction'
|
||||||
>,
|
>,
|
||||||
): T {
|
): T {
|
||||||
// Need to implement DB Webpack config extensions here
|
|
||||||
if (args.webpack) {
|
|
||||||
const existingWebpackConfig = args.payload.config.admin.webpack
|
|
||||||
? args.payload.config.admin.webpack
|
|
||||||
: (webpackConfig) => webpackConfig
|
|
||||||
args.payload.config.admin.webpack = (webpackConfig: Configuration) => {
|
|
||||||
return args.webpack(existingWebpackConfig(webpackConfig))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return {
|
return {
|
||||||
// Default 'null' transaction functions
|
// Default 'null' transaction functions
|
||||||
beginTransaction,
|
beginTransaction,
|
||||||
|
|||||||
@@ -1,5 +1,3 @@
|
|||||||
import type { Configuration } from 'webpack'
|
|
||||||
|
|
||||||
import type { TypeWithID } from '../collections/config/types'
|
import type { TypeWithID } from '../collections/config/types'
|
||||||
import type { TypeWithID as GlobalsTypeWithID } from '../globals/config/types'
|
import type { TypeWithID as GlobalsTypeWithID } from '../globals/config/types'
|
||||||
import type { Payload } from '../payload'
|
import type { Payload } from '../payload'
|
||||||
@@ -140,10 +138,6 @@ export interface BaseDatabaseAdapter {
|
|||||||
* assign the transaction to use when making queries, defaults to the last started transaction
|
* assign the transaction to use when making queries, defaults to the last started transaction
|
||||||
*/
|
*/
|
||||||
useTransaction?: (id: number | string) => void
|
useTransaction?: (id: number | string) => void
|
||||||
/**
|
|
||||||
* Used to alias server only modules or make other changes to webpack configuration
|
|
||||||
*/
|
|
||||||
webpack?: Webpack
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export type Init = (payload: Payload) => Promise<void>
|
export type Init = (payload: Payload) => Promise<void>
|
||||||
@@ -152,8 +146,6 @@ export type Connect = (payload: Payload) => Promise<void>
|
|||||||
|
|
||||||
export type Destroy = (payload: Payload) => Promise<void>
|
export type Destroy = (payload: Payload) => Promise<void>
|
||||||
|
|
||||||
export type Webpack = (config: Configuration) => Configuration
|
|
||||||
|
|
||||||
export type CreateMigration = (payload: Payload, migrationName?: string) => Promise<void>
|
export type CreateMigration = (payload: Payload, migrationName?: string) => Promise<void>
|
||||||
|
|
||||||
export type Transaction = (
|
export type Transaction = (
|
||||||
|
|||||||
@@ -6,3 +6,4 @@ export { defaults } from '../config/defaults'
|
|||||||
export { sanitizeConfig } from '../config/sanitize'
|
export { sanitizeConfig } from '../config/sanitize'
|
||||||
export { baseBlockFields } from '../fields/baseFields/baseBlockFields'
|
export { baseBlockFields } from '../fields/baseFields/baseBlockFields'
|
||||||
export { baseIDField } from '../fields/baseFields/baseIDField'
|
export { baseIDField } from '../fields/baseFields/baseIDField'
|
||||||
|
export { sanitizeFields } from '../fields/config/sanitize'
|
||||||
|
|||||||
@@ -46,7 +46,6 @@ export {
|
|||||||
UpdateOneArgs,
|
UpdateOneArgs,
|
||||||
UpdateVersion,
|
UpdateVersion,
|
||||||
UpdateVersionArgs,
|
UpdateVersionArgs,
|
||||||
Webpack,
|
|
||||||
} from '../database/types'
|
} from '../database/types'
|
||||||
|
|
||||||
export * from '../database/queryValidation/types'
|
export * from '../database/queryValidation/types'
|
||||||
|
|||||||
@@ -9,7 +9,7 @@ import type {
|
|||||||
} from './types'
|
} from './types'
|
||||||
import { Config } from '../../config/types'
|
import { Config } from '../../config/types'
|
||||||
import { InvalidFieldName, InvalidFieldRelationship, MissingFieldType } from '../../errors'
|
import { InvalidFieldName, InvalidFieldRelationship, MissingFieldType } from '../../errors'
|
||||||
import sanitizeFields from './sanitize'
|
import { sanitizeFields } from './sanitize'
|
||||||
import { DatabaseAdapter } from '../..'
|
import { DatabaseAdapter } from '../..'
|
||||||
|
|
||||||
const dummyConfig: Config = {
|
const dummyConfig: Config = {
|
||||||
|
|||||||
@@ -12,10 +12,14 @@ import { fieldAffectsData, tabHasName } from './types'
|
|||||||
type Args = {
|
type Args = {
|
||||||
config: Config
|
config: Config
|
||||||
fields: Field[]
|
fields: Field[]
|
||||||
validRelationships: string[]
|
/**
|
||||||
|
* If not null, will validate that upload and relationship fields do not relate to a collection that is not in this array.
|
||||||
|
* This validation will be skipped if validRelationships is null.
|
||||||
|
*/
|
||||||
|
validRelationships: null | string[]
|
||||||
}
|
}
|
||||||
|
|
||||||
const sanitizeFields = ({ config, fields, validRelationships }: Args): Field[] => {
|
export const sanitizeFields = ({ config, fields, validRelationships }: Args): Field[] => {
|
||||||
if (!fields) return []
|
if (!fields) return []
|
||||||
|
|
||||||
return fields.map((unsanitizedField) => {
|
return fields.map((unsanitizedField) => {
|
||||||
@@ -48,12 +52,16 @@ const sanitizeFields = ({ config, fields, validRelationships }: Args): Field[] =
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (field.type === 'relationship' || field.type === 'upload') {
|
if (field.type === 'relationship' || field.type === 'upload') {
|
||||||
const relationships = Array.isArray(field.relationTo) ? field.relationTo : [field.relationTo]
|
if (validRelationships) {
|
||||||
|
const relationships = Array.isArray(field.relationTo)
|
||||||
|
? field.relationTo
|
||||||
|
: [field.relationTo]
|
||||||
relationships.forEach((relationship: string) => {
|
relationships.forEach((relationship: string) => {
|
||||||
if (!validRelationships.includes(relationship)) {
|
if (!validRelationships.includes(relationship)) {
|
||||||
throw new InvalidFieldRelationship(field, relationship)
|
throw new InvalidFieldRelationship(field, relationship)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
}
|
||||||
|
|
||||||
if (field.type === 'relationship') {
|
if (field.type === 'relationship') {
|
||||||
if (field.min && !field.minRows) {
|
if (field.min && !field.minRows) {
|
||||||
@@ -155,5 +163,3 @@ const sanitizeFields = ({ config, fields, validRelationships }: Args): Field[] =
|
|||||||
return field
|
return field
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
export default sanitizeFields
|
|
||||||
|
|||||||
@@ -2,7 +2,7 @@ import type { Config } from '../../config/types'
|
|||||||
import type { SanitizedGlobalConfig } from './types'
|
import type { SanitizedGlobalConfig } from './types'
|
||||||
|
|
||||||
import defaultAccess from '../../auth/defaultAccess'
|
import defaultAccess from '../../auth/defaultAccess'
|
||||||
import sanitizeFields from '../../fields/config/sanitize'
|
import { sanitizeFields } from '../../fields/config/sanitize'
|
||||||
import { fieldAffectsData } from '../../fields/config/types'
|
import { fieldAffectsData } from '../../fields/config/types'
|
||||||
import mergeBaseFields from '../../fields/mergeBaseFields'
|
import mergeBaseFields from '../../fields/mergeBaseFields'
|
||||||
import translations from '../../translations'
|
import translations from '../../translations'
|
||||||
@@ -92,7 +92,7 @@ const sanitizeGlobals = (config: Config): SanitizedGlobalConfig[] => {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
const validRelationships = collections.map((c) => c.slug)
|
const validRelationships = collections.map((c) => c.slug) || []
|
||||||
sanitizedGlobal.fields = sanitizeFields({
|
sanitizedGlobal.fields = sanitizeFields({
|
||||||
config,
|
config,
|
||||||
fields: sanitizedGlobal.fields,
|
fields: sanitizedGlobal.fields,
|
||||||
|
|||||||
@@ -68,8 +68,6 @@ export const BlockContent: React.FC<Props> = (props) => {
|
|||||||
})
|
})
|
||||||
}, [editor, nodeKey, collapsed])
|
}, [editor, nodeKey, collapsed])
|
||||||
|
|
||||||
console.log('BLOCK', block)
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<React.Fragment>
|
<React.Fragment>
|
||||||
<Collapsible
|
<Collapsible
|
||||||
|
|||||||
@@ -8,6 +8,8 @@
|
|||||||
--font-body
|
--font-body
|
||||||
); // Reset font to non-serif, body font, as the lexical editor parent uses a serif font.
|
); // Reset font to non-serif, body font, as the lexical editor parent uses a serif font.
|
||||||
|
|
||||||
|
margin: 0 0 1.5em;
|
||||||
|
|
||||||
&__header {
|
&__header {
|
||||||
h3 {
|
h3 {
|
||||||
margin: 0;
|
margin: 0;
|
||||||
|
|||||||
@@ -7,6 +7,9 @@ const baseClass = 'lexical-block'
|
|||||||
|
|
||||||
import type { Data } from 'payload/types'
|
import type { Data } from 'payload/types'
|
||||||
|
|
||||||
|
import { useConfig } from 'payload/components/utilities'
|
||||||
|
import { sanitizeFields } from 'payload/config'
|
||||||
|
|
||||||
import type { BlocksFeatureProps } from '..'
|
import type { BlocksFeatureProps } from '..'
|
||||||
|
|
||||||
import { useEditorConfigContext } from '../../../lexical/config/EditorConfigProvider'
|
import { useEditorConfigContext } from '../../../lexical/config/EditorConfigProvider'
|
||||||
@@ -23,6 +26,7 @@ type Props = {
|
|||||||
|
|
||||||
export const BlockComponent: React.FC<Props> = (props) => {
|
export const BlockComponent: React.FC<Props> = (props) => {
|
||||||
const { children, className, fields, format, nodeKey } = props
|
const { children, className, fields, format, nodeKey } = props
|
||||||
|
const payloadConfig = useConfig()
|
||||||
|
|
||||||
const { editorConfig, field } = useEditorConfigContext()
|
const { editorConfig, field } = useEditorConfigContext()
|
||||||
|
|
||||||
@@ -30,6 +34,14 @@ export const BlockComponent: React.FC<Props> = (props) => {
|
|||||||
editorConfig?.resolvedFeatureMap?.get('blocks')?.props as BlocksFeatureProps
|
editorConfig?.resolvedFeatureMap?.get('blocks')?.props as BlocksFeatureProps
|
||||||
)?.blocks?.find((block) => block.slug === fields?.data?.blockType)
|
)?.blocks?.find((block) => block.slug === fields?.data?.blockType)
|
||||||
|
|
||||||
|
// Sanitize block's fields here. This is done here and not in the feature, because the payload config is available here
|
||||||
|
const validRelationships = payloadConfig.collections.map((c) => c.slug) || []
|
||||||
|
block.fields = sanitizeFields({
|
||||||
|
config: payloadConfig,
|
||||||
|
fields: block.fields,
|
||||||
|
validRelationships,
|
||||||
|
})
|
||||||
|
|
||||||
const initialDataRef = React.useRef<Data>(buildInitialState(fields.data || {})) // Store initial value in a ref, so it doesn't change on re-render and only gets initialized once
|
const initialDataRef = React.useRef<Data>(buildInitialState(fields.data || {})) // Store initial value in a ref, so it doesn't change on re-render and only gets initialized once
|
||||||
|
|
||||||
// Memoized Form JSX
|
// Memoized Form JSX
|
||||||
|
|||||||
@@ -30,12 +30,8 @@ export const BlocksFeature = (props?: BlocksFeatureProps): FeatureProvider => {
|
|||||||
? formatLabels(unsanitizedBlock.slug)
|
? formatLabels(unsanitizedBlock.slug)
|
||||||
: unsanitizedBlock.labels
|
: unsanitizedBlock.labels
|
||||||
|
|
||||||
// TODO
|
// unsanitizedBlock.fields are sanitized in the React component and not here.
|
||||||
/*unsanitizedBlock.fields = sanitizeFields({
|
// That's because we do not have access to the payload config here.
|
||||||
config,
|
|
||||||
fields: block.fields,
|
|
||||||
validRelationships,
|
|
||||||
})*/
|
|
||||||
|
|
||||||
return unsanitizedBlock
|
return unsanitizedBlock
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
html[data-theme='light'] {
|
html[data-theme='light'] {
|
||||||
.link-editor {
|
.link-editor {
|
||||||
box-shadow: 0px 6px 20px 0px rgba(0, 0, 0, 0.2);
|
@include shadow-m;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -35,7 +35,7 @@ html[data-theme='light'] {
|
|||||||
border: 0;
|
border: 0;
|
||||||
outline: 0;
|
outline: 0;
|
||||||
position: relative;
|
position: relative;
|
||||||
font-family: inherit;
|
font-family: var(--font-body);
|
||||||
|
|
||||||
a {
|
a {
|
||||||
text-decoration: none;
|
text-decoration: none;
|
||||||
|
|||||||
@@ -101,6 +101,7 @@ const Component: React.FC<Props> = (props) => {
|
|||||||
<div className={`${baseClass}__actions`}>
|
<div className={`${baseClass}__actions`}>
|
||||||
<Button
|
<Button
|
||||||
buttonStyle="icon-label"
|
buttonStyle="icon-label"
|
||||||
|
className={`${baseClass}__swapButton`}
|
||||||
disabled={field?.admin?.readOnly}
|
disabled={field?.admin?.readOnly}
|
||||||
el="div"
|
el="div"
|
||||||
icon="swap"
|
icon="swap"
|
||||||
|
|||||||
@@ -10,6 +10,7 @@
|
|||||||
border: 1px solid var(--theme-elevation-100);
|
border: 1px solid var(--theme-elevation-100);
|
||||||
max-width: base(15);
|
max-width: base(15);
|
||||||
font-family: var(--font-body);
|
font-family: var(--font-body);
|
||||||
|
margin: 0 0 1.5em;
|
||||||
|
|
||||||
&:hover {
|
&:hover {
|
||||||
border: 1px solid var(--theme-elevation-150);
|
border: 1px solid var(--theme-elevation-150);
|
||||||
@@ -56,7 +57,14 @@
|
|||||||
& > * {
|
& > * {
|
||||||
margin: 0;
|
margin: 0;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
&__swapButton {
|
||||||
|
margin: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
&__doc-drawer-toggler,
|
||||||
|
&__swapButton {
|
||||||
&:disabled {
|
&:disabled {
|
||||||
color: var(--theme-elevation-300);
|
color: var(--theme-elevation-300);
|
||||||
pointer-events: none;
|
pointer-events: none;
|
||||||
|
|||||||
@@ -10,6 +10,7 @@
|
|||||||
border: 1px solid var(--theme-elevation-100);
|
border: 1px solid var(--theme-elevation-100);
|
||||||
position: relative;
|
position: relative;
|
||||||
font-family: var(--font-body);
|
font-family: var(--font-body);
|
||||||
|
margin: 0 0 1.5em;
|
||||||
|
|
||||||
.btn {
|
.btn {
|
||||||
margin: 0;
|
margin: 0;
|
||||||
|
|||||||
@@ -1,4 +0,0 @@
|
|||||||
@import 'payload/scss';
|
|
||||||
|
|
||||||
.editor-upload {
|
|
||||||
}
|
|
||||||
@@ -12,8 +12,6 @@ import {
|
|||||||
} from 'lexical'
|
} from 'lexical'
|
||||||
import * as React from 'react'
|
import * as React from 'react'
|
||||||
|
|
||||||
import { UploadFeatureProps } from '..'
|
|
||||||
|
|
||||||
// @ts-expect-error TypeScript being dumb
|
// @ts-expect-error TypeScript being dumb
|
||||||
const RawUploadComponent = React.lazy(async () => await import('../component'))
|
const RawUploadComponent = React.lazy(async () => await import('../component'))
|
||||||
|
|
||||||
|
|||||||
@@ -94,7 +94,7 @@ html[data-theme='light'] {
|
|||||||
.floating-select-toolbar-popup__dropdown {
|
.floating-select-toolbar-popup__dropdown {
|
||||||
&--items {
|
&--items {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
box-shadow: 0px 6px 20px 0px rgba(0, 0, 0, 0.2);
|
@include shadow-m;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
html[data-theme='light'] {
|
html[data-theme='light'] {
|
||||||
.floating-select-toolbar-popup {
|
.floating-select-toolbar-popup {
|
||||||
box-shadow: 0px 6px 20px 0px rgba(0, 0, 0, 0.2);
|
@include shadow-m;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -527,11 +527,17 @@ export function useMenuAnchorRef(
|
|||||||
if (left + menuWidth > rootElementRect.right) {
|
if (left + menuWidth > rootElementRect.right) {
|
||||||
containerDiv.style.left = `${rootElementRect.right - menuWidth + window.scrollX}px`
|
containerDiv.style.left = `${rootElementRect.right - menuWidth + window.scrollX}px`
|
||||||
}
|
}
|
||||||
const margin = 10
|
|
||||||
|
const wouldGoOffTopOfScreen = top < menuHeight
|
||||||
|
const wouldGoOffBottomOfContainer = top + menuHeight > rootElementRect.bottom
|
||||||
|
|
||||||
|
// Position slash menu above the cursor instead of below (default) if it would otherwise go off the bottom of the screen.
|
||||||
if (
|
if (
|
||||||
(top + menuHeight > window.innerHeight || top + menuHeight > rootElementRect.bottom) &&
|
(top + menuHeight > window.innerHeight ||
|
||||||
|
(wouldGoOffBottomOfContainer && !wouldGoOffTopOfScreen)) &&
|
||||||
top - rootElementRect.top > menuHeight
|
top - rootElementRect.top > menuHeight
|
||||||
) {
|
) {
|
||||||
|
const margin = 24
|
||||||
containerDiv.style.top = `${
|
containerDiv.style.top = `${
|
||||||
top + VERTICAL_OFFSET - menuHeight + window.scrollY - (height + margin)
|
top + VERTICAL_OFFSET - menuHeight + window.scrollY - (height + margin)
|
||||||
}px`
|
}px`
|
||||||
|
|||||||
@@ -1,4 +1,10 @@
|
|||||||
import type { LexicalCommand, LexicalEditor, RangeSelection, TextNode } from 'lexical'
|
import type {
|
||||||
|
LexicalCommand,
|
||||||
|
LexicalEditor,
|
||||||
|
ParagraphNode,
|
||||||
|
RangeSelection,
|
||||||
|
TextNode,
|
||||||
|
} from 'lexical'
|
||||||
|
|
||||||
import { useLexicalComposerContext } from '@lexical/react/LexicalComposerContext'
|
import { useLexicalComposerContext } from '@lexical/react/LexicalComposerContext'
|
||||||
import { mergeRegister } from '@lexical/utils'
|
import { mergeRegister } from '@lexical/utils'
|
||||||
@@ -53,7 +59,8 @@ function tryToPositionRange(leadOffset: number, range: Range, editorWindow: Wind
|
|||||||
|
|
||||||
try {
|
try {
|
||||||
range.setStart(anchorNode, startOffset)
|
range.setStart(anchorNode, startOffset)
|
||||||
range.setEnd(anchorNode, endOffset)
|
// if endOffset is 0, positioning the range for when you click the plus button to open the slash menu will fial
|
||||||
|
range.setEnd(anchorNode, endOffset > 1 ? endOffset : 1)
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
@@ -176,7 +183,7 @@ export type TypeaheadMenuPluginProps = {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export const ENABLE_SLASH_MENU_COMMAND: LexicalCommand<{
|
export const ENABLE_SLASH_MENU_COMMAND: LexicalCommand<{
|
||||||
rect: DOMRect
|
node: ParagraphNode
|
||||||
}> = createCommand('ENABLE_SLASH_MENU_COMMAND')
|
}> = createCommand('ENABLE_SLASH_MENU_COMMAND')
|
||||||
|
|
||||||
export function LexicalTypeaheadMenuPlugin({
|
export function LexicalTypeaheadMenuPlugin({
|
||||||
@@ -215,7 +222,7 @@ export function LexicalTypeaheadMenuPlugin({
|
|||||||
return mergeRegister(
|
return mergeRegister(
|
||||||
editor.registerCommand(
|
editor.registerCommand(
|
||||||
ENABLE_SLASH_MENU_COMMAND,
|
ENABLE_SLASH_MENU_COMMAND,
|
||||||
({ rect }) => {
|
({ node }) => {
|
||||||
editor.getEditorState().read(() => {
|
editor.getEditorState().read(() => {
|
||||||
const match: MenuTextMatch = {
|
const match: MenuTextMatch = {
|
||||||
leadOffset: 0,
|
leadOffset: 0,
|
||||||
@@ -223,15 +230,22 @@ export function LexicalTypeaheadMenuPlugin({
|
|||||||
replaceableString: '',
|
replaceableString: '',
|
||||||
}
|
}
|
||||||
if (match !== null && !isSelectionOnEntityBoundary(editor, match.leadOffset)) {
|
if (match !== null && !isSelectionOnEntityBoundary(editor, match.leadOffset)) {
|
||||||
if (rect !== null) {
|
if (node !== null) {
|
||||||
|
const editorWindow = editor._window ?? window
|
||||||
|
const range = editorWindow.document.createRange()
|
||||||
|
|
||||||
|
const isRangePositioned = tryToPositionRange(match.leadOffset, range, editorWindow)
|
||||||
|
if (isRangePositioned !== null) {
|
||||||
startTransition(() =>
|
startTransition(() =>
|
||||||
openTypeahead({
|
openTypeahead({
|
||||||
getRect: () => {
|
getRect: () => {
|
||||||
return rect
|
return range.getBoundingClientRect()
|
||||||
},
|
},
|
||||||
match,
|
match,
|
||||||
}),
|
}),
|
||||||
)
|
)
|
||||||
|
}
|
||||||
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -270,7 +284,9 @@ export function LexicalTypeaheadMenuPlugin({
|
|||||||
if (isRangePositioned !== null) {
|
if (isRangePositioned !== null) {
|
||||||
startTransition(() =>
|
startTransition(() =>
|
||||||
openTypeahead({
|
openTypeahead({
|
||||||
getRect: () => range.getBoundingClientRect(),
|
getRect: () => {
|
||||||
|
return range.getBoundingClientRect()
|
||||||
|
},
|
||||||
match,
|
match,
|
||||||
}),
|
}),
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
html[data-theme='light'] {
|
html[data-theme='light'] {
|
||||||
.slash-menu {
|
.slash-menu {
|
||||||
box-shadow: 0px 6px 20px 0px rgba(0, 0, 0, 0.2);
|
@include shadow-m;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -12,6 +12,9 @@ html[data-theme='light'] {
|
|||||||
color: var(--color-base-800);
|
color: var(--color-base-800);
|
||||||
border-radius: 4px;
|
border-radius: 4px;
|
||||||
list-style: none;
|
list-style: none;
|
||||||
|
font-family: var(--font-body);
|
||||||
|
max-height: 300px;
|
||||||
|
overflow-y: scroll;
|
||||||
|
|
||||||
.group {
|
.group {
|
||||||
padding-bottom: 8px;
|
padding-bottom: 8px;
|
||||||
@@ -24,7 +27,10 @@ html[data-theme='light'] {
|
|||||||
}
|
}
|
||||||
|
|
||||||
.item {
|
.item {
|
||||||
padding-left: 8px;
|
all: unset;
|
||||||
|
padding-left: 12px;
|
||||||
|
font-size: 13px;
|
||||||
|
box-sizing: border-box;
|
||||||
background: none;
|
background: none;
|
||||||
border: none;
|
border: none;
|
||||||
color: var(--color-base-900);
|
color: var(--color-base-900);
|
||||||
|
|||||||
@@ -239,9 +239,9 @@ function useAddBlockHandle(
|
|||||||
if (!emptyBlockElem) {
|
if (!emptyBlockElem) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
let node: ParagraphNode
|
||||||
editor.update(() => {
|
editor.update(() => {
|
||||||
const node: ParagraphNode = $getNearestNodeFromDOMNode(emptyBlockElem) as ParagraphNode
|
node = $getNearestNodeFromDOMNode(emptyBlockElem) as ParagraphNode
|
||||||
if (!node || node.getType() !== 'paragraph') {
|
if (!node || node.getType() !== 'paragraph') {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@@ -257,7 +257,7 @@ function useAddBlockHandle(
|
|||||||
// Otherwise, this won't work
|
// Otherwise, this won't work
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
editor.dispatchCommand(ENABLE_SLASH_MENU_COMMAND, {
|
editor.dispatchCommand(ENABLE_SLASH_MENU_COMMAND, {
|
||||||
rect: emptyBlockElem.getBoundingClientRect(),
|
node: node,
|
||||||
})
|
})
|
||||||
}, 0)
|
}, 0)
|
||||||
|
|
||||||
|
|||||||
26
scripts/release_beta.sh
Executable file
26
scripts/release_beta.sh
Executable file
@@ -0,0 +1,26 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
|
||||||
|
set -ex
|
||||||
|
|
||||||
|
# Build packages/payload
|
||||||
|
|
||||||
|
package_name=$1
|
||||||
|
package_dir="packages/$package_name"
|
||||||
|
|
||||||
|
if [ -z "$package_name" ]; then
|
||||||
|
echo "Please specify a package to publish"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Check if packages/$package_name exists
|
||||||
|
|
||||||
|
if [ ! -d "$package_dir" ]; then
|
||||||
|
echo "Package $package_name does not exist"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
npm --prefix "$package_dir" version pre --preid beta
|
||||||
|
git add "$package_dir"/package.json
|
||||||
|
new_version=$(node -p "require('./$package_dir/package.json').version")
|
||||||
|
git commit -m "chore(release): $package_name@$new_version"
|
||||||
|
pnpm publish -C "$package_dir" --tag beta --no-git-checks
|
||||||
@@ -76,11 +76,11 @@ export function buildConfigWithDefaults(testConfig?: Partial<Config>): Promise<S
|
|||||||
...existingConfig.resolve?.alias,
|
...existingConfig.resolve?.alias,
|
||||||
[path.resolve(__dirname, '../packages/db-postgres/src/index')]: path.resolve(
|
[path.resolve(__dirname, '../packages/db-postgres/src/index')]: path.resolve(
|
||||||
__dirname,
|
__dirname,
|
||||||
'../packages/db-postgres/src/mock.js',
|
'../packages/db-postgres/mock.js',
|
||||||
),
|
),
|
||||||
[path.resolve(__dirname, '../packages/db-mongodb/src/index')]: path.resolve(
|
[path.resolve(__dirname, '../packages/db-mongodb/src/index')]: path.resolve(
|
||||||
__dirname,
|
__dirname,
|
||||||
'../packages/db-mongodb/src/mock.js',
|
'../packages/db-mongodb/mock.js',
|
||||||
),
|
),
|
||||||
[path.resolve(__dirname, '../packages/bundler-webpack/src/index')]: path.resolve(
|
[path.resolve(__dirname, '../packages/bundler-webpack/src/index')]: path.resolve(
|
||||||
__dirname,
|
__dirname,
|
||||||
@@ -88,7 +88,7 @@ export function buildConfigWithDefaults(testConfig?: Partial<Config>): Promise<S
|
|||||||
),
|
),
|
||||||
[path.resolve(__dirname, '../packages/bundler-vite/src/index')]: path.resolve(
|
[path.resolve(__dirname, '../packages/bundler-vite/src/index')]: path.resolve(
|
||||||
__dirname,
|
__dirname,
|
||||||
'../packages/bundler-vite/src/mock.js',
|
'../packages/bundler-vite/mock.js',
|
||||||
),
|
),
|
||||||
react: path.resolve(__dirname, '../packages/payload/node_modules/react'),
|
react: path.resolve(__dirname, '../packages/payload/node_modules/react'),
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -41,7 +41,7 @@ describe('Fields', () => {
|
|||||||
;({ serverURL } = await initPayloadTest({ __dirname, init: { local: false } }))
|
;({ serverURL } = await initPayloadTest({ __dirname, init: { local: false } }))
|
||||||
config = await configPromise
|
config = await configPromise
|
||||||
|
|
||||||
client = new RESTClient(config, { serverURL, defaultSlug: 'point-fields' })
|
client = new RESTClient(config, { defaultSlug: 'point-fields', serverURL })
|
||||||
const graphQLURL = `${serverURL}${config.routes.api}${config.routes.graphQL}`
|
const graphQLURL = `${serverURL}${config.routes.api}${config.routes.graphQL}`
|
||||||
graphQLClient = new GraphQLClient(graphQLURL)
|
graphQLClient = new GraphQLClient(graphQLURL)
|
||||||
token = await client.login()
|
token = await client.login()
|
||||||
@@ -64,7 +64,7 @@ describe('Fields', () => {
|
|||||||
})
|
})
|
||||||
|
|
||||||
it('should populate default values in beforeValidate hook', async () => {
|
it('should populate default values in beforeValidate hook', async () => {
|
||||||
const { fieldWithDefaultValue, dependentOnFieldWithDefaultValue } = await payload.create({
|
const { dependentOnFieldWithDefaultValue, fieldWithDefaultValue } = await payload.create({
|
||||||
collection: 'text-fields',
|
collection: 'text-fields',
|
||||||
data: { text },
|
data: { text },
|
||||||
})
|
})
|
||||||
@@ -89,10 +89,6 @@ describe('Fields', () => {
|
|||||||
depth: 0,
|
depth: 0,
|
||||||
where: {
|
where: {
|
||||||
updatedAt: {
|
updatedAt: {
|
||||||
// TODO:
|
|
||||||
// drizzle is not adjusting for timezones
|
|
||||||
// tenMinutesAgo: "2023-08-29T15:49:39.897Z" UTC
|
|
||||||
// doc.updatedAt: "2023-08-29T11:59:43.738Z" GMT -4
|
|
||||||
greater_than_equal: tenMinutesAgo,
|
greater_than_equal: tenMinutesAgo,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
@@ -121,15 +117,15 @@ describe('Fields', () => {
|
|||||||
beforeAll(async () => {
|
beforeAll(async () => {
|
||||||
const { id } = await payload.create({
|
const { id } = await payload.create({
|
||||||
collection: 'select-fields',
|
collection: 'select-fields',
|
||||||
locale: 'en',
|
|
||||||
data: {
|
data: {
|
||||||
selectHasManyLocalized: ['one', 'two'],
|
selectHasManyLocalized: ['one', 'two'],
|
||||||
},
|
},
|
||||||
|
locale: 'en',
|
||||||
})
|
})
|
||||||
doc = await payload.findByID({
|
doc = await payload.findByID({
|
||||||
|
id,
|
||||||
collection: 'select-fields',
|
collection: 'select-fields',
|
||||||
locale: 'all',
|
locale: 'all',
|
||||||
id,
|
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
@@ -146,8 +142,8 @@ describe('Fields', () => {
|
|||||||
})
|
})
|
||||||
|
|
||||||
const updatedDoc = await payload.update({
|
const updatedDoc = await payload.update({
|
||||||
collection: 'select-fields',
|
|
||||||
id,
|
id,
|
||||||
|
collection: 'select-fields',
|
||||||
data: {
|
data: {
|
||||||
select: 'one',
|
select: 'one',
|
||||||
},
|
},
|
||||||
@@ -245,15 +241,15 @@ describe('Fields', () => {
|
|||||||
const localizedHasMany = [5, 10]
|
const localizedHasMany = [5, 10]
|
||||||
const { id } = await payload.create({
|
const { id } = await payload.create({
|
||||||
collection: 'number-fields',
|
collection: 'number-fields',
|
||||||
locale: 'en',
|
|
||||||
data: {
|
data: {
|
||||||
localizedHasMany,
|
localizedHasMany,
|
||||||
},
|
},
|
||||||
|
locale: 'en',
|
||||||
})
|
})
|
||||||
const localizedDoc = await payload.findByID({
|
const localizedDoc = await payload.findByID({
|
||||||
|
id,
|
||||||
collection: 'number-fields',
|
collection: 'number-fields',
|
||||||
locale: 'all',
|
locale: 'all',
|
||||||
id,
|
|
||||||
})
|
})
|
||||||
|
|
||||||
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
||||||
@@ -284,81 +280,44 @@ describe('Fields', () => {
|
|||||||
it('should have indexes', () => {
|
it('should have indexes', () => {
|
||||||
expect(definitions.text).toEqual(1)
|
expect(definitions.text).toEqual(1)
|
||||||
})
|
})
|
||||||
|
|
||||||
it('should have unique indexes', () => {
|
it('should have unique indexes', () => {
|
||||||
expect(definitions.uniqueText).toEqual(1)
|
expect(definitions.uniqueText).toEqual(1)
|
||||||
expect(options.uniqueText).toMatchObject({ unique: true })
|
expect(options.uniqueText).toMatchObject({ unique: true })
|
||||||
})
|
})
|
||||||
it('should have 2dsphere indexes on point fields', () => {
|
|
||||||
expect(definitions.point).toEqual('2dsphere')
|
|
||||||
})
|
|
||||||
it('should have 2dsphere indexes on point fields in groups', () => {
|
|
||||||
expect(definitions['group.point']).toEqual('2dsphere')
|
|
||||||
})
|
|
||||||
it('should have a sparse index on a unique localized field in a group', () => {
|
|
||||||
expect(definitions['group.localizedUnique.en']).toEqual(1)
|
|
||||||
expect(options['group.localizedUnique.en']).toMatchObject({ unique: true, sparse: true })
|
|
||||||
expect(definitions['group.localizedUnique.es']).toEqual(1)
|
|
||||||
expect(options['group.localizedUnique.es']).toMatchObject({ unique: true, sparse: true })
|
|
||||||
})
|
|
||||||
it('should have unique indexes in a collapsible', () => {
|
|
||||||
expect(definitions['collapsibleLocalizedUnique.en']).toEqual(1)
|
|
||||||
expect(options['collapsibleLocalizedUnique.en']).toMatchObject({
|
|
||||||
unique: true,
|
|
||||||
sparse: true,
|
|
||||||
})
|
|
||||||
expect(definitions.collapsibleTextUnique).toEqual(1)
|
|
||||||
expect(options.collapsibleTextUnique).toMatchObject({ unique: true })
|
|
||||||
})
|
|
||||||
it('should have unique compound indexes', () => {
|
it('should have unique compound indexes', () => {
|
||||||
expect(definitions.partOne).toEqual(1)
|
expect(definitions.partOne).toEqual(1)
|
||||||
expect(options.partOne).toMatchObject({
|
expect(options.partOne).toMatchObject({
|
||||||
unique: true,
|
|
||||||
name: 'compound-index',
|
name: 'compound-index',
|
||||||
sparse: true,
|
sparse: true,
|
||||||
|
unique: true,
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
it('should throw validation error saving on unique fields', async () => {
|
|
||||||
const data = {
|
it('should have 2dsphere indexes on point fields', () => {
|
||||||
text: 'a',
|
expect(definitions.point).toEqual('2dsphere')
|
||||||
uniqueText: 'a',
|
|
||||||
}
|
|
||||||
await payload.create({
|
|
||||||
collection: 'indexed-fields',
|
|
||||||
data,
|
|
||||||
})
|
})
|
||||||
expect(async () => {
|
|
||||||
const result = await payload.create({
|
it('should have 2dsphere indexes on point fields in groups', () => {
|
||||||
collection: 'indexed-fields',
|
expect(definitions['group.point']).toEqual('2dsphere')
|
||||||
data,
|
|
||||||
})
|
})
|
||||||
return result.error
|
|
||||||
}).toBeDefined()
|
it('should have a sparse index on a unique localized field in a group', () => {
|
||||||
|
expect(definitions['group.localizedUnique.en']).toEqual(1)
|
||||||
|
expect(options['group.localizedUnique.en']).toMatchObject({ sparse: true, unique: true })
|
||||||
|
expect(definitions['group.localizedUnique.es']).toEqual(1)
|
||||||
|
expect(options['group.localizedUnique.es']).toMatchObject({ sparse: true, unique: true })
|
||||||
})
|
})
|
||||||
it('should throw validation error saving on unique combined fields', async () => {
|
|
||||||
await payload.delete({ collection: 'indexed-fields', where: {} })
|
it('should have unique indexes in a collapsible', () => {
|
||||||
const data1 = {
|
expect(definitions['collapsibleLocalizedUnique.en']).toEqual(1)
|
||||||
text: 'a',
|
expect(options['collapsibleLocalizedUnique.en']).toMatchObject({
|
||||||
uniqueText: 'a',
|
sparse: true,
|
||||||
partOne: 'u',
|
unique: true,
|
||||||
partTwo: 'u',
|
|
||||||
}
|
|
||||||
const data2 = {
|
|
||||||
text: 'b',
|
|
||||||
uniqueText: 'b',
|
|
||||||
partOne: 'u',
|
|
||||||
partTwo: 'u',
|
|
||||||
}
|
|
||||||
await payload.create({
|
|
||||||
collection: 'indexed-fields',
|
|
||||||
data: data1,
|
|
||||||
})
|
})
|
||||||
expect(async () => {
|
expect(definitions.collapsibleTextUnique).toEqual(1)
|
||||||
const result = await payload.create({
|
expect(options.collapsibleTextUnique).toMatchObject({ unique: true })
|
||||||
collection: 'indexed-fields',
|
|
||||||
data: data2,
|
|
||||||
})
|
|
||||||
return result.error
|
|
||||||
}).toBeDefined()
|
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
@@ -386,9 +345,9 @@ describe('Fields', () => {
|
|||||||
it('should have version indexes from collection indexes', () => {
|
it('should have version indexes from collection indexes', () => {
|
||||||
expect(definitions['version.partOne']).toEqual(1)
|
expect(definitions['version.partOne']).toEqual(1)
|
||||||
expect(options['version.partOne']).toMatchObject({
|
expect(options['version.partOne']).toMatchObject({
|
||||||
unique: true,
|
|
||||||
name: 'compound-index',
|
name: 'compound-index',
|
||||||
sparse: true,
|
sparse: true,
|
||||||
|
unique: true,
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
@@ -424,9 +383,9 @@ describe('Fields', () => {
|
|||||||
doc = await payload.create({
|
doc = await payload.create({
|
||||||
collection: 'point-fields',
|
collection: 'point-fields',
|
||||||
data: {
|
data: {
|
||||||
point,
|
|
||||||
localized,
|
|
||||||
group,
|
group,
|
||||||
|
localized,
|
||||||
|
point,
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
|
|
||||||
@@ -440,9 +399,9 @@ describe('Fields', () => {
|
|||||||
payload.create({
|
payload.create({
|
||||||
collection: 'point-fields',
|
collection: 'point-fields',
|
||||||
data: {
|
data: {
|
||||||
point,
|
|
||||||
localized,
|
|
||||||
group,
|
group,
|
||||||
|
localized,
|
||||||
|
point,
|
||||||
},
|
},
|
||||||
}),
|
}),
|
||||||
).rejects.toThrow(Error)
|
).rejects.toThrow(Error)
|
||||||
@@ -463,6 +422,52 @@ describe('Fields', () => {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
describe('unique indexes', () => {
|
||||||
|
it('should throw validation error saving on unique fields', async () => {
|
||||||
|
const data = {
|
||||||
|
text: 'a',
|
||||||
|
uniqueText: 'a',
|
||||||
|
}
|
||||||
|
await payload.create({
|
||||||
|
collection: 'indexed-fields',
|
||||||
|
data,
|
||||||
|
})
|
||||||
|
expect(async () => {
|
||||||
|
const result = await payload.create({
|
||||||
|
collection: 'indexed-fields',
|
||||||
|
data,
|
||||||
|
})
|
||||||
|
return result.error
|
||||||
|
}).toBeDefined()
|
||||||
|
})
|
||||||
|
it('should throw validation error saving on unique combined fields', async () => {
|
||||||
|
await payload.delete({ collection: 'indexed-fields', where: {} })
|
||||||
|
const data1 = {
|
||||||
|
partOne: 'u',
|
||||||
|
partTwo: 'u',
|
||||||
|
text: 'a',
|
||||||
|
uniqueText: 'a',
|
||||||
|
}
|
||||||
|
const data2 = {
|
||||||
|
partOne: 'u',
|
||||||
|
partTwo: 'u',
|
||||||
|
text: 'b',
|
||||||
|
uniqueText: 'b',
|
||||||
|
}
|
||||||
|
await payload.create({
|
||||||
|
collection: 'indexed-fields',
|
||||||
|
data: data1,
|
||||||
|
})
|
||||||
|
expect(async () => {
|
||||||
|
const result = await payload.create({
|
||||||
|
collection: 'indexed-fields',
|
||||||
|
data: data2,
|
||||||
|
})
|
||||||
|
return result.error
|
||||||
|
}).toBeDefined()
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
describe('array', () => {
|
describe('array', () => {
|
||||||
let doc
|
let doc
|
||||||
const collection = arrayFieldsSlug
|
const collection = arrayFieldsSlug
|
||||||
@@ -499,26 +504,26 @@ describe('Fields', () => {
|
|||||||
})
|
})
|
||||||
|
|
||||||
const enDoc = await payload.update({
|
const enDoc = await payload.update({
|
||||||
collection,
|
|
||||||
id,
|
id,
|
||||||
locale: 'en',
|
collection,
|
||||||
data: {
|
data: {
|
||||||
localized: [{ text: enText }],
|
localized: [{ text: enText }],
|
||||||
},
|
},
|
||||||
|
locale: 'en',
|
||||||
})
|
})
|
||||||
|
|
||||||
const esDoc = await payload.update({
|
const esDoc = await payload.update({
|
||||||
collection,
|
|
||||||
id,
|
id,
|
||||||
locale: 'es',
|
collection,
|
||||||
data: {
|
data: {
|
||||||
localized: [{ text: esText }],
|
localized: [{ text: esText }],
|
||||||
},
|
},
|
||||||
|
locale: 'es',
|
||||||
})
|
})
|
||||||
|
|
||||||
const allLocales = (await payload.findByID({
|
const allLocales = (await payload.findByID({
|
||||||
collection,
|
|
||||||
id,
|
id,
|
||||||
|
collection,
|
||||||
locale: 'all',
|
locale: 'all',
|
||||||
})) as unknown as { localized: { en: unknown; es: unknown } }
|
})) as unknown as { localized: { en: unknown; es: unknown } }
|
||||||
|
|
||||||
@@ -569,8 +574,8 @@ describe('Fields', () => {
|
|||||||
|
|
||||||
it('should create with localized text inside a named tab', async () => {
|
it('should create with localized text inside a named tab', async () => {
|
||||||
document = await payload.findByID({
|
document = await payload.findByID({
|
||||||
collection: tabsSlug,
|
|
||||||
id: document.id,
|
id: document.id,
|
||||||
|
collection: tabsSlug,
|
||||||
locale: 'all',
|
locale: 'all',
|
||||||
})
|
})
|
||||||
expect(document.localizedTab.en.text).toStrictEqual(localizedTextValue)
|
expect(document.localizedTab.en.text).toStrictEqual(localizedTextValue)
|
||||||
@@ -578,8 +583,8 @@ describe('Fields', () => {
|
|||||||
|
|
||||||
it('should allow access control on a named tab', async () => {
|
it('should allow access control on a named tab', async () => {
|
||||||
document = await payload.findByID({
|
document = await payload.findByID({
|
||||||
collection: tabsSlug,
|
|
||||||
id: document.id,
|
id: document.id,
|
||||||
|
collection: tabsSlug,
|
||||||
overrideAccess: false,
|
overrideAccess: false,
|
||||||
})
|
})
|
||||||
expect(document.accessControlTab).toBeUndefined()
|
expect(document.accessControlTab).toBeUndefined()
|
||||||
@@ -735,8 +740,8 @@ describe('Fields', () => {
|
|||||||
expect(jsonFieldsDoc.json.state).toEqual({})
|
expect(jsonFieldsDoc.json.state).toEqual({})
|
||||||
|
|
||||||
const updatedJsonFieldsDoc = await payload.update({
|
const updatedJsonFieldsDoc = await payload.update({
|
||||||
collection: 'json-fields',
|
|
||||||
id: jsonFieldsDoc.id,
|
id: jsonFieldsDoc.id,
|
||||||
|
collection: 'json-fields',
|
||||||
data: {
|
data: {
|
||||||
json: {
|
json: {
|
||||||
state: {},
|
state: {},
|
||||||
@@ -800,8 +805,8 @@ describe('Fields', () => {
|
|||||||
expect(nodes).toBeDefined()
|
expect(nodes).toBeDefined()
|
||||||
const child = nodes.flatMap((n) => n.children).find((c) => c.doc)
|
const child = nodes.flatMap((n) => n.children).find((c) => c.doc)
|
||||||
expect(child).toMatchObject({
|
expect(child).toMatchObject({
|
||||||
type: 'link',
|
|
||||||
linkType: 'internal',
|
linkType: 'internal',
|
||||||
|
type: 'link',
|
||||||
})
|
})
|
||||||
expect(child.doc.relationTo).toEqual('array-fields')
|
expect(child.doc.relationTo).toEqual('array-fields')
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user