vlasky:galvanized-iron-router

v2.1.1Published 2 months ago

Galvanized Iron Router

Version License

Galvanized Iron Router is a fork of the classic Iron Router package, giving it a new lease of life by making it fully compatible with Meteor 3.0 and beyond. Just as galvanizing iron makes it rust-resistant and longer lasting, this fork ensures Iron Router continues to work reliably with modern Meteor applications.

It's a complete client/server routing system for Meteor with layouts, middleware, and reactive templates.

Guide

The primary guide for this fork is in Guide.md. The original Iron Router guide is still available as a legacy reference: iron-meteor.github.io/iron-router.

Installation

meteor add vlasky:galvanized-iron-router

Compatibility

Galvanized Iron Router supports all versions of Meteor from version 2.8.1 onwards. It has been tested on Meteor 2.8.1 and 3.4.

For Meteor 3.0+ projects, Galvanized Iron Router automatically adapts to:

  • Async/await execution model (no Fibers dependency)
  • Express 5 body parsing (when available)

Migrating from iron:router

Migrating from iron:router to vlasky:galvanized-iron-router is simple:

meteor remove iron:router
meteor add vlasky:galvanized-iron-router

That's it! Your existing code will work without any changes. Galvanized Iron Router maintains 100% API compatibility with the original Iron Router.

Examples

There are comprehensive examples in the examples folder organized by feature:

Quick Start

Create some routes in a client/server JavaScript file:

1Router.route('/', function () {
2  this.render('MyTemplate');
3});
4
5Router.route('/items', function () {
6  this.render('Items');
7});
8
9Router.route('/items/:_id', function () {
10  var item = Items.findOne({_id: this.params._id});
11  this.render('ShowItem', {data: item});
12});
13
14Router.route('/files/:filename', function () {
15  this.response.end('hi from the server\n');
16}, {where: 'server'});
17
18Router.route('/restful', {where: 'server'})
19  .get(function () {
20    this.response.end('get request\n');
21  })
22  .post(function () {
23    this.response.end('post request\n');
24  });
25

ES6 Module Support for Controllers

When using ES6 modules, controllers are no longer automatically available on the global scope. Galvanized Iron Router provides a controller registry so you don't need to pollute the global window object.

Registering Controllers

Example:

1// client/controllers.js
2import { DashboardController } from './management/dashboard.js';
3import { StoreController } from './management/store.js';
4import { UsersController } from './management/users.js';
5
6Router.registerControllers([
7  DashboardController,
8  StoreController,
9  UsersController
10]);

Routes work exactly as before - controller names are extracted automatically from the class:

1Router.route('/dashboard', { controller: 'DashboardController' });
2Router.route('/store/:id', { controller: 'StoreController' });

For anonymous controllers or custom names, use the two-argument form:

1Router.registerController('MyController', RouteController.extend({ ... }));

Alternatively, you can register a controller map to avoid relying on constructor names (useful for controllers created via RouteController.extend()):

1Router.registerControllers({
2  DashboardController,
3  StoreController,
4  UsersController
5});

How It Works

When resolving a controller by name, the router checks:

  1. Controller registry - Controllers registered via registerControllers()
  2. Global namespace - Falls back to window[controllerName] for backwards compatibility

This means existing code that assigns controllers to window continues to work unchanged.

API Notes

Hooks

onRun and onBeforeAction hooks require you to call this.next() to continue to the next handler. This follows the connect middleware convention.

1Router.onBeforeAction(function() {
2  if (! Meteor.userId()) {
3    this.render('login');
4  } else {
5    this.next();
6  }
7});

Middleware handler naming

Handler names are used for lookups like findByName, insertBefore, and insertAfter.

  • Explicit names ({ name: 'auth' }) must be unique and are the only safe way to target a handler by name.
  • Implicit names (derived from function names or paths) are allowed to collide and should not be relied on for name-based insertion.

If you plan to reference a handler later, always provide an explicit name.

Controller Methods

Use this.layout("fooTemplate") inside a route action to set the layout.

Query Parameters

Query parameters are available on this.params.query.

Loading Hook

The loading hook runs automatically on the client side if your route has a waitOn. You can set a global or per-route loadingTemplate.

If you want to setup subscriptions but not have an automatic loading hook, use the subscriptions option, which still affects .ready()-ness, but doesn't force the loading hook.

Hook and option inheritance

Hooks and options are inherited from parent controllers and the router. The order of precedence is: route; controller; parent controller; router.

Option lookup treats undefined as "not set" and will fall through to lower-precedence sources. If you need to explicitly clear an option, use null.

Route names

A route's name is accessible via route.getName(). For example: Router.current().route.getName().

Routes on client and server

It's not strictly required, but Iron Router works best when routes are declared on both client and server. This allows the client to route to the server and vice-versa.

Catchall routes

Iron Router uses path-to-regexp. The syntax for catchall routes is '/(.*)'.

Template Lookup

If you don't explicitly set a template option on your route, and you don't explicitly render a template name, the router will try to automatically render a template based on the name of the route. By default the router will look for the PascalCase name of the template.

For example, if you have a route defined like this:

1Router.route('/items/:_id', {name: 'items.show'});

The router will by default look for a template named ItemsShow with capital letters for each word and punctuation removed. If you would like to customize this behavior you can set your own converter function. For example, let's say you don't want any conversion. You can set the converter function like this:

1Router.setTemplateNameConverter(function (str) { return str; });

Contributing

Contributors are very welcome. There are many things you can help with, including finding and fixing bugs, creating examples for the examples folder, contributing to improved design or adding features. Some guidelines below:

  • Questions: Please post to Stack Overflow and tag with iron-router : https://stackoverflow.com/questions/tagged/iron-router.

  • New Features: If you'd like to work on a feature, start by creating a 'Feature Design: Title' issue. This will let people bat it around a bit before you send a full blown pull request. Also, you can create an issue to discuss a design even if you won't be working on it.

  • Bugs: If you think you found a bug, please create a "reproduction." This is a small project that demonstrates the problem as concisely as possible. The project should be cloneable from GitHub. Any bug reports without a reproduction that don't have an obvious solution will be marked as "awaiting-reproduction" and closed after one week.

Working Locally

This is useful if you're contributing code to Galvanized Iron Router.

  1. Set up a local packages folder
  2. Add the PACKAGE_DIRS environment variable to your .bashrc file
- Example: `export PACKAGE_DIRS="/home/user/code/packages"`
  1. Clone the repository into your local packages directory
  2. Add the package to your Meteor project
git clone https://github.com/vlasky/galvanized-iron-router.git /home/user/code/packages/galvanized-iron-router
cd my-project
meteor add vlasky:galvanized-iron-router

License

MIT