From 77f45397b856898ff6bba064298f012d5452962b Mon Sep 17 00:00:00 2001 From: Gary Tempus Jr Date: Tue, 17 Dec 2024 18:12:29 -0500 Subject: [PATCH 01/13] :white_check_mark: test(SerializerV2): add initial tests for admin boundary areas GTC-3085 --- .../serializers/area.serializerV2.test.js | 49 +++++++++++++++++++ 1 file changed, 49 insertions(+) create mode 100644 app/test/unit/serializers/area.serializerV2.test.js diff --git a/app/test/unit/serializers/area.serializerV2.test.js b/app/test/unit/serializers/area.serializerV2.test.js new file mode 100644 index 0000000..3795136 --- /dev/null +++ b/app/test/unit/serializers/area.serializerV2.test.js @@ -0,0 +1,49 @@ +const chai = require('chai'); +const AreaModel = require('models/area.modelV2'); +const areaSerializerV2 = require('serializers/area.serializerV2'); + +const { expect } = chai; + +describe('Area Serializer V2', () => { + const area = { + name: 'Distrito Central, Francisco Morazán, Honduras', + geostore: 'abcf7041e2fbc5e8e7774178157ababe', + iso: { + country: 'HND', + region: '8', + subregion: '4', + }, + admin: { + adm0: 'HND', + adm1: 8, + adm2: 4, + } + }; + + it('should include the name of the Area', () => { + const result = areaSerializerV2.serialize(new AreaModel(area)); + expect(result.data.attributes.name).to.equal('Distrito Central, Francisco Morazán, Honduras'); + }); + + it('should include the geostore of the Area', () => { + const result = areaSerializerV2.serialize(new AreaModel(area)); + expect(result.data.attributes.geostore).to.equal('abcf7041e2fbc5e8e7774178157ababe'); + }); + + describe('Administrative Boundary IDs', () => { + describe('The ISO attribute', () => { + it('should include the country, region, and subregion', () => { + const result = areaSerializerV2.serialize(new AreaModel(area)); + expect(result.data.attributes.iso).to.deep.include({ country: 'HND', region: '8', subregion: '4' }); + }); + + }); + + describe('The Admin attribute', () => { + it('should include the adm0, adm1, and adm2 IDs', () => { + const result = areaSerializerV2.serialize(new AreaModel(area)); + expect(result.data.attributes.admin).to.deep.include({ adm0: 'HND', adm1: 8, adm2: 4 }); + }); + }); + }); +}); From 769b4f2a77a63641d6f3b83154352bf476d1751f Mon Sep 17 00:00:00 2001 From: Gary Tempus Jr Date: Wed, 18 Dec 2024 12:40:38 -0500 Subject: [PATCH 02/13] feat(SerializerV2): add `source` attribute to representations For administrative boundary areas, add a `source` attribute that describes the provider and the version of the IDs being used. GTC-3085 --- app/src/serializers/area.serializerV2.js | 38 +++++++++++++++++++ .../serializers/area.serializerV2.test.js | 9 +++++ 2 files changed, 47 insertions(+) diff --git a/app/src/serializers/area.serializerV2.js b/app/src/serializers/area.serializerV2.js index 4f745ce..af63fcb 100644 --- a/app/src/serializers/area.serializerV2.js +++ b/app/src/serializers/area.serializerV2.js @@ -39,6 +39,42 @@ const areaSerializer = new JSONAPISerializer('area', { keyForAttribute: 'camelCase' }); +function isAdministrativeBoundary(area) { + if (area.attributes && area.attributes.iso && area.attributes.iso.country) { + return !!area.attributes.iso.country; + } + return area.attributes && area.attributes.admin + ? !!area.attributes.admin.adm0 + : false; + +} + +function addSourceToIsoAttribute(area) { + if (area.attributes ? area.attributes.iso : undefined) { + area.attributes.iso.source = { + provider: 'gadm', + version: '3.6', + }; + } +} + +function addSourceToAdminAttribute(area) { + if (area.attributes ? area.attributes.admin : undefined) { + area.attributes.admin.source = { + provider: 'gadm', + version: '3.6', + }; + } +} + +const addSourceForAdministrativeAreas = (data) => { + const areas = Array.isArray(data) ? data : [data]; + areas.filter(isAdministrativeBoundary).forEach((area) => { + addSourceToIsoAttribute(area); + addSourceToAdminAttribute(area); + }); +}; + class AreaSerializer { static serialize(data, link = null) { @@ -53,6 +89,8 @@ class AreaSerializer { }); } + addSourceForAdministrativeAreas(serializedData.data); + if (link) { serializedData.links = { self: `${link}page[number]=${data.page}&page[size]=${data.limit}`, diff --git a/app/test/unit/serializers/area.serializerV2.test.js b/app/test/unit/serializers/area.serializerV2.test.js index 3795136..8a8cc69 100644 --- a/app/test/unit/serializers/area.serializerV2.test.js +++ b/app/test/unit/serializers/area.serializerV2.test.js @@ -37,6 +37,10 @@ describe('Area Serializer V2', () => { expect(result.data.attributes.iso).to.deep.include({ country: 'HND', region: '8', subregion: '4' }); }); + it('should include the administrative ID provider and version', () => { + const result = areaSerializerV2.serialize(new AreaModel(area)); + expect(result.data.attributes.iso).to.deep.include({ source: { provider: 'gadm', version: '3.6' } }); + }); }); describe('The Admin attribute', () => { @@ -44,6 +48,11 @@ describe('Area Serializer V2', () => { const result = areaSerializerV2.serialize(new AreaModel(area)); expect(result.data.attributes.admin).to.deep.include({ adm0: 'HND', adm1: 8, adm2: 4 }); }); + + it('should include the administrative ID provider and version', () => { + const result = areaSerializerV2.serialize(new AreaModel(area)); + expect(result.data.attributes.admin).to.deep.include({ source: { provider: 'gadm', version: '3.6' } }); + }); }); }); }); From 9de3b572c8dc14b3f4fde4347c0178ee2bdb9807 Mon Sep 17 00:00:00 2001 From: Gary Tempus Jr Date: Wed, 18 Dec 2024 12:46:53 -0500 Subject: [PATCH 03/13] refactor(SerializerV2): extract addSource method --- app/src/serializers/area.serializerV2.js | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/app/src/serializers/area.serializerV2.js b/app/src/serializers/area.serializerV2.js index af63fcb..6ba521e 100644 --- a/app/src/serializers/area.serializerV2.js +++ b/app/src/serializers/area.serializerV2.js @@ -49,21 +49,22 @@ function isAdministrativeBoundary(area) { } +function addSource(adminInfo) { + adminInfo.source = { + provider: 'gadm', + version: '3.6', + }; +} + function addSourceToIsoAttribute(area) { if (area.attributes ? area.attributes.iso : undefined) { - area.attributes.iso.source = { - provider: 'gadm', - version: '3.6', - }; + addSource(area.attributes.iso); } } function addSourceToAdminAttribute(area) { if (area.attributes ? area.attributes.admin : undefined) { - area.attributes.admin.source = { - provider: 'gadm', - version: '3.6', - }; + addSource(area.attributes.admin); } } From 3c8c7e7919a20a677b247c7bf33766ef1aec23ad Mon Sep 17 00:00:00 2001 From: Gary Tempus Jr Date: Wed, 18 Dec 2024 13:55:53 -0500 Subject: [PATCH 04/13] refactor(SerializerV2): use `null` instead of `undefined` --- app/src/serializers/area.serializerV2.js | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/app/src/serializers/area.serializerV2.js b/app/src/serializers/area.serializerV2.js index 6ba521e..ba13a90 100644 --- a/app/src/serializers/area.serializerV2.js +++ b/app/src/serializers/area.serializerV2.js @@ -43,6 +43,7 @@ function isAdministrativeBoundary(area) { if (area.attributes && area.attributes.iso && area.attributes.iso.country) { return !!area.attributes.iso.country; } + return area.attributes && area.attributes.admin ? !!area.attributes.admin.adm0 : false; @@ -57,13 +58,13 @@ function addSource(adminInfo) { } function addSourceToIsoAttribute(area) { - if (area.attributes ? area.attributes.iso : undefined) { + if (area.attributes ? area.attributes.iso : null) { addSource(area.attributes.iso); } } function addSourceToAdminAttribute(area) { - if (area.attributes ? area.attributes.admin : undefined) { + if (area.attributes ? area.attributes.admin : null) { addSource(area.attributes.admin); } } From a518ff430d6e3b7253c1c70e8cafffaa10b25e23 Mon Sep 17 00:00:00 2001 From: Gary Tempus Jr Date: Wed, 18 Dec 2024 14:07:54 -0500 Subject: [PATCH 05/13] :white_check_mark: test(Serializer): add initial tests for admin boundary areas GTC-3085 --- app/src/serializers/area.serializer.js | 40 +++++++++++++++++++ .../unit/serializers/area.serializer.test.js | 40 +++++++++++++++++++ 2 files changed, 80 insertions(+) create mode 100644 app/test/unit/serializers/area.serializer.test.js diff --git a/app/src/serializers/area.serializer.js b/app/src/serializers/area.serializer.js index da1c92b..92c7dc3 100644 --- a/app/src/serializers/area.serializer.js +++ b/app/src/serializers/area.serializer.js @@ -25,6 +25,44 @@ const areaSerializer = new JSONAPISerializer('area', { keyForAttribute: 'camelCase' }); +function isAdministrativeBoundary(area) { + if (area.attributes && area.attributes.iso && area.attributes.iso.country) { + return !!area.attributes.iso.country; + } + + return area.attributes && area.attributes.admin + ? !!area.attributes.admin.adm0 + : false; + +} + +function addSource(adminInfo) { + adminInfo.source = { + provider: 'gadm', + version: '2.8', + }; +} + +function addSourceToIsoAttribute(area) { + if (area.attributes ? area.attributes.iso : null) { + addSource(area.attributes.iso); + } +} + +function addSourceToAdminAttribute(area) { + if (area.attributes ? area.attributes.admin : null) { + addSource(area.attributes.admin); + } +} + +const addSourceForAdministrativeAreas = (data) => { + const areas = Array.isArray(data) ? data : [data]; + areas.filter(isAdministrativeBoundary).forEach((area) => { + addSourceToIsoAttribute(area); + addSourceToAdminAttribute(area); + }); +}; + class AreaSerializer { static serialize(data, link = null) { @@ -35,6 +73,8 @@ class AreaSerializer { result = areaSerializer.serialize(data); } + addSourceForAdministrativeAreas(result.data); + if (link) { result.links = { self: `${link}page[number]=${data.page}&page[size]=${data.limit}`, diff --git a/app/test/unit/serializers/area.serializer.test.js b/app/test/unit/serializers/area.serializer.test.js new file mode 100644 index 0000000..df23bc6 --- /dev/null +++ b/app/test/unit/serializers/area.serializer.test.js @@ -0,0 +1,40 @@ +const chai = require('chai'); +const AreaModel = require('models/area.model'); +const areaSerializer = require('serializers/area.serializer'); + +const { expect } = chai; + +describe('Area Serializer', () => { + const area = { + name: 'Distrito Central, Francisco Morazán, Honduras', + geostore: 'abcf7041e2fbc5e8e7774178157ababe', + iso: { + country: 'HND', + region: '8', + }, + }; + + it('should include the name of the Area', () => { + const result = areaSerializer.serialize(new AreaModel(area)); + expect(result.data.attributes.name).to.equal('Distrito Central, Francisco Morazán, Honduras'); + }); + + it('should include the geostore of the Area', () => { + const result = areaSerializer.serialize(new AreaModel(area)); + expect(result.data.attributes.geostore).to.equal('abcf7041e2fbc5e8e7774178157ababe'); + }); + + describe('Administrative Boundary IDs', () => { + describe('The ISO attribute', () => { + it('should include the country and region', () => { + const result = areaSerializer.serialize(new AreaModel(area)); + expect(result.data.attributes.iso).to.deep.include({ country: 'HND', region: '8', }); + }); + + it('should include the administrative ID provider and version', () => { + const result = areaSerializer.serialize(new AreaModel(area)); + expect(result.data.attributes.iso).to.deep.include({ source: { provider: 'gadm', version: '2.8' } }); + }); + }); + }); +}); From 028038b7dc1d21277c688f4bb3998f8a7e4e9db2 Mon Sep 17 00:00:00 2001 From: Gary Tempus Jr Date: Wed, 18 Dec 2024 15:18:34 -0500 Subject: [PATCH 06/13] refactor: moved behavior for adding `source` to its own module GTC-3085 --- app/src/serializers/adminSourceUtils.js | 54 +++++++++++++++++++ app/src/serializers/area.serializer.js | 42 +-------------- app/src/serializers/area.serializerV2.js | 41 +------------- .../unit/serializers/adminSourceUtils.test.js | 41 ++++++++++++++ 4 files changed, 99 insertions(+), 79 deletions(-) create mode 100644 app/src/serializers/adminSourceUtils.js create mode 100644 app/test/unit/serializers/adminSourceUtils.test.js diff --git a/app/src/serializers/adminSourceUtils.js b/app/src/serializers/adminSourceUtils.js new file mode 100644 index 0000000..618e9aa --- /dev/null +++ b/app/src/serializers/adminSourceUtils.js @@ -0,0 +1,54 @@ +const GADM_VERSION_2_8 = '2.8'; +const GADM_VERSION_3_6 = '3.6'; + +let gadmVersion = GADM_VERSION_2_8; + +function isAdministrativeBoundary(area) { + if (area.attributes && area.attributes.iso && area.attributes.iso.country) { + return !!area.attributes.iso.country; + } + + return area.attributes && area.attributes.admin + ? !!area.attributes.admin.adm0 + : false; + +} + +function addSource(adminInfo) { + adminInfo.source = { + provider: 'gadm', + version: gadmVersion, + }; +} + +function addSourceToIsoAttribute(area) { + if (area.attributes ? area.attributes.iso : null) { + addSource(area.attributes.iso); + } +} + +function addSourceToAdminAttribute(area) { + if (area.attributes ? area.attributes.admin : null) { + addSource(area.attributes.admin); + } +} + +function addSourceForAdministrativeAreas(data) { + const areas = Array.isArray(data) ? data : [data]; + areas.filter(isAdministrativeBoundary).forEach((area) => { + addSourceToIsoAttribute(area); + addSourceToAdminAttribute(area); + }); +} + +const addV1SourceForAdministrativeAreas = (data) => { + gadmVersion = GADM_VERSION_2_8; + addSourceForAdministrativeAreas(data); +}; + +const addV2SourceForAdministrativeAreas = (data) => { + gadmVersion = GADM_VERSION_3_6; + addSourceForAdministrativeAreas(data); +}; + +module.exports = { addV1SourceForAdministrativeAreas, addV2SourceForAdministrativeAreas }; diff --git a/app/src/serializers/area.serializer.js b/app/src/serializers/area.serializer.js index 92c7dc3..f18d8db 100644 --- a/app/src/serializers/area.serializer.js +++ b/app/src/serializers/area.serializer.js @@ -1,4 +1,5 @@ const JSONAPISerializer = require('jsonapi-serializer').Serializer; +const { addV1SourceForAdministrativeAreas } = require('./adminSourceUtils'); const areaSerializer = new JSONAPISerializer('area', { attributes: [ @@ -25,44 +26,6 @@ const areaSerializer = new JSONAPISerializer('area', { keyForAttribute: 'camelCase' }); -function isAdministrativeBoundary(area) { - if (area.attributes && area.attributes.iso && area.attributes.iso.country) { - return !!area.attributes.iso.country; - } - - return area.attributes && area.attributes.admin - ? !!area.attributes.admin.adm0 - : false; - -} - -function addSource(adminInfo) { - adminInfo.source = { - provider: 'gadm', - version: '2.8', - }; -} - -function addSourceToIsoAttribute(area) { - if (area.attributes ? area.attributes.iso : null) { - addSource(area.attributes.iso); - } -} - -function addSourceToAdminAttribute(area) { - if (area.attributes ? area.attributes.admin : null) { - addSource(area.attributes.admin); - } -} - -const addSourceForAdministrativeAreas = (data) => { - const areas = Array.isArray(data) ? data : [data]; - areas.filter(isAdministrativeBoundary).forEach((area) => { - addSourceToIsoAttribute(area); - addSourceToAdminAttribute(area); - }); -}; - class AreaSerializer { static serialize(data, link = null) { @@ -73,7 +36,7 @@ class AreaSerializer { result = areaSerializer.serialize(data); } - addSourceForAdministrativeAreas(result.data); + addV1SourceForAdministrativeAreas(result.data); if (link) { result.links = { @@ -92,7 +55,6 @@ class AreaSerializer { return result; } - } module.exports = AreaSerializer; diff --git a/app/src/serializers/area.serializerV2.js b/app/src/serializers/area.serializerV2.js index ba13a90..0946d42 100644 --- a/app/src/serializers/area.serializerV2.js +++ b/app/src/serializers/area.serializerV2.js @@ -1,4 +1,5 @@ const JSONAPISerializer = require('jsonapi-serializer').Serializer; +const { addV2SourceForAdministrativeAreas } = require('./adminSourceUtils'); const areaSerializer = new JSONAPISerializer('area', { attributes: [ @@ -39,44 +40,6 @@ const areaSerializer = new JSONAPISerializer('area', { keyForAttribute: 'camelCase' }); -function isAdministrativeBoundary(area) { - if (area.attributes && area.attributes.iso && area.attributes.iso.country) { - return !!area.attributes.iso.country; - } - - return area.attributes && area.attributes.admin - ? !!area.attributes.admin.adm0 - : false; - -} - -function addSource(adminInfo) { - adminInfo.source = { - provider: 'gadm', - version: '3.6', - }; -} - -function addSourceToIsoAttribute(area) { - if (area.attributes ? area.attributes.iso : null) { - addSource(area.attributes.iso); - } -} - -function addSourceToAdminAttribute(area) { - if (area.attributes ? area.attributes.admin : null) { - addSource(area.attributes.admin); - } -} - -const addSourceForAdministrativeAreas = (data) => { - const areas = Array.isArray(data) ? data : [data]; - areas.filter(isAdministrativeBoundary).forEach((area) => { - addSourceToIsoAttribute(area); - addSourceToAdminAttribute(area); - }); -}; - class AreaSerializer { static serialize(data, link = null) { @@ -91,7 +54,7 @@ class AreaSerializer { }); } - addSourceForAdministrativeAreas(serializedData.data); + addV2SourceForAdministrativeAreas(serializedData.data); if (link) { serializedData.links = { diff --git a/app/test/unit/serializers/adminSourceUtils.test.js b/app/test/unit/serializers/adminSourceUtils.test.js new file mode 100644 index 0000000..445e90c --- /dev/null +++ b/app/test/unit/serializers/adminSourceUtils.test.js @@ -0,0 +1,41 @@ +const chai = require('chai'); +const { addV1SourceForAdministrativeAreas, addV2SourceForAdministrativeAreas } = require('serializers/adminSourceUtils'); + +const { expect } = chai; + + + +describe('adminSourceUtils', () => { + describe('Adding GADM 2.8 Source Information', () => { + const serializedAreaFragment = { + attributes: { + iso: { + country: 'HND', + region: '8', + }, + }, + }; + + it('should add GADM 2.8 source information', () => { + addV1SourceForAdministrativeAreas(serializedAreaFragment); + expect(serializedAreaFragment.attributes.iso).to.deep.include({ source: { provider: 'gadm', version: '2.8' } }); + }); + }); + + describe('Adding GADM 3.6 Source Information', () => { + const serializedAreaFragment = { + attributes: { + iso: { + country: 'HND', + region: '8', + subregion: '4', + }, + }, + }; + + it('should add GADM 3.6 source information', () => { + addV2SourceForAdministrativeAreas(serializedAreaFragment); + expect(serializedAreaFragment.attributes.iso).to.deep.include({ source: { provider: 'gadm', version: '3.6' } }); + }); + }); +}); From 5f4283a7d3b39ee4567fdf3b9b764b6c279f28fe Mon Sep 17 00:00:00 2001 From: Gary Tempus Jr Date: Wed, 18 Dec 2024 15:37:56 -0500 Subject: [PATCH 07/13] refactor(adminSourceUtils): clean up the check for admin area GTC-3085 --- app/src/serializers/adminSourceUtils.js | 11 +++-------- app/test/unit/serializers/adminSourceUtils.test.js | 2 -- 2 files changed, 3 insertions(+), 10 deletions(-) diff --git a/app/src/serializers/adminSourceUtils.js b/app/src/serializers/adminSourceUtils.js index 618e9aa..63a0509 100644 --- a/app/src/serializers/adminSourceUtils.js +++ b/app/src/serializers/adminSourceUtils.js @@ -4,14 +4,9 @@ const GADM_VERSION_3_6 = '3.6'; let gadmVersion = GADM_VERSION_2_8; function isAdministrativeBoundary(area) { - if (area.attributes && area.attributes.iso && area.attributes.iso.country) { - return !!area.attributes.iso.country; - } - - return area.attributes && area.attributes.admin - ? !!area.attributes.admin.adm0 - : false; - + const iso = area.attributes ? area.attributes.iso : null; + const admin = area.attributes ? area.attributes.admin : null; + return (iso && iso.country) || (admin && admin.adm0); } function addSource(adminInfo) { diff --git a/app/test/unit/serializers/adminSourceUtils.test.js b/app/test/unit/serializers/adminSourceUtils.test.js index 445e90c..d990c84 100644 --- a/app/test/unit/serializers/adminSourceUtils.test.js +++ b/app/test/unit/serializers/adminSourceUtils.test.js @@ -3,8 +3,6 @@ const { addV1SourceForAdministrativeAreas, addV2SourceForAdministrativeAreas } = const { expect } = chai; - - describe('adminSourceUtils', () => { describe('Adding GADM 2.8 Source Information', () => { const serializedAreaFragment = { From e0cb47ef04aefa2370636792d33e967e551abc30 Mon Sep 17 00:00:00 2001 From: Gary Tempus Jr Date: Wed, 18 Dec 2024 16:00:43 -0500 Subject: [PATCH 08/13] :white_check_mark: test: do not add `source` info to custom areas GTC-3085 --- .../unit/serializers/adminSourceUtils.test.js | 38 +++++++++++++++++++ .../unit/serializers/area.serializer.test.js | 13 +++++++ .../serializers/area.serializerV2.test.js | 21 ++++++++++ 3 files changed, 72 insertions(+) diff --git a/app/test/unit/serializers/adminSourceUtils.test.js b/app/test/unit/serializers/adminSourceUtils.test.js index d990c84..bc4caa9 100644 --- a/app/test/unit/serializers/adminSourceUtils.test.js +++ b/app/test/unit/serializers/adminSourceUtils.test.js @@ -18,6 +18,21 @@ describe('adminSourceUtils', () => { addV1SourceForAdministrativeAreas(serializedAreaFragment); expect(serializedAreaFragment.attributes.iso).to.deep.include({ source: { provider: 'gadm', version: '2.8' } }); }); + + describe('An Area That Is NOT An Administrative Boundary', () => { + const serializedCustomAreaFragment = { + attributes: { + name: 'Distrito Central, Francisco Morazán, Honduras', + geostore: 'abcf7041e2fbc5e8e7774178157ababe', + iso: {}, + } + }; + + it('should not add source information to the iso attribute', () => { + addV1SourceForAdministrativeAreas(serializedCustomAreaFragment); + expect(serializedCustomAreaFragment.attributes.iso).to.not.have.property('source'); + }); + }); }); describe('Adding GADM 3.6 Source Information', () => { @@ -35,5 +50,28 @@ describe('adminSourceUtils', () => { addV2SourceForAdministrativeAreas(serializedAreaFragment); expect(serializedAreaFragment.attributes.iso).to.deep.include({ source: { provider: 'gadm', version: '3.6' } }); }); + + describe('An Area That Is NOT An Administrative Boundary', () => { + const serializedCustomAreaFragment = { + attributes: { + name: 'Distrito Central, Francisco Morazán, Honduras', + geostore: 'abcf7041e2fbc5e8e7774178157ababe', + iso: {}, + admin: { + adm0: null, + } + } + }; + + it('should not add source information to the iso attribute', () => { + addV1SourceForAdministrativeAreas(serializedCustomAreaFragment); + expect(serializedCustomAreaFragment.attributes.iso).to.not.have.property('source'); + }); + + it('should not add source information to the admin attribute', () => { + addV1SourceForAdministrativeAreas(serializedCustomAreaFragment); + expect(serializedCustomAreaFragment.attributes.admin).to.not.have.property('source'); + }); + }); }); }); diff --git a/app/test/unit/serializers/area.serializer.test.js b/app/test/unit/serializers/area.serializer.test.js index df23bc6..ce4b086 100644 --- a/app/test/unit/serializers/area.serializer.test.js +++ b/app/test/unit/serializers/area.serializer.test.js @@ -37,4 +37,17 @@ describe('Area Serializer', () => { }); }); }); + + describe('An Area That Is NOT An Administrative Boundary', () => { + const customArea = { + name: 'Distrito Central, Francisco Morazán, Honduras', + geostore: 'abcf7041e2fbc5e8e7774178157ababe', + iso: {}, + }; + + it('should not add source information to the iso attribute', () => { + const result = areaSerializer.serialize(new AreaModel(customArea)); + expect(result.data.attributes.iso).to.not.have.property('source'); + }); + }); }); diff --git a/app/test/unit/serializers/area.serializerV2.test.js b/app/test/unit/serializers/area.serializerV2.test.js index 8a8cc69..9ef608d 100644 --- a/app/test/unit/serializers/area.serializerV2.test.js +++ b/app/test/unit/serializers/area.serializerV2.test.js @@ -54,5 +54,26 @@ describe('Area Serializer V2', () => { expect(result.data.attributes.admin).to.deep.include({ source: { provider: 'gadm', version: '3.6' } }); }); }); + + describe('An Area That Is NOT An Administrative Boundary', () => { + const customArea = { + name: 'Distrito Central, Francisco Morazán, Honduras', + geostore: 'abcf7041e2fbc5e8e7774178157ababe', + iso: {}, + admin: { + adm0: null, + } + }; + + it('should not add source information to the iso attribute', () => { + const result = areaSerializerV2.serialize(new AreaModel(customArea)); + expect(result.data.attributes.iso).to.not.have.property('source'); + }); + + it('should not add source information to the admin attribute', () => { + const result = areaSerializerV2.serialize(new AreaModel(customArea)); + expect(result.data.attributes.admin).to.not.have.property('source'); + }); + }); }); }); From d29674920f12e4c348110b42c1e5ef38e96f3069 Mon Sep 17 00:00:00 2001 From: Gary Tempus Jr Date: Wed, 18 Dec 2024 16:43:54 -0500 Subject: [PATCH 09/13] :broom: chore: update build configs for development --- area.sh | 8 ++++---- docker-compose-develop.yml | 4 +++- 2 files changed, 7 insertions(+), 5 deletions(-) diff --git a/area.sh b/area.sh index b6d46e6..630de94 100755 --- a/area.sh +++ b/area.sh @@ -5,12 +5,12 @@ case "$1" in yarn start ;; develop) - type docker-compose >/dev/null 2>&1 || { echo >&2 "docker-compose is required but it's not installed. Aborting."; exit 1; } - docker-compose -f docker-compose-develop.yml build && docker-compose -f docker-compose-develop.yml up + type docker compose >/dev/null 2>&1 || { echo >&2 "docker compose is required but it's not installed. Aborting."; exit 1; } + docker compose -f docker-compose-develop.yml build && docker compose -f docker-compose-develop.yml up ;; test) - type docker-compose >/dev/null 2>&1 || { echo >&2 "docker-compose is required but it's not installed. Aborting."; exit 1; } - docker-compose -f docker-compose-test.yml build && docker-compose -f docker-compose-test.yml up --abort-on-container-exit + type docker compose >/dev/null 2>&1 || { echo >&2 "docker compose is required but it's not installed. Aborting."; exit 1; } + docker compose -f docker-compose-test.yml build && docker compose -f docker-compose-test.yml up --abort-on-container-exit ;; *) echo "Usage: area.sh {start|develop|test}" >&2 diff --git a/docker-compose-develop.yml b/docker-compose-develop.yml index eaff46f..47d93c1 100644 --- a/docker-compose-develop.yml +++ b/docker-compose-develop.yml @@ -11,12 +11,14 @@ services: PORT: 4100 NODE_ENV: dev NODE_PATH: app/src - MONGO_PORT_27017_TCP_ADDR: mongo + MONGO_PORT_27017_TCP_ADDR: gfw-areas-mongo WAIT_HOSTS: mongo:27017 FASTLY_ENABLED: "false" AWS_REGION: "us-east-1" AWS_ACCESS_KEY_ID: "test" AWS_SECRET_ACCESS_KEY: "test" + REQUIRE_API_KEY: "false" + AWS_CLOUD_WATCH_LOGGING_ENABLED: "false" command: develop depends_on: - mongo From d32008747f9c0a577913454dd11a48b3f1744459 Mon Sep 17 00:00:00 2001 From: Gary Tempus Jr Date: Thu, 19 Dec 2024 14:07:09 -0500 Subject: [PATCH 10/13] feat(Serializers): ensure that representation updates stick I found out that mongo models, when serialized, don't act like POJOs. Adding a property to an existing object wasn't working as expected. Converting to a POJO before doing the admin updates work. This caused several of the end-to-end tests to finally start failing. That was a good thing! --- app/src/serializers/adminSourceUtils.js | 22 +++++++++----- app/src/serializers/area.serializer.js | 2 +- app/src/serializers/area.serializerV2.js | 2 +- app/test/e2e/v1/create-area-fw.spec.js | 12 ++++++-- app/test/e2e/v1/create-area.spec.js | 30 +++++++++++++++---- app/test/e2e/v1/update-area.spec.js | 18 +++++++++-- app/test/e2e/v2/create-area.spec.js | 30 +++++++++++++++---- app/test/e2e/v2/update-area.spec.js | 18 +++++++++-- .../unit/serializers/adminSourceUtils.test.js | 20 ++++++------- 9 files changed, 117 insertions(+), 37 deletions(-) diff --git a/app/src/serializers/adminSourceUtils.js b/app/src/serializers/adminSourceUtils.js index 63a0509..da577f6 100644 --- a/app/src/serializers/adminSourceUtils.js +++ b/app/src/serializers/adminSourceUtils.js @@ -10,21 +10,25 @@ function isAdministrativeBoundary(area) { } function addSource(adminInfo) { - adminInfo.source = { - provider: 'gadm', - version: gadmVersion, + const result = { + ...adminInfo, + source: { + provider: 'gadm', + version: gadmVersion, + } }; + return result; } function addSourceToIsoAttribute(area) { if (area.attributes ? area.attributes.iso : null) { - addSource(area.attributes.iso); + area.attributes.iso = addSource(area.attributes.iso); } } function addSourceToAdminAttribute(area) { if (area.attributes ? area.attributes.admin : null) { - addSource(area.attributes.admin); + area.attributes.admin = addSource(area.attributes.admin); } } @@ -37,13 +41,17 @@ function addSourceForAdministrativeAreas(data) { } const addV1SourceForAdministrativeAreas = (data) => { + const plainObject = JSON.parse(JSON.stringify(data)); gadmVersion = GADM_VERSION_2_8; - addSourceForAdministrativeAreas(data); + addSourceForAdministrativeAreas(plainObject); + return plainObject; }; const addV2SourceForAdministrativeAreas = (data) => { + const plainObject = JSON.parse(JSON.stringify(data)); gadmVersion = GADM_VERSION_3_6; - addSourceForAdministrativeAreas(data); + addSourceForAdministrativeAreas(plainObject); + return plainObject; }; module.exports = { addV1SourceForAdministrativeAreas, addV2SourceForAdministrativeAreas }; diff --git a/app/src/serializers/area.serializer.js b/app/src/serializers/area.serializer.js index f18d8db..7ce821c 100644 --- a/app/src/serializers/area.serializer.js +++ b/app/src/serializers/area.serializer.js @@ -36,7 +36,7 @@ class AreaSerializer { result = areaSerializer.serialize(data); } - addV1SourceForAdministrativeAreas(result.data); + result.data = addV1SourceForAdministrativeAreas(result.data); if (link) { result.links = { diff --git a/app/src/serializers/area.serializerV2.js b/app/src/serializers/area.serializerV2.js index 0946d42..03b4d8e 100644 --- a/app/src/serializers/area.serializerV2.js +++ b/app/src/serializers/area.serializerV2.js @@ -54,7 +54,7 @@ class AreaSerializer { }); } - addV2SourceForAdministrativeAreas(serializedData.data); + serializedData.data = addV2SourceForAdministrativeAreas(serializedData.data); if (link) { serializedData.links = { diff --git a/app/test/e2e/v1/create-area-fw.spec.js b/app/test/e2e/v1/create-area-fw.spec.js index 4e701bc..3d4e02c 100644 --- a/app/test/e2e/v1/create-area-fw.spec.js +++ b/app/test/e2e/v1/create-area-fw.spec.js @@ -81,7 +81,11 @@ describe('V1 - Create area FW', () => { }); response.body.data.attributes.should.have.property('iso').and.deep.equal({ country: 'createdCountryIso', - region: 'createdRegionIso' + region: 'createdRegionIso', + source: { + provider: 'gadm', + version: '2.8', + } }); response.body.data.attributes.should.have.property('createdAt'); response.body.data.attributes.should.have.property('updatedAt'); @@ -166,7 +170,11 @@ describe('V1 - Create area FW', () => { }); response.body.data.attributes.should.have.property('iso').and.deep.equal({ country: 'createdCountryIso', - region: 'createdRegionIso' + region: 'createdRegionIso', + source: { + provider: 'gadm', + version: '2.8', + } }); response.body.data.attributes.should.have.property('createdAt'); response.body.data.attributes.should.have.property('updatedAt'); diff --git a/app/test/e2e/v1/create-area.spec.js b/app/test/e2e/v1/create-area.spec.js index d665479..d3320c6 100644 --- a/app/test/e2e/v1/create-area.spec.js +++ b/app/test/e2e/v1/create-area.spec.js @@ -81,7 +81,11 @@ describe('V1 - Create area', () => { }); response.body.data.attributes.should.have.property('iso').and.deep.equal({ country: 'createdCountryIso', - region: 'createdRegionIso' + region: 'createdRegionIso', + source: { + provider: 'gadm', + version: '2.8', + } }); response.body.data.attributes.should.have.property('createdAt'); response.body.data.attributes.should.have.property('updatedAt'); @@ -137,7 +141,11 @@ describe('V1 - Create area', () => { }); response.body.data.attributes.should.have.property('iso').and.deep.equal({ country: 'createdCountryIso', - region: 'createdRegionIso' + region: 'createdRegionIso', + source: { + provider: 'gadm', + version: '2.8', + } }); response.body.data.attributes.should.have.property('createdAt'); response.body.data.attributes.should.have.property('updatedAt'); @@ -197,7 +205,11 @@ describe('V1 - Create area', () => { }); response.body.data.attributes.should.have.property('iso').and.deep.equal({ country: 'createdCountryIso', - region: 'createdRegionIso' + region: 'createdRegionIso', + source: { + provider: 'gadm', + version: '2.8', + } }); response.body.data.attributes.should.have.property('createdAt'); response.body.data.attributes.should.have.property('updatedAt'); @@ -256,7 +268,11 @@ describe('V1 - Create area', () => { }); response.body.data.attributes.should.have.property('iso').and.deep.equal({ country: 'createdCountryIso', - region: 'createdRegionIso' + region: 'createdRegionIso', + source: { + provider: 'gadm', + version: '2.8', + } }); response.body.data.attributes.should.have.property('createdAt'); response.body.data.attributes.should.have.property('updatedAt'); @@ -313,7 +329,11 @@ describe('V1 - Create area', () => { }); response.body.data.attributes.should.have.property('iso').and.deep.equal({ country: 'createdCountryIso', - region: 'createdRegionIso' + region: 'createdRegionIso', + source: { + provider: 'gadm', + version: '2.8', + } }); response.body.data.attributes.should.have.property('createdAt'); response.body.data.attributes.should.have.property('updatedAt'); diff --git a/app/test/e2e/v1/update-area.spec.js b/app/test/e2e/v1/update-area.spec.js index 53c89a3..edba778 100644 --- a/app/test/e2e/v1/update-area.spec.js +++ b/app/test/e2e/v1/update-area.spec.js @@ -97,7 +97,11 @@ describe('V1 - Update area', () => { }); response.body.data.attributes.should.have.property('iso').and.deep.equal({ country: 'updatedCountryIso', - region: 'updatedRegionIso' + region: 'updatedRegionIso', + source: { + provider: 'gadm', + version: '2.8', + } }); response.body.data.attributes.should.have.property('createdAt'); response.body.data.attributes.should.have.property('updatedAt'); @@ -156,7 +160,11 @@ describe('V1 - Update area', () => { }); response.body.data.attributes.should.have.property('iso').and.deep.equal({ country: 'updatedCountryIso', - region: 'updatedRegionIso' + region: 'updatedRegionIso', + source: { + provider: 'gadm', + version: '2.8', + } }); response.body.data.attributes.should.have.property('createdAt'); response.body.data.attributes.should.have.property('updatedAt'); @@ -219,7 +227,11 @@ describe('V1 - Update area', () => { }); response.body.data.attributes.should.have.property('iso').and.deep.equal({ country: 'updatedCountryIso', - region: 'updatedRegionIso' + region: 'updatedRegionIso', + source: { + provider: 'gadm', + version: '2.8', + } }); response.body.data.attributes.should.have.property('createdAt'); response.body.data.attributes.should.have.property('updatedAt'); diff --git a/app/test/e2e/v2/create-area.spec.js b/app/test/e2e/v2/create-area.spec.js index 74457ce..8ad8cc9 100644 --- a/app/test/e2e/v2/create-area.spec.js +++ b/app/test/e2e/v2/create-area.spec.js @@ -75,7 +75,11 @@ describe('V2 - Create area', () => { response.body.data.attributes.should.have.property('use').and.deep.equal({ id: 'bbb', name: 'created name' }); response.body.data.attributes.should.have.property('iso').and.deep.equal({ country: 'createdCountryIso', - region: 'createdRegionIso' + region: 'createdRegionIso', + source: { + provider: 'gadm', + version: '3.6', + } }); response.body.data.attributes.should.have.property('createdAt'); response.body.data.attributes.should.have.property('updatedAt'); @@ -128,7 +132,11 @@ describe('V2 - Create area', () => { }); response.body.data.attributes.should.have.property('iso').and.deep.equal({ country: 'createdCountryIso', - region: 'createdRegionIso' + region: 'createdRegionIso', + source: { + provider: 'gadm', + version: '3.6', + } }); response.body.data.attributes.should.have.property('createdAt'); response.body.data.attributes.should.have.property('updatedAt'); @@ -180,7 +188,11 @@ describe('V2 - Create area', () => { }); response.body.data.attributes.should.have.property('iso').and.deep.equal({ country: 'createdCountryIso', - region: 'createdRegionIso' + region: 'createdRegionIso', + source: { + provider: 'gadm', + version: '3.6', + } }); response.body.data.attributes.should.have.property('createdAt'); response.body.data.attributes.should.have.property('updatedAt'); @@ -238,7 +250,11 @@ describe('V2 - Create area', () => { }); response.body.data.attributes.should.have.property('iso').and.deep.equal({ country: 'createdCountryIso', - region: 'createdRegionIso' + region: 'createdRegionIso', + source: { + provider: 'gadm', + version: '3.6', + } }); response.body.data.attributes.should.have.property('createdAt'); response.body.data.attributes.should.have.property('updatedAt'); @@ -294,7 +310,11 @@ describe('V2 - Create area', () => { response.body.data.attributes.should.have.property('use').and.deep.equal({ id: 'bbb', name: 'created name' }); response.body.data.attributes.should.have.property('iso').and.deep.equal({ country: 'createdCountryIso', - region: 'createdRegionIso' + region: 'createdRegionIso', + source: { + provider: 'gadm', + version: '3.6', + } }); response.body.data.attributes.should.have.property('createdAt'); response.body.data.attributes.should.have.property('updatedAt'); diff --git a/app/test/e2e/v2/update-area.spec.js b/app/test/e2e/v2/update-area.spec.js index 93db2f7..3c9c643 100644 --- a/app/test/e2e/v2/update-area.spec.js +++ b/app/test/e2e/v2/update-area.spec.js @@ -97,7 +97,11 @@ describe('V2 - Update area', () => { }); response.body.data.attributes.should.have.property('iso').and.deep.equal({ country: 'updatedCountryIso', - region: 'updatedRegionIso' + region: 'updatedRegionIso', + source: { + provider: 'gadm', + version: '3.6', + } }); response.body.data.attributes.should.have.property('createdAt'); response.body.data.attributes.should.have.property('updatedAt'); @@ -156,7 +160,11 @@ describe('V2 - Update area', () => { }); response.body.data.attributes.should.have.property('iso').and.deep.equal({ country: 'updatedCountryIso', - region: 'updatedRegionIso' + region: 'updatedRegionIso', + source: { + provider: 'gadm', + version: '3.6', + } }); response.body.data.attributes.should.have.property('createdAt'); response.body.data.attributes.should.have.property('updatedAt'); @@ -211,7 +219,11 @@ describe('V2 - Update area', () => { }); response.body.data.attributes.should.have.property('iso').and.deep.equal({ country: 'updatedCountryIso', - region: 'updatedRegionIso' + region: 'updatedRegionIso', + source: { + provider: 'gadm', + version: '3.6', + } }); response.body.data.attributes.should.have.property('createdAt'); response.body.data.attributes.should.have.property('updatedAt'); diff --git a/app/test/unit/serializers/adminSourceUtils.test.js b/app/test/unit/serializers/adminSourceUtils.test.js index bc4caa9..5af2690 100644 --- a/app/test/unit/serializers/adminSourceUtils.test.js +++ b/app/test/unit/serializers/adminSourceUtils.test.js @@ -15,8 +15,8 @@ describe('adminSourceUtils', () => { }; it('should add GADM 2.8 source information', () => { - addV1SourceForAdministrativeAreas(serializedAreaFragment); - expect(serializedAreaFragment.attributes.iso).to.deep.include({ source: { provider: 'gadm', version: '2.8' } }); + const result = addV1SourceForAdministrativeAreas(serializedAreaFragment); + expect(result.attributes.iso).to.deep.include({ source: { provider: 'gadm', version: '2.8' } }); }); describe('An Area That Is NOT An Administrative Boundary', () => { @@ -29,8 +29,8 @@ describe('adminSourceUtils', () => { }; it('should not add source information to the iso attribute', () => { - addV1SourceForAdministrativeAreas(serializedCustomAreaFragment); - expect(serializedCustomAreaFragment.attributes.iso).to.not.have.property('source'); + const result = addV1SourceForAdministrativeAreas(serializedCustomAreaFragment); + expect(result.attributes.iso).to.not.have.property('source'); }); }); }); @@ -47,8 +47,8 @@ describe('adminSourceUtils', () => { }; it('should add GADM 3.6 source information', () => { - addV2SourceForAdministrativeAreas(serializedAreaFragment); - expect(serializedAreaFragment.attributes.iso).to.deep.include({ source: { provider: 'gadm', version: '3.6' } }); + const result = addV2SourceForAdministrativeAreas(serializedAreaFragment); + expect(result.attributes.iso).to.deep.include({ source: { provider: 'gadm', version: '3.6' } }); }); describe('An Area That Is NOT An Administrative Boundary', () => { @@ -64,13 +64,13 @@ describe('adminSourceUtils', () => { }; it('should not add source information to the iso attribute', () => { - addV1SourceForAdministrativeAreas(serializedCustomAreaFragment); - expect(serializedCustomAreaFragment.attributes.iso).to.not.have.property('source'); + const result = addV1SourceForAdministrativeAreas(serializedCustomAreaFragment); + expect(result.attributes.iso).to.not.have.property('source'); }); it('should not add source information to the admin attribute', () => { - addV1SourceForAdministrativeAreas(serializedCustomAreaFragment); - expect(serializedCustomAreaFragment.attributes.admin).to.not.have.property('source'); + const result = addV1SourceForAdministrativeAreas(serializedCustomAreaFragment); + expect(result.attributes.admin).to.not.have.property('source'); }); }); }); From 9df420a641e2ae8b5187cdaca4bd0b4e21f0263b Mon Sep 17 00:00:00 2001 From: Gary Tempus Jr Date: Thu, 19 Dec 2024 14:45:20 -0500 Subject: [PATCH 11/13] feat: do not add source to empty 'iso' properties of an Area --- app/src/serializers/adminSourceUtils.js | 16 ++++-- app/test/e2e/v2/create-area.spec.js | 54 +++++++++++++++++++ .../unit/serializers/adminSourceUtils.test.js | 18 +++++++ 3 files changed, 83 insertions(+), 5 deletions(-) diff --git a/app/src/serializers/adminSourceUtils.js b/app/src/serializers/adminSourceUtils.js index da577f6..955f10c 100644 --- a/app/src/serializers/adminSourceUtils.js +++ b/app/src/serializers/adminSourceUtils.js @@ -3,10 +3,16 @@ const GADM_VERSION_3_6 = '3.6'; let gadmVersion = GADM_VERSION_2_8; +function isIsoDefined(area) { + return area.attributes.iso && area.attributes.iso.country; +} + +function isAdminDefined(area) { + return area.attributes.admin && area.attributes.admin.adm0; +} + function isAdministrativeBoundary(area) { - const iso = area.attributes ? area.attributes.iso : null; - const admin = area.attributes ? area.attributes.admin : null; - return (iso && iso.country) || (admin && admin.adm0); + return isIsoDefined(area) || isAdminDefined(area); } function addSource(adminInfo) { @@ -21,13 +27,13 @@ function addSource(adminInfo) { } function addSourceToIsoAttribute(area) { - if (area.attributes ? area.attributes.iso : null) { + if (isIsoDefined(area)) { area.attributes.iso = addSource(area.attributes.iso); } } function addSourceToAdminAttribute(area) { - if (area.attributes ? area.attributes.admin : null) { + if (isAdminDefined(area)) { area.attributes.admin = addSource(area.attributes.admin); } } diff --git a/app/test/e2e/v2/create-area.spec.js b/app/test/e2e/v2/create-area.spec.js index 8ad8cc9..3b88d06 100644 --- a/app/test/e2e/v2/create-area.spec.js +++ b/app/test/e2e/v2/create-area.spec.js @@ -96,6 +96,60 @@ describe('V2 - Create area', () => { }); }); + it('Creating an area while being logged in as a user that owns the area and using admin instead of iso should return a 200 HTTP code and the created area object', async () => { + mockValidateRequestWithApiKeyAndUserToken({ user: USERS.USER }); + + const response = await requester + .post(`/api/v2/area`) + .set('Authorization', 'Bearer abcd') + .set('x-api-key', 'api-key-test') + .send({ + name: 'Portugal area', + application: 'rw', + geostore: '713899292fc118a915741728ef84a2a7', + wdpaid: 3, + use: { id: 'bbb', name: 'created name' }, + admin: { adm0: 'createdCountryIso', adm1: 15, adm2: 8 }, + datasets: '[{"slug":"viirs","name":"VIIRS","startDate":"7","endDate":"1","lastCreate":1513793462776.0,"_id":"5a3aa9eb98b5910011731f66","active":true,"cache":true}]', + templateId: 'createdTemplateId' + }); + + response.status.should.equal(200); + response.body.should.have.property('data').and.be.an('object'); + response.body.data.should.have.property('type').and.equal('area'); + response.body.data.should.have.property('id'); + response.body.data.attributes.should.have.property('name').and.equal('Portugal area'); + response.body.data.attributes.should.have.property('application').and.equal('rw'); + response.body.data.attributes.should.have.property('geostore').and.equal('713899292fc118a915741728ef84a2a7'); + response.body.data.attributes.should.have.property('userId').and.equal(USERS.USER.id); + response.body.data.attributes.should.have.property('wdpaid').and.equal(3); + response.body.data.attributes.should.have.property('env').and.equal('production'); + response.body.data.attributes.should.have.property('use').and.deep.equal({ id: 'bbb', name: 'created name' }); + response.body.data.attributes.should.have.property('admin').and.deep.equal({ + adm0: 'createdCountryIso', + adm1: 15, + adm2: 8, + source: { + provider: 'gadm', + version: '3.6', + } + }); + response.body.data.attributes.should.have.property('iso').and.eql({}); + response.body.data.attributes.should.have.property('createdAt'); + response.body.data.attributes.should.have.property('updatedAt'); + new Date(response.body.data.attributes.updatedAt).should.closeToTime(new Date(response.body.data.attributes.createdAt), 5); + response.body.data.attributes.should.have.property('datasets').and.be.an('array').and.length(1); + response.body.data.attributes.datasets[0].should.deep.equal({ + cache: true, + active: true, + _id: '5a3aa9eb98b5910011731f66', + slug: 'viirs', + name: 'VIIRS', + startDate: '7', + endDate: '1' + }); + }); + describe('Custom envs', () => { it('Creating an area with no env should be successful and have the default env value', async () => { diff --git a/app/test/unit/serializers/adminSourceUtils.test.js b/app/test/unit/serializers/adminSourceUtils.test.js index 5af2690..f615550 100644 --- a/app/test/unit/serializers/adminSourceUtils.test.js +++ b/app/test/unit/serializers/adminSourceUtils.test.js @@ -51,6 +51,24 @@ describe('adminSourceUtils', () => { expect(result.attributes.iso).to.deep.include({ source: { provider: 'gadm', version: '3.6' } }); }); + describe('An Administrative Boundary Area with Both an "iso" and "admin" Property', () => { + it('should NOT add source information to an empty "iso" object', () => { + const serializedAreaFragmentWithEmptyIsoAndAdmin = { + attributes: { + iso: {}, + admin: { + adm0: 'HND', + adm1: 8, + adm2: 4 + }, + }, + }; + + const result = addV2SourceForAdministrativeAreas(serializedAreaFragmentWithEmptyIsoAndAdmin); + expect(result.attributes.iso).to.eql({}); + }); + }); + describe('An Area That Is NOT An Administrative Boundary', () => { const serializedCustomAreaFragment = { attributes: { From 074304b34bb184eb59465df5deab2a4d0bfd4250 Mon Sep 17 00:00:00 2001 From: Gary Tempus Jr Date: Thu, 19 Dec 2024 14:55:42 -0500 Subject: [PATCH 12/13] refactor: create the pojo areas in the serializers --- app/src/serializers/adminSourceUtils.js | 9 +++------ app/src/serializers/area.serializer.js | 2 +- app/src/serializers/area.serializerV2.js | 2 +- 3 files changed, 5 insertions(+), 8 deletions(-) diff --git a/app/src/serializers/adminSourceUtils.js b/app/src/serializers/adminSourceUtils.js index 955f10c..60c0d44 100644 --- a/app/src/serializers/adminSourceUtils.js +++ b/app/src/serializers/adminSourceUtils.js @@ -44,20 +44,17 @@ function addSourceForAdministrativeAreas(data) { addSourceToIsoAttribute(area); addSourceToAdminAttribute(area); }); + return data; } const addV1SourceForAdministrativeAreas = (data) => { - const plainObject = JSON.parse(JSON.stringify(data)); gadmVersion = GADM_VERSION_2_8; - addSourceForAdministrativeAreas(plainObject); - return plainObject; + return addSourceForAdministrativeAreas(data); }; const addV2SourceForAdministrativeAreas = (data) => { - const plainObject = JSON.parse(JSON.stringify(data)); gadmVersion = GADM_VERSION_3_6; - addSourceForAdministrativeAreas(plainObject); - return plainObject; + return addSourceForAdministrativeAreas(data); }; module.exports = { addV1SourceForAdministrativeAreas, addV2SourceForAdministrativeAreas }; diff --git a/app/src/serializers/area.serializer.js b/app/src/serializers/area.serializer.js index 7ce821c..b4410cc 100644 --- a/app/src/serializers/area.serializer.js +++ b/app/src/serializers/area.serializer.js @@ -36,7 +36,7 @@ class AreaSerializer { result = areaSerializer.serialize(data); } - result.data = addV1SourceForAdministrativeAreas(result.data); + result.data = addV1SourceForAdministrativeAreas(JSON.parse(JSON.stringify(result.data))); if (link) { result.links = { diff --git a/app/src/serializers/area.serializerV2.js b/app/src/serializers/area.serializerV2.js index 03b4d8e..798cc89 100644 --- a/app/src/serializers/area.serializerV2.js +++ b/app/src/serializers/area.serializerV2.js @@ -54,7 +54,7 @@ class AreaSerializer { }); } - serializedData.data = addV2SourceForAdministrativeAreas(serializedData.data); + serializedData.data = addV2SourceForAdministrativeAreas(JSON.parse(JSON.stringify(serializedData.data))); if (link) { serializedData.links = { From 27231d9fc3da653846010eef35be7b8926bddb36 Mon Sep 17 00:00:00 2001 From: Gary Tempus Jr Date: Thu, 19 Dec 2024 18:09:07 -0500 Subject: [PATCH 13/13] :broom: chore: update node to ~20.5 and add missing dev dependencies --- Dockerfile | 2 +- entrypoint.sh | 2 +- package.json | 4 +- yarn.lock | 152 +++++++++++++++++++++++++++++++++++++++++++++++--- 4 files changed, 150 insertions(+), 10 deletions(-) diff --git a/Dockerfile b/Dockerfile index 40e253c..3758d91 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,4 +1,4 @@ -FROM node:20.4-alpine3.18 +FROM node:20.5-alpine3.18 MAINTAINER info@vizzuality.com ENV NAME gfw-area diff --git a/entrypoint.sh b/entrypoint.sh index 4cb2938..74894c1 100755 --- a/entrypoint.sh +++ b/entrypoint.sh @@ -4,7 +4,7 @@ set -e case "$1" in develop) echo "Running Development Server" - exec grunt --gruntfile app/Gruntfile.js | bunyan + exec npx grunt --gruntfile app/Gruntfile.js | npx bunyan ;; startDev) echo "Running Start Dev" diff --git a/package.json b/package.json index 153a9db..d3d8791 100644 --- a/package.json +++ b/package.json @@ -12,7 +12,7 @@ "keywords": [], "license": "ISC", "engines": { - "node": "~20.4" + "node": "~20.5" }, "author": { "name": "Vizzuality", @@ -32,6 +32,8 @@ "eslint-plugin-react": "^7.30.0", "grunt": "^1.5.3", "grunt-cli": "^1.3.2", + "grunt-contrib-watch": "^1.1.0", + "grunt-express-server": "^0.5.4", "grunt-mocha-test": "^0.13.3", "grunt-simple-nyc": "^3.0.1", "husky": "^3.0.9", diff --git a/yarn.lock b/yarn.lock index 613c008..a315468 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1755,6 +1755,13 @@ ast-types-flow@^0.0.7: resolved "https://registry.yarnpkg.com/ast-types-flow/-/ast-types-flow-0.0.7.tgz#f70b735c6bca1a5c9c22d982c3e39e7feba3bdad" integrity sha1-9wtzXGvKGlycItmCw+Oef+ujva0= +async@^2.6.0: + version "2.6.4" + resolved "https://registry.yarnpkg.com/async/-/async-2.6.4.tgz#706b7ff6084664cd7eae713f6f965433b5504221" + integrity sha512-mzo5dfJYwAn29PeiJ0zvwTo04zj8HDJj0Mn8TD7sno7q12prdbnasKJHhkm2c1LgrhlJ0teaea8860oxi51mGA== + dependencies: + lodash "^4.17.14" + async@^3.1.0: version "3.1.0" resolved "https://registry.yarnpkg.com/async/-/async-3.1.0.tgz#42b3b12ae1b74927b5217d8c0016baaf62463772" @@ -1913,6 +1920,16 @@ bluebird@^3.5.0: resolved "https://registry.yarnpkg.com/bluebird/-/bluebird-3.5.5.tgz#a8d0afd73251effbbd5fe384a77d73003c17a71f" integrity sha512-5am6HnnfN+urzt4yfg7IgTbotDjIT/u8AJpEt0sIU9FtXfVeezXAPKswrG+xKUCOYAINpSdgZVDU6QFh+cuH3w== +body@^5.1.0: + version "5.1.0" + resolved "https://registry.yarnpkg.com/body/-/body-5.1.0.tgz#e4ba0ce410a46936323367609ecb4e6553125069" + integrity sha512-chUsBxGRtuElD6fmw1gHLpvnKdVLK302peeFa9ZqAEk8TyzZ3fygLyUEDDPTJvL9+Bor0dIwn6ePOsRM2y0zQQ== + dependencies: + continuable-cache "^0.3.1" + error "^7.0.0" + raw-body "~1.1.0" + safe-json-parse "~1.0.1" + bowser@^2.11.0: version "2.11.0" resolved "https://registry.yarnpkg.com/bowser/-/bowser-2.11.0.tgz#5ca3c35757a7aa5771500c70a73a9f91ef420a8f" @@ -2009,6 +2026,11 @@ bunyan@^1.8.15: mv "~2" safe-json-stringify "~1" +bytes@1: + version "1.0.0" + resolved "https://registry.yarnpkg.com/bytes/-/bytes-1.0.0.tgz#3569ede8ba34315fab99c3e92cb04c7220de1fa8" + integrity sha512-/x68VkHLeTl3/Ll8IvxdwzhrT+IyKc52e/oyHhA2RwqPqswSnjVbSddfPRwAsJtbilMAPSRWwAlpxdYsSWOTKQ== + bytes@3.1.0, bytes@^3.1.0: version "3.1.0" resolved "https://registry.yarnpkg.com/bytes/-/bytes-3.1.0.tgz#f6cf7933a360e0588fa9fde85651cdc7f805d1f6" @@ -2390,6 +2412,11 @@ content-type@^1.0.4: resolved "https://registry.yarnpkg.com/content-type/-/content-type-1.0.4.tgz#e138cc75e040c727b1966fe5e5f8c9aee256fe3b" integrity sha512-hIP3EEPs8tB9AT1L+NUqtwOAps4mk2Zob89MWXMHjHWg9milF/j4osnnQLXBCBFBk/tvIG/tUc9mOUJiPBhPXA== +continuable-cache@^0.3.1: + version "0.3.1" + resolved "https://registry.yarnpkg.com/continuable-cache/-/continuable-cache-0.3.1.tgz#bd727a7faed77e71ff3985ac93351a912733ad0f" + integrity sha512-TF30kpKhTH8AGCG3dut0rdd/19B7Z+qCnrMoBLpyQu/2drZdNrrpcjPEoJeSVsQM+8KmWG5O56oPDjSSUsuTyA== + convert-source-map@^1.6.0: version "1.7.0" resolved "https://registry.yarnpkg.com/convert-source-map/-/convert-source-map-1.7.0.tgz#17a2cb882d7f77d3490585e2ce6c524424a3a442" @@ -2802,6 +2829,13 @@ error-ex@^1.3.1: dependencies: is-arrayish "^0.2.1" +error@^7.0.0: + version "7.2.1" + resolved "https://registry.yarnpkg.com/error/-/error-7.2.1.tgz#eab21a4689b5f684fc83da84a0e390de82d94894" + integrity sha512-fo9HBvWnx3NGUKMvMwB/CBCMMrfEJgbDTVDEkPygA3Bdd3lM1OyCd+rbQ8BwnpF6GdVeOLDNmyL4N5Bg80ZvdA== + dependencies: + string-template "~0.2.1" + es-abstract@^1.19.0, es-abstract@^1.19.1, es-abstract@^1.19.2, es-abstract@^1.19.5, es-abstract@^1.20.0: version "1.20.1" resolved "https://registry.yarnpkg.com/es-abstract/-/es-abstract-1.20.1.tgz#027292cd6ef44bd12b1913b828116f54787d1814" @@ -3233,6 +3267,13 @@ fastq@^1.6.0: dependencies: reusify "^1.0.0" +faye-websocket@~0.10.0: + version "0.10.0" + resolved "https://registry.yarnpkg.com/faye-websocket/-/faye-websocket-0.10.0.tgz#4e492f8d04dfb6f89003507f6edbf2d501e7c6f4" + integrity sha512-Xhj93RXbMSq8urNCUq4p9l0P6hnySJ/7YNRhYNug0bLOuii7pKO7xQFb5mx9xZXWCar88pLPb805PvUkwrLZpQ== + dependencies: + websocket-driver ">=0.5.1" + figures@^1.7.0: version "1.7.0" resolved "https://registry.yarnpkg.com/figures/-/figures-1.7.0.tgz#cbe1e3affcf1cd44b80cadfed28dc793a9701d2e" @@ -3539,6 +3580,13 @@ functions-have-names@^1.2.2: resolved "https://registry.yarnpkg.com/functions-have-names/-/functions-have-names-1.2.3.tgz#0404fe4ee2ba2f607f0e0ec3c80bae994133b834" integrity sha512-xckBUXyTIqT97tq2x2AMb+g163b5JFysYk0x4qxNFwbfQkmNZoiRHb6sPzI9/QV33WeuvVYBUIiD4NzNIyqaRQ== +gaze@^1.1.0: + version "1.1.3" + resolved "https://registry.yarnpkg.com/gaze/-/gaze-1.1.3.tgz#c441733e13b927ac8c0ff0b4c3b033f28812924a" + integrity sha512-BRdNm8hbWzFzWHERTrejLqwHDfS4GibPoq5wjTPIoJHoBtKGPg3xAFfxmM+9ztbXelxcf2hwQcaz1PtmFeue8g== + dependencies: + globule "^1.0.0" + gensync@^1.0.0-beta.2: version "1.0.0-beta.2" resolved "https://registry.yarnpkg.com/gensync/-/gensync-1.0.0-beta.2.tgz#32a6ee76c3d7f52d46b2b1ae5d93fea8580a25e0" @@ -3654,7 +3702,7 @@ glob@^6.0.1: once "^1.3.0" path-is-absolute "^1.0.0" -glob@^7.1.3, glob@~7.1.6: +glob@^7.1.3, glob@~7.1.1, glob@~7.1.6: version "7.1.7" resolved "https://registry.yarnpkg.com/glob/-/glob-7.1.7.tgz#3b193e9233f01d42d0b3f78294bbeeb418f94a90" integrity sha512-OvD9ENzPLbegENnYP5UUfJIirTg4+XwMWGaQfQTY0JenxNvvIKP3U3/tAQSPIu/lHxXYSZmpXlUHeqAIdKzBLQ== @@ -3735,6 +3783,15 @@ globby@^10.0.1: merge2 "^1.2.3" slash "^3.0.0" +globule@^1.0.0: + version "1.3.4" + resolved "https://registry.yarnpkg.com/globule/-/globule-1.3.4.tgz#7c11c43056055a75a6e68294453c17f2796170fb" + integrity sha512-OPTIfhMBh7JbBYDpa5b+Q5ptmMWKwcNcFSR/0c6t8V4f3ZAVBEsKNY37QdVqmLRYSMhOUGYrY0QhSoEpzGr/Eg== + dependencies: + glob "~7.1.1" + lodash "^4.17.21" + minimatch "~3.0.2" + graceful-fs@^4.1.11, graceful-fs@^4.1.2: version "4.1.15" resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.1.15.tgz#ffb703e1066e8a0eeaa4c8b80ba9253eeefbfb00" @@ -3772,6 +3829,21 @@ grunt-cli@~1.4.3: nopt "~4.0.1" v8flags "~3.2.0" +grunt-contrib-watch@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/grunt-contrib-watch/-/grunt-contrib-watch-1.1.0.tgz#c143ca5b824b288a024b856639a5345aedb78ed4" + integrity sha512-yGweN+0DW5yM+oo58fRu/XIRrPcn3r4tQx+nL7eMRwjpvk+rQY6R8o94BPK0i2UhTg9FN21hS+m8vR8v9vXfeg== + dependencies: + async "^2.6.0" + gaze "^1.1.0" + lodash "^4.17.10" + tiny-lr "^1.1.1" + +grunt-express-server@^0.5.4: + version "0.5.4" + resolved "https://registry.yarnpkg.com/grunt-express-server/-/grunt-express-server-0.5.4.tgz#8ce79c335c6cbb9ef50ee1dfaa61942028f43aeb" + integrity sha512-Q9sTDOwxC46uviL1/LSXFflTMv+/WnwANtzxD7hwnEXaej79LS1AUZlWc/O5P+CWjKG69/1xJFn+CVP94fOQ6Q== + grunt-known-options@~1.1.0: version "1.1.1" resolved "https://registry.yarnpkg.com/grunt-known-options/-/grunt-known-options-1.1.1.tgz#6cc088107bd0219dc5d3e57d91923f469059804d" @@ -4055,6 +4127,11 @@ http-errors@~1.6.2: setprototypeof "1.1.0" statuses ">= 1.4.0 < 2" +http-parser-js@>=0.5.1: + version "0.5.8" + resolved "https://registry.yarnpkg.com/http-parser-js/-/http-parser-js-0.5.8.tgz#af23090d9ac4e24573de6f6aecc9d84a48bf20e3" + integrity sha512-SGeBX54F94Wgu5RH3X5jsDtf4eHyRogWX1XGT3b4HuW3tQPM4AaBzoUji/4AAJNXCEOWZ5O0DgZmJw1947gD5Q== + http-signature@~1.2.0: version "1.2.0" resolved "https://registry.yarnpkg.com/http-signature/-/http-signature-1.2.0.tgz#9aecd925114772f3d95b65a60abb8f7c18fbace1" @@ -5094,6 +5171,11 @@ listr@^0.14.3: p-map "^2.0.0" rxjs "^6.3.3" +livereload-js@^2.3.0: + version "2.4.0" + resolved "https://registry.yarnpkg.com/livereload-js/-/livereload-js-2.4.0.tgz#447c31cf1ea9ab52fc20db615c5ddf678f78009c" + integrity sha512-XPQH8Z2GDP/Hwz2PCDrh2mth4yFejwA1OZ/81Ti3LgKyhDcEjsSsqFWZojHG0va/duGd+WyosY7eXLDoOyqcPw== + load-grunt-tasks@^5.1.0: version "5.1.0" resolved "https://registry.yarnpkg.com/load-grunt-tasks/-/load-grunt-tasks-5.1.0.tgz#14894c27a7e34ebbef9937c39cc35c573cd04c1c" @@ -5194,16 +5276,16 @@ lodash@^3.9.3: resolved "https://registry.yarnpkg.com/lodash/-/lodash-3.10.1.tgz#5bf45e8e49ba4189e17d482789dfd15bd140b7b6" integrity sha1-W/Rejkm6QYnhfUgnid/RW9FAt7Y= +lodash@^4.17.10, lodash@^4.17.14, lodash@^4.17.19, lodash@^4.17.21, lodash@~4.17.19, lodash@~4.17.21: + version "4.17.21" + resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.21.tgz#679591c564c3bffaae8454cf0b3df370c3d6911c" + integrity sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg== + lodash@^4.17.13, lodash@^4.17.15, lodash@^4.17.2, lodash@^4.17.4: version "4.17.15" resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.15.tgz#b447f6670a0455bbfeedd11392eff330ea097548" integrity sha512-8xOcRHvCjnocdS5cpwXQXVzmmh5e5+saE2QGoeQmbKmRS6J3VQppPOIt0MnmE+4xlZoumy0GPG0D0MVIQbNA1A== -lodash@^4.17.19, lodash@~4.17.19, lodash@~4.17.21: - version "4.17.21" - resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.21.tgz#679591c564c3bffaae8454cf0b3df370c3d6911c" - integrity sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg== - log-symbols@4.1.0: version "4.1.0" resolved "https://registry.yarnpkg.com/log-symbols/-/log-symbols-4.1.0.tgz#3fbdbb95b4683ac9fc785111e792e558d4abd503" @@ -5398,6 +5480,13 @@ minimatch@^3.1.1, minimatch@^3.1.2: dependencies: brace-expansion "^1.1.7" +minimatch@~3.0.2: + version "3.0.8" + resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.0.8.tgz#5e6a59bd11e2ab0de1cfb843eb2d82e546c321c1" + integrity sha512-6FsRAQsxQ61mw+qP1ZzbL9Bc78x2p5OqNgNpnoAFLTrX8n5Kxph0CsnhmKKNXTWjXqU5L0pGPR7hYk+XWZr60Q== + dependencies: + brace-expansion "^1.1.7" + minimist@0.0.8: version "0.0.8" resolved "https://registry.yarnpkg.com/minimist/-/minimist-0.0.8.tgz#857fcabfc3397d2625b8228262e86aa7a011b05d" @@ -6377,6 +6466,14 @@ raw-body@^2.2.0: iconv-lite "0.4.24" unpipe "1.0.0" +raw-body@~1.1.0: + version "1.1.7" + resolved "https://registry.yarnpkg.com/raw-body/-/raw-body-1.1.7.tgz#1d027c2bfa116acc6623bca8f00016572a87d425" + integrity sha512-WmJJU2e9Y6M5UzTOkHaM7xJGAPQD8PNzx3bAd2+uhZAim6wDk6dAZxPVYLF67XhbR4hmKGh33Lpmh4XWrCH5Mg== + dependencies: + bytes "1" + string_decoder "0.10" + react-is@^16.13.1: version "16.13.1" resolved "https://registry.yarnpkg.com/react-is/-/react-is-16.13.1.tgz#789729a4dc36de2999dc156dd6c1d9c18cea56a4" @@ -6754,11 +6851,16 @@ safe-buffer@5.1.2, safe-buffer@^5.0.1, safe-buffer@^5.1.2, safe-buffer@~5.1.0, s resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.1.2.tgz#991ec69d296e0313747d59bdfd2b745c35f8828d" integrity sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g== -safe-buffer@5.2.1, safe-buffer@^5.1.0, safe-buffer@^5.1.1, safe-buffer@~5.2.0: +safe-buffer@5.2.1, safe-buffer@>=5.1.0, safe-buffer@^5.1.0, safe-buffer@^5.1.1, safe-buffer@~5.2.0: version "5.2.1" resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.2.1.tgz#1eaf9fa9bdb1fdd4ec75f58f9cdb4e6b7827eec6" integrity sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ== +safe-json-parse@~1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/safe-json-parse/-/safe-json-parse-1.0.1.tgz#3e76723e38dfdda13c9b1d29a1e07ffee4b30b57" + integrity sha512-o0JmTu17WGUaUOHa1l0FPGXKBfijbxK6qoHzlkihsDXxzBHvJcA7zgviKR92Xs841rX9pK16unfphLq0/KqX7A== + safe-json-stringify@~1: version "1.2.0" resolved "https://registry.yarnpkg.com/safe-json-stringify/-/safe-json-stringify-1.2.0.tgz#356e44bc98f1f93ce45df14bcd7c01cda86e0afd" @@ -7120,6 +7222,11 @@ string-argv@^0.3.0: resolved "https://registry.yarnpkg.com/string-argv/-/string-argv-0.3.1.tgz#95e2fbec0427ae19184935f816d74aaa4c5c19da" integrity sha512-a1uQGz7IyVy9YwhqjZIZu1c8JO8dNIe20xBmSS6qu9kv++k3JGzCVmprbNN5Kn+BgzD5E7YYwg1CcjuJMRNsvg== +string-template@~0.2.1: + version "0.2.1" + resolved "https://registry.yarnpkg.com/string-template/-/string-template-0.2.1.tgz#42932e598a352d01fc22ec3367d9d84eec6c9add" + integrity sha512-Yptehjogou2xm4UJbxJ4CxgZx12HBfeystp0y3x7s4Dj32ltVVG1Gg8YhKjHZkHicuKpZX/ffilA8505VbUbpw== + string-width@^1.0.1: version "1.0.2" resolved "https://registry.yarnpkg.com/string-width/-/string-width-1.0.2.tgz#118bdf5b8cdc51a2a7e70d211e07e2b0b9b107d3" @@ -7196,6 +7303,11 @@ string.prototype.trimstart@^1.0.5: define-properties "^1.1.4" es-abstract "^1.19.5" +string_decoder@0.10: + version "0.10.31" + resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-0.10.31.tgz#62e203bc41766c6c28c9fc84301dab1c5310fa94" + integrity sha512-ev2QzSzWPYmy9GuqfIVildA4OdcGLeFZQrq5ys6RtiuF+RQQiZWr8TZNyAcuVXyQRYfEO+MsoB/1BuQVhOJuoQ== + string_decoder@^1.1.1: version "1.3.0" resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-1.3.0.tgz#42f114594a46cf1a8e30b0a84f56c78c3edac21e" @@ -7390,6 +7502,18 @@ text-table@^0.2.0: resolved "https://registry.yarnpkg.com/through/-/through-2.3.8.tgz#0dd4c9ffaabc357960b1b724115d7e0e86a2e1f5" integrity sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU= +tiny-lr@^1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/tiny-lr/-/tiny-lr-1.1.1.tgz#9fa547412f238fedb068ee295af8b682c98b2aab" + integrity sha512-44yhA3tsaRoMOjQQ+5v5mVdqef+kH6Qze9jTpqtVufgYjYt08zyZAwNwwVBj3i1rJMnR52IxOW0LK0vBzgAkuA== + dependencies: + body "^5.1.0" + debug "^3.1.0" + faye-websocket "~0.10.0" + livereload-js "^2.3.0" + object-assign "^4.1.0" + qs "^6.4.0" + tmp@0.0.31: version "0.0.31" resolved "https://registry.yarnpkg.com/tmp/-/tmp-0.0.31.tgz#8f38ab9438e17315e5dbd8b3657e8bfb277ae4a7" @@ -7698,6 +7822,20 @@ verror@1.10.0: core-util-is "1.0.2" extsprintf "^1.2.0" +websocket-driver@>=0.5.1: + version "0.7.4" + resolved "https://registry.yarnpkg.com/websocket-driver/-/websocket-driver-0.7.4.tgz#89ad5295bbf64b480abcba31e4953aca706f5760" + integrity sha512-b17KeDIQVjvb0ssuSDF2cYXSg2iztliJ4B9WdsuB6J952qCPKmnVq4DyW5motImXHDC1cBT/1UezrJVsKw5zjg== + dependencies: + http-parser-js ">=0.5.1" + safe-buffer ">=5.1.0" + websocket-extensions ">=0.1.1" + +websocket-extensions@>=0.1.1: + version "0.1.4" + resolved "https://registry.yarnpkg.com/websocket-extensions/-/websocket-extensions-0.1.4.tgz#7f8473bc839dfd87608adb95d7eb075211578a42" + integrity sha512-OqedPIGOfsDlo31UNwYbCFMSaO9m9G/0faIHj5/dZFDMFqPTcx6UwqyOy3COEaEOg/9VsGIpdqn62W5KhoKSpg== + which-boxed-primitive@^1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/which-boxed-primitive/-/which-boxed-primitive-1.0.2.tgz#13757bc89b209b049fe5d86430e21cf40a89a8e6"