chore: passing field tests

This commit is contained in:
James
2023-09-27 16:25:23 -04:00
parent 6e81fa68e8
commit 09883ee78c
12 changed files with 154 additions and 51 deletions

View File

@@ -1,7 +1,7 @@
import { formatJSONPathSegment } from './formatJSONPathSegment'
export const convertPathToJSONTraversal = (path: string) => {
const segments = path.split('.')
export const convertPathToJSONTraversal = (incomingSegments: string[]) => {
const segments = [...incomingSegments]
segments.shift()
return segments.reduce((res, segment, i) => {

View File

@@ -45,7 +45,7 @@ type CreateConstraintArgs = {
}
const createConstraint = ({ operator, pathSegments, value }: CreateConstraintArgs): string => {
const jsonQuery = convertPathToJSONTraversal(pathSegments.join('.'))
const jsonQuery = convertPathToJSONTraversal(pathSegments)
return `${pathSegments[0]}${jsonQuery} ${operatorMap[operator]} '${value}'`
}

View File

@@ -24,6 +24,7 @@ type TableColumn = {
constraints: Constraint[]
field: FieldAffectingData
getNotNullColumnByValue?: (val: unknown) => string
pathSegments?: string[]
rawColumn?: SQL
table: GenericTable
}
@@ -56,12 +57,13 @@ export const getTableColumnFromPath = ({
fields,
joinAliases,
joins,
locale,
pathSegments,
locale: incomingLocale,
pathSegments: incomingSegments,
selectFields,
tableName,
}: Args): TableColumn => {
const fieldPath = pathSegments[0]
const fieldPath = incomingSegments[0]
let locale = incomingLocale
const field = flattenTopLevelFields(fields as Field[]).find(
(fieldToFind) => fieldAffectsData(fieldToFind) && fieldToFind.name === fieldPath,
) as Field | TabAsField
@@ -81,6 +83,21 @@ export const getTableColumnFromPath = ({
}
if (field) {
const pathSegments = [...incomingSegments]
// If next segment is a locale,
// we need to take it out and use it as the locale from this point on
if ('localized' in field && field.localized && adapter.payload.config.localization) {
const matchedLocale = adapter.payload.config.localization.localeCodes.find(
(locale) => locale === pathSegments[1],
)
if (matchedLocale) {
locale = matchedLocale
pathSegments.splice(1, 1)
}
}
switch (field.type) {
case 'tabs': {
return getTableColumnFromPath({
@@ -204,7 +221,7 @@ export const getTableColumnFromPath = ({
let blockTableColumn: TableColumn
let newTableName: string
const hasBlockField = field.blocks.some((block) => {
newTableName = `${tableName}_${toSnakeCase(block.slug)}`
newTableName = `${tableName}_blocks_${toSnakeCase(block.slug)}`
let result
const blockConstraints = []
const blockSelectFields = {}
@@ -255,6 +272,7 @@ export const getTableColumnFromPath = ({
columnName: blockTableColumn.columnName,
constraints,
field: blockTableColumn.field,
pathSegments: pathSegments.slice(1),
rawColumn: blockTableColumn.rawColumn,
table: adapter.tables[newTableName],
}
@@ -381,6 +399,7 @@ export const getTableColumnFromPath = ({
columnName: `${columnPrefix}${field.name}`,
constraints,
field,
pathSegments: pathSegments,
table: targetTable,
}
}

View File

@@ -82,6 +82,7 @@ export async function parseParams({
constraints: queryConstraints,
field,
getNotNullColumnByValue,
pathSegments,
rawColumn,
table,
} = getTableColumnFromPath({
@@ -102,14 +103,14 @@ export async function parseParams({
constraints.push(operatorMap.equals(constraintTable[col], value))
})
if (['json', 'richText'].includes(field.type)) {
const pathSegments = relationOrPath.split('.').slice(1)
pathSegments.unshift(table[columnName].name)
if (['json', 'richText'].includes(field.type) && Array.isArray(pathSegments)) {
const segments = pathSegments.slice(1)
segments.unshift(table[columnName].name)
if (field.type === 'richText') {
const jsonQuery = createJSONQuery({
operator,
pathSegments,
pathSegments: segments,
treatAsArray: ['children'],
treatRootAsArray: true,
value: val,
@@ -119,7 +120,7 @@ export async function parseParams({
}
if (field.type === 'json') {
const jsonQuery = convertPathToJSONTraversal(relationOrPath)
const jsonQuery = convertPathToJSONTraversal(pathSegments)
constraints.push(sql.raw(`${table[columnName].name}${jsonQuery} = '%${val}%'`))
}

View File

@@ -29,6 +29,9 @@ type Args = {
buildRelationships?: boolean
disableUnique: boolean
fields: Field[]
rootRelationsToBuild?: Map<string, string>
rootTableIDColType?: string
rootTableName?: string
tableName: string
timestamps?: boolean
}
@@ -44,6 +47,9 @@ export const buildTable = ({
buildRelationships,
disableUnique = false,
fields,
rootRelationsToBuild,
rootTableIDColType,
rootTableName,
tableName,
timestamps,
}: Args): Result => {
@@ -100,6 +106,9 @@ export const buildTable = ({
parentTableName: tableName,
relationsToBuild,
relationships,
rootRelationsToBuild: rootRelationsToBuild || relationsToBuild,
rootTableIDColType: rootTableIDColType || idColType,
rootTableName: rootTableName || tableName,
}))
if (timestamps) {

View File

@@ -28,6 +28,7 @@ import { hasLocalesTable } from '../utilities/hasLocalesTable'
import { buildTable } from './build'
import { createIndex } from './createIndex'
import { parentIDColumnMap } from './parentIDColumnMap'
import { validateExistingBlockIsIdentical } from './validateExistingBlockIsIdentical'
type Args = {
adapter: PostgresAdapter
@@ -45,6 +46,9 @@ type Args = {
parentTableName: string
relationsToBuild: Map<string, string>
relationships: Set<string>
rootRelationsToBuild?: Map<string, string>
rootTableIDColType: string
rootTableName: string
}
type Result = {
@@ -70,6 +74,9 @@ export const traverseFields = ({
parentTableName,
relationsToBuild,
relationships,
rootRelationsToBuild,
rootTableIDColType,
rootTableName,
}: Args): Result => {
let hasLocalizedField = false
let hasLocalizedRelationshipField = false
@@ -89,7 +96,9 @@ export const traverseFields = ({
let targetIndexes = indexes
if (fieldAffectsData(field)) {
columnName = `${columnPrefix || ''}${field.name[0] === '_' ? '_' : ''}${toSnakeCase(field.name)}`
columnName = `${columnPrefix || ''}${field.name[0] === '_' ? '_' : ''}${toSnakeCase(
field.name,
)}`
fieldName = `${fieldPrefix || ''}${field.name}`
// If field is localized,
@@ -271,6 +280,9 @@ export const traverseFields = ({
baseExtraConfig,
disableUnique,
fields: field.fields,
rootRelationsToBuild,
rootTableIDColType,
rootTableName,
tableName: arrayTableName,
})
@@ -302,12 +314,12 @@ export const traverseFields = ({
case 'blocks': {
field.blocks.forEach((block) => {
const blockTableName = `${newTableName}_${toSnakeCase(block.slug)}`
const blockTableName = `${rootTableName}_blocks_${toSnakeCase(block.slug)}`
if (!adapter.tables[blockTableName]) {
const baseColumns: Record<string, PgColumnBuilder> = {
_order: integer('_order').notNull(),
_parentID: parentIDColumnMap[parentIDColType]('_parent_id')
.references(() => adapter.tables[parentTableName].id, { onDelete: 'cascade' })
_parentID: parentIDColumnMap[rootTableIDColType]('_parent_id')
.references(() => adapter.tables[rootTableName].id, { onDelete: 'cascade' })
.notNull(),
_path: text('_path').notNull(),
}
@@ -332,6 +344,9 @@ export const traverseFields = ({
baseExtraConfig,
disableUnique,
fields: block.fields,
rootRelationsToBuild,
rootTableIDColType,
rootTableName,
tableName: blockTableName,
})
@@ -339,9 +354,9 @@ export const traverseFields = ({
adapter.tables[blockTableName],
({ many, one }) => {
const result: Record<string, Relation<string>> = {
_parentID: one(adapter.tables[parentTableName], {
_parentID: one(adapter.tables[rootTableName], {
fields: [adapter.tables[blockTableName]._parentID],
references: [adapter.tables[parentTableName].id],
references: [adapter.tables[rootTableName].id],
}),
}
@@ -358,9 +373,16 @@ export const traverseFields = ({
)
adapter.relations[`relations_${blockTableName}`] = blockTableRelations
} else if (process.env.NODE_ENV !== 'production') {
validateExistingBlockIsIdentical({
block,
localized: field.localized,
rootTableName,
table: adapter.tables[blockTableName],
})
}
relationsToBuild.set(`_blocks_${block.slug}`, blockTableName)
rootRelationsToBuild.set(`_blocks_${block.slug}`, blockTableName)
})
break
@@ -390,6 +412,9 @@ export const traverseFields = ({
parentTableName,
relationsToBuild,
relationships,
rootRelationsToBuild,
rootTableIDColType,
rootTableName,
})
if (groupHasLocalizedField) hasLocalizedField = true
@@ -420,6 +445,9 @@ export const traverseFields = ({
parentTableName,
relationsToBuild,
relationships,
rootRelationsToBuild,
rootTableIDColType,
rootTableName,
})
if (groupHasLocalizedField) hasLocalizedField = true
@@ -451,6 +479,9 @@ export const traverseFields = ({
parentTableName,
relationsToBuild,
relationships,
rootRelationsToBuild,
rootTableIDColType,
rootTableName,
})
if (tabHasLocalizedField) hasLocalizedField = true
@@ -484,6 +515,9 @@ export const traverseFields = ({
parentTableName,
relationsToBuild,
relationships,
rootRelationsToBuild,
rootTableIDColType,
rootTableName,
})
if (rowHasLocalizedField) hasLocalizedField = true

View File

@@ -0,0 +1,40 @@
import type { Block } from 'payload/types'
import { InvalidConfiguration } from 'payload/errors'
import { flattenTopLevelFields } from 'payload/utilities'
import type { GenericTable } from '../types'
type Args = {
block: Block
localized: boolean
rootTableName: string
table: GenericTable
}
export const validateExistingBlockIsIdentical = ({
block,
localized,
rootTableName,
table,
}: Args): void => {
if (table) {
const fieldNames = flattenTopLevelFields(block.fields).flatMap((field) => field.name)
Object.keys(table).forEach((fieldName) => {
if (!['_locale', '_order', '_parentID', '_path'].includes(fieldName)) {
if (fieldNames.indexOf(fieldName) === -1) {
throw new InvalidConfiguration(
`The table ${rootTableName} has multiple blocks with slug ${block.slug}, but the schemas do not match. One block includes the field ${fieldName}, while the other block does not.`,
)
}
}
})
if (Boolean(localized) !== Boolean(table._locale)) {
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.`,
)
}
}
}

View File

@@ -54,7 +54,7 @@ export const transformBlocks = ({
if (field.localized && locale) newRow.row._locale = locale
const blockTableName = `${baseTableName}_${blockType}`
const blockTableName = `${baseTableName}_blocks_${blockType}`
traverseFields({
arrays: newRow.arrays,

View File

@@ -185,12 +185,12 @@ export const upsertRow = async <T extends TypeWithID>({
parentID: insertedRow.id,
pathColumnName: '_path',
rows: blockRows.map(({ row }) => row),
tableName: `${tableName}_${blockName}`,
tableName: `${tableName}_blocks_${blockName}`,
})
}
insertedBlockRows[blockName] = await db
.insert(adapter.tables[`${tableName}_${blockName}`])
.insert(adapter.tables[`${tableName}_blocks_${blockName}`])
.values(blockRows.map(({ row }) => row))
.returning()
@@ -217,7 +217,7 @@ export const upsertRow = async <T extends TypeWithID>({
if (blockLocaleRowsToInsert.length > 0) {
await db
.insert(adapter.tables[`${tableName}_${blockName}_locales`])
.insert(adapter.tables[`${tableName}_blocks_${blockName}_locales`])
.values(blockLocaleRowsToInsert)
.returning()
}

View File

@@ -1,10 +1,10 @@
import type { CollectionConfig } from '../../../../packages/payload/src/collections/config/types'
import type { Field } from '../../../../packages/payload/src/fields/config/types'
import type { BlockField } from '../../../../packages/payload/src/fields/config/types'
export const blocksFieldSeedData = [
export const getBlocksFieldSeedData = (prefix?: string): any => [
{
blockName: 'First block',
blockType: 'text',
blockType: prefix ? `${prefix}Content` : 'content',
text: 'first block',
richText: [
{
@@ -14,12 +14,12 @@ export const blocksFieldSeedData = [
},
{
blockName: 'Second block',
blockType: 'number',
blockType: prefix ? `${prefix}Number` : 'number',
number: 342,
},
{
blockName: 'Sub-block demonstration',
blockType: 'subBlocks',
blockType: prefix ? `${prefix}SubBlocks` : 'subBlocks',
subBlocks: [
{
blockName: 'First sub block',
@@ -38,15 +38,15 @@ export const blocksFieldSeedData = [
blockType: 'i18n-text',
text: 'first block',
},
] as const
]
export const blocksField: Field = {
export const getBlocksField = (prefix?: string): BlockField => ({
name: 'blocks',
type: 'blocks',
required: true,
blocks: [
{
slug: 'text',
slug: prefix ? `${prefix}Content` : 'content',
fields: [
{
name: 'text',
@@ -60,7 +60,7 @@ export const blocksField: Field = {
],
},
{
slug: 'number',
slug: prefix ? `${prefix}Number` : 'number',
fields: [
{
name: 'number',
@@ -70,7 +70,7 @@ export const blocksField: Field = {
],
},
{
slug: 'subBlocks',
slug: prefix ? `${prefix}SubBlocks` : 'subBlocks',
fields: [
{
type: 'collapsible',
@@ -107,7 +107,7 @@ export const blocksField: Field = {
],
},
{
slug: 'tabs',
slug: prefix ? `${prefix}Tabs` : 'tabs',
fields: [
{
type: 'tabs',
@@ -143,15 +143,15 @@ export const blocksField: Field = {
],
},
],
defaultValue: blocksFieldSeedData,
}
defaultValue: getBlocksFieldSeedData(prefix),
})
const BlockFields: CollectionConfig = {
slug: 'block-fields',
fields: [
blocksField,
getBlocksField(),
{
...blocksField,
...getBlocksField('localized'),
name: 'collapsedByDefaultBlocks',
localized: true,
admin: {
@@ -159,7 +159,7 @@ const BlockFields: CollectionConfig = {
},
},
{
...blocksField,
...getBlocksField('localized'),
name: 'localizedBlocks',
localized: true,
},
@@ -247,8 +247,8 @@ const BlockFields: CollectionConfig = {
}
export const blocksDoc = {
blocks: blocksFieldSeedData,
localizedBlocks: blocksFieldSeedData,
blocks: getBlocksFieldSeedData(),
localizedBlocks: getBlocksFieldSeedData('localized'),
}
export default BlockFields

View File

@@ -1,7 +1,7 @@
/* eslint-disable no-param-reassign */
import type { CollectionConfig } from '../../../../packages/payload/src/collections/config/types'
import { blocksField, blocksFieldSeedData } from '../Blocks'
import { getBlocksField, getBlocksFieldSeedData } from '../Blocks'
import { UIField } from './UIField'
import { localizedTextValue, namedTabDefaultValue, namedTabText, tabsSlug } from './constants'
@@ -50,7 +50,7 @@ const TabsFields: CollectionConfig = {
{
label: 'Tab with Blocks',
description: 'Blocks are rendered here to ensure they populate and render correctly.',
fields: [blocksField],
fields: [getBlocksField()],
},
{
label: 'Tab with Group',
@@ -277,7 +277,7 @@ export const tabsDoc = {
text: 'Here is some data for the third row',
},
],
blocks: blocksFieldSeedData,
blocks: getBlocksFieldSeedData(),
group: {
number: 12,
},

View File

@@ -11,7 +11,7 @@ import { initPayloadTest } from '../helpers/configHelpers'
import { RESTClient } from '../helpers/rest'
import configPromise from '../uploads/config'
import { arrayDefaultValue, arrayFieldsSlug } from './collections/Array'
import { blocksFieldSeedData } from './collections/Blocks'
import { blocksDoc } from './collections/Blocks'
import { dateDoc } from './collections/Date'
import {
groupDefaultChild,
@@ -612,16 +612,16 @@ describe('Fields', () => {
collection: 'block-fields',
})
expect(blockFields.docs[0].blocks[0].blockType).toEqual(blocksFieldSeedData[0].blockType)
expect(blockFields.docs[0].blocks[0].text).toEqual(blocksFieldSeedData[0].text)
expect(blockFields.docs[0].blocks[0].blockType).toEqual(blocksDoc.blocks[0].blockType)
expect(blockFields.docs[0].blocks[0].text).toEqual(blocksDoc.blocks[0].text)
expect(blockFields.docs[0].blocks[2].blockType).toEqual(blocksFieldSeedData[2].blockType)
expect(blockFields.docs[0].blocks[2].blockName).toEqual(blocksFieldSeedData[2].blockName)
expect(blockFields.docs[0].blocks[2].blockType).toEqual(blocksDoc.blocks[2].blockType)
expect(blockFields.docs[0].blocks[2].blockName).toEqual(blocksDoc.blocks[2].blockName)
expect(blockFields.docs[0].blocks[2].subBlocks[0].number).toEqual(
blocksFieldSeedData[2].subBlocks[0].number,
blocksDoc.blocks[2].subBlocks[0].number,
)
expect(blockFields.docs[0].blocks[2].subBlocks[1].text).toEqual(
blocksFieldSeedData[2].subBlocks[1].text,
blocksDoc.blocks[2].subBlocks[1].text,
)
})