This is a boilerplate application that provides a ready-to-use implementation of the MEAN (MongoDB/MySQL, Express, Angular, Node) stack according to the MVC (model-view-controller) design pattern. It includes a standard controllers for a web-based interface and for a RESTful API interface.
This app has been built as part of my participation in the course Web Technology (2ID60) at Eindhoven University of Technology. It is intended as a working example to give you a kick start when developing your own application. You can freely use this code, modify and redistribute it to your own needs. Be aware that delivering this app without your own models, views and controllers may result in plagiarism litigations.
Make sure the following dependencies have been installed on the target machine and are accessible from the project folder. All the Node.js specific dependencies are defined by package.json
and don't require separate installation.
- Node.js
- NPM (node package manager)
- Database server (e.g. MongoDB or MySQL)
- Nodemon (optional)
- Pull this project from GitHub.
- Run
npm install
in the project directory. - Create a MySQL database and add the credentials in JSON format to
configs/db.json
. - Run
node mysql.install.js
(file is not yet included, so don't bother trying). - Run
nodemon bin/www
from the project directory. - By default the app runs locally on port 3000. Go to
http://localhost:3000
in your web browser. Replacelocalhost
with the IP address of your server, if the app has been installed remotely. - Enjoy :).
A custom routing schema has been implemented in router.js
to support autodiscovery of valid routes. Typically, a route has the structure /<directories>/<controller>/<action>/<params>
. It takes the request path and splits it. Next, the following logic is applied:
- Shift the first element from
req.path
and test if a directory with this value exists inapp.locals.paths.controllers
(this is the base directory for the controllers). - If
true
, add the value toreq.directory
, apply step 1 with the next element inreq.path
. - If
false
, continue to step 2. - Shift the first element from
req.path
and add the value toreq.controller
. Ifundefined
, default toindex
. - Shift the first element from
req.path
and add the value toreq.action
. Ifundefined
, default toindex
. - Add the remaining elements from
path
toreq.params
. - Determine if the request method is an allowed verb for this action. Search for a value in
app.locals.verbs
in the following order: - Take the value of the complete route as identified by the key
<req.directory>/<req.controller>/<req.action>
, if not defined, - Take the value of the action as identified by the key
<req.action>
, if not defined, - Take the default value as identified by the key
_default
. - Run the controller in
app.locals.paths.controllers + '/' + req.directory + '/' + req.controller.CamelCase() + 'Controller'
with actionreq.action.camelCase() + 'Action'
. The controller is an object and must be an instance ofBaseController
. The controller object must contain the method with the name of the action (e.g.indexAction: function() {}
). Throw a 404 error if the controller or action do not exist.
Based on the HTTP request GET http://localhost:3000/api/eu261/eligible-route/kl/ams/svo
.
These variables will be available in the Controller class.
req.directory = 'api'; // The directory ./controllers/api exists and will be used
req.controller = 'Eu261'; // Controller value after CamelCase() has been applied
req.action = 'eligibleRoute'; // Action value after camelCase() has been applied
req.route = 'api/Eu261/eligibleRoute';
req.params = ['kl', 'ams', 'svo'];
The following controller file and action are parsed. As you can see, the router will add Controller
to the value in req.controller
and Action
to the value in req.action
.
- Controller file:
./controllers/api/Eu261Controller.js
- Action:
eligibleRouteAction()
A controller file has the following structure. Replace BaseController
with any controller name in the controller/_abstract
directory. This directory is automatically included during the bootstrap in app.js
, so there is no need to explicitly require it in the controller.
module.exports = BaseController.extend({
indexAction: function(next) {
next();
}
});
You can perform all (S)CRUD operations on the following URI’s via HTTP. <root>
must be replaced by the base URI of the application (typically the domain name).
<column>
can take the valuesname
,id
,alpha2
oralpha3
<query>
is a string with the search value- Returns an array of countries that match the criteria
<id>
is a string with the ISO 3166-1 ID code- Returns an object with the inserted data on success.
- Accepts these PUT/POST parameters.
id
(Required, Unique, Integer (4), ISO 3166-1 ID code)alpha2
(Required, Unique, CHAR(2), ISO 3166-1 Alpha 2 code)alpha3
(Required, Unique, CHAR(3) ISO 3166-1 Alpha 3 code)name
(Required, Unique, Varchar(64) UNGEGN Country name)alt_name
(Optional, Unique or NULL, Varchar(64) name as most commonly used)- Returns an object with the inserted data on success.
<id>
is a string with the ISO 3166-1 ID code- Accepts these PUT/PATCH parameters.
alpha2
Required, Unique, CHAR(2), ISO 3166-1 Alpha 2 code)alpha3
(Required, Unique, CHAR(3) ISO 3166-1 Alpha 3 code)name
(Required, Unique, Varchar(64) UNGEGN Country name)alt_name
(Optional, Unique or NULL, Varchar(64) name as most commonly used)- Returns an object with the inserted data on success.
<id>
is a string with the ISO 3166-1 ID code- Returns status code 200 on success.