UNPKG

8.18 kBJavaScriptView Raw
1"use strict";
2/*
3 * @adonisjs/lucid
4 *
5 * (c) Harminder Virk <virk@adonisjs.com>
6 *
7 * For the full copyright and license information, please view the LICENSE
8 * file that was distributed with this source code.
9 */
10Object.defineProperty(exports, "__esModule", { value: true });
11exports.FactoryModel = void 0;
12const hooks_1 = require("@poppinss/hooks");
13const HasOne_1 = require("./Relations/HasOne");
14const HasMany_1 = require("./Relations/HasMany");
15const FactoryBuilder_1 = require("./FactoryBuilder");
16const BelongsTo_1 = require("./Relations/BelongsTo");
17const ManyToMany_1 = require("./Relations/ManyToMany");
18/**
19 * Factory model exposes the API to define a model factory with custom
20 * states and relationships
21 */
22class FactoryModel {
23 constructor(model, define, manager) {
24 Object.defineProperty(this, "model", {
25 enumerable: true,
26 configurable: true,
27 writable: true,
28 value: model
29 });
30 Object.defineProperty(this, "define", {
31 enumerable: true,
32 configurable: true,
33 writable: true,
34 value: define
35 });
36 Object.defineProperty(this, "manager", {
37 enumerable: true,
38 configurable: true,
39 writable: true,
40 value: manager
41 });
42 /**
43 * Method to instantiate a new model instance. This method can be
44 * overridden using the `newUp` public method.
45 */
46 Object.defineProperty(this, "newUpModelInstance", {
47 enumerable: true,
48 configurable: true,
49 writable: true,
50 value: function (attributes) {
51 const ModelConstructor = this.model;
52 /**
53 * Handling case, where someone returns model instance directly
54 */
55 if (attributes instanceof ModelConstructor) {
56 return attributes;
57 }
58 const modelInstance = new ModelConstructor();
59 modelInstance.merge(attributes);
60 return modelInstance;
61 }.bind(this)
62 });
63 /**
64 * Method to merge runtime attributes with the model instance. This method
65 * can be overridden using the `merge` method.
66 */
67 Object.defineProperty(this, "mergeAttributes", {
68 enumerable: true,
69 configurable: true,
70 writable: true,
71 value: function (model, attributes) {
72 model.merge(attributes);
73 }.bind(this)
74 });
75 /**
76 * A collection of factory states
77 */
78 Object.defineProperty(this, "states", {
79 enumerable: true,
80 configurable: true,
81 writable: true,
82 value: {}
83 });
84 /**
85 * A collection of factory relations
86 */
87 Object.defineProperty(this, "relations", {
88 enumerable: true,
89 configurable: true,
90 writable: true,
91 value: {}
92 });
93 /**
94 * A set of registered hooks
95 */
96 Object.defineProperty(this, "hooks", {
97 enumerable: true,
98 configurable: true,
99 writable: true,
100 value: new hooks_1.Hooks()
101 });
102 }
103 /**
104 * Register a before event hook
105 */
106 before(event, handler) {
107 this.hooks.add('before', event, handler);
108 return this;
109 }
110 /**
111 * Register an after event hook
112 */
113 after(event, handler) {
114 this.hooks.add('after', event, handler);
115 return this;
116 }
117 /**
118 * Returns state callback defined on the model factory. Raises an
119 * exception, when state is not registered
120 */
121 getState(state) {
122 const stateCallback = this.states[state];
123 if (!stateCallback) {
124 throw new Error(`Cannot apply undefined state "${state}". Double check the model factory`);
125 }
126 return stateCallback;
127 }
128 /**
129 * Returns the pre-registered relationship factory function, along with
130 * the original model relation.
131 */
132 getRelation(relation) {
133 const relationship = this.relations[relation];
134 if (!relationship) {
135 throw new Error(`Cannot setup undefined relationship "${relation}". Double check the model factory`);
136 }
137 return relationship;
138 }
139 /**
140 * Define custom state for the factory. When executing the factory,
141 * you can apply the pre-defined states
142 */
143 state(state, callback) {
144 this.states[state] = callback;
145 return this;
146 }
147 /**
148 * Define a relationship on another factory
149 */
150 relation(relation, callback) {
151 const modelRelation = this.model.$getRelation(relation);
152 /**
153 * Only whitelisted relationships are allowed on the factory
154 */
155 if (!modelRelation) {
156 throw new Error([
157 `Cannot define "${relation}" relationship.`,
158 `The relationship must exist on the "${this.model.name}" model first`,
159 ].join(' '));
160 }
161 switch (modelRelation.type) {
162 case 'belongsTo':
163 this.relations[relation] = new BelongsTo_1.BelongsTo(modelRelation, callback);
164 break;
165 case 'hasOne':
166 this.relations[relation] = new HasOne_1.HasOne(modelRelation, callback);
167 break;
168 case 'hasMany':
169 this.relations[relation] = new HasMany_1.HasMany(modelRelation, callback);
170 break;
171 case 'manyToMany':
172 this.relations[relation] = new ManyToMany_1.ManyToMany(modelRelation, callback);
173 break;
174 case 'hasManyThrough':
175 throw new Error([
176 `Cannot define "${relation}" relationship.`,
177 '"hasManyThrough" relationship does not have any persistance API',
178 ].join(' '));
179 }
180 return this;
181 }
182 /**
183 * Define a custom `newUp` method
184 */
185 newUp(callback) {
186 this.newUpModelInstance = callback;
187 return this;
188 }
189 /**
190 * Define a custom `merge` method
191 */
192 merge(callback) {
193 this.mergeAttributes = callback;
194 return this;
195 }
196 /**
197 * Build factory model and return factory builder. The builder is then
198 * used to make/create model instances
199 */
200 build() {
201 /**
202 * Return a build object, which proxies all of the factory builder
203 * method and invokes them with a fresh instance.
204 */
205 const builder = {
206 model: this,
207 query(options) {
208 return new FactoryBuilder_1.FactoryBuilder(this.model, options);
209 },
210 client(...args) {
211 return this.query().client(...args);
212 },
213 connection(...args) {
214 return this.query().connection(...args);
215 },
216 apply(...args) {
217 return this.query().apply(...args);
218 },
219 with(relation, ...args) {
220 return this.query().with(relation, ...args);
221 },
222 merge(attributes) {
223 return this.query().merge(attributes);
224 },
225 useCtx(ctx) {
226 return this.query().useCtx(ctx);
227 },
228 make(callback) {
229 return this.query().make(callback);
230 },
231 makeStubbed(callback) {
232 return this.query().makeStubbed(callback);
233 },
234 create(callback) {
235 return this.query().create(callback);
236 },
237 makeMany(count, callback) {
238 return this.query().makeMany(count, callback);
239 },
240 makeStubbedMany(count, callback) {
241 return this.query().makeStubbedMany(count, callback);
242 },
243 createMany(count, callback) {
244 return this.query().createMany(count, callback);
245 },
246 };
247 return builder;
248 }
249}
250exports.FactoryModel = FactoryModel;