-
Notifications
You must be signed in to change notification settings - Fork 0
/
index.ts
56 lines (52 loc) · 1.85 KB
/
index.ts
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 Meta, Model } from "accel-record-core";
type Functionable<T> = {
[K in keyof T]: T[K] | ((seq?: number) => T[K]);
};
type FunctionableUnion<D> = D extends infer T ? Functionable<Extract<D, T>> : never;
export type BuildParams<T extends typeof Model> = Partial<
FunctionableUnion<Meta<T>["CreateInput"]>
>;
type BuildParamsCallable<T extends typeof Model> =
| BuildParams<T>
| ((opt: { seq: number }) => BuildParams<T>);
// eslint-disable-next-line max-lines-per-function
export const defineFactory = <
T extends typeof Model,
S extends { [key: string]: BuildParamsCallable<T> },
>(
model: T,
defaults: BuildParamsCallable<T>,
options?: {
traits?: S;
}
) => {
let seq = 0;
type Trait = keyof S;
const callIfFunc = (arg: any) => (typeof arg === "function" ? arg(++seq) : arg);
const getValues = (params: BuildParams<T>, traits: Trait[]) => {
const data = { ...callIfFunc(defaults) };
for (const trait of traits) {
Object.assign(data, callIfFunc(options?.traits?.[trait]));
}
Object.assign(data, params);
const ret = {} as any;
for (const [key, value] of Object.entries(data)) {
ret[key] = callIfFunc(value);
}
return ret;
};
return {
create(params: BuildParams<T> = {}, ...traits: Trait[]): ReturnType<typeof Model.create<T>> {
return model.create(getValues(params, traits));
},
build(params: BuildParams<T> = {}, ...traits: Trait[]): ReturnType<typeof Model.build<T>> {
return model.build(getValues(params, traits));
},
createList(count: number, params: BuildParams<T> = {}, ...traits: Trait[]) {
return Array.from({ length: count }, () => this.create(params, ...traits));
},
buildList(count: number, params: BuildParams<T> = {}, ...traits: Trait[]) {
return Array.from({ length: count }, () => this.build(params, ...traits));
},
};
};