(calls: {
input: Data[];
find: () => Promise<T[]>;
getInputId: (input: Data) => string;
getFetchedDataId: (input: T) => string;
create: (input: Data[]) => Promise<F[]>;
update: (input: Data[]) => Promise<F[]>;
})
| 13 | } |
| 14 | |
| 15 | export async function upsertMany<T, F, Data>(calls: { |
| 16 | input: Data[]; |
| 17 | find: () => Promise<T[]>; |
| 18 | getInputId: (input: Data) => string; |
| 19 | getFetchedDataId: (input: T) => string; |
| 20 | create: (input: Data[]) => Promise<F[]>; |
| 21 | update: (input: Data[]) => Promise<F[]>; |
| 22 | }) { |
| 23 | const { find, create, getInputId, getFetchedDataId, input, update } = calls; |
| 24 | const existing = await find(); |
| 25 | // map existing to id |
| 26 | const existingMap = existing.reduce( |
| 27 | (acc, cur) => { |
| 28 | acc[getFetchedDataId(cur)] = cur; |
| 29 | return acc; |
| 30 | }, |
| 31 | {} as Record<string, T>, |
| 32 | ); |
| 33 | |
| 34 | const toCreate = input |
| 35 | .filter((c) => !existingMap[getInputId(c)]) |
| 36 | .map((c) => c); |
| 37 | const toUpdate = input |
| 38 | .filter((c) => existingMap[getInputId(c)]) |
| 39 | .map((c) => c); |
| 40 | const [created, updated] = await Promise.all([ |
| 41 | update(toUpdate), |
| 42 | create(toCreate), |
| 43 | ]); |
| 44 | return [...created, ...updated]; |
| 45 | } |
| 46 | |
| 47 | export function addDefaultValues<T, F>( |
| 48 | input: T[], |
no test coverage detected