├── .babelrc ├── .gitignore ├── .travis.yml ├── LICENSE ├── README.md ├── dist ├── vue-router-multiguard.min.js └── vue-router-multiguard.min.js.map ├── index.js ├── package.json ├── test └── test.js ├── types └── index.d.ts └── webpack.config.js /.babelrc: -------------------------------------------------------------------------------- 1 | { 2 | "presets": ["env"] 3 | } -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: node_js 2 | node_js: 3 | - "8" 4 | - "7" 5 | - "6" -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2017 Atanas Angelov 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Vue Router Multiguard [![Build Status](https://travis-ci.org/atanas-dev/vue-router-multiguard.svg?branch=master)](https://travis-ci.org/atanas-dev/vue-router-multiguard) 2 | 3 | Provides the ability to specify multiple guards for vue router routes. 4 | 5 | ## Installing 6 | 7 | `npm install vue-router-multiguard` 8 | 9 | ## Notes 10 | 11 | - Guards are executed serially in the order they are supplied, respecting asynchronous ones. 12 | - Guard execution will stop when all passed guards are executed OR when any guard calls `next()` with an argument other than `undefined`. 13 | - When a guard calls `next()` with an argument other than `undefined`, that argument will be passed to VueRouter. 14 | 15 | ## Usage 16 | 17 | `multiguard(function[] guards)` -> `function(to, from, next) {... }` 18 | 19 | ```js 20 | import VueRouter from 'vue-router'; 21 | import multiguard from 'vue-router-multiguard'; 22 | 23 | const guard1 = function(to, from, next) { 24 | setTimeout(function() { 25 | console.log('guard1 called'); 26 | next(); 27 | }, 1000); 28 | } 29 | 30 | const guard2 = function(to, from, next) { 31 | setTimeout(function() { 32 | console.log('guard2 called'); 33 | next(); 34 | }, 1000); 35 | } 36 | 37 | const router = new VueRouter({ 38 | routes: [ 39 | { 40 | name: 'home', 41 | path: '/', 42 | component: {}, 43 | beforeEnter: multiguard([guard1, guard2]), 44 | } 45 | ] 46 | }); 47 | ``` 48 | 49 | ## Running the tests 50 | 51 | `npm test` 52 | 53 | ## License 54 | 55 | This project is licensed under the MIT License - see the [LICENSE](LICENSE) file for details 56 | -------------------------------------------------------------------------------- /dist/vue-router-multiguard.min.js: -------------------------------------------------------------------------------- 1 | !function(t,r){"object"==typeof exports&&"object"==typeof module?module.exports=r():"function"==typeof define&&define.amd?define("VueRouterMultiguard",[],r):"object"==typeof exports?exports.VueRouterMultiguard=r():t.VueRouterMultiguard=r()}(this,function(){return function(t){function r(n){if(e[n])return e[n].exports;var o=e[n]={i:n,l:!1,exports:{}};return t[n].call(o.exports,o,o.exports,r),o.l=!0,o.exports}var e={};return r.m=t,r.c=e,r.d=function(t,e,n){r.o(t,e)||Object.defineProperty(t,e,{configurable:!1,enumerable:!0,get:n})},r.n=function(t){var e=t&&t.__esModule?function(){return t.default}:function(){return t};return r.d(e,"a",e),e},r.o=function(t,r){return Object.prototype.hasOwnProperty.call(t,r)},r.p="/dist/",r(r.s=0)}([function(t,r,e){"use strict";function n(t){return void 0===t}function o(t,r,e,u){var i=t.slice(0),f=i.shift();if(n(f))return void u();f(r,e,function(t){if(n(t))return void o(i,r,e,u);u(t)})}t.exports=function(t){if(!Array.isArray(t))throw new Error("You must specify an array of guards");return function(r,e,n){return o(t,r,e,n)}}}])}); 2 | //# sourceMappingURL=vue-router-multiguard.min.js.map -------------------------------------------------------------------------------- /dist/vue-router-multiguard.min.js.map: -------------------------------------------------------------------------------- 1 | {"version":3,"sources":["webpack:///webpack/universalModuleDefinition","webpack:///vue-router-multiguard.min.js","webpack:///webpack/bootstrap 822fcccc70c301c3d144","webpack:///./index.js"],"names":["root","factory","exports","module","define","amd","this","modules","__webpack_require__","moduleId","installedModules","i","l","call","m","c","d","name","getter","o","Object","defineProperty","configurable","enumerable","get","n","__esModule","object","property","prototype","hasOwnProperty","p","s","isUndefined","value","undefined","evaluateGuards","guards","to","from","next","guardsLeft","slice","nextGuard","shift","nextArg","Array","isArray","Error"],"mappings":"CAAA,SAAAA,EAAAC,GACA,gBAAAC,UAAA,gBAAAC,QACAA,OAAAD,QAAAD,IACA,kBAAAG,gBAAAC,IACAD,OAAA,yBAAAH,GACA,gBAAAC,SACAA,QAAA,oBAAAD,IAEAD,EAAA,oBAAAC,KACCK,KAAA,WACD,MCAgB,UAAUC,GCN1B,QAAAC,GAAAC,GAGA,GAAAC,EAAAD,GACA,MAAAC,GAAAD,GAAAP,OAGA,IAAAC,GAAAO,EAAAD,IACAE,EAAAF,EACAG,GAAA,EACAV,WAUA,OANAK,GAAAE,GAAAI,KAAAV,EAAAD,QAAAC,IAAAD,QAAAM,GAGAL,EAAAS,GAAA,EAGAT,EAAAD,QAvBA,GAAAQ,KA4DA,OAhCAF,GAAAM,EAAAP,EAGAC,EAAAO,EAAAL,EAGAF,EAAAQ,EAAA,SAAAd,EAAAe,EAAAC,GACAV,EAAAW,EAAAjB,EAAAe,IACAG,OAAAC,eAAAnB,EAAAe,GACAK,cAAA,EACAC,YAAA,EACAC,IAAAN,KAMAV,EAAAiB,EAAA,SAAAtB,GACA,GAAAe,GAAAf,KAAAuB,WACA,WAA2B,MAAAvB,GAAA,SAC3B,WAAiC,MAAAA,GAEjC,OADAK,GAAAQ,EAAAE,EAAA,IAAAA,GACAA,GAIAV,EAAAW,EAAA,SAAAQ,EAAAC,GAAsD,MAAAR,QAAAS,UAAAC,eAAAjB,KAAAc,EAAAC,IAGtDpB,EAAAuB,EAAA,SAGAvB,IAAAwB,EAAA,KDgBM,SAAU7B,EAAQD,EAASM,GAEjC,YE/EA,SAASyB,GAAYC,GACjB,WAAiBC,KAAVD,EAGX,QAASE,GAAeC,EAAQC,EAAIC,EAAMC,GACtC,GAAMC,GAAaJ,EAAOK,MAAM,GAC1BC,EAAYF,EAAWG,OAE7B,IAAIX,EAAYU,GAEZ,WADAH,IAIJG,GAAUL,EAAIC,EAAM,SAACM,GACjB,GAAIZ,EAAYY,GAEZ,WADAT,GAAeK,EAAYH,EAAIC,EAAMC,EAIzCA,GAAKK,KAIb1C,EAAOD,QAAU,SAASmC,GACtB,IAAKS,MAAMC,QAAQV,GACf,KAAM,IAAIW,OAAM,sCAGpB,OAAO,UAACV,EAAIC,EAAMC,GACd,MAAOJ,GAAeC,EAAQC,EAAIC,EAAMC","file":"vue-router-multiguard.min.js","sourcesContent":["(function webpackUniversalModuleDefinition(root, factory) {\n\tif(typeof exports === 'object' && typeof module === 'object')\n\t\tmodule.exports = factory();\n\telse if(typeof define === 'function' && define.amd)\n\t\tdefine(\"VueRouterMultiguard\", [], factory);\n\telse if(typeof exports === 'object')\n\t\texports[\"VueRouterMultiguard\"] = factory();\n\telse\n\t\troot[\"VueRouterMultiguard\"] = factory();\n})(this, function() {\nreturn \n\n\n// WEBPACK FOOTER //\n// webpack/universalModuleDefinition","(function webpackUniversalModuleDefinition(root, factory) {\n\tif(typeof exports === 'object' && typeof module === 'object')\n\t\tmodule.exports = factory();\n\telse if(typeof define === 'function' && define.amd)\n\t\tdefine(\"VueRouterMultiguard\", [], factory);\n\telse if(typeof exports === 'object')\n\t\texports[\"VueRouterMultiguard\"] = factory();\n\telse\n\t\troot[\"VueRouterMultiguard\"] = factory();\n})(this, function() {\nreturn /******/ (function(modules) { // webpackBootstrap\n/******/ \t// The module cache\n/******/ \tvar installedModules = {};\n/******/\n/******/ \t// The require function\n/******/ \tfunction __webpack_require__(moduleId) {\n/******/\n/******/ \t\t// Check if module is in cache\n/******/ \t\tif(installedModules[moduleId]) {\n/******/ \t\t\treturn installedModules[moduleId].exports;\n/******/ \t\t}\n/******/ \t\t// Create a new module (and put it into the cache)\n/******/ \t\tvar module = installedModules[moduleId] = {\n/******/ \t\t\ti: moduleId,\n/******/ \t\t\tl: false,\n/******/ \t\t\texports: {}\n/******/ \t\t};\n/******/\n/******/ \t\t// Execute the module function\n/******/ \t\tmodules[moduleId].call(module.exports, module, module.exports, __webpack_require__);\n/******/\n/******/ \t\t// Flag the module as loaded\n/******/ \t\tmodule.l = true;\n/******/\n/******/ \t\t// Return the exports of the module\n/******/ \t\treturn module.exports;\n/******/ \t}\n/******/\n/******/\n/******/ \t// expose the modules object (__webpack_modules__)\n/******/ \t__webpack_require__.m = modules;\n/******/\n/******/ \t// expose the module cache\n/******/ \t__webpack_require__.c = installedModules;\n/******/\n/******/ \t// define getter function for harmony exports\n/******/ \t__webpack_require__.d = function(exports, name, getter) {\n/******/ \t\tif(!__webpack_require__.o(exports, name)) {\n/******/ \t\t\tObject.defineProperty(exports, name, {\n/******/ \t\t\t\tconfigurable: false,\n/******/ \t\t\t\tenumerable: true,\n/******/ \t\t\t\tget: getter\n/******/ \t\t\t});\n/******/ \t\t}\n/******/ \t};\n/******/\n/******/ \t// getDefaultExport function for compatibility with non-harmony modules\n/******/ \t__webpack_require__.n = function(module) {\n/******/ \t\tvar getter = module && module.__esModule ?\n/******/ \t\t\tfunction getDefault() { return module['default']; } :\n/******/ \t\t\tfunction getModuleExports() { return module; };\n/******/ \t\t__webpack_require__.d(getter, 'a', getter);\n/******/ \t\treturn getter;\n/******/ \t};\n/******/\n/******/ \t// Object.prototype.hasOwnProperty.call\n/******/ \t__webpack_require__.o = function(object, property) { return Object.prototype.hasOwnProperty.call(object, property); };\n/******/\n/******/ \t// __webpack_public_path__\n/******/ \t__webpack_require__.p = \"/dist/\";\n/******/\n/******/ \t// Load entry module and return exports\n/******/ \treturn __webpack_require__(__webpack_require__.s = 0);\n/******/ })\n/************************************************************************/\n/******/ ([\n/* 0 */\n/***/ (function(module, exports, __webpack_require__) {\n\n\"use strict\";\n\n\nfunction isUndefined(value) {\n return value === undefined;\n}\n\nfunction evaluateGuards(guards, to, from, next) {\n var guardsLeft = guards.slice(0); // clone the array so we do not accidentally modify it\n var nextGuard = guardsLeft.shift();\n\n if (isUndefined(nextGuard)) {\n next();\n return;\n }\n\n nextGuard(to, from, function (nextArg) {\n if (isUndefined(nextArg)) {\n evaluateGuards(guardsLeft, to, from, next);\n return;\n }\n\n next(nextArg);\n });\n}\n\nmodule.exports = function (guards) {\n if (!Array.isArray(guards)) {\n throw new Error('You must specify an array of guards');\n }\n\n return function (to, from, next) {\n return evaluateGuards(guards, to, from, next);\n };\n};\n\n/***/ })\n/******/ ]);\n});\n\n\n// WEBPACK FOOTER //\n// vue-router-multiguard.min.js"," \t// The module cache\n \tvar installedModules = {};\n\n \t// The require function\n \tfunction __webpack_require__(moduleId) {\n\n \t\t// Check if module is in cache\n \t\tif(installedModules[moduleId]) {\n \t\t\treturn installedModules[moduleId].exports;\n \t\t}\n \t\t// Create a new module (and put it into the cache)\n \t\tvar module = installedModules[moduleId] = {\n \t\t\ti: moduleId,\n \t\t\tl: false,\n \t\t\texports: {}\n \t\t};\n\n \t\t// Execute the module function\n \t\tmodules[moduleId].call(module.exports, module, module.exports, __webpack_require__);\n\n \t\t// Flag the module as loaded\n \t\tmodule.l = true;\n\n \t\t// Return the exports of the module\n \t\treturn module.exports;\n \t}\n\n\n \t// expose the modules object (__webpack_modules__)\n \t__webpack_require__.m = modules;\n\n \t// expose the module cache\n \t__webpack_require__.c = installedModules;\n\n \t// define getter function for harmony exports\n \t__webpack_require__.d = function(exports, name, getter) {\n \t\tif(!__webpack_require__.o(exports, name)) {\n \t\t\tObject.defineProperty(exports, name, {\n \t\t\t\tconfigurable: false,\n \t\t\t\tenumerable: true,\n \t\t\t\tget: getter\n \t\t\t});\n \t\t}\n \t};\n\n \t// getDefaultExport function for compatibility with non-harmony modules\n \t__webpack_require__.n = function(module) {\n \t\tvar getter = module && module.__esModule ?\n \t\t\tfunction getDefault() { return module['default']; } :\n \t\t\tfunction getModuleExports() { return module; };\n \t\t__webpack_require__.d(getter, 'a', getter);\n \t\treturn getter;\n \t};\n\n \t// Object.prototype.hasOwnProperty.call\n \t__webpack_require__.o = function(object, property) { return Object.prototype.hasOwnProperty.call(object, property); };\n\n \t// __webpack_public_path__\n \t__webpack_require__.p = \"/dist/\";\n\n \t// Load entry module and return exports\n \treturn __webpack_require__(__webpack_require__.s = 0);\n\n\n\n// WEBPACK FOOTER //\n// webpack/bootstrap 822fcccc70c301c3d144","function isUndefined(value) {\r\n return value === undefined;\r\n}\r\n\r\nfunction evaluateGuards(guards, to, from, next) {\r\n const guardsLeft = guards.slice(0); // clone the array so we do not accidentally modify it\r\n const nextGuard = guardsLeft.shift();\r\n\r\n if (isUndefined(nextGuard)) {\r\n next();\r\n return;\r\n }\r\n\r\n nextGuard(to, from, (nextArg) => {\r\n if (isUndefined(nextArg)) {\r\n evaluateGuards(guardsLeft, to, from, next);\r\n return;\r\n }\r\n\r\n next(nextArg);\r\n });\r\n}\r\n\r\nmodule.exports = function(guards) {\r\n if (!Array.isArray(guards)) {\r\n throw new Error('You must specify an array of guards');\r\n }\r\n\r\n return (to, from, next) => {\r\n return evaluateGuards(guards, to, from, next);\r\n };\r\n}\r\n\n\n\n// WEBPACK FOOTER //\n// ./index.js"],"sourceRoot":""} -------------------------------------------------------------------------------- /index.js: -------------------------------------------------------------------------------- 1 | function isUndefined(value) { 2 | return value === undefined; 3 | } 4 | 5 | function evaluateGuards(guards, to, from, next) { 6 | const guardsLeft = guards.slice(0); // clone the array so we do not accidentally modify it 7 | const nextGuard = guardsLeft.shift(); 8 | 9 | if (isUndefined(nextGuard)) { 10 | next(); 11 | return; 12 | } 13 | 14 | nextGuard(to, from, (nextArg) => { 15 | if (isUndefined(nextArg)) { 16 | evaluateGuards(guardsLeft, to, from, next); 17 | return; 18 | } 19 | 20 | next(nextArg); 21 | }); 22 | } 23 | 24 | module.exports = function(guards) { 25 | if (!Array.isArray(guards)) { 26 | throw new Error('You must specify an array of guards'); 27 | } 28 | 29 | return (to, from, next) => { 30 | return evaluateGuards(guards, to, from, next); 31 | }; 32 | } 33 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "vue-router-multiguard", 3 | "version": "1.0.3", 4 | "description": "Provides the ability to specify multiple guards for vue routes", 5 | "repository": { 6 | "type": "git", 7 | "url": "https://github.com/atanas-angelov-dev/vue-router-multiguard.git" 8 | }, 9 | "main": "dist/vue-router-multiguard.min.js", 10 | "scripts": { 11 | "test": "mocha", 12 | "build": "webpack" 13 | }, 14 | "keywords": [ 15 | "vue-router", 16 | "vue-router-guard", 17 | "guard", 18 | "multiple-guard" 19 | ], 20 | "author": "Atanas Angelov ", 21 | "license": "MIT", 22 | "devDependencies": { 23 | "babel-core": "^6.26.0", 24 | "babel-loader": "^7.1.2", 25 | "babel-preset-env": "^1.6.1", 26 | "mocha": "^3.5.0", 27 | "webpack": "^3.8.1" 28 | }, 29 | "typings": "types/index.d.ts" 30 | } 31 | -------------------------------------------------------------------------------- /test/test.js: -------------------------------------------------------------------------------- 1 | const assert = require('assert'); 2 | const multiguard = require('../index.js'); 3 | 4 | describe('multiguard(guards)', function() { 5 | it('should throw an error when the argument is not an array', function(done) { 6 | assert.throws(() => multiguard({}), Error, 'You must specify an array of guards'); 7 | done(); 8 | }); 9 | 10 | describe('should call next with', function() { 11 | it('undefined when the argument is an empty array', function(done) { 12 | const guard = multiguard([]) 13 | guard(null, null, (nextArg) => { 14 | assert.equal(nextArg, undefined); 15 | done(); 16 | }); 17 | }); 18 | 19 | it('undefined when the only guard calls next with undefined', function(done) { 20 | const guard = multiguard([ 21 | (to, from, next) => next(), 22 | ]); 23 | guard(null, null, (nextArg) => { 24 | assert.equal(nextArg, undefined); 25 | done(); 26 | }); 27 | }); 28 | 29 | it('whatever value the only guard calls next with', function(done) { 30 | const expected = {name: 'example.route.name'}; 31 | const guard = multiguard([ 32 | (to, from, next) => next(expected), 33 | ]); 34 | guard(null, null, (nextArg) => { 35 | assert.equal(nextArg, expected); 36 | done(); 37 | }); 38 | }); 39 | 40 | it('undefined when all guards pass', function(done) { 41 | const guard = multiguard([ 42 | (to, from, next) => next(), 43 | (to, from, next) => next(), 44 | ]); 45 | guard(null, null, (nextArg) => { 46 | assert.equal(nextArg, undefined); 47 | done(); 48 | }); 49 | }); 50 | 51 | it('the value of the first guard when it is not undefined', function(done) { 52 | const expected = {name: 'example.route.name'}; 53 | const guard = multiguard([ 54 | (to, from, next) => next(expected), 55 | (to, from, next) => next(), 56 | ]); 57 | guard(null, null, (nextArg) => { 58 | assert.equal(nextArg, expected); 59 | done(); 60 | }); 61 | }); 62 | 63 | it('the value of the second guard when it is not undefined', function(done) { 64 | const expected = {name: 'example.route.name'}; 65 | const guard = multiguard([ 66 | (to, from, next) => next(), 67 | (to, from, next) => next(expected), 68 | ]); 69 | guard(null, null, (nextArg) => { 70 | assert.equal(nextArg, expected); 71 | done(); 72 | }); 73 | }); 74 | 75 | it('the value of the first guard to call next with a non-undefined value', function(done) { 76 | const expected = {name: 'example.route.name'}; 77 | const unexpected = {name: 'example.route.name.2'}; 78 | const guard = multiguard([ 79 | (to, from, next) => next(), 80 | (to, from, next) => next(expected), 81 | (to, from, next) => next(unexpected), 82 | ]); 83 | guard(null, null, (nextArg) => { 84 | assert.equal(nextArg, expected); 85 | done(); 86 | }); 87 | }); 88 | }); 89 | 90 | it('should not call the second guard when the first guard calls next with a non-undefined value', function(done) { 91 | const expected = {name: 'example.route.name'}; 92 | const guard = multiguard([ 93 | (to, from, next) => next(expected), 94 | (to, from, next) => assert.fail('Second guard called when it shouldn\'t have been'), 95 | ]); 96 | guard(null, null, (nextArg) => { 97 | assert.equal(nextArg, expected); 98 | done(); 99 | }); 100 | }); 101 | }); -------------------------------------------------------------------------------- /types/index.d.ts: -------------------------------------------------------------------------------- 1 | import { NavigationGuard } from 'vue-router'; 2 | 3 | export default function Multiguard(guards: Array): NavigationGuard; 4 | -------------------------------------------------------------------------------- /webpack.config.js: -------------------------------------------------------------------------------- 1 | var path = require('path') 2 | var webpack = require('webpack') 3 | 4 | module.exports = { 5 | entry: { 6 | 'vue-router-multiguard': './index.js', 7 | }, 8 | output: { 9 | path: path.resolve(__dirname, './dist'), 10 | publicPath: '/dist/', 11 | filename: 'vue-router-multiguard.min.js', 12 | library: 'VueRouterMultiguard', 13 | libraryTarget: 'umd', 14 | umdNamedDefine: true 15 | }, 16 | module: { 17 | rules: [{ 18 | test: /\.js$/, 19 | loader: 'babel-loader', 20 | exclude: /node_modules/ 21 | }] 22 | }, 23 | plugins: [ 24 | new webpack.LoaderOptionsPlugin({ 25 | minimize: true, 26 | debug: false 27 | }), 28 | new webpack.optimize.UglifyJsPlugin({ 29 | sourceMap: true, 30 | include: /\.min\.js$/, 31 | compress: { 32 | warnings: false 33 | } 34 | }) 35 | ], 36 | devtool: 'source-map' 37 | } 38 | --------------------------------------------------------------------------------