diff --git a/api/src/paths/taxonomy/taxon/index.test.ts b/api/src/paths/taxonomy/taxon/index.test.ts index a1e0d7ae..bd4662e1 100644 --- a/api/src/paths/taxonomy/taxon/index.test.ts +++ b/api/src/paths/taxonomy/taxon/index.test.ts @@ -52,8 +52,8 @@ describe('taxon', () => { sinon.stub(db, 'getDBConnection').returns(dbConnectionObj); - const mock1 = { id: '1', commonName: 'something', scientificName: 'string' } as unknown as any; - const mock2 = { id: '2', commonName: null, scientificName: 'string' } as unknown as any; + const mock1 = { id: '1', commonNames: ['something'], scientificName: 'string' } as unknown as any; + const mock2 = { id: '2', commonNames: null, scientificName: 'string' } as unknown as any; const getSpeciesFromIdsStub = sinon.stub(ItisService.prototype, 'searchItisByTerm').resolves([mock1, mock2]); diff --git a/api/src/paths/taxonomy/taxon/index.ts b/api/src/paths/taxonomy/taxon/index.ts index aaec0324..590927f9 100644 --- a/api/src/paths/taxonomy/taxon/index.ts +++ b/api/src/paths/taxonomy/taxon/index.ts @@ -45,17 +45,25 @@ GET.apiDoc = { items: { title: 'Taxon', type: 'object', - required: ['tsn', 'commonName', 'scientificName'], + required: ['tsn', 'commonNames', 'scientificName'], properties: { tsn: { type: 'integer' }, - commonName: { - type: 'string', - nullable: true + commonNames: { + type: 'array', + items: { + type: 'string' + } }, scientificName: { type: 'string' + }, + rank: { + type: 'string' + }, + kingdom: { + type: 'string' } }, additionalProperties: false diff --git a/api/src/paths/taxonomy/taxon/tsn/index.test.ts b/api/src/paths/taxonomy/taxon/tsn/index.test.ts index 7102e926..cddbcab3 100644 --- a/api/src/paths/taxonomy/taxon/tsn/index.test.ts +++ b/api/src/paths/taxonomy/taxon/tsn/index.test.ts @@ -52,8 +52,8 @@ describe('tsn', () => { sinon.stub(db, 'getDBConnection').returns(dbConnectionObj); - const mock1 = { tsn: '1', commonName: 'something', scientificName: 'string' } as unknown as any; - const mock2 = { tsn: '2', commonName: null, scientificName: 'string' } as unknown as any; + const mock1 = { tsn: '1', commonNames: ['something'], scientificName: 'string' } as unknown as any; + const mock2 = { tsn: '2', commonNames: [], scientificName: 'string' } as unknown as any; const getTaxonByTsnIdsStub = sinon.stub(TaxonomyService.prototype, 'getTaxonByTsnIds').resolves([mock1, mock2]); diff --git a/api/src/paths/taxonomy/taxon/tsn/index.ts b/api/src/paths/taxonomy/taxon/tsn/index.ts index 7ac992da..ca366067 100644 --- a/api/src/paths/taxonomy/taxon/tsn/index.ts +++ b/api/src/paths/taxonomy/taxon/tsn/index.ts @@ -47,17 +47,25 @@ GET.apiDoc = { items: { title: 'Species', type: 'object', - required: ['tsn', 'commonName', 'scientificName'], + required: ['tsn', 'commonNames', 'scientificName'], properties: { tsn: { type: 'integer' }, - commonName: { - type: 'string', - nullable: true + commonNames: { + type: 'array', + items: { + type: 'string' + } }, scientificName: { type: 'string' + }, + rank: { + type: 'string' + }, + kingdom: { + type: 'string' } }, additionalProperties: false diff --git a/api/src/repositories/taxonomy-repository.test.ts b/api/src/repositories/taxonomy-repository.test.ts index 348654b9..ad601af9 100644 --- a/api/src/repositories/taxonomy-repository.test.ts +++ b/api/src/repositories/taxonomy-repository.test.ts @@ -73,7 +73,7 @@ describe('TaxonomyRepository', () => { const taxonomyRepository = new TaxonomyRepository(mockDBConnection); - const response = await taxonomyRepository.addItisTaxonRecord(1, 'string', 'string', {}, 'string'); + const response = await taxonomyRepository.addItisTaxonRecord(1, 'string', ['string'], {}, 'string'); expect(response).to.be.eql({ taxon_id: 1, diff --git a/api/src/repositories/taxonomy-repository.ts b/api/src/repositories/taxonomy-repository.ts index 262b4e61..10773a43 100644 --- a/api/src/repositories/taxonomy-repository.ts +++ b/api/src/repositories/taxonomy-repository.ts @@ -53,7 +53,7 @@ export class TaxonomyRepository extends BaseRepository { * * @param {number} itisTsn * @param {string} itisScientificName - * @param {(string | null)} commonName + * @param {string[]} commonNames * @param {Record} itisData * @param {string} itisUpdateDate * @return {*} {Promise} @@ -62,12 +62,13 @@ export class TaxonomyRepository extends BaseRepository { async addItisTaxonRecord( itisTsn: number, itisScientificName: string, - commonName: string | null, + commonNames: string[], itisData: Record, itisUpdateDate: string ): Promise { defaultLog.debug({ label: 'addItisTaxonRecord', itisTsn }); + // TODO: Store multiple common names rather than just the first item of the commonNames array const sqlStatement = SQL` WITH inserted_row AS ( INSERT INTO @@ -82,7 +83,7 @@ export class TaxonomyRepository extends BaseRepository { VALUES ( ${itisTsn}, ${itisScientificName}, - ${commonName}, + ${commonNames[0]}, ${itisData}, ${itisUpdateDate} ) diff --git a/api/src/services/itis-service.test.ts b/api/src/services/itis-service.test.ts index f08ec48c..be8b8dd7 100644 --- a/api/src/services/itis-service.test.ts +++ b/api/src/services/itis-service.test.ts @@ -40,14 +40,15 @@ describe('ItisService', () => { response: { docs: [ { - commonNames: ['$commonName'], + commonNames: ['$commonNames$English'], kingdom: 'kingdom', name: 'name', parentTSN: 'parentTSN', scientificName: 'scientificName', tsn: '123', updateDate: 'updateDate', - usage: 'usage' + usage: '', + rank: 'kingdom' } ] } @@ -67,8 +68,10 @@ describe('ItisService', () => { expect(response).to.eql([ { tsn: 123, - commonName: 'commonName', - scientificName: 'scientificName' + commonNames: ['commonNames'], + scientificName: 'scientificName', + rank: 'kingdom', + kingdom: 'kingdom' } ]); @@ -121,14 +124,15 @@ describe('ItisService', () => { response: { docs: [ { - commonNames: ['$commonName'], + commonNames: ['$commonNames$English'], kingdom: 'kingdom', name: 'name', parentTSN: 'parentTSN', scientificName: 'scientificName', tsn: '123', updateDate: 'updateDate', - usage: 'usage' + usage: '', + rank: 'kingdom' } ] } @@ -145,14 +149,15 @@ describe('ItisService', () => { expect(response).to.eql([ { - commonNames: ['$commonName'], + commonNames: ['$commonNames$English'], kingdom: 'kingdom', name: 'name', parentTSN: 'parentTSN', scientificName: 'scientificName', tsn: '123', updateDate: 'updateDate', - usage: 'usage' + usage: '', + rank: 'kingdom' } ]); @@ -200,7 +205,7 @@ describe('ItisService', () => { const response = await itisService.getItisSolrTermSearchUrl(['term']); expect(response).to.equal( - 'https://services.itis.gov/?wt=json&sort=nameWOInd+asc&rows=25&omitHeader=true&fl=tsn+scientificName:nameWOInd+kingdom+parentTSN+commonNames:vernacular+updateDate+usage&q=((nameWOInd:*term*+AND+usage:/(valid|accepted)/)+OR+(vernacular:*term*+AND+usage:/(valid|accepted)/))' + 'https://services.itis.gov/?wt=json&sort=kingdom+asc&rows=150&omitHeader=true&fl=tsn+scientificName:nameWOInd+kingdom+parentTSN+commonNames:vernacular+updateDate+usage+rank&q=((nameWOInd:*term*+AND+usage:/(valid|accepted)/)+OR+(vernacular:*term*+AND+usage:/(valid|accepted)/))' ); }); }); @@ -228,7 +233,7 @@ describe('ItisService', () => { const response = await itisService.getItisSolrTsnSearchUrl([123]); expect(response).to.equal( - 'https://services.itis.gov/??wt=json&sort=nameWOInd+asc&rows=25&omitHeader=true&fl=tsn+scientificName:nameWOInd+kingdom+parentTSN+commonNames:vernacular+updateDate+usage&&q=tsn:123' + 'https://services.itis.gov/??wt=json&sort=kingdom+asc&rows=150&omitHeader=true&fl=tsn+scientificName:nameWOInd+kingdom+parentTSN+commonNames:vernacular+updateDate+usage+rank&&q=tsn:123' ); }); }); diff --git a/api/src/services/itis-service.ts b/api/src/services/itis-service.ts index 306c0801..9407d867 100644 --- a/api/src/services/itis-service.ts +++ b/api/src/services/itis-service.ts @@ -1,4 +1,5 @@ import axios from 'axios'; +import { sortTaxonSearchResults } from '../utils/itis-sort'; import { getLogger } from '../utils/logger'; import { TaxonSearchResult } from './taxonomy-service'; @@ -13,6 +14,7 @@ export type ItisSolrSearchResponse = { tsn: string; updateDate: string; usage: string; + rank: string; }; /** @@ -42,7 +44,14 @@ export class ItisService { return []; } - return this._sanitizeItisData(response.data.response.docs); + const sanitizedResponse = this._sanitizeItisData(response.data.response.docs); + + // Sort the results to place exact matches at the top + const sortedResponse = sortTaxonSearchResults(sanitizedResponse, searchTerms); + + // Return only a subset of the records + // More records than are returned here are requested from ITIS to help find and prioritize exact matches + return sortedResponse.slice(0, 15); } /** @@ -67,19 +76,22 @@ export class ItisService { } /** - * Cleans up the ITIS search response data. + * Cleans up the ITIS search response data * * @param {ItisSolrSearchResponse[]} data * @memberof ItisService */ _sanitizeItisData = (data: ItisSolrSearchResponse[]): TaxonSearchResult[] => { return data.map((item: ItisSolrSearchResponse) => { - const commonName = item.commonNames ? item.commonNames[0].split('$')[1] : null; + const englishNames = item.commonNames?.filter((name) => name.split('$')[2] === 'English'); + const commonNames = englishNames?.map((name) => name.split('$')[1]) ?? []; return { tsn: Number(item.tsn), - commonName: commonName, - scientificName: item.scientificName + commonNames: commonNames, + scientificName: item.scientificName, + rank: item.rank, + kingdom: item.kingdom }; }); }; @@ -100,9 +112,9 @@ export class ItisService { } return `${itisUrl}?${this._getItisSolrTypeParam()}&${this._getItisSolrSortParam( - 'nameWOInd', - 'asc', - 25 + ['kingdom'], + ['asc'], + 150 )}&${this._getItisSolrFilterParam()}&${this._getItisSolrQueryParam(searchTerms)}`; } @@ -122,9 +134,9 @@ export class ItisService { } return `${itisUrl}??${this._getItisSolrTypeParam()}&${this._getItisSolrSortParam( - 'nameWOInd', - 'asc', - 25 + ['kingdom'], + ['asc'], + 150 )}&${this._getItisSolrFilterParam()}&&q=${this._getItisSolrTsnSearch(searchTsnIds)}`; } @@ -153,12 +165,12 @@ export class ItisService { * * @param {string} sortBy * @param {('asc' | 'desc')} sortDir - * @param {number} [limit=25] + * @param {number} limit * @return {*} {string} * @memberof ItisService */ - _getItisSolrSortParam(sortBy: string, sortDir: 'asc' | 'desc', limit = 25): string { - return `sort=${sortBy}+${sortDir}&rows=${limit}`; + _getItisSolrSortParam(sortBy: string[], sortDir: ('asc' | 'desc')[], limit: number): string { + return `sort=${sortBy.map((f, index) => `${f}+${sortDir[index]}`).join(',')}&rows=${limit}`; } /** @@ -168,7 +180,7 @@ export class ItisService { * @memberof ItisService */ _getItisSolrFilterParam(): string { - return 'omitHeader=true&fl=tsn+scientificName:nameWOInd+kingdom+parentTSN+commonNames:vernacular+updateDate+usage'; + return 'omitHeader=true&fl=tsn+scientificName:nameWOInd+kingdom+parentTSN+commonNames:vernacular+updateDate+usage+rank'; } /** diff --git a/api/src/services/taxonomy-service.test.ts b/api/src/services/taxonomy-service.test.ts index bb6af9df..1ddc58b9 100644 --- a/api/src/services/taxonomy-service.test.ts +++ b/api/src/services/taxonomy-service.test.ts @@ -16,14 +16,15 @@ describe('TaxonomyService', () => { const getItisSolrSearchResponse: ItisSolrSearchResponse[] = [ { - commonNames: ['$commonName'], + commonNames: ['$commonNames'], kingdom: 'kingdom', name: 'name', parentTSN: 'parentTSN', scientificName: 'scientificName', tsn: 'tsn', updateDate: 'updateDate', - usage: 'usage' + usage: 'usage', + rank: 'rank' } ]; @@ -63,7 +64,7 @@ describe('TaxonomyService', () => { const response = await taxonomyService.getTaxonByTsnIds([1]); expect(repo).to.be.calledOnce; - expect(response).to.be.eql([{ tsn: 1, commonName: 'common_name', scientificName: 'itis_scientific_name' }]); + expect(response).to.be.eql([{ tsn: 1, commonNames: ['common_name'], scientificName: 'itis_scientific_name' }]); }); it('if some records do not exist in db should return array of taxon records', async () => { @@ -118,8 +119,8 @@ describe('TaxonomyService', () => { expect(searchItisByTSNStub).to.be.calledOnce; expect(itisService).to.be.calledOnce; expect(response).to.be.eql([ - { tsn: 1, commonName: 'common_name', scientificName: 'itis_scientific_name' }, - { tsn: 2, commonName: 'common_name', scientificName: 'itis_scientific_name' } + { tsn: 1, commonNames: ['common_name'], scientificName: 'itis_scientific_name' }, + { tsn: 2, commonNames: ['common_name'], scientificName: 'itis_scientific_name' } ]); }); }); @@ -135,7 +136,7 @@ describe('TaxonomyService', () => { itis_tsn: 1, bc_taxon_code: null, itis_scientific_name: 'scientificName', - common_name: 'commonName', + common_name: 'commonNames', itis_data: {}, record_effective_date: 'updateDate', record_end_date: null, @@ -154,7 +155,7 @@ describe('TaxonomyService', () => { itis_tsn: 1, bc_taxon_code: null, itis_scientific_name: 'scientificName', - common_name: 'commonName', + common_name: 'commonNames', itis_data: {}, record_effective_date: 'updateDate', record_end_date: null, diff --git a/api/src/services/taxonomy-service.ts b/api/src/services/taxonomy-service.ts index 5b24e759..b9686cd8 100644 --- a/api/src/services/taxonomy-service.ts +++ b/api/src/services/taxonomy-service.ts @@ -7,7 +7,7 @@ const defaultLog = getLogger('services/taxonomy-service'); export type TaxonSearchResult = { tsn: number; - commonName: string | null; + commonNames: string[]; scientificName: string; }; @@ -56,13 +56,12 @@ export class TaxonomyService { } _sanitizeTaxonRecordsData(taxonRecords: TaxonRecord[]): TaxonSearchResult[] { - return taxonRecords.map((item: TaxonRecord) => { - return { - tsn: item.itis_tsn, - commonName: item.common_name, - scientificName: item.itis_scientific_name - }; - }); + return taxonRecords.map((item: TaxonRecord) => ({ + tsn: item.itis_tsn, + // TODO: wrap commonNames in array until the database supports multiple common names + commonNames: item?.common_name ? [item.common_name] : [], + scientificName: item.itis_scientific_name + })); } /** @@ -73,23 +72,23 @@ export class TaxonomyService { * @memberof TaxonomyService */ async addItisTaxonRecord(itisSolrResponse: ItisSolrSearchResponse): Promise { - let commonName = null; - if (itisSolrResponse.commonNames) { - commonName = itisSolrResponse.commonNames[0].split('$')[1]; - /* Sample itisResponse: - * commonNames: [ - * '$withered wooly milk-vetch$English$N$152846$2012-12-21 00:00:00$', - * '$woolly locoweed$English$N$124501$2011-06-29 00:00:00$', - * '$Davis Mountains locoweed$English$N$124502$2011-06-29 00:00:00$', - * '$woolly milkvetch$English$N$72035$2012-12-21 00:00:00$' - * ] - */ - } + const commonNames = + itisSolrResponse.commonNames + .filter((name) => name.split('$')[2] === 'English') + .map((name) => name.split('$')[1]) ?? []; + /* Sample itisResponse: + * commonNames: [ + * '$withered wooly milk-vetch$English$N$152846$2012-12-21 00:00:00$', + * '$woolly locoweed$English$N$124501$2011-06-29 00:00:00$', + * '$Davis Mountains locoweed$English$N$124502$2011-06-29 00:00:00$', + * '$woolly milkvetch$English$N$72035$2012-12-21 00:00:00$' + * ] + */ return this.taxonRepository.addItisTaxonRecord( Number(itisSolrResponse.tsn), itisSolrResponse.scientificName, - commonName, + commonNames, itisSolrResponse, itisSolrResponse.updateDate ); diff --git a/api/src/utils/itis-sort.test.ts b/api/src/utils/itis-sort.test.ts new file mode 100644 index 00000000..94eb506b --- /dev/null +++ b/api/src/utils/itis-sort.test.ts @@ -0,0 +1,80 @@ +import { expect } from 'chai'; +import { describe } from 'mocha'; +import { TaxonSearchResult } from '../services/taxonomy-service'; +import { sortTaxonSearchResults } from './itis-sort'; + +describe('itis-sort', () => { + describe('sortTaxonSearchResults', () => { + it('Sorts the list when there is only 1 item', () => { + const data: TaxonSearchResult[] = [ + { + tsn: 1, + commonNames: ['Moose', 'moose'], + scientificName: 'Alces alces' + } + ]; + const searchTerms = ['Moose']; + + const result = sortTaxonSearchResults(data, searchTerms); + + expect(result.length).to.equal(data.length); + expect(result[0].tsn).to.equal(1); + }); + + it('Sorts the list when there are exact matches', () => { + const data: TaxonSearchResult[] = [ + { + tsn: 1, + commonNames: ['Goose', 'goose'], + scientificName: 'Goose goose' + }, + { + tsn: 2, + commonNames: ['Moose', 'moose'], + scientificName: 'Moose moose' + }, + { + tsn: 3, + commonNames: ['House'], + scientificName: 'House' + } + ]; + const searchTerms = ['Moose']; + + const result = sortTaxonSearchResults(data, searchTerms); + + expect(result.length).to.equal(data.length); + expect(result[0].tsn).to.equal(2); + expect(result[1].tsn).to.equal(1); + expect(result[2].tsn).to.equal(3); + }); + + it('Sorts the list when there are no exact matches', () => { + const data: TaxonSearchResult[] = [ + { + tsn: 1, + commonNames: ['Goose', 'goose'], + scientificName: 'Goose goose' + }, + { + tsn: 2, + commonNames: ['Moose', 'moose'], + scientificName: 'Moose moose' + }, + { + tsn: 3, + commonNames: ['House'], + scientificName: 'House' + } + ]; + const searchTerms = ['oose']; + + const result = sortTaxonSearchResults(data, searchTerms); + + expect(result.length).to.equal(data.length); + expect(result[0].tsn).to.equal(1); + expect(result[1].tsn).to.equal(2); + expect(result[2].tsn).to.equal(3); + }); + }); +}); diff --git a/api/src/utils/itis-sort.ts b/api/src/utils/itis-sort.ts new file mode 100644 index 00000000..a4c4ec70 --- /dev/null +++ b/api/src/utils/itis-sort.ts @@ -0,0 +1,89 @@ +import { TaxonSearchResult } from '../services/taxonomy-service'; + +/** + * Sorts the ITIS response by how strongly records match the search terms + * + * @param {TaxonSearchResult[]} taxonSearchResults + * @param {string[]} searchTerms + * @return {*} {TaxonSearchResult[]} + */ +export const sortTaxonSearchResults = ( + taxonSearchResults: TaxonSearchResult[], + searchTerms: string[] +): TaxonSearchResult[] => { + const searchTermsLower = searchTerms.map((item) => item.toLowerCase()); + const searchTermJoined = searchTermsLower.join(' '); + + // Caches the scientific name data + const scientificNameDataMap = new Map(); + // Caches the common name data + const commonNamesDataMap = new Map(); + + // Returns the scientific name data, adding it to the cache if it doesn't exist + const getScientificNameData = (scientificName: string) => { + if (!scientificNameDataMap.has(scientificName)) { + const lowercased = scientificName.toLowerCase(); + scientificNameDataMap.set(scientificName, { words: lowercased.trim().split(' '), lowercased }); + } + + return scientificNameDataMap.get(scientificName) as { words: string[]; lowercased: string }; + }; + + // Returns the common names data, adding it to the cache if it doesn't exist + const getCommonNamesData = (commonNames: string[]) => { + return commonNames.map((commonName) => { + if (!commonNamesDataMap.has(commonName)) { + const lowercased = commonName.toLowerCase(); + commonNamesDataMap.set(commonName, { words: lowercased.trim().split(' '), lowercased }); + } + + return commonNamesDataMap.get(commonName) as { words: string[]; lowercased: string }; + }); + }; + + /** + * Custom scoring function to determine how well a record matches the search terms. + * + * @param {TaxonSearchResult} taxonSearchResult + * @return {*} + */ + const calculateScore = (taxonSearchResult: TaxonSearchResult) => { + let score = 0; + + const scientificNameData = getScientificNameData(taxonSearchResult.scientificName); + const commonNamesData = getCommonNamesData(taxonSearchResult.commonNames); + + // Check if any word in the scientific or common name matches ANY of the search terms + // eg. ['Black', 'bear'] -> "Black" matches on "Black widow" + if ( + searchTermsLower.some( + (term) => scientificNameData.words.includes(term) || commonNamesData.some((data) => data.words.includes(term)) + ) + ) { + score += 1; + } + + // Check if either the scientific name or any common name CONTAINS the search terms joined + // eg. ['Black', 'bear'] -> "Black bear" matches on "American black bear" + if ( + scientificNameData.lowercased.includes(searchTermJoined) || + commonNamesData.some((data) => data.lowercased.includes(searchTermJoined)) + ) { + score += 2; + } + + // Check if either the scientific name or any common name is EXACTLY EQUAL to the search terms joined + // eg. ['Wolf'] -> "Wolf" is prioritized over "Forest Wolf" + if ( + scientificNameData.lowercased === searchTermJoined || + commonNamesData.some((data) => data.lowercased === searchTermJoined) + ) { + score += 3; + } + + return score; + }; + + // Sort the data by the score + return taxonSearchResults.sort((a, b) => calculateScore(b) - calculateScore(a)); +}; diff --git a/app/package-lock.json b/app/package-lock.json index ca5135e9..a4fa1974 100644 --- a/app/package-lock.json +++ b/app/package-lock.json @@ -1838,12 +1838,33 @@ "integrity": "sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==", "dev": true }, + "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==", + "dev": true, + "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==", + "dev": true + }, "emoji-regex": { "version": "9.2.2", "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz", "integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==", "dev": true }, + "is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "dev": true + }, "string-width": { "version": "5.1.2", "resolved": "https://registry.npmjs.org/string-width/-/string-width-5.1.2.tgz", @@ -1855,6 +1876,43 @@ "strip-ansi": "^7.0.1" } }, + "string-width-cjs": { + "version": "npm:string-width@4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "dev": true, + "requires": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "dependencies": { + "emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "dev": true + }, + "strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "dev": true, + "requires": { + "ansi-regex": "^5.0.1" + } + } + } + }, + "strip-ansi-cjs": { + "version": "npm:strip-ansi@6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "dev": true, + "requires": { + "ansi-regex": "^5.0.1" + } + }, "wrap-ansi": { "version": "8.1.0", "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-8.1.0.tgz", @@ -1865,6 +1923,54 @@ "string-width": "^5.0.1", "strip-ansi": "^7.0.1" } + }, + "wrap-ansi-cjs": { + "version": "npm:wrap-ansi@7.0.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", + "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", + "dev": true, + "requires": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + }, + "dependencies": { + "ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "requires": { + "color-convert": "^2.0.1" + } + }, + "emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "dev": true + }, + "string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "dev": true, + "requires": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + } + }, + "strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "dev": true, + "requires": { + "ansi-regex": "^5.0.1" + } + } + } } } }, @@ -18107,40 +18213,6 @@ } } }, - "string-width-cjs": { - "version": "npm:string-width@4.2.3", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", - "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", - "dev": true, - "requires": { - "emoji-regex": "^8.0.0", - "is-fullwidth-code-point": "^3.0.0", - "strip-ansi": "^6.0.1" - }, - "dependencies": { - "emoji-regex": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", - "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", - "dev": true - }, - "is-fullwidth-code-point": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", - "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", - "dev": true - }, - "strip-ansi": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", - "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", - "dev": true, - "requires": { - "ansi-regex": "^5.0.1" - } - } - } - }, "string.prototype.matchall": { "version": "4.0.11", "resolved": "https://registry.npmjs.org/string.prototype.matchall/-/string.prototype.matchall-4.0.11.tgz", @@ -18236,15 +18308,6 @@ } } }, - "strip-ansi-cjs": { - "version": "npm:strip-ansi@6.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", - "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", - "dev": true, - "requires": { - "ansi-regex": "^5.0.1" - } - }, "strip-bom": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-2.0.0.tgz", @@ -19871,75 +19934,6 @@ } } }, - "wrap-ansi-cjs": { - "version": "npm:wrap-ansi@7.0.0", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", - "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", - "dev": true, - "requires": { - "ansi-styles": "^4.0.0", - "string-width": "^4.1.0", - "strip-ansi": "^6.0.0" - }, - "dependencies": { - "ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dev": true, - "requires": { - "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==", - "dev": true, - "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==", - "dev": true - }, - "emoji-regex": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", - "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", - "dev": true - }, - "is-fullwidth-code-point": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", - "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", - "dev": true - }, - "string-width": { - "version": "4.2.3", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", - "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", - "dev": true, - "requires": { - "emoji-regex": "^8.0.0", - "is-fullwidth-code-point": "^3.0.0", - "strip-ansi": "^6.0.1" - } - }, - "strip-ansi": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", - "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", - "dev": true, - "requires": { - "ansi-regex": "^5.0.1" - } - } - } - }, "wrappy": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", diff --git a/database/package-lock.json b/database/package-lock.json index 958af2e6..bc8a1ef2 100644 --- a/database/package-lock.json +++ b/database/package-lock.json @@ -526,7 +526,7 @@ "color-name": { "version": "1.1.3", "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", - "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==", + "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=", "dev": true }, "colorette": { @@ -542,7 +542,7 @@ "concat-map": { "version": "0.0.1", "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", - "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==", + "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=", "dev": true }, "core-util-is": { @@ -1032,7 +1032,7 @@ "fast-levenshtein": { "version": "2.0.6", "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", - "integrity": "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==", + "integrity": "sha1-PYpcZog6FqMMqGQ+hR8Zuqd5eRc=", "dev": true }, "fastq": { @@ -1101,7 +1101,7 @@ "fs.realpath": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", - "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==", + "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=", "dev": true }, "function-bind": { @@ -1124,7 +1124,7 @@ "functional-red-black-tree": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/functional-red-black-tree/-/functional-red-black-tree-1.0.1.tgz", - "integrity": "sha512-dsKNQNdj6xA3T+QlADDA7mOSlX0qiMINjn0cgr+eGHGsbSHzTabcIogz2+p/iqP1Xs6EP/sS2SbqH+brGTbq0g==", + "integrity": "sha1-GwqzvVU7Kg1jmdKcDj6gslIHgyc=", "dev": true }, "functions-have-names": { @@ -1273,7 +1273,7 @@ "has-flag": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", - "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==", + "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", "dev": true }, "has-property-descriptors": { @@ -1347,13 +1347,13 @@ "imurmurhash": { "version": "0.1.4", "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", - "integrity": "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==", + "integrity": "sha1-khi5srkoojixPcT7a21XbyMUU+o=", "dev": true }, "inflight": { "version": "1.0.6", "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", - "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==", + "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", "dev": true, "requires": { "once": "^1.3.0", @@ -1395,7 +1395,7 @@ "is-arrayish": { "version": "0.2.1", "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", - "integrity": "sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg==", + "integrity": "sha1-d8mYQFJ6qOyxqLppe4BkWnqSap0=", "dev": true }, "is-bigint": { @@ -1452,7 +1452,7 @@ "is-extglob": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", - "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==", + "integrity": "sha1-qIwCU1eR8C7TfHahueqXc8gz+MI=", "dev": true }, "is-fullwidth-code-point": { @@ -1555,7 +1555,7 @@ "isexe": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", - "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", + "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=", "dev": true }, "js-tokens": { @@ -1595,7 +1595,7 @@ "json-stable-stringify-without-jsonify": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz", - "integrity": "sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==", + "integrity": "sha1-nbe1lJatPzz+8wp1FC0tkwrXJlE=", "dev": true }, "jsonparse": { @@ -1647,7 +1647,7 @@ "load-json-file": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-4.0.0.tgz", - "integrity": "sha512-Kx8hMakjX03tiGTLAIdJ+lL0htKnXjEZN6hk/tozf/WOuYGdZBJrZ+rCJRbVCugsjB3jMLn9746NsQIf5VjBMw==", + "integrity": "sha1-L19Fq5HjMhYjT9U62rZo607AmTs=", "dev": true, "requires": { "graceful-fs": "^4.1.2", @@ -1670,7 +1670,7 @@ "lodash.truncate": { "version": "4.4.2", "resolved": "https://registry.npmjs.org/lodash.truncate/-/lodash.truncate-4.4.2.tgz", - "integrity": "sha512-jttmRe7bRse52OsWIMDLaXxWqRAmtIUccAQ3garviCqJjafXOfNMO0yMfNpdD6zbGaTU0P5Nz7e7gAT6cKmJRw==", + "integrity": "sha1-WjUNoLERO4N+z//VgSy+WNbq4ZM=", "dev": true }, "lru-cache": { @@ -1691,7 +1691,7 @@ "memorystream": { "version": "0.3.1", "resolved": "https://registry.npmjs.org/memorystream/-/memorystream-0.3.1.tgz", - "integrity": "sha512-S3UwM3yj5mtUSEfP41UZmt/0SCoVYUcU1rkXv+BQ5Ig8ndL4sPoJNBUJERafdPb5jjHJGuMgytgKvKIf58XNBw==", + "integrity": "sha1-htcJCzDORV1j+64S3aUaR93K+bI=", "dev": true }, "merge2": { @@ -1727,7 +1727,7 @@ "natural-compare": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", - "integrity": "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==", + "integrity": "sha1-Sr6/7tdUHywnrPspvbvRXI1bpPc=", "dev": true }, "nice-try": { @@ -1798,7 +1798,7 @@ "path-key": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/path-key/-/path-key-2.0.1.tgz", - "integrity": "sha512-fEHGKCSmUSDPv4uoj8AlD+joPlq3peND+HRYyxFz4KPw4z926S/b8rIuFs2FYJg3BwsxJf6A9/3eIdLaYC+9Dw==", + "integrity": "sha1-QRyttXTFoUDTpLGRDUDYDMn0C0A=", "dev": true }, "semver": { @@ -1810,7 +1810,7 @@ "shebang-command": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-1.2.0.tgz", - "integrity": "sha512-EV3L1+UQWGor21OmnvojK36mhg+TyIKDh3iFBKBohr5xeXIhNBcx8oWdgkTEEQ+BEFFYdLRuqMfd5L84N1V5Vg==", + "integrity": "sha1-RKrGW2lbAzmJaMOfNj/uXer98eo=", "dev": true, "requires": { "shebang-regex": "^1.0.0" @@ -1819,7 +1819,7 @@ "shebang-regex": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-1.0.0.tgz", - "integrity": "sha512-wpoSFAxys6b2a2wHZ1XpDSgD7N9iVjg29Ph9uV/uaP9Ex/KXlkTZTeddxDPSYQpgvzKLGJke2UU0AzoGCjNIvQ==", + "integrity": "sha1-2kL0l0DAtC2yypcoVxyxkMmO/qM=", "dev": true }, "which": { @@ -1860,7 +1860,7 @@ "once": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", - "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", + "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", "dev": true, "requires": { "wrappy": "1" @@ -1897,7 +1897,7 @@ "parse-json": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-4.0.0.tgz", - "integrity": "sha512-aOIos8bujGN93/8Ox/jPLh7RwVnPEysynVFE+fQZyg6jKELEHwzgKdLRFHUgXJL6kylijVSBC4BvN9OmsB48Rw==", + "integrity": "sha1-vjX1Qlvh9/bHRxhPmKeIy5lHfuA=", "dev": true, "requires": { "error-ex": "^1.3.1", @@ -1907,7 +1907,7 @@ "path-is-absolute": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", - "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==", + "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=", "dev": true }, "path-key": { @@ -2003,7 +2003,7 @@ "pify": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz", - "integrity": "sha512-C3FsVNH1udSEX48gGX1xfvwTWfsYWj5U+8/uK15BGzIGrKoUpghX8hWZwa/OFnakBiiVNmBvemTJR5mcy7iPcg==", + "integrity": "sha1-5aSs0sEB/fPZpNB/DbxNtJ3SgXY=", "dev": true }, "possible-typed-array-names": { @@ -2020,7 +2020,7 @@ "postgres-bytea": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/postgres-bytea/-/postgres-bytea-1.0.0.tgz", - "integrity": "sha512-xy3pmLuQqRBZBXDULy7KbaitYqLcmxigw14Q5sj8QBVLqEwXfeybIKVWiqAXTlcvdvb0+xkOtDbfQMOf4lST1w==" + "integrity": "sha1-AntTPAqokOJtFy1Hz5zOzFIazTU=" }, "postgres-date": { "version": "1.0.7", @@ -2089,7 +2089,7 @@ "read-pkg": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-3.0.0.tgz", - "integrity": "sha512-BLq/cCO9two+lBgiTYNqD6GdtK8s4NpaWrl6/rCO9w0TUS8oJl7cmToOZfRYllKTISY6nt1U7jQ53brmKqY6BA==", + "integrity": "sha1-nLxoaXj+5l0WwA4rGcI3/Pbjg4k=", "dev": true, "requires": { "load-json-file": "^4.0.0", @@ -2234,7 +2234,7 @@ "semver": { "version": "4.3.2", "resolved": "https://registry.npmjs.org/semver/-/semver-4.3.2.tgz", - "integrity": "sha512-VyFUffiBx8hABJ9HYSTXLRwyZtdDHMzMtFmID1aiNAD2BZppBmJm0Hqw3p2jkgxP9BNt1pQ9RnC49P0EcXf6cA==" + "integrity": "sha1-x6BxWKgL7dBSNVt3DYLWZA+AO+c=" }, "set-function-length": { "version": "1.2.2", @@ -2378,7 +2378,7 @@ "sprintf-js": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", - "integrity": "sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==", + "integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw=", "dev": true }, "string-width": { @@ -2459,7 +2459,7 @@ "strip-bom": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz", - "integrity": "sha512-vavAMRXOgBVNF6nyEEmL3DBK19iRpDcoIwW+swQ+CbGiu7lju6t+JklA1MHweoWtadgt4ISVUsXLyDq34ddcwA==", + "integrity": "sha1-IzTBjpx1n3vdVv3vfprj1YjmjtM=", "dev": true }, "strip-json-comments": { @@ -2523,7 +2523,7 @@ "text-table": { "version": "0.2.0", "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", - "integrity": "sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==", + "integrity": "sha1-f17oI66AUgfACvLfSoTsP8+lcLQ=", "dev": true }, "through": { @@ -2748,7 +2748,7 @@ "wrappy": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", - "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==", + "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=", "dev": true }, "xtend": {