UNPKG

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