Une application passe-partout pour la création d'applications Web à l'aide d'express et de Mongoose.
$ git clone https://github.com/wikiyodo/expressjs-boilerplate.git
$ cd expressjs-boilerplate
$ npm install
$ cp .env.example .env
$ npm run start:staging
├── /.data/
├── /app/
│ ├── Http
│ │ ├── Controllers
│ │ ├── Middleware
│ ├── Model
├── /bootstrap/
│ │ ├── boot-configuration.js
│ │ ├── boot-environment.js
│ │ ├── boot-helper-path.js
│ │ ├── boot-router.js
│ │ ├── index.js
│ │ ├── post-index.js
├── /commands/
│ ├── index.js
│ ├── seed.js
├── /database/
│ ├── /schema/
│ │ ├── bank.js
│ │ ├── users.js
│ ├── /seeds/
│ │ ├── bank.js
│ ├── /connection.js
│ └── /all-seeds.js
├── /global/
│ ├── constants.js
│ ├── user-roles.js
├── /helpers/ *
├── /resources/
│ ├── /lang/
│ ├── /view/
├── /routes/
│ ├── /api/
│ │ ├── index.js
│ │ ├── user.js
│ │ ├── guest.js
│ ├── index.js
│ ├── routes-string.js
├── /tests/
├── .env
├── .env.example
├── .gitignore
├── app.js
├── cmd.js
├── package.json
├── package-lock.json
└── Readme.md
Le résolveur contient une liste de modules qui peuvent aider dans divers aspects.
// how to access the resolver
var resolver = require(process.env.resolver);
Utilisé pour l'analyse des chaînes de route et de l'objet
resolver.parser(urlSelector, urlParameters, skipBackSlash);
Renvoie une chaîne de chemin par rapport au répertoire racine.
resolver.router('database/all-seeds'); // returns __ROOT_DIRECTORY__/database/all-seeds
Renvoie le chemin d'accès au module de connexion DB.
const resolver = require(process.env.resolver);
var mongoose = require(resolver.connection());
mongoose.model('User', UserSchema);
Renvoie le chemin d'accès au fichier de modèle passé en tant que paramètre
const resolver = require(process.env.resolver);
var bankModelPath = pathResolver.model('bank');
const Bank = require(bankModelPath);
Renvoie le chemin d'accès au fichier de schéma de base de données passé en tant que paramètre
const resolver = require(process.env.resolver);
var bankSchemaPath = resolver.dbSchema('bank');
const BankSchema = require(bankSchemaPath);
var Bank = mongoose.model('Bank', BankSchema);
Renvoie le chemin d'accès au fichier de contrôleur passé en tant que paramètre
const resolver = require(process.env.resolver);
var userControllerPath = resolver.controllers('user-controller');
const UserController= require(userControllerPath);
UserController.deleteUser(user_id, (err, response)=>{ });
Renvoie le chemin d'accès au fichier middleware transmis en tant que paramètre
const resolver = require(process.env.resolver);
var authMiddlewarePath= resolver.middleware('auth');
const AuthMiddleware= require(authMiddlewarePath);
app.use('/user', AuthMiddleware);
Tous les itinéraires sont contenus dans le projet_directory / itinéraires et sont attachés / mappés au routeur de base qui est contenu dans /routes/index.js
var express = require('express');
var router = express.Router();
// this contains all API routes.
var apiRouter = require('./api/index');
// this contains all routes that can be accessed via the web browsers
var webRouter = require('./web/index');
var routeString = require('./routes-string');
module.exports = (app) => {
app.use('/api', apiRouter);
app.use('/', apiRouter);
};
Disons que vous souhaitez créer un point de terminaison de l'API pour que les gens puissent obtenir le temps du serveur actuel dans un fichier séparé (Time.js qui contiendra tous les points de terminaison relatifs au temps).
Créer et ouvrir /Routes/API/time.js. Ensuite, le contenu devrait ressembler:
var express = require('express');
var router = express.Router();
// endpoint = /api/time/current
router.get('/current'), (req, res)=>{
res.status = 200;
res.send({time:Date.now});
res.end();
});
module.exports = router;
...
const TimeRouter = require('./time'); // this loads the time.js file
...
// use endpoint = /api/time
router.use('/time', TimeRouter );
Le routage dynamique vous permet de placer et de déclarer tous vos itinéraires / chemins dans un fichier et de les appeler pour une utilisation n'importe où sans avoir besoin de le refléter. Une fois que vous modifiez la valeur d'un itinéraire, il change partout où il est utilisé.
Tous les routes et chemins sont placés dans /routes/routes-string.js
const api = {
user: {
get: '/:id',
roles: {
get: '/all',
},
register: {
':role': {
save: '/save/:userId?'
}
}
},
bank: {
get: '/all'
}
};
const WEB = {
};
module.exports = {
api,
...WEB
};
...
const resolver = require(process.env.resolver);
// the dynamic routing module is place in the resolver and can be accessed resolver.parser
var $ = resolver.parser;
...
// $('api.bank.get', 'api') returns /api/bank/all as path
router.get($('api.bank.get', 'api'), BankController.getAllBanks);
Resolver.PaSer (chemin, trinidex) est utilisé pour analyser les index d'un itinéraire.
Given that our route is -->
{
user: {
get:{
all: '/all'
},
':userId':{
profile: 'profile'
}
}
}
// to formulate user/get/all we will transverse through the index user.get.all
// to formulate user/:userId/profile, transverse through user.:userId.profile
resolver.parser('user.get.all'); // returns /user/get/all
resolver.parser('user.get.all', 'user'); // returns /get/all
resolver.parser('user.get.all', 'user.get'); // returns /all
resolver.parser('user.:userId.profile', {
userId: 3
}); // returns /user/3/profile
Pour définir les détails de votre base de données, ouvrez le fichier /.env et mettez à jour le contenu comme suit:
"DATABASE": {
"USERNAME": "YOUR DATABASE USERNAME",
"PASSWORD": "YOUR DATABASE PASSWORD",
"HOST": "YOUR DATABASE HOST e.g localhost",
"PORT": "YOUR DATABASE PORT e.g 27017",
"NAME": "YOUR DATABASE NAME",
"OPTIONS": {} // extra mongoose options
}
Au lieu de définir toute votre logique de gestion de demande en tant que fermetures dans les fichiers d'itinéraire, vous souhaiterez peut-être organiser ce comportement à l'aide d'un objet Controller. Les contrôleurs peuvent regrouper la logique de traitement des demandes liées dans un seul objet (source: https://laravel.com/docs/5.7/Controllers). Pour créer un contrôleur, créez un nouveau fichier, par exemple, User-Controller.js dans / app / http / contrôlers. Un contrôleur typique ressemble à ceci;
const resolver = require(process.env.resolver);
const Controller = require('./controller');
var UserController = {};
UserController.getUserRoles = (req, res, next) => {
var returnableRoles = [];
for (var role in Roles)
returnableRoles.push(Roles[role]);
Controller.defaultResponse(res, returnableRoles);
};
module.exports = UserController;
Pour accéder à votre contrôleur n'importe où, vous pouvez facilement utiliser Resolver.
...
const resolver = require(process.env.resolver);
const UserController = require(resolver.controllers('user-controller'));
...
router.get('/user/roles', UserController.getUserRoles);
...
Le middleware fournit un mécanisme pratique pour filtrer les demandes HTTP entrant dans votre application. Les middlewares sont stockés dans / app / http / middleware pour créer un middleware, créer un nouveau fichier, par exemple auth.js dans / app / http / middleware. Un middleware typique ressemble à ceci;
module.exports = (req, res, next) => {
// your logic here
// proceed to next middleware
next();
}
Pour accéder à votre middleware n'importe où, vous pouvez facilement utiliser Resolver.Middleware («Nom of Your Middleware»)
...
const resolver = require(process.env.resolver);
const AuthMiddleware= require(resolver.middleware('auth'));
...
router.use('/user', AuthMiddleware);
...
Tout le schéma de la base de données du projet est placé dans le répertoire de base de données / schéma. Un schéma typique ressemble à ceci:
const resolver = require(process.env.resolver);
var mongoose = require(resolver.connection());
var lastUpdateDate = require('./plugins/last-update');
var Schema = mongoose.Schema;
// sample for a bank schema
var structure = {};
structure.name = String;
structure.code = String;
var bankSchema = new Schema(structure);
bankSchema.plugin(lastUpdateDate);
module.exports = bankSchema;
Cette passe-partout comprend une méthode simple pour entretenir votre base de données avec des données de test à l'aide de fichiers de semences. Toutes les graines de base de données sont placées dans le répertoire de base de données / graines.
const pathResolver = require(process.env.resolver);
const Bank= require(pathResolver.model('bank')).Bank;
var getBanks = () => {
return {
"ACCESS BANK": "044",
"ACCESSMOBILE": "323",
"ASO SAVINGS AND LOANS": "401",
"CELLULANT": "317",
"CENTRAL BANK OF NIGERIA": "001",
"CITIBANK": "023",
"CORONATION MERCHANT BANK": "559",
"CORPORETTI": "310",
"COVENANT MICROFINANCE BANK": "551",
"DIAMOND BANK": "063",
"EARTHOLEUM(QIK QIK)": "302",
"ECOBANK NIGERIA": "050",
"ECOMOBILE": "307",
"EKONDO MICROFINANCE BANK": "562",
"ENTERPRISE BANK": "084",
"EQUITORIAL TRUST BANK": "040",
"E - TRANZACT": "306",
"FBN M- MONEY": "309",
"FBN MORTGAGES": "413",
"FETS(MY WALLET)": "314",
"FIDELITY BANK": "070",
"FIDELITY MOBILE": "318",
"FINATRUST MICROFINANCE BANK": "608",
"FIRST BANK OF NIGERIA": "011",
"FIRST CITY MONUMENT BANK": "214",
"FIRST INLAND BANK": "085",
"FORTIS MICROFINANCE BANK": "501",
"FORTIS MOBILE": "308",
"FSDH": "601",
"GT MOBILE MONEY": "315",
"GUARANTY TRUST BANK": "058",
"HEDONMARK": "324",
"HERITAGE BANK": "030",
"IMPERIAL HOMES MORTGAGE BANK": "415",
"INTERCONTINENTAL BANK": "069",
"JAIZ BANK": "301",
"JUBILEE LIFE": "402",
"KEGOW": "303",
"KEYSTONE BANK": "082",
"MAINSTREET BANK": "014",
"MIMONEY(POWERED BY INTELLIFIN)": "330",
"M - KUDI": "313",
"MONETIZE": "312",
"MONEYBOX": "325",
"NEW PRUDENTIAL BANK": "561",
"NPF MFB": "552",
"OCEANIC BANK": "056",
"OMOLUABI SAVINGS AND LOANS": "606",
"ONE FINANCE": "565",
"PAGA": "327",
"PAGE MFBANK": "560",
"PARALLEX": "502",
"PARKWAY(READY CASH)": "311",
"PAYATTITUDE ONLINE": "329",
"PAYCOM": "304",
"PROVIDUS BANK": "101",
"SAFETRUST MORTGAGE BANK": "403",
"SEED CAPITAL MICROFINANCE BANK": "609",
"SKYE BANK": "076",
"STANBIC IBTC BANK": "221",
"STANBIC MOBILE": "304",
"STANDARD CHARTERED BANK": "068",
"STERLING BANK": "232",
"STERLING MOBILE": "326",
"SUNTRUST": "100",
"TEASY MOBILE": "319",
"TRUSTBOND": "523",
"U - MO": "316",
"UNION BANK OF NIGERIA": "032",
"UNITED BANK FOR AFRICA": "033",
"UNITY BANK": "215",
"VFD MICROFINANCE BANK": "566",
"VISUAL ICT": "328",
"VTNETWORK": "320",
"WEMA BANK": "035",
"ZENITH BANK": "057",
"ZENITH MOBILE": "322"
};
};
var locationSeed = () => {
// get all banks
banks = getBanks();
var insertables = [];
for (var name in banks) {
var code = banks[name];
insertables.push({
name,
code
});
}
Bank.insertMany(insertables, (err, docs) => {
if (err) {
console.error(err);
}
});
};
module.exports = locationSeed;
Après avoir placé vos graines dans le répertoire des graines, vous devez le spécifier dans /database/all-seeds.js pour permettre au semence de le localiser
var SeedBanks= require('./seeds/banks');
var exports = {
SeedBanks,
// place your seeds here
};
module.exports = exports;
Pour migrer vos graines, vous utilisez la commande ci-dessous.
> node cmd run:seed
Cela vous permet d'exécuter certaines commandes dans la CLI (interface de ligne de commande).
Pour créer votre commande personnalisée; Créez un fichier qui héberge la logique à votre commande dans / commandes , par exemple / commands/remove-users.js pourrait contenir l'extrait ci-dessous
var exports = {};
exports.removeOldUsers = (args) => {
// logic here
};
module.exports = exports;
Spécifiez ensuite le nom de votre commande et également une fonction appelable dans /commands/index.js
var seeder = require('./seed');
/**
* @info all arguments are to be placed here
*/
const arguments = {
'run:seed': seeder.runSeed,
'your_command': CallableFunction
};
module.exports = arguments;
Cela vous permet de valider une valeur donnée par rapport à un ensemble de règles.
// Use this to import validation module
var resolver = require(process.env.resolver);
var validator = require(resolver.validator());
Les validations sont effectuées de manière asynchrone. validator (array_of_rules, rappel);
validator([
{
fieldName: "name", // name of the field
fieldValue: 2, // the value of the field
validation: 'min:3|max:4', // set of validation rules
errorMessage:"Invalid name" // custom error message for all rules.
}
], (result) => {
res.send(result);
res.end();
});
Les règles autorisées incluent:
Cela vérifie que la valeur de don est d'une longueur ou d'une valeur minimale de la valeur spécifiée. Par exemple, Min: 2, vérifie que la chaîne a une longueur minimale de 2 caractères et au cas où elle est numérique, il vérifie que le nombre donné est supérieur ou égal à 2.
Cela vérifie que la valeur de don est d'une longueur ou d'une valeur maximale de la valeur spécifiée. EG Min: 2, vérifie que la chaîne a une longueur maximale de 2 caractères et au cas où elle est numérique, il vérifie que le nombre donné est inférieur ou égal à 2.
Cela vérifie que la valeur donnée ne contient que des caractères alphabétiques et rien d'autre.
Cela vérifie que la valeur donnée ne contient que des caractères numériques alpha et rien d'autre.
Cela confirme que la valeur donnée est un tableau d'articles.
Cela confirme que la valeur donnée est un numéro décimal
Cela valide que la valeur donnée est un e-mail valide.
Cela valide que la valeur donnée ne contient que des valeurs numériques.
Cela vérifie si la valeur donnée est un numéro de téléphone valide.
Cela vérifie que la valeur donnée n'est pas vide.
Pour vérifier si une validation a échoué
validator(rules, (result) => {
result.failed(); // returns a boolean. true when it fails and false when it doesnt.
result.getFirst('field name'); // returns the first error for the field and undefined in case there is no error
result.getError('field name'); // returns all errors for the field
});
Les tests unitaires n'ont pas été inclus dans cette passe-partole. Cependant, vous pouvez choisir de l'inclure par vous-même.
Tout le monde et tout le monde est invité à contribuer.
Mit