git kitty Hacking through NYC

muse: breaking down the pieces

This is a continuation of muse: a CMS scaffolding tool.

if at first you don't succeed, move on...

So I started to work on the code injection component of muse and came up with a solution I thought was pretty cool. Keeping in mind that depending on which options you add to the muse command the code injected into the files changes. My initial idea was to build a data object like so:

module.exports = {
  content: [
    {
      path: 'server/models/index.js',
      data: 'module.exports = {...}'
    },
    {
      path: 'server/models/User.js',
      basic: {
        data: '// basic strategy auth code'
      },
      oath: {
        data: '// oauh strategy auth code'
      },
      both: {
        data: '// both local and oauth strategies auth code'
      }
    },
    ...

After requiring my module I could then do a basic lookup by path, which is a dynamic piece of data I have access to in this scope. If the code changes based on option parameters (i.e. basic, oauth, both) I can pass those in as well and achieve a more custom definition. Now this implementation isn't perfect, but for my first shot I was happy with it.

// The data lookup method that finds the associated file code
function dataLog(path, options, callback) {
  var lib = require('../lib/data');

  _.each(lib.content, function(content){
    if(content.path === path){
      if(options){
        callback(content[options].data);
      } else {
        callback(content.data);
      }
    }
  });
}

// The write method that creates and populates the file
function write(path, options) {
  var cleanPath = path.split('./')[1];

  dataLog(cleanPath, options, function(data){
    fs.writeFile(path, data);
  });
}

Then I tried it...

I copied an existing piece of code into this object and surveyed the horror that this file would become. Yes, it worked and if the amount of code was small or there was no need for whitespace it might be the way to go. However, neither of those things are true so it's back to the drawing board. My next implementation is just going to be a basic fileRead—fileWrite solution, which means I need to optimize the file structure for ease of lookup and retrieval.

...to something else

So after the above realization I decided not to implement it. I wasn't ready. In addition to now questioning my file structure I was questioning my over application architecture. So to appease my fears I decided to build the app that muse would generate with its defaults.

Muse options and defaults:

Usage: muse [options]

  Options:

    -h, --help              output usage information
    -V, --version           output the version number
    -c, --css <engine>      add stylesheet engine support (css|sass|less) defaults to css
    -e, --view <engine>     add view engine support (dust|ejs|hbs) defaults to dust
    -p, --portal            add client portal to site where users can login
    -a, --auth <type>       choose authentication strategy (basic|oauth|both) defaults to basic
    -n, --noblog            remove blog functionality from site
    -f, --framework <name>  add client-side framework support (angular|ember) defaults to none
    -b, --backend <name>    configure server-side framework (koa|hapi|sails) defaults to express
    -d, --database <name>   configure database support (mongo|postgres) defaults to mongo

So the default application would be an express app with basic/local authentication, a css stylesheet, dust views, no client portal, no client side framework, and a mongoDB database. Now I knew what my actual MVP application would be and I was able to update my developmental task list and create the release plan below.

the new plan

Version 2.0:

  • Finalize default configuration and structure
    • Basic mongoose models and CRUD operations for Users and Pages
    • Separate view routes from API routes in preparation for client-side framework support
  • Admin functionality without permissions
    • Admin Dashboard
    • Site Management
    • Content Management
    • User Management
  • Navigation
    • Single top level page routing
    • Additional secondary level routing
  • Blog functionality
    • Basic mongoose models and CRUD operations for Blogs, and Posts
    • Single blog with multiple posts (without comments or tags)
  • Multiple engine support
    • Style: css
    • Style: sass
    • Style: less
    • View: dust
    • View: ejs
    • View: handlebars

Version 2.5:

  • Admin functionality with roles and multi-part permissions
    • Basic mongoose models and CRUD operations for Roles and Permissions
    • Content creation and editing
    • Content publication
    • Content deletion
    • User viewing
    • User creation and editing
  • Portal Option
    • Clients can login to site
  • Client User Authentication (Passport)
    • Basic user auth
    • OAuth support for Google+, Twitter, and Facebook
    • Both local and OAuth
  • Email system support (Mailgun)
    • Account creation
    • Password change
  • Blog functionality
    • Basic mongoose models and CRUD operations for Comments and Tags
    • Single blog with multiple posts (with comments and tags)

next steps

I'm going to be focusing on building out a 2.0 application and achieving an overall structure I am happy with. After that I can return to my muse.

#happyhacking