Command Line Interface (CLI)

In Apogeu, all commands have the syntax with apogeu command

Example:

$ apogeu new my-project

Display the command options with the -h option:

$ apogeu -h

Commands:
 start                                                                 Start project
 new [project_name]                                                    New project
 create  [all|middleware|controller|service|model]   Create model structure
 test [test_type] [all|unit|integration]                               Run project tests

Options:
 --version, -v  Show version number  [boolean]
 --help, -h     Show help  [boolean]

Available Commands
  • apogeu start

    This command starts your application

    You can simply run:

    $ apogeu start
    
    info: Mongoose default connection open to mongodb://localhost:27017/apogeu
    info: Mongoose default connection is open
    info: Application listening on port 3000
  • apogeu new

    For you to create a new application:

    $ apogeu new my-project
    
    info: my-project app created

    Or for you to create in the current folder

    $ apogeu new
  • apogeu create

    To create a model, service, controller or middleware, the apogeu create command is used.

    $ apogeu create model user
    
    info: User structure created

    You can also create all structures using apogeu create all name

    $ apogeu create all user
    
    info: User structure created
  • apogeu test

    To run the unit and/or integration tests, use the command apogeu test

    $ apogeu test unit
    
    info: running unit tests
    
     ✓ user service is an object
    
     1 passing (7ms)

    You can also create all tests using apogeu test all

    $ apogeu test all
    
    info: Mongoose default connection open to mongodb://localhost:27017/apogeu
    info: Mongoose default connection is open
    info: running unit tests
    
     ✓ user service is an object
    
     1 passing (15ms)
    
    info: running integration tests
    info: Application listening on port 3000
    
    Mongoose: users.find({}, { limit: undefined, skip: undefined, fields: {} })
     ✓ list users (438ms)
    
     1 passing (443ms)
  • apogeu --debug

    Use the --debug option to display the entire process of some command.

    Example with the new command:

    $ apogeu new my-project --debug
    
    apogeu:apogeu init apogeu +0ms
    apogeu:debug global.Promise = require("bluebird") +204ms
    apogeu:new project name: my-project +3s
    apogeu:createDir my-project +14ms
    apogeu:download downloading sources +45ms
    apogeu:createDir my-project/app/assets/images +2s
    apogeu:createDir my-project/app/assets/javascripts +19ms
    apogeu:createDir my-project/app/assets/stylesheets +3ms
    apogeu:createDir my-project/app/controllers +4ms
    apogeu:createDir my-project/app/i18n +7ms
    apogeu:createDir my-project/app/middlewares +2ms
    apogeu:createDir my-project/app/models +2ms
    apogeu:createDir my-project/app/services +3ms
    apogeu:createDir my-project/app/views +4ms
    apogeu:createDir my-project/config +6ms
    apogeu:createDir my-project/config/scaffold +91ms
    apogeu:createDir my-project/public/stylesheets +11ms
    apogeu:createDir my-project/test/integration +3ms
    apogeu:createDir my-project/test/unit +1ms
    apogeu:createPackage creating package file +272ms
    apogeu:installDependencies installing app dependencies +3ms
    apogeu:createDir my-project/node_modules +0ms
    apogeu:installDependencies dependencies installed +1m
    info: my-project app created

Models

A model module fulfills the M in the Model View Controller (MVC) pattern and represents a persistent entity that is mapped onto an underlying database. In Apogeu a model is a module with a plural name convention and lives in the app/models directory.

Models don't need to be required, just use UserModel wherever you want.

A model can be created with the apogeu model model_name command:

$ apogeu create model user

Create the app/models/user.js module

const mongoose = require('mongoose');
const Schema = mongoose.Schema;
const UserModel = new Schema({
});
module.exports = mongoose.model('User', UserModel);

Services

A service contains business logic that can be reused across a Apogeu application. In Apogeu, a service is a module with a plural name that ends in the "Service" convention and lives in the app/services directory.

Services don't need to be required, just use UsersService wherever you want.

A service can be created with the apogeu create service model_name command:

$ apogeu create service user

Create the app/services/users.js module

const UsersService = {
};
module.exports = UsersService;

Controllers

A controller fulfills the C in the Model View Controller (MVC) pattern and is responsible for handling web requests. In Apogeu, a service is a module with a plural name that ends in the "Controller" convention and lives in the app/controllers directory.

Controllers don't need to be required, just use UsersController wherever you want.

A controller can be created with the apogeu create controller model_name command:

$ apogeu create controller user

Create the app/controllers/users.js module

const UsersController = {
};
module.exports = UsersController;

Middlewares

Middleware functions are functions that have access to the request object (req), the response object (res), and the next function in the application’s request-response cycle. In Apogeu, a service is a module with a singular name that ends in the "Middleware" convention and lives in the app/middlewares directory.

Middlewares don't need to be required, just use LogMiddleware wherever you want.

A middleware can be created with the apogeu create middleware log command:

$ apogeu create middleware log

Create the app/middlewares/log.js module

const LogMiddleware = (req, res, next) => {
  next();
};
module.exports = LogMiddleware;

Routes

Routing refers to the definition of application end points (URIs) and how they respond to client requests.

