Compare commits
1 Commits
db-postgre
...
fix/db-mon
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
44231b55cb |
18
CHANGELOG.md
18
CHANGELOG.md
@@ -1,21 +1,3 @@
|
|||||||
## [2.8.2](https://github.com/payloadcms/payload/compare/v2.8.1...v2.8.2) (2024-01-16)
|
|
||||||
|
|
||||||
|
|
||||||
### Features
|
|
||||||
|
|
||||||
* **db-postgres:** support drizzle logging config ([#4809](https://github.com/payloadcms/payload/issues/4809)) ([371353f](https://github.com/payloadcms/payload/commit/371353f1535fbab4ebd9f56fc14fd10a30eec289))
|
|
||||||
* **plugin-form-builder:** add validation for form ID when creating a submission
|
|
||||||
* **plugin-seo:** allow field and interface overrides
|
|
||||||
|
|
||||||
### Bug Fixes
|
|
||||||
|
|
||||||
* **db-mongodb:** mongodb versions creating duplicates ([#4825](https://github.com/payloadcms/payload/issues/4825)) ([a861311](https://github.com/payloadcms/payload/commit/a861311c5a98126700f98f9a2ab380782e754717))
|
|
||||||
* **db-mongodb:** transactionOptions=false typeErrors ([82383a5](https://github.com/payloadcms/payload/commit/82383a5b5f52785115c0feb970da70e91971b7ca))
|
|
||||||
* **db-postgres:** Remove duplicate keys from response ([#4747](https://github.com/payloadcms/payload/issues/4747)) ([eb9e771](https://github.com/payloadcms/payload/commit/eb9e771a9ca03636486d36654f215b73435574cb))
|
|
||||||
* **db-postgres:** validateExistingBlockIsIdentical with arrays ([3b88adc](https://github.com/payloadcms/payload/commit/3b88adc7d0594af63ce190c40c9ee3905df67a31))
|
|
||||||
* **db-postgres:** validateExistingBlockIsIdentical with other tables ([0647c87](https://github.com/payloadcms/payload/commit/0647c870f15dc1b122734b678c2abeb6f56377d4))
|
|
||||||
* removes max-width from field-types class & correctly sets it on uploads ([#4829](https://github.com/payloadcms/payload/issues/4829)) ([ee5390a](https://github.com/payloadcms/payload/commit/ee5390aaca37a4154cde8392b60f091ec3e5175c))
|
|
||||||
|
|
||||||
## [2.8.1](https://github.com/payloadcms/payload/compare/v2.8.0...v2.8.1) (2024-01-12)
|
## [2.8.1](https://github.com/payloadcms/payload/compare/v2.8.0...v2.8.1) (2024-01-12)
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -159,39 +159,6 @@ A function called by the search preview component to display the actual URL of y
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
#### `interfaceName`
|
|
||||||
|
|
||||||
Rename the meta group interface name that is generated for TypeScript and GraphQL.
|
|
||||||
|
|
||||||
```ts
|
|
||||||
// payload.config.ts
|
|
||||||
{
|
|
||||||
// ...
|
|
||||||
seoPlugin({
|
|
||||||
interfaceName: 'customInterfaceNameSEO'
|
|
||||||
})
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
#### `fieldOverrides`
|
|
||||||
|
|
||||||
Pass any valid field props to the base fields: Title, Description or Image.
|
|
||||||
|
|
||||||
```ts
|
|
||||||
// payload.config.ts
|
|
||||||
seoPlugin({
|
|
||||||
// ...
|
|
||||||
fieldOverrides: {
|
|
||||||
title: {
|
|
||||||
required: true,
|
|
||||||
},
|
|
||||||
description: {
|
|
||||||
localized: true,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
})
|
|
||||||
```
|
|
||||||
|
|
||||||
## TypeScript
|
## TypeScript
|
||||||
|
|
||||||
All types can be directly imported:
|
All types can be directly imported:
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@payloadcms/db-mongodb",
|
"name": "@payloadcms/db-mongodb",
|
||||||
"version": "1.3.2",
|
"version": "1.3.1",
|
||||||
"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",
|
||||||
|
|||||||
@@ -50,7 +50,7 @@ export const connect: Connect = async function connect(this: MongooseAdapter, pa
|
|||||||
|
|
||||||
const client = this.connection.getClient()
|
const client = this.connection.getClient()
|
||||||
|
|
||||||
if (!client.options.replicaSet) {
|
if (!client.options.replicaSet || this.transactionOptions === false) {
|
||||||
this.transactionOptions = false
|
this.transactionOptions = false
|
||||||
this.beginTransaction = undefined
|
this.beginTransaction = undefined
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -49,7 +49,6 @@ export const createGlobalVersion: CreateGlobalVersion = async function createGlo
|
|||||||
],
|
],
|
||||||
},
|
},
|
||||||
{ $unset: { latest: 1 } },
|
{ $unset: { latest: 1 } },
|
||||||
options,
|
|
||||||
)
|
)
|
||||||
|
|
||||||
const result: Document = JSON.parse(JSON.stringify(doc))
|
const result: Document = JSON.parse(JSON.stringify(doc))
|
||||||
|
|||||||
@@ -57,7 +57,6 @@ export const createVersion: CreateVersion = async function createVersion(
|
|||||||
],
|
],
|
||||||
},
|
},
|
||||||
{ $unset: { latest: 1 } },
|
{ $unset: { latest: 1 } },
|
||||||
options,
|
|
||||||
)
|
)
|
||||||
|
|
||||||
const result: Document = JSON.parse(JSON.stringify(doc))
|
const result: Document = JSON.parse(JSON.stringify(doc))
|
||||||
|
|||||||
@@ -63,7 +63,6 @@ export const find: Find = async function find(
|
|||||||
paginationOptions.useCustomCountFn = () => {
|
paginationOptions.useCustomCountFn = () => {
|
||||||
return Promise.resolve(
|
return Promise.resolve(
|
||||||
Model.countDocuments(query, {
|
Model.countDocuments(query, {
|
||||||
...options,
|
|
||||||
hint: { _id: 1 },
|
hint: { _id: 1 },
|
||||||
}),
|
}),
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -82,7 +82,6 @@ export const findGlobalVersions: FindGlobalVersions = async function findGlobalV
|
|||||||
paginationOptions.useCustomCountFn = () => {
|
paginationOptions.useCustomCountFn = () => {
|
||||||
return Promise.resolve(
|
return Promise.resolve(
|
||||||
Model.countDocuments(query, {
|
Model.countDocuments(query, {
|
||||||
...options,
|
|
||||||
hint: { _id: 1 },
|
hint: { _id: 1 },
|
||||||
}),
|
}),
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -79,7 +79,6 @@ export const findVersions: FindVersions = async function findVersions(
|
|||||||
paginationOptions.useCustomCountFn = () => {
|
paginationOptions.useCustomCountFn = () => {
|
||||||
return Promise.resolve(
|
return Promise.resolve(
|
||||||
Model.countDocuments(query, {
|
Model.countDocuments(query, {
|
||||||
...options,
|
|
||||||
hint: { _id: 1 },
|
hint: { _id: 1 },
|
||||||
}),
|
}),
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -93,13 +93,18 @@ export function mongooseAdapter({
|
|||||||
connectOptions,
|
connectOptions,
|
||||||
disableIndexHints = false,
|
disableIndexHints = false,
|
||||||
migrationDir: migrationDirArg,
|
migrationDir: migrationDirArg,
|
||||||
transactionOptions = {},
|
transactionOptions,
|
||||||
url,
|
url,
|
||||||
}: Args): MongooseAdapterResult {
|
}: Args): MongooseAdapterResult {
|
||||||
function adapter({ payload }: { payload: Payload }) {
|
function adapter({ payload }: { payload: Payload }) {
|
||||||
const migrationDir = findMigrationDir(migrationDirArg)
|
const migrationDir = findMigrationDir(migrationDirArg)
|
||||||
|
let beginTransactionFunction = beginTransaction
|
||||||
mongoose.set('strictQuery', false)
|
mongoose.set('strictQuery', false)
|
||||||
|
|
||||||
|
if (transactionOptions === false) {
|
||||||
|
beginTransactionFunction = () => null
|
||||||
|
}
|
||||||
|
|
||||||
return createDatabaseAdapter<MongooseAdapter>({
|
return createDatabaseAdapter<MongooseAdapter>({
|
||||||
name: 'mongoose',
|
name: 'mongoose',
|
||||||
|
|
||||||
@@ -117,7 +122,7 @@ export function mongooseAdapter({
|
|||||||
versions: {},
|
versions: {},
|
||||||
|
|
||||||
// DatabaseAdapter
|
// DatabaseAdapter
|
||||||
beginTransaction: transactionOptions ? beginTransaction : undefined,
|
beginTransaction: beginTransactionFunction,
|
||||||
commitTransaction,
|
commitTransaction,
|
||||||
connect,
|
connect,
|
||||||
create,
|
create,
|
||||||
|
|||||||
@@ -65,7 +65,8 @@ export const sanitizeQueryValue = ({
|
|||||||
if (field.type === 'date' && typeof val === 'string') {
|
if (field.type === 'date' && typeof val === 'string') {
|
||||||
formattedValue = new Date(val)
|
formattedValue = new Date(val)
|
||||||
if (Number.isNaN(Date.parse(formattedValue))) {
|
if (Number.isNaN(Date.parse(formattedValue))) {
|
||||||
return undefined
|
// ignore invalid query
|
||||||
|
return { rawQuery: {} }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@payloadcms/db-postgres",
|
"name": "@payloadcms/db-postgres",
|
||||||
"version": "0.4.0",
|
"version": "0.3.1",
|
||||||
"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",
|
||||||
@@ -22,8 +22,8 @@
|
|||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@libsql/client": "^0.3.1",
|
"@libsql/client": "^0.3.1",
|
||||||
"console-table-printer": "2.11.2",
|
"console-table-printer": "2.11.2",
|
||||||
"drizzle-kit": "0.20.5-608ae62",
|
"drizzle-kit": "0.19.13-e99bac1",
|
||||||
"drizzle-orm": "0.29.3",
|
"drizzle-orm": "0.28.5",
|
||||||
"pg": "8.11.3",
|
"pg": "8.11.3",
|
||||||
"prompts": "2.4.2",
|
"prompts": "2.4.2",
|
||||||
"to-snake-case": "1.0.0",
|
"to-snake-case": "1.0.0",
|
||||||
|
|||||||
@@ -18,9 +18,8 @@ export const connect: Connect = async function connect(this: PostgresAdapter, pa
|
|||||||
try {
|
try {
|
||||||
this.pool = new Pool(this.poolOptions)
|
this.pool = new Pool(this.poolOptions)
|
||||||
await this.pool.connect()
|
await this.pool.connect()
|
||||||
const logger = this.logger || false
|
|
||||||
|
|
||||||
this.drizzle = drizzle(this.pool, { schema: this.schema, logger })
|
this.drizzle = drizzle(this.pool, { schema: this.schema })
|
||||||
if (process.env.PAYLOAD_DROP_DATABASE === 'true') {
|
if (process.env.PAYLOAD_DROP_DATABASE === 'true') {
|
||||||
this.payload.logger.info('---- DROPPING TABLES ----')
|
this.payload.logger.info('---- DROPPING TABLES ----')
|
||||||
await this.drizzle.execute(sql`drop schema public cascade;
|
await this.drizzle.execute(sql`drop schema public cascade;
|
||||||
@@ -40,7 +39,7 @@ export const connect: Connect = async function connect(this: PostgresAdapter, pa
|
|||||||
)
|
)
|
||||||
return
|
return
|
||||||
|
|
||||||
const { pushSchema } = require('drizzle-kit/payload')
|
const { pushSchema } = require('drizzle-kit/utils')
|
||||||
|
|
||||||
// This will prompt if clarifications are needed for Drizzle to push new schema
|
// This will prompt if clarifications are needed for Drizzle to push new schema
|
||||||
const { apply, hasDataLoss, statementsToExecute, warnings } = await pushSchema(
|
const { apply, hasDataLoss, statementsToExecute, warnings } = await pushSchema(
|
||||||
@@ -60,9 +59,9 @@ export const connect: Connect = async function connect(this: PostgresAdapter, pa
|
|||||||
const { confirm: acceptWarnings } = await prompts(
|
const { confirm: acceptWarnings } = await prompts(
|
||||||
{
|
{
|
||||||
name: 'confirm',
|
name: 'confirm',
|
||||||
type: 'confirm',
|
|
||||||
initial: false,
|
initial: false,
|
||||||
message,
|
message,
|
||||||
|
type: 'confirm',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
onCancel: () => {
|
onCancel: () => {
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/* eslint-disable no-restricted-syntax, no-await-in-loop */
|
/* eslint-disable no-restricted-syntax, no-await-in-loop */
|
||||||
import type { DrizzleSnapshotJSON } from 'drizzle-kit/payload'
|
import type { DrizzleSnapshotJSON } from 'drizzle-kit/utils'
|
||||||
import type { CreateMigration } from 'payload/database'
|
import type { CreateMigration } from 'payload/database'
|
||||||
|
|
||||||
import fs from 'fs'
|
import fs from 'fs'
|
||||||
@@ -60,7 +60,7 @@ export const createMigration: CreateMigration = async function createMigration(
|
|||||||
fs.mkdirSync(dir)
|
fs.mkdirSync(dir)
|
||||||
}
|
}
|
||||||
|
|
||||||
const { generateDrizzleJson, generateMigration } = require('drizzle-kit/payload')
|
const { generateDrizzleJson, generateMigration } = require('drizzle-kit/utils')
|
||||||
|
|
||||||
const [yyymmdd, hhmmss] = new Date().toISOString().split('T')
|
const [yyymmdd, hhmmss] = new Date().toISOString().split('T')
|
||||||
const formattedDate = yyymmdd.replace(/\D/g, '')
|
const formattedDate = yyymmdd.replace(/\D/g, '')
|
||||||
@@ -99,9 +99,9 @@ export const createMigration: CreateMigration = async function createMigration(
|
|||||||
const { confirm: shouldCreateBlankMigration } = await prompts(
|
const { confirm: shouldCreateBlankMigration } = await prompts(
|
||||||
{
|
{
|
||||||
name: 'confirm',
|
name: 'confirm',
|
||||||
type: 'confirm',
|
|
||||||
initial: false,
|
initial: false,
|
||||||
message: 'No schema changes detected. Would you like to create a blank migration file?',
|
message: 'No schema changes detected. Would you like to create a blank migration file?',
|
||||||
|
type: 'confirm',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
onCancel: () => {
|
onCancel: () => {
|
||||||
|
|||||||
@@ -50,7 +50,6 @@ export function postgresAdapter(args: Args): PostgresAdapterResult {
|
|||||||
drizzle: undefined,
|
drizzle: undefined,
|
||||||
enums: {},
|
enums: {},
|
||||||
fieldConstraints: {},
|
fieldConstraints: {},
|
||||||
logger: args.logger,
|
|
||||||
pool: undefined,
|
pool: undefined,
|
||||||
poolOptions: args.pool,
|
poolOptions: args.pool,
|
||||||
push: args.push,
|
push: args.push,
|
||||||
|
|||||||
@@ -80,7 +80,7 @@ export async function migrate(this: PostgresAdapter): Promise<void> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async function runMigrationFile(payload: Payload, migration: Migration, batch: number) {
|
async function runMigrationFile(payload: Payload, migration: Migration, batch: number) {
|
||||||
const { generateDrizzleJson } = require('drizzle-kit/payload')
|
const { generateDrizzleJson } = require('drizzle-kit/utils')
|
||||||
|
|
||||||
const start = Date.now()
|
const start = Date.now()
|
||||||
const req = { payload } as PayloadRequest
|
const req = { payload } as PayloadRequest
|
||||||
|
|||||||
46
packages/db-postgres/src/reference.ts
Normal file
46
packages/db-postgres/src/reference.ts
Normal file
@@ -0,0 +1,46 @@
|
|||||||
|
// type GenerateMigration = (before: DrizzleSnapshotJSON, after: DrizzleSnapshotJSON) => string[]
|
||||||
|
|
||||||
|
// type GenerateDrizzleJSON = (schema: DrizzleSchemaExports) => DrizzleSnapshotJSON
|
||||||
|
|
||||||
|
// type PushDiff = (schema: DrizzleSchemaExports) => Promise<{ warnings: string[], apply: () => Promise<void> }>
|
||||||
|
|
||||||
|
// drizzle-kit@utils
|
||||||
|
|
||||||
|
import { drizzle } from 'drizzle-orm/node-postgres'
|
||||||
|
import { Pool } from 'pg'
|
||||||
|
|
||||||
|
async function generateUsage() {
|
||||||
|
const { generateDrizzleJson, generateMigration } = require('drizzle-kit/utils')
|
||||||
|
|
||||||
|
// @ts-expect-error Just TypeScript being broken // TODO: Open TypeScript issue
|
||||||
|
const schema = await import('./data/users')
|
||||||
|
// @ts-expect-error Just TypeScript being broken // TODO: Open TypeScript issue
|
||||||
|
const schemaAfter = await import('./data/users-after')
|
||||||
|
|
||||||
|
const drizzleJsonBefore = generateDrizzleJson(schema)
|
||||||
|
const drizzleJsonAfter = generateDrizzleJson(schemaAfter)
|
||||||
|
|
||||||
|
const sqlStatements = await generateMigration(drizzleJsonBefore, drizzleJsonAfter)
|
||||||
|
|
||||||
|
console.log(sqlStatements)
|
||||||
|
}
|
||||||
|
|
||||||
|
async function pushUsage() {
|
||||||
|
const { pushSchema } = require('drizzle-kit/utils')
|
||||||
|
|
||||||
|
// @ts-expect-error Just TypeScript being broken // TODO: Open TypeScript issue
|
||||||
|
const schemaAfter = await import('./data/users-after')
|
||||||
|
|
||||||
|
const db = drizzle(new Pool({ connectionString: '' }))
|
||||||
|
|
||||||
|
const response = await pushSchema(schemaAfter, db)
|
||||||
|
|
||||||
|
console.log('\n')
|
||||||
|
console.log('hasDataLoss: ', response.hasDataLoss)
|
||||||
|
console.log('warnings: ', response.warnings)
|
||||||
|
console.log('statements: ', response.statementsToExecute)
|
||||||
|
|
||||||
|
await response.apply()
|
||||||
|
|
||||||
|
process.exit(0)
|
||||||
|
}
|
||||||
@@ -16,10 +16,7 @@ const getFlattenedFieldNames = (fields: Field[], prefix: string = ''): string[]
|
|||||||
return fields.reduce((fieldsToUse, field) => {
|
return fields.reduce((fieldsToUse, field) => {
|
||||||
let fieldPrefix = prefix
|
let fieldPrefix = prefix
|
||||||
|
|
||||||
if (
|
if (field.type === 'blocks') {
|
||||||
['array', 'blocks', 'relationship', 'upload'].includes(field.type) ||
|
|
||||||
('hasMany' in field && field.hasMany === true)
|
|
||||||
) {
|
|
||||||
return fieldsToUse
|
return fieldsToUse
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -57,27 +54,29 @@ export const validateExistingBlockIsIdentical = ({
|
|||||||
rootTableName,
|
rootTableName,
|
||||||
table,
|
table,
|
||||||
}: Args): void => {
|
}: Args): void => {
|
||||||
const fieldNames = getFlattenedFieldNames(block.fields)
|
if (table) {
|
||||||
|
const fieldNames = getFlattenedFieldNames(block.fields)
|
||||||
|
|
||||||
const missingField =
|
const missingField =
|
||||||
// ensure every field from the config is in the matching table
|
// ensure every field from the config is in the matching table
|
||||||
fieldNames.find((name) => Object.keys(table).indexOf(name) === -1) ||
|
fieldNames.find((name) => Object.keys(table).indexOf(name) === -1) ||
|
||||||
// ensure every table column is matched for every field from the config
|
// ensure every table column is matched for every field from the config
|
||||||
Object.keys(table).find((fieldName) => {
|
Object.keys(table).find((fieldName) => {
|
||||||
if (!['_locale', '_order', '_parentID', '_path', '_uuid'].includes(fieldName)) {
|
if (!['_locale', '_order', '_parentID', '_path', '_uuid'].includes(fieldName)) {
|
||||||
return fieldNames.indexOf(fieldName) === -1
|
return fieldNames.indexOf(fieldName) === -1
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
if (missingField) {
|
if (missingField) {
|
||||||
throw new InvalidConfiguration(
|
throw new InvalidConfiguration(
|
||||||
`The table ${rootTableName} has multiple blocks with slug ${block.slug}, but the schemas do not match. One block includes the field ${missingField}, while the other block does not.`,
|
`The table ${rootTableName} has multiple blocks with slug ${block.slug}, but the schemas do not match. One block includes the field ${missingField}, while the other block does not.`,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (Boolean(localized) !== Boolean(table._locale)) {
|
if (Boolean(localized) !== Boolean(table._locale)) {
|
||||||
throw new InvalidConfiguration(
|
throw new InvalidConfiguration(
|
||||||
`The table ${rootTableName} has multiple blocks with slug ${block.slug}, but the schemas do not match. One is localized, but another is not. Block schemas of the same name must match exactly.`,
|
`The table ${rootTableName} has multiple blocks with slug ${block.slug}, but the schemas do not match. One is localized, but another is not. Block schemas of the same name must match exactly.`,
|
||||||
)
|
)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -7,8 +7,8 @@ import { fieldAffectsData } from 'payload/types'
|
|||||||
import type { BlocksMap } from '../../utilities/createBlocksMap'
|
import type { BlocksMap } from '../../utilities/createBlocksMap'
|
||||||
|
|
||||||
import { transformHasManyNumber } from './hasManyNumber'
|
import { transformHasManyNumber } from './hasManyNumber'
|
||||||
import { transformHasManyText } from './hasManyText'
|
|
||||||
import { transformRelationship } from './relationship'
|
import { transformRelationship } from './relationship'
|
||||||
|
import { transformHasManyText } from './hasManyText'
|
||||||
|
|
||||||
type TraverseFieldsArgs = {
|
type TraverseFieldsArgs = {
|
||||||
/**
|
/**
|
||||||
@@ -35,6 +35,10 @@ type TraverseFieldsArgs = {
|
|||||||
* An array of Payload fields to traverse
|
* An array of Payload fields to traverse
|
||||||
*/
|
*/
|
||||||
fields: (Field | TabAsField)[]
|
fields: (Field | TabAsField)[]
|
||||||
|
/**
|
||||||
|
* All hasMany text fields, as returned by Drizzle, keyed on an object by field path
|
||||||
|
*/
|
||||||
|
texts: Record<string, Record<string, unknown>[]>
|
||||||
/**
|
/**
|
||||||
* All hasMany number fields, as returned by Drizzle, keyed on an object by field path
|
* All hasMany number fields, as returned by Drizzle, keyed on an object by field path
|
||||||
*/
|
*/
|
||||||
@@ -51,10 +55,6 @@ type TraverseFieldsArgs = {
|
|||||||
* Data structure representing the nearest table from db
|
* Data structure representing the nearest table from db
|
||||||
*/
|
*/
|
||||||
table: Record<string, unknown>
|
table: Record<string, unknown>
|
||||||
/**
|
|
||||||
* All hasMany text fields, as returned by Drizzle, keyed on an object by field path
|
|
||||||
*/
|
|
||||||
texts: Record<string, Record<string, unknown>[]>
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Traverse fields recursively, transforming data
|
// Traverse fields recursively, transforming data
|
||||||
@@ -66,11 +66,11 @@ export const traverseFields = <T extends Record<string, unknown>>({
|
|||||||
deletions,
|
deletions,
|
||||||
fieldPrefix,
|
fieldPrefix,
|
||||||
fields,
|
fields,
|
||||||
|
texts,
|
||||||
numbers,
|
numbers,
|
||||||
path,
|
path,
|
||||||
relationships,
|
relationships,
|
||||||
table,
|
table,
|
||||||
texts,
|
|
||||||
}: TraverseFieldsArgs): T => {
|
}: TraverseFieldsArgs): T => {
|
||||||
const sanitizedPath = path ? `${path}.` : path
|
const sanitizedPath = path ? `${path}.` : path
|
||||||
|
|
||||||
@@ -83,11 +83,11 @@ export const traverseFields = <T extends Record<string, unknown>>({
|
|||||||
deletions,
|
deletions,
|
||||||
fieldPrefix,
|
fieldPrefix,
|
||||||
fields: field.tabs.map((tab) => ({ ...tab, type: 'tab' })),
|
fields: field.tabs.map((tab) => ({ ...tab, type: 'tab' })),
|
||||||
|
texts,
|
||||||
numbers,
|
numbers,
|
||||||
path,
|
path,
|
||||||
relationships,
|
relationships,
|
||||||
table,
|
table,
|
||||||
texts,
|
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -103,22 +103,17 @@ export const traverseFields = <T extends Record<string, unknown>>({
|
|||||||
deletions,
|
deletions,
|
||||||
fieldPrefix,
|
fieldPrefix,
|
||||||
fields: field.fields,
|
fields: field.fields,
|
||||||
|
texts,
|
||||||
numbers,
|
numbers,
|
||||||
path,
|
path,
|
||||||
relationships,
|
relationships,
|
||||||
table,
|
table,
|
||||||
texts,
|
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
if (fieldAffectsData(field)) {
|
if (fieldAffectsData(field)) {
|
||||||
const fieldName = `${fieldPrefix || ''}${field.name}`
|
const fieldName = `${fieldPrefix || ''}${field.name}`
|
||||||
const fieldData = table[fieldName]
|
const fieldData = table[fieldName]
|
||||||
|
|
||||||
if (fieldPrefix) {
|
|
||||||
deletions.push(() => delete table[fieldName])
|
|
||||||
}
|
|
||||||
|
|
||||||
if (field.type === 'array') {
|
if (field.type === 'array') {
|
||||||
if (Array.isArray(fieldData)) {
|
if (Array.isArray(fieldData)) {
|
||||||
if (field.localized) {
|
if (field.localized) {
|
||||||
@@ -140,17 +135,13 @@ export const traverseFields = <T extends Record<string, unknown>>({
|
|||||||
deletions,
|
deletions,
|
||||||
fieldPrefix: '',
|
fieldPrefix: '',
|
||||||
fields: field.fields,
|
fields: field.fields,
|
||||||
|
texts,
|
||||||
numbers,
|
numbers,
|
||||||
path: `${sanitizedPath}${field.name}.${row._order - 1}`,
|
path: `${sanitizedPath}${field.name}.${row._order - 1}`,
|
||||||
relationships,
|
relationships,
|
||||||
table: row,
|
table: row,
|
||||||
texts,
|
|
||||||
})
|
})
|
||||||
|
|
||||||
if ('_order' in rowResult) {
|
|
||||||
delete rowResult._order
|
|
||||||
}
|
|
||||||
|
|
||||||
arrayResult[locale].push(rowResult)
|
arrayResult[locale].push(rowResult)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -162,11 +153,6 @@ export const traverseFields = <T extends Record<string, unknown>>({
|
|||||||
row.id = row._uuid
|
row.id = row._uuid
|
||||||
delete row._uuid
|
delete row._uuid
|
||||||
}
|
}
|
||||||
|
|
||||||
if ('_order' in row) {
|
|
||||||
delete row._order
|
|
||||||
}
|
|
||||||
|
|
||||||
return traverseFields<T>({
|
return traverseFields<T>({
|
||||||
blocks,
|
blocks,
|
||||||
config,
|
config,
|
||||||
@@ -174,11 +160,11 @@ export const traverseFields = <T extends Record<string, unknown>>({
|
|||||||
deletions,
|
deletions,
|
||||||
fieldPrefix: '',
|
fieldPrefix: '',
|
||||||
fields: field.fields,
|
fields: field.fields,
|
||||||
|
texts,
|
||||||
numbers,
|
numbers,
|
||||||
path: `${sanitizedPath}${field.name}.${i}`,
|
path: `${sanitizedPath}${field.name}.${i}`,
|
||||||
relationships,
|
relationships,
|
||||||
table: row,
|
table: row,
|
||||||
texts,
|
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@@ -218,11 +204,11 @@ export const traverseFields = <T extends Record<string, unknown>>({
|
|||||||
deletions,
|
deletions,
|
||||||
fieldPrefix: '',
|
fieldPrefix: '',
|
||||||
fields: block.fields,
|
fields: block.fields,
|
||||||
|
texts,
|
||||||
numbers,
|
numbers,
|
||||||
path: `${blockFieldPath}.${row._order - 1}`,
|
path: `${blockFieldPath}.${row._order - 1}`,
|
||||||
relationships,
|
relationships,
|
||||||
table: row,
|
table: row,
|
||||||
texts,
|
|
||||||
})
|
})
|
||||||
|
|
||||||
delete blockResult._order
|
delete blockResult._order
|
||||||
@@ -249,11 +235,11 @@ export const traverseFields = <T extends Record<string, unknown>>({
|
|||||||
deletions,
|
deletions,
|
||||||
fieldPrefix: '',
|
fieldPrefix: '',
|
||||||
fields: block.fields,
|
fields: block.fields,
|
||||||
|
texts,
|
||||||
numbers,
|
numbers,
|
||||||
path: `${blockFieldPath}.${i}`,
|
path: `${blockFieldPath}.${i}`,
|
||||||
relationships,
|
relationships,
|
||||||
table: row,
|
table: row,
|
||||||
texts,
|
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -330,15 +316,15 @@ export const traverseFields = <T extends Record<string, unknown>>({
|
|||||||
transformHasManyText({
|
transformHasManyText({
|
||||||
field,
|
field,
|
||||||
locale,
|
locale,
|
||||||
ref: result,
|
|
||||||
textRows: texts,
|
textRows: texts,
|
||||||
|
ref: result,
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
} else {
|
} else {
|
||||||
transformHasManyText({
|
transformHasManyText({
|
||||||
field,
|
field,
|
||||||
ref: result,
|
|
||||||
textRows: textPathMatch,
|
textRows: textPathMatch,
|
||||||
|
ref: result,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -434,16 +420,13 @@ export const traverseFields = <T extends Record<string, unknown>>({
|
|||||||
deletions,
|
deletions,
|
||||||
fieldPrefix: groupFieldPrefix,
|
fieldPrefix: groupFieldPrefix,
|
||||||
fields: field.fields,
|
fields: field.fields,
|
||||||
|
texts,
|
||||||
numbers,
|
numbers,
|
||||||
path: `${sanitizedPath}${field.name}`,
|
path: `${sanitizedPath}${field.name}`,
|
||||||
relationships,
|
relationships,
|
||||||
table,
|
table,
|
||||||
texts,
|
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
if ('_order' in ref) {
|
|
||||||
delete ref._order
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
const groupData = {}
|
const groupData = {}
|
||||||
|
|
||||||
@@ -454,15 +437,12 @@ export const traverseFields = <T extends Record<string, unknown>>({
|
|||||||
deletions,
|
deletions,
|
||||||
fieldPrefix: groupFieldPrefix,
|
fieldPrefix: groupFieldPrefix,
|
||||||
fields: field.fields,
|
fields: field.fields,
|
||||||
|
texts,
|
||||||
numbers,
|
numbers,
|
||||||
path: `${sanitizedPath}${field.name}`,
|
path: `${sanitizedPath}${field.name}`,
|
||||||
relationships,
|
relationships,
|
||||||
table,
|
table,
|
||||||
texts,
|
|
||||||
})
|
})
|
||||||
if ('_order' in ref) {
|
|
||||||
delete ref._order
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
break
|
break
|
||||||
|
|||||||
@@ -1,7 +1,6 @@
|
|||||||
import type {
|
import type {
|
||||||
ColumnBaseConfig,
|
ColumnBaseConfig,
|
||||||
ColumnDataType,
|
ColumnDataType,
|
||||||
DrizzleConfig,
|
|
||||||
ExtractTablesWithRelations,
|
ExtractTablesWithRelations,
|
||||||
Relation,
|
Relation,
|
||||||
Relations,
|
Relations,
|
||||||
@@ -17,7 +16,6 @@ export type DrizzleDB = NodePgDatabase<Record<string, unknown>>
|
|||||||
export type Args = {
|
export type Args = {
|
||||||
migrationDir?: string
|
migrationDir?: string
|
||||||
pool: PoolConfig
|
pool: PoolConfig
|
||||||
logger?: DrizzleConfig['logger']
|
|
||||||
push?: boolean
|
push?: boolean
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -49,7 +47,6 @@ export type DrizzleTransaction = PgTransaction<
|
|||||||
|
|
||||||
export type PostgresAdapter = BaseDatabaseAdapter & {
|
export type PostgresAdapter = BaseDatabaseAdapter & {
|
||||||
drizzle: DrizzleDB
|
drizzle: DrizzleDB
|
||||||
logger: DrizzleConfig['logger']
|
|
||||||
enums: Record<string, GenericEnum>
|
enums: Record<string, GenericEnum>
|
||||||
pool: Pool
|
pool: Pool
|
||||||
poolOptions: Args['pool']
|
poolOptions: Args['pool']
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "payload",
|
"name": "payload",
|
||||||
"version": "2.8.2",
|
"version": "2.8.1",
|
||||||
"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": "./dist/index.js",
|
"main": "./dist/index.js",
|
||||||
|
|||||||
@@ -13,6 +13,7 @@
|
|||||||
|
|
||||||
& > .field-type {
|
& > .field-type {
|
||||||
margin-bottom: var(--spacing-field);
|
margin-bottom: var(--spacing-field);
|
||||||
|
max-width: 100%;
|
||||||
|
|
||||||
&[type='hidden'] {
|
&[type='hidden'] {
|
||||||
margin-bottom: 0;
|
margin-bottom: 0;
|
||||||
|
|||||||
@@ -2,7 +2,6 @@
|
|||||||
|
|
||||||
.upload {
|
.upload {
|
||||||
position: relative;
|
position: relative;
|
||||||
max-width: 100%;
|
|
||||||
|
|
||||||
&__wrap {
|
&__wrap {
|
||||||
background: var(--theme-elevation-50);
|
background: var(--theme-elevation-50);
|
||||||
|
|||||||
@@ -577,7 +577,7 @@ export type Block = {
|
|||||||
*/
|
*/
|
||||||
interfaceName?: string
|
interfaceName?: string
|
||||||
labels?: Labels
|
labels?: Labels
|
||||||
slug: string
|
slug: string,
|
||||||
/** Extension point to add your custom data. */
|
/** Extension point to add your custom data. */
|
||||||
custom?: Record<string, any>
|
custom?: Record<string, any>
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -22,7 +22,7 @@ type MetaDescriptionProps = TextareaField & {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export const MetaDescription: React.FC<MetaDescriptionProps> = (props) => {
|
export const MetaDescription: React.FC<MetaDescriptionProps> = (props) => {
|
||||||
const { name, label, path, pluginConfig, required } = props
|
const { name, label, path, pluginConfig } = props
|
||||||
|
|
||||||
const { t } = useTranslation('plugin-seo')
|
const { t } = useTranslation('plugin-seo')
|
||||||
|
|
||||||
@@ -36,7 +36,7 @@ export const MetaDescription: React.FC<MetaDescriptionProps> = (props) => {
|
|||||||
path,
|
path,
|
||||||
} as Options)
|
} as Options)
|
||||||
|
|
||||||
const { setValue, showError, value, errorMessage } = field
|
const { setValue, showError, value } = field
|
||||||
|
|
||||||
const regenerateDescription = useCallback(async () => {
|
const regenerateDescription = useCallback(async () => {
|
||||||
const { generateDescription } = pluginConfig
|
const { generateDescription } = pluginConfig
|
||||||
@@ -67,18 +67,6 @@ export const MetaDescription: React.FC<MetaDescriptionProps> = (props) => {
|
|||||||
>
|
>
|
||||||
<div>
|
<div>
|
||||||
{label && typeof label === 'string' && label}
|
{label && typeof label === 'string' && label}
|
||||||
|
|
||||||
{required && (
|
|
||||||
<span
|
|
||||||
style={{
|
|
||||||
marginLeft: '5px',
|
|
||||||
color: 'var(--theme-error-500)',
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
*
|
|
||||||
</span>
|
|
||||||
)}
|
|
||||||
|
|
||||||
{typeof pluginConfig.generateDescription === 'function' && (
|
{typeof pluginConfig.generateDescription === 'function' && (
|
||||||
<React.Fragment>
|
<React.Fragment>
|
||||||
—
|
—
|
||||||
@@ -129,8 +117,6 @@ export const MetaDescription: React.FC<MetaDescriptionProps> = (props) => {
|
|||||||
style={{
|
style={{
|
||||||
marginBottom: 0,
|
marginBottom: 0,
|
||||||
}}
|
}}
|
||||||
required={required}
|
|
||||||
errorMessage={errorMessage}
|
|
||||||
value={value}
|
value={value}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -19,7 +19,7 @@ type MetaImageProps = UploadInputProps & {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export const MetaImage: React.FC<MetaImageProps> = (props) => {
|
export const MetaImage: React.FC<MetaImageProps> = (props) => {
|
||||||
const { name, fieldTypes, label, pluginConfig, relationTo, required } = props || {}
|
const { name, fieldTypes, label, pluginConfig, relationTo } = props || {}
|
||||||
|
|
||||||
const field: FieldType<string> = useField(props as Options)
|
const field: FieldType<string> = useField(props as Options)
|
||||||
|
|
||||||
@@ -29,7 +29,7 @@ export const MetaImage: React.FC<MetaImageProps> = (props) => {
|
|||||||
const [fields] = useAllFormFields()
|
const [fields] = useAllFormFields()
|
||||||
const docInfo = useDocumentInfo()
|
const docInfo = useDocumentInfo()
|
||||||
|
|
||||||
const { setValue, showError, value, errorMessage } = field
|
const { setValue, showError, value } = field
|
||||||
|
|
||||||
const regenerateImage = useCallback(async () => {
|
const regenerateImage = useCallback(async () => {
|
||||||
const { generateImage } = pluginConfig
|
const { generateImage } = pluginConfig
|
||||||
@@ -68,18 +68,6 @@ export const MetaImage: React.FC<MetaImageProps> = (props) => {
|
|||||||
>
|
>
|
||||||
<div>
|
<div>
|
||||||
{label && typeof label === 'string' && label}
|
{label && typeof label === 'string' && label}
|
||||||
|
|
||||||
{required && (
|
|
||||||
<span
|
|
||||||
style={{
|
|
||||||
marginLeft: '5px',
|
|
||||||
color: 'var(--theme-error-500)',
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
*
|
|
||||||
</span>
|
|
||||||
)}
|
|
||||||
|
|
||||||
{typeof pluginConfig.generateImage === 'function' && (
|
{typeof pluginConfig.generateImage === 'function' && (
|
||||||
<React.Fragment>
|
<React.Fragment>
|
||||||
—
|
—
|
||||||
@@ -122,8 +110,6 @@ export const MetaImage: React.FC<MetaImageProps> = (props) => {
|
|||||||
collection={collection}
|
collection={collection}
|
||||||
fieldTypes={fieldTypes}
|
fieldTypes={fieldTypes}
|
||||||
filterOptions={{}}
|
filterOptions={{}}
|
||||||
errorMessage={errorMessage}
|
|
||||||
required={required}
|
|
||||||
label={undefined}
|
label={undefined}
|
||||||
name={name}
|
name={name}
|
||||||
onChange={(incomingImage) => {
|
onChange={(incomingImage) => {
|
||||||
|
|||||||
@@ -25,7 +25,7 @@ type MetaTitleProps = TextFieldType & {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export const MetaTitle: React.FC<MetaTitleProps> = (props) => {
|
export const MetaTitle: React.FC<MetaTitleProps> = (props) => {
|
||||||
const { name, label, path, pluginConfig, required } = props || {}
|
const { name, label, path, pluginConfig } = props || {}
|
||||||
|
|
||||||
const { t } = useTranslation('plugin-seo')
|
const { t } = useTranslation('plugin-seo')
|
||||||
|
|
||||||
@@ -39,7 +39,7 @@ export const MetaTitle: React.FC<MetaTitleProps> = (props) => {
|
|||||||
const [fields] = useAllFormFields()
|
const [fields] = useAllFormFields()
|
||||||
const docInfo = useDocumentInfo()
|
const docInfo = useDocumentInfo()
|
||||||
|
|
||||||
const { setValue, showError, value, errorMessage } = field
|
const { setValue, showError, value } = field
|
||||||
|
|
||||||
const regenerateTitle = useCallback(async () => {
|
const regenerateTitle = useCallback(async () => {
|
||||||
const { generateTitle } = pluginConfig
|
const { generateTitle } = pluginConfig
|
||||||
@@ -70,18 +70,6 @@ export const MetaTitle: React.FC<MetaTitleProps> = (props) => {
|
|||||||
>
|
>
|
||||||
<div>
|
<div>
|
||||||
{label && typeof label === 'string' && label}
|
{label && typeof label === 'string' && label}
|
||||||
|
|
||||||
{required && (
|
|
||||||
<span
|
|
||||||
style={{
|
|
||||||
marginLeft: '5px',
|
|
||||||
color: 'var(--theme-error-500)',
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
*
|
|
||||||
</span>
|
|
||||||
)}
|
|
||||||
|
|
||||||
{typeof pluginConfig.generateTitle === 'function' && (
|
{typeof pluginConfig.generateTitle === 'function' && (
|
||||||
<React.Fragment>
|
<React.Fragment>
|
||||||
—
|
—
|
||||||
@@ -133,8 +121,6 @@ export const MetaTitle: React.FC<MetaTitleProps> = (props) => {
|
|||||||
style={{
|
style={{
|
||||||
marginBottom: 0,
|
marginBottom: 0,
|
||||||
}}
|
}}
|
||||||
errorMessage={errorMessage}
|
|
||||||
required={required}
|
|
||||||
value={value}
|
value={value}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -30,7 +30,6 @@ const seo =
|
|||||||
},
|
},
|
||||||
label: 'Overview',
|
label: 'Overview',
|
||||||
},
|
},
|
||||||
// @ts-expect-error
|
|
||||||
{
|
{
|
||||||
name: 'title',
|
name: 'title',
|
||||||
type: 'text',
|
type: 'text',
|
||||||
@@ -40,7 +39,6 @@ const seo =
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
localized: true,
|
localized: true,
|
||||||
...(pluginConfig?.fieldOverrides?.title ?? {}),
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: 'description',
|
name: 'description',
|
||||||
@@ -51,7 +49,6 @@ const seo =
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
localized: true,
|
localized: true,
|
||||||
...(pluginConfig?.fieldOverrides?.description ?? {}),
|
|
||||||
},
|
},
|
||||||
...(pluginConfig?.uploadsCollection
|
...(pluginConfig?.uploadsCollection
|
||||||
? [
|
? [
|
||||||
@@ -69,7 +66,6 @@ const seo =
|
|||||||
label: 'Meta Image',
|
label: 'Meta Image',
|
||||||
localized: true,
|
localized: true,
|
||||||
relationTo: pluginConfig?.uploadsCollection,
|
relationTo: pluginConfig?.uploadsCollection,
|
||||||
...(pluginConfig?.fieldOverrides?.image ?? {}),
|
|
||||||
} as Field,
|
} as Field,
|
||||||
]
|
]
|
||||||
: []),
|
: []),
|
||||||
@@ -85,7 +81,6 @@ const seo =
|
|||||||
label: 'Preview',
|
label: 'Preview',
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
interfaceName: pluginConfig.interfaceName,
|
|
||||||
label: 'SEO',
|
label: 'SEO',
|
||||||
},
|
},
|
||||||
]
|
]
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
import type { ContextType } from 'payload/dist/admin/components/utilities/DocumentInfo/types'
|
import type { ContextType } from 'payload/dist/admin/components/utilities/DocumentInfo/types'
|
||||||
import type { Field, TextareaField, TextField, UploadField } from 'payload/dist/fields/config/types'
|
import type { Field } from 'payload/dist/fields/config/types'
|
||||||
|
|
||||||
export type GenerateTitle = <T = any>(
|
export type GenerateTitle = <T = any>(
|
||||||
args: ContextType & { doc: T; locale?: string },
|
args: ContextType & { doc: T; locale?: string },
|
||||||
@@ -29,12 +29,6 @@ export interface PluginConfig {
|
|||||||
generateURL?: GenerateURL
|
generateURL?: GenerateURL
|
||||||
globals?: string[]
|
globals?: string[]
|
||||||
tabbedUI?: boolean
|
tabbedUI?: boolean
|
||||||
fieldOverrides?: {
|
|
||||||
title?: Partial<TextField>
|
|
||||||
description?: Partial<TextareaField>
|
|
||||||
image?: Partial<UploadField>
|
|
||||||
}
|
|
||||||
interfaceName?: string
|
|
||||||
uploadsCollection?: string
|
uploadsCollection?: string
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -37,7 +37,7 @@ export const Preview: React.FC<PreviewProps> = (props) => {
|
|||||||
if (typeof generateURL === 'function' && !href) {
|
if (typeof generateURL === 'function' && !href) {
|
||||||
const newHref = await generateURL({
|
const newHref = await generateURL({
|
||||||
...docInfo,
|
...docInfo,
|
||||||
doc: { ...fields },
|
doc: { fields },
|
||||||
locale: typeof locale === 'object' ? locale?.code : locale,
|
locale: typeof locale === 'object' ? locale?.code : locale,
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|||||||
632
pnpm-lock.yaml
generated
632
pnpm-lock.yaml
generated
File diff suppressed because it is too large
Load Diff
@@ -41,7 +41,7 @@ export default buildConfigWithDefaults({
|
|||||||
{
|
{
|
||||||
name: 'blockTwoField',
|
name: 'blockTwoField',
|
||||||
type: 'text',
|
type: 'text',
|
||||||
},
|
}
|
||||||
],
|
],
|
||||||
custom: { description: 'The blockOne of this page' },
|
custom: { description: 'The blockOne of this page' },
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
import payload from '../../packages/payload/src'
|
import payload from '../../packages/payload/src'
|
||||||
import { initPayloadTest } from '../helpers/configHelpers'
|
import { initPayloadTest } from '../helpers/configHelpers'
|
||||||
import { BlockField } from 'payload/dist/fields/config/types'
|
import { BlockField } from "payload/dist/fields/config/types";
|
||||||
|
|
||||||
require('isomorphic-fetch')
|
require('isomorphic-fetch')
|
||||||
|
|
||||||
@@ -39,7 +39,7 @@ describe('Config', () => {
|
|||||||
|
|
||||||
it('allows a custom field in collection fields', () => {
|
it('allows a custom field in collection fields', () => {
|
||||||
const [collection] = payload.config.collections
|
const [collection] = payload.config.collections
|
||||||
const [field] = collection.fields
|
const [field,] = collection.fields
|
||||||
|
|
||||||
expect(field.custom).toEqual({ description: 'The title of this page' })
|
expect(field.custom).toEqual({ description: 'The title of this page' })
|
||||||
})
|
})
|
||||||
@@ -48,9 +48,7 @@ describe('Config', () => {
|
|||||||
const [collection] = payload.config.collections
|
const [collection] = payload.config.collections
|
||||||
const [, blocksField] = collection.fields
|
const [, blocksField] = collection.fields
|
||||||
|
|
||||||
expect((blocksField as BlockField).blocks[0].custom).toEqual({
|
expect((blocksField as BlockField).blocks[0].custom).toEqual({ description: 'The blockOne of this page' })
|
||||||
description: 'The blockOne of this page',
|
|
||||||
})
|
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|||||||
@@ -8,76 +8,77 @@
|
|||||||
|
|
||||||
export interface Config {
|
export interface Config {
|
||||||
collections: {
|
collections: {
|
||||||
pages: Page
|
pages: Page;
|
||||||
users: User
|
users: User;
|
||||||
'payload-preferences': PayloadPreference
|
'payload-preferences': PayloadPreference;
|
||||||
'payload-migrations': PayloadMigration
|
'payload-migrations': PayloadMigration;
|
||||||
}
|
};
|
||||||
globals: {
|
globals: {
|
||||||
'my-global': MyGlobal
|
'my-global': MyGlobal;
|
||||||
}
|
};
|
||||||
}
|
}
|
||||||
export interface Page {
|
export interface Page {
|
||||||
id: string
|
id: string;
|
||||||
title?: string | null
|
title?: string | null;
|
||||||
myBlocks?:
|
myBlocks?:
|
||||||
| {
|
| {
|
||||||
blockOneField?: string | null
|
blockOneField?: string | null;
|
||||||
blockTwoField?: string | null
|
blockTwoField?: string | null;
|
||||||
id?: string | null
|
id?: string | null;
|
||||||
blockName?: string | null
|
blockName?: string | null;
|
||||||
blockType: 'blockOne'
|
blockType: 'blockOne';
|
||||||
}[]
|
}[]
|
||||||
| null
|
| null;
|
||||||
updatedAt: string
|
updatedAt: string;
|
||||||
createdAt: string
|
createdAt: string;
|
||||||
}
|
}
|
||||||
export interface User {
|
export interface User {
|
||||||
id: string
|
id: string;
|
||||||
updatedAt: string
|
updatedAt: string;
|
||||||
createdAt: string
|
createdAt: string;
|
||||||
email: string
|
email: string;
|
||||||
resetPasswordToken?: string | null
|
resetPasswordToken?: string | null;
|
||||||
resetPasswordExpiration?: string | null
|
resetPasswordExpiration?: string | null;
|
||||||
salt?: string | null
|
salt?: string | null;
|
||||||
hash?: string | null
|
hash?: string | null;
|
||||||
loginAttempts?: number | null
|
loginAttempts?: number | null;
|
||||||
lockUntil?: string | null
|
lockUntil?: string | null;
|
||||||
password: string | null
|
password: string | null;
|
||||||
}
|
}
|
||||||
export interface PayloadPreference {
|
export interface PayloadPreference {
|
||||||
id: string
|
id: string;
|
||||||
user: {
|
user: {
|
||||||
relationTo: 'users'
|
relationTo: 'users';
|
||||||
value: string | User
|
value: string | User;
|
||||||
}
|
};
|
||||||
key?: string | null
|
key?: string | null;
|
||||||
value?:
|
value?:
|
||||||
| {
|
| {
|
||||||
[k: string]: unknown
|
[k: string]: unknown;
|
||||||
}
|
}
|
||||||
| unknown[]
|
| unknown[]
|
||||||
| string
|
| string
|
||||||
| number
|
| number
|
||||||
| boolean
|
| boolean
|
||||||
| null
|
| null;
|
||||||
updatedAt: string
|
updatedAt: string;
|
||||||
createdAt: string
|
createdAt: string;
|
||||||
}
|
}
|
||||||
export interface PayloadMigration {
|
export interface PayloadMigration {
|
||||||
id: string
|
id: string;
|
||||||
name?: string | null
|
name?: string | null;
|
||||||
batch?: number | null
|
batch?: number | null;
|
||||||
updatedAt: string
|
updatedAt: string;
|
||||||
createdAt: string
|
createdAt: string;
|
||||||
}
|
}
|
||||||
export interface MyGlobal {
|
export interface MyGlobal {
|
||||||
id: string
|
id: string;
|
||||||
title?: string | null
|
title?: string | null;
|
||||||
updatedAt?: string | null
|
updatedAt?: string | null;
|
||||||
createdAt?: string | null
|
createdAt?: string | null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
declare module 'payload' {
|
declare module 'payload' {
|
||||||
export interface GeneratedTypes extends Config {}
|
export interface GeneratedTypes extends Config {}
|
||||||
}
|
}
|
||||||
@@ -246,22 +246,6 @@ const BlockFields: CollectionConfig = {
|
|||||||
},
|
},
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
{
|
|
||||||
slug: 'block-b',
|
|
||||||
fields: [
|
|
||||||
{
|
|
||||||
name: 'items',
|
|
||||||
type: 'array',
|
|
||||||
fields: [
|
|
||||||
{
|
|
||||||
name: 'title2',
|
|
||||||
type: 'text',
|
|
||||||
required: true,
|
|
||||||
},
|
|
||||||
],
|
|
||||||
},
|
|
||||||
],
|
|
||||||
},
|
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -58,24 +58,6 @@ const GroupFields: CollectionConfig = {
|
|||||||
},
|
},
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
{
|
|
||||||
name: 'arrayOfGroups',
|
|
||||||
type: 'array',
|
|
||||||
defaultValue: [
|
|
||||||
{
|
|
||||||
groupItem: {
|
|
||||||
text: 'Hello world',
|
|
||||||
},
|
|
||||||
},
|
|
||||||
],
|
|
||||||
fields: [
|
|
||||||
{
|
|
||||||
name: 'groupItem',
|
|
||||||
type: 'group',
|
|
||||||
fields: [{ name: 'text', type: 'text' }],
|
|
||||||
},
|
|
||||||
],
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
name: 'potentiallyEmptyGroup',
|
name: 'potentiallyEmptyGroup',
|
||||||
type: 'group',
|
type: 'group',
|
||||||
|
|||||||
@@ -100,8 +100,8 @@ describe('Fields', () => {
|
|||||||
const { id } = await payload.create({
|
const { id } = await payload.create({
|
||||||
collection: 'text-fields',
|
collection: 'text-fields',
|
||||||
data: {
|
data: {
|
||||||
text,
|
|
||||||
localizedHasMany,
|
localizedHasMany,
|
||||||
|
text,
|
||||||
},
|
},
|
||||||
locale: 'en',
|
locale: 'en',
|
||||||
})
|
})
|
||||||
@@ -257,6 +257,20 @@ describe('Fields', () => {
|
|||||||
expect(docs.map(({ id }) => id)).toContain(doc.id)
|
expect(docs.map(({ id }) => id)).toContain(doc.id)
|
||||||
})
|
})
|
||||||
|
|
||||||
|
it('should not error using invalid date query', async () => {
|
||||||
|
const { result, status } = await client.find({
|
||||||
|
slug: 'date-fields',
|
||||||
|
query: {
|
||||||
|
updatedAt: {
|
||||||
|
like: 'invalid',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
})
|
||||||
|
|
||||||
|
expect(status).toStrictEqual(200)
|
||||||
|
expect(result.docs).toBeDefined()
|
||||||
|
})
|
||||||
|
|
||||||
it('should query createdAt', async () => {
|
it('should query createdAt', async () => {
|
||||||
const result = await payload.find({
|
const result = await payload.find({
|
||||||
collection: 'date-fields',
|
collection: 'date-fields',
|
||||||
@@ -268,7 +282,7 @@ describe('Fields', () => {
|
|||||||
},
|
},
|
||||||
})
|
})
|
||||||
|
|
||||||
expect(result.docs[0].id).toEqual(doc.id)
|
expect(result.docs[0].id).toStrictEqual(doc.id)
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
@@ -643,14 +657,6 @@ describe('Fields', () => {
|
|||||||
collection,
|
collection,
|
||||||
})
|
})
|
||||||
|
|
||||||
expect(result.items[0]).toMatchObject({
|
|
||||||
subArray: [
|
|
||||||
{
|
|
||||||
text: subArrayText,
|
|
||||||
},
|
|
||||||
],
|
|
||||||
text: 'test',
|
|
||||||
})
|
|
||||||
expect(result.items[0].subArray[0].text).toStrictEqual(subArrayText)
|
expect(result.items[0].subArray[0].text).toStrictEqual(subArrayText)
|
||||||
})
|
})
|
||||||
|
|
||||||
@@ -715,15 +721,6 @@ describe('Fields', () => {
|
|||||||
expect(document.group.defaultParent).toStrictEqual(groupDefaultValue)
|
expect(document.group.defaultParent).toStrictEqual(groupDefaultValue)
|
||||||
expect(document.group.defaultChild).toStrictEqual(groupDefaultChild)
|
expect(document.group.defaultChild).toStrictEqual(groupDefaultChild)
|
||||||
})
|
})
|
||||||
|
|
||||||
it('should not have duplicate keys', async () => {
|
|
||||||
expect(document.arrayOfGroups[0]).toMatchObject({
|
|
||||||
id: expect.any(String),
|
|
||||||
groupItem: {
|
|
||||||
text: 'Hello world',
|
|
||||||
},
|
|
||||||
})
|
|
||||||
})
|
|
||||||
})
|
})
|
||||||
|
|
||||||
describe('tabs', () => {
|
describe('tabs', () => {
|
||||||
@@ -1200,8 +1197,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({
|
||||||
linkType: 'internal',
|
|
||||||
type: 'link',
|
type: 'link',
|
||||||
|
linkType: 'internal',
|
||||||
})
|
})
|
||||||
expect(child.doc.relationTo).toEqual('array-fields')
|
expect(child.doc.relationTo).toEqual('array-fields')
|
||||||
|
|
||||||
|
|||||||
@@ -51,11 +51,6 @@ export default buildConfigWithDefaults({
|
|||||||
label: 'og:title',
|
label: 'og:title',
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
fieldOverrides: {
|
|
||||||
title: {
|
|
||||||
required: true,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
generateTitle: (data: any) => `Website.com — ${data?.doc?.title?.value}`,
|
generateTitle: (data: any) => `Website.com — ${data?.doc?.title?.value}`,
|
||||||
generateDescription: ({ doc }: any) => doc?.excerpt?.value,
|
generateDescription: ({ doc }: any) => doc?.excerpt?.value,
|
||||||
generateURL: ({ doc, locale }: any) =>
|
generateURL: ({ doc, locale }: any) =>
|
||||||
|
|||||||
@@ -78,15 +78,6 @@ describe('SEO Plugin', () => {
|
|||||||
await expect(metaTitle).toHaveValue('Website.com — Test Page')
|
await expect(metaTitle).toHaveValue('Website.com — Test Page')
|
||||||
})
|
})
|
||||||
|
|
||||||
// todo: Re-enable this test once required attributes are fixed
|
|
||||||
/* test('Title should be required as per custom override', async () => {
|
|
||||||
const metaTitleClass = '#field-title'
|
|
||||||
|
|
||||||
const metaTitle = page.locator(metaTitleClass).nth(0)
|
|
||||||
|
|
||||||
await expect(metaTitle).toHaveAttribute('required', '')
|
|
||||||
}) */
|
|
||||||
|
|
||||||
test('Indicator should be orangered and characters counted', async () => {
|
test('Indicator should be orangered and characters counted', async () => {
|
||||||
const indicatorClass =
|
const indicatorClass =
|
||||||
'#field-meta > div > div.render-fields.render-fields--margins-small > div:nth-child(2) > div:nth-child(3) > div > div:nth-child(3) > div'
|
'#field-meta > div > div.render-fields.render-fields--margins-small > div:nth-child(2) > div:nth-child(3) > div > div:nth-child(3) > div'
|
||||||
|
|||||||
@@ -31,9 +31,6 @@ describe('SEO Plugin', () => {
|
|||||||
data: {
|
data: {
|
||||||
title: 'Test page',
|
title: 'Test page',
|
||||||
slug: 'test-page',
|
slug: 'test-page',
|
||||||
meta: {
|
|
||||||
title: 'Test page',
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
depth: 0,
|
depth: 0,
|
||||||
})
|
})
|
||||||
|
|||||||
Reference in New Issue
Block a user