diff --git a/app/api.js b/app/api.js index a816e63c..58b75cb0 100644 --- a/app/api.js +++ b/app/api.js @@ -65,14 +65,6 @@ export async function fileInfo(id, owner_token) { throw new Error(response.status); } -export async function hasPassword(id) { - const response = await fetch(`/api/exists/${id}`); - if (response.ok) { - return response.json(); - } - throw new Error(response.status); -} - export async function metadata(id, keychain) { const result = await fetchWithAuthAndRetry( `/api/metadata/${id}`, @@ -141,6 +133,7 @@ async function upload( metadata, verifierB64, timeLimit, + bearerToken, onprogress, canceller ) { @@ -159,6 +152,7 @@ async function upload( const fileMeta = { fileMetadata: metadataHeader, authorization: `send-v1 ${verifierB64}`, + bearer: bearerToken, timeLimit }; @@ -200,8 +194,9 @@ export function uploadWs( encrypted, metadata, verifierB64, - onprogress, - timeLimit + timeLimit, + bearerToken, + onprogress ) { const canceller = { cancelled: false }; @@ -216,6 +211,7 @@ export function uploadWs( metadata, verifierB64, timeLimit, + bearerToken, onprogress, canceller ) @@ -332,3 +328,19 @@ export function downloadFile(id, keychain, onprogress) { result: tryDownload(id, keychain, onprogress, canceller, 2) }; } + +export async function getFileList(bearerToken) { + const headers = new Headers({ Authorization: `Bearer ${bearerToken}` }); + const response = await fetch('/api/filelist', { headers }); + return response.body; // stream +} + +export async function setFileList(bearerToken, data) { + const headers = new Headers({ Authorization: `Bearer ${bearerToken}` }); + const response = await fetch('/api/filelist', { + headers, + method: 'POST', + body: data + }); + return response.status === 200; +} diff --git a/app/archive.js b/app/archive.js index 24d1a2de..6cdce5f4 100644 --- a/app/archive.js +++ b/app/archive.js @@ -1,4 +1,4 @@ -/* global MAXFILESIZE */ +/* global LIMITS */ import { blobStream, concatStream } from './streams'; function isDupe(newFile, array) { @@ -15,7 +15,7 @@ function isDupe(newFile, array) { } export default class Archive { - constructor(files) { + constructor(files = []) { this.files = Array.from(files); } @@ -49,20 +49,19 @@ export default class Archive { return concatStream(this.files.map(file => blobStream(file))); } - addFiles(files) { + addFiles(files, maxSize) { + if (this.files.length + files.length > LIMITS.MAX_FILES_PER_ARCHIVE) { + throw new Error('tooManyFiles'); + } const newFiles = files.filter(file => !isDupe(file, this.files)); const newSize = newFiles.reduce((total, file) => total + file.size, 0); - if (this.size + newSize > MAXFILESIZE) { - return false; + if (this.size + newSize > maxSize) { + throw new Error('fileTooBig'); } this.files = this.files.concat(newFiles); return true; } - checkSize() { - return this.size <= MAXFILESIZE; - } - remove(index) { this.files.splice(index, 1); } diff --git a/app/fileManager.js b/app/fileManager.js index 204034ad..4dd61ad3 100644 --- a/app/fileManager.js +++ b/app/fileManager.js @@ -1,12 +1,11 @@ -/* global MAXFILESIZE */ -/* global DEFAULT_EXPIRE_SECONDS */ +/* global DEFAULTS LIMITS */ import FileSender from './fileSender'; import FileReceiver from './fileReceiver'; import { copyToClipboard, delay, openLinksInNewTab, percent } from './utils'; import * as metrics from './metrics'; -import { hasPassword } from './api'; import Archive from './archive'; import { bytes } from './utils'; +import { prepareWrapKey } from './fxa'; export default function(state, emitter) { let lastRender = 0; @@ -17,19 +16,8 @@ export default function(state, emitter) { } async function checkFiles() { - const files = state.storage.files.slice(); - let rerender = false; - for (const file of files) { - const oldLimit = file.dlimit; - const oldTotal = file.dtotal; - await file.updateDownloadCount(); - if (file.dtotal === file.dlimit) { - state.storage.remove(file.id); - rerender = true; - } else if (oldLimit !== file.dlimit || oldTotal !== file.dtotal) { - rerender = true; - } - } + const changes = await state.user.syncFileList(); + const rerender = changes.incoming || changes.downloadCount; if (rerender) { render(); } @@ -57,6 +45,16 @@ export default function(state, emitter) { lastRender = Date.now(); }); + emitter.on('login', async () => { + const k = await prepareWrapKey(state.storage); + location.assign(`/api/fxa/login?keys_jwk=${k}`); + }); + + emitter.on('logout', () => { + state.user.logout(); + render(); + }); + emitter.on('changeLimit', async ({ file, value }) => { await file.changeLimit(value); state.storage.writeFile(file); @@ -90,29 +88,37 @@ export default function(state, emitter) { }); emitter.on('addFiles', async ({ files }) => { - if (state.archive) { - if (!state.archive.addFiles(files)) { - // eslint-disable-next-line no-alert - alert(state.translate('fileTooBig', { size: bytes(MAXFILESIZE) })); - return; - } - } else { - const archive = new Archive(files); - if (!archive.checkSize()) { - // eslint-disable-next-line no-alert - alert(state.translate('fileTooBig', { size: bytes(MAXFILESIZE) })); - return; - } - state.archive = archive; + const maxSize = state.user.maxSize; + state.archive = state.archive || new Archive(); + try { + state.archive.addFiles(files, maxSize); + } catch (e) { + alert( + state.translate(e.message, { + size: bytes(maxSize), + count: LIMITS.MAX_FILES_PER_ARCHIVE + }) + ); } render(); }); emitter.on('upload', async ({ type, dlCount, password }) => { if (!state.archive) return; + if (state.storage.files.length >= LIMITS.MAX_ARCHIVES_PER_USER) { + return alert( + state.translate('tooManyArchives', { + count: LIMITS.MAX_ARCHIVES_PER_USER + }) + ); + } const size = state.archive.size; - if (!state.timeLimit) state.timeLimit = DEFAULT_EXPIRE_SECONDS; - const sender = new FileSender(state.archive, state.timeLimit); + if (!state.timeLimit) state.timeLimit = DEFAULTS.EXPIRE_SECONDS; + const sender = new FileSender( + state.archive, + state.timeLimit, + state.user.bearerToken + ); sender.on('progress', updateProgress); sender.on('encrypting', render); @@ -132,7 +138,6 @@ export default function(state, emitter) { metrics.completedUpload(ownedFile); state.storage.addFile(ownedFile); - if (password) { emitter.emit('password', { password, file: ownedFile }); } @@ -185,17 +190,6 @@ export default function(state, emitter) { render(); }); - emitter.on('getPasswordExist', async ({ id }) => { - try { - state.fileInfo = await hasPassword(id); - render(); - } catch (e) { - if (e.message === '404') { - return emitter.emit('pushState', '/404'); - } - } - }); - emitter.on('getMetadata', async () => { const file = state.fileInfo; @@ -204,7 +198,7 @@ export default function(state, emitter) { await receiver.getMetadata(); state.transfer = receiver; } catch (e) { - if (e.message === '401') { + if (e.message === '401' || e.message === '404') { file.password = null; if (!file.requiresPassword) { return emitter.emit('pushState', '/404'); diff --git a/app/fileReceiver.js b/app/fileReceiver.js index 4546ad0a..0971905b 100644 --- a/app/fileReceiver.js +++ b/app/fileReceiver.js @@ -1,6 +1,6 @@ import Nanobus from 'nanobus'; import Keychain from './keychain'; -import { delay, bytes } from './utils'; +import { delay, bytes, streamToArrayBuffer } from './utils'; import { downloadFile, metadata } from './api'; import { blobStream } from './streams'; import Zip from './zip'; @@ -191,20 +191,6 @@ export default class FileReceiver extends Nanobus { } } -async function streamToArrayBuffer(stream, size) { - const result = new Uint8Array(size); - let offset = 0; - const reader = stream.getReader(); - let state = await reader.read(); - while (!state.done) { - result.set(state.value, offset); - offset += state.value.length; - state = await reader.read(); - } - - return result.buffer; -} - async function saveFile(file) { return new Promise(function(resolve, reject) { const dataView = new DataView(file.plaintext); diff --git a/app/fileSender.js b/app/fileSender.js index 42d67e40..9eaef301 100644 --- a/app/fileSender.js +++ b/app/fileSender.js @@ -1,4 +1,4 @@ -/* global DEFAULT_EXPIRE_SECONDS */ +/* global DEFAULTS */ import Nanobus from 'nanobus'; import OwnedFile from './ownedFile'; import Keychain from './keychain'; @@ -7,9 +7,10 @@ import { uploadWs } from './api'; import { encryptedSize } from './ece'; export default class FileSender extends Nanobus { - constructor(file, timeLimit) { + constructor(file, timeLimit, bearerToken) { super('FileSender'); - this.timeLimit = timeLimit || DEFAULT_EXPIRE_SECONDS; + this.timeLimit = timeLimit || DEFAULTS.EXPIRE_SECONDS; + this.bearerToken = bearerToken; this.file = file; this.keychain = new Keychain(); this.reset(); @@ -75,11 +76,12 @@ export default class FileSender extends Nanobus { encStream, metadata, authKeyB64, + this.timeLimit, + this.bearerToken, p => { this.progress = [p, totalSize]; this.emit('progress'); - }, - this.timeLimit + } ); if (this.cancelled) { diff --git a/app/fxa.js b/app/fxa.js new file mode 100644 index 00000000..fe6eba38 --- /dev/null +++ b/app/fxa.js @@ -0,0 +1,44 @@ +import jose from 'node-jose'; +import { arrayToB64, b64ToArray } from './utils'; + +const encoder = new TextEncoder(); + +export async function prepareWrapKey(storage) { + const keystore = jose.JWK.createKeyStore(); + const keypair = await keystore.generate('EC', 'P-256'); + storage.set('fxaWrapKey', JSON.stringify(keystore.toJSON(true))); + return jose.util.base64url.encode(JSON.stringify(keypair.toJSON())); +} + +export async function getFileListKey(storage, bundle) { + const keystore = await jose.JWK.asKeyStore( + JSON.parse(storage.get('fxaWrapKey')) + ); + const result = await jose.JWE.createDecrypt(keystore).decrypt(bundle); + const jwks = JSON.parse(jose.util.utf8.encode(result.plaintext)); + const jwk = jwks['https://identity.mozilla.com/apps/send']; + const baseKey = await crypto.subtle.importKey( + 'raw', + b64ToArray(jwk.k), + { name: 'HKDF' }, + false, + ['deriveKey'] + ); + const fileListKey = await crypto.subtle.deriveKey( + { + name: 'HKDF', + salt: new Uint8Array(), + info: encoder.encode('fileList'), + hash: 'SHA-256' + }, + baseKey, + { + name: 'AES-GCM', + length: 128 + }, + true, + ['encrypt', 'decrypt'] + ); + const rawFileListKey = await crypto.subtle.exportKey('raw', fileListKey); + return arrayToB64(new Uint8Array(rawFileListKey)); +} diff --git a/app/main.js b/app/main.js index ce4140a2..141299cc 100644 --- a/app/main.js +++ b/app/main.js @@ -1,3 +1,4 @@ +/* global userInfo */ import 'fast-text-encoding'; // MS Edge support import 'fluent-intl-polyfill'; import app from './routes'; @@ -11,6 +12,8 @@ import metrics from './metrics'; import experiments from './experiments'; import Raven from 'raven-js'; import './main.css'; +import User from './user'; +import { getFileListKey } from './fxa'; (async function start() { if (navigator.doNotTrack !== '1' && window.RAVEN_CONFIG) { @@ -20,6 +23,9 @@ import './main.css'; if (capa.streamDownload) { navigator.serviceWorker.register('/serviceWorker.js'); } + if (userInfo && userInfo.keys_jwe) { + userInfo.fileListKey = await getFileListKey(storage, userInfo.keys_jwe); + } app.use((state, emitter) => { state.capabilities = capa; state.transfer = null; @@ -27,6 +33,7 @@ import './main.css'; state.translate = locale.getTranslator(); state.storage = storage; state.raven = Raven; + state.user = new User(userInfo, storage); window.appState = state; let unsupportedReason = null; if ( diff --git a/app/ownedFile.js b/app/ownedFile.js index 3b4dfbae..7fd8a94b 100644 --- a/app/ownedFile.js +++ b/app/ownedFile.js @@ -22,6 +22,14 @@ export default class OwnedFile { this.timeLimit = obj.timeLimit; } + get hasPassword() { + return !!this._hasPassword; + } + + get expired() { + return this.dlimit === this.dtotal || Date.now() > this.expiresAt; + } + async setPassword(password) { try { this.password = password; @@ -48,11 +56,9 @@ export default class OwnedFile { return Promise.resolve(true); } - get hasPassword() { - return !!this._hasPassword; - } - async updateDownloadCount() { + const oldTotal = this.dtotal; + const oldLimit = this.dlimit; try { const result = await fileInfo(this.id, this.ownerToken); this.dtotal = result.dtotal; @@ -63,6 +69,7 @@ export default class OwnedFile { } // ignore other errors } + return oldTotal !== this.dtotal || oldLimit !== this.dlimit; } toJSON() { diff --git a/app/pages/preview/index.js b/app/pages/preview/index.js index aa86d862..076d26c8 100644 --- a/app/pages/preview/index.js +++ b/app/pages/preview/index.js @@ -4,7 +4,7 @@ const downloadButton = require('../../templates/downloadButton'); const downloadedFiles = require('../../templates/uploadedFileList'); module.exports = function(state, emit) { - const ownedFile = state.storage.getFileById(state.params.id); + const fileInfo = state.fileInfo; const trySendLink = html` @@ -25,7 +25,7 @@ module.exports = function(state, emit) {
${titleSection(state)} - ${downloadedFiles(ownedFile, state, emit)} + ${downloadedFiles(fileInfo, state, emit)}
${state.translate('downloadMessage2')}
${downloadButton(state, emit)} diff --git a/app/pages/welcome/index.js b/app/pages/welcome/index.js index ad818aa5..c64a1416 100644 --- a/app/pages/welcome/index.js +++ b/app/pages/welcome/index.js @@ -62,11 +62,11 @@ module.exports = function(state, emit) { onfocus=${onfocus} onblur=${onblur} onchange=${addFiles} /> - +
- ${expireInfo(state)} + ${expireInfo(state, emit)} ${setPasswordSection(state)}
diff --git a/app/routes/download.js b/app/routes/download.js index cf815330..722a6b45 100644 --- a/app/routes/download.js +++ b/app/routes/download.js @@ -1,15 +1,21 @@ +/* global downloadMetadata */ const preview = require('../pages/preview'); const password = require('../pages/password'); +function createFileInfo(state) { + return { + id: state.params.id, + secretKey: state.params.key, + nonce: downloadMetadata.nonce, + requiresPassword: downloadMetadata.pwd + }; +} + module.exports = function(state, emit) { if (!state.fileInfo) { - emit('getPasswordExist', { id: state.params.id }); - return; + state.fileInfo = createFileInfo(state); } - state.fileInfo.id = state.params.id; - state.fileInfo.secretKey = state.params.key; - if (!state.transfer && !state.fileInfo.requiresPassword) { emit('getMetadata'); } diff --git a/app/routes/index.js b/app/routes/index.js index db337e70..d596001f 100644 --- a/app/routes/index.js +++ b/app/routes/index.js @@ -38,7 +38,7 @@ function body(template) {
- ${profile(state)} + ${profile(state, emit)} ${template(state, emit)}
@@ -67,7 +67,11 @@ app.route('/unsupported/:reason', body(require('../pages/unsupported'))); app.route('/legal', body(require('../pages/legal'))); app.route('/error', body(require('../pages/error'))); app.route('/blank', body(require('../pages/blank'))); -app.route('*', body(require('../pages/notFound'))); app.route('/signin', body(require('../pages/signin'))); +app.route('/api/fxa/oauth', function(state, emit) { + emit('replaceState', '/'); + setTimeout(() => emit('render')); +}); +app.route('*', body(require('../pages/notFound'))); module.exports = app; diff --git a/app/storage.js b/app/storage.js index 3981b259..2edc5d94 100644 --- a/app/storage.js +++ b/app/storage.js @@ -38,7 +38,7 @@ class Storage { } loadFiles() { - const fs = []; + const fs = new Map(); for (let i = 0; i < this.engine.length; i++) { const k = this.engine.key(i); if (isFile(k)) { @@ -48,14 +48,14 @@ class Storage { f.id = f.fileId; } - fs.push(f); + fs.set(f.id, f); } catch (err) { // obviously you're not a golfer this.engine.removeItem(k); } } } - return fs.sort((a, b) => a.createdAt - b.createdAt); + return fs; } get totalDownloads() { @@ -90,26 +90,44 @@ class Storage { } get files() { - return this._files; + return Array.from(this._files.values()).sort( + (a, b) => a.createdAt - b.createdAt + ); + } + + get user() { + try { + return JSON.parse(this.engine.getItem('user')); + } catch (e) { + return null; + } + } + + set user(info) { + return this.engine.setItem('user', JSON.stringify(info)); } getFileById(id) { - return this._files.find(f => f.id === id); + return this._files.get(id); } get(id) { return this.engine.getItem(id); } + set(id, value) { + return this.engine.setItem(id, value); + } + remove(property) { if (isFile(property)) { - this._files.splice(this._files.findIndex(f => f.id === property), 1); + this._files.delete(property); } this.engine.removeItem(property); } addFile(file) { - this._files.push(file); + this._files.set(file.id, file); this.writeFile(file); } @@ -120,6 +138,39 @@ class Storage { writeFiles() { this._files.forEach(f => this.writeFile(f)); } + + clearLocalFiles() { + this._files.forEach(f => this.engine.removeItem(f.id)); + this._files = new Map(); + } + + async merge(files = []) { + let incoming = false; + let outgoing = false; + let downloadCount = false; + for (const f of files) { + if (!this.getFileById(f.id)) { + this.addFile(new OwnedFile(f)); + incoming = true; + } + } + const workingFiles = this.files.slice(); + for (const f of workingFiles) { + const cc = await f.updateDownloadCount(); + downloadCount = downloadCount || cc; + outgoing = outgoing || f.expired; + if (f.expired) { + this.remove(f.id); + } else if (!files.find(x => x.id === f.id)) { + outgoing = true; + } + } + return { + incoming, + outgoing, + downloadCount + }; + } } export default new Storage(); diff --git a/app/templates/expireInfo/index.js b/app/templates/expireInfo/index.js index ce4332cb..fa7a91b8 100644 --- a/app/templates/expireInfo/index.js +++ b/app/templates/expireInfo/index.js @@ -3,7 +3,7 @@ const raw = require('choo/html/raw'); const selectbox = require('../selectbox'); const timeLimitText = require('../timeLimitText'); -module.exports = function(state) { +module.exports = function(state, emit) { const el = html`
${raw( state.translate('frontPageExpireInfo', { downloadCount: '', @@ -11,15 +11,25 @@ module.exports = function(state) { }) )}
`; + if (el.__encoded) { + // we're rendering on the server + return el; + } const dlCountSelect = el.querySelector('#dlCount'); el.replaceChild( selectbox( state.downloadCount || 1, - [1, 2, 3, 4, 5, 20], + [1, 2, 3, 4, 5, 20, 50, 100, 200], num => state.translate('downloadCount', { num }), value => { + const max = state.user.maxDownloads; + if (value > max) { + alert('todo: this setting requires an account'); + value = max; + } state.downloadCount = value; + emit('render'); } ), dlCountSelect @@ -29,10 +39,16 @@ module.exports = function(state) { el.replaceChild( selectbox( state.timeLimit || 86400, - [300, 3600, 86400, 604800, 1209600], + [300, 3600, 86400, 604800], num => timeLimitText(state.translate, num), value => { + const max = state.user.maxExpireSeconds; + if (value > max) { + alert('todo: this setting requires an account'); + value = max; + } state.timeLimit = value; + emit('render'); } ), timeSelect diff --git a/app/templates/userAccount/index.js b/app/templates/userAccount/index.js index 9a63fd5e..ff7a9490 100644 --- a/app/templates/userAccount/index.js +++ b/app/templates/userAccount/index.js @@ -1,33 +1,41 @@ const html = require('choo/html'); -const assets = require('../../../common/assets'); -// eslint-disable-next-line no-unused-vars -module.exports = function(state) { - const notLoggedInMenu = html` +module.exports = function(state, emit) { + const user = state.user; + const menu = user.loggedIn + ? html` +
` + : html` `; return html` `; function avatarClick(event) { @@ -37,6 +45,16 @@ module.exports = function(state) { dropdown.focus(); } + function login(event) { + event.preventDefault(); + emit('login'); + } + + function logout(event) { + event.preventDefault(); + emit('logout'); + } + //the onblur trick makes links unclickable wtf /* function hideMenu(event) { diff --git a/app/templates/userAccount/userAccount.css b/app/templates/userAccount/userAccount.css index fa532684..44ae4feb 100644 --- a/app/templates/userAccount/userAccount.css +++ b/app/templates/userAccount/userAccount.css @@ -5,12 +5,18 @@ padding: 0; } +.account__avatar { + height: 32px; + width: 32px; + border-radius: 50%; +} + .account_dropdown { z-index: 2; position: absolute; top: 30px; left: -15px; - width: 150px; + min-width: 150px; list-style-type: none; border: 1px solid #ccc; border-radius: 4px; @@ -62,3 +68,11 @@ background-color: var(--primaryControlBGColor); color: var(--primaryControlFGColor); } + +.account_dropdown__text { + display: block; + padding: 0 14px; + font-size: 13px; + color: var(--lightTextColor); + line-height: 24px; +} diff --git a/app/user.js b/app/user.js new file mode 100644 index 00000000..22668dcd --- /dev/null +++ b/app/user.js @@ -0,0 +1,102 @@ +/* global LIMITS */ +import assets from '../common/assets'; +import { getFileList, setFileList } from './api'; +import { encryptStream, decryptStream } from './ece'; +import { b64ToArray, streamToArrayBuffer } from './utils'; +import { blobStream } from './streams'; + +const textEncoder = new TextEncoder(); +const textDecoder = new TextDecoder(); + +export default class User { + constructor(info, storage) { + if (info && storage) { + storage.user = info; + } + this.storage = storage; + this.data = info || storage.user || {}; + } + + get avatar() { + const defaultAvatar = assets.get('user.svg'); + if (this.data.avatarDefault) { + return defaultAvatar; + } + return this.data.avatar || defaultAvatar; + } + + get name() { + return this.data.displayName; + } + + get email() { + return this.data.email; + } + + get loggedIn() { + return !!this.data.access_token; + } + + get bearerToken() { + return this.data.access_token; + } + + get maxSize() { + return this.loggedIn ? LIMITS.MAX_FILE_SIZE : LIMITS.ANON.MAX_FILE_SIZE; + } + + get maxExpireSeconds() { + return this.loggedIn + ? LIMITS.MAX_EXPIRE_SECONDS + : LIMITS.ANON.MAX_EXPIRE_SECONDS; + } + + get maxDownloads() { + return this.loggedIn ? LIMITS.MAX_DOWNLOADS : LIMITS.ANON.MAX_DOWNLOADS; + } + + login() {} + + logout() { + this.storage.user = null; + this.storage.clearLocalFiles(); + this.data = {}; + } + + async syncFileList() { + let changes = { incoming: false, outgoing: false, downloadCount: false }; + if (!this.loggedIn) { + return this.storage.merge(); + } + let list = []; + try { + const encrypted = await getFileList(this.bearerToken); + const decrypted = await streamToArrayBuffer( + decryptStream(encrypted, b64ToArray(this.data.fileListKey)) + ); + list = JSON.parse(textDecoder.decode(decrypted)); + } catch (e) { + // + } + changes = await this.storage.merge(list); + if (!changes.outgoing) { + return changes; + } + try { + const blob = new Blob([ + textEncoder.encode(JSON.stringify(this.storage.files)) + ]); + const encrypted = await streamToArrayBuffer( + encryptStream(blobStream(blob), b64ToArray(this.data.fileListKey)) + ); + await setFileList(this.bearerToken, encrypted); + } catch (e) { + // + } + return changes; + } + + toJSON() { + return this.data; + } +} diff --git a/app/utils.js b/app/utils.js index 8e5e5302..263aaa39 100644 --- a/app/utils.js +++ b/app/utils.js @@ -151,6 +151,37 @@ function browserName() { } } +async function streamToArrayBuffer(stream, size) { + const reader = stream.getReader(); + let state = await reader.read(); + + if (size) { + const result = new Uint8Array(size); + let offset = 0; + while (!state.done) { + result.set(state.value, offset); + offset += state.value.length; + state = await reader.read(); + } + return result.buffer; + } + + const parts = []; + let len = 0; + while (!state.done) { + parts.push(state.value); + len += state.value.length; + state = await reader.read(); + } + let offset = 0; + const result = new Uint8Array(len); + for (const part of parts) { + result.set(part, offset); + offset += part.length; + } + return result.buffer; +} + module.exports = { fadeOut, delay, @@ -164,5 +195,6 @@ module.exports = { loadShim, isFile, openLinksInNewTab, - browserName + browserName, + streamToArrayBuffer }; diff --git a/package-lock.json b/package-lock.json index 28a7cf5b..db732c80 100644 --- a/package-lock.json +++ b/package-lock.json @@ -888,11 +888,6 @@ "resolved": "https://registry.npmjs.org/async-limiter/-/async-limiter-1.0.0.tgz", "integrity": "sha512-jp/uFnooOiO+L211eZOoSyzpOITMXx1rBITauYykG3BRYPu8h0UcxsPNB04RR5vo4Tyz3+ay17tR6JVf9qzYWg==" }, - "asyncc": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/asyncc/-/asyncc-2.0.3.tgz", - "integrity": "sha512-aaZsHXP6vMebFl2hsR7zJmhnRyeGkLFcPKBP0FuOerdIgervBjPlEV7H6cQGtu6fV0l6O/7KO+nPrlfCLWOTUQ==" - }, "atob": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/atob/-/atob-2.1.1.tgz", @@ -926,9 +921,9 @@ } }, "aws-sdk": { - "version": "2.288.0", - "resolved": "https://registry.npmjs.org/aws-sdk/-/aws-sdk-2.288.0.tgz", - "integrity": "sha512-kV0yLAP3DPfUpDfFOCvOn4s/69XqVH7D53Vnfgf6mgKO5bp1HVFpWfTJ/OZeiwRy7hfIi0xTiSEmPXaMG0ACkg==", + "version": "2.291.0", + "resolved": "https://registry.npmjs.org/aws-sdk/-/aws-sdk-2.291.0.tgz", + "integrity": "sha512-al/oJuKN2mokw4nafloptGrmdzm4UZ8AeLuM2bFtPmb0nvwajOr/vSa/XhQTw+T07Vm9T8iJyWyqygq74E/YMQ==", "requires": { "buffer": "4.9.1", "events": "1.1.1", @@ -1781,7 +1776,8 @@ "balanced-match": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz", - "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=" + "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=", + "dev": true }, "base": { "version": "0.11.2", @@ -1843,6 +1839,12 @@ "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.3.0.tgz", "integrity": "sha512-ccav/yGvoa80BQDljCxsmmQ3Xvx60/UpBIij5QN21W3wBi/hhIC9OoO+KLpu9IJTS9j4DRVJ3aDDF9cMSoa2lw==" }, + "base64url": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/base64url/-/base64url-3.0.0.tgz", + "integrity": "sha512-LIVmqIrIWuiqTvn4RzcrwCOuHo2DD6tKmKBPXXlr4p4n4l6BZBkwFTIa3zu1XkX5MbZgro4a6BvPi+n2Mns5Gg==", + "dev": true + }, "batch": { "version": "0.6.1", "resolved": "https://registry.npmjs.org/batch/-/batch-0.6.1.tgz", @@ -1922,6 +1924,7 @@ "version": "1.1.11", "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dev": true, "requires": { "balanced-match": "^1.0.0", "concat-map": "0.0.1" @@ -2592,7 +2595,8 @@ "commander": { "version": "2.16.0", "resolved": "https://registry.npmjs.org/commander/-/commander-2.16.0.tgz", - "integrity": "sha512-sVXqklSaotK9at437sFlFpyOcJonxe0yST/AG9DkQKUdIE6IqGIMv4SfAQSKaJbSdVEJYItASCrBiVQHq1HQew==" + "integrity": "sha512-sVXqklSaotK9at437sFlFpyOcJonxe0yST/AG9DkQKUdIE6IqGIMv4SfAQSKaJbSdVEJYItASCrBiVQHq1HQew==", + "dev": true }, "commondir": { "version": "1.0.1", @@ -2649,7 +2653,8 @@ "concat-map": { "version": "0.0.1", "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", - "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=" + "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=", + "dev": true }, "concat-stream": { "version": "1.6.2", @@ -4337,7 +4342,7 @@ }, "event-stream": { "version": "3.3.4", - "resolved": "https://registry.npmjs.org/event-stream/-/event-stream-3.3.4.tgz", + "resolved": "http://registry.npmjs.org/event-stream/-/event-stream-3.3.4.tgz", "integrity": "sha1-SrTJoPWlTbkzi0w02Gv86PSzVXE=", "dev": true, "requires": { @@ -5082,7 +5087,8 @@ "fs.realpath": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", - "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=" + "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=", + "dev": true }, "fsevents": { "version": "1.2.4", @@ -5097,27 +5103,27 @@ "dependencies": { "abbrev": { "version": "1.1.1", - "resolved": false, + "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.1.1.tgz", "integrity": "sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==", "dev": true, "optional": true }, "ansi-regex": { "version": "2.1.1", - "resolved": false, + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=", "dev": true }, "aproba": { "version": "1.2.0", - "resolved": false, + "resolved": "https://registry.npmjs.org/aproba/-/aproba-1.2.0.tgz", "integrity": "sha512-Y9J6ZjXtoYh8RnXVCMOU/ttDmk1aBjunq9vO0ta5x85WDQiQfUF9sIPBITdbiiIVcBo03Hi3jMxigBtsddlXRw==", "dev": true, "optional": true }, "are-we-there-yet": { "version": "1.1.4", - "resolved": false, + "resolved": "https://registry.npmjs.org/are-we-there-yet/-/are-we-there-yet-1.1.4.tgz", "integrity": "sha1-u13KOCu5TwXhUZQ3PRb9O6HKEQ0=", "dev": true, "optional": true, @@ -5128,13 +5134,13 @@ }, "balanced-match": { "version": "1.0.0", - "resolved": false, + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz", "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=", "dev": true }, "brace-expansion": { "version": "1.1.11", - "resolved": false, + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", "dev": true, "requires": { @@ -5144,39 +5150,39 @@ }, "chownr": { "version": "1.0.1", - "resolved": false, + "resolved": "https://registry.npmjs.org/chownr/-/chownr-1.0.1.tgz", "integrity": "sha1-4qdQQqlVGQi+vSW4Uj1fl2nXkYE=", "dev": true, "optional": true }, "code-point-at": { "version": "1.1.0", - "resolved": false, + "resolved": "https://registry.npmjs.org/code-point-at/-/code-point-at-1.1.0.tgz", "integrity": "sha1-DQcLTQQ6W+ozovGkDi7bPZpMz3c=", "dev": true }, "concat-map": { "version": "0.0.1", - "resolved": false, + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=", "dev": true }, "console-control-strings": { "version": "1.1.0", - "resolved": false, + "resolved": "https://registry.npmjs.org/console-control-strings/-/console-control-strings-1.1.0.tgz", "integrity": "sha1-PXz0Rk22RG6mRL9LOVB/mFEAjo4=", "dev": true }, "core-util-is": { "version": "1.0.2", - "resolved": false, + "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=", "dev": true, "optional": true }, "debug": { "version": "2.6.9", - "resolved": false, + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", "dev": true, "optional": true, @@ -5186,28 +5192,28 @@ }, "deep-extend": { "version": "0.5.1", - "resolved": false, + "resolved": "https://registry.npmjs.org/deep-extend/-/deep-extend-0.5.1.tgz", "integrity": "sha512-N8vBdOa+DF7zkRrDCsaOXoCs/E2fJfx9B9MrKnnSiHNh4ws7eSys6YQE4KvT1cecKmOASYQBhbKjeuDD9lT81w==", "dev": true, "optional": true }, "delegates": { "version": "1.0.0", - "resolved": false, + "resolved": "https://registry.npmjs.org/delegates/-/delegates-1.0.0.tgz", "integrity": "sha1-hMbhWbgZBP3KWaDvRM2HDTElD5o=", "dev": true, "optional": true }, "detect-libc": { "version": "1.0.3", - "resolved": false, + "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-1.0.3.tgz", "integrity": "sha1-+hN8S9aY7fVc1c0CrFWfkaTEups=", "dev": true, "optional": true }, "fs-minipass": { "version": "1.2.5", - "resolved": false, + "resolved": "https://registry.npmjs.org/fs-minipass/-/fs-minipass-1.2.5.tgz", "integrity": "sha512-JhBl0skXjUPCFH7x6x61gQxrKyXsxB5gcgePLZCwfyCGGsTISMoIeObbrvVeP6Xmyaudw4TT43qV2Gz+iyd2oQ==", "dev": true, "optional": true, @@ -5217,14 +5223,14 @@ }, "fs.realpath": { "version": "1.0.0", - "resolved": false, + "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=", "dev": true, "optional": true }, "gauge": { "version": "2.7.4", - "resolved": false, + "resolved": "https://registry.npmjs.org/gauge/-/gauge-2.7.4.tgz", "integrity": "sha1-LANAXHU4w51+s3sxcCLjJfsBi/c=", "dev": true, "optional": true, @@ -5241,7 +5247,7 @@ }, "glob": { "version": "7.1.2", - "resolved": false, + "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.2.tgz", "integrity": "sha512-MJTUg1kjuLeQCJ+ccE4Vpa6kKVXkPYJ2mOCQyUuKLcLQsdrMCpBPUi8qVE6+YuaJkozeA9NusTAw3hLr8Xe5EQ==", "dev": true, "optional": true, @@ -5256,14 +5262,14 @@ }, "has-unicode": { "version": "2.0.1", - "resolved": false, + "resolved": "https://registry.npmjs.org/has-unicode/-/has-unicode-2.0.1.tgz", "integrity": "sha1-4Ob+aijPUROIVeCG0Wkedx3iqLk=", "dev": true, "optional": true }, "iconv-lite": { "version": "0.4.21", - "resolved": false, + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.21.tgz", "integrity": "sha512-En5V9za5mBt2oUA03WGD3TwDv0MKAruqsuxstbMUZaj9W9k/m1CV/9py3l0L5kw9Bln8fdHQmzHSYtvpvTLpKw==", "dev": true, "optional": true, @@ -5273,7 +5279,7 @@ }, "ignore-walk": { "version": "3.0.1", - "resolved": false, + "resolved": "https://registry.npmjs.org/ignore-walk/-/ignore-walk-3.0.1.tgz", "integrity": "sha512-DTVlMx3IYPe0/JJcYP7Gxg7ttZZu3IInhuEhbchuqneY9wWe5Ojy2mXLBaQFUQmo0AW2r3qG7m1mg86js+gnlQ==", "dev": true, "optional": true, @@ -5283,7 +5289,7 @@ }, "inflight": { "version": "1.0.6", - "resolved": false, + "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", "dev": true, "optional": true, @@ -5294,20 +5300,20 @@ }, "inherits": { "version": "2.0.3", - "resolved": false, + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=", "dev": true }, "ini": { "version": "1.3.5", - "resolved": false, + "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.5.tgz", "integrity": "sha512-RZY5huIKCMRWDUqZlEi72f/lmXKMvuszcMBduliQ3nnWbx9X/ZBQO7DijMEYS9EhHBb2qacRUMtC7svLwe0lcw==", "dev": true, "optional": true }, "is-fullwidth-code-point": { "version": "1.0.0", - "resolved": false, + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz", "integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=", "dev": true, "requires": { @@ -5316,14 +5322,14 @@ }, "isarray": { "version": "1.0.0", - "resolved": false, + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", "dev": true, "optional": true }, "minimatch": { "version": "3.0.4", - "resolved": false, + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", "dev": true, "requires": { @@ -5332,13 +5338,13 @@ }, "minimist": { "version": "0.0.8", - "resolved": false, + "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz", "integrity": "sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0=", "dev": true }, "minipass": { "version": "2.2.4", - "resolved": false, + "resolved": "https://registry.npmjs.org/minipass/-/minipass-2.2.4.tgz", "integrity": "sha512-hzXIWWet/BzWhYs2b+u7dRHlruXhwdgvlTMDKC6Cb1U7ps6Ac6yQlR39xsbjWJE377YTCtKwIXIpJ5oP+j5y8g==", "dev": true, "requires": { @@ -5348,7 +5354,7 @@ }, "minizlib": { "version": "1.1.0", - "resolved": false, + "resolved": "https://registry.npmjs.org/minizlib/-/minizlib-1.1.0.tgz", "integrity": "sha512-4T6Ur/GctZ27nHfpt9THOdRZNgyJ9FZchYO1ceg5S8Q3DNLCKYy44nCZzgCJgcvx2UM8czmqak5BCxJMrq37lA==", "dev": true, "optional": true, @@ -5358,7 +5364,7 @@ }, "mkdirp": { "version": "0.5.1", - "resolved": false, + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz", "integrity": "sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM=", "dev": true, "requires": { @@ -5367,14 +5373,14 @@ }, "ms": { "version": "2.0.0", - "resolved": false, + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", "dev": true, "optional": true }, "needle": { "version": "2.2.0", - "resolved": false, + "resolved": "https://registry.npmjs.org/needle/-/needle-2.2.0.tgz", "integrity": "sha512-eFagy6c+TYayorXw/qtAdSvaUpEbBsDwDyxYFgLZ0lTojfH7K+OdBqAF7TAFwDokJaGpubpSGG0wO3iC0XPi8w==", "dev": true, "optional": true, @@ -5386,7 +5392,7 @@ }, "node-pre-gyp": { "version": "0.10.0", - "resolved": false, + "resolved": "https://registry.npmjs.org/node-pre-gyp/-/node-pre-gyp-0.10.0.tgz", "integrity": "sha512-G7kEonQLRbcA/mOoFoxvlMrw6Q6dPf92+t/l0DFSMuSlDoWaI9JWIyPwK0jyE1bph//CUEL65/Fz1m2vJbmjQQ==", "dev": true, "optional": true, @@ -5405,7 +5411,7 @@ }, "nopt": { "version": "4.0.1", - "resolved": false, + "resolved": "https://registry.npmjs.org/nopt/-/nopt-4.0.1.tgz", "integrity": "sha1-0NRoWv1UFRk8jHUFYC0NF81kR00=", "dev": true, "optional": true, @@ -5416,14 +5422,14 @@ }, "npm-bundled": { "version": "1.0.3", - "resolved": false, + "resolved": "https://registry.npmjs.org/npm-bundled/-/npm-bundled-1.0.3.tgz", "integrity": "sha512-ByQ3oJ/5ETLyglU2+8dBObvhfWXX8dtPZDMePCahptliFX2iIuhyEszyFk401PZUNQH20vvdW5MLjJxkwU80Ow==", "dev": true, "optional": true }, "npm-packlist": { "version": "1.1.10", - "resolved": false, + "resolved": "https://registry.npmjs.org/npm-packlist/-/npm-packlist-1.1.10.tgz", "integrity": "sha512-AQC0Dyhzn4EiYEfIUjCdMl0JJ61I2ER9ukf/sLxJUcZHfo+VyEfz2rMJgLZSS1v30OxPQe1cN0LZA1xbcaVfWA==", "dev": true, "optional": true, @@ -5434,7 +5440,7 @@ }, "npmlog": { "version": "4.1.2", - "resolved": false, + "resolved": "https://registry.npmjs.org/npmlog/-/npmlog-4.1.2.tgz", "integrity": "sha512-2uUqazuKlTaSI/dC8AzicUck7+IrEaOnN/e0jd3Xtt1KcGpwx30v50mL7oPyr/h9bL3E4aZccVwpwP+5W9Vjkg==", "dev": true, "optional": true, @@ -5447,20 +5453,20 @@ }, "number-is-nan": { "version": "1.0.1", - "resolved": false, + "resolved": "https://registry.npmjs.org/number-is-nan/-/number-is-nan-1.0.1.tgz", "integrity": "sha1-CXtgK1NCKlIsGvuHkDGDNpQaAR0=", "dev": true }, "object-assign": { "version": "4.1.1", - "resolved": false, + "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=", "dev": true, "optional": true }, "once": { "version": "1.4.0", - "resolved": false, + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", "dev": true, "requires": { @@ -5469,21 +5475,21 @@ }, "os-homedir": { "version": "1.0.2", - "resolved": false, + "resolved": "https://registry.npmjs.org/os-homedir/-/os-homedir-1.0.2.tgz", "integrity": "sha1-/7xJiDNuDoM94MFox+8VISGqf7M=", "dev": true, "optional": true }, "os-tmpdir": { "version": "1.0.2", - "resolved": false, + "resolved": "https://registry.npmjs.org/os-tmpdir/-/os-tmpdir-1.0.2.tgz", "integrity": "sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ=", "dev": true, "optional": true }, "osenv": { "version": "0.1.5", - "resolved": false, + "resolved": "https://registry.npmjs.org/osenv/-/osenv-0.1.5.tgz", "integrity": "sha512-0CWcCECdMVc2Rw3U5w9ZjqX6ga6ubk1xDVKxtBQPK7wis/0F2r9T6k4ydGYhecl7YUBxBVxhL5oisPsNxAPe2g==", "dev": true, "optional": true, @@ -5494,21 +5500,21 @@ }, "path-is-absolute": { "version": "1.0.1", - "resolved": false, + "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=", "dev": true, "optional": true }, "process-nextick-args": { "version": "2.0.0", - "resolved": false, + "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.0.tgz", "integrity": "sha512-MtEC1TqN0EU5nephaJ4rAtThHtC86dNN9qCuEhtshvpVBkAW5ZO7BASN9REnF9eoXGcRub+pFuKEpOHE+HbEMw==", "dev": true, "optional": true }, "rc": { "version": "1.2.7", - "resolved": false, + "resolved": "https://registry.npmjs.org/rc/-/rc-1.2.7.tgz", "integrity": "sha512-LdLD8xD4zzLsAT5xyushXDNscEjB7+2ulnl8+r1pnESlYtlJtVSoCMBGr30eDRJ3+2Gq89jK9P9e4tCEH1+ywA==", "dev": true, "optional": true, @@ -5521,7 +5527,7 @@ "dependencies": { "minimist": { "version": "1.2.0", - "resolved": false, + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=", "dev": true, "optional": true @@ -5530,7 +5536,7 @@ }, "readable-stream": { "version": "2.3.6", - "resolved": false, + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.6.tgz", "integrity": "sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw==", "dev": true, "optional": true, @@ -5546,7 +5552,7 @@ }, "rimraf": { "version": "2.6.2", - "resolved": false, + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.6.2.tgz", "integrity": "sha512-lreewLK/BlghmxtfH36YYVg1i8IAce4TI7oao75I1g245+6BctqTVQiBP3YUJ9C6DQOXJmkYR9X9fCLtCOJc5w==", "dev": true, "optional": true, @@ -5556,48 +5562,48 @@ }, "safe-buffer": { "version": "5.1.1", - "resolved": false, + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.1.tgz", "integrity": "sha512-kKvNJn6Mm93gAczWVJg7wH+wGYWNrDHdWvpUmHyEsgCtIwwo3bqPtV4tR5tuPaUhTOo/kvhVwd8XwwOllGYkbg==", "dev": true }, "safer-buffer": { "version": "2.1.2", - "resolved": false, + "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==", "dev": true, "optional": true }, "sax": { "version": "1.2.4", - "resolved": false, + "resolved": "https://registry.npmjs.org/sax/-/sax-1.2.4.tgz", "integrity": "sha512-NqVDv9TpANUjFm0N8uM5GxL36UgKi9/atZw+x7YFnQ8ckwFGKrl4xX4yWtrey3UJm5nP1kUbnYgLopqWNSRhWw==", "dev": true, "optional": true }, "semver": { "version": "5.5.0", - "resolved": false, + "resolved": "https://registry.npmjs.org/semver/-/semver-5.5.0.tgz", "integrity": "sha512-4SJ3dm0WAwWy/NVeioZh5AntkdJoWKxHxcmyP622fOkgHa4z3R0TdBJICINyaSDE6uNwVc8gZr+ZinwZAH4xIA==", "dev": true, "optional": true }, "set-blocking": { "version": "2.0.0", - "resolved": false, + "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", "integrity": "sha1-BF+XgtARrppoA93TgrJDkrPYkPc=", "dev": true, "optional": true }, "signal-exit": { "version": "3.0.2", - "resolved": false, + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.2.tgz", "integrity": "sha1-tf3AjxKH6hF4Yo5BXiUTK3NkbG0=", "dev": true, "optional": true }, "string-width": { "version": "1.0.2", - "resolved": false, + "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=", "dev": true, "requires": { @@ -5608,7 +5614,7 @@ }, "string_decoder": { "version": "1.1.1", - "resolved": false, + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", "dev": true, "optional": true, @@ -5618,7 +5624,7 @@ }, "strip-ansi": { "version": "3.0.1", - "resolved": false, + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", "dev": true, "requires": { @@ -5627,14 +5633,14 @@ }, "strip-json-comments": { "version": "2.0.1", - "resolved": false, + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz", "integrity": "sha1-PFMZQukIwml8DsNEhYwobHygpgo=", "dev": true, "optional": true }, "tar": { "version": "4.4.1", - "resolved": false, + "resolved": "https://registry.npmjs.org/tar/-/tar-4.4.1.tgz", "integrity": "sha512-O+v1r9yN4tOsvl90p5HAP4AEqbYhx4036AGMm075fH9F8Qwi3oJ+v4u50FkT/KkvywNGtwkk0zRI+8eYm1X/xg==", "dev": true, "optional": true, @@ -5650,14 +5656,14 @@ }, "util-deprecate": { "version": "1.0.2", - "resolved": false, + "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=", "dev": true, "optional": true }, "wide-align": { "version": "1.1.2", - "resolved": false, + "resolved": "https://registry.npmjs.org/wide-align/-/wide-align-1.1.2.tgz", "integrity": "sha512-ijDLlyQ7s6x1JgCLur53osjm/UXUYD9+0PbYKrBsYisYXzCxN+HC3mYDNy/dWdmf3AwqwU3CXwDCvsNgGK1S0w==", "dev": true, "optional": true, @@ -5667,13 +5673,13 @@ }, "wrappy": { "version": "1.0.2", - "resolved": false, + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=", "dev": true }, "yallist": { "version": "3.0.2", - "resolved": false, + "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.0.2.tgz", "integrity": "sha1-hFK0u36Dx8GI2AQcGoN8dz1ti7k=", "dev": true } @@ -5736,6 +5742,7 @@ "version": "7.1.2", "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.2.tgz", "integrity": "sha512-MJTUg1kjuLeQCJ+ccE4Vpa6kKVXkPYJ2mOCQyUuKLcLQsdrMCpBPUi8qVE6+YuaJkozeA9NusTAw3hLr8Xe5EQ==", + "dev": true, "requires": { "fs.realpath": "^1.0.0", "inflight": "^1.0.4", @@ -6355,6 +6362,7 @@ "version": "1.0.6", "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", + "dev": true, "requires": { "once": "^1.3.0", "wrappy": "1" @@ -7445,7 +7453,7 @@ }, "onetime": { "version": "1.1.0", - "resolved": "https://registry.npmjs.org/onetime/-/onetime-1.1.0.tgz", + "resolved": "http://registry.npmjs.org/onetime/-/onetime-1.1.0.tgz", "integrity": "sha1-ofeDj4MUxRbwXs78vEzP4EtO14k=", "dev": true }, @@ -7520,7 +7528,8 @@ "lodash": { "version": "4.17.10", "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.10.tgz", - "integrity": "sha512-UejweD1pDoXu+AD825lWwp4ZGtSwgnpZxb3JDViD7StjQz+Nb/6l093lx4OQ0foGWNRoc19mWy7BzL+UAK2iVg==" + "integrity": "sha512-UejweD1pDoXu+AD825lWwp4ZGtSwgnpZxb3JDViD7StjQz+Nb/6l093lx4OQ0foGWNRoc19mWy7BzL+UAK2iVg==", + "dev": true }, "lodash._reinterpolate": { "version": "3.0.0", @@ -7528,12 +7537,24 @@ "integrity": "sha1-DM8tiRZq8Ds2Y8eWU4t1rG4RTZ0=", "dev": true }, + "lodash.assign": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/lodash.assign/-/lodash.assign-4.2.0.tgz", + "integrity": "sha1-DZnzzNem0mHRm9rrkkUAXShYCOc=", + "dev": true + }, "lodash.camelcase": { "version": "4.3.0", "resolved": "https://registry.npmjs.org/lodash.camelcase/-/lodash.camelcase-4.3.0.tgz", "integrity": "sha1-soqmKIorn8ZRA1x3EfZathkDMaY=", "dev": true }, + "lodash.clone": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/lodash.clone/-/lodash.clone-4.5.0.tgz", + "integrity": "sha1-GVhwRQ9aExkkeN9Lw9I9LeoZB7Y=", + "dev": true + }, "lodash.clonedeep": { "version": "4.5.0", "resolved": "https://registry.npmjs.org/lodash.clonedeep/-/lodash.clonedeep-4.5.0.tgz", @@ -7545,18 +7566,60 @@ "integrity": "sha1-gteb/zCmfEAF/9XiUVMArZyk168=", "dev": true }, + "lodash.fill": { + "version": "3.4.0", + "resolved": "https://registry.npmjs.org/lodash.fill/-/lodash.fill-3.4.0.tgz", + "integrity": "sha1-o8dK5kDQU63w3CB5+HIHiOi/74U=", + "dev": true + }, + "lodash.flatten": { + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/lodash.flatten/-/lodash.flatten-4.4.0.tgz", + "integrity": "sha1-8xwiIlqWMtK7+OSt2+8kCqdlph8=", + "dev": true + }, "lodash.get": { "version": "4.4.2", "resolved": "https://registry.npmjs.org/lodash.get/-/lodash.get-4.4.2.tgz", "integrity": "sha1-LRd/ZS+jHpObRDjVNBSZ36OCXpk=", "dev": true }, + "lodash.intersection": { + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/lodash.intersection/-/lodash.intersection-4.4.0.tgz", + "integrity": "sha1-ChG6Yx0OlcI8fy9Mu5ppLtF45wU=", + "dev": true + }, "lodash.memoize": { "version": "4.1.2", "resolved": "https://registry.npmjs.org/lodash.memoize/-/lodash.memoize-4.1.2.tgz", "integrity": "sha1-vMbEmkKihA7Zl/Mj6tpezRguC/4=", "dev": true }, + "lodash.merge": { + "version": "4.6.1", + "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.1.tgz", + "integrity": "sha512-AOYza4+Hf5z1/0Hztxpm2/xiPZgi/cjMqdnKTUWTBSKchJlxXXuUSxCCl8rJlf4g6yww/j6mA8nC8Hw/EZWxKQ==", + "dev": true + }, + "lodash.omit": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/lodash.omit/-/lodash.omit-4.5.0.tgz", + "integrity": "sha1-brGa5aHuHdnfC5aeZs4Lf6MLXmA=", + "dev": true + }, + "lodash.partialright": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/lodash.partialright/-/lodash.partialright-4.2.1.tgz", + "integrity": "sha1-ATDYDoM2MmTUAHTzKbij56ihzEs=", + "dev": true + }, + "lodash.pick": { + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/lodash.pick/-/lodash.pick-4.4.0.tgz", + "integrity": "sha1-UvBWEP/53tQiYRRB7R/BI6AwAbM=", + "dev": true + }, "lodash.template": { "version": "4.4.0", "resolved": "https://registry.npmjs.org/lodash.template/-/lodash.template-4.4.0.tgz", @@ -7649,7 +7712,7 @@ }, "onetime": { "version": "1.1.0", - "resolved": "https://registry.npmjs.org/onetime/-/onetime-1.1.0.tgz", + "resolved": "http://registry.npmjs.org/onetime/-/onetime-1.1.0.tgz", "integrity": "sha1-ofeDj4MUxRbwXs78vEzP4EtO14k=", "dev": true }, @@ -8012,6 +8075,7 @@ "version": "3.0.4", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", + "dev": true, "requires": { "brace-expansion": "^1.1.7" } @@ -8423,12 +8487,48 @@ "resolved": "https://registry.npmjs.org/nocache/-/nocache-2.0.0.tgz", "integrity": "sha1-ICtIAhoMTL3i34DeFaF0Q8i0OYA=" }, + "node-fetch": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.2.0.tgz", + "integrity": "sha512-OayFWziIxiHY8bCUyLX6sTpDH8Jsbp4FfYd1j1f7vZyfgkcOnAyM4oQR16f8a0s7Gl/viMGRey8eScYk4V4EZA==" + }, "node-forge": { "version": "0.7.5", "resolved": "https://registry.npmjs.org/node-forge/-/node-forge-0.7.5.tgz", "integrity": "sha512-MmbQJ2MTESTjt3Gi/3yG1wGpIMhUfcIypUCGtTizFR9IiccFwxSpfp0vtIZlkFclEqERemxfnSdZEMR9VqqEFQ==", "dev": true }, + "node-jose": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/node-jose/-/node-jose-1.0.0.tgz", + "integrity": "sha512-RE3P8l60Rj9ELrpPmvw6sOQ1hSyYfmQdNUMCa4EN7nCE1ux5JVX+GfXv+mfUTEMhZwNMwxBtI0+X1CKKeukSVQ==", + "dev": true, + "requires": { + "base64url": "^3.0.0", + "es6-promise": "^4.0.5", + "lodash.assign": "^4.0.8", + "lodash.clone": "^4.3.2", + "lodash.fill": "^3.2.2", + "lodash.flatten": "^4.2.0", + "lodash.intersection": "^4.1.2", + "lodash.merge": "^4.3.5", + "lodash.omit": "^4.2.1", + "lodash.partialright": "^4.1.3", + "lodash.pick": "^4.2.0", + "lodash.uniq": "^4.2.1", + "long": "^4.0.0", + "node-forge": "^0.7.1", + "uuid": "^3.0.1" + }, + "dependencies": { + "long": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/long/-/long-4.0.0.tgz", + "integrity": "sha512-XsP+KhQif4bjX1kbuSiySJFNAehNxgLb6hPRGJ9QsUr8ajHkuXGdrHmFUTUUXhDwVX2R5bY4JNZEwbUiMhV+MA==", + "dev": true + } + } + }, "node-libs-browser": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/node-libs-browser/-/node-libs-browser-2.1.0.tgz", @@ -8721,7 +8821,7 @@ "dependencies": { "align-text": { "version": "0.1.4", - "resolved": false, + "resolved": "https://registry.npmjs.org/align-text/-/align-text-0.1.4.tgz", "integrity": "sha1-DNkKVhCT810KmSVsIrcGlDP60Rc=", "dev": true, "requires": { @@ -8732,19 +8832,19 @@ }, "amdefine": { "version": "1.0.1", - "resolved": false, + "resolved": "https://registry.npmjs.org/amdefine/-/amdefine-1.0.1.tgz", "integrity": "sha1-SlKCrBZHKek2Gbz9OtFR+BfOkfU=", "dev": true }, "ansi-regex": { "version": "3.0.0", - "resolved": false, + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz", "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=", "dev": true }, "append-transform": { "version": "0.4.0", - "resolved": false, + "resolved": "https://registry.npmjs.org/append-transform/-/append-transform-0.4.0.tgz", "integrity": "sha1-126/jKlNJ24keja61EpLdKthGZE=", "dev": true, "requires": { @@ -8753,68 +8853,68 @@ }, "archy": { "version": "1.0.0", - "resolved": false, + "resolved": "https://registry.npmjs.org/archy/-/archy-1.0.0.tgz", "integrity": "sha1-+cjBN1fMHde8N5rHeyxipcKGjEA=", "dev": true }, "arr-diff": { "version": "4.0.0", - "resolved": false, + "resolved": "https://registry.npmjs.org/arr-diff/-/arr-diff-4.0.0.tgz", "integrity": "sha1-1kYQdP6/7HHn4VI1dhoyml3HxSA=", "dev": true }, "arr-flatten": { "version": "1.1.0", - "resolved": false, - "integrity": "sha1-NgSLv/TntH4TZkQxbJlmnqWukfE=", + "resolved": "https://registry.npmjs.org/arr-flatten/-/arr-flatten-1.1.0.tgz", + "integrity": "sha512-L3hKV5R/p5o81R7O02IGnwpDmkp6E982XhtbuwSe3O4qOtMMMtodicASA1Cny2U+aCXcNpml+m4dPsvsJ3jatg==", "dev": true }, "arr-union": { "version": "3.1.0", - "resolved": false, + "resolved": "https://registry.npmjs.org/arr-union/-/arr-union-3.1.0.tgz", "integrity": "sha1-45sJrqne+Gao8gbiiK9jkZuuOcQ=", "dev": true }, "array-unique": { "version": "0.3.2", - "resolved": false, + "resolved": "https://registry.npmjs.org/array-unique/-/array-unique-0.3.2.tgz", "integrity": "sha1-qJS3XUvE9s1nnvMkSp/Y9Gri1Cg=", "dev": true }, "arrify": { "version": "1.0.1", - "resolved": false, + "resolved": "https://registry.npmjs.org/arrify/-/arrify-1.0.1.tgz", "integrity": "sha1-iYUI2iIm84DfkEcoRWhJwVAaSw0=", "dev": true }, "assign-symbols": { "version": "1.0.0", - "resolved": false, + "resolved": "https://registry.npmjs.org/assign-symbols/-/assign-symbols-1.0.0.tgz", "integrity": "sha1-WWZ/QfrdTyDMvCu5a41Pf3jsA2c=", "dev": true }, "async": { "version": "1.5.2", - "resolved": false, + "resolved": "https://registry.npmjs.org/async/-/async-1.5.2.tgz", "integrity": "sha1-7GphrlZIDAw8skHJVhjiCJL5Zyo=", "dev": true }, "atob": { "version": "2.1.1", - "resolved": false, + "resolved": "https://registry.npmjs.org/atob/-/atob-2.1.1.tgz", "integrity": "sha1-ri1acpR38onWDdf5amMUoi3Wwio=", "dev": true }, "balanced-match": { "version": "1.0.0", - "resolved": false, + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz", "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=", "dev": true }, "base": { "version": "0.11.2", - "resolved": false, - "integrity": "sha1-e95c7RRbbVUakNuH+DxVi060io8=", + "resolved": "https://registry.npmjs.org/base/-/base-0.11.2.tgz", + "integrity": "sha512-5T6P4xPgpp0YDFvSWwEZ4NoE3aM4QBQXDzmVbraCkFj8zHM+mba8SyqB5DbZWyR7mYHo6Y7BdQo3MoA4m0TeQg==", "dev": true, "requires": { "cache-base": "^1.0.1", @@ -8828,7 +8928,7 @@ "dependencies": { "define-property": { "version": "1.0.0", - "resolved": false, + "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=", "dev": true, "requires": { @@ -8837,8 +8937,8 @@ }, "is-accessor-descriptor": { "version": "1.0.0", - "resolved": false, - "integrity": "sha1-FpwvbT3x+ZJhgHI2XJsOofaHhlY=", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", + "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", "dev": true, "requires": { "kind-of": "^6.0.0" @@ -8846,8 +8946,8 @@ }, "is-data-descriptor": { "version": "1.0.0", - "resolved": false, - "integrity": "sha1-2Eh2Mh0Oet0DmQQGq7u9NrqSaMc=", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", + "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", "dev": true, "requires": { "kind-of": "^6.0.0" @@ -8855,8 +8955,8 @@ }, "is-descriptor": { "version": "1.0.2", - "resolved": false, - "integrity": "sha1-OxWXRqZmBLBPjIFSS6NlxfFNhuw=", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", + "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", "dev": true, "requires": { "is-accessor-descriptor": "^1.0.0", @@ -8866,16 +8966,16 @@ }, "kind-of": { "version": "6.0.2", - "resolved": false, - "integrity": "sha1-ARRrNqYhjmTljzqNZt5df8b20FE=", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.2.tgz", + "integrity": "sha512-s5kLOcnH0XqDO+FvuaLX8DDjZ18CGFk7VygH40QoKPUQhW4e2rvM0rwUq0t8IQDOwYSeLK01U90OjzBTme2QqA==", "dev": true } } }, "brace-expansion": { "version": "1.1.11", - "resolved": false, - "integrity": "sha1-PH/L9SnYcibz0vUrlm/1Jx60Qd0=", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", "dev": true, "requires": { "balanced-match": "^1.0.0", @@ -8884,8 +8984,8 @@ }, "braces": { "version": "2.3.2", - "resolved": false, - "integrity": "sha1-WXn9PxTNUxVl5fot8av/8d+u5yk=", + "resolved": "https://registry.npmjs.org/braces/-/braces-2.3.2.tgz", + "integrity": "sha512-aNdbnj9P8PjdXU4ybaWLK2IF3jc/EoDYbC7AazW6to3TRsfXxscC9UXOB5iDiEQrkyIbWp2SLQda4+QAa7nc3w==", "dev": true, "requires": { "arr-flatten": "^1.1.0", @@ -8902,7 +9002,7 @@ "dependencies": { "extend-shallow": { "version": "2.0.1", - "resolved": false, + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", "dev": true, "requires": { @@ -8913,14 +9013,14 @@ }, "builtin-modules": { "version": "1.1.1", - "resolved": false, + "resolved": "https://registry.npmjs.org/builtin-modules/-/builtin-modules-1.1.1.tgz", "integrity": "sha1-Jw8HbFpywC9bZaR9+Uxf46J4iS8=", "dev": true }, "cache-base": { "version": "1.0.1", - "resolved": false, - "integrity": "sha1-Cn9GQWgxyLZi7jb+TnxZ129marI=", + "resolved": "https://registry.npmjs.org/cache-base/-/cache-base-1.0.1.tgz", + "integrity": "sha512-AKcdTnFSWATd5/GCPRxr2ChwIJ85CeyrEyjRHlKxQ56d4XJMGym0uAiKn0xbLOGOl3+yRpOTi484dVCEc5AUzQ==", "dev": true, "requires": { "collection-visit": "^1.0.0", @@ -8936,7 +9036,7 @@ }, "caching-transform": { "version": "1.0.1", - "resolved": false, + "resolved": "https://registry.npmjs.org/caching-transform/-/caching-transform-1.0.1.tgz", "integrity": "sha1-bb2y8g+Nj7znnz6U6dF0Lc31wKE=", "dev": true, "requires": { @@ -8947,14 +9047,14 @@ }, "camelcase": { "version": "1.2.1", - "resolved": false, + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-1.2.1.tgz", "integrity": "sha1-m7UwTS4LVmmLLHWLCKPqqdqlijk=", "dev": true, "optional": true }, "center-align": { "version": "0.1.3", - "resolved": false, + "resolved": "https://registry.npmjs.org/center-align/-/center-align-0.1.3.tgz", "integrity": "sha1-qg0yYptu6XIgBBHL1EYckHvCt60=", "dev": true, "optional": true, @@ -8965,8 +9065,8 @@ }, "class-utils": { "version": "0.3.6", - "resolved": false, - "integrity": "sha1-+TNprouafOAv1B+q0MqDAzGQxGM=", + "resolved": "https://registry.npmjs.org/class-utils/-/class-utils-0.3.6.tgz", + "integrity": "sha512-qOhPa/Fj7s6TY8H8esGu5QNpMMQxz79h+urzrNYN6mn+9BnxlDGf5QZ+XeCDsxSjPqsSR56XOZOJmpeurnLMeg==", "dev": true, "requires": { "arr-union": "^3.1.0", @@ -8977,7 +9077,7 @@ "dependencies": { "define-property": { "version": "0.2.5", - "resolved": false, + "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", "dev": true, "requires": { @@ -8988,7 +9088,7 @@ }, "cliui": { "version": "2.1.0", - "resolved": false, + "resolved": "https://registry.npmjs.org/cliui/-/cliui-2.1.0.tgz", "integrity": "sha1-S0dXYP+AJkx2LDoXGQMukcf+oNE=", "dev": true, "optional": true, @@ -9000,7 +9100,7 @@ "dependencies": { "wordwrap": { "version": "0.0.2", - "resolved": false, + "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-0.0.2.tgz", "integrity": "sha1-t5Zpu0LstAn4PVg8rVLKF+qhZD8=", "dev": true, "optional": true @@ -9009,13 +9109,13 @@ }, "code-point-at": { "version": "1.1.0", - "resolved": false, + "resolved": "https://registry.npmjs.org/code-point-at/-/code-point-at-1.1.0.tgz", "integrity": "sha1-DQcLTQQ6W+ozovGkDi7bPZpMz3c=", "dev": true }, "collection-visit": { "version": "1.0.0", - "resolved": false, + "resolved": "https://registry.npmjs.org/collection-visit/-/collection-visit-1.0.0.tgz", "integrity": "sha1-S8A3PBZLwykbTTaMgpzxqApZ3KA=", "dev": true, "requires": { @@ -9025,37 +9125,37 @@ }, "commondir": { "version": "1.0.1", - "resolved": false, + "resolved": "https://registry.npmjs.org/commondir/-/commondir-1.0.1.tgz", "integrity": "sha1-3dgA2gxmEnOTzKWVDqloo6rxJTs=", "dev": true }, "component-emitter": { "version": "1.2.1", - "resolved": false, + "resolved": "https://registry.npmjs.org/component-emitter/-/component-emitter-1.2.1.tgz", "integrity": "sha1-E3kY1teCg/ffemt8WmPhQOaUJeY=", "dev": true }, "concat-map": { "version": "0.0.1", - "resolved": false, + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=", "dev": true }, "convert-source-map": { "version": "1.5.1", - "resolved": false, + "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.5.1.tgz", "integrity": "sha1-uCeAl7m8IpNl3lxiz1/K7YtVmeU=", "dev": true }, "copy-descriptor": { "version": "0.1.1", - "resolved": false, + "resolved": "https://registry.npmjs.org/copy-descriptor/-/copy-descriptor-0.1.1.tgz", "integrity": "sha1-Z29us8OZl8LuGsOpJP1hJHSPV40=", "dev": true }, "cross-spawn": { "version": "4.0.2", - "resolved": false, + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-4.0.2.tgz", "integrity": "sha1-e5JHYhwjrf3ThWAEqCPL45dCTUE=", "dev": true, "requires": { @@ -9065,7 +9165,7 @@ }, "debug": { "version": "3.1.0", - "resolved": false, + "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", "integrity": "sha1-W7WgZyYotkFJVmuhaBnmFRjGcmE=", "dev": true, "requires": { @@ -9074,25 +9174,25 @@ }, "debug-log": { "version": "1.0.1", - "resolved": false, + "resolved": "https://registry.npmjs.org/debug-log/-/debug-log-1.0.1.tgz", "integrity": "sha1-IwdjLUwEOCuN+KMvcLiVBG1SdF8=", "dev": true }, "decamelize": { "version": "1.2.0", - "resolved": false, + "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz", "integrity": "sha1-9lNNFRSCabIDUue+4m9QH5oZEpA=", "dev": true }, "decode-uri-component": { "version": "0.2.0", - "resolved": false, + "resolved": "https://registry.npmjs.org/decode-uri-component/-/decode-uri-component-0.2.0.tgz", "integrity": "sha1-6zkTMzRYd1y4TNGh+uBiEGu4dUU=", "dev": true }, "default-require-extensions": { "version": "1.0.0", - "resolved": false, + "resolved": "https://registry.npmjs.org/default-require-extensions/-/default-require-extensions-1.0.0.tgz", "integrity": "sha1-836hXT4T/9m0N9M+GnW1+5eHTLg=", "dev": true, "requires": { @@ -9101,8 +9201,8 @@ }, "define-property": { "version": "2.0.2", - "resolved": false, - "integrity": "sha1-1Flono1lS6d+AqgX+HENcCyxbp0=", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-2.0.2.tgz", + "integrity": "sha512-jwK2UV4cnPpbcG7+VRARKTZPUWowwXA8bzH5NP6ud0oeAxyYPuGZUAC7hMugpCdz4BeSZl2Dl9k66CHJ/46ZYQ==", "dev": true, "requires": { "is-descriptor": "^1.0.2", @@ -9111,8 +9211,8 @@ "dependencies": { "is-accessor-descriptor": { "version": "1.0.0", - "resolved": false, - "integrity": "sha1-FpwvbT3x+ZJhgHI2XJsOofaHhlY=", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", + "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", "dev": true, "requires": { "kind-of": "^6.0.0" @@ -9120,8 +9220,8 @@ }, "is-data-descriptor": { "version": "1.0.0", - "resolved": false, - "integrity": "sha1-2Eh2Mh0Oet0DmQQGq7u9NrqSaMc=", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", + "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", "dev": true, "requires": { "kind-of": "^6.0.0" @@ -9129,8 +9229,8 @@ }, "is-descriptor": { "version": "1.0.2", - "resolved": false, - "integrity": "sha1-OxWXRqZmBLBPjIFSS6NlxfFNhuw=", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", + "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", "dev": true, "requires": { "is-accessor-descriptor": "^1.0.0", @@ -9140,15 +9240,15 @@ }, "kind-of": { "version": "6.0.2", - "resolved": false, - "integrity": "sha1-ARRrNqYhjmTljzqNZt5df8b20FE=", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.2.tgz", + "integrity": "sha512-s5kLOcnH0XqDO+FvuaLX8DDjZ18CGFk7VygH40QoKPUQhW4e2rvM0rwUq0t8IQDOwYSeLK01U90OjzBTme2QqA==", "dev": true } } }, "error-ex": { "version": "1.3.1", - "resolved": false, + "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.1.tgz", "integrity": "sha1-+FWobOYa3E6GIcPNoh56dhLDqNw=", "dev": true, "requires": { @@ -9157,7 +9257,7 @@ }, "execa": { "version": "0.7.0", - "resolved": false, + "resolved": "https://registry.npmjs.org/execa/-/execa-0.7.0.tgz", "integrity": "sha1-lEvs00zEHuMqY6n68nrVpl/Fl3c=", "dev": true, "requires": { @@ -9172,7 +9272,7 @@ "dependencies": { "cross-spawn": { "version": "5.1.0", - "resolved": false, + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-5.1.0.tgz", "integrity": "sha1-6L0O/uWPz/b4+UUQoKVUu/ojVEk=", "dev": true, "requires": { @@ -9185,7 +9285,7 @@ }, "expand-brackets": { "version": "2.1.4", - "resolved": false, + "resolved": "https://registry.npmjs.org/expand-brackets/-/expand-brackets-2.1.4.tgz", "integrity": "sha1-t3c14xXOMPa27/D4OwQVGiJEliI=", "dev": true, "requires": { @@ -9200,7 +9300,7 @@ "dependencies": { "debug": { "version": "2.6.9", - "resolved": false, + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", "integrity": "sha1-XRKFFd8TT/Mn6QpMk/Tgd6U2NB8=", "dev": true, "requires": { @@ -9209,7 +9309,7 @@ }, "define-property": { "version": "0.2.5", - "resolved": false, + "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", "dev": true, "requires": { @@ -9218,7 +9318,7 @@ }, "extend-shallow": { "version": "2.0.1", - "resolved": false, + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", "dev": true, "requires": { @@ -9229,7 +9329,7 @@ }, "extend-shallow": { "version": "3.0.2", - "resolved": false, + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-3.0.2.tgz", "integrity": "sha1-Jqcarwc7OfshJxcnRhMcJwQCjbg=", "dev": true, "requires": { @@ -9239,8 +9339,8 @@ "dependencies": { "is-extendable": { "version": "1.0.1", - "resolved": false, - "integrity": "sha1-p0cPnkJnM9gb2B4RVSZOOjUHyrQ=", + "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-1.0.1.tgz", + "integrity": "sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA==", "dev": true, "requires": { "is-plain-object": "^2.0.4" @@ -9250,8 +9350,8 @@ }, "extglob": { "version": "2.0.4", - "resolved": false, - "integrity": "sha1-rQD+TcYSqSMuhxhxHcXLWrAoVUM=", + "resolved": "https://registry.npmjs.org/extglob/-/extglob-2.0.4.tgz", + "integrity": "sha512-Nmb6QXkELsuBr24CJSkilo6UHHgbekK5UiZgfE6UHD3Eb27YC6oD+bhcT+tJ6cl8dmsgdQxnWlcry8ksBIBLpw==", "dev": true, "requires": { "array-unique": "^0.3.2", @@ -9266,7 +9366,7 @@ "dependencies": { "define-property": { "version": "1.0.0", - "resolved": false, + "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=", "dev": true, "requires": { @@ -9275,7 +9375,7 @@ }, "extend-shallow": { "version": "2.0.1", - "resolved": false, + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", "dev": true, "requires": { @@ -9284,8 +9384,8 @@ }, "is-accessor-descriptor": { "version": "1.0.0", - "resolved": false, - "integrity": "sha1-FpwvbT3x+ZJhgHI2XJsOofaHhlY=", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", + "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", "dev": true, "requires": { "kind-of": "^6.0.0" @@ -9293,8 +9393,8 @@ }, "is-data-descriptor": { "version": "1.0.0", - "resolved": false, - "integrity": "sha1-2Eh2Mh0Oet0DmQQGq7u9NrqSaMc=", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", + "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", "dev": true, "requires": { "kind-of": "^6.0.0" @@ -9302,8 +9402,8 @@ }, "is-descriptor": { "version": "1.0.2", - "resolved": false, - "integrity": "sha1-OxWXRqZmBLBPjIFSS6NlxfFNhuw=", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", + "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", "dev": true, "requires": { "is-accessor-descriptor": "^1.0.0", @@ -9313,15 +9413,15 @@ }, "kind-of": { "version": "6.0.2", - "resolved": false, - "integrity": "sha1-ARRrNqYhjmTljzqNZt5df8b20FE=", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.2.tgz", + "integrity": "sha512-s5kLOcnH0XqDO+FvuaLX8DDjZ18CGFk7VygH40QoKPUQhW4e2rvM0rwUq0t8IQDOwYSeLK01U90OjzBTme2QqA==", "dev": true } } }, "fill-range": { "version": "4.0.0", - "resolved": false, + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-4.0.0.tgz", "integrity": "sha1-1USBHUKPmOsGpj3EAtJAPDKMOPc=", "dev": true, "requires": { @@ -9333,7 +9433,7 @@ "dependencies": { "extend-shallow": { "version": "2.0.1", - "resolved": false, + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", "dev": true, "requires": { @@ -9344,7 +9444,7 @@ }, "find-cache-dir": { "version": "0.1.1", - "resolved": false, + "resolved": "https://registry.npmjs.org/find-cache-dir/-/find-cache-dir-0.1.1.tgz", "integrity": "sha1-yN765XyKUqinhPnjHFfHQumToLk=", "dev": true, "requires": { @@ -9355,7 +9455,7 @@ }, "find-up": { "version": "2.1.0", - "resolved": false, + "resolved": "https://registry.npmjs.org/find-up/-/find-up-2.1.0.tgz", "integrity": "sha1-RdG35QbHF93UgndaK3eSCjwMV6c=", "dev": true, "requires": { @@ -9364,13 +9464,13 @@ }, "for-in": { "version": "1.0.2", - "resolved": false, + "resolved": "https://registry.npmjs.org/for-in/-/for-in-1.0.2.tgz", "integrity": "sha1-gQaNKVqBQuwKxybG4iAMMPttXoA=", "dev": true }, "foreground-child": { "version": "1.5.6", - "resolved": false, + "resolved": "https://registry.npmjs.org/foreground-child/-/foreground-child-1.5.6.tgz", "integrity": "sha1-T9ca0t/elnibmApcCilZN8svXOk=", "dev": true, "requires": { @@ -9380,7 +9480,7 @@ }, "fragment-cache": { "version": "0.2.1", - "resolved": false, + "resolved": "https://registry.npmjs.org/fragment-cache/-/fragment-cache-0.2.1.tgz", "integrity": "sha1-QpD60n8T6Jvn8zeZxrxaCr//DRk=", "dev": true, "requires": { @@ -9389,32 +9489,32 @@ }, "fs.realpath": { "version": "1.0.0", - "resolved": false, + "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=", "dev": true }, "get-caller-file": { "version": "1.0.2", - "resolved": false, + "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-1.0.2.tgz", "integrity": "sha1-9wLmMSfn4jHBYKgMFVSstw1QR+U=", "dev": true }, "get-stream": { "version": "3.0.0", - "resolved": false, + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-3.0.0.tgz", "integrity": "sha1-jpQ9E1jcN1VQVOy+LtsFqhdO3hQ=", "dev": true }, "get-value": { "version": "2.0.6", - "resolved": false, + "resolved": "https://registry.npmjs.org/get-value/-/get-value-2.0.6.tgz", "integrity": "sha1-3BXKHGcjh8p2vTesCjlbogQqLCg=", "dev": true }, "glob": { "version": "7.1.2", - "resolved": false, - "integrity": "sha1-wZyd+aAocC1nhhI4SmVSQExjbRU=", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.2.tgz", + "integrity": "sha512-MJTUg1kjuLeQCJ+ccE4Vpa6kKVXkPYJ2mOCQyUuKLcLQsdrMCpBPUi8qVE6+YuaJkozeA9NusTAw3hLr8Xe5EQ==", "dev": true, "requires": { "fs.realpath": "^1.0.0", @@ -9427,13 +9527,13 @@ }, "graceful-fs": { "version": "4.1.11", - "resolved": false, + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.1.11.tgz", "integrity": "sha1-Dovf5NHduIVNZOBOp8AOKgJuVlg=", "dev": true }, "handlebars": { "version": "4.0.11", - "resolved": false, + "resolved": "https://registry.npmjs.org/handlebars/-/handlebars-4.0.11.tgz", "integrity": "sha1-Ywo13+ApS8KB7a5v/F0yn8eYLcw=", "dev": true, "requires": { @@ -9445,7 +9545,7 @@ "dependencies": { "source-map": { "version": "0.4.4", - "resolved": false, + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.4.4.tgz", "integrity": "sha1-66T12pwNyZneaAMti092FzZSA2s=", "dev": true, "requires": { @@ -9456,7 +9556,7 @@ }, "has-value": { "version": "1.0.0", - "resolved": false, + "resolved": "https://registry.npmjs.org/has-value/-/has-value-1.0.0.tgz", "integrity": "sha1-GLKB2lhbHFxR3vJMkw7SmgvmsXc=", "dev": true, "requires": { @@ -9467,7 +9567,7 @@ }, "has-values": { "version": "1.0.0", - "resolved": false, + "resolved": "https://registry.npmjs.org/has-values/-/has-values-1.0.0.tgz", "integrity": "sha1-lbC2P+whRmGab+V/51Yo1aOe/k8=", "dev": true, "requires": { @@ -9477,7 +9577,7 @@ "dependencies": { "kind-of": { "version": "4.0.0", - "resolved": false, + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-4.0.0.tgz", "integrity": "sha1-IIE989cSkosgc3hpGkUGb65y3Vc=", "dev": true, "requires": { @@ -9488,19 +9588,19 @@ }, "hosted-git-info": { "version": "2.6.0", - "resolved": false, - "integrity": "sha1-IyNbKasjDFdqqw1PE/wEawsDgiI=", + "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.6.0.tgz", + "integrity": "sha512-lIbgIIQA3lz5XaB6vxakj6sDHADJiZadYEJB+FgA+C4nubM1NwcuvUr9EJPmnH1skZqpqUzWborWo8EIUi0Sdw==", "dev": true }, "imurmurhash": { "version": "0.1.4", - "resolved": false, + "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", "integrity": "sha1-khi5srkoojixPcT7a21XbyMUU+o=", "dev": true }, "inflight": { "version": "1.0.6", - "resolved": false, + "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", "dev": true, "requires": { @@ -9510,19 +9610,19 @@ }, "inherits": { "version": "2.0.3", - "resolved": false, + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=", "dev": true }, "invert-kv": { "version": "1.0.0", - "resolved": false, + "resolved": "https://registry.npmjs.org/invert-kv/-/invert-kv-1.0.0.tgz", "integrity": "sha1-EEqOSqym09jNFXqO+L+rLXo//bY=", "dev": true }, "is-accessor-descriptor": { "version": "0.1.6", - "resolved": false, + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz", "integrity": "sha1-qeEss66Nh2cn7u84Q/igiXtcmNY=", "dev": true, "requires": { @@ -9531,19 +9631,19 @@ }, "is-arrayish": { "version": "0.2.1", - "resolved": false, + "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", "integrity": "sha1-d8mYQFJ6qOyxqLppe4BkWnqSap0=", "dev": true }, "is-buffer": { "version": "1.1.6", - "resolved": false, - "integrity": "sha1-76ouqdqg16suoTqXsritUf776L4=", + "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz", + "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==", "dev": true }, "is-builtin-module": { "version": "1.0.0", - "resolved": false, + "resolved": "https://registry.npmjs.org/is-builtin-module/-/is-builtin-module-1.0.0.tgz", "integrity": "sha1-VAVy0096wxGfj3bDDLwbHgN6/74=", "dev": true, "requires": { @@ -9552,7 +9652,7 @@ }, "is-data-descriptor": { "version": "0.1.4", - "resolved": false, + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz", "integrity": "sha1-C17mSDiOLIYCgueT8YVv7D8wG1Y=", "dev": true, "requires": { @@ -9561,8 +9661,8 @@ }, "is-descriptor": { "version": "0.1.6", - "resolved": false, - "integrity": "sha1-Nm2CQN3kh8pRgjsaufB6EKeCUco=", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.6.tgz", + "integrity": "sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg==", "dev": true, "requires": { "is-accessor-descriptor": "^0.1.6", @@ -9572,27 +9672,27 @@ "dependencies": { "kind-of": { "version": "5.1.0", - "resolved": false, - "integrity": "sha1-cpyR4thXt6QZofmqZWhcTDP1hF0=", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz", + "integrity": "sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw==", "dev": true } } }, "is-extendable": { "version": "0.1.1", - "resolved": false, + "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-0.1.1.tgz", "integrity": "sha1-YrEQ4omkcUGOPsNqYX1HLjAd/Ik=", "dev": true }, "is-fullwidth-code-point": { "version": "2.0.0", - "resolved": false, + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=", "dev": true }, "is-number": { "version": "3.0.0", - "resolved": false, + "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz", "integrity": "sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU=", "dev": true, "requires": { @@ -9601,8 +9701,8 @@ }, "is-odd": { "version": "2.0.0", - "resolved": false, - "integrity": "sha1-dkZiRnH9fqVYzNmieVGC8pWPGyQ=", + "resolved": "https://registry.npmjs.org/is-odd/-/is-odd-2.0.0.tgz", + "integrity": "sha512-OTiixgpZAT1M4NHgS5IguFp/Vz2VI3U7Goh4/HA1adtwyLtSBrxYlcSYkhpAE07s4fKEcjrFxyvtQBND4vFQyQ==", "dev": true, "requires": { "is-number": "^4.0.0" @@ -9610,16 +9710,16 @@ "dependencies": { "is-number": { "version": "4.0.0", - "resolved": false, - "integrity": "sha1-ACbjf1RU1z41bf5lZGmYZ8an8P8=", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-4.0.0.tgz", + "integrity": "sha512-rSklcAIlf1OmFdyAqbnWTLVelsQ58uvZ66S/ZyawjWqIviTWCjg2PzVGw8WUA+nNuPTqb4wgA+NszrJ+08LlgQ==", "dev": true } } }, "is-plain-object": { "version": "2.0.4", - "resolved": false, - "integrity": "sha1-LBY7P6+xtgbZ0Xko8FwqHDjgdnc=", + "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz", + "integrity": "sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og==", "dev": true, "requires": { "isobject": "^3.0.1" @@ -9627,50 +9727,50 @@ }, "is-stream": { "version": "1.1.0", - "resolved": false, + "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-1.1.0.tgz", "integrity": "sha1-EtSj3U5o4Lec6428hBc66A2RykQ=", "dev": true }, "is-utf8": { "version": "0.2.1", - "resolved": false, + "resolved": "https://registry.npmjs.org/is-utf8/-/is-utf8-0.2.1.tgz", "integrity": "sha1-Sw2hRCEE0bM2NA6AeX6GXPOffXI=", "dev": true }, "is-windows": { "version": "1.0.2", - "resolved": false, - "integrity": "sha1-0YUOuXkezRjmGCzhKjDzlmNLsZ0=", + "resolved": "https://registry.npmjs.org/is-windows/-/is-windows-1.0.2.tgz", + "integrity": "sha512-eXK1UInq2bPmjyX6e3VHIzMLobc4J94i4AWn+Hpq3OU5KkrRC96OAcR3PRJ/pGu6m8TRnBHP9dkXQVsT/COVIA==", "dev": true }, "isarray": { "version": "1.0.0", - "resolved": false, + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", "dev": true }, "isexe": { "version": "2.0.0", - "resolved": false, + "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=", "dev": true }, "isobject": { "version": "3.0.1", - "resolved": false, + "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=", "dev": true }, "istanbul-lib-coverage": { "version": "1.2.0", - "resolved": false, - "integrity": "sha1-99jy5CuX43/nlhFMsPnWi146Q0E=", + "resolved": "https://registry.npmjs.org/istanbul-lib-coverage/-/istanbul-lib-coverage-1.2.0.tgz", + "integrity": "sha512-GvgM/uXRwm+gLlvkWHTjDAvwynZkL9ns15calTrmhGgowlwJBbWMYzWbKqE2DT6JDP1AFXKa+Zi0EkqNCUqY0A==", "dev": true }, "istanbul-lib-hook": { "version": "1.1.0", - "resolved": false, - "integrity": "sha1-hTjZcDcss3FtU+VVI91UtVeo2Js=", + "resolved": "https://registry.npmjs.org/istanbul-lib-hook/-/istanbul-lib-hook-1.1.0.tgz", + "integrity": "sha512-U3qEgwVDUerZ0bt8cfl3dSP3S6opBoOtk3ROO5f2EfBr/SRiD9FQqzwaZBqFORu8W7O0EXpai+k7kxHK13beRg==", "dev": true, "requires": { "append-transform": "^0.4.0" @@ -9701,8 +9801,8 @@ }, "istanbul-lib-report": { "version": "1.1.3", - "resolved": false, - "integrity": "sha1-LfEhiMD6d5kMDSF20tC6M5QYglk=", + "resolved": "https://registry.npmjs.org/istanbul-lib-report/-/istanbul-lib-report-1.1.3.tgz", + "integrity": "sha512-D4jVbMDtT2dPmloPJS/rmeP626N5Pr3Rp+SovrPn1+zPChGHcggd/0sL29jnbm4oK9W0wHjCRsdch9oLd7cm6g==", "dev": true, "requires": { "istanbul-lib-coverage": "^1.1.2", @@ -9713,13 +9813,13 @@ "dependencies": { "has-flag": { "version": "1.0.0", - "resolved": false, + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-1.0.0.tgz", "integrity": "sha1-nZ55MWXOAXoA8AQYxD+UKnsdEfo=", "dev": true }, "supports-color": { "version": "3.2.3", - "resolved": false, + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-3.2.3.tgz", "integrity": "sha1-ZawFBLOVQXHYpklGsq48u4pfVPY=", "dev": true, "requires": { @@ -9730,7 +9830,7 @@ }, "istanbul-lib-source-maps": { "version": "1.2.5", - "resolved": false, + "resolved": "https://registry.npmjs.org/istanbul-lib-source-maps/-/istanbul-lib-source-maps-1.2.5.tgz", "integrity": "sha1-/+a+Tnq4bTYD5CkNVJkLFFBvybE=", "dev": true, "requires": { @@ -9743,7 +9843,7 @@ }, "istanbul-reports": { "version": "1.4.1", - "resolved": false, + "resolved": "https://registry.npmjs.org/istanbul-reports/-/istanbul-reports-1.4.1.tgz", "integrity": "sha1-Ty6OkoqnoF0dpsQn1AmLJlXsczQ=", "dev": true, "requires": { @@ -9752,7 +9852,7 @@ }, "kind-of": { "version": "3.2.2", - "resolved": false, + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", "dev": true, "requires": { @@ -9761,14 +9861,14 @@ }, "lazy-cache": { "version": "1.0.4", - "resolved": false, + "resolved": "https://registry.npmjs.org/lazy-cache/-/lazy-cache-1.0.4.tgz", "integrity": "sha1-odePw6UEdMuAhF07O24dpJpEbo4=", "dev": true, "optional": true }, "lcid": { "version": "1.0.0", - "resolved": false, + "resolved": "https://registry.npmjs.org/lcid/-/lcid-1.0.0.tgz", "integrity": "sha1-MIrMr6C8SDo4Z7S28rlQYlHRuDU=", "dev": true, "requires": { @@ -9777,7 +9877,7 @@ }, "load-json-file": { "version": "1.1.0", - "resolved": false, + "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-1.1.0.tgz", "integrity": "sha1-lWkFcI1YtLq0wiYbBPWfMcmTdMA=", "dev": true, "requires": { @@ -9790,7 +9890,7 @@ }, "locate-path": { "version": "2.0.0", - "resolved": false, + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-2.0.0.tgz", "integrity": "sha1-K1aLJl7slExtnA3pw9u7ygNUzY4=", "dev": true, "requires": { @@ -9800,7 +9900,7 @@ "dependencies": { "path-exists": { "version": "3.0.0", - "resolved": false, + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz", "integrity": "sha1-zg6+ql94yxiSXqfYENe1mwEP1RU=", "dev": true } @@ -9808,14 +9908,14 @@ }, "longest": { "version": "1.0.1", - "resolved": false, + "resolved": "https://registry.npmjs.org/longest/-/longest-1.0.1.tgz", "integrity": "sha1-MKCy2jj3N3DoKUoNIuZiXtd9AJc=", "dev": true }, "lru-cache": { "version": "4.1.3", - "resolved": false, - "integrity": "sha1-oRdc80lt/IQ2wVbDNLSVWZK85pw=", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-4.1.3.tgz", + "integrity": "sha512-fFEhvcgzuIoJVUF8fYr5KR0YqxD238zgObTps31YdADwPPAp82a4M8TrckkWyx7ekNlf9aBcVn81cFwwXngrJA==", "dev": true, "requires": { "pseudomap": "^1.0.2", @@ -9824,13 +9924,13 @@ }, "map-cache": { "version": "0.2.2", - "resolved": false, + "resolved": "https://registry.npmjs.org/map-cache/-/map-cache-0.2.2.tgz", "integrity": "sha1-wyq9C9ZSXZsFFkW7TyasXcmKDb8=", "dev": true }, "map-visit": { "version": "1.0.0", - "resolved": false, + "resolved": "https://registry.npmjs.org/map-visit/-/map-visit-1.0.0.tgz", "integrity": "sha1-7Nyo8TFE5mDxtb1B8S80edmN+48=", "dev": true, "requires": { @@ -9839,7 +9939,7 @@ }, "md5-hex": { "version": "1.3.0", - "resolved": false, + "resolved": "https://registry.npmjs.org/md5-hex/-/md5-hex-1.3.0.tgz", "integrity": "sha1-0sSv6YPENwZiF5uMrRRSGRNQRsQ=", "dev": true, "requires": { @@ -9848,13 +9948,13 @@ }, "md5-o-matic": { "version": "0.1.1", - "resolved": false, + "resolved": "https://registry.npmjs.org/md5-o-matic/-/md5-o-matic-0.1.1.tgz", "integrity": "sha1-givM1l4RfFFPqxdrJZRdVBAKA8M=", "dev": true }, "mem": { "version": "1.1.0", - "resolved": false, + "resolved": "https://registry.npmjs.org/mem/-/mem-1.1.0.tgz", "integrity": "sha1-Xt1StIXKHZAP5kiVUFOZoN+kX3Y=", "dev": true, "requires": { @@ -9863,8 +9963,8 @@ }, "merge-source-map": { "version": "1.1.0", - "resolved": false, - "integrity": "sha1-L93n5gIJOfcJBqaPLXrmheTIxkY=", + "resolved": "https://registry.npmjs.org/merge-source-map/-/merge-source-map-1.1.0.tgz", + "integrity": "sha512-Qkcp7P2ygktpMPh2mCQZaf3jhN6D3Z/qVZHSdWvQ+2Ef5HgRAPBO57A77+ENm0CPx2+1Ce/MYKi3ymqdfuqibw==", "dev": true, "requires": { "source-map": "^0.6.1" @@ -9872,16 +9972,16 @@ "dependencies": { "source-map": { "version": "0.6.1", - "resolved": false, - "integrity": "sha1-dHIq8y6WFOnCh6jQu95IteLxomM=", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", "dev": true } } }, "micromatch": { "version": "3.1.10", - "resolved": false, - "integrity": "sha1-cIWbyVyYQJUvNZoGij/En57PrCM=", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-3.1.10.tgz", + "integrity": "sha512-MWikgl9n9M3w+bpsY3He8L+w9eF9338xRl8IAO5viDizwSzziFEyUzo2xrrloB64ADbTf8uA8vRqqttDTOmccg==", "dev": true, "requires": { "arr-diff": "^4.0.0", @@ -9901,22 +10001,22 @@ "dependencies": { "kind-of": { "version": "6.0.2", - "resolved": false, - "integrity": "sha1-ARRrNqYhjmTljzqNZt5df8b20FE=", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.2.tgz", + "integrity": "sha512-s5kLOcnH0XqDO+FvuaLX8DDjZ18CGFk7VygH40QoKPUQhW4e2rvM0rwUq0t8IQDOwYSeLK01U90OjzBTme2QqA==", "dev": true } } }, "mimic-fn": { "version": "1.2.0", - "resolved": false, - "integrity": "sha1-ggyGo5M0ZA6ZUWkovQP8qIBX0CI=", + "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-1.2.0.tgz", + "integrity": "sha512-jf84uxzwiuiIVKiOLpfYk7N46TSy8ubTonmneY9vrpHNAnp0QBt2BxWV9dO3/j+BoVAb+a5G6YDPW3M5HOdMWQ==", "dev": true }, "minimatch": { "version": "3.0.4", - "resolved": false, - "integrity": "sha1-UWbihkV/AzBgZL5Ul+jbsMPTIIM=", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", + "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", "dev": true, "requires": { "brace-expansion": "^1.1.7" @@ -9924,14 +10024,14 @@ }, "minimist": { "version": "0.0.8", - "resolved": false, + "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz", "integrity": "sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0=", "dev": true }, "mixin-deep": { "version": "1.3.1", - "resolved": false, - "integrity": "sha1-pJ5yaNzhoNlpjkUybFYm3zVD0P4=", + "resolved": "https://registry.npmjs.org/mixin-deep/-/mixin-deep-1.3.1.tgz", + "integrity": "sha512-8ZItLHeEgaqEvd5lYBXfm4EZSFCX29Jb9K+lAHhDKzReKBQKj3R+7NOF6tjqYi9t4oI8VUfaWITJQm86wnXGNQ==", "dev": true, "requires": { "for-in": "^1.0.2", @@ -9940,8 +10040,8 @@ "dependencies": { "is-extendable": { "version": "1.0.1", - "resolved": false, - "integrity": "sha1-p0cPnkJnM9gb2B4RVSZOOjUHyrQ=", + "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-1.0.1.tgz", + "integrity": "sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA==", "dev": true, "requires": { "is-plain-object": "^2.0.4" @@ -9951,7 +10051,7 @@ }, "mkdirp": { "version": "0.5.1", - "resolved": false, + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz", "integrity": "sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM=", "dev": true, "requires": { @@ -9960,14 +10060,14 @@ }, "ms": { "version": "2.0.0", - "resolved": false, + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", "dev": true }, "nanomatch": { "version": "1.2.9", - "resolved": false, - "integrity": "sha1-h59xUMstq3pHElkGbBBO7m4Pp8I=", + "resolved": "https://registry.npmjs.org/nanomatch/-/nanomatch-1.2.9.tgz", + "integrity": "sha512-n8R9bS8yQ6eSXaV6jHUpKzD8gLsin02w1HSFiegwrs9E098Ylhw5jdyKPaYqvHknHaSCKTPp7C8dGCQ0q9koXA==", "dev": true, "requires": { "arr-diff": "^4.0.0", @@ -9986,16 +10086,16 @@ "dependencies": { "kind-of": { "version": "6.0.2", - "resolved": false, - "integrity": "sha1-ARRrNqYhjmTljzqNZt5df8b20FE=", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.2.tgz", + "integrity": "sha512-s5kLOcnH0XqDO+FvuaLX8DDjZ18CGFk7VygH40QoKPUQhW4e2rvM0rwUq0t8IQDOwYSeLK01U90OjzBTme2QqA==", "dev": true } } }, "normalize-package-data": { "version": "2.4.0", - "resolved": false, - "integrity": "sha1-EvlaMH1YNSB1oEkHuErIvpisAS8=", + "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-2.4.0.tgz", + "integrity": "sha512-9jjUFbTPfEy3R/ad/2oNbKtW9Hgovl5O1FvFWKkKblNXoN/Oou6+9+KKohPK13Yc3/TyunyWhJp6gvRNR/PPAw==", "dev": true, "requires": { "hosted-git-info": "^2.1.4", @@ -10006,7 +10106,7 @@ }, "npm-run-path": { "version": "2.0.2", - "resolved": false, + "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-2.0.2.tgz", "integrity": "sha1-NakjLfo11wZ7TLLd8jV7GHFTbF8=", "dev": true, "requires": { @@ -10015,19 +10115,19 @@ }, "number-is-nan": { "version": "1.0.1", - "resolved": false, + "resolved": "https://registry.npmjs.org/number-is-nan/-/number-is-nan-1.0.1.tgz", "integrity": "sha1-CXtgK1NCKlIsGvuHkDGDNpQaAR0=", "dev": true }, "object-assign": { "version": "4.1.1", - "resolved": false, + "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=", "dev": true }, "object-copy": { "version": "0.1.0", - "resolved": false, + "resolved": "https://registry.npmjs.org/object-copy/-/object-copy-0.1.0.tgz", "integrity": "sha1-fn2Fi3gb18mRpBupde04EnVOmYw=", "dev": true, "requires": { @@ -10038,7 +10138,7 @@ "dependencies": { "define-property": { "version": "0.2.5", - "resolved": false, + "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", "dev": true, "requires": { @@ -10049,7 +10149,7 @@ }, "object-visit": { "version": "1.0.1", - "resolved": false, + "resolved": "https://registry.npmjs.org/object-visit/-/object-visit-1.0.1.tgz", "integrity": "sha1-95xEk68MU3e1n+OdOV5BBC3QRbs=", "dev": true, "requires": { @@ -10058,7 +10158,7 @@ }, "object.pick": { "version": "1.3.0", - "resolved": false, + "resolved": "https://registry.npmjs.org/object.pick/-/object.pick-1.3.0.tgz", "integrity": "sha1-h6EKxMFpS9Lhy/U1kaZhQftd10c=", "dev": true, "requires": { @@ -10067,7 +10167,7 @@ }, "once": { "version": "1.4.0", - "resolved": false, + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", "dev": true, "requires": { @@ -10076,7 +10176,7 @@ }, "optimist": { "version": "0.6.1", - "resolved": false, + "resolved": "https://registry.npmjs.org/optimist/-/optimist-0.6.1.tgz", "integrity": "sha1-2j6nRob6IaGaERwybpDrFaAZZoY=", "dev": true, "requires": { @@ -10086,14 +10186,14 @@ }, "os-homedir": { "version": "1.0.2", - "resolved": false, + "resolved": "https://registry.npmjs.org/os-homedir/-/os-homedir-1.0.2.tgz", "integrity": "sha1-/7xJiDNuDoM94MFox+8VISGqf7M=", "dev": true }, "os-locale": { "version": "2.1.0", - "resolved": false, - "integrity": "sha1-QrwpAKa1uL0XN2yOiCtlr8zyS/I=", + "resolved": "https://registry.npmjs.org/os-locale/-/os-locale-2.1.0.tgz", + "integrity": "sha512-3sslG3zJbEYcaC4YVAvDorjGxc7tv6KVATnLPZONiljsUncvihe9BQoVCEs0RZ1kmf4Hk9OBqlZfJZWI4GanKA==", "dev": true, "requires": { "execa": "^0.7.0", @@ -10103,14 +10203,14 @@ }, "p-finally": { "version": "1.0.0", - "resolved": false, + "resolved": "https://registry.npmjs.org/p-finally/-/p-finally-1.0.0.tgz", "integrity": "sha1-P7z7FbiZpEEjs0ttzBi3JDNqLK4=", "dev": true }, "p-limit": { "version": "1.2.0", - "resolved": false, - "integrity": "sha1-DpK2vty1nwIsE9DxlJ3ILRWQnxw=", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-1.2.0.tgz", + "integrity": "sha512-Y/OtIaXtUPr4/YpMv1pCL5L5ed0rumAaAeBSj12F+bSlMdys7i8oQF/GUJmfpTS/QoaRrS/k6pma29haJpsMng==", "dev": true, "requires": { "p-try": "^1.0.0" @@ -10118,7 +10218,7 @@ }, "p-locate": { "version": "2.0.0", - "resolved": false, + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-2.0.0.tgz", "integrity": "sha1-IKAQOyIqcMj9OcwuWAaA893l7EM=", "dev": true, "requires": { @@ -10127,13 +10227,13 @@ }, "p-try": { "version": "1.0.0", - "resolved": false, + "resolved": "https://registry.npmjs.org/p-try/-/p-try-1.0.0.tgz", "integrity": "sha1-y8ec26+P1CKOE/Yh8rGiN8GyB7M=", "dev": true }, "parse-json": { "version": "2.2.0", - "resolved": false, + "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-2.2.0.tgz", "integrity": "sha1-9ID0BDTvgHQfhGkJn43qGPVaTck=", "dev": true, "requires": { @@ -10142,13 +10242,13 @@ }, "pascalcase": { "version": "0.1.1", - "resolved": false, + "resolved": "https://registry.npmjs.org/pascalcase/-/pascalcase-0.1.1.tgz", "integrity": "sha1-s2PlXoAGym/iF4TS2yK9FdeRfxQ=", "dev": true }, "path-exists": { "version": "2.1.0", - "resolved": false, + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-2.1.0.tgz", "integrity": "sha1-D+tsZPD8UY2adU3V77YscCJ2H0s=", "dev": true, "requires": { @@ -10157,25 +10257,25 @@ }, "path-is-absolute": { "version": "1.0.1", - "resolved": false, + "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=", "dev": true }, "path-key": { "version": "2.0.1", - "resolved": false, + "resolved": "https://registry.npmjs.org/path-key/-/path-key-2.0.1.tgz", "integrity": "sha1-QRyttXTFoUDTpLGRDUDYDMn0C0A=", "dev": true }, "path-parse": { "version": "1.0.5", - "resolved": false, + "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.5.tgz", "integrity": "sha1-PBrfhx6pzWyUMbbqK9dKD/BVxME=", "dev": true }, "path-type": { "version": "1.1.0", - "resolved": false, + "resolved": "https://registry.npmjs.org/path-type/-/path-type-1.1.0.tgz", "integrity": "sha1-WcRPfuSR2nBNpBXaWkBwuk+P5EE=", "dev": true, "requires": { @@ -10186,19 +10286,19 @@ }, "pify": { "version": "2.3.0", - "resolved": false, + "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=", "dev": true }, "pinkie": { "version": "2.0.4", - "resolved": false, + "resolved": "https://registry.npmjs.org/pinkie/-/pinkie-2.0.4.tgz", "integrity": "sha1-clVrgM+g1IqXToDnckjoDtT3+HA=", "dev": true }, "pinkie-promise": { "version": "2.0.1", - "resolved": false, + "resolved": "https://registry.npmjs.org/pinkie-promise/-/pinkie-promise-2.0.1.tgz", "integrity": "sha1-ITXW36ejWMBprJsXh3YogihFD/o=", "dev": true, "requires": { @@ -10207,7 +10307,7 @@ }, "pkg-dir": { "version": "1.0.0", - "resolved": false, + "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-1.0.0.tgz", "integrity": "sha1-ektQio1bstYp1EcFb/TpyTFM89Q=", "dev": true, "requires": { @@ -10216,7 +10316,7 @@ "dependencies": { "find-up": { "version": "1.1.2", - "resolved": false, + "resolved": "https://registry.npmjs.org/find-up/-/find-up-1.1.2.tgz", "integrity": "sha1-ay6YIrGizgpgq2TWEOzK1TyyTQ8=", "dev": true, "requires": { @@ -10228,19 +10328,19 @@ }, "posix-character-classes": { "version": "0.1.1", - "resolved": false, + "resolved": "https://registry.npmjs.org/posix-character-classes/-/posix-character-classes-0.1.1.tgz", "integrity": "sha1-AerA/jta9xoqbAL+q7jB/vfgDqs=", "dev": true }, "pseudomap": { "version": "1.0.2", - "resolved": false, + "resolved": "https://registry.npmjs.org/pseudomap/-/pseudomap-1.0.2.tgz", "integrity": "sha1-8FKijacOYYkX7wqKw0wa5aaChrM=", "dev": true }, "read-pkg": { "version": "1.1.0", - "resolved": false, + "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-1.1.0.tgz", "integrity": "sha1-9f+qXs0pyzHAR0vKfXVra7KePyg=", "dev": true, "requires": { @@ -10251,7 +10351,7 @@ }, "read-pkg-up": { "version": "1.0.1", - "resolved": false, + "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-1.0.1.tgz", "integrity": "sha1-nWPBMnbAZZGNV/ACpX9AobZD+wI=", "dev": true, "requires": { @@ -10261,7 +10361,7 @@ "dependencies": { "find-up": { "version": "1.1.2", - "resolved": false, + "resolved": "https://registry.npmjs.org/find-up/-/find-up-1.1.2.tgz", "integrity": "sha1-ay6YIrGizgpgq2TWEOzK1TyyTQ8=", "dev": true, "requires": { @@ -10273,8 +10373,8 @@ }, "regex-not": { "version": "1.0.2", - "resolved": false, - "integrity": "sha1-H07OJ+ALC2XgJHpoEOaoXYOldSw=", + "resolved": "https://registry.npmjs.org/regex-not/-/regex-not-1.0.2.tgz", + "integrity": "sha512-J6SDjUgDxQj5NusnOtdFxDwN/+HWykR8GELwctJ7mdqhcyy1xEc4SRFHUXvxTp661YaVKAjfRLZ9cCqS6tn32A==", "dev": true, "requires": { "extend-shallow": "^3.0.2", @@ -10283,49 +10383,49 @@ }, "repeat-element": { "version": "1.1.2", - "resolved": false, + "resolved": "https://registry.npmjs.org/repeat-element/-/repeat-element-1.1.2.tgz", "integrity": "sha1-7wiaF40Ug7quTZPrmLT55OEdmQo=", "dev": true }, "repeat-string": { "version": "1.6.1", - "resolved": false, + "resolved": "https://registry.npmjs.org/repeat-string/-/repeat-string-1.6.1.tgz", "integrity": "sha1-jcrkcOHIirwtYA//Sndihtp15jc=", "dev": true }, "require-directory": { "version": "2.1.1", - "resolved": false, + "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", "integrity": "sha1-jGStX9MNqxyXbiNE/+f3kqam30I=", "dev": true }, "require-main-filename": { "version": "1.0.1", - "resolved": false, + "resolved": "https://registry.npmjs.org/require-main-filename/-/require-main-filename-1.0.1.tgz", "integrity": "sha1-l/cXtp1IeE9fUmpsWqj/3aBVpNE=", "dev": true }, "resolve-from": { "version": "2.0.0", - "resolved": false, + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-2.0.0.tgz", "integrity": "sha1-lICrIOlP+h2egKgEx+oUdhGWa1c=", "dev": true }, "resolve-url": { "version": "0.2.1", - "resolved": false, + "resolved": "https://registry.npmjs.org/resolve-url/-/resolve-url-0.2.1.tgz", "integrity": "sha1-LGN/53yJOv0qZj/iGqkIAGjiBSo=", "dev": true }, "ret": { "version": "0.1.15", - "resolved": false, - "integrity": "sha1-uKSCXVvbH8P29Twrwz+BOIaBx7w=", + "resolved": "https://registry.npmjs.org/ret/-/ret-0.1.15.tgz", + "integrity": "sha512-TTlYpa+OL+vMMNG24xSlQGEJ3B/RzEfUlLct7b5G/ytav+wPrplCpVMFuwzXbkecJrb6IYo1iFb0S9v37754mg==", "dev": true }, "right-align": { "version": "0.1.3", - "resolved": false, + "resolved": "https://registry.npmjs.org/right-align/-/right-align-0.1.3.tgz", "integrity": "sha1-YTObci/mo1FWiSENJOFMlhSGE+8=", "dev": true, "optional": true, @@ -10335,8 +10435,8 @@ }, "rimraf": { "version": "2.6.2", - "resolved": false, - "integrity": "sha1-LtgVDSShbqhlHm1u8PR8QVjOejY=", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.6.2.tgz", + "integrity": "sha512-lreewLK/BlghmxtfH36YYVg1i8IAce4TI7oao75I1g245+6BctqTVQiBP3YUJ9C6DQOXJmkYR9X9fCLtCOJc5w==", "dev": true, "requires": { "glob": "^7.0.5" @@ -10344,7 +10444,7 @@ }, "safe-regex": { "version": "1.1.0", - "resolved": false, + "resolved": "https://registry.npmjs.org/safe-regex/-/safe-regex-1.1.0.tgz", "integrity": "sha1-QKNmnzsHfR6UPURinhV91IAjvy4=", "dev": true, "requires": { @@ -10353,20 +10453,20 @@ }, "semver": { "version": "5.5.0", - "resolved": false, - "integrity": "sha1-3Eu8emyp2Rbe5dQ1FvAJK1j3uKs=", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.5.0.tgz", + "integrity": "sha512-4SJ3dm0WAwWy/NVeioZh5AntkdJoWKxHxcmyP622fOkgHa4z3R0TdBJICINyaSDE6uNwVc8gZr+ZinwZAH4xIA==", "dev": true }, "set-blocking": { "version": "2.0.0", - "resolved": false, + "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", "integrity": "sha1-BF+XgtARrppoA93TgrJDkrPYkPc=", "dev": true }, "set-value": { "version": "2.0.0", - "resolved": false, - "integrity": "sha1-ca5KiPD+77v1LR6mBPP7MV67YnQ=", + "resolved": "https://registry.npmjs.org/set-value/-/set-value-2.0.0.tgz", + "integrity": "sha512-hw0yxk9GT/Hr5yJEYnHNKYXkIA8mVJgd9ditYZCe16ZczcaELYYcfvaXesNACk2O8O0nTiPQcQhGUQj8JLzeeg==", "dev": true, "requires": { "extend-shallow": "^2.0.1", @@ -10377,7 +10477,7 @@ "dependencies": { "extend-shallow": { "version": "2.0.1", - "resolved": false, + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", "dev": true, "requires": { @@ -10388,7 +10488,7 @@ }, "shebang-command": { "version": "1.2.0", - "resolved": false, + "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-1.2.0.tgz", "integrity": "sha1-RKrGW2lbAzmJaMOfNj/uXer98eo=", "dev": true, "requires": { @@ -10397,26 +10497,26 @@ }, "shebang-regex": { "version": "1.0.0", - "resolved": false, + "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-1.0.0.tgz", "integrity": "sha1-2kL0l0DAtC2yypcoVxyxkMmO/qM=", "dev": true }, "signal-exit": { "version": "3.0.2", - "resolved": false, + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.2.tgz", "integrity": "sha1-tf3AjxKH6hF4Yo5BXiUTK3NkbG0=", "dev": true }, "slide": { "version": "1.1.6", - "resolved": false, + "resolved": "https://registry.npmjs.org/slide/-/slide-1.1.6.tgz", "integrity": "sha1-VusCfWW00tzmyy4tMsTUr8nh1wc=", "dev": true }, "snapdragon": { "version": "0.8.2", - "resolved": false, - "integrity": "sha1-ZJIufFZbDhQgS6GqfWlkJ40lGC0=", + "resolved": "https://registry.npmjs.org/snapdragon/-/snapdragon-0.8.2.tgz", + "integrity": "sha512-FtyOnWN/wCHTVXOMwvSv26d+ko5vWlIDD6zoUJ7LW8vh+ZBC8QdljveRP+crNrtBwioEUWy/4dMtbBjA4ioNlg==", "dev": true, "requires": { "base": "^0.11.1", @@ -10431,7 +10531,7 @@ "dependencies": { "debug": { "version": "2.6.9", - "resolved": false, + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", "integrity": "sha1-XRKFFd8TT/Mn6QpMk/Tgd6U2NB8=", "dev": true, "requires": { @@ -10440,7 +10540,7 @@ }, "define-property": { "version": "0.2.5", - "resolved": false, + "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", "dev": true, "requires": { @@ -10449,7 +10549,7 @@ }, "extend-shallow": { "version": "2.0.1", - "resolved": false, + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", "dev": true, "requires": { @@ -10460,8 +10560,8 @@ }, "snapdragon-node": { "version": "2.1.1", - "resolved": false, - "integrity": "sha1-bBdfhv8UvbByRWPo88GwIaKGhTs=", + "resolved": "https://registry.npmjs.org/snapdragon-node/-/snapdragon-node-2.1.1.tgz", + "integrity": "sha512-O27l4xaMYt/RSQ5TR3vpWCAB5Kb/czIcqUFOM/C4fYcLnbZUc1PkjTAMjof2pBWaSTwOUd6qUHcFGVGj7aIwnw==", "dev": true, "requires": { "define-property": "^1.0.0", @@ -10471,7 +10571,7 @@ "dependencies": { "define-property": { "version": "1.0.0", - "resolved": false, + "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=", "dev": true, "requires": { @@ -10480,8 +10580,8 @@ }, "is-accessor-descriptor": { "version": "1.0.0", - "resolved": false, - "integrity": "sha1-FpwvbT3x+ZJhgHI2XJsOofaHhlY=", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", + "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", "dev": true, "requires": { "kind-of": "^6.0.0" @@ -10489,8 +10589,8 @@ }, "is-data-descriptor": { "version": "1.0.0", - "resolved": false, - "integrity": "sha1-2Eh2Mh0Oet0DmQQGq7u9NrqSaMc=", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", + "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", "dev": true, "requires": { "kind-of": "^6.0.0" @@ -10498,8 +10598,8 @@ }, "is-descriptor": { "version": "1.0.2", - "resolved": false, - "integrity": "sha1-OxWXRqZmBLBPjIFSS6NlxfFNhuw=", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", + "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", "dev": true, "requires": { "is-accessor-descriptor": "^1.0.0", @@ -10509,16 +10609,16 @@ }, "kind-of": { "version": "6.0.2", - "resolved": false, - "integrity": "sha1-ARRrNqYhjmTljzqNZt5df8b20FE=", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.2.tgz", + "integrity": "sha512-s5kLOcnH0XqDO+FvuaLX8DDjZ18CGFk7VygH40QoKPUQhW4e2rvM0rwUq0t8IQDOwYSeLK01U90OjzBTme2QqA==", "dev": true } } }, "snapdragon-util": { "version": "3.0.1", - "resolved": false, - "integrity": "sha1-+VZHlIbyrNeXAGk/b3uAXkWrVuI=", + "resolved": "https://registry.npmjs.org/snapdragon-util/-/snapdragon-util-3.0.1.tgz", + "integrity": "sha512-mbKkMdQKsjX4BAL4bRYTj21edOf8cN7XHdYUJEe+Zn99hVEYcMvKPct1IqNe7+AZPirn8BCDOQBHQZknqmKlZQ==", "dev": true, "requires": { "kind-of": "^3.2.0" @@ -10526,13 +10626,13 @@ }, "source-map": { "version": "0.5.7", - "resolved": false, + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", "dev": true }, "source-map-resolve": { "version": "0.5.2", - "resolved": false, + "resolved": "https://registry.npmjs.org/source-map-resolve/-/source-map-resolve-0.5.2.tgz", "integrity": "sha1-cuLMNAlVQ+Q7LGKyxMENSpBU8lk=", "dev": true, "requires": { @@ -10545,14 +10645,14 @@ }, "source-map-url": { "version": "0.4.0", - "resolved": false, + "resolved": "https://registry.npmjs.org/source-map-url/-/source-map-url-0.4.0.tgz", "integrity": "sha1-PpNdfd1zYxuXZZlW1VEo6HtQhKM=", "dev": true }, "spawn-wrap": { "version": "1.4.2", - "resolved": false, - "integrity": "sha1-z/WOc6giRhe2Vhq9wyWG6gyCJIw=", + "resolved": "https://registry.npmjs.org/spawn-wrap/-/spawn-wrap-1.4.2.tgz", + "integrity": "sha512-vMwR3OmmDhnxCVxM8M+xO/FtIp6Ju/mNaDfCMMW7FDcLRTPFWUswec4LXJHTJE2hwTI9O0YBfygu4DalFl7Ylg==", "dev": true, "requires": { "foreground-child": "^1.5.6", @@ -10565,8 +10665,8 @@ }, "spdx-correct": { "version": "3.0.0", - "resolved": false, - "integrity": "sha1-BaW01xU6GVvJLDxCW2nzsqlSTII=", + "resolved": "https://registry.npmjs.org/spdx-correct/-/spdx-correct-3.0.0.tgz", + "integrity": "sha512-N19o9z5cEyc8yQQPukRCZ9EUmb4HUpnrmaL/fxS2pBo2jbfcFRVuFZ/oFC+vZz0MNNk0h80iMn5/S6qGZOL5+g==", "dev": true, "requires": { "spdx-expression-parse": "^3.0.0", @@ -10575,14 +10675,14 @@ }, "spdx-exceptions": { "version": "2.1.0", - "resolved": false, - "integrity": "sha1-LHrmEFbHFKW5ubKyr30xHvXHj+k=", + "resolved": "https://registry.npmjs.org/spdx-exceptions/-/spdx-exceptions-2.1.0.tgz", + "integrity": "sha512-4K1NsmrlCU1JJgUrtgEeTVyfx8VaYea9J9LvARxhbHtVtohPs/gFGG5yy49beySjlIMhhXZ4QqujIZEfS4l6Cg==", "dev": true }, "spdx-expression-parse": { "version": "3.0.0", - "resolved": false, - "integrity": "sha1-meEZt6XaAOBUkcn6M4t5BII7QdA=", + "resolved": "https://registry.npmjs.org/spdx-expression-parse/-/spdx-expression-parse-3.0.0.tgz", + "integrity": "sha512-Yg6D3XpRD4kkOmTpdgbUiEJFKghJH03fiC1OPll5h/0sO6neh2jqRDVHOQ4o/LMea0tgCkbMgea5ip/e+MkWyg==", "dev": true, "requires": { "spdx-exceptions": "^2.1.0", @@ -10591,14 +10691,14 @@ }, "spdx-license-ids": { "version": "3.0.0", - "resolved": false, - "integrity": "sha1-enzShHDMbToc/m1miG9rxDDTrIc=", + "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.0.tgz", + "integrity": "sha512-2+EPwgbnmOIl8HjGBXXMd9NAu02vLjOO1nWw4kmeRDFyHn+M/ETfHxQUK0oXg8ctgVnl9t3rosNVsZ1jG61nDA==", "dev": true }, "split-string": { "version": "3.1.0", - "resolved": false, - "integrity": "sha1-fLCd2jqGWFcFxks5pkZgOGguj+I=", + "resolved": "https://registry.npmjs.org/split-string/-/split-string-3.1.0.tgz", + "integrity": "sha512-NzNVhJDYpwceVVii8/Hu6DKfD2G+NrQHlS/V/qgv763EYudVwEcMQNxd2lh+0VrUByXN/oJkl5grOhYWvQUYiw==", "dev": true, "requires": { "extend-shallow": "^3.0.0" @@ -10606,7 +10706,7 @@ }, "static-extend": { "version": "0.1.2", - "resolved": false, + "resolved": "https://registry.npmjs.org/static-extend/-/static-extend-0.1.2.tgz", "integrity": "sha1-YICcOcv/VTNyJv1eC1IPNB8ftcY=", "dev": true, "requires": { @@ -10616,7 +10716,7 @@ "dependencies": { "define-property": { "version": "0.2.5", - "resolved": false, + "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", "dev": true, "requires": { @@ -10627,8 +10727,8 @@ }, "string-width": { "version": "2.1.1", - "resolved": false, - "integrity": "sha1-q5Pyeo3BPSjKyBXEYhQ6bZASrp4=", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz", + "integrity": "sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw==", "dev": true, "requires": { "is-fullwidth-code-point": "^2.0.0", @@ -10637,7 +10737,7 @@ }, "strip-ansi": { "version": "4.0.0", - "resolved": false, + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=", "dev": true, "requires": { @@ -10646,7 +10746,7 @@ }, "strip-bom": { "version": "2.0.0", - "resolved": false, + "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-2.0.0.tgz", "integrity": "sha1-YhmoVhZSBJHzV4i9vxRHqZx+aw4=", "dev": true, "requires": { @@ -10655,14 +10755,14 @@ }, "strip-eof": { "version": "1.0.0", - "resolved": false, + "resolved": "https://registry.npmjs.org/strip-eof/-/strip-eof-1.0.0.tgz", "integrity": "sha1-u0P/VZim6wXYm1n80SnJgzE2Br8=", "dev": true }, "test-exclude": { "version": "4.2.1", - "resolved": false, - "integrity": "sha1-36Ii8DSAvKaSB8pyizfXS0X3JPo=", + "resolved": "https://registry.npmjs.org/test-exclude/-/test-exclude-4.2.1.tgz", + "integrity": "sha512-qpqlP/8Zl+sosLxBcVKl9vYy26T9NPalxSzzCP/OY6K7j938ui2oKgo+kRZYfxAeIpLqpbVnsHq1tyV70E4lWQ==", "dev": true, "requires": { "arrify": "^1.0.1", @@ -10674,7 +10774,7 @@ }, "to-object-path": { "version": "0.3.0", - "resolved": false, + "resolved": "https://registry.npmjs.org/to-object-path/-/to-object-path-0.3.0.tgz", "integrity": "sha1-KXWIt7Dn4KwI4E5nL4XB9JmeF68=", "dev": true, "requires": { @@ -10683,8 +10783,8 @@ }, "to-regex": { "version": "3.0.2", - "resolved": false, - "integrity": "sha1-E8/dmzNlUvMLUfM6iuG0Knp1mc4=", + "resolved": "https://registry.npmjs.org/to-regex/-/to-regex-3.0.2.tgz", + "integrity": "sha512-FWtleNAtZ/Ki2qtqej2CXTOayOH9bHDQF+Q48VpWyDXjbYxA4Yz8iDB31zXOBUlOHHKidDbqGVrTUvQMPmBGBw==", "dev": true, "requires": { "define-property": "^2.0.2", @@ -10695,7 +10795,7 @@ }, "to-regex-range": { "version": "2.1.1", - "resolved": false, + "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-2.1.1.tgz", "integrity": "sha1-fIDBe53+vlmeJzZ+DU3VWQFB2zg=", "dev": true, "requires": { @@ -10705,7 +10805,7 @@ }, "uglify-js": { "version": "2.8.29", - "resolved": false, + "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-2.8.29.tgz", "integrity": "sha1-KcVzMUgFe7Th913zW3qcty5qWd0=", "dev": true, "optional": true, @@ -10717,7 +10817,7 @@ "dependencies": { "yargs": { "version": "3.10.0", - "resolved": false, + "resolved": "https://registry.npmjs.org/yargs/-/yargs-3.10.0.tgz", "integrity": "sha1-9+572FfdfB0tOMDnTvvWgdFDH9E=", "dev": true, "optional": true, @@ -10732,14 +10832,14 @@ }, "uglify-to-browserify": { "version": "1.0.2", - "resolved": false, + "resolved": "https://registry.npmjs.org/uglify-to-browserify/-/uglify-to-browserify-1.0.2.tgz", "integrity": "sha1-bgkk1r2mta/jSeOabWMoUKD4grc=", "dev": true, "optional": true }, "union-value": { "version": "1.0.0", - "resolved": false, + "resolved": "https://registry.npmjs.org/union-value/-/union-value-1.0.0.tgz", "integrity": "sha1-XHHDTLW61dzr4+oM0IIHulqhrqQ=", "dev": true, "requires": { @@ -10751,7 +10851,7 @@ "dependencies": { "extend-shallow": { "version": "2.0.1", - "resolved": false, + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", "dev": true, "requires": { @@ -10760,7 +10860,7 @@ }, "set-value": { "version": "0.4.3", - "resolved": false, + "resolved": "https://registry.npmjs.org/set-value/-/set-value-0.4.3.tgz", "integrity": "sha1-fbCPnT0i3H945Trzw79GZuzfzPE=", "dev": true, "requires": { @@ -10774,7 +10874,7 @@ }, "unset-value": { "version": "1.0.0", - "resolved": false, + "resolved": "https://registry.npmjs.org/unset-value/-/unset-value-1.0.0.tgz", "integrity": "sha1-g3aHP30jNRef+x5vw6jtDfyKtVk=", "dev": true, "requires": { @@ -10784,7 +10884,7 @@ "dependencies": { "has-value": { "version": "0.3.1", - "resolved": false, + "resolved": "https://registry.npmjs.org/has-value/-/has-value-0.3.1.tgz", "integrity": "sha1-ex9YutpiyoJ+wKIHgCVlSEWZXh8=", "dev": true, "requires": { @@ -10795,7 +10895,7 @@ "dependencies": { "isobject": { "version": "2.1.0", - "resolved": false, + "resolved": "https://registry.npmjs.org/isobject/-/isobject-2.1.0.tgz", "integrity": "sha1-8GVWEJaj8dou9GJy+BXIQNh+DIk=", "dev": true, "requires": { @@ -10806,7 +10906,7 @@ }, "has-values": { "version": "0.1.4", - "resolved": false, + "resolved": "https://registry.npmjs.org/has-values/-/has-values-0.1.4.tgz", "integrity": "sha1-bWHeldkd/Km5oCCJrThL/49it3E=", "dev": true } @@ -10814,14 +10914,14 @@ }, "urix": { "version": "0.1.0", - "resolved": false, + "resolved": "https://registry.npmjs.org/urix/-/urix-0.1.0.tgz", "integrity": "sha1-2pN/emLiH+wf0Y1Js1wpNQZ6bHI=", "dev": true }, "use": { "version": "3.1.0", - "resolved": false, - "integrity": "sha1-FHFr8D/f79AwQK71jYtLhfOnxUQ=", + "resolved": "https://registry.npmjs.org/use/-/use-3.1.0.tgz", + "integrity": "sha512-6UJEQM/L+mzC3ZJNM56Q4DFGLX/evKGRg15UJHGB9X5j5Z3AFbgZvjUh2yq/UJUY4U5dh7Fal++XbNg1uzpRAw==", "dev": true, "requires": { "kind-of": "^6.0.2" @@ -10829,16 +10929,16 @@ "dependencies": { "kind-of": { "version": "6.0.2", - "resolved": false, - "integrity": "sha1-ARRrNqYhjmTljzqNZt5df8b20FE=", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.2.tgz", + "integrity": "sha512-s5kLOcnH0XqDO+FvuaLX8DDjZ18CGFk7VygH40QoKPUQhW4e2rvM0rwUq0t8IQDOwYSeLK01U90OjzBTme2QqA==", "dev": true } } }, "validate-npm-package-license": { "version": "3.0.3", - "resolved": false, - "integrity": "sha1-gWQ7y+8b3+zUYjeT3EZIlIupgzg=", + "resolved": "https://registry.npmjs.org/validate-npm-package-license/-/validate-npm-package-license-3.0.3.tgz", + "integrity": "sha512-63ZOUnL4SIXj4L0NixR3L1lcjO38crAbgrTpl28t8jjrfuiOBL5Iygm+60qPs/KsZGzPNg6Smnc/oY16QTjF0g==", "dev": true, "requires": { "spdx-correct": "^3.0.0", @@ -10847,7 +10947,7 @@ }, "which": { "version": "1.3.1", - "resolved": false, + "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz", "integrity": "sha1-pFBD1U9YBTFtqNYvn1CRjT2nCwo=", "dev": true, "requires": { @@ -10856,26 +10956,26 @@ }, "which-module": { "version": "2.0.0", - "resolved": false, + "resolved": "https://registry.npmjs.org/which-module/-/which-module-2.0.0.tgz", "integrity": "sha1-2e8H3Od7mQK4o6j6SzHD4/fm6Ho=", "dev": true }, "window-size": { "version": "0.1.0", - "resolved": false, + "resolved": "https://registry.npmjs.org/window-size/-/window-size-0.1.0.tgz", "integrity": "sha1-VDjNLqk7IC76Ohn+iIeu58lPnJ0=", "dev": true, "optional": true }, "wordwrap": { "version": "0.0.3", - "resolved": false, + "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-0.0.3.tgz", "integrity": "sha1-o9XabNXAvAAI03I0u68b7WMFkQc=", "dev": true }, "wrap-ansi": { "version": "2.1.0", - "resolved": false, + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-2.1.0.tgz", "integrity": "sha1-2Pw9KE3QV5T+hJc8rs3Rz4JP3YU=", "dev": true, "requires": { @@ -10885,13 +10985,13 @@ "dependencies": { "ansi-regex": { "version": "2.1.1", - "resolved": false, + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=", "dev": true }, "is-fullwidth-code-point": { "version": "1.0.0", - "resolved": false, + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz", "integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=", "dev": true, "requires": { @@ -10900,7 +11000,7 @@ }, "string-width": { "version": "1.0.2", - "resolved": false, + "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=", "dev": true, "requires": { @@ -10911,7 +11011,7 @@ }, "strip-ansi": { "version": "3.0.1", - "resolved": false, + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", "dev": true, "requires": { @@ -10922,13 +11022,13 @@ }, "wrappy": { "version": "1.0.2", - "resolved": false, + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=", "dev": true }, "write-file-atomic": { "version": "1.3.4", - "resolved": false, + "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-1.3.4.tgz", "integrity": "sha1-+Aek8LHZ6ROuekgRLmzDrxmRtF8=", "dev": true, "requires": { @@ -10939,20 +11039,20 @@ }, "y18n": { "version": "3.2.1", - "resolved": false, + "resolved": "https://registry.npmjs.org/y18n/-/y18n-3.2.1.tgz", "integrity": "sha1-bRX7qITAhnnA136I53WegR4H+kE=", "dev": true }, "yallist": { "version": "2.1.2", - "resolved": false, + "resolved": "https://registry.npmjs.org/yallist/-/yallist-2.1.2.tgz", "integrity": "sha1-HBH5IY8HYImkfdUS+TxmmaaoHVI=", "dev": true }, "yargs": { "version": "11.1.0", - "resolved": false, - "integrity": "sha1-kLhpk07W6HERXqL/WLA/RyTtLXc=", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-11.1.0.tgz", + "integrity": "sha512-NwW69J42EsCSanF8kyn5upxvjp5ds+t3+udGBeTbFnERA+lF541DDpMawzo4z6W/QrzNM18D+BPMiOBibnFV5A==", "dev": true, "requires": { "cliui": "^4.0.0", @@ -10971,14 +11071,14 @@ "dependencies": { "camelcase": { "version": "4.1.0", - "resolved": false, + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-4.1.0.tgz", "integrity": "sha1-1UVjW+HjPFQmScaRc+Xeas+uNN0=", "dev": true }, "cliui": { "version": "4.1.0", - "resolved": false, - "integrity": "sha1-NIQi2+gtgAswIu709qwQvy5NG0k=", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-4.1.0.tgz", + "integrity": "sha512-4FG+RSG9DL7uEwRUZXZn3SS34DiDPfzP0VOiEwtUWlE+AR2EIg+hSyvrIgUUfhdgR/UkAeW2QHgeP+hWrXs7jQ==", "dev": true, "requires": { "string-width": "^2.1.1", @@ -10988,7 +11088,7 @@ }, "yargs-parser": { "version": "9.0.2", - "resolved": false, + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-9.0.2.tgz", "integrity": "sha1-nM9qQ0YP5O1Aqbto9I1DuKaMwHc=", "dev": true, "requires": { @@ -10999,8 +11099,8 @@ }, "yargs-parser": { "version": "8.1.0", - "resolved": false, - "integrity": "sha1-8TdqM7Ziml0GN4KUTacyYx6WaVA=", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-8.1.0.tgz", + "integrity": "sha512-yP+6QqN8BmrgW2ggLtTbdrOyBNSI7zBa4IykmiV5R1wl1JWNxQvWhMfMdmzIYtKU7oP3OOInY/tl2ov3BDjnJQ==", "dev": true, "requires": { "camelcase": "^4.1.0" @@ -11008,7 +11108,7 @@ "dependencies": { "camelcase": { "version": "4.1.0", - "resolved": false, + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-4.1.0.tgz", "integrity": "sha1-1UVjW+HjPFQmScaRc+Xeas+uNN0=", "dev": true } @@ -11225,7 +11325,7 @@ }, "onetime": { "version": "1.1.0", - "resolved": "https://registry.npmjs.org/onetime/-/onetime-1.1.0.tgz", + "resolved": "http://registry.npmjs.org/onetime/-/onetime-1.1.0.tgz", "integrity": "sha1-ofeDj4MUxRbwXs78vEzP4EtO14k=", "dev": true }, @@ -11315,18 +11415,6 @@ "integrity": "sha1-y8ec26+P1CKOE/Yh8rGiN8GyB7M=", "dev": true }, - "package-lock": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/package-lock/-/package-lock-1.0.0.tgz", - "integrity": "sha1-fvr3IC6fxMzBXc8sKitKlroNZLA=", - "requires": { - "asyncc": "^2.0.0", - "commander": "^2.11.0", - "glob": "^7.1.2", - "lodash": "^4.17.4", - "traverse": "^0.6.6" - } - }, "pako": { "version": "1.0.6", "resolved": "https://registry.npmjs.org/pako/-/pako-1.0.6.tgz", @@ -11450,7 +11538,8 @@ "path-is-absolute": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", - "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=" + "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=", + "dev": true }, "path-is-inside": { "version": "1.0.2", @@ -15054,11 +15143,6 @@ "nanobench": "^2.1.1" } }, - "traverse": { - "version": "0.6.6", - "resolved": "https://registry.npmjs.org/traverse/-/traverse-0.6.6.tgz", - "integrity": "sha1-y99WD9e5r2MlAv7UD5GMFX6pcTc=" - }, "trim": { "version": "0.0.1", "resolved": "https://registry.npmjs.org/trim/-/trim-0.0.1.tgz", diff --git a/package.json b/package.json index deee0a01..e67c9135 100644 --- a/package.json +++ b/package.json @@ -28,7 +28,7 @@ "test:frontend": "cross-env NODE_ENV=development node test/frontend/runner.js && nyc report --reporter=html", "test-integration": "docker-compose up --abort-on-container-exit --exit-code-from integration-tests --build --remove-orphans --quiet-pull && docker-compose down", "test-integration-stage": "cross-env BASE_URL=https://send.stage.mozaws.net npm run test-integration", - "start": "npm run clean && cross-env NODE_ENV=development webpack-dev-server --mode=development", + "start": "npm run clean && cross-env NODE_ENV=development BASE_URL=http://localhost:8080 webpack-dev-server --mode=development", "prod": "node server/bin/prod.js" }, "lint-staged": { @@ -89,6 +89,7 @@ "mocha": "^5.2.0", "nanobus": "^4.3.2", "nanotiming": "^7.3.1", + "node-jose": "^1.0.0", "npm-run-all": "^4.1.3", "nyc": "^12.0.2", "postcss-cssnext": "^3.1.0", @@ -129,7 +130,7 @@ "helmet": "^3.13.0", "mkdirp": "^0.5.1", "mozlog": "^2.2.0", - "package-lock": "^1.0.0", + "node-fetch": "^2.2.0", "raven": "^2.6.3", "redis": "^2.8.0", "websocket-stream": "^5.1.2" diff --git a/public/locales/en-US/send.ftl b/public/locales/en-US/send.ftl index b16ccc8b..29218ca5 100644 --- a/public/locales/en-US/send.ftl +++ b/public/locales/en-US/send.ftl @@ -84,6 +84,8 @@ errorPageHeader = Something went wrong! errorPageMessage = There has been an error uploading the file. errorPageLink = Send another file fileTooBig = That file is too big to upload. It should be less than { $size }. +tooManyFiles = Only { $count } files can be uploaded at a time. +tooManyArchives = Only { $count } archives are allowed. linkExpiredAlt = Link expired expiredPageHeader = This link has expired or never existed in the first place! notSupportedHeader = Your browser is not supported. @@ -162,4 +164,5 @@ accountBenefitExpiry = Have more expiry options accountBenefitSync = Manage your uploads across devices accountBenefitNotify = Be notified when your files are downloaded accountBenefitMore = Do a lot more! - +manageAccount = Manage Account +logOut = Sign Out diff --git a/server/config.js b/server/config.js index 73985155..dcbab8ed 100644 --- a/server/config.js +++ b/server/config.js @@ -21,7 +21,7 @@ const conf = convict({ }, expire_times_seconds: { format: Array, - default: [300, 3600, 86400, 604800, 1209600], + default: [300, 3600, 86400, 604800], env: 'EXPIRE_TIMES_SECONDS' }, default_expire_seconds: { @@ -31,9 +31,34 @@ const conf = convict({ }, max_expire_seconds: { format: Number, - default: 1209600, + default: 86400 * 7, env: 'MAX_EXPIRE_SECONDS' }, + anon_max_expire_seconds: { + format: Number, + default: 86400, + env: 'ANON_MAX_EXPIRE_SECONDS' + }, + max_downloads: { + format: Number, + default: 200, + env: 'MAX_DOWNLOADS' + }, + anon_max_downloads: { + format: Number, + default: 20, + env: 'ANON_MAX_DOWNLOADS' + }, + max_files_per_archive: { + format: Number, + default: 64, + env: 'MAX_FILES_PER_ARCHIVE' + }, + max_archives_per_user: { + format: Number, + default: 16, + env: 'MAX_ARCHIVES_PER_USER' + }, redis_host: { format: String, default: 'localhost', @@ -77,9 +102,14 @@ const conf = convict({ }, max_file_size: { format: Number, - default: 1024 * 1024 * 1024 * 3, + default: 1024 * 1024 * 1024 * 4, env: 'MAX_FILE_SIZE' }, + anon_max_file_size: { + format: Number, + default: 1024 * 1024 * 500, + env: 'ANON_MAX_FILE_SIZE' + }, l10n_dev: { format: Boolean, default: false, @@ -94,6 +124,21 @@ const conf = convict({ format: 'String', default: `${tmpdir()}${path.sep}send-${randomBytes(4).toString('hex')}`, env: 'FILE_DIR' + }, + fxa_url: { + format: 'url', + default: 'https://stable.dev.lcip.org', + env: 'FXA_URL' + }, + fxa_client_id: { + format: String, + default: 'b50ec33d3c9beb6d', // localhost + env: 'FXA_CLIENT_ID' + }, + fxa_client_secret: { + format: String, + default: '05ac76fbe3e739c9effbaea439bc07d265c613c5e0da9070590a2378377c09d8', // localhost + env: 'FXA_CLIENT_SECRET' } }); diff --git a/server/initScript.js b/server/initScript.js new file mode 100644 index 00000000..69ad2db0 --- /dev/null +++ b/server/initScript.js @@ -0,0 +1,17 @@ +const html = require('choo/html'); +const raw = require('choo/html/raw'); + +module.exports = function(state) { + // return ''; + return state.cspNonce + ? html` + ` + : ''; +}; diff --git a/server/layout.js b/server/layout.js index 26438d79..366e3381 100644 --- a/server/layout.js +++ b/server/layout.js @@ -1,6 +1,7 @@ const html = require('choo/html'); const assets = require('../common/assets'); const locales = require('../common/locales'); +const initScript = require('./initScript'); module.exports = function(state, body = '') { const firaTag = state.fira @@ -73,6 +74,7 @@ module.exports = function(state, body = '') { ${body} + ${initScript(state)} `; }; diff --git a/server/middleware/auth.js b/server/middleware/auth.js index b1a1607d..07808001 100644 --- a/server/middleware/auth.js +++ b/server/middleware/auth.js @@ -1,38 +1,70 @@ const crypto = require('crypto'); const storage = require('../storage'); +const fxa = require('../routes/fxa'); -module.exports = async function(req, res, next) { - const id = req.params.id; - if (id && req.header('Authorization')) { - try { - const auth = req.header('Authorization').split(' ')[1]; - const meta = await storage.metadata(id); - if (!meta) { - return res.sendStatus(404); - } - const hmac = crypto.createHmac( - 'sha256', - Buffer.from(meta.auth, 'base64') - ); - hmac.update(Buffer.from(meta.nonce, 'base64')); - const verifyHash = hmac.digest(); - if (verifyHash.equals(Buffer.from(auth, 'base64'))) { - req.nonce = crypto.randomBytes(16).toString('base64'); - storage.setField(id, 'nonce', req.nonce); - res.set('WWW-Authenticate', `send-v1 ${req.nonce}`); - req.authorized = true; - req.meta = meta; - } else { - res.set('WWW-Authenticate', `send-v1 ${meta.nonce}`); +module.exports = { + hmac: async function(req, res, next) { + const id = req.params.id; + const authHeader = req.header('Authorization'); + if (id && authHeader) { + try { + const auth = req.header('Authorization').split(' ')[1]; + const meta = await storage.metadata(id); + if (!meta) { + return res.sendStatus(404); + } + const hmac = crypto.createHmac( + 'sha256', + Buffer.from(meta.auth, 'base64') + ); + hmac.update(Buffer.from(meta.nonce, 'base64')); + const verifyHash = hmac.digest(); + if (verifyHash.equals(Buffer.from(auth, 'base64'))) { + req.nonce = crypto.randomBytes(16).toString('base64'); + storage.setField(id, 'nonce', req.nonce); + res.set('WWW-Authenticate', `send-v1 ${req.nonce}`); + req.authorized = true; + req.meta = meta; + } else { + res.set('WWW-Authenticate', `send-v1 ${meta.nonce}`); + req.authorized = false; + } + } catch (e) { req.authorized = false; } - } catch (e) { - req.authorized = false; } - } - if (req.authorized) { - next(); - } else { - res.sendStatus(401); + if (req.authorized) { + next(); + } else { + res.sendStatus(401); + } + }, + owner: async function(req, res, next) { + const id = req.params.id; + const ownerToken = req.body.owner_token; + if (id && ownerToken) { + try { + req.meta = await storage.metadata(id); + if (!req.meta) { + return res.sendStatus(404); + } + req.authorized = req.meta.owner === ownerToken; + } catch (e) { + req.authorized = false; + } + } + if (req.authorized) { + next(); + } else { + res.sendStatus(401); + } + }, + fxa: async function(req, res, next) { + const authHeader = req.header('Authorization'); + if (authHeader && /^Bearer\s/i.test(authHeader)) { + const token = authHeader.split(' ')[1]; + req.user = await fxa.verify(token); + } + return next(); } }; diff --git a/server/middleware/owner.js b/server/middleware/owner.js deleted file mode 100644 index eb66562d..00000000 --- a/server/middleware/owner.js +++ /dev/null @@ -1,22 +0,0 @@ -const storage = require('../storage'); - -module.exports = async function(req, res, next) { - const id = req.params.id; - const ownerToken = req.body.owner_token; - if (id && ownerToken) { - try { - req.meta = await storage.metadata(id); - if (!req.meta) { - return res.sendStatus(404); - } - req.authorized = req.meta.owner === ownerToken; - } catch (e) { - req.authorized = false; - } - } - if (req.authorized) { - next(); - } else { - res.sendStatus(401); - } -}; diff --git a/server/routes/download.js b/server/routes/download.js index b28baf8a..5680ed36 100644 --- a/server/routes/download.js +++ b/server/routes/download.js @@ -14,15 +14,15 @@ module.exports = async function(req, res) { 'WWW-Authenticate': `send-v1 ${req.nonce}` }); - const file_stream = await storage.get(id); + const fileStream = await storage.get(id); let cancelled = false; req.on('close', () => { cancelled = true; - file_stream.destroy(); + fileStream.destroy(); }); - file_stream.on('end', async () => { + fileStream.on('end', async () => { if (cancelled) { return; } @@ -40,7 +40,7 @@ module.exports = async function(req, res) { } }); - file_stream.pipe(res); + fileStream.pipe(res); } catch (e) { res.sendStatus(404); } diff --git a/server/routes/filelist.js b/server/routes/filelist.js new file mode 100644 index 00000000..8f276595 --- /dev/null +++ b/server/routes/filelist.js @@ -0,0 +1,49 @@ +const config = require('../config'); +const storage = require('../storage'); +const Limiter = require('../limiter'); + +function id(user) { + return `filelist-${user}`; +} + +module.exports = { + async get(req, res) { + if (!req.user) { + return res.sendStatus(401); + } + try { + const fileId = id(req.user); + const contentLength = await storage.length(fileId); + const fileStream = await storage.get(fileId); + res.writeHead(200, { + 'Content-Type': 'application/octet-stream', + 'Content-Length': contentLength + }); + fileStream.pipe(res); + } catch (e) { + res.sendStatus(404); + } + }, + + async post(req, res) { + if (!req.user) { + return res.sendStatus(401); + } + try { + const limiter = new Limiter(1024 * 1024 * 10); + const fileStream = req.pipe(limiter); + await storage.set( + id(req.user), + fileStream, + { n: 'a' }, //TODO + config.max_expire_seconds + ); + res.sendStatus(200); + } catch (e) { + if (e.message === 'limit') { + return res.sendStatus(413); + } + res.sendStatus(500); + } + } +}; diff --git a/server/routes/fxa.js b/server/routes/fxa.js new file mode 100644 index 00000000..50544425 --- /dev/null +++ b/server/routes/fxa.js @@ -0,0 +1,96 @@ +const { URLSearchParams } = require('url'); +const fetch = require('node-fetch'); +const config = require('../config'); +const pages = require('./pages'); + +const KEY_SCOPE = 'https://identity.mozilla.com/apps/send'; +let fxaConfig = null; +let lastConfigRefresh = 0; + +async function getFxaConfig() { + if (fxaConfig && Date.now() - lastConfigRefresh < 1000 * 60 * 5) { + return fxaConfig; + } + const res = await fetch(`${config.fxa_url}/.well-known/openid-configuration`); + fxaConfig = await res.json(); + lastConfigRefresh = Date.now(); + return fxaConfig; +} + +module.exports = { + login: async function(req, res) { + const query = req.query; + if (!query || !query.keys_jwk) { + return res.sendStatus(400); + } + const c = await getFxaConfig(); + const params = new URLSearchParams({ + client_id: config.fxa_client_id, + redirect_uri: `${config.base_url}/api/fxa/oauth`, + state: 'todo', + scope: `profile ${KEY_SCOPE}`, + action: 'email', + keys_jwk: query.keys_jwk + }); + res.redirect(`${c.authorization_endpoint}?${params.toString()}`); + }, + + oauth: async function(req, res) { + const query = req.query; + if (!query || !query.code || !query.state || !query.action) { + return res.sendStatus(400); + } + const c = await getFxaConfig(); + const x = await fetch(c.token_endpoint, { + method: 'POST', + body: JSON.stringify({ + code: query.code, + client_id: config.fxa_client_id, + client_secret: config.fxa_client_secret + }), + headers: { + 'content-type': 'application/json' + } + }); + const zzz = await x.json(); + console.error(zzz); + const p = await fetch(c.userinfo_endpoint, { + method: 'GET', + headers: { + authorization: `Bearer ${zzz.access_token}` + } + }); + const userInfo = await p.json(); + userInfo.keys_jwe = zzz.keys_jwe; + userInfo.access_token = zzz.access_token; + req.userInfo = userInfo; + pages.index(req, res); + }, + + verify: async function(token) { + if (!token) { + return null; + } + + const c = await getFxaConfig(); + try { + const verifyUrl = c.jwks_uri.replace('jwks', 'verify'); + const result = await fetch(verifyUrl, { + method: 'POST', + headers: { 'Content-Type': 'application/json' }, + body: JSON.stringify({ token }) + }); + const info = await result.json(); + if ( + info.scope && + Array.isArray(info.scope) && + info.scope.includes(KEY_SCOPE) + ) { + return info.user; + } + } catch (e) { + // gulp + } + return null; + } +}; diff --git a/server/routes/index.js b/server/routes/index.js index 33091402..590becb4 100644 --- a/server/routes/index.js +++ b/server/routes/index.js @@ -1,11 +1,13 @@ +const crypto = require('crypto'); const express = require('express'); const helmet = require('helmet'); const storage = require('../storage'); const config = require('../config'); const auth = require('../middleware/auth'); -const owner = require('../middleware/owner'); const language = require('../middleware/language'); const pages = require('./pages'); +const fxa = require('./fxa'); +const filelist = require('./filelist'); const IS_DEV = config.env === 'development'; const ID_REGEX = '([0-9a-fA-F]{10})'; @@ -18,6 +20,10 @@ module.exports = function(app) { force: !IS_DEV }) ); + app.use(function(req, res, next) { + req.cspNonce = crypto.randomBytes(16).toString('hex'); + next(); + }); if (!IS_DEV) { app.use( helmet.contentSecurityPolicy({ @@ -31,8 +37,18 @@ module.exports = function(app) { 'https://sentry.prod.mozaws.net', 'https://www.google-analytics.com' ], - imgSrc: ["'self'", 'https://www.google-analytics.com'], - scriptSrc: ["'self'"], + imgSrc: [ + "'self'", + 'https://www.google-analytics.com', + 'https://*.dev.lcip.org', + 'https://firefoxusercontent.com' + ], + scriptSrc: [ + "'self'", + function(req) { + return `'nonce-${req.cspNonce}'`; + } + ], styleSrc: ["'self'", 'https://code.cdn.mozilla.net'], fontSrc: ["'self'", 'https://code.cdn.mozilla.net'], formAction: ["'none'"], @@ -49,22 +65,30 @@ module.exports = function(app) { next(); }); app.use(express.json()); - app.get('/', language, pages.blank); + app.get('/', language, pages.index); app.get('/legal', language, pages.legal); app.get('/jsconfig.js', require('./jsconfig')); app.get(`/share/:id${ID_REGEX}`, language, pages.blank); app.get(`/download/:id${ID_REGEX}`, language, pages.download); app.get('/completed', language, pages.blank); app.get('/unsupported/:reason', language, pages.unsupported); - app.get(`/api/download/:id${ID_REGEX}`, auth, require('./download')); - app.get(`/api/download/blob/:id${ID_REGEX}`, auth, require('./download')); + app.get(`/api/download/:id${ID_REGEX}`, auth.hmac, require('./download')); + app.get( + `/api/download/blob/:id${ID_REGEX}`, + auth.hmac, + require('./download') + ); app.get(`/api/exists/:id${ID_REGEX}`, require('./exists')); - app.get(`/api/metadata/:id${ID_REGEX}`, auth, require('./metadata')); - app.post('/api/upload', require('./upload')); - app.post(`/api/delete/:id${ID_REGEX}`, owner, require('./delete')); - app.post(`/api/password/:id${ID_REGEX}`, owner, require('./password')); - app.post(`/api/params/:id${ID_REGEX}`, owner, require('./params')); - app.post(`/api/info/:id${ID_REGEX}`, owner, require('./info')); + app.get(`/api/metadata/:id${ID_REGEX}`, auth.hmac, require('./metadata')); + app.get('/api/fxa/login', fxa.login); + app.get('/api/fxa/oauth', fxa.oauth); + app.get('/api/filelist', auth.fxa, filelist.get); + app.post('/api/filelist', auth.fxa, filelist.post); + app.post('/api/upload', auth.fxa, require('./upload')); + app.post(`/api/delete/:id${ID_REGEX}`, auth.owner, require('./delete')); + app.post(`/api/password/:id${ID_REGEX}`, auth.owner, require('./password')); + app.post(`/api/params/:id${ID_REGEX}`, auth.owner, require('./params')); + app.post(`/api/info/:id${ID_REGEX}`, auth.owner, require('./info')); app.get('/__version__', function(req, res) { res.sendFile(require.resolve('../../dist/version.json')); diff --git a/server/routes/jsconfig.js b/server/routes/jsconfig.js index 11caecdf..1257a0c3 100644 --- a/server/routes/jsconfig.js +++ b/server/routes/jsconfig.js @@ -34,8 +34,21 @@ var isUnsupportedPage = /\\\/unsupported/.test(location.pathname); if (isIE && !isUnsupportedPage) { window.location.replace('/unsupported/ie'); } -var MAXFILESIZE = ${config.max_file_size}; -var DEFAULT_EXPIRE_SECONDS = ${config.default_expire_seconds}; +var LIMITS = { + ANON: { + MAX_FILE_SIZE: ${config.anon_max_file_size}, + MAX_DOWNLOADS: ${config.anon_max_downloads}, + MAX_EXPIRE_SECONDS: ${config.anon_max_expire_seconds}, + }, + MAX_FILE_SIZE: ${config.max_file_size}, + MAX_DOWNLOADS: ${config.max_downloads}, + MAX_EXPIRE_SECONDS: ${config.max_expire_seconds}, + MAX_FILES_PER_ARCHIVE: ${config.max_files_per_archive}, + MAX_ARCHIVES_PER_USER: ${config.max_archives_per_user} +}; +var DEFAULTS = { + EXPIRE_SECONDS: ${config.default_expire_seconds} +}; ${ga} ${sentry} `; diff --git a/server/routes/pages.js b/server/routes/pages.js index 4b8128cf..d880b549 100644 --- a/server/routes/pages.js +++ b/server/routes/pages.js @@ -27,7 +27,7 @@ module.exports = { routes.toString( `/download/${id}`, Object.assign(state(req), { - fileInfo: { nonce, requiresPassword: pwd } + downloadMetadata: { nonce, pwd } }) ) ) diff --git a/server/routes/params.js b/server/routes/params.js index 3cb75460..24d1546f 100644 --- a/server/routes/params.js +++ b/server/routes/params.js @@ -1,8 +1,10 @@ +const config = require('../config'); const storage = require('../storage'); module.exports = function(req, res) { const dlimit = req.body.dlimit; - if (!dlimit || dlimit > 20) { + // TODO: fxa auth + if (!dlimit || dlimit > config.max_downloads) { return res.sendStatus(400); } diff --git a/server/routes/ws.js b/server/routes/ws.js index 0fa99ec2..0da42903 100644 --- a/server/routes/ws.js +++ b/server/routes/ws.js @@ -5,10 +5,11 @@ const mozlog = require('../log'); const Limiter = require('../limiter'); const Parser = require('../streamparser'); const wsStream = require('websocket-stream/stream'); +// const fxa = require('./fxa'); const log = mozlog('send.upload'); -module.exports = async function(ws, req) { +module.exports = function(ws, req) { let fileStream; ws.on('close', e => { @@ -26,12 +27,19 @@ module.exports = async function(ws, req) { const timeLimit = fileInfo.timeLimit; const metadata = fileInfo.fileMetadata; const auth = fileInfo.authorization; + const user = '1'; //await fxa.verify(fileInfo.bearer); // TODO + const maxFileSize = user + ? config.max_file_size + : config.anon_max_file_size; + const maxExpireSeconds = user + ? config.max_expire_seconds + : config.anon_max_expire_seconds; if ( !metadata || !auth || timeLimit <= 0 || - timeLimit > config.max_expire_seconds + timeLimit > maxExpireSeconds ) { ws.send( JSON.stringify({ @@ -51,7 +59,7 @@ module.exports = async function(ws, req) { const protocol = config.env === 'production' ? 'https' : req.protocol; const url = `${protocol}://${req.get('host')}/download/${newId}/`; - const limiter = new Limiter(config.max_file_size); + const limiter = new Limiter(maxFileSize); const parser = new Parser(); fileStream = wsStream(ws, { binary: true }) .pipe(limiter) diff --git a/server/state.js b/server/state.js index 152ccd60..94147cec 100644 --- a/server/state.js +++ b/server/state.js @@ -1,9 +1,12 @@ const config = require('./config'); const layout = require('./layout'); const locales = require('../common/locales'); +const assets = require('../common/assets'); module.exports = function(req) { const locale = req.language || 'en-US'; + const userInfo = req.userInfo || { avatar: assets.get('user.svg') }; + userInfo.loggedIn = !!userInfo.access_token; return { locale, translate: locales.getTranslator(locale), @@ -17,6 +20,8 @@ module.exports = function(req) { }, fira: false, fileInfo: {}, + cspNonce: req.cspNonce, + user: userInfo, layout }; }; diff --git a/test/backend/auth-tests.js b/test/backend/auth-tests.js index 632007ab..cf424a8b 100644 --- a/test/backend/auth-tests.js +++ b/test/backend/auth-tests.js @@ -31,7 +31,7 @@ const storedMeta = { const authMiddleware = proxyquire('../../server/middleware/auth', { '../storage': storage -}); +}).hmac; describe('Owner Middleware', function() { afterEach(function() { diff --git a/test/backend/owner-tests.js b/test/backend/owner-tests.js index a5dd6589..380e3ce7 100644 --- a/test/backend/owner-tests.js +++ b/test/backend/owner-tests.js @@ -19,9 +19,9 @@ function response() { }; } -const ownerMiddleware = proxyquire('../../server/middleware/owner', { +const ownerMiddleware = proxyquire('../../server/middleware/auth', { '../storage': storage -}); +}).owner; describe('Owner Middleware', function() { afterEach(function() { diff --git a/test/backend/params-tests.js b/test/backend/params-tests.js index cba749f9..1ff38b2f 100644 --- a/test/backend/params-tests.js +++ b/test/backend/params-tests.js @@ -40,7 +40,7 @@ describe('/api/params', function() { it('sends a 400 if dlimit is too large', function() { const req = request('x'); const res = response(); - req.body.dlimit = 21; + req.body.dlimit = 201; paramsRoute(req, res); sinon.assert.calledWith(res.sendStatus, 400); }); diff --git a/test/frontend/tests/api-tests.js b/test/frontend/tests/api-tests.js index f8e8ad65..2fb96ce7 100644 --- a/test/frontend/tests/api-tests.js +++ b/test/frontend/tests/api-tests.js @@ -1,4 +1,4 @@ -/* global DEFAULT_EXPIRE_SECONDS */ +/* global DEFAULTS */ import assert from 'assert'; import Archive from '../../../app/archive'; import * as api from '../../../app/api'; @@ -23,8 +23,9 @@ describe('API', function() { enc, meta, verifierB64, - p, - DEFAULT_EXPIRE_SECONDS + DEFAULTS.EXPIRE_SECONDS, + null, + p ); const result = await up.result; @@ -43,8 +44,9 @@ describe('API', function() { enc, meta, verifierB64, - p, - DEFAULT_EXPIRE_SECONDS + DEFAULTS.EXPIRE_SECONDS, + null, + p ); up.cancel(); diff --git a/webpack.config.js b/webpack.config.js index f0c7e549..c0d343c0 100644 --- a/webpack.config.js +++ b/webpack.config.js @@ -176,7 +176,7 @@ const web = { from: '*.*' } ]), - new webpack.IgnorePlugin(/dist/), // used in common/*.js + new webpack.IgnorePlugin(/\.\.\/dist/), // used in common/*.js new webpack.IgnorePlugin(/require-from-string/), // used in common/locales.js new webpack.HashedModuleIdsPlugin(), new ExtractTextPlugin({