In Apogeu, a route is a module that lives in the config/routes.js.

// config/routes.js

module.exports = {
  'get /': HomepagesController.index,

  'get /middleware': [LogMiddleware, HomepagesController.index],

  '/users': [
    {
      method: 'get',
      middlewares: [LogMiddleware],
      controller: UsersController.list,
    },
    {
      method: 'post',
      controller: UsersController.create,
    },
  ],

  '/users/:id': [
    {
      method: 'get',
      controller: UsersController.findById,
    },
    {
      method: 'put',
      controller: UsersController.update,
    },
    {
      method: 'delete',
      controller: UsersController.delete,
    },
  ],

};

Views

For the views we use the Pug template engine.

You can learn more about it in: https://pugjs.org

In Apogeu, the views that lives in the app/views.

Scaffold

Scaffolding allows you to generate some basic interfaces. In Apogeu, scaffold lives in the config/scaffold directory.

  • config/scaffold/controller

    A controller is used with the apogeu create controller model_name command:

    $ apogeu create controller user

    The scaffold will create the app/controllers/users.js based on the next module:

    const {{model}}Controller = {
    
      index: (req, res) => {
        res.send('{{model}}Controller');
      },
    
    };
    
    module.exports = {{model}}Controller;
  • config/scaffold/controllerCrud

    A controllerCrud is used with the apogeu create controller model_name --crud command:

    $ apogeu create controller user --crud

    The scaffold will create the app/controllers/users.js based on the next module:

    const {{model}}Controller = {
    
      list: (req, res, next) => {
        {{model}}Service
          .list(req.query)
          .then(data => res.status(200).json({ success: true, data }))
          .catch(next);
      },
    
      create: (req, res, next) => {
        {{model}}Service
          .create(req.body)
          .then(data => res.status(200).json({ success: true, data }))
          .catch(next);
      },
    
      findById: (req, res, next) => {
        {{model}}Service
          .findById(req.params.id)
          .then(data => res.status(200).json({ success: true, data }))
          .catch(next);
      },
    
      update: (req, res, next) => {
        {{model}}Service
          .update(req.params.id, req.body)
          .then(data => res.status(200).json({ success: true, data }))
          .catch(next);
      },
    
      delete: (req, res, next) => {
        {{model}}Service
          .delete(req.params.id)
          .then(() => res.status(200).json({ success: true }))
          .catch(next);
      },
    
    };
    
    module.exports = {{model}}Controller;
  • config/scaffold/middleware

    A middleware is used with the apogeu create middleware model_name command:

    $ apogeu create middleware log

    The scaffold will create the app/middlewares/log.js based on the next module:

    const {{model}}Middleware = (req, res, next) => {
      next();
    };
    
    module.exports = {{model}}Middleware;
  • config/scaffold/model

    A model is used with the apogeu create model model_name command:

    $ apogeu create model user

    The scaffold will create the app/models/user.js based on the next module:

    const mongoose = require('mongoose');
    
    const Schema = mongoose.Schema;
    
    const {{model}}Model = new Schema({
    
    });
    
    module.exports = mongoose.model('{{model}}', {{model}}Model);
  • config/scaffold/service

    A service is used with the apogeu create service model_name command:

    $ apogeu create service user

    The scaffold will create the app/services/users.js based on the next module:

    const {{model}}Service = {
    
      index: () => new Promise((resolve, reject) => {
      }),
    
    };
    
    module.exports = {{model}}Service;
  • config/scaffold/serviceCrud

    A serviceCrud is used with the apogeu create service model_name --crud command:

    $ apogeu create service user --crud

    The scaffold will create the app/services/users.js based on the next module:

    const {{model}}Service = {
    
      list: (query = {}) => {
        const { limit, skip, sort } = query;
        return {{model}}Model
          .find({})
          .limit(limit)
          .skip(skip)
          .sort(sort);
      },
    
      create: (body = {}) => {
        const model = new {{model}}Model(body);
        return model.save();
      },
    
      findById: (_id) => new Promise((resolve, reject) => {
        {{model}}Model
          .findOne({ _id })
          .then((data) => {
            if (!data) return reject({ success: false, message: 'Not found', status: 404 });
            resolve(data);
          })
          .catch(reject);
      }),
    
      update: (_id, body) => new Promise((resolve, reject) => {
        {{model}}Service.findById(_id)
          .then((user) => {
            Object.assign(user, body);
            user.save().then(resolve).catch(reject);
          })
          .catch(reject);
      }),
    
      delete: _id => new Promise((resolve, reject) => {
        {{model}}Service.findById(_id)
          .then((user) => {
            user.remove().then(resolve).catch(reject);
          })
          .catch(reject);
      }),
    
    };
    
    module.exports = {{model}}Service;

Tests

There are distinct structures for unit tests and integration tests.

.js files inside test/unit folder are taken as unit tests, so they only have access to the app's structure.

.js files inside test/integration folder are taken as integration tests, so the app is started before run the tests.

Currently only mocha tests are comprehended by Apogeu.

const assert = require('assert');

it('list users', (done) => {
  UsersService.list({ limit: 1 })
    .then((results) => {
      assert.equal(results.length, 1);
      done();
    });
});