fix(db-postgres, db-sqlite): hasMany text, number, poly relationship, blocks, arrays within localized fields (#7900)

## Description

In Postgres, localized blocks or arrays that contain other array / block
/ relationship fields were not properly storing locales in the database.

Now they are! Need to check a few things yet:

- Ensure test coverage is sufficient
- Test localized array, with non-localized array inside of it
- Test localized block with relationship field within it
- Ensure `_rels` table gets the `locale` column added if a single
non-localized relationship exists within a localized array / block

Fixes step 6 as identified in #7805
This commit is contained in:
James Mikrut
2024-08-28 13:43:12 -04:00
committed by GitHub
parent 3d9051ad34
commit 18b0806b5b
17 changed files with 990 additions and 96 deletions

View File

@@ -58,9 +58,17 @@ type Args = {
tableName: string tableName: string
timestamps?: boolean timestamps?: boolean
versions: boolean versions: boolean
/**
* Tracks whether or not this table is built
* from the result of a localized array or block field at some point
*/
withinLocalizedArrayOrBlock?: boolean
} }
type Result = { type Result = {
hasLocalizedManyNumberField: boolean
hasLocalizedManyTextField: boolean
hasLocalizedRelationshipField: boolean
hasManyNumberField: 'index' | boolean hasManyNumberField: 'index' | boolean
hasManyTextField: 'index' | boolean hasManyTextField: 'index' | boolean
relationsToBuild: RelationMap relationsToBuild: RelationMap
@@ -81,6 +89,7 @@ export const buildTable = ({
tableName, tableName,
timestamps, timestamps,
versions, versions,
withinLocalizedArrayOrBlock,
}: Args): Result => { }: Args): Result => {
const isRoot = !incomingRootTableName const isRoot = !incomingRootTableName
const rootTableName = incomingRootTableName || tableName const rootTableName = incomingRootTableName || tableName
@@ -128,6 +137,7 @@ export const buildTable = ({
rootTableIDColType: rootTableIDColType || idColType, rootTableIDColType: rootTableIDColType || idColType,
rootTableName, rootTableName,
versions, versions,
withinLocalizedArrayOrBlock,
}) })
// split the relationsToBuild by localized and non-localized // split the relationsToBuild by localized and non-localized
@@ -478,5 +488,12 @@ export const buildTable = ({
return result return result
}) })
return { hasManyNumberField, hasManyTextField, relationsToBuild } return {
hasLocalizedManyNumberField,
hasLocalizedManyTextField,
hasLocalizedRelationshipField,
hasManyNumberField,
hasManyTextField,
relationsToBuild,
}
} }

View File

