Skip to content

Commit 0935824

Browse files
authored
feat(db-*): add customID arg to db.create (#15653)
This PR adds `customID` argument to `payload.db.create` which can be used to ensure that a document is created with the provided ID, for example: ```ts payload.db.create({ collection: 'posts', customID: 'ce98d6c4-c3ab-45de-9dfc-bf33d94cc941', data: { } }) ``` This does not require to have a custom ID field in `posts` collection, as the following: ```ts payload.db.create({ collection: 'posts', data: { customID: 'ce98d6c4-c3ab-45de-9dfc-bf33d94cc941' } }) ``` Can be used only when you define a custom ID field
1 parent 9a38469 commit 0935824

File tree

6 files changed

+48
-2
lines changed

6 files changed

+48
-2
lines changed

packages/db-mongodb/src/create.ts

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ import { transform } from './utilities/transform.js'
1111

1212
export const create: Create = async function create(
1313
this: MongooseAdapter,
14-
{ collection: collectionSlug, data, req, returning },
14+
{ collection: collectionSlug, customID, data, req, returning },
1515
) {
1616
const { collectionConfig, customIDType, Model } = getCollection({ adapter: this, collectionSlug })
1717

@@ -30,6 +30,12 @@ export const create: Create = async function create(
3030

3131
if (customIDType) {
3232
data._id = data.id
33+
} else if (customID) {
34+
if (Types.ObjectId.isValid(customID)) {
35+
data._id = new Types.ObjectId(customID)
36+
} else {
37+
data._id = customID
38+
}
3339
} else if (this.allowIDOnCreate && data.id) {
3440
try {
3541
data._id = new Types.ObjectId(data.id as string)

packages/drizzle/src/create.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ import { getTransaction } from './utilities/getTransaction.js'
99

1010
export const create: Create = async function create(
1111
this: DrizzleAdapter,
12-
{ collection: collectionSlug, data, req, returning, select },
12+
{ collection: collectionSlug, customID, data, req, returning, select },
1313
) {
1414
const collection = this.payload.collections[collectionSlug].config
1515

@@ -20,6 +20,7 @@ export const create: Create = async function create(
2020
const result = await upsertRow({
2121
adapter: this,
2222
collectionSlug,
23+
customID,
2324
data,
2425
db,
2526
fields: collection.flattenedFields,

packages/drizzle/src/upsertRow/index.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,7 @@ export const upsertRow = async <T extends Record<string, unknown> | TypeWithID>(
4444
// TODO:
4545
// When we support joins for write operations (create/update) - pass collectionSlug to the buildFindManyArgs
4646
// Make a new argument in upsertRow.ts and pass the slug from every operation.
47+
customID,
4748
joinQuery: _joinQuery,
4849
operation,
4950
path = '',
@@ -196,6 +197,10 @@ export const upsertRow = async <T extends Record<string, unknown> | TypeWithID>(
196197
tableName,
197198
})
198199

200+
if (customID) {
201+
rowToInsert.row.id = customID
202+
}
203+
199204
// First, we insert the main row
200205
try {
201206
if (operation === 'update') {

packages/drizzle/src/upsertRow/types.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ type BaseArgs = {
2828
}
2929

3030
type CreateArgs = {
31+
customID?: number | string
3132
id?: never
3233
joinQuery?: never
3334
operation: 'create'
@@ -37,6 +38,7 @@ type CreateArgs = {
3738
} & BaseArgs
3839

3940
type UpdateArgs = {
41+
customID?: never
4042
id?: number | string
4143
joinQuery?: JoinQuery
4244
operation: 'update'

packages/payload/src/database/types.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -507,6 +507,7 @@ export type UpdateVersion = <T extends JsonObject = JsonObject>(
507507

508508
export type CreateArgs = {
509509
collection: CollectionSlug
510+
customID?: number | string
510511
data: Record<string, unknown>
511512
draft?: boolean
512513
locale?: string

test/database/int.spec.ts

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
/* eslint-disable vitest/no-conditional-expect */
12
import type { MongooseAdapter } from '@payloadcms/db-mongodb'
23
import type { PostgresAdapter } from '@payloadcms/db-postgres'
34
import type { Table } from 'drizzle-orm'
@@ -604,14 +605,17 @@ describe('database', () => {
604605
expect(updatedDocWithTimestamps.updatedAt).toBeUndefined()
605606
}
606607

608+
// eslint-disable-next-line vitest/expect-expect
607609
it('ensure timestamps are not created in update or create when timestamps are disabled', async () => {
608610
await noTimestampsTestLocalAPI()
609611
})
610612

613+
// eslint-disable-next-line vitest/expect-expect
611614
it('ensure timestamps are not created in db adapter update or create when timestamps are disabled', async () => {
612615
await noTimestampsTestDB(true)
613616
})
614617

618+
// eslint-disable-next-line vitest/expect-expect
615619
it(
616620
'ensure timestamps are not created in update or create when timestamps are disabled even with allowAdditionalKeys true',
617621
{ db: 'mongo' },
@@ -623,6 +627,7 @@ describe('database', () => {
623627
},
624628
)
625629

630+
// eslint-disable-next-line vitest/expect-expect
626631
it(
627632
'ensure timestamps are not created in db adapter update or create when timestamps are disabled even with allowAdditionalKeys true',
628633
{ db: 'mongo' },
@@ -4206,6 +4211,32 @@ describe('database', () => {
42064211
}
42074212
})
42084213

4214+
it('should allow creating docs with payload.db.create with custom ID', async () => {
4215+
if (payload.db.name === 'mongoose') {
4216+
const customId = new mongoose.Types.ObjectId().toHexString()
4217+
const res = await payload.db.create({
4218+
collection: 'simple',
4219+
customID: customId,
4220+
data: {
4221+
text: 'Test with custom ID',
4222+
},
4223+
})
4224+
4225+
expect(res.id).toBe(customId)
4226+
} else {
4227+
const id = payload.db.defaultIDType === 'text' ? randomUUID() : 95231
4228+
const res = await payload.db.create({
4229+
collection: 'simple',
4230+
customID: id,
4231+
data: {
4232+
text: 'Test with custom ID',
4233+
},
4234+
})
4235+
4236+
expect(res.id).toBe(id)
4237+
}
4238+
})
4239+
42094240
it('should allow to query like by ID with draft: true', async () => {
42104241
const category = await payload.create({
42114242
collection: 'categories',

0 commit comments

Comments
 (0)