-
-
Notifications
You must be signed in to change notification settings - Fork 144
Expand file tree
/
Copy pathtransaction.ts
More file actions
56 lines (54 loc) · 2.37 KB
/
transaction.ts
File metadata and controls
56 lines (54 loc) · 2.37 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
import type { Logger } from '@zenstackhq/client-helpers';
import { createInvalidator, type InvalidateFunc } from '@zenstackhq/client-helpers';
import type { FetchFn } from '@zenstackhq/client-helpers/fetch';
import { fetcher, marshal } from '@zenstackhq/client-helpers/fetch';
import { CoreReadOperations } from '@zenstackhq/orm';
import type { SchemaDef } from '@zenstackhq/schema';
import { TRANSACTION_ROUTE_PREFIX } from './constants.js';
import type { TransactionOperation } from './types.js';
/**
* Builds the mutation function for a sequential transaction request.
*/
export function makeTransactionMutationFn<Schema extends SchemaDef>(endpoint: string, fetch: FetchFn | undefined) {
return (operations: TransactionOperation<Schema>[]) => {
const reqUrl = `${endpoint}/${TRANSACTION_ROUTE_PREFIX}/sequential`;
const fetchInit = {
method: 'POST',
headers: { 'content-type': 'application/json' },
body: marshal(operations),
};
return fetcher<unknown[]>(reqUrl, fetchInit, fetch);
};
}
/**
* Builds the `onSuccess` handler for a sequential transaction mutation that invalidates
* all queries affected by the operations in the transaction.
*
* @param schema The schema definition.
* @param invalidateFunc Function that invalidates queries matching a predicate.
* @param logging Logging option.
* @param origOnSuccess The user-provided `onSuccess` callback to call after invalidation.
*/
export function makeTransactionOnSuccess(
schema: SchemaDef,
invalidateFunc: InvalidateFunc,
logging: Logger | undefined,
origOnSuccess: ((...args: any[]) => any) | undefined,
) {
return async (...args: any[]) => {
const variables = Array.isArray(args[1]) ? args[1] : [];
for (const op of variables) {
if (typeof op?.model !== 'string' || typeof op?.op !== 'string') {
continue;
}
// read-only ops don't mutate state, so they don't trigger invalidation
if (CoreReadOperations.includes(op.op)) {
continue;
}
const invalidator = createInvalidator(op.model, op.op, schema, invalidateFunc, logging);
// pass op.args as mutation variables so the invalidator can analyze nested writes
await invalidator(args[0], op.args, args[2]);
}
await origOnSuccess?.(...args);
};
}