mirror of
https://github.com/bellingcat/datasheet-server.git
synced 2026-06-07 19:08:34 +03:00
new server test with precommit hook to secure .env files, set up CI environment (#5)
* new server test with precommit hook to secure .env files, set up CI environment (#3) * [TESTS] added all registered routes to api server test * [WIP] abstracting config to env where it makes sense, refactoring elsewhere, adding more tests * [WIP] fixed tests so they fail as expected * [WIP] * [DEBUG] fixed issues with the env configuration, added correct tests * [MISC] env didn't get readded on last precommit * [TESTS] added longer wait time for server as sometimtimes tests fail arbitrarily
This commit is contained in:
4
.env.example
Normal file
4
.env.example
Normal file
@@ -0,0 +1,4 @@
|
||||
PORT=4040
|
||||
MAPBOX_TOKEN=pk.ANOTHERLONGSTRING.pMXNkIn0.xjjmguLIeX-r8FWomVG8Tg
|
||||
SERVICE_ACCOUNT_EMAIL="DUMMY-SERVICE-WORKER-NAME@DUMMY-PROJECT-NAME.iam.gserviceaccount.com"
|
||||
SERVICE_ACCOUNT_PRIVATE_KEY="-----BEGIN PRIVATE KEY-----\A-vErY-l0nG-sTr1Ng\n-----END PRIVATE KEY-----\n"
|
||||
2
.gitignore
vendored
2
.gitignore
vendored
@@ -5,6 +5,8 @@
|
||||
.DS_Store
|
||||
*.swp
|
||||
|
||||
.env
|
||||
*service-account-key\.json
|
||||
src/config.js
|
||||
/yarn-error.log
|
||||
*.pem
|
||||
19
.travis.yml
19
.travis.yml
@@ -1,15 +1,18 @@
|
||||
language: node_js
|
||||
node_js:
|
||||
- "stable"
|
||||
- stable
|
||||
cache:
|
||||
directories:
|
||||
- node_modules
|
||||
- node_modules
|
||||
before_script:
|
||||
- npm install -g yarn
|
||||
- cp ./src/example.config.js ./src/config.js
|
||||
- npm install -g yarn
|
||||
- cp ./src/example.config.js ./src/config.js
|
||||
install:
|
||||
- yarn
|
||||
- yarn
|
||||
script:
|
||||
- yarn build
|
||||
- yarn lint
|
||||
- yarn test
|
||||
- yarn build
|
||||
- yarn lint
|
||||
- yarn test
|
||||
before_install:
|
||||
- openssl aes-256-cbc -K $encrypted_4f23b46f1ec6_key -iv $encrypted_4f23b46f1ec6_iv
|
||||
-in .env.enc -out .env -d
|
||||
|
||||
@@ -11,6 +11,11 @@
|
||||
"test-watch": "ava --watch",
|
||||
"test": "ava --verbose"
|
||||
},
|
||||
"husky": {
|
||||
"hooks": {
|
||||
"pre-commit": "yarn test && yarn lint && travis encrypt-file .env --add --force && git add ."
|
||||
}
|
||||
},
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "git+https://github.com/developit/express-es6-rest-api.git"
|
||||
@@ -21,6 +26,7 @@
|
||||
"body-parser": "^1.13.3",
|
||||
"compression": "^1.5.2",
|
||||
"cors": "^2.8.5",
|
||||
"dotenv": "^6.1.0",
|
||||
"express": "^4.13.3",
|
||||
"express-graphql": "^0.6.12",
|
||||
"googleapis": "^32.0.0",
|
||||
@@ -39,6 +45,7 @@
|
||||
"@babel/preset-env": "^7.1.0",
|
||||
"@babel/register": "^7.0.0",
|
||||
"ava": "1.0.0-beta.8",
|
||||
"husky": "^1.2.0",
|
||||
"nodemon": "1.18.7",
|
||||
"standard": "^12.0.1"
|
||||
},
|
||||
|
||||
@@ -15,6 +15,20 @@ export default ({ config, controller }) => {
|
||||
res.json(controller.blueprints())
|
||||
})
|
||||
|
||||
api.get('/update', (req, res) => {
|
||||
controller
|
||||
.update()
|
||||
.then(msg =>
|
||||
res.json({
|
||||
success: msg
|
||||
})
|
||||
)
|
||||
.catch(err =>
|
||||
res.status(404)
|
||||
.send({ error: err.message, err })
|
||||
)
|
||||
})
|
||||
|
||||
api.get('/:sheet/:tab/:resource/:frag', (req, res) => {
|
||||
const { sheet, tab, resource, frag } = req.params
|
||||
controller
|
||||
@@ -27,8 +41,9 @@ export default ({ config, controller }) => {
|
||||
})
|
||||
|
||||
api.get('/:sheet/:tab/:resource', (req, res) => {
|
||||
const { sheet, tab, resource } = req.params
|
||||
controller
|
||||
.retrieve(req.params.sheet, req.params.tab, req.params.resource)
|
||||
.retrieve(sheet, tab, resource)
|
||||
.then(data => res.json(data))
|
||||
.catch(err =>
|
||||
res.status(err.status || 404)
|
||||
@@ -36,30 +51,16 @@ export default ({ config, controller }) => {
|
||||
)
|
||||
})
|
||||
|
||||
api.get('/update', (req, res) => {
|
||||
controller
|
||||
.update()
|
||||
.then(msg =>
|
||||
res.json({
|
||||
success: msg
|
||||
})
|
||||
)
|
||||
.catch(err =>
|
||||
res.status(404)
|
||||
.send({ error: err.message })
|
||||
)
|
||||
})
|
||||
|
||||
// ERROR routes. Note that it is important that these come AFTER routes
|
||||
// like /update, so that the regex does not greedily match these routes.
|
||||
|
||||
api.get('/:sheet', (req, res) => {
|
||||
res.status(404)
|
||||
res.status(400)
|
||||
.send({ error: copy.errors.onlysheet })
|
||||
})
|
||||
|
||||
api.get('/:sheet/:tab', (req, res) => {
|
||||
res.status(404)
|
||||
res.status(400)
|
||||
.send({ error: copy.errors.onlyTab })
|
||||
})
|
||||
|
||||
|
||||
@@ -3,12 +3,10 @@ import BP from './lib/blueprinters'
|
||||
export default {
|
||||
port: 4040,
|
||||
googleSheets: {
|
||||
email: 'SOME_SERVICE_ACCOUNT_EMAIL',
|
||||
privateKey: 'SOME_SERVICE_ACCOUNT_PRIVATE_KEY',
|
||||
sheets: [
|
||||
{
|
||||
name: 'example',
|
||||
id: '1UC7DkCFeUXHfpUxUGruExwFbP4pqVBdJLOKfo6wDDGk',
|
||||
id: '15gb_aYJw7WSVZmtS0FZvcpGx1-kwKX3VHH8YV6La4hY',
|
||||
tabs: {
|
||||
export_events: [BP.deeprows, BP.rows],
|
||||
export_categories: [BP.groups, BP.rows],
|
||||
|
||||
@@ -3,7 +3,10 @@ import express from 'express'
|
||||
import initialize from './initialize'
|
||||
import middleware from './middleware'
|
||||
import api from './api'
|
||||
import config from './config'
|
||||
// import config from './sheets_config'
|
||||
import dotenv from 'dotenv'
|
||||
|
||||
dotenv.config()
|
||||
|
||||
let app = express()
|
||||
app.server = http.createServer(app)
|
||||
@@ -15,6 +18,8 @@ if (process.env.NODE_ENV === 'development') {
|
||||
app.use(cors())
|
||||
}
|
||||
|
||||
const config = process.env
|
||||
|
||||
initialize(controller => {
|
||||
app.use(
|
||||
middleware({
|
||||
@@ -30,7 +35,7 @@ initialize(controller => {
|
||||
})
|
||||
)
|
||||
|
||||
app.server.listen(process.env.PORT || config.port, () => {
|
||||
app.server.listen(process.env.PORT || 4040, () => {
|
||||
console.log(`Started on port ${app.server.address().port}`)
|
||||
})
|
||||
})
|
||||
|
||||
@@ -1,13 +1,13 @@
|
||||
import StoreJson from './models/StoreJson'
|
||||
import Fetcher from './lib/Fetcher'
|
||||
import Controller from './lib/Controller'
|
||||
import config from './config'
|
||||
import sheetsConfig from './sheets_config'
|
||||
|
||||
const { googleSheets } = config
|
||||
const { sheets, privateKey, email } = googleSheets
|
||||
const { googleSheets } = sheetsConfig
|
||||
const { sheets } = googleSheets
|
||||
|
||||
function authenticate (_fetcher) {
|
||||
return _fetcher.fetcher.authenticate(email, privateKey).then(msg => {
|
||||
return _fetcher.fetcher.authenticate(process.env.SERVICE_ACCOUNT_EMAIL, process.env.SERVICE_ACCOUNT_PRIVATE_KEY).then(msg => {
|
||||
console.log(msg)
|
||||
return true
|
||||
})
|
||||
@@ -24,7 +24,7 @@ export default callback => {
|
||||
Promise.all(fetchers.map(authenticate))
|
||||
.then(() => {
|
||||
console.log(`===================`)
|
||||
console.log(`grant access to: ${email}`)
|
||||
console.log(`grant access to: ${process.env.SERVICE_ACCOUNT_EMAIL}`)
|
||||
console.log(`===================`)
|
||||
|
||||
// NB: reformat fetchers as config for controller
|
||||
@@ -39,7 +39,7 @@ export default callback => {
|
||||
console.log(err)
|
||||
console.log(
|
||||
`ERROR: the server couldn't connect to all of the sheets you provided. Ensure you have granted access to ${
|
||||
email
|
||||
process.env.SERVICE_ACCOUNT_EMAIL
|
||||
} on ALL listed sheets.`
|
||||
)
|
||||
})
|
||||
|
||||
@@ -36,6 +36,7 @@ class Controller {
|
||||
retrieve (sheet, tab, resource) {
|
||||
if (this._sheetExists(sheet)) {
|
||||
const fetcher = this.fetchers[sheet]
|
||||
// console.log(fetcher);
|
||||
return fetcher.retrieve(tab, resource)
|
||||
} else {
|
||||
return Promise.reject(new Error(copy.errors.noResource(sheet)))
|
||||
|
||||
@@ -189,7 +189,7 @@ class Fetcher {
|
||||
|
||||
retrieveFrag (tab, resource, frag) {
|
||||
const title = fmtName(tab)
|
||||
const url = `${this.id}/${tab}/${resource}/${frag}`
|
||||
const url = `${this.sheetName}/${tab}/${resource}/${frag || ''}`
|
||||
return this.db.load(url, this.blueprints[title])
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
import { Router } from 'express'
|
||||
import { mapboxAccessToken } from '../config'
|
||||
import morgan from 'morgan'
|
||||
import mapbox from './mapbox'
|
||||
|
||||
@@ -10,8 +9,8 @@ export default ({ config, db }) => {
|
||||
/* logging middleware */
|
||||
routes.use(morgan('dev'))
|
||||
|
||||
if (mapboxAccessToken) {
|
||||
routes.get('/mapbox/:z/:y/:x', mapbox(mapboxAccessToken))
|
||||
if (process.env.MAPBOX_TOKEN) {
|
||||
routes.get('/mapbox/:z/:y/:x', mapbox(process.env.MAPBOX_TOKEN))
|
||||
}
|
||||
|
||||
return routes
|
||||
|
||||
19
src/sheets_config.js
Normal file
19
src/sheets_config.js
Normal file
@@ -0,0 +1,19 @@
|
||||
import BP from './lib/blueprinters'
|
||||
|
||||
export default {
|
||||
googleSheets: {
|
||||
sheets: [
|
||||
{
|
||||
name: 'example',
|
||||
id: '1UC7DkCFeUXHfpUxUGruExwFbP4pqVBdJLOKfo6wDDGk',
|
||||
tabs: {
|
||||
export_events: [BP.deeprows, BP.rows],
|
||||
export_categories: [BP.groups, BP.rows],
|
||||
export_sources: BP.ids,
|
||||
export_sites: BP.rows,
|
||||
export_tags: BP.tree
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
103
test/server_process.js
Normal file
103
test/server_process.js
Normal file
@@ -0,0 +1,103 @@
|
||||
var assert = require('assert');
|
||||
var child_process = require('child_process')
|
||||
var http = require('http');
|
||||
import test from 'ava'
|
||||
|
||||
const SERVER_LAUNCH_WAIT_TIME = 10 * 1000;
|
||||
|
||||
var server_proc = null;
|
||||
var server_exited = false;
|
||||
|
||||
test.before.cb(t => {
|
||||
console.log("launching server...")
|
||||
server_proc = child_process.spawn('yarn', ['dev'], {
|
||||
cwd: '.',
|
||||
stdio: 'ignore'
|
||||
});
|
||||
|
||||
server_proc.on('exit', function(code, signal) {
|
||||
server_exited = true;
|
||||
});
|
||||
|
||||
setTimeout(t.end, SERVER_LAUNCH_WAIT_TIME);
|
||||
});
|
||||
|
||||
test.after(function() {
|
||||
console.log("killing server...")
|
||||
server_proc.kill('SIGKILL');
|
||||
});
|
||||
|
||||
test('should launch', t => {
|
||||
t.false(server_exited);
|
||||
});
|
||||
|
||||
var passUrls = [
|
||||
// Express API registered routes:
|
||||
// /
|
||||
'/api/',
|
||||
// /blueprints
|
||||
'/api/blueprints',
|
||||
// /update
|
||||
'/api/update',
|
||||
// /:sheet/:tab/:resource
|
||||
'/api/example/export_events/rows',
|
||||
// /:sheet/:tab/:resource/:frag
|
||||
'/api/example/export_events/rows/1'
|
||||
];
|
||||
|
||||
var failUrls = [
|
||||
// /:sheet
|
||||
'/api/example',
|
||||
// /:sheet/:tab
|
||||
'/api/example/events'
|
||||
]
|
||||
|
||||
passUrls.forEach(function(url) {
|
||||
test.cb('should respond successfully to request for "' + url + '"', t => {
|
||||
http.get({
|
||||
hostname: 'localhost',
|
||||
port: 4040,
|
||||
path: url,
|
||||
agent: false
|
||||
}, function(res) {
|
||||
var result_data = '';
|
||||
|
||||
if(res.statusCode != 200) {
|
||||
t.fail('Server response was not 200.');
|
||||
} else {
|
||||
res.on('data', function(data) { result_data += data });
|
||||
|
||||
res.on('end', function() {
|
||||
if (result_data.length > 0) {
|
||||
t.pass();
|
||||
} else {
|
||||
t.fail("Server returned no data.");
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
t.end();
|
||||
})
|
||||
});
|
||||
});
|
||||
|
||||
failUrls.forEach(function(url) {
|
||||
test.cb('should fail to respond to request for "' + url + '"', t => {
|
||||
http.get({
|
||||
hostname: 'localhost',
|
||||
port: 4040,
|
||||
path: url,
|
||||
agent: false
|
||||
}, function(res) {
|
||||
var result_data = '';
|
||||
|
||||
if(res.statusCode < 400) {
|
||||
t.fail('Server response was not erroneous.');
|
||||
} else {
|
||||
t.pass();
|
||||
}
|
||||
|
||||
t.end();
|
||||
})
|
||||
});
|
||||
});
|
||||
173
yarn.lock
173
yarn.lock
@@ -996,16 +996,35 @@ call-signature@0.0.2:
|
||||
version "0.0.2"
|
||||
resolved "https://registry.yarnpkg.com/call-signature/-/call-signature-0.0.2.tgz#a84abc825a55ef4cb2b028bd74e205a65b9a4996"
|
||||
|
||||
caller-callsite@^2.0.0:
|
||||
version "2.0.0"
|
||||
resolved "https://registry.yarnpkg.com/caller-callsite/-/caller-callsite-2.0.0.tgz#847e0fce0a223750a9a027c54b33731ad3154134"
|
||||
integrity sha1-hH4PzgoiN1CpoCfFSzNzGtMVQTQ=
|
||||
dependencies:
|
||||
callsites "^2.0.0"
|
||||
|
||||
caller-path@^0.1.0:
|
||||
version "0.1.0"
|
||||
resolved "https://registry.yarnpkg.com/caller-path/-/caller-path-0.1.0.tgz#94085ef63581ecd3daa92444a8fe94e82577751f"
|
||||
dependencies:
|
||||
callsites "^0.2.0"
|
||||
|
||||
caller-path@^2.0.0:
|
||||
version "2.0.0"
|
||||
resolved "https://registry.yarnpkg.com/caller-path/-/caller-path-2.0.0.tgz#468f83044e369ab2010fac5f06ceee15bb2cb1f4"
|
||||
integrity sha1-Ro+DBE42mrIBD6xfBs7uFbsssfQ=
|
||||
dependencies:
|
||||
caller-callsite "^2.0.0"
|
||||
|
||||
callsites@^0.2.0:
|
||||
version "0.2.0"
|
||||
resolved "https://registry.yarnpkg.com/callsites/-/callsites-0.2.0.tgz#afab96262910a7f33c19a5775825c69f34e350ca"
|
||||
|
||||
callsites@^2.0.0:
|
||||
version "2.0.0"
|
||||
resolved "https://registry.yarnpkg.com/callsites/-/callsites-2.0.0.tgz#06eb84f00eea413da86affefacbffb36093b3c50"
|
||||
integrity sha1-BuuE8A7qQT2oav/vrL/7Ngk7PFA=
|
||||
|
||||
camelcase-keys@^4.0.0:
|
||||
version "4.2.0"
|
||||
resolved "https://registry.yarnpkg.com/camelcase-keys/-/camelcase-keys-4.2.0.tgz#a2aa5fb1af688758259c32c141426d78923b9b77"
|
||||
@@ -1274,6 +1293,16 @@ cors@^2.8.5:
|
||||
object-assign "^4"
|
||||
vary "^1"
|
||||
|
||||
cosmiconfig@^5.0.6:
|
||||
version "5.0.7"
|
||||
resolved "https://registry.yarnpkg.com/cosmiconfig/-/cosmiconfig-5.0.7.tgz#39826b292ee0d78eda137dfa3173bd1c21a43b04"
|
||||
integrity sha512-PcLqxTKiDmNT6pSpy4N6KtuPwb53W+2tzNvwOZw0WH9N6O0vLIBq0x8aj8Oj75ere4YcGi48bDFCL+3fRJdlNA==
|
||||
dependencies:
|
||||
import-fresh "^2.0.0"
|
||||
is-directory "^0.3.1"
|
||||
js-yaml "^3.9.0"
|
||||
parse-json "^4.0.0"
|
||||
|
||||
create-error-class@^3.0.0:
|
||||
version "3.0.2"
|
||||
resolved "https://registry.yarnpkg.com/create-error-class/-/create-error-class-3.0.2.tgz#06be7abef947a3f14a30fd610671d401bca8b7b6"
|
||||
@@ -1288,7 +1317,7 @@ cross-spawn@^5.0.1:
|
||||
shebang-command "^1.2.0"
|
||||
which "^1.2.9"
|
||||
|
||||
cross-spawn@^6.0.5:
|
||||
cross-spawn@^6.0.0, cross-spawn@^6.0.5:
|
||||
version "6.0.5"
|
||||
resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-6.0.5.tgz#4a5ec7c64dfae22c3a14124dbacdee846d80cbc4"
|
||||
dependencies:
|
||||
@@ -1470,6 +1499,11 @@ dot-prop@^4.1.0, dot-prop@^4.2.0:
|
||||
dependencies:
|
||||
is-obj "^1.0.0"
|
||||
|
||||
dotenv@^6.1.0:
|
||||
version "6.1.0"
|
||||
resolved "https://registry.yarnpkg.com/dotenv/-/dotenv-6.1.0.tgz#9853b6ca98292acb7dec67a95018fa40bccff42c"
|
||||
integrity sha512-/veDn2ztgRlB7gKmE3i9f6CmDIyXAy6d5nBq+whO9SLX+Zs1sXEgFLPi+aSuWqUuusMfbi84fT8j34fs1HaYUw==
|
||||
|
||||
duplexer3@^0.1.4:
|
||||
version "0.1.4"
|
||||
resolved "https://registry.yarnpkg.com/duplexer3/-/duplexer3-0.1.4.tgz#ee01dd1cac0ed3cbc7fdbea37dc0a8f1ce002ce2"
|
||||
@@ -1503,6 +1537,13 @@ encodeurl@~1.0.2:
|
||||
version "1.0.2"
|
||||
resolved "https://registry.yarnpkg.com/encodeurl/-/encodeurl-1.0.2.tgz#ad3ff4c86ec2d029322f5a02c3a9a606c95b3f59"
|
||||
|
||||
end-of-stream@^1.1.0:
|
||||
version "1.4.1"
|
||||
resolved "https://registry.yarnpkg.com/end-of-stream/-/end-of-stream-1.4.1.tgz#ed29634d19baba463b6ce6b80a37213eab71ec43"
|
||||
integrity sha512-1MkrZNvWTKCaigbn+W15elq2BB/L22nqrSY5DKlo3X6+vclJm8Bb5djXJBmEX6fS3+zCh/F4VBK5Z2KxJt4s2Q==
|
||||
dependencies:
|
||||
once "^1.4.0"
|
||||
|
||||
equal-length@^1.0.0:
|
||||
version "1.0.1"
|
||||
resolved "https://registry.yarnpkg.com/equal-length/-/equal-length-1.0.1.tgz#21ca112d48ab24b4e1e7ffc0e5339d31fdfc274c"
|
||||
@@ -1741,6 +1782,19 @@ execa@^0.7.0:
|
||||
signal-exit "^3.0.0"
|
||||
strip-eof "^1.0.0"
|
||||
|
||||
execa@^1.0.0:
|
||||
version "1.0.0"
|
||||
resolved "https://registry.yarnpkg.com/execa/-/execa-1.0.0.tgz#c6236a5bb4df6d6f15e88e7f017798216749ddd8"
|
||||
integrity sha512-adbxcyWV46qiHyvSp50TKt05tB4tK3HcmF7/nxfAdhnox83seTDbwnaqKO4sXRy7roHAIFqJP/Rw/AuEbX61LA==
|
||||
dependencies:
|
||||
cross-spawn "^6.0.0"
|
||||
get-stream "^4.0.0"
|
||||
is-stream "^1.1.0"
|
||||
npm-run-path "^2.0.0"
|
||||
p-finally "^1.0.0"
|
||||
signal-exit "^3.0.0"
|
||||
strip-eof "^1.0.0"
|
||||
|
||||
expand-brackets@^2.1.4:
|
||||
version "2.1.4"
|
||||
resolved "https://registry.yarnpkg.com/expand-brackets/-/expand-brackets-2.1.4.tgz#b77735e315ce30f6b6eff0f83b04151a22449622"
|
||||
@@ -1910,6 +1964,13 @@ find-up@^2.0.0, find-up@^2.1.0:
|
||||
dependencies:
|
||||
locate-path "^2.0.0"
|
||||
|
||||
find-up@^3.0.0:
|
||||
version "3.0.0"
|
||||
resolved "https://registry.yarnpkg.com/find-up/-/find-up-3.0.0.tgz#49169f1d7993430646da61ecc5ae355c21c97b73"
|
||||
integrity sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==
|
||||
dependencies:
|
||||
locate-path "^3.0.0"
|
||||
|
||||
flat-cache@^1.2.1:
|
||||
version "1.3.0"
|
||||
resolved "https://registry.yarnpkg.com/flat-cache/-/flat-cache-1.3.0.tgz#d3030b32b38154f4e3b7e9c709f490f7ef97c481"
|
||||
@@ -2009,6 +2070,13 @@ get-stream@^3.0.0:
|
||||
version "3.0.0"
|
||||
resolved "http://registry.npmjs.org/get-stream/-/get-stream-3.0.0.tgz#8e943d1358dc37555054ecbe2edb05aa174ede14"
|
||||
|
||||
get-stream@^4.0.0:
|
||||
version "4.1.0"
|
||||
resolved "https://registry.yarnpkg.com/get-stream/-/get-stream-4.1.0.tgz#c1b255575f3dc21d59bfc79cd3d2b46b1c3a54b5"
|
||||
integrity sha512-GMat4EJ5161kIy2HevLlr4luNjBgvmj413KaQA7jt4V8B4RDsfpHk7WQ9GVqfYyyx8OS/L66Kox+rJRNklLK7w==
|
||||
dependencies:
|
||||
pump "^3.0.0"
|
||||
|
||||
get-value@^2.0.3, get-value@^2.0.6:
|
||||
version "2.0.6"
|
||||
resolved "https://registry.yarnpkg.com/get-value/-/get-value-2.0.6.tgz#dc15ca1c672387ca76bd37ac0a395ba2042a2c28"
|
||||
@@ -2226,6 +2294,22 @@ http-errors@^1.3.0:
|
||||
statuses ">= 1.5.0 < 2"
|
||||
toidentifier "1.0.0"
|
||||
|
||||
husky@^1.2.0:
|
||||
version "1.2.0"
|
||||
resolved "https://registry.yarnpkg.com/husky/-/husky-1.2.0.tgz#d631dda1e4a9ee8ba69a10b0c51a0e2c66e711e5"
|
||||
integrity sha512-/ib3+iycykXC0tYIxsyqierikVa9DA2DrT32UEirqNEFVqOj1bFMTgP3jAz8HM7FgC/C8pc/BTUa9MV2GEkZaA==
|
||||
dependencies:
|
||||
cosmiconfig "^5.0.6"
|
||||
execa "^1.0.0"
|
||||
find-up "^3.0.0"
|
||||
get-stdin "^6.0.0"
|
||||
is-ci "^1.2.1"
|
||||
pkg-dir "^3.0.0"
|
||||
please-upgrade-node "^3.1.1"
|
||||
read-pkg "^4.0.1"
|
||||
run-node "^1.0.0"
|
||||
slash "^2.0.0"
|
||||
|
||||
iconv-lite@0.4.23:
|
||||
version "0.4.23"
|
||||
resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.4.23.tgz#297871f63be507adcfbfca715d0cd0eed84e9a63"
|
||||
@@ -2256,6 +2340,14 @@ ignore@^4.0.2:
|
||||
version "4.0.6"
|
||||
resolved "https://registry.yarnpkg.com/ignore/-/ignore-4.0.6.tgz#750e3db5862087b4737ebac8207ffd1ef27b25fc"
|
||||
|
||||
import-fresh@^2.0.0:
|
||||
version "2.0.0"
|
||||
resolved "https://registry.yarnpkg.com/import-fresh/-/import-fresh-2.0.0.tgz#d81355c15612d386c61f9ddd3922d4304822a546"
|
||||
integrity sha1-2BNVwVYS04bGH53dOSLUMEgipUY=
|
||||
dependencies:
|
||||
caller-path "^2.0.0"
|
||||
resolve-from "^3.0.0"
|
||||
|
||||
import-lazy@^2.1.0:
|
||||
version "2.1.0"
|
||||
resolved "https://registry.yarnpkg.com/import-lazy/-/import-lazy-2.1.0.tgz#05698e3d45c88e8d7e9d92cb0584e77f096f3e43"
|
||||
@@ -2358,7 +2450,7 @@ is-callable@^1.1.3, is-callable@^1.1.4:
|
||||
version "1.1.4"
|
||||
resolved "https://registry.yarnpkg.com/is-callable/-/is-callable-1.1.4.tgz#1e1adf219e1eeb684d691f9d6a05ff0d30a24d75"
|
||||
|
||||
is-ci@^1.0.10, is-ci@^1.2.0:
|
||||
is-ci@^1.0.10, is-ci@^1.2.0, is-ci@^1.2.1:
|
||||
version "1.2.1"
|
||||
resolved "https://registry.yarnpkg.com/is-ci/-/is-ci-1.2.1.tgz#e3779c8ee17fccf428488f6e281187f2e632841c"
|
||||
dependencies:
|
||||
@@ -2396,6 +2488,11 @@ is-descriptor@^1.0.0, is-descriptor@^1.0.2:
|
||||
is-data-descriptor "^1.0.0"
|
||||
kind-of "^6.0.2"
|
||||
|
||||
is-directory@^0.3.1:
|
||||
version "0.3.1"
|
||||
resolved "https://registry.yarnpkg.com/is-directory/-/is-directory-0.3.1.tgz#61339b6f2475fc772fd9c9d83f5c8575dc154ae1"
|
||||
integrity sha1-YTObbyR1/Hcv2cnYP1yFddwVSuE=
|
||||
|
||||
is-error@^2.2.1:
|
||||
version "2.2.1"
|
||||
resolved "https://registry.yarnpkg.com/is-error/-/is-error-2.2.1.tgz#684a96d84076577c98f4cdb40c6d26a5123bf19c"
|
||||
@@ -2577,7 +2674,7 @@ js-tokens@^3.0.2:
|
||||
version "3.0.2"
|
||||
resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-3.0.2.tgz#9866df395102130e38f7f996bceb65443209c25b"
|
||||
|
||||
js-yaml@^3.10.0, js-yaml@^3.11.0:
|
||||
js-yaml@^3.10.0, js-yaml@^3.11.0, js-yaml@^3.9.0:
|
||||
version "3.12.0"
|
||||
resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-3.12.0.tgz#eaed656ec8344f10f527c6bfa1b6e2244de167d1"
|
||||
dependencies:
|
||||
@@ -2687,6 +2784,14 @@ locate-path@^2.0.0:
|
||||
p-locate "^2.0.0"
|
||||
path-exists "^3.0.0"
|
||||
|
||||
locate-path@^3.0.0:
|
||||
version "3.0.0"
|
||||
resolved "https://registry.yarnpkg.com/locate-path/-/locate-path-3.0.0.tgz#dbec3b3ab759758071b58fe59fc41871af21400e"
|
||||
integrity sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==
|
||||
dependencies:
|
||||
p-locate "^3.0.0"
|
||||
path-exists "^3.0.0"
|
||||
|
||||
lodash.clone@^4.5.0:
|
||||
version "4.5.0"
|
||||
resolved "https://registry.yarnpkg.com/lodash.clone/-/lodash.clone-4.5.0.tgz#195870450f5a13192478df4bc3d23d2dea1907b6"
|
||||
@@ -3145,7 +3250,7 @@ on-headers@~1.0.1:
|
||||
version "1.0.1"
|
||||
resolved "https://registry.yarnpkg.com/on-headers/-/on-headers-1.0.1.tgz#928f5d0f470d49342651ea6794b0857c100693f7"
|
||||
|
||||
once@^1.3.0:
|
||||
once@^1.3.0, once@^1.3.1, once@^1.4.0:
|
||||
version "1.4.0"
|
||||
resolved "https://registry.yarnpkg.com/once/-/once-1.4.0.tgz#583b1aa775961d4b113ac17d9c50baef9dd76bd1"
|
||||
dependencies:
|
||||
@@ -3212,12 +3317,26 @@ p-limit@^1.1.0:
|
||||
dependencies:
|
||||
p-try "^1.0.0"
|
||||
|
||||
p-limit@^2.0.0:
|
||||
version "2.0.0"
|
||||
resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-2.0.0.tgz#e624ed54ee8c460a778b3c9f3670496ff8a57aec"
|
||||
integrity sha512-fl5s52lI5ahKCernzzIyAP0QAZbGIovtVHGwpcu1Jr/EpzLVDI2myISHwGqK7m8uQFugVWSrbxH7XnhGtvEc+A==
|
||||
dependencies:
|
||||
p-try "^2.0.0"
|
||||
|
||||
p-locate@^2.0.0:
|
||||
version "2.0.0"
|
||||
resolved "https://registry.yarnpkg.com/p-locate/-/p-locate-2.0.0.tgz#20a0103b222a70c8fd39cc2e580680f3dde5ec43"
|
||||
dependencies:
|
||||
p-limit "^1.1.0"
|
||||
|
||||
p-locate@^3.0.0:
|
||||
version "3.0.0"
|
||||
resolved "https://registry.yarnpkg.com/p-locate/-/p-locate-3.0.0.tgz#322d69a05c0264b25997d9f40cd8a891ab0064a4"
|
||||
integrity sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ==
|
||||
dependencies:
|
||||
p-limit "^2.0.0"
|
||||
|
||||
p-map@^1.1.1:
|
||||
version "1.2.0"
|
||||
resolved "https://registry.yarnpkg.com/p-map/-/p-map-1.2.0.tgz#e4e94f311eabbc8633a1e79908165fca26241b6b"
|
||||
@@ -3226,6 +3345,11 @@ p-try@^1.0.0:
|
||||
version "1.0.0"
|
||||
resolved "https://registry.yarnpkg.com/p-try/-/p-try-1.0.0.tgz#cbc79cdbaf8fd4228e13f621f2b1a237c1b207b3"
|
||||
|
||||
p-try@^2.0.0:
|
||||
version "2.0.0"
|
||||
resolved "https://registry.yarnpkg.com/p-try/-/p-try-2.0.0.tgz#85080bb87c64688fa47996fe8f7dfbe8211760b1"
|
||||
integrity sha512-hMp0onDKIajHfIkdRk3P4CdCmErkYAxxDtP3Wx/4nZ3aGlau2VKh3mZpcuFkH27WQkL/3WBCPOktzA9ZOAnMQQ==
|
||||
|
||||
package-hash@^2.0.0:
|
||||
version "2.0.0"
|
||||
resolved "https://registry.yarnpkg.com/package-hash/-/package-hash-2.0.0.tgz#78ae326c89e05a4d813b68601977af05c00d2a0d"
|
||||
@@ -3370,6 +3494,20 @@ pkg-dir@^2.0.0:
|
||||
dependencies:
|
||||
find-up "^2.1.0"
|
||||
|
||||
pkg-dir@^3.0.0:
|
||||
version "3.0.0"
|
||||
resolved "https://registry.yarnpkg.com/pkg-dir/-/pkg-dir-3.0.0.tgz#2749020f239ed990881b1f71210d51eb6523bea3"
|
||||
integrity sha512-/E57AYkoeQ25qkxMj5PBOVgF8Kiu/h7cYS30Z5+R7WaiCCBfLq58ZI/dSeaEKb9WVJV5n/03QwrN3IeWIFllvw==
|
||||
dependencies:
|
||||
find-up "^3.0.0"
|
||||
|
||||
please-upgrade-node@^3.1.1:
|
||||
version "3.1.1"
|
||||
resolved "https://registry.yarnpkg.com/please-upgrade-node/-/please-upgrade-node-3.1.1.tgz#ed320051dfcc5024fae696712c8288993595e8ac"
|
||||
integrity sha512-KY1uHnQ2NlQHqIJQpnh/i54rKkuxCEBx+voJIS/Mvb+L2iYd2NMotwduhKTMjfC1uKoX3VXOxLjIYG66dfJTVQ==
|
||||
dependencies:
|
||||
semver-compare "^1.0.0"
|
||||
|
||||
plur@^3.0.1:
|
||||
version "3.0.1"
|
||||
resolved "https://registry.yarnpkg.com/plur/-/plur-3.0.1.tgz#268652d605f816699b42b86248de73c9acd06a7c"
|
||||
@@ -3433,6 +3571,14 @@ pstree.remy@^1.1.2:
|
||||
resolved "https://registry.yarnpkg.com/pstree.remy/-/pstree.remy-1.1.2.tgz#4448bbeb4b2af1fed242afc8dc7416a6f504951a"
|
||||
integrity sha512-vL6NLxNHzkNTjGJUpMm5PLC+94/0tTlC1vkP9bdU0pOHih+EujMjgMTwfZopZvHWRFbqJ5Y73OMoau50PewDDA==
|
||||
|
||||
pump@^3.0.0:
|
||||
version "3.0.0"
|
||||
resolved "https://registry.yarnpkg.com/pump/-/pump-3.0.0.tgz#b4a2116815bde2f4e1ea602354e8c75565107a64"
|
||||
integrity sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==
|
||||
dependencies:
|
||||
end-of-stream "^1.1.0"
|
||||
once "^1.3.1"
|
||||
|
||||
punycode@^2.1.0:
|
||||
version "2.1.1"
|
||||
resolved "https://registry.yarnpkg.com/punycode/-/punycode-2.1.1.tgz#b58b010ac40c22c5657616c8d2c2c02c7bf479ec"
|
||||
@@ -3501,6 +3647,15 @@ read-pkg@^3.0.0:
|
||||
normalize-package-data "^2.3.2"
|
||||
path-type "^3.0.0"
|
||||
|
||||
read-pkg@^4.0.1:
|
||||
version "4.0.1"
|
||||
resolved "https://registry.yarnpkg.com/read-pkg/-/read-pkg-4.0.1.tgz#963625378f3e1c4d48c85872b5a6ec7d5d093237"
|
||||
integrity sha1-ljYlN48+HE1IyFhytabsfV0JMjc=
|
||||
dependencies:
|
||||
normalize-package-data "^2.3.2"
|
||||
parse-json "^4.0.0"
|
||||
pify "^3.0.0"
|
||||
|
||||
readable-stream@^2.0.2, readable-stream@^2.0.6:
|
||||
version "2.3.6"
|
||||
resolved "http://registry.npmjs.org/readable-stream/-/readable-stream-2.3.6.tgz#b11c27d88b8ff1fbe070643cf94b0c79ae1b0aaf"
|
||||
@@ -3677,6 +3832,11 @@ run-async@^2.2.0:
|
||||
dependencies:
|
||||
is-promise "^2.1.0"
|
||||
|
||||
run-node@^1.0.0:
|
||||
version "1.0.0"
|
||||
resolved "https://registry.yarnpkg.com/run-node/-/run-node-1.0.0.tgz#46b50b946a2aa2d4947ae1d886e9856fd9cabe5e"
|
||||
integrity sha512-kc120TBlQ3mih1LSzdAJXo4xn/GWS2ec0l3S+syHDXP9uRr0JAT8Qd3mdMuyjqCzeZktgP3try92cEgf9Nks8A==
|
||||
|
||||
run-parallel@^1.1.2:
|
||||
version "1.1.9"
|
||||
resolved "https://registry.yarnpkg.com/run-parallel/-/run-parallel-1.1.9.tgz#c9dd3a7cf9f4b2c4b6244e173a6ed866e61dd679"
|
||||
@@ -3705,6 +3865,11 @@ sax@^1.2.4:
|
||||
version "1.2.4"
|
||||
resolved "https://registry.yarnpkg.com/sax/-/sax-1.2.4.tgz#2816234e2378bddc4e5354fab5caa895df7100d9"
|
||||
|
||||
semver-compare@^1.0.0:
|
||||
version "1.0.0"
|
||||
resolved "https://registry.yarnpkg.com/semver-compare/-/semver-compare-1.0.0.tgz#0dee216a1c941ab37e9efb1788f6afc5ff5537fc"
|
||||
integrity sha1-De4hahyUGrN+nvsXiPavxf9VN/w=
|
||||
|
||||
semver-diff@^2.0.0:
|
||||
version "2.1.0"
|
||||
resolved "https://registry.yarnpkg.com/semver-diff/-/semver-diff-2.1.0.tgz#4bbb8437c8d37e4b0cf1a68fd726ec6d645d6d36"
|
||||
|
||||
Reference in New Issue
Block a user