diff --git a/README.md b/README.md index f0eb668..6cbb1f4 100644 --- a/README.md +++ b/README.md @@ -11,7 +11,7 @@ You need NPM to install folder-router in your NodeJS project. $ npm install --save folder-router ``` -You can now use it in your main server file. +You can now use it in your main server file. The first parameters must be your express instance, the second one must be the location of your routes directory. I highly recommand to use absolute location. ```js var app = require('express')(); @@ -24,8 +24,8 @@ app.listen(3000); ## Creating your routes -In your routes directory, you can create as much as file as you want, everything will be read and add to express by folder-router. A route file MUST export a express.Router() instance as below : - +In your routes directory, you can create as much as file as you want, everything will be read and add to express by folder-router. A route file MUST export a express.Router() instance as below: + routes/book.js ```js var Router = require('express').Router(); @@ -48,9 +48,9 @@ Here is the list of all end points : - GET http://localhost:3000/book - GET http://localhost:3000/book/5 - POST http://localhost:3000/book - + ------------- -Also, you can create a directory "book" and write your routes like so : +Also, you can create a directory "book" and write your routes like so: routes/book/book.js ```js var Router = require('express').Router(); @@ -69,7 +69,7 @@ Router.post('/', function(req, res) { module.exports = Router; ``` -The name of the file has no impact. The end point remains the same because it takes the name of the sub directory +The name of the file has no impact by default. The end point remains the same because it takes the name of the sub directory --------- @@ -95,6 +95,51 @@ module.exports = Router; module.exports.root = '/book'; // here ``` +--------- + +If you want to use name files as part of the route as well, you can use `useFilenameAsRoot` option like so: + +```js +var app = require('express')(); +var router = require('folder-router'); + +router(app, { + location: __dirname + '/routes', + useFilenameAsRoot: true +}); + +app.listen(3000); +``` + +So now the endpoints will end up like: + +- GET http://localhost:3000/book/book +- GET http://localhost:3000/book/book/5 +- POST http://localhost:3000/book/book + +Take note that index.js files won't be used as part of the route, for example: + +routes/book/index.js +```js +var Router = require('express').Router(); + +Router.get('/', function(req, res) { + res.end('All Books !'); +}); + +Router.get('/:id', function(req, res) { + res.end('Books with id = ', req.params.id); +}); + +Router.post('/', function(req, res) { + res.end('Adding a new book') +}); +``` +It will define the following routes: + +- GET http://localhost:3000/book +- GET http://localhost:3000/book/5 +- POST http://localhost:3000/book ## Tests @@ -107,11 +152,11 @@ $ mocha ./test ``` ## Contribute -All ways to contribute to folder-router are highly appreciated: -- improving the readme -- writing features -- writing tests -- writing a tutorial +All ways to contribute to folder-router are highly appreciated: +- improving the readme +- writing features +- writing tests +- writing a tutorial - troubleshooting reported issues - + Thank you very much ! diff --git a/lib/index.js b/lib/index.js index d5d6edd..63bfb01 100644 --- a/lib/index.js +++ b/lib/index.js @@ -1,52 +1,82 @@ var path = require('path'); var fs = require('fs'); -function exist(location) { - try { - var stat = fs.statSync(location); - return (stat.isFile() || stat.isDirectory()); - } catch (err) { - return (false); - } +function exist (location) { + try { + const stat = fs.statSync(location); + return (stat.isFile() || stat.isDirectory()); + } catch (err) { + return false; + } } -function handleFolder(app, root, folder) { - var files = fs.readdirSync(folder); +function handleFolder (app, config) { + const { location: folder } = config; + const files = fs.readdirSync(folder); - files.forEach(function(file) { - var absolutePathFile = path.join(folder, file); - analyzeFile(app, root, absolutePathFile); - }); + files.forEach((file) => { + const absolutePathFile = path.join(folder, file); + analyzeFile(app, Object.assign({}, config, { location: absolutePathFile })); + }); } -function handleFile(app, root, filepath) { - var fileContent = require(filepath); - var middlewareRoot = ''; +function getRoute (fileContent, config) { + const { root, location: filepath, useFilenameAsRoot } = config; - if (fileContent.root) { - middlewareRoot = fileContent.root; - } else { - var location = path.dirname(filepath); - middlewareRoot = location.substr(root.length); + if (useFilenameAsRoot) { + const {name, dir} = path.parse(filepath); + if (name === 'index') { + return dir.substr(root.length); } - app.use(middlewareRoot, require(filepath)); + return path.join(dir, name).substr(root.length); + } + + if (fileContent.root) { + return fileContent.root; + } + + return path + .dirname(filepath) + .substr(root.length); } -function analyzeFile(app, root, location) { - var stat = fs.statSync(location); +function handleFile (app, config) { + const { location: filepath } = config; + const fileContent = require(filepath); + let middlewareRoot = getRoute(fileContent, config); - if (stat.isFile()) - handleFile(app, root, location); - else if (stat.isDirectory()) - handleFolder(app, root, location); + app.use(middlewareRoot, require(filepath)); } -module.exports = function(app, location) { - location = location || './routes'; - location = path.resolve(location); +function analyzeFile (app, config) { + const { location } = config; + const stat = fs.statSync(location); - if (!exist(location)) { - throw new Error('Cannot find routes folder'); - } - analyzeFile(app, location, location); + if (stat.isFile()) { + handleFile(app, config); + } else if (stat.isDirectory()) { + handleFolder(app, config); + } } + +function getConfig (config) { + if (typeof config === 'string') { + config = { location: config }; + } + const { location = './routes', useFilenameAsRoot = false } = config; + const root = path.resolve(location); + return { + location: root, + root, + useFilenameAsRoot + }; +} + +module.exports = (app, options) => { + const config = getConfig(options); + + if (!exist(config.location)) { + throw new Error('Cannot find routes folder'); + } + analyzeFile(app, config); +}; diff --git a/package.json b/package.json index 3db4421..84a2169 100644 --- a/package.json +++ b/package.json @@ -1,9 +1,11 @@ { "name": "folder-router", - "version": "1.0.4", - "description": "A simple router based on folder name ", + "version": "2.0.0", + "description": "A simple router based on folder name", "main": "lib/index.js", "scripts": { + "lint": "semistandard --fix --env mocha", + "pretest": "npm run lint", "test": "mocha ./test" }, "repository": { @@ -21,14 +23,15 @@ "rest" ], "author": "dorianamouroux", - "license": "ISC", + "license": "MIT", "bugs": { "url": "https://github.com/dorianamouroux/folder-router/issues" }, "homepage": "https://github.com/dorianamouroux/folder-router#readme", - "dependencies": {}, "devDependencies": { "express": "^4.13.4", + "mocha": "^5.2.0", + "semistandard": "*", "supertest": "^1.2.0" } } diff --git a/test/index.js b/test/index.js index 80c0a56..a3fc197 100644 --- a/test/index.js +++ b/test/index.js @@ -1,31 +1,109 @@ -var request = require('supertest'); +const path = require('path'); +const request = require('supertest'); +const express = require('express'); +const router = require('../'); -var app = require('./server/app').getApp; +const routesPath = path.join(__dirname, 'server', 'routes'); -describe('Test all endpoint', function() { - it('should respond 200 on /', function(done) { - request(app) - .get('/') - .expect(200, done); // note that we're passing the done as parameter to the expect +const createApp = (options = routesPath) => { + const app = express(); + + router(app, options); + + return app; +}; + +let app; + +describe('Test all endpoint', () => { + context('when `options` is a string', () => { + before(() => { + app = createApp(); + }); + + it('should respond 200 on /', (done) => { + request(app) + .get('/') + .expect(200, done); // note that we're passing the done as parameter to the expect + }); + it('should respond 200 on /contact', (done) => { + request(app) + .get('/contact') + .expect(200, done); // note that we're passing the done as parameter to the expect + }); + it('should respond 200 on /book', (done) => { + request(app) + .get('/book') + .expect(200, done); // note that we're passing the done as parameter to the expect + }); + it('should respond 200 on /book/4', (done) => { + request(app) + .get('/book/4') + .expect(200, done); // note that we're passing the done as parameter to the expect + }); + + it('should respond 200 on /books', (done) => { + request(app) + .get('/books') + .expect(200, done); // note that we're passing the done as parameter to the expect }); - it('should respond 200 on /contact', function(done) { - request(app) - .get('/contact') - .expect(200, done); // note that we're passing the done as parameter to the expect + it('should respond 200 on /books/4', (done) => { + request(app) + .get('/books/4') + .expect(200, done); // note that we're passing the done as parameter to the expect }); - it('should respond 200 on /book', function(done) { - request(app) - .get('/book') - .expect(200, done); // note that we're passing the done as parameter to the expect + + it('should respond 200 on /user', (done) => { + request(app) + .get('/user') + .expect(200, done); // note that we're passing the done as parameter to the expect + }); + }); + + context('when `useFilenameAsRoot` is true', () => { + before(() => { + app = createApp({ + location: routesPath, + useFilenameAsRoot: true + }); + }); + + it('should respond 200 on /', (done) => { + request(app) + .get('/') + .expect(200, done); // note that we're passing the done as parameter to the expect + }); + it('should respond 200 on /contact', (done) => { + request(app) + .get('/contact') + .expect(200, done); // note that we're passing the done as parameter to the expect }); - it('should respond 200 on /book/4', function(done) { - request(app) - .get('/book/4') - .expect(200, done); // note that we're passing the done as parameter to the expect + it('should respond 200 on /books/books', (done) => { + request(app) + .get('/books/books') + .expect(200, done); // note that we're passing the done as parameter to the expect }); - it('should respond 200 on /user', function(done) { - request(app) - .get('/user') - .expect(200, done); // note that we're passing the done as parameter to the expect + it('should respond 200 on /books/books/4', (done) => { + request(app) + .get('/books/books/4') + .expect(200, done); // note that we're passing the done as parameter to the expect + }); + + it('should respond 200 on /books', (done) => { + request(app) + .get('/books') + .expect(200, done); // note that we're passing the done as parameter to the expect + }); + it('should respond 200 on /books/4', (done) => { + request(app) + .get('/books/4') + .expect(200, done); // note that we're passing the done as parameter to the expect + }); + + it('should respond 200 on /user/user', (done) => { + request(app) + .get('/user/user') + .expect(200, done); // note that we're passing the done as parameter to the expect }); + }); }); diff --git a/test/server/app.js b/test/server/app.js deleted file mode 100644 index bbbd660..0000000 --- a/test/server/app.js +++ /dev/null @@ -1,6 +0,0 @@ -var app = require('express')(); -var router = require('../..'); - -router(app, __dirname + '/routes'); - -module.exports.getApp = app; diff --git a/test/server/routes/books/books.js b/test/server/routes/books/books.js index 00e2213..d4d8ad1 100644 --- a/test/server/routes/books/books.js +++ b/test/server/routes/books/books.js @@ -1,11 +1,11 @@ var Router = require('express').Router(); -Router.get('/', function(req, res) { - res.end('books'); +Router.get('/', function (req, res) { + res.end('books'); }); -Router.get('/:id', function(req, res) { - res.end('book = ' + req.params.id); +Router.get('/:id', function (req, res) { + res.end('book = ' + req.params.id); }); module.exports = Router; diff --git a/test/server/routes/books/index.js b/test/server/routes/books/index.js new file mode 100644 index 0000000..56250be --- /dev/null +++ b/test/server/routes/books/index.js @@ -0,0 +1,13 @@ +var Router = require('express').Router(); + +Router.get('/', function (req, res) { + res.end('books'); +}); + +Router.get('/:id', function (req, res) { + res.end('book = ' + req.params.id); +}); + +module.exports = Router; + +module.exports.root = '/books'; diff --git a/test/server/routes/index.js b/test/server/routes/index.js index 94457cb..c970d84 100644 --- a/test/server/routes/index.js +++ b/test/server/routes/index.js @@ -1,11 +1,11 @@ var Router = require('express').Router(); -Router.get('/', function(req, res) { - res.end('index'); +Router.get('/', function (req, res) { + res.end('index'); }); -Router.get('/contact', function(req, res) { - res.end('contact'); +Router.get('/contact', function (req, res) { + res.end('contact'); }); module.exports = Router; diff --git a/test/server/routes/user/user.js b/test/server/routes/user/user.js index 1337296..47b7a2e 100644 --- a/test/server/routes/user/user.js +++ b/test/server/routes/user/user.js @@ -1,7 +1,7 @@ var Router = require('express').Router(); -Router.get('/', function(req, res) { - res.end('user'); +Router.get('/', function (req, res) { + res.end('user'); }); module.exports = Router;