├── .babelrc
├── .editorconfig
├── .eslintignore
├── .eslintrc
├── .gitignore
├── .prettierrc.json
├── .tern-project
├── .vscode
└── settings.json
├── CODE_OF_CONDUCT.md
├── README.md
├── bower.json
├── build
└── build.rollup.js
├── dist
├── vue-authenticate.common.js
├── vue-authenticate.esm.js
├── vue-authenticate.js
└── vue-authenticate.min.js
├── package-lock.json
├── package.json
├── src
├── authenticate.js
├── globals.js
├── index.js
├── oauth
│ ├── oauth1.js
│ ├── oauth2.js
│ └── popup.js
├── options.js
├── promise.js
├── storage.js
├── storage
│ ├── cookie-storage.js
│ ├── local-storage.js
│ ├── memory-storage.js
│ └── session-storage.js
└── utils.js
└── yarn.lock
/.babelrc:
--------------------------------------------------------------------------------
1 | {
2 | "presets": [
3 | [
4 | "@babel/preset-env",
5 | {
6 | "modules": false
7 | }
8 | ]
9 | ],
10 | "plugins": ["external-helpers"]
11 | }
--------------------------------------------------------------------------------
/.editorconfig:
--------------------------------------------------------------------------------
1 | # http://editorconfig.org
2 |
3 | root = true
4 |
5 | [*]
6 | charset = utf-8
7 | indent_style = space
8 | indent_size = 2
9 | end_of_line = lf
10 | insert_final_newline = true
11 | trim_trailing_whitespace = true
12 |
13 | [*.md]
14 | insert_final_newline = false
15 | trim_trailing_whitespace = false
16 |
--------------------------------------------------------------------------------
/.eslintignore:
--------------------------------------------------------------------------------
1 | flow
2 | dist
3 | packages
4 |
--------------------------------------------------------------------------------
/.eslintrc:
--------------------------------------------------------------------------------
1 | {
2 | "root": true,
3 | "parser": "babel-eslint",
4 | "parserOptions": {
5 | "sourceType": "module"
6 | },
7 | "env": {
8 | "browser": true,
9 | },
10 | "extends": "standard",
11 | "plugins": [
12 | "html"
13 | ],
14 | "rules": {
15 | "arrow-parens": 0,
16 | "generator-star-spacing': 0
17 | }
18 | }
19 |
20 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 |
2 | # Dependency directory
3 | node_modules
4 | bower_components
5 |
6 | Thumbs.db
7 | .DS_Store
8 |
9 | npm-debug.log*
10 | yarn-debug.log*
11 | yarn-error.log*
12 |
13 | # Editor directories and files
14 | .idea
15 | *.suo
16 | *.ntvs*
17 | *.njsproj
18 | *.sln
19 | *.iml
20 | .vscode
21 | settings.json
22 | jsconfig.json
23 |
--------------------------------------------------------------------------------
/.prettierrc.json:
--------------------------------------------------------------------------------
1 | {
2 | "trailingComma": "es5",
3 | "tabWidth": 2,
4 | "semi": true,
5 | "singleQuote": true,
6 | "useTabs": false,
7 | "printWidth": 80,
8 | "arrowParens": "avoid"
9 | }
10 |
--------------------------------------------------------------------------------
/.tern-project:
--------------------------------------------------------------------------------
1 | {
2 | "plugins": {
3 | "es_modules": {},
4 | "node": {}
5 | },
6 | "libs": [
7 | "ecma5",
8 | "ecma6",
9 | "react",
10 | "browser"
11 | ],
12 | "ecmaVersion": 6
13 | }
14 |
--------------------------------------------------------------------------------
/.vscode/settings.json:
--------------------------------------------------------------------------------
1 | {
2 | "eslint.enable": false
3 | }
--------------------------------------------------------------------------------
/CODE_OF_CONDUCT.md:
--------------------------------------------------------------------------------
1 | # Code of Conduct
2 |
3 | Don't be an asshole.
4 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | [**WARNING**]: README file is currently in process of rewrite and will be released soon.
2 |
3 | # vue-authenticate
4 |
5 | [](https://gitter.im/vuejs-auth/vue-authenticate?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
6 |
7 | **vue-authenticate** is easily configurable solution for [Vue.js](https://vuejs.org/) that provides local login/registration as well as Social login using Github, Facebook, Google and other OAuth providers.
8 |
9 |
10 |
11 | The best part about this library is that it is not strictly coupled to one request handling library like [vue-axios](https://github.com/imcvampire/vue-axios). You will be able to use it with different libraries.
12 |
13 | For now it is tested to work with [vue-resource](https://github.com/pagekit/vue-resource) and [axios](https://github.com/mzabriskie/axios) (using [vue-axios](https://github.com/imcvampire/vue-axios) wrapper).
14 |
15 | **WARNING:** From version 1.3.0 default request library is `axios` using `vue-axios` wrapper plugin.
16 |
17 | This library was inspired by well known authentication library for Angular called [Satellizer](https://github.com/sahat/satellizer) developed by [Sahat Yalkabov](http://sahatyalkabov.com). They share almost identical configuration and API so you can easily switch from Angular to Vue.js project.
18 |
19 | ## Supported OAuth providers and configurations
20 |
21 | 1. Facebook (https://github.com/dgrubelic/vue-authenticate/blob/master/src/options.js#L21)
22 | 2. Google (https://github.com/dgrubelic/vue-authenticate/blob/master/src/options.js#L34)
23 | 3. Github (https://github.com/dgrubelic/vue-authenticate/blob/master/src/options.js#L49)
24 | 4. Instagram (https://github.com/dgrubelic/vue-authenticate/blob/master/src/options.js#L61)
25 | 5. Twitter (https://github.com/dgrubelic/vue-authenticate/blob/master/src/options.js#L72)
26 | 6. Bitbucket (https://github.com/dgrubelic/vue-authenticate/blob/master/src/options.js#L81)
27 | 7. LinkedIn (https://github.com/dgrubelic/vue-authenticate/blob/master/src/options.js#L93)
28 | 8. Microsoft Live (https://github.com/dgrubelic/vue-authenticate/blob/master/src/options.js#L106)
29 |
30 | ## Installation
31 | ```bash
32 | npm install vue-authenticate
33 | ```
34 |
35 | ## Usage
36 | ```javascript
37 | import Vue from 'vue'
38 | import VueAxios from 'vue-axios'
39 | import VueAuthenticate from 'vue-authenticate'
40 | import axios from 'axios';
41 |
42 | Vue.use(VueAxios, axios)
43 | Vue.use(VueAuthenticate, {
44 | baseUrl: 'http://localhost:3000', // Your API domain
45 |
46 | providers: {
47 | github: {
48 | clientId: '',
49 | redirectUri: 'http://localhost:8080/auth/callback' // Your client app URL
50 | }
51 | }
52 | })
53 | ```
54 |
55 | ### Email & password login and registration
56 | ```javascript
57 | new Vue({
58 | methods: {
59 | login: function () {
60 | this.$auth.login({ email, password }).then(function () {
61 | // Execute application logic after successful login
62 | })
63 | },
64 |
65 | register: function () {
66 | this.$auth.register({ name, email, password }).then(function () {
67 | // Execute application logic after successful registration
68 | })
69 | }
70 | }
71 | })
72 | ```
73 |
74 | ```html
75 |
76 |
77 | ```
78 |
79 | ### Social account authentication
80 |
81 | ```javascript
82 | new Vue({
83 | methods: {
84 | authenticate: function (provider) {
85 | this.$auth.authenticate(provider).then(function () {
86 | // Execute application logic after successful social authentication
87 | })
88 | }
89 | }
90 | })
91 | ```
92 |
93 | ```html
94 |
95 |
96 |
97 |
98 | ```
99 |
100 | ### Vuex authentication
101 |
102 | #### Import and initialize all required libraries
103 |
104 | ```javascript
105 | // ES6 example
106 | import Vue from 'vue'
107 | import Vuex from 'vuex'
108 | import VueAxios from 'vue-axios'
109 | import { VueAuthenticate } from 'vue-authenticate'
110 | import axios from 'axios';
111 |
112 | Vue.use(Vuex)
113 | Vue.use(VueAxios, axios)
114 |
115 | const vueAuth = new VueAuthenticate(Vue.prototype.$http, {
116 | baseUrl: 'http://localhost:4000'
117 | })
118 | ```
119 |
120 | ```javascript
121 | // CommonJS example
122 | var Vue = require('vue')
123 | var Vuex = require('vuex')
124 | var VueAxios = require('vue-axios')
125 | var VueAuthenticate = require('vue-authenticate')
126 | var axios = require('axios');
127 |
128 | Vue.use(Vuex)
129 | Vue.use(VueAxios, axios)
130 |
131 | // ES5, CommonJS example
132 | var vueAuth = VueAuthenticate.factory(Vue.prototype.$http, {
133 | baseUrl: 'http://localhost:4000'
134 | })
135 | ```
136 |
137 | Once you have created VueAuthenticate instance, you can use it in Vuex store like this:
138 |
139 | ```javascript
140 | export default new Vuex.Store({
141 |
142 | // You can use it as state property
143 | state: {
144 | isAuthenticated: false
145 | },
146 |
147 | // You can use it as a state getter function (probably the best solution)
148 | getters: {
149 | isAuthenticated () {
150 | return vueAuth.isAuthenticated()
151 | }
152 | },
153 |
154 | // Mutation for when you use it as state property
155 | mutations: {
156 | isAuthenticated (state, payload) {
157 | state.isAuthenticated = payload.isAuthenticated
158 | }
159 | },
160 |
161 | actions: {
162 |
163 | // Perform VueAuthenticate login using Vuex actions
164 | login (context, payload) {
165 |
166 | vueAuth.login(payload.user, payload.requestOptions).then((response) => {
167 | context.commit('isAuthenticated', {
168 | isAuthenticated: vueAuth.isAuthenticated()
169 | })
170 | })
171 |
172 | }
173 | }
174 | })
175 | ```
176 |
177 | Later in Vue component, you can dispatch Vuex state action like this
178 |
179 | ```javascript
180 | // You define your store logic here
181 | import store from './store.js'
182 |
183 | new Vue({
184 | store,
185 |
186 | computed: {
187 | isAuthenticated: function () {
188 | return this.$store.getters.isAuthenticated()
189 | }
190 | },
191 |
192 | methods: {
193 | login () {
194 | this.$store.dispatch('login', { user, requestOptions })
195 | }
196 | }
197 | })
198 | ```
199 |
200 | ### Custom request and response interceptors
201 |
202 | You can easily setup custom request and response interceptors if you use different request handling library.
203 |
204 | **Important**: You must set both `request` and `response` interceptors at all times.
205 |
206 | ```javascript
207 |
208 | /**
209 | * This is example for request and response interceptors for axios library
210 | */
211 |
212 | Vue.use(VueAuthenticate, {
213 | bindRequestInterceptor: function () {
214 | this.$http.interceptors.request.use((config) => {
215 | if (this.isAuthenticated()) {
216 | config.headers['Authorization'] = [
217 | this.options.tokenType, this.getToken()
218 | ].join(' ')
219 | } else {
220 | delete config.headers['Authorization']
221 | }
222 | return config
223 | })
224 | },
225 |
226 | bindResponseInterceptor: function () {
227 | this.$http.interceptors.response.use((response) => {
228 | this.setToken(response)
229 | return response
230 | })
231 | }
232 | })
233 |
234 | ```
235 |
236 | ## License
237 |
238 | The MIT License (MIT)
239 |
240 | Copyright (c) 2017 Davor Grubelić
241 |
242 | Permission is hereby granted, free of charge, to any person obtaining a copy of
243 | this software and associated documentation files (the "Software"), to deal in
244 | the Software without restriction, including without limitation the rights to
245 | use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
246 | the Software, and to permit persons to whom the Software is furnished to do so,
247 | subject to the following conditions:
248 |
249 | The above copyright notice and this permission notice shall be included in all
250 | copies or substantial portions of the Software.
251 |
252 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
253 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
254 | FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
255 | COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
256 | IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
257 | CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
258 |
--------------------------------------------------------------------------------
/bower.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "vue-authenticate",
3 | "version": "1.5.0",
4 | "main": "dist/vue-authenticate.js",
5 | "homepage": "https://github.com/dgrubelic/vue-authenticate",
6 | "ignore": []
7 | }
8 |
--------------------------------------------------------------------------------
/build/build.rollup.js:
--------------------------------------------------------------------------------
1 | var fs = require('fs');
2 | var rollup = require('rollup');
3 | var uglify = require('uglify-js');
4 | var buble = require('@rollup/plugin-buble');
5 | var uglify = require('rollup-plugin-uglify').uglify;
6 | var rollupBanner = require('rollup-plugin-banner').default;
7 | var package = require('../package.json');
8 |
9 | var banner =
10 | 'vue-authenticate v' +
11 | package.version +
12 | '\n' +
13 | 'https://github.com/dgrubelic/vue-authenticate\n' +
14 | 'Released under the MIT License.\n';
15 |
16 | function buildSource(inputOptions, outputOptions) {
17 | rollup
18 | .rollup(inputOptions)
19 | .then(function (bundle) {
20 | return bundle.generate(outputOptions).then(function (output) {
21 | bundle.write(outputOptions);
22 | });
23 | })
24 | .catch(logError);
25 | }
26 |
27 | buildSource(
28 | {
29 | input: 'src/index.js',
30 | plugins: [buble(), rollupBanner(banner)],
31 | },
32 | {
33 | file: 'dist/vue-authenticate.js',
34 | format: 'umd',
35 | name: 'VueAuthenticate',
36 | }
37 | );
38 |
39 | buildSource(
40 | {
41 | input: 'src/index.js',
42 | plugins: [buble(), uglify(), rollupBanner(banner)],
43 | },
44 | {
45 | file: 'dist/vue-authenticate.min.js',
46 | format: 'umd',
47 | name: 'VueAuthenticate',
48 | }
49 | );
50 |
51 | buildSource(
52 | {
53 | input: 'src/index.js',
54 | plugins: [rollupBanner(banner)],
55 | },
56 | {
57 | file: 'dist/vue-authenticate.esm.js',
58 | format: 'es',
59 | }
60 | );
61 |
62 | buildSource(
63 | {
64 | input: 'src/index.js',
65 | plugins: [rollupBanner(banner)],
66 | },
67 | {
68 | file: 'dist/vue-authenticate.common.js',
69 | format: 'cjs',
70 | }
71 | );
72 |
73 | function logError(e) {
74 | console.error(e);
75 | }
76 |
77 | function getSize(code) {
78 | return (((code && code.length) || 0) / 1024).toFixed(2) + 'kb';
79 | }
80 |
81 | function blue(str) {
82 | return '\x1b[1m\x1b[34m' + str + '\x1b[39m\x1b[22m';
83 | }
84 |
--------------------------------------------------------------------------------
/dist/vue-authenticate.esm.js:
--------------------------------------------------------------------------------
1 | /**
2 | * vue-authenticate v1.5.0
3 | * https://github.com/dgrubelic/vue-authenticate
4 | * Released under the MIT License.
5 | *
6 | */
7 |
8 | if (typeof Object.assign != 'function') {
9 | Object.assign = function (target, varArgs) {
10 | if (target == null) {
11 | throw new TypeError('Cannot convert undefined or null to object');
12 | }
13 |
14 | var to = Object(target);
15 |
16 | for (var index = 1; index < arguments.length; index++) {
17 | var nextSource = arguments[index];
18 |
19 | if (nextSource != null) {
20 | // Skip over if undefined or null
21 | for (var nextKey in nextSource) {
22 | // Avoid bugs when hasOwnProperty is shadowed
23 | if (Object.prototype.hasOwnProperty.call(nextSource, nextKey)) {
24 | to[nextKey] = nextSource[nextKey];
25 | }
26 | }
27 | }
28 | }
29 | return to;
30 | };
31 | }
32 |
33 | function camelCase(name) {
34 | return name.replace(/([\:\-\_]+(.))/g, function (
35 | _,
36 | separator,
37 | letter,
38 | offset
39 | ) {
40 | return offset ? letter.toUpperCase() : letter;
41 | });
42 | }
43 |
44 | function isUndefined(value) {
45 | return typeof value === 'undefined';
46 | }
47 |
48 | function isObject(value) {
49 | return value !== null && typeof value === 'object';
50 | }
51 |
52 | function isString(value) {
53 | return typeof value === 'string';
54 | }
55 |
56 | function isFunction(value) {
57 | return typeof value === 'function';
58 | }
59 |
60 | function objectExtend(a, b) {
61 | // Don't touch 'null' or 'undefined' objects.
62 | if (a == null || b == null) {
63 | return a;
64 | }
65 |
66 | Object.keys(b).forEach(function (key) {
67 | if (Object.prototype.toString.call(b[key]) == '[object Object]') {
68 | if (Object.prototype.toString.call(a[key]) != '[object Object]') {
69 | a[key] = b[key];
70 | } else {
71 | a[key] = objectExtend(a[key], b[key]);
72 | }
73 | } else {
74 | a[key] = b[key];
75 | }
76 | });
77 |
78 | return a;
79 | }
80 |
81 | /**
82 | * Assemble url from two segments
83 | *
84 | * @author Sahat Yalkabov
85 | * @copyright Method taken from https://github.com/sahat/satellizer
86 | *
87 | * @param {String} baseUrl Base url
88 | * @param {String} url URI
89 | * @return {String}
90 | */
91 | function joinUrl(baseUrl, url) {
92 | if (/^(?:[a-z]+:)?\/\//i.test(url)) {
93 | return url;
94 | }
95 | let joined = [baseUrl, url].join('/');
96 | let normalize = function (str) {
97 | return str
98 | .replace(/[\/]+/g, '/')
99 | .replace(/\/\?/g, '?')
100 | .replace(/\/\#/g, '#')
101 | .replace(/\:\//g, '://');
102 | };
103 | return normalize(joined);
104 | }
105 |
106 | /**
107 | * Get full path based on current location
108 | *
109 | * @author Sahat Yalkabov
110 | * @copyright Method taken from https://github.com/sahat/satellizer
111 | *
112 | * @param {Location} location
113 | * @return {String}
114 | */
115 | function getFullUrlPath(location) {
116 | const isHttps = location.protocol === 'https:';
117 | return (
118 | location.protocol +
119 | '//' +
120 | location.hostname +
121 | ':' +
122 | (location.port || (isHttps ? '443' : '80')) +
123 | (/^\//.test(location.pathname)
124 | ? location.pathname
125 | : '/' + location.pathname)
126 | );
127 | }
128 |
129 | /**
130 | * Parse query string variables
131 | *
132 | * @author Sahat Yalkabov
133 | * @copyright Method taken from https://github.com/sahat/satellizer
134 | *
135 | * @param {String} Query string
136 | * @return {String}
137 | */
138 | function parseQueryString(str) {
139 | let obj = {};
140 | let key;
141 | let value;
142 | (str || '').split('&').forEach(keyValue => {
143 | if (keyValue) {
144 | value = keyValue.split('=');
145 | key = decodeURIComponent(value[0]);
146 | obj[key] = !!value[1] ? decodeURIComponent(value[1]) : true;
147 | }
148 | });
149 | return obj;
150 | }
151 |
152 | /**
153 | * Decode base64 string
154 | * @author Sahat Yalkabov
155 | * @copyright Method taken from https://github.com/sahat/satellizer
156 | *
157 | * @param {String} str base64 encoded string
158 | * @return {Object}
159 | */
160 | function decodeBase64(str) {
161 | let buffer;
162 | if (typeof module !== 'undefined' && module.exports) {
163 | try {
164 | buffer = require('buffer').Buffer;
165 | } catch (err) {
166 | // noop
167 | }
168 | }
169 |
170 | let fromCharCode = String.fromCharCode;
171 |
172 | let re_btou = new RegExp(
173 | [
174 | '[\xC0-\xDF][\x80-\xBF]',
175 | '[\xE0-\xEF][\x80-\xBF]{2}',
176 | '[\xF0-\xF7][\x80-\xBF]{3}',
177 | ].join('|'),
178 | 'g'
179 | );
180 |
181 | let cb_btou = function (cccc) {
182 | switch (cccc.length) {
183 | case 4:
184 | let cp =
185 | ((0x07 & cccc.charCodeAt(0)) << 18) |
186 | ((0x3f & cccc.charCodeAt(1)) << 12) |
187 | ((0x3f & cccc.charCodeAt(2)) << 6) |
188 | (0x3f & cccc.charCodeAt(3));
189 | let offset = cp - 0x10000;
190 | return (
191 | fromCharCode((offset >>> 10) + 0xd800) +
192 | fromCharCode((offset & 0x3ff) + 0xdc00)
193 | );
194 | case 3:
195 | return fromCharCode(
196 | ((0x0f & cccc.charCodeAt(0)) << 12) |
197 | ((0x3f & cccc.charCodeAt(1)) << 6) |
198 | (0x3f & cccc.charCodeAt(2))
199 | );
200 | default:
201 | return fromCharCode(
202 | ((0x1f & cccc.charCodeAt(0)) << 6) | (0x3f & cccc.charCodeAt(1))
203 | );
204 | }
205 | };
206 |
207 | let btou = function (b) {
208 | return b.replace(re_btou, cb_btou);
209 | };
210 |
211 | let _decode = buffer
212 | ? function (a) {
213 | return (a.constructor === buffer.constructor
214 | ? a
215 | : new buffer(a, 'base64')
216 | ).toString();
217 | }
218 | : function (a) {
219 | return btou(atob(a));
220 | };
221 |
222 | return _decode(
223 | String(str)
224 | .replace(/[-_]/g, function (m0) {
225 | return m0 === '-' ? '+' : '/';
226 | })
227 | .replace(/[^A-Za-z0-9\+\/]/g, '')
228 | );
229 | }
230 |
231 | function parseCookies(str = '') {
232 | if (str.length === 0) return {};
233 | const parsed = {};
234 | const pattern = new RegExp('\\s*;\\s*');
235 | str.split(pattern).forEach(i => {
236 | const [encodedKey, encodedValue] = i.split('=');
237 | const key = decodeURIComponent(encodedKey);
238 | const value = decodeURIComponent(encodedValue);
239 | parsed[key] = value;
240 | });
241 | return parsed;
242 | }
243 |
244 | function formatOptions(options) {
245 | const { path, domain, expires, secure } = options;
246 | return [
247 | typeof path === 'undefined' || path === null ? '' : ';path=' + path,
248 | typeof domain === 'undefined' || domain === null ? '' : ';domain=' + domain,
249 | typeof expires === 'undefined' || expires === null
250 | ? ''
251 | : ';expires=' + expires.toUTCString(),
252 | typeof secure === 'undefined' || secure === null || secure === false
253 | ? ''
254 | : ';secure',
255 | ].join('');
256 | }
257 |
258 | function formatCookie(key, value, options) {
259 | return [
260 | encodeURIComponent(key),
261 | '=',
262 | encodeURIComponent(value),
263 | formatOptions(options),
264 | ].join('');
265 | }
266 |
267 | function getObjectProperty(objectRef, propertyName) {
268 | let value = undefined;
269 | let valueRef = objectRef;
270 | const propNames = propertyName.split('.');
271 |
272 | for (var i = 0; i < propNames.length; i++) {
273 | const key = propNames[i];
274 | value = valueRef[key];
275 |
276 | if (isObject(value)) {
277 | valueRef = valueRef[key];
278 | } else {
279 | break;
280 | }
281 | }
282 |
283 | return value;
284 | }
285 |
286 | // Store setTimeout reference so promise-polyfill will be unaffected by
287 | // other code modifying setTimeout (like sinon.useFakeTimers())
288 | var setTimeoutFunc = setTimeout;
289 |
290 | function noop() {}
291 |
292 | // Polyfill for Function.prototype.bind
293 | function bind(fn, thisArg) {
294 | return function () {
295 | fn.apply(thisArg, arguments);
296 | };
297 | }
298 |
299 | function Promise$1(fn) {
300 | if (typeof this !== 'object')
301 | throw new TypeError('Promises must be constructed via new');
302 | if (typeof fn !== 'function') throw new TypeError('not a function');
303 | this._state = 0;
304 | this._handled = false;
305 | this._value = undefined;
306 | this._deferreds = [];
307 |
308 | doResolve(fn, this);
309 | }
310 |
311 | function handle(self, deferred) {
312 | while (self._state === 3) {
313 | self = self._value;
314 | }
315 | if (self._state === 0) {
316 | self._deferreds.push(deferred);
317 | return;
318 | }
319 | self._handled = true;
320 | Promise$1._immediateFn(function () {
321 | var cb = self._state === 1 ? deferred.onFulfilled : deferred.onRejected;
322 | if (cb === null) {
323 | (self._state === 1 ? resolve : reject)(deferred.promise, self._value);
324 | return;
325 | }
326 | var ret;
327 | try {
328 | ret = cb(self._value);
329 | } catch (e) {
330 | reject(deferred.promise, e);
331 | return;
332 | }
333 | resolve(deferred.promise, ret);
334 | });
335 | }
336 |
337 | function resolve(self, newValue) {
338 | try {
339 | // Promise Resolution Procedure: https://github.com/promises-aplus/promises-spec#the-promise-resolution-procedure
340 | if (newValue === self)
341 | throw new TypeError('A promise cannot be resolved with itself.');
342 | if (
343 | newValue &&
344 | (typeof newValue === 'object' || typeof newValue === 'function')
345 | ) {
346 | var then = newValue.then;
347 | if (newValue instanceof Promise$1) {
348 | self._state = 3;
349 | self._value = newValue;
350 | finale(self);
351 | return;
352 | } else if (typeof then === 'function') {
353 | doResolve(bind(then, newValue), self);
354 | return;
355 | }
356 | }
357 | self._state = 1;
358 | self._value = newValue;
359 | finale(self);
360 | } catch (e) {
361 | reject(self, e);
362 | }
363 | }
364 |
365 | function reject(self, newValue) {
366 | self._state = 2;
367 | self._value = newValue;
368 | finale(self);
369 | }
370 |
371 | function finale(self) {
372 | if (self._state === 2 && self._deferreds.length === 0) {
373 | Promise$1._immediateFn(function () {
374 | if (!self._handled) {
375 | Promise$1._unhandledRejectionFn(self._value);
376 | }
377 | });
378 | }
379 |
380 | for (var i = 0, len = self._deferreds.length; i < len; i++) {
381 | handle(self, self._deferreds[i]);
382 | }
383 | self._deferreds = null;
384 | }
385 |
386 | function Handler(onFulfilled, onRejected, promise) {
387 | this.onFulfilled = typeof onFulfilled === 'function' ? onFulfilled : null;
388 | this.onRejected = typeof onRejected === 'function' ? onRejected : null;
389 | this.promise = promise;
390 | }
391 |
392 | /**
393 | * Take a potentially misbehaving resolver function and make sure
394 | * onFulfilled and onRejected are only called once.
395 | *
396 | * Makes no guarantees about asynchrony.
397 | */
398 | function doResolve(fn, self) {
399 | var done = false;
400 | try {
401 | fn(
402 | function (value) {
403 | if (done) return;
404 | done = true;
405 | resolve(self, value);
406 | },
407 | function (reason) {
408 | if (done) return;
409 | done = true;
410 | reject(self, reason);
411 | }
412 | );
413 | } catch (ex) {
414 | if (done) return;
415 | done = true;
416 | reject(self, ex);
417 | }
418 | }
419 |
420 | Promise$1.prototype['catch'] = function (onRejected) {
421 | return this.then(null, onRejected);
422 | };
423 |
424 | Promise$1.prototype.then = function (onFulfilled, onRejected) {
425 | var prom = new this.constructor(noop);
426 |
427 | handle(this, new Handler(onFulfilled, onRejected, prom));
428 | return prom;
429 | };
430 |
431 | Promise$1.all = function (arr) {
432 | var args = Array.prototype.slice.call(arr);
433 |
434 | return new Promise$1(function (resolve, reject) {
435 | if (args.length === 0) return resolve([]);
436 | var remaining = args.length;
437 |
438 | function res(i, val) {
439 | try {
440 | if (val && (typeof val === 'object' || typeof val === 'function')) {
441 | var then = val.then;
442 | if (typeof then === 'function') {
443 | then.call(
444 | val,
445 | function (val) {
446 | res(i, val);
447 | },
448 | reject
449 | );
450 | return;
451 | }
452 | }
453 | args[i] = val;
454 | if (--remaining === 0) {
455 | resolve(args);
456 | }
457 | } catch (ex) {
458 | reject(ex);
459 | }
460 | }
461 |
462 | for (var i = 0; i < args.length; i++) {
463 | res(i, args[i]);
464 | }
465 | });
466 | };
467 |
468 | Promise$1.resolve = function (value) {
469 | if (value && typeof value === 'object' && value.constructor === Promise$1) {
470 | return value;
471 | }
472 |
473 | return new Promise$1(function (resolve) {
474 | resolve(value);
475 | });
476 | };
477 |
478 | Promise$1.reject = function (value) {
479 | return new Promise$1(function (resolve, reject) {
480 | reject(value);
481 | });
482 | };
483 |
484 | Promise$1.race = function (values) {
485 | return new Promise$1(function (resolve, reject) {
486 | for (var i = 0, len = values.length; i < len; i++) {
487 | values[i].then(resolve, reject);
488 | }
489 | });
490 | };
491 |
492 | // Use polyfill for setImmediate for performance gains
493 | Promise$1._immediateFn =
494 | (typeof setImmediate === 'function' &&
495 | function (fn) {
496 | setImmediate(fn);
497 | }) ||
498 | function (fn) {
499 | setTimeoutFunc(fn, 0);
500 | };
501 |
502 | Promise$1._unhandledRejectionFn = function _unhandledRejectionFn(err) {
503 | if (typeof console !== 'undefined' && console) {
504 | console.warn('Possible Unhandled Promise Rejection:', err); // eslint-disable-line no-console
505 | }
506 | };
507 |
508 | /**
509 | * Set the immediate function to execute callbacks
510 | * @param fn {function} Function to execute
511 | * @deprecated
512 | */
513 | Promise$1._setImmediateFn = function _setImmediateFn(fn) {
514 | Promise$1._immediateFn = fn;
515 | };
516 |
517 | /**
518 | * Change the function to execute on unhandled rejection
519 | * @param {function} fn Function to execute on unhandled rejection
520 | * @deprecated
521 | */
522 | Promise$1._setUnhandledRejectionFn = function _setUnhandledRejectionFn(fn) {
523 | Promise$1._unhandledRejectionFn = fn;
524 | };
525 |
526 | const fakeDocument = {
527 | createElement() { },
528 | };
529 |
530 | const fakeWindow = {
531 | atob() { },
532 | open() { },
533 | location: {},
534 | localStorage: {
535 | setItem() { },
536 | getItem() { },
537 | removeItem() { },
538 | },
539 | sessionStorage: {
540 | setItem() { },
541 | getItem() { },
542 | removeItem() { },
543 | },
544 | };
545 |
546 | const $document = (typeof document !== undefined)
547 | ? document
548 | : fakeDocument;
549 |
550 | const $window = (typeof window !== undefined)
551 | ? window
552 | : fakeWindow;
553 |
554 | function getCookieDomainUrl() {
555 | try {
556 | return $window.location.hostname;
557 | } catch (e) {}
558 |
559 | return '';
560 | }
561 |
562 | function getRedirectUri(uri) {
563 | try {
564 | return !isUndefined(uri)
565 | ? `${$window.location.origin}${uri}`
566 | : $window.location.origin;
567 | } catch (e) {}
568 |
569 | return uri || null;
570 | }
571 |
572 | /**
573 | * Default configuration
574 | */
575 | var defaultOptions = {
576 | baseUrl: null,
577 | tokenPath: 'access_token',
578 | tokenName: 'token',
579 | tokenPrefix: 'vueauth',
580 | tokenHeader: 'Authorization',
581 | tokenType: 'Bearer',
582 | loginUrl: '/auth/login',
583 | registerUrl: '/auth/register',
584 | logoutUrl: null,
585 | storageType: 'localStorage',
586 | storageNamespace: 'vue-authenticate',
587 | cookieStorage: {
588 | domain: getCookieDomainUrl(),
589 | path: '/',
590 | secure: false,
591 | },
592 | requestDataKey: 'data',
593 | responseDataKey: 'data',
594 |
595 | /**
596 | * Default request interceptor for Axios library
597 | * @context {VueAuthenticate}
598 | */
599 | bindRequestInterceptor: function ($auth) {
600 | const tokenHeader = $auth.options.tokenHeader;
601 |
602 | $auth.$http.interceptors.request.use(config => {
603 | if ($auth.isAuthenticated()) {
604 | config.headers[tokenHeader] = [
605 | $auth.options.tokenType,
606 | $auth.getToken(),
607 | ].join(' ');
608 | } else {
609 | delete config.headers[tokenHeader];
610 | }
611 | return config;
612 | });
613 | },
614 |
615 | providers: {
616 | facebook: {
617 | name: 'facebook',
618 | url: '/auth/facebook',
619 | authorizationEndpoint: 'https://www.facebook.com/v10.0/dialog/oauth',
620 | redirectUri: getRedirectUri('/'),
621 | requiredUrlParams: ['display', 'scope'],
622 | scope: ['email'],
623 | scopeDelimiter: ',',
624 | display: 'popup',
625 | oauthType: '2.0',
626 | popupOptions: { width: 580, height: 400 },
627 | },
628 |
629 | google: {
630 | name: 'google',
631 | url: '/auth/google',
632 | authorizationEndpoint: 'https://accounts.google.com/o/oauth2/auth',
633 | redirectUri: getRedirectUri(),
634 | requiredUrlParams: ['scope'],
635 | optionalUrlParams: ['display'],
636 | scope: ['profile', 'email'],
637 | scopePrefix: 'openid',
638 | scopeDelimiter: ' ',
639 | display: 'popup',
640 | oauthType: '2.0',
641 | popupOptions: { width: 452, height: 633 },
642 | },
643 |
644 | github: {
645 | name: 'github',
646 | url: '/auth/github',
647 | authorizationEndpoint: 'https://github.com/login/oauth/authorize',
648 | redirectUri: getRedirectUri(),
649 | optionalUrlParams: ['scope'],
650 | scope: ['user:email'],
651 | scopeDelimiter: ' ',
652 | oauthType: '2.0',
653 | popupOptions: { width: 1020, height: 618 },
654 | },
655 |
656 | instagram: {
657 | name: 'instagram',
658 | url: '/auth/instagram',
659 | authorizationEndpoint: 'https://api.instagram.com/oauth/authorize',
660 | redirectUri: getRedirectUri(),
661 | requiredUrlParams: ['scope'],
662 | scope: ['basic'],
663 | scopeDelimiter: '+',
664 | oauthType: '2.0',
665 | popupOptions: { width: null, height: null },
666 | },
667 |
668 | twitter: {
669 | name: 'twitter',
670 | url: '/auth/twitter',
671 | authorizationEndpoint: 'https://api.twitter.com/oauth/authenticate',
672 | redirectUri: getRedirectUri(),
673 | oauthType: '1.0',
674 | popupOptions: { width: 495, height: 645 },
675 | },
676 |
677 | bitbucket: {
678 | name: 'bitbucket',
679 | url: '/auth/bitbucket',
680 | authorizationEndpoint: 'https://bitbucket.org/site/oauth2/authorize',
681 | redirectUri: getRedirectUri('/'),
682 | optionalUrlParams: ['scope'],
683 | scope: ['email'],
684 | scopeDelimiter: ' ',
685 | oauthType: '2.0',
686 | popupOptions: { width: 1020, height: 618 },
687 | },
688 |
689 | linkedin: {
690 | name: 'linkedin',
691 | url: '/auth/linkedin',
692 | authorizationEndpoint: 'https://www.linkedin.com/oauth/v2/authorization',
693 | redirectUri: getRedirectUri(),
694 | requiredUrlParams: ['state'],
695 | scope: ['r_emailaddress'],
696 | scopeDelimiter: ' ',
697 | state: 'STATE',
698 | oauthType: '2.0',
699 | popupOptions: { width: 527, height: 582 },
700 | },
701 |
702 | live: {
703 | name: 'live',
704 | url: '/auth/live',
705 | authorizationEndpoint: 'https://login.live.com/oauth20_authorize.srf',
706 | redirectUri: getRedirectUri(),
707 | requiredUrlParams: ['display', 'scope'],
708 | scope: ['wl.emails'],
709 | scopeDelimiter: ' ',
710 | display: 'popup',
711 | oauthType: '2.0',
712 | popupOptions: { width: 500, height: 560 },
713 | },
714 |
715 | oauth1: {
716 | name: null,
717 | url: '/auth/oauth1',
718 | authorizationEndpoint: null,
719 | redirectUri: getRedirectUri(),
720 | oauthType: '1.0',
721 | popupOptions: null,
722 | },
723 |
724 | oauth2: {
725 | name: null,
726 | url: '/auth/oauth2',
727 | clientId: null,
728 | redirectUri: getRedirectUri(),
729 | authorizationEndpoint: null,
730 | defaultUrlParams: ['response_type', 'client_id', 'redirect_uri'],
731 | requiredUrlParams: null,
732 | optionalUrlParams: null,
733 | scope: null,
734 | scopePrefix: null,
735 | scopeDelimiter: null,
736 | state: null,
737 | oauthType: '2.0',
738 | popupOptions: null,
739 | responseType: 'code',
740 | responseParams: {
741 | code: 'code',
742 | clientId: 'clientId',
743 | redirectUri: 'redirectUri',
744 | },
745 | },
746 | },
747 | };
748 |
749 | class CookieStorage {
750 | constructor(defaultOptions) {
751 | this._defaultOptions = objectExtend(
752 | {
753 | domain: getCookieDomainUrl(),
754 | expires: null,
755 | path: '/',
756 | secure: false,
757 | },
758 | defaultOptions
759 | );
760 | }
761 |
762 | setItem(key, value) {
763 | const options = objectExtend({}, this._defaultOptions);
764 | const cookie = formatCookie(key, value, options);
765 | this._setCookie(cookie);
766 | }
767 |
768 | getItem(key) {
769 | const cookies = parseCookies(this._getCookie());
770 | return cookies.hasOwnProperty(key) ? cookies[key] : null;
771 | }
772 |
773 | removeItem(key) {
774 | const value = '';
775 | const defaultOptions = objectExtend({}, this._defaultOptions);
776 | const options = objectExtend(defaultOptions, {
777 | expires: new Date(0),
778 | });
779 | const cookie = formatCookie(key, value, options);
780 | this._setCookie(cookie);
781 | }
782 |
783 | _getCookie() {
784 | try {
785 | return $document.cookie === 'undefined' ? '' : $document.cookie;
786 | } catch (e) {}
787 |
788 | return '';
789 | }
790 |
791 | _setCookie(cookie) {
792 | try {
793 | $document.cookie = cookie;
794 | } catch (e) {}
795 | }
796 | }
797 |
798 | class LocalStorage {
799 | constructor(namespace) {
800 | this.namespace = namespace || null;
801 | }
802 |
803 | setItem(key, value) {
804 | $window.localStorage.setItem(this._getStorageKey(key), value);
805 | }
806 |
807 | getItem(key) {
808 | return $window.localStorage.getItem(this._getStorageKey(key));
809 | }
810 |
811 | removeItem(key) {
812 | $window.localStorage.removeItem(this._getStorageKey(key));
813 | }
814 |
815 | _getStorageKey(key) {
816 | if (this.namespace) {
817 | return [this.namespace, key].join('.');
818 | }
819 | return key;
820 | }
821 | }
822 |
823 | class MemoryStorage {
824 | constructor(namespace) {
825 | this.namespace = namespace || null;
826 | this._storage = {};
827 | }
828 |
829 | setItem(key, value) {
830 | this._storage[this._getStorageKey(key)] = value;
831 | }
832 |
833 | getItem(key) {
834 | return this._storage[this._getStorageKey(key)];
835 | }
836 |
837 | removeItem(key) {
838 | delete this._storage[this._getStorageKey(key)];
839 | }
840 |
841 | _getStorageKey(key) {
842 | if (this.namespace) {
843 | return [this.namespace, key].join('.');
844 | }
845 | return key;
846 | }
847 | }
848 |
849 | class SessionStorage {
850 | constructor(namespace) {
851 | this.namespace = namespace || null;
852 | }
853 |
854 | setItem(key, value) {
855 | $window.sessionStorage.setItem(this._getStorageKey(key), value);
856 | }
857 |
858 | getItem(key) {
859 | return $window.sessionStorage.getItem(this._getStorageKey(key));
860 | }
861 |
862 | removeItem(key) {
863 | $window.sessionStorage.removeItem(this._getStorageKey(key));
864 | }
865 |
866 | _getStorageKey(key) {
867 | if (this.namespace) {
868 | return [this.namespace, key].join('.');
869 | }
870 | return key;
871 | }
872 | }
873 |
874 | function StorageFactory(options) {
875 | switch (options.storageType) {
876 | case 'localStorage':
877 | try {
878 | $window.localStorage.setItem('testKey', 'test');
879 | $window.localStorage.removeItem('testKey');
880 | return new LocalStorage(options.storageNamespace);
881 | } catch (e) {}
882 |
883 | case 'sessionStorage':
884 | try {
885 | $window.sessionStorage.setItem('testKey', 'test');
886 | $window.sessionStorage.removeItem('testKey');
887 | return new SessionStorage(options.storageNamespace);
888 | } catch (e) {}
889 |
890 | case 'cookieStorage':
891 | return new CookieStorage(options.cookieStorage);
892 |
893 | case 'memoryStorage':
894 | default:
895 | return new MemoryStorage(options.storageNamespace);
896 | }
897 | }
898 |
899 | /**
900 | * OAuth2 popup management class
901 | *
902 | * @author Sahat Yalkabov
903 | * @copyright Class mostly taken from https://github.com/sahat/satellizer
904 | * and adjusted to fit vue-authenticate library
905 | */
906 | class OAuthPopup {
907 | constructor(url, name, popupOptions) {
908 | this.popup = null;
909 | this.url = url;
910 | this.name = name;
911 | this.popupOptions = popupOptions;
912 | }
913 |
914 | open(redirectUri, skipPooling) {
915 | try {
916 | this.popup = $window.open(this.url, this.name, this._stringifyOptions());
917 | if (this.popup && this.popup.focus) {
918 | this.popup.focus();
919 | }
920 |
921 | if (skipPooling) {
922 | return Promise$1.resolve();
923 | } else {
924 | return this.pooling(redirectUri);
925 | }
926 | } catch (e) {
927 | return Promise$1.reject(new Error('OAuth popup error occurred'));
928 | }
929 | }
930 |
931 | pooling(redirectUri) {
932 | return new Promise$1((resolve, reject) => {
933 | const redirectUriParser = $document.createElement('a');
934 | redirectUriParser.href = redirectUri;
935 | const redirectUriPath = getFullUrlPath(redirectUriParser);
936 |
937 | let poolingInterval = setInterval(() => {
938 | if (
939 | !this.popup ||
940 | this.popup.closed ||
941 | this.popup.closed === undefined
942 | ) {
943 | clearInterval(poolingInterval);
944 | poolingInterval = null;
945 | reject(new Error('Auth popup window closed'));
946 | }
947 |
948 | try {
949 | const popupWindowPath = getFullUrlPath(this.popup.location);
950 |
951 | if (popupWindowPath === redirectUriPath) {
952 | if (this.popup.location.search || this.popup.location.hash) {
953 | const query = parseQueryString(
954 | this.popup.location.search.substring(1).replace(/\/$/, '')
955 | );
956 | const hash = parseQueryString(
957 | this.popup.location.hash.substring(1).replace(/[\/$]/, '')
958 | );
959 | let params = objectExtend({}, query);
960 | params = objectExtend(params, hash);
961 |
962 | if (params.error) {
963 | reject(new Error(params.error));
964 | } else {
965 | resolve(params);
966 | }
967 | } else {
968 | reject(
969 | new Error(
970 | 'OAuth redirect has occurred but no query or hash parameters were found.'
971 | )
972 | );
973 | }
974 |
975 | clearInterval(poolingInterval);
976 | poolingInterval = null;
977 | this.popup.close();
978 | }
979 | } catch (e) {
980 | // Ignore DOMException: Blocked a frame with origin from accessing a cross-origin frame.
981 | }
982 | }, 250);
983 | });
984 | }
985 |
986 | _stringifyOptions() {
987 | let options = [];
988 | for (var optionKey in this.popupOptions) {
989 | if (!isUndefined(this.popupOptions[optionKey])) {
990 | options.push(`${optionKey}=${this.popupOptions[optionKey]}`);
991 | }
992 | }
993 | return options.join(',');
994 | }
995 | }
996 |
997 | const defaultProviderConfig$1 = {
998 | name: null,
999 | url: null,
1000 | authorizationEndpoint: null,
1001 | scope: null,
1002 | scopePrefix: null,
1003 | scopeDelimiter: null,
1004 | redirectUri: null,
1005 | requiredUrlParams: null,
1006 | defaultUrlParams: null,
1007 | oauthType: '1.0',
1008 | popupOptions: {},
1009 | };
1010 |
1011 | class OAuth {
1012 | constructor($http, storage, providerConfig, options) {
1013 | this.$http = $http;
1014 | this.storage = storage;
1015 | this.providerConfig = objectExtend({}, defaultProviderConfig$1);
1016 | this.providerConfig = objectExtend(this.providerConfig, providerConfig);
1017 | this.options = options;
1018 | }
1019 |
1020 | /**
1021 | * Initialize OAuth1 process
1022 | * @param {Object} userData User data
1023 | * @return {Promise}
1024 | */
1025 | init(userData) {
1026 | this.oauthPopup = new OAuthPopup(
1027 | 'about:blank',
1028 | this.providerConfig.name,
1029 | this.providerConfig.popupOptions
1030 | );
1031 |
1032 | if (!$window['cordova']) {
1033 | this.oauthPopup.open(this.providerConfig.redirectUri, true);
1034 | }
1035 |
1036 | return this.getRequestToken().then(response => {
1037 | return this.openPopup(response).then(popupResponse => {
1038 | return this.exchangeForToken(popupResponse, userData);
1039 | });
1040 | });
1041 | }
1042 |
1043 | /**
1044 | * Get OAuth1 request token
1045 | * @return {Promise}
1046 | */
1047 | getRequestToken() {
1048 | let requestOptions = {};
1049 | requestOptions.method = 'POST';
1050 | requestOptions[this.options.requestDataKey] = objectExtend(
1051 | {},
1052 | this.providerConfig
1053 | );
1054 | requestOptions.withCredentials = this.options.withCredentials;
1055 | if (this.options.baseUrl) {
1056 | requestOptions.url = joinUrl(
1057 | this.options.baseUrl,
1058 | this.providerConfig.url
1059 | );
1060 | } else {
1061 | requestOptions.url = this.providerConfig.url;
1062 | }
1063 |
1064 | return this.$http(requestOptions);
1065 | }
1066 |
1067 | /**
1068 | * Open OAuth1 popup
1069 | * @param {Object} response Response object containing request token
1070 | * @return {Promise}
1071 | */
1072 | openPopup(response) {
1073 | const url = [
1074 | this.providerConfig.authorizationEndpoint,
1075 | this.buildQueryString(response[this.options.responseDataKey]),
1076 | ].join('?');
1077 |
1078 | this.oauthPopup.popup.location = url;
1079 | if ($window['cordova']) {
1080 | return this.oauthPopup.open(this.providerConfig.redirectUri);
1081 | } else {
1082 | return this.oauthPopup.pooling(this.providerConfig.redirectUri);
1083 | }
1084 | }
1085 |
1086 | /**
1087 | * Exchange token and token verifier for access token
1088 | * @param {Object} oauth OAuth data containing token and token verifier
1089 | * @param {Object} userData User data
1090 | * @return {Promise}
1091 | */
1092 | exchangeForToken(oauth, userData) {
1093 | let payload = objectExtend({}, userData);
1094 | payload = objectExtend(payload, oauth);
1095 | let requestOptions = {};
1096 | requestOptions.method = 'POST';
1097 | requestOptions[this.options.requestDataKey] = payload;
1098 | requestOptions.withCredentials = this.options.withCredentials;
1099 | if (this.options.baseUrl) {
1100 | requestOptions.url = joinUrl(
1101 | this.options.baseUrl,
1102 | this.providerConfig.url
1103 | );
1104 | } else {
1105 | requestOptions.url = this.providerConfig.url;
1106 | }
1107 | return this.$http(requestOptions);
1108 | }
1109 |
1110 | buildQueryString(params) {
1111 | const parsedParams = [];
1112 | for (var key in params) {
1113 | let value = params[key];
1114 | parsedParams.push(
1115 | encodeURIComponent(key) + '=' + encodeURIComponent(value)
1116 | );
1117 | }
1118 | return parsedParams.join('&');
1119 | }
1120 | }
1121 |
1122 | /**
1123 | * Default provider configuration
1124 | * @type {Object}
1125 | */
1126 | const defaultProviderConfig = {
1127 | name: null,
1128 | url: null,
1129 | clientId: null,
1130 | authorizationEndpoint: null,
1131 | redirectUri: null,
1132 | scope: null,
1133 | scopePrefix: null,
1134 | scopeDelimiter: null,
1135 | state: null,
1136 | requiredUrlParams: null,
1137 | defaultUrlParams: ['response_type', 'client_id', 'redirect_uri'],
1138 | responseType: 'code',
1139 | responseParams: {
1140 | code: 'code',
1141 | clientId: 'clientId',
1142 | redirectUri: 'redirectUri',
1143 | },
1144 | oauthType: '2.0',
1145 | popupOptions: {},
1146 | };
1147 |
1148 | class OAuth2 {
1149 | constructor($http, storage, providerConfig, options) {
1150 | this.$http = $http;
1151 | this.storage = storage;
1152 | this.providerConfig = objectExtend({}, defaultProviderConfig);
1153 | this.providerConfig = objectExtend(this.providerConfig, providerConfig);
1154 | this.options = options;
1155 | }
1156 |
1157 | init(userData) {
1158 | let stateName = this.providerConfig.name + '_state';
1159 | if (isFunction(this.providerConfig.state)) {
1160 | this.storage.setItem(stateName, this.providerConfig.state());
1161 | } else if (isString(this.providerConfig.state)) {
1162 | this.storage.setItem(stateName, this.providerConfig.state);
1163 | }
1164 |
1165 | let url = [
1166 | this.providerConfig.authorizationEndpoint,
1167 | this._stringifyRequestParams(),
1168 | ].join('?');
1169 |
1170 | this.oauthPopup = new OAuthPopup(
1171 | url,
1172 | this.providerConfig.name,
1173 | this.providerConfig.popupOptions
1174 | );
1175 |
1176 | return new Promise((resolve, reject) => {
1177 | this.oauthPopup
1178 | .open(this.providerConfig.redirectUri)
1179 | .then(response => {
1180 | if (
1181 | this.providerConfig.responseType === 'token' ||
1182 | !this.providerConfig.url
1183 | ) {
1184 | return resolve(response);
1185 | }
1186 |
1187 | if (
1188 | response.state &&
1189 | response.state !== this.storage.getItem(stateName)
1190 | ) {
1191 | return reject(
1192 | new Error(
1193 | 'State parameter value does not match original OAuth request state value'
1194 | )
1195 | );
1196 | }
1197 |
1198 | resolve(this.exchangeForToken(response, userData));
1199 | })
1200 | .catch(err => {
1201 | reject(err);
1202 | });
1203 | });
1204 | }
1205 |
1206 | /**
1207 | * Exchange temporary oauth data for access token
1208 | * @author Sahat Yalkabov
1209 | * @copyright Method taken from https://github.com/sahat/satellizer
1210 | *
1211 | * @param {[type]} oauth [description]
1212 | * @param {[type]} userData [description]
1213 | * @return {[type]} [description]
1214 | */
1215 | exchangeForToken(oauth, userData) {
1216 | let payload = objectExtend({}, userData);
1217 |
1218 | for (let key in this.providerConfig.responseParams) {
1219 | this.providerConfig.responseParams[key];
1220 |
1221 | switch (key) {
1222 | case 'code':
1223 | payload[key] = oauth.code;
1224 | break;
1225 | case 'clientId':
1226 | payload[key] = this.providerConfig.clientId;
1227 | break;
1228 | case 'redirectUri':
1229 | payload[key] = this.providerConfig.redirectUri;
1230 | break;
1231 | default:
1232 | payload[key] = oauth[key];
1233 | }
1234 | }
1235 |
1236 | if (oauth.state) {
1237 | payload.state = oauth.state;
1238 | }
1239 |
1240 | let exchangeTokenUrl;
1241 | if (this.options.baseUrl) {
1242 | exchangeTokenUrl = joinUrl(this.options.baseUrl, this.providerConfig.url);
1243 | } else {
1244 | exchangeTokenUrl = this.providerConfig.url;
1245 | }
1246 |
1247 | return this.$http.post(exchangeTokenUrl, payload, {
1248 | withCredentials: this.options.withCredentials,
1249 | });
1250 | }
1251 |
1252 | /**
1253 | * Stringify oauth params
1254 | * @author Sahat Yalkabov
1255 | * @copyright Method taken from https://github.com/sahat/satellizer
1256 | *
1257 | * @return {String}
1258 | */
1259 | _stringifyRequestParams() {
1260 | let keyValuePairs = [];
1261 | let paramCategories = [
1262 | 'defaultUrlParams',
1263 | 'requiredUrlParams',
1264 | 'optionalUrlParams',
1265 | ];
1266 |
1267 | paramCategories.forEach(categoryName => {
1268 | if (!this.providerConfig[categoryName]) return;
1269 | if (!Array.isArray(this.providerConfig[categoryName])) return;
1270 |
1271 | this.providerConfig[categoryName].forEach(paramName => {
1272 | let camelCaseParamName = camelCase(paramName);
1273 | let paramValue = isFunction(this.providerConfig[paramName])
1274 | ? this.providerConfig[paramName]()
1275 | : this.providerConfig[camelCaseParamName];
1276 |
1277 | if (paramName === 'redirect_uri' && !paramValue) return;
1278 |
1279 | if (paramName === 'state') {
1280 | let stateName = this.providerConfig.name + '_state';
1281 | paramValue = encodeURIComponent(this.storage.getItem(stateName));
1282 | }
1283 | if (paramName === 'scope' && Array.isArray(paramValue)) {
1284 | paramValue = paramValue.join(this.providerConfig.scopeDelimiter);
1285 | if (this.providerConfig.scopePrefix) {
1286 | paramValue = [this.providerConfig.scopePrefix, paramValue].join(
1287 | this.providerConfig.scopeDelimiter
1288 | );
1289 | }
1290 | }
1291 |
1292 | keyValuePairs.push([paramName, paramValue]);
1293 | });
1294 | });
1295 |
1296 | return keyValuePairs
1297 | .map(param => {
1298 | return param.join('=');
1299 | })
1300 | .join('&');
1301 | }
1302 | }
1303 |
1304 | class VueAuthenticate {
1305 | constructor($http, overrideOptions) {
1306 | let options = objectExtend({}, defaultOptions);
1307 | options = objectExtend(options, overrideOptions);
1308 | let storage = StorageFactory(options);
1309 |
1310 | Object.defineProperties(this, {
1311 | $http: {
1312 | get() {
1313 | return $http;
1314 | },
1315 | },
1316 |
1317 | options: {
1318 | get() {
1319 | return options;
1320 | },
1321 | },
1322 |
1323 | storage: {
1324 | get() {
1325 | return storage;
1326 | },
1327 | },
1328 |
1329 | tokenName: {
1330 | get() {
1331 | if (this.options.tokenPrefix) {
1332 | return [this.options.tokenPrefix, this.options.tokenName].join('_');
1333 | } else {
1334 | return this.options.tokenName;
1335 | }
1336 | },
1337 | },
1338 | });
1339 |
1340 | // Setup request interceptors
1341 | if (
1342 | this.options.bindRequestInterceptor &&
1343 | isFunction(this.options.bindRequestInterceptor)
1344 | ) {
1345 | this.options.bindRequestInterceptor.call(this, this);
1346 | } else {
1347 | throw new Error('Request interceptor must be functions');
1348 | }
1349 | }
1350 |
1351 | /**
1352 | * Check if user is authenticated
1353 | * @author Sahat Yalkabov
1354 | * @copyright Method taken from https://github.com/sahat/satellizer
1355 | * @return {Boolean}
1356 | */
1357 | isAuthenticated() {
1358 | let token = this.storage.getItem(this.tokenName);
1359 |
1360 | if (token) {
1361 | // Token is present
1362 | if (token.split('.').length === 3) {
1363 | // Token with a valid JWT format XXX.YYY.ZZZ
1364 | try {
1365 | // Could be a valid JWT or an access token with the same format
1366 | const base64Url = token.split('.')[1];
1367 | const base64 = base64Url.replace('-', '+').replace('_', '/');
1368 | const exp = JSON.parse($window.atob(base64)).exp;
1369 | if (typeof exp === 'number') {
1370 | // JWT with an optonal expiration claims
1371 | return Math.round(new Date().getTime() / 1000) < exp;
1372 | }
1373 | } catch (e) {
1374 | return true; // Pass: Non-JWT token that looks like JWT
1375 | }
1376 | }
1377 | return true; // Pass: All other tokens
1378 | }
1379 | return false;
1380 | }
1381 |
1382 | /**
1383 | * Get token if user is authenticated
1384 | * @return {String} Authentication token
1385 | */
1386 | getToken() {
1387 | return this.storage.getItem(this.tokenName);
1388 | }
1389 |
1390 | /**
1391 | * Set new authentication token
1392 | * @param {String|Object} token
1393 | */
1394 | setToken(response, tokenPath) {
1395 | if (response[this.options.responseDataKey]) {
1396 | response = response[this.options.responseDataKey];
1397 | }
1398 |
1399 | const responseTokenPath = tokenPath || this.options.tokenPath;
1400 | const token = getObjectProperty(response, responseTokenPath);
1401 |
1402 | if (token) {
1403 | this.storage.setItem(this.tokenName, token);
1404 | }
1405 | }
1406 |
1407 | getPayload() {
1408 | const token = this.storage.getItem(this.tokenName);
1409 |
1410 | if (token && token.split('.').length === 3) {
1411 | try {
1412 | const base64Url = token.split('.')[1];
1413 | const base64 = base64Url.replace('-', '+').replace('_', '/');
1414 | return JSON.parse(decodeBase64(base64));
1415 | } catch (e) {}
1416 | }
1417 | }
1418 |
1419 | /**
1420 | * Login user using email and password
1421 | * @param {Object} user User data
1422 | * @param {Object} requestOptions Request options
1423 | * @return {Promise} Request promise
1424 | */
1425 | login(user, requestOptions) {
1426 | requestOptions = requestOptions || {};
1427 | requestOptions.url = requestOptions.url
1428 | ? requestOptions.url
1429 | : joinUrl(this.options.baseUrl, this.options.loginUrl);
1430 | requestOptions[this.options.requestDataKey] =
1431 | user || requestOptions[this.options.requestDataKey];
1432 | requestOptions.method = requestOptions.method || 'POST';
1433 | requestOptions.withCredentials =
1434 | requestOptions.withCredentials || this.options.withCredentials;
1435 |
1436 | return this.$http(requestOptions).then(response => {
1437 | this.setToken(response);
1438 | return response;
1439 | });
1440 | }
1441 |
1442 | /**
1443 | * Register new user
1444 | * @param {Object} user User data
1445 | * @param {Object} requestOptions Request options
1446 | * @return {Promise} Request promise
1447 | */
1448 | register(user, requestOptions) {
1449 | requestOptions = requestOptions || {};
1450 | requestOptions.url = requestOptions.url
1451 | ? requestOptions.url
1452 | : joinUrl(this.options.baseUrl, this.options.registerUrl);
1453 | requestOptions[this.options.requestDataKey] =
1454 | user || requestOptions[this.options.requestDataKey];
1455 | requestOptions.method = requestOptions.method || 'POST';
1456 | requestOptions.withCredentials =
1457 | requestOptions.withCredentials || this.options.withCredentials;
1458 |
1459 | return this.$http(requestOptions).then(response => {
1460 | this.setToken(response);
1461 | return response;
1462 | });
1463 | }
1464 |
1465 | /**
1466 | * Logout current user
1467 | * @param {Object} requestOptions Logout request options object
1468 | * @return {Promise} Request promise
1469 | */
1470 | logout(requestOptions) {
1471 | if (!this.isAuthenticated()) {
1472 | return Promise$1.reject(
1473 | new Error('There is no currently authenticated user')
1474 | );
1475 | }
1476 |
1477 | requestOptions = requestOptions || {};
1478 |
1479 | if (requestOptions.url || this.options.logoutUrl) {
1480 | requestOptions.url = requestOptions.url
1481 | ? requestOptions.url
1482 | : joinUrl(this.options.baseUrl, this.options.logoutUrl);
1483 | requestOptions.method = requestOptions.method || 'POST';
1484 | requestOptions[this.options.requestDataKey] =
1485 | requestOptions[this.options.requestDataKey] || undefined;
1486 | requestOptions.withCredentials =
1487 | requestOptions.withCredentials || this.options.withCredentials;
1488 |
1489 | return this.$http(requestOptions).then(response => {
1490 | this.storage.removeItem(this.tokenName);
1491 | return response;
1492 | });
1493 | } else {
1494 | this.storage.removeItem(this.tokenName);
1495 | return Promise$1.resolve();
1496 | }
1497 | }
1498 |
1499 | /**
1500 | * Authenticate user using authentication provider
1501 | *
1502 | * @param {String} provider Provider name
1503 | * @param {Object} userData User data
1504 | * @return {Promise} Request promise
1505 | */
1506 | authenticate(provider, userData) {
1507 | return new Promise$1((resolve, reject) => {
1508 | var providerConfig = this.options.providers[provider];
1509 | if (!providerConfig) {
1510 | return reject(new Error('Unknown provider'));
1511 | }
1512 |
1513 | let providerInstance;
1514 | switch (providerConfig.oauthType) {
1515 | case '1.0':
1516 | providerInstance = new OAuth(
1517 | this.$http,
1518 | this.storage,
1519 | providerConfig,
1520 | this.options
1521 | );
1522 | break;
1523 | case '2.0':
1524 | providerInstance = new OAuth2(
1525 | this.$http,
1526 | this.storage,
1527 | providerConfig,
1528 | this.options
1529 | );
1530 | break;
1531 | default:
1532 | return reject(new Error('Invalid OAuth type'));
1533 | }
1534 |
1535 | return providerInstance
1536 | .init(userData)
1537 | .then(response => {
1538 | this.setToken(response, providerConfig.tokenPath);
1539 |
1540 | if (this.isAuthenticated()) {
1541 | return resolve(response);
1542 | } else {
1543 | return reject(new Error('Authentication failed'));
1544 | }
1545 | })
1546 | .catch(err => reject(err));
1547 | });
1548 | }
1549 |
1550 | /**
1551 | * Link user using authentication provider without login
1552 | *
1553 | * @param {String} provider Provider name
1554 | * @param {Object} userData User data
1555 | * @return {Promise} Request promise
1556 | */
1557 | link(provider, userData) {
1558 | return new Promise$1((resolve, reject) => {
1559 | var providerConfig = this.options.providers[provider];
1560 | if (!providerConfig) {
1561 | return reject(new Error('Unknown provider'));
1562 | }
1563 |
1564 | let providerInstance;
1565 | switch (providerConfig.oauthType) {
1566 | case '1.0':
1567 | providerInstance = new OAuth(
1568 | this.$http,
1569 | this.storage,
1570 | providerConfig,
1571 | this.options
1572 | );
1573 | break;
1574 | case '2.0':
1575 | providerInstance = new OAuth2(
1576 | this.$http,
1577 | this.storage,
1578 | providerConfig,
1579 | this.options
1580 | );
1581 | break;
1582 | default:
1583 | return reject(new Error('Invalid OAuth type'));
1584 | }
1585 |
1586 | return providerInstance
1587 | .init(userData)
1588 | .then(response => {
1589 | if (response[this.options.responseDataKey]) {
1590 | response = response[this.options.responseDataKey];
1591 | }
1592 |
1593 | resolve(response);
1594 | })
1595 | .catch(reject);
1596 | });
1597 | }
1598 | }
1599 |
1600 | /**
1601 | * VueAuthenticate plugin
1602 | * @param {Object} Vue
1603 | * @param {Object} options
1604 | */
1605 | function plugin(Vue, options) {
1606 | if (plugin.installed) {
1607 | return;
1608 | }
1609 |
1610 | plugin.installed = true;
1611 |
1612 | let vueAuthInstance = null;
1613 | Object.defineProperties(Vue.prototype, {
1614 | $auth: {
1615 | get() {
1616 | if (!vueAuthInstance) {
1617 | // Request handler library not found, throw error
1618 | if (!this.$http) {
1619 | throw new Error('Request handler instance not found');
1620 | }
1621 |
1622 | vueAuthInstance = new VueAuthenticate(this.$http, options);
1623 | }
1624 | return vueAuthInstance;
1625 | },
1626 | },
1627 | });
1628 | }
1629 |
1630 | /**
1631 | * External factory helper for ES5 and CommonJS
1632 | * @param {Object} $http Instance of request handling library
1633 | * @param {Object} options Configuration object
1634 | * @return {VueAuthenticate} VueAuthenticate instance
1635 | */
1636 | plugin.factory = function ($http, options) {
1637 | return new VueAuthenticate($http, options);
1638 | };
1639 |
1640 | export default plugin;
1641 |
--------------------------------------------------------------------------------
/dist/vue-authenticate.min.js:
--------------------------------------------------------------------------------
1 | /**
2 | * vue-authenticate v1.5.0
3 | * https://github.com/dgrubelic/vue-authenticate
4 | * Released under the MIT License.
5 | *
6 | */
7 |
8 | !function(t,e){"object"==typeof exports&&"undefined"!=typeof module?module.exports=e():"function"==typeof define&&define.amd?define(e):(t="undefined"!=typeof globalThis?globalThis:t||self).VueAuthenticate=e()}(this,function(){"use strict";function o(t){return void 0===t}function s(t){return"function"==typeof t}function p(e,o){return null==e||null==o||Object.keys(o).forEach(function(t){"[object Object]"!=Object.prototype.toString.call(o[t])||"[object Object]"!=Object.prototype.toString.call(e[t])?e[t]=o[t]:e[t]=p(e[t],o[t])}),e}function n(t,e){if(/^(?:[a-z]+:)?\/\//i.test(e))return e;return[t,e].join("/").replace(/[\/]+/g,"/").replace(/\/\?/g,"?").replace(/\/\#/g,"#").replace(/\:\//g,"://")}function u(t){var e="https:"===t.protocol;return t.protocol+"//"+t.hostname+":"+(t.port||(e?"443":"80"))+(/^\//.test(t.pathname)?t.pathname:"/"+t.pathname)}function c(t){var e,o,r={};return(t||"").split("&").forEach(function(t){t&&(o=t.split("="),e=decodeURIComponent(o[0]),r[e]=!o[1]||decodeURIComponent(o[1]))}),r}function r(t){var e;if("undefined"!=typeof module&&module.exports)try{e=require("buffer").Buffer}catch(t){}function o(t){switch(t.length){case 4:var e=((7&t.charCodeAt(0))<<18|(63&t.charCodeAt(1))<<12|(63&t.charCodeAt(2))<<6|63&t.charCodeAt(3))-65536;return r(55296+(e>>>10))+r(56320+(1023&e));case 3:return r((15&t.charCodeAt(0))<<12|(63&t.charCodeAt(1))<<6|63&t.charCodeAt(2));default:return r((31&t.charCodeAt(0))<<6|63&t.charCodeAt(1))}}var r=String.fromCharCode,n=new RegExp(["[À-ß][-¿]","[à-ï][-¿]{2}","[ð-÷][-¿]{3}"].join("|"),"g");return(e?function(t){return(t.constructor===e.constructor?t:new e(t,"base64")).toString()}:function(t){return atob(t).replace(n,o)})(String(t).replace(/[-_]/g,function(t){return"-"===t?"+":"/"}).replace(/[^A-Za-z0-9\+\/]/g,""))}function i(t,e,o){return[encodeURIComponent(t),"=",encodeURIComponent(e),(t=(r=o).path,e=r.domain,o=r.expires,r=r.secure,[null==t?"":";path="+t,null==e?"":";domain="+e,null==o?"":";expires="+o.toUTCString(),null==r||!1===r?"":";secure"].join(""))].join("");var r}"function"!=typeof Object.assign&&(Object.assign=function(t,e){var o=arguments;if(null==t)throw new TypeError("Cannot convert undefined or null to object");for(var r=Object(t),n=1;n
67 | * @copyright Method taken from https://github.com/sahat/satellizer
68 | * @return {Boolean}
69 | */
70 | isAuthenticated() {
71 | let token = this.storage.getItem(this.tokenName);
72 |
73 | if (token) {
74 | // Token is present
75 | if (token.split('.').length === 3) {
76 | // Token with a valid JWT format XXX.YYY.ZZZ
77 | try {
78 | // Could be a valid JWT or an access token with the same format
79 | const base64Url = token.split('.')[1];
80 | const base64 = base64Url.replace('-', '+').replace('_', '/');
81 | const exp = JSON.parse($window.atob(base64)).exp;
82 | if (typeof exp === 'number') {
83 | // JWT with an optonal expiration claims
84 | return Math.round(new Date().getTime() / 1000) < exp;
85 | }
86 | } catch (e) {
87 | return true; // Pass: Non-JWT token that looks like JWT
88 | }
89 | }
90 | return true; // Pass: All other tokens
91 | }
92 | return false;
93 | }
94 |
95 | /**
96 | * Get token if user is authenticated
97 | * @return {String} Authentication token
98 | */
99 | getToken() {
100 | return this.storage.getItem(this.tokenName);
101 | }
102 |
103 | /**
104 | * Set new authentication token
105 | * @param {String|Object} token
106 | */
107 | setToken(response, tokenPath) {
108 | if (response[this.options.responseDataKey]) {
109 | response = response[this.options.responseDataKey];
110 | }
111 |
112 | const responseTokenPath = tokenPath || this.options.tokenPath;
113 | const token = getObjectProperty(response, responseTokenPath);
114 |
115 | if (token) {
116 | this.storage.setItem(this.tokenName, token);
117 | }
118 | }
119 |
120 | getPayload() {
121 | const token = this.storage.getItem(this.tokenName);
122 |
123 | if (token && token.split('.').length === 3) {
124 | try {
125 | const base64Url = token.split('.')[1];
126 | const base64 = base64Url.replace('-', '+').replace('_', '/');
127 | return JSON.parse(decodeBase64(base64));
128 | } catch (e) {}
129 | }
130 | }
131 |
132 | /**
133 | * Login user using email and password
134 | * @param {Object} user User data
135 | * @param {Object} requestOptions Request options
136 | * @return {Promise} Request promise
137 | */
138 | login(user, requestOptions) {
139 | requestOptions = requestOptions || {};
140 | requestOptions.url = requestOptions.url
141 | ? requestOptions.url
142 | : joinUrl(this.options.baseUrl, this.options.loginUrl);
143 | requestOptions[this.options.requestDataKey] =
144 | user || requestOptions[this.options.requestDataKey];
145 | requestOptions.method = requestOptions.method || 'POST';
146 | requestOptions.withCredentials =
147 | requestOptions.withCredentials || this.options.withCredentials;
148 |
149 | return this.$http(requestOptions).then(response => {
150 | this.setToken(response);
151 | return response;
152 | });
153 | }
154 |
155 | /**
156 | * Register new user
157 | * @param {Object} user User data
158 | * @param {Object} requestOptions Request options
159 | * @return {Promise} Request promise
160 | */
161 | register(user, requestOptions) {
162 | requestOptions = requestOptions || {};
163 | requestOptions.url = requestOptions.url
164 | ? requestOptions.url
165 | : joinUrl(this.options.baseUrl, this.options.registerUrl);
166 | requestOptions[this.options.requestDataKey] =
167 | user || requestOptions[this.options.requestDataKey];
168 | requestOptions.method = requestOptions.method || 'POST';
169 | requestOptions.withCredentials =
170 | requestOptions.withCredentials || this.options.withCredentials;
171 |
172 | return this.$http(requestOptions).then(response => {
173 | this.setToken(response);
174 | return response;
175 | });
176 | }
177 |
178 | /**
179 | * Logout current user
180 | * @param {Object} requestOptions Logout request options object
181 | * @return {Promise} Request promise
182 | */
183 | logout(requestOptions) {
184 | if (!this.isAuthenticated()) {
185 | return Promise.reject(
186 | new Error('There is no currently authenticated user')
187 | );
188 | }
189 |
190 | requestOptions = requestOptions || {};
191 |
192 | if (requestOptions.url || this.options.logoutUrl) {
193 | requestOptions.url = requestOptions.url
194 | ? requestOptions.url
195 | : joinUrl(this.options.baseUrl, this.options.logoutUrl);
196 | requestOptions.method = requestOptions.method || 'POST';
197 | requestOptions[this.options.requestDataKey] =
198 | requestOptions[this.options.requestDataKey] || undefined;
199 | requestOptions.withCredentials =
200 | requestOptions.withCredentials || this.options.withCredentials;
201 |
202 | return this.$http(requestOptions).then(response => {
203 | this.storage.removeItem(this.tokenName);
204 | return response;
205 | });
206 | } else {
207 | this.storage.removeItem(this.tokenName);
208 | return Promise.resolve();
209 | }
210 | }
211 |
212 | /**
213 | * Authenticate user using authentication provider
214 | *
215 | * @param {String} provider Provider name
216 | * @param {Object} userData User data
217 | * @return {Promise} Request promise
218 | */
219 | authenticate(provider, userData) {
220 | return new Promise((resolve, reject) => {
221 | var providerConfig = this.options.providers[provider];
222 | if (!providerConfig) {
223 | return reject(new Error('Unknown provider'));
224 | }
225 |
226 | let providerInstance;
227 | switch (providerConfig.oauthType) {
228 | case '1.0':
229 | providerInstance = new OAuth1(
230 | this.$http,
231 | this.storage,
232 | providerConfig,
233 | this.options
234 | );
235 | break;
236 | case '2.0':
237 | providerInstance = new OAuth2(
238 | this.$http,
239 | this.storage,
240 | providerConfig,
241 | this.options
242 | );
243 | break;
244 | default:
245 | return reject(new Error('Invalid OAuth type'));
246 | }
247 |
248 | return providerInstance
249 | .init(userData)
250 | .then(response => {
251 | this.setToken(response, providerConfig.tokenPath);
252 |
253 | if (this.isAuthenticated()) {
254 | return resolve(response);
255 | } else {
256 | return reject(new Error('Authentication failed'));
257 | }
258 | })
259 | .catch(err => reject(err));
260 | });
261 | }
262 |
263 | /**
264 | * Link user using authentication provider without login
265 | *
266 | * @param {String} provider Provider name
267 | * @param {Object} userData User data
268 | * @return {Promise} Request promise
269 | */
270 | link(provider, userData) {
271 | return new Promise((resolve, reject) => {
272 | var providerConfig = this.options.providers[provider];
273 | if (!providerConfig) {
274 | return reject(new Error('Unknown provider'));
275 | }
276 |
277 | let providerInstance;
278 | switch (providerConfig.oauthType) {
279 | case '1.0':
280 | providerInstance = new OAuth1(
281 | this.$http,
282 | this.storage,
283 | providerConfig,
284 | this.options
285 | );
286 | break;
287 | case '2.0':
288 | providerInstance = new OAuth2(
289 | this.$http,
290 | this.storage,
291 | providerConfig,
292 | this.options
293 | );
294 | break;
295 | default:
296 | return reject(new Error('Invalid OAuth type'));
297 | }
298 |
299 | return providerInstance
300 | .init(userData)
301 | .then(response => {
302 | if (response[this.options.responseDataKey]) {
303 | response = response[this.options.responseDataKey];
304 | }
305 |
306 | resolve(response);
307 | })
308 | .catch(reject);
309 | });
310 | }
311 | }
312 |
--------------------------------------------------------------------------------
/src/globals.js:
--------------------------------------------------------------------------------
1 | const fakeDocument = {
2 | createElement() { },
3 | };
4 |
5 | const fakeWindow = {
6 | atob() { },
7 | open() { },
8 | location: {},
9 | localStorage: {
10 | setItem() { },
11 | getItem() { },
12 | removeItem() { },
13 | },
14 | sessionStorage: {
15 | setItem() { },
16 | getItem() { },
17 | removeItem() { },
18 | },
19 | };
20 |
21 | export const $document = (typeof document !== undefined)
22 | ? document
23 | : fakeDocument;
24 |
25 | export const $window = (typeof window !== undefined)
26 | ? window
27 | : fakeWindow;
28 |
--------------------------------------------------------------------------------
/src/index.js:
--------------------------------------------------------------------------------
1 | import './utils.js';
2 | import VueAuthenticate from './authenticate.js';
3 |
4 | /**
5 | * VueAuthenticate plugin
6 | * @param {Object} Vue
7 | * @param {Object} options
8 | */
9 | function plugin(Vue, options) {
10 | if (plugin.installed) {
11 | return;
12 | }
13 |
14 | plugin.installed = true;
15 |
16 | let vueAuthInstance = null;
17 | Object.defineProperties(Vue.prototype, {
18 | $auth: {
19 | get() {
20 | if (!vueAuthInstance) {
21 | // Request handler library not found, throw error
22 | if (!this.$http) {
23 | throw new Error('Request handler instance not found');
24 | }
25 |
26 | vueAuthInstance = new VueAuthenticate(this.$http, options);
27 | }
28 | return vueAuthInstance;
29 | },
30 | },
31 | });
32 | }
33 |
34 | /**
35 | * External factory helper for ES5 and CommonJS
36 | * @param {Object} $http Instance of request handling library
37 | * @param {Object} options Configuration object
38 | * @return {VueAuthenticate} VueAuthenticate instance
39 | */
40 | plugin.factory = function ($http, options) {
41 | return new VueAuthenticate($http, options);
42 | };
43 |
44 | export default plugin;
45 |
--------------------------------------------------------------------------------
/src/oauth/oauth1.js:
--------------------------------------------------------------------------------
1 | import OAuthPopup from './popup.js';
2 | import { $window } from '../globals.js';
3 | import {
4 | objectExtend,
5 | isString,
6 | isObject,
7 | isFunction,
8 | joinUrl,
9 | } from '../utils.js';
10 |
11 | const defaultProviderConfig = {
12 | name: null,
13 | url: null,
14 | authorizationEndpoint: null,
15 | scope: null,
16 | scopePrefix: null,
17 | scopeDelimiter: null,
18 | redirectUri: null,
19 | requiredUrlParams: null,
20 | defaultUrlParams: null,
21 | oauthType: '1.0',
22 | popupOptions: {},
23 | };
24 |
25 | export default class OAuth {
26 | constructor($http, storage, providerConfig, options) {
27 | this.$http = $http;
28 | this.storage = storage;
29 | this.providerConfig = objectExtend({}, defaultProviderConfig);
30 | this.providerConfig = objectExtend(this.providerConfig, providerConfig);
31 | this.options = options;
32 | }
33 |
34 | /**
35 | * Initialize OAuth1 process
36 | * @param {Object} userData User data
37 | * @return {Promise}
38 | */
39 | init(userData) {
40 | this.oauthPopup = new OAuthPopup(
41 | 'about:blank',
42 | this.providerConfig.name,
43 | this.providerConfig.popupOptions
44 | );
45 |
46 | if (!$window['cordova']) {
47 | this.oauthPopup.open(this.providerConfig.redirectUri, true);
48 | }
49 |
50 | return this.getRequestToken().then(response => {
51 | return this.openPopup(response).then(popupResponse => {
52 | return this.exchangeForToken(popupResponse, userData);
53 | });
54 | });
55 | }
56 |
57 | /**
58 | * Get OAuth1 request token
59 | * @return {Promise}
60 | */
61 | getRequestToken() {
62 | let requestOptions = {};
63 | requestOptions.method = 'POST';
64 | requestOptions[this.options.requestDataKey] = objectExtend(
65 | {},
66 | this.providerConfig
67 | );
68 | requestOptions.withCredentials = this.options.withCredentials;
69 | if (this.options.baseUrl) {
70 | requestOptions.url = joinUrl(
71 | this.options.baseUrl,
72 | this.providerConfig.url
73 | );
74 | } else {
75 | requestOptions.url = this.providerConfig.url;
76 | }
77 |
78 | return this.$http(requestOptions);
79 | }
80 |
81 | /**
82 | * Open OAuth1 popup
83 | * @param {Object} response Response object containing request token
84 | * @return {Promise}
85 | */
86 | openPopup(response) {
87 | const url = [
88 | this.providerConfig.authorizationEndpoint,
89 | this.buildQueryString(response[this.options.responseDataKey]),
90 | ].join('?');
91 |
92 | this.oauthPopup.popup.location = url;
93 | if ($window['cordova']) {
94 | return this.oauthPopup.open(this.providerConfig.redirectUri);
95 | } else {
96 | return this.oauthPopup.pooling(this.providerConfig.redirectUri);
97 | }
98 | }
99 |
100 | /**
101 | * Exchange token and token verifier for access token
102 | * @param {Object} oauth OAuth data containing token and token verifier
103 | * @param {Object} userData User data
104 | * @return {Promise}
105 | */
106 | exchangeForToken(oauth, userData) {
107 | let payload = objectExtend({}, userData);
108 | payload = objectExtend(payload, oauth);
109 | let requestOptions = {};
110 | requestOptions.method = 'POST';
111 | requestOptions[this.options.requestDataKey] = payload;
112 | requestOptions.withCredentials = this.options.withCredentials;
113 | if (this.options.baseUrl) {
114 | requestOptions.url = joinUrl(
115 | this.options.baseUrl,
116 | this.providerConfig.url
117 | );
118 | } else {
119 | requestOptions.url = this.providerConfig.url;
120 | }
121 | return this.$http(requestOptions);
122 | }
123 |
124 | buildQueryString(params) {
125 | const parsedParams = [];
126 | for (var key in params) {
127 | let value = params[key];
128 | parsedParams.push(
129 | encodeURIComponent(key) + '=' + encodeURIComponent(value)
130 | );
131 | }
132 | return parsedParams.join('&');
133 | }
134 | }
135 |
--------------------------------------------------------------------------------
/src/oauth/oauth2.js:
--------------------------------------------------------------------------------
1 | import OAuthPopup from './popup.js';
2 | import {
3 | camelCase,
4 | isFunction,
5 | isString,
6 | objectExtend,
7 | joinUrl,
8 | } from '../utils.js';
9 |
10 | /**
11 | * Default provider configuration
12 | * @type {Object}
13 | */
14 | const defaultProviderConfig = {
15 | name: null,
16 | url: null,
17 | clientId: null,
18 | authorizationEndpoint: null,
19 | redirectUri: null,
20 | scope: null,
21 | scopePrefix: null,
22 | scopeDelimiter: null,
23 | state: null,
24 | requiredUrlParams: null,
25 | defaultUrlParams: ['response_type', 'client_id', 'redirect_uri'],
26 | responseType: 'code',
27 | responseParams: {
28 | code: 'code',
29 | clientId: 'clientId',
30 | redirectUri: 'redirectUri',
31 | },
32 | oauthType: '2.0',
33 | popupOptions: {},
34 | };
35 |
36 | export default class OAuth2 {
37 | constructor($http, storage, providerConfig, options) {
38 | this.$http = $http;
39 | this.storage = storage;
40 | this.providerConfig = objectExtend({}, defaultProviderConfig);
41 | this.providerConfig = objectExtend(this.providerConfig, providerConfig);
42 | this.options = options;
43 | }
44 |
45 | init(userData) {
46 | let stateName = this.providerConfig.name + '_state';
47 | if (isFunction(this.providerConfig.state)) {
48 | this.storage.setItem(stateName, this.providerConfig.state());
49 | } else if (isString(this.providerConfig.state)) {
50 | this.storage.setItem(stateName, this.providerConfig.state);
51 | }
52 |
53 | let url = [
54 | this.providerConfig.authorizationEndpoint,
55 | this._stringifyRequestParams(),
56 | ].join('?');
57 |
58 | this.oauthPopup = new OAuthPopup(
59 | url,
60 | this.providerConfig.name,
61 | this.providerConfig.popupOptions
62 | );
63 |
64 | return new Promise((resolve, reject) => {
65 | this.oauthPopup
66 | .open(this.providerConfig.redirectUri)
67 | .then(response => {
68 | if (
69 | this.providerConfig.responseType === 'token' ||
70 | !this.providerConfig.url
71 | ) {
72 | return resolve(response);
73 | }
74 |
75 | if (
76 | response.state &&
77 | response.state !== this.storage.getItem(stateName)
78 | ) {
79 | return reject(
80 | new Error(
81 | 'State parameter value does not match original OAuth request state value'
82 | )
83 | );
84 | }
85 |
86 | resolve(this.exchangeForToken(response, userData));
87 | })
88 | .catch(err => {
89 | reject(err);
90 | });
91 | });
92 | }
93 |
94 | /**
95 | * Exchange temporary oauth data for access token
96 | * @author Sahat Yalkabov
97 | * @copyright Method taken from https://github.com/sahat/satellizer
98 | *
99 | * @param {[type]} oauth [description]
100 | * @param {[type]} userData [description]
101 | * @return {[type]} [description]
102 | */
103 | exchangeForToken(oauth, userData) {
104 | let payload = objectExtend({}, userData);
105 |
106 | for (let key in this.providerConfig.responseParams) {
107 | let value = this.providerConfig.responseParams[key];
108 |
109 | switch (key) {
110 | case 'code':
111 | payload[key] = oauth.code;
112 | break;
113 | case 'clientId':
114 | payload[key] = this.providerConfig.clientId;
115 | break;
116 | case 'redirectUri':
117 | payload[key] = this.providerConfig.redirectUri;
118 | break;
119 | default:
120 | payload[key] = oauth[key];
121 | }
122 | }
123 |
124 | if (oauth.state) {
125 | payload.state = oauth.state;
126 | }
127 |
128 | let exchangeTokenUrl;
129 | if (this.options.baseUrl) {
130 | exchangeTokenUrl = joinUrl(this.options.baseUrl, this.providerConfig.url);
131 | } else {
132 | exchangeTokenUrl = this.providerConfig.url;
133 | }
134 |
135 | return this.$http.post(exchangeTokenUrl, payload, {
136 | withCredentials: this.options.withCredentials,
137 | });
138 | }
139 |
140 | /**
141 | * Stringify oauth params
142 | * @author Sahat Yalkabov
143 | * @copyright Method taken from https://github.com/sahat/satellizer
144 | *
145 | * @return {String}
146 | */
147 | _stringifyRequestParams() {
148 | let keyValuePairs = [];
149 | let paramCategories = [
150 | 'defaultUrlParams',
151 | 'requiredUrlParams',
152 | 'optionalUrlParams',
153 | ];
154 |
155 | paramCategories.forEach(categoryName => {
156 | if (!this.providerConfig[categoryName]) return;
157 | if (!Array.isArray(this.providerConfig[categoryName])) return;
158 |
159 | this.providerConfig[categoryName].forEach(paramName => {
160 | let camelCaseParamName = camelCase(paramName);
161 | let paramValue = isFunction(this.providerConfig[paramName])
162 | ? this.providerConfig[paramName]()
163 | : this.providerConfig[camelCaseParamName];
164 |
165 | if (paramName === 'redirect_uri' && !paramValue) return;
166 |
167 | if (paramName === 'state') {
168 | let stateName = this.providerConfig.name + '_state';
169 | paramValue = encodeURIComponent(this.storage.getItem(stateName));
170 | }
171 | if (paramName === 'scope' && Array.isArray(paramValue)) {
172 | paramValue = paramValue.join(this.providerConfig.scopeDelimiter);
173 | if (this.providerConfig.scopePrefix) {
174 | paramValue = [this.providerConfig.scopePrefix, paramValue].join(
175 | this.providerConfig.scopeDelimiter
176 | );
177 | }
178 | }
179 |
180 | keyValuePairs.push([paramName, paramValue]);
181 | });
182 | });
183 |
184 | return keyValuePairs
185 | .map(param => {
186 | return param.join('=');
187 | })
188 | .join('&');
189 | }
190 | }
191 |
--------------------------------------------------------------------------------
/src/oauth/popup.js:
--------------------------------------------------------------------------------
1 | import Promise from '../promise.js';
2 | import { $document, $window } from '../globals.js';
3 | import {
4 | objectExtend,
5 | parseQueryString,
6 | getFullUrlPath,
7 | isUndefined,
8 | } from '../utils.js';
9 |
10 | /**
11 | * OAuth2 popup management class
12 | *
13 | * @author Sahat Yalkabov
14 | * @copyright Class mostly taken from https://github.com/sahat/satellizer
15 | * and adjusted to fit vue-authenticate library
16 | */
17 | export default class OAuthPopup {
18 | constructor(url, name, popupOptions) {
19 | this.popup = null;
20 | this.url = url;
21 | this.name = name;
22 | this.popupOptions = popupOptions;
23 | }
24 |
25 | open(redirectUri, skipPooling) {
26 | try {
27 | this.popup = $window.open(this.url, this.name, this._stringifyOptions());
28 | if (this.popup && this.popup.focus) {
29 | this.popup.focus();
30 | }
31 |
32 | if (skipPooling) {
33 | return Promise.resolve();
34 | } else {
35 | return this.pooling(redirectUri);
36 | }
37 | } catch (e) {
38 | return Promise.reject(new Error('OAuth popup error occurred'));
39 | }
40 | }
41 |
42 | pooling(redirectUri) {
43 | return new Promise((resolve, reject) => {
44 | const redirectUriParser = $document.createElement('a');
45 | redirectUriParser.href = redirectUri;
46 | const redirectUriPath = getFullUrlPath(redirectUriParser);
47 |
48 | let poolingInterval = setInterval(() => {
49 | if (
50 | !this.popup ||
51 | this.popup.closed ||
52 | this.popup.closed === undefined
53 | ) {
54 | clearInterval(poolingInterval);
55 | poolingInterval = null;
56 | reject(new Error('Auth popup window closed'));
57 | }
58 |
59 | try {
60 | const popupWindowPath = getFullUrlPath(this.popup.location);
61 |
62 | if (popupWindowPath === redirectUriPath) {
63 | if (this.popup.location.search || this.popup.location.hash) {
64 | const query = parseQueryString(
65 | this.popup.location.search.substring(1).replace(/\/$/, '')
66 | );
67 | const hash = parseQueryString(
68 | this.popup.location.hash.substring(1).replace(/[\/$]/, '')
69 | );
70 | let params = objectExtend({}, query);
71 | params = objectExtend(params, hash);
72 |
73 | if (params.error) {
74 | reject(new Error(params.error));
75 | } else {
76 | resolve(params);
77 | }
78 | } else {
79 | reject(
80 | new Error(
81 | 'OAuth redirect has occurred but no query or hash parameters were found.'
82 | )
83 | );
84 | }
85 |
86 | clearInterval(poolingInterval);
87 | poolingInterval = null;
88 | this.popup.close();
89 | }
90 | } catch (e) {
91 | // Ignore DOMException: Blocked a frame with origin from accessing a cross-origin frame.
92 | }
93 | }, 250);
94 | });
95 | }
96 |
97 | _stringifyOptions() {
98 | let options = [];
99 | for (var optionKey in this.popupOptions) {
100 | if (!isUndefined(this.popupOptions[optionKey])) {
101 | options.push(`${optionKey}=${this.popupOptions[optionKey]}`);
102 | }
103 | }
104 | return options.join(',');
105 | }
106 | }
107 |
--------------------------------------------------------------------------------
/src/options.js:
--------------------------------------------------------------------------------
1 | import { isUndefined } from './utils';
2 | import { $window } from './globals';
3 |
4 | export function getCookieDomainUrl() {
5 | try {
6 | return $window.location.hostname;
7 | } catch (e) {}
8 |
9 | return '';
10 | }
11 |
12 | export function getRedirectUri(uri) {
13 | try {
14 | return !isUndefined(uri)
15 | ? `${$window.location.origin}${uri}`
16 | : $window.location.origin;
17 | } catch (e) {}
18 |
19 | return uri || null;
20 | }
21 |
22 | /**
23 | * Default configuration
24 | */
25 | export default {
26 | baseUrl: null,
27 | tokenPath: 'access_token',
28 | tokenName: 'token',
29 | tokenPrefix: 'vueauth',
30 | tokenHeader: 'Authorization',
31 | tokenType: 'Bearer',
32 | loginUrl: '/auth/login',
33 | registerUrl: '/auth/register',
34 | logoutUrl: null,
35 | storageType: 'localStorage',
36 | storageNamespace: 'vue-authenticate',
37 | cookieStorage: {
38 | domain: getCookieDomainUrl(),
39 | path: '/',
40 | secure: false,
41 | },
42 | requestDataKey: 'data',
43 | responseDataKey: 'data',
44 |
45 | /**
46 | * Default request interceptor for Axios library
47 | * @context {VueAuthenticate}
48 | */
49 | bindRequestInterceptor: function ($auth) {
50 | const tokenHeader = $auth.options.tokenHeader;
51 |
52 | $auth.$http.interceptors.request.use(config => {
53 | if ($auth.isAuthenticated()) {
54 | config.headers[tokenHeader] = [
55 | $auth.options.tokenType,
56 | $auth.getToken(),
57 | ].join(' ');
58 | } else {
59 | delete config.headers[tokenHeader];
60 | }
61 | return config;
62 | });
63 | },
64 |
65 | providers: {
66 | facebook: {
67 | name: 'facebook',
68 | url: '/auth/facebook',
69 | authorizationEndpoint: 'https://www.facebook.com/v10.0/dialog/oauth',
70 | redirectUri: getRedirectUri('/'),
71 | requiredUrlParams: ['display', 'scope'],
72 | scope: ['email'],
73 | scopeDelimiter: ',',
74 | display: 'popup',
75 | oauthType: '2.0',
76 | popupOptions: { width: 580, height: 400 },
77 | },
78 |
79 | google: {
80 | name: 'google',
81 | url: '/auth/google',
82 | authorizationEndpoint: 'https://accounts.google.com/o/oauth2/auth',
83 | redirectUri: getRedirectUri(),
84 | requiredUrlParams: ['scope'],
85 | optionalUrlParams: ['display'],
86 | scope: ['profile', 'email'],
87 | scopePrefix: 'openid',
88 | scopeDelimiter: ' ',
89 | display: 'popup',
90 | oauthType: '2.0',
91 | popupOptions: { width: 452, height: 633 },
92 | },
93 |
94 | github: {
95 | name: 'github',
96 | url: '/auth/github',
97 | authorizationEndpoint: 'https://github.com/login/oauth/authorize',
98 | redirectUri: getRedirectUri(),
99 | optionalUrlParams: ['scope'],
100 | scope: ['user:email'],
101 | scopeDelimiter: ' ',
102 | oauthType: '2.0',
103 | popupOptions: { width: 1020, height: 618 },
104 | },
105 |
106 | instagram: {
107 | name: 'instagram',
108 | url: '/auth/instagram',
109 | authorizationEndpoint: 'https://api.instagram.com/oauth/authorize',
110 | redirectUri: getRedirectUri(),
111 | requiredUrlParams: ['scope'],
112 | scope: ['basic'],
113 | scopeDelimiter: '+',
114 | oauthType: '2.0',
115 | popupOptions: { width: null, height: null },
116 | },
117 |
118 | twitter: {
119 | name: 'twitter',
120 | url: '/auth/twitter',
121 | authorizationEndpoint: 'https://api.twitter.com/oauth/authenticate',
122 | redirectUri: getRedirectUri(),
123 | oauthType: '1.0',
124 | popupOptions: { width: 495, height: 645 },
125 | },
126 |
127 | bitbucket: {
128 | name: 'bitbucket',
129 | url: '/auth/bitbucket',
130 | authorizationEndpoint: 'https://bitbucket.org/site/oauth2/authorize',
131 | redirectUri: getRedirectUri('/'),
132 | optionalUrlParams: ['scope'],
133 | scope: ['email'],
134 | scopeDelimiter: ' ',
135 | oauthType: '2.0',
136 | popupOptions: { width: 1020, height: 618 },
137 | },
138 |
139 | linkedin: {
140 | name: 'linkedin',
141 | url: '/auth/linkedin',
142 | authorizationEndpoint: 'https://www.linkedin.com/oauth/v2/authorization',
143 | redirectUri: getRedirectUri(),
144 | requiredUrlParams: ['state'],
145 | scope: ['r_emailaddress'],
146 | scopeDelimiter: ' ',
147 | state: 'STATE',
148 | oauthType: '2.0',
149 | popupOptions: { width: 527, height: 582 },
150 | },
151 |
152 | live: {
153 | name: 'live',
154 | url: '/auth/live',
155 | authorizationEndpoint: 'https://login.live.com/oauth20_authorize.srf',
156 | redirectUri: getRedirectUri(),
157 | requiredUrlParams: ['display', 'scope'],
158 | scope: ['wl.emails'],
159 | scopeDelimiter: ' ',
160 | display: 'popup',
161 | oauthType: '2.0',
162 | popupOptions: { width: 500, height: 560 },
163 | },
164 |
165 | oauth1: {
166 | name: null,
167 | url: '/auth/oauth1',
168 | authorizationEndpoint: null,
169 | redirectUri: getRedirectUri(),
170 | oauthType: '1.0',
171 | popupOptions: null,
172 | },
173 |
174 | oauth2: {
175 | name: null,
176 | url: '/auth/oauth2',
177 | clientId: null,
178 | redirectUri: getRedirectUri(),
179 | authorizationEndpoint: null,
180 | defaultUrlParams: ['response_type', 'client_id', 'redirect_uri'],
181 | requiredUrlParams: null,
182 | optionalUrlParams: null,
183 | scope: null,
184 | scopePrefix: null,
185 | scopeDelimiter: null,
186 | state: null,
187 | oauthType: '2.0',
188 | popupOptions: null,
189 | responseType: 'code',
190 | responseParams: {
191 | code: 'code',
192 | clientId: 'clientId',
193 | redirectUri: 'redirectUri',
194 | },
195 | },
196 | },
197 | };
198 |
--------------------------------------------------------------------------------
/src/promise.js:
--------------------------------------------------------------------------------
1 | // Store setTimeout reference so promise-polyfill will be unaffected by
2 | // other code modifying setTimeout (like sinon.useFakeTimers())
3 | var setTimeoutFunc = setTimeout;
4 |
5 | function noop() {}
6 |
7 | // Polyfill for Function.prototype.bind
8 | function bind(fn, thisArg) {
9 | return function () {
10 | fn.apply(thisArg, arguments);
11 | };
12 | }
13 |
14 | function Promise(fn) {
15 | if (typeof this !== 'object')
16 | throw new TypeError('Promises must be constructed via new');
17 | if (typeof fn !== 'function') throw new TypeError('not a function');
18 | this._state = 0;
19 | this._handled = false;
20 | this._value = undefined;
21 | this._deferreds = [];
22 |
23 | doResolve(fn, this);
24 | }
25 |
26 | function handle(self, deferred) {
27 | while (self._state === 3) {
28 | self = self._value;
29 | }
30 | if (self._state === 0) {
31 | self._deferreds.push(deferred);
32 | return;
33 | }
34 | self._handled = true;
35 | Promise._immediateFn(function () {
36 | var cb = self._state === 1 ? deferred.onFulfilled : deferred.onRejected;
37 | if (cb === null) {
38 | (self._state === 1 ? resolve : reject)(deferred.promise, self._value);
39 | return;
40 | }
41 | var ret;
42 | try {
43 | ret = cb(self._value);
44 | } catch (e) {
45 | reject(deferred.promise, e);
46 | return;
47 | }
48 | resolve(deferred.promise, ret);
49 | });
50 | }
51 |
52 | function resolve(self, newValue) {
53 | try {
54 | // Promise Resolution Procedure: https://github.com/promises-aplus/promises-spec#the-promise-resolution-procedure
55 | if (newValue === self)
56 | throw new TypeError('A promise cannot be resolved with itself.');
57 | if (
58 | newValue &&
59 | (typeof newValue === 'object' || typeof newValue === 'function')
60 | ) {
61 | var then = newValue.then;
62 | if (newValue instanceof Promise) {
63 | self._state = 3;
64 | self._value = newValue;
65 | finale(self);
66 | return;
67 | } else if (typeof then === 'function') {
68 | doResolve(bind(then, newValue), self);
69 | return;
70 | }
71 | }
72 | self._state = 1;
73 | self._value = newValue;
74 | finale(self);
75 | } catch (e) {
76 | reject(self, e);
77 | }
78 | }
79 |
80 | function reject(self, newValue) {
81 | self._state = 2;
82 | self._value = newValue;
83 | finale(self);
84 | }
85 |
86 | function finale(self) {
87 | if (self._state === 2 && self._deferreds.length === 0) {
88 | Promise._immediateFn(function () {
89 | if (!self._handled) {
90 | Promise._unhandledRejectionFn(self._value);
91 | }
92 | });
93 | }
94 |
95 | for (var i = 0, len = self._deferreds.length; i < len; i++) {
96 | handle(self, self._deferreds[i]);
97 | }
98 | self._deferreds = null;
99 | }
100 |
101 | function Handler(onFulfilled, onRejected, promise) {
102 | this.onFulfilled = typeof onFulfilled === 'function' ? onFulfilled : null;
103 | this.onRejected = typeof onRejected === 'function' ? onRejected : null;
104 | this.promise = promise;
105 | }
106 |
107 | /**
108 | * Take a potentially misbehaving resolver function and make sure
109 | * onFulfilled and onRejected are only called once.
110 | *
111 | * Makes no guarantees about asynchrony.
112 | */
113 | function doResolve(fn, self) {
114 | var done = false;
115 | try {
116 | fn(
117 | function (value) {
118 | if (done) return;
119 | done = true;
120 | resolve(self, value);
121 | },
122 | function (reason) {
123 | if (done) return;
124 | done = true;
125 | reject(self, reason);
126 | }
127 | );
128 | } catch (ex) {
129 | if (done) return;
130 | done = true;
131 | reject(self, ex);
132 | }
133 | }
134 |
135 | Promise.prototype['catch'] = function (onRejected) {
136 | return this.then(null, onRejected);
137 | };
138 |
139 | Promise.prototype.then = function (onFulfilled, onRejected) {
140 | var prom = new this.constructor(noop);
141 |
142 | handle(this, new Handler(onFulfilled, onRejected, prom));
143 | return prom;
144 | };
145 |
146 | Promise.all = function (arr) {
147 | var args = Array.prototype.slice.call(arr);
148 |
149 | return new Promise(function (resolve, reject) {
150 | if (args.length === 0) return resolve([]);
151 | var remaining = args.length;
152 |
153 | function res(i, val) {
154 | try {
155 | if (val && (typeof val === 'object' || typeof val === 'function')) {
156 | var then = val.then;
157 | if (typeof then === 'function') {
158 | then.call(
159 | val,
160 | function (val) {
161 | res(i, val);
162 | },
163 | reject
164 | );
165 | return;
166 | }
167 | }
168 | args[i] = val;
169 | if (--remaining === 0) {
170 | resolve(args);
171 | }
172 | } catch (ex) {
173 | reject(ex);
174 | }
175 | }
176 |
177 | for (var i = 0; i < args.length; i++) {
178 | res(i, args[i]);
179 | }
180 | });
181 | };
182 |
183 | Promise.resolve = function (value) {
184 | if (value && typeof value === 'object' && value.constructor === Promise) {
185 | return value;
186 | }
187 |
188 | return new Promise(function (resolve) {
189 | resolve(value);
190 | });
191 | };
192 |
193 | Promise.reject = function (value) {
194 | return new Promise(function (resolve, reject) {
195 | reject(value);
196 | });
197 | };
198 |
199 | Promise.race = function (values) {
200 | return new Promise(function (resolve, reject) {
201 | for (var i = 0, len = values.length; i < len; i++) {
202 | values[i].then(resolve, reject);
203 | }
204 | });
205 | };
206 |
207 | // Use polyfill for setImmediate for performance gains
208 | Promise._immediateFn =
209 | (typeof setImmediate === 'function' &&
210 | function (fn) {
211 | setImmediate(fn);
212 | }) ||
213 | function (fn) {
214 | setTimeoutFunc(fn, 0);
215 | };
216 |
217 | Promise._unhandledRejectionFn = function _unhandledRejectionFn(err) {
218 | if (typeof console !== 'undefined' && console) {
219 | console.warn('Possible Unhandled Promise Rejection:', err); // eslint-disable-line no-console
220 | }
221 | };
222 |
223 | /**
224 | * Set the immediate function to execute callbacks
225 | * @param fn {function} Function to execute
226 | * @deprecated
227 | */
228 | Promise._setImmediateFn = function _setImmediateFn(fn) {
229 | Promise._immediateFn = fn;
230 | };
231 |
232 | /**
233 | * Change the function to execute on unhandled rejection
234 | * @param {function} fn Function to execute on unhandled rejection
235 | * @deprecated
236 | */
237 | Promise._setUnhandledRejectionFn = function _setUnhandledRejectionFn(fn) {
238 | Promise._unhandledRejectionFn = fn;
239 | };
240 |
241 | export default Promise;
242 |
--------------------------------------------------------------------------------
/src/storage.js:
--------------------------------------------------------------------------------
1 | import { $window } from './globals';
2 | import CookieStorage from './storage/cookie-storage.js';
3 | import LocalStorage from './storage/local-storage.js';
4 | import MemoryStorage from './storage/memory-storage.js';
5 | import SessionStorage from './storage/session-storage.js';
6 |
7 | export default function StorageFactory(options) {
8 | switch (options.storageType) {
9 | case 'localStorage':
10 | try {
11 | $window.localStorage.setItem('testKey', 'test');
12 | $window.localStorage.removeItem('testKey');
13 | return new LocalStorage(options.storageNamespace);
14 | } catch (e) {}
15 |
16 | case 'sessionStorage':
17 | try {
18 | $window.sessionStorage.setItem('testKey', 'test');
19 | $window.sessionStorage.removeItem('testKey');
20 | return new SessionStorage(options.storageNamespace);
21 | } catch (e) {}
22 |
23 | case 'cookieStorage':
24 | return new CookieStorage(options.cookieStorage);
25 |
26 | case 'memoryStorage':
27 | default:
28 | return new MemoryStorage(options.storageNamespace);
29 | break;
30 | }
31 | }
32 |
--------------------------------------------------------------------------------
/src/storage/cookie-storage.js:
--------------------------------------------------------------------------------
1 | import { $document } from '../globals.js';
2 | import { objectExtend, formatCookie, parseCookies } from '../utils.js';
3 | import { getCookieDomainUrl } from '../options.js';
4 |
5 | class CookieStorage {
6 | constructor(defaultOptions) {
7 | this._defaultOptions = objectExtend(
8 | {
9 | domain: getCookieDomainUrl(),
10 | expires: null,
11 | path: '/',
12 | secure: false,
13 | },
14 | defaultOptions
15 | );
16 | }
17 |
18 | setItem(key, value) {
19 | const options = objectExtend({}, this._defaultOptions);
20 | const cookie = formatCookie(key, value, options);
21 | this._setCookie(cookie);
22 | }
23 |
24 | getItem(key) {
25 | const cookies = parseCookies(this._getCookie());
26 | return cookies.hasOwnProperty(key) ? cookies[key] : null;
27 | }
28 |
29 | removeItem(key) {
30 | const value = '';
31 | const defaultOptions = objectExtend({}, this._defaultOptions);
32 | const options = objectExtend(defaultOptions, {
33 | expires: new Date(0),
34 | });
35 | const cookie = formatCookie(key, value, options);
36 | this._setCookie(cookie);
37 | }
38 |
39 | _getCookie() {
40 | try {
41 | return $document.cookie === 'undefined' ? '' : $document.cookie;
42 | } catch (e) {}
43 |
44 | return '';
45 | }
46 |
47 | _setCookie(cookie) {
48 | try {
49 | $document.cookie = cookie;
50 | } catch (e) {}
51 | }
52 | }
53 |
54 | export default CookieStorage;
55 |
--------------------------------------------------------------------------------
/src/storage/local-storage.js:
--------------------------------------------------------------------------------
1 | import { $window } from '../globals.js';
2 |
3 | class LocalStorage {
4 | constructor(namespace) {
5 | this.namespace = namespace || null;
6 | }
7 |
8 | setItem(key, value) {
9 | $window.localStorage.setItem(this._getStorageKey(key), value);
10 | }
11 |
12 | getItem(key) {
13 | return $window.localStorage.getItem(this._getStorageKey(key));
14 | }
15 |
16 | removeItem(key) {
17 | $window.localStorage.removeItem(this._getStorageKey(key));
18 | }
19 |
20 | _getStorageKey(key) {
21 | if (this.namespace) {
22 | return [this.namespace, key].join('.');
23 | }
24 | return key;
25 | }
26 | }
27 |
28 | export default LocalStorage;
29 |
--------------------------------------------------------------------------------
/src/storage/memory-storage.js:
--------------------------------------------------------------------------------
1 | class MemoryStorage {
2 | constructor(namespace) {
3 | this.namespace = namespace || null;
4 | this._storage = {};
5 | }
6 |
7 | setItem(key, value) {
8 | this._storage[this._getStorageKey(key)] = value;
9 | }
10 |
11 | getItem(key) {
12 | return this._storage[this._getStorageKey(key)];
13 | }
14 |
15 | removeItem(key) {
16 | delete this._storage[this._getStorageKey(key)];
17 | }
18 |
19 | _getStorageKey(key) {
20 | if (this.namespace) {
21 | return [this.namespace, key].join('.');
22 | }
23 | return key;
24 | }
25 | }
26 |
27 | export default MemoryStorage;
28 |
--------------------------------------------------------------------------------
/src/storage/session-storage.js:
--------------------------------------------------------------------------------
1 | import { $window } from '../globals.js';
2 |
3 | class SessionStorage {
4 | constructor(namespace) {
5 | this.namespace = namespace || null;
6 | }
7 |
8 | setItem(key, value) {
9 | $window.sessionStorage.setItem(this._getStorageKey(key), value);
10 | }
11 |
12 | getItem(key) {
13 | return $window.sessionStorage.getItem(this._getStorageKey(key));
14 | }
15 |
16 | removeItem(key) {
17 | $window.sessionStorage.removeItem(this._getStorageKey(key));
18 | }
19 |
20 | _getStorageKey(key) {
21 | if (this.namespace) {
22 | return [this.namespace, key].join('.');
23 | }
24 | return key;
25 | }
26 | }
27 |
28 | export default SessionStorage;
29 |
--------------------------------------------------------------------------------
/src/utils.js:
--------------------------------------------------------------------------------
1 | if (typeof Object.assign != 'function') {
2 | Object.assign = function (target, varArgs) {
3 | 'use strict';
4 | if (target == null) {
5 | throw new TypeError('Cannot convert undefined or null to object');
6 | }
7 |
8 | var to = Object(target);
9 |
10 | for (var index = 1; index < arguments.length; index++) {
11 | var nextSource = arguments[index];
12 |
13 | if (nextSource != null) {
14 | // Skip over if undefined or null
15 | for (var nextKey in nextSource) {
16 | // Avoid bugs when hasOwnProperty is shadowed
17 | if (Object.prototype.hasOwnProperty.call(nextSource, nextKey)) {
18 | to[nextKey] = nextSource[nextKey];
19 | }
20 | }
21 | }
22 | }
23 | return to;
24 | };
25 | }
26 |
27 | export function camelCase(name) {
28 | return name.replace(/([\:\-\_]+(.))/g, function (
29 | _,
30 | separator,
31 | letter,
32 | offset
33 | ) {
34 | return offset ? letter.toUpperCase() : letter;
35 | });
36 | }
37 |
38 | export function isUndefined(value) {
39 | return typeof value === 'undefined';
40 | }
41 |
42 | export function isDefined(value) {
43 | return typeof value !== 'undefined';
44 | }
45 |
46 | export function isObject(value) {
47 | return value !== null && typeof value === 'object';
48 | }
49 |
50 | export function isString(value) {
51 | return typeof value === 'string';
52 | }
53 |
54 | export function isNumber(value) {
55 | return typeof value === 'number';
56 | }
57 |
58 | export function isFunction(value) {
59 | return typeof value === 'function';
60 | }
61 |
62 | export function objectExtend(a, b) {
63 | // Don't touch 'null' or 'undefined' objects.
64 | if (a == null || b == null) {
65 | return a;
66 | }
67 |
68 | Object.keys(b).forEach(function (key) {
69 | if (Object.prototype.toString.call(b[key]) == '[object Object]') {
70 | if (Object.prototype.toString.call(a[key]) != '[object Object]') {
71 | a[key] = b[key];
72 | } else {
73 | a[key] = objectExtend(a[key], b[key]);
74 | }
75 | } else {
76 | a[key] = b[key];
77 | }
78 | });
79 |
80 | return a;
81 | }
82 |
83 | /**
84 | * Assemble url from two segments
85 | *
86 | * @author Sahat Yalkabov
87 | * @copyright Method taken from https://github.com/sahat/satellizer
88 | *
89 | * @param {String} baseUrl Base url
90 | * @param {String} url URI
91 | * @return {String}
92 | */
93 | export function joinUrl(baseUrl, url) {
94 | if (/^(?:[a-z]+:)?\/\//i.test(url)) {
95 | return url;
96 | }
97 | let joined = [baseUrl, url].join('/');
98 | let normalize = function (str) {
99 | return str
100 | .replace(/[\/]+/g, '/')
101 | .replace(/\/\?/g, '?')
102 | .replace(/\/\#/g, '#')
103 | .replace(/\:\//g, '://');
104 | };
105 | return normalize(joined);
106 | }
107 |
108 | /**
109 | * Get full path based on current location
110 | *
111 | * @author Sahat Yalkabov
112 | * @copyright Method taken from https://github.com/sahat/satellizer
113 | *
114 | * @param {Location} location
115 | * @return {String}
116 | */
117 | export function getFullUrlPath(location) {
118 | const isHttps = location.protocol === 'https:';
119 | return (
120 | location.protocol +
121 | '//' +
122 | location.hostname +
123 | ':' +
124 | (location.port || (isHttps ? '443' : '80')) +
125 | (/^\//.test(location.pathname)
126 | ? location.pathname
127 | : '/' + location.pathname)
128 | );
129 | }
130 |
131 | /**
132 | * Parse query string variables
133 | *
134 | * @author Sahat Yalkabov
135 | * @copyright Method taken from https://github.com/sahat/satellizer
136 | *
137 | * @param {String} Query string
138 | * @return {String}
139 | */
140 | export function parseQueryString(str) {
141 | let obj = {};
142 | let key;
143 | let value;
144 | (str || '').split('&').forEach(keyValue => {
145 | if (keyValue) {
146 | value = keyValue.split('=');
147 | key = decodeURIComponent(value[0]);
148 | obj[key] = !!value[1] ? decodeURIComponent(value[1]) : true;
149 | }
150 | });
151 | return obj;
152 | }
153 |
154 | /**
155 | * Decode base64 string
156 | * @author Sahat Yalkabov
157 | * @copyright Method taken from https://github.com/sahat/satellizer
158 | *
159 | * @param {String} str base64 encoded string
160 | * @return {Object}
161 | */
162 | export function decodeBase64(str) {
163 | let buffer;
164 | if (typeof module !== 'undefined' && module.exports) {
165 | try {
166 | buffer = require('buffer').Buffer;
167 | } catch (err) {
168 | // noop
169 | }
170 | }
171 |
172 | let fromCharCode = String.fromCharCode;
173 |
174 | let re_btou = new RegExp(
175 | [
176 | '[\xC0-\xDF][\x80-\xBF]',
177 | '[\xE0-\xEF][\x80-\xBF]{2}',
178 | '[\xF0-\xF7][\x80-\xBF]{3}',
179 | ].join('|'),
180 | 'g'
181 | );
182 |
183 | let cb_btou = function (cccc) {
184 | switch (cccc.length) {
185 | case 4:
186 | let cp =
187 | ((0x07 & cccc.charCodeAt(0)) << 18) |
188 | ((0x3f & cccc.charCodeAt(1)) << 12) |
189 | ((0x3f & cccc.charCodeAt(2)) << 6) |
190 | (0x3f & cccc.charCodeAt(3));
191 | let offset = cp - 0x10000;
192 | return (
193 | fromCharCode((offset >>> 10) + 0xd800) +
194 | fromCharCode((offset & 0x3ff) + 0xdc00)
195 | );
196 | case 3:
197 | return fromCharCode(
198 | ((0x0f & cccc.charCodeAt(0)) << 12) |
199 | ((0x3f & cccc.charCodeAt(1)) << 6) |
200 | (0x3f & cccc.charCodeAt(2))
201 | );
202 | default:
203 | return fromCharCode(
204 | ((0x1f & cccc.charCodeAt(0)) << 6) | (0x3f & cccc.charCodeAt(1))
205 | );
206 | }
207 | };
208 |
209 | let btou = function (b) {
210 | return b.replace(re_btou, cb_btou);
211 | };
212 |
213 | let _decode = buffer
214 | ? function (a) {
215 | return (a.constructor === buffer.constructor
216 | ? a
217 | : new buffer(a, 'base64')
218 | ).toString();
219 | }
220 | : function (a) {
221 | return btou(atob(a));
222 | };
223 |
224 | return _decode(
225 | String(str)
226 | .replace(/[-_]/g, function (m0) {
227 | return m0 === '-' ? '+' : '/';
228 | })
229 | .replace(/[^A-Za-z0-9\+\/]/g, '')
230 | );
231 | }
232 |
233 | export function parseCookies(str = '') {
234 | if (str.length === 0) return {};
235 | const parsed = {};
236 | const pattern = new RegExp('\\s*;\\s*');
237 | str.split(pattern).forEach(i => {
238 | const [encodedKey, encodedValue] = i.split('=');
239 | const key = decodeURIComponent(encodedKey);
240 | const value = decodeURIComponent(encodedValue);
241 | parsed[key] = value;
242 | });
243 | return parsed;
244 | }
245 |
246 | export function formatOptions(options) {
247 | const { path, domain, expires, secure } = options;
248 | return [
249 | typeof path === 'undefined' || path === null ? '' : ';path=' + path,
250 | typeof domain === 'undefined' || domain === null ? '' : ';domain=' + domain,
251 | typeof expires === 'undefined' || expires === null
252 | ? ''
253 | : ';expires=' + expires.toUTCString(),
254 | typeof secure === 'undefined' || secure === null || secure === false
255 | ? ''
256 | : ';secure',
257 | ].join('');
258 | }
259 |
260 | export function formatCookie(key, value, options) {
261 | return [
262 | encodeURIComponent(key),
263 | '=',
264 | encodeURIComponent(value),
265 | formatOptions(options),
266 | ].join('');
267 | }
268 |
269 | export function getObjectProperty(objectRef, propertyName) {
270 | let value = undefined;
271 | let valueRef = objectRef;
272 | const propNames = propertyName.split('.');
273 |
274 | for (var i = 0; i < propNames.length; i++) {
275 | const key = propNames[i];
276 | value = valueRef[key];
277 |
278 | if (isObject(value)) {
279 | valueRef = valueRef[key];
280 | } else {
281 | break;
282 | }
283 | }
284 |
285 | return value;
286 | }
287 |
--------------------------------------------------------------------------------
/yarn.lock:
--------------------------------------------------------------------------------
1 | # THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY.
2 | # yarn lockfile v1
3 |
4 |
5 | "@babel/code-frame@^7.0.0", "@babel/code-frame@^7.8.3":
6 | version "7.8.3"
7 | resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.8.3.tgz#33e25903d7481181534e12ec0a25f16b6fcf419e"
8 | integrity sha512-a9gxpmdXtZEInkCSHUJDLHZVBgb1QS0jhss4cPP93EW7s+uC5bikET2twEF3KV+7rDblJcmNvTR7VJejqd2C2g==
9 | dependencies:
10 | "@babel/highlight" "^7.8.3"
11 |
12 | "@babel/core@^7.9.0":
13 | version "7.9.0"
14 | resolved "https://registry.yarnpkg.com/@babel/core/-/core-7.9.0.tgz#ac977b538b77e132ff706f3b8a4dbad09c03c56e"
15 | integrity sha512-kWc7L0fw1xwvI0zi8OKVBuxRVefwGOrKSQMvrQ3dW+bIIavBY3/NpXmpjMy7bQnLgwgzWQZ8TlM57YHpHNHz4w==
16 | dependencies:
17 | "@babel/code-frame" "^7.8.3"
18 | "@babel/generator" "^7.9.0"
19 | "@babel/helper-module-transforms" "^7.9.0"
20 | "@babel/helpers" "^7.9.0"
21 | "@babel/parser" "^7.9.0"
22 | "@babel/template" "^7.8.6"
23 | "@babel/traverse" "^7.9.0"
24 | "@babel/types" "^7.9.0"
25 | convert-source-map "^1.7.0"
26 | debug "^4.1.0"
27 | gensync "^1.0.0-beta.1"
28 | json5 "^2.1.2"
29 | lodash "^4.17.13"
30 | resolve "^1.3.2"
31 | semver "^5.4.1"
32 | source-map "^0.5.0"
33 |
34 | "@babel/generator@^7.9.0", "@babel/generator@^7.9.5":
35 | version "7.9.5"
36 | resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.9.5.tgz#27f0917741acc41e6eaaced6d68f96c3fa9afaf9"
37 | integrity sha512-GbNIxVB3ZJe3tLeDm1HSn2AhuD/mVcyLDpgtLXa5tplmWrJdF/elxB56XNqCuD6szyNkDi6wuoKXln3QeBmCHQ==
38 | dependencies:
39 | "@babel/types" "^7.9.5"
40 | jsesc "^2.5.1"
41 | lodash "^4.17.13"
42 | source-map "^0.5.0"
43 |
44 | "@babel/helper-function-name@^7.9.5":
45 | version "7.9.5"
46 | resolved "https://registry.yarnpkg.com/@babel/helper-function-name/-/helper-function-name-7.9.5.tgz#2b53820d35275120e1874a82e5aabe1376920a5c"
47 | integrity sha512-JVcQZeXM59Cd1qanDUxv9fgJpt3NeKUaqBqUEvfmQ+BCOKq2xUgaWZW2hr0dkbyJgezYuplEoh5knmrnS68efw==
48 | dependencies:
49 | "@babel/helper-get-function-arity" "^7.8.3"
50 | "@babel/template" "^7.8.3"
51 | "@babel/types" "^7.9.5"
52 |
53 | "@babel/helper-get-function-arity@^7.8.3":
54 | version "7.8.3"
55 | resolved "https://registry.yarnpkg.com/@babel/helper-get-function-arity/-/helper-get-function-arity-7.8.3.tgz#b894b947bd004381ce63ea1db9f08547e920abd5"
56 | integrity sha512-FVDR+Gd9iLjUMY1fzE2SR0IuaJToR4RkCDARVfsBBPSP53GEqSFjD8gNyxg246VUyc/ALRxFaAK8rVG7UT7xRA==
57 | dependencies:
58 | "@babel/types" "^7.8.3"
59 |
60 | "@babel/helper-member-expression-to-functions@^7.8.3":
61 | version "7.8.3"
62 | resolved "https://registry.yarnpkg.com/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.8.3.tgz#659b710498ea6c1d9907e0c73f206eee7dadc24c"
63 | integrity sha512-fO4Egq88utkQFjbPrSHGmGLFqmrshs11d46WI+WZDESt7Wu7wN2G2Iu+NMMZJFDOVRHAMIkB5SNh30NtwCA7RA==
64 | dependencies:
65 | "@babel/types" "^7.8.3"
66 |
67 | "@babel/helper-module-imports@^7.0.0", "@babel/helper-module-imports@^7.8.3":
68 | version "7.8.3"
69 | resolved "https://registry.yarnpkg.com/@babel/helper-module-imports/-/helper-module-imports-7.8.3.tgz#7fe39589b39c016331b6b8c3f441e8f0b1419498"
70 | integrity sha512-R0Bx3jippsbAEtzkpZ/6FIiuzOURPcMjHp+Z6xPe6DtApDJx+w7UYyOLanZqO8+wKR9G10s/FmHXvxaMd9s6Kg==
71 | dependencies:
72 | "@babel/types" "^7.8.3"
73 |
74 | "@babel/helper-module-transforms@^7.9.0":
75 | version "7.9.0"
76 | resolved "https://registry.yarnpkg.com/@babel/helper-module-transforms/-/helper-module-transforms-7.9.0.tgz#43b34dfe15961918707d247327431388e9fe96e5"
77 | integrity sha512-0FvKyu0gpPfIQ8EkxlrAydOWROdHpBmiCiRwLkUiBGhCUPRRbVD2/tm3sFr/c/GWFrQ/ffutGUAnx7V0FzT2wA==
78 | dependencies:
79 | "@babel/helper-module-imports" "^7.8.3"
80 | "@babel/helper-replace-supers" "^7.8.6"
81 | "@babel/helper-simple-access" "^7.8.3"
82 | "@babel/helper-split-export-declaration" "^7.8.3"
83 | "@babel/template" "^7.8.6"
84 | "@babel/types" "^7.9.0"
85 | lodash "^4.17.13"
86 |
87 | "@babel/helper-optimise-call-expression@^7.8.3":
88 | version "7.8.3"
89 | resolved "https://registry.yarnpkg.com/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.8.3.tgz#7ed071813d09c75298ef4f208956006b6111ecb9"
90 | integrity sha512-Kag20n86cbO2AvHca6EJsvqAd82gc6VMGule4HwebwMlwkpXuVqrNRj6CkCV2sKxgi9MyAUnZVnZ6lJ1/vKhHQ==
91 | dependencies:
92 | "@babel/types" "^7.8.3"
93 |
94 | "@babel/helper-replace-supers@^7.8.6":
95 | version "7.8.6"
96 | resolved "https://registry.yarnpkg.com/@babel/helper-replace-supers/-/helper-replace-supers-7.8.6.tgz#5ada744fd5ad73203bf1d67459a27dcba67effc8"
97 | integrity sha512-PeMArdA4Sv/Wf4zXwBKPqVj7n9UF/xg6slNRtZW84FM7JpE1CbG8B612FyM4cxrf4fMAMGO0kR7voy1ForHHFA==
98 | dependencies:
99 | "@babel/helper-member-expression-to-functions" "^7.8.3"
100 | "@babel/helper-optimise-call-expression" "^7.8.3"
101 | "@babel/traverse" "^7.8.6"
102 | "@babel/types" "^7.8.6"
103 |
104 | "@babel/helper-simple-access@^7.8.3":
105 | version "7.8.3"
106 | resolved "https://registry.yarnpkg.com/@babel/helper-simple-access/-/helper-simple-access-7.8.3.tgz#7f8109928b4dab4654076986af575231deb639ae"
107 | integrity sha512-VNGUDjx5cCWg4vvCTR8qQ7YJYZ+HBjxOgXEl7ounz+4Sn7+LMD3CFrCTEU6/qXKbA2nKg21CwhhBzO0RpRbdCw==
108 | dependencies:
109 | "@babel/template" "^7.8.3"
110 | "@babel/types" "^7.8.3"
111 |
112 | "@babel/helper-split-export-declaration@^7.8.3":
113 | version "7.8.3"
114 | resolved "https://registry.yarnpkg.com/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.8.3.tgz#31a9f30070f91368a7182cf05f831781065fc7a9"
115 | integrity sha512-3x3yOeyBhW851hroze7ElzdkeRXQYQbFIb7gLK1WQYsw2GWDay5gAJNw1sWJ0VFP6z5J1whqeXH/WCdCjZv6dA==
116 | dependencies:
117 | "@babel/types" "^7.8.3"
118 |
119 | "@babel/helper-validator-identifier@^7.9.0", "@babel/helper-validator-identifier@^7.9.5":
120 | version "7.9.5"
121 | resolved "https://registry.yarnpkg.com/@babel/helper-validator-identifier/-/helper-validator-identifier-7.9.5.tgz#90977a8e6fbf6b431a7dc31752eee233bf052d80"
122 | integrity sha512-/8arLKUFq882w4tWGj9JYzRpAlZgiWUJ+dtteNTDqrRBz9Iguck9Rn3ykuBDoUwh2TO4tSAJlrxDUOXWklJe4g==
123 |
124 | "@babel/helpers@^7.9.0":
125 | version "7.9.2"
126 | resolved "https://registry.yarnpkg.com/@babel/helpers/-/helpers-7.9.2.tgz#b42a81a811f1e7313b88cba8adc66b3d9ae6c09f"
127 | integrity sha512-JwLvzlXVPjO8eU9c/wF9/zOIN7X6h8DYf7mG4CiFRZRvZNKEF5dQ3H3V+ASkHoIB3mWhatgl5ONhyqHRI6MppA==
128 | dependencies:
129 | "@babel/template" "^7.8.3"
130 | "@babel/traverse" "^7.9.0"
131 | "@babel/types" "^7.9.0"
132 |
133 | "@babel/highlight@^7.8.3":
134 | version "7.9.0"
135 | resolved "https://registry.yarnpkg.com/@babel/highlight/-/highlight-7.9.0.tgz#4e9b45ccb82b79607271b2979ad82c7b68163079"
136 | integrity sha512-lJZPilxX7Op3Nv/2cvFdnlepPXDxi29wxteT57Q965oc5R9v86ztx0jfxVrTcBk8C2kcPkkDa2Z4T3ZsPPVWsQ==
137 | dependencies:
138 | "@babel/helper-validator-identifier" "^7.9.0"
139 | chalk "^2.0.0"
140 | js-tokens "^4.0.0"
141 |
142 | "@babel/parser@^7.8.6", "@babel/parser@^7.9.0":
143 | version "7.9.4"
144 | resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.9.4.tgz#68a35e6b0319bbc014465be43828300113f2f2e8"
145 | integrity sha512-bC49otXX6N0/VYhgOMh4gnP26E9xnDZK3TmbNpxYzzz9BQLBosQwfyOe9/cXUU3txYhTzLCbcqd5c8y/OmCjHA==
146 |
147 | "@babel/template@^7.8.3", "@babel/template@^7.8.6":
148 | version "7.8.6"
149 | resolved "https://registry.yarnpkg.com/@babel/template/-/template-7.8.6.tgz#86b22af15f828dfb086474f964dcc3e39c43ce2b"
150 | integrity sha512-zbMsPMy/v0PWFZEhQJ66bqjhH+z0JgMoBWuikXybgG3Gkd/3t5oQ1Rw2WQhnSrsOmsKXnZOx15tkC4qON/+JPg==
151 | dependencies:
152 | "@babel/code-frame" "^7.8.3"
153 | "@babel/parser" "^7.8.6"
154 | "@babel/types" "^7.8.6"
155 |
156 | "@babel/traverse@^7.8.6", "@babel/traverse@^7.9.0":
157 | version "7.9.5"
158 | resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.9.5.tgz#6e7c56b44e2ac7011a948c21e283ddd9d9db97a2"
159 | integrity sha512-c4gH3jsvSuGUezlP6rzSJ6jf8fYjLj3hsMZRx/nX0h+fmHN0w+ekubRrHPqnMec0meycA2nwCsJ7dC8IPem2FQ==
160 | dependencies:
161 | "@babel/code-frame" "^7.8.3"
162 | "@babel/generator" "^7.9.5"
163 | "@babel/helper-function-name" "^7.9.5"
164 | "@babel/helper-split-export-declaration" "^7.8.3"
165 | "@babel/parser" "^7.9.0"
166 | "@babel/types" "^7.9.5"
167 | debug "^4.1.0"
168 | globals "^11.1.0"
169 | lodash "^4.17.13"
170 |
171 | "@babel/types@^7.8.3", "@babel/types@^7.8.6", "@babel/types@^7.9.0", "@babel/types@^7.9.5":
172 | version "7.9.5"
173 | resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.9.5.tgz#89231f82915a8a566a703b3b20133f73da6b9444"
174 | integrity sha512-XjnvNqenk818r5zMaba+sLQjnbda31UfUURv3ei0qPQw4u+j2jMyJ5b11y8ZHYTRSI3NnInQkkkRT4fLqqPdHg==
175 | dependencies:
176 | "@babel/helper-validator-identifier" "^7.9.5"
177 | lodash "^4.17.13"
178 | to-fast-properties "^2.0.0"
179 |
180 | "@rollup/plugin-buble@^0.21.3":
181 | version "0.21.3"
182 | resolved "https://registry.yarnpkg.com/@rollup/plugin-buble/-/plugin-buble-0.21.3.tgz#1649a915b1d051a4f430d40e7734a7f67a69b33e"
183 | integrity sha512-Iv8cCuFPnMdqV4pcyU+OrfjOfagPArRQ1PyQjx5KgHk3dARedI+8PNTLSMpJts0lQJr8yF2pAU4GxpxCBJ9HYw==
184 | dependencies:
185 | "@rollup/pluginutils" "^3.0.8"
186 | "@types/buble" "^0.19.2"
187 | buble "^0.20.0"
188 |
189 | "@rollup/pluginutils@^3.0.8":
190 | version "3.0.9"
191 | resolved "https://registry.yarnpkg.com/@rollup/pluginutils/-/pluginutils-3.0.9.tgz#aa6adca2c45e5a1b950103a999e3cddfe49fd775"
192 | integrity sha512-TLZavlfPAZYI7v33wQh4mTP6zojne14yok3DNSLcjoG/Hirxfkonn6icP5rrNWRn8nZsirJBFFpijVOJzkUHDg==
193 | dependencies:
194 | "@types/estree" "0.0.39"
195 | estree-walker "^1.0.1"
196 | micromatch "^4.0.2"
197 |
198 | "@types/buble@^0.19.2":
199 | version "0.19.2"
200 | resolved "https://registry.yarnpkg.com/@types/buble/-/buble-0.19.2.tgz#a4289d20b175b3c206aaad80caabdabe3ecdfdd1"
201 | integrity sha512-uUD8zIfXMKThmFkahTXDGI3CthFH1kMg2dOm3KLi4GlC5cbARA64bEcUMbbWdWdE73eoc/iBB9PiTMqH0dNS2Q==
202 | dependencies:
203 | magic-string "^0.25.0"
204 |
205 | "@types/estree@0.0.39":
206 | version "0.0.39"
207 | resolved "https://registry.yarnpkg.com/@types/estree/-/estree-0.0.39.tgz#e177e699ee1b8c22d23174caaa7422644389509f"
208 | integrity sha512-EYNwp3bU+98cpU4lAWYYL7Zz+2gryWH1qbdDTidVd6hkiR6weksdbMadyXKXNPEkQFhXM+hVO9ZygomHXp+AIw==
209 |
210 | acorn-dynamic-import@^4.0.0:
211 | version "4.0.0"
212 | resolved "https://registry.yarnpkg.com/acorn-dynamic-import/-/acorn-dynamic-import-4.0.0.tgz#482210140582a36b83c3e342e1cfebcaa9240948"
213 | integrity sha512-d3OEjQV4ROpoflsnUA8HozoIR504TFxNivYEUi6uwz0IYhBkTDXGuWlNdMtybRt3nqVx/L6XqMt0FxkXuWKZhw==
214 |
215 | acorn-jsx@^5.2.0:
216 | version "5.2.0"
217 | resolved "https://registry.yarnpkg.com/acorn-jsx/-/acorn-jsx-5.2.0.tgz#4c66069173d6fdd68ed85239fc256226182b2ebe"
218 | integrity sha512-HiUX/+K2YpkpJ+SzBffkM/AQ2YE03S0U1kjTLVpoJdhZMOWy8qvXVN9JdLqv2QsaQ6MPYQIuNmwD8zOiYUofLQ==
219 |
220 | acorn@^6.1.1:
221 | version "6.1.1"
222 | resolved "https://registry.yarnpkg.com/acorn/-/acorn-6.1.1.tgz#7d25ae05bb8ad1f9b699108e1094ecd7884adc1f"
223 | integrity sha512-jPTiwtOxaHNaAPg/dmrJ/beuzLRnXtB0kQPQ8JpotKJgTB6rX6c8mlf315941pyjBSaPg8NHXS9fhP4u17DpGA==
224 |
225 | acorn@^6.4.1:
226 | version "6.4.1"
227 | resolved "https://registry.yarnpkg.com/acorn/-/acorn-6.4.1.tgz#531e58ba3f51b9dacb9a6646ca4debf5b14ca474"
228 | integrity sha512-ZVA9k326Nwrj3Cj9jlh3wGFutC2ZornPNARZwsNYqQYgN0EsV2d53w5RN/co65Ohn4sUAUtb1rSUAOD6XN9idA==
229 |
230 | ajv@^6.10.0:
231 | version "6.10.0"
232 | resolved "https://registry.yarnpkg.com/ajv/-/ajv-6.10.0.tgz#90d0d54439da587cd7e843bfb7045f50bd22bdf1"
233 | integrity sha512-nffhOpkymDECQyR0mnsUtoCE8RlX38G0rYP+wgLWFyZuUyuuojSSvi/+euOiQBIn63whYwYVIIH1TvE3tu4OEg==
234 | dependencies:
235 | fast-deep-equal "^2.0.1"
236 | fast-json-stable-stringify "^2.0.0"
237 | json-schema-traverse "^0.4.1"
238 | uri-js "^4.2.2"
239 |
240 | ansi-styles@^3.2.1:
241 | version "3.2.1"
242 | resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-3.2.1.tgz#41fbb20243e50b12be0f04b8dedbf07520ce841d"
243 | integrity sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==
244 | dependencies:
245 | color-convert "^1.9.0"
246 |
247 | axios@^0.18.0:
248 | version "0.18.0"
249 | resolved "https://registry.yarnpkg.com/axios/-/axios-0.18.0.tgz#32d53e4851efdc0a11993b6cd000789d70c05102"
250 | integrity sha1-MtU+SFHv3AoRmTts0AB4nXDAUQI=
251 | dependencies:
252 | follow-redirects "^1.3.0"
253 | is-buffer "^1.1.5"
254 |
255 | braces@^3.0.1:
256 | version "3.0.2"
257 | resolved "https://registry.yarnpkg.com/braces/-/braces-3.0.2.tgz#3454e1a462ee8d599e236df336cd9ea4f8afe107"
258 | integrity sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==
259 | dependencies:
260 | fill-range "^7.0.1"
261 |
262 | buble@^0.20.0:
263 | version "0.20.0"
264 | resolved "https://registry.yarnpkg.com/buble/-/buble-0.20.0.tgz#a143979a8d968b7f76b57f38f2e7ce7cfe938d1f"
265 | integrity sha512-/1gnaMQE8xvd5qsNBl+iTuyjJ9XxeaVxAMF86dQ4EyxFJOZtsgOS8Ra+7WHgZTam5IFDtt4BguN0sH0tVTKrOw==
266 | dependencies:
267 | acorn "^6.4.1"
268 | acorn-dynamic-import "^4.0.0"
269 | acorn-jsx "^5.2.0"
270 | chalk "^2.4.2"
271 | magic-string "^0.25.7"
272 | minimist "^1.2.5"
273 | regexpu-core "4.5.4"
274 |
275 | chalk@^2.0.0, chalk@^2.4.2:
276 | version "2.4.2"
277 | resolved "https://registry.yarnpkg.com/chalk/-/chalk-2.4.2.tgz#cd42541677a54333cf541a49108c1432b44c9424"
278 | integrity sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==
279 | dependencies:
280 | ansi-styles "^3.2.1"
281 | escape-string-regexp "^1.0.5"
282 | supports-color "^5.3.0"
283 |
284 | color-convert@^1.9.0:
285 | version "1.9.3"
286 | resolved "https://registry.yarnpkg.com/color-convert/-/color-convert-1.9.3.tgz#bb71850690e1f136567de629d2d5471deda4c1e8"
287 | integrity sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==
288 | dependencies:
289 | color-name "1.1.3"
290 |
291 | color-name@1.1.3:
292 | version "1.1.3"
293 | resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.3.tgz#a7d0558bd89c42f795dd42328f740831ca53bc25"
294 | integrity sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=
295 |
296 | commander@~2.20.3:
297 | version "2.20.3"
298 | resolved "https://registry.yarnpkg.com/commander/-/commander-2.20.3.tgz#fd485e84c03eb4881c20722ba48035e8531aeb33"
299 | integrity sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==
300 |
301 | convert-source-map@^1.7.0:
302 | version "1.7.0"
303 | resolved "https://registry.yarnpkg.com/convert-source-map/-/convert-source-map-1.7.0.tgz#17a2cb882d7f77d3490585e2ce6c524424a3a442"
304 | integrity sha512-4FJkXzKXEDB1snCFZlLP4gpC3JILicCpGbzG9f9G7tGqGCzETQ2hWPrcinA9oU4wtf2biUaEH5065UnMeR33oA==
305 | dependencies:
306 | safe-buffer "~5.1.1"
307 |
308 | debug@^3.2.6:
309 | version "3.2.6"
310 | resolved "https://registry.yarnpkg.com/debug/-/debug-3.2.6.tgz#e83d17de16d8a7efb7717edbe5fb10135eee629b"
311 | integrity sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ==
312 | dependencies:
313 | ms "^2.1.1"
314 |
315 | debug@^4.1.0:
316 | version "4.1.1"
317 | resolved "https://registry.yarnpkg.com/debug/-/debug-4.1.1.tgz#3b72260255109c6b589cee050f1d516139664791"
318 | integrity sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==
319 | dependencies:
320 | ms "^2.1.1"
321 |
322 | escape-string-regexp@^1.0.5:
323 | version "1.0.5"
324 | resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz#1b61c0562190a8dff6ae3bb2cf0200ca130b86d4"
325 | integrity sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=
326 |
327 | estree-walker@^0.6.1:
328 | version "0.6.1"
329 | resolved "https://registry.yarnpkg.com/estree-walker/-/estree-walker-0.6.1.tgz#53049143f40c6eb918b23671d1fe3219f3a1b362"
330 | integrity sha512-SqmZANLWS0mnatqbSfRP5g8OXZC12Fgg1IwNtLsyHDzJizORW4khDfjPqJZsemPWBB2uqykUah5YpQ6epsqC/w==
331 |
332 | estree-walker@^1.0.1:
333 | version "1.0.1"
334 | resolved "https://registry.yarnpkg.com/estree-walker/-/estree-walker-1.0.1.tgz#31bc5d612c96b704106b477e6dd5d8aa138cb700"
335 | integrity sha512-1fMXF3YP4pZZVozF8j/ZLfvnR8NSIljt56UhbZ5PeeDmmGHpgpdwQt7ITlGvYaQukCvuBRMLEiKiYC+oeIg4cg==
336 |
337 | fast-deep-equal@^2.0.1:
338 | version "2.0.1"
339 | resolved "https://registry.yarnpkg.com/fast-deep-equal/-/fast-deep-equal-2.0.1.tgz#7b05218ddf9667bf7f370bf7fdb2cb15fdd0aa49"
340 | integrity sha1-ewUhjd+WZ79/Nwv3/bLLFf3Qqkk=
341 |
342 | fast-json-stable-stringify@^2.0.0:
343 | version "2.0.0"
344 | resolved "https://registry.yarnpkg.com/fast-json-stable-stringify/-/fast-json-stable-stringify-2.0.0.tgz#d5142c0caee6b1189f87d3a76111064f86c8bbf2"
345 | integrity sha1-1RQsDK7msRifh9OnYREGT4bIu/I=
346 |
347 | fill-range@^7.0.1:
348 | version "7.0.1"
349 | resolved "https://registry.yarnpkg.com/fill-range/-/fill-range-7.0.1.tgz#1919a6a7c75fe38b2c7c77e5198535da9acdda40"
350 | integrity sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==
351 | dependencies:
352 | to-regex-range "^5.0.1"
353 |
354 | follow-redirects@^1.3.0:
355 | version "1.7.0"
356 | resolved "https://registry.yarnpkg.com/follow-redirects/-/follow-redirects-1.7.0.tgz#489ebc198dc0e7f64167bd23b03c4c19b5784c76"
357 | integrity sha512-m/pZQy4Gj287eNy94nivy5wchN3Kp+Q5WgUPNy5lJSZ3sgkVKSYV/ZChMAQVIgx1SqfZ2zBZtPA2YlXIWxxJOQ==
358 | dependencies:
359 | debug "^3.2.6"
360 |
361 | fsevents@~2.1.2:
362 | version "2.1.2"
363 | resolved "https://registry.yarnpkg.com/fsevents/-/fsevents-2.1.2.tgz#4c0a1fb34bc68e543b4b82a9ec392bfbda840805"
364 | integrity sha512-R4wDiBwZ0KzpgOWetKDug1FZcYhqYnUYKtfZYt4mD5SBz76q0KR4Q9o7GIPamsVPGmW3EYPPJ0dOOjvx32ldZA==
365 |
366 | gensync@^1.0.0-beta.1:
367 | version "1.0.0-beta.1"
368 | resolved "https://registry.yarnpkg.com/gensync/-/gensync-1.0.0-beta.1.tgz#58f4361ff987e5ff6e1e7a210827aa371eaac269"
369 | integrity sha512-r8EC6NO1sngH/zdD9fiRDLdcgnbayXah+mLgManTaIZJqEC1MZstmnox8KpnI2/fxQwrp5OpCOYWLp4rBl4Jcg==
370 |
371 | globals@^11.1.0:
372 | version "11.12.0"
373 | resolved "https://registry.yarnpkg.com/globals/-/globals-11.12.0.tgz#ab8795338868a0babd8525758018c2a7eb95c42e"
374 | integrity sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==
375 |
376 | has-flag@^3.0.0:
377 | version "3.0.0"
378 | resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-3.0.0.tgz#b5d454dc2199ae225699f3467e5a07f3b955bafd"
379 | integrity sha1-tdRU3CGZriJWmfNGfloH87lVuv0=
380 |
381 | is-buffer@^1.1.5:
382 | version "1.1.6"
383 | resolved "https://registry.yarnpkg.com/is-buffer/-/is-buffer-1.1.6.tgz#efaa2ea9daa0d7ab2ea13a97b2b8ad51fefbe8be"
384 | integrity sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==
385 |
386 | is-number@^7.0.0:
387 | version "7.0.0"
388 | resolved "https://registry.yarnpkg.com/is-number/-/is-number-7.0.0.tgz#7535345b896734d5f80c4d06c50955527a14f12b"
389 | integrity sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==
390 |
391 | jest-worker@^24.0.0:
392 | version "24.9.0"
393 | resolved "https://registry.yarnpkg.com/jest-worker/-/jest-worker-24.9.0.tgz#5dbfdb5b2d322e98567898238a9697bcce67b3e5"
394 | integrity sha512-51PE4haMSXcHohnSMdM42anbvZANYTqMrr52tVKPqqsPJMzoP6FYYDVqahX/HrAoKEKz3uUPzSvKs9A3qR4iVw==
395 | dependencies:
396 | merge-stream "^2.0.0"
397 | supports-color "^6.1.0"
398 |
399 | js-tokens@^4.0.0:
400 | version "4.0.0"
401 | resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-4.0.0.tgz#19203fb59991df98e3a287050d4647cdeaf32499"
402 | integrity sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==
403 |
404 | jsesc@^2.5.1:
405 | version "2.5.2"
406 | resolved "https://registry.yarnpkg.com/jsesc/-/jsesc-2.5.2.tgz#80564d2e483dacf6e8ef209650a67df3f0c283a4"
407 | integrity sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA==
408 |
409 | jsesc@~0.5.0:
410 | version "0.5.0"
411 | resolved "https://registry.yarnpkg.com/jsesc/-/jsesc-0.5.0.tgz#e7dee66e35d6fc16f710fe91d5cf69f70f08911d"
412 | integrity sha1-597mbjXW/Bb3EP6R1c9p9w8IkR0=
413 |
414 | json-schema-traverse@^0.4.1:
415 | version "0.4.1"
416 | resolved "https://registry.yarnpkg.com/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz#69f6a87d9513ab8bb8fe63bdb0979c448e684660"
417 | integrity sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==
418 |
419 | json5@^2.1.2:
420 | version "2.1.3"
421 | resolved "https://registry.yarnpkg.com/json5/-/json5-2.1.3.tgz#c9b0f7fa9233bfe5807fe66fcf3a5617ed597d43"
422 | integrity sha512-KXPvOm8K9IJKFM0bmdn8QXh7udDh1g/giieX0NLCaMnb4hEiVFqnop2ImTXCc5e0/oHz3LTqmHGtExn5hfMkOA==
423 | dependencies:
424 | minimist "^1.2.5"
425 |
426 | lodash._reinterpolate@^3.0.0:
427 | version "3.0.0"
428 | resolved "https://registry.yarnpkg.com/lodash._reinterpolate/-/lodash._reinterpolate-3.0.0.tgz#0ccf2d89166af03b3663c796538b75ac6e114d9d"
429 | integrity sha1-DM8tiRZq8Ds2Y8eWU4t1rG4RTZ0=
430 |
431 | lodash.template@^4.4.0:
432 | version "4.5.0"
433 | resolved "https://registry.yarnpkg.com/lodash.template/-/lodash.template-4.5.0.tgz#f976195cf3f347d0d5f52483569fe8031ccce8ab"
434 | integrity sha512-84vYFxIkmidUiFxidA/KjjH9pAycqW+h980j7Fuz5qxRtO9pgB7MDFTdys1N7A5mcucRiDyEq4fusljItR1T/A==
435 | dependencies:
436 | lodash._reinterpolate "^3.0.0"
437 | lodash.templatesettings "^4.0.0"
438 |
439 | lodash.templatesettings@^4.0.0:
440 | version "4.2.0"
441 | resolved "https://registry.yarnpkg.com/lodash.templatesettings/-/lodash.templatesettings-4.2.0.tgz#e481310f049d3cf6d47e912ad09313b154f0fb33"
442 | integrity sha512-stgLz+i3Aa9mZgnjr/O+v9ruKZsPsndy7qPZOchbqk2cnTU1ZaldKK+v7m54WoKIyxiuMZTKT2H81F8BeAc3ZQ==
443 | dependencies:
444 | lodash._reinterpolate "^3.0.0"
445 |
446 | lodash@^4.17.13:
447 | version "4.17.15"
448 | resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.15.tgz#b447f6670a0455bbfeedd11392eff330ea097548"
449 | integrity sha512-8xOcRHvCjnocdS5cpwXQXVzmmh5e5+saE2QGoeQmbKmRS6J3VQppPOIt0MnmE+4xlZoumy0GPG0D0MVIQbNA1A==
450 |
451 | magic-string@^0.25.0, magic-string@^0.25.7:
452 | version "0.25.7"
453 | resolved "https://registry.yarnpkg.com/magic-string/-/magic-string-0.25.7.tgz#3f497d6fd34c669c6798dcb821f2ef31f5445051"
454 | integrity sha512-4CrMT5DOHTDk4HYDlzmwu4FVCcIYI8gauveasrdCu2IKIFOJ3f0v/8MDGJCDL9oD2ppz/Av1b0Nj345H9M+XIA==
455 | dependencies:
456 | sourcemap-codec "^1.4.4"
457 |
458 | merge-stream@^2.0.0:
459 | version "2.0.0"
460 | resolved "https://registry.yarnpkg.com/merge-stream/-/merge-stream-2.0.0.tgz#52823629a14dd00c9770fb6ad47dc6310f2c1f60"
461 | integrity sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==
462 |
463 | micromatch@^4.0.2:
464 | version "4.0.2"
465 | resolved "https://registry.yarnpkg.com/micromatch/-/micromatch-4.0.2.tgz#4fcb0999bf9fbc2fcbdd212f6d629b9a56c39259"
466 | integrity sha512-y7FpHSbMUMoyPbYUSzO6PaZ6FyRnQOpHuKwbo1G+Knck95XVU4QAiKdGEnj5wwoS7PlOgthX/09u5iFJ+aYf5Q==
467 | dependencies:
468 | braces "^3.0.1"
469 | picomatch "^2.0.5"
470 |
471 | minimist@^1.2.5:
472 | version "1.2.5"
473 | resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.5.tgz#67d66014b66a6a8aaa0c083c5fd58df4e4e97602"
474 | integrity sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw==
475 |
476 | ms@^2.1.1:
477 | version "2.1.1"
478 | resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.1.tgz#30a5864eb3ebb0a66f2ebe6d727af06a09d86e0a"
479 | integrity sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg==
480 |
481 | path-parse@^1.0.6:
482 | version "1.0.6"
483 | resolved "https://registry.yarnpkg.com/path-parse/-/path-parse-1.0.6.tgz#d62dbb5679405d72c4737ec58600e9ddcf06d24c"
484 | integrity sha512-GSmOT2EbHrINBf9SR7CDELwlJ8AENk3Qn7OikK4nFYAu3Ote2+JYNVvkpAEQm3/TLNEJFD/xZJjzyxg3KBWOzw==
485 |
486 | picomatch@^2.0.5:
487 | version "2.2.2"
488 | resolved "https://registry.yarnpkg.com/picomatch/-/picomatch-2.2.2.tgz#21f333e9b6b8eaff02468f5146ea406d345f4dad"
489 | integrity sha512-q0M/9eZHzmr0AulXyPwNfZjtwZ/RBZlbN3K3CErVrk50T2ASYI7Bye0EvekFY3IP1Nt2DHu0re+V2ZHIpMkuWg==
490 |
491 | punycode@^2.1.0:
492 | version "2.1.1"
493 | resolved "https://registry.yarnpkg.com/punycode/-/punycode-2.1.1.tgz#b58b010ac40c22c5657616c8d2c2c02c7bf479ec"
494 | integrity sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==
495 |
496 | regenerate-unicode-properties@^8.0.2:
497 | version "8.2.0"
498 | resolved "https://registry.yarnpkg.com/regenerate-unicode-properties/-/regenerate-unicode-properties-8.2.0.tgz#e5de7111d655e7ba60c057dbe9ff37c87e65cdec"
499 | integrity sha512-F9DjY1vKLo/tPePDycuH3dn9H1OTPIkVD9Kz4LODu+F2C75mgjAJ7x/gwy6ZcSNRAAkhNlJSOHRe8k3p+K9WhA==
500 | dependencies:
501 | regenerate "^1.4.0"
502 |
503 | regenerate@^1.4.0:
504 | version "1.4.0"
505 | resolved "https://registry.yarnpkg.com/regenerate/-/regenerate-1.4.0.tgz#4a856ec4b56e4077c557589cae85e7a4c8869a11"
506 | integrity sha512-1G6jJVDWrt0rK99kBjvEtziZNCICAuvIPkSiUFIQxVP06RCVpq3dmDo2oi6ABpYaDYaTRr67BEhL8r1wgEZZKg==
507 |
508 | regexpu-core@4.5.4:
509 | version "4.5.4"
510 | resolved "https://registry.yarnpkg.com/regexpu-core/-/regexpu-core-4.5.4.tgz#080d9d02289aa87fe1667a4f5136bc98a6aebaae"
511 | integrity sha512-BtizvGtFQKGPUcTy56o3nk1bGRp4SZOTYrDtGNlqCQufptV5IkkLN6Emw+yunAJjzf+C9FQFtvq7IoA3+oMYHQ==
512 | dependencies:
513 | regenerate "^1.4.0"
514 | regenerate-unicode-properties "^8.0.2"
515 | regjsgen "^0.5.0"
516 | regjsparser "^0.6.0"
517 | unicode-match-property-ecmascript "^1.0.4"
518 | unicode-match-property-value-ecmascript "^1.1.0"
519 |
520 | regjsgen@^0.5.0:
521 | version "0.5.1"
522 | resolved "https://registry.yarnpkg.com/regjsgen/-/regjsgen-0.5.1.tgz#48f0bf1a5ea205196929c0d9798b42d1ed98443c"
523 | integrity sha512-5qxzGZjDs9w4tzT3TPhCJqWdCc3RLYwy9J2NB0nm5Lz+S273lvWcpjaTGHsT1dc6Hhfq41uSEOw8wBmxrKOuyg==
524 |
525 | regjsparser@^0.6.0:
526 | version "0.6.4"
527 | resolved "https://registry.yarnpkg.com/regjsparser/-/regjsparser-0.6.4.tgz#a769f8684308401a66e9b529d2436ff4d0666272"
528 | integrity sha512-64O87/dPDgfk8/RQqC4gkZoGyyWFIEUTTh80CU6CWuK5vkCGyekIx+oKcEIYtP/RAxSQltCZHCNu/mdd7fqlJw==
529 | dependencies:
530 | jsesc "~0.5.0"
531 |
532 | resolve@^1.3.2:
533 | version "1.16.1"
534 | resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.16.1.tgz#49fac5d8bacf1fd53f200fa51247ae736175832c"
535 | integrity sha512-rmAglCSqWWMrrBv/XM6sW0NuRFiKViw/W4d9EbC4pt+49H8JwHy+mcGmALTEg504AUDcLTvb1T2q3E9AnmY+ig==
536 | dependencies:
537 | path-parse "^1.0.6"
538 |
539 | rollup-plugin-babel@^4.4.0:
540 | version "4.4.0"
541 | resolved "https://registry.yarnpkg.com/rollup-plugin-babel/-/rollup-plugin-babel-4.4.0.tgz#d15bd259466a9d1accbdb2fe2fff17c52d030acb"
542 | integrity sha512-Lek/TYp1+7g7I+uMfJnnSJ7YWoD58ajo6Oarhlex7lvUce+RCKRuGRSgztDO3/MF/PuGKmUL5iTHKf208UNszw==
543 | dependencies:
544 | "@babel/helper-module-imports" "^7.0.0"
545 | rollup-pluginutils "^2.8.1"
546 |
547 | rollup-plugin-banner@^0.2.1:
548 | version "0.2.1"
549 | resolved "https://registry.yarnpkg.com/rollup-plugin-banner/-/rollup-plugin-banner-0.2.1.tgz#f62f26c468530ecea16263da83175079625f9c6f"
550 | integrity sha512-Bs1uIPCsGpKIkNOwmBsCqn+dJ/xaojWk9PNlvd+1MEScddr1yUQlO6McAXi72wJyNWYL+9u9EI2JAZMpLRH92w==
551 | dependencies:
552 | lodash.template "^4.4.0"
553 |
554 | rollup-plugin-uglify@^6.0.4:
555 | version "6.0.4"
556 | resolved "https://registry.yarnpkg.com/rollup-plugin-uglify/-/rollup-plugin-uglify-6.0.4.tgz#65a0959d91586627f1e46a7db966fd504ec6c4e6"
557 | integrity sha512-ddgqkH02klveu34TF0JqygPwZnsbhHVI6t8+hGTcYHngPkQb5MIHI0XiztXIN/d6V9j+efwHAqEL7LspSxQXGw==
558 | dependencies:
559 | "@babel/code-frame" "^7.0.0"
560 | jest-worker "^24.0.0"
561 | serialize-javascript "^2.1.2"
562 | uglify-js "^3.4.9"
563 |
564 | rollup-pluginutils@^2.8.1:
565 | version "2.8.2"
566 | resolved "https://registry.yarnpkg.com/rollup-pluginutils/-/rollup-pluginutils-2.8.2.tgz#72f2af0748b592364dbd3389e600e5a9444a351e"
567 | integrity sha512-EEp9NhnUkwY8aif6bxgovPHMoMoNr2FulJziTndpt5H9RdwC47GSGuII9XxpSdzVGM0GWrNPHV6ie1LTNJPaLQ==
568 | dependencies:
569 | estree-walker "^0.6.1"
570 |
571 | rollup@^2.6.1:
572 | version "2.6.1"
573 | resolved "https://registry.yarnpkg.com/rollup/-/rollup-2.6.1.tgz#8354e67caa7b8bf24c2488d9e2f64da2be62eebe"
574 | integrity sha512-1RhFDRJeg027YjBO6+JxmVWkEZY0ASztHhoEUEWxOwkh4mjO58TFD6Uo7T7Y3FbmDpRTfKhM5NVxJyimCn0Elg==
575 | optionalDependencies:
576 | fsevents "~2.1.2"
577 |
578 | safe-buffer@~5.1.1:
579 | version "5.1.2"
580 | resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.1.2.tgz#991ec69d296e0313747d59bdfd2b745c35f8828d"
581 | integrity sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==
582 |
583 | semver@^5.4.1:
584 | version "5.7.1"
585 | resolved "https://registry.yarnpkg.com/semver/-/semver-5.7.1.tgz#a954f931aeba508d307bbf069eff0c01c96116f7"
586 | integrity sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==
587 |
588 | serialize-javascript@^2.1.2:
589 | version "2.1.2"
590 | resolved "https://registry.yarnpkg.com/serialize-javascript/-/serialize-javascript-2.1.2.tgz#ecec53b0e0317bdc95ef76ab7074b7384785fa61"
591 | integrity sha512-rs9OggEUF0V4jUSecXazOYsLfu7OGK2qIn3c7IPBiffz32XniEp/TX9Xmc9LQfK2nQ2QKHvZ2oygKUGU0lG4jQ==
592 |
593 | source-map@^0.5.0:
594 | version "0.5.7"
595 | resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.5.7.tgz#8a039d2d1021d22d1ea14c80d8ea468ba2ef3fcc"
596 | integrity sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=
597 |
598 | sourcemap-codec@^1.4.4:
599 | version "1.4.8"
600 | resolved "https://registry.yarnpkg.com/sourcemap-codec/-/sourcemap-codec-1.4.8.tgz#ea804bd94857402e6992d05a38ef1ae35a9ab4c4"
601 | integrity sha512-9NykojV5Uih4lgo5So5dtw+f0JgJX30KCNI8gwhz2J9A15wD0Ml6tjHKwf6fTSa6fAdVBdZeNOs9eJ71qCk8vA==
602 |
603 | supports-color@^5.3.0:
604 | version "5.5.0"
605 | resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-5.5.0.tgz#e2e69a44ac8772f78a1ec0b35b689df6530efc8f"
606 | integrity sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==
607 | dependencies:
608 | has-flag "^3.0.0"
609 |
610 | supports-color@^6.1.0:
611 | version "6.1.0"
612 | resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-6.1.0.tgz#0764abc69c63d5ac842dd4867e8d025e880df8f3"
613 | integrity sha512-qe1jfm1Mg7Nq/NSh6XE24gPXROEVsWHxC1LIx//XNlD9iw7YZQGjZNjYN7xGaEG6iKdA8EtNFW6R0gjnVXp+wQ==
614 | dependencies:
615 | has-flag "^3.0.0"
616 |
617 | to-fast-properties@^2.0.0:
618 | version "2.0.0"
619 | resolved "https://registry.yarnpkg.com/to-fast-properties/-/to-fast-properties-2.0.0.tgz#dc5e698cbd079265bc73e0377681a4e4e83f616e"
620 | integrity sha1-3F5pjL0HkmW8c+A3doGk5Og/YW4=
621 |
622 | to-regex-range@^5.0.1:
623 | version "5.0.1"
624 | resolved "https://registry.yarnpkg.com/to-regex-range/-/to-regex-range-5.0.1.tgz#1648c44aae7c8d988a326018ed72f5b4dd0392e4"
625 | integrity sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==
626 | dependencies:
627 | is-number "^7.0.0"
628 |
629 | uglify-js@^3.4.9, uglify-js@^3.9.1:
630 | version "3.9.1"
631 | resolved "https://registry.yarnpkg.com/uglify-js/-/uglify-js-3.9.1.tgz#a56a71c8caa2d36b5556cc1fd57df01ae3491539"
632 | integrity sha512-JUPoL1jHsc9fOjVFHdQIhqEEJsQvfKDjlubcCilu8U26uZ73qOg8VsN8O1jbuei44ZPlwL7kmbAdM4tzaUvqnA==
633 | dependencies:
634 | commander "~2.20.3"
635 |
636 | unicode-canonical-property-names-ecmascript@^1.0.4:
637 | version "1.0.4"
638 | resolved "https://registry.yarnpkg.com/unicode-canonical-property-names-ecmascript/-/unicode-canonical-property-names-ecmascript-1.0.4.tgz#2619800c4c825800efdd8343af7dd9933cbe2818"
639 | integrity sha512-jDrNnXWHd4oHiTZnx/ZG7gtUTVp+gCcTTKr8L0HjlwphROEW3+Him+IpvC+xcJEFegapiMZyZe02CyuOnRmbnQ==
640 |
641 | unicode-match-property-ecmascript@^1.0.4:
642 | version "1.0.4"
643 | resolved "https://registry.yarnpkg.com/unicode-match-property-ecmascript/-/unicode-match-property-ecmascript-1.0.4.tgz#8ed2a32569961bce9227d09cd3ffbb8fed5f020c"
644 | integrity sha512-L4Qoh15vTfntsn4P1zqnHulG0LdXgjSO035fEpdtp6YxXhMT51Q6vgM5lYdG/5X3MjS+k/Y9Xw4SFCY9IkR0rg==
645 | dependencies:
646 | unicode-canonical-property-names-ecmascript "^1.0.4"
647 | unicode-property-aliases-ecmascript "^1.0.4"
648 |
649 | unicode-match-property-value-ecmascript@^1.1.0:
650 | version "1.2.0"
651 | resolved "https://registry.yarnpkg.com/unicode-match-property-value-ecmascript/-/unicode-match-property-value-ecmascript-1.2.0.tgz#0d91f600eeeb3096aa962b1d6fc88876e64ea531"
652 | integrity sha512-wjuQHGQVofmSJv1uVISKLE5zO2rNGzM/KCYZch/QQvez7C1hUhBIuZ701fYXExuufJFMPhv2SyL8CyoIfMLbIQ==
653 |
654 | unicode-property-aliases-ecmascript@^1.0.4:
655 | version "1.1.0"
656 | resolved "https://registry.yarnpkg.com/unicode-property-aliases-ecmascript/-/unicode-property-aliases-ecmascript-1.1.0.tgz#dd57a99f6207bedff4628abefb94c50db941c8f4"
657 | integrity sha512-PqSoPh/pWetQ2phoj5RLiaqIk4kCNwoV3CI+LfGmWLKI3rE3kl1h59XpX2BjgDrmbxD9ARtQobPGU1SguCYuQg==
658 |
659 | uri-js@^4.2.2:
660 | version "4.2.2"
661 | resolved "https://registry.yarnpkg.com/uri-js/-/uri-js-4.2.2.tgz#94c540e1ff772956e2299507c010aea6c8838eb0"
662 | integrity sha512-KY9Frmirql91X2Qgjry0Wd4Y+YTdrdZheS8TFwvkbLWf/G5KNJDCh6pKL5OZctEW4+0Baa5idK2ZQuELRwPznQ==
663 | dependencies:
664 | punycode "^2.1.0"
665 |
666 | vue-axios@^2.1.4:
667 | version "2.1.4"
668 | resolved "https://registry.yarnpkg.com/vue-axios/-/vue-axios-2.1.4.tgz#a9d298f7e876f9a87feb336b37adcbce34ff9f9f"
669 | integrity sha512-DS8Q+WFT3i7nS0aZ/NMmTPf2yhbtlXhj4QEZmY69au/BshsGzGjC6dXaniZaPQlErP3J3Sv1HtQ4RVrXaUTkxA==
670 |
671 | vue@^2.6.10:
672 | version "2.6.10"
673 | resolved "https://registry.yarnpkg.com/vue/-/vue-2.6.10.tgz#a72b1a42a4d82a721ea438d1b6bf55e66195c637"
674 | integrity sha512-ImThpeNU9HbdZL3utgMCq0oiMzAkt1mcgy3/E6zWC/G6AaQoeuFdsl9nDhTDU3X1R6FK7nsIUuRACVcjI+A2GQ==
675 |
--------------------------------------------------------------------------------