1 | declare module '@ioc:Adonis/Lucid/Factory' {
|
2 | import { faker } from '@faker-js/faker';
|
3 | import { OneOrMany, QueryClientContract, TransactionClientContract } from '@ioc:Adonis/Lucid/Database';
|
4 | import { LucidRow, LucidModel, ModelAttributes, ModelAdapterOptions, RelationshipsContract, ExtractModelRelations, ModelObject } from '@ioc:Adonis/Lucid/Orm';
|
5 | /**
|
6 | * ------------------------------------------------------
|
7 | * Helpers
|
8 | * ------------------------------------------------------
|
9 | */
|
10 | /**
|
11 | * Extracts the attributes accepted by the lucid model set on a
|
12 | * factory
|
13 | */
|
14 | export type ExtractFactoryAttributes<T extends FactoryModelContract<LucidModel>> = Partial<ModelAttributes<InstanceType<T['model']>>>;
|
15 | /**
|
16 | * ------------------------------------------------------
|
17 | * Callbacks
|
18 | * ------------------------------------------------------
|
19 | */
|
20 | /**
|
21 | * Function to return the model attributes.
|
22 | */
|
23 | export type DefineCallback<Model extends LucidModel> = (ctx: FactoryContextContract) => Promise<Partial<ModelAttributes<InstanceType<Model>>>> | Partial<ModelAttributes<InstanceType<Model>>>;
|
24 | /**
|
25 | * Function to generate custom stub ids
|
26 | */
|
27 | export type StubIdCallback = (counter: number, model: LucidRow) => any;
|
28 | /**
|
29 | * Function to initiate a model instance. It will receive the
|
30 | * attributes returned by the `define` method
|
31 | */
|
32 | export type NewUpCallback<T extends FactoryModelContract<LucidModel>> = (attributes: ExtractFactoryAttributes<T>, ctx: FactoryContextContract, model: T['model'], builder: FactoryBuilderContract<T>) => InstanceType<T['model']>;
|
33 | /**
|
34 | * Function to merge attributes defined during runtime
|
35 | */
|
36 | export type MergeCallback<T extends FactoryModelContract<LucidModel>> = (row: InstanceType<T['model']>, attributes: ExtractFactoryAttributes<T>, ctx: FactoryContextContract, builder: FactoryBuilderContract<T>) => void;
|
37 | /**
|
38 | * Callback to define a new model state
|
39 | */
|
40 | export type StateCallback<Model extends LucidModel> = (row: InstanceType<Model>, ctx: FactoryContextContract, builder: FactoryBuilderContract<FactoryModelContract<Model>>) => any | Promise<any>;
|
41 | /**
|
42 | * ------------------------------------------------------
|
43 | * Hooks
|
44 | * ------------------------------------------------------
|
45 | */
|
46 | /**
|
47 | * List of events for which a factory will trigger hooks
|
48 | */
|
49 | export type EventsList = 'makeStubbed' | 'create' | 'make';
|
50 | /**
|
51 | * Shape of hooks handler
|
52 | */
|
53 | export type HooksHandler<Model extends FactoryModelContract<LucidModel>> = (builder: FactoryBuilderContract<Model>, row: InstanceType<Model['model']>, ctx: FactoryContextContract) => void | Promise<void>;
|
54 | /**
|
55 | * ------------------------------------------------------
|
56 | * Runtime context
|
57 | * ------------------------------------------------------
|
58 | */
|
59 | /**
|
60 | * The runtime context of the factory builder. A new state is constructed
|
61 | * for each `create/make` operation and passed down to relationships
|
62 | * as well.
|
63 | */
|
64 | export interface FactoryContextContract {
|
65 | faker: typeof faker;
|
66 | isStubbed: boolean;
|
67 | $trx: TransactionClientContract | undefined;
|
68 | }
|
69 | /**
|
70 | * ------------------------------------------------------
|
71 | * Relationships
|
72 | * ------------------------------------------------------
|
73 | */
|
74 | /**
|
75 | * Callback accepted by the `with` method and relationships
|
76 | * `create` and `make` methods
|
77 | */
|
78 | export type RelationCallback = (builder: FactoryBuilderContract<FactoryModelContract<LucidModel>>) => void;
|
79 | /**
|
80 | * Shape of the factory relationships. To keep relationships slim, we will have
|
81 | * a common interface for relationships vs fine tuning API for each type of
|
82 | * relationship
|
83 | */
|
84 | export interface FactoryRelationContract {
|
85 | parent: LucidRow;
|
86 | /**
|
87 | * Reference to the Lucid model relationship
|
88 | */
|
89 | relation: RelationshipsContract;
|
90 | /**
|
91 | * Merge attributes with the relationship and its children
|
92 | */
|
93 | merge(attributes: any): this;
|
94 | /**
|
95 | * Define custom pivot attributes for many to many
|
96 | * relationship
|
97 | */
|
98 | pivotAttributes?(attributes: ModelObject | ModelObject[]): this;
|
99 | /**
|
100 | * Pass context to the relationship. Must be done everytime, so that
|
101 | * relationships uses the same transaction as the parent model
|
102 | */
|
103 | useCtx(ctx: FactoryContextContract): this;
|
104 | /**
|
105 | * Create and persist
|
106 | */
|
107 | create(parent: LucidRow, callback?: RelationCallback, count?: number): Promise<void>;
|
108 | /**
|
109 | * Create and stub
|
110 | */
|
111 | make(parent: LucidRow, callback?: RelationCallback, count?: number): Promise<void>;
|
112 | }
|
113 | /**
|
114 | * ------------------------------------------------------
|
115 | * Runtime builder
|
116 | * ------------------------------------------------------
|
117 | */
|
118 | /**
|
119 | * Factory builder uses the factory model to create/make
|
120 | * instances of lucid models
|
121 | */
|
122 | export interface FactoryBuilderContract<FactoryModel extends FactoryModelContract<LucidModel>> {
|
123 | /**
|
124 | * Reference to the factory
|
125 | */
|
126 | factory: FactoryModel;
|
127 | /**
|
128 | * Define custom database connection
|
129 | */
|
130 | connection(connection: string): this;
|
131 | /**
|
132 | * Define custom query client
|
133 | */
|
134 | client(client: QueryClientContract): this;
|
135 | /**
|
136 | * Apply pre-defined state
|
137 | */
|
138 | apply<K extends keyof FactoryModel['states']>(...states: K[]): this;
|
139 | /**
|
140 | * Create/make relationships for explicitly defined related factories
|
141 | */
|
142 | with<K extends keyof FactoryModel['relations']>(relation: K, count?: number, callback?: (
|
143 | /**
|
144 | * Receives the explicitly defined factory
|
145 | */
|
146 | builder: FactoryModel['relations'][K] extends () => FactoryBuilderContract<any> ? ReturnType<FactoryModel['relations'][K]> & {
|
147 | parent: InstanceType<FactoryModel['model']>;
|
148 | } : never) => void): this;
|
149 | /**
|
150 | * Define pivot attributes when persisting a many to many
|
151 | * relationship. Results in a noop, when not called
|
152 | * for a many to many relationship
|
153 | */
|
154 | pivotAttributes(attributes: ModelObject | ModelObject[]): this;
|
155 | /**
|
156 | * Merge custom set of attributes. They are passed to the merge method of
|
157 | * the model factory
|
158 | *
|
159 | * For `createMany` and `makeMany`, you can pass an array of attributes mapped
|
160 | * according to the array index.
|
161 | */
|
162 | merge(attributes: OneOrMany<ExtractFactoryAttributes<FactoryModel>>): this;
|
163 | /**
|
164 | * Merge custom set of attributes with the correct factory builder
|
165 | * model and all of its relationships as well
|
166 | */
|
167 | mergeRecursive(attributes: any): this;
|
168 | /**
|
169 | * Define custom runtime context. This method is usually called by
|
170 | * the relationships to ensure a single context is used by the
|
171 | * parent and relationship factories.
|
172 | *
|
173 | * Do not define a custom context, unless you know what you are really
|
174 | * doing.
|
175 | */
|
176 | useCtx(ctx: FactoryContextContract): this;
|
177 | /**
|
178 | * Tap into the persistence layer of factory builder. Allows one
|
179 | * to modify the model instance just before it is persisted
|
180 | * to the database
|
181 | */
|
182 | tap(callback: (row: InstanceType<FactoryModel['model']>, ctx: FactoryContextContract, builder: this) => void): this;
|
183 | /**
|
184 | * Make model instance without persitance. The make method
|
185 | * doesn't process relationships
|
186 | */
|
187 | make(): Promise<InstanceType<FactoryModel['model']>>;
|
188 | /**
|
189 | * Create model instance and stub out the persistance
|
190 | * mechanism
|
191 | */
|
192 | makeStubbed(): Promise<InstanceType<FactoryModel['model']>>;
|
193 | /**
|
194 | * Create and persist model instance
|
195 | */
|
196 | create(): Promise<InstanceType<FactoryModel['model']>>;
|
197 | /**
|
198 | * Make model instance without persitance. The makeMany method
|
199 | * doesn't process relationships
|
200 | */
|
201 | makeMany(count: number): Promise<InstanceType<FactoryModel['model']>[]>;
|
202 | /**
|
203 | * Create one or more model instances and stub
|
204 | * out the persistance mechanism.
|
205 | */
|
206 | makeStubbedMany(count: number): Promise<InstanceType<FactoryModel['model']>[]>;
|
207 | /**
|
208 | * Create and persist more than one model instance
|
209 | */
|
210 | createMany(count: number): Promise<InstanceType<FactoryModel['model']>[]>;
|
211 | }
|
212 | /**
|
213 | * Query contract that initiates the factory builder. Since the factory builder
|
214 | * API surface is small, we also proxy all of it's methods for a nicer DX
|
215 | */
|
216 | export interface FactoryBuilderQueryContract<FactoryModel extends FactoryModelContract<LucidModel>> extends FactoryBuilderContract<FactoryModel> {
|
217 | query(options?: ModelAdapterOptions, viaRelation?: FactoryRelationContract): FactoryBuilderContract<FactoryModel>;
|
218 | }
|
219 | /**
|
220 | * ------------------------------------------------------
|
221 | * Factory model
|
222 | * ------------------------------------------------------
|
223 | */
|
224 | /**
|
225 | * Factory model exposes the API to defined a model factory with states
|
226 | * and relationships
|
227 | */
|
228 | export interface FactoryModelContract<Model extends LucidModel> {
|
229 | /**
|
230 | * Reference to the underlying lucid model used by the factory
|
231 | * model
|
232 | */
|
233 | model: Model;
|
234 | /**
|
235 | * Mainly for types support. Not used at runtime to derive any
|
236 | * logic. Sorry, at times have to hack into typescript to
|
237 | * get the desired output. :)
|
238 | */
|
239 | states: unknown;
|
240 | relations: unknown;
|
241 | /**
|
242 | * Optionally define a custom method to instantiate the model
|
243 | * instance and manage merging attributes
|
244 | */
|
245 | newUp(callback: NewUpCallback<this>): this;
|
246 | merge(callback: MergeCallback<this>): this;
|
247 | /**
|
248 | * Define custom state for the factory. When executing the factory,
|
249 | * you can apply the pre-defined states
|
250 | */
|
251 | state<K extends string>(state: K, callback: StateCallback<Model>): this & {
|
252 | states: {
|
253 | [P in K]: StateCallback<Model>;
|
254 | };
|
255 | };
|
256 | /**
|
257 | * Define a relationship on another factory
|
258 | */
|
259 | relation<K extends ExtractModelRelations<InstanceType<Model>>, Relation>(relation: K, callback: Relation): this & {
|
260 | relations: {
|
261 | [P in K]: Relation;
|
262 | };
|
263 | };
|
264 | /**
|
265 | * Define before hooks. Only `create` event is invoked
|
266 | * during the before lifecycle
|
267 | */
|
268 | before(event: Exclude<EventsList, 'make'>, handler: HooksHandler<this>): this;
|
269 | /**
|
270 | * Define after hooks.
|
271 | */
|
272 | after(event: EventsList, handler: HooksHandler<this>): this;
|
273 | /**
|
274 | * Build model factory. This method returns the factory builder, which can be used to
|
275 | * execute model queries
|
276 | */
|
277 | build(): FactoryBuilderQueryContract<this>;
|
278 | }
|
279 | /**
|
280 | * ------------------------------------------------------
|
281 | * Manager to register new factories
|
282 | * ------------------------------------------------------
|
283 | */
|
284 | /**
|
285 | * Factory manager to define new factories
|
286 | */
|
287 | export interface FactoryManagerContract {
|
288 | /**
|
289 | * Define a custom factory
|
290 | */
|
291 | define<Model extends LucidModel>(model: Model, callback: DefineCallback<Model>): FactoryModelContract<Model>;
|
292 | /**
|
293 | * Define a custom callback to generate stub ids
|
294 | */
|
295 | stubId(callback: StubIdCallback): void;
|
296 | }
|
297 | const Factory: FactoryManagerContract;
|
298 | export default Factory;
|
299 | }
|