@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
JavaScript
;
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;