diff --git a/api/v1/resources/authors.js b/api/v1/resources/authors.js index 945ddd7..7395960 100644 --- a/api/v1/resources/authors.js +++ b/api/v1/resources/authors.js @@ -21,7 +21,13 @@ module.exports = { responseMessages: ResponseMessages } }, - validate: Schema.authors, + validate: { + params: Schema.authors.params, + failAction: (request, h, err) => { + throw err; + return; + } + }, notes: [ 'This route fetches authors starting with the provided letters.' ] diff --git a/api/v1/resources/families.js b/api/v1/resources/families.js index a6cde89..9fc1763 100644 --- a/api/v1/resources/families.js +++ b/api/v1/resources/families.js @@ -20,7 +20,13 @@ module.exports = { responseMessages: ResponseMessages } }, - validate: Schema.families, + validate: { + params: Schema.families.params, + failAction: (request, h, err) => { + throw err; + return; + } + }, notes: [ 'This route fetches the families starting with the provided letters.' ] diff --git a/api/v1/resources/files.js b/api/v1/resources/files.js index ba1d369..f908edd 100644 --- a/api/v1/resources/files.js +++ b/api/v1/resources/files.js @@ -42,7 +42,14 @@ module.exports = { responseMessages: ResponseMessages } }, - validate: Schema.files, + validate: { + params: Schema.files.params, + query: Schema.files.query, + failAction: (request, h, err) => { + throw err; + return; + } + }, notes: [ 'Files inside Zenodo records', ] diff --git a/api/v1/resources/keywords.js b/api/v1/resources/keywords.js index bcfcf4d..24bc0f8 100644 --- a/api/v1/resources/keywords.js +++ b/api/v1/resources/keywords.js @@ -20,7 +20,13 @@ module.exports = { responseMessages: ResponseMessages } }, - validate: Schema.keywords, + validate: { + params: Schema.keywords.params, + failAction: (request, h, err) => { + throw err; + return; + } + }, notes: [ 'This route fetches the keywords starting with the provided letters.' ] diff --git a/api/v1/resources/record.js b/api/v1/resources/record.js index b6f402c..32c05ed 100644 --- a/api/v1/resources/record.js +++ b/api/v1/resources/record.js @@ -49,7 +49,14 @@ module.exports = { responseMessages: ResponseMessages } }, - validate: Schema.record, + validate: { + params: Schema.record.params, + query: Schema.record.query, + failAction: (request, h, err) => { + throw err; + return; + } + }, notes: [ 'This is the main route for fetching a record matching an id or a set of records matching the provided query parameters.' ] diff --git a/api/v1/resources/records.js b/api/v1/resources/records.js index 66a1094..27531bd 100644 --- a/api/v1/resources/records.js +++ b/api/v1/resources/records.js @@ -250,7 +250,14 @@ module.exports = { responseMessages: ResponseMessages } }, - validate: Schema.records, + validate: { + params: Schema.records.params, + query: Schema.records.query, + failAction: (request, h, err) => { + throw err; + return; + } + }, notes: [ 'This is the main route for fetching records matching the provided query parameters.' ] diff --git a/api/v1/resources/taxa.js b/api/v1/resources/taxa.js index e117695..b87ffd5 100644 --- a/api/v1/resources/taxa.js +++ b/api/v1/resources/taxa.js @@ -20,7 +20,13 @@ module.exports = { responseMessages: ResponseMessages } }, - validate: Schema.authors, + validate: { + params: Schema.taxa.params, + failAction: (request, h, err) => { + throw err; + return; + } + }, notes: [ 'This route fetches taxa starting with the provided letters.' ] diff --git a/api/v1/resources/treatment.js b/api/v1/resources/treatment.js index 1db792a..56dd88e 100644 --- a/api/v1/resources/treatment.js +++ b/api/v1/resources/treatment.js @@ -184,7 +184,14 @@ const treatment = { responseMessages: ResponseMessages } }, - validate: Schema.treatments, + validate: { + params: Schema.treatments.params, + query: Schema.treatments.query, + failAction: (request, h, err) => { + throw err; + return; + } + }, notes: [ 'This is the main route for fetching a treatment matching an id.' ] diff --git a/api/v1/schema.js b/api/v1/schema.js index 0405896..478b4f4 100644 --- a/api/v1/schema.js +++ b/api/v1/schema.js @@ -151,6 +151,30 @@ const schema = { refreshCache: Joi.boolean() .default(false) }) + }, + + authors: { + params: Joi.object({ + term: Joi.string().description('retrieve all authors starting with the provided letters (at leeast 3)').required().min(3).message('at least 3 characters are required (for example, « authors/ago »)') + }) + }, + + taxa: { + params: Joi.object({ + term: Joi.string().description('retrieve all taxa starting with the provided letters (at leeast 3)').required().min(3).message('at least 3 characters are required (for example, « authors/ago »)') + }) + }, + + families: { + params: Joi.object({ + term: Joi.string().description('retrieve all families starting with the provided letters (at leeast 3)').required().min(3).message('at least 3 characters are required (for example, « authors/ago »)') + }) + }, + + keywords: { + params: Joi.object({ + term: Joi.string().description('retrieve all keywords starting with the provided letters (at leeast 3)').required().min(3).message('at least 3 characters are required (for example, « authors/ago »)') + }) } }; diff --git a/api/v2/lib/dd2datadictionary.js b/api/v2/lib/dd2datadictionary.js index 4fc7887..6362b7b 100644 --- a/api/v2/lib/dd2datadictionary.js +++ b/api/v2/lib/dd2datadictionary.js @@ -1,68 +1,131 @@ 'use strict'; -const { dd, commonParams } = require('../../../dataDictionary/dd'); - -module.exports = (function() { +/*********************************************************************** + * + * Here we import the raw data definitions defined in dd.js and the + * files included therein, and export a combined and flattened data- + * dictionary as well as the resources grouped by resourceGroups to + * facilitate fast and convenient lookups. + * + **********************************************************************/ - const dataDictionary = []; +const { dd, commonParams } = require('../../../dataDictionary/dd'); +const dd2datadictionary = function() { + + // We will flatten and compile the data dictionary by + // converting the following + // + // dd = { + // zenodeoCore: { treatments: [] }, + // zenodeoRelated: { + // figureCitations: [], + // bibRefCitations: [], + // … + // } + // } + // + // to the following + // + // dataDictionary = { + // treatments: [], + // figureCitations: [], + // bibRefCitations: [], + // … + // } + // + // In the process, we will also add the required + // common parameters to all the resources + const dataDictionary = {}; + + // We will also create a bundle of all the resources + // grouped by their resource groups, and carrying with + // them the name of the 'resource' and the name of the + // 'resourceId'. This will look like + // + // "zenodeoCore": [ + // { + // "name": "treatments", + // "resourceId": "treatmentId" + // } + // ], + // "zenodeoRelated": [ + // { + // "name": "figureCitations", + // "resourceId": "figureCitationId" + // }, + // { + // "name": "bibRefCitations", + // "resourceId": "bibRefCitationId" + // }, const resourceGroups = {}; + // loop over each resourceGroup 'rg' in the raw dd + // 'rg' will be one of + // - zenodeoCore + // - zendeoRelated + // - zenodo + // - lookups for (let rg in dd) { - resourceGroups[rg] = []; - const resources = dd[rg]; - - for (let r in resources) { - resources[r].push(...commonParams['all']); + resourceGroups[rg] = []; + + // loop over each resource in the respective resource groups + const groupResources = dd[rg]; + for (let resource in groupResources) { - // this ensures that nothing is added to 'treatments' - if (commonParams[rg].length) { - resources[r].push(...commonParams[rg]); - } - - - //if (rg === 'zenodo') { - - // resources[r].push(...commonZenodoQueryParams); - //} - //else if (rg === 'zenodeo') { - - // if (r !== 'treatments') { + // Add the commonParams to 'all' the resources no matter + // which resourceGroup they are in (hence, the 'all') + let gr = groupResources[resource]; + gr.push(...commonParams['all']); + + // Don't add any params if a particular resourceGroup's + // specific commonParams are empty. This ensures nothing + // is added to 'treatments' which is a part of 'zenodeoCore' + // and to all the lookups. We do this by testing whether the + // commonParams of a 'rg' are empty by checking its .length() + if (commonParams[rg].length) { - // resources[r].push(...commonZenodeoQueryParams); - // } - //} + // we are using concat() instead of push() because we + // want to add these parameters in front of the array + // rather than at the end of the array + gr = [].concat(commonParams[rg], gr) + } - for (let i = 0, j = resources[r].length; i < j; i++) { + // For every resource, we add its name and the name of its + // resourceId key to the resourceGroups hash + let name = resource; + let resourceId = ''; + for (let i = 0, j = gr.length; i < j; i++) { - if (rg === 'lookups') { + if (rg !== 'lookups') { - resourceGroups[rg].push({ - name: r, - resourceId: '' - }); - break; - } - else { + if (gr[i].resourceId) { - if (resources[r][i].resourceId && resources[r][i].resourceId === true) { + if (gr[i].resourceId === true) { - resourceGroups[rg].push({ - name: r, - resourceId: resources[r][i].plaziName - }); - break; + resourceId = gr[i].plaziName; + break; + } } + } } - dataDictionary.push(...resources[r]); + resourceGroups[rg].push({ + name: name, + resourceId: resourceId + }); + + dataDictionary[resource] = gr; + } + + } return { @@ -70,4 +133,21 @@ module.exports = (function() { resourceGroups: resourceGroups }; -})(); \ No newline at end of file +}; + +const test = function() { + + const dd = dd2datadictionary(); + console.log(JSON.stringify(dd, null, ' ')); + +}; + +// https://stackoverflow.com/questions/6398196/detect-if-called-through-require-or-directly-by-command-line?rq=1 +if (require.main === module) { + + test(); +} +else { + + module.exports = (dd2datadictionary)(); +} \ No newline at end of file diff --git a/api/v2/lib/dd2queries.js b/api/v2/lib/dd2queries.js index ce15596..5951487 100644 --- a/api/v2/lib/dd2queries.js +++ b/api/v2/lib/dd2queries.js @@ -1,11 +1,16 @@ 'use strict'; +/*********************************************************************** + * + * Here we use the combined and flatened data dictionary to generate all + * the SQL queries required to extract data from the db based on the + * supplied queryObject + * + **********************************************************************/ + const config = require('config'); const plog = require(config.get('plog')); -// The following params may be present in the querystring but they are -// not included when making the SQL -const exclude = ['resources', 'communities', 'facets', 'page', 'size', 'stats', 'xml', 'limit', 'offset', 'refreshCache', 'resources', 'resourceId']; // We need sort params only for the data query. // Here we figure out the sortcol and sortdir @@ -37,28 +42,47 @@ const calcConstraint = function(ddKeys, queryObject) { } else { for (let k in queryObject) { - - if (! exclude.includes(k)) { - - const ddk = ddKeys.byQueryString[queryObject.resource][k]; - if (ddk) { - const op = ddk.queryable; - const sqlName = ddk.sqlName; - - if (op === 'equal') { - constraint.push(`${sqlName} = @${k}`); - } - else if (op === 'like') { - queryObject[k] = queryObject[k] + '%'; - constraint.push(`${sqlName} LIKE @${k}`); - } - else if (op === 'match') { - matchTables.push(ddk.table); - constraint.push(`${sqlName} MATCH @${k}`); - } + + const f = ddKeys.byQueryString[queryObject.resource][k]; + + if (f) { + + const op = f.queryable; + const sqlName = f.sqlName; + + if (op === 'equal') { + constraint.push(`${sqlName} = @${k}`); + } + else if (op === 'like') { + queryObject[k] = queryObject[k] + '%'; + constraint.push(`${sqlName} LIKE @${k}`); + } + else if (op === 'match') { + matchTables.push(f.table); + constraint.push(`${sqlName} MATCH @${k}`); + } + else if (op === 'between') { + + // else if (col === 'lat') { + // cols.push('latitude > @min_latitude'); + // cols.push('latitude < @max_latitude'); + // queryObject.min_latitude = queryObject.lat - range; + // queryObject.max_latitude = +queryObject.lat + range; + // } + // else if (col === 'lon') { + // cols.push('longitude > @min_longitude'); + // cols.push('longitude < @max_longitude'); + // queryObject.min_longitude = queryObject.lon - range; + // queryObject.max_longitude = +queryObject.lon + range; + // } + + const delta = 0.9; + queryObject[`min_${k}`] = +queryObject[k] - delta; + queryObject[`max_${k}`] = +queryObject[k] + delta; + constraint.push(`${sqlName} > @min_${k}`); + constraint.push(`${sqlName} < @max_${k}`); } } - } } @@ -129,36 +153,36 @@ const calcQuery = function(ddKeys, queryGroup, query, queryObject, matchTables, return sql; }; -const ddKeys = function() { - +const getDdKeys = function() { + const byQueryString = {}; const byResourceIds = {}; const { dataDictionary, resourceGroups } = require('./dd2datadictionary'); - + for (let resource in dataDictionary) { + // resource-specific data dictionary + const rdd = dataDictionary[resource]; + byQueryString[resource] = {}; - const resPart = dataDictionary[resource]; - for (let i = 0, j = resPart.length; i < j; i++) { - const qs = resPart[i].queryString; + for (let i = 0, j = rdd.length; i < j; i++) { + const f = rdd[i]; + const qs = f.queryString; + if (qs) { byQueryString[resource][qs] = { - sqlName: resPart[i].sqlName || qs, - queryable: resPart[i].queryable, - table: resPart[i].table || false, - resourceId: resPart[i].resourceId || false + sqlName: f.sqlName || qs, + queryable: f.queryable, + table: f.table || false, + resourceId: f.resourceId ? f.plaziName : false } - if (resPart[i].resourceId) { - - byResourceIds[resource] = resPart[i].plaziName - } - } + } } @@ -172,7 +196,7 @@ const ddKeys = function() { const dd2queries = function(queryObject) { - plog.info('queryObject', JSON.stringify(queryObject)); + plog.info('queryObject', queryObject); // get a reference to the resource-specific query parts. // For example, if 'queryObject.resource' is 'treatments' @@ -181,7 +205,9 @@ const dd2queries = function(queryObject) { const qParts = require('./qparts'); const r = qParts[queryObject.resource]; - const ddKeys = ddKeys(); + const ddKeys = getDdKeys(); + plog.info('ddKeys', ddKeys); + const pk = ddKeys.byResourceIds[queryObject.resource]; const [ matchTables, constraint ] = calcConstraint(ddKeys, queryObject); @@ -193,13 +219,17 @@ const dd2queries = function(queryObject) { // we want to retain the original query parts. const queries = JSON.parse(JSON.stringify(r.queries)); - const queryGroups = { - PK: [ 'related', 'taxonStats' ], - notPK: [ 'facets', 'stats' ] - }; + const doGroups = ['essential']; + + if (queryObject[pk]) { - const doGroups = queryObject[pk] ? queryGroups.PK : queryGroups.notPK; - doGroups.push('essential'); + doGroups.push(...[ 'related', 'taxonStats' ]); + } + else { + + if (queryObject.facets) doGroups.push('facets'); + if (queryObject.stats) doGroups.push('stats'); + } const q = {}; @@ -233,26 +263,39 @@ const dd2queries = function(queryObject) { return q; }; -module.exports = dd2queries; - -// const so = dd2schema(); -// const q = dd2queries({ -// communities: ['biosyslit', 'belgiumherbarium'], -// refreshCache: false, -// page: 1, -// size: 30, -// resources: 'treatments', -// facets: true, -// stats: true, -// xml: false, -// //sortBy: 'journalYear:ASC', -// q: 'carabus', -// authorityName: 'Agosti', -// journalYear: '1996', -// format: 'xml', -// treatmentTitle: 'opheys', -// doi: '10.2454/sdff:1956', -// treatmentId: '58F12CC7CCAD08F32CF9920D36C9992E' -// }); - -// console.log(JSON.stringify(q, null, '\t')) \ No newline at end of file +const test = function() { + + const queryObject = { + communities: ['biosyslit', 'belgiumherbarium'], + refreshCache: false, + page: 1, + size: 30, + resource: 'treatments', + facets: false, + stats: false, + xml: false, + sortBy: 'journalYear:ASC', + // q: 'carabus', + authorityName: 'Agosti', + // journalYear: '1996', + // format: 'xml', + // treatmentTitle: 'opheys', + // doi: '10.2454/sdff:1956', + // treatmentId: '58F12CC7CCAD08F32CF9920D36C9992E' + }; + + const q = dd2queries(queryObject); + console.log(q); + +}; + +// https://stackoverflow.com/questions/6398196/detect-if-called-through-require-or-directly-by-command-line?rq=1 +if (require.main === module) { + + test(); +} +else { + + module.exports = dd2queries; +} + diff --git a/api/v2/lib/dd2schema.js b/api/v2/lib/dd2schema.js index 04cef29..f7a8bdd 100644 --- a/api/v2/lib/dd2schema.js +++ b/api/v2/lib/dd2schema.js @@ -1,11 +1,18 @@ 'use strict'; +/*********************************************************************** + * + * Here we convert the combined and flattened data-dictionary into a + * schema that can be used by Joi for parameter vaidation in the + * incoming REST API queries. + * + **********************************************************************/ + const Joi = require('@hapi/joi'); const { dataDictionary, resourceGroups } = require('./dd2datadictionary'); const Boom = require('@hapi/boom'); -// 'resources' is the plural form of the desired resource -// for example, 'treatments' or 'materialsCitations' + const dd2schema = function() { // the schema object we are going to construct @@ -14,17 +21,16 @@ const dd2schema = function() { for (let resource in dataDictionary) { - // resource-specific data dictionary - const rdd = dataDictionary[resource]; - // resource-specific schema description const rso = {}; const rsoLog = {}; + // resource-specific data dictionary + const rdd = dataDictionary[resource]; + for (let i = 0, j = rdd.length; i < j; i++) { - const f = rdd[i]; - //const n = f.plaziName; + const f = rdd[i]; const qs = f.queryString; if (qs) { @@ -49,36 +55,37 @@ const dd2schema = function() { soLog[resource] = { query: `Joi.object(${JSON.stringify(rsoLog, null, 4)})` }; } - //plog.info('Schema Object', so); - return so; + return { Schema: so, SchemaLog: soLog }; }; -// const so = dd2schema(); - -// const { error, value } = so.treatments.query.validate({ -// communities: 'biosyslit', -// refreshCache: false, -// page: 1, -// size: 30, -// //resources: 'treatments', -// facets: true, -// stats: true, -// xml: false, -// sortBy: 'journalYear:ASC', -// q: 'carabus', -// // authorityName: 'Agosti', -// // journalYear: '1996', -// format: 'xml', -// treatmentTitle: 'opheys', -// doi: '10.2454/sdff:1956' -// }); - -// if (error) { -// console.log(error); -// } -// else { -// plog.info('passed'); -// } - -module.exports = (dd2schema)(); \ No newline at end of file +const test = function() { + + const { Schema, SchemaLog } = dd2schema(); + console.log(SchemaLog); + + const { error, value } = Schema.materialsCitations.query.validate({ + materialsCitationId: '19325B47274DC7B60C78E6AEBFAB8689' + }); + + if (error) { + + console.log(error); + } + else { + + console.log('passed'); + } + +}; + + +// https://stackoverflow.com/questions/6398196/detect-if-called-through-require-or-directly-by-command-line?rq=1 +if (require.main === module) { + + test(); +} +else { + + module.exports = (dd2schema)(); +} \ No newline at end of file diff --git a/api/v2/lib/routeMaker.js b/api/v2/lib/routeMaker.js index 605c92c..d86953b 100644 --- a/api/v2/lib/routeMaker.js +++ b/api/v2/lib/routeMaker.js @@ -1,12 +1,17 @@ 'use strict'; -const Schema = require('./dd2schema'); +const { Schema, SchemaLog } = require('./dd2schema'); const ResponseMessages = require('../../responseMessages'); const Utils = require('../utils'); const h = function(resource) { - const { handler, getRecords } = require(`../lib/${resource.group}`); + const rg = resource.group.startsWith('zenodeo') ? 'zenodeo' : resource.group; + const { handler, getRecords } = require(`../lib/${rg}`); + + // Add a '2' to the name for lookups because lookups by the + // same names already exist in api/v1, and plugin names + // have to be unique const pluginName = resource.group === 'lookups' ? `${resource.name}2` : resource.name; @@ -45,12 +50,17 @@ const h = function(resource) { responseMessages: ResponseMessages } }, - validate: Schema[resource.name], + validate: { + query: Schema[resource.name].query, + failAction: (request, h, err) => { + throw err; + return; + } + }, notes: [ `This is the main route for fetching ${resource.name} matching the provided query parameters.` ] } - }]); }, @@ -59,4 +69,4 @@ const h = function(resource) { }; -module.exports = h; \ No newline at end of file +module.exports = h; diff --git a/api/v2/lib/zenodeoCore.js b/api/v2/lib/zenodeo.js similarity index 75% rename from api/v2/lib/zenodeoCore.js rename to api/v2/lib/zenodeo.js index 1fc0ff8..201462c 100644 --- a/api/v2/lib/zenodeoCore.js +++ b/api/v2/lib/zenodeo.js @@ -1,12 +1,18 @@ -/************************************** - * abstracted logic for the handler and other functions - * for resources that are fetched from Zenodeo - * - treatments.js - * - treatmentAuthors.js - **************************************/ - 'use strict'; +/******************************************************* + * + * Abstracted logic for the handler and other functions + * for the related resources that are fetched from + * Zenodeo + * - treatmentAuthors + * - materialsCitations + * - treatmentCitations + * - bibRefCitations + * - figureCitations + * + ******************************************************/ + const config = require('config'); const plog = require(config.get('plog')); const cacheOn = config.get('v2.cache.on'); @@ -14,9 +20,8 @@ const uriZenodeo = config.get('v2.uri.zenodeo'); const Utils = require('../utils'); const Database = require('better-sqlite3'); const db = new Database(config.get('data.treatments')); -const dbQueries = new Database(config.get('data.queries')); -const fs = require('fs'); - +// const dbQueries = new Database(config.get('data.queries')); +//console.log('rg') const dd2queries = require('../lib/dd2queries'); @@ -29,18 +34,14 @@ const handler = function(resource) { // bunch up messages to print them to the log const messages = [{label: 'queryObject', params: queryObject}]; - //if (queryObject.resource === 'treatments') { - - // if xml is being requested, send it back and be done with it - if (queryObject.format && queryObject.format === 'xml') { - - plog.log({ header: 'WEB QUERY', messages: messages }); - return h.response(getXml(queryObject.treatmentId)) - .type('text/xml') - .header('Content-Type', 'application/xml'); - - } - //} + if (queryObject.format && queryObject.format === 'xml') { + + plog.log({ header: 'WEB QUERY', messages: messages }); + return h.response(getXml(queryObject.treatmentId)) + .type('text/xml') + .header('Content-Type', 'application/xml'); + + } // cacheKey is the URL query without the refreshCache param. const cacheKey = Utils.makeCacheKey(request); @@ -106,94 +107,7 @@ const getRecords = function(cacheKey) { } }; -// https://stackoverflow.com/a/18234317/183692 -const formatUnicorn = function () { - - let str = this.toString().replace(/@(\w+)/g, "'{\$1}'"); - - if (arguments.length) { - - const t = typeof arguments[0]; - const args = ('string' === t || 'number' === t) ? - Array.prototype.slice.call(arguments) - : arguments[0]; - - for (let key in args) { - str = str.replace(new RegExp("\\{" + key + "\\}", "gi"), args[key]); - } - } - - return str; -}; - -String.prototype.formatUnicorn = String.prototype.formatUnicorn || formatUnicorn; - -const dataForDelivery = function(t, data, debug) { - - if (cacheOn) { - return data; - } - else { - const report = { msec: t.msr } - - if (process.env.NODE_ENV === 'test') { - report.debug = debug; - } - - const {queryObject, sqls} = debug; - const inserts = sqls.length; - - const s1 = dbQueries.prepare(`INSERT INTO webqueries (qp) VALUES(@qp) ON CONFLICT(qp) DO UPDATE SET count=count+1`); - - const s2 = dbQueries.prepare('SELECT Max(id) AS id FROM webqueries'); - - const s3 = dbQueries.prepare(`INSERT INTO sqlqueries (sql) VALUES(@sql) ON CONFLICT(sql) DO NOTHING`); - - const s4 = dbQueries.prepare('SELECT Max(id) AS id FROM sqlqueries'); - - const s5 = dbQueries.prepare('INSERT INTO stats (webqueries_id, sqlqueries_id, timeTaken) VALUES (@webqueries_id, @sqlqueries_id, @timeTaken)'); - - if (inserts) { - - try { - //dbQueries.prepare('BEGIN TRANSACTION').run(); - - const qp = JSON.stringify(queryObject); - s1.run({qp: qp}); - - const webqueries_id = s2.get().id; - - for (let i = 0; i < inserts; i++) { - - const sql = sqls[i].sql.formatUnicorn(queryObject); - const t = sqls[i].took; - - s3.run({sql: sql}); - - const sqlqueries_id = s4.get().id; - - s5.run({ - webqueries_id: webqueries_id, - sqlqueries_id: sqlqueries_id, - timeTaken: t.msr - }); - - } - } - catch (error) { - console.log(error); - } - - } - - return { - value: data, - cached: null, - report: report - } - } - -}; +String.prototype.formatUnicorn = String.prototype.formatUnicorn || Utils.formatUnicorn; const getOneRecord = function(queryObject) { @@ -258,7 +172,7 @@ const getOneRecord = function(queryObject) { // We are done if no records found if (! data['num-of-records']) { timer = process.hrtime(timer); - return dataForDelivery(timer, data, debug); + return Utils.dataForDelivery(timer, data, debug); } // more data from beyond the database @@ -273,7 +187,7 @@ const getOneRecord = function(queryObject) { data['related-records'] = getRelatedRecords(q, queryObject, debug); timer = process.hrtime(timer); - return dataForDelivery(timer, data, debug); + return Utils.dataForDelivery(timer, data, debug); }; const getManyRecords = async function(queryObject) { @@ -289,6 +203,7 @@ const getManyRecords = async function(queryObject) { const q = dd2queries(queryObject); + // this is where we will store the various SQL statements // and their performance metrics so we can store them in a db const debug = { @@ -336,7 +251,7 @@ const getManyRecords = async function(queryObject) { }); timer = process.hrtime(timer); - return dataForDelivery(timer, data, debug); + return Utils.dataForDelivery(timer, data, debug); } // get the records @@ -349,7 +264,7 @@ const getManyRecords = async function(queryObject) { data.records = db.prepare(dataSql).all(queryObject) || []; t = process.hrtime(t); - const p = { sql: countSql, took: Utils.timerFormat(t) }; + const p = { sql: dataSql, took: Utils.timerFormat(t) }; messages.push({ label: 'data', params: p }); debug.sqls.push(p); @@ -368,12 +283,16 @@ const getManyRecords = async function(queryObject) { data.records.forEach(rec => { + //console.log(`queryObject.resourceId: ${rec[queryObject.resourceId]}`); rec._links = {}; rec._links.self = Utils.makeLink({ uri: uriZenodeo, params: { - resource: queryObject.resource, - resourceId: [ queryObject.resourceId, rec[queryObject.resourceId] ] + path: queryObject.path, + resourceId: { + key: queryObject.resourceId, + val: rec[queryObject.resourceId] + } } }); @@ -422,7 +341,7 @@ const getManyRecords = async function(queryObject) { // all done timer = process.hrtime(timer); - return dataForDelivery(timer, data, debug); + return Utils.dataForDelivery(timer, data, debug); }; const getStatsFacets = function(type, q, queryObject, debug) { diff --git a/api/v2/lib/zenodeoRelated.js b/api/v2/lib/zenodeoRelated.js deleted file mode 100644 index f229a83..0000000 --- a/api/v2/lib/zenodeoRelated.js +++ /dev/null @@ -1,570 +0,0 @@ -/************************************** - * abstracted logic for the handler and other functions - * for resources that are fetched from Zenodeo - * - treatments.js - * - treatmentAuthors.js - **************************************/ - -'use strict'; - -const config = require('config'); -const plog = require(config.get('plog')); -const cacheOn = config.get('v2.cache.on'); -const uriZenodeo = config.get('v2.uri.zenodeo'); -const Utils = require('../utils'); -const Database = require('better-sqlite3'); -const db = new Database(config.get('data.treatments')); -const dbQueries = new Database(config.get('data.queries')); -const fs = require('fs'); - -const dd2queries = require('../lib/dd2queries'); - - -const handler = function(resource) { - - return async function(request, h) { - - const queryObject = Utils.modifyIncomingQueryObject(request.query, resource); - - // bunch up messages to print them to the log - const messages = [{label: 'queryObject', params: queryObject}]; - - // if (queryObject.resource === 'treatments') { - - // // if xml is being requested, send it back and be done with it - // if (queryObject.format && queryObject.format === 'xml') { - - // plog.log({ header: 'WEB QUERY', messages: messages }); - // return h.response(getXml(queryObject.treatmentId)) - // .type('text/xml') - // .header('Content-Type', 'application/xml'); - - // } - // } - - // cacheKey is the URL query without the refreshCache param. - const cacheKey = Utils.makeCacheKey(request); - messages.push({label: 'cacheKey', params: cacheKey}); - - let result; - if (cacheOn) { - if (queryObject.refreshCache || queryObject.refreshCache === 'true') { - - messages.push({ - label: 'info', - params: 'force emptying the cache' - }); - - this.cache.drop(cacheKey); - - messages.push({ - label: 'info', - params: 'refilling the cache with fresh results' - }); - - } - - messages.push({ - label: 'info', - params: 'getting results from the cache' - }); - - plog.log({ header: 'WEB QUERY', messages: messages }); - result = this.cache.get(cacheKey); - } - else { - - messages.push({ - label: 'info', - params: 'querying for fresh results' - }); - - plog.log({ header: 'WEB QUERY', messages: messages }); - result = getRecords(cacheKey); - - } - - return result; - - }; - -}; - -const getRecords = function(cacheKey) { - - const queryObject = Utils.makeQueryObject(cacheKey); - - // A resourceId is present. The query is for a specific - // record. All other query params are ignored - if (queryObject[queryObject.resourceId]) { - return getOneRecord(queryObject); - } - - // More complicated queries with search parameters - else { - return getManyRecords(queryObject) - } -}; - -// https://stackoverflow.com/a/18234317/183692 -const formatUnicorn = function () { - - let str = this.toString().replace(/@(\w+)/g, "'{\$1}'"); - - if (arguments.length) { - - const t = typeof arguments[0]; - const args = ('string' === t || 'number' === t) ? - Array.prototype.slice.call(arguments) - : arguments[0]; - - for (let key in args) { - str = str.replace(new RegExp("\\{" + key + "\\}", "gi"), args[key]); - } - } - - return str; -}; - -String.prototype.formatUnicorn = String.prototype.formatUnicorn || formatUnicorn; - -const dataForDelivery = function(t, data, debug) { - - if (cacheOn) { - return data; - } - else { - const report = { msec: t.msr } - - if (process.env.NODE_ENV === 'test') { - report.debug = debug; - } - - const {queryObject, sqls} = debug; - const inserts = sqls.length; - - const s1 = dbQueries.prepare(`INSERT INTO webqueries (qp) VALUES(@qp) ON CONFLICT(qp) DO UPDATE SET count=count+1`); - - const s2 = dbQueries.prepare('SELECT Max(id) AS id FROM webqueries'); - - const s3 = dbQueries.prepare(`INSERT INTO sqlqueries (sql) VALUES(@sql) ON CONFLICT(sql) DO NOTHING`); - - const s4 = dbQueries.prepare('SELECT Max(id) AS id FROM sqlqueries'); - - const s5 = dbQueries.prepare('INSERT INTO stats (webqueries_id, sqlqueries_id, timeTaken) VALUES (@webqueries_id, @sqlqueries_id, @timeTaken)'); - - if (inserts) { - - try { - //dbQueries.prepare('BEGIN TRANSACTION').run(); - - const qp = JSON.stringify(queryObject); - s1.run({qp: qp}); - - const webqueries_id = s2.get().id; - - for (let i = 0; i < inserts; i++) { - - const sql = sqls[i].sql.formatUnicorn(queryObject); - const t = sqls[i].took; - - s3.run({sql: sql}); - - const sqlqueries_id = s4.get().id; - - s5.run({ - webqueries_id: webqueries_id, - sqlqueries_id: sqlqueries_id, - timeTaken: t.msr - }); - - } - } - catch (error) { - console.log(error); - } - - } - - return { - value: data, - cached: null, - report: report - } - } - -}; - -const getOneRecord = function(queryObject) { - - let timer = process.hrtime(); - - const messages = [ {label: 'queryObject', params: queryObject} ]; - - // data will hold all the query results to be sent back - const data = { - 'search-criteria': Utils.makeSearchCriteria(queryObject) - }; - - const q = dd2queries(queryObject); - - // this is where we will store the various SQL statements - // and their performance metrics so we can store them in a db - const debug = { - queryObject: queryObject, - sqls: [] - }; - - const sql = q.essential.data.sql; - - try { - - let t = process.hrtime(); - - // add query results to data.records. If no results are found, - // add an empty array to data.records - const records = db.prepare(sql).get(queryObject); - if (records) { - data.records = [ records ]; - data['num-of-records'] = 1; - } - else { - data.records = []; - data['num-of-records'] = 0; - } - - t = process.hrtime(t); - const p = { sql: sql, took: Utils.timerFormat(t) }; - - messages.push({ label: 'data', params: p }); - debug.sqls.push(p); - } - catch (error) { - plog.error(error, sql); - } - - data._links = {}; - data._links.self = Utils.makeLink({ - uri: uriZenodeo, - params: data['search-criteria'] - }); - - plog.log({ - header: 'ONE QUERY', - messages: messages, - queryObject: queryObject - }); - - // We are done if no records found - if (! data['num-of-records']) { - timer = process.hrtime(timer); - return dataForDelivery(timer, data, debug); - } - - // more data from beyond the database - if (queryObject.resource === 'treatments') { - if (queryObject.xml && queryObject.xml === 'true') { - data.records[0].xml = getXml(queryObject.treatmentId); - } - - data.taxonStats = getTaxonStats(q, queryObject, debug); - } - - data['related-records'] = getRelatedRecords(q, queryObject, debug); - - timer = process.hrtime(timer); - return dataForDelivery(timer, data, debug); -}; - -const getManyRecords = async function(queryObject) { - - let timer = process.hrtime(); - - const messages = [{label: 'queryObject', params: queryObject}]; - - // data will hold all the query results to be sent back - const data = { - 'search-criteria': Utils.makeSearchCriteria(queryObject) - }; - - const q = dd2queries(queryObject); - - // this is where we will store the various SQL statements - // and their performance metrics so we can store them in a db - const debug = { - queryObject: queryObject, - sqls: [] - }; - - const id = queryObject.id ? parseInt(queryObject.id) : 0; - - // first find total number of matches - const countSql = q.essential.count.sql; - - - try { - - let t = process.hrtime(); - - data['num-of-records'] = db.prepare(countSql) - .get(queryObject) - .numOfRecords; - - t = process.hrtime(t); - const p = { sql: countSql, took: Utils.timerFormat(t) }; - - messages.push({ label: 'count', params: p }); - debug.sqls.push(p); - } - catch (error) { - plog.error(error, countSql); - } - - // add a self link to the data - data._links = {}; - data._links.self = Utils.makeLink({ - uri: uriZenodeo, - params: data['search-criteria'] - }); - - // We are done if no records found - if (! data['num-of-records']) { - plog.log({ - header: 'MANY QUERIES', - messages: messages, - queryObject: queryObject - }); - - timer = process.hrtime(timer); - return dataForDelivery(timer, data, debug); - } - - // get the records - const dataSql = q.essential.data.sql; - - try { - - let t = process.hrtime(); - - data.records = db.prepare(dataSql).all(queryObject) || []; - - t = process.hrtime(t); - const p = { sql: countSql, took: Utils.timerFormat(t) }; - - messages.push({ label: 'data', params: p }); - debug.sqls.push(p); - } - catch (error) { - plog.error(error, dataSql); - } - - plog.log({ - header: 'MANY QUERIES', - messages: messages, - queryObject: queryObject - }); - - if (data.records.length > 0) { - - data.records.forEach(rec => { - - rec._links = {}; - rec._links.self = Utils.makeLink({ - uri: uriZenodeo, - params: { - resource: queryObject.resource, - resourceId: [ queryObject.resourceId, rec[queryObject.resourceId] ] - } - }); - - }); - - const lastrec = data.records[data.records.length - 1]; - data.nextid = lastrec.id; - - } - else { - data.nextid = ''; - } - - // set some records-specific from and to for the formatted - // search criteria string - const num = data.records.length; - data.from = ((queryObject.page - 1) * queryObject.size) + 1; - data.to = num < queryObject.size ? - data.from + num - 1 : - data.from + queryObject.size - 1; - - data.previd = id; - - data.prevpage = queryObject.page >= 1 ? queryObject.page - 1 : ''; - data.nextpage = num < queryObject.size ? '' : +queryObject.page + 1; - - data._links.prev = Utils.makeLink({ - uri: uriZenodeo, - params: data['search-criteria'], - page: data.prevpage - }); - - data._links.next = Utils.makeLink({ - uri: uriZenodeo, - params: data['search-criteria'], - page: data.nextpage - }); - - // finally, get facets and stats, if requested - const groupedQueries = ['facets', 'stats']; - groupedQueries.forEach(g => { - if (g in queryObject && queryObject[g] === 'true') { - data[g] = getStatsFacets(g, q, queryObject, debug); - } - }); - - // all done - timer = process.hrtime(timer); - return dataForDelivery(timer, data, debug); -}; - -const getStatsFacets = function(type, q, queryObject, debug) { - - const result = {}; - const messages = []; - - for (let query in q[type]) { - - let t = process.hrtime(); - - const sql = q[type][query].sql; - - try { - result[query] = db.prepare(sql).all(queryObject); - } - catch (error) { - plog.error(error, sql); - } - - t = process.hrtime(t); - - const p = { sql: sql, took: Utils.timerFormat(t) }; - messages.push({ label: query, params: p }); - debug.sqls.push(p); - } - - plog.log({ - header: `${type.toUpperCase()} QUERIES`, - messages: messages, - queryObject: queryObject - }); - - return result; -}; - -const getRelatedRecords = function(q, queryObject, debug) { - - const related = {}; - const messages = []; - - for (let query in q.related) { - - const pk = q.related[query].pk; - const sql = q.related[query].sql; - - let t = process.hrtime(); - - try { - related[query] = Utils.halify({ - records: db.prepare(sql).all(queryObject), - uri: uriZenodeo, - resource: query, - id: pk - }); - } - catch (error) { - plog.error(error, sql); - } - - t = process.hrtime(t); - - const p = { sql: sql, took: Utils.timerFormat(t) }; - debug.sqls.push(p); - messages.push({ label: query, params: p }); - - } - - plog.log({ - header: 'ONE RELATED', - messages: messages, - queryObject: queryObject - }); - - return related; -}; - -// const getTaxonStats = function(q, queryObject, debug) { - -// const taxonStats = {}; -// const messages = []; - -// for (let query in q.taxonStats) { - -// const sql = q.taxonStats[query].sql; - -// let t = process.hrtime(); - -// try { -// taxonStats[query] = db.prepare(sql).get(queryObject).num; -// } -// catch (error) { -// plog.error(error, sql); -// } - -// t = process.hrtime(t); - -// const p = { sql: sql, took: Utils.timerFormat(t) }; -// debug.sqls.push(p); -// messages.push({ label: query, params: p }); - -// } - -// plog.log({ -// header: 'ONE TAXONSTATS', -// messages: messages, -// queryObject: queryObject -// }); - -// return taxonStats; -// }; - -// const getXml = function(treatmentId) { -// const one = treatmentId.substr(0, 1); -// const two = treatmentId.substr(0, 2); -// const thr = treatmentId.substr(0, 3); - -// plog.info(`getting the xml for ${treatmentId}`); - -// return fs.readFileSync( -// `data/treatments/${one}/${two}/${thr}/${treatmentId}.xml`, -// 'utf8' -// ) -// }; - -// const formatAuthors = function(authors) { -// let authorsArr = authors.map(a => { return a.author }); -// const numOfAuthors = authorsArr.length; - -// let authorsList = ''; -// if (numOfAuthors === 1) { -// authorsList = authorsArr[0]; -// } -// else if (numOfAuthors === 2) { -// authorsList = authorsArr.join(' and '); -// } -// else if (numOfAuthors > 2) { -// authorsList = authorsArr.slice(0, 2).join(', '); -// authorsList += ' and ' + authorsArr[numOfAuthors - 1] -// } - -// return authorsList; -// }; - -module.exports = { handler, getRecords }; \ No newline at end of file diff --git a/api/v2/lib/zenodo.js b/api/v2/lib/zenodo.js index 610afcd..fdac1b1 100644 --- a/api/v2/lib/zenodo.js +++ b/api/v2/lib/zenodo.js @@ -93,7 +93,7 @@ const getOneRecord = async function(queryObject) { const uriRemote = uriZenodo + queryObject[queryObject.resourceId]; const messages = [ {label: 'queryObject', params: queryObject} ]; - const messages = [ {label: 'remote URI', params: uriRemote} ]; + messages.push({label: 'remote URI', params: uriRemote}); // data will hold all the query results to be sent back const data = { diff --git a/api/v2/resources/wpsummary.js b/api/v2/resources/wpsummary.js index f6c5b81..4b67dd5 100644 --- a/api/v2/resources/wpsummary.js +++ b/api/v2/resources/wpsummary.js @@ -1,5 +1,5 @@ const wiki = require('wikijs').default; -const Schema = require('../schema.js'); +//const Schema = require('../schema.js'); module.exports = { plugin: { @@ -32,7 +32,7 @@ module.exports = { //responseMessages: ResponseMessages } }, - validate: Schema.wpsummary, + //validate: Schema.wpsummary, notes: [ 'Summary from the Wikipedia page', ] diff --git a/api/v2/utils.js b/api/v2/utils.js index 3482680..3a31152 100644 --- a/api/v2/utils.js +++ b/api/v2/utils.js @@ -4,10 +4,11 @@ const Wreck = require('@hapi/wreck'); const config = require('config'); const plog = require(config.get('plog')); - +const cacheOn = config.get('v2.cache.on'); const Database = require('better-sqlite3'); const dbFacets = new Database(config.get('data.facets')); const dbTreatments = new Database(config.get('data.treatments')); +const dbQueries = new Database(config.get('data.queries')); const facets = { authors: 'author', @@ -17,6 +18,93 @@ const facets = { }; module.exports = { + + dataForDelivery: function(t, data, debug) { + + if (cacheOn) { + return data; + } + else { + const report = { msec: t.msr } + + if (process.env.NODE_ENV === 'test') { + report.debug = debug; + } + + const {queryObject, sqls} = debug; + const inserts = sqls.length; + + const s1 = dbQueries.prepare(`INSERT INTO webqueries (qp) VALUES(@qp) ON CONFLICT(qp) DO UPDATE SET count=count+1`); + + const s2 = dbQueries.prepare('SELECT Max(id) AS id FROM webqueries'); + + const s3 = dbQueries.prepare(`INSERT INTO sqlqueries (sql) VALUES(@sql) ON CONFLICT(sql) DO NOTHING`); + + const s4 = dbQueries.prepare('SELECT Max(id) AS id FROM sqlqueries'); + + const s5 = dbQueries.prepare('INSERT INTO stats (webqueries_id, sqlqueries_id, timeTaken) VALUES (@webqueries_id, @sqlqueries_id, @timeTaken)'); + + if (inserts) { + + try { + //dbQueries.prepare('BEGIN TRANSACTION').run(); + + const qp = JSON.stringify(queryObject); + s1.run({qp: qp}); + + const webqueries_id = s2.get().id; + + for (let i = 0; i < inserts; i++) { + + const sql = sqls[i].sql.formatUnicorn(queryObject); + const t = sqls[i].took; + + s3.run({sql: sql}); + + const sqlqueries_id = s4.get().id; + + s5.run({ + webqueries_id: webqueries_id, + sqlqueries_id: sqlqueries_id, + timeTaken: t.msr + }); + + } + } + catch (error) { + console.log(error); + } + + } + + return { + value: data, + cached: null, + report: report + } + } + + }, + + // https://stackoverflow.com/a/18234317/183692 + formatUnicorn: function () { + + let str = this.toString().replace(/@(\w+)/g, "'{\$1}'"); + + if (arguments.length) { + + const t = typeof arguments[0]; + const args = ('string' === t || 'number' === t) ? + Array.prototype.slice.call(arguments) + : arguments[0]; + + for (let key in args) { + str = str.replace(new RegExp("\\{" + key + "\\}", "gi"), args[key]); + } + } + + return str; + }, timerFormat: function(t) { @@ -289,14 +377,14 @@ module.exports = { makeLink: function({uri, params, page}) { const qs = Object.entries(params) - .filter(e => e[0] !== 'resource') + .filter(e => e[0] !== 'path') .map(e => page ? `${e[0]}=${(e[0] === 'page' ? page : e[1])}` - : e[0] === 'resourceId' ? `${e[1][0]}=${e[1][1]}` - : `${e[0]}=${e[1]}`) + : e[0] === 'resourceId' ? `${e[1].key}=${e[1].val}` + : `${e[0]}=${e[1]}`) .sort() .join('&'); - return { href: `${uri}/${params.resource}?${qs}` } + return { href: `${uri}/${params.path}?${qs}` } }, /* The incoming queryObject is changed so queries can be made */ @@ -352,14 +440,18 @@ module.exports = { 'limit', 'offset', //'page', - 'path', + //'path', 'refreshCache', - //'resource', + 'resource', 'resourceId', //'size', 'stats' ]; + if (queryObject[queryObject.resourceId]) { + exclude.push(...['page', 'size']); + } + for (let key in queryObject) { if (! exclude.includes(key)) { sc[key] = queryObject[key]; diff --git a/config/default.js b/config/default.js index c0af389..b3cf8db 100644 --- a/config/default.js +++ b/config/default.js @@ -32,24 +32,7 @@ module.exports = { url: 'https://creativecommons.org/publicdomain/zero/1.0/legalcode' } }, - // 'cache': { - // 'path': path.join(cwd, 'cache'), - // 'v1': { - // 'path': path.join(cwd, 'cache'), - // 'name': 'persistent', - // }, - // 'v2': { - // 'path': path.join(cwd, 'cache', 'catbox'), - // 'name': 'catbox', - // 'on': false - // } - //}, - // 'uri': { - // 'local': 'http://localhost:3000', - // 'remote': 'https://zenodo.org/api', - // 'zenodeo': 'http://localhost:3030', - // 'zenodo': 'https://zenodo.org/api' - // }, + 'download-program': { "newTreatmentsDir": path.join(cwd, 'data', 'treatmentsNew'), "treatmentsListDir": path.join(cwd, 'data'), @@ -58,6 +41,7 @@ module.exports = { "downloadListURL": 'http://tb.plazi.org/GgServer/search?&indexName=0&resultFormat=XML&lastModifiedSince=' }, 'swaggered-scheme': ['http'], + port: 3030, loglevel: 'INFO', diff --git a/dataDictionary/dd.js b/dataDictionary/dd.js index 3c267a2..3121741 100644 --- a/dataDictionary/dd.js +++ b/dataDictionary/dd.js @@ -1,6 +1,7 @@ 'use strict'; /*********************************************************************** + * * Every data-dictionary (dd) element for a resource should * have the following keys * @@ -150,7 +151,7 @@ const commonParams = { zenodoName : '', sqlType : 'TEXT NOT NULL', cheerioElement: '$("document").attr("docId")', - description : 'The unique ID of the treatment', + description : 'The unique ID of the parent treatment (FK)', queryable : 'equal', queryString : 'treatmentId', validation : 'Joi.string().guid().description(`${d}`).optional()', diff --git a/dataDictionary/figureCitations.js b/dataDictionary/figureCitations.js index 0f60a14..d1a32c6 100644 --- a/dataDictionary/figureCitations.js +++ b/dataDictionary/figureCitations.js @@ -1,17 +1,17 @@ 'use strict'; module.exports = [ - { - plaziName : 'id', - zenodoName : '', - sqlType : 'INTEGER PRIMARY KEY', - cheerioElement: '', - description : 'pk', - queryable : '', - queryString : '', - validation : '', - resourceId : false - }, + // { + // plaziName : 'id', + // zenodoName : '', + // sqlType : 'INTEGER PRIMARY KEY', + // cheerioElement: '', + // description : 'pk', + // queryable : '', + // queryString : '', + // validation : '', + // resourceId : false + // }, { plaziName : 'figureCitationId', zenodoName : '', diff --git a/dataDictionary/materialsCitations.js b/dataDictionary/materialsCitations.js index 442c97b..2687254 100644 --- a/dataDictionary/materialsCitations.js +++ b/dataDictionary/materialsCitations.js @@ -1,17 +1,6 @@ 'use strict'; module.exports = [ - { - plaziName : 'id', - zenodoName : '', - sqlType : 'INTEGER PRIMARY KEY', - cheerioElement: '', - description : 'pk', - queryable : '', - queryString : '', - validation : '', - resourceId : false - }, { plaziName : 'materialsCitationId', zenodoName : '', @@ -226,8 +215,31 @@ module.exports = [ zenodoName : 'geo_lat', sqlType : 'TEXT', cheerioElement: '$("materialsCitation").attr("latitude")', - description : 'Geographic coordinates of the location where the specimen was collected', - queryable : 'equal', + description : `Geographic coordinates of the location where the specimen was collected. +Since it is unreasonable to expect the user to provide exact lat/lon coordinates, a delta of 0.9 +is used to find all the points contained in the resulting box. For example, if latitude 77 and +longitude 78 are provided, the two points A and B are located inside the bounding box made from +submitted coordinates +- a delta of 0.9 + + lat: 77.9 lat: 77.9 + lon: 77.1 lon: 78.9 + ┌───────────────────────────────────────────────┐ + │ │ + │ │ + │ lat: 77.53333 │ + │ lon: 78.88333 │ + │ B │ + │ │ + │ │ + │ lat: 77.2 │ + │ lon: 78.11667 │ + │ A │ + │ │ + │ │ + └───────────────────────────────────────────────┘ + lat: 76.1 lat: 76.1 + lon: 77.1 lon: 78.9`, + queryable : 'between', queryString : 'latitude', validation : 'Joi.number().min(-90).max(90).description(`${d}`).optional()', resourceId : false @@ -237,8 +249,31 @@ module.exports = [ zenodoName : 'geo_lon', sqlType : 'TEXT', cheerioElement: '$("materialsCitation").attr("longitude")', - description : 'Geographic coordinates of the location where the specimen was collected', - queryable : 'equal', + description : `Geographic coordinates of the location where the specimen was collected. + Since it is unreasonable to expect the user to provide exact lat/lon coordinates, a delta of 0.9 + is used to find all the points contained in the resulting box. For example, if latitude 77 and + longitude 78 are provided, the two points A and B are located inside the bounding box made from + submitted coordinates +- a delta of 0.9 + + lat: 77.9 lat: 77.9 + lon: 77.1 lon: 78.9 + ┌───────────────────────────────────────────────┐ + │ │ + │ │ + │ lat: 77.53333 │ + │ lon: 78.88333 │ + │ B │ + │ │ + │ │ + │ lat: 77.2 │ + │ lon: 78.11667 │ + │ A │ + │ │ + │ │ + └───────────────────────────────────────────────┘ + lat: 76.1 lat: 76.1 + lon: 77.1 lon: 78.9`, + queryable : 'between', queryString : 'longitude', validation : 'Joi.number().min(-180).max(180).description(`${d}`).optional()', resourceId : false diff --git a/dataDictionary/treatmentAuthors.js b/dataDictionary/treatmentAuthors.js index 9ead389..d1bf2a1 100644 --- a/dataDictionary/treatmentAuthors.js +++ b/dataDictionary/treatmentAuthors.js @@ -1,17 +1,17 @@ 'use strict'; module.exports = [ - { - plaziName : 'id', - zenodoName : '', - sqlType : 'INTEGER PRIMARY KEY', - cheerioElement: '', - description : 'pk', - queryable : '', - queryString : '', - validation : '', - resourceId : false - }, + // { + // plaziName : 'id', + // zenodoName : '', + // sqlType : 'INTEGER PRIMARY KEY', + // cheerioElement: '', + // description : 'pk', + // queryable : '', + // queryString : '', + // validation : '', + // resourceId : false + // }, { plaziName : 'treatmentAuthorId', zenodoName : '', diff --git a/dataDictionary/treatmentCitations.js b/dataDictionary/treatmentCitations.js index 10ce3b5..5357c06 100644 --- a/dataDictionary/treatmentCitations.js +++ b/dataDictionary/treatmentCitations.js @@ -1,17 +1,17 @@ 'use strict'; module.exports = [ - { - plaziName : 'id', - zenodoName : '', - sqlType : 'INTEGER PRIMARY KEY', - cheerioElement: '', - description : 'pk', - queryable : '', - queryString : '', - validation : '', - resourceId : false - }, + // { + // plaziName : 'id', + // zenodoName : '', + // sqlType : 'INTEGER PRIMARY KEY', + // cheerioElement: '', + // description : 'pk', + // queryable : '', + // queryString : '', + // validation : '', + // resourceId : false + // }, { plaziName : 'treatmentCitationId', zenodoName : '', diff --git a/dataDictionary/treatments.js b/dataDictionary/treatments.js index 0e6bf0c..a8d15eb 100644 --- a/dataDictionary/treatments.js +++ b/dataDictionary/treatments.js @@ -6,7 +6,7 @@ module.exports = [ zenodoName : '', sqlType : 'INTEGER PRIMARY KEY', cheerioElement: '', - description : 'pk', + description : 'The primary key (PK) for this table', queryable : '', queryString : '', validation : '', @@ -23,6 +23,17 @@ module.exports = [ validation : 'Joi.string().guid().description(`${d}`).optional()', resourceId : true }, + { + plaziName : 'deleted', + zenodoName : '', + sqlType : 'INTEGER DEFAULT 0', + cheerioElement: '$("document").attr("deleted")', + description : 'A boolean that tracks whether or not this resource is considered deleted/revoked, 1 if yes, 0 if no', + queryable : '', + queryString : '', + validation : '', + resourceId : false + }, { plaziName : 'treatmentTitle', zenodoName : 'title', @@ -269,17 +280,6 @@ module.exports = [ validation : 'Joi.string().description(`${d}`).optional()', resourceId : false }, - { - plaziName : 'deleted', - zenodoName : '', - sqlType : 'INTEGER DEFAULT 0', - cheerioElement: '$("document").attr("deleted")', - description : 'A boolean that tracks whether or not this resource is considered deleted/revoked, 1 if yes, 0 if no', - queryable : '', - queryString : '', - validation : '', - resourceId : false - }, { plaziName : 'fulltext', zenodoName : '', diff --git a/index.js b/index.js index d09dfc9..d072427 100644 --- a/index.js +++ b/index.js @@ -1,11 +1,11 @@ -/* -Start this program from the command line with `pm2` +'use strict'; - ~/Nodes/punkish$ NODE_ENV=production pm2 start index.js --name zenodeo - ~/Nodes/punkish$ NODE_ENV=production pm2 restart zenodeo -*/ -'use strict'; +// Start this program from the command line with `pm2` + +// ~/Nodes/punkish$ NODE_ENV=production pm2 start index.js --name zenodeo +// ~/Nodes/punkish$ NODE_ENV=production pm2 restart zenodeo + /*** hapi 18.4.0 *************************************/ const Hapi = require('@hapi/hapi'); @@ -123,7 +123,13 @@ const start = async () => { ]); await server.start(); - console.log('Server running on %s', server.info.uri); + + if (process.env.NODE_ENV) { + console.log('Server running in %s mode on %s', process.env.NODE_ENV.toUpperCase(), server.info.uri); + } + else { + console.log('Server running in DEVELOPMENT mode on %s', server.info.uri); + } server.events.on('log', (event, tags) => { diff --git a/lib/plog.js b/lib/plog.js index 464e9ca..f61249e 100644 --- a/lib/plog.js +++ b/lib/plog.js @@ -26,7 +26,7 @@ const prepareMsg = function(param1, param2) { msg = param2.join(''); } else if (typeof(param2) === 'object') { - msg = JSON.stringify(param2); + msg = JSON.stringify(param2, null, ' '); } else { msg = param2; diff --git a/package-lock.json b/package-lock.json new file mode 100644 index 0000000..e401bd5 --- /dev/null +++ b/package-lock.json @@ -0,0 +1,2318 @@ +{ + "name": "zenodeo", + "version": "2.6.0", + "lockfileVersion": 1, + "requires": true, + "dependencies": { + "@hapi/accept": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/@hapi/accept/-/accept-5.0.1.tgz", + "integrity": "sha512-fMr4d7zLzsAXo28PRRQPXR1o2Wmu+6z+VY1UzDp0iFo13Twj8WePakwXBiqn3E1aAlTpSNzCXdnnQXFhst8h8Q==", + "requires": { + "@hapi/boom": "9.x.x", + "@hapi/hoek": "9.x.x" + } + }, + "@hapi/address": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/@hapi/address/-/address-4.0.1.tgz", + "integrity": "sha512-0oEP5UiyV4f3d6cBL8F3Z5S7iWSX39Knnl0lY8i+6gfmmIBj44JCBNtcMgwyS+5v7j3VYavNay0NFHDS+UGQcw==", + "requires": { + "@hapi/hoek": "^9.0.0" + } + }, + "@hapi/ammo": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/@hapi/ammo/-/ammo-5.0.1.tgz", + "integrity": "sha512-FbCNwcTbnQP4VYYhLNGZmA76xb2aHg9AMPiy18NZyWMG310P5KdFGyA9v2rm5ujrIny77dEEIkMOwl0Xv+fSSA==", + "requires": { + "@hapi/hoek": "9.x.x" + } + }, + "@hapi/b64": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/@hapi/b64/-/b64-5.0.0.tgz", + "integrity": "sha512-ngu0tSEmrezoiIaNGG6rRvKOUkUuDdf4XTPnONHGYfSGRmDqPZX5oJL6HAdKTo1UQHECbdB4OzhWrfgVppjHUw==", + "requires": { + "@hapi/hoek": "9.x.x" + } + }, + "@hapi/boom": { + "version": "9.1.0", + "resolved": "https://registry.npmjs.org/@hapi/boom/-/boom-9.1.0.tgz", + "integrity": "sha512-4nZmpp4tXbm162LaZT45P7F7sgiem8dwAh2vHWT6XX24dozNjGMg6BvKCRvtCUcmcXqeMIUqWN8Rc5X8yKuROQ==", + "requires": { + "@hapi/hoek": "9.x.x" + } + }, + "@hapi/bounce": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/@hapi/bounce/-/bounce-2.0.0.tgz", + "integrity": "sha512-JesW92uyzOOyuzJKjoLHM1ThiOvHPOLDHw01YV8yh5nCso7sDwJho1h0Ad2N+E62bZyz46TG3xhAi/78Gsct6A==", + "requires": { + "@hapi/boom": "9.x.x", + "@hapi/hoek": "9.x.x" + } + }, + "@hapi/bourne": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/@hapi/bourne/-/bourne-2.0.0.tgz", + "integrity": "sha512-WEezM1FWztfbzqIUbsDzFRVMxSoLy3HugVcux6KDDtTqzPsLE8NDRHfXvev66aH1i2oOKKar3/XDjbvh/OUBdg==" + }, + "@hapi/call": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/@hapi/call/-/call-8.0.0.tgz", + "integrity": "sha512-4xHIWWqaIDQlVU88XAnomACSoC7iWUfaLfdu2T7I0y+HFFwZUrKKGfwn6ik4kwKsJRMnOliG3UXsF8V/94+Lkg==", + "requires": { + "@hapi/address": "4.x.x", + "@hapi/boom": "9.x.x", + "@hapi/hoek": "9.x.x" + } + }, + "@hapi/catbox": { + "version": "11.1.0", + "resolved": "https://registry.npmjs.org/@hapi/catbox/-/catbox-11.1.0.tgz", + "integrity": "sha512-FDEjfn26RZRyOEPeZdaAL7dRiAK5FOGuwTnTw0gxK30csAlKeOHsEnoIxnLIXx7QOS17eUaOk6+MiweWQM6Keg==", + "requires": { + "@hapi/boom": "9.x.x", + "@hapi/hoek": "9.x.x", + "@hapi/joi": "17.x.x", + "@hapi/podium": "4.x.x" + } + }, + "@hapi/catbox-memory": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/@hapi/catbox-memory/-/catbox-memory-5.0.0.tgz", + "integrity": "sha512-ByuxVJPHNaXwLzbBv4GdTr6ccpe1nG+AfYt+8ftDWEJY7EWBWzD+Klhy5oPTDGzU26pNUh1e7fcYI1ILZRxAXQ==", + "requires": { + "@hapi/boom": "9.x.x", + "@hapi/hoek": "9.x.x" + } + }, + "@hapi/content": { + "version": "5.0.2", + "resolved": "https://registry.npmjs.org/@hapi/content/-/content-5.0.2.tgz", + "integrity": "sha512-mre4dl1ygd4ZyOH3tiYBrOUBzV7Pu/EOs8VLGf58vtOEECWed8Uuw6B4iR9AN/8uQt42tB04qpVaMyoMQh0oMw==", + "requires": { + "@hapi/boom": "9.x.x" + } + }, + "@hapi/cryptiles": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/@hapi/cryptiles/-/cryptiles-5.0.0.tgz", + "integrity": "sha512-Yq43ti9N51Z7jbm0Q7YVCcofA+4Gh5wsBX/jZ++Z+FM8GYfBQ1WmI9ufZSL+BVX8vRxzDkdQ2fKoG6cxOQlnVQ==", + "requires": { + "@hapi/boom": "9.x.x" + } + }, + "@hapi/file": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/@hapi/file/-/file-2.0.0.tgz", + "integrity": "sha512-WSrlgpvEqgPWkI18kkGELEZfXr0bYLtr16iIN4Krh9sRnzBZN6nnWxHFxtsnP684wueEySBbXPDg/WfA9xJdBQ==" + }, + "@hapi/formula": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/@hapi/formula/-/formula-2.0.0.tgz", + "integrity": "sha512-V87P8fv7PI0LH7LiVi8Lkf3x+KCO7pQozXRssAHNXXL9L1K+uyu4XypLXwxqVDKgyQai6qj3/KteNlrqDx4W5A==" + }, + "@hapi/hapi": { + "version": "19.1.1", + "resolved": "https://registry.npmjs.org/@hapi/hapi/-/hapi-19.1.1.tgz", + "integrity": "sha512-rpQzSs0XsHSF7usM4qdJJ0Bcmhs9stWhUW3OiamW33bw4qL8q3uEgUKB9KH8ODmluCAkkXOQ0X0Dh9t94E5VIw==", + "requires": { + "@hapi/accept": "^5.0.1", + "@hapi/ammo": "^5.0.1", + "@hapi/boom": "9.x.x", + "@hapi/bounce": "2.x.x", + "@hapi/call": "8.x.x", + "@hapi/catbox": "11.x.x", + "@hapi/catbox-memory": "5.x.x", + "@hapi/heavy": "7.x.x", + "@hapi/hoek": "9.x.x", + "@hapi/joi": "17.x.x", + "@hapi/mimos": "5.x.x", + "@hapi/podium": "4.x.x", + "@hapi/shot": "5.x.x", + "@hapi/somever": "3.x.x", + "@hapi/statehood": "^7.0.2", + "@hapi/subtext": "^7.0.3", + "@hapi/teamwork": "4.x.x", + "@hapi/topo": "5.x.x" + } + }, + "@hapi/heavy": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/@hapi/heavy/-/heavy-7.0.0.tgz", + "integrity": "sha512-n/nheUG6zNleWkjY+3fzV3VJIAumUCaa/WoTmurjqlYY5JgC5ZKOpvP7tWi8rXmKZhbcXgjH3fHFoM55LoBT7g==", + "requires": { + "@hapi/boom": "9.x.x", + "@hapi/hoek": "9.x.x", + "@hapi/joi": "17.x.x" + } + }, + "@hapi/hoek": { + "version": "9.0.4", + "resolved": "https://registry.npmjs.org/@hapi/hoek/-/hoek-9.0.4.tgz", + "integrity": "sha512-EwaJS7RjoXUZ2cXXKZZxZqieGtc7RbvQhUy8FwDoMQtxWVi14tFjeFCYPZAM1mBCpOpiBpyaZbb9NeHc7eGKgw==" + }, + "@hapi/inert": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/@hapi/inert/-/inert-6.0.1.tgz", + "integrity": "sha512-oLxAmtWni3nH4INU2gcXFnHBw0GhHYF3HR71hAWrPc91dq+iFYGfawfaMbonwGr5DkzFiGe8Ir5sZAt2AqeINA==", + "requires": { + "@hapi/ammo": "5.x.x", + "@hapi/boom": "9.x.x", + "@hapi/bounce": "2.x.x", + "@hapi/hoek": "9.x.x", + "@hapi/joi": "17.x.x", + "lru-cache": "5.x.x" + } + }, + "@hapi/iron": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/@hapi/iron/-/iron-6.0.0.tgz", + "integrity": "sha512-zvGvWDufiTGpTJPG1Y/McN8UqWBu0k/xs/7l++HVU535NLHXsHhy54cfEMdW7EjwKfbBfM9Xy25FmTiobb7Hvw==", + "requires": { + "@hapi/b64": "5.x.x", + "@hapi/boom": "9.x.x", + "@hapi/bourne": "2.x.x", + "@hapi/cryptiles": "5.x.x", + "@hapi/hoek": "9.x.x" + } + }, + "@hapi/joi": { + "version": "17.1.1", + "resolved": "https://registry.npmjs.org/@hapi/joi/-/joi-17.1.1.tgz", + "integrity": "sha512-p4DKeZAoeZW4g3u7ZeRo+vCDuSDgSvtsB/NpfjXEHTUjSeINAi/RrVOWiVQ1isaoLzMvFEhe8n5065mQq1AdQg==", + "requires": { + "@hapi/address": "^4.0.1", + "@hapi/formula": "^2.0.0", + "@hapi/hoek": "^9.0.0", + "@hapi/pinpoint": "^2.0.0", + "@hapi/topo": "^5.0.0" + } + }, + "@hapi/mimos": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/@hapi/mimos/-/mimos-5.0.0.tgz", + "integrity": "sha512-EVS6wJYeE73InTlPWt+2e3Izn319iIvffDreci3qDNT+t3lA5ylJ0/SoTaID8e0TPNUkHUSsgJZXEmLHvoYzrA==", + "requires": { + "@hapi/hoek": "9.x.x", + "mime-db": "1.x.x" + } + }, + "@hapi/nigel": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/@hapi/nigel/-/nigel-4.0.0.tgz", + "integrity": "sha512-Bqs1pjcDnDQo/XGoiCCNHWTFcMzPbz3L4KU04njeFQMzzEmsojMRX7TX+PezQYCMKtHJOtMg0bHxZyMGqYtbSA==", + "requires": { + "@hapi/hoek": "9.x.x", + "@hapi/vise": "4.x.x" + } + }, + "@hapi/pez": { + "version": "5.0.2", + "resolved": "https://registry.npmjs.org/@hapi/pez/-/pez-5.0.2.tgz", + "integrity": "sha512-jr1lAm8mE7J2IBxvDIuDI1qy2aAsoaD2jxOUd/7JRg/Vmrzco8HdKhtz4fKk6KHU6zbbsAp5m5aSWWVTUrag7g==", + "requires": { + "@hapi/b64": "5.x.x", + "@hapi/boom": "9.x.x", + "@hapi/content": "^5.0.2", + "@hapi/hoek": "9.x.x", + "@hapi/nigel": "4.x.x" + } + }, + "@hapi/pinpoint": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/@hapi/pinpoint/-/pinpoint-2.0.0.tgz", + "integrity": "sha512-vzXR5MY7n4XeIvLpfl3HtE3coZYO4raKXW766R6DZw/6aLqR26iuZ109K7a0NtF2Db0jxqh7xz2AxkUwpUFybw==" + }, + "@hapi/podium": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/@hapi/podium/-/podium-4.1.0.tgz", + "integrity": "sha512-k/n0McAu8PvonfQRLyKKUvvdb+Gh/O5iAeIwv535Hpxw9B1qZcrYdZyWtHZ8O5PkA9/b/Kk+BdvtgcxeKMB/2g==", + "requires": { + "@hapi/hoek": "9.x.x", + "@hapi/joi": "17.x.x", + "@hapi/teamwork": "4.x.x" + } + }, + "@hapi/shot": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/@hapi/shot/-/shot-5.0.0.tgz", + "integrity": "sha512-JXddnJkRh3Xhv9lY1tA+TSIUaoODKbdNIPL/M8WFvFQKOttmGaDeqTW5e8Gf01LtLI7L5DraLMULHjrK1+YNFg==", + "requires": { + "@hapi/hoek": "9.x.x", + "@hapi/joi": "17.x.x" + } + }, + "@hapi/somever": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@hapi/somever/-/somever-3.0.0.tgz", + "integrity": "sha512-Upw/kmKotC9iEmK4y047HMYe4LDKsE5NWfjgX41XNKmFvxsQL7OiaCWVhuyyhU0ShDGBfIAnCH8jZr49z/JzZA==", + "requires": { + "@hapi/bounce": "2.x.x", + "@hapi/hoek": "9.x.x" + } + }, + "@hapi/statehood": { + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/@hapi/statehood/-/statehood-7.0.2.tgz", + "integrity": "sha512-+0VNxysQu+UYzkfvAXq3X4aN65TnUwiR7gsq2cQ/4Rq26nCJjHAfrkYReEeshU2hPmJ3m5QuaBzyDqRm8WOpyg==", + "requires": { + "@hapi/boom": "9.x.x", + "@hapi/bounce": "2.x.x", + "@hapi/bourne": "2.x.x", + "@hapi/cryptiles": "5.x.x", + "@hapi/hoek": "9.x.x", + "@hapi/iron": "6.x.x", + "@hapi/joi": "17.x.x" + } + }, + "@hapi/subtext": { + "version": "7.0.3", + "resolved": "https://registry.npmjs.org/@hapi/subtext/-/subtext-7.0.3.tgz", + "integrity": "sha512-CekDizZkDGERJ01C0+TzHlKtqdXZxzSWTOaH6THBrbOHnsr3GY+yiMZC+AfNCypfE17RaIakGIAbpL2Tk1z2+A==", + "requires": { + "@hapi/boom": "9.x.x", + "@hapi/bourne": "2.x.x", + "@hapi/content": "^5.0.2", + "@hapi/file": "2.x.x", + "@hapi/hoek": "9.x.x", + "@hapi/pez": "^5.0.1", + "@hapi/wreck": "17.x.x" + } + }, + "@hapi/teamwork": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/@hapi/teamwork/-/teamwork-4.0.0.tgz", + "integrity": "sha512-V6xYOrr5aFv/IJqNPneaYCu8vuGTKisamqHVRS3JJnbZr18TrpXdsJOYk9pjPhFti+M2YETPebQLUr820N5NoQ==" + }, + "@hapi/topo": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/@hapi/topo/-/topo-5.0.0.tgz", + "integrity": "sha512-tFJlT47db0kMqVm3H4nQYgn6Pwg10GTZHb1pwmSiv1K4ks6drQOtfEF5ZnPjkvC+y4/bUPHK+bc87QvLcL+WMw==", + "requires": { + "@hapi/hoek": "^9.0.0" + } + }, + "@hapi/vise": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/@hapi/vise/-/vise-4.0.0.tgz", + "integrity": "sha512-eYyLkuUiFZTer59h+SGy7hUm+qE9p+UemePTHLlIWppEd+wExn3Df5jO04bFQTm7nleF5V8CtuYQYb+VFpZ6Sg==", + "requires": { + "@hapi/hoek": "9.x.x" + } + }, + "@hapi/vision": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/@hapi/vision/-/vision-6.0.0.tgz", + "integrity": "sha512-NRG87SLS8evCTwAGlVHykmlk1i9z+7TD2pUwoDHRpjwqX/syt0ecrEKMLV/VdMijE9tCAtKIIXt+Myb16tT7Sw==", + "requires": { + "@hapi/boom": "9.x.x", + "@hapi/bounce": "2.x.x", + "@hapi/hoek": "9.x.x", + "@hapi/joi": "17.x.x" + } + }, + "@hapi/wreck": { + "version": "17.0.0", + "resolved": "https://registry.npmjs.org/@hapi/wreck/-/wreck-17.0.0.tgz", + "integrity": "sha512-d8lqCinbKyDByn7GzJDRDbitddhIEydNm44UcAMejfhEH3o4IYvKYq6K8cAqXbilXPuvZc0ErlUOg9SDdgRtMw==", + "requires": { + "@hapi/boom": "9.x.x", + "@hapi/bourne": "2.x.x", + "@hapi/hoek": "9.x.x" + } + }, + "@sindresorhus/is": { + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/@sindresorhus/is/-/is-0.7.0.tgz", + "integrity": "sha512-ONhaKPIufzzrlNbqtWFFd+jlnemX6lJAgq9ZeiZtS7I1PIf/la7CW4m83rTXRnVnsMbW2k56pGYu7AUFJD9Pow==" + }, + "@types/color-name": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@types/color-name/-/color-name-1.1.1.tgz", + "integrity": "sha512-rr+OQyAjxze7GgWrSaJwydHStIhHq2lvY3BOC2Mj7KnzI7XK0Uw1TOOdI9lDoajEbSWLiYgoo4f1R51erQfhPQ==" + }, + "@types/node": { + "version": "13.11.1", + "resolved": "https://registry.npmjs.org/@types/node/-/node-13.11.1.tgz", + "integrity": "sha512-eWQGP3qtxwL8FGneRrC5DwrJLGN4/dH1clNTuLfN81HCrxVtxRjygDTUoZJ5ASlDEeo0ppYFQjQIlXhtXpOn6g==" + }, + "ansi-regex": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", + "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=" + }, + "ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "requires": { + "color-convert": "^1.9.0" + } + }, + "aproba": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/aproba/-/aproba-1.2.0.tgz", + "integrity": "sha512-Y9J6ZjXtoYh8RnXVCMOU/ttDmk1aBjunq9vO0ta5x85WDQiQfUF9sIPBITdbiiIVcBo03Hi3jMxigBtsddlXRw==" + }, + "archive-type": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/archive-type/-/archive-type-4.0.0.tgz", + "integrity": "sha1-+S5yIzBW38aWlHJ0nCZ72wRrHXA=", + "requires": { + "file-type": "^4.2.0" + }, + "dependencies": { + "file-type": { + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/file-type/-/file-type-4.4.0.tgz", + "integrity": "sha1-G2AOX8ofvcboDApwxxyNul95BsU=" + } + } + }, + "are-we-there-yet": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/are-we-there-yet/-/are-we-there-yet-1.1.5.tgz", + "integrity": "sha512-5hYdAkZlcG8tOLujVDTgCT+uPX0VnpAH28gWsLfzpXYm7wP6mp5Q/gYyR7YQ0cKVJcXJnl3j2kpBan13PtQf6w==", + "requires": { + "delegates": "^1.0.0", + "readable-stream": "^2.0.6" + } + }, + "argparse": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", + "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", + "requires": { + "sprintf-js": "~1.0.2" + } + }, + "base64-js": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.3.1.tgz", + "integrity": "sha512-mLQ4i2QO1ytvGWFWmcngKO//JXAQueZvwEKtjgQFM4jIK0kU+ytMfplL8j+n5mspOfjHwoAg+9yhb7BwAHm36g==" + }, + "better-sqlite3": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/better-sqlite3/-/better-sqlite3-6.0.1.tgz", + "integrity": "sha512-4aV1zEknM9g1a6B0mVBx1oIlmYioEJ8gSS3J6EpN1b1bKYEE+N5lmpmXHKNKTi0qjHziSd7XrXwHl1kpqvEcHQ==", + "requires": { + "bindings": "^1.5.0", + "integer": "^3.0.1", + "prebuild-install": "^5.3.3", + "tar": "4.4.10" + } + }, + "bindings": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/bindings/-/bindings-1.5.0.tgz", + "integrity": "sha512-p2q/t/mhvuOj/UeLlV6566GD/guowlr0hHxClI0W9m7MWYkL1F0hLo+0Aexs9HSPCtR1SXQ0TD3MMKrXZajbiQ==", + "requires": { + "file-uri-to-path": "1.0.0" + } + }, + "bl": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/bl/-/bl-4.0.2.tgz", + "integrity": "sha512-j4OH8f6Qg2bGuWfRiltT2HYGx0e1QcBTrK9KAHNMwMZdQnDZFk0ZSYIpADjYCB3U12nicC5tVJwSIhwOWjb4RQ==", + "requires": { + "buffer": "^5.5.0", + "inherits": "^2.0.4", + "readable-stream": "^3.4.0" + }, + "dependencies": { + "readable-stream": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", + "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", + "requires": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + } + } + } + }, + "blipp": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/blipp/-/blipp-4.0.1.tgz", + "integrity": "sha512-nmtErzngVgJF6HlpnEymOil23m5U82oTYhbU8m619kQzj8yJ2q1ZFbL45i+dBcO92XTocyyj3QtC3GMxRujv8w==", + "requires": { + "@hapi/hoek": "8.x.x", + "@hapi/joi": "15.x.x", + "chalk": "2.x.x", + "easy-table": "1.x.x" + }, + "dependencies": { + "@hapi/address": { + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/@hapi/address/-/address-2.1.4.tgz", + "integrity": "sha512-QD1PhQk+s31P1ixsX0H0Suoupp3VMXzIVMSwobR3F3MSUO2YCV0B7xqLcUw/Bh8yuvd3LhpyqLQWTNcRmp6IdQ==" + }, + "@hapi/bourne": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/@hapi/bourne/-/bourne-1.3.2.tgz", + "integrity": "sha512-1dVNHT76Uu5N3eJNTYcvxee+jzX4Z9lfciqRRHCU27ihbUcYi+iSc2iml5Ke1LXe1SyJCLA0+14Jh4tXJgOppA==" + }, + "@hapi/hoek": { + "version": "8.5.1", + "resolved": "https://registry.npmjs.org/@hapi/hoek/-/hoek-8.5.1.tgz", + "integrity": "sha512-yN7kbciD87WzLGc5539Tn0sApjyiGHAJgKvG9W8C7O+6c7qmoQMfVs0W4bX17eqz6C78QJqqFrtgdK5EWf6Qow==" + }, + "@hapi/joi": { + "version": "15.1.1", + "resolved": "https://registry.npmjs.org/@hapi/joi/-/joi-15.1.1.tgz", + "integrity": "sha512-entf8ZMOK8sc+8YfeOlM8pCfg3b5+WZIKBfUaaJT8UsjAAPjartzxIYm3TIbjvA4u+u++KbcXD38k682nVHDAQ==", + "requires": { + "@hapi/address": "2.x.x", + "@hapi/bourne": "1.x.x", + "@hapi/hoek": "8.x.x", + "@hapi/topo": "3.x.x" + } + }, + "@hapi/topo": { + "version": "3.1.6", + "resolved": "https://registry.npmjs.org/@hapi/topo/-/topo-3.1.6.tgz", + "integrity": "sha512-tAag0jEcjwH+P2quUfipd7liWCNX2F8NvYjQp2wtInsZxnMlypdw0FtAOLxtvvkO+GSRRbmNi8m/5y42PQJYCQ==", + "requires": { + "@hapi/hoek": "^8.3.0" + } + }, + "chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "requires": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + } + } + } + }, + "boolbase": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/boolbase/-/boolbase-1.0.0.tgz", + "integrity": "sha1-aN/1++YMUes3cl6p4+0xDcwed24=" + }, + "boom": { + "version": "7.3.0", + "resolved": "https://registry.npmjs.org/boom/-/boom-7.3.0.tgz", + "integrity": "sha512-Swpoyi2t5+GhOEGw8rEsKvTxFLIDiiKoUc2gsoV6Lyr43LHBIzch3k2MvYUs8RTROrIkVJ3Al0TkaOGjnb+B6A==", + "requires": { + "hoek": "6.x.x" + } + }, + "buffer": { + "version": "5.6.0", + "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.6.0.tgz", + "integrity": "sha512-/gDYp/UtU0eA1ys8bOs9J6a+E/KWIY+DZ+Q2WESNUA0jFRsJOc0SNUO6xJ5SGA1xueg3NL65W6s+NY5l9cunuw==", + "requires": { + "base64-js": "^1.0.2", + "ieee754": "^1.1.4" + } + }, + "buffer-alloc": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/buffer-alloc/-/buffer-alloc-1.2.0.tgz", + "integrity": "sha512-CFsHQgjtW1UChdXgbyJGtnm+O/uLQeZdtbDo8mfUgYXCHSM1wgrVxXm6bSyrUuErEb+4sYVGCzASBRot7zyrow==", + "requires": { + "buffer-alloc-unsafe": "^1.1.0", + "buffer-fill": "^1.0.0" + } + }, + "buffer-alloc-unsafe": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/buffer-alloc-unsafe/-/buffer-alloc-unsafe-1.1.0.tgz", + "integrity": "sha512-TEM2iMIEQdJ2yjPJoSIsldnleVaAk1oW3DBVUykyOLsEsFmEc9kn+SFFPz+gl54KQNxlDnAwCXosOS9Okx2xAg==" + }, + "buffer-crc32": { + "version": "0.2.13", + "resolved": "https://registry.npmjs.org/buffer-crc32/-/buffer-crc32-0.2.13.tgz", + "integrity": "sha1-DTM+PwDqxQqhRUq9MO+MKl2ackI=" + }, + "buffer-fill": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/buffer-fill/-/buffer-fill-1.0.0.tgz", + "integrity": "sha1-+PeLdniYiO858gXNY39o5wISKyw=" + }, + "cacheable-request": { + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/cacheable-request/-/cacheable-request-2.1.4.tgz", + "integrity": "sha1-DYCIAbY0KtM8kd+dC0TcCbkeXD0=", + "requires": { + "clone-response": "1.0.2", + "get-stream": "3.0.0", + "http-cache-semantics": "3.8.1", + "keyv": "3.0.0", + "lowercase-keys": "1.0.0", + "normalize-url": "2.0.1", + "responselike": "1.0.2" + }, + "dependencies": { + "lowercase-keys": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/lowercase-keys/-/lowercase-keys-1.0.0.tgz", + "integrity": "sha1-TjNms55/VFfjXxMkvfb4jQv8cwY=" + } + } + }, + "call-me-maybe": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/call-me-maybe/-/call-me-maybe-1.0.1.tgz", + "integrity": "sha1-JtII6onje1y95gJQoV8DHBak1ms=" + }, + "camelcase": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-4.1.0.tgz", + "integrity": "sha1-1UVjW+HjPFQmScaRc+Xeas+uNN0=" + }, + "catbox": { + "version": "10.0.6", + "resolved": "https://registry.npmjs.org/catbox/-/catbox-10.0.6.tgz", + "integrity": "sha512-gQWCnF/jbHcfwGbQ4FQxyRiAwLRipqWTTXjpq7rTqqdcsnZosFa0L3LsCZcPTF33QIeMMkS7QmFBHt6QdzGPvg==", + "requires": { + "boom": "7.x.x", + "hoek": "6.x.x", + "joi": "14.x.x" + } + }, + "catbox-disk": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/catbox-disk/-/catbox-disk-3.0.2.tgz", + "integrity": "sha512-7NUkO/XhE1sEdRDr5F6rGZyIZptwk6I9z42MJ4VTOzjdthI5r5EoOff3J+aKuSO90fTjm4asPYrGmVRvVJB5Bg==", + "requires": { + "catbox": "^10.x.x", + "hoek": "^6.x.x", + "mkdirp": "0.5.x", + "walk": "^2.x.x" + }, + "dependencies": { + "mkdirp": { + "version": "0.5.5", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.5.tgz", + "integrity": "sha512-NKmAlESf6jMGym1++R0Ra7wvhV+wFW63FaSOFPwRahvea0gMUcGUhVeAg/0BC0wiv9ih5NYPB1Wn1UEI1/L+xQ==", + "requires": { + "minimist": "^1.2.5" + } + } + } + }, + "caw": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/caw/-/caw-2.0.1.tgz", + "integrity": "sha512-Cg8/ZSBEa8ZVY9HspcGUYaK63d/bN7rqS3CYCzEGUxuYv6UlmcjzDUz2fCFFHyTvUW5Pk0I+3hkA3iXlIj6guA==", + "requires": { + "get-proxy": "^2.0.0", + "isurl": "^1.0.0-alpha5", + "tunnel-agent": "^0.6.0", + "url-to-options": "^1.0.1" + } + }, + "chalk": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.0.0.tgz", + "integrity": "sha512-N9oWFcegS0sFr9oh1oz2d7Npos6vNoWW9HvtCg5N1KRFpUhaAhvTv5Y58g880fZaEYSNm3qDz8SU1UrGvp+n7A==", + "requires": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "dependencies": { + "ansi-styles": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.2.1.tgz", + "integrity": "sha512-9VGjrMsG1vePxcSweQsN20KY/c4zN0h9fLjqAbwbPfahM3t+NL+M9HC8xeXG2I8pX5NoamTGNuomEUFI7fcUjA==", + "requires": { + "@types/color-name": "^1.1.1", + "color-convert": "^2.0.1" + } + }, + "color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "requires": { + "color-name": "~1.1.4" + } + }, + "color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" + }, + "has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==" + }, + "supports-color": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.1.0.tgz", + "integrity": "sha512-oRSIpR8pxT1Wr2FquTNnGet79b3BWljqOuoW/h4oBhxJ/HUbX5nX6JSruTkvXDCFMwDPvsaTTbvMLKZWSy0R5g==", + "requires": { + "has-flag": "^4.0.0" + } + } + } + }, + "chance": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/chance/-/chance-1.1.4.tgz", + "integrity": "sha512-pXPDSu3knKlb6H7ahQfpq//J9mSOxYK8SMtp8MV/nRJh8aLRDIl0ipLH8At8+nVogVwtvPZzyIzY/EbcY/cLuQ==" + }, + "cheerio": { + "version": "1.0.0-rc.3", + "resolved": "https://registry.npmjs.org/cheerio/-/cheerio-1.0.0-rc.3.tgz", + "integrity": "sha512-0td5ijfUPuubwLUu0OBoe98gZj8C/AA+RW3v67GPlGOrvxWjZmBXiBCRU+I8VEiNyJzjth40POfHiz2RB3gImA==", + "requires": { + "css-select": "~1.2.0", + "dom-serializer": "~0.1.1", + "entities": "~1.1.1", + "htmlparser2": "^3.9.1", + "lodash": "^4.15.0", + "parse5": "^3.0.1" + } + }, + "chownr": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/chownr/-/chownr-1.1.4.tgz", + "integrity": "sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg==" + }, + "clone": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/clone/-/clone-1.0.4.tgz", + "integrity": "sha1-2jCcwmPfFZlMaIypAheco8fNfH4=", + "optional": true + }, + "clone-response": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/clone-response/-/clone-response-1.0.2.tgz", + "integrity": "sha1-0dyXOSAxTfZ/vrlCI7TuNQI56Ws=", + "requires": { + "mimic-response": "^1.0.0" + }, + "dependencies": { + "mimic-response": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-1.0.1.tgz", + "integrity": "sha512-j5EctnkH7amfV/q5Hgmoal1g2QHFJRraOtmx0JpIqkxhBhI/lJSl1nMpQ45hVarwNETOoWEimndZ4QK0RHxuxQ==" + } + } + }, + "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-convert": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", + "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", + "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=" + }, + "commander": { + "version": "2.8.1", + "resolved": "https://registry.npmjs.org/commander/-/commander-2.8.1.tgz", + "integrity": "sha1-Br42f+v9oMMwqh4qBy09yXYkJdQ=", + "requires": { + "graceful-readlink": ">= 1.0.0" + } + }, + "config": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/config/-/config-3.3.1.tgz", + "integrity": "sha512-+2/KaaaAzdwUBE3jgZON11L1ggLLhpf2FsGrfqYFHZW22ySGv/HqYIXrBwKKvn+XZh1UBUjHwAcrfsSkSygT+Q==", + "requires": { + "json5": "^2.1.1" + } + }, + "config-chain": { + "version": "1.1.12", + "resolved": "https://registry.npmjs.org/config-chain/-/config-chain-1.1.12.tgz", + "integrity": "sha512-a1eOIcu8+7lUInge4Rpf/n4Krkf3Dd9lqhljRzII1/Zno/kRtUWnznPO3jOKBmTEktkt3fkxisUcivoj0ebzoA==", + "requires": { + "ini": "^1.3.4", + "proto-list": "~1.2.1" + } + }, + "console-control-strings": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/console-control-strings/-/console-control-strings-1.1.0.tgz", + "integrity": "sha1-PXz0Rk22RG6mRL9LOVB/mFEAjo4=" + }, + "content-disposition": { + "version": "0.5.3", + "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.3.tgz", + "integrity": "sha512-ExO0774ikEObIAEV9kDo50o+79VCUdEB6n6lzKgGwupcVeRlhrj3qGAfwq8G6uBJjkqLrhT0qEYFcWng8z1z0g==", + "requires": { + "safe-buffer": "5.1.2" + } + }, + "core-js": { + "version": "2.6.11", + "resolved": "https://registry.npmjs.org/core-js/-/core-js-2.6.11.tgz", + "integrity": "sha512-5wjnpaT/3dV+XB4borEsnAYQchn00XSgTAWKDkEqv+K8KevjbzmofK6hfJ9TZIlpj2N0xQpazy7PiRQiWHqzWg==" + }, + "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=" + }, + "cross-fetch": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/cross-fetch/-/cross-fetch-3.0.4.tgz", + "integrity": "sha512-MSHgpjQqgbT/94D4CyADeNoYh52zMkCX4pcJvPP5WqPsLFMKjr2TCMg381ox5qI0ii2dPwaLx/00477knXqXVw==", + "requires": { + "node-fetch": "2.6.0", + "whatwg-fetch": "3.0.0" + } + }, + "css-select": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/css-select/-/css-select-1.2.0.tgz", + "integrity": "sha1-KzoRBTnFNV8c2NMUYj6HCxIeyFg=", + "requires": { + "boolbase": "~1.0.0", + "css-what": "2.1", + "domutils": "1.5.1", + "nth-check": "~1.0.1" + } + }, + "css-what": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/css-what/-/css-what-2.1.3.tgz", + "integrity": "sha512-a+EPoD+uZiNfh+5fxw2nO9QwFa6nJe2Or35fGY6Ipw1R3R4AGz1d1TEZrCegvw2YTmZ0jXirGYlzxxpYSHwpEg==" + }, + "csvjson": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/csvjson/-/csvjson-5.1.0.tgz", + "integrity": "sha512-OqALQHA0k2rEGluOWikwFq5qtkRUDyoWP2u0UJy8uFjFx5FPMjPzx7D2Hn2KjBLpc8jkGrT9HDNgTUfopDlqVg==" + }, + "debug": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz", + "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==", + "requires": { + "ms": "^2.1.1" + } + }, + "decode-uri-component": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/decode-uri-component/-/decode-uri-component-0.2.0.tgz", + "integrity": "sha1-6zkTMzRYd1y4TNGh+uBiEGu4dUU=" + }, + "decompress": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/decompress/-/decompress-4.2.1.tgz", + "integrity": "sha512-e48kc2IjU+2Zw8cTb6VZcJQ3lgVbS4uuB1TfCHbiZIP/haNXm+SVyhu+87jts5/3ROpd82GSVCoNs/z8l4ZOaQ==", + "requires": { + "decompress-tar": "^4.0.0", + "decompress-tarbz2": "^4.0.0", + "decompress-targz": "^4.0.0", + "decompress-unzip": "^4.0.1", + "graceful-fs": "^4.1.10", + "make-dir": "^1.0.0", + "pify": "^2.3.0", + "strip-dirs": "^2.0.0" + }, + "dependencies": { + "pify": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", + "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=" + } + } + }, + "decompress-response": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/decompress-response/-/decompress-response-4.2.1.tgz", + "integrity": "sha512-jOSne2qbyE+/r8G1VU+G/82LBs2Fs4LAsTiLSHOCOMZQl2OKZ6i8i4IyHemTe+/yIXOtTcRQMzPcgyhoFlqPkw==", + "requires": { + "mimic-response": "^2.0.0" + } + }, + "decompress-tar": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/decompress-tar/-/decompress-tar-4.1.1.tgz", + "integrity": "sha512-JdJMaCrGpB5fESVyxwpCx4Jdj2AagLmv3y58Qy4GE6HMVjWz1FeVQk1Ct4Kye7PftcdOo/7U7UKzYBJgqnGeUQ==", + "requires": { + "file-type": "^5.2.0", + "is-stream": "^1.1.0", + "tar-stream": "^1.5.2" + }, + "dependencies": { + "bl": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/bl/-/bl-1.2.2.tgz", + "integrity": "sha512-e8tQYnZodmebYDWGH7KMRvtzKXaJHx3BbilrgZCfvyLUYdKpK1t5PSPmpkny/SgiTSCnjfLW7v5rlONXVFkQEA==", + "requires": { + "readable-stream": "^2.3.5", + "safe-buffer": "^5.1.1" + } + }, + "file-type": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/file-type/-/file-type-5.2.0.tgz", + "integrity": "sha1-LdvqfHP/42No365J3DOMBYwritY=" + }, + "tar-stream": { + "version": "1.6.2", + "resolved": "https://registry.npmjs.org/tar-stream/-/tar-stream-1.6.2.tgz", + "integrity": "sha512-rzS0heiNf8Xn7/mpdSVVSMAWAoy9bfb1WOTYC78Z0UQKeKa/CWS8FOq0lKGNa8DWKAn9gxjCvMLYc5PGXYlK2A==", + "requires": { + "bl": "^1.0.0", + "buffer-alloc": "^1.2.0", + "end-of-stream": "^1.0.0", + "fs-constants": "^1.0.0", + "readable-stream": "^2.3.0", + "to-buffer": "^1.1.1", + "xtend": "^4.0.0" + } + } + } + }, + "decompress-tarbz2": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/decompress-tarbz2/-/decompress-tarbz2-4.1.1.tgz", + "integrity": "sha512-s88xLzf1r81ICXLAVQVzaN6ZmX4A6U4z2nMbOwobxkLoIIfjVMBg7TeguTUXkKeXni795B6y5rnvDw7rxhAq9A==", + "requires": { + "decompress-tar": "^4.1.0", + "file-type": "^6.1.0", + "is-stream": "^1.1.0", + "seek-bzip": "^1.0.5", + "unbzip2-stream": "^1.0.9" + }, + "dependencies": { + "file-type": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/file-type/-/file-type-6.2.0.tgz", + "integrity": "sha512-YPcTBDV+2Tm0VqjybVd32MHdlEGAtuxS3VAYsumFokDSMG+ROT5wawGlnHDoz7bfMcMDt9hxuXvXwoKUx2fkOg==" + } + } + }, + "decompress-targz": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/decompress-targz/-/decompress-targz-4.1.1.tgz", + "integrity": "sha512-4z81Znfr6chWnRDNfFNqLwPvm4db3WuZkqV+UgXQzSngG3CEKdBkw5jrv3axjjL96glyiiKjsxJG3X6WBZwX3w==", + "requires": { + "decompress-tar": "^4.1.1", + "file-type": "^5.2.0", + "is-stream": "^1.1.0" + }, + "dependencies": { + "file-type": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/file-type/-/file-type-5.2.0.tgz", + "integrity": "sha1-LdvqfHP/42No365J3DOMBYwritY=" + } + } + }, + "decompress-unzip": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/decompress-unzip/-/decompress-unzip-4.0.1.tgz", + "integrity": "sha1-3qrM39FK6vhVePczroIQ+bSEj2k=", + "requires": { + "file-type": "^3.8.0", + "get-stream": "^2.2.0", + "pify": "^2.3.0", + "yauzl": "^2.4.2" + }, + "dependencies": { + "file-type": { + "version": "3.9.0", + "resolved": "https://registry.npmjs.org/file-type/-/file-type-3.9.0.tgz", + "integrity": "sha1-JXoHg4TR24CHvESdEH1SpSZyuek=" + }, + "get-stream": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-2.3.1.tgz", + "integrity": "sha1-Xzj5PzRgCWZu4BUKBUFn+Rvdld4=", + "requires": { + "object-assign": "^4.0.1", + "pinkie-promise": "^2.0.0" + } + }, + "pify": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", + "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=" + } + } + }, + "deep-extend": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/deep-extend/-/deep-extend-0.6.0.tgz", + "integrity": "sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA==" + }, + "defaults": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/defaults/-/defaults-1.0.3.tgz", + "integrity": "sha1-xlYFHpgX2f8I7YgUd/P+QBnz730=", + "optional": true, + "requires": { + "clone": "^1.0.2" + } + }, + "delegates": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delegates/-/delegates-1.0.0.tgz", + "integrity": "sha1-hMbhWbgZBP3KWaDvRM2HDTElD5o=" + }, + "detect-libc": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-1.0.3.tgz", + "integrity": "sha1-+hN8S9aY7fVc1c0CrFWfkaTEups=" + }, + "dom-serializer": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-0.1.1.tgz", + "integrity": "sha512-l0IU0pPzLWSHBcieZbpOKgkIn3ts3vAh7ZuFyXNwJxJXk/c4Gwj9xaTJwIDVQCXawWD0qb3IzMGH5rglQaO0XA==", + "requires": { + "domelementtype": "^1.3.0", + "entities": "^1.1.1" + } + }, + "domelementtype": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-1.3.1.tgz", + "integrity": "sha512-BSKB+TSpMpFI/HOxCNr1O8aMOTZ8hT3pM3GQ0w/mWRmkhEDSFJkkyzz4XQsBV44BChwGkrDfMyjVD0eA2aFV3w==" + }, + "domhandler": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/domhandler/-/domhandler-2.4.2.tgz", + "integrity": "sha512-JiK04h0Ht5u/80fdLMCEmV4zkNh2BcoMFBmZ/91WtYZ8qVXSKjiw7fXMgFPnHcSZgOo3XdinHvmnDUeMf5R4wA==", + "requires": { + "domelementtype": "1" + } + }, + "domutils": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/domutils/-/domutils-1.5.1.tgz", + "integrity": "sha1-3NhIiib1Y9YQeeSMn3t+Mjc2gs8=", + "requires": { + "dom-serializer": "0", + "domelementtype": "1" + } + }, + "download": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/download/-/download-7.1.0.tgz", + "integrity": "sha512-xqnBTVd/E+GxJVrX5/eUJiLYjCGPwMpdL+jGhGU57BvtcA7wwhtHVbXBeUk51kOpW3S7Jn3BQbN9Q1R1Km2qDQ==", + "requires": { + "archive-type": "^4.0.0", + "caw": "^2.0.1", + "content-disposition": "^0.5.2", + "decompress": "^4.2.0", + "ext-name": "^5.0.0", + "file-type": "^8.1.0", + "filenamify": "^2.0.0", + "get-stream": "^3.0.0", + "got": "^8.3.1", + "make-dir": "^1.2.0", + "p-event": "^2.1.0", + "pify": "^3.0.0" + } + }, + "duplexer3": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/duplexer3/-/duplexer3-0.1.4.tgz", + "integrity": "sha1-7gHdHKwO08vH/b6jfcCo8c4ALOI=" + }, + "easy-table": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/easy-table/-/easy-table-1.1.1.tgz", + "integrity": "sha512-C9Lvm0WFcn2RgxbMnTbXZenMIWcBtkzMr+dWqq/JsVoGFSVUVlPqeOa5LP5kM0I3zoOazFpckOEb2/0LDFfToQ==", + "requires": { + "ansi-regex": "^3.0.0", + "wcwidth": ">=1.0.1" + }, + "dependencies": { + "ansi-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz", + "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=" + } + } + }, + "end-of-stream": { + "version": "1.4.4", + "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.4.tgz", + "integrity": "sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==", + "requires": { + "once": "^1.4.0" + } + }, + "entities": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/entities/-/entities-1.1.2.tgz", + "integrity": "sha512-f2LZMYl1Fzu7YSBKg+RoROelpOaNrcGmE9AZubeDfrCEia483oW4MI4VyFd5VNHIgQ/7qm1I0wUHK1eJnn2y2w==" + }, + "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=" + }, + "esprima": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", + "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==" + }, + "expand-template": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/expand-template/-/expand-template-2.0.3.tgz", + "integrity": "sha512-XYfuKMvj4O35f/pOXLObndIRvyQ+/+6AhODh+OKWj9S9498pHHn/IMszH+gt0fBCRWMNfk1ZSp5x3AifmnI2vg==" + }, + "ext-list": { + "version": "2.2.2", + "resolved": "https://registry.npmjs.org/ext-list/-/ext-list-2.2.2.tgz", + "integrity": "sha512-u+SQgsubraE6zItfVA0tBuCBhfU9ogSRnsvygI7wht9TS510oLkBRXBsqopeUG/GBOIQyKZO9wjTqIu/sf5zFA==", + "requires": { + "mime-db": "^1.28.0" + } + }, + "ext-name": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/ext-name/-/ext-name-5.0.0.tgz", + "integrity": "sha512-yblEwXAbGv1VQDmow7s38W77hzAgJAO50ztBLMcUyUBfxv1HC+LGwtiEN+Co6LtlqT/5uwVOxsD4TNIilWhwdQ==", + "requires": { + "ext-list": "^2.0.0", + "sort-keys-length": "^1.0.0" + } + }, + "fd-slicer": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/fd-slicer/-/fd-slicer-1.1.0.tgz", + "integrity": "sha1-JcfInLH5B3+IkbvmHY85Dq4lbx4=", + "requires": { + "pend": "~1.2.0" + } + }, + "file-type": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/file-type/-/file-type-8.1.0.tgz", + "integrity": "sha512-qyQ0pzAy78gVoJsmYeNgl8uH8yKhr1lVhW7JbzJmnlRi0I4R2eEDEJZVKG8agpDnLpacwNbDhLNG/LMdxHD2YQ==" + }, + "file-uri-to-path": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/file-uri-to-path/-/file-uri-to-path-1.0.0.tgz", + "integrity": "sha512-0Zt+s3L7Vf1biwWZ29aARiVYLx7iMGnEUl9x33fbB/j3jR81u/O2LbqK+Bm1CDSNDKVtJ/YjwY7TUd5SkeLQLw==" + }, + "filename-reserved-regex": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/filename-reserved-regex/-/filename-reserved-regex-2.0.0.tgz", + "integrity": "sha1-q/c9+rc10EVECr/qLZHzieu/oik=" + }, + "filenamify": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/filenamify/-/filenamify-2.1.0.tgz", + "integrity": "sha512-ICw7NTT6RsDp2rnYKVd8Fu4cr6ITzGy3+u4vUujPkabyaz+03F24NWEX7fs5fp+kBonlaqPH8fAO2NM+SXt/JA==", + "requires": { + "filename-reserved-regex": "^2.0.0", + "strip-outer": "^1.0.0", + "trim-repeated": "^1.0.0" + } + }, + "foreachasync": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/foreachasync/-/foreachasync-3.0.0.tgz", + "integrity": "sha1-VQKYfchxS+M5IJfzLgBxyd7gfPY=" + }, + "format-util": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/format-util/-/format-util-1.0.5.tgz", + "integrity": "sha512-varLbTj0e0yVyRpqQhuWV+8hlePAgaoFRhNFj50BNjEIrw1/DphHSObtqwskVCPWNgzwPoQrZAbfa/SBiicNeg==" + }, + "from2": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/from2/-/from2-2.3.0.tgz", + "integrity": "sha1-i/tVAr3kpNNs/e6gB/zKIdfjgq8=", + "requires": { + "inherits": "^2.0.1", + "readable-stream": "^2.0.0" + } + }, + "fs-constants": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs-constants/-/fs-constants-1.0.0.tgz", + "integrity": "sha512-y6OAwoSIf7FyjMIv94u+b5rdheZEjzR63GTyZJm5qh4Bi+2YgwLCcI/fPFZkL5PSixOt6ZNKm+w+Hfp/Bciwow==" + }, + "fs-minipass": { + "version": "1.2.7", + "resolved": "https://registry.npmjs.org/fs-minipass/-/fs-minipass-1.2.7.tgz", + "integrity": "sha512-GWSSJGFy4e9GUeCcbIkED+bgAoFyj7XF1mV8rma3QW4NIqX9Kyx79N/PF61H5udOV3aY1IaMLs6pGbH71nlCTA==", + "requires": { + "minipass": "^2.6.0" + } + }, + "gauge": { + "version": "2.7.4", + "resolved": "https://registry.npmjs.org/gauge/-/gauge-2.7.4.tgz", + "integrity": "sha1-LANAXHU4w51+s3sxcCLjJfsBi/c=", + "requires": { + "aproba": "^1.0.3", + "console-control-strings": "^1.0.0", + "has-unicode": "^2.0.0", + "object-assign": "^4.1.0", + "signal-exit": "^3.0.0", + "string-width": "^1.0.1", + "strip-ansi": "^3.0.1", + "wide-align": "^1.1.0" + } + }, + "get-proxy": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/get-proxy/-/get-proxy-2.1.0.tgz", + "integrity": "sha512-zmZIaQTWnNQb4R4fJUEp/FC51eZsc6EkErspy3xtIYStaq8EB/hDIWipxsal+E8rz0qD7f2sL/NA9Xee4RInJw==", + "requires": { + "npm-conf": "^1.1.0" + } + }, + "get-stream": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-3.0.0.tgz", + "integrity": "sha1-jpQ9E1jcN1VQVOy+LtsFqhdO3hQ=" + }, + "github-from-package": { + "version": "0.0.0", + "resolved": "https://registry.npmjs.org/github-from-package/-/github-from-package-0.0.0.tgz", + "integrity": "sha1-l/tdlr/eiXMxPyDoKI75oWf6ZM4=" + }, + "got": { + "version": "8.3.2", + "resolved": "https://registry.npmjs.org/got/-/got-8.3.2.tgz", + "integrity": "sha512-qjUJ5U/hawxosMryILofZCkm3C84PLJS/0grRIpjAwu+Lkxxj5cxeCU25BG0/3mDSpXKTyZr8oh8wIgLaH0QCw==", + "requires": { + "@sindresorhus/is": "^0.7.0", + "cacheable-request": "^2.1.1", + "decompress-response": "^3.3.0", + "duplexer3": "^0.1.4", + "get-stream": "^3.0.0", + "into-stream": "^3.1.0", + "is-retry-allowed": "^1.1.0", + "isurl": "^1.0.0-alpha5", + "lowercase-keys": "^1.0.0", + "mimic-response": "^1.0.0", + "p-cancelable": "^0.4.0", + "p-timeout": "^2.0.1", + "pify": "^3.0.0", + "safe-buffer": "^5.1.1", + "timed-out": "^4.0.1", + "url-parse-lax": "^3.0.0", + "url-to-options": "^1.0.1" + }, + "dependencies": { + "decompress-response": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/decompress-response/-/decompress-response-3.3.0.tgz", + "integrity": "sha1-gKTdMjdIOEv6JICDYirt7Jgq3/M=", + "requires": { + "mimic-response": "^1.0.0" + } + }, + "mimic-response": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-1.0.1.tgz", + "integrity": "sha512-j5EctnkH7amfV/q5Hgmoal1g2QHFJRraOtmx0JpIqkxhBhI/lJSl1nMpQ45hVarwNETOoWEimndZ4QK0RHxuxQ==" + } + } + }, + "graceful-fs": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.3.tgz", + "integrity": "sha512-a30VEBm4PEdx1dRB7MFK7BejejvCvBronbLjht+sHuGYj8PHs7M/5Z+rt5lw551vZ7yfTCj4Vuyy3mSJytDWRQ==" + }, + "graceful-readlink": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/graceful-readlink/-/graceful-readlink-1.0.1.tgz", + "integrity": "sha1-TK+tdrxi8C+gObL5Tpo906ORpyU=" + }, + "handlebars": { + "version": "4.7.6", + "resolved": "https://registry.npmjs.org/handlebars/-/handlebars-4.7.6.tgz", + "integrity": "sha512-1f2BACcBfiwAfStCKZNrUCgqNZkGsAT7UM3kkYtXuLo0KnaVfjKOyf7PRzB6++aK9STyT1Pd2ZCPe3EGOXleXA==", + "requires": { + "minimist": "^1.2.5", + "neo-async": "^2.6.0", + "source-map": "^0.6.1", + "uglify-js": "^3.1.4", + "wordwrap": "^1.0.0" + } + }, + "hapi-swagger": { + "version": "13.0.0", + "resolved": "https://registry.npmjs.org/hapi-swagger/-/hapi-swagger-13.0.0.tgz", + "integrity": "sha512-DlnfmjcWnrUapVLjwxZzjwQHDrLX/HGLmKHdzkpCx6nzKh36GbeerPNE7wvCghvWyzwxq7fEbgZPsqOlNvsLSA==", + "requires": { + "@hapi/boom": "^8.0.1", + "@hapi/hoek": "^9.0.2", + "handlebars": "^4.5.3", + "http-status": "^1.0.1", + "json-schema-ref-parser": "^6.1.0", + "swagger-parser": "4.0.2", + "swagger-ui-dist": "^3.22.1" + }, + "dependencies": { + "@hapi/boom": { + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/@hapi/boom/-/boom-8.0.1.tgz", + "integrity": "sha512-SnBM2GzEYEA6AGFKXBqNLWXR3uNBui0bkmklYXX1gYtevVhDTy2uakwkSauxvIWMtlANGRhzChYg95If3FWCwA==", + "requires": { + "@hapi/hoek": "8.x.x" + }, + "dependencies": { + "@hapi/hoek": { + "version": "8.5.1", + "resolved": "https://registry.npmjs.org/@hapi/hoek/-/hoek-8.5.1.tgz", + "integrity": "sha512-yN7kbciD87WzLGc5539Tn0sApjyiGHAJgKvG9W8C7O+6c7qmoQMfVs0W4bX17eqz6C78QJqqFrtgdK5EWf6Qow==" + } + } + } + } + }, + "has-flag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=" + }, + "has-symbol-support-x": { + "version": "1.4.2", + "resolved": "https://registry.npmjs.org/has-symbol-support-x/-/has-symbol-support-x-1.4.2.tgz", + "integrity": "sha512-3ToOva++HaW+eCpgqZrCfN51IPB+7bJNVT6CUATzueB5Heb8o6Nam0V3HG5dlDvZU1Gn5QLcbahiKw/XVk5JJw==" + }, + "has-to-string-tag-x": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/has-to-string-tag-x/-/has-to-string-tag-x-1.4.1.tgz", + "integrity": "sha512-vdbKfmw+3LoOYVr+mtxHaX5a96+0f3DljYd8JOqvOLsf5mw2Otda2qCDT9qRqLAhrjyQ0h7ual5nOiASpsGNFw==", + "requires": { + "has-symbol-support-x": "^1.4.1" + } + }, + "has-unicode": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/has-unicode/-/has-unicode-2.0.1.tgz", + "integrity": "sha1-4Ob+aijPUROIVeCG0Wkedx3iqLk=" + }, + "hoek": { + "version": "6.1.3", + "resolved": "https://registry.npmjs.org/hoek/-/hoek-6.1.3.tgz", + "integrity": "sha512-YXXAAhmF9zpQbC7LEcREFtXfGq5K1fmd+4PHkBq8NUqmzW3G+Dq10bI/i0KucLRwss3YYFQ0fSfoxBZYiGUqtQ==" + }, + "htmlparser2": { + "version": "3.10.1", + "resolved": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-3.10.1.tgz", + "integrity": "sha512-IgieNijUMbkDovyoKObU1DUhm1iwNYE/fuifEoEHfd1oZKZDaONBSkal7Y01shxsM49R4XaMdGez3WnF9UfiCQ==", + "requires": { + "domelementtype": "^1.3.1", + "domhandler": "^2.3.0", + "domutils": "^1.5.1", + "entities": "^1.1.1", + "inherits": "^2.0.1", + "readable-stream": "^3.1.1" + }, + "dependencies": { + "readable-stream": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", + "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", + "requires": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + } + } + } + }, + "http-cache-semantics": { + "version": "3.8.1", + "resolved": "https://registry.npmjs.org/http-cache-semantics/-/http-cache-semantics-3.8.1.tgz", + "integrity": "sha512-5ai2iksyV8ZXmnZhHH4rWPoxxistEexSi5936zIQ1bnNTW5VnA85B6P/VpXiRM017IgRvb2kKo1a//y+0wSp3w==" + }, + "http-status": { + "version": "1.4.2", + "resolved": "https://registry.npmjs.org/http-status/-/http-status-1.4.2.tgz", + "integrity": "sha512-mBnIohUwRw9NyXMEMMv8/GANnzEYUj0Y8d3uL01zDWFkxUjYyZ6rgCaAI2zZ1Wb34Oqtbx/nFZolPRDc8Xlm5A==" + }, + "ieee754": { + "version": "1.1.13", + "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.1.13.tgz", + "integrity": "sha512-4vf7I2LYV/HaWerSo3XmlMkp5eZ83i+/CDluXi/IGTs/O1sejBNhTtnxzmRZfvOUqj7lZjqHkeTvpgSFDlWZTg==" + }, + "infobox-parser": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/infobox-parser/-/infobox-parser-3.3.1.tgz", + "integrity": "sha512-Aj1uF/taawGhet8cazhXz2uEDFMOqH8hnuw720wvi7Zw6bJWmA45Ta2FI9xMG5wvvo4CB6GR9S1/RUFtC6EtAg==", + "requires": { + "camelcase": "^4.1.0" + } + }, + "inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" + }, + "ini": { + "version": "1.3.5", + "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.5.tgz", + "integrity": "sha512-RZY5huIKCMRWDUqZlEi72f/lmXKMvuszcMBduliQ3nnWbx9X/ZBQO7DijMEYS9EhHBb2qacRUMtC7svLwe0lcw==" + }, + "integer": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/integer/-/integer-3.0.1.tgz", + "integrity": "sha512-OqtER6W2GIJTIcnT5o2B/pWGgvurnVOYs4OZCgay40QEIbMTnNq4R0KSaIw1TZyFtPWjm5aNM+pBBMTfc3exmw==", + "requires": { + "bindings": "^1.5.0", + "prebuild-install": "^5.3.3" + } + }, + "into-stream": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/into-stream/-/into-stream-3.1.0.tgz", + "integrity": "sha1-lvsKk2wSur1v8XUqF9BWFqvQlMY=", + "requires": { + "from2": "^2.1.1", + "p-is-promise": "^1.1.0" + } + }, + "is": { + "version": "0.2.7", + "resolved": "https://registry.npmjs.org/is/-/is-0.2.7.tgz", + "integrity": "sha1-OzSixI81mXLzUEKEkZOucmS2NWI=" + }, + "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.0" + } + }, + "is-natural-number": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/is-natural-number/-/is-natural-number-4.0.1.tgz", + "integrity": "sha1-q5124dtM7VHjXeDHLr7PCfc0zeg=" + }, + "is-object": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-object/-/is-object-1.0.1.tgz", + "integrity": "sha1-iVJojF7C/9awPsyF52ngKQMINHA=" + }, + "is-plain-obj": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-1.1.0.tgz", + "integrity": "sha1-caUMhCnfync8kqOQpKA7OfzVHT4=" + }, + "is-retry-allowed": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/is-retry-allowed/-/is-retry-allowed-1.2.0.tgz", + "integrity": "sha512-RUbUeKwvm3XG2VYamhJL1xFktgjvPzL0Hq8C+6yrWIswDy3BIXGqCxhxkc30N9jqK311gVU137K8Ei55/zVJRg==" + }, + "is-stream": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-1.1.0.tgz", + "integrity": "sha1-EtSj3U5o4Lec6428hBc66A2RykQ=" + }, + "isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=" + }, + "isemail": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/isemail/-/isemail-3.2.0.tgz", + "integrity": "sha512-zKqkK+O+dGqevc93KNsbZ/TqTUFd46MwWjYOoMrjIMZ51eU7DtQG3Wmd9SQQT7i7RVnuTPEiYEWHU3MSbxC1Tg==", + "requires": { + "punycode": "2.x.x" + } + }, + "isurl": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isurl/-/isurl-1.0.0.tgz", + "integrity": "sha512-1P/yWsxPlDtn7QeRD+ULKQPaIaN6yF368GZ2vDfv0AL0NwpStafjWCDDdn0k8wgFMWpVAqG7oJhxHnlud42i9w==", + "requires": { + "has-to-string-tag-x": "^1.2.0", + "is-object": "^1.0.1" + } + }, + "joi": { + "version": "14.3.1", + "resolved": "https://registry.npmjs.org/joi/-/joi-14.3.1.tgz", + "integrity": "sha512-LQDdM+pkOrpAn4Lp+neNIFV3axv1Vna3j38bisbQhETPMANYRbFJFUyOZcOClYvM/hppMhGWuKSFEK9vjrB+bQ==", + "requires": { + "hoek": "6.x.x", + "isemail": "3.x.x", + "topo": "3.x.x" + } + }, + "js-yaml": { + "version": "3.13.1", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.13.1.tgz", + "integrity": "sha512-YfbcO7jXDdyj0DGxYVSlSeQNHbD7XPWvrVWeVUujrQEoZzWJIRrCPoyk6kL6IAjAG2IolMK4T0hNUe0HOUs5Jw==", + "requires": { + "argparse": "^1.0.7", + "esprima": "^4.0.0" + } + }, + "json-buffer": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.0.tgz", + "integrity": "sha1-Wx85evx11ne96Lz8Dkfh+aPZqJg=" + }, + "json-schema-ref-parser": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/json-schema-ref-parser/-/json-schema-ref-parser-6.1.0.tgz", + "integrity": "sha512-pXe9H1m6IgIpXmE5JSb8epilNTGsmTb2iPohAXpOdhqGFbQjNeHHsZxU+C8w6T81GZxSPFLeUoqDJmzxx5IGuw==", + "requires": { + "call-me-maybe": "^1.0.1", + "js-yaml": "^3.12.1", + "ono": "^4.0.11" + } + }, + "json5": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/json5/-/json5-2.1.3.tgz", + "integrity": "sha512-KXPvOm8K9IJKFM0bmdn8QXh7udDh1g/giieX0NLCaMnb4hEiVFqnop2ImTXCc5e0/oHz3LTqmHGtExn5hfMkOA==", + "requires": { + "minimist": "^1.2.5" + } + }, + "keyv": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/keyv/-/keyv-3.0.0.tgz", + "integrity": "sha512-eguHnq22OE3uVoSYG0LVWNP+4ppamWr9+zWBe1bsNcovIMy6huUJFPgy4mGwCd/rnl3vOLGW1MTlu4c57CT1xA==", + "requires": { + "json-buffer": "3.0.0" + } + }, + "lodash": { + "version": "4.17.15", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.15.tgz", + "integrity": "sha512-8xOcRHvCjnocdS5cpwXQXVzmmh5e5+saE2QGoeQmbKmRS6J3VQppPOIt0MnmE+4xlZoumy0GPG0D0MVIQbNA1A==" + }, + "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.isequal": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/lodash.isequal/-/lodash.isequal-4.5.0.tgz", + "integrity": "sha1-QVxEePK8wwEgwizhDtMib30+GOA=" + }, + "lowercase-keys": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/lowercase-keys/-/lowercase-keys-1.0.1.tgz", + "integrity": "sha512-G2Lj61tXDnVFFOi8VZds+SoQjtQC3dgokKdDG2mTm1tx4m50NUHBOZSBwQQHyy0V12A0JTG4icfZQH+xPyh8VA==" + }, + "lru-cache": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz", + "integrity": "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==", + "requires": { + "yallist": "^3.0.2" + } + }, + "make-dir": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-1.3.0.tgz", + "integrity": "sha512-2w31R7SJtieJJnQtGc7RVL2StM2vGYVfqUOvUDxH6bC6aJTxPxTF0GnIgCyu7tjockiUWAYQRbxa7vKn34s5sQ==", + "requires": { + "pify": "^3.0.0" + } + }, + "mime-db": { + "version": "1.43.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.43.0.tgz", + "integrity": "sha512-+5dsGEEovYbT8UY9yD7eE4XTc4UwJ1jBYlgaQQF38ENsKR3wj/8q8RFZrF9WIZpB2V1ArTVFUva8sAul1NzRzQ==" + }, + "mimic-response": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-2.1.0.tgz", + "integrity": "sha512-wXqjST+SLt7R009ySCglWBCFpjUygmCIfD790/kVbiGmUgfYGuB14PiTd5DwVxSV4NcYHjzMkoj5LjQZwTQLEA==" + }, + "minimist": { + "version": "1.2.5", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.5.tgz", + "integrity": "sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw==" + }, + "minipass": { + "version": "2.9.0", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-2.9.0.tgz", + "integrity": "sha512-wxfUjg9WebH+CUDX/CdbRlh5SmfZiy/hpkxaRI16Y9W56Pa75sWgd/rvFilSgrauD9NyFymP/+JFV3KwzIsJeg==", + "requires": { + "safe-buffer": "^5.1.2", + "yallist": "^3.0.0" + } + }, + "minizlib": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/minizlib/-/minizlib-1.3.3.tgz", + "integrity": "sha512-6ZYMOEnmVsdCeTJVE0W9ZD+pVnE8h9Hma/iOwwRDsdQoePpoX56/8B6z3P9VNwppJuBKNRuFDRNRqRWexT9G9Q==", + "requires": { + "minipass": "^2.9.0" + } + }, + "mkdirp": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz", + "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==" + }, + "mkdirp-classic": { + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/mkdirp-classic/-/mkdirp-classic-0.5.2.tgz", + "integrity": "sha512-ejdnDQcR75gwknmMw/tx02AuRs8jCtqFoFqDZMjiNxsu85sRIJVXDKHuLYvUUPRBUtV2FpSZa9bL1BUa3BdR2g==" + }, + "mkdirp-no-bin": { + "version": "0.5.1", + "resolved": "https://registry.npmjs.org/mkdirp-no-bin/-/mkdirp-no-bin-0.5.1.tgz", + "integrity": "sha1-NMYjGW02+y7i5WGrYHMFYy4AYZ8=" + }, + "ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" + }, + "napi-build-utils": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/napi-build-utils/-/napi-build-utils-1.0.2.tgz", + "integrity": "sha512-ONmRUqK7zj7DWX0D9ADe03wbwOBZxNAfF20PlGfCWQcD3+/MakShIHrMqx9YwPTfxDdF1zLeL+RGZiR9kGMLdg==" + }, + "neo-async": { + "version": "2.6.1", + "resolved": "https://registry.npmjs.org/neo-async/-/neo-async-2.6.1.tgz", + "integrity": "sha512-iyam8fBuCUpWeKPGpaNMetEocMt364qkCsfL9JuhjXX6dRnguRVOfk2GZaDpPjcOKiiXCPINZC1GczQ7iTq3Zw==" + }, + "node-abi": { + "version": "2.15.0", + "resolved": "https://registry.npmjs.org/node-abi/-/node-abi-2.15.0.tgz", + "integrity": "sha512-FeLpTS0F39U7hHZU1srAK4Vx+5AHNVOTP+hxBNQknR/54laTHSFIJkDWDqiquY1LeLUgTfPN7sLPhMubx0PLAg==", + "requires": { + "semver": "^5.4.1" + } + }, + "node-fetch": { + "version": "2.6.0", + "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.0.tgz", + "integrity": "sha512-8dG4H5ujfvFiqDmVu9fQ5bOHUC15JMjMY/Zumv26oOvvVJjM67KF8koCWIabKQ1GJIa9r2mMZscBq/TbdOcmNA==" + }, + "node.extend": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/node.extend/-/node.extend-1.0.8.tgz", + "integrity": "sha1-urBDefc4P0WHmQyd8Htqf2Xbdys=", + "requires": { + "is": "~0.2.6", + "object-keys": "~0.4.0" + } + }, + "node.flow": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/node.flow/-/node.flow-1.2.3.tgz", + "integrity": "sha1-4cRKgq7KjXi0WKd/s9xkLy66Jkk=", + "requires": { + "node.extend": "1.0.8" + } + }, + "nodemailer": { + "version": "6.4.6", + "resolved": "https://registry.npmjs.org/nodemailer/-/nodemailer-6.4.6.tgz", + "integrity": "sha512-/kJ+FYVEm2HuUlw87hjSqTss+GU35D4giOpdSfGp7DO+5h6RlJj7R94YaYHOkoxu1CSaM0d3WRBtCzwXrY6MKA==" + }, + "noop-logger": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/noop-logger/-/noop-logger-0.1.1.tgz", + "integrity": "sha1-lKKxYzxPExdVMAfYlm/Q6EG2pMI=" + }, + "normalize-url": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/normalize-url/-/normalize-url-2.0.1.tgz", + "integrity": "sha512-D6MUW4K/VzoJ4rJ01JFKxDrtY1v9wrgzCX5f2qj/lzH1m/lW6MhUZFKerVsnyjOhOsYzI9Kqqak+10l4LvLpMw==", + "requires": { + "prepend-http": "^2.0.0", + "query-string": "^5.0.1", + "sort-keys": "^2.0.0" + }, + "dependencies": { + "sort-keys": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/sort-keys/-/sort-keys-2.0.0.tgz", + "integrity": "sha1-ZYU1WEhh7JfXMNbPQYIuH1ZoQSg=", + "requires": { + "is-plain-obj": "^1.0.0" + } + } + } + }, + "npm-conf": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/npm-conf/-/npm-conf-1.1.3.tgz", + "integrity": "sha512-Yic4bZHJOt9RCFbRP3GgpqhScOY4HH3V2P8yBj6CeYq118Qr+BLXqT2JvpJ00mryLESpgOxf5XlFv4ZjXxLScw==", + "requires": { + "config-chain": "^1.1.11", + "pify": "^3.0.0" + } + }, + "npmlog": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/npmlog/-/npmlog-4.1.2.tgz", + "integrity": "sha512-2uUqazuKlTaSI/dC8AzicUck7+IrEaOnN/e0jd3Xtt1KcGpwx30v50mL7oPyr/h9bL3E4aZccVwpwP+5W9Vjkg==", + "requires": { + "are-we-there-yet": "~1.1.2", + "console-control-strings": "~1.1.0", + "gauge": "~2.7.3", + "set-blocking": "~2.0.0" + } + }, + "nth-check": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/nth-check/-/nth-check-1.0.2.tgz", + "integrity": "sha512-WeBOdju8SnzPN5vTUJYxYUxLeXpCaVP5i5e0LF8fg7WORF2Wd7wFX/pk0tYZk7s8T+J7VLy0Da6J1+wCT0AtHg==", + "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=" + }, + "object-assign": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", + "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=" + }, + "object-keys": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-0.4.0.tgz", + "integrity": "sha1-KKaq50KN0sOpLz2V8hM13SBOAzY=" + }, + "once": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", + "requires": { + "wrappy": "1" + } + }, + "ono": { + "version": "4.0.11", + "resolved": "https://registry.npmjs.org/ono/-/ono-4.0.11.tgz", + "integrity": "sha512-jQ31cORBFE6td25deYeD80wxKBMj+zBmHTrVxnc6CKhx8gho6ipmWM5zj/oeoqioZ99yqBls9Z/9Nss7J26G2g==", + "requires": { + "format-util": "^1.0.3" + } + }, + "p-cancelable": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/p-cancelable/-/p-cancelable-0.4.1.tgz", + "integrity": "sha512-HNa1A8LvB1kie7cERyy21VNeHb2CWJJYqyyC2o3klWFfMGlFmWv2Z7sFgZH8ZiaYL95ydToKTFVXgMV/Os0bBQ==" + }, + "p-event": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/p-event/-/p-event-2.3.1.tgz", + "integrity": "sha512-NQCqOFhbpVTMX4qMe8PF8lbGtzZ+LCiN7pcNrb/413Na7+TRoe1xkKUzuWa/YEJdGQ0FvKtj35EEbDoVPO2kbA==", + "requires": { + "p-timeout": "^2.0.1" + } + }, + "p-finally": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/p-finally/-/p-finally-1.0.0.tgz", + "integrity": "sha1-P7z7FbiZpEEjs0ttzBi3JDNqLK4=" + }, + "p-is-promise": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/p-is-promise/-/p-is-promise-1.1.0.tgz", + "integrity": "sha1-nJRWmJ6fZYgBewQ01WCXZ1w9oF4=" + }, + "p-timeout": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/p-timeout/-/p-timeout-2.0.1.tgz", + "integrity": "sha512-88em58dDVB/KzPEx1X0N3LwFfYZPyDc4B6eF38M1rk9VTZMbxXXgjugz8mmwpS9Ox4BDZ+t6t3QP5+/gazweIA==", + "requires": { + "p-finally": "^1.0.0" + } + }, + "parse5": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/parse5/-/parse5-3.0.3.tgz", + "integrity": "sha512-rgO9Zg5LLLkfJF9E6CCmXlSE4UVceloys8JrFqCcHloC3usd/kJCyPDwH2SOlzix2j3xaP9sUX3e8+kvkuleAA==", + "requires": { + "@types/node": "*" + } + }, + "pend": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/pend/-/pend-1.2.0.tgz", + "integrity": "sha1-elfrVQpng/kRUzH89GY9XI4AelA=" + }, + "persistent-cache": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/persistent-cache/-/persistent-cache-1.1.1.tgz", + "integrity": "sha1-ndiBPghcSrowmHsI4RqcqGpipUw=", + "requires": { + "mkdirp-no-bin": "^0.5.1", + "rmdir": "^1.2.0" + } + }, + "picolog": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/picolog/-/picolog-1.0.4.tgz", + "integrity": "sha1-qOC3CwgehkuItMhYu/y4OIF1hdU=" + }, + "pify": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz", + "integrity": "sha1-5aSs0sEB/fPZpNB/DbxNtJ3SgXY=" + }, + "pinkie": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/pinkie/-/pinkie-2.0.4.tgz", + "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.0" + } + }, + "prebuild-install": { + "version": "5.3.3", + "resolved": "https://registry.npmjs.org/prebuild-install/-/prebuild-install-5.3.3.tgz", + "integrity": "sha512-GV+nsUXuPW2p8Zy7SarF/2W/oiK8bFQgJcncoJ0d7kRpekEA0ftChjfEaF9/Y+QJEc/wFR7RAEa8lYByuUIe2g==", + "requires": { + "detect-libc": "^1.0.3", + "expand-template": "^2.0.3", + "github-from-package": "0.0.0", + "minimist": "^1.2.0", + "mkdirp": "^0.5.1", + "napi-build-utils": "^1.0.1", + "node-abi": "^2.7.0", + "noop-logger": "^0.1.1", + "npmlog": "^4.0.1", + "pump": "^3.0.0", + "rc": "^1.2.7", + "simple-get": "^3.0.3", + "tar-fs": "^2.0.0", + "tunnel-agent": "^0.6.0", + "which-pm-runs": "^1.0.0" + }, + "dependencies": { + "mkdirp": { + "version": "0.5.5", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.5.tgz", + "integrity": "sha512-NKmAlESf6jMGym1++R0Ra7wvhV+wFW63FaSOFPwRahvea0gMUcGUhVeAg/0BC0wiv9ih5NYPB1Wn1UEI1/L+xQ==", + "requires": { + "minimist": "^1.2.5" + } + } + } + }, + "prepend-http": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/prepend-http/-/prepend-http-2.0.0.tgz", + "integrity": "sha1-6SQ0v6XqjBn0HN/UAddBo8gZ2Jc=" + }, + "process-nextick-args": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", + "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==" + }, + "progress": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/progress/-/progress-2.0.3.tgz", + "integrity": "sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA==" + }, + "proto-list": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/proto-list/-/proto-list-1.2.4.tgz", + "integrity": "sha1-IS1b/hMYMGpCD2QCuOJv85ZHqEk=" + }, + "pump": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.0.tgz", + "integrity": "sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==", + "requires": { + "end-of-stream": "^1.1.0", + "once": "^1.3.1" + } + }, + "punycode": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz", + "integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==" + }, + "query-string": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/query-string/-/query-string-5.1.1.tgz", + "integrity": "sha512-gjWOsm2SoGlgLEdAGt7a6slVOk9mGiXmPFMqrEhLQ68rhQuBnpfs3+EmlvqKyxnCo9/PPlF+9MtY02S1aFg+Jw==", + "requires": { + "decode-uri-component": "^0.2.0", + "object-assign": "^4.1.0", + "strict-uri-encode": "^1.0.0" + } + }, + "rc": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/rc/-/rc-1.2.8.tgz", + "integrity": "sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw==", + "requires": { + "deep-extend": "^0.6.0", + "ini": "~1.3.0", + "minimist": "^1.2.0", + "strip-json-comments": "~2.0.1" + } + }, + "readable-stream": { + "version": "2.3.7", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", + "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", + "requires": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "responselike": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/responselike/-/responselike-1.0.2.tgz", + "integrity": "sha1-kYcg7ztjHFZCvgaPFa3lpG9Loec=", + "requires": { + "lowercase-keys": "^1.0.0" + } + }, + "rmdir": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/rmdir/-/rmdir-1.2.0.tgz", + "integrity": "sha1-T+A1fLBhaMJY5z6WgJPcTooPMlM=", + "requires": { + "node.flow": "1.2.3" + } + }, + "safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" + }, + "seek-bzip": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/seek-bzip/-/seek-bzip-1.0.5.tgz", + "integrity": "sha1-z+kXyz0nS8/6x5J1ivUxc+sfq9w=", + "requires": { + "commander": "~2.8.1" + } + }, + "semver": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", + "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==" + }, + "set-blocking": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", + "integrity": "sha1-BF+XgtARrppoA93TgrJDkrPYkPc=" + }, + "signal-exit": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.3.tgz", + "integrity": "sha512-VUJ49FC8U1OxwZLxIbTTrDvLnf/6TDgxZcK8wxR8zs13xpx7xbG60ndBlhNrFi2EMuFRoeDoJO7wthSLq42EjA==" + }, + "simple-concat": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/simple-concat/-/simple-concat-1.0.0.tgz", + "integrity": "sha1-c0TLuLbib7J9ZrL8hvn21Zl1IcY=" + }, + "simple-get": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/simple-get/-/simple-get-3.1.0.tgz", + "integrity": "sha512-bCR6cP+aTdScaQCnQKbPKtJOKDp/hj9EDLJo3Nw4y1QksqaovlW/bnptB6/c1e+qmNIDHRK+oXFDdEqBT8WzUA==", + "requires": { + "decompress-response": "^4.2.0", + "once": "^1.3.1", + "simple-concat": "^1.0.0" + } + }, + "sort-keys": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/sort-keys/-/sort-keys-1.1.2.tgz", + "integrity": "sha1-RBttTTRnmPG05J6JIK37oOVD+a0=", + "requires": { + "is-plain-obj": "^1.0.0" + } + }, + "sort-keys-length": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/sort-keys-length/-/sort-keys-length-1.0.1.tgz", + "integrity": "sha1-nLb09OnkgVWmqgZx7dM2/xR5oYg=", + "requires": { + "sort-keys": "^1.0.0" + } + }, + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==" + }, + "sprintf-js": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", + "integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw=" + }, + "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.0.0", + "is-fullwidth-code-point": "^1.0.0", + "strip-ansi": "^3.0.0" + } + }, + "string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "requires": { + "safe-buffer": "~5.1.0" + } + }, + "strip-ansi": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", + "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", + "requires": { + "ansi-regex": "^2.0.0" + } + }, + "strip-dirs": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/strip-dirs/-/strip-dirs-2.1.0.tgz", + "integrity": "sha512-JOCxOeKLm2CAS73y/U4ZeZPTkE+gNVCzKt7Eox84Iej1LT/2pTWYpZKJuxwQpvX1LiZb1xokNR7RLfuBAa7T3g==", + "requires": { + "is-natural-number": "^4.0.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=" + }, + "strip-outer": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/strip-outer/-/strip-outer-1.0.1.tgz", + "integrity": "sha512-k55yxKHwaXnpYGsOzg4Vl8+tDrWylxDEpknGjhTiZB8dFRU5rTo9CAzeycivxV3s+zlTKwrs6WxMxR95n26kwg==", + "requires": { + "escape-string-regexp": "^1.0.2" + } + }, + "supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "requires": { + "has-flag": "^3.0.0" + } + }, + "swagger-methods": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/swagger-methods/-/swagger-methods-1.0.8.tgz", + "integrity": "sha512-G6baCwuHA+C5jf4FNOrosE4XlmGsdjbOjdBK4yuiDDj/ro9uR4Srj3OR84oQMT8F3qKp00tYNv0YN730oTHPZA==" + }, + "swagger-parser": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/swagger-parser/-/swagger-parser-4.0.2.tgz", + "integrity": "sha512-hKslog8LhsXICJ1sMLsA8b8hQ3oUEX0457aLCFJc4zz6m8drmnCtyjbVqS5HycaKFOKVolJc2wFoe8KDPWfp4g==", + "requires": { + "call-me-maybe": "^1.0.1", + "debug": "^3.1.0", + "json-schema-ref-parser": "^4.1.0", + "ono": "^4.0.3", + "swagger-methods": "^1.0.4", + "swagger-schema-official": "2.0.0-bab6bed", + "z-schema": "^3.19.0" + }, + "dependencies": { + "debug": { + "version": "3.2.6", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.6.tgz", + "integrity": "sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ==", + "requires": { + "ms": "^2.1.1" + } + }, + "json-schema-ref-parser": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/json-schema-ref-parser/-/json-schema-ref-parser-4.1.1.tgz", + "integrity": "sha512-lByoCHZ6H2zgb6NtsXIqtzQ+6Ji7iVqnrhWxsXLhF+gXmgu6E8+ErpDxCMR439MUG1nfMjWI2HAoM8l0XgSNhw==", + "requires": { + "call-me-maybe": "^1.0.1", + "debug": "^3.1.0", + "js-yaml": "^3.10.0", + "ono": "^4.0.3" + } + } + } + }, + "swagger-schema-official": { + "version": "2.0.0-bab6bed", + "resolved": "https://registry.npmjs.org/swagger-schema-official/-/swagger-schema-official-2.0.0-bab6bed.tgz", + "integrity": "sha1-cAcEaNbSl3ylI3suUZyn0Gouo/0=" + }, + "swagger-ui-dist": { + "version": "3.25.0", + "resolved": "https://registry.npmjs.org/swagger-ui-dist/-/swagger-ui-dist-3.25.0.tgz", + "integrity": "sha512-vwvJPPbdooTvDwLGzjIXinOXizDJJ6U1hxnJL3y6U3aL1d2MSXDmKg2139XaLBhsVZdnQJV2bOkX4reB+RXamg==" + }, + "tar": { + "version": "4.4.10", + "resolved": "https://registry.npmjs.org/tar/-/tar-4.4.10.tgz", + "integrity": "sha512-g2SVs5QIxvo6OLp0GudTqEf05maawKUxXru104iaayWA09551tFCTI8f1Asb4lPfkBr91k07iL4c11XO3/b0tA==", + "requires": { + "chownr": "^1.1.1", + "fs-minipass": "^1.2.5", + "minipass": "^2.3.5", + "minizlib": "^1.2.1", + "mkdirp": "^0.5.0", + "safe-buffer": "^5.1.2", + "yallist": "^3.0.3" + }, + "dependencies": { + "mkdirp": { + "version": "0.5.5", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.5.tgz", + "integrity": "sha512-NKmAlESf6jMGym1++R0Ra7wvhV+wFW63FaSOFPwRahvea0gMUcGUhVeAg/0BC0wiv9ih5NYPB1Wn1UEI1/L+xQ==", + "requires": { + "minimist": "^1.2.5" + } + } + } + }, + "tar-fs": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/tar-fs/-/tar-fs-2.0.1.tgz", + "integrity": "sha512-6tzWDMeroL87uF/+lin46k+Q+46rAJ0SyPGz7OW7wTgblI273hsBqk2C1j0/xNadNLKDTUL9BukSjB7cwgmlPA==", + "requires": { + "chownr": "^1.1.1", + "mkdirp-classic": "^0.5.2", + "pump": "^3.0.0", + "tar-stream": "^2.0.0" + } + }, + "tar-stream": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/tar-stream/-/tar-stream-2.1.2.tgz", + "integrity": "sha512-UaF6FoJ32WqALZGOIAApXx+OdxhekNMChu6axLJR85zMMjXKWFGjbIRe+J6P4UnRGg9rAwWvbTT0oI7hD/Un7Q==", + "requires": { + "bl": "^4.0.1", + "end-of-stream": "^1.4.1", + "fs-constants": "^1.0.0", + "inherits": "^2.0.3", + "readable-stream": "^3.1.1" + }, + "dependencies": { + "readable-stream": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", + "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", + "requires": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + } + } + } + }, + "through": { + "version": "2.3.8", + "resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz", + "integrity": "sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU=" + }, + "timed-out": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/timed-out/-/timed-out-4.0.1.tgz", + "integrity": "sha1-8y6srFoXW+ol1/q1Zas+2HQe9W8=" + }, + "to-buffer": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/to-buffer/-/to-buffer-1.1.1.tgz", + "integrity": "sha512-lx9B5iv7msuFYE3dytT+KE5tap+rNYw+K4jVkb9R/asAb+pbBSM17jtunHplhBe6RRJdZx3Pn2Jph24O32mOVg==" + }, + "topo": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/topo/-/topo-3.0.3.tgz", + "integrity": "sha512-IgpPtvD4kjrJ7CRA3ov2FhWQADwv+Tdqbsf1ZnPUSAtCJ9e1Z44MmoSGDXGk4IppoZA7jd/QRkNddlLJWlUZsQ==", + "requires": { + "hoek": "6.x.x" + } + }, + "trim-repeated": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/trim-repeated/-/trim-repeated-1.0.0.tgz", + "integrity": "sha1-42RqLqTokTEr9+rObPsFOAvAHCE=", + "requires": { + "escape-string-regexp": "^1.0.2" + } + }, + "tunnel-agent": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz", + "integrity": "sha1-J6XeoGs2sEoKmWZ3SykIaPD8QP0=", + "requires": { + "safe-buffer": "^5.0.1" + } + }, + "uglify-js": { + "version": "3.9.1", + "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-3.9.1.tgz", + "integrity": "sha512-JUPoL1jHsc9fOjVFHdQIhqEEJsQvfKDjlubcCilu8U26uZ73qOg8VsN8O1jbuei44ZPlwL7kmbAdM4tzaUvqnA==", + "optional": true, + "requires": { + "commander": "~2.20.3" + }, + "dependencies": { + "commander": { + "version": "2.20.3", + "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", + "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==", + "optional": true + } + } + }, + "unbzip2-stream": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/unbzip2-stream/-/unbzip2-stream-1.4.1.tgz", + "integrity": "sha512-sgDYfSDPMsA4Hr2/w7vOlrJBlwzmyakk1+hW8ObLvxSp0LA36LcL2XItGvOT3OSblohSdevMuT8FQjLsqyy4sA==", + "requires": { + "buffer": "^5.2.1", + "through": "^2.3.8" + } + }, + "url-parse-lax": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/url-parse-lax/-/url-parse-lax-3.0.0.tgz", + "integrity": "sha1-FrXK/Afb42dsGxmZF3gj1lA6yww=", + "requires": { + "prepend-http": "^2.0.0" + } + }, + "url-to-options": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/url-to-options/-/url-to-options-1.0.1.tgz", + "integrity": "sha1-FQWgOiiaSMvXpDTvuu7FBV9WM6k=" + }, + "util-deprecate": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", + "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=" + }, + "validator": { + "version": "10.11.0", + "resolved": "https://registry.npmjs.org/validator/-/validator-10.11.0.tgz", + "integrity": "sha512-X/p3UZerAIsbBfN/IwahhYaBbY68EN/UQBWHtsbXGT5bfrH/p4NQzUCG1kF/rtKaNpnJ7jAu6NGTdSNtyNIXMw==" + }, + "walk": { + "version": "2.3.14", + "resolved": "https://registry.npmjs.org/walk/-/walk-2.3.14.tgz", + "integrity": "sha512-5skcWAUmySj6hkBdH6B6+3ddMjVQYH5Qy9QGbPmN8kVmLteXk+yVXg+yfk1nbX30EYakahLrr8iPcCxJQSCBeg==", + "requires": { + "foreachasync": "^3.0.0" + } + }, + "wcwidth": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/wcwidth/-/wcwidth-1.0.1.tgz", + "integrity": "sha1-8LDc+RW8X/FSivrbLA4XtTLaL+g=", + "optional": true, + "requires": { + "defaults": "^1.0.3" + } + }, + "whatwg-fetch": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/whatwg-fetch/-/whatwg-fetch-3.0.0.tgz", + "integrity": "sha512-9GSJUgz1D4MfyKU7KRqwOjXCXTqWdFNvEr7eUBYchQiVc744mqK/MzXPNR2WsPkmkOa4ywfg8C2n8h+13Bey1Q==" + }, + "which-pm-runs": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/which-pm-runs/-/which-pm-runs-1.0.0.tgz", + "integrity": "sha1-Zws6+8VS4LVd9rd4DKdGFfI60cs=" + }, + "wide-align": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/wide-align/-/wide-align-1.1.3.tgz", + "integrity": "sha512-QGkOQc8XL6Bt5PwnsExKBPuMKBxnGxWWW3fU55Xt4feHozMUhdUMaBCk290qpm/wG5u/RSKzwdAC4i51YigihA==", + "requires": { + "string-width": "^1.0.2 || 2" + } + }, + "wikijs": { + "version": "5.5.1", + "resolved": "https://registry.npmjs.org/wikijs/-/wikijs-5.5.1.tgz", + "integrity": "sha512-g8Xd/qx0LxsaCcTXJRZ1gpdjc3XV1T+hgMKoobd1dRq4nnoLuJCo3XDn6ZSjbahmD74f9dz7PyBDgh5LFSpbEA==", + "requires": { + "cross-fetch": "^3.0.2", + "infobox-parser": "3.3.1" + } + }, + "wordwrap": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-1.0.0.tgz", + "integrity": "sha1-J1hIEIkUVqQXHI0CJkQa3pDLyus=" + }, + "wrappy": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=" + }, + "xtend": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz", + "integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==" + }, + "yallist": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz", + "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==" + }, + "yauzl": { + "version": "2.10.0", + "resolved": "https://registry.npmjs.org/yauzl/-/yauzl-2.10.0.tgz", + "integrity": "sha1-x+sXyT4RLLEIb6bY5R+wZnt5pfk=", + "requires": { + "buffer-crc32": "~0.2.3", + "fd-slicer": "~1.1.0" + } + }, + "z-schema": { + "version": "3.25.1", + "resolved": "https://registry.npmjs.org/z-schema/-/z-schema-3.25.1.tgz", + "integrity": "sha512-7tDlwhrBG+oYFdXNOjILSurpfQyuVgkRe3hB2q8TEssamDHB7BbLWYkYO98nTn0FibfdFroFKDjndbgufAgS/Q==", + "requires": { + "commander": "^2.7.1", + "core-js": "^2.5.7", + "lodash.get": "^4.0.0", + "lodash.isequal": "^4.0.0", + "validator": "^10.0.0" + } + } + } +} diff --git a/package.json b/package.json index 2cb084c..1b30458 100644 --- a/package.json +++ b/package.json @@ -1,44 +1,38 @@ { "name": "zenodeo", - "version": "2.5.0", + "version": "2.6.0", "description": "`nodejs` interface to the Zenodo/BLR community collection", "main": "index.js", "repository": "https://github.com/punkish/zenodeo", "author": "Puneet Kishor", "license": "CC0-1.0", "dependencies": { - "@hapi/boom": "^7.4.11", - "@hapi/catbox": "^10.2.3", - "@hapi/hapi": "^18.4.0", - "@hapi/inert": "^5.2.2", - "@hapi/joi": "^16.1.8", - "@hapi/vision": "^5.5.4", - "@hapi/wreck": "^15.1.0", - "better-sqlite3": "^5.4.3", + "@hapi/boom": "^9.1.0", + "@hapi/catbox": "^11.1.0", + "@hapi/hapi": "^19.1.1", + "@hapi/inert": "^6.0.1", + "@hapi/joi": "^17.1.1", + "@hapi/vision": "^6.0.0", + "@hapi/wreck": "^17.0.0", + "better-sqlite3": "^6.0.1", "blipp": "^4.0.1", "catbox-disk": "^3.0.2", - "chalk": "^3.0.0", + "chalk": "^4.0.0", "chance": "^1.1.3", "cheerio": "^1.0.0-rc.3", "config": "^3.2.4", "csvjson": "^5.1.0", "debug": "^4.1.1", "download": "^7.1.0", - "handlebars": "^4.5.3", - "hapi-swagger": "^11.0.1", - "minimist": "^1.2.0", - "mkdirp": "^0.5.1", + "handlebars": "^4.7.6", + "hapi-swagger": "^13.0.0", + "minimist": "^1.2.5", + "mkdirp": "^1.0.4", "nodemailer": "^6.4.0", "persistent-cache": "^1.1.1", "picolog": "^1.0.4", "progress": "^2.0.3", "wikijs": "^5.5.1" }, - "devDependencies": { - "chai": "^4.2.0", - "mocha": "^7.1.0" - }, - "scripts": { - "test": "mocha" - } + "devDependencies": {} } diff --git a/resources/deefault.js b/resources/deefault.js deleted file mode 100644 index b32576a..0000000 --- a/resources/deefault.js +++ /dev/null @@ -1,71 +0,0 @@ -// default route, redirects to the most recent API -const debug = require('debug')('default'); - -const deefault = { - method: 'GET', - path: '/{param*}', - config: { - description: "default route", - tags: ['private'] - }, - handler: function(request, h) { - - //debug(request.url); - - let uri = ''; - - const APIs = ['v1', 'v2']; - // const collections = [ - // 'v1', - // 'v2', - // 'records', - // 'communities' - // ]; - - // const singles = [ - // 'record' - // ]; - - - if (request.params.param) { - - let params = request.params.param.split('/'); - - //Debug(params); - - // add latest version if there is no version - if ((params[0] !== 'v1') && (params[0] !== 'v2')) { - params.unshift(`v${APIs.length}`); - } - - //Debug(params); - - uri = params.join('/'); - - // add a trailing slash if requesting a collection - // - - // add the query params - if (request.query) { - const qry = []; - for (let q in request.query) { - qry.push(`${q}=${request.query[q]}`); - } - - if (qry.length) { - uri += '?' + qry.join('&'); - } - } - } - - else { - uri = `/v${APIs.length}/`; - } - - - //debug(`uri: ${uri}`); - return h.redirect(uri); - } -}; - -module.exports = deefault; \ No newline at end of file diff --git a/resources/releases.js b/resources/releases.js index 6493fb4..7574704 100644 --- a/resources/releases.js +++ b/resources/releases.js @@ -1,31 +1,163 @@ -const about = { +const notes = { method: 'GET', - path: '/releases', + path: '/notes', config: { - description: "releases", + description: "release notes", tags: ['zenodeo'], validate: {}, notes: [ - 'root', + 'release notes', ] }, handler: function(request, h) { + + const data = getRecords(); + return h.view( // content template - 'releases', + 'notes', // data - null, + data, - // layout { layout: 'main' } ); } }; + +const getRecords = function() { + + return { + notes: [ + { + summary: 'version 2.6.0', + detail: ` +
https://zenodeo.punkish.org/v2/materialscitations?lat=77&lon=78
will actually return all the records that are within the following box: latitude > 76.1 AND latitude < 77.9 AND longitude > 77.1 AND longitude < 78.9
+
++lat: 77.9 lat: 77.9 +lon: 77.1 lon: 78.9 ++-----------------------------------------------+ +| | +| | +| lat: 77.53333 | +| lon: 78.88333 | +| ++ | +| | +| | +| lat: 77.2 | +| lon: 78.11667 | +| + | +| | +| | ++-----------------------------------------------+ +lat: 76.1 lat: 76.1 +lon: 77.1 lon: 78.9 ++
stats=true
) then stats for the entire resource-set will be returned. If a query is specified, then stats for the returned data will be included.
+ To upgrade the `Zenodeo` API to the latest version, run the following commands
- -$ git pull
-$ yarn
-
-
- https://zenodeo.punkish.org/v2/materialscitations?lat=77&lon=78
will actually return all the records that are within the following box: latitude > 76.1 AND latitude < 77.9 AND longitude > 77.1 AND longitude < 78.9
-
-- lat: 77.9 lat: 77.9 - lon: 77.1 lon: 78.9 - +-----------------------------------------------+ - | | - | | - | lat: 77.53333 | - | lon: 78.88333 | - | ++ | - | | - | | - | lat: 77.2 | - | lon: 78.11667 | - | + | - | | - | | - +-----------------------------------------------+ - lat: 76.1 lat: 76.1 - lon: 77.1 lon: 78.9 --
stats=true
) then stats for the entire resource-set will be returned. If a query is specified, then stats for the returned data will be included.{{{detail}}}
+