UNPKG

11.2 kBTypeScriptView Raw
1declare 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}