fix(db-postgres): ensure globals have createdAt, updatedAt and globalType fields (#10938)
Previously, data for globals was inconsistent across database adapters. In Postgres, globals didn't store correct `createdAt`, `updatedAt` fields and the `updateGlobal` lacked the `globalType` field. This PR solves that without introducing schema changes.
This commit is contained in:
@@ -16,7 +16,9 @@ export async function createGlobal<T extends Record<string, unknown>>(
|
|||||||
|
|
||||||
const tableName = this.tableNameMap.get(toSnakeCase(globalConfig.slug))
|
const tableName = this.tableNameMap.get(toSnakeCase(globalConfig.slug))
|
||||||
|
|
||||||
const result = await upsertRow<T>({
|
data.createdAt = new Date().toISOString()
|
||||||
|
|
||||||
|
const result = await upsertRow<{ globalType: string } & T>({
|
||||||
adapter: this,
|
adapter: this,
|
||||||
data,
|
data,
|
||||||
db,
|
db,
|
||||||
@@ -26,5 +28,7 @@ export async function createGlobal<T extends Record<string, unknown>>(
|
|||||||
tableName,
|
tableName,
|
||||||
})
|
})
|
||||||
|
|
||||||
|
result.globalType = slug
|
||||||
|
|
||||||
return result
|
return result
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -479,8 +479,9 @@ export const traverseFields = ({
|
|||||||
}
|
}
|
||||||
|
|
||||||
valuesToTransform.forEach(({ localeKey, ref, value }) => {
|
valuesToTransform.forEach(({ localeKey, ref, value }) => {
|
||||||
if (typeof value !== 'undefined') {
|
|
||||||
let formattedValue = value
|
let formattedValue = value
|
||||||
|
|
||||||
|
if (typeof value !== 'undefined') {
|
||||||
if (value && field.type === 'point' && adapter.name !== 'sqlite') {
|
if (value && field.type === 'point' && adapter.name !== 'sqlite') {
|
||||||
formattedValue = sql`ST_GeomFromGeoJSON(${JSON.stringify(value)})`
|
formattedValue = sql`ST_GeomFromGeoJSON(${JSON.stringify(value)})`
|
||||||
}
|
}
|
||||||
@@ -490,12 +491,16 @@ export const traverseFields = ({
|
|||||||
formattedValue = new Date(value).toISOString()
|
formattedValue = new Date(value).toISOString()
|
||||||
} else if (value instanceof Date) {
|
} else if (value instanceof Date) {
|
||||||
formattedValue = value.toISOString()
|
formattedValue = value.toISOString()
|
||||||
} else if (fieldName === 'updatedAt') {
|
}
|
||||||
// let the db handle this
|
|
||||||
formattedValue = new Date().toISOString()
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (field.type === 'date' && fieldName === 'updatedAt') {
|
||||||
|
// let the db handle this
|
||||||
|
formattedValue = new Date().toISOString()
|
||||||
|
}
|
||||||
|
|
||||||
|
if (typeof formattedValue !== 'undefined') {
|
||||||
if (localeKey) {
|
if (localeKey) {
|
||||||
ref[localeKey][fieldName] = formattedValue
|
ref[localeKey][fieldName] = formattedValue
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
@@ -17,7 +17,7 @@ export async function updateGlobal<T extends Record<string, unknown>>(
|
|||||||
|
|
||||||
const existingGlobal = await db.query[tableName].findFirst({})
|
const existingGlobal = await db.query[tableName].findFirst({})
|
||||||
|
|
||||||
const result = await upsertRow<T>({
|
const result = await upsertRow<{ globalType: string } & T>({
|
||||||
...(existingGlobal ? { id: existingGlobal.id, operation: 'update' } : { operation: 'create' }),
|
...(existingGlobal ? { id: existingGlobal.id, operation: 'update' } : { operation: 'create' }),
|
||||||
adapter: this,
|
adapter: this,
|
||||||
data,
|
data,
|
||||||
@@ -28,5 +28,7 @@ export async function updateGlobal<T extends Record<string, unknown>>(
|
|||||||
tableName,
|
tableName,
|
||||||
})
|
})
|
||||||
|
|
||||||
|
result.globalType = slug
|
||||||
|
|
||||||
return result
|
return result
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -244,6 +244,11 @@ export const updateOperation = async <
|
|||||||
// /////////////////////////////////////
|
// /////////////////////////////////////
|
||||||
|
|
||||||
if (!shouldSaveDraft) {
|
if (!shouldSaveDraft) {
|
||||||
|
// Ensure global has createdAt
|
||||||
|
if (!result.createdAt) {
|
||||||
|
result.createdAt = new Date().toISOString()
|
||||||
|
}
|
||||||
|
|
||||||
if (globalExists) {
|
if (globalExists) {
|
||||||
result = await payload.db.updateGlobal({
|
result = await payload.db.updateGlobal({
|
||||||
slug,
|
slug,
|
||||||
|
|||||||
@@ -563,6 +563,24 @@ export default buildConfigWithDefaults({
|
|||||||
],
|
],
|
||||||
versions: true,
|
versions: true,
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
slug: 'global-2',
|
||||||
|
fields: [
|
||||||
|
{
|
||||||
|
name: 'text',
|
||||||
|
type: 'text',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
slug: 'global-3',
|
||||||
|
fields: [
|
||||||
|
{
|
||||||
|
name: 'text',
|
||||||
|
type: 'text',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
],
|
],
|
||||||
localization: {
|
localization: {
|
||||||
defaultLocale: 'en',
|
defaultLocale: 'en',
|
||||||
|
|||||||
@@ -27,6 +27,7 @@ import { initPayloadInt } from '../helpers/initPayloadInt.js'
|
|||||||
import { isMongoose } from '../helpers/isMongoose.js'
|
import { isMongoose } from '../helpers/isMongoose.js'
|
||||||
import removeFiles from '../helpers/removeFiles.js'
|
import removeFiles from '../helpers/removeFiles.js'
|
||||||
import { errorOnUnnamedFieldsSlug, postsSlug } from './shared.js'
|
import { errorOnUnnamedFieldsSlug, postsSlug } from './shared.js'
|
||||||
|
import { Global2 } from './payload-types.js'
|
||||||
|
|
||||||
const filename = fileURLToPath(import.meta.url)
|
const filename = fileURLToPath(import.meta.url)
|
||||||
const dirname = path.dirname(filename)
|
const dirname = path.dirname(filename)
|
||||||
@@ -1357,4 +1358,54 @@ describe('database', () => {
|
|||||||
const { id: id_2 } = await payload.create({ collection: postsSlug, data: { title: 'ASD' } })
|
const { id: id_2 } = await payload.create({ collection: postsSlug, data: { title: 'ASD' } })
|
||||||
expect(id_2).not.toBe(id)
|
expect(id_2).not.toBe(id)
|
||||||
})
|
})
|
||||||
|
|
||||||
|
it('payload.db.createGlobal should have globalType, updatedAt, createdAt fields', async () => {
|
||||||
|
let timestamp = Date.now()
|
||||||
|
let result = (await payload.db.createGlobal({
|
||||||
|
slug: 'global-2',
|
||||||
|
data: { text: 'this is global-2' },
|
||||||
|
})) as Global2 & { globalType: string }
|
||||||
|
|
||||||
|
expect(result.text).toBe('this is global-2')
|
||||||
|
expect(result.globalType).toBe('global-2')
|
||||||
|
expect(timestamp).toBeLessThanOrEqual(new Date(result.createdAt as string).getTime())
|
||||||
|
expect(timestamp).toBeLessThanOrEqual(new Date(result.updatedAt as string).getTime())
|
||||||
|
|
||||||
|
const createdAt = new Date(result.createdAt as string).getTime()
|
||||||
|
|
||||||
|
result = (await payload.db.updateGlobal({
|
||||||
|
slug: 'global-2',
|
||||||
|
data: { text: 'this is global-2 but updated' },
|
||||||
|
})) as Global2 & { globalType: string }
|
||||||
|
|
||||||
|
expect(result.text).toBe('this is global-2 but updated')
|
||||||
|
expect(result.globalType).toBe('global-2')
|
||||||
|
expect(createdAt).toEqual(new Date(result.createdAt as string).getTime())
|
||||||
|
expect(createdAt).toBeLessThan(new Date(result.updatedAt as string).getTime())
|
||||||
|
})
|
||||||
|
|
||||||
|
it('payload.updateGlobal should have globalType, updatedAt, createdAt fields', async () => {
|
||||||
|
let timestamp = Date.now()
|
||||||
|
let result = (await payload.updateGlobal({
|
||||||
|
slug: 'global-3',
|
||||||
|
data: { text: 'this is global-3' },
|
||||||
|
})) as Global2 & { globalType: string }
|
||||||
|
|
||||||
|
expect(result.text).toBe('this is global-3')
|
||||||
|
expect(result.globalType).toBe('global-3')
|
||||||
|
expect(timestamp).toBeLessThanOrEqual(new Date(result.createdAt as string).getTime())
|
||||||
|
expect(timestamp).toBeLessThanOrEqual(new Date(result.updatedAt as string).getTime())
|
||||||
|
|
||||||
|
const createdAt = new Date(result.createdAt as string).getTime()
|
||||||
|
|
||||||
|
result = (await payload.updateGlobal({
|
||||||
|
slug: 'global-3',
|
||||||
|
data: { text: 'this is global-3 but updated' },
|
||||||
|
})) as Global2 & { globalType: string }
|
||||||
|
|
||||||
|
expect(result.text).toBe('this is global-3 but updated')
|
||||||
|
expect(result.globalType).toBe('global-3')
|
||||||
|
expect(createdAt).toEqual(new Date(result.createdAt as string).getTime())
|
||||||
|
expect(createdAt).toBeLessThan(new Date(result.updatedAt as string).getTime())
|
||||||
|
})
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -52,9 +52,13 @@ export interface Config {
|
|||||||
};
|
};
|
||||||
globals: {
|
globals: {
|
||||||
global: Global;
|
global: Global;
|
||||||
|
'global-2': Global2;
|
||||||
|
'global-3': Global3;
|
||||||
};
|
};
|
||||||
globalsSelect: {
|
globalsSelect: {
|
||||||
global: GlobalSelect<false> | GlobalSelect<true>;
|
global: GlobalSelect<false> | GlobalSelect<true>;
|
||||||
|
'global-2': Global2Select<false> | Global2Select<true>;
|
||||||
|
'global-3': Global3Select<false> | Global3Select<true>;
|
||||||
};
|
};
|
||||||
locale: 'en' | 'es';
|
locale: 'en' | 'es';
|
||||||
user: User & {
|
user: User & {
|
||||||
@@ -753,6 +757,26 @@ export interface Global {
|
|||||||
updatedAt?: string | null;
|
updatedAt?: string | null;
|
||||||
createdAt?: string | null;
|
createdAt?: string | null;
|
||||||
}
|
}
|
||||||
|
/**
|
||||||
|
* This interface was referenced by `Config`'s JSON-Schema
|
||||||
|
* via the `definition` "global-2".
|
||||||
|
*/
|
||||||
|
export interface Global2 {
|
||||||
|
id: string;
|
||||||
|
text?: string | null;
|
||||||
|
updatedAt?: string | null;
|
||||||
|
createdAt?: string | null;
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* This interface was referenced by `Config`'s JSON-Schema
|
||||||
|
* via the `definition` "global-3".
|
||||||
|
*/
|
||||||
|
export interface Global3 {
|
||||||
|
id: string;
|
||||||
|
text?: string | null;
|
||||||
|
updatedAt?: string | null;
|
||||||
|
createdAt?: string | null;
|
||||||
|
}
|
||||||
/**
|
/**
|
||||||
* This interface was referenced by `Config`'s JSON-Schema
|
* This interface was referenced by `Config`'s JSON-Schema
|
||||||
* via the `definition` "global_select".
|
* via the `definition` "global_select".
|
||||||
@@ -763,6 +787,26 @@ export interface GlobalSelect<T extends boolean = true> {
|
|||||||
createdAt?: T;
|
createdAt?: T;
|
||||||
globalType?: T;
|
globalType?: T;
|
||||||
}
|
}
|
||||||
|
/**
|
||||||
|
* This interface was referenced by `Config`'s JSON-Schema
|
||||||
|
* via the `definition` "global-2_select".
|
||||||
|
*/
|
||||||
|
export interface Global2Select<T extends boolean = true> {
|
||||||
|
text?: T;
|
||||||
|
updatedAt?: T;
|
||||||
|
createdAt?: T;
|
||||||
|
globalType?: T;
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* This interface was referenced by `Config`'s JSON-Schema
|
||||||
|
* via the `definition` "global-3_select".
|
||||||
|
*/
|
||||||
|
export interface Global3Select<T extends boolean = true> {
|
||||||
|
text?: T;
|
||||||
|
updatedAt?: T;
|
||||||
|
createdAt?: T;
|
||||||
|
globalType?: T;
|
||||||
|
}
|
||||||
/**
|
/**
|
||||||
* This interface was referenced by `Config`'s JSON-Schema
|
* This interface was referenced by `Config`'s JSON-Schema
|
||||||
* via the `definition` "auth".
|
* via the `definition` "auth".
|
||||||
|
|||||||
Reference in New Issue
Block a user