Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix: allow mutation selection without passing a patch builder #964

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
27 changes: 26 additions & 1 deletion src/data/transaction.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import type {
IdentifiedSanityDocumentStub,
MultipleMutationResult,
Mutation,
MutationSelection,
PatchOperations,
SanityDocument,
SanityDocumentStub,
Expand Down Expand Up @@ -213,16 +214,29 @@ export class Transaction extends BaseTransaction {
* @param patchOps - Operations to perform, or a builder function
*/
patch(documentId: string, patchOps?: PatchBuilder | PatchOperations): this
/**
* Performs a patch on the given selection. Can either be a builder function or an object of patch operations.
*
* @param selection - An object with `query` and optional `params`, defining which document(s) to patch
* @param patchOps - Operations to perform, or a builder function
*/
patch(patch: MutationSelection, patchOps?: PatchBuilder | PatchOperations): this
/**
* Adds the given patch instance to the transaction.
* The operation is added to the current transaction, ready to be commited by `commit()`
*
* @param patch - Patch to execute
*/
patch(patch: Patch): this
patch(patchOrDocumentId: Patch | string, patchOps?: PatchBuilder | PatchOperations): this {
patch(
patchOrDocumentId: Patch | MutationSelection | string,
patchOps?: PatchBuilder | PatchOperations,
): this {
const isBuilder = typeof patchOps === 'function'
const isPatch = typeof patchOrDocumentId !== 'string' && patchOrDocumentId instanceof Patch
const isMutationSelection =
typeof patchOrDocumentId === 'object' &&
('query' in patchOrDocumentId || 'id' in patchOrDocumentId)

// transaction.patch(client.patch('documentId').inc({visits: 1}))
if (isPatch) {
Expand All @@ -239,6 +253,17 @@ export class Transaction extends BaseTransaction {
return this._add({patch: patch.serialize()})
}

/**
* transaction.patch(
* {query: "*[_type == 'person' && points >= $threshold]", params: { threshold: 100 }},
* {dec: { points: 100 }, inc: { bonuses: 1 }}
* )
*/
if (isMutationSelection) {
const patch = new Patch(patchOrDocumentId, patchOps || {}, this.#client)
return this._add({patch: patch.serialize()})
}

return this._add({patch: {id: patchOrDocumentId, ...patchOps}})
}
}
Expand Down
42 changes: 42 additions & 0 deletions test/client.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2379,6 +2379,48 @@ describe('client', async () => {
])
})

test('patch can use a mutation selector', () => {
const transaction = getClient()
.transaction()
.patch(
{
query: '*[_id in $ids]',
params: {ids: ['abc123', 'foo.456']},
},
{inc: {count: 1}},
)

expect(transaction.serialize()).toEqual([
{
patch: {
query: '*[_id in $ids]',
params: {ids: ['abc123', 'foo.456']},
inc: {count: 1},
},
},
])

const transactionWithCallback = getClient()
.transaction()
.patch(
{
query: '*[_id in $ids]',
params: {ids: ['abc123', 'foo.456']},
},
(p) => p.inc({count: 1}),
)

expect(transactionWithCallback.serialize()).toEqual([
{
patch: {
query: '*[_id in $ids]',
params: {ids: ['abc123', 'foo.456']},
inc: {count: 1},
},
},
])
})

test.skipIf(isEdge)('executes transaction when commit() is called', async () => {
const mutations = [{create: {_type: 'foo', bar: true}}, {delete: {id: 'barfoo'}}]
nock(projectHost())
Expand Down
Loading