-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathpatch-batch.util.ts
More file actions
83 lines (75 loc) · 2.05 KB
/
patch-batch.util.ts
File metadata and controls
83 lines (75 loc) · 2.05 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
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
import type { Id, Params } from '@feathersjs/feathers'
import { dequal as deepEqual } from 'dequal'
import type { KeyOf } from '../../internal.utils.js'
export type PatchBatchOptions<IdKey extends string> = {
/** the key of the id property */
id?: IdKey
}
export type PatchBatchResultItem<T = Record<string, unknown>, P = Params> = [
Id | null,
T,
P | undefined,
]
/**
* Batch patching utility that takes an array of items to be changed and returns an array of arguments to be called with the `patch` method.
*
* This utility is useful when you need to patch multiple items with varying data in as few requests as possible.
*
* @example
* ```ts
* const items = [
* { id: 1, value: 10 },
* { id: 2, value: 10 },
* { id: 3, value: 20 },
* ];
*
* const batched = patchBatch(items, { id: 'id' });
* // batched will be:
* // [
* // [null, { value: 10 }, { query: { id: { $in: [1, 2] } } }],
* // [3, { value: 20 }, undefined],
* // ]
*
* await Promise.all(batched.map(args => service.patch(...args)));
* ```
*
* @see https://utils.feathersjs.com/utils/patch-batch.html
*/
export function patchBatch<
T extends Record<string, any>,
IdKey extends KeyOf<T>,
P extends Params,
R extends Omit<T, IdKey> = Omit<T, IdKey>,
>(
items: T[],
options?: PatchBatchOptions<IdKey>,
): PatchBatchResultItem<R, P>[] {
const map: { ids: Id[]; data: R }[] = []
const idKey = options?.id ?? 'id'
for (const _data of items) {
const data = _data as unknown as R
const id = _data[idKey]
delete (data as any)[idKey as any]
const index = map.findIndex((item) => {
return deepEqual(item.data, data)
})
if (index === -1) {
map.push({ ids: [id], data })
} else {
map[index].ids.push(id)
}
}
return map.map(({ ids, data }) => {
return ids.length === 1
? ([ids[0], data, undefined] as PatchBatchResultItem<R, P>)
: ([
null,
data,
{
query: {
[idKey]: { $in: ids },
},
},
] as PatchBatchResultItem<R, P>)
})
}