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 } 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) => InstanceType<T['model']>;
|
33 | /**
|
34 | * Function to merge attributes defined during runtime
|
35 | */
|
36 | export type MergeCallback<T extends FactoryModelContract<LucidModel>> = (model: InstanceType<T['model']>, attributes: ExtractFactoryAttributes<T>, ctx: FactoryContextContract) => void;
|
37 | /**
|
38 | * Callback to define a new model state
|
39 | */
|
40 | export type StateCallback<Model extends LucidRow> = (model: Model, ctx: FactoryContextContract) => 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>> = (factory: FactoryBuilderContract<Model>, model: 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 = (factory: 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 | /**
|
86 | * Reference to the Lucid model relationship
|
87 | */
|
88 | relation: RelationshipsContract;
|
89 | /**
|
90 | * Pass context to the relationship. Must be done everytime, so that
|
91 | * relationships uses the same transaction as the parent model
|
92 | */
|
93 | useCtx(ctx: FactoryContextContract): this;
|
94 | /**
|
95 | * Create and persist
|
96 | */
|
97 | create(parent: LucidRow, callback?: RelationCallback, count?: number): Promise<void>;
|
98 | /**
|
99 | * Create and stub
|
100 | */
|
101 | make(parent: LucidRow, callback?: RelationCallback, count?: number): Promise<void>;
|
102 | }
|
103 | /**
|
104 | * ------------------------------------------------------
|
105 | * Runtime builder
|
106 | * ------------------------------------------------------
|
107 | */
|
108 | /**
|
109 | * Factory builder uses the factory model to create/make
|
110 | * instances of lucid models
|
111 | */
|
112 | export interface FactoryBuilderContract<FactoryModel extends FactoryModelContract<LucidModel>> {
|
113 | /**
|
114 | * Define custom database connection
|
115 | */
|
116 | connection(connection: string): this;
|
117 | /**
|
118 | * Define custom query client
|
119 | */
|
120 | client(client: QueryClientContract): this;
|
121 | /**
|
122 | * Apply pre-defined state
|
123 | */
|
124 | apply<K extends keyof FactoryModel['states']>(...states: K[]): this;
|
125 | /**
|
126 | * Create/make relationships for explicitly defined related factories
|
127 | */
|
128 | with<K extends keyof FactoryModel['relations']>(relation: K, count?: number, callback?: (
|
129 | /**
|
130 | * Receives the explicitly defined factory
|
131 | */
|
132 | factory: FactoryModel['relations'][K] extends () => FactoryBuilderContract<any> ? ReturnType<FactoryModel['relations'][K]> : never) => void): this;
|
133 | /**
|
134 | * Merge custom set of attributes. They are passed to the merge method of
|
135 | * the model factory
|
136 | *
|
137 | * For `createMany` and `makeMany`, you can pass an array of attributes mapped
|
138 | * according to the array index.
|
139 | */
|
140 | merge(attributes: OneOrMany<ExtractFactoryAttributes<FactoryModel>>): this;
|
141 | /**
|
142 | * Define custom runtime context. This method is usually called by
|
143 | * the relationships to ensure a single context is used by the
|
144 | * parent and relationship factories.
|
145 | *
|
146 | * Do not define a custom context, unless you know what you are really
|
147 | * doing.
|
148 | */
|
149 | useCtx(ctx: FactoryContextContract): this;
|
150 | /**
|
151 | * Make model instance without persitance. The make method
|
152 | * doesn't process relationships
|
153 | */
|
154 | make(callback?: (model: InstanceType<FactoryModel['model']>, ctx: FactoryContextContract) => void): Promise<InstanceType<FactoryModel['model']>>;
|
155 | /**
|
156 | * Create model instance and stub out the persistance
|
157 | * mechanism
|
158 | */
|
159 | makeStubbed(callback?: (model: InstanceType<FactoryModel['model']>, ctx: FactoryContextContract) => void): Promise<InstanceType<FactoryModel['model']>>;
|
160 | /**
|
161 | * Create and persist model instance
|
162 | */
|
163 | create(callback?: (model: InstanceType<FactoryModel['model']>, ctx: FactoryContextContract) => void): Promise<InstanceType<FactoryModel['model']>>;
|
164 | /**
|
165 | * Make model instance without persitance. The makeMany method
|
166 | * doesn't process relationships
|
167 | */
|
168 | makeMany(count: number, callback?: (model: InstanceType<FactoryModel['model']>, ctx: FactoryContextContract) => void): Promise<InstanceType<FactoryModel['model']>[]>;
|
169 | /**
|
170 | * Create one or more model instances and stub
|
171 | * out the persistance mechanism.
|
172 | */
|
173 | makeStubbedMany(count: number, callback?: (model: InstanceType<FactoryModel['model']>, ctx: FactoryContextContract) => void): Promise<InstanceType<FactoryModel['model']>[]>;
|
174 | /**
|
175 | * Create and persist more than one model instance
|
176 | */
|
177 | createMany(count: number, callback?: (model: InstanceType<FactoryModel['model']>, ctx: FactoryContextContract) => void): Promise<InstanceType<FactoryModel['model']>[]>;
|
178 | }
|
179 | /**
|
180 | * Query contract that initiates the factory builder. Since the factory builder
|
181 | * API surface is small, we also proxy all of it's methods for a nicer DX
|
182 | */
|
183 | export interface FactoryBuilderQueryContract<FactoryModel extends FactoryModelContract<LucidModel>> extends FactoryBuilderContract<FactoryModel> {
|
184 | query(options?: ModelAdapterOptions): FactoryBuilderContract<FactoryModel>;
|
185 | }
|
186 | /**
|
187 | * ------------------------------------------------------
|
188 | * Factory model
|
189 | * ------------------------------------------------------
|
190 | */
|
191 | /**
|
192 | * Factory model exposes the API to defined a model factory with states
|
193 | * and relationships
|
194 | */
|
195 | export interface FactoryModelContract<Model extends LucidModel> {
|
196 | /**
|
197 | * Reference to the underlying lucid model used by the factory
|
198 | * model
|
199 | */
|
200 | model: Model;
|
201 | /**
|
202 | * Mainly for types support. Not used at runtime to derive any
|
203 | * logic. Sorry, at times have to hack into typescript to
|
204 | * get the desired output. :)
|
205 | */
|
206 | states: unknown;
|
207 | relations: unknown;
|
208 | /**
|
209 | * Optionally define a custom method to instantiate the model
|
210 | * instance
|
211 | */
|
212 | newUp(callback: NewUpCallback<this>): this;
|
213 | merge(callback: MergeCallback<this>): this;
|
214 | /**
|
215 | * Define custom state for the factory. When executing the factory,
|
216 | * you can apply the pre-defined states
|
217 | */
|
218 | state<K extends string>(state: K, callback: StateCallback<InstanceType<Model>>): this & {
|
219 | states: {
|
220 | [P in K]: StateCallback<InstanceType<Model>>;
|
221 | };
|
222 | };
|
223 | /**
|
224 | * Define a relationship on another factory
|
225 | */
|
226 | relation<K extends ExtractModelRelations<InstanceType<Model>>, Relation>(relation: K, callback: Relation): this & {
|
227 | relations: {
|
228 | [P in K]: Relation;
|
229 | };
|
230 | };
|
231 | /**
|
232 | * Define before hooks. Only `create` event is invoked
|
233 | * during the before lifecycle
|
234 | */
|
235 | before(event: Exclude<EventsList, 'make'>, handler: HooksHandler<this>): this;
|
236 | /**
|
237 | * Define after hooks.
|
238 | */
|
239 | after(event: EventsList, handler: HooksHandler<this>): this;
|
240 | /**
|
241 | * Build model factory. This method returns the factory builder, which can be used to
|
242 | * execute model queries
|
243 | */
|
244 | build(): FactoryBuilderQueryContract<this>;
|
245 | }
|
246 | /**
|
247 | * ------------------------------------------------------
|
248 | * Manager to register new factories
|
249 | * ------------------------------------------------------
|
250 | */
|
251 | /**
|
252 | * Factory manager to define new factories
|
253 | */
|
254 | export interface FactoryManagerContract {
|
255 | /**
|
256 | * Define a custom factory
|
257 | */
|
258 | define<Model extends LucidModel>(model: Model, callback: DefineCallback<Model>): FactoryModelContract<Model>;
|
259 | /**
|
260 | * Define a custom callback to generate stub ids
|
261 | */
|
262 | stubId(callback: StubIdCallback): void;
|
263 | }
|
264 | const Factory: FactoryManagerContract;
|
265 | export default Factory;
|
266 | }
|