diff --git a/packages/drizzle/src/createGlobal.ts b/packages/drizzle/src/createGlobal.ts index d76a27926b..cc8015ae49 100644 --- a/packages/drizzle/src/createGlobal.ts +++ b/packages/drizzle/src/createGlobal.ts @@ -16,7 +16,9 @@ export async function createGlobal>( const tableName = this.tableNameMap.get(toSnakeCase(globalConfig.slug)) - const result = await upsertRow({ + data.createdAt = new Date().toISOString() + + const result = await upsertRow<{ globalType: string } & T>({ adapter: this, data, db, @@ -26,5 +28,7 @@ export async function createGlobal>( tableName, }) + result.globalType = slug + return result } diff --git a/packages/drizzle/src/transform/write/traverseFields.ts b/packages/drizzle/src/transform/write/traverseFields.ts index 928432837c..f51e9cc2f6 100644 --- a/packages/drizzle/src/transform/write/traverseFields.ts +++ b/packages/drizzle/src/transform/write/traverseFields.ts @@ -479,8 +479,9 @@ export const traverseFields = ({ } valuesToTransform.forEach(({ localeKey, ref, value }) => { + let formattedValue = value + if (typeof value !== 'undefined') { - let formattedValue = value if (value && field.type === 'point' && adapter.name !== 'sqlite') { formattedValue = sql`ST_GeomFromGeoJSON(${JSON.stringify(value)})` } @@ -490,12 +491,16 @@ export const traverseFields = ({ formattedValue = new Date(value).toISOString() } else if (value instanceof Date) { 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) { ref[localeKey][fieldName] = formattedValue } else { diff --git a/packages/drizzle/src/updateGlobal.ts b/packages/drizzle/src/updateGlobal.ts index 088c42b78d..d3ba00858d 100644 --- a/packages/drizzle/src/updateGlobal.ts +++ b/packages/drizzle/src/updateGlobal.ts @@ -17,7 +17,7 @@ export async function updateGlobal>( const existingGlobal = await db.query[tableName].findFirst({}) - const result = await upsertRow({ + const result = await upsertRow<{ globalType: string } & T>({ ...(existingGlobal ? { id: existingGlobal.id, operation: 'update' } : { operation: 'create' }), adapter: this, data, @@ -28,5 +28,7 @@ export async function updateGlobal>( tableName, }) + result.globalType = slug + return result } diff --git a/packages/payload/src/globals/operations/update.ts b/packages/payload/src/globals/operations/update.ts index 2a64cad0fd..d699b1b78c 100644 --- a/packages/payload/src/globals/operations/update.ts +++ b/packages/payload/src/globals/operations/update.ts @@ -244,6 +244,11 @@ export const updateOperation = async < // ///////////////////////////////////// if (!shouldSaveDraft) { + // Ensure global has createdAt + if (!result.createdAt) { + result.createdAt = new Date().toISOString() + } + if (globalExists) { result = await payload.db.updateGlobal({ slug, diff --git a/test/database/config.ts b/test/database/config.ts index eb5fd9df9e..8342cfcf1f 100644 --- a/test/database/config.ts +++ b/test/database/config.ts @@ -563,6 +563,24 @@ export default buildConfigWithDefaults({ ], versions: true, }, + { + slug: 'global-2', + fields: [ + { + name: 'text', + type: 'text', + }, + ], + }, + { + slug: 'global-3', + fields: [ + { + name: 'text', + type: 'text', + }, + ], + }, ], localization: { defaultLocale: 'en', diff --git a/test/database/int.spec.ts b/test/database/int.spec.ts index 888624d1e2..0a2cd81cad 100644 --- a/test/database/int.spec.ts +++ b/test/database/int.spec.ts @@ -27,6 +27,7 @@ import { initPayloadInt } from '../helpers/initPayloadInt.js' import { isMongoose } from '../helpers/isMongoose.js' import removeFiles from '../helpers/removeFiles.js' import { errorOnUnnamedFieldsSlug, postsSlug } from './shared.js' +import { Global2 } from './payload-types.js' const filename = fileURLToPath(import.meta.url) const dirname = path.dirname(filename) @@ -1357,4 +1358,54 @@ describe('database', () => { const { id: id_2 } = await payload.create({ collection: postsSlug, data: { title: 'ASD' } }) 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()) + }) }) diff --git a/test/database/payload-types.ts b/test/database/payload-types.ts index 62a306a5e3..f3a3ad31e1 100644 --- a/test/database/payload-types.ts +++ b/test/database/payload-types.ts @@ -52,9 +52,13 @@ export interface Config { }; globals: { global: Global; + 'global-2': Global2; + 'global-3': Global3; }; globalsSelect: { global: GlobalSelect | GlobalSelect; + 'global-2': Global2Select | Global2Select; + 'global-3': Global3Select | Global3Select; }; locale: 'en' | 'es'; user: User & { @@ -753,6 +757,26 @@ export interface Global { updatedAt?: 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 * via the `definition` "global_select". @@ -763,6 +787,26 @@ export interface GlobalSelect { createdAt?: T; globalType?: T; } +/** + * This interface was referenced by `Config`'s JSON-Schema + * via the `definition` "global-2_select". + */ +export interface Global2Select { + 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 { + text?: T; + updatedAt?: T; + createdAt?: T; + globalType?: T; +} /** * This interface was referenced by `Config`'s JSON-Schema * via the `definition` "auth".