├── .gitignore ├── .watchmanconfig ├── App.js ├── README.md ├── app.example.json ├── babel.config.js ├── config ├── firestore.indexes.json ├── firestore.rules ├── options.example.json └── storage.rules ├── firebase.example.json ├── functions ├── .gitignore ├── expo.js ├── index.js ├── package-lock.json └── package.json ├── package-lock.json ├── package.json └── src ├── App.js ├── components ├── AddItemScreen.js ├── CameraView.js ├── Comments.js ├── ConvertAnonymousUser.js ├── EmojiOverlay.js ├── ItemScreen.js ├── Login.js ├── MapScreen.js └── Settings.js ├── containers ├── AddItemScreen.js ├── AuthContainer.js ├── ConvertAnonymousUser.js ├── DataContainer.js ├── ItemScreen.js ├── MapScreen.js ├── Navigator.js ├── NotificationContainer.js └── Settings.js └── lib ├── firebase.js ├── geo.js ├── options.js ├── theme.js ├── urlToBlob.js ├── usernameGenerator.js └── wrapInTry.js /.gitignore: -------------------------------------------------------------------------------- 1 | **/node_modules/**/* 2 | .expo/* 3 | npm-debug.* 4 | *.jks 5 | *.p12 6 | *.key 7 | *.mobileprovision 8 | /app.json 9 | /firebase.json 10 | /config/options.json 11 | assets/**/* 12 | firebase-debug.log 13 | .firebaserc 14 | node_modules 15 | -------------------------------------------------------------------------------- /.watchmanconfig: -------------------------------------------------------------------------------- 1 | {} 2 | -------------------------------------------------------------------------------- /App.js: -------------------------------------------------------------------------------- 1 | import App from './src/App' 2 | export default App 3 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # react-native-community-maps 2 | Boilerplate app to geographically map user content, built on top of the awesome [Expo toolchain](https://docs.expo.io/versions/latest/) 3 | 4 | ![VI2LsXBn6f](https://user-images.githubusercontent.com/1440796/54887040-ce998180-4e8e-11e9-8dca-bf285fc52adc.gif) 5 | 6 | Create your own app (in minutes!) to map interesting things around your neighborhood. Maybe it's your fav graffiti, or a really nice sofa that needs a new home. Other users are notified in real time and can comment on each post. 7 | 8 | ## Get started 9 | 1. Fork and clone this repo 10 | 2. Install package depenencies: run `npm i && cd functions && npm i && cd ..` 11 | 3. Use the `*.example.*` files to create you own versions of `app.json`, `firebase.json`, and `config/options.json` 12 | 4. Setup the backend: 13 | 1. Visit the [firebase console](https://console.firebase.google.com) and create a new project, 14 | 2. Select Authentication and enable Email/Password and Anonymous signin methods 15 | 3. Select Database and create a Firestore database 16 | 4. Select Storage and click Get Started 17 | 5. Install the [firebase cli](https://firebase.google.com/docs/cli/) 18 | 6. Run `firebase setup:web` and copy the printed config variables into `firebase.json` (don't overwrite existing rule paths) 19 | 7. Run `firebase deploy` 20 | 5. Run `expo start` 21 | 22 | ## Options 23 | `app.json` - this is your standard [expo config file](https://docs.expo.io/versions/latest/workflow/configuration/). You'll need to customize this before publishing. 24 | 25 | `config/options.json` - Everything related to the look-and-feel of the app, and which features are enabled, comes from this file. 26 | 27 | |name|default|description| 28 | |----|-------|-----------| 29 | |`defaultEmoji`|🍔|the default emoji for new items| 30 | |`noEmojiPicker`|`false`|disallow users to pick their own emoji for new items| 31 | |`newMsgPlaceholder`|['Say something...']|Array of placeholder strings to be chosen from at random| 32 | 33 | 34 | 35 | #### Projects using react-native-community-maps 36 | [Sofab](https://itunes.apple.com/us/app/sofab/id1455005485) 37 | -------------------------------------------------------------------------------- /app.example.json: -------------------------------------------------------------------------------- 1 | { 2 | "expo": { 3 | "name": "YourAppName", 4 | "slug": "your-app-slug", 5 | "privacy": "public", 6 | "sdkVersion": "31.0.0", 7 | "platforms": [ 8 | "ios", 9 | "android" 10 | ], 11 | "version": "1.0.0", 12 | "orientation": "portrait", 13 | "updates": { 14 | "fallbackToCacheTimeout": 0 15 | }, 16 | "assetBundlePatterns": [ 17 | "**/*" 18 | ], 19 | "ios": { 20 | "bundleIdentifier": "your.bundle.id", 21 | "buildNumber": "1", 22 | "infoPlist": { 23 | "NSCameraUsageDescription": "Upload pictures of what you find", 24 | "NSLocationWhenInUseUsageDescription": "Tell users where you took the picture" 25 | } 26 | }, 27 | "android": { 28 | "package": "your.package.id" 29 | } 30 | 31 | } 32 | } -------------------------------------------------------------------------------- /babel.config.js: -------------------------------------------------------------------------------- 1 | module.exports = function(api) { 2 | api.cache(true); 3 | return { 4 | presets: ['babel-preset-expo'], 5 | env: { 6 | production: { 7 | plugins: ['react-native-paper/babel'], 8 | }, 9 | }, 10 | }; 11 | }; -------------------------------------------------------------------------------- /config/firestore.indexes.json: -------------------------------------------------------------------------------- 1 | { 2 | // Example: 3 | // 4 | // "indexes": [ 5 | // { 6 | // "collectionGroup": "widgets", 7 | // "queryScope": "COLLECTION", 8 | // "fields": [ 9 | // { "fieldPath": "foo", "arrayConfig": "CONTAINS" }, 10 | // { "fieldPath": "bar", "mode": "DESCENDING" } 11 | // ] 12 | // }, 13 | // 14 | // "fieldOverrides": [ 15 | // { 16 | // "collectionGroup": "widgets", 17 | // "fieldPath": "baz", 18 | // "indexes": [ 19 | // { "order": "ASCENDING", "queryScope": "COLLECTION" } 20 | // ] 21 | // }, 22 | // ] 23 | // ] 24 | "indexes": [], 25 | "fieldOverrides": [] 26 | } -------------------------------------------------------------------------------- /config/firestore.rules: -------------------------------------------------------------------------------- 1 | // Allow read/write access on all documents to any user signed in to the application 2 | service cloud.firestore { 3 | match /databases/{database}/documents { 4 | match /{document=**} { 5 | allow read, write: if request.auth.uid != null; 6 | } 7 | } 8 | } -------------------------------------------------------------------------------- /config/options.example.json: -------------------------------------------------------------------------------- 1 | { 2 | "itemEmoji": "🍔", 3 | "placeholders": [ "Say something..." ], 4 | "noEmojiPicker": false, 5 | "shareUrl": "https://your-project-subdomain-goes-here.cloudfunctions.net/getItem/{id}" 6 | } -------------------------------------------------------------------------------- /config/storage.rules: -------------------------------------------------------------------------------- 1 | // Only authenticated users can read or write to the bucket 2 | service firebase.storage { 3 | match /b/{bucket}/o { 4 | match /{allPaths=**} { 5 | allow read, write: if request.auth != null; 6 | } 7 | } 8 | } -------------------------------------------------------------------------------- /firebase.example.json: -------------------------------------------------------------------------------- 1 | { 2 | "apiKey": "xxxxxxxxxxx", 3 | "authDomain": "xxxxxxxxxxx", 4 | "databaseURL": "xxxxxxxxxxx", 5 | "projectId": "xxxxxxxxxxx", 6 | "storageBucket": "xxxxxxxxxxx", 7 | "messagingSenderId": "xxxxxxxxxxx", 8 | "firestore": { 9 | "rules": "config/firestore.rules", 10 | "indexes": "config/firestore.indexes.json" 11 | }, 12 | "storage": { 13 | "rules": "config/storage.rules" 14 | } 15 | } -------------------------------------------------------------------------------- /functions/.gitignore: -------------------------------------------------------------------------------- 1 | node_modules/ -------------------------------------------------------------------------------- /functions/expo.js: -------------------------------------------------------------------------------- 1 | const axios = require('axios') 2 | 3 | const PUSH_URL = 'https://exp.host/--/api/v2/push/send' 4 | 5 | module.exports.sendPushNotification = payload => { 6 | return axios({ 7 | url: PUSH_URL, 8 | method: 'POST', 9 | data: payload, 10 | responseType: 'json' 11 | }) 12 | } -------------------------------------------------------------------------------- /functions/index.js: -------------------------------------------------------------------------------- 1 | const functions = require('firebase-functions') 2 | const { GeoFirestore } = require('geofirestore') 3 | 4 | const { sendPushNotification } = require('./expo') 5 | 6 | const express = require('express'); 7 | 8 | const admin = require('firebase-admin'); 9 | admin.initializeApp(); 10 | 11 | const firestore = admin.firestore() 12 | const geofirestore = new GeoFirestore(firestore); 13 | const notificationPreferences = geofirestore.collection('notificationPreferences') 14 | 15 | 16 | exports.onCreateItem = functions.firestore 17 | .document('items/{itemId}') 18 | .onCreate((snap, context) => { 19 | const data = snap.data() 20 | 21 | // get nearby users 22 | return notificationPreferences 23 | // this doesnt work for some reason. the link that it returns to create the requried index does nothing. 24 | // .where('shouldNotify', '==', true) 25 | .near({ center: data.coordinates, radius: 10000 }) 26 | .get() 27 | .then(result => { 28 | 29 | const notificationQueue = [] 30 | 31 | // filter users that should be notified 32 | result.docs.forEach(doc => { 33 | const { 34 | shouldNotify, 35 | pushToken, 36 | radius, 37 | } = doc.data() 38 | 39 | if ( 40 | shouldNotify && // do they want to be notified? 41 | pushToken && // do we have a push token for them? 42 | doc.distance*1000 < radius // is this item within the their notification radius? 43 | ) notificationQueue.push(pushToken) // if so, add it to the queue. 44 | }) 45 | 46 | const promises = notificationQueue.map(token => 47 | sendPushNotification({ 48 | to: token, 49 | title: "New item available", 50 | data, 51 | }) 52 | ) 53 | 54 | return Promise.all(promises) 55 | .then(() => true) 56 | }) 57 | }) 58 | 59 | 60 | const app = express(); 61 | app.get('/:id', (req, res) => { 62 | return firestore 63 | .collection('items') 64 | .doc(req.params.id) 65 | .get() 66 | .then(doc => { 67 | if (!doc.exists) 68 | return res.status(404).send('You just got 404\'d!!') 69 | const data = doc.data() 70 | res.status(200).send(` 71 | 72 | 73 | Nice find! 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 125 | 126 | 127 |
128 |
129 | 130 | 131 |
132 |
133 | 138 | 139 |
140 |
141 | 142 | 156 | 157 | `); 158 | }) 159 | }); 160 | 161 | exports.getItem = functions.https.onRequest(app); 162 | -------------------------------------------------------------------------------- /functions/package-lock.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "functions", 3 | "requires": true, 4 | "lockfileVersion": 1, 5 | "dependencies": { 6 | "@firebase/app": { 7 | "version": "0.3.9", 8 | "resolved": "https://registry.npmjs.org/@firebase/app/-/app-0.3.9.tgz", 9 | "integrity": "sha512-mjgBSQsjln5vAV4zDIn3gjsRlcvn6KxMVNGdhdJmrHRPfjBYUQJycn2X3xwF0krwB41WS8SQCsHHQssXY+kfVQ==", 10 | "requires": { 11 | "@firebase/app-types": "0.3.4", 12 | "@firebase/util": "0.2.7", 13 | "dom-storage": "2.1.0", 14 | "tslib": "1.9.0", 15 | "xmlhttprequest": "1.8.0" 16 | } 17 | }, 18 | "@firebase/app-types": { 19 | "version": "0.3.4", 20 | "resolved": "https://registry.npmjs.org/@firebase/app-types/-/app-types-0.3.4.tgz", 21 | "integrity": "sha512-XIc1wu7CJ0469STQPwyuokcBGFpRr7BVKKdajj/wAxzNntatDTXo1jdGfmjA8UYcuvW+QJmMkOE9KIOf5HgSzw==" 22 | }, 23 | "@firebase/auth": { 24 | "version": "0.12.0", 25 | "resolved": "https://registry.npmjs.org/@firebase/auth/-/auth-0.12.0.tgz", 26 | "integrity": "sha512-DGYvAmz2aUmrWYS3ADw/UmsuicxJi6G+X38XITqNPUrd1YxmM5SBzX19oEb9WCrJZXcr4JaESg6hQkT2yEPaCA==", 27 | "requires": { 28 | "@firebase/auth-types": "0.8.0" 29 | } 30 | }, 31 | "@firebase/auth-types": { 32 | "version": "0.8.0", 33 | "resolved": "https://registry.npmjs.org/@firebase/auth-types/-/auth-types-0.8.0.tgz", 34 | "integrity": "sha512-foQHhvyB0RR+mb/+wmHXd/VOU+D8fruFEW1k79Q9wzyTPpovMBa1Mcns5fwEWBhUfi8bmoEtaGB8RSAHnTFzTg==" 35 | }, 36 | "@firebase/database": { 37 | "version": "0.3.12", 38 | "resolved": "https://registry.npmjs.org/@firebase/database/-/database-0.3.12.tgz", 39 | "integrity": "sha512-Gim1kYUXBOX7xYwrBY6sOgQerOkhYGYvwwPCFeuBTXVy6X8b98SCSk7oMrmrG0+tG6gosmq7CT59AOxZEx4/0Q==", 40 | "requires": { 41 | "@firebase/database-types": "0.3.5", 42 | "@firebase/logger": "0.1.6", 43 | "@firebase/util": "0.2.7", 44 | "faye-websocket": "0.11.1", 45 | "tslib": "1.9.0" 46 | } 47 | }, 48 | "@firebase/database-types": { 49 | "version": "0.3.5", 50 | "resolved": "https://registry.npmjs.org/@firebase/database-types/-/database-types-0.3.5.tgz", 51 | "integrity": "sha512-MB98w9DsZtTN45sf651s5z4f2zdn5gPi2SMaZk32HLihPDgKv5pepzZ+grxioM7z5ZU1EvjjXRL7oM81OH3mZQ==" 52 | }, 53 | "@firebase/firestore": { 54 | "version": "1.5.3", 55 | "resolved": "https://registry.npmjs.org/@firebase/firestore/-/firestore-1.5.3.tgz", 56 | "integrity": "sha512-O/yAbXpitOA6g627cUl0/FHYlkTy1EiEKMKOlnlMOJF2fH+nLVZREXjsrCC7N2tIvTn7yYwfpZ4zpSNvrhwiTA==", 57 | "requires": { 58 | "@firebase/firestore-types": "1.5.0", 59 | "@firebase/logger": "0.1.25", 60 | "@firebase/util": "0.2.28", 61 | "@firebase/webchannel-wrapper": "0.2.26", 62 | "@grpc/proto-loader": "^0.5.0", 63 | "grpc": "1.23.3", 64 | "tslib": "1.10.0" 65 | }, 66 | "dependencies": { 67 | "@firebase/firestore-types": { 68 | "version": "1.5.0", 69 | "resolved": "https://registry.npmjs.org/@firebase/firestore-types/-/firestore-types-1.5.0.tgz", 70 | "integrity": "sha512-VhRHNbEbak+R2iK8e1ir2Lec7eaHMZpGTRy6LMtzATYthlkwNHF9tO8JU8l6d1/kYkI4+DWzX++i3HhTziHEWA==" 71 | }, 72 | "@firebase/logger": { 73 | "version": "0.1.25", 74 | "resolved": "https://registry.npmjs.org/@firebase/logger/-/logger-0.1.25.tgz", 75 | "integrity": "sha512-/lRhuepVcCCnQ2jcO5Hr08SYdmZDTQU9fdPdzg+qXJ9k/QnIrD2RbswXQcL6mmae3uPpX7fFXQAoScJ9pzp50w==" 76 | }, 77 | "@firebase/util": { 78 | "version": "0.2.28", 79 | "resolved": "https://registry.npmjs.org/@firebase/util/-/util-0.2.28.tgz", 80 | "integrity": "sha512-ZQMAWtXj8y5kvB6izs0aTM/jG+WO8HpqhXA/EwD6LckJ+1P5LnAhaLZt1zR4HpuCE+jeP5I32Id5RJ/aifFs6A==", 81 | "requires": { 82 | "tslib": "1.10.0" 83 | } 84 | }, 85 | "@grpc/proto-loader": { 86 | "version": "0.5.3", 87 | "resolved": "https://registry.npmjs.org/@grpc/proto-loader/-/proto-loader-0.5.3.tgz", 88 | "integrity": "sha512-8qvUtGg77G2ZT2HqdqYoM/OY97gQd/0crSG34xNmZ4ZOsv3aQT/FQV9QfZPazTGna6MIoyUd+u6AxsoZjJ/VMQ==", 89 | "requires": { 90 | "lodash.camelcase": "^4.3.0", 91 | "protobufjs": "^6.8.6" 92 | } 93 | }, 94 | "grpc": { 95 | "version": "1.23.3", 96 | "resolved": "https://registry.npmjs.org/grpc/-/grpc-1.23.3.tgz", 97 | "integrity": "sha512-7vdzxPw9s5UYch4aUn4hyM5tMaouaxUUkwkgJlwbR4AXMxiYZJOv19N2ps2eKiuUbJovo5fnGF9hg/X91gWYjw==", 98 | "requires": { 99 | "@types/bytebuffer": "^5.0.40", 100 | "lodash.camelcase": "^4.3.0", 101 | "lodash.clone": "^4.5.0", 102 | "nan": "^2.13.2", 103 | "node-pre-gyp": "^0.13.0", 104 | "protobufjs": "^5.0.3" 105 | }, 106 | "dependencies": { 107 | "abbrev": { 108 | "version": "1.1.1", 109 | "bundled": true 110 | }, 111 | "ansi-regex": { 112 | "version": "2.1.1", 113 | "bundled": true 114 | }, 115 | "aproba": { 116 | "version": "1.2.0", 117 | "bundled": true 118 | }, 119 | "are-we-there-yet": { 120 | "version": "1.1.5", 121 | "bundled": true, 122 | "requires": { 123 | "delegates": "^1.0.0", 124 | "readable-stream": "^2.0.6" 125 | } 126 | }, 127 | "balanced-match": { 128 | "version": "1.0.0", 129 | "bundled": true 130 | }, 131 | "brace-expansion": { 132 | "version": "1.1.11", 133 | "bundled": true, 134 | "requires": { 135 | "balanced-match": "^1.0.0", 136 | "concat-map": "0.0.1" 137 | } 138 | }, 139 | "chownr": { 140 | "version": "1.1.2", 141 | "bundled": true 142 | }, 143 | "code-point-at": { 144 | "version": "1.1.0", 145 | "bundled": true 146 | }, 147 | "concat-map": { 148 | "version": "0.0.1", 149 | "bundled": true 150 | }, 151 | "console-control-strings": { 152 | "version": "1.1.0", 153 | "bundled": true 154 | }, 155 | "core-util-is": { 156 | "version": "1.0.2", 157 | "bundled": true 158 | }, 159 | "debug": { 160 | "version": "3.2.6", 161 | "bundled": true, 162 | "requires": { 163 | "ms": "^2.1.1" 164 | } 165 | }, 166 | "deep-extend": { 167 | "version": "0.6.0", 168 | "bundled": true 169 | }, 170 | "delegates": { 171 | "version": "1.0.0", 172 | "bundled": true 173 | }, 174 | "detect-libc": { 175 | "version": "1.0.3", 176 | "bundled": true 177 | }, 178 | "fs-minipass": { 179 | "version": "1.2.6", 180 | "bundled": true, 181 | "requires": { 182 | "minipass": "^2.2.1" 183 | } 184 | }, 185 | "fs.realpath": { 186 | "version": "1.0.0", 187 | "bundled": true 188 | }, 189 | "gauge": { 190 | "version": "2.7.4", 191 | "bundled": true, 192 | "requires": { 193 | "aproba": "^1.0.3", 194 | "console-control-strings": "^1.0.0", 195 | "has-unicode": "^2.0.0", 196 | "object-assign": "^4.1.0", 197 | "signal-exit": "^3.0.0", 198 | "string-width": "^1.0.1", 199 | "strip-ansi": "^3.0.1", 200 | "wide-align": "^1.1.0" 201 | } 202 | }, 203 | "glob": { 204 | "version": "7.1.4", 205 | "bundled": true, 206 | "requires": { 207 | "fs.realpath": "^1.0.0", 208 | "inflight": "^1.0.4", 209 | "inherits": "2", 210 | "minimatch": "^3.0.4", 211 | "once": "^1.3.0", 212 | "path-is-absolute": "^1.0.0" 213 | } 214 | }, 215 | "has-unicode": { 216 | "version": "2.0.1", 217 | "bundled": true 218 | }, 219 | "iconv-lite": { 220 | "version": "0.4.24", 221 | "bundled": true, 222 | "requires": { 223 | "safer-buffer": ">= 2.1.2 < 3" 224 | } 225 | }, 226 | "ignore-walk": { 227 | "version": "3.0.1", 228 | "bundled": true, 229 | "requires": { 230 | "minimatch": "^3.0.4" 231 | } 232 | }, 233 | "inflight": { 234 | "version": "1.0.6", 235 | "bundled": true, 236 | "requires": { 237 | "once": "^1.3.0", 238 | "wrappy": "1" 239 | } 240 | }, 241 | "inherits": { 242 | "version": "2.0.4", 243 | "bundled": true 244 | }, 245 | "ini": { 246 | "version": "1.3.5", 247 | "bundled": true 248 | }, 249 | "is-fullwidth-code-point": { 250 | "version": "1.0.0", 251 | "bundled": true, 252 | "requires": { 253 | "number-is-nan": "^1.0.0" 254 | } 255 | }, 256 | "isarray": { 257 | "version": "1.0.0", 258 | "bundled": true 259 | }, 260 | "minimatch": { 261 | "version": "3.0.4", 262 | "bundled": true, 263 | "requires": { 264 | "brace-expansion": "^1.1.7" 265 | } 266 | }, 267 | "minimist": { 268 | "version": "1.2.0", 269 | "bundled": true 270 | }, 271 | "minipass": { 272 | "version": "2.3.5", 273 | "bundled": true, 274 | "requires": { 275 | "safe-buffer": "^5.1.2", 276 | "yallist": "^3.0.0" 277 | } 278 | }, 279 | "minizlib": { 280 | "version": "1.2.1", 281 | "bundled": true, 282 | "requires": { 283 | "minipass": "^2.2.1" 284 | } 285 | }, 286 | "mkdirp": { 287 | "version": "0.5.1", 288 | "bundled": true, 289 | "requires": { 290 | "minimist": "0.0.8" 291 | }, 292 | "dependencies": { 293 | "minimist": { 294 | "version": "0.0.8", 295 | "bundled": true 296 | } 297 | } 298 | }, 299 | "ms": { 300 | "version": "2.1.2", 301 | "bundled": true 302 | }, 303 | "needle": { 304 | "version": "2.4.0", 305 | "bundled": true, 306 | "requires": { 307 | "debug": "^3.2.6", 308 | "iconv-lite": "^0.4.4", 309 | "sax": "^1.2.4" 310 | } 311 | }, 312 | "node-pre-gyp": { 313 | "version": "0.13.0", 314 | "bundled": true, 315 | "requires": { 316 | "detect-libc": "^1.0.2", 317 | "mkdirp": "^0.5.1", 318 | "needle": "^2.2.1", 319 | "nopt": "^4.0.1", 320 | "npm-packlist": "^1.1.6", 321 | "npmlog": "^4.0.2", 322 | "rc": "^1.2.7", 323 | "rimraf": "^2.6.1", 324 | "semver": "^5.3.0", 325 | "tar": "^4" 326 | } 327 | }, 328 | "nopt": { 329 | "version": "4.0.1", 330 | "bundled": true, 331 | "requires": { 332 | "abbrev": "1", 333 | "osenv": "^0.1.4" 334 | } 335 | }, 336 | "npm-bundled": { 337 | "version": "1.0.6", 338 | "bundled": true 339 | }, 340 | "npm-packlist": { 341 | "version": "1.4.4", 342 | "bundled": true, 343 | "requires": { 344 | "ignore-walk": "^3.0.1", 345 | "npm-bundled": "^1.0.1" 346 | } 347 | }, 348 | "npmlog": { 349 | "version": "4.1.2", 350 | "bundled": true, 351 | "requires": { 352 | "are-we-there-yet": "~1.1.2", 353 | "console-control-strings": "~1.1.0", 354 | "gauge": "~2.7.3", 355 | "set-blocking": "~2.0.0" 356 | } 357 | }, 358 | "number-is-nan": { 359 | "version": "1.0.1", 360 | "bundled": true 361 | }, 362 | "object-assign": { 363 | "version": "4.1.1", 364 | "bundled": true 365 | }, 366 | "once": { 367 | "version": "1.4.0", 368 | "bundled": true, 369 | "requires": { 370 | "wrappy": "1" 371 | } 372 | }, 373 | "os-homedir": { 374 | "version": "1.0.2", 375 | "bundled": true 376 | }, 377 | "os-tmpdir": { 378 | "version": "1.0.2", 379 | "bundled": true 380 | }, 381 | "osenv": { 382 | "version": "0.1.5", 383 | "bundled": true, 384 | "requires": { 385 | "os-homedir": "^1.0.0", 386 | "os-tmpdir": "^1.0.0" 387 | } 388 | }, 389 | "path-is-absolute": { 390 | "version": "1.0.1", 391 | "bundled": true 392 | }, 393 | "process-nextick-args": { 394 | "version": "2.0.1", 395 | "bundled": true 396 | }, 397 | "protobufjs": { 398 | "version": "5.0.3", 399 | "resolved": "https://registry.npmjs.org/protobufjs/-/protobufjs-5.0.3.tgz", 400 | "integrity": "sha512-55Kcx1MhPZX0zTbVosMQEO5R6/rikNXd9b6RQK4KSPcrSIIwoXTtebIczUrXlwaSrbz4x8XUVThGPob1n8I4QA==", 401 | "requires": { 402 | "ascli": "~1", 403 | "bytebuffer": "~5", 404 | "glob": "^7.0.5", 405 | "yargs": "^3.10.0" 406 | } 407 | }, 408 | "rc": { 409 | "version": "1.2.8", 410 | "bundled": true, 411 | "requires": { 412 | "deep-extend": "^0.6.0", 413 | "ini": "~1.3.0", 414 | "minimist": "^1.2.0", 415 | "strip-json-comments": "~2.0.1" 416 | } 417 | }, 418 | "readable-stream": { 419 | "version": "2.3.6", 420 | "bundled": true, 421 | "requires": { 422 | "core-util-is": "~1.0.0", 423 | "inherits": "~2.0.3", 424 | "isarray": "~1.0.0", 425 | "process-nextick-args": "~2.0.0", 426 | "safe-buffer": "~5.1.1", 427 | "string_decoder": "~1.1.1", 428 | "util-deprecate": "~1.0.1" 429 | } 430 | }, 431 | "rimraf": { 432 | "version": "2.7.1", 433 | "bundled": true, 434 | "requires": { 435 | "glob": "^7.1.3" 436 | } 437 | }, 438 | "safe-buffer": { 439 | "version": "5.1.2", 440 | "bundled": true 441 | }, 442 | "safer-buffer": { 443 | "version": "2.1.2", 444 | "bundled": true 445 | }, 446 | "sax": { 447 | "version": "1.2.4", 448 | "bundled": true 449 | }, 450 | "semver": { 451 | "version": "5.7.1", 452 | "bundled": true 453 | }, 454 | "set-blocking": { 455 | "version": "2.0.0", 456 | "bundled": true 457 | }, 458 | "signal-exit": { 459 | "version": "3.0.2", 460 | "bundled": true 461 | }, 462 | "string-width": { 463 | "version": "1.0.2", 464 | "bundled": true, 465 | "requires": { 466 | "code-point-at": "^1.0.0", 467 | "is-fullwidth-code-point": "^1.0.0", 468 | "strip-ansi": "^3.0.0" 469 | } 470 | }, 471 | "string_decoder": { 472 | "version": "1.1.1", 473 | "bundled": true, 474 | "requires": { 475 | "safe-buffer": "~5.1.0" 476 | } 477 | }, 478 | "strip-ansi": { 479 | "version": "3.0.1", 480 | "bundled": true, 481 | "requires": { 482 | "ansi-regex": "^2.0.0" 483 | } 484 | }, 485 | "strip-json-comments": { 486 | "version": "2.0.1", 487 | "bundled": true 488 | }, 489 | "tar": { 490 | "version": "4.4.10", 491 | "bundled": true, 492 | "requires": { 493 | "chownr": "^1.1.1", 494 | "fs-minipass": "^1.2.5", 495 | "minipass": "^2.3.5", 496 | "minizlib": "^1.2.1", 497 | "mkdirp": "^0.5.0", 498 | "safe-buffer": "^5.1.2", 499 | "yallist": "^3.0.3" 500 | } 501 | }, 502 | "util-deprecate": { 503 | "version": "1.0.2", 504 | "bundled": true 505 | }, 506 | "wide-align": { 507 | "version": "1.1.3", 508 | "bundled": true, 509 | "requires": { 510 | "string-width": "^1.0.2 || 2" 511 | } 512 | }, 513 | "wrappy": { 514 | "version": "1.0.2", 515 | "bundled": true 516 | }, 517 | "yallist": { 518 | "version": "3.0.3", 519 | "bundled": true 520 | } 521 | } 522 | }, 523 | "nan": { 524 | "version": "2.14.0", 525 | "resolved": "https://registry.npmjs.org/nan/-/nan-2.14.0.tgz", 526 | "integrity": "sha512-INOFj37C7k3AfaNTtX8RhsTw7qRy7eLET14cROi9+5HAVbbHuIWUHEauBv5qT4Av2tWasiTY1Jw6puUNqRJXQg==" 527 | }, 528 | "tslib": { 529 | "version": "1.10.0", 530 | "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.10.0.tgz", 531 | "integrity": "sha512-qOebF53frne81cf0S9B41ByenJ3/IuH8yJKngAX35CmiZySA0khhkovshKK+jGCaMnVomla7gVlIcc3EvKPbTQ==" 532 | } 533 | } 534 | }, 535 | "@firebase/firestore-types": { 536 | "version": "1.9.0", 537 | "resolved": "https://registry.npmjs.org/@firebase/firestore-types/-/firestore-types-1.9.0.tgz", 538 | "integrity": "sha512-UOtneGMUTLr58P56Y0GT/c4ZyC39vOoRAzgwad4PIsyc7HlKShbHKJpyys/LdlUYIsQdy/2El3Qy1veiBQ+ZJg==" 539 | }, 540 | "@firebase/functions": { 541 | "version": "0.4.18", 542 | "resolved": "https://registry.npmjs.org/@firebase/functions/-/functions-0.4.18.tgz", 543 | "integrity": "sha512-N/ijwpxJy26kOErYIi5QS8pQgMZEuEMF/zDaNmgqcoN3J8P52NhBnVQZnIl+U4W96nQfNiURhSwXEERHFyvSZQ==", 544 | "requires": { 545 | "@firebase/functions-types": "0.3.8", 546 | "@firebase/messaging-types": "0.3.2", 547 | "isomorphic-fetch": "2.2.1", 548 | "tslib": "1.10.0" 549 | }, 550 | "dependencies": { 551 | "tslib": { 552 | "version": "1.10.0", 553 | "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.10.0.tgz", 554 | "integrity": "sha512-qOebF53frne81cf0S9B41ByenJ3/IuH8yJKngAX35CmiZySA0khhkovshKK+jGCaMnVomla7gVlIcc3EvKPbTQ==" 555 | } 556 | } 557 | }, 558 | "@firebase/functions-types": { 559 | "version": "0.3.8", 560 | "resolved": "https://registry.npmjs.org/@firebase/functions-types/-/functions-types-0.3.8.tgz", 561 | "integrity": "sha512-9hajHxA4UWVCGFmoL8PBYHpamE3JTNjObieMmnvZw3cMRTP2EwipMpzZi+GPbMlA/9swF9yHCY/XFAEkwbvdgQ==" 562 | }, 563 | "@firebase/installations": { 564 | "version": "0.2.7", 565 | "resolved": "https://registry.npmjs.org/@firebase/installations/-/installations-0.2.7.tgz", 566 | "integrity": "sha512-67tzowHVwRBtEuB1HLMD+fCdoRyinOQlMKBes7UwrtZIVd0CPDUqAKxNqup5EypWZb7O2tqFtRzK7POajfSNMA==", 567 | "requires": { 568 | "@firebase/installations-types": "0.1.2", 569 | "@firebase/util": "0.2.28", 570 | "idb": "3.0.2", 571 | "tslib": "1.10.0" 572 | }, 573 | "dependencies": { 574 | "@firebase/util": { 575 | "version": "0.2.28", 576 | "resolved": "https://registry.npmjs.org/@firebase/util/-/util-0.2.28.tgz", 577 | "integrity": "sha512-ZQMAWtXj8y5kvB6izs0aTM/jG+WO8HpqhXA/EwD6LckJ+1P5LnAhaLZt1zR4HpuCE+jeP5I32Id5RJ/aifFs6A==", 578 | "requires": { 579 | "tslib": "1.10.0" 580 | } 581 | }, 582 | "tslib": { 583 | "version": "1.10.0", 584 | "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.10.0.tgz", 585 | "integrity": "sha512-qOebF53frne81cf0S9B41ByenJ3/IuH8yJKngAX35CmiZySA0khhkovshKK+jGCaMnVomla7gVlIcc3EvKPbTQ==" 586 | } 587 | } 588 | }, 589 | "@firebase/installations-types": { 590 | "version": "0.1.2", 591 | "resolved": "https://registry.npmjs.org/@firebase/installations-types/-/installations-types-0.1.2.tgz", 592 | "integrity": "sha512-fQaWIW8hyX1XUN7+FCSPjvM1agFjGidVuF4Sxi7aFwfyh5t+4fD2VpM4wCQbWmodnx4fZLvsuQd9mkxxU+lGYQ==" 593 | }, 594 | "@firebase/logger": { 595 | "version": "0.1.6", 596 | "resolved": "https://registry.npmjs.org/@firebase/logger/-/logger-0.1.6.tgz", 597 | "integrity": "sha512-74COMdYK/CZBgCSzEJGtQYpi1wGg1QlCUTQ/BrqqEIGg7GcnEcUCyjtRLogRQPYj3P7qaJLzHTSErJ8ZUAGotQ==" 598 | }, 599 | "@firebase/messaging": { 600 | "version": "0.4.11", 601 | "resolved": "https://registry.npmjs.org/@firebase/messaging/-/messaging-0.4.11.tgz", 602 | "integrity": "sha512-KYt479yio6ThkV7Pb9LRB1KPIBio+OR4RozwyoLC1ZSVQdTIrd/sVEuDSzYY88Wh/6Kg6ejdu2z6mfWG9l1ZaQ==", 603 | "requires": { 604 | "@firebase/messaging-types": "0.3.2", 605 | "@firebase/util": "0.2.28", 606 | "tslib": "1.10.0" 607 | }, 608 | "dependencies": { 609 | "@firebase/util": { 610 | "version": "0.2.28", 611 | "resolved": "https://registry.npmjs.org/@firebase/util/-/util-0.2.28.tgz", 612 | "integrity": "sha512-ZQMAWtXj8y5kvB6izs0aTM/jG+WO8HpqhXA/EwD6LckJ+1P5LnAhaLZt1zR4HpuCE+jeP5I32Id5RJ/aifFs6A==", 613 | "requires": { 614 | "tslib": "1.10.0" 615 | } 616 | }, 617 | "tslib": { 618 | "version": "1.10.0", 619 | "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.10.0.tgz", 620 | "integrity": "sha512-qOebF53frne81cf0S9B41ByenJ3/IuH8yJKngAX35CmiZySA0khhkovshKK+jGCaMnVomla7gVlIcc3EvKPbTQ==" 621 | } 622 | } 623 | }, 624 | "@firebase/messaging-types": { 625 | "version": "0.3.2", 626 | "resolved": "https://registry.npmjs.org/@firebase/messaging-types/-/messaging-types-0.3.2.tgz", 627 | "integrity": "sha512-2qa2qNKqpalmtwaUV3+wQqfCm5myP/dViIBv+pXF8HinemIfO1IPQtr9pCNfsSYyus78qEhtfldnPWXxUH5v0w==" 628 | }, 629 | "@firebase/performance": { 630 | "version": "0.2.19", 631 | "resolved": "https://registry.npmjs.org/@firebase/performance/-/performance-0.2.19.tgz", 632 | "integrity": "sha512-dINWwR/XcSiSnFNNX7QWfec8bymiXk1Zp6mPyPN+R9ONMrpDbygQUy06oT/6r/xx9nHG4Za6KMUJag3sWNKqnQ==", 633 | "requires": { 634 | "@firebase/installations": "0.2.7", 635 | "@firebase/logger": "0.1.25", 636 | "@firebase/performance-types": "0.0.3", 637 | "@firebase/util": "0.2.28", 638 | "tslib": "1.10.0" 639 | }, 640 | "dependencies": { 641 | "@firebase/logger": { 642 | "version": "0.1.25", 643 | "resolved": "https://registry.npmjs.org/@firebase/logger/-/logger-0.1.25.tgz", 644 | "integrity": "sha512-/lRhuepVcCCnQ2jcO5Hr08SYdmZDTQU9fdPdzg+qXJ9k/QnIrD2RbswXQcL6mmae3uPpX7fFXQAoScJ9pzp50w==" 645 | }, 646 | "@firebase/util": { 647 | "version": "0.2.28", 648 | "resolved": "https://registry.npmjs.org/@firebase/util/-/util-0.2.28.tgz", 649 | "integrity": "sha512-ZQMAWtXj8y5kvB6izs0aTM/jG+WO8HpqhXA/EwD6LckJ+1P5LnAhaLZt1zR4HpuCE+jeP5I32Id5RJ/aifFs6A==", 650 | "requires": { 651 | "tslib": "1.10.0" 652 | } 653 | }, 654 | "tslib": { 655 | "version": "1.10.0", 656 | "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.10.0.tgz", 657 | "integrity": "sha512-qOebF53frne81cf0S9B41ByenJ3/IuH8yJKngAX35CmiZySA0khhkovshKK+jGCaMnVomla7gVlIcc3EvKPbTQ==" 658 | } 659 | } 660 | }, 661 | "@firebase/performance-types": { 662 | "version": "0.0.3", 663 | "resolved": "https://registry.npmjs.org/@firebase/performance-types/-/performance-types-0.0.3.tgz", 664 | "integrity": "sha512-RuC63nYJPJU65AsrNMc3fTRcRgHiyNcQLh9ufeKUT1mEsFgpxr167gMb+tpzNU4jsbvM6+c6nQAFdHpqcGkRlQ==" 665 | }, 666 | "@firebase/polyfill": { 667 | "version": "0.3.22", 668 | "resolved": "https://registry.npmjs.org/@firebase/polyfill/-/polyfill-0.3.22.tgz", 669 | "integrity": "sha512-PYbEqDHJhJJoF2Q5IB/oP0Tz6O2vSUPtODy9kUQibi+T0bK1gkTaySPwz8GAgHfIpFNENj1kK+7Xpf87R8bYbw==", 670 | "requires": { 671 | "core-js": "3.2.1", 672 | "promise-polyfill": "8.1.3", 673 | "whatwg-fetch": "2.0.4" 674 | }, 675 | "dependencies": { 676 | "whatwg-fetch": { 677 | "version": "2.0.4", 678 | "resolved": "https://registry.npmjs.org/whatwg-fetch/-/whatwg-fetch-2.0.4.tgz", 679 | "integrity": "sha512-dcQ1GWpOD/eEQ97k66aiEVpNnapVj90/+R+SXTPYGHpYBBypfKJEQjLrvMZ7YXbKm21gXd4NcuxUTjiv1YtLng==" 680 | } 681 | } 682 | }, 683 | "@firebase/storage": { 684 | "version": "0.3.12", 685 | "resolved": "https://registry.npmjs.org/@firebase/storage/-/storage-0.3.12.tgz", 686 | "integrity": "sha512-8hXt3qPZlVH+yPF4W9Dc15/gBiTPGUJUgYs3dH9WnO41QWl1o4aNlZpZK/pdnpCIO1GmN0+PxJW9TCNb0H0Hqw==", 687 | "requires": { 688 | "@firebase/storage-types": "0.3.3", 689 | "@firebase/util": "0.2.28", 690 | "tslib": "1.10.0" 691 | }, 692 | "dependencies": { 693 | "@firebase/util": { 694 | "version": "0.2.28", 695 | "resolved": "https://registry.npmjs.org/@firebase/util/-/util-0.2.28.tgz", 696 | "integrity": "sha512-ZQMAWtXj8y5kvB6izs0aTM/jG+WO8HpqhXA/EwD6LckJ+1P5LnAhaLZt1zR4HpuCE+jeP5I32Id5RJ/aifFs6A==", 697 | "requires": { 698 | "tslib": "1.10.0" 699 | } 700 | }, 701 | "tslib": { 702 | "version": "1.10.0", 703 | "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.10.0.tgz", 704 | "integrity": "sha512-qOebF53frne81cf0S9B41ByenJ3/IuH8yJKngAX35CmiZySA0khhkovshKK+jGCaMnVomla7gVlIcc3EvKPbTQ==" 705 | } 706 | } 707 | }, 708 | "@firebase/storage-types": { 709 | "version": "0.3.3", 710 | "resolved": "https://registry.npmjs.org/@firebase/storage-types/-/storage-types-0.3.3.tgz", 711 | "integrity": "sha512-fUp4kpbxwDiWs/aIBJqBvXgFHZvgoND2JA0gJYSEsXtWtVwfgzY/710plErgZDeQKopX5eOR1sHskZkQUy0U6w==" 712 | }, 713 | "@firebase/util": { 714 | "version": "0.2.7", 715 | "resolved": "https://registry.npmjs.org/@firebase/util/-/util-0.2.7.tgz", 716 | "integrity": "sha512-I6rN6smH1XEXUIDySI2jr4pM8r2tBnE40mANYco2lbzs2D0nk9aiwKp5MTWRAmqRy4WDe7sx9sqs0cFefzsD6A==", 717 | "requires": { 718 | "tslib": "1.9.0" 719 | } 720 | }, 721 | "@firebase/webchannel-wrapper": { 722 | "version": "0.2.26", 723 | "resolved": "https://registry.npmjs.org/@firebase/webchannel-wrapper/-/webchannel-wrapper-0.2.26.tgz", 724 | "integrity": "sha512-VlTurkvs4v7EVFWESBZGOPghFEokQhU5au5CP9WqA8B2/PcQRDsaaQlQCA6VATuEnW+vtSiSBvTiOc4004f8xg==" 725 | }, 726 | "@google-cloud/common": { 727 | "version": "0.31.0", 728 | "resolved": "https://registry.npmjs.org/@google-cloud/common/-/common-0.31.0.tgz", 729 | "integrity": "sha512-mO7WFavzqmr24btNb2zimUh+M3fGnIKGbkR1VT6ZG3yDV+S7BiZPmPiFHKRJVrxwi5sA9U6X6fpNpHgj7j2a2w==", 730 | "optional": true, 731 | "requires": { 732 | "@google-cloud/projectify": "^0.3.2", 733 | "@google-cloud/promisify": "^0.3.0", 734 | "@types/duplexify": "^3.5.0", 735 | "@types/request": "^2.47.0", 736 | "arrify": "^1.0.1", 737 | "duplexify": "^3.6.0", 738 | "ent": "^2.2.0", 739 | "extend": "^3.0.1", 740 | "google-auth-library": "^3.0.0", 741 | "pify": "^4.0.0", 742 | "retry-request": "^4.0.0" 743 | } 744 | }, 745 | "@google-cloud/firestore": { 746 | "version": "1.0.1", 747 | "resolved": "https://registry.npmjs.org/@google-cloud/firestore/-/firestore-1.0.1.tgz", 748 | "integrity": "sha512-h8DxYkrP62VZjmwUJWwsm9F+fUagne2ANML9eIOPT3JWBS+41ZBxNgxOjH8hR5Htxz6GD+xsrr0KYxKBd1eepQ==", 749 | "requires": { 750 | "@google-cloud/projectify": "^0.3.0", 751 | "bun": "^0.0.12", 752 | "deep-equal": "^1.0.1", 753 | "extend": "^3.0.1", 754 | "functional-red-black-tree": "^1.0.1", 755 | "google-gax": "^0.24.0", 756 | "is": "^3.2.1", 757 | "lodash.merge": "^4.6.1", 758 | "protobufjs": "^6.8.6", 759 | "through2": "^3.0.0" 760 | } 761 | }, 762 | "@google-cloud/paginator": { 763 | "version": "0.1.2", 764 | "resolved": "https://registry.npmjs.org/@google-cloud/paginator/-/paginator-0.1.2.tgz", 765 | "integrity": "sha512-XL09cuPSEPyyNifavxWJRYkUFr5zCJ9njcFjqc1AqSQ2QIKycwdTxOP/zHsAWj0xN3rw1ApevA8o+8VAD4R6hw==", 766 | "optional": true, 767 | "requires": { 768 | "arrify": "^1.0.1", 769 | "extend": "^3.0.1", 770 | "is": "^3.2.1", 771 | "split-array-stream": "^2.0.0", 772 | "stream-events": "^1.0.4" 773 | } 774 | }, 775 | "@google-cloud/projectify": { 776 | "version": "0.3.2", 777 | "resolved": "https://registry.npmjs.org/@google-cloud/projectify/-/projectify-0.3.2.tgz", 778 | "integrity": "sha512-t1bs5gE105IpgikX7zPCJZzVyXM5xZ/1kJomUPim2E2pNp4OUUFNyvKm/T2aM6GBP2F30o8abCD+/wbOhHWYYA==", 779 | "optional": true 780 | }, 781 | "@google-cloud/promisify": { 782 | "version": "0.3.1", 783 | "resolved": "https://registry.npmjs.org/@google-cloud/promisify/-/promisify-0.3.1.tgz", 784 | "integrity": "sha512-QzB0/IMvB0eFxFK7Eqh+bfC8NLv3E9ScjWQrPOk6GgfNroxcVITdTlT8NRsRrcp5+QQJVPLkRqKG0PUdaWXmHw==", 785 | "optional": true 786 | }, 787 | "@google-cloud/storage": { 788 | "version": "2.4.2", 789 | "resolved": "https://registry.npmjs.org/@google-cloud/storage/-/storage-2.4.2.tgz", 790 | "integrity": "sha512-G4rlt5h2oypPYU2ZtmF3N0FpE47aRvsxp8NmZEdlScd5LgjDAu5Ha01hMOA/ZHBVsUlOGFfa+TxU5Ei/56+0Gg==", 791 | "optional": true, 792 | "requires": { 793 | "@google-cloud/common": "^0.31.0", 794 | "@google-cloud/paginator": "^0.1.0", 795 | "@google-cloud/promisify": "^0.3.0", 796 | "arrify": "^1.0.0", 797 | "async": "^2.0.1", 798 | "compressible": "^2.0.12", 799 | "concat-stream": "^2.0.0", 800 | "duplexify": "^3.5.0", 801 | "extend": "^3.0.0", 802 | "gcs-resumable-upload": "^0.14.1", 803 | "hash-stream-validation": "^0.2.1", 804 | "mime": "^2.2.0", 805 | "mime-types": "^2.0.8", 806 | "once": "^1.3.1", 807 | "pumpify": "^1.5.1", 808 | "snakeize": "^0.1.0", 809 | "stream-events": "^1.0.1", 810 | "teeny-request": "^3.11.3", 811 | "through2": "^3.0.0", 812 | "xdg-basedir": "^3.0.0" 813 | } 814 | }, 815 | "@grpc/grpc-js": { 816 | "version": "0.3.5", 817 | "resolved": "https://registry.npmjs.org/@grpc/grpc-js/-/grpc-js-0.3.5.tgz", 818 | "integrity": "sha512-LAzNgWYr5FHIkn1XPVTOO5qt6an6sBz0dPSKGOjoBwm6eUgHCVGvyxc72DGXgRHwT8hBfT1VwBmhwGHwfdtjeA==", 819 | "optional": true, 820 | "requires": { 821 | "semver": "^5.5.0" 822 | } 823 | }, 824 | "@grpc/proto-loader": { 825 | "version": "0.4.0", 826 | "resolved": "https://registry.npmjs.org/@grpc/proto-loader/-/proto-loader-0.4.0.tgz", 827 | "integrity": "sha512-Jm6o+75uWT7E6+lt8edg4J1F/9+BedOjaMgwE14pxS/AO43/0ZqK+rCLVVrXLoExwSAZvgvOD2B0ivy3Spsspw==", 828 | "optional": true, 829 | "requires": { 830 | "lodash.camelcase": "^4.3.0", 831 | "protobufjs": "^6.8.6" 832 | } 833 | }, 834 | "@protobufjs/aspromise": { 835 | "version": "1.1.2", 836 | "resolved": "https://registry.npmjs.org/@protobufjs/aspromise/-/aspromise-1.1.2.tgz", 837 | "integrity": "sha1-m4sMxmPWaafY9vXQiToU00jzD78=", 838 | "optional": true 839 | }, 840 | "@protobufjs/base64": { 841 | "version": "1.1.2", 842 | "resolved": "https://registry.npmjs.org/@protobufjs/base64/-/base64-1.1.2.tgz", 843 | "integrity": "sha512-AZkcAA5vnN/v4PDqKyMR5lx7hZttPDgClv83E//FMNhR2TMcLUhfRUBHCmSl0oi9zMgDDqRUJkSxO3wm85+XLg==", 844 | "optional": true 845 | }, 846 | "@protobufjs/codegen": { 847 | "version": "2.0.4", 848 | "resolved": "https://registry.npmjs.org/@protobufjs/codegen/-/codegen-2.0.4.tgz", 849 | "integrity": "sha512-YyFaikqM5sH0ziFZCN3xDC7zeGaB/d0IUb9CATugHWbd1FRFwWwt4ld4OYMPWu5a3Xe01mGAULCdqhMlPl29Jg==", 850 | "optional": true 851 | }, 852 | "@protobufjs/eventemitter": { 853 | "version": "1.1.0", 854 | "resolved": "https://registry.npmjs.org/@protobufjs/eventemitter/-/eventemitter-1.1.0.tgz", 855 | "integrity": "sha1-NVy8mLr61ZePntCV85diHx0Ga3A=", 856 | "optional": true 857 | }, 858 | "@protobufjs/fetch": { 859 | "version": "1.1.0", 860 | "resolved": "https://registry.npmjs.org/@protobufjs/fetch/-/fetch-1.1.0.tgz", 861 | "integrity": "sha1-upn7WYYUr2VwDBYZ/wbUVLDYTEU=", 862 | "optional": true, 863 | "requires": { 864 | "@protobufjs/aspromise": "^1.1.1", 865 | "@protobufjs/inquire": "^1.1.0" 866 | } 867 | }, 868 | "@protobufjs/float": { 869 | "version": "1.0.2", 870 | "resolved": "https://registry.npmjs.org/@protobufjs/float/-/float-1.0.2.tgz", 871 | "integrity": "sha1-Xp4avctz/Ap8uLKR33jIy9l7h9E=", 872 | "optional": true 873 | }, 874 | "@protobufjs/inquire": { 875 | "version": "1.1.0", 876 | "resolved": "https://registry.npmjs.org/@protobufjs/inquire/-/inquire-1.1.0.tgz", 877 | "integrity": "sha1-/yAOPnzyQp4tyvwRQIKOjMY48Ik=", 878 | "optional": true 879 | }, 880 | "@protobufjs/path": { 881 | "version": "1.1.2", 882 | "resolved": "https://registry.npmjs.org/@protobufjs/path/-/path-1.1.2.tgz", 883 | "integrity": "sha1-bMKyDFya1q0NzP0hynZz2Nf79o0=", 884 | "optional": true 885 | }, 886 | "@protobufjs/pool": { 887 | "version": "1.1.0", 888 | "resolved": "https://registry.npmjs.org/@protobufjs/pool/-/pool-1.1.0.tgz", 889 | "integrity": "sha1-Cf0V8tbTq/qbZbw2ZQbWrXhG/1Q=", 890 | "optional": true 891 | }, 892 | "@protobufjs/utf8": { 893 | "version": "1.1.0", 894 | "resolved": "https://registry.npmjs.org/@protobufjs/utf8/-/utf8-1.1.0.tgz", 895 | "integrity": "sha1-p3c2C1s5oaLlEG+OhY8v0tBgxXA=", 896 | "optional": true 897 | }, 898 | "@types/body-parser": { 899 | "version": "1.17.0", 900 | "resolved": "https://registry.npmjs.org/@types/body-parser/-/body-parser-1.17.0.tgz", 901 | "integrity": "sha512-a2+YeUjPkztKJu5aIF2yArYFQQp8d51wZ7DavSHjFuY1mqVgidGyzEQ41JIVNy82fXj8yPgy2vJmfIywgESW6w==", 902 | "requires": { 903 | "@types/connect": "*", 904 | "@types/node": "*" 905 | } 906 | }, 907 | "@types/bytebuffer": { 908 | "version": "5.0.40", 909 | "resolved": "https://registry.npmjs.org/@types/bytebuffer/-/bytebuffer-5.0.40.tgz", 910 | "integrity": "sha512-h48dyzZrPMz25K6Q4+NCwWaxwXany2FhQg/ErOcdZS1ZpsaDnDMZg8JYLMTGz7uvXKrcKGJUZJlZObyfgdaN9g==", 911 | "requires": { 912 | "@types/long": "*", 913 | "@types/node": "*" 914 | } 915 | }, 916 | "@types/caseless": { 917 | "version": "0.12.1", 918 | "resolved": "https://registry.npmjs.org/@types/caseless/-/caseless-0.12.1.tgz", 919 | "integrity": "sha512-FhlMa34NHp9K5MY1Uz8yb+ZvuX0pnvn3jScRSNAb75KHGB8d3rEU6hqMs3Z2vjuytcMfRg6c5CHMc3wtYyD2/A==", 920 | "optional": true 921 | }, 922 | "@types/connect": { 923 | "version": "3.4.32", 924 | "resolved": "https://registry.npmjs.org/@types/connect/-/connect-3.4.32.tgz", 925 | "integrity": "sha512-4r8qa0quOvh7lGD0pre62CAb1oni1OO6ecJLGCezTmhQ8Fz50Arx9RUszryR8KlgK6avuSXvviL6yWyViQABOg==", 926 | "requires": { 927 | "@types/node": "*" 928 | } 929 | }, 930 | "@types/cors": { 931 | "version": "2.8.4", 932 | "resolved": "https://registry.npmjs.org/@types/cors/-/cors-2.8.4.tgz", 933 | "integrity": "sha512-ipZjBVsm2tF/n8qFGOuGBkUij9X9ZswVi9G3bx/6dz7POpVa6gVHcj1wsX/LVEn9MMF41fxK/PnZPPoTD1UFPw==", 934 | "requires": { 935 | "@types/express": "*" 936 | } 937 | }, 938 | "@types/duplexify": { 939 | "version": "3.6.0", 940 | "resolved": "https://registry.npmjs.org/@types/duplexify/-/duplexify-3.6.0.tgz", 941 | "integrity": "sha512-5zOA53RUlzN74bvrSGwjudssD9F3a797sDZQkiYpUOxW+WHaXTCPz4/d5Dgi6FKnOqZ2CpaTo0DhgIfsXAOE/A==", 942 | "optional": true, 943 | "requires": { 944 | "@types/node": "*" 945 | } 946 | }, 947 | "@types/express": { 948 | "version": "4.16.1", 949 | "resolved": "https://registry.npmjs.org/@types/express/-/express-4.16.1.tgz", 950 | "integrity": "sha512-V0clmJow23WeyblmACoxbHBu2JKlE5TiIme6Lem14FnPW9gsttyHtk6wq7njcdIWH1njAaFgR8gW09lgY98gQg==", 951 | "requires": { 952 | "@types/body-parser": "*", 953 | "@types/express-serve-static-core": "*", 954 | "@types/serve-static": "*" 955 | } 956 | }, 957 | "@types/express-serve-static-core": { 958 | "version": "4.16.1", 959 | "resolved": "https://registry.npmjs.org/@types/express-serve-static-core/-/express-serve-static-core-4.16.1.tgz", 960 | "integrity": "sha512-QgbIMRU1EVRry5cIu1ORCQP4flSYqLM1lS5LYyGWfKnFT3E58f0gKto7BR13clBFVrVZ0G0rbLZ1hUpSkgQQOA==", 961 | "requires": { 962 | "@types/node": "*", 963 | "@types/range-parser": "*" 964 | } 965 | }, 966 | "@types/form-data": { 967 | "version": "2.2.1", 968 | "resolved": "https://registry.npmjs.org/@types/form-data/-/form-data-2.2.1.tgz", 969 | "integrity": "sha512-JAMFhOaHIciYVh8fb5/83nmuO/AHwmto+Hq7a9y8FzLDcC1KCU344XDOMEmahnrTFlHjgh4L0WJFczNIX2GxnQ==", 970 | "optional": true, 971 | "requires": { 972 | "@types/node": "*" 973 | } 974 | }, 975 | "@types/jsonwebtoken": { 976 | "version": "7.2.8", 977 | "resolved": "https://registry.npmjs.org/@types/jsonwebtoken/-/jsonwebtoken-7.2.8.tgz", 978 | "integrity": "sha512-XENN3YzEB8D6TiUww0O8SRznzy1v+77lH7UmuN54xq/IHIsyWjWOzZuFFTtoiRuaE782uAoRwBe/wwow+vQXZw==", 979 | "requires": { 980 | "@types/node": "*" 981 | } 982 | }, 983 | "@types/lodash": { 984 | "version": "4.14.121", 985 | "resolved": "https://registry.npmjs.org/@types/lodash/-/lodash-4.14.121.tgz", 986 | "integrity": "sha512-ORj7IBWj13iYufXt/VXrCNMbUuCTJfhzme5kx9U/UtcIPdJYuvPDUAlHlbNhz/8lKCLy9XGIZnGrqXOtQbPGoQ==" 987 | }, 988 | "@types/long": { 989 | "version": "4.0.0", 990 | "resolved": "https://registry.npmjs.org/@types/long/-/long-4.0.0.tgz", 991 | "integrity": "sha512-1w52Nyx4Gq47uuu0EVcsHBxZFJgurQ+rTKS3qMHxR1GY2T8c2AJYd6vZoZ9q1rupaDjU0yT+Jc2XTyXkjeMA+Q==" 992 | }, 993 | "@types/mime": { 994 | "version": "2.0.1", 995 | "resolved": "https://registry.npmjs.org/@types/mime/-/mime-2.0.1.tgz", 996 | "integrity": "sha512-FwI9gX75FgVBJ7ywgnq/P7tw+/o1GUbtP0KzbtusLigAOgIgNISRK0ZPl4qertvXSIE8YbsVJueQ90cDt9YYyw==" 997 | }, 998 | "@types/node": { 999 | "version": "8.10.40", 1000 | "resolved": "https://registry.npmjs.org/@types/node/-/node-8.10.40.tgz", 1001 | "integrity": "sha512-RRSjdwz63kS4u7edIwJUn8NqKLLQ6LyqF/X4+4jp38MBT3Vwetewi2N4dgJEshLbDwNgOJXNYoOwzVZUSSLhkQ==" 1002 | }, 1003 | "@types/range-parser": { 1004 | "version": "1.2.3", 1005 | "resolved": "https://registry.npmjs.org/@types/range-parser/-/range-parser-1.2.3.tgz", 1006 | "integrity": "sha512-ewFXqrQHlFsgc09MK5jP5iR7vumV/BYayNC6PgJO2LPe8vrnNFyjQjSppfEngITi0qvfKtzFvgKymGheFM9UOA==" 1007 | }, 1008 | "@types/request": { 1009 | "version": "2.48.1", 1010 | "resolved": "https://registry.npmjs.org/@types/request/-/request-2.48.1.tgz", 1011 | "integrity": "sha512-ZgEZ1TiD+KGA9LiAAPPJL68Id2UWfeSO62ijSXZjFJArVV+2pKcsVHmrcu+1oiE3q6eDGiFiSolRc4JHoerBBg==", 1012 | "optional": true, 1013 | "requires": { 1014 | "@types/caseless": "*", 1015 | "@types/form-data": "*", 1016 | "@types/node": "*", 1017 | "@types/tough-cookie": "*" 1018 | } 1019 | }, 1020 | "@types/serve-static": { 1021 | "version": "1.13.2", 1022 | "resolved": "https://registry.npmjs.org/@types/serve-static/-/serve-static-1.13.2.tgz", 1023 | "integrity": "sha512-/BZ4QRLpH/bNYgZgwhKEh+5AsboDBcUdlBYgzoLX0fpj3Y2gp6EApyOlM3bK53wQS/OE1SrdSYBAbux2D1528Q==", 1024 | "requires": { 1025 | "@types/express-serve-static-core": "*", 1026 | "@types/mime": "*" 1027 | } 1028 | }, 1029 | "@types/tough-cookie": { 1030 | "version": "2.3.5", 1031 | "resolved": "https://registry.npmjs.org/@types/tough-cookie/-/tough-cookie-2.3.5.tgz", 1032 | "integrity": "sha512-SCcK7mvGi3+ZNz833RRjFIxrn4gI1PPR3NtuIS+6vMkvmsGjosqTJwRt5bAEFLRz+wtJMWv8+uOnZf2hi2QXTg==", 1033 | "optional": true 1034 | }, 1035 | "abort-controller": { 1036 | "version": "2.0.2", 1037 | "resolved": "https://registry.npmjs.org/abort-controller/-/abort-controller-2.0.2.tgz", 1038 | "integrity": "sha512-JXEYGxxMwiNl9EUdLysK0K0DwB7ENw6KeeaLHgofijTfJYPB/vOer3Mb+IcP913dCfWiQsd05MmVNl0H5PanrQ==", 1039 | "optional": true, 1040 | "requires": { 1041 | "event-target-shim": "^5.0.0" 1042 | } 1043 | }, 1044 | "accepts": { 1045 | "version": "1.3.5", 1046 | "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.5.tgz", 1047 | "integrity": "sha1-63d99gEXI6OxTopywIBcjoZ0a9I=", 1048 | "requires": { 1049 | "mime-types": "~2.1.18", 1050 | "negotiator": "0.6.1" 1051 | } 1052 | }, 1053 | "agent-base": { 1054 | "version": "4.2.1", 1055 | "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-4.2.1.tgz", 1056 | "integrity": "sha512-JVwXMr9nHYTUXsBFKUqhJwvlcYU/blreOEUkhNR2eXZIvwd+c+o5V4MgDPKWnMS/56awN3TRzIP+KoPn+roQtg==", 1057 | "optional": true, 1058 | "requires": { 1059 | "es6-promisify": "^5.0.0" 1060 | } 1061 | }, 1062 | "ajv": { 1063 | "version": "6.9.1", 1064 | "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.9.1.tgz", 1065 | "integrity": "sha512-XDN92U311aINL77ieWHmqCcNlwjoP5cHXDxIxbf2MaPYuCXOHS7gHH8jktxeK5omgd52XbSTX6a4Piwd1pQmzA==", 1066 | "optional": true, 1067 | "requires": { 1068 | "fast-deep-equal": "^2.0.1", 1069 | "fast-json-stable-stringify": "^2.0.0", 1070 | "json-schema-traverse": "^0.4.1", 1071 | "uri-js": "^4.2.2" 1072 | } 1073 | }, 1074 | "ansi-regex": { 1075 | "version": "2.1.1", 1076 | "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", 1077 | "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=", 1078 | "optional": true 1079 | }, 1080 | "array-flatten": { 1081 | "version": "1.1.1", 1082 | "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz", 1083 | "integrity": "sha1-ml9pkFGx5wczKPKgCJaLZOopVdI=" 1084 | }, 1085 | "arrify": { 1086 | "version": "1.0.1", 1087 | "resolved": "https://registry.npmjs.org/arrify/-/arrify-1.0.1.tgz", 1088 | "integrity": "sha1-iYUI2iIm84DfkEcoRWhJwVAaSw0=", 1089 | "optional": true 1090 | }, 1091 | "ascli": { 1092 | "version": "1.0.1", 1093 | "resolved": "https://registry.npmjs.org/ascli/-/ascli-1.0.1.tgz", 1094 | "integrity": "sha1-vPpZdKYvGOgcq660lzKrSoj5Brw=", 1095 | "requires": { 1096 | "colour": "~0.7.1", 1097 | "optjs": "~3.2.2" 1098 | } 1099 | }, 1100 | "asn1": { 1101 | "version": "0.2.4", 1102 | "resolved": "https://registry.npmjs.org/asn1/-/asn1-0.2.4.tgz", 1103 | "integrity": "sha512-jxwzQpLQjSmWXgwaCZE9Nz+glAG01yF1QnWgbhGwHI5A6FRIEY6IVqtHhIepHqI7/kyEyQEagBC5mBEFlIYvdg==", 1104 | "optional": true, 1105 | "requires": { 1106 | "safer-buffer": "~2.1.0" 1107 | } 1108 | }, 1109 | "assert-plus": { 1110 | "version": "1.0.0", 1111 | "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", 1112 | "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=", 1113 | "optional": true 1114 | }, 1115 | "async": { 1116 | "version": "2.6.2", 1117 | "resolved": "https://registry.npmjs.org/async/-/async-2.6.2.tgz", 1118 | "integrity": "sha512-H1qVYh1MYhEEFLsP97cVKqCGo7KfCyTt6uEWqsTBr9SO84oK9Uwbyd/yCW+6rKJLHksBNUVWZDAjfS+Ccx0Bbg==", 1119 | "optional": true, 1120 | "requires": { 1121 | "lodash": "^4.17.11" 1122 | } 1123 | }, 1124 | "asynckit": { 1125 | "version": "0.4.0", 1126 | "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", 1127 | "integrity": "sha1-x57Zf380y48robyXkLzDZkdLS3k=", 1128 | "optional": true 1129 | }, 1130 | "aws-sign2": { 1131 | "version": "0.7.0", 1132 | "resolved": "https://registry.npmjs.org/aws-sign2/-/aws-sign2-0.7.0.tgz", 1133 | "integrity": "sha1-tG6JCTSpWR8tL2+G1+ap8bP+dqg=", 1134 | "optional": true 1135 | }, 1136 | "aws4": { 1137 | "version": "1.8.0", 1138 | "resolved": "https://registry.npmjs.org/aws4/-/aws4-1.8.0.tgz", 1139 | "integrity": "sha512-ReZxvNHIOv88FlT7rxcXIIC0fPt4KZqZbOlivyWtXLt8ESx84zd3kMC6iK5jVeS2qt+g7ftS7ye4fi06X5rtRQ==", 1140 | "optional": true 1141 | }, 1142 | "axios": { 1143 | "version": "0.18.1", 1144 | "resolved": "https://registry.npmjs.org/axios/-/axios-0.18.1.tgz", 1145 | "integrity": "sha512-0BfJq4NSfQXd+SkFdrvFbG7addhYSBA2mQwISr46pD6E5iqkWg02RAs8vyTT/j0RTnoYmeXauBuSv1qKwR179g==", 1146 | "requires": { 1147 | "follow-redirects": "1.5.10", 1148 | "is-buffer": "^2.0.2" 1149 | } 1150 | }, 1151 | "base64-js": { 1152 | "version": "1.3.0", 1153 | "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.3.0.tgz", 1154 | "integrity": "sha512-ccav/yGvoa80BQDljCxsmmQ3Xvx60/UpBIij5QN21W3wBi/hhIC9OoO+KLpu9IJTS9j4DRVJ3aDDF9cMSoa2lw==", 1155 | "optional": true 1156 | }, 1157 | "bcrypt-pbkdf": { 1158 | "version": "1.0.2", 1159 | "resolved": "https://registry.npmjs.org/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.2.tgz", 1160 | "integrity": "sha1-pDAdOJtqQ/m2f/PKEaP2Y342Dp4=", 1161 | "optional": true, 1162 | "requires": { 1163 | "tweetnacl": "^0.14.3" 1164 | } 1165 | }, 1166 | "bignumber.js": { 1167 | "version": "7.2.1", 1168 | "resolved": "https://registry.npmjs.org/bignumber.js/-/bignumber.js-7.2.1.tgz", 1169 | "integrity": "sha512-S4XzBk5sMB+Rcb/LNcpzXr57VRTxgAvaAEDAl1AwRx27j00hT84O6OkteE7u8UB3NuaaygCRrEpqox4uDOrbdQ==", 1170 | "optional": true 1171 | }, 1172 | "body-parser": { 1173 | "version": "1.18.3", 1174 | "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.18.3.tgz", 1175 | "integrity": "sha1-WykhmP/dVTs6DyDe0FkrlWlVyLQ=", 1176 | "requires": { 1177 | "bytes": "3.0.0", 1178 | "content-type": "~1.0.4", 1179 | "debug": "2.6.9", 1180 | "depd": "~1.1.2", 1181 | "http-errors": "~1.6.3", 1182 | "iconv-lite": "0.4.23", 1183 | "on-finished": "~2.3.0", 1184 | "qs": "6.5.2", 1185 | "raw-body": "2.3.3", 1186 | "type-is": "~1.6.16" 1187 | }, 1188 | "dependencies": { 1189 | "debug": { 1190 | "version": "2.6.9", 1191 | "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", 1192 | "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", 1193 | "requires": { 1194 | "ms": "2.0.0" 1195 | } 1196 | }, 1197 | "ms": { 1198 | "version": "2.0.0", 1199 | "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", 1200 | "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" 1201 | } 1202 | } 1203 | }, 1204 | "buffer-equal-constant-time": { 1205 | "version": "1.0.1", 1206 | "resolved": "https://registry.npmjs.org/buffer-equal-constant-time/-/buffer-equal-constant-time-1.0.1.tgz", 1207 | "integrity": "sha1-+OcRMvf/5uAaXJaXpMbz5I1cyBk=" 1208 | }, 1209 | "buffer-from": { 1210 | "version": "1.1.1", 1211 | "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.1.tgz", 1212 | "integrity": "sha512-MQcXEUbCKtEo7bhqEs6560Hyd4XaovZlO/k9V3hjVUF/zwW7KBVdSK4gIt/bzwS9MbR5qob+F5jusZsb0YQK2A==", 1213 | "optional": true 1214 | }, 1215 | "bun": { 1216 | "version": "0.0.12", 1217 | "resolved": "https://registry.npmjs.org/bun/-/bun-0.0.12.tgz", 1218 | "integrity": "sha512-Toms18J9DqnT+IfWkwxVTB2EaBprHvjlMWrTIsfX4xbu3ZBqVBwrERU0em1IgtRe04wT+wJxMlKHZok24hrcSQ==", 1219 | "optional": true, 1220 | "requires": { 1221 | "readable-stream": "~1.0.32" 1222 | } 1223 | }, 1224 | "bytebuffer": { 1225 | "version": "5.0.1", 1226 | "resolved": "https://registry.npmjs.org/bytebuffer/-/bytebuffer-5.0.1.tgz", 1227 | "integrity": "sha1-WC7qSxqHO20CCkjVjfhfC7ps/d0=", 1228 | "requires": { 1229 | "long": "~3" 1230 | }, 1231 | "dependencies": { 1232 | "long": { 1233 | "version": "3.2.0", 1234 | "resolved": "https://registry.npmjs.org/long/-/long-3.2.0.tgz", 1235 | "integrity": "sha1-2CG3E4yhy1gcFymQ7xTbIAtcR0s=", 1236 | "optional": true 1237 | } 1238 | } 1239 | }, 1240 | "bytes": { 1241 | "version": "3.0.0", 1242 | "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.0.0.tgz", 1243 | "integrity": "sha1-0ygVQE1olpn4Wk6k+odV3ROpYEg=" 1244 | }, 1245 | "camelcase": { 1246 | "version": "2.1.1", 1247 | "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-2.1.1.tgz", 1248 | "integrity": "sha1-fB0W1nmhu+WcoCys7PsBHiAfWh8=", 1249 | "optional": true 1250 | }, 1251 | "caseless": { 1252 | "version": "0.12.0", 1253 | "resolved": "https://registry.npmjs.org/caseless/-/caseless-0.12.0.tgz", 1254 | "integrity": "sha1-G2gcIf+EAzyCZUMJBolCDRhxUdw=", 1255 | "optional": true 1256 | }, 1257 | "cliui": { 1258 | "version": "3.2.0", 1259 | "resolved": "https://registry.npmjs.org/cliui/-/cliui-3.2.0.tgz", 1260 | "integrity": "sha1-EgYBU3qRbSmUD5NNo7SNWFo5IT0=", 1261 | "optional": true, 1262 | "requires": { 1263 | "string-width": "^1.0.1", 1264 | "strip-ansi": "^3.0.1", 1265 | "wrap-ansi": "^2.0.0" 1266 | } 1267 | }, 1268 | "code-point-at": { 1269 | "version": "1.1.0", 1270 | "resolved": "https://registry.npmjs.org/code-point-at/-/code-point-at-1.1.0.tgz", 1271 | "integrity": "sha1-DQcLTQQ6W+ozovGkDi7bPZpMz3c=", 1272 | "optional": true 1273 | }, 1274 | "colour": { 1275 | "version": "0.7.1", 1276 | "resolved": "https://registry.npmjs.org/colour/-/colour-0.7.1.tgz", 1277 | "integrity": "sha1-nLFpkX7F0SwHNtPoaFdG3xyt93g=", 1278 | "optional": true 1279 | }, 1280 | "combined-stream": { 1281 | "version": "1.0.7", 1282 | "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.7.tgz", 1283 | "integrity": "sha512-brWl9y6vOB1xYPZcpZde3N9zDByXTosAeMDo4p1wzo6UMOX4vumB+TP1RZ76sfE6Md68Q0NJSrE/gbezd4Ul+w==", 1284 | "optional": true, 1285 | "requires": { 1286 | "delayed-stream": "~1.0.0" 1287 | } 1288 | }, 1289 | "compressible": { 1290 | "version": "2.0.15", 1291 | "resolved": "https://registry.npmjs.org/compressible/-/compressible-2.0.15.tgz", 1292 | "integrity": "sha512-4aE67DL33dSW9gw4CI2H/yTxqHLNcxp0yS6jB+4h+wr3e43+1z7vm0HU9qXOH8j+qjKuL8+UtkOxYQSMq60Ylw==", 1293 | "optional": true, 1294 | "requires": { 1295 | "mime-db": ">= 1.36.0 < 2" 1296 | } 1297 | }, 1298 | "concat-stream": { 1299 | "version": "2.0.0", 1300 | "resolved": "https://registry.npmjs.org/concat-stream/-/concat-stream-2.0.0.tgz", 1301 | "integrity": "sha512-MWufYdFw53ccGjCA+Ol7XJYpAlW6/prSMzuPOTRnJGcGzuhLn4Scrz7qf6o8bROZ514ltazcIFJZevcfbo0x7A==", 1302 | "optional": true, 1303 | "requires": { 1304 | "buffer-from": "^1.0.0", 1305 | "inherits": "^2.0.3", 1306 | "readable-stream": "^3.0.2", 1307 | "typedarray": "^0.0.6" 1308 | }, 1309 | "dependencies": { 1310 | "readable-stream": { 1311 | "version": "3.1.1", 1312 | "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.1.1.tgz", 1313 | "integrity": "sha512-DkN66hPyqDhnIQ6Jcsvx9bFjhw214O4poMBcIMgPVpQvNy9a0e0Uhg5SqySyDKAmUlwt8LonTBz1ezOnM8pUdA==", 1314 | "optional": true, 1315 | "requires": { 1316 | "inherits": "^2.0.3", 1317 | "string_decoder": "^1.1.1", 1318 | "util-deprecate": "^1.0.1" 1319 | } 1320 | }, 1321 | "string_decoder": { 1322 | "version": "1.2.0", 1323 | "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.2.0.tgz", 1324 | "integrity": "sha512-6YqyX6ZWEYguAxgZzHGL7SsCeGx3V2TtOTqZz1xSTSWnqsbWwbptafNyvf/ACquZUXV3DANr5BDIwNYe1mN42w==", 1325 | "optional": true, 1326 | "requires": { 1327 | "safe-buffer": "~5.1.0" 1328 | } 1329 | } 1330 | } 1331 | }, 1332 | "configstore": { 1333 | "version": "4.0.0", 1334 | "resolved": "https://registry.npmjs.org/configstore/-/configstore-4.0.0.tgz", 1335 | "integrity": "sha512-CmquAXFBocrzaSM8mtGPMM/HiWmyIpr4CcJl/rgY2uCObZ/S7cKU0silxslqJejl+t/T9HS8E0PUNQD81JGUEQ==", 1336 | "optional": true, 1337 | "requires": { 1338 | "dot-prop": "^4.1.0", 1339 | "graceful-fs": "^4.1.2", 1340 | "make-dir": "^1.0.0", 1341 | "unique-string": "^1.0.0", 1342 | "write-file-atomic": "^2.0.0", 1343 | "xdg-basedir": "^3.0.0" 1344 | } 1345 | }, 1346 | "content-disposition": { 1347 | "version": "0.5.2", 1348 | "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.2.tgz", 1349 | "integrity": "sha1-DPaLud318r55YcOoUXjLhdunjLQ=" 1350 | }, 1351 | "content-type": { 1352 | "version": "1.0.4", 1353 | "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.4.tgz", 1354 | "integrity": "sha512-hIP3EEPs8tB9AT1L+NUqtwOAps4mk2Zob89MWXMHjHWg9milF/j4osnnQLXBCBFBk/tvIG/tUc9mOUJiPBhPXA==" 1355 | }, 1356 | "cookie": { 1357 | "version": "0.3.1", 1358 | "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.3.1.tgz", 1359 | "integrity": "sha1-5+Ch+e9DtMi6klxcWpboBtFoc7s=" 1360 | }, 1361 | "cookie-signature": { 1362 | "version": "1.0.6", 1363 | "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz", 1364 | "integrity": "sha1-4wOogrNCzD7oylE6eZmXNNqzriw=" 1365 | }, 1366 | "core-js": { 1367 | "version": "3.2.1", 1368 | "resolved": "https://registry.npmjs.org/core-js/-/core-js-3.2.1.tgz", 1369 | "integrity": "sha512-Qa5XSVefSVPRxy2XfUC13WbvqkxhkwB3ve+pgCQveNgYzbM/UxZeu1dcOX/xr4UmfUd+muuvsaxilQzCyUurMw==" 1370 | }, 1371 | "core-util-is": { 1372 | "version": "1.0.2", 1373 | "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", 1374 | "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=", 1375 | "optional": true 1376 | }, 1377 | "cors": { 1378 | "version": "2.8.5", 1379 | "resolved": "https://registry.npmjs.org/cors/-/cors-2.8.5.tgz", 1380 | "integrity": "sha512-KIHbLJqu73RGr/hnbrO9uBeixNGuvSQjul/jdFvS/KFSIH1hWVd1ng7zOHx+YrEfInLG7q4n6GHQ9cDtxv/P6g==", 1381 | "requires": { 1382 | "object-assign": "^4", 1383 | "vary": "^1" 1384 | } 1385 | }, 1386 | "crypto-random-string": { 1387 | "version": "1.0.0", 1388 | "resolved": "https://registry.npmjs.org/crypto-random-string/-/crypto-random-string-1.0.0.tgz", 1389 | "integrity": "sha1-ojD2T1aDEOFJgAmUB5DsmVRbyn4=", 1390 | "optional": true 1391 | }, 1392 | "dashdash": { 1393 | "version": "1.14.1", 1394 | "resolved": "https://registry.npmjs.org/dashdash/-/dashdash-1.14.1.tgz", 1395 | "integrity": "sha1-hTz6D3y+L+1d4gMmuN1YEDX24vA=", 1396 | "optional": true, 1397 | "requires": { 1398 | "assert-plus": "^1.0.0" 1399 | } 1400 | }, 1401 | "debug": { 1402 | "version": "3.2.6", 1403 | "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.6.tgz", 1404 | "integrity": "sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ==", 1405 | "optional": true, 1406 | "requires": { 1407 | "ms": "^2.1.1" 1408 | } 1409 | }, 1410 | "decamelize": { 1411 | "version": "1.2.0", 1412 | "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz", 1413 | "integrity": "sha1-9lNNFRSCabIDUue+4m9QH5oZEpA=", 1414 | "optional": true 1415 | }, 1416 | "deep-equal": { 1417 | "version": "1.0.1", 1418 | "resolved": "https://registry.npmjs.org/deep-equal/-/deep-equal-1.0.1.tgz", 1419 | "integrity": "sha1-9dJgKStmDghO/0zbyfCK0yR0SLU=", 1420 | "optional": true 1421 | }, 1422 | "delayed-stream": { 1423 | "version": "1.0.0", 1424 | "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", 1425 | "integrity": "sha1-3zrhmayt+31ECqrgsp4icrJOxhk=", 1426 | "optional": true 1427 | }, 1428 | "depd": { 1429 | "version": "1.1.2", 1430 | "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz", 1431 | "integrity": "sha1-m81S4UwJd2PnSbJ0xDRu0uVgtak=" 1432 | }, 1433 | "destroy": { 1434 | "version": "1.0.4", 1435 | "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.0.4.tgz", 1436 | "integrity": "sha1-l4hXRCxEdJ5CBmE+N5RiBYJqvYA=" 1437 | }, 1438 | "dom-storage": { 1439 | "version": "2.1.0", 1440 | "resolved": "https://registry.npmjs.org/dom-storage/-/dom-storage-2.1.0.tgz", 1441 | "integrity": "sha512-g6RpyWXzl0RR6OTElHKBl7nwnK87GUyZMYC7JWsB/IA73vpqK2K6LT39x4VepLxlSsWBFrPVLnsSR5Jyty0+2Q==" 1442 | }, 1443 | "dot-prop": { 1444 | "version": "4.2.0", 1445 | "resolved": "https://registry.npmjs.org/dot-prop/-/dot-prop-4.2.0.tgz", 1446 | "integrity": "sha512-tUMXrxlExSW6U2EXiiKGSBVdYgtV8qlHL+C10TsW4PURY/ic+eaysnSkwB4kA/mBlCyy/IKDJ+Lc3wbWeaXtuQ==", 1447 | "optional": true, 1448 | "requires": { 1449 | "is-obj": "^1.0.0" 1450 | } 1451 | }, 1452 | "duplexify": { 1453 | "version": "3.7.1", 1454 | "resolved": "https://registry.npmjs.org/duplexify/-/duplexify-3.7.1.tgz", 1455 | "integrity": "sha512-07z8uv2wMyS51kKhD1KsdXJg5WQ6t93RneqRxUHnskXVtlYYkLqM0gqStQZ3pj073g687jPCHrqNfCzawLYh5g==", 1456 | "optional": true, 1457 | "requires": { 1458 | "end-of-stream": "^1.0.0", 1459 | "inherits": "^2.0.1", 1460 | "readable-stream": "^2.0.0", 1461 | "stream-shift": "^1.0.0" 1462 | }, 1463 | "dependencies": { 1464 | "isarray": { 1465 | "version": "1.0.0", 1466 | "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", 1467 | "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", 1468 | "optional": true 1469 | }, 1470 | "readable-stream": { 1471 | "version": "2.3.6", 1472 | "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.6.tgz", 1473 | "integrity": "sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw==", 1474 | "optional": true, 1475 | "requires": { 1476 | "core-util-is": "~1.0.0", 1477 | "inherits": "~2.0.3", 1478 | "isarray": "~1.0.0", 1479 | "process-nextick-args": "~2.0.0", 1480 | "safe-buffer": "~5.1.1", 1481 | "string_decoder": "~1.1.1", 1482 | "util-deprecate": "~1.0.1" 1483 | } 1484 | }, 1485 | "string_decoder": { 1486 | "version": "1.1.1", 1487 | "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", 1488 | "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", 1489 | "optional": true, 1490 | "requires": { 1491 | "safe-buffer": "~5.1.0" 1492 | } 1493 | } 1494 | } 1495 | }, 1496 | "ecc-jsbn": { 1497 | "version": "0.1.2", 1498 | "resolved": "https://registry.npmjs.org/ecc-jsbn/-/ecc-jsbn-0.1.2.tgz", 1499 | "integrity": "sha1-OoOpBOVDUyh4dMVkt1SThoSamMk=", 1500 | "optional": true, 1501 | "requires": { 1502 | "jsbn": "~0.1.0", 1503 | "safer-buffer": "^2.1.0" 1504 | } 1505 | }, 1506 | "ecdsa-sig-formatter": { 1507 | "version": "1.0.10", 1508 | "resolved": "https://registry.npmjs.org/ecdsa-sig-formatter/-/ecdsa-sig-formatter-1.0.10.tgz", 1509 | "integrity": "sha1-HFlQAPBKiJffuFAAiSoPTDOvhsM=", 1510 | "requires": { 1511 | "safe-buffer": "^5.0.1" 1512 | } 1513 | }, 1514 | "ee-first": { 1515 | "version": "1.1.1", 1516 | "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", 1517 | "integrity": "sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0=" 1518 | }, 1519 | "encodeurl": { 1520 | "version": "1.0.2", 1521 | "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz", 1522 | "integrity": "sha1-rT/0yG7C0CkyL1oCw6mmBslbP1k=" 1523 | }, 1524 | "encoding": { 1525 | "version": "0.1.12", 1526 | "resolved": "https://registry.npmjs.org/encoding/-/encoding-0.1.12.tgz", 1527 | "integrity": "sha1-U4tm8+5izRq1HsMjgp0flIDHS+s=", 1528 | "requires": { 1529 | "iconv-lite": "~0.4.13" 1530 | } 1531 | }, 1532 | "end-of-stream": { 1533 | "version": "1.4.1", 1534 | "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.1.tgz", 1535 | "integrity": "sha512-1MkrZNvWTKCaigbn+W15elq2BB/L22nqrSY5DKlo3X6+vclJm8Bb5djXJBmEX6fS3+zCh/F4VBK5Z2KxJt4s2Q==", 1536 | "optional": true, 1537 | "requires": { 1538 | "once": "^1.4.0" 1539 | } 1540 | }, 1541 | "ent": { 1542 | "version": "2.2.0", 1543 | "resolved": "https://registry.npmjs.org/ent/-/ent-2.2.0.tgz", 1544 | "integrity": "sha1-6WQhkyWiHQX0RGai9obtbOX13R0=", 1545 | "optional": true 1546 | }, 1547 | "es6-promise": { 1548 | "version": "4.2.6", 1549 | "resolved": "https://registry.npmjs.org/es6-promise/-/es6-promise-4.2.6.tgz", 1550 | "integrity": "sha512-aRVgGdnmW2OiySVPUC9e6m+plolMAJKjZnQlCwNSuK5yQ0JN61DZSO1X1Ufd1foqWRAlig0rhduTCHe7sVtK5Q==", 1551 | "optional": true 1552 | }, 1553 | "es6-promisify": { 1554 | "version": "5.0.0", 1555 | "resolved": "https://registry.npmjs.org/es6-promisify/-/es6-promisify-5.0.0.tgz", 1556 | "integrity": "sha1-UQnWLz5W6pZ8S2NQWu8IKRyKUgM=", 1557 | "optional": true, 1558 | "requires": { 1559 | "es6-promise": "^4.0.3" 1560 | } 1561 | }, 1562 | "escape-html": { 1563 | "version": "1.0.3", 1564 | "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", 1565 | "integrity": "sha1-Aljq5NPQwJdN4cFpGI7wBR0dGYg=" 1566 | }, 1567 | "etag": { 1568 | "version": "1.8.1", 1569 | "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz", 1570 | "integrity": "sha1-Qa4u62XvpiJorr/qg6x9eSmbCIc=" 1571 | }, 1572 | "event-target-shim": { 1573 | "version": "5.0.0", 1574 | "resolved": "https://registry.npmjs.org/event-target-shim/-/event-target-shim-5.0.0.tgz", 1575 | "integrity": "sha512-vu4tlY5xqMEGj/rzuDHxfvm9Kk2562O5h58i8xwnkMkv/yqmBqBcDJt/vGBrOBbCKuVc5eV3ghYxAX9YUhyi0w==", 1576 | "optional": true 1577 | }, 1578 | "express": { 1579 | "version": "4.16.4", 1580 | "resolved": "https://registry.npmjs.org/express/-/express-4.16.4.tgz", 1581 | "integrity": "sha512-j12Uuyb4FMrd/qQAm6uCHAkPtO8FDTRJZBDd5D2KOL2eLaz1yUNdUB/NOIyq0iU4q4cFarsUCrnFDPBcnksuOg==", 1582 | "requires": { 1583 | "accepts": "~1.3.5", 1584 | "array-flatten": "1.1.1", 1585 | "body-parser": "1.18.3", 1586 | "content-disposition": "0.5.2", 1587 | "content-type": "~1.0.4", 1588 | "cookie": "0.3.1", 1589 | "cookie-signature": "1.0.6", 1590 | "debug": "2.6.9", 1591 | "depd": "~1.1.2", 1592 | "encodeurl": "~1.0.2", 1593 | "escape-html": "~1.0.3", 1594 | "etag": "~1.8.1", 1595 | "finalhandler": "1.1.1", 1596 | "fresh": "0.5.2", 1597 | "merge-descriptors": "1.0.1", 1598 | "methods": "~1.1.2", 1599 | "on-finished": "~2.3.0", 1600 | "parseurl": "~1.3.2", 1601 | "path-to-regexp": "0.1.7", 1602 | "proxy-addr": "~2.0.4", 1603 | "qs": "6.5.2", 1604 | "range-parser": "~1.2.0", 1605 | "safe-buffer": "5.1.2", 1606 | "send": "0.16.2", 1607 | "serve-static": "1.13.2", 1608 | "setprototypeof": "1.1.0", 1609 | "statuses": "~1.4.0", 1610 | "type-is": "~1.6.16", 1611 | "utils-merge": "1.0.1", 1612 | "vary": "~1.1.2" 1613 | }, 1614 | "dependencies": { 1615 | "debug": { 1616 | "version": "2.6.9", 1617 | "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", 1618 | "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", 1619 | "requires": { 1620 | "ms": "2.0.0" 1621 | } 1622 | }, 1623 | "ms": { 1624 | "version": "2.0.0", 1625 | "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", 1626 | "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" 1627 | } 1628 | } 1629 | }, 1630 | "extend": { 1631 | "version": "3.0.2", 1632 | "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz", 1633 | "integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==", 1634 | "optional": true 1635 | }, 1636 | "extsprintf": { 1637 | "version": "1.3.0", 1638 | "resolved": "https://registry.npmjs.org/extsprintf/-/extsprintf-1.3.0.tgz", 1639 | "integrity": "sha1-lpGEQOMEGnpBT4xS48V06zw+HgU=", 1640 | "optional": true 1641 | }, 1642 | "fast-deep-equal": { 1643 | "version": "2.0.1", 1644 | "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-2.0.1.tgz", 1645 | "integrity": "sha1-ewUhjd+WZ79/Nwv3/bLLFf3Qqkk=", 1646 | "optional": true 1647 | }, 1648 | "fast-json-stable-stringify": { 1649 | "version": "2.0.0", 1650 | "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.0.0.tgz", 1651 | "integrity": "sha1-1RQsDK7msRifh9OnYREGT4bIu/I=", 1652 | "optional": true 1653 | }, 1654 | "fast-text-encoding": { 1655 | "version": "1.0.0", 1656 | "resolved": "https://registry.npmjs.org/fast-text-encoding/-/fast-text-encoding-1.0.0.tgz", 1657 | "integrity": "sha512-R9bHCvweUxxwkDwhjav5vxpFvdPGlVngtqmx4pIZfSUhM/Q4NiIUHB456BAf+Q1Nwu3HEZYONtu+Rya+af4jiQ==", 1658 | "optional": true 1659 | }, 1660 | "faye-websocket": { 1661 | "version": "0.11.1", 1662 | "resolved": "https://registry.npmjs.org/faye-websocket/-/faye-websocket-0.11.1.tgz", 1663 | "integrity": "sha1-8O/hjE9W5PQK/H4Gxxn9XuYYjzg=", 1664 | "requires": { 1665 | "websocket-driver": ">=0.5.1" 1666 | } 1667 | }, 1668 | "finalhandler": { 1669 | "version": "1.1.1", 1670 | "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.1.1.tgz", 1671 | "integrity": "sha512-Y1GUDo39ez4aHAw7MysnUD5JzYX+WaIj8I57kO3aEPT1fFRL4sr7mjei97FgnwhAyyzRYmQZaTHb2+9uZ1dPtg==", 1672 | "requires": { 1673 | "debug": "2.6.9", 1674 | "encodeurl": "~1.0.2", 1675 | "escape-html": "~1.0.3", 1676 | "on-finished": "~2.3.0", 1677 | "parseurl": "~1.3.2", 1678 | "statuses": "~1.4.0", 1679 | "unpipe": "~1.0.0" 1680 | }, 1681 | "dependencies": { 1682 | "debug": { 1683 | "version": "2.6.9", 1684 | "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", 1685 | "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", 1686 | "requires": { 1687 | "ms": "2.0.0" 1688 | } 1689 | }, 1690 | "ms": { 1691 | "version": "2.0.0", 1692 | "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", 1693 | "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" 1694 | } 1695 | } 1696 | }, 1697 | "firebase": { 1698 | "version": "6.6.2", 1699 | "resolved": "https://registry.npmjs.org/firebase/-/firebase-6.6.2.tgz", 1700 | "integrity": "sha512-uL9uNbutC0T8GAxrGgOCC35Ven3QKJqzJozNoVIpBuiWrB9ifm9aKOxn44h6o5ouviax3LVvoiG2jLkLkdQq4A==", 1701 | "requires": { 1702 | "@firebase/app": "0.4.17", 1703 | "@firebase/app-types": "0.4.3", 1704 | "@firebase/auth": "0.12.0", 1705 | "@firebase/database": "0.5.4", 1706 | "@firebase/firestore": "1.5.3", 1707 | "@firebase/functions": "0.4.18", 1708 | "@firebase/installations": "0.2.7", 1709 | "@firebase/messaging": "0.4.11", 1710 | "@firebase/performance": "0.2.19", 1711 | "@firebase/polyfill": "0.3.22", 1712 | "@firebase/storage": "0.3.12", 1713 | "@firebase/util": "0.2.28" 1714 | }, 1715 | "dependencies": { 1716 | "@firebase/app": { 1717 | "version": "0.4.17", 1718 | "resolved": "https://registry.npmjs.org/@firebase/app/-/app-0.4.17.tgz", 1719 | "integrity": "sha512-YkCe10/KHnfJ5Lx79SCQ4ZJRlpnwe8Yns6Ntf7kltXq1hCQCUrKEU3zaOTPY90SBx36hYm47IaqkKwT/kBOK3A==", 1720 | "requires": { 1721 | "@firebase/app-types": "0.4.3", 1722 | "@firebase/logger": "0.1.25", 1723 | "@firebase/util": "0.2.28", 1724 | "dom-storage": "2.1.0", 1725 | "tslib": "1.10.0", 1726 | "xmlhttprequest": "1.8.0" 1727 | } 1728 | }, 1729 | "@firebase/app-types": { 1730 | "version": "0.4.3", 1731 | "resolved": "https://registry.npmjs.org/@firebase/app-types/-/app-types-0.4.3.tgz", 1732 | "integrity": "sha512-VU5c+ZjejvefLVH4cjiX3Hy1w9HYMv7TtZ1tF9ZmOqT4DSIU1a3VISWoo8///cGGffr5IirMO+Q/WZLI4p8VcA==" 1733 | }, 1734 | "@firebase/database": { 1735 | "version": "0.5.4", 1736 | "resolved": "https://registry.npmjs.org/@firebase/database/-/database-0.5.4.tgz", 1737 | "integrity": "sha512-Hz1Bi3fzIcNNocE4EhvvwoEQGurG2BGssWD3/6a2bzty+K1e57SLea2Ied8QYNBUU1zt/4McHfa3Y71EQIyn/w==", 1738 | "requires": { 1739 | "@firebase/database-types": "0.4.3", 1740 | "@firebase/logger": "0.1.25", 1741 | "@firebase/util": "0.2.28", 1742 | "faye-websocket": "0.11.3", 1743 | "tslib": "1.10.0" 1744 | } 1745 | }, 1746 | "@firebase/database-types": { 1747 | "version": "0.4.3", 1748 | "resolved": "https://registry.npmjs.org/@firebase/database-types/-/database-types-0.4.3.tgz", 1749 | "integrity": "sha512-21yCiJA2Tyt6dJYwWeB69MwoawBu5UWNtP6MAY0ugyRBHVdjAMHMYalPxCjZ46LAmhfim0+i8NXRadOFVS3hUA==", 1750 | "requires": { 1751 | "@firebase/app-types": "0.x" 1752 | } 1753 | }, 1754 | "@firebase/logger": { 1755 | "version": "0.1.25", 1756 | "resolved": "https://registry.npmjs.org/@firebase/logger/-/logger-0.1.25.tgz", 1757 | "integrity": "sha512-/lRhuepVcCCnQ2jcO5Hr08SYdmZDTQU9fdPdzg+qXJ9k/QnIrD2RbswXQcL6mmae3uPpX7fFXQAoScJ9pzp50w==" 1758 | }, 1759 | "@firebase/util": { 1760 | "version": "0.2.28", 1761 | "resolved": "https://registry.npmjs.org/@firebase/util/-/util-0.2.28.tgz", 1762 | "integrity": "sha512-ZQMAWtXj8y5kvB6izs0aTM/jG+WO8HpqhXA/EwD6LckJ+1P5LnAhaLZt1zR4HpuCE+jeP5I32Id5RJ/aifFs6A==", 1763 | "requires": { 1764 | "tslib": "1.10.0" 1765 | } 1766 | }, 1767 | "faye-websocket": { 1768 | "version": "0.11.3", 1769 | "resolved": "https://registry.npmjs.org/faye-websocket/-/faye-websocket-0.11.3.tgz", 1770 | "integrity": "sha512-D2y4bovYpzziGgbHYtGCMjlJM36vAl/y+xUyn1C+FVx8szd1E+86KwVw6XvYSzOP8iMpm1X0I4xJD+QtUb36OA==", 1771 | "requires": { 1772 | "websocket-driver": ">=0.5.1" 1773 | } 1774 | }, 1775 | "tslib": { 1776 | "version": "1.10.0", 1777 | "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.10.0.tgz", 1778 | "integrity": "sha512-qOebF53frne81cf0S9B41ByenJ3/IuH8yJKngAX35CmiZySA0khhkovshKK+jGCaMnVomla7gVlIcc3EvKPbTQ==" 1779 | } 1780 | } 1781 | }, 1782 | "firebase-admin": { 1783 | "version": "7.0.0", 1784 | "resolved": "https://registry.npmjs.org/firebase-admin/-/firebase-admin-7.0.0.tgz", 1785 | "integrity": "sha512-uYJVRuq8/b9PeJrgZwE2OIfr/MQAVhWxUpOa4AnWEEjzM7hzw2CQjY2iFzH6o0/7rTyAiGeFPQQQLBMg/xuQ6w==", 1786 | "requires": { 1787 | "@firebase/app": "^0.3.4", 1788 | "@firebase/database": "^0.3.6", 1789 | "@google-cloud/firestore": "^1.0.1", 1790 | "@google-cloud/storage": "^2.3.0", 1791 | "@types/node": "^8.0.53", 1792 | "jsonwebtoken": "8.1.0", 1793 | "node-forge": "0.7.4" 1794 | } 1795 | }, 1796 | "firebase-functions": { 1797 | "version": "2.2.0", 1798 | "resolved": "https://registry.npmjs.org/firebase-functions/-/firebase-functions-2.2.0.tgz", 1799 | "integrity": "sha512-83rJvXreTH98q1XEEUZ4G9nFZ0sUVaqkxPC+v25L9FuXsWgAFpW7G28K0MJ9DBPNo/RaeNNw0zvZVtDw11CEbQ==", 1800 | "requires": { 1801 | "@types/cors": "^2.8.1", 1802 | "@types/express": "^4.11.1", 1803 | "@types/jsonwebtoken": "^7.2.6", 1804 | "@types/lodash": "^4.14.34", 1805 | "cors": "^2.8.4", 1806 | "express": "^4.16.2", 1807 | "jsonwebtoken": "^8.2.1", 1808 | "lodash": "^4.6.1" 1809 | }, 1810 | "dependencies": { 1811 | "jsonwebtoken": { 1812 | "version": "8.5.0", 1813 | "resolved": "https://registry.npmjs.org/jsonwebtoken/-/jsonwebtoken-8.5.0.tgz", 1814 | "integrity": "sha512-IqEycp0znWHNA11TpYi77bVgyBO/pGESDh7Ajhas+u0ttkGkKYIIAjniL4Bw5+oVejVF+SYkaI7XKfwCCyeTuA==", 1815 | "requires": { 1816 | "jws": "^3.2.1", 1817 | "lodash.includes": "^4.3.0", 1818 | "lodash.isboolean": "^3.0.3", 1819 | "lodash.isinteger": "^4.0.4", 1820 | "lodash.isnumber": "^3.0.3", 1821 | "lodash.isplainobject": "^4.0.6", 1822 | "lodash.isstring": "^4.0.1", 1823 | "lodash.once": "^4.0.0", 1824 | "ms": "^2.1.1", 1825 | "semver": "^5.6.0" 1826 | } 1827 | } 1828 | } 1829 | }, 1830 | "follow-redirects": { 1831 | "version": "1.5.10", 1832 | "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.5.10.tgz", 1833 | "integrity": "sha512-0V5l4Cizzvqt5D44aTXbFZz+FtyXV1vrDN6qrelxtfYQKW0KO0W2T/hkE8xvGa/540LkZlkaUjO4ailYTFtHVQ==", 1834 | "requires": { 1835 | "debug": "=3.1.0" 1836 | }, 1837 | "dependencies": { 1838 | "debug": { 1839 | "version": "3.1.0", 1840 | "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", 1841 | "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", 1842 | "requires": { 1843 | "ms": "2.0.0" 1844 | } 1845 | }, 1846 | "ms": { 1847 | "version": "2.0.0", 1848 | "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", 1849 | "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" 1850 | } 1851 | } 1852 | }, 1853 | "forever-agent": { 1854 | "version": "0.6.1", 1855 | "resolved": "https://registry.npmjs.org/forever-agent/-/forever-agent-0.6.1.tgz", 1856 | "integrity": "sha1-+8cfDEGt6zf5bFd60e1C2P2sypE=", 1857 | "optional": true 1858 | }, 1859 | "form-data": { 1860 | "version": "2.3.3", 1861 | "resolved": "https://registry.npmjs.org/form-data/-/form-data-2.3.3.tgz", 1862 | "integrity": "sha512-1lLKB2Mu3aGP1Q/2eCOx0fNbRMe7XdwktwOruhfqqd0rIJWwN4Dh+E3hrPSlDCXnSR7UtZ1N38rVXm+6+MEhJQ==", 1863 | "optional": true, 1864 | "requires": { 1865 | "asynckit": "^0.4.0", 1866 | "combined-stream": "^1.0.6", 1867 | "mime-types": "^2.1.12" 1868 | } 1869 | }, 1870 | "forwarded": { 1871 | "version": "0.1.2", 1872 | "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.1.2.tgz", 1873 | "integrity": "sha1-mMI9qxF1ZXuMBXPozszZGw/xjIQ=" 1874 | }, 1875 | "fresh": { 1876 | "version": "0.5.2", 1877 | "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz", 1878 | "integrity": "sha1-PYyt2Q2XZWn6g1qx+OSyOhBWBac=" 1879 | }, 1880 | "functional-red-black-tree": { 1881 | "version": "1.0.1", 1882 | "resolved": "https://registry.npmjs.org/functional-red-black-tree/-/functional-red-black-tree-1.0.1.tgz", 1883 | "integrity": "sha1-GwqzvVU7Kg1jmdKcDj6gslIHgyc=", 1884 | "optional": true 1885 | }, 1886 | "gaxios": { 1887 | "version": "1.7.0", 1888 | "resolved": "https://registry.npmjs.org/gaxios/-/gaxios-1.7.0.tgz", 1889 | "integrity": "sha512-2SaZTtaEgnSMgRrBVnPA5O9Tc8xWfnL48fuxFL7zOHZwnam3HiNOkoosnRgnkNBZoEZrH1Aja3wMCrrDtOEqUw==", 1890 | "optional": true, 1891 | "requires": { 1892 | "abort-controller": "^2.0.2", 1893 | "extend": "^3.0.2", 1894 | "https-proxy-agent": "^2.2.1", 1895 | "node-fetch": "^2.2.0" 1896 | } 1897 | }, 1898 | "gcp-metadata": { 1899 | "version": "0.9.3", 1900 | "resolved": "https://registry.npmjs.org/gcp-metadata/-/gcp-metadata-0.9.3.tgz", 1901 | "integrity": "sha512-caV4S84xAjENtpezLCT/GILEAF5h/bC4cNqZFmt/tjTn8t+JBtTkQrgBrJu3857YdsnlM8rxX/PMcKGtE8hUlw==", 1902 | "optional": true, 1903 | "requires": { 1904 | "gaxios": "^1.0.2", 1905 | "json-bigint": "^0.3.0" 1906 | } 1907 | }, 1908 | "gcs-resumable-upload": { 1909 | "version": "0.14.1", 1910 | "resolved": "https://registry.npmjs.org/gcs-resumable-upload/-/gcs-resumable-upload-0.14.1.tgz", 1911 | "integrity": "sha512-vkIxLeVyW20DdcyhI8GvOkISV62y7+fKAdelUTn8F5en8AmPduqro5xz3VoHkj/RJ3PQmqNovYYaYPyPHwebzw==", 1912 | "optional": true, 1913 | "requires": { 1914 | "configstore": "^4.0.0", 1915 | "google-auth-library": "^3.0.0", 1916 | "pumpify": "^1.5.1", 1917 | "request": "^2.87.0", 1918 | "stream-events": "^1.0.4" 1919 | } 1920 | }, 1921 | "geofirestore": { 1922 | "version": "3.3.1", 1923 | "resolved": "https://registry.npmjs.org/geofirestore/-/geofirestore-3.3.1.tgz", 1924 | "integrity": "sha512-iExXDRXvtFi5fcM7yQI6VpSIt9b/bbsaKfUCGYSOObkF4EVONzaNM/OT3IZ1Ylrlvao7qBoardgMuN38I8ADOA==", 1925 | "requires": { 1926 | "@firebase/firestore-types": "x.x.x", 1927 | "@google-cloud/firestore": "x.x.x", 1928 | "@types/node": "x.x.x", 1929 | "firebase": "5.x.x || 6.x.x" 1930 | } 1931 | }, 1932 | "getpass": { 1933 | "version": "0.1.7", 1934 | "resolved": "https://registry.npmjs.org/getpass/-/getpass-0.1.7.tgz", 1935 | "integrity": "sha1-Xv+OPmhNVprkyysSgmBOi6YhSfo=", 1936 | "optional": true, 1937 | "requires": { 1938 | "assert-plus": "^1.0.0" 1939 | } 1940 | }, 1941 | "google-auth-library": { 1942 | "version": "3.1.0", 1943 | "resolved": "https://registry.npmjs.org/google-auth-library/-/google-auth-library-3.1.0.tgz", 1944 | "integrity": "sha512-EntjrOgSffw5EhZGoV8+ROPwEK/aQpoMZaULw3bKailEGdjaUI25PmmFc4AN6vG/Q24YEUiuLxtTXa1Usar5Eg==", 1945 | "optional": true, 1946 | "requires": { 1947 | "base64-js": "^1.3.0", 1948 | "fast-text-encoding": "^1.0.0", 1949 | "gaxios": "^1.2.1", 1950 | "gcp-metadata": "^0.9.3", 1951 | "gtoken": "^2.3.2", 1952 | "https-proxy-agent": "^2.2.1", 1953 | "jws": "^3.1.5", 1954 | "lru-cache": "^5.0.0", 1955 | "semver": "^5.5.0" 1956 | } 1957 | }, 1958 | "google-gax": { 1959 | "version": "0.24.0", 1960 | "resolved": "https://registry.npmjs.org/google-gax/-/google-gax-0.24.0.tgz", 1961 | "integrity": "sha512-x+eeMgHlAFXScvuw3gm0r/DkN8519QtdST8U0KMt934dwfsavF2iFvOhnXaNvEL99CXtDImOON+NqkTfIzq/FQ==", 1962 | "optional": true, 1963 | "requires": { 1964 | "@grpc/grpc-js": "^0.3.0", 1965 | "@grpc/proto-loader": "^0.4.0", 1966 | "duplexify": "^3.6.0", 1967 | "google-auth-library": "^3.0.0", 1968 | "google-proto-files": "^0.18.0", 1969 | "grpc": "^1.16.0", 1970 | "is-stream-ended": "^0.1.4", 1971 | "lodash.at": "^4.6.0", 1972 | "lodash.has": "^4.5.2", 1973 | "protobufjs": "^6.8.8", 1974 | "retry-request": "^4.0.0", 1975 | "semver": "^5.5.1", 1976 | "walkdir": "0.0.12" 1977 | } 1978 | }, 1979 | "google-p12-pem": { 1980 | "version": "1.0.3", 1981 | "resolved": "https://registry.npmjs.org/google-p12-pem/-/google-p12-pem-1.0.3.tgz", 1982 | "integrity": "sha512-KGnAiMMWaJp4j4tYVvAjfP3wCKZRLv9M1Nir2wRRNWUYO7j1aX8O9Qgz+a8/EQ5rAvuo4SIu79n6SIdkNl7Msg==", 1983 | "optional": true, 1984 | "requires": { 1985 | "node-forge": "^0.7.5", 1986 | "pify": "^4.0.0" 1987 | }, 1988 | "dependencies": { 1989 | "node-forge": { 1990 | "version": "0.7.6", 1991 | "resolved": "https://registry.npmjs.org/node-forge/-/node-forge-0.7.6.tgz", 1992 | "integrity": "sha512-sol30LUpz1jQFBjOKwbjxijiE3b6pjd74YwfD0fJOKPjF+fONKb2Yg8rYgS6+bK6VDl+/wfr4IYpC7jDzLUIfw==", 1993 | "optional": true 1994 | } 1995 | } 1996 | }, 1997 | "google-proto-files": { 1998 | "version": "0.18.0", 1999 | "resolved": "https://registry.npmjs.org/google-proto-files/-/google-proto-files-0.18.0.tgz", 2000 | "integrity": "sha512-blJ5rA3TWEiZIw7Qm0GHNERDdZeezDj46wE4O5uGnOWpZI/STQjeI6rPbqiwjmxzG+b592Hrp2+GKYfbmKR+Lg==", 2001 | "optional": true, 2002 | "requires": { 2003 | "protobufjs": "^6.8.0", 2004 | "walkdir": "0.0.12" 2005 | } 2006 | }, 2007 | "graceful-fs": { 2008 | "version": "4.1.15", 2009 | "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.1.15.tgz", 2010 | "integrity": "sha512-6uHUhOPEBgQ24HM+r6b/QwWfZq+yiFcipKFrOFiBEnWdy5sdzYoi+pJeQaPI5qOLRFqWmAXUPQNsielzdLoecA==", 2011 | "optional": true 2012 | }, 2013 | "grpc": { 2014 | "version": "1.18.0", 2015 | "resolved": "https://registry.npmjs.org/grpc/-/grpc-1.18.0.tgz", 2016 | "integrity": "sha512-M0K67Zhv2ZzCjrTbQvjWgYFPB929L+qAVnbNgXepbfO5kJxUYc30dP8m8vb+o8QdahLHAeYfIqRoIzZRcCB98Q==", 2017 | "optional": true, 2018 | "requires": { 2019 | "lodash.camelcase": "^4.3.0", 2020 | "lodash.clone": "^4.5.0", 2021 | "nan": "^2.0.0", 2022 | "node-pre-gyp": "^0.12.0", 2023 | "protobufjs": "^5.0.3" 2024 | }, 2025 | "dependencies": { 2026 | "abbrev": { 2027 | "version": "1.1.1", 2028 | "bundled": true, 2029 | "optional": true 2030 | }, 2031 | "ansi-regex": { 2032 | "version": "2.1.1", 2033 | "bundled": true, 2034 | "optional": true 2035 | }, 2036 | "aproba": { 2037 | "version": "1.2.0", 2038 | "bundled": true, 2039 | "optional": true 2040 | }, 2041 | "are-we-there-yet": { 2042 | "version": "1.1.5", 2043 | "bundled": true, 2044 | "optional": true, 2045 | "requires": { 2046 | "delegates": "^1.0.0", 2047 | "readable-stream": "^2.0.6" 2048 | } 2049 | }, 2050 | "balanced-match": { 2051 | "version": "1.0.0", 2052 | "bundled": true, 2053 | "optional": true 2054 | }, 2055 | "brace-expansion": { 2056 | "version": "1.1.11", 2057 | "bundled": true, 2058 | "optional": true, 2059 | "requires": { 2060 | "balanced-match": "^1.0.0", 2061 | "concat-map": "0.0.1" 2062 | } 2063 | }, 2064 | "chownr": { 2065 | "version": "1.1.1", 2066 | "bundled": true, 2067 | "optional": true 2068 | }, 2069 | "code-point-at": { 2070 | "version": "1.1.0", 2071 | "bundled": true, 2072 | "optional": true 2073 | }, 2074 | "concat-map": { 2075 | "version": "0.0.1", 2076 | "bundled": true, 2077 | "optional": true 2078 | }, 2079 | "console-control-strings": { 2080 | "version": "1.1.0", 2081 | "bundled": true, 2082 | "optional": true 2083 | }, 2084 | "core-util-is": { 2085 | "version": "1.0.2", 2086 | "bundled": true, 2087 | "optional": true 2088 | }, 2089 | "debug": { 2090 | "version": "2.6.9", 2091 | "bundled": true, 2092 | "optional": true, 2093 | "requires": { 2094 | "ms": "2.0.0" 2095 | } 2096 | }, 2097 | "deep-extend": { 2098 | "version": "0.6.0", 2099 | "bundled": true, 2100 | "optional": true 2101 | }, 2102 | "delegates": { 2103 | "version": "1.0.0", 2104 | "bundled": true, 2105 | "optional": true 2106 | }, 2107 | "detect-libc": { 2108 | "version": "1.0.3", 2109 | "bundled": true, 2110 | "optional": true 2111 | }, 2112 | "fs-minipass": { 2113 | "version": "1.2.5", 2114 | "bundled": true, 2115 | "optional": true, 2116 | "requires": { 2117 | "minipass": "^2.2.1" 2118 | } 2119 | }, 2120 | "fs.realpath": { 2121 | "version": "1.0.0", 2122 | "bundled": true, 2123 | "optional": true 2124 | }, 2125 | "gauge": { 2126 | "version": "2.7.4", 2127 | "bundled": true, 2128 | "optional": true, 2129 | "requires": { 2130 | "aproba": "^1.0.3", 2131 | "console-control-strings": "^1.0.0", 2132 | "has-unicode": "^2.0.0", 2133 | "object-assign": "^4.1.0", 2134 | "signal-exit": "^3.0.0", 2135 | "string-width": "^1.0.1", 2136 | "strip-ansi": "^3.0.1", 2137 | "wide-align": "^1.1.0" 2138 | } 2139 | }, 2140 | "glob": { 2141 | "version": "7.1.2", 2142 | "bundled": true, 2143 | "optional": true, 2144 | "requires": { 2145 | "fs.realpath": "^1.0.0", 2146 | "inflight": "^1.0.4", 2147 | "inherits": "2", 2148 | "minimatch": "^3.0.4", 2149 | "once": "^1.3.0", 2150 | "path-is-absolute": "^1.0.0" 2151 | } 2152 | }, 2153 | "has-unicode": { 2154 | "version": "2.0.1", 2155 | "bundled": true, 2156 | "optional": true 2157 | }, 2158 | "iconv-lite": { 2159 | "version": "0.4.23", 2160 | "bundled": true, 2161 | "optional": true, 2162 | "requires": { 2163 | "safer-buffer": ">= 2.1.2 < 3" 2164 | } 2165 | }, 2166 | "ignore-walk": { 2167 | "version": "3.0.1", 2168 | "bundled": true, 2169 | "optional": true, 2170 | "requires": { 2171 | "minimatch": "^3.0.4" 2172 | } 2173 | }, 2174 | "inflight": { 2175 | "version": "1.0.6", 2176 | "bundled": true, 2177 | "optional": true, 2178 | "requires": { 2179 | "once": "^1.3.0", 2180 | "wrappy": "1" 2181 | } 2182 | }, 2183 | "inherits": { 2184 | "version": "2.0.3", 2185 | "bundled": true, 2186 | "optional": true 2187 | }, 2188 | "ini": { 2189 | "version": "1.3.5", 2190 | "bundled": true, 2191 | "optional": true 2192 | }, 2193 | "is-fullwidth-code-point": { 2194 | "version": "1.0.0", 2195 | "bundled": true, 2196 | "optional": true, 2197 | "requires": { 2198 | "number-is-nan": "^1.0.0" 2199 | } 2200 | }, 2201 | "isarray": { 2202 | "version": "1.0.0", 2203 | "bundled": true, 2204 | "optional": true 2205 | }, 2206 | "minimatch": { 2207 | "version": "3.0.4", 2208 | "bundled": true, 2209 | "optional": true, 2210 | "requires": { 2211 | "brace-expansion": "^1.1.7" 2212 | } 2213 | }, 2214 | "minimist": { 2215 | "version": "1.2.0", 2216 | "bundled": true, 2217 | "optional": true 2218 | }, 2219 | "minipass": { 2220 | "version": "2.3.5", 2221 | "bundled": true, 2222 | "optional": true, 2223 | "requires": { 2224 | "safe-buffer": "^5.1.2", 2225 | "yallist": "^3.0.0" 2226 | } 2227 | }, 2228 | "minizlib": { 2229 | "version": "1.1.1", 2230 | "bundled": true, 2231 | "optional": true, 2232 | "requires": { 2233 | "minipass": "^2.2.1" 2234 | } 2235 | }, 2236 | "mkdirp": { 2237 | "version": "0.5.1", 2238 | "bundled": true, 2239 | "optional": true, 2240 | "requires": { 2241 | "minimist": "0.0.8" 2242 | }, 2243 | "dependencies": { 2244 | "minimist": { 2245 | "version": "0.0.8", 2246 | "bundled": true, 2247 | "optional": true 2248 | } 2249 | } 2250 | }, 2251 | "ms": { 2252 | "version": "2.0.0", 2253 | "bundled": true, 2254 | "optional": true 2255 | }, 2256 | "needle": { 2257 | "version": "2.2.4", 2258 | "bundled": true, 2259 | "optional": true, 2260 | "requires": { 2261 | "debug": "^2.1.2", 2262 | "iconv-lite": "^0.4.4", 2263 | "sax": "^1.2.4" 2264 | } 2265 | }, 2266 | "node-pre-gyp": { 2267 | "version": "0.12.0", 2268 | "bundled": true, 2269 | "optional": true, 2270 | "requires": { 2271 | "detect-libc": "^1.0.2", 2272 | "mkdirp": "^0.5.1", 2273 | "needle": "^2.2.1", 2274 | "nopt": "^4.0.1", 2275 | "npm-packlist": "^1.1.6", 2276 | "npmlog": "^4.0.2", 2277 | "rc": "^1.2.7", 2278 | "rimraf": "^2.6.1", 2279 | "semver": "^5.3.0", 2280 | "tar": "^4" 2281 | } 2282 | }, 2283 | "nopt": { 2284 | "version": "4.0.1", 2285 | "bundled": true, 2286 | "optional": true, 2287 | "requires": { 2288 | "abbrev": "1", 2289 | "osenv": "^0.1.4" 2290 | } 2291 | }, 2292 | "npm-bundled": { 2293 | "version": "1.0.5", 2294 | "bundled": true, 2295 | "optional": true 2296 | }, 2297 | "npm-packlist": { 2298 | "version": "1.1.12", 2299 | "bundled": true, 2300 | "optional": true, 2301 | "requires": { 2302 | "ignore-walk": "^3.0.1", 2303 | "npm-bundled": "^1.0.1" 2304 | } 2305 | }, 2306 | "npmlog": { 2307 | "version": "4.1.2", 2308 | "bundled": true, 2309 | "optional": true, 2310 | "requires": { 2311 | "are-we-there-yet": "~1.1.2", 2312 | "console-control-strings": "~1.1.0", 2313 | "gauge": "~2.7.3", 2314 | "set-blocking": "~2.0.0" 2315 | } 2316 | }, 2317 | "number-is-nan": { 2318 | "version": "1.0.1", 2319 | "bundled": true, 2320 | "optional": true 2321 | }, 2322 | "object-assign": { 2323 | "version": "4.1.1", 2324 | "bundled": true, 2325 | "optional": true 2326 | }, 2327 | "once": { 2328 | "version": "1.4.0", 2329 | "bundled": true, 2330 | "optional": true, 2331 | "requires": { 2332 | "wrappy": "1" 2333 | } 2334 | }, 2335 | "os-homedir": { 2336 | "version": "1.0.2", 2337 | "bundled": true, 2338 | "optional": true 2339 | }, 2340 | "os-tmpdir": { 2341 | "version": "1.0.2", 2342 | "bundled": true, 2343 | "optional": true 2344 | }, 2345 | "osenv": { 2346 | "version": "0.1.5", 2347 | "bundled": true, 2348 | "optional": true, 2349 | "requires": { 2350 | "os-homedir": "^1.0.0", 2351 | "os-tmpdir": "^1.0.0" 2352 | } 2353 | }, 2354 | "path-is-absolute": { 2355 | "version": "1.0.1", 2356 | "bundled": true, 2357 | "optional": true 2358 | }, 2359 | "process-nextick-args": { 2360 | "version": "2.0.0", 2361 | "bundled": true, 2362 | "optional": true 2363 | }, 2364 | "protobufjs": { 2365 | "version": "5.0.3", 2366 | "resolved": "https://registry.npmjs.org/protobufjs/-/protobufjs-5.0.3.tgz", 2367 | "integrity": "sha512-55Kcx1MhPZX0zTbVosMQEO5R6/rikNXd9b6RQK4KSPcrSIIwoXTtebIczUrXlwaSrbz4x8XUVThGPob1n8I4QA==", 2368 | "optional": true, 2369 | "requires": { 2370 | "ascli": "~1", 2371 | "bytebuffer": "~5", 2372 | "glob": "^7.0.5", 2373 | "yargs": "^3.10.0" 2374 | } 2375 | }, 2376 | "rc": { 2377 | "version": "1.2.8", 2378 | "bundled": true, 2379 | "optional": true, 2380 | "requires": { 2381 | "deep-extend": "^0.6.0", 2382 | "ini": "~1.3.0", 2383 | "minimist": "^1.2.0", 2384 | "strip-json-comments": "~2.0.1" 2385 | } 2386 | }, 2387 | "readable-stream": { 2388 | "version": "2.3.6", 2389 | "bundled": true, 2390 | "optional": true, 2391 | "requires": { 2392 | "core-util-is": "~1.0.0", 2393 | "inherits": "~2.0.3", 2394 | "isarray": "~1.0.0", 2395 | "process-nextick-args": "~2.0.0", 2396 | "safe-buffer": "~5.1.1", 2397 | "string_decoder": "~1.1.1", 2398 | "util-deprecate": "~1.0.1" 2399 | } 2400 | }, 2401 | "rimraf": { 2402 | "version": "2.6.2", 2403 | "bundled": true, 2404 | "optional": true, 2405 | "requires": { 2406 | "glob": "^7.0.5" 2407 | } 2408 | }, 2409 | "safe-buffer": { 2410 | "version": "5.1.2", 2411 | "bundled": true, 2412 | "optional": true 2413 | }, 2414 | "safer-buffer": { 2415 | "version": "2.1.2", 2416 | "bundled": true, 2417 | "optional": true 2418 | }, 2419 | "sax": { 2420 | "version": "1.2.4", 2421 | "bundled": true, 2422 | "optional": true 2423 | }, 2424 | "semver": { 2425 | "version": "5.6.0", 2426 | "bundled": true, 2427 | "optional": true 2428 | }, 2429 | "set-blocking": { 2430 | "version": "2.0.0", 2431 | "bundled": true, 2432 | "optional": true 2433 | }, 2434 | "signal-exit": { 2435 | "version": "3.0.2", 2436 | "bundled": true, 2437 | "optional": true 2438 | }, 2439 | "string-width": { 2440 | "version": "1.0.2", 2441 | "bundled": true, 2442 | "optional": true, 2443 | "requires": { 2444 | "code-point-at": "^1.0.0", 2445 | "is-fullwidth-code-point": "^1.0.0", 2446 | "strip-ansi": "^3.0.0" 2447 | } 2448 | }, 2449 | "string_decoder": { 2450 | "version": "1.1.1", 2451 | "bundled": true, 2452 | "optional": true, 2453 | "requires": { 2454 | "safe-buffer": "~5.1.0" 2455 | } 2456 | }, 2457 | "strip-ansi": { 2458 | "version": "3.0.1", 2459 | "bundled": true, 2460 | "optional": true, 2461 | "requires": { 2462 | "ansi-regex": "^2.0.0" 2463 | } 2464 | }, 2465 | "strip-json-comments": { 2466 | "version": "2.0.1", 2467 | "bundled": true, 2468 | "optional": true 2469 | }, 2470 | "tar": { 2471 | "version": "4.4.8", 2472 | "bundled": true, 2473 | "optional": true, 2474 | "requires": { 2475 | "chownr": "^1.1.1", 2476 | "fs-minipass": "^1.2.5", 2477 | "minipass": "^2.3.4", 2478 | "minizlib": "^1.1.1", 2479 | "mkdirp": "^0.5.0", 2480 | "safe-buffer": "^5.1.2", 2481 | "yallist": "^3.0.2" 2482 | } 2483 | }, 2484 | "util-deprecate": { 2485 | "version": "1.0.2", 2486 | "bundled": true, 2487 | "optional": true 2488 | }, 2489 | "wide-align": { 2490 | "version": "1.1.3", 2491 | "bundled": true, 2492 | "optional": true, 2493 | "requires": { 2494 | "string-width": "^1.0.2 || 2" 2495 | } 2496 | }, 2497 | "wrappy": { 2498 | "version": "1.0.2", 2499 | "bundled": true, 2500 | "optional": true 2501 | }, 2502 | "yallist": { 2503 | "version": "3.0.3", 2504 | "bundled": true, 2505 | "optional": true 2506 | } 2507 | } 2508 | }, 2509 | "gtoken": { 2510 | "version": "2.3.2", 2511 | "resolved": "https://registry.npmjs.org/gtoken/-/gtoken-2.3.2.tgz", 2512 | "integrity": "sha512-F8EObUGyC8Qd3WXTloNULZBwfUsOABoHElihB1F6zGhT/cy38iPL09wGLRY712I+hQnOyA+sYlgPFX2cOKz0qg==", 2513 | "optional": true, 2514 | "requires": { 2515 | "gaxios": "^1.0.4", 2516 | "google-p12-pem": "^1.0.0", 2517 | "jws": "^3.1.5", 2518 | "mime": "^2.2.0", 2519 | "pify": "^4.0.0" 2520 | } 2521 | }, 2522 | "har-schema": { 2523 | "version": "2.0.0", 2524 | "resolved": "https://registry.npmjs.org/har-schema/-/har-schema-2.0.0.tgz", 2525 | "integrity": "sha1-qUwiJOvKwEeCoNkDVSHyRzW37JI=", 2526 | "optional": true 2527 | }, 2528 | "har-validator": { 2529 | "version": "5.1.3", 2530 | "resolved": "https://registry.npmjs.org/har-validator/-/har-validator-5.1.3.tgz", 2531 | "integrity": "sha512-sNvOCzEQNr/qrvJgc3UG/kD4QtlHycrzwS+6mfTrrSq97BvaYcPZZI1ZSqGSPR73Cxn4LKTD4PttRwfU7jWq5g==", 2532 | "optional": true, 2533 | "requires": { 2534 | "ajv": "^6.5.5", 2535 | "har-schema": "^2.0.0" 2536 | } 2537 | }, 2538 | "hash-stream-validation": { 2539 | "version": "0.2.1", 2540 | "resolved": "https://registry.npmjs.org/hash-stream-validation/-/hash-stream-validation-0.2.1.tgz", 2541 | "integrity": "sha1-7Mm5l7IYvluzEphii7gHhptz3NE=", 2542 | "optional": true, 2543 | "requires": { 2544 | "through2": "^2.0.0" 2545 | }, 2546 | "dependencies": { 2547 | "isarray": { 2548 | "version": "1.0.0", 2549 | "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", 2550 | "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", 2551 | "optional": true 2552 | }, 2553 | "readable-stream": { 2554 | "version": "2.3.6", 2555 | "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.6.tgz", 2556 | "integrity": "sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw==", 2557 | "optional": true, 2558 | "requires": { 2559 | "core-util-is": "~1.0.0", 2560 | "inherits": "~2.0.3", 2561 | "isarray": "~1.0.0", 2562 | "process-nextick-args": "~2.0.0", 2563 | "safe-buffer": "~5.1.1", 2564 | "string_decoder": "~1.1.1", 2565 | "util-deprecate": "~1.0.1" 2566 | } 2567 | }, 2568 | "string_decoder": { 2569 | "version": "1.1.1", 2570 | "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", 2571 | "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", 2572 | "optional": true, 2573 | "requires": { 2574 | "safe-buffer": "~5.1.0" 2575 | } 2576 | }, 2577 | "through2": { 2578 | "version": "2.0.5", 2579 | "resolved": "https://registry.npmjs.org/through2/-/through2-2.0.5.tgz", 2580 | "integrity": "sha512-/mrRod8xqpA+IHSLyGCQ2s8SPHiCDEeQJSep1jqLYeEUClOFG2Qsh+4FU6G9VeqpZnGW/Su8LQGc4YKni5rYSQ==", 2581 | "optional": true, 2582 | "requires": { 2583 | "readable-stream": "~2.3.6", 2584 | "xtend": "~4.0.1" 2585 | } 2586 | } 2587 | } 2588 | }, 2589 | "http-errors": { 2590 | "version": "1.6.3", 2591 | "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.6.3.tgz", 2592 | "integrity": "sha1-i1VoC7S+KDoLW/TqLjhYC+HZMg0=", 2593 | "requires": { 2594 | "depd": "~1.1.2", 2595 | "inherits": "2.0.3", 2596 | "setprototypeof": "1.1.0", 2597 | "statuses": ">= 1.4.0 < 2" 2598 | } 2599 | }, 2600 | "http-parser-js": { 2601 | "version": "0.5.0", 2602 | "resolved": "https://registry.npmjs.org/http-parser-js/-/http-parser-js-0.5.0.tgz", 2603 | "integrity": "sha512-cZdEF7r4gfRIq7ezX9J0T+kQmJNOub71dWbgAXVHDct80TKP4MCETtZQ31xyv38UwgzkWPYF/Xc0ge55dW9Z9w==" 2604 | }, 2605 | "http-signature": { 2606 | "version": "1.2.0", 2607 | "resolved": "https://registry.npmjs.org/http-signature/-/http-signature-1.2.0.tgz", 2608 | "integrity": "sha1-muzZJRFHcvPZW2WmCruPfBj7rOE=", 2609 | "optional": true, 2610 | "requires": { 2611 | "assert-plus": "^1.0.0", 2612 | "jsprim": "^1.2.2", 2613 | "sshpk": "^1.7.0" 2614 | } 2615 | }, 2616 | "https-proxy-agent": { 2617 | "version": "2.2.1", 2618 | "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-2.2.1.tgz", 2619 | "integrity": "sha512-HPCTS1LW51bcyMYbxUIOO4HEOlQ1/1qRaFWcyxvwaqUS9TY88aoEuHUY33kuAh1YhVVaDQhLZsnPd+XNARWZlQ==", 2620 | "optional": true, 2621 | "requires": { 2622 | "agent-base": "^4.1.0", 2623 | "debug": "^3.1.0" 2624 | } 2625 | }, 2626 | "iconv-lite": { 2627 | "version": "0.4.23", 2628 | "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.23.tgz", 2629 | "integrity": "sha512-neyTUVFtahjf0mB3dZT77u+8O0QB89jFdnBkd5P1JgYPbPaia3gXXOVL2fq8VyU2gMMD7SaN7QukTB/pmXYvDA==", 2630 | "requires": { 2631 | "safer-buffer": ">= 2.1.2 < 3" 2632 | } 2633 | }, 2634 | "idb": { 2635 | "version": "3.0.2", 2636 | "resolved": "https://registry.npmjs.org/idb/-/idb-3.0.2.tgz", 2637 | "integrity": "sha512-+FLa/0sTXqyux0o6C+i2lOR0VoS60LU/jzUo5xjfY6+7sEEgy4Gz1O7yFBXvjd7N0NyIGWIRg8DcQSLEG+VSPw==" 2638 | }, 2639 | "imurmurhash": { 2640 | "version": "0.1.4", 2641 | "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", 2642 | "integrity": "sha1-khi5srkoojixPcT7a21XbyMUU+o=", 2643 | "optional": true 2644 | }, 2645 | "inherits": { 2646 | "version": "2.0.3", 2647 | "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", 2648 | "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=" 2649 | }, 2650 | "invert-kv": { 2651 | "version": "1.0.0", 2652 | "resolved": "https://registry.npmjs.org/invert-kv/-/invert-kv-1.0.0.tgz", 2653 | "integrity": "sha1-EEqOSqym09jNFXqO+L+rLXo//bY=", 2654 | "optional": true 2655 | }, 2656 | "ipaddr.js": { 2657 | "version": "1.8.0", 2658 | "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.8.0.tgz", 2659 | "integrity": "sha1-6qM9bd16zo9/b+DJygRA5wZzix4=" 2660 | }, 2661 | "is": { 2662 | "version": "3.3.0", 2663 | "resolved": "https://registry.npmjs.org/is/-/is-3.3.0.tgz", 2664 | "integrity": "sha512-nW24QBoPcFGGHJGUwnfpI7Yc5CdqWNdsyHQszVE/z2pKHXzh7FZ5GWhJqSyaQ9wMkQnsTx+kAI8bHlCX4tKdbg==", 2665 | "optional": true 2666 | }, 2667 | "is-buffer": { 2668 | "version": "2.0.4", 2669 | "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-2.0.4.tgz", 2670 | "integrity": "sha512-Kq1rokWXOPXWuaMAqZiJW4XxsmD9zGx9q4aePabbn3qCRGedtH7Cm+zV8WETitMfu1wdh+Rvd6w5egwSngUX2A==" 2671 | }, 2672 | "is-fullwidth-code-point": { 2673 | "version": "1.0.0", 2674 | "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz", 2675 | "integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=", 2676 | "optional": true, 2677 | "requires": { 2678 | "number-is-nan": "^1.0.0" 2679 | } 2680 | }, 2681 | "is-obj": { 2682 | "version": "1.0.1", 2683 | "resolved": "https://registry.npmjs.org/is-obj/-/is-obj-1.0.1.tgz", 2684 | "integrity": "sha1-PkcprB9f3gJc19g6iW2rn09n2w8=", 2685 | "optional": true 2686 | }, 2687 | "is-stream": { 2688 | "version": "1.1.0", 2689 | "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-1.1.0.tgz", 2690 | "integrity": "sha1-EtSj3U5o4Lec6428hBc66A2RykQ=" 2691 | }, 2692 | "is-stream-ended": { 2693 | "version": "0.1.4", 2694 | "resolved": "https://registry.npmjs.org/is-stream-ended/-/is-stream-ended-0.1.4.tgz", 2695 | "integrity": "sha512-xj0XPvmr7bQFTvirqnFr50o0hQIh6ZItDqloxt5aJrR4NQsYeSsyFQERYGCAzfindAcnKjINnwEEgLx4IqVzQw==", 2696 | "optional": true 2697 | }, 2698 | "is-typedarray": { 2699 | "version": "1.0.0", 2700 | "resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz", 2701 | "integrity": "sha1-5HnICFjfDBsR3dppQPlgEfzaSpo=", 2702 | "optional": true 2703 | }, 2704 | "isarray": { 2705 | "version": "0.0.1", 2706 | "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", 2707 | "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=", 2708 | "optional": true 2709 | }, 2710 | "isomorphic-fetch": { 2711 | "version": "2.2.1", 2712 | "resolved": "https://registry.npmjs.org/isomorphic-fetch/-/isomorphic-fetch-2.2.1.tgz", 2713 | "integrity": "sha1-YRrhrPFPXoH3KVB0coGf6XM1WKk=", 2714 | "requires": { 2715 | "node-fetch": "^1.0.1", 2716 | "whatwg-fetch": ">=0.10.0" 2717 | }, 2718 | "dependencies": { 2719 | "node-fetch": { 2720 | "version": "1.7.3", 2721 | "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-1.7.3.tgz", 2722 | "integrity": "sha512-NhZ4CsKx7cYm2vSrBAr2PvFOe6sWDf0UYLRqA6svUYg7+/TSfVAu49jYC4BvQ4Sms9SZgdqGBgroqfDhJdTyKQ==", 2723 | "requires": { 2724 | "encoding": "^0.1.11", 2725 | "is-stream": "^1.0.1" 2726 | } 2727 | } 2728 | } 2729 | }, 2730 | "isstream": { 2731 | "version": "0.1.2", 2732 | "resolved": "https://registry.npmjs.org/isstream/-/isstream-0.1.2.tgz", 2733 | "integrity": "sha1-R+Y/evVa+m+S4VAOaQ64uFKcCZo=", 2734 | "optional": true 2735 | }, 2736 | "jsbn": { 2737 | "version": "0.1.1", 2738 | "resolved": "https://registry.npmjs.org/jsbn/-/jsbn-0.1.1.tgz", 2739 | "integrity": "sha1-peZUwuWi3rXyAdls77yoDA7y9RM=", 2740 | "optional": true 2741 | }, 2742 | "json-bigint": { 2743 | "version": "0.3.0", 2744 | "resolved": "https://registry.npmjs.org/json-bigint/-/json-bigint-0.3.0.tgz", 2745 | "integrity": "sha1-DM2RLEuCcNBfBW+9E4FLU9OCWx4=", 2746 | "optional": true, 2747 | "requires": { 2748 | "bignumber.js": "^7.0.0" 2749 | } 2750 | }, 2751 | "json-schema": { 2752 | "version": "0.2.3", 2753 | "resolved": "https://registry.npmjs.org/json-schema/-/json-schema-0.2.3.tgz", 2754 | "integrity": "sha1-tIDIkuWaLwWVTOcnvT8qTogvnhM=", 2755 | "optional": true 2756 | }, 2757 | "json-schema-traverse": { 2758 | "version": "0.4.1", 2759 | "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", 2760 | "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", 2761 | "optional": true 2762 | }, 2763 | "json-stringify-safe": { 2764 | "version": "5.0.1", 2765 | "resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz", 2766 | "integrity": "sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus=", 2767 | "optional": true 2768 | }, 2769 | "jsonwebtoken": { 2770 | "version": "8.1.0", 2771 | "resolved": "https://registry.npmjs.org/jsonwebtoken/-/jsonwebtoken-8.1.0.tgz", 2772 | "integrity": "sha1-xjl80uX9WD1lwAeoPce7eOaYK4M=", 2773 | "requires": { 2774 | "jws": "^3.1.4", 2775 | "lodash.includes": "^4.3.0", 2776 | "lodash.isboolean": "^3.0.3", 2777 | "lodash.isinteger": "^4.0.4", 2778 | "lodash.isnumber": "^3.0.3", 2779 | "lodash.isplainobject": "^4.0.6", 2780 | "lodash.isstring": "^4.0.1", 2781 | "lodash.once": "^4.0.0", 2782 | "ms": "^2.0.0", 2783 | "xtend": "^4.0.1" 2784 | } 2785 | }, 2786 | "jsprim": { 2787 | "version": "1.4.1", 2788 | "resolved": "https://registry.npmjs.org/jsprim/-/jsprim-1.4.1.tgz", 2789 | "integrity": "sha1-MT5mvB5cwG5Di8G3SZwuXFastqI=", 2790 | "optional": true, 2791 | "requires": { 2792 | "assert-plus": "1.0.0", 2793 | "extsprintf": "1.3.0", 2794 | "json-schema": "0.2.3", 2795 | "verror": "1.10.0" 2796 | } 2797 | }, 2798 | "jwa": { 2799 | "version": "1.2.0", 2800 | "resolved": "https://registry.npmjs.org/jwa/-/jwa-1.2.0.tgz", 2801 | "integrity": "sha512-Grku9ZST5NNQ3hqNUodSkDfEBqAmGA1R8yiyPHOnLzEKI0GaCQC/XhFmsheXYuXzFQJdILbh+lYBiliqG5R/Vg==", 2802 | "requires": { 2803 | "buffer-equal-constant-time": "1.0.1", 2804 | "ecdsa-sig-formatter": "1.0.10", 2805 | "safe-buffer": "^5.0.1" 2806 | } 2807 | }, 2808 | "jws": { 2809 | "version": "3.2.1", 2810 | "resolved": "https://registry.npmjs.org/jws/-/jws-3.2.1.tgz", 2811 | "integrity": "sha512-bGA2omSrFUkd72dhh05bIAN832znP4wOU3lfuXtRBuGTbsmNmDXMQg28f0Vsxaxgk4myF5YkKQpz6qeRpMgX9g==", 2812 | "requires": { 2813 | "jwa": "^1.2.0", 2814 | "safe-buffer": "^5.0.1" 2815 | } 2816 | }, 2817 | "lcid": { 2818 | "version": "1.0.0", 2819 | "resolved": "https://registry.npmjs.org/lcid/-/lcid-1.0.0.tgz", 2820 | "integrity": "sha1-MIrMr6C8SDo4Z7S28rlQYlHRuDU=", 2821 | "optional": true, 2822 | "requires": { 2823 | "invert-kv": "^1.0.0" 2824 | } 2825 | }, 2826 | "lodash": { 2827 | "version": "4.17.15", 2828 | "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.15.tgz", 2829 | "integrity": "sha512-8xOcRHvCjnocdS5cpwXQXVzmmh5e5+saE2QGoeQmbKmRS6J3VQppPOIt0MnmE+4xlZoumy0GPG0D0MVIQbNA1A==" 2830 | }, 2831 | "lodash.at": { 2832 | "version": "4.6.0", 2833 | "resolved": "https://registry.npmjs.org/lodash.at/-/lodash.at-4.6.0.tgz", 2834 | "integrity": "sha1-k83OZk8KGZTqM9181A4jr9EbD/g=", 2835 | "optional": true 2836 | }, 2837 | "lodash.camelcase": { 2838 | "version": "4.3.0", 2839 | "resolved": "https://registry.npmjs.org/lodash.camelcase/-/lodash.camelcase-4.3.0.tgz", 2840 | "integrity": "sha1-soqmKIorn8ZRA1x3EfZathkDMaY=" 2841 | }, 2842 | "lodash.clone": { 2843 | "version": "4.5.0", 2844 | "resolved": "https://registry.npmjs.org/lodash.clone/-/lodash.clone-4.5.0.tgz", 2845 | "integrity": "sha1-GVhwRQ9aExkkeN9Lw9I9LeoZB7Y=" 2846 | }, 2847 | "lodash.has": { 2848 | "version": "4.5.2", 2849 | "resolved": "https://registry.npmjs.org/lodash.has/-/lodash.has-4.5.2.tgz", 2850 | "integrity": "sha1-0Z9NwQlQWMzL4rDN9O4P5Ko3yGI=", 2851 | "optional": true 2852 | }, 2853 | "lodash.includes": { 2854 | "version": "4.3.0", 2855 | "resolved": "https://registry.npmjs.org/lodash.includes/-/lodash.includes-4.3.0.tgz", 2856 | "integrity": "sha1-YLuYqHy5I8aMoeUTJUgzFISfVT8=" 2857 | }, 2858 | "lodash.isboolean": { 2859 | "version": "3.0.3", 2860 | "resolved": "https://registry.npmjs.org/lodash.isboolean/-/lodash.isboolean-3.0.3.tgz", 2861 | "integrity": "sha1-bC4XHbKiV82WgC/UOwGyDV9YcPY=" 2862 | }, 2863 | "lodash.isinteger": { 2864 | "version": "4.0.4", 2865 | "resolved": "https://registry.npmjs.org/lodash.isinteger/-/lodash.isinteger-4.0.4.tgz", 2866 | "integrity": "sha1-YZwK89A/iwTDH1iChAt3sRzWg0M=" 2867 | }, 2868 | "lodash.isnumber": { 2869 | "version": "3.0.3", 2870 | "resolved": "https://registry.npmjs.org/lodash.isnumber/-/lodash.isnumber-3.0.3.tgz", 2871 | "integrity": "sha1-POdoEMWSjQM1IwGsKHMX8RwLH/w=" 2872 | }, 2873 | "lodash.isplainobject": { 2874 | "version": "4.0.6", 2875 | "resolved": "https://registry.npmjs.org/lodash.isplainobject/-/lodash.isplainobject-4.0.6.tgz", 2876 | "integrity": "sha1-fFJqUtibRcRcxpC4gWO+BJf1UMs=" 2877 | }, 2878 | "lodash.isstring": { 2879 | "version": "4.0.1", 2880 | "resolved": "https://registry.npmjs.org/lodash.isstring/-/lodash.isstring-4.0.1.tgz", 2881 | "integrity": "sha1-1SfftUVuynzJu5XV2ur4i6VKVFE=" 2882 | }, 2883 | "lodash.merge": { 2884 | "version": "4.6.2", 2885 | "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz", 2886 | "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==" 2887 | }, 2888 | "lodash.once": { 2889 | "version": "4.1.1", 2890 | "resolved": "https://registry.npmjs.org/lodash.once/-/lodash.once-4.1.1.tgz", 2891 | "integrity": "sha1-DdOXEhPHxW34gJd9UEyI+0cal6w=" 2892 | }, 2893 | "long": { 2894 | "version": "4.0.0", 2895 | "resolved": "https://registry.npmjs.org/long/-/long-4.0.0.tgz", 2896 | "integrity": "sha512-XsP+KhQif4bjX1kbuSiySJFNAehNxgLb6hPRGJ9QsUr8ajHkuXGdrHmFUTUUXhDwVX2R5bY4JNZEwbUiMhV+MA==", 2897 | "optional": true 2898 | }, 2899 | "lru-cache": { 2900 | "version": "5.1.1", 2901 | "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz", 2902 | "integrity": "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==", 2903 | "optional": true, 2904 | "requires": { 2905 | "yallist": "^3.0.2" 2906 | } 2907 | }, 2908 | "make-dir": { 2909 | "version": "1.3.0", 2910 | "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-1.3.0.tgz", 2911 | "integrity": "sha512-2w31R7SJtieJJnQtGc7RVL2StM2vGYVfqUOvUDxH6bC6aJTxPxTF0GnIgCyu7tjockiUWAYQRbxa7vKn34s5sQ==", 2912 | "optional": true, 2913 | "requires": { 2914 | "pify": "^3.0.0" 2915 | }, 2916 | "dependencies": { 2917 | "pify": { 2918 | "version": "3.0.0", 2919 | "resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz", 2920 | "integrity": "sha1-5aSs0sEB/fPZpNB/DbxNtJ3SgXY=", 2921 | "optional": true 2922 | } 2923 | } 2924 | }, 2925 | "media-typer": { 2926 | "version": "0.3.0", 2927 | "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", 2928 | "integrity": "sha1-hxDXrwqmJvj/+hzgAWhUUmMlV0g=" 2929 | }, 2930 | "merge-descriptors": { 2931 | "version": "1.0.1", 2932 | "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.1.tgz", 2933 | "integrity": "sha1-sAqqVW3YtEVoFQ7J0blT8/kMu2E=" 2934 | }, 2935 | "methods": { 2936 | "version": "1.1.2", 2937 | "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz", 2938 | "integrity": "sha1-VSmk1nZUE07cxSZmVoNbD4Ua/O4=" 2939 | }, 2940 | "mime": { 2941 | "version": "2.4.0", 2942 | "resolved": "https://registry.npmjs.org/mime/-/mime-2.4.0.tgz", 2943 | "integrity": "sha512-ikBcWwyqXQSHKtciCcctu9YfPbFYZ4+gbHEmE0Q8jzcTYQg5dHCr3g2wwAZjPoJfQVXZq6KXAjpXOTf5/cjT7w==", 2944 | "optional": true 2945 | }, 2946 | "mime-db": { 2947 | "version": "1.38.0", 2948 | "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.38.0.tgz", 2949 | "integrity": "sha512-bqVioMFFzc2awcdJZIzR3HjZFX20QhilVS7hytkKrv7xFAn8bM1gzc/FOX2awLISvWe0PV8ptFKcon+wZ5qYkg==" 2950 | }, 2951 | "mime-types": { 2952 | "version": "2.1.22", 2953 | "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.22.tgz", 2954 | "integrity": "sha512-aGl6TZGnhm/li6F7yx82bJiBZwgiEa4Hf6CNr8YO+r5UHr53tSTYZb102zyU50DOWWKeOv0uQLRL0/9EiKWCog==", 2955 | "requires": { 2956 | "mime-db": "~1.38.0" 2957 | } 2958 | }, 2959 | "ms": { 2960 | "version": "2.1.1", 2961 | "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.1.tgz", 2962 | "integrity": "sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg==" 2963 | }, 2964 | "nan": { 2965 | "version": "2.12.1", 2966 | "resolved": "https://registry.npmjs.org/nan/-/nan-2.12.1.tgz", 2967 | "integrity": "sha512-JY7V6lRkStKcKTvHO5NVSQRv+RV+FIL5pvDoLiAtSL9pKlC5x9PKQcZDsq7m4FO4d57mkhC6Z+QhAh3Jdk5JFw==", 2968 | "optional": true 2969 | }, 2970 | "negotiator": { 2971 | "version": "0.6.1", 2972 | "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.1.tgz", 2973 | "integrity": "sha1-KzJxhOiZIQEXeyhWP7XnECrNDKk=" 2974 | }, 2975 | "node-fetch": { 2976 | "version": "2.3.0", 2977 | "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.3.0.tgz", 2978 | "integrity": "sha512-MOd8pV3fxENbryESLgVIeaGKrdl+uaYhCSSVkjeOb/31/njTpcis5aWfdqgNlHIrKOLRbMnfPINPOML2CIFeXA==", 2979 | "optional": true 2980 | }, 2981 | "node-forge": { 2982 | "version": "0.7.4", 2983 | "resolved": "https://registry.npmjs.org/node-forge/-/node-forge-0.7.4.tgz", 2984 | "integrity": "sha512-8Df0906+tq/omxuCZD6PqhPaQDYuyJ1d+VITgxoIA8zvQd1ru+nMJcDChHH324MWitIgbVkAkQoGEEVJNpn/PA==" 2985 | }, 2986 | "number-is-nan": { 2987 | "version": "1.0.1", 2988 | "resolved": "https://registry.npmjs.org/number-is-nan/-/number-is-nan-1.0.1.tgz", 2989 | "integrity": "sha1-CXtgK1NCKlIsGvuHkDGDNpQaAR0=", 2990 | "optional": true 2991 | }, 2992 | "oauth-sign": { 2993 | "version": "0.9.0", 2994 | "resolved": "https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.9.0.tgz", 2995 | "integrity": "sha512-fexhUFFPTGV8ybAtSIGbV6gOkSv8UtRbDBnAyLQw4QPKkgNlsH2ByPGtMUqdWkos6YCRmAqViwgZrJc/mRDzZQ==", 2996 | "optional": true 2997 | }, 2998 | "object-assign": { 2999 | "version": "4.1.1", 3000 | "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", 3001 | "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=" 3002 | }, 3003 | "on-finished": { 3004 | "version": "2.3.0", 3005 | "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.3.0.tgz", 3006 | "integrity": "sha1-IPEzZIGwg811M3mSoWlxqi2QaUc=", 3007 | "requires": { 3008 | "ee-first": "1.1.1" 3009 | } 3010 | }, 3011 | "once": { 3012 | "version": "1.4.0", 3013 | "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", 3014 | "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", 3015 | "optional": true, 3016 | "requires": { 3017 | "wrappy": "1" 3018 | } 3019 | }, 3020 | "optjs": { 3021 | "version": "3.2.2", 3022 | "resolved": "https://registry.npmjs.org/optjs/-/optjs-3.2.2.tgz", 3023 | "integrity": "sha1-aabOicRCpEQDFBrS+bNwvVu29O4=", 3024 | "optional": true 3025 | }, 3026 | "os-locale": { 3027 | "version": "1.4.0", 3028 | "resolved": "https://registry.npmjs.org/os-locale/-/os-locale-1.4.0.tgz", 3029 | "integrity": "sha1-IPnxeuKe00XoveWDsT0gCYA8FNk=", 3030 | "optional": true, 3031 | "requires": { 3032 | "lcid": "^1.0.0" 3033 | } 3034 | }, 3035 | "parseurl": { 3036 | "version": "1.3.2", 3037 | "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.2.tgz", 3038 | "integrity": "sha1-/CidTtiZMRlGDBViUyYs3I3mW/M=" 3039 | }, 3040 | "path-to-regexp": { 3041 | "version": "0.1.7", 3042 | "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.7.tgz", 3043 | "integrity": "sha1-32BBeABfUi8V60SQ5yR6G/qmf4w=" 3044 | }, 3045 | "performance-now": { 3046 | "version": "2.1.0", 3047 | "resolved": "https://registry.npmjs.org/performance-now/-/performance-now-2.1.0.tgz", 3048 | "integrity": "sha1-Ywn04OX6kT7BxpMHrjZLSzd8nns=", 3049 | "optional": true 3050 | }, 3051 | "pify": { 3052 | "version": "4.0.1", 3053 | "resolved": "https://registry.npmjs.org/pify/-/pify-4.0.1.tgz", 3054 | "integrity": "sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g==", 3055 | "optional": true 3056 | }, 3057 | "process-nextick-args": { 3058 | "version": "2.0.0", 3059 | "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.0.tgz", 3060 | "integrity": "sha512-MtEC1TqN0EU5nephaJ4rAtThHtC86dNN9qCuEhtshvpVBkAW5ZO7BASN9REnF9eoXGcRub+pFuKEpOHE+HbEMw==", 3061 | "optional": true 3062 | }, 3063 | "promise-polyfill": { 3064 | "version": "8.1.3", 3065 | "resolved": "https://registry.npmjs.org/promise-polyfill/-/promise-polyfill-8.1.3.tgz", 3066 | "integrity": "sha512-MG5r82wBzh7pSKDRa9y+vllNHz3e3d4CNj1PQE4BQYxLme0gKYYBm9YENq+UkEikyZ0XbiGWxYlVw3Rl9O/U8g==" 3067 | }, 3068 | "protobufjs": { 3069 | "version": "6.8.8", 3070 | "resolved": "https://registry.npmjs.org/protobufjs/-/protobufjs-6.8.8.tgz", 3071 | "integrity": "sha512-AAmHtD5pXgZfi7GMpllpO3q1Xw1OYldr+dMUlAnffGTAhqkg72WdmSY71uKBF/JuyiKs8psYbtKrhi0ASCD8qw==", 3072 | "requires": { 3073 | "@protobufjs/aspromise": "^1.1.2", 3074 | "@protobufjs/base64": "^1.1.2", 3075 | "@protobufjs/codegen": "^2.0.4", 3076 | "@protobufjs/eventemitter": "^1.1.0", 3077 | "@protobufjs/fetch": "^1.1.0", 3078 | "@protobufjs/float": "^1.0.2", 3079 | "@protobufjs/inquire": "^1.1.0", 3080 | "@protobufjs/path": "^1.1.2", 3081 | "@protobufjs/pool": "^1.1.0", 3082 | "@protobufjs/utf8": "^1.1.0", 3083 | "@types/long": "^4.0.0", 3084 | "@types/node": "^10.1.0", 3085 | "long": "^4.0.0" 3086 | }, 3087 | "dependencies": { 3088 | "@types/node": { 3089 | "version": "10.12.26", 3090 | "resolved": "https://registry.npmjs.org/@types/node/-/node-10.12.26.tgz", 3091 | "integrity": "sha512-nMRqS+mL1TOnIJrL6LKJcNZPB8V3eTfRo9FQA2b5gDvrHurC8XbSA86KNe0dShlEL7ReWJv/OU9NL7Z0dnqWTg==", 3092 | "optional": true 3093 | } 3094 | } 3095 | }, 3096 | "proxy-addr": { 3097 | "version": "2.0.4", 3098 | "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.4.tgz", 3099 | "integrity": "sha512-5erio2h9jp5CHGwcybmxmVqHmnCBZeewlfJ0pex+UW7Qny7OOZXTtH56TGNyBizkgiOwhJtMKrVzDTeKcySZwA==", 3100 | "requires": { 3101 | "forwarded": "~0.1.2", 3102 | "ipaddr.js": "1.8.0" 3103 | } 3104 | }, 3105 | "psl": { 3106 | "version": "1.1.31", 3107 | "resolved": "https://registry.npmjs.org/psl/-/psl-1.1.31.tgz", 3108 | "integrity": "sha512-/6pt4+C+T+wZUieKR620OpzN/LlnNKuWjy1iFLQ/UG35JqHlR/89MP1d96dUfkf6Dne3TuLQzOYEYshJ+Hx8mw==", 3109 | "optional": true 3110 | }, 3111 | "pump": { 3112 | "version": "2.0.1", 3113 | "resolved": "https://registry.npmjs.org/pump/-/pump-2.0.1.tgz", 3114 | "integrity": "sha512-ruPMNRkN3MHP1cWJc9OWr+T/xDP0jhXYCLfJcBuX54hhfIBnaQmAUMfDcG4DM5UMWByBbJY69QSphm3jtDKIkA==", 3115 | "optional": true, 3116 | "requires": { 3117 | "end-of-stream": "^1.1.0", 3118 | "once": "^1.3.1" 3119 | } 3120 | }, 3121 | "pumpify": { 3122 | "version": "1.5.1", 3123 | "resolved": "https://registry.npmjs.org/pumpify/-/pumpify-1.5.1.tgz", 3124 | "integrity": "sha512-oClZI37HvuUJJxSKKrC17bZ9Cu0ZYhEAGPsPUy9KlMUmv9dKX2o77RUmq7f3XjIxbwyGwYzbzQ1L2Ks8sIradQ==", 3125 | "optional": true, 3126 | "requires": { 3127 | "duplexify": "^3.6.0", 3128 | "inherits": "^2.0.3", 3129 | "pump": "^2.0.0" 3130 | } 3131 | }, 3132 | "punycode": { 3133 | "version": "2.1.1", 3134 | "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz", 3135 | "integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==", 3136 | "optional": true 3137 | }, 3138 | "qs": { 3139 | "version": "6.5.2", 3140 | "resolved": "https://registry.npmjs.org/qs/-/qs-6.5.2.tgz", 3141 | "integrity": "sha512-N5ZAX4/LxJmF+7wN74pUD6qAh9/wnvdQcjq9TZjevvXzSUo7bfmw91saqMjzGS2xq91/odN2dW/WOl7qQHNDGA==" 3142 | }, 3143 | "range-parser": { 3144 | "version": "1.2.0", 3145 | "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.0.tgz", 3146 | "integrity": "sha1-9JvmtIeJTdxA3MlKMi9hEJLgDV4=" 3147 | }, 3148 | "raw-body": { 3149 | "version": "2.3.3", 3150 | "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.3.3.tgz", 3151 | "integrity": "sha512-9esiElv1BrZoI3rCDuOuKCBRbuApGGaDPQfjSflGxdy4oyzqghxu6klEkkVIvBje+FF0BX9coEv8KqW6X/7njw==", 3152 | "requires": { 3153 | "bytes": "3.0.0", 3154 | "http-errors": "1.6.3", 3155 | "iconv-lite": "0.4.23", 3156 | "unpipe": "1.0.0" 3157 | } 3158 | }, 3159 | "readable-stream": { 3160 | "version": "1.0.34", 3161 | "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.0.34.tgz", 3162 | "integrity": "sha1-Elgg40vIQtLyqq+v5MKRbuMsFXw=", 3163 | "optional": true, 3164 | "requires": { 3165 | "core-util-is": "~1.0.0", 3166 | "inherits": "~2.0.1", 3167 | "isarray": "0.0.1", 3168 | "string_decoder": "~0.10.x" 3169 | } 3170 | }, 3171 | "request": { 3172 | "version": "2.88.0", 3173 | "resolved": "https://registry.npmjs.org/request/-/request-2.88.0.tgz", 3174 | "integrity": "sha512-NAqBSrijGLZdM0WZNsInLJpkJokL72XYjUpnB0iwsRgxh7dB6COrHnTBNwN0E+lHDAJzu7kLAkDeY08z2/A0hg==", 3175 | "optional": true, 3176 | "requires": { 3177 | "aws-sign2": "~0.7.0", 3178 | "aws4": "^1.8.0", 3179 | "caseless": "~0.12.0", 3180 | "combined-stream": "~1.0.6", 3181 | "extend": "~3.0.2", 3182 | "forever-agent": "~0.6.1", 3183 | "form-data": "~2.3.2", 3184 | "har-validator": "~5.1.0", 3185 | "http-signature": "~1.2.0", 3186 | "is-typedarray": "~1.0.0", 3187 | "isstream": "~0.1.2", 3188 | "json-stringify-safe": "~5.0.1", 3189 | "mime-types": "~2.1.19", 3190 | "oauth-sign": "~0.9.0", 3191 | "performance-now": "^2.1.0", 3192 | "qs": "~6.5.2", 3193 | "safe-buffer": "^5.1.2", 3194 | "tough-cookie": "~2.4.3", 3195 | "tunnel-agent": "^0.6.0", 3196 | "uuid": "^3.3.2" 3197 | } 3198 | }, 3199 | "retry-request": { 3200 | "version": "4.0.0", 3201 | "resolved": "https://registry.npmjs.org/retry-request/-/retry-request-4.0.0.tgz", 3202 | "integrity": "sha512-S4HNLaWcMP6r8E4TMH52Y7/pM8uNayOcTDDQNBwsCccL1uI+Ol2TljxRDPzaNfbhOB30+XWP5NnZkB3LiJxi1w==", 3203 | "optional": true, 3204 | "requires": { 3205 | "through2": "^2.0.0" 3206 | }, 3207 | "dependencies": { 3208 | "isarray": { 3209 | "version": "1.0.0", 3210 | "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", 3211 | "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", 3212 | "optional": true 3213 | }, 3214 | "readable-stream": { 3215 | "version": "2.3.6", 3216 | "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.6.tgz", 3217 | "integrity": "sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw==", 3218 | "optional": true, 3219 | "requires": { 3220 | "core-util-is": "~1.0.0", 3221 | "inherits": "~2.0.3", 3222 | "isarray": "~1.0.0", 3223 | "process-nextick-args": "~2.0.0", 3224 | "safe-buffer": "~5.1.1", 3225 | "string_decoder": "~1.1.1", 3226 | "util-deprecate": "~1.0.1" 3227 | } 3228 | }, 3229 | "string_decoder": { 3230 | "version": "1.1.1", 3231 | "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", 3232 | "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", 3233 | "optional": true, 3234 | "requires": { 3235 | "safe-buffer": "~5.1.0" 3236 | } 3237 | }, 3238 | "through2": { 3239 | "version": "2.0.5", 3240 | "resolved": "https://registry.npmjs.org/through2/-/through2-2.0.5.tgz", 3241 | "integrity": "sha512-/mrRod8xqpA+IHSLyGCQ2s8SPHiCDEeQJSep1jqLYeEUClOFG2Qsh+4FU6G9VeqpZnGW/Su8LQGc4YKni5rYSQ==", 3242 | "optional": true, 3243 | "requires": { 3244 | "readable-stream": "~2.3.6", 3245 | "xtend": "~4.0.1" 3246 | } 3247 | } 3248 | } 3249 | }, 3250 | "safe-buffer": { 3251 | "version": "5.1.2", 3252 | "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", 3253 | "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" 3254 | }, 3255 | "safer-buffer": { 3256 | "version": "2.1.2", 3257 | "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", 3258 | "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==" 3259 | }, 3260 | "semver": { 3261 | "version": "5.6.0", 3262 | "resolved": "https://registry.npmjs.org/semver/-/semver-5.6.0.tgz", 3263 | "integrity": "sha512-RS9R6R35NYgQn++fkDWaOmqGoj4Ek9gGs+DPxNUZKuwE183xjJroKvyo1IzVFeXvUrvmALy6FWD5xrdJT25gMg==" 3264 | }, 3265 | "send": { 3266 | "version": "0.16.2", 3267 | "resolved": "https://registry.npmjs.org/send/-/send-0.16.2.tgz", 3268 | "integrity": "sha512-E64YFPUssFHEFBvpbbjr44NCLtI1AohxQ8ZSiJjQLskAdKuriYEP6VyGEsRDH8ScozGpkaX1BGvhanqCwkcEZw==", 3269 | "requires": { 3270 | "debug": "2.6.9", 3271 | "depd": "~1.1.2", 3272 | "destroy": "~1.0.4", 3273 | "encodeurl": "~1.0.2", 3274 | "escape-html": "~1.0.3", 3275 | "etag": "~1.8.1", 3276 | "fresh": "0.5.2", 3277 | "http-errors": "~1.6.2", 3278 | "mime": "1.4.1", 3279 | "ms": "2.0.0", 3280 | "on-finished": "~2.3.0", 3281 | "range-parser": "~1.2.0", 3282 | "statuses": "~1.4.0" 3283 | }, 3284 | "dependencies": { 3285 | "debug": { 3286 | "version": "2.6.9", 3287 | "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", 3288 | "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", 3289 | "requires": { 3290 | "ms": "2.0.0" 3291 | } 3292 | }, 3293 | "mime": { 3294 | "version": "1.4.1", 3295 | "resolved": "https://registry.npmjs.org/mime/-/mime-1.4.1.tgz", 3296 | "integrity": "sha512-KI1+qOZu5DcW6wayYHSzR/tXKCDC5Om4s1z2QJjDULzLcmf3DvzS7oluY4HCTrc+9FiKmWUgeNLg7W3uIQvxtQ==" 3297 | }, 3298 | "ms": { 3299 | "version": "2.0.0", 3300 | "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", 3301 | "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" 3302 | } 3303 | } 3304 | }, 3305 | "serve-static": { 3306 | "version": "1.13.2", 3307 | "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.13.2.tgz", 3308 | "integrity": "sha512-p/tdJrO4U387R9oMjb1oj7qSMaMfmOyd4j9hOFoxZe2baQszgHcSWjuya/CiT5kgZZKRudHNOA0pYXOl8rQ5nw==", 3309 | "requires": { 3310 | "encodeurl": "~1.0.2", 3311 | "escape-html": "~1.0.3", 3312 | "parseurl": "~1.3.2", 3313 | "send": "0.16.2" 3314 | } 3315 | }, 3316 | "setprototypeof": { 3317 | "version": "1.1.0", 3318 | "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.1.0.tgz", 3319 | "integrity": "sha512-BvE/TwpZX4FXExxOxZyRGQQv651MSwmWKZGqvmPcRIjDqWub67kTKuIMx43cZZrS/cBBzwBcNDWoFxt2XEFIpQ==" 3320 | }, 3321 | "signal-exit": { 3322 | "version": "3.0.2", 3323 | "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.2.tgz", 3324 | "integrity": "sha1-tf3AjxKH6hF4Yo5BXiUTK3NkbG0=", 3325 | "optional": true 3326 | }, 3327 | "snakeize": { 3328 | "version": "0.1.0", 3329 | "resolved": "https://registry.npmjs.org/snakeize/-/snakeize-0.1.0.tgz", 3330 | "integrity": "sha1-EMCI2LWOsHazIpu1oE4jLOEmQi0=", 3331 | "optional": true 3332 | }, 3333 | "split-array-stream": { 3334 | "version": "2.0.0", 3335 | "resolved": "https://registry.npmjs.org/split-array-stream/-/split-array-stream-2.0.0.tgz", 3336 | "integrity": "sha512-hmMswlVY91WvGMxs0k8MRgq8zb2mSen4FmDNc5AFiTWtrBpdZN6nwD6kROVe4vNL+ywrvbCKsWVCnEd4riELIg==", 3337 | "optional": true, 3338 | "requires": { 3339 | "is-stream-ended": "^0.1.4" 3340 | } 3341 | }, 3342 | "sshpk": { 3343 | "version": "1.16.1", 3344 | "resolved": "https://registry.npmjs.org/sshpk/-/sshpk-1.16.1.tgz", 3345 | "integrity": "sha512-HXXqVUq7+pcKeLqqZj6mHFUMvXtOJt1uoUx09pFW6011inTMxqI8BA8PM95myrIyyKwdnzjdFjLiE6KBPVtJIg==", 3346 | "optional": true, 3347 | "requires": { 3348 | "asn1": "~0.2.3", 3349 | "assert-plus": "^1.0.0", 3350 | "bcrypt-pbkdf": "^1.0.0", 3351 | "dashdash": "^1.12.0", 3352 | "ecc-jsbn": "~0.1.1", 3353 | "getpass": "^0.1.1", 3354 | "jsbn": "~0.1.0", 3355 | "safer-buffer": "^2.0.2", 3356 | "tweetnacl": "~0.14.0" 3357 | } 3358 | }, 3359 | "statuses": { 3360 | "version": "1.4.0", 3361 | "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.4.0.tgz", 3362 | "integrity": "sha512-zhSCtt8v2NDrRlPQpCNtw/heZLtfUDqxBM1udqikb/Hbk52LK4nQSwr10u77iopCW5LsyHpuXS0GnEc48mLeew==" 3363 | }, 3364 | "stream-events": { 3365 | "version": "1.0.5", 3366 | "resolved": "https://registry.npmjs.org/stream-events/-/stream-events-1.0.5.tgz", 3367 | "integrity": "sha512-E1GUzBSgvct8Jsb3v2X15pjzN1tYebtbLaMg+eBOUOAxgbLoSbT2NS91ckc5lJD1KfLjId+jXJRgo0qnV5Nerg==", 3368 | "optional": true, 3369 | "requires": { 3370 | "stubs": "^3.0.0" 3371 | } 3372 | }, 3373 | "stream-shift": { 3374 | "version": "1.0.0", 3375 | "resolved": "https://registry.npmjs.org/stream-shift/-/stream-shift-1.0.0.tgz", 3376 | "integrity": "sha1-1cdSgl5TZ+eG944Y5EXqIjoVWVI=", 3377 | "optional": true 3378 | }, 3379 | "string-width": { 3380 | "version": "1.0.2", 3381 | "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", 3382 | "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=", 3383 | "optional": true, 3384 | "requires": { 3385 | "code-point-at": "^1.0.0", 3386 | "is-fullwidth-code-point": "^1.0.0", 3387 | "strip-ansi": "^3.0.0" 3388 | } 3389 | }, 3390 | "string_decoder": { 3391 | "version": "0.10.31", 3392 | "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", 3393 | "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=", 3394 | "optional": true 3395 | }, 3396 | "strip-ansi": { 3397 | "version": "3.0.1", 3398 | "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", 3399 | "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", 3400 | "optional": true, 3401 | "requires": { 3402 | "ansi-regex": "^2.0.0" 3403 | } 3404 | }, 3405 | "stubs": { 3406 | "version": "3.0.0", 3407 | "resolved": "https://registry.npmjs.org/stubs/-/stubs-3.0.0.tgz", 3408 | "integrity": "sha1-6NK6H6nJBXAwPAMLaQD31fiavls=", 3409 | "optional": true 3410 | }, 3411 | "teeny-request": { 3412 | "version": "3.11.3", 3413 | "resolved": "https://registry.npmjs.org/teeny-request/-/teeny-request-3.11.3.tgz", 3414 | "integrity": "sha512-CKncqSF7sH6p4rzCgkb/z/Pcos5efl0DmolzvlqRQUNcpRIruOhY9+T1FsIlyEbfWd7MsFpodROOwHYh2BaXzw==", 3415 | "optional": true, 3416 | "requires": { 3417 | "https-proxy-agent": "^2.2.1", 3418 | "node-fetch": "^2.2.0", 3419 | "uuid": "^3.3.2" 3420 | } 3421 | }, 3422 | "through2": { 3423 | "version": "3.0.0", 3424 | "resolved": "https://registry.npmjs.org/through2/-/through2-3.0.0.tgz", 3425 | "integrity": "sha512-8B+sevlqP4OiCjonI1Zw03Sf8PuV1eRsYQgLad5eonILOdyeRsY27A/2Ze8IlvlMvq31OH+3fz/styI7Ya62yQ==", 3426 | "optional": true, 3427 | "requires": { 3428 | "readable-stream": "2 || 3", 3429 | "xtend": "~4.0.1" 3430 | }, 3431 | "dependencies": { 3432 | "readable-stream": { 3433 | "version": "3.1.1", 3434 | "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.1.1.tgz", 3435 | "integrity": "sha512-DkN66hPyqDhnIQ6Jcsvx9bFjhw214O4poMBcIMgPVpQvNy9a0e0Uhg5SqySyDKAmUlwt8LonTBz1ezOnM8pUdA==", 3436 | "optional": true, 3437 | "requires": { 3438 | "inherits": "^2.0.3", 3439 | "string_decoder": "^1.1.1", 3440 | "util-deprecate": "^1.0.1" 3441 | } 3442 | }, 3443 | "string_decoder": { 3444 | "version": "1.2.0", 3445 | "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.2.0.tgz", 3446 | "integrity": "sha512-6YqyX6ZWEYguAxgZzHGL7SsCeGx3V2TtOTqZz1xSTSWnqsbWwbptafNyvf/ACquZUXV3DANr5BDIwNYe1mN42w==", 3447 | "optional": true, 3448 | "requires": { 3449 | "safe-buffer": "~5.1.0" 3450 | } 3451 | } 3452 | } 3453 | }, 3454 | "tough-cookie": { 3455 | "version": "2.4.3", 3456 | "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.4.3.tgz", 3457 | "integrity": "sha512-Q5srk/4vDM54WJsJio3XNn6K2sCG+CQ8G5Wz6bZhRZoAe/+TxjWB/GlFAnYEbkYVlON9FMk/fE3h2RLpPXo4lQ==", 3458 | "optional": true, 3459 | "requires": { 3460 | "psl": "^1.1.24", 3461 | "punycode": "^1.4.1" 3462 | }, 3463 | "dependencies": { 3464 | "punycode": { 3465 | "version": "1.4.1", 3466 | "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.4.1.tgz", 3467 | "integrity": "sha1-wNWmOycYgArY4esPpSachN1BhF4=", 3468 | "optional": true 3469 | } 3470 | } 3471 | }, 3472 | "tslib": { 3473 | "version": "1.9.0", 3474 | "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.9.0.tgz", 3475 | "integrity": "sha512-f/qGG2tUkrISBlQZEjEqoZ3B2+npJjIf04H1wuAv9iA8i04Icp+61KRXxFdha22670NJopsZCIjhC3SnjPRKrQ==" 3476 | }, 3477 | "tunnel-agent": { 3478 | "version": "0.6.0", 3479 | "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz", 3480 | "integrity": "sha1-J6XeoGs2sEoKmWZ3SykIaPD8QP0=", 3481 | "optional": true, 3482 | "requires": { 3483 | "safe-buffer": "^5.0.1" 3484 | } 3485 | }, 3486 | "tweetnacl": { 3487 | "version": "0.14.5", 3488 | "resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-0.14.5.tgz", 3489 | "integrity": "sha1-WuaBd/GS1EViadEIr6k/+HQ/T2Q=", 3490 | "optional": true 3491 | }, 3492 | "type-is": { 3493 | "version": "1.6.16", 3494 | "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.16.tgz", 3495 | "integrity": "sha512-HRkVv/5qY2G6I8iab9cI7v1bOIdhm94dVjQCPFElW9W+3GeDOSHmy2EBYe4VTApuzolPcmgFTN3ftVJRKR2J9Q==", 3496 | "requires": { 3497 | "media-typer": "0.3.0", 3498 | "mime-types": "~2.1.18" 3499 | } 3500 | }, 3501 | "typedarray": { 3502 | "version": "0.0.6", 3503 | "resolved": "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz", 3504 | "integrity": "sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c=", 3505 | "optional": true 3506 | }, 3507 | "unique-string": { 3508 | "version": "1.0.0", 3509 | "resolved": "https://registry.npmjs.org/unique-string/-/unique-string-1.0.0.tgz", 3510 | "integrity": "sha1-nhBXzKhRq7kzmPizOuGHuZyuwRo=", 3511 | "optional": true, 3512 | "requires": { 3513 | "crypto-random-string": "^1.0.0" 3514 | } 3515 | }, 3516 | "unpipe": { 3517 | "version": "1.0.0", 3518 | "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", 3519 | "integrity": "sha1-sr9O6FFKrmFltIF4KdIbLvSZBOw=" 3520 | }, 3521 | "uri-js": { 3522 | "version": "4.2.2", 3523 | "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.2.2.tgz", 3524 | "integrity": "sha512-KY9Frmirql91X2Qgjry0Wd4Y+YTdrdZheS8TFwvkbLWf/G5KNJDCh6pKL5OZctEW4+0Baa5idK2ZQuELRwPznQ==", 3525 | "optional": true, 3526 | "requires": { 3527 | "punycode": "^2.1.0" 3528 | } 3529 | }, 3530 | "util-deprecate": { 3531 | "version": "1.0.2", 3532 | "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", 3533 | "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=", 3534 | "optional": true 3535 | }, 3536 | "utils-merge": { 3537 | "version": "1.0.1", 3538 | "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz", 3539 | "integrity": "sha1-n5VxD1CiZ5R7LMwSR0HBAoQn5xM=" 3540 | }, 3541 | "uuid": { 3542 | "version": "3.3.2", 3543 | "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.3.2.tgz", 3544 | "integrity": "sha512-yXJmeNaw3DnnKAOKJE51sL/ZaYfWJRl1pK9dr19YFCu0ObS231AB1/LbqTKRAQ5kw8A90rA6fr4riOUpTZvQZA==", 3545 | "optional": true 3546 | }, 3547 | "vary": { 3548 | "version": "1.1.2", 3549 | "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", 3550 | "integrity": "sha1-IpnwLG3tMNSllhsLn3RSShj2NPw=" 3551 | }, 3552 | "verror": { 3553 | "version": "1.10.0", 3554 | "resolved": "https://registry.npmjs.org/verror/-/verror-1.10.0.tgz", 3555 | "integrity": "sha1-OhBcoXBTr1XW4nDB+CiGguGNpAA=", 3556 | "optional": true, 3557 | "requires": { 3558 | "assert-plus": "^1.0.0", 3559 | "core-util-is": "1.0.2", 3560 | "extsprintf": "^1.2.0" 3561 | } 3562 | }, 3563 | "walkdir": { 3564 | "version": "0.0.12", 3565 | "resolved": "https://registry.npmjs.org/walkdir/-/walkdir-0.0.12.tgz", 3566 | "integrity": "sha512-HFhaD4mMWPzFSqhpyDG48KDdrjfn409YQuVW7ckZYhW4sE87mYtWifdB/+73RA7+p4s4K18n5Jfx1kHthE1gBw==", 3567 | "optional": true 3568 | }, 3569 | "websocket-driver": { 3570 | "version": "0.7.0", 3571 | "resolved": "https://registry.npmjs.org/websocket-driver/-/websocket-driver-0.7.0.tgz", 3572 | "integrity": "sha1-DK+dLXVdk67gSdS90NP+LMoqJOs=", 3573 | "requires": { 3574 | "http-parser-js": ">=0.4.0", 3575 | "websocket-extensions": ">=0.1.1" 3576 | } 3577 | }, 3578 | "websocket-extensions": { 3579 | "version": "0.1.3", 3580 | "resolved": "https://registry.npmjs.org/websocket-extensions/-/websocket-extensions-0.1.3.tgz", 3581 | "integrity": "sha512-nqHUnMXmBzT0w570r2JpJxfiSD1IzoI+HGVdd3aZ0yNi3ngvQ4jv1dtHt5VGxfI2yj5yqImPhOK4vmIh2xMbGg==" 3582 | }, 3583 | "whatwg-fetch": { 3584 | "version": "3.0.0", 3585 | "resolved": "https://registry.npmjs.org/whatwg-fetch/-/whatwg-fetch-3.0.0.tgz", 3586 | "integrity": "sha512-9GSJUgz1D4MfyKU7KRqwOjXCXTqWdFNvEr7eUBYchQiVc744mqK/MzXPNR2WsPkmkOa4ywfg8C2n8h+13Bey1Q==" 3587 | }, 3588 | "window-size": { 3589 | "version": "0.1.4", 3590 | "resolved": "https://registry.npmjs.org/window-size/-/window-size-0.1.4.tgz", 3591 | "integrity": "sha1-+OGqHuWlPsW/FR/6CXQqatdpeHY=", 3592 | "optional": true 3593 | }, 3594 | "wrap-ansi": { 3595 | "version": "2.1.0", 3596 | "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-2.1.0.tgz", 3597 | "integrity": "sha1-2Pw9KE3QV5T+hJc8rs3Rz4JP3YU=", 3598 | "optional": true, 3599 | "requires": { 3600 | "string-width": "^1.0.1", 3601 | "strip-ansi": "^3.0.1" 3602 | } 3603 | }, 3604 | "wrappy": { 3605 | "version": "1.0.2", 3606 | "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", 3607 | "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=", 3608 | "optional": true 3609 | }, 3610 | "write-file-atomic": { 3611 | "version": "2.4.2", 3612 | "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-2.4.2.tgz", 3613 | "integrity": "sha512-s0b6vB3xIVRLWywa6X9TOMA7k9zio0TMOsl9ZnDkliA/cfJlpHXAscj0gbHVJiTdIuAYpIyqS5GW91fqm6gG5g==", 3614 | "optional": true, 3615 | "requires": { 3616 | "graceful-fs": "^4.1.11", 3617 | "imurmurhash": "^0.1.4", 3618 | "signal-exit": "^3.0.2" 3619 | } 3620 | }, 3621 | "xdg-basedir": { 3622 | "version": "3.0.0", 3623 | "resolved": "https://registry.npmjs.org/xdg-basedir/-/xdg-basedir-3.0.0.tgz", 3624 | "integrity": "sha1-SWsswQnsqNus/i3HK2A8F8WHCtQ=", 3625 | "optional": true 3626 | }, 3627 | "xmlhttprequest": { 3628 | "version": "1.8.0", 3629 | "resolved": "https://registry.npmjs.org/xmlhttprequest/-/xmlhttprequest-1.8.0.tgz", 3630 | "integrity": "sha1-Z/4HXFwk/vOfnWX197f+dRcZaPw=" 3631 | }, 3632 | "xtend": { 3633 | "version": "4.0.1", 3634 | "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.1.tgz", 3635 | "integrity": "sha1-pcbVMr5lbiPbgg77lDofBJmNY68=" 3636 | }, 3637 | "y18n": { 3638 | "version": "3.2.1", 3639 | "resolved": "https://registry.npmjs.org/y18n/-/y18n-3.2.1.tgz", 3640 | "integrity": "sha1-bRX7qITAhnnA136I53WegR4H+kE=", 3641 | "optional": true 3642 | }, 3643 | "yallist": { 3644 | "version": "3.0.3", 3645 | "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.0.3.tgz", 3646 | "integrity": "sha512-S+Zk8DEWE6oKpV+vI3qWkaK+jSbIK86pCwe2IF/xwIpQ8jEuxpw9NyaGjmp9+BoJv5FV2piqCDcoCtStppiq2A==", 3647 | "optional": true 3648 | }, 3649 | "yargs": { 3650 | "version": "3.32.0", 3651 | "resolved": "https://registry.npmjs.org/yargs/-/yargs-3.32.0.tgz", 3652 | "integrity": "sha1-AwiOnr+edWtpdRYR0qXvWRSCyZU=", 3653 | "requires": { 3654 | "camelcase": "^2.0.1", 3655 | "cliui": "^3.0.3", 3656 | "decamelize": "^1.1.1", 3657 | "os-locale": "^1.4.0", 3658 | "string-width": "^1.0.1", 3659 | "window-size": "^0.1.4", 3660 | "y18n": "^3.2.0" 3661 | } 3662 | } 3663 | } 3664 | } 3665 | -------------------------------------------------------------------------------- /functions/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "functions", 3 | "description": "Cloud Functions for Firebase", 4 | "scripts": { 5 | "serve": "firebase serve --only functions", 6 | "shell": "firebase functions:shell", 7 | "start": "npm run shell", 8 | "deploy": "firebase deploy --only functions", 9 | "logs": "firebase functions:log" 10 | }, 11 | "dependencies": { 12 | "axios": "^0.18.1", 13 | "express": "^4.16.4", 14 | "firebase-admin": "~7.0.0", 15 | "firebase-functions": "^2.2.0", 16 | "geofirestore": "^3.2.2" 17 | }, 18 | "private": true 19 | } 20 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "react-native-community-maps", 3 | "main": "node_modules/expo/AppEntry.js", 4 | "private": true, 5 | "scripts": { 6 | "start": "expo start", 7 | "android": "expo start --android", 8 | "ios": "expo start --ios", 9 | "eject": "expo eject" 10 | }, 11 | "dependencies": { 12 | "@babel/runtime": "^7.1.5", 13 | "@expo/react-native-action-sheet": "^2.1.0", 14 | "deepmerge": "^3.2.0", 15 | "expo": "^31.0.2", 16 | "firebase": "^5.5.8", 17 | "geofirestore": "github:geofirestore/geofirestore-js#dev", 18 | "react": "16.5.0", 19 | "react-native": "https://github.com/expo/react-native/archive/sdk-31.0.0.tar.gz", 20 | "react-native-emoji-selector": "^0.1.6", 21 | "react-native-expo-image-cache": "^3.2.0", 22 | "react-native-image-pan-zoom": "^2.1.11", 23 | "react-native-paper": "^2.12.0", 24 | "react-navigation": "^3.3.2" 25 | }, 26 | "devDependencies": { 27 | "babel-preset-expo": "^5.0.0" 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /src/App.js: -------------------------------------------------------------------------------- 1 | import React from 'react' 2 | import { 3 | ActionSheetProvider, 4 | } from '@expo/react-native-action-sheet' 5 | 6 | import { 7 | Provider as PaperProvider, 8 | } from 'react-native-paper' 9 | 10 | import AuthContainer from './containers/AuthContainer' 11 | import DataContainer from './containers/DataContainer' 12 | import NotificationContainer from './containers/NotificationContainer' 13 | import Navigator from './containers/Navigator' 14 | import theme from './lib/theme' 15 | 16 | export default () => ( 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | ) -------------------------------------------------------------------------------- /src/components/AddItemScreen.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { 3 | StyleSheet, 4 | Text, 5 | View, 6 | } from 'react-native'; 7 | 8 | import { 9 | MapView, 10 | } from 'expo'; 11 | 12 | import { 13 | HelperText, 14 | } from 'react-native-paper'; 15 | 16 | import { 17 | defaultEmoji, 18 | noEmojiPicker, 19 | } from '../lib/options' 20 | 21 | import CameraView from './CameraView' 22 | import EmojiOverlay from './EmojiOverlay' 23 | 24 | const DELTA = 0.001 25 | 26 | export default class AddItemScreen extends React.Component { 27 | state = { 28 | emoji: defaultEmoji, 29 | showEmojiPicker: false, 30 | } 31 | 32 | componentDidMount() { 33 | const { 34 | navigation 35 | } = this.props 36 | 37 | const { 38 | longitude, 39 | latitude, 40 | } = navigation.getParam('coordinates') 41 | 42 | this.setState({ 43 | coordinates: { 44 | longitude, 45 | latitude, 46 | }, 47 | initialRegion: { 48 | longitude, 49 | latitude, 50 | latitudeDelta: DELTA, 51 | longitudeDelta: DELTA, 52 | }, 53 | didMount: true, 54 | }) 55 | 56 | navigation.setParams({ 57 | onSave: this.onSave, 58 | }) 59 | } 60 | 61 | onRegionChangeComplete = ({ longitude, latitude }) => { 62 | this.setState({ 63 | coordinates: { 64 | longitude, 65 | latitude, 66 | } 67 | }) 68 | } 69 | 70 | onEmojiSelected = emoji => { 71 | this.setState({ 72 | emoji, 73 | showEmojiPicker: false, 74 | }) 75 | } 76 | 77 | onCancel = () => { 78 | this.props.onCancel() 79 | } 80 | 81 | onSetPicture = picture => { 82 | this.setState({ 83 | picture 84 | }) 85 | 86 | this.props.navigation.setParams({ 87 | canSave: !!picture, 88 | }) 89 | } 90 | 91 | toggleEmojiPicker = () => { 92 | const { 93 | showEmojiPicker, 94 | } = this.state 95 | 96 | this.setState({ 97 | showEmojiPicker: !showEmojiPicker, 98 | }) 99 | } 100 | 101 | onSave = () => { 102 | const { 103 | picture, 104 | emoji, 105 | coordinates, 106 | } = this.state 107 | 108 | this.props.data.addNewItem({ 109 | picture, 110 | emoji, 111 | coordinates, 112 | }) 113 | 114 | this.props.navigation.goBack() 115 | } 116 | 117 | render() { 118 | const { 119 | initialRegion, 120 | coordinates, 121 | didMount, 122 | showEmojiPicker, 123 | emoji, 124 | picture, 125 | } = this.state 126 | 127 | if (!didMount) return 128 | 129 | return ( 130 | 132 | 133 | 136 | 138 | 145 | 147 | Drag the map to adjust location 148 | 149 | 152 | {emoji} 153 | 154 | 155 | 160 | 161 | ); 162 | } 163 | } 164 | 165 | 166 | const styles = StyleSheet.create({ 167 | container: { 168 | flex: 1, 169 | }, 170 | mapContainer: { 171 | flex: 1, 172 | alignItems: 'center', 173 | justifyContent: 'center', 174 | }, 175 | map: { 176 | ...StyleSheet.absoluteFill, 177 | }, 178 | camera: { 179 | flex: 1, 180 | }, 181 | emojiPicker: { 182 | height: 400, 183 | }, 184 | emoji: { 185 | fontSize: 50, 186 | }, 187 | text: { 188 | position: 'absolute', 189 | top: 0 190 | } 191 | }); 192 | -------------------------------------------------------------------------------- /src/components/CameraView.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | 3 | import { 4 | StyleSheet, 5 | Alert, 6 | View, 7 | TouchableHighlight, 8 | ImageBackground, 9 | } from 'react-native'; 10 | 11 | import { 12 | Camera, 13 | Permissions, 14 | Linking, 15 | ImagePicker, 16 | } from 'expo'; 17 | 18 | import { 19 | IconButton, 20 | HelperText, 21 | Button, 22 | FAB, 23 | } from 'react-native-paper' 24 | 25 | import { 26 | MaterialIcons, 27 | } from '@expo/vector-icons'; 28 | 29 | export default class CameraView extends React.Component { 30 | state = { 31 | hasCameraPermission: null, 32 | shouldFlash: false, 33 | }; 34 | 35 | async componentDidMount() { 36 | const { 37 | status 38 | } = await Permissions.askAsync(Permissions.CAMERA); 39 | 40 | this.setState({ 41 | hasCameraPermission: status === 'granted' 42 | }); 43 | } 44 | 45 | snap = async () => { 46 | if (this.camera) { 47 | this.camera.pausePreview(); 48 | 49 | await this.camera.takePictureAsync({ 50 | exif: true, 51 | onPictureSaved: this.setPicture 52 | }); 53 | 54 | } 55 | }; 56 | 57 | onSelectImage = async () => { 58 | const { 59 | status 60 | } = await Permissions.askAsync(Permissions.CAMERA_ROLL); 61 | 62 | if (status !== 'granted') 63 | return Alert.alert( 64 | 'Camera roll permissions', 65 | 'Oops! We need permission to access your camera roll. Go to settings to enable it', 66 | [{ 67 | text: 'Cancel', 68 | type: 'cancel', 69 | }, { 70 | text: 'Open Settings', 71 | onPress: () => Linking.openURL('app-settings:'), 72 | }] 73 | ) 74 | 75 | const picture = await ImagePicker.launchImageLibraryAsync({ 76 | mediaTypes: ImagePicker.MediaTypeOptions.Images, 77 | allowsEditing: true, 78 | }) 79 | 80 | if (!picture.cancelled) 81 | this.setPicture(picture) 82 | } 83 | 84 | setPicture = picture => { 85 | this.setState({ 86 | picture, 87 | }) 88 | 89 | this.props.onSetPicture(picture) 90 | } 91 | 92 | clearPicture = () => { 93 | this.setPicture() 94 | } 95 | 96 | renderPicture = () => { 97 | const { 98 | picture 99 | } = this.state 100 | 101 | return ( 102 | 106 | 110 | 111 | ) 112 | } 113 | 114 | toggleFlash = () => { 115 | this.setState({ 116 | shouldFlash: !this.state.shouldFlash 117 | }) 118 | } 119 | 120 | openSettings = () => Linking.openURL('app-settings:') 121 | 122 | renderCamera = () => { 123 | const { 124 | shouldFlash 125 | } = this.state 126 | 127 | return ( 128 | this.camera = ref } > 134 | 135 | 141 | 142 | 148 | 149 | 153 | 154 | 155 | ) 156 | } 157 | 158 | render() { 159 | const { 160 | hasCameraPermission, 161 | picture, 162 | } = this.state; 163 | 164 | const { 165 | style, 166 | } = this.props 167 | 168 | if (hasCameraPermission === null) 169 | return 170 | 171 | if (!hasCameraPermission) 172 | return ( 173 | 174 | 176 | Oops! We don't have permission to access your camera. 177 | 178 | 182 | 183 | 187 | 188 | ) 189 | 190 | return ( 191 | 192 | { picture 193 | ? this.renderPicture() 194 | : this.renderCamera() 195 | } 196 | 197 | ); 198 | } 199 | } 200 | 201 | 202 | const styles = StyleSheet.create({ 203 | container: { 204 | flex: 1, 205 | justifyContent: 'flex-end', 206 | alignItems: 'center', 207 | }, 208 | 209 | snapButton: { 210 | margin: 10, 211 | backgroundColor: 'red', 212 | }, 213 | 214 | toggleFlash: { 215 | position: 'absolute', 216 | top: 5, 217 | left: 5, 218 | borderRadius: 25, 219 | opacity: 0.7, 220 | }, 221 | 222 | selectImage: { 223 | position: 'absolute', 224 | bottom: 5, 225 | right: 5, 226 | borderRadius: 25, 227 | opacity: 0.7, 228 | }, 229 | 230 | clearPicture: { 231 | margin: 10, 232 | }, 233 | 234 | cameraAlert: { 235 | alignItems: 'center', 236 | justifyContent: 'center', 237 | }, 238 | }); 239 | -------------------------------------------------------------------------------- /src/components/Comments.js: -------------------------------------------------------------------------------- 1 | import React from 'react' 2 | 3 | import { 4 | View, 5 | StyleSheet, 6 | FlatList, 7 | SafeAreaView, 8 | } from 'react-native' 9 | 10 | import { 11 | Text, 12 | Caption, 13 | Button, 14 | TextInput, 15 | List, 16 | } from 'react-native-paper'; 17 | 18 | import { 19 | newMsgPlaceholder 20 | } from '../lib/options' 21 | 22 | const sleep = ms => new Promise(resolve => setTimeout(resolve, ms)) 23 | 24 | const randomPlaceholder = () => newMsgPlaceholder[Math.floor(Math.random() * newMsgPlaceholder.length)] 25 | 26 | export default class Comments extends React.Component { 27 | state={ 28 | loading: false, 29 | error: null, 30 | body: '' 31 | } 32 | 33 | onSubmit = async () => { 34 | try { 35 | const { 36 | onSubmit, 37 | } = this.props 38 | 39 | const { 40 | body, 41 | } = this.state 42 | 43 | this.setState({ 44 | loading: true, 45 | }) 46 | 47 | await onSubmit(body) 48 | 49 | this.setState({ 50 | loading: false, 51 | error: null, 52 | body: '', 53 | }) 54 | this.scrollToEnd() 55 | } catch (error) { 56 | console.log(error) 57 | 58 | this.setState({ 59 | loading: false, 60 | error, 61 | }) 62 | } 63 | } 64 | 65 | onChangeText = body => { 66 | this.setState({ 67 | body 68 | }) 69 | } 70 | 71 | scrollToEnd = async () => { 72 | await sleep(300) 73 | this.listRef.scrollToEnd() 74 | } 75 | 76 | renderItem = ({ item }) => { 77 | const { 78 | users, 79 | } = this.props 80 | 81 | const { 82 | username='Anonymous', 83 | } = users[item.userId] || {} 84 | 85 | return ( 86 | 90 | ) 91 | 92 | } 93 | 94 | render() { 95 | const { 96 | body, 97 | loading, 98 | } = this.state 99 | 100 | const { 101 | messages, 102 | style, 103 | } = this.props 104 | 105 | return ( 106 | 108 | this.listRef = r} 110 | data={messages} 111 | keyExtractor={item => item.id} 112 | renderItem={this.renderItem}/> 113 | 114 | 116 | 126 | 134 | 135 | 136 | 137 | ) 138 | } 139 | } 140 | 141 | const styles = StyleSheet.create({ 142 | container: { 143 | flex: 1, 144 | }, 145 | messagesContainer: { 146 | flex: 1, 147 | }, 148 | newMessageRow: { 149 | flexDirection: 'row', 150 | borderTopWidth: 0.5, 151 | borderTopColor: 'grey', 152 | }, 153 | bodyInput: { 154 | flex: 1, 155 | }, 156 | sendButton: { 157 | justifyContent: 'center', 158 | }, 159 | displayName: { 160 | fontWeight: 'bold', 161 | paddingHorizontal: 10, 162 | }, 163 | body: { 164 | fontWeight: 'normal', 165 | marginHorizontal: 20, 166 | }, 167 | comment: { 168 | padding: 0, 169 | } 170 | }) -------------------------------------------------------------------------------- /src/components/ConvertAnonymousUser.js: -------------------------------------------------------------------------------- 1 | import React from 'react' 2 | 3 | import { 4 | View, 5 | StyleSheet, 6 | KeyboardAvoidingView, 7 | Platform, 8 | } from 'react-native' 9 | 10 | import { 11 | TextInput, 12 | ActivityIndicator, 13 | HelperText, 14 | Button, 15 | } from 'react-native-paper' 16 | 17 | import { Header } from 'react-navigation'; 18 | 19 | import UsernameGenerator from '../lib/usernameGenerator' 20 | 21 | export default class ConvertAnonymouseUser extends React.Component { 22 | state={ 23 | username: null, 24 | email: null, 25 | password: null, 26 | usernamePlaceholder: null, 27 | } 28 | 29 | componentDidMount = async () => { 30 | const usernamePlaceholder = await UsernameGenerator.generate() 31 | this.setState({ 32 | usernamePlaceholder, 33 | }) 34 | } 35 | 36 | onConvert = async () => { 37 | const success = await this.props.auth.onConvertAnonymousUser(this.state) 38 | if (success) 39 | this.props.navigation.goBack() 40 | } 41 | 42 | render() { 43 | const { 44 | auth: { 45 | loading, 46 | error, 47 | } 48 | } = this.props 49 | 50 | const { 51 | username, 52 | email, 53 | password, 54 | usernamePlaceholder, 55 | } = this.state 56 | 57 | return ( 58 | 63 | 65 | this.setState({ email })} /> 72 | 73 | this.setState({ username })} /> 80 | 81 | this.setState({ password })} /> 88 | 89 | 92 | { error && error.message } 93 | 94 | 95 | 101 | 102 | 104 | 105 | 106 | 107 | ) 108 | } 109 | } 110 | 111 | const styles = StyleSheet.create({ 112 | container: { 113 | flex: 1, 114 | justifyContent: 'center', 115 | }, 116 | innerContainer: { 117 | flex: 1, 118 | marginHorizontal: 40, 119 | justifyContent: 'center', 120 | }, 121 | input: { 122 | marginVertical: 10, 123 | }, 124 | error: { 125 | color: 'red', 126 | margin: 10, 127 | }, 128 | loading: { 129 | opacity: 0.5, 130 | alignItems: 'center', 131 | justifyContent: 'center', 132 | } 133 | }) -------------------------------------------------------------------------------- /src/components/EmojiOverlay.js: -------------------------------------------------------------------------------- 1 | import React from 'react' 2 | 3 | import { 4 | View, 5 | Modal, 6 | TouchableOpacity, 7 | StyleSheet, 8 | } from 'react-native' 9 | 10 | import EmojiSelector from 'react-native-emoji-selector' 11 | 12 | 13 | export default ({ 14 | visible, 15 | style, 16 | onEmojiSelected, 17 | onTapOutside, 18 | }) => ( 19 | 24 | 27 | 29 | 31 | 32 | 33 | 34 | ) 35 | 36 | const styles = StyleSheet.create({ 37 | container: { 38 | flex: 1, 39 | backgroundColor: '#ffffff96', 40 | alignItems: 'center', 41 | justifyContent: 'center', 42 | } 43 | }) 44 | -------------------------------------------------------------------------------- /src/components/ItemScreen.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { Header } from 'react-navigation'; 3 | 4 | import { 5 | StyleSheet, 6 | View, 7 | TouchableHighlight, 8 | Dimensions, 9 | KeyboardAvoidingView, 10 | Platform, 11 | Share, 12 | Alert, 13 | } from 'react-native'; 14 | 15 | import { Modal, Portal } from 'react-native-paper'; 16 | 17 | import { 18 | Image, 19 | } from 'react-native-expo-image-cache' 20 | 21 | import ImageZoom from 'react-native-image-pan-zoom' 22 | 23 | import Comments from './Comments' 24 | 25 | import { 26 | shareUrl 27 | } from '../lib/options' 28 | 29 | const { height, width } = Dimensions.get('window') 30 | 31 | const SIZE = Math.min(height, width) 32 | 33 | export default class ItemScreen extends React.Component { 34 | state = { 35 | id: null, 36 | body: null, 37 | loading: false, 38 | shouldShowModal: false, 39 | } 40 | 41 | componentDidMount() { 42 | const { 43 | navigation, 44 | data: { 45 | setChatRoom, 46 | addToViewedBy, 47 | }, 48 | } = this.props 49 | 50 | const id = navigation.getParam('id') 51 | 52 | setChatRoom(id) 53 | addToViewedBy(id) 54 | 55 | this.setState({ 56 | id 57 | }) 58 | 59 | navigation.setParams({ 60 | onMore: this.onMore, 61 | }) 62 | } 63 | 64 | onMore = () => { 65 | const options = ['Share', 'Flag', 'Cancel']; 66 | const destructiveButtonIndex = 1; 67 | const cancelButtonIndex = 2; 68 | 69 | this.props.showActionSheetWithOptions( 70 | { 71 | options, 72 | cancelButtonIndex, 73 | destructiveButtonIndex, 74 | }, 75 | buttonIndex => { 76 | switch (buttonIndex) { 77 | case 0: 78 | return this.onShare() 79 | case 1: 80 | return this.onFlag() 81 | } 82 | }, 83 | ); 84 | } 85 | 86 | onFlag = () => { 87 | const options = ['Item is missing', 'Spam', 'Offensive content', 'Cancel']; 88 | const cancelButtonIndex = 3; 89 | 90 | this.props.showActionSheetWithOptions( 91 | { 92 | options, 93 | cancelButtonIndex, 94 | }, 95 | buttonIndex => { 96 | if (buttonIndex !== cancelButtonIndex) 97 | Alert.alert('Flagged', 'Thanks for letting us know 🤓') 98 | }, 99 | ); 100 | } 101 | 102 | onShare = () => { 103 | const { 104 | id, 105 | } = this.state 106 | 107 | Share.share({ 108 | message: 'Check out this dope stuff! ' + shareUrl.replace('{id}', id), 109 | }) 110 | } 111 | 112 | onLike = () => { 113 | const { 114 | id, 115 | } = this.state 116 | 117 | const { 118 | data: { 119 | items, 120 | }, 121 | } = this.props 122 | 123 | setLikes(id, items[id].likes + 1) 124 | } 125 | 126 | onDislike = () => { 127 | const { 128 | id, 129 | } = this.state 130 | 131 | const { 132 | data: { 133 | items, 134 | setDislikes, 135 | }, 136 | } = this.props 137 | 138 | setDislikes(id, items[id].dislikes + 1) 139 | } 140 | 141 | onSendMessage = async message => { 142 | const { 143 | id, 144 | } = this.state 145 | 146 | const { 147 | data: { 148 | sendMessage, 149 | }, 150 | } = this.props 151 | 152 | await sendMessage(id, message) 153 | } 154 | 155 | onToggleModal = () => { 156 | const { 157 | shouldShowModal, 158 | } = this.state 159 | 160 | this.setState({ 161 | shouldShowModal: !shouldShowModal, 162 | }) 163 | } 164 | 165 | 166 | 167 | render() { 168 | 169 | const { 170 | id, 171 | shouldShowModal, 172 | } = this.state 173 | 174 | if (!id) return 175 | 176 | const { 177 | data: { 178 | messages, 179 | items, 180 | users, 181 | }, 182 | } = this.props 183 | 184 | const item = items[id] 185 | 186 | if (!item) return 187 | 188 | const { 189 | picturePreview, 190 | pictureUri, 191 | } = item 192 | 193 | return ( 194 | 198 | 201 | 209 | 210 | 211 | 217 | 218 | 222 | 230 | 238 | 239 | 240 | 241 | 242 | ) 243 | } 244 | } 245 | 246 | 247 | const styles = StyleSheet.create({ 248 | container: { 249 | flex: 1, 250 | justifyContent: 'flex-end', 251 | }, 252 | image: { 253 | flex: 1, 254 | }, 255 | closeButton: { 256 | position: 'absolute', 257 | top: 20, 258 | right: 20, 259 | }, 260 | messages: { 261 | flex: 1, 262 | }, 263 | dislikeButton: { 264 | position: 'absolute', 265 | bottom: 20, 266 | left: 20, 267 | }, 268 | likeButton: { 269 | position: 'absolute', 270 | bottom: 20, 271 | right: 20, 272 | }, 273 | emoji: { 274 | fontSize: 40, 275 | }, 276 | button: { 277 | backgroundColor: 'white', 278 | height: 56, 279 | width: 56, 280 | borderRadius: 28, 281 | alignItems: 'center', 282 | justifyContent: 'center', 283 | shadowColor: "#000", 284 | shadowOffset: { 285 | width: 0, 286 | height: 2, 287 | }, 288 | shadowOpacity: 0.2, 289 | shadowRadius: 2.5, 290 | elevation: 4, 291 | } 292 | }); 293 | -------------------------------------------------------------------------------- /src/components/Login.js: -------------------------------------------------------------------------------- 1 | import React from 'react' 2 | 3 | import { 4 | View, 5 | StyleSheet, 6 | KeyboardAvoidingView, 7 | } from 'react-native' 8 | 9 | import { 10 | TextInput, 11 | ActivityIndicator, 12 | HelperText, 13 | Button, 14 | } from 'react-native-paper' 15 | 16 | import UsernameGenerator from '../lib/usernameGenerator' 17 | 18 | export default class Login extends React.Component { 19 | state={ 20 | username: null, 21 | email: null, 22 | password: null, 23 | screen: 'signup', 24 | usernamePlaceholder: null, 25 | } 26 | 27 | componentDidMount = async () => { 28 | const usernamePlaceholder = await UsernameGenerator.generate() 29 | this.setState({ 30 | usernamePlaceholder, 31 | }) 32 | } 33 | 34 | onLogin = () => this.props.auth.onLogin(this.state) 35 | onSignup = () => this.props.auth.onSignup(this.state) 36 | onAnonymousLogin = () => this.props.auth.onAnonymousLogin() 37 | 38 | renderScene = () => { 39 | const { 40 | auth: { 41 | loading, 42 | error, 43 | } 44 | } = this.props 45 | 46 | const { 47 | username, 48 | email, 49 | password, 50 | screen, 51 | usernamePlaceholder, 52 | } = this.state 53 | 54 | switch (screen) { 55 | case 'login': 56 | return ( 57 | 59 | this.setState({ email })} /> 66 | 67 | this.setState({ password })} /> 74 | 75 | 78 | { error && error.message } 79 | 80 | 81 | 87 | 88 | 90 | 91 | ) 92 | 93 | case 'signup': 94 | return ( 95 | 97 | this.setState({ email })} /> 104 | 105 | this.setState({ username })} /> 112 | 113 | this.setState({ password })} /> 120 | 121 | 124 | { error && error.message } 125 | 126 | 127 | 133 | 134 | 140 | 141 | 143 | 144 | 145 | ) 146 | } 147 | } 148 | 149 | render() { 150 | const { 151 | screen 152 | } = this.state 153 | 154 | return ( 155 | 159 | { this.renderScene() } 160 | 161 | 163 | 169 | 175 | 176 | 177 | ) 178 | } 179 | } 180 | 181 | const styles = StyleSheet.create({ 182 | container: { 183 | flex: 1, 184 | justifyContent: 'center', 185 | }, 186 | innerContainer: { 187 | flex: 1, 188 | marginHorizontal: 40, 189 | justifyContent: 'center', 190 | }, 191 | input: { 192 | marginVertical: 10, 193 | }, 194 | error: { 195 | color: 'red', 196 | margin: 10, 197 | }, 198 | loading: { 199 | opacity: 0.5, 200 | alignItems: 'center', 201 | justifyContent: 'center', 202 | }, 203 | buttonGroup: { 204 | flexDirection: 'row', 205 | }, 206 | button: { 207 | flex: 1, 208 | padding: 10, 209 | } 210 | }) -------------------------------------------------------------------------------- /src/components/MapScreen.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { 3 | StyleSheet, 4 | Text, 5 | View, 6 | TouchableHighlight, 7 | ActivityIndicator, 8 | Alert, 9 | Linking, 10 | } from 'react-native'; 11 | 12 | import { 13 | MapView, 14 | Location, 15 | Permissions, 16 | } from 'expo' 17 | 18 | import { 19 | FAB, 20 | } from 'react-native-paper' 21 | 22 | const DELTA = 0.001 23 | 24 | export default class App extends React.Component { 25 | state={ 26 | userCoordinates: null, 27 | } 28 | 29 | async componentDidMount() { 30 | 31 | 32 | this.props.navigation.setParams({ 33 | onShowSettings: this.onShowSettings, 34 | }) 35 | 36 | let { status } = await Permissions.askAsync(Permissions.LOCATION); 37 | this.setState({ 38 | permissionStatus: status, 39 | }) 40 | 41 | if (status !== 'granted') return 42 | this.locationUnsubscribe = Location.watchPositionAsync({}, this.onUserLocationChange) 43 | } 44 | 45 | componentWillUnmount() { 46 | this.locationUnsubscribe && this.locationUnsubscribe() 47 | } 48 | 49 | onUserLocationChange = (res) => { 50 | const { coords } = res 51 | if (!this.state.userCoordinates) 52 | this.zoomToCoordinates(coords) 53 | 54 | this.setState({ 55 | userCoordinates: coords 56 | }) 57 | } 58 | 59 | 60 | renderMarker = id => { 61 | const { 62 | auth: { 63 | user, 64 | }, 65 | data: { 66 | items, 67 | }={}, 68 | } = this.props 69 | 70 | const { 71 | coordinates, 72 | emoji, 73 | viewedBy=[], 74 | } = items[id] 75 | 76 | 77 | 78 | return ( 79 | this.onShowItem(id) } 82 | coordinate={coordinates}> 83 | this.onShowItem(id) }> 89 | { emoji } 90 | 91 | 92 | ) 93 | } 94 | 95 | zoomToUser = () => { 96 | const { 97 | userCoordinates, 98 | permissionStatus, 99 | } = this.state 100 | 101 | if (permissionStatus !== 'granted') { 102 | this.alertPermissions() 103 | return 104 | } 105 | 106 | if (!userCoordinates) 107 | return 108 | 109 | this.zoomToCoordinates(userCoordinates) 110 | } 111 | 112 | zoomToCoordinates = (coordinates) => { 113 | if (!this.mapRef) return 114 | 115 | this.mapRef.animateToRegion({ 116 | ...coordinates, 117 | latitudeDelta: DELTA, 118 | longitudeDelta: DELTA, 119 | }) 120 | } 121 | 122 | onAddItem = () => { 123 | const { 124 | userCoordinates, 125 | permissionStatus, 126 | } = this.state 127 | 128 | if (permissionStatus !== 'granted') { 129 | this.alertPermissions() 130 | return 131 | } 132 | 133 | if (!userCoordinates) 134 | return 135 | 136 | this.props.navigation.navigate('AddItemScreen', { 137 | coordinates: userCoordinates 138 | }) 139 | } 140 | 141 | alertPermissions = () => { 142 | Alert.alert( 143 | 'Location permissions', 144 | 'Oops! we need your location first. Go to settings to enable it', 145 | [{ 146 | text: 'Cancel', 147 | type: 'cancel', 148 | }, { 149 | text: 'Open Settings', 150 | onPress: () => Linking.openURL('app-settings:'), 151 | }] 152 | ) 153 | } 154 | 155 | onShowItem = id => { 156 | this.props.navigation.navigate('ItemScreen', { 157 | id 158 | }) 159 | } 160 | 161 | onShowSettings = () => { 162 | const { 163 | userCoordinates, 164 | } = this.state 165 | 166 | this.props.navigation.navigate('Settings', { 167 | coordinates: userCoordinates 168 | }) 169 | } 170 | 171 | render() { 172 | const { 173 | userCoordinates, 174 | } = this.state 175 | 176 | const { 177 | data: { 178 | items, 179 | loading, 180 | }={}, 181 | } = this.props 182 | 183 | return ( 184 | 186 | 187 | this.mapRef = r} 189 | style={styles.map} 190 | showsCompass={false} 191 | showsUserLocation={true} 192 | showsPointsOfInterest={false}> 193 | { Object.keys(items).map(this.renderMarker) } 194 | 195 | 196 | 202 | 203 | 210 | 211 | 212 | ); 213 | } 214 | } 215 | 216 | 217 | const styles = StyleSheet.create({ 218 | container: { 219 | flex: 1, 220 | }, 221 | map: { 222 | ...StyleSheet.absoluteFill, 223 | }, 224 | myLocationFab: { 225 | position: 'absolute', 226 | right: 15, 227 | top: 15, 228 | }, 229 | addItemFab: { 230 | position: 'absolute', 231 | right: 15, 232 | bottom: 15, 233 | }, 234 | emoji: { 235 | fontSize: 30, 236 | zIndex: 1, 237 | }, 238 | viewed: { 239 | opacity: 0.65, 240 | zIndex: 0, 241 | }, 242 | }); 243 | -------------------------------------------------------------------------------- /src/components/Settings.js: -------------------------------------------------------------------------------- 1 | import React, { 2 | Component 3 | } from 'react'; 4 | 5 | import { 6 | View, 7 | Alert, 8 | StyleSheet, 9 | Image, 10 | } from 'react-native' 11 | 12 | import { 13 | Text, 14 | Switch, 15 | Banner, 16 | } from 'react-native-paper' 17 | 18 | import { 19 | MapView, 20 | } from 'expo' 21 | 22 | const DELTA = 0.005 23 | 24 | export default class Settings extends Component { 25 | state={ 26 | visible: true, 27 | } 28 | 29 | componentDidMount() { 30 | const { 31 | navigation 32 | } = this.props 33 | 34 | navigation.setParams({ 35 | onMore: this.onMore, 36 | }) 37 | 38 | const { 39 | longitude, 40 | latitude, 41 | } = navigation.getParam('coordinates') 42 | 43 | this.setState({ 44 | userRegion: { 45 | longitude, 46 | latitude, 47 | longitudeDelta: DELTA, 48 | latitudeDelta: DELTA, 49 | } 50 | }) 51 | } 52 | 53 | onMore = () => { 54 | const { 55 | showActionSheetWithOptions, 56 | auth: { 57 | onSignOut, 58 | user: { 59 | isAnonymous 60 | } 61 | } 62 | } = this.props 63 | 64 | const options = [ 65 | isAnonymous ? 'Signup' : 'Logout', 66 | 'Delete account', 67 | 'Cancel' 68 | ]; 69 | 70 | const destructiveButtonIndex = 1; 71 | const cancelButtonIndex = 2; 72 | 73 | showActionSheetWithOptions( 74 | { 75 | options, 76 | cancelButtonIndex, 77 | destructiveButtonIndex, 78 | }, 79 | buttonIndex => { 80 | switch (buttonIndex) { 81 | case 0: 82 | return isAnonymous ? this.onSignUp() : onSignOut() 83 | case 1: 84 | return this.onDeleteAccount() 85 | } 86 | }, 87 | ); 88 | } 89 | 90 | onSignUp = () => { 91 | this.props.navigation.navigate('ConvertAnonymousUser') 92 | } 93 | 94 | onDeleteAccount = () => { 95 | const { 96 | auth: { 97 | onDeleteUser 98 | } 99 | } = this.props 100 | 101 | Alert.alert( 102 | 'Are you sure?', 103 | 'You can\'t undo this action ', 104 | [ 105 | {text: 'Delete account', onPress: onDeleteUser }, 106 | {text: 'Cancel', style: 'cancel'}, 107 | ], 108 | ) 109 | 110 | } 111 | 112 | render() { 113 | const { 114 | userRegion 115 | } = this.state 116 | 117 | const { 118 | notification: { 119 | region, 120 | shouldNotify, 121 | setRegion, 122 | setShouldNotify, 123 | isLoading, 124 | }, 125 | auth: { 126 | user: { 127 | isAnonymous, 128 | }, 129 | } 130 | } = this.props 131 | 132 | return ( 133 | 135 | 136 | { isAnonymous && 137 | this.setState({ visible: false }), 143 | }, 144 | { 145 | label: 'Signup', 146 | onPress: this.onSignUp, 147 | }, 148 | ]} 149 | > 150 | { `You're currently signed in as an anonymous user.\nSIGNUP to select a username and password.` } 151 | 152 | } 153 | 154 | 156 | 158 | Notify me when new stuff is posted 159 | 162 | 163 | 164 | { shouldNotify && 165 | 167 | 183 | 186 | Move to set notification area 187 | { isLoading && Saving... } 188 | 189 | 190 | } 191 | 192 | 193 | ) 194 | } 195 | } 196 | 197 | const styles = StyleSheet.create({ 198 | container: { 199 | flex: 1, 200 | }, 201 | innerContainer: { 202 | flex: 1, 203 | padding: 20, 204 | }, 205 | optionRow: { 206 | flexDirection: 'row', 207 | justifyContent: 'space-between', 208 | alignItems: 'center', 209 | marginBottom: 10, 210 | }, 211 | map: { 212 | aspectRatio: 1, 213 | }, 214 | overlay: { 215 | ...StyleSheet.absoluteFill, 216 | backgroundColor: 'transparent', 217 | borderRadius: 500, 218 | borderWidth: 2, 219 | borderColor: '#696969', 220 | alignItems: 'center', 221 | opacity: 0.5, 222 | padding: 20, 223 | } 224 | }) -------------------------------------------------------------------------------- /src/containers/AddItemScreen.js: -------------------------------------------------------------------------------- 1 | import { 2 | DataContainerHoc 3 | } from './DataContainer' 4 | 5 | import AddItemScreen from '../components/AddItemScreen' 6 | 7 | export default DataContainerHoc(AddItemScreen) 8 | -------------------------------------------------------------------------------- /src/containers/AuthContainer.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | 3 | import { 4 | AppLoading 5 | } from 'expo' 6 | 7 | import { 8 | auth, 9 | db, 10 | EmailAuthProvider, 11 | } from '../lib/firebase' 12 | 13 | import Login from '../components/Login' 14 | 15 | import wrapInTry from '../lib/wrapInTry' 16 | import UsernameGenerator from '../lib/usernameGenerator' 17 | 18 | const AuthContext = React.createContext({ 19 | user: null, 20 | loading: false, 21 | error: null, 22 | }); 23 | 24 | const validateUsername = username => { 25 | if (!/^\w{6,20}$/.test(username)) 26 | throw new Error('Username must be 6-20 characters. Only letters, numbers, and underscores.') 27 | } 28 | 29 | export default class AuthContainer extends React.Component { 30 | state = { 31 | user: null, 32 | loading: false, 33 | error: null, 34 | } 35 | 36 | componentDidMount = () => { 37 | this.unsubscribeAuthState = auth.onAuthStateChanged(currentUser => { 38 | if (!currentUser) { 39 | this.setState({ 40 | user: null, 41 | isReady: true 42 | }) 43 | return 44 | } 45 | 46 | this.unsubscribeUser = db.collection('users').doc(currentUser.uid) 47 | .onSnapshot(doc => { 48 | this.setState({ 49 | user: { 50 | id: doc.id, 51 | isAnonymous: currentUser.isAnonymous, 52 | ...doc.data(), 53 | }, 54 | isReady: true, 55 | }) 56 | }, e => console.log('CAUGHT', e)) 57 | }) 58 | 59 | const wrapWithState = wrapInTry(state => this.setState(state)) 60 | 61 | this.onLogin = wrapWithState(this.onLogin) 62 | this.onSignup = wrapWithState(this.onSignup) 63 | this.onSignOut = wrapWithState(this.onSignOut) 64 | this.onDeleteUser = wrapWithState(this.onDeleteUser) 65 | this.onSetUsername = wrapWithState(this.onSetUsername) 66 | this.onAnonymousLogin = wrapWithState(this.onAnonymousLogin) 67 | this.onConvertAnonymousUser = wrapWithState(this.onConvertAnonymousUser) 68 | } 69 | 70 | 71 | 72 | componentWillUnmount() { 73 | this.unsubscribeUser && this.unsubscribeUser() 74 | this.unsubscribeAuthState && this.unsubscribeAuthState() 75 | } 76 | 77 | onLogin = ({ email, password }) => auth.signInWithEmailAndPassword(email, password) 78 | onSignOut = () => auth.signOut() 79 | 80 | onAnonymousLogin = async () => { 81 | await auth.signInAnonymously() 82 | 83 | const user = auth.currentUser; 84 | const username = await UsernameGenerator.generate() 85 | 86 | await db.collection('users').doc(user.uid).set({ 87 | username 88 | }, { 89 | merge: true 90 | }) 91 | } 92 | 93 | onSignup = async ({ username, email, password }) => { 94 | validateUsername(username) 95 | 96 | await auth.createUserWithEmailAndPassword(email, password) 97 | 98 | const user = auth.currentUser; 99 | 100 | await db.collection('users').doc(user.uid).set({ 101 | username 102 | }, { 103 | merge: true 104 | }) 105 | } 106 | 107 | 108 | 109 | onConvertAnonymousUser = async ({ username, email, password }) => { 110 | validateUsername(username) 111 | var credential = EmailAuthProvider.credential(email, password); 112 | await auth.currentUser.linkAndRetrieveDataWithCredential(credential) 113 | const user = auth.currentUser; 114 | 115 | await db.collection('users').doc(user.uid).set({ 116 | username 117 | }, { 118 | merge: true 119 | }) 120 | } 121 | 122 | onSetUsername = ({ username }) => { 123 | validateUsername(username) 124 | const user = auth.currentUser; 125 | 126 | return db.collection('users').doc(user.uid).set({ 127 | username 128 | }, { 129 | merge: true 130 | }) 131 | } 132 | 133 | 134 | onDeleteUser = async () => { 135 | const user = auth.currentUser 136 | 137 | await db.collection('users').doc(user.uid) 138 | await user.delete() 139 | } 140 | 141 | render() { 142 | const { 143 | isReady, 144 | user, 145 | } = this.state 146 | 147 | if (!isReady) 148 | return 149 | 150 | if (!user) 151 | return 159 | 160 | return ( 161 | 171 | { this.props.children } 172 | 173 | ) 174 | } 175 | } 176 | 177 | export const AuthContainerHoc = (Component) => props => ( 178 | 179 | { context => } 180 | 181 | ) 182 | -------------------------------------------------------------------------------- /src/containers/ConvertAnonymousUser.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | 3 | import { 4 | AuthContainerHoc 5 | } from './AuthContainer' 6 | 7 | import ConvertAnonymousUser from '../components/ConvertAnonymousUser' 8 | 9 | export default AuthContainerHoc( 10 | ConvertAnonymousUser 11 | ) 12 | -------------------------------------------------------------------------------- /src/containers/DataContainer.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | 3 | import { 4 | ImageManipulator 5 | } from 'expo' 6 | 7 | import urlToBlob from '../lib/urlToBlob' 8 | 9 | import { 10 | db, 11 | auth, 12 | storage, 13 | } from '../lib/firebase' 14 | 15 | import FB from 'firebase' 16 | 17 | const { firestore: { GeoPoint, FieldValue } } = FB 18 | 19 | const DataContext = React.createContext({ 20 | items: {}, 21 | messages: [], 22 | loading: false, 23 | error: null, 24 | }); 25 | 26 | const geoPointToObj = geopoint => ({ 27 | longitude: geopoint.longitude, 28 | latitude: geopoint.latitude, 29 | }) 30 | 31 | export default class DataContainer extends React.Component { 32 | state = { 33 | items: {}, 34 | users: {}, 35 | messages: [], 36 | loading: false, 37 | error: null, 38 | } 39 | 40 | componentDidMount() { 41 | this.firebaseUnsubscribe = db.collection('items') 42 | .orderBy('createdAt', 'desc') 43 | .onSnapshot(querySnapshot => { 44 | 45 | var items = {}; 46 | querySnapshot.forEach(async doc => { 47 | const data = doc.data() 48 | 49 | items[doc.id] = { 50 | ...data, 51 | coordinates: geoPointToObj(data.coordinates) 52 | } 53 | }) 54 | 55 | const ids = Object.values(items).map(m => m.userId) 56 | this.loadUsers({ ids }) 57 | 58 | this.setState({ 59 | items: { 60 | ...this.state.items, 61 | ...items, 62 | } 63 | }) 64 | }, e => console.log('CAUGHT', e)) 65 | } 66 | 67 | componentWillUnmount() { 68 | this.firebaseUnsubscribe && this.firebaseUnsubscribe() 69 | } 70 | 71 | loadUsers = async ({ ids }) => { 72 | const existingIds = Object.keys(this.state.users) 73 | const uniqueIds = ids.filter((id, index) => ids.indexOf(id) === index) 74 | const newIds = uniqueIds.filter(id => existingIds.indexOf(id) === -1) 75 | const promises = newIds.map(id => db.collection('users').doc(id).get()) 76 | const results = await Promise.all(promises) 77 | const users = {} 78 | results.forEach(r => { 79 | users[r.id] = r.data() 80 | }) 81 | 82 | this.setState({ 83 | users: { 84 | ...this.state.users, 85 | ...users, 86 | } 87 | }) 88 | } 89 | 90 | addNewItem = async ({ emoji, coordinates, picture }) => { 91 | this.setState({ 92 | loading: true, 93 | }) 94 | 95 | try { 96 | const { 97 | uri, 98 | } = picture 99 | 100 | const { 101 | longitude, 102 | latitude, 103 | } = coordinates 104 | 105 | const filename = uri.substring(uri.lastIndexOf('/') + 1) 106 | 107 | const ref = storage.ref().child(filename) 108 | const blob = await urlToBlob(uri) 109 | 110 | const uploadTask = await ref.put(blob) 111 | const pictureUri = await uploadTask.ref.getDownloadURL() 112 | const { base64 } = await ImageManipulator.manipulateAsync(uri, [{ 113 | resize: { 114 | width: 25, 115 | } 116 | }], { 117 | compress: 0, 118 | base64: true 119 | }) 120 | 121 | await db.collection('items').add({ 122 | emoji, 123 | pictureUri, 124 | createdAt: Date.now(), 125 | picturePreview: base64, 126 | coordinates: new GeoPoint(latitude, longitude), 127 | userId: auth.currentUser.uid, 128 | likes: 1, 129 | dislikes: 0, 130 | viewedBy: [], 131 | }) 132 | 133 | this.setState({ 134 | error: null, 135 | loading: false, 136 | }) 137 | } catch (error) { 138 | console.log(error) 139 | this.setState({ 140 | error, 141 | loading: false, 142 | }) 143 | } 144 | } 145 | 146 | setLikes = (id, likes) => { 147 | db.collection('items').doc(id).update({ 148 | likes 149 | }) 150 | } 151 | 152 | setDislikes = (id, dislikes) => { 153 | db.collection('items').doc(id).update({ 154 | dislikes 155 | }) 156 | } 157 | 158 | addToViewedBy = (id) => { 159 | db.collection('items').doc(id).update({ 160 | viewedBy: FieldValue.arrayUnion(auth.currentUser.uid) 161 | }) 162 | } 163 | 164 | setChatRoom = (id) => { 165 | if (this.chatUnsubscribe) this.chatUnsubscribe() 166 | 167 | this.setState({ 168 | messages: [] 169 | }) 170 | 171 | if (!id) return 172 | 173 | this.chatUnsubscribe = db.collection('rooms') 174 | .doc(id) 175 | .collection('messages') 176 | .orderBy('at', 'asc') 177 | .onSnapshot(querySnapshot => { 178 | 179 | var messages = []; 180 | querySnapshot.forEach(doc => { 181 | messages.push({ 182 | id: doc.id, 183 | ...doc.data(), 184 | }) 185 | }) 186 | 187 | const ids = messages.map(m => m.userId) 188 | this.loadUsers({ ids }) 189 | 190 | this.setState({ 191 | messages 192 | }) 193 | }, e => console.log('CAUGHT', e)) 194 | } 195 | 196 | sendMessage = async (id, body) => { 197 | await db.collection('rooms') 198 | .doc(id) 199 | .collection('messages') 200 | .add({ 201 | body, 202 | userId: auth.currentUser.uid, 203 | at: Date.now(), 204 | }) 205 | } 206 | 207 | 208 | render() { 209 | return ( 210 | 221 | { this.props.children } 222 | 223 | ); 224 | } 225 | } 226 | 227 | export const DataContainerHoc = (Component) => props => ( 228 | 229 | { context => } 230 | 231 | ) 232 | 233 | -------------------------------------------------------------------------------- /src/containers/ItemScreen.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | 3 | import { 4 | DataContainerHoc 5 | } from './DataContainer' 6 | 7 | import { 8 | connectActionSheet, 9 | } from '@expo/react-native-action-sheet'; 10 | 11 | import ItemScreen from '../components/ItemScreen' 12 | 13 | export default DataContainerHoc( 14 | connectActionSheet( 15 | ItemScreen 16 | ) 17 | ) 18 | -------------------------------------------------------------------------------- /src/containers/MapScreen.js: -------------------------------------------------------------------------------- 1 | import { 2 | DataContainerHoc 3 | } from '../containers/DataContainer' 4 | 5 | import { 6 | AuthContainerHoc 7 | } from './AuthContainer' 8 | 9 | import MapScreen from '../components/MapScreen' 10 | 11 | export default AuthContainerHoc( 12 | DataContainerHoc( 13 | MapScreen 14 | ) 15 | ) 16 | -------------------------------------------------------------------------------- /src/containers/Navigator.js: -------------------------------------------------------------------------------- 1 | import React from 'react' 2 | 3 | import { 4 | createStackNavigator, 5 | createAppContainer, 6 | } from 'react-navigation' 7 | 8 | import { 9 | Appbar, 10 | } from 'react-native-paper' 11 | 12 | import MapScreen from './MapScreen' 13 | import ItemScreen from './ItemScreen' 14 | import AddTimescren from './AddItemScreen' 15 | import Settings from './Settings' 16 | import ConvertAnonymousUser from './ConvertAnonymousUser'; 17 | 18 | const noop = () => {} 19 | 20 | const appStack = createStackNavigator({ 21 | MapScreen: { 22 | screen: MapScreen, 23 | navigationOptions: ({ navigation }) => ({ 24 | header: ( 25 | 26 | 27 | 28 | 29 | ), 30 | }) 31 | }, 32 | Settings: { 33 | screen: Settings, 34 | navigationOptions: ({ navigation}) => ({ 35 | header: ( 36 | 37 | navigation.goBack()} /> 38 | 39 | 40 | 41 | ), 42 | }) 43 | }, 44 | ConvertAnonymousUser: { 45 | screen: ConvertAnonymousUser, 46 | navigationOptions: ({ navigation}) => ({ 47 | header: ( 48 | 49 | navigation.goBack()} /> 50 | 51 | ), 52 | }) 53 | }, 54 | ItemScreen: { 55 | screen: ItemScreen, 56 | navigationOptions: ({ navigation }) => ({ 57 | header: ( 58 | 59 | navigation.goBack()} /> 60 | 61 | 62 | 63 | ), 64 | }) 65 | }, 66 | AddItemScreen: { 67 | screen: AddTimescren, 68 | navigationOptions: ({ navigation }) => ({ 69 | header: ( 70 | 71 | navigation.goBack()} /> 72 | 73 | 77 | 78 | ), 79 | }) 80 | }, 81 | }, { 82 | initialRouteName: 'MapScreen', 83 | }); 84 | 85 | export default createAppContainer(appStack) -------------------------------------------------------------------------------- /src/containers/NotificationContainer.js: -------------------------------------------------------------------------------- 1 | import React from 'react' 2 | 3 | import { 4 | Alert, 5 | } from 'react-native' 6 | 7 | import { 8 | Notifications, 9 | Permissions, 10 | Linking, 11 | } from 'expo' 12 | 13 | import { 14 | auth, 15 | db, 16 | } from '../lib/firebase' 17 | 18 | import FB from 'firebase' 19 | 20 | import { 21 | getMetersBetweenPoints, 22 | } from '../lib/geo' 23 | 24 | const { firestore: { GeoPoint } } = FB 25 | 26 | const { GeoFirestore } = require('geofirestore') 27 | 28 | const NotificationContext = React.createContext({ 29 | region: {}, 30 | shouldNotify: false, 31 | isLoading: false, 32 | error: null, 33 | }); 34 | 35 | const geofirestore = new GeoFirestore(db); 36 | const notificationPreferences = geofirestore.collection('notificationPreferences') 37 | 38 | 39 | export default class NotificationContainer extends React.Component { 40 | 41 | componentDidMount = () => { 42 | this.unsubscribe = notificationPreferences.doc(auth.currentUser.uid) 43 | .onSnapshot(doc => { 44 | const data = doc.data() 45 | if (!data) return 46 | // if there's no location data yet, geofirestore won't parse the data from the 47 | // nested data document, or whatever it's called. So we do it ourselves. 48 | this.setState(data.d ? data.d : data) 49 | }, e => console.log('CAUGHT', e)) 50 | } 51 | 52 | componentWillUnmount() { 53 | this.unsubscribe && this.unsubscribe() 54 | } 55 | 56 | async requestPermission() { 57 | const { status: existingStatus } = await Permissions.getAsync( 58 | Permissions.NOTIFICATIONS 59 | ); 60 | 61 | let finalStatus = existingStatus; 62 | 63 | // only ask if permissions have not already been determined, because 64 | // iOS won't necessarily prompt the user a second time. 65 | if (existingStatus !== 'granted') { 66 | // Android remote notification permissions are granted during the app 67 | // install, so this will only ask on iOS 68 | const { status } = await Permissions.askAsync(Permissions.NOTIFICATIONS); 69 | finalStatus = status; 70 | } 71 | 72 | // Stop here if the user did not grant permissions 73 | if (finalStatus !== 'granted') { 74 | return false 75 | } 76 | 77 | // Get the token that uniquely identifies this device 78 | const pushToken = await Notifications.getExpoPushTokenAsync(); 79 | 80 | await notificationPreferences.doc(auth.currentUser.uid).set({ 81 | pushToken 82 | }, { 83 | merge: true 84 | }) 85 | 86 | return true 87 | } 88 | 89 | setRegion = async region => { 90 | this.setState({ 91 | isLoading: true, 92 | }) 93 | 94 | try { 95 | const radius = getMetersBetweenPoints(region, { 96 | longitude: region.longitude + region.longitudeDelta, 97 | latitude: region.latitude + region.latitudeDelta, 98 | }) 99 | 100 | await notificationPreferences.doc(auth.currentUser.uid) 101 | .set({ 102 | region, 103 | radius: Math.round(radius), 104 | }, { 105 | customKey: 'region', 106 | merge: true 107 | }) 108 | 109 | this.setState({ 110 | isLoading: false, 111 | error: null, 112 | }) 113 | } catch (error) { 114 | this.setState({ 115 | isLoading: false, 116 | error, 117 | }) 118 | } 119 | } 120 | 121 | openSettings = () => Linking.openURL('app-settings:') 122 | 123 | setShouldNotify = async shouldNotify => { 124 | if (shouldNotify) { 125 | const hasPermission = await this.requestPermission() 126 | if (!hasPermission) { 127 | Alert.alert( 128 | 'Oops...🙈', 129 | 'We don\'t have permission. Please enable Push Notifications from settings', 130 | [ 131 | {text: 'Open settings', onPress: this.openSettings }, 132 | {text: 'Cancel', style: 'cancel'}, 133 | ], 134 | ) 135 | 136 | return 137 | } 138 | } 139 | 140 | this.setState({ 141 | isLoading: true, 142 | }) 143 | try { 144 | await notificationPreferences.doc(auth.currentUser.uid) 145 | .set({ 146 | shouldNotify 147 | }, { 148 | merge: true 149 | }) 150 | this.setState({ 151 | isLoading: false, 152 | error: null, 153 | }) 154 | } catch(e) { 155 | this.setState({ 156 | isLoading: false, 157 | error, 158 | }) 159 | } 160 | } 161 | 162 | render() { 163 | return ( 164 | 171 | { this.props.children } 172 | 173 | ); 174 | } 175 | } 176 | 177 | export const NotificationContainerHoc = (Component) => props => ( 178 | 179 | { context => } 180 | 181 | ) 182 | -------------------------------------------------------------------------------- /src/containers/Settings.js: -------------------------------------------------------------------------------- 1 | import { 2 | AuthContainerHoc 3 | } from './AuthContainer' 4 | 5 | import { 6 | NotificationContainerHoc 7 | } from './NotificationContainer' 8 | 9 | import { 10 | connectActionSheet, 11 | } from '@expo/react-native-action-sheet'; 12 | 13 | import Settings from '../components/Settings' 14 | 15 | export default AuthContainerHoc( 16 | NotificationContainerHoc( 17 | connectActionSheet( 18 | Settings 19 | ) 20 | ) 21 | ) 22 | -------------------------------------------------------------------------------- /src/lib/firebase.js: -------------------------------------------------------------------------------- 1 | import * as Firebase from 'firebase'; 2 | import 'firebase/firestore' 3 | import firebaseConfig from '../../firebase.json' 4 | 5 | const firebase = Firebase.initializeApp(firebaseConfig); 6 | 7 | export const db = firebase.firestore() 8 | 9 | db.settings({ 10 | timestampsInSnapshots: true 11 | }) 12 | 13 | export const storage = firebase.storage() 14 | export const auth = firebase.auth() 15 | export const EmailAuthProvider = Firebase.auth.EmailAuthProvider 16 | 17 | export default firebase 18 | -------------------------------------------------------------------------------- /src/lib/geo.js: -------------------------------------------------------------------------------- 1 | export const getMetersBetweenPoints = (point1, point2) => { 2 | const earthRadius = 6371 3 | const [dLat, dLng] = [ 4 | degToRadians(point2.latitude - point1.latitude), 5 | degToRadians(point2.longitude - point1.longitude) 6 | ] 7 | const a = 8 | Math.sin( dLat / 2 ) * Math.sin( dLat / 2 ) + 9 | Math.cos(degToRadians(point1.latitude)) * Math.cos(degToRadians(point2.latitude)) * 10 | Math.sin( dLng / 2 ) * Math.sin( dLng / 2 ); 11 | const c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt( 1 - a )); 12 | return Math.abs(( earthRadius * c ) * 350); 13 | } 14 | 15 | export const degToRadians = deg => deg * ( Math.PI / 180 ) -------------------------------------------------------------------------------- /src/lib/options.js: -------------------------------------------------------------------------------- 1 | import options from '../../config/options' 2 | 3 | module.exports = { 4 | defaultEmoji: '🍔', 5 | noEmojiPicker: false, 6 | randomUsernameGeneratorUrl: 'http://names.drycodes.com/1?separator=space', 7 | newMsgPlaceholder: [ 'Say something...' ], 8 | ...options, 9 | } -------------------------------------------------------------------------------- /src/lib/theme.js: -------------------------------------------------------------------------------- 1 | import { 2 | DefaultTheme, 3 | } from 'react-native-paper' 4 | 5 | import * as deepmerge from 'deepmerge' 6 | 7 | import options from './options' 8 | 9 | export default deepmerge.default(DefaultTheme, options.theme || {}) -------------------------------------------------------------------------------- /src/lib/urlToBlob.js: -------------------------------------------------------------------------------- 1 | export default url => new Promise((resolve, reject) => { 2 | var xhr = new XMLHttpRequest(); 3 | xhr.onerror = reject; 4 | xhr.onreadystatechange = () => { 5 | if (xhr.readyState === 4) { 6 | resolve(xhr.response); 7 | } 8 | }; 9 | xhr.open('GET', url); 10 | xhr.responseType = 'blob'; // convert type 11 | xhr.send(); 12 | }) -------------------------------------------------------------------------------- /src/lib/usernameGenerator.js: -------------------------------------------------------------------------------- 1 | 2 | import { 3 | randomUsernameGeneratorUrl, 4 | } from './options' 5 | 6 | const random = array => array[Math.floor(Math.random() * array.length)] 7 | const upcase = str => str.charAt(0).toUpperCase() + str.slice(1) 8 | export default { 9 | generate: async () => { 10 | const res = await fetch(randomUsernameGeneratorUrl) 11 | const json = await res.json() 12 | const name = Array.isArray(json) 13 | ? random(json) 14 | : json 15 | return name 16 | .replace(/[^a-z]/gi, ' ') 17 | .split(' ') 18 | .map(upcase) 19 | .join('') 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /src/lib/wrapInTry.js: -------------------------------------------------------------------------------- 1 | export default setState => func => async params => { 2 | try { 3 | setState({ 4 | loading: true 5 | }) 6 | 7 | await func(params) 8 | 9 | setState({ 10 | loading: false, 11 | error: null, 12 | }) 13 | return true 14 | } catch (error) { 15 | console.log(error) 16 | setState({ 17 | loading: false, 18 | error, 19 | }) 20 | return false 21 | } 22 | } --------------------------------------------------------------------------------