แอปพลิเคชั่นหม้อไอน้ำสำหรับการสร้างเว็บแอปโดยใช้ Express และ 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
ตัวแก้ไขมีรายการของโมดูลที่สามารถช่วยในด้านต่าง ๆ
// how to access the resolver
var resolver = require(process.env.resolver);
ใช้สำหรับการแยกวิเคราะห์สายและวัตถุ
resolver.parser(urlSelector, urlParameters, skipBackSlash);
ส่งคืนสตริงของเส้นทางที่สัมพันธ์กับไดเรกทอรีราก
resolver.router('database/all-seeds'); // returns __ROOT_DIRECTORY__/database/all-seeds
ส่งคืนเส้นทางไปยังโมดูลการเชื่อมต่อ DB
const resolver = require(process.env.resolver);
var mongoose = require(resolver.connection());
mongoose.model('User', UserSchema);
ส่งคืนพา ธ ไปยังไฟล์โมเดลที่ส่งเป็นพารามิเตอร์
const resolver = require(process.env.resolver);
var bankModelPath = pathResolver.model('bank');
const Bank = require(bankModelPath);
ส่งคืนพา ธ ไปยังไฟล์สคีมาฐานข้อมูลที่ส่งผ่านเป็นพารามิเตอร์
const resolver = require(process.env.resolver);
var bankSchemaPath = resolver.dbSchema('bank');
const BankSchema = require(bankSchemaPath);
var Bank = mongoose.model('Bank', BankSchema);
ส่งคืนพา ธ ไปยังไฟล์คอนโทรลเลอร์ที่ส่งเป็นพารามิเตอร์
const resolver = require(process.env.resolver);
var userControllerPath = resolver.controllers('user-controller');
const UserController= require(userControllerPath);
UserController.deleteUser(user_id, (err, response)=>{ });
ส่งคืนพา ธ ไปยังไฟล์มิดเดิลแวร์ที่ส่งเป็นพารามิเตอร์
const resolver = require(process.env.resolver);
var authMiddlewarePath= resolver.middleware('auth');
const AuthMiddleware= require(authMiddlewarePath);
app.use('/user', AuthMiddleware);
เส้นทางทั้งหมดมีอยู่ใน project_directory /เส้นทางและติด /แมปกับเราเตอร์ฐานซึ่งมีอยู่ใน /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);
};
สมมติว่าคุณต้องการสร้างจุดสิ้นสุด API สำหรับผู้ที่ได้รับเวลาเซิร์ฟเวอร์ปัจจุบันในไฟล์แยกต่างหาก (time.js ซึ่งจะมีจุดสิ้นสุดทั้งหมดที่เกี่ยวข้องกับเวลา)
สร้างและเปิด/routes/api/time.js แล้วเนื้อหาควรมีลักษณะ:
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 );
การกำหนดเส้นทางแบบไดนามิกช่วยให้คุณสามารถวางและประกาศเส้นทาง/เส้นทางทั้งหมดของคุณในไฟล์และเรียกพวกเขาเพื่อใช้งานได้ทุกที่โดยไม่จำเป็นต้องตัดสินใจอีกครั้ง เมื่อคุณเปลี่ยนค่าของเส้นทางมันจะเปลี่ยนไปทุกที่ที่ใช้
เส้นทางและเส้นทางทั้งหมดจะถูกวางไว้ใน /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.parser (Path, TrimIndex) ใช้เพื่อแยกดัชนีของเส้นทาง
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
หากต้องการตั้งค่ารายละเอียดฐานข้อมูลของคุณให้เปิดไฟล์ /.env และอัปเดตเนื้อหาดังนี้:
"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
}
แทนที่จะกำหนดตรรกะการจัดการคำขอทั้งหมดของคุณเป็นการปิดในไฟล์เส้นทางคุณอาจต้องการจัดระเบียบพฤติกรรมนี้โดยใช้วัตถุคอนโทรลเลอร์ คอนโทรลเลอร์สามารถจัดกลุ่มการจัดการคำขอที่เกี่ยวข้องกับลอจิกลงในวัตถุเดียว (ที่มา: https://laravel.com/docs/5.7/controllers) ในการสร้างคอนโทรลเลอร์ให้สร้างไฟล์ใหม่เช่นผู้ใช้ controller.js in/app/http/คอนโทรลเลอร์ คอนโทรลเลอร์ทั่วไปมีลักษณะเช่นนี้
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;
ในการเข้าถึงคอนโทรลเลอร์ของคุณทุกที่คุณสามารถใช้ Resolver.Controllers ('ชื่อของตัวควบคุมของคุณ') ได้อย่างง่ายดาย)
...
const resolver = require(process.env.resolver);
const UserController = require(resolver.controllers('user-controller'));
...
router.get('/user/roles', UserController.getUserRoles);
...
มิดเดิลแวร์ให้กลไกที่สะดวกสำหรับการกรองคำขอ HTTP ที่ป้อนแอปพลิเคชันของคุณ Middlewares จะถูกเก็บไว้ใน/App/Http/Middleware เพื่อสร้างมิดเดิลแวร์สร้างไฟล์ใหม่เช่น auth.js in/app/http/middleware มิดเดิลแวร์ทั่วไปมีลักษณะเช่นนี้
module.exports = (req, res, next) => {
// your logic here
// proceed to next middleware
next();
}
ในการเข้าถึงมิดเดิลแวร์ของคุณทุกที่คุณสามารถใช้ Resolver.middleware ได้อย่างง่ายดาย ('ชื่อของคุณ-มิดเดิ้ลแวร์')
...
const resolver = require(process.env.resolver);
const AuthMiddleware= require(resolver.middleware('auth'));
...
router.use('/user', AuthMiddleware);
...
สคีมาฐานข้อมูลทั้งหมดสำหรับโครงการถูกวางไว้ในไดเรกทอรี /ฐานข้อมูล /สคีมา สคีมาทั่วไปมีลักษณะเช่นนี้:
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;
แผ่นหม้อไอน้ำนี้มีวิธีง่ายๆในการเพาะฐานข้อมูลของคุณด้วยข้อมูลการทดสอบโดยใช้ไฟล์เมล็ด เมล็ดฐานข้อมูลทั้งหมดจะถูกวางไว้ในไดเรกทอรี /ฐานข้อมูล /เมล็ด
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;
หลังจากวางเมล็ดพันธุ์ของคุณไว้ในไดเรกทอรีเมล็ดคุณต้องระบุใน /database /all-seeds.js เพื่อให้ผู้ทำ seeder สามารถค้นหาได้
var SeedBanks= require('./seeds/banks');
var exports = {
SeedBanks,
// place your seeds here
};
module.exports = exports;
ในการโยกย้ายเมล็ดของคุณจากนั้นคุณใช้คำสั่ง Bellow
> node cmd run:seed
สิ่งนี้ช่วยให้คุณสามารถเรียกใช้คำสั่งบางอย่างใน CLI (อินเทอร์เฟซบรรทัดคำสั่ง)
เพื่อสร้างคำสั่งที่กำหนดเอง สร้างไฟล์ที่โฮสต์ลอจิกกับคำสั่งของคุณใน /คำสั่ง เช่น /commands/remove-users.js อาจมีตัวอย่างด้านล่าง
var exports = {};
exports.removeOldUsers = (args) => {
// logic here
};
module.exports = exports;
จากนั้นระบุชื่อคำสั่งของคุณและฟังก์ชันที่เรียกได้ใน /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;
สิ่งนี้ช่วยให้คุณตรวจสอบค่าที่กำหนดกับชุดของกฎบางอย่าง
// Use this to import validation module
var resolver = require(process.env.resolver);
var validator = require(resolver.validator());
การตรวจสอบความถูกต้องแบบอะซิงโครนัส ผู้ตรวจสอบ (array_of_rules, โทรกลับ);
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();
});
กฎที่อนุญาต ได้แก่ :
สิ่งนี้ตรวจสอบว่าค่าที่ให้นั้นมีความยาวต่ำสุดหรือค่าของค่าที่ระบุ เช่นขั้นต่ำ: 2 ตรวจสอบว่าสตริงมีความยาวขั้นต่ำ 2 อักขระและในกรณีที่เป็นตัวเลขจะตรวจสอบว่าหมายเลขที่กำหนดนั้นมากกว่าหรือเท่ากับ 2
สิ่งนี้ตรวจสอบว่าค่าที่ให้นั้นมีความยาวสูงสุดหรือค่าของค่าที่ระบุ เช่นขั้นต่ำ: 2 ตรวจสอบว่าสตริงมีความยาวสูงสุด 2 อักขระและในกรณีที่เป็นตัวเลขจะตรวจสอบว่าหมายเลขที่กำหนดน้อยกว่าหรือเท่ากับ 2
สิ่งนี้ตรวจสอบว่าค่าที่กำหนดมีเพียงอักขระตัวอักษรและไม่มีอะไรอื่น
สิ่งนี้ตรวจสอบว่าค่าที่กำหนดนั้นมีอักขระตัวเลขอัลฟ่าเท่านั้นและไม่มีอะไรอื่น
นี่เป็นการยืนยันว่าค่าที่กำหนดเป็นอาร์เรย์ของรายการ
นี่เป็นการยืนยันว่าค่าที่กำหนดเป็นจำนวนทศนิยม
สิ่งนี้ตรวจสอบว่าค่าที่กำหนดเป็นอีเมลที่ถูกต้อง
สิ่งนี้ตรวจสอบว่าค่าที่กำหนดมีค่าตัวเลขเท่านั้น
นี่จะตรวจสอบว่าค่าที่กำหนดเป็นหมายเลขโทรศัพท์ที่ถูกต้องหรือไม่
สิ่งนี้ตรวจสอบว่าค่าที่กำหนดไม่ว่างเปล่า
เพื่อตรวจสอบว่าการตรวจสอบล้มเหลวหรือไม่
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
});
การทดสอบหน่วยไม่รวมอยู่ในแผ่นหม้อไอน้ำนี้ อย่างไรก็ตามคุณสามารถเลือกที่จะรวมไว้ด้วยตัวเอง
ทุกคนและทุกคนยินดีที่จะมีส่วนร่วม
มิกซ์