slush-regenerator
Version:
A slush generator for many website things (Optimized for Laravel 5.2)
424 lines (368 loc) • 15.6 kB
JavaScript
var gulp = require('gulp'),
gutil = require('gulp-util'),
cheerio = require('gulp-cheerio'),
rm = require('gulp-rm'),
changeCase = require('change-case'),
pluralize = require('pluralize'),
jsonpatch = require('jsonpatch'),
walk = require('tree-walk'),
kvp = require('key-value-pointer'),
_ = require('underscore'),
CountryLanguage = require('country-language'),
mc = require('memory-cache');
// CLI UI
var Table = require('cli-table');
// Building options
var framework = 'Laravel';
if (framework == 'Laravel')
{
var command = require('./../plugins/laravel/app/Console/Commands/command'),
config = require('./../plugins/laravel/config/config'),
controller = require('./../plugins/laravel/app/Http/Controllers/controller'),
handler = require('./../plugins/laravel/app/Exceptions/handler'),
migration = require('./../plugins/laravel/database/migrations/migration'),
model = require('./../plugins/laravel/app/model'),
policy = require('./../plugins/laravel/app/Policies/policy'),
provider = require('./../plugins/laravel/app/Providers/provider'),
request = require('./../plugins/laravel/app/Http/Requests/request'),
routes = require('./../plugins/laravel/app/Http/routes'),
seeder = require('./../plugins/laravel/database/seeds/seeder'),
view = require('./../plugins/laravel/resources/views/crudl');
}
var schema =
{
cwd: null,
list_of_things: [],
unorganized_things: [],
organized_things: [],
counters: {
migrations: 0,
models: 0,
},
settings:
{
traditional_logging: false, // Logging via commandline text output (no fancy UI)
},
// Datatypes native to schemaorg
native_data_types: ['BooleanDate', 'DateTime', 'Number', 'Text', 'Time'],
/* Convert a KVP match to a JSONpatch */
convert_match_to_patch: function(thing_match, parent_match)
{
var thing_path = thing_match.pointer,
thing_path = thing_path.replace('/class_name', '');
var parent_path = parent_match.pointer,
parent_path = parent_path.replace('class_name', 'nested_classes/');
// TODO: Use replace instead of copy and remove once JSONpatch library is fixed
// var json_patch = [{ "op": "move", "from": thing_path, "path": parent_path }];
schema.organized_things = jsonpatch.apply_patch(schema.organized_things, [{ "op": "copy", "from": thing_path, "path": parent_path }]);
var json_patch = [{ "op": "remove", "path": thing_path }];
return json_patch;
},
/* Organize a thing */
organize_thing: function(thing)
{
var class_name = thing['class_name'],
sub_class = thing['sub_class'];
if (sub_class != null)
{
var thing_match = false,
parent_match = false;
var thing_match_found = kvp(schema.organized_things).query(function (node) {
if (node.key == 'class_name' && node.value == class_name) {
thing_match = node;
return true;
}
});
var parent_match_found = kvp(schema.organized_things).query(function (node) {
if (node.key == 'class_name' && node.value == sub_class) {
parent_match = node;
return true;
}
});
thing_match_found = (typeof thing_match_found == 'string');
parent_match_found = (typeof parent_match_found == 'string');
if (thing_match_found && parent_match_found)
{
// Overview
var msg = gutil.colors.magenta(thing['class_name'])
+ gutil.colors.yellow(' has now been added to organized tree,');
gutil.log(msg);
gutil.log( gutil.colors.yellow('it contains the following fields: ') );
// Show fields as table
var table = new Table({
chars: {
'top': '═' , 'top-mid': '╤' , 'top-left': '╔' , 'top-right': '╗'
, 'bottom': '═' , 'bottom-mid': '╧' , 'bottom-left': '╚' , 'bottom-right': '╝'
, 'left': '║' , 'left-mid': '╟' , 'mid': '─' , 'mid-mid': '┼'
, 'right': '║' , 'right-mid': '╢' , 'middle': '│'
},
head: ['Field', 'Data type']
});
var properties = thing['properties'];
for (property in properties)
{
table.push([changeCase.snakeCase(property), properties[property]]);
}
// Alternative fields as list
var fields = Object.keys(thing['properties']);
fields = fields.map( function(key, value)
{
return changeCase.snakeCase(value);
});
var field_list = fields.join(', ');
if (field_list != '')
{
gutil.log( gutil.colors.green(thing['class_name'] + ' (migration)') );
try
{
console.log( table.toString() );
}
catch (e)
{
console.log(field_list);
}
}
else
{
gutil.log( gutil.colors.red('No fields! (could be an issue)') );
}
// Fit into place according to hierachy
json_patch = schema.convert_match_to_patch(thing_match, parent_match);
try
{
schema.organized_things = jsonpatch.apply_patch(schema.organized_things, json_patch);
}
catch (PatchApplyError)
{
throw new Error(PatchApplyError);
}
}
else
{
// This is an issue with schemaorg inconsistancy, may be worth doing guess work here
// e.g OrganizationPlace isn't a thing but Place is >:/
gutil.log( gutil.colors.red('Parent class does not exist ' + thing['sub_class'] + ' this is an issue with schemaorg') );
}
}
},
/* Make a schema */
make_schema: function(thing, answers)
{
var make_command = (answers.components.indexOf('Command') != -1),
make_controller = (answers.components.indexOf('Controller') != -1),
make_migration = (answers.components.indexOf('Migration') != -1),
make_model = (answers.components.indexOf('Model') != -1),
make_policy = (answers.components.indexOf('Policy') != -1),
make_request = (answers.components.indexOf('Request') != -1),
make_views = (answers.components.indexOf('View') != -1);
var table_name = changeCase.snakeCase( thing['class_name'] ),
parent_table_name = changeCase.snakeCase( thing['sub_class'] );
if (schema.traditional_logging)
{
var msg = 'Creating migration for ' + thing['class_name'] + ' Thing, table name will be called `' + table_name + '`.';
msg += ' Now determining field names and types';
gutil.log( gutil.colors.magenta(msg) );
}
// Check which fields are native datatypes (according to laravel)
var properties = thing['properties'],
parent_class = thing['sub_class'],
show_field_handling = false;
// Avoid creating certain files when no fields exist
if (!Object.keys(properties).length)
{
make_command = false,
make_controller = false,
make_migration = false,
make_policy = false,
make_request = false,
make_views = false;
gutil.log( gutil.colors.red(thing['class_name'] + ' has no properties, this could be an issue with the schema or the application') );
}
// Migrations
var database_field_handling = migration.database_field_handling(schema.cwd, table_name, parent_table_name, properties, show_field_handling, make_migration, schema.list_of_things, answers.locales),
table_fields = database_field_handling['valid_fields'],
foreign_keys = database_field_handling['foreign_keys'];
// Update foreign keys
for (foreign_key of foreign_keys)
{
if (migration.foreign_keys.indexOf(foreign_key) == -1)
{
migration.foreign_keys.push(foreign_key);
}
}
// Views
var form_field_handling = view.form_field_handling(table_name, parent_table_name, properties, show_field_handling, schema.list_of_things),
form_fields = form_field_handling['valid_fields'];
form_fields = form_fields.concat(form_field_handling['natural_language_fields']);
var mandatory_fields = [];
mandatory_fields.push( migration.dbf('id', 'bigIncrements', 'ID') );
if (parent_class != null)
{
var parent_column = migration.dbf(changeCase.snakeCase(parent_class) + '_id', 'bigInteger', parent_class + ' ID', pluralize( changeCase.snakeCase(parent_class) ));
mandatory_fields.push(parent_column);
}
table_fields = mandatory_fields.concat(table_fields);
var controller_name = changeCase.pascalCase(table_name) + 'Controller',
model_name = changeCase.pascalCase(table_name),
model_instance_name = '$' + changeCase.snakeCase(table_name),
policy_name = changeCase.pascalCase(table_name) + 'Policy',
request_name = changeCase.pascalCase(table_name) + 'Request';
/* Go forth and make things */
// Controllers
if (make_controller)
{
if (parent_table_name != '' && schema.native_data_types.indexOf( changeCase.ucFirst(parent_table_name) ) == -1)
{
parent_controller_name = changeCase.pascalCase(parent_table_name) + 'Controller';
}
else
{
parent_controller_name = 'BaseController';
}
schema.make_controller(controller_name, parent_controller_name, model_name, request_name, answers.theme);
}
// Migrations
if (make_migration && !(migration.problematic_tables.indexOf( pluralize(table_name) ) > -1))
{
schema.make_migration(pluralize(table_name), table_fields);
}
// Models
if (make_model && !(model.problematic_models.indexOf(model_name) > -1))
{
schema.make_model(model_name, changeCase.pascalCase(parent_table_name), table_fields, answers.df);
}
// Policies
if (make_policy)
{
schema.make_policy(policy_name, model_name, model_instance_name);
}
// Requests
if (make_request)
{
schema.make_request(request_name, model_name);
}
// Views
if (make_views)
{
schema.make_views(changeCase.pascalCase(table_name), changeCase.pascalCase(parent_table_name), form_fields, answers);
}
},
/* Make all migrations stored in cache */
make_migrations: function() {
// Create table migrations
for (table_name of migration.tables) {
var db_fields = mc.get(table_name);
if (db_fields != null) {
console.log(table_name, 'being created');
migration.create_table(schema.cwd, table_name, db_fields);
}
else {
throw new Error('Cache not set for following table: ' + table_name);
}
}
// Create migrations for foreign keys
var processed_foreign_keys = [];
for (foreign_key of migration.foreign_keys)
{
var table_name = foreign_key,
db_fields = mc.get(table_name);
if (db_fields != null && !(processed_foreign_keys.indexOf(table_name) > -1))
{
console.log(table_name, 'being modified');
migration.add_foreign_keys(schema.cwd, table_name, db_fields);
}
else
{
// TODO: Ignore for now (can be looked at once schema is up to date)
}
}
},
/* Write command */
make_command: function(command_name, signature, description, model_name)
{
command.create(schema.cwd, command_name, signature, description, model_name);
},
/* Make config files */
make_configs: function()
{
config.copy_base_files(schema.cwd);
},
/* Write controller */
make_controller: function(controller_name, parent_controller_name, model_name, request_name, layout)
{
controller.copy_base_files(schema.cwd);
controller.create(schema.cwd, controller_name, parent_controller_name, model_name, request_name, layout);
},
/* Make handlers */
make_handlers: function()
{
// TODO: Choose handlers as question
var handlers = [
{
exception: 'NotFoundHttpException',
statusCode: '404',
pageTitle: '404 Page Not Found',
viewFile: 'errors.404'
}
];
handler.copy_base_files(schema.cwd, handlers);
},
/* Write kernel */
make_kernel: function(commands)
{
command.copy_base_files(schema.cwd, commands);
},
/* Store migration in cache for later use */
make_migration: function(table_name, database_fields)
{
migration.cache(table_name, database_fields);
},
/* Write model */
make_model: function(model_name, parent_model_name, field_names, df)
{
model.copy_base_files(schema.cwd);
// Avoid native datatype being declared as models
if (schema.native_data_types.indexOf(parent_model_name) > -1)
{
parent_model_name = 'Model';
}
model.create(schema.cwd, model_name, parent_model_name, field_names, df);
},
/* Write policy */
make_policy: function(policy_name, model_name, model_instance_name)
{
policy.create(schema.cwd, policy_name, model_name, model_instance_name);
},
/* Write request */
make_request: function(request_name, model_name)
{
request.create(schema.cwd, request_name, model_name);
},
/* Write routes */
make_routes: function(resources)
{
routes.copy_base_files(schema.list_of_things);
routes.create(schema.cwd, resources);
},
/* Write seeds */
make_seed_runner: function(seeder_classes, super_admin)
{
seeder.copy_base_files(schema.cwd, seeder_classes, super_admin);
},
make_seed: function(seeder_class, resource)
{
seeder.create(schema.cwd, seeder_class, resource);
},
/* Write providers */
make_providers: function(policies)
{
provider.create_auth_provider(schema.cwd, policies);
},
/* Write views */
make_views: function(context_name, parent_context_name, form_fields, answers)
{
view.copy_base_files(schema.cwd, answers.theme);
view.create(schema.cwd, context_name, parent_context_name, form_fields, answers.df);
}
};
module.exports = schema;