UNPKG

@adonisjs/lucid

Version:

SQL ORM built on top of Active Record pattern

142 lines (141 loc) 5.4 kB
/* * @adonisjs/lucid * * (c) Harminder Virk <virk@adonisjs.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) { var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d; if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc); 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; return c > 3 && r && Object.defineProperty(target, key, r), r; }; import { BaseCommand, flags } from '@adonisjs/core/ace'; import { isAbsolute } from 'node:path'; export default class SchemaGenerate extends BaseCommand { static commandName = 'schema:generate'; static description = 'Generate schema classes for all the tables in your database'; static options = { startApp: true, }; /** * Not a valid connection */ printNotAValidConnection(connection) { this.logger.error(`"${connection}" is not a valid connection name. Double check "config/database" file`); } /** * Returns beautified log message string */ printLogMessage(message) { const arrow = this.colors.gray('❯'); this.logger.logUpdate(`${arrow} ${message}`); } /** * Run as a subcommand. Never close database connection or exit * process here */ async runAsSubCommand() { const db = await this.app.container.make('lucid.db'); this.connection = this.connection || db.primaryConnectionName; /** * Invalid database connection */ const managerConnection = db.manager.get(this.connection); if (!managerConnection) { this.printNotAValidConnection(this.connection); this.exitCode = 1; return; } /** * Check if schema generation is disabled */ if (managerConnection.config.schemaGeneration?.enabled === false) { this.logger.info('Schema generation is disabled'); return; } const outputPath = managerConnection.config.schemaGeneration?.outputPath ?? './database/schema.ts'; let schemas = ['public']; const migrationsTableName = managerConnection.config.migrations?.tableName ?? 'adonis_schema'; const migrationsVersionsTableName = `${migrationsTableName}_versions`; if ('searchPath' in managerConnection.config && managerConnection.config.searchPath) { schemas = managerConnection.config.searchPath; } /** * Initiate schema generator */ const { OrmSchemaGenerator } = await import('../src/orm/schema_generator/generator.js'); this.generator = new OrmSchemaGenerator(db, this.app, { connectionName: this.connection, schemas, ...managerConnection.config.schemaGeneration, excludeTables: [migrationsTableName, migrationsVersionsTableName], outputPath: isAbsolute(outputPath) ? outputPath : this.app.makePath(outputPath), }); /** * Listen for progression events when compactOutput is not * enabled */ if (!this.compactOutput) { this.generator.on('collect:tables', (tables) => { this.printLogMessage(`Scanned "${this.connection}" database and found ${tables.length} tables`); }); this.generator.on('table:info', ({ tableName }) => { this.printLogMessage(`Scanned table ${tableName}`); }); this.generator.on('generating:schema', () => { this.printLogMessage('Creating schema classes for scanned tables'); }); } try { const start = process.hrtime(); await this.generator.generate(); if (this.compactOutput) { this.logger.logUpdatePersist(); } this.logger.success('Schema classes generated', { startTime: start }); } catch (error) { this.logger.error('Unable to generate schema classes'); this.error = error; this.exitCode = 1; } } /** * Branching out, so that if required we can implement * "runAsMain" separately from "runAsSubCommand". * * For now, they both are the same */ async runAsMain() { await this.runAsSubCommand(); } /** * Handle command */ async run() { if (this.isMain) { await this.runAsMain(); } else { await this.runAsSubCommand(); } } /** * Lifecycle method invoked by ace after the "run" * method. */ async completed() { if (this.generator && this.isMain) { await this.generator.close(); } } } __decorate([ flags.string({ description: 'Define a custom database connection', alias: 'c' }) ], SchemaGenerate.prototype, "connection", void 0); __decorate([ flags.boolean({ description: 'A compact single-line output' }) ], SchemaGenerate.prototype, "compactOutput", void 0);