diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 40ff413b72..1b551272eb 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -1,5 +1,14 @@ # Contributing to World Cleanup Day App and Platform +Not sure how to start? Read on for the general process or [jump right in](GETTING_STARTED.md). + +- [Code of Conduct](#code-of-conduct) +- [How can you contribute?](#how-you-can-contribute) +- [Issue Contributions](#issue-contributions) +- [Code Contributions](#code-contributions) +- [Additional Notes](#additional-notes) +- [Developer's Certificate of Origin 1.1](#developers-certificate-of-origin-11) + ## Code of Conduct * We are committed to providing a friendly, safe and welcoming environment for all, regardless of level of experience, gender identity and expression, sexual orientation, disability, personal appearance, body size, race, ethnicity, age, religion, nationality, or other similar characteristic. @@ -13,7 +22,7 @@ * Likewise any spamming, trolling, flaming, baiting or other attention-stealing behavior is not welcome. * Avoid the use of personal pronouns in code comments or documentation. There is no need to address persons when explaining code (e.g. "When the developer"). -## How you can contribute? +## How you can contribute? Do you like to design? * Create art for social media banners to promote the project diff --git a/GETTING_STARTED.md b/GETTING_STARTED.md new file mode 100644 index 0000000000..9788587a91 --- /dev/null +++ b/GETTING_STARTED.md @@ -0,0 +1,38 @@ +# Getting started + +This document will help you set up the project for development. + +## Basic dependencies +Install git, docker, docker-compose, node and yarn. + + +## Backend services +Consult the dedicated [readme](devops/dev/README.md) to set them up, run +them and verify they work. + +### Adding dummy data +This repository comes without trashpoint data. You will need some to work +on the related APIS or marker related functionality. + +**TODO:** expand with wcd_dummy instructions + + +## Web-app (admin backend) +Consult the dedicated [readme](web-app/README.md), but in essence: + +```bash +npm install # the first time +npm start +``` + +## Mobile-apps +Consult the dedicated [readme](mobile-app/README.md). + + +## Extra reading + +* [Contributing](./CONTRIBUTING.md) to World Cleanup Day App and Platform +* [Code of Conduct](./CODE_OF_CONDUCT.md) +* [Governance](./GOVERNANCE.md) +* [Roadmap](./ROADMAP.md) +* Issues marked [good first issue](https://github.com/letsdoitworld/World-Cleanup-Day/issues?q=is%3Aissue+is%3Aopen+label%3A%22good+first+issue%22) diff --git a/README.md b/README.md index 6aeef6126c..53b9ed35b1 100644 --- a/README.md +++ b/README.md @@ -3,7 +3,7 @@ [![Join the chat at https://gitter.im/letsdoitworld/World-Cleanup-Day](https://badges.gitter.im/letsdoitworld/World-Cleanup-Day.svg)](https://gitter.im/letsdoitworld/World-Cleanup-Day?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge) -Over 17 million trash heroes have already cleaned up more than 500 000 tonnes of trash in over 100 countries! The movement against pollution is growing fast and we're now building the World Cleanup App and Platform for the hundreds of millions of people people joining the World Cleanup Day on **15th of September 2018**. +Over 20 million trash heroes have already cleaned up more than 500 000 tonnes of trash in over 100 countries! The movement against pollution is growing fast and we're now building the World Cleanup App and Platform for the hundreds of millions of people people joining the World Cleanup Day on **15th of September 2018**. Together we will get rid of trash once and for all, save lives, improve health & reduce costs. Read below on how you can participate! Let's do it! 😃 @@ -43,6 +43,9 @@ Join the movement and let's clean up the World together! ## API See the [API docs](http://ldiw-api.s3-website.eu-central-1.amazonaws.com/) +## Translations +See [translate.worldcleanupday.org](https://translate.worldcleanupday.org/ ) + ## Roadmap See [Roadmap.md](https://github.com/letsdoitworld/World-Cleanup-Day/blob/master/ROADMAP.md) diff --git a/backend-api/api/controllers/teams.js b/backend-api/api/controllers/teams.js new file mode 100644 index 0000000000..3f28399b85 --- /dev/null +++ b/backend-api/api/controllers/teams.js @@ -0,0 +1,28 @@ +'use strict'; +const senecaRequestMw = require('../../modules/swagger-setup/middleware/seneca'); + +module.exports = { + getAllTeams: senecaRequestMw( + 'role:db,cmd:getAllTeams', + req => ({ + CC: req.swagger.params.country.value, + search: req.swagger.params.search.value, + }), + ), + getAllTeamsWeb: senecaRequestMw( + 'role:db,cmd:getAllTeamsWeb', + req => ({ + CC: req.swagger.params.country.value, + superadmin: req.swagger.params.superadmin.value, + }), + ), + getCountTeamsTrashpoints: senecaRequestMw( + 'role:db,cmd:getCountTeamsTrashpoints', + ), + getTeam: senecaRequestMw( + 'role:db,cmd:getTeam', + req => ({ + id: req.swagger.params.id.value, + }), + ) +}; diff --git a/backend-api/api/controllers/users.js b/backend-api/api/controllers/users.js index 997738f370..2e8100a1fe 100644 --- a/backend-api/api/controllers/users.js +++ b/backend-api/api/controllers/users.js @@ -17,6 +17,12 @@ module.exports = { update: req.swagger.params.update.value, }), ), + modifyUserTeam: senecaRequestMw( + 'role:db,cmd:modifyOwnUserProfile', + req => ({ + update: req.swagger.params.update.value, + }), + ), getUserProfile: senecaRequestMw( 'role:db,cmd:getAccountById', req => ({ diff --git a/backend-api/api/v1.0.yaml b/backend-api/api/v1.0.yaml index 309a8b9a6d..5843207fdc 100644 --- a/backend-api/api/v1.0.yaml +++ b/backend-api/api/v1.0.yaml @@ -68,6 +68,22 @@ paths: "default": $ref: "#/responses/ErrorSet" #----------------------------------------------------------------------------- + /me/team: + x-swagger-router-controller: users + put: + description: Join user to team. + operationId: modifyUserTeam + x-security: [bearer] + parameters: + - $ref: "#/parameters/ModifyTeam" + responses: + "200": + description: Account information. + schema: + $ref: "#/definitions/Account" + "default": + $ref: "#/responses/ErrorSet" + #----------------------------------------------------------------------------- /auth/external: x-swagger-router-controller: users post: @@ -193,6 +209,58 @@ paths: "default": $ref: "#/responses/ErrorSet" #----------------------------------------------------------------------------- + /teams: + x-swagger-router-controller: teams + get: + description: List all teams. + operationId: getAllTeams + parameters: + - $ref: "#/parameters/Country" + - $ref: "#/parameters/Search" + responses: + "200": + $ref: "#/responses/Teams" + "default": + $ref: "#/responses/ErrorSet" + /teams/web: + x-swagger-router-controller: teams + get: + description: List all teams attached to this admin. + operationId: getAllTeamsWeb + x-security: [bearer, {roles:[superadmin, leader]}] + parameters: + - $ref: "#/parameters/Country" + - $ref: "#/parameters/Superadmin" + responses: + "200": + $ref: "#/responses/Teams" + "default": + $ref: "#/responses/ErrorSet" + /teams/trashpoints: + x-swagger-router-controller: teams + get: + description: Fetch information about trashpoints for all teams. + operationId: getCountTeamsTrashpoints + responses: + "200": + $ref: "#/responses/Teams" + "default": + $ref: "#/responses/ErrorSet" + /teams/{id}: + x-swagger-router-controller: teams + get: + description: Fetch complete info about a specific team. + operationId: getTeam + parameters: + - $ref: "#/parameters/UUID" + responses: + "200": + description: Full team information. + schema: + $ref: "#/definitions/Team" + "default": + $ref: "#/responses/ErrorSet" + #----------------------------------------------------------------------------- /areas/user: x-swagger-router-controller: areas get: @@ -541,6 +609,20 @@ parameters: minLength: 3 maxLength: 10 #----------------------------------------------------------------------------- + Search: + name: search + in: query + required: false + type: string + minLength: 3 + maxLength: 60 + #----------------------------------------------------------------------------- + Superadmin: + name: superadmin + in: query + required: false + type: boolean + #----------------------------------------------------------------------------- Country: name: country in: query @@ -559,6 +641,17 @@ parameters: country: $ref: "#/definitions/CountryCode" #----------------------------------------------------------------------------- + ModifyTeam: + name: update + in: body + required: true + schema: + type: object + required: [team] + properties: + team: + $ref: "#/definitions/UUID" + #----------------------------------------------------------------------------- ModifyTrashpoint: name: trashpoint in: body @@ -677,6 +770,12 @@ responses: description: List of trashpoints for area leader consumption. schema: $ref: "#/definitions/PaginatedAreaTrashpoints" + Teams: + description: List of teams. + schema: + type: array + items: + $ref: "#/definitions/Team" StorageAuth: description: A short-term authorization allowing access to storage operations. schema: @@ -720,6 +819,28 @@ definitions: description: Area can be optionally be assigned to a user. $ref: "#/definitions/UUID" #----------------------------------------------------------------------------- + # Team properties. + #----------------------------------------------------------------------------- + Team: + type: object + required: [id, name] + properties: + id: + description: A unique code of team + type: string + name: + description: A name of team + type: string + teamDescription: + description: Desctiption of team + type: string + trashpoints: + description: How many trashpoints have this team + type: integer + users: + description: How many users have this team + type: integer + #----------------------------------------------------------------------------- # Account properties. #----------------------------------------------------------------------------- Account: @@ -743,6 +864,10 @@ definitions: $ref: "#/definitions/ISOTimestamp" locked: type: boolean + team: + type: + - string + - 'null' AccountPlusAreas: allOf: - "$ref": "#/definitions/Account" diff --git a/backend-api/modules/swagger-setup/middleware/security.js b/backend-api/modules/swagger-setup/middleware/security.js index 9d037d9731..52677f8a37 100644 --- a/backend-api/modules/swagger-setup/middleware/security.js +++ b/backend-api/modules/swagger-setup/middleware/security.js @@ -72,7 +72,7 @@ const bearerCheck = async (req, res, next) => { if (response.isSuccessful()) { const ret = response.getPayload(); req.__.user = util.object.filter(ret.account, { - id: true, termsAcceptedAt: true, role: true, + id: true, termsAcceptedAt: true, role: true, team: true }); req.__.session = ret.session; return next(); diff --git a/backend-api/yarn.lock b/backend-api/yarn.lock index ab5453d3ff..b502264dd1 100644 --- a/backend-api/yarn.lock +++ b/backend-api/yarn.lock @@ -13,10 +13,6 @@ append-field@^0.1.0: version "0.1.0" resolved "https://registry.yarnpkg.com/append-field/-/append-field-0.1.0.tgz#6ddc58fa083c7bc545d3c5995b2830cc2366d44a" -archy@1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/archy/-/archy-1.0.0.tgz#f9c8c13757cc1dd7bc379ac77b2c62a5c2868c40" - argparse@^1.0.7: version "1.0.9" resolved "https://registry.yarnpkg.com/argparse/-/argparse-1.0.9.tgz#73d83bc263f86e97f8cc4f6bae1b0e90a7d22c86" @@ -31,28 +27,14 @@ async@^1.3.0, async@^1.4.0: version "1.5.2" resolved "https://registry.yarnpkg.com/async/-/async-1.5.2.tgz#ec6a61ae56480c0c3cb241c95618e20892f9672a" -async@~1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/async/-/async-1.0.0.tgz#f8fc04ca3a13784ade9e1641af98578cfbd647a9" - asynckit@^0.4.0: version "0.4.0" resolved "https://registry.yarnpkg.com/asynckit/-/asynckit-0.4.0.tgz#c79ed97f7f34cb8f2ba1bc9790bcc366474b4b79" -backoff@~2.5.0: - version "2.5.0" - resolved "https://registry.yarnpkg.com/backoff/-/backoff-2.5.0.tgz#f616eda9d3e4b66b8ca7fca79f695722c5f8e26f" - dependencies: - precond "0.2" - basic-auth@~1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/basic-auth/-/basic-auth-1.1.0.tgz#45221ee429f7ee1e5035be3f51533f1cdfd29884" -bluebird@^3.5.0: - version "3.5.0" - resolved "https://registry.yarnpkg.com/bluebird/-/bluebird-3.5.0.tgz#791420d7f551eea2897453a8a77653f96606d67c" - body-parser@1.12.4: version "1.12.4" resolved "https://registry.yarnpkg.com/body-parser/-/body-parser-1.12.4.tgz#090700c4ba28862a8520ef378395fdee5f61c229" @@ -67,18 +49,6 @@ body-parser@1.12.4: raw-body "~2.0.1" type-is "~1.6.2" -boom@3.x.x: - version "3.2.2" - resolved "https://registry.yarnpkg.com/boom/-/boom-3.2.2.tgz#0f0cc5d04adc5003b8c7d71f42cca7271fef0e78" - dependencies: - hoek "4.x.x" - -boom@4.x.x: - version "4.3.1" - resolved "https://registry.yarnpkg.com/boom/-/boom-4.3.1.tgz#4f8a3005cb4a7e3889f749030fd25b96e01d2e31" - dependencies: - hoek "4.x.x" - busboy@^0.2.11: version "0.2.14" resolved "https://registry.yarnpkg.com/busboy/-/busboy-0.2.14.tgz#6c2a622efcf47c57bbbe1e2a9c37ad36c7925453" @@ -94,10 +64,6 @@ bytes@2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/bytes/-/bytes-2.1.0.tgz#ac93c410e2ffc9cc7cf4b464b38289067f5e47b4" -colors@1.0.x: - version "1.0.3" - resolved "https://registry.yarnpkg.com/colors/-/colors-1.0.3.tgz#0433f44d809680fdeb60ed260f1b0c262e82a40b" - combined-stream@^1.0.5: version "1.0.5" resolved "https://registry.yarnpkg.com/combined-stream/-/combined-stream-1.0.5.tgz#938370a57b4a51dea2c77c15d5c5fdf895164009" @@ -151,10 +117,6 @@ cors@=2.8.4: object-assign "^4" vary "^1" -cycle@1.0.x: - version "1.0.3" - resolved "https://registry.yarnpkg.com/cycle/-/cycle-1.0.3.tgz#21e80b2be8580f98b468f379430662b046c34ad2" - debug@2, debug@2.6.8, debug@^2.2.0: version "2.6.8" resolved "https://registry.yarnpkg.com/debug/-/debug-2.6.8.tgz#e731531ca2ede27d188222427da17821d68ff4fc" @@ -212,12 +174,6 @@ encodeurl@~1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/encodeurl/-/encodeurl-1.0.1.tgz#79e3d58655346909fe6f0f45a5de68103b294d20" -eraro@0.4, eraro@0.4.1, eraro@~0.4.1: - version "0.4.1" - resolved "https://registry.yarnpkg.com/eraro/-/eraro-0.4.1.tgz#6538730769a1e89ffc3f0c7e2c94d5a1f866629d" - dependencies: - lodash "~2.4.1" - escape-html@~1.0.3: version "1.0.3" resolved "https://registry.yarnpkg.com/escape-html/-/escape-html-1.0.3.tgz#0258eae4d3d0c0974de1c169188ef0051d1d1988" @@ -271,10 +227,6 @@ extend@3.0.0, extend@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/extend/-/extend-3.0.0.tgz#5a474353b9f3353ddd8176dfd37b91c83a46f1d4" -eyes@0.1.x: - version "0.1.8" - resolved "https://registry.yarnpkg.com/eyes/-/eyes-0.1.8.tgz#62cf120234c683785d902348a800ef3e0cc20bc0" - finalhandler@~1.0.3: version "1.0.3" resolved "https://registry.yarnpkg.com/finalhandler/-/finalhandler-1.0.3.tgz#ef47e77950e999780e86022a560e3217e0d0cc89" @@ -319,26 +271,12 @@ fresh@0.5.0: version "0.5.0" resolved "https://registry.yarnpkg.com/fresh/-/fresh-0.5.0.tgz#f474ca5e6a9246d6fd8e0953cfa9b9c805afa78e" -gate-executor@1.1.1: - version "1.1.1" - resolved "https://registry.yarnpkg.com/gate-executor/-/gate-executor-1.1.1.tgz#667f677284a0dbe86b6c48a0b4afe8c484812caf" - -gex@0.2.2: - version "0.2.2" - resolved "https://registry.yarnpkg.com/gex/-/gex-0.2.2.tgz#2d409d2430959708da55cf56294c64f6d8973487" - dependencies: - lodash "3.10.0" - graphlib@^2.1.1: version "2.1.1" resolved "https://registry.yarnpkg.com/graphlib/-/graphlib-2.1.1.tgz#42352c52ba2f4d035cb566eb91f7395f76ebc951" dependencies: lodash "^4.11.1" -hoek@4.x.x: - version "4.2.0" - resolved "https://registry.yarnpkg.com/hoek/-/hoek-4.2.0.tgz#72d9d0754f7fe25ca2d01ad8f8f9a9449a89526d" - http-errors@~1.6.1: version "1.6.1" resolved "https://registry.yarnpkg.com/http-errors/-/http-errors-1.6.1.tgz#5f8b8ed98aca545656bf572997387f904a722257" @@ -368,10 +306,6 @@ isarray@~1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/isarray/-/isarray-1.0.0.tgz#bb935d48582cba168c06834957a54a3e07124f11" -isstream@0.1.x: - version "0.1.2" - resolved "https://registry.yarnpkg.com/isstream/-/isstream-0.1.2.tgz#47e63f7af55afa6f92e1500e690eb8b8529c099a" - js-yaml@=3.9.0, js-yaml@^3.3.1, js-yaml@^3.8.3: version "3.9.0" resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-3.9.0.tgz#4ffbbf25c2ac963b8299dc74da7e3740de1c18ce" @@ -391,18 +325,6 @@ json-refs@^2.1.5: slash "^1.0.0" uri-js "^3.0.2" -json-stringify-safe@5.0.1: - version "5.0.1" - resolved "https://registry.yarnpkg.com/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz#1296a2d58fd45f19a0f6ce01d65701e2c735b6eb" - -jsonic@0.2.2: - version "0.2.2" - resolved "https://registry.yarnpkg.com/jsonic/-/jsonic-0.2.2.tgz#127bb99df4d821652c48a23d025cf2b16e618491" - -jsonic@0.3.0: - version "0.3.0" - resolved "https://registry.yarnpkg.com/jsonic/-/jsonic-0.3.0.tgz#b545da95f54392e58b3dda05f5f2e377a6c9d1bf" - lodash-compat@^3.10.0: version "3.10.2" resolved "https://registry.yarnpkg.com/lodash-compat/-/lodash-compat-3.10.2.tgz#c6940128a9d30f8e902cd2cf99fd0cba4ecfc183" @@ -593,29 +515,10 @@ lodash.support@~2.4.1: dependencies: lodash._isnative "~2.4.1" -lodash@3.10.0: - version "3.10.0" - resolved "https://registry.yarnpkg.com/lodash/-/lodash-3.10.0.tgz#93d51c672828a4416a12af57220ba8a8737e2fbb" - -lodash@4.15, lodash@4.15.0: - version "4.15.0" - resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.15.0.tgz#3162391d8f0140aa22cf8f6b3c34d6b7f63d3aa9" - -lodash@4.17.4, lodash@^4.11.1: +lodash@^4.11.1: version "4.17.4" resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.4.tgz#78203a4d1c328ae1d86dca6460e369b57f4055ae" -lodash@~2.4.1: - version "2.4.2" - resolved "https://registry.yarnpkg.com/lodash/-/lodash-2.4.2.tgz#fadd834b9683073da179b3eae6d9c0d15053f73e" - -lru-cache@4.0.1: - version "4.0.1" - resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-4.0.1.tgz#1343955edaf2e37d9b9e7ee7241e27c4b9fb72be" - dependencies: - pseudomap "^1.0.1" - yallist "^2.0.0" - media-typer@0.3.0: version "0.3.0" resolved "https://registry.yarnpkg.com/media-typer/-/media-typer-0.3.0.tgz#8710d7af0aa626f8fffa1ce00168545263255748" @@ -646,20 +549,12 @@ minimist@0.0.8: version "0.0.8" resolved "https://registry.yarnpkg.com/minimist/-/minimist-0.0.8.tgz#857fcabfc3397d2625b8228262e86aa7a011b05d" -minimist@1.2.0, minimist@^1.2.0: - version "1.2.0" - resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.0.tgz#a35008b20f41383eec1fb914f4cd5df79a264284" - mkdirp@^0.5.1: version "0.5.1" resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-0.5.1.tgz#30057438eac6cf7f8c4767f38648d6697d75c903" dependencies: minimist "0.0.8" -moment@^2.18.1: - version "2.18.1" - resolved "https://registry.yarnpkg.com/moment/-/moment-2.18.1.tgz#c36193dd3ce1c2eed2adb7c802dbbc77a81b1c0f" - morgan@=1.8.2: version "1.8.2" resolved "https://registry.yarnpkg.com/morgan/-/morgan-1.8.2.tgz#784ac7734e4a453a9c6e6e8680a9329275c8b687" @@ -695,29 +590,10 @@ native-promise-only@^0.8.1: version "0.8.1" resolved "https://registry.yarnpkg.com/native-promise-only/-/native-promise-only-0.8.1.tgz#20a318c30cb45f71fe7adfbf7b21c99c1472ef11" -ndjson@1.4.3: - version "1.4.3" - resolved "https://registry.yarnpkg.com/ndjson/-/ndjson-1.4.3.tgz#7aa026fe3ab38a7da1a2b4ad07b1008e733eb239" - dependencies: - minimist "^1.2.0" - split2 "^0.2.1" - through2 "^0.6.1" - negotiator@0.6.1: version "0.6.1" resolved "https://registry.yarnpkg.com/negotiator/-/negotiator-0.6.1.tgz#2b327184e8992101177b28563fb5e7102acd0ca9" -nid@0.3, nid@0.3.2: - version "0.3.2" - resolved "https://registry.yarnpkg.com/nid/-/nid-0.3.2.tgz#977a9318ed5c2a38edd66263f3eafd8143f2251a" - -norma@0.3, norma@0.3.0: - version "0.3.0" - resolved "https://registry.yarnpkg.com/norma/-/norma-0.3.0.tgz#27265c3411018c32c93ee719f692cf90dec5ab64" - dependencies: - eraro "~0.4.1" - lodash "~2.4.1" - object-assign@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/object-assign/-/object-assign-3.0.0.tgz#9bedd5ca0897949bca47e7ff408062d549f587f2" @@ -742,10 +618,6 @@ on-headers@~1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/on-headers/-/on-headers-1.0.1.tgz#928f5d0f470d49342651ea6794b0857c100693f7" -ordu@0.1.1: - version "0.1.1" - resolved "https://registry.yarnpkg.com/ordu/-/ordu-0.1.1.tgz#9c8109493693caf08299fca84c596aeb860baeaa" - parseurl@^1.3.0, parseurl@~1.3.1: version "1.3.1" resolved "https://registry.yarnpkg.com/parseurl/-/parseurl-1.3.1.tgz#c8ab8c9223ba34888aa64a297b28853bec18da56" @@ -767,24 +639,6 @@ path-to-regexp@^1.2.0: dependencies: isarray "0.0.1" -patrun@0.5.0: - version "0.5.0" - resolved "https://registry.yarnpkg.com/patrun/-/patrun-0.5.0.tgz#77a51f773ac4931bb353fd41d59de6478fc6118d" - dependencies: - gex "0.2.2" - lodash "3.10.0" - -patrun@0.5.1: - version "0.5.1" - resolved "https://registry.yarnpkg.com/patrun/-/patrun-0.5.1.tgz#5bff3757f4f3fd2bdfb6a04d27942cbec3e12f1c" - dependencies: - gex "0.2.2" - lodash "4.15.0" - -precond@0.2: - version "0.2.3" - resolved "https://registry.yarnpkg.com/precond/-/precond-0.2.3.tgz#aa9591bcaa24923f1e0f4849d240f47efc1075ac" - process-nextick-args@~1.0.6: version "1.0.7" resolved "https://registry.yarnpkg.com/process-nextick-args/-/process-nextick-args-1.0.7.tgz#150e20b756590ad3f91093f25a4f2ad8bff30ba3" @@ -796,10 +650,6 @@ proxy-addr@~1.1.4: forwarded "~0.1.0" ipaddr.js "1.4.0" -pseudomap@^1.0.1: - version "1.0.2" - resolved "https://registry.yarnpkg.com/pseudomap/-/pseudomap-1.0.2.tgz#f052a28da70e618917ef0a8ac34c1ae5a68286b3" - punycode@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/punycode/-/punycode-2.1.0.tgz#5f863edc89b96db09074bad7947bf09056ca4e7d" @@ -812,10 +662,6 @@ qs@2.4.2: version "2.4.2" resolved "https://registry.yarnpkg.com/qs/-/qs-2.4.2.tgz#f7ce788e5777df0b5010da7f7c4e73ba32470f5a" -qs@6.2.1: - version "6.2.1" - resolved "https://registry.yarnpkg.com/qs/-/qs-6.2.1.tgz#ce03c5ff0935bc1d9d69a9f14cbd18e568d67625" - qs@6.4.0, qs@^6.1.0: version "6.4.0" resolved "https://registry.yarnpkg.com/qs/-/qs-6.4.0.tgz#13e26d28ad6b0ffaa91312cd3bf708ed351e7233" @@ -853,15 +699,6 @@ readable-stream@1.1.x: isarray "0.0.1" string_decoder "~0.10.x" -"readable-stream@>=1.0.33-1 <1.1.0-0": - version "1.0.34" - resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-1.0.34.tgz#125820e34bc842d2f2aaafafe4c2916ee32c157c" - dependencies: - core-util-is "~1.0.0" - inherits "~2.0.1" - isarray "0.0.1" - string_decoder "~0.10.x" - readable-stream@^2.0.5, readable-stream@^2.2.2: version "2.3.3" resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-2.3.3.tgz#368f2512d79f9d46fdfc71349ae7878bbc1eb95c" @@ -874,28 +711,14 @@ readable-stream@^2.0.5, readable-stream@^2.2.2: string_decoder "~1.0.3" util-deprecate "~1.0.1" -reconnect-core@1.3.0: - version "1.3.0" - resolved "https://registry.yarnpkg.com/reconnect-core/-/reconnect-core-1.3.0.tgz#fbae52919a7877d844e3246d01a2f26701c833c8" - dependencies: - backoff "~2.5.0" - reduce-component@1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/reduce-component/-/reduce-component-1.0.1.tgz#e0c93542c574521bea13df0f9488ed82ab77c5da" -rolling-stats@0.1.1: - version "0.1.1" - resolved "https://registry.yarnpkg.com/rolling-stats/-/rolling-stats-0.1.1.tgz#cd5af774a8893b30a674832fa2f4abaa478cfc80" - safe-buffer@~5.1.0, safe-buffer@~5.1.1: version "5.1.1" resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.1.1.tgz#893312af69b2123def71f57889001671eeb2c853" -semver@5.3.0: - version "5.3.0" - resolved "https://registry.yarnpkg.com/semver/-/semver-5.3.0.tgz#9b2ce5d3de02d17c6012ad326aa6b4d0cf54f94f" - send@0.15.3: version "0.15.3" resolved "https://registry.yarnpkg.com/send/-/send-0.15.3.tgz#5013f9f99023df50d1bd9892c19e3defd1d53309" @@ -914,52 +737,6 @@ send@0.15.3: range-parser "~1.2.0" statuses "~1.3.1" -seneca-log-filter@0.1.0: - version "0.1.0" - resolved "https://registry.yarnpkg.com/seneca-log-filter/-/seneca-log-filter-0.1.0.tgz#f513de77dfdcc120023f847a7c60ceed0afc66b3" - dependencies: - lodash "4.15.0" - -seneca-transport@2.1.1: - version "2.1.1" - resolved "https://registry.yarnpkg.com/seneca-transport/-/seneca-transport-2.1.1.tgz#ff8d1a0335bfe037ca7ceddf27828bdd55292a22" - dependencies: - eraro "0.4.1" - gex "0.2.2" - jsonic "0.2.2" - lodash "4.15.0" - lru-cache "4.0.1" - ndjson "1.4.3" - nid "0.3.2" - patrun "0.5.0" - qs "6.2.1" - reconnect-core "1.3.0" - wreck "9.0.0" - -seneca@^3.4.1: - version "3.4.1" - resolved "https://registry.yarnpkg.com/seneca/-/seneca-3.4.1.tgz#1cc252cbff0917adc8dabe9e993d45faadb5a8be" - dependencies: - archy "1.0.0" - eraro "0.4.1" - gate-executor "1.1.1" - gex "0.2.2" - json-stringify-safe "5.0.1" - jsonic "0.3.0" - lodash "4.17.4" - minimist "1.2.0" - nid "0.3.2" - norma "0.3.0" - ordu "0.1.1" - patrun "0.5.1" - qs "6.4.0" - rolling-stats "0.1.1" - semver "5.3.0" - seneca-log-filter "0.1.0" - seneca-transport "2.1.1" - use-plugin "0.3.2" - wreck "12.2.0" - serve-static@1.12.3, serve-static@^1.10.0: version "1.12.3" resolved "https://registry.yarnpkg.com/serve-static/-/serve-static-1.12.3.tgz#9f4ba19e2f3030c547f8af99107838ec38d5b1e2" @@ -981,20 +758,10 @@ spark-md5@^1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/spark-md5/-/spark-md5-1.0.1.tgz#c4b9a8d41cf7b0845423a821824f8dffa0f51b7c" -split2@^0.2.1: - version "0.2.1" - resolved "https://registry.yarnpkg.com/split2/-/split2-0.2.1.tgz#02ddac9adc03ec0bb78c1282ec079ca6e85ae900" - dependencies: - through2 "~0.6.1" - sprintf-js@~1.0.2: version "1.0.3" resolved "https://registry.yarnpkg.com/sprintf-js/-/sprintf-js-1.0.3.tgz#04e6926f662895354f3dd015203633b857297e2c" -stack-trace@0.0.x: - version "0.0.10" - resolved "https://registry.yarnpkg.com/stack-trace/-/stack-trace-0.0.10.tgz#547c70b347e8d32b4e108ea1a2a159e5fdde19c0" - "statuses@>= 1.3.1 < 2", statuses@~1.3.1: version "1.3.1" resolved "https://registry.yarnpkg.com/statuses/-/statuses-1.3.1.tgz#faf51b9eb74aaef3b3acf4ad5f61abf24cb7b93e" @@ -1077,13 +844,6 @@ swagger-tools@=0.10.1: traverse "^0.6.6" z-schema "^3.15.4" -through2@^0.6.1, through2@~0.6.1: - version "0.6.5" - resolved "https://registry.yarnpkg.com/through2/-/through2-0.6.5.tgz#41ab9c67b29d57209071410e1d7a7a968cd3ad48" - dependencies: - readable-stream ">=1.0.33-1 <1.1.0-0" - xtend ">=4.0.0 <4.1.0-0" - traverse@^0.6.6: version "0.6.6" resolved "https://registry.yarnpkg.com/traverse/-/traverse-0.6.6.tgz#cbdf560fd7b9af632502fed40f918c157ea97137" @@ -1109,15 +869,6 @@ uri-js@^3.0.2: dependencies: punycode "^2.1.0" -use-plugin@0.3.2: - version "0.3.2" - resolved "https://registry.yarnpkg.com/use-plugin/-/use-plugin-0.3.2.tgz#01f8b872f24ccdea4fd7958f057f4d55bf1fdff4" - dependencies: - eraro "0.4" - lodash "4.15" - nid "0.3" - norma "0.3" - util-deprecate@~1.0.1: version "1.0.2" resolved "https://registry.yarnpkg.com/util-deprecate/-/util-deprecate-1.0.2.tgz#450d4dc9fa70de732762fbd2d4a28981419a0ccf" @@ -1126,10 +877,6 @@ utils-merge@1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/utils-merge/-/utils-merge-1.0.0.tgz#0294fb922bb9375153541c4f7096231f287c8af8" -uuid@^3.1.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/uuid/-/uuid-3.1.0.tgz#3dd3d3e790abc24d7b0d3a034ffababe28ebbc04" - validator@^6.0.0: version "6.3.0" resolved "https://registry.yarnpkg.com/validator/-/validator-6.3.0.tgz#47ce23ed8d4eaddfa9d4b8ef0071b6cf1078d7c8" @@ -1138,39 +885,10 @@ vary@^1, vary@~1.1.1: version "1.1.1" resolved "https://registry.yarnpkg.com/vary/-/vary-1.1.1.tgz#67535ebb694c1d52257457984665323f587e8d37" -winston@^2.3.1: - version "2.3.1" - resolved "https://registry.yarnpkg.com/winston/-/winston-2.3.1.tgz#0b48420d978c01804cf0230b648861598225a119" - dependencies: - async "~1.0.0" - colors "1.0.x" - cycle "1.0.x" - eyes "0.1.x" - isstream "0.1.x" - stack-trace "0.0.x" - -wreck@12.2.0: - version "12.2.0" - resolved "https://registry.yarnpkg.com/wreck/-/wreck-12.2.0.tgz#a1c3371e2152bf6d3600ff581b669c68a4d3d8b8" - dependencies: - boom "4.x.x" - hoek "4.x.x" - -wreck@9.0.0: - version "9.0.0" - resolved "https://registry.yarnpkg.com/wreck/-/wreck-9.0.0.tgz#1de63d49bb07b94fe718864b8be63176e63331ec" - dependencies: - boom "3.x.x" - hoek "4.x.x" - -"xtend@>=4.0.0 <4.1.0-0", xtend@^4.0.0: +xtend@^4.0.0: version "4.0.1" resolved "https://registry.yarnpkg.com/xtend/-/xtend-4.0.1.tgz#a5c6d532be656e23db820efb943a1f04998d63af" -yallist@^2.0.0: - version "2.1.2" - resolved "https://registry.yarnpkg.com/yallist/-/yallist-2.1.2.tgz#1c11f9218f076089a47dd512f93c6699a6a81d52" - z-schema@^3.15.4: version "3.18.2" resolved "https://registry.yarnpkg.com/z-schema/-/z-schema-3.18.2.tgz#e422196b5efe60b46adef3c3f2aef2deaa911161" diff --git a/backend-db/app.js b/backend-db/app.js index 2dddf6b3fa..d32331e537 100644 --- a/backend-db/app.js +++ b/backend-db/app.js @@ -6,3 +6,4 @@ service.use('./plugins/datasets'); service.use('./plugins/trashpoints'); service.use('./plugins/images'); service.use('./plugins/areas'); +service.use('./plugins/teams'); diff --git a/backend-db/modules/db/couchdb/adapter.js b/backend-db/modules/db/couchdb/adapter.js index 0443b951c3..6e9336dff8 100644 --- a/backend-db/modules/db/couchdb/adapter.js +++ b/backend-db/modules/db/couchdb/adapter.js @@ -21,7 +21,8 @@ const TYPE_TO_DB_MAP = { 'Account': 'accounts', 'Session': 'sessions', 'Area': 'areas', -} + 'Team': 'teams' +}; const cdb = require('./driver'); const types = require('../types'); @@ -128,7 +129,7 @@ const adapter = { const ret = docs.pop(); return ret; }, - getOneEntityById: async (datatype, view, id) => { + getOneEntityById: async (datatype, view, id) => { if (!id) { return false; } diff --git a/backend-db/modules/db/couchdb/countries.json b/backend-db/modules/db/couchdb/countries.json new file mode 100644 index 0000000000..53768a7a60 --- /dev/null +++ b/backend-db/modules/db/couchdb/countries.json @@ -0,0 +1,247 @@ +{ + "AD": "Andorra", + "AE": "United Arab Emirates", + "AF": "Afghanistan", + "AG": "Antigua and Barbuda", + "AI": "Anguilla", + "AL": "Albania", + "AM": "Armenia", + "AN": "Bonaire, Saint Eustatius and Saba", + "AO": "Angola", + "AQ": "Antarctica", + "AR": "Argentina", + "AS": "American Samoa", + "AT": "Austria", + "AU": "Australia", + "AW": "Aruba", + "AX": "Åland", + "AZ": "Azerbaijan", + "BA": "Bosnia and Herzegovina", + "BB": "Barbados", + "BD": "Bangladesh", + "BE": "Belgium", + "BF": "Burkina Faso", + "BG": "Bulgaria", + "BH": "Bahrain", + "BI": "Burundi", + "BJ": "Benin", + "BM": "Bermuda", + "BN": "Brunei", + "BO": "Bolivia", + "BR": "Brazil", + "BS": "Bahamas", + "BT": "Bhutan", + "BV": "Bouvet Island", + "BW": "Botswana", + "BY": "Belarus", + "BZ": "Belize", + "CA": "Canada", + "CC": "Cocos Islands", + "CD": "Democratic Republic of the Congo", + "CF": "Central African Republic", + "CG": "Republic of Congo", + "CH": "Switzerland", + "CI": "Côte d'Ivoire", + "CK": "Cook Islands", + "CL": "Chile", + "CM": "Cameroon", + "CN": "China", + "CO": "Colombia", + "CR": "Costa Rica", + "CU": "Cuba", + "CV": "Cape Verde", + "CX": "Christmas Island", + "CY": "Cyprus", + "CZ": "Czech Republic", + "DE": "Germany", + "DJ": "Djibouti", + "DK": "Denmark", + "DM": "Dominica", + "DO": "Dominican Republic", + "DZ": "Algeria", + "EC": "Ecuador", + "EE": "Estonia", + "EG": "Egypt", + "EH": "Western Sahara", + "ER": "Eritrea", + "ES": "Spain", + "ET": "Ethiopia", + "FI": "Finland", + "FJ": "Fiji", + "FK": "Falkland Islands", + "FM": "Micronesia", + "FO": "Faroe Islands", + "FR": "France", + "GA": "Gabon", + "GB": "United Kingdom", + "GD": "Grenada", + "GE": "Georgia", + "GF": "French Guiana", + "GG": "Guernsey", + "GH": "Ghana", + "GI": "Gibraltar", + "GL": "Greenland", + "GM": "Gambia", + "GN": "Guinea", + "GP": "Guadeloupe", + "GQ": "Equatorial Guinea", + "GR": "Greece", + "GS": "South Georgia and the South Sandwich Islands", + "GT": "Guatemala", + "GU": "Guam", + "GW": "Guinea-Bissau", + "GY": "Guyana", + "HK": "Hong Kong", + "HM": "Heard Island and McDonald Islands", + "HN": "Honduras", + "HR": "Croatia", + "HT": "Haiti", + "HU": "Hungary", + "ID": "Indonesia", + "IE": "Ireland", + "IL": "Israel", + "IM": "Isle of Man", + "IN": "India", + "IO": "British Indian Ocean Territory", + "IQ": "Iraq", + "IR": "Iran", + "IS": "Iceland", + "IT": "Italy", + "JE": "Jersey", + "JM": "Jamaica", + "JO": "Jordan", + "JP": "Japan", + "KE": "Kenya", + "KG": "Kyrgyzstan", + "KH": "Cambodia", + "KI": "Kiribati", + "KM": "Comoros", + "KN": "Saint Kitts and Nevis", + "KP": "North Korea", + "KR": "South Korea", + "KW": "Kuwait", + "KY": "Cayman Islands", + "KZ": "Kazakhstan", + "LA": "Laos", + "LB": "Lebanon", + "LC": "Saint Lucia", + "LI": "Liechtenstein", + "LK": "Sri Lanka", + "LR": "Liberia", + "LS": "Lesotho", + "LT": "Lithuania", + "LU": "Luxembourg", + "LV": "Latvia", + "LY": "Libya", + "MA": "Morocco", + "MC": "Monaco", + "MD": "Moldova", + "ME": "Montenegro", + "MG": "Madagascar", + "MH": "Marshall Islands", + "MK": "Macedonia", + "ML": "Mali", + "MM": "Myanmar", + "MN": "Mongolia", + "MO": "Macao", + "MP": "Northern Mariana Islands", + "MQ": "Martinique", + "MR": "Mauritania", + "MS": "Montserrat", + "MT": "Malta", + "MU": "Mauritius", + "MV": "Maldives", + "MW": "Malawi", + "MX": "Mexico", + "MY": "Malaysia", + "MZ": "Mozambique", + "NA": "Namibia", + "NC": "New Caledonia", + "NE": "Niger", + "NF": "Norfolk Island", + "NG": "Nigeria", + "NI": "Nicaragua", + "NL": "Netherlands", + "NO": "Norway", + "NP": "Nepal", + "NR": "Nauru", + "NU": "Niue", + "NZ": "New Zealand", + "OM": "Oman", + "PA": "Panama", + "PE": "Peru", + "PF": "French Polynesia", + "PG": "Papua New Guinea", + "PH": "Philippines", + "PK": "Pakistan", + "PL": "Poland", + "PM": "Saint Pierre and Miquelon", + "PN": "Pitcairn Islands", + "PR": "Puerto Rico", + "PS": "Palestina", + "PT": "Portugal", + "PW": "Palau", + "PY": "Paraguay", + "QA": "Qatar", + "RE": "Reunion", + "RO": "Romania", + "RS": "Serbia", + "RU": "Russia", + "RW": "Rwanda", + "SA": "Saudi Arabia", + "SB": "Solomon Islands", + "SC": "Seychelles", + "SD": "Sudan", + "SE": "Sweden", + "SG": "Singapore", + "SH": "Saint Helena", + "SI": "Slovenia", + "SJ": "Svalbard and Jan Mayen", + "SK": "Slovakia", + "SL": "Sierra Leone", + "SM": "San Marino", + "SN": "Senegal", + "SO": "Somalia", + "SR": "Suriname", + "ST": "Sao Tome and Principe", + "SV": "El Salvador", + "SY": "Syria", + "SZ": "Swaziland", + "TC": "Turks and Caicos Islands", + "TD": "Chad", + "TF": "French Southern Territories", + "TG": "Togo", + "TH": "Thailand", + "TJ": "Tajikistan", + "TK": "Tokelau", + "TL": "East Timor", + "TM": "Turkmenistan", + "TN": "Tunisia", + "TO": "Tonga", + "TR": "Turkey", + "TT": "Trinidad and Tobago", + "TV": "Tuvalu", + "TW": "Taiwan", + "TZ": "Tanzania", + "UA": "Ukraine", + "UG": "Uganda", + "UM": "United States Minor Outlying Islands", + "US": "United States", + "UY": "Uruguay", + "UZ": "Uzbekistan", + "VA": "Vatican City", + "VC": "Saint Vincent and the Grenadines", + "VE": "Venezuela", + "VG": "British Virgin Islands", + "VI": "Virgin Islands, U.S.", + "VN": "Vietnam", + "VU": "Vanuatu", + "WF": "Wallis and Futuna", + "WS": "Samoa", + "XK": "Kosovo", + "YE": "Yemen", + "YT": "Mayotte", + "ZA": "South Africa", + "ZM": "Zambia", + "ZW": "Zimbabwe" +} diff --git a/backend-db/modules/db/couchdb/design/index.js b/backend-db/modules/db/couchdb/design/index.js index 05b06e838f..f6bd6310bb 100644 --- a/backend-db/modules/db/couchdb/design/index.js +++ b/backend-db/modules/db/couchdb/design/index.js @@ -136,6 +136,19 @@ const designDocs = { }, }, }, + countByTeam: { + $version: 1, + views: { + view: { + map: function (doc) { + if (doc.$doctype === 'account' && doc.team) { + emit(doc.team, null); + } + }, + reduce: '_count', + }, + }, + }, }, sessions: { all: { @@ -151,6 +164,32 @@ const designDocs = { }, }, }, + teams: { + all: { + $version: 1, + views: { + view: { + map: function (doc) { + if (doc.$doctype === 'team') { + emit(doc._id, doc); + } + }, + }, + }, + }, + byTeamId: { + $version: 1, + views: { + view: { + map: function (doc) { + if (doc.$doctype === 'team') { + emit(doc._id, doc); + } + }, + }, + }, + }, + }, areas: { all: { $version: 1, @@ -374,6 +413,31 @@ const designDocs = { }, }, }, + countByTeam: { + $version: 1, + views: { + view: { + map: function (doc) { + if (doc.$doctype === 'trashpoint' && doc.team) { + emit(doc.team, null); + } + }, + reduce: '_count', + }, + }, + }, + byTeam: { + $version: 1, + views: { + view: { + map: function (doc) { + if (doc.$doctype === 'trashpoint' && doc.team) { + emit([doc.team, doc.updatedAt], doc); + } + } + }, + }, + }, }, }; diff --git a/backend-db/modules/db/couchdb/index.js b/backend-db/modules/db/couchdb/index.js index 86d5775f1f..467640afaa 100644 --- a/backend-db/modules/db/couchdb/index.js +++ b/backend-db/modules/db/couchdb/index.js @@ -10,606 +10,715 @@ const util = require('module-util'); const cdb = require('./driver'); const adapter = require('./adapter'); -const types = require('../types'); -const grid = require('../../geo/grid'); +const types = require('../types'); +const grid = require('../../geo/grid'); +const gravatar = require('gravatar'); +const _ = require('lodash'); +const COUNTRY_LIST = require('./countries'); const RETRY_CONFLICTS = 3; +const CCs = ['AD', 'AE', 'AF', 'AG', 'AI', 'AL', 'AM', 'AO', 'AQ', 'AR', 'AS', 'AT', 'AU', 'AW', 'AX', 'AZ', 'BA', 'BB', 'BD', 'BE', 'BF', 'BG', 'BH', 'BI', 'BJ', 'BL', 'BM', 'BN', 'BO', 'BQ', 'BR', 'BS', 'BT', 'BV', 'BW', 'BY', 'BZ', 'CA', 'CC', 'CD', 'CF', 'CG', 'CH', 'CI', 'CK', 'CL', 'CM', 'CN', 'CO', 'CR', 'CU', 'CV', 'CW', 'CX', 'CY', 'CZ', 'DE', 'DJ', 'DK', 'DM', 'DO', 'DZ', 'EC', 'EE', 'EG', 'EH', 'ER', 'ES', 'ET', 'FI', 'FJ', 'FK', 'FM', 'FO', 'FR', 'GA', 'GB', 'GD', 'GE', 'GF', 'GG', 'GH', 'GI', 'GL', 'GM', 'GN', 'GP', 'GQ', 'GR', 'GS', 'GT', 'GU', 'GW', 'GY', 'HK', 'HM', 'HN', 'HR', 'HT', 'HU', 'ID', 'IE', 'IL', 'IM', 'IN', 'IO', 'IQ', 'IR', 'IS', 'IT', 'JE', 'JM', 'JO', 'JP', 'KE', 'KG', 'KH', 'KI', 'KM', 'KN', 'KP', 'KR', 'KW', 'KY', 'KZ', 'LA', 'LB', 'LC', 'LI', 'LK', 'LR', 'LS', 'LT', 'LU', 'LV', 'LY', 'MA', 'MC', 'MD', 'ME', 'MF', 'MG', 'MH', 'MK', 'ML', 'MM', 'MN', 'MO', 'MP', 'MQ', 'MR', 'MS', 'MT', 'MU', 'MV', 'MW', 'MX', 'MY', 'MZ', 'NA', 'NC', 'NE', 'NF', 'NG', 'NI', 'NL', 'NO', 'NP', 'NR', 'NU', 'NZ', 'OM', 'PA', 'PE', 'PF', 'PG', 'PH', 'PK', 'PL', 'PM', 'PN', 'PR', 'PS', 'PT', 'PW', 'PY', 'QA', 'RE', 'RO', 'RS', 'RU', 'RW', 'SA', 'SB', 'SC', 'SD', 'SE', 'SG', 'SH', 'SI', 'SJ', 'SK', 'SL', 'SM', 'SN', 'SO', 'SR', 'SS', 'ST', 'SV', 'SX', 'SY', 'SZ', 'TC', 'TD', 'TF', 'TG', 'TH', 'TJ', 'TK', 'TL', 'TM', 'TN', 'TO', 'TR', 'TT', 'TV', 'TZ', 'UA', 'UG', 'UM', 'US', 'UY', 'UZ', 'VA', 'VC', 'VE', 'VG', 'VI', 'VN', 'VU', 'WF', 'WS', 'YE', 'YT', 'ZA', 'ZM', 'ZW'] + +const teamImages = [ + 'https://ucarecdn.com/069167ae-5519-475b-a6bf-69bee37a1200/Reddie.png', + 'https://ucarecdn.com/3ca80cb0-2bae-43e1-a8b4-16b6a1c41145/Yellowish.png', + 'https://ucarecdn.com/478662d2-74d6-458e-8325-feef48697f26/Brownie.png', + 'https://ucarecdn.com/cdb9551f-d911-4356-bd75-ba0df7460ce9/Orangey.png', + 'https://ucarecdn.com/7c0a324e-3447-495b-90a9-f7b5a6958d36/Yellow.png', + 'https://ucarecdn.com/82023a51-d50a-4f2f-aa0f-7e3a938de06b/Blueish.png' +] + const layer = { - //======================================================== - // COMMON - //======================================================== - ready: () => cdb.SERVER_READY, + //======================================================== + // COMMON + //======================================================== + ready: () => cdb.SERVER_READY, - //======================================================== - // DATASETS - //======================================================== - getDataset: async id => { - return await adapter.getOneEntityById('Dataset', '_design/all/_view/view', id); - }, - getAllDatasets: async () => { - return await adapter.getEntities('Dataset', '_design/all/_view/view', {sorted: false}); - }, - createDataset: async type => { - const id = util.uuid.random(); - await adapter.createDocument('Dataset', id, { - type, - }, { - createdAt: util.time.getNowUTC(), - }); - return await layer.getDataset(id); - }, + //======================================================== + // DATASETS + //======================================================== + getDataset: async id => { + return await adapter.getOneEntityById('Dataset', '_design/all/_view/view', id); + }, + getAllDatasets: async () => { + return await adapter.getEntities('Dataset', '_design/all/_view/view', {sorted: false}); + }, + createDataset: async type => { + const id = util.uuid.random(); + await adapter.createDocument('Dataset', id, { + type, + }, { + createdAt: util.time.getNowUTC(), + }); + return await layer.getDataset(id); + }, - //======================================================== - // ACCOUNTS - //======================================================== - getAccounts: async (pageSize = 10, pageNumber = 1) => { - return await adapter.getEntities( - 'Account', - '_design/byName/_view/view', - { - sorted: true, - limit: pageSize, - skip: pageSize * (pageNumber - 1), - } - ); - }, - getAccountsByCountry: async (country, pageSize = 10, pageNumber = 1) => { - return await adapter.getEntities( - 'Account', - '_design/byCountryAndName/_view/view', - { - sorted: true, - limit: pageSize, - skip: pageSize * (pageNumber - 1), - startkey: [country], - endkey: [country, {}], - } - ); - }, - getAccountsByNameSearch: async (nameSearch, pageSize = 10, pageNumber = 1, country = null) => { - return await adapter.getEntities( - 'Account', - '_design/byNamePieces/_view/view', - { - reduce: false, - sorted: true, - limit: pageSize, - skip: pageSize * (pageNumber - 1), - startkey: country ? [nameSearch, country] : [nameSearch], - endkey: country ? [nameSearch, country, {}] : [nameSearch, {}], - } - ); - }, - countAccounts: async () => { - const ret = await adapter.getRawDocs('Account', '_design/countAll/_view/view', {}); - if (!ret.length) { - return 0; - } - return parseInt(ret.pop()); - }, - countAccountsForCountry: async country => { - const ret = await adapter.getRawDocs('Account', '_design/countByCountry/_view/view', { - key: country, - group: true, - }); - if (!ret.length) { - return 0; - } - return parseInt(ret.pop()); - }, - countAccountsForNameSearch: async (nameSearch, country = null) => { - const ret = await adapter.getRawDocs('Account', '_design/byNamePieces/_view/view', { - startkey: country ? [nameSearch, country] : [nameSearch], - endkey: country ? [nameSearch, country, {}] : [nameSearch, {}], - reduce: true, - group: false, - }); - if (!ret.length) { - return 0; - } - return parseInt(ret.pop()); - }, - getAccount: async id => { - return await adapter.getOneEntityById('Account', '_design/all/_view/view', id); - }, - getRawAccountDoc: async id => { - return await adapter.getOneRawDocById('Account', '_design/all/_view/view', id); - }, - modifyAccount: async (id, who, update, rawAccountDoc = null) => { - return await adapter.modifyDocument( - 'Account', - rawAccountDoc || await layer.getRawAccountDoc(id), - update, - { - updatedAt: util.time.getNowUTC(), - updatedBy: who, - } - ); - }, - createAccount: async (id, name, email, role, pictureURL) => { - await adapter.createDocument('Account', id, { - name, - email, - role, - pictureURL, - }, { - locked: false, - createdAt: util.time.getNowUTC(), - createdBy: id, - }); - return await layer.getAccount(id); - }, - updateAccountTerms: async id => { - const account = await layer.getRawAccountDoc(id); - if (!account) { - return false; - } - if (account.termsAcceptedAt) { - return true; - } - const ret = await adapter.modifyDocument( - 'Account', - account, - {}, - { - termsAcceptedAt: util.time.getNowUTC(), - updatedAt: util.time.getNowUTC(), - updatedBy: id, - } - ); - if (!ret) { - return false; - } - return true; - }, - setAccountLock: async (accountId, locked, updatedBy, rawAccountDoc = null) => { - rawAccountDoc = rawAccountDoc || await layer.getRawAccountDoc(accountId); - if (!rawAccountDoc) { - return false; - } - const ret = await adapter.modifyDocument( - 'Account', - rawAccountDoc, - {}, - { - locked, - updatedAt: util.time.getNowUTC(), - updatedBy, - } - ); - if (!ret) { - return false; - } - return true; - }, + //======================================================== + // ACCOUNTS + //======================================================== + getAccounts: async (pageSize = 10, pageNumber = 1) => { + return await adapter.getEntities( + 'Account', + '_design/byName/_view/view', + { + sorted: true, + limit: pageSize, + skip: pageSize * (pageNumber - 1), + } + ); + }, + getAccountsByCountry: async (country, pageSize = 10, pageNumber = 1) => { + return await adapter.getEntities( + 'Account', + '_design/byCountryAndName/_view/view', + { + sorted: true, + limit: pageSize, + skip: pageSize * (pageNumber - 1), + startkey: [country], + endkey: [country, {}], + } + ); + }, + getAccountsByNameSearch: async (nameSearch, pageSize = 10, pageNumber = 1, country = null) => { + return await adapter.getEntities( + 'Account', + '_design/byNamePieces/_view/view', + { + reduce: false, + sorted: true, + limit: pageSize, + skip: pageSize * (pageNumber - 1), + startkey: country ? [nameSearch, country] : [nameSearch], + endkey: country ? [nameSearch, country, {}] : [nameSearch, {}], + } + ); + }, + countAccounts: async () => { + const ret = await adapter.getRawDocs('Account', '_design/countAll/_view/view', {}); + if (!ret.length) { + return 0; + } + return parseInt(ret.pop()); + }, + countAccountsForCountry: async country => { + const ret = await adapter.getRawDocs('Account', '_design/countByCountry/_view/view', { + key: country, + group: true, + }); + if (!ret.length) { + return 0; + } + return parseInt(ret.pop()); + }, + countAccountsForTeam: async teamId => { + const ret = await adapter.getRawDocs( + 'Account', + '_design/countByTeam/_view/view', { + key: teamId, + group: true, + }); + if (!ret.length) { + return 0; + } + return parseInt(ret.pop()); + }, + countAccountsForNameSearch: async (nameSearch, country = null) => { + const ret = await adapter.getRawDocs('Account', '_design/byNamePieces/_view/view', { + startkey: country ? [nameSearch, country] : [nameSearch], + endkey: country ? [nameSearch, country, {}] : [nameSearch, {}], + reduce: true, + group: false, + }); + if (!ret.length) { + return 0; + } + return parseInt(ret.pop()); + }, + getAccount: async id => { + return await adapter.getOneEntityById('Account', '_design/all/_view/view', id); + }, + getRawAccountDoc: async id => { + return await adapter.getOneRawDocById('Account', '_design/all/_view/view', id); + }, + modifyAccount: async (id, who, update, rawAccountDoc = null) => { + return await adapter.modifyDocument( + 'Account', + rawAccountDoc || await layer.getRawAccountDoc(id), + update, + { + updatedAt: util.time.getNowUTC(), + updatedBy: who, + } + ); + }, + createAccount: async (id, name, email, role, pictureURL, team) => { + await adapter.createDocument('Account', id, { + name, + email, + role, + pictureURL, + team + }, { + locked: false, + createdAt: util.time.getNowUTC(), + createdBy: id, + }); + return await layer.getAccount(id); + }, + updateAccountTerms: async id => { + const account = await layer.getRawAccountDoc(id); + if (!account) { + return false; + } + if (account.termsAcceptedAt) { + return true; + } + const ret = await adapter.modifyDocument( + 'Account', + account, + {}, + { + termsAcceptedAt: util.time.getNowUTC(), + updatedAt: util.time.getNowUTC(), + updatedBy: id, + } + ); + if (!ret) { + return false; + } + return true; + }, + setAccountLock: async (accountId, locked, updatedBy, rawAccountDoc = null) => { + rawAccountDoc = rawAccountDoc || await layer.getRawAccountDoc(accountId); + if (!rawAccountDoc) { + return false; + } + const ret = await adapter.modifyDocument( + 'Account', + rawAccountDoc, + {}, + { + locked, + updatedAt: util.time.getNowUTC(), + updatedBy, + } + ); + if (!ret) { + return false; + } + return true; + }, - //======================================================== - // SESSIONS - //======================================================== - getSession: async id => { - return await adapter.getOneEntityById('Session', '_design/all/_view/view', id); - }, - touchSession: async (id, expirationDays) => { - // XXX: This function is particularly susceptible to race conditions. - // There are updates coming in sometimes as fast as 10ms behind each other. - // We retry the timestamp update several times, since it's the only method - // that works with Couch's optimistic locking. A successful update breaks - // the cycle. A conflict error retries. Any other error throws. - for (let i = 0; i < RETRY_CONFLICTS; i++) { - try { - return await adapter.modifyDocument( - 'Session', - await adapter.getOneRawDocById('Session', '_design/all/_view/view', id), - { - expiresAt: util.time.getNowUTCShifted(expirationDays, 'd'), - updatedAt: util.time.getNowUTC(), - } - ); - } catch (e) { - if (e.code !== 'EDOCCONFLICT') { - throw e; - } - } - } - }, - createOrTouchSession: async (accountId, expirationDays) => { - const id = types.Session.makeSessionIdFromAccountId(accountId); - // assume session exists, attempt to update it - const session = await layer.touchSession(id, expirationDays); - // if it was there, all done, return it - if (session) { - return session; - } - // we didn't find it, so create it and return it - await adapter.createDocument('Session', id, { - accountId, - }, { + //======================================================== + // SESSIONS + //======================================================== + getSession: async id => { + return await adapter.getOneEntityById('Session', '_design/all/_view/view', id); + }, + touchSession: async (id, expirationDays) => { + // XXX: This function is particularly susceptible to race conditions. + // There are updates coming in sometimes as fast as 10ms behind each other. + // We retry the timestamp update several times, since it's the only method + // that works with Couch's optimistic locking. A successful update breaks + // the cycle. A conflict error retries. Any other error throws. + for (let i = 0; i < RETRY_CONFLICTS; i++) { + try { + return await adapter.modifyDocument( + 'Session', + await adapter.getOneRawDocById('Session', '_design/all/_view/view', id), + { expiresAt: util.time.getNowUTCShifted(expirationDays, 'd'), - createdAt: util.time.getNowUTC(), updatedAt: util.time.getNowUTC(), - }); - return await layer.getSession(id); - }, - verifyAndTouchSession: async (id, expirationDays) => { - const session = await layer.getSession(id); - if (!session) { - return false; - } - // check expiration time - const now = util.time.getNowUTC(); - if (now >= session.expiresAt) { - await layer.removeSession(id); - return false; - } - // session is ok, extend the expiration time - return await layer.touchSession(id, expirationDays); - }, - removeSession: async id => { - return await adapter.removeDocument('Session', '_design/all/_view/view', id); - }, - - //======================================================== - // TRASHPOINTS - //======================================================== - getTrashpoint: async id => { - return await adapter.getOneEntityById('Trashpoint', '_design/all/_view/view', id); - }, - getRawTrashpointDoc: async id => { - return await adapter.getOneRawDocById('Trashpoint', '_design/all/_view/view', id); - }, - getAdminTrashpoints: async (pageSize = 10, pageNumber = 1) => { - return await adapter.getEntities( - 'Trashpoint', - '_design/byCreationTime/_view/view', - { - sorted: true, - limit: pageSize, - skip: pageSize * (pageNumber - 1), - descending: true, - } + } ); - }, - getAreaTrashpoints: async (areaCode, pageSize = 10, pageNumber = 1) => { - return await adapter.getEntities( - 'Trashpoint', - '_design/byArea/_view/view', - { - sorted: true, - limit: pageSize, - skip: pageSize * (pageNumber - 1), - descending: true, //XXX: when descending, startkey and endkey are reversed - startkey: [areaCode, {}], - endkey: [areaCode], - } - ); - }, - getUserTrashpoints: async (userId, pageSize = 10, pageNumber = 1) => { - return await adapter.getEntities( - 'Trashpoint', - '_design/byCreatingUser/_view/view', - { - sorted: true, - descending: true, //XXX: when desc=true, startkey and endkey are reversed - startkey: [userId, {}], - endkey: [userId], - limit: pageSize, - skip: pageSize * (pageNumber - 1), - } - ); - }, - getGridCellTrashpoints: async (datasetId, cellSize, gridCoord) => { - const scale = grid.getScaleForCellSize(cellSize); - const ret = await adapter.getEntities( - 'Trashpoint', - `_design/byGridCell${scale}/_view/view`, - { - startkey: [datasetId, gridCoord], - endkey: [datasetId, gridCoord], - 'inclusive_end': true, - sorted: false, - } - ); - return ret.filter(val => val !== null); - }, - getOverviewTrashpoints: async (datasetId, cellSize, nwLat, nwLong, seLat, seLong) => { - const scale = grid.getScaleForCellSize(cellSize); - const ret = await layer.getOverview('Trashpoint', `_design/isolated${scale}/_view/view`, - datasetId, scale, nwLat, nwLong, seLat, seLong); - return ret.filter(row => adapter.rawDocToEntity('Trashpoint', row)); - }, - getOverviewClusters: async (datasetId, cellSize, nwLat, nwLong, seLat, seLong) => { - const scale = grid.getScaleForCellSize(cellSize); - const ret = await layer.getOverview('Trashpoint', `_design/clusters${scale}/_view/view`, - datasetId, scale, nwLat, nwLong, seLat, seLong, { - 'group_level': 2, - }); - return ret.filter(row => adapter.rawDocToEntity('Cluster', row)); - }, - getOverview: async (datatype, view, datasetId, scale, nwLat, nwLong, seLat, seLong, extraViewParams = {}) => { - const cellCoords = grid.geoCornersToCells( - [nwLong, nwLat], [seLong, seLat], grid.SCALES[scale]); - const ret = await adapter.getRawDocs( - datatype, - view, - Object.assign({ - startkey: [datasetId, cellCoords[0]], - endkey: [datasetId, cellCoords[1]], - 'inclusive_end': true, - group: true, - reduce: true, - sorted: false, - }, extraViewParams), - false // leave data untouched, we need the keys - ); - if (!ret || !ret.data || !ret.data.rows) { - return []; + } catch (e) { + if (e.code !== 'EDOCCONFLICT') { + throw e; } - return ret.data.rows - .filter(row => row.value !== null) - //XXX: filter cell coords here because couch stops after matching the 1st coord and returns cells that are vertically outside the area - .filter(row => grid.cellIsInGridArea(row.key[1], cellCoords[0], cellCoords[1])) - .map(row => { - const val = row.value; - val.coordinates = row.key[1]; - return val; - }) - ; - }, - countUserTrashpoints: async userId => { - const ret = await adapter.getRawDocs( - 'Trashpoint', - '_design/countByCreatingUser/_view/view', { - key: userId, - }); - if (!ret.length) { - return 0; - } - return parseInt(ret.pop()); - }, - countTrashpoints: async () => { - const ret = await adapter.getRawDocs( - 'Trashpoint', - '_design/countAll/_view/view', - { - group: false, - } - ); - if (!ret.length) { - return 0; - } - return parseInt(ret.pop()); - }, - modifyTrashpoint: async (id, who, update, rawTrashpointDoc = null) => { - return await adapter.modifyDocument( - 'Trashpoint', - rawTrashpointDoc || await layer.getRawTrashpointDoc(id), - update, - { - updatedAt: util.time.getNowUTC(), - updatedBy: who, - } - ); - }, - touchTrashpoint: async (id, who) => { - return await layer.modifyTrashpoint(id, who, {}); - }, - createTrashpoint: async (datasetId, who, create) => { - create.counter = 1, //FIXME: generate this number using a couchbase atomic counter - create.datasetId = datasetId; - create.hashtags = create.hashtags || []; + } + } + }, + createOrTouchSession: async (accountId, expirationDays) => { + const id = types.Session.makeSessionIdFromAccountId(accountId); + // assume session exists, attempt to update it + const session = await layer.touchSession(id, expirationDays); + // if it was there, all done, return it + if (session) { + return session; + } + // we didn't find it, so create it and return it + await adapter.createDocument('Session', id, { + accountId, + }, { + expiresAt: util.time.getNowUTCShifted(expirationDays, 'd'), + createdAt: util.time.getNowUTC(), + updatedAt: util.time.getNowUTC(), + }); + return await layer.getSession(id); + }, + verifyAndTouchSession: async (id, expirationDays) => { + const session = await layer.getSession(id); + if (!session) { + return false; + } + // check expiration time + const now = util.time.getNowUTC(); + if (now >= session.expiresAt) { + await layer.removeSession(id); + return false; + } + // session is ok, extend the expiration time + return await layer.touchSession(id, expirationDays); + }, + removeSession: async id => { + return await adapter.removeDocument('Session', '_design/all/_view/view', id); + }, - const id = util.uuid.random(); - await adapter.createDocument('Trashpoint', id, create, { - updatedAt: util.time.getNowUTC(), - updatedBy: who, - createdAt: util.time.getNowUTC(), - createdBy: who, - }); + //======================================================== + // TRASHPOINTS + //======================================================== + getTrashpoint: async id => { + return await adapter.getOneEntityById('Trashpoint', '_design/all/_view/view', id); + }, + getRawTrashpointDoc: async id => { + return await adapter.getOneRawDocById('Trashpoint', '_design/all/_view/view', id); + }, + getAdminTrashpoints: async (pageSize = 10, pageNumber = 1) => { + return await adapter.getEntities( + 'Trashpoint', + '_design/byCreationTime/_view/view', + { + sorted: true, + limit: pageSize, + skip: pageSize * (pageNumber - 1), + descending: true, + } + ); + }, + getAreaTrashpoints: async (areaCode, pageSize = 10, pageNumber = 1) => { + return await adapter.getEntities( + 'Trashpoint', + '_design/byArea/_view/view', + { + sorted: true, + limit: pageSize, + skip: pageSize * (pageNumber - 1), + descending: true, //XXX: when descending, startkey and endkey are reversed + startkey: [areaCode, {}], + endkey: [areaCode], + } + ); + }, + getUserTrashpoints: async (userId, pageSize = 10, pageNumber = 1) => { + return await adapter.getEntities( + 'Trashpoint', + '_design/byCreatingUser/_view/view', + { + sorted: true, + descending: true, //XXX: when desc=true, startkey and endkey are reversed + startkey: [userId, {}], + endkey: [userId], + limit: pageSize, + skip: pageSize * (pageNumber - 1), + } + ); + }, + getGridCellTrashpoints: async (datasetId, cellSize, gridCoord) => { + const scale = grid.getScaleForCellSize(cellSize); + const ret = await adapter.getEntities( + 'Trashpoint', + `_design/byGridCell${scale}/_view/view`, + { + startkey: [datasetId, gridCoord], + endkey: [datasetId, gridCoord], + 'inclusive_end': true, + sorted: false, + } + ); + return ret.filter(val => val !== null); + }, + getOverviewTrashpoints: async (datasetId, cellSize, nwLat, nwLong, seLat, seLong) => { + const scale = grid.getScaleForCellSize(cellSize); + const ret = await layer.getOverview('Trashpoint', `_design/isolated${scale}/_view/view`, + datasetId, scale, nwLat, nwLong, seLat, seLong); + return ret.filter(row => adapter.rawDocToEntity('Trashpoint', row)); + }, + getOverviewClusters: async (datasetId, cellSize, nwLat, nwLong, seLat, seLong) => { + const scale = grid.getScaleForCellSize(cellSize); + const ret = await layer.getOverview('Trashpoint', `_design/clusters${scale}/_view/view`, + datasetId, scale, nwLat, nwLong, seLat, seLong, { + 'group_level': 2, + }); + return ret.filter(row => adapter.rawDocToEntity('Cluster', row)); + }, + getOverview: async (datatype, view, datasetId, scale, nwLat, nwLong, seLat, seLong, extraViewParams = {}) => { + const cellCoords = grid.geoCornersToCells( + [nwLong, nwLat], [seLong, seLat], grid.SCALES[scale]); + const ret = await adapter.getRawDocs( + datatype, + view, + Object.assign({ + startkey: [datasetId, cellCoords[0]], + endkey: [datasetId, cellCoords[1]], + 'inclusive_end': true, + group: true, + reduce: true, + sorted: false, + }, extraViewParams), + false // leave data untouched, we need the keys + ); + if (!ret || !ret.data || !ret.data.rows) { + return []; + } + return ret.data.rows + .filter(row => row.value !== null) + //XXX: filter cell coords here because couch stops after matching the 1st coord and returns cells that are vertically outside the area + .filter(row => grid.cellIsInGridArea(row.key[1], cellCoords[0], cellCoords[1])) + .map(row => { + const val = row.value; + val.coordinates = row.key[1]; + return val; + }) + ; + }, + countUserTrashpoints: async userId => { + const ret = await adapter.getRawDocs( + 'Trashpoint', + '_design/countByCreatingUser/_view/view', { + key: userId, + }); + if (!ret.length) { + return 0; + } + return parseInt(ret.pop()); + }, + countTeamTrashpoints: async teamId => { + const ret = await adapter.getRawDocs( + 'Trashpoint', + '_design/countByTeam/_view/view', { + key: teamId, + }); + if (!ret.length) { + return 0; + } + return parseInt(ret.pop()); + }, + getTeamTrashpoints: async (teamId, amount) => { + const trashpoints = await adapter.getEntities( + 'Trashpoint', + '_design/byTeam/_view/view', { + descending: true, //XXX: when desc=true, startkey and endkey are reversed + startkey: [teamId, {}], + endkey: [teamId], + sorted: true + }) + let groupCount = {} + if (trashpoints.length) { + _.forEach(_.groupBy(trashpoints, 'status'), (group, status) => groupCount[status] = group.length); + } + const cutedTrashpoints = amount > 0 ? trashpoints.slice(-amount) : trashpoints; + return [cutedTrashpoints, groupCount]; + }, + countTrashpoints: async () => { + const ret = await adapter.getRawDocs( + 'Trashpoint', + '_design/countAll/_view/view', + { + group: false, + } + ); + if (!ret.length) { + return 0; + } + return parseInt(ret.pop()); + }, + modifyTrashpoint: async (id, who, update, rawTrashpointDoc = null) => { + return await adapter.modifyDocument( + 'Trashpoint', + rawTrashpointDoc || await layer.getRawTrashpointDoc(id), + update, + { + updatedAt: util.time.getNowUTC(), + updatedBy: who, + } + ); + }, + touchTrashpoint: async (id, who) => { + return await layer.modifyTrashpoint(id, who, {}); + }, + createTrashpoint: async (datasetId, who, create) => { + create.counter = 1, //FIXME: generate this number using a couchbase atomic counter + create.datasetId = datasetId; + create.hashtags = create.hashtags || []; - return await layer.getTrashpoint(id); - }, - removeTrashpoint: async id => { - return await adapter.removeDocument('Trashpoint', '_design/all/_view/view', id); - }, + const id = util.uuid.random(); + await adapter.createDocument('Trashpoint', id, create, { + updatedAt: util.time.getNowUTC(), + updatedBy: who, + createdAt: util.time.getNowUTC(), + createdBy: who, + }); - //======================================================== - // IMAGES - //======================================================== - getImage: async id => { - return await adapter.getOneEntityById('Image', '_design/all/_view/view', id); - }, - allocateImage: async (type, trashpointId, who, parentId = undefined) => { - const id = util.uuid.random(); - await adapter.createDocument('Image', id, { - type, - status: types.Image.STATUS_PENDING, - trashpointId, - parentId, - }, { - updatedAt: util.time.getNowUTC(), - updatedBy: who, - createdAt: util.time.getNowUTC(), - createdBy: who, - }); + return await layer.getTrashpoint(id); + }, + removeTrashpoint: async id => { + return await adapter.removeDocument('Trashpoint', '_design/all/_view/view', id); + }, - return await layer.getImage(id); - }, - modifyImage: async (id, who, update, rawImageDoc = null) => { - return await adapter.modifyDocument( - 'Image', - rawImageDoc || await adapter.getOneRawDocById('Image', '_design/all/_view/view', id), - update, - { - updatedAt: util.time.getNowUTC(), - updatedBy: who, - } - ); - }, - removeImage: async id => { - return await adapter.removeDocument('Image', '_design/all/_view/view', id); - }, - getTrashpointImages: async (trashpointId, status = null) => { - const ret = await adapter.getEntities( - 'Image', - '_design/byTrashpointAndStatusAndCreation/_view/view', - { - descending: true, //XXX: when desc=true, startkey and endkey are reversed - startkey: status ? [trashpointId, status, {}] : [trashpointId, {}], - endkey: status ? [trashpointId, status] : [trashpointId], - sorted: true, - } - ); - return ret; - }, - getChildImages: async (parentId, trashpointId) => { - const ret = await adapter.getEntities( - 'Image', - '_design/byTrashpointAndParent/_view/view', - { - keys: [ - [trashpointId, parentId], - ], - sorted: false, - } - ); - return ret; - }, + //======================================================== + // IMAGES + //======================================================== + getImage: async id => { + return await adapter.getOneEntityById('Image', '_design/all/_view/view', id); + }, + allocateImage: async (type, trashpointId, who, parentId = undefined) => { + const id = util.uuid.random(); + await adapter.createDocument('Image', id, { + type, + status: types.Image.STATUS_PENDING, + trashpointId, + parentId, + }, { + updatedAt: util.time.getNowUTC(), + updatedBy: who, + createdAt: util.time.getNowUTC(), + createdBy: who, + }); - //======================================================== - // AREAS - //======================================================== - getArea: async id => { - return await adapter.getOneEntityById('Area', '_design/all/_view/view', id); - }, - getAllAreas: async () => { - const ret = await adapter.getEntities('Area', '_design/all/_view/view', {sorted: false}); - return ret; - }, - getAreasByParent: async parentId => { - return await adapter.getEntities( - 'Area', - `_design/byParent/_view/view`, - { - startkey: parentId || null, - endkey: parentId || null, - 'inclusive_end': true, - sorted: false, - } - ); - }, - getAreasForLeader: async leaderId => { - return await adapter.getEntities( - 'Area', - `_design/byLeader/_view/view`, - { - startkey: leaderId, - endkey: leaderId, - 'inclusive_end': true, - sorted: false, - } - ); - }, - countLeaderAreas: async leaderId => { - const ret = await adapter.getRawDocs('Area', `_design/countByLeader/_view/view`, { - key: leaderId, + return await layer.getImage(id); + }, + modifyImage: async (id, who, update, rawImageDoc = null) => { + return await adapter.modifyDocument( + 'Image', + rawImageDoc || await adapter.getOneRawDocById('Image', '_design/all/_view/view', id), + update, + { + updatedAt: util.time.getNowUTC(), + updatedBy: who, + } + ); + }, + removeImage: async id => { + return await adapter.removeDocument('Image', '_design/all/_view/view', id); + }, + getTrashpointImages: async (trashpointId, status = null) => { + const ret = await adapter.getEntities( + 'Image', + '_design/byTrashpointAndStatusAndCreation/_view/view', + { + descending: true, //XXX: when desc=true, startkey and endkey are reversed + startkey: status ? [trashpointId, status, {}] : [trashpointId, {}], + endkey: status ? [trashpointId, status] : [trashpointId], + sorted: true, + } + ); + return ret; + }, + getChildImages: async (parentId, trashpointId) => { + const ret = await adapter.getEntities( + 'Image', + '_design/byTrashpointAndParent/_view/view', + { + keys: [ + [trashpointId, parentId], + ], + sorted: false, + } + ); + return ret; + }, + + //======================================================== + // AREAS + //======================================================== + getArea: async id => { + return await adapter.getOneEntityById('Area', '_design/all/_view/view', id); + }, + getAllAreas: async () => { + const ret = await adapter.getEntities('Area', '_design/all/_view/view', {sorted: false}); + return ret; + }, + getAreasByParent: async parentId => { + return await adapter.getEntities( + 'Area', + `_design/byParent/_view/view`, + { + startkey: parentId || null, + endkey: parentId || null, + 'inclusive_end': true, + sorted: false, + } + ); + }, + getAreasForLeader: async leaderId => { + return await adapter.getEntities( + 'Area', + `_design/byLeader/_view/view`, + { + startkey: leaderId, + endkey: leaderId, + 'inclusive_end': true, + sorted: false, + } + ); + }, + countLeaderAreas: async leaderId => { + const ret = await adapter.getRawDocs('Area', `_design/countByLeader/_view/view`, { + key: leaderId, + }); + if (!ret.length) { + return 0; + } + return parseInt(ret.pop()); + }, + getRawAreaDoc: async id => { + return await adapter.getOneRawDocById('Area', '_design/all/_view/view', id); + }, + modifyArea: async (id, who, update, rawAreaDoc = null) => { + return await adapter.modifyDocument( + 'Area', + rawAreaDoc || await layer.getRawAreaDoc(id), + update, + { + updatedAt: util.time.getNowUTC(), + updatedBy: who || undefined, + } + ); + }, + seedAreas: async (metadata) => { + const ret = await layer.getAllAreas(); + if (!Array.isArray(ret)) { + return false; + } + const existingAreas = ret.reduce((prev, area) => { + prev[area.id] = area; + return prev; + }, {}); + for (let area of metadata) { + if (!existingAreas[area.code]) { + await adapter.createDocument('Area', area.code, { + name: area.name, + parentId: area.parent || undefined, }); - if (!ret.length) { - return 0; - } - return parseInt(ret.pop()); - }, - getRawAreaDoc: async id => { - return await adapter.getOneRawDocById('Area', '_design/all/_view/view', id); - }, - modifyArea: async (id, who, update, rawAreaDoc = null) => { - return await adapter.modifyDocument( - 'Area', - rawAreaDoc || await layer.getRawAreaDoc(id), - update, - { - updatedAt: util.time.getNowUTC(), - updatedBy: who || undefined, - } - ); - }, - seedAreas: async (metadata) => { - const ret = await layer.getAllAreas(); - if (!Array.isArray(ret)) { - return false; - } - const existingAreas = ret.reduce((prev, area) => { - prev[area.id] = area; - return prev; - }, {}); - for (let area of metadata) { - if (!existingAreas[area.code]) { - await adapter.createDocument('Area', area.code, { - name: area.name, - parentId: area.parent || undefined, - }); - } - else { - if (existingAreas[area.code].name !== area.name - || existingAreas[area.code].parentId !== area.parent - ) { - await layer.modifyArea(area.code, null, { - name: area.name, - parentId: area.parent || undefined, - }); - } - } + } + else { + if (existingAreas[area.code].name !== area.name + || existingAreas[area.code].parentId !== area.parent + ) { + await layer.modifyArea(area.code, null, { + name: area.name, + parentId: area.parent || undefined, + }); } + } + } + return true; + }, + countAreaTrashpoints: async (areaCode, byStatus = false) => { + const ret = await adapter.getRawDocs( + 'Trashpoint', + '_design/countAreaStatus/_view/view', { + group: true, + 'group_level': byStatus ? 2 : 1, + startkey: [areaCode], + endkey: [areaCode, {}], + }, + byStatus ? false : true // for statuses we'll need the keys + ); + if (byStatus) { + if (!ret || !ret.data || !ret.data.rows || !ret.data.rows.length) { + return {}; + } + return ret.data.rows.reduce((all, row) => { + all[row.key[1]] = row.value; + return all; + }, {}); + } + else { + if (!ret.length) { + return 0; + } + return parseInt(ret.pop()); + } + }, + areaIsInherited: async (leaderId, areaId) => { + // compute area ancestors + const ancestorAreas = []; + areaId.split('.').reduce((prefix, codeBit) => { + ancestorAreas.push(prefix + codeBit); + return prefix + codeBit + '.'; + }, ''); + ancestorAreas.pop(); + // fetch areas where this user is leader + const assignedAreas = (await layer.getAreasForLeader(leaderId)).map(area => area.id); + if (!assignedAreas.length) { + return false; + } + // see if any of them is among the ancestors + for (let ancestorCode of ancestorAreas) { + if (assignedAreas.indexOf(ancestorCode) !== -1) { return true; - }, - countAreaTrashpoints: async (areaCode, byStatus = false) => { - const ret = await adapter.getRawDocs( - 'Trashpoint', - '_design/countAreaStatus/_view/view', { - group: true, - 'group_level': byStatus ? 2 : 1, - startkey: [areaCode], - endkey: [areaCode, {}], - }, - byStatus ? false : true // for statuses we'll need the keys - ); - if (byStatus) { - if (!ret || !ret.data || !ret.data.rows || !ret.data.rows.length) { - return {}; - } - return ret.data.rows.reduce((all, row) => { - all[row.key[1]] = row.value; - return all; - }, {}); - } - else { - if (!ret.length) { - return 0; - } - return parseInt(ret.pop()); - } - }, - areaIsInherited: async (leaderId, areaId) => { - // compute area ancestors - const ancestorAreas = []; - areaId.split('.').reduce((prefix, codeBit) => { - ancestorAreas.push(prefix + codeBit); - return prefix + codeBit + '.'; - }, ''); - ancestorAreas.pop(); - // fetch areas where this user is leader - const assignedAreas = (await layer.getAreasForLeader(leaderId)).map(area => area.id); - if (!assignedAreas.length) { - return false; - } - // see if any of them is among the ancestors - for (let ancestorCode of ancestorAreas) { - if (assignedAreas.indexOf(ancestorCode) !== -1) { - return true; - } + } + } + return false; + }, + + //======================================================== + // TEAMS + //======================================================== + getTeam: id => adapter.getOneEntityById('Team', '_design/byTeamId/_view/view', id), + getAllTeams: () => adapter.getEntities('Team', '_design/all/_view/view', {sorted: true}), + getAllTeamsByCountry: async (country, search) => { + const teams = await adapter.getEntities( + 'Team', + '_design/all/_view/view', + { + sorted: true, + } + ); + const filteredTeams = search ? teams.filter(team => + team.name && team.name.toUpperCase().indexOf(search.toUpperCase()) > -1 || + team.teamDescription && team.teamDescription.toUpperCase().indexOf(search.toUpperCase()) > -1 || + COUNTRY_LIST[team.CC] && COUNTRY_LIST[team.CC].toUpperCase().indexOf(search.toUpperCase()) > -1 + ) : teams; + const sortedTeamsByCountry = _.sortBy(filteredTeams, team => team.CC !== country); + return sortedTeamsByCountry + }, + getCountTeamsTrashpoints: () => adapter.getEntities('Team', '_design/all/_view/view', {sorted: false}), + getRawTeamDoc: id => adapter.getOneRawDocById('Team', '_design/byTeamId/_view/view', id), + createTeam: async (id, who, create) => { + await adapter.createDocument('Team', id, create, { + createdAt: util.time.getNowUTC(), + createdBy: who || undefined, + }); + return await layer.getTeam(id); + }, + seedTeams: async (metadata) => { + const ret = await layer.getAllTeams(); + if (!Array.isArray(ret)) { + return false; + } + const existingTeams = ret.reduce((prev, team) => { + prev[team.id] = team; + return prev; + }, {}); + const neededParams = ['name', 'teamDescription', 'CC']; + _.each(metadata, async (team, key) => { + const existedTeam = existingTeams[team.id]; + if (!existedTeam && (!team.CC || team.CC && CCs.includes(team.CC))) { + // team.image = gravatar.url(team.name, {s: '100', r: 'x', d: 'identicon'}, true); + if (!team.image) { + team.image = teamImages[key % teamImages.length]; } - return false; - }, + team.nationalTeam = true; + await layer.createTeam(team.id, null, _.pick(team, [...neededParams, 'image', 'nationalTeam'])); + } + }); + return true; + }, + }; module.exports = layer; diff --git a/backend-db/modules/db/types.js b/backend-db/modules/db/types.js index 536c2e2847..f27a619eb2 100644 --- a/backend-db/modules/db/types.js +++ b/backend-db/modules/db/types.js @@ -51,6 +51,7 @@ class Account extends Type { role: true, pictureURL: true, country: true, + team: true, termsAcceptedAt: true, locked: true, createdAt: true, @@ -69,6 +70,7 @@ declareConstants(Account, { ROLE_LEADER: 'leader', ROLE_ADMIN: 'admin', ROLE_SUPERADMIN: 'superadmin', + DEFAULT_TEAM: null, }); class Session extends Type { @@ -108,6 +110,7 @@ class Trashpoint extends Type { address: true, hashtags: true, counter: true, + team: true, createdAt: true, createdBy: true, updatedAt: true, @@ -196,6 +199,26 @@ class Area extends Type { } } +class Team extends Type { + constructor(data) { + super(); + this.value = util.object.filter(data, { + id: true, + name: true, + teamDescription: true, + image: true, + trashpoints: true, + createdAt: true, + createdBy: true, + updatedAt: true, + updatedBy: true, + nationalTeam: true, + CC: true + }); + //FIXME: validate field values + } +} + const datatypeFactory = (datatype, data) => { switch (datatype) { case 'Dataset': @@ -212,15 +235,17 @@ const datatypeFactory = (datatype, data) => { return new Cluster(data); case 'Area': return new Area(data); + case 'Team': + return new Team(data); default: - throw new TypeError(`Unknown data type '${datatype}'.`) + throw new TypeError(`Unknown data type '${datatype}'.`); } -} +}; const normalizeData = (datatype, data) => (datatypeFactory(datatype, data)).export(); module.exports = { datatypeFactory, normalizeData, - Dataset, Account, Session, Trashpoint, Image, Cluster, Area, + Dataset, Account, Session, Trashpoint, Image, Cluster, Area, Team }; diff --git a/backend-db/package-lock.json b/backend-db/package-lock.json new file mode 100644 index 0000000000..cdb6fad034 --- /dev/null +++ b/backend-db/package-lock.json @@ -0,0 +1,13 @@ +{ + "name": "backend-db", + "version": "1.0.0", + "lockfileVersion": 1, + "requires": true, + "dependencies": { + "lodash": { + "version": "4.17.5", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.5.tgz", + "integrity": "sha512-svL3uiZf1RwhH+cWrfZn3A4+U58wbP0tGVTLQPbjplZxZ8ROD9VLuNgsRniTlLe7OlSqR79RUehXgpBW/s0IQw==" + } + } +} diff --git a/backend-db/package.json b/backend-db/package.json index 711f17387d..5ce20bdcc6 100644 --- a/backend-db/package.json +++ b/backend-db/package.json @@ -8,6 +8,8 @@ "dependencies": { "bluebird": "=3.5.0", "caught": "=0.1.1", + "gravatar": "^1.6.0", + "lodash": "^4.17.5", "node-couchdb": "=1.1.1" } } diff --git a/backend-db/plugins/accounts.js b/backend-db/plugins/accounts.js index 58aef7234c..6de5cbd2ac 100644 --- a/backend-db/plugins/accounts.js +++ b/backend-db/plugins/accounts.js @@ -15,18 +15,20 @@ const filterBriefAccountData = account => util.object.filter(account, { country: true, pictureURL: true, termsAcceptedAt: true, + team: true, + teamInfo: true }); const countriesForLeader = areasForLeader => { const leaderAreaHash = areasForLeader // only need the country code - .map(area => area.id) - // extract the top level country codes for all areas - // eg. [US.CA.SF, RO.AB, RO.BC] will become {US:true, RO:true} - .reduce((topAreaHash, areaCode) => { - topAreaHash[areaCode.split('.').shift()] = true; - return topAreaHash; - }, {}) + .map(area => area.id) + // extract the top level country codes for all areas + // eg. [US.CA.SF, RO.AB, RO.BC] will become {US:true, RO:true} + .reduce((topAreaHash, areaCode) => { + topAreaHash[areaCode.split('.').shift()] = true; + return topAreaHash; + }, {}) ; return Object.getOwnPropertyNames(leaderAreaHash); }; @@ -40,217 +42,249 @@ module.exports = function () { lucius.register('role:db,cmd:lockAccount', async function (connector, args, __) { return connector.input(args) - .use(async function ({accountId, locked}, responder) { - // basic sanity checks - if (accountId === __.user.id) { - return responder.failure(new LuciusError(E.ACCOUNT_CANNOT_SELF_LOCK)); - } - const rawAccount = await db.getRawAccountDoc(accountId); - if (!rawAccount) { - return responder.failure(new LuciusError(E.ACCOUNT_NOT_FOUND, {id: accountId})); - } - if (__.user.role === Account.ROLE_LEADER) { - // superadmins can only be [un]locked by other superadmins - if (rawAccount.role === Account.ROLE_SUPERADMIN) { - return responder.failure(new LuciusError(E.ACCESS_DENIED)); + .use(async function ({accountId, locked}, responder) { + // basic sanity checks + if (accountId === __.user.id) { + return responder.failure(new LuciusError(E.ACCOUNT_CANNOT_SELF_LOCK)); } - // leaders may only access users whose country falls in one of their areas - if (!rawAccount.country) { - return responder.failure(new LuciusError(E.ACCOUNT_NOT_SUBJECT_TO_LEADER, {accountId, leaderId: __.user.id})); + const rawAccount = await db.getRawAccountDoc(accountId); + if (!rawAccount) { + return responder.failure(new LuciusError(E.ACCOUNT_NOT_FOUND, {id: accountId})); } - const leaderCountries = countriesForLeader(await db.getAreasForLeader(__.user.id)); - if (leaderCountries.indexOf(rawAccount.country) === -1) { - return responder.failure(new LuciusError(E.ACCOUNT_NOT_SUBJECT_TO_LEADER, {accountId, leaderId: __.user.id})); + if (__.user.role === Account.ROLE_LEADER) { + // superadmins can only be [un]locked by other superadmins + if (rawAccount.role === Account.ROLE_SUPERADMIN) { + return responder.failure(new LuciusError(E.ACCESS_DENIED)); + } + // leaders may only access users whose country falls in one of their areas + if (!rawAccount.country) { + return responder.failure(new LuciusError(E.ACCOUNT_NOT_SUBJECT_TO_LEADER, { + accountId, + leaderId: __.user.id + })); + } + const leaderCountries = countriesForLeader(await db.getAreasForLeader(__.user.id)); + if (leaderCountries.indexOf(rawAccount.country) === -1) { + return responder.failure(new LuciusError(E.ACCOUNT_NOT_SUBJECT_TO_LEADER, { + accountId, + leaderId: __.user.id + })); + } + } + // perform [un]lock + const ret = await db.setAccountLock(accountId, locked, __.user.id, rawAccount); + if (!ret) { + return responder.failure(new LuciusError( + E.ACCOUNT_NOT_FOUND, {id: accountId})) } - } - // perform [un]lock - const ret = await db.setAccountLock(accountId, locked, __.user.id, rawAccount); - if (!ret) { - return responder.failure(new LuciusError( - E.ACCOUNT_NOT_FOUND, {id: accountId})) - } - return responder.success(); - }) + return responder.success(); + }) }); lucius.register('role:db,cmd:endSession', async function (connector, args, __) { return connector.input(args) - .use(async function ({sessionId}, responder) { - const ret = await db.removeSession(sessionId); - if (!ret) { - return responder.failure(new LuciusError( - E.SESSION_NOT_FOUND, {id: sessionId})) - } - return responder.success(); - }) + .use(async function ({sessionId}, responder) { + const ret = await db.removeSession(sessionId); + if (!ret) { + return responder.failure(new LuciusError( + E.SESSION_NOT_FOUND, {id: sessionId})) + } + return responder.success(); + }) }); lucius.register('role:db,cmd:acceptTerms', async function (connector, args, __) { return connector - .use(async function (foo, responder) { - const accountId = __.user.id; - const ret = await db.updateAccountTerms(accountId); - if (!ret) { - return responder.failure(new LuciusError( - E.ACCOUNT_NOT_FOUND, {id: accountId})) - } - return responder.success(); - }) + .use(async function (foo, responder) { + const accountId = __.user.id; + const ret = await db.updateAccountTerms(accountId); + if (!ret) { + return responder.failure(new LuciusError( + E.ACCOUNT_NOT_FOUND, {id: accountId})) + } + return responder.success(); + }) }); lucius.register('role:db,cmd:getAccounts', async function (connector, args, __) { return connector.input(args) - .use(async function ({pageSize, pageNumber, country, nameSearch}, responder) { - if (nameSearch) { - nameSearch = nameSearch.toLowerCase(); - } - let accounts; - let total; - if (__.user.role === Account.ROLE_SUPERADMIN) { + .use(async function ({pageSize, pageNumber, country, nameSearch}, responder) { if (nameSearch) { - accounts = await db.getAccountsByNameSearch(nameSearch, pageSize, pageNumber, country); - total = await db.countAccountsForNameSearch(nameSearch, country); - } - else if (country) { - accounts = await db.getAccountsByCountry(country, pageSize, pageNumber); - total = await db.countAccountsForCountry(country); - } - else { - accounts = await db.getAccounts(pageSize, pageNumber); - total = await db.countAccounts(); + nameSearch = nameSearch.toLowerCase(); } - } - else { - if (!country) { - return responder.failure(new LuciusError(E.COUNTRY_REQUIRED)); - } - const leaderCountries = countriesForLeader(await db.getAreasForLeader(__.user.id)); - if (leaderCountries.indexOf(country) === -1) { - return responder.failure(new LuciusError(E.ACCESS_DENIED)); - } - if (nameSearch) { - accounts = await db.getAccountsByNameSearch(nameSearch, pageSize, pageNumber, country); - total = await db.countAccountsForNameSearch(nameSearch, country); + let accounts; + let total; + if (__.user.role === Account.ROLE_SUPERADMIN) { + if (nameSearch) { + accounts = await db.getAccountsByNameSearch(nameSearch, pageSize, pageNumber, country); + total = await db.countAccountsForNameSearch(nameSearch, country); + } + else if (country) { + accounts = await db.getAccountsByCountry(country, pageSize, pageNumber); + total = await db.countAccountsForCountry(country); + } + else { + accounts = await db.getAccounts(pageSize, pageNumber); + total = await db.countAccounts(); + } } else { - accounts = await db.getAccountsByCountry(country, pageSize, pageNumber); - total = await db.countAccountsForCountry(country); + if (!country) { + return responder.failure(new LuciusError(E.COUNTRY_REQUIRED)); + } + const leaderCountries = countriesForLeader(await db.getAreasForLeader(__.user.id)); + if (leaderCountries.indexOf(country) === -1) { + return responder.failure(new LuciusError(E.ACCESS_DENIED)); + } + if (nameSearch) { + accounts = await db.getAccountsByNameSearch(nameSearch, pageSize, pageNumber, country); + total = await db.countAccountsForNameSearch(nameSearch, country); + } + else { + accounts = await db.getAccountsByCountry(country, pageSize, pageNumber); + total = await db.countAccountsForCountry(country); + } } - } - return responder.success({ - total, - pageSize, - pageNumber, - records: accounts.map(a => filterBriefAccountData(a)), - }); - }) + return responder.success({ + total, + pageSize, + pageNumber, + records: accounts.map(a => filterBriefAccountData(a)), + }); + }) }); lucius.register('role:db,cmd:modifyOwnUserProfile', async function (connector, args, __) { return connector.input(args) - .use(async function ({update}, responder) { - const id = __.user.id; - const account = await db.modifyAccount(id, id, update); - if (!account) { - return responder.failure(new LuciusError(E.ACCOUNT_NOT_FOUND, {id})) - } - return responder.success(filterBriefAccountData(account)); - }) + .use(async function ({update}, responder) { + const id = __.user.id; + const account = await db.modifyAccount(id, id, update); + if (!account) { + return responder.failure(new LuciusError(E.ACCOUNT_NOT_FOUND, {id})) + } + if (account.team) { + account.teamInfo = await db.getTeam(account.team) + account.teamInfo.members = await db.countAccountsForTeam(account.team) + account.teamInfo.trashpoints = await db.countTeamTrashpoints(account.team) + const trashpoints = await db.getTeamTrashpoints(account.team, 4) + account.teamInfo.lastTrashpoints = trashpoints[0]; + account.teamInfo.groupCount = trashpoints[1]; + } + return responder.success(filterBriefAccountData(account)); + }) }); lucius.register('role:db,cmd:getOrCreateAccountFromSocial', async function (connector, args, __) { return connector.input(args) - .use(async function (socialAccount, responder) { - const accountId = Account.makeAccountIdFromSocial( - socialAccount.source, - socialAccount.id - ); - let account = await db.getAccount(accountId); - if (!account) { - account = await db.createAccount( - accountId, - socialAccount.name, - socialAccount.email, - Account.ROLE_VOLUNTEER, - socialAccount.pictureURL + .use(async function (socialAccount, responder) { + const accountId = Account.makeAccountIdFromSocial( + socialAccount.source, + socialAccount.id ); - } - return responder.success(account); - }); + let account = await db.getAccount(accountId); + if (!account) { + account = await db.createAccount( + accountId, + socialAccount.name, + socialAccount.email, + Account.ROLE_VOLUNTEER, + socialAccount.pictureURL, + Account.DEFAULT_TEAM + ); + } + return responder.success(account); + }); }); lucius.register('role:db,cmd:getOrCreateSession', async function (connector, args, __) { return connector.input(args) - .use(async function ({accountId}, responder) { - const session = await db.createOrTouchSession( - accountId, - util.time.getExpirationIntervalInDays(), - ); - return responder.success({id: session.id}); - }); + .use(async function ({accountId}, responder) { + const session = await db.createOrTouchSession( + accountId, + util.time.getExpirationIntervalInDays(), + ); + return responder.success({id: session.id}); + }); }); lucius.register('role:db,cmd:getAccountById', async function (connector, args, __) { return connector.input(args) - .use(async function ({accountId, filterFields}, responder) { - // see if target account exists - let account = await db.getAccount(accountId); - if (!account) { - return responder.failure(new LuciusError(E.ACCOUNT_NOT_FOUND, {id: accountId})); - } - // users can always see their own account info - if (__.user.id !== account.id - // superadmins can see any user's account info - && __.user.role !== Account.ROLE_SUPERADMIN - ) { - // leaders may only access users whose country falls in one of their areas - if (__.user.role === Account.ROLE_LEADER) { - if (!account.country) { - return responder.failure(new LuciusError(E.ACCOUNT_NOT_SUBJECT_TO_LEADER, {accountId, leaderId: __.user.id})); + .use(async function ({accountId, filterFields}, responder) { + // see if target account exists + let account = await db.getAccount(accountId); + if (!account) { + return responder.failure(new LuciusError(E.ACCOUNT_NOT_FOUND, {id: accountId})); + } + // users can always see their own account info + if (__.user.id !== account.id + // superadmins can see any user's account info + && __.user.role !== Account.ROLE_SUPERADMIN + ) { + // leaders may only access users whose country falls in one of their areas + if (__.user.role === Account.ROLE_LEADER) { + if (!account.country) { + return responder.failure(new LuciusError(E.ACCOUNT_NOT_SUBJECT_TO_LEADER, { + accountId, + leaderId: __.user.id + })); + } + const leaderCountries = countriesForLeader(await db.getAreasForLeader(__.user.id)); + if (leaderCountries.indexOf(account.country) === -1) { + return responder.failure(new LuciusError(E.ACCOUNT_NOT_SUBJECT_TO_LEADER, { + accountId, + leaderId: __.user.id + })); + } } - const leaderCountries = countriesForLeader(await db.getAreasForLeader(__.user.id)); - if (leaderCountries.indexOf(account.country) === -1) { - return responder.failure(new LuciusError(E.ACCOUNT_NOT_SUBJECT_TO_LEADER, {accountId, leaderId: __.user.id})); + else { + // fallback to deny in all other cases + return responder.failure(new LuciusError(E.ACCESS_DENIED)); } } - else { - // fallback to deny in all other cases - return responder.failure(new LuciusError(E.ACCESS_DENIED)); + // prepare account data + if (filterFields) { + account = filterBriefAccountData(account); + } + if (account.role === Account.ROLE_LEADER) { + account.areas = (await db.getAreasForLeader(account.id)).map(area => area.id); + } else { + account.areas = []; + } + if (account.team) { + const teamInfo = await db.getTeam(account.team); + if (teamInfo) { + account.teamInfo = teamInfo; + account.teamInfo.members = await db.countAccountsForTeam(account.team); + account.teamInfo.trashpoints = await db.countTeamTrashpoints(account.team); + const trashpoints = await db.getTeamTrashpoints(account.team, 4); + account.teamInfo.lastTrashpoints = trashpoints[0]; + account.teamInfo.groupCount = trashpoints[1]; + } } - } - // prepare account data - if (filterFields) { - account = filterBriefAccountData(account); - } - if (account.role === Account.ROLE_LEADER) { - account.areas = (await db.getAreasForLeader(account.id)).map(area => area.id); - } else { - account.areas = []; - } - return responder.success(account); - }); + return responder.success(account); + }); }); lucius.register('role:db,cmd:getAccountBySessionId', async function (connector, args, __) { return connector.input(args) - .use(async function ({sessionId}, responder) { - // check that the session exists; - // we re-extend the expiration time in the process - const session = await db.verifyAndTouchSession( - sessionId, util.time.getExpirationIntervalInDays() - ); - if (!session) { - return responder.failure(new LuciusError( - E.SESSION_NOT_FOUND, {id: sessionId})) - } - // get the account info - const account = await db.getAccount(session.accountId); - if (!account) { - return responder.failure(new LuciusError( - E.ACCOUNT_NOT_FOUND, {id: session.accountId})) - } - return responder.success(filterBriefAccountData(account)); - }); + .use(async function ({sessionId}, responder) { + // check that the session exists; + // we re-extend the expiration time in the process + const session = await db.verifyAndTouchSession( + sessionId, util.time.getExpirationIntervalInDays() + ); + if (!session) { + return responder.failure(new LuciusError( + E.SESSION_NOT_FOUND, {id: sessionId})) + } + // get the account info + const account = await db.getAccount(session.accountId); + if (!account) { + return responder.failure(new LuciusError( + E.ACCOUNT_NOT_FOUND, {id: session.accountId})) + } + return responder.success(filterBriefAccountData(account)); + }); }); return PLUGIN_NAME; diff --git a/backend-db/plugins/teams.js b/backend-db/plugins/teams.js new file mode 100644 index 0000000000..f4e29c6178 --- /dev/null +++ b/backend-db/plugins/teams.js @@ -0,0 +1,76 @@ +'use strict'; +const {E, LuciusError, Lucius} = require('module-lucius'); +const db = require('../modules/db'); +const logger = require('module-logger'); +const {Team, Account} = require('../modules/db/types'); +const {list} = require('../teamList'); +const _ = require('lodash'); + +const PLUGIN_NAME = 'teams'; + +const additionalTeamInfo = async (team, amount) => { + team.members = await db.countAccountsForTeam(team.id); + team.trashpoints = await db.countTeamTrashpoints(team.id); + const trashpoints = await db.getTeamTrashpoints(team.id, amount) + team.lastTrashpoints = trashpoints[0]; + team.groupCount = trashpoints[1]; + return team +} + +module.exports = function () { + const lucius = new Lucius(this); + + lucius.pluginInit(PLUGIN_NAME, next => { + db.ready() + .then(() => db.seedTeams(list)) + .then(() => next()) + .catch(e => next(e)); + }); + + lucius.register('role:db,cmd:getAllTeams', async function (connector, args) { + return connector.input(args) + .use(async function ({CC, search}, responder) { + const teams = await db.getAllTeamsByCountry(CC, search); + const AMOOUNT_OF_TEAMS = 4; + const teamsWithMembers = await Promise.all(teams.map(async team => additionalTeamInfo(team, AMOOUNT_OF_TEAMS))); + return responder.success(teamsWithMembers); + }); + }); + + lucius.register('role:db,cmd:getAllTeamsWeb', async function (connector, args) { + return connector.input(args) + .use(async function ({CC, superadmin}, responder) { + const teams = await db.getAllTeams(); + const filteredTeams = superadmin ? teams : teams.filter(team => team.CC === CC); + return responder.success(filteredTeams); + }); + }); + + lucius.register('role:db,cmd:getCountTeamsTrashpoints', async function (connector, args) { + return connector.input(args) + .use(async function ({}, responder) { + let teams = await db.getAllTeams(); + let i, len; + for (i = 0, len = teams.length; i < len; i++) { + teams[i]['trashpoints'] = await db.countTeamTrashpoints(teams[i].id); + teams[i]['users'] = await db.countAccountsForTeam(teams[i].id); + } + + return responder.success(teams); + }); + }); + + lucius.register('role:db,cmd:getTeam', async function (connector, args, __) { + return connector.input(args) + .use(async function ({id}, responder) { + const team = await db.getTeam(id); + if (!team) { + return responder.failure(new LuciusError(E.TEAM_NOT_FOUND, {id: id})); + } + const fullInfoTeam = await additionalTeamInfo(team, -1); + return responder.success(fullInfoTeam); + }); + }); + + return PLUGIN_NAME; +}; diff --git a/backend-db/teamList.json b/backend-db/teamList.json new file mode 100644 index 0000000000..409ab8538d --- /dev/null +++ b/backend-db/teamList.json @@ -0,0 +1,348 @@ +{ + "list": [ + { + "id": "3b61b794-2b8e-11e8-b467-0ed5f89f718b", + "name": "Friends of World Cleanup Day", + "teamDescription": "If you believe that World Cleanup Day is a wonderful initiative which you want to support, then this team is for you! Map the waste so we can end trash blindness once and for all!" + + }, + { + "id": "3b61bb86-2b8e-11e8-b467-0ed5f89f718a", + "name": "Going Zero Waste", + "teamDescription": "A future without waste and toxic pollution is not just a dream; it’s a necessity. Help us to locate trash piles in your country!" + + }, + { + "id": "3b61c0e0-2b8e-11e8-b467-0ed5f89f718c", + "name": "JCI Trash Hunters", + "teamDescription": "Hi, JCI family! It is time to declare the trash hunting season open! Join the JCI mapping team to show how young action-minded people make a difference!" + + }, + { + "id": "3b61c36a-2b8e-11e8-b467-0ed5f89f718d", + "name": "Let’s Do It! World", + "teamDescription": "Join us and let's map the world! Let's Do It! World is an international movement that tackles environmental and social problems related to mismanaged waste, by mobilising millions of positive-minded, action-orientated people." + }, + { + "id": "3b61c5cc-2b8e-11e8-b467-0ed5f89f718e", + "name": "Just Map It", + "teamDescription": "Running, hiking or just walking around your neighbourhood?! Join the Just Map It team and put your active spirit to good use!" + + }, + { + "id": "3b61c81a-2b8e-11e8-b467-0ed5f89f718f", + "name": "Mapping for Peace", + "teamDescription": "Everyone who believes that sustainability and peace go hand in hand - join the Peace One day mapping team. Let's map the waste, and bring about peace of mind as well!" + }, + { + "id": "3b61c81a-2b8e-11e8-b467-0ed5f89f718g", + "name": "Ülemiste City", + "teamDescription": "Are you an employee or friend of Ülemiste City. Join this team and help to make the change towards a cleaner and healthier world.", + "image": "https://ucarecdn.com/97027779-24b8-4d5c-a2c3-c577c42a15e1/YC_logo_CMYK2.jpg", + "CC": "EE" + }, + { + "id": "3b61c81a-2b8e-11e8-b467-0ed5f89f718h", + "name": "Salesforce", + "teamDescription": "Are you an employee or friend of Salesforce. Join this team and help to make the change towards a cleaner and healthier world." + }, + { + "id": "3b61c81a-2b8e-11e8-b467-0ed5f89f718i", + "name": "YMCA", + "teamDescription": "Are you an employee or friend of YMCA. Join this team and help to make the change towards a cleaner and healthier world.", + "CC": "US" + }, + { + "id": "3b61c81a-2b8e-11e8-b467-0ed5f89f718j", + "name": "Outdoor Retailer", + "teamDescription": "Are you an employee or friend of Outdoor Retailer. Join this team and help to make the change towards a cleaner and healthier world.", + "CC": "US" + }, + { + "id": "3b61c81a-2b8e-11e8-b467-0ed5f89f718k", + "name": "Vail Resorts", + "teamDescription": "Are you an employee or friend of Vail Resorts. Join this team and help to make the change towards a cleaner and healthier world.", + "CC": "US" + }, + { + "id": "3b61c81a-2b8e-11e8-b467-0ed5f89f718l", + "name": "United States Navy", + "teamDescription": "Are you an employee or friend of United States Navy. Join this team and help to make the change towards a cleaner and healthier world.", + "CC": "US" + }, + { + "id": "3b61c81a-2b8e-11e8-b467-0ed5f89f718m", + "name": "United States Army", + "teamDescription": "Are you an employee or friend of United States Army. Join this team and help to make the change towards a cleaner and healthier world.", + "CC": "US" + }, + { + "id": "3b61c81a-2b8e-11e8-b467-0ed5f89f718n", + "name": "United States Air Force", + "teamDescription": "Are you an employee or friend of United States Air Force. Join this team and help to make the change towards a cleaner and healthier world.", + "CC": "US" + }, + { + "id": "3b61c81a-2b8e-11e8-b467-0ed5f89f718o", + "name": "United States Coast Guard", + "teamDescription": "Are you an employee or friend of United States Coast Guard. Join this team and help to make the change towards a cleaner and healthier world.", + "CC": "US" + }, + { + "id": "3b61c81a-2b8e-11e8-b467-0ed5f89f718p", + "name": "United States Marines", + "teamDescription": "Are you an employee or friend of United States Marines. Join this team and help to make the change towards a cleaner and healthier world.", + "CC": "US" + }, + { + "id": "3b61c81a-2b8e-11e8-b467-0ed5f89f718q", + "name": "IMG", + "teamDescription": "Are you an employee or friend of IMG. Join this team and help to make the change towards a cleaner and healthier world." + }, + { + "id": "3b61c81a-2b8e-11e8-b467-0ed5f89f718r", + "name": "GSMA", + "teamDescription": "Are you an employee or friend of GSMA. Join this team and help to make the change towards a cleaner and healthier world." + }, + { + "id": "3b61c81a-2b8e-11e8-b467-0ed5f89f718s", + "name": "Microsoft", + "teamDescription": "Do you believe that trash can be data? Hunt for data about trash!" + }, + { + "id": "3b61c81a-2b8e-11e8-b467-0ed5f89f718t", + "name": "Zero Waste - Cambodia", + "teamDescription": "Are you an employee or friend of Zero Waste - Cambodia. Join this team and help to make the change towards a cleaner and healthier world.", + "CC": "KH" + }, + { + "id": "3b61c81a-2b8e-11e8-b467-0ed5f89f718u", + "name": "Cúcuta", + "teamDescription": "Este equipo tiene como objetivo localizar, limpiar y transformar basureros ilegales en la ciudad de Cúcuta y sus alrededores, todos los habitantes locales están invitados a hacer parte de esta causa.", + "CC": "CO" + }, + { + "id": "3b61c81a-2b8e-11e8-b467-0ed5f89f718v", + "name": "Valledupar", + "teamDescription": "Este equipo tiene como objetivo localizar, limpiar y transformar basureros ilegales en la ciudad de Valledupar y sus alrededores, todos los habitantes locales están invitados a hacer parte de esta causa.", + "CC": "CO" + }, + { + "id": "3b61c81a-2b8e-11e8-b467-0ed5f89f718w", + "name": "Santa Marta", + "teamDescription": "Este equipo tiene como objetivo localizar, limpiar y transformar basureros ilegales en la ciudad de Santa Marta y sus alrededores, todos los habitantes locales están invitados a hacer parte de esta causa.", + "CC": "CO" + }, + { + "id": "3b61c81a-2b8e-11e8-b467-0ed5f89f718x", + "name": "Barranquilla", + "teamDescription": "Este equipo tiene como objetivo localizar, limpiar y transformar basureros ilegales en la ciudad de Barranquilla y sus alrededores, todos los habitantes locales están invitados a hacer parte de esta causa.", + "CC": "CO" + }, + { + "id": "3b61c81a-2b8e-11e8-b467-0ed5f89f718y", + "name": "San Andrés", + "teamDescription": "Este equipo tiene como objetivo localizar, limpiar y transformar basureros ilegales en la ciudad de San Andrés y sus alrededores, todos los habitantes locales están invitados a hacer parte de esta causa.", + "CC": "CO" + }, + { + "id": "3b61c81a-2b8e-11e8-b467-0ed5f89f718z", + "name": "Bogotá", + "teamDescription": "Este equipo tiene como objetivo localizar, limpiar y transformar basureros ilegales en la ciudad de Bogotá y sus alrededores, todos los habitantes locales están invitados a hacer parte de esta causa.", + "CC": "CO" + }, + { + "id": "3b61c81a-2b8e-11e8-b467-0ed5f89f719a", + "name": "Medellín", + "teamDescription": "Este equipo tiene como objetivo localizar, limpiar y transformar basureros ilegales en la ciudad de Medellín y sus alrededores, todos los habitantes locales están invitados a hacer parte de esta causa.", + "CC": "CO" + }, + { + "id": "3b61c81a-2b8e-11e8-b467-0ed5f89f719b", + "name": "Bucaramanga", + "teamDescription": "Este equipo tiene como objetivo localizar, limpiar y transformar basureros ilegales en la ciudad de Bucaramanga y sus alrededores, todos los habitantes locales están invitados a hacer parte de esta causa.", + "CC": "CO" + }, + { + "id": "3b61c81a-2b8e-11e8-b467-0ed5f89f719c", + "name": "La Jagua", + "teamDescription": "Este equipo tiene como objetivo localizar, limpiar y transformar basureros ilegales en la ciudad de La Jagua y sus alrededores, todos los habitantes locales están invitados a hacer parte de esta causa.", + "CC": "CO" + }, + { + "id": "3b61c81a-2b8e-11e8-b467-0ed5f89f719d", + "name": "Cartanegra", + "teamDescription": "Este equipo tiene como objetivo localizar, limpiar y transformar basureros ilegales en la ciudad de Cartanegra y sus alrededores, todos los habitantes locales están invitados a hacer parte de esta causa.", + "CC": "CO" + }, + { + "id": "3b61c81a-2b8e-11e8-b467-0ed5f89f719e", + "name": "Cali", + "teamDescription": "Este equipo tiene como objetivo localizar, limpiar y transformar basureros ilegales en la ciudad de Cali y sus alrededores, todos los habitantes locales están invitados a hacer parte de esta causa.", + "CC": "CO" + }, + { + "id": "3b61c81a-2b8e-11e8-b467-0ed5f89f719f", + "name": "Pereira", + "teamDescription": "Este equipo tiene como objetivo localizar, limpiar y transformar basureros ilegales en la ciudad de Pereira y sus alrededores, todos los habitantes locales están invitados a hacer parte de esta causa.", + "CC": "CO" + }, + { + "id": "3b61c81a-2b8e-11e8-b467-0ed5f89f719g", + "name": "Riohacha", + "teamDescription": "Este equipo tiene como objetivo localizar, limpiar y transformar basureros ilegales en la ciudad de Riohacha y sus alrededores, todos los habitantes locales están invitados a hacer parte de esta causa.", + "CC": "CO" + }, + { + "id": "3b61c81a-2b8e-11e8-b467-0ed5f89f719h", + "name": "Acandí", + "teamDescription": "Este equipo tiene como objetivo localizar, limpiar y transformar basureros ilegales en el municipio de Acandí y sus alrededores, todos los habitantes locales están invitados a hacer parte de esta causa.", + "CC": "CO" + }, + { + "id": "3b61c81a-2b8e-11e8-b467-0ed5f89f719i", + "name": "Scouting for Better World", + "teamDescription": "Global scouting movement creating a better waste free world" + }, + { + "id": "3b61c81a-2b8e-11e8-b467-0ed5f89f719k", + "name": "The Coca-Cola Journey", + "teamDescription": "Are you part of the worldwide Coke family or just loving Coke? This team is for you!" + }, + { + "id": "3b61c81a-2b8e-11e8-b467-0ed5f89f719j", + "name": "Creating a GLOBE", + "teamDescription": "GLOBE programme will map for citizen science. Be part of GLOBE" + }, + { + "id": "3b61c81a-2b8e-11e8-b467-0ed5f89f719l", + "name": "Youth 4 Global Goals", + "teamDescription": "AIESEC believes that young people are part of the solution to create positive change in the world. Do you?" + }, + { + "id": "3b61c81a-2b8e-11e8-b467-0ed5f89f719m", + "name": "Earth Day is Every Day", + "teamDescription": "Help End Plastic Pollution with Earth Day Network" + }, + { + "id": "3b61c81a-2b8e-11e8-b467-0ed5f89f719nf", + "name": "Beat Plastic Pollution", + "teamDescription": "If you can't reuse it, refuse it! Join United Nations initiative to beat plastic pollution." + }, + { + "id": "3b61c81a-2b8e-11e8-b467-0ed5f89f719o", + "name": "Rudda Føroyar", + "teamDescription": "Are you an employee or friend of Rudda Føroyar. Join this team and help to make the change towards a cleaner and healthier world.", + "CC": "FO" + }, + { + "id": "3b61c81a-2b8e-11e8-b467-0ed5f89f719p", + "name": "Heimasidur", + "teamDescription": "Are you an employee or friend of Heimasidur. Join this team and help to make the change towards a cleaner and healthier world.", + "CC": "FO" + }, + { + "id": "3b61c81a-2b8e-11e8-b467-0ed5f89f719q", + "name": "Elinsa", + "teamDescription": "Are you an employee or friend of Elinsa. Join this team and help to make the change towards a cleaner and healthier world.", + "CC": "FO" + }, + { + "id": "3b61c81a-2b8e-11e8-b467-0ed5f89f719r", + "name": "Vist", + "teamDescription": "Are you an employee or friend of Vist. Join this team and help to make the change towards a cleaner and healthier world.", + "CC": "FO" + }, + { + "id": "3b61c81a-2b8e-11e8-b467-0ed5f89f719s", + "name": "Borg", + "teamDescription": "Are you an employee or friend of Borg. Join this team and help to make the change towards a cleaner and healthier world.", + "CC": "FO" + }, + { + "id": "3b61c81a-2b8e-11e8-b467-0ed5f89f719t", + "name": "JCI BENIN", + "teamDescription": "Are you an employee or friend of JCI BENIN. Join this team and help to make the change towards a cleaner and healthier world.", + "CC": "BJ" + }, + { + "id": "3b61c81a-2b8e-11e8-b467-0ed5f89f719u", + "name": "AIESEC BENIN", + "teamDescription": "Are you an employee or friend of AIESEC BENIN. Join this team and help to make the change towards a cleaner and healthier world.", + "CC": "BJ" + }, + { + "id": "3b61c81a-2b8e-11e8-b467-0ed5f89f719v", + "name": "Club UEMOA/BENIN", + "teamDescription": "Are you an employee or friend of Club UEMOA/BENIN. Join this team and help to make the change towards a cleaner and healthier world.", + "CC": "BJ" + }, + { + "id": "3b61c81a-2b8e-11e8-b467-0ed5f89f719w", + "name": "La Brigade Verte", + "teamDescription": "Are you an employee or friend of La Brigade Verte. Join this team and help to make the change towards a cleaner and healthier world.", + "CC": "BJ" + }, + { + "id": "3b61c81a-2b8e-11e8-b467-0ed5f89f719x", + "name": "UJD2PB", + "teamDescription": "Are you an employee or friend of UJD2PB. Join this team and help to make the change towards a cleaner and healthier world.", + "CC": "BJ" + }, + { + "id": "3b61c81a-2b8e-11e8-b467-0ed5f89f719y", + "name": "ONG aide et progrès", + "teamDescription": "Are you an employee or friend of ONG aide et progrès. Join this team and help to make the change towards a cleaner and healthier world.", + "CC": "BJ" + }, + { + "id": "3b61c81a-2b8e-11e8-b467-0ed5f89f719z", + "name": "Rotaract BENIN", + "teamDescription": "Are you an employee or friend of Rotaract BENIN. Join this team and help to make the change towards a cleaner and healthier world.", + "CC": "BJ" + }, + { + "id": "3b61c81a-2b8e-11e8-b467-0ed5f89f717a", + "name": "CROIX ROUGE BENIN", + "teamDescription": "Are you an employee or friend of CROIX ROUGE BENIN. Join this team and help to make the change towards a cleaner and healthier world.", + "CC": "BJ" + }, + { + "id": "3b61c81a-2b8e-11e8-b467-0ed5f89f717b", + "name": "SCOUT BENINOIS", + "teamDescription": "Are you an employee or friend of SCOUT BENINOIS. Join this team and help to make the change towards a cleaner and healthier world.", + "CC": "BJ" + }, + { + "id": "3b61c81a-2b8e-11e8-b467-0ed5f89f717c", + "name": "OCJ", + "teamDescription": "Are you an employee or friend of OCJ. Join this team and help to make the change towards a cleaner and healthier world.", + "CC": "BJ" + }, + { + "id": "3b61c81a-2b8e-11e8-b467-0ed5f89f717d", + "name": "AMAF BENIN", + "teamDescription": "Are you an employee or friend of AMAF BENIN. Join this team and help to make the change towards a cleaner and healthier world.", + "CC": "BJ" + }, + { + "id": "3b61c81a-2b8e-11e8-b467-0ed5f89f717e", + "name": "2TG - ONG", + "teamDescription": "Are you an employee or friend of 2TG - ONG. Join this team and help to make the change towards a cleaner and healthier world.", + "CC": "BJ" + }, + { + "id": "3b61c81a-2b8e-11e8-b467-0ed5f89f717f", + "name": "ONG NEH", + "teamDescription": "Are you an employee or friend of ONG NEH. Join this team and help to make the change towards a cleaner and healthier world.", + "CC": "BJ" + }, + { + "id": "3b61c81a-2b8e-11e8-b467-0ed5f89f717g", + "name": "Plogging Thailand Team", + "teamDescription": "Plogging Thailand is a group of runners in Thailand who has passion in good health and clean city", + "image": "https://ucarecdn.com/db2bc61d-5504-4fba-ab27-718311c4f098/Plogging_Thailand.jpg", + "CC": "TH" + } + ] +} diff --git a/backend-db/yarn.lock b/backend-db/yarn.lock index e9d0b3ae5f..dbf341519d 100644 --- a/backend-db/yarn.lock +++ b/backend-db/yarn.lock @@ -9,9 +9,9 @@ ajv@^4.9.1: co "^4.6.0" json-stable-stringify "^1.0.1" -archy@1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/archy/-/archy-1.0.0.tgz#f9c8c13757cc1dd7bc379ac77b2c62a5c2868c40" +ansi-regex@^2.0.0: + version "2.1.1" + resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-2.1.1.tgz#c3b33ab5ee360d86e0e628f0468ae7ef27d654df" asn1@~0.2.3: version "0.2.3" @@ -25,10 +25,6 @@ assert-plus@^0.2.0: version "0.2.0" resolved "https://registry.yarnpkg.com/assert-plus/-/assert-plus-0.2.0.tgz#d74e1b87e7affc0db8aadb7021f3fe48101ab234" -async@~1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/async/-/async-1.0.0.tgz#f8fc04ca3a13784ade9e1641af98578cfbd647a9" - asynckit@^0.4.0: version "0.4.0" resolved "https://registry.yarnpkg.com/asynckit/-/asynckit-0.4.0.tgz#c79ed97f7f34cb8f2ba1bc9790bcc366474b4b79" @@ -41,39 +37,33 @@ aws4@^1.2.1: version "1.6.0" resolved "https://registry.yarnpkg.com/aws4/-/aws4-1.6.0.tgz#83ef5ca860b2b32e4a0deedee8c771b9db57471e" -backoff@~2.5.0: - version "2.5.0" - resolved "https://registry.yarnpkg.com/backoff/-/backoff-2.5.0.tgz#f616eda9d3e4b66b8ca7fca79f695722c5f8e26f" - dependencies: - precond "0.2" - bcrypt-pbkdf@^1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.1.tgz#63bc5dcb61331b92bc05fd528953c33462a06f8d" dependencies: tweetnacl "^0.14.3" -bluebird@=3.5.0, bluebird@^3.5.0: +bluebird@=3.5.0: version "3.5.0" resolved "https://registry.yarnpkg.com/bluebird/-/bluebird-3.5.0.tgz#791420d7f551eea2897453a8a77653f96606d67c" +blueimp-md5@^2.3.0: + version "2.10.0" + resolved "https://registry.yarnpkg.com/blueimp-md5/-/blueimp-md5-2.10.0.tgz#02f0843921f90dca14f5b8920a38593201d6964d" + boom@2.x.x: version "2.10.1" resolved "https://registry.yarnpkg.com/boom/-/boom-2.10.1.tgz#39c8918ceff5799f83f9492a848f625add0c766f" dependencies: hoek "2.x.x" -boom@3.x.x: - version "3.2.2" - resolved "https://registry.yarnpkg.com/boom/-/boom-3.2.2.tgz#0f0cc5d04adc5003b8c7d71f42cca7271fef0e78" - dependencies: - hoek "4.x.x" +builtin-modules@^1.0.0: + version "1.1.1" + resolved "https://registry.yarnpkg.com/builtin-modules/-/builtin-modules-1.1.1.tgz#270f076c5a72c02f5b65a47df94c5fe3a278892f" -boom@4.x.x: - version "4.3.1" - resolved "https://registry.yarnpkg.com/boom/-/boom-4.3.1.tgz#4f8a3005cb4a7e3889f749030fd25b96e01d2e31" - dependencies: - hoek "4.x.x" +camelcase@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-3.0.0.tgz#32fc4b9fcdaf845fcdf7e73bb97cac2261f0ab0a" caseless@~0.12.0: version "0.12.0" @@ -83,13 +73,21 @@ caught@=0.1.1: version "0.1.1" resolved "https://registry.yarnpkg.com/caught/-/caught-0.1.1.tgz#8abc85f205ba11fe70e4fc6faf3f46ddc18908ca" +cliui@^3.2.0: + version "3.2.0" + resolved "https://registry.yarnpkg.com/cliui/-/cliui-3.2.0.tgz#120601537a916d29940f934da3b48d585a39213d" + dependencies: + string-width "^1.0.1" + strip-ansi "^3.0.1" + wrap-ansi "^2.0.0" + co@^4.6.0: version "4.6.0" resolved "https://registry.yarnpkg.com/co/-/co-4.6.0.tgz#6ea6bdf3d853ae54ccb8e47bfa0bf3f9031fb184" -colors@1.0.x: - version "1.0.3" - resolved "https://registry.yarnpkg.com/colors/-/colors-1.0.3.tgz#0433f44d809680fdeb60ed260f1b0c262e82a40b" +code-point-at@^1.0.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/code-point-at/-/code-point-at-1.1.0.tgz#0d070b4d043a5bea33a2f1a40e2edb3d9a4ccf77" combined-stream@^1.0.5, combined-stream@~1.0.5: version "1.0.5" @@ -97,26 +95,22 @@ combined-stream@^1.0.5, combined-stream@~1.0.5: dependencies: delayed-stream "~1.0.0" -core-util-is@~1.0.0: - version "1.0.2" - resolved "https://registry.yarnpkg.com/core-util-is/-/core-util-is-1.0.2.tgz#b5fd54220aa2bc5ab57aab7140c940754503c1a7" - cryptiles@2.x.x: version "2.0.5" resolved "https://registry.yarnpkg.com/cryptiles/-/cryptiles-2.0.5.tgz#3bdfecdc608147c1c67202fa291e7dca59eaa3b8" dependencies: boom "2.x.x" -cycle@1.0.x: - version "1.0.3" - resolved "https://registry.yarnpkg.com/cycle/-/cycle-1.0.3.tgz#21e80b2be8580f98b468f379430662b046c34ad2" - dashdash@^1.12.0: version "1.14.1" resolved "https://registry.yarnpkg.com/dashdash/-/dashdash-1.14.1.tgz#853cfa0f7cbe2fed5de20326b8dd581035f6e2f0" dependencies: assert-plus "^1.0.0" +decamelize@^1.1.1: + version "1.2.0" + resolved "https://registry.yarnpkg.com/decamelize/-/decamelize-1.2.0.tgz#f6534d15148269b20352e7bee26f501f9a191290" + delayed-stream@~1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/delayed-stream/-/delayed-stream-1.0.0.tgz#df3ae199acadfb7d440aaae0b29e2272b24ec619" @@ -127,11 +121,15 @@ ecc-jsbn@~0.1.1: dependencies: jsbn "~0.1.0" -eraro@0.4, eraro@0.4.1, eraro@~0.4.1: - version "0.4.1" - resolved "https://registry.yarnpkg.com/eraro/-/eraro-0.4.1.tgz#6538730769a1e89ffc3f0c7e2c94d5a1f866629d" +email-validator@^1.0.7: + version "1.1.1" + resolved "https://registry.yarnpkg.com/email-validator/-/email-validator-1.1.1.tgz#b07f3be7bac1dc099bc43e75f6ae399f552d5a80" + +error-ex@^1.2.0: + version "1.3.1" + resolved "https://registry.yarnpkg.com/error-ex/-/error-ex-1.3.1.tgz#f855a86ce61adc4e8621c3cda21e7a7612c3a8dc" dependencies: - lodash "~2.4.1" + is-arrayish "^0.2.1" extend@~3.0.0: version "3.0.1" @@ -141,9 +139,12 @@ extsprintf@1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/extsprintf/-/extsprintf-1.0.2.tgz#e1080e0658e300b06294990cc70e1502235fd550" -eyes@0.1.x: - version "0.1.8" - resolved "https://registry.yarnpkg.com/eyes/-/eyes-0.1.8.tgz#62cf120234c683785d902348a800ef3e0cc20bc0" +find-up@^1.0.0: + version "1.1.2" + resolved "https://registry.yarnpkg.com/find-up/-/find-up-1.1.2.tgz#6b2e9822b1a2ce0a60ab64d610eccad53cb24d0f" + dependencies: + path-exists "^2.0.0" + pinkie-promise "^2.0.0" forever-agent@~0.6.1: version "0.6.1" @@ -157,9 +158,9 @@ form-data@~2.1.1: combined-stream "^1.0.5" mime-types "^2.1.12" -gate-executor@1.1.1: - version "1.1.1" - resolved "https://registry.yarnpkg.com/gate-executor/-/gate-executor-1.1.1.tgz#667f677284a0dbe86b6c48a0b4afe8c484812caf" +get-caller-file@^1.0.1: + version "1.0.2" + resolved "https://registry.yarnpkg.com/get-caller-file/-/get-caller-file-1.0.2.tgz#f702e63127e7e231c160a80c1554acb70d5047e5" getpass@^0.1.1: version "0.1.7" @@ -167,11 +168,18 @@ getpass@^0.1.1: dependencies: assert-plus "^1.0.0" -gex@0.2.2: - version "0.2.2" - resolved "https://registry.yarnpkg.com/gex/-/gex-0.2.2.tgz#2d409d2430959708da55cf56294c64f6d8973487" +graceful-fs@^4.1.2: + version "4.1.11" + resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.1.11.tgz#0e8bdfe4d1ddb8854d64e04ea7c00e2a026e5658" + +gravatar@^1.6.0: + version "1.6.0" + resolved "https://registry.yarnpkg.com/gravatar/-/gravatar-1.6.0.tgz#8bdc9b786ca725a8e7076416d1731f8d3331c976" dependencies: - lodash "3.10.0" + blueimp-md5 "^2.3.0" + email-validator "^1.0.7" + querystring "0.2.0" + yargs "^6.0.0" har-schema@^1.0.5: version "1.0.5" @@ -197,9 +205,9 @@ hoek@2.x.x: version "2.16.3" resolved "https://registry.yarnpkg.com/hoek/-/hoek-2.16.3.tgz#20bb7403d3cea398e91dc4710a8ff1b8274a25ed" -hoek@4.x.x: - version "4.1.1" - resolved "https://registry.yarnpkg.com/hoek/-/hoek-4.1.1.tgz#9cc573ffba2b7b408fb5e9c2a13796be94cddce9" +hosted-git-info@^2.1.4: + version "2.5.0" + resolved "https://registry.yarnpkg.com/hosted-git-info/-/hosted-git-info-2.5.0.tgz#6d60e34b3abbc8313062c3b798ef8d901a07af3c" http-signature@~1.1.0: version "1.1.1" @@ -209,19 +217,35 @@ http-signature@~1.1.0: jsprim "^1.2.2" sshpk "^1.7.0" -inherits@~2.0.1: - version "2.0.3" - resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.3.tgz#633c2c83e3da42a502f52466022480f4208261de" +invert-kv@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/invert-kv/-/invert-kv-1.0.0.tgz#104a8e4aaca6d3d8cd157a8ef8bfab2d7a3ffdb6" + +is-arrayish@^0.2.1: + version "0.2.1" + resolved "https://registry.yarnpkg.com/is-arrayish/-/is-arrayish-0.2.1.tgz#77c99840527aa8ecb1a8ba697b80645a7a926a9d" + +is-builtin-module@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/is-builtin-module/-/is-builtin-module-1.0.0.tgz#540572d34f7ac3119f8f76c30cbc1b1e037affbe" + dependencies: + builtin-modules "^1.0.0" + +is-fullwidth-code-point@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz#ef9e31386f031a7f0d643af82fde50c457ef00cb" + dependencies: + number-is-nan "^1.0.0" is-typedarray@~1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/is-typedarray/-/is-typedarray-1.0.0.tgz#e479c80858df0c1b11ddda6940f96011fcda4a9a" -isarray@0.0.1: - version "0.0.1" - resolved "https://registry.yarnpkg.com/isarray/-/isarray-0.0.1.tgz#8a18acfca9a8f4177e09abfc6038939b05d1eedf" +is-utf8@^0.2.0: + version "0.2.1" + resolved "https://registry.yarnpkg.com/is-utf8/-/is-utf8-0.2.1.tgz#4b0da1442104d1b336340e80797e865cf39f7d72" -isstream@0.1.x, isstream@~0.1.2: +isstream@~0.1.2: version "0.1.2" resolved "https://registry.yarnpkg.com/isstream/-/isstream-0.1.2.tgz#47e63f7af55afa6f92e1500e690eb8b8529c099a" @@ -239,18 +263,10 @@ json-stable-stringify@^1.0.1: dependencies: jsonify "~0.0.0" -json-stringify-safe@5.0.1, json-stringify-safe@~5.0.1: +json-stringify-safe@~5.0.1: version "5.0.1" resolved "https://registry.yarnpkg.com/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz#1296a2d58fd45f19a0f6ce01d65701e2c735b6eb" -jsonic@0.2.2: - version "0.2.2" - resolved "https://registry.yarnpkg.com/jsonic/-/jsonic-0.2.2.tgz#127bb99df4d821652c48a23d025cf2b16e618491" - -jsonic@0.3.0: - version "0.3.0" - resolved "https://registry.yarnpkg.com/jsonic/-/jsonic-0.3.0.tgz#b545da95f54392e58b3dda05f5f2e377a6c9d1bf" - jsonify@~0.0.0: version "0.0.0" resolved "https://registry.yarnpkg.com/jsonify/-/jsonify-0.0.0.tgz#2c74b6ee41d93ca51b7b5aaee8f503631d252a73" @@ -264,28 +280,25 @@ jsprim@^1.2.2: json-schema "0.2.3" verror "1.3.6" -lodash@3.10.0: - version "3.10.0" - resolved "https://registry.yarnpkg.com/lodash/-/lodash-3.10.0.tgz#93d51c672828a4416a12af57220ba8a8737e2fbb" - -lodash@4.15, lodash@4.15.0: - version "4.15.0" - resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.15.0.tgz#3162391d8f0140aa22cf8f6b3c34d6b7f63d3aa9" - -lodash@4.17.4: - version "4.17.4" - resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.4.tgz#78203a4d1c328ae1d86dca6460e369b57f4055ae" - -lodash@~2.4.1: - version "2.4.2" - resolved "https://registry.yarnpkg.com/lodash/-/lodash-2.4.2.tgz#fadd834b9683073da179b3eae6d9c0d15053f73e" +lcid@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/lcid/-/lcid-1.0.0.tgz#308accafa0bc483a3867b4b6f2b9506251d1b835" + dependencies: + invert-kv "^1.0.0" -lru-cache@4.0.1: - version "4.0.1" - resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-4.0.1.tgz#1343955edaf2e37d9b9e7ee7241e27c4b9fb72be" +load-json-file@^1.0.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/load-json-file/-/load-json-file-1.1.0.tgz#956905708d58b4bab4c2261b04f59f31c99374c0" dependencies: - pseudomap "^1.0.1" - yallist "^2.0.0" + graceful-fs "^4.1.2" + parse-json "^2.2.0" + pify "^2.0.0" + pinkie-promise "^2.0.0" + strip-bom "^2.0.0" + +lodash@^4.17.5: + version "4.17.5" + resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.5.tgz#99a92d65c0272debe8c96b6057bc8fbfa3bed511" mime-db@~1.27.0: version "1.27.0" @@ -297,99 +310,99 @@ mime-types@^2.1.12, mime-types@~2.1.7: dependencies: mime-db "~1.27.0" -minimist@1.2.0, minimist@^1.2.0: - version "1.2.0" - resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.0.tgz#a35008b20f41383eec1fb914f4cd5df79a264284" - -ndjson@1.4.3: - version "1.4.3" - resolved "https://registry.yarnpkg.com/ndjson/-/ndjson-1.4.3.tgz#7aa026fe3ab38a7da1a2b4ad07b1008e733eb239" - dependencies: - minimist "^1.2.0" - split2 "^0.2.1" - through2 "^0.6.1" - -nid@0.3, nid@0.3.2: - version "0.3.2" - resolved "https://registry.yarnpkg.com/nid/-/nid-0.3.2.tgz#977a9318ed5c2a38edd66263f3eafd8143f2251a" - node-couchdb@=1.1.1: version "1.1.1" resolved "https://registry.yarnpkg.com/node-couchdb/-/node-couchdb-1.1.1.tgz#90f50058b2d4e08cc46814b623754eb5eb1141b2" dependencies: request "^2.79.0" -norma@0.3, norma@0.3.0: - version "0.3.0" - resolved "https://registry.yarnpkg.com/norma/-/norma-0.3.0.tgz#27265c3411018c32c93ee719f692cf90dec5ab64" +normalize-package-data@^2.3.2: + version "2.4.0" + resolved "https://registry.yarnpkg.com/normalize-package-data/-/normalize-package-data-2.4.0.tgz#12f95a307d58352075a04907b84ac8be98ac012f" dependencies: - eraro "~0.4.1" - lodash "~2.4.1" + hosted-git-info "^2.1.4" + is-builtin-module "^1.0.0" + semver "2 || 3 || 4 || 5" + validate-npm-package-license "^3.0.1" + +number-is-nan@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/number-is-nan/-/number-is-nan-1.0.1.tgz#097b602b53422a522c1afb8790318336941a011d" oauth-sign@~0.8.1: version "0.8.2" resolved "https://registry.yarnpkg.com/oauth-sign/-/oauth-sign-0.8.2.tgz#46a6ab7f0aead8deae9ec0565780b7d4efeb9d43" -ordu@0.1.1: - version "0.1.1" - resolved "https://registry.yarnpkg.com/ordu/-/ordu-0.1.1.tgz#9c8109493693caf08299fca84c596aeb860baeaa" +os-locale@^1.4.0: + version "1.4.0" + resolved "https://registry.yarnpkg.com/os-locale/-/os-locale-1.4.0.tgz#20f9f17ae29ed345e8bde583b13d2009803c14d9" + dependencies: + lcid "^1.0.0" -patrun@0.5.0: - version "0.5.0" - resolved "https://registry.yarnpkg.com/patrun/-/patrun-0.5.0.tgz#77a51f773ac4931bb353fd41d59de6478fc6118d" +parse-json@^2.2.0: + version "2.2.0" + resolved "https://registry.yarnpkg.com/parse-json/-/parse-json-2.2.0.tgz#f480f40434ef80741f8469099f8dea18f55a4dc9" dependencies: - gex "0.2.2" - lodash "3.10.0" + error-ex "^1.2.0" -patrun@0.5.1: - version "0.5.1" - resolved "https://registry.yarnpkg.com/patrun/-/patrun-0.5.1.tgz#5bff3757f4f3fd2bdfb6a04d27942cbec3e12f1c" +path-exists@^2.0.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/path-exists/-/path-exists-2.1.0.tgz#0feb6c64f0fc518d9a754dd5efb62c7022761f4b" dependencies: - gex "0.2.2" - lodash "4.15.0" + pinkie-promise "^2.0.0" + +path-type@^1.0.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/path-type/-/path-type-1.1.0.tgz#59c44f7ee491da704da415da5a4070ba4f8fe441" + dependencies: + graceful-fs "^4.1.2" + pify "^2.0.0" + pinkie-promise "^2.0.0" performance-now@^0.2.0: version "0.2.0" resolved "https://registry.yarnpkg.com/performance-now/-/performance-now-0.2.0.tgz#33ef30c5c77d4ea21c5a53869d91b56d8f2555e5" -precond@0.2: - version "0.2.3" - resolved "https://registry.yarnpkg.com/precond/-/precond-0.2.3.tgz#aa9591bcaa24923f1e0f4849d240f47efc1075ac" +pify@^2.0.0: + version "2.3.0" + resolved "https://registry.yarnpkg.com/pify/-/pify-2.3.0.tgz#ed141a6ac043a849ea588498e7dca8b15330e90c" -pseudomap@^1.0.1: - version "1.0.2" - resolved "https://registry.yarnpkg.com/pseudomap/-/pseudomap-1.0.2.tgz#f052a28da70e618917ef0a8ac34c1ae5a68286b3" +pinkie-promise@^2.0.0: + version "2.0.1" + resolved "https://registry.yarnpkg.com/pinkie-promise/-/pinkie-promise-2.0.1.tgz#2135d6dfa7a358c069ac9b178776288228450ffa" + dependencies: + pinkie "^2.0.0" + +pinkie@^2.0.0: + version "2.0.4" + resolved "https://registry.yarnpkg.com/pinkie/-/pinkie-2.0.4.tgz#72556b80cfa0d48a974e80e77248e80ed4f7f870" punycode@^1.4.1: version "1.4.1" resolved "https://registry.yarnpkg.com/punycode/-/punycode-1.4.1.tgz#c0d5a63b2718800ad8e1eb0fa5269c84dd41845e" -qs@6.2.1: - version "6.2.1" - resolved "https://registry.yarnpkg.com/qs/-/qs-6.2.1.tgz#ce03c5ff0935bc1d9d69a9f14cbd18e568d67625" - -qs@6.4.0: - version "6.4.0" - resolved "https://registry.yarnpkg.com/qs/-/qs-6.4.0.tgz#13e26d28ad6b0ffaa91312cd3bf708ed351e7233" - qs@~6.3.0: version "6.3.2" resolved "https://registry.yarnpkg.com/qs/-/qs-6.3.2.tgz#e75bd5f6e268122a2a0e0bda630b2550c166502c" -"readable-stream@>=1.0.33-1 <1.1.0-0": - version "1.0.34" - resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-1.0.34.tgz#125820e34bc842d2f2aaafafe4c2916ee32c157c" +querystring@0.2.0: + version "0.2.0" + resolved "https://registry.yarnpkg.com/querystring/-/querystring-0.2.0.tgz#b209849203bb25df820da756e747005878521620" + +read-pkg-up@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/read-pkg-up/-/read-pkg-up-1.0.1.tgz#9d63c13276c065918d57f002a57f40a1b643fb02" dependencies: - core-util-is "~1.0.0" - inherits "~2.0.1" - isarray "0.0.1" - string_decoder "~0.10.x" + find-up "^1.0.0" + read-pkg "^1.0.0" -reconnect-core@1.3.0: - version "1.3.0" - resolved "https://registry.yarnpkg.com/reconnect-core/-/reconnect-core-1.3.0.tgz#fbae52919a7877d844e3246d01a2f26701c833c8" +read-pkg@^1.0.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/read-pkg/-/read-pkg-1.1.0.tgz#f5ffaa5ecd29cb31c0474bca7d756b6bb29e3f28" dependencies: - backoff "~2.5.0" + load-json-file "^1.0.0" + normalize-package-data "^2.3.2" + path-type "^1.0.0" request@^2.79.0: version "2.80.0" @@ -417,59 +430,21 @@ request@^2.79.0: tunnel-agent "~0.4.1" uuid "^3.0.0" -rolling-stats@0.1.1: - version "0.1.1" - resolved "https://registry.yarnpkg.com/rolling-stats/-/rolling-stats-0.1.1.tgz#cd5af774a8893b30a674832fa2f4abaa478cfc80" +require-directory@^2.1.1: + version "2.1.1" + resolved "https://registry.yarnpkg.com/require-directory/-/require-directory-2.1.1.tgz#8c64ad5fd30dab1c976e2344ffe7f792a6a6df42" -semver@5.3.0: - version "5.3.0" - resolved "https://registry.yarnpkg.com/semver/-/semver-5.3.0.tgz#9b2ce5d3de02d17c6012ad326aa6b4d0cf54f94f" +require-main-filename@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/require-main-filename/-/require-main-filename-1.0.1.tgz#97f717b69d48784f5f526a6c5aa8ffdda055a4d1" -seneca-log-filter@0.1.0: - version "0.1.0" - resolved "https://registry.yarnpkg.com/seneca-log-filter/-/seneca-log-filter-0.1.0.tgz#f513de77dfdcc120023f847a7c60ceed0afc66b3" - dependencies: - lodash "4.15.0" +"semver@2 || 3 || 4 || 5": + version "5.5.0" + resolved "https://registry.yarnpkg.com/semver/-/semver-5.5.0.tgz#dc4bbc7a6ca9d916dee5d43516f0092b58f7b8ab" -seneca-transport@2.1.1: - version "2.1.1" - resolved "https://registry.yarnpkg.com/seneca-transport/-/seneca-transport-2.1.1.tgz#ff8d1a0335bfe037ca7ceddf27828bdd55292a22" - dependencies: - eraro "0.4.1" - gex "0.2.2" - jsonic "0.2.2" - lodash "4.15.0" - lru-cache "4.0.1" - ndjson "1.4.3" - nid "0.3.2" - patrun "0.5.0" - qs "6.2.1" - reconnect-core "1.3.0" - wreck "9.0.0" - -seneca@^3.4.1: - version "3.4.1" - resolved "https://registry.yarnpkg.com/seneca/-/seneca-3.4.1.tgz#1cc252cbff0917adc8dabe9e993d45faadb5a8be" - dependencies: - archy "1.0.0" - eraro "0.4.1" - gate-executor "1.1.1" - gex "0.2.2" - json-stringify-safe "5.0.1" - jsonic "0.3.0" - lodash "4.17.4" - minimist "1.2.0" - nid "0.3.2" - norma "0.3.0" - ordu "0.1.1" - patrun "0.5.1" - qs "6.4.0" - rolling-stats "0.1.1" - semver "5.3.0" - seneca-log-filter "0.1.0" - seneca-transport "2.1.1" - use-plugin "0.3.2" - wreck "12.2.0" +set-blocking@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/set-blocking/-/set-blocking-2.0.0.tgz#045f9782d011ae9a6803ddd382b24392b3d890f7" sntp@1.x.x: version "1.0.9" @@ -477,11 +452,27 @@ sntp@1.x.x: dependencies: hoek "2.x.x" -split2@^0.2.1: - version "0.2.1" - resolved "https://registry.yarnpkg.com/split2/-/split2-0.2.1.tgz#02ddac9adc03ec0bb78c1282ec079ca6e85ae900" +spdx-correct@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/spdx-correct/-/spdx-correct-3.0.0.tgz#05a5b4d7153a195bc92c3c425b69f3b2a9524c82" + dependencies: + spdx-expression-parse "^3.0.0" + spdx-license-ids "^3.0.0" + +spdx-exceptions@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/spdx-exceptions/-/spdx-exceptions-2.1.0.tgz#2c7ae61056c714a5b9b9b2b2af7d311ef5c78fe9" + +spdx-expression-parse@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/spdx-expression-parse/-/spdx-expression-parse-3.0.0.tgz#99e119b7a5da00e05491c9fa338b7904823b41d0" dependencies: - through2 "~0.6.1" + spdx-exceptions "^2.1.0" + spdx-license-ids "^3.0.0" + +spdx-license-ids@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/spdx-license-ids/-/spdx-license-ids-3.0.0.tgz#7a7cd28470cc6d3a1cfe6d66886f6bc430d3ac87" sshpk@^1.7.0: version "1.13.1" @@ -497,24 +488,29 @@ sshpk@^1.7.0: jsbn "~0.1.0" tweetnacl "~0.14.0" -stack-trace@0.0.x: - version "0.0.10" - resolved "https://registry.yarnpkg.com/stack-trace/-/stack-trace-0.0.10.tgz#547c70b347e8d32b4e108ea1a2a159e5fdde19c0" - -string_decoder@~0.10.x: - version "0.10.31" - resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-0.10.31.tgz#62e203bc41766c6c28c9fc84301dab1c5310fa94" +string-width@^1.0.1, string-width@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/string-width/-/string-width-1.0.2.tgz#118bdf5b8cdc51a2a7e70d211e07e2b0b9b107d3" + dependencies: + code-point-at "^1.0.0" + is-fullwidth-code-point "^1.0.0" + strip-ansi "^3.0.0" stringstream@~0.0.4: version "0.0.5" resolved "https://registry.yarnpkg.com/stringstream/-/stringstream-0.0.5.tgz#4e484cd4de5a0bbbee18e46307710a8a81621878" -through2@^0.6.1, through2@~0.6.1: - version "0.6.5" - resolved "https://registry.yarnpkg.com/through2/-/through2-0.6.5.tgz#41ab9c67b29d57209071410e1d7a7a968cd3ad48" +strip-ansi@^3.0.0, strip-ansi@^3.0.1: + version "3.0.1" + resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-3.0.1.tgz#6a385fb8853d952d5ff05d0e8aaf94278dc63dcf" + dependencies: + ansi-regex "^2.0.0" + +strip-bom@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/strip-bom/-/strip-bom-2.0.0.tgz#6219a85616520491f35788bdbf1447a99c7e6b0e" dependencies: - readable-stream ">=1.0.33-1 <1.1.0-0" - xtend ">=4.0.0 <4.1.0-0" + is-utf8 "^0.2.0" tough-cookie@~2.3.0: version "2.3.2" @@ -530,54 +526,58 @@ tweetnacl@^0.14.3, tweetnacl@~0.14.0: version "0.14.5" resolved "https://registry.yarnpkg.com/tweetnacl/-/tweetnacl-0.14.5.tgz#5ae68177f192d4456269d108afa93ff8743f4f64" -use-plugin@0.3.2: - version "0.3.2" - resolved "https://registry.yarnpkg.com/use-plugin/-/use-plugin-0.3.2.tgz#01f8b872f24ccdea4fd7958f057f4d55bf1fdff4" - dependencies: - eraro "0.4" - lodash "4.15" - nid "0.3" - norma "0.3" - uuid@^3.0.0: version "3.1.0" resolved "https://registry.yarnpkg.com/uuid/-/uuid-3.1.0.tgz#3dd3d3e790abc24d7b0d3a034ffababe28ebbc04" +validate-npm-package-license@^3.0.1: + version "3.0.3" + resolved "https://registry.yarnpkg.com/validate-npm-package-license/-/validate-npm-package-license-3.0.3.tgz#81643bcbef1bdfecd4623793dc4648948ba98338" + dependencies: + spdx-correct "^3.0.0" + spdx-expression-parse "^3.0.0" + verror@1.3.6: version "1.3.6" resolved "https://registry.yarnpkg.com/verror/-/verror-1.3.6.tgz#cff5df12946d297d2baaefaa2689e25be01c005c" dependencies: extsprintf "1.0.2" -winston@^2.3.1: - version "2.3.1" - resolved "https://registry.yarnpkg.com/winston/-/winston-2.3.1.tgz#0b48420d978c01804cf0230b648861598225a119" - dependencies: - async "~1.0.0" - colors "1.0.x" - cycle "1.0.x" - eyes "0.1.x" - isstream "0.1.x" - stack-trace "0.0.x" - -wreck@12.2.0: - version "12.2.0" - resolved "https://registry.yarnpkg.com/wreck/-/wreck-12.2.0.tgz#a1c3371e2152bf6d3600ff581b669c68a4d3d8b8" - dependencies: - boom "4.x.x" - hoek "4.x.x" +which-module@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/which-module/-/which-module-1.0.0.tgz#bba63ca861948994ff307736089e3b96026c2a4f" -wreck@9.0.0: - version "9.0.0" - resolved "https://registry.yarnpkg.com/wreck/-/wreck-9.0.0.tgz#1de63d49bb07b94fe718864b8be63176e63331ec" +wrap-ansi@^2.0.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-2.1.0.tgz#d8fc3d284dd05794fe84973caecdd1cf824fdd85" dependencies: - boom "3.x.x" - hoek "4.x.x" + string-width "^1.0.1" + strip-ansi "^3.0.1" -"xtend@>=4.0.0 <4.1.0-0": - version "4.0.1" - resolved "https://registry.yarnpkg.com/xtend/-/xtend-4.0.1.tgz#a5c6d532be656e23db820efb943a1f04998d63af" +y18n@^3.2.1: + version "3.2.1" + resolved "https://registry.yarnpkg.com/y18n/-/y18n-3.2.1.tgz#6d15fba884c08679c0d77e88e7759e811e07fa41" -yallist@^2.0.0: - version "2.1.2" - resolved "https://registry.yarnpkg.com/yallist/-/yallist-2.1.2.tgz#1c11f9218f076089a47dd512f93c6699a6a81d52" +yargs-parser@^4.2.0: + version "4.2.1" + resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-4.2.1.tgz#29cceac0dc4f03c6c87b4a9f217dd18c9f74871c" + dependencies: + camelcase "^3.0.0" + +yargs@^6.0.0: + version "6.6.0" + resolved "https://registry.yarnpkg.com/yargs/-/yargs-6.6.0.tgz#782ec21ef403345f830a808ca3d513af56065208" + dependencies: + camelcase "^3.0.0" + cliui "^3.2.0" + decamelize "^1.1.1" + get-caller-file "^1.0.1" + os-locale "^1.4.0" + read-pkg-up "^1.0.1" + require-directory "^2.1.1" + require-main-filename "^1.0.1" + set-blocking "^2.0.0" + string-width "^1.0.2" + which-module "^1.0.0" + y18n "^3.2.1" + yargs-parser "^4.2.0" diff --git a/ldiw-swarm/.gitignore b/ldiw-swarm/.gitignore new file mode 100644 index 0000000000..723ef36f4e --- /dev/null +++ b/ldiw-swarm/.gitignore @@ -0,0 +1 @@ +.idea \ No newline at end of file diff --git a/ldiw-swarm/README.md b/ldiw-swarm/README.md new file mode 100644 index 0000000000..b0d9440a98 --- /dev/null +++ b/ldiw-swarm/README.md @@ -0,0 +1,213 @@ +# LDIW swarm project files +![LDIW swarm](http://nebulaworks.com/blog/wp-content/uploads/2016/07/docker-swarm-1-e1468994621291.png "LDIW swarm" ) + +## Contents + +- [About](#about) + - [Repo directory structure](#repo-directory-structure) +- [Requirements](#requirements) + - [Operating System](#operating-system-requirements) + - [Software](#software-requirements) +- [Configuration](#configuration) + - [Cloud services](#cloud-services) + - [Host configuration](#host-configuration) + - [Docker preconfiguration](#docker-preconfiguration) + - [Clusters](#clusters) +- [Deployment](#deployment) + - [Deployment Pipelines](#deployment-pipelines) + - [Development (workstation) deployment](#development-(workstation)-deployment) + - [QA/Staging deployment](#staging-deployment) + - [Staging URLs](#staging-urls) + - [Production deployment](#production-deployment) + - [Production URLs](#production-urls) +- [Backup and monitoring](#backup-and-monitoring) + - [Backup](#backup) + - [Monitoring](#monitoring) +- [Diagrams](#diagrams) + +## ABOUT +This is the project holding swarm configuration files for the [LDIW PROJECT](.) services. The project holds configuration files for both the development environments (qa, staging) and also for the production environment. +The development environment configuration files are located under the [staging](./staging) directory. +The production environment configuration files are located under the [prodution](./production) directory. + +### Repo directory structure +This repository has a directory structure organized on different directories at the root level. Each directory has an **app** subdirectory (if applicable) and in the root there are templates for +infrastructure apps. Each directory corresponds to a certain deployed cluster, based on role: + +- [infra](./infra) - This contains templates and scripts for the deployment of the software infrastructure needed to support the main application stack: reverse-proxy, certbot, ELK stack,registry, jenkins. This directory does not contain an **app** subdirectory, as this cluster is only for running supporting services; +- [production](./production) - In the root there are templates for minimal supporting services (certbot, proxy, log routing). Under the [production/app](./production/app) subdirectory there is the +application template to be deployed on the **production** cluster(s). +- [staging](./staging) - In the root there are templates for minimal supporting services (certbot, proxy, log routing). Under the [staging/app](./staging/app) subdirectory there is the +application template to be deployed on the **staging** cluster, that holds the **QA** and **STAGING** environments. +- [support](./support) - This directory holds documentation and supporting files and scripts. + + +## Requirements +### Operating system requirements +For the cluster deployments on staging and production clusters, **Ubuntu 16.04.2 LTS x64** was used. +On local environments, the service stack was built on various Linux distributions and OSX versions. + +### Software Requirements +For the **cluster deployments** the main requirement is [Docker Engine](https://docs.docker.com/engine/). You can find detailed installation instructions for Ubuntu [here](https://docs.docker.com/install/linux/docker-ce/ubuntu/). On the staging and production clusters, version `17.06.0-ce` of `docker-ce` vas deployed. More recent versions should be backward compatible and should support the existing deployment templates (compose files) and deployed applications. + +For **local deployments** please install the latest [docker-ce](https://docs.docker.com/install/linux/docker-ce/ubuntu/) and [docker-compose](https://docs.docker.com/compose/install/#install-compose) for starting the application stack. + + +## Configuration +### Cloud Services +Development and production clusters have been deployed on Microsoft Azure, using Standard A2v2 and Standard A4v2 instances. +The following AWS services are used: +- **VM** - cluster nodes are deployed on Linux based virtual machines; +- **Storage account** - asset storage, backup storage, blob storage; +- **Traffic Manager** - Geographic traffic management; +- **VPN** - VPNs must be configured between geographic nodes in order for database replication, log management, docker image management to work; +- **CDN** - distribution of assets stored on storage accounts; +- **Load Balancer** - redirection and load balancing of requests to the docker clusters; + + +### Host configuration +Host configuration is minimal. +- After starting the VM instance, installation of `docker-ce` is needed and the host must be joined in the existing docker cluster. +- `/etc/fstab` must be configured to mount CIFS volumes and swapfile on boot. +- `/opt/deploy/`, `/backup/` directories should be created. + + +### Docker preconfiguration +The one time creation of **docker networks** is needed. The deployment templates describe these resources as external. All services are deployed inside the same docker overlay network in order to be +able to communicate with each other. + +On clusters that host multiple logical environments (staging), separate docker networks are required for each environment, so that separation of services must exist. + + +### Clusters +The **QA** ,**STAGING** and **PRODUCTION** environments run on top of docker swarm clusters. These environments are split between two physical clusters (the **staging** and the **production** clusters) as can be seen from the [cluster diagram](./support/EU-clusters.png). + +To provide support for builds, logging and other needed infrastructure, the **INFRA** physical cluster is also deployed alongside the application clusters [cluster diagram](./support/EU-clusters.png). + +The following stacks have deployable templates in this repository: + +1. **Infrastructure** + - elasticsearch + - [kibana](https://logging.ops.worldcleanupday.com) + - logstash + - logspout + - certbot + - [registry](https://registry.ops.worldcleanupday.com/) +2. **Proxy** + - proxy ([docker flow proxy](https://github.com/vfarcic/docker-flow-proxy)) + - swarm-listener (part of dfp project) + - certbot ([letsencrypt-companion for docker flow proxy](https://hub.docker.com/r/hamburml/docker-flow-letsencrypt/)) +3. **Application** + - api + - auth + - db + - geo + - couchdb + - webapp + + +## Deployment +### Deployment pipelines +[Jenkins](https://jenkins.ops.worldcleanupday.com) has **job list** views that that correspond to the cluster virtual environments (qa, staging, production). + +![Jenkins views](support/jenkins_jobs.png "Jenkins views and jobs"). + +The pipeline for building and deployment on one of the **development** environments is started by running the **build** job, eg. _1-ldiw-qa-build_. After finishing, the **publish** job is +automatically started, which in turn starts the **deploy** job. +- the **build** job pulls all repos and uses the scripts in the devops repo to build container images +- the **publish** job pushes the previously built images to a local docker registry. The docker registry is available on `localhost:5000` on the staging cluster. +- the **deploy** job uses the LDIW-swarm repo to start the application containers. + +![Development pipeline steps](support/build-publish-deploy.png "Development pipeline steps") + +The name of the pipeline jobs starts with a number which represents the order in which the jobs will run. + + +### Development (workstation) deployment +Building and deploying services on the workstation should be done using the [devops](https://github.com/letsdoitworld/World-Cleanup-Day/tree/master/devops/dev) repository. + +1. Pull the code for the services in the locations documented in the [devops](https://github.com/letsdoitworld/World-Cleanup-Day/tree/master/devops/dev) repository. + +2. After pulling the code, the services are built according to the rules configured in the `docker-compose.yml` file and in the `Dockerfile` from each repo. The build command is `docker-compose +build` or you can go to step 3 to **build** and **deploy** services in one go; +3. The last step is the `docker-compose up -d` command, which starts all services previously built. Afterwards, built images are available locally and services can be manipulated using normal [docker-compose](https://docs.docker.com/compose/reference/) commands. + +### Staging/Production deployment + +**Deployment** - as in starting of the application stacks - on cluster systems is done with the help of the current repository [ldiw-swarm](.), which contains deployment templates for docker swarm. The **building** of container images is handled using the rules and scripts in the [devops](https://github.com/letsdoitworld/World-Cleanup-Day/tree/master/devops/dev) repository. The orchestration is done using the [jenkins](https://jenkins.ops.worldcleanupday.com) instance deployed on the staging cluster. + +Services should be deployed using the deployment scripts present in all stack directories. These scripts will generate a configuration file from the existing templates by replacing environment variables defined in .env files. Next it will create a service stack and deploy all services present in the configuration file. + + +#### Staging Deployment +Stack and configuration files for deployment on development environments (QA and STAGING) are in the [staging](./staging) directory. + +**The root** of this directory contains the configuration file for the infrastructure services: [certbot](./staging/certbot-template.yml), [proxy](./staging/proxy-template.yml), [logspout](./staging/infrastructure-template.yml) for the staging cluster. The stacks should be deployed using their respective scripts: [deploy_certbot.sh](./staging/deploy_certbot.sh), [deploy_infra](./staging/deploy_infra.sh), [deploy_proxy](./staging/deploy_proxy.sh). + +The deployment scripts read the `.env` file and populate variables in the stack templates. +The `.env` file present is there to take environment variables from the jenkins deploy jobs. + +**app** +Directory containing stack file and deploy script for the backend api services - see the list above - [app-template.yml](./staging/app/app-template.yml) +The stack is used to deploy pre-built images, along with some ***environment variable files*** which come from each services' respective repo. + +The automation pipeline for development environments has three main steps: +1. [build](https://jenkins.ops.worldcleanupday.com/view/QA/job/1-ldiw-qa-build/) - In this step, docker images are built and tagged with the environment name and numeric tags. This step is started manually from the Jenkins views. +2. [publish](https://jenkins.ops.worldcleanupday.com/view/QA/job/2-ldiw-qa-publish/) - In this step, docker images created in the build step are pushed to a the [docker registry](https://registry.ops.worldcleanupday.com/v2/_catalog), hosted on the **INFRA** cluster. This step is started automatically upon successful completion of the **build** step. +3. [deploy](https://jenkins.ops.worldcleanupday.com/view/QA/job/3-ldiw-qa-deploy/) - In this step, docker images published in the **publish** step are deployed as containers (or services) on the environment for which they were built. This step is started automatically upon successful completion of the **publish** step. + + +#### Staging URLs + +Following are project URLs for all development environments: +- [kibana](https://logging.ops.worldcleanupday.com) +- [jenkins](https://jenkins.ops.worldcleanupday.com) +- [API-qa](https://api-qa.app.worldcleanupday.com/) +- [API-staging](https://api-staging.app.worldcleanupday.com/) +- [couchdb-qa](https://couch-qa.app.worldcleanupday.com) +- [couchdb-staging](https://couch-staging.app.worldcleanupday.com/) +- [webapp-qa](https://qa.app.worldcleanupday.com/) +- [webapp-staging](https://staging.app.worldcleanupday.com/) + +### Production deployment +The production directory stores stack files and configurations for the production environment. The setup is identical to staging, except for minor adjustments that stem from the fact that the staging physical cluster hosts more than one docker swarm. Usually, all new updates and needed configuration changes should first be deployed on the staging cluster and, after thorough testing, be merged in the configuration of the production cluster. + +The automation pipeline for production excludes the build step, as container images are built on staging and pushed to the production registry once approved: + +The pipeline for deployment on one of the **production** environment has only two jobs: _publish_ and _deploy_. This is because the production pipeline is designed to deploy only images built and tested previously on the **staging** environment: + +1. the **publish** job from the [PRODUCTION view](https://jenkins.ops.worldcleanupday.com/view/PRODUCTION/) reformats the tags for the staging images and pushes those images to [docker registry](https://registry.ops.worldcleanupday.com/). This step is started manually when a new version of the application is to be deployed to production. +2. the **deploy** jobs from the [PRODUCTION view](https://jenkins.ops.worldcleanupday.com/view/PRODUCTION/) are the only jobs that run on the main management nodes of the productions clusters. It pulls the `ldiw-swarm` repo and deploys the application stack as defined [here](./production/app). There is a production deployment job for every management node of every deployed application cluster (currently EU and US). This step is started manually after the publish step has completed successfully. + + +#### Production URLs + +Following are project URLs for the production environment: +- [kibana](https://logging.ops.worldcleanupday.com) +- [jenkins prod view](https://jenkins.ops.worldcleanupday.com/view/PRODUCTION/) +- [API](https://api.app.worldcleanupday.com/) +- [webapp](https://app.worldcleanupday.com/) + + +## Backup and monitoring +### Backup +Backup is performed daily by a [cron script](./support/scripts/backup.sh) running on the manager node. Backup data is stored on an azure file storage mounted in the `/backup` directory. +- couchdb +- service volumes + + +### Monitoring +Monitoring is done with sensu by http requests on the public endpoints and services. The following services are monitored: +- [production API](https://api.app.worldcleanupday.com/api/v1/datasets) +- production SSL certificate +- [production webapp]( https://app.worldcleanupday.com/) + + +## Diagrams +EU regional deployment consisting of three clusters: infrastructure, development and production. + +![EU clusters](./support/EU-clusters.png "EU region clusters") + +Diagram for routing of http requests to the production cluster(s). Only the EU and US clusters are implemented, with the US in standby. + +![API requests](./support/api.png "API requests") diff --git a/ldiw-swarm/infra/.env b/ldiw-swarm/infra/.env new file mode 100644 index 0000000000..d09b81ae31 --- /dev/null +++ b/ldiw-swarm/infra/.env @@ -0,0 +1,7 @@ +export ENV_LABEL="" +export DEPLOYMENT_LABEL="Deployed on $(date)" +export NETWORK="infrastructure" + +export KIBANA_URL=logging.ops.worldcleanupday.com +export GRAFANA_URL=monit.ops.worldcleanupday.com +export REGISTRY_URL=registry.ops.worldcleanupday.com diff --git a/ldiw-swarm/infra/certbot-template.yml b/ldiw-swarm/infra/certbot-template.yml new file mode 100644 index 0000000000..b9e174b9f2 --- /dev/null +++ b/ldiw-swarm/infra/certbot-template.yml @@ -0,0 +1,37 @@ +version: '3.1' + +services: + letsencrypt-companion: + image: hamburml/docker-flow-letsencrypt:latest + networks: + - ${NETWORK} + environment: +# - DOMAIN_1=('jenkins.ops.worldcleanupday.com') +# - DOMAIN_2=('registry.ops.worldcleanupday.com') +# - DOMAIN_3=('logging.ops.worldcleanupday.com') + - CERTBOT_EMAIL=daniel.jirca@qualitance.com + - PROXY_ADDRESS=proxy + - CERTBOT_CRON_RENEW=('0 3 * * *' '0 15 * * *') + volumes: + - /volatile/certbot:/etc/letsencrypt + deploy: + labels: + - com.df.servicePath=/.well-known/acme-challenge + - com.df.notify=true +# - com.df.distribute=true + - com.df.port=80 + - "com.ldiw.description=${DEPLOYMENT_LABEL}" + placement: + constraints: [node.role == manager] + replicas: 1 + +networks: + ${NETWORK}: + driver: overlay + external: true + +volumes: + certbot: + driver: "azurefile" + driver_opts: + share: "certificates" diff --git a/ldiw-swarm/infra/deploy_certbot.sh b/ldiw-swarm/infra/deploy_certbot.sh new file mode 100755 index 0000000000..6e3b747599 --- /dev/null +++ b/ldiw-swarm/infra/deploy_certbot.sh @@ -0,0 +1,4 @@ +#!/bin/bash +source .env +envsubst < certbot-template.yml > certbot.yml +docker stack deploy -c certbot.yml --with-registry-auth certbot diff --git a/ldiw-swarm/infra/deploy_infra.sh b/ldiw-swarm/infra/deploy_infra.sh new file mode 100755 index 0000000000..c45c89e0bf --- /dev/null +++ b/ldiw-swarm/infra/deploy_infra.sh @@ -0,0 +1,4 @@ +#!/bin/bash +source .env +envsubst < infrastructure-template.yml > infrastructure.yml +docker stack deploy -c infrastructure.yml --with-registry-auth infra diff --git a/ldiw-swarm/infra/deploy_proxy.sh b/ldiw-swarm/infra/deploy_proxy.sh new file mode 100755 index 0000000000..5662fa3812 --- /dev/null +++ b/ldiw-swarm/infra/deploy_proxy.sh @@ -0,0 +1,4 @@ +#!/bin/bash +source .env +envsubst < proxy-template.yml > proxy.yml +docker stack deploy -c proxy.yml --with-registry-auth proxy diff --git a/ldiw-swarm/infra/elk_elastalert/elasticsearch.yml b/ldiw-swarm/infra/elk_elastalert/elasticsearch.yml new file mode 100644 index 0000000000..c11dcfa670 --- /dev/null +++ b/ldiw-swarm/infra/elk_elastalert/elasticsearch.yml @@ -0,0 +1,26 @@ +--- +## Default Elasticsearch configuration from elasticsearch-docker. +## from https://github.com/elastic/elasticsearch-docker/blob/master/build/elasticsearch/elasticsearch.yml +# +cluster.name: "docker-cluster" +network.host: 0.0.0.0 + +# minimum_master_nodes need to be explicitly set when bound on a public IP +# set to 1 to allow single node clusters +# Details: https://github.com/elastic/elasticsearch/pull/17288 +discovery.zen.minimum_master_nodes: 1 + +## Use single node discovery in order to disable production mode and avoid bootstrap checks +## see https://www.elastic.co/guide/en/elasticsearch/reference/current/bootstrap-checks.html +# +discovery.type: single-node + +## Disable X-Pack +## see https://www.elastic.co/guide/en/x-pack/current/xpack-settings.html +## https://www.elastic.co/guide/en/x-pack/current/installing-xpack.html#xpack-enabling +# +xpack.security.enabled: false +xpack.monitoring.enabled: false +xpack.ml.enabled: false +xpack.graph.enabled: false +xpack.watcher.enabled: false \ No newline at end of file diff --git a/ldiw-swarm/infra/elk_elastalert/kibana/kibana.yml b/ldiw-swarm/infra/elk_elastalert/kibana/kibana.yml new file mode 100644 index 0000000000..50bba63d90 --- /dev/null +++ b/ldiw-swarm/infra/elk_elastalert/kibana/kibana.yml @@ -0,0 +1,17 @@ +--- +## Default Kibana configuration from kibana-docker. +## from https://github.com/elastic/kibana-docker/blob/master/build/kibana/config/kibana.yml +# +server.name: kibana +server.host: "0" +elasticsearch.url: http://elasticsearch:9200 + +## Disable X-Pack +## see https://www.elastic.co/guide/en/x-pack/current/xpack-settings.html +## https://www.elastic.co/guide/en/x-pack/current/installing-xpack.html#xpack-enabling +# +xpack.security.enabled: false +xpack.monitoring.enabled: false +xpack.ml.enabled: false +xpack.graph.enabled: false +xpack.reporting.enabled: false \ No newline at end of file diff --git a/ldiw-swarm/infra/elk_elastalert/logstash/logstash.conf b/ldiw-swarm/infra/elk_elastalert/logstash/logstash.conf new file mode 100644 index 0000000000..6cf0352cfa --- /dev/null +++ b/ldiw-swarm/infra/elk_elastalert/logstash/logstash.conf @@ -0,0 +1,26 @@ +input { + syslog { + port => 51415 + } + udp { + port => 5000 + codec => json + } + tcp { + port => 5000 + codec => json + } +} + +## Add your filters / logstash plugins configuration here + +output { + elasticsearch { + hosts => "elasticsearch:9200" + } + # Remove in production + #stdout { + # codec => rubydebug + #} + +} \ No newline at end of file diff --git a/ldiw-swarm/infra/elk_elastalert/logstash/logstash.yml b/ldiw-swarm/infra/elk_elastalert/logstash/logstash.yml new file mode 100644 index 0000000000..09a7fe156b --- /dev/null +++ b/ldiw-swarm/infra/elk_elastalert/logstash/logstash.yml @@ -0,0 +1,12 @@ +--- +## Default Logstash configuration from logstash-docker. +## from https://github.com/elastic/logstash-docker/blob/master/build/logstash/config/logstash.yml +# +http.host: "0.0.0.0" +path.config: /usr/share/logstash/pipeline + +## Disable X-Pack +## see https://www.elastic.co/guide/en/x-pack/current/xpack-settings.html +## https://www.elastic.co/guide/en/x-pack/current/installing-xpack.html#xpack-enabling +# +xpack.monitoring.enabled: false \ No newline at end of file diff --git a/ldiw-swarm/infra/infrastructure-template.yml b/ldiw-swarm/infra/infrastructure-template.yml new file mode 100644 index 0000000000..548a168c1b --- /dev/null +++ b/ldiw-swarm/infra/infrastructure-template.yml @@ -0,0 +1,183 @@ +version: '3.1' + +services: + jenkins: + image: jenkins:2.60.2-alpine + extra_hosts: + - "dock1-eu-infra:10.150.1.100" + - "dock2-eu-infra:10.150.1.101" + - "dock1-eu-staging:10.150.1.200" + - "dock2-eu-staging:10.150.1.201" + - "dock1-eu-prod:10.150.2.100" + - "dock2-eu-prod:10.150.2.101" + - "dock1-us-prod:10.150.3.100" + - "dock2-us-prod:10.150.3.101" + volumes: +# - jenkins:/var/jenkins_home + - /volatile/jenkins:/var/jenkins_home + environment: + - JENKINS_JAVA_OPTIONS="-Djava.awt.headless=true -Dhudson.security.csrf.requestfield=crumb -Duser.timezone=Europe/Bucharest" + - TZ=Europe/Bucharest + # ports: + # - 8080:8080 + # - 50001:50001 + networks: + - ${NETWORK} + deploy: + replicas: 1 + labels: + - com.df.notify=true + - com.df.serviceDomain=jenkins.ops.worldcleanupday.com + - com.df.servicePath=/ + - com.df.srcPort=443 + - com.df.port=8080 + # do ssl and http -> https redirect + - com.df.httpsOnly=true + - com.df.xForwardedProto=true + - com.df.redirectWhenHttpProto=true + - com.diw.description="${DEPLOYMENT_LABEL}" + + + registry: + image: registry:2 + environment: + REGISTRY_HTTP_SECRET: supersecret + REGISTRY_AUTH: htpasswd # configured in nginx + REGISTRY_AUTH_HTPASSWD_PATH: /etc/docker/registry/registry-htpasswd # configured in nginx + REGISTRY_AUTH_HTPASSWD_REALM: "Ldiw Registry" # configured in nginx + REGISTRY_STORAGE_DELETE_ENABLED: 'true' + volumes: + - registry:/var/lib/registry + - $PWD/registry/:/etc/docker/registry + networks: + - ${NETWORK} +# ports: +# - 5000:5000 + deploy: + replicas: 1 # more than 1 registry creates timeout loops during docker push + labels: + - com.df.reqMode=http + - com.df.notify=true + - com.df.serviceDomain=registry.ops.worldcleanupday.com + - com.df.servicePath=/ + - com.df.port=5000 + - com.df.httpsOnly=true + - com.df.xForwardedProto=true + - com.df.redirectWhenHttpProto=true + - com.df.sessionType=sticky-server +# - com.df.connectionMode=http-server-close + - com.ldiw.description="${DEPLOYMENT_LABEL}" + + + elasticsearch: + image: docker.elastic.co/elasticsearch/elasticsearch:5.4.1 + volumes: + - ./elk_elastalert/elasticsearch.yml:/usr/share/elasticsearch/config/elasticsearch.yml + - elk:/usr/share/elasticsearch/data + # ports: + # - "9200:9200" + # - "9300:9300" + environment: + - "LOGSPOUT=ignore" + - "ES_JAVA_OPTS=-Xmx2g -Xms2g" + networks: + - ${NETWORK} + deploy: + resources: + limits: + memory: 4G + replicas: 1 + restart_policy: + condition: on-failure + # placement: + # constraints: + # - node.hostname == dock1-eu-infra + labels: + com.ldiw.description: "${DEPLOYMENT_LABEL}" + + kibana: + image: docker.elastic.co/kibana/kibana:5.4.1 + secrets: + - dfp_users_kibana + volumes: + - $PWD/elk_elastalert/kibana/kibana.yml:/usr/share/kibana/config/kibana.yml + networks: + - ${NETWORK} + deploy: + labels: + - com.df.notify=true + - com.df.serviceDomain=${KIBANA_URL} + - com.df.servicePath=/ + - com.df.srcPort=443 + - com.df.port=5601 + # do ssl and http -> https redirect + - com.df.httpsOnly=true + - com.df.xForwardedProto=true + - com.df.redirectWhenHttpProto=true + - com.df.users=manager:m4n4g3r +# - com.df.usersSecret=kibana + # - com.df.usersPassEncrypted=true + - com.runspace.description="${DEPLOYMENT_LABEL}" + + + logstash: + image: docker.elastic.co/logstash/logstash:5.4.1 + volumes: + - ./elk_elastalert/logstash/logstash.yml:/usr/share/logstash/config/logstash.yml + - ./elk_elastalert/logstash/logstash.conf:/usr/share/logstash/pipeline/logstash.conf + ports: + - "5100:5000" + # - "12201:12201" + environment: + - "LOGSPOUT=ignore" + - "LS_JAVA_OPTS=-Xmx256m -Xms256m" + networks: + - ${NETWORK} + deploy: + labels: + - com.ldiw.description="${DEPLOYMENT_LABEL}" + + + logspout: + image: gliderlabs/logspout + volumes: + - /var/run/docker.sock:/var/run/docker.sock + command: "syslog://logstash:51415" + environment: + - "LOGSPOUT=ignore" + - "SYSLOG_FORMAT=rfc3164" + networks: + - ${NETWORK} + deploy: + mode: global + labels: + - com.ldiw.description="${DEPLOYMENT_LABEL}" + +networks: + ${NETWORK}: + driver: overlay + external: true + +volumes: + jenkins: + driver: "azurefile" + driver_opts: + share: "jenkins" + uid: 1000 + gid: 1000 + filemode: 0777 + dirmode: 0777 + registry: + driver: "azurefile" + driver_opts: + share: "registry" + elk: + driver: "azurefile" + driver_opts: + share: "elk" + +secrets: + registry.pem: + external: true + dfp_users_kibana: + external: true \ No newline at end of file diff --git a/ldiw-swarm/infra/jenkins/build_and_tag.sh b/ldiw-swarm/infra/jenkins/build_and_tag.sh new file mode 100644 index 0000000000..36d9ce6d65 --- /dev/null +++ b/ldiw-swarm/infra/jenkins/build_and_tag.sh @@ -0,0 +1,57 @@ +#!/bin/bash -e + +set -x +ls -la +hostname + +whoami + +eval `ssh-agent -s` +ssh-add ~/.ssh/id_rsa +cd backend-prod + +# change subrepos.ini according to env_label +sed -e s/'DEFAULT_BRANCH=.*'/"DEFAULT_BRANCH=$REPOS_BRANCH"/g -i subrepos.ini + + +./get_subrepos.sh + +# BUILD STATIC web-app +cd $WORKSPACE/backend-prod/services/web-app +mv services/web-app/* . + +echo "export const API_URL = \"$API_URL\";" > env.js + +./build_static.sh +cd ../../ + + +docker-compose -f docker-compose.yaml build + +TAGGED_IMAGES="" +IMAGES=$(docker images -q --filter reference=backendprod*) +TAG1="latest" +TAG2="$BUILD_NUMBER" +for i in $IMAGES;do + SERVICE_NAME=$(docker inspect $i --format '{{index .RepoTags 0 }}' | sed -e 's/\[//g' -e 's/\]//g' | sed -e "s/backendprod_//g" | sed -e 's/:latest//g') + + NEW_NAME="registry.ops.worldcleanupday.com/"$SERVICE_NAME"-${ENV_LABEL}:$TAG1" + NEW_NAME2="registry.ops.worldcleanupday.com/"$SERVICE_NAME"-${ENV_LABEL}:$TAG2" + + # create new tag for build image + echo "Tagging latest image (NEW_NAME) with name: $NEW_NAME" + docker tag $i $NEW_NAME + echo "Tagging built image with build_number: $NEW_NAME2" + docker tag $i $NEW_NAME2 + + # add images to image list + TAGGED_IMAGES="$TAGGED_IMAGES $NEW_NAME $NEW_NAME2" +done +echo "These images were tagged and should be published:" +for i in $TAGGED_IMAGES; do + echo $i +done + +echo "TAGGED_IMAGES=$TAGGED_IMAGES" > file.properties +echo "CLUSTER_NETWORK_NAME=$CLUSTER_NETWORK_NAME" >> file.properties +echo "DELETE_EXISTING_DATABASES=$DELETE_EXISTING_DATABASES" >> file.properties \ No newline at end of file diff --git a/ldiw-swarm/infra/jenkins/deploy_DEV.sh b/ldiw-swarm/infra/jenkins/deploy_DEV.sh new file mode 100644 index 0000000000..b2bd1ce096 --- /dev/null +++ b/ldiw-swarm/infra/jenkins/deploy_DEV.sh @@ -0,0 +1,43 @@ +#!/bin/bash +docker stack rm app${ENV_LABEL} || true +# wait for couchdb to clear filesystem locks +sleep 10 + +set +x + +eval `ssh-agent -s` +ssh-add /root/.ssh/id_rsa_jenkins +rm -rf app/services +cd devops + +# change subrepos.ini according to file.properties from build stage + +sed -e s/'DEFAULT_BRANCH=.*'/"DEFAULT_BRANCH=$REPOS_BRANCH"/g -i subrepos.ini + + +sed "2i BRANCH_api=$BRANCH_api" -i subrepos.ini +sed "3i BRANCH_identity=$BRANCH_identity" -i subrepos.ini +sed "4i BRANCH_dashboard=$BRANCH_dashboard" -i subrepos.ini +sed "5i BRANCH_logic=$BRANCH_logic" -i subrepos.ini +sed "6i BRANCH_data=$BRANCH_data" -i subrepos.ini +sed "7i BRANCH_nexudus=$BRANCH_nexudus" -i subrepos.ini +sed "8i BRANCH_messaging=$BRANCH_messaging" -i subrepos.ini +sed "9i BRANCH_doors=$BRANCH_doors" -i subrepos.ini +sed "10i BRANCH_rgnets=$BRANCH_rgnets" -i subrepos.ini +sed "11i BRANCH_doorflow=$BRANCH_doorflow" -i subrepos.ini +sed "12i BRANCH_couchdb=$BRANCH_couchdb" -i subrepos.ini +sed "13i BRANCH_booking=$BRANCH_booking" -i subrepos.ini +sed "14i BRANCH_community=$BRANCH_community" -i subrepos.ini + +./get_subrepos_jenkins.sh +mv services ../app/ +mv *env ../app/ +cd ../app +sed -e s/"ENV_LABEL=.*"/"ENV_LABEL=$ENV_LABEL"/g -i .env + +# Change swagger config to point to correct api url +sed -e "7s/host:.*/host: runspace-${ENV_LABEL}.qualitance.com/g" -e "s/schemes.*/schemes:/g" -e "10s/#//g" -i services/api/swagger/api/swagger/v1.0.yaml + +./deploy_app.sh +echo "Giving the cluster time to start all containers.." +sleep 120 \ No newline at end of file diff --git a/ldiw-swarm/infra/jenkins/deploy_QA_STAGING.sh b/ldiw-swarm/infra/jenkins/deploy_QA_STAGING.sh new file mode 100644 index 0000000000..943ddf7371 --- /dev/null +++ b/ldiw-swarm/infra/jenkins/deploy_QA_STAGING.sh @@ -0,0 +1,74 @@ +#!/bin/bash +set +x +# move everything to the shared file system +mkdir -p /opt/deploy/workspace +cp -a $WORKSPACE /opt/deploy/workspace +WORKSPACE=/opt/deploy/workspace/$JOB_NAME +cd $WORKSPACE + +if $DELETE_EXISTING_DATABASES; then + dbs=$(curl -ubackenddb:rockychrome -XGET https://couch-qa.app.worldcleanupday.com/_all_dbs | sed -e s/\"//g -e s/_replicator//g -e s/,//g -e s/_users//g -e 's/\[//g' -e 's/\]//g') + for i in $dbs; do + curl -ubackenddb:rockychrome -XDELETE https://couch-qa.app.worldcleanupday.com/$i; + done +fi + +docker stack rm app${ENV_LABEL} || true +# wait for couchdb to clear filesystem locks +sleep 10 + + +eval `ssh-agent -s` +ssh-add /root/.ssh/id_rsa + +cp -a devops/backend-prod/.env staging/app/.globalenv +cp -a devops/backend-prod/services/backend-api/.env staging/app/api.env +cp -a devops/backend-prod/services/backend-auth/.env staging/app/auth.env +cp -a devops/backend-prod/services/backend-db/.env staging/app/db.env +cp -a devops/backend-prod/services/backend-geo/.env staging/app/geo.env +#cp -a devops/backend-prod/services/couchbase/local.ini staging/app/local.ini +cp -a devops/backend-prod/services/couchdb/etc/local.ini staging/app/local.ini +cp -a devops/backend-prod/services/couchdb/.env staging/app/couchdb.env + +# change subrepos.ini according to env_label +#if [ $ENV_LABEL == "qa" ]; then +# sed -e s/'DEFAULT_BRANCH=.*'/'DEFAULT_BRANCH=develop'/g -i subrepos.ini +#fi +# +#if [ $ENV_LABEL == "staging" ] || [ $ENV_LABEL == "production" ]; then +# sed -e s/'DEFAULT_BRANCH=.*'/'DEFAULT_BRANCH=master'/g -i subrepos.ini +#fi +cd staging/app +sed -e s/"ENV_LABEL=.*"/"ENV_LABEL=$ENV_LABEL"/g -i .env + +# change auth.env +sed -e "s#JWT_SECRET=.*#JWT_SECRET=$JWT_SECRET#g" -i auth.env +sed -e "s#AZURE_STORAGE_ACCESS_KEY=.*#AZURE_STORAGE_ACCESS_KEY=$AZURE_STORAGE_ACCESS_KEY#g" -i auth.env +sed -e "s#AZURESTORAGE_ACCOUNT=.*#AZURESTORAGE_ACCOUNT=$AZURESTORAGE_ACCOUNT#g" -i auth.env +sed -e "s#COUCHDB_USER=.*#COUCHDB_USER=$COUCHDB_USER#g" -i .globalenv +sed -e "s#COUCHDB_PASSWORD=.*#COUCHDB_PASSWORD=$COUCHDB_PASSWORD#g" -i .globalenv + +# add couch url add end of db.env +#echo "COUCHBASE_ENDPOINT=$COUCHBASE_ENDPOINT" >> db.env + +# Perform some env variable changes for STAGING +#if [ $ENV_LABEL == "staging" ]; then +# sed -e s/"RGNETS_DEBUG_MODE=.*"/"RGNETS_DEBUG_MODE=$RGNETS_DEBUG_MODE"/g -i logic.env +#fi + +./deploy_app.sh +echo "Giving the cluster time to start all containers.." +sleep 120 + +# restart the proxy for STAGING and QA + +# TODO +#if [ $ENV_LABEL == "staging" ] || [ $ENV_LABEL == "qa" ]; then +# echo "Restart the proxy stack" +# docker service rm proxy_proxy +# cd ${WORKSPACE}/staging +# ./deploy_proxy.sh +# sleep 10 +# cd $WORKSPACE/infra && ./deploy_proxy.sh +#fi +# end TODO \ No newline at end of file diff --git a/ldiw-swarm/infra/jenkins/deploy_infra.sh b/ldiw-swarm/infra/jenkins/deploy_infra.sh new file mode 100644 index 0000000000..ffac62eaa2 --- /dev/null +++ b/ldiw-swarm/infra/jenkins/deploy_infra.sh @@ -0,0 +1,25 @@ +#!/bin/bash + +set -x +# move everything to the shared file system +mkdir -p /opt/deploy/workspace +cp -a $WORKSPACE /opt/deploy/workspace +WORKSPACE=/opt/deploy/workspace/$JOB_NAME +cd $WORKSPACE/${ENV_LABEL} + + +# Check tasks to do +if $DEPLOY_PROXY; then + docker stack rm proxy + ./deploy_proxy.sh +fi + +if $DEPLOY_CERTBOT; then + docker stack rm certbot + ./deploy_certbot.sh +fi + +if $DEPLOY_INFRA; then + docker stack rm infra + ./deploy_infra.sh +fi \ No newline at end of file diff --git a/ldiw-swarm/infra/jenkins/prod_deploy.sh b/ldiw-swarm/infra/jenkins/prod_deploy.sh new file mode 100644 index 0000000000..038188d223 --- /dev/null +++ b/ldiw-swarm/infra/jenkins/prod_deploy.sh @@ -0,0 +1,43 @@ +#!/bin/bash +set -x +# move everything to the shared file system +mkdir -p /opt/deploy/workspace +cp -a $WORKSPACE /opt/deploy/workspace +WORKSPACE=/opt/deploy/workspace/$JOB_NAME +cd $WORKSPACE + + +docker stack rm app || true +# wait for couchbase to clear filesystem locks +sleep 10 + + +eval `ssh-agent -s` +ssh-add /root/.ssh/id_rsa + +cp -a devops/backend-prod/.env ${ENV_LABEL}/app/.globalenv +cp -a devops/backend-prod/services/backend-api/.env ${ENV_LABEL}/app/api.env +cp -a devops/backend-prod/services/backend-auth/.env ${ENV_LABEL}/app/auth.env +cp -a devops/backend-prod/services/backend-db/.env ${ENV_LABEL}/app/db.env +cp -a devops/backend-prod/services/backend-geo/.env ${ENV_LABEL}/app/geo.env +#cp -a devops/backend-prod/services/couchbase/local.ini ${ENV_LABEL}/app/local.ini +cp -a devops/backend-prod/services/couchdb/etc/local.ini ${ENV_LABEL}/app/local.ini +cp -a devops/backend-prod/services/couchdb/.env ${ENV_LABEL}/app/couchdb.env + + +cd ${ENV_LABEL}/app +sed -e s/"ENV_LABEL=.*"/"ENV_LABEL=$ENV_LABEL"/g -i .env + +# change auth.env +sed -e "s#JWT_SECRET=.*#JWT_SECRET=$JWT_SECRET#g" -i auth.env +sed -e "s#AZURE_STORAGE_ACCESS_KEY=.*#AZURE_STORAGE_ACCESS_KEY=$AZURE_STORAGE_ACCESS_KEY#g" -i auth.env +sed -e "s#AZURE_STORAGE_ACCOUNT=.*#AZURE_STORAGE_ACCOUNT=$STORAGE_ACCOUNT#g" -i auth.env +sed -e "s#COUCHDB_USER=.*#COUCHDB_USER=$COUCHDB_USER#g" -i .globalenv +sed -e "s#COUCHDB_PASSWORD=.*#COUCHDB_PASSWORD=$COUCHDB_PASSWORD#g" -i .globalenv + +# add couch url add end of db.env +echo "COUCHBASE_ENDPOINT=$COUCHBASE_ENDPOINT" >> db.env + +./deploy_app.sh +echo "Giving the cluster time to start all containers.." +sleep 120 \ No newline at end of file diff --git a/ldiw-swarm/infra/jenkins/publish.sh b/ldiw-swarm/infra/jenkins/publish.sh new file mode 100644 index 0000000000..84e00d4d9f --- /dev/null +++ b/ldiw-swarm/infra/jenkins/publish.sh @@ -0,0 +1,15 @@ +#/bin/bash + +set +x +# docker rmi $(docker images -q --filter dangling=true) || true + +# push image tags to registry +for i in $TAGGED_IMAGES; do + echo "Pushing image $i to registry.." + docker push $i + if [ $? != "0" ];then echo "Push failed! exiting..";exit 1;fi + echo "Removing local image." + docker rmi $i -f +done + +docker rmi $(docker images -q --filter reference=backend*) -f || true \ No newline at end of file diff --git a/ldiw-swarm/infra/proxy-template.yml b/ldiw-swarm/infra/proxy-template.yml new file mode 100644 index 0000000000..8582722df2 --- /dev/null +++ b/ldiw-swarm/infra/proxy-template.yml @@ -0,0 +1,51 @@ +version: '3.1' + +services: + proxy: + image: vfarcic/docker-flow-proxy:17.08.28-3 + ports: + - 80:80 + - 443:443 + networks: + - ${NETWORK} + environment: + - LISTENER_ADDRESS=swarm-listener + - MODE=swarm + - DO_NOT_RESOLVE_ADDR=true + - CHECK_RESOLVERS=true +# - DEBUG=true + deploy: + replicas: 1 + labels: + com.ldiw.description: "${DEPLOYMENT_LABEL}" + + swarm-listener: + image: vfarcic/docker-flow-swarm-listener:17.07.28-1 + networks: + - ${NETWORK} + volumes: + - /var/run/docker.sock:/var/run/docker.sock + environment: + - DF_NOTIFY_CREATE_SERVICE_URL=http://proxy:8080/v1/docker-flow-proxy/reconfigure + - DF_NOTIFY_REMOVE_SERVICE_URL=http://proxy:8080/v1/docker-flow-proxy/remove + deploy: + placement: + constraints: [node.role == manager] + labels: + com.ldiw.description: "${DEPLOYMENT_LABEL}" + +networks: + ${NETWORK}: + driver: overlay + external: true + +volumes: + certbot: + driver: "azurefile" + driver_opts: + share: "certificates" + + +#secrets: +# cert-qualitance.com.pem: +# external: true \ No newline at end of file diff --git a/ldiw-swarm/infra/registry/config.yml b/ldiw-swarm/infra/registry/config.yml new file mode 100644 index 0000000000..a4118e3ddf --- /dev/null +++ b/ldiw-swarm/infra/registry/config.yml @@ -0,0 +1,24 @@ +version: 0.1 +log: + fields: + service: registry +storage: + cache: + blobdescriptor: inmemory + filesystem: + rootdirectory: /var/lib/registry +http: + addr: :5000 + headers: + X-Content-Type-Options: [nosniff] +health: + storagedriver: + enabled: true + interval: 10s + threshold: 3 +delete: + enabled: true +auth: + htpasswd: + realm: Ldiw Registry + path: registry-htpasswd \ No newline at end of file diff --git a/ldiw-swarm/infra/registry/registry-htpasswd b/ldiw-swarm/infra/registry/registry-htpasswd new file mode 100644 index 0000000000..8a54b6d629 --- /dev/null +++ b/ldiw-swarm/infra/registry/registry-htpasswd @@ -0,0 +1 @@ +manager:$2y$05$K.l6szsXazZvcedvO6pYuu6/ZPwy29/gTA8CtvEjI4O.b0Azof3pe \ No newline at end of file diff --git a/ldiw-swarm/production/.env b/ldiw-swarm/production/.env new file mode 100644 index 0000000000..8b9145f056 --- /dev/null +++ b/ldiw-swarm/production/.env @@ -0,0 +1,4 @@ +export CLUSTER_NETWORK_NAME="production" +export ENV_LABEL="" +export DEPLOYMENT_LABEL="Deployed on $(date)" +export NETWORK="${CLUSTER_NETWORK_NAME}" \ No newline at end of file diff --git a/ldiw-swarm/production/app/.env b/ldiw-swarm/production/app/.env new file mode 100644 index 0000000000..33a40b8d3c --- /dev/null +++ b/ldiw-swarm/production/app/.env @@ -0,0 +1,4 @@ +export ENV_LABEL="production" +export DEPLOYMENT_LABEL="Deployed on $(date)" +export NETWORK="${ENV_LABEL}" + diff --git a/ldiw-swarm/production/app/api.env b/ldiw-swarm/production/app/api.env new file mode 100644 index 0000000000..8b13789179 --- /dev/null +++ b/ldiw-swarm/production/app/api.env @@ -0,0 +1 @@ + diff --git a/ldiw-swarm/production/app/app-template.yml b/ldiw-swarm/production/app/app-template.yml new file mode 100644 index 0000000000..bd48168999 --- /dev/null +++ b/ldiw-swarm/production/app/app-template.yml @@ -0,0 +1,125 @@ +version: '3.1' + +services: + api: + image: registry.ops.worldcleanupday.com/api + networks: + - ${NETWORK} + env_file: + - api.env + - .globalenv + deploy: + replicas: 2 + restart_policy: + condition: on-failure + labels: + - com.df.notify=true + - com.df.serviceDomain=api.app.worldcleanupday.com + - com.df.servicePath=/ + # - com.df.srcPort=443 + - com.df.port=80 + # do ssl and http -> https redirect + - com.df.httpsOnly=true + - com.df.xForwardedProto=true + - com.df.redirectWhenHttpProto=true + - com.ldiw.description="${DEPLOYMENT_LABEL}" + + auth: + image: registry.ops.worldcleanupday.com/auth + networks: + - ${NETWORK} + env_file: + - auth.env + - .globalenv + deploy: + replicas: 2 + restart_policy: + condition: on-failure + labels: + - com.ldiw.description="${DEPLOYMENT_LABEL}" + + db: + image: registry.ops.worldcleanupday.com/db + networks: + - ${NETWORK} + env_file: + - db.env + - .globalenv + deploy: + replicas: 2 + restart_policy: + condition: on-failure + labels: + - com.ldiw.description="${DEPLOYMENT_LABEL}" + + geo: + image: registry.ops.worldcleanupday.com/geo + networks: + - ${NETWORK} + env_file: + - geo.env + - .globalenv + deploy: + replicas: 2 + restart_policy: + condition: on-failure + labels: + - com.ldiw.description="${DEPLOYMENT_LABEL}" + + couchdb: + image: registry.ops.worldcleanupday.com/couchdb_geocouch:2 + networks: + - ${NETWORK} + environment: + - "LCB_LOGLEVEL=5" + - "COUCHDB_USER=backenddb" + - "COUCHDB_PASSWORD=rockychrome" + env_file: + - couchdb.env + - .globalenv + volumes: + - couchdb-${ENV_LABEL}:/usr/local/var/lib/couchdb + - $PWD/local.ini:/usr/local/etc/couchdb/local.ini + deploy: + replicas: 1 + restart_policy: + condition: on-failure + placement: + constraints: + - node.role!=manager + labels: + - com.ldiw.description="${DEPLOYMENT_LABEL}" + + webapp: + image: registry.ops.worldcleanupday.com/webapp + networks: + - ${NETWORK} + deploy: + replicas: 2 + restart_policy: + condition: on-failure + labels: + - com.df.notify=true + - com.df.serviceDomain=app.worldcleanupday.com + - com.df.servicePath=/ + # - com.df.srcPort=443 + - com.df.port=80 + # do ssl and http -> https redirect + - com.df.httpsOnly=true + - com.df.reqMode=http + - com.df.xForwardedProto=true + - com.df.redirectWhenHttpProto=true + - com.ldiw.description="${DEPLOYMENT_LABEL}" + + +networks: + ${NETWORK}: + driver: overlay + external: true + + +volumes: + couchdb-${ENV_LABEL}: + driver: "azurefile" + driver_opts: + share: "couch-${ENV_LABEL}" \ No newline at end of file diff --git a/ldiw-swarm/production/app/deploy_app.sh b/ldiw-swarm/production/app/deploy_app.sh new file mode 100755 index 0000000000..307097c1c5 --- /dev/null +++ b/ldiw-swarm/production/app/deploy_app.sh @@ -0,0 +1,5 @@ +#!/bin/bash +source .env +envsubst < app-template.yml > app.yml +#env $(cat .api | grep ^[A-Z] | xargs) +docker stack deploy -c app.yml --with-registry-auth app diff --git a/ldiw-swarm/production/certbot-template.yml b/ldiw-swarm/production/certbot-template.yml new file mode 100644 index 0000000000..87030cb6ff --- /dev/null +++ b/ldiw-swarm/production/certbot-template.yml @@ -0,0 +1,30 @@ +version: '3.1' + +services: + letsencrypt-companion: + image: hamburml/docker-flow-letsencrypt:latest + networks: + - ${NETWORK} + environment: + - DOMAIN_1=('api.app.worldcleanupday.com') + - DOMAIN_2=('app.worldcleanupday.com') + - CERTBOT_EMAIL=daniel.jirca@qualitance.com + - PROXY_ADDRESS=proxy + - CERTBOT_CRON_RENEW=('0 3 * * *' '0 15 * * *') + volumes: + - /volatile/certbot:/etc/letsencrypt + deploy: + labels: + - com.df.servicePath=/.well-known/acme-challenge + - com.df.notify=true +# - com.df.distribute=true + - com.df.port=80 + - "com.ldiw.description=${DEPLOYMENT_LABEL}" + placement: + constraints: [node.role == manager] + replicas: 1 + +networks: + ${NETWORK}: + driver: overlay + external: true diff --git a/ldiw-swarm/production/deploy_certbot.sh b/ldiw-swarm/production/deploy_certbot.sh new file mode 100755 index 0000000000..6e3b747599 --- /dev/null +++ b/ldiw-swarm/production/deploy_certbot.sh @@ -0,0 +1,4 @@ +#!/bin/bash +source .env +envsubst < certbot-template.yml > certbot.yml +docker stack deploy -c certbot.yml --with-registry-auth certbot diff --git a/ldiw-swarm/production/deploy_infra.sh b/ldiw-swarm/production/deploy_infra.sh new file mode 100755 index 0000000000..c45c89e0bf --- /dev/null +++ b/ldiw-swarm/production/deploy_infra.sh @@ -0,0 +1,4 @@ +#!/bin/bash +source .env +envsubst < infrastructure-template.yml > infrastructure.yml +docker stack deploy -c infrastructure.yml --with-registry-auth infra diff --git a/ldiw-swarm/production/deploy_proxy.sh b/ldiw-swarm/production/deploy_proxy.sh new file mode 100755 index 0000000000..5662fa3812 --- /dev/null +++ b/ldiw-swarm/production/deploy_proxy.sh @@ -0,0 +1,4 @@ +#!/bin/bash +source .env +envsubst < proxy-template.yml > proxy.yml +docker stack deploy -c proxy.yml --with-registry-auth proxy diff --git a/ldiw-swarm/production/infrastructure-template.yml b/ldiw-swarm/production/infrastructure-template.yml new file mode 100644 index 0000000000..d871ca2821 --- /dev/null +++ b/ldiw-swarm/production/infrastructure-template.yml @@ -0,0 +1,26 @@ +version: '3.1' + +services: + logspout: + image: bekt/logspout-logstash + volumes: + - /var/run/docker.sock:/var/run/docker.sock + environment: + - "LOGSPOUT=ignore" + - "ROUTE_URIS=logstash+tcp://dock1-eu-infra:5100" + extra_hosts: + - "dock1-eu-infra:10.150.1.100" + networks: + - ${NETWORK} + deploy: + mode: global + restart_policy: + condition: on-failure + labels: + - com.ldiw.description="${DEPLOYMENT_LABEL}" + + +networks: + ${NETWORK}: + driver: overlay + external: true diff --git a/ldiw-swarm/production/proxy-template.yml b/ldiw-swarm/production/proxy-template.yml new file mode 100644 index 0000000000..fcafcadda0 --- /dev/null +++ b/ldiw-swarm/production/proxy-template.yml @@ -0,0 +1,40 @@ +version: '3.1' + +services: + proxy: + image: vfarcic/docker-flow-proxy:17.08.28-3 + ports: + - 80:80 + - 443:443 + networks: + - ${NETWORK} + environment: + - LISTENER_ADDRESS=swarm-listener + - MODE=swarm + - DO_NOT_RESOLVE_ADDR=true + - CHECK_RESOLVERS=true +# - DEBUG=true + deploy: + replicas: 2 + labels: + com.ldiw.description: "${DEPLOYMENT_LABEL}" + + swarm-listener: + image: vfarcic/docker-flow-swarm-listener:17.07.28-1 + networks: + - ${NETWORK} + volumes: + - /var/run/docker.sock:/var/run/docker.sock + environment: + - DF_NOTIFY_CREATE_SERVICE_URL=http://proxy:8080/v1/docker-flow-proxy/reconfigure + - DF_NOTIFY_REMOVE_SERVICE_URL=http://proxy:8080/v1/docker-flow-proxy/remove + deploy: + placement: + constraints: [node.role == manager] + labels: + com.ldiw.description: "${DEPLOYMENT_LABEL}" + +networks: + ${NETWORK}: + driver: overlay + external: true \ No newline at end of file diff --git a/ldiw-swarm/staging/.env b/ldiw-swarm/staging/.env new file mode 100644 index 0000000000..7834372424 --- /dev/null +++ b/ldiw-swarm/staging/.env @@ -0,0 +1,4 @@ +export CLUSTER_NETWORK_NAME="infra" +export ENV_LABEL="" +export DEPLOYMENT_LABEL="Deployed on $(date)" +export NETWORK="${CLUSTER_NETWORK_NAME}" diff --git a/ldiw-swarm/staging/app/.env b/ldiw-swarm/staging/app/.env new file mode 100644 index 0000000000..e3c08d2cbf --- /dev/null +++ b/ldiw-swarm/staging/app/.env @@ -0,0 +1,3 @@ +export ENV_LABEL="" +export DEPLOYMENT_LABEL="Deployed on $(date)" +export NETWORK="ldiw-${ENV_LABEL}" \ No newline at end of file diff --git a/ldiw-swarm/staging/app/app-template.yml b/ldiw-swarm/staging/app/app-template.yml new file mode 100644 index 0000000000..47bf3c710a --- /dev/null +++ b/ldiw-swarm/staging/app/app-template.yml @@ -0,0 +1,166 @@ +version: '3.1' + +services: + api: + image: registry.ops.worldcleanupday.com/api-${ENV_LABEL} + networks: + - ${NETWORK} + env_file: + - api.env + - .globalenv + deploy: + replicas: 2 + restart_policy: + condition: on-failure + labels: + - com.df.notify=true + - com.df.serviceDomain=api-${ENV_LABEL}.app.worldcleanupday.com + - com.df.servicePath=/ + # - com.df.srcPort=443 + - com.df.port=80 + # do ssl and http -> https redirect + - com.df.httpsOnly=true + - com.df.xForwardedProto=true + - com.df.redirectWhenHttpProto=true + - com.ldiw.description="${DEPLOYMENT_LABEL}" + + auth: + image: registry.ops.worldcleanupday.com/auth-${ENV_LABEL} + networks: + - ${NETWORK} + env_file: + - auth.env + - .globalenv + deploy: + replicas: 2 + restart_policy: + condition: on-failure + labels: + - com.ldiw.description="${DEPLOYMENT_LABEL}" + + db: + image: registry.ops.worldcleanupday.com/db-${ENV_LABEL} + networks: + - ${NETWORK} + env_file: + - db.env + - .globalenv + deploy: + replicas: 2 + restart_policy: + condition: on-failure + labels: + - com.ldiw.description="${DEPLOYMENT_LABEL}" + + geo: + image: registry.ops.worldcleanupday.com/geo-${ENV_LABEL} + networks: + - ${NETWORK} + env_file: + - geo.env + - .globalenv + deploy: + replicas: 2 + restart_policy: + condition: on-failure + labels: + - com.ldiw.description="${DEPLOYMENT_LABEL}" + + couchdb: + image: registry.ops.worldcleanupday.com/couchdb_geocouch:2 + networks: + - ${NETWORK} + environment: + - "LCB_LOGLEVEL=5" + - "COUCHDB_USER=backenddb" + - "COUCHDB_PASSWORD=rockychrome" + env_file: + - couchdb.env + - .globalenv + volumes: + - couchdb-${ENV_LABEL}:/usr/local/var/lib/couchdb + - $PWD/local.ini:/usr/local/etc/couchdb/local.ini + deploy: + replicas: 1 + restart_policy: + condition: on-failure +# placement: +# constraints: [node.role == worker] +# resources: +# limits: +# memory: 1G + labels: + - com.df.notify=true + - com.df.serviceDomain=couch-${ENV_LABEL}.app.worldcleanupday.com + - com.df.servicePath=/ + # - com.df.srcPort=443 + - com.df.port=5984 + # do ssl and http -> https redirect + - com.df.httpsOnly=true + - com.df.xForwardedProto=true + - com.df.redirectWhenHttpProto=true + - com.ldiw.description="${DEPLOYMENT_LABEL}" + + webapp: + image: registry.ops.worldcleanupday.com/webapp-${ENV_LABEL} + networks: + - ${NETWORK} + deploy: + replicas: 2 + restart_policy: + condition: on-failure + labels: + - com.df.notify=true + - com.df.serviceDomain=${ENV_LABEL}.app.worldcleanupday.com + - com.df.servicePath=/ + - com.df.srcPort=443 + - com.df.port=80 + # do ssl and http -> https redirect + - com.df.httpsOnly=true + - com.df.xForwardedProto=true + - com.df.redirectWhenHttpProto=true + - com.ldiw.description="${DEPLOYMENT_LABEL}" + +# couchbase: +## image: couchbase/server:community-4.5.1 +# image: couchbase:enterprise-4.6.2 +# networks: +# - ${NETWORK} +# environment: +# - "LCB_LOGLEVEL=5" +# volumes: +## - couch-${ENV_LABEL}:/opt/couchbase/var/lib/couchbase +# - /volatile/couchent-${ENV_LABEL}:/opt/couchbase/var/lib/couchbase +# - ./local.ini:/opt/couchbase/etc/couchdb/local.ini +# deploy: +# replicas: 1 +# restart_policy: +# condition: on-failure +# placement: +# constraints: [node.role == worker] +# resources: +# limits: +# memory: 1G +# labels: +# - com.df.notify=true +# - com.df.serviceDomain=couch-${ENV_LABEL}.app.worldcleanupday.com +# - com.df.servicePath=/ +# - com.df.srcPort=443 +# - com.df.port=8091 +# # do ssl and http -> https redirect +# - com.df.httpsOnly=true +# - com.df.xForwardedProto=true +# - com.df.redirectWhenHttpProto=true +# - com.ldiw.description="${DEPLOYMENT_LABEL}" + +networks: + ${NETWORK}: + driver: overlay + external: true + + +volumes: + couchdb-${ENV_LABEL}: + driver: "azurefile" + driver_opts: + share: "couch-${ENV_LABEL}" \ No newline at end of file diff --git a/ldiw-swarm/staging/app/deploy_app.sh b/ldiw-swarm/staging/app/deploy_app.sh new file mode 100755 index 0000000000..d8dd14f3ac --- /dev/null +++ b/ldiw-swarm/staging/app/deploy_app.sh @@ -0,0 +1,4 @@ +#!/bin/bash +source .env +envsubst < app-template.yml > app.yml +docker stack deploy -c app.yml --with-registry-auth app${ENV_LABEL} diff --git a/ldiw-swarm/staging/certbot-template.yml b/ldiw-swarm/staging/certbot-template.yml new file mode 100644 index 0000000000..6b40082c42 --- /dev/null +++ b/ldiw-swarm/staging/certbot-template.yml @@ -0,0 +1,40 @@ +version: '3.1' + +services: + letsencrypt-companion: + image: hamburml/docker-flow-letsencrypt:latest + networks: + - infra + environment: + - DOMAIN_1=('api-qa.app.worldcleanupday.com') + - DOMAIN_2=('api-staging.app.worldcleanupday.com') + - DOMAIN_3=('couch-qa.app.worldcleanupday.com') + - DOMAIN_4=('couch-staging.app.worldcleanupday.com') + - DOMAIN_5=('staging.app.worldcleanupday.com') + - DOMAIN_6=('qa.app.worldcleanupday.com') + - CERTBOT_EMAIL=daniel.jirca@qualitance.com + - PROXY_ADDRESS=proxy + - CERTBOT_CRON_RENEW=('0 3 * * *' '0 15 * * *') + volumes: + - /volatile/certbot:/etc/letsencrypt + deploy: + labels: + - com.df.servicePath=/.well-known/acme-challenge + - com.df.notify=true +# - com.df.distribute=true + - com.df.port=80 + - "com.ldiw.description=${DEPLOYMENT_LABEL}" + placement: + constraints: [node.role == manager] + replicas: 1 + +networks: + ${NETWORK}: + driver: overlay + external: true + +volumes: + certbot: + driver: "azurefile" + driver_opts: + share: "certificates" diff --git a/ldiw-swarm/staging/deploy_certbot.sh b/ldiw-swarm/staging/deploy_certbot.sh new file mode 100755 index 0000000000..6e3b747599 --- /dev/null +++ b/ldiw-swarm/staging/deploy_certbot.sh @@ -0,0 +1,4 @@ +#!/bin/bash +source .env +envsubst < certbot-template.yml > certbot.yml +docker stack deploy -c certbot.yml --with-registry-auth certbot diff --git a/ldiw-swarm/staging/deploy_infra.sh b/ldiw-swarm/staging/deploy_infra.sh new file mode 100755 index 0000000000..c45c89e0bf --- /dev/null +++ b/ldiw-swarm/staging/deploy_infra.sh @@ -0,0 +1,4 @@ +#!/bin/bash +source .env +envsubst < infrastructure-template.yml > infrastructure.yml +docker stack deploy -c infrastructure.yml --with-registry-auth infra diff --git a/ldiw-swarm/staging/deploy_proxy.sh b/ldiw-swarm/staging/deploy_proxy.sh new file mode 100755 index 0000000000..5662fa3812 --- /dev/null +++ b/ldiw-swarm/staging/deploy_proxy.sh @@ -0,0 +1,4 @@ +#!/bin/bash +source .env +envsubst < proxy-template.yml > proxy.yml +docker stack deploy -c proxy.yml --with-registry-auth proxy diff --git a/ldiw-swarm/staging/infrastructure-template.yml b/ldiw-swarm/staging/infrastructure-template.yml new file mode 100644 index 0000000000..f8e59c36b6 --- /dev/null +++ b/ldiw-swarm/staging/infrastructure-template.yml @@ -0,0 +1,34 @@ +version: '3.1' + +services: + logspout: + image: bekt/logspout-logstash + volumes: + - /var/run/docker.sock:/var/run/docker.sock + environment: + - "LOGSPOUT=ignore" + - "ROUTE_URIS=logstash+tcp://dock1-eu-infra:5100" + extra_hosts: + - "dock1-eu-infra:10.150.1.100" + networks: + - infra + - ldiw-qa + - ldiw-staging + deploy: + mode: global + restart_policy: + condition: on-failure + labels: + - com.ldiw.description="${DEPLOYMENT_LABEL}" + + +networks: + infra: + driver: overlay + external: true + ldiw-qa: + driver: overlay + external: true + ldiw-staging: + driver: overlay + external: true diff --git a/ldiw-swarm/staging/proxy-template.yml b/ldiw-swarm/staging/proxy-template.yml new file mode 100644 index 0000000000..ced7189af8 --- /dev/null +++ b/ldiw-swarm/staging/proxy-template.yml @@ -0,0 +1,54 @@ +version: '3.1' + +services: + proxy: + image: vfarcic/docker-flow-proxy:17.08.28-3 + ports: + - 80:80 + - 443:443 + networks: + - infra + - ldiw-qa + - ldiw-staging + environment: + - LISTENER_ADDRESS=swarm-listener + - MODE=swarm + - DO_NOT_RESOLVE_ADDR=true + - CHECK_RESOLVERS=true +# - DEBUG=true + deploy: + replicas: 1 + labels: + com.ldiw.description: "${DEPLOYMENT_LABEL}" + + swarm-listener: + image: vfarcic/docker-flow-swarm-listener:17.07.28-1 + networks: + - infra + volumes: + - /var/run/docker.sock:/var/run/docker.sock + environment: + - DF_NOTIFY_CREATE_SERVICE_URL=http://proxy:8080/v1/docker-flow-proxy/reconfigure + - DF_NOTIFY_REMOVE_SERVICE_URL=http://proxy:8080/v1/docker-flow-proxy/remove + deploy: + placement: + constraints: [node.role == manager] + labels: + com.ldiw.description: "${DEPLOYMENT_LABEL}" + +networks: + infra: + driver: overlay + external: true + ldiw-qa: + driver: overlay + external: true + ldiw-staging: + driver: overlay + external: true + +volumes: + certbot: + driver: "azurefile" + driver_opts: + share: "certificates" diff --git a/ldiw-swarm/support/EU-clusters.png b/ldiw-swarm/support/EU-clusters.png new file mode 100644 index 0000000000..1532cbb82e Binary files /dev/null and b/ldiw-swarm/support/EU-clusters.png differ diff --git a/ldiw-swarm/support/api.png b/ldiw-swarm/support/api.png new file mode 100644 index 0000000000..86c78e36b7 Binary files /dev/null and b/ldiw-swarm/support/api.png differ diff --git a/ldiw-swarm/support/build-publish-deploy.png b/ldiw-swarm/support/build-publish-deploy.png new file mode 100644 index 0000000000..1e261c74f7 Binary files /dev/null and b/ldiw-swarm/support/build-publish-deploy.png differ diff --git a/ldiw-swarm/support/jenkins_jobs.png b/ldiw-swarm/support/jenkins_jobs.png new file mode 100644 index 0000000000..abfc1abac6 Binary files /dev/null and b/ldiw-swarm/support/jenkins_jobs.png differ diff --git a/ldiw-swarm/support/scripts/backup.sh b/ldiw-swarm/support/scripts/backup.sh new file mode 100644 index 0000000000..4ebb605254 --- /dev/null +++ b/ldiw-swarm/support/scripts/backup.sh @@ -0,0 +1,8 @@ +#!/bin/bash +BACKUP_DIR="$(date +%d%m%Y_%H%M)" +echo $BACKUP_DIR +mkdir -p /backup/$BACKUP_DIR +mount /mnt && sleep 10 +ionice -c2 -n7 tar --use-compress-program=pigz -cf /backup/$BACKUP_DIR/couchdb.tgz -C /mnt/ . +sha1sum /backup/$BACKUP_DIR/couchdb.tgz > /backup/$BACKUP_DIR/couchdb.tgz.sha1 +umount /mnt diff --git a/mobile-app/package-lock.json b/mobile-app/package-lock.json index b9c160a8a7..0f6b3ba0ad 100644 --- a/mobile-app/package-lock.json +++ b/mobile-app/package-lock.json @@ -1,13 +1,18 @@ -{ +remote-redux-devtools{ "name": "mobile-app", "version": "0.1.0", "lockfileVersion": 1, + "requires": true, "dependencies": { "@ccheever/crayon": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/@ccheever/crayon/-/crayon-5.0.0.tgz", "integrity": "sha1-pxknU8HCXXWI7QHWBYxkxFenHGM=", "dev": true, + "requires": { + "has-color": "0.1.7", + "strip-ansi": "0.2.2" + }, "dependencies": { "ansi-regex": { "version": "0.1.0", @@ -19,7 +24,38 @@ "version": "0.2.2", "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-0.2.2.tgz", "integrity": "sha1-hU0pDJgVJfyMOXqRCwJa4tVP/Ag=", - "dev": true + "dev": true, + "requires": { + "ansi-regex": "0.1.0" + } + } + } + }, + "@expo/spawn-async": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/@expo/spawn-async/-/spawn-async-1.3.0.tgz", + "integrity": "sha1-Abik9ruhC3kmY/knLfZsfpAWba0=", + "requires": { + "cross-spawn": "5.1.0" + } + }, + "@expo/vector-icons": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/@expo/vector-icons/-/vector-icons-5.0.0.tgz", + "integrity": "sha1-OA1Xili3NraTrN0aqG+LZXZGW6Q=", + "requires": { + "react-native-vector-icons": "4.1.1" + }, + "dependencies": { + "react-native-vector-icons": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/react-native-vector-icons/-/react-native-vector-icons-4.1.1.tgz", + "integrity": "sha1-msdb3nfZJDNGZoxR3Kd1Z3VCgIc=", + "requires": { + "lodash": "4.17.4", + "prop-types": "15.5.10", + "yargs": "6.6.0" + } } } }, @@ -27,13 +63,25 @@ "version": "5.3.0", "resolved": "https://registry.npmjs.org/@exponent/json-file/-/json-file-5.3.0.tgz", "integrity": "sha1-RtRUpPnmqHLzBlTEWijP3IPnnAM=", - "dev": true + "dev": true, + "requires": { + "json5": "0.5.1", + "lodash": "4.17.4", + "mz": "2.6.0" + } }, "@exponent/ngrok": { "version": "2.2.7", "resolved": "https://registry.npmjs.org/@exponent/ngrok/-/ngrok-2.2.7.tgz", "integrity": "sha1-N/5m+SKxAD2ip4xmt9TTvJMT5CM=", "dev": true, + "requires": { + "async": "0.9.2", + "decompress-zip": "0.3.0", + "lock": "0.1.3", + "request": "2.81.0", + "uuid": "3.0.1" + }, "dependencies": { "async": { "version": "0.9.2", @@ -48,6 +96,12 @@ "resolved": "https://registry.npmjs.org/@exponent/node-auth0/-/node-auth0-2.6.0.tgz", "integrity": "sha1-1wN3F8VLYYOSOi2ncq2/gvIfEto=", "dev": true, + "requires": { + "bluebird": "2.11.0", + "request": "2.81.0", + "rest-facade": "1.5.0", + "url-join": "0.0.1" + }, "dependencies": { "bluebird": { "version": "2.11.0", @@ -62,12 +116,20 @@ "resolved": "https://registry.npmjs.org/@exponent/osascript/-/osascript-1.6.4.tgz", "integrity": "sha1-HFwLKN1BuMtOEeBsejIwv77fFq0=", "dev": true, + "requires": { + "@exponent/spawn-async": "1.2.8", + "babel-runtime": "5.8.38", + "exec-async": "2.2.0" + }, "dependencies": { "babel-runtime": { "version": "5.8.38", "resolved": "https://registry.npmjs.org/babel-runtime/-/babel-runtime-5.8.38.tgz", "integrity": "sha1-HAsC62MxL18If/IEUIJ7QlydTBk=", - "dev": true + "dev": true, + "requires": { + "core-js": "1.2.7" + } }, "core-js": { "version": "1.2.7", @@ -82,12 +144,19 @@ "resolved": "https://registry.npmjs.org/@exponent/spawn-async/-/spawn-async-1.2.8.tgz", "integrity": "sha1-y/+kVwSTldArWQ9sBPBvSs0Mtyk=", "dev": true, + "requires": { + "cross-spawn": "4.0.2" + }, "dependencies": { "cross-spawn": { "version": "4.0.2", "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-4.0.2.tgz", "integrity": "sha1-e5JHYhwjrf3ThWAEqCPL45dCTUE=", - "dev": true + "dev": true, + "requires": { + "lru-cache": "4.1.1", + "which": "1.2.14" + } } } }, @@ -95,6 +164,16 @@ "version": "1.1.2", "resolved": "https://registry.npmjs.org/@segment/loosely-validate-event/-/loosely-validate-event-1.1.2.tgz", "integrity": "sha1-13hAmZ4/fkPnSzsNQzkcFSb3k7g=", + "dev": true, + "requires": { + "component-type": "1.2.1", + "join-component": "1.1.0" + } + }, + "Base64": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/Base64/-/Base64-0.1.4.tgz", + "integrity": "sha1-6fbGvvVn/WNepBYqsU3TKedKpt4=", "dev": true }, "abbrev": { @@ -103,35 +182,120 @@ "integrity": "sha1-0FVMIlZjbi9W58LlrRg/hZQo2B8=", "dev": true }, + "absolute-path": { + "version": "0.0.0", + "resolved": "https://registry.npmjs.org/absolute-path/-/absolute-path-0.0.0.tgz", + "integrity": "sha1-p4di+9rftSl76ZsV01p4Wy8JW/c=" + }, "accepts": { "version": "1.3.3", "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.3.tgz", "integrity": "sha1-w8p0NJOGSMPg2cHjKN1otiLChMo=", + "requires": { + "mime-types": "2.1.15", + "negotiator": "0.6.1" + } + }, + "acorn": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-5.5.0.tgz", + "integrity": "sha512-arn53F07VXmls4o4pUhSzBa4fvaagPRe7AVZ8l7NHxFWUie2DsuFSBMMNAkgzRlOhEhzAnxeKyaWVzOH4xqp/g==", "dev": true }, + "acorn-jsx": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-3.0.1.tgz", + "integrity": "sha1-r9+UiPsezvyDSPb7IvRk4ypYs2s=", + "dev": true, + "requires": { + "acorn": "3.3.0" + }, + "dependencies": { + "acorn": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-3.3.0.tgz", + "integrity": "sha1-ReN/s56No/JbruP/U2niu18iAXo=", + "dev": true + } + } + }, "ajv": { "version": "4.11.8", "resolved": "https://registry.npmjs.org/ajv/-/ajv-4.11.8.tgz", "integrity": "sha1-gv+wKynmYq5TvcIK8VlHcGc5xTY=", + "requires": { + "co": "4.6.0", + "json-stable-stringify": "1.0.1" + } + }, + "ajv-keywords": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-1.5.1.tgz", + "integrity": "sha1-MU3QpLM2j609/NxU7eYXG4htrzw=", "dev": true }, + "align-text": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/align-text/-/align-text-0.1.4.tgz", + "integrity": "sha1-DNkKVhCT810KmSVsIrcGlDP60Rc=", + "requires": { + "kind-of": "3.2.2", + "longest": "1.0.1", + "repeat-string": "1.6.1" + } + }, "analytics-node": { "version": "2.4.1", "resolved": "https://registry.npmjs.org/analytics-node/-/analytics-node-2.4.1.tgz", "integrity": "sha1-H5bI64h7bEdpEESsf8mhIx+wIPc=", - "dev": true + "dev": true, + "requires": { + "@segment/loosely-validate-event": "1.1.2", + "clone": "2.1.1", + "commander": "2.9.0", + "crypto-token": "1.0.1", + "debug": "2.6.8", + "lodash": "4.17.4", + "remove-trailing-slash": "0.1.0", + "superagent": "3.5.2", + "superagent-retry": "0.6.0" + } + }, + "ansi": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/ansi/-/ansi-0.3.1.tgz", + "integrity": "sha1-DELU+xcWDVqa8eSEus4cZpIsGyE=" + }, + "ansi-align": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/ansi-align/-/ansi-align-1.1.0.tgz", + "integrity": "sha1-LwwWWIKXOa3V67FeawxuNCPwFro=", + "requires": { + "string-width": "1.0.2" + } + }, + "ansi-gray": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/ansi-gray/-/ansi-gray-0.1.1.tgz", + "integrity": "sha1-KWLPVOyXksSFEKPetSRDaGHvclE=", + "requires": { + "ansi-wrap": "0.1.0" + } }, "ansi-regex": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", - "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=", - "dev": true + "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=" }, "ansi-styles": { "version": "2.2.1", "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz", - "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=", - "dev": true + "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=" + }, + "ansi-wrap": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/ansi-wrap/-/ansi-wrap-0.1.0.tgz", + "integrity": "sha1-qCJQ3bABXponyoLoLqYDu/pF768=" }, "any-promise": { "version": "1.3.0", @@ -139,29 +303,113 @@ "integrity": "sha1-q8av7tzqUugJzcA3au0845Y10X8=", "dev": true }, + "anymatch": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-1.3.2.tgz", + "integrity": "sha512-0XNayC8lTHQ2OI8aljNCN3sSx6hsr/1+rlcDAotXJR7C1oZZHCNsfpbKwMjRA3Uqb5tF1Rae2oloTr4xpq+WjA==", + "requires": { + "micromatch": "2.3.11", + "normalize-path": "2.1.1" + } + }, + "are-we-there-yet": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/are-we-there-yet/-/are-we-there-yet-1.1.4.tgz", + "integrity": "sha1-u13KOCu5TwXhUZQ3PRb9O6HKEQ0=", + "requires": { + "delegates": "1.0.0", + "readable-stream": "1.1.14" + } + }, + "argparse": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", + "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", + "dev": true, + "requires": { + "sprintf-js": "1.0.3" + } + }, + "argsarray": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/argsarray/-/argsarray-0.0.1.tgz", + "integrity": "sha1-bnIHtOzbObCviDA/pa4ivajfYcs=" + }, + "aria-query": { + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/aria-query/-/aria-query-0.5.0.tgz", + "integrity": "sha1-heMVLNjMW6sY2+1hzZxPzlT6ecM=", + "dev": true, + "requires": { + "ast-types-flow": "0.0.7" + } + }, "arr-diff": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/arr-diff/-/arr-diff-2.0.0.tgz", "integrity": "sha1-jzuCf5Vai9ZpaX5KQlasPOrjVs8=", - "dev": true + "requires": { + "arr-flatten": "1.0.3" + } }, "arr-flatten": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/arr-flatten/-/arr-flatten-1.0.3.tgz", - "integrity": "sha1-onTthawIhJtr14R8RYB0XcUa37E=", - "dev": true + "integrity": "sha1-onTthawIhJtr14R8RYB0XcUa37E=" + }, + "array-differ": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/array-differ/-/array-differ-1.0.0.tgz", + "integrity": "sha1-7/UuN1gknTO+QCuLuOVkuytdQDE=" + }, + "array-filter": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/array-filter/-/array-filter-0.0.1.tgz", + "integrity": "sha1-fajPLiZijtcygDWB/SH2fKzS7uw=" }, "array-flatten": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz", - "integrity": "sha1-ml9pkFGx5wczKPKgCJaLZOopVdI=", - "dev": true + "integrity": "sha1-ml9pkFGx5wczKPKgCJaLZOopVdI=" + }, + "array-includes": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/array-includes/-/array-includes-3.0.3.tgz", + "integrity": "sha1-GEtI9i2S10UrsxsyMWXH+L0CJm0=", + "dev": true, + "requires": { + "define-properties": "1.1.2", + "es-abstract": "1.10.0" + } + }, + "array-map": { + "version": "0.0.0", + "resolved": "https://registry.npmjs.org/array-map/-/array-map-0.0.0.tgz", + "integrity": "sha1-iKK6tz0c97zVwbEYoAP2b2ZfpmI=" + }, + "array-reduce": { + "version": "0.0.0", + "resolved": "https://registry.npmjs.org/array-reduce/-/array-reduce-0.0.0.tgz", + "integrity": "sha1-FziZ0//Rx9k4PkR5Ul2+J4yrXys=" + }, + "array-union": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/array-union/-/array-union-1.0.2.tgz", + "integrity": "sha1-mjRBDk9OPaI96jdb5b5w8kd47Dk=", + "dev": true, + "requires": { + "array-uniq": "1.0.3" + } + }, + "array-uniq": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/array-uniq/-/array-uniq-1.0.3.tgz", + "integrity": "sha1-r2rId6Jcx/dOBYiUdThY39sk/bY=" }, "array-unique": { "version": "0.2.1", "resolved": "https://registry.npmjs.org/array-unique/-/array-unique-0.2.1.tgz", - "integrity": "sha1-odl8yvy8JiXMcPrc6zalDFiwGlM=", - "dev": true + "integrity": "sha1-odl8yvy8JiXMcPrc6zalDFiwGlM=" }, "arrify": { "version": "1.0.1", @@ -169,6 +417,11 @@ "integrity": "sha1-iYUI2iIm84DfkEcoRWhJwVAaSw0=", "dev": true }, + "art": { + "version": "0.10.1", + "resolved": "https://registry.npmjs.org/art/-/art-0.10.1.tgz", + "integrity": "sha1-OFQYg+OZIlxeGT/yRujxV897IUY=" + }, "asap": { "version": "2.0.5", "resolved": "https://registry.npmjs.org/asap/-/asap-2.0.5.tgz", @@ -177,26 +430,47 @@ "asn1": { "version": "0.2.3", "resolved": "https://registry.npmjs.org/asn1/-/asn1-0.2.3.tgz", - "integrity": "sha1-2sh4dxPJlmhJ/IGAd36+nB3fO4Y=", - "dev": true + "integrity": "sha1-2sh4dxPJlmhJ/IGAd36+nB3fO4Y=" }, "assert-plus": { "version": "0.2.0", "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-0.2.0.tgz", - "integrity": "sha1-104bh+ev/A24qttwIfP+SBAasjQ=", + "integrity": "sha1-104bh+ev/A24qttwIfP+SBAasjQ=" + }, + "ast-types-flow": { + "version": "0.0.7", + "resolved": "https://registry.npmjs.org/ast-types-flow/-/ast-types-flow-0.0.7.tgz", + "integrity": "sha1-9wtzXGvKGlycItmCw+Oef+ujva0=", "dev": true }, + "async": { + "version": "2.6.0", + "resolved": "https://registry.npmjs.org/async/-/async-2.6.0.tgz", + "integrity": "sha512-xAfGg1/NTLBBKlHFmnd7PlmUW9KhVQIUuSrYem9xzFUZy13ScvtyGGejaae9iAVRiRq9+Cx7DPFaAAhCpyxyPw==", + "requires": { + "lodash": "4.17.4" + } + }, "asynckit": { "version": "0.4.0", "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", - "integrity": "sha1-x57Zf380y48robyXkLzDZkdLS3k=", - "dev": true + "integrity": "sha1-x57Zf380y48robyXkLzDZkdLS3k=" }, "auth0-js": { "version": "7.6.1", "resolved": "https://registry.npmjs.org/auth0-js/-/auth0-js-7.6.1.tgz", "integrity": "sha1-W66oYDEzuxQ70sMntVpX2nr9+Xw=", "dev": true, + "requires": { + "Base64": "0.1.4", + "json-fallback": "0.0.1", + "jsonp": "0.0.4", + "qs": "6.4.0", + "reqwest": "2.0.5", + "trim": "0.0.1", + "winchan": "0.1.4", + "xtend": "2.1.2" + }, "dependencies": { "xtend": { "version": "2.1.2", @@ -209,56 +483,274 @@ "aws-sign2": { "version": "0.6.0", "resolved": "https://registry.npmjs.org/aws-sign2/-/aws-sign2-0.6.0.tgz", - "integrity": "sha1-FDQt0428yU0OW4fXY81jYSwOeU8=", - "dev": true + "integrity": "sha1-FDQt0428yU0OW4fXY81jYSwOeU8=" }, "aws4": { "version": "1.6.0", "resolved": "https://registry.npmjs.org/aws4/-/aws4-1.6.0.tgz", - "integrity": "sha1-g+9cqGCysy5KDe7e6MdxudtXRx4=", - "dev": true + "integrity": "sha1-g+9cqGCysy5KDe7e6MdxudtXRx4=" + }, + "axios": { + "version": "0.16.2", + "resolved": "https://registry.npmjs.org/axios/-/axios-0.16.2.tgz", + "integrity": "sha1-uk+S8XFn37q0CYN4VFS5rBScPG0=", + "requires": { + "follow-redirects": "1.4.1", + "is-buffer": "1.1.5" + } + }, + "axobject-query": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/axobject-query/-/axobject-query-0.1.0.tgz", + "integrity": "sha1-YvWdvFnJ+SQnWco0mWDnov48NsA=", + "dev": true, + "requires": { + "ast-types-flow": "0.0.7" + } }, "babel-code-frame": { "version": "6.22.0", "resolved": "https://registry.npmjs.org/babel-code-frame/-/babel-code-frame-6.22.0.tgz", "integrity": "sha1-AnYgvuVnqIwyVhV05/0IAdMxGOQ=", - "dev": true + "requires": { + "chalk": "1.1.3", + "esutils": "2.0.2", + "js-tokens": "3.0.1" + } }, "babel-core": { "version": "6.25.0", "resolved": "https://registry.npmjs.org/babel-core/-/babel-core-6.25.0.tgz", "integrity": "sha1-fdQrBGPHQunVKW3rPsZ6kyLa1yk=", - "dev": true + "requires": { + "babel-code-frame": "6.22.0", + "babel-generator": "6.25.0", + "babel-helpers": "6.24.1", + "babel-messages": "6.23.0", + "babel-register": "6.24.1", + "babel-runtime": "6.23.0", + "babel-template": "6.25.0", + "babel-traverse": "6.25.0", + "babel-types": "6.25.0", + "babylon": "6.17.3", + "convert-source-map": "1.5.0", + "debug": "2.6.8", + "json5": "0.5.1", + "lodash": "4.17.4", + "minimatch": "3.0.4", + "path-is-absolute": "1.0.1", + "private": "0.1.7", + "slash": "1.0.0", + "source-map": "0.5.6" + } + }, + "babel-eslint": { + "version": "7.2.3", + "resolved": "https://registry.npmjs.org/babel-eslint/-/babel-eslint-7.2.3.tgz", + "integrity": "sha1-sv4tgBJkcPXBlELcdXJTqJdxCCc=", + "dev": true, + "requires": { + "babel-code-frame": "6.22.0", + "babel-traverse": "6.25.0", + "babel-types": "6.25.0", + "babylon": "6.17.3" + } }, "babel-generator": { "version": "6.25.0", "resolved": "https://registry.npmjs.org/babel-generator/-/babel-generator-6.25.0.tgz", "integrity": "sha1-M6GvcNXyiQrrRlpKd5PB32qeqfw=", - "dev": true + "requires": { + "babel-messages": "6.23.0", + "babel-runtime": "6.23.0", + "babel-types": "6.25.0", + "detect-indent": "4.0.0", + "jsesc": "1.3.0", + "lodash": "4.17.4", + "source-map": "0.5.6", + "trim-right": "1.0.1" + } + }, + "babel-helper-builder-binary-assignment-operator-visitor": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-helper-builder-binary-assignment-operator-visitor/-/babel-helper-builder-binary-assignment-operator-visitor-6.24.1.tgz", + "integrity": "sha1-zORReto1b0IgvK6KAsKzRvmlZmQ=", + "requires": { + "babel-helper-explode-assignable-expression": "6.24.1", + "babel-runtime": "6.23.0", + "babel-types": "6.25.0" + } + }, + "babel-helper-builder-react-jsx": { + "version": "6.26.0", + "resolved": "https://registry.npmjs.org/babel-helper-builder-react-jsx/-/babel-helper-builder-react-jsx-6.26.0.tgz", + "integrity": "sha1-Of+DE7dci2Xc7/HzHTg+D/KkCKA=", + "requires": { + "babel-runtime": "6.23.0", + "babel-types": "6.25.0", + "esutils": "2.0.2" + } + }, + "babel-helper-call-delegate": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-helper-call-delegate/-/babel-helper-call-delegate-6.24.1.tgz", + "integrity": "sha1-7Oaqzdx25Bw0YfiL/Fdb0Nqi340=", + "requires": { + "babel-helper-hoist-variables": "6.24.1", + "babel-runtime": "6.23.0", + "babel-traverse": "6.25.0", + "babel-types": "6.25.0" + } + }, + "babel-helper-define-map": { + "version": "6.26.0", + "resolved": "https://registry.npmjs.org/babel-helper-define-map/-/babel-helper-define-map-6.26.0.tgz", + "integrity": "sha1-pfVtq0GiX5fstJjH66ypgZ+Vvl8=", + "requires": { + "babel-helper-function-name": "6.24.1", + "babel-runtime": "6.23.0", + "babel-types": "6.25.0", + "lodash": "4.17.4" + } + }, + "babel-helper-explode-assignable-expression": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-helper-explode-assignable-expression/-/babel-helper-explode-assignable-expression-6.24.1.tgz", + "integrity": "sha1-8luCz33BBDPFX3BZLVdGQArCLKo=", + "requires": { + "babel-runtime": "6.23.0", + "babel-traverse": "6.25.0", + "babel-types": "6.25.0" + } + }, + "babel-helper-function-name": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-helper-function-name/-/babel-helper-function-name-6.24.1.tgz", + "integrity": "sha1-00dbjAPtmCQqJbSDUasYOZ01gKk=", + "requires": { + "babel-helper-get-function-arity": "6.24.1", + "babel-runtime": "6.23.0", + "babel-template": "6.25.0", + "babel-traverse": "6.25.0", + "babel-types": "6.25.0" + } + }, + "babel-helper-get-function-arity": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-helper-get-function-arity/-/babel-helper-get-function-arity-6.24.1.tgz", + "integrity": "sha1-j3eCqpNAfEHTqlCQj4mwMbG2hT0=", + "requires": { + "babel-runtime": "6.23.0", + "babel-types": "6.25.0" + } + }, + "babel-helper-hoist-variables": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-helper-hoist-variables/-/babel-helper-hoist-variables-6.24.1.tgz", + "integrity": "sha1-HssnaJydJVE+rbyZFKc/VAi+enY=", + "requires": { + "babel-runtime": "6.23.0", + "babel-types": "6.25.0" + } + }, + "babel-helper-optimise-call-expression": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-helper-optimise-call-expression/-/babel-helper-optimise-call-expression-6.24.1.tgz", + "integrity": "sha1-96E0J7qfc/j0+pk8VKl4gtEkQlc=", + "requires": { + "babel-runtime": "6.23.0", + "babel-types": "6.25.0" + } + }, + "babel-helper-regex": { + "version": "6.26.0", + "resolved": "https://registry.npmjs.org/babel-helper-regex/-/babel-helper-regex-6.26.0.tgz", + "integrity": "sha1-MlxZ+QL4LyS3T6zu0DY5VPZJXnI=", + "requires": { + "babel-runtime": "6.23.0", + "babel-types": "6.25.0", + "lodash": "4.17.4" + } + }, + "babel-helper-remap-async-to-generator": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-helper-remap-async-to-generator/-/babel-helper-remap-async-to-generator-6.24.1.tgz", + "integrity": "sha1-XsWBgnrXI/7N04HxySg5BnbkVRs=", + "requires": { + "babel-helper-function-name": "6.24.1", + "babel-runtime": "6.23.0", + "babel-template": "6.25.0", + "babel-traverse": "6.25.0", + "babel-types": "6.25.0" + } + }, + "babel-helper-replace-supers": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-helper-replace-supers/-/babel-helper-replace-supers-6.24.1.tgz", + "integrity": "sha1-v22/5Dk40XNpohPKiov3S2qQqxo=", + "requires": { + "babel-helper-optimise-call-expression": "6.24.1", + "babel-messages": "6.23.0", + "babel-runtime": "6.23.0", + "babel-template": "6.25.0", + "babel-traverse": "6.25.0", + "babel-types": "6.25.0" + } }, "babel-helpers": { "version": "6.24.1", "resolved": "https://registry.npmjs.org/babel-helpers/-/babel-helpers-6.24.1.tgz", "integrity": "sha1-NHHenK7DiOXIUOWX5Yom3fN2ArI=", - "dev": true + "requires": { + "babel-runtime": "6.23.0", + "babel-template": "6.25.0" + } }, "babel-jest": { "version": "19.0.0", "resolved": "https://registry.npmjs.org/babel-jest/-/babel-jest-19.0.0.tgz", "integrity": "sha1-WTI87ZmjqE01naIZyogQdP/Gzj8=", - "dev": true + "dev": true, + "requires": { + "babel-core": "6.25.0", + "babel-plugin-istanbul": "4.1.4", + "babel-preset-jest": "19.0.0" + } }, "babel-messages": { "version": "6.23.0", "resolved": "https://registry.npmjs.org/babel-messages/-/babel-messages-6.23.0.tgz", "integrity": "sha1-8830cDhYA1sqKVHG7F7fbGLyYw4=", - "dev": true + "requires": { + "babel-runtime": "6.23.0" + } + }, + "babel-plugin-check-es2015-constants": { + "version": "6.22.0", + "resolved": "https://registry.npmjs.org/babel-plugin-check-es2015-constants/-/babel-plugin-check-es2015-constants-6.22.0.tgz", + "integrity": "sha1-NRV7EBQm/S/9PaP3XH0ekYNbv4o=", + "requires": { + "babel-runtime": "6.23.0" + } + }, + "babel-plugin-external-helpers": { + "version": "6.22.0", + "resolved": "https://registry.npmjs.org/babel-plugin-external-helpers/-/babel-plugin-external-helpers-6.22.0.tgz", + "integrity": "sha1-IoX0iwK9Xe3oUXXK+MYuhq3M76E=", + "requires": { + "babel-runtime": "6.23.0" + } }, "babel-plugin-istanbul": { "version": "4.1.4", "resolved": "https://registry.npmjs.org/babel-plugin-istanbul/-/babel-plugin-istanbul-4.1.4.tgz", "integrity": "sha1-GN3oS/POMp/d8/QQP66SFFbY5Yc=", - "dev": true + "dev": true, + "requires": { + "find-up": "2.1.0", + "istanbul-lib-instrument": "1.7.2", + "test-exclude": "4.1.1" + } }, "babel-plugin-jest-hoist": { "version": "19.0.0", @@ -266,90 +758,704 @@ "integrity": "sha1-SuKgTqYSpuc2UfP95SwXiZEwS+o=", "dev": true }, - "babel-preset-jest": { - "version": "19.0.0", - "resolved": "https://registry.npmjs.org/babel-preset-jest/-/babel-preset-jest-19.0.0.tgz", - "integrity": "sha1-ItZyAdAjJKGVgRKI6zgpS7PKw5Y=", - "dev": true + "babel-plugin-module-resolver": { + "version": "2.7.1", + "resolved": "https://registry.npmjs.org/babel-plugin-module-resolver/-/babel-plugin-module-resolver-2.7.1.tgz", + "integrity": "sha1-GL48Qt31n3pFbJ4FEs2ROU9uS+E=", + "requires": { + "find-babel-config": "1.1.0", + "glob": "7.1.2", + "resolve": "1.5.0" + } }, - "babel-register": { - "version": "6.24.1", - "resolved": "https://registry.npmjs.org/babel-register/-/babel-register-6.24.1.tgz", - "integrity": "sha1-fhDhOi9xBlvfrVoXh7pFvKbe118=", - "dev": true + "babel-plugin-react-transform": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/babel-plugin-react-transform/-/babel-plugin-react-transform-2.0.2.tgz", + "integrity": "sha1-UVu/qZaJOYEULZCx+bFjXeKZUQk=", + "requires": { + "lodash": "4.17.4" + } }, - "babel-runtime": { - "version": "6.23.0", - "resolved": "https://registry.npmjs.org/babel-runtime/-/babel-runtime-6.23.0.tgz", - "integrity": "sha1-CpSJ8UTecO+zzkMArM2zKeL8VDs=", - "dev": true + "babel-plugin-syntax-async-functions": { + "version": "6.13.0", + "resolved": "https://registry.npmjs.org/babel-plugin-syntax-async-functions/-/babel-plugin-syntax-async-functions-6.13.0.tgz", + "integrity": "sha1-ytnK0RkbWtY0vzCuCHI5HgZHvpU=" + }, + "babel-plugin-syntax-class-constructor-call": { + "version": "6.18.0", + "resolved": "https://registry.npmjs.org/babel-plugin-syntax-class-constructor-call/-/babel-plugin-syntax-class-constructor-call-6.18.0.tgz", + "integrity": "sha1-nLnTn+Q8hgC+yBRkVt3L1OGnZBY=" + }, + "babel-plugin-syntax-class-properties": { + "version": "6.13.0", + "resolved": "https://registry.npmjs.org/babel-plugin-syntax-class-properties/-/babel-plugin-syntax-class-properties-6.13.0.tgz", + "integrity": "sha1-1+sjt5oxf4VDlixQW4J8fWysJ94=" + }, + "babel-plugin-syntax-decorators": { + "version": "6.13.0", + "resolved": "https://registry.npmjs.org/babel-plugin-syntax-decorators/-/babel-plugin-syntax-decorators-6.13.0.tgz", + "integrity": "sha1-MSVjtNvePMgGzuPkFszurd0RrAs=" + }, + "babel-plugin-syntax-do-expressions": { + "version": "6.13.0", + "resolved": "https://registry.npmjs.org/babel-plugin-syntax-do-expressions/-/babel-plugin-syntax-do-expressions-6.13.0.tgz", + "integrity": "sha1-V0d1YTmqJtOQ0JQQsDdEugfkeW0=" + }, + "babel-plugin-syntax-exponentiation-operator": { + "version": "6.13.0", + "resolved": "https://registry.npmjs.org/babel-plugin-syntax-exponentiation-operator/-/babel-plugin-syntax-exponentiation-operator-6.13.0.tgz", + "integrity": "sha1-nufoM3KQ2pUoggGmpX9BcDF4MN4=" + }, + "babel-plugin-syntax-export-extensions": { + "version": "6.13.0", + "resolved": "https://registry.npmjs.org/babel-plugin-syntax-export-extensions/-/babel-plugin-syntax-export-extensions-6.13.0.tgz", + "integrity": "sha1-cKFITw+QiaToStRLrDU8lbmxJyE=" + }, + "babel-plugin-syntax-flow": { + "version": "6.18.0", + "resolved": "https://registry.npmjs.org/babel-plugin-syntax-flow/-/babel-plugin-syntax-flow-6.18.0.tgz", + "integrity": "sha1-TDqyCiryaqIM0lmVw5jE63AxDI0=" + }, + "babel-plugin-syntax-function-bind": { + "version": "6.13.0", + "resolved": "https://registry.npmjs.org/babel-plugin-syntax-function-bind/-/babel-plugin-syntax-function-bind-6.13.0.tgz", + "integrity": "sha1-SMSV8Xe98xqYHnMvVa3AvdJgH0Y=" + }, + "babel-plugin-syntax-jsx": { + "version": "6.18.0", + "resolved": "https://registry.npmjs.org/babel-plugin-syntax-jsx/-/babel-plugin-syntax-jsx-6.18.0.tgz", + "integrity": "sha1-CvMqmm4Tyno/1QaeYtew9Y0NiUY=" + }, + "babel-plugin-syntax-object-rest-spread": { + "version": "6.13.0", + "resolved": "https://registry.npmjs.org/babel-plugin-syntax-object-rest-spread/-/babel-plugin-syntax-object-rest-spread-6.13.0.tgz", + "integrity": "sha1-/WU28rzhODb/o6VFjEkDpZe7O/U=" + }, + "babel-plugin-syntax-trailing-function-commas": { + "version": "6.22.0", + "resolved": "https://registry.npmjs.org/babel-plugin-syntax-trailing-function-commas/-/babel-plugin-syntax-trailing-function-commas-6.22.0.tgz", + "integrity": "sha1-ugNgk3+NBuQBgKQ/4NVhb/9TLPM=" + }, + "babel-plugin-transform-async-to-generator": { + "version": "6.16.0", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-async-to-generator/-/babel-plugin-transform-async-to-generator-6.16.0.tgz", + "integrity": "sha1-Gew2yxSGtZ+fRorfpCzhOQjKKZk=", + "requires": { + "babel-helper-remap-async-to-generator": "6.24.1", + "babel-plugin-syntax-async-functions": "6.13.0", + "babel-runtime": "6.23.0" + } }, - "babel-template": { - "version": "6.25.0", - "resolved": "https://registry.npmjs.org/babel-template/-/babel-template-6.25.0.tgz", - "integrity": "sha1-ZlJBFmt8KqTGGdceGSlpVSsQwHE=", - "dev": true + "babel-plugin-transform-class-constructor-call": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-class-constructor-call/-/babel-plugin-transform-class-constructor-call-6.24.1.tgz", + "integrity": "sha1-gNwoVQWsBn3LjWxl4vbxGrd2Xvk=", + "requires": { + "babel-plugin-syntax-class-constructor-call": "6.18.0", + "babel-runtime": "6.23.0", + "babel-template": "6.25.0" + } }, - "babel-traverse": { - "version": "6.25.0", - "resolved": "https://registry.npmjs.org/babel-traverse/-/babel-traverse-6.25.0.tgz", - "integrity": "sha1-IldJfi/NGbie3BPEyROB+VEklvE=", - "dev": true + "babel-plugin-transform-class-properties": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-class-properties/-/babel-plugin-transform-class-properties-6.24.1.tgz", + "integrity": "sha1-anl2PqYdM9NvN7YRqp3vgagbRqw=", + "requires": { + "babel-helper-function-name": "6.24.1", + "babel-plugin-syntax-class-properties": "6.13.0", + "babel-runtime": "6.23.0", + "babel-template": "6.25.0" + } }, - "babel-types": { - "version": "6.25.0", - "resolved": "https://registry.npmjs.org/babel-types/-/babel-types-6.25.0.tgz", - "integrity": "sha1-cK+ySNVmDl0Y+BHZHIMDtUE0oY4=", - "dev": true + "babel-plugin-transform-decorators-legacy": { + "version": "1.3.4", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-decorators-legacy/-/babel-plugin-transform-decorators-legacy-1.3.4.tgz", + "integrity": "sha1-dBtY9sW86eYCfgiC2cmU8E82aSU=", + "requires": { + "babel-plugin-syntax-decorators": "6.13.0", + "babel-runtime": "6.23.0", + "babel-template": "6.25.0" + } }, - "babylon": { - "version": "6.17.3", - "resolved": "https://registry.npmjs.org/babylon/-/babylon-6.17.3.tgz", - "integrity": "sha512-mq0x3HCAGGmQyZXviOVe5TRsw37Ijy3D43jCqt/9WVf+onx2dUgW3PosnqCbScAFhRO9DGs8nxoMzU0iiosMqQ==", - "dev": true + "babel-plugin-transform-do-expressions": { + "version": "6.22.0", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-do-expressions/-/babel-plugin-transform-do-expressions-6.22.0.tgz", + "integrity": "sha1-KMyvkoEtlJws0SgfaQyP3EaK6bs=", + "requires": { + "babel-plugin-syntax-do-expressions": "6.13.0", + "babel-runtime": "6.23.0" + } }, - "balanced-match": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz", - "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=", - "dev": true + "babel-plugin-transform-es2015-arrow-functions": { + "version": "6.22.0", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-arrow-functions/-/babel-plugin-transform-es2015-arrow-functions-6.22.0.tgz", + "integrity": "sha1-RSaSy3EdX3ncf4XkQM5BufJE0iE=", + "requires": { + "babel-runtime": "6.23.0" + } }, - "base-64": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/base-64/-/base-64-0.1.0.tgz", - "integrity": "sha1-eAqZyE59YAJgNhURxId2E78k9rs=", - "dev": true + "babel-plugin-transform-es2015-block-scoped-functions": { + "version": "6.22.0", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-block-scoped-functions/-/babel-plugin-transform-es2015-block-scoped-functions-6.22.0.tgz", + "integrity": "sha1-u8UbSflk1wy42OC5ToICRs46YUE=", + "requires": { + "babel-runtime": "6.23.0" + } }, - "Base64": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/Base64/-/Base64-0.1.4.tgz", - "integrity": "sha1-6fbGvvVn/WNepBYqsU3TKedKpt4=", - "dev": true + "babel-plugin-transform-es2015-block-scoping": { + "version": "6.26.0", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-block-scoping/-/babel-plugin-transform-es2015-block-scoping-6.26.0.tgz", + "integrity": "sha1-1w9SmcEwjQXBL0Y4E7CgnnOxiV8=", + "requires": { + "babel-runtime": "6.23.0", + "babel-template": "6.25.0", + "babel-traverse": "6.25.0", + "babel-types": "6.25.0", + "lodash": "4.17.4" + } }, - "base64url": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/base64url/-/base64url-2.0.0.tgz", - "integrity": "sha1-6sFuA+oUOO/5Qj1puqNiYu0fcLs=", - "dev": true + "babel-plugin-transform-es2015-classes": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-classes/-/babel-plugin-transform-es2015-classes-6.24.1.tgz", + "integrity": "sha1-WkxYpQyclGHlZLSyo7+ryXolhNs=", + "requires": { + "babel-helper-define-map": "6.26.0", + "babel-helper-function-name": "6.24.1", + "babel-helper-optimise-call-expression": "6.24.1", + "babel-helper-replace-supers": "6.24.1", + "babel-messages": "6.23.0", + "babel-runtime": "6.23.0", + "babel-template": "6.25.0", + "babel-traverse": "6.25.0", + "babel-types": "6.25.0" + } }, - "bcrypt-pbkdf": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.1.tgz", - "integrity": "sha1-Y7xdy2EzG5K8Bf1SiVPDNGKgb40=", - "dev": true, - "optional": true + "babel-plugin-transform-es2015-computed-properties": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-computed-properties/-/babel-plugin-transform-es2015-computed-properties-6.24.1.tgz", + "integrity": "sha1-b+Ko0WiV1WNPTNmZttNICjCBWbM=", + "requires": { + "babel-runtime": "6.23.0", + "babel-template": "6.25.0" + } }, - "binary": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/binary/-/binary-0.3.0.tgz", - "integrity": "sha1-n2BVO8XOjDOG87VTz/R0Yq3sqnk=", - "dev": true + "babel-plugin-transform-es2015-destructuring": { + "version": "6.23.0", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-destructuring/-/babel-plugin-transform-es2015-destructuring-6.23.0.tgz", + "integrity": "sha1-mXux8auWf2gtKwh2/jWNYOdlxW0=", + "requires": { + "babel-runtime": "6.23.0" + } }, - "block-stream": { + "babel-plugin-transform-es2015-for-of": { + "version": "6.23.0", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-for-of/-/babel-plugin-transform-es2015-for-of-6.23.0.tgz", + "integrity": "sha1-9HyVsrYT3x0+zC/bdXNiPHUkhpE=", + "requires": { + "babel-runtime": "6.23.0" + } + }, + "babel-plugin-transform-es2015-function-name": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-function-name/-/babel-plugin-transform-es2015-function-name-6.24.1.tgz", + "integrity": "sha1-g0yJhTvDaxrw86TF26qU/Y6sqos=", + "requires": { + "babel-helper-function-name": "6.24.1", + "babel-runtime": "6.23.0", + "babel-types": "6.25.0" + } + }, + "babel-plugin-transform-es2015-literals": { + "version": "6.22.0", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-literals/-/babel-plugin-transform-es2015-literals-6.22.0.tgz", + "integrity": "sha1-T1SgLWzWbPkVKAAZox0xklN3yi4=", + "requires": { + "babel-runtime": "6.23.0" + } + }, + "babel-plugin-transform-es2015-modules-commonjs": { + "version": "6.26.0", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-modules-commonjs/-/babel-plugin-transform-es2015-modules-commonjs-6.26.0.tgz", + "integrity": "sha1-DYOUApt9xqvhqX7xgeAHWN0uXYo=", + "requires": { + "babel-plugin-transform-strict-mode": "6.24.1", + "babel-runtime": "6.23.0", + "babel-template": "6.25.0", + "babel-types": "6.25.0" + } + }, + "babel-plugin-transform-es2015-object-super": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-object-super/-/babel-plugin-transform-es2015-object-super-6.24.1.tgz", + "integrity": "sha1-JM72muIcuDp/hgPa0CH1cusnj40=", + "requires": { + "babel-helper-replace-supers": "6.24.1", + "babel-runtime": "6.23.0" + } + }, + "babel-plugin-transform-es2015-parameters": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-parameters/-/babel-plugin-transform-es2015-parameters-6.24.1.tgz", + "integrity": "sha1-V6w1GrScrxSpfNE7CfZv3wpiXys=", + "requires": { + "babel-helper-call-delegate": "6.24.1", + "babel-helper-get-function-arity": "6.24.1", + "babel-runtime": "6.23.0", + "babel-template": "6.25.0", + "babel-traverse": "6.25.0", + "babel-types": "6.25.0" + } + }, + "babel-plugin-transform-es2015-shorthand-properties": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-shorthand-properties/-/babel-plugin-transform-es2015-shorthand-properties-6.24.1.tgz", + "integrity": "sha1-JPh11nIch2YbvZmkYi5R8U3jiqA=", + "requires": { + "babel-runtime": "6.23.0", + "babel-types": "6.25.0" + } + }, + "babel-plugin-transform-es2015-spread": { + "version": "6.22.0", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-spread/-/babel-plugin-transform-es2015-spread-6.22.0.tgz", + "integrity": "sha1-1taKmfia7cRTbIGlQujdnxdG+NE=", + "requires": { + "babel-runtime": "6.23.0" + } + }, + "babel-plugin-transform-es2015-sticky-regex": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-sticky-regex/-/babel-plugin-transform-es2015-sticky-regex-6.24.1.tgz", + "integrity": "sha1-AMHNsaynERLN8M9hJsLta0V8zbw=", + "requires": { + "babel-helper-regex": "6.26.0", + "babel-runtime": "6.23.0", + "babel-types": "6.25.0" + } + }, + "babel-plugin-transform-es2015-template-literals": { + "version": "6.22.0", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-template-literals/-/babel-plugin-transform-es2015-template-literals-6.22.0.tgz", + "integrity": "sha1-qEs0UPfp+PH2g51taH2oS7EjbY0=", + "requires": { + "babel-runtime": "6.23.0" + } + }, + "babel-plugin-transform-es2015-unicode-regex": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-unicode-regex/-/babel-plugin-transform-es2015-unicode-regex-6.24.1.tgz", + "integrity": "sha1-04sS9C6nMj9yk4fxinxa4frrNek=", + "requires": { + "babel-helper-regex": "6.26.0", + "babel-runtime": "6.23.0", + "regexpu-core": "2.0.0" + } + }, + "babel-plugin-transform-es3-member-expression-literals": { + "version": "6.22.0", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-es3-member-expression-literals/-/babel-plugin-transform-es3-member-expression-literals-6.22.0.tgz", + "integrity": "sha1-cz00RPPsxBvvjtGmpOCWV7iWnrs=", + "requires": { + "babel-runtime": "6.23.0" + } + }, + "babel-plugin-transform-es3-property-literals": { + "version": "6.22.0", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-es3-property-literals/-/babel-plugin-transform-es3-property-literals-6.22.0.tgz", + "integrity": "sha1-sgeNWELiKr9A9z6M3pzTcRq9V1g=", + "requires": { + "babel-runtime": "6.23.0" + } + }, + "babel-plugin-transform-exponentiation-operator": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-exponentiation-operator/-/babel-plugin-transform-exponentiation-operator-6.24.1.tgz", + "integrity": "sha1-KrDJx/MJj6SJB3cruBP+QejeOg4=", + "requires": { + "babel-helper-builder-binary-assignment-operator-visitor": "6.24.1", + "babel-plugin-syntax-exponentiation-operator": "6.13.0", + "babel-runtime": "6.23.0" + } + }, + "babel-plugin-transform-export-extensions": { + "version": "6.22.0", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-export-extensions/-/babel-plugin-transform-export-extensions-6.22.0.tgz", + "integrity": "sha1-U3OLR+deghhYnuqUbLvTkQm75lM=", + "requires": { + "babel-plugin-syntax-export-extensions": "6.13.0", + "babel-runtime": "6.23.0" + } + }, + "babel-plugin-transform-flow-strip-types": { + "version": "6.22.0", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-flow-strip-types/-/babel-plugin-transform-flow-strip-types-6.22.0.tgz", + "integrity": "sha1-hMtnKTXUNxT9wyvOhFaNh0Qc988=", + "requires": { + "babel-plugin-syntax-flow": "6.18.0", + "babel-runtime": "6.23.0" + } + }, + "babel-plugin-transform-function-bind": { + "version": "6.22.0", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-function-bind/-/babel-plugin-transform-function-bind-6.22.0.tgz", + "integrity": "sha1-xvuOlqwpajELjPjqQBRiQH3fapc=", + "requires": { + "babel-plugin-syntax-function-bind": "6.13.0", + "babel-runtime": "6.23.0" + } + }, + "babel-plugin-transform-object-assign": { + "version": "6.22.0", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-object-assign/-/babel-plugin-transform-object-assign-6.22.0.tgz", + "integrity": "sha1-+Z0vZvGgsNSY40bFNZaEdAyqILo=", + "requires": { + "babel-runtime": "6.23.0" + } + }, + "babel-plugin-transform-object-rest-spread": { + "version": "6.26.0", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-object-rest-spread/-/babel-plugin-transform-object-rest-spread-6.26.0.tgz", + "integrity": "sha1-DzZpLVD+9rfi1LOsFHgTepY7ewY=", + "requires": { + "babel-plugin-syntax-object-rest-spread": "6.13.0", + "babel-runtime": "6.23.0" + } + }, + "babel-plugin-transform-react-display-name": { + "version": "6.25.0", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-react-display-name/-/babel-plugin-transform-react-display-name-6.25.0.tgz", + "integrity": "sha1-Z+K/Hx6ck6sI25Z5LgU5K/LMKNE=", + "requires": { + "babel-runtime": "6.23.0" + } + }, + "babel-plugin-transform-react-jsx": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-react-jsx/-/babel-plugin-transform-react-jsx-6.24.1.tgz", + "integrity": "sha1-hAoCjn30YN/DotKfDA2R9jduZqM=", + "requires": { + "babel-helper-builder-react-jsx": "6.26.0", + "babel-plugin-syntax-jsx": "6.18.0", + "babel-runtime": "6.23.0" + } + }, + "babel-plugin-transform-react-jsx-source": { + "version": "6.22.0", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-react-jsx-source/-/babel-plugin-transform-react-jsx-source-6.22.0.tgz", + "integrity": "sha1-ZqwSFT9c0tF7PBkmj0vwGX9E7NY=", + "requires": { + "babel-plugin-syntax-jsx": "6.18.0", + "babel-runtime": "6.23.0" + } + }, + "babel-plugin-transform-regenerator": { + "version": "6.26.0", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-regenerator/-/babel-plugin-transform-regenerator-6.26.0.tgz", + "integrity": "sha1-4HA2lvveJ/Cj78rPi03KL3s6jy8=", + "requires": { + "regenerator-transform": "0.10.1" + } + }, + "babel-plugin-transform-strict-mode": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-strict-mode/-/babel-plugin-transform-strict-mode-6.24.1.tgz", + "integrity": "sha1-1fr3qleKZbvlkc9e2uBKDGcCB1g=", + "requires": { + "babel-runtime": "6.23.0", + "babel-types": "6.25.0" + } + }, + "babel-polyfill": { + "version": "6.26.0", + "resolved": "https://registry.npmjs.org/babel-polyfill/-/babel-polyfill-6.26.0.tgz", + "integrity": "sha1-N5k3q8Z9eJWXCtxiHyhM2WbPIVM=", + "requires": { + "babel-runtime": "6.23.0", + "core-js": "2.4.1", + "regenerator-runtime": "0.10.5" + } + }, + "babel-preset-es2015-node": { + "version": "6.1.1", + "resolved": "https://registry.npmjs.org/babel-preset-es2015-node/-/babel-preset-es2015-node-6.1.1.tgz", + "integrity": "sha1-YLIxVwJLDP6/OmNVTLBe4DW05V8=", + "requires": { + "babel-plugin-transform-es2015-destructuring": "6.23.0", + "babel-plugin-transform-es2015-function-name": "6.24.1", + "babel-plugin-transform-es2015-modules-commonjs": "6.26.0", + "babel-plugin-transform-es2015-parameters": "6.24.1", + "babel-plugin-transform-es2015-shorthand-properties": "6.24.1", + "babel-plugin-transform-es2015-spread": "6.22.0", + "babel-plugin-transform-es2015-sticky-regex": "6.24.1", + "babel-plugin-transform-es2015-unicode-regex": "6.24.1", + "semver": "5.3.0" + } + }, + "babel-preset-expo": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/babel-preset-expo/-/babel-preset-expo-2.0.0.tgz", + "integrity": "sha1-ijTTT+W2IcihUryfwGVn/ycNMUs=", + "requires": { + "babel-plugin-module-resolver": "2.5.0", + "babel-plugin-transform-decorators-legacy": "1.3.4", + "babel-preset-react-native-stage-0": "1.0.1" + }, + "dependencies": { + "babel-plugin-module-resolver": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/babel-plugin-module-resolver/-/babel-plugin-module-resolver-2.5.0.tgz", + "integrity": "sha1-oSBLSuraBm6K+5ufnEPiONc9Qbs=", + "requires": { + "find-babel-config": "1.1.0", + "glob": "7.1.2", + "resolve": "1.5.0" + } + } + } + }, + "babel-preset-fbjs": { + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/babel-preset-fbjs/-/babel-preset-fbjs-2.1.4.tgz", + "integrity": "sha512-6XVQwlO26V5/0P9s2Eje8Epqkv/ihaMJ798+W98ktOA8fCn2IFM6wEi7CDW3fTbKFZ/8fDGvGZH01B6GSuNiWA==", + "requires": { + "babel-plugin-check-es2015-constants": "6.22.0", + "babel-plugin-syntax-class-properties": "6.13.0", + "babel-plugin-syntax-flow": "6.18.0", + "babel-plugin-syntax-jsx": "6.18.0", + "babel-plugin-syntax-object-rest-spread": "6.13.0", + "babel-plugin-syntax-trailing-function-commas": "6.22.0", + "babel-plugin-transform-class-properties": "6.24.1", + "babel-plugin-transform-es2015-arrow-functions": "6.22.0", + "babel-plugin-transform-es2015-block-scoped-functions": "6.22.0", + "babel-plugin-transform-es2015-block-scoping": "6.26.0", + "babel-plugin-transform-es2015-classes": "6.24.1", + "babel-plugin-transform-es2015-computed-properties": "6.24.1", + "babel-plugin-transform-es2015-destructuring": "6.23.0", + "babel-plugin-transform-es2015-for-of": "6.23.0", + "babel-plugin-transform-es2015-function-name": "6.24.1", + "babel-plugin-transform-es2015-literals": "6.22.0", + "babel-plugin-transform-es2015-modules-commonjs": "6.26.0", + "babel-plugin-transform-es2015-object-super": "6.24.1", + "babel-plugin-transform-es2015-parameters": "6.24.1", + "babel-plugin-transform-es2015-shorthand-properties": "6.24.1", + "babel-plugin-transform-es2015-spread": "6.22.0", + "babel-plugin-transform-es2015-template-literals": "6.22.0", + "babel-plugin-transform-es3-member-expression-literals": "6.22.0", + "babel-plugin-transform-es3-property-literals": "6.22.0", + "babel-plugin-transform-flow-strip-types": "6.22.0", + "babel-plugin-transform-object-rest-spread": "6.26.0", + "babel-plugin-transform-react-display-name": "6.25.0", + "babel-plugin-transform-react-jsx": "6.24.1" + } + }, + "babel-preset-jest": { + "version": "19.0.0", + "resolved": "https://registry.npmjs.org/babel-preset-jest/-/babel-preset-jest-19.0.0.tgz", + "integrity": "sha1-ItZyAdAjJKGVgRKI6zgpS7PKw5Y=", + "dev": true, + "requires": { + "babel-plugin-jest-hoist": "19.0.0" + } + }, + "babel-preset-react-native": { + "version": "1.9.2", + "resolved": "https://registry.npmjs.org/babel-preset-react-native/-/babel-preset-react-native-1.9.2.tgz", + "integrity": "sha1-sird0uNV/zs5Zxt5voB+Ut+hRfI=", + "requires": { + "babel-plugin-check-es2015-constants": "6.22.0", + "babel-plugin-react-transform": "2.0.2", + "babel-plugin-syntax-async-functions": "6.13.0", + "babel-plugin-syntax-class-properties": "6.13.0", + "babel-plugin-syntax-flow": "6.18.0", + "babel-plugin-syntax-jsx": "6.18.0", + "babel-plugin-syntax-trailing-function-commas": "6.22.0", + "babel-plugin-transform-class-properties": "6.24.1", + "babel-plugin-transform-es2015-arrow-functions": "6.22.0", + "babel-plugin-transform-es2015-block-scoping": "6.26.0", + "babel-plugin-transform-es2015-classes": "6.24.1", + "babel-plugin-transform-es2015-computed-properties": "6.24.1", + "babel-plugin-transform-es2015-destructuring": "6.23.0", + "babel-plugin-transform-es2015-for-of": "6.23.0", + "babel-plugin-transform-es2015-function-name": "6.24.1", + "babel-plugin-transform-es2015-literals": "6.22.0", + "babel-plugin-transform-es2015-modules-commonjs": "6.26.0", + "babel-plugin-transform-es2015-parameters": "6.24.1", + "babel-plugin-transform-es2015-shorthand-properties": "6.24.1", + "babel-plugin-transform-es2015-spread": "6.22.0", + "babel-plugin-transform-es2015-template-literals": "6.22.0", + "babel-plugin-transform-flow-strip-types": "6.22.0", + "babel-plugin-transform-object-assign": "6.22.0", + "babel-plugin-transform-object-rest-spread": "6.26.0", + "babel-plugin-transform-react-display-name": "6.25.0", + "babel-plugin-transform-react-jsx": "6.24.1", + "babel-plugin-transform-react-jsx-source": "6.22.0", + "babel-plugin-transform-regenerator": "6.26.0", + "react-transform-hmr": "1.0.4" + } + }, + "babel-preset-react-native-stage-0": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/babel-preset-react-native-stage-0/-/babel-preset-react-native-stage-0-1.0.1.tgz", + "integrity": "sha1-1fX2hVdUce91aknxkbGTJp90MG4=", + "requires": { + "babel-plugin-syntax-trailing-function-commas": "6.22.0", + "babel-plugin-transform-class-constructor-call": "6.24.1", + "babel-plugin-transform-decorators-legacy": "1.3.4", + "babel-plugin-transform-do-expressions": "6.22.0", + "babel-plugin-transform-exponentiation-operator": "6.24.1", + "babel-plugin-transform-export-extensions": "6.22.0", + "babel-plugin-transform-function-bind": "6.22.0", + "babel-preset-react-native": "1.9.2" + } + }, + "babel-register": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-register/-/babel-register-6.24.1.tgz", + "integrity": "sha1-fhDhOi9xBlvfrVoXh7pFvKbe118=", + "requires": { + "babel-core": "6.25.0", + "babel-runtime": "6.23.0", + "core-js": "2.4.1", + "home-or-tmp": "2.0.0", + "lodash": "4.17.4", + "mkdirp": "0.5.1", + "source-map-support": "0.4.15" + } + }, + "babel-runtime": { + "version": "6.23.0", + "resolved": "https://registry.npmjs.org/babel-runtime/-/babel-runtime-6.23.0.tgz", + "integrity": "sha1-CpSJ8UTecO+zzkMArM2zKeL8VDs=", + "requires": { + "core-js": "2.4.1", + "regenerator-runtime": "0.10.5" + } + }, + "babel-template": { + "version": "6.25.0", + "resolved": "https://registry.npmjs.org/babel-template/-/babel-template-6.25.0.tgz", + "integrity": "sha1-ZlJBFmt8KqTGGdceGSlpVSsQwHE=", + "requires": { + "babel-runtime": "6.23.0", + "babel-traverse": "6.25.0", + "babel-types": "6.25.0", + "babylon": "6.17.3", + "lodash": "4.17.4" + } + }, + "babel-traverse": { + "version": "6.25.0", + "resolved": "https://registry.npmjs.org/babel-traverse/-/babel-traverse-6.25.0.tgz", + "integrity": "sha1-IldJfi/NGbie3BPEyROB+VEklvE=", + "requires": { + "babel-code-frame": "6.22.0", + "babel-messages": "6.23.0", + "babel-runtime": "6.23.0", + "babel-types": "6.25.0", + "babylon": "6.17.3", + "debug": "2.6.8", + "globals": "9.18.0", + "invariant": "2.2.2", + "lodash": "4.17.4" + } + }, + "babel-types": { + "version": "6.25.0", + "resolved": "https://registry.npmjs.org/babel-types/-/babel-types-6.25.0.tgz", + "integrity": "sha1-cK+ySNVmDl0Y+BHZHIMDtUE0oY4=", + "requires": { + "babel-runtime": "6.23.0", + "esutils": "2.0.2", + "lodash": "4.17.4", + "to-fast-properties": "1.0.3" + } + }, + "babylon": { + "version": "6.17.3", + "resolved": "https://registry.npmjs.org/babylon/-/babylon-6.17.3.tgz", + "integrity": "sha512-mq0x3HCAGGmQyZXviOVe5TRsw37Ijy3D43jCqt/9WVf+onx2dUgW3PosnqCbScAFhRO9DGs8nxoMzU0iiosMqQ==" + }, + "balanced-match": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz", + "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=" + }, + "base-64": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/base-64/-/base-64-0.1.0.tgz", + "integrity": "sha1-eAqZyE59YAJgNhURxId2E78k9rs=" + }, + "base64-js": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.2.3.tgz", + "integrity": "sha512-MsAhsUW1GxCdgYSO6tAfZrNapmUKk7mWx/k5mFY/A1gBtkaCaNapTg+FExCw1r9yeaZhqx/xPg43xgTFH6KL5w==" + }, + "base64-url": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/base64-url/-/base64-url-1.2.1.tgz", + "integrity": "sha1-GZ/WYXAqDnt9yubgaYuwicUvbXg=" + }, + "base64url": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/base64url/-/base64url-2.0.0.tgz", + "integrity": "sha1-6sFuA+oUOO/5Qj1puqNiYu0fcLs=", + "dev": true + }, + "basic-auth": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/basic-auth/-/basic-auth-2.0.0.tgz", + "integrity": "sha1-AV2z81PgLlY3d1X5YnQuiYHnu7o=", + "requires": { + "safe-buffer": "5.1.0" + } + }, + "basic-auth-connect": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/basic-auth-connect/-/basic-auth-connect-1.0.0.tgz", + "integrity": "sha1-/bC0OWLKe0BFanwrtI/hc9otISI=" + }, + "batch": { + "version": "0.5.3", + "resolved": "https://registry.npmjs.org/batch/-/batch-0.5.3.tgz", + "integrity": "sha1-PzQU84AyF0O/wQQvmoP/HVgk1GQ=" + }, + "bcrypt-pbkdf": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.1.tgz", + "integrity": "sha1-Y7xdy2EzG5K8Bf1SiVPDNGKgb40=", + "optional": true, + "requires": { + "tweetnacl": "0.14.5" + } + }, + "beeper": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/beeper/-/beeper-1.1.1.tgz", + "integrity": "sha1-5tXqjF2tABMEpwsiY4RH9pyy+Ak=" + }, + "big-integer": { + "version": "1.6.26", + "resolved": "https://registry.npmjs.org/big-integer/-/big-integer-1.6.26.tgz", + "integrity": "sha1-OvFnL6Ytry1eyvrPblqg0l4Cwcg=" + }, + "binary": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/binary/-/binary-0.3.0.tgz", + "integrity": "sha1-n2BVO8XOjDOG87VTz/R0Yq3sqnk=", + "dev": true, + "requires": { + "buffers": "0.1.1", + "chainsaw": "0.1.0" + } + }, + "block-stream": { "version": "0.0.9", "resolved": "https://registry.npmjs.org/block-stream/-/block-stream-0.0.9.tgz", "integrity": "sha1-E+v+d4oDIFz+A3UUgeu0szAMEmo=", - "dev": true + "dev": true, + "requires": { + "inherits": "2.0.3" + } }, "bluebird": { "version": "3.5.0", @@ -361,39 +1467,127 @@ "version": "1.17.2", "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.17.2.tgz", "integrity": "sha1-+IkqvI+eYn1Crtr7yma/WrmRBO4=", - "dev": true, + "requires": { + "bytes": "2.4.0", + "content-type": "1.0.2", + "debug": "2.6.7", + "depd": "1.1.0", + "http-errors": "1.6.1", + "iconv-lite": "0.4.15", + "on-finished": "2.3.0", + "qs": "6.4.0", + "raw-body": "2.2.0", + "type-is": "1.6.15" + }, "dependencies": { "debug": { "version": "2.6.7", "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.7.tgz", "integrity": "sha1-krrR9tBbu2u6Isyoi80OyJTChh4=", - "dev": true + "requires": { + "ms": "2.0.0" + } }, "iconv-lite": { "version": "0.4.15", "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.15.tgz", - "integrity": "sha1-/iZaIYrGpXz+hUkn6dBMGYJe3es=", - "dev": true + "integrity": "sha1-/iZaIYrGpXz+hUkn6dBMGYJe3es=" } } }, + "boolbase": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/boolbase/-/boolbase-1.0.0.tgz", + "integrity": "sha1-aN/1++YMUes3cl6p4+0xDcwed24=", + "dev": true + }, "boom": { "version": "2.10.1", "resolved": "https://registry.npmjs.org/boom/-/boom-2.10.1.tgz", "integrity": "sha1-OciRjO/1eZ+D+UkqhI9iWt0Mdm8=", - "dev": true + "requires": { + "hoek": "2.16.3" + } + }, + "boxen": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/boxen/-/boxen-0.6.0.tgz", + "integrity": "sha1-g2TUJIrDT/DvGy8r9JpsYM4NgbY=", + "requires": { + "ansi-align": "1.1.0", + "camelcase": "2.1.1", + "chalk": "1.1.3", + "cli-boxes": "1.0.0", + "filled-array": "1.1.0", + "object-assign": "4.1.1", + "repeating": "2.0.1", + "string-width": "1.0.2", + "widest-line": "1.0.0" + }, + "dependencies": { + "camelcase": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-2.1.1.tgz", + "integrity": "sha1-fB0W1nmhu+WcoCys7PsBHiAfWh8=" + } + } + }, + "bplist-creator": { + "version": "0.0.7", + "resolved": "https://registry.npmjs.org/bplist-creator/-/bplist-creator-0.0.7.tgz", + "integrity": "sha1-N98VNgkoJLh8QvlXsBNEEXNyrkU=", + "requires": { + "stream-buffers": "2.2.0" + } + }, + "bplist-parser": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/bplist-parser/-/bplist-parser-0.1.1.tgz", + "integrity": "sha1-1g1dzCDLptx+HymbNdPh+V2vuuY=", + "requires": { + "big-integer": "1.6.26" + } }, "brace-expansion": { "version": "1.1.8", "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.8.tgz", "integrity": "sha1-wHshHHyVLsH479Uad+8NHTmQopI=", - "dev": true + "requires": { + "balanced-match": "1.0.0", + "concat-map": "0.0.1" + } }, "braces": { "version": "1.8.5", "resolved": "https://registry.npmjs.org/braces/-/braces-1.8.5.tgz", "integrity": "sha1-uneWLhLf+WnWt2cR6RS3N4V79qc=", - "dev": true + "requires": { + "expand-range": "1.8.2", + "preserve": "0.2.0", + "repeat-element": "1.1.2" + } + }, + "bser": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/bser/-/bser-1.0.3.tgz", + "integrity": "sha1-1j2hnuFzMKDiYNKjRCKyGolSAxc=", + "requires": { + "node-int64": "0.4.0" + } + }, + "buffer-alloc": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/buffer-alloc/-/buffer-alloc-1.1.0.tgz", + "integrity": "sha1-BVFNM78WVtNUDGhPZbEgLpDsowM=", + "requires": { + "buffer-alloc-unsafe": "0.1.1", + "buffer-fill": "0.1.0" + } + }, + "buffer-alloc-unsafe": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/buffer-alloc-unsafe/-/buffer-alloc-unsafe-0.1.1.tgz", + "integrity": "sha1-/+H2dVHdBVc33iUzN7/oU9+rGmo=" }, "buffer-equal-constant-time": { "version": "1.0.1", @@ -401,6 +1595,11 @@ "integrity": "sha1-+OcRMvf/5uAaXJaXpMbz5I1cyBk=", "dev": true }, + "buffer-fill": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/buffer-fill/-/buffer-fill-0.1.0.tgz", + "integrity": "sha1-ypRw6NTRuXf9dUP04qtqfclRAag=" + }, "buffers": { "version": "0.1.1", "resolved": "https://registry.npmjs.org/buffers/-/buffers-0.1.1.tgz", @@ -410,20 +1609,33 @@ "builtin-modules": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/builtin-modules/-/builtin-modules-1.1.1.tgz", - "integrity": "sha1-Jw8HbFpywC9bZaR9+Uxf46J4iS8=", - "dev": true + "integrity": "sha1-Jw8HbFpywC9bZaR9+Uxf46J4iS8=" }, "bunyan": { "version": "1.8.10", "resolved": "https://registry.npmjs.org/bunyan/-/bunyan-1.8.10.tgz", "integrity": "sha1-IB/t0mxwgLYy9BYHL1OpC5pSmBw=", - "dev": true + "dev": true, + "requires": { + "dtrace-provider": "0.8.3", + "moment": "2.18.1", + "mv": "2.1.1", + "safe-json-stringify": "1.0.4" + } }, "bytes": { "version": "2.4.0", "resolved": "https://registry.npmjs.org/bytes/-/bytes-2.4.0.tgz", - "integrity": "sha1-fZcZb51br39pNeJZhVSe3SpsIzk=", - "dev": true + "integrity": "sha1-fZcZb51br39pNeJZhVSe3SpsIzk=" + }, + "caller-path": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/caller-path/-/caller-path-0.1.0.tgz", + "integrity": "sha1-lAhe9jWB7NPaqSREqP6U6CV3dR8=", + "dev": true, + "requires": { + "callsites": "0.2.0" + } }, "callsite": { "version": "1.0.0", @@ -431,71 +1643,230 @@ "integrity": "sha1-KAOY5dZkvXQDi28JBRU+borxvCA=", "dev": true }, + "callsites": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/callsites/-/callsites-0.2.0.tgz", + "integrity": "sha1-r6uWJikQp/M8GaV3WCXGnzTjUMo=", + "dev": true + }, "camel-case": { "version": "1.2.2", "resolved": "https://registry.npmjs.org/camel-case/-/camel-case-1.2.2.tgz", "integrity": "sha1-Gsp8TRlTWaLOmVV5NDPG5VQlEfI=", - "dev": true + "dev": true, + "requires": { + "sentence-case": "1.1.3", + "upper-case": "1.1.3" + } + }, + "camelcase": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-3.0.0.tgz", + "integrity": "sha1-MvxLn82vhF/N9+c7uXysImHwqwo=" + }, + "capture-stack-trace": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/capture-stack-trace/-/capture-stack-trace-1.0.0.tgz", + "integrity": "sha1-Sm+gc5nCa7pH8LJJa00PtAjFVQ0=" }, "caseless": { "version": "0.12.0", "resolved": "https://registry.npmjs.org/caseless/-/caseless-0.12.0.tgz", - "integrity": "sha1-G2gcIf+EAzyCZUMJBolCDRhxUdw=", - "dev": true + "integrity": "sha1-G2gcIf+EAzyCZUMJBolCDRhxUdw=" + }, + "center-align": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/center-align/-/center-align-0.1.3.tgz", + "integrity": "sha1-qg0yYptu6XIgBBHL1EYckHvCt60=", + "requires": { + "align-text": "0.1.4", + "lazy-cache": "1.0.4" + } }, "chainsaw": { "version": "0.1.0", "resolved": "https://registry.npmjs.org/chainsaw/-/chainsaw-0.1.0.tgz", "integrity": "sha1-XqtQsor+WAdNDVgpE4iCi15fvJg=", - "dev": true + "dev": true, + "requires": { + "traverse": "0.3.9" + } }, "chalk": { "version": "1.1.3", "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", - "dev": true + "requires": { + "ansi-styles": "2.2.1", + "escape-string-regexp": "1.0.5", + "has-ansi": "2.0.0", + "strip-ansi": "3.0.1", + "supports-color": "2.0.0" + } }, "change-case": { "version": "2.3.1", "resolved": "https://registry.npmjs.org/change-case/-/change-case-2.3.1.tgz", "integrity": "sha1-LE/ePwY7tB0AzWjg1aCdthy+iU8=", + "dev": true, + "requires": { + "camel-case": "1.2.2", + "constant-case": "1.1.2", + "dot-case": "1.1.2", + "is-lower-case": "1.1.3", + "is-upper-case": "1.1.2", + "lower-case": "1.1.4", + "lower-case-first": "1.0.2", + "param-case": "1.1.2", + "pascal-case": "1.1.2", + "path-case": "1.1.2", + "sentence-case": "1.1.3", + "snake-case": "1.1.2", + "swap-case": "1.1.2", + "title-case": "1.1.2", + "upper-case": "1.1.3", + "upper-case-first": "1.1.2" + } + }, + "change-emitter": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/change-emitter/-/change-emitter-0.1.6.tgz", + "integrity": "sha1-6LL+PX8at9aaMhma/5HqaTFAlRU=" + }, + "cheerio": { + "version": "0.22.0", + "resolved": "https://registry.npmjs.org/cheerio/-/cheerio-0.22.0.tgz", + "integrity": "sha1-qbqoYKP5tZWmuBsahocxIe06Jp4=", + "dev": true, + "requires": { + "css-select": "1.2.0", + "dom-serializer": "0.1.0", + "entities": "1.1.1", + "htmlparser2": "3.9.2", + "lodash.assignin": "4.2.0", + "lodash.bind": "4.2.1", + "lodash.defaults": "4.2.0", + "lodash.filter": "4.6.0", + "lodash.flatten": "4.4.0", + "lodash.foreach": "4.5.0", + "lodash.map": "4.6.0", + "lodash.merge": "4.6.1", + "lodash.pick": "4.4.0", + "lodash.reduce": "4.6.0", + "lodash.reject": "4.6.0", + "lodash.some": "4.6.0" + } + }, + "circular-json": { + "version": "0.3.3", + "resolved": "https://registry.npmjs.org/circular-json/-/circular-json-0.3.3.tgz", + "integrity": "sha512-UZK3NBx2Mca+b5LsG7bY183pHWt5Y1xts4P3Pz7ENTwGVnJOUWbRb3ocjvX7hx9tq/yTAdclXm9sZ38gNuem4A==", "dev": true }, + "clamp": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/clamp/-/clamp-1.0.1.tgz", + "integrity": "sha1-ZqDmQBGBbjcZaCj9yMjBRzEshjQ=" + }, + "cli-boxes": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/cli-boxes/-/cli-boxes-1.0.0.tgz", + "integrity": "sha1-T6kXw+WclKAEzWH47lCdplFocUM=" + }, "cli-cursor": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-2.1.0.tgz", "integrity": "sha1-s12sN2R5+sw+lHR9QdDQ9SOP/LU=", - "dev": true + "requires": { + "restore-cursor": "2.0.0" + } }, "cli-width": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/cli-width/-/cli-width-2.1.0.tgz", - "integrity": "sha1-sjTKIJsp72b8UY2bmNWEewDt8Ao=", - "dev": true + "integrity": "sha1-sjTKIJsp72b8UY2bmNWEewDt8Ao=" + }, + "cliui": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-3.2.0.tgz", + "integrity": "sha1-EgYBU3qRbSmUD5NNo7SNWFo5IT0=", + "requires": { + "string-width": "1.0.2", + "strip-ansi": "3.0.1", + "wrap-ansi": "2.1.0" + } }, "clone": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/clone/-/clone-2.1.1.tgz", - "integrity": "sha1-0hfR6WERjjrJpLi7oyhVU79kfNs=", - "dev": true + "integrity": "sha1-0hfR6WERjjrJpLi7oyhVU79kfNs=" + }, + "clone-stats": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/clone-stats/-/clone-stats-0.0.1.tgz", + "integrity": "sha1-uI+UqCzzi4eR1YBG6kAprYjKmdE=" }, "co": { "version": "4.6.0", "resolved": "https://registry.npmjs.org/co/-/co-4.6.0.tgz", - "integrity": "sha1-bqa989hTrlTMuOR7+gvz+QMfsYQ=", - "dev": true + "integrity": "sha1-bqa989hTrlTMuOR7+gvz+QMfsYQ=" + }, + "code-point-at": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/code-point-at/-/code-point-at-1.1.0.tgz", + "integrity": "sha1-DQcLTQQ6W+ozovGkDi7bPZpMz3c=" + }, + "color": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/color/-/color-1.0.3.tgz", + "integrity": "sha1-5I6DLYXxTvaU+0aIEcLVz+cptV0=", + "requires": { + "color-convert": "1.9.1", + "color-string": "1.5.2" + } + }, + "color-convert": { + "version": "1.9.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.1.tgz", + "integrity": "sha512-mjGanIiwQJskCC18rPR6OmrZ6fm2Lc7PeGFYwCmy5J34wC6F1PzdGL6xeMfmgicfYcNLGuVFA3WzXtIDCQSZxQ==", + "requires": { + "color-name": "1.1.3" + } + }, + "color-name": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", + "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=" + }, + "color-string": { + "version": "1.5.2", + "resolved": "https://registry.npmjs.org/color-string/-/color-string-1.5.2.tgz", + "integrity": "sha1-JuRYFLw8mny9Z1FkikFDRRSnc6k=", + "requires": { + "color-name": "1.1.3", + "simple-swizzle": "0.2.2" + } + }, + "color-support": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-support/-/color-support-1.1.3.tgz", + "integrity": "sha512-qiBjkpbMLO/HL68y+lh4q0/O1MZFj2RX6X/KmMa3+gJD3z+WwI1ZzDHysvqHGS3mP6mznPckpXmw1nI9cJjyRg==" }, "combined-stream": { "version": "1.0.5", "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.5.tgz", "integrity": "sha1-k4NwpXtKUd6ix3wV1cX9+JUWQAk=", - "dev": true + "requires": { + "delayed-stream": "1.0.0" + } }, "commander": { "version": "2.9.0", "resolved": "https://registry.npmjs.org/commander/-/commander-2.9.0.tgz", "integrity": "sha1-nJkJQXbhIkDLItbFFGCYQA/g99Q=", - "dev": true + "requires": { + "graceful-readlink": "1.0.1" + } }, "component-emitter": { "version": "1.2.1", @@ -509,47 +1880,203 @@ "integrity": "sha1-ikeQFwAjjk/DIml3EjAibyS0Fak=", "dev": true }, + "compressible": { + "version": "2.0.13", + "resolved": "https://registry.npmjs.org/compressible/-/compressible-2.0.13.tgz", + "integrity": "sha1-DRAgq5JLL9tNYnmHXH1tq6a6p6k=", + "requires": { + "mime-db": "1.27.0" + } + }, + "compression": { + "version": "1.7.2", + "resolved": "https://registry.npmjs.org/compression/-/compression-1.7.2.tgz", + "integrity": "sha1-qv+81qr4VLROuygDU9WtFlH1mmk=", + "requires": { + "accepts": "1.3.3", + "bytes": "2.4.0", + "compressible": "2.0.13", + "debug": "2.6.8", + "on-headers": "1.0.1", + "safe-buffer": "5.1.0", + "vary": "1.1.1" + } + }, "concat-map": { "version": "0.0.1", "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", - "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=", - "dev": true + "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=" + }, + "concat-stream": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/concat-stream/-/concat-stream-1.6.0.tgz", + "integrity": "sha1-CqxmL9Ur54lk1VMvaUeE5wEQrPc=", + "requires": { + "inherits": "2.0.3", + "readable-stream": "1.1.14", + "typedarray": "0.0.6" + } + }, + "configstore": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/configstore/-/configstore-2.1.0.tgz", + "integrity": "sha1-c3o6cDbpiGECqmCZ5HuzOrGroaE=", + "requires": { + "dot-prop": "3.0.0", + "graceful-fs": "4.1.11", + "mkdirp": "0.5.1", + "object-assign": "4.1.1", + "os-tmpdir": "1.0.2", + "osenv": "0.1.5", + "uuid": "3.0.1", + "write-file-atomic": "1.3.4", + "xdg-basedir": "2.0.0" + } + }, + "connect": { + "version": "2.30.2", + "resolved": "https://registry.npmjs.org/connect/-/connect-2.30.2.tgz", + "integrity": "sha1-jam8vooFTT0xjXTf7JA7XDmhtgk=", + "requires": { + "basic-auth-connect": "1.0.0", + "body-parser": "1.17.2", + "bytes": "2.4.0", + "compression": "1.5.2", + "connect-timeout": "1.6.2", + "content-type": "1.0.2", + "cookie": "0.3.1", + "cookie-parser": "1.3.5", + "cookie-signature": "1.0.6", + "csurf": "1.8.3", + "debug": "2.6.8", + "depd": "1.1.0", + "errorhandler": "1.4.3", + "express-session": "1.11.3", + "finalhandler": "1.0.3", + "fresh": "0.5.0", + "http-errors": "1.6.1", + "method-override": "2.3.10", + "morgan": "1.6.1", + "multiparty": "3.3.2", + "on-headers": "1.0.1", + "parseurl": "1.3.1", + "pause": "0.1.0", + "qs": "6.4.0", + "response-time": "2.3.2", + "serve-favicon": "2.3.2", + "serve-index": "1.7.3", + "serve-static": "1.12.3", + "type-is": "1.6.15", + "utils-merge": "1.0.0", + "vhost": "3.0.2" + }, + "dependencies": { + "basic-auth": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/basic-auth/-/basic-auth-1.0.4.tgz", + "integrity": "sha1-Awk1sB3nyblKgksp8/zLdQ06UpA=" + }, + "compression": { + "version": "1.5.2", + "resolved": "https://registry.npmjs.org/compression/-/compression-1.5.2.tgz", + "integrity": "sha1-sDuNhub4rSloPLqN+R3cb/x3s5U=", + "requires": { + "accepts": "1.3.3", + "bytes": "2.4.0", + "compressible": "2.0.13", + "debug": "2.6.8", + "on-headers": "1.0.1", + "vary": "1.1.1" + } + }, + "errorhandler": { + "version": "1.4.3", + "resolved": "https://registry.npmjs.org/errorhandler/-/errorhandler-1.4.3.tgz", + "integrity": "sha1-t7cO2PNZ6duICS8tIMD4MUIK2D8=", + "requires": { + "accepts": "1.3.3", + "escape-html": "1.0.3" + } + }, + "morgan": { + "version": "1.6.1", + "resolved": "https://registry.npmjs.org/morgan/-/morgan-1.6.1.tgz", + "integrity": "sha1-X9gYOYxoGcuiinzWZk8pL+HAu/I=", + "requires": { + "basic-auth": "1.0.4", + "debug": "2.6.8", + "depd": "1.1.0", + "on-finished": "2.3.0", + "on-headers": "1.0.1" + } + } + } + }, + "connect-pause": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/connect-pause/-/connect-pause-0.1.0.tgz", + "integrity": "sha1-D9d72e+Lpg0KJw7lIxOz2tRsQSo=" + }, + "connect-timeout": { + "version": "1.6.2", + "resolved": "https://registry.npmjs.org/connect-timeout/-/connect-timeout-1.6.2.tgz", + "integrity": "sha1-3ppexh4zoStu2qt7XwYumMWZuI4=", + "requires": { + "debug": "2.6.8", + "http-errors": "1.6.1", + "ms": "2.0.0", + "on-headers": "1.0.1" + } }, "constant-case": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/constant-case/-/constant-case-1.1.2.tgz", "integrity": "sha1-jsLKW6ND4Aqjjb9OIA/VrJB+/WM=", + "dev": true, + "requires": { + "snake-case": "1.1.2", + "upper-case": "1.1.3" + } + }, + "contains-path": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/contains-path/-/contains-path-0.1.0.tgz", + "integrity": "sha1-/ozxhP9mcLa67wGp1IYaXL7EEgo=", "dev": true }, "content-disposition": { "version": "0.5.2", "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.2.tgz", - "integrity": "sha1-DPaLud318r55YcOoUXjLhdunjLQ=", - "dev": true + "integrity": "sha1-DPaLud318r55YcOoUXjLhdunjLQ=" }, "content-type": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.2.tgz", - "integrity": "sha1-t9ETrueo3Se9IRM8TcJSnfFyHu0=", - "dev": true + "integrity": "sha1-t9ETrueo3Se9IRM8TcJSnfFyHu0=" }, "convert-source-map": { "version": "1.5.0", "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.5.0.tgz", - "integrity": "sha1-ms1whRxtXf3ZPZKC5e35SgP/RrU=", - "dev": true + "integrity": "sha1-ms1whRxtXf3ZPZKC5e35SgP/RrU=" }, "cookie": { "version": "0.3.1", "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.3.1.tgz", - "integrity": "sha1-5+Ch+e9DtMi6klxcWpboBtFoc7s=", - "dev": true + "integrity": "sha1-5+Ch+e9DtMi6klxcWpboBtFoc7s=" + }, + "cookie-parser": { + "version": "1.3.5", + "resolved": "https://registry.npmjs.org/cookie-parser/-/cookie-parser-1.3.5.tgz", + "integrity": "sha1-nXVVcPtdF4kHcSJ6AjFNm+fPg1Y=", + "requires": { + "cookie": "0.3.1", + "cookie-signature": "1.0.6" + } }, "cookie-signature": { "version": "1.0.6", "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz", - "integrity": "sha1-4wOogrNCzD7oylE6eZmXNNqzriw=", - "dev": true + "integrity": "sha1-4wOogrNCzD7oylE6eZmXNNqzriw=" }, "cookiejar": { "version": "2.1.1", @@ -560,31 +2087,62 @@ "core-js": { "version": "2.4.1", "resolved": "https://registry.npmjs.org/core-js/-/core-js-2.4.1.tgz", - "integrity": "sha1-TekR5mew6ukSTjQlS1OupvxhjT4=", - "dev": true + "integrity": "sha1-TekR5mew6ukSTjQlS1OupvxhjT4=" }, "core-util-is": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", - "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=", - "dev": true + "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=" + }, + "cors": { + "version": "2.8.4", + "resolved": "https://registry.npmjs.org/cors/-/cors-2.8.4.tgz", + "integrity": "sha1-K9OB8usgECAQXNUOpZ2mMJBpRoY=", + "requires": { + "object-assign": "4.1.1", + "vary": "1.1.1" + } + }, + "crc": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/crc/-/crc-3.3.0.tgz", + "integrity": "sha1-+mIuG8OIvyVzCQgta2UgDOZwkLo=" + }, + "create-error-class": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/create-error-class/-/create-error-class-3.0.2.tgz", + "integrity": "sha1-Br56vvlHo/FKMP1hBnHUAbyot7Y=", + "requires": { + "capture-stack-trace": "1.0.0" + } }, "create-react-class": { "version": "15.5.4", "resolved": "https://registry.npmjs.org/create-react-class/-/create-react-class-15.5.4.tgz", - "integrity": "sha1-GIh1yxXi++TKWVtvQ+sOSh8A/lA=" + "integrity": "sha1-GIh1yxXi++TKWVtvQ+sOSh8A/lA=", + "requires": { + "fbjs": "0.8.12", + "loose-envify": "1.3.1", + "object-assign": "4.1.1" + } }, "cross-spawn": { "version": "5.1.0", "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-5.1.0.tgz", "integrity": "sha1-6L0O/uWPz/b4+UUQoKVUu/ojVEk=", - "dev": true + "requires": { + "lru-cache": "4.1.1", + "shebang-command": "1.2.0", + "which": "1.2.14" + } }, "cryptiles": { "version": "2.0.5", "resolved": "https://registry.npmjs.org/cryptiles/-/cryptiles-2.0.5.tgz", "integrity": "sha1-O9/s3GCBR8HGcgL6KR59ylnqo7g=", - "dev": true + "requires": { + "boom": "2.10.1" + } }, "crypto-token": { "version": "1.0.1", @@ -592,37 +2150,126 @@ "integrity": "sha1-J8ZIL687Y8L12hFXf4MENG/nl6U=", "dev": true }, + "csrf": { + "version": "3.0.6", + "resolved": "https://registry.npmjs.org/csrf/-/csrf-3.0.6.tgz", + "integrity": "sha1-thEg3c7q/JHnbtUxO7XAsmZ7cQo=", + "requires": { + "rndm": "1.2.0", + "tsscmp": "1.0.5", + "uid-safe": "2.1.4" + } + }, + "css-mediaquery": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/css-mediaquery/-/css-mediaquery-0.1.2.tgz", + "integrity": "sha1-aiw3NEkoYYYxxUvTPO3TAdoYvqA=" + }, + "css-select": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/css-select/-/css-select-1.2.0.tgz", + "integrity": "sha1-KzoRBTnFNV8c2NMUYj6HCxIeyFg=", + "dev": true, + "requires": { + "boolbase": "1.0.0", + "css-what": "2.1.0", + "domutils": "1.5.1", + "nth-check": "1.0.1" + } + }, + "css-what": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/css-what/-/css-what-2.1.0.tgz", + "integrity": "sha1-lGfQMsOM+u+58teVASUwYvh/ob0=", + "dev": true + }, + "csurf": { + "version": "1.8.3", + "resolved": "https://registry.npmjs.org/csurf/-/csurf-1.8.3.tgz", + "integrity": "sha1-I/KhO/HY/OHQyZZYg5RELLqGpWo=", + "requires": { + "cookie": "0.3.1", + "cookie-signature": "1.0.6", + "csrf": "3.0.6", + "http-errors": "1.6.1" + } + }, + "d": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/d/-/d-1.0.0.tgz", + "integrity": "sha1-dUu1v+VUUdpppYuU1F9MWwRi1Y8=", + "dev": true, + "requires": { + "es5-ext": "0.10.39" + } + }, + "damerau-levenshtein": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/damerau-levenshtein/-/damerau-levenshtein-1.0.4.tgz", + "integrity": "sha1-AxkcQyy27qFou3fzpV/9zLiXhRQ=", + "dev": true + }, "dashdash": { "version": "1.14.1", "resolved": "https://registry.npmjs.org/dashdash/-/dashdash-1.14.1.tgz", "integrity": "sha1-hTz6D3y+L+1d4gMmuN1YEDX24vA=", - "dev": true, + "requires": { + "assert-plus": "1.0.0" + }, "dependencies": { "assert-plus": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", - "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=", - "dev": true + "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=" } } }, + "dateformat": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/dateformat/-/dateformat-2.2.0.tgz", + "integrity": "sha1-QGXiATz5+5Ft39gu+1Bq1MZ2kGI=" + }, "debug": { "version": "2.6.8", "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.8.tgz", "integrity": "sha1-5zFTHKLt4n0YgiJCfaF4IdaP9Pw=", - "dev": true + "requires": { + "ms": "2.0.0" + } }, "decache": { "version": "4.1.0", "resolved": "https://registry.npmjs.org/decache/-/decache-4.1.0.tgz", "integrity": "sha1-IDfV7fdW3aIwyFAjZZ58PR1uAQU=", - "dev": true + "dev": true, + "requires": { + "callsite": "1.0.0" + } + }, + "decamelize": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz", + "integrity": "sha1-9lNNFRSCabIDUue+4m9QH5oZEpA=" }, "decompress-zip": { "version": "0.3.0", "resolved": "https://registry.npmjs.org/decompress-zip/-/decompress-zip-0.3.0.tgz", "integrity": "sha1-rjvLfjTGWHmt/nfhnDD4ZgK0vbA=", - "dev": true + "dev": true, + "requires": { + "binary": "0.3.0", + "graceful-fs": "4.1.11", + "mkpath": "0.1.0", + "nopt": "3.0.6", + "q": "1.5.0", + "readable-stream": "1.1.14", + "touch": "0.0.3" + } + }, + "dedent": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/dedent/-/dedent-0.6.0.tgz", + "integrity": "sha1-Dm2o8M5Sg471zsXI+TlrDBtko8s=" }, "deep-diff": { "version": "0.3.4", @@ -630,6 +2277,42 @@ "integrity": "sha1-qsXDmVIjar5fA3ojSQYLoBsArkg=", "dev": true }, + "deep-extend": { + "version": "0.4.2", + "resolved": "https://registry.npmjs.org/deep-extend/-/deep-extend-0.4.2.tgz", + "integrity": "sha1-SLaZwn4zS/ifEIkr5DL25MfTSn8=" + }, + "deep-is": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.3.tgz", + "integrity": "sha1-s2nW+128E+7PUk+RsHD+7cNXzzQ=", + "dev": true + }, + "define-properties": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.1.2.tgz", + "integrity": "sha1-g6c/L+pWmJj7c3GTyPhzyvbUXJQ=", + "dev": true, + "requires": { + "foreach": "2.0.5", + "object-keys": "1.0.11" + } + }, + "del": { + "version": "2.2.2", + "resolved": "https://registry.npmjs.org/del/-/del-2.2.2.tgz", + "integrity": "sha1-wSyYHQZ4RshLyvhiz/kw2Qf/0ag=", + "dev": true, + "requires": { + "globby": "5.0.0", + "is-path-cwd": "1.0.0", + "is-path-in-cwd": "1.0.0", + "object-assign": "4.1.1", + "pify": "2.3.0", + "pinkie-promise": "2.0.1", + "rimraf": "2.6.1" + } + }, "delay-async": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/delay-async/-/delay-async-1.1.0.tgz", @@ -639,105 +2322,564 @@ "delayed-stream": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", - "integrity": "sha1-3zrhmayt+31ECqrgsp4icrJOxhk=", - "dev": true + "integrity": "sha1-3zrhmayt+31ECqrgsp4icrJOxhk=" + }, + "delegates": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delegates/-/delegates-1.0.0.tgz", + "integrity": "sha1-hMbhWbgZBP3KWaDvRM2HDTElD5o=" + }, + "denodeify": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/denodeify/-/denodeify-1.2.1.tgz", + "integrity": "sha1-OjYof1A05pnnV3kBBSwubJQlFjE=" }, "depd": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.0.tgz", - "integrity": "sha1-4b2Cxqq2ztlluXuIsX7T5SjKGMM=", - "dev": true + "integrity": "sha1-4b2Cxqq2ztlluXuIsX7T5SjKGMM=" }, "destroy": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.0.4.tgz", - "integrity": "sha1-l4hXRCxEdJ5CBmE+N5RiBYJqvYA=", - "dev": true + "integrity": "sha1-l4hXRCxEdJ5CBmE+N5RiBYJqvYA=" }, "detect-indent": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/detect-indent/-/detect-indent-4.0.0.tgz", "integrity": "sha1-920GQ1LN9Docts5hnE7jqUdd4gg=", + "requires": { + "repeating": "2.0.1" + } + }, + "diff": { + "version": "3.4.0", + "resolved": "https://registry.npmjs.org/diff/-/diff-3.4.0.tgz", + "integrity": "sha512-QpVuMTEoJMF7cKzi6bvWhRulU1fZqZnvyVQgNhPaxxuTYwyjn/j1v9falseQ/uXWwPnO56RBfwtg4h/EQXmucA==", + "dev": true + }, + "doctrine": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-2.1.0.tgz", + "integrity": "sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw==", + "dev": true, + "requires": { + "esutils": "2.0.2" + } + }, + "dom-serializer": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-0.1.0.tgz", + "integrity": "sha1-BzxpdUbOB4DOI75KKOKT5AvDDII=", + "dev": true, + "requires": { + "domelementtype": "1.1.3", + "entities": "1.1.1" + }, + "dependencies": { + "domelementtype": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-1.1.3.tgz", + "integrity": "sha1-vSh3PiZCiBrsUVRJJCmcXNgiGFs=", + "dev": true + } + } + }, + "dom-walk": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/dom-walk/-/dom-walk-0.1.1.tgz", + "integrity": "sha1-ZyIm3HTI95mtNTB9+TaroRrNYBg=" + }, + "domelementtype": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-1.3.0.tgz", + "integrity": "sha1-sXrtguirWeUt2cGbF1bg/BhyBMI=", "dev": true }, - "dot-case": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/dot-case/-/dot-case-1.1.2.tgz", - "integrity": "sha1-HnOCaQDeKNbeVIC8HeMdCEKwa+w=", - "dev": true + "domhandler": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/domhandler/-/domhandler-2.4.1.tgz", + "integrity": "sha1-iS5HAAqZvlW783dP/qBWHYh5wlk=", + "dev": true, + "requires": { + "domelementtype": "1.3.0" + } + }, + "domutils": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/domutils/-/domutils-1.5.1.tgz", + "integrity": "sha1-3NhIiib1Y9YQeeSMn3t+Mjc2gs8=", + "dev": true, + "requires": { + "dom-serializer": "0.1.0", + "domelementtype": "1.3.0" + } + }, + "dot-case": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/dot-case/-/dot-case-1.1.2.tgz", + "integrity": "sha1-HnOCaQDeKNbeVIC8HeMdCEKwa+w=", + "dev": true, + "requires": { + "sentence-case": "1.1.3" + } + }, + "dot-prop": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/dot-prop/-/dot-prop-3.0.0.tgz", + "integrity": "sha1-G3CK8JSknJoOfbyteQq6U52sEXc=", + "requires": { + "is-obj": "1.0.1" + } + }, + "dtrace-provider": { + "version": "0.8.3", + "resolved": "https://registry.npmjs.org/dtrace-provider/-/dtrace-provider-0.8.3.tgz", + "integrity": "sha1-uhv8ZJMoXM/PxqtpzVxh10wqQ78=", + "dev": true, + "optional": true, + "requires": { + "nan": "2.6.2" + } + }, + "duplexer2": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/duplexer2/-/duplexer2-0.1.4.tgz", + "integrity": "sha1-ixLauHjA1p4+eJEFFmKjL8a93ME=", + "requires": { + "readable-stream": "1.1.14" + } + }, + "ecc-jsbn": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/ecc-jsbn/-/ecc-jsbn-0.1.1.tgz", + "integrity": "sha1-D8c6ntXw1Tw4GTOYUj735UN3dQU=", + "optional": true, + "requires": { + "jsbn": "0.1.1" + } + }, + "ecdsa-sig-formatter": { + "version": "1.0.9", + "resolved": "https://registry.npmjs.org/ecdsa-sig-formatter/-/ecdsa-sig-formatter-1.0.9.tgz", + "integrity": "sha1-S8kmJ07Dtau1AW5+HWCSGsJisqE=", + "dev": true, + "requires": { + "base64url": "2.0.0", + "safe-buffer": "5.1.0" + } + }, + "ee-first": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", + "integrity": "sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0=" + }, + "emoji-regex": { + "version": "6.5.1", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-6.5.1.tgz", + "integrity": "sha512-PAHp6TxrCy7MGMFidro8uikr+zlJJKJ/Q6mm2ExZ7HwkyR9lSVFfE3kt36qcwa24BQL7y0G9axycGjK1A/0uNQ==", + "dev": true + }, + "encodeurl": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.1.tgz", + "integrity": "sha1-eePVhlU0aQn+bw9Fpd5oEDspTSA=" + }, + "encoding": { + "version": "0.1.12", + "resolved": "https://registry.npmjs.org/encoding/-/encoding-0.1.12.tgz", + "integrity": "sha1-U4tm8+5izRq1HsMjgp0flIDHS+s=", + "requires": { + "iconv-lite": "0.4.13" + } + }, + "entities": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/entities/-/entities-1.1.1.tgz", + "integrity": "sha1-blwtClYhtdra7O+AuQ7ftc13cvA=", + "dev": true + }, + "enzyme": { + "version": "2.9.1", + "resolved": "https://registry.npmjs.org/enzyme/-/enzyme-2.9.1.tgz", + "integrity": "sha1-B9XOaRJBJA+4F78sSxjW5TAkDfY=", + "dev": true, + "requires": { + "cheerio": "0.22.0", + "function.prototype.name": "1.1.0", + "is-subset": "0.1.1", + "lodash": "4.17.4", + "object-is": "1.0.1", + "object.assign": "4.1.0", + "object.entries": "1.0.4", + "object.values": "1.0.4", + "prop-types": "15.5.10", + "uuid": "3.0.1" + } + }, + "errno": { + "version": "0.1.7", + "resolved": "https://registry.npmjs.org/errno/-/errno-0.1.7.tgz", + "integrity": "sha512-MfrRBDWzIWifgq6tJj60gkAwtLNb6sQPlcFrSOflcP1aFmmruKQ2wRnze/8V6kgyz7H3FF8Npzv78mZ7XLLflg==", + "requires": { + "prr": "1.0.1" + } + }, + "error-ex": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.1.tgz", + "integrity": "sha1-+FWobOYa3E6GIcPNoh56dhLDqNw=", + "requires": { + "is-arrayish": "0.2.1" + } + }, + "errorhandler": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/errorhandler/-/errorhandler-1.5.0.tgz", + "integrity": "sha1-6rpkyl1UKjEayUX1gt78M2Fl2fQ=", + "requires": { + "accepts": "1.3.3", + "escape-html": "1.0.3" + } + }, + "es-abstract": { + "version": "1.10.0", + "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.10.0.tgz", + "integrity": "sha512-/uh/DhdqIOSkAWifU+8nG78vlQxdLckUdI/sPgy0VhuXi2qJ7T8czBmqIYtLQVpCIFYafChnsRsB5pyb1JdmCQ==", + "dev": true, + "requires": { + "es-to-primitive": "1.1.1", + "function-bind": "1.1.1", + "has": "1.0.1", + "is-callable": "1.1.3", + "is-regex": "1.0.4" + } + }, + "es-to-primitive": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.1.1.tgz", + "integrity": "sha1-RTVSSKiJeQNLZ5Lhm7gfK3l13Q0=", + "dev": true, + "requires": { + "is-callable": "1.1.3", + "is-date-object": "1.0.1", + "is-symbol": "1.0.1" + } + }, + "es5-ext": { + "version": "0.10.39", + "resolved": "https://registry.npmjs.org/es5-ext/-/es5-ext-0.10.39.tgz", + "integrity": "sha512-AlaXZhPHl0po/uxMx1tyrlt1O86M6D5iVaDH8UgLfgek4kXTX6vzsRfJQWC2Ku+aG8pkw1XWzh9eTkwfVrsD5g==", + "dev": true, + "requires": { + "es6-iterator": "2.0.3", + "es6-symbol": "3.1.1" + } + }, + "es6-error": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/es6-error/-/es6-error-4.0.2.tgz", + "integrity": "sha1-7sXHJurO9Rt/a3PCDbbhsTsGnJg=", + "dev": true + }, + "es6-iterator": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/es6-iterator/-/es6-iterator-2.0.3.tgz", + "integrity": "sha1-p96IkUGgWpSwhUQDstCg+/qY87c=", + "dev": true, + "requires": { + "d": "1.0.0", + "es5-ext": "0.10.39", + "es6-symbol": "3.1.1" + } + }, + "es6-map": { + "version": "0.1.5", + "resolved": "https://registry.npmjs.org/es6-map/-/es6-map-0.1.5.tgz", + "integrity": "sha1-kTbgUD3MBqMBaQ8LsU/042TpSfA=", + "dev": true, + "requires": { + "d": "1.0.0", + "es5-ext": "0.10.39", + "es6-iterator": "2.0.3", + "es6-set": "0.1.5", + "es6-symbol": "3.1.1", + "event-emitter": "0.3.5" + } + }, + "es6-set": { + "version": "0.1.5", + "resolved": "https://registry.npmjs.org/es6-set/-/es6-set-0.1.5.tgz", + "integrity": "sha1-0rPsXU2ADO2BjbU40ol02wpzzLE=", + "dev": true, + "requires": { + "d": "1.0.0", + "es5-ext": "0.10.39", + "es6-iterator": "2.0.3", + "es6-symbol": "3.1.1", + "event-emitter": "0.3.5" + } + }, + "es6-symbol": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/es6-symbol/-/es6-symbol-3.1.1.tgz", + "integrity": "sha1-vwDvT9q2uhtG7Le2KbTH7VcVzHc=", + "dev": true, + "requires": { + "d": "1.0.0", + "es5-ext": "0.10.39" + } + }, + "es6-weak-map": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/es6-weak-map/-/es6-weak-map-2.0.2.tgz", + "integrity": "sha1-XjqzIlH/0VOKH45f+hNXdy+S2W8=", + "dev": true, + "requires": { + "d": "1.0.0", + "es5-ext": "0.10.39", + "es6-iterator": "2.0.3", + "es6-symbol": "3.1.1" + } + }, + "escape-html": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", + "integrity": "sha1-Aljq5NPQwJdN4cFpGI7wBR0dGYg=" + }, + "escape-string-regexp": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=" + }, + "escope": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/escope/-/escope-3.6.0.tgz", + "integrity": "sha1-4Bl16BJ4GhY6ba392AOY3GTIicM=", + "dev": true, + "requires": { + "es6-map": "0.1.5", + "es6-weak-map": "2.0.2", + "esrecurse": "4.2.1", + "estraverse": "4.2.0" + } + }, + "eslint": { + "version": "3.19.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-3.19.0.tgz", + "integrity": "sha1-yPxiAcf0DdCJQbh8CFdnOGpnmsw=", + "dev": true, + "requires": { + "babel-code-frame": "6.22.0", + "chalk": "1.1.3", + "concat-stream": "1.6.0", + "debug": "2.6.8", + "doctrine": "2.1.0", + "escope": "3.6.0", + "espree": "3.5.3", + "esquery": "1.0.0", + "estraverse": "4.2.0", + "esutils": "2.0.2", + "file-entry-cache": "2.0.0", + "glob": "7.1.2", + "globals": "9.18.0", + "ignore": "3.3.7", + "imurmurhash": "0.1.4", + "inquirer": "3.1.0", + "is-my-json-valid": "2.17.2", + "is-resolvable": "1.1.0", + "js-yaml": "3.10.0", + "json-stable-stringify": "1.0.1", + "levn": "0.3.0", + "lodash": "4.17.4", + "mkdirp": "0.5.1", + "natural-compare": "1.4.0", + "optionator": "0.8.2", + "path-is-inside": "1.0.2", + "pluralize": "1.2.1", + "progress": "2.0.0", + "require-uncached": "1.0.3", + "shelljs": "0.7.8", + "strip-bom": "2.0.0", + "strip-json-comments": "2.0.1", + "table": "3.8.3", + "text-table": "0.2.0", + "user-home": "2.0.0" + }, + "dependencies": { + "pluralize": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/pluralize/-/pluralize-1.2.1.tgz", + "integrity": "sha1-0aIUg/0iu0HlihL6NCGCMUCJfEU=", + "dev": true + } + } + }, + "eslint-config-airbnb": { + "version": "15.0.1", + "resolved": "https://registry.npmjs.org/eslint-config-airbnb/-/eslint-config-airbnb-15.0.1.tgz", + "integrity": "sha1-e1GI5bfHS5ss5jn9Xh2rqP12Gu0=", + "dev": true, + "requires": { + "eslint-config-airbnb-base": "11.3.2" + } }, - "dtrace-provider": { - "version": "0.8.3", - "resolved": "https://registry.npmjs.org/dtrace-provider/-/dtrace-provider-0.8.3.tgz", - "integrity": "sha1-uhv8ZJMoXM/PxqtpzVxh10wqQ78=", + "eslint-config-airbnb-base": { + "version": "11.3.2", + "resolved": "https://registry.npmjs.org/eslint-config-airbnb-base/-/eslint-config-airbnb-base-11.3.2.tgz", + "integrity": "sha512-/fhjt/VqzBA2SRsx7ErDtv6Ayf+XLw9LIOqmpBuHFCVwyJo2EtzGWMB9fYRFBoWWQLxmNmCpenNiH0RxyeS41w==", "dev": true, - "optional": true + "requires": { + "eslint-restricted-globals": "0.1.1" + } }, - "ecc-jsbn": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/ecc-jsbn/-/ecc-jsbn-0.1.1.tgz", - "integrity": "sha1-D8c6ntXw1Tw4GTOYUj735UN3dQU=", + "eslint-import-resolver-node": { + "version": "0.2.3", + "resolved": "https://registry.npmjs.org/eslint-import-resolver-node/-/eslint-import-resolver-node-0.2.3.tgz", + "integrity": "sha1-Wt2BBujJKNssuiMrzZ76hG49oWw=", "dev": true, - "optional": true + "requires": { + "debug": "2.6.8", + "object-assign": "4.1.1", + "resolve": "1.5.0" + } }, - "ecdsa-sig-formatter": { - "version": "1.0.9", - "resolved": "https://registry.npmjs.org/ecdsa-sig-formatter/-/ecdsa-sig-formatter-1.0.9.tgz", - "integrity": "sha1-S8kmJ07Dtau1AW5+HWCSGsJisqE=", - "dev": true + "eslint-module-utils": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/eslint-module-utils/-/eslint-module-utils-2.1.1.tgz", + "integrity": "sha512-jDI/X5l/6D1rRD/3T43q8Qgbls2nq5km5KSqiwlyUbGo5+04fXhMKdCPhjwbqAa6HXWaMxj8Q4hQDIh7IadJQw==", + "dev": true, + "requires": { + "debug": "2.6.8", + "pkg-dir": "1.0.0" + } }, - "ee-first": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", - "integrity": "sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0=", - "dev": true + "eslint-plugin-import": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-import/-/eslint-plugin-import-2.3.0.tgz", + "integrity": "sha1-N8gB4K2g4pbL3yDD85OstbUq82s=", + "dev": true, + "requires": { + "builtin-modules": "1.1.1", + "contains-path": "0.1.0", + "debug": "2.6.8", + "doctrine": "1.5.0", + "eslint-import-resolver-node": "0.2.3", + "eslint-module-utils": "2.1.1", + "has": "1.0.1", + "lodash.cond": "4.5.2", + "minimatch": "3.0.4", + "read-pkg-up": "1.0.1" + }, + "dependencies": { + "doctrine": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-1.5.0.tgz", + "integrity": "sha1-N53Ocw9hZvds76TmcHoVmwLFpvo=", + "dev": true, + "requires": { + "esutils": "2.0.2", + "isarray": "1.0.0" + } + } + } }, - "encodeurl": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.1.tgz", - "integrity": "sha1-eePVhlU0aQn+bw9Fpd5oEDspTSA=", - "dev": true + "eslint-plugin-jsx-a11y": { + "version": "5.0.3", + "resolved": "https://registry.npmjs.org/eslint-plugin-jsx-a11y/-/eslint-plugin-jsx-a11y-5.0.3.tgz", + "integrity": "sha1-SpOfduwSUBBSiCMzG/lIzFczgLY=", + "dev": true, + "requires": { + "aria-query": "0.5.0", + "array-includes": "3.0.3", + "ast-types-flow": "0.0.7", + "axobject-query": "0.1.0", + "damerau-levenshtein": "1.0.4", + "emoji-regex": "6.5.1", + "jsx-ast-utils": "1.4.1" + } }, - "encoding": { - "version": "0.1.12", - "resolved": "https://registry.npmjs.org/encoding/-/encoding-0.1.12.tgz", - "integrity": "sha1-U4tm8+5izRq1HsMjgp0flIDHS+s=" + "eslint-plugin-react": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-react/-/eslint-plugin-react-7.1.0.tgz", + "integrity": "sha1-J3cKzzn1/UnNCvQIPOWBBOs5DUw=", + "dev": true, + "requires": { + "doctrine": "2.1.0", + "has": "1.0.1", + "jsx-ast-utils": "1.4.1" + } }, - "error-ex": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.1.tgz", - "integrity": "sha1-+FWobOYa3E6GIcPNoh56dhLDqNw=", + "eslint-restricted-globals": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/eslint-restricted-globals/-/eslint-restricted-globals-0.1.1.tgz", + "integrity": "sha1-NfDVy8ZMLj7WLpO0saevBbp+1Nc=", "dev": true }, - "es6-error": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/es6-error/-/es6-error-4.0.2.tgz", - "integrity": "sha1-7sXHJurO9Rt/a3PCDbbhsTsGnJg=", - "dev": true + "espree": { + "version": "3.5.3", + "resolved": "https://registry.npmjs.org/espree/-/espree-3.5.3.tgz", + "integrity": "sha512-Zy3tAJDORxQZLl2baguiRU1syPERAIg0L+JB2MWorORgTu/CplzvxS9WWA7Xh4+Q+eOQihNs/1o1Xep8cvCxWQ==", + "dev": true, + "requires": { + "acorn": "5.5.0", + "acorn-jsx": "3.0.1" + } }, - "escape-html": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", - "integrity": "sha1-Aljq5NPQwJdN4cFpGI7wBR0dGYg=", + "esprima": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.0.tgz", + "integrity": "sha512-oftTcaMu/EGrEIu904mWteKIv8vMuOgGYo7EhVJJN00R/EED9DCua/xxHRdYnKtcECzVg7xOWhflvJMnqcFZjw==", "dev": true }, - "escape-string-regexp": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", - "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=", + "esquery": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.0.0.tgz", + "integrity": "sha1-z7qLV9f7qT8XKYqKAGoEzaE9gPo=", + "dev": true, + "requires": { + "estraverse": "4.2.0" + } + }, + "esrecurse": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.2.1.tgz", + "integrity": "sha512-64RBB++fIOAXPw3P9cy89qfMlvZEXZkqqJkjqqXIvzP5ezRZjW+lPWjw35UX/3EhUPFYbg5ER4JYgDw4007/DQ==", + "dev": true, + "requires": { + "estraverse": "4.2.0" + } + }, + "estraverse": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.2.0.tgz", + "integrity": "sha1-De4/7TH81GlhjOc0IJn8GvoL2xM=", "dev": true }, "esutils": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.2.tgz", - "integrity": "sha1-Cr9PHKpbyx96nYrMbepPqqBLrJs=", - "dev": true + "integrity": "sha1-Cr9PHKpbyx96nYrMbepPqqBLrJs=" }, "etag": { "version": "1.8.0", "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.0.tgz", - "integrity": "sha1-b2Ma7zNtbEY2K1F2QETOIWvjwFE=", - "dev": true + "integrity": "sha1-b2Ma7zNtbEY2K1F2QETOIWvjwFE=" + }, + "event-emitter": { + "version": "0.3.5", + "resolved": "https://registry.npmjs.org/event-emitter/-/event-emitter-0.3.5.tgz", + "integrity": "sha1-34xp7vFkeSPHFXuc6DhAYQsCzDk=", + "dev": true, + "requires": { + "d": "1.0.0", + "es5-ext": "0.10.39" + } + }, + "event-target-shim": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/event-target-shim/-/event-target-shim-1.1.1.tgz", + "integrity": "sha1-qG5e5r2qFgVEddp5fM3fDFVphJE=" }, "exec-async": { "version": "2.2.0", @@ -745,6 +2887,14 @@ "integrity": "sha1-x8WtLu80eNODkMbdOs/orw78gwE=", "dev": true }, + "exec-sh": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/exec-sh/-/exec-sh-0.2.1.tgz", + "integrity": "sha512-aLt95pexaugVtQerpmE51+4QfWrNc304uez7jvj6fWnN8GeEHpttB8F36n8N7uVhUMbH/1enbxQ9HImZ4w/9qg==", + "requires": { + "merge": "1.2.0" + } + }, "exists-async": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/exists-async/-/exists-async-2.0.0.tgz", @@ -755,45 +2905,129 @@ "version": "0.1.5", "resolved": "https://registry.npmjs.org/expand-brackets/-/expand-brackets-0.1.5.tgz", "integrity": "sha1-3wcoTjQqgHzXM6xa9yQR5YHRF3s=", - "dev": true + "requires": { + "is-posix-bracket": "0.1.1" + } }, "expand-range": { "version": "1.8.2", "resolved": "https://registry.npmjs.org/expand-range/-/expand-range-1.8.2.tgz", "integrity": "sha1-opnv/TNf4nIeuujiV+x5ZE/IUzc=", - "dev": true + "requires": { + "fill-range": "2.2.3" + } + }, + "expo": { + "version": "19.0.1", + "resolved": "https://registry.npmjs.org/expo/-/expo-19.0.1.tgz", + "integrity": "sha1-RrrA7gA23uqQzcQZgByE5w3M+cY=", + "requires": { + "@expo/vector-icons": "5.0.0", + "babel-preset-expo": "2.0.0", + "fbemitter": "2.1.1", + "lodash.map": "4.6.0", + "lodash.zipobject": "4.1.3", + "lottie-react-native": "1.1.1", + "md5-file": "3.2.3", + "pretty-format": "20.0.3", + "prop-types": "15.5.10", + "react-native-branch": "2.0.0-beta.3", + "react-native-maps": "0.15.3", + "react-native-svg": "5.3.0", + "uuid-js": "0.7.5", + "websql": "github:expo/node-websql#e364fa65146a9e2157a19e5c719e7702c2b6b87a" + } }, "express": { "version": "4.15.3", "resolved": "https://registry.npmjs.org/express/-/express-4.15.3.tgz", "integrity": "sha1-urZdDwOqgMNYQIly/HAPkWlEtmI=", - "dev": true, + "requires": { + "accepts": "1.3.3", + "array-flatten": "1.1.1", + "content-disposition": "0.5.2", + "content-type": "1.0.2", + "cookie": "0.3.1", + "cookie-signature": "1.0.6", + "debug": "2.6.7", + "depd": "1.1.0", + "encodeurl": "1.0.1", + "escape-html": "1.0.3", + "etag": "1.8.0", + "finalhandler": "1.0.3", + "fresh": "0.5.0", + "merge-descriptors": "1.0.1", + "methods": "1.1.2", + "on-finished": "2.3.0", + "parseurl": "1.3.1", + "path-to-regexp": "0.1.7", + "proxy-addr": "1.1.4", + "qs": "6.4.0", + "range-parser": "1.2.0", + "send": "0.15.3", + "serve-static": "1.12.3", + "setprototypeof": "1.0.3", + "statuses": "1.3.1", + "type-is": "1.6.15", + "utils-merge": "1.0.0", + "vary": "1.1.1" + }, "dependencies": { "debug": { "version": "2.6.7", "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.7.tgz", "integrity": "sha1-krrR9tBbu2u6Isyoi80OyJTChh4=", - "dev": true + "requires": { + "ms": "2.0.0" + } + } + } + }, + "express-session": { + "version": "1.11.3", + "resolved": "https://registry.npmjs.org/express-session/-/express-session-1.11.3.tgz", + "integrity": "sha1-XMmPP1/4Ttg1+Ry/CqvQxxB0AK8=", + "requires": { + "cookie": "0.3.1", + "cookie-signature": "1.0.6", + "crc": "3.3.0", + "debug": "2.6.8", + "depd": "1.1.0", + "on-headers": "1.0.1", + "parseurl": "1.3.1", + "uid-safe": "2.0.0", + "utils-merge": "1.0.0" + }, + "dependencies": { + "uid-safe": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/uid-safe/-/uid-safe-2.0.0.tgz", + "integrity": "sha1-p/PGymSh9qXQTsDvPkw9U2cxcTc=", + "requires": { + "base64-url": "1.2.1" + } } } }, "extend": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.1.tgz", - "integrity": "sha1-p1Xqe8Gt/MWjHOfnYtuq3F5jZEQ=", - "dev": true + "integrity": "sha1-p1Xqe8Gt/MWjHOfnYtuq3F5jZEQ=" }, "external-editor": { "version": "2.0.4", "resolved": "https://registry.npmjs.org/external-editor/-/external-editor-2.0.4.tgz", "integrity": "sha1-HtkZnanL/i7y96MbL96LDRI2iXI=", - "dev": true, + "requires": { + "iconv-lite": "0.4.18", + "jschardet": "1.4.2", + "tmp": "0.0.31" + }, "dependencies": { "iconv-lite": { "version": "0.4.18", "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.18.tgz", - "integrity": "sha512-sr1ZQph3UwHTR0XftSbK85OvBbxe/abLGzEnPENCQwmHf7sck8Oyu4ob3LgBxWWxRoM+QszeUyl7jbqapu2TqA==", - "dev": true + "integrity": "sha512-sr1ZQph3UwHTR0XftSbK85OvBbxe/abLGzEnPENCQwmHf7sck8Oyu4ob3LgBxWWxRoM+QszeUyl7jbqapu2TqA==" } } }, @@ -801,24 +3035,123 @@ "version": "0.3.2", "resolved": "https://registry.npmjs.org/extglob/-/extglob-0.3.2.tgz", "integrity": "sha1-Lhj/PS9JqydlzskCPwEdqo2DSaE=", - "dev": true + "requires": { + "is-extglob": "1.0.0" + } }, "extsprintf": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/extsprintf/-/extsprintf-1.0.2.tgz", - "integrity": "sha1-4QgOBljjALBilJkMxw4VAiNf1VA=", + "integrity": "sha1-4QgOBljjALBilJkMxw4VAiNf1VA=" + }, + "fancy-log": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/fancy-log/-/fancy-log-1.3.2.tgz", + "integrity": "sha1-9BEl49hPLn2JpD0G2VjI94vha+E=", + "requires": { + "ansi-gray": "0.1.1", + "color-support": "1.1.3", + "time-stamp": "1.1.0" + } + }, + "fast-levenshtein": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", + "integrity": "sha1-PYpcZog6FqMMqGQ+hR8Zuqd5eRc=", "dev": true }, + "fb-watchman": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/fb-watchman/-/fb-watchman-2.0.0.tgz", + "integrity": "sha1-VOmr99+i8mzZsWNsWIwa/AXeXVg=", + "requires": { + "bser": "2.0.0" + }, + "dependencies": { + "bser": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/bser/-/bser-2.0.0.tgz", + "integrity": "sha1-mseNPtXZFYBP2HrLFYvHlxR6Fxk=", + "requires": { + "node-int64": "0.4.0" + } + } + } + }, + "fbemitter": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/fbemitter/-/fbemitter-2.1.1.tgz", + "integrity": "sha1-Uj4U/a9SSIBbsC9i78M75wP1GGU=", + "requires": { + "fbjs": "0.8.12" + } + }, "fbjs": { "version": "0.8.12", "resolved": "https://registry.npmjs.org/fbjs/-/fbjs-0.8.12.tgz", "integrity": "sha1-ELXZL3bUVXX9Y6IX1OoCvqL47QQ=", + "requires": { + "core-js": "1.2.7", + "isomorphic-fetch": "2.2.1", + "loose-envify": "1.3.1", + "object-assign": "4.1.1", + "promise": "7.1.1", + "setimmediate": "1.0.5", + "ua-parser-js": "0.7.12" + }, "dependencies": { "core-js": { "version": "1.2.7", "resolved": "https://registry.npmjs.org/core-js/-/core-js-1.2.7.tgz", - "integrity": "sha1-ZSKUwUZR2yj6k70tX/KYOk8IxjY=", - "dev": true + "integrity": "sha1-ZSKUwUZR2yj6k70tX/KYOk8IxjY=" + } + } + }, + "fbjs-scripts": { + "version": "0.7.1", + "resolved": "https://registry.npmjs.org/fbjs-scripts/-/fbjs-scripts-0.7.1.tgz", + "integrity": "sha1-TxFeIY4kPjrdvw7dqsHjxi9wP6w=", + "requires": { + "babel-core": "6.25.0", + "babel-preset-fbjs": "1.0.0", + "core-js": "2.4.1", + "cross-spawn": "5.1.0", + "gulp-util": "3.0.8", + "object-assign": "4.1.1", + "semver": "5.3.0", + "through2": "2.0.3" + }, + "dependencies": { + "babel-preset-fbjs": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/babel-preset-fbjs/-/babel-preset-fbjs-1.0.0.tgz", + "integrity": "sha1-yXLlybMB1OyeeXH0rsPhSsAXqLA=", + "requires": { + "babel-plugin-check-es2015-constants": "6.22.0", + "babel-plugin-syntax-flow": "6.18.0", + "babel-plugin-syntax-object-rest-spread": "6.13.0", + "babel-plugin-syntax-trailing-function-commas": "6.22.0", + "babel-plugin-transform-class-properties": "6.24.1", + "babel-plugin-transform-es2015-arrow-functions": "6.22.0", + "babel-plugin-transform-es2015-block-scoped-functions": "6.22.0", + "babel-plugin-transform-es2015-block-scoping": "6.26.0", + "babel-plugin-transform-es2015-classes": "6.24.1", + "babel-plugin-transform-es2015-computed-properties": "6.24.1", + "babel-plugin-transform-es2015-destructuring": "6.23.0", + "babel-plugin-transform-es2015-for-of": "6.23.0", + "babel-plugin-transform-es2015-literals": "6.22.0", + "babel-plugin-transform-es2015-modules-commonjs": "6.26.0", + "babel-plugin-transform-es2015-object-super": "6.24.1", + "babel-plugin-transform-es2015-parameters": "6.24.1", + "babel-plugin-transform-es2015-shorthand-properties": "6.24.1", + "babel-plugin-transform-es2015-spread": "6.22.0", + "babel-plugin-transform-es2015-template-literals": "6.22.0", + "babel-plugin-transform-es3-member-expression-literals": "6.22.0", + "babel-plugin-transform-es3-property-literals": "6.22.0", + "babel-plugin-transform-flow-strip-types": "6.22.0", + "babel-plugin-transform-object-rest-spread": "6.26.0", + "object-assign": "4.1.1" + } } } }, @@ -826,7 +3159,19 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/figures/-/figures-2.0.0.tgz", "integrity": "sha1-OrGi0qYsi/tDGgyUy3l6L84nyWI=", - "dev": true + "requires": { + "escape-string-regexp": "1.0.5" + } + }, + "file-entry-cache": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-2.0.0.tgz", + "integrity": "sha1-w5KZDD5oR4PYOLjISkXYoEhFg2E=", + "dev": true, + "requires": { + "flat-cache": "1.3.0", + "object-assign": "4.1.1" + } }, "file-type": { "version": "4.4.0", @@ -837,58 +3182,129 @@ "filename-regex": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/filename-regex/-/filename-regex-2.0.1.tgz", - "integrity": "sha1-wcS5vuPglyXdsQa3XB4wH+LxiyY=", - "dev": true + "integrity": "sha1-wcS5vuPglyXdsQa3XB4wH+LxiyY=" }, "fill-range": { "version": "2.2.3", "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-2.2.3.tgz", "integrity": "sha1-ULd9/X5Gm8dJJHCWNpn+eoSFpyM=", - "dev": true + "requires": { + "is-number": "2.1.0", + "isobject": "2.1.0", + "randomatic": "1.1.7", + "repeat-element": "1.1.2", + "repeat-string": "1.6.1" + } + }, + "filled-array": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/filled-array/-/filled-array-1.1.0.tgz", + "integrity": "sha1-w8T2xmO5I0WamqKZEtLQMfFQf4Q=" }, "finalhandler": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.0.3.tgz", "integrity": "sha1-70fneVDpmXgOhgIqVg4yF+DQzIk=", - "dev": true, + "requires": { + "debug": "2.6.7", + "encodeurl": "1.0.1", + "escape-html": "1.0.3", + "on-finished": "2.3.0", + "parseurl": "1.3.1", + "statuses": "1.3.1", + "unpipe": "1.0.0" + }, "dependencies": { "debug": { "version": "2.6.7", "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.7.tgz", "integrity": "sha1-krrR9tBbu2u6Isyoi80OyJTChh4=", - "dev": true + "requires": { + "ms": "2.0.0" + } } } }, + "find-babel-config": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/find-babel-config/-/find-babel-config-1.1.0.tgz", + "integrity": "sha1-rMAQQ6Z0n+w0Qpvmtk9ULrtdY1U=", + "requires": { + "json5": "0.5.1", + "path-exists": "3.0.0" + } + }, "find-up": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/find-up/-/find-up-2.1.0.tgz", "integrity": "sha1-RdG35QbHF93UgndaK3eSCjwMV6c=", - "dev": true + "dev": true, + "requires": { + "locate-path": "2.0.0" + } + }, + "flat-cache": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-1.3.0.tgz", + "integrity": "sha1-0wMLMrOBVPTjt+nHCfSQ9++XxIE=", + "dev": true, + "requires": { + "circular-json": "0.3.3", + "del": "2.2.2", + "graceful-fs": "4.1.11", + "write": "0.2.1" + } + }, + "follow-redirects": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.4.1.tgz", + "integrity": "sha512-uxYePVPogtya1ktGnAAXOacnbIuRMB4dkvqeNz2qTtTQsuzSfbDolV+wMMKxAmCx0bLgAKLbBOkjItMbbkR1vg==", + "requires": { + "debug": "2.6.8" + } }, "for-in": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/for-in/-/for-in-1.0.2.tgz", - "integrity": "sha1-gQaNKVqBQuwKxybG4iAMMPttXoA=", - "dev": true + "integrity": "sha1-gQaNKVqBQuwKxybG4iAMMPttXoA=" }, "for-own": { "version": "0.1.5", "resolved": "https://registry.npmjs.org/for-own/-/for-own-0.1.5.tgz", "integrity": "sha1-UmXGgaTylNq78XyVCbZ2OqhFEM4=", + "requires": { + "for-in": "1.0.2" + } + }, + "foreach": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/foreach/-/foreach-2.0.5.tgz", + "integrity": "sha1-C+4AUBiusmDQo6865ljdATbsG5k=", "dev": true }, "forever-agent": { "version": "0.6.1", "resolved": "https://registry.npmjs.org/forever-agent/-/forever-agent-0.6.1.tgz", - "integrity": "sha1-+8cfDEGt6zf5bFd60e1C2P2sypE=", - "dev": true + "integrity": "sha1-+8cfDEGt6zf5bFd60e1C2P2sypE=" }, "form-data": { "version": "2.1.4", "resolved": "https://registry.npmjs.org/form-data/-/form-data-2.1.4.tgz", "integrity": "sha1-M8GDrPGTJ27KqYFDpp6Uv+4XUNE=", - "dev": true + "requires": { + "asynckit": "0.4.0", + "combined-stream": "1.0.5", + "mime-types": "2.1.15" + } + }, + "formatio": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/formatio/-/formatio-1.2.0.tgz", + "integrity": "sha1-87IWfZBoxGmKjVH092CjmlTYGOs=", + "dev": true, + "requires": { + "samsam": "1.3.0" + } }, "formidable": { "version": "1.1.1", @@ -899,8 +3315,7 @@ "forwarded": { "version": "0.1.0", "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.1.0.tgz", - "integrity": "sha1-Ge+YdMSuHCl7zweP3mOgm2aoQ2M=", - "dev": true + "integrity": "sha1-Ge+YdMSuHCl7zweP3mOgm2aoQ2M=" }, "freeport-async": { "version": "1.1.1", @@ -911,44 +3326,101 @@ "fresh": { "version": "0.5.0", "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.0.tgz", - "integrity": "sha1-9HTKXmqSRtb9jglTz6m5yAWvp44=", - "dev": true + "integrity": "sha1-9HTKXmqSRtb9jglTz6m5yAWvp44=" }, "fs-extra": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-3.0.1.tgz", "integrity": "sha1-N5TzeMWLNC6n27sjCVEJxLO2IpE=", - "dev": true + "requires": { + "graceful-fs": "4.1.11", + "jsonfile": "3.0.0", + "universalify": "0.1.0" + } }, "fs.realpath": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", - "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=", - "dev": true + "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=" }, "fstream": { "version": "1.0.11", "resolved": "https://registry.npmjs.org/fstream/-/fstream-1.0.11.tgz", "integrity": "sha1-XB+x8RdHcRTwYyoOtLcbPLD9MXE=", + "dev": true, + "requires": { + "graceful-fs": "4.1.11", + "inherits": "2.0.3", + "mkdirp": "0.5.1", + "rimraf": "2.6.1" + } + }, + "function-bind": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", + "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==", + "dev": true + }, + "function.prototype.name": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/function.prototype.name/-/function.prototype.name-1.1.0.tgz", + "integrity": "sha512-Bs0VRrTz4ghD8pTmbJQD1mZ8A/mN0ur/jGz+A6FBxPDUPkm1tNfF6bhTYPA7i7aF4lZJVr+OXTNNrnnIl58Wfg==", + "dev": true, + "requires": { + "define-properties": "1.1.2", + "function-bind": "1.1.1", + "is-callable": "1.1.3" + } + }, + "gauge": { + "version": "1.2.7", + "resolved": "https://registry.npmjs.org/gauge/-/gauge-1.2.7.tgz", + "integrity": "sha1-6c7FSD09TuDvRLYKfZnkk14TbZM=", + "requires": { + "ansi": "0.3.1", + "has-unicode": "2.0.1", + "lodash.pad": "4.5.1", + "lodash.padend": "4.6.1", + "lodash.padstart": "4.6.1" + } + }, + "generate-function": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/generate-function/-/generate-function-2.0.0.tgz", + "integrity": "sha1-aFj+fAlpt9TpCTM3ZHrHn2DfvnQ=", "dev": true }, + "generate-object-property": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/generate-object-property/-/generate-object-property-1.2.0.tgz", + "integrity": "sha1-nA4cQDCM6AT0eDYYuTf6iPmdUNA=", + "dev": true, + "requires": { + "is-property": "1.0.2" + } + }, + "get-caller-file": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-1.0.2.tgz", + "integrity": "sha1-9wLmMSfn4jHBYKgMFVSstw1QR+U=" + }, "get-params": { "version": "0.1.2", "resolved": "https://registry.npmjs.org/get-params/-/get-params-0.1.2.tgz", - "integrity": "sha1-uuDfq6WIoMYNeDTA2Nwv9g7u8v4=", - "dev": true + "integrity": "sha1-uuDfq6WIoMYNeDTA2Nwv9g7u8v4=" }, "getpass": { "version": "0.1.7", "resolved": "https://registry.npmjs.org/getpass/-/getpass-0.1.7.tgz", "integrity": "sha1-Xv+OPmhNVprkyysSgmBOi6YhSfo=", - "dev": true, + "requires": { + "assert-plus": "1.0.0" + }, "dependencies": { "assert-plus": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", - "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=", - "dev": true + "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=" } } }, @@ -956,55 +3428,163 @@ "version": "7.1.2", "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.2.tgz", "integrity": "sha512-MJTUg1kjuLeQCJ+ccE4Vpa6kKVXkPYJ2mOCQyUuKLcLQsdrMCpBPUi8qVE6+YuaJkozeA9NusTAw3hLr8Xe5EQ==", - "dev": true + "requires": { + "fs.realpath": "1.0.0", + "inflight": "1.0.6", + "inherits": "2.0.3", + "minimatch": "3.0.4", + "once": "1.4.0", + "path-is-absolute": "1.0.1" + } }, "glob-base": { "version": "0.3.0", "resolved": "https://registry.npmjs.org/glob-base/-/glob-base-0.3.0.tgz", "integrity": "sha1-27Fk9iIbHAscz4Kuoyi0l98Oo8Q=", - "dev": true + "requires": { + "glob-parent": "2.0.0", + "is-glob": "2.0.1" + } }, "glob-parent": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-2.0.0.tgz", "integrity": "sha1-gTg9ctsFT8zPUzbaqQLxgvbtuyg=", - "dev": true + "requires": { + "is-glob": "2.0.1" + } + }, + "global": { + "version": "4.3.2", + "resolved": "https://registry.npmjs.org/global/-/global-4.3.2.tgz", + "integrity": "sha1-52mJJopsdMOJCLEwWxD8DjlOnQ8=", + "requires": { + "min-document": "2.19.0", + "process": "0.5.2" + } }, "globals": { "version": "9.18.0", "resolved": "https://registry.npmjs.org/globals/-/globals-9.18.0.tgz", - "integrity": "sha512-S0nG3CLEQiY/ILxqtztTWH/3iRRdyBLw6KMDxnKMchrtbj2OFmehVh0WUCfW3DUrIgx/qFrJPICrq4Z4sTR9UQ==", - "dev": true + "integrity": "sha512-S0nG3CLEQiY/ILxqtztTWH/3iRRdyBLw6KMDxnKMchrtbj2OFmehVh0WUCfW3DUrIgx/qFrJPICrq4Z4sTR9UQ==" + }, + "globby": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/globby/-/globby-5.0.0.tgz", + "integrity": "sha1-69hGZ8oNuzMLmbz8aOrCvFQ3Dg0=", + "dev": true, + "requires": { + "array-union": "1.0.2", + "arrify": "1.0.1", + "glob": "7.1.2", + "object-assign": "4.1.1", + "pify": "2.3.0", + "pinkie-promise": "2.0.1" + } + }, + "glogg": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/glogg/-/glogg-1.0.1.tgz", + "integrity": "sha512-ynYqXLoluBKf9XGR1gA59yEJisIL7YHEH4xr3ZziHB5/yl4qWfaK8Js9jGe6gBGCSCKVqiyO30WnRZADvemUNw==", + "requires": { + "sparkles": "1.0.0" + } + }, + "got": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/got/-/got-5.7.1.tgz", + "integrity": "sha1-X4FjWmHkplifGAVp6k44FoClHzU=", + "requires": { + "create-error-class": "3.0.2", + "duplexer2": "0.1.4", + "is-redirect": "1.0.0", + "is-retry-allowed": "1.1.0", + "is-stream": "1.1.0", + "lowercase-keys": "1.0.0", + "node-status-codes": "1.0.0", + "object-assign": "4.1.1", + "parse-json": "2.2.0", + "pinkie-promise": "2.0.1", + "read-all-stream": "3.1.0", + "readable-stream": "1.1.14", + "timed-out": "3.1.3", + "unzip-response": "1.0.2", + "url-parse-lax": "1.0.0" + } }, "graceful-fs": { "version": "4.1.11", "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.1.11.tgz", - "integrity": "sha1-Dovf5NHduIVNZOBOp8AOKgJuVlg=", - "dev": true + "integrity": "sha1-Dovf5NHduIVNZOBOp8AOKgJuVlg=" }, "graceful-readlink": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/graceful-readlink/-/graceful-readlink-1.0.1.tgz", - "integrity": "sha1-TK+tdrxi8C+gObL5Tpo906ORpyU=", - "dev": true + "integrity": "sha1-TK+tdrxi8C+gObL5Tpo906ORpyU=" + }, + "gulp-util": { + "version": "3.0.8", + "resolved": "https://registry.npmjs.org/gulp-util/-/gulp-util-3.0.8.tgz", + "integrity": "sha1-AFTh50RQLifATBh8PsxQXdVLu08=", + "requires": { + "array-differ": "1.0.0", + "array-uniq": "1.0.3", + "beeper": "1.1.1", + "chalk": "1.1.3", + "dateformat": "2.2.0", + "fancy-log": "1.3.2", + "gulplog": "1.0.0", + "has-gulplog": "0.1.0", + "lodash._reescape": "3.0.0", + "lodash._reevaluate": "3.0.0", + "lodash._reinterpolate": "3.0.0", + "lodash.template": "3.6.2", + "minimist": "0.0.8", + "multipipe": "0.1.2", + "object-assign": "4.1.1", + "replace-ext": "0.0.1", + "through2": "2.0.3", + "vinyl": "0.5.3" + } + }, + "gulplog": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/gulplog/-/gulplog-1.0.0.tgz", + "integrity": "sha1-4oxNRdBey77YGDY86PnFkmIp/+U=", + "requires": { + "glogg": "1.0.1" + } }, "har-schema": { "version": "1.0.5", "resolved": "https://registry.npmjs.org/har-schema/-/har-schema-1.0.5.tgz", - "integrity": "sha1-0mMTX0MwfALGAq/I/pWXDAFRNp4=", - "dev": true + "integrity": "sha1-0mMTX0MwfALGAq/I/pWXDAFRNp4=" }, "har-validator": { "version": "4.2.1", "resolved": "https://registry.npmjs.org/har-validator/-/har-validator-4.2.1.tgz", "integrity": "sha1-M0gdDxu/9gDdID11gSpqX7oALio=", - "dev": true + "requires": { + "ajv": "4.11.8", + "har-schema": "1.0.5" + } + }, + "has": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/has/-/has-1.0.1.tgz", + "integrity": "sha1-hGFzP1OLCDfJNh45qauelwTcLyg=", + "dev": true, + "requires": { + "function-bind": "1.1.1" + } }, "has-ansi": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/has-ansi/-/has-ansi-2.0.0.tgz", "integrity": "sha1-NPUEnOHs3ysGSa8+8k5F7TVBbZE=", - "dev": true + "requires": { + "ansi-regex": "2.1.1" + } }, "has-color": { "version": "0.1.7", @@ -1012,11 +3592,33 @@ "integrity": "sha1-ZxRKUmDDT8PMpnfQQdr1L+e3iy8=", "dev": true }, + "has-gulplog": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/has-gulplog/-/has-gulplog-0.1.0.tgz", + "integrity": "sha1-ZBTIKRNpfaUVkDl9r7EvIpZ4Ec4=", + "requires": { + "sparkles": "1.0.0" + } + }, + "has-symbols": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.0.tgz", + "integrity": "sha1-uhqPGvKg/DllD1yFA2dwQSIGO0Q=", + "dev": true + }, + "has-unicode": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/has-unicode/-/has-unicode-2.0.1.tgz", + "integrity": "sha1-4Ob+aijPUROIVeCG0Wkedx3iqLk=" + }, "hasbin": { "version": "1.2.3", "resolved": "https://registry.npmjs.org/hasbin/-/hasbin-1.2.3.tgz", "integrity": "sha1-eMWSaJPIAhXCtWiuH9P8q3omlrA=", "dev": true, + "requires": { + "async": "1.5.2" + }, "dependencies": { "async": { "version": "1.5.2", @@ -1030,13 +3632,17 @@ "version": "3.1.3", "resolved": "https://registry.npmjs.org/hawk/-/hawk-3.1.3.tgz", "integrity": "sha1-B4REvXwWQLD+VA0sm3PVlnjo4cQ=", - "dev": true + "requires": { + "boom": "2.10.1", + "cryptiles": "2.0.5", + "hoek": "2.16.3", + "sntp": "1.0.9" + } }, "hoek": { "version": "2.16.3", "resolved": "https://registry.npmjs.org/hoek/-/hoek-2.16.3.tgz", - "integrity": "sha1-ILt0A9POo5jpHcRxCo/xuCdKJe0=", - "dev": true + "integrity": "sha1-ILt0A9POo5jpHcRxCo/xuCdKJe0=" }, "hoist-non-react-statics": { "version": "1.2.0", @@ -1053,31 +3659,87 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/home-or-tmp/-/home-or-tmp-2.0.0.tgz", "integrity": "sha1-42w/LSyufXRqhX440Y1fMqeILbg=", - "dev": true + "requires": { + "os-homedir": "1.0.2", + "os-tmpdir": "1.0.2" + } }, "hosted-git-info": { "version": "2.4.2", "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.4.2.tgz", - "integrity": "sha1-AHa59GonBQbduq6lZJaJdGBhKmc=", - "dev": true + "integrity": "sha1-AHa59GonBQbduq6lZJaJdGBhKmc=" + }, + "htmlparser2": { + "version": "3.9.2", + "resolved": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-3.9.2.tgz", + "integrity": "sha1-G9+HrMoPP55T+k/M6w9LTLsAszg=", + "dev": true, + "requires": { + "domelementtype": "1.3.0", + "domhandler": "2.4.1", + "domutils": "1.5.1", + "entities": "1.1.1", + "inherits": "2.0.3", + "readable-stream": "1.1.14" + } }, "http-errors": { "version": "1.6.1", "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.6.1.tgz", "integrity": "sha1-X4uO2YrKVFZWv1cplzh/kEpyIlc=", - "dev": true + "requires": { + "depd": "1.1.0", + "inherits": "2.0.3", + "setprototypeof": "1.0.3", + "statuses": "1.3.1" + } }, "http-signature": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/http-signature/-/http-signature-1.1.1.tgz", "integrity": "sha1-33LiZwZs0Kxn+3at+OE0qPvPkb8=", - "dev": true + "requires": { + "assert-plus": "0.2.0", + "jsprim": "1.4.0", + "sshpk": "1.13.1" + } + }, + "i18next": { + "version": "8.4.3", + "resolved": "https://registry.npmjs.org/i18next/-/i18next-8.4.3.tgz", + "integrity": "sha1-Nrb/UWxPmSAQ7tzOJKNsRgnox9w=" }, "iconv-lite": { "version": "0.4.13", "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.13.tgz", "integrity": "sha1-H4irpKsLFQjoMSrMOTRfNumS4vI=" }, + "ignore": { + "version": "3.3.7", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-3.3.7.tgz", + "integrity": "sha512-YGG3ejvBNHRqu0559EOxxNFihD0AjpvHlC/pdGKd3X3ofe+CoJkYazwNJYTNebqpPKN+VVQbh4ZFn1DivMNuHA==", + "dev": true + }, + "image-size": { + "version": "0.3.5", + "resolved": "https://registry.npmjs.org/image-size/-/image-size-0.3.5.tgz", + "integrity": "sha1-gyQOqy+1sAsEqrjHSwRx6cunrYw=" + }, + "immediate": { + "version": "3.2.3", + "resolved": "https://registry.npmjs.org/immediate/-/immediate-3.2.3.tgz", + "integrity": "sha1-0UD6j2FGWb1lQSMwl92qwlzdmRw=" + }, + "immutable": { + "version": "3.8.2", + "resolved": "https://registry.npmjs.org/immutable/-/immutable-3.8.2.tgz", + "integrity": "sha1-wkOZUUVbs5kT2vKBN28VMOEErfM=" + }, + "imurmurhash": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", + "integrity": "sha1-khi5srkoojixPcT7a21XbyMUU+o=" + }, "indent-string": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-3.1.0.tgz", @@ -1088,37 +3750,60 @@ "version": "1.0.6", "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", - "dev": true + "requires": { + "once": "1.4.0", + "wrappy": "1.0.2" + } }, "inherits": { "version": "2.0.3", "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", - "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=", - "dev": true + "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=" + }, + "ini": { + "version": "1.3.5", + "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.5.tgz", + "integrity": "sha512-RZY5huIKCMRWDUqZlEi72f/lmXKMvuszcMBduliQ3nnWbx9X/ZBQO7DijMEYS9EhHBb2qacRUMtC7svLwe0lcw==" }, "inquirer": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/inquirer/-/inquirer-3.1.0.tgz", "integrity": "sha512-JLl89yPOEoGohLjeGs3XCekeovADbrEw/WRJQYgPED6zeJWrpIsY9i9/rn+VltZox/9w94lVYqo94QfEmniB1w==", - "dev": true, + "requires": { + "ansi-escapes": "2.0.0", + "chalk": "1.1.3", + "cli-cursor": "2.1.0", + "cli-width": "2.1.0", + "external-editor": "2.0.4", + "figures": "2.0.0", + "lodash": "4.17.4", + "mute-stream": "0.0.7", + "run-async": "2.3.0", + "rx-lite": "4.0.8", + "rx-lite-aggregates": "4.0.8", + "string-width": "2.0.0", + "strip-ansi": "3.0.1", + "through": "2.3.8" + }, "dependencies": { "ansi-escapes": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-2.0.0.tgz", - "integrity": "sha1-W65SvkJIeN2Xg+iRDj/Cki6DyBs=", - "dev": true + "integrity": "sha1-W65SvkJIeN2Xg+iRDj/Cki6DyBs=" }, "is-fullwidth-code-point": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", - "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=", - "dev": true + "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=" }, "string-width": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/string-width/-/string-width-2.0.0.tgz", "integrity": "sha1-Y1xUNsxypuDDh87KJ41OLuxSaH4=", - "dev": true + "requires": { + "is-fullwidth-code-point": "2.0.0", + "strip-ansi": "3.0.1" + } } } }, @@ -1128,10 +3813,24 @@ "integrity": "sha1-NK/2GaRep9MrsSKGap4xXucwM+g=", "dev": true }, + "interpret": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/interpret/-/interpret-1.1.0.tgz", + "integrity": "sha1-ftGxQQxqDg94z5XTuEQMY/eLhhQ=", + "dev": true + }, "invariant": { "version": "2.2.2", "resolved": "https://registry.npmjs.org/invariant/-/invariant-2.2.2.tgz", - "integrity": "sha1-nh9WrArNtr8wMwbzOL47IErmA2A=" + "integrity": "sha1-nh9WrArNtr8wMwbzOL47IErmA2A=", + "requires": { + "loose-envify": "1.3.1" + } + }, + "invert-kv": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/invert-kv/-/invert-kv-1.0.0.tgz", + "integrity": "sha1-EEqOSqym09jNFXqO+L+rLXo//bY=" }, "ip": { "version": "1.1.5", @@ -1142,121 +3841,241 @@ "ipaddr.js": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.3.0.tgz", - "integrity": "sha1-HgOlL9rYOou7KyXL9JmLTP/NPew=", - "dev": true + "integrity": "sha1-HgOlL9rYOou7KyXL9JmLTP/NPew=" }, "is-arrayish": { "version": "0.2.1", "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", - "integrity": "sha1-d8mYQFJ6qOyxqLppe4BkWnqSap0=", - "dev": true + "integrity": "sha1-d8mYQFJ6qOyxqLppe4BkWnqSap0=" }, "is-buffer": { "version": "1.1.5", "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.5.tgz", - "integrity": "sha1-Hzsm72E7IUuIy8ojzGwB2Hlh7sw=", - "dev": true + "integrity": "sha1-Hzsm72E7IUuIy8ojzGwB2Hlh7sw=" }, "is-builtin-module": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/is-builtin-module/-/is-builtin-module-1.0.0.tgz", "integrity": "sha1-VAVy0096wxGfj3bDDLwbHgN6/74=", + "requires": { + "builtin-modules": "1.1.1" + } + }, + "is-callable": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.1.3.tgz", + "integrity": "sha1-hut1OSgF3cM69xySoO7fdO52BLI=", + "dev": true + }, + "is-date-object": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.0.1.tgz", + "integrity": "sha1-mqIOtq7rv/d/vTPnTKAbM1gdOhY=", "dev": true }, "is-dotfile": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/is-dotfile/-/is-dotfile-1.0.3.tgz", - "integrity": "sha1-pqLzL/0t+wT1yiXs0Pa4PPeYoeE=", - "dev": true + "integrity": "sha1-pqLzL/0t+wT1yiXs0Pa4PPeYoeE=" }, "is-equal-shallow": { "version": "0.1.3", "resolved": "https://registry.npmjs.org/is-equal-shallow/-/is-equal-shallow-0.1.3.tgz", "integrity": "sha1-IjgJj8Ih3gvPpdnqxMRdY4qhxTQ=", - "dev": true + "requires": { + "is-primitive": "2.0.0" + } }, "is-extendable": { "version": "0.1.1", "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-0.1.1.tgz", - "integrity": "sha1-YrEQ4omkcUGOPsNqYX1HLjAd/Ik=", - "dev": true + "integrity": "sha1-YrEQ4omkcUGOPsNqYX1HLjAd/Ik=" }, "is-extglob": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-1.0.0.tgz", - "integrity": "sha1-rEaBd8SUNAWgkvyPKXYMb/xiBsA=", - "dev": true + "integrity": "sha1-rEaBd8SUNAWgkvyPKXYMb/xiBsA=" }, "is-finite": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/is-finite/-/is-finite-1.0.2.tgz", "integrity": "sha1-zGZ3aVYCvlUO8R6LSqYwU0K20Ko=", - "dev": true + "requires": { + "number-is-nan": "1.0.1" + } + }, + "is-fullwidth-code-point": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz", + "integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=", + "requires": { + "number-is-nan": "1.0.1" + } }, "is-glob": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-2.0.1.tgz", "integrity": "sha1-0Jb5JqPe1WAPP9/ZEZjLCIjC2GM=", - "dev": true + "requires": { + "is-extglob": "1.0.0" + } }, "is-lower-case": { "version": "1.1.3", "resolved": "https://registry.npmjs.org/is-lower-case/-/is-lower-case-1.1.3.tgz", "integrity": "sha1-fhR75HaNxGbbO/shzGCzHmrWk5M=", + "dev": true, + "requires": { + "lower-case": "1.1.4" + } + }, + "is-my-ip-valid": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-my-ip-valid/-/is-my-ip-valid-1.0.0.tgz", + "integrity": "sha512-gmh/eWXROncUzRnIa1Ubrt5b8ep/MGSnfAUI3aRp+sqTCs1tv1Isl8d8F6JmkN3dXKc3ehZMrtiPN9eL03NuaQ==", "dev": true }, + "is-my-json-valid": { + "version": "2.17.2", + "resolved": "https://registry.npmjs.org/is-my-json-valid/-/is-my-json-valid-2.17.2.tgz", + "integrity": "sha512-IBhBslgngMQN8DDSppmgDv7RNrlFotuuDsKcrCP3+HbFaVivIBU7u9oiiErw8sH4ynx3+gOGQ3q2otkgiSi6kg==", + "dev": true, + "requires": { + "generate-function": "2.0.0", + "generate-object-property": "1.2.0", + "is-my-ip-valid": "1.0.0", + "jsonpointer": "4.0.1", + "xtend": "4.0.1" + } + }, + "is-npm": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-npm/-/is-npm-1.0.0.tgz", + "integrity": "sha1-8vtjpl5JBbQGyGBydloaTceTufQ=" + }, "is-number": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/is-number/-/is-number-2.1.0.tgz", "integrity": "sha1-Afy7s5NGOlSPL0ZszhbezknbkI8=", + "requires": { + "kind-of": "3.2.2" + } + }, + "is-obj": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-obj/-/is-obj-1.0.1.tgz", + "integrity": "sha1-PkcprB9f3gJc19g6iW2rn09n2w8=" + }, + "is-path-cwd": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-path-cwd/-/is-path-cwd-1.0.0.tgz", + "integrity": "sha1-0iXsIxMuie3Tj9p2dHLmLmXxEG0=", "dev": true }, + "is-path-in-cwd": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-path-in-cwd/-/is-path-in-cwd-1.0.0.tgz", + "integrity": "sha1-ZHdYK4IU1gI0YJRWcAO+ip6sBNw=", + "dev": true, + "requires": { + "is-path-inside": "1.0.1" + } + }, + "is-path-inside": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-1.0.1.tgz", + "integrity": "sha1-jvW33lBDej/cprToZe96pVy0gDY=", + "dev": true, + "requires": { + "path-is-inside": "1.0.2" + } + }, "is-posix-bracket": { "version": "0.1.1", "resolved": "https://registry.npmjs.org/is-posix-bracket/-/is-posix-bracket-0.1.1.tgz", - "integrity": "sha1-MzTceXdDaOkvAW5vvAqI9c1ua8Q=", - "dev": true + "integrity": "sha1-MzTceXdDaOkvAW5vvAqI9c1ua8Q=" }, "is-primitive": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/is-primitive/-/is-primitive-2.0.0.tgz", - "integrity": "sha1-IHurkWOEmcB7Kt8kCkGochADRXU=", - "dev": true + "integrity": "sha1-IHurkWOEmcB7Kt8kCkGochADRXU=" }, "is-promise": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/is-promise/-/is-promise-2.1.0.tgz", - "integrity": "sha1-eaKp7OfwlugPNtKy87wWwf9L8/o=", + "integrity": "sha1-eaKp7OfwlugPNtKy87wWwf9L8/o=" + }, + "is-property": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-property/-/is-property-1.0.2.tgz", + "integrity": "sha1-V/4cTkhHTt1lsJkR8msc1Ald2oQ=", + "dev": true + }, + "is-redirect": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-redirect/-/is-redirect-1.0.0.tgz", + "integrity": "sha1-HQPd7VO9jbDzDCbk+V02/HyH3CQ=" + }, + "is-regex": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.0.4.tgz", + "integrity": "sha1-VRdIm1RwkbCTDglWVM7SXul+lJE=", + "dev": true, + "requires": { + "has": "1.0.1" + } + }, + "is-resolvable": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-resolvable/-/is-resolvable-1.1.0.tgz", + "integrity": "sha512-qgDYXFSR5WvEfuS5dMj6oTMEbrrSaM0CrFk2Yiq/gXnBvD9pMa2jGXxyhGLfvhZpuMZe18CJpFxAt3CRs42NMg==", "dev": true }, + "is-retry-allowed": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-retry-allowed/-/is-retry-allowed-1.1.0.tgz", + "integrity": "sha1-EaBgVotnM5REAz0BJaYaINVk+zQ=" + }, "is-stream": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-1.1.0.tgz", "integrity": "sha1-EtSj3U5o4Lec6428hBc66A2RykQ=" }, + "is-subset": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/is-subset/-/is-subset-0.1.1.tgz", + "integrity": "sha1-ilkRfZMt4d4A8kX83TnOQ/HpOaY=", + "dev": true + }, + "is-symbol": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.0.1.tgz", + "integrity": "sha1-PMWfAAJRlLarLjjbrmaJJWtmBXI=", + "dev": true + }, "is-typedarray": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz", - "integrity": "sha1-5HnICFjfDBsR3dppQPlgEfzaSpo=", - "dev": true + "integrity": "sha1-5HnICFjfDBsR3dppQPlgEfzaSpo=" }, "is-upper-case": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/is-upper-case/-/is-upper-case-1.1.2.tgz", "integrity": "sha1-jQsfp+eTOh5YSDYA7H2WYcuvdW8=", - "dev": true + "dev": true, + "requires": { + "upper-case": "1.1.3" + } }, "is-utf8": { "version": "0.2.1", "resolved": "https://registry.npmjs.org/is-utf8/-/is-utf8-0.2.1.tgz", - "integrity": "sha1-Sw2hRCEE0bM2NA6AeX6GXPOffXI=", - "dev": true + "integrity": "sha1-Sw2hRCEE0bM2NA6AeX6GXPOffXI=" }, "isarray": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", - "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", - "dev": true + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=" }, "isemail": { "version": "2.2.1", @@ -1267,25 +4086,29 @@ "isexe": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", - "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=", - "dev": true + "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=" }, "isobject": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/isobject/-/isobject-2.1.0.tgz", "integrity": "sha1-8GVWEJaj8dou9GJy+BXIQNh+DIk=", - "dev": true + "requires": { + "isarray": "1.0.0" + } }, "isomorphic-fetch": { "version": "2.2.1", "resolved": "https://registry.npmjs.org/isomorphic-fetch/-/isomorphic-fetch-2.2.1.tgz", - "integrity": "sha1-YRrhrPFPXoH3KVB0coGf6XM1WKk=" + "integrity": "sha1-YRrhrPFPXoH3KVB0coGf6XM1WKk=", + "requires": { + "node-fetch": "1.7.1", + "whatwg-fetch": "2.0.3" + } }, "isstream": { "version": "0.1.2", "resolved": "https://registry.npmjs.org/isstream/-/isstream-0.1.2.tgz", - "integrity": "sha1-R+Y/evVa+m+S4VAOaQ64uFKcCZo=", - "dev": true + "integrity": "sha1-R+Y/evVa+m+S4VAOaQ64uFKcCZo=" }, "istanbul-lib-coverage": { "version": "1.1.1", @@ -1297,7 +4120,16 @@ "version": "1.7.2", "resolved": "https://registry.npmjs.org/istanbul-lib-instrument/-/istanbul-lib-instrument-1.7.2.tgz", "integrity": "sha512-lPgUY+Pa5dlq2/l0qs1PJZ54QPSfo+s4+UZdkb2d0hbOyrEIAbUJphBLFjEyXBdeCONgGRADFzs3ojfFtmuwFA==", - "dev": true + "dev": true, + "requires": { + "babel-generator": "6.25.0", + "babel-template": "6.25.0", + "babel-traverse": "6.25.0", + "babel-types": "6.25.0", + "babylon": "6.17.3", + "istanbul-lib-coverage": "1.1.1", + "semver": "5.3.0" + } }, "items": { "version": "2.1.1", @@ -1310,26 +4142,109 @@ "resolved": "https://registry.npmjs.org/jest/-/jest-19.0.2.tgz", "integrity": "sha1-t5T6r4/0Yec4jyi+71WaVPILLBA=", "dev": true, + "requires": { + "jest-cli": "19.0.2" + }, "dependencies": { "jest-cli": { "version": "19.0.2", "resolved": "https://registry.npmjs.org/jest-cli/-/jest-cli-19.0.2.tgz", "integrity": "sha1-zDYgtirKxfLZOlSMtu9pfU7IVEM=", - "dev": true + "dev": true, + "requires": { + "chalk": "1.1.3", + "graceful-fs": "4.1.11", + "istanbul-lib-coverage": "1.1.1", + "istanbul-lib-instrument": "1.7.2", + "micromatch": "2.3.11", + "slash": "1.0.0", + "throat": "3.2.0", + "which": "1.2.14", + "worker-farm": "1.5.4", + "yargs": "6.6.0" + } } } }, + "jest-docblock": { + "version": "20.0.3", + "resolved": "https://registry.npmjs.org/jest-docblock/-/jest-docblock-20.0.3.tgz", + "integrity": "sha1-F76phDQswz2DxQ++FUXqDvqkRxI=" + }, "jest-expo": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/jest-expo/-/jest-expo-1.0.2.tgz", "integrity": "sha1-OAY710rr6gRZVfzzpJlWIlqXBi4=", - "dev": true + "dev": true, + "requires": { + "babel-jest": "19.0.0", + "jest": "19.0.2", + "react-test-renderer": "16.0.0-alpha.6" + } + }, + "jest-haste-map": { + "version": "20.0.5", + "resolved": "https://registry.npmjs.org/jest-haste-map/-/jest-haste-map-20.0.5.tgz", + "integrity": "sha512-0IKAQjUvuZjMCNi/0VNQQF74/H9KB67hsHJqGiwTWQC6XO5Azs7kLWm+6Q/dwuhvDUvABDOBMFK2/FwZ3sZ07Q==", + "requires": { + "fb-watchman": "2.0.0", + "graceful-fs": "4.1.11", + "jest-docblock": "20.0.3", + "micromatch": "2.3.11", + "sane": "1.6.0", + "worker-farm": "1.5.4" + }, + "dependencies": { + "bser": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/bser/-/bser-1.0.2.tgz", + "integrity": "sha1-OBEWlwsqbe6lZG3RXdcnhES1YWk=", + "requires": { + "node-int64": "0.4.0" + } + }, + "sane": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/sane/-/sane-1.6.0.tgz", + "integrity": "sha1-lhDEUjB6E10pwf3+JUcDQYDEZ3U=", + "requires": { + "anymatch": "1.3.2", + "exec-sh": "0.2.1", + "fb-watchman": "1.9.2", + "minimatch": "3.0.4", + "minimist": "0.0.8", + "walker": "1.0.7", + "watch": "0.10.0" + }, + "dependencies": { + "fb-watchman": { + "version": "1.9.2", + "resolved": "https://registry.npmjs.org/fb-watchman/-/fb-watchman-1.9.2.tgz", + "integrity": "sha1-okz0eCf4LTj7Waaa1wt247auc4M=", + "requires": { + "bser": "1.0.2" + } + } + } + } + } + }, + "jju": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/jju/-/jju-1.3.0.tgz", + "integrity": "sha1-2t2e8BkkvHKLA/L3l5vb1i96Kqo=" }, "joi": { "version": "10.5.2", "resolved": "https://registry.npmjs.org/joi/-/joi-10.5.2.tgz", "integrity": "sha512-Do/NXTokq86nvFfggE4UbwNnyzvALn3Ay+gMwQSAkrQoWTYc4LvkabhypVZiqDZq0TbtVhUpOphe4dmKB6/Pxg==", "dev": true, + "requires": { + "hoek": "4.1.1", + "isemail": "2.2.1", + "items": "2.1.1", + "topo": "2.0.2" + }, "dependencies": { "hoek": { "version": "4.1.1", @@ -1350,30 +4265,36 @@ "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-3.0.1.tgz", "integrity": "sha1-COnxMkhKLEWjCQfp3E1VZ7fxFNc=" }, + "js-yaml": { + "version": "3.10.0", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.10.0.tgz", + "integrity": "sha512-O2v52ffjLa9VeM43J4XocZE//WT9N0IiwDa3KSHH7Tu8CtH+1qM8SIZvnsTh6v+4yFy5KUY3BHUVwjpfAWsjIA==", + "dev": true, + "requires": { + "argparse": "1.0.10", + "esprima": "4.0.0" + } + }, "jsan": { "version": "3.1.9", "resolved": "https://registry.npmjs.org/jsan/-/jsan-3.1.9.tgz", - "integrity": "sha1-JwVnbBBY8KfZrCZq0Daldpz6fJY=", - "dev": true + "integrity": "sha1-JwVnbBBY8KfZrCZq0Daldpz6fJY=" }, "jsbn": { "version": "0.1.1", "resolved": "https://registry.npmjs.org/jsbn/-/jsbn-0.1.1.tgz", "integrity": "sha1-peZUwuWi3rXyAdls77yoDA7y9RM=", - "dev": true, "optional": true }, "jschardet": { "version": "1.4.2", "resolved": "https://registry.npmjs.org/jschardet/-/jschardet-1.4.2.tgz", - "integrity": "sha1-KqEH8UKvQSHRRWWdRPUIMJYeaZo=", - "dev": true + "integrity": "sha1-KqEH8UKvQSHRRWWdRPUIMJYeaZo=" }, "jsesc": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-1.3.0.tgz", - "integrity": "sha1-RsP+yMGJKxKwgz25vHYiF226s0s=", - "dev": true + "integrity": "sha1-RsP+yMGJKxKwgz25vHYiF226s0s=" }, "json-fallback": { "version": "0.0.1", @@ -1381,46 +4302,90 @@ "integrity": "sha1-6OMIPD/drQ+bXwnTMSB0RCWA14E=", "dev": true }, + "json-parse-helpfulerror": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/json-parse-helpfulerror/-/json-parse-helpfulerror-1.0.3.tgz", + "integrity": "sha1-E/FM4C7tTpgSl7ZOueO5MuLdE9w=", + "requires": { + "jju": "1.3.0" + } + }, "json-schema": { "version": "0.2.3", "resolved": "https://registry.npmjs.org/json-schema/-/json-schema-0.2.3.tgz", - "integrity": "sha1-tIDIkuWaLwWVTOcnvT8qTogvnhM=", - "dev": true + "integrity": "sha1-tIDIkuWaLwWVTOcnvT8qTogvnhM=" + }, + "json-server": { + "version": "0.10.3", + "resolved": "https://registry.npmjs.org/json-server/-/json-server-0.10.3.tgz", + "integrity": "sha512-hkt6xIWC/b8GqzE2qf4JTKCtDByVLbfPDkMglQlTjGlaJnA8oVoO2XGHmfxHZe3oOu8qRW/mqolvUIH2BwemkQ==", + "requires": { + "body-parser": "1.17.2", + "chalk": "1.1.3", + "compression": "1.7.2", + "connect-pause": "0.1.0", + "cors": "2.8.4", + "errorhandler": "1.5.0", + "express": "4.15.3", + "json-parse-helpfulerror": "1.0.3", + "lodash": "4.17.4", + "lodash-id": "0.13.0", + "lowdb": "0.15.5", + "method-override": "2.3.10", + "morgan": "1.9.0", + "object-assign": "4.1.1", + "pluralize": "3.1.0", + "request": "2.81.0", + "server-destroy": "1.0.1", + "shortid": "2.2.8", + "update-notifier": "1.0.3", + "yargs": "6.6.0" + } }, "json-stable-stringify": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/json-stable-stringify/-/json-stable-stringify-1.0.1.tgz", "integrity": "sha1-mnWdOcXy/1A/1TAGRu1EX4jE+a8=", - "dev": true + "requires": { + "jsonify": "0.0.0" + } }, "json-stringify-safe": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz", - "integrity": "sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus=", - "dev": true + "integrity": "sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus=" }, "json5": { "version": "0.5.1", "resolved": "https://registry.npmjs.org/json5/-/json5-0.5.1.tgz", - "integrity": "sha1-Hq3nrMASA0rYTiOWdn6tn6VJWCE=", - "dev": true + "integrity": "sha1-Hq3nrMASA0rYTiOWdn6tn6VJWCE=" }, "jsonfile": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-3.0.0.tgz", "integrity": "sha1-kufHRE5f/V+jLmqa6LhQNN+DR9A=", - "dev": true + "requires": { + "graceful-fs": "4.1.11" + } }, "jsonify": { "version": "0.0.0", "resolved": "https://registry.npmjs.org/jsonify/-/jsonify-0.0.0.tgz", - "integrity": "sha1-LHS27kHZPKUbe1qu6PUDYx0lKnM=", - "dev": true + "integrity": "sha1-LHS27kHZPKUbe1qu6PUDYx0lKnM=" }, "jsonp": { "version": "0.0.4", "resolved": "https://registry.npmjs.org/jsonp/-/jsonp-0.0.4.tgz", "integrity": "sha1-lGZaS3caq+y4qshBNbmVlHVpGL0=", + "dev": true, + "requires": { + "debug": "2.6.8" + } + }, + "jsonpointer": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/jsonpointer/-/jsonpointer-4.0.1.tgz", + "integrity": "sha1-T9kss04OnbPInIYi7PUfm5eMbLk=", "dev": true }, "jsonschema": { @@ -1434,6 +4399,13 @@ "resolved": "https://registry.npmjs.org/jsonwebtoken/-/jsonwebtoken-7.4.1.tgz", "integrity": "sha1-fKMk9SFfi+A5zTWmxFu4y3SkSPs=", "dev": true, + "requires": { + "joi": "6.10.1", + "jws": "3.1.4", + "lodash.once": "4.1.1", + "ms": "2.0.0", + "xtend": "4.0.1" + }, "dependencies": { "isemail": { "version": "1.2.0", @@ -1445,13 +4417,22 @@ "version": "6.10.1", "resolved": "https://registry.npmjs.org/joi/-/joi-6.10.1.tgz", "integrity": "sha1-TVDDGAeRIgAP5fFq8f+OGRe3fgY=", - "dev": true + "dev": true, + "requires": { + "hoek": "2.16.3", + "isemail": "1.2.0", + "moment": "2.18.1", + "topo": "1.1.0" + } }, "topo": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/topo/-/topo-1.1.0.tgz", "integrity": "sha1-6ddRYV0buH3IZdsYL6HKCl71NtU=", - "dev": true + "dev": true, + "requires": { + "hoek": "2.16.3" + } } } }, @@ -1459,78 +4440,432 @@ "version": "1.4.0", "resolved": "https://registry.npmjs.org/jsprim/-/jsprim-1.4.0.tgz", "integrity": "sha1-o7h+QCmNjDgFUtjMdiigu5WiKRg=", - "dev": true, + "requires": { + "assert-plus": "1.0.0", + "extsprintf": "1.0.2", + "json-schema": "0.2.3", + "verror": "1.3.6" + }, "dependencies": { "assert-plus": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", - "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=", - "dev": true + "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=" } } }, + "jsx-ast-utils": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/jsx-ast-utils/-/jsx-ast-utils-1.4.1.tgz", + "integrity": "sha1-OGchPo3Xm/Ho8jAMDPwe+xgsDfE=", + "dev": true + }, "jwa": { "version": "1.1.5", "resolved": "https://registry.npmjs.org/jwa/-/jwa-1.1.5.tgz", "integrity": "sha1-oFUs4CIHQs1S4VN3SjKQXDDnVuU=", - "dev": true + "dev": true, + "requires": { + "base64url": "2.0.0", + "buffer-equal-constant-time": "1.0.1", + "ecdsa-sig-formatter": "1.0.9", + "safe-buffer": "5.1.0" + } }, "jws": { "version": "3.1.4", "resolved": "https://registry.npmjs.org/jws/-/jws-3.1.4.tgz", "integrity": "sha1-+ei5M46KhHJ31kRLFGT2GIDgUKI=", - "dev": true + "dev": true, + "requires": { + "base64url": "2.0.0", + "jwa": "1.1.5", + "safe-buffer": "5.1.0" + } }, "kind-of": { "version": "3.2.2", "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "dev": true + "requires": { + "is-buffer": "1.1.5" + } + }, + "latest-version": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/latest-version/-/latest-version-2.0.0.tgz", + "integrity": "sha1-VvjWE5YghHuAF/jx9NeOIRMkFos=", + "requires": { + "package-json": "2.4.0" + } + }, + "lazy-cache": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/lazy-cache/-/lazy-cache-1.0.4.tgz", + "integrity": "sha1-odePw6UEdMuAhF07O24dpJpEbo4=" + }, + "lazy-req": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/lazy-req/-/lazy-req-1.1.0.tgz", + "integrity": "sha1-va6+rTD42CQDnODOFJ1Nqge6H6w=" + }, + "lcid": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/lcid/-/lcid-1.0.0.tgz", + "integrity": "sha1-MIrMr6C8SDo4Z7S28rlQYlHRuDU=", + "requires": { + "invert-kv": "1.0.0" + } + }, + "left-pad": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/left-pad/-/left-pad-1.2.0.tgz", + "integrity": "sha1-0wpzxrggHY99jnlWupYWCHpo4O4=" + }, + "levn": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/levn/-/levn-0.3.0.tgz", + "integrity": "sha1-OwmSTt+fCDwEkP3UwLxEIeBHZO4=", + "dev": true, + "requires": { + "prelude-ls": "1.1.2", + "type-check": "0.3.2" + } }, "linked-list": { "version": "0.1.0", "resolved": "https://registry.npmjs.org/linked-list/-/linked-list-0.1.0.tgz", - "integrity": "sha1-eYsP+X0bkqT9CEgPVa6k6dSdN78=", + "integrity": "sha1-eYsP+X0bkqT9CEgPVa6k6dSdN78=" + }, + "load-json-file": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-1.1.0.tgz", + "integrity": "sha1-lWkFcI1YtLq0wiYbBPWfMcmTdMA=", + "requires": { + "graceful-fs": "4.1.11", + "parse-json": "2.2.0", + "pify": "2.3.0", + "pinkie-promise": "2.0.1", + "strip-bom": "2.0.0" + } + }, + "locate-path": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-2.0.0.tgz", + "integrity": "sha1-K1aLJl7slExtnA3pw9u7ygNUzY4=", + "dev": true, + "requires": { + "p-locate": "2.0.0", + "path-exists": "3.0.0" + } + }, + "lock": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/lock/-/lock-0.1.3.tgz", + "integrity": "sha1-9mwcqgxBlW4UJmCAOe1ZtxvfGFQ=", + "dev": true + }, + "lodash": { + "version": "4.17.4", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.4.tgz", + "integrity": "sha1-eCA6TRwyiuHYbcpkYONptX9AVa4=" + }, + "lodash-es": { + "version": "4.17.4", + "resolved": "https://registry.npmjs.org/lodash-es/-/lodash-es-4.17.4.tgz", + "integrity": "sha1-3MHXVS4VCgZABzupyzHXDwMpUOc=" + }, + "lodash-id": { + "version": "0.13.0", + "resolved": "https://registry.npmjs.org/lodash-id/-/lodash-id-0.13.0.tgz", + "integrity": "sha1-GyCGwk8ATwdBG9sJt3UHIRS83cY=" + }, + "lodash._basecopy": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/lodash._basecopy/-/lodash._basecopy-3.0.1.tgz", + "integrity": "sha1-jaDmqHbPNEwK2KVIghEd08XHyjY=" + }, + "lodash._basetostring": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/lodash._basetostring/-/lodash._basetostring-3.0.1.tgz", + "integrity": "sha1-0YYdh3+CSlL2aYMtyvPuFVZqB9U=" + }, + "lodash._basevalues": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/lodash._basevalues/-/lodash._basevalues-3.0.0.tgz", + "integrity": "sha1-W3dXYoAr3j0yl1A+JjAIIP32Ybc=" + }, + "lodash._getnative": { + "version": "3.9.1", + "resolved": "https://registry.npmjs.org/lodash._getnative/-/lodash._getnative-3.9.1.tgz", + "integrity": "sha1-VwvH3t5G1hzc3mh9ZdPuy6o6r/U=" + }, + "lodash._isiterateecall": { + "version": "3.0.9", + "resolved": "https://registry.npmjs.org/lodash._isiterateecall/-/lodash._isiterateecall-3.0.9.tgz", + "integrity": "sha1-UgOte6Ql+uhCRg5pbbnPPmqsBXw=" + }, + "lodash._reescape": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/lodash._reescape/-/lodash._reescape-3.0.0.tgz", + "integrity": "sha1-Kx1vXf4HyKNVdT5fJ/rH8c3hYWo=" + }, + "lodash._reevaluate": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/lodash._reevaluate/-/lodash._reevaluate-3.0.0.tgz", + "integrity": "sha1-WLx0xAZklTrgsSTYBpltrKQx4u0=" + }, + "lodash._reinterpolate": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/lodash._reinterpolate/-/lodash._reinterpolate-3.0.0.tgz", + "integrity": "sha1-DM8tiRZq8Ds2Y8eWU4t1rG4RTZ0=" + }, + "lodash._root": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/lodash._root/-/lodash._root-3.0.1.tgz", + "integrity": "sha1-+6HEUkwZ7ppfgTa0YJ8BfPTe1pI=" + }, + "lodash.assignin": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/lodash.assignin/-/lodash.assignin-4.2.0.tgz", + "integrity": "sha1-uo31+4QesKPoBEIysOJjqNxqKKI=", + "dev": true + }, + "lodash.bind": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/lodash.bind/-/lodash.bind-4.2.1.tgz", + "integrity": "sha1-euMBfpOWIqwxt9fX3LGzTbFpDTU=", + "dev": true + }, + "lodash.cond": { + "version": "4.5.2", + "resolved": "https://registry.npmjs.org/lodash.cond/-/lodash.cond-4.5.2.tgz", + "integrity": "sha1-9HGh2khr5g9quVXRcRVSPdHSVdU=", + "dev": true + }, + "lodash.defaults": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/lodash.defaults/-/lodash.defaults-4.2.0.tgz", + "integrity": "sha1-0JF4cW/+pN3p5ft7N/bwgCJ0WAw=", + "dev": true + }, + "lodash.escape": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/lodash.escape/-/lodash.escape-3.2.0.tgz", + "integrity": "sha1-mV7g3BjBtIzJLv+ucaEKq1tIdpg=", + "requires": { + "lodash._root": "3.0.1" + } + }, + "lodash.filter": { + "version": "4.6.0", + "resolved": "https://registry.npmjs.org/lodash.filter/-/lodash.filter-4.6.0.tgz", + "integrity": "sha1-ZosdSYFgOuHMWm+nYBQ+SAtMSs4=", + "dev": true + }, + "lodash.flatten": { + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/lodash.flatten/-/lodash.flatten-4.4.0.tgz", + "integrity": "sha1-8xwiIlqWMtK7+OSt2+8kCqdlph8=", + "dev": true + }, + "lodash.foreach": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/lodash.foreach/-/lodash.foreach-4.5.0.tgz", + "integrity": "sha1-Gmo16s5AEoDH8G3d7DUWWrJ+PlM=", + "dev": true + }, + "lodash.forin": { + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/lodash.forin/-/lodash.forin-4.4.0.tgz", + "integrity": "sha1-XT8grlZAEfvog4H32YlJyclRlzE=" + }, + "lodash.get": { + "version": "4.4.2", + "resolved": "https://registry.npmjs.org/lodash.get/-/lodash.get-4.4.2.tgz", + "integrity": "sha1-LRd/ZS+jHpObRDjVNBSZ36OCXpk=" + }, + "lodash.isarguments": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/lodash.isarguments/-/lodash.isarguments-3.1.0.tgz", + "integrity": "sha1-L1c9hcaiQon/AGY7SRwdM4/zRYo=" + }, + "lodash.isarray": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/lodash.isarray/-/lodash.isarray-3.0.4.tgz", + "integrity": "sha1-eeTriMNqgSKvhvhEqpvNhRtfu1U=" + }, + "lodash.isempty": { + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/lodash.isempty/-/lodash.isempty-4.4.0.tgz", + "integrity": "sha1-b4bL7di+TsmHvpqvM8loTbGzHn4=" + }, + "lodash.keys": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/lodash.keys/-/lodash.keys-3.1.2.tgz", + "integrity": "sha1-TbwEcrFWvlCgsoaFXRvQsMZWCYo=", + "requires": { + "lodash._getnative": "3.9.1", + "lodash.isarguments": "3.1.0", + "lodash.isarray": "3.0.4" + } + }, + "lodash.map": { + "version": "4.6.0", + "resolved": "https://registry.npmjs.org/lodash.map/-/lodash.map-4.6.0.tgz", + "integrity": "sha1-dx7Hg540c9nEzeKLGTlMNWL09tM=" + }, + "lodash.merge": { + "version": "4.6.1", + "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.1.tgz", + "integrity": "sha512-AOYza4+Hf5z1/0Hztxpm2/xiPZgi/cjMqdnKTUWTBSKchJlxXXuUSxCCl8rJlf4g6yww/j6mA8nC8Hw/EZWxKQ==", + "dev": true + }, + "lodash.once": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/lodash.once/-/lodash.once-4.1.1.tgz", + "integrity": "sha1-DdOXEhPHxW34gJd9UEyI+0cal6w=", "dev": true }, - "load-json-file": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-1.1.0.tgz", - "integrity": "sha1-lWkFcI1YtLq0wiYbBPWfMcmTdMA=", + "lodash.pad": { + "version": "4.5.1", + "resolved": "https://registry.npmjs.org/lodash.pad/-/lodash.pad-4.5.1.tgz", + "integrity": "sha1-QzCUmoM6fI2iLMIPaibE1Z3runA=" + }, + "lodash.padend": { + "version": "4.6.1", + "resolved": "https://registry.npmjs.org/lodash.padend/-/lodash.padend-4.6.1.tgz", + "integrity": "sha1-U8y6BH0G4VjTEfRdpiX05J5vFm4=" + }, + "lodash.padstart": { + "version": "4.6.1", + "resolved": "https://registry.npmjs.org/lodash.padstart/-/lodash.padstart-4.6.1.tgz", + "integrity": "sha1-0uPuv/DZ05rVD1y9G1KnvOa7YRs=" + }, + "lodash.pick": { + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/lodash.pick/-/lodash.pick-4.4.0.tgz", + "integrity": "sha1-UvBWEP/53tQiYRRB7R/BI6AwAbM=", "dev": true }, - "locate-path": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-2.0.0.tgz", - "integrity": "sha1-K1aLJl7slExtnA3pw9u7ygNUzY4=", + "lodash.pickby": { + "version": "4.6.0", + "resolved": "https://registry.npmjs.org/lodash.pickby/-/lodash.pickby-4.6.0.tgz", + "integrity": "sha1-feoh2MGNdwOifHBMFdO4SmfjOv8=" + }, + "lodash.reduce": { + "version": "4.6.0", + "resolved": "https://registry.npmjs.org/lodash.reduce/-/lodash.reduce-4.6.0.tgz", + "integrity": "sha1-8atrg5KZrUj3hKu/R2WW8DuRTTs=", "dev": true }, - "lock": { - "version": "0.1.3", - "resolved": "https://registry.npmjs.org/lock/-/lock-0.1.3.tgz", - "integrity": "sha1-9mwcqgxBlW4UJmCAOe1ZtxvfGFQ=", + "lodash.reject": { + "version": "4.6.0", + "resolved": "https://registry.npmjs.org/lodash.reject/-/lodash.reject-4.6.0.tgz", + "integrity": "sha1-gNZJLcFHCGS79YNTO2UfQqn1JBU=", "dev": true }, - "lodash": { - "version": "4.17.4", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.4.tgz", - "integrity": "sha1-eCA6TRwyiuHYbcpkYONptX9AVa4=" + "lodash.restparam": { + "version": "3.6.1", + "resolved": "https://registry.npmjs.org/lodash.restparam/-/lodash.restparam-3.6.1.tgz", + "integrity": "sha1-k2pOMJ7zMKdkXtQUWYbIWuWyCAU=" }, - "lodash-es": { - "version": "4.17.4", - "resolved": "https://registry.npmjs.org/lodash-es/-/lodash-es-4.17.4.tgz", - "integrity": "sha1-3MHXVS4VCgZABzupyzHXDwMpUOc=" + "lodash.set": { + "version": "4.3.2", + "resolved": "https://registry.npmjs.org/lodash.set/-/lodash.set-4.3.2.tgz", + "integrity": "sha1-2HV7HagH3eJIFrDWqEvqGnYjCyM=" }, - "lodash.once": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/lodash.once/-/lodash.once-4.1.1.tgz", - "integrity": "sha1-DdOXEhPHxW34gJd9UEyI+0cal6w=", + "lodash.some": { + "version": "4.6.0", + "resolved": "https://registry.npmjs.org/lodash.some/-/lodash.some-4.6.0.tgz", + "integrity": "sha1-G7nzFO9ri63tE7VJFpsqlF62jk0=", + "dev": true + }, + "lodash.template": { + "version": "3.6.2", + "resolved": "https://registry.npmjs.org/lodash.template/-/lodash.template-3.6.2.tgz", + "integrity": "sha1-+M3sxhaaJVvpCYrosMU9N4kx0U8=", + "requires": { + "lodash._basecopy": "3.0.1", + "lodash._basetostring": "3.0.1", + "lodash._basevalues": "3.0.0", + "lodash._isiterateecall": "3.0.9", + "lodash._reinterpolate": "3.0.0", + "lodash.escape": "3.2.0", + "lodash.keys": "3.1.2", + "lodash.restparam": "3.6.1", + "lodash.templatesettings": "3.1.1" + } + }, + "lodash.templatesettings": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/lodash.templatesettings/-/lodash.templatesettings-3.1.1.tgz", + "integrity": "sha1-+zB4RHU7Zrnxr6VOJix0UwfbqOU=", + "requires": { + "lodash._reinterpolate": "3.0.0", + "lodash.escape": "3.2.0" + } + }, + "lodash.times": { + "version": "4.3.2", + "resolved": "https://registry.npmjs.org/lodash.times/-/lodash.times-4.3.2.tgz", + "integrity": "sha1-Ph8lZcQxdU1Uq1fy7RdBk5KFyh0=" + }, + "lodash.unset": { + "version": "4.5.2", + "resolved": "https://registry.npmjs.org/lodash.unset/-/lodash.unset-4.5.2.tgz", + "integrity": "sha1-Nw0dPoW3Kn4bDN8tJyEhMG8j5O0=" + }, + "lodash.zipobject": { + "version": "4.1.3", + "resolved": "https://registry.npmjs.org/lodash.zipobject/-/lodash.zipobject-4.1.3.tgz", + "integrity": "sha1-s5n1q6j/YqdG9peb8gshT5ZNvvg=" + }, + "lolex": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/lolex/-/lolex-1.6.0.tgz", + "integrity": "sha1-OpoCg0UqR9dDnnJzG54H1zhuSfY=", "dev": true }, + "longest": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/longest/-/longest-1.0.1.tgz", + "integrity": "sha1-MKCy2jj3N3DoKUoNIuZiXtd9AJc=" + }, "loose-envify": { "version": "1.3.1", "resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.3.1.tgz", - "integrity": "sha1-0aitM/qc4OcT1l/dCsi3SNR4yEg=" + "integrity": "sha1-0aitM/qc4OcT1l/dCsi3SNR4yEg=", + "requires": { + "js-tokens": "3.0.1" + } + }, + "lottie-ios": { + "version": "1.5.2", + "resolved": "https://registry.npmjs.org/lottie-ios/-/lottie-ios-1.5.2.tgz", + "integrity": "sha1-wYjxuqHDCKKRU4/FhaduDPwGBxE=" + }, + "lottie-react-native": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/lottie-react-native/-/lottie-react-native-1.1.1.tgz", + "integrity": "sha1-HIejr8qW7foIaSJxQKLP+bzGLJs=", + "requires": { + "invariant": "2.2.2", + "lottie-ios": "1.5.2", + "react-native-safe-module": "1.2.0" + } + }, + "lowdb": { + "version": "0.15.5", + "resolved": "https://registry.npmjs.org/lowdb/-/lowdb-0.15.5.tgz", + "integrity": "sha1-mt4QXfiqVzaS0SIWIrhUFPv0+pY=", + "requires": { + "graceful-fs": "4.1.11", + "is-promise": "2.1.0", + "json-parse-helpfulerror": "1.0.3", + "lodash": "4.17.4", + "steno": "0.4.4" + } }, "lower-case": { "version": "1.1.4", @@ -1542,19 +4877,49 @@ "version": "1.0.2", "resolved": "https://registry.npmjs.org/lower-case-first/-/lower-case-first-1.0.2.tgz", "integrity": "sha1-5dp8JvKacHO+AtUrrJmA5ZIq36E=", - "dev": true + "dev": true, + "requires": { + "lower-case": "1.1.4" + } + }, + "lowercase-keys": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/lowercase-keys/-/lowercase-keys-1.0.0.tgz", + "integrity": "sha1-TjNms55/VFfjXxMkvfb4jQv8cwY=" }, "lru-cache": { "version": "4.1.1", "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-4.1.1.tgz", "integrity": "sha512-q4spe4KTfsAS1SUHLO0wz8Qiyf1+vMIAgpRYioFYDMNqKfHQbg+AVDH3i4fvpl71/P1L0dBl+fQi+P37UYf0ew==", - "dev": true + "requires": { + "pseudomap": "1.0.2", + "yallist": "2.1.2" + } + }, + "makeerror": { + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/makeerror/-/makeerror-1.0.11.tgz", + "integrity": "sha1-4BpckQnyr3lmDk6LlYd5AYT1qWw=", + "requires": { + "tmpl": "1.0.4" + } }, "match-require": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/match-require/-/match-require-2.1.0.tgz", "integrity": "sha1-9n1ixMsdcD9Aj7Y7Vbmug/sl4sw=", - "dev": true + "dev": true, + "requires": { + "uuid": "3.0.1" + } + }, + "md5-file": { + "version": "3.2.3", + "resolved": "https://registry.npmjs.org/md5-file/-/md5-file-3.2.3.tgz", + "integrity": "sha512-3Tkp1piAHaworfcCgH0jKbTvj1jWWFgbvh2cXaNCgHwyTCBxxvD1Y04rmfpvdPm1P4oXMOpm6+2H7sr7v9v8Fw==", + "requires": { + "buffer-alloc": "1.1.0" + } }, "md5hex": { "version": "1.0.0", @@ -1565,74 +4930,163 @@ "media-typer": { "version": "0.3.0", "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", - "integrity": "sha1-hxDXrwqmJvj/+hzgAWhUUmMlV0g=", - "dev": true + "integrity": "sha1-hxDXrwqmJvj/+hzgAWhUUmMlV0g=" + }, + "merge": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/merge/-/merge-1.2.0.tgz", + "integrity": "sha1-dTHjnUlJwoGma4xabgJl6LBYlNo=" }, "merge-descriptors": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.1.tgz", - "integrity": "sha1-sAqqVW3YtEVoFQ7J0blT8/kMu2E=", - "dev": true + "integrity": "sha1-sAqqVW3YtEVoFQ7J0blT8/kMu2E=" + }, + "merge-stream": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-1.0.1.tgz", + "integrity": "sha1-QEEgLVCKNCugAXQAjfDCUbjBNeE=", + "requires": { + "readable-stream": "1.1.14" + } + }, + "method-override": { + "version": "2.3.10", + "resolved": "https://registry.npmjs.org/method-override/-/method-override-2.3.10.tgz", + "integrity": "sha1-49r41d7hDdLc59SuiNYrvud0drQ=", + "requires": { + "debug": "2.6.8", + "methods": "1.1.2", + "parseurl": "1.3.1", + "vary": "1.1.1" + } }, "methods": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz", - "integrity": "sha1-VSmk1nZUE07cxSZmVoNbD4Ua/O4=", - "dev": true + "integrity": "sha1-VSmk1nZUE07cxSZmVoNbD4Ua/O4=" + }, + "metro-bundler": { + "version": "0.7.8", + "resolved": "https://registry.npmjs.org/metro-bundler/-/metro-bundler-0.7.8.tgz", + "integrity": "sha512-6djvyY3giKujmgnC+n3HgPQ7/tREwtSv7T1puCsA9Ourz+A2VjgeYa4HBTs1IPWYQYWucjBWzA8F7EJc0voMyg==", + "requires": { + "absolute-path": "0.0.0", + "async": "2.6.0", + "babel-core": "6.25.0", + "babel-generator": "6.25.0", + "babel-plugin-external-helpers": "6.22.0", + "babel-preset-es2015-node": "6.1.1", + "babel-preset-fbjs": "2.1.4", + "babel-preset-react-native": "1.9.2", + "babel-register": "6.24.1", + "babylon": "6.17.3", + "chalk": "1.1.3", + "concat-stream": "1.6.0", + "core-js": "2.4.1", + "debug": "2.6.8", + "denodeify": "1.2.1", + "fbjs": "0.8.12", + "graceful-fs": "4.1.11", + "image-size": "0.3.5", + "jest-haste-map": "20.0.5", + "json-stable-stringify": "1.0.1", + "json5": "0.5.1", + "left-pad": "1.2.0", + "lodash": "4.17.4", + "merge-stream": "1.0.1", + "mime-types": "2.1.15", + "mkdirp": "0.5.1", + "request": "2.81.0", + "rimraf": "2.6.1", + "source-map": "0.5.6", + "temp": "0.8.3", + "throat": "3.2.0", + "uglify-js": "2.7.5", + "write-file-atomic": "1.3.4", + "xpipe": "1.0.5" + } }, "micromatch": { "version": "2.3.11", "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-2.3.11.tgz", "integrity": "sha1-hmd8l9FyCzY0MdBNDRUpO9OMFWU=", - "dev": true + "requires": { + "arr-diff": "2.0.0", + "array-unique": "0.2.1", + "braces": "1.8.5", + "expand-brackets": "0.1.5", + "extglob": "0.3.2", + "filename-regex": "2.0.1", + "is-extglob": "1.0.0", + "is-glob": "2.0.1", + "kind-of": "3.2.2", + "normalize-path": "2.1.1", + "object.omit": "2.0.1", + "parse-glob": "3.0.4", + "regex-cache": "0.4.3" + } }, "mime": { "version": "1.3.6", "resolved": "https://registry.npmjs.org/mime/-/mime-1.3.6.tgz", - "integrity": "sha1-WR2E02U6awtKO5343lqoEI5y5eA=", - "dev": true + "integrity": "sha1-WR2E02U6awtKO5343lqoEI5y5eA=" }, "mime-db": { "version": "1.27.0", "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.27.0.tgz", - "integrity": "sha1-gg9XIpa70g7CXtVeW13oaeVDbrE=", - "dev": true + "integrity": "sha1-gg9XIpa70g7CXtVeW13oaeVDbrE=" }, "mime-types": { "version": "2.1.15", "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.15.tgz", "integrity": "sha1-pOv1BkCUVpI3uM9wBGd20J/JKu0=", - "dev": true + "requires": { + "mime-db": "1.27.0" + } }, "mimic-fn": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-1.1.0.tgz", - "integrity": "sha1-5md4PZLonb00KBi1IwudYqZyrRg=", - "dev": true + "integrity": "sha1-5md4PZLonb00KBi1IwudYqZyrRg=" + }, + "min-document": { + "version": "2.19.0", + "resolved": "https://registry.npmjs.org/min-document/-/min-document-2.19.0.tgz", + "integrity": "sha1-e9KC4/WELtKVu3SM3Z8f+iyCRoU=", + "requires": { + "dom-walk": "0.1.1" + } }, "minimatch": { "version": "3.0.4", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", - "dev": true + "requires": { + "brace-expansion": "1.1.8" + } }, "minimist": { "version": "0.0.8", "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz", - "integrity": "sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0=", - "dev": true + "integrity": "sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0=" }, "mkdirp": { "version": "0.5.1", "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz", "integrity": "sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM=", - "dev": true + "requires": { + "minimist": "0.0.8" + } }, "mkdirp-promise": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/mkdirp-promise/-/mkdirp-promise-5.0.1.tgz", "integrity": "sha1-6bj2jlUsaKnBcTuEiD96HdA5uKE=", - "dev": true + "dev": true, + "requires": { + "mkdirp": "0.5.1" + } }, "mkpath": { "version": "0.1.0", @@ -1645,6 +5099,18 @@ "resolved": "https://registry.npmjs.org/moment/-/moment-2.18.1.tgz", "integrity": "sha1-w2GT3Tzhwu7SrbfIAtu8d6gbHA8=" }, + "morgan": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/morgan/-/morgan-1.9.0.tgz", + "integrity": "sha1-0B+mxlhZt2/PMbPLU6OCGjEdgFE=", + "requires": { + "basic-auth": "2.0.0", + "debug": "2.6.8", + "depd": "1.1.0", + "on-finished": "2.3.0", + "on-headers": "1.0.1" + } + }, "mout": { "version": "0.11.1", "resolved": "https://registry.npmjs.org/mout/-/mout-0.11.1.tgz", @@ -1654,14 +5120,39 @@ "ms": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", - "dev": true + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" + }, + "multiparty": { + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/multiparty/-/multiparty-3.3.2.tgz", + "integrity": "sha1-Nd5oBNwZZD5SSfPT473GyM4wHT8=", + "requires": { + "readable-stream": "1.1.14", + "stream-counter": "0.2.0" + } + }, + "multipipe": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/multipipe/-/multipipe-0.1.2.tgz", + "integrity": "sha1-Ko8t33Du1WTf8tV/HhoTfZ8FB4s=", + "requires": { + "duplexer2": "0.0.2" + }, + "dependencies": { + "duplexer2": { + "version": "0.0.2", + "resolved": "https://registry.npmjs.org/duplexer2/-/duplexer2-0.0.2.tgz", + "integrity": "sha1-xhTc9n4vsUmVqRcR5aYX6KYKMds=", + "requires": { + "readable-stream": "1.1.14" + } + } + } }, "mute-stream": { "version": "0.0.7", "resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-0.0.7.tgz", - "integrity": "sha1-MHXOk7whuPq0PhvE2n6BFe0ee6s=", - "dev": true + "integrity": "sha1-MHXOk7whuPq0PhvE2n6BFe0ee6s=" }, "mv": { "version": "2.1.1", @@ -1669,20 +5160,35 @@ "integrity": "sha1-rmzg1vbV4KT32JN5jQPB6pVZtqI=", "dev": true, "optional": true, + "requires": { + "mkdirp": "0.5.1", + "ncp": "2.0.0", + "rimraf": "2.4.5" + }, "dependencies": { "glob": { "version": "6.0.4", "resolved": "https://registry.npmjs.org/glob/-/glob-6.0.4.tgz", "integrity": "sha1-DwiGD2oVUSey+t1PnOJLGqtuTSI=", "dev": true, - "optional": true + "optional": true, + "requires": { + "inflight": "1.0.6", + "inherits": "2.0.3", + "minimatch": "3.0.4", + "once": "1.4.0", + "path-is-absolute": "1.0.1" + } }, "rimraf": { "version": "2.4.5", "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.4.5.tgz", "integrity": "sha1-7nEM5dk6j9uFb7Xqj/Di11k0sto=", "dev": true, - "optional": true + "optional": true, + "requires": { + "glob": "6.0.4" + } } } }, @@ -1690,7 +5196,12 @@ "version": "2.6.0", "resolved": "https://registry.npmjs.org/mz/-/mz-2.6.0.tgz", "integrity": "sha1-yLhSHZWN8KTydoAl22nHGe5O8c4=", - "dev": true + "dev": true, + "requires": { + "any-promise": "1.3.0", + "object-assign": "4.1.1", + "thenify-all": "1.6.0" + } }, "nan": { "version": "2.6.2", @@ -1699,6 +5210,18 @@ "dev": true, "optional": true }, + "native-promise-only": { + "version": "0.8.1", + "resolved": "https://registry.npmjs.org/native-promise-only/-/native-promise-only-0.8.1.tgz", + "integrity": "sha1-IKMYwwy0X3H+et+/eyHJnBRy7xE=", + "dev": true + }, + "natural-compare": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", + "integrity": "sha1-Sr6/7tdUHywnrPspvbvRXI1bpPc=", + "dev": true + }, "ncp": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/ncp/-/ncp-2.0.0.tgz", @@ -1708,90 +5231,275 @@ "negotiator": { "version": "0.6.1", "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.1.tgz", - "integrity": "sha1-KzJxhOiZIQEXeyhWP7XnECrNDKk=", - "dev": true + "integrity": "sha1-KzJxhOiZIQEXeyhWP7XnECrNDKk=" }, "node-fetch": { "version": "1.7.1", "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-1.7.1.tgz", - "integrity": "sha512-j8XsFGCLw79vWXkZtMSmmLaOk9z5SQ9bV/tkbZVCqvgwzrjAGq66igobLofHtF63NvMTp2WjytpsNTGKa+XRIQ==" + "integrity": "sha512-j8XsFGCLw79vWXkZtMSmmLaOk9z5SQ9bV/tkbZVCqvgwzrjAGq66igobLofHtF63NvMTp2WjytpsNTGKa+XRIQ==", + "requires": { + "encoding": "0.1.12", + "is-stream": "1.1.0" + } + }, + "node-int64": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/node-int64/-/node-int64-0.4.0.tgz", + "integrity": "sha1-h6kGXNs1XTGC2PlM4RGIuCXGijs=" + }, + "node-status-codes": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/node-status-codes/-/node-status-codes-1.0.0.tgz", + "integrity": "sha1-WuVUHQJGRdMqWPzdyc7s6nrjrC8=" + }, + "noop-fn": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/noop-fn/-/noop-fn-1.0.0.tgz", + "integrity": "sha1-XzPUfxPSFQ35PgywNmmemC94/78=" }, "nopt": { "version": "3.0.6", "resolved": "https://registry.npmjs.org/nopt/-/nopt-3.0.6.tgz", "integrity": "sha1-xkZdvwirzU2zWTF/eaxopkayj/k=", - "dev": true + "dev": true, + "requires": { + "abbrev": "1.1.0" + } }, "normalize-package-data": { "version": "2.3.8", "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-2.3.8.tgz", "integrity": "sha1-2Bntoqne29H/pWPqQHHZNngilbs=", - "dev": true + "requires": { + "hosted-git-info": "2.4.2", + "is-builtin-module": "1.0.0", + "semver": "5.3.0", + "validate-npm-package-license": "3.0.1" + } }, "normalize-path": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-2.1.1.tgz", "integrity": "sha1-GrKLVW4Zg2Oowab35vogE3/mrtk=", - "dev": true + "requires": { + "remove-trailing-separator": "1.0.2" + } + }, + "npmlog": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/npmlog/-/npmlog-2.0.4.tgz", + "integrity": "sha1-mLUlMPJRTKkNCexbIsiEZyI3VpI=", + "requires": { + "ansi": "0.3.1", + "are-we-there-yet": "1.1.4", + "gauge": "1.2.7" + } + }, + "nth-check": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/nth-check/-/nth-check-1.0.1.tgz", + "integrity": "sha1-mSms32KPwsQQmN6rgqxYDPFJquQ=", + "dev": true, + "requires": { + "boolbase": "1.0.0" + } }, "number-is-nan": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/number-is-nan/-/number-is-nan-1.0.1.tgz", - "integrity": "sha1-CXtgK1NCKlIsGvuHkDGDNpQaAR0=", - "dev": true + "integrity": "sha1-CXtgK1NCKlIsGvuHkDGDNpQaAR0=" }, "oauth-sign": { "version": "0.8.2", "resolved": "https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.8.2.tgz", - "integrity": "sha1-Rqarfwrq2N6unsBWV4C31O/rnUM=", - "dev": true + "integrity": "sha1-Rqarfwrq2N6unsBWV4C31O/rnUM=" }, "object-assign": { "version": "4.1.1", "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=" }, + "object-is": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/object-is/-/object-is-1.0.1.tgz", + "integrity": "sha1-CqYOyZiaCz7Xlc9NBvYs8a1lObY=", + "dev": true + }, + "object-keys": { + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.0.11.tgz", + "integrity": "sha1-xUYBd4rVYPEULODgG8yotW0TQm0=", + "dev": true + }, + "object-resolve-path": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/object-resolve-path/-/object-resolve-path-1.1.1.tgz", + "integrity": "sha1-p/j5Poogr4DkQhe6fbVDFtnRIjI=" + }, + "object.assign": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.0.tgz", + "integrity": "sha512-exHJeq6kBKj58mqGyTQ9DFvrZC/eR6OwxzoM9YRoGBqrXYonaFyGiFMuc9VZrXf7DarreEwMpurG3dd+CNyW5w==", + "dev": true, + "requires": { + "define-properties": "1.1.2", + "function-bind": "1.1.1", + "has-symbols": "1.0.0", + "object-keys": "1.0.11" + } + }, + "object.entries": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/object.entries/-/object.entries-1.0.4.tgz", + "integrity": "sha1-G/mk3SKI9bM/Opk9JXZh8F0WGl8=", + "dev": true, + "requires": { + "define-properties": "1.1.2", + "es-abstract": "1.10.0", + "function-bind": "1.1.1", + "has": "1.0.1" + } + }, "object.omit": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/object.omit/-/object.omit-2.0.1.tgz", "integrity": "sha1-Gpx0SCnznbuFjHbKNXmuKlTr0fo=", - "dev": true + "requires": { + "for-own": "0.1.5", + "is-extendable": "0.1.1" + } + }, + "object.values": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/object.values/-/object.values-1.0.4.tgz", + "integrity": "sha1-5STaCbT2b/Bd9FdUbscqyZ8TBpo=", + "dev": true, + "requires": { + "define-properties": "1.1.2", + "es-abstract": "1.10.0", + "function-bind": "1.1.1", + "has": "1.0.1" + } }, "on-finished": { "version": "2.3.0", "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.3.0.tgz", "integrity": "sha1-IPEzZIGwg811M3mSoWlxqi2QaUc=", - "dev": true + "requires": { + "ee-first": "1.1.1" + } + }, + "on-headers": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/on-headers/-/on-headers-1.0.1.tgz", + "integrity": "sha1-ko9dD0cNSTQmUepnlLCFfBAGk/c=" }, "once": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", - "dev": true + "requires": { + "wrappy": "1.0.2" + } }, "onetime": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/onetime/-/onetime-2.0.1.tgz", "integrity": "sha1-BnQoIw/WdEOyeUsiu6UotoZ5YtQ=", - "dev": true + "requires": { + "mimic-fn": "1.1.0" + } + }, + "opencollective": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/opencollective/-/opencollective-1.0.3.tgz", + "integrity": "sha1-ruY3K8KBRFg2kMPKja7PwSDdDvE=", + "requires": { + "babel-polyfill": "6.23.0", + "chalk": "1.1.3", + "inquirer": "3.1.0", + "minimist": "0.0.8", + "node-fetch": "1.7.1", + "opn": "4.0.2" + }, + "dependencies": { + "babel-polyfill": { + "version": "6.23.0", + "resolved": "https://registry.npmjs.org/babel-polyfill/-/babel-polyfill-6.23.0.tgz", + "integrity": "sha1-g2TKYt+Or7gwSZ9pkXdGbDsDSZ0=", + "requires": { + "babel-runtime": "6.23.0", + "core-js": "2.4.1", + "regenerator-runtime": "0.10.5" + } + } + } }, "opn": { "version": "4.0.2", "resolved": "https://registry.npmjs.org/opn/-/opn-4.0.2.tgz", "integrity": "sha1-erwi5kTf9jsKltWrfyeQwPAavJU=", - "dev": true + "requires": { + "object-assign": "4.1.1", + "pinkie-promise": "2.0.1" + } + }, + "optimist": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/optimist/-/optimist-0.6.1.tgz", + "integrity": "sha1-2j6nRob6IaGaERwybpDrFaAZZoY=", + "requires": { + "minimist": "0.0.8", + "wordwrap": "0.0.3" + }, + "dependencies": { + "wordwrap": { + "version": "0.0.3", + "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-0.0.3.tgz", + "integrity": "sha1-o9XabNXAvAAI03I0u68b7WMFkQc=" + } + } + }, + "optionator": { + "version": "0.8.2", + "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.8.2.tgz", + "integrity": "sha1-NkxeQJ0/TWMB1sC0wFu6UBgK62Q=", + "dev": true, + "requires": { + "deep-is": "0.1.3", + "fast-levenshtein": "2.0.6", + "levn": "0.3.0", + "prelude-ls": "1.1.2", + "type-check": "0.3.2", + "wordwrap": "1.0.0" + } }, "os-homedir": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/os-homedir/-/os-homedir-1.0.2.tgz", - "integrity": "sha1-/7xJiDNuDoM94MFox+8VISGqf7M=", - "dev": true + "integrity": "sha1-/7xJiDNuDoM94MFox+8VISGqf7M=" + }, + "os-locale": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/os-locale/-/os-locale-1.4.0.tgz", + "integrity": "sha1-IPnxeuKe00XoveWDsT0gCYA8FNk=", + "requires": { + "lcid": "1.0.0" + } }, "os-tmpdir": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/os-tmpdir/-/os-tmpdir-1.0.2.tgz", - "integrity": "sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ=", - "dev": true + "integrity": "sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ=" + }, + "osenv": { + "version": "0.1.5", + "resolved": "https://registry.npmjs.org/osenv/-/osenv-0.1.5.tgz", + "integrity": "sha512-0CWcCECdMVc2Rw3U5w9ZjqX6ga6ubk1xDVKxtBQPK7wis/0F2r9T6k4ydGYhecl7YUBxBVxhL5oisPsNxAPe2g==", + "requires": { + "os-homedir": "1.0.2", + "os-tmpdir": "1.0.2" + } }, "p-limit": { "version": "1.1.0", @@ -1803,114 +5511,233 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-2.0.0.tgz", "integrity": "sha1-IKAQOyIqcMj9OcwuWAaA893l7EM=", - "dev": true + "dev": true, + "requires": { + "p-limit": "1.1.0" + } + }, + "package-json": { + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/package-json/-/package-json-2.4.0.tgz", + "integrity": "sha1-DRW9Z9HLvduyyiIv8u24a8sxqLs=", + "requires": { + "got": "5.7.1", + "registry-auth-token": "3.3.2", + "registry-url": "3.1.0", + "semver": "5.3.0" + } }, "param-case": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/param-case/-/param-case-1.1.2.tgz", "integrity": "sha1-3LCRpDwlm5Io8cNB57akTqC/l0M=", - "dev": true + "dev": true, + "requires": { + "sentence-case": "1.1.3" + } }, "parse-glob": { "version": "3.0.4", "resolved": "https://registry.npmjs.org/parse-glob/-/parse-glob-3.0.4.tgz", "integrity": "sha1-ssN2z7EfNVE7rdFz7wu246OIORw=", - "dev": true + "requires": { + "glob-base": "0.3.0", + "is-dotfile": "1.0.3", + "is-extglob": "1.0.0", + "is-glob": "2.0.1" + } }, "parse-json": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-2.2.0.tgz", "integrity": "sha1-9ID0BDTvgHQfhGkJn43qGPVaTck=", - "dev": true + "requires": { + "error-ex": "1.3.1" + } }, "parseurl": { "version": "1.3.1", "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.1.tgz", - "integrity": "sha1-yKuMkiO6NIiKpkopeyiFO+wY2lY=", - "dev": true + "integrity": "sha1-yKuMkiO6NIiKpkopeyiFO+wY2lY=" }, "pascal-case": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/pascal-case/-/pascal-case-1.1.2.tgz", "integrity": "sha1-Pl1kogBDgwp8STRMLXS0G+DJyZs=", - "dev": true + "dev": true, + "requires": { + "camel-case": "1.2.2", + "upper-case-first": "1.1.2" + } }, "path-case": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/path-case/-/path-case-1.1.2.tgz", "integrity": "sha1-UM5roNO+090LXCqcRVNpdDRAlRQ=", - "dev": true + "dev": true, + "requires": { + "sentence-case": "1.1.3" + } }, "path-exists": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz", - "integrity": "sha1-zg6+ql94yxiSXqfYENe1mwEP1RU=", - "dev": true + "integrity": "sha1-zg6+ql94yxiSXqfYENe1mwEP1RU=" }, "path-is-absolute": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", - "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=", + "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=" + }, + "path-is-inside": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/path-is-inside/-/path-is-inside-1.0.2.tgz", + "integrity": "sha1-NlQX3t5EQw0cEa9hAn+s8HS9/FM=", "dev": true }, + "path-parse": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.5.tgz", + "integrity": "sha1-PBrfhx6pzWyUMbbqK9dKD/BVxME=" + }, "path-to-regexp": { "version": "0.1.7", "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.7.tgz", - "integrity": "sha1-32BBeABfUi8V60SQ5yR6G/qmf4w=", - "dev": true + "integrity": "sha1-32BBeABfUi8V60SQ5yR6G/qmf4w=" }, "path-type": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/path-type/-/path-type-1.1.0.tgz", "integrity": "sha1-WcRPfuSR2nBNpBXaWkBwuk+P5EE=", - "dev": true + "requires": { + "graceful-fs": "4.1.11", + "pify": "2.3.0", + "pinkie-promise": "2.0.1" + } + }, + "pause": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/pause/-/pause-0.1.0.tgz", + "integrity": "sha1-68ikqGGf8LioGsFRPDQ0/0af23Q=" + }, + "pegjs": { + "version": "0.10.0", + "resolved": "https://registry.npmjs.org/pegjs/-/pegjs-0.10.0.tgz", + "integrity": "sha1-z4uvrm7d/0tafvsYUmnqr0YQ3b0=" }, "performance-now": { "version": "0.2.0", "resolved": "https://registry.npmjs.org/performance-now/-/performance-now-0.2.0.tgz", - "integrity": "sha1-M+8wxcd9TqIcWlOGnZG1bY8lVeU=", - "dev": true + "integrity": "sha1-M+8wxcd9TqIcWlOGnZG1bY8lVeU=" }, "pify": { "version": "2.3.0", "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", - "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=", - "dev": true + "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=" }, "pinkie": { "version": "2.0.4", "resolved": "https://registry.npmjs.org/pinkie/-/pinkie-2.0.4.tgz", - "integrity": "sha1-clVrgM+g1IqXToDnckjoDtT3+HA=", - "dev": true + "integrity": "sha1-clVrgM+g1IqXToDnckjoDtT3+HA=" }, "pinkie-promise": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/pinkie-promise/-/pinkie-promise-2.0.1.tgz", "integrity": "sha1-ITXW36ejWMBprJsXh3YogihFD/o=", + "requires": { + "pinkie": "2.0.4" + } + }, + "pkg-dir": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-1.0.0.tgz", + "integrity": "sha1-ektQio1bstYp1EcFb/TpyTFM89Q=", + "dev": true, + "requires": { + "find-up": "2.1.0" + } + }, + "plist": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/plist/-/plist-1.2.0.tgz", + "integrity": "sha1-CEtQk93JJQbiWfh0uNmxr7jHlZM=", + "requires": { + "base64-js": "0.0.8", + "util-deprecate": "1.0.2", + "xmlbuilder": "4.0.0", + "xmldom": "0.1.27" + }, + "dependencies": { + "base64-js": { + "version": "0.0.8", + "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-0.0.8.tgz", + "integrity": "sha1-EQHpVE9KdrG8OybUUsqW16NeeXg=" + } + } + }, + "pluralize": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/pluralize/-/pluralize-3.1.0.tgz", + "integrity": "sha1-hCE9ChI1YGnaqEBgxVkkJjMWE2g=" + }, + "pouchdb-collections": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/pouchdb-collections/-/pouchdb-collections-1.0.1.tgz", + "integrity": "sha1-/mOhfal3YRq+98uAJssalVP9g1k=" + }, + "prelude-ls": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.1.2.tgz", + "integrity": "sha1-IZMqVJ9eUv/ZqCf1cOBL5iqX2lQ=", "dev": true }, + "prepend-http": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/prepend-http/-/prepend-http-1.0.4.tgz", + "integrity": "sha1-1PRWKwzjaW5BrFLQ4ALlemNdxtw=" + }, "preserve": { "version": "0.2.0", "resolved": "https://registry.npmjs.org/preserve/-/preserve-0.2.0.tgz", - "integrity": "sha1-gV7R9uvGWSb4ZbMQwHE7yzMVzks=", + "integrity": "sha1-gV7R9uvGWSb4ZbMQwHE7yzMVzks=" + }, + "prettier": { + "version": "1.11.0", + "resolved": "https://registry.npmjs.org/prettier/-/prettier-1.11.0.tgz", + "integrity": "sha512-5TznPccvjc3WtACW2YuHXQDCCpE6cTU7rpRLTw7dtNmvrI6j8lirXwICrYImyDZknIC4RL2epnGVqRbVAsQw+w==", "dev": true }, + "pretty-format": { + "version": "20.0.3", + "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-20.0.3.tgz", + "integrity": "sha1-Ag41ClYKH+GpjcO+tsz/s4beixQ=", + "requires": { + "ansi-regex": "2.1.1", + "ansi-styles": "2.2.1" + } + }, "private": { "version": "0.1.7", "resolved": "https://registry.npmjs.org/private/-/private-0.1.7.tgz", - "integrity": "sha1-aM5eih7woju1cMwoU3tTMqumPvE=", - "dev": true + "integrity": "sha1-aM5eih7woju1cMwoU3tTMqumPvE=" + }, + "process": { + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/process/-/process-0.5.2.tgz", + "integrity": "sha1-FjjYqONML0QKkduVq5rrZ3/Bhc8=" }, "progress": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/progress/-/progress-2.0.0.tgz", - "integrity": "sha1-ihvjZr+Pwj2yvSPxDG/pILQ4nR8=", - "dev": true + "integrity": "sha1-ihvjZr+Pwj2yvSPxDG/pILQ4nR8=" }, "promise": { "version": "7.1.1", "resolved": "https://registry.npmjs.org/promise/-/promise-7.1.1.tgz", - "integrity": "sha1-SJZUxpJha4qlWwck+oCbt9tJxb8=" + "integrity": "sha1-SJZUxpJha4qlWwck+oCbt9tJxb8=", + "requires": { + "asap": "2.0.5" + } }, "promise-props": { "version": "1.0.0", @@ -1921,25 +5748,35 @@ "prop-types": { "version": "15.5.10", "resolved": "https://registry.npmjs.org/prop-types/-/prop-types-15.5.10.tgz", - "integrity": "sha1-J5ffwxJhguOpXj37suiT3ddFYVQ=" + "integrity": "sha1-J5ffwxJhguOpXj37suiT3ddFYVQ=", + "requires": { + "fbjs": "0.8.12", + "loose-envify": "1.3.1" + } }, "proxy-addr": { "version": "1.1.4", "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-1.1.4.tgz", "integrity": "sha1-J+VF9pYKRKYn2bREZ+NcG2tM4vM=", - "dev": true + "requires": { + "forwarded": "0.1.0", + "ipaddr.js": "1.3.0" + } + }, + "prr": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/prr/-/prr-1.0.1.tgz", + "integrity": "sha1-0/wRS6BplaRexok/SEzrHXj19HY=" }, "pseudomap": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/pseudomap/-/pseudomap-1.0.2.tgz", - "integrity": "sha1-8FKijacOYYkX7wqKw0wa5aaChrM=", - "dev": true + "integrity": "sha1-8FKijacOYYkX7wqKw0wa5aaChrM=" }, "punycode": { "version": "1.4.1", "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.4.1.tgz", - "integrity": "sha1-wNWmOycYgArY4esPpSachN1BhF4=", - "dev": true + "integrity": "sha1-wNWmOycYgArY4esPpSachN1BhF4=" }, "q": { "version": "1.5.0", @@ -1956,32 +5793,51 @@ "qs": { "version": "6.4.0", "resolved": "https://registry.npmjs.org/qs/-/qs-6.4.0.tgz", - "integrity": "sha1-E+JtKK1rD/qpExLNO/cI7TUecjM=", - "dev": true + "integrity": "sha1-E+JtKK1rD/qpExLNO/cI7TUecjM=" + }, + "query-string": { + "version": "4.3.4", + "resolved": "https://registry.npmjs.org/query-string/-/query-string-4.3.4.tgz", + "integrity": "sha1-u7aTucqRXCMlFbIosaArYJBD2+s=", + "requires": { + "object-assign": "4.1.1", + "strict-uri-encode": "1.1.0" + } }, "querystring": { "version": "0.2.0", "resolved": "https://registry.npmjs.org/querystring/-/querystring-0.2.0.tgz", - "integrity": "sha1-sgmEkgO7Jd+CDadW50cAWHhSFiA=", - "dev": true + "integrity": "sha1-sgmEkgO7Jd+CDadW50cAWHhSFiA=" + }, + "random-bytes": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/random-bytes/-/random-bytes-1.0.0.tgz", + "integrity": "sha1-T2ih3Arli9P7lYSMMDJNt11kNgs=" }, "randomatic": { "version": "1.1.7", "resolved": "https://registry.npmjs.org/randomatic/-/randomatic-1.1.7.tgz", "integrity": "sha512-D5JUjPyJbaJDkuAazpVnSfVkLlpeO3wDlPROTMLGKG1zMFNFRgrciKo1ltz/AzNTkqE0HzDx655QOL51N06how==", - "dev": true, + "requires": { + "is-number": "3.0.0", + "kind-of": "4.0.0" + }, "dependencies": { "is-number": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz", "integrity": "sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU=", - "dev": true, + "requires": { + "kind-of": "3.2.2" + }, "dependencies": { "kind-of": { "version": "3.2.2", "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "dev": true + "requires": { + "is-buffer": "1.1.5" + } } } }, @@ -1989,41 +5845,306 @@ "version": "4.0.0", "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-4.0.0.tgz", "integrity": "sha1-IIE989cSkosgc3hpGkUGb65y3Vc=", - "dev": true + "requires": { + "is-buffer": "1.1.5" + } } } }, "range-parser": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.0.tgz", - "integrity": "sha1-9JvmtIeJTdxA3MlKMi9hEJLgDV4=", - "dev": true + "integrity": "sha1-9JvmtIeJTdxA3MlKMi9hEJLgDV4=" + }, + "raven-js": { + "version": "3.22.4", + "resolved": "https://registry.npmjs.org/raven-js/-/raven-js-3.22.4.tgz", + "integrity": "sha512-zcaFcpVwRdI+Dc/H4JAzCkdZKcnE/joIFkn8aeErJJE6Hu4PFjD/2mG4g3iObS9TuHsm/XCSctEp4NnR93+MJQ==" }, "raw-body": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.2.0.tgz", "integrity": "sha1-mUl2z2pQlqQRYoQEkvC9xdbn+5Y=", - "dev": true, + "requires": { + "bytes": "2.4.0", + "iconv-lite": "0.4.15", + "unpipe": "1.0.0" + }, "dependencies": { "iconv-lite": { "version": "0.4.15", "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.15.tgz", - "integrity": "sha1-/iZaIYrGpXz+hUkn6dBMGYJe3es=", - "dev": true + "integrity": "sha1-/iZaIYrGpXz+hUkn6dBMGYJe3es=" } } }, + "rc": { + "version": "1.2.5", + "resolved": "https://registry.npmjs.org/rc/-/rc-1.2.5.tgz", + "integrity": "sha1-J1zWh/bjs2zHVrqibf7oCnkDAf0=", + "requires": { + "deep-extend": "0.4.2", + "ini": "1.3.5", + "minimist": "0.0.8", + "strip-json-comments": "2.0.1" + } + }, + "react": { + "version": "16.0.0-alpha.12", + "resolved": "https://registry.npmjs.org/react/-/react-16.0.0-alpha.12.tgz", + "integrity": "sha1-jFlIUoFIXfMZtvd2gtjdBiHAgZQ=", + "requires": { + "create-react-class": "15.5.4", + "fbjs": "0.8.12", + "loose-envify": "1.3.1", + "object-assign": "4.1.1", + "prop-types": "15.5.10" + } + }, + "react-addons-test-utils": { + "version": "15.6.2", + "resolved": "https://registry.npmjs.org/react-addons-test-utils/-/react-addons-test-utils-15.6.2.tgz", + "integrity": "sha1-wStu/cIkfBDae4dw0YUICnsEcVY=", + "dev": true + }, + "react-clone-referenced-element": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/react-clone-referenced-element/-/react-clone-referenced-element-1.0.1.tgz", + "integrity": "sha1-K7qMaUBMXkqUQ5hgC8xMlB+GBoI=" + }, + "react-deep-force-update": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/react-deep-force-update/-/react-deep-force-update-1.1.1.tgz", + "integrity": "sha1-vNMUeAJ7ZLMznxCJIatSC0MT3Cw=" + }, + "react-devtools-core": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/react-devtools-core/-/react-devtools-core-2.3.1.tgz", + "integrity": "sha1-3IOrqFc17/5eHcOGoWFMtejQBH0=", + "requires": { + "shell-quote": "1.6.1", + "ws": "3.0.0" + } + }, "react-dom": { "version": "15.6.0", "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-15.6.0.tgz", "integrity": "sha1-i8I8sMgOcGNVt2yp+M5Hz3vfttE=", - "dev": true + "dev": true, + "requires": { + "fbjs": "0.8.12", + "loose-envify": "1.3.1", + "object-assign": "4.1.1", + "prop-types": "15.5.10" + } + }, + "react-i18next": { + "version": "4.8.0", + "resolved": "https://registry.npmjs.org/react-i18next/-/react-i18next-4.8.0.tgz", + "integrity": "sha1-kvDSgcXzmsjzw/OBVi1SPp2DAlQ=", + "requires": { + "hoist-non-react-statics": "1.2.0" + } + }, + "react-native": { + "version": "0.46.4", + "resolved": "https://registry.npmjs.org/react-native/-/react-native-0.46.4.tgz", + "integrity": "sha1-KBu8wWXlw2tMjqqGjmdoVD6BG8s=", + "requires": { + "absolute-path": "0.0.0", + "art": "0.10.1", + "async": "2.6.0", + "babel-core": "6.25.0", + "babel-generator": "6.25.0", + "babel-plugin-external-helpers": "6.22.0", + "babel-plugin-syntax-trailing-function-commas": "6.22.0", + "babel-plugin-transform-async-to-generator": "6.16.0", + "babel-plugin-transform-class-properties": "6.24.1", + "babel-plugin-transform-flow-strip-types": "6.22.0", + "babel-plugin-transform-object-rest-spread": "6.26.0", + "babel-polyfill": "6.26.0", + "babel-preset-es2015-node": "6.1.1", + "babel-preset-fbjs": "2.1.4", + "babel-preset-react-native": "1.9.2", + "babel-register": "6.24.1", + "babel-runtime": "6.23.0", + "babel-traverse": "6.25.0", + "babel-types": "6.25.0", + "babylon": "6.17.3", + "base64-js": "1.2.3", + "bser": "1.0.3", + "chalk": "1.1.3", + "commander": "2.9.0", + "concat-stream": "1.6.0", + "connect": "2.30.2", + "core-js": "2.4.1", + "create-react-class": "15.5.4", + "debug": "2.6.8", + "denodeify": "1.2.1", + "errno": "0.1.7", + "event-target-shim": "1.1.1", + "fbjs": "0.8.12", + "fbjs-scripts": "0.7.1", + "form-data": "2.1.4", + "fs-extra": "3.0.1", + "glob": "7.1.2", + "graceful-fs": "4.1.11", + "image-size": "0.3.5", + "inquirer": "3.1.0", + "jest-haste-map": "20.0.5", + "json-stable-stringify": "1.0.1", + "json5": "0.5.1", + "left-pad": "1.2.0", + "lodash": "4.17.4", + "merge-stream": "1.0.1", + "metro-bundler": "0.7.8", + "mime": "1.3.6", + "mime-types": "2.1.15", + "minimist": "0.0.8", + "mkdirp": "0.5.1", + "node-fetch": "1.7.1", + "npmlog": "2.0.4", + "opn": "4.0.2", + "optimist": "0.6.1", + "plist": "1.2.0", + "pretty-format": "4.3.1", + "promise": "7.1.1", + "prop-types": "15.5.10", + "react-clone-referenced-element": "1.0.1", + "react-devtools-core": "2.3.1", + "react-timer-mixin": "0.13.3", + "react-transform-hmr": "1.0.4", + "rebound": "0.0.13", + "regenerator-runtime": "0.10.5", + "request": "2.81.0", + "rimraf": "2.6.1", + "sane": "1.4.1", + "semver": "5.3.0", + "shell-quote": "1.6.1", + "source-map": "0.5.6", + "stacktrace-parser": "0.1.4", + "temp": "0.8.3", + "throat": "3.2.0", + "uglify-js": "2.7.5", + "whatwg-fetch": "2.0.3", + "wordwrap": "1.0.0", + "write-file-atomic": "1.3.4", + "ws": "3.0.0", + "xcode": "0.9.3", + "xmldoc": "0.4.0", + "xpipe": "1.0.5", + "xtend": "4.0.1", + "yargs": "6.6.0" + }, + "dependencies": { + "pretty-format": { + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-4.3.1.tgz", + "integrity": "sha1-UwvlxCs8BbNkFKeipDN6qArNDo0=" + } + } + }, + "react-native-animatable": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/react-native-animatable/-/react-native-animatable-1.2.4.tgz", + "integrity": "sha512-cVTQXa/cp8gfxcl+l6I1rGAI7EeoNZ0ur9vtxb3tD5iGlJbIyUfQK61e6BycnZewdgQ639Mp6OrueXTpZlv76Q==", + "requires": { + "prop-types": "15.5.10" + } + }, + "react-native-branch": { + "version": "2.0.0-beta.3", + "resolved": "https://registry.npmjs.org/react-native-branch/-/react-native-branch-2.0.0-beta.3.tgz", + "integrity": "sha1-IWevhrvJ+WS9Rb1fN2hOW1SWXjI=" + }, + "react-native-dismiss-keyboard": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/react-native-dismiss-keyboard/-/react-native-dismiss-keyboard-1.0.0.tgz", + "integrity": "sha1-MohiQrPyMX4SHzrrmwpYXiuHm0k=" + }, + "react-native-drawer-layout": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/react-native-drawer-layout/-/react-native-drawer-layout-1.3.2.tgz", + "integrity": "sha512-fjO0scqbJUfNu2wuEpvywL7DYLXuCXJ2W/zYhWz986rdLytidbys1QGVvkaszHrb4Y7OqO96mTkgpOcP8KWevw==", + "requires": { + "react-native-dismiss-keyboard": "1.0.0" + } + }, + "react-native-drawer-layout-polyfill": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/react-native-drawer-layout-polyfill/-/react-native-drawer-layout-polyfill-1.3.2.tgz", + "integrity": "sha512-XzPhfLDJrYHru+e8+dFwhf0FtTeAp7JXPpFYezYV6P1nTeA1Tia/kDpFT+O2DWTrBKBEI8FGhZnThrroZmHIxg==", + "requires": { + "react-native-drawer-layout": "1.3.2" + } + }, + "react-native-elements": { + "version": "0.14.0", + "resolved": "https://registry.npmjs.org/react-native-elements/-/react-native-elements-0.14.0.tgz", + "integrity": "sha1-60UHPHBtgzPLOwW9DV2IMZjwrrQ=", + "requires": { + "lodash.isempty": "4.4.0", + "lodash.times": "4.3.2", + "opencollective": "1.0.3", + "prop-types": "15.5.10", + "react-native-side-menu": "0.20.3", + "react-native-tab-navigator": "0.3.4" + } + }, + "react-native-extended-stylesheet": { + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/react-native-extended-stylesheet/-/react-native-extended-stylesheet-0.5.0.tgz", + "integrity": "sha1-/RcNIPxCMSKJQ1qaExOvqJ7+0I4=", + "requires": { + "css-mediaquery": "0.1.2", + "object-resolve-path": "1.1.1" + } + }, + "react-native-maps": { + "version": "0.15.3", + "resolved": "https://registry.npmjs.org/react-native-maps/-/react-native-maps-0.15.3.tgz", + "integrity": "sha1-XZ4KjjDsxR3HVbejuda27V4t0Iw=" + }, + "react-native-message-bar": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/react-native-message-bar/-/react-native-message-bar-1.6.0.tgz", + "integrity": "sha1-eWI+iWVUdSFpJwkHcbAjhha28cc=" + }, + "react-native-popover": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/react-native-popover/-/react-native-popover-0.2.0.tgz", + "integrity": "sha1-v2akzl0Fg/8zHtsAiQOA9KEXH28=", + "requires": { + "react-tween-state": "0.0.5" + } + }, + "react-native-safe-module": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/react-native-safe-module/-/react-native-safe-module-1.2.0.tgz", + "integrity": "sha1-ojgkyiTtwpAZE2lKdmRkdRE9Vw0=", + "requires": { + "dedent": "0.6.0" + } }, "react-native-scripts": { "version": "0.0.31", "resolved": "https://registry.npmjs.org/react-native-scripts/-/react-native-scripts-0.0.31.tgz", "integrity": "sha1-bOA8ray/y27b09f01+eGMwAIubo=", "dev": true, + "requires": { + "babel-runtime": "6.23.0", + "chalk": "1.1.3", + "cross-spawn": "5.1.0", + "fs-extra": "3.0.1", + "indent-string": "3.1.0", + "inquirer": "3.1.0", + "match-require": "2.1.0", + "minimist": "1.2.0", + "path-exists": "3.0.0", + "progress": "2.0.0", + "qrcode-terminal": "0.11.0", + "xdl": "41.1.0" + }, "dependencies": { "minimist": { "version": "1.2.0", @@ -2033,46 +6154,210 @@ } } }, + "react-native-sentry": { + "version": "0.24.2", + "resolved": "https://registry.npmjs.org/react-native-sentry/-/react-native-sentry-0.24.2.tgz", + "integrity": "sha512-qg9eU7Y3e0kI+59et9w+r8Hw6GgU4Z2k377y2CPqURWq3lEiuHe/QOZSKeSIfQspWN2QhjsxnB3aA2g/Fz7eyA==", + "requires": { + "chalk": "1.1.3", + "glob": "7.1.2", + "inquirer": "3.1.0", + "raven-js": "3.22.4", + "sentry-cli-binary": "1.25.0", + "xcode": "0.9.3" + } + }, + "react-native-side-menu": { + "version": "0.20.3", + "resolved": "https://registry.npmjs.org/react-native-side-menu/-/react-native-side-menu-0.20.3.tgz", + "integrity": "sha512-JWYlCvsHk4KSL/7fY1MYjlSr+Psi3cw0mgsKLeRfysTDxBVtCfBVjmHNT2MvjfI7ZXAAlyFEqBnwQXD1vWWHgg==" + }, + "react-native-slider": { + "version": "0.11.0", + "resolved": "https://registry.npmjs.org/react-native-slider/-/react-native-slider-0.11.0.tgz", + "integrity": "sha512-jV9K87eu9uWr0uJIyrSpBLnCKvVlOySC2wynq9TFCdV9oGgjt7Niq8Q1A8R8v+5GHsuBw/s8vEj1AAkkUi+u+w==", + "requires": { + "prop-types": "15.5.10" + } + }, + "react-native-svg": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/react-native-svg/-/react-native-svg-5.3.0.tgz", + "integrity": "sha1-DSypi+5nJtYnwsoxYXrJxffULa8=", + "requires": { + "color": "0.11.4", + "lodash": "4.17.4" + }, + "dependencies": { + "color": { + "version": "0.11.4", + "resolved": "https://registry.npmjs.org/color/-/color-0.11.4.tgz", + "integrity": "sha1-bXtcdPtl6EHNSHkq0e1eB7kE12Q=", + "requires": { + "clone": "2.1.1", + "color-convert": "1.9.1", + "color-string": "0.3.0" + } + }, + "color-string": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/color-string/-/color-string-0.3.0.tgz", + "integrity": "sha1-J9RvtnAlxcL6JZk7+/V55HhBuZE=", + "requires": { + "color-name": "1.1.3" + } + } + } + }, + "react-native-tab-navigator": { + "version": "0.3.4", + "resolved": "https://registry.npmjs.org/react-native-tab-navigator/-/react-native-tab-navigator-0.3.4.tgz", + "integrity": "sha1-VKGPGtBqCdSg3oH/AEFrwbdgyWA=", + "requires": { + "immutable": "3.8.2", + "prop-types": "15.5.10" + } + }, + "react-native-tab-view": { + "version": "0.0.65", + "resolved": "https://registry.npmjs.org/react-native-tab-view/-/react-native-tab-view-0.0.65.tgz", + "integrity": "sha1-toXqMIH/fJZIbNmXNhAmxAcwLFk=", + "requires": { + "prop-types": "15.5.10" + } + }, + "react-native-vector-icons": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/react-native-vector-icons/-/react-native-vector-icons-4.2.0.tgz", + "integrity": "sha1-BZS2jevddY3OTFZb8C4tZNcATYI=", + "requires": { + "lodash": "4.17.4", + "prop-types": "15.5.10", + "yargs": "6.6.0" + } + }, + "react-navigation": { + "version": "1.0.0-beta.11", + "resolved": "https://registry.npmjs.org/react-navigation/-/react-navigation-1.0.0-beta.11.tgz", + "integrity": "sha1-QnHtsjzbzG64hgL3/eCnfw73oWA=", + "requires": { + "clamp": "1.0.1", + "fbjs": "0.8.12", + "hoist-non-react-statics": "1.2.0", + "path-to-regexp": "0.1.7", + "prop-types": "15.5.10", + "react-native-drawer-layout-polyfill": "1.3.2", + "react-native-tab-view": "0.0.65" + } + }, + "react-proxy": { + "version": "1.1.8", + "resolved": "https://registry.npmjs.org/react-proxy/-/react-proxy-1.1.8.tgz", + "integrity": "sha1-nb/Z2SdSjDqp9ETkVYw3gwq4wmo=", + "requires": { + "lodash": "4.17.4", + "react-deep-force-update": "1.1.1" + } + }, "react-redux": { "version": "5.0.5", "resolved": "https://registry.npmjs.org/react-redux/-/react-redux-5.0.5.tgz", - "integrity": "sha1-+OjHsjlCJXblLWt9sGQ5RpvphGo=" + "integrity": "sha1-+OjHsjlCJXblLWt9sGQ5RpvphGo=", + "requires": { + "create-react-class": "15.5.4", + "hoist-non-react-statics": "1.2.0", + "invariant": "2.2.2", + "lodash": "4.17.4", + "lodash-es": "4.17.4", + "loose-envify": "1.3.1", + "prop-types": "15.5.10" + } }, "react-test-renderer": { "version": "16.0.0-alpha.6", "resolved": "https://registry.npmjs.org/react-test-renderer/-/react-test-renderer-16.0.0-alpha.6.tgz", "integrity": "sha1-wDLe8NyDGc7jnKpOQ3OmABnLN4Y=", - "dev": true + "dev": true, + "requires": { + "fbjs": "0.8.12", + "object-assign": "4.1.1" + } + }, + "react-timer-mixin": { + "version": "0.13.3", + "resolved": "https://registry.npmjs.org/react-timer-mixin/-/react-timer-mixin-0.13.3.tgz", + "integrity": "sha1-Dai5+AfsB9w+hU0ILHN8ZWBbPSI=" + }, + "react-transform-hmr": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/react-transform-hmr/-/react-transform-hmr-1.0.4.tgz", + "integrity": "sha1-4aQL0Krvxy6N/Xp82gmvhQZjl7s=", + "requires": { + "global": "4.3.2", + "react-proxy": "1.1.8" + } + }, + "react-tween-state": { + "version": "0.0.5", + "resolved": "https://registry.npmjs.org/react-tween-state/-/react-tween-state-0.0.5.tgz", + "integrity": "sha1-vSXCfyVYuDmmx67juF+rlndg0dI=", + "requires": { + "tween-functions": "1.2.0" + } + }, + "read-all-stream": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/read-all-stream/-/read-all-stream-3.1.0.tgz", + "integrity": "sha1-NcPhd/IHjveJ7kv6+kNzB06u9Po=", + "requires": { + "pinkie-promise": "2.0.1", + "readable-stream": "1.1.14" + } }, "read-chunk": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/read-chunk/-/read-chunk-2.0.0.tgz", "integrity": "sha1-Mkbod4KRFs7AWWdMTV8wD3qSYfM=", - "dev": true + "dev": true, + "requires": { + "pify": "2.3.0" + } }, "read-pkg": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-1.1.0.tgz", "integrity": "sha1-9f+qXs0pyzHAR0vKfXVra7KePyg=", - "dev": true + "requires": { + "load-json-file": "1.1.0", + "normalize-package-data": "2.3.8", + "path-type": "1.1.0" + } }, "read-pkg-up": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-1.0.1.tgz", "integrity": "sha1-nWPBMnbAZZGNV/ACpX9AobZD+wI=", - "dev": true, + "requires": { + "find-up": "1.1.2", + "read-pkg": "1.1.0" + }, "dependencies": { "find-up": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/find-up/-/find-up-1.1.2.tgz", "integrity": "sha1-ay6YIrGizgpgq2TWEOzK1TyyTQ8=", - "dev": true + "requires": { + "path-exists": "2.1.0", + "pinkie-promise": "2.0.1" + } }, "path-exists": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-2.1.0.tgz", "integrity": "sha1-D+tsZPD8UY2adU3V77YscCJ2H0s=", - "dev": true + "requires": { + "pinkie-promise": "2.0.1" + } } } }, @@ -2080,68 +6365,208 @@ "version": "1.1.14", "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.1.14.tgz", "integrity": "sha1-fPTFTvZI44EwhMY23SB54WbAgdk=", - "dev": true, + "requires": { + "core-util-is": "1.0.2", + "inherits": "2.0.3", + "isarray": "0.0.1", + "string_decoder": "0.10.31" + }, "dependencies": { "isarray": { "version": "0.0.1", "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", - "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=", - "dev": true + "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=" } } }, + "rebound": { + "version": "0.0.13", + "resolved": "https://registry.npmjs.org/rebound/-/rebound-0.0.13.tgz", + "integrity": "sha1-SiJSVMr32nVnl7GcWBe/enlB+sE=" + }, + "rechoir": { + "version": "0.6.2", + "resolved": "https://registry.npmjs.org/rechoir/-/rechoir-0.6.2.tgz", + "integrity": "sha1-hSBLVNuoLVdC4oyWdW70OvUOM4Q=", + "dev": true, + "requires": { + "resolve": "1.5.0" + } + }, + "recompose": { + "version": "0.23.5", + "resolved": "https://registry.npmjs.org/recompose/-/recompose-0.23.5.tgz", + "integrity": "sha1-cqyCYSRr7DeCNdGHRn0CpyHosd4=", + "requires": { + "change-emitter": "0.1.6", + "fbjs": "0.8.12", + "hoist-non-react-statics": "1.2.0", + "symbol-observable": "1.0.4" + } + }, "redux": { "version": "3.6.0", "resolved": "https://registry.npmjs.org/redux/-/redux-3.6.0.tgz", - "integrity": "sha1-iHwrPQub2G7KK+cFccJ2VMGeGI0=" + "integrity": "sha1-iHwrPQub2G7KK+cFccJ2VMGeGI0=", + "requires": { + "lodash": "4.17.4", + "lodash-es": "4.17.4", + "loose-envify": "1.3.1", + "symbol-observable": "1.0.4" + } }, "redux-devtools-instrument": { "version": "1.8.2", "resolved": "https://registry.npmjs.org/redux-devtools-instrument/-/redux-devtools-instrument-1.8.2.tgz", "integrity": "sha1-XpHP5ALnkNrj/S8NI197fYSwn/4=", - "dev": true + "requires": { + "lodash": "4.17.4", + "symbol-observable": "1.0.4" + } }, "redux-logger": { "version": "2.10.2", "resolved": "https://registry.npmjs.org/redux-logger/-/redux-logger-2.10.2.tgz", "integrity": "sha1-PFpfCm8yV3wd6t9mVfJX+CxsOTc=", - "dev": true + "dev": true, + "requires": { + "deep-diff": "0.3.4" + } + }, + "redux-persist": { + "version": "4.8.0", + "resolved": "https://registry.npmjs.org/redux-persist/-/redux-persist-4.8.0.tgz", + "integrity": "sha1-F/2ZiUm97vknXkz2CtW74cc2dfw=", + "requires": { + "json-stringify-safe": "5.0.1", + "lodash": "4.17.4", + "lodash-es": "4.17.4" + } + }, + "redux-persist-transform-filter": { + "version": "0.0.15", + "resolved": "https://registry.npmjs.org/redux-persist-transform-filter/-/redux-persist-transform-filter-0.0.15.tgz", + "integrity": "sha512-R9hi1dJkfNPPpTHH7VsDrHpiPEaiNlN4Qolhs89IDY88go+w3pntTGY6Td7hM5zOrUsr3j9rp60EdD/eMfKO2A==", + "requires": { + "lodash.forin": "4.4.0", + "lodash.get": "4.4.2", + "lodash.isempty": "4.4.0", + "lodash.pickby": "4.6.0", + "lodash.set": "4.3.2", + "lodash.unset": "4.5.2" + } + }, + "redux-thunk": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/redux-thunk/-/redux-thunk-2.2.0.tgz", + "integrity": "sha1-5hWhbha0ehmlFXZhM9Hj6Zt4UuU=" + }, + "regenerate": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/regenerate/-/regenerate-1.3.3.tgz", + "integrity": "sha512-jVpo1GadrDAK59t/0jRx5VxYWQEDkkEKi6+HjE3joFVLfDOh9Xrdh0dF1eSq+BI/SwvTQ44gSscJ8N5zYL61sg==" }, "regenerator-runtime": { "version": "0.10.5", "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.10.5.tgz", - "integrity": "sha1-M2w+/BIgrc7dosn6tntaeVWjNlg=", - "dev": true + "integrity": "sha1-M2w+/BIgrc7dosn6tntaeVWjNlg=" + }, + "regenerator-transform": { + "version": "0.10.1", + "resolved": "https://registry.npmjs.org/regenerator-transform/-/regenerator-transform-0.10.1.tgz", + "integrity": "sha512-PJepbvDbuK1xgIgnau7Y90cwaAmO/LCLMI2mPvaXq2heGMR3aWW5/BQvYrhJ8jgmQjXewXvBjzfqKcVOmhjZ6Q==", + "requires": { + "babel-runtime": "6.23.0", + "babel-types": "6.25.0", + "private": "0.1.7" + } }, "regex-cache": { "version": "0.4.3", "resolved": "https://registry.npmjs.org/regex-cache/-/regex-cache-0.4.3.tgz", "integrity": "sha1-mxpsNdTQ3871cRrmUejp09cRQUU=", - "dev": true + "requires": { + "is-equal-shallow": "0.1.3", + "is-primitive": "2.0.0" + } + }, + "regexpu-core": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/regexpu-core/-/regexpu-core-2.0.0.tgz", + "integrity": "sha1-SdA4g3uNz4v6W5pCE5k45uoq4kA=", + "requires": { + "regenerate": "1.3.3", + "regjsgen": "0.2.0", + "regjsparser": "0.1.5" + } + }, + "registry-auth-token": { + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/registry-auth-token/-/registry-auth-token-3.3.2.tgz", + "integrity": "sha512-JL39c60XlzCVgNrO+qq68FoNb56w/m7JYvGR2jT5iR1xBrUA3Mfx5Twk5rqTThPmQKMWydGmq8oFtDlxfrmxnQ==", + "requires": { + "rc": "1.2.5", + "safe-buffer": "5.1.0" + } + }, + "registry-url": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/registry-url/-/registry-url-3.1.0.tgz", + "integrity": "sha1-PU74cPc93h138M+aOBQyRE4XSUI=", + "requires": { + "rc": "1.2.5" + } + }, + "regjsgen": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/regjsgen/-/regjsgen-0.2.0.tgz", + "integrity": "sha1-bAFq3qxVT3WCP+N6wFuS1aTtsfc=" + }, + "regjsparser": { + "version": "0.1.5", + "resolved": "https://registry.npmjs.org/regjsparser/-/regjsparser-0.1.5.tgz", + "integrity": "sha1-fuj4Tcb6eS0/0K4ijSS9lJ6tIFw=", + "requires": { + "jsesc": "1.3.0" + } }, "remote-redux-devtools": { "version": "0.5.11", "resolved": "https://registry.npmjs.org/remote-redux-devtools/-/remote-redux-devtools-0.5.11.tgz", "integrity": "sha1-x+gJ9fb+0Udg20p6EdzgOZwXA8o=", - "dev": true + "requires": { + "jsan": "3.1.9", + "querystring": "0.2.0", + "redux-devtools-instrument": "1.8.2", + "remotedev-utils": "0.1.4", + "rn-host-detect": "1.1.3", + "socketcluster-client": "5.5.1" + } }, "remotedev-serialize": { "version": "0.1.0", "resolved": "https://registry.npmjs.org/remotedev-serialize/-/remotedev-serialize-0.1.0.tgz", "integrity": "sha1-B0do6Yy3qoBvRZlO6wyK+VEg7jI=", - "dev": true + "requires": { + "jsan": "3.1.9" + } }, "remotedev-utils": { "version": "0.1.4", "resolved": "https://registry.npmjs.org/remotedev-utils/-/remotedev-utils-0.1.4.tgz", "integrity": "sha1-ZDcAgZqUNngHPHXrGF6B2WYgs0g=", - "dev": true + "requires": { + "get-params": "0.1.2", + "jsan": "3.1.9", + "lodash": "4.17.4", + "remotedev-serialize": "0.1.0", + "shortid": "2.2.8" + } }, "remove-trailing-separator": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/remove-trailing-separator/-/remove-trailing-separator-1.0.2.tgz", - "integrity": "sha1-abBi2XhyetFNxrVrpKt3L9jXBRE=", - "dev": true + "integrity": "sha1-abBi2XhyetFNxrVrpKt3L9jXBRE=" }, "remove-trailing-slash": { "version": "0.1.0", @@ -2152,38 +6577,83 @@ "repeat-element": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/repeat-element/-/repeat-element-1.1.2.tgz", - "integrity": "sha1-7wiaF40Ug7quTZPrmLT55OEdmQo=", - "dev": true + "integrity": "sha1-7wiaF40Ug7quTZPrmLT55OEdmQo=" }, "repeat-string": { "version": "1.6.1", "resolved": "https://registry.npmjs.org/repeat-string/-/repeat-string-1.6.1.tgz", - "integrity": "sha1-jcrkcOHIirwtYA//Sndihtp15jc=", - "dev": true + "integrity": "sha1-jcrkcOHIirwtYA//Sndihtp15jc=" }, "repeating": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/repeating/-/repeating-2.0.1.tgz", "integrity": "sha1-UhTFOpJtNVJwdSf7q0FdvAjQbdo=", - "dev": true + "requires": { + "is-finite": "1.0.2" + } + }, + "replace-ext": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/replace-ext/-/replace-ext-0.0.1.tgz", + "integrity": "sha1-KbvZIHinOfC8zitO5B6DeVNSKSQ=" }, "request": { "version": "2.81.0", "resolved": "https://registry.npmjs.org/request/-/request-2.81.0.tgz", "integrity": "sha1-xpKJRqDgbF+Nb4qTM0af/aRimKA=", - "dev": true + "requires": { + "aws-sign2": "0.6.0", + "aws4": "1.6.0", + "caseless": "0.12.0", + "combined-stream": "1.0.5", + "extend": "3.0.1", + "forever-agent": "0.6.1", + "form-data": "2.1.4", + "har-validator": "4.2.1", + "hawk": "3.1.3", + "http-signature": "1.1.1", + "is-typedarray": "1.0.0", + "isstream": "0.1.2", + "json-stringify-safe": "5.0.1", + "mime-types": "2.1.15", + "oauth-sign": "0.8.2", + "performance-now": "0.2.0", + "qs": "6.4.0", + "safe-buffer": "5.1.0", + "stringstream": "0.0.5", + "tough-cookie": "2.3.2", + "tunnel-agent": "0.6.0", + "uuid": "3.0.1" + } }, "request-progress": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/request-progress/-/request-progress-3.0.0.tgz", "integrity": "sha1-TKdUCBx/7GP1BeT6qCWqBs1mnb4=", - "dev": true + "dev": true, + "requires": { + "throttleit": "1.0.0" + } + }, + "require-directory": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", + "integrity": "sha1-jGStX9MNqxyXbiNE/+f3kqam30I=" }, "require-main-filename": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/require-main-filename/-/require-main-filename-1.0.1.tgz", - "integrity": "sha1-l/cXtp1IeE9fUmpsWqj/3aBVpNE=", - "dev": true + "integrity": "sha1-l/cXtp1IeE9fUmpsWqj/3aBVpNE=" + }, + "require-uncached": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/require-uncached/-/require-uncached-1.0.3.tgz", + "integrity": "sha1-Tg1W1slmL9MeQwEcS5WqSZVUIdM=", + "dev": true, + "requires": { + "caller-path": "0.1.0", + "resolve-from": "1.0.1" + } }, "reqwest": { "version": "2.0.5", @@ -2191,11 +6661,44 @@ "integrity": "sha1-APsVrEkYxBnKgrQ/JMeIguZgOaE=", "dev": true }, + "reselect": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/reselect/-/reselect-3.0.1.tgz", + "integrity": "sha1-79qpjqdFEyTQkrKyFjpqHXqaIUc=" + }, + "resolve": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.5.0.tgz", + "integrity": "sha512-hgoSGrc3pjzAPHNBg+KnFcK2HwlHTs/YrAGUr6qgTVUZmXv1UEXXl0bZNBKMA9fud6lRYFdPGz0xXxycPzmmiw==", + "requires": { + "path-parse": "1.0.5" + } + }, + "resolve-from": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-1.0.1.tgz", + "integrity": "sha1-Jsv+k10a7uq7Kbw/5a6wHpPUQiY=", + "dev": true + }, + "response-time": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/response-time/-/response-time-2.3.2.tgz", + "integrity": "sha1-/6cbq5UtYvfB1Jt0NDVfvGjf/Fo=", + "requires": { + "depd": "1.1.0", + "on-headers": "1.0.1" + } + }, "rest-facade": { "version": "1.5.0", "resolved": "https://registry.npmjs.org/rest-facade/-/rest-facade-1.5.0.tgz", "integrity": "sha1-nYhurwJWx+zJAsF8n3v5ByQ43O4=", "dev": true, + "requires": { + "bluebird": "2.11.0", + "change-case": "2.3.1", + "superagent": "3.5.2" + }, "dependencies": { "bluebird": { "version": "2.11.0", @@ -2209,43 +6712,62 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-2.0.0.tgz", "integrity": "sha1-n37ih/gv0ybU/RYpI9YhKe7g368=", - "dev": true + "requires": { + "onetime": "2.0.1", + "signal-exit": "3.0.2" + } + }, + "right-align": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/right-align/-/right-align-0.1.3.tgz", + "integrity": "sha1-YTObci/mo1FWiSENJOFMlhSGE+8=", + "requires": { + "align-text": "0.1.4" + } }, "rimraf": { "version": "2.6.1", "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.6.1.tgz", "integrity": "sha1-wjOOxkPfeht/5cVPqG9XQopV8z0=", - "dev": true + "requires": { + "glob": "7.1.2" + } }, "rn-host-detect": { "version": "1.1.3", "resolved": "https://registry.npmjs.org/rn-host-detect/-/rn-host-detect-1.1.3.tgz", - "integrity": "sha1-JC124vpIXEjXUUFuZbfM5ZaWnpE=", - "dev": true + "integrity": "sha1-JC124vpIXEjXUUFuZbfM5ZaWnpE=" + }, + "rndm": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/rndm/-/rndm-1.2.0.tgz", + "integrity": "sha1-8z/pz7Urv9UgqhgyO8ZdsRCht2w=" }, "run-async": { "version": "2.3.0", "resolved": "https://registry.npmjs.org/run-async/-/run-async-2.3.0.tgz", "integrity": "sha1-A3GrSuC91yDUFm19/aZP96RFpsA=", - "dev": true + "requires": { + "is-promise": "2.1.0" + } }, "rx-lite": { "version": "4.0.8", "resolved": "https://registry.npmjs.org/rx-lite/-/rx-lite-4.0.8.tgz", - "integrity": "sha1-Cx4Rr4vESDbwSmQH6S2kJGe3lEQ=", - "dev": true + "integrity": "sha1-Cx4Rr4vESDbwSmQH6S2kJGe3lEQ=" }, "rx-lite-aggregates": { "version": "4.0.8", "resolved": "https://registry.npmjs.org/rx-lite-aggregates/-/rx-lite-aggregates-4.0.8.tgz", "integrity": "sha1-dTuHqJoRyVRnxKwWJsTvxOBcZ74=", - "dev": true + "requires": { + "rx-lite": "4.0.8" + } }, "safe-buffer": { "version": "5.1.0", "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.0.tgz", - "integrity": "sha512-aSLEDudu6OoRr/2rU609gRmnYboRLxgDG1z9o2Q0os7236FwvcqIOO8r8U5JUEwivZOhDaKlFO4SbPTJYyBEyQ==", - "dev": true + "integrity": "sha512-aSLEDudu6OoRr/2rU609gRmnYboRLxgDG1z9o2Q0os7236FwvcqIOO8r8U5JUEwivZOhDaKlFO4SbPTJYyBEyQ==" }, "safe-json-stringify": { "version": "1.0.4", @@ -2254,61 +6776,126 @@ "dev": true, "optional": true }, + "samsam": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/samsam/-/samsam-1.3.0.tgz", + "integrity": "sha512-1HwIYD/8UlOtFS3QO3w7ey+SdSDFE4HRNLZoZRYVQefrOY3l17epswImeB1ijgJFQJodIaHcwkp3r/myBjFVbg==", + "dev": true + }, + "sane": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/sane/-/sane-1.4.1.tgz", + "integrity": "sha1-iPdj10BA9fDCVrYWPbOZvxEKxxU=", + "requires": { + "exec-sh": "0.2.1", + "fb-watchman": "1.9.2", + "minimatch": "3.0.4", + "minimist": "0.0.8", + "walker": "1.0.7", + "watch": "0.10.0" + }, + "dependencies": { + "bser": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/bser/-/bser-1.0.2.tgz", + "integrity": "sha1-OBEWlwsqbe6lZG3RXdcnhES1YWk=", + "requires": { + "node-int64": "0.4.0" + } + }, + "fb-watchman": { + "version": "1.9.2", + "resolved": "https://registry.npmjs.org/fb-watchman/-/fb-watchman-1.9.2.tgz", + "integrity": "sha1-okz0eCf4LTj7Waaa1wt247auc4M=", + "requires": { + "bser": "1.0.2" + } + } + } + }, + "sax": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/sax/-/sax-1.1.6.tgz", + "integrity": "sha1-XWFr6KXmB9VOEUr65Vt+ry/MMkA=" + }, "sc-channel": { "version": "1.0.6", "resolved": "https://registry.npmjs.org/sc-channel/-/sc-channel-1.0.6.tgz", "integrity": "sha1-s4vUepk+eCkPvFNGeGf2sqCghjk=", - "dev": true + "requires": { + "sc-emitter": "1.1.0" + } }, "sc-emitter": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/sc-emitter/-/sc-emitter-1.1.0.tgz", "integrity": "sha1-7xGdQiL0xk+Ie0hpZO8REWzdDnU=", - "dev": true, + "requires": { + "component-emitter": "1.2.0" + }, "dependencies": { "component-emitter": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/component-emitter/-/component-emitter-1.2.0.tgz", - "integrity": "sha1-zNETqGOI0GSC0D3j/H35hSa6jv4=", - "dev": true + "integrity": "sha1-zNETqGOI0GSC0D3j/H35hSa6jv4=" } } }, "sc-errors": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/sc-errors/-/sc-errors-1.2.1.tgz", - "integrity": "sha1-AkF9Pj8sELG7ZtQqrouv0uqzueI=", - "dev": true + "integrity": "sha1-AkF9Pj8sELG7ZtQqrouv0uqzueI=" }, "sc-formatter": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/sc-formatter/-/sc-formatter-3.0.0.tgz", - "integrity": "sha1-yRsf5WwmCr1aai5q+YxyS8eZijg=", - "dev": true + "integrity": "sha1-yRsf5WwmCr1aai5q+YxyS8eZijg=" }, "semver": { "version": "5.3.0", "resolved": "https://registry.npmjs.org/semver/-/semver-5.3.0.tgz", - "integrity": "sha1-myzl094C0XxgEq0yaqa00M9U+U8=", - "dev": true + "integrity": "sha1-myzl094C0XxgEq0yaqa00M9U+U8=" + }, + "semver-diff": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/semver-diff/-/semver-diff-2.1.0.tgz", + "integrity": "sha1-S7uEN8jTfksM8aaP1ybsbWRdbTY=", + "requires": { + "semver": "5.3.0" + } }, "send": { "version": "0.15.3", "resolved": "https://registry.npmjs.org/send/-/send-0.15.3.tgz", "integrity": "sha1-UBP5+ZAj31DRvZiSwZ4979HVMwk=", - "dev": true, + "requires": { + "debug": "2.6.7", + "depd": "1.1.0", + "destroy": "1.0.4", + "encodeurl": "1.0.1", + "escape-html": "1.0.3", + "etag": "1.8.0", + "fresh": "0.5.0", + "http-errors": "1.6.1", + "mime": "1.3.4", + "ms": "2.0.0", + "on-finished": "2.3.0", + "range-parser": "1.2.0", + "statuses": "1.3.1" + }, "dependencies": { "debug": { "version": "2.6.7", "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.7.tgz", "integrity": "sha1-krrR9tBbu2u6Isyoi80OyJTChh4=", - "dev": true + "requires": { + "ms": "2.0.0" + } }, "mime": { "version": "1.3.4", "resolved": "https://registry.npmjs.org/mime/-/mime-1.3.4.tgz", - "integrity": "sha1-EV+eO2s9rylZmDyzjxSaLUDrXVM=", - "dev": true + "integrity": "sha1-EV+eO2s9rylZmDyzjxSaLUDrXVM=" } } }, @@ -2316,13 +6903,100 @@ "version": "1.1.3", "resolved": "https://registry.npmjs.org/sentence-case/-/sentence-case-1.1.3.tgz", "integrity": "sha1-gDSq/CFFdy06vhUJqkLJ4QQtwTk=", - "dev": true + "dev": true, + "requires": { + "lower-case": "1.1.4" + } + }, + "sentry-cli-binary": { + "version": "1.25.0", + "resolved": "https://registry.npmjs.org/sentry-cli-binary/-/sentry-cli-binary-1.25.0.tgz", + "integrity": "sha1-YdEbAZcStbEHXkiHMdaWCyiVkYM=", + "requires": { + "progress": "2.0.0" + } + }, + "sentry-expo": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/sentry-expo/-/sentry-expo-1.7.0.tgz", + "integrity": "sha512-h+Xa45Qlzi6ICM/IqrSYEoz1HVFXExWs0kCXATgzwNlnexpUJsKPLpwgoavl2rNKtHQ4pNGcgAH7MYGzUo5Q8A==", + "requires": { + "@expo/spawn-async": "1.3.0", + "mkdirp": "0.5.1", + "react-native-sentry": "0.30.3", + "rimraf": "2.6.1" + }, + "dependencies": { + "react-native-sentry": { + "version": "0.30.3", + "resolved": "https://registry.npmjs.org/react-native-sentry/-/react-native-sentry-0.30.3.tgz", + "integrity": "sha1-tk5ZEnBwUhqsUXJCNVQ+id717nM=", + "requires": { + "chalk": "1.1.3", + "glob": "7.1.2", + "inquirer": "3.1.0", + "raven-js": "3.22.4", + "sentry-cli-binary": "1.25.0", + "xcode": "1.0.0" + } + }, + "xcode": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/xcode/-/xcode-1.0.0.tgz", + "integrity": "sha1-4fWxRDJF3tOMGAeW3xoQ/e2ghOw=", + "requires": { + "pegjs": "0.10.0", + "simple-plist": "0.2.1", + "uuid": "3.0.1" + } + } + } + }, + "serve-favicon": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/serve-favicon/-/serve-favicon-2.3.2.tgz", + "integrity": "sha1-3UGeJo3gEqtysxnTN/IQUBP5OB8=", + "requires": { + "etag": "1.8.0", + "fresh": "0.5.0", + "ms": "2.0.0", + "parseurl": "1.3.1" + } + }, + "serve-index": { + "version": "1.7.3", + "resolved": "https://registry.npmjs.org/serve-index/-/serve-index-1.7.3.tgz", + "integrity": "sha1-egV/xu4o3GP2RWbl+lexEahq7NI=", + "requires": { + "accepts": "1.3.3", + "batch": "0.5.3", + "debug": "2.6.8", + "escape-html": "1.0.3", + "http-errors": "1.6.1", + "mime-types": "2.1.15", + "parseurl": "1.3.1" + } }, "serve-static": { "version": "1.12.3", "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.12.3.tgz", "integrity": "sha1-n0uhni8wMMVH+K+ZEHg47DjVseI=", - "dev": true + "requires": { + "encodeurl": "1.0.1", + "escape-html": "1.0.3", + "parseurl": "1.3.1", + "send": "0.15.3" + } + }, + "server-destroy": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/server-destroy/-/server-destroy-1.0.1.tgz", + "integrity": "sha1-8Tv5KOQrnD55OD5hzDmYtdFObN0=" + }, + "set-blocking": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", + "integrity": "sha1-BF+XgtARrppoA93TgrJDkrPYkPc=" }, "setimmediate": { "version": "1.0.5", @@ -2332,44 +7006,133 @@ "setprototypeof": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.0.3.tgz", - "integrity": "sha1-ZlZ+NwQ+608E2RvWWMDL77VbjgQ=", - "dev": true + "integrity": "sha1-ZlZ+NwQ+608E2RvWWMDL77VbjgQ=" }, "shebang-command": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-1.2.0.tgz", "integrity": "sha1-RKrGW2lbAzmJaMOfNj/uXer98eo=", - "dev": true + "requires": { + "shebang-regex": "1.0.0" + } }, "shebang-regex": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-1.0.0.tgz", - "integrity": "sha1-2kL0l0DAtC2yypcoVxyxkMmO/qM=", - "dev": true + "integrity": "sha1-2kL0l0DAtC2yypcoVxyxkMmO/qM=" + }, + "shell-quote": { + "version": "1.6.1", + "resolved": "https://registry.npmjs.org/shell-quote/-/shell-quote-1.6.1.tgz", + "integrity": "sha1-9HgZSczkAmlxJ0MOo7PFR29IF2c=", + "requires": { + "array-filter": "0.0.1", + "array-map": "0.0.0", + "array-reduce": "0.0.0", + "jsonify": "0.0.0" + } + }, + "shelljs": { + "version": "0.7.8", + "resolved": "https://registry.npmjs.org/shelljs/-/shelljs-0.7.8.tgz", + "integrity": "sha1-3svPh0sNHl+3LhSxZKloMEjprLM=", + "dev": true, + "requires": { + "glob": "7.1.2", + "interpret": "1.1.0", + "rechoir": "0.6.2" + } }, "shortid": { "version": "2.2.8", "resolved": "https://registry.npmjs.org/shortid/-/shortid-2.2.8.tgz", - "integrity": "sha1-AzsRfWoul1gE9vCWnb59PQs1UTE=", - "dev": true + "integrity": "sha1-AzsRfWoul1gE9vCWnb59PQs1UTE=" }, "signal-exit": { "version": "3.0.2", "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.2.tgz", - "integrity": "sha1-tf3AjxKH6hF4Yo5BXiUTK3NkbG0=", - "dev": true + "integrity": "sha1-tf3AjxKH6hF4Yo5BXiUTK3NkbG0=" + }, + "simple-plist": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/simple-plist/-/simple-plist-0.2.1.tgz", + "integrity": "sha1-cXZts1IyaSjPOoByQrp2IyJjZyM=", + "requires": { + "bplist-creator": "0.0.7", + "bplist-parser": "0.1.1", + "plist": "2.0.1" + }, + "dependencies": { + "base64-js": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.1.2.tgz", + "integrity": "sha1-1kAMrBxMZgl22Q0HoENR2JOV9eg=" + }, + "plist": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/plist/-/plist-2.0.1.tgz", + "integrity": "sha1-CjLKlIGxw2TpLhjcVch23p0B2os=", + "requires": { + "base64-js": "1.1.2", + "xmlbuilder": "8.2.2", + "xmldom": "0.1.27" + } + }, + "xmlbuilder": { + "version": "8.2.2", + "resolved": "https://registry.npmjs.org/xmlbuilder/-/xmlbuilder-8.2.2.tgz", + "integrity": "sha1-aSSGc0ELS6QuGmE2VR0pIjNap3M=" + } + } + }, + "simple-swizzle": { + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/simple-swizzle/-/simple-swizzle-0.2.2.tgz", + "integrity": "sha1-pNprY1/8zMoz9w0Xy5JZLeleVXo=", + "requires": { + "is-arrayish": "0.2.1" + } + }, + "sinon": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/sinon/-/sinon-2.4.1.tgz", + "integrity": "sha512-vFTrO9Wt0ECffDYIPSP/E5bBugt0UjcBQOfQUMh66xzkyPEnhl/vM2LRZi2ajuTdkH07sA6DzrM6KvdvGIH8xw==", + "dev": true, + "requires": { + "diff": "3.4.0", + "formatio": "1.2.0", + "lolex": "1.6.0", + "native-promise-only": "0.8.1", + "path-to-regexp": "0.1.7", + "samsam": "1.3.0", + "text-encoding": "0.6.4", + "type-detect": "4.0.8" + } }, "slash": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/slash/-/slash-1.0.0.tgz", - "integrity": "sha1-xB8vbDn8FtHNF61LXYlhFK5HDVU=", + "integrity": "sha1-xB8vbDn8FtHNF61LXYlhFK5HDVU=" + }, + "slice-ansi": { + "version": "0.0.4", + "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-0.0.4.tgz", + "integrity": "sha1-7b+JA/ZvfOL46v1s7tZeJkyDGzU=", "dev": true }, + "slide": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/slide/-/slide-1.1.6.tgz", + "integrity": "sha1-VusCfWW00tzmyy4tMsTUr8nh1wc=" + }, "slugid": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/slugid/-/slugid-1.1.0.tgz", "integrity": "sha1-4J8AiZwJ9acFjtw23UnwRv1QqCo=", "dev": true, + "requires": { + "uuid": "2.0.3" + }, "dependencies": { "uuid": { "version": "2.0.3", @@ -2389,105 +7152,207 @@ "version": "1.1.2", "resolved": "https://registry.npmjs.org/snake-case/-/snake-case-1.1.2.tgz", "integrity": "sha1-DC8l4wUVjZoY09l3BmGH/vilpmo=", - "dev": true + "dev": true, + "requires": { + "sentence-case": "1.1.3" + } }, "sntp": { "version": "1.0.9", "resolved": "https://registry.npmjs.org/sntp/-/sntp-1.0.9.tgz", "integrity": "sha1-ZUEYTMkK7qbG57NeJlkIJEPGYZg=", - "dev": true + "requires": { + "hoek": "2.16.3" + } }, "socketcluster-client": { "version": "5.5.1", "resolved": "https://registry.npmjs.org/socketcluster-client/-/socketcluster-client-5.5.1.tgz", "integrity": "sha1-VmqsBeixNzDX5SSY6xrWc6bfHKM=", - "dev": true + "requires": { + "base-64": "0.1.0", + "clone": "2.1.1", + "linked-list": "0.1.0", + "querystring": "0.2.0", + "sc-channel": "1.0.6", + "sc-emitter": "1.1.0", + "sc-errors": "1.2.1", + "sc-formatter": "3.0.0", + "ws": "3.0.0" + } }, "source-map": { "version": "0.5.6", "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.6.tgz", - "integrity": "sha1-dc449SvwczxafwwRjYEzSiu19BI=", - "dev": true + "integrity": "sha1-dc449SvwczxafwwRjYEzSiu19BI=" }, "source-map-support": { "version": "0.4.15", "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.4.15.tgz", "integrity": "sha1-AyAt9lwG0r2MfsI2KhkwVv7407E=", - "dev": true + "requires": { + "source-map": "0.5.6" + } + }, + "sparkles": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/sparkles/-/sparkles-1.0.0.tgz", + "integrity": "sha1-Gsu/tZJDbRC76PeFt8xvgoFQEsM=" }, "spdx-correct": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/spdx-correct/-/spdx-correct-1.0.2.tgz", "integrity": "sha1-SzBz2TP/UfORLwOsVRlJikFQ20A=", - "dev": true + "requires": { + "spdx-license-ids": "1.2.2" + } }, "spdx-expression-parse": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/spdx-expression-parse/-/spdx-expression-parse-1.0.4.tgz", - "integrity": "sha1-m98vIOH0DtRH++JzJmGR/O1RYmw=", - "dev": true + "integrity": "sha1-m98vIOH0DtRH++JzJmGR/O1RYmw=" }, "spdx-license-ids": { "version": "1.2.2", "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-1.2.2.tgz", - "integrity": "sha1-yd96NCRZSt5r0RkA1ZZpbcBrrFc=", + "integrity": "sha1-yd96NCRZSt5r0RkA1ZZpbcBrrFc=" + }, + "sprintf-js": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", + "integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw=", "dev": true }, "sshpk": { "version": "1.13.1", "resolved": "https://registry.npmjs.org/sshpk/-/sshpk-1.13.1.tgz", "integrity": "sha1-US322mKHFEMW3EwY/hzx2UBzm+M=", - "dev": true, + "requires": { + "asn1": "0.2.3", + "assert-plus": "1.0.0", + "bcrypt-pbkdf": "1.0.1", + "dashdash": "1.14.1", + "ecc-jsbn": "0.1.1", + "getpass": "0.1.7", + "jsbn": "0.1.1", + "tweetnacl": "0.14.5" + }, "dependencies": { "assert-plus": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", - "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=", - "dev": true + "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=" } } }, + "stacktrace-parser": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/stacktrace-parser/-/stacktrace-parser-0.1.4.tgz", + "integrity": "sha1-ATl5IuX2Ls8whFUiyVxP4dJefU4=" + }, "statuses": { "version": "1.3.1", "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.3.1.tgz", - "integrity": "sha1-+vUbnrdKrvOzrPStX2Gr8ky3uT4=", - "dev": true + "integrity": "sha1-+vUbnrdKrvOzrPStX2Gr8ky3uT4=" + }, + "steno": { + "version": "0.4.4", + "resolved": "https://registry.npmjs.org/steno/-/steno-0.4.4.tgz", + "integrity": "sha1-BxEFvfwobmYVwEA8J+nXtdy4Vcs=", + "requires": { + "graceful-fs": "4.1.11" + } + }, + "stream-buffers": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/stream-buffers/-/stream-buffers-2.2.0.tgz", + "integrity": "sha1-kdX1Ew0c75bc+n9yaUUYh0HQnuQ=" + }, + "stream-counter": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/stream-counter/-/stream-counter-0.2.0.tgz", + "integrity": "sha1-3tJmVWMZyLDiIoErnPOyb6fZR94=", + "requires": { + "readable-stream": "1.1.14" + } + }, + "strict-uri-encode": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/strict-uri-encode/-/strict-uri-encode-1.1.0.tgz", + "integrity": "sha1-J5siXfHVgrH1TmWt3UNS4Y+qBxM=" + }, + "string-width": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", + "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=", + "requires": { + "code-point-at": "1.1.0", + "is-fullwidth-code-point": "1.0.0", + "strip-ansi": "3.0.1" + } }, "string_decoder": { "version": "0.10.31", "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", - "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=", - "dev": true + "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=" }, "stringstream": { "version": "0.0.5", "resolved": "https://registry.npmjs.org/stringstream/-/stringstream-0.0.5.tgz", - "integrity": "sha1-TkhM1N5aC7vuGORjB3EKioFiGHg=", - "dev": true + "integrity": "sha1-TkhM1N5aC7vuGORjB3EKioFiGHg=" }, "strip-ansi": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", - "dev": true + "requires": { + "ansi-regex": "2.1.1" + } }, "strip-bom": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-2.0.0.tgz", "integrity": "sha1-YhmoVhZSBJHzV4i9vxRHqZx+aw4=", - "dev": true + "requires": { + "is-utf8": "0.2.1" + } + }, + "strip-json-comments": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz", + "integrity": "sha1-PFMZQukIwml8DsNEhYwobHygpgo=" }, "superagent": { "version": "3.5.2", "resolved": "https://registry.npmjs.org/superagent/-/superagent-3.5.2.tgz", "integrity": "sha1-M2GjlxVnUEw1EGOr6q4PqiPb8/g=", "dev": true, + "requires": { + "component-emitter": "1.2.1", + "cookiejar": "2.1.1", + "debug": "2.6.8", + "extend": "3.0.1", + "form-data": "2.1.4", + "formidable": "1.1.1", + "methods": "1.1.2", + "mime": "1.3.6", + "qs": "6.4.0", + "readable-stream": "2.2.11" + }, "dependencies": { "readable-stream": { "version": "2.2.11", "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.2.11.tgz", "integrity": "sha512-h+8+r3MKEhkiVrwdKL8aWs1oc1VvBu33ueshOvS26RsZQ3Amhx/oO3TKe4lApSV9ueY6as8EAh7mtuFjdlhg9Q==", - "dev": true + "dev": true, + "requires": { + "core-util-is": "1.0.2", + "inherits": "2.0.3", + "isarray": "1.0.0", + "safe-buffer": "5.0.1", + "string_decoder": "1.0.2", + "util-deprecate": "1.0.2" + } }, "safe-buffer": { "version": "5.0.1", @@ -2499,7 +7364,10 @@ "version": "1.0.2", "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.0.2.tgz", "integrity": "sha1-sp4fThEl+pehA4K4pTNze3SR4Xk=", - "dev": true + "dev": true, + "requires": { + "safe-buffer": "5.0.1" + } } } }, @@ -2512,31 +7380,78 @@ "supports-color": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz", - "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=", - "dev": true + "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=" }, "swap-case": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/swap-case/-/swap-case-1.1.2.tgz", "integrity": "sha1-w5IDpFhzhfrTyFCgvRvK+ggZdOM=", - "dev": true + "dev": true, + "requires": { + "lower-case": "1.1.4", + "upper-case": "1.1.3" + } }, "symbol-observable": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/symbol-observable/-/symbol-observable-1.0.4.tgz", "integrity": "sha1-Kb9hXUqnEhvdiYsi1LP5vE4qoD0=" }, + "table": { + "version": "3.8.3", + "resolved": "https://registry.npmjs.org/table/-/table-3.8.3.tgz", + "integrity": "sha1-K7xULw/amGGnVdOUf+/Ys/UThV8=", + "dev": true, + "requires": { + "ajv": "4.11.8", + "ajv-keywords": "1.5.1", + "chalk": "1.1.3", + "lodash": "4.17.4", + "slice-ansi": "0.0.4", + "string-width": "2.1.1" + }, + "dependencies": { + "is-fullwidth-code-point": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", + "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=", + "dev": true + }, + "string-width": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz", + "integrity": "sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw==", + "dev": true, + "requires": { + "is-fullwidth-code-point": "2.0.0", + "strip-ansi": "3.0.1" + } + } + } + }, "tar": { "version": "2.2.1", "resolved": "https://registry.npmjs.org/tar/-/tar-2.2.1.tgz", "integrity": "sha1-jk0qJWwOIYXGsYrWlK7JaLg8sdE=", - "dev": true + "dev": true, + "requires": { + "block-stream": "0.0.9", + "fstream": "1.0.11", + "inherits": "2.0.3" + } }, "tar.gz": { "version": "1.0.5", "resolved": "https://registry.npmjs.org/tar.gz/-/tar.gz-1.0.5.tgz", "integrity": "sha1-4a2n5F7yJBtLHuWBI8j0C108G8Q=", "dev": true, + "requires": { + "bluebird": "2.11.0", + "commander": "2.9.0", + "fstream": "1.0.11", + "mout": "0.11.1", + "tar": "2.2.1" + }, "dependencies": { "bluebird": { "version": "2.11.0", @@ -2546,23 +7461,62 @@ } } }, + "temp": { + "version": "0.8.3", + "resolved": "https://registry.npmjs.org/temp/-/temp-0.8.3.tgz", + "integrity": "sha1-4Ma8TSa5AxJEEOT+2BEDAU38H1k=", + "requires": { + "os-tmpdir": "1.0.2", + "rimraf": "2.6.1" + } + }, "test-exclude": { "version": "4.1.1", "resolved": "https://registry.npmjs.org/test-exclude/-/test-exclude-4.1.1.tgz", "integrity": "sha512-35+Asrsk3XHJDBgf/VRFexPgh3UyETv8IAn/LRTiZjVy6rjPVqdEk8dJcJYBzl1w0XCJM48lvTy8SfEsCWS4nA==", + "dev": true, + "requires": { + "arrify": "1.0.1", + "micromatch": "2.3.11", + "object-assign": "4.1.1", + "read-pkg-up": "1.0.1", + "require-main-filename": "1.0.1" + } + }, + "text-encoding": { + "version": "0.6.4", + "resolved": "https://registry.npmjs.org/text-encoding/-/text-encoding-0.6.4.tgz", + "integrity": "sha1-45mpgiV6J22uQou5KEXLcb3CbRk=", + "dev": true + }, + "text-table": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", + "integrity": "sha1-f17oI66AUgfACvLfSoTsP8+lcLQ=", "dev": true }, "thenify": { "version": "3.3.0", "resolved": "https://registry.npmjs.org/thenify/-/thenify-3.3.0.tgz", "integrity": "sha1-5p44obq+lpsBCCB5eLn2K4hgSDk=", - "dev": true + "dev": true, + "requires": { + "any-promise": "1.3.0" + } }, "thenify-all": { "version": "1.6.0", "resolved": "https://registry.npmjs.org/thenify-all/-/thenify-all-1.6.0.tgz", "integrity": "sha1-GhkY1ALY/D+Y+/I02wvMjMEOlyY=", - "dev": true + "dev": true, + "requires": { + "thenify": "3.3.0" + } + }, + "throat": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/throat/-/throat-3.2.0.tgz", + "integrity": "sha512-/EY8VpvlqJ+sFtLPeOgc8Pl7kQVOWv0woD87KTXVHPIAE842FGT+rokxIhe8xIUP1cfgrkt0as0vDLjDiMtr8w==" }, "throttleit": { "version": "1.0.0", @@ -2573,32 +7527,68 @@ "through": { "version": "2.3.8", "resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz", - "integrity": "sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU=", - "dev": true + "integrity": "sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU=" + }, + "through2": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/through2/-/through2-2.0.3.tgz", + "integrity": "sha1-AARWmzfHx0ujnEPzzteNGtlBQL4=", + "requires": { + "readable-stream": "1.1.14", + "xtend": "4.0.1" + } + }, + "time-stamp": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/time-stamp/-/time-stamp-1.1.0.tgz", + "integrity": "sha1-dkpaEa9QVhkhsTPztE5hhofg9cM=" + }, + "timed-out": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/timed-out/-/timed-out-3.1.3.tgz", + "integrity": "sha1-lYYL/MXHbCd/j4Mm/Q9bLiDrohc=" + }, + "tiny-queue": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/tiny-queue/-/tiny-queue-0.2.1.tgz", + "integrity": "sha1-JaZ/LG4lOyypQZd7XvdELvl6YEY=" }, "title-case": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/title-case/-/title-case-1.1.2.tgz", "integrity": "sha1-+uSmrlRr+iLQg6DuqRCkDRLtT1o=", - "dev": true + "dev": true, + "requires": { + "sentence-case": "1.1.3", + "upper-case": "1.1.3" + } }, "tmp": { "version": "0.0.31", "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.0.31.tgz", "integrity": "sha1-jzirlDjhcxXl29izZX6L+yd65Kc=", - "dev": true + "requires": { + "os-tmpdir": "1.0.2" + } + }, + "tmpl": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/tmpl/-/tmpl-1.0.4.tgz", + "integrity": "sha1-I2QN17QtAEM5ERQIIOXPRA5SHdE=" }, "to-fast-properties": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-1.0.3.tgz", - "integrity": "sha1-uDVx+k2MJbguIxsG46MFXeTKGkc=", - "dev": true + "integrity": "sha1-uDVx+k2MJbguIxsG46MFXeTKGkc=" }, "topo": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/topo/-/topo-2.0.2.tgz", "integrity": "sha1-zVYVdSU5BXwNwEkaYhw7xvvh0YI=", "dev": true, + "requires": { + "hoek": "4.1.1" + }, "dependencies": { "hoek": { "version": "4.1.1", @@ -2613,12 +7603,18 @@ "resolved": "https://registry.npmjs.org/touch/-/touch-0.0.3.tgz", "integrity": "sha1-Ua7z1ElXHU8oel2Hyci0kYGg2x0=", "dev": true, + "requires": { + "nopt": "1.0.10" + }, "dependencies": { "nopt": { "version": "1.0.10", "resolved": "https://registry.npmjs.org/nopt/-/nopt-1.0.10.tgz", "integrity": "sha1-bd0hvSoxQXuScn3Vhfim83YI6+4=", - "dev": true + "dev": true, + "requires": { + "abbrev": "1.1.0" + } } } }, @@ -2626,7 +7622,9 @@ "version": "2.3.2", "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.3.2.tgz", "integrity": "sha1-8IH3bkyFcg5sN6X6ztc3FQ2EByo=", - "dev": true + "requires": { + "punycode": "1.4.1" + } }, "traverse": { "version": "0.3.9", @@ -2649,50 +7647,162 @@ "trim-right": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/trim-right/-/trim-right-1.0.1.tgz", - "integrity": "sha1-yy4SAwZ+DI3h9hQJS5/kVwTqYAM=", - "dev": true + "integrity": "sha1-yy4SAwZ+DI3h9hQJS5/kVwTqYAM=" + }, + "tsscmp": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/tsscmp/-/tsscmp-1.0.5.tgz", + "integrity": "sha1-fcSjOvcVgatDN9qR2FylQn69mpc=" }, "tunnel-agent": { "version": "0.6.0", "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz", "integrity": "sha1-J6XeoGs2sEoKmWZ3SykIaPD8QP0=", - "dev": true + "requires": { + "safe-buffer": "5.1.0" + } + }, + "tween-functions": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/tween-functions/-/tween-functions-1.2.0.tgz", + "integrity": "sha1-GuOlDnxguz3vd06scHrLynO7w/8=" }, "tweetnacl": { "version": "0.14.5", "resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-0.14.5.tgz", "integrity": "sha1-WuaBd/GS1EViadEIr6k/+HQ/T2Q=", - "dev": true, "optional": true }, + "type-check": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.3.2.tgz", + "integrity": "sha1-WITKtRLPHTVeP7eE8wgEsrUg23I=", + "dev": true, + "requires": { + "prelude-ls": "1.1.2" + } + }, + "type-detect": { + "version": "4.0.8", + "resolved": "https://registry.npmjs.org/type-detect/-/type-detect-4.0.8.tgz", + "integrity": "sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g==", + "dev": true + }, "type-is": { "version": "1.6.15", "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.15.tgz", "integrity": "sha1-yrEPtJCeRByChC6v4a1kbIGARBA=", - "dev": true + "requires": { + "media-typer": "0.3.0", + "mime-types": "2.1.15" + } + }, + "typedarray": { + "version": "0.0.6", + "resolved": "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz", + "integrity": "sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c=" }, "ua-parser-js": { "version": "0.7.12", "resolved": "https://registry.npmjs.org/ua-parser-js/-/ua-parser-js-0.7.12.tgz", "integrity": "sha1-BMgamb3V3FImPqKdJMa/jUgYpLs=" }, + "uglify-js": { + "version": "2.7.5", + "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-2.7.5.tgz", + "integrity": "sha1-RhLAx7qu4rp8SH3kkErhIgefLKg=", + "requires": { + "async": "0.2.10", + "source-map": "0.5.6", + "uglify-to-browserify": "1.0.2", + "yargs": "3.10.0" + }, + "dependencies": { + "async": { + "version": "0.2.10", + "resolved": "https://registry.npmjs.org/async/-/async-0.2.10.tgz", + "integrity": "sha1-trvgsGdLnXGXCMo43owjfLUmw9E=" + }, + "camelcase": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-1.2.1.tgz", + "integrity": "sha1-m7UwTS4LVmmLLHWLCKPqqdqlijk=" + }, + "cliui": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-2.1.0.tgz", + "integrity": "sha1-S0dXYP+AJkx2LDoXGQMukcf+oNE=", + "requires": { + "center-align": "0.1.3", + "right-align": "0.1.3", + "wordwrap": "0.0.2" + } + }, + "wordwrap": { + "version": "0.0.2", + "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-0.0.2.tgz", + "integrity": "sha1-t5Zpu0LstAn4PVg8rVLKF+qhZD8=" + }, + "yargs": { + "version": "3.10.0", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-3.10.0.tgz", + "integrity": "sha1-9+572FfdfB0tOMDnTvvWgdFDH9E=", + "requires": { + "camelcase": "1.2.1", + "cliui": "2.1.0", + "decamelize": "1.2.0", + "window-size": "0.1.0" + } + } + } + }, + "uglify-to-browserify": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/uglify-to-browserify/-/uglify-to-browserify-1.0.2.tgz", + "integrity": "sha1-bgkk1r2mta/jSeOabWMoUKD4grc=" + }, + "uid-safe": { + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/uid-safe/-/uid-safe-2.1.4.tgz", + "integrity": "sha1-Otbzg2jG1MjHXsF2I/t5qh0HHYE=", + "requires": { + "random-bytes": "1.0.0" + } + }, "ultron": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/ultron/-/ultron-1.1.0.tgz", - "integrity": "sha1-sHoualQagV/Go0zNRTO67DB8qGQ=", - "dev": true + "integrity": "sha1-sHoualQagV/Go0zNRTO67DB8qGQ=" }, "universalify": { "version": "0.1.0", "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.1.0.tgz", - "integrity": "sha1-nrHEZR3rzGcMyU8adXYjMruWd3g=", - "dev": true + "integrity": "sha1-nrHEZR3rzGcMyU8adXYjMruWd3g=" }, "unpipe": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", - "integrity": "sha1-sr9O6FFKrmFltIF4KdIbLvSZBOw=", - "dev": true + "integrity": "sha1-sr9O6FFKrmFltIF4KdIbLvSZBOw=" + }, + "unzip-response": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/unzip-response/-/unzip-response-1.0.2.tgz", + "integrity": "sha1-uYTwh3/AqJwsdzzB73tbIytbBv4=" + }, + "update-notifier": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/update-notifier/-/update-notifier-1.0.3.tgz", + "integrity": "sha1-j5LFFUgr1oMbfJMBPnD4dVLHz1o=", + "requires": { + "boxen": "0.6.0", + "chalk": "1.1.3", + "configstore": "2.1.0", + "is-npm": "1.0.0", + "latest-version": "2.0.0", + "lazy-req": "1.1.0", + "semver-diff": "2.1.0", + "xdg-basedir": "2.0.0" + } }, "upper-case": { "version": "1.1.3", @@ -2704,13 +7814,20 @@ "version": "1.1.2", "resolved": "https://registry.npmjs.org/upper-case-first/-/upper-case-first-1.1.2.tgz", "integrity": "sha1-XXm+3P8UQZUY/S7bCgUHybaFkRU=", - "dev": true + "dev": true, + "requires": { + "upper-case": "1.1.3" + } }, "url": { "version": "0.11.0", "resolved": "https://registry.npmjs.org/url/-/url-0.11.0.tgz", "integrity": "sha1-ODjpfPxgUh63PFJajlW/3Z4uKPE=", "dev": true, + "requires": { + "punycode": "1.3.2", + "querystring": "0.2.0" + }, "dependencies": { "punycode": { "version": "1.3.2", @@ -2726,35 +7843,102 @@ "integrity": "sha1-HbSK1CLTQCRpqH99l73r/k+x48g=", "dev": true }, + "url-parse-lax": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/url-parse-lax/-/url-parse-lax-1.0.0.tgz", + "integrity": "sha1-evjzA2Rem9eaJy56FKxovAYJ2nM=", + "requires": { + "prepend-http": "1.0.4" + } + }, + "user-home": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/user-home/-/user-home-2.0.0.tgz", + "integrity": "sha1-nHC/2Babwdy/SGBODwS4tJzenp8=", + "dev": true, + "requires": { + "os-homedir": "1.0.2" + } + }, + "util-deprecate": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", + "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=" + }, "utils-merge": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.0.tgz", - "integrity": "sha1-ApT7kiu5N1FTVBxPcJYjHyh8ivg=", - "dev": true + "integrity": "sha1-ApT7kiu5N1FTVBxPcJYjHyh8ivg=" }, "uuid": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.0.1.tgz", - "integrity": "sha1-ZUS7ot/ajBzxfmKaOjBeK7H+5sE=", - "dev": true + "integrity": "sha1-ZUS7ot/ajBzxfmKaOjBeK7H+5sE=" + }, + "uuid-js": { + "version": "0.7.5", + "resolved": "https://registry.npmjs.org/uuid-js/-/uuid-js-0.7.5.tgz", + "integrity": "sha1-bIhtAqU9LUDc8l2RoXC0p7JblNA=" }, "validate-npm-package-license": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/validate-npm-package-license/-/validate-npm-package-license-3.0.1.tgz", "integrity": "sha1-KAS6vnEq0zeUWaz74kdGqywwP7w=", - "dev": true + "requires": { + "spdx-correct": "1.0.2", + "spdx-expression-parse": "1.0.4" + } }, "vary": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.1.tgz", - "integrity": "sha1-Z1Neu2lMHVIldFeYRmUyP1h+jTc=", - "dev": true + "integrity": "sha1-Z1Neu2lMHVIldFeYRmUyP1h+jTc=" }, "verror": { "version": "1.3.6", "resolved": "https://registry.npmjs.org/verror/-/verror-1.3.6.tgz", "integrity": "sha1-z/XfEpRtKX0rqu+qJoniW+AcAFw=", - "dev": true + "requires": { + "extsprintf": "1.0.2" + } + }, + "vhost": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/vhost/-/vhost-3.0.2.tgz", + "integrity": "sha1-L7HezUxGaqiLD5NBrzPcGv8keNU=" + }, + "vinyl": { + "version": "0.5.3", + "resolved": "https://registry.npmjs.org/vinyl/-/vinyl-0.5.3.tgz", + "integrity": "sha1-sEVbOPxeDPMNQyUTLkYZcMIJHN4=", + "requires": { + "clone": "2.1.1", + "clone-stats": "0.0.1", + "replace-ext": "0.0.1" + } + }, + "walker": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/walker/-/walker-1.0.7.tgz", + "integrity": "sha1-L3+bj9ENZ3JisYqITijRlhjgKPs=", + "requires": { + "makeerror": "1.0.11" + } + }, + "watch": { + "version": "0.10.0", + "resolved": "https://registry.npmjs.org/watch/-/watch-0.10.0.tgz", + "integrity": "sha1-d3mLLaD5kQ1ZXxrOWwwiWFIfIdw=" + }, + "websql": { + "version": "github:expo/node-websql#e364fa65146a9e2157a19e5c719e7702c2b6b87a", + "requires": { + "argsarray": "0.0.1", + "immediate": "3.2.3", + "noop-fn": "1.0.0", + "pouchdb-collections": "1.0.1", + "tiny-queue": "0.2.1" + } }, "whatwg-fetch": { "version": "2.0.3", @@ -2765,7 +7949,22 @@ "version": "1.2.14", "resolved": "https://registry.npmjs.org/which/-/which-1.2.14.tgz", "integrity": "sha1-mofEN48D6CfOyvGs31bHNsAcFOU=", - "dev": true + "requires": { + "isexe": "2.0.0" + } + }, + "which-module": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/which-module/-/which-module-1.0.0.tgz", + "integrity": "sha1-u6Y8qGGUiZT/MHc2CJ47lgJsKk8=" + }, + "widest-line": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/widest-line/-/widest-line-1.0.0.tgz", + "integrity": "sha1-DAnIXCqUaD0Nfq+O4JfVZL8OEFw=", + "requires": { + "string-width": "1.0.2" + } }, "winchan": { "version": "0.1.4", @@ -2773,43 +7972,176 @@ "integrity": "sha1-iPoSQRzVQutiYBjDihlry7F5k7s=", "dev": true }, + "window-size": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/window-size/-/window-size-0.1.0.tgz", + "integrity": "sha1-VDjNLqk7IC76Ohn+iIeu58lPnJ0=" + }, + "wordwrap": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-1.0.0.tgz", + "integrity": "sha1-J1hIEIkUVqQXHI0CJkQa3pDLyus=" + }, + "worker-farm": { + "version": "1.5.4", + "resolved": "https://registry.npmjs.org/worker-farm/-/worker-farm-1.5.4.tgz", + "integrity": "sha512-ITyClEvcfv0ozqJl1vmWFWhvI+OIrkbInYqkEPE50wFPXj8J9Gd3FYf8+CkZJXJJsQBYe+2DvmoK9Zhx5w8W+w==", + "requires": { + "errno": "0.1.7", + "xtend": "4.0.1" + } + }, + "wrap-ansi": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-2.1.0.tgz", + "integrity": "sha1-2Pw9KE3QV5T+hJc8rs3Rz4JP3YU=", + "requires": { + "string-width": "1.0.2", + "strip-ansi": "3.0.1" + } + }, "wrappy": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", - "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=", - "dev": true + "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=" + }, + "write": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/write/-/write-0.2.1.tgz", + "integrity": "sha1-X8A4KOJkzqP+kUVUdvejxWbLB1c=", + "dev": true, + "requires": { + "mkdirp": "0.5.1" + } + }, + "write-file-atomic": { + "version": "1.3.4", + "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-1.3.4.tgz", + "integrity": "sha1-+Aek8LHZ6ROuekgRLmzDrxmRtF8=", + "requires": { + "graceful-fs": "4.1.11", + "imurmurhash": "0.1.4", + "slide": "1.1.6" + } }, "ws": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/ws/-/ws-3.0.0.tgz", "integrity": "sha1-mN2wAFbIOQy3Ued4h4hJf5kQO2w=", - "dev": true, + "requires": { + "safe-buffer": "5.0.1", + "ultron": "1.1.0" + }, "dependencies": { "safe-buffer": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.0.1.tgz", - "integrity": "sha1-0mPKVGls2KMGtcplUekt5XkY++c=", - "dev": true + "integrity": "sha1-0mPKVGls2KMGtcplUekt5XkY++c=" } } }, + "xcode": { + "version": "0.9.3", + "resolved": "https://registry.npmjs.org/xcode/-/xcode-0.9.3.tgz", + "integrity": "sha1-kQqJwWrubMC0LKgFptC0z4chHPM=", + "requires": { + "pegjs": "0.10.0", + "simple-plist": "0.2.1", + "uuid": "3.0.1" + } + }, + "xdg-basedir": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/xdg-basedir/-/xdg-basedir-2.0.0.tgz", + "integrity": "sha1-7byQPMOF/ARSPZZqM1UEtVBNG9I=", + "requires": { + "os-homedir": "1.0.2" + } + }, "xdl": { "version": "41.1.0", "resolved": "https://registry.npmjs.org/xdl/-/xdl-41.1.0.tgz", "integrity": "sha512-Sf7ePBujqHp+cYTMJX5QdS0JRHP63NL4sl2RKZQjX1pgSQlhqGtFiI9EzEhRcBirOs0xgAnoXVx5XSFiIn+L7g==", "dev": true, + "requires": { + "@ccheever/crayon": "5.0.0", + "@exponent/json-file": "5.3.0", + "@exponent/ngrok": "2.2.7", + "@exponent/node-auth0": "2.6.0", + "@exponent/osascript": "1.6.4", + "@exponent/spawn-async": "1.2.8", + "analytics-node": "2.4.1", + "auth0-js": "7.6.1", + "bluebird": "3.5.0", + "body-parser": "1.17.2", + "bunyan": "1.8.10", + "decache": "4.1.0", + "delay-async": "1.1.0", + "es6-error": "4.0.2", + "exec-async": "2.2.0", + "exists-async": "2.0.0", + "express": "4.15.3", + "file-type": "4.4.0", + "freeport-async": "1.1.1", + "fs-extra": "0.30.0", + "glob": "7.1.2", + "hasbin": "1.2.3", + "home-dir": "1.0.0", + "indent-string": "3.1.0", + "instapromise": "2.0.7-rc.1", + "ip": "1.1.5", + "joi": "10.5.2", + "jsonfile": "2.4.0", + "jsonschema": "1.1.1", + "jsonwebtoken": "7.4.1", + "lodash": "4.17.4", + "md5hex": "1.0.0", + "minimist": "1.2.0", + "mkdirp": "0.5.1", + "mkdirp-promise": "5.0.1", + "mz": "2.6.0", + "ncp": "2.0.0", + "opn": "4.0.2", + "promise-props": "1.0.0", + "react": "15.6.0", + "react-redux": "5.0.5", + "read-chunk": "2.0.0", + "redux": "3.6.0", + "redux-logger": "2.10.2", + "request": "2.81.0", + "request-progress": "3.0.0", + "semver": "5.3.0", + "slugid": "1.1.0", + "slugify": "1.1.0", + "source-map-support": "0.4.15", + "tar.gz": "1.0.5", + "tree-kill": "1.1.0", + "url": "0.11.0", + "uuid": "3.0.1", + "xhr2": "0.1.4", + "yesno": "0.0.1" + }, "dependencies": { "fs-extra": { "version": "0.30.0", "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-0.30.0.tgz", "integrity": "sha1-8jP/zAjU2n1DLapEl3aYnbHfk/A=", - "dev": true + "dev": true, + "requires": { + "graceful-fs": "4.1.11", + "jsonfile": "2.4.0", + "path-is-absolute": "1.0.1", + "rimraf": "2.6.1" + } }, "jsonfile": { "version": "2.4.0", "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-2.4.0.tgz", "integrity": "sha1-NzaitCi4e72gzIO1P6PWM6NcKug=", - "dev": true + "dev": true, + "requires": { + "graceful-fs": "4.1.11" + } }, "minimist": { "version": "1.2.0", @@ -2821,7 +8153,14 @@ "version": "15.6.0", "resolved": "https://registry.npmjs.org/react/-/react-15.6.0.tgz", "integrity": "sha1-wjKZtI4w7TAlCM6J4aAskZ+Ca84=", - "dev": true + "dev": true, + "requires": { + "create-react-class": "15.5.4", + "fbjs": "0.8.12", + "loose-envify": "1.3.1", + "object-assign": "4.1.1", + "prop-types": "15.5.10" + } } } }, @@ -2831,17 +8170,74 @@ "integrity": "sha1-f4dliEdxbbUCYyOBL4GMras4el8=", "dev": true }, + "xmlbuilder": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/xmlbuilder/-/xmlbuilder-4.0.0.tgz", + "integrity": "sha1-mLj2UcowqmJANvEn0RzGbce5B6M=", + "requires": { + "lodash": "4.17.4" + } + }, + "xmldoc": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/xmldoc/-/xmldoc-0.4.0.tgz", + "integrity": "sha1-0lciS+g5PqrL+DfvIn/Y7CWzaIg=", + "requires": { + "sax": "1.1.6" + } + }, + "xmldom": { + "version": "0.1.27", + "resolved": "https://registry.npmjs.org/xmldom/-/xmldom-0.1.27.tgz", + "integrity": "sha1-1QH5ezvbQDr4757MIFcxh6rawOk=" + }, + "xpipe": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/xpipe/-/xpipe-1.0.5.tgz", + "integrity": "sha1-jdi/Rfw/f1Xw4FS4ePQ6YmFNr98=" + }, "xtend": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.1.tgz", - "integrity": "sha1-pcbVMr5lbiPbgg77lDofBJmNY68=", - "dev": true + "integrity": "sha1-pcbVMr5lbiPbgg77lDofBJmNY68=" + }, + "y18n": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-3.2.1.tgz", + "integrity": "sha1-bRX7qITAhnnA136I53WegR4H+kE=" }, "yallist": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/yallist/-/yallist-2.1.2.tgz", - "integrity": "sha1-HBH5IY8HYImkfdUS+TxmmaaoHVI=", - "dev": true + "integrity": "sha1-HBH5IY8HYImkfdUS+TxmmaaoHVI=" + }, + "yargs": { + "version": "6.6.0", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-6.6.0.tgz", + "integrity": "sha1-eC7CHvQDNF+DCoCMo9UTr1YGUgg=", + "requires": { + "camelcase": "3.0.0", + "cliui": "3.2.0", + "decamelize": "1.2.0", + "get-caller-file": "1.0.2", + "os-locale": "1.4.0", + "read-pkg-up": "1.0.1", + "require-directory": "2.1.1", + "require-main-filename": "1.0.1", + "set-blocking": "2.0.0", + "string-width": "1.0.2", + "which-module": "1.0.0", + "y18n": "3.2.1", + "yargs-parser": "4.2.1" + } + }, + "yargs-parser": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-4.2.1.tgz", + "integrity": "sha1-KczqwNxPA8bIe0qfIX3RjJ90hxw=", + "requires": { + "camelcase": "3.0.0" + } }, "yesno": { "version": "0.0.1", diff --git a/mobile-app/package.json b/mobile-app/package.json index c7806c37e4..088d443963 100644 --- a/mobile-app/package.json +++ b/mobile-app/package.json @@ -13,7 +13,7 @@ "eslint-plugin-jsx-a11y": "5.0.3", "eslint-plugin-react": "7.1.0", "jest": "^20.0.4", - "jest-expo": "1.0.1", + "jest-expo": "^26.0.0", "prettier": "^1.4.4", "react-addons-test-utils": "^15.6.0", "react-dom": "15.5.4", @@ -34,31 +34,30 @@ "preset": "jest-expo" }, "dependencies": { - "@expo/vector-icons": "5.0.0", "axios": "^0.16.2", "babel-plugin-module-resolver": "^2.7.1", - "color": "1.0.3", - "expo": "19.0.1", + "color": "^3.0.0", + "expo": "^26.0.0", "global": "^4.3.2", "i18next": "^8.4.3", "invariant": "^2.2.2", "json-server": "^0.10.1", - "lodash": "^4.17.4", + "lodash": "^4.17.5", "moment": "^2.18.1", "prop-types": "15.5.10", "query-string": "^4.3.4", - "react": "16.0.0-alpha.12", + "react": "16.3.0-alpha.1", "react-i18next": "^4.6.2", - "react-native": "~0.46", + "react-native": "https://github.com/expo/react-native/archive/sdk-26.0.0.tar.gz", "react-native-animatable": "^1.2.2", - "react-native-elements": "^0.14.0", + "react-native-elements": "^0.19.1", "react-native-extended-stylesheet": "0.5.0", "react-native-message-bar": "^1.6.0", "react-native-popover": "^0.2.0", "react-native-sentry": "^0.24.0", "react-native-slider": "^0.11.0", "react-native-vector-icons": "4.2.0", - "react-navigation": "1.0.0-beta.11", + "react-navigation": "1.5.8", "react-redux": "5.0.5", "recompose": "^0.23.5", "redux": "3.6.0", @@ -67,6 +66,6 @@ "redux-thunk": "2.2.0", "remote-redux-devtools": "^0.5.12", "reselect": "^3.0.1", - "sentry-expo": "^1.6.0" + "sentry-expo": "~1.7.0" } } diff --git a/mobile-app/src/assets/images/ic_organization.png b/mobile-app/src/assets/images/ic_organization.png new file mode 100644 index 0000000000..b7dbdc04bd Binary files /dev/null and b/mobile-app/src/assets/images/ic_organization.png differ diff --git a/mobile-app/src/assets/images/ic_organization@2x.png b/mobile-app/src/assets/images/ic_organization@2x.png new file mode 100644 index 0000000000..819b4a3293 Binary files /dev/null and b/mobile-app/src/assets/images/ic_organization@2x.png differ diff --git a/mobile-app/src/assets/images/ic_organization@3x.png b/mobile-app/src/assets/images/ic_organization@3x.png new file mode 100644 index 0000000000..c73327e031 Binary files /dev/null and b/mobile-app/src/assets/images/ic_organization@3x.png differ diff --git a/mobile-app/src/components/CustomSlider/CustomSlider.js b/mobile-app/src/components/CustomSlider/CustomSlider.js index 5a5b03bbb6..9e4441ce8b 100644 --- a/mobile-app/src/components/CustomSlider/CustomSlider.js +++ b/mobile-app/src/components/CustomSlider/CustomSlider.js @@ -58,8 +58,9 @@ const CustomSlider = (props) => { width: props.width, }} > - {props.gradationData.map(data => ( + {props.gradationData.map((data, key) => ( @@ -108,10 +109,6 @@ CustomSlider.propTypes = { knobSize: PropTypes.number, innerKnobSize: PropTypes.number, trackHeight: PropTypes.number, - gradationData: PropTypes.shape({ - position: PropTypes.number.isRequired, - image: PropTypes.object, - }), }; export default CustomSlider; \ No newline at end of file diff --git a/mobile-app/src/components/Header/Header.js b/mobile-app/src/components/Header/Header.js index 8ef2e5d35e..7b38d783ba 100644 --- a/mobile-app/src/components/Header/Header.js +++ b/mobile-app/src/components/Header/Header.js @@ -43,13 +43,14 @@ class Header extends React.Component { titleRightButton = '', leftButtonImage, rightButtonImage, + containerStyle } = this.props; const showLeftButton = !!titleLeftButton; const showRightButton = !!titleRightButton; return ( - + {showLeftButton && { - const { markers = [], handleOnMarkerPress } = this.props; - return markers.map((marker) => { - return ( - - ); - }); + const {markers = [], handleOnMarkerPress} = this.props; + return markers.map((marker, key) => ); }; displayCircle = () => { - const { circleProps } = this.props; + const {circleProps} = this.props; return circleProps ? { - const { onRegionChangeComplete } = this.props; - let { longitudeDelta, longitude } = region; + const {onRegionChangeComplete} = this.props; + let {longitudeDelta, longitude} = region; if (onRegionChangeComplete) { // on android, the longitude delta is sometimes negative ( which doesn't make any sense ) // https://github.com/airbnb/react-native-maps/issues/1386 diff --git a/mobile-app/src/components/Map/Marker.js b/mobile-app/src/components/Map/Marker.js index 6aaa3649ac..5283d6c520 100644 --- a/mobile-app/src/components/Map/Marker.js +++ b/mobile-app/src/components/Map/Marker.js @@ -1,10 +1,9 @@ -import React, { Component } from 'react'; -import { MapView } from 'expo'; -import { View, Image, Text } from 'react-native'; +import React, {Component} from 'react'; +import {MapView} from 'expo'; import PropTypes from 'prop-types'; import _ from 'lodash'; -import styles from './styles'; +import MarkerView from './MarkerView'; const MARKER_STATUS_IMAGES = { cleaned: require('./images/pointer_cleaned.png'), @@ -25,39 +24,27 @@ const MARKER_OFFSET = { y: 0, }; -const Marker = ({ marker, onMarkerPress = _.noop }) => { - if (!marker) { - return null; - } +const Marker = ({marker, onMarkerPress = _.noop}) => { + if (!marker) { + return null; + } - let pointOffset = { ...MARKER_OFFSET }; + let pointOffset = {...MARKER_OFFSET}; - if (marker.isTrashpile) { - pointOffset = { ...TRASHPILE_MARKER_OFFSET }; - } + if (marker.isTrashpile) { + pointOffset = {...TRASHPILE_MARKER_OFFSET}; + } - let showLabel = marker.isTrashpile && marker.count > 0; + let showLabel = marker.isTrashpile && marker.count > 0; - return ( - - {showLabel && - - - {marker.count} - - } - - - - - ); -}; + /> + } +; Marker.propTypes = { // disabled becuase of too many warnings diff --git a/mobile-app/src/components/Map/MarkerView.android.js b/mobile-app/src/components/Map/MarkerView.android.js new file mode 100644 index 0000000000..793d6c320e --- /dev/null +++ b/mobile-app/src/components/Map/MarkerView.android.js @@ -0,0 +1,26 @@ +import React from 'react'; +import {MapView} from 'expo'; +import {View, Image, Text} from 'react-native'; + +import styles from './styles'; + +const MarkerView = ({marker, onMarkerPress, showLabel, image}) => + + {showLabel && + + + {marker.count} + + } + + + + + +export default MarkerView; diff --git a/mobile-app/src/components/Map/MarkerView.ios.js b/mobile-app/src/components/Map/MarkerView.ios.js new file mode 100644 index 0000000000..18e2fa8bca --- /dev/null +++ b/mobile-app/src/components/Map/MarkerView.ios.js @@ -0,0 +1,30 @@ +import React from 'react'; +import {MapView} from 'expo'; +import {View, Text, ImageBackground} from 'react-native'; + +import styles from './styles'; + +const MarkerView = ({showLabel, marker, onMarkerPress, image}) => + + + {showLabel && + + + {marker.count} + + } + + + + + + +export default MarkerView; diff --git a/mobile-app/src/components/PhotoPicker/components/LazyImage.js b/mobile-app/src/components/PhotoPicker/components/LazyImage.js index b485f0d1fe..4865662a1c 100644 --- a/mobile-app/src/components/PhotoPicker/components/LazyImage.js +++ b/mobile-app/src/components/PhotoPicker/components/LazyImage.js @@ -1,6 +1,7 @@ -import React, { Component } from 'react'; +import React, {Component} from 'react'; import { Image, + ImageBackground, Animated, View, Text, @@ -19,6 +20,11 @@ export class LazyImage extends Component { opacity: new Animated.Value(1), }; } + + componentDidMount() { + this.onLoad(); + } + onLoad = () => { Animated.timing(this.state.opacity, { toValue: 0, @@ -29,25 +35,26 @@ export class LazyImage extends Component { }); }); }; + render() { - const { children, style = {}, ...props } = this.props; + const {children, style = {}, ...props} = this.props; return ( - + {!this.state.loaded && - } - + } + {children} - + ); } diff --git a/mobile-app/src/components/TabMiddleButton/TabMiddleButton.js b/mobile-app/src/components/TabMiddleButton/TabMiddleButton.js index 113050a61d..1e03d750cd 100644 --- a/mobile-app/src/components/TabMiddleButton/TabMiddleButton.js +++ b/mobile-app/src/components/TabMiddleButton/TabMiddleButton.js @@ -1,12 +1,12 @@ -import React, { Component } from 'react'; +import React, {Component} from 'react'; import PropTypes from 'prop-types'; -import { View, TouchableWithoutFeedback, Text } from 'react-native'; -import { Ionicons } from '@expo/vector-icons'; -import { connect } from 'react-redux'; -import { compose } from 'recompose'; +import {View, TouchableWithoutFeedback, Text} from 'react-native'; +import {Ionicons} from '@expo/vector-icons'; +import {connect} from 'react-redux'; +import {compose} from 'recompose'; -import { handleSentryError } from '../../shared/helpers'; -import { withCameraActions } from '../../services/Camera'; +import {handleSentryError} from '../../shared/helpers'; +import {withCameraActions} from '../../services/Camera'; import ImageService from '../../services/Image'; import { selectors as locationSels, @@ -15,7 +15,7 @@ import { import ButtonPopover from './components/ButtonPopover'; -import { Popover } from '../Popover'; +import {Popover} from '../Popover'; import styles from './styles'; import { @@ -39,12 +39,12 @@ class TabMiddleButton extends Component { constructor(props) { super(props); - this.state = { popoverShow: false }; + this.state = {popoverShow: false}; if (!props.wasPopoverShown) { this.onPopoverShow(); const timer = setTimeout(() => { - this.setState({ showPopover: true }); + this.setState({showPopover: true}); clearTimeout(timer); }, 1000); } @@ -56,7 +56,7 @@ class TabMiddleButton extends Component { } }; locationActiveGuard = () => { - const { locationActive } = this.props; + const {locationActive} = this.props; if (!locationActive) { this.props.showLocationErrorModal(); return false; @@ -74,7 +74,11 @@ class TabMiddleButton extends Component { base64, width, height, - } = await this.props.takePhotoAsync({ quality: 0.2, base64: true }); + } = await this.props.takePhotoAsync({ + quality: 0.2, + base64: true, + }); + if (cancelled) { return; } @@ -83,9 +87,9 @@ class TabMiddleButton extends Component { width, height, }); - const { navigation, userLocation } = this.props; + const {navigation, userLocation} = this.props; navigation.navigate('CreateMarker', { - photos: [{ uri, thumbnail: { base64: thumbnailBase64 }, base64 }], + photos: [{uri, thumbnail: {base64: thumbnailBase64}, base64}], coords: userLocation, }); } catch (e) { @@ -94,14 +98,14 @@ class TabMiddleButton extends Component { } }; handleOnClosePopover = () => { - this.setState({ showPopover: false }); + this.setState({showPopover: false}); }; render() { return ( - + {this.state.showPopover && { - return Expo.Util.getCurrentLocaleAsync().then((lang) => { + return Expo.DangerZone.Localization.getCurrentLocaleAsync().then((lang) => { try { if (lang.indexOf('_')) { callback(lang.split('_')[0]); @@ -45,31 +45,32 @@ i18n.use(languageDetector).init({ // i18n.addResources('ar', 'general', require('../trans/ar.json')); // i18n.addResources('ay', 'general', require('../trans/ay.json')); -// i18n.addResources('be', 'general', require('../trans/be.json')); +i18n.addResources('be', 'general', require('../trans/be.json')); // i18n.addResources('bg', 'general', require('../trans/bg.json')); // i18n.addResources('bo', 'general', require('../trans/bo.json')); // i18n.addResources('bs', 'general', require('../trans/bs.json')); // i18n.addResources('ca', 'general', require('../trans/ca.json')); -// i18n.addResources('ceb', 'general', require('../trans/ceb.json')); +i18n.addResources('ceb', 'general', require('../trans/ceb.json')); // i18n.addResources('cs', 'general', require('../trans/cs.json')); // i18n.addResources('csb', 'general', require('../trans/csb.json')); // i18n.addResources('cy', 'general', require('../trans/cy.json')); // i18n.addResources('da', 'general', require('../trans/da.json')); -// i18n.addResources('de', 'general', require('../trans/de.json')); +i18n.addResources('de', 'general', require('../trans/de.json')); // i18n.addResources('ee', 'general', require('../trans/ee.json')); -// i18n.addResources('el', 'general', require('../trans/el.json')); +i18n.addResources('el', 'general', require('../trans/el.json')); i18n.addResources('en', 'general', require('../trans/en.json')); i18n.addResources('es', 'general', require('../trans/es.json')); -// i18n.addResources('et', 'general', require('../trans/et.json')); +i18n.addResources('et', 'general', require('../trans/et.json')); // i18n.addResources('eu', 'general', require('../trans/eu.json')); // i18n.addResources('fa', 'general', require('../trans/fa.json')); // i18n.addResources('fi', 'general', require('../trans/fi.json')); -// i18n.addResources('fil', 'general', require('../trans/fil.json')); +i18n.addResources('fil', 'general', require('../trans/fil.json')); // i18n.addResources('fj', 'general', require('../trans/fj.json')); +i18n.addResources('fo', 'general', require('../trans/fo.json')); i18n.addResources('fr', 'general', require('../trans/fr.json')); // i18n.addResources('ga', 'general', require('../trans/ga.json')); @@ -83,7 +84,7 @@ i18n.addResources('hi', 'general', require('../trans/hi.json')); // i18n.addResources('hmn', 'general', require('../trans/hmn.json')); // i18n.addResources('hr', 'general', require('../trans/hr.json')); // i18n.addResources('ht', 'general', require('../trans/ht.json')); -// i18n.addResources('hu', 'general', require('../trans/hu.json')); +i18n.addResources('hu', 'general', require('../trans/hu.json')); // i18n.addResources('hy', 'general', require('../trans/hy.json')); // Android sends 'in' as language id for Indonesia (it should be id) @@ -91,9 +92,9 @@ i18n.addResources('in', 'general', require('../trans/id.json')); // i18n.addResources('ig', 'general', require('../trans/ig.json')); // i18n.addResources('io', 'general', require('../trans/io.json')); // i18n.addResources('is', 'general', require('../trans/is.json')); -// i18n.addResources('it', 'general', require('../trans/it.json')); +i18n.addResources('it', 'general', require('../trans/it.json')); -// i18n.addResources('ja', 'general', require('../trans/ja.json')); +i18n.addResources('ja', 'general', require('../trans/ja.json')); // i18n.addResources('jv', 'general', require('../trans/jv.json')); // i18n.addResources('ka', 'general', require('../trans/ka.json')); @@ -107,7 +108,7 @@ i18n.addResources('in', 'general', require('../trans/id.json')); // i18n.addResources('lg', 'general', require('../trans/lg.json')); // i18n.addResources('lo', 'general', require('../trans/lo.json')); -// i18n.addResources('lt', 'general', require('../trans/lt.json')); +i18n.addResources('lt', 'general', require('../trans/lt.json')); // i18n.addResources('lv', 'general', require('../trans/lv.json')); // i18n.addResources('mg', 'general', require('../trans/mg.json')); @@ -118,18 +119,18 @@ i18n.addResources('in', 'general', require('../trans/id.json')); // i18n.addResources('na', 'general', require('../trans/na.json')); // i18n.addResources('ne', 'general', require('../trans/ne.json')); -// i18n.addResources('nl', 'general', require('../trans/nl.json')); -// i18n.addResources('no', 'general', require('../trans/no.json')); +i18n.addResources('nl', 'general', require('../trans/nl.json')); +i18n.addResources('no', 'general', require('../trans/no.json')); // i18n.addResources('pap', 'general', require('../trans/pap.json')); // i18n.addResources('pcm', 'general', require('../trans/pcm.json')); -// i18n.addResources('pl', 'general', require('../trans/pl.json')); -// i18n.addResources('pt', 'general', require('../trans/pt.json')); +i18n.addResources('pl', 'general', require('../trans/pl.json')); +i18n.addResources('pt', 'general', require('../trans/pt.json')); // i18n.addResources('qu', 'general', require('../trans/qu.json')); // i18n.addResources('quc', 'general', require('../trans/quc.json')); -// i18n.addResources('ro', 'general', require('../trans/ro.json')); +i18n.addResources('ro', 'general', require('../trans/ro.json')); i18n.addResources('ru', 'general', require('../trans/ru.json')); // i18n.addResources('rw', 'general', require('../trans/rw.json')); // i18n.addResources('ry', 'general', require('../trans/ry.json')); @@ -137,9 +138,9 @@ i18n.addResources('ru', 'general', require('../trans/ru.json')); // i18n.addResources('sco', 'general', require('../trans/sco.json')); // i18n.addResources('si', 'general', require('../trans/si.json')); // i18n.addResources('sk', 'general', require('../trans/sk.json')); -// i18n.addResources('sl', 'general', require('../trans/sl.json')); +i18n.addResources('sl', 'general', require('../trans/sl.json')); // i18n.addResources('so', 'general', require('../trans/so.json')); -// i18n.addResources('sq', 'general', require('../trans/sq.json')); +i18n.addResources('sq', 'general', require('../trans/sq.json')); // i18n.addResources('sv', 'general', require('../trans/sv.json')); // i18n.addResources('sw', 'general', require('../trans/sw.json')); @@ -148,16 +149,16 @@ i18n.addResources('ru', 'general', require('../trans/ru.json')); // i18n.addResources('tg', 'general', require('../trans/tg.json')); // i18n.addResources('th', 'general', require('../trans/th.json')); // i18n.addResources('tk', 'general', require('../trans/tk.json')); -// i18n.addResources('tl', 'general', require('../trans/tl.json')); +i18n.addResources('tl', 'general', require('../trans/tl.json')); // i18n.addResources('tn', 'general', require('../trans/tn.json')); -// i18n.addResources('tr', 'general', require('../trans/tr.json')); +i18n.addResources('tr', 'general', require('../trans/tr.json')); // i18n.addResources('ty', 'general', require('../trans/ty.json')); // i18n.addResources('ug', 'general', require('../trans/ug.json')); -// i18n.addResources('uk', 'general', require('../trans/uk.json')); +i18n.addResources('uk', 'general', require('../trans/uk.json')); // i18n.addResources('ur', 'general', require('../trans/ur.json')); -// i18n.addResources('vi', 'general', require('../trans/vi.json')); +i18n.addResources('vi', 'general', require('../trans/vi.json')); // i18n.addResources('vls', 'general', require('../trans/vls.json')); // i18n.addResources('wo', 'general', require('../trans/wo.json')); diff --git a/mobile-app/src/config/persist.js b/mobile-app/src/config/persist.js index 75bc371880..6d888e1445 100644 --- a/mobile-app/src/config/persist.js +++ b/mobile-app/src/config/persist.js @@ -2,7 +2,7 @@ import { persistStore } from 'redux-persist'; import { createFilter } from 'redux-persist-transform-filter'; const appFilter = createFilter('app', ['popover']); -const userFilter = createFilter('user', ['auth']); +const userFilter = createFilter('user', ['auth', 'profile']); export const persistStoreAsync = ({ store, storage }) => { return new Promise((resolve, reject) => { diff --git a/mobile-app/src/config/routes.js b/mobile-app/src/config/routes.js index 4ee2cdefb1..604b00d88c 100644 --- a/mobile-app/src/config/routes.js +++ b/mobile-app/src/config/routes.js @@ -8,8 +8,10 @@ import CreateMarker from '../screens/CreateMarker'; import EditLocation from '../screens/EditLocation'; import Details from '../screens/Details'; import Profile from '../screens/Profile'; +import TeamProfile from '../screens/TeamProfile'; import Settings from '../screens/Settings'; import MyActivity from '../screens/MyActivity'; +import Teams from '../screens/Teams'; import { Header, HEADER_BUTTONS_IMAGES } from '../components/Header'; import { CreateMarkerButton } from '../screens/CreateMarkerButton'; import { @@ -116,7 +118,7 @@ const ProfileStack = StackNavigator({ const MyActivityStack = StackNavigator({ MyActivity: { screen: MyActivity, - navigationOptions: ({ navigation }) => ({ + navigationOptions: () => ({ header: () =>
, }), }, @@ -125,7 +127,7 @@ const MyActivityStack = StackNavigator({ const NotificationsStack = StackNavigator({ Notifications: { screen: Notifications, - navigationOptions: ({ navigation }) => ({ + navigationOptions: () => ({ header: () =>
, }), }, @@ -185,6 +187,25 @@ const TabStack = TabNavigator( }, ); +export const ROUTES = { + Login: 'Login', + PublicHome: 'PublicHome', + Tabs: 'Tabs', + CreateMarker: 'CreateMarker', + EditTrashpoint: 'EditTrashpoint', + Details: 'Details', + AcceptTerms: 'AcceptTerms', + PrivacyAndTerms: 'PrivacyAndTerms', + Terms: 'Terms', + Privacy: 'Privacy', + About: 'About', + EditLocation: 'EditLocation', + Settings: 'Settings', + Teams: 'Teams', + TeamProfile: 'TeamProfile', + DenyTerms: 'DenyTerms', +} + const AppNavigator = StackNavigator( { Login: { @@ -338,6 +359,29 @@ const AppNavigator = StackNavigator( />, }), }, + Teams: { + screen: Teams, + navigationOptions: ({ navigation }) => ({ + header: () => +
navigation.goBack(null)} + title={i18n.t('label_teams_header')} + leftButtonImage={HEADER_BUTTONS_IMAGES.arrowBack} + containerStyle={{borderBottomWidth: 0}} + />, + }), + }, + TeamProfile: { + screen: TeamProfile, + navigationOptions: ({ navigation }) => ({ + header: () => +
navigation.goBack(null)} + title={i18n.t('label_header_team_profile')} + leftButtonImage={HEADER_BUTTONS_IMAGES.arrowBack} + />, + }), + }, DenyTerms: { screen: DenyTerms, navigationOptions: { diff --git a/mobile-app/src/config/store.js b/mobile-app/src/config/store.js index f6c00de8a3..3530fb3350 100644 --- a/mobile-app/src/config/store.js +++ b/mobile-app/src/config/store.js @@ -8,6 +8,7 @@ import { trashpileReducer, appReducer, userReducer, + teamsReducer, } from '../reducers'; const rootReducer = combineReducers({ @@ -15,6 +16,7 @@ const rootReducer = combineReducers({ trashpile: trashpileReducer, app: appReducer, user: userReducer, + teams: teamsReducer, }); const resetStateOnSignOutReducer = reducer => (state, action) => { @@ -28,6 +30,7 @@ const resetStateOnSignOutReducer = reducer => (state, action) => { user: undefined, location: state.location, trashpile: state.trashpile, + teams: state.teams, }; return reducer(stateWithoutSensitiveData, action); }; diff --git a/mobile-app/src/config/styles.js b/mobile-app/src/config/styles.js index 17613b8c3b..8b3e766a5a 100644 --- a/mobile-app/src/config/styles.js +++ b/mobile-app/src/config/styles.js @@ -11,7 +11,10 @@ const colors = { $red: '#FC515E', $iconColor: ICON_COLOR, $white: WHITE_COLOR, - $textColor:'#2B2B2B' + $textColor: '#2B2B2B', + $textTitleColor: '#3E8EDE', + $headerGrey: '#F6F6F6', + $headerBorderBlack: '#D9D9D9', }; const dimensions = { $radius10: 10, diff --git a/mobile-app/src/i18n/ui-strings.json b/mobile-app/src/i18n/ui-strings.json index 9c7af1aa97..e9f57bd6c9 100644 --- a/mobile-app/src/i18n/ui-strings.json +++ b/mobile-app/src/i18n/ui-strings.json @@ -1,131 +1,157 @@ - { - "label_text_app_subtitle": "Let's clean up the world together!", - "label_button_facebook": "Continue with Facebook", - "label_button_google": "Continue with Google", - "label_button_try_app": "Try out the app without account", - "label_button_acknowledge": "Ok, got it!", - "label_button_cancel": "Cancel", - "label_button_continue": "Continue", - "label_trash_status_threat": "threat", - "label_trash_status_regular": "regular", - "label_trash_status_cleaned": "cleaned", - "label_trash_status_outdated": "outdated", - "label_trash_status_user": "user", - "label_trash_status_change_location": "changeLocation", - "label_trash_status_state_threat": "This point is a threat!", - "label_trash_status_state_regular": "This is a regular trashpoint.", - "label_trash_status_state_cleaned": "This point is cleaned!", - "label_trash_status_state_outdated": "This point is outdated!", - "label_TP_created_date": "Created", - "label_TP_updated_date": "Updated", - "label_TP_by": " by ", - "label_trash_amount_handful": "handful", - "label_trash_amount_bagful": "bagful", - "label_trash_amount_cartloadl": "cartload", - "label_trash_amount_truckload": "truckload", - "label_trash_type_plastic": "Plastic", - "label_trash_type_metal": "Metal", - "label_trash_type_glass": "Glass", - "label_trash_type_electro": "Electronics", - "label_trash_type_paper": "Paper/Wood", - "label_trash_type_tyres": "Tyres", - "label_trash_type_dom_waste": "Domestic waste", - "label_trash_type_furniture": "Furniture", - "label_trash_type_org_waste": "Organic waste", - "label_header_tc": "Terms and Conditions", - "label_button_tc_agree": "I agree with the Terms & Conditions", - "label_header_map": "Map", - "label_text_popover_subtitle": "Join other people who are mapping trash!", - "label_text_popover_text": "Start creating trashpoints to make your community cleaner and healthier.", - "label_header_activity": "My activity", - "label_text_activity_empty_subtitle": "Nothing to see here!", - "label_text_activity_empty_text": "You haven't added any trashpoints yet. When you do, they will be listed here.", - "label_text_activity_empty_hint": "Add a trashpoint!", - "label_header_notific": "Notifications", - "label_text_notific_empty_subtitle": "Nothing to see here!", - "label_text_notific_empty_text": "We haven't seen any notifications come in yet, but we'll let you know when we do!", - "label_header_profile": "My profile", - "label_header_settings": "Account settings", - "label_button_country_empty": "Country", - "label_text_country": "Country", - "label_header_select_country": "Select a country", - "label_text_select_country_hint": "Search", - "label_button_tc": "Terms and Conditions", - "label_button_logout": "Log out", - "label_text_congrats_image": "Trash captured", - "label_text_congrats_subtitle": "Great job!", - "label_text_congrats_text": "Now save the point by verifying the data.", - "label_header_createTP": "Create a trashpoint", - "label_button_createTP_editloc": "Edit location", - "label_header_edit_loc": "Edit location", - "label_button_edit_loc_set": "Set trashpoint location", - "label_text_createTP_status_subtitle": "Point status", - "label_text_createTP_status_text": "If a quick action is needed (toxic, heavy metals), please set as threat.", - "label_text_createTP_add_photos": "Add trash photos", - "label_text_createTP_select_amount": "Select trash amount", - "label_text_createTP_select_type": "Select trash type", - "label_text_createTP_add_hashtags": "Additional added tags", - "label_text_createTP_add_hashtags_hint": "ie. #brandname, #cans", - "label_button_createTP_confirm_create": "Create trashpoint", - "label_alert_createTP_success": "Trashpoint successfully created", - "label_text_detailsTP_photos": "Trash photos", - "label_text_detailsTP_amount": "Trash amount", - "label_text_detailsTP_type": "Trash type", - "label_text_editTP_ask": "Is this trashpoint information still correct and up to date?", - "label_text_editTP_letsconfirm": "Yes, I confirm", - "label_alert_editTP_confirm": "Trashpoint successfully confirmed", - "label_text_editTP_letsedit": "No, let's edit", - "label_header_editTP": "Edit a trashpoint", - "label_button_editTP_save": "Save trashpoint changes", - "label_alert_editTP_edit": "Trashpoint successfully updated", - "label_alert_editTP_delete": "Trashpoint successfully deleted", - "label_error_editTP_out_of_rng_subtitle": "Out of range", - "label_error_editTP_out_of_rng_text": "A point can only be edx`ited if you are within 100 meters of it.", - "label_error_saveTP_subtitle": "Save trashpoint", - "label_error_saveTP_pic_and_type": "It's more useful for us if you to take at least one picture of the trashpoint and set its trash type.", - "label_error_saveTP_picture": "It's more useful for us if you to take at least one picture of the trashpoint before saving.", - "label_error_saveTP_trash_type": "It's more useful for us if you set the trashpoint's type before saving.", - "label_error_change_loc_subtitle": "Out of bounds", - "label_error_change_loc_text": "Please place a point within 100 meters of your location.", - "label_error_generic_error_subtitle": "Out of bounds", - "label_error_generic_error_text": "There was an error on the server.", - "label_error_network_subtitle": "No network connection", - "label_error_network_text": "Mobile data is disabled. Enable mobile data or connect your phone to Wi-Fi to use the application.", - "label_error_location_subtitle": "Enable location", - "label_error_location_text": "Location Services are turned off. Please enable your GPS in your Settings to use the application.", - "label_error_loc_permission_text": "Location Services are not permitted. Please allow them in order to use the application.", - "label_trash_details_header": "Trashpoint details", - "label_privacy_policy_header": "Privacy Policy", - "label_about_header": "About", - "label_edit_trashpoint_button": "Edit trashpoint", - "label_100m_limit_modal": "A point can only be edited if you are within 100 meters of it.", - "label_retry_button": "Retry", - "label_country_picker_placeholder": "Choose your country", - "label_camera_permission_warning_ios": "You must change camera access permissions. To do this, go to Settings > Privacy > Camera", - "label_camera_permission_warning_android": "You must change camera access permissions. To do this, go to Settings > Apps", - "label_camera_error_title": "Camera Access Denied", - "label_error_modal_default_title": "Oh noes!", - "label_error_modal_default_subtitle": "The fail whale detected a server error!", - "label_location_permission_warning_ios": "You must change location permissions. To do this, go to Settings > Privacy > Location services.", - "label_location_permission_warning_android": "You must change location permissions. To do this, go to Settings > Apps.", - "label_location_off_warning": "Location Services are turned off. Please enable your GPS in your Settings to use the application.", - "label_location_modal_title": "Enable location", - "label_network_off_warning_title": "No network connection", - "label_network_off_warning": "Mobile data is disabled. Enable mobile data or connect your phone to Wi-Fi to use the application.", - "label_loading_image_text": "Almost there...", - "label_loading_image_subtext": "Please wait while we save your actions.", - "label_create_marker_missing_photos": "The marker photos could not be uploaded. Please try adding them again.", - "label_edit_marker_missing_photos": "The marker photos could not be uploaded. Please try adding them again.", - "label_confirm_marker_missing_photos": "The marker photos could not be uploaded. Please try adding them again.", - "label_button_delete": "Delete", - "label_delete_photo_title": "Delete photo", - "label_delete_photo_subtitle": "Are you sure you want to delete the photo? You cannot undo this.", - "label_text_about_1": "This app is an initiative by Let's Do It World", - "label_text_about_2": "All the data collected by users worldwide will be visualised in the global trash map for initiating worldwide clean-up events on World Cleanup Day, 15 September 2018", - "label_text_about_3": "This app is a joint cooperation with", - "label_text_about_4": "Estonian product, sponsored by the country and government", - "label_text_about_5": "Funders: Estonian Ministry of Environment, The Ministry of Foreign Affairs of the Republic of Estonia, Estonian Republic 100 program", - "label_button_editTP_delete": "Delete trashpoint", - "label_locked_account_warning": "Your account is locked. For details contact an administrator." + "label_text_app_subtitle":"Let's clean up the world together!", + "label_button_facebook":"Continue with Facebook", + "label_button_google":"Continue with Google", + "label_button_try_app":"Try out the app without account", + "label_button_acknowledge":"Ok, got it!", + "label_button_cancel":"Cancel", + "label_button_continue":"Continue", + "label_trash_status_threat":"threat", + "label_trash_status_regular":"regular", + "label_trash_status_cleaned":"cleaned", + "label_trash_status_outdated":"outdated", + "label_trash_status_user":"user", + "label_trash_status_change_location":"changeLocation", + "label_trash_status_state_threat":"This point is a threat!", + "label_trash_status_state_regular":"This is a regular trashpoint.", + "label_trash_status_state_cleaned":"This point is cleaned!", + "label_trash_status_state_outdated":"This point is outdated!", + "label_TP_created_date":"Created", + "label_TP_updated_date":"Updated", + "label_TP_by":" by ", + "label_trash_amount_handful":"handful", + "label_trash_amount_bagful":"bagful", + "label_trash_amount_cartloadl":"cartload", + "label_trash_amount_truckload":"truckload", + "label_trash_type_plastic":"Plastic", + "label_trash_type_metal":"Metal", + "label_trash_type_glass":"Glass", + "label_trash_type_electro":"Electronics", + "label_trash_type_paper":"Paper/Wood", + "label_trash_type_tyres":"Tyres", + "label_trash_type_dom_waste":"Domestic waste", + "label_trash_type_furniture":"Furniture", + "label_trash_type_org_waste":"Organic waste", + "label_header_tc":"Terms and Conditions", + "label_button_tc_agree":"I agree with the Terms & Conditions", + "label_header_map":"Map", + "label_text_popover_subtitle":"Join other people who are mapping trash!", + "label_text_popover_text":"Start creating trashpoints to make your community cleaner and healthier.", + "label_header_activity":"My activity", + "label_text_activity_empty_subtitle":"Nothing to see here!", + "label_text_activity_empty_text":"You haven't added any trashpoints yet. When you do, they will be listed here.", + "label_text_activity_empty_hint":"Add a trashpoint!", + "label_header_notific":"Notifications", + "label_text_notific_empty_subtitle":"Nothing to see here!", + "label_text_notific_empty_text":"We haven't seen any notifications come in yet, but we'll let you know when we do!", + "label_header_profile":"My profile", + "label_header_settings":"Account settings", + "label_button_country_empty":"Country", + "label_text_country":"Country", + "label_header_select_country":"Select a country", + "label_text_select_country_hint":"Search", + "label_button_tc":"Terms and Conditions", + "label_button_logout":"Log out", + "label_text_congrats_image":"Trash captured", + "label_text_congrats_subtitle":"Great job!", + "label_text_congrats_text":"Now save the point by verifying the data.", + "label_header_createTP":"Create a trashpoint", + "label_button_createTP_editloc":"Edit location", + "label_header_edit_loc":"Edit location", + "label_button_edit_loc_set":"Set trashpoint location", + "label_text_createTP_status_subtitle":"Point status", + "label_text_createTP_status_text":"If a quick action is needed (toxic, heavy metals), please set as threat.", + "label_text_createTP_add_photos":"Add trash photos", + "label_text_createTP_select_amount":"Select trash amount", + "label_text_createTP_select_type":"Select trash type", + "label_text_createTP_add_hashtags":"Additional added tags", + "label_text_createTP_add_hashtags_hint":"ie. #brandname, #cans", + "label_button_createTP_confirm_create":"Create trashpoint", + "label_alert_createTP_success":"Trashpoint successfully created", + "label_text_detailsTP_photos":"Trash photos", + "label_text_detailsTP_amount":"Trash amount", + "label_text_detailsTP_type":"Trash type", + "label_text_editTP_ask":"Is this trashpoint information still correct and up to date?", + "label_text_editTP_letsconfirm":"Yes, I confirm", + "label_alert_editTP_confirm":"Trashpoint successfully confirmed", + "label_text_editTP_letsedit":"No, let's edit", + "label_header_editTP":"Edit a trashpoint", + "label_button_editTP_save":"Save trashpoint changes", + "label_alert_editTP_edit":"Trashpoint successfully updated", + "label_alert_editTP_delete":"Trashpoint successfully deleted", + "label_error_editTP_out_of_rng_subtitle":"Out of range", + "label_error_editTP_out_of_rng_text":"A point can only be edited if you are within 100 meters of it.", + "label_error_saveTP_subtitle":"Save trashpoint", + "label_error_saveTP_pic_and_type":"It's more useful for us if you take at least one picture of the trashpoint and set its trash type.", + "label_error_saveTP_picture":"It's more useful for us if you take at least one picture of the trashpoint before saving.", + "label_error_saveTP_trash_type":"It's more useful for us if you set the trashpoint's type before saving.", + "label_error_change_loc_subtitle":"Out of bounds", + "label_error_change_loc_text":"Please place a point within 100 meters of your location.", + "label_error_generic_error_subtitle":"Out of bounds", + "label_error_generic_error_text":"There was an error on the server.", + "label_error_network_subtitle":"No network connection", + "label_error_network_text":"Mobile data is disabled. Enable mobile data or connect your phone to Wi-Fi to use the application.", + "label_error_location_subtitle":"Enable location", + "label_error_location_text":"Location Services are turned off. Please enable your GPS in your Settings to use the application.", + "label_error_loc_permission_text":"Location Services are not permitted. Please allow them in order to use the application.", + "label_trash_details_header":"Trashpoint details", + "label_privacy_policy_header":"Privacy Policy", + "label_about_header":"About", + "label_edit_trashpoint_button":"Edit trashpoint", + "label_100m_limit_modal":"A point can only be edited if you are within 100 meters of it.", + "label_retry_button":"Retry", + "label_country_picker_placeholder":"Choose your country", + "label_camera_permission_warning_ios":"You must change camera access permissions. To do this, go to Settings > Privacy > Camera", + "label_camera_permission_warning_android":"You must change camera access permissions. To do this, go to Settings > Apps", + "label_camera_error_title":"Camera Access Denied", + "label_error_modal_default_title":"Oh noes!", + "label_error_modal_default_subtitle":"The fail whale detected a server error!", + "label_location_permission_warning_ios":"You must change location permissions. To do this, go to Settings > Privacy > Location services.", + "label_location_permission_warning_android":"You must change location permissions. To do this, go to Settings > Apps.", + "label_location_off_warning":"Location Services are turned off. Please enable your GPS in your Settings to use the application.", + "label_location_modal_title":"Enable location", + "label_network_off_warning_title":"Welcome to offline mode!", + "label_network_off_warning":"Mobile data is disabled. Enable mobile data or connect your phone to Wi-Fi to use the application.", + "label_loading_image_text":"Almost there...", + "label_loading_image_subtext":"Please wait while we save your actions.", + "label_create_marker_missing_photos":"The marker photos could not be uploaded. Please try adding them again.", + "label_edit_marker_missing_photos":"The marker photos could not be uploaded. Please try adding them again.", + "label_confirm_marker_missing_photos":"The marker photos could not be uploaded. Please try adding them again.", + "label_button_delete":"Delete", + "label_delete_photo_title":"Delete photo", + "label_delete_photo_subtitle":"Are you sure you want to delete the photo? You cannot undo this.", + "label_text_about_1":"This app is an initiative by Let's Do It World", + "label_text_about_2":"All the data collected by users worldwide will be visualised in the global trash map for initiating worldwide clean-up events on World Cleanup Day, 15 September 2018", + "label_text_about_3":"This app is a joint cooperation with", + "label_text_about_4":"Estonian product, sponsored by the country and government", + "label_text_about_5":"Funders: Estonian Ministry of Environment, The Ministry of Foreign Affairs of the Republic of Estonia, Estonian Republic 100 program", + "label_button_editTP_delete":"Delete trashpoint", + "label_locked_account_warning":"Your account is locked. For details contact an administrator.", + "label_no_connection_note":"Continue mapping as before. The trashpoints will be sent to the map server as soon as you regain Internet access.", + "label_your_coordinates":"Your coordinates", + "label_header_team_profile":"Team profile", + "label_button_join_team":"Join a team", + "label_button_leave_team":"Leave a team", + "label_text_global_team":"Global", + "label_text_members":"members", + "label_text_team_trash_points":"Team trash points", + "label_text_latest_activity":"Latest activity", + "label_text_select_leave":"Do you really want to leave the team", + "label_text_select_join":"Do you really want to join the team", + "label_button_join":"Join", + "label_button_leave":"Leave", + "label_text_my_team":"My Team", + "label_text_team":"Team", + "label_teams_header":"Teams", + "label_text_your_team":"Your team: ", + "label_text_join_a_team":"Join a team", + "label_text_join_a_team_description":"Join your sisters and brothers in arms!", + "label_text_search_placeholder":"Search a team", + "label_text_search_teams":"Search teams", + "label_text_search_for_a_team":"Search for a team!", + "label_text_work_together":"Work together with other people and create competings teams. The winner is the world!", + "label_text_trashpoint":"Trashpoint", + "label_no":"No", + "label_yes":"Yes", + "label_cancel":"Cancel" } diff --git a/mobile-app/src/index.js b/mobile-app/src/index.js index d5bffeea6e..e151b98add 100644 --- a/mobile-app/src/index.js +++ b/mobile-app/src/index.js @@ -16,6 +16,7 @@ import store from './config/store'; import Navigator from './config/routes'; import { images, fonts } from './config/assets'; import { operations as appOperations } from './reducers/app'; +import { operations as teamsOperations } from './reducers/teams'; import { handleSentryError } from './shared/helpers'; import './config/styles'; @@ -27,10 +28,11 @@ import { API_URL, SENTRY_URL } from '../env'; // Remove this once Sentry is correctly setup. // Sentry.enableInExpoDevelopment = true; -Sentry.config(SENTRY_URL).install(); +Sentry.config(SENTRY_URL) + .install(); const WrappedNavigator = () => { - return ; + return ; }; // AsyncStorage.clear() const AppNavigator = compose( @@ -45,6 +47,7 @@ const AppNavigator = compose( )(WrappedNavigator); Api.setBaseURL(API_URL); + class App extends Component { constructor() { super(); @@ -71,15 +74,15 @@ class App extends Component { storage: AsyncStorage, }), store.dispatch(appOperations.fetchDatasets()), - ]).then( - () => { - this.setState({ assetsLoaded: true }); - }, - (e) => { - handleSentryError(e); - console.log(e.message); - }, - ); + ]) + .then( + () => { + this.setState({ assetsLoaded: true }); + }, + (e) => { + handleSentryError(e); + }, + ); }; registerMessageBarRef = (a) => { MessageBarManager.registerMessageBar(a); @@ -91,14 +94,14 @@ class App extends Component { - - + + ); } - return ; + return ; } } diff --git a/mobile-app/src/reducers/app/actions.js b/mobile-app/src/reducers/app/actions.js index f0b7c38c49..d962dc0e86 100644 --- a/mobile-app/src/reducers/app/actions.js +++ b/mobile-app/src/reducers/app/actions.js @@ -37,6 +37,11 @@ const setActiveScreen = activeScreen => ({ const setConnectionChecked = () => ({ type: types.SET_CONNECTION_CHECKED }); const updateNetworkStatus = isConnected => ({ type: types.UPDATE_NETWORK_STATUS, payload: { isConnected } }); +const updateSyncStatus = inSync => + ({ type: types.UPDATE_SYNC_STATUS, payload: { inSync } }); +const updateLackConnMessStatus = noLackConnectionAlert => + ({ type: types.UPDATE_LACK_CONNECTION_MESSAGE_STATUS, payload: { noLackConnectionAlert } }); + export default { setPopoverShown, setPopoverMessage, @@ -45,4 +50,6 @@ export default { hideErrorMessage, setConnectionChecked, updateNetworkStatus, + updateSyncStatus, + updateLackConnMessStatus }; diff --git a/mobile-app/src/reducers/app/reducers.js b/mobile-app/src/reducers/app/reducers.js index fb8a39bdfd..32fe8673d9 100644 --- a/mobile-app/src/reducers/app/reducers.js +++ b/mobile-app/src/reducers/app/reducers.js @@ -1,10 +1,10 @@ import { combineReducers } from 'redux'; - import types from './types'; +import i18n from '../../config/i18n'; const popoverInitialState = { shown: false, - message: 'Join other people who are mapping trash!', + message: i18n.t('label_text_popover_subtitle'), }; const errorInitialState = { visible: false, @@ -15,6 +15,8 @@ const errorInitialState = { const networkStatusState = { isConnected: false, connectionChecked: false, + noLackConnectionAlert: false, + inSync: false }; const networkReducer = (state = networkStatusState, action) => { @@ -23,6 +25,10 @@ const networkReducer = (state = networkStatusState, action) => { return { ...state, connectionChecked: true }; case types.UPDATE_NETWORK_STATUS: return { ...state, isConnected: action.payload.isConnected }; + case types.UPDATE_SYNC_STATUS: + return { ...state, inSync: action.payload.inSync }; + case types.UPDATE_LACK_CONNECTION_MESSAGE_STATUS: + return { ...state, noLackConnectionAlert: action.payload.noLackConnectionAlert }; default: return state; } diff --git a/mobile-app/src/reducers/app/selectors.js b/mobile-app/src/reducers/app/selectors.js index 99c8833cdb..43af0540b5 100644 --- a/mobile-app/src/reducers/app/selectors.js +++ b/mobile-app/src/reducers/app/selectors.js @@ -31,6 +31,8 @@ const networkSelector = createSelector(stateSelector, state => state.network); const wasConnectionChecked = createSelector(networkSelector, state => state.connectionChecked); const isConnected = createSelector(networkSelector, state => state.isConnected); +const inSync = createSelector(networkSelector, state => state.inSync); +const isNoLackConnectionAlert = createSelector(networkSelector, state => state.noLackConnectionAlert); export default { wasPopoverShown, @@ -46,4 +48,6 @@ export default { wasConnectionChecked, isConnected, + inSync, + isNoLackConnectionAlert }; diff --git a/mobile-app/src/reducers/app/types.js b/mobile-app/src/reducers/app/types.js index 35461344bb..17930f575a 100644 --- a/mobile-app/src/reducers/app/types.js +++ b/mobile-app/src/reducers/app/types.js @@ -8,6 +8,8 @@ const FETCH_DATASETS_FAILED = 'FETCH_DATASETS_FAILED'; const SET_ACTIVE_SCREEN = 'SET_ACTIVE_SCREEN'; const UPDATE_NETWORK_STATUS = 'UPDATE_NETWORK_STATUS'; const SET_CONNECTION_CHECKED = 'SET_CONNECTION_CHECKED'; +const UPDATE_SYNC_STATUS = 'UPDATE_SYNC_STATUS'; +const UPDATE_LACK_CONNECTION_MESSAGE_STATUS = 'UPDATE_LACK_CONNECTION_MESSAGE_STATUS'; export default { SET_POPOVER_SHOWN, @@ -20,4 +22,6 @@ export default { SET_ACTIVE_SCREEN, UPDATE_NETWORK_STATUS, SET_CONNECTION_CHECKED, + UPDATE_SYNC_STATUS, + UPDATE_LACK_CONNECTION_MESSAGE_STATUS }; diff --git a/mobile-app/src/reducers/index.js b/mobile-app/src/reducers/index.js index 73784e9080..73a3333d10 100644 --- a/mobile-app/src/reducers/index.js +++ b/mobile-app/src/reducers/index.js @@ -1,7 +1,8 @@ import appReducer from './app'; import { locationReducer } from './location'; import { trashpileReducer } from './trashpile'; +import { teamsReducer } from './teams'; export { default as userReducer } from './user'; -export { trashpileReducer, appReducer, locationReducer }; +export { trashpileReducer, appReducer, locationReducer, teamsReducer }; diff --git a/mobile-app/src/reducers/teams/index.js b/mobile-app/src/reducers/teams/index.js new file mode 100644 index 0000000000..e18505b2ab --- /dev/null +++ b/mobile-app/src/reducers/teams/index.js @@ -0,0 +1,6 @@ +//import actions from './actions'; +import reducer from './reducer'; +import selectors from './selectors'; +import operations from './operations'; + +export { reducer as teamsReducer, selectors, operations }; diff --git a/mobile-app/src/reducers/teams/operations.js b/mobile-app/src/reducers/teams/operations.js new file mode 100644 index 0000000000..2fb97d99d7 --- /dev/null +++ b/mobile-app/src/reducers/teams/operations.js @@ -0,0 +1,70 @@ +import Api from '../../services/Api'; +import userActions from '../user/actions'; +import types from './types'; +import { handleSentryError } from '../../shared/helpers'; +import { API_ENDPOINTS } from '../../shared/constants'; + +const updateTeam = profile => async (dispatch) => { + dispatch(userActions.updateProfile()); + try { + const response = await Api.put(API_ENDPOINTS.USER_TEAM, profile); + if (!response || !response.data) { + throw { error: 'Could not not read response data' }; + } + dispatch(userActions.updateProfileDone(response.data)); + return response.data; + } catch (ex) { + handleSentryError(ex); + dispatch(userActions.updateProfileError(ex)); + } +}; + +const fetchTeams = search => { + return async (dispatch, getState) => { + + dispatch({ type: types.FETCH_TEAMS_REQUEST }); + + const response = await Api.get(API_ENDPOINTS.FETCH_TEAMS(getState().user.profile.entity.country || 'EN', search)) + + if (!response) { + return dispatch({ type: types.FETCH_TEAMS_FAILED }); + } + + const { data } = response; + dispatch({ + type: types.FETCH_TEAMS_SUCCESS, + payload: data, + }); + }; +}; + +const fetchTeamsByCountry = () => { + return async (dispatch, getState) => { + dispatch({ type: types.FETCH_TEAMS_REQUEST }); + const country = getState().user.profile.entity.country || 'EN'; + const response = await Api.get(API_ENDPOINTS.FETCH_TEAMS_BY_COUNTRY(country)); + + if (!response) { + return dispatch({ type: types.FETCH_TEAMS_BY_COUNTRY_FAILED }); + } + + const { data } = response; + const filteredTeams = data.filter(team => team.CC === undefined || team.CC === country); + dispatch({ + type: types.FETCH_TEAMS_BY_COUNTRY_SUCCESS, + payload: filteredTeams, + }); + } +}; + +const clearTeams = () => (dispatch => { + dispatch({ type: types.CLEAR_TEAMS_SUCCESS }); +}); + + +export default { + updateTeam, + fetchTeams, + clearTeams, + fetchTeamsByCountry +}; diff --git a/mobile-app/src/reducers/teams/reducer.js b/mobile-app/src/reducers/teams/reducer.js new file mode 100644 index 0000000000..ce6a8af4d0 --- /dev/null +++ b/mobile-app/src/reducers/teams/reducer.js @@ -0,0 +1,28 @@ +import types from './types'; + +const initialState = { + list: [], + loading: false, +}; + +export default (state = initialState, action) => { + switch (action.type) { + case types.FETCH_TEAMS_REQUEST: + return { ...state, loading: true }; + case types.FETCH_TEAMS_SUCCESS: + return { ...state, list: action.payload, loading: false }; + case types.FETCH_TEAMS_FAILED: + return { ...state, loading: false }; + case types.CLEAR_TEAMS_SUCCESS: + return { ...state, list: [] }; + case types.FETCH_TEAMS_BY_COUNTRY_REQUEST: + return { ...state, loading: true }; + case types.FETCH_TEAMS_BY_COUNTRY_SUCCESS: + return { ...state, list: action.payload, loading: false}; + case types.FETCH_TEAMS_BY_COUNTRY_FAILED: + return { ...state, loading: false }; + default: + return state; + } +}; + diff --git a/mobile-app/src/reducers/teams/selectors.js b/mobile-app/src/reducers/teams/selectors.js new file mode 100644 index 0000000000..952af8c396 --- /dev/null +++ b/mobile-app/src/reducers/teams/selectors.js @@ -0,0 +1,13 @@ +import { createSelector } from 'reselect'; + +const stateSelector = state => state.teams; + +const teamsSelector = createSelector(stateSelector, state => state.list); + +const loadingSelector = createSelector(stateSelector, state => state.loading); + + +export default { + teamsSelector, + loadingSelector, +}; diff --git a/mobile-app/src/reducers/teams/types.js b/mobile-app/src/reducers/teams/types.js new file mode 100644 index 0000000000..114cd43280 --- /dev/null +++ b/mobile-app/src/reducers/teams/types.js @@ -0,0 +1,17 @@ +const FETCH_TEAMS_REQUEST = 'FETCH_TEAMS_REQUEST'; +const FETCH_TEAMS_SUCCESS = 'FETCH_TEAMS_SUCCESS'; +const FETCH_TEAMS_FAILED = 'FETCH_TEAMS_FAILED'; +const CLEAR_TEAMS_SUCCESS = 'CLEAR_TEAMS_SUCCESS'; +const FETCH_TEAMS_BY_COUNTRY_REQUEST = 'FETCH_TEAMS_BY_COUNTRY_REQUEST'; +const FETCH_TEAMS_BY_COUNTRY_SUCCESS = 'FETCH_TEAMS_BY_COUNTRY_SUCCESS'; +const FETCH_TEAMS_BY_COUNTRY_FAILED = 'FETCH_TEAMS_BY_COUNTRY_FAILED'; + +export default { + FETCH_TEAMS_REQUEST, + FETCH_TEAMS_SUCCESS, + FETCH_TEAMS_FAILED, + CLEAR_TEAMS_SUCCESS, + FETCH_TEAMS_BY_COUNTRY_REQUEST, + FETCH_TEAMS_BY_COUNTRY_SUCCESS, + FETCH_TEAMS_BY_COUNTRY_FAILED, +}; diff --git a/mobile-app/src/reducers/trashpile/operations.js b/mobile-app/src/reducers/trashpile/operations.js index 8b12bbd5f6..94182da6d8 100644 --- a/mobile-app/src/reducers/trashpile/operations.js +++ b/mobile-app/src/reducers/trashpile/operations.js @@ -4,6 +4,7 @@ import { API_ENDPOINTS, TRASHPOINT_IMAGE_TYPES, DIAGONALE_IN_PX, MARKER_DIAGONAL DEFAULT_ZOOM, SCREEN_WIDTH} from '../../shared/constants'; import types from './types'; import { Api } from '../../services'; +import OfflineService from '../../services/Offline'; import axios from 'axios'; import { selectors as appSelectors, operations as appOps } from '../app'; import { selectors as trashpileSelectors } from '../trashpile'; @@ -201,7 +202,6 @@ export const handleUpload = async ({ photos, markerId }) => { failed: [], backendConfirmed: false, }; - if (photosResponse) { const thumbnailsPhotos = photosResponse.data .filter(pr => pr.type === TRASHPOINT_IMAGE_TYPES.THUMBNAIL) @@ -217,7 +217,7 @@ export const handleUpload = async ({ photos, markerId }) => { const mediumPhotos = photosResponse.data .filter(pr => pr.type === TRASHPOINT_IMAGE_TYPES.MEDIUM) .map(({ permission: { token, resourceId } }, index) => { - const { base64 } = photos[index]; + const { thumbnail: { base64 } } = photos[index]; return { url: token, id: resourceId, @@ -226,7 +226,6 @@ export const handleUpload = async ({ photos, markerId }) => { }); const handledPhotos = [...thumbnailsPhotos, ...mediumPhotos]; - const uploadedPhotosResponses = await uploadPhotosOnAzure(handledPhotos); if (uploadedPhotosResponses) { @@ -272,6 +271,7 @@ export const createMarker = ({ address, amount, photos, + team }, isEdit,) => { return async (dispatch, getState) => { @@ -285,6 +285,7 @@ export const createMarker = ({ name, address, amount, + team }; let newPhotos = []; let toDeletePhotos = []; @@ -307,11 +308,25 @@ export const createMarker = ({ p => p.id !== undefined && p.delete === true && !!p.parentId, ); } + const isConnected = appSelectors.isConnected(getState()); + const url = isEdit ? API_ENDPOINTS.UPDATE_TRASHPOINT(id) : API_ENDPOINTS.CREATE_TRASHPOINT; - const createMarkerResponse = await Api.put(url, newMarker); + let createMarkerResponse = false; + + if (isConnected) { + createMarkerResponse = await Api.put(url, newMarker); + } else { + createMarkerResponse = await OfflineService.saveTrashpoint( + url, + newMarker, + photos, + !isEdit ? [] : toDeletePhotos + ); + dispatch(appOps.updateSyncStatus(false)) + } if (!createMarkerResponse) { dispatch({ type: types.CREATE_MARKER_FAILED }); @@ -320,13 +335,14 @@ export const createMarker = ({ let uploadStatus; - if (isEdit && newPhotos.length > 0) { + if (isEdit && newPhotos.length > 0 && isConnected) { uploadStatus = await handleUpload({ photos: newPhotos, markerId: createMarkerResponse.data.id, }); } - if (isEdit && toDeletePhotos.length > 0) { + + if (isEdit && toDeletePhotos.length > 0 && isConnected) { try { await Promise.all( toDeletePhotos.map(p => deleteImage(id, p.parentId)), @@ -337,16 +353,16 @@ export const createMarker = ({ } } - if (!isEdit) { + if (!isEdit && isConnected) { uploadStatus = await handleUpload({ photos, markerId: createMarkerResponse.data.id, }); + } if (uploadStatus === undefined) { uploadStatus = true; } - dispatch({ type: types.CREATE_MARKER_SUCCESS, marker: { @@ -357,6 +373,7 @@ export const createMarker = ({ }, }, }); + return { ...createMarkerResponse.data, photoStatus: uploadStatus, diff --git a/mobile-app/src/reducers/user/operations.js b/mobile-app/src/reducers/user/operations.js index 9ec50bc0d1..9c8642e14d 100644 --- a/mobile-app/src/reducers/user/operations.js +++ b/mobile-app/src/reducers/user/operations.js @@ -61,7 +61,6 @@ const getProfile = () => async (dispatch) => { try { const response = await Api.get('/me'); - dispatch(actions.fetchProfileDone(response.data)); return response.data; } catch (ex) { diff --git a/mobile-app/src/reducers/user/selectors.js b/mobile-app/src/reducers/user/selectors.js index 5d06599bf8..fd96305fbd 100644 --- a/mobile-app/src/reducers/user/selectors.js +++ b/mobile-app/src/reducers/user/selectors.js @@ -1,5 +1,6 @@ import { createSelector } from 'reselect'; import { selectors as trashpileSelector } from '../trashpile'; +import { selectors as teamsSelector } from '../teams'; import { COUNTRY_LIST, USER_ROLES } from '../../shared/constants'; @@ -46,6 +47,16 @@ const getProfileCountry = createSelector(getProfile, (profile) => { } return COUNTRY_LIST.find(c => c.code === profile.country); }); +const getProfileTeam = createSelector( + getProfile, + profile => profile && profile.teamInfo, +); + +const getProfileTeamId = createSelector( + getProfileTeam, + team => team && team.id, +); + const getRole = createSelector(getProfile, (profile) => { if (!profile) { return undefined; @@ -65,6 +76,7 @@ export default { isProfileLoading, getProfileError, getProfileCountry, + getProfileTeam, getCachedLocation, didAgreeToTerms, getToken, @@ -74,4 +86,5 @@ export default { getRole, isLeader, isSuperAdmin, + getProfileTeamId, }; diff --git a/mobile-app/src/screens/CreateMarker/CreateMarker.js b/mobile-app/src/screens/CreateMarker/CreateMarker.js index 6d7e5ff9e3..f208b4b0f8 100644 --- a/mobile-app/src/screens/CreateMarker/CreateMarker.js +++ b/mobile-app/src/screens/CreateMarker/CreateMarker.js @@ -23,6 +23,7 @@ import { withCameraActions } from '../../services/Camera'; import ImageService from '../../services/Image'; import { withLoadingScreen } from '../../services/Loading'; import { operations as locationOperations } from '../../reducers/location'; +import { selectors as userSelectors } from '../../reducers/user'; import { Button } from '../../components/Buttons'; import { LocationPicker } from './components/LocationPicker'; import { StatusPicker } from './components/StatusPicker'; @@ -92,7 +93,8 @@ class CreateMarker extends Component { congratsShown: false, trashCompositionTypes: TRASH_COMPOSITION_TYPE_LIST.map( trashCompositionType => ({ - ...trashCompositionType, + type: trashCompositionType.type, + label: props.t(trashCompositionType.label), selected: false, }), ), @@ -267,7 +269,7 @@ class CreateMarker extends Component { } handleTrashpointCreate = () => { - const { createMarker, navigation, setErrorMessage, t } = this.props; + const { createMarker, navigation, setErrorMessage, t, teamId } = this.props; const { photos, trashCompositionTypes, @@ -293,6 +295,7 @@ class CreateMarker extends Component { amount: AMOUNT_STATUSES[amount], address: completeAddress, name: `${streetAddress} ${streetNumber}`, + team: teamId, }).then( (res) => { if (res) { @@ -568,6 +571,7 @@ const mapDispatch = { const mapStateToProps = state => ({ isConnected: appSels.isConnected(state), loading: trashpileSelectors.isLoading(state), + teamId: userSelectors.getProfileTeamId(state), }); export default compose( diff --git a/mobile-app/src/screens/Details/Details.js b/mobile-app/src/screens/Details/Details.js index 5a80036b05..2c3b104cd0 100644 --- a/mobile-app/src/screens/Details/Details.js +++ b/mobile-app/src/screens/Details/Details.js @@ -16,7 +16,6 @@ import _ from 'lodash'; import { translate } from 'react-i18next'; import { Map } from '../../components/Map'; -import { SimpleButton } from '../../components/Buttons'; import { getHeightPercentage, getWidthPercentage, @@ -123,7 +122,7 @@ class Details extends Component { displayTrashCompositionTypes = () => { const { composition, hashtags } = this.props.marker; return [...composition, ...hashtags].map(trashCompositionType => { - const text = TRASH_COMPOSITION_TYPES_HASH[trashCompositionType]; + const text = this.props.t(TRASH_COMPOSITION_TYPES_HASH[trashCompositionType]); return ( @@ -288,7 +287,9 @@ class Details extends Component { if (marker && marker.name) { return marker.name; } - return ''; + + const { initialLocation: { longitude, latitude } } = this.state; + return `${latitude.toFixed(2)}, ${longitude.toFixed(2)}`; }; renderStreetDetails = () => { const { address } = this.state; @@ -308,7 +309,7 @@ class Details extends Component { // {`${this.renderStreetDetails()} | ${latitude.toFixed( // 6, // )}, ${longitude.toFixed(6)}`} - const streetDetails = this.renderStreetDetails(); + const streetDetails = this.renderStreetDetails().trim(); const gpsCoords = this.renderMarkerCoords(); if (streetDetails && gpsCoords) { return `${streetDetails} | ${gpsCoords}`; diff --git a/mobile-app/src/screens/EditTrashpoint/.EditTrashpoint.js.swp b/mobile-app/src/screens/EditTrashpoint/.EditTrashpoint.js.swp deleted file mode 100644 index 364dc76d88..0000000000 Binary files a/mobile-app/src/screens/EditTrashpoint/.EditTrashpoint.js.swp and /dev/null differ diff --git a/mobile-app/src/screens/EditTrashpoint/EditTrashpoint.js b/mobile-app/src/screens/EditTrashpoint/EditTrashpoint.js index 2560e3de73..1b0133bda5 100644 --- a/mobile-app/src/screens/EditTrashpoint/EditTrashpoint.js +++ b/mobile-app/src/screens/EditTrashpoint/EditTrashpoint.js @@ -108,7 +108,8 @@ class EditTrashpoint extends Component { trashCompositionTypes: TRASH_COMPOSITION_TYPE_LIST.map( (trashCompositionType) => { return { - ...trashCompositionType, + type: trashCompositionType.type, + label: props.t(trashCompositionType.label), selected: marker.composition.indexOf(trashCompositionType.type) !== -1, }; }, diff --git a/mobile-app/src/screens/Home.js b/mobile-app/src/screens/Home.js index 5c9a002afd..bf684a2081 100644 --- a/mobile-app/src/screens/Home.js +++ b/mobile-app/src/screens/Home.js @@ -1,5 +1,5 @@ import React, { Component } from 'react'; -import { StatusBar, View } from 'react-native'; +import { StatusBar, View, Text } from 'react-native'; import { connect } from 'react-redux'; import { compose } from 'recompose'; @@ -12,8 +12,10 @@ import { import { selectors as locationSelectors } from '../reducers/location'; import { selectors as appSelectors } from '../reducers/app'; import { SCREENS } from '../shared/constants'; -import { DELTA_HASH, GRID_HASH, MIN_ZOOM } from '../shared/constants'; +import { MIN_ZOOM } from '../shared/constants'; import _ from 'lodash'; +import {translate} from 'react-i18next'; +import styles from './styles'; class Home extends Component { state = { @@ -34,7 +36,7 @@ class Home extends Component { marker => marker.id === event.nativeEvent.id, ); - if (!marker.isTrashpile) { + if (!marker || !marker.isTrashpile) { return; } @@ -105,9 +107,29 @@ class Home extends Component { }); }; + displayNoConnected = (latitude, longitude) => { + return ( + + + {this.props.t('label_network_off_warning_title')} + + + {this.props.t('label_no_connection_note')} + + + {this.props.t('label_your_coordinates')} + {`: ${latitude.toFixed(2)}, ${longitude.toFixed(2)}`} + + + ); + }; + render() { - const { markers, initialRegion } = this.props; + const { markers, initialRegion, isConnected, userLocation: { longitude, latitude } } = this.props; + if (!isConnected) { + return this.displayNoConnected(latitude, longitude); + } return ( @@ -135,6 +157,7 @@ const mapStateToProps = state => { activeScreen: appSelectors.getActiveScreen(state), userLocation: locationSelectors.userLocationSelector(state), delta: trashpileSelectors.getLastDeltaValue(state), + isConnected: appSelectors.isConnected(state), }; }; @@ -164,4 +187,5 @@ const mapDispatchToProps = dispatch => { export default compose( connect(mapStateToProps, mapDispatchToProps), withNavigationHelpers(), + translate(), )(Home); diff --git a/mobile-app/src/screens/Login/Login.js b/mobile-app/src/screens/Login/Login.js index 304aafde09..f1501d20e2 100644 --- a/mobile-app/src/screens/Login/Login.js +++ b/mobile-app/src/screens/Login/Login.js @@ -6,6 +6,7 @@ import { Text, TouchableOpacity, ActivityIndicator, + ImageBackground } from 'react-native'; import { connect } from 'react-redux'; import PropTypes from 'prop-types'; @@ -17,6 +18,7 @@ import { LinearGradient } from 'expo'; import { withNavigationHelpers } from '../../services/Navigation'; import { withLoadingScreen } from '../../services/Loading'; import { fetchAddress } from '../../services/Location'; +import { operations as teamsOperations } from '../../reducers/teams'; import { PRIVACY_URL, TERMS_URL } from '../../../env'; import { @@ -76,8 +78,10 @@ class Login extends Component { locationActive, location, updateProfile, + fetchTeams } = this.props; - const tabsGo = userProfile => { + const tabsGo = async userProfile => { + // await fetchTeams(); if (userProfile && userProfile.termsAcceptedAt) { this.props.navigation.resetTo('Tabs', {}); } else { @@ -85,6 +89,7 @@ class Login extends Component { } }; + if (!profile) { getProfile().then( userProfile => { @@ -157,7 +162,7 @@ class Login extends Component { ); } return ( - - + ); } } @@ -229,6 +234,7 @@ const mapDispatch = { googleLogin: userOperations.googleLogin, getProfile: userOperations.getProfile, updateProfile: userOperations.updateProfile, + fetchTeams: teamsOperations.fetchTeams, }; export default compose( diff --git a/mobile-app/src/screens/MyActivity/MyActivity.js b/mobile-app/src/screens/MyActivity/MyActivity.js index 90c52b3d3c..580b9b2aa7 100644 --- a/mobile-app/src/screens/MyActivity/MyActivity.js +++ b/mobile-app/src/screens/MyActivity/MyActivity.js @@ -19,6 +19,7 @@ import { selectors as trashSels, operations as trashOps, } from '../../reducers/trashpile'; +import { selectors as appSelectors } from '../../reducers/app'; import ActivityListItem from './components/ActivityListItem'; import { Divider } from '../../components/Divider'; import { EmptyStateScreen } from '../../components/EmptyStateScreen'; @@ -26,9 +27,10 @@ import { SimpleButton } from '../../components/Buttons'; import styles from './styles'; -const divider = () => ; +const divider = () => ; class MyActivity extends PureComponent { + goToDetails = _.debounce( ({ id, location }) => { this.props.navigation.navigate('Details', { @@ -43,22 +45,24 @@ class MyActivity extends PureComponent { }, ); - componentWillMount = () => {}; + componentWillMount = () => { + }; _renderItem = ({ item }) => - ; + ; _keyExtractor = ({ id }) => id; displayEmptyState = () => { return ( - + {this.props.t('label_text_activity_empty_hint')} - + ); @@ -67,14 +71,15 @@ class MyActivity extends PureComponent { displayLoading = () => { return ( - + ); }; displayRetry = () => { return ( - + ); }; @@ -110,13 +115,13 @@ class MyActivity extends PureComponent { }; render() { - const { loading, error, initialLoad, refreshing } = this.props; + const { loading, error, initialLoad, refreshing, isConnected } = this.props; - if (!initialLoad && error) { + if (!initialLoad && error && isConnected) { return this.displayRetry(); } - if (!initialLoad && loading && !refreshing) { + if (!initialLoad && loading && !refreshing || !isConnected) { return this.displayLoading(); } @@ -132,6 +137,7 @@ MyActivity.propTypes = { canLoadMore: PropTypes.bool.isRequired, refreshing: PropTypes.bool.isRequired, fetchUserTrashpoints: PropTypes.func.isRequired, + isConnected: PropTypes.bool.isRequired, }; const mapStateToProps = state => ({ @@ -141,6 +147,7 @@ const mapStateToProps = state => ({ initialLoad: trashSels.userTrashpointsInitialLoaded(state), canLoadMore: trashSels.userTrashpointsCanLoadMore(state), refreshing: trashSels.userTrashpointsRefreshing(state), + isConnected: appSelectors.isConnected(state), }); const mapDispatch = { fetchUserTrashpoints: trashOps.fetchUserTrashpoints, diff --git a/mobile-app/src/screens/MyActivity/components/ActivityListItem.js b/mobile-app/src/screens/MyActivity/components/ActivityListItem.js index a05a2ab09f..a25d9df388 100644 --- a/mobile-app/src/screens/MyActivity/components/ActivityListItem.js +++ b/mobile-app/src/screens/MyActivity/components/ActivityListItem.js @@ -52,26 +52,38 @@ const ActivityListItem = ({ location, counter = '', onPressItem, + backgroundColor }) => { const statusStyle = { backgroundColor: STATUSES_COLOR[status] }; + let nameToList = name.trim(); + let addressToList = address.trim(); + if (!nameToList || !addressToList) { + const { longitude, latitude } = location; + if (!nameToList) { + nameToList = `${latitude.toFixed(3)}, ${longitude.toFixed(3)}`; + } + if (!addressToList) { + addressToList = `${latitude.toFixed(6)}, ${longitude.toFixed(6)}`; + } + } return ( onPressItem({ id, location })} activeOpacity={0.9} > - + - {name} + {nameToList} - {address} + {addressToList} diff --git a/mobile-app/src/screens/Profile/Profile.js b/mobile-app/src/screens/Profile/Profile.js index 1b83d6580c..4fdae192cb 100644 --- a/mobile-app/src/screens/Profile/Profile.js +++ b/mobile-app/src/screens/Profile/Profile.js @@ -1,22 +1,55 @@ import React, { Component } from 'react'; -import { View, Image, Text } from 'react-native'; +import { View, Image, Text, ActivityIndicator } from 'react-native'; import { compose } from 'recompose'; import { connect } from 'react-redux'; +import { translate } from 'react-i18next'; import { Divider } from '../../components/Divider'; import { selectors as userSelectors } from '../../reducers/user'; +import { operations as teamsOps } from '../../reducers/teams'; +import { operations as userOps } from '../../reducers/user'; +import { selectors as appSelectors } from '../../reducers/app'; import { withNavigationHelpers } from '../../services/Navigation'; import styles from './styles'; +import { COUNTRIES_HASH } from '../../shared/countries'; +import SelectBlock from './SelectBlock'; +import { ROUTES } from '../../config/routes'; class Profile extends Component { + + componentWillMount() { + this.props.getProfile(); + } + + handleTeamPress = team => { + this.props.navigation.navigate(ROUTES.TeamProfile, { team }); + }; + + handleJoinTeamPress = () => { + this.props.navigation.navigate(ROUTES.Teams); + }; + + + displayLoading = () => { + return ( + + + + ); + }; + renderProfilePicture = (profile) => { const img = profile && profile.pictureURL ? { uri: profile.pictureURL } : require('./avatar.png'); - return ; + return ; }; + render() { - const { profile, country } = this.props; + const { t, profile, country, team, isConnected } = this.props; + if (!isConnected) { + return this.displayLoading(); + } return ( @@ -28,21 +61,47 @@ class Profile extends Component { {profile && profile.name} {country && - - - - - {country.name} - - } - + + + + {country.name} + + + } - + + + {team && + + + My team + {SelectBlock({ + header: team.name, + description: team.CC ? COUNTRIES_HASH[team.CC] : this.props.t('label_text_global_team'), + onPress: () => this.handleTeamPress(team), + imageURL: team.image, + imageLocal: require('./team.png'), + })} + + + } + + How to increase your impact + {SelectBlock({ + header: team ? t('label_text_search_teams') : t('label_text_join_a_team'), + description: t('label_text_join_a_team_description'), + onPress: this.handleJoinTeamPress, + imageLocal: require('./team.png') + })} + + + - ); + ) + ; } } @@ -50,12 +109,17 @@ const mapStateToProps = (state) => { return { profile: userSelectors.getProfile(state), country: userSelectors.getProfileCountry(state), + team: userSelectors.getProfileTeam(state), + isConnected: appSelectors.isConnected(state), }; }; - -const mapDispatchToProps = {}; +const mapDispatchToProps = { + updateTeam: teamsOps.updateTeam, + getProfile: userOps.getProfile, +}; export default compose( connect(mapStateToProps, mapDispatchToProps), withNavigationHelpers(), + translate(), )(Profile); diff --git a/mobile-app/src/screens/Profile/SelectBlock.js b/mobile-app/src/screens/Profile/SelectBlock.js new file mode 100644 index 0000000000..65ea7160b7 --- /dev/null +++ b/mobile-app/src/screens/Profile/SelectBlock.js @@ -0,0 +1,47 @@ +import React from 'react'; +import { View, Image, Text, TouchableHighlight } from 'react-native'; + +import styles from './styles'; + +const renderTeamImage = (imageURL, imageLocal) => { + return ( + + {imageURL ? + : + } + + ); +}; + +export default SelectBlock = ({ header, description, onPress, imageURL, imageLocal }) => ( + + + + {renderTeamImage(imageURL, imageLocal)} + + + + + {header} + + + + + {description} + + + + + + + + +); + diff --git a/mobile-app/src/screens/Profile/styles.js b/mobile-app/src/screens/Profile/styles.js index 950c29976f..5976d27619 100644 --- a/mobile-app/src/screens/Profile/styles.js +++ b/mobile-app/src/screens/Profile/styles.js @@ -42,4 +42,67 @@ export default EStyleSheet.create({ marginTop: getHeightPercentage(20), alignItems: 'center', }, + teamContainer: { + paddingVertical: getHeightPercentage(20), + flexDirection: 'row', + alignItems: 'flex-start', + justifyContent: 'flex-start', + flexWrap: 'wrap', + }, + teamIconContainer: { + width: '20%', + flexGrow: 1, + }, + teamIconImage: { + width: getWidthPercentage(40), + height: getWidthPercentage(40), + }, + teamContentContainer: { + flexGrow: 1, + width: '70%', + }, + teamTitleContainer: { + }, + teamTitle: { + fontFamily: '$boldFont', + fontSize: 20, + color: '$textTitleColor', + paddingRight: 20, + }, + teamNameContainer: { + }, + teamName: { + fontFamily: '$font', + fontSize: 15, + color: '#404040', + paddingRight: 20, + }, + teamChevronContainer: { + width: '10%', + alignItems: 'flex-end', + height: '100%', + paddingTop: 10, + }, + teamChevron: { + height: getHeightPercentage(15), + resizeMode: 'contain', + }, + addInfoContainer: { + paddingHorizontal: getWidthPercentage(10), + backgroundColor: '$white', + }, + teamsContainer: { + paddingHorizontal: getWidthPercentage(20), + paddingTop: getHeightPercentage(20), + }, + teamsHeader: { + fontSize: 20, + fontFamily: '$boldFont', + paddingTop: getHeightPercentage(1), + }, + displayLoadingView: { + flex: 1, + alignItems: 'center', + justifyContent: 'center', + }, }); diff --git a/mobile-app/src/screens/Profile/team.png b/mobile-app/src/screens/Profile/team.png new file mode 100644 index 0000000000..f1a1e0b699 Binary files /dev/null and b/mobile-app/src/screens/Profile/team.png differ diff --git a/mobile-app/src/screens/Settings/Settings.js b/mobile-app/src/screens/Settings/Settings.js index 9e50eb3d07..a5b297b80a 100644 --- a/mobile-app/src/screens/Settings/Settings.js +++ b/mobile-app/src/screens/Settings/Settings.js @@ -1,5 +1,5 @@ import React, { Component } from 'react'; -import { View } from 'react-native'; +import { View, ActivityIndicator } from 'react-native'; import { compose } from 'recompose'; import { connect } from 'react-redux'; import { translate } from 'react-i18next'; @@ -20,6 +20,7 @@ import styles, { downRightIcon, defaultRightIcon, } from './styles'; +import {selectors as appSelectors} from '../../reducers/app'; class Settings extends Component { constructor(props) { @@ -103,11 +104,24 @@ class Settings extends Component { ); }; + displayLoading = () => { + return ( + + + + ); + }; + render() { - const { country } = this.props; + const { country, isConnected } = this.props; + if(!isConnected) { + return this.displayLoading(); + } + const countrySubtitle = country ? country.name : this.props.t('label_country_picker_placeholder'); + return ( @@ -157,11 +171,13 @@ class Settings extends Component { ); } } + const mapState = (state) => { return { profile: userSels.getProfile(state), country: userSels.getProfileCountry(state), isProfileUpdating: userSels.isProfileUpdating(state), + isConnected: appSelectors.isConnected(state), }; }; const mapDispatch = { diff --git a/mobile-app/src/screens/Settings/components/CountryModal/CountryModal.js b/mobile-app/src/screens/Settings/components/CountryModal/CountryModal.js index 0dfe13f36f..5f99697311 100644 --- a/mobile-app/src/screens/Settings/components/CountryModal/CountryModal.js +++ b/mobile-app/src/screens/Settings/components/CountryModal/CountryModal.js @@ -51,11 +51,11 @@ class CountryModal extends Component {
diff --git a/mobile-app/src/screens/Settings/styles.js b/mobile-app/src/screens/Settings/styles.js index a2c5661dc8..6247b8b422 100644 --- a/mobile-app/src/screens/Settings/styles.js +++ b/mobile-app/src/screens/Settings/styles.js @@ -34,6 +34,11 @@ const styles = EStyleSheet.create({ marginBottom: 0, fontSize: 20, }, + displayLoadingView: { + flex: 1, + alignItems: 'center', + justifyContent: 'center', + }, }); export default styles; export const rightIcon = { diff --git a/mobile-app/src/screens/TeamProfile/TeamProfile.js b/mobile-app/src/screens/TeamProfile/TeamProfile.js new file mode 100644 index 0000000000..f9f7ca3378 --- /dev/null +++ b/mobile-app/src/screens/TeamProfile/TeamProfile.js @@ -0,0 +1,167 @@ +import React, { Component } from 'react'; +import { View, Image, Text, Alert, ScrollView, } from 'react-native'; +import { compose } from 'recompose'; +import { connect } from 'react-redux'; +import { translate } from 'react-i18next'; +import _ from 'lodash'; + +import { Divider } from '../../components/Divider'; +import { selectors as userSelectors } from '../../reducers/user'; +import { operations as teamsOps } from '../../reducers/teams'; +import { withNavigationHelpers } from '../../services/Navigation'; +import { COUNTRIES_HASH } from '../../shared/countries'; +import { Button } from '../../components/Buttons'; +import TrashCircle from './TrashCircle'; +import ActivityListItem from '../MyActivity/components/ActivityListItem'; +import { LAST_ACTIVITY_TRASHPOINTS_AMOUNT } from '../../shared/constants'; + +import styles from './styles'; + +class TeamProfile extends Component { + + + constructor(props) { + super(props); + const { params } = props.navigation.state; + this.state = params; + } + + alert = (join, onPress, team) => { + const { t } = this.props; + Alert.alert( + join ? t('label_button_join_team') : t('label_button_leave_team'), + `${join ? t('label_text_select_join') : t('label_text_select_leave')} ${team.name}?`, + [ + { text: t('label_no'), style: t('label_cancel') }, + { text: t('label_yes'), onPress }, + ], + ); + }; + + handleJoinTeamPress = team => this.alert(true, () => this.joinTeam(team.id), team); + + joinTeam = (id) => { + this.props.updateTeam({ team: id }); + this.props.navigation.navigate('Profile'); + }; + + goToDetails = _.debounce( + ({ id, location }) => { + this.props.navigation.navigate('Details', { + markerId: id, + latlng: location, + }); + }, + 1000, + { + leading: true, + trailing: false, + }, + ); + + handleTeamLeavePress = (team) => this.alert(false, this.leaveTeam, team); + + leaveTeam = () => { + this.props.updateTeam({ team: '' }); + this.props.navigation.navigate('Profile'); + }; + + + render() { + const { team } = this.state; + const myTeam = this.props.team; + + return ( + + + + + + + + + + {team.name} + + + + + {team.CC ? COUNTRIES_HASH[team.CC] : this.props.t('label_text_global_team')} + + + + + + {team.members} {this.props.t('label_text_members')} + + + + + + + {team.teamDescription} + + + + {this.props.t('label_text_team_trash_points')}: {team.trashpoints} + + {team.groupCount && + + + + + } + + + + {this.props.t('label_text_latest_activity')} + + {team.lastTrashpoints && team.lastTrashpoints.slice(0, LAST_ACTIVITY_TRASHPOINTS_AMOUNT).map(trash => ( + + ))} + + + {(myTeam && myTeam.id === team.id || !myTeam) && + + + + + + + + ); + } + + render() { + return ( + + ); + } +} + +const mapState = state => ({ + teams: selectors.getAllTeams(state), + loading: selectors.getTeamsLoading(state), +}); +const mapDispatch = { + fetchAllTeams: actions.fetchAllTeams, +}; + +TeamsList.propTypes = { + teams: PropTypes.array.isRequired, + fetchAllTeams: PropTypes.func.isRequired, +}; + +export default connect(mapState, mapDispatch)(TeamsList); diff --git a/web-app/src/pages/TeamsList/components/TeamsListItem/TeamsListItem.css b/web-app/src/pages/TeamsList/components/TeamsListItem/TeamsListItem.css new file mode 100644 index 0000000000..3e5b24d3d4 --- /dev/null +++ b/web-app/src/pages/TeamsList/components/TeamsListItem/TeamsListItem.css @@ -0,0 +1,29 @@ +.TeamsListItem { + display: flex; + flex-direction: row; + align-items: stretch; + justify-content: space-between; + padding-top: 13px; + padding-left: 8px; + padding-bottom: 9px; + cursor: default; +} + +.TeamsListItem:hover { + background-color: #D8EDFF; + cursor: pointer +} + +.TeamsListItem-name-container { + flex: 1; +} + +.TeamsListItem-trashpoint-container { + flex: 0; + padding: 0 10px; +} + +.TeamsListItem-users-container { + flex: 0; + padding: 0 10px; +} diff --git a/web-app/src/pages/TeamsList/components/TeamsListItem/TeamsListItem.js b/web-app/src/pages/TeamsList/components/TeamsListItem/TeamsListItem.js new file mode 100644 index 0000000000..28d70369c1 --- /dev/null +++ b/web-app/src/pages/TeamsList/components/TeamsListItem/TeamsListItem.js @@ -0,0 +1,20 @@ +import React from 'react'; + +import './TeamsListItem.css'; + +const TeamsListItem = ({ team: { name, trashpoints, users} , fetchTeam}) => { + return ( +
+
+ {name} +
+
+ {users} +
+
+ {trashpoints} +
+
+ ); +}; +export default TeamsListItem; diff --git a/web-app/src/pages/TeamsList/components/TeamsListItem/index.js b/web-app/src/pages/TeamsList/components/TeamsListItem/index.js new file mode 100644 index 0000000000..ece245f8b7 --- /dev/null +++ b/web-app/src/pages/TeamsList/components/TeamsListItem/index.js @@ -0,0 +1 @@ +export { default as TeamsListItem } from './TeamsListItem'; diff --git a/web-app/src/pages/TeamsList/index.js b/web-app/src/pages/TeamsList/index.js new file mode 100644 index 0000000000..cbc251d8c3 --- /dev/null +++ b/web-app/src/pages/TeamsList/index.js @@ -0,0 +1 @@ +export { default as TeamsList } from './TeamsList'; \ No newline at end of file diff --git a/web-app/src/pages/TrashpointList/TrashpointList.css b/web-app/src/pages/TrashpointList/TrashpointList.css index 2b1053f15b..1f0178cb75 100644 --- a/web-app/src/pages/TrashpointList/TrashpointList.css +++ b/web-app/src/pages/TrashpointList/TrashpointList.css @@ -34,4 +34,18 @@ font-weight: bold; line-height: 14px; text-align: center; -} \ No newline at end of file +} + +.StatusCount-block { + display: 'flex'; + flex: '1'; + flexDirection: 'column'; +} + +.MinusFlex { + flex: -1; +} + +.Flex { + flex: 1; +} diff --git a/web-app/src/pages/TrashpointList/TrashpointList.js b/web-app/src/pages/TrashpointList/TrashpointList.js index 61f5f898d1..cd911c6c6f 100644 --- a/web-app/src/pages/TrashpointList/TrashpointList.js +++ b/web-app/src/pages/TrashpointList/TrashpointList.js @@ -6,6 +6,7 @@ import _ from 'lodash'; import { actions, selectors } from '../../reducers/trashpile'; import { List } from '../../components/List'; import { TrashpointListItem } from './components/TrashpointListItem'; +import './TrashpointList.css'; const STATUS_COUNT_HASH = { threat: { @@ -139,11 +140,11 @@ class TrashpointList extends Component { render() { return ( -
-
+
+
{this.renderStatusCounts()}
-
+
async (dispatch, getState) => { + dispatch({ type: TYPES.FETCH_TEAMS_REQUEST }); + const country = userSelectors.getProfile(getState()).country; + const superadmin = userSelectors.getProfile(getState()).role === USER_ROLES.SUPERADMIN; + const response = country ? await ApiService.get(API_ENDPOINTS.FETCH_TEAMS(country, superadmin)) : await ApiService.get(API_ENDPOINTS.FETCH_ALL_TEAMS(superadmin)); + if (!response) { + return dispatch({ type: TYPES.FETCH_TEAMS_FAILED }); + } + + dispatch({ + type: TYPES.FETCH_TEAMS_SUCCESS, + teams: response.data, + }); +}; + + +const fetchTeam = (teamId) => async dispatch => { + dispatch({ type: TYPES.FETCH_TEAM_REQUEST }); + const response = await ApiService.get(API_ENDPOINTS.FETCH_TEAM(teamId)); + if (!response) { + return dispatch({ type: TYPES.FETCH_TEAM_FAILED }); + } + + dispatch({ + type: TYPES.FETCH_TEAM_SUCCESS, + team: response.data, + }); +}; + +export default { + fetchAllTeams, + fetchTeam +}; diff --git a/web-app/src/reducers/teams/index.js b/web-app/src/reducers/teams/index.js new file mode 100644 index 0000000000..da7e3555d6 --- /dev/null +++ b/web-app/src/reducers/teams/index.js @@ -0,0 +1,4 @@ +export { default } from './reducer'; +export { default as types } from './types'; +export { default as actions } from './actions'; +export { default as selectors } from './selectors'; diff --git a/web-app/src/reducers/teams/reducer.js b/web-app/src/reducers/teams/reducer.js new file mode 100644 index 0000000000..d29fb52eb7 --- /dev/null +++ b/web-app/src/reducers/teams/reducer.js @@ -0,0 +1,29 @@ +import TYPES from './types'; + +const TEAMS_INITIAL_STATE = { + teams: [], + loading: false, + teamLoading: false, + error: false, + team: {} +}; +const teamsReducer = (state = TEAMS_INITIAL_STATE, action) => { + switch (action.type) { + case TYPES.FETCH_TEAMS_REQUEST: + return { ...state, loading: true }; + case TYPES.FETCH_TEAMS_SUCCESS: + return { ...state, loading: false, teams: action.teams }; + case TYPES.FETCH_TEAMS_FAILED: + return { ...state, loading: false }; + case TYPES.FETCH_TEAM_REQUEST: + return { ...state, teamLoading: true }; + case TYPES.FETCH_TEAM_SUCCESS: + return { ...state, teamLoading: false, team: action.team }; + case TYPES.FETCH_TEAM_FAILED: + return { ...state, teamLoading: false }; + default: + return state; + } +}; + +export default teamsReducer; diff --git a/web-app/src/reducers/teams/selectors.js b/web-app/src/reducers/teams/selectors.js new file mode 100644 index 0000000000..23a2f12857 --- /dev/null +++ b/web-app/src/reducers/teams/selectors.js @@ -0,0 +1,14 @@ +import { createSelector } from 'reselect'; + +const teamsSelector = state => state.teams; +const getAllTeams = createSelector(teamsSelector, state => state.teams); +const getSelectedTeam = createSelector(teamsSelector, state => state.team); +const getTeamsLoading = createSelector(teamsSelector, state => state.loading); +const getSelectedTeamLoading = createSelector(teamsSelector, state => state.teamLoading); + +export default { + getAllTeams, + getTeamsLoading, + getSelectedTeam, + getSelectedTeamLoading +}; diff --git a/web-app/src/reducers/teams/types.js b/web-app/src/reducers/teams/types.js new file mode 100644 index 0000000000..73a142bce5 --- /dev/null +++ b/web-app/src/reducers/teams/types.js @@ -0,0 +1,8 @@ +export default { + FETCH_TEAMS_REQUEST: 'FETCH_TEAMS_REQUEST', + FETCH_TEAMS_SUCCESS: 'FETCH_TEAMS_SUCCESS', + FETCH_TEAMS_FAILED: 'FETCH_TEAMS_FAILED', + FETCH_TEAM_REQUEST: 'FETCH_TEAM_REQUEST', + FETCH_TEAM_SUCCESS: 'FETCH_TEAM_SUCCESS', + FETCH_TEAM_FAILED: 'FETCH_TEAM_FAILED', +}; diff --git a/web-app/src/reducers/trashpile/actions.js b/web-app/src/reducers/trashpile/actions.js index 23e59dc098..b75ef7d27e 100644 --- a/web-app/src/reducers/trashpile/actions.js +++ b/web-app/src/reducers/trashpile/actions.js @@ -365,10 +365,10 @@ export const handleUpload = async ({ photos, markerId }) => { const handledPhotos = [...thumbnailsPhotos, ...mediumPhotos]; const uploadedPhotosResponses = await uploadPhotosOnAzure(handledPhotos); - + const CONFIRM_CODE = 201; if (uploadedPhotosResponses) { uploadedPhotosResponses.forEach(({ status }, index) => { - const state = status === 201 ? 'confirmed' : 'failed'; + const state = status === CONFIRM_CODE ? 'confirmed' : 'failed'; uploadedPhotosIds[state].push(handledPhotos[index].id); }); const upRes = await confirmUploadedPhotos(markerId, uploadedPhotosIds); @@ -402,6 +402,7 @@ export const createMarker = ( ) => async (dispatch, getState) => { try { dispatch({ type: TYPES.CREATE_MARKER_REQUEST }); + const newMarker = { hashtags, composition, diff --git a/web-app/src/reducers/user.js b/web-app/src/reducers/user.js index b6bf503770..ff2807bb88 100644 --- a/web-app/src/reducers/user.js +++ b/web-app/src/reducers/user.js @@ -69,19 +69,20 @@ const authenticate = ({ network, token }) => async (dispatch, getState) => { const networkToken = response.data.token; ApiService.setAuthToken(networkToken); dispatch(setAuthToken(networkToken)); - dispatch(fetchProfile()).then(profile => { - if (!profile) { - return; - } - if (profile.locked) { - console.log('Account is locked'); - return; - } - if (!isAllowedRole(getState())) { - dispatch(logout()); - dispatch(appActions.showModal()); - } - }); + dispatch(fetchProfile()) + .then(profile => { + if (!profile) { + return; + } + if (profile.locked) { + console.log('Account is locked'); + return; + } + if (!isAllowedRole(getState())) { + dispatch(logout()); + dispatch(appActions.showModal()); + } + }); } catch (e) { console.log(e); } diff --git a/web-app/src/routes/Home/Home.css b/web-app/src/routes/Home/Home.css index 568a7893d0..e47a1cd203 100644 --- a/web-app/src/routes/Home/Home.css +++ b/web-app/src/routes/Home/Home.css @@ -62,6 +62,7 @@ .Home-create-marker-button span { text-align: center; height: 20px; + min-width: 123px; width: 123px; color: #FFFFFF; font-family: "Noto Sans"; diff --git a/web-app/src/routes/Home/Home.js b/web-app/src/routes/Home/Home.js index fae9b07dc3..af173a5ddf 100644 --- a/web-app/src/routes/Home/Home.js +++ b/web-app/src/routes/Home/Home.js @@ -16,13 +16,16 @@ import { UserDetails } from '../../pages/UserDetails'; import { CreateTrashpoint } from '../../components/CreateTrashpoint'; import { AreaList } from '../../pages/AreaList'; import { UserList } from '../../pages/UserList'; +import { TeamsList } from '../../pages/TeamsList'; import { AdminMap } from '../../pages/AdminMap'; import { TrashpointDetails } from '../../pages/TrashpointDetails'; +import { TeamDetails } from '../../pages/TeamDetails'; import { USER_ROLES } from '../../shared/constants'; import { Terms } from '../../components/Terms'; import { Privacy } from '../../components/Privacy'; import trashpointIcon from '../../assets/trashpoint_menu.png'; import userIcon from '../../assets/user_menu.png'; +import teamsIcon from '../../assets/teams_menu.png'; const BOTTOM_LINKS = [ { title: 'Terms & conditions', url: '/terms' }, @@ -59,11 +62,12 @@ class Home extends React.Component { - {/* */} + +
@@ -83,6 +87,7 @@ class Home extends React.Component { } const SIDEBAR_LINKS = [ { image: trashpointIcon, title: 'Trashpoints', url: '/areas' }, + { image: teamsIcon, title: 'Teams', url: '/teams' }, ]; if ([USER_ROLES.SUPERADMIN, USER_ROLES.LEADER].indexOf(userProfile.role) >= 0) { SIDEBAR_LINKS.push({ diff --git a/web-app/src/services/Api.js b/web-app/src/services/Api.js index 4f9adaacdd..b6126f8d6b 100644 --- a/web-app/src/services/Api.js +++ b/web-app/src/services/Api.js @@ -79,11 +79,12 @@ class ApiService { } } const IS_PRODUCTION = window.location.host === 'app.worldcleanupday.com'; -// export const BASE_URL = 'http://10.100.1.143:60000/api/v1' export const BASE_URL = process.env.NODE_ENV === 'development' - ? 'https://api-qa.app.worldcleanupday.com/api/v1' + ? process.env.REACT_APP_LOCAL_API + ? process.env.REACT_APP_LOCAL_API + : 'https://api-qa.app.worldcleanupday.com/api/v1' : IS_PRODUCTION ? `${window.location.protocol}//api.${window.location.host}/api/v1` : `${window.location.protocol}//api-${window.location.host}/api/v1`; diff --git a/web-app/src/shared/constants.js b/web-app/src/shared/constants.js index c63c13a9c9..fd813ac217 100644 --- a/web-app/src/shared/constants.js +++ b/web-app/src/shared/constants.js @@ -1,8 +1,8 @@ export const GOOGLE_MAPS_API_KEY = 'AIzaSyD0AC9TcY3xdmRsc_atlSHRreEbnEbxPEA'; -export const googleMapURL = `https://maps.googleapis.com/maps/api/js?v=3.27&libraries=places,geometry&key=${GOOGLE_MAPS_API_KEY}`; +export const googleMapURL = `https://maps.googleapis.com/maps/api/js?v=3.31&libraries=places,geometry&key=${GOOGLE_MAPS_API_KEY}`; export const DEFAULT_ZOOM_LEVEL = 18; -export const NO_PERMISSION_ZOOM_LEVEL = 9; -export const ESTONIA_CENTER_COORDINATES = { lat: 58.5953, lng: 25.0136 }; +export const NO_PERMISSION_ZOOM_LEVEL = 5; +export const EUROPE_CENTER_COORDINATES = { lat: 55.6057228, lng: 5.2133975 }; export const MARKER_DIAGONALE_IN_PX = 2 * Math.sqrt(Math.pow(28, 2) + Math.pow(38, 2)); const MAX_ZOOM_LEVEL = 22; export const DATASETS_TYPES = { @@ -29,6 +29,10 @@ export const API_ENDPOINTS = { FETCH_CLUSTER_TRASHPOINTS: '/overview/trashpoints/grid', LOCK_USER: userId => `/users/${userId}/lock`, FETCH_AREA_TRASHPOINTS: areaId => `/areas/${areaId}/trashpoints`, + FETCH_TEAMS: (country, superadmin) => `/teams/web?country=${country}&superadmin=${superadmin}`, + FETCH_ALL_TEAMS: superadmin => `/teams/web?superadmin=${superadmin}`, + FETCH_TEAMS_TRASHPOINTS: '/teams/trashpoints', + FETCH_TEAM: teamId => `/teams/${teamId}`, }; export const BACKEND_LOGIN_SOURCES = { FACEBOOK: 'facebook', diff --git a/web-app/yarn.lock b/web-app/yarn.lock index 368d613375..b26e18cc26 100644 --- a/web-app/yarn.lock +++ b/web-app/yarn.lock @@ -1,7 +1,5 @@ # THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. # yarn lockfile v1 - - "@storybook/addon-actions@^3.1.2": version "3.1.2" resolved "https://registry.yarnpkg.com/@storybook/addon-actions/-/addon-actions-3.1.2.tgz#0f28ae69277964d098fcd5e3f4a74b09a233a48c" @@ -174,7 +172,7 @@ acorn@^5.0.0, acorn@^5.0.1: version "5.0.3" resolved "https://registry.yarnpkg.com/acorn/-/acorn-5.0.3.tgz#c460df08491463f028ccb82eab3730bf01087b3d" -address@1.0.1, address@^1.0.1: +address@^1.0.1, address@1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/address/-/address-1.0.1.tgz#363f5d3f2be26d0655d8afd5a9562e4fc2194537" @@ -372,14 +370,14 @@ asn1@~0.2.3: version "0.2.3" resolved "https://registry.yarnpkg.com/asn1/-/asn1-0.2.3.tgz#dac8787713c9966849fc8180777ebe9c1ddf3b86" -assert-plus@1.0.0, assert-plus@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/assert-plus/-/assert-plus-1.0.0.tgz#f12e0f3c5d77b0b1cdd9146942e4e96c1e4dd525" - assert-plus@^0.2.0: version "0.2.0" resolved "https://registry.yarnpkg.com/assert-plus/-/assert-plus-0.2.0.tgz#d74e1b87e7affc0db8aadb7021f3fe48101ab234" +assert-plus@^1.0.0, assert-plus@1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/assert-plus/-/assert-plus-1.0.0.tgz#f12e0f3c5d77b0b1cdd9146942e4e96c1e4dd525" + assert@^1.1.1: version "1.4.1" resolved "https://registry.yarnpkg.com/assert/-/assert-1.4.1.tgz#99912d591836b5a6f5b345c0f07eefc08fc65d91" @@ -420,17 +418,6 @@ attr-accept@^1.0.3: version "1.1.0" resolved "https://registry.yarnpkg.com/attr-accept/-/attr-accept-1.1.0.tgz#b5cd35227f163935a8f1de10ed3eba16941f6be6" -autoprefixer@7.1.0: - version "7.1.0" - resolved "https://registry.yarnpkg.com/autoprefixer/-/autoprefixer-7.1.0.tgz#ae4913adc221fa6ca5ad3a6f8039f6a5c06b3877" - dependencies: - browserslist "^2.1.2" - caniuse-lite "^1.0.30000669" - normalize-range "^0.1.2" - num2fraction "^1.2.2" - postcss "^6.0.1" - postcss-value-parser "^3.2.3" - autoprefixer@^6.3.1: version "6.7.7" resolved "https://registry.yarnpkg.com/autoprefixer/-/autoprefixer-6.7.7.tgz#1dbd1c835658e35ce3f9984099db00585c782014" @@ -453,6 +440,17 @@ autoprefixer@^7.1.1: postcss "^6.0.1" postcss-value-parser "^3.2.3" +autoprefixer@7.1.0: + version "7.1.0" + resolved "https://registry.yarnpkg.com/autoprefixer/-/autoprefixer-7.1.0.tgz#ae4913adc221fa6ca5ad3a6f8039f6a5c06b3877" + dependencies: + browserslist "^2.1.2" + caniuse-lite "^1.0.30000669" + normalize-range "^0.1.2" + num2fraction "^1.2.2" + postcss "^6.0.1" + postcss-value-parser "^3.2.3" + aws-sign2@~0.6.0: version "0.6.0" resolved "https://registry.yarnpkg.com/aws-sign2/-/aws-sign2-0.6.0.tgz#14342dd38dbcc94d0e5b87d763cd63612c0e794f" @@ -474,7 +472,7 @@ axobject-query@^0.1.0: dependencies: ast-types-flow "0.0.7" -babel-code-frame@6.22.0, babel-code-frame@^6.11.0, babel-code-frame@^6.16.0, babel-code-frame@^6.22.0: +babel-code-frame@^6.11.0, babel-code-frame@^6.16.0, babel-code-frame@^6.22.0, babel-code-frame@6.22.0: version "6.22.0" resolved "https://registry.yarnpkg.com/babel-code-frame/-/babel-code-frame-6.22.0.tgz#027620bee567a88c32561574e7fd0801d33118e4" dependencies: @@ -482,7 +480,7 @@ babel-code-frame@6.22.0, babel-code-frame@^6.11.0, babel-code-frame@^6.16.0, bab esutils "^2.0.2" js-tokens "^3.0.0" -babel-core@6.24.1, babel-core@^6.0.0, babel-core@^6.24.1: +babel-core@^6.0.0, babel-core@^6.24.1, babel-core@6.24.1: version "6.24.1" resolved "https://registry.yarnpkg.com/babel-core/-/babel-core-6.24.1.tgz#8c428564dce1e1f41fb337ec34f4c3b022b5ad83" dependencies: @@ -506,7 +504,7 @@ babel-core@6.24.1, babel-core@^6.0.0, babel-core@^6.24.1: slash "^1.0.0" source-map "^0.5.0" -babel-eslint@7.2.3, babel-eslint@^7.2.3: +babel-eslint@^7.2.3, babel-eslint@7.2.3: version "7.2.3" resolved "https://registry.yarnpkg.com/babel-eslint/-/babel-eslint-7.2.3.tgz#b2fe2d80126470f5c19442dc757253a897710827" dependencies: @@ -654,7 +652,7 @@ babel-helpers@^6.24.1: babel-runtime "^6.22.0" babel-template "^6.24.1" -babel-jest@20.0.3, babel-jest@^20.0.3: +babel-jest@^20.0.3, babel-jest@20.0.3: version "20.0.3" resolved "https://registry.yarnpkg.com/babel-jest/-/babel-jest-20.0.3.tgz#e4a03b13dc10389e140fc645d09ffc4ced301671" dependencies: @@ -662,7 +660,7 @@ babel-jest@20.0.3, babel-jest@^20.0.3: babel-plugin-istanbul "^4.0.0" babel-preset-jest "^20.0.3" -babel-loader@7.0.0, babel-loader@^7.0.0: +babel-loader@^7.0.0, babel-loader@7.0.0: version "7.0.0" resolved "https://registry.yarnpkg.com/babel-loader/-/babel-loader-7.0.0.tgz#2e43a66bee1fff4470533d0402c8a4532fafbaf7" dependencies: @@ -734,7 +732,7 @@ babel-plugin-syntax-do-expressions@^6.8.0: version "6.13.0" resolved "https://registry.yarnpkg.com/babel-plugin-syntax-do-expressions/-/babel-plugin-syntax-do-expressions-6.13.0.tgz#5747756139aa26d390d09410b03744ba07e4796d" -babel-plugin-syntax-dynamic-import@6.18.0, babel-plugin-syntax-dynamic-import@^6.18.0: +babel-plugin-syntax-dynamic-import@^6.18.0, babel-plugin-syntax-dynamic-import@6.18.0: version "6.18.0" resolved "https://registry.yarnpkg.com/babel-plugin-syntax-dynamic-import/-/babel-plugin-syntax-dynamic-import-6.18.0.tgz#8d6a26229c83745a9982a441051572caa179b1da" @@ -790,7 +788,7 @@ babel-plugin-transform-class-constructor-call@^6.24.1: babel-runtime "^6.22.0" babel-template "^6.24.1" -babel-plugin-transform-class-properties@6.24.1, babel-plugin-transform-class-properties@^6.24.1: +babel-plugin-transform-class-properties@^6.24.1, babel-plugin-transform-class-properties@6.24.1: version "6.24.1" resolved "https://registry.yarnpkg.com/babel-plugin-transform-class-properties/-/babel-plugin-transform-class-properties-6.24.1.tgz#6a79763ea61d33d36f37b611aa9def81a81b46ac" dependencies: @@ -1013,7 +1011,7 @@ babel-plugin-transform-function-bind@^6.22.0: babel-plugin-syntax-function-bind "^6.8.0" babel-runtime "^6.22.0" -babel-plugin-transform-object-rest-spread@6.23.0, babel-plugin-transform-object-rest-spread@^6.22.0: +babel-plugin-transform-object-rest-spread@^6.22.0, babel-plugin-transform-object-rest-spread@6.23.0: version "6.23.0" resolved "https://registry.yarnpkg.com/babel-plugin-transform-object-rest-spread/-/babel-plugin-transform-object-rest-spread-6.23.0.tgz#875d6bc9be761c58a2ae3feee5dc4895d8c7f921" dependencies: @@ -1032,21 +1030,21 @@ babel-plugin-transform-react-display-name@^6.23.0: dependencies: babel-runtime "^6.22.0" -babel-plugin-transform-react-jsx-self@6.22.0, babel-plugin-transform-react-jsx-self@^6.22.0: +babel-plugin-transform-react-jsx-self@^6.22.0, babel-plugin-transform-react-jsx-self@6.22.0: version "6.22.0" resolved "https://registry.yarnpkg.com/babel-plugin-transform-react-jsx-self/-/babel-plugin-transform-react-jsx-self-6.22.0.tgz#df6d80a9da2612a121e6ddd7558bcbecf06e636e" dependencies: babel-plugin-syntax-jsx "^6.8.0" babel-runtime "^6.22.0" -babel-plugin-transform-react-jsx-source@6.22.0, babel-plugin-transform-react-jsx-source@^6.22.0: +babel-plugin-transform-react-jsx-source@^6.22.0, babel-plugin-transform-react-jsx-source@6.22.0: version "6.22.0" resolved "https://registry.yarnpkg.com/babel-plugin-transform-react-jsx-source/-/babel-plugin-transform-react-jsx-source-6.22.0.tgz#66ac12153f5cd2d17b3c19268f4bf0197f44ecd6" dependencies: babel-plugin-syntax-jsx "^6.8.0" babel-runtime "^6.22.0" -babel-plugin-transform-react-jsx@6.24.1, babel-plugin-transform-react-jsx@^6.24.1: +babel-plugin-transform-react-jsx@^6.24.1, babel-plugin-transform-react-jsx@6.24.1: version "6.24.1" resolved "https://registry.yarnpkg.com/babel-plugin-transform-react-jsx/-/babel-plugin-transform-react-jsx-6.24.1.tgz#840a028e7df460dfc3a2d29f0c0d91f6376e66a3" dependencies: @@ -1054,7 +1052,7 @@ babel-plugin-transform-react-jsx@6.24.1, babel-plugin-transform-react-jsx@^6.24. babel-plugin-syntax-jsx "^6.8.0" babel-runtime "^6.22.0" -babel-plugin-transform-regenerator@6.24.1, babel-plugin-transform-regenerator@^6.22.0, babel-plugin-transform-regenerator@^6.24.1: +babel-plugin-transform-regenerator@^6.22.0, babel-plugin-transform-regenerator@^6.24.1, babel-plugin-transform-regenerator@6.24.1: version "6.24.1" resolved "https://registry.yarnpkg.com/babel-plugin-transform-regenerator/-/babel-plugin-transform-regenerator-6.24.1.tgz#b8da305ad43c3c99b4848e4fe4037b770d23c418" dependencies: @@ -1171,7 +1169,7 @@ babel-preset-react-app@^3.0.0: babel-preset-env "1.4.0" babel-preset-react "6.24.1" -babel-preset-react@6.24.1, babel-preset-react@^6.24.1: +babel-preset-react@^6.24.1, babel-preset-react@6.24.1: version "6.24.1" resolved "https://registry.yarnpkg.com/babel-preset-react/-/babel-preset-react-6.24.1.tgz#ba69dfaea45fc3ec639b6a4ecea6e17702c91380" dependencies: @@ -1229,7 +1227,7 @@ babel-register@^6.24.1: mkdirp "^0.5.1" source-map-support "^0.4.2" -babel-runtime@6.23.0, babel-runtime@6.x.x, babel-runtime@^6.11.6, babel-runtime@^6.18.0, babel-runtime@^6.22.0, babel-runtime@^6.23.0, babel-runtime@^6.5.0, babel-runtime@^6.9.2: +babel-runtime@^6.11.6, babel-runtime@^6.18.0, babel-runtime@^6.22.0, babel-runtime@^6.23.0, babel-runtime@^6.5.0, babel-runtime@^6.9.2, babel-runtime@6.23.0, babel-runtime@6.x.x: version "6.23.0" resolved "https://registry.yarnpkg.com/babel-runtime/-/babel-runtime-6.23.0.tgz#0a9489f144de70efb3ce4300accdb329e2fc543b" dependencies: @@ -1443,18 +1441,18 @@ browserslist@^2.1.2, browserslist@^2.1.3: caniuse-lite "^1.0.30000670" electron-to-chromium "^1.3.11" -bser@1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/bser/-/bser-1.0.2.tgz#381116970b2a6deea5646dd15dd7278444b56169" - dependencies: - node-int64 "^0.4.0" - bser@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/bser/-/bser-2.0.0.tgz#9ac78d3ed5d915804fd87acb158bc797147a1719" dependencies: node-int64 "^0.4.0" +bser@1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/bser/-/bser-1.0.2.tgz#381116970b2a6deea5646dd15dd7278444b56169" + dependencies: + node-int64 "^0.4.0" + buffer-xor@^1.0.2: version "1.0.3" resolved "https://registry.yarnpkg.com/buffer-xor/-/buffer-xor-1.0.3.tgz#26e61ed1422fb70dd42e6e36729ed51d855fe8d9" @@ -1544,14 +1542,14 @@ capture-stack-trace@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/capture-stack-trace/-/capture-stack-trace-1.0.0.tgz#4a6fa07399c26bba47f0b2496b4d0fb408c5550d" -case-sensitive-paths-webpack-plugin@1.1.4: - version "1.1.4" - resolved "https://registry.yarnpkg.com/case-sensitive-paths-webpack-plugin/-/case-sensitive-paths-webpack-plugin-1.1.4.tgz#8aaedd5699a86cac2b34cf40d9b4145758978472" - case-sensitive-paths-webpack-plugin@^2.0.0: version "2.1.1" resolved "https://registry.yarnpkg.com/case-sensitive-paths-webpack-plugin/-/case-sensitive-paths-webpack-plugin-2.1.1.tgz#3d29ced8c1f124bf6f53846fb3f5894731fdc909" +case-sensitive-paths-webpack-plugin@1.1.4: + version "1.1.4" + resolved "https://registry.yarnpkg.com/case-sensitive-paths-webpack-plugin/-/case-sensitive-paths-webpack-plugin-1.1.4.tgz#8aaedd5699a86cac2b34cf40d9b4145758978472" + caseless@~0.12.0: version "0.12.0" resolved "https://registry.yarnpkg.com/caseless/-/caseless-0.12.0.tgz#1b681c21ff84033c826543090689420d187151dc" @@ -1563,7 +1561,7 @@ center-align@^0.1.1: align-text "^0.1.3" lazy-cache "^1.0.3" -chalk@1.1.3, chalk@^1.0.0, chalk@^1.1.0, chalk@^1.1.1, chalk@^1.1.3: +chalk@^1.0.0, chalk@^1.1.0, chalk@^1.1.1, chalk@^1.1.3, chalk@1.1.3: version "1.1.3" resolved "https://registry.yarnpkg.com/chalk/-/chalk-1.1.3.tgz#a8115c55e4a702fe4d150abd3872822a7e09fc98" dependencies: @@ -1612,7 +1610,7 @@ clap@^1.0.9: dependencies: chalk "^1.1.3" -classnames@2.2.5, classnames@^2.2.3, classnames@^2.2.5: +classnames@^2.2.3, classnames@^2.2.5, classnames@2.2.5: version "2.2.5" resolved "https://registry.yarnpkg.com/classnames/-/classnames-2.2.5.tgz#fb3801d453467649ef3603c7d61a02bd129bde6d" @@ -1658,14 +1656,14 @@ cliui@^3.2.0: strip-ansi "^3.0.1" wrap-ansi "^2.0.0" -clone@2.1.1: - version "2.1.1" - resolved "https://registry.yarnpkg.com/clone/-/clone-2.1.1.tgz#d217d1e961118e3ac9a4b8bba3285553bf647cdb" - clone@^1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/clone/-/clone-1.0.2.tgz#260b7a99ebb1edfe247538175f783243cb19d149" +clone@2.1.1: + version "2.1.1" + resolved "https://registry.yarnpkg.com/clone/-/clone-2.1.1.tgz#d217d1e961118e3ac9a4b8bba3285553bf647cdb" + co@^4.6.0: version "4.6.0" resolved "https://registry.yarnpkg.com/co/-/co-4.6.0.tgz#6ea6bdf3d853ae54ccb8e47bfa0bf3f9031fb184" @@ -1722,7 +1720,7 @@ combined-stream@^1.0.5, combined-stream@~1.0.5: dependencies: delayed-stream "~1.0.0" -commander@2.9.x, commander@^2.9.0, commander@~2.9.0: +commander@^2.9.0, commander@~2.9.0, commander@2.9.x: version "2.9.0" resolved "https://registry.yarnpkg.com/commander/-/commander-2.9.0.tgz#9c99094176e12240cb22d6c5146098400fe0f7d4" dependencies: @@ -1907,13 +1905,6 @@ create-react-class@^15.5.2, create-react-class@^15.5.3: loose-envify "^1.3.1" object-assign "^4.1.1" -cross-spawn@4.0.2: - version "4.0.2" - resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-4.0.2.tgz#7b9247621c23adfdd3856004a823cbe397424d41" - dependencies: - lru-cache "^4.0.1" - which "^1.2.9" - cross-spawn@^3.0.0: version "3.0.1" resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-3.0.1.tgz#1256037ecb9f0c5f79e3d6ef135e30770184b982" @@ -1929,6 +1920,13 @@ cross-spawn@^5.0.1: shebang-command "^1.2.0" which "^1.2.9" +cross-spawn@4.0.2: + version "4.0.2" + resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-4.0.2.tgz#7b9247621c23adfdd3856004a823cbe397424d41" + dependencies: + lru-cache "^4.0.1" + which "^1.2.9" + cryptiles@2.x.x: version "2.0.5" resolved "https://registry.yarnpkg.com/cryptiles/-/cryptiles-2.0.5.tgz#3bdfecdc608147c1c67202fa291e7dca59eaa3b8" @@ -1964,7 +1962,7 @@ css-in-js-utils@^1.0.3: dependencies: hyphenate-style-name "^1.0.2" -css-loader@0.28.1, css-loader@^0.28.1: +css-loader@^0.28.1, css-loader@0.28.1: version "0.28.1" resolved "https://registry.yarnpkg.com/css-loader/-/css-loader-0.28.1.tgz#220325599f8f00452d9ceb4c3ca6c8a66798642d" dependencies: @@ -2057,7 +2055,7 @@ csso@~2.3.1: clap "^1.0.9" source-map "^0.5.3" -cssom@0.3.x, "cssom@>= 0.3.2 < 0.4.0": +"cssom@>= 0.3.2 < 0.4.0", cssom@0.3.x: version "0.3.2" resolved "https://registry.yarnpkg.com/cssom/-/cssom-0.3.2.tgz#b8036170c79f07a90ff2f16e22284027a243848b" @@ -2093,7 +2091,13 @@ date-now@^0.1.4: version "0.1.4" resolved "https://registry.yarnpkg.com/date-now/-/date-now-0.1.4.tgz#eaf439fd4d4848ad74e5cc7dbef200672b9e345b" -debug@2.2.0, debug@~2.2.0: +debug@^2.1.1, debug@^2.2.0, debug@^2.4.5, debug@^2.6.0, debug@^2.6.3, debug@^2.6.6, debug@^2.6.8, debug@2.6.8: + version "2.6.8" + resolved "https://registry.yarnpkg.com/debug/-/debug-2.6.8.tgz#e731531ca2ede27d188222427da17821d68ff4fc" + dependencies: + ms "2.0.0" + +debug@~2.2.0, debug@2.2.0: version "2.2.0" resolved "https://registry.yarnpkg.com/debug/-/debug-2.2.0.tgz#f87057e995b1a1f6ae6a4960664137bc56f039da" dependencies: @@ -2105,12 +2109,6 @@ debug@2.6.7: dependencies: ms "2.0.0" -debug@2.6.8, debug@^2.1.1, debug@^2.2.0, debug@^2.4.5, debug@^2.6.0, debug@^2.6.3, debug@^2.6.6, debug@^2.6.8: - version "2.6.8" - resolved "https://registry.yarnpkg.com/debug/-/debug-2.6.8.tgz#e731531ca2ede27d188222427da17821d68ff4fc" - dependencies: - ms "2.0.0" - decamelize@^1.0.0, decamelize@^1.1.1, decamelize@^1.1.2: version "1.2.0" resolved "https://registry.yarnpkg.com/decamelize/-/decamelize-1.2.0.tgz#f6534d15148269b20352e7bee26f501f9a191290" @@ -2168,7 +2166,7 @@ delegates@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/delegates/-/delegates-1.0.0.tgz#84c6e159b81904fdca59a0ef44cd870d31250f9a" -depd@1.1.0, depd@~1.1.0: +depd@~1.1.0, depd@1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/depd/-/depd-1.1.0.tgz#e1bd82c6aab6ced965b97b88b17ed3e528ca18c3" @@ -2205,16 +2203,16 @@ diffie-hellman@^5.0.0: miller-rabin "^4.0.0" randombytes "^2.0.0" -doctrine@1.5.0: - version "1.5.0" - resolved "https://registry.yarnpkg.com/doctrine/-/doctrine-1.5.0.tgz#379dce730f6166f76cefa4e6707a159b02c5a6fa" +doctrine@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/doctrine/-/doctrine-2.0.0.tgz#c73d8d2909d22291e1a007a395804da8b665fe63" dependencies: esutils "^2.0.2" isarray "^1.0.0" -doctrine@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/doctrine/-/doctrine-2.0.0.tgz#c73d8d2909d22291e1a007a395804da8b665fe63" +doctrine@1.5.0: + version "1.5.0" + resolved "https://registry.yarnpkg.com/doctrine/-/doctrine-1.5.0.tgz#379dce730f6166f76cefa4e6707a159b02c5a6fa" dependencies: esutils "^2.0.2" isarray "^1.0.0" @@ -2246,14 +2244,14 @@ domain-browser@^1.1.1: version "1.1.7" resolved "https://registry.yarnpkg.com/domain-browser/-/domain-browser-1.1.7.tgz#867aa4b093faa05f1de08c06f4d7b21fdf8698bc" -domelementtype@1: - version "1.3.0" - resolved "https://registry.yarnpkg.com/domelementtype/-/domelementtype-1.3.0.tgz#b17aed82e8ab59e52dd9c19b1756e0fc187204c2" - domelementtype@~1.1.1: version "1.1.3" resolved "https://registry.yarnpkg.com/domelementtype/-/domelementtype-1.1.3.tgz#bd28773e2642881aec51544924299c5cd822185b" +domelementtype@1: + version "1.3.0" + resolved "https://registry.yarnpkg.com/domelementtype/-/domelementtype-1.3.0.tgz#b17aed82e8ab59e52dd9c19b1756e0fc187204c2" + domhandler@2.1: version "2.1.0" resolved "https://registry.yarnpkg.com/domhandler/-/domhandler-2.1.0.tgz#d2646f5e57f6c3bab11cf6cb05d3c0acf7412594" @@ -2289,16 +2287,16 @@ dotenv@4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/dotenv/-/dotenv-4.0.0.tgz#864ef1379aced55ce6f95debecdce179f7a0cd1d" +duplexer@^0.1.1, duplexer@~0.1.1: + version "0.1.1" + resolved "https://registry.yarnpkg.com/duplexer/-/duplexer-0.1.1.tgz#ace6ff808c1ce66b57d1ebf97977acb02334cfc1" + duplexer2@^0.1.4: version "0.1.4" resolved "https://registry.yarnpkg.com/duplexer2/-/duplexer2-0.1.4.tgz#8b12dab878c0d69e3e7891051662a32fc6bddcc1" dependencies: readable-stream "^2.0.2" -duplexer@^0.1.1, duplexer@~0.1.1: - version "0.1.1" - resolved "https://registry.yarnpkg.com/duplexer/-/duplexer-0.1.1.tgz#ace6ff808c1ce66b57d1ebf97977acb02334cfc1" - ecc-jsbn@~0.1.1: version "0.1.1" resolved "https://registry.yarnpkg.com/ecc-jsbn/-/ecc-jsbn-0.1.1.tgz#0fc73a9ed5f0d53c38193398523ef7e543777505" @@ -2360,7 +2358,7 @@ entities@~1.1.1: version "1.1.1" resolved "https://registry.yarnpkg.com/entities/-/entities-1.1.1.tgz#6e5c2d0a5621b5dadaecef80b90edfb5cd7772f0" -"errno@>=0.1.1 <0.2.0-0", errno@^0.1.3: +errno@^0.1.3, "errno@>=0.1.1 <0.2.0-0": version "0.1.4" resolved "https://registry.yarnpkg.com/errno/-/errno-0.1.4.tgz#b896e23a9e5e8ba33871fc996abd3635fc9a1c7d" dependencies: @@ -2400,7 +2398,7 @@ es5-shim@^4.5.9: version "4.5.9" resolved "https://registry.yarnpkg.com/es5-shim/-/es5-shim-4.5.9.tgz#2a1e2b9e583ff5fed0c20a3ee2cbf3f75230a5c0" -es6-iterator@2, es6-iterator@^2.0.1, es6-iterator@~2.0.1: +es6-iterator@^2.0.1, es6-iterator@~2.0.1, es6-iterator@2: version "2.0.1" resolved "https://registry.yarnpkg.com/es6-iterator/-/es6-iterator-2.0.1.tgz#8e319c9f0453bf575d374940a655920e59ca5512" dependencies: @@ -2437,7 +2435,7 @@ es6-shim@^0.35.1: version "0.35.3" resolved "https://registry.yarnpkg.com/es6-shim/-/es6-shim-0.35.3.tgz#9bfb7363feffff87a6cdb6cd93e405ec3c4b6f26" -es6-symbol@3.1.1, es6-symbol@^3.1, es6-symbol@^3.1.1, es6-symbol@~3.1, es6-symbol@~3.1.1: +es6-symbol@^3.1, es6-symbol@^3.1.1, es6-symbol@~3.1, es6-symbol@~3.1.1, es6-symbol@3.1.1: version "3.1.1" resolved "https://registry.yarnpkg.com/es6-symbol/-/es6-symbol-3.1.1.tgz#bf00ef4fdab6ba1b46ecb7b629b4c7ed5715cc77" dependencies: @@ -2457,7 +2455,7 @@ escape-html@~1.0.3: version "1.0.3" resolved "https://registry.yarnpkg.com/escape-html/-/escape-html-1.0.3.tgz#0258eae4d3d0c0974de1c169188ef0051d1d1988" -escape-string-regexp@1.0.5, escape-string-regexp@^1.0.2, escape-string-regexp@^1.0.5: +escape-string-regexp@^1.0.2, escape-string-regexp@^1.0.5, escape-string-regexp@1.0.5: version "1.0.5" resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz#1b61c0562190a8dff6ae3bb2cf0200ca130b86d4" @@ -2521,21 +2519,21 @@ eslint-module-utils@^2.0.0: debug "2.2.0" pkg-dir "^1.0.0" -eslint-plugin-flowtype@2.33.0: - version "2.33.0" - resolved "https://registry.yarnpkg.com/eslint-plugin-flowtype/-/eslint-plugin-flowtype-2.33.0.tgz#b2783814ed2ddcf729953b8f65ff73c90cabee4b" - dependencies: - lodash "^4.15.0" - eslint-plugin-flowtype@^2.34.0: version "2.34.0" resolved "https://registry.yarnpkg.com/eslint-plugin-flowtype/-/eslint-plugin-flowtype-2.34.0.tgz#b9875f314652e5081623c9d2b18a346bbb759c09" dependencies: lodash "^4.15.0" -eslint-plugin-import@2.2.0: - version "2.2.0" - resolved "https://registry.yarnpkg.com/eslint-plugin-import/-/eslint-plugin-import-2.2.0.tgz#72ba306fad305d67c4816348a4699a4229ac8b4e" +eslint-plugin-flowtype@2.33.0: + version "2.33.0" + resolved "https://registry.yarnpkg.com/eslint-plugin-flowtype/-/eslint-plugin-flowtype-2.33.0.tgz#b2783814ed2ddcf729953b8f65ff73c90cabee4b" + dependencies: + lodash "^4.15.0" + +eslint-plugin-import@^2.3.0: + version "2.3.0" + resolved "https://registry.yarnpkg.com/eslint-plugin-import/-/eslint-plugin-import-2.3.0.tgz#37c801e0ada0e296cbdf20c3f393acb5b52af36b" dependencies: builtin-modules "^1.1.1" contains-path "^0.1.0" @@ -2546,11 +2544,11 @@ eslint-plugin-import@2.2.0: has "^1.0.1" lodash.cond "^4.3.0" minimatch "^3.0.3" - pkg-up "^1.0.0" + read-pkg-up "^2.0.0" -eslint-plugin-import@^2.3.0: - version "2.3.0" - resolved "https://registry.yarnpkg.com/eslint-plugin-import/-/eslint-plugin-import-2.3.0.tgz#37c801e0ada0e296cbdf20c3f393acb5b52af36b" +eslint-plugin-import@2.2.0: + version "2.2.0" + resolved "https://registry.yarnpkg.com/eslint-plugin-import/-/eslint-plugin-import-2.2.0.tgz#72ba306fad305d67c4816348a4699a4229ac8b4e" dependencies: builtin-modules "^1.1.1" contains-path "^0.1.0" @@ -2561,9 +2559,9 @@ eslint-plugin-import@^2.3.0: has "^1.0.1" lodash.cond "^4.3.0" minimatch "^3.0.3" - read-pkg-up "^2.0.0" + pkg-up "^1.0.0" -eslint-plugin-jsx-a11y@5.0.3, eslint-plugin-jsx-a11y@^5.0.3: +eslint-plugin-jsx-a11y@^5.0.3, eslint-plugin-jsx-a11y@5.0.3: version "5.0.3" resolved "https://registry.yarnpkg.com/eslint-plugin-jsx-a11y/-/eslint-plugin-jsx-a11y-5.0.3.tgz#4a939f76ec125010528823331bf948cc573380b6" dependencies: @@ -2575,14 +2573,6 @@ eslint-plugin-jsx-a11y@5.0.3, eslint-plugin-jsx-a11y@^5.0.3: emoji-regex "^6.1.0" jsx-ast-utils "^1.4.0" -eslint-plugin-react@7.0.1: - version "7.0.1" - resolved "https://registry.yarnpkg.com/eslint-plugin-react/-/eslint-plugin-react-7.0.1.tgz#e78107e1e559c6e2b17786bb67c2e2a010ad0d2f" - dependencies: - doctrine "^2.0.0" - has "^1.0.1" - jsx-ast-utils "^1.3.4" - eslint-plugin-react@^7.1.0: version "7.1.0" resolved "https://registry.yarnpkg.com/eslint-plugin-react/-/eslint-plugin-react-7.1.0.tgz#27770acf39f5fd49cd0af4083ce58104eb390d4c" @@ -2591,7 +2581,15 @@ eslint-plugin-react@^7.1.0: has "^1.0.1" jsx-ast-utils "^1.4.1" -eslint@3.19.0, eslint@^3.19.0: +eslint-plugin-react@7.0.1: + version "7.0.1" + resolved "https://registry.yarnpkg.com/eslint-plugin-react/-/eslint-plugin-react-7.0.1.tgz#e78107e1e559c6e2b17786bb67c2e2a010ad0d2f" + dependencies: + doctrine "^2.0.0" + has "^1.0.1" + jsx-ast-utils "^1.3.4" + +eslint@^3.19.0, eslint@3.19.0: version "3.19.0" resolved "https://registry.yarnpkg.com/eslint/-/eslint-3.19.0.tgz#c8fc6201c7f40dd08941b87c085767386a679acc" dependencies: @@ -2884,7 +2882,7 @@ file-entry-cache@^2.0.0: flat-cache "^1.2.1" object-assign "^4.0.1" -file-loader@0.11.1, file-loader@^0.11.1: +file-loader@^0.11.1, file-loader@0.11.1: version "0.11.1" resolved "https://registry.yarnpkg.com/file-loader/-/file-loader-0.11.1.tgz#6b328ee1234a729e4e47d36375dd6d35c0e1db84" dependencies: @@ -3021,14 +3019,6 @@ from@~0: version "0.1.7" resolved "https://registry.yarnpkg.com/from/-/from-0.1.7.tgz#83c60afc58b9c56997007ed1a768b3ab303a44fe" -fs-extra@3.0.1: - version "3.0.1" - resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-3.0.1.tgz#3794f378c58b342ea7dbbb23095109c4b3b62291" - dependencies: - graceful-fs "^4.1.2" - jsonfile "^3.0.0" - universalify "^0.1.0" - fs-extra@^0.30.0: version "0.30.0" resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-0.30.0.tgz#f233ffcc08d4da7d432daa449776989db1df93f0" @@ -3039,11 +3029,19 @@ fs-extra@^0.30.0: path-is-absolute "^1.0.0" rimraf "^2.2.8" +fs-extra@3.0.1: + version "3.0.1" + resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-3.0.1.tgz#3794f378c58b342ea7dbbb23095109c4b3b62291" + dependencies: + graceful-fs "^4.1.2" + jsonfile "^3.0.0" + universalify "^0.1.0" + fs.realpath@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/fs.realpath/-/fs.realpath-1.0.0.tgz#1504ad2523158caa40db4a2787cb01411994ea4f" -fsevents@1.0.17, fsevents@^1.0.0: +fsevents@^1.0.0, fsevents@1.0.17: version "1.0.17" resolved "https://registry.yarnpkg.com/fsevents/-/fsevents-1.0.17.tgz#8537f3f12272678765b4fd6528c0f1f66f8f4558" dependencies: @@ -3292,7 +3290,7 @@ he@1.1.x: version "1.1.1" resolved "https://registry.yarnpkg.com/he/-/he-1.1.1.tgz#93410fd21b009735151f8868c2f271f3427e23fd" -history@4.6.3, history@^4.5.1, history@^4.6.0: +history@^4.5.1, history@^4.6.0, history@4.6.3: version "4.6.3" resolved "https://registry.yarnpkg.com/history/-/history-4.6.3.tgz#6d723a8712c581d6bef37e8c26f4aedc6eb86967" dependencies: @@ -3314,7 +3312,7 @@ hoek@2.x.x: version "2.16.3" resolved "https://registry.yarnpkg.com/hoek/-/hoek-2.16.3.tgz#20bb7403d3cea398e91dc4710a8ff1b8274a25ed" -hoist-non-react-statics@1.x.x, hoist-non-react-statics@^1.0.3, hoist-non-react-statics@^1.2.0: +hoist-non-react-statics@^1.0.3, hoist-non-react-statics@^1.2.0, hoist-non-react-statics@1.x.x: version "1.2.0" resolved "https://registry.yarnpkg.com/hoist-non-react-statics/-/hoist-non-react-statics-1.2.0.tgz#aa448cf0986d55cc40773b17174b7dd066cb7cfb" @@ -3352,7 +3350,7 @@ html-encoding-sniffer@^1.0.1: dependencies: whatwg-encoding "^1.0.1" -html-entities@1.2.1, html-entities@^1.2.0: +html-entities@^1.2.0, html-entities@1.2.1: version "1.2.1" resolved "https://registry.yarnpkg.com/html-entities/-/html-entities-1.2.1.tgz#0df29351f0721163515dfb9e5543e5f6eed5162f" @@ -3434,14 +3432,14 @@ hyphenate-style-name@^1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/hyphenate-style-name/-/hyphenate-style-name-1.0.2.tgz#31160a36930adaf1fc04c6074f7eb41465d4ec4b" -iconv-lite@0.4.13: - version "0.4.13" - resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.4.13.tgz#1f88aba4ab0b1508e8312acc39345f36e992e2f2" - iconv-lite@^0.4.17, iconv-lite@~0.4.13: version "0.4.17" resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.4.17.tgz#4fdaa3b38acbc2c031b045d0edcdfe1ecab18c8d" +iconv-lite@0.4.13: + version "0.4.13" + resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.4.13.tgz#1f88aba4ab0b1508e8312acc39345f36e992e2f2" + icss-replace-symbols@^1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/icss-replace-symbols/-/icss-replace-symbols-1.1.0.tgz#06ea6f83679a7749e386cfe1fe812ae5db223ded" @@ -3487,7 +3485,7 @@ inflight@^1.0.4: once "^1.3.0" wrappy "1" -inherits@2, inherits@2.0.3, inherits@^2.0.1, inherits@^2.0.3, inherits@~2.0.0, inherits@~2.0.1: +inherits@^2.0.1, inherits@^2.0.3, inherits@~2.0.0, inherits@~2.0.1, inherits@2, inherits@2.0.3: version "2.0.3" resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.3.tgz#633c2c83e3da42a502f52466022480f4208261de" @@ -3506,24 +3504,6 @@ inline-style-prefixer@^3.0.2: bowser "^1.6.0" css-in-js-utils "^1.0.3" -inquirer@3.0.6: - version "3.0.6" - resolved "https://registry.yarnpkg.com/inquirer/-/inquirer-3.0.6.tgz#e04aaa9d05b7a3cb9b0f407d04375f0447190347" - dependencies: - ansi-escapes "^1.1.0" - chalk "^1.0.0" - cli-cursor "^2.1.0" - cli-width "^2.0.0" - external-editor "^2.0.1" - figures "^2.0.0" - lodash "^4.3.0" - mute-stream "0.0.7" - run-async "^2.2.0" - rx "^4.1.0" - string-width "^2.0.0" - strip-ansi "^3.0.0" - through "^2.3.6" - inquirer@^0.12.0: version "0.12.0" resolved "https://registry.yarnpkg.com/inquirer/-/inquirer-0.12.0.tgz#1ef2bfd63504df0bc75785fff8c2c41df12f077e" @@ -3542,11 +3522,29 @@ inquirer@^0.12.0: strip-ansi "^3.0.0" through "^2.3.6" +inquirer@3.0.6: + version "3.0.6" + resolved "https://registry.yarnpkg.com/inquirer/-/inquirer-3.0.6.tgz#e04aaa9d05b7a3cb9b0f407d04375f0447190347" + dependencies: + ansi-escapes "^1.1.0" + chalk "^1.0.0" + cli-cursor "^2.1.0" + cli-width "^2.0.0" + external-editor "^2.0.1" + figures "^2.0.0" + lodash "^4.3.0" + mute-stream "0.0.7" + run-async "^2.2.0" + rx "^4.1.0" + string-width "^2.0.0" + strip-ansi "^3.0.0" + through "^2.3.6" + interpret@^1.0.0: version "1.0.3" resolved "https://registry.yarnpkg.com/interpret/-/interpret-1.0.3.tgz#cbc35c62eeee73f19ab7b10a801511401afc0f90" -invariant@2.x.x, invariant@^2.0.0, invariant@^2.2.0, invariant@^2.2.1, invariant@^2.2.2: +invariant@^2.0.0, invariant@^2.2.0, invariant@^2.2.1, invariant@^2.2.2, invariant@2.x.x: version "2.2.2" resolved "https://registry.yarnpkg.com/invariant/-/invariant-2.2.2.tgz#9e1f56ac0acdb6bf303306f338be3b204ae60360" dependencies: @@ -3771,14 +3769,14 @@ is-wsl@^1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/is-wsl/-/is-wsl-1.1.0.tgz#1f16e4aa22b04d1336b66188a66af3c600c3a66d" +isarray@^1.0.0, isarray@~1.0.0, isarray@1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/isarray/-/isarray-1.0.0.tgz#bb935d48582cba168c06834957a54a3e07124f11" + isarray@0.0.1: version "0.0.1" resolved "https://registry.yarnpkg.com/isarray/-/isarray-0.0.1.tgz#8a18acfca9a8f4177e09abfc6038939b05d1eedf" -isarray@1.0.0, isarray@^1.0.0, isarray@~1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/isarray/-/isarray-1.0.0.tgz#bb935d48582cba168c06834957a54a3e07124f11" - isexe@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/isexe/-/isexe-2.0.0.tgz#e8fbf374dc556ff8947a10dcb0572d633f2cfa10" @@ -4364,7 +4362,7 @@ lodash.isarguments@^3.0.0: version "3.1.0" resolved "https://registry.yarnpkg.com/lodash.isarguments/-/lodash.isarguments-3.1.0.tgz#2f573d85c6a24289ff00663b491c1d338ff3458a" -lodash.isarray@3.0.4, lodash.isarray@^3.0.0: +lodash.isarray@^3.0.0, lodash.isarray@3.0.4: version "3.0.4" resolved "https://registry.yarnpkg.com/lodash.isarray/-/lodash.isarray-3.0.4.tgz#79e4eb88c36a8122af86f844aa9bcd851b5fbb55" @@ -4435,7 +4433,7 @@ lodash.unset@^4.5.2: version "4.5.2" resolved "https://registry.yarnpkg.com/lodash.unset/-/lodash.unset-4.5.2.tgz#370d1d3e85b72a7e1b0cdf2d272121306f23e4ed" -lodash@4.x.x, "lodash@>=3.5 <5", lodash@^4.0.0, lodash@^4.14.0, lodash@^4.15.0, lodash@^4.16.2, lodash@^4.17.2, lodash@^4.17.3, lodash@^4.17.4, lodash@^4.2.0, lodash@^4.2.1, lodash@^4.3.0, lodash@~4.17.4: +lodash@^4.0.0, lodash@^4.14.0, lodash@^4.15.0, lodash@^4.16.2, lodash@^4.17.2, lodash@^4.17.3, lodash@^4.17.4, lodash@^4.2.0, lodash@^4.2.1, lodash@^4.3.0, "lodash@>=3.5 <5", lodash@~4.17.4, lodash@4.x.x: version "4.17.4" resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.4.tgz#78203a4d1c328ae1d86dca6460e369b57f4055ae" @@ -4584,14 +4582,14 @@ mime-types@^2.1.12, mime-types@~2.1.11, mime-types@~2.1.15, mime-types@~2.1.7: dependencies: mime-db "~1.27.0" +mime@^1.3.4, mime@1.3.x: + version "1.3.6" + resolved "https://registry.yarnpkg.com/mime/-/mime-1.3.6.tgz#591d84d3653a6b0b4a3b9df8de5aa8108e72e5e0" + mime@1.3.4: version "1.3.4" resolved "https://registry.yarnpkg.com/mime/-/mime-1.3.4.tgz#115f9e3b6b3daf2959983cb38f149a2d40eb5d53" -mime@1.3.x, mime@^1.3.4: - version "1.3.6" - resolved "https://registry.yarnpkg.com/mime/-/mime-1.3.6.tgz#591d84d3653a6b0b4a3b9df8de5aa8108e72e5e0" - mimic-fn@^1.0.0: version "1.1.0" resolved "https://registry.yarnpkg.com/mimic-fn/-/mimic-fn-1.1.0.tgz#e667783d92e89dbd342818b5230b9d62a672ad18" @@ -4610,27 +4608,27 @@ minimalistic-crypto-utils@^1.0.0, minimalistic-crypto-utils@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/minimalistic-crypto-utils/-/minimalistic-crypto-utils-1.0.1.tgz#f6c00c1c0b082246e5c4d99dfb8c7c083b2b582a" -minimatch@3.0.3: - version "3.0.3" - resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.0.3.tgz#2a4e4090b96b2db06a9d7df01055a62a77c9b774" - dependencies: - brace-expansion "^1.0.0" - minimatch@^3.0.0, minimatch@^3.0.2, minimatch@^3.0.3, minimatch@^3.0.4, minimatch@~3.0.2: version "3.0.4" resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.0.4.tgz#5166e286457f03306064be5497e8dbb0c3d32083" dependencies: brace-expansion "^1.1.7" -minimist@0.0.8, minimist@~0.0.1: - version "0.0.8" - resolved "https://registry.yarnpkg.com/minimist/-/minimist-0.0.8.tgz#857fcabfc3397d2625b8228262e86aa7a011b05d" +minimatch@3.0.3: + version "3.0.3" + resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.0.3.tgz#2a4e4090b96b2db06a9d7df01055a62a77c9b774" + dependencies: + brace-expansion "^1.0.0" minimist@^1.1.1, minimist@^1.1.3, minimist@^1.2.0: version "1.2.0" resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.0.tgz#a35008b20f41383eec1fb914f4cd5df79a264284" -mkdirp@0.5.1, mkdirp@0.5.x, "mkdirp@>=0.5 0", mkdirp@^0.5.0, mkdirp@^0.5.1, mkdirp@~0.5.0, mkdirp@~0.5.1: +minimist@~0.0.1, minimist@0.0.8: + version "0.0.8" + resolved "https://registry.yarnpkg.com/minimist/-/minimist-0.0.8.tgz#857fcabfc3397d2625b8228262e86aa7a011b05d" + +mkdirp@^0.5.0, mkdirp@^0.5.1, "mkdirp@>=0.5 0", mkdirp@~0.5.0, mkdirp@~0.5.1, mkdirp@0.5.1, mkdirp@0.5.x: version "0.5.1" resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-0.5.1.tgz#30057438eac6cf7f8c4767f38648d6697d75c903" dependencies: @@ -4810,12 +4808,6 @@ node-status-codes@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/node-status-codes/-/node-status-codes-1.0.0.tgz#5ae5541d024645d32a58fcddc9ceecea7ae3ac2f" -"nopt@2 || 3": - version "3.0.6" - resolved "https://registry.yarnpkg.com/nopt/-/nopt-3.0.6.tgz#c6465dbf08abcd4db359317f79ac68a646b28ff9" - dependencies: - abbrev "1" - nopt@^4.0.1: version "4.0.1" resolved "https://registry.yarnpkg.com/nopt/-/nopt-4.0.1.tgz#d0d4685afd5415193c8c7505602d0d17cd64474d" @@ -4823,6 +4815,12 @@ nopt@^4.0.1: abbrev "1" osenv "^0.1.4" +"nopt@2 || 3": + version "3.0.6" + resolved "https://registry.yarnpkg.com/nopt/-/nopt-3.0.6.tgz#c6465dbf08abcd4db359317f79ac68a646b28ff9" + dependencies: + abbrev "1" + normalize-package-data@^2.3.2, normalize-package-data@^2.3.4: version "2.3.8" resolved "https://registry.yarnpkg.com/normalize-package-data/-/normalize-package-data-2.3.8.tgz#d819eda2a9dedbd1ffa563ea4071d936782295bb" @@ -4863,7 +4861,7 @@ npm-run-all@^4.0.2: shell-quote "^1.6.1" string.prototype.padend "^3.0.0" -"npmlog@0 || 1 || 2 || 3 || 4", npmlog@^4.0.0, npmlog@^4.0.2: +npmlog@^4.0.0, npmlog@^4.0.2, "npmlog@0 || 1 || 2 || 3 || 4": version "4.1.0" resolved "https://registry.yarnpkg.com/npmlog/-/npmlog-4.1.0.tgz#dc59bee85f64f00ed424efb2af0783df25d1c0b5" dependencies: @@ -4894,14 +4892,14 @@ oauth-sign@~0.8.1: version "0.8.2" resolved "https://registry.yarnpkg.com/oauth-sign/-/oauth-sign-0.8.2.tgz#46a6ab7f0aead8deae9ec0565780b7d4efeb9d43" +object-assign@^4.0.1, object-assign@^4.1.0, object-assign@^4.1.1, object-assign@4.1.1: + version "4.1.1" + resolved "https://registry.yarnpkg.com/object-assign/-/object-assign-4.1.1.tgz#2109adc7965887cfc05cbbd442cac8bfbb360863" + object-assign@4.0.1: version "4.0.1" resolved "https://registry.yarnpkg.com/object-assign/-/object-assign-4.0.1.tgz#99504456c3598b5cad4fc59c26e8a9bb107fe0bd" -object-assign@4.1.1, object-assign@^4.0.1, object-assign@^4.1.0, object-assign@^4.1.1: - version "4.1.1" - resolved "https://registry.yarnpkg.com/object-assign/-/object-assign-4.1.1.tgz#2109adc7965887cfc05cbbd442cac8bfbb360863" - object-hash@^1.1.4: version "1.1.8" resolved "https://registry.yarnpkg.com/object-hash/-/object-hash-1.1.8.tgz#28a659cf987d96a4dabe7860289f3b5326c4a03c" @@ -5027,7 +5025,7 @@ os-tmpdir@^1.0.0, os-tmpdir@^1.0.1, os-tmpdir@~1.0.1: version "1.0.2" resolved "https://registry.yarnpkg.com/os-tmpdir/-/os-tmpdir-1.0.2.tgz#bbe67406c79aa85c5cfec766fe5734555dfa1274" -osenv@0, osenv@^0.1.0, osenv@^0.1.4: +osenv@^0.1.0, osenv@^0.1.4, osenv@0: version "0.1.4" resolved "https://registry.yarnpkg.com/osenv/-/osenv-0.1.4.tgz#42fe6d5953df06c8064be6f176c3d05aaaa34644" dependencies: @@ -5126,16 +5124,16 @@ path-parse@^1.0.5: version "1.0.5" resolved "https://registry.yarnpkg.com/path-parse/-/path-parse-1.0.5.tgz#3c1adf871ea9cd6c9431b6ea2bd74a0ff055c4c1" -path-to-regexp@0.1.7: - version "0.1.7" - resolved "https://registry.yarnpkg.com/path-to-regexp/-/path-to-regexp-0.1.7.tgz#df604178005f522f15eb4490e7247a1bfaa67f8c" - path-to-regexp@^1.0.1, path-to-regexp@^1.5.3: version "1.7.0" resolved "https://registry.yarnpkg.com/path-to-regexp/-/path-to-regexp-1.7.0.tgz#59fde0f435badacba103a84e9d3bc64e96b9937d" dependencies: isarray "0.0.1" +path-to-regexp@0.1.7: + version "0.1.7" + resolved "https://registry.yarnpkg.com/path-to-regexp/-/path-to-regexp-0.1.7.tgz#df604178005f522f15eb4490e7247a1bfaa67f8c" + path-type@^1.0.0: version "1.1.0" resolved "https://registry.yarnpkg.com/path-type/-/path-type-1.1.0.tgz#59c44f7ee491da704da415da5a4070ba4f8fe441" @@ -5286,7 +5284,7 @@ postcss-filter-plugins@^2.0.0: postcss "^5.0.4" uniqid "^4.0.0" -postcss-flexbugs-fixes@3.0.0, postcss-flexbugs-fixes@^3.0.0: +postcss-flexbugs-fixes@^3.0.0, postcss-flexbugs-fixes@3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/postcss-flexbugs-fixes/-/postcss-flexbugs-fixes-3.0.0.tgz#7b31cb6c27d0417a35a67914c295f83c403c7ed4" dependencies: @@ -5315,7 +5313,7 @@ postcss-load-plugins@^2.3.0: cosmiconfig "^2.1.1" object-assign "^4.1.0" -postcss-loader@2.0.5, postcss-loader@^2.0.5: +postcss-loader@^2.0.5, postcss-loader@2.0.5: version "2.0.5" resolved "https://registry.yarnpkg.com/postcss-loader/-/postcss-loader-2.0.5.tgz#c19d3e8b83eb1ac316f5621ef4c0ef5b3d1b8b3a" dependencies: @@ -5559,7 +5557,7 @@ progress@^1.1.8: version "1.1.8" resolved "https://registry.yarnpkg.com/progress/-/progress-1.1.8.tgz#e260c78f6161cdd9b0e56cc3e0a85de17c7a57be" -promise@7.1.1, promise@^7.1.1: +promise@^7.1.1, promise@7.1.1: version "7.1.1" resolved "https://registry.yarnpkg.com/promise/-/promise-7.1.1.tgz#489654c692616b8aa55b0724fa809bb7db49c5bf" dependencies: @@ -5603,34 +5601,34 @@ public-encrypt@^4.0.0: parse-asn1 "^5.0.0" randombytes "^2.0.1" -punycode@1.3.2: - version "1.3.2" - resolved "https://registry.yarnpkg.com/punycode/-/punycode-1.3.2.tgz#9653a036fb7c1ee42342f2325cceefea3926c48d" - punycode@^1.2.4, punycode@^1.4.1: version "1.4.1" resolved "https://registry.yarnpkg.com/punycode/-/punycode-1.4.1.tgz#c0d5a63b2718800ad8e1eb0fa5269c84dd41845e" +punycode@1.3.2: + version "1.3.2" + resolved "https://registry.yarnpkg.com/punycode/-/punycode-1.3.2.tgz#9653a036fb7c1ee42342f2325cceefea3926c48d" + q@^1.1.2: version "1.5.0" resolved "https://registry.yarnpkg.com/q/-/q-1.5.0.tgz#dd01bac9d06d30e6f219aecb8253ee9ebdc308f1" -qs@6.4.0, qs@^6.4.0, qs@~6.4.0: +qs@^6.4.0, qs@~6.4.0, qs@6.4.0: version "6.4.0" resolved "https://registry.yarnpkg.com/qs/-/qs-6.4.0.tgz#13e26d28ad6b0ffaa91312cd3bf708ed351e7233" -query-string@5.0.0: - version "5.0.0" - resolved "https://registry.yarnpkg.com/query-string/-/query-string-5.0.0.tgz#fbdf7004b4d2aff792f9871981b7a2794f555947" +query-string@^4.1.0: + version "4.3.4" + resolved "https://registry.yarnpkg.com/query-string/-/query-string-4.3.4.tgz#bbb693b9ca915c232515b228b1a02b609043dbeb" dependencies: - decode-uri-component "^0.2.0" object-assign "^4.1.0" strict-uri-encode "^1.0.0" -query-string@^4.1.0: - version "4.3.4" - resolved "https://registry.yarnpkg.com/query-string/-/query-string-4.3.4.tgz#bbb693b9ca915c232515b228b1a02b609043dbeb" +query-string@5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/query-string/-/query-string-5.0.0.tgz#fbdf7004b4d2aff792f9871981b7a2794f555947" dependencies: + decode-uri-component "^0.2.0" object-assign "^4.1.0" strict-uri-encode "^1.0.0" @@ -5638,18 +5636,18 @@ querystring-es3@^0.2.0: version "0.2.1" resolved "https://registry.yarnpkg.com/querystring-es3/-/querystring-es3-0.2.1.tgz#9ec61f79049875707d69414596fd907a4d711e73" -querystring@0.2.0, querystring@^0.2.0: +querystring@^0.2.0, querystring@0.2.0: version "0.2.0" resolved "https://registry.yarnpkg.com/querystring/-/querystring-0.2.0.tgz#b209849203bb25df820da756e747005878521620" -querystringify@0.0.x: - version "0.0.4" - resolved "https://registry.yarnpkg.com/querystringify/-/querystringify-0.0.4.tgz#0cf7f84f9463ff0ae51c4c4b142d95be37724d9c" - querystringify@~1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/querystringify/-/querystringify-1.0.0.tgz#6286242112c5b712fa654e526652bf6a13ff05cb" +querystringify@0.0.x: + version "0.0.4" + resolved "https://registry.yarnpkg.com/querystringify/-/querystringify-0.0.4.tgz#0cf7f84f9463ff0ae51c4c4b142d95be37724d9c" + raf@^3.1.0: version "3.3.2" resolved "https://registry.yarnpkg.com/raf/-/raf-3.3.2.tgz#0c13be0b5b49b46f76d6669248d527cf2b02fe27" @@ -6012,15 +6010,6 @@ read-pkg@^2.0.0: normalize-package-data "^2.3.2" path-type "^2.0.0" -readable-stream@1.0: - version "1.0.34" - resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-1.0.34.tgz#125820e34bc842d2f2aaafafe4c2916ee32c157c" - dependencies: - core-util-is "~1.0.0" - inherits "~2.0.1" - isarray "0.0.1" - string_decoder "~0.10.x" - readable-stream@^2.0.0, readable-stream@^2.0.1, readable-stream@^2.0.2, readable-stream@^2.0.5, readable-stream@^2.0.6, readable-stream@^2.1.4, readable-stream@^2.2.2, readable-stream@^2.2.6, readable-stream@^2.2.9: version "2.2.11" resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-2.2.11.tgz#0796b31f8d7688007ff0b93a8088d34aa17c0f72" @@ -6033,6 +6022,15 @@ readable-stream@^2.0.0, readable-stream@^2.0.1, readable-stream@^2.0.2, readable string_decoder "~1.0.0" util-deprecate "~1.0.1" +readable-stream@1.0: + version "1.0.34" + resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-1.0.34.tgz#125820e34bc842d2f2aaafafe4c2916ee32c157c" + dependencies: + core-util-is "~1.0.0" + inherits "~2.0.1" + isarray "0.0.1" + string_decoder "~0.10.x" + readdirp@^2.0.0: version "2.1.0" resolved "https://registry.yarnpkg.com/readdirp/-/readdirp-2.1.0.tgz#4ed0ad060df3073300c48440373f72d1cc642d78" @@ -6261,7 +6259,7 @@ repeating@^2.0.0: dependencies: is-finite "^1.0.0" -request@2, request@^2.79.0, request@^2.81.0: +request@^2.79.0, request@^2.81.0, request@2: version "2.81.0" resolved "https://registry.yarnpkg.com/request/-/request-2.81.0.tgz#c6928946a0e06c5f8d6f8a9333469ffda46298a0" dependencies: @@ -6323,16 +6321,16 @@ resolve-pathname@^2.0.0: version "2.1.0" resolved "https://registry.yarnpkg.com/resolve-pathname/-/resolve-pathname-2.1.0.tgz#e8358801b86b83b17560d4e3c382d7aef2100944" -resolve@1.1.7: - version "1.1.7" - resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.1.7.tgz#203114d82ad2c5ed9e8e0411b3932875e889e97b" - resolve@^1.1.6, resolve@^1.3.2: version "1.3.3" resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.3.3.tgz#655907c3469a8680dc2de3a275a8fdd69691f0e5" dependencies: path-parse "^1.0.5" +resolve@1.1.7: + version "1.1.7" + resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.1.7.tgz#203114d82ad2c5ed9e8e0411b3932875e889e97b" + restore-cursor@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/restore-cursor/-/restore-cursor-1.0.1.tgz#34661f46886327fed2991479152252df92daa541" @@ -6353,7 +6351,7 @@ right-align@^0.1.1: dependencies: align-text "^0.1.1" -rimraf@2, rimraf@^2.2.8, rimraf@^2.5.1, rimraf@^2.6.1: +rimraf@^2.2.8, rimraf@^2.5.1, rimraf@^2.6.1, rimraf@2: version "2.6.1" resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-2.6.1.tgz#c2338ec643df7a1b7fe5c54fa86f57428a55f33d" dependencies: @@ -6390,7 +6388,7 @@ rx@^4.1.0: version "4.1.0" resolved "https://registry.yarnpkg.com/rx/-/rx-4.1.0.tgz#a5f13ff79ef3b740fe30aa803fb09f98805d4782" -safe-buffer@5.0.1, safe-buffer@^5.0.1, safe-buffer@~5.0.1: +safe-buffer@^5.0.1, safe-buffer@~5.0.1, safe-buffer@5.0.1: version "5.0.1" resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.0.1.tgz#d263ca54696cd8a306b5ca6551e92de57918fbe7" @@ -6429,7 +6427,7 @@ sc-channel@~1.0.6: dependencies: sc-emitter "1.x.x" -sc-emitter@1.x.x, sc-emitter@~1.1.0: +sc-emitter@~1.1.0, sc-emitter@1.x.x: version "1.1.0" resolved "https://registry.yarnpkg.com/sc-emitter/-/sc-emitter-1.1.0.tgz#ef119d4222f4c64f887b486964ef11116cdd0e75" dependencies: @@ -6470,7 +6468,7 @@ semver-diff@^2.0.0: dependencies: semver "^5.0.3" -"semver@2 || 3 || 4 || 5", semver@^5.0.3, semver@^5.1.0, semver@^5.3.0, semver@~5.3.0: +semver@^5.0.3, semver@^5.1.0, semver@^5.3.0, semver@~5.3.0, "semver@2 || 3 || 4 || 5": version "5.3.0" resolved "https://registry.yarnpkg.com/semver/-/semver-5.3.0.tgz#9b2ce5d3de02d17c6012ad326aa6b4d0cf54f94f" @@ -6553,7 +6551,7 @@ sha.js@^2.4.0, sha.js@^2.4.8: dependencies: inherits "^2.0.1" -shallowequal@0.2.x, shallowequal@^0.2.2: +shallowequal@^0.2.2, shallowequal@0.2.x: version "0.2.2" resolved "https://registry.yarnpkg.com/shallowequal/-/shallowequal-0.2.2.tgz#1e32fd5bcab6ad688a4812cb0cc04efc75c7014e" dependencies: @@ -6569,7 +6567,7 @@ shebang-regex@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/shebang-regex/-/shebang-regex-1.0.0.tgz#da42f49740c0b42db2ca9728571cb190c98efea3" -shell-quote@1.6.1, shell-quote@^1.6.1: +shell-quote@^1.6.1, shell-quote@1.6.1: version "1.6.1" resolved "https://registry.yarnpkg.com/shell-quote/-/shell-quote-1.6.1.tgz#f4781949cce402697127430ea3b3c5476f481767" dependencies: @@ -6679,16 +6677,16 @@ source-map-support@^0.4.2: dependencies: source-map "^0.5.6" -source-map@0.5.6, source-map@0.5.x, source-map@^0.5.0, source-map@^0.5.3, source-map@^0.5.6, source-map@~0.5.0, source-map@~0.5.1, source-map@~0.5.3: - version "0.5.6" - resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.5.6.tgz#75ce38f52bf0733c5a7f0c118d81334a2bb5f412" - source-map@^0.4.2, source-map@^0.4.4: version "0.4.4" resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.4.4.tgz#eba4f5da9c0dc999de68032d8b4f76173652036b" dependencies: amdefine ">=0.0.4" +source-map@^0.5.0, source-map@^0.5.3, source-map@^0.5.6, source-map@~0.5.0, source-map@~0.5.1, source-map@~0.5.3, source-map@0.5.6, source-map@0.5.x: + version "0.5.6" + resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.5.6.tgz#75ce38f52bf0733c5a7f0c118d81334a2bb5f412" + source-map@~0.2.0: version "0.2.0" resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.2.0.tgz#dab73fbcfc2ba819b4de03bd6f6eaa48164b3f9d" @@ -6793,6 +6791,16 @@ strict-uri-encode@^1.0.0: version "1.1.0" resolved "https://registry.yarnpkg.com/strict-uri-encode/-/strict-uri-encode-1.1.0.tgz#279b225df1d582b1f54e65addd4352e18faa0713" +string_decoder@^0.10.25, string_decoder@~0.10.x: + version "0.10.31" + resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-0.10.31.tgz#62e203bc41766c6c28c9fc84301dab1c5310fa94" + +string_decoder@~1.0.0: + version "1.0.2" + resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-1.0.2.tgz#b29e1f4e1125fa97a10382b8a533737b7491e179" + dependencies: + safe-buffer "~5.0.1" + string-length@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/string-length/-/string-length-1.0.1.tgz#56970fb1c38558e9e70b728bf3de269ac45adfac" @@ -6830,36 +6838,26 @@ string.prototype.padstart@^3.0.0: es-abstract "^1.4.3" function-bind "^1.0.2" -string_decoder@^0.10.25, string_decoder@~0.10.x: - version "0.10.31" - resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-0.10.31.tgz#62e203bc41766c6c28c9fc84301dab1c5310fa94" - -string_decoder@~1.0.0: - version "1.0.2" - resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-1.0.2.tgz#b29e1f4e1125fa97a10382b8a533737b7491e179" - dependencies: - safe-buffer "~5.0.1" - stringstream@~0.0.4: version "0.0.5" resolved "https://registry.yarnpkg.com/stringstream/-/stringstream-0.0.5.tgz#4e484cd4de5a0bbbee18e46307710a8a81621878" -strip-ansi@3.0.1, strip-ansi@^3.0.0, strip-ansi@^3.0.1: +strip-ansi@^3.0.0, strip-ansi@^3.0.1, strip-ansi@3.0.1: version "3.0.1" resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-3.0.1.tgz#6a385fb8853d952d5ff05d0e8aaf94278dc63dcf" dependencies: ansi-regex "^2.0.0" -strip-bom@3.0.0, strip-bom@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/strip-bom/-/strip-bom-3.0.0.tgz#2334c18e9c759f7bdd56fdef7e9ae3d588e68ed3" - strip-bom@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/strip-bom/-/strip-bom-2.0.0.tgz#6219a85616520491f35788bdbf1447a99c7e6b0e" dependencies: is-utf8 "^0.2.0" +strip-bom@^3.0.0, strip-bom@3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/strip-bom/-/strip-bom-3.0.0.tgz#2334c18e9c759f7bdd56fdef7e9ae3d588e68ed3" + strip-indent@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/strip-indent/-/strip-indent-1.0.1.tgz#0c7962a6adefa7bbd4ac366460a638552ae1a0a2" @@ -6870,7 +6868,7 @@ strip-json-comments@~2.0.1: version "2.0.1" resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-2.0.1.tgz#3c531942e908c2697c0ec344858c286c7ca0a60a" -style-loader@0.17.0, style-loader@^0.17.0: +style-loader@^0.17.0, style-loader@0.17.0: version "0.17.0" resolved "https://registry.yarnpkg.com/style-loader/-/style-loader-0.17.0.tgz#e8254bccdb7af74bd58274e36107b4d5ab4df310" dependencies: @@ -6982,7 +6980,7 @@ test-exclude@^4.1.1: read-pkg-up "^1.0.1" require-main-filename "^1.0.1" -text-table@0.2.0, text-table@~0.2.0: +text-table@~0.2.0, text-table@0.2.0: version "0.2.0" resolved "https://registry.yarnpkg.com/text-table/-/text-table-0.2.0.tgz#7f5ee823ae805207c00af2df4a84ec3fcfa570b4" @@ -6990,7 +6988,7 @@ throat@^3.0.0: version "3.2.0" resolved "https://registry.yarnpkg.com/throat/-/throat-3.2.0.tgz#50cb0670edbc40237b9e347d7e1f88e4620af836" -through@2, through@^2.3.6, through@~2.3, through@~2.3.1: +through@^2.3.6, through@~2.3, through@~2.3.1, through@2: version "2.3.8" resolved "https://registry.yarnpkg.com/through/-/through-2.3.8.tgz#0dd4c9ffaabc357960b1b724115d7e0e86a2e1f5" @@ -7083,13 +7081,6 @@ ua-parser-js@^0.7.9: version "0.7.12" resolved "https://registry.yarnpkg.com/ua-parser-js/-/ua-parser-js-0.7.12.tgz#04c81a99bdd5dc52263ea29d24c6bf8d4818a4bb" -uglify-js@3.0.x: - version "3.0.15" - resolved "https://registry.yarnpkg.com/uglify-js/-/uglify-js-3.0.15.tgz#aacb323a846b234602270dead8a32441a8806f42" - dependencies: - commander "~2.9.0" - source-map "~0.5.1" - uglify-js@^2.6, uglify-js@^2.8.27, uglify-js@^2.8.5: version "2.8.28" resolved "https://registry.yarnpkg.com/uglify-js/-/uglify-js-2.8.28.tgz#e335032df9bb20dcb918f164589d5af47f38834a" @@ -7099,6 +7090,13 @@ uglify-js@^2.6, uglify-js@^2.8.27, uglify-js@^2.8.5: optionalDependencies: uglify-to-browserify "~1.0.0" +uglify-js@3.0.x: + version "3.0.15" + resolved "https://registry.yarnpkg.com/uglify-js/-/uglify-js-3.0.15.tgz#aacb323a846b234602270dead8a32441a8806f42" + dependencies: + commander "~2.9.0" + source-map "~0.5.1" + uglify-to-browserify@~1.0.0: version "1.0.2" resolved "https://registry.yarnpkg.com/uglify-to-browserify/-/uglify-to-browserify-1.0.2.tgz#6e0924d6bda6b5afe349e39a6d632850a0f882b7" @@ -7164,7 +7162,7 @@ urijs@^1.16.1: version "1.18.10" resolved "https://registry.yarnpkg.com/urijs/-/urijs-1.18.10.tgz#b94463eaba59a1a796036a467bb633c667f221ab" -url-loader@0.5.8, url-loader@^0.5.8: +url-loader@^0.5.8, url-loader@0.5.8: version "0.5.8" resolved "https://registry.yarnpkg.com/url-loader/-/url-loader-0.5.8.tgz#b9183b1801e0f847718673673040bc9dc1c715c5" dependencies: @@ -7177,13 +7175,6 @@ url-parse-lax@^1.0.0: dependencies: prepend-http "^1.0.1" -url-parse@1.0.x: - version "1.0.5" - resolved "https://registry.yarnpkg.com/url-parse/-/url-parse-1.0.5.tgz#0854860422afdcfefeb6c965c662d4800169927b" - dependencies: - querystringify "0.0.x" - requires-port "1.0.x" - url-parse@^1.1.1, url-parse@^1.1.8: version "1.1.9" resolved "https://registry.yarnpkg.com/url-parse/-/url-parse-1.1.9.tgz#c67f1d775d51f0a18911dd7b3ffad27bb9e5bd19" @@ -7191,6 +7182,13 @@ url-parse@^1.1.1, url-parse@^1.1.8: querystringify "~1.0.0" requires-port "1.0.x" +url-parse@1.0.x: + version "1.0.5" + resolved "https://registry.yarnpkg.com/url-parse/-/url-parse-1.0.5.tgz#0854860422afdcfefeb6c965c662d4800169927b" + dependencies: + querystringify "0.0.x" + requires-port "1.0.x" + url@^0.11.0: version "0.11.0" resolved "https://registry.yarnpkg.com/url/-/url-0.11.0.tgz#3838e97cfc60521eb73c525a8e55bfdd9e2e28f1" @@ -7208,7 +7206,7 @@ util-deprecate@^1.0.2, util-deprecate@~1.0.1: version "1.0.2" resolved "https://registry.yarnpkg.com/util-deprecate/-/util-deprecate-1.0.2.tgz#450d4dc9fa70de732762fbd2d4a28981419a0ccf" -util@0.10.3, util@^0.10.3: +util@^0.10.3, util@0.10.3: version "0.10.3" resolved "https://registry.yarnpkg.com/util/-/util-0.10.3.tgz#7afb1afe50805246489e3db7fe0ed379336ac0f9" dependencies: @@ -7364,7 +7362,7 @@ webpack-sources@^0.2.3: source-list-map "^1.1.1" source-map "~0.5.3" -webpack@2.6.1, webpack@^2.5.1: +webpack@^2.5.1, webpack@2.6.1: version "2.6.1" resolved "https://registry.yarnpkg.com/webpack/-/webpack-2.6.1.tgz#2e0457f0abb1ac5df3ab106c69c672f236785f07" dependencies: @@ -7406,7 +7404,7 @@ whatwg-encoding@^1.0.1: dependencies: iconv-lite "0.4.13" -whatwg-fetch@2.0.3, whatwg-fetch@>=0.10.0: +whatwg-fetch@>=0.10.0, whatwg-fetch@2.0.3: version "2.0.3" resolved "https://registry.yarnpkg.com/whatwg-fetch/-/whatwg-fetch-2.0.3.tgz#9c84ec2dcf68187ff00bc64e1274b442176e1c84" @@ -7425,7 +7423,7 @@ which-module@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/which-module/-/which-module-1.0.0.tgz#bba63ca861948994ff307736089e3b96026c2a4f" -which@1, which@^1.2.12, which@^1.2.9: +which@^1.2.12, which@^1.2.9, which@1: version "1.2.14" resolved "https://registry.yarnpkg.com/which/-/which-1.2.14.tgz#9a87c4378f03e827cecaf1acdf56c736c01c14e5" dependencies: @@ -7447,7 +7445,7 @@ window-size@0.1.0: version "0.1.0" resolved "https://registry.yarnpkg.com/window-size/-/window-size-0.1.0.tgz#5438cd2ea93b202efa3a19fe8887aee7c94f9c9d" -wordwrap@0.0.2, wordwrap@~0.0.2: +wordwrap@~0.0.2, wordwrap@0.0.2: version "0.0.2" resolved "https://registry.yarnpkg.com/wordwrap/-/wordwrap-0.0.2.tgz#b79669bb42ecb409f83d583cad52ca17eaa1643f" @@ -7520,7 +7518,7 @@ xml-name-validator@^2.0.1: version "2.0.1" resolved "https://registry.yarnpkg.com/xml-name-validator/-/xml-name-validator-2.0.1.tgz#4d8b8f1eccd3419aa362061becef515e1e559635" -"xtend@>=4.0.0 <4.1.0-0", xtend@^4.0.0: +xtend@^4.0.0, "xtend@>=4.0.0 <4.1.0-0": version "4.0.1" resolved "https://registry.yarnpkg.com/xtend/-/xtend-4.0.1.tgz#a5c6d532be656e23db820efb943a1f04998d63af" @@ -7588,3 +7586,4 @@ yargs@~3.10.0: cliui "^2.1.0" decamelize "^1.0.0" window-size "0.1.0" +