UNPKG

11.7 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 */
10var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
11 if (k2 === undefined) k2 = k;
12 var desc = Object.getOwnPropertyDescriptor(m, k);
13 if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
14 desc = { enumerable: true, get: function() { return m[k]; } };
15 }
16 Object.defineProperty(o, k2, desc);
17}) : (function(o, m, k, k2) {
18 if (k2 === undefined) k2 = k;
19 o[k2] = m[k];
20}));
21var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
22 Object.defineProperty(o, "default", { enumerable: true, value: v });
23}) : function(o, v) {
24 o["default"] = v;
25});
26var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
27 var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
28 if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
29 else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
30 return c > 3 && r && Object.defineProperty(target, key, r), r;
31};
32var __importStar = (this && this.__importStar) || function (mod) {
33 if (mod && mod.__esModule) return mod;
34 var result = {};
35 if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
36 __setModuleDefault(result, mod);
37 return result;
38};
39var __metadata = (this && this.__metadata) || function (k, v) {
40 if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
41};
42var __importDefault = (this && this.__importDefault) || function (mod) {
43 return (mod && mod.__esModule) ? mod : { "default": mod };
44};
45Object.defineProperty(exports, "__esModule", { value: true });
46const slash_1 = __importDefault(require("slash"));
47const path_1 = require("path");
48const standalone_1 = require("@adonisjs/core/build/standalone");
49class DbSeed extends standalone_1.BaseCommand {
50 constructor() {
51 super(...arguments);
52 Object.defineProperty(this, "seeder", {
53 enumerable: true,
54 configurable: true,
55 writable: true,
56 value: void 0
57 });
58 /**
59 * Track if one or more seeders have failed
60 */
61 Object.defineProperty(this, "hasError", {
62 enumerable: true,
63 configurable: true,
64 writable: true,
65 value: false
66 });
67 /**
68 * Choose a custom pre-defined connection. Otherwise, we use the
69 * default connection
70 */
71 Object.defineProperty(this, "connection", {
72 enumerable: true,
73 configurable: true,
74 writable: true,
75 value: void 0
76 });
77 /**
78 * Interactive mode allows selecting seeder files
79 */
80 Object.defineProperty(this, "interactive", {
81 enumerable: true,
82 configurable: true,
83 writable: true,
84 value: void 0
85 });
86 /**
87 * Define a custom set of seeder files. Interactive and files together ignores
88 * the interactive mode.
89 */
90 Object.defineProperty(this, "files", {
91 enumerable: true,
92 configurable: true,
93 writable: true,
94 value: []
95 });
96 /**
97 * Display migrations result in one compact single-line output
98 */
99 Object.defineProperty(this, "compactOutput", {
100 enumerable: true,
101 configurable: true,
102 writable: true,
103 value: false
104 });
105 }
106 /**
107 * Print log message to the console
108 */
109 printLogMessage(file) {
110 const colors = this['colors'];
111 let color = 'gray';
112 let message = '';
113 let prefix = '';
114 switch (file.status) {
115 case 'pending':
116 message = 'pending ';
117 color = 'gray';
118 break;
119 case 'failed':
120 message = 'error ';
121 prefix = file.error.message;
122 color = 'red';
123 break;
124 case 'ignored':
125 message = 'ignored ';
126 prefix = 'Enabled only in development environment';
127 color = 'dim';
128 break;
129 case 'completed':
130 message = 'completed';
131 color = 'green';
132 break;
133 }
134 console.log(`${colors[color]('❯')} ${colors[color](message)} ${file.file.name}`);
135 if (prefix) {
136 console.log(` ${colors[color](prefix)}`);
137 }
138 }
139 /**
140 * Not a valid connection
141 */
142 printNotAValidConnection(connection) {
143 this.logger.error(`"${connection}" is not a valid connection name. Double check "config/database" file`);
144 }
145 /**
146 * Print log that the selected seeder file is invalid
147 */
148 printNotAValidFile(fileName) {
149 this.printLogMessage({
150 file: {
151 name: fileName,
152 absPath: fileName,
153 getSource: () => { },
154 },
155 status: 'failed',
156 error: new Error('Invalid file path. Pass relative path from the application root'),
157 });
158 }
159 /**
160 * Get files cherry picked using either "--interactive" or the
161 * "--files" flag
162 */
163 async getCherryPickedFiles(seedersFiles) {
164 if (this.files.length) {
165 return this.files.map((file) => {
166 const fileExt = (0, path_1.extname)(file);
167 return (fileExt ? file.replace(fileExt, '') : file).replace(/^\.\/|^\.\\\\/, '');
168 });
169 }
170 else if (this.interactive) {
171 return await this.prompt.multiple('Select files to run', seedersFiles.map((file) => {
172 return { name: file.name };
173 }));
174 }
175 return seedersFiles.map((file) => file.name);
176 }
177 /**
178 * Instantiate seeders runner
179 */
180 async instantiateSeeder() {
181 const db = this.application.container.use('Adonis/Lucid/Database');
182 const { SeedsRunner } = await Promise.resolve().then(() => __importStar(require('../src/SeedsRunner')));
183 this.seeder = new SeedsRunner(db, this.application, this.connection);
184 }
185 /**
186 * Execute selected seeders
187 */
188 async executedSeeders(selectedSeederFiles, files) {
189 const seedersResults = [];
190 for (let fileName of selectedSeederFiles) {
191 const sourceFile = files.find(({ name }) => (0, slash_1.default)(fileName) === (0, slash_1.default)(name));
192 if (!sourceFile) {
193 this.printNotAValidFile(fileName);
194 this.hasError = true;
195 return;
196 }
197 const response = await this.seeder.run(sourceFile);
198 if (response.status === 'failed') {
199 this.hasError = true;
200 }
201 if (!this.compactOutput) {
202 this.printLogMessage(response);
203 }
204 seedersResults.push(response);
205 }
206 return seedersResults;
207 }
208 /**
209 * Print Single-line output when `compact-output` is enabled
210 */
211 logCompactFinalStatus(seedersResults) {
212 const countByStatus = seedersResults.reduce((acc, value) => {
213 acc[value.status] = acc[value.status] + 1;
214 return acc;
215 }, { completed: 0, failed: 0, ignored: 0, pending: 0 });
216 let message = `❯ Executed ${countByStatus.completed} seeders`;
217 if (countByStatus.failed) {
218 message += `, ${countByStatus.failed} failed`;
219 }
220 if (countByStatus.ignored) {
221 message += `, ${countByStatus.ignored} ignored`;
222 }
223 const color = countByStatus.failed ? 'red' : 'grey';
224 this.logger.log(this.colors[color](message));
225 if (countByStatus.failed > 0) {
226 const erroredSeeder = seedersResults.find((seeder) => seeder.status === 'failed');
227 const seederName = this.colors.grey(erroredSeeder.file.name + ':');
228 const error = this.colors.red(erroredSeeder.error.message);
229 this.logger.log(`${seederName} ${error}\n`);
230 }
231 }
232 /**
233 * Run as a subcommand. Never close database connection or exit
234 * process here
235 */
236 async runAsSubCommand() {
237 const db = this.application.container.use('Adonis/Lucid/Database');
238 this.connection = this.connection || db.primaryConnectionName;
239 /**
240 * Invalid database connection
241 */
242 if (!db.manager.has(this.connection)) {
243 this.printNotAValidConnection(this.connection);
244 this.exitCode = 1;
245 return;
246 }
247 /**
248 * Cannot use --files and --interactive together
249 */
250 if (this.files && this.interactive) {
251 this.logger.warning('Cannot use "--interactive" and "--files" together. Ignoring "--interactive"');
252 }
253 await this.instantiateSeeder();
254 const files = await this.seeder.getList();
255 const cherryPickedFiles = await this.getCherryPickedFiles(files);
256 const result = await this.executedSeeders(cherryPickedFiles, files);
257 if (this.compactOutput && result) {
258 this.logCompactFinalStatus(result);
259 }
260 this.exitCode = this.hasError ? 1 : 0;
261 }
262 /**
263 * Branching out, so that if required we can implement
264 * "runAsMain" separately from "runAsSubCommand".
265 *
266 * For now, they both are the same
267 */
268 async runAsMain() {
269 await this.runAsSubCommand();
270 }
271 /**
272 * Handle command
273 */
274 async run() {
275 if (this.isMain) {
276 await this.runAsMain();
277 }
278 else {
279 await this.runAsSubCommand();
280 }
281 }
282 /**
283 * Lifecycle method invoked by ace after the "run"
284 * method.
285 */
286 async completed() {
287 if (this.seeder && this.isMain) {
288 await this.seeder.close();
289 }
290 }
291}
292Object.defineProperty(DbSeed, "commandName", {
293 enumerable: true,
294 configurable: true,
295 writable: true,
296 value: 'db:seed'
297});
298Object.defineProperty(DbSeed, "description", {
299 enumerable: true,
300 configurable: true,
301 writable: true,
302 value: 'Execute database seeders'
303});
304Object.defineProperty(DbSeed, "settings", {
305 enumerable: true,
306 configurable: true,
307 writable: true,
308 value: {
309 loadApp: true,
310 }
311});
312__decorate([
313 standalone_1.flags.string({ description: 'Define a custom database connection for the seeders', alias: 'c' }),
314 __metadata("design:type", String)
315], DbSeed.prototype, "connection", void 0);
316__decorate([
317 standalone_1.flags.boolean({ description: 'Run seeders in interactive mode', alias: 'i' }),
318 __metadata("design:type", Boolean)
319], DbSeed.prototype, "interactive", void 0);
320__decorate([
321 standalone_1.flags.array({ description: 'Define a custom set of seeders files names to run', alias: 'f' }),
322 __metadata("design:type", Array)
323], DbSeed.prototype, "files", void 0);
324__decorate([
325 standalone_1.flags.boolean({ description: 'A compact single-line output' }),
326 __metadata("design:type", Boolean)
327], DbSeed.prototype, "compactOutput", void 0);
328exports.default = DbSeed;