express-enrouten
express-enrouten copied to clipboard
Directory mode: process files with index.js before all others
This PR changes the default behavior of express-enrouten to process files in directory mode alphabetically (explicitly) and to process index.js
before all other files. This allows slightly more predictable route handling as structures get more complex. With this change, routes which must go earlier can be put into index.js
for the given level.
Old behavior:
[development] Listening on http://localhost:8000
[router] GET /about/ (./controllers/about.js)
[router] POST /amz-ses/ (./controllers/amz-ses.js)
[router] GET /ecgs/:ecg (./controllers/ecgs/index.js)
[router] POST /ecgs/:ecg (./controllers/ecgs/index.js)
[router] POST /ecgs/:ecg/tags (./controllers/ecgs/index.js)
[router] POST /ecgs/:ecg/signature (./controllers/ecgs/index.js)
[router] POST /ecgs/:ecg/uploaded (./controllers/ecgs/index.js)
[router] GET / (./controllers/index.js)
[router] GET /success (./controllers/index.js)
[router] GET /login/ (./controllers/login/index.js)
[router] POST /login/ (./controllers/login/index.js)
[router] GET /login/reset/ (./controllers/login/reset.js)
[router] POST /login/reset/ (./controllers/login/reset.js)
[router] GET /login/reset/sent (./controllers/login/reset.js)
...
New behavior:
[development] Listening on http://localhost:8000
[router] GET / (./controllers/index.js)
[router] GET /success (./controllers/index.js)
[router] GET /about/ (./controllers/about.js)
[router] POST /amz-ses/ (./controllers/amz-ses.js)
[router] GET /ecgs/:ecg (./controllers/ecgs/index.js)
[router] POST /ecgs/:ecg (./controllers/ecgs/index.js)
[router] POST /ecgs/:ecg/tags (./controllers/ecgs/index.js)
[router] POST /ecgs/:ecg/signature (./controllers/ecgs/index.js)
[router] POST /ecgs/:ecg/uploaded (./controllers/ecgs/index.js)
[router] GET /login/ (./controllers/login/index.js)
[router] POST /login/ (./controllers/login/index.js)
[router] GET /login/reset/ (./controllers/login/reset.js)
[router] POST /login/reset/ (./controllers/login/reset.js)
[router] GET /login/reset/sent (./controllers/login/reset.js)
...
This may be a breaking change for some consumers if they rely on the current behavior for proper route selection (perhaps on case-insensitive file systems).
Oh, this is interesting!
This dovetails nicely into #35, specifically the discussion around swaggerize-express. I would like to see the two converge on solution since it will be a breaking change either way.
I'll admit I'm relatively new to the node game, so some of the frameworks are foreign to me. If my understanding of swagger is correct, it basically is a configuration-convention to REST mapper. Is your idea of the perfect world in Kraken:
- express-enrouten handles directory routes like swaggerize-express, or...
- express-enrouten/swaggerize-express merge (you could swap out enrouten for swaggerize today via config.json updates I believe)
If you're looking for option 1, I can probably put that together tonight.
I was more thinking that the traversal implementation be pulled into a separate module that can be reference by both enrouten and swagger. I think that module would then need to include the changes suggested here to introduce an ordering algorithm when file are scanned an loaded.
So I've cobbled together what could be the base for this as a gist. It appears to match the behavior of a hybrid expresss-enrouten
/swaggerize-express
. It supports an options hash which can tell it to exclude dotfiles, and the user can provide a predicate to filter files.
Basically:
var routes = routeifyDirectory('./controllers');
Object.keys(routes).forEach(function (fn) {
console.log('%s (%s)', lpad(routes[fn], 30), fn);
});
Looks like:
/ (controllers\index.js)
/about (controllers\about.js)
/admin (controllers\admin.js)
/companies/:company (controllers\companies\{company}.js)
/contact (controllers\contact.js)
/login (controllers\login\index.js)
/login/reset (controllers\login\reset.js)
/logout (controllers\logout.js)
/products/:product/update (controllers\products\{product}\update.js)
/products/:product (controllers\products\{product}.js)
/products (controllers\products.js)
/suppliers/:supplier (controllers\suppliers\{supplier}\index.js)
/users (controllers\users\index.js)
/users/:user (controllers\users\{user}.js)
I think a useful addition would be a params folder where we could specify req.param handlers, but that's a PR for another day.
~~The downfall of this approach with enrouten, is express doesn't let you get the params from your parents in the stack. I had forgotten this until attempting to convert express-enrouten this AM. Swaggerize lives by this, but enrouten controllers expect more flexibility (e.g. taking a Router
and not a Route
).~~
I learn something new about express every day:
var router = express.Router({ mergeParams: true })
I've completed my conversion to order routes with index.js
first, use swaggerize-express style file naming, and be compatible with the old style structure (minus the order of resulting routes).
The functionality is broken out into a separate file ./lib/routeify.js
, which I'm not certain deserves its own npm module. A tentative look at how swaggerize-express's readhandlers.js
does its directory traversal suggests I could drop this into there as were.
This is obviously a big departure from current enrouten, and perhaps should be tagged vNext.
I understand the use of index.js
to map /
but I wonder if there is also a case for:
/car/ford.js => '/car/ford'
Such that one could optionally use /name/index.js
as well as simply /name.js
to map /name
.
I am thinking of adding index.js
as an alternate to /name.js
for convenience (even though that would block index
from use as a path name) for familiarity's sake.
This is currently in place (not only in enrouten, but preserved in my update).
On Thu, Aug 21, 2014 at 1:15 PM, Trevor [email protected] wrote:
I understand the use of index.js to map / but I wonder if there is also a case for:
/car/ford.js => '/car/ford'
Such that one could optionally use /name/index.js as well as simply /name.js to map /name.
I am thinking of adding index.js as an alternate to /name.js for convenience (even though that would block index from use as a path name) for familiarity's sake.
— Reply to this email directly or view it on GitHub https://github.com/krakenjs/express-enrouten/pull/47#issuecomment-52951907 .
Christopher A. Watford [email protected]
/facepalm
Right. Missed that obvious bit.
When you stare at directories of route handlers all day, it makes your eyes water ("there has got to be a better way!").
The one problem this brings with it is you find yourself nesting handlers deeply leading to ../../../../../
madness in require statements.
A nasty side effect seems to be router.param()
no longer appears to work as it only affects the paths at the current level.
@sixlettervariables would you be able to rebase your changes?
Yep!
On Jul 12, 2017 18:22, "Gabriel Csapo" [email protected] wrote:
@sixlettervariables https://github.com/sixlettervariables would you be able to rebase your changes?
— You are receiving this because you were mentioned. Reply to this email directly, view it on GitHub https://github.com/krakenjs/express-enrouten/pull/47#issuecomment-314914620, or mute the thread https://github.com/notifications/unsubscribe-auth/AH22YnYYmEZ8V6G_r0fLBvUOE94tIohQks5sNUcUgaJpZM4CYKGb .
Rebased.
@sixlettervariables thank you for rebasing, looking for others to get a thumbs on this to get it merged in!
@sixlettervariables how about handling for nested routes like this?
/users (controllers\users\index.js)
/users/:user (controllers\users\{user}\index.js)
/users/:user/orders (controllers\users\{user}\orders\index.js)
I was unable to get this code working, it just doesnt appear to be matching
yarn remove express-enrouten
yarn add sixlettervariables/express-enrouten#order-routes
Directory
/api/enitities/1000/alerts => api/entities/{id}/alerts.js
alerts.js does not run
I do not actively maintain any nodejs projects anymore, and my free time is lacking. If someone would like to pick this up and fix/extend it that'd be great.