@@ -52,6 +52,11 @@ type Args = {
rootTableIDColType: IDType rootTableIDColType: IDType
rootTableName: string rootTableName: string
versions: boolean versions: boolean
/**
* Tracks whether or not this table is built
* from the result of a localized array or block field at some point
*/
withinLocalizedArrayOrBlock?: boolean
} }
type Result = { type Result = {
@@ -84,6 +89,7 @@ export const traverseFields = ({
rootTableIDColType, rootTableIDColType,
rootTableName, rootTableName,
versions, versions,
withinLocalizedArrayOrBlock,
}: Args): Result => { }: Args): Result => {
let hasLocalizedField = false let hasLocalizedField = false
let hasLocalizedRelationshipField = false let hasLocalizedRelationshipField = false
@@ -150,7 +156,11 @@ export const traverseFields = ({
switch (field.type) { switch (field.type) {
case 'text': { case 'text': {
if (field.hasMany) { if (field.hasMany) {
if (field.localized) { const isLocalized =
Boolean(field.localized && adapter.payload.config.localization) ||
withinLocalizedArrayOrBlock
if (isLocalized) {
hasLocalizedManyTextField = true hasLocalizedManyTextField = true
} }
@@ -179,7 +189,11 @@ export const traverseFields = ({
case 'number': { case 'number': {
if (field.hasMany) { if (field.hasMany) {
if (field.localized) { const isLocalized =
Boolean(field.localized && adapter.payload.config.localization) ||
withinLocalizedArrayOrBlock
if (isLocalized) {
hasLocalizedManyNumberField = true hasLocalizedManyNumberField = true
} }
@@ -255,7 +269,11 @@ export const traverseFields = ({
parentIdx: (cols) => index(`${selectTableName}_parent_idx`).on(cols.parent), parentIdx: (cols) => index(`${selectTableName}_parent_idx`).on(cols.parent),
} }
if (field.localized) { const isLocalized =
Boolean(field.localized && adapter.payload.config.localization) ||
withinLocalizedArrayOrBlock
if (isLocalized) {
baseColumns.locale = text('locale', { enum: locales }).notNull() baseColumns.locale = text('locale', { enum: locales }).notNull()
baseExtraConfig.localeIdx = (cols) => baseExtraConfig.localeIdx = (cols) =>
index(`${selectTableName}_locale_idx`).on(cols.locale) index(`${selectTableName}_locale_idx`).on(cols.locale)
@@ -337,13 +355,20 @@ export const traverseFields = ({
_parentIDIdx: (cols) => index(`${arrayTableName}_parent_id_idx`).on(cols._parentID), _parentIDIdx: (cols) => index(`${arrayTableName}_parent_id_idx`).on(cols._parentID),
} }
if (field.localized && adapter.payload.config.localization) { const isLocalized =
Boolean(field.localized && adapter.payload.config.localization) ||
withinLocalizedArrayOrBlock
if (isLocalized) {
baseColumns._locale = text('_locale', { enum: locales }).notNull() baseColumns._locale = text('_locale', { enum: locales }).notNull()
baseExtraConfig._localeIdx = (cols) => baseExtraConfig._localeIdx = (cols) =>
index(`${arrayTableName}_locale_idx`).on(cols._locale) index(`${arrayTableName}_locale_idx`).on(cols._locale)
} }
const { const {
hasLocalizedManyNumberField: subHasLocalizedManyNumberField,
hasLocalizedManyTextField: subHasLocalizedManyTextField,
hasLocalizedRelationshipField: subHasLocalizedRelationshipField,
hasManyNumberField: subHasManyNumberField, hasManyNumberField: subHasManyNumberField,
hasManyTextField: subHasManyTextField, hasManyTextField: subHasManyTextField,
relationsToBuild: subRelationsToBuild, relationsToBuild: subRelationsToBuild,
@@ -360,8 +385,21 @@ export const traverseFields = ({
rootTableName, rootTableName,
tableName: arrayTableName, tableName: arrayTableName,
versions, versions,
withinLocalizedArrayOrBlock: isLocalized,
}) })
if (subHasLocalizedManyNumberField) {
hasLocalizedManyNumberField = subHasLocalizedManyNumberField
}
if (subHasLocalizedRelationshipField) {
hasLocalizedRelationshipField = subHasLocalizedRelationshipField
}
if (subHasLocalizedManyTextField) {
hasLocalizedManyTextField = subHasLocalizedManyTextField
}
if (subHasManyTextField) { if (subHasManyTextField) {
if (!hasManyTextField || subHasManyTextField === 'index') if (!hasManyTextField || subHasManyTextField === 'index')
hasManyTextField = subHasManyTextField hasManyTextField = subHasManyTextField
@@ -453,13 +491,20 @@ export const traverseFields = ({
_pathIdx: (cols) => index(`${blockTableName}_path_idx`).on(cols._path), _pathIdx: (cols) => index(`${blockTableName}_path_idx`).on(cols._path),
} }
if (field.localized && adapter.payload.config.localization) { const isLocalized =
Boolean(field.localized && adapter.payload.config.localization) ||
withinLocalizedArrayOrBlock
if (isLocalized) {
baseColumns._locale = text('_locale', { enum: locales }).notNull() baseColumns._locale = text('_locale', { enum: locales }).notNull()
baseExtraConfig._localeIdx = (cols) => baseExtraConfig._localeIdx = (cols) =>
index(`${blockTableName}_locale_idx`).on(cols._locale) index(`${blockTableName}_locale_idx`).on(cols._locale)
} }
const { const {
hasLocalizedManyNumberField: subHasLocalizedManyNumberField,
hasLocalizedManyTextField: subHasLocalizedManyTextField,
hasLocalizedRelationshipField: subHasLocalizedRelationshipField,
hasManyNumberField: subHasManyNumberField, hasManyNumberField: subHasManyNumberField,
hasManyTextField: subHasManyTextField, hasManyTextField: subHasManyTextField,
relationsToBuild: subRelationsToBuild, relationsToBuild: subRelationsToBuild,
@@ -476,8 +521,21 @@ export const traverseFields = ({
rootTableName, rootTableName,
tableName: blockTableName, tableName: blockTableName,
versions, versions,
withinLocalizedArrayOrBlock: isLocalized,
}) })
if (subHasLocalizedManyNumberField) {
hasLocalizedManyNumberField = subHasLocalizedManyNumberField
}
if (subHasLocalizedRelationshipField) {
hasLocalizedRelationshipField = subHasLocalizedRelationshipField
}
if (subHasLocalizedManyTextField) {
hasLocalizedManyTextField = subHasLocalizedManyTextField
}
if (subHasManyTextField) { if (subHasManyTextField) {
if (!hasManyTextField || subHasManyTextField === 'index') if (!hasManyTextField || subHasManyTextField === 'index')
hasManyTextField = subHasManyTextField hasManyTextField = subHasManyTextField
@@ -577,6 +635,7 @@ export const traverseFields = ({
rootTableIDColType, rootTableIDColType,
rootTableName, rootTableName,
versions, versions,
withinLocalizedArrayOrBlock,
}) })
if (groupHasLocalizedField) hasLocalizedField = true if (groupHasLocalizedField) hasLocalizedField = true
@@ -618,6 +677,7 @@ export const traverseFields = ({
rootTableIDColType, rootTableIDColType,
rootTableName, rootTableName,
versions, versions,
withinLocalizedArrayOrBlock,
}) })
if (groupHasLocalizedField) hasLocalizedField = true if (groupHasLocalizedField) hasLocalizedField = true
@@ -660,6 +720,7 @@ export const traverseFields = ({
rootTableIDColType, rootTableIDColType,
rootTableName, rootTableName,
versions, versions,
withinLocalizedArrayOrBlock,
}) })
if (tabHasLocalizedField) hasLocalizedField = true if (tabHasLocalizedField) hasLocalizedField = true
@@ -702,6 +763,7 @@ export const traverseFields = ({
rootTableIDColType, rootTableIDColType,
rootTableName, rootTableName,
versions, versions,
withinLocalizedArrayOrBlock,
}) })
if (rowHasLocalizedField) hasLocalizedField = true if (rowHasLocalizedField) hasLocalizedField = true
@@ -753,7 +815,10 @@ export const traverseFields = ({
} }
break break
} }
if (adapter.payload.config.localization && field.localized) { if (
Boolean(field.localized && adapter.payload.config.localization) ||
withinLocalizedArrayOrBlock
) {
hasLocalizedRelationshipField = true hasLocalizedRelationshipField = true
} }

View File

@@ -54,9 +54,17 @@ type Args = {
tableName: string tableName: string
timestamps?: boolean timestamps?: boolean
versions: boolean versions: boolean
/**
* Tracks whether or not this table is built
* from the result of a localized array or block field at some point
*/
withinLocalizedArrayOrBlock?: boolean
} }
type Result = { type Result = {
hasLocalizedManyNumberField: boolean
hasLocalizedManyTextField: boolean
hasLocalizedRelationshipField: boolean
hasManyNumberField: 'index' | boolean hasManyNumberField: 'index' | boolean
hasManyTextField: 'index' | boolean hasManyTextField: 'index' | boolean
relationsToBuild: RelationMap relationsToBuild: RelationMap
@@ -76,6 +84,7 @@ export const buildTable = ({
tableName, tableName,
timestamps, timestamps,
versions, versions,
withinLocalizedArrayOrBlock,
}: Args): Result => { }: Args): Result => {
const isRoot = !incomingRootTableName const isRoot = !incomingRootTableName
const rootTableName = incomingRootTableName || tableName const rootTableName = incomingRootTableName || tableName
@@ -122,6 +131,7 @@ export const buildTable = ({
rootTableIDColType: rootTableIDColType || idColType, rootTableIDColType: rootTableIDColType || idColType,
rootTableName, rootTableName,
versions, versions,
withinLocalizedArrayOrBlock,
}) })
// split the relationsToBuild by localized and non-localized // split the relationsToBuild by localized and non-localized
@@ -464,5 +474,12 @@ export const buildTable = ({
return result return result
}) })
return { hasManyNumberField, hasManyTextField, relationsToBuild } return {
hasLocalizedManyNumberField,
hasLocalizedManyTextField,
hasLocalizedRelationshipField,
hasManyNumberField,
hasManyTextField,
relationsToBuild,
}
} }

View File

@@ -58,6 +58,11 @@ type Args = {
rootTableIDColType: string rootTableIDColType: string
rootTableName: string rootTableName: string
versions: boolean versions: boolean
/**
* Tracks whether or not this table is built
* from the result of a localized array or block field at some point
*/
withinLocalizedArrayOrBlock?: boolean
} }
type Result = { type Result = {
@@ -89,6 +94,7 @@ export const traverseFields = ({
rootTableIDColType, rootTableIDColType,
rootTableName, rootTableName,
versions, versions,
withinLocalizedArrayOrBlock,
}: Args): Result => { }: Args): Result => {
const throwValidationError = true const throwValidationError = true
let hasLocalizedField = false let hasLocalizedField = false
@@ -156,7 +162,11 @@ export const traverseFields = ({
switch (field.type) { switch (field.type) {
case 'text': { case 'text': {
if (field.hasMany) { if (field.hasMany) {
if (field.localized) { const isLocalized =
Boolean(field.localized && adapter.payload.config.localization) ||
withinLocalizedArrayOrBlock
if (isLocalized) {
hasLocalizedManyTextField = true hasLocalizedManyTextField = true
} }
@@ -185,7 +195,11 @@ export const traverseFields = ({
case 'number': { case 'number': {
if (field.hasMany) { if (field.hasMany) {
if (field.localized) { const isLocalized =
Boolean(field.localized && adapter.payload.config.localization) ||
withinLocalizedArrayOrBlock
if (isLocalized) {
hasLocalizedManyNumberField = true hasLocalizedManyNumberField = true
} }
@@ -276,7 +290,11 @@ export const traverseFields = ({
parentIdx: (cols) => index(`${selectTableName}_parent_idx`).on(cols.parent), parentIdx: (cols) => index(`${selectTableName}_parent_idx`).on(cols.parent),
} }
if (field.localized) { const isLocalized =
Boolean(field.localized && adapter.payload.config.localization) ||
withinLocalizedArrayOrBlock
if (isLocalized) {
baseColumns.locale = adapter.enums.enum__locales('locale').notNull() baseColumns.locale = adapter.enums.enum__locales('locale').notNull()
baseExtraConfig.localeIdx = (cols) => baseExtraConfig.localeIdx = (cols) =>
index(`${selectTableName}_locale_idx`).on(cols.locale) index(`${selectTableName}_locale_idx`).on(cols.locale)
@@ -354,13 +372,20 @@ export const traverseFields = ({
_parentIDIdx: (cols) => index(`${arrayTableName}_parent_id_idx`).on(cols._parentID), _parentIDIdx: (cols) => index(`${arrayTableName}_parent_id_idx`).on(cols._parentID),
} }
if (field.localized && adapter.payload.config.localization) { const isLocalized =
Boolean(field.localized && adapter.payload.config.localization) ||
withinLocalizedArrayOrBlock
if (isLocalized) {
baseColumns._locale = adapter.enums.enum__locales('_locale').notNull() baseColumns._locale = adapter.enums.enum__locales('_locale').notNull()
baseExtraConfig._localeIdx = (cols) => baseExtraConfig._localeIdx = (cols) =>
index(`${arrayTableName}_locale_idx`).on(cols._locale) index(`${arrayTableName}_locale_idx`).on(cols._locale)
} }
const { const {
hasLocalizedManyNumberField: subHasLocalizedManyNumberField,
hasLocalizedManyTextField: subHasLocalizedManyTextField,
hasLocalizedRelationshipField: subHasLocalizedRelationshipField,
hasManyNumberField: subHasManyNumberField, hasManyNumberField: subHasManyNumberField,
hasManyTextField: subHasManyTextField, hasManyTextField: subHasManyTextField,
relationsToBuild: subRelationsToBuild, relationsToBuild: subRelationsToBuild,
@@ -377,8 +402,21 @@ export const traverseFields = ({
rootTableName, rootTableName,
tableName: arrayTableName, tableName: arrayTableName,
versions, versions,
withinLocalizedArrayOrBlock: isLocalized,
}) })
if (subHasLocalizedManyNumberField) {
hasLocalizedManyNumberField = subHasLocalizedManyNumberField
}
if (subHasLocalizedRelationshipField) {
hasLocalizedRelationshipField = subHasLocalizedRelationshipField
}
if (subHasLocalizedManyTextField) {
hasLocalizedManyTextField = subHasLocalizedManyTextField
}
if (subHasManyTextField) { if (subHasManyTextField) {
if (!hasManyTextField || subHasManyTextField === 'index') if (!hasManyTextField || subHasManyTextField === 'index')
hasManyTextField = subHasManyTextField hasManyTextField = subHasManyTextField
@@ -466,13 +504,20 @@ export const traverseFields = ({
_pathIdx: (cols) => index(`${blockTableName}_path_idx`).on(cols._path), _pathIdx: (cols) => index(`${blockTableName}_path_idx`).on(cols._path),
} }
if (field.localized && adapter.payload.config.localization) { const isLocalized =
Boolean(field.localized && adapter.payload.config.localization) ||
withinLocalizedArrayOrBlock
if (isLocalized) {
baseColumns._locale = adapter.enums.enum__locales('_locale').notNull() baseColumns._locale = adapter.enums.enum__locales('_locale').notNull()
baseExtraConfig._localeIdx = (cols) => baseExtraConfig._localeIdx = (cols) =>
index(`${blockTableName}_locale_idx`).on(cols._locale) index(`${blockTableName}_locale_idx`).on(cols._locale)
} }
const { const {
hasLocalizedManyNumberField: subHasLocalizedManyNumberField,
hasLocalizedManyTextField: subHasLocalizedManyTextField,
hasLocalizedRelationshipField: subHasLocalizedRelationshipField,
hasManyNumberField: subHasManyNumberField, hasManyNumberField: subHasManyNumberField,
hasManyTextField: subHasManyTextField, hasManyTextField: subHasManyTextField,
relationsToBuild: subRelationsToBuild, relationsToBuild: subRelationsToBuild,
@@ -489,8 +534,21 @@ export const traverseFields = ({
rootTableName, rootTableName,
tableName: blockTableName, tableName: blockTableName,
versions, versions,
withinLocalizedArrayOrBlock: isLocalized,
}) })
if (subHasLocalizedManyNumberField) {
hasLocalizedManyNumberField = subHasLocalizedManyNumberField
}
if (subHasLocalizedRelationshipField) {
hasLocalizedRelationshipField = subHasLocalizedRelationshipField
}
if (subHasLocalizedManyTextField) {
hasLocalizedManyTextField = subHasLocalizedManyTextField
}
if (subHasManyTextField) { if (subHasManyTextField) {
if (!hasManyTextField || subHasManyTextField === 'index') if (!hasManyTextField || subHasManyTextField === 'index')
hasManyTextField = subHasManyTextField hasManyTextField = subHasManyTextField
@@ -589,6 +647,7 @@ export const traverseFields = ({
rootTableIDColType, rootTableIDColType,
rootTableName, rootTableName,
versions, versions,
withinLocalizedArrayOrBlock,
}) })
if (groupHasLocalizedField) hasLocalizedField = true if (groupHasLocalizedField) hasLocalizedField = true
@@ -629,6 +688,7 @@ export const traverseFields = ({
rootTableIDColType, rootTableIDColType,
rootTableName, rootTableName,
versions, versions,
withinLocalizedArrayOrBlock,
}) })
if (groupHasLocalizedField) hasLocalizedField = true if (groupHasLocalizedField) hasLocalizedField = true
@@ -670,6 +730,7 @@ export const traverseFields = ({
rootTableIDColType, rootTableIDColType,
rootTableName, rootTableName,
versions, versions,
withinLocalizedArrayOrBlock,
}) })
if (tabHasLocalizedField) hasLocalizedField = true if (tabHasLocalizedField) hasLocalizedField = true
@@ -711,6 +772,7 @@ export const traverseFields = ({
rootTableIDColType, rootTableIDColType,
rootTableName, rootTableName,
versions, versions,
withinLocalizedArrayOrBlock,
}) })
if (rowHasLocalizedField) hasLocalizedField = true if (rowHasLocalizedField) hasLocalizedField = true
@@ -761,7 +823,11 @@ export const traverseFields = ({
} }
break break
} }
if (adapter.payload.config.localization && field.localized) {
if (
Boolean(field.localized && adapter.payload.config.localization) ||
withinLocalizedArrayOrBlock
) {
hasLocalizedRelationshipField = true hasLocalizedRelationshipField = true
} }

View File

@@ -1,4 +1,3 @@
/* eslint-disable no-param-reassign */
import type { NumberField } from 'payload' import type { NumberField } from 'payload'
type Args = { type Args = {
@@ -6,10 +5,29 @@ type Args = {
locale?: string locale?: string
numberRows: Record<string, unknown>[] numberRows: Record<string, unknown>[]
ref: Record<string, unknown> ref: Record<string, unknown>
withinArrayOrBlockLocale?: string
} }
export const transformHasManyNumber = ({ field, locale, numberRows, ref }: Args) => { export const transformHasManyNumber = ({
const result = numberRows.map(({ number }) => number) field,
locale,
numberRows,
ref,
withinArrayOrBlockLocale,
}: Args) => {
let result: unknown[]
if (withinArrayOrBlockLocale) {
result = numberRows.reduce((acc, { locale, number }) => {
if (locale === withinArrayOrBlockLocale) {
acc.push(number)
}
return acc
}, [])
} else {
result = numberRows.map(({ number }) => number)
}
if (locale) { if (locale) {
ref[field.name][locale] = result ref[field.name][locale] = result

View File

@@ -1,4 +1,3 @@
/* eslint-disable no-param-reassign */
import type { TextField } from 'payload' import type { TextField } from 'payload'
type Args = { type Args = {
@@ -6,10 +5,29 @@ type Args = {
locale?: string locale?: string
ref: Record<string, unknown> ref: Record<string, unknown>
textRows: Record<string, unknown>[] textRows: Record<string, unknown>[]
withinArrayOrBlockLocale?: string
} }
export const transformHasManyText = ({ field, locale, ref, textRows }: Args) => { export const transformHasManyText = ({
const result = textRows.map(({ text }) => text) field,
locale,
ref,
textRows,
withinArrayOrBlockLocale,
}: Args) => {
let result: unknown[]
if (withinArrayOrBlockLocale) {
result = textRows.reduce((acc, { locale, text }) => {
if (locale === withinArrayOrBlockLocale) {
acc.push(text)
}
return acc
}, [])
} else {
result = textRows.map(({ text }) => text)
}
if (locale) { if (locale) {
ref[field.name][locale] = result ref[field.name][locale] = result

View File

@@ -1,4 +1,3 @@
/* eslint-disable no-param-reassign */
import type { RelationshipField, UploadField } from 'payload' import type { RelationshipField, UploadField } from 'payload'
type Args = { type Args = {
@@ -6,21 +5,31 @@ type Args = {
locale?: string locale?: string
ref: Record<string, unknown> ref: Record<string, unknown>
relations: Record<string, unknown>[] relations: Record<string, unknown>[]
withinArrayOrBlockLocale?: string
} }
export const transformRelationship = ({ field, locale, ref, relations }: Args) => { export const transformRelationship = ({
field,
locale,
ref,
relations,
withinArrayOrBlockLocale,
}: Args) => {
let result: unknown let result: unknown
if (!('hasMany' in field) || field.hasMany === false) { if (!('hasMany' in field) || field.hasMany === false) {
const relation = relations[0] let relation = relations[0]
if (withinArrayOrBlockLocale) {
relation = relations.find((rel) => rel.locale === withinArrayOrBlockLocale)
}
if (relation) { if (relation) {
// Handle hasOne Poly // Handle hasOne Poly
if (Array.isArray(field.relationTo)) { if (Array.isArray(field.relationTo)) {
const matchedRelation = Object.entries(relation).find( const matchedRelation = Object.entries(relation).find(([key, val]) => {
([key, val]) => return val !== null && !['id', 'locale', 'order', 'parent', 'path'].includes(key)
val !== null && !['id', 'locale', 'order', 'parent', 'path'].includes(key), })
)
if (matchedRelation) { if (matchedRelation) {
const relationTo = matchedRelation[0].replace('ID', '') const relationTo = matchedRelation[0].replace('ID', '')
@@ -36,18 +45,26 @@ export const transformRelationship = ({ field, locale, ref, relations }: Args) =
const transformedRelations = [] const transformedRelations = []
relations.forEach((relation) => { relations.forEach((relation) => {
let matchedLocale = true
if (withinArrayOrBlockLocale) {
matchedLocale = relation.locale === withinArrayOrBlockLocale
}
// Handle hasMany // Handle hasMany
if (!Array.isArray(field.relationTo)) { if (!Array.isArray(field.relationTo)) {
const relatedData = relation[`${field.relationTo}ID`] const relatedData = relation[`${field.relationTo}ID`]
if (relatedData) { if (relatedData && matchedLocale) {
transformedRelations.push(relatedData) transformedRelations.push(relatedData)
} }
} else { } else {
// Handle hasMany Poly // Handle hasMany Poly
const matchedRelation = Object.entries(relation).find( const matchedRelation = Object.entries(relation).find(
([key, val]) => ([key, val]) =>
val !== null && !['id', 'locale', 'order', 'parent', 'path'].includes(key), val !== null &&
!['id', 'locale', 'order', 'parent', 'path'].includes(key) &&
matchedLocale,
) )
if (matchedRelation) { if (matchedRelation) {

View File

@@ -58,6 +58,10 @@ type TraverseFieldsArgs = {
* All hasMany text fields, as returned by Drizzle, keyed on an object by field path * All hasMany text fields, as returned by Drizzle, keyed on an object by field path
*/ */
texts: Record<string, Record<string, unknown>[]> texts: Record<string, Record<string, unknown>[]>
/**
* Set to a locale if this group of fields is within a localized array or block.
*/
withinArrayOrBlockLocale?: string
} }
// Traverse fields recursively, transforming data // Traverse fields recursively, transforming data
@@ -75,6 +79,7 @@ export const traverseFields = <T extends Record<string, unknown>>({
relationships, relationships,
table, table,
texts, texts,
withinArrayOrBlockLocale,
}: TraverseFieldsArgs): T => { }: TraverseFieldsArgs): T => {
const sanitizedPath = path ? `${path}.` : path const sanitizedPath = path ? `${path}.` : path
@@ -93,6 +98,7 @@ export const traverseFields = <T extends Record<string, unknown>>({
relationships, relationships,
table, table,
texts, texts,
withinArrayOrBlockLocale,
}) })
} }
@@ -114,6 +120,7 @@ export const traverseFields = <T extends Record<string, unknown>>({
relationships, relationships,
table, table,
texts, texts,
withinArrayOrBlockLocale,
}) })
} }
@@ -157,6 +164,7 @@ export const traverseFields = <T extends Record<string, unknown>>({
relationships, relationships,
table: row, table: row,
texts, texts,
withinArrayOrBlockLocale: locale,
}) })
if ('_order' in rowResult) { if ('_order' in rowResult) {
@@ -192,6 +200,7 @@ export const traverseFields = <T extends Record<string, unknown>>({
relationships, relationships,
table: row, table: row,
texts, texts,
withinArrayOrBlockLocale,
}) })
}) })
} }
@@ -237,6 +246,7 @@ export const traverseFields = <T extends Record<string, unknown>>({
relationships, relationships,
table: row, table: row,
texts, texts,
withinArrayOrBlockLocale: locale,
}) })
delete blockResult._order delete blockResult._order
@@ -247,7 +257,7 @@ export const traverseFields = <T extends Record<string, unknown>>({
}) })
}) })
} else { } else {
result[field.name] = blocks[blockFieldPath].map((row, i) => { result[field.name] = blocks[blockFieldPath].reduce((acc, row, i) => {
delete row._order delete row._order
if (row._uuid) { if (row._uuid) {
row.id = row._uuid row.id = row._uuid
@@ -256,7 +266,16 @@ export const traverseFields = <T extends Record<string, unknown>>({
const block = field.blocks.find(({ slug }) => slug === row.blockType) const block = field.blocks.find(({ slug }) => slug === row.blockType)
if (block) { if (block) {
return traverseFields<T>({ if (
!withinArrayOrBlockLocale ||
(withinArrayOrBlockLocale && withinArrayOrBlockLocale === row._locale)
) {
if (row._locale) {
delete row._locale
}
acc.push(
traverseFields<T>({
adapter, adapter,
blocks, blocks,
config, config,
@@ -269,11 +288,18 @@ export const traverseFields = <T extends Record<string, unknown>>({
relationships, relationships,
table: row, table: row,
texts, texts,
}) withinArrayOrBlockLocale,
}),
)
return acc
}
} else {
acc.push({})
} }
return {} return acc
}) }, [])
} }
} }
@@ -334,6 +360,7 @@ export const traverseFields = <T extends Record<string, unknown>>({
field, field,
ref: result, ref: result,
relations: relationPathMatch, relations: relationPathMatch,
withinArrayOrBlockLocale,
}) })
} }
return result return result
@@ -368,6 +395,7 @@ export const traverseFields = <T extends Record<string, unknown>>({
field, field,
ref: result, ref: result,
textRows: textPathMatch, textRows: textPathMatch,
withinArrayOrBlockLocale,
}) })
} }
@@ -402,6 +430,7 @@ export const traverseFields = <T extends Record<string, unknown>>({
field, field,
numberRows: numberPathMatch, numberRows: numberPathMatch,
ref: result, ref: result,
withinArrayOrBlockLocale,
}) })
} }
@@ -466,6 +495,7 @@ export const traverseFields = <T extends Record<string, unknown>>({
relationships, relationships,
table, table,
texts, texts,
withinArrayOrBlockLocale,
}) })
if ('_order' in ref) { if ('_order' in ref) {

View File

@@ -1,4 +1,3 @@
/* eslint-disable no-param-reassign */
import type { ArrayField } from 'payload' import type { ArrayField } from 'payload'
import type { DrizzleAdapter } from '../../types.js' import type { DrizzleAdapter } from '../../types.js'
@@ -26,6 +25,11 @@ type Args = {
[tableName: string]: Record<string, unknown>[] [tableName: string]: Record<string, unknown>[]
} }
texts: Record<string, unknown>[] texts: Record<string, unknown>[]
/**
* Set to a locale code if this set of fields is traversed within a
* localized array or block field
*/
withinArrayOrBlockLocale?: string
} }
export const transformArray = ({ export const transformArray = ({
@@ -43,6 +47,7 @@ export const transformArray = ({
relationshipsToDelete, relationshipsToDelete,
selects, selects,
texts, texts,
withinArrayOrBlockLocale,
}: Args) => { }: Args) => {
const newRows: ArrayRowToInsert[] = [] const newRows: ArrayRowToInsert[] = []
@@ -78,6 +83,10 @@ export const transformArray = ({
newRow.row._locale = locale newRow.row._locale = locale
} }
if (withinArrayOrBlockLocale) {
newRow.row._locale = withinArrayOrBlockLocale
}
traverseFields({ traverseFields({
adapter, adapter,
arrays: newRow.arrays, arrays: newRow.arrays,
@@ -97,6 +106,7 @@ export const transformArray = ({
row: newRow.row, row: newRow.row,
selects, selects,
texts, texts,
withinArrayOrBlockLocale,
}) })
newRows.push(newRow) newRows.push(newRow)

View File

@@ -1,4 +1,3 @@
/* eslint-disable no-param-reassign */
import type { BlockField } from 'payload' import type { BlockField } from 'payload'
import toSnakeCase from 'to-snake-case' import toSnakeCase from 'to-snake-case'
@@ -26,6 +25,11 @@ type Args = {
[tableName: string]: Record<string, unknown>[] [tableName: string]: Record<string, unknown>[]
} }
texts: Record<string, unknown>[] texts: Record<string, unknown>[]
/**
* Set to a locale code if this set of fields is traversed within a
* localized array or block field
*/
withinArrayOrBlockLocale?: string
} }
export const transformBlocks = ({ export const transformBlocks = ({
adapter, adapter,
@@ -41,6 +45,7 @@ export const transformBlocks = ({
relationshipsToDelete, relationshipsToDelete,
selects, selects,
texts, texts,
withinArrayOrBlockLocale,
}: Args) => { }: Args) => {
data.forEach((blockRow, i) => { data.forEach((blockRow, i) => {
if (typeof blockRow.blockType !== 'string') return if (typeof blockRow.blockType !== 'string') return
@@ -60,6 +65,7 @@ export const transformBlocks = ({
} }
if (field.localized && locale) newRow.row._locale = locale if (field.localized && locale) newRow.row._locale = locale
if (withinArrayOrBlockLocale) newRow.row._locale = withinArrayOrBlockLocale
const blockTableName = adapter.tableNameMap.get(`${baseTableName}_blocks_${blockType}`) const blockTableName = adapter.tableNameMap.get(`${baseTableName}_blocks_${blockType}`)
@@ -94,6 +100,7 @@ export const transformBlocks = ({
row: newRow.row, row: newRow.row,
selects, selects,
texts, texts,
withinArrayOrBlockLocale,
}) })
blocks[blockType].push(newRow) blocks[blockType].push(newRow)

View File

@@ -57,6 +57,11 @@ type Args = {
[tableName: string]: Record<string, unknown>[] [tableName: string]: Record<string, unknown>[]
} }
texts: Record<string, unknown>[] texts: Record<string, unknown>[]
/**
* Set to a locale code if this set of fields is traversed within a
* localized array or block field
*/
withinArrayOrBlockLocale?: string
} }
export const traverseFields = ({ export const traverseFields = ({
@@ -80,6 +85,7 @@ export const traverseFields = ({
row, row,
selects, selects,
texts, texts,
withinArrayOrBlockLocale,
}: Args) => { }: Args) => {
fields.forEach((field) => { fields.forEach((field) => {
let columnName = '' let columnName = ''
@@ -116,6 +122,7 @@ export const traverseFields = ({
relationshipsToDelete, relationshipsToDelete,
selects, selects,
texts, texts,
withinArrayOrBlockLocale: localeKey,
}) })
arrays[arrayTableName] = arrays[arrayTableName].concat(newRows) arrays[arrayTableName] = arrays[arrayTableName].concat(newRows)
@@ -137,6 +144,7 @@ export const traverseFields = ({
relationshipsToDelete, relationshipsToDelete,
selects, selects,
texts, texts,
withinArrayOrBlockLocale,
}) })
arrays[arrayTableName] = arrays[arrayTableName].concat(newRows) arrays[arrayTableName] = arrays[arrayTableName].concat(newRows)
@@ -168,6 +176,7 @@ export const traverseFields = ({
relationshipsToDelete, relationshipsToDelete,
selects, selects,
texts, texts,
withinArrayOrBlockLocale: localeKey,
}) })
} }
}) })
@@ -186,6 +195,7 @@ export const traverseFields = ({
relationshipsToDelete, relationshipsToDelete,
selects, selects,
texts, texts,
withinArrayOrBlockLocale,
}) })
} }
@@ -217,6 +227,7 @@ export const traverseFields = ({
row, row,
selects, selects,
texts, texts,
withinArrayOrBlockLocale: localeKey,
}) })
}) })
} else { } else {
@@ -240,6 +251,7 @@ export const traverseFields = ({
row, row,
selects, selects,
texts, texts,
withinArrayOrBlockLocale,
}) })
} }
} }
@@ -274,6 +286,7 @@ export const traverseFields = ({
row, row,
selects, selects,
texts, texts,
withinArrayOrBlockLocale: localeKey,
}) })
}) })
} else { } else {
@@ -297,6 +310,7 @@ export const traverseFields = ({
row, row,
selects, selects,
texts, texts,
withinArrayOrBlockLocale,
}) })
} }
} }
@@ -321,6 +335,7 @@ export const traverseFields = ({
row, row,
selects, selects,
texts, texts,
withinArrayOrBlockLocale,
}) })
} }
}) })
@@ -347,6 +362,7 @@ export const traverseFields = ({
row, row,
selects, selects,
texts, texts,
withinArrayOrBlockLocale,
}) })
} }
@@ -387,6 +403,7 @@ export const traverseFields = ({
transformRelationship({ transformRelationship({
baseRow: { baseRow: {
locale: withinArrayOrBlockLocale,
path: relationshipPath, path: relationshipPath,
}, },
data: fieldData, data: fieldData,
@@ -440,6 +457,7 @@ export const traverseFields = ({
} else if (Array.isArray(fieldData)) { } else if (Array.isArray(fieldData)) {
transformTexts({ transformTexts({
baseRow: { baseRow: {
locale: withinArrayOrBlockLocale,
path: textPath, path: textPath,
}, },
data: fieldData, data: fieldData,
@@ -471,6 +489,7 @@ export const traverseFields = ({
} else if (Array.isArray(fieldData)) { } else if (Array.isArray(fieldData)) {
transformNumbers({ transformNumbers({
baseRow: { baseRow: {
locale: withinArrayOrBlockLocale,
path: numberPath, path: numberPath,
}, },
data: fieldData, data: fieldData,
@@ -503,6 +522,7 @@ export const traverseFields = ({
const newRows = transformSelects({ const newRows = transformSelects({
id: data._uuid || data.id, id: data._uuid || data.id,
data: data[field.name], data: data[field.name],
locale: withinArrayOrBlockLocale,
}) })
selects[selectTableName] = selects[selectTableName].concat(newRows) selects[selectTableName] = selects[selectTableName].concat(newRows)

View File

@@ -0,0 +1,37 @@
import type { CollectionConfig } from 'payload'
export const blocksCollectionSlug = 'blocks-fields'
export const BlocksCollection: CollectionConfig = {
slug: blocksCollectionSlug,
fields: [
{
name: 'content',
label: 'Content',
type: 'blocks',
localized: true,
blocks: [
{
slug: 'blockInsideBlock',
fields: [
{
name: 'content',
type: 'blocks',
blocks: [
{
slug: 'textBlock',
fields: [
{
name: 'text',
type: 'text',
},
],
},
],
},
],
},
],
},
],
}

View File

@@ -0,0 +1,42 @@
import type { CollectionConfig } from 'payload'
export const NestedArray: CollectionConfig = {
slug: 'nested-arrays',
fields: [
{
name: 'arrayWithBlocks',
type: 'array',
localized: true,
fields: [
{
name: 'blocksWithinArray',
type: 'blocks',
blocks: [
{
slug: 'someBlock',
fields: [
{
name: 'relationWithinBlock',
type: 'relationship',
relationTo: 'localized-posts',
},
],
},
],
},
],
},
{
name: 'arrayWithLocalizedRelation',
type: 'array',
fields: [
{
name: 'localizedRelation',
type: 'relationship',
localized: true,
relationTo: 'localized-posts',
},
],
},
],
}

View File

@@ -0,0 +1,47 @@
import type { CollectionConfig } from 'payload'
export const NestedFields: CollectionConfig = {
slug: 'nested-field-tables',
fields: [
{
name: 'array',
type: 'array',
localized: true,
fields: [
{
name: 'relation',
type: 'relationship',
relationTo: ['localized-posts'],
},
{
name: 'hasManyRelation',
type: 'relationship',
hasMany: true,
relationTo: 'localized-posts',
},
{
name: 'hasManyPolyRelation',
type: 'relationship',
hasMany: true,
relationTo: ['localized-posts'],
},
{
name: 'select',
type: 'select',
hasMany: true,
options: ['one', 'two', 'three'],
},
{
name: 'number',
type: 'number',
hasMany: true,
},
{
name: 'text',
type: 'text',
hasMany: true,
},
],
},
],
}

View File

@@ -7,7 +7,10 @@ import type { LocalizedPost } from './payload-types.js'
import { buildConfigWithDefaults } from '../buildConfigWithDefaults.js' import { buildConfigWithDefaults } from '../buildConfigWithDefaults.js'
import { devUser } from '../credentials.js' import { devUser } from '../credentials.js'
import { ArrayCollection } from './collections/Array/index.js' import { ArrayCollection } from './collections/Array/index.js'
import { BlocksCollection } from './collections/Blocks/index.js'
import { Group } from './collections/Group/index.js' import { Group } from './collections/Group/index.js'
import { NestedArray } from './collections/NestedArray/index.js'
import { NestedFields } from './collections/NestedFields/index.js'
import { NestedToArrayAndBlock } from './collections/NestedToArrayAndBlock/index.js' import { NestedToArrayAndBlock } from './collections/NestedToArrayAndBlock/index.js'
import { Tab } from './collections/Tab/index.js' import { Tab } from './collections/Tab/index.js'
import { import {
@@ -50,6 +53,9 @@ export default buildConfigWithDefaults({
}, },
}, },
collections: [ collections: [
BlocksCollection,
NestedArray,
NestedFields,
{ {
auth: true, auth: true,
fields: [ fields: [

View File

@@ -1395,6 +1395,328 @@ describe('Localization', () => {
expect(docEs.deep.blocks[0].title).toBe('hello es') expect(docEs.deep.blocks[0].title).toBe('hello es')
}) })
}) })
describe('nested blocks', () => {
let id
it('should allow creating nested blocks per locale', async () => {
const doc = await payload.create({
collection: 'blocks-fields',
data: {
content: [
{
blockType: 'blockInsideBlock',
content: [
{
blockType: 'textBlock',
text: 'hello',
},
],
},
],
},
})
id = doc.id
await payload.update({
collection: 'blocks-fields',
id,
locale: 'es',
data: {
content: [
{
blockType: 'blockInsideBlock',
content: [
{
blockType: 'textBlock',
text: 'hola',
},
],
},
],
},
})
const retrieved = await payload.findByID({
collection: 'blocks-fields',
id,
locale: 'all',
})
expect(retrieved.content.en[0].content).toHaveLength(1)
expect(retrieved.content.es[0].content).toHaveLength(1)
})
})
describe('nested arrays', () => {
it('should not duplicate block rows for blocks within localized array fields', async () => {
const randomDoc = (
await payload.find({
collection: 'localized-posts',
depth: 0,
})
).docs[0]
const randomDoc2 = (
await payload.find({
collection: 'localized-posts',
depth: 0,
})
).docs[1]
const blocksWithinArrayEN = [
{
blockName: '1',
blockType: 'someBlock',
relationWithinBlock: randomDoc.id,
},
{
blockName: '2',
blockType: 'someBlock',
relationWithinBlock: randomDoc.id,
},
{
blockName: '3',
blockType: 'someBlock',
relationWithinBlock: randomDoc.id,
},
]
const blocksWithinArrayES = [
{
blockName: '1',
blockType: 'someBlock',
relationWithinBlock: randomDoc2.id,
},
{
blockName: '2',
blockType: 'someBlock',
relationWithinBlock: randomDoc2.id,
},
{
blockName: '3',
blockType: 'someBlock',
relationWithinBlock: randomDoc2.id,
},
]
const createdEnDoc = await payload.create({
collection: 'nested-arrays',
locale: 'en',
depth: 0,
data: {
arrayWithBlocks: [
{
blocksWithinArray: blocksWithinArrayEN as any,
},
],
},
})
const updatedEsDoc = await payload.update({
collection: 'nested-arrays',
id: createdEnDoc.id,
depth: 0,
locale: 'es',
data: {
arrayWithBlocks: [
{
blocksWithinArray: blocksWithinArrayES as any,
},
],
},
})
const esArrayBlocks = updatedEsDoc.arrayWithBlocks[0].blocksWithinArray
// recursively remove any id field within esArrayRow
const removeId = (obj) => {
if (obj instanceof Object) {
delete obj.id
Object.values(obj).forEach(removeId)
}
}
removeId(esArrayBlocks)
removeId(createdEnDoc.arrayWithBlocks[0].blocksWithinArray)
expect(esArrayBlocks).toEqual(blocksWithinArrayES)
expect(createdEnDoc.arrayWithBlocks[0].blocksWithinArray).toEqual(blocksWithinArrayEN)
// pull enDoc again and make sure the update of esDoc did not mess with the data of enDoc
const enDoc2 = await payload.findByID({
id: createdEnDoc.id,
collection: 'nested-arrays',
locale: 'en',
depth: 0,
})
removeId(enDoc2.arrayWithBlocks[0].blocksWithinArray)
expect(enDoc2.arrayWithBlocks[0].blocksWithinArray).toEqual(blocksWithinArrayEN)
})
it('should update localized relation within unLocalized array', async () => {
const randomTextDoc = (
await payload.find({
collection: 'localized-posts',
depth: 0,
})
).docs[0]
const randomTextDoc2 = (
await payload.find({
collection: 'localized-posts',
depth: 0,
})
).docs[1]
const createdEnDoc = await payload.create({
collection: 'nested-arrays',
locale: 'en',
depth: 0,
data: {
arrayWithLocalizedRelation: [
{
localizedRelation: randomTextDoc.id,
},
],
},
})
const updatedEsDoc = await payload.update({
collection: 'nested-arrays',
id: createdEnDoc.id,
depth: 0,
locale: 'es',
data: {
arrayWithLocalizedRelation: [
{
id: createdEnDoc.arrayWithLocalizedRelation[0].id,
localizedRelation: randomTextDoc2.id,
},
],
},
})
expect(updatedEsDoc.arrayWithLocalizedRelation).toHaveLength(1)
expect(updatedEsDoc.arrayWithLocalizedRelation[0].localizedRelation).toBe(randomTextDoc2.id)
expect(createdEnDoc.arrayWithLocalizedRelation).toHaveLength(1)
expect(createdEnDoc.arrayWithLocalizedRelation[0].localizedRelation).toBe(randomTextDoc.id)
// pull enDoc again and make sure the update of esDoc did not mess with the data of enDoc
const enDoc2 = await payload.findByID({
id: createdEnDoc.id,
collection: 'nested-arrays',
locale: 'en',
depth: 0,
})
expect(enDoc2.arrayWithLocalizedRelation).toHaveLength(1)
expect(enDoc2.arrayWithLocalizedRelation[0].localizedRelation).toBe(randomTextDoc.id)
})
})
describe('nested fields', () => {
it('should allow for fields which could contain new tables within localized arrays to be stored', async () => {
const randomDoc = (
await payload.find({
collection: 'localized-posts',
depth: 0,
})
).docs[0]
const randomDoc2 = (
await payload.find({
collection: 'localized-posts',
depth: 0,
})
).docs[1]
const newDoc = await payload.create({
collection: 'nested-field-tables',
data: {
array: [
{
relation: {
value: randomDoc.id,
relationTo: 'localized-posts',
},
hasManyRelation: [randomDoc.id, randomDoc2.id],
hasManyPolyRelation: [
{
relationTo: 'localized-posts',
value: randomDoc.id,
},
{
relationTo: 'localized-posts',
value: randomDoc2.id,
},
],
number: [1, 2],
text: ['hello', 'goodbye'],
select: ['one'],
},
],
},
})
await payload.update({
collection: 'nested-field-tables',
id: newDoc.id,
locale: 'es',
data: {
array: [
{
relation: {
value: randomDoc2.id,
relationTo: 'localized-posts',
},
hasManyRelation: [randomDoc2.id, randomDoc.id],
hasManyPolyRelation: [
{
relationTo: 'localized-posts',
value: randomDoc2.id,
},
{
relationTo: 'localized-posts',
value: randomDoc.id,
},
],
select: ['two', 'three'],
text: ['hola', 'adios'],
number: [3, 4],
},
],
},
})
const retrieved = await payload.findByID({
collection: 'nested-field-tables',
id: newDoc.id,
depth: 0,
locale: 'all',
})
expect(retrieved.array.en[0].relation.value).toStrictEqual(randomDoc.id)
expect(retrieved.array.es[0].relation.value).toStrictEqual(randomDoc2.id)
expect(retrieved.array.en[0].hasManyRelation).toEqual([randomDoc.id, randomDoc2.id])
expect(retrieved.array.es[0].hasManyRelation).toEqual([randomDoc2.id, randomDoc.id])
expect(retrieved.array.en[0].hasManyPolyRelation).toEqual([
{ value: randomDoc.id, relationTo: 'localized-posts' },
{ value: randomDoc2.id, relationTo: 'localized-posts' },
])
expect(retrieved.array.es[0].hasManyPolyRelation).toEqual([
{ value: randomDoc2.id, relationTo: 'localized-posts' },
{ value: randomDoc.id, relationTo: 'localized-posts' },
])
expect(retrieved.array.en[0].number).toEqual([1, 2])
expect(retrieved.array.es[0].number).toEqual([3, 4])
expect(retrieved.array.en[0].select).toEqual(['one'])
expect(retrieved.array.es[0].select).toEqual(['two', 'three'])
expect(retrieved.array.en[0].text).toEqual(['hello', 'goodbye'])
expect(retrieved.array.es[0].text).toEqual(['hola', 'adios'])
})
})
}) })
async function createLocalizedPost(data: { async function createLocalizedPost(data: {

View File

@@ -11,6 +11,9 @@ export interface Config {
users: UserAuthOperations; users: UserAuthOperations;
}; };
collections: { collections: {
'blocks-fields': BlocksField;
'nested-arrays': NestedArray;
'nested-fields': NestedField;
users: User; users: User;
'localized-posts': LocalizedPost; 'localized-posts': LocalizedPost;
'array-fields': ArrayField; 'array-fields': ArrayField;
@@ -19,15 +22,20 @@ export interface Config {
'relationship-localized': RelationshipLocalized; 'relationship-localized': RelationshipLocalized;
dummy: Dummy; dummy: Dummy;
nested: Nested; nested: Nested;
groups: Group;
tabs: Tab;
'localized-sort': LocalizedSort; 'localized-sort': LocalizedSort;
'blocks-same-name': BlocksSameName; 'blocks-same-name': BlocksSameName;
'payload-preferences': PayloadPreference; 'payload-preferences': PayloadPreference;
'payload-migrations': PayloadMigration; 'payload-migrations': PayloadMigration;
}; };
db: {
defaultIDType: number;
};
globals: { globals: {
'global-array': GlobalArray; 'global-array': GlobalArray;
}; };
locale: 'en' | 'es' | 'hu' | 'pt' | 'ar'; locale: 'en' | 'es' | 'pt' | 'ar' | 'hu';
user: User & { user: User & {
collection: 'users'; collection: 'users';
}; };
@@ -35,23 +43,125 @@ export interface Config {
export interface UserAuthOperations { export interface UserAuthOperations {
forgotPassword: { forgotPassword: {
email: string; email: string;
password: string;
}; };
login: { login: {
password: string;
email: string; email: string;
password: string;
}; };
registerFirstUser: { registerFirstUser: {
email: string; email: string;
password: string; password: string;
}; };
unlock: {
email: string;
password: string;
};
}
/**
* This interface was referenced by `Config`'s JSON-Schema
* via the `definition` "blocks-fields".
*/
export interface BlocksField {
id: number;
content?:
| {
content?:
| {
text?: string | null;
id?: string | null;
blockName?: string | null;
blockType: 'textBlock';
}[]
| null;
id?: string | null;
blockName?: string | null;
blockType: 'blockInsideBlock';
}[]
| null;
updatedAt: string;
createdAt: string;
}
/**
* This interface was referenced by `Config`'s JSON-Schema
* via the `definition` "nested-arrays".
*/
export interface NestedArray {
id: number;
arrayWithBlocks?:
| {
blocksWithinArray?:
| {
relationWithinBlock?: (number | null) | LocalizedPost;
id?: string | null;
blockName?: string | null;
blockType: 'someBlock';
}[]
| null;
id?: string | null;
}[]
| null;
arrayWithLocalizedRelation?:
| {
localizedRelation?: (number | null) | LocalizedPost;
id?: string | null;
}[]
| null;
updatedAt: string;
createdAt: string;
}
/**
* This interface was referenced by `Config`'s JSON-Schema
* via the `definition` "localized-posts".
*/
export interface LocalizedPost {
id: number;
title?: string | null;
description?: string | null;
localizedDescription?: string | null;
localizedCheckbox?: boolean | null;
children?: (number | LocalizedPost)[] | null;
group?: {
children?: string | null;
};
updatedAt: string;
createdAt: string;
}
/**
* This interface was referenced by `Config`'s JSON-Schema
* via the `definition` "nested-fields".
*/
export interface NestedField {
id: number;
array?:
| {
relation?: {
relationTo: 'localized-posts';
value: number | LocalizedPost;
} | null;
hasManyRelation?: (number | LocalizedPost)[] | null;
hasManyPolyRelation?:
| {
relationTo: 'localized-posts';
value: number | LocalizedPost;
}[]
| null;
select?: ('one' | 'two' | 'three')[] | null;
number?: number[] | null;
text?: string[] | null;
id?: string | null;
}[]
| null;
updatedAt: string;
createdAt: string;
} }
/** /**
* This interface was referenced by `Config`'s JSON-Schema * This interface was referenced by `Config`'s JSON-Schema
* via the `definition` "users". * via the `definition` "users".
*/ */
export interface User { export interface User {
id: string; id: number;
relation?: (string | null) | LocalizedPost; relation?: (number | null) | LocalizedPost;
updatedAt: string; updatedAt: string;
createdAt: string; createdAt: string;
email: string; email: string;
@@ -63,29 +173,12 @@ export interface User {
lockUntil?: string | null; lockUntil?: string | null;
password?: string | null; password?: string | null;
} }
/**
* This interface was referenced by `Config`'s JSON-Schema
* via the `definition` "localized-posts".
*/
export interface LocalizedPost {
id: string;
title?: string | null;
localizedDescription?: string | null;
description?: string | null;
localizedCheckbox?: boolean | null;
children?: (string | LocalizedPost)[] | null;
group?: {
children?: string | null;
};
updatedAt: string;
createdAt: string;
}
/** /**
* This interface was referenced by `Config`'s JSON-Schema * This interface was referenced by `Config`'s JSON-Schema
* via the `definition` "array-fields". * via the `definition` "array-fields".
*/ */
export interface ArrayField { export interface ArrayField {
id: string; id: number;
items?: items?:
| { | {
text: string; text: string;
@@ -100,7 +193,7 @@ export interface ArrayField {
* via the `definition` "localized-required". * via the `definition` "localized-required".
*/ */
export interface LocalizedRequired { export interface LocalizedRequired {
id: string; id: number;
title: string; title: string;
layout: ( layout: (
| { | {
@@ -124,27 +217,27 @@ export interface LocalizedRequired {
* via the `definition` "with-localized-relationship". * via the `definition` "with-localized-relationship".
*/ */
export interface WithLocalizedRelationship { export interface WithLocalizedRelationship {
id: string; id: number;
localizedRelationship?: (string | null) | LocalizedPost; localizedRelationship?: (number | null) | LocalizedPost;
localizedRelationHasManyField?: (string | LocalizedPost)[] | null; localizedRelationHasManyField?: (number | LocalizedPost)[] | null;
localizedRelationMultiRelationTo?: localizedRelationMultiRelationTo?:
| ({ | ({
relationTo: 'localized-posts'; relationTo: 'localized-posts';
value: string | LocalizedPost; value: number | LocalizedPost;
} | null) } | null)
| ({ | ({
relationTo: 'dummy'; relationTo: 'dummy';
value: string | Dummy; value: number | Dummy;
} | null); } | null);
localizedRelationMultiRelationToHasMany?: localizedRelationMultiRelationToHasMany?:
| ( | (
| { | {
relationTo: 'localized-posts'; relationTo: 'localized-posts';
value: string | LocalizedPost; value: number | LocalizedPost;
} }
| { | {
relationTo: 'dummy'; relationTo: 'dummy';
value: string | Dummy; value: number | Dummy;
} }
)[] )[]
| null; | null;
@@ -156,7 +249,7 @@ export interface WithLocalizedRelationship {
* via the `definition` "dummy". * via the `definition` "dummy".
*/ */
export interface Dummy { export interface Dummy {
id: string; id: number;
name?: string | null; name?: string | null;
updatedAt: string; updatedAt: string;
createdAt: string; createdAt: string;
@@ -166,33 +259,33 @@ export interface Dummy {
* via the `definition` "relationship-localized". * via the `definition` "relationship-localized".
*/ */
export interface RelationshipLocalized { export interface RelationshipLocalized {
id: string; id: number;
relationship?: (string | null) | LocalizedPost; relationship?: (number | null) | LocalizedPost;
relationshipHasMany?: (string | LocalizedPost)[] | null; relationshipHasMany?: (number | LocalizedPost)[] | null;
relationMultiRelationTo?: relationMultiRelationTo?:
| ({ | ({
relationTo: 'localized-posts'; relationTo: 'localized-posts';
value: string | LocalizedPost; value: number | LocalizedPost;
} | null) } | null)
| ({ | ({
relationTo: 'dummy'; relationTo: 'dummy';
value: string | Dummy; value: number | Dummy;
} | null); } | null);
relationMultiRelationToHasMany?: relationMultiRelationToHasMany?:
| ( | (
| { | {
relationTo: 'localized-posts'; relationTo: 'localized-posts';
value: string | LocalizedPost; value: number | LocalizedPost;
} }
| { | {
relationTo: 'dummy'; relationTo: 'dummy';
value: string | Dummy; value: number | Dummy;
} }
)[] )[]
| null; | null;
arrayField?: arrayField?:
| { | {
nestedRelation?: (string | null) | LocalizedPost; nestedRelation?: (number | null) | LocalizedPost;
id?: string | null; id?: string | null;
}[] }[]
| null; | null;
@@ -204,7 +297,7 @@ export interface RelationshipLocalized {
* via the `definition` "nested". * via the `definition` "nested".
*/ */
export interface Nested { export interface Nested {
id: string; id: number;
blocks?: blocks?:
| { | {
array?: array?:
@@ -222,12 +315,74 @@ export interface Nested {
updatedAt: string; updatedAt: string;
createdAt: string; createdAt: string;
} }
/**
* This interface was referenced by `Config`'s JSON-Schema
* via the `definition` "groups".
*/
export interface Group {
id: number;
groupLocalized?: {
title?: string | null;
};
group?: {
title?: string | null;
};
deep?: {
array?:
| {
title?: string | null;
id?: string | null;
}[]
| null;
blocks?:
| {
title?: string | null;
id?: string | null;
blockName?: string | null;
blockType: 'first';
}[]
| null;
};
updatedAt: string;
createdAt: string;
}
/**
* This interface was referenced by `Config`'s JSON-Schema
* via the `definition` "tabs".
*/
export interface Tab {
id: number;
tabLocalized?: {
title?: string | null;
};
tab?: {
title?: string | null;
};
deep?: {
array?:
| {
title?: string | null;
id?: string | null;
}[]
| null;
blocks?:
| {
title?: string | null;
id?: string | null;
blockName?: string | null;
blockType: 'first';
}[]
| null;
};
updatedAt: string;
createdAt: string;
}
/** /**
* This interface was referenced by `Config`'s JSON-Schema * This interface was referenced by `Config`'s JSON-Schema
* via the `definition` "localized-sort". * via the `definition` "localized-sort".
*/ */
export interface LocalizedSort { export interface LocalizedSort {
id: string; id: number;
title?: string | null; title?: string | null;
date?: string | null; date?: string | null;
updatedAt: string; updatedAt: string;
@@ -238,7 +393,7 @@ export interface LocalizedSort {
* via the `definition` "blocks-same-name". * via the `definition` "blocks-same-name".
*/ */
export interface BlocksSameName { export interface BlocksSameName {
id: string; id: number;
blocks?: blocks?:
| ( | (
| { | {
@@ -263,10 +418,10 @@ export interface BlocksSameName {
* via the `definition` "payload-preferences". * via the `definition` "payload-preferences".
*/ */
export interface PayloadPreference { export interface PayloadPreference {
id: string; id: number;
user: { user: {
relationTo: 'users'; relationTo: 'users';
value: string | User; value: number | User;
}; };
key?: string | null; key?: string | null;
value?: value?:
@@ -286,7 +441,7 @@ export interface PayloadPreference {
* via the `definition` "payload-migrations". * via the `definition` "payload-migrations".
*/ */
export interface PayloadMigration { export interface PayloadMigration {
id: string; id: number;
name?: string | null; name?: string | null;
batch?: number | null; batch?: number | null;
updatedAt: string; updatedAt: string;
@@ -297,7 +452,7 @@ export interface PayloadMigration {
* via the `definition` "global-array". * via the `definition` "global-array".
*/ */
export interface GlobalArray { export interface GlobalArray {
id: string; id: number;
array?: array?:
| { | {
text?: string | null; text?: string | null;