UNPKG

@shagital/adonisjs-crud-generator

Version:

Adonisjs Admin Panel Generator is a package that helps you quickly scaffold your typical CRUD admin interfaces. It generates the admin panel code based on the existing (migrated) table in the database

233 lines (232 loc) 11.3 kB
"use strict"; 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; }; var __metadata = (this && this.__metadata) || function (k, v) { if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v); }; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); const standalone_1 = require("@adonisjs/core/build/standalone"); const helpers_1 = require("../common/helpers"); const fs_extra_1 = __importDefault(require("fs-extra")); const util_1 = __importDefault(require("util")); const execSync = util_1.default.promisify(require('child_process').execSync); class CrudInit extends standalone_1.BaseCommand { async run() { this.Env = this.application.container.use('Adonis/Core/Env'); if (this.application.inProduction && !this.force) { const confirmAction = await this.prompt.confirm('Run command in production?'); if (!confirmAction) { return; } } let prefix = this.prefix || this.application.config.get('crudGenerator.admin_prefix'); if (prefix && (prefix.length > 20 || prefix.length < 5 || !prefix.match(/^[0-9A-Za-z]+$/))) { this.logger.error('Prefix must be an alphanumeric string between 5 and 50 characters.'); return; } else if (!prefix) { prefix = this.application.config.get('crudGenerator.admin_prefix', (0, helpers_1.random)(20)); } this.logger.debug(`Admin route will use prefix: ${prefix}`); if (!this.initializeDirectories()) { return; } Promise.all([ this.copyConfig(prefix), this.copyController(), this.copyRoute(prefix), this.copyViews(prefix), this.copyMigration(this.migrate), this.createEnv(prefix), ]).then(() => { this.logger.info('Admin Generator done with initialisation. Please run any pending migrations'); }); } initializeDirectories() { // first make sure appropriate folders exist, if not create let adminAppPath = this.application.viewsPath('admin'); let configPath = this.application.configPath(); let migrationPath = this.application.migrationsPath(); let startPath = this.application.startPath(); let controllerPath = `${this.application.appRoot}/app/Controllers/Http/Admin`; let modelPath = `${this.application.appRoot}/app/Models`; let middlewarePath = `${this.application.appRoot}/app/Middleware`; try { if (!fs_extra_1.default.existsSync(adminAppPath)) { fs_extra_1.default.mkdirSync(adminAppPath, { recursive: true }); } if (!fs_extra_1.default.existsSync(configPath)) { fs_extra_1.default.mkdirSync(configPath, { recursive: true }); } if (!fs_extra_1.default.existsSync(migrationPath)) { fs_extra_1.default.mkdirSync(migrationPath, { recursive: true }); } if (!fs_extra_1.default.existsSync(startPath)) { fs_extra_1.default.mkdirSync(startPath, { recursive: true }); } if (!fs_extra_1.default.existsSync(controllerPath)) { fs_extra_1.default.mkdirSync(controllerPath, { recursive: true }); } if (!fs_extra_1.default.existsSync(modelPath)) { fs_extra_1.default.mkdirSync(modelPath, { recursive: true }); } if (!fs_extra_1.default.existsSync(middlewarePath)) { fs_extra_1.default.mkdirSync(middlewarePath, { recursive: true }); } return true; } catch (e) { this.logger.error(`Error occured while trying to create required directories: ${e.message}`); return false; } } runMigration() { this.logger.info('Run migration'); execSync(`node ace migration:run`, (_e) => { }); } createEnv(prefix) { this.logger.info('Creating sample env files'); const baseUrl = `${this.Env.get('APP_URL', `http://${this.Env.get('HOST')}:${this.Env.get('PORT')}`)}/${prefix}`; this.logger.info(`Set vue app base URL: ${baseUrl}`); let envPath = this.application.viewsPath('admin/.env'); this.logger.debug(`Env Path: ${envPath}`); let envExamplePath = this.application.viewsPath('admin/.env.example'); this.logger.debug(`Example Env Path: ${envExamplePath}`); let data = `NODE_ENV=development VUE_APP_BASE_URI= VUE_APP_NAME= VUE_APP_I18N_LOCALE=en VUE_APP_I18N_FALLBACK_LOCALE=en `; fs_extra_1.default.appendFileSync(envExamplePath, data); data = `NODE_ENV=development VUE_APP_BASE_URI=${baseUrl} VUE_APP_NAME=${this.Env.get('APP_NAME')} VUE_APP_I18N_LOCALE=en VUE_APP_I18N_FALLBACK_LOCALE=en `; fs_extra_1.default.appendFileSync(envPath, data); } copyRoute(prefix) { this.logger.info('Copy Route'); let routeFile = this.application.startPath(`routes.ts`); let routeData = ` Route.group(() => { Route.post('login', 'Admin/ProfilesController.login').as('admin.profile.login') }).prefix('${prefix}/auth') Route.group(() => { Route.get('me', 'Admin/ProfilesController.show').as('admin.profile') Route.get('logout', 'Admin/ProfilesController.logout').as('admin.profile.logout') Route.patch('refresh', 'Admin/ProfilesController.refresh').as('admin.profile.refresh') Route.patch('update', 'Admin/ProfilesController.updateProfile').as('admin.profile.update') }) .prefix('${prefix}/auth') .middleware(['auth:api', 'is:administrator'])`; let data = String(fs_extra_1.default.readFileSync(routeFile)); let append = ''; // check if routes have been appended before if (!data.includes(routeData)) { append += `${routeData}\n`; } fs_extra_1.default.appendFileSync(routeFile, append); } copyMigration(migrate) { this.logger.info('Copy migration'); let password = (0, helpers_1.random)(); let migrationFile = `${__dirname}/../templates/default/migrations/admin_default_role_permission.txt`; let destinationFile = this.application.migrationsPath(`admin_default_role_permission.ts`); let data = String(fs_extra_1.default.readFileSync(migrationFile)); if (fs_extra_1.default.existsSync(destinationFile)) { this.logger.debug(`Migration ${destinationFile} already exists. Won't be modified.`); return; } let adminUserModelNamespace = this.application.config.get('CrudGenerator.admin_user', 'App/Models/User'); let modelName = String((0, helpers_1.resolveModelName)(adminUserModelNamespace)); data = data .replace('{{password}}', `'${password}'`) .replace('{{modelNamespace}}', adminUserModelNamespace) .replace('{{userModel}}', modelName) .replace('{{userModelNamespace}}', adminUserModelNamespace); data = (0, helpers_1.replaceAll)(data, '{{model}}', modelName); fs_extra_1.default.writeFileSync(destinationFile, data); this.logger.debug(`Password: ${password}`); if (migrate) this.runMigration(); } copyConfig(prefix) { this.logger.info('Copy config'); let configPath = this.application.configPath(`crudGenerator.ts`); fs_extra_1.default.copyFileSync(`${__dirname}/../config/crudGenerator.txt`, configPath); let data = String(fs_extra_1.default.readFileSync(configPath)); let host = (0, helpers_1.resolveUrl)(this.Env.get('APP_URL', this.Env.get('HOST')), 'host'); let adminEmail = host && (0, helpers_1.validEmail)(`admin@${host}`) ? `admin@${host}` : 'administrator@webmail.com'; data = data.replace('{{adminPrefix}}', prefix).replace('{{adminEmail}}', adminEmail); fs_extra_1.default.writeFileSync(configPath, data); } copyController() { this.logger.info('Copy Controller'); let sourcePath = `${__dirname}/../templates/default/controller/ProfilesController.txt`; let destinationPath = `${this.application.appRoot}/app/Controllers/Http/Admin/ProfilesController.ts`; let data = String(fs_extra_1.default.readFileSync(sourcePath)); let adminUserModelNamespace = this.application.config.get('CrudGenerator.admin_user', 'App/Models/User'); let modelName = adminUserModelNamespace.split('/').pop(); data = data.replace('{{modelNamespace}}', adminUserModelNamespace); data = (0, helpers_1.replaceAll)(data, '{{model}}', modelName); fs_extra_1.default.writeFileSync(destinationPath, data); } async copyViews(prefix) { this.logger.info('Copy views'); fs_extra_1.default.copySync(`${__dirname}/../templates/default/views`, this.application.viewsPath('admin')); const baseUrl = `${this.Env.get('APP_URL', `${this.Env.get('HOST')}:${this.Env.get('PORT')}`)}/${prefix}`; this.logger.info(`Set Vue app API baseURL: ${baseUrl}`); let paths = [ this.application.viewsPath('admin/src/main.js'), this.application.viewsPath('admin/src/store/global/actions.js'), ]; for (let path of paths) { let data = String(fs_extra_1.default.readFileSync(path)); data = data.replace('{{baseUrl}}', baseUrl).replace('{{appName}}', this.Env.get('APP_NAME')); fs_extra_1.default.writeFileSync(path, data); } } } /** * Command name is used to run the command */ CrudInit.commandName = 'crud:init'; /** * Command description is displayed in the "help" output */ CrudInit.description = 'Publish admin configs'; CrudInit.settings = { /** * Set the following value to true, if you want to load the application * before running the command */ loadApp: true, /** * Set the following value to true, if you want this command to keep running until * you manually decide to exit the process */ stayAlive: false, }; __decorate([ standalone_1.flags.string({ description: 'Define a custom admin route prefix' }), __metadata("design:type", String) ], CrudInit.prototype, "prefix", void 0); __decorate([ standalone_1.flags.boolean({ description: 'Automatically run newly created migration' }), __metadata("design:type", Boolean) ], CrudInit.prototype, "migrate", void 0); __decorate([ standalone_1.flags.boolean({ description: 'Force run command in production' }), __metadata("design:type", Boolean) ], CrudInit.prototype, "force", void 0); exports.default = CrudInit;