Skip to content

Commit 1f67b41

Browse files
author
Karl Hepler
committed
Completely rewritten
1 parent f509985 commit 1f67b41

12 files changed

+480
-258
lines changed

.gitignore

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
node_modules
2+
test
3+
*.sw*

README.md

Lines changed: 1 addition & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -2,39 +2,4 @@
22

33
Laravel-like middleware for Angular
44

5-
## Installation / Setup
6-
7-
1. `bower install kjh-middleware --save` or `npm install kjh-middleware --save`
8-
2. Include 'kjhMiddleware' in your main module
9-
3. Install & import uiRouter
10-
11-
## Usage
12-
13-
1. Add the following config to your app:
14-
15-
.config(['middlewareProvider', function(middlewareProvider) {
16-
middlewareProvider.routeMiddlware({
17-
'label': ['anything', function(anything) {
18-
// Go to next middleware
19-
this.next();
20-
21-
// Redirect to a different state
22-
this.redirectTo('state-name');
23-
24-
// Get the route parameters
25-
var params = this.params();
26-
}]
27-
});
28-
})
29-
30-
2. Reference the middleware in your routes, either as a string separated by pipes OR an array
31-
32-
$stateProvider
33-
.state('state1', {
34-
...
35-
'middleware': 'middleware1|middleware2|middleware3' OR ['middleware1', 'middleware2', 'middleware3']
36-
})
37-
38-
## TODO
39-
40-
* Make this compatible with ngRouter
5+
I need to write new documentation

bower.json

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,8 @@
11
{
2-
"name": "kjh-middleware",
3-
"description": "Laravel-like middleware for angular uiRouter",
4-
"main": "kjh-middleware.js",
2+
"name": "angular-middleware",
3+
"version": "2.0.0",
4+
"description": "Laravel-like middleware for angular ui.router and ngRoute",
5+
"main": "dist/angular-middleware.min.js",
56
"authors": [
67
"Karl Hepler <karl.hepler@gmail.com>"
78
],
@@ -11,9 +12,12 @@
1112
"laravel",
1213
"angular",
1314
"angular",
14-
"ui-router"
15+
"ui-router",
16+
"ngRoute",
17+
"ui.router",
18+
"angular-route"
1519
],
16-
"homepage": "https://github.com/oldtimeguitarguy/kjh-middleware",
20+
"homepage": "https://github.com/oldtimeguitarguy/angular-middleware",
1721
"moduleType": [],
1822
"ignore": [
1923
"**/.*",

dist/angular-middleware.js

Lines changed: 215 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,215 @@
1+
;(function(angular) {
2+
"use strict";
3+
4+
// This has to be declared here
5+
// because this is concatinated
6+
// BEFORE the provider, which defines it
7+
var mappings = {};
8+
9+
var $middlewareFactory = [
10+
'$injector', '$q',
11+
function middlewareFactory($injector, $q) {
12+
13+
/**
14+
* This object is used to group
15+
* private middleware properties
16+
* that are used throughout this
17+
*/
18+
var middleware = {
19+
next: nextMiddleware
20+
};
21+
22+
/**
23+
* This object is passed
24+
* to the invoked middleware
25+
* and is used as the main API
26+
*/
27+
var request = {
28+
next: nextRequest,
29+
redirectTo: redirectTo
30+
};
31+
32+
/**
33+
* Initialize $middleware
34+
*
35+
* @param {object} toRoute
36+
* @param {mixed} toParams
37+
* @returns {promise}
38+
*/
39+
return function initialize(toRoute, toParams) {
40+
// Return early if the toRoute doesn't have middleware
41+
if ( !hasMiddleware(toRoute) ) return;
42+
43+
// Store a copy of the route parameters in the request
44+
request.params = angular.copy(toParams);
45+
46+
// Set the middleware index to 0
47+
middleware.index = 0;
48+
49+
// Set the middleware names
50+
middleware.names = getMiddlewareNames(toRoute);
51+
52+
// Create a deferred promise
53+
middleware.resolution = $q.defer();
54+
55+
// Process the first middleware
56+
middleware.next();
57+
58+
// Return the promise
59+
return middleware.resolution.promise;
60+
};
61+
62+
/**
63+
* Determine if the given route has middleware
64+
*
65+
* @param {object} toRoute
66+
* @returns {boolean}
67+
*/
68+
function hasMiddleware(route) {
69+
return !!route.middleware;
70+
}
71+
72+
/**
73+
* Get the middleware names
74+
* from an array or a piped string
75+
*
76+
* @param {object} route
77+
* @returns {array}
78+
*/
79+
function getMiddlewareNames(route) {
80+
return route.middleware instanceof Array
81+
? route.middleware
82+
: route.middleware.split('|');
83+
}
84+
85+
/**
86+
* Attempt to invoke the next middleware
87+
*
88+
* @returns {void}
89+
*/
90+
function nextMiddleware() {
91+
// Get the next middleware
92+
var next = mappings[middleware.names[middleware.index++]];
93+
94+
// If there is middleware, then invoke it, binding request
95+
if ( next ) $injector.invoke(next, request);
96+
}
97+
98+
/**
99+
* Go to the next request.
100+
* If there are more middleware,
101+
* then go to the next middleware.
102+
* Otherwise, resolve the middleware resolution.
103+
*
104+
* @returns {void}
105+
*/
106+
function nextRequest() {
107+
// If there are no more middleware,
108+
// then resolve the middleware resolution
109+
if ( middleware.index == middleware.names.length ) {
110+
middleware.resolution.resolve();
111+
}
112+
113+
// Attempt to invoke the next middleware
114+
middleware.next();
115+
}
116+
117+
/**
118+
* Redirect to another route
119+
*
120+
* @returns {void}
121+
*/
122+
function redirectTo(route) {
123+
middleware.resolution.reject('redirectTo:' + route);
124+
}
125+
}];
126+
127+
var $middleware = function middlewareProvider() {
128+
/**
129+
* Create custom middleware mappings
130+
*
131+
* ex:
132+
*
133+
* $middlewareProvider.map({
134+
* 'auth': ['$log', '$http',
135+
* function redirectIfNotAuthenticated($log, $http) {
136+
* var self = this;
137+
*
138+
* // Make a get request
139+
* $http.get('/is-authenticated')
140+
*
141+
* // The get request succeeded
142+
* .then(function success() {
143+
* self.next();
144+
* },
145+
*
146+
* // The get request failed
147+
* function fail(err) {
148+
* $log.error(err);
149+
* self.redirectTo('/');
150+
* });
151+
* }]
152+
* });
153+
*/
154+
this.map = function map(customMappings) {
155+
// Make sure customMappings is an object
156+
if ( typeof customMappings !== 'object' ) {
157+
throw 'Your middleware map must be an object!';
158+
}
159+
160+
// Set the mappings
161+
mappings = customMappings;
162+
};
163+
164+
// $get the middleware factory
165+
this.$get = $middlewareFactory;
166+
};
167+
168+
angular.module('ngRoute.middleware', []).provider('$middleware', $middleware)
169+
170+
// @todo: implement ngRoute.middleware!
171+
172+
angular.module('ui.router.middleware', []).provider('$middleware', $middleware)
173+
174+
.config(['$stateProvider', function($stateProvider) {
175+
// Init resolve:{} to all states
176+
// https://github.com/angular-ui/ui-router/issues/1165
177+
$stateProvider.decorator('path', function(state, parentFn) {
178+
if (state.self.resolve === undefined) {
179+
state.self.resolve = {};
180+
state.resolve = state.self.resolve;
181+
}
182+
return parentFn(state);
183+
});
184+
}])
185+
186+
.run(['$rootScope', '$state', '$middleware', function($rootScope, $state, $middleware) {
187+
/**
188+
* Handle middleware
189+
*/
190+
$rootScope.$on('$stateChangeStart', function(event, toState, toParams) {
191+
// Force the state to resolve the middleware before loading
192+
toState.resolve.middleware = function() {
193+
return $middleware(toState, toParams);
194+
};
195+
});
196+
197+
/**
198+
* Handle redirects from middleware
199+
*/
200+
$rootScope.$on('$stateChangeError', function(event, toState, toParams, fromState, fromParams, error) {
201+
var pattern = /redirectTo\:(.*)/;
202+
var match;
203+
204+
// Only proceed if there is a match to the pattern
205+
if ((match = pattern.exec(error)) !== null) {
206+
207+
// Prevent state change error from working normally
208+
event.preventDefault();
209+
210+
// Redirect, allowing reloading and preventing url param inheritance
211+
return $state.transitionTo(match[1], null, { location: true, inherit: false, relative: $state.$current, notify: true, reload: true });
212+
}
213+
});
214+
}])
215+
}(angular));

dist/angular-middleware.min.js

Lines changed: 1 addition & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

gulpfile.js

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
var gulp = require('gulp');
2+
var concat = require('gulp-concat');
3+
var uglify = require('gulp-uglify');
4+
var rename = require('gulp-rename');
5+
var iife = require('gulp-iife');
6+
7+
var src = 'src/**/*.js';
8+
9+
gulp.task('build-dev', function buildDev() {
10+
return gulp.src(src)
11+
.pipe(concat('angular-middleware.js'))
12+
.pipe(iife({
13+
params: ['angular']
14+
}))
15+
.pipe(gulp.dest('./dist/'));
16+
});
17+
18+
gulp.task('build-prod', ['build-dev'], function buildProd() {
19+
return gulp.src('dist/angular-middleware.js')
20+
.pipe(uglify())
21+
.pipe(rename(function rename(path) {
22+
path.basename += '.min';
23+
}))
24+
.pipe(gulp.dest('./dist/'));
25+
});
26+
27+
gulp.task('watch', function watch() {
28+
gulp.watch(src, ['build-dev']);
29+
});
30+
31+
gulp.task('default', ['build-dev']);

0 commit comments

Comments
 (0)