Git does not track empty directory. In order to track a directory, a file must exist within it. The trick that many people use is to create a hidden file usually called .gitkeep. The name of the file does not matter. As long as there is a file in the directory .gitkeep, readme.txt etc, git will track directory.
One of the main directories. Here you will find all the development structures of your application.
Directory where all assets files are located.
Directory where all images are located.
Directory where all JavaScript files are located.
Directory where all Stylus files are located.
Stylus file example.
body
padding 50px
font 14px "Lucida Grande", Helvetica, Arial, sans-serif
a
color #00B7FF
Directory where all controllers files are located.
Controller file example rendering a view.
See more at hereconst HomepagesController = {
index: (req, res) => {
res.render('index', { title: 'Apogeu' });
},
};
module.exports = HomepagesController;
Controller file example CRUD api.
See more at hereconst UsersController = {
list: (req, res, next) => {
UsersService
.list(req.query)
.then(data => res.status(200).json({ success: true, data }))
.catch(next);
},
create: (req, res, next) => {
UsersService
.create(req.body)
.then(data => res.status(200).json({ success: true, data }))
.catch(next);
},
findById: (req, res, next) => {
UsersService
.findById(req.params.id)
.then(data => res.status(200).json({ success: true, data }))
.catch(next);
},
update: (req, res, next) => {
UsersService
.update(req.params.id, req.body)
.then(data => res.status(200).json({ success: true, data }))
.catch(next);
},
delete: (req, res, next) => {
UsersService
.delete(req.params.id)
.then(() => res.status(200).json({ success: true }))
.catch(next);
},
};
module.exports = UsersController;
Directory where all translation files are located.
Translation file example.
See more at here{
"title": "Apogeu",
"welcome": "Welcome to Apogeu"
}
Directory where all middlewares files are located.
Middleware file example.
See more at hereconst log = require('winston');
const LogMiddleware = (req, res, next) => {
log.debug('log middleware');
next();
};
module.exports = LogMiddleware;
Directory where all models files are located.
Model file example.
See more at hereconst mongoose = require('mongoose');
const Schema = mongoose.Schema;
const UserModel = new Schema({
name: {
type: String,
required: true,
},
});
module.exports = mongoose.model('User', UserModel);
Directory where all services files are located.
Service file example CRUD.
See more at hereconst UsersService = {
list: (query = {}) => {
const { limit, skip, sort } = query;
return UserModel
.find({})
.limit(limit)
.skip(skip)
.sort(sort);
},
create: (body = {}) => {
const model = new UserModel(body);
return model.save();
},
findById: _id => new Promise((resolve, reject) => {
UserModel
.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) => {
UsersService.findById(_id)
.then((user) => {
Object.assign(user, body);
user.save().then(resolve).catch(reject);
})
.catch(reject);
}),
delete: _id => new Promise((resolve, reject) => {
UsersService.findById(_id)
.then((user) => {
user.remove().then(resolve).catch(reject);
})
.catch(reject);
}),
};
module.exports = UsersService;
Directory where all views (pug) files are located.
Error page example.
See more at hereextends layout
block content
h1= message
h2= error.status
pre #{error.stack}
Index page example.
See more at hereextends layout
block content
h1= __('title')
p= __('welcome')
Layout example.
See more at heredoctype html
html
head
title= title
link(rel='stylesheet', href='/public/stylesheets/style.css')
body
block content
Directory where all config files are located
Scaffold to create a new controller
See more at hereconst {{model}}Controller = {
index: (req, res) => {
res.send('{{model}}Controller');
},
};
module.exports = {{model}}Controller;
Scaffold to create a new controller crud
See more at hereconst {{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;
Scaffold to create a new middleware
See more at hereconst {{model}}Middleware = (req, res, next) => {
next();
};
module.exports = {{model}}Middleware;
Scaffold to create a new model
See more at hereconst mongoose = require('mongoose');
const Schema = mongoose.Schema;
const {{model}}Model = new Schema({
});
module.exports = mongoose.model('{{model}}', {{model}}Model);
Scaffold to create a new service
See more at hereconst {{model}}Service = {
index: () => new Promise((resolve, reject) => {
}),
};
module.exports = {{model}}Service;
Here your database is defined. By default in Apogeu the database is MongoDB using the Mongoose module.
See default file:
const mongoose = require('mongoose');
const log = require('winston');
const mongooseTimestamps = require('mongoose-timestamp');
const envs = require('./envs');
const { timestamps, mongodb, node_env } = envs;
log.debug(`mongoose timestamps: ${timestamps}`);
mongoose.Promise = Promise;
if (timestamps) mongoose.plugin(mongooseTimestamps);
module.exports = () => new Promise((resolve, reject) => {
const debugMongoose = node_env !== 'production';
log.debug(`debug mongoose: ${debugMongoose}`);
mongoose.set('debug', debugMongoose);
mongoose.connect(mongodb);
mongoose.connection.on('connected', () => log.info(`Mongoose default connection open to ${mongodb}`));
mongoose.connection.on('error', err => reject(err));
mongoose.connection.on('disconnected', () => log.info('Mongoose default connection disconnected'));
mongoose.connection.once('open', () => {
resolve();
log.info('Mongoose default connection is open');
});
process.on('SIGINT', () => {
mongoose.connection.close(() => {
log.info('Mongoose default connection disconnected through app termination');
process.exit(0);
});
});
});
Here is where all environments are declared
Name | Type | Default value | Description |
---|---|---|---|
node_env | String | development | The environment definition of your application. Possible values: development | test | production. |
timestamps | Boolean | true | Enable ou disable the mongoose timestamps. See more in mongoose-timestamp. Possible values: true | false. |
mongodb | String | mongodb://localhost:27017/apogeu | Mongoose uri connection. See more in mongoose connections. |
port | Number | 3000 | Port setting for your application. |
logger | String | dev | HTTP request logger middleware for node.js. See more in morgan |
cluster | Number | Number of your cpu | The cluster module allows you to easily create child processes that all share server ports. See more in nodejs cluster |
See default file:
module.exports = {
node_env: 'development',
timestamps: true,
mongodb: 'mongodb://localhost:27017/apogeu',
};
Here is where all routes are declared
See default file:
// 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,
},
],
};
Directory where all public files are located
Directory where all css files are located.
All Stylus files are compiled to this location.body{padding:50px;font:14px "Lucida Grande",Helvetica,Arial,sans-serif}a{color:#00b7ff}
Directory where all tests are created
Directory where all integration tests are created
A integration test can be executed with the apogeu test integration
command:
$ apogeu test integration
Example output console:
info: Mongoose default connection open to mongodb://localhost:27017/apogeu
info: Mongoose default connection is open
info: running integration tests
info: Application listening on port 3000
Mongoose: users.find({}, { limit: undefined, skip: undefined, fields: {} })
✓ list users
1 passing (58ms)
Example integration test:
const assert = require('assert');
it('list users', (done) => {
UsersService.list()
.then((results) => {
assert.equal(Array.isArray(results), true);
done();
});
});
Directory where all unit tests are created
A unit test can be executed with the apogeu test unit
command:
$ apogeu test unit
Example output console:
info: running unit tests
✓ user service is an object
1 passing (7ms)
Example unit test:
const assert = require('assert');
it('user service is an object', (done) => {
assert.equal(typeof UsersService, 'object');
done();
});
EditorConfig helps developers define and maintain consistent coding styles between different editors and IDEs. The EditorConfig project consists of a file format for defining coding styles and a collection of text editor plugins that enable editors to read the file format and adhere to defined styles.
EditorConfig files are easily readable and they work nicely with version control systems.
# EditorConfig is awesome: http://EditorConfig.org
# top-most EditorConfig file
root = true
[*]
end_of_line = lf
insert_final_newline = true
[*.js]
indent_style = space
indent_size = 2
[Makefile]
indent_style = tab
[{package.json,.travis.yml}]
indent_style = space
indent_size = 2
A gitignore file specifies intentionally untracked files that Git should ignore. Files already tracked by Git are not affected.
# Logs
logs
*.log
npm-debug.log*
yarn-debug.log*
yarn-error.log*
# Runtime data
pids
*.pid
*.seed
*.pid.lock
# Directory for instrumented libs generated by jscoverage/JSCover
lib-cov
# Coverage directory used by tools like istanbul
coverage
# nyc test coverage
.nyc_output
# Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files)
.grunt
# Bower dependency directory (https://bower.io/)
bower_components
# node-waf configuration
.lock-wscript
# Compiled binary addons (http://nodejs.org/api/addons.html)
build/Release
# Dependency directories
node_modules/
jspm_packages/
# Typescript v1 declaration files
typings/
# Optional npm cache directory
.npm
# Optional eslint cache
.eslintcache
# Optional REPL history
.node_repl_history
# Output of 'npm pack'
*.tgz
# Yarn Integrity file
.yarn-integrity
# dotenv environment variables file
.env
#IntelliJ
.idea/
*.iml
In Apogeu, index.js
is invoked at initialization where it receives parameter app
/*
*
* The app object conventionally denotes the Express application
*
*/
module.exports = (app) => {
};
A package.json file affords you a lot of great things:
See more in:
Specifics of npm's package.json handling
Default file:
{
"name": "handson-test",
"version": "0.0.0",
"description": "",
"dependencies": {
"bluebird": "^3.5.0",
"mongoose": "^4.8.5",
"mongoose-timestamp": "^0.6.0",
"winston": "^2.3.1"
},
"devDependencies": {
"assert": "^1.4.1",
"mocha": "^3.2.0",
"eslint": "^3.17.0",
"eslint-config-airbnb-base": "^11.1.1",
"eslint-plugin-import": "^2.2.0"
}
}
A README file, along with a repository license, contribution guidelines, and a code of conduct, helps you communicate expectations for and manage contributions to your project.
Yarn is a package manager for your code. It allows you to use and share code with other developers from around the world. Yarn does this quickly, securely, and reliably so you don’t ever have to worry.