From b3a4fa9b3856ae5220a7d7394647e951a0ea82f0 Mon Sep 17 00:00:00 2001 From: Harald Mayer Date: Fri, 9 Aug 2024 09:08:52 +0200 Subject: [PATCH] initial commit of sf project, metadata, GitHub Actions... --- .forceignore | 15 + .github/workflows/code-analyze.yml | 79 + .github/workflows/create-package-beta.yml | 28 + .github/workflows/create-package-version.yml | 40 + .github/workflows/install-package-version.yml | 31 + .github/workflows/main.yml | 22 + .github/workflows/pr.yml | 18 + .gitignore | 61 + .husky/pre-commit | 4 + .lintstagedrc.js | 3 + .prettierignore | 9 + .prettierrc | 23 + LICENSE | 21 + README.md | 10 + data/brokers-data.json | 100 + data/brokers-data.json.tmp | 0 data/contacts-data.json | 54 + data/contacts-data.json.tmp | 0 data/properties-data.json | 268 + data/properties-data.json.tmp | 0 data/sample-data-plan.json | 23 + data/sample-data-plan.json.tmp | 0 data/sfdmu/Account.csv | 0 data/sfdmu/Contact.csv | 6 + data/sfdmu/Hutte__Broker__c.csv | 9 + data/sfdmu/Hutte__Property__c.csv | 13 + data/sfdmu/Individual.csv | 0 data/sfdmu/MissingParentRecordsReport.csv | 0 data/sfdmu/export.json | 20 + .../applications/Dreamhouse.app-meta.xml | 63 + .../pageTemplate_2_7_3/pageTemplate_2_7_3.cmp | 41 + .../pageTemplate_2_7_3.cmp-meta.xml | 5 + .../pageTemplate_2_7_3.design | 9 + .../pageTemplate_2_7_3/pageTemplate_2_7_3.svg | 7 + .../main/default/classes/FileUtilities.cls | 29 + .../classes/FileUtilities.cls-meta.xml | 5 + .../default/classes/FileUtilitiesTest.cls | 76 + .../classes/FileUtilitiesTest.cls-meta.xml | 5 + .../main/default/classes/GeocodingService.cls | 72 + .../classes/GeocodingService.cls-meta.xml | 5 + .../default/classes/GeocodingServiceTest.cls | 100 + .../classes/GeocodingServiceTest.cls-meta.xml | 5 + .../main/default/classes/PagedResult.cls | 13 + .../default/classes/PagedResult.cls-meta.xml | 5 + .../default/classes/PropertyController.cls | 112 + .../classes/PropertyController.cls-meta.xml | 5 + .../default/classes/SampleDataController.cls | 63 + .../classes/SampleDataController.cls-meta.xml | 5 + .../classes/TestPropertyController.cls | 121 + .../TestPropertyController.cls-meta.xml | 5 + .../classes/TestSampleDataController.cls | 17 + .../TestSampleDataController.cls-meta.xml | 5 + .../HUTTE_LOGOTYPE_MAIN_SYMBOL_ALPHA.asset | Bin 0 -> 47566 bytes ..._LOGOTYPE_MAIN_SYMBOL_ALPHA.asset-meta.xml | 17 + .../contentassets/dreamhouselogosquare.asset | Bin 0 -> 23382 bytes .../dreamhouselogosquare.asset-meta.xml | 17 + .../openStreetMap.cspTrustedSite-meta.xml | 15 + ...st_2_amazonaws_com.cspTrustedSite-meta.xml | 15 + .../Broker_Record_Page.flexipage-meta.xml | 378 ++ .../Property_Explorer.flexipage-meta.xml | 58 + .../Property_Finder.flexipage-meta.xml | 50 + .../Property_Record_Page.flexipage-meta.xml | 552 ++ .../flexipages/Settings.flexipage-meta.xml | 26 + .../flows/Create_property.flow-meta.xml | 619 +++ force-app/main/default/lwc/.eslintrc.json | 14 + .../__tests__/barcodeScanner.test.js | 183 + .../lwc/barcodeScanner/barcodeScanner.html | 35 + .../lwc/barcodeScanner/barcodeScanner.js | 80 + .../barcodeScanner/barcodeScanner.js-meta.xml | 17 + .../brokerCard/__tests__/brokerCard.test.js | 181 + .../__tests__/data/getPropertyRecord.json | 18 + .../default/lwc/brokerCard/brokerCard.html | 20 + .../main/default/lwc/brokerCard/brokerCard.js | 36 + .../lwc/brokerCard/brokerCard.js-meta.xml | 20 + .../__tests__/data/getRecord.json | 20 + .../__tests__/daysOnMarket.test.js | 255 + .../default/lwc/daysOnMarket/daysOnMarket.css | 57 + .../lwc/daysOnMarket/daysOnMarket.html | 43 + .../default/lwc/daysOnMarket/daysOnMarket.js | 94 + .../lwc/daysOnMarket/daysOnMarket.js-meta.xml | 22 + .../errorPanel/__tests__/errorPanel.test.js | 122 + .../main/default/lwc/errorPanel/errorPanel.js | 28 + .../lwc/errorPanel/errorPanel.js-meta.xml | 5 + .../errorPanel/templates/inlineMessage.html | 19 + .../templates/noDataIllustration.html | 257 + .../lwc/ldsUtils/__tests__/ldsUtils.test.js | 61 + .../main/default/lwc/ldsUtils/ldsUtils.js | 37 + .../default/lwc/ldsUtils/ldsUtils.js-meta.xml | 8 + .../listContactsFromDevice.html | 40 + .../listContactsFromDevice.js | 31 + .../listContactsFromDevice.js-meta.xml | 9 + .../__tests__/navigateToRecord.test.js | 45 + .../navigateToRecord/navigateToRecord.html | 1 + .../lwc/navigateToRecord/navigateToRecord.js | 18 + .../navigateToRecord.js-meta.xml | 20 + .../lwc/paginator/__tests__/paginator.test.js | 144 + .../main/default/lwc/paginator/paginator.html | 29 + .../main/default/lwc/paginator/paginator.js | 36 + .../lwc/paginator/paginator.js-meta.xml | 5 + .../__tests__/data/getPictures.json | 4 + .../__tests__/data/getPropertyRecord.json | 18 + .../__tests__/propertyCarousel.test.js | 174 + .../propertyCarousel/propertyCarousel.html | 47 + .../lwc/propertyCarousel/propertyCarousel.js | 105 + .../propertyCarousel.js-meta.xml | 20 + .../__tests__/propertyFilter.test.js | 275 + .../lwc/propertyFilter/propertyFilter.html | 42 + .../lwc/propertyFilter/propertyFilter.js | 61 + .../propertyFilter/propertyFilter.js-meta.xml | 17 + .../__tests__/propertyListMap.test.js | 220 + .../lwc/propertyListMap/propertyListMap.css | 34 + .../lwc/propertyListMap/propertyListMap.html | 3 + .../lwc/propertyListMap/propertyListMap.js | 170 + .../propertyListMap.js-meta.xml | 9 + .../__tests__/data/getRecord.json | 20 + .../__tests__/propertyLocation.test.js | 135 + .../propertyLocation/propertyLocation.html | 38 + .../lwc/propertyLocation/propertyLocation.js | 85 + .../propertyLocation.js-meta.xml | 20 + .../__tests__/data/propertyRecord.json | 26 + .../propertyMap/__tests__/propertyMap.test.js | 96 + .../default/lwc/propertyMap/propertyMap.html | 21 + .../default/lwc/propertyMap/propertyMap.js | 78 + .../lwc/propertyMap/propertyMap.js-meta.xml | 27 + .../__tests__/data/getRecord.json | 20 + .../__tests__/propertySummary.test.js | 99 + .../lwc/propertySummary/propertySummary.html | 39 + .../lwc/propertySummary/propertySummary.js | 73 + .../propertySummary.js-meta.xml | 27 + .../__tests__/propertyTile.small.test.js | 66 + .../__tests__/propertyTile.test.js | 97 + .../default/lwc/propertyTile/propertyTile.css | 26 + .../lwc/propertyTile/propertyTile.html | 19 + .../default/lwc/propertyTile/propertyTile.js | 32 + .../lwc/propertyTile/propertyTile.js-meta.xml | 5 + .../__tests__/data/getPagedPropertyList.json | 106 + .../__tests__/propertyTileList.test.js | 134 + .../lwc/propertyTileList/propertyTileList.css | 7 + .../propertyTileList/propertyTileList.html | 32 + .../lwc/propertyTileList/propertyTileList.js | 70 + .../propertyTileList.js-meta.xml | 17 + .../__tests__/sampleDataImporter.test.js | 115 + .../sampleDataImporter.html | 19 + .../sampleDataImporter/sampleDataImporter.js | 25 + .../sampleDataImporter.js-meta.xml | 9 + .../FiltersChange.messageChannel-meta.xml | 21 + .../PropertySelected.messageChannel-meta.xml | 9 + .../Broker__c/Broker__c.object-meta.xml | 165 + .../Broker_Compact.compactLayout-meta.xml | 10 + .../fields/Broker_Id__c.field-meta.xml | 12 + .../Broker__c/fields/Email__c.field-meta.xml | 11 + .../fields/Mobile_Phone__c.field-meta.xml | 8 + .../Broker__c/fields/Phone__c.field-meta.xml | 8 + .../fields/Picture_IMG__c.field-meta.xml | 12 + .../fields/Picture__c.field-meta.xml | 8 + .../Broker__c/fields/Title__c.field-meta.xml | 11 + .../Broker__c/listViews/All.listView-meta.xml | 7 + .../Property__c/Property__c.object-meta.xml | 167 + ...erty_Compact_Layout.compactLayout-meta.xml | 10 + .../fields/Address__c.field-meta.xml | 13 + .../fields/Assessed_Value__c.field-meta.xml | 12 + .../fields/Baths__c.field-meta.xml | 14 + .../Property__c/fields/Beds__c.field-meta.xml | 14 + .../fields/Broker__c.field-meta.xml | 14 + .../Property__c/fields/City__c.field-meta.xml | 13 + .../fields/Date_Agreement__c.field-meta.xml | 10 + .../fields/Date_Closed__c.field-meta.xml | 10 + .../fields/Date_Contracted__c.field-meta.xml | 10 + .../fields/Date_Listed__c.field-meta.xml | 11 + .../fields/Date_Pre_Market__c.field-meta.xml | 10 + .../fields/Days_On_Market__c.field-meta.xml | 15 + .../fields/Description__c.field-meta.xml | 11 + .../fields/Location__c.field-meta.xml | 12 + .../fields/Picture_IMG__c.field-meta.xml | 13 + .../fields/Picture__c.field-meta.xml | 10 + .../fields/Price_Sold__c.field-meta.xml | 12 + .../fields/Price__c.field-meta.xml | 12 + .../fields/Record_Link__c.field-meta.xml | 13 + .../fields/State__c.field-meta.xml | 13 + .../fields/Status__c.field-meta.xml | 41 + .../Property__c/fields/Tags__c.field-meta.xml | 13 + .../fields/Thumbnail_IMG__c.field-meta.xml | 13 + .../fields/Thumbnail__c.field-meta.xml | 10 + .../Property__c/fields/Zip__c.field-meta.xml | 13 + .../listViews/All.listView-meta.xml | 11 + .../dreamhouse.permissionset-meta.xml | 219 + ...ominatim_openstreetmap.remoteSite-meta.xml | 6 + .../leafletjs.resource-meta.xml | 6 + .../leafletjs/images/layers-2x.png | Bin 0 -> 1259 bytes .../leafletjs/images/layers.png | Bin 0 -> 696 bytes .../leafletjs/images/marker-icon-2x.png | Bin 0 -> 2464 bytes .../leafletjs/images/marker-icon.png | Bin 0 -> 1466 bytes .../leafletjs/images/marker-shadow.png | Bin 0 -> 618 bytes .../staticresources/leafletjs/leaflet.css | 661 +++ .../staticresources/leafletjs/leaflet.js | 6 + .../staticresources/sample_data_brokers.json | 74 + .../sample_data_brokers.resource-meta.xml | 6 + .../staticresources/sample_data_contacts.json | 32 + .../sample_data_contacts.resource-meta.xml | 6 + .../sample_data_properties.json | 242 + .../sample_data_properties.resource-meta.xml | 6 + .../main/default/tabs/Broker__c.tab-meta.xml | 5 + .../tabs/Property_Explorer.tab-meta.xml | 7 + .../default/tabs/Property_Finder.tab-meta.xml | 7 + .../default/tabs/Property__c.tab-meta.xml | 5 + .../main/default/tabs/Settings.tab-meta.xml | 7 + force-app/test/jest-mocks/apex.js | 1 + force-app/test/jest-mocks/global/navigator.js | 15 + .../test/jest-mocks/lightning/mediaUtils.js | 1 + .../jest-mocks/lightning/messageService.js | 25 + .../lightning/mobileCapabilities.js | 91 + .../test/jest-mocks/lightning/navigation.js | 41 + .../lightning/platformShowToastEvent.js | 18 + force-app/test/jest-mocks/schema.js | 5 + hutte.yml | 21 + package.json | 41 + release.config.mjs | 29 + scripts/addnamespaceToData.sh | 54 + scripts/addnamespaceToLWC.sh | 18 + scripts/apex/hello.apex | 10 + scripts/soql/account.soql | 6 + sfdx-project.json | 19 + yarn.lock | 4715 +++++++++++++++++ 223 files changed, 15376 insertions(+) create mode 100755 .forceignore create mode 100644 .github/workflows/code-analyze.yml create mode 100644 .github/workflows/create-package-beta.yml create mode 100644 .github/workflows/create-package-version.yml create mode 100644 .github/workflows/install-package-version.yml create mode 100644 .github/workflows/main.yml create mode 100644 .github/workflows/pr.yml create mode 100644 .gitignore create mode 100755 .husky/pre-commit create mode 100644 .lintstagedrc.js create mode 100755 .prettierignore create mode 100755 .prettierrc create mode 100644 LICENSE create mode 100644 README.md create mode 100644 data/brokers-data.json create mode 100644 data/brokers-data.json.tmp create mode 100644 data/contacts-data.json create mode 100644 data/contacts-data.json.tmp create mode 100644 data/properties-data.json create mode 100644 data/properties-data.json.tmp create mode 100644 data/sample-data-plan.json create mode 100644 data/sample-data-plan.json.tmp create mode 100644 data/sfdmu/Account.csv create mode 100644 data/sfdmu/Contact.csv create mode 100644 data/sfdmu/Hutte__Broker__c.csv create mode 100644 data/sfdmu/Hutte__Property__c.csv create mode 100644 data/sfdmu/Individual.csv create mode 100644 data/sfdmu/MissingParentRecordsReport.csv create mode 100644 data/sfdmu/export.json create mode 100644 force-app/main/default/applications/Dreamhouse.app-meta.xml create mode 100644 force-app/main/default/aura/pageTemplate_2_7_3/pageTemplate_2_7_3.cmp create mode 100644 force-app/main/default/aura/pageTemplate_2_7_3/pageTemplate_2_7_3.cmp-meta.xml create mode 100644 force-app/main/default/aura/pageTemplate_2_7_3/pageTemplate_2_7_3.design create mode 100644 force-app/main/default/aura/pageTemplate_2_7_3/pageTemplate_2_7_3.svg create mode 100644 force-app/main/default/classes/FileUtilities.cls create mode 100644 force-app/main/default/classes/FileUtilities.cls-meta.xml create mode 100644 force-app/main/default/classes/FileUtilitiesTest.cls create mode 100644 force-app/main/default/classes/FileUtilitiesTest.cls-meta.xml create mode 100644 force-app/main/default/classes/GeocodingService.cls create mode 100644 force-app/main/default/classes/GeocodingService.cls-meta.xml create mode 100644 force-app/main/default/classes/GeocodingServiceTest.cls create mode 100644 force-app/main/default/classes/GeocodingServiceTest.cls-meta.xml create mode 100644 force-app/main/default/classes/PagedResult.cls create mode 100644 force-app/main/default/classes/PagedResult.cls-meta.xml create mode 100644 force-app/main/default/classes/PropertyController.cls create mode 100644 force-app/main/default/classes/PropertyController.cls-meta.xml create mode 100644 force-app/main/default/classes/SampleDataController.cls create mode 100644 force-app/main/default/classes/SampleDataController.cls-meta.xml create mode 100644 force-app/main/default/classes/TestPropertyController.cls create mode 100644 force-app/main/default/classes/TestPropertyController.cls-meta.xml create mode 100644 force-app/main/default/classes/TestSampleDataController.cls create mode 100644 force-app/main/default/classes/TestSampleDataController.cls-meta.xml create mode 100644 force-app/main/default/contentassets/HUTTE_LOGOTYPE_MAIN_SYMBOL_ALPHA.asset create mode 100644 force-app/main/default/contentassets/HUTTE_LOGOTYPE_MAIN_SYMBOL_ALPHA.asset-meta.xml create mode 100644 force-app/main/default/contentassets/dreamhouselogosquare.asset create mode 100644 force-app/main/default/contentassets/dreamhouselogosquare.asset-meta.xml create mode 100644 force-app/main/default/cspTrustedSites/openStreetMap.cspTrustedSite-meta.xml create mode 100644 force-app/main/default/cspTrustedSites/s3_us_west_2_amazonaws_com.cspTrustedSite-meta.xml create mode 100644 force-app/main/default/flexipages/Broker_Record_Page.flexipage-meta.xml create mode 100644 force-app/main/default/flexipages/Property_Explorer.flexipage-meta.xml create mode 100644 force-app/main/default/flexipages/Property_Finder.flexipage-meta.xml create mode 100644 force-app/main/default/flexipages/Property_Record_Page.flexipage-meta.xml create mode 100644 force-app/main/default/flexipages/Settings.flexipage-meta.xml create mode 100644 force-app/main/default/flows/Create_property.flow-meta.xml create mode 100644 force-app/main/default/lwc/.eslintrc.json create mode 100644 force-app/main/default/lwc/barcodeScanner/__tests__/barcodeScanner.test.js create mode 100644 force-app/main/default/lwc/barcodeScanner/barcodeScanner.html create mode 100644 force-app/main/default/lwc/barcodeScanner/barcodeScanner.js create mode 100644 force-app/main/default/lwc/barcodeScanner/barcodeScanner.js-meta.xml create mode 100644 force-app/main/default/lwc/brokerCard/__tests__/brokerCard.test.js create mode 100644 force-app/main/default/lwc/brokerCard/__tests__/data/getPropertyRecord.json create mode 100644 force-app/main/default/lwc/brokerCard/brokerCard.html create mode 100644 force-app/main/default/lwc/brokerCard/brokerCard.js create mode 100644 force-app/main/default/lwc/brokerCard/brokerCard.js-meta.xml create mode 100644 force-app/main/default/lwc/daysOnMarket/__tests__/data/getRecord.json create mode 100644 force-app/main/default/lwc/daysOnMarket/__tests__/daysOnMarket.test.js create mode 100644 force-app/main/default/lwc/daysOnMarket/daysOnMarket.css create mode 100644 force-app/main/default/lwc/daysOnMarket/daysOnMarket.html create mode 100644 force-app/main/default/lwc/daysOnMarket/daysOnMarket.js create mode 100644 force-app/main/default/lwc/daysOnMarket/daysOnMarket.js-meta.xml create mode 100644 force-app/main/default/lwc/errorPanel/__tests__/errorPanel.test.js create mode 100644 force-app/main/default/lwc/errorPanel/errorPanel.js create mode 100644 force-app/main/default/lwc/errorPanel/errorPanel.js-meta.xml create mode 100755 force-app/main/default/lwc/errorPanel/templates/inlineMessage.html create mode 100644 force-app/main/default/lwc/errorPanel/templates/noDataIllustration.html create mode 100644 force-app/main/default/lwc/ldsUtils/__tests__/ldsUtils.test.js create mode 100644 force-app/main/default/lwc/ldsUtils/ldsUtils.js create mode 100644 force-app/main/default/lwc/ldsUtils/ldsUtils.js-meta.xml create mode 100644 force-app/main/default/lwc/listContactsFromDevice/listContactsFromDevice.html create mode 100644 force-app/main/default/lwc/listContactsFromDevice/listContactsFromDevice.js create mode 100644 force-app/main/default/lwc/listContactsFromDevice/listContactsFromDevice.js-meta.xml create mode 100644 force-app/main/default/lwc/navigateToRecord/__tests__/navigateToRecord.test.js create mode 100644 force-app/main/default/lwc/navigateToRecord/navigateToRecord.html create mode 100644 force-app/main/default/lwc/navigateToRecord/navigateToRecord.js create mode 100644 force-app/main/default/lwc/navigateToRecord/navigateToRecord.js-meta.xml create mode 100644 force-app/main/default/lwc/paginator/__tests__/paginator.test.js create mode 100644 force-app/main/default/lwc/paginator/paginator.html create mode 100644 force-app/main/default/lwc/paginator/paginator.js create mode 100644 force-app/main/default/lwc/paginator/paginator.js-meta.xml create mode 100644 force-app/main/default/lwc/propertyCarousel/__tests__/data/getPictures.json create mode 100644 force-app/main/default/lwc/propertyCarousel/__tests__/data/getPropertyRecord.json create mode 100644 force-app/main/default/lwc/propertyCarousel/__tests__/propertyCarousel.test.js create mode 100644 force-app/main/default/lwc/propertyCarousel/propertyCarousel.html create mode 100644 force-app/main/default/lwc/propertyCarousel/propertyCarousel.js create mode 100644 force-app/main/default/lwc/propertyCarousel/propertyCarousel.js-meta.xml create mode 100644 force-app/main/default/lwc/propertyFilter/__tests__/propertyFilter.test.js create mode 100644 force-app/main/default/lwc/propertyFilter/propertyFilter.html create mode 100644 force-app/main/default/lwc/propertyFilter/propertyFilter.js create mode 100644 force-app/main/default/lwc/propertyFilter/propertyFilter.js-meta.xml create mode 100644 force-app/main/default/lwc/propertyListMap/__tests__/propertyListMap.test.js create mode 100644 force-app/main/default/lwc/propertyListMap/propertyListMap.css create mode 100644 force-app/main/default/lwc/propertyListMap/propertyListMap.html create mode 100644 force-app/main/default/lwc/propertyListMap/propertyListMap.js create mode 100644 force-app/main/default/lwc/propertyListMap/propertyListMap.js-meta.xml create mode 100644 force-app/main/default/lwc/propertyLocation/__tests__/data/getRecord.json create mode 100644 force-app/main/default/lwc/propertyLocation/__tests__/propertyLocation.test.js create mode 100644 force-app/main/default/lwc/propertyLocation/propertyLocation.html create mode 100644 force-app/main/default/lwc/propertyLocation/propertyLocation.js create mode 100644 force-app/main/default/lwc/propertyLocation/propertyLocation.js-meta.xml create mode 100644 force-app/main/default/lwc/propertyMap/__tests__/data/propertyRecord.json create mode 100644 force-app/main/default/lwc/propertyMap/__tests__/propertyMap.test.js create mode 100644 force-app/main/default/lwc/propertyMap/propertyMap.html create mode 100644 force-app/main/default/lwc/propertyMap/propertyMap.js create mode 100644 force-app/main/default/lwc/propertyMap/propertyMap.js-meta.xml create mode 100644 force-app/main/default/lwc/propertySummary/__tests__/data/getRecord.json create mode 100644 force-app/main/default/lwc/propertySummary/__tests__/propertySummary.test.js create mode 100644 force-app/main/default/lwc/propertySummary/propertySummary.html create mode 100644 force-app/main/default/lwc/propertySummary/propertySummary.js create mode 100644 force-app/main/default/lwc/propertySummary/propertySummary.js-meta.xml create mode 100644 force-app/main/default/lwc/propertyTile/__tests__/propertyTile.small.test.js create mode 100644 force-app/main/default/lwc/propertyTile/__tests__/propertyTile.test.js create mode 100644 force-app/main/default/lwc/propertyTile/propertyTile.css create mode 100644 force-app/main/default/lwc/propertyTile/propertyTile.html create mode 100644 force-app/main/default/lwc/propertyTile/propertyTile.js create mode 100644 force-app/main/default/lwc/propertyTile/propertyTile.js-meta.xml create mode 100644 force-app/main/default/lwc/propertyTileList/__tests__/data/getPagedPropertyList.json create mode 100644 force-app/main/default/lwc/propertyTileList/__tests__/propertyTileList.test.js create mode 100644 force-app/main/default/lwc/propertyTileList/propertyTileList.css create mode 100644 force-app/main/default/lwc/propertyTileList/propertyTileList.html create mode 100644 force-app/main/default/lwc/propertyTileList/propertyTileList.js create mode 100644 force-app/main/default/lwc/propertyTileList/propertyTileList.js-meta.xml create mode 100644 force-app/main/default/lwc/sampleDataImporter/__tests__/sampleDataImporter.test.js create mode 100644 force-app/main/default/lwc/sampleDataImporter/sampleDataImporter.html create mode 100644 force-app/main/default/lwc/sampleDataImporter/sampleDataImporter.js create mode 100644 force-app/main/default/lwc/sampleDataImporter/sampleDataImporter.js-meta.xml create mode 100644 force-app/main/default/messageChannels/FiltersChange.messageChannel-meta.xml create mode 100644 force-app/main/default/messageChannels/PropertySelected.messageChannel-meta.xml create mode 100644 force-app/main/default/objects/Broker__c/Broker__c.object-meta.xml create mode 100644 force-app/main/default/objects/Broker__c/compactLayouts/Broker_Compact.compactLayout-meta.xml create mode 100644 force-app/main/default/objects/Broker__c/fields/Broker_Id__c.field-meta.xml create mode 100644 force-app/main/default/objects/Broker__c/fields/Email__c.field-meta.xml create mode 100644 force-app/main/default/objects/Broker__c/fields/Mobile_Phone__c.field-meta.xml create mode 100644 force-app/main/default/objects/Broker__c/fields/Phone__c.field-meta.xml create mode 100644 force-app/main/default/objects/Broker__c/fields/Picture_IMG__c.field-meta.xml create mode 100644 force-app/main/default/objects/Broker__c/fields/Picture__c.field-meta.xml create mode 100644 force-app/main/default/objects/Broker__c/fields/Title__c.field-meta.xml create mode 100644 force-app/main/default/objects/Broker__c/listViews/All.listView-meta.xml create mode 100644 force-app/main/default/objects/Property__c/Property__c.object-meta.xml create mode 100644 force-app/main/default/objects/Property__c/compactLayouts/Property_Compact_Layout.compactLayout-meta.xml create mode 100644 force-app/main/default/objects/Property__c/fields/Address__c.field-meta.xml create mode 100644 force-app/main/default/objects/Property__c/fields/Assessed_Value__c.field-meta.xml create mode 100644 force-app/main/default/objects/Property__c/fields/Baths__c.field-meta.xml create mode 100644 force-app/main/default/objects/Property__c/fields/Beds__c.field-meta.xml create mode 100644 force-app/main/default/objects/Property__c/fields/Broker__c.field-meta.xml create mode 100644 force-app/main/default/objects/Property__c/fields/City__c.field-meta.xml create mode 100644 force-app/main/default/objects/Property__c/fields/Date_Agreement__c.field-meta.xml create mode 100644 force-app/main/default/objects/Property__c/fields/Date_Closed__c.field-meta.xml create mode 100644 force-app/main/default/objects/Property__c/fields/Date_Contracted__c.field-meta.xml create mode 100644 force-app/main/default/objects/Property__c/fields/Date_Listed__c.field-meta.xml create mode 100644 force-app/main/default/objects/Property__c/fields/Date_Pre_Market__c.field-meta.xml create mode 100644 force-app/main/default/objects/Property__c/fields/Days_On_Market__c.field-meta.xml create mode 100644 force-app/main/default/objects/Property__c/fields/Description__c.field-meta.xml create mode 100644 force-app/main/default/objects/Property__c/fields/Location__c.field-meta.xml create mode 100644 force-app/main/default/objects/Property__c/fields/Picture_IMG__c.field-meta.xml create mode 100644 force-app/main/default/objects/Property__c/fields/Picture__c.field-meta.xml create mode 100644 force-app/main/default/objects/Property__c/fields/Price_Sold__c.field-meta.xml create mode 100644 force-app/main/default/objects/Property__c/fields/Price__c.field-meta.xml create mode 100644 force-app/main/default/objects/Property__c/fields/Record_Link__c.field-meta.xml create mode 100644 force-app/main/default/objects/Property__c/fields/State__c.field-meta.xml create mode 100644 force-app/main/default/objects/Property__c/fields/Status__c.field-meta.xml create mode 100644 force-app/main/default/objects/Property__c/fields/Tags__c.field-meta.xml create mode 100644 force-app/main/default/objects/Property__c/fields/Thumbnail_IMG__c.field-meta.xml create mode 100644 force-app/main/default/objects/Property__c/fields/Thumbnail__c.field-meta.xml create mode 100644 force-app/main/default/objects/Property__c/fields/Zip__c.field-meta.xml create mode 100644 force-app/main/default/objects/Property__c/listViews/All.listView-meta.xml create mode 100644 force-app/main/default/permissionsets/dreamhouse.permissionset-meta.xml create mode 100644 force-app/main/default/remoteSiteSettings/nominatim_openstreetmap.remoteSite-meta.xml create mode 100644 force-app/main/default/staticresources/leafletjs.resource-meta.xml create mode 100644 force-app/main/default/staticresources/leafletjs/images/layers-2x.png create mode 100644 force-app/main/default/staticresources/leafletjs/images/layers.png create mode 100644 force-app/main/default/staticresources/leafletjs/images/marker-icon-2x.png create mode 100644 force-app/main/default/staticresources/leafletjs/images/marker-icon.png create mode 100644 force-app/main/default/staticresources/leafletjs/images/marker-shadow.png create mode 100644 force-app/main/default/staticresources/leafletjs/leaflet.css create mode 100644 force-app/main/default/staticresources/leafletjs/leaflet.js create mode 100644 force-app/main/default/staticresources/sample_data_brokers.json create mode 100644 force-app/main/default/staticresources/sample_data_brokers.resource-meta.xml create mode 100644 force-app/main/default/staticresources/sample_data_contacts.json create mode 100644 force-app/main/default/staticresources/sample_data_contacts.resource-meta.xml create mode 100644 force-app/main/default/staticresources/sample_data_properties.json create mode 100644 force-app/main/default/staticresources/sample_data_properties.resource-meta.xml create mode 100644 force-app/main/default/tabs/Broker__c.tab-meta.xml create mode 100644 force-app/main/default/tabs/Property_Explorer.tab-meta.xml create mode 100644 force-app/main/default/tabs/Property_Finder.tab-meta.xml create mode 100644 force-app/main/default/tabs/Property__c.tab-meta.xml create mode 100644 force-app/main/default/tabs/Settings.tab-meta.xml create mode 100644 force-app/test/jest-mocks/apex.js create mode 100644 force-app/test/jest-mocks/global/navigator.js create mode 100644 force-app/test/jest-mocks/lightning/mediaUtils.js create mode 100644 force-app/test/jest-mocks/lightning/messageService.js create mode 100644 force-app/test/jest-mocks/lightning/mobileCapabilities.js create mode 100644 force-app/test/jest-mocks/lightning/navigation.js create mode 100644 force-app/test/jest-mocks/lightning/platformShowToastEvent.js create mode 100644 force-app/test/jest-mocks/schema.js create mode 100644 hutte.yml create mode 100644 package.json create mode 100644 release.config.mjs create mode 100755 scripts/addnamespaceToData.sh create mode 100755 scripts/addnamespaceToLWC.sh create mode 100644 scripts/apex/hello.apex create mode 100644 scripts/soql/account.soql create mode 100644 sfdx-project.json create mode 100644 yarn.lock diff --git a/.forceignore b/.forceignore new file mode 100755 index 0000000..3d36001 --- /dev/null +++ b/.forceignore @@ -0,0 +1,15 @@ +# List files or directories below to ignore them when running force:source:push, force:source:pull, and force:source:status +# More information: https://developer.salesforce.com/docs/atlas.en-us.sfdx_dev.meta/sfdx_dev/sfdx_dev_exclude_source.htm +# + +package.xml + +# LWC configuration files +**/jsconfig.json +**/.eslintrc.json + +# LWC Jest +**/__tests__/** +**/tsconfig.json + +**/*.ts diff --git a/.github/workflows/code-analyze.yml b/.github/workflows/code-analyze.yml new file mode 100644 index 0000000..c51db74 --- /dev/null +++ b/.github/workflows/code-analyze.yml @@ -0,0 +1,79 @@ +name: Salesforce Code Quality + +on: + workflow_dispatch: + workflow_call: + +jobs: + PMD: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - uses: actions/setup-node@v3 + - name: Setup Salesforce CLI + run: | + npm i --global @salesforce/cli + sf plugins:install @salesforce/sfdx-scanner + - name: SF Code Analyzer - PMD - Report findings as comments + uses: mitchspano/sfdx-scan-pull-request@v0.1.16 + with: + report-mode: comments + engine: pmd + pmdconfig: config/pmd/ruleset.xml + severity-threshold: 4 + strictly-enforced-rules: '[{ "engine": "pmd", "category": "Performance", "rule": "AvoidDebugStatements" }]' + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + + RetireJS: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - uses: actions/setup-node@v3 + - name: Setup Salesforce CLI + run: | + npm i --global @salesforce/cli + sf plugins:install @salesforce/sfdx-scanner + - name: SF Code Analyzer - RetireJS - Report findings as comments + uses: mitchspano/sfdx-scan-pull-request@v0.1.16 + with: + report-mode: comments + engine: retire-js + severity-threshold: 4 + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + + ESLint: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - uses: actions/setup-node@v3 + - name: Setup Salesforce CLI + run: | + npm i --global @salesforce/cli + sf plugins:install @salesforce/sfdx-scanner + - name: Install deps + run: | + yarn install + - name: SF Code Analyzer - ESLint - Report findings as comments + uses: mitchspano/sfdx-scan-pull-request@v0.1.16 + with: + report-mode: comments + engine: eslint + eslintconfig: .eslintrc.json + severity-threshold: 4 + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + + GraphEngine: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - uses: actions/setup-node@v3 + - name: Setup Salesforce CLI + run: | + npm i --global @salesforce/cli + sf plugins:install @salesforce/sfdx-scanner + - name: SF Code Analyzer - Data Flow Analysis + run: | + sf scanner:run:dfa --target force-app --projectdir force-app --format table --severity-threshold 3 diff --git a/.github/workflows/create-package-beta.yml b/.github/workflows/create-package-beta.yml new file mode 100644 index 0000000..50bb3f5 --- /dev/null +++ b/.github/workflows/create-package-beta.yml @@ -0,0 +1,28 @@ +name: Create Package Beta + +on: + workflow_dispatch: + workflow_call: + +jobs: + default: + name: Create Package Beta + runs-on: ubuntu-latest + steps: + - uses: actions/setup-node@v4 + with: + node-version: 20 + - name: Setup Salesforce CLI + run: | + npm install --global @salesforce/cli + - uses: actions/checkout@v4 + with: + fetch-depth: 0 + - name: Authenticate Dev Hub org + run: | + echo "${{ secrets.SFDX_AUTH_URL_DEVHUB }}" | sf org login sfdx-url --set-default-dev-hub --sfdx-url-stdin + - name: Create package beta + run: | + # increment minor version, fallback to 0.1.0 + nextReleaseVersion="$(sf package version list --packages "ISVShowcase" --released --order-by MajorVersion,MinorVersion,PatchVersion --json | yq '.result[-1] | ( .MajorVersion + "." + ( .MinorVersion + 1 ) + "." + .PatchVersion )' || echo "0.1.0")" + sf package version create --package ISVShowcase --version-number "${nextReleaseVersion}.NEXT" --installation-key-bypass --code-coverage --wait 30 diff --git a/.github/workflows/create-package-version.yml b/.github/workflows/create-package-version.yml new file mode 100644 index 0000000..2876ab5 --- /dev/null +++ b/.github/workflows/create-package-version.yml @@ -0,0 +1,40 @@ +name: Create Package Version + +on: + workflow_dispatch: + workflow_call: + outputs: + packageVersionId: + description: 'If a package version has been published, this is the package version id (04t)' + value: ${{ jobs.default.outputs.packageVersionId }} + version: + description: 'If a package version has been published, this is the package version number (major.minor.patch.build)' + value: ${{ jobs.default.outputs.version }} + +jobs: + default: + name: Create Package Version + runs-on: ubuntu-latest + outputs: + packageVersionId: ${{ steps.create-package-version.outputs.packageVersionId }} + version: ${{ steps.create-package-version.outputs.version }} + steps: + - uses: actions/setup-node@v4 + with: + node-version: 20 + - name: Setup Salesforce CLI + run: | + npm install --global @salesforce/cli + - uses: actions/checkout@v4 + with: + fetch-depth: 0 + - name: Authenticate Dev Hub org + run: | + echo "${{ secrets.SFDX_AUTH_URL_DEVHUB }}" | sf org login sfdx-url --set-default-dev-hub --sfdx-url-stdin + - id: create-package-version + name: Create package version + run: | + npx -y -p @semantic-release/exec -p semantic-release semantic-release + # packageVersionId and version will be set as output for the GH action (see release.config.mjs) + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} diff --git a/.github/workflows/install-package-version.yml b/.github/workflows/install-package-version.yml new file mode 100644 index 0000000..6b776b3 --- /dev/null +++ b/.github/workflows/install-package-version.yml @@ -0,0 +1,31 @@ +name: Install Package Version + +on: + workflow_dispatch: + inputs: + packageVersion: + description: 'ID (starts with 04t) or alias of the package version to install' + required: true + workflow_call: + inputs: + packageVersion: + type: string + description: 'ID (starts with 04t) or alias of the package version to install' + required: true + +jobs: + default: + runs-on: ubuntu-latest + steps: + - uses: actions/setup-node@v4 + with: + node-version: 20 + - name: Setup Salesforce CLI + run: | + npm install --global @salesforce/cli + - name: Authenticate target org + run: | + echo "${{ secrets.AUTH_URL_TRIAL_DEMO }}" | sf org login sfdx-url --set-default --sfdx-url-stdin + - name: Install package version in target org + run: | + sf package install --no-prompt --publish-wait 20 --wait 60 --package "${{ inputs.packageVersion }}" diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml new file mode 100644 index 0000000..4562816 --- /dev/null +++ b/.github/workflows/main.yml @@ -0,0 +1,22 @@ +name: Main + +on: + push: + branches: + - main + paths: + - force-app/** + +jobs: + create-package-version: + name: Run Create Package Version Workflow + uses: ./.github/workflows/create-package-version.yml + secrets: inherit + install-package-version: + name: Run Install Package Version Workflow + uses: ./.github/workflows/install-package-version.yml + needs: create-package-version + if: ${{ needs.create-package-version.outputs.packageVersionId != '' }} + with: + packageVersion: ${{ needs.create-package-version.outputs.packageVersionId }} + secrets: inherit diff --git a/.github/workflows/pr.yml b/.github/workflows/pr.yml new file mode 100644 index 0000000..f37dc5d --- /dev/null +++ b/.github/workflows/pr.yml @@ -0,0 +1,18 @@ +name: Pull Request + +on: + pull_request: + branches: + - main + paths: + - force-app/** + +jobs: + code-analyze: + name: Run Salesforce Code Analyzer + uses: ./.github/workflows/code-analyze.yml + secrets: inherit + create-package-beta: + name: Run Create Package Beta Workflow + uses: ./.github/workflows/create-package-beta.yml + secrets: inherit diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..a03ba75 --- /dev/null +++ b/.gitignore @@ -0,0 +1,61 @@ +# This file is used for Git repositories to specify intentionally untracked files that Git should ignore. +# If you are not using git, you can delete this file. For more information see: https://git-scm.com/docs/gitignore +# For useful gitignore templates see: https://github.com/github/gitignore + +# Salesforce cache +.sf/ +.sfdx/ +.localdevserver/ +deploy-options.json + +# LWC VSCode autocomplete +**/lwc/jsconfig.json + +# LWC Jest coverage reports +coverage/ + +# Logs +logs +*.log +npm-debug.log* +yarn-debug.log* +yarn-error.log* + +# Dependency directories +node_modules/ + +# Eslint cache +.eslintcache + +# MacOS system files +.DS_Store + +# Windows system files +Thumbs.db +ehthumbs.db +[Dd]esktop.ini +$RECYCLE.BIN/ + +# Local environment variables +.env + +# Python Salesforce Functions +**/__pycache__/ +**/.venv/ +**/venv/ + +# SFDMU +/data/source/ +/data/target/ +/data/logs/ + +# SGD +deltas* + +# package xml +package.xml + +# SFDMU +/data/sfdmu/source/ +/data/sfdmu/target/ +/data/sfdmu/logs/ \ No newline at end of file diff --git a/.husky/pre-commit b/.husky/pre-commit new file mode 100755 index 0000000..868f111 --- /dev/null +++ b/.husky/pre-commit @@ -0,0 +1,4 @@ +#!/usr/bin/env sh +. "$(dirname "$0")/_/husky.sh" + +npm run precommit \ No newline at end of file diff --git a/.lintstagedrc.js b/.lintstagedrc.js new file mode 100644 index 0000000..4e73c6e --- /dev/null +++ b/.lintstagedrc.js @@ -0,0 +1,3 @@ +module.exports = { + '**/*.{auradoc,cls,cmp,component,css,design,html,js,json,md,page,trigger,xml,yaml,yml}': 'prettier --write' +}; diff --git a/.prettierignore b/.prettierignore new file mode 100755 index 0000000..45f1078 --- /dev/null +++ b/.prettierignore @@ -0,0 +1,9 @@ +# List files or directories below to ignore them when running prettier +# More information: https://prettier.io/docs/en/ignore.html +# + +**/staticresources/** +.localdevserver +.sfdx +*.md +coverage/ diff --git a/.prettierrc b/.prettierrc new file mode 100755 index 0000000..d470226 --- /dev/null +++ b/.prettierrc @@ -0,0 +1,23 @@ +{ + "singleQuote": true, + "printWidth": 120, + "requireConfig": false, + "useTabs": false, + "trailingComma": "none", + "bracketSpacing": true, + "jsxBracketSameLine": false, + "semi": true, + "tabWidth": 4, + "editor.formatOnSave": true, + "overrides": [ + { + "files": "**/lwc/**/*.html", + "options": { "parser": "lwc" } + }, + { + "files": "*.{cmp,page,component}", + "options": { "parser": "html" } + } + ], + "plugins": ["prettier-plugin-apex", "@prettier/plugin-xml"] +} diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..752acc7 --- /dev/null +++ b/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2024 Hutte + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. \ No newline at end of file diff --git a/README.md b/README.md new file mode 100644 index 0000000..2310668 --- /dev/null +++ b/README.md @@ -0,0 +1,10 @@ +# This repository contains + +## Skeleton SF Project +Based on [Hutte Project Template](https://github.com/hutte-recipes/hutte-project-template) + +## Sample source and GitHub Actions to build/promote/install package versions + +Check [Creating a 2GP for AppExchange](https://hutte-io.notion.site/Creating-a-2GP-for-AppExchange-c3a92c93261d4cb1a658fff696622bdb) for learning more about generating your first 2GP + +When using this template, please make sure to replace the namespace Hutte in all files inside the force-app directory (replace Hutte__ with YourNamespace__) as well as in sfdx-project.json (property "namespace"). \ No newline at end of file diff --git a/data/brokers-data.json b/data/brokers-data.json new file mode 100644 index 0000000..9fedd87 --- /dev/null +++ b/data/brokers-data.json @@ -0,0 +1,100 @@ +{ + "records": [ + { + "attributes": { + "type": "Hutte__Broker__c", + "referenceId": "CarolineBrookerRef" + }, + "Name": "Caroline Kingsley", + "Hutte__Title__c": "Senior Broker", + "Hutte__Phone__c": "617-244-3672", + "Hutte__Mobile_Phone__c": "617-244-3672", + "Hutte__Email__c": "caroline@dreamhouse.demo", + "Hutte__Picture__c": "https://s3-us-west-2.amazonaws.com/dev-or-devrl-s3-bucket/sample-apps/people/caroline_kingsley.jpg" + }, + { + "attributes": { + "type": "Hutte__Broker__c", + "referenceId": "MichaelJonesRef" + }, + "Name": "Michael Jones", + "Hutte__Title__c": "Senior Broker", + "Hutte__Phone__c": "617-244-3672", + "Hutte__Mobile_Phone__c": "617-244-3672", + "Hutte__Email__c": "michael@dreamhouse.demo", + "Hutte__Picture__c": "https://s3-us-west-2.amazonaws.com/dev-or-devrl-s3-bucket/sample-apps/people/michael_jones.jpg" + }, + { + "attributes": { + "type": "Hutte__Broker__c", + "referenceId": "JonathanBradleyRef" + }, + "Name": "Jonathan Bradley", + "Hutte__Title__c": "Senior Broker", + "Hutte__Phone__c": "617-244-3672", + "Hutte__Mobile_Phone__c": "617-244-3672", + "Hutte__Email__c": "jonathan@dreamhouse.demo", + "Hutte__Picture__c": "https://s3-us-west-2.amazonaws.com/dev-or-devrl-s3-bucket/sample-apps/people/jonathan_bradley.jpg" + }, + { + "attributes": { + "type": "Hutte__Broker__c", + "referenceId": "JenniferWuRef" + }, + "Name": "Jennifer Wu", + "Hutte__Title__c": "Senior Broker", + "Hutte__Phone__c": "617-244-3672", + "Hutte__Mobile_Phone__c": "617-244-3672", + "Hutte__Email__c": "jen@dreamhouse.demo", + "Hutte__Picture__c": "https://s3-us-west-2.amazonaws.com/dev-or-devrl-s3-bucket/sample-apps/people/jennifer_wu.jpg" + }, + { + "attributes": { + "type": "Hutte__Broker__c", + "referenceId": "OliviaGreenRef" + }, + "Name": "Olivia Green", + "Hutte__Title__c": "Senior Broker", + "Hutte__Phone__c": "617-244-3672", + "Hutte__Mobile_Phone__c": "617-244-3672", + "Hutte__Email__c": "olivia@dreamhouse.demo", + "Hutte__Picture__c": "https://s3-us-west-2.amazonaws.com/dev-or-devrl-s3-bucket/sample-apps/people/olivia_green.jpg" + }, + { + "attributes": { + "type": "Hutte__Broker__c", + "referenceId": "MiriamAupontRef" + }, + "Name": "Miriam Aupont", + "Hutte__Title__c": "Senior Broker", + "Hutte__Phone__c": "617-244-3672", + "Hutte__Mobile_Phone__c": "617-244-3672", + "Hutte__Email__c": "miriam@dreamhouse.demo", + "Hutte__Picture__c": "https://s3-us-west-2.amazonaws.com/dev-or-devrl-s3-bucket/sample-apps/people/miriam_aupont.jpg" + }, + { + "attributes": { + "type": "Hutte__Broker__c", + "referenceId": "MichelleLambertRef" + }, + "Name": "Michelle Lambert", + "Hutte__Title__c": "Senior Broker", + "Hutte__Phone__c": "617-244-3672", + "Hutte__Mobile_Phone__c": "617-244-3672", + "Hutte__Email__c": "michelle@dreamhouse.demo", + "Hutte__Picture__c": "https://s3-us-west-2.amazonaws.com/dev-or-devrl-s3-bucket/sample-apps/people/michelle_lambert.jpg" + }, + { + "attributes": { + "type": "Hutte__Broker__c", + "referenceId": "VictorOchoaRef" + }, + "Name": "Victor Ochoa", + "Hutte__Title__c": "Senior Broker", + "Hutte__Phone__c": "617-244-3672", + "Hutte__Mobile_Phone__c": "617-244-3672", + "Hutte__Email__c": "victor@dreamhouse.demo", + "Hutte__Picture__c": "https://s3-us-west-2.amazonaws.com/dev-or-devrl-s3-bucket/sample-apps/people/victor_ochoa.jpg" + } + ] +} diff --git a/data/brokers-data.json.tmp b/data/brokers-data.json.tmp new file mode 100644 index 0000000..e69de29 diff --git a/data/contacts-data.json b/data/contacts-data.json new file mode 100644 index 0000000..4e4e9dc --- /dev/null +++ b/data/contacts-data.json @@ -0,0 +1,54 @@ +{ + "records": [ + { + "attributes": { + "type": "Contact", + "referenceId": "Contact1Ref" + }, + "FirstName": "Brad", + "LastName": "Holmes", + "Phone": "617-555-0143", + "Email": "bholmes@goodmail.com" + }, + { + "attributes": { + "type": "Contact", + "referenceId": "Contact2Ref" + }, + "FirstName": "Leslie", + "LastName": "Martin", + "Phone": "617-555-0112", + "Email": "leslie@pentagon.com" + }, + { + "attributes": { + "type": "Contact", + "referenceId": "Contact3Ref" + }, + "FirstName": "July", + "LastName": "Walker", + "Phone": "617-555-0170", + "Email": "julywalker@brain.com" + }, + { + "attributes": { + "type": "Contact", + "referenceId": "Contact4Ref" + }, + "FirstName": "Anna", + "LastName": "Jones", + "Phone": "617-555-0181", + "Email": "annaj@mymail.com" + }, + { + "attributes": { + "type": "Contact", + "referenceId": "Contact5Ref" + }, + "FirstName": "John", + "LastName": "Connor", + "Phone": "617-555-0133", + "Email": "jconnor@goodmail.com" + } + ] +} diff --git a/data/contacts-data.json.tmp b/data/contacts-data.json.tmp new file mode 100644 index 0000000..e69de29 diff --git a/data/properties-data.json b/data/properties-data.json new file mode 100644 index 0000000..9e8032f --- /dev/null +++ b/data/properties-data.json @@ -0,0 +1,268 @@ +{ + "records": [ + { + "attributes": { + "type": "Hutte__Property__c", + "referenceId": "18HenryStRef" + }, + "Name": "Stunning Victorian", + "Hutte__Address__c": "18 Henry St", + "Hutte__City__c": "Cambridge", + "Hutte__State__c": "MA", + "Hutte__Zip__c": "01742", + "Hutte__Price__c": 975000, + "Hutte__Beds__c": 4, + "Hutte__Baths__c": 3, + "Hutte__Location__Longitude__s": -71.11095, + "Hutte__Location__Latitude__s": 42.35663, + "Hutte__Picture__c": "https://s3-us-west-2.amazonaws.com/dev-or-devrl-s3-bucket/sample-apps/realty/house01.jpg", + "Hutte__Thumbnail__c": "https://s3-us-west-2.amazonaws.com/dev-or-devrl-s3-bucket/sample-apps/realty/house01sq.jpg", + "Hutte__Tags__c": "victorian", + "Hutte__Description__c": "Lorem ipsum dolor sit amet", + "Hutte__Broker__c": "@CarolineBrookerRef", + "Hutte__Status__c": "Available" + }, + { + "attributes": { + "type": "Hutte__Property__c", + "referenceId": "24PearlStRef" + }, + "Name": "Ultimate Sophistication", + "Hutte__Address__c": "24 Pearl St", + "Hutte__City__c": "Cambridge", + "Hutte__State__c": "MA", + "Hutte__Zip__c": "02420", + "Hutte__Price__c": 1200000, + "Hutte__Beds__c": 5, + "Hutte__Baths__c": 4, + "Hutte__Location__Longitude__s": -71.10869, + "Hutte__Location__Latitude__s": 42.359103, + "Hutte__Picture__c": "https://s3-us-west-2.amazonaws.com/dev-or-devrl-s3-bucket/sample-apps/realty/house02.jpg", + "Hutte__Thumbnail__c": "https://s3-us-west-2.amazonaws.com/dev-or-devrl-s3-bucket/sample-apps/realty/house02sq.jpg", + "Hutte__Tags__c": "colonial", + "Hutte__Description__c": "Lorem ipsum dolor sit amet", + "Hutte__Broker__c": "@MichaelJonesRef", + "Hutte__Status__c": "Contracted" + }, + { + "attributes": { + "type": "Hutte__Property__c", + "referenceId": "72FrancisStRef" + }, + "Name": "Modern City Living", + "Hutte__Address__c": "72 Francis St", + "Hutte__City__c": "Boston", + "Hutte__State__c": "MA", + "Hutte__Zip__c": "02420", + "Hutte__Price__c": 825000, + "Hutte__Beds__c": 5, + "Hutte__Baths__c": 4, + "Hutte__Location__Longitude__s": -71.106827, + "Hutte__Location__Latitude__s": 42.335435, + "Hutte__Picture__c": "https://s3-us-west-2.amazonaws.com/dev-or-devrl-s3-bucket/sample-apps/realty/house03.jpg", + "Hutte__Thumbnail__c": "https://s3-us-west-2.amazonaws.com/dev-or-devrl-s3-bucket/sample-apps/realty/house03sq.jpg", + "Hutte__Tags__c": "contemporary", + "Hutte__Description__c": "Lorem ipsum dolor sit amet", + "Hutte__Broker__c": "@JonathanBradleyRef", + "Hutte__Status__c": "Pre Market" + }, + { + "attributes": { + "type": "Hutte__Property__c", + "referenceId": "32PrinceStRef" + }, + "Name": "Stunning Colonial", + "Hutte__Address__c": "32 Prince St", + "Hutte__City__c": "Cambridge", + "Hutte__State__c": "MA", + "Hutte__Zip__c": "02420", + "Hutte__Price__c": 930000, + "Hutte__Beds__c": 5, + "Hutte__Baths__c": 4, + "Hutte__Location__Longitude__s": -71.110448, + "Hutte__Location__Latitude__s": 42.360642, + "Hutte__Picture__c": "https://s3-us-west-2.amazonaws.com/dev-or-devrl-s3-bucket/sample-apps/realty/house04.jpg", + "Hutte__Thumbnail__c": "https://s3-us-west-2.amazonaws.com/dev-or-devrl-s3-bucket/sample-apps/realty/house04sq.jpg", + "Hutte__Tags__c": "colonial", + "Hutte__Description__c": "Lorem ipsum dolor sit amet", + "Hutte__Broker__c": "@JenniferWuRef", + "Hutte__Status__c": "Available" + }, + { + "attributes": { + "type": "Hutte__Property__c", + "referenceId": "110BaxterStRef" + }, + "Name": "Waterfront in the City", + "Hutte__Address__c": "110 Baxter Street", + "Hutte__City__c": "Boston", + "Hutte__State__c": "MA", + "Hutte__Zip__c": "02420", + "Hutte__Price__c": 850000, + "Hutte__Beds__c": 3, + "Hutte__Baths__c": 2, + "Hutte__Location__Longitude__s": -71.084454, + "Hutte__Location__Latitude__s": 42.368168, + "Hutte__Picture__c": "https://s3-us-west-2.amazonaws.com/dev-or-devrl-s3-bucket/sample-apps/realty/house05.jpg", + "Hutte__Thumbnail__c": "https://s3-us-west-2.amazonaws.com/dev-or-devrl-s3-bucket/sample-apps/realty/house05sq.jpg", + "Hutte__Tags__c": "contemporary", + "Hutte__Description__c": "Lorem ipsum dolor sit amet", + "Hutte__Broker__c": "@OliviaGreenRef", + "Hutte__Status__c": "Closed" + }, + { + "attributes": { + "type": "Hutte__Property__c", + "referenceId": "448HanoverStRef" + }, + "Name": "Quiet Retreat", + "Hutte__Address__c": "448 Hanover St", + "Hutte__City__c": "Boston", + "Hutte__State__c": "MA", + "Hutte__Zip__c": "02420", + "Hutte__Price__c": 725000, + "Hutte__Beds__c": 4, + "Hutte__Baths__c": 2, + "Hutte__Location__Longitude__s": -71.052617, + "Hutte__Location__Latitude__s": 42.366855, + "Hutte__Picture__c": "https://s3-us-west-2.amazonaws.com/dev-or-devrl-s3-bucket/sample-apps/realty/house06.jpg", + "Hutte__Thumbnail__c": "https://s3-us-west-2.amazonaws.com/dev-or-devrl-s3-bucket/sample-apps/realty/house06sq.jpg", + "Hutte__Tags__c": "colonial", + "Hutte__Description__c": "Lorem ipsum dolor sit amet", + "Hutte__Broker__c": "@MiriamAupontRef", + "Hutte__Status__c": "Contracted" + }, + { + "attributes": { + "type": "Hutte__Property__c", + "referenceId": "127EndicottStRef" + }, + "Name": "City Living", + "Hutte__Address__c": "127 Endicott St", + "Hutte__City__c": "Boston", + "Hutte__State__c": "MA", + "Hutte__Zip__c": "02420", + "Hutte__Price__c": 450000, + "Hutte__Beds__c": 3, + "Hutte__Baths__c": 1, + "Hutte__Location__Longitude__s": -71.057352, + "Hutte__Location__Latitude__s": 42.365003, + "Hutte__Picture__c": "https://s3-us-west-2.amazonaws.com/dev-or-devrl-s3-bucket/sample-apps/realty/house07.jpg", + "Hutte__Thumbnail__c": "https://s3-us-west-2.amazonaws.com/dev-or-devrl-s3-bucket/sample-apps/realty/house07sq.jpg", + "Hutte__Tags__c": "colonial", + "Hutte__Description__c": "Lorem ipsum dolor sit amet", + "Hutte__Broker__c": "@MichelleLambertRef", + "Hutte__Status__c": "Available" + }, + { + "attributes": { + "type": "Hutte__Property__c", + "referenceId": "48BrattleStRef" + }, + "Name": "Heart of Harvard Square", + "Hutte__Address__c": "48 Brattle St", + "Hutte__City__c": "Cambridge", + "Hutte__State__c": "MA", + "Hutte__Zip__c": "02420", + "Hutte__Price__c": 450000, + "Hutte__Beds__c": 5, + "Hutte__Baths__c": 4, + "Hutte__Location__Longitude__s": -71.121653, + "Hutte__Location__Latitude__s": 42.374117, + "Hutte__Picture__c": "https://s3-us-west-2.amazonaws.com/dev-or-devrl-s3-bucket/sample-apps/realty/house10.jpg", + "Hutte__Thumbnail__c": "https://s3-us-west-2.amazonaws.com/dev-or-devrl-s3-bucket/sample-apps/realty/house10sq.jpg", + "Hutte__Tags__c": "victorian", + "Hutte__Description__c": "Lorem ipsum dolor sit amet", + "Hutte__Broker__c": "@VictorOchoaRef", + "Hutte__Status__c": "Under Agreement" + }, + { + "attributes": { + "type": "Hutte__Property__c", + "referenceId": "121HarborwalkRef" + }, + "Name": "Seaport District Retreat", + "Hutte__Address__c": "121 Harborwalk", + "Hutte__City__c": "Boston", + "Hutte__State__c": "MA", + "Hutte__Zip__c": "02420", + "Hutte__Price__c": 450000, + "Hutte__Beds__c": 3, + "Hutte__Baths__c": 3, + "Hutte__Location__Longitude__s": -71.049327, + "Hutte__Location__Latitude__s": 42.35695, + "Hutte__Picture__c": "https://s3-us-west-2.amazonaws.com/dev-or-devrl-s3-bucket/sample-apps/realty/house09.jpg", + "Hutte__Thumbnail__c": "https://s3-us-west-2.amazonaws.com/dev-or-devrl-s3-bucket/sample-apps/realty/house09sq.jpg", + "Hutte__Tags__c": "contemporary", + "Hutte__Description__c": "Lorem ipsum dolor sit amet", + "Hutte__Broker__c": "@CarolineBrookerRef", + "Hutte__Status__c": "Available" + }, + { + "attributes": { + "type": "Hutte__Property__c", + "referenceId": "640HarrisonAveRef" + }, + "Name": "Contemporary City Living", + "Hutte__Address__c": "640 Harrison Ave", + "Hutte__City__c": "Boston", + "Hutte__State__c": "MA", + "Hutte__Zip__c": "02420", + "Hutte__Price__c": 650000, + "Hutte__Beds__c": 2, + "Hutte__Baths__c": 2, + "Hutte__Location__Longitude__s": -71.068781, + "Hutte__Location__Latitude__s": 42.339892, + "Hutte__Picture__c": "https://s3-us-west-2.amazonaws.com/dev-or-devrl-s3-bucket/sample-apps/realty/house08.jpg", + "Hutte__Thumbnail__c": "https://s3-us-west-2.amazonaws.com/dev-or-devrl-s3-bucket/sample-apps/realty/house08sq.jpg", + "Hutte__Tags__c": "contemporary", + "Hutte__Description__c": "Lorem ipsum dolor sit amet", + "Hutte__Broker__c": "@MichaelJonesRef", + "Hutte__Status__c": "Available" + }, + { + "attributes": { + "type": "Hutte__Property__c", + "referenceId": "95GloucesterStRef" + }, + "Name": "Architectural Details", + "Hutte__Address__c": "95 Gloucester St", + "Hutte__City__c": "Boston", + "Hutte__State__c": "MA", + "Hutte__Zip__c": "02420", + "Hutte__Price__c": 690000, + "Hutte__Beds__c": 3, + "Hutte__Baths__c": 3, + "Hutte__Location__Latitude__s": 42.349693, + "Hutte__Location__Longitude__s": -71.084407, + "Hutte__Picture__c": "https://s3-us-west-2.amazonaws.com/dev-or-devrl-s3-bucket/sample-apps/realty/house11.jpg", + "Hutte__Thumbnail__c": "https://s3-us-west-2.amazonaws.com/dev-or-devrl-s3-bucket/sample-apps/realty/house11sq.jpg", + "Hutte__Tags__c": "contemporary", + "Hutte__Description__c": "Lorem ipsum dolor sit amet", + "Hutte__Broker__c": "@JonathanBradleyRef", + "Hutte__Status__c": "Available" + }, + { + "attributes": { + "type": "Hutte__Property__c", + "referenceId": "145CommonwealthAveRef" + }, + "Name": "Contemporary Luxury", + "Hutte__Address__c": "145 Commonwealth Ave", + "Hutte__City__c": "Boston", + "Hutte__State__c": "MA", + "Hutte__Zip__c": "02420", + "Hutte__Price__c": 845000, + "Hutte__Beds__c": 4, + "Hutte__Baths__c": 3, + "Hutte__Location__Latitude__s": 42.352466, + "Hutte__Location__Longitude__s": -71.075311, + "Hutte__Picture__c": "https://s3-us-west-2.amazonaws.com/dev-or-devrl-s3-bucket/sample-apps/realty/house12.jpg", + "Hutte__Thumbnail__c": "https://s3-us-west-2.amazonaws.com/dev-or-devrl-s3-bucket/sample-apps/realty/house12sq.jpg", + "Hutte__Tags__c": "contemporary", + "Hutte__Description__c": "Lorem ipsum dolor sit amet", + "Hutte__Broker__c": "@JenniferWuRef", + "Hutte__Status__c": "Available" + } + ] +} diff --git a/data/properties-data.json.tmp b/data/properties-data.json.tmp new file mode 100644 index 0000000..e69de29 diff --git a/data/sample-data-plan.json b/data/sample-data-plan.json new file mode 100644 index 0000000..95b2c49 --- /dev/null +++ b/data/sample-data-plan.json @@ -0,0 +1,23 @@ +[ + { + "sobject": "Hutte__Broker__c", + "saveRefs": true, + "files": [ + "brokers-data.json" + ] + }, + { + "sobject": "Hutte__Property__c", + "resolveRefs": true, + "files": [ + "properties-data.json" + ] + }, + { + "sobject": "Contact", + "resolveRefs": false, + "files": [ + "contacts-data.json" + ] + } +] diff --git a/data/sample-data-plan.json.tmp b/data/sample-data-plan.json.tmp new file mode 100644 index 0000000..e69de29 diff --git a/data/sfdmu/Account.csv b/data/sfdmu/Account.csv new file mode 100644 index 0000000..e69de29 diff --git a/data/sfdmu/Contact.csv b/data/sfdmu/Contact.csv new file mode 100644 index 0000000..15a6954 --- /dev/null +++ b/data/sfdmu/Contact.csv @@ -0,0 +1,6 @@ +$$Email$LastName$FirstName,Account.Name,AssistantName,AssistantPhone,Birthdate,CleanStatus,Department,Description,Email,EmailBouncedDate,EmailBouncedReason,Fax,FirstName,HomePhone,Individual.Name,Jigsaw,LastName,LeadSource,MailingCity,MailingCountry,MailingGeocodeAccuracy,MailingLatitude,MailingLongitude,MailingPostalCode,MailingState,MailingStreet,MobilePhone,OtherCity,OtherCountry,OtherGeocodeAccuracy,OtherLatitude,OtherLongitude,OtherPhone,OtherPostalCode,OtherState,OtherStreet,Phone,ReportsTo.$$Email$LastName$FirstName,Salutation,Title +annaj@mymail.com;Jones;Anna,,,,,Pending,,,annaj@mymail.com,,,,Anna,,,,Jones,,,,,,,,,,,,,,,,,,,,617-555-0181,,, +bholmes@goodmail.com;Holmes;Brad,,,,,Pending,,,bholmes@goodmail.com,,,,Brad,,,,Holmes,,,,,,,,,,,,,,,,,,,,617-555-0143,,, +jconnor@goodmail.com;Connor;John,,,,,Pending,,,jconnor@goodmail.com,,,,John,,,,Connor,,,,,,,,,,,,,,,,,,,,617-555-0133,,, +julywalker@brain.com;Walker;July,,,,,Pending,,,julywalker@brain.com,,,,July,,,,Walker,,,,,,,,,,,,,,,,,,,,617-555-0170,,, +leslie@pentagon.com;Martin;Leslie,,,,,Pending,,,leslie@pentagon.com,,,,Leslie,,,,Martin,,,,,,,,,,,,,,,,,,,,617-555-0112,,, diff --git a/data/sfdmu/Hutte__Broker__c.csv b/data/sfdmu/Hutte__Broker__c.csv new file mode 100644 index 0000000..49a6b45 --- /dev/null +++ b/data/sfdmu/Hutte__Broker__c.csv @@ -0,0 +1,9 @@ +Hutte__Broker_Id__c,Hutte__Email__c,Hutte__Mobile_Phone__c,Hutte__Phone__c,Hutte__Picture__c,Hutte__Title__c,Name +,caroline@dreamhouse.demo,617-244-3672,617-244-3672,https://s3-us-west-2.amazonaws.com/dev-or-devrl-s3-bucket/sample-apps/people/caroline_kingsley.jpg,Senior Broker,Caroline Kingsley +,jen@dreamhouse.demo,617-244-3672,617-244-3672,https://s3-us-west-2.amazonaws.com/dev-or-devrl-s3-bucket/sample-apps/people/jennifer_wu.jpg,Senior Broker,Jennifer Wu +,jonathan@dreamhouse.demo,617-244-3672,617-244-3672,https://s3-us-west-2.amazonaws.com/dev-or-devrl-s3-bucket/sample-apps/people/jonathan_bradley.jpg,Senior Broker,Jonathan Bradley +,michael@dreamhouse.demo,617-244-3672,617-244-3672,https://s3-us-west-2.amazonaws.com/dev-or-devrl-s3-bucket/sample-apps/people/michael_jones.jpg,Senior Broker,Michael Jones +,michelle@dreamhouse.demo,617-244-3672,617-244-3672,https://s3-us-west-2.amazonaws.com/dev-or-devrl-s3-bucket/sample-apps/people/michelle_lambert.jpg,Senior Broker,Michelle Lambert +,miriam@dreamhouse.demo,617-244-3672,617-244-3672,https://s3-us-west-2.amazonaws.com/dev-or-devrl-s3-bucket/sample-apps/people/miriam_aupont.jpg,Senior Broker,Miriam Aupont +,olivia@dreamhouse.demo,617-244-3672,617-244-3672,https://s3-us-west-2.amazonaws.com/dev-or-devrl-s3-bucket/sample-apps/people/olivia_green.jpg,Senior Broker,Olivia Green +,victor@dreamhouse.demo,617-244-3672,617-244-3672,https://s3-us-west-2.amazonaws.com/dev-or-devrl-s3-bucket/sample-apps/people/victor_ochoa.jpg,Senior Broker,Victor Ochoa diff --git a/data/sfdmu/Hutte__Property__c.csv b/data/sfdmu/Hutte__Property__c.csv new file mode 100644 index 0000000..06a2314 --- /dev/null +++ b/data/sfdmu/Hutte__Property__c.csv @@ -0,0 +1,13 @@ +$$Name$Hutte__Location__Longitude__s$Hutte__Location__Latitude__s,Hutte__Address__c,Hutte__Assessed_Value__c,Hutte__Baths__c,Hutte__Beds__c,Hutte__Broker__r.Hutte__Email__c,Hutte__City__c,Hutte__Date_Agreement__c,Hutte__Date_Closed__c,Hutte__Date_Contracted__c,Hutte__Date_Listed__c,Hutte__Date_Pre_Market__c,Hutte__Description__c,Hutte__Location__Latitude__s,Hutte__Location__Longitude__s,Hutte__Picture__c,Hutte__Price__c,Hutte__Price_Sold__c,Hutte__State__c,Hutte__Status__c,Hutte__Tags__c,Hutte__Thumbnail__c,Hutte__Zip__c,Name +Architectural Details;-71.084407;42.349693,95 Gloucester St,,3,3,jonathan@dreamhouse.demo,Boston,,,,2024-07-27,,Lorem ipsum dolor sit amet,42.349693,-71.084407,https://s3-us-west-2.amazonaws.com/dev-or-devrl-s3-bucket/sample-apps/realty/house11.jpg,690000,,MA,Available,contemporary,https://s3-us-west-2.amazonaws.com/dev-or-devrl-s3-bucket/sample-apps/realty/house11sq.jpg,02420,Architectural Details +City Living;-71.057352;42.365003,127 Endicott St,,1,3,michelle@dreamhouse.demo,Boston,,,,2024-07-27,,Lorem ipsum dolor sit amet,42.365003,-71.057352,https://s3-us-west-2.amazonaws.com/dev-or-devrl-s3-bucket/sample-apps/realty/house07.jpg,450000,,MA,Available,colonial,https://s3-us-west-2.amazonaws.com/dev-or-devrl-s3-bucket/sample-apps/realty/house07sq.jpg,02420,City Living +Contemporary City Living;-71.068781;42.339892,640 Harrison Ave,,2,2,michael@dreamhouse.demo,Boston,,,,2024-07-27,,Lorem ipsum dolor sit amet,42.339892,-71.068781,https://s3-us-west-2.amazonaws.com/dev-or-devrl-s3-bucket/sample-apps/realty/house08.jpg,650000,,MA,Available,contemporary,https://s3-us-west-2.amazonaws.com/dev-or-devrl-s3-bucket/sample-apps/realty/house08sq.jpg,02420,Contemporary City Living +Contemporary Luxury;-71.075311;42.352466,145 Commonwealth Ave,,3,4,jen@dreamhouse.demo,Boston,,,,2024-07-27,,Lorem ipsum dolor sit amet,42.352466,-71.075311,https://s3-us-west-2.amazonaws.com/dev-or-devrl-s3-bucket/sample-apps/realty/house12.jpg,845000,,MA,Available,contemporary,https://s3-us-west-2.amazonaws.com/dev-or-devrl-s3-bucket/sample-apps/realty/house12sq.jpg,02420,Contemporary Luxury +Heart of Harvard Square;-71.121653;42.374117,48 Brattle St,,4,5,victor@dreamhouse.demo,Cambridge,,,,2024-07-27,,Lorem ipsum dolor sit amet,42.374117,-71.121653,https://s3-us-west-2.amazonaws.com/dev-or-devrl-s3-bucket/sample-apps/realty/house10.jpg,450000,,MA,Under Agreement,victorian,https://s3-us-west-2.amazonaws.com/dev-or-devrl-s3-bucket/sample-apps/realty/house10sq.jpg,02420,Heart of Harvard Square +Modern City Living;-71.106827;42.335435,72 Francis St,,4,5,jonathan@dreamhouse.demo,Boston,,,,2024-07-27,,Lorem ipsum dolor sit amet,42.335435,-71.106827,https://s3-us-west-2.amazonaws.com/dev-or-devrl-s3-bucket/sample-apps/realty/house03.jpg,825000,,MA,Pre Market,contemporary,https://s3-us-west-2.amazonaws.com/dev-or-devrl-s3-bucket/sample-apps/realty/house03sq.jpg,02420,Modern City Living +Quiet Retreat;-71.052617;42.366855,448 Hanover St,,2,4,miriam@dreamhouse.demo,Boston,,,,2024-07-27,,Lorem ipsum dolor sit amet,42.366855,-71.052617,https://s3-us-west-2.amazonaws.com/dev-or-devrl-s3-bucket/sample-apps/realty/house06.jpg,725000,,MA,Contracted,colonial,https://s3-us-west-2.amazonaws.com/dev-or-devrl-s3-bucket/sample-apps/realty/house06sq.jpg,02420,Quiet Retreat +Seaport District Retreat;-71.049327;42.35695,121 Harborwalk,,3,3,caroline@dreamhouse.demo,Boston,,,,2024-07-27,,Lorem ipsum dolor sit amet,42.35695,-71.049327,https://s3-us-west-2.amazonaws.com/dev-or-devrl-s3-bucket/sample-apps/realty/house09.jpg,450000,,MA,Available,contemporary,https://s3-us-west-2.amazonaws.com/dev-or-devrl-s3-bucket/sample-apps/realty/house09sq.jpg,02420,Seaport District Retreat +Stunning Colonial;-71.110448;42.360642,32 Prince St,,4,5,jen@dreamhouse.demo,Cambridge,,,,2024-07-27,,Lorem ipsum dolor sit amet,42.360642,-71.110448,https://s3-us-west-2.amazonaws.com/dev-or-devrl-s3-bucket/sample-apps/realty/house04.jpg,930000,,MA,Available,colonial,https://s3-us-west-2.amazonaws.com/dev-or-devrl-s3-bucket/sample-apps/realty/house04sq.jpg,02420,Stunning Colonial +Stunning Victorian;-71.11095;42.35663,18 Henry St,,3,4,caroline@dreamhouse.demo,Cambridge,,,,2024-07-27,,Lorem ipsum dolor sit amet,42.35663,-71.11095,https://s3-us-west-2.amazonaws.com/dev-or-devrl-s3-bucket/sample-apps/realty/house01.jpg,975000,,MA,Available,victorian,https://s3-us-west-2.amazonaws.com/dev-or-devrl-s3-bucket/sample-apps/realty/house01sq.jpg,01742,Stunning Victorian +Ultimate Sophistication;-71.10869;42.359103,24 Pearl St,,4,5,michael@dreamhouse.demo,Cambridge,,,,2024-07-27,,Lorem ipsum dolor sit amet,42.359103,-71.10869,https://s3-us-west-2.amazonaws.com/dev-or-devrl-s3-bucket/sample-apps/realty/house02.jpg,1200000,,MA,Contracted,colonial,https://s3-us-west-2.amazonaws.com/dev-or-devrl-s3-bucket/sample-apps/realty/house02sq.jpg,02420,Ultimate Sophistication +Waterfront in the City;-71.084454;42.368168,110 Baxter Street,,2,3,olivia@dreamhouse.demo,Boston,,,,2024-07-27,,Lorem ipsum dolor sit amet,42.368168,-71.084454,https://s3-us-west-2.amazonaws.com/dev-or-devrl-s3-bucket/sample-apps/realty/house05.jpg,850000,,MA,Closed,contemporary,https://s3-us-west-2.amazonaws.com/dev-or-devrl-s3-bucket/sample-apps/realty/house05sq.jpg,02420,Waterfront in the City diff --git a/data/sfdmu/Individual.csv b/data/sfdmu/Individual.csv new file mode 100644 index 0000000..e69de29 diff --git a/data/sfdmu/MissingParentRecordsReport.csv b/data/sfdmu/MissingParentRecordsReport.csv new file mode 100644 index 0000000..e69de29 diff --git a/data/sfdmu/export.json b/data/sfdmu/export.json new file mode 100644 index 0000000..193602f --- /dev/null +++ b/data/sfdmu/export.json @@ -0,0 +1,20 @@ +{ + "objects": [ + { + "query": "SELECT readonly_false FROM Hutte__Broker__c ORDER BY Name ASC", + "operation": "Upsert", + "externalId": "Hutte__Email__c" + }, + { + "query": "SELECT readonly_false FROM Hutte__Property__c ORDER BY Name ASC", + "operation": "Upsert", + "externalId": "Name;Hutte__Location__Longitude__s;Hutte__Location__Latitude__s" + }, + { + "query": "SELECT readonly_false FROM Contact ORDER BY Email,LastName,FirstName ASC", + "operation": "Upsert", + "externalId": "Email;LastName;FirstName" + } + ], + "excludeIdsFromCSVFiles": true +} diff --git a/force-app/main/default/applications/Dreamhouse.app-meta.xml b/force-app/main/default/applications/Dreamhouse.app-meta.xml new file mode 100644 index 0000000..918a290 --- /dev/null +++ b/force-app/main/default/applications/Dreamhouse.app-meta.xml @@ -0,0 +1,63 @@ + + + + View + Action override created by Lightning App Builder during activation. + Broker_Record_Page + Large + false + Flexipage + Broker__c + + + View + Action override created by Lightning App Builder during activation. + Broker_Record_Page + Small + false + Flexipage + Broker__c + + + View + Action override created by Lightning App Builder during activation. + Property_Record_Page + Large + false + Flexipage + Property__c + + + View + Action override created by Lightning App Builder during activation. + Property_Record_Page + Small + false + Flexipage + Property__c + + + #9189FE + HUTTE_LOGOTYPE_MAIN_SYMBOL_ALPHA + 1 + false + + Small + Large + false + false + false + false + + Standard + all + standard-home + Property_Explorer + Property_Finder + standard-Contact + Property__c + Broker__c + standard-File + Settings + Lightning + diff --git a/force-app/main/default/aura/pageTemplate_2_7_3/pageTemplate_2_7_3.cmp b/force-app/main/default/aura/pageTemplate_2_7_3/pageTemplate_2_7_3.cmp new file mode 100644 index 0000000..43e626e --- /dev/null +++ b/force-app/main/default/aura/pageTemplate_2_7_3/pageTemplate_2_7_3.cmp @@ -0,0 +1,41 @@ + + + + +
+ + + + + {!v.left} + + + {!v.center} + + + {!v.right} + + + + + + + + {!v.left} {!v.center} {!v.right} + + + +
+
\ No newline at end of file diff --git a/force-app/main/default/aura/pageTemplate_2_7_3/pageTemplate_2_7_3.cmp-meta.xml b/force-app/main/default/aura/pageTemplate_2_7_3/pageTemplate_2_7_3.cmp-meta.xml new file mode 100644 index 0000000..8aa7f3b --- /dev/null +++ b/force-app/main/default/aura/pageTemplate_2_7_3/pageTemplate_2_7_3.cmp-meta.xml @@ -0,0 +1,5 @@ + + + 61.0 + A Lightning Component Bundle + diff --git a/force-app/main/default/aura/pageTemplate_2_7_3/pageTemplate_2_7_3.design b/force-app/main/default/aura/pageTemplate_2_7_3/pageTemplate_2_7_3.design new file mode 100644 index 0000000..5bab1af --- /dev/null +++ b/force-app/main/default/aura/pageTemplate_2_7_3/pageTemplate_2_7_3.design @@ -0,0 +1,9 @@ + + + + + + + + + \ No newline at end of file diff --git a/force-app/main/default/aura/pageTemplate_2_7_3/pageTemplate_2_7_3.svg b/force-app/main/default/aura/pageTemplate_2_7_3/pageTemplate_2_7_3.svg new file mode 100644 index 0000000..791b3c7 --- /dev/null +++ b/force-app/main/default/aura/pageTemplate_2_7_3/pageTemplate_2_7_3.svg @@ -0,0 +1,7 @@ + + + + + + + \ No newline at end of file diff --git a/force-app/main/default/classes/FileUtilities.cls b/force-app/main/default/classes/FileUtilities.cls new file mode 100644 index 0000000..f855c8a --- /dev/null +++ b/force-app/main/default/classes/FileUtilities.cls @@ -0,0 +1,29 @@ +public with sharing class FileUtilities { + @AuraEnabled + public static String createFile(String base64data, String filename, String recordId) { + try { + ContentVersion contentVersion = new ContentVersion(); + contentVersion.VersionData = EncodingUtil.base64Decode(base64data); + contentVersion.Title = filename; + contentVersion.PathOnClient = filename; + insert contentVersion; + + contentVersion = [ + SELECT ContentDocumentId + FROM ContentVersion + WHERE Id = :contentVersion.Id + WITH USER_MODE + ]; + + ContentDocumentLink contentDocumentLink = new ContentDocumentLink(); + contentDocumentLink.ContentDocumentId = contentVersion.ContentDocumentId; + contentDocumentLink.LinkedEntityId = recordId; + contentDocumentLink.ShareType = 'V'; + insert contentDocumentLink; + + return contentDocumentLink.Id; + } catch (Exception e) { + throw new AuraHandledException('Error creating file: ' + e); + } + } +} diff --git a/force-app/main/default/classes/FileUtilities.cls-meta.xml b/force-app/main/default/classes/FileUtilities.cls-meta.xml new file mode 100644 index 0000000..651b172 --- /dev/null +++ b/force-app/main/default/classes/FileUtilities.cls-meta.xml @@ -0,0 +1,5 @@ + + + 61.0 + Active + diff --git a/force-app/main/default/classes/FileUtilitiesTest.cls b/force-app/main/default/classes/FileUtilitiesTest.cls new file mode 100644 index 0000000..bf45ac6 --- /dev/null +++ b/force-app/main/default/classes/FileUtilitiesTest.cls @@ -0,0 +1,76 @@ +@isTest +private with sharing class FileUtilitiesTest { + @isTest + static void createFileSucceedsWhenCorrectInput() { + // GIVEN + Property__c property = new Property__c(); + insert property; + + String base64Data = '/9j/4AAQSkZJRgABAQAAAQABAAD/4gHYSUNDX1BST0ZJTEUAAQEAAAHIAAAAAAQwAABtbnRyUkdCIFhZWiAAAAAAAAAAAAAAAABhY3NwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAA9tYAAQAAAADTLQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAlkZXNjAAAA8AAAACRyWFlaAAABFAAAABRnWFlaAAABKAAAABRiWFlaAAABPAAAABR3dHB0AAABUAAAABRyVFJDAAABZAAAAChnVFJDAAABZAAAAChiVFJDAAABZAAAAChjcHJ0AAABjAAAADxtbHVjAAAAAAAAAAEAAAAMZW5VUwAAAAgAAAAcAHMAUgBHAEJYWVogAAAAAAAAb6IAADj1AAADkFhZWiAAAAAAAABimQAAt4UAABjaWFlaIAAAAAAAACSgAAAPhAAAts9YWVogAAAAAAAA9tYAAQAAAADTLXBhcmEAAAAAAAQAAAACZmYAAPKnAAANWQAAE9AAAApbAAAAAAAAAABtbHVjAAAAAAAAAAEAAAAMZW5VUwAAACAAAAAcAEcAbwBvAGcAbABlACAASQBuAGMALgAgADIAMAAxADb'; + String fileName = 'file.png'; + String recordId = property.Id; + + // WHEN + String contentDocumentLinkId = FileUtilities.createFile(base64Data, fileName, recordId); + + // THEN + Assert.isNotNull(contentDocumentLinkId); + } + + @isTest + static void createFileFailsWhenIncorrectRecordId() { + // GIVEN + String base64Data = '/9j/4AAQSkZJRgABAQAAAQABAAD/4gHYSUNDX1BST0ZJTEUAAQEAAAHIAAAAAAQwAABtbnRyUkdCIFhZWiAAAAAAAAAAAAAAAABhY3NwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAA9tYAAQAAAADTLQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAlkZXNjAAAA8AAAACRyWFlaAAABFAAAABRnWFlaAAABKAAAABRiWFlaAAABPAAAABR3dHB0AAABUAAAABRyVFJDAAABZAAAAChnVFJDAAABZAAAAChiVFJDAAABZAAAAChjcHJ0AAABjAAAADxtbHVjAAAAAAAAAAEAAAAMZW5VUwAAAAgAAAAcAHMAUgBHAEJYWVogAAAAAAAAb6IAADj1AAADkFhZWiAAAAAAAABimQAAt4UAABjaWFlaIAAAAAAAACSgAAAPhAAAts9YWVogAAAAAAAA9tYAAQAAAADTLXBhcmEAAAAAAAQAAAACZmYAAPKnAAANWQAAE9AAAApbAAAAAAAAAABtbHVjAAAAAAAAAAEAAAAMZW5VUwAAACAAAAAcAEcAbwBvAGcAbABlACAASQBuAGMALgAgADIAMAAxADb'; + String fileName = 'file.png'; + String recordId = 'INVALID_ID'; + + try { + // WHEN + String contentDocumentLinkId = FileUtilities.createFile(base64Data, fileName, recordId); + Assert.fail('Expected an AuraHandledException'); + } catch (Exception e) { + // THEN + Assert.isInstanceOfType(e, AuraHandledException.class); + } + } + + @isTest + static void createFileFailsWhenIncorrectBase64Data() { + // GIVEN + Property__c property = new Property__c(); + insert property; + + String base64Data = ''; + String fileName = 'file.png'; + String recordId = property.Id; + + try { + // WHEN + String contentDocumentLinkId = FileUtilities.createFile(base64Data, fileName, recordId); + Assert.fail('Expected an AuraHandledException'); + } catch (Exception e) { + // THEN + Assert.isInstanceOfType(e, AuraHandledException.class); + } + } + + @isTest + static void createFileFailsWhenIncorrectFilename() { + // GIVEN + Property__c property = new Property__c(); + insert property; + + String base64Data = '/9j/4AAQSkZJRgABAQAAAQABAAD/4gHYSUNDX1BST0ZJTEUAAQEAAAHIAAAAAAQwAABtbnRyUkdCIFhZWiAAAAAAAAAAAAAAAABhY3NwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAA9tYAAQAAAADTLQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAlkZXNjAAAA8AAAACRyWFlaAAABFAAAABRnWFlaAAABKAAAABRiWFlaAAABPAAAABR3dHB0AAABUAAAABRyVFJDAAABZAAAAChnVFJDAAABZAAAAChiVFJDAAABZAAAAChjcHJ0AAABjAAAADxtbHVjAAAAAAAAAAEAAAAMZW5VUwAAAAgAAAAcAHMAUgBHAEJYWVogAAAAAAAAb6IAADj1AAADkFhZWiAAAAAAAABimQAAt4UAABjaWFlaIAAAAAAAACSgAAAPhAAAts9YWVogAAAAAAAA9tYAAQAAAADTLXBhcmEAAAAAAAQAAAACZmYAAPKnAAANWQAAE9AAAApbAAAAAAAAAABtbHVjAAAAAAAAAAEAAAAMZW5VUwAAACAAAAAcAEcAbwBvAGcAbABlACAASQBuAGMALgAgADIAMAAxADb'; + String fileName = ''; + String recordId = property.Id; + + try { + // WHEN + String contentDocumentLinkId = FileUtilities.createFile(base64Data, fileName, recordId); + Assert.fail('Expected an AuraHandledException'); + } catch (Exception e) { + // THEN + Assert.isInstanceOfType(e, AuraHandledException.class); + } + } +} diff --git a/force-app/main/default/classes/FileUtilitiesTest.cls-meta.xml b/force-app/main/default/classes/FileUtilitiesTest.cls-meta.xml new file mode 100644 index 0000000..651b172 --- /dev/null +++ b/force-app/main/default/classes/FileUtilitiesTest.cls-meta.xml @@ -0,0 +1,5 @@ + + + 61.0 + Active + diff --git a/force-app/main/default/classes/GeocodingService.cls b/force-app/main/default/classes/GeocodingService.cls new file mode 100644 index 0000000..e882a26 --- /dev/null +++ b/force-app/main/default/classes/GeocodingService.cls @@ -0,0 +1,72 @@ +public with sharing class GeocodingService { + private static final String BASE_URL = 'https://nominatim.openstreetmap.org/search?format=json'; + + @InvocableMethod(callout=true label='Geocode address') + public static List geocodeAddresses( + List addresses + ) { + List computedCoordinates = new List(); + + for (GeocodingAddress address : addresses) { + String geocodingUrl = BASE_URL; + geocodingUrl += (String.isNotBlank(address.street)) + ? '&street=' + address.street + : ''; + geocodingUrl += (String.isNotBlank(address.city)) + ? '&city=' + address.city + : ''; + geocodingUrl += (String.isNotBlank(address.state)) + ? '&state=' + address.state + : ''; + geocodingUrl += (String.isNotBlank(address.country)) + ? '&country=' + address.country + : ''; + geocodingUrl += (String.isNotBlank(address.postalcode)) + ? '&postalcode=' + address.postalcode + : ''; + + Coordinates coords = new Coordinates(); + if (geocodingUrl != BASE_URL) { + Http http = new Http(); + HttpRequest request = new HttpRequest(); + request.setEndpoint(geocodingUrl); + request.setMethod('GET'); + request.setHeader( + 'http-referer', + URL.getOrgDomainUrl().toExternalForm() + ); + HttpResponse response = http.send(request); + if (response.getStatusCode() == 200) { + List deserializedCoords = (List) JSON.deserialize( + response.getBody(), + List.class + ); + coords = deserializedCoords[0]; + } + } + + computedCoordinates.add(coords); + } + return computedCoordinates; + } + + public class GeocodingAddress { + @InvocableVariable + public String street; + @InvocableVariable + public String city; + @InvocableVariable + public String state; + @InvocableVariable + public String country; + @InvocableVariable + public String postalcode; + } + + public class Coordinates { + @InvocableVariable + public Decimal lat; + @InvocableVariable + public Decimal lon; + } +} \ No newline at end of file diff --git a/force-app/main/default/classes/GeocodingService.cls-meta.xml b/force-app/main/default/classes/GeocodingService.cls-meta.xml new file mode 100644 index 0000000..651b172 --- /dev/null +++ b/force-app/main/default/classes/GeocodingService.cls-meta.xml @@ -0,0 +1,5 @@ + + + 61.0 + Active + diff --git a/force-app/main/default/classes/GeocodingServiceTest.cls b/force-app/main/default/classes/GeocodingServiceTest.cls new file mode 100644 index 0000000..4ebde07 --- /dev/null +++ b/force-app/main/default/classes/GeocodingServiceTest.cls @@ -0,0 +1,100 @@ +@isTest +private with sharing class GeocodingServiceTest { + private static final String STREET = 'Camino del Jueves 26'; + private static final String CITY = 'Armilla'; + private static final String POSTAL_CODE = '18100'; + private static final String STATE = 'Granada'; + private static final String COUNTRY = 'Spain'; + private static final Decimal LATITUDE = 3.123; + private static final Decimal LONGITUDE = 31.333; + + @isTest + static void successResponse() { + // GIVEN + GeocodingService.GeocodingAddress address = new GeocodingService.GeocodingAddress(); + address.street = STREET; + address.city = CITY; + address.postalcode = POSTAL_CODE; + address.state = STATE; + address.country = COUNTRY; + + Test.setMock( + HttpCalloutMock.class, + new OpenStreetMapHttpCalloutMockImpl() + ); + + // WHEN + List computedCoordinates = GeocodingService.geocodeAddresses( + new List{ address } + ); + + // THEN + Assert.areEqual(1, computedCoordinates.size()); + Assert.areEqual(LATITUDE, computedCoordinates[0].lat); + Assert.areEqual(LONGITUDE, computedCoordinates[0].lon); + } + @isTest + static void blankAddress() { + // GIVEN + GeocodingService.GeocodingAddress address = new GeocodingService.GeocodingAddress(); + + Test.setMock( + HttpCalloutMock.class, + new OpenStreetMapHttpCalloutMockImpl() + ); + + // WHEN + List computedCoordinates = GeocodingService.geocodeAddresses( + new List{ address } + ); + + // THEN + Assert.areEqual(1, computedCoordinates.size()); + Assert.isNull(computedCoordinates[0].lat); + Assert.isNull(computedCoordinates[0].lon); + } + @isTest + static void errorResponse() { + // GIVEN + GeocodingService.GeocodingAddress address = new GeocodingService.GeocodingAddress(); + address.street = STREET; + address.city = CITY; + address.postalcode = POSTAL_CODE; + address.state = STATE; + address.country = COUNTRY; + + Test.setMock( + HttpCalloutMock.class, + new OpenStreetMapHttpCalloutMockImplError() + ); + + // WHEN + List computedCoordinates = GeocodingService.geocodeAddresses( + new List{ address } + ); + + // THEN + Assert.areEqual(1, computedCoordinates.size()); + Assert.isNull(computedCoordinates[0].lat); + Assert.isNull(computedCoordinates[0].lon); + } + + public class OpenStreetMapHttpCalloutMockImpl implements HttpCalloutMock { + public HTTPResponse respond(HTTPRequest req) { + HttpResponse res = new HttpResponse(); + res.setHeader('Content-Type', 'application/json'); + res.setBody('[{"lat": ' + LATITUDE + ',"lon": ' + LONGITUDE + '}]'); + res.setStatusCode(200); + return res; + } + } + + public class OpenStreetMapHttpCalloutMockImplError implements HttpCalloutMock { + public HTTPResponse respond(HTTPRequest req) { + HttpResponse res = new HttpResponse(); + res.setHeader('Content-Type', 'application/json'); + res.setStatusCode(400); + return res; + } + } +} \ No newline at end of file diff --git a/force-app/main/default/classes/GeocodingServiceTest.cls-meta.xml b/force-app/main/default/classes/GeocodingServiceTest.cls-meta.xml new file mode 100644 index 0000000..651b172 --- /dev/null +++ b/force-app/main/default/classes/GeocodingServiceTest.cls-meta.xml @@ -0,0 +1,5 @@ + + + 61.0 + Active + diff --git a/force-app/main/default/classes/PagedResult.cls b/force-app/main/default/classes/PagedResult.cls new file mode 100644 index 0000000..8adf001 --- /dev/null +++ b/force-app/main/default/classes/PagedResult.cls @@ -0,0 +1,13 @@ +public with sharing class PagedResult { + @AuraEnabled + public Integer pageSize { get; set; } + + @AuraEnabled + public Integer pageNumber { get; set; } + + @AuraEnabled + public Integer totalItemCount { get; set; } + + @AuraEnabled + public Object[] records { get; set; } +} \ No newline at end of file diff --git a/force-app/main/default/classes/PagedResult.cls-meta.xml b/force-app/main/default/classes/PagedResult.cls-meta.xml new file mode 100644 index 0000000..651b172 --- /dev/null +++ b/force-app/main/default/classes/PagedResult.cls-meta.xml @@ -0,0 +1,5 @@ + + + 61.0 + Active + diff --git a/force-app/main/default/classes/PropertyController.cls b/force-app/main/default/classes/PropertyController.cls new file mode 100644 index 0000000..2292365 --- /dev/null +++ b/force-app/main/default/classes/PropertyController.cls @@ -0,0 +1,112 @@ +public with sharing class PropertyController { + private static final Decimal DEFAULT_MAX_PRICE = 9999999; + private static final Integer DEFAULT_PAGE_SIZE = 9; + + /** + * Endpoint that retrieves a paged and filtered list of properties + * @param searchKey String used for searching on property title, city and tags + * @param maxPrice Maximum price + * @param minBedrooms Minimum number of bedrooms + * @param minBathrooms Minimum number of bathrooms + * @param pageSize Number of properties per page + * @param pageNumber Page number + * @return PagedResult object holding the paged and filtered list of properties + */ + @AuraEnabled(cacheable=true scope='global') + public static PagedResult getPagedPropertyList( + String searchKey, + Decimal maxPrice, + Integer minBedrooms, + Integer minBathrooms, + Integer pageSize, + Integer pageNumber + ) { + // Normalize inputs + Decimal safeMaxPrice = maxPrice ?? DEFAULT_MAX_PRICE; + Integer safeMinBedrooms = minBedrooms ?? 0; + Integer safeMinBathrooms = minBathrooms ?? 0; + Integer safePageSize = pageSize ?? DEFAULT_PAGE_SIZE; + Integer safePageNumber = pageNumber ?? 1; + + String searchPattern = '%' + searchKey + '%'; + Integer offset = (safePageNumber - 1) * safePageSize; + + PagedResult result = new PagedResult(); + result.pageSize = safePageSize; + result.pageNumber = safePageNumber; + result.totalItemCount = [ + SELECT COUNT() + FROM Property__c + WHERE + (Name LIKE :searchPattern + OR City__c LIKE :searchPattern + OR Tags__c LIKE :searchPattern) + AND Price__c <= :safeMaxPrice + AND Beds__c >= :safeMinBedrooms + AND Baths__c >= :safeMinBathrooms + ]; + result.records = [ + SELECT + Id, + Name, + Address__c, + City__c, + State__c, + Description__c, + Price__c, + Baths__c, + Beds__c, + Thumbnail__c, + Location__Latitude__s, + Location__Longitude__s + FROM Property__c + WHERE + (Name LIKE :searchPattern + OR City__c LIKE :searchPattern + OR Tags__c LIKE :searchPattern) + AND Price__c <= :safeMaxPrice + AND Beds__c >= :safeMinBedrooms + AND Baths__c >= :safeMinBathrooms + WITH USER_MODE + ORDER BY Price__c + LIMIT :safePageSize + OFFSET :offset + ]; + return result; + } + + /** + * Endpoint that retrieves pictures associated with a property + * @param propertyId Property Id + * @return List of ContentVersion holding the pictures + */ + @AuraEnabled(cacheable=true scope='global') + public static List getPictures(Id propertyId) { + List links = [ + SELECT Id, LinkedEntityId, ContentDocument.Title + FROM ContentDocumentLink + WHERE + LinkedEntityId = :propertyId + AND ContentDocument.FileType IN ('PNG', 'JPG', 'GIF') + WITH USER_MODE + ]; + + if (links.isEmpty()) { + return null; + } + + Set contentIds = new Set(); + + for (ContentDocumentLink link : links) { + contentIds.add(link.ContentDocumentId); + } + + return [ + SELECT Id, Title + FROM ContentVersion + WHERE ContentDocumentId IN :contentIds AND IsLatest = TRUE + WITH USER_MODE + ORDER BY CreatedDate + ]; + } +} \ No newline at end of file diff --git a/force-app/main/default/classes/PropertyController.cls-meta.xml b/force-app/main/default/classes/PropertyController.cls-meta.xml new file mode 100644 index 0000000..651b172 --- /dev/null +++ b/force-app/main/default/classes/PropertyController.cls-meta.xml @@ -0,0 +1,5 @@ + + + 61.0 + Active + diff --git a/force-app/main/default/classes/SampleDataController.cls b/force-app/main/default/classes/SampleDataController.cls new file mode 100644 index 0000000..23b8b79 --- /dev/null +++ b/force-app/main/default/classes/SampleDataController.cls @@ -0,0 +1,63 @@ +public with sharing class SampleDataController { + @AuraEnabled + public static void importSampleData() { + delete [SELECT Id FROM Case]; + delete [SELECT Id FROM Property__c]; + delete [SELECT Id FROM Broker__c]; + delete [SELECT Id FROM Contact]; + + insertBrokers(); + insertProperties(); + insertContacts(); + } + + private static void insertBrokers() { + StaticResource brokersResource = [ + SELECT Id, Body + FROM StaticResource + WHERE Name = 'sample_data_brokers' + ]; + String brokersJSON = brokersResource.body.toString(); + List brokers = (List) JSON.deserialize( + brokersJSON, + List.class + ); + insert brokers; + } + + private static void insertProperties() { + StaticResource propertiesResource = [ + SELECT Id, Body + FROM StaticResource + WHERE Name = 'sample_data_properties' + ]; + String propertiesJSON = propertiesResource.body.toString(); + List properties = (List) JSON.deserialize( + propertiesJSON, + List.class + ); + randomizeDateListed(properties); + insert properties; + } + + private static void insertContacts() { + StaticResource contactsResource = [ + SELECT Id, Body + FROM StaticResource + WHERE Name = 'sample_data_contacts' + ]; + String contactsJSON = contactsResource.body.toString(); + List contacts = (List) JSON.deserialize( + contactsJSON, + List.class + ); + insert contacts; + } + + private static void randomizeDateListed(List properties) { + for (Property__c property : properties) { + property.Date_Listed__c = + System.today() - Integer.valueof((Math.random() * 90)); + } + } +} \ No newline at end of file diff --git a/force-app/main/default/classes/SampleDataController.cls-meta.xml b/force-app/main/default/classes/SampleDataController.cls-meta.xml new file mode 100644 index 0000000..651b172 --- /dev/null +++ b/force-app/main/default/classes/SampleDataController.cls-meta.xml @@ -0,0 +1,5 @@ + + + 61.0 + Active + diff --git a/force-app/main/default/classes/TestPropertyController.cls b/force-app/main/default/classes/TestPropertyController.cls new file mode 100644 index 0000000..f7e0062 --- /dev/null +++ b/force-app/main/default/classes/TestPropertyController.cls @@ -0,0 +1,121 @@ +@isTest +private class TestPropertyController { + private final static String MOCK_PICTURE_NAME = 'MockPictureName'; + + public static void createProperties(Integer amount) { + List properties = new List(); + for (Integer i = 0; i < amount; i++) { + properties.add( + new Property__c( + Name = 'Name ' + i, + Price__c = 20000, + Beds__c = 3, + Baths__c = 3 + ) + ); + } + insert properties; + } + + @isTest + static void testGetPagedPropertyList() { + Profile standardUserProfile = [ + SELECT Name, Id + FROM Profile + WHERE + UserType = 'Standard' + AND PermissionsPrivacyDataAccess = FALSE + AND PermissionsSubmitMacrosAllowed = TRUE + AND PermissionsMassInlineEdit = TRUE + LIMIT 1 + ]; + User testUser = new User( + Alias = 'standt', + Email = 'standarduser@testorg.com', + EmailEncodingKey = 'UTF-8', + LastName = 'Testing', + LanguageLocaleKey = 'en_US', + LocaleSidKey = 'en_US', + ProfileId = standardUserProfile.Id, + TimeZoneSidKey = 'America/Los_Angeles', + UserName = 'standarduser@dreamhouse-testorg.com' + ); + insert testUser; + PermissionSet ps = [ + SELECT Id + FROM PermissionSet + WHERE Name = 'dreamhouse' + ]; + insert new PermissionSetAssignment( + AssigneeId = testUser.Id, + PermissionSetId = ps.Id + ); + + // Insert test properties as admin + System.runAs(new User(Id = UserInfo.getUserId())) { + TestPropertyController.createProperties(5); + } + // Read properties as test user + System.runAs(testUser) { + Test.startTest(); + PagedResult result = PropertyController.getPagedPropertyList( + '', + 999999, + 0, + 0, + 10, + 1 + ); + Test.stopTest(); + Assert.areEqual(5, result.records.size()); + } + } + + @isTest + static void testGetPicturesNoResults() { + Property__c property = new Property__c(Name = 'Name'); + insert property; + + Test.startTest(); + List items = PropertyController.getPictures( + property.Id + ); + Test.stopTest(); + + Assert.isNull(items); + } + + @isTest + static void testGetPicturesWithResults() { + Property__c property = new Property__c(Name = 'Name'); + insert property; + + // Insert mock picture + ContentVersion picture = new Contentversion(); + picture.Title = MOCK_PICTURE_NAME; + picture.PathOnClient = 'picture.png'; + picture.Versiondata = EncodingUtil.base64Decode('MockValue'); + insert picture; + + // Link picture to property record + List documents = [ + SELECT Id, Title, LatestPublishedVersionId + FROM ContentDocument + LIMIT 1 + ]; + ContentDocumentLink link = new ContentDocumentLink(); + link.LinkedEntityId = property.Id; + link.ContentDocumentId = documents[0].Id; + link.shareType = 'V'; + insert link; + + Test.startTest(); + List items = PropertyController.getPictures( + property.Id + ); + Test.stopTest(); + + Assert.areEqual(1, items.size()); + Assert.areEqual(MOCK_PICTURE_NAME, items[0].Title); + } +} \ No newline at end of file diff --git a/force-app/main/default/classes/TestPropertyController.cls-meta.xml b/force-app/main/default/classes/TestPropertyController.cls-meta.xml new file mode 100644 index 0000000..651b172 --- /dev/null +++ b/force-app/main/default/classes/TestPropertyController.cls-meta.xml @@ -0,0 +1,5 @@ + + + 61.0 + Active + diff --git a/force-app/main/default/classes/TestSampleDataController.cls b/force-app/main/default/classes/TestSampleDataController.cls new file mode 100644 index 0000000..f30fd0b --- /dev/null +++ b/force-app/main/default/classes/TestSampleDataController.cls @@ -0,0 +1,17 @@ +@isTest +private class TestSampleDataController { + @isTest + static void importSampleData() { + Test.startTest(); + SampleDataController.importSampleData(); + Test.stopTest(); + + Integer propertyNumber = [SELECT COUNT() FROM Property__c]; + Integer brokerNumber = [SELECT COUNT() FROM Broker__c]; + Integer contactNumber = [SELECT COUNT() FROM Contact]; + + Assert.isTrue(propertyNumber > 0, 'Expected properties were created.'); + Assert.isTrue(brokerNumber > 0, 'Expected brokers were created.'); + Assert.isTrue(contactNumber > 0, 'Expected contacts were created.'); + } +} \ No newline at end of file diff --git a/force-app/main/default/classes/TestSampleDataController.cls-meta.xml b/force-app/main/default/classes/TestSampleDataController.cls-meta.xml new file mode 100644 index 0000000..651b172 --- /dev/null +++ b/force-app/main/default/classes/TestSampleDataController.cls-meta.xml @@ -0,0 +1,5 @@ + + + 61.0 + Active + diff --git a/force-app/main/default/contentassets/HUTTE_LOGOTYPE_MAIN_SYMBOL_ALPHA.asset b/force-app/main/default/contentassets/HUTTE_LOGOTYPE_MAIN_SYMBOL_ALPHA.asset new file mode 100644 index 0000000000000000000000000000000000000000..30bd6ab70c63ea7f379ec5b682c4d4061c150b3f GIT binary patch literal 47566 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 literal 0 HcmV?d00001 diff --git a/force-app/main/default/contentassets/HUTTE_LOGOTYPE_MAIN_SYMBOL_ALPHA.asset-meta.xml b/force-app/main/default/contentassets/HUTTE_LOGOTYPE_MAIN_SYMBOL_ALPHA.asset-meta.xml new file mode 100644 index 0000000..d310b15 --- /dev/null +++ b/force-app/main/default/contentassets/HUTTE_LOGOTYPE_MAIN_SYMBOL_ALPHA.asset-meta.xml @@ -0,0 +1,17 @@ + + + false + en_US + HUTTE_LOGOTYPE_MAIN_SYMBOL_ALPHA + + + VIEWER + + + + + 1 + HUTTE LOGOTYPE_MAIN SYMBOL ALPHA.png + + + diff --git a/force-app/main/default/contentassets/dreamhouselogosquare.asset b/force-app/main/default/contentassets/dreamhouselogosquare.asset new file mode 100644 index 0000000000000000000000000000000000000000..4fef8da4dbb527cb85f0d698a8d191a8862d77db GIT binary patch literal 23382 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 H=N|h%cJ=&d literal 0 HcmV?d00001 diff --git a/force-app/main/default/contentassets/dreamhouselogosquare.asset-meta.xml b/force-app/main/default/contentassets/dreamhouselogosquare.asset-meta.xml new file mode 100644 index 0000000..b79ecb3 --- /dev/null +++ b/force-app/main/default/contentassets/dreamhouselogosquare.asset-meta.xml @@ -0,0 +1,17 @@ + + + false + en_US + dreamhouselogosquare + + + VIEWER + + + + + 1 + dreamhouse-logo-square.png + + + diff --git a/force-app/main/default/cspTrustedSites/openStreetMap.cspTrustedSite-meta.xml b/force-app/main/default/cspTrustedSites/openStreetMap.cspTrustedSite-meta.xml new file mode 100644 index 0000000..747f89d --- /dev/null +++ b/force-app/main/default/cspTrustedSites/openStreetMap.cspTrustedSite-meta.xml @@ -0,0 +1,15 @@ + + + false + false + LEX + OpenStreetMap tiles + https://tile.openstreetmap.org + true + false + false + false + true + false + false + diff --git a/force-app/main/default/cspTrustedSites/s3_us_west_2_amazonaws_com.cspTrustedSite-meta.xml b/force-app/main/default/cspTrustedSites/s3_us_west_2_amazonaws_com.cspTrustedSite-meta.xml new file mode 100644 index 0000000..632db8d --- /dev/null +++ b/force-app/main/default/cspTrustedSites/s3_us_west_2_amazonaws_com.cspTrustedSite-meta.xml @@ -0,0 +1,15 @@ + + + false + false + LEX + Amazon S3 hosted sample app media + https://s3-us-west-2.amazonaws.com + true + false + false + false + true + false + false + diff --git a/force-app/main/default/flexipages/Broker_Record_Page.flexipage-meta.xml b/force-app/main/default/flexipages/Broker_Record_Page.flexipage-meta.xml new file mode 100644 index 0000000..6607679 --- /dev/null +++ b/force-app/main/default/flexipages/Broker_Record_Page.flexipage-meta.xml @@ -0,0 +1,378 @@ + + + + + + + collapsed + false + + + enableActionsConfiguration + false + + + hideChatterActions + false + + + numVisibleActions + 3 + + force:highlightsPanel + force_highlightsPanel + + + Replace + header + Region + + + + + + relatedListComponentOverride + NONE + + + rowsToDisplay + 10 + + + showActionBar + true + + force:relatedListContainer + force_relatedListContainer + + + Replace + relatedTabContent + Facet + + + + + + uiBehavior + readonly + + Record.Picture_IMG__c + RecordPicture_IMG__cField + + + + + + uiBehavior + none + + Record.Picture__c + RecordPicture__cField + + + Facet-1bc3dd0f-6743-478f-8d51-2bb48e689fb5 + Facet + + + + + + body + Facet-1bc3dd0f-6743-478f-8d51-2bb48e689fb5 + + flexipage:column + flexipage_column + + + Facet-410fbc19-10c0-4677-8608-2cb7d8d102b3 + Facet + + + + + + uiBehavior + required + + Record.Name + RecordNameField + + + + + + uiBehavior + none + + Record.Title__c + RecordTitle__cField + + + + + + uiBehavior + none + + Record.Email__c + RecordEmail__cField + + + Facet-4885c180-b6bf-40af-bc91-3d83e2f7627b + Facet + + + + + + uiBehavior + none + + Record.Phone__c + RecordPhone__cField + + + + + + uiBehavior + none + + Record.Mobile_Phone__c + RecordMobile_Phone__cField + + + + + + uiBehavior + none + + Record.OwnerId + RecordOwnerIdField + + + Facet-1fcbd98c-c9c7-4a47-ad59-f4bfcd05d5a2 + Facet + + + + + + body + Facet-4885c180-b6bf-40af-bc91-3d83e2f7627b + + flexipage:column + flexipage_column2 + + + + + + body + Facet-1fcbd98c-c9c7-4a47-ad59-f4bfcd05d5a2 + + flexipage:column + flexipage_column3 + + + Facet-7da398a8-59d5-4a99-a9ea-dfac94d7055f + Facet + + + + + + uiBehavior + readonly + + Record.CreatedById + RecordCreatedByIdField + + + Facet-9e941d2d-a3ed-4186-99e4-40cfe151b0fa + Facet + + + + + + uiBehavior + readonly + + Record.LastModifiedById + RecordLastModifiedByIdField + + + Facet-f7173fe8-e18a-4fbd-8898-53927906768d + Facet + + + + + + body + Facet-9e941d2d-a3ed-4186-99e4-40cfe151b0fa + + flexipage:column + flexipage_column4 + + + + + + body + Facet-f7173fe8-e18a-4fbd-8898-53927906768d + + flexipage:column + flexipage_column5 + + + Facet-4fdd7013-0316-404e-a707-2618d3582ae5 + Facet + + + + + + columns + Facet-410fbc19-10c0-4677-8608-2cb7d8d102b3 + + + label + Picture + + flexipage:fieldSection + flexipage_fieldSection + + + + + + columns + Facet-7da398a8-59d5-4a99-a9ea-dfac94d7055f + + + label + Information + + flexipage:fieldSection + flexipage_fieldSection2 + + + + + + columns + Facet-4fdd7013-0316-404e-a707-2618d3582ae5 + + + label + System Information + + flexipage:fieldSection + flexipage_fieldSection3 + + + + + force:recordDetailPanelMobile + force_recordDetailPanelMobile + + + Replace + detailTabContent + Facet + + + + + + body + relatedTabContent + + + title + Standard.Tab.relatedLists + + flexipage:tab + relatedListsTab + + + + + + active + true + + + body + detailTabContent + + + title + Standard.Tab.detail + + flexipage:tab + detailTab + + + Replace + maintabs + Facet + + + + + + tabs + maintabs + + flexipage:tabset + flexipage_tabset + + + Replace + main + Region + + + + + + parentFieldApiName + Broker__c.Id + + + relatedListApiName + Properties__r + + + relatedListComponentOverride + NONE + + + rowsToDisplay + 10 + + + showActionBar + true + + force:relatedListSingleContainer + force_relatedListSingleContainer + + + Replace + sidebar + Region + + Broker Record Page + flexipage__default_rec_L + Broker__c + + RecordPage + diff --git a/force-app/main/default/flexipages/Property_Explorer.flexipage-meta.xml b/force-app/main/default/flexipages/Property_Explorer.flexipage-meta.xml new file mode 100644 index 0000000..019fa6f --- /dev/null +++ b/force-app/main/default/flexipages/Property_Explorer.flexipage-meta.xml @@ -0,0 +1,58 @@ + + + + + + propertyFilter + propertyFilter + + + + + + flowLayout + oneColumn + + + flowName + Create_property + + flowruntime:interview + flowruntime_interview + + + left + Region + + + + + propertyTileList + propertyTileList + + + center + Region + + + + + propertySummary + propertySummary + + + + + propertyMap + propertyMap + + + right + Region + + Property Explorer + + AppPage + diff --git a/force-app/main/default/flexipages/Property_Finder.flexipage-meta.xml b/force-app/main/default/flexipages/Property_Finder.flexipage-meta.xml new file mode 100644 index 0000000..c6e7031 --- /dev/null +++ b/force-app/main/default/flexipages/Property_Finder.flexipage-meta.xml @@ -0,0 +1,50 @@ + + + + + + barcodeScanner + c_barcodeScanner + + + + + propertyFilter + propertyFilter + + + left + Region + + + + + propertyListMap + c_propertyListMap + + + center + Region + + + + + propertySummary + propertySummary + + + + + daysOnMarket + daysOnMarket + + + right + Region + + Property Finder + + AppPage + diff --git a/force-app/main/default/flexipages/Property_Record_Page.flexipage-meta.xml b/force-app/main/default/flexipages/Property_Record_Page.flexipage-meta.xml new file mode 100644 index 0000000..9bca1a2 --- /dev/null +++ b/force-app/main/default/flexipages/Property_Record_Page.flexipage-meta.xml @@ -0,0 +1,552 @@ + + + + + + + collapsed + false + + + enableActionsConfiguration + false + + + hideChatterActions + false + + + numVisibleActions + 3 + + force:highlightsPanel + force_highlightsPanel + + + Replace + header + Region + + + + + + relatedListComponentOverride + NONE + + force:relatedListContainer + force_relatedListContainer + + + Replace + relatedTabContent + Facet + + + + + + uiBehavior + required + + Record.Name + RecordNameField + + + + + + uiBehavior + none + + Record.Address__c + RecordAddress__cField + + + + + + uiBehavior + none + + Record.State__c + RecordState__cField + + + + + + uiBehavior + none + + Record.Zip__c + RecordZip__cField + + + + + + uiBehavior + none + + Record.Tags__c + RecordTags__cField + + + + + + uiBehavior + none + + Record.Status__c + RecordStatus__cField + + + + + + uiBehavior + none + + Record.OwnerId + RecordOwnerIdField + + + Facet-eb9c4d7e-6868-43e8-9851-85aacdd3a54d + Facet + + + + + + uiBehavior + none + + Record.Picture_IMG__c + RecordPicture_IMG_cField + + + Facet-41d5d7e8-b344-4110-9175-150a259f72a8 + Facet + + + + + + body + Facet-eb9c4d7e-6868-43e8-9851-85aacdd3a54d + + flexipage:column + flexipage_column + + + + + + body + Facet-41d5d7e8-b344-4110-9175-150a259f72a8 + + flexipage:column + flexipage_column2 + + + Facet-66400b5a-c4b2-472c-af56-e7f4f40b3969 + Facet + + + + + + uiBehavior + none + + Record.Description__c + RecordDescription__cField + + + Facet-3d2d92e6-96c0-4649-a0b0-d02f5a08f655 + Facet + + + + + + body + Facet-3d2d92e6-96c0-4649-a0b0-d02f5a08f655 + + flexipage:column + flexipage_column3 + + + Facet-7e923dfb-c368-4633-ae9c-3eb3f51a73bb + Facet + + + + + + uiBehavior + readonly + + Record.CreatedById + RecordCreatedByIdField + + + Facet-89988119-afc3-4937-8a69-76d39cb3a74a + Facet + + + + + + uiBehavior + readonly + + Record.LastModifiedById + RecordLastModifiedByIdField + + + Facet-2d0a01d5-75cd-48da-b598-1e36cc2fa406 + Facet + + + + + + body + Facet-89988119-afc3-4937-8a69-76d39cb3a74a + + flexipage:column + flexipage_column4 + + + + + + body + Facet-2d0a01d5-75cd-48da-b598-1e36cc2fa406 + + flexipage:column + flexipage_column5 + + + Facet-00b780e0-4e42-4a35-854d-bec7c63f2545 + Facet + + + + + + columns + Facet-66400b5a-c4b2-472c-af56-e7f4f40b3969 + + + horizontalAlignment + false + + + label + Information + + flexipage:fieldSection + flexipage_fieldSection + + + + + + columns + Facet-7e923dfb-c368-4633-ae9c-3eb3f51a73bb + + + horizontalAlignment + false + + + label + Description + + flexipage:fieldSection + flexipage_fieldSection2 + + + + + + columns + Facet-00b780e0-4e42-4a35-854d-bec7c63f2545 + + + horizontalAlignment + false + + + label + System Information + + flexipage:fieldSection + flexipage_fieldSection3 + + + + + force:recordDetailPanelMobile + force_recordDetailPanelMobile + + + Replace + detailTabContent + Facet + + + + + + uiBehavior + none + + Record.Date_Contracted__c + RecordDate_Contracted__cField + + + + + + uiBehavior + none + + Record.Date_Pre_Market__c + RecordDate_Pre_Market__cField + + + + + + uiBehavior + none + + Record.Date_Closed__c + RecordDate_Closed__cField + + + Facet-c5e2ef33-3e0f-472c-a3bb-22376d3962e9 + Facet + + + + + + uiBehavior + none + + Record.Date_Listed__c + RecordDate_Listed__cField + + + + + + uiBehavior + none + + Record.Date_Agreement__c + RecordDate_Agreement__cField + + + Facet-1ca35247-9088-453b-a163-ef03309a958c + Facet + + + + + + body + Facet-c5e2ef33-3e0f-472c-a3bb-22376d3962e9 + + flexipage:column + flexipage_column6 + + + + + + body + Facet-1ca35247-9088-453b-a163-ef03309a958c + + flexipage:column + flexipage_column7 + + + Facet-ad40adb5-82bf-4e08-836c-f48698589d81 + Facet + + + + + + columns + Facet-ad40adb5-82bf-4e08-836c-f48698589d81 + + + horizontalAlignment + false + + + label + Dates + + flexipage:fieldSection + flexipage_fieldSection4 + + + Facet-1e191467-3189-4ef6-9dfa-5dd515d8a8f0 + Facet + + + + + brokerCard + c_brokerCard + + + Facet-be553f16-e92a-4849-9817-aaa81df23b96 + Facet + + + + + + body + relatedTabContent + + + title + Standard.Tab.relatedLists + + flexipage:tab + relatedListsTab + + + + + + active + true + + + body + detailTabContent + + + title + Standard.Tab.detail + + flexipage:tab + detailTab + + + + + + body + Facet-1e191467-3189-4ef6-9dfa-5dd515d8a8f0 + + + title + Dates + + flexipage:tab + customTab + + + + + + body + Facet-be553f16-e92a-4849-9817-aaa81df23b96 + + + title + Broker + + flexipage:tab + flexipage_tab + + + Replace + maintabs + Facet + + + + + + tabs + maintabs + + flexipage:tabset + flexipage_tabset + + + Replace + main + Region + + + + + brokerCard + c_brokerCard2 + + + + + daysOnMarket + daysOnMarket + + + {!Record.Days_On_Market__c} + GT + 0 + + + + + + + propertyMap + propertyMap + + + {!Record.Location__Latitude__s} + GT + 0 + + + + + + + propertyLocation + c_propertyLocation + + + + + propertyCarousel + propertyCarousel + + + Replace + sidebar + Region + + Property Record Page + flexipage__default_rec_L + Property__c + + RecordPage + diff --git a/force-app/main/default/flexipages/Settings.flexipage-meta.xml b/force-app/main/default/flexipages/Settings.flexipage-meta.xml new file mode 100644 index 0000000..249c99b --- /dev/null +++ b/force-app/main/default/flexipages/Settings.flexipage-meta.xml @@ -0,0 +1,26 @@ + + + + + + sampleDataImporter + sampleDataImporter + + + region1 + Region + + + region2 + Region + + + region3 + Region + + Settings + + AppPage + diff --git a/force-app/main/default/flows/Create_property.flow-meta.xml b/force-app/main/default/flows/Create_property.flow-meta.xml new file mode 100644 index 0000000..84037e0 --- /dev/null +++ b/force-app/main/default/flows/Create_property.flow-meta.xml @@ -0,0 +1,619 @@ + + + + geocode_address + + 666 + 350 + GeocodingService + apex + + property_details + + + Error5 + + CurrentTransaction + + city + + property_address.city + + + + country + + property_address.country + + + + postalcode + + property_address.postalCode + + + + state + + property_address.province + + + + street + + property_address.street + + + GeocodingService + true + 1 + + 51.0 + + If_content_document_found + + 666 + 890 + + navigate_to_record_detail + + Default Outcome + + Content_Document_Link_found + and + + get_main_content_document + IsNull + + false + + + + get_main_content_version + + + + + + if_content_version_found + + 314 + 1106 + + navigate_to_record_detail + + Default Outcome + + picture_found + and + + get_main_content_version + IsNull + + false + + + + set_main_picture + + + + + This flow helps agents creating new properties in just a few clicks. It calculates the geocoded address calling out to a 3rd party service. + Default + + Main picture URL that we'll use as thumbnail + main_picture_url + String + "/sfc/servlet.shepherd/version/download/" + {!get_main_content_version.Id} + + Create Property {!$Flow.CurrentDateTime} + + + BuilderType + + LightningFlowBuilder + + + + CanvasMode + + AUTO_LAYOUT_CANVAS + + + + OriginBuilderType + + LightningFlowBuilder + + + Flow + + create_property + + 666 + 566 + + upload_picture + + + error_creating_records + + + Address__c + + property_address.street + + + + Baths__c + + number_of_baths + + + + Beds__c + + number_of_beds + + + + Broker__c + + property_broker.recordId + + + + City__c + + property_address.city + + + + Date_Listed__c + + $Flow.CurrentDate + + + + Description__c + + property_description + + + + Location__Latitude__s + + geocode_address.lat + + + + Location__Longitude__s + + geocode_address.lon + + + + Name + + property_name + + + + Price__c + + property_price + + + + State__c + + property_address.province + + + + Status__c + + Available + + + + Tags__c + + property_tags + + + + Zip__c + + property_address.postalCode + + + Property__c + true + + + Retrieve just one of the pictures to be the main one + get_main_content_document + + 666 + 782 + false + + If_content_document_found + + + Error2 + + and + + LinkedEntityId + EqualTo + + create_property + + + true + ContentDocumentLink + true + + + get_main_content_version + + 314 + 998 + false + + if_content_version_found + + + Error3 + + and + + ContentDocumentId + EqualTo + + get_main_content_document.ContentDocumentId + + + + IsLatest + EqualTo + + true + + + true + ContentVersion + true + + + set_main_picture + + 50 + 1214 + + navigate_to_record_detail + + + Error4 + + and + + Id + EqualTo + + create_property + + + + Picture__c + + main_picture_url + + + + Thumbnail__c + + main_picture_url + + + Property__c + + + address + + 666 + 242 + true + true + true + + geocode_address + + + property_address + flowruntime:address + ComponentInstance + UseStoredValues + true + true + + true + true + + + Error2 + + 1194 + 890 + true + true + true + + error2_text + <p>Unknown error retrieving uploaded picture.</p> + DisplayText + + true + true + + + Error3 + + 754 + 1106 + true + true + true + + error3_text + <p><span style="background-color: rgb(255, 255, 255); color: rgb(62, 62, 60);">Unknown error retrieving uploaded picture.</span></p> + DisplayText + + true + true + + + Error4 + + 314 + 1322 + false + true + true + + error4_text + <p><span style="background-color: rgb(255, 255, 255); color: rgb(62, 62, 60);">Unknown error setting picture as Property thumbnail.</span></p> + DisplayText + + true + true + + + Error5 + + 1722 + 458 + true + true + true + + error5_text + <p>Error retrieving geocoded address.</p> + DisplayText + + true + true + + + error_creating_records + + 1458 + 674 + false + true + true + + error + <p>Error creating records. Try again.</p> + DisplayText + + true + true + + + navigate_to_record_detail + + 666 + 1730 + false + true + true + + navigate_to_record_lwc + Hutte:navigateToRecord + ComponentInstance + + recordId + + create_property + + + UseStoredValues + true + true + + true + true + + + new_property + + 666 + 134 + true + true + true + + address + + + property_name + String + Property Name + InputField + UseStoredValues + true + + + property_description + String + Description + InputField + UseStoredValues + false + + + property_broker + flowruntime:lookup + ComponentInstance + + fieldApiName + + Hutte__Broker__c + + + + label + + Broker + + + + objectApiName + + Hutte__Property__c + + + UseStoredValues + true + true + + + property_price + Currency + + 100000.0 + + Price + InputField + UseStoredValues + true + 0 + + true + true + + + property_details + + 666 + 458 + true + true + true + + create_property + + + number_of_beds + Number + + 4.0 + + Number of Bedrooms + InputField + UseStoredValues + false + 0 + + + number_of_baths + Number + + 2.0 + + Number of Bathrooms + InputField + UseStoredValues + false + 0 + + + property_tags + String + Tags + InputField + UseStoredValues + false + + true + true + + + upload_picture + + 666 + 674 + false + true + true + + get_main_content_document + + + property_picture + forceContent:fileUpload + ComponentInstance + + label + + Upload Picture + + + + accept + + .jpg,.png,.gif + + + + recordId + + create_property + + + + multiple + + true + + + UseStoredValues + true + true + + true + true + + + 540 + 0 + + new_property + + + Active + diff --git a/force-app/main/default/lwc/.eslintrc.json b/force-app/main/default/lwc/.eslintrc.json new file mode 100644 index 0000000..0fc06c0 --- /dev/null +++ b/force-app/main/default/lwc/.eslintrc.json @@ -0,0 +1,14 @@ +{ + "extends": ["@salesforce/eslint-config-lwc/recommended"], + "overrides": [ + { + "files": ["*.test.js"], + "rules": { + "@lwc/lwc/no-unexpected-wire-adapter-usages": "off" + }, + "env": { + "node": true + } + } + ] +} diff --git a/force-app/main/default/lwc/barcodeScanner/__tests__/barcodeScanner.test.js b/force-app/main/default/lwc/barcodeScanner/__tests__/barcodeScanner.test.js new file mode 100644 index 0000000..f527601 --- /dev/null +++ b/force-app/main/default/lwc/barcodeScanner/__tests__/barcodeScanner.test.js @@ -0,0 +1,183 @@ +import { createElement } from 'lwc'; +import { getNavigateCalledWith } from 'lightning/navigation'; +import BarcodeScanner from 'c/barcodeScanner'; + +// Mock various barcode functionality from mobileCapabilites.js +import { + resetBarcodeScannerStubs, + setBarcodeScannerAvailable, + setUserCanceledScan, + setBarcodeScanError +} from 'lightning/mobileCapabilities'; + +// Enable spying on toast event data +import { ShowToastEventName } from 'lightning/platformShowToastEvent'; + +describe('c-barcode-scanner-example', () => { + afterEach(() => { + // Reset the JSDOM instance shared across test cases in a single file + while (document.body.firstChild) { + document.body.removeChild(document.body.firstChild); + } + + // Prevent data saved on mocks from leaking between tests + jest.clearAllMocks(); + + // Reset stubs + resetBarcodeScannerStubs(); + }); + + // Helper function to wait until the microtask queue is empty. + // Used when having to wait for asynchronous/DOM updates. + async function flushPromises() { + return Promise.resolve(); + } + + it('directs the user to the mobile app when Barcode Scanner is unavailable', async () => { + // Create initial BarcodeScanner element and attach to virtual DOM + const elementBarcodeScanner = createElement( + 'c-barcode-scanner-example', + { is: BarcodeScanner } + ); + document.body.appendChild(elementBarcodeScanner); + + // Mount `Scan QR Code` button and trigger scan of property record ID + const elementScannerDirections = + elementBarcodeScanner.shadowRoot.querySelector( + '[data-test="scanner-directions"]' + ); + + expect(elementScannerDirections).not.toBeNull(); + }); + + it('shows the `Scan QR Code` button when BarcodeScanner is available', async () => { + // Create initial BarcodeScanner element and attach to virtual DOM + const elementBarcodeScanner = createElement( + 'c-barcode-scanner-example', + { is: BarcodeScanner } + ); + // Stub barcodeScanner as available + setBarcodeScannerAvailable(); + + document.body.appendChild(elementBarcodeScanner); + + // Mount `Scan QR Code` button and trigger scan of property record ID + const elementScanQRCodeButton = + elementBarcodeScanner.shadowRoot.querySelector('lightning-button'); + + expect(elementScanQRCodeButton).not.toBeNull(); + }); + + it('navigates to the expected record view when a QR code is correctly scanned', async () => { + // Property record values to compare component output against + const NAV_TYPE = 'standard__recordPage'; + const NAV_ACTION_NAME = 'view'; + const NAV_RECORD_ID = '0031700000pJRRWAA4'; + + // Stub barcodeScanner availability to true + setBarcodeScannerAvailable(); + + // Create initial BarcodeScanner element and attach to virtual DOM + const elementBarcodeScanner = createElement( + 'c-barcode-scanner-example', + { is: BarcodeScanner } + ); + document.body.appendChild(elementBarcodeScanner); + + // Mount `Scan QR Code` button and trigger scan of property record ID + const elementScanQRCodeButton = + elementBarcodeScanner.shadowRoot.querySelector('lightning-button'); + elementScanQRCodeButton.click(); + + // Wait for async scan function to settle + await flushPromises(); + + // Get data the NavigationMixin was called with + const { pageReference } = getNavigateCalledWith(); + + // Confirm redirection to expected property record + expect(pageReference.type).toBe(NAV_TYPE); + expect(pageReference.attributes.actionName).toBe(NAV_ACTION_NAME); + expect(pageReference.attributes.recordId).toBe(NAV_RECORD_ID); + }); + + it('triggers an error toast notification when the user cancels the scan', async () => { + // Stub barcodeScanner as available + setBarcodeScannerAvailable(); + + // Mock user canceling the scan + setUserCanceledScan(); + + // Mock handler for toast event + const toastEventSpy = jest.fn(); + + // Create initial BarcodeScanner element and attach to virtual DOM + const elementBarcodeScanner = createElement( + 'c-barcode-scanner-example', + { is: BarcodeScanner } + ); + document.body.appendChild(elementBarcodeScanner); + + // Add toast event listener to component + elementBarcodeScanner.addEventListener( + ShowToastEventName, + toastEventSpy + ); + + // Mount `Scan QR Code` button and trigger scan of property record ID + const elementScanQRCodeButton = + elementBarcodeScanner.shadowRoot.querySelector('lightning-button'); + elementScanQRCodeButton.click(); + + // Wait for element to mount + await flushPromises(); + + // Check that cancelation toast was triggered + + // Check if toast event has been fired + expect(toastEventSpy).toHaveBeenCalled(); + expect(toastEventSpy.mock.calls[0][0].detail.title).toBe( + 'Scanning Canceled' + ); + }); + + it('shows an error toast when there was a problem with the scan', async () => { + // Stub barcodeScanner as available + setBarcodeScannerAvailable(); + + // Mock scan erroring out + setBarcodeScanError(); + + // Mock handler for toast event + const toastEventSpy = jest.fn(); + + // Create initial BarcodeScanner element and attach to virtual DOM + const elementBarcodeScanner = createElement( + 'c-barcode-scanner-example', + { + is: BarcodeScanner + } + ); + document.body.appendChild(elementBarcodeScanner); + + // Add toast event listener to component + elementBarcodeScanner.addEventListener( + ShowToastEventName, + toastEventSpy + ); + + // Mount `Scan QR Code` button and trigger scan of property record ID + const elementScanQRCodeButton = + elementBarcodeScanner.shadowRoot.querySelector('lightning-button'); + elementScanQRCodeButton.click(); + + // Wait for element to mount + await flushPromises(); + + // Check that generic BarcodeScanner toast was triggered + expect(toastEventSpy).toHaveBeenCalled(); + expect(toastEventSpy.mock.calls[0][0].detail.title).toBe( + 'Barcode Scanner Error' + ); + }); +}); diff --git a/force-app/main/default/lwc/barcodeScanner/barcodeScanner.html b/force-app/main/default/lwc/barcodeScanner/barcodeScanner.html new file mode 100644 index 0000000..ce1f7e4 --- /dev/null +++ b/force-app/main/default/lwc/barcodeScanner/barcodeScanner.html @@ -0,0 +1,35 @@ + \ No newline at end of file diff --git a/force-app/main/default/lwc/barcodeScanner/barcodeScanner.js b/force-app/main/default/lwc/barcodeScanner/barcodeScanner.js new file mode 100644 index 0000000..bf7c0be --- /dev/null +++ b/force-app/main/default/lwc/barcodeScanner/barcodeScanner.js @@ -0,0 +1,80 @@ +import { LightningElement } from 'lwc'; +import { NavigationMixin } from 'lightning/navigation'; +import { ShowToastEvent } from 'lightning/platformShowToastEvent'; +import { getBarcodeScanner } from 'lightning/mobileCapabilities'; + +export default class BarcodeScanner extends NavigationMixin(LightningElement) { + myScanner; + scanButtonEnabled = false; + scannedQrCode = ''; + + // When the component is initialized, determine whether to enable the Scan button + connectedCallback() { + this.myScanner = getBarcodeScanner(); + if (this.myScanner?.isAvailable()) { + this.scanButtonEnabled = true; + } + } + + async handleBeginScanClick() { + // Reset scannedQrCode to empty string before starting a new scan + this.scannedQrCode = ''; + + // Make sure BarcodeScanner is available before trying to use it + // Scan QR Code button also disabled when scanner unavailable + if (this.myScanner?.isAvailable()) { + const scanningOptions = { + barcodeTypes: [this.myScanner.barcodeTypes.QR], + instructionText: 'Scan a QR Code', + successText: 'Scanning complete.' + }; + + // Try starting the scanning process, then using the result to navigate to a property record + try { + const captureResult = await this.myScanner.beginCapture(scanningOptions); + + // Extract QR code data + this.scannedQrCode = captureResult.value; + + // Navigate to the records page of the property with extracted ID + this[NavigationMixin.Navigate]({ + type: 'standard__recordPage', + attributes: { + recordId: this.scannedQrCode, + objectApiName: 'Hutte__Property__c', + actionName: 'view' + } + }); + } catch (error) { + // There was an error while scanning + // We chose to handle errors with toasts to stay in line with the mobile experience + // The user canceled the scan + if (error.code === 'userDismissedScanner') { + this.dispatchEvent( + new ShowToastEvent({ + title: 'Scanning Canceled', + message: 'Scanning session canceled.', + mode: 'sticky' + }) + ); + } + + // There was some other kind of error + else { + // Inform the user we ran into something unexpected + this.dispatchEvent( + new ShowToastEvent({ + title: 'Barcode Scanner Error', + message: 'There was a problem scanning the QR code: ' + error.message, + variant: 'error', + mode: 'sticky' + }) + ); + } + } finally { + // Close capture process regardless of whether we completed successfully or had an error + this.myScanner.endCapture(); + } + } + } +} \ No newline at end of file diff --git a/force-app/main/default/lwc/barcodeScanner/barcodeScanner.js-meta.xml b/force-app/main/default/lwc/barcodeScanner/barcodeScanner.js-meta.xml new file mode 100644 index 0000000..399a37a --- /dev/null +++ b/force-app/main/default/lwc/barcodeScanner/barcodeScanner.js-meta.xml @@ -0,0 +1,17 @@ + + + 61.0 + true + Barcode Scanner + + lightning__AppPage + + + + + + + + + + \ No newline at end of file diff --git a/force-app/main/default/lwc/brokerCard/__tests__/brokerCard.test.js b/force-app/main/default/lwc/brokerCard/__tests__/brokerCard.test.js new file mode 100644 index 0000000..527b6e5 --- /dev/null +++ b/force-app/main/default/lwc/brokerCard/__tests__/brokerCard.test.js @@ -0,0 +1,181 @@ +import { createElement } from 'lwc'; +import BrokerCard from 'c/brokerCard'; +import { getNavigateCalledWith } from 'lightning/navigation'; +import { getRecord, getFieldValue } from 'lightning/uiRecordApi'; + +// Mock realistic data +const mockGetPropertyRecord = require('./data/getPropertyRecord.json'); + +const BROKER_ID = 'a003h000003xlBiAAI'; + +const BROKER_FIELDS_INPUT = [ + { + fieldApiName: 'Name', + objectApiName: 'Broker__c' + }, + { + fieldApiName: 'Phone__c', + objectApiName: 'Broker__c' + }, + { + fieldApiName: 'Mobile_Phone__c', + objectApiName: 'Broker__c' + }, + { + fieldApiName: 'Email__c', + objectApiName: 'Broker__c' + } +]; + +describe('c-broker-card', () => { + afterEach(() => { + // The jsdom instance is shared across test cases in a single file so reset the DOM + while (document.body.firstChild) { + document.body.removeChild(document.body.firstChild); + } + + // Prevent data saved on mocks from leaking between tests + jest.clearAllMocks(); + }); + + // Helper function to wait until the microtask queue is empty. This is needed for promise + // timing. + async function flushPromises() { + return Promise.resolve(); + } + + describe('broker record form', () => { + it('gets property data from wire service', async () => { + // Create element + const element = createElement('c-broker-card', { + is: BrokerCard + }); + document.body.appendChild(element); + + // Emit data from @wire + getRecord.emit(mockGetPropertyRecord); + + // Wait for any asynchronous DOM updates + await flushPromises(); + + const propertyEl = element.shadowRoot.querySelector( + 'lightning-record-form' + ); + expect(getFieldValue).toHaveBeenCalled(); + expect(propertyEl.recordId).toBe(BROKER_ID); + }); + + it('renders lightning-record-form with given input values', async () => { + // Create element + const element = createElement('c-broker-card', { + is: BrokerCard + }); + document.body.appendChild(element); + + // Emit data from @wire + getRecord.emit(mockGetPropertyRecord); + + // Wait for any asynchronous DOM updates + await flushPromises(); + + const propertyEl = element.shadowRoot.querySelector( + 'lightning-record-form' + ); + expect(propertyEl.fields).toEqual(BROKER_FIELDS_INPUT); + expect(propertyEl.recordId).toBe(BROKER_ID); + }); + }); + + describe('navigate to broker record', () => { + it('navigates to record view', async () => { + // Nav param values to test later + const NAV_TYPE = 'standard__recordPage'; + const NAV_OBJECT_API_NAME = 'Property__c'; + const NAV_ACTION_NAME = 'view'; + const NAV_RECORD_ID = BROKER_ID; + + // Create initial lwc element and attach to virtual DOM + const element = createElement('c-broker-card', { + is: BrokerCard + }); + document.body.appendChild(element); + + // Simulate the data sent over wire adapter to hydrate the wired property + getRecord.emit(mockGetPropertyRecord); + + // Wait for any asynchronous DOM updates + await flushPromises(); + + // Get handle to view button and fire click event + const buttonEl = element.shadowRoot.querySelector( + 'lightning-button-icon' + ); + buttonEl.click(); + + const { pageReference } = getNavigateCalledWith(); + // Verify component called with correct event type and params + expect(pageReference.type).toBe(NAV_TYPE); + expect(pageReference.attributes.objectApiName).toBe( + NAV_OBJECT_API_NAME + ); + expect(pageReference.attributes.actionName).toBe(NAV_ACTION_NAME); + expect(pageReference.attributes.recordId).toBe(NAV_RECORD_ID); + }); + }); + + describe('error panel', () => { + it('renders error if data is not retrieved successfully', async () => { + const WIRE_ERROR = 'Something bad happened'; + + // Create element and attach to virtual DOM + const element = createElement('c-broker-card', { + is: BrokerCard + }); + document.body.appendChild(element); + + getRecord.error(WIRE_ERROR); + + // Wait for any asynchronous DOM updates + await flushPromises(); + + const errorPanelEl = + element.shadowRoot.querySelector('c-error-panel'); + expect(errorPanelEl).not.toBeNull(); + expect(errorPanelEl.errors.body).toBe(WIRE_ERROR); + expect(errorPanelEl.friendlyMessage).toBe('Error retrieving data'); + }); + }); + + it('is accessible when property returned', async () => { + const element = createElement('c-broker-card', { + is: BrokerCard + }); + + document.body.appendChild(element); + + // Emit data from @wire + getRecord.emit(mockGetPropertyRecord); + + // Wait for any asynchronous DOM updates + await flushPromises(); + + await expect(element).toBeAccessible(); + }); + + it('is accessible when error returned', async () => { + const WIRE_ERROR = 'Something bad happened'; + + // Create element and attach to virtual DOM + const element = createElement('c-broker-card', { + is: BrokerCard + }); + document.body.appendChild(element); + + getRecord.error(WIRE_ERROR); + + // Wait for any asynchronous DOM updates + await flushPromises(); + + await expect(element).toBeAccessible(); + }); +}); diff --git a/force-app/main/default/lwc/brokerCard/__tests__/data/getPropertyRecord.json b/force-app/main/default/lwc/brokerCard/__tests__/data/getPropertyRecord.json new file mode 100644 index 0000000..31c18bb --- /dev/null +++ b/force-app/main/default/lwc/brokerCard/__tests__/data/getPropertyRecord.json @@ -0,0 +1,18 @@ +{ + "apiName": "Property__c", + "childRelationships": {}, + "eTag": "e724fda6d93b891f98c7e0b6b3d7686c", + "fields": { + "Broker__c": { + "displayValue": null, + "value": "a003h000003xlBiAAI" + } + }, + "id": "a013h000009HEM7AAO", + "lastModifiedById": "00540000032Tm3AAE", + "lastModifiedDate": "2020-07-15T19:56:23.000Z", + "recordTypeId": "012000000000000AAA", + "recordTypeInfo": null, + "systemModstamp": "2020-07-15T19:56:23.000Z", + "weakEtag": 1594842983000 +} diff --git a/force-app/main/default/lwc/brokerCard/brokerCard.html b/force-app/main/default/lwc/brokerCard/brokerCard.html new file mode 100644 index 0000000..9fca4d0 --- /dev/null +++ b/force-app/main/default/lwc/brokerCard/brokerCard.html @@ -0,0 +1,20 @@ + \ No newline at end of file diff --git a/force-app/main/default/lwc/brokerCard/brokerCard.js b/force-app/main/default/lwc/brokerCard/brokerCard.js new file mode 100644 index 0000000..f246a9a --- /dev/null +++ b/force-app/main/default/lwc/brokerCard/brokerCard.js @@ -0,0 +1,36 @@ +import { LightningElement, api, wire } from 'lwc'; +import { getRecord, getFieldValue } from 'lightning/uiRecordApi'; +import { NavigationMixin } from 'lightning/navigation'; + +import BROKER_FIELD from '@salesforce/schema/Property__c.Broker__c'; +import NAME_FIELD from '@salesforce/schema/Broker__c.Name'; +import PHONE_FIELD from '@salesforce/schema/Broker__c.Phone__c'; +import MOBILE_PHONE_FIELD from '@salesforce/schema/Broker__c.Mobile_Phone__c'; +import EMAIL_FIELD from '@salesforce/schema/Broker__c.Email__c'; + +const PROPERTY_FIELDS = [BROKER_FIELD]; +const BROKER_FIELDS = [NAME_FIELD, PHONE_FIELD, MOBILE_PHONE_FIELD, EMAIL_FIELD]; + +export default class BrokerCard extends NavigationMixin(LightningElement) { + @api recordId; + + brokerFields = BROKER_FIELDS; + + @wire(getRecord, { recordId: '$recordId', fields: PROPERTY_FIELDS }) + property; + + get brokerId() { + return getFieldValue(this.property.data, BROKER_FIELD); + } + + handleNavigateToRecord() { + this[NavigationMixin.Navigate]({ + type: 'standard__recordPage', + attributes: { + recordId: this.brokerId, + objectApiName: 'Hutte__Property__c', + actionName: 'view' + } + }); + } +} \ No newline at end of file diff --git a/force-app/main/default/lwc/brokerCard/brokerCard.js-meta.xml b/force-app/main/default/lwc/brokerCard/brokerCard.js-meta.xml new file mode 100644 index 0000000..30cec35 --- /dev/null +++ b/force-app/main/default/lwc/brokerCard/brokerCard.js-meta.xml @@ -0,0 +1,20 @@ + + + 61.0 + true + Broker Card + + lightning__RecordPage + + + + + Property__c + + + + + + + + \ No newline at end of file diff --git a/force-app/main/default/lwc/daysOnMarket/__tests__/data/getRecord.json b/force-app/main/default/lwc/daysOnMarket/__tests__/data/getRecord.json new file mode 100644 index 0000000..145201f --- /dev/null +++ b/force-app/main/default/lwc/daysOnMarket/__tests__/data/getRecord.json @@ -0,0 +1,20 @@ +{ + "apiName": "Property__c", + "childRelationships": {}, + "id": "a015I000002taYUQAY", + "lastModifiedById": "0054I000001RjtIQAS", + "lastModifiedDate": "2020-06-09T07:48:54.000Z", + "recordTypeId": "012000000000000AAA", + "recordTypeInfo": null, + "systemModstamp": "2020-06-09T07:48:55.000Z", + "fields": { + "Date_Listed__c": { + "displayValue": "30/5/2020", + "value": "2020-05-30" + }, + "Days_On_Market__c": { + "displayValue": null, + "value": 18 + } + } +} diff --git a/force-app/main/default/lwc/daysOnMarket/__tests__/daysOnMarket.test.js b/force-app/main/default/lwc/daysOnMarket/__tests__/daysOnMarket.test.js new file mode 100644 index 0000000..7cbb93d --- /dev/null +++ b/force-app/main/default/lwc/daysOnMarket/__tests__/daysOnMarket.test.js @@ -0,0 +1,255 @@ +import { createElement } from 'lwc'; +import DaysOnMarket from 'c/daysOnMarket'; +import { getRecord, getFieldValue } from 'lightning/uiRecordApi'; +import { + subscribe, + MessageContext, + publish, + unsubscribe +} from 'lightning/messageService'; +import PROPERTYSELECTEDMC from '@salesforce/messageChannel/PropertySelected__c'; +import DATE_LISTED_FIELD from '@salesforce/schema/Property__c.Date_Listed__c'; +import DAYS_ON_MARKET_FIELD from '@salesforce/schema/Property__c.Days_On_Market__c'; + +const MAX_DAYS_CHART = 90; + +const mockGetRecord = require('./data/getRecord.json'); + +describe('c-days-on-market', () => { + afterEach(() => { + // The jsdom instance is shared across test cases in a single file so reset the DOM + while (document.body.firstChild) { + document.body.removeChild(document.body.firstChild); + } + + // Prevent data saved on mocks from leaking between tests + jest.clearAllMocks(); + }); + + // Helper function to wait until the microtask queue is empty. + // Used when having to wait for asynchronous DOM updates. + async function flushPromises() { + return Promise.resolve(); + } + + it('renders error if no property is selected', () => { + // Create initial element + const element = createElement('c-days-on-market', { + is: DaysOnMarket + }); + document.body.appendChild(element); + + const errorPanelElement = + element.shadowRoot.querySelector('c-error-panel'); + expect(errorPanelElement.friendlyMessage).toBe( + 'Select a property to see days on the market' + ); + }); + + it('registers the LMS subscriber during the component lifecycle', () => { + // Create initial element + const element = createElement('c-days-on-market', { + is: DaysOnMarket + }); + document.body.appendChild(element); + + // Validate if pubsub got registered after connected to the DOM + expect(subscribe).toHaveBeenCalled(); + expect(subscribe.mock.calls[0][1]).toBe(PROPERTYSELECTEDMC); + }); + + it('unregisters the LMS subscriber during the component lifecycle', () => { + // Create initial element + const element = createElement('c-days-on-market', { + is: DaysOnMarket + }); + document.body.appendChild(element); + document.body.removeChild(element); + + // Validate if pubsub got unsubscribed after disconnected from the DOM + expect(unsubscribe).toHaveBeenCalled(); + }); + + it('invokes getRecord with the published message payload value', async () => { + // Create element + const element = createElement('c-days-on-market', { + is: DaysOnMarket + }); + document.body.appendChild(element); + + // Simulate pulishing a message using RECORD_SELECTED_CHANNEL message channel + const messagePayload = { propertyId: '001' }; + publish(MessageContext, PROPERTYSELECTEDMC, messagePayload); + + // Wait for any asynchronous DOM updates + await flushPromises(); + + // The component subscription should cause getRecord to be invoked. + // Below we test that it is invoked with the messagePayload value + // that was published with the simulated publish invocation above. + const { propertyId, fields } = getRecord.getLastConfig(); + expect(propertyId).toEqual(messagePayload.recordId); + expect(fields).toEqual([DATE_LISTED_FIELD, DAYS_ON_MARKET_FIELD]); + }); + + describe('getRecord @wire data', () => { + function validateHTML(element, type) { + const badgeEl = element.shadowRoot.querySelector( + `div.badge.${type}` + ); + expect(badgeEl).not.toBeNull(); + + const daysDivEl = element.shadowRoot.querySelector('div.days'); + expect(daysDivEl.textContent).toBe( + getFieldValue(mockGetRecord, DAYS_ON_MARKET_FIELD).toString() + ); + + const chartBarEl = element.shadowRoot.querySelector( + `div.bar.${type}` + ); + expect(chartBarEl).not.toBeNull(); + const width = + (getFieldValue(mockGetRecord, DAYS_ON_MARKET_FIELD) / + MAX_DAYS_CHART) * + 100; + expect(chartBarEl.style.width).toBe(`${width}%`); + + const formattedDateTimeEl = element.shadowRoot.querySelector( + 'lightning-formatted-date-time' + ); + expect(formattedDateTimeEl.value).toBe( + getFieldValue(mockGetRecord, DATE_LISTED_FIELD).toString() + ); + } + + describe('renders days on market', () => { + // eslint-disable-next-line jest/expect-expect + it('in normal case', async () => { + // Create element + const element = createElement('c-days-on-market', { + is: DaysOnMarket + }); + element.recordId = '001'; + document.body.appendChild(element); + + // Emit data from @wire + getRecord.emit(mockGetRecord); + + // Wait for any asynchronous DOM updates + await flushPromises(); + + // Select elements for validation + validateHTML(element, 'normal'); + }); + + // eslint-disable-next-line jest/expect-expect + it('in warning case', async () => { + // Create element + const element = createElement('c-days-on-market', { + is: DaysOnMarket + }); + element.recordId = '001'; + document.body.appendChild(element); + + // Emit data from @wire + mockGetRecord.fields.Days_On_Market__c.value = 48; + getRecord.emit(mockGetRecord); + + // Wait for any asynchronous DOM updates + await flushPromises(); + + // Select elements for validation + validateHTML(element, 'warning'); + }); + + // eslint-disable-next-line jest/expect-expect + it('in alert case', async () => { + // Create element + const element = createElement('c-days-on-market', { + is: DaysOnMarket + }); + element.recordId = '001'; + document.body.appendChild(element); + + // Emit data from @wire + mockGetRecord.fields.Days_On_Market__c.value = 68; + getRecord.emit(mockGetRecord); + + // Wait for any asynchronous DOM updates + await flushPromises(); + + // Select elements for validation + validateHTML(element, 'alert'); + }); + }); + }); + describe('getRecord @wire error', () => { + it('renders an error panel when there is an error', async () => { + const APEX_ERROR = { + body: 'Error retrieving records', + ok: false, + status: '400', + statusText: 'Bad Request' + }; + + // Create initial element + const element = createElement('c-days-on-market', { + is: DaysOnMarket + }); + element.recordId = '001'; + document.body.appendChild(element); + + // Emit error from @wire + getRecord.error( + APEX_ERROR.body, + APEX_ERROR.status, + APEX_ERROR.statusText + ); + + // Wait for any asynchronous DOM updates + await flushPromises(); + + const errorPanelEl = + element.shadowRoot.querySelector('c-error-panel'); + expect(errorPanelEl).not.toBeNull(); + expect(errorPanelEl.errors).toStrictEqual(APEX_ERROR); + }); + }); + + it('is accessible when property selected', async () => { + const element = createElement('c-days-on-market', { + is: DaysOnMarket + }); + + element.recordId = '001'; + document.body.appendChild(element); + + // Emit data from @wire + getRecord.emit(mockGetRecord); + + // Wait for any asynchronous DOM updates + await flushPromises(); + + await expect(element).toBeAccessible(); + }); + + it('is accessible when no property selected', async () => { + const element = createElement('c-days-on-market', { + is: DaysOnMarket + }); + document.body.appendChild(element); + + await expect(element).toBeAccessible(); + }); + + it('is accessible when error returned', async () => { + // Create initial element + const element = createElement('c-days-on-market', { + is: DaysOnMarket + }); + element.recordId = '001'; + document.body.appendChild(element); + + await expect(element).toBeAccessible(); + }); +}); diff --git a/force-app/main/default/lwc/daysOnMarket/daysOnMarket.css b/force-app/main/default/lwc/daysOnMarket/daysOnMarket.css new file mode 100644 index 0000000..549575f --- /dev/null +++ b/force-app/main/default/lwc/daysOnMarket/daysOnMarket.css @@ -0,0 +1,57 @@ +.badge { + text-align: center; + margin-right: var(--lwc-varSpacingXxSmall, 4px); + padding: var(--lwc-varSpacingXSmall, 8px) var(--lwc-varSpacingSmall, 12px); + border-radius: var(--lwc-borderRadiusMedium, 4px); + color: var(--lwc-colorTextInverse, #ffffff); +} + +.badge.alert { + background-color: #c23934; + border: solid var(--lwc-borderWidthThin, 1px) #c23934; +} + +.badge.normal { + background-color: #00716b; + border: solid var(--lwc-borderWidthThin, 1px) #00716b; +} + +.badge.warning { + background-color: #f28c00; + border: solid var(--lwc-borderWidthThin, 1px) #f28c00; +} + +.bar { + -webkit-transform: translate3d(0, 0, 0); + transform: translate3d(0, 0, 0); + height: 58px; + transition: all 0.5s ease-in-out; + position: absolute; + left: var(--lwc-spacingXxxSmall, 2px); +} + +.bar.normal { + background-color: #00716b; +} + +.bar.warning { + background-color: #f28c00; +} + +.bar.alert { + background-color: #c23934; +} + +.axis { + font-weight: 200; +} + +.axis > div { + height: 60px; + border-bottom: solid var(--lwc-borderWidthThin, 1px) rgb(216, 221, 230); + border-left: solid var(--lwc-borderWidthThin, 1px) rgb(216, 221, 230); +} + +.axis .legend { + margin-top: 60px; +} \ No newline at end of file diff --git a/force-app/main/default/lwc/daysOnMarket/daysOnMarket.html b/force-app/main/default/lwc/daysOnMarket/daysOnMarket.html new file mode 100644 index 0000000..2722438 --- /dev/null +++ b/force-app/main/default/lwc/daysOnMarket/daysOnMarket.html @@ -0,0 +1,43 @@ + \ No newline at end of file diff --git a/force-app/main/default/lwc/daysOnMarket/daysOnMarket.js b/force-app/main/default/lwc/daysOnMarket/daysOnMarket.js new file mode 100644 index 0000000..c3159b6 --- /dev/null +++ b/force-app/main/default/lwc/daysOnMarket/daysOnMarket.js @@ -0,0 +1,94 @@ +import { LightningElement, api, wire } from 'lwc'; +import { getRecord, getFieldValue } from 'lightning/uiRecordApi'; +import { + subscribe, + unsubscribe, + MessageContext +} from 'lightning/messageService'; +import PROPERTYSELECTEDMC from '@salesforce/messageChannel/PropertySelected__c'; +import DATE_LISTED_FIELD from '@salesforce/schema/Property__c.Date_Listed__c'; +import DAYS_ON_MARKET_FIELD from '@salesforce/schema/Property__c.Days_On_Market__c'; + +const MAX_DAYS_NORMAL_STATUS = 30; +const MAX_DAYS_WARNING_STATUS = 60; +const MAX_DAYS_CHART = 90; + +const FIELDS = [DATE_LISTED_FIELD, DAYS_ON_MARKET_FIELD]; + +export default class DaysOnMarket extends LightningElement { + error; + daysOnMarket; + dateListed; + propertyId; + status; + subscription; + + @wire(MessageContext) + messageContext; + + @wire(getRecord, { recordId: '$propertyId', fields: FIELDS }) + wiredRecord({ error, data }) { + if (data) { + this.error = undefined; + this.dateListed = getFieldValue(data, DATE_LISTED_FIELD); + this.daysOnMarket = getFieldValue(data, DAYS_ON_MARKET_FIELD); + if (this.daysOnMarket < MAX_DAYS_NORMAL_STATUS) { + this.status = 'normal'; + } else if (this.daysOnMarket < MAX_DAYS_WARNING_STATUS) { + this.status = 'warning'; + } else { + this.status = 'alert'; + } + } else if (error) { + this.daysOnMarket = undefined; + this.dateListed = undefined; + this.status = undefined; + this.error = error; + } + } + + @api + get recordId() { + return this.propertyId; + } + + set recordId(propertyId) { + this.propertyId = propertyId; + } + + get hasNoPropertyId() { + return this.propertyId === undefined; + } + + get badgeClass() { + return 'badge ' + this.status; + } + + get barClass() { + return 'bar ' + this.status; + } + + get barStyle() { + const value = (this.daysOnMarket / MAX_DAYS_CHART) * 100; + return 'width:' + value + '%'; + } + + connectedCallback() { + this.subscription = subscribe( + this.messageContext, + PROPERTYSELECTEDMC, + (message) => { + this.handlePropertySelected(message); + } + ); + } + + disconnectedCallback() { + unsubscribe(this.subscription); + this.subscription = null; + } + + handlePropertySelected(message) { + this.propertyId = message.propertyId; + } +} \ No newline at end of file diff --git a/force-app/main/default/lwc/daysOnMarket/daysOnMarket.js-meta.xml b/force-app/main/default/lwc/daysOnMarket/daysOnMarket.js-meta.xml new file mode 100644 index 0000000..020d148 --- /dev/null +++ b/force-app/main/default/lwc/daysOnMarket/daysOnMarket.js-meta.xml @@ -0,0 +1,22 @@ + + + 61.0 + true + Days on Market + + lightning__AppPage + lightning__RecordPage + lightning__HomePage + + + + + Property__c + + + + + + + + \ No newline at end of file diff --git a/force-app/main/default/lwc/errorPanel/__tests__/errorPanel.test.js b/force-app/main/default/lwc/errorPanel/__tests__/errorPanel.test.js new file mode 100644 index 0000000..0413593 --- /dev/null +++ b/force-app/main/default/lwc/errorPanel/__tests__/errorPanel.test.js @@ -0,0 +1,122 @@ +import { createElement } from 'lwc'; +import ErrorPanel from 'c/errorPanel'; + +describe('c-error-panel', () => { + afterEach(() => { + // The jsdom instance is shared across test cases in a single file so reset the DOM + while (document.body.firstChild) { + document.body.removeChild(document.body.firstChild); + } + }); + + // Helper function to wait until the microtask queue is empty. + // Used when having to wait for asynchronous DOM updates. + async function flushPromises() { + return Promise.resolve(); + } + + it('displays a default friendly message', () => { + const MESSAGE = 'Error retrieving data'; + + // Create initial element + const element = createElement('c-error-panel', { + is: ErrorPanel + }); + document.body.appendChild(element); + + const messageEl = element.shadowRoot.querySelector('h3'); + expect(messageEl.textContent).toBe(MESSAGE); + }); + + it('displays a custom friendly message', () => { + const MESSAGE = 'Errors are bad'; + + // Create initial element + const element = createElement('c-error-panel', { + is: ErrorPanel + }); + element.friendlyMessage = MESSAGE; + document.body.appendChild(element); + + const messageEl = element.shadowRoot.querySelector('h3'); + expect(messageEl.textContent).toBe(MESSAGE); + }); + + it('displays no error details when no errors are passed as parameters', () => { + // Create initial element + const element = createElement('c-error-panel', { + is: ErrorPanel + }); + document.body.appendChild(element); + + const anchorEl = element.shadowRoot.querySelector('a'); + expect(anchorEl).toBeNull(); + }); + + it('displays error details when errors are passed as parameters', async () => { + const ERROR_MESSAGES_INPUT = [ + { statusText: 'First bad error' }, + { statusText: 'Second bad error' } + ]; + const ERROR_MESSAGES_OUTPUT = ['First bad error', 'Second bad error']; + + // Create initial element + const element = createElement('c-error-panel', { + is: ErrorPanel + }); + element.type = 'inlineMessage'; + element.errors = ERROR_MESSAGES_INPUT; + document.body.appendChild(element); + + // Click link to show details + element.shadowRoot.querySelector('a').click(); + + // Wait for any asynchronous DOM updates + await flushPromises(); + + const messageTexts = Array.from( + element.shadowRoot.querySelectorAll('p') + ).map((errorMessage) => (errorMessage = errorMessage.textContent)); + expect(messageTexts).toEqual(ERROR_MESSAGES_OUTPUT); + }); + + it('is accessible when inline message', async () => { + const ERROR_MESSAGES_INPUT = [ + { statusText: 'First bad error' }, + { statusText: 'Second bad error' } + ]; + + const element = createElement('c-error-panel', { + is: ErrorPanel + }); + + element.type = 'inlineMessage'; + element.errors = ERROR_MESSAGES_INPUT; + document.body.appendChild(element); + + // Click link to show details + element.shadowRoot.querySelector('a').click(); + + // Wait for any asynchronous DOM updates + await flushPromises(); + + await expect(element).toBeAccessible(); + }); + + it('is accessible when no data illustration', async () => { + const ERROR_MESSAGES_INPUT = [ + { statusText: 'First bad error' }, + { statusText: 'Second bad error' } + ]; + + const element = createElement('c-error-panel', { + is: ErrorPanel + }); + + element.type = 'noDataIllustration'; + element.errors = ERROR_MESSAGES_INPUT; + document.body.appendChild(element); + + await expect(element).toBeAccessible(); + }); +}); diff --git a/force-app/main/default/lwc/errorPanel/errorPanel.js b/force-app/main/default/lwc/errorPanel/errorPanel.js new file mode 100644 index 0000000..5dafd3c --- /dev/null +++ b/force-app/main/default/lwc/errorPanel/errorPanel.js @@ -0,0 +1,28 @@ +import { LightningElement, api } from 'lwc'; +import { reduceErrors } from 'c/ldsUtils'; +import noDataIllustration from './templates/noDataIllustration.html'; +import inlineMessage from './templates/inlineMessage.html'; + +export default class ErrorPanel extends LightningElement { + /** Single or array of LDS errors */ + @api errors; + /** Generic / user-friendly message */ + @api friendlyMessage = 'Error retrieving data'; + /** Type of error message **/ + @api type; + + viewDetails = false; + + get errorMessages() { + return reduceErrors(this.errors); + } + + handleShowDetailsClick() { + this.viewDetails = !this.viewDetails; + } + + render() { + if (this.type === 'inlineMessage') return inlineMessage; + return noDataIllustration; + } +} \ No newline at end of file diff --git a/force-app/main/default/lwc/errorPanel/errorPanel.js-meta.xml b/force-app/main/default/lwc/errorPanel/errorPanel.js-meta.xml new file mode 100644 index 0000000..a4a5ed3 --- /dev/null +++ b/force-app/main/default/lwc/errorPanel/errorPanel.js-meta.xml @@ -0,0 +1,5 @@ + + + 61.0 + false + \ No newline at end of file diff --git a/force-app/main/default/lwc/errorPanel/templates/inlineMessage.html b/force-app/main/default/lwc/errorPanel/templates/inlineMessage.html new file mode 100755 index 0000000..aceb4cc --- /dev/null +++ b/force-app/main/default/lwc/errorPanel/templates/inlineMessage.html @@ -0,0 +1,19 @@ + \ No newline at end of file diff --git a/force-app/main/default/lwc/errorPanel/templates/noDataIllustration.html b/force-app/main/default/lwc/errorPanel/templates/noDataIllustration.html new file mode 100644 index 0000000..eb83302 --- /dev/null +++ b/force-app/main/default/lwc/errorPanel/templates/noDataIllustration.html @@ -0,0 +1,257 @@ + \ No newline at end of file diff --git a/force-app/main/default/lwc/ldsUtils/__tests__/ldsUtils.test.js b/force-app/main/default/lwc/ldsUtils/__tests__/ldsUtils.test.js new file mode 100644 index 0000000..dfb398a --- /dev/null +++ b/force-app/main/default/lwc/ldsUtils/__tests__/ldsUtils.test.js @@ -0,0 +1,61 @@ +import { reduceErrors } from 'c/ldsUtils'; + +describe('c-lds-utils', () => { + describe('reduceErrors', () => { + it('reduces single error with message in body', () => { + const FULL_ERROR = { body: { message: 'mockError' } }; + const REDUCED_ERROR = [FULL_ERROR.body.message]; + + const reduced = reduceErrors(FULL_ERROR); + + expect(reduced).toStrictEqual(REDUCED_ERROR); + }); + + it('reduces single error with multiple bodies with messages', () => { + const FULL_ERROR = { + body: [{ message: 'mockError1' }, { message: 'mockError2' }] + }; + const REDUCED_ERROR = [ + FULL_ERROR.body[0].message, + FULL_ERROR.body[1].message + ]; + + const reduced = reduceErrors(FULL_ERROR); + + expect(reduced).toStrictEqual(REDUCED_ERROR); + }); + + it('reduces single error message string', () => { + const FULL_ERROR = { message: 'mockError' }; + const REDUCED_ERROR = [FULL_ERROR.message]; + + const reduced = reduceErrors(FULL_ERROR); + + expect(reduced).toStrictEqual(REDUCED_ERROR); + }); + + it('reduces array of error message string', () => { + const FULL_ERROR = [ + { message: 'mockError1' }, + { message: 'mockError2' } + ]; + const REDUCED_ERROR = [ + FULL_ERROR[0].message, + FULL_ERROR[1].message + ]; + + const reduced = reduceErrors(FULL_ERROR); + + expect(reduced).toStrictEqual(REDUCED_ERROR); + }); + + it('reduces single error with unknown shape', () => { + const FULL_ERROR = { statusText: 'mockStatus' }; + const REDUCED_ERROR = [FULL_ERROR.statusText]; + + const reduced = reduceErrors(FULL_ERROR); + + expect(reduced).toStrictEqual(REDUCED_ERROR); + }); + }); +}); diff --git a/force-app/main/default/lwc/ldsUtils/ldsUtils.js b/force-app/main/default/lwc/ldsUtils/ldsUtils.js new file mode 100644 index 0000000..db98851 --- /dev/null +++ b/force-app/main/default/lwc/ldsUtils/ldsUtils.js @@ -0,0 +1,37 @@ +/** + * Reduces one or more LDS errors into a string[] of error messages. + * @param {FetchResponse|FetchResponse[]} errors + * @return {String[]} Error messages + */ +export function reduceErrors(errors) { + if (!Array.isArray(errors)) { + errors = [errors]; + } + + return ( + errors + // Remove null/undefined items + .filter((error) => !!error) + // Extract an error message + .map((error) => { + // UI API read errors + if (Array.isArray(error.body)) { + return error.body.map((e) => e.message); + } + // UI API DML, Apex and network errors + else if (error.body && typeof error.body.message === 'string') { + return error.body.message; + } + // JS errors + else if (typeof error.message === 'string') { + return error.message; + } + // Unknown error shape so try HTTP status text + return error.statusText; + }) + // Flatten + .reduce((prev, curr) => prev.concat(curr), []) + // Remove empty strings + .filter((message) => !!message) + ); +} \ No newline at end of file diff --git a/force-app/main/default/lwc/ldsUtils/ldsUtils.js-meta.xml b/force-app/main/default/lwc/ldsUtils/ldsUtils.js-meta.xml new file mode 100644 index 0000000..be8d172 --- /dev/null +++ b/force-app/main/default/lwc/ldsUtils/ldsUtils.js-meta.xml @@ -0,0 +1,8 @@ + + + 61.0 + false + \ No newline at end of file diff --git a/force-app/main/default/lwc/listContactsFromDevice/listContactsFromDevice.html b/force-app/main/default/lwc/listContactsFromDevice/listContactsFromDevice.html new file mode 100644 index 0000000..ee44c6a --- /dev/null +++ b/force-app/main/default/lwc/listContactsFromDevice/listContactsFromDevice.html @@ -0,0 +1,40 @@ + \ No newline at end of file diff --git a/force-app/main/default/lwc/listContactsFromDevice/listContactsFromDevice.js b/force-app/main/default/lwc/listContactsFromDevice/listContactsFromDevice.js new file mode 100644 index 0000000..a4b83d4 --- /dev/null +++ b/force-app/main/default/lwc/listContactsFromDevice/listContactsFromDevice.js @@ -0,0 +1,31 @@ +import { LightningElement } from 'lwc'; +import { getContactsService } from 'lightning/mobileCapabilities'; + +export default class ListContactsFromDevice extends LightningElement { + contactsService; + deviceContacts; + error; + + async connectedCallback() { + this.contactsService = getContactsService(); + if (this.contactsService.isAvailable()) { + await this.retrieveDeviceContacts(); + } else { + this.error = { message: 'Contact service not available' }; + } + } + + async retrieveDeviceContacts() { + const options = { + permissionRationaleText: + 'Allow access to your contacts to enable contacts processing.' + }; + + try { + this.deviceContacts = + await this.contactsService.getContacts(options); + } catch (error) { + this.error = error; + } + } +} \ No newline at end of file diff --git a/force-app/main/default/lwc/listContactsFromDevice/listContactsFromDevice.js-meta.xml b/force-app/main/default/lwc/listContactsFromDevice/listContactsFromDevice.js-meta.xml new file mode 100644 index 0000000..bc308af --- /dev/null +++ b/force-app/main/default/lwc/listContactsFromDevice/listContactsFromDevice.js-meta.xml @@ -0,0 +1,9 @@ + + + 61.0 + true + Lists Contacts from Device + + lightning__AppPage + + \ No newline at end of file diff --git a/force-app/main/default/lwc/navigateToRecord/__tests__/navigateToRecord.test.js b/force-app/main/default/lwc/navigateToRecord/__tests__/navigateToRecord.test.js new file mode 100644 index 0000000..f6af6a7 --- /dev/null +++ b/force-app/main/default/lwc/navigateToRecord/__tests__/navigateToRecord.test.js @@ -0,0 +1,45 @@ +import { createElement } from 'lwc'; +import NavigateToRecord from 'c/navigateToRecord'; +import { getNavigateCalledWith } from 'lightning/navigation'; + +describe('c-navigate-to-record', () => { + afterEach(() => { + // The jsdom instance is shared across test cases in a single file so reset the DOM + while (document.body.firstChild) { + document.body.removeChild(document.body.firstChild); + } + // Prevent data saved on mocks from leaking between tests + jest.clearAllMocks(); + }); + + // Helper function to wait until the microtask queue is empty. + // Used when having to wait for asynchronous DOM updates. + async function flushPromises() { + return Promise.resolve(); + } + + it('navigates to record view', async () => { + // Nav param values to test later + const NAV_TYPE = 'standard__recordPage'; + const NAV_ACTION_NAME = 'view'; + const NAV_RECORD_ID = '0031700000pJRRWAA4'; + + // Create initial lwc element and attach to virtual DOM + const element = createElement('c-navigate-to-record', { + is: NavigateToRecord + }); + + element.recordId = NAV_RECORD_ID; + document.body.appendChild(element); + + // Wait for any asynchronous DOM updates + await flushPromises(); + + const { pageReference } = getNavigateCalledWith(); + + // Verify component called with correct event type and params + expect(pageReference.type).toBe(NAV_TYPE); + expect(pageReference.attributes.actionName).toBe(NAV_ACTION_NAME); + expect(pageReference.attributes.recordId).toBe(NAV_RECORD_ID); + }); +}); diff --git a/force-app/main/default/lwc/navigateToRecord/navigateToRecord.html b/force-app/main/default/lwc/navigateToRecord/navigateToRecord.html new file mode 100644 index 0000000..0440d2c --- /dev/null +++ b/force-app/main/default/lwc/navigateToRecord/navigateToRecord.html @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/force-app/main/default/lwc/navigateToRecord/navigateToRecord.js b/force-app/main/default/lwc/navigateToRecord/navigateToRecord.js new file mode 100644 index 0000000..7ddf9a9 --- /dev/null +++ b/force-app/main/default/lwc/navigateToRecord/navigateToRecord.js @@ -0,0 +1,18 @@ +import { LightningElement, api } from 'lwc'; +import { NavigationMixin } from 'lightning/navigation'; + +export default class NavigateToRecord extends NavigationMixin( + LightningElement +) { + @api recordId; + + connectedCallback() { + this[NavigationMixin.Navigate]({ + type: 'standard__recordPage', + attributes: { + recordId: this.recordId, + actionName: 'view' + } + }); + } +} \ No newline at end of file diff --git a/force-app/main/default/lwc/navigateToRecord/navigateToRecord.js-meta.xml b/force-app/main/default/lwc/navigateToRecord/navigateToRecord.js-meta.xml new file mode 100644 index 0000000..f302749 --- /dev/null +++ b/force-app/main/default/lwc/navigateToRecord/navigateToRecord.js-meta.xml @@ -0,0 +1,20 @@ + + + 61.0 + true + Navigate to Record Page + + lightning__FlowScreen + + + + + + + \ No newline at end of file diff --git a/force-app/main/default/lwc/paginator/__tests__/paginator.test.js b/force-app/main/default/lwc/paginator/__tests__/paginator.test.js new file mode 100644 index 0000000..0ba2815 --- /dev/null +++ b/force-app/main/default/lwc/paginator/__tests__/paginator.test.js @@ -0,0 +1,144 @@ +import { createElement } from 'lwc'; +import Paginator from 'c/paginator'; + +describe('c-paginator', () => { + afterEach(() => { + // The jsdom instance is shared across test cases in a single file so reset the DOM + while (document.body.firstChild) { + document.body.removeChild(document.body.firstChild); + } + }); + + // Helper function to wait until the microtask queue is empty. + // Used when having to wait for asynchronous DOM updates. + async function flushPromises() { + return Promise.resolve(); + } + + it('sends "next" event on button click', async () => { + // Create initial element + const element = createElement('c-paginator', { + is: Paginator + }); + // Simulate we are on first page + element.pageNumber = 1; + element.pageSize = 10; + element.totalItemCount = 100; + document.body.appendChild(element); + + // Mock handlers for child events + const handlerNext = jest.fn(); + + // Add event listener to catch child events + element.addEventListener('next', handlerNext); + + // Click the next(>) button + const nextButtonEl = + element.shadowRoot.querySelector('.right-button-icon'); + nextButtonEl.click(); + + // Wait for any asynchronous DOM updates + await flushPromises(); + + // Validate if mocked events got fired + expect(handlerNext.mock.calls.length).toBe(1); + + // Validate previous button is hidden + const prevButtonEl = + element.shadowRoot.querySelector('.left-button-icon'); + expect(prevButtonEl).toBeNull(); + }); + + it('sends "previous" event on button click', async () => { + // Create initial element + const element = createElement('c-paginator', { + is: Paginator + }); + // Simulate we are on last page + element.pageNumber = 10; + element.pageSize = 10; + element.totalItemCount = 100; + document.body.appendChild(element); + + // Mock handlers for child events + const handlerPrevious = jest.fn(); + + // Add event listener to catch child events + element.addEventListener('previous', handlerPrevious); + + // Click the Previous(<) button + const prevButtonEl = + element.shadowRoot.querySelector('.left-button-icon'); + prevButtonEl.click(); + + // Wait for any asynchronous DOM updates + await flushPromises(); + + // Validate if mocked events got fired + expect(handlerPrevious.mock.calls.length).toBe(1); + + // Validate next button is hidden + const nextButtonEl = + element.shadowRoot.querySelector('.right-button-icon'); + expect(nextButtonEl).toBeNull(); + }); + + it('displays total item count, page number, and number of pages with zero items', () => { + // Create initial element + const element = createElement('c-paginator', { + is: Paginator + }); + //Set the public property values + element.pageNumber = 0; + element.pageSize = 9; + element.totalItemCount = 0; + + document.body.appendChild(element); + + // Query div for validating the display message on component init + const lightningLayoutItemEl = + element.shadowRoot.querySelector('.nav-info'); + //Check for the 0 items message + expect(lightningLayoutItemEl).not.toBeNull(); + expect(lightningLayoutItemEl.textContent).toBe('0 items • page 0 of 0'); + }); + + it('displays total item count, page number, and number of pages with some items', async () => { + // Create initial element + const element = createElement('c-paginator', { + is: Paginator + }); + document.body.appendChild(element); + + //Set the public properties for item count greater than zero + element.pageNumber = 1; + element.pageSize = 9; + element.totalItemCount = 12; + + // Query div for validating the display message on component init + const lightningLayoutItemEl = + element.shadowRoot.querySelector('.nav-info'); + + // Wait for any asynchronous DOM updates + await flushPromises(); + + // Query div for validating computed style attribute value on public property change + expect(lightningLayoutItemEl).not.toBeNull(); + expect(lightningLayoutItemEl.textContent).toBe( + '12 items • page 1 of 2' + ); + }); + + it('is accessible', async () => { + const element = createElement('c-paginator', { + is: Paginator + }); + + element.pageNumber = 3; + element.pageSize = 9; + element.totalItemCount = 12; + document.body.appendChild(element); + + await expect(element).toBeAccessible(); + }); +}); diff --git a/force-app/main/default/lwc/paginator/paginator.html b/force-app/main/default/lwc/paginator/paginator.html new file mode 100644 index 0000000..2d78050 --- /dev/null +++ b/force-app/main/default/lwc/paginator/paginator.html @@ -0,0 +1,29 @@ + \ No newline at end of file diff --git a/force-app/main/default/lwc/paginator/paginator.js b/force-app/main/default/lwc/paginator/paginator.js new file mode 100644 index 0000000..9a6e08b --- /dev/null +++ b/force-app/main/default/lwc/paginator/paginator.js @@ -0,0 +1,36 @@ +import { LightningElement, api } from 'lwc'; + +export default class Paginator extends LightningElement { + /** The current page number. */ + @api pageNumber; + + /** The number of items on a page. */ + @api pageSize; + + /** The total number of items in the list. */ + @api totalItemCount; + + handlePrevious() { + this.dispatchEvent(new CustomEvent('previous')); + } + + handleNext() { + this.dispatchEvent(new CustomEvent('next')); + } + + get currentPageNumber() { + return this.totalItemCount === 0 ? 0 : this.pageNumber; + } + + get isNotFirstPage() { + return this.pageNumber > 1; + } + + get isNotLastPage() { + return this.pageNumber < this.totalPages; + } + + get totalPages() { + return Math.ceil(this.totalItemCount / this.pageSize); + } +} \ No newline at end of file diff --git a/force-app/main/default/lwc/paginator/paginator.js-meta.xml b/force-app/main/default/lwc/paginator/paginator.js-meta.xml new file mode 100644 index 0000000..a4a5ed3 --- /dev/null +++ b/force-app/main/default/lwc/paginator/paginator.js-meta.xml @@ -0,0 +1,5 @@ + + + 61.0 + false + \ No newline at end of file diff --git a/force-app/main/default/lwc/propertyCarousel/__tests__/data/getPictures.json b/force-app/main/default/lwc/propertyCarousel/__tests__/data/getPictures.json new file mode 100644 index 0000000..9560d65 --- /dev/null +++ b/force-app/main/default/lwc/propertyCarousel/__tests__/data/getPictures.json @@ -0,0 +1,4 @@ +[ + { "Id": "0682F000000igu2QAA", "Title": "pic1" }, + { "Id": "0682F000000igu2QA4", "Title": "pic2" } +] diff --git a/force-app/main/default/lwc/propertyCarousel/__tests__/data/getPropertyRecord.json b/force-app/main/default/lwc/propertyCarousel/__tests__/data/getPropertyRecord.json new file mode 100644 index 0000000..31c18bb --- /dev/null +++ b/force-app/main/default/lwc/propertyCarousel/__tests__/data/getPropertyRecord.json @@ -0,0 +1,18 @@ +{ + "apiName": "Property__c", + "childRelationships": {}, + "eTag": "e724fda6d93b891f98c7e0b6b3d7686c", + "fields": { + "Broker__c": { + "displayValue": null, + "value": "a003h000003xlBiAAI" + } + }, + "id": "a013h000009HEM7AAO", + "lastModifiedById": "00540000032Tm3AAE", + "lastModifiedDate": "2020-07-15T19:56:23.000Z", + "recordTypeId": "012000000000000AAA", + "recordTypeInfo": null, + "systemModstamp": "2020-07-15T19:56:23.000Z", + "weakEtag": 1594842983000 +} diff --git a/force-app/main/default/lwc/propertyCarousel/__tests__/propertyCarousel.test.js b/force-app/main/default/lwc/propertyCarousel/__tests__/propertyCarousel.test.js new file mode 100644 index 0000000..741dadb --- /dev/null +++ b/force-app/main/default/lwc/propertyCarousel/__tests__/propertyCarousel.test.js @@ -0,0 +1,174 @@ +import { createElement } from 'lwc'; +import PropertyCarousel from 'c/propertyCarousel'; +import { getRecord } from 'lightning/uiRecordApi'; +import { processImage } from 'lightning/mediaUtils'; +import { refreshApex } from '@salesforce/apex'; +import getPictures from '@salesforce/apex/PropertyController.getPictures'; +import createFile from '@salesforce/apex/FileUtilities.createFile'; + +// Realistic data with multiple records +const mockGetPictures = require('./data/getPictures.json'); + +// Mock realistic data +const mockGetPropertyRecord = require('./data/getPropertyRecord.json'); + +// Mock getPictures Apex wire adapter +jest.mock( + '@salesforce/apex/PropertyController.getPictures', + () => { + const { + createApexTestWireAdapter + } = require('@salesforce/sfdx-lwc-jest'); + return { + default: createApexTestWireAdapter(jest.fn()) + }; + }, + { virtual: true } +); + +// Mocking createFile imperative Apex method call +jest.mock( + '@salesforce/apex/FileUtilities.createFile', + () => { + return { + default: jest.fn() + }; + }, + { virtual: true } +); + +describe('c-property-carousel', () => { + afterEach(() => { + // The jsdom instance is shared across test cases in a single file so reset the DOM + while (document.body.firstChild) { + document.body.removeChild(document.body.firstChild); + } + jest.clearAllMocks(); + }); + + // Helper function to wait until the microtask queue is empty. + // Used when having to wait for asynchronous DOM updates. + async function flushPromises() { + return Promise.resolve(); + } + + describe('@wire data', () => { + it('renders carousel with pictures when property and pictures returned', async () => { + const element = createElement('c-property-carousel', { + is: PropertyCarousel + }); + document.body.appendChild(element); + + // Emit mock property + getRecord.emit(mockGetPropertyRecord); + + // Emit mock pictures + getPictures.emit(mockGetPictures); + + // Wait for any asynchronous DOM updates + await flushPromises(); + + const carouselEl = + element.shadowRoot.querySelector('lightning-carousel'); + expect(carouselEl).not.toBeNull(); + const carouselImageEls = element.shadowRoot.querySelectorAll( + 'lightning-carousel-image' + ); + expect(carouselImageEls.length).toBe(mockGetPictures.length); + }); + + it('renders no pictures message when property but no pictures returned', async () => { + const element = createElement('c-property-carousel', { + is: PropertyCarousel + }); + document.body.appendChild(element); + + // Emit mock property + getRecord.emit(mockGetPropertyRecord); + + // Emit no pictures + getPictures.emit(null); + + // Wait for any asynchronous DOM updates + await flushPromises(); + + const pEl = element.shadowRoot.querySelector( + 'p.slds-text-align_center' + ); + expect(pEl).not.toBeNull(); + expect(pEl.textContent).toBe( + 'There are currently no pictures for this property.' + ); + }); + + it('renders error when getProperty returns error', async () => { + const element = createElement('c-property-carousel', { + is: PropertyCarousel + }); + document.body.appendChild(element); + + // Emit error + getRecord.error(); + + // Wait for any asynchronous DOM updates + await flushPromises(); + + const errorPanelEl = + element.shadowRoot.querySelector('c-error-panel'); + expect(errorPanelEl).not.toBeNull(); + }); + + it('renders error when getPictures returns error', async () => { + const element = createElement('c-property-carousel', { + is: PropertyCarousel + }); + document.body.appendChild(element); + + // Emit mock property + getRecord.emit(mockGetPropertyRecord); + + // Emit error + getPictures.error(); + + // Wait for any asynchronous DOM updates + await flushPromises(); + + const errorPanelEl = + element.shadowRoot.querySelector('c-error-panel'); + expect(errorPanelEl).not.toBeNull(); + }); + }); + describe('lightning-input interactions', () => { + it('calls processImage when a picture is uploaded', async () => { + const element = createElement('c-property-carousel', { + is: PropertyCarousel + }); + document.body.appendChild(element); + + // Emit mock property + getRecord.emit(mockGetPropertyRecord); + + // Emit mock createFile + createFile.mockResolvedValue('A00012345678'); + + // Wait for any asynchronous DOM updates + await flushPromises(); + + // Simulate input click + const lightningInputEl = + element.shadowRoot.querySelector('lightning-input'); + lightningInputEl.files = [ + new File(['1234'], 'test.jpg', { type: 'image/jpeg' }) + ]; + lightningInputEl.dispatchEvent(new CustomEvent('change')); + + // eslint-disable-next-line @lwc/lwc/no-async-operation + await new Promise((resolve) => setTimeout(() => resolve(), 10)); + + // Assertions + expect(processImage).toHaveBeenCalled(); + expect(createFile).toHaveBeenCalled(); + expect(refreshApex).toHaveBeenCalled(); + }); + }); +}); diff --git a/force-app/main/default/lwc/propertyCarousel/propertyCarousel.html b/force-app/main/default/lwc/propertyCarousel/propertyCarousel.html new file mode 100644 index 0000000..0b221f7 --- /dev/null +++ b/force-app/main/default/lwc/propertyCarousel/propertyCarousel.html @@ -0,0 +1,47 @@ + \ No newline at end of file diff --git a/force-app/main/default/lwc/propertyCarousel/propertyCarousel.js b/force-app/main/default/lwc/propertyCarousel/propertyCarousel.js new file mode 100644 index 0000000..dc9cb72 --- /dev/null +++ b/force-app/main/default/lwc/propertyCarousel/propertyCarousel.js @@ -0,0 +1,105 @@ +import { LightningElement, wire, api } from 'lwc'; +import { getRecord, getFieldValue } from 'lightning/uiRecordApi'; +import { processImage } from 'lightning/mediaUtils'; +import { refreshApex } from '@salesforce/apex'; +import getPictures from '@salesforce/apex/PropertyController.getPictures'; +import createFile from '@salesforce/apex/FileUtilities.createFile'; + +import ADDRESS_FIELD from '@salesforce/schema/Property__c.Address__c'; +import CITY_FIELD from '@salesforce/schema/Property__c.City__c'; +import DESCRIPTION_FIELD from '@salesforce/schema/Property__c.Description__c'; + +const FIELDS = [ADDRESS_FIELD, CITY_FIELD, DESCRIPTION_FIELD]; + +export default class PropertyCarousel extends LightningElement { + @api recordId; + carouselItems; + pictures; + + @wire(getRecord, { recordId: '$recordId', fields: FIELDS }) + property; + + @wire(getPictures, { propertyId: '$recordId' }) + wiredPictures(pictures) { + this.pictures = pictures; + if (pictures.data) { + const files = pictures.data; + if (Array.isArray(files) && files.length) { + this.carouselItems = files.map((file) => { + return { + title: file.Title, + url: `/sfc/servlet.shepherd/version/download/${file.Id}` + }; + }); + } else { + this.carouselItems = null; + } + } + } + + get address() { + return getFieldValue(this.property.data, ADDRESS_FIELD); + } + + get city() { + return getFieldValue(this.property.data, CITY_FIELD); + } + + get description() { + return getFieldValue(this.property.data, DESCRIPTION_FIELD); + } + + get errors() { + const errors = [this.property.error, this.pictures.error].filter( + (error) => error + ); + return errors.length ? errors : null; + } + + // As this app is accessible on mobile, let's resize/compress the images for a better UX + // If you don't need compression, use lightning-file-upload instead + async handleFilesSelected(event) { + try { + const options = { + resizeMode: 'fill', + resizeStrategy: 'reduce', + targetWidth: 500, + targetHeight: 500, + compressionQuality: 0.75, + imageSmoothingEnabled: true, + preserveTransparency: false, + backgroundColor: 'white' + }; + + // Process each file individually to allow partial uploads succeed + /* eslint-disable no-await-in-loop */ + for (const file of event.target.files) { + // Compress and resize image + const blob = await processImage(file, options); + + // Convert to base64 + const base64data = await this.blobToBase64(blob); + + // Create file attached to record + await createFile({ + base64data: base64data, + filename: file.name, + recordId: this.recordId + }); + + // Refresh pictures to incorporate uploaded file + refreshApex(this.pictures); + } + } catch (error) { + console.error('Error compressing and creating file: ', error); + } + } + + async blobToBase64(blob) { + return new Promise((resolve) => { + const reader = new FileReader(); + reader.onloadend = () => resolve(reader.result.split(',')[1]); // Remove Data-URL declaration + reader.readAsDataURL(blob); + }); + } +} \ No newline at end of file diff --git a/force-app/main/default/lwc/propertyCarousel/propertyCarousel.js-meta.xml b/force-app/main/default/lwc/propertyCarousel/propertyCarousel.js-meta.xml new file mode 100644 index 0000000..ccae37e --- /dev/null +++ b/force-app/main/default/lwc/propertyCarousel/propertyCarousel.js-meta.xml @@ -0,0 +1,20 @@ + + + 61.0 + true + Property Carousel + + lightning__RecordPage + + + + + Property__c + + + + + + + + \ No newline at end of file diff --git a/force-app/main/default/lwc/propertyFilter/__tests__/propertyFilter.test.js b/force-app/main/default/lwc/propertyFilter/__tests__/propertyFilter.test.js new file mode 100644 index 0000000..5b5a146 --- /dev/null +++ b/force-app/main/default/lwc/propertyFilter/__tests__/propertyFilter.test.js @@ -0,0 +1,275 @@ +import { createElement } from 'lwc'; +import PropertyFilter from 'c/propertyFilter'; +import { publish } from 'lightning/messageService'; +import FILTERSCHANGEMC from '@salesforce/messageChannel/FiltersChange__c'; + +const MAX_PRICE = 1200000; + +const DEFAULT_SEARCH_CRITERIA = { + searchKey: '', + maxPrice: MAX_PRICE, + minBedrooms: 0, + minBathrooms: 0 +}; + +describe('c-property-filter', () => { + beforeAll(() => { + // We use fake timers as setTimeout is used in the JavaScript file. + jest.useFakeTimers(); + }); + + afterEach(() => { + // The jsdom instance is shared across test cases in a single file so reset the DOM + while (document.body.firstChild) { + document.body.removeChild(document.body.firstChild); + } + jest.clearAllMocks(); + }); + + // Helper function to wait until the microtask queue is empty. + // Used when having to wait for asynchronous DOM updates. + async function flushPromises() { + return Promise.resolve(); + } + + it('fires the change event on new search input', async () => { + // Create initial element + const element = createElement('c-property-filter', { + is: PropertyFilter + }); + document.body.appendChild(element); + + // Query lightning-input element + const lightningInputEl = + element.shadowRoot.querySelector('lightning-input'); + lightningInputEl.dispatchEvent( + new CustomEvent('change', { + detail: { + value: 'Boston' + } + }) + ); + + // Run all fake timers. + jest.runAllTimers(); + + const SEARCH_CRITERIA = { + searchKey: 'Boston', + maxPrice: MAX_PRICE, + minBedrooms: 0, + minBathrooms: 0 + }; + + // Wait for any asynchronous DOM updates + await flushPromises(); + + // Was publish called and was it called with the correct params? + expect(publish).toHaveBeenCalledWith( + undefined, + FILTERSCHANGEMC, + SEARCH_CRITERIA + ); + }); + + it('fires the change event on Max Price slider input', async () => { + // Create initial element + const element = createElement('c-property-filter', { + is: PropertyFilter + }); + document.body.appendChild(element); + + // Query lightning-input element + const lightningSliderEl = + element.shadowRoot.querySelector('lightning-slider'); + lightningSliderEl.dispatchEvent( + new CustomEvent('change', { + detail: { + value: 60000 + } + }) + ); + + // Run all fake timers. + jest.runAllTimers(); + + const SEARCH_CRITERIA = { + searchKey: '', + maxPrice: 60000, + minBedrooms: 0, + minBathrooms: 0 + }; + + // Wait for any asynchronous DOM updates + await flushPromises(); + + // Was publish called and was it called with the correct params? + expect(publish).toHaveBeenCalledWith( + undefined, + FILTERSCHANGEMC, + SEARCH_CRITERIA + ); + }); + + it('fires the change event on Bedrooms slider input', async () => { + // Create initial element + const element = createElement('c-property-filter', { + is: PropertyFilter + }); + document.body.appendChild(element); + + // Query lightning-input element + const lightningSliderEl = + element.shadowRoot.querySelectorAll('lightning-slider')[1]; + lightningSliderEl.dispatchEvent( + new CustomEvent('change', { + detail: { + value: 2 + } + }) + ); + + // Run all fake timers. + jest.runAllTimers(); + + const SEARCH_CRITERIA = { + searchKey: '', + maxPrice: MAX_PRICE, + minBedrooms: 2, + minBathrooms: 0 + }; + + // Wait for any asynchronous DOM updates + await flushPromises(); + + // Was publish called and was it called with the correct params? + expect(publish).toHaveBeenCalledWith( + undefined, + FILTERSCHANGEMC, + SEARCH_CRITERIA + ); + }); + + it('fires the change event on Bathrooms slider input', async () => { + // Create initial element + const element = createElement('c-property-filter', { + is: PropertyFilter + }); + document.body.appendChild(element); + + // Query lightning-input element + const lightningSliderEl = + element.shadowRoot.querySelectorAll('lightning-slider')[2]; + lightningSliderEl.dispatchEvent( + new CustomEvent('change', { + detail: { + value: 2 + } + }) + ); + + // Run all fake timers. + jest.runAllTimers(); + + const SEARCH_CRITERIA = { + searchKey: '', + maxPrice: MAX_PRICE, + minBedrooms: 0, + minBathrooms: 2 + }; + + // Wait for any asynchronous DOM updates + await flushPromises(); + + // Was publish called and was it called with the correct params? + expect(publish).toHaveBeenCalledWith( + undefined, + FILTERSCHANGEMC, + SEARCH_CRITERIA + ); + }); + + it('fires change event when reset button is clicked', async () => { + // Create initial element + const element = createElement('c-property-filter', { + is: PropertyFilter + }); + document.body.appendChild(element); + + // Click reset button + const lightningButtonEl = + element.shadowRoot.querySelector('lightning-button'); + lightningButtonEl.click(); + // Run all fake timers. + jest.runAllTimers(); + + // Wait for any asynchronous DOM updates + await flushPromises(); + + // Was publish called and was it called with the correct params? + expect(publish).toHaveBeenCalledWith( + undefined, + FILTERSCHANGEMC, + DEFAULT_SEARCH_CRITERIA + ); + }); + + it('resets to default values when reset button is clicked', async () => { + // Create initial element + const element = createElement('c-property-filter', { + is: PropertyFilter + }); + document.body.appendChild(element); + + // Set inital form values + let searchKeyEl = element.shadowRoot.querySelector('lightning-input'); + searchKeyEl.dispatchEvent( + new CustomEvent('change', { + detail: { + value: 'someValue' + } + }) + ); + let sliderEls = element.shadowRoot.querySelectorAll('lightning-slider'); + sliderEls[0].dispatchEvent( + new CustomEvent('change', { + detail: { + value: 1 + } + }) + ); + sliderEls[1].dispatchEvent( + new CustomEvent('change', { + detail: { + value: 2 + } + }) + ); + sliderEls[2].dispatchEvent( + new CustomEvent('change', { + detail: { + value: 3 + } + }) + ); + + // Click reset button + const lightningButtonEl = + element.shadowRoot.querySelector('lightning-button'); + lightningButtonEl.click(); + + // Wait for any asynchronous DOM updates + await flushPromises(); + + // Check for default searchkey value + searchKeyEl = element.shadowRoot.querySelector('lightning-input'); + expect(searchKeyEl.value).toBe(DEFAULT_SEARCH_CRITERIA.searchKey); + + sliderEls = element.shadowRoot.querySelectorAll('lightning-slider'); + // Check for default maxPrice value + expect(sliderEls[0].value).toBe(DEFAULT_SEARCH_CRITERIA.maxPrice); + // Check for default minBedrooms value + expect(sliderEls[1].value).toBe(DEFAULT_SEARCH_CRITERIA.minBedrooms); + // Check for default minBathrooms value + expect(sliderEls[2].value).toBe(DEFAULT_SEARCH_CRITERIA.minBathrooms); + }); +}); diff --git a/force-app/main/default/lwc/propertyFilter/propertyFilter.html b/force-app/main/default/lwc/propertyFilter/propertyFilter.html new file mode 100644 index 0000000..29a7d22 --- /dev/null +++ b/force-app/main/default/lwc/propertyFilter/propertyFilter.html @@ -0,0 +1,42 @@ + \ No newline at end of file diff --git a/force-app/main/default/lwc/propertyFilter/propertyFilter.js b/force-app/main/default/lwc/propertyFilter/propertyFilter.js new file mode 100644 index 0000000..9867ec1 --- /dev/null +++ b/force-app/main/default/lwc/propertyFilter/propertyFilter.js @@ -0,0 +1,61 @@ +import { LightningElement, wire } from 'lwc'; +import { publish, MessageContext } from 'lightning/messageService'; +import FILTERSCHANGEMC from '@salesforce/messageChannel/FiltersChange__c'; + +const DELAY = 350; +const MAX_PRICE = 1200000; + +export default class PropertyFilter extends LightningElement { + searchKey = ''; + maxPrice = MAX_PRICE; + minBedrooms = 0; + minBathrooms = 0; + + @wire(MessageContext) + messageContext; + + handleReset() { + this.searchKey = ''; + this.maxPrice = MAX_PRICE; + this.minBedrooms = 0; + this.minBathrooms = 0; + this.fireChangeEvent(); + } + + handleSearchKeyChange(event) { + this.searchKey = event.detail.value; + this.fireChangeEvent(); + } + + handleMaxPriceChange(event) { + this.maxPrice = event.detail.value; + this.fireChangeEvent(); + } + + handleMinBedroomsChange(event) { + this.minBedrooms = event.detail.value; + this.fireChangeEvent(); + } + + handleMinBathroomsChange(event) { + this.minBathrooms = event.detail.value; + this.fireChangeEvent(); + } + + fireChangeEvent() { + // Debouncing this method: Do not actually fire the event as long as this function is + // being called within a delay of DELAY. This is to avoid a very large number of Apex + // method calls in components listening to this event. + window.clearTimeout(this.delayTimeout); + // eslint-disable-next-line @lwc/lwc/no-async-operation + this.delayTimeout = setTimeout(() => { + const filters = { + searchKey: this.searchKey, + maxPrice: this.maxPrice, + minBedrooms: this.minBedrooms, + minBathrooms: this.minBathrooms + }; + publish(this.messageContext, FILTERSCHANGEMC, filters); + }, DELAY); + } +} \ No newline at end of file diff --git a/force-app/main/default/lwc/propertyFilter/propertyFilter.js-meta.xml b/force-app/main/default/lwc/propertyFilter/propertyFilter.js-meta.xml new file mode 100644 index 0000000..f9ebd3a --- /dev/null +++ b/force-app/main/default/lwc/propertyFilter/propertyFilter.js-meta.xml @@ -0,0 +1,17 @@ + + + 61.0 + true + Property Filter + + lightning__AppPage + + + + + + + + + + \ No newline at end of file diff --git a/force-app/main/default/lwc/propertyListMap/__tests__/propertyListMap.test.js b/force-app/main/default/lwc/propertyListMap/__tests__/propertyListMap.test.js new file mode 100644 index 0000000..18a6ee2 --- /dev/null +++ b/force-app/main/default/lwc/propertyListMap/__tests__/propertyListMap.test.js @@ -0,0 +1,220 @@ +import { createElement } from 'lwc'; +import PropertyListMap from 'c/propertyListMap'; +import getPagedPropertyList from '@salesforce/apex/PropertyController.getPagedPropertyList'; + +import { subscribe } from 'lightning/messageService'; +import FILTERS_CHANGED from '@salesforce/messageChannel/FiltersChange__c'; + +import { ShowToastEventName } from 'lightning/platformShowToastEvent'; +import { loadScript, loadStyle } from 'lightning/platformResourceLoader'; + +// Mock getPagedPropertyList Apex wire adapter +jest.mock( + '@salesforce/apex/PropertyController.getPagedPropertyList', + () => { + const { + createApexTestWireAdapter + } = require('@salesforce/sfdx-lwc-jest'); + return { + default: createApexTestWireAdapter(jest.fn()) + }; + }, + { virtual: true } +); + +const MOCK_PROPERTIES = { + records: [ + { Id: 'id1', Location__Latitude__s: 10, Location__Longitude__s: 11 }, + { Id: 'id2', Location__Latitude__s: 20, Location__Longitude__s: 21 } + ] +}; + +// Sample error for loadScript error +const LOAD_SCRIPT_ERROR = { + body: { message: 'Mock load script error has occurred' }, + ok: false, + status: 400, + statusText: 'Bad Request' +}; + +const LEAFLET_STUB = { + map: () => ({ + setView: () => {}, + scrollWheelZoom: { + disable: () => {} + }, + removeLayer: () => {} + }), + tileLayer: () => ({ + addTo: () => {} + }), + divIcon: () => {}, + marker: () => ({ + on: () => {}, + bindTooltip: () => {} + }), + layerGroup: () => ({ + addTo: () => {} + }) +}; + +describe('c-property-list-map', () => { + beforeEach(() => { + // Inject Leaflet stub as a global 'L' variable + global.L = LEAFLET_STUB; + }); + + afterEach(() => { + // The jsdom instance is shared across test cases in a single file so reset the DOM + while (document.body.firstChild) { + document.body.removeChild(document.body.firstChild); + } + // Reset mocks so that every test run has a clean implementation + jest.resetAllMocks(); + // Clear leaflet global + global.L = undefined; + }); + + // Helper function to wait until the microtask queue is empty. + // Used when having to wait for asynchronous DOM updates. + async function flushPromises() { + return Promise.resolve(); + } + + it('registers propertyFilters subscriber during the component lifecycle', () => { + // Create component + const element = createElement('c-property-list-map', { + is: PropertyListMap + }); + document.body.appendChild(element); + + // Validate if subscriber got registered after connected to the DOM + expect(subscribe).toHaveBeenCalled(); + expect(subscribe.mock.calls[0][1]).toBe(FILTERS_CHANGED); + }); + + it('loads the leaflet javascript and css static resources', () => { + // Create component + const element = createElement('c-property-list-map', { + is: PropertyListMap + }); + document.body.appendChild(element); + + // Validation that the loadScript and loadStyle promises + // are called once. + expect(loadScript.mock.calls.length).toBe(1); + expect(loadStyle.mock.calls.length).toBe(1); + + // Validation that the JS and CSS files are passed as parameters. + expect(loadScript.mock.calls[0][1]).toEqual('leafletjs/leaflet.js'); + expect(loadStyle.mock.calls[0][1]).toEqual('leafletjs/leaflet.css'); + }); + + it('fires a toast event if the static resource cannot be loaded', async () => { + loadScript.mockRejectedValue(LOAD_SCRIPT_ERROR); + + // Create component + const element = createElement('c-property-list-map', { + is: PropertyListMap + }); + document.body.appendChild(element); + + // Mock handler for toast event + const handler = jest.fn(); + // Add event listener to catch toast event + element.addEventListener(ShowToastEventName, handler); + + // Wait for any asynchronous DOM updates + // We wait twice here in order to ensure that style and script are loaded + await flushPromises(); + await flushPromises(); + + // Check if toast event has been fired + expect(handler).toHaveBeenCalled(); + expect(handler.mock.calls[0][0].detail.title).toBe( + 'Error while loading Leaflet' + ); + expect(handler.mock.calls[0][0].detail.variant).toBe('error'); + }); + + it('fires a toast event when properties cannot be retrieved', async () => { + // Create component + const element = createElement('c-property-list-map', { + is: PropertyListMap + }); + document.body.appendChild(element); + + // Mock handler for toast event + const handler = jest.fn(); + // Add event listener to catch toast event + element.addEventListener(ShowToastEventName, handler); + + // Emit error from @wire + getPagedPropertyList.error(); + + // Wait for any asynchronous DOM updates + await flushPromises(); + + // Check if toast event has been fired + expect(handler).toHaveBeenCalled(); + expect(handler.mock.calls[0][0].detail.title).toBe( + 'Error loading properties' + ); + expect(handler.mock.calls[0][0].detail.variant).toBe('error'); + }); + + it('updates map when properties are received', async () => { + // Mock leaflet and add it as a global 'L' variable + const markerMock = jest.fn(() => ({ + on: () => {}, + bindTooltip: () => {} + })); + const layerGroupAddToMock = jest.fn(); + const leafletMock = { + map: () => ({ + setView: () => {}, + scrollWheelZoom: { + disable: () => {} + }, + removeLayer: () => {} + }), + tileLayer: () => ({ + addTo: () => {} + }), + divIcon: () => {}, + marker: markerMock, + layerGroup: () => ({ + addTo: layerGroupAddToMock + }) + }; + global.L = leafletMock; + + // Create component + const element = createElement('c-property-list-map', { + is: PropertyListMap + }); + document.body.appendChild(element); + + // Wait for any asynchronous DOM updates + await flushPromises(); + + // Emit mock properties + getPagedPropertyList.emit(MOCK_PROPERTIES); + + // Wait for any asynchronous DOM updates + await flushPromises(); + + // Check that markers are set up with property data + expect(markerMock).toHaveBeenCalledTimes( + MOCK_PROPERTIES.records.length + ); + MOCK_PROPERTIES.records.forEach((property, index) => { + expect(markerMock.mock.calls[index][0]).toStrictEqual([ + MOCK_PROPERTIES.records[index].Location__Latitude__s, + MOCK_PROPERTIES.records[index].Location__Longitude__s + ]); + }); + // Check that layer is added to map + expect(layerGroupAddToMock).toHaveBeenCalled(); + }); +}); diff --git a/force-app/main/default/lwc/propertyListMap/propertyListMap.css b/force-app/main/default/lwc/propertyListMap/propertyListMap.css new file mode 100644 index 0000000..1126d1a --- /dev/null +++ b/force-app/main/default/lwc/propertyListMap/propertyListMap.css @@ -0,0 +1,34 @@ +.map { + height: 550px; +} + +.tooltip-picture { + position: relative; + width: 150px; + height: 150px; + background-size: cover; + background-position: center; + background-repeat: no-repeat; +} + +.tooltip-picture .lower-third { + position: absolute; + /* @sldsValidatorIgnore */ + bottom: 0; + /* @sldsValidatorIgnore */ + left: 0; + /* @sldsValidatorIgnore */ + right: 0; + background-color: rgba(0, 0, 0, 0.5); + color: white; + padding: 0.15rem; +} + +.lower-third h1 { + font-weight: bold; + /* @sldsValidatorIgnore */ + white-space: nowrap; + overflow: hidden; + /* @sldsValidatorIgnore */ + text-overflow: ellipsis; +} \ No newline at end of file diff --git a/force-app/main/default/lwc/propertyListMap/propertyListMap.html b/force-app/main/default/lwc/propertyListMap/propertyListMap.html new file mode 100644 index 0000000..1dcaa61 --- /dev/null +++ b/force-app/main/default/lwc/propertyListMap/propertyListMap.html @@ -0,0 +1,3 @@ + \ No newline at end of file diff --git a/force-app/main/default/lwc/propertyListMap/propertyListMap.js b/force-app/main/default/lwc/propertyListMap/propertyListMap.js new file mode 100644 index 0000000..6fde1a5 --- /dev/null +++ b/force-app/main/default/lwc/propertyListMap/propertyListMap.js @@ -0,0 +1,170 @@ +/* global L */ +import { LightningElement, wire } from 'lwc'; +import { publish, subscribe, unsubscribe, MessageContext } from 'lightning/messageService'; +import FILTERS_CHANGED from '@salesforce/messageChannel/FiltersChange__c'; +import PROPERTY_SELECTED from '@salesforce/messageChannel/PropertySelected__c'; +import { ShowToastEvent } from 'lightning/platformShowToastEvent'; +import { loadScript, loadStyle } from 'lightning/platformResourceLoader'; +import LEAFLET from '@salesforce/resourceUrl/leafletjs'; +import getPagedPropertyList from '@salesforce/apex/PropertyController.getPagedPropertyList'; + +const LEAFLET_NOT_LOADED = 0; +const LEAFLET_LOADING = 1; +const LEAFLET_READY = 2; + +export default class PropertyListMap extends LightningElement { + properties = []; + + // Map + leafletState = LEAFLET_NOT_LOADED; + map; + propertyLayer; + + // Filters + searchKey = ''; + maxPrice = null; + minBedrooms = null; + minBathrooms = null; + pageNumber = null; + pageSize = null; + + @wire(MessageContext) + messageContext; + + @wire(getPagedPropertyList, { + searchKey: '$searchKey', + maxPrice: '$maxPrice', + minBedrooms: '$minBedrooms', + minBathrooms: '$minBathrooms', + pageSize: '$pageSize', + pageNumber: '$pageNumber' + }) + wiredProperties({ error, data }) { + if (data) { + this.properties = data.records; + // Display properties on map + this.displayProperties(); + } else if (error) { + this.properties = []; + this.dispatchEvent( + new ShowToastEvent({ + title: 'Error loading properties', + message: error.message, + variant: 'error' + }) + ); + } + } + + connectedCallback() { + this.subscription = subscribe(this.messageContext, FILTERS_CHANGED, (message) => { + this.handleFilterChange(message); + }); + } + + disconnectedCallback() { + unsubscribe(this.subscription); + this.subscription = null; + } + + async renderedCallback() { + if (this.leafletState === LEAFLET_NOT_LOADED) { + await this.initializeLeaflet(); + } + } + + async initializeLeaflet() { + try { + // Leaflet is loading + this.leafletState = LEAFLET_LOADING; + + // Load resource files + await Promise.all([loadScript(this, `${LEAFLET}/leaflet.js`), loadStyle(this, `${LEAFLET}/leaflet.css`)]); + + // Configure map + const mapElement = this.template.querySelector('.map'); + this.map = L.map(mapElement, { + zoomControl: true, + tap: false + // eslint-disable-next-line no-magic-numbers + }); + this.map.setView([42.356045, -71.08565], 13); + this.map.scrollWheelZoom.disable(); + L.tileLayer('https://tile.openstreetmap.org/{z}/{x}/{y}.png', { + maxZoom: 19, + attribution: '© OpenStreetMap' + }).addTo(this.map); + + // Leaflet is ready + this.leafletState = LEAFLET_READY; + + // Display properties + this.displayProperties(); + } catch (error) { + const message = error.message || error.body.message; + this.dispatchEvent( + new ShowToastEvent({ + title: 'Error while loading Leaflet', + message, + variant: 'error' + }) + ); + } + } + + displayProperties() { + // Stop if leaflet isn't ready yet + if (this.leafletState !== LEAFLET_READY) { + return; + } + + // Remove previous property layer form map if it exits + if (this.propertyLayer) { + this.map.removeLayer(this.propertyLayer); + } + + // Prepare property icon + const icon = L.divIcon({ + className: 'my-div-icon', + html: '' + }); + + // Prepare click handler for property marker + const markerClickHandler = (event) => { + // Send message using the Lightning Message Service + const message = { propertyId: event.target.propertyId }; + publish(this.messageContext, PROPERTY_SELECTED, message); + }; + + // Prepare property markers + const markers = this.properties.map((property) => { + const latLng = [property.Hutte__Location__Latitude__s, property.Hutte__Location__Longitude__s]; + const tooltipMarkup = this.getTooltipMarkup(property); + const marker = L.marker(latLng, { icon }); + marker.propertyId = property.Id; + marker.on('click', markerClickHandler); + marker.bindTooltip(tooltipMarkup, { offset: [45, -40] }); + return marker; + }); + + // Create a layer with property markers and add it to map + this.propertyLayer = L.layerGroup(markers); + this.propertyLayer.addTo(this.map); + } + + handleFilterChange(filters) { + this.searchKey = filters.searchKey; + this.maxPrice = filters.maxPrice; + this.minBedrooms = filters.minBedrooms; + this.minBathrooms = filters.minBathrooms; + } + + getTooltipMarkup(property) { + return `
+
+

${property.Name}

+

Beds: ${property.Hutte__Beds__c} - Baths: ${property.Hutte__Baths__c}

+
+
`; + } +} \ No newline at end of file diff --git a/force-app/main/default/lwc/propertyListMap/propertyListMap.js-meta.xml b/force-app/main/default/lwc/propertyListMap/propertyListMap.js-meta.xml new file mode 100644 index 0000000..3553aa6 --- /dev/null +++ b/force-app/main/default/lwc/propertyListMap/propertyListMap.js-meta.xml @@ -0,0 +1,9 @@ + + + 61.0 + true + Property List Map + + lightning__AppPage + + \ No newline at end of file diff --git a/force-app/main/default/lwc/propertyLocation/__tests__/data/getRecord.json b/force-app/main/default/lwc/propertyLocation/__tests__/data/getRecord.json new file mode 100644 index 0000000..2aa3814 --- /dev/null +++ b/force-app/main/default/lwc/propertyLocation/__tests__/data/getRecord.json @@ -0,0 +1,20 @@ +{ + "apiName": "Property__c", + "childRelationships": {}, + "id": "a015I000002taYUQAY", + "lastModifiedById": "0054I000001RjtIQAS", + "lastModifiedDate": "2020-06-09T07:48:54.000Z", + "recordTypeId": "012000000000000AAA", + "recordTypeInfo": null, + "systemModstamp": "2020-06-09T07:48:54.000Z", + "fields": { + "Hutte__Location__Latitude__s": { + "displayValue": "37.751", + "value": "37.751" + }, + "Hutte__Location__Longitude__s": { + "displayValue": "-97.822", + "value": "-97.822" + } + } +} diff --git a/force-app/main/default/lwc/propertyLocation/__tests__/propertyLocation.test.js b/force-app/main/default/lwc/propertyLocation/__tests__/propertyLocation.test.js new file mode 100644 index 0000000..ca297c7 --- /dev/null +++ b/force-app/main/default/lwc/propertyLocation/__tests__/propertyLocation.test.js @@ -0,0 +1,135 @@ +import { createElement } from 'lwc'; +import PropertyLocation from 'c/propertyLocation'; +import { getRecord } from 'lightning/uiRecordApi'; +import { setDeviceLocationServiceAvailable } from 'lightning/mobileCapabilities'; +import { mockGeolocation } from '../../../../../test/jest-mocks/global/navigator'; + +// Realistic property record +const mockPropertyRecord = require('./data/getRecord.json'); + +const checkDistanceCalculation = (element) => { + const latitudeEl = element.shadowRoot.querySelector( + 'div.location .latitude' + ); + expect(latitudeEl).not.toBe(null); + const longitudeEl = element.shadowRoot.querySelector( + 'div.location .longitude' + ); + expect(longitudeEl).not.toBe(null); + const formattedNumberEl = element.shadowRoot.querySelector( + 'div.location lightning-formatted-number' + ); + expect(formattedNumberEl).not.toBe(null); + + // Compare with coordinates in mobileCapabilities.js mock + expect(latitudeEl.textContent.trim()).toBe('42.361145'); + expect(longitudeEl.textContent.trim()).toBe('-71.057083'); + // Distance between mocked property and mocked location + expect(formattedNumberEl.value).toBe(1444.43371701009); +}; + +describe('c-property-location', () => { + afterEach(() => { + // The jsdom instance is shared across test cases in a single file so reset the DOM + while (document.body.firstChild) { + document.body.removeChild(document.body.firstChild); + } + jest.clearAllMocks(); + }); + + // Helper function to wait until the microtask queue is empty. + // Used when having to wait for asynchronous DOM updates. + async function flushPromises() { + return Promise.resolve(); + } + + it('renders an error panel when no location services are available', async () => { + const element = createElement('c-property-location', { + is: PropertyLocation + }); + + document.body.appendChild(element); + + // Wait for any asynchronous DOM updates + await flushPromises(); + + const panelEl = element.shadowRoot.querySelector('c-error-panel'); + expect(panelEl).not.toBeNull(); + }); + + it('renders an error panel when getRecord returns an error', async () => { + const element = createElement('c-property-location', { + is: PropertyLocation + }); + + document.body.appendChild(element); + + // Simulate error + getRecord.error(); + + // Wait for any asynchronous DOM updates + await flushPromises(); + + const panelEl = element.shadowRoot.querySelector('c-error-panel'); + expect(panelEl).not.toBeNull(); + }); + + // eslint-disable-next-line jest/expect-expect + it('renders coordinates and distance when browser location is available', async () => { + // Simulate browser location + global.navigator.geolocation = mockGeolocation; + + const element = createElement('c-property-location', { + is: PropertyLocation + }); + element.recordId = mockPropertyRecord.id; + document.body.appendChild(element); + + // Simulate property selection + getRecord.emit(mockPropertyRecord); + + // Wait for any asynchronous DOM updates + await flushPromises(); + + checkDistanceCalculation(element); + }); + + // eslint-disable-next-line jest/expect-expect + it('renders coordinates and distance when device location is available', async () => { + // Simulate device location is available + setDeviceLocationServiceAvailable(true); + + const element = createElement('c-property-location', { + is: PropertyLocation + }); + element.recordId = mockPropertyRecord.id; + document.body.appendChild(element); + + // Simulate property selection + getRecord.emit(mockPropertyRecord); + + // Wait for any asynchronous DOM updates + await flushPromises(); + + checkDistanceCalculation(element); + }); + + it('is accessible when panel is shown', async () => { + // Simulate device location is available + setDeviceLocationServiceAvailable(true); + + const element = createElement('c-property-location', { + is: PropertyLocation + }); + element.recordId = mockPropertyRecord.id; + document.body.appendChild(element); + + // Simulate property selection + getRecord.emit(mockPropertyRecord); + + // Wait for any asynchronous DOM updates + await flushPromises(); + + await expect(element).toBeAccessible(); + }); +}); diff --git a/force-app/main/default/lwc/propertyLocation/propertyLocation.html b/force-app/main/default/lwc/propertyLocation/propertyLocation.html new file mode 100644 index 0000000..e14e416 --- /dev/null +++ b/force-app/main/default/lwc/propertyLocation/propertyLocation.html @@ -0,0 +1,38 @@ + \ No newline at end of file diff --git a/force-app/main/default/lwc/propertyLocation/propertyLocation.js b/force-app/main/default/lwc/propertyLocation/propertyLocation.js new file mode 100644 index 0000000..cd1a5fd --- /dev/null +++ b/force-app/main/default/lwc/propertyLocation/propertyLocation.js @@ -0,0 +1,85 @@ +import { LightningElement, wire, api } from 'lwc'; +import { getLocationService } from 'lightning/mobileCapabilities'; +import { getRecord, getFieldValue } from 'lightning/uiRecordApi'; + +// Using hardcoded fields due to LWC bug +const LATITUDE_FIELD = 'Hutte__Property__c.Hutte__Location__Latitude__s'; +const LONGITUDE_FIELD = 'Hutte__Property__c.Hutte__Location__Longitude__s'; + +const fields = [LATITUDE_FIELD, LONGITUDE_FIELD]; + +export default class PropertyLocation extends LightningElement { + error; + deviceLocationService; + distance; + location; + @api recordId; + + @wire(getRecord, { recordId: '$recordId', fields }) + wiredProperty({ data, error }) { + if (data) { + this.property = data; + this.calculateDistance(); + } else if (error) { + this.error = error; + this.property = undefined; + } + } + + async connectedCallback() { + this.deviceLocationService = getLocationService(); + if (this.deviceLocationService.isAvailable()) { + // Running on the Salesforce mobile app on a device + await this.calculateLocationFromMobileDevice(); + } else if (navigator.geolocation) { + // Running on a browser + this.calculateLocationFromBrowser(); + } else { + this.error = { message: 'No location services available' }; + } + } + + async calculateLocationFromMobileDevice() { + try { + this.location = await this.deviceLocationService.getCurrentPosition({ + enableHighAccuracy: true + }); + this.calculateDistance(); + } catch (error) { + this.error = error; + } + } + + calculateLocationFromBrowser() { + navigator.geolocation.getCurrentPosition( + (result) => { + this.location = result; + this.calculateDistance(); + }, + (error) => { + this.error = error; + } + ); + } + + calculateDistance() { + if (this.location && this.property) { + const latitude1 = this.location.coords.latitude; + const latitude2 = getFieldValue(this.property, LATITUDE_FIELD); + const longitude1 = this.location.coords.longitude; + const longitude2 = getFieldValue(this.property, LONGITUDE_FIELD); + + // Haversine formula + const deg2rad = (deg) => (deg * Math.PI) / 180.0; + const earthRadius = 6371; // Radius of the earth in km + const dLat = deg2rad(latitude2 - latitude1); // deg2rad below + const dLon = deg2rad(longitude2 - longitude1); + const a = + Math.sin(dLat / 2) * Math.sin(dLat / 2) + + Math.cos(deg2rad(latitude1)) * Math.cos(deg2rad(latitude2)) * Math.sin(dLon / 2) * Math.sin(dLon / 2); + const c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a)); + const d = earthRadius * c; + this.distance = d / 1.609344; + } + } +} \ No newline at end of file diff --git a/force-app/main/default/lwc/propertyLocation/propertyLocation.js-meta.xml b/force-app/main/default/lwc/propertyLocation/propertyLocation.js-meta.xml new file mode 100644 index 0000000..8b7c715 --- /dev/null +++ b/force-app/main/default/lwc/propertyLocation/propertyLocation.js-meta.xml @@ -0,0 +1,20 @@ + + + 61.0 + true + Property Location + + lightning__RecordPage + + + + + Property__c + + + + + + + + \ No newline at end of file diff --git a/force-app/main/default/lwc/propertyMap/__tests__/data/propertyRecord.json b/force-app/main/default/lwc/propertyMap/__tests__/data/propertyRecord.json new file mode 100644 index 0000000..40fa1ce --- /dev/null +++ b/force-app/main/default/lwc/propertyMap/__tests__/data/propertyRecord.json @@ -0,0 +1,26 @@ +{ + "apiName": "Property__c", + "fields": { + "Name": { + "displayValue": null, + "value": "Stunning Colonial" + }, + "Address__c": { + "displayValue": null, + "value": "127 Endicott St" + }, + "City__c": { + "displayValue": null, + "value": "Boston" + }, + "Hutte__Location__Latitude__s": { + "displayValue": null, + "value": "10" + }, + "Hutte__Location__Longitude__s": { + "displayValue": null, + "value": "10" + } + }, + "id": "a013h000009HEM7AAO" +} diff --git a/force-app/main/default/lwc/propertyMap/__tests__/propertyMap.test.js b/force-app/main/default/lwc/propertyMap/__tests__/propertyMap.test.js new file mode 100644 index 0000000..94407c5 --- /dev/null +++ b/force-app/main/default/lwc/propertyMap/__tests__/propertyMap.test.js @@ -0,0 +1,96 @@ +import { createElement } from 'lwc'; +import PropertyMap from 'c/propertyMap'; +import { getRecord } from 'lightning/uiRecordApi'; + +// Realistic property record +const mockPropertyRecord = require('./data/propertyRecord.json'); +const EXPECTED_MAP_MARKERS = [ + { + location: { + Latitude: mockPropertyRecord.fields.Location__Latitude__s.value, + Longitude: mockPropertyRecord.fields.Location__Longitude__s.value + }, + title: `${mockPropertyRecord.fields.Name.value}`, + description: `Address: ${mockPropertyRecord.fields.Address__c.value}`, + mapIcon: { + path: 'M1472 992v480q0 26-19 45t-45 19h-384v-384h-256v384h-384q-26 0-45-19t-19-45v-480q0-1 .5-3t.5-3l575-474 575 474q1 2 1 6zm223-69l-62 74q-8 9-21 11h-3q-13 0-21-7l-692-577-692 577q-12 8-24 7-13-2-21-11l-62-74q-8-10-7-23.5t11-21.5l719-599q32-26 76-26t76 26l244 204v-195q0-14 9-23t23-9h192q14 0 23 9t9 23v408l219 182q10 8 11 21.5t-7 23.5z', + fillColor: '#f28b00', + fillOpacity: 1, + strokeWeight: 1, + scale: 0.02 + } + } +]; + +describe('c-property-map', () => { + afterEach(() => { + // The jsdom instance is shared across test cases in a single file so reset the DOM + while (document.body.firstChild) { + document.body.removeChild(document.body.firstChild); + } + jest.clearAllMocks(); + }); + + // Helper function to wait until the microtask queue is empty. + // Used when having to wait for asynchronous DOM updates. + async function flushPromises() { + return Promise.resolve(); + } + + it('renders an error panel when no property is selected', async () => { + const element = createElement('c-property-map', { + is: PropertyMap + }); + + document.body.appendChild(element); + + // Wait for any asynchronous DOM updates + await flushPromises(); + + const panelEl = element.shadowRoot.querySelector('c-error-panel'); + expect(panelEl).not.toBeNull(); + }); + + it('renders a map when a property is selected', async () => { + const element = createElement('c-property-map', { + is: PropertyMap + }); + document.body.appendChild(element); + + // Simulate property selection + getRecord.emit(mockPropertyRecord); + + // Wait for any asynchronous DOM updates + await flushPromises(); + + const mapEl = element.shadowRoot.querySelector('lightning-map'); + expect(mapEl).not.toBeNull(); + expect(mapEl.mapMarkers).toStrictEqual(EXPECTED_MAP_MARKERS); + }); + + it('is accessible when property is selected', async () => { + const element = createElement('c-property-map', { + is: PropertyMap + }); + + document.body.appendChild(element); + + // Simulate property selection + getRecord.emit(mockPropertyRecord); + + // Wait for any asynchronous DOM updates + await flushPromises(); + + await expect(element).toBeAccessible(); + }); + + it('is accessible when property is not selected', async () => { + const element = createElement('c-property-map', { + is: PropertyMap + }); + + document.body.appendChild(element); + + await expect(element).toBeAccessible(); + }); +}); diff --git a/force-app/main/default/lwc/propertyMap/propertyMap.html b/force-app/main/default/lwc/propertyMap/propertyMap.html new file mode 100644 index 0000000..3b5aa91 --- /dev/null +++ b/force-app/main/default/lwc/propertyMap/propertyMap.html @@ -0,0 +1,21 @@ + \ No newline at end of file diff --git a/force-app/main/default/lwc/propertyMap/propertyMap.js b/force-app/main/default/lwc/propertyMap/propertyMap.js new file mode 100644 index 0000000..c2d2f9a --- /dev/null +++ b/force-app/main/default/lwc/propertyMap/propertyMap.js @@ -0,0 +1,78 @@ +import { LightningElement, api, wire } from 'lwc'; +import { getRecord } from 'lightning/uiRecordApi'; +import { subscribe, unsubscribe, MessageContext } from 'lightning/messageService'; +import PROPERTYSELECTEDMC from '@salesforce/messageChannel/PropertySelected__c'; + +const fields = [ + 'Hutte__Property__c.Name', + 'Hutte__Property__c.Hutte__Address__c', + 'Hutte__Property__c.Hutte__City__c', + 'Hutte__Property__c.Hutte__Location__Latitude__s', + 'Hutte__Property__c.Hutte__Location__Longitude__s' +]; + +export default class PropertyMap extends LightningElement { + address; + error; + markers; + propertyId; + subscription = null; + zoomLevel = 14; + + @wire(MessageContext) + messageContext; + + @wire(getRecord, { recordId: '$propertyId', fields }) + wiredRecord({ error, data }) { + if (data) { + this.error = undefined; + const property = data.fields; + this.address = `${property.Hutte__Address__c.value}, ${property.Hutte__City__c.value}`; + this.markers = [ + { + location: { + Latitude: property.Hutte__Location__Latitude__s.value, + Longitude: property.Hutte__Location__Longitude__s.value + }, + title: `${property.Name.value}`, + description: `Address: ${property.Hutte__Address__c.value}`, + mapIcon: { + path: 'M1472 992v480q0 26-19 45t-45 19h-384v-384h-256v384h-384q-26 0-45-19t-19-45v-480q0-1 .5-3t.5-3l575-474 575 474q1 2 1 6zm223-69l-62 74q-8 9-21 11h-3q-13 0-21-7l-692-577-692 577q-12 8-24 7-13-2-21-11l-62-74q-8-10-7-23.5t11-21.5l719-599q32-26 76-26t76 26l244 204v-195q0-14 9-23t23-9h192q14 0 23 9t9 23v408l219 182q10 8 11 21.5t-7 23.5z', + fillColor: '#f28b00', + fillOpacity: 1, + strokeWeight: 1, + scale: 0.02 + } + } + ]; + } else if (error) { + this.error = error; + this.address = undefined; + this.markers = []; + } + } + + @api + get recordId() { + return this.propertyId; + } + + set recordId(propertyId) { + this.propertyId = propertyId; + } + + connectedCallback() { + this.subscription = subscribe(this.messageContext, PROPERTYSELECTEDMC, (message) => { + this.handlePropertySelected(message); + }); + } + + disconnectedCallback() { + unsubscribe(this.subscription); + this.subscription = null; + } + + handlePropertySelected(message) { + this.propertyId = message.propertyId; + } +} \ No newline at end of file diff --git a/force-app/main/default/lwc/propertyMap/propertyMap.js-meta.xml b/force-app/main/default/lwc/propertyMap/propertyMap.js-meta.xml new file mode 100644 index 0000000..cb1c043 --- /dev/null +++ b/force-app/main/default/lwc/propertyMap/propertyMap.js-meta.xml @@ -0,0 +1,27 @@ + + + 61.0 + true + Property Map + + lightning__AppPage + lightning__RecordPage + + + + + + + + + + + Property__c + + + + + + + + \ No newline at end of file diff --git a/force-app/main/default/lwc/propertySummary/__tests__/data/getRecord.json b/force-app/main/default/lwc/propertySummary/__tests__/data/getRecord.json new file mode 100644 index 0000000..efe808d --- /dev/null +++ b/force-app/main/default/lwc/propertySummary/__tests__/data/getRecord.json @@ -0,0 +1,20 @@ +{ + "apiName": "Property__c", + "childRelationships": {}, + "id": "a015I000002taYUQAY", + "lastModifiedById": "0054I000001RjtIQAS", + "lastModifiedDate": "2020-06-09T07:48:54.000Z", + "recordTypeId": "012000000000000AAA", + "recordTypeInfo": null, + "systemModstamp": "2020-06-09T07:48:54.000Z", + "fields": { + "Date_Listed__c": { + "displayValue": "30/5/2020", + "value": "2020-05-30" + }, + "Days_On_Market__c": { + "displayValue": null, + "value": 18 + } + } +} diff --git a/force-app/main/default/lwc/propertySummary/__tests__/propertySummary.test.js b/force-app/main/default/lwc/propertySummary/__tests__/propertySummary.test.js new file mode 100644 index 0000000..0b7f792 --- /dev/null +++ b/force-app/main/default/lwc/propertySummary/__tests__/propertySummary.test.js @@ -0,0 +1,99 @@ +import { createElement } from 'lwc'; +import PropertySummary from 'c/propertySummary'; +import { getRecord } from 'lightning/uiRecordApi'; + +// Realistic property record +const mockPropertyRecord = require('./data/getRecord.json'); + +describe('c-property-summary', () => { + afterEach(() => { + // The jsdom instance is shared across test cases in a single file so reset the DOM + while (document.body.firstChild) { + document.body.removeChild(document.body.firstChild); + } + jest.clearAllMocks(); + }); + + // Helper function to wait until the microtask queue is empty. + // Used when having to wait for asynchronous DOM updates. + async function flushPromises() { + return Promise.resolve(); + } + + it('renders an error panel when no property is selected', async () => { + const element = createElement('c-property-summary', { + is: PropertySummary + }); + + document.body.appendChild(element); + + // Wait for any asynchronous DOM updates + await flushPromises(); + + const panelEl = element.shadowRoot.querySelector('c-error-panel'); + expect(panelEl).not.toBeNull(); + }); + + it('renders an error panel when getRecord returns an error', async () => { + const element = createElement('c-property-summary', { + is: PropertySummary + }); + + document.body.appendChild(element); + + // Simulate error + getRecord.error(); + + // Wait for any asynchronous DOM updates + await flushPromises(); + + const panelEl = element.shadowRoot.querySelector('c-error-panel'); + expect(panelEl).not.toBeNull(); + }); + + it('renders a lightning-record-form when a property is selected', async () => { + const element = createElement('c-property-summary', { + is: PropertySummary + }); + element.recordId = mockPropertyRecord.id; + document.body.appendChild(element); + + // Simulate property selection + getRecord.emit(mockPropertyRecord); + + // Wait for any asynchronous DOM updates + await flushPromises(); + + const formEl = element.shadowRoot.querySelector( + 'lightning-record-form' + ); + expect(formEl).not.toBeNull(); + expect(formEl.recordId).toStrictEqual(mockPropertyRecord.id); + }); + + it('is accessible when property is selected', async () => { + const element = createElement('c-property-summary', { + is: PropertySummary + }); + + document.body.appendChild(element); + + // Simulate property selection + getRecord.emit(mockPropertyRecord); + + // Wait for any asynchronous DOM updates + await flushPromises(); + + await expect(element).toBeAccessible(); + }); + + it('is accessible when property is not selected', async () => { + const element = createElement('c-property-summary', { + is: PropertySummary + }); + + document.body.appendChild(element); + + await expect(element).toBeAccessible(); + }); +}); diff --git a/force-app/main/default/lwc/propertySummary/propertySummary.html b/force-app/main/default/lwc/propertySummary/propertySummary.html new file mode 100644 index 0000000..0f9ac71 --- /dev/null +++ b/force-app/main/default/lwc/propertySummary/propertySummary.html @@ -0,0 +1,39 @@ + \ No newline at end of file diff --git a/force-app/main/default/lwc/propertySummary/propertySummary.js b/force-app/main/default/lwc/propertySummary/propertySummary.js new file mode 100644 index 0000000..cb73bed --- /dev/null +++ b/force-app/main/default/lwc/propertySummary/propertySummary.js @@ -0,0 +1,73 @@ +import { LightningElement, api, wire } from 'lwc'; +import { getRecord, getFieldValue } from 'lightning/uiRecordApi'; +import { NavigationMixin } from 'lightning/navigation'; +import { subscribe, unsubscribe, MessageContext } from 'lightning/messageService'; +import PROPERTYSELECTEDMC from '@salesforce/messageChannel/PropertySelected__c'; +import NAME_FIELD from '@salesforce/schema/Property__c.Name'; +import BED_FIELD from '@salesforce/schema/Property__c.Beds__c'; +import BATH_FIELD from '@salesforce/schema/Property__c.Baths__c'; +import PRICE_FIELD from '@salesforce/schema/Property__c.Price__c'; +import BROKER_FIELD from '@salesforce/schema/Property__c.Broker__c'; +import PICTURE_FIELD from '@salesforce/schema/Property__c.Picture__c'; + +export default class PropertySummary extends NavigationMixin(LightningElement) { + propertyId; + propertyFields = [BED_FIELD, BATH_FIELD, PRICE_FIELD, BROKER_FIELD]; + subscription = null; + + @wire(MessageContext) + messageContext; + + @wire(getRecord, { + recordId: '$propertyId', + fields: [NAME_FIELD, PICTURE_FIELD] + }) + property; + + @api + get recordId() { + return this.propertyId; + } + + set recordId(propertyId) { + this.propertyId = propertyId; + } + + get hasNoPropertyId() { + return this.propertyId === undefined; + } + + get propertyName() { + return getFieldValue(this.property.data, NAME_FIELD); + } + + get pictureURL() { + return getFieldValue(this.property.data, PICTURE_FIELD); + } + + connectedCallback() { + this.subscription = subscribe(this.messageContext, PROPERTYSELECTEDMC, (message) => { + this.handlePropertySelected(message); + }); + } + + disconnectedCallback() { + unsubscribe(this.subscription); + this.subscription = null; + } + + handlePropertySelected(message) { + this.propertyId = message.propertyId; + } + + handleNavigateToRecord() { + this[NavigationMixin.Navigate]({ + type: 'standard__recordPage', + attributes: { + recordId: this.propertyId, + objectApiName: 'Hutte__Property__c', + actionName: 'view' + } + }); + } +} \ No newline at end of file diff --git a/force-app/main/default/lwc/propertySummary/propertySummary.js-meta.xml b/force-app/main/default/lwc/propertySummary/propertySummary.js-meta.xml new file mode 100644 index 0000000..c4aa467 --- /dev/null +++ b/force-app/main/default/lwc/propertySummary/propertySummary.js-meta.xml @@ -0,0 +1,27 @@ + + + 61.0 + true + Property Summary + + lightning__AppPage + lightning__RecordPage + + + + + + + + + + + Property__c + + + + + + + + \ No newline at end of file diff --git a/force-app/main/default/lwc/propertyTile/__tests__/propertyTile.small.test.js b/force-app/main/default/lwc/propertyTile/__tests__/propertyTile.small.test.js new file mode 100644 index 0000000..440d877 --- /dev/null +++ b/force-app/main/default/lwc/propertyTile/__tests__/propertyTile.small.test.js @@ -0,0 +1,66 @@ +import { createElement } from 'lwc'; +import PropertyTile from 'c/propertyTile'; +import { getNavigateCalledWith } from 'lightning/navigation'; + +const PROPERTY = { + City__c: 'Some City', + Beds__c: '3', + Baths__c: '1', + Price__c: '450000', + Thumbnail__c: 'some-property.jpg', + Id: '12345' +}; + +// Mock small formFactor -> Currently this test resides +// in a different file because there is no way to reassign the mock dynamically +jest.mock( + '@salesforce/client/formFactor', + () => { + return { default: 'Small' }; + }, + { virtual: true } +); + +describe('c-property-tile', () => { + afterEach(() => { + // The jsdom instance is shared across test cases in a single file so reset the DOM + while (document.body.firstChild) { + document.body.removeChild(document.body.firstChild); + } + }); + + // Helper function to wait until the microtask queue is empty. + // Used when having to wait for asynchronous DOM updates. + async function flushPromises() { + return Promise.resolve(); + } + + it('Navigates to property record page on click for Small formFactor', async () => { + const NAV_TYPE = 'standard__recordPage'; + const NAV_ACTION_NAME = 'view'; + const NAV_OBJECT_API_NAME = 'Property__c'; + + const element = createElement('c-property-tile', { + is: PropertyTile + }); + element.property = PROPERTY; + document.body.appendChild(element); + + const anchorEl = element.shadowRoot.querySelector('a'); + anchorEl.click(); + + // Wait for any asynchronous DOM updates + await flushPromises(); + + // Get data the NavigationMixin was called with + const { pageReference } = getNavigateCalledWith(); + + // Confirm redirection to expected property record + expect(pageReference.type).toBe(NAV_TYPE); + expect(pageReference.attributes.actionName).toBe(NAV_ACTION_NAME); + expect(pageReference.attributes.objectApiName).toBe( + NAV_OBJECT_API_NAME + ); + expect(pageReference.attributes.recordId).toBe(PROPERTY.Id); + }); +}); diff --git a/force-app/main/default/lwc/propertyTile/__tests__/propertyTile.test.js b/force-app/main/default/lwc/propertyTile/__tests__/propertyTile.test.js new file mode 100644 index 0000000..9bf9f29 --- /dev/null +++ b/force-app/main/default/lwc/propertyTile/__tests__/propertyTile.test.js @@ -0,0 +1,97 @@ +import { createElement } from 'lwc'; +import PropertyTile from 'c/propertyTile'; + +const PROPERTY = { + Name: 'My House', + City__c: 'Some City', + Beds__c: '3', + Baths__c: '1', + Price__c: '450000', + Thumbnail__c: 'some-property.jpg', + Id: '12345' +}; + +describe('c-property-tile', () => { + afterEach(() => { + // The jsdom instance is shared across test cases in a single file so reset the DOM + while (document.body.firstChild) { + document.body.removeChild(document.body.firstChild); + } + }); + + // Helper function to wait until the microtask queue is empty. + // Used when having to wait for asynchronous DOM updates. + async function flushPromises() { + return Promise.resolve(); + } + + it('displays a property in the tile', () => { + const element = createElement('c-property-tile', { + is: PropertyTile + }); + element.property = PROPERTY; + document.body.appendChild(element); + + const headerEl = element.shadowRoot.querySelector('.truncate'); + expect(headerEl.textContent).toBe( + `${PROPERTY.City__c} • ${PROPERTY.Name}` + ); + + const paragraphEl = element.shadowRoot.querySelector('p'); + expect(paragraphEl.textContent).toBe( + `Beds: ${PROPERTY.Beds__c} - Baths: ${PROPERTY.Baths__c}` + ); + + const priceEl = element.shadowRoot.querySelector( + 'lightning-formatted-number' + ); + expect(priceEl.value).toBe(PROPERTY.Price__c); + }); + + it('displays the correct background image in the tile', () => { + const element = createElement('c-property-tile', { + is: PropertyTile + }); + element.property = PROPERTY; + document.body.appendChild(element); + + const backgroundEl = element.shadowRoot.querySelector('.tile'); + expect(backgroundEl.style.backgroundImage).toBe( + `url(${PROPERTY.Thumbnail__c})` + ); + }); + + it('Fires the property selected event on click for non Small formFactors', async () => { + const element = createElement('c-property-tile', { + is: PropertyTile + }); + element.property = PROPERTY; + document.body.appendChild(element); + + // Mock handler for child event + const handler = jest.fn(); + element.addEventListener('selected', handler); + + const anchorEl = element.shadowRoot.querySelector('a'); + anchorEl.click(); + + // Wait for any asynchronous DOM updates + await flushPromises(); + + // Validate if event got fired + expect(handler).toHaveBeenCalled(); + const selectEvent = handler.mock.calls[0][0]; + expect(selectEvent.detail).toBe(PROPERTY.Id); + }); + + it('is accessible', async () => { + const element = createElement('c-property-tile', { + is: PropertyTile + }); + + element.property = PROPERTY; + document.body.appendChild(element); + + await expect(element).toBeAccessible(); + }); +}); diff --git a/force-app/main/default/lwc/propertyTile/propertyTile.css b/force-app/main/default/lwc/propertyTile/propertyTile.css new file mode 100644 index 0000000..8b9e0d1 --- /dev/null +++ b/force-app/main/default/lwc/propertyTile/propertyTile.css @@ -0,0 +1,26 @@ +.tile { + position: relative; + height: 220px; + background-size: cover; + background-position: center; + background-repeat: no-repeat; +} + +.lower-third { + position: absolute; + /* @sldsValidatorIgnore */ + bottom: 0; + /* @sldsValidatorIgnore */ + left: 0; + /* @sldsValidatorIgnore */ + right: 0; + background-color: rgba(0, 0, 0, 0.5); +} + +.truncate { + /* @sldsValidatorIgnore */ + white-space: nowrap; + overflow: hidden; + /* @sldsValidatorIgnore */ + text-overflow: ellipsis; +} \ No newline at end of file diff --git a/force-app/main/default/lwc/propertyTile/propertyTile.html b/force-app/main/default/lwc/propertyTile/propertyTile.html new file mode 100644 index 0000000..4b4f24c --- /dev/null +++ b/force-app/main/default/lwc/propertyTile/propertyTile.html @@ -0,0 +1,19 @@ + \ No newline at end of file diff --git a/force-app/main/default/lwc/propertyTile/propertyTile.js b/force-app/main/default/lwc/propertyTile/propertyTile.js new file mode 100644 index 0000000..a9fc6bb --- /dev/null +++ b/force-app/main/default/lwc/propertyTile/propertyTile.js @@ -0,0 +1,32 @@ +import { LightningElement, api } from 'lwc'; +import FORM_FACTOR from '@salesforce/client/formFactor'; +import { NavigationMixin } from 'lightning/navigation'; + +export default class PropertyTile extends NavigationMixin(LightningElement) { + @api property; + formFactor = FORM_FACTOR; + + handlePropertySelected() { + if (FORM_FACTOR === 'Small') { + // In Phones, navigate to property record page directly + this[NavigationMixin.Navigate]({ + type: 'standard__recordPage', + attributes: { + recordId: this.property.Id, + objectApiName: 'Hutte__Property__c', + actionName: 'view' + } + }); + } else { + // In other devices, send message to other cmps on the page + const selectedEvent = new CustomEvent('selected', { + detail: this.property.Id + }); + this.dispatchEvent(selectedEvent); + } + } + + get backgroundImageStyle() { + return `background-image:url(${this.property.Hutte__Thumbnail__c})`; + } +} \ No newline at end of file diff --git a/force-app/main/default/lwc/propertyTile/propertyTile.js-meta.xml b/force-app/main/default/lwc/propertyTile/propertyTile.js-meta.xml new file mode 100644 index 0000000..a4a5ed3 --- /dev/null +++ b/force-app/main/default/lwc/propertyTile/propertyTile.js-meta.xml @@ -0,0 +1,5 @@ + + + 61.0 + false + \ No newline at end of file diff --git a/force-app/main/default/lwc/propertyTileList/__tests__/data/getPagedPropertyList.json b/force-app/main/default/lwc/propertyTileList/__tests__/data/getPagedPropertyList.json new file mode 100644 index 0000000..2c5d2c3 --- /dev/null +++ b/force-app/main/default/lwc/propertyTileList/__tests__/data/getPagedPropertyList.json @@ -0,0 +1,106 @@ +{ + "pageNumber": 1, + "pageSize": 9, + "records": [ + { + "Id": "a012F000009ovH1QAI", + "Address__c": "127 Endicott St", + "City__c": "Boston", + "State__c": "MA", + "Description__c": "Lorem ipsum dolor sit amet", + "Price__c": 450000, + "Baths__c": 1, + "Beds__c": 3, + "Thumbnail__c": "https://s3-us-west-2.amazonaws.com/dev-or-devrl-s3-bucket/sample-apps/realty/house07sq.jpg" + }, + { + "Id": "a012F000009ovH2QAI", + "Address__c": "48 Brattle st", + "City__c": "Cambridge", + "State__c": "MA", + "Description__c": "Lorem ipsum dolor sit amet", + "Price__c": 450000, + "Baths__c": 4, + "Beds__c": 5, + "Thumbnail__c": "https://s3-us-west-2.amazonaws.com/dev-or-devrl-s3-bucket/sample-apps/realty/house10sq.jpg" + }, + { + "Id": "a012F000009ovH3QAI", + "Address__c": "121 Harborwalk", + "City__c": "Boston", + "State__c": "MA", + "Description__c": "Lorem ipsum dolor sit amet", + "Price__c": 450000, + "Baths__c": 3, + "Beds__c": 3, + "Thumbnail__c": "https://s3-us-west-2.amazonaws.com/dev-or-devrl-s3-bucket/sample-apps/realty/house09sq.jpg" + }, + { + "Id": "a012F000009ovH4QAI", + "Address__c": "640 Harrison Ave", + "City__c": "Boston", + "State__c": "MA", + "Description__c": "Lorem ipsum dolor sit amet", + "Price__c": 650000, + "Baths__c": 2, + "Beds__c": 2, + "Thumbnail__c": "https://s3-us-west-2.amazonaws.com/dev-or-devrl-s3-bucket/sample-apps/realty/house08sq.jpg" + }, + { + "Id": "a012F000009ovH5QAI", + "Address__c": "95 Gloucester St", + "City__c": "Boston", + "State__c": "MA", + "Description__c": "Lorem ipsum dolor sit amet", + "Price__c": 690000, + "Baths__c": 3, + "Beds__c": 3, + "Thumbnail__c": "https://s3-us-west-2.amazonaws.com/dev-or-devrl-s3-bucket/sample-apps/realty/house11sq.jpg" + }, + { + "Id": "a012F000009ovH0QAI", + "Address__c": "448 Hanover St", + "City__c": "Boston", + "State__c": "MA", + "Description__c": "Lorem ipsum dolor sit amet", + "Price__c": 725000, + "Baths__c": 2, + "Beds__c": 4, + "Thumbnail__c": "https://s3-us-west-2.amazonaws.com/dev-or-devrl-s3-bucket/sample-apps/realty/house06sq.jpg" + }, + { + "Id": "a012F000009ovGxQAI", + "Address__c": "72 Francis st", + "City__c": "Boston", + "State__c": "MA", + "Description__c": "Lorem ipsum dolor sit amet", + "Price__c": 825000, + "Baths__c": 4, + "Beds__c": 5, + "Thumbnail__c": "https://s3-us-west-2.amazonaws.com/dev-or-devrl-s3-bucket/sample-apps/realty/house03sq.jpg" + }, + { + "Id": "a012F000009ovH6QAI", + "Address__c": "145 Commonwealth Ave", + "City__c": "Boston", + "State__c": "MA", + "Description__c": "Lorem ipsum dolor sit amet", + "Price__c": 845000, + "Baths__c": 3, + "Beds__c": 4, + "Thumbnail__c": "https://s3-us-west-2.amazonaws.com/dev-or-devrl-s3-bucket/sample-apps/realty/house12sq.jpg" + }, + { + "Id": "a012F000009ovGzQAI", + "Address__c": "110 Baxter Street", + "City__c": "Boston", + "State__c": "MA", + "Description__c": "Lorem ipsum dolor sit amet", + "Price__c": 850000, + "Baths__c": 2, + "Beds__c": 3, + "Thumbnail__c": "https://s3-us-west-2.amazonaws.com/dev-or-devrl-s3-bucket/sample-apps/realty/house05sq.jpg" + } + ], + "totalItemCount": 12 +} diff --git a/force-app/main/default/lwc/propertyTileList/__tests__/propertyTileList.test.js b/force-app/main/default/lwc/propertyTileList/__tests__/propertyTileList.test.js new file mode 100644 index 0000000..17a8166 --- /dev/null +++ b/force-app/main/default/lwc/propertyTileList/__tests__/propertyTileList.test.js @@ -0,0 +1,134 @@ +import { createElement } from 'lwc'; +import PropertyTileList from 'c/propertyTileList'; +import getPagedPropertyList from '@salesforce/apex/PropertyController.getPagedPropertyList'; +import { publish, subscribe, MessageContext } from 'lightning/messageService'; +import FILTERSCHANGEMC from '@salesforce/messageChannel/FiltersChange__c'; +import PROPERTYSELECTEDMC from '@salesforce/messageChannel/PropertySelected__c'; + +// Realistic data with multiple records +const mockgetPagedPropertyList = require('./data/getPagedPropertyList.json'); + +// Mock getPagedPropertyList Apex wire adapter +jest.mock( + '@salesforce/apex/PropertyController.getPagedPropertyList', + () => { + const { + createApexTestWireAdapter + } = require('@salesforce/sfdx-lwc-jest'); + return { + default: createApexTestWireAdapter(jest.fn()) + }; + }, + { virtual: true } +); + +describe('c-property-tile-list', () => { + afterEach(() => { + // The jsdom instance is shared across test cases in a single file so reset the DOM + while (document.body.firstChild) { + document.body.removeChild(document.body.firstChild); + } + jest.clearAllMocks(); + }); + + // Helper function to wait until the microtask queue is empty. + // Used when having to wait for asynchronous DOM updates. + async function flushPromises() { + return Promise.resolve(); + } + + describe('@wire data', () => { + it('renders properties when data returned', async () => { + const element = createElement('c-property-tile-list', { + is: PropertyTileList + }); + document.body.appendChild(element); + + // Emit mock properties + getPagedPropertyList.emit(mockgetPagedPropertyList); + + // Wait for any asynchronous DOM updates + await flushPromises(); + + const propertyTileEls = + element.shadowRoot.querySelectorAll('c-property-tile'); + expect(propertyTileEls.length).toBe( + mockgetPagedPropertyList.records.length + ); + }); + + it('renders error panel when error returned', async () => { + const element = createElement('c-property-tile-list', { + is: PropertyTileList + }); + document.body.appendChild(element); + + // Emit error + getPagedPropertyList.error(); + + // Wait for any asynchronous DOM updates + await flushPromises(); + + const errorPanelEl = + element.shadowRoot.querySelector('c-error-panel'); + expect(errorPanelEl).not.toBeNull(); + }); + }); + + it('registers propertyFilters subscriber during the component lifecycle', () => { + const element = createElement('c-property-tile-list', { + is: PropertyTileList + }); + document.body.appendChild(element); + + // Validate if subscriber got registered after connected to the DOM + expect(subscribe).toHaveBeenCalled(); + expect(subscribe.mock.calls[0][1]).toBe(FILTERSCHANGEMC); + }); + + it('invokes getPagedPropertyList with the propertyFilters message payload value', async () => { + const element = createElement('c-property-tile-list', { + is: PropertyTileList + }); + document.body.appendChild(element); + + // Simulate pulishing a message using FILTERSCHANGEMC message channel + const messagePayload = { + searchKey: 'victorian', + maxPrice: 400000, + minBedrooms: 4, + minBathrooms: 2 + }; + publish(MessageContext, FILTERSCHANGEMC, messagePayload); + + // Wait for any asynchronous DOM updates + await flushPromises(); + + // The component subscription should cause getRecord to be invoked. + // Below we test that it is invoked with the messagePayload value + // that was published with the simulated publish invocation above. + const receivedPayload = getPagedPropertyList.getLastConfig(); + expect(receivedPayload.searchKey).toBe(messagePayload.searchKey); + expect(receivedPayload.maxPrice).toBe(messagePayload.maxPrice); + expect(receivedPayload.minBedrooms).toBe(messagePayload.minBedrooms); + expect(receivedPayload.minBathrooms).toBe(messagePayload.minBathrooms); + }); + + it('sends propertySelected event when c-property-tile selected', async () => { + const element = createElement('c-property-tile-list', { + is: PropertyTileList + }); + document.body.appendChild(element); + getPagedPropertyList.emit(mockgetPagedPropertyList); + + // Wait for any asynchronous DOM updates + await flushPromises(); + + const propertyTile = + element.shadowRoot.querySelector('c-property-tile'); + propertyTile.dispatchEvent(new CustomEvent('selected')); + expect(publish).toHaveBeenCalledWith(undefined, PROPERTYSELECTEDMC, { + propertyId: null + }); + }); +}); diff --git a/force-app/main/default/lwc/propertyTileList/propertyTileList.css b/force-app/main/default/lwc/propertyTileList/propertyTileList.css new file mode 100644 index 0000000..64ee5c6 --- /dev/null +++ b/force-app/main/default/lwc/propertyTileList/propertyTileList.css @@ -0,0 +1,7 @@ +c-property-tile { + min-width: 220px; +} + +c-property-tile:hover { + box-shadow: 4px 5px 5px #9d9fa0; +} \ No newline at end of file diff --git a/force-app/main/default/lwc/propertyTileList/propertyTileList.html b/force-app/main/default/lwc/propertyTileList/propertyTileList.html new file mode 100644 index 0000000..7d9cea9 --- /dev/null +++ b/force-app/main/default/lwc/propertyTileList/propertyTileList.html @@ -0,0 +1,32 @@ + \ No newline at end of file diff --git a/force-app/main/default/lwc/propertyTileList/propertyTileList.js b/force-app/main/default/lwc/propertyTileList/propertyTileList.js new file mode 100644 index 0000000..1ac164b --- /dev/null +++ b/force-app/main/default/lwc/propertyTileList/propertyTileList.js @@ -0,0 +1,70 @@ +import { LightningElement, wire } from 'lwc'; +import { + publish, + subscribe, + unsubscribe, + MessageContext +} from 'lightning/messageService'; +import FILTERSCHANGEMC from '@salesforce/messageChannel/FiltersChange__c'; +import PROPERTYSELECTEDMC from '@salesforce/messageChannel/PropertySelected__c'; +import getPagedPropertyList from '@salesforce/apex/PropertyController.getPagedPropertyList'; + +const PAGE_SIZE = 9; + +export default class PropertyTileList extends LightningElement { + pageNumber = 1; + pageSize = PAGE_SIZE; + + searchKey = ''; + maxPrice = 9999999; + minBedrooms = 0; + minBathrooms = 0; + + @wire(MessageContext) + messageContext; + + @wire(getPagedPropertyList, { + searchKey: '$searchKey', + maxPrice: '$maxPrice', + minBedrooms: '$minBedrooms', + minBathrooms: '$minBathrooms', + pageSize: '$pageSize', + pageNumber: '$pageNumber' + }) + properties; + + connectedCallback() { + this.subscription = subscribe( + this.messageContext, + FILTERSCHANGEMC, + (message) => { + this.handleFilterChange(message); + } + ); + } + + disconnectedCallback() { + unsubscribe(this.subscription); + this.subscription = null; + } + + handleFilterChange(filters) { + this.searchKey = filters.searchKey; + this.maxPrice = filters.maxPrice; + this.minBedrooms = filters.minBedrooms; + this.minBathrooms = filters.minBathrooms; + } + + handlePreviousPage() { + this.pageNumber = this.pageNumber - 1; + } + + handleNextPage() { + this.pageNumber = this.pageNumber + 1; + } + + handlePropertySelected(event) { + const message = { propertyId: event.detail }; + publish(this.messageContext, PROPERTYSELECTEDMC, message); + } +} \ No newline at end of file diff --git a/force-app/main/default/lwc/propertyTileList/propertyTileList.js-meta.xml b/force-app/main/default/lwc/propertyTileList/propertyTileList.js-meta.xml new file mode 100644 index 0000000..9270748 --- /dev/null +++ b/force-app/main/default/lwc/propertyTileList/propertyTileList.js-meta.xml @@ -0,0 +1,17 @@ + + + 61.0 + true + Property Tile List + + lightning__AppPage + + + + + + + + + + \ No newline at end of file diff --git a/force-app/main/default/lwc/sampleDataImporter/__tests__/sampleDataImporter.test.js b/force-app/main/default/lwc/sampleDataImporter/__tests__/sampleDataImporter.test.js new file mode 100644 index 0000000..4bbd9b0 --- /dev/null +++ b/force-app/main/default/lwc/sampleDataImporter/__tests__/sampleDataImporter.test.js @@ -0,0 +1,115 @@ +import { createElement } from 'lwc'; +import SampleDataImporter from 'c/sampleDataImporter'; +import { ShowToastEventName } from 'lightning/platformShowToastEvent'; +import importSampleData from '@salesforce/apex/SampleDataController.importSampleData'; + +// Mocking imperative Apex method call +jest.mock( + '@salesforce/apex/SampleDataController.importSampleData', + () => { + return { + default: jest.fn() + }; + }, + { virtual: true } +); + +// Sample data for imperative Apex call +const APEX_OPERATION_SUCCESS = null; + +// Sample error for imperative Apex call +const APEX_OPERATION_ERROR = { + message: 'An internal server error has occurred' +}; + +describe('c-sample-data-importer', () => { + afterEach(() => { + // The jsdom instance is shared across test cases in a single file so reset the DOM + while (document.body.firstChild) { + document.body.removeChild(document.body.firstChild); + } + + // Prevent data saved on mocks from leaking between tests + jest.clearAllMocks(); + }); + + // Helper function to wait until the microtask queue is empty. + // Used when having to wait for asynchronous DOM updates. + async function flushPromises() { + return Promise.resolve(); + } + + it('fires success event when importSampleData runs successfully', async () => { + // Assign mock value for resolved Apex promise + importSampleData.mockResolvedValue(APEX_OPERATION_SUCCESS); + + // Create initial element + const element = createElement('c-sample-data-importer', { + is: SampleDataImporter + }); + document.body.appendChild(element); + + // Mock handler for toast event + const handler = jest.fn(); + // Add event listener to catch toast event + element.addEventListener(ShowToastEventName, handler); + + // Select button for executing Apex call + const buttonEl = element.shadowRoot.querySelector('lightning-button'); + buttonEl.click(); + + // Wait for any asynchronous DOM updates + await flushPromises(); + + // Check if toast event has been fired + expect(handler).toHaveBeenCalled(); + expect(handler.mock.calls[0][0].detail.variant).toBe('success'); + expect(handler.mock.calls[0][0].detail.title).toBe('Success'); + expect(handler.mock.calls[0][0].detail.message).toBe( + 'Sample data successfully imported' + ); + }); + + it('fires error event when importSampleData runs with error', async () => { + // Assign mock value for resolved Apex promise + importSampleData.mockRejectedValue(APEX_OPERATION_ERROR); + + // Create initial element + const element = createElement('c-sample-data-importer', { + is: SampleDataImporter + }); + document.body.appendChild(element); + + // Mock handler for toast event + const handler = jest.fn(); + // Add event listener to catch toast event + element.addEventListener(ShowToastEventName, handler); + + // Select button for executing Apex call + const buttonEl = element.shadowRoot.querySelector('lightning-button'); + buttonEl.click(); + + // Wait for any asynchronous DOM updates + await flushPromises(); + + // Check if toast event has been fired + expect(handler).toHaveBeenCalled(); + expect(handler.mock.calls[0][0].detail.variant).toBe('error'); + expect(handler.mock.calls[0][0].detail.title).toBe( + 'Error while importing data' + ); + expect(handler.mock.calls[0][0].detail.message).toBe( + APEX_OPERATION_ERROR.message + ); + }); + + it('is accessible', async () => { + const element = createElement('c-sample-data-importer', { + is: SampleDataImporter + }); + + document.body.appendChild(element); + + await expect(element).toBeAccessible(); + }); +}); diff --git a/force-app/main/default/lwc/sampleDataImporter/sampleDataImporter.html b/force-app/main/default/lwc/sampleDataImporter/sampleDataImporter.html new file mode 100644 index 0000000..5c85454 --- /dev/null +++ b/force-app/main/default/lwc/sampleDataImporter/sampleDataImporter.html @@ -0,0 +1,19 @@ + \ No newline at end of file diff --git a/force-app/main/default/lwc/sampleDataImporter/sampleDataImporter.js b/force-app/main/default/lwc/sampleDataImporter/sampleDataImporter.js new file mode 100644 index 0000000..760f337 --- /dev/null +++ b/force-app/main/default/lwc/sampleDataImporter/sampleDataImporter.js @@ -0,0 +1,25 @@ +import { LightningElement } from 'lwc'; +import { ShowToastEvent } from 'lightning/platformShowToastEvent'; +import importSampleData from '@salesforce/apex/SampleDataController.importSampleData'; + +export default class SampleDataImporter extends LightningElement { + handleImportSampleData() { + importSampleData() + .then(() => { + const evt = new ShowToastEvent({ + title: 'Success', + message: 'Sample data successfully imported', + variant: 'success' + }); + this.dispatchEvent(evt); + }) + .catch((e) => { + const evt = new ShowToastEvent({ + title: 'Error while importing data', + message: e.message, + variant: 'error' + }); + this.dispatchEvent(evt); + }); + } +} \ No newline at end of file diff --git a/force-app/main/default/lwc/sampleDataImporter/sampleDataImporter.js-meta.xml b/force-app/main/default/lwc/sampleDataImporter/sampleDataImporter.js-meta.xml new file mode 100644 index 0000000..a258006 --- /dev/null +++ b/force-app/main/default/lwc/sampleDataImporter/sampleDataImporter.js-meta.xml @@ -0,0 +1,9 @@ + + + 61.0 + true + Sample Property Importer + + lightning__AppPage + + \ No newline at end of file diff --git a/force-app/main/default/messageChannels/FiltersChange.messageChannel-meta.xml b/force-app/main/default/messageChannels/FiltersChange.messageChannel-meta.xml new file mode 100644 index 0000000..332e2e4 --- /dev/null +++ b/force-app/main/default/messageChannels/FiltersChange.messageChannel-meta.xml @@ -0,0 +1,21 @@ + + + true + + Search Key + searchKey + + + Max Price + maxPrice + + + Minimum number of Bedrooms + minBedrooms + + + Minimum number of Bathrooms + minBathrooms + + Filters Change Message Channel + diff --git a/force-app/main/default/messageChannels/PropertySelected.messageChannel-meta.xml b/force-app/main/default/messageChannels/PropertySelected.messageChannel-meta.xml new file mode 100644 index 0000000..1226ff1 --- /dev/null +++ b/force-app/main/default/messageChannels/PropertySelected.messageChannel-meta.xml @@ -0,0 +1,9 @@ + + + true + + Property Id + propertyId + + Property Selected Message Channel + diff --git a/force-app/main/default/objects/Broker__c/Broker__c.object-meta.xml b/force-app/main/default/objects/Broker__c/Broker__c.object-meta.xml new file mode 100644 index 0000000..385ff44 --- /dev/null +++ b/force-app/main/default/objects/Broker__c/Broker__c.object-meta.xml @@ -0,0 +1,165 @@ + + + + Accept + Default + + + Accept + Large + Default + + + Accept + Small + Default + + + CancelEdit + Default + + + CancelEdit + Large + Default + + + CancelEdit + Small + Default + + + Clone + Default + + + Clone + Large + Default + + + Clone + Small + Default + + + Delete + Default + + + Delete + Large + Default + + + Delete + Small + Default + + + Edit + Default + + + Edit + Large + Default + + + Edit + Small + Default + + + List + Default + + + List + Large + Default + + + List + Small + Default + + + New + Default + + + New + Large + Default + + + New + Small + Default + + + SaveEdit + Default + + + SaveEdit + Large + Default + + + SaveEdit + Small + Default + + + Tab + Default + + + Tab + Large + Default + + + Tab + Small + Default + + + View + Default + + + View + Large + Default + + + View + Small + Default + + false + Broker_Compact + Deployed + false + true + false + false + false + true + true + true + true + Private + + + + Text + + Brokers + + ReadWrite + Public + diff --git a/force-app/main/default/objects/Broker__c/compactLayouts/Broker_Compact.compactLayout-meta.xml b/force-app/main/default/objects/Broker__c/compactLayouts/Broker_Compact.compactLayout-meta.xml new file mode 100644 index 0000000..1975fa1 --- /dev/null +++ b/force-app/main/default/objects/Broker__c/compactLayouts/Broker_Compact.compactLayout-meta.xml @@ -0,0 +1,10 @@ + + + Broker_Compact + Name + Title__c + Phone__c + Mobile_Phone__c + Email__c + + diff --git a/force-app/main/default/objects/Broker__c/fields/Broker_Id__c.field-meta.xml b/force-app/main/default/objects/Broker__c/fields/Broker_Id__c.field-meta.xml new file mode 100644 index 0000000..97bae1d --- /dev/null +++ b/force-app/main/default/objects/Broker__c/fields/Broker_Id__c.field-meta.xml @@ -0,0 +1,12 @@ + + + Broker_Id__c + true + + 18 + false + 0 + false + Number + false + diff --git a/force-app/main/default/objects/Broker__c/fields/Email__c.field-meta.xml b/force-app/main/default/objects/Broker__c/fields/Email__c.field-meta.xml new file mode 100644 index 0000000..45ab92b --- /dev/null +++ b/force-app/main/default/objects/Broker__c/fields/Email__c.field-meta.xml @@ -0,0 +1,11 @@ + + + Email__c + false + The email address of your broker + + false + false + Email + false + diff --git a/force-app/main/default/objects/Broker__c/fields/Mobile_Phone__c.field-meta.xml b/force-app/main/default/objects/Broker__c/fields/Mobile_Phone__c.field-meta.xml new file mode 100644 index 0000000..0f57f49 --- /dev/null +++ b/force-app/main/default/objects/Broker__c/fields/Mobile_Phone__c.field-meta.xml @@ -0,0 +1,8 @@ + + + Mobile_Phone__c + + false + false + Phone + diff --git a/force-app/main/default/objects/Broker__c/fields/Phone__c.field-meta.xml b/force-app/main/default/objects/Broker__c/fields/Phone__c.field-meta.xml new file mode 100644 index 0000000..56f9ae6 --- /dev/null +++ b/force-app/main/default/objects/Broker__c/fields/Phone__c.field-meta.xml @@ -0,0 +1,8 @@ + + + Phone__c + + false + false + Phone + diff --git a/force-app/main/default/objects/Broker__c/fields/Picture_IMG__c.field-meta.xml b/force-app/main/default/objects/Broker__c/fields/Picture_IMG__c.field-meta.xml new file mode 100644 index 0000000..1ee98c4 --- /dev/null +++ b/force-app/main/default/objects/Broker__c/fields/Picture_IMG__c.field-meta.xml @@ -0,0 +1,12 @@ + + + Picture_IMG__c + false + IMAGE( Picture__c , "picture" , 150, 150) + BlankAsZero + + false + false + Text + false + diff --git a/force-app/main/default/objects/Broker__c/fields/Picture__c.field-meta.xml b/force-app/main/default/objects/Broker__c/fields/Picture__c.field-meta.xml new file mode 100644 index 0000000..c596e64 --- /dev/null +++ b/force-app/main/default/objects/Broker__c/fields/Picture__c.field-meta.xml @@ -0,0 +1,8 @@ + + + Picture__c + + false + false + Url + diff --git a/force-app/main/default/objects/Broker__c/fields/Title__c.field-meta.xml b/force-app/main/default/objects/Broker__c/fields/Title__c.field-meta.xml new file mode 100644 index 0000000..88d88c8 --- /dev/null +++ b/force-app/main/default/objects/Broker__c/fields/Title__c.field-meta.xml @@ -0,0 +1,11 @@ + + + Title__c + false + + 30 + false + false + Text + false + diff --git a/force-app/main/default/objects/Broker__c/listViews/All.listView-meta.xml b/force-app/main/default/objects/Broker__c/listViews/All.listView-meta.xml new file mode 100644 index 0000000..f957a40 --- /dev/null +++ b/force-app/main/default/objects/Broker__c/listViews/All.listView-meta.xml @@ -0,0 +1,7 @@ + + + All + NAME + Everything + + diff --git a/force-app/main/default/objects/Property__c/Property__c.object-meta.xml b/force-app/main/default/objects/Property__c/Property__c.object-meta.xml new file mode 100644 index 0000000..9a51b3e --- /dev/null +++ b/force-app/main/default/objects/Property__c/Property__c.object-meta.xml @@ -0,0 +1,167 @@ + + + + Accept + Default + + + Accept + Large + Default + + + Accept + Small + Default + + + CancelEdit + Default + + + CancelEdit + Large + Default + + + CancelEdit + Small + Default + + + Clone + Default + + + Clone + Large + Default + + + Clone + Small + Default + + + Delete + Default + + + Delete + Large + Default + + + Delete + Small + Default + + + Edit + Default + + + Edit + Large + Default + + + Edit + Small + Default + + + List + Default + + + List + Large + Default + + + List + Small + Default + + + New + Default + + + New + Large + Default + + + New + Small + Default + + + SaveEdit + Default + + + SaveEdit + Large + Default + + + SaveEdit + Small + Default + + + Tab + Default + + + Tab + Large + Default + + + Tab + Small + Default + + + View + Default + + + View + Large + Default + + + View + Small + Default + + false + Property_Compact_Layout + Deployed + true + true + true + true + false + true + true + true + true + Private + + + + false + false + Text + + Properties + + ReadWrite + Public + diff --git a/force-app/main/default/objects/Property__c/compactLayouts/Property_Compact_Layout.compactLayout-meta.xml b/force-app/main/default/objects/Property__c/compactLayouts/Property_Compact_Layout.compactLayout-meta.xml new file mode 100644 index 0000000..bbe1071 --- /dev/null +++ b/force-app/main/default/objects/Property__c/compactLayouts/Property_Compact_Layout.compactLayout-meta.xml @@ -0,0 +1,10 @@ + + + Property_Compact_Layout + Name + City__c + Price__c + Beds__c + Baths__c + + diff --git a/force-app/main/default/objects/Property__c/fields/Address__c.field-meta.xml b/force-app/main/default/objects/Property__c/fields/Address__c.field-meta.xml new file mode 100644 index 0000000..5fbb048 --- /dev/null +++ b/force-app/main/default/objects/Property__c/fields/Address__c.field-meta.xml @@ -0,0 +1,13 @@ + + + Address__c + false + + 100 + false + false + false + false + Text + false + diff --git a/force-app/main/default/objects/Property__c/fields/Assessed_Value__c.field-meta.xml b/force-app/main/default/objects/Property__c/fields/Assessed_Value__c.field-meta.xml new file mode 100644 index 0000000..bbeddad --- /dev/null +++ b/force-app/main/default/objects/Property__c/fields/Assessed_Value__c.field-meta.xml @@ -0,0 +1,12 @@ + + + Assessed_Value__c + + 18 + false + 0 + false + false + false + Currency + diff --git a/force-app/main/default/objects/Property__c/fields/Baths__c.field-meta.xml b/force-app/main/default/objects/Property__c/fields/Baths__c.field-meta.xml new file mode 100644 index 0000000..107b031 --- /dev/null +++ b/force-app/main/default/objects/Property__c/fields/Baths__c.field-meta.xml @@ -0,0 +1,14 @@ + + + Baths__c + false + + 2 + false + 0 + false + false + false + Number + false + diff --git a/force-app/main/default/objects/Property__c/fields/Beds__c.field-meta.xml b/force-app/main/default/objects/Property__c/fields/Beds__c.field-meta.xml new file mode 100644 index 0000000..3adbb35 --- /dev/null +++ b/force-app/main/default/objects/Property__c/fields/Beds__c.field-meta.xml @@ -0,0 +1,14 @@ + + + Beds__c + false + + 2 + false + 0 + false + false + false + Number + false + diff --git a/force-app/main/default/objects/Property__c/fields/Broker__c.field-meta.xml b/force-app/main/default/objects/Property__c/fields/Broker__c.field-meta.xml new file mode 100644 index 0000000..9eafffe --- /dev/null +++ b/force-app/main/default/objects/Property__c/fields/Broker__c.field-meta.xml @@ -0,0 +1,14 @@ + + + Broker__c + SetNull + + Broker__c + Properties + Properties + false + false + false + false + Lookup + diff --git a/force-app/main/default/objects/Property__c/fields/City__c.field-meta.xml b/force-app/main/default/objects/Property__c/fields/City__c.field-meta.xml new file mode 100644 index 0000000..c3ccc00 --- /dev/null +++ b/force-app/main/default/objects/Property__c/fields/City__c.field-meta.xml @@ -0,0 +1,13 @@ + + + City__c + false + + 50 + false + false + false + false + Text + false + diff --git a/force-app/main/default/objects/Property__c/fields/Date_Agreement__c.field-meta.xml b/force-app/main/default/objects/Property__c/fields/Date_Agreement__c.field-meta.xml new file mode 100644 index 0000000..f4d60c9 --- /dev/null +++ b/force-app/main/default/objects/Property__c/fields/Date_Agreement__c.field-meta.xml @@ -0,0 +1,10 @@ + + + Date_Agreement__c + + false + false + false + false + Date + diff --git a/force-app/main/default/objects/Property__c/fields/Date_Closed__c.field-meta.xml b/force-app/main/default/objects/Property__c/fields/Date_Closed__c.field-meta.xml new file mode 100644 index 0000000..fcfc112 --- /dev/null +++ b/force-app/main/default/objects/Property__c/fields/Date_Closed__c.field-meta.xml @@ -0,0 +1,10 @@ + + + Date_Closed__c + + false + false + false + false + Date + diff --git a/force-app/main/default/objects/Property__c/fields/Date_Contracted__c.field-meta.xml b/force-app/main/default/objects/Property__c/fields/Date_Contracted__c.field-meta.xml new file mode 100644 index 0000000..76c6e4c --- /dev/null +++ b/force-app/main/default/objects/Property__c/fields/Date_Contracted__c.field-meta.xml @@ -0,0 +1,10 @@ + + + Date_Contracted__c + + false + false + false + false + Date + diff --git a/force-app/main/default/objects/Property__c/fields/Date_Listed__c.field-meta.xml b/force-app/main/default/objects/Property__c/fields/Date_Listed__c.field-meta.xml new file mode 100644 index 0000000..b2dd9ca --- /dev/null +++ b/force-app/main/default/objects/Property__c/fields/Date_Listed__c.field-meta.xml @@ -0,0 +1,11 @@ + + + Date_Listed__c + TODAY() - 10 + + false + false + false + false + Date + diff --git a/force-app/main/default/objects/Property__c/fields/Date_Pre_Market__c.field-meta.xml b/force-app/main/default/objects/Property__c/fields/Date_Pre_Market__c.field-meta.xml new file mode 100644 index 0000000..165555b --- /dev/null +++ b/force-app/main/default/objects/Property__c/fields/Date_Pre_Market__c.field-meta.xml @@ -0,0 +1,10 @@ + + + Date_Pre_Market__c + + false + false + false + false + Date + diff --git a/force-app/main/default/objects/Property__c/fields/Days_On_Market__c.field-meta.xml b/force-app/main/default/objects/Property__c/fields/Days_On_Market__c.field-meta.xml new file mode 100644 index 0000000..43095ad --- /dev/null +++ b/force-app/main/default/objects/Property__c/fields/Days_On_Market__c.field-meta.xml @@ -0,0 +1,15 @@ + + + Days_On_Market__c + false + TODAY() - Date_Listed__c + BlankAsZero + + 18 + false + 0 + false + false + Number + false + diff --git a/force-app/main/default/objects/Property__c/fields/Description__c.field-meta.xml b/force-app/main/default/objects/Property__c/fields/Description__c.field-meta.xml new file mode 100644 index 0000000..3df16b2 --- /dev/null +++ b/force-app/main/default/objects/Property__c/fields/Description__c.field-meta.xml @@ -0,0 +1,11 @@ + + + Description__c + + 500 + false + false + false + LongTextArea + 3 + diff --git a/force-app/main/default/objects/Property__c/fields/Location__c.field-meta.xml b/force-app/main/default/objects/Property__c/fields/Location__c.field-meta.xml new file mode 100644 index 0000000..3deb1ef --- /dev/null +++ b/force-app/main/default/objects/Property__c/fields/Location__c.field-meta.xml @@ -0,0 +1,12 @@ + + + Location__c + true + + false + 7 + false + false + false + Location + diff --git a/force-app/main/default/objects/Property__c/fields/Picture_IMG__c.field-meta.xml b/force-app/main/default/objects/Property__c/fields/Picture_IMG__c.field-meta.xml new file mode 100644 index 0000000..1be1f9e --- /dev/null +++ b/force-app/main/default/objects/Property__c/fields/Picture_IMG__c.field-meta.xml @@ -0,0 +1,13 @@ + + + Picture_IMG__c + false + if(ISBLANK(Picture__c), '', IMAGE(Picture__c, "Picture")) + BlankAsZero + + false + false + false + Text + false + diff --git a/force-app/main/default/objects/Property__c/fields/Picture__c.field-meta.xml b/force-app/main/default/objects/Property__c/fields/Picture__c.field-meta.xml new file mode 100644 index 0000000..6340e23 --- /dev/null +++ b/force-app/main/default/objects/Property__c/fields/Picture__c.field-meta.xml @@ -0,0 +1,10 @@ + + + Picture__c + + false + false + false + false + Url + diff --git a/force-app/main/default/objects/Property__c/fields/Price_Sold__c.field-meta.xml b/force-app/main/default/objects/Property__c/fields/Price_Sold__c.field-meta.xml new file mode 100644 index 0000000..565dae8 --- /dev/null +++ b/force-app/main/default/objects/Property__c/fields/Price_Sold__c.field-meta.xml @@ -0,0 +1,12 @@ + + + Price_Sold__c + + 8 + false + 0 + false + false + false + Currency + diff --git a/force-app/main/default/objects/Property__c/fields/Price__c.field-meta.xml b/force-app/main/default/objects/Property__c/fields/Price__c.field-meta.xml new file mode 100644 index 0000000..621f854 --- /dev/null +++ b/force-app/main/default/objects/Property__c/fields/Price__c.field-meta.xml @@ -0,0 +1,12 @@ + + + Price__c + + 8 + false + 0 + true + true + false + Currency + diff --git a/force-app/main/default/objects/Property__c/fields/Record_Link__c.field-meta.xml b/force-app/main/default/objects/Property__c/fields/Record_Link__c.field-meta.xml new file mode 100644 index 0000000..a186ead --- /dev/null +++ b/force-app/main/default/objects/Property__c/fields/Record_Link__c.field-meta.xml @@ -0,0 +1,13 @@ + + + Record_Link__c + false + LEFT($Api.Partner_Server_URL_260, FIND( '/services', $Api.Partner_Server_URL_260))+ Id + BlankAsZero + + false + false + false + Text + false + diff --git a/force-app/main/default/objects/Property__c/fields/State__c.field-meta.xml b/force-app/main/default/objects/Property__c/fields/State__c.field-meta.xml new file mode 100644 index 0000000..286d042 --- /dev/null +++ b/force-app/main/default/objects/Property__c/fields/State__c.field-meta.xml @@ -0,0 +1,13 @@ + + + State__c + false + + 20 + false + false + false + false + Text + false + diff --git a/force-app/main/default/objects/Property__c/fields/Status__c.field-meta.xml b/force-app/main/default/objects/Property__c/fields/Status__c.field-meta.xml new file mode 100644 index 0000000..a663176 --- /dev/null +++ b/force-app/main/default/objects/Property__c/fields/Status__c.field-meta.xml @@ -0,0 +1,41 @@ + + + Status__c + + false + true + false + false + Picklist + + true + + false + + Contracted + false + + + + Pre Market + false + + + + Available + false + + + + Under Agreement + false + + + + Closed + false + + + + + diff --git a/force-app/main/default/objects/Property__c/fields/Tags__c.field-meta.xml b/force-app/main/default/objects/Property__c/fields/Tags__c.field-meta.xml new file mode 100644 index 0000000..8fc32b7 --- /dev/null +++ b/force-app/main/default/objects/Property__c/fields/Tags__c.field-meta.xml @@ -0,0 +1,13 @@ + + + Tags__c + false + + 255 + false + false + false + false + Text + false + diff --git a/force-app/main/default/objects/Property__c/fields/Thumbnail_IMG__c.field-meta.xml b/force-app/main/default/objects/Property__c/fields/Thumbnail_IMG__c.field-meta.xml new file mode 100644 index 0000000..2882ef9 --- /dev/null +++ b/force-app/main/default/objects/Property__c/fields/Thumbnail_IMG__c.field-meta.xml @@ -0,0 +1,13 @@ + + + Thumbnail_IMG__c + false + if(ISBLANK(Thumbnail__c), "", IMAGE(Thumbnail__c, "Picture", 200, 200)) + BlankAsZero + + false + false + false + Text + false + diff --git a/force-app/main/default/objects/Property__c/fields/Thumbnail__c.field-meta.xml b/force-app/main/default/objects/Property__c/fields/Thumbnail__c.field-meta.xml new file mode 100644 index 0000000..48048c7 --- /dev/null +++ b/force-app/main/default/objects/Property__c/fields/Thumbnail__c.field-meta.xml @@ -0,0 +1,10 @@ + + + Thumbnail__c + + false + false + false + false + Url + diff --git a/force-app/main/default/objects/Property__c/fields/Zip__c.field-meta.xml b/force-app/main/default/objects/Property__c/fields/Zip__c.field-meta.xml new file mode 100644 index 0000000..283915b --- /dev/null +++ b/force-app/main/default/objects/Property__c/fields/Zip__c.field-meta.xml @@ -0,0 +1,13 @@ + + + Zip__c + false + + 10 + false + false + false + false + Text + false + diff --git a/force-app/main/default/objects/Property__c/listViews/All.listView-meta.xml b/force-app/main/default/objects/Property__c/listViews/All.listView-meta.xml new file mode 100644 index 0000000..576f82e --- /dev/null +++ b/force-app/main/default/objects/Property__c/listViews/All.listView-meta.xml @@ -0,0 +1,11 @@ + + + All + NAME + City__c + Beds__c + Price__c + Status__c + Everything + + diff --git a/force-app/main/default/permissionsets/dreamhouse.permissionset-meta.xml b/force-app/main/default/permissionsets/dreamhouse.permissionset-meta.xml new file mode 100644 index 0000000..61d8f2d --- /dev/null +++ b/force-app/main/default/permissionsets/dreamhouse.permissionset-meta.xml @@ -0,0 +1,219 @@ + + + + Dreamhouse + true + + + PagedResult + true + + + PropertyController + true + + + SampleDataController + true + + + true + Broker__c.Broker_Id__c + true + + + true + Broker__c.Email__c + true + + + true + Broker__c.Mobile_Phone__c + true + + + true + Broker__c.Phone__c + true + + + false + Broker__c.Picture_IMG__c + true + + + true + Broker__c.Picture__c + true + + + true + Broker__c.Title__c + true + + + true + Property__c.Address__c + true + + + true + Property__c.Assessed_Value__c + true + + + true + Property__c.Baths__c + true + + + true + Property__c.Beds__c + true + + + true + Property__c.Broker__c + true + + + true + Property__c.City__c + true + + + true + Property__c.Date_Agreement__c + true + + + true + Property__c.Date_Closed__c + true + + + true + Property__c.Date_Contracted__c + true + + + true + Property__c.Date_Listed__c + true + + + true + Property__c.Date_Pre_Market__c + true + + + false + Property__c.Days_On_Market__c + true + + + true + Property__c.Description__c + true + + + true + Property__c.Location__c + true + + + false + Property__c.Picture_IMG__c + true + + + true + Property__c.Picture__c + true + + + true + Property__c.Price_Sold__c + true + + + true + Property__c.Price__c + true + + + false + Property__c.Record_Link__c + true + + + true + Property__c.State__c + true + + + true + Property__c.Status__c + true + + + true + Property__c.Tags__c + true + + + false + Property__c.Thumbnail_IMG__c + true + + + true + Property__c.Thumbnail__c + true + + + true + Property__c.Zip__c + true + + false + + + true + true + true + true + true + Broker__c + true + + + true + true + true + true + true + Property__c + true + + + Broker__c + Visible + + + Property_Explorer + Visible + + + Property_Finder + Visible + + + Property__c + Visible + + + Settings + Visible + + diff --git a/force-app/main/default/remoteSiteSettings/nominatim_openstreetmap.remoteSite-meta.xml b/force-app/main/default/remoteSiteSettings/nominatim_openstreetmap.remoteSite-meta.xml new file mode 100644 index 0000000..43dc76c --- /dev/null +++ b/force-app/main/default/remoteSiteSettings/nominatim_openstreetmap.remoteSite-meta.xml @@ -0,0 +1,6 @@ + + + false + true + https://nominatim.openstreetmap.org + diff --git a/force-app/main/default/staticresources/leafletjs.resource-meta.xml b/force-app/main/default/staticresources/leafletjs.resource-meta.xml new file mode 100644 index 0000000..3f3975f --- /dev/null +++ b/force-app/main/default/staticresources/leafletjs.resource-meta.xml @@ -0,0 +1,6 @@ + + + Private + application/zip + JS library that renders maps + diff --git a/force-app/main/default/staticresources/leafletjs/images/layers-2x.png b/force-app/main/default/staticresources/leafletjs/images/layers-2x.png new file mode 100644 index 0000000000000000000000000000000000000000..200c333dca9652ac4cba004d609e5af4eee168c1 GIT binary patch literal 1259 zcmVFhCYNy;#0irRPomHqW|G1C*;4?@4#E?jH>?v@U%cy?3dQAc-DchXVErpOh~ z-jbon+tNbnl6hoEb;)TVk+%hTDDi_G%i3*RZ&15!$Fjr^f;Ke&A@|?=`2&+{zr+3a z{D*=t(`AXyS%X7N z%a#RZw6vD^t_rnM`L4E>m=U&R!A-&}nZIi$BOPvkhrCuUe@BN~-lRD)f44;J%TwgE zcze8u!PQ_NR7?o(NylLXVTfDO zxs5=@|GsYEsNo4M#nT%N!UE(?dnS)t2+{ELYAFp*3=iF=|EQnTp`#vlSXuGVraYo? z+RCzXo6h3qA8{KG?S4nE(lM+;Eb4nT3XV;7gcAxUi5m)`k5tv}cPy()8ZR3TLW3I- zAS^}cq-IJvL7a4RgR!yk@~RT%$lA7{L5ES*hyx)M4(yxI$Ub(4f)K|^v1>zvwQY!_ zIrWw8q9GS^!Dp~}+?mbnB6jDF8mVlbQ!jFKDY;w=7;XO{9bq7>LXGK24WA`;rL)_Z z)&j}pbV(;6gY;VMhbxgvn`X;6x}VUEE-7 z%)7j-%t8S=ZL3yc)HbXDAqJZvBTPoiW_A-+a8m3_Z?v{DN7Tnr#O_VUMT0UBt$;p` zDh6JbGHN8JJ*JN%y2%msb97@_S>9!%Egwk;?PEkU9ntz&3uR}%Fj5d$JHQbQb3}a{ zSzFT^#n=VInPpcAS}CNxj?_ zVscANk5Cfz(51EI1pz};AWWb|kgbYNb4wCEGUn3+eMUMV?1-{=I4TlmLJMot@rd07 zZuo2hk1ccu{YmGkcYdWAVdk{Z4Nm?^cTD&}jGm+Q1SYIXMwmG*oO*83&#>l%nbR`G zhh=lZ%xIb7kU3#;TBbfECrnC9P=-XpL|TG2BoZdj61*XiFbW8?1Z_wp%#;>${SUIy V$8qr;L*)Pf002ovPDHLkV1hYLS~36t literal 0 HcmV?d00001 diff --git a/force-app/main/default/staticresources/leafletjs/images/layers.png b/force-app/main/default/staticresources/leafletjs/images/layers.png new file mode 100644 index 0000000000000000000000000000000000000000..1a72e5784b2b456eac5d7670738db80697af3377 GIT binary patch literal 696 zcmV;p0!RIcP)*@&l2<6p=!C&s@#ZL+%BQvF&b?w6S%wp=I>1QHj7AP5C)IWy#b znXXB;g;j=$a-tW89K%FbDceHVq&unY*Wx3L#=EGWH=rjqnp|4c_Ulec!ql3#G-5ZF zVlbBA@XP=)C8U&+Lrc)S4O5%1$&{(;7R^K(CSnvSr$v;+B$8q&7Bf|h$#PARo1^%M zf1H^nG-EiXVXr07OH(*8R)xa|FD;lXUlg_-%)~ZGsL2cX0NXaAzN2q%jqLRR6ruVk8`Jb7n#{`T;o@`F= z#3YcynIR^s83UNF3D!f5m#Mg)NJ24&Qfrqb&_z=yF;=B)#9Iq7u-@^O!(mW{D;qvr zPc)gVb%aowtS8m@ElL4A9G>w#ffQ~q{i&_i)*6f^)Sz|C?C>zb4Uo?H<-&Hz@a?J; z$ml@zGygWofb9$ZBj6aLjpLhsT2AzjOu=-*u_gSCUYnU^5s62$4H-fe}gSR(=wKRaTHh!@*b)YV6mo|a4Fn6Rgc&Rpk zvn_X|3VY?v=>nJ{slE^V1GaGWk}m@aIWGIpghbfPh8m@aIWEo_%AZI>==moIFVE^L=C zZJ91?mo03UEp3-BY?wBGur6$uD{Yr9Y?m%SHF8Fk1pc(Nva%QJ+{FLkalfypz3&M|||Fn`7|g3c~4(nXHKFmRnwn$J#_$xE8i z|Ns9!kC;(oC1qQk>LMp3_a2(odYyMT@>voX=UI)k>1cJdn;gjmJ-|6v4nb1Oryh)eQMwHP(i@!36%vGJyFK(JTj?Vb{{C=jx&)@1l zlFmnw%0`&bqruifkkHKC=vbiAM3&E`#Mv>2%tw;VK8?_|&E89cs{a1}$J*!f_xd-C z&F%B|oxRgPlh0F!txkxrQjNA`m9~?&&|jw4W0<`_iNHsX$VQXVK!B}Xkh4>av|f_8 zLY2?t?ejE=%(TnfV5iqOjm?d;&qI~ZGl|SzU77a)002XDQchC<95+*MjE@82?VLm= z3xf6%Vd@99z|q|-ua5l3kJxvZwan-8K1cPiwQAtlcNX~ZqLeoMB+a;7)WA|O#HOB% zg6SX;754xD1{Fy}K~#8Ntklac&zTpadXZ& zC*_=T&g7hfbI$R?v%9?sknIb97gJOJ=`-8YyS3ndqN+Jm+x33!p&Hc@@L$w))s2@N ztv~i}Emc?DykgwFWwma($8+~b>l?tqj$dh13R^nMZnva9 zn0Vflzv2Dvp`oVQw{Guby~i`JGbyBGTEC{y>yzCkg>K&CIeQ$u;lyQ+M{O~gEJ^)Z zrF3p)^>|uT;57}WY&IRwyOQ=dq%Az}_t=_hKowP!Z79q0;@Zu(SWEJJcHY+5T6I({ zw)wj*SNi4wrd+POUfZe4gF77vW?j zoFS}|r2n&$U9Y!S4VEOyN}OpZZi|?cr1VcE_tHsDQgp-ga(SwkBrkCm{|*-yb=}ZW zvcYvLvfA90TPn|!-TuYJV<6`}+RJeRgP3EA=qQcF9k0*#*{f&I_pjam%I6Dd#YE|G zqB!R}tW-K!wV1w+4JcFA_s6~=@9F&j8`u$-ifLN3vK;`lvaA-`jRn_}(8|)!3?-}I zvFi{H;@A$gEZYh?%|Qr_y#*UkOPjwiRCsJQ>mb6h5yGIk6C5_XA=8T?IBfm_?+P0; zhhUs)-(0R*H<&Kku(1>#cGtOpk&Z&kQcw&SJv-4VY<+;=8hYnoX zfNJMCa9)^5Z0;2dCUk;x-%#yS!I~Jr3pNuI!g_tHz!$hKwt1GL~sFvx)3u4TA zv>CLGdQtoZ7Du7ctJRfTqY;FPxs1G{ZJ?73D5J@OO{6BHcPbk{_mjg&p2QFeke%QI zlAJ-kvjuwy1<5D-6>su68A+i998aSZNnQX)+Q}6(GK-C%8G-!1bOJBONU{gT%IOOE z;Yk24YC@^lFW77>r6x7eS1Omc;8=GUp#&zLQ&L{ zv8$hGC`wp~$9pR>f%-_Ps3>YhzP(+vC(E*zr1CVO8ChN^MI-VGMX7+|(r!SGZ9gd5 zzO9sQd>sm|f1|X&oh=8lOzd6+ITvo zCXInR?>RZ#>Hb*PO=7dI!dZ(wY4O}ZGv zdfQFio7+0~PN*RFCZGM6@9-o~y*@?;k00NvOsw54t1^tt{*ATMs^2j}4Wp=4t3RH* z_+8b`F-{E=0sOgM<;VHTo!Ij3u zmmI`2?K7g(GOcGA)@h?$SW&pwHdtj1n57PLI8&6RHhx4R%Q7b z^JEqR)@06V!pbS*@D_ZyRMo_LlT}r{#sXOx4kM-V<_V{!5SSuM^SIVCA37|nY7LWQ zZA#B1h4l`6asz=Lvax_#GMRX|NF>=$=p{Qn0i@ExX1jGhy@B8a*_uR+ODEbVi8ObL zezG?azy>E~S~dl43&8<$(2H}P&*tuBdESUP83KQ?8B z?K(!uS>H1wlWQz;qOfB`T#TZ=EoSp~vZ5XtCvwm1h*Ex6mzTsn_y@_=xREIslV-%- zpdWkEzMjeNOGWrSM32gpBt27*O29NdhGzuDgYxcf`Jjjqw@B;Vmdb@fxdhCRi`Kg> zmUTr$=&@#i!%F4Q6mb&4QKfR^95KJ!<6~fqx-f^66AV!|ywG{6D^Vay-3b99>XOe# e-I|>x8~*?ZhF3snGbtJX0000cOl4 literal 0 HcmV?d00001 diff --git a/force-app/main/default/staticresources/leafletjs/images/marker-icon.png b/force-app/main/default/staticresources/leafletjs/images/marker-icon.png new file mode 100644 index 0000000000000000000000000000000000000000..950edf24677ded147df13b26f91baa2b0fa70513 GIT binary patch literal 1466 zcmV;r1x5OaP)P001cn1^@s6z>|W`000GnNklGNuHDcIX17Zdjl&3`L?0sTjIws<{((Dh&g-s0<@jYQyl?D*X^?%13;ml^gy> ziMrY_^1WI=(g@LMizu=zCoA>C`6|QEq1eV92k*7m>G65*&@&6)aC&e}G zI)pf-Za|N`DT&Cn1J|o`19mumxW~hiKiKyc-P`S@q)rdTo84@QI@;0yXrG%9uhI>A zG5QHb6s4=<6xy{1 z@NMxEkryp{LS44%z$3lP^cX!9+2-;CTt3wM4(k*#C{aiIiLuB>jJj;KPhPzIC00bL zU3a#;aJld94lCW=`4&aAy8M7PY=HQ>O%$YEP4c4UY#CRxfgbE~(|uiI=YS8q;O9y6 zmIkXzR`}p7ti|PrM3a}WMnR=3NVnWdAAR>b9X@)DKL6=YsvmH%?I24wdq?Gh54_;# z$?_LvgjEdspdQlft#4CQ z`2Zyvy?*)N1Ftw|{_hakhG9WjS?Az@I@+IZ8JbWewR!XUK4&6346+d#~gsE0SY(LX8&JfY>Aj)RxGy96nwhs2rv zzW6pTnMpFkDSkT*a*6Dx|u@ds6ISVn0@^RmIsKZ5Y;bazbc;tTSq(kg(=481ODrPyNB6n z-$+U}(w$m6U6H$w17Bw+wDaFIe~GvNMYvnw31MpY0eQKT9l>SU``8k7w4)z!GZKMI z#_cEKq7k~i%nlK@6c-K?+R;B#5$?T#YpKD`t_4bAs^#E+@5QW$@OX3*`;(#{U^d-vY)&xEE>n5lYl&T?Amke9$Lam@{1K@O ze*LXqlKQHiv=gx+V^Cbb2?z@ISBQ*3amF;9UJ3SBg(N|710TLamQmYZ&Qjn2LuO<* zCZlB4n%@pc&7NNnY1}x+NWpHlq`OJEo|`aYN9<`RBUB+79g;>dgb6YlfN#kGL?lO_ z!6~M^7sOnbsUkKk<@Ysie&`G>ruxH&Mgy&8;i=A zB9OO!xR{AyODw>DS-q5YM{0ExFEAzt zm>RdS+ssW(-8|?xr0(?$vBVB*%(xDLtq3Hf0I5yFm<_g=W2`QWAax{1rWVH=I!VrP zs(rTFX@W#t$hXNvbgX`gK&^w_YD;CQ!B@e0QbLIWaKAXQe2-kkloo;{iF#6}z!4=W zi$giRj1{ zt;2w`VSCF#WE&*ev7jpsC=6175@(~nTE2;7M-L((0bH@yG}-TB$R~WXd?tA$s3|%y zA`9$sA(>F%J3ioz<-LJl*^o1|w84l>HBR`>3l9c8$5Xr@xCiIQ7{x$fMCzOk_-M=% z+{a_Q#;42`#KfUte@$NT77uaTz?b-fBe)1s5XE$yA79fm?KqM^VgLXD07*qoM6N<$ Ef<_J(9smFU literal 0 HcmV?d00001 diff --git a/force-app/main/default/staticresources/leafletjs/leaflet.css b/force-app/main/default/staticresources/leafletjs/leaflet.css new file mode 100644 index 0000000..2961b76 --- /dev/null +++ b/force-app/main/default/staticresources/leafletjs/leaflet.css @@ -0,0 +1,661 @@ +/* required styles */ + +.leaflet-pane, +.leaflet-tile, +.leaflet-marker-icon, +.leaflet-marker-shadow, +.leaflet-tile-container, +.leaflet-pane > svg, +.leaflet-pane > canvas, +.leaflet-zoom-box, +.leaflet-image-layer, +.leaflet-layer { + position: absolute; + left: 0; + top: 0; + } +.leaflet-container { + overflow: hidden; + } +.leaflet-tile, +.leaflet-marker-icon, +.leaflet-marker-shadow { + -webkit-user-select: none; + -moz-user-select: none; + user-select: none; + -webkit-user-drag: none; + } +/* Prevents IE11 from highlighting tiles in blue */ +.leaflet-tile::selection { + background: transparent; +} +/* Safari renders non-retina tile on retina better with this, but Chrome is worse */ +.leaflet-safari .leaflet-tile { + image-rendering: -webkit-optimize-contrast; + } +/* hack that prevents hw layers "stretching" when loading new tiles */ +.leaflet-safari .leaflet-tile-container { + width: 1600px; + height: 1600px; + -webkit-transform-origin: 0 0; + } +.leaflet-marker-icon, +.leaflet-marker-shadow { + display: block; + } +/* .leaflet-container svg: reset svg max-width decleration shipped in Joomla! (joomla.org) 3.x */ +/* .leaflet-container img: map is broken in FF if you have max-width: 100% on tiles */ +.leaflet-container .leaflet-overlay-pane svg { + max-width: none !important; + max-height: none !important; + } +.leaflet-container .leaflet-marker-pane img, +.leaflet-container .leaflet-shadow-pane img, +.leaflet-container .leaflet-tile-pane img, +.leaflet-container img.leaflet-image-layer, +.leaflet-container .leaflet-tile { + max-width: none !important; + max-height: none !important; + width: auto; + padding: 0; + } + +.leaflet-container img.leaflet-tile { + /* See: https://bugs.chromium.org/p/chromium/issues/detail?id=600120 */ + mix-blend-mode: plus-lighter; +} + +.leaflet-container.leaflet-touch-zoom { + -ms-touch-action: pan-x pan-y; + touch-action: pan-x pan-y; + } +.leaflet-container.leaflet-touch-drag { + -ms-touch-action: pinch-zoom; + /* Fallback for FF which doesn't support pinch-zoom */ + touch-action: none; + touch-action: pinch-zoom; +} +.leaflet-container.leaflet-touch-drag.leaflet-touch-zoom { + -ms-touch-action: none; + touch-action: none; +} +.leaflet-container { + -webkit-tap-highlight-color: transparent; +} +.leaflet-container a { + -webkit-tap-highlight-color: rgba(51, 181, 229, 0.4); +} +.leaflet-tile { + filter: inherit; + visibility: hidden; + } +.leaflet-tile-loaded { + visibility: inherit; + } +.leaflet-zoom-box { + width: 0; + height: 0; + -moz-box-sizing: border-box; + box-sizing: border-box; + z-index: 800; + } +/* workaround for https://bugzilla.mozilla.org/show_bug.cgi?id=888319 */ +.leaflet-overlay-pane svg { + -moz-user-select: none; + } + +.leaflet-pane { z-index: 400; } + +.leaflet-tile-pane { z-index: 200; } +.leaflet-overlay-pane { z-index: 400; } +.leaflet-shadow-pane { z-index: 500; } +.leaflet-marker-pane { z-index: 600; } +.leaflet-tooltip-pane { z-index: 650; } +.leaflet-popup-pane { z-index: 700; } + +.leaflet-map-pane canvas { z-index: 100; } +.leaflet-map-pane svg { z-index: 200; } + +.leaflet-vml-shape { + width: 1px; + height: 1px; + } +.lvml { + behavior: url(#default#VML); + display: inline-block; + position: absolute; + } + + +/* control positioning */ + +.leaflet-control { + position: relative; + z-index: 800; + pointer-events: visiblePainted; /* IE 9-10 doesn't have auto */ + pointer-events: auto; + } +.leaflet-top, +.leaflet-bottom { + position: absolute; + z-index: 1000; + pointer-events: none; + } +.leaflet-top { + top: 0; + } +.leaflet-right { + right: 0; + } +.leaflet-bottom { + bottom: 0; + } +.leaflet-left { + left: 0; + } +.leaflet-control { + float: left; + clear: both; + } +.leaflet-right .leaflet-control { + float: right; + } +.leaflet-top .leaflet-control { + margin-top: 10px; + } +.leaflet-bottom .leaflet-control { + margin-bottom: 10px; + } +.leaflet-left .leaflet-control { + margin-left: 10px; + } +.leaflet-right .leaflet-control { + margin-right: 10px; + } + + +/* zoom and fade animations */ + +.leaflet-fade-anim .leaflet-popup { + opacity: 0; + -webkit-transition: opacity 0.2s linear; + -moz-transition: opacity 0.2s linear; + transition: opacity 0.2s linear; + } +.leaflet-fade-anim .leaflet-map-pane .leaflet-popup { + opacity: 1; + } +.leaflet-zoom-animated { + -webkit-transform-origin: 0 0; + -ms-transform-origin: 0 0; + transform-origin: 0 0; + } +svg.leaflet-zoom-animated { + will-change: transform; +} + +.leaflet-zoom-anim .leaflet-zoom-animated { + -webkit-transition: -webkit-transform 0.25s cubic-bezier(0,0,0.25,1); + -moz-transition: -moz-transform 0.25s cubic-bezier(0,0,0.25,1); + transition: transform 0.25s cubic-bezier(0,0,0.25,1); + } +.leaflet-zoom-anim .leaflet-tile, +.leaflet-pan-anim .leaflet-tile { + -webkit-transition: none; + -moz-transition: none; + transition: none; + } + +.leaflet-zoom-anim .leaflet-zoom-hide { + visibility: hidden; + } + + +/* cursors */ + +.leaflet-interactive { + cursor: pointer; + } +.leaflet-grab { + cursor: -webkit-grab; + cursor: -moz-grab; + cursor: grab; + } +.leaflet-crosshair, +.leaflet-crosshair .leaflet-interactive { + cursor: crosshair; + } +.leaflet-popup-pane, +.leaflet-control { + cursor: auto; + } +.leaflet-dragging .leaflet-grab, +.leaflet-dragging .leaflet-grab .leaflet-interactive, +.leaflet-dragging .leaflet-marker-draggable { + cursor: move; + cursor: -webkit-grabbing; + cursor: -moz-grabbing; + cursor: grabbing; + } + +/* marker & overlays interactivity */ +.leaflet-marker-icon, +.leaflet-marker-shadow, +.leaflet-image-layer, +.leaflet-pane > svg path, +.leaflet-tile-container { + pointer-events: none; + } + +.leaflet-marker-icon.leaflet-interactive, +.leaflet-image-layer.leaflet-interactive, +.leaflet-pane > svg path.leaflet-interactive, +svg.leaflet-image-layer.leaflet-interactive path { + pointer-events: visiblePainted; /* IE 9-10 doesn't have auto */ + pointer-events: auto; + } + +/* visual tweaks */ + +.leaflet-container { + background: #ddd; + outline-offset: 1px; + } +.leaflet-container a { + color: #0078A8; + } +.leaflet-zoom-box { + border: 2px dotted #38f; + background: rgba(255,255,255,0.5); + } + + +/* general typography */ +.leaflet-container { + font-family: "Helvetica Neue", Arial, Helvetica, sans-serif; + font-size: 12px; + font-size: 0.75rem; + line-height: 1.5; + } + + +/* general toolbar styles */ + +.leaflet-bar { + box-shadow: 0 1px 5px rgba(0,0,0,0.65); + border-radius: 4px; + } +.leaflet-bar a { + background-color: #fff; + border-bottom: 1px solid #ccc; + width: 26px; + height: 26px; + line-height: 26px; + display: block; + text-align: center; + text-decoration: none; + color: black; + } +.leaflet-bar a, +.leaflet-control-layers-toggle { + background-position: 50% 50%; + background-repeat: no-repeat; + display: block; + } +.leaflet-bar a:hover, +.leaflet-bar a:focus { + background-color: #f4f4f4; + } +.leaflet-bar a:first-child { + border-top-left-radius: 4px; + border-top-right-radius: 4px; + } +.leaflet-bar a:last-child { + border-bottom-left-radius: 4px; + border-bottom-right-radius: 4px; + border-bottom: none; + } +.leaflet-bar a.leaflet-disabled { + cursor: default; + background-color: #f4f4f4; + color: #bbb; + } + +.leaflet-touch .leaflet-bar a { + width: 30px; + height: 30px; + line-height: 30px; + } +.leaflet-touch .leaflet-bar a:first-child { + border-top-left-radius: 2px; + border-top-right-radius: 2px; + } +.leaflet-touch .leaflet-bar a:last-child { + border-bottom-left-radius: 2px; + border-bottom-right-radius: 2px; + } + +/* zoom control */ + +.leaflet-control-zoom-in, +.leaflet-control-zoom-out { + font: bold 18px 'Lucida Console', Monaco, monospace; + text-indent: 1px; + } + +.leaflet-touch .leaflet-control-zoom-in, .leaflet-touch .leaflet-control-zoom-out { + font-size: 22px; + } + + +/* layers control */ + +.leaflet-control-layers { + box-shadow: 0 1px 5px rgba(0,0,0,0.4); + background: #fff; + border-radius: 5px; + } +.leaflet-control-layers-toggle { + background-image: url(images/layers.png); + width: 36px; + height: 36px; + } +.leaflet-retina .leaflet-control-layers-toggle { + background-image: url(images/layers-2x.png); + background-size: 26px 26px; + } +.leaflet-touch .leaflet-control-layers-toggle { + width: 44px; + height: 44px; + } +.leaflet-control-layers .leaflet-control-layers-list, +.leaflet-control-layers-expanded .leaflet-control-layers-toggle { + display: none; + } +.leaflet-control-layers-expanded .leaflet-control-layers-list { + display: block; + position: relative; + } +.leaflet-control-layers-expanded { + padding: 6px 10px 6px 6px; + color: #333; + background: #fff; + } +.leaflet-control-layers-scrollbar { + overflow-y: scroll; + overflow-x: hidden; + padding-right: 5px; + } +.leaflet-control-layers-selector { + margin-top: 2px; + position: relative; + top: 1px; + } +.leaflet-control-layers label { + display: block; + font-size: 13px; + font-size: 1.08333em; + } +.leaflet-control-layers-separator { + height: 0; + border-top: 1px solid #ddd; + margin: 5px -10px 5px -6px; + } + +/* Default icon URLs */ +.leaflet-default-icon-path { /* used only in path-guessing heuristic, see L.Icon.Default */ + background-image: url(images/marker-icon.png); + } + + +/* attribution and scale controls */ + +.leaflet-container .leaflet-control-attribution { + background: #fff; + background: rgba(255, 255, 255, 0.8); + margin: 0; + } +.leaflet-control-attribution, +.leaflet-control-scale-line { + padding: 0 5px; + color: #333; + line-height: 1.4; + } +.leaflet-control-attribution a { + text-decoration: none; + } +.leaflet-control-attribution a:hover, +.leaflet-control-attribution a:focus { + text-decoration: underline; + } +.leaflet-attribution-flag { + display: inline !important; + vertical-align: baseline !important; + width: 1em; + height: 0.6669em; + } +.leaflet-left .leaflet-control-scale { + margin-left: 5px; + } +.leaflet-bottom .leaflet-control-scale { + margin-bottom: 5px; + } +.leaflet-control-scale-line { + border: 2px solid #777; + border-top: none; + line-height: 1.1; + padding: 2px 5px 1px; + white-space: nowrap; + -moz-box-sizing: border-box; + box-sizing: border-box; + background: rgba(255, 255, 255, 0.8); + text-shadow: 1px 1px #fff; + } +.leaflet-control-scale-line:not(:first-child) { + border-top: 2px solid #777; + border-bottom: none; + margin-top: -2px; + } +.leaflet-control-scale-line:not(:first-child):not(:last-child) { + border-bottom: 2px solid #777; + } + +.leaflet-touch .leaflet-control-attribution, +.leaflet-touch .leaflet-control-layers, +.leaflet-touch .leaflet-bar { + box-shadow: none; + } +.leaflet-touch .leaflet-control-layers, +.leaflet-touch .leaflet-bar { + border: 2px solid rgba(0,0,0,0.2); + background-clip: padding-box; + } + + +/* popup */ + +.leaflet-popup { + position: absolute; + text-align: center; + margin-bottom: 20px; + } +.leaflet-popup-content-wrapper { + padding: 1px; + text-align: left; + border-radius: 12px; + } +.leaflet-popup-content { + margin: 13px 24px 13px 20px; + line-height: 1.3; + font-size: 13px; + font-size: 1.08333em; + min-height: 1px; + } +.leaflet-popup-content p { + margin: 17px 0; + margin: 1.3em 0; + } +.leaflet-popup-tip-container { + width: 40px; + height: 20px; + position: absolute; + left: 50%; + margin-top: -1px; + margin-left: -20px; + overflow: hidden; + pointer-events: none; + } +.leaflet-popup-tip { + width: 17px; + height: 17px; + padding: 1px; + + margin: -10px auto 0; + pointer-events: auto; + + -webkit-transform: rotate(45deg); + -moz-transform: rotate(45deg); + -ms-transform: rotate(45deg); + transform: rotate(45deg); + } +.leaflet-popup-content-wrapper, +.leaflet-popup-tip { + background: white; + color: #333; + box-shadow: 0 3px 14px rgba(0,0,0,0.4); + } +.leaflet-container a.leaflet-popup-close-button { + position: absolute; + top: 0; + right: 0; + border: none; + text-align: center; + width: 24px; + height: 24px; + font: 16px/24px Tahoma, Verdana, sans-serif; + color: #757575; + text-decoration: none; + background: transparent; + } +.leaflet-container a.leaflet-popup-close-button:hover, +.leaflet-container a.leaflet-popup-close-button:focus { + color: #585858; + } +.leaflet-popup-scrolled { + overflow: auto; + } + +.leaflet-oldie .leaflet-popup-content-wrapper { + -ms-zoom: 1; + } +.leaflet-oldie .leaflet-popup-tip { + width: 24px; + margin: 0 auto; + + -ms-filter: "progid:DXImageTransform.Microsoft.Matrix(M11=0.70710678, M12=0.70710678, M21=-0.70710678, M22=0.70710678)"; + filter: progid:DXImageTransform.Microsoft.Matrix(M11=0.70710678, M12=0.70710678, M21=-0.70710678, M22=0.70710678); + } + +.leaflet-oldie .leaflet-control-zoom, +.leaflet-oldie .leaflet-control-layers, +.leaflet-oldie .leaflet-popup-content-wrapper, +.leaflet-oldie .leaflet-popup-tip { + border: 1px solid #999; + } + + +/* div icon */ + +.leaflet-div-icon { + background: #fff; + border: 1px solid #666; + } + + +/* Tooltip */ +/* Base styles for the element that has a tooltip */ +.leaflet-tooltip { + position: absolute; + padding: 6px; + background-color: #fff; + border: 1px solid #fff; + border-radius: 3px; + color: #222; + white-space: nowrap; + -webkit-user-select: none; + -moz-user-select: none; + -ms-user-select: none; + user-select: none; + pointer-events: none; + box-shadow: 0 1px 3px rgba(0,0,0,0.4); + } +.leaflet-tooltip.leaflet-interactive { + cursor: pointer; + pointer-events: auto; + } +.leaflet-tooltip-top:before, +.leaflet-tooltip-bottom:before, +.leaflet-tooltip-left:before, +.leaflet-tooltip-right:before { + position: absolute; + pointer-events: none; + border: 6px solid transparent; + background: transparent; + content: ""; + } + +/* Directions */ + +.leaflet-tooltip-bottom { + margin-top: 6px; +} +.leaflet-tooltip-top { + margin-top: -6px; +} +.leaflet-tooltip-bottom:before, +.leaflet-tooltip-top:before { + left: 50%; + margin-left: -6px; + } +.leaflet-tooltip-top:before { + bottom: 0; + margin-bottom: -12px; + border-top-color: #fff; + } +.leaflet-tooltip-bottom:before { + top: 0; + margin-top: -12px; + margin-left: -6px; + border-bottom-color: #fff; + } +.leaflet-tooltip-left { + margin-left: -6px; +} +.leaflet-tooltip-right { + margin-left: 6px; +} +.leaflet-tooltip-left:before, +.leaflet-tooltip-right:before { + top: 50%; + margin-top: -6px; + } +.leaflet-tooltip-left:before { + right: 0; + margin-right: -12px; + border-left-color: #fff; + } +.leaflet-tooltip-right:before { + left: 0; + margin-left: -12px; + border-right-color: #fff; + } + +/* Printing */ + +@media print { + /* Prevent printers from removing background-images of controls. */ + .leaflet-control { + -webkit-print-color-adjust: exact; + print-color-adjust: exact; + } + } diff --git a/force-app/main/default/staticresources/leafletjs/leaflet.js b/force-app/main/default/staticresources/leafletjs/leaflet.js new file mode 100644 index 0000000..a3bf693 --- /dev/null +++ b/force-app/main/default/staticresources/leafletjs/leaflet.js @@ -0,0 +1,6 @@ +/* @preserve + * Leaflet 1.9.4, a JS library for interactive maps. https://leafletjs.com + * (c) 2010-2023 Vladimir Agafonkin, (c) 2010-2011 CloudMade + */ +!function(t,e){"object"==typeof exports&&"undefined"!=typeof module?e(exports):"function"==typeof define&&define.amd?define(["exports"],e):e((t="undefined"!=typeof globalThis?globalThis:t||self).leaflet={})}(this,function(t){"use strict";function l(t){for(var e,i,n=1,o=arguments.length;n=this.min.x&&i.x<=this.max.x&&e.y>=this.min.y&&i.y<=this.max.y},intersects:function(t){t=_(t);var e=this.min,i=this.max,n=t.min,t=t.max,o=t.x>=e.x&&n.x<=i.x,t=t.y>=e.y&&n.y<=i.y;return o&&t},overlaps:function(t){t=_(t);var e=this.min,i=this.max,n=t.min,t=t.max,o=t.x>e.x&&n.xe.y&&n.y=n.lat&&i.lat<=o.lat&&e.lng>=n.lng&&i.lng<=o.lng},intersects:function(t){t=g(t);var e=this._southWest,i=this._northEast,n=t.getSouthWest(),t=t.getNorthEast(),o=t.lat>=e.lat&&n.lat<=i.lat,t=t.lng>=e.lng&&n.lng<=i.lng;return o&&t},overlaps:function(t){t=g(t);var e=this._southWest,i=this._northEast,n=t.getSouthWest(),t=t.getNorthEast(),o=t.lat>e.lat&&n.late.lng&&n.lng","http://www.w3.org/2000/svg"===(Wt.firstChild&&Wt.firstChild.namespaceURI));function y(t){return 0<=navigator.userAgent.toLowerCase().indexOf(t)}var b={ie:pt,ielt9:mt,edge:n,webkit:ft,android:gt,android23:vt,androidStock:yt,opera:xt,chrome:wt,gecko:bt,safari:Pt,phantom:Lt,opera12:o,win:Tt,ie3d:Mt,webkit3d:zt,gecko3d:_t,any3d:Ct,mobile:Zt,mobileWebkit:St,mobileWebkit3d:Et,msPointer:kt,pointer:Ot,touch:Bt,touchNative:At,mobileOpera:It,mobileGecko:Rt,retina:Nt,passiveEvents:Dt,canvas:jt,svg:Ht,vml:!Ht&&function(){try{var t=document.createElement("div"),e=(t.innerHTML='',t.firstChild);return e.style.behavior="url(#default#VML)",e&&"object"==typeof e.adj}catch(t){return!1}}(),inlineSvg:Wt,mac:0===navigator.platform.indexOf("Mac"),linux:0===navigator.platform.indexOf("Linux")},Ft=b.msPointer?"MSPointerDown":"pointerdown",Ut=b.msPointer?"MSPointerMove":"pointermove",Vt=b.msPointer?"MSPointerUp":"pointerup",qt=b.msPointer?"MSPointerCancel":"pointercancel",Gt={touchstart:Ft,touchmove:Ut,touchend:Vt,touchcancel:qt},Kt={touchstart:function(t,e){e.MSPOINTER_TYPE_TOUCH&&e.pointerType===e.MSPOINTER_TYPE_TOUCH&&O(e);ee(t,e)},touchmove:ee,touchend:ee,touchcancel:ee},Yt={},Xt=!1;function Jt(t,e,i){return"touchstart"!==e||Xt||(document.addEventListener(Ft,$t,!0),document.addEventListener(Ut,Qt,!0),document.addEventListener(Vt,te,!0),document.addEventListener(qt,te,!0),Xt=!0),Kt[e]?(i=Kt[e].bind(this,i),t.addEventListener(Gt[e],i,!1),i):(console.warn("wrong event specified:",e),u)}function $t(t){Yt[t.pointerId]=t}function Qt(t){Yt[t.pointerId]&&(Yt[t.pointerId]=t)}function te(t){delete Yt[t.pointerId]}function ee(t,e){if(e.pointerType!==(e.MSPOINTER_TYPE_MOUSE||"mouse")){for(var i in e.touches=[],Yt)e.touches.push(Yt[i]);e.changedTouches=[e],t(e)}}var ie=200;function ne(t,i){t.addEventListener("dblclick",i);var n,o=0;function e(t){var e;1!==t.detail?n=t.detail:"mouse"===t.pointerType||t.sourceCapabilities&&!t.sourceCapabilities.firesTouchEvents||((e=Ne(t)).some(function(t){return t instanceof HTMLLabelElement&&t.attributes.for})&&!e.some(function(t){return t instanceof HTMLInputElement||t instanceof HTMLSelectElement})||((e=Date.now())-o<=ie?2===++n&&i(function(t){var e,i,n={};for(i in t)e=t[i],n[i]=e&&e.bind?e.bind(t):e;return(t=n).type="dblclick",n.detail=2,n.isTrusted=!1,n._simulated=!0,n}(t)):n=1,o=e))}return t.addEventListener("click",e),{dblclick:i,simDblclick:e}}var oe,se,re,ae,he,le,ue=we(["transform","webkitTransform","OTransform","MozTransform","msTransform"]),ce=we(["webkitTransition","transition","OTransition","MozTransition","msTransition"]),de="webkitTransition"===ce||"OTransition"===ce?ce+"End":"transitionend";function _e(t){return"string"==typeof t?document.getElementById(t):t}function pe(t,e){var i=t.style[e]||t.currentStyle&&t.currentStyle[e];return"auto"===(i=i&&"auto"!==i||!document.defaultView?i:(t=document.defaultView.getComputedStyle(t,null))?t[e]:null)?null:i}function P(t,e,i){t=document.createElement(t);return t.className=e||"",i&&i.appendChild(t),t}function T(t){var e=t.parentNode;e&&e.removeChild(t)}function me(t){for(;t.firstChild;)t.removeChild(t.firstChild)}function fe(t){var e=t.parentNode;e&&e.lastChild!==t&&e.appendChild(t)}function ge(t){var e=t.parentNode;e&&e.firstChild!==t&&e.insertBefore(t,e.firstChild)}function ve(t,e){return void 0!==t.classList?t.classList.contains(e):0<(t=xe(t)).length&&new RegExp("(^|\\s)"+e+"(\\s|$)").test(t)}function M(t,e){var i;if(void 0!==t.classList)for(var n=F(e),o=0,s=n.length;othis.options.maxZoom)?this.setZoom(t):this},panInsideBounds:function(t,e){this._enforcingBounds=!0;var i=this.getCenter(),t=this._limitCenter(i,this._zoom,g(t));return i.equals(t)||this.panTo(t,e),this._enforcingBounds=!1,this},panInside:function(t,e){var i=m((e=e||{}).paddingTopLeft||e.padding||[0,0]),n=m(e.paddingBottomRight||e.padding||[0,0]),o=this.project(this.getCenter()),t=this.project(t),s=this.getPixelBounds(),i=_([s.min.add(i),s.max.subtract(n)]),s=i.getSize();return i.contains(t)||(this._enforcingBounds=!0,n=t.subtract(i.getCenter()),i=i.extend(t).getSize().subtract(s),o.x+=n.x<0?-i.x:i.x,o.y+=n.y<0?-i.y:i.y,this.panTo(this.unproject(o),e),this._enforcingBounds=!1),this},invalidateSize:function(t){if(!this._loaded)return this;t=l({animate:!1,pan:!0},!0===t?{animate:!0}:t);var e=this.getSize(),i=(this._sizeChanged=!0,this._lastCenter=null,this.getSize()),n=e.divideBy(2).round(),o=i.divideBy(2).round(),n=n.subtract(o);return n.x||n.y?(t.animate&&t.pan?this.panBy(n):(t.pan&&this._rawPanBy(n),this.fire("move"),t.debounceMoveend?(clearTimeout(this._sizeTimer),this._sizeTimer=setTimeout(a(this.fire,this,"moveend"),200)):this.fire("moveend")),this.fire("resize",{oldSize:e,newSize:i})):this},stop:function(){return this.setZoom(this._limitZoom(this._zoom)),this.options.zoomSnap||this.fire("viewreset"),this._stop()},locate:function(t){var e,i;return t=this._locateOptions=l({timeout:1e4,watch:!1},t),"geolocation"in navigator?(e=a(this._handleGeolocationResponse,this),i=a(this._handleGeolocationError,this),t.watch?this._locationWatchId=navigator.geolocation.watchPosition(e,i,t):navigator.geolocation.getCurrentPosition(e,i,t)):this._handleGeolocationError({code:0,message:"Geolocation not supported."}),this},stopLocate:function(){return navigator.geolocation&&navigator.geolocation.clearWatch&&navigator.geolocation.clearWatch(this._locationWatchId),this._locateOptions&&(this._locateOptions.setView=!1),this},_handleGeolocationError:function(t){var e;this._container._leaflet_id&&(e=t.code,t=t.message||(1===e?"permission denied":2===e?"position unavailable":"timeout"),this._locateOptions.setView&&!this._loaded&&this.fitWorld(),this.fire("locationerror",{code:e,message:"Geolocation error: "+t+"."}))},_handleGeolocationResponse:function(t){if(this._container._leaflet_id){var e,i,n=new v(t.coords.latitude,t.coords.longitude),o=n.toBounds(2*t.coords.accuracy),s=this._locateOptions,r=(s.setView&&(e=this.getBoundsZoom(o),this.setView(n,s.maxZoom?Math.min(e,s.maxZoom):e)),{latlng:n,bounds:o,timestamp:t.timestamp});for(i in t.coords)"number"==typeof t.coords[i]&&(r[i]=t.coords[i]);this.fire("locationfound",r)}},addHandler:function(t,e){return e&&(e=this[t]=new e(this),this._handlers.push(e),this.options[t]&&e.enable()),this},remove:function(){if(this._initEvents(!0),this.options.maxBounds&&this.off("moveend",this._panInsideMaxBounds),this._containerId!==this._container._leaflet_id)throw new Error("Map container is being reused by another instance");try{delete this._container._leaflet_id,delete this._containerId}catch(t){this._container._leaflet_id=void 0,this._containerId=void 0}for(var t in void 0!==this._locationWatchId&&this.stopLocate(),this._stop(),T(this._mapPane),this._clearControlPos&&this._clearControlPos(),this._resizeRequest&&(r(this._resizeRequest),this._resizeRequest=null),this._clearHandlers(),this._loaded&&this.fire("unload"),this._layers)this._layers[t].remove();for(t in this._panes)T(this._panes[t]);return this._layers=[],this._panes=[],delete this._mapPane,delete this._renderer,this},createPane:function(t,e){e=P("div","leaflet-pane"+(t?" leaflet-"+t.replace("Pane","")+"-pane":""),e||this._mapPane);return t&&(this._panes[t]=e),e},getCenter:function(){return this._checkIfLoaded(),this._lastCenter&&!this._moved()?this._lastCenter.clone():this.layerPointToLatLng(this._getCenterLayerPoint())},getZoom:function(){return this._zoom},getBounds:function(){var t=this.getPixelBounds();return new s(this.unproject(t.getBottomLeft()),this.unproject(t.getTopRight()))},getMinZoom:function(){return void 0===this.options.minZoom?this._layersMinZoom||0:this.options.minZoom},getMaxZoom:function(){return void 0===this.options.maxZoom?void 0===this._layersMaxZoom?1/0:this._layersMaxZoom:this.options.maxZoom},getBoundsZoom:function(t,e,i){t=g(t),i=m(i||[0,0]);var n=this.getZoom()||0,o=this.getMinZoom(),s=this.getMaxZoom(),r=t.getNorthWest(),t=t.getSouthEast(),i=this.getSize().subtract(i),t=_(this.project(t,n),this.project(r,n)).getSize(),r=b.any3d?this.options.zoomSnap:1,a=i.x/t.x,i=i.y/t.y,t=e?Math.max(a,i):Math.min(a,i),n=this.getScaleZoom(t,n);return r&&(n=Math.round(n/(r/100))*(r/100),n=e?Math.ceil(n/r)*r:Math.floor(n/r)*r),Math.max(o,Math.min(s,n))},getSize:function(){return this._size&&!this._sizeChanged||(this._size=new p(this._container.clientWidth||0,this._container.clientHeight||0),this._sizeChanged=!1),this._size.clone()},getPixelBounds:function(t,e){t=this._getTopLeftPoint(t,e);return new f(t,t.add(this.getSize()))},getPixelOrigin:function(){return this._checkIfLoaded(),this._pixelOrigin},getPixelWorldBounds:function(t){return this.options.crs.getProjectedBounds(void 0===t?this.getZoom():t)},getPane:function(t){return"string"==typeof t?this._panes[t]:t},getPanes:function(){return this._panes},getContainer:function(){return this._container},getZoomScale:function(t,e){var i=this.options.crs;return e=void 0===e?this._zoom:e,i.scale(t)/i.scale(e)},getScaleZoom:function(t,e){var i=this.options.crs,t=(e=void 0===e?this._zoom:e,i.zoom(t*i.scale(e)));return isNaN(t)?1/0:t},project:function(t,e){return e=void 0===e?this._zoom:e,this.options.crs.latLngToPoint(w(t),e)},unproject:function(t,e){return e=void 0===e?this._zoom:e,this.options.crs.pointToLatLng(m(t),e)},layerPointToLatLng:function(t){t=m(t).add(this.getPixelOrigin());return this.unproject(t)},latLngToLayerPoint:function(t){return this.project(w(t))._round()._subtract(this.getPixelOrigin())},wrapLatLng:function(t){return this.options.crs.wrapLatLng(w(t))},wrapLatLngBounds:function(t){return this.options.crs.wrapLatLngBounds(g(t))},distance:function(t,e){return this.options.crs.distance(w(t),w(e))},containerPointToLayerPoint:function(t){return m(t).subtract(this._getMapPanePos())},layerPointToContainerPoint:function(t){return m(t).add(this._getMapPanePos())},containerPointToLatLng:function(t){t=this.containerPointToLayerPoint(m(t));return this.layerPointToLatLng(t)},latLngToContainerPoint:function(t){return this.layerPointToContainerPoint(this.latLngToLayerPoint(w(t)))},mouseEventToContainerPoint:function(t){return De(t,this._container)},mouseEventToLayerPoint:function(t){return this.containerPointToLayerPoint(this.mouseEventToContainerPoint(t))},mouseEventToLatLng:function(t){return this.layerPointToLatLng(this.mouseEventToLayerPoint(t))},_initContainer:function(t){t=this._container=_e(t);if(!t)throw new Error("Map container not found.");if(t._leaflet_id)throw new Error("Map container is already initialized.");S(t,"scroll",this._onScroll,this),this._containerId=h(t)},_initLayout:function(){var t=this._container,e=(this._fadeAnimated=this.options.fadeAnimation&&b.any3d,M(t,"leaflet-container"+(b.touch?" leaflet-touch":"")+(b.retina?" leaflet-retina":"")+(b.ielt9?" leaflet-oldie":"")+(b.safari?" leaflet-safari":"")+(this._fadeAnimated?" leaflet-fade-anim":"")),pe(t,"position"));"absolute"!==e&&"relative"!==e&&"fixed"!==e&&"sticky"!==e&&(t.style.position="relative"),this._initPanes(),this._initControlPos&&this._initControlPos()},_initPanes:function(){var t=this._panes={};this._paneRenderers={},this._mapPane=this.createPane("mapPane",this._container),Z(this._mapPane,new p(0,0)),this.createPane("tilePane"),this.createPane("overlayPane"),this.createPane("shadowPane"),this.createPane("markerPane"),this.createPane("tooltipPane"),this.createPane("popupPane"),this.options.markerZoomAnimation||(M(t.markerPane,"leaflet-zoom-hide"),M(t.shadowPane,"leaflet-zoom-hide"))},_resetView:function(t,e,i){Z(this._mapPane,new p(0,0));var n=!this._loaded,o=(this._loaded=!0,e=this._limitZoom(e),this.fire("viewprereset"),this._zoom!==e);this._moveStart(o,i)._move(t,e)._moveEnd(o),this.fire("viewreset"),n&&this.fire("load")},_moveStart:function(t,e){return t&&this.fire("zoomstart"),e||this.fire("movestart"),this},_move:function(t,e,i,n){void 0===e&&(e=this._zoom);var o=this._zoom!==e;return this._zoom=e,this._lastCenter=t,this._pixelOrigin=this._getNewPixelOrigin(t),n?i&&i.pinch&&this.fire("zoom",i):((o||i&&i.pinch)&&this.fire("zoom",i),this.fire("move",i)),this},_moveEnd:function(t){return t&&this.fire("zoomend"),this.fire("moveend")},_stop:function(){return r(this._flyToFrame),this._panAnim&&this._panAnim.stop(),this},_rawPanBy:function(t){Z(this._mapPane,this._getMapPanePos().subtract(t))},_getZoomSpan:function(){return this.getMaxZoom()-this.getMinZoom()},_panInsideMaxBounds:function(){this._enforcingBounds||this.panInsideBounds(this.options.maxBounds)},_checkIfLoaded:function(){if(!this._loaded)throw new Error("Set map center and zoom first.")},_initEvents:function(t){this._targets={};var e=t?k:S;e((this._targets[h(this._container)]=this)._container,"click dblclick mousedown mouseup mouseover mouseout mousemove contextmenu keypress keydown keyup",this._handleDOMEvent,this),this.options.trackResize&&e(window,"resize",this._onResize,this),b.any3d&&this.options.transform3DLimit&&(t?this.off:this.on).call(this,"moveend",this._onMoveEnd)},_onResize:function(){r(this._resizeRequest),this._resizeRequest=x(function(){this.invalidateSize({debounceMoveend:!0})},this)},_onScroll:function(){this._container.scrollTop=0,this._container.scrollLeft=0},_onMoveEnd:function(){var t=this._getMapPanePos();Math.max(Math.abs(t.x),Math.abs(t.y))>=this.options.transform3DLimit&&this._resetView(this.getCenter(),this.getZoom())},_findEventTargets:function(t,e){for(var i,n=[],o="mouseout"===e||"mouseover"===e,s=t.target||t.srcElement,r=!1;s;){if((i=this._targets[h(s)])&&("click"===e||"preclick"===e)&&this._draggableMoved(i)){r=!0;break}if(i&&i.listens(e,!0)){if(o&&!We(s,t))break;if(n.push(i),o)break}if(s===this._container)break;s=s.parentNode}return n=n.length||r||o||!this.listens(e,!0)?n:[this]},_isClickDisabled:function(t){for(;t&&t!==this._container;){if(t._leaflet_disable_click)return!0;t=t.parentNode}},_handleDOMEvent:function(t){var e,i=t.target||t.srcElement;!this._loaded||i._leaflet_disable_events||"click"===t.type&&this._isClickDisabled(i)||("mousedown"===(e=t.type)&&Me(i),this._fireDOMEvent(t,e))},_mouseEvents:["click","dblclick","mouseover","mouseout","contextmenu"],_fireDOMEvent:function(t,e,i){"click"===t.type&&((a=l({},t)).type="preclick",this._fireDOMEvent(a,a.type,i));var n=this._findEventTargets(t,e);if(i){for(var o=[],s=0;sthis.options.zoomAnimationThreshold)return!1;var n=this.getZoomScale(e),n=this._getCenterOffset(t)._divideBy(1-1/n);if(!0!==i.animate&&!this.getSize().contains(n))return!1;x(function(){this._moveStart(!0,i.noMoveStart||!1)._animateZoom(t,e,!0)},this)}return!0},_animateZoom:function(t,e,i,n){this._mapPane&&(i&&(this._animatingZoom=!0,this._animateToCenter=t,this._animateToZoom=e,M(this._mapPane,"leaflet-zoom-anim")),this.fire("zoomanim",{center:t,zoom:e,noUpdate:n}),this._tempFireZoomEvent||(this._tempFireZoomEvent=this._zoom!==this._animateToZoom),this._move(this._animateToCenter,this._animateToZoom,void 0,!0),setTimeout(a(this._onZoomTransitionEnd,this),250))},_onZoomTransitionEnd:function(){this._animatingZoom&&(this._mapPane&&z(this._mapPane,"leaflet-zoom-anim"),this._animatingZoom=!1,this._move(this._animateToCenter,this._animateToZoom,void 0,!0),this._tempFireZoomEvent&&this.fire("zoom"),delete this._tempFireZoomEvent,this.fire("move"),this._moveEnd(!0))}});function Ue(t){return new B(t)}var B=et.extend({options:{position:"topright"},initialize:function(t){c(this,t)},getPosition:function(){return this.options.position},setPosition:function(t){var e=this._map;return e&&e.removeControl(this),this.options.position=t,e&&e.addControl(this),this},getContainer:function(){return this._container},addTo:function(t){this.remove(),this._map=t;var e=this._container=this.onAdd(t),i=this.getPosition(),t=t._controlCorners[i];return M(e,"leaflet-control"),-1!==i.indexOf("bottom")?t.insertBefore(e,t.firstChild):t.appendChild(e),this._map.on("unload",this.remove,this),this},remove:function(){return this._map&&(T(this._container),this.onRemove&&this.onRemove(this._map),this._map.off("unload",this.remove,this),this._map=null),this},_refocusOnMap:function(t){this._map&&t&&0",e=document.createElement("div");return e.innerHTML=t,e.firstChild},_addItem:function(t){var e,i=document.createElement("label"),n=this._map.hasLayer(t.layer),n=(t.overlay?((e=document.createElement("input")).type="checkbox",e.className="leaflet-control-layers-selector",e.defaultChecked=n):e=this._createRadioElement("leaflet-base-layers_"+h(this),n),this._layerControlInputs.push(e),e.layerId=h(t.layer),S(e,"click",this._onInputClick,this),document.createElement("span")),o=(n.innerHTML=" "+t.name,document.createElement("span"));return i.appendChild(o),o.appendChild(e),o.appendChild(n),(t.overlay?this._overlaysList:this._baseLayersList).appendChild(i),this._checkDisabledLayers(),i},_onInputClick:function(){if(!this._preventClick){var t,e,i=this._layerControlInputs,n=[],o=[];this._handlingClick=!0;for(var s=i.length-1;0<=s;s--)t=i[s],e=this._getLayer(t.layerId).layer,t.checked?n.push(e):t.checked||o.push(e);for(s=0;se.options.maxZoom},_expandIfNotCollapsed:function(){return this._map&&!this.options.collapsed&&this.expand(),this},_expandSafely:function(){var t=this._section,e=(this._preventClick=!0,S(t,"click",O),this.expand(),this);setTimeout(function(){k(t,"click",O),e._preventClick=!1})}})),qe=B.extend({options:{position:"topleft",zoomInText:'',zoomInTitle:"Zoom in",zoomOutText:'',zoomOutTitle:"Zoom out"},onAdd:function(t){var e="leaflet-control-zoom",i=P("div",e+" leaflet-bar"),n=this.options;return this._zoomInButton=this._createButton(n.zoomInText,n.zoomInTitle,e+"-in",i,this._zoomIn),this._zoomOutButton=this._createButton(n.zoomOutText,n.zoomOutTitle,e+"-out",i,this._zoomOut),this._updateDisabled(),t.on("zoomend zoomlevelschange",this._updateDisabled,this),i},onRemove:function(t){t.off("zoomend zoomlevelschange",this._updateDisabled,this)},disable:function(){return this._disabled=!0,this._updateDisabled(),this},enable:function(){return this._disabled=!1,this._updateDisabled(),this},_zoomIn:function(t){!this._disabled&&this._map._zoomthis._map.getMinZoom()&&this._map.zoomOut(this._map.options.zoomDelta*(t.shiftKey?3:1))},_createButton:function(t,e,i,n,o){i=P("a",i,n);return i.innerHTML=t,i.href="#",i.title=e,i.setAttribute("role","button"),i.setAttribute("aria-label",e),Ie(i),S(i,"click",Re),S(i,"click",o,this),S(i,"click",this._refocusOnMap,this),i},_updateDisabled:function(){var t=this._map,e="leaflet-disabled";z(this._zoomInButton,e),z(this._zoomOutButton,e),this._zoomInButton.setAttribute("aria-disabled","false"),this._zoomOutButton.setAttribute("aria-disabled","false"),!this._disabled&&t._zoom!==t.getMinZoom()||(M(this._zoomOutButton,e),this._zoomOutButton.setAttribute("aria-disabled","true")),!this._disabled&&t._zoom!==t.getMaxZoom()||(M(this._zoomInButton,e),this._zoomInButton.setAttribute("aria-disabled","true"))}}),Ge=(A.mergeOptions({zoomControl:!0}),A.addInitHook(function(){this.options.zoomControl&&(this.zoomControl=new qe,this.addControl(this.zoomControl))}),B.extend({options:{position:"bottomleft",maxWidth:100,metric:!0,imperial:!0},onAdd:function(t){var e="leaflet-control-scale",i=P("div",e),n=this.options;return this._addScales(n,e+"-line",i),t.on(n.updateWhenIdle?"moveend":"move",this._update,this),t.whenReady(this._update,this),i},onRemove:function(t){t.off(this.options.updateWhenIdle?"moveend":"move",this._update,this)},_addScales:function(t,e,i){t.metric&&(this._mScale=P("div",e,i)),t.imperial&&(this._iScale=P("div",e,i))},_update:function(){var t=this._map,e=t.getSize().y/2,t=t.distance(t.containerPointToLatLng([0,e]),t.containerPointToLatLng([this.options.maxWidth,e]));this._updateScales(t)},_updateScales:function(t){this.options.metric&&t&&this._updateMetric(t),this.options.imperial&&t&&this._updateImperial(t)},_updateMetric:function(t){var e=this._getRoundNum(t);this._updateScale(this._mScale,e<1e3?e+" m":e/1e3+" km",e/t)},_updateImperial:function(t){var e,i,t=3.2808399*t;5280'+(b.inlineSvg?' ':"")+"Leaflet"},initialize:function(t){c(this,t),this._attributions={}},onAdd:function(t){for(var e in(t.attributionControl=this)._container=P("div","leaflet-control-attribution"),Ie(this._container),t._layers)t._layers[e].getAttribution&&this.addAttribution(t._layers[e].getAttribution());return this._update(),t.on("layeradd",this._addAttribution,this),this._container},onRemove:function(t){t.off("layeradd",this._addAttribution,this)},_addAttribution:function(t){t.layer.getAttribution&&(this.addAttribution(t.layer.getAttribution()),t.layer.once("remove",function(){this.removeAttribution(t.layer.getAttribution())},this))},setPrefix:function(t){return this.options.prefix=t,this._update(),this},addAttribution:function(t){return t&&(this._attributions[t]||(this._attributions[t]=0),this._attributions[t]++,this._update()),this},removeAttribution:function(t){return t&&this._attributions[t]&&(this._attributions[t]--,this._update()),this},_update:function(){if(this._map){var t,e=[];for(t in this._attributions)this._attributions[t]&&e.push(t);var i=[];this.options.prefix&&i.push(this.options.prefix),e.length&&i.push(e.join(", ")),this._container.innerHTML=i.join(' ')}}}),n=(A.mergeOptions({attributionControl:!0}),A.addInitHook(function(){this.options.attributionControl&&(new Ke).addTo(this)}),B.Layers=Ve,B.Zoom=qe,B.Scale=Ge,B.Attribution=Ke,Ue.layers=function(t,e,i){return new Ve(t,e,i)},Ue.zoom=function(t){return new qe(t)},Ue.scale=function(t){return new Ge(t)},Ue.attribution=function(t){return new Ke(t)},et.extend({initialize:function(t){this._map=t},enable:function(){return this._enabled||(this._enabled=!0,this.addHooks()),this},disable:function(){return this._enabled&&(this._enabled=!1,this.removeHooks()),this},enabled:function(){return!!this._enabled}})),ft=(n.addTo=function(t,e){return t.addHandler(e,this),this},{Events:e}),Ye=b.touch?"touchstart mousedown":"mousedown",Xe=it.extend({options:{clickTolerance:3},initialize:function(t,e,i,n){c(this,n),this._element=t,this._dragStartTarget=e||t,this._preventOutline=i},enable:function(){this._enabled||(S(this._dragStartTarget,Ye,this._onDown,this),this._enabled=!0)},disable:function(){this._enabled&&(Xe._dragging===this&&this.finishDrag(!0),k(this._dragStartTarget,Ye,this._onDown,this),this._enabled=!1,this._moved=!1)},_onDown:function(t){var e,i;this._enabled&&(this._moved=!1,ve(this._element,"leaflet-zoom-anim")||(t.touches&&1!==t.touches.length?Xe._dragging===this&&this.finishDrag():Xe._dragging||t.shiftKey||1!==t.which&&1!==t.button&&!t.touches||((Xe._dragging=this)._preventOutline&&Me(this._element),Le(),re(),this._moving||(this.fire("down"),i=t.touches?t.touches[0]:t,e=Ce(this._element),this._startPoint=new p(i.clientX,i.clientY),this._startPos=Pe(this._element),this._parentScale=Ze(e),i="mousedown"===t.type,S(document,i?"mousemove":"touchmove",this._onMove,this),S(document,i?"mouseup":"touchend touchcancel",this._onUp,this)))))},_onMove:function(t){var e;this._enabled&&(t.touches&&1e&&(i.push(t[n]),o=n);oe.max.x&&(i|=2),t.ye.max.y&&(i|=8),i}function ri(t,e,i,n){var o=e.x,e=e.y,s=i.x-o,r=i.y-e,a=s*s+r*r;return 0this._layersMaxZoom&&this.setZoom(this._layersMaxZoom),void 0===this.options.minZoom&&this._layersMinZoom&&this.getZoom()t.y!=n.y>t.y&&t.x<(n.x-i.x)*(t.y-i.y)/(n.y-i.y)+i.x&&(l=!l);return l||yi.prototype._containsPoint.call(this,t,!0)}});var wi=ci.extend({initialize:function(t,e){c(this,e),this._layers={},t&&this.addData(t)},addData:function(t){var e,i,n,o=d(t)?t:t.features;if(o){for(e=0,i=o.length;es.x&&(r=i.x+a-s.x+o.x),i.x-r-n.x<(a=0)&&(r=i.x-n.x),i.y+e+o.y>s.y&&(a=i.y+e-s.y+o.y),i.y-a-n.y<0&&(a=i.y-n.y),(r||a)&&(this.options.keepInView&&(this._autopanning=!0),t.fire("autopanstart").panBy([r,a]))))},_getAnchor:function(){return m(this._source&&this._source._getPopupAnchor?this._source._getPopupAnchor():[0,0])}})),Ii=(A.mergeOptions({closePopupOnClick:!0}),A.include({openPopup:function(t,e,i){return this._initOverlay(Bi,t,e,i).openOn(this),this},closePopup:function(t){return(t=arguments.length?t:this._popup)&&t.close(),this}}),o.include({bindPopup:function(t,e){return this._popup=this._initOverlay(Bi,this._popup,t,e),this._popupHandlersAdded||(this.on({click:this._openPopup,keypress:this._onKeyPress,remove:this.closePopup,move:this._movePopup}),this._popupHandlersAdded=!0),this},unbindPopup:function(){return this._popup&&(this.off({click:this._openPopup,keypress:this._onKeyPress,remove:this.closePopup,move:this._movePopup}),this._popupHandlersAdded=!1,this._popup=null),this},openPopup:function(t){return this._popup&&(this instanceof ci||(this._popup._source=this),this._popup._prepareOpen(t||this._latlng)&&this._popup.openOn(this._map)),this},closePopup:function(){return this._popup&&this._popup.close(),this},togglePopup:function(){return this._popup&&this._popup.toggle(this),this},isPopupOpen:function(){return!!this._popup&&this._popup.isOpen()},setPopupContent:function(t){return this._popup&&this._popup.setContent(t),this},getPopup:function(){return this._popup},_openPopup:function(t){var e;this._popup&&this._map&&(Re(t),e=t.layer||t.target,this._popup._source!==e||e instanceof fi?(this._popup._source=e,this.openPopup(t.latlng)):this._map.hasLayer(this._popup)?this.closePopup():this.openPopup(t.latlng))},_movePopup:function(t){this._popup.setLatLng(t.latlng)},_onKeyPress:function(t){13===t.originalEvent.keyCode&&this._openPopup(t)}}),Ai.extend({options:{pane:"tooltipPane",offset:[0,0],direction:"auto",permanent:!1,sticky:!1,opacity:.9},onAdd:function(t){Ai.prototype.onAdd.call(this,t),this.setOpacity(this.options.opacity),t.fire("tooltipopen",{tooltip:this}),this._source&&(this.addEventParent(this._source),this._source.fire("tooltipopen",{tooltip:this},!0))},onRemove:function(t){Ai.prototype.onRemove.call(this,t),t.fire("tooltipclose",{tooltip:this}),this._source&&(this.removeEventParent(this._source),this._source.fire("tooltipclose",{tooltip:this},!0))},getEvents:function(){var t=Ai.prototype.getEvents.call(this);return this.options.permanent||(t.preclick=this.close),t},_initLayout:function(){var t="leaflet-tooltip "+(this.options.className||"")+" leaflet-zoom-"+(this._zoomAnimated?"animated":"hide");this._contentNode=this._container=P("div",t),this._container.setAttribute("role","tooltip"),this._container.setAttribute("id","leaflet-tooltip-"+h(this))},_updateLayout:function(){},_adjustPan:function(){},_setPosition:function(t){var e,i=this._map,n=this._container,o=i.latLngToContainerPoint(i.getCenter()),i=i.layerPointToContainerPoint(t),s=this.options.direction,r=n.offsetWidth,a=n.offsetHeight,h=m(this.options.offset),l=this._getAnchor(),i="top"===s?(e=r/2,a):"bottom"===s?(e=r/2,0):(e="center"===s?r/2:"right"===s?0:"left"===s?r:i.xthis.options.maxZoom||nthis.options.maxZoom||void 0!==this.options.minZoom&&oi.max.x)||!e.wrapLat&&(t.yi.max.y))return!1}return!this.options.bounds||(e=this._tileCoordsToBounds(t),g(this.options.bounds).overlaps(e))},_keyToBounds:function(t){return this._tileCoordsToBounds(this._keyToTileCoords(t))},_tileCoordsToNwSe:function(t){var e=this._map,i=this.getTileSize(),n=t.scaleBy(i),i=n.add(i);return[e.unproject(n,t.z),e.unproject(i,t.z)]},_tileCoordsToBounds:function(t){t=this._tileCoordsToNwSe(t),t=new s(t[0],t[1]);return t=this.options.noWrap?t:this._map.wrapLatLngBounds(t)},_tileCoordsToKey:function(t){return t.x+":"+t.y+":"+t.z},_keyToTileCoords:function(t){var t=t.split(":"),e=new p(+t[0],+t[1]);return e.z=+t[2],e},_removeTile:function(t){var e=this._tiles[t];e&&(T(e.el),delete this._tiles[t],this.fire("tileunload",{tile:e.el,coords:this._keyToTileCoords(t)}))},_initTile:function(t){M(t,"leaflet-tile");var e=this.getTileSize();t.style.width=e.x+"px",t.style.height=e.y+"px",t.onselectstart=u,t.onmousemove=u,b.ielt9&&this.options.opacity<1&&C(t,this.options.opacity)},_addTile:function(t,e){var i=this._getTilePos(t),n=this._tileCoordsToKey(t),o=this.createTile(this._wrapCoords(t),a(this._tileReady,this,t));this._initTile(o),this.createTile.length<2&&x(a(this._tileReady,this,t,null,o)),Z(o,i),this._tiles[n]={el:o,coords:t,current:!0},e.appendChild(o),this.fire("tileloadstart",{tile:o,coords:t})},_tileReady:function(t,e,i){e&&this.fire("tileerror",{error:e,tile:i,coords:t});var n=this._tileCoordsToKey(t);(i=this._tiles[n])&&(i.loaded=+new Date,this._map._fadeAnimated?(C(i.el,0),r(this._fadeFrame),this._fadeFrame=x(this._updateOpacity,this)):(i.active=!0,this._pruneTiles()),e||(M(i.el,"leaflet-tile-loaded"),this.fire("tileload",{tile:i.el,coords:t})),this._noTilesToLoad()&&(this._loading=!1,this.fire("load"),b.ielt9||!this._map._fadeAnimated?x(this._pruneTiles,this):setTimeout(a(this._pruneTiles,this),250)))},_getTilePos:function(t){return t.scaleBy(this.getTileSize()).subtract(this._level.origin)},_wrapCoords:function(t){var e=new p(this._wrapX?H(t.x,this._wrapX):t.x,this._wrapY?H(t.y,this._wrapY):t.y);return e.z=t.z,e},_pxBoundsToTileRange:function(t){var e=this.getTileSize();return new f(t.min.unscaleBy(e).floor(),t.max.unscaleBy(e).ceil().subtract([1,1]))},_noTilesToLoad:function(){for(var t in this._tiles)if(!this._tiles[t].loaded)return!1;return!0}});var Di=Ni.extend({options:{minZoom:0,maxZoom:18,subdomains:"abc",errorTileUrl:"",zoomOffset:0,tms:!1,zoomReverse:!1,detectRetina:!1,crossOrigin:!1,referrerPolicy:!1},initialize:function(t,e){this._url=t,(e=c(this,e)).detectRetina&&b.retina&&0')}}catch(t){}return function(t){return document.createElement("<"+t+' xmlns="urn:schemas-microsoft.com:vml" class="lvml">')}}(),zt={_initContainer:function(){this._container=P("div","leaflet-vml-container")},_update:function(){this._map._animatingZoom||(Wi.prototype._update.call(this),this.fire("update"))},_initPath:function(t){var e=t._container=Vi("shape");M(e,"leaflet-vml-shape "+(this.options.className||"")),e.coordsize="1 1",t._path=Vi("path"),e.appendChild(t._path),this._updateStyle(t),this._layers[h(t)]=t},_addPath:function(t){var e=t._container;this._container.appendChild(e),t.options.interactive&&t.addInteractiveTarget(e)},_removePath:function(t){var e=t._container;T(e),t.removeInteractiveTarget(e),delete this._layers[h(t)]},_updateStyle:function(t){var e=t._stroke,i=t._fill,n=t.options,o=t._container;o.stroked=!!n.stroke,o.filled=!!n.fill,n.stroke?(e=e||(t._stroke=Vi("stroke")),o.appendChild(e),e.weight=n.weight+"px",e.color=n.color,e.opacity=n.opacity,n.dashArray?e.dashStyle=d(n.dashArray)?n.dashArray.join(" "):n.dashArray.replace(/( *, *)/g," "):e.dashStyle="",e.endcap=n.lineCap.replace("butt","flat"),e.joinstyle=n.lineJoin):e&&(o.removeChild(e),t._stroke=null),n.fill?(i=i||(t._fill=Vi("fill")),o.appendChild(i),i.color=n.fillColor||n.color,i.opacity=n.fillOpacity):i&&(o.removeChild(i),t._fill=null)},_updateCircle:function(t){var e=t._point.round(),i=Math.round(t._radius),n=Math.round(t._radiusY||i);this._setPath(t,t._empty()?"M0 0":"AL "+e.x+","+e.y+" "+i+","+n+" 0,23592600")},_setPath:function(t,e){t._path.v=e},_bringToFront:function(t){fe(t._container)},_bringToBack:function(t){ge(t._container)}},qi=b.vml?Vi:ct,Gi=Wi.extend({_initContainer:function(){this._container=qi("svg"),this._container.setAttribute("pointer-events","none"),this._rootGroup=qi("g"),this._container.appendChild(this._rootGroup)},_destroyContainer:function(){T(this._container),k(this._container),delete this._container,delete this._rootGroup,delete this._svgSize},_update:function(){var t,e,i;this._map._animatingZoom&&this._bounds||(Wi.prototype._update.call(this),e=(t=this._bounds).getSize(),i=this._container,this._svgSize&&this._svgSize.equals(e)||(this._svgSize=e,i.setAttribute("width",e.x),i.setAttribute("height",e.y)),Z(i,t.min),i.setAttribute("viewBox",[t.min.x,t.min.y,e.x,e.y].join(" ")),this.fire("update"))},_initPath:function(t){var e=t._path=qi("path");t.options.className&&M(e,t.options.className),t.options.interactive&&M(e,"leaflet-interactive"),this._updateStyle(t),this._layers[h(t)]=t},_addPath:function(t){this._rootGroup||this._initContainer(),this._rootGroup.appendChild(t._path),t.addInteractiveTarget(t._path)},_removePath:function(t){T(t._path),t.removeInteractiveTarget(t._path),delete this._layers[h(t)]},_updatePath:function(t){t._project(),t._update()},_updateStyle:function(t){var e=t._path,t=t.options;e&&(t.stroke?(e.setAttribute("stroke",t.color),e.setAttribute("stroke-opacity",t.opacity),e.setAttribute("stroke-width",t.weight),e.setAttribute("stroke-linecap",t.lineCap),e.setAttribute("stroke-linejoin",t.lineJoin),t.dashArray?e.setAttribute("stroke-dasharray",t.dashArray):e.removeAttribute("stroke-dasharray"),t.dashOffset?e.setAttribute("stroke-dashoffset",t.dashOffset):e.removeAttribute("stroke-dashoffset")):e.setAttribute("stroke","none"),t.fill?(e.setAttribute("fill",t.fillColor||t.color),e.setAttribute("fill-opacity",t.fillOpacity),e.setAttribute("fill-rule",t.fillRule||"evenodd")):e.setAttribute("fill","none"))},_updatePoly:function(t,e){this._setPath(t,dt(t._parts,e))},_updateCircle:function(t){var e=t._point,i=Math.max(Math.round(t._radius),1),n="a"+i+","+(Math.max(Math.round(t._radiusY),1)||i)+" 0 1,0 ",e=t._empty()?"M0 0":"M"+(e.x-i)+","+e.y+n+2*i+",0 "+n+2*-i+",0 ";this._setPath(t,e)},_setPath:function(t,e){t._path.setAttribute("d",e)},_bringToFront:function(t){fe(t._path)},_bringToBack:function(t){ge(t._path)}});function Ki(t){return b.svg||b.vml?new Gi(t):null}b.vml&&Gi.include(zt),A.include({getRenderer:function(t){t=(t=t.options.renderer||this._getPaneRenderer(t.options.pane)||this.options.renderer||this._renderer)||(this._renderer=this._createRenderer());return this.hasLayer(t)||this.addLayer(t),t},_getPaneRenderer:function(t){var e;return"overlayPane"!==t&&void 0!==t&&(void 0===(e=this._paneRenderers[t])&&(e=this._createRenderer({pane:t}),this._paneRenderers[t]=e),e)},_createRenderer:function(t){return this.options.preferCanvas&&Ui(t)||Ki(t)}});var Yi=xi.extend({initialize:function(t,e){xi.prototype.initialize.call(this,this._boundsToLatLngs(t),e)},setBounds:function(t){return this.setLatLngs(this._boundsToLatLngs(t))},_boundsToLatLngs:function(t){return[(t=g(t)).getSouthWest(),t.getNorthWest(),t.getNorthEast(),t.getSouthEast()]}});Gi.create=qi,Gi.pointsToPath=dt,wi.geometryToLayer=bi,wi.coordsToLatLng=Li,wi.coordsToLatLngs=Ti,wi.latLngToCoords=Mi,wi.latLngsToCoords=zi,wi.getFeature=Ci,wi.asFeature=Zi,A.mergeOptions({boxZoom:!0});var _t=n.extend({initialize:function(t){this._map=t,this._container=t._container,this._pane=t._panes.overlayPane,this._resetStateTimeout=0,t.on("unload",this._destroy,this)},addHooks:function(){S(this._container,"mousedown",this._onMouseDown,this)},removeHooks:function(){k(this._container,"mousedown",this._onMouseDown,this)},moved:function(){return this._moved},_destroy:function(){T(this._pane),delete this._pane},_resetState:function(){this._resetStateTimeout=0,this._moved=!1},_clearDeferredResetState:function(){0!==this._resetStateTimeout&&(clearTimeout(this._resetStateTimeout),this._resetStateTimeout=0)},_onMouseDown:function(t){if(!t.shiftKey||1!==t.which&&1!==t.button)return!1;this._clearDeferredResetState(),this._resetState(),re(),Le(),this._startPoint=this._map.mouseEventToContainerPoint(t),S(document,{contextmenu:Re,mousemove:this._onMouseMove,mouseup:this._onMouseUp,keydown:this._onKeyDown},this)},_onMouseMove:function(t){this._moved||(this._moved=!0,this._box=P("div","leaflet-zoom-box",this._container),M(this._container,"leaflet-crosshair"),this._map.fire("boxzoomstart")),this._point=this._map.mouseEventToContainerPoint(t);var t=new f(this._point,this._startPoint),e=t.getSize();Z(this._box,t.min),this._box.style.width=e.x+"px",this._box.style.height=e.y+"px"},_finish:function(){this._moved&&(T(this._box),z(this._container,"leaflet-crosshair")),ae(),Te(),k(document,{contextmenu:Re,mousemove:this._onMouseMove,mouseup:this._onMouseUp,keydown:this._onKeyDown},this)},_onMouseUp:function(t){1!==t.which&&1!==t.button||(this._finish(),this._moved&&(this._clearDeferredResetState(),this._resetStateTimeout=setTimeout(a(this._resetState,this),0),t=new s(this._map.containerPointToLatLng(this._startPoint),this._map.containerPointToLatLng(this._point)),this._map.fitBounds(t).fire("boxzoomend",{boxZoomBounds:t})))},_onKeyDown:function(t){27===t.keyCode&&(this._finish(),this._clearDeferredResetState(),this._resetState())}}),Ct=(A.addInitHook("addHandler","boxZoom",_t),A.mergeOptions({doubleClickZoom:!0}),n.extend({addHooks:function(){this._map.on("dblclick",this._onDoubleClick,this)},removeHooks:function(){this._map.off("dblclick",this._onDoubleClick,this)},_onDoubleClick:function(t){var e=this._map,i=e.getZoom(),n=e.options.zoomDelta,i=t.originalEvent.shiftKey?i-n:i+n;"center"===e.options.doubleClickZoom?e.setZoom(i):e.setZoomAround(t.containerPoint,i)}})),Zt=(A.addInitHook("addHandler","doubleClickZoom",Ct),A.mergeOptions({dragging:!0,inertia:!0,inertiaDeceleration:3400,inertiaMaxSpeed:1/0,easeLinearity:.2,worldCopyJump:!1,maxBoundsViscosity:0}),n.extend({addHooks:function(){var t;this._draggable||(t=this._map,this._draggable=new Xe(t._mapPane,t._container),this._draggable.on({dragstart:this._onDragStart,drag:this._onDrag,dragend:this._onDragEnd},this),this._draggable.on("predrag",this._onPreDragLimit,this),t.options.worldCopyJump&&(this._draggable.on("predrag",this._onPreDragWrap,this),t.on("zoomend",this._onZoomEnd,this),t.whenReady(this._onZoomEnd,this))),M(this._map._container,"leaflet-grab leaflet-touch-drag"),this._draggable.enable(),this._positions=[],this._times=[]},removeHooks:function(){z(this._map._container,"leaflet-grab"),z(this._map._container,"leaflet-touch-drag"),this._draggable.disable()},moved:function(){return this._draggable&&this._draggable._moved},moving:function(){return this._draggable&&this._draggable._moving},_onDragStart:function(){var t,e=this._map;e._stop(),this._map.options.maxBounds&&this._map.options.maxBoundsViscosity?(t=g(this._map.options.maxBounds),this._offsetLimit=_(this._map.latLngToContainerPoint(t.getNorthWest()).multiplyBy(-1),this._map.latLngToContainerPoint(t.getSouthEast()).multiplyBy(-1).add(this._map.getSize())),this._viscosity=Math.min(1,Math.max(0,this._map.options.maxBoundsViscosity))):this._offsetLimit=null,e.fire("movestart").fire("dragstart"),e.options.inertia&&(this._positions=[],this._times=[])},_onDrag:function(t){var e,i;this._map.options.inertia&&(e=this._lastTime=+new Date,i=this._lastPos=this._draggable._absPos||this._draggable._newPos,this._positions.push(i),this._times.push(e),this._prunePositions(e)),this._map.fire("move",t).fire("drag",t)},_prunePositions:function(t){for(;1e.max.x&&(t.x=this._viscousLimit(t.x,e.max.x)),t.y>e.max.y&&(t.y=this._viscousLimit(t.y,e.max.y)),this._draggable._newPos=this._draggable._startPos.add(t))},_onPreDragWrap:function(){var t=this._worldWidth,e=Math.round(t/2),i=this._initialWorldOffset,n=this._draggable._newPos.x,o=(n-e+i)%t+e-i,n=(n+e+i)%t-e-i,t=Math.abs(o+i)e.getMaxZoom()&&1 + + Private + application/json + Sample data used to initialize Broker__c records + diff --git a/force-app/main/default/staticresources/sample_data_contacts.json b/force-app/main/default/staticresources/sample_data_contacts.json new file mode 100644 index 0000000..79e47c2 --- /dev/null +++ b/force-app/main/default/staticresources/sample_data_contacts.json @@ -0,0 +1,32 @@ +[ + { + "FirstName": "Brad", + "LastName": "Holmes", + "Phone": "617-555-0143", + "Email": "bholmes@goodmail.com" + }, + { + "FirstName": "Leslie", + "LastName": "Martin", + "Phone": "617-555-0112", + "Email": "leslie@pentagon.com" + }, + { + "FirstName": "July", + "LastName": "Walker", + "Phone": "617-555-0170", + "Email": "julywalker@brain.com" + }, + { + "FirstName": "Anna", + "LastName": "Jones", + "Phone": "617-555-0181", + "Email": "annaj@mymail.com" + }, + { + "FirstName": "John", + "LastName": "Connor", + "Phone": "617-555-0133", + "Email": "jconnor@goodmail.com" + } +] \ No newline at end of file diff --git a/force-app/main/default/staticresources/sample_data_contacts.resource-meta.xml b/force-app/main/default/staticresources/sample_data_contacts.resource-meta.xml new file mode 100644 index 0000000..1e39c0a --- /dev/null +++ b/force-app/main/default/staticresources/sample_data_contacts.resource-meta.xml @@ -0,0 +1,6 @@ + + + Private + application/json + Sample data used to initialize Contact records + diff --git a/force-app/main/default/staticresources/sample_data_properties.json b/force-app/main/default/staticresources/sample_data_properties.json new file mode 100644 index 0000000..e8108b1 --- /dev/null +++ b/force-app/main/default/staticresources/sample_data_properties.json @@ -0,0 +1,242 @@ +[ + { + "Name": "Stunning Victorian", + "Hutte__Address__c": "18 Henry St", + "Hutte__City__c": "Cambridge", + "Hutte__State__c": "MA", + "Hutte__Zip__c": "01742", + "Hutte__Price__c": 975000, + "Hutte__Beds__c": 4, + "Hutte__Baths__c": 3, + "Hutte__Location__Longitude__s": -71.11095, + "Hutte__Location__Latitude__s": 42.35663, + "Hutte__Picture__c": "https://s3-us-west-2.amazonaws.com/dev-or-devrl-s3-bucket/sample-apps/realty/house01.jpg", + "Hutte__Thumbnail__c": "https://s3-us-west-2.amazonaws.com/dev-or-devrl-s3-bucket/sample-apps/realty/house01sq.jpg", + "Hutte__Tags__c": "victorian", + "Hutte__Description__c": "Lorem ipsum dolor sit amet", + "Hutte__Broker__r": { + "Hutte__Broker_Id__c": 1 + }, + "Hutte__Status__c": "Available" + }, + { + "Name": "Ultimate Sophistication", + "Hutte__Address__c": "24 Pearl St", + "Hutte__City__c": "Cambridge", + "Hutte__State__c": "MA", + "Hutte__Zip__c": "02420", + "Hutte__Price__c": 1200000, + "Hutte__Beds__c": 5, + "Hutte__Baths__c": 4, + "Hutte__Location__Longitude__s": -71.10869, + "Hutte__Location__Latitude__s": 42.359103, + "Hutte__Picture__c": "https://s3-us-west-2.amazonaws.com/dev-or-devrl-s3-bucket/sample-apps/realty/house02.jpg", + "Hutte__Thumbnail__c": "https://s3-us-west-2.amazonaws.com/dev-or-devrl-s3-bucket/sample-apps/realty/house02sq.jpg", + "Hutte__Tags__c": "colonial", + "Hutte__Description__c": "Lorem ipsum dolor sit amet", + "Hutte__Broker__r": { + "Hutte__Broker_Id__c": 2 + }, + "Hutte__Status__c": "Contracted" + }, + { + "Name": "Modern City Living", + "Hutte__Address__c": "72 Francis St", + "Hutte__City__c": "Boston", + "Hutte__State__c": "MA", + "Hutte__Zip__c": "02420", + "Hutte__Price__c": 825000, + "Hutte__Beds__c": 5, + "Hutte__Baths__c": 4, + "Hutte__Location__Longitude__s": -71.106827, + "Hutte__Location__Latitude__s": 42.335435, + "Hutte__Picture__c": "https://s3-us-west-2.amazonaws.com/dev-or-devrl-s3-bucket/sample-apps/realty/house03.jpg", + "Hutte__Thumbnail__c": "https://s3-us-west-2.amazonaws.com/dev-or-devrl-s3-bucket/sample-apps/realty/house03sq.jpg", + "Hutte__Tags__c": "contemporary", + "Hutte__Description__c": "Lorem ipsum dolor sit amet", + "Hutte__Broker__r": { + "Hutte__Broker_Id__c": 3 + }, + "Hutte__Status__c": "Pre Market" + }, + { + "Name": "Stunning Colonial", + "Hutte__Address__c": "32 Prince St", + "Hutte__City__c": "Cambridge", + "Hutte__State__c": "MA", + "Hutte__Zip__c": "02420", + "Hutte__Price__c": 930000, + "Hutte__Beds__c": 5, + "Hutte__Baths__c": 4, + "Hutte__Location__Longitude__s": -71.110448, + "Hutte__Location__Latitude__s": 42.360642, + "Hutte__Picture__c": "https://s3-us-west-2.amazonaws.com/dev-or-devrl-s3-bucket/sample-apps/realty/house04.jpg", + "Hutte__Thumbnail__c": "https://s3-us-west-2.amazonaws.com/dev-or-devrl-s3-bucket/sample-apps/realty/house04sq.jpg", + "Hutte__Tags__c": "colonial", + "Hutte__Description__c": "Lorem ipsum dolor sit amet", + "Hutte__Broker__r": { + "Hutte__Broker_Id__c": 4 + }, + "Hutte__Status__c": "Available" + }, + { + "Name": "Waterfront in the City", + "Hutte__Address__c": "110 Baxter Street", + "Hutte__City__c": "Boston", + "Hutte__State__c": "MA", + "Hutte__Zip__c": "02420", + "Hutte__Price__c": 850000, + "Hutte__Beds__c": 3, + "Hutte__Baths__c": 2, + "Hutte__Location__Longitude__s": -71.084454, + "Hutte__Location__Latitude__s": 42.368168, + "Hutte__Picture__c": "https://s3-us-west-2.amazonaws.com/dev-or-devrl-s3-bucket/sample-apps/realty/house05.jpg", + "Hutte__Thumbnail__c": "https://s3-us-west-2.amazonaws.com/dev-or-devrl-s3-bucket/sample-apps/realty/house05sq.jpg", + "Hutte__Tags__c": "contemporary", + "Hutte__Description__c": "Lorem ipsum dolor sit amet", + "Hutte__Broker__r": { + "Hutte__Broker_Id__c": 5 + }, + "Hutte__Status__c": "Closed" + }, + { + "Name": "Quiet Retreat", + "Hutte__Address__c": "448 Hanover St", + "Hutte__City__c": "Boston", + "Hutte__State__c": "MA", + "Hutte__Zip__c": "02420", + "Hutte__Price__c": 725000, + "Hutte__Beds__c": 4, + "Hutte__Baths__c": 2, + "Hutte__Location__Longitude__s": -71.052617, + "Hutte__Location__Latitude__s": 42.366855, + "Hutte__Picture__c": "https://s3-us-west-2.amazonaws.com/dev-or-devrl-s3-bucket/sample-apps/realty/house06.jpg", + "Hutte__Thumbnail__c": "https://s3-us-west-2.amazonaws.com/dev-or-devrl-s3-bucket/sample-apps/realty/house06sq.jpg", + "Hutte__Tags__c": "colonial", + "Hutte__Description__c": "Lorem ipsum dolor sit amet", + "Hutte__Broker__r": { + "Hutte__Broker_Id__c": 6 + }, + "Hutte__Status__c": "Contracted" + }, + { + "Name": "City Living", + "Hutte__Address__c": "127 Endicott St", + "Hutte__City__c": "Boston", + "Hutte__State__c": "MA", + "Hutte__Zip__c": "02420", + "Hutte__Price__c": 450000, + "Hutte__Beds__c": 3, + "Hutte__Baths__c": 1, + "Hutte__Location__Longitude__s": -71.057352, + "Hutte__Location__Latitude__s": 42.365003, + "Hutte__Picture__c": "https://s3-us-west-2.amazonaws.com/dev-or-devrl-s3-bucket/sample-apps/realty/house07.jpg", + "Hutte__Thumbnail__c": "https://s3-us-west-2.amazonaws.com/dev-or-devrl-s3-bucket/sample-apps/realty/house07sq.jpg", + "Hutte__Tags__c": "colonial", + "Hutte__Description__c": "Lorem ipsum dolor sit amet", + "Hutte__Broker__r": { + "Hutte__Broker_Id__c": 7 + }, + "Hutte__Status__c": "Available" + }, + { + "Name": "Heart of Harvard Square", + "Hutte__Address__c": "48 Brattle St", + "Hutte__City__c": "Cambridge", + "Hutte__State__c": "MA", + "Hutte__Zip__c": "02420", + "Hutte__Price__c": 450000, + "Hutte__Beds__c": 5, + "Hutte__Baths__c": 4, + "Hutte__Location__Longitude__s": -71.121653, + "Hutte__Location__Latitude__s": 42.374117, + "Hutte__Picture__c": "https://s3-us-west-2.amazonaws.com/dev-or-devrl-s3-bucket/sample-apps/realty/house10.jpg", + "Hutte__Thumbnail__c": "https://s3-us-west-2.amazonaws.com/dev-or-devrl-s3-bucket/sample-apps/realty/house10sq.jpg", + "Hutte__Tags__c": "victorian", + "Hutte__Description__c": "Lorem ipsum dolor sit amet", + "Hutte__Broker__r": { + "Hutte__Broker_Id__c": 8 + }, + "Hutte__Status__c": "Under Agreement" + }, + { + "Name": "Seaport District Retreat", + "Hutte__Address__c": "121 Harborwalk", + "Hutte__City__c": "Boston", + "Hutte__State__c": "MA", + "Hutte__Zip__c": "02420", + "Hutte__Price__c": 450000, + "Hutte__Beds__c": 3, + "Hutte__Baths__c": 3, + "Hutte__Location__Longitude__s": -71.049327, + "Hutte__Location__Latitude__s": 42.35695, + "Hutte__Picture__c": "https://s3-us-west-2.amazonaws.com/dev-or-devrl-s3-bucket/sample-apps/realty/house09.jpg", + "Hutte__Thumbnail__c": "https://s3-us-west-2.amazonaws.com/dev-or-devrl-s3-bucket/sample-apps/realty/house09sq.jpg", + "Hutte__Tags__c": "contemporary", + "Hutte__Description__c": "Lorem ipsum dolor sit amet", + "Hutte__Broker__r": { + "Hutte__Broker_Id__c": 1 + }, + "Hutte__Status__c": "Available" + }, + { + "Name": "Contemporary City Living", + "Hutte__Address__c": "640 Harrison Ave", + "Hutte__City__c": "Boston", + "Hutte__State__c": "MA", + "Hutte__Zip__c": "02420", + "Hutte__Price__c": 650000, + "Hutte__Beds__c": 2, + "Hutte__Baths__c": 2, + "Hutte__Location__Longitude__s": -71.068781, + "Hutte__Location__Latitude__s": 42.339892, + "Hutte__Picture__c": "https://s3-us-west-2.amazonaws.com/dev-or-devrl-s3-bucket/sample-apps/realty/house08.jpg", + "Hutte__Thumbnail__c": "https://s3-us-west-2.amazonaws.com/dev-or-devrl-s3-bucket/sample-apps/realty/house08sq.jpg", + "Hutte__Tags__c": "contemporary", + "Hutte__Description__c": "Lorem ipsum dolor sit amet", + "Hutte__Broker__r": { + "Hutte__Broker_Id__c": 2 + }, + "Hutte__Status__c": "Available" + }, + { + "Name": "Architectural Details", + "Hutte__Address__c": "95 Gloucester St", + "Hutte__City__c": "Boston", + "Hutte__State__c": "MA", + "Hutte__Zip__c": "02420", + "Hutte__Price__c": 690000, + "Hutte__Beds__c": 3, + "Hutte__Baths__c": 3, + "Hutte__Location__Latitude__s": 42.349693, + "Hutte__Location__Longitude__s": -71.084407, + "Hutte__Picture__c": "https://s3-us-west-2.amazonaws.com/dev-or-devrl-s3-bucket/sample-apps/realty/house11.jpg", + "Hutte__Thumbnail__c": "https://s3-us-west-2.amazonaws.com/dev-or-devrl-s3-bucket/sample-apps/realty/house11sq.jpg", + "Hutte__Tags__c": "contemporary", + "Hutte__Description__c": "Lorem ipsum dolor sit amet", + "Hutte__Broker__r": { + "Hutte__Broker_Id__c": 3 + }, + "Hutte__Status__c": "Available" + }, + { + "Name": "Contemporary Luxury", + "Hutte__Address__c": "145 Commonwealth Ave", + "Hutte__City__c": "Boston", + "Hutte__State__c": "MA", + "Hutte__Zip__c": "02420", + "Hutte__Price__c": 845000, + "Hutte__Beds__c": 4, + "Hutte__Baths__c": 3, + "Hutte__Location__Latitude__s": 42.352466, + "Hutte__Location__Longitude__s": -71.075311, + "Hutte__Picture__c": "https://s3-us-west-2.amazonaws.com/dev-or-devrl-s3-bucket/sample-apps/realty/house12.jpg", + "Hutte__Thumbnail__c": "https://s3-us-west-2.amazonaws.com/dev-or-devrl-s3-bucket/sample-apps/realty/house12sq.jpg", + "Hutte__Tags__c": "contemporary", + "Hutte__Description__c": "Lorem ipsum dolor sit amet", + "Hutte__Broker__r": { + "Hutte__Broker_Id__c": 4 + }, + "Hutte__Status__c": "Available" + } +] \ No newline at end of file diff --git a/force-app/main/default/staticresources/sample_data_properties.resource-meta.xml b/force-app/main/default/staticresources/sample_data_properties.resource-meta.xml new file mode 100644 index 0000000..ba43675 --- /dev/null +++ b/force-app/main/default/staticresources/sample_data_properties.resource-meta.xml @@ -0,0 +1,6 @@ + + + Private + application/json + Sample data used to initialize Property__c records + diff --git a/force-app/main/default/tabs/Broker__c.tab-meta.xml b/force-app/main/default/tabs/Broker__c.tab-meta.xml new file mode 100644 index 0000000..cad40e6 --- /dev/null +++ b/force-app/main/default/tabs/Broker__c.tab-meta.xml @@ -0,0 +1,5 @@ + + + true + Custom15: People + diff --git a/force-app/main/default/tabs/Property_Explorer.tab-meta.xml b/force-app/main/default/tabs/Property_Explorer.tab-meta.xml new file mode 100644 index 0000000..cf77167 --- /dev/null +++ b/force-app/main/default/tabs/Property_Explorer.tab-meta.xml @@ -0,0 +1,7 @@ + + + Created by Lightning App Builder + Property_Explorer + + Custom39: Telescope + diff --git a/force-app/main/default/tabs/Property_Finder.tab-meta.xml b/force-app/main/default/tabs/Property_Finder.tab-meta.xml new file mode 100644 index 0000000..41e5369 --- /dev/null +++ b/force-app/main/default/tabs/Property_Finder.tab-meta.xml @@ -0,0 +1,7 @@ + + + Created by Lightning App Builder + Property_Finder + + Custom78: Map + diff --git a/force-app/main/default/tabs/Property__c.tab-meta.xml b/force-app/main/default/tabs/Property__c.tab-meta.xml new file mode 100644 index 0000000..e9a3cf4 --- /dev/null +++ b/force-app/main/default/tabs/Property__c.tab-meta.xml @@ -0,0 +1,5 @@ + + + true + Custom85: Real Estate Sign + diff --git a/force-app/main/default/tabs/Settings.tab-meta.xml b/force-app/main/default/tabs/Settings.tab-meta.xml new file mode 100644 index 0000000..87d437c --- /dev/null +++ b/force-app/main/default/tabs/Settings.tab-meta.xml @@ -0,0 +1,7 @@ + + + Created by Lightning App Builder + Settings + + Custom19: Wrench + diff --git a/force-app/test/jest-mocks/apex.js b/force-app/test/jest-mocks/apex.js new file mode 100644 index 0000000..a7c2fb9 --- /dev/null +++ b/force-app/test/jest-mocks/apex.js @@ -0,0 +1 @@ +export const refreshApex = jest.fn(() => Promise.resolve()); diff --git a/force-app/test/jest-mocks/global/navigator.js b/force-app/test/jest-mocks/global/navigator.js new file mode 100644 index 0000000..b2989fa --- /dev/null +++ b/force-app/test/jest-mocks/global/navigator.js @@ -0,0 +1,15 @@ +// Mock browser geolocation service this way: +// import { mockGeolocation } from '../../../../../test/jest-mocks/global/navigator'; +// navigator.geolocation = mockGeolocation; +export const mockGeolocation = { + getCurrentPosition: jest.fn().mockImplementation((success) => + Promise.resolve( + success({ + coords: { + latitude: 42.361145, + longitude: -71.057083 + } + }) + ) + ) +}; diff --git a/force-app/test/jest-mocks/lightning/mediaUtils.js b/force-app/test/jest-mocks/lightning/mediaUtils.js new file mode 100644 index 0000000..cef4085 --- /dev/null +++ b/force-app/test/jest-mocks/lightning/mediaUtils.js @@ -0,0 +1 @@ +export const processImage = jest.fn(() => Promise.resolve(new Blob())); diff --git a/force-app/test/jest-mocks/lightning/messageService.js b/force-app/test/jest-mocks/lightning/messageService.js new file mode 100644 index 0000000..501a4d7 --- /dev/null +++ b/force-app/test/jest-mocks/lightning/messageService.js @@ -0,0 +1,25 @@ +/** + * For the original lightning/messageService (LMS) stub that comes by default with + * @salesforce/sfdx-lwc-jest, see: + * https://github.com/salesforce/sfdx-lwc-jest/blob/master/src/lightning-stubs/messageService/messageService.js + */ +export const APPLICATION_SCOPE = Symbol('APPLICATION_SCOPE'); +export const createMessageChannel = jest.fn(); +export const createMessageContext = jest.fn(); +export const MessageContext = jest.fn(); +export const releaseMessageContext = jest.fn(); +export const unsubscribe = jest.fn(); +// LMS stub implementation that lets you test a single message handler on a single channel +var _messageChannel = null; +var _messageHandler = null; +export const publish = jest.fn((messageContext, messageChannel, message) => { + if (_messageHandler && _messageChannel === messageChannel) { + _messageHandler(message); + } +}); +export const subscribe = jest.fn( + (messageContext, messageChannel, messageHandler) => { + _messageChannel = messageChannel; + _messageHandler = messageHandler; + } +); diff --git a/force-app/test/jest-mocks/lightning/mobileCapabilities.js b/force-app/test/jest-mocks/lightning/mobileCapabilities.js new file mode 100644 index 0000000..79d1a4a --- /dev/null +++ b/force-app/test/jest-mocks/lightning/mobileCapabilities.js @@ -0,0 +1,91 @@ +// ~~~~~ MOCK getLocationService ~~~~~ + +// To stub getLocationService.isAvailable(), add the following to your test: +// import { setDeviceLocationServiceAvailable } from 'lightning/mobileCapabilities'; +// setDeviceLocationServiceAvailable(true); + +let _deviceLocationServiceAvailable = false; + +export const getLocationService = jest.fn().mockImplementation(() => { + return { + isAvailable: jest.fn().mockReturnValue(_deviceLocationServiceAvailable), + getCurrentPosition: jest.fn().mockImplementation(() => + Promise.resolve({ + coords: { + latitude: 42.361145, + longitude: -71.057083 + } + }) + ) + }; +}); + +export const setDeviceLocationServiceAvailable = (value = true) => { + _deviceLocationServiceAvailable = value; +}; + +// ~~~~~ MOCK getBarcodeScanner ~~~~~ + +// To stub getBarcodeScanner.isAvailable(), add the following to your test: +// import { setBarcodeScannerAvailable } from 'lightning/mobileCapabilities'; +// setBarcodeScannerAvailable(true); + +// Mock getBarcodeScanner stubs that can be altered from within test files +let _barcodeScannerAvailable = false; +let _userCanceledScan = false; +let _scanThrewAnError = false; + +// Reset all BarcodeScanner stubs to false +export const resetBarcodeScannerStubs = () => { + _barcodeScannerAvailable = false; + _userCanceledScan = false; + _scanThrewAnError = false; +}; + +// Enables us to stub getBarcodeScanner.isAvailable() to a desired value (or true) from within the component test +export const setBarcodeScannerAvailable = (value = true) => { + _barcodeScannerAvailable = value; +}; + +// Enables us to mock user canceling (or not canceling) a scan from within the component test +export const setUserCanceledScan = (value = true) => { + _userCanceledScan = value; +}; + +// Enables us to mock there being an error (or not) from within the component test +export const setBarcodeScanError = (value = true) => { + _scanThrewAnError = value; +}; + +// Jest mock getBarcodeScanner that returns expected values/"functionality" for all methods and properties accessed in barcodeScanner.js +export const getBarcodeScanner = jest.fn().mockImplementation(() => { + return { + isAvailable: jest.fn().mockReturnValue(_barcodeScannerAvailable), + barcodeTypes: jest + .fn() + .mockReturnValue({ QR: _barcodeScannerAvailable }), + beginCapture: jest.fn().mockImplementation(() => { + // NB: Simultaneously initialising & throwing an Error (e.g. `throw new Error`) will exclude options + // See https://rollbar.com/guides/javascript/how-to-throw-exceptions-in-javascript + + let error; + + if (_userCanceledScan) { + error = new Error('User canceled scan'); + error.code = 'userDismissedScanner'; + } + + // ELSE if instead of plain IF to ensure only one error type is assigned + else if (_scanThrewAnError) { + error = new Error('There was a problem scanning the code'); + error.code = 'unknownReason'; + } + + if (error) throw error; + + // Return scan result + return Promise.resolve({ value: '0031700000pJRRWAA4' }); + }), + endCapture: jest.fn().mockReturnValue(_barcodeScannerAvailable) + }; +}); diff --git a/force-app/test/jest-mocks/lightning/navigation.js b/force-app/test/jest-mocks/lightning/navigation.js new file mode 100644 index 0000000..9aad987 --- /dev/null +++ b/force-app/test/jest-mocks/lightning/navigation.js @@ -0,0 +1,41 @@ +/** + * For the original lightning/navigation mock that comes by default with + * @salesforce/sfdx-lwc-jest, see: + * https://github.com/salesforce/sfdx-lwc-jest/blob/master/src/lightning-stubs/navigation/navigation.js + */ +export const CurrentPageReference = jest.fn(); + +let _navigatePageReference, _generatePageReference, _replace; + +const Navigate = Symbol('Navigate'); +const GenerateUrl = Symbol('GenerateUrl'); +export const NavigationMixin = (Base) => { + return class extends Base { + [Navigate](pageReference, replace) { + _navigatePageReference = pageReference; + _replace = replace; + } + [GenerateUrl](pageReference) { + _generatePageReference = pageReference; + return new Promise((resolve) => resolve('https://www.example.com')); + } + }; +}; +NavigationMixin.Navigate = Navigate; +NavigationMixin.GenerateUrl = GenerateUrl; + +/* + * Tests do not have access to the internals of this mixin used by the + * component under test so save a reference to the arguments the Navigate method is + * invoked with and provide access with this function. + */ +export const getNavigateCalledWith = () => { + return { + pageReference: _navigatePageReference, + replace: _replace + }; +}; + +export const getGenerateUrlCalledWith = () => ({ + pageReference: _generatePageReference +}); diff --git a/force-app/test/jest-mocks/lightning/platformShowToastEvent.js b/force-app/test/jest-mocks/lightning/platformShowToastEvent.js new file mode 100644 index 0000000..cb500b7 --- /dev/null +++ b/force-app/test/jest-mocks/lightning/platformShowToastEvent.js @@ -0,0 +1,18 @@ +/** + * For the original lightning/platformShowToastEvent mock that comes by default with + * @salesforce/sfdx-lwc-jest, see: + * https://github.com/salesforce/sfdx-lwc-jest/blob/master/src/lightning-stubs/platformShowToastEvent/platformShowToastEvent.js + */ + +export const ShowToastEventName = 'lightning__showtoast'; + +export class ShowToastEvent extends CustomEvent { + constructor(toast) { + super(ShowToastEventName, { + composed: true, + cancelable: true, + bubbles: true, + detail: toast + }); + } +} diff --git a/force-app/test/jest-mocks/schema.js b/force-app/test/jest-mocks/schema.js new file mode 100644 index 0000000..7152632 --- /dev/null +++ b/force-app/test/jest-mocks/schema.js @@ -0,0 +1,5 @@ +export const Property__c = { + objectApiName: 'Property__c', + Date_Listed__c: { fieldApiName: 'Date_Listed__c' }, + Days_On_Market__c: { fieldApiName: 'Days_On_Market__c' } +}; diff --git a/hutte.yml b/hutte.yml new file mode 100644 index 0000000..515ce1f --- /dev/null +++ b/hutte.yml @@ -0,0 +1,21 @@ +version: '1.0' + +# Shell script to run when pushing the source code to the scratch orgs. +# It's a great place to automate tasks like permission set assignments or data loading. +push_script: | + set -euo pipefail # fail fast + sf project deploy start --wait 60 --ignore-conflicts + sf org assign permset --name dreamhouse + sf data tree import -p data/sample-data-plan.json +custom_scripts: + # This scripts will be displayed on the scratch org's page + scratch_org: + 'Export Data': + description: 'Export data using SFDMU' + run: | + set -euo pipefail # fail fast + echo y | sf plugins install sfdmu + sf sfdmu run -p data/sfdmu -s "${SALESFORCE_USERNAME}" -u csvfile --filelog 0 -n + git add data + git commit -m "modified data" + git push origin "${HUTTE_GIT_SOURCE_BRANCH}" diff --git a/package.json b/package.json new file mode 100644 index 0000000..3fa866c --- /dev/null +++ b/package.json @@ -0,0 +1,41 @@ +{ + "name": "salesforce-app", + "private": true, + "version": "1.0.0", + "description": "Salesforce App", + "scripts": { + "lint": "eslint **/{aura,lwc}/**", + "test": "npm run test:unit", + "test:unit": "sfdx-lwc-jest", + "test:unit:watch": "sfdx-lwc-jest --watch", + "test:unit:debug": "sfdx-lwc-jest --debug", + "test:unit:coverage": "sfdx-lwc-jest --coverage", + "prettier": "prettier --write \"**/*.{cls,cmp,component,css,html,js,json,md,page,trigger,xml,yaml,yml}\"", + "prettier:verify": "prettier --list-different \"**/*.{cls,cmp,component,css,html,js,json,md,page,trigger,xml,yaml,yml}\"", + "postinstall": "husky install", + "precommit": "lint-staged" + }, + "devDependencies": { + "@lwc/eslint-plugin-lwc": "^1.1.2", + "@prettier/plugin-xml": "^3.2.2", + "@salesforce/eslint-config-lwc": "^3.2.3", + "@salesforce/eslint-plugin-aura": "^2.0.0", + "@salesforce/eslint-plugin-lightning": "^1.0.0", + "@salesforce/sfdx-lwc-jest": "^1.1.0", + "eslint": "^8.11.0", + "eslint-plugin-import": "^2.25.4", + "eslint-plugin-jest": "^26.1.2", + "husky": "^8.0.3", + "lint-staged": "^12.3.7", + "prettier": "^3.1.0", + "prettier-plugin-apex": "^2.0.1" + }, + "lint-staged": { + "**/*.{cls,cmp,component,css,html,js,json,md,page,trigger,xml,yaml,yml}": [ + "prettier --write" + ], + "**/{aura,lwc}/**": [ + "eslint" + ] + } +} diff --git a/release.config.mjs b/release.config.mjs new file mode 100644 index 0000000..1864f48 --- /dev/null +++ b/release.config.mjs @@ -0,0 +1,29 @@ +import { readFileSync } from 'node:fs'; + +const packageName = JSON.parse(readFileSync('sfdx-project.json', 'utf8')).packageDirectories.find( + (packageDirectory) => packageDirectory.default +).package; + +/** + * @type {import('semantic-release').GlobalConfig} + */ +export default { + plugins: [ + '@semantic-release/commit-analyzer', + '@semantic-release/release-notes-generator', + [ + '@semantic-release/exec', + { + shell: '/bin/bash', + // create package version for default package directory + publishCmd: `sf package version create --package "${packageName}" --version-number "\${nextRelease.version}.NEXT" --installation-key-bypass --code-coverage --wait 30 --json`, + // output package version id for GitHub Actions + // promote package version + successCmd: `echo "packageVersionId=\${releases[0].result.SubscriberPackageVersionId}" >> "\${process.env.GITHUB_OUTPUT}"; + echo "version=\${releases[0].result.VersionNumber}" >> "\${process.env.GITHUB_OUTPUT}"; + sf package version promote --package "\${releases[0].result.SubscriberPackageVersionId}" --no-prompt --json` + } + ], + '@semantic-release/github' + ] +}; diff --git a/scripts/addnamespaceToData.sh b/scripts/addnamespaceToData.sh new file mode 100755 index 0000000..aadd0a2 --- /dev/null +++ b/scripts/addnamespaceToData.sh @@ -0,0 +1,54 @@ +#!/bin/bash + +# Directory containing JSON files +DATA_DIR="data" + +# Define the namespace prefix +NAMESPACE="Hutte__" + +# Function to process JSON files +process_json_files() { + echo "Looking for JSON files in $DATA_DIR" + + # List files in the data directory for debugging + ls -l "$DATA_DIR" + + for file in "$DATA_DIR"/*.json; do + # Check if the file exists + if [[ -f $file ]]; then + echo "Processing $file" + + # Use jq to transform the JSON + jq 'walk( + if type == "object" then + with_entries( + if (.key | test("__c$|__s$")) then + .key |= "Hutte__" + . + elif (.value | type == "string" and test("__c$|__s$")) then + .value |= "Hutte__" + . + else + . + end + ) + elif type == "array" then + map( + if type == "string" and test("__c$|__s$") then + "Hutte__" + . + else + . + end + ) + else + . + end + )' "$file" > "${file}.tmp" && mv "${file}.tmp" "$file" + else + echo "No JSON files found in $DATA_DIR" + fi + done +} + +# Call the function to process JSON files +process_json_files + +echo "Processing complete." diff --git a/scripts/addnamespaceToLWC.sh b/scripts/addnamespaceToLWC.sh new file mode 100755 index 0000000..368d583 --- /dev/null +++ b/scripts/addnamespaceToLWC.sh @@ -0,0 +1,18 @@ +#!/bin/bash + +# Define the namespace prefix +NAMESPACE="Hutte__" + +# Define the directory containing the LWC files +LWC_DIR="force-app/main/default/lwc" + +# Find all .js, .html, and .js-meta.xml files in the LWC directory and iterate through them +find "$LWC_DIR" -type f \( -name "*.js" -o -name "*.html" -o -name "*.js-meta.xml" \) | while read -r FILE; do + # Use sed to add the namespace prefix to words ending with __c or __s + sed -i.bak -E "s/([a-zA-Z0-9_]+\.)?([a-zA-Z0-9_]+)(__[cs])/\1$NAMESPACE\2\3/g" "$FILE" + # Remove the backup file created by sed (optional) + rm "${FILE}.bak" + echo "Processed: $FILE" +done + +echo "Namespace prefixing completed." diff --git a/scripts/apex/hello.apex b/scripts/apex/hello.apex new file mode 100644 index 0000000..47121d5 --- /dev/null +++ b/scripts/apex/hello.apex @@ -0,0 +1,10 @@ +// Use .apex files to store anonymous Apex. +// You can execute anonymous Apex in VS Code by selecting the +// apex text and running the command: +// SFDX: Execute Anonymous Apex with Currently Selected Text +// You can also execute the entire file by running the command: +// SFDX: Execute Anonymous Apex with Editor Contents + +string tempvar = 'Enter_your_name_here'; +System.debug('Hello World!'); +System.debug('My name is ' + tempvar); diff --git a/scripts/soql/account.soql b/scripts/soql/account.soql new file mode 100644 index 0000000..10d4b9c --- /dev/null +++ b/scripts/soql/account.soql @@ -0,0 +1,6 @@ +// Use .soql files to store SOQL queries. +// You can execute queries in VS Code by selecting the +// query text and running the command: +// SFDX: Execute SOQL Query with Currently Selected Text + +SELECT Id, Name FROM Account diff --git a/sfdx-project.json b/sfdx-project.json new file mode 100644 index 0000000..7c9780d --- /dev/null +++ b/sfdx-project.json @@ -0,0 +1,19 @@ +{ + "packageDirectories": [ + { + "versionNumber": "0.0.0.NEXT", + "path": "force-app", + "default": false, + "package": "Dreamhut", + "versionDescription": "A second generation managed package based on the Salesforce Dreamhouse sample app", + "ancestorVersion": "HIGHEST" + } + ], + "name": "Dreamhut", + "namespace": "Hutte", + "sfdcLoginUrl": "https://login.salesforce.com", + "sourceApiVersion": "61.0", + "packageAliases": { + "Dreamhut": "0HoS7000000015lKAA" + } +} diff --git a/yarn.lock b/yarn.lock new file mode 100644 index 0000000..04f6e82 --- /dev/null +++ b/yarn.lock @@ -0,0 +1,4715 @@ +# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. +# yarn lockfile v1 + + +"@aashutoshrathi/word-wrap@^1.2.3": + version "1.2.6" + resolved "https://registry.yarnpkg.com/@aashutoshrathi/word-wrap/-/word-wrap-1.2.6.tgz#bd9154aec9983f77b3a034ecaa015c2e4201f6cf" + integrity sha512-1Yjs2SvM8TflER/OD3cOjhWWOZb58A2t7wpE2S9XfBYTiIl+XFhQG2bjy4Pu1I+EAlCNUzRDYDdFwFYUKvXcIA== + +"@ampproject/remapping@^2.2.0": + version "2.2.1" + resolved "https://registry.yarnpkg.com/@ampproject/remapping/-/remapping-2.2.1.tgz#99e8e11851128b8702cd57c33684f1d0f260b630" + integrity sha512-lFMjJTrFL3j7L9yBxwYfCq2k6qqwHyzuUl/XBnif78PWTJYyL/dfowQHWE3sp6U6ZzqWiiIZnpTMO96zhkjwtg== + dependencies: + "@jridgewell/gen-mapping" "^0.3.0" + "@jridgewell/trace-mapping" "^0.3.9" + +"@babel/code-frame@^7.0.0", "@babel/code-frame@^7.12.13", "@babel/code-frame@^7.21.4", "@babel/code-frame@^7.22.13", "@babel/code-frame@^7.23.4": + version "7.23.4" + resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.23.4.tgz#03ae5af150be94392cb5c7ccd97db5a19a5da6aa" + integrity sha512-r1IONyb6Ia+jYR2vvIDhdWdlTGhqbBoFqLTQidzZ4kepUFH15ejXvFHxCVbtl7BOXIudsIubf4E81xeA3h3IXA== + dependencies: + "@babel/highlight" "^7.23.4" + chalk "^2.4.2" + +"@babel/compat-data@^7.20.5", "@babel/compat-data@^7.22.9": + version "7.23.3" + resolved "https://registry.yarnpkg.com/@babel/compat-data/-/compat-data-7.23.3.tgz#3febd552541e62b5e883a25eb3effd7c7379db11" + integrity sha512-BmR4bWbDIoFJmJ9z2cZ8Gmm2MXgEDgjdWgpKmKWUt54UGFJdlj31ECtbaDvCG/qVdG3AQ1SfpZEs01lUFbzLOQ== + +"@babel/core@^7.1.0", "@babel/core@^7.12.3", "@babel/core@^7.21.3", "@babel/core@^7.7.2", "@babel/core@^7.8.0": + version "7.23.3" + resolved "https://registry.yarnpkg.com/@babel/core/-/core-7.23.3.tgz#5ec09c8803b91f51cc887dedc2654a35852849c9" + integrity sha512-Jg+msLuNuCJDyBvFv5+OKOUjWMZgd85bKjbICd3zWrKAo+bJ49HJufi7CQE0q0uR8NGyO6xkCACScNqyjHSZew== + dependencies: + "@ampproject/remapping" "^2.2.0" + "@babel/code-frame" "^7.22.13" + "@babel/generator" "^7.23.3" + "@babel/helper-compilation-targets" "^7.22.15" + "@babel/helper-module-transforms" "^7.23.3" + "@babel/helpers" "^7.23.2" + "@babel/parser" "^7.23.3" + "@babel/template" "^7.22.15" + "@babel/traverse" "^7.23.3" + "@babel/types" "^7.23.3" + convert-source-map "^2.0.0" + debug "^4.1.0" + gensync "^1.0.0-beta.2" + json5 "^2.2.3" + semver "^6.3.1" + +"@babel/core@~7.21.0": + version "7.21.8" + resolved "https://registry.yarnpkg.com/@babel/core/-/core-7.21.8.tgz#2a8c7f0f53d60100ba4c32470ba0281c92aa9aa4" + integrity sha512-YeM22Sondbo523Sz0+CirSPnbj9bG3P0CdHcBZdqUuaeOaYEFbOLoGU7lebvGP6P5J/WE9wOn7u7C4J9HvS1xQ== + dependencies: + "@ampproject/remapping" "^2.2.0" + "@babel/code-frame" "^7.21.4" + "@babel/generator" "^7.21.5" + "@babel/helper-compilation-targets" "^7.21.5" + "@babel/helper-module-transforms" "^7.21.5" + "@babel/helpers" "^7.21.5" + "@babel/parser" "^7.21.8" + "@babel/template" "^7.20.7" + "@babel/traverse" "^7.21.5" + "@babel/types" "^7.21.5" + convert-source-map "^1.7.0" + debug "^4.1.0" + gensync "^1.0.0-beta.2" + json5 "^2.2.2" + semver "^6.3.0" + +"@babel/core@~7.22.8": + version "7.22.20" + resolved "https://registry.yarnpkg.com/@babel/core/-/core-7.22.20.tgz#e3d0eed84c049e2a2ae0a64d27b6a37edec385b7" + integrity sha512-Y6jd1ahLubuYweD/zJH+vvOY141v4f9igNQAQ+MBgq9JlHS2iTsZKn1aMsb3vGccZsXI16VzTBw52Xx0DWmtnA== + dependencies: + "@ampproject/remapping" "^2.2.0" + "@babel/code-frame" "^7.22.13" + "@babel/generator" "^7.22.15" + "@babel/helper-compilation-targets" "^7.22.15" + "@babel/helper-module-transforms" "^7.22.20" + "@babel/helpers" "^7.22.15" + "@babel/parser" "^7.22.16" + "@babel/template" "^7.22.15" + "@babel/traverse" "^7.22.20" + "@babel/types" "^7.22.19" + convert-source-map "^1.7.0" + debug "^4.1.0" + gensync "^1.0.0-beta.2" + json5 "^2.2.3" + semver "^6.3.1" + +"@babel/eslint-parser@~7.22.7": + version "7.22.15" + resolved "https://registry.yarnpkg.com/@babel/eslint-parser/-/eslint-parser-7.22.15.tgz#263f059c476e29ca4972481a17b8b660cb025a34" + integrity sha512-yc8OOBIQk1EcRrpizuARSQS0TWAcOMpEJ1aafhNznaeYkeL+OhqnDObGFylB8ka8VFF/sZc+S4RzHyO+3LjQxg== + dependencies: + "@nicolo-ribaudo/eslint-scope-5-internals" "5.1.1-v1" + eslint-visitor-keys "^2.1.0" + semver "^6.3.1" + +"@babel/generator@^7.21.5", "@babel/generator@^7.22.15", "@babel/generator@^7.23.3", "@babel/generator@^7.23.4", "@babel/generator@^7.7.2": + version "7.23.4" + resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.23.4.tgz#4a41377d8566ec18f807f42962a7f3551de83d1c" + integrity sha512-esuS49Cga3HcThFNebGhlgsrVLkvhqvYDTzgjfFFlHJcIfLe5jFmRRfCQ1KuBfc4Jrtn3ndLgKWAKjBE+IraYQ== + dependencies: + "@babel/types" "^7.23.4" + "@jridgewell/gen-mapping" "^0.3.2" + "@jridgewell/trace-mapping" "^0.3.17" + jsesc "^2.5.1" + +"@babel/helper-annotate-as-pure@^7.22.5": + version "7.22.5" + resolved "https://registry.yarnpkg.com/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.22.5.tgz#e7f06737b197d580a01edf75d97e2c8be99d3882" + integrity sha512-LvBTxu8bQSQkcyKOU+a1btnNFQ1dMAd0R6PyW3arXes06F6QLWLIrd681bxRPIXlrMGR3XYnW9JyML7dP3qgxg== + dependencies: + "@babel/types" "^7.22.5" + +"@babel/helper-compilation-targets@^7.20.7", "@babel/helper-compilation-targets@^7.21.5", "@babel/helper-compilation-targets@^7.22.15": + version "7.22.15" + resolved "https://registry.yarnpkg.com/@babel/helper-compilation-targets/-/helper-compilation-targets-7.22.15.tgz#0698fc44551a26cf29f18d4662d5bf545a6cfc52" + integrity sha512-y6EEzULok0Qvz8yyLkCvVX+02ic+By2UdOhylwUOvOn9dvYc9mKICJuuU1n1XBI02YWsNsnrY1kc6DVbjcXbtw== + dependencies: + "@babel/compat-data" "^7.22.9" + "@babel/helper-validator-option" "^7.22.15" + browserslist "^4.21.9" + lru-cache "^5.1.1" + semver "^6.3.1" + +"@babel/helper-create-class-features-plugin@^7.18.6", "@babel/helper-create-class-features-plugin@^7.22.15": + version "7.22.15" + resolved "https://registry.yarnpkg.com/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.22.15.tgz#97a61b385e57fe458496fad19f8e63b63c867de4" + integrity sha512-jKkwA59IXcvSaiK2UN45kKwSC9o+KuoXsBDvHvU/7BecYIp8GQ2UwrVvFgJASUT+hBnwJx6MhvMCuMzwZZ7jlg== + dependencies: + "@babel/helper-annotate-as-pure" "^7.22.5" + "@babel/helper-environment-visitor" "^7.22.5" + "@babel/helper-function-name" "^7.22.5" + "@babel/helper-member-expression-to-functions" "^7.22.15" + "@babel/helper-optimise-call-expression" "^7.22.5" + "@babel/helper-replace-supers" "^7.22.9" + "@babel/helper-skip-transparent-expression-wrappers" "^7.22.5" + "@babel/helper-split-export-declaration" "^7.22.6" + semver "^6.3.1" + +"@babel/helper-environment-visitor@^7.22.20", "@babel/helper-environment-visitor@^7.22.5": + version "7.22.20" + resolved "https://registry.yarnpkg.com/@babel/helper-environment-visitor/-/helper-environment-visitor-7.22.20.tgz#96159db61d34a29dba454c959f5ae4a649ba9167" + integrity sha512-zfedSIzFhat/gFhWfHtgWvlec0nqB9YEIVrpuwjruLlXfUSnA8cJB0miHKwqDnQ7d32aKo2xt88/xZptwxbfhA== + +"@babel/helper-function-name@^7.22.5", "@babel/helper-function-name@^7.23.0": + version "7.23.0" + resolved "https://registry.yarnpkg.com/@babel/helper-function-name/-/helper-function-name-7.23.0.tgz#1f9a3cdbd5b2698a670c30d2735f9af95ed52759" + integrity sha512-OErEqsrxjZTJciZ4Oo+eoZqeW9UIiOcuYKRJA4ZAgV9myA+pOXhhmpfNCKjEH/auVfEYVFJ6y1Tc4r0eIApqiw== + dependencies: + "@babel/template" "^7.22.15" + "@babel/types" "^7.23.0" + +"@babel/helper-hoist-variables@^7.22.5": + version "7.22.5" + resolved "https://registry.yarnpkg.com/@babel/helper-hoist-variables/-/helper-hoist-variables-7.22.5.tgz#c01a007dac05c085914e8fb652b339db50d823bb" + integrity sha512-wGjk9QZVzvknA6yKIUURb8zY3grXCcOZt+/7Wcy8O2uctxhplmUPkOdlgoNhmdVee2c92JXbf1xpMtVNbfoxRw== + dependencies: + "@babel/types" "^7.22.5" + +"@babel/helper-member-expression-to-functions@^7.22.15": + version "7.23.0" + resolved "https://registry.yarnpkg.com/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.23.0.tgz#9263e88cc5e41d39ec18c9a3e0eced59a3e7d366" + integrity sha512-6gfrPwh7OuT6gZyJZvd6WbTfrqAo7vm4xCzAXOusKqq/vWdKXphTpj5klHKNmRUU6/QRGlBsyU9mAIPaWHlqJA== + dependencies: + "@babel/types" "^7.23.0" + +"@babel/helper-module-imports@^7.22.15": + version "7.22.15" + resolved "https://registry.yarnpkg.com/@babel/helper-module-imports/-/helper-module-imports-7.22.15.tgz#16146307acdc40cc00c3b2c647713076464bdbf0" + integrity sha512-0pYVBnDKZO2fnSPCrgM/6WMc7eS20Fbok+0r88fp+YtWVLZrp4CkafFGIp+W0VKw4a22sgebPT99y+FDNMdP4w== + dependencies: + "@babel/types" "^7.22.15" + +"@babel/helper-module-imports@~7.18.6": + version "7.18.6" + resolved "https://registry.yarnpkg.com/@babel/helper-module-imports/-/helper-module-imports-7.18.6.tgz#1e3ebdbbd08aad1437b428c50204db13c5a3ca6e" + integrity sha512-0NFvs3VkuSYbFi1x2Vd6tKrywq+z/cLeYC/RJNFrIX/30Bf5aiGYbtvGXolEktzJH8o5E5KJ3tT+nkxuuZFVlA== + dependencies: + "@babel/types" "^7.18.6" + +"@babel/helper-module-transforms@^7.21.5", "@babel/helper-module-transforms@^7.22.20", "@babel/helper-module-transforms@^7.23.3": + version "7.23.3" + resolved "https://registry.yarnpkg.com/@babel/helper-module-transforms/-/helper-module-transforms-7.23.3.tgz#d7d12c3c5d30af5b3c0fcab2a6d5217773e2d0f1" + integrity sha512-7bBs4ED9OmswdfDzpz4MpWgSrV7FXlc3zIagvLFjS5H+Mk7Snr21vQ6QwrsoCGMfNC4e4LQPdoULEt4ykz0SRQ== + dependencies: + "@babel/helper-environment-visitor" "^7.22.20" + "@babel/helper-module-imports" "^7.22.15" + "@babel/helper-simple-access" "^7.22.5" + "@babel/helper-split-export-declaration" "^7.22.6" + "@babel/helper-validator-identifier" "^7.22.20" + +"@babel/helper-optimise-call-expression@^7.22.5": + version "7.22.5" + resolved "https://registry.yarnpkg.com/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.22.5.tgz#f21531a9ccbff644fdd156b4077c16ff0c3f609e" + integrity sha512-HBwaojN0xFRx4yIvpwGqxiV2tUfl7401jlok564NgB9EHS1y6QT17FmKWm4ztqjeVdXLuC4fSvHc5ePpQjoTbw== + dependencies: + "@babel/types" "^7.22.5" + +"@babel/helper-plugin-utils@^7.0.0", "@babel/helper-plugin-utils@^7.10.4", "@babel/helper-plugin-utils@^7.12.13", "@babel/helper-plugin-utils@^7.14.5", "@babel/helper-plugin-utils@^7.18.6", "@babel/helper-plugin-utils@^7.20.2", "@babel/helper-plugin-utils@^7.22.5", "@babel/helper-plugin-utils@^7.8.0": + version "7.22.5" + resolved "https://registry.yarnpkg.com/@babel/helper-plugin-utils/-/helper-plugin-utils-7.22.5.tgz#dd7ee3735e8a313b9f7b05a773d892e88e6d7295" + integrity sha512-uLls06UVKgFG9QD4OeFYLEGteMIAa5kpTPcFL28yuCIIzsf6ZyKZMllKVOCZFhiZ5ptnwX4mtKdWCBE/uT4amg== + +"@babel/helper-replace-supers@^7.22.9": + version "7.22.20" + resolved "https://registry.yarnpkg.com/@babel/helper-replace-supers/-/helper-replace-supers-7.22.20.tgz#e37d367123ca98fe455a9887734ed2e16eb7a793" + integrity sha512-qsW0In3dbwQUbK8kejJ4R7IHVGwHJlV6lpG6UA7a9hSa2YEiAib+N1T2kr6PEeUT+Fl7najmSOS6SmAwCHK6Tw== + dependencies: + "@babel/helper-environment-visitor" "^7.22.20" + "@babel/helper-member-expression-to-functions" "^7.22.15" + "@babel/helper-optimise-call-expression" "^7.22.5" + +"@babel/helper-simple-access@^7.22.5": + version "7.22.5" + resolved "https://registry.yarnpkg.com/@babel/helper-simple-access/-/helper-simple-access-7.22.5.tgz#4938357dc7d782b80ed6dbb03a0fba3d22b1d5de" + integrity sha512-n0H99E/K+Bika3++WNL17POvo4rKWZ7lZEp1Q+fStVbUi8nxPQEBOlTmCOxW/0JsS56SKKQ+ojAe2pHKJHN35w== + dependencies: + "@babel/types" "^7.22.5" + +"@babel/helper-skip-transparent-expression-wrappers@^7.22.5": + version "7.22.5" + resolved "https://registry.yarnpkg.com/@babel/helper-skip-transparent-expression-wrappers/-/helper-skip-transparent-expression-wrappers-7.22.5.tgz#007f15240b5751c537c40e77abb4e89eeaaa8847" + integrity sha512-tK14r66JZKiC43p8Ki33yLBVJKlQDFoA8GYN67lWCDCqoL6EMMSuM9b+Iff2jHaM/RRFYl7K+iiru7hbRqNx8Q== + dependencies: + "@babel/types" "^7.22.5" + +"@babel/helper-split-export-declaration@^7.22.6": + version "7.22.6" + resolved "https://registry.yarnpkg.com/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.22.6.tgz#322c61b7310c0997fe4c323955667f18fcefb91c" + integrity sha512-AsUnxuLhRYsisFiaJwvp1QF+I3KjD5FOxut14q/GzovUe6orHLesW2C7d754kRm53h5gqrz6sFl6sxc4BVtE/g== + dependencies: + "@babel/types" "^7.22.5" + +"@babel/helper-string-parser@^7.23.4": + version "7.23.4" + resolved "https://registry.yarnpkg.com/@babel/helper-string-parser/-/helper-string-parser-7.23.4.tgz#9478c707febcbbe1ddb38a3d91a2e054ae622d83" + integrity sha512-803gmbQdqwdf4olxrX4AJyFBV/RTr3rSmOj0rKwesmzlfhYNDEs+/iOcznzpNWlJlIlTJC2QfPFcHB6DlzdVLQ== + +"@babel/helper-validator-identifier@^7.22.20": + version "7.22.20" + resolved "https://registry.yarnpkg.com/@babel/helper-validator-identifier/-/helper-validator-identifier-7.22.20.tgz#c4ae002c61d2879e724581d96665583dbc1dc0e0" + integrity sha512-Y4OZ+ytlatR8AI+8KZfKuL5urKp7qey08ha31L8b3BwewJAoJamTzyvxPR/5D+KkdJCGPq/+8TukHBlY10FX9A== + +"@babel/helper-validator-option@^7.22.15": + version "7.22.15" + resolved "https://registry.yarnpkg.com/@babel/helper-validator-option/-/helper-validator-option-7.22.15.tgz#694c30dfa1d09a6534cdfcafbe56789d36aba040" + integrity sha512-bMn7RmyFjY/mdECUbgn9eoSY4vqvacUnS9i9vGAGttgFWesO6B4CYWA7XlpbWgBt71iv/hfbPlynohStqnu5hA== + +"@babel/helpers@^7.21.5", "@babel/helpers@^7.22.15", "@babel/helpers@^7.23.2": + version "7.23.4" + resolved "https://registry.yarnpkg.com/@babel/helpers/-/helpers-7.23.4.tgz#7d2cfb969aa43222032193accd7329851facf3c1" + integrity sha512-HfcMizYz10cr3h29VqyfGL6ZWIjTwWfvYBMsBVGwpcbhNGe3wQ1ZXZRPzZoAHhd9OqHadHqjQ89iVKINXnbzuw== + dependencies: + "@babel/template" "^7.22.15" + "@babel/traverse" "^7.23.4" + "@babel/types" "^7.23.4" + +"@babel/highlight@^7.23.4": + version "7.23.4" + resolved "https://registry.yarnpkg.com/@babel/highlight/-/highlight-7.23.4.tgz#edaadf4d8232e1a961432db785091207ead0621b" + integrity sha512-acGdbYSfp2WheJoJm/EBBBLh/ID8KDc64ISZ9DYtBmC8/Q204PZJLHyzeB5qMzJ5trcOkybd78M4x2KWsUq++A== + dependencies: + "@babel/helper-validator-identifier" "^7.22.20" + chalk "^2.4.2" + js-tokens "^4.0.0" + +"@babel/parser@^7.1.0", "@babel/parser@^7.14.7", "@babel/parser@^7.20.7", "@babel/parser@^7.21.8", "@babel/parser@^7.22.15", "@babel/parser@^7.22.16", "@babel/parser@^7.23.3", "@babel/parser@^7.23.4": + version "7.23.4" + resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.23.4.tgz#409fbe690c333bb70187e2de4021e1e47a026661" + integrity sha512-vf3Xna6UEprW+7t6EtOmFpHNAuxw3xqPZghy+brsnusscJRW5BMUzzHZc5ICjULee81WeUV2jjakG09MDglJXQ== + +"@babel/plugin-proposal-class-properties@~7.18.6": + version "7.18.6" + resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-class-properties/-/plugin-proposal-class-properties-7.18.6.tgz#b110f59741895f7ec21a6fff696ec46265c446a3" + integrity sha512-cumfXOF0+nzZrrN8Rf0t7M+tF6sZc7vhQwYQck9q1/5w2OExlD+b4v4RpMJFaV1Z7WcDRgO6FqvxqxGlwo+RHQ== + dependencies: + "@babel/helper-create-class-features-plugin" "^7.18.6" + "@babel/helper-plugin-utils" "^7.18.6" + +"@babel/plugin-proposal-dynamic-import@^7.18.6": + version "7.18.6" + resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-dynamic-import/-/plugin-proposal-dynamic-import-7.18.6.tgz#72bcf8d408799f547d759298c3c27c7e7faa4d94" + integrity sha512-1auuwmK+Rz13SJj36R+jqFPMJWyKEDd7lLSdOj4oJK0UTgGueSAtkrCvz9ewmgyU/P941Rv2fQwZJN8s6QruXw== + dependencies: + "@babel/helper-plugin-utils" "^7.18.6" + "@babel/plugin-syntax-dynamic-import" "^7.8.3" + +"@babel/plugin-proposal-object-rest-spread@~7.20.2": + version "7.20.7" + resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-object-rest-spread/-/plugin-proposal-object-rest-spread-7.20.7.tgz#aa662940ef425779c75534a5c41e9d936edc390a" + integrity sha512-d2S98yCiLxDVmBmE8UjGcfPvNEUbA1U5q5WxaWFUGRzJSVAZqm5W6MbPct0jxnegUZ0niLeNX+IOzEs7wYg9Dg== + dependencies: + "@babel/compat-data" "^7.20.5" + "@babel/helper-compilation-targets" "^7.20.7" + "@babel/helper-plugin-utils" "^7.20.2" + "@babel/plugin-syntax-object-rest-spread" "^7.8.3" + "@babel/plugin-transform-parameters" "^7.20.7" + +"@babel/plugin-syntax-async-generators@^7.8.4": + version "7.8.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-async-generators/-/plugin-syntax-async-generators-7.8.4.tgz#a983fb1aeb2ec3f6ed042a210f640e90e786fe0d" + integrity sha512-tycmZxkGfZaxhMRbXlPXuVFpdWlXpir2W4AMhSJgRKzk/eDlIXOhb2LHWoLpDF7TEHylV5zNhykX6KAgHJmTNw== + dependencies: + "@babel/helper-plugin-utils" "^7.8.0" + +"@babel/plugin-syntax-bigint@^7.8.3": + version "7.8.3" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-bigint/-/plugin-syntax-bigint-7.8.3.tgz#4c9a6f669f5d0cdf1b90a1671e9a146be5300cea" + integrity sha512-wnTnFlG+YxQm3vDxpGE57Pj0srRU4sHE/mDkt1qv2YJJSeUAec2ma4WLUnUPeKjyrfntVwe/N6dCXpU+zL3Npg== + dependencies: + "@babel/helper-plugin-utils" "^7.8.0" + +"@babel/plugin-syntax-class-properties@^7.12.13", "@babel/plugin-syntax-class-properties@^7.8.3": + version "7.12.13" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-class-properties/-/plugin-syntax-class-properties-7.12.13.tgz#b5c987274c4a3a82b89714796931a6b53544ae10" + integrity sha512-fm4idjKla0YahUNgFNLCB0qySdsoPiZP3iQE3rky0mBUtMZ23yDJ9SJdg6dXTSDnulOVqiF3Hgr9nbXvXTQZYA== + dependencies: + "@babel/helper-plugin-utils" "^7.12.13" + +"@babel/plugin-syntax-decorators@^7.21.0": + version "7.23.3" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-decorators/-/plugin-syntax-decorators-7.23.3.tgz#a1d351d6c25bfdcf2e16f99b039101bc0ffcb0ca" + integrity sha512-cf7Niq4/+/juY67E0PbgH0TDhLQ5J7zS8C/Q5FFx+DWyrRa9sUQdTXkjqKu8zGvuqr7vw1muKiukseihU+PJDA== + dependencies: + "@babel/helper-plugin-utils" "^7.22.5" + +"@babel/plugin-syntax-dynamic-import@^7.8.3": + version "7.8.3" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-dynamic-import/-/plugin-syntax-dynamic-import-7.8.3.tgz#62bf98b2da3cd21d626154fc96ee5b3cb68eacb3" + integrity sha512-5gdGbFon+PszYzqs83S3E5mpi7/y/8M9eC90MRTZfduQOYW76ig6SOSPNe41IG5LoP3FGBn2N0RjVDSQiS94kQ== + dependencies: + "@babel/helper-plugin-utils" "^7.8.0" + +"@babel/plugin-syntax-import-meta@^7.8.3": + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-import-meta/-/plugin-syntax-import-meta-7.10.4.tgz#ee601348c370fa334d2207be158777496521fd51" + integrity sha512-Yqfm+XDx0+Prh3VSeEQCPU81yC+JWZ2pDPFSS4ZdpfZhp4MkFMaDC1UqseovEKwSUpnIL7+vK+Clp7bfh0iD7g== + dependencies: + "@babel/helper-plugin-utils" "^7.10.4" + +"@babel/plugin-syntax-json-strings@^7.8.3": + version "7.8.3" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-json-strings/-/plugin-syntax-json-strings-7.8.3.tgz#01ca21b668cd8218c9e640cb6dd88c5412b2c96a" + integrity sha512-lY6kdGpWHvjoe2vk4WrAapEuBR69EMxZl+RoGRhrFGNYVK8mOPAW8VfbT/ZgrFbXlDNiiaxQnAtgVCZ6jv30EA== + dependencies: + "@babel/helper-plugin-utils" "^7.8.0" + +"@babel/plugin-syntax-jsx@^7.23.3": + version "7.23.3" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.23.3.tgz#8f2e4f8a9b5f9aa16067e142c1ac9cd9f810f473" + integrity sha512-EB2MELswq55OHUoRZLGg/zC7QWUKfNLpE57m/S2yr1uEneIgsTgrSzXP3NXEsMkVn76OlaVVnzN+ugObuYGwhg== + dependencies: + "@babel/helper-plugin-utils" "^7.22.5" + +"@babel/plugin-syntax-logical-assignment-operators@^7.8.3": + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-logical-assignment-operators/-/plugin-syntax-logical-assignment-operators-7.10.4.tgz#ca91ef46303530448b906652bac2e9fe9941f699" + integrity sha512-d8waShlpFDinQ5MtvGU9xDAOzKH47+FFoney2baFIoMr952hKOLp1HR7VszoZvOsV/4+RRszNY7D17ba0te0ig== + dependencies: + "@babel/helper-plugin-utils" "^7.10.4" + +"@babel/plugin-syntax-nullish-coalescing-operator@^7.8.3": + version "7.8.3" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-nullish-coalescing-operator/-/plugin-syntax-nullish-coalescing-operator-7.8.3.tgz#167ed70368886081f74b5c36c65a88c03b66d1a9" + integrity sha512-aSff4zPII1u2QD7y+F8oDsz19ew4IGEJg9SVW+bqwpwtfFleiQDMdzA/R+UlWDzfnHFCxxleFT0PMIrR36XLNQ== + dependencies: + "@babel/helper-plugin-utils" "^7.8.0" + +"@babel/plugin-syntax-numeric-separator@^7.8.3": + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-numeric-separator/-/plugin-syntax-numeric-separator-7.10.4.tgz#b9b070b3e33570cd9fd07ba7fa91c0dd37b9af97" + integrity sha512-9H6YdfkcK/uOnY/K7/aA2xpzaAgkQn37yzWUMRK7OaPOqOpGS1+n0H5hxT9AUw9EsSjPW8SVyMJwYRtWs3X3ug== + dependencies: + "@babel/helper-plugin-utils" "^7.10.4" + +"@babel/plugin-syntax-object-rest-spread@^7.8.3": + version "7.8.3" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-object-rest-spread/-/plugin-syntax-object-rest-spread-7.8.3.tgz#60e225edcbd98a640332a2e72dd3e66f1af55871" + integrity sha512-XoqMijGZb9y3y2XskN+P1wUGiVwWZ5JmoDRwx5+3GmEplNyVM2s2Dg8ILFQm8rWM48orGy5YpI5Bl8U1y7ydlA== + dependencies: + "@babel/helper-plugin-utils" "^7.8.0" + +"@babel/plugin-syntax-optional-catch-binding@^7.8.3": + version "7.8.3" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-optional-catch-binding/-/plugin-syntax-optional-catch-binding-7.8.3.tgz#6111a265bcfb020eb9efd0fdfd7d26402b9ed6c1" + integrity sha512-6VPD0Pc1lpTqw0aKoeRTMiB+kWhAoT24PA+ksWSBrFtl5SIRVpZlwN3NNPQjehA2E/91FV3RjLWoVTglWcSV3Q== + dependencies: + "@babel/helper-plugin-utils" "^7.8.0" + +"@babel/plugin-syntax-optional-chaining@^7.8.3": + version "7.8.3" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-optional-chaining/-/plugin-syntax-optional-chaining-7.8.3.tgz#4f69c2ab95167e0180cd5336613f8c5788f7d48a" + integrity sha512-KoK9ErH1MBlCPxV0VANkXW2/dw4vlbGDrFgz8bmUsBGYkFRcbRwMh6cIJubdPrkxRwuGdtCk0v/wPTKbQgBjkg== + dependencies: + "@babel/helper-plugin-utils" "^7.8.0" + +"@babel/plugin-syntax-top-level-await@^7.8.3": + version "7.14.5" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-top-level-await/-/plugin-syntax-top-level-await-7.14.5.tgz#c1cfdadc35a646240001f06138247b741c34d94c" + integrity sha512-hx++upLv5U1rgYfwe1xBQUhRmU41NEvpUvrp8jkrSCdvGSnM5/qdRMtylJ6PG5OFkBaHkbTAKTnd3/YyESRHFw== + dependencies: + "@babel/helper-plugin-utils" "^7.14.5" + +"@babel/plugin-syntax-typescript@^7.23.3", "@babel/plugin-syntax-typescript@^7.7.2": + version "7.23.3" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-typescript/-/plugin-syntax-typescript-7.23.3.tgz#24f460c85dbbc983cd2b9c4994178bcc01df958f" + integrity sha512-9EiNjVJOMwCO+43TqoTrgQ8jMwcAd0sWyXi9RPfIsLTj4R2MADDDQXELhffaUx/uJv2AYcxBgPwH6j4TIA4ytQ== + dependencies: + "@babel/helper-plugin-utils" "^7.22.5" + +"@babel/plugin-transform-modules-commonjs@^7.21.2", "@babel/plugin-transform-modules-commonjs@^7.23.3": + version "7.23.3" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.23.3.tgz#661ae831b9577e52be57dd8356b734f9700b53b4" + integrity sha512-aVS0F65LKsdNOtcz6FRCpE4OgsP2OFnW46qNxNIX9h3wuzaNcSQsJysuMwqSibC98HPrf2vCgtxKNwS0DAlgcA== + dependencies: + "@babel/helper-module-transforms" "^7.23.3" + "@babel/helper-plugin-utils" "^7.22.5" + "@babel/helper-simple-access" "^7.22.5" + +"@babel/plugin-transform-parameters@^7.20.7": + version "7.23.3" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-parameters/-/plugin-transform-parameters-7.23.3.tgz#83ef5d1baf4b1072fa6e54b2b0999a7b2527e2af" + integrity sha512-09lMt6UsUb3/34BbECKVbVwrT9bO6lILWln237z7sLaWnMsTi7Yc9fhX5DLpkJzAGfaReXI22wP41SZmnAA3Vw== + dependencies: + "@babel/helper-plugin-utils" "^7.22.5" + +"@babel/plugin-transform-typescript@^7.23.3": + version "7.23.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-typescript/-/plugin-transform-typescript-7.23.4.tgz#da12914d17b3c4b307f32c5fd91fbfdf17d56f86" + integrity sha512-39hCCOl+YUAyMOu6B9SmUTiHUU0t/CxJNUmY3qRdJujbqi+lrQcL11ysYUsAvFWPBdhihrv1z0oRG84Yr3dODQ== + dependencies: + "@babel/helper-annotate-as-pure" "^7.22.5" + "@babel/helper-create-class-features-plugin" "^7.22.15" + "@babel/helper-plugin-utils" "^7.22.5" + "@babel/plugin-syntax-typescript" "^7.23.3" + +"@babel/preset-typescript@^7.21.0": + version "7.23.3" + resolved "https://registry.yarnpkg.com/@babel/preset-typescript/-/preset-typescript-7.23.3.tgz#14534b34ed5b6d435aa05f1ae1c5e7adcc01d913" + integrity sha512-17oIGVlqz6CchO9RFYn5U6ZpWRZIngayYCtrPRSgANSwC2V1Jb+iP74nVxzzXJte8b8BYxrL1yY96xfhTBrNNQ== + dependencies: + "@babel/helper-plugin-utils" "^7.22.5" + "@babel/helper-validator-option" "^7.22.15" + "@babel/plugin-syntax-jsx" "^7.23.3" + "@babel/plugin-transform-modules-commonjs" "^7.23.3" + "@babel/plugin-transform-typescript" "^7.23.3" + +"@babel/template@^7.20.7", "@babel/template@^7.22.15", "@babel/template@^7.3.3": + version "7.22.15" + resolved "https://registry.yarnpkg.com/@babel/template/-/template-7.22.15.tgz#09576efc3830f0430f4548ef971dde1350ef2f38" + integrity sha512-QPErUVm4uyJa60rkI73qneDacvdvzxshT3kksGqlGWYdOTIUOwJ7RDUL8sGqslY1uXWSL6xMFKEXDS3ox2uF0w== + dependencies: + "@babel/code-frame" "^7.22.13" + "@babel/parser" "^7.22.15" + "@babel/types" "^7.22.15" + +"@babel/traverse@^7.21.5", "@babel/traverse@^7.22.20", "@babel/traverse@^7.23.3", "@babel/traverse@^7.23.4", "@babel/traverse@^7.7.2": + version "7.23.4" + resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.23.4.tgz#c2790f7edf106d059a0098770fe70801417f3f85" + integrity sha512-IYM8wSUwunWTB6tFC2dkKZhxbIjHoWemdK+3f8/wq8aKhbUscxD5MX72ubd90fxvFknaLPeGw5ycU84V1obHJg== + dependencies: + "@babel/code-frame" "^7.23.4" + "@babel/generator" "^7.23.4" + "@babel/helper-environment-visitor" "^7.22.20" + "@babel/helper-function-name" "^7.23.0" + "@babel/helper-hoist-variables" "^7.22.5" + "@babel/helper-split-export-declaration" "^7.22.6" + "@babel/parser" "^7.23.4" + "@babel/types" "^7.23.4" + debug "^4.1.0" + globals "^11.1.0" + +"@babel/types@^7.0.0", "@babel/types@^7.18.6", "@babel/types@^7.20.7", "@babel/types@^7.21.5", "@babel/types@^7.22.15", "@babel/types@^7.22.19", "@babel/types@^7.22.5", "@babel/types@^7.23.0", "@babel/types@^7.23.3", "@babel/types@^7.23.4", "@babel/types@^7.3.3": + version "7.23.4" + resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.23.4.tgz#7206a1810fc512a7f7f7d4dace4cb4c1c9dbfb8e" + integrity sha512-7uIFwVYpoplT5jp/kVv6EF93VaJ8H+Yn5IczYiaAi98ajzjfoZfslet/e0sLh+wVBjb2qqIut1b0S26VSafsSQ== + dependencies: + "@babel/helper-string-parser" "^7.23.4" + "@babel/helper-validator-identifier" "^7.22.20" + to-fast-properties "^2.0.0" + +"@bcoe/v8-coverage@^0.2.3": + version "0.2.3" + resolved "https://registry.yarnpkg.com/@bcoe/v8-coverage/-/v8-coverage-0.2.3.tgz#75a2e8b51cb758a7553d6804a5932d7aace75c39" + integrity sha512-0hYQ8SB4Db5zvZB4axdMHGwEaQjkZzFjQiN9LVYvIFB2nSUHW9tYpxWriPrWDASIxiaXax83REcLxuSdnGPZtw== + +"@eslint-community/eslint-utils@^4.2.0": + version "4.4.0" + resolved "https://registry.yarnpkg.com/@eslint-community/eslint-utils/-/eslint-utils-4.4.0.tgz#a23514e8fb9af1269d5f7788aa556798d61c6b59" + integrity sha512-1/sA4dwrzBAyeUoQ6oxahHKmrZvsnLCg4RfxW3ZFGGmQkSNQPFNLV9CUEFQP1x9EYXHTo5p6xdhZM1Ne9p/AfA== + dependencies: + eslint-visitor-keys "^3.3.0" + +"@eslint-community/regexpp@^4.6.1": + version "4.10.0" + resolved "https://registry.yarnpkg.com/@eslint-community/regexpp/-/regexpp-4.10.0.tgz#548f6de556857c8bb73bbee70c35dc82a2e74d63" + integrity sha512-Cu96Sd2By9mCNTx2iyKOmq10v22jUVQv0lQnlGNy16oE9589yE+QADPbrMGCkA51cKZSg3Pu/aTJVTGfL/qjUA== + +"@eslint/eslintrc@^2.1.3": + version "2.1.3" + resolved "https://registry.yarnpkg.com/@eslint/eslintrc/-/eslintrc-2.1.3.tgz#797470a75fe0fbd5a53350ee715e85e87baff22d" + integrity sha512-yZzuIG+jnVu6hNSzFEN07e8BxF3uAzYtQb6uDkaYZLo6oYZDCq454c5kB8zxnzfCYyP4MIuyBn10L0DqwujTmA== + dependencies: + ajv "^6.12.4" + debug "^4.3.2" + espree "^9.6.0" + globals "^13.19.0" + ignore "^5.2.0" + import-fresh "^3.2.1" + js-yaml "^4.1.0" + minimatch "^3.1.2" + strip-json-comments "^3.1.1" + +"@eslint/js@8.54.0": + version "8.54.0" + resolved "https://registry.yarnpkg.com/@eslint/js/-/js-8.54.0.tgz#4fab9a2ff7860082c304f750e94acd644cf984cf" + integrity sha512-ut5V+D+fOoWPgGGNj83GGjnntO39xDy6DWxO0wb7Jp3DcMX0TfIqdzHF85VTQkerdyGmuuMD9AKAo5KiNlf/AQ== + +"@hapi/hoek@^9.0.0": + version "9.3.0" + resolved "https://registry.yarnpkg.com/@hapi/hoek/-/hoek-9.3.0.tgz#8368869dcb735be2e7f5cb7647de78e167a251fb" + integrity sha512-/c6rf4UJlmHlC9b5BaNvzAcFv7HZ2QHaV0D4/HNlBdvFnvQq8RI4kYdhyPCl7Xj+oWvTWQ8ujhqS53LIgAe6KQ== + +"@hapi/topo@^5.0.0": + version "5.1.0" + resolved "https://registry.yarnpkg.com/@hapi/topo/-/topo-5.1.0.tgz#dc448e332c6c6e37a4dc02fd84ba8d44b9afb012" + integrity sha512-foQZKJig7Ob0BMAYBfcJk8d77QtOe7Wo4ox7ff1lQYoNNAb6jwcY1ncdoy2e9wQZzvNy7ODZCYJkK8kzmcAnAg== + dependencies: + "@hapi/hoek" "^9.0.0" + +"@humanwhocodes/config-array@^0.11.13": + version "0.11.13" + resolved "https://registry.yarnpkg.com/@humanwhocodes/config-array/-/config-array-0.11.13.tgz#075dc9684f40a531d9b26b0822153c1e832ee297" + integrity sha512-JSBDMiDKSzQVngfRjOdFXgFfklaXI4K9nLF49Auh21lmBWRLIK3+xTErTWD4KU54pb6coM6ESE7Awz/FNU3zgQ== + dependencies: + "@humanwhocodes/object-schema" "^2.0.1" + debug "^4.1.1" + minimatch "^3.0.5" + +"@humanwhocodes/module-importer@^1.0.1": + version "1.0.1" + resolved "https://registry.yarnpkg.com/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz#af5b2691a22b44be847b0ca81641c5fb6ad0172c" + integrity sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA== + +"@humanwhocodes/object-schema@^2.0.1": + version "2.0.1" + resolved "https://registry.yarnpkg.com/@humanwhocodes/object-schema/-/object-schema-2.0.1.tgz#e5211452df060fa8522b55c7b3c0c4d1981cb044" + integrity sha512-dvuCeX5fC9dXgJn9t+X5atfmgQAzUOWqS1254Gh0m6i8wKd10ebXkfNKiRK+1GWi/yTvvLDHpoxLr0xxxeslWw== + +"@istanbuljs/load-nyc-config@^1.0.0": + version "1.1.0" + resolved "https://registry.yarnpkg.com/@istanbuljs/load-nyc-config/-/load-nyc-config-1.1.0.tgz#fd3db1d59ecf7cf121e80650bb86712f9b55eced" + integrity sha512-VjeHSlIzpv/NyD3N0YuHfXOPDIixcA1q2ZV98wsMqcYlPmv2n3Yb2lYP9XMElnaFVXg5A7YLTeLu6V84uQDjmQ== + dependencies: + camelcase "^5.3.1" + find-up "^4.1.0" + get-package-type "^0.1.0" + js-yaml "^3.13.1" + resolve-from "^5.0.0" + +"@istanbuljs/schema@^0.1.2": + version "0.1.3" + resolved "https://registry.yarnpkg.com/@istanbuljs/schema/-/schema-0.1.3.tgz#e45e384e4b8ec16bce2fd903af78450f6bf7ec98" + integrity sha512-ZXRY4jNvVgSVQ8DL3LTcakaAtXwTVUxE81hslsyD2AtoXW/wVob10HkOJ1X/pAlcI7D+2YoZKg5do8G/w6RYgA== + +"@jest/console@^27.5.1": + version "27.5.1" + resolved "https://registry.yarnpkg.com/@jest/console/-/console-27.5.1.tgz#260fe7239602fe5130a94f1aa386eff54b014bba" + integrity sha512-kZ/tNpS3NXn0mlXXXPNuDZnb4c0oZ20r4K5eemM2k30ZC3G0T02nXUvyhf5YdbXWHPEJLc9qGLxEZ216MdL+Zg== + dependencies: + "@jest/types" "^27.5.1" + "@types/node" "*" + chalk "^4.0.0" + jest-message-util "^27.5.1" + jest-util "^27.5.1" + slash "^3.0.0" + +"@jest/core@^27.4.7", "@jest/core@^27.5.1": + version "27.5.1" + resolved "https://registry.yarnpkg.com/@jest/core/-/core-27.5.1.tgz#267ac5f704e09dc52de2922cbf3af9edcd64b626" + integrity sha512-AK6/UTrvQD0Cd24NSqmIA6rKsu0tKIxfiCducZvqxYdmMisOYAsdItspT+fQDQYARPf8XgjAFZi0ogW2agH5nQ== + dependencies: + "@jest/console" "^27.5.1" + "@jest/reporters" "^27.5.1" + "@jest/test-result" "^27.5.1" + "@jest/transform" "^27.5.1" + "@jest/types" "^27.5.1" + "@types/node" "*" + ansi-escapes "^4.2.1" + chalk "^4.0.0" + emittery "^0.8.1" + exit "^0.1.2" + graceful-fs "^4.2.9" + jest-changed-files "^27.5.1" + jest-config "^27.5.1" + jest-haste-map "^27.5.1" + jest-message-util "^27.5.1" + jest-regex-util "^27.5.1" + jest-resolve "^27.5.1" + jest-resolve-dependencies "^27.5.1" + jest-runner "^27.5.1" + jest-runtime "^27.5.1" + jest-snapshot "^27.5.1" + jest-util "^27.5.1" + jest-validate "^27.5.1" + jest-watcher "^27.5.1" + micromatch "^4.0.4" + rimraf "^3.0.0" + slash "^3.0.0" + strip-ansi "^6.0.0" + +"@jest/environment@^27.5.1": + version "27.5.1" + resolved "https://registry.yarnpkg.com/@jest/environment/-/environment-27.5.1.tgz#d7425820511fe7158abbecc010140c3fd3be9c74" + integrity sha512-/WQjhPJe3/ghaol/4Bq480JKXV/Rfw8nQdN7f41fM8VDHLcxKXou6QyXAh3EFr9/bVG3x74z1NWDkP87EiY8gA== + dependencies: + "@jest/fake-timers" "^27.5.1" + "@jest/types" "^27.5.1" + "@types/node" "*" + jest-mock "^27.5.1" + +"@jest/fake-timers@^27.5.1": + version "27.5.1" + resolved "https://registry.yarnpkg.com/@jest/fake-timers/-/fake-timers-27.5.1.tgz#76979745ce0579c8a94a4678af7a748eda8ada74" + integrity sha512-/aPowoolwa07k7/oM3aASneNeBGCmGQsc3ugN4u6s4C/+s5M64MFo/+djTdiwcbQlRfFElGuDXWzaWj6QgKObQ== + dependencies: + "@jest/types" "^27.5.1" + "@sinonjs/fake-timers" "^8.0.1" + "@types/node" "*" + jest-message-util "^27.5.1" + jest-mock "^27.5.1" + jest-util "^27.5.1" + +"@jest/globals@^27.5.1": + version "27.5.1" + resolved "https://registry.yarnpkg.com/@jest/globals/-/globals-27.5.1.tgz#7ac06ce57ab966566c7963431cef458434601b2b" + integrity sha512-ZEJNB41OBQQgGzgyInAv0UUfDDj3upmHydjieSxFvTRuZElrx7tXg/uVQ5hYVEwiXs3+aMsAeEc9X7xiSKCm4Q== + dependencies: + "@jest/environment" "^27.5.1" + "@jest/types" "^27.5.1" + expect "^27.5.1" + +"@jest/reporters@^27.5.1": + version "27.5.1" + resolved "https://registry.yarnpkg.com/@jest/reporters/-/reporters-27.5.1.tgz#ceda7be96170b03c923c37987b64015812ffec04" + integrity sha512-cPXh9hWIlVJMQkVk84aIvXuBB4uQQmFqZiacloFuGiP3ah1sbCxCosidXFDfqG8+6fO1oR2dTJTlsOy4VFmUfw== + dependencies: + "@bcoe/v8-coverage" "^0.2.3" + "@jest/console" "^27.5.1" + "@jest/test-result" "^27.5.1" + "@jest/transform" "^27.5.1" + "@jest/types" "^27.5.1" + "@types/node" "*" + chalk "^4.0.0" + collect-v8-coverage "^1.0.0" + exit "^0.1.2" + glob "^7.1.2" + graceful-fs "^4.2.9" + istanbul-lib-coverage "^3.0.0" + istanbul-lib-instrument "^5.1.0" + istanbul-lib-report "^3.0.0" + istanbul-lib-source-maps "^4.0.0" + istanbul-reports "^3.1.3" + jest-haste-map "^27.5.1" + jest-resolve "^27.5.1" + jest-util "^27.5.1" + jest-worker "^27.5.1" + slash "^3.0.0" + source-map "^0.6.0" + string-length "^4.0.1" + terminal-link "^2.0.0" + v8-to-istanbul "^8.1.0" + +"@jest/schemas@^29.6.3": + version "29.6.3" + resolved "https://registry.yarnpkg.com/@jest/schemas/-/schemas-29.6.3.tgz#430b5ce8a4e0044a7e3819663305a7b3091c8e03" + integrity sha512-mo5j5X+jIZmJQveBKeS/clAueipV7KgiX1vMgCxam1RNYiqE1w62n0/tJJnHtjW8ZHcQco5gY85jA3mi0L+nSA== + dependencies: + "@sinclair/typebox" "^0.27.8" + +"@jest/source-map@^27.5.1": + version "27.5.1" + resolved "https://registry.yarnpkg.com/@jest/source-map/-/source-map-27.5.1.tgz#6608391e465add4205eae073b55e7f279e04e8cf" + integrity sha512-y9NIHUYF3PJRlHk98NdC/N1gl88BL08aQQgu4k4ZopQkCw9t9cV8mtl3TV8b/YCB8XaVTFrmUTAJvjsntDireg== + dependencies: + callsites "^3.0.0" + graceful-fs "^4.2.9" + source-map "^0.6.0" + +"@jest/test-result@^27.5.1": + version "27.5.1" + resolved "https://registry.yarnpkg.com/@jest/test-result/-/test-result-27.5.1.tgz#56a6585fa80f7cdab72b8c5fc2e871d03832f5bb" + integrity sha512-EW35l2RYFUcUQxFJz5Cv5MTOxlJIQs4I7gxzi2zVU7PJhOwfYq1MdC5nhSmYjX1gmMmLPvB3sIaC+BkcHRBfag== + dependencies: + "@jest/console" "^27.5.1" + "@jest/types" "^27.5.1" + "@types/istanbul-lib-coverage" "^2.0.0" + collect-v8-coverage "^1.0.0" + +"@jest/test-sequencer@^27.5.1": + version "27.5.1" + resolved "https://registry.yarnpkg.com/@jest/test-sequencer/-/test-sequencer-27.5.1.tgz#4057e0e9cea4439e544c6353c6affe58d095745b" + integrity sha512-LCheJF7WB2+9JuCS7VB/EmGIdQuhtqjRNI9A43idHv3E4KltCTsPsLxvdaubFHSYwY/fNjMWjl6vNRhDiN7vpQ== + dependencies: + "@jest/test-result" "^27.5.1" + graceful-fs "^4.2.9" + jest-haste-map "^27.5.1" + jest-runtime "^27.5.1" + +"@jest/transform@^27.5.1": + version "27.5.1" + resolved "https://registry.yarnpkg.com/@jest/transform/-/transform-27.5.1.tgz#6c3501dcc00c4c08915f292a600ece5ecfe1f409" + integrity sha512-ipON6WtYgl/1329g5AIJVbUuEh0wZVbdpGwC99Jw4LwuoBNS95MVphU6zOeD9pDkon+LLbFL7lOQRapbB8SCHw== + dependencies: + "@babel/core" "^7.1.0" + "@jest/types" "^27.5.1" + babel-plugin-istanbul "^6.1.1" + chalk "^4.0.0" + convert-source-map "^1.4.0" + fast-json-stable-stringify "^2.0.0" + graceful-fs "^4.2.9" + jest-haste-map "^27.5.1" + jest-regex-util "^27.5.1" + jest-util "^27.5.1" + micromatch "^4.0.4" + pirates "^4.0.4" + slash "^3.0.0" + source-map "^0.6.1" + write-file-atomic "^3.0.0" + +"@jest/types@^27.5.1": + version "27.5.1" + resolved "https://registry.yarnpkg.com/@jest/types/-/types-27.5.1.tgz#3c79ec4a8ba61c170bf937bcf9e98a9df175ec80" + integrity sha512-Cx46iJ9QpwQTjIdq5VJu2QTMMs3QlEjI0x1QbBP5W1+nMzyc2XmimiRR/CbX9TO0cPTeUlxWMOu8mslYsJ8DEw== + dependencies: + "@types/istanbul-lib-coverage" "^2.0.0" + "@types/istanbul-reports" "^3.0.0" + "@types/node" "*" + "@types/yargs" "^16.0.0" + chalk "^4.0.0" + +"@jridgewell/gen-mapping@^0.3.0", "@jridgewell/gen-mapping@^0.3.2": + version "0.3.3" + resolved "https://registry.yarnpkg.com/@jridgewell/gen-mapping/-/gen-mapping-0.3.3.tgz#7e02e6eb5df901aaedb08514203b096614024098" + integrity sha512-HLhSWOLRi875zjjMG/r+Nv0oCW8umGb0BgEhyX3dDX3egwZtB8PqLnjz3yedt8R5StBrzcg4aBpnh8UA9D1BoQ== + dependencies: + "@jridgewell/set-array" "^1.0.1" + "@jridgewell/sourcemap-codec" "^1.4.10" + "@jridgewell/trace-mapping" "^0.3.9" + +"@jridgewell/resolve-uri@^3.1.0": + version "3.1.1" + resolved "https://registry.yarnpkg.com/@jridgewell/resolve-uri/-/resolve-uri-3.1.1.tgz#c08679063f279615a3326583ba3a90d1d82cc721" + integrity sha512-dSYZh7HhCDtCKm4QakX0xFpsRDqjjtZf/kjI/v3T3Nwt5r8/qz/M19F9ySyOqU94SXBmeG9ttTul+YnR4LOxFA== + +"@jridgewell/set-array@^1.0.1": + version "1.1.2" + resolved "https://registry.yarnpkg.com/@jridgewell/set-array/-/set-array-1.1.2.tgz#7c6cf998d6d20b914c0a55a91ae928ff25965e72" + integrity sha512-xnkseuNADM0gt2bs+BvhO0p78Mk762YnZdsuzFV018NoG1Sj1SCQvpSqa7XUaTam5vAGasABV9qXASMKnFMwMw== + +"@jridgewell/sourcemap-codec@^1.4.10", "@jridgewell/sourcemap-codec@^1.4.14": + version "1.4.15" + resolved "https://registry.yarnpkg.com/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.15.tgz#d7c6e6755c78567a951e04ab52ef0fd26de59f32" + integrity sha512-eF2rxCRulEKXHTRiDrDy6erMYWqNw4LPdQ8UQA4huuxaQsVeRPFl2oM8oDGxMFhJUWZf9McpLtJasDDZb/Bpeg== + +"@jridgewell/trace-mapping@^0.3.17", "@jridgewell/trace-mapping@^0.3.9": + version "0.3.20" + resolved "https://registry.yarnpkg.com/@jridgewell/trace-mapping/-/trace-mapping-0.3.20.tgz#72e45707cf240fa6b081d0366f8265b0cd10197f" + integrity sha512-R8LcPeWZol2zR8mmH3JeKQ6QRCFb7XgUhV9ZlGhHLGyg4wpPiPZNQOOWhFZhxKw8u//yTbNGI42Bx/3paXEQ+Q== + dependencies: + "@jridgewell/resolve-uri" "^3.1.0" + "@jridgewell/sourcemap-codec" "^1.4.14" + +"@lwc/babel-plugin-component@2.42.0": + version "2.42.0" + resolved "https://registry.yarnpkg.com/@lwc/babel-plugin-component/-/babel-plugin-component-2.42.0.tgz#f3c9f83baf0ebf1ae2d71246512a3af46f2e114a" + integrity sha512-JqMM7vxKCUypgxnjxizfSFmm1hPRw8blFIyY1sxiBSrwXhZXTHxtstLRCZkATRsG4dAjj4wQ7SrNRhd7oQXD9Q== + dependencies: + "@babel/helper-module-imports" "~7.18.6" + "@lwc/errors" "2.42.0" + "@lwc/shared" "2.42.0" + line-column "~1.0.2" + +"@lwc/compiler@2.42.0": + version "2.42.0" + resolved "https://registry.yarnpkg.com/@lwc/compiler/-/compiler-2.42.0.tgz#f6402f333f3a169dd740f443844a8722c27d5d08" + integrity sha512-0NJFUAFVp4I/TI4GHvSwS86tyv7GuduxHLVsZ0Q42rAdvJmbMBvD8jIlCflhHLgzT0ePSD6pkoq9aKjks03RnQ== + dependencies: + "@babel/core" "~7.21.0" + "@babel/plugin-proposal-class-properties" "~7.18.6" + "@babel/plugin-proposal-object-rest-spread" "~7.20.2" + "@lwc/babel-plugin-component" "2.42.0" + "@lwc/errors" "2.42.0" + "@lwc/shared" "2.42.0" + "@lwc/style-compiler" "2.42.0" + "@lwc/template-compiler" "2.42.0" + +"@lwc/engine-dom@2.42.0": + version "2.42.0" + resolved "https://registry.yarnpkg.com/@lwc/engine-dom/-/engine-dom-2.42.0.tgz#91baf6c41cdd55d5a9eccf699317795f7e909ac9" + integrity sha512-yLo+C8MsLfDPrpAiHN8ktdVi2we2z1fryfXNYu9TMIaXwro/Bdw8PMzpIz5Q0E19KruGaAmixAzaLxymhwj2gQ== + +"@lwc/errors@2.42.0": + version "2.42.0" + resolved "https://registry.yarnpkg.com/@lwc/errors/-/errors-2.42.0.tgz#91179812ff50d566334a1ae65e0c580d85febb42" + integrity sha512-byCYjSXoV8B3s9d+rPwpQwGZ2y4u6Gh+QJkDT6ZGgcXhBCWeQLPp87rnZdhTau3Da0P7319G+ivOp57smbk/Eg== + +"@lwc/eslint-plugin-lwc@^1.1.2": + version "1.7.0" + resolved "https://registry.yarnpkg.com/@lwc/eslint-plugin-lwc/-/eslint-plugin-lwc-1.7.0.tgz#2d440800dede6fe12acb3f486dce95e34dd55b9d" + integrity sha512-nmyoIFAbUFR5lUEvmHdEqgIqbHquUHjiLBKmrGzocFOu8PKI4jMgZdjI53Wrcn2ddLwBUwLZyEdkcvms3ni00A== + dependencies: + globals "^13.23.0" + minimatch "^9.0.3" + +"@lwc/jest-preset@11.8.0": + version "11.8.0" + resolved "https://registry.yarnpkg.com/@lwc/jest-preset/-/jest-preset-11.8.0.tgz#aaec8b4c4d6a250ed97d8d07978b8e3cdc014138" + integrity sha512-BHb246V3LGm8q1HPYKFEZIgHwgFi8X5lN2R0FZavfyt1lnGhSa4ilS/zpLAgTHhyTOUhXkR4BKTDauCGLl4brw== + dependencies: + "@lwc/jest-resolver" "11.8.0" + "@lwc/jest-serializer" "11.8.0" + "@lwc/jest-transformer" "11.8.0" + +"@lwc/jest-resolver@11.8.0": + version "11.8.0" + resolved "https://registry.yarnpkg.com/@lwc/jest-resolver/-/jest-resolver-11.8.0.tgz#ea17888f1f55a7975d4c1b035cd07173395c3bed" + integrity sha512-mN5tXW1jko671GUE/yZP/xbZ1ECpnZo40dLMzFctIUF9kOmMjRMv/xdsBTtBnI59W2WKMYDs8G7pywdMFBeZvw== + dependencies: + "@lwc/jest-shared" "11.8.0" + +"@lwc/jest-serializer@11.8.0": + version "11.8.0" + resolved "https://registry.yarnpkg.com/@lwc/jest-serializer/-/jest-serializer-11.8.0.tgz#eb520f6e1d4a1a6296af9101b745183387faa7cf" + integrity sha512-bjIywlnvTkfEvBNKOrb/DHMvTw/V78ZSgNwry2eCHcDFI93adj6HkAx+Qq214uprnT/lZUtxosJBTcc/DkjrpA== + dependencies: + pretty-format "^29.5.0" + +"@lwc/jest-shared@11.8.0": + version "11.8.0" + resolved "https://registry.yarnpkg.com/@lwc/jest-shared/-/jest-shared-11.8.0.tgz#dde7b80cca2eb1360a11d735e3da4c98ac036420" + integrity sha512-g4xgbD5+NC75omjZ6YZZ/tJhhrBnFEj2Lx/oY/yLtKUDXRX//PiWmGGcdlUbM5X8T8Bx9VR1wFttlB2Ta26VPQ== + +"@lwc/jest-transformer@11.8.0": + version "11.8.0" + resolved "https://registry.yarnpkg.com/@lwc/jest-transformer/-/jest-transformer-11.8.0.tgz#adcac2c8b1daac9058407e4d33734fe72c8df32e" + integrity sha512-qEyQnw95I7NtFugoTbIRlxN7jXiKCsrEo6ZvMOtyVAAJeKjbv02j+2XCSp15e8usnH5UFNY7DKm2wTxMfr991A== + dependencies: + "@babel/core" "^7.21.3" + "@babel/plugin-proposal-dynamic-import" "^7.18.6" + "@babel/plugin-syntax-class-properties" "^7.12.13" + "@babel/plugin-syntax-decorators" "^7.21.0" + "@babel/plugin-transform-modules-commonjs" "^7.21.2" + "@babel/preset-typescript" "^7.21.0" + "@lwc/jest-shared" "11.8.0" + babel-preset-jest "^29.5.0" + +"@lwc/module-resolver@2.42.0": + version "2.42.0" + resolved "https://registry.yarnpkg.com/@lwc/module-resolver/-/module-resolver-2.42.0.tgz#a52189eb6060dd781eccaeb795ffa53f7e33cf3e" + integrity sha512-pwtgFNm/sNIS7daRnLCNLY4CqO/B31/ZwsqQd3Hs5eaH9iSFrGnoUm4sTVFyLljVAy7CXKdakwkvcj3JKjsO+w== + dependencies: + resolve "~1.22.1" + +"@lwc/shared@2.42.0": + version "2.42.0" + resolved "https://registry.yarnpkg.com/@lwc/shared/-/shared-2.42.0.tgz#6ddbaaf6fee1c1bd812723b1101eb08b6e328535" + integrity sha512-YSI9VObp3fJ5yyg6vE4tDRB8dqKRT5ZYmKL03lzQh6+NMcjqv+EyW48Q2pPcv2ghsg0mJHvHBl7+hFGe5Z03OQ== + +"@lwc/style-compiler@2.42.0": + version "2.42.0" + resolved "https://registry.yarnpkg.com/@lwc/style-compiler/-/style-compiler-2.42.0.tgz#0ac36abed925cafd7763c384aa351a9af60b6477" + integrity sha512-8p9YKqiNqK9XlblLgHYigRfNFsohmKYl400w/t5uewaMlLx/DoPlxcUmeEhGtibqkGEK7uqnuvLZDsO99Tuylw== + dependencies: + "@lwc/shared" "2.42.0" + postcss "~8.4.20" + postcss-selector-parser "~6.0.11" + postcss-value-parser "~4.2.0" + string.prototype.matchall "^4.0.8" + +"@lwc/synthetic-shadow@2.42.0": + version "2.42.0" + resolved "https://registry.yarnpkg.com/@lwc/synthetic-shadow/-/synthetic-shadow-2.42.0.tgz#53332140e75dea1cc2cc20f6c4a9ab0c193de465" + integrity sha512-UgtQqoyoIH8qi2Tv05PuX3FGRjeASyBb8Ylqmn4qed7nCOeek5uUbWh2sX2Ck/lK73qVqk4jiH8xsK9MIrQvoQ== + +"@lwc/template-compiler@2.42.0": + version "2.42.0" + resolved "https://registry.yarnpkg.com/@lwc/template-compiler/-/template-compiler-2.42.0.tgz#23a2915b57e1407ce48c3d27605dc79fdbb0717d" + integrity sha512-IMmm50fJUVG4kiX8gVptT6V/amtGMIi1dbcCU7rixjoBxd/F20lhZN3yHSPiWGFmoBWri16cFd+5hu3YYPRJdw== + dependencies: + "@lwc/errors" "2.42.0" + "@lwc/shared" "2.42.0" + acorn "~8.8.2" + astring "~1.8.3" + estree-walker "~2.0.2" + he "~1.2.0" + parse5 "~6.0.1" + +"@lwc/wire-service@2.42.0": + version "2.42.0" + resolved "https://registry.yarnpkg.com/@lwc/wire-service/-/wire-service-2.42.0.tgz#78dfe3612e7e49dcaf9f747008a9d400fefd3093" + integrity sha512-ZUY+8tYRxSYP5Murcb9tHZYXfMas4gNGfnt50Z/FxMX2kEC8Snp6sPyUTV1k4q+zTNu0zJ+WYHVpMgB+QfUc+w== + +"@mdn/browser-compat-data@^5.2.34", "@mdn/browser-compat-data@^5.3.13": + version "5.4.2" + resolved "https://registry.yarnpkg.com/@mdn/browser-compat-data/-/browser-compat-data-5.4.2.tgz#96364693d73d9ee6735cf7390dfcc052c8b24c8a" + integrity sha512-KuBlKNjbZyU3jCTNGsJl+accdAZRUVVyMBeIXAUT+oMUQ64Uq2mxKajzonFJOXkhaAvTac+sDtJSLhaOzKIo2Q== + +"@nicolo-ribaudo/eslint-scope-5-internals@5.1.1-v1": + version "5.1.1-v1" + resolved "https://registry.yarnpkg.com/@nicolo-ribaudo/eslint-scope-5-internals/-/eslint-scope-5-internals-5.1.1-v1.tgz#dbf733a965ca47b1973177dc0bb6c889edcfb129" + integrity sha512-54/JRvkLIzzDWshCWfuhadfrfZVPiElY8Fcgmg1HroEly/EDSszzhBAsarCux+D/kOslTRquNzuyGSmUSTTHGg== + dependencies: + eslint-scope "5.1.1" + +"@nodelib/fs.scandir@2.1.5": + version "2.1.5" + resolved "https://registry.yarnpkg.com/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz#7619c2eb21b25483f6d167548b4cfd5a7488c3d5" + integrity sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g== + dependencies: + "@nodelib/fs.stat" "2.0.5" + run-parallel "^1.1.9" + +"@nodelib/fs.stat@2.0.5", "@nodelib/fs.stat@^2.0.2": + version "2.0.5" + resolved "https://registry.yarnpkg.com/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz#5bd262af94e9d25bd1e71b05deed44876a222e8b" + integrity sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A== + +"@nodelib/fs.walk@^1.2.3", "@nodelib/fs.walk@^1.2.8": + version "1.2.8" + resolved "https://registry.yarnpkg.com/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz#e95737e8bb6746ddedf69c556953494f196fe69a" + integrity sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg== + dependencies: + "@nodelib/fs.scandir" "2.1.5" + fastq "^1.6.0" + +"@prettier/plugin-xml@^3.2.2": + version "3.2.2" + resolved "https://registry.yarnpkg.com/@prettier/plugin-xml/-/plugin-xml-3.2.2.tgz#ccc53d39b333aef140433b62449ea9f74d8e2eb6" + integrity sha512-SoE70SQF1AKIvK7LVK80JcdAe6wrDcbodFFjcoqb1FkOqV0G0oSlgAFDwoRXPqkUE5p/YF2nGsnUbnfm6471sw== + dependencies: + "@xml-tools/parser" "^1.0.11" + +"@salesforce/eslint-config-lwc@^3.2.3": + version "3.5.2" + resolved "https://registry.yarnpkg.com/@salesforce/eslint-config-lwc/-/eslint-config-lwc-3.5.2.tgz#45ae1596a35395cfec7c49736b9c52f8b9aa2b82" + integrity sha512-TqD5pF/OwjNNrms5nn9f6bf630T7WzXuH0RYF1ybsFOYsGQ2vFxD/F5fUNAjdQgLTR0hXK303j8yIw2fwTiOIQ== + dependencies: + "@babel/core" "~7.22.8" + "@babel/eslint-parser" "~7.22.7" + eslint-restricted-globals "~0.2.0" + semver "^7.5.3" + +"@salesforce/eslint-plugin-aura@^2.0.0": + version "2.1.0" + resolved "https://registry.yarnpkg.com/@salesforce/eslint-plugin-aura/-/eslint-plugin-aura-2.1.0.tgz#11c65d6190ecfffbc27e06b2d686026784c0b5c5" + integrity sha512-7HfwSBKTHQZQboLoEhkBY7bYR9wTaT+G5jHXGlq8y31hEnNhJXRZ+RERDEwDm1jYa2SV9lE8nMNr0/8EKIGjlQ== + dependencies: + eslint-plugin-compat "^4.0.2" + +"@salesforce/eslint-plugin-lightning@^1.0.0": + version "1.0.0" + resolved "https://registry.yarnpkg.com/@salesforce/eslint-plugin-lightning/-/eslint-plugin-lightning-1.0.0.tgz#9ecf80527d83394960ef3c358c790cdfde44f578" + integrity sha512-zk0PKXAcHKHepAG2EOSWlkOTxQM0Aw1CT6+MUxJcM42fCDwH/yPPpGkG3CWtRfmVViODGOwU9ywU2wlkAYcvUQ== + +"@salesforce/sfdx-lwc-jest@^1.1.0": + version "1.4.1" + resolved "https://registry.yarnpkg.com/@salesforce/sfdx-lwc-jest/-/sfdx-lwc-jest-1.4.1.tgz#0dbe131e54dcbe3c37818eff57d9ad4364d43ae7" + integrity sha512-BYKt4FxBJfKkWUKvSC2Yxb+mnIcP+6URbawsX8aeo1pKRnz6TDusiNZE8bR+8ZRWwnmeUC0fzKlZEi3xIqzMRg== + dependencies: + "@lwc/compiler" "2.42.0" + "@lwc/engine-dom" "2.42.0" + "@lwc/jest-preset" "11.8.0" + "@lwc/jest-resolver" "11.8.0" + "@lwc/jest-serializer" "11.8.0" + "@lwc/jest-transformer" "11.8.0" + "@lwc/module-resolver" "2.42.0" + "@lwc/synthetic-shadow" "2.42.0" + "@lwc/wire-service" "2.42.0" + "@salesforce/wire-service-jest-util" "4.0.1" + chalk "^4.1.2" + fast-glob "^3.2.12" + jest "27.4.7" + yargs "~17.6.2" + +"@salesforce/wire-service-jest-util@4.0.1": + version "4.0.1" + resolved "https://registry.yarnpkg.com/@salesforce/wire-service-jest-util/-/wire-service-jest-util-4.0.1.tgz#776d2a8b5dee9a63803e46cde7d511f32ada85ae" + integrity sha512-6u3ZGXDCeRnKSX8WHRpVQAXmGiee6NkhmQb0gXmcPAm8zW/Q7o7lRJNvXKnxnXY7qyiKXVYDQAFKJjtGpaCfjw== + +"@sideway/address@^4.1.3": + version "4.1.4" + resolved "https://registry.yarnpkg.com/@sideway/address/-/address-4.1.4.tgz#03dccebc6ea47fdc226f7d3d1ad512955d4783f0" + integrity sha512-7vwq+rOHVWjyXxVlR76Agnvhy8I9rpzjosTESvmhNeXOXdZZB15Fl+TI9x1SiHZH5Jv2wTGduSxFDIaq0m3DUw== + dependencies: + "@hapi/hoek" "^9.0.0" + +"@sideway/formula@^3.0.1": + version "3.0.1" + resolved "https://registry.yarnpkg.com/@sideway/formula/-/formula-3.0.1.tgz#80fcbcbaf7ce031e0ef2dd29b1bfc7c3f583611f" + integrity sha512-/poHZJJVjx3L+zVD6g9KgHfYnb443oi7wLu/XKojDviHy6HOEOA6z1Trk5aR1dGcmPenJEgb2sK2I80LeS3MIg== + +"@sideway/pinpoint@^2.0.0": + version "2.0.0" + resolved "https://registry.yarnpkg.com/@sideway/pinpoint/-/pinpoint-2.0.0.tgz#cff8ffadc372ad29fd3f78277aeb29e632cc70df" + integrity sha512-RNiOoTPkptFtSVzQevY/yWtZwf/RxyVnPy/OcA9HBM3MlGDnBEYL5B41H0MTn0Uec8Hi+2qUtTfG2WWZBmMejQ== + +"@sinclair/typebox@^0.27.8": + version "0.27.8" + resolved "https://registry.yarnpkg.com/@sinclair/typebox/-/typebox-0.27.8.tgz#6667fac16c436b5434a387a34dedb013198f6e6e" + integrity sha512-+Fj43pSMwJs4KRrH/938Uf+uAELIgVBmQzg/q1YG10djyfA3TnrU8N8XzqCh/okZdszqBQTZf96idMfE5lnwTA== + +"@sinonjs/commons@^1.7.0": + version "1.8.6" + resolved "https://registry.yarnpkg.com/@sinonjs/commons/-/commons-1.8.6.tgz#80c516a4dc264c2a69115e7578d62581ff455ed9" + integrity sha512-Ky+XkAkqPZSm3NLBeUng77EBQl3cmeJhITaGHdYH8kjVB+aun3S4XBRti2zt17mtt0mIUDiNxYeoJm6drVvBJQ== + dependencies: + type-detect "4.0.8" + +"@sinonjs/fake-timers@^8.0.1": + version "8.1.0" + resolved "https://registry.yarnpkg.com/@sinonjs/fake-timers/-/fake-timers-8.1.0.tgz#3fdc2b6cb58935b21bfb8d1625eb1300484316e7" + integrity sha512-OAPJUAtgeINhh/TAlUID4QTs53Njm7xzddaVlEs/SXwgtiD1tW22zAB/W1wdqfrpmikgaWQ9Fw6Ws+hsiRm5Vg== + dependencies: + "@sinonjs/commons" "^1.7.0" + +"@tootallnate/once@1": + version "1.1.2" + resolved "https://registry.yarnpkg.com/@tootallnate/once/-/once-1.1.2.tgz#ccb91445360179a04e7fe6aff78c00ffc1eeaf82" + integrity sha512-RbzJvlNzmRq5c3O09UipeuXno4tA1FE6ikOjxZK0tuxVv3412l64l5t1W5pj4+rJq9vpkm/kwiR07aZXnsKPxw== + +"@types/babel__core@^7.0.0", "@types/babel__core@^7.1.14": + version "7.20.5" + resolved "https://registry.yarnpkg.com/@types/babel__core/-/babel__core-7.20.5.tgz#3df15f27ba85319caa07ba08d0721889bb39c017" + integrity sha512-qoQprZvz5wQFJwMDqeseRXWv3rqMvhgpbXFfVyWhbx9X47POIA6i/+dXefEmZKoAgOaTdaIgNSMqMIU61yRyzA== + dependencies: + "@babel/parser" "^7.20.7" + "@babel/types" "^7.20.7" + "@types/babel__generator" "*" + "@types/babel__template" "*" + "@types/babel__traverse" "*" + +"@types/babel__generator@*": + version "7.6.7" + resolved "https://registry.yarnpkg.com/@types/babel__generator/-/babel__generator-7.6.7.tgz#a7aebf15c7bc0eb9abd638bdb5c0b8700399c9d0" + integrity sha512-6Sfsq+EaaLrw4RmdFWE9Onp63TOUue71AWb4Gpa6JxzgTYtimbM086WnYTy2U67AofR++QKCo08ZP6pwx8YFHQ== + dependencies: + "@babel/types" "^7.0.0" + +"@types/babel__template@*": + version "7.4.4" + resolved "https://registry.yarnpkg.com/@types/babel__template/-/babel__template-7.4.4.tgz#5672513701c1b2199bc6dad636a9d7491586766f" + integrity sha512-h/NUaSyG5EyxBIp8YRxo4RMe2/qQgvyowRwVMzhYhBCONbW8PUsg4lkFMrhgZhUe5z3L3MiLDuvyJ/CaPa2A8A== + dependencies: + "@babel/parser" "^7.1.0" + "@babel/types" "^7.0.0" + +"@types/babel__traverse@*", "@types/babel__traverse@^7.0.4", "@types/babel__traverse@^7.0.6": + version "7.20.4" + resolved "https://registry.yarnpkg.com/@types/babel__traverse/-/babel__traverse-7.20.4.tgz#ec2c06fed6549df8bc0eb4615b683749a4a92e1b" + integrity sha512-mSM/iKUk5fDDrEV/e83qY+Cr3I1+Q3qqTuEn++HAWYjEa1+NxZr6CNrcJGf2ZTnq4HoFGC3zaTPZTobCzCFukA== + dependencies: + "@babel/types" "^7.20.7" + +"@types/graceful-fs@^4.1.2": + version "4.1.9" + resolved "https://registry.yarnpkg.com/@types/graceful-fs/-/graceful-fs-4.1.9.tgz#2a06bc0f68a20ab37b3e36aa238be6abdf49e8b4" + integrity sha512-olP3sd1qOEe5dXTSaFvQG+02VdRXcdytWLAZsAq1PecU8uqQAhkrnbli7DagjtXKW/Bl7YJbUsa8MPcuc8LHEQ== + dependencies: + "@types/node" "*" + +"@types/istanbul-lib-coverage@*", "@types/istanbul-lib-coverage@^2.0.0", "@types/istanbul-lib-coverage@^2.0.1": + version "2.0.6" + resolved "https://registry.yarnpkg.com/@types/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.6.tgz#7739c232a1fee9b4d3ce8985f314c0c6d33549d7" + integrity sha512-2QF/t/auWm0lsy8XtKVPG19v3sSOQlJe/YHZgfjb/KBBHOGSV+J2q/S671rcq9uTBrLAXmZpqJiaQbMT+zNU1w== + +"@types/istanbul-lib-report@*": + version "3.0.3" + resolved "https://registry.yarnpkg.com/@types/istanbul-lib-report/-/istanbul-lib-report-3.0.3.tgz#53047614ae72e19fc0401d872de3ae2b4ce350bf" + integrity sha512-NQn7AHQnk/RSLOxrBbGyJM/aVQ+pjj5HCgasFxc0K/KhoATfQ/47AyUl15I2yBUpihjmas+a+VJBOqecrFH+uA== + dependencies: + "@types/istanbul-lib-coverage" "*" + +"@types/istanbul-reports@^3.0.0": + version "3.0.4" + resolved "https://registry.yarnpkg.com/@types/istanbul-reports/-/istanbul-reports-3.0.4.tgz#0f03e3d2f670fbdac586e34b433783070cc16f54" + integrity sha512-pk2B1NWalF9toCRu6gjBzR69syFjP4Od8WRAX+0mmf9lAjCRicLOWc+ZrxZHx/0XRjotgkF9t6iaMJ+aXcOdZQ== + dependencies: + "@types/istanbul-lib-report" "*" + +"@types/json-schema@^7.0.9": + version "7.0.15" + resolved "https://registry.yarnpkg.com/@types/json-schema/-/json-schema-7.0.15.tgz#596a1747233694d50f6ad8a7869fcb6f56cf5841" + integrity sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA== + +"@types/json5@^0.0.29": + version "0.0.29" + resolved "https://registry.yarnpkg.com/@types/json5/-/json5-0.0.29.tgz#ee28707ae94e11d2b827bcbe5270bcea7f3e71ee" + integrity sha512-dRLjCWHYg4oaA77cxO64oO+7JwCwnIzkZPdrrC71jQmQtlhM556pwKo5bUzqvZndkVbeFLIIi+9TC40JNF5hNQ== + +"@types/node@*": + version "20.10.0" + resolved "https://registry.yarnpkg.com/@types/node/-/node-20.10.0.tgz#16ddf9c0a72b832ec4fcce35b8249cf149214617" + integrity sha512-D0WfRmU9TQ8I9PFx9Yc+EBHw+vSpIub4IDvQivcp26PtPrdMGAq5SDcpXEo/epqa/DXotVpekHiLNTg3iaKXBQ== + dependencies: + undici-types "~5.26.4" + +"@types/prettier@^2.1.5": + version "2.7.3" + resolved "https://registry.yarnpkg.com/@types/prettier/-/prettier-2.7.3.tgz#3e51a17e291d01d17d3fc61422015a933af7a08f" + integrity sha512-+68kP9yzs4LMp7VNh8gdzMSPZFL44MLGqiHWvttYJe+6qnuVr4Ek9wSBQoveqY/r+LwjCcU29kNVkidwim+kYA== + +"@types/semver@^7.3.12": + version "7.5.6" + resolved "https://registry.yarnpkg.com/@types/semver/-/semver-7.5.6.tgz#c65b2bfce1bec346582c07724e3f8c1017a20339" + integrity sha512-dn1l8LaMea/IjDoHNd9J52uBbInB796CDffS6VdIxvqYCPSG0V0DzHp76GpaWnlhg88uYyPbXCDIowa86ybd5A== + +"@types/stack-utils@^2.0.0": + version "2.0.3" + resolved "https://registry.yarnpkg.com/@types/stack-utils/-/stack-utils-2.0.3.tgz#6209321eb2c1712a7e7466422b8cb1fc0d9dd5d8" + integrity sha512-9aEbYZ3TbYMznPdcdr3SmIrLXwC/AKZXQeCf9Pgao5CKb8CyHuEX5jzWPTkvregvhRJHcpRO6BFoGW9ycaOkYw== + +"@types/yargs-parser@*": + version "21.0.3" + resolved "https://registry.yarnpkg.com/@types/yargs-parser/-/yargs-parser-21.0.3.tgz#815e30b786d2e8f0dcd85fd5bcf5e1a04d008f15" + integrity sha512-I4q9QU9MQv4oEOz4tAHJtNz1cwuLxn2F3xcc2iV5WdqLPpUnj30aUuxt1mAxYTG+oe8CZMV/+6rU4S4gRDzqtQ== + +"@types/yargs@^16.0.0": + version "16.0.9" + resolved "https://registry.yarnpkg.com/@types/yargs/-/yargs-16.0.9.tgz#ba506215e45f7707e6cbcaf386981155b7ab956e" + integrity sha512-tHhzvkFXZQeTECenFoRljLBYPZJ7jAVxqqtEI0qTLOmuultnFp4I9yKE17vTuhf7BkhCu7I4XuemPgikDVuYqA== + dependencies: + "@types/yargs-parser" "*" + +"@typescript-eslint/scope-manager@5.62.0": + version "5.62.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/scope-manager/-/scope-manager-5.62.0.tgz#d9457ccc6a0b8d6b37d0eb252a23022478c5460c" + integrity sha512-VXuvVvZeQCQb5Zgf4HAxc04q5j+WrNAtNh9OwCsCgpKqESMTu3tF/jhZ3xG6T4NZwWl65Bg8KuS2uEvhSfLl0w== + dependencies: + "@typescript-eslint/types" "5.62.0" + "@typescript-eslint/visitor-keys" "5.62.0" + +"@typescript-eslint/types@5.62.0": + version "5.62.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/types/-/types-5.62.0.tgz#258607e60effa309f067608931c3df6fed41fd2f" + integrity sha512-87NVngcbVXUahrRTqIK27gD2t5Cu1yuCXxbLcFtCzZGlfyVWWh8mLHkoxzjsB6DDNnvdL+fW8MiwPEJyGJQDgQ== + +"@typescript-eslint/typescript-estree@5.62.0": + version "5.62.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/typescript-estree/-/typescript-estree-5.62.0.tgz#7d17794b77fabcac615d6a48fb143330d962eb9b" + integrity sha512-CmcQ6uY7b9y694lKdRB8FEel7JbU/40iSAPomu++SjLMntB+2Leay2LO6i8VnJk58MtE9/nQSFIH6jpyRWyYzA== + dependencies: + "@typescript-eslint/types" "5.62.0" + "@typescript-eslint/visitor-keys" "5.62.0" + debug "^4.3.4" + globby "^11.1.0" + is-glob "^4.0.3" + semver "^7.3.7" + tsutils "^3.21.0" + +"@typescript-eslint/utils@^5.10.0": + version "5.62.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/utils/-/utils-5.62.0.tgz#141e809c71636e4a75daa39faed2fb5f4b10df86" + integrity sha512-n8oxjeb5aIbPFEtmQxQYOLI0i9n5ySBEY/ZEHHZqKQSFnxio1rv6dthascc9dLuwrL0RC5mPCxB7vnAVGAYWAQ== + dependencies: + "@eslint-community/eslint-utils" "^4.2.0" + "@types/json-schema" "^7.0.9" + "@types/semver" "^7.3.12" + "@typescript-eslint/scope-manager" "5.62.0" + "@typescript-eslint/types" "5.62.0" + "@typescript-eslint/typescript-estree" "5.62.0" + eslint-scope "^5.1.1" + semver "^7.3.7" + +"@typescript-eslint/visitor-keys@5.62.0": + version "5.62.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/visitor-keys/-/visitor-keys-5.62.0.tgz#2174011917ce582875954ffe2f6912d5931e353e" + integrity sha512-07ny+LHRzQXepkGg6w0mFY41fVUNBrL2Roj/++7V1txKugfjm/Ci/qSND03r2RhlJhJYMcTn9AhhSSqQp0Ysyw== + dependencies: + "@typescript-eslint/types" "5.62.0" + eslint-visitor-keys "^3.3.0" + +"@ungap/structured-clone@^1.2.0": + version "1.2.0" + resolved "https://registry.yarnpkg.com/@ungap/structured-clone/-/structured-clone-1.2.0.tgz#756641adb587851b5ccb3e095daf27ae581c8406" + integrity sha512-zuVdFrMJiuCDQUMCzQaD6KL28MjnqqN8XnAqiEq9PNm/hCPTSGfrXCOfwj1ow4LFb/tNymJPwsNbVePc1xFqrQ== + +"@xml-tools/parser@^1.0.11": + version "1.0.11" + resolved "https://registry.yarnpkg.com/@xml-tools/parser/-/parser-1.0.11.tgz#a118a14099ea5c3c537e4781fad2fc195b57f8ff" + integrity sha512-aKqQ077XnR+oQtHJlrAflaZaL7qZsulWc/i/ZEooar5JiWj1eLt0+Wg28cpa+XLney107wXqneC+oG1IZvxkTA== + dependencies: + chevrotain "7.1.1" + +abab@^2.0.3, abab@^2.0.5: + version "2.0.6" + resolved "https://registry.yarnpkg.com/abab/-/abab-2.0.6.tgz#41b80f2c871d19686216b82309231cfd3cb3d291" + integrity sha512-j2afSsaIENvHZN2B8GOpF566vZ5WVk5opAiMTvWgaQT8DkbOqsTfvNAvHoRGU2zzP8cPoqys+xHTRDWW8L+/BA== + +acorn-globals@^6.0.0: + version "6.0.0" + resolved "https://registry.yarnpkg.com/acorn-globals/-/acorn-globals-6.0.0.tgz#46cdd39f0f8ff08a876619b55f5ac8a6dc770b45" + integrity sha512-ZQl7LOWaF5ePqqcX4hLuv/bLXYQNfNWw2c0/yX/TsPRKamzHcTGQnlCjHT3TsmkOUVEPS3crCxiPfdzE/Trlhg== + dependencies: + acorn "^7.1.1" + acorn-walk "^7.1.1" + +acorn-jsx@^5.3.2: + version "5.3.2" + resolved "https://registry.yarnpkg.com/acorn-jsx/-/acorn-jsx-5.3.2.tgz#7ed5bb55908b3b2f1bc55c6af1653bada7f07937" + integrity sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ== + +acorn-walk@^7.1.1: + version "7.2.0" + resolved "https://registry.yarnpkg.com/acorn-walk/-/acorn-walk-7.2.0.tgz#0de889a601203909b0fbe07b8938dc21d2e967bc" + integrity sha512-OPdCF6GsMIP+Az+aWfAAOEt2/+iVDKE7oy6lJ098aoe59oAmK76qV6Gw60SbZ8jHuG2wH058GF4pLFbYamYrVA== + +acorn@^7.1.1: + version "7.4.1" + resolved "https://registry.yarnpkg.com/acorn/-/acorn-7.4.1.tgz#feaed255973d2e77555b83dbc08851a6c63520fa" + integrity sha512-nQyp0o1/mNdbTO1PO6kHkwSrmgZ0MT/jCCpNiwbUjGoRN4dlBhqJtoQuCnEOKzgTVwg0ZWiCoQy6SxMebQVh8A== + +acorn@^8.2.4, acorn@^8.9.0: + version "8.11.2" + resolved "https://registry.yarnpkg.com/acorn/-/acorn-8.11.2.tgz#ca0d78b51895be5390a5903c5b3bdcdaf78ae40b" + integrity sha512-nc0Axzp/0FILLEVsm4fNwLCwMttvhEI263QtVPQcbpfZZ3ts0hLsZGOpE6czNlid7CJ9MlyH8reXkpsf3YUY4w== + +acorn@~8.8.2: + version "8.8.2" + resolved "https://registry.yarnpkg.com/acorn/-/acorn-8.8.2.tgz#1b2f25db02af965399b9776b0c2c391276d37c4a" + integrity sha512-xjIYgE8HBrkpd/sJqOGNspf8uHG+NOHGOw6a/Urj8taM2EXfdNAH2oFcPeIFfsv3+kz/mJrS5VuMqbNLjCa2vw== + +agent-base@6: + version "6.0.2" + resolved "https://registry.yarnpkg.com/agent-base/-/agent-base-6.0.2.tgz#49fff58577cfee3f37176feab4c22e00f86d7f77" + integrity sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ== + dependencies: + debug "4" + +aggregate-error@^3.0.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/aggregate-error/-/aggregate-error-3.1.0.tgz#92670ff50f5359bdb7a3e0d40d0ec30c5737687a" + integrity sha512-4I7Td01quW/RpocfNayFdFVk1qSuoh0E7JrbRJ16nH01HhKFQ88INq9Sd+nd72zqRySlr9BmDA8xlEJ6vJMrYA== + dependencies: + clean-stack "^2.0.0" + indent-string "^4.0.0" + +ajv@^6.12.4: + version "6.12.6" + resolved "https://registry.yarnpkg.com/ajv/-/ajv-6.12.6.tgz#baf5a62e802b07d977034586f8c3baf5adf26df4" + integrity sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g== + dependencies: + fast-deep-equal "^3.1.1" + fast-json-stable-stringify "^2.0.0" + json-schema-traverse "^0.4.1" + uri-js "^4.2.2" + +ansi-escapes@^4.2.1, ansi-escapes@^4.3.0: + version "4.3.2" + resolved "https://registry.yarnpkg.com/ansi-escapes/-/ansi-escapes-4.3.2.tgz#6b2291d1db7d98b6521d5f1efa42d0f3a9feb65e" + integrity sha512-gKXj5ALrKWQLsYG9jlTRmR/xKluxHV+Z9QEwNIgCfM1/uwPMCuzVVnh5mwTd+OuBZcwSIMbqssNWRm1lE51QaQ== + dependencies: + type-fest "^0.21.3" + +ansi-regex@^5.0.1: + version "5.0.1" + resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-5.0.1.tgz#082cb2c89c9fe8659a311a53bd6a4dc5301db304" + integrity sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ== + +ansi-regex@^6.0.1: + version "6.0.1" + resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-6.0.1.tgz#3183e38fae9a65d7cb5e53945cd5897d0260a06a" + integrity sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA== + +ansi-styles@^3.2.1: + version "3.2.1" + resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-3.2.1.tgz#41fbb20243e50b12be0f04b8dedbf07520ce841d" + integrity sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA== + dependencies: + color-convert "^1.9.0" + +ansi-styles@^4.0.0, ansi-styles@^4.1.0: + version "4.3.0" + resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-4.3.0.tgz#edd803628ae71c04c85ae7a0906edad34b648937" + integrity sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg== + dependencies: + color-convert "^2.0.1" + +ansi-styles@^5.0.0: + version "5.2.0" + resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-5.2.0.tgz#07449690ad45777d1924ac2abb2fc8895dba836b" + integrity sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA== + +ansi-styles@^6.0.0: + version "6.2.1" + resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-6.2.1.tgz#0e62320cf99c21afff3b3012192546aacbfb05c5" + integrity sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug== + +anymatch@^3.0.3: + version "3.1.3" + resolved "https://registry.yarnpkg.com/anymatch/-/anymatch-3.1.3.tgz#790c58b19ba1720a84205b57c618d5ad8524973e" + integrity sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw== + dependencies: + normalize-path "^3.0.0" + picomatch "^2.0.4" + +argparse@^1.0.7: + version "1.0.10" + resolved "https://registry.yarnpkg.com/argparse/-/argparse-1.0.10.tgz#bcd6791ea5ae09725e17e5ad988134cd40b3d911" + integrity sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg== + dependencies: + sprintf-js "~1.0.2" + +argparse@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/argparse/-/argparse-2.0.1.tgz#246f50f3ca78a3240f6c997e8a9bd1eac49e4b38" + integrity sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q== + +array-buffer-byte-length@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/array-buffer-byte-length/-/array-buffer-byte-length-1.0.0.tgz#fabe8bc193fea865f317fe7807085ee0dee5aead" + integrity sha512-LPuwb2P+NrQw3XhxGc36+XSvuBPopovXYTR9Ew++Du9Yb/bx5AzBfrIsBoj0EZUifjQU+sHL21sseZ3jerWO/A== + dependencies: + call-bind "^1.0.2" + is-array-buffer "^3.0.1" + +array-includes@^3.1.7: + version "3.1.7" + resolved "https://registry.yarnpkg.com/array-includes/-/array-includes-3.1.7.tgz#8cd2e01b26f7a3086cbc87271593fe921c62abda" + integrity sha512-dlcsNBIiWhPkHdOEEKnehA+RNUWDc4UqFtnIXU4uuYDPtA4LDkr7qip2p0VvFAEXNDr0yWZ9PJyIRiGjRLQzwQ== + dependencies: + call-bind "^1.0.2" + define-properties "^1.2.0" + es-abstract "^1.22.1" + get-intrinsic "^1.2.1" + is-string "^1.0.7" + +array-union@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/array-union/-/array-union-2.1.0.tgz#b798420adbeb1de828d84acd8a2e23d3efe85e8d" + integrity sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw== + +array.prototype.findlastindex@^1.2.3: + version "1.2.3" + resolved "https://registry.yarnpkg.com/array.prototype.findlastindex/-/array.prototype.findlastindex-1.2.3.tgz#b37598438f97b579166940814e2c0493a4f50207" + integrity sha512-LzLoiOMAxvy+Gd3BAq3B7VeIgPdo+Q8hthvKtXybMvRV0jrXfJM/t8mw7nNlpEcVlVUnCnM2KSX4XU5HmpodOA== + dependencies: + call-bind "^1.0.2" + define-properties "^1.2.0" + es-abstract "^1.22.1" + es-shim-unscopables "^1.0.0" + get-intrinsic "^1.2.1" + +array.prototype.flat@^1.3.2: + version "1.3.2" + resolved "https://registry.yarnpkg.com/array.prototype.flat/-/array.prototype.flat-1.3.2.tgz#1476217df8cff17d72ee8f3ba06738db5b387d18" + integrity sha512-djYB+Zx2vLewY8RWlNCUdHjDXs2XOgm602S9E7P/UpHgfeHL00cRiIF+IN/G/aUJ7kGPb6yO/ErDI5V2s8iycA== + dependencies: + call-bind "^1.0.2" + define-properties "^1.2.0" + es-abstract "^1.22.1" + es-shim-unscopables "^1.0.0" + +array.prototype.flatmap@^1.3.2: + version "1.3.2" + resolved "https://registry.yarnpkg.com/array.prototype.flatmap/-/array.prototype.flatmap-1.3.2.tgz#c9a7c6831db8e719d6ce639190146c24bbd3e527" + integrity sha512-Ewyx0c9PmpcsByhSW4r+9zDU7sGjFc86qf/kKtuSCRdhfbk0SNLLkaT5qvcHnRGgc5NP/ly/y+qkXkqONX54CQ== + dependencies: + call-bind "^1.0.2" + define-properties "^1.2.0" + es-abstract "^1.22.1" + es-shim-unscopables "^1.0.0" + +arraybuffer.prototype.slice@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/arraybuffer.prototype.slice/-/arraybuffer.prototype.slice-1.0.2.tgz#98bd561953e3e74bb34938e77647179dfe6e9f12" + integrity sha512-yMBKppFur/fbHu9/6USUe03bZ4knMYiwFBcyiaXB8Go0qNehwX6inYPzK9U0NeQvGxKthcmHcaR8P5MStSRBAw== + dependencies: + array-buffer-byte-length "^1.0.0" + call-bind "^1.0.2" + define-properties "^1.2.0" + es-abstract "^1.22.1" + get-intrinsic "^1.2.1" + is-array-buffer "^3.0.2" + is-shared-array-buffer "^1.0.2" + +ast-metadata-inferer@^0.8.0: + version "0.8.0" + resolved "https://registry.yarnpkg.com/ast-metadata-inferer/-/ast-metadata-inferer-0.8.0.tgz#0f94c3425e310d8da45823ab2161142e3f134343" + integrity sha512-jOMKcHht9LxYIEQu+RVd22vtgrPaVCtDRQ/16IGmurdzxvYbDd5ynxjnyrzLnieG96eTcAyaoj/wN/4/1FyyeA== + dependencies: + "@mdn/browser-compat-data" "^5.2.34" + +astral-regex@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/astral-regex/-/astral-regex-2.0.0.tgz#483143c567aeed4785759c0865786dc77d7d2e31" + integrity sha512-Z7tMw1ytTXt5jqMcOP+OQteU1VuNK9Y02uuJtKQ1Sv69jXQKKg5cibLwGJow8yzZP+eAc18EmLGPal0bp36rvQ== + +astring@~1.8.3: + version "1.8.6" + resolved "https://registry.yarnpkg.com/astring/-/astring-1.8.6.tgz#2c9c157cf1739d67561c56ba896e6948f6b93731" + integrity sha512-ISvCdHdlTDlH5IpxQJIex7BWBywFWgjJSVdwst+/iQCoEYnyOaQ95+X1JGshuBjGp6nxKUy1jMgE3zPqN7fQdg== + +asynckit@^0.4.0: + version "0.4.0" + resolved "https://registry.yarnpkg.com/asynckit/-/asynckit-0.4.0.tgz#c79ed97f7f34cb8f2ba1bc9790bcc366474b4b79" + integrity sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q== + +available-typed-arrays@^1.0.5: + version "1.0.5" + resolved "https://registry.yarnpkg.com/available-typed-arrays/-/available-typed-arrays-1.0.5.tgz#92f95616501069d07d10edb2fc37d3e1c65123b7" + integrity sha512-DMD0KiN46eipeziST1LPP/STfDU0sufISXmjSgvVsoU2tqxctQeASejWcfNtxYKqETM1UxQ8sp2OrSBWpHY6sw== + +axios@^1.6.1: + version "1.6.2" + resolved "https://registry.yarnpkg.com/axios/-/axios-1.6.2.tgz#de67d42c755b571d3e698df1b6504cde9b0ee9f2" + integrity sha512-7i24Ri4pmDRfJTR7LDBhsOTtcm+9kjX5WiY1X3wIisx6G9So3pfMkEiU7emUBe46oceVImccTEM3k6C5dbVW8A== + dependencies: + follow-redirects "^1.15.0" + form-data "^4.0.0" + proxy-from-env "^1.1.0" + +babel-jest@^27.5.1: + version "27.5.1" + resolved "https://registry.yarnpkg.com/babel-jest/-/babel-jest-27.5.1.tgz#a1bf8d61928edfefd21da27eb86a695bfd691444" + integrity sha512-cdQ5dXjGRd0IBRATiQ4mZGlGlRE8kJpjPOixdNRdT+m3UcNqmYWN6rK6nvtXYfY3D76cb8s/O1Ss8ea24PIwcg== + dependencies: + "@jest/transform" "^27.5.1" + "@jest/types" "^27.5.1" + "@types/babel__core" "^7.1.14" + babel-plugin-istanbul "^6.1.1" + babel-preset-jest "^27.5.1" + chalk "^4.0.0" + graceful-fs "^4.2.9" + slash "^3.0.0" + +babel-plugin-istanbul@^6.1.1: + version "6.1.1" + resolved "https://registry.yarnpkg.com/babel-plugin-istanbul/-/babel-plugin-istanbul-6.1.1.tgz#fa88ec59232fd9b4e36dbbc540a8ec9a9b47da73" + integrity sha512-Y1IQok9821cC9onCx5otgFfRm7Lm+I+wwxOx738M/WLPZ9Q42m4IG5W0FNX8WLL2gYMZo3JkuXIH2DOpWM+qwA== + dependencies: + "@babel/helper-plugin-utils" "^7.0.0" + "@istanbuljs/load-nyc-config" "^1.0.0" + "@istanbuljs/schema" "^0.1.2" + istanbul-lib-instrument "^5.0.4" + test-exclude "^6.0.0" + +babel-plugin-jest-hoist@^27.5.1: + version "27.5.1" + resolved "https://registry.yarnpkg.com/babel-plugin-jest-hoist/-/babel-plugin-jest-hoist-27.5.1.tgz#9be98ecf28c331eb9f5df9c72d6f89deb8181c2e" + integrity sha512-50wCwD5EMNW4aRpOwtqzyZHIewTYNxLA4nhB+09d8BIssfNfzBRhkBIHiaPv1Si226TQSvp8gxAJm2iY2qs2hQ== + dependencies: + "@babel/template" "^7.3.3" + "@babel/types" "^7.3.3" + "@types/babel__core" "^7.0.0" + "@types/babel__traverse" "^7.0.6" + +babel-plugin-jest-hoist@^29.6.3: + version "29.6.3" + resolved "https://registry.yarnpkg.com/babel-plugin-jest-hoist/-/babel-plugin-jest-hoist-29.6.3.tgz#aadbe943464182a8922c3c927c3067ff40d24626" + integrity sha512-ESAc/RJvGTFEzRwOTT4+lNDk/GNHMkKbNzsvT0qKRfDyyYTskxB5rnU2njIDYVxXCBHHEI1c0YwHob3WaYujOg== + dependencies: + "@babel/template" "^7.3.3" + "@babel/types" "^7.3.3" + "@types/babel__core" "^7.1.14" + "@types/babel__traverse" "^7.0.6" + +babel-preset-current-node-syntax@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/babel-preset-current-node-syntax/-/babel-preset-current-node-syntax-1.0.1.tgz#b4399239b89b2a011f9ddbe3e4f401fc40cff73b" + integrity sha512-M7LQ0bxarkxQoN+vz5aJPsLBn77n8QgTFmo8WK0/44auK2xlCXrYcUxHFxgU7qW5Yzw/CjmLRK2uJzaCd7LvqQ== + dependencies: + "@babel/plugin-syntax-async-generators" "^7.8.4" + "@babel/plugin-syntax-bigint" "^7.8.3" + "@babel/plugin-syntax-class-properties" "^7.8.3" + "@babel/plugin-syntax-import-meta" "^7.8.3" + "@babel/plugin-syntax-json-strings" "^7.8.3" + "@babel/plugin-syntax-logical-assignment-operators" "^7.8.3" + "@babel/plugin-syntax-nullish-coalescing-operator" "^7.8.3" + "@babel/plugin-syntax-numeric-separator" "^7.8.3" + "@babel/plugin-syntax-object-rest-spread" "^7.8.3" + "@babel/plugin-syntax-optional-catch-binding" "^7.8.3" + "@babel/plugin-syntax-optional-chaining" "^7.8.3" + "@babel/plugin-syntax-top-level-await" "^7.8.3" + +babel-preset-jest@^27.5.1: + version "27.5.1" + resolved "https://registry.yarnpkg.com/babel-preset-jest/-/babel-preset-jest-27.5.1.tgz#91f10f58034cb7989cb4f962b69fa6eef6a6bc81" + integrity sha512-Nptf2FzlPCWYuJg41HBqXVT8ym6bXOevuCTbhxlUpjwtysGaIWFvDEjp4y+G7fl13FgOdjs7P/DmErqH7da0Ag== + dependencies: + babel-plugin-jest-hoist "^27.5.1" + babel-preset-current-node-syntax "^1.0.0" + +babel-preset-jest@^29.5.0: + version "29.6.3" + resolved "https://registry.yarnpkg.com/babel-preset-jest/-/babel-preset-jest-29.6.3.tgz#fa05fa510e7d493896d7b0dd2033601c840f171c" + integrity sha512-0B3bhxR6snWXJZtR/RliHTDPRgn1sNHOR0yVtq/IiQFyuOVjFS+wuio/R4gSNkyYmKmJB4wGZv2NZanmKmTnNA== + dependencies: + babel-plugin-jest-hoist "^29.6.3" + babel-preset-current-node-syntax "^1.0.0" + +balanced-match@^1.0.0: + version "1.0.2" + resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.2.tgz#e83e3a7e3f300b34cb9d87f615fa0cbf357690ee" + integrity sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw== + +brace-expansion@^1.1.7: + version "1.1.11" + resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-1.1.11.tgz#3c7fcbf529d87226f3d2f52b966ff5271eb441dd" + integrity sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA== + dependencies: + balanced-match "^1.0.0" + concat-map "0.0.1" + +brace-expansion@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-2.0.1.tgz#1edc459e0f0c548486ecf9fc99f2221364b9a0ae" + integrity sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA== + dependencies: + balanced-match "^1.0.0" + +braces@^3.0.2: + version "3.0.2" + resolved "https://registry.yarnpkg.com/braces/-/braces-3.0.2.tgz#3454e1a462ee8d599e236df336cd9ea4f8afe107" + integrity sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A== + dependencies: + fill-range "^7.0.1" + +browser-process-hrtime@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/browser-process-hrtime/-/browser-process-hrtime-1.0.0.tgz#3c9b4b7d782c8121e56f10106d84c0d0ffc94626" + integrity sha512-9o5UecI3GhkpM6DrXr69PblIuWxPKk9Y0jHBRhdocZ2y7YECBFCsHm79Pr3OyR2AvjhDkabFJaDJMYRazHgsow== + +browserslist@^4.21.10, browserslist@^4.21.9: + version "4.22.1" + resolved "https://registry.yarnpkg.com/browserslist/-/browserslist-4.22.1.tgz#ba91958d1a59b87dab6fed8dfbcb3da5e2e9c619" + integrity sha512-FEVc202+2iuClEhZhrWy6ZiAcRLvNMyYcxZ8raemul1DYVOVdFsbqckWLdsixQZCpJlwe77Z3UTalE7jsjnKfQ== + dependencies: + caniuse-lite "^1.0.30001541" + electron-to-chromium "^1.4.535" + node-releases "^2.0.13" + update-browserslist-db "^1.0.13" + +bser@2.1.1: + version "2.1.1" + resolved "https://registry.yarnpkg.com/bser/-/bser-2.1.1.tgz#e6787da20ece9d07998533cfd9de6f5c38f4bc05" + integrity sha512-gQxTNE/GAfIIrmHLUE3oJyp5FO6HRBfhjnw4/wMmA63ZGDJnWBmgY/lyQBpnDUkGmAhbSe39tx2d/iTOAfglwQ== + dependencies: + node-int64 "^0.4.0" + +buffer-from@^1.0.0: + version "1.1.2" + resolved "https://registry.yarnpkg.com/buffer-from/-/buffer-from-1.1.2.tgz#2b146a6fd72e80b4f55d255f35ed59a3a9a41bd5" + integrity sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ== + +call-bind@^1.0.0, call-bind@^1.0.2, call-bind@^1.0.4, call-bind@^1.0.5: + version "1.0.5" + resolved "https://registry.yarnpkg.com/call-bind/-/call-bind-1.0.5.tgz#6fa2b7845ce0ea49bf4d8b9ef64727a2c2e2e513" + integrity sha512-C3nQxfFZxFRVoJoGKKI8y3MOEo129NQ+FgQ08iye+Mk4zNZZGdjfs06bVTr+DBSlA66Q2VEcMki/cUCP4SercQ== + dependencies: + function-bind "^1.1.2" + get-intrinsic "^1.2.1" + set-function-length "^1.1.1" + +callsites@^3.0.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/callsites/-/callsites-3.1.0.tgz#b3630abd8943432f54b3f0519238e33cd7df2f73" + integrity sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ== + +camelcase@^5.3.1: + version "5.3.1" + resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-5.3.1.tgz#e3c9b31569e106811df242f715725a1f4c494320" + integrity sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg== + +camelcase@^6.2.0: + version "6.3.0" + resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-6.3.0.tgz#5685b95eb209ac9c0c177467778c9c84df58ba9a" + integrity sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA== + +caniuse-lite@^1.0.30001524, caniuse-lite@^1.0.30001541: + version "1.0.30001565" + resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001565.tgz#a528b253c8a2d95d2b415e11d8b9942acc100c4f" + integrity sha512-xrE//a3O7TP0vaJ8ikzkD2c2NgcVUvsEe2IvFTntV4Yd1Z9FVzh+gW+enX96L0psrbaFMcVcH2l90xNuGDWc8w== + +chalk@^2.4.2: + version "2.4.2" + resolved "https://registry.yarnpkg.com/chalk/-/chalk-2.4.2.tgz#cd42541677a54333cf541a49108c1432b44c9424" + integrity sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ== + dependencies: + ansi-styles "^3.2.1" + escape-string-regexp "^1.0.5" + supports-color "^5.3.0" + +chalk@^4.0.0, chalk@^4.1.2: + version "4.1.2" + resolved "https://registry.yarnpkg.com/chalk/-/chalk-4.1.2.tgz#aac4e2b7734a740867aeb16bf02aad556a1e7a01" + integrity sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA== + dependencies: + ansi-styles "^4.1.0" + supports-color "^7.1.0" + +char-regex@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/char-regex/-/char-regex-1.0.2.tgz#d744358226217f981ed58f479b1d6bcc29545dcf" + integrity sha512-kWWXztvZ5SBQV+eRgKFeh8q5sLuZY2+8WUIzlxWVTg+oGwY14qylx1KbKzHd8P6ZYkAg0xyIDU9JMHhyJMZ1jw== + +chevrotain@7.1.1: + version "7.1.1" + resolved "https://registry.yarnpkg.com/chevrotain/-/chevrotain-7.1.1.tgz#5122814eafd1585a9601f9180a7be9c42d5699c6" + integrity sha512-wy3mC1x4ye+O+QkEinVJkPf5u2vsrDIYW9G7ZuwFl6v/Yu0LwUuT2POsb+NUWApebyxfkQq6+yDfRExbnI5rcw== + dependencies: + regexp-to-ast "0.5.0" + +ci-info@^3.2.0: + version "3.9.0" + resolved "https://registry.yarnpkg.com/ci-info/-/ci-info-3.9.0.tgz#4279a62028a7b1f262f3473fc9605f5e218c59b4" + integrity sha512-NIxF55hv4nSqQswkAeiOi1r83xy8JldOFDTWiug55KBu9Jnblncd2U6ViHmYgHf01TPZS77NJBhBMKdWj9HQMQ== + +cjs-module-lexer@^1.0.0: + version "1.2.3" + resolved "https://registry.yarnpkg.com/cjs-module-lexer/-/cjs-module-lexer-1.2.3.tgz#6c370ab19f8a3394e318fe682686ec0ac684d107" + integrity sha512-0TNiGstbQmCFwt4akjjBg5pLRTSyj/PkWQ1ZoO2zntmg9yLqSRxwEa4iCfQLGjqhiqBfOJa7W/E8wfGrTDmlZQ== + +clean-stack@^2.0.0: + version "2.2.0" + resolved "https://registry.yarnpkg.com/clean-stack/-/clean-stack-2.2.0.tgz#ee8472dbb129e727b31e8a10a427dee9dfe4008b" + integrity sha512-4diC9HaTE+KRAMWhDhrGOECgWZxoevMc5TlkObMqNSsVU62PYzXZ/SMTjzyGAFF1YusgxGcSWTEXBhp0CPwQ1A== + +cli-cursor@^3.1.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/cli-cursor/-/cli-cursor-3.1.0.tgz#264305a7ae490d1d03bf0c9ba7c925d1753af307" + integrity sha512-I/zHAwsKf9FqGoXM4WWRACob9+SNukZTd94DWF57E4toouRulbCxcUh6RKUEOQlYTHJnzkPMySvPNaaSLNfLZw== + dependencies: + restore-cursor "^3.1.0" + +cli-truncate@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/cli-truncate/-/cli-truncate-2.1.0.tgz#c39e28bf05edcde5be3b98992a22deed5a2b93c7" + integrity sha512-n8fOixwDD6b/ObinzTrp1ZKFzbgvKZvuz/TvejnLn1aQfC6r52XEx85FmuC+3HI+JM7coBRXUvNqEU2PHVrHpg== + dependencies: + slice-ansi "^3.0.0" + string-width "^4.2.0" + +cli-truncate@^3.1.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/cli-truncate/-/cli-truncate-3.1.0.tgz#3f23ab12535e3d73e839bb43e73c9de487db1389" + integrity sha512-wfOBkjXteqSnI59oPcJkcPl/ZmwvMMOj340qUIY1SKZCv0B9Cf4D4fAucRkIKQmsIuYK3x1rrgU7MeGRruiuiA== + dependencies: + slice-ansi "^5.0.0" + string-width "^5.0.0" + +cliui@^7.0.2: + version "7.0.4" + resolved "https://registry.yarnpkg.com/cliui/-/cliui-7.0.4.tgz#a0265ee655476fc807aea9df3df8df7783808b4f" + integrity sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ== + dependencies: + string-width "^4.2.0" + strip-ansi "^6.0.0" + wrap-ansi "^7.0.0" + +cliui@^8.0.1: + version "8.0.1" + resolved "https://registry.yarnpkg.com/cliui/-/cliui-8.0.1.tgz#0c04b075db02cbfe60dc8e6cf2f5486b1a3608aa" + integrity sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ== + dependencies: + string-width "^4.2.0" + strip-ansi "^6.0.1" + wrap-ansi "^7.0.0" + +co@^4.6.0: + version "4.6.0" + resolved "https://registry.yarnpkg.com/co/-/co-4.6.0.tgz#6ea6bdf3d853ae54ccb8e47bfa0bf3f9031fb184" + integrity sha512-QVb0dM5HvG+uaxitm8wONl7jltx8dqhfU33DcqtOZcLSVIKSDDLDi7+0LbAKiyI8hD9u42m2YxXSkMGWThaecQ== + +collect-v8-coverage@^1.0.0: + version "1.0.2" + resolved "https://registry.yarnpkg.com/collect-v8-coverage/-/collect-v8-coverage-1.0.2.tgz#c0b29bcd33bcd0779a1344c2136051e6afd3d9e9" + integrity sha512-lHl4d5/ONEbLlJvaJNtsF/Lz+WvB07u2ycqTYbdrq7UypDXailES4valYb2eWiJFxZlVmpGekfqoxQhzyFdT4Q== + +color-convert@^1.9.0: + version "1.9.3" + resolved "https://registry.yarnpkg.com/color-convert/-/color-convert-1.9.3.tgz#bb71850690e1f136567de629d2d5471deda4c1e8" + integrity sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg== + dependencies: + color-name "1.1.3" + +color-convert@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/color-convert/-/color-convert-2.0.1.tgz#72d3a68d598c9bdb3af2ad1e84f21d896abd4de3" + integrity sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ== + dependencies: + color-name "~1.1.4" + +color-name@1.1.3: + version "1.1.3" + resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.3.tgz#a7d0558bd89c42f795dd42328f740831ca53bc25" + integrity sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw== + +color-name@~1.1.4: + version "1.1.4" + resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.4.tgz#c2a09a87acbde69543de6f63fa3995c826c536a2" + integrity sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA== + +colorette@^2.0.16: + version "2.0.20" + resolved "https://registry.yarnpkg.com/colorette/-/colorette-2.0.20.tgz#9eb793e6833067f7235902fcd3b09917a000a95a" + integrity sha512-IfEDxwoWIjkeXL1eXcDiow4UbKjhLdq6/EuSVR9GMN7KVH3r9gQ83e73hsz1Nd1T3ijd5xv1wcWRYO+D6kCI2w== + +combined-stream@^1.0.8: + version "1.0.8" + resolved "https://registry.yarnpkg.com/combined-stream/-/combined-stream-1.0.8.tgz#c3d45a8b34fd730631a110a8a2520682b31d5a7f" + integrity sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg== + dependencies: + delayed-stream "~1.0.0" + +commander@^9.3.0: + version "9.5.0" + resolved "https://registry.yarnpkg.com/commander/-/commander-9.5.0.tgz#bc08d1eb5cedf7ccb797a96199d41c7bc3e60d30" + integrity sha512-KRs7WVDKg86PWiuAqhDrAQnTXZKraVcCc6vFdL14qrZ/DcWwuRo7VoiYXalXO7S5GKpqYiVEwCbgFDfxNHKJBQ== + +concat-map@0.0.1: + version "0.0.1" + resolved "https://registry.yarnpkg.com/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b" + integrity sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg== + +convert-source-map@^1.4.0, convert-source-map@^1.6.0, convert-source-map@^1.7.0: + version "1.9.0" + resolved "https://registry.yarnpkg.com/convert-source-map/-/convert-source-map-1.9.0.tgz#7faae62353fb4213366d0ca98358d22e8368b05f" + integrity sha512-ASFBup0Mz1uyiIjANan1jzLQami9z1PoYSZCiiYW2FczPbenXc45FZdBZLzOT+r6+iciuEModtmCti+hjaAk0A== + +convert-source-map@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/convert-source-map/-/convert-source-map-2.0.0.tgz#4b560f649fc4e918dd0ab75cf4961e8bc882d82a" + integrity sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg== + +cross-spawn@^7.0.2, cross-spawn@^7.0.3: + version "7.0.3" + resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-7.0.3.tgz#f73a85b9d5d41d045551c177e2882d4ac85728a6" + integrity sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w== + dependencies: + path-key "^3.1.0" + shebang-command "^2.0.0" + which "^2.0.1" + +cssesc@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/cssesc/-/cssesc-3.0.0.tgz#37741919903b868565e1c09ea747445cd18983ee" + integrity sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg== + +cssom@^0.4.4: + version "0.4.4" + resolved "https://registry.yarnpkg.com/cssom/-/cssom-0.4.4.tgz#5a66cf93d2d0b661d80bf6a44fb65f5c2e4e0a10" + integrity sha512-p3pvU7r1MyyqbTk+WbNJIgJjG2VmTIaB10rI93LzVPrmDJKkzKYMtxxyAvQXR/NS6otuzveI7+7BBq3SjBS2mw== + +cssom@~0.3.6: + version "0.3.8" + resolved "https://registry.yarnpkg.com/cssom/-/cssom-0.3.8.tgz#9f1276f5b2b463f2114d3f2c75250af8c1a36f4a" + integrity sha512-b0tGHbfegbhPJpxpiBPU2sCkigAqtM9O121le6bbOlgyV+NyGyCmVfJ6QW9eRjz8CpNfWEOYBIMIGRYkLwsIYg== + +cssstyle@^2.3.0: + version "2.3.0" + resolved "https://registry.yarnpkg.com/cssstyle/-/cssstyle-2.3.0.tgz#ff665a0ddbdc31864b09647f34163443d90b0852" + integrity sha512-AZL67abkUzIuvcHqk7c09cezpGNcxUxU4Ioi/05xHk4DQeTkWmGYftIE6ctU6AEt+Gn4n1lDStOtj7FKycP71A== + dependencies: + cssom "~0.3.6" + +data-urls@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/data-urls/-/data-urls-2.0.0.tgz#156485a72963a970f5d5821aaf642bef2bf2db9b" + integrity sha512-X5eWTSXO/BJmpdIKCRuKUgSCgAN0OwliVK3yPKbwIWU1Tdw5BRajxlzMidvh+gwko9AfQ9zIj52pzF91Q3YAvQ== + dependencies: + abab "^2.0.3" + whatwg-mimetype "^2.3.0" + whatwg-url "^8.0.0" + +debug@4, debug@^4.1.0, debug@^4.1.1, debug@^4.3.2, debug@^4.3.4: + version "4.3.4" + resolved "https://registry.yarnpkg.com/debug/-/debug-4.3.4.tgz#1319f6579357f2338d3337d2cdd4914bb5dcc865" + integrity sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ== + dependencies: + ms "2.1.2" + +debug@^3.2.7: + version "3.2.7" + resolved "https://registry.yarnpkg.com/debug/-/debug-3.2.7.tgz#72580b7e9145fb39b6676f9c5e5fb100b934179a" + integrity sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ== + dependencies: + ms "^2.1.1" + +decimal.js@^10.2.1: + version "10.4.3" + resolved "https://registry.yarnpkg.com/decimal.js/-/decimal.js-10.4.3.tgz#1044092884d245d1b7f65725fa4ad4c6f781cc23" + integrity sha512-VBBaLc1MgL5XpzgIP7ny5Z6Nx3UrRkIViUkPUdtl9aya5amy3De1gsUUSB1g3+3sExYNjCAsAznmukyxCb1GRA== + +dedent@^0.7.0: + version "0.7.0" + resolved "https://registry.yarnpkg.com/dedent/-/dedent-0.7.0.tgz#2495ddbaf6eb874abb0e1be9df22d2e5a544326c" + integrity sha512-Q6fKUPqnAHAyhiUgFU7BUzLiv0kd8saH9al7tnu5Q/okj6dnupxyTgFIBjVzJATdfIAm9NAsvXNzjaKa+bxVyA== + +deep-is@^0.1.3: + version "0.1.4" + resolved "https://registry.yarnpkg.com/deep-is/-/deep-is-0.1.4.tgz#a6f2dce612fadd2ef1f519b73551f17e85199831" + integrity sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ== + +deepmerge@^4.2.2: + version "4.3.1" + resolved "https://registry.yarnpkg.com/deepmerge/-/deepmerge-4.3.1.tgz#44b5f2147cd3b00d4b56137685966f26fd25dd4a" + integrity sha512-3sUqbMEc77XqpdNO7FRyRog+eW3ph+GYCbj+rK+uYyRMuwsVy0rMiVtPn+QJlKFvWP/1PYpapqYn0Me2knFn+A== + +define-data-property@^1.0.1, define-data-property@^1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/define-data-property/-/define-data-property-1.1.1.tgz#c35f7cd0ab09883480d12ac5cb213715587800b3" + integrity sha512-E7uGkTzkk1d0ByLeSc6ZsFS79Axg+m1P/VsgYsxHgiuc3tFSj+MjMIwe90FC4lOAZzNBdY7kkO2P2wKdsQ1vgQ== + dependencies: + get-intrinsic "^1.2.1" + gopd "^1.0.1" + has-property-descriptors "^1.0.0" + +define-properties@^1.1.3, define-properties@^1.1.4, define-properties@^1.2.0: + version "1.2.1" + resolved "https://registry.yarnpkg.com/define-properties/-/define-properties-1.2.1.tgz#10781cc616eb951a80a034bafcaa7377f6af2b6c" + integrity sha512-8QmQKqEASLd5nx0U1B1okLElbUuuttJ/AnYmRXbbbGDWh6uS208EjD4Xqq/I9wK7u0v6O08XhTWnt5XtEbR6Dg== + dependencies: + define-data-property "^1.0.1" + has-property-descriptors "^1.0.0" + object-keys "^1.1.1" + +delayed-stream@~1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/delayed-stream/-/delayed-stream-1.0.0.tgz#df3ae199acadfb7d440aaae0b29e2272b24ec619" + integrity sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ== + +detect-newline@^3.0.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/detect-newline/-/detect-newline-3.1.0.tgz#576f5dfc63ae1a192ff192d8ad3af6308991b651" + integrity sha512-TLz+x/vEXm/Y7P7wn1EJFNLxYpUD4TgMosxY6fAVJUnJMbupHBOncxyWUG9OpTaH9EBD7uFI5LfEgmMOc54DsA== + +diff-sequences@^27.5.1: + version "27.5.1" + resolved "https://registry.yarnpkg.com/diff-sequences/-/diff-sequences-27.5.1.tgz#eaecc0d327fd68c8d9672a1e64ab8dccb2ef5327" + integrity sha512-k1gCAXAsNgLwEL+Y8Wvl+M6oEFj5bgazfZULpS5CneoPPXRaCCW7dm+q21Ky2VEE5X+VeRDBVg1Pcvvsr4TtNQ== + +dir-glob@^3.0.1: + version "3.0.1" + resolved "https://registry.yarnpkg.com/dir-glob/-/dir-glob-3.0.1.tgz#56dbf73d992a4a93ba1584f4534063fd2e41717f" + integrity sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA== + dependencies: + path-type "^4.0.0" + +doctrine@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/doctrine/-/doctrine-2.1.0.tgz#5cd01fc101621b42c4cd7f5d1a66243716d3f39d" + integrity sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw== + dependencies: + esutils "^2.0.2" + +doctrine@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/doctrine/-/doctrine-3.0.0.tgz#addebead72a6574db783639dc87a121773973961" + integrity sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w== + dependencies: + esutils "^2.0.2" + +domexception@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/domexception/-/domexception-2.0.1.tgz#fb44aefba793e1574b0af6aed2801d057529f304" + integrity sha512-yxJ2mFy/sibVQlu5qHjOkf9J3K6zgmCxgJ94u2EdvDOV09H+32LtRswEcUsmUWN72pVLOEnTSRaIVVzVQgS0dg== + dependencies: + webidl-conversions "^5.0.0" + +eastasianwidth@^0.2.0: + version "0.2.0" + resolved "https://registry.yarnpkg.com/eastasianwidth/-/eastasianwidth-0.2.0.tgz#696ce2ec0aa0e6ea93a397ffcf24aa7840c827cb" + integrity sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA== + +electron-to-chromium@^1.4.535: + version "1.4.596" + resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.4.596.tgz#6752d1aa795d942d49dfc5d3764d6ea283fab1d7" + integrity sha512-zW3zbZ40Icb2BCWjm47nxwcFGYlIgdXkAx85XDO7cyky9J4QQfq8t0W19/TLZqq3JPQXtlv8BPIGmfa9Jb4scg== + +emittery@^0.8.1: + version "0.8.1" + resolved "https://registry.yarnpkg.com/emittery/-/emittery-0.8.1.tgz#bb23cc86d03b30aa75a7f734819dee2e1ba70860" + integrity sha512-uDfvUjVrfGJJhymx/kz6prltenw1u7WrCg1oa94zYY8xxVpLLUu045LAT0dhDZdXG58/EpPL/5kA180fQ/qudg== + +emoji-regex@^8.0.0: + version "8.0.0" + resolved "https://registry.yarnpkg.com/emoji-regex/-/emoji-regex-8.0.0.tgz#e818fd69ce5ccfcb404594f842963bf53164cc37" + integrity sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A== + +emoji-regex@^9.2.2: + version "9.2.2" + resolved "https://registry.yarnpkg.com/emoji-regex/-/emoji-regex-9.2.2.tgz#840c8803b0d8047f4ff0cf963176b32d4ef3ed72" + integrity sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg== + +error-ex@^1.3.1: + version "1.3.2" + resolved "https://registry.yarnpkg.com/error-ex/-/error-ex-1.3.2.tgz#b4ac40648107fdcdcfae242f428bea8a14d4f1bf" + integrity sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g== + dependencies: + is-arrayish "^0.2.1" + +es-abstract@^1.22.1: + version "1.22.3" + resolved "https://registry.yarnpkg.com/es-abstract/-/es-abstract-1.22.3.tgz#48e79f5573198de6dee3589195727f4f74bc4f32" + integrity sha512-eiiY8HQeYfYH2Con2berK+To6GrK2RxbPawDkGq4UiCQQfZHb6wX9qQqkbpPqaxQFcl8d9QzZqo0tGE0VcrdwA== + dependencies: + array-buffer-byte-length "^1.0.0" + arraybuffer.prototype.slice "^1.0.2" + available-typed-arrays "^1.0.5" + call-bind "^1.0.5" + es-set-tostringtag "^2.0.1" + es-to-primitive "^1.2.1" + function.prototype.name "^1.1.6" + get-intrinsic "^1.2.2" + get-symbol-description "^1.0.0" + globalthis "^1.0.3" + gopd "^1.0.1" + has-property-descriptors "^1.0.0" + has-proto "^1.0.1" + has-symbols "^1.0.3" + hasown "^2.0.0" + internal-slot "^1.0.5" + is-array-buffer "^3.0.2" + is-callable "^1.2.7" + is-negative-zero "^2.0.2" + is-regex "^1.1.4" + is-shared-array-buffer "^1.0.2" + is-string "^1.0.7" + is-typed-array "^1.1.12" + is-weakref "^1.0.2" + object-inspect "^1.13.1" + object-keys "^1.1.1" + object.assign "^4.1.4" + regexp.prototype.flags "^1.5.1" + safe-array-concat "^1.0.1" + safe-regex-test "^1.0.0" + string.prototype.trim "^1.2.8" + string.prototype.trimend "^1.0.7" + string.prototype.trimstart "^1.0.7" + typed-array-buffer "^1.0.0" + typed-array-byte-length "^1.0.0" + typed-array-byte-offset "^1.0.0" + typed-array-length "^1.0.4" + unbox-primitive "^1.0.2" + which-typed-array "^1.1.13" + +es-set-tostringtag@^2.0.1: + version "2.0.2" + resolved "https://registry.yarnpkg.com/es-set-tostringtag/-/es-set-tostringtag-2.0.2.tgz#11f7cc9f63376930a5f20be4915834f4bc74f9c9" + integrity sha512-BuDyupZt65P9D2D2vA/zqcI3G5xRsklm5N3xCwuiy+/vKy8i0ifdsQP1sLgO4tZDSCaQUSnmC48khknGMV3D2Q== + dependencies: + get-intrinsic "^1.2.2" + has-tostringtag "^1.0.0" + hasown "^2.0.0" + +es-shim-unscopables@^1.0.0: + version "1.0.2" + resolved "https://registry.yarnpkg.com/es-shim-unscopables/-/es-shim-unscopables-1.0.2.tgz#1f6942e71ecc7835ed1c8a83006d8771a63a3763" + integrity sha512-J3yBRXCzDu4ULnQwxyToo/OjdMx6akgVC7K6few0a7F/0wLtmKKN7I73AH5T2836UuXRqN7Qg+IIUw/+YJksRw== + dependencies: + hasown "^2.0.0" + +es-to-primitive@^1.2.1: + version "1.2.1" + resolved "https://registry.yarnpkg.com/es-to-primitive/-/es-to-primitive-1.2.1.tgz#e55cd4c9cdc188bcefb03b366c736323fc5c898a" + integrity sha512-QCOllgZJtaUo9miYBcLChTUaHNjJF3PYs1VidD7AwiEj1kYxKeQTctLAezAOH5ZKRH0g2IgPn6KwB4IT8iRpvA== + dependencies: + is-callable "^1.1.4" + is-date-object "^1.0.1" + is-symbol "^1.0.2" + +escalade@^3.1.1: + version "3.1.1" + resolved "https://registry.yarnpkg.com/escalade/-/escalade-3.1.1.tgz#d8cfdc7000965c5a0174b4a82eaa5c0552742e40" + integrity sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw== + +escape-string-regexp@^1.0.5: + version "1.0.5" + resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz#1b61c0562190a8dff6ae3bb2cf0200ca130b86d4" + integrity sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg== + +escape-string-regexp@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-2.0.0.tgz#a30304e99daa32e23b2fd20f51babd07cffca344" + integrity sha512-UpzcLCXolUWcNu5HtVMHYdXJjArjsF9C0aNnquZYY4uW/Vu0miy5YoWvbV345HauVvcAUnpRuhMMcqTcGOY2+w== + +escape-string-regexp@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz#14ba83a5d373e3d311e5afca29cf5bfad965bf34" + integrity sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA== + +escodegen@^2.0.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/escodegen/-/escodegen-2.1.0.tgz#ba93bbb7a43986d29d6041f99f5262da773e2e17" + integrity sha512-2NlIDTwUWJN0mRPQOdtQBzbUHvdGY2P1VXSyU83Q3xKxM7WHX2Ql8dKq782Q9TgQUNOLEzEYu9bzLNj1q88I5w== + dependencies: + esprima "^4.0.1" + estraverse "^5.2.0" + esutils "^2.0.2" + optionalDependencies: + source-map "~0.6.1" + +eslint-import-resolver-node@^0.3.9: + version "0.3.9" + resolved "https://registry.yarnpkg.com/eslint-import-resolver-node/-/eslint-import-resolver-node-0.3.9.tgz#d4eaac52b8a2e7c3cd1903eb00f7e053356118ac" + integrity sha512-WFj2isz22JahUv+B788TlO3N6zL3nNJGU8CcZbPZvVEkBPaJdCV4vy5wyghty5ROFbCRnm132v8BScu5/1BQ8g== + dependencies: + debug "^3.2.7" + is-core-module "^2.13.0" + resolve "^1.22.4" + +eslint-module-utils@^2.8.0: + version "2.8.0" + resolved "https://registry.yarnpkg.com/eslint-module-utils/-/eslint-module-utils-2.8.0.tgz#e439fee65fc33f6bba630ff621efc38ec0375c49" + integrity sha512-aWajIYfsqCKRDgUfjEXNN/JlrzauMuSEy5sbd7WXbtW3EH6A6MpwEh42c7qD+MqQo9QMJ6fWLAeIJynx0g6OAw== + dependencies: + debug "^3.2.7" + +eslint-plugin-compat@^4.0.2: + version "4.2.0" + resolved "https://registry.yarnpkg.com/eslint-plugin-compat/-/eslint-plugin-compat-4.2.0.tgz#eeaf80daa1afe495c88a47e9281295acae45c0aa" + integrity sha512-RDKSYD0maWy5r7zb5cWQS+uSPc26mgOzdORJ8hxILmWM7S/Ncwky7BcAtXVY5iRbKjBdHsWU8Yg7hfoZjtkv7w== + dependencies: + "@mdn/browser-compat-data" "^5.3.13" + ast-metadata-inferer "^0.8.0" + browserslist "^4.21.10" + caniuse-lite "^1.0.30001524" + find-up "^5.0.0" + lodash.memoize "^4.1.2" + semver "^7.5.4" + +eslint-plugin-import@^2.25.4: + version "2.29.0" + resolved "https://registry.yarnpkg.com/eslint-plugin-import/-/eslint-plugin-import-2.29.0.tgz#8133232e4329ee344f2f612885ac3073b0b7e155" + integrity sha512-QPOO5NO6Odv5lpoTkddtutccQjysJuFxoPS7fAHO+9m9udNHvTCPSAMW9zGAYj8lAIdr40I8yPCdUYrncXtrwg== + dependencies: + array-includes "^3.1.7" + array.prototype.findlastindex "^1.2.3" + array.prototype.flat "^1.3.2" + array.prototype.flatmap "^1.3.2" + debug "^3.2.7" + doctrine "^2.1.0" + eslint-import-resolver-node "^0.3.9" + eslint-module-utils "^2.8.0" + hasown "^2.0.0" + is-core-module "^2.13.1" + is-glob "^4.0.3" + minimatch "^3.1.2" + object.fromentries "^2.0.7" + object.groupby "^1.0.1" + object.values "^1.1.7" + semver "^6.3.1" + tsconfig-paths "^3.14.2" + +eslint-plugin-jest@^26.1.2: + version "26.9.0" + resolved "https://registry.yarnpkg.com/eslint-plugin-jest/-/eslint-plugin-jest-26.9.0.tgz#7931c31000b1c19e57dbfb71bbf71b817d1bf949" + integrity sha512-TWJxWGp1J628gxh2KhaH1H1paEdgE2J61BBF1I59c6xWeL5+D1BzMxGDN/nXAfX+aSkR5u80K+XhskK6Gwq9ng== + dependencies: + "@typescript-eslint/utils" "^5.10.0" + +eslint-restricted-globals@~0.2.0: + version "0.2.0" + resolved "https://registry.yarnpkg.com/eslint-restricted-globals/-/eslint-restricted-globals-0.2.0.tgz#7729f326af97bec7a7e56d9f7d9c064b79285c50" + integrity sha512-kwYJALm5KS2QW3Mc1PgObO4V+pTR6RQtRT65L1GQILlEnAhabUQqGAX7/qUjoQR4KZJKehWpBtyDEiDecwmY9A== + +eslint-scope@5.1.1, eslint-scope@^5.1.1: + version "5.1.1" + resolved "https://registry.yarnpkg.com/eslint-scope/-/eslint-scope-5.1.1.tgz#e786e59a66cb92b3f6c1fb0d508aab174848f48c" + integrity sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw== + dependencies: + esrecurse "^4.3.0" + estraverse "^4.1.1" + +eslint-scope@^7.2.2: + version "7.2.2" + resolved "https://registry.yarnpkg.com/eslint-scope/-/eslint-scope-7.2.2.tgz#deb4f92563390f32006894af62a22dba1c46423f" + integrity sha512-dOt21O7lTMhDM+X9mB4GX+DZrZtCUJPL/wlcTqxyrx5IvO0IYtILdtrQGQp+8n5S0gwSVmOf9NQrjMOgfQZlIg== + dependencies: + esrecurse "^4.3.0" + estraverse "^5.2.0" + +eslint-visitor-keys@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-2.1.0.tgz#f65328259305927392c938ed44eb0a5c9b2bd303" + integrity sha512-0rSmRBzXgDzIsD6mGdJgevzgezI534Cer5L/vyMX0kHzT/jiB43jRhd9YUlMGYLQy2zprNmoT8qasCGtY+QaKw== + +eslint-visitor-keys@^3.3.0, eslint-visitor-keys@^3.4.1, eslint-visitor-keys@^3.4.3: + version "3.4.3" + resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz#0cd72fe8550e3c2eae156a96a4dddcd1c8ac5800" + integrity sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag== + +eslint@^8.11.0: + version "8.54.0" + resolved "https://registry.yarnpkg.com/eslint/-/eslint-8.54.0.tgz#588e0dd4388af91a2e8fa37ea64924074c783537" + integrity sha512-NY0DfAkM8BIZDVl6PgSa1ttZbx3xHgJzSNJKYcQglem6CppHyMhRIQkBVSSMaSRnLhig3jsDbEzOjwCVt4AmmA== + dependencies: + "@eslint-community/eslint-utils" "^4.2.0" + "@eslint-community/regexpp" "^4.6.1" + "@eslint/eslintrc" "^2.1.3" + "@eslint/js" "8.54.0" + "@humanwhocodes/config-array" "^0.11.13" + "@humanwhocodes/module-importer" "^1.0.1" + "@nodelib/fs.walk" "^1.2.8" + "@ungap/structured-clone" "^1.2.0" + ajv "^6.12.4" + chalk "^4.0.0" + cross-spawn "^7.0.2" + debug "^4.3.2" + doctrine "^3.0.0" + escape-string-regexp "^4.0.0" + eslint-scope "^7.2.2" + eslint-visitor-keys "^3.4.3" + espree "^9.6.1" + esquery "^1.4.2" + esutils "^2.0.2" + fast-deep-equal "^3.1.3" + file-entry-cache "^6.0.1" + find-up "^5.0.0" + glob-parent "^6.0.2" + globals "^13.19.0" + graphemer "^1.4.0" + ignore "^5.2.0" + imurmurhash "^0.1.4" + is-glob "^4.0.0" + is-path-inside "^3.0.3" + js-yaml "^4.1.0" + json-stable-stringify-without-jsonify "^1.0.1" + levn "^0.4.1" + lodash.merge "^4.6.2" + minimatch "^3.1.2" + natural-compare "^1.4.0" + optionator "^0.9.3" + strip-ansi "^6.0.1" + text-table "^0.2.0" + +espree@^9.6.0, espree@^9.6.1: + version "9.6.1" + resolved "https://registry.yarnpkg.com/espree/-/espree-9.6.1.tgz#a2a17b8e434690a5432f2f8018ce71d331a48c6f" + integrity sha512-oruZaFkjorTpF32kDSI5/75ViwGeZginGGy2NoOSg3Q9bnwlnmDm4HLnkl0RE3n+njDXR037aY1+x58Z/zFdwQ== + dependencies: + acorn "^8.9.0" + acorn-jsx "^5.3.2" + eslint-visitor-keys "^3.4.1" + +esprima@^4.0.0, esprima@^4.0.1: + version "4.0.1" + resolved "https://registry.yarnpkg.com/esprima/-/esprima-4.0.1.tgz#13b04cdb3e6c5d19df91ab6987a8695619b0aa71" + integrity sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A== + +esquery@^1.4.2: + version "1.5.0" + resolved "https://registry.yarnpkg.com/esquery/-/esquery-1.5.0.tgz#6ce17738de8577694edd7361c57182ac8cb0db0b" + integrity sha512-YQLXUplAwJgCydQ78IMJywZCceoqk1oH01OERdSAJc/7U2AylwjhSCLDEtqwg811idIS/9fIU5GjG73IgjKMVg== + dependencies: + estraverse "^5.1.0" + +esrecurse@^4.3.0: + version "4.3.0" + resolved "https://registry.yarnpkg.com/esrecurse/-/esrecurse-4.3.0.tgz#7ad7964d679abb28bee72cec63758b1c5d2c9921" + integrity sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag== + dependencies: + estraverse "^5.2.0" + +estraverse@^4.1.1: + version "4.3.0" + resolved "https://registry.yarnpkg.com/estraverse/-/estraverse-4.3.0.tgz#398ad3f3c5a24948be7725e83d11a7de28cdbd1d" + integrity sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw== + +estraverse@^5.1.0, estraverse@^5.2.0: + version "5.3.0" + resolved "https://registry.yarnpkg.com/estraverse/-/estraverse-5.3.0.tgz#2eea5290702f26ab8fe5370370ff86c965d21123" + integrity sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA== + +estree-walker@~2.0.2: + version "2.0.2" + resolved "https://registry.yarnpkg.com/estree-walker/-/estree-walker-2.0.2.tgz#52f010178c2a4c117a7757cfe942adb7d2da4cac" + integrity sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w== + +esutils@^2.0.2: + version "2.0.3" + resolved "https://registry.yarnpkg.com/esutils/-/esutils-2.0.3.tgz#74d2eb4de0b8da1293711910d50775b9b710ef64" + integrity sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g== + +execa@^5.0.0, execa@^5.1.1: + version "5.1.1" + resolved "https://registry.yarnpkg.com/execa/-/execa-5.1.1.tgz#f80ad9cbf4298f7bd1d4c9555c21e93741c411dd" + integrity sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg== + dependencies: + cross-spawn "^7.0.3" + get-stream "^6.0.0" + human-signals "^2.1.0" + is-stream "^2.0.0" + merge-stream "^2.0.0" + npm-run-path "^4.0.1" + onetime "^5.1.2" + signal-exit "^3.0.3" + strip-final-newline "^2.0.0" + +exit@^0.1.2: + version "0.1.2" + resolved "https://registry.yarnpkg.com/exit/-/exit-0.1.2.tgz#0632638f8d877cc82107d30a0fff1a17cba1cd0c" + integrity sha512-Zk/eNKV2zbjpKzrsQ+n1G6poVbErQxJ0LBOJXaKZ1EViLzH+hrLu9cdXI4zw9dBQJslwBEpbQ2P1oS7nDxs6jQ== + +expect@^27.5.1: + version "27.5.1" + resolved "https://registry.yarnpkg.com/expect/-/expect-27.5.1.tgz#83ce59f1e5bdf5f9d2b94b61d2050db48f3fef74" + integrity sha512-E1q5hSUG2AmYQwQJ041nvgpkODHQvB+RKlB4IYdru6uJsyFTRyZAP463M+1lINorwbqAmUggi6+WwkD8lCS/Dw== + dependencies: + "@jest/types" "^27.5.1" + jest-get-type "^27.5.1" + jest-matcher-utils "^27.5.1" + jest-message-util "^27.5.1" + +fast-deep-equal@^3.1.1, fast-deep-equal@^3.1.3: + version "3.1.3" + resolved "https://registry.yarnpkg.com/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz#3a7d56b559d6cbc3eb512325244e619a65c6c525" + integrity sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q== + +fast-glob@^3.2.12, fast-glob@^3.2.9: + version "3.3.2" + resolved "https://registry.yarnpkg.com/fast-glob/-/fast-glob-3.3.2.tgz#a904501e57cfdd2ffcded45e99a54fef55e46129" + integrity sha512-oX2ruAFQwf/Orj8m737Y5adxDQO0LAB7/S5MnxCdTNDd4p6BsyIVsv9JQsATbTSq8KHRpLwIHbVlUNatxd+1Ow== + dependencies: + "@nodelib/fs.stat" "^2.0.2" + "@nodelib/fs.walk" "^1.2.3" + glob-parent "^5.1.2" + merge2 "^1.3.0" + micromatch "^4.0.4" + +fast-json-stable-stringify@^2.0.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz#874bf69c6f404c2b5d99c481341399fd55892633" + integrity sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw== + +fast-levenshtein@^2.0.6: + version "2.0.6" + resolved "https://registry.yarnpkg.com/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz#3d8a5c66883a16a30ca8643e851f19baa7797917" + integrity sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw== + +fastq@^1.6.0: + version "1.15.0" + resolved "https://registry.yarnpkg.com/fastq/-/fastq-1.15.0.tgz#d04d07c6a2a68fe4599fea8d2e103a937fae6b3a" + integrity sha512-wBrocU2LCXXa+lWBt8RoIRD89Fi8OdABODa/kEnyeyjS5aZO5/GNvI5sEINADqP/h8M29UHTHUb53sUu5Ihqdw== + dependencies: + reusify "^1.0.4" + +fb-watchman@^2.0.0: + version "2.0.2" + resolved "https://registry.yarnpkg.com/fb-watchman/-/fb-watchman-2.0.2.tgz#e9524ee6b5c77e9e5001af0f85f3adbb8623255c" + integrity sha512-p5161BqbuCaSnB8jIbzQHOlpgsPmK5rJVDfDKO91Axs5NC1uu3HRQm6wt9cd9/+GtQQIO53JdGXXoyDpTAsgYA== + dependencies: + bser "2.1.1" + +file-entry-cache@^6.0.1: + version "6.0.1" + resolved "https://registry.yarnpkg.com/file-entry-cache/-/file-entry-cache-6.0.1.tgz#211b2dd9659cb0394b073e7323ac3c933d522027" + integrity sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg== + dependencies: + flat-cache "^3.0.4" + +fill-range@^7.0.1: + version "7.0.1" + resolved "https://registry.yarnpkg.com/fill-range/-/fill-range-7.0.1.tgz#1919a6a7c75fe38b2c7c77e5198535da9acdda40" + integrity sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ== + dependencies: + to-regex-range "^5.0.1" + +find-up@^4.0.0, find-up@^4.1.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/find-up/-/find-up-4.1.0.tgz#97afe7d6cdc0bc5928584b7c8d7b16e8a9aa5d19" + integrity sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw== + dependencies: + locate-path "^5.0.0" + path-exists "^4.0.0" + +find-up@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/find-up/-/find-up-5.0.0.tgz#4c92819ecb7083561e4f4a240a86be5198f536fc" + integrity sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng== + dependencies: + locate-path "^6.0.0" + path-exists "^4.0.0" + +flat-cache@^3.0.4: + version "3.2.0" + resolved "https://registry.yarnpkg.com/flat-cache/-/flat-cache-3.2.0.tgz#2c0c2d5040c99b1632771a9d105725c0115363ee" + integrity sha512-CYcENa+FtcUKLmhhqyctpclsq7QF38pKjZHsGNiSQF5r4FtoKDWabFDl3hzaEQMvT1LHEysw5twgLvpYYb4vbw== + dependencies: + flatted "^3.2.9" + keyv "^4.5.3" + rimraf "^3.0.2" + +flatted@^3.2.9: + version "3.2.9" + resolved "https://registry.yarnpkg.com/flatted/-/flatted-3.2.9.tgz#7eb4c67ca1ba34232ca9d2d93e9886e611ad7daf" + integrity sha512-36yxDn5H7OFZQla0/jFJmbIKTdZAQHngCedGxiMmpNfEZM0sdEeT+WczLQrjK6D7o2aiyLYDnkw0R3JK0Qv1RQ== + +follow-redirects@^1.15.0: + version "1.15.3" + resolved "https://registry.yarnpkg.com/follow-redirects/-/follow-redirects-1.15.3.tgz#fe2f3ef2690afce7e82ed0b44db08165b207123a" + integrity sha512-1VzOtuEM8pC9SFU1E+8KfTjZyMztRsgEfwQl44z8A25uy13jSzTj6dyK2Df52iV0vgHCfBwLhDWevLn95w5v6Q== + +for-each@^0.3.3: + version "0.3.3" + resolved "https://registry.yarnpkg.com/for-each/-/for-each-0.3.3.tgz#69b447e88a0a5d32c3e7084f3f1710034b21376e" + integrity sha512-jqYfLp7mo9vIyQf8ykW2v7A+2N4QjeCeI5+Dz9XraiO1ign81wjiH7Fb9vSOWvQfNtmSa4H2RoQTrrXivdUZmw== + dependencies: + is-callable "^1.1.3" + +form-data@^3.0.0: + version "3.0.1" + resolved "https://registry.yarnpkg.com/form-data/-/form-data-3.0.1.tgz#ebd53791b78356a99af9a300d4282c4d5eb9755f" + integrity sha512-RHkBKtLWUVwd7SqRIvCZMEvAMoGUp0XU+seQiZejj0COz3RI3hWP4sCv3gZWWLjJTd7rGwcsF5eKZGii0r/hbg== + dependencies: + asynckit "^0.4.0" + combined-stream "^1.0.8" + mime-types "^2.1.12" + +form-data@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/form-data/-/form-data-4.0.0.tgz#93919daeaf361ee529584b9b31664dc12c9fa452" + integrity sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww== + dependencies: + asynckit "^0.4.0" + combined-stream "^1.0.8" + mime-types "^2.1.12" + +fs.realpath@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/fs.realpath/-/fs.realpath-1.0.0.tgz#1504ad2523158caa40db4a2787cb01411994ea4f" + integrity sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw== + +fsevents@^2.3.2: + version "2.3.3" + resolved "https://registry.yarnpkg.com/fsevents/-/fsevents-2.3.3.tgz#cac6407785d03675a2a5e1a5305c697b347d90d6" + integrity sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw== + +function-bind@^1.1.2: + version "1.1.2" + resolved "https://registry.yarnpkg.com/function-bind/-/function-bind-1.1.2.tgz#2c02d864d97f3ea6c8830c464cbd11ab6eab7a1c" + integrity sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA== + +function.prototype.name@^1.1.6: + version "1.1.6" + resolved "https://registry.yarnpkg.com/function.prototype.name/-/function.prototype.name-1.1.6.tgz#cdf315b7d90ee77a4c6ee216c3c3362da07533fd" + integrity sha512-Z5kx79swU5P27WEayXM1tBi5Ze/lbIyiNgU3qyXUOf9b2rgXYyF9Dy9Cx+IQv/Lc8WCG6L82zwUPpSS9hGehIg== + dependencies: + call-bind "^1.0.2" + define-properties "^1.2.0" + es-abstract "^1.22.1" + functions-have-names "^1.2.3" + +functions-have-names@^1.2.3: + version "1.2.3" + resolved "https://registry.yarnpkg.com/functions-have-names/-/functions-have-names-1.2.3.tgz#0404fe4ee2ba2f607f0e0ec3c80bae994133b834" + integrity sha512-xckBUXyTIqT97tq2x2AMb+g163b5JFysYk0x4qxNFwbfQkmNZoiRHb6sPzI9/QV33WeuvVYBUIiD4NzNIyqaRQ== + +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" + integrity sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg== + +get-caller-file@^2.0.5: + version "2.0.5" + resolved "https://registry.yarnpkg.com/get-caller-file/-/get-caller-file-2.0.5.tgz#4f94412a82db32f36e3b0b9741f8a97feb031f7e" + integrity sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg== + +get-intrinsic@^1.0.2, get-intrinsic@^1.1.1, get-intrinsic@^1.1.3, get-intrinsic@^1.2.0, get-intrinsic@^1.2.1, get-intrinsic@^1.2.2: + version "1.2.2" + resolved "https://registry.yarnpkg.com/get-intrinsic/-/get-intrinsic-1.2.2.tgz#281b7622971123e1ef4b3c90fd7539306da93f3b" + integrity sha512-0gSo4ml/0j98Y3lngkFEot/zhiCeWsbYIlZ+uZOVgzLyLaUw7wxUL+nCTP0XJvJg1AXulJRI3UJi8GsbDuxdGA== + dependencies: + function-bind "^1.1.2" + has-proto "^1.0.1" + has-symbols "^1.0.3" + hasown "^2.0.0" + +get-package-type@^0.1.0: + version "0.1.0" + resolved "https://registry.yarnpkg.com/get-package-type/-/get-package-type-0.1.0.tgz#8de2d803cff44df3bc6c456e6668b36c3926e11a" + integrity sha512-pjzuKtY64GYfWizNAJ0fr9VqttZkNiK2iS430LtIHzjBEr6bX8Am2zm4sW4Ro5wjWW5cAlRL1qAMTcXbjNAO2Q== + +get-stream@^6.0.0: + version "6.0.1" + resolved "https://registry.yarnpkg.com/get-stream/-/get-stream-6.0.1.tgz#a262d8eef67aced57c2852ad6167526a43cbf7b7" + integrity sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg== + +get-symbol-description@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/get-symbol-description/-/get-symbol-description-1.0.0.tgz#7fdb81c900101fbd564dd5f1a30af5aadc1e58d6" + integrity sha512-2EmdH1YvIQiZpltCNgkuiUnyukzxM/R6NDJX31Ke3BG1Nq5b0S2PhX59UKi9vZpPDQVdqn+1IcaAwnzTT5vCjw== + dependencies: + call-bind "^1.0.2" + get-intrinsic "^1.1.1" + +glob-parent@^5.1.2: + version "5.1.2" + resolved "https://registry.yarnpkg.com/glob-parent/-/glob-parent-5.1.2.tgz#869832c58034fe68a4093c17dc15e8340d8401c4" + integrity sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow== + dependencies: + is-glob "^4.0.1" + +glob-parent@^6.0.2: + version "6.0.2" + resolved "https://registry.yarnpkg.com/glob-parent/-/glob-parent-6.0.2.tgz#6d237d99083950c79290f24c7642a3de9a28f9e3" + integrity sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A== + dependencies: + is-glob "^4.0.3" + +glob@^7.1.1, glob@^7.1.2, glob@^7.1.3, glob@^7.1.4: + version "7.2.3" + resolved "https://registry.yarnpkg.com/glob/-/glob-7.2.3.tgz#b8df0fb802bbfa8e89bd1d938b4e16578ed44f2b" + integrity sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q== + dependencies: + fs.realpath "^1.0.0" + inflight "^1.0.4" + inherits "2" + minimatch "^3.1.1" + once "^1.3.0" + path-is-absolute "^1.0.0" + +globals@^11.1.0: + version "11.12.0" + resolved "https://registry.yarnpkg.com/globals/-/globals-11.12.0.tgz#ab8795338868a0babd8525758018c2a7eb95c42e" + integrity sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA== + +globals@^13.19.0, globals@^13.23.0: + version "13.23.0" + resolved "https://registry.yarnpkg.com/globals/-/globals-13.23.0.tgz#ef31673c926a0976e1f61dab4dca57e0c0a8af02" + integrity sha512-XAmF0RjlrjY23MA51q3HltdlGxUpXPvg0GioKiD9X6HD28iMjo2dKC8Vqwm7lne4GNr78+RHTfliktR6ZH09wA== + dependencies: + type-fest "^0.20.2" + +globalthis@^1.0.3: + version "1.0.3" + resolved "https://registry.yarnpkg.com/globalthis/-/globalthis-1.0.3.tgz#5852882a52b80dc301b0660273e1ed082f0b6ccf" + integrity sha512-sFdI5LyBiNTHjRd7cGPWapiHWMOXKyuBNX/cWJ3NfzrZQVa8GI/8cofCl74AOVqq9W5kNmguTIzJ/1s2gyI9wA== + dependencies: + define-properties "^1.1.3" + +globby@^11.1.0: + version "11.1.0" + resolved "https://registry.yarnpkg.com/globby/-/globby-11.1.0.tgz#bd4be98bb042f83d796f7e3811991fbe82a0d34b" + integrity sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g== + dependencies: + array-union "^2.1.0" + dir-glob "^3.0.1" + fast-glob "^3.2.9" + ignore "^5.2.0" + merge2 "^1.4.1" + slash "^3.0.0" + +gopd@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/gopd/-/gopd-1.0.1.tgz#29ff76de69dac7489b7c0918a5788e56477c332c" + integrity sha512-d65bNlIadxvpb/A2abVdlqKqV563juRnZ1Wtk6s1sIR8uNsXR70xqIzVqxVf1eTqDunwT2MkczEeaezCKTZhwA== + dependencies: + get-intrinsic "^1.1.3" + +graceful-fs@^4.2.9: + version "4.2.11" + resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.11.tgz#4183e4e8bf08bb6e05bbb2f7d2e0c8f712ca40e3" + integrity sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ== + +graphemer@^1.4.0: + version "1.4.0" + resolved "https://registry.yarnpkg.com/graphemer/-/graphemer-1.4.0.tgz#fb2f1d55e0e3a1849aeffc90c4fa0dd53a0e66c6" + integrity sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag== + +has-bigints@^1.0.1, has-bigints@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/has-bigints/-/has-bigints-1.0.2.tgz#0871bd3e3d51626f6ca0966668ba35d5602d6eaa" + integrity sha512-tSvCKtBr9lkF0Ex0aQiP9N+OpV4zi2r/Nee5VkRDbaqv35RLYMzbwQfFSZZH0kR+Rd6302UJZ2p/bJCEoR3VoQ== + +has-flag@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-3.0.0.tgz#b5d454dc2199ae225699f3467e5a07f3b955bafd" + integrity sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw== + +has-flag@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-4.0.0.tgz#944771fd9c81c81265c4d6941860da06bb59479b" + integrity sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ== + +has-property-descriptors@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/has-property-descriptors/-/has-property-descriptors-1.0.1.tgz#52ba30b6c5ec87fd89fa574bc1c39125c6f65340" + integrity sha512-VsX8eaIewvas0xnvinAe9bw4WfIeODpGYikiWYLH+dma0Jw6KHYqWiWfhQlgOVK8D6PvjubK5Uc4P0iIhIcNVg== + dependencies: + get-intrinsic "^1.2.2" + +has-proto@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/has-proto/-/has-proto-1.0.1.tgz#1885c1305538958aff469fef37937c22795408e0" + integrity sha512-7qE+iP+O+bgF9clE5+UoBFzE65mlBiVj3tKCrlNQ0Ogwm0BjpT/gK4SlLYDMybDh5I3TCTKnPPa0oMG7JDYrhg== + +has-symbols@^1.0.2, has-symbols@^1.0.3: + version "1.0.3" + resolved "https://registry.yarnpkg.com/has-symbols/-/has-symbols-1.0.3.tgz#bb7b2c4349251dce87b125f7bdf874aa7c8b39f8" + integrity sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A== + +has-tostringtag@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/has-tostringtag/-/has-tostringtag-1.0.0.tgz#7e133818a7d394734f941e73c3d3f9291e658b25" + integrity sha512-kFjcSNhnlGV1kyoGk7OXKSawH5JOb/LzUc5w9B02hOTO0dfFRjbHQKvg1d6cf3HbeUmtU9VbbV3qzZ2Teh97WQ== + dependencies: + has-symbols "^1.0.2" + +hasown@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/hasown/-/hasown-2.0.0.tgz#f4c513d454a57b7c7e1650778de226b11700546c" + integrity sha512-vUptKVTpIJhcczKBbgnS+RtcuYMB8+oNzPK2/Hp3hanz8JmpATdmmgLgSaadVREkDm+e2giHwY3ZRkyjSIDDFA== + dependencies: + function-bind "^1.1.2" + +he@~1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/he/-/he-1.2.0.tgz#84ae65fa7eafb165fddb61566ae14baf05664f0f" + integrity sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw== + +html-encoding-sniffer@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/html-encoding-sniffer/-/html-encoding-sniffer-2.0.1.tgz#42a6dc4fd33f00281176e8b23759ca4e4fa185f3" + integrity sha512-D5JbOMBIR/TVZkubHT+OyT2705QvogUW4IBn6nHd756OwieSF9aDYFj4dv6HHEVGYbHaLETa3WggZYWWMyy3ZQ== + dependencies: + whatwg-encoding "^1.0.5" + +html-escaper@^2.0.0: + version "2.0.2" + resolved "https://registry.yarnpkg.com/html-escaper/-/html-escaper-2.0.2.tgz#dfd60027da36a36dfcbe236262c00a5822681453" + integrity sha512-H2iMtd0I4Mt5eYiapRdIDjp+XzelXQ0tFE4JS7YFwFevXXMmOp9myNrUvCg0D6ws8iqkRPBfKHgbwig1SmlLfg== + +http-proxy-agent@^4.0.1: + version "4.0.1" + resolved "https://registry.yarnpkg.com/http-proxy-agent/-/http-proxy-agent-4.0.1.tgz#8a8c8ef7f5932ccf953c296ca8291b95aa74aa3a" + integrity sha512-k0zdNgqWTGA6aeIRVpvfVob4fL52dTfaehylg0Y4UvSySvOq/Y+BOyPrgpUrA7HylqvU8vIZGsRuXmspskV0Tg== + dependencies: + "@tootallnate/once" "1" + agent-base "6" + debug "4" + +https-proxy-agent@^5.0.0: + version "5.0.1" + resolved "https://registry.yarnpkg.com/https-proxy-agent/-/https-proxy-agent-5.0.1.tgz#c59ef224a04fe8b754f3db0063a25ea30d0005d6" + integrity sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA== + dependencies: + agent-base "6" + debug "4" + +human-signals@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/human-signals/-/human-signals-2.1.0.tgz#dc91fcba42e4d06e4abaed33b3e7a3c02f514ea0" + integrity sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw== + +husky@^8.0.3: + version "8.0.3" + resolved "https://registry.yarnpkg.com/husky/-/husky-8.0.3.tgz#4936d7212e46d1dea28fef29bb3a108872cd9184" + integrity sha512-+dQSyqPh4x1hlO1swXBiNb2HzTDN1I2IGLQx1GrBuiqFJfoMrnZWwVmatvSiO+Iz8fBUnf+lekwNo4c2LlXItg== + +iconv-lite@0.4.24: + version "0.4.24" + resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.4.24.tgz#2022b4b25fbddc21d2f524974a474aafe733908b" + integrity sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA== + dependencies: + safer-buffer ">= 2.1.2 < 3" + +ignore@^5.2.0: + version "5.3.0" + resolved "https://registry.yarnpkg.com/ignore/-/ignore-5.3.0.tgz#67418ae40d34d6999c95ff56016759c718c82f78" + integrity sha512-g7dmpshy+gD7mh88OC9NwSGTKoc3kyLAZQRU1mt53Aw/vnvfXnbC+F/7F7QoYVKbV+KNvJx8wArewKy1vXMtlg== + +import-fresh@^3.2.1: + version "3.3.0" + resolved "https://registry.yarnpkg.com/import-fresh/-/import-fresh-3.3.0.tgz#37162c25fcb9ebaa2e6e53d5b4d88ce17d9e0c2b" + integrity sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw== + dependencies: + parent-module "^1.0.0" + resolve-from "^4.0.0" + +import-local@^3.0.2: + version "3.1.0" + resolved "https://registry.yarnpkg.com/import-local/-/import-local-3.1.0.tgz#b4479df8a5fd44f6cdce24070675676063c95cb4" + integrity sha512-ASB07uLtnDs1o6EHjKpX34BKYDSqnFerfTOJL2HvMqF70LnxpjkzDB8J44oT9pu4AMPkQwf8jl6szgvNd2tRIg== + dependencies: + pkg-dir "^4.2.0" + resolve-cwd "^3.0.0" + +imurmurhash@^0.1.4: + version "0.1.4" + resolved "https://registry.yarnpkg.com/imurmurhash/-/imurmurhash-0.1.4.tgz#9218b9b2b928a238b13dc4fb6b6d576f231453ea" + integrity sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA== + +indent-string@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/indent-string/-/indent-string-4.0.0.tgz#624f8f4497d619b2d9768531d58f4122854d7251" + integrity sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg== + +inflight@^1.0.4: + version "1.0.6" + resolved "https://registry.yarnpkg.com/inflight/-/inflight-1.0.6.tgz#49bd6331d7d02d0c09bc910a1075ba8165b56df9" + integrity sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA== + dependencies: + once "^1.3.0" + wrappy "1" + +inherits@2: + version "2.0.4" + resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.4.tgz#0fa2c64f932917c3433a0ded55363aae37416b7c" + integrity sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ== + +internal-slot@^1.0.5: + version "1.0.6" + resolved "https://registry.yarnpkg.com/internal-slot/-/internal-slot-1.0.6.tgz#37e756098c4911c5e912b8edbf71ed3aa116f930" + integrity sha512-Xj6dv+PsbtwyPpEflsejS+oIZxmMlV44zAhG479uYu89MsjcYOhCFnNyKrkJrihbsiasQyY0afoCl/9BLR65bg== + dependencies: + get-intrinsic "^1.2.2" + hasown "^2.0.0" + side-channel "^1.0.4" + +is-array-buffer@^3.0.1, is-array-buffer@^3.0.2: + version "3.0.2" + resolved "https://registry.yarnpkg.com/is-array-buffer/-/is-array-buffer-3.0.2.tgz#f2653ced8412081638ecb0ebbd0c41c6e0aecbbe" + integrity sha512-y+FyyR/w8vfIRq4eQcM1EYgSTnmHXPqaF+IgzgraytCFq5Xh8lllDVmAZolPJiZttZLeFSINPYMaEJ7/vWUa1w== + dependencies: + call-bind "^1.0.2" + get-intrinsic "^1.2.0" + is-typed-array "^1.1.10" + +is-arrayish@^0.2.1: + version "0.2.1" + resolved "https://registry.yarnpkg.com/is-arrayish/-/is-arrayish-0.2.1.tgz#77c99840527aa8ecb1a8ba697b80645a7a926a9d" + integrity sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg== + +is-bigint@^1.0.1: + version "1.0.4" + resolved "https://registry.yarnpkg.com/is-bigint/-/is-bigint-1.0.4.tgz#08147a1875bc2b32005d41ccd8291dffc6691df3" + integrity sha512-zB9CruMamjym81i2JZ3UMn54PKGsQzsJeo6xvN3HJJ4CAsQNB6iRutp2To77OfCNuoxspsIhzaPoO1zyCEhFOg== + dependencies: + has-bigints "^1.0.1" + +is-boolean-object@^1.1.0: + version "1.1.2" + resolved "https://registry.yarnpkg.com/is-boolean-object/-/is-boolean-object-1.1.2.tgz#5c6dc200246dd9321ae4b885a114bb1f75f63719" + integrity sha512-gDYaKHJmnj4aWxyj6YHyXVpdQawtVLHU5cb+eztPGczf6cjuTdwve5ZIEfgXqH4e57An1D1AKf8CZ3kYrQRqYA== + dependencies: + call-bind "^1.0.2" + has-tostringtag "^1.0.0" + +is-callable@^1.1.3, is-callable@^1.1.4, is-callable@^1.2.7: + version "1.2.7" + resolved "https://registry.yarnpkg.com/is-callable/-/is-callable-1.2.7.tgz#3bc2a85ea742d9e36205dcacdd72ca1fdc51b055" + integrity sha512-1BC0BVFhS/p0qtw6enp8e+8OD0UrK0oFLztSjNzhcKA3WDuJxxAPXzPuPtKkjEY9UUoEWlX/8fgKeu2S8i9JTA== + +is-core-module@^2.13.0, is-core-module@^2.13.1: + version "2.13.1" + resolved "https://registry.yarnpkg.com/is-core-module/-/is-core-module-2.13.1.tgz#ad0d7532c6fea9da1ebdc82742d74525c6273384" + integrity sha512-hHrIjvZsftOsvKSn2TRYl63zvxsgE0K+0mYMoH6gD4omR5IWB2KynivBQczo3+wF1cCkjzvptnI9Q0sPU66ilw== + dependencies: + hasown "^2.0.0" + +is-date-object@^1.0.1: + version "1.0.5" + resolved "https://registry.yarnpkg.com/is-date-object/-/is-date-object-1.0.5.tgz#0841d5536e724c25597bf6ea62e1bd38298df31f" + integrity sha512-9YQaSxsAiSwcvS33MBk3wTCVnWK+HhF8VZR2jRxehM16QcVOdHqPn4VPHmRK4lSr38n9JriurInLcP90xsYNfQ== + dependencies: + has-tostringtag "^1.0.0" + +is-extglob@^2.1.1: + version "2.1.1" + resolved "https://registry.yarnpkg.com/is-extglob/-/is-extglob-2.1.1.tgz#a88c02535791f02ed37c76a1b9ea9773c833f8c2" + integrity sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ== + +is-fullwidth-code-point@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz#f116f8064fe90b3f7844a38997c0b75051269f1d" + integrity sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg== + +is-fullwidth-code-point@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-4.0.0.tgz#fae3167c729e7463f8461ce512b080a49268aa88" + integrity sha512-O4L094N2/dZ7xqVdrXhh9r1KODPJpFms8B5sGdJLPy664AgvXsreZUyCQQNItZRDlYug4xStLjNp/sz3HvBowQ== + +is-generator-fn@^2.0.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/is-generator-fn/-/is-generator-fn-2.1.0.tgz#7d140adc389aaf3011a8f2a2a4cfa6faadffb118" + integrity sha512-cTIB4yPYL/Grw0EaSzASzg6bBy9gqCofvWN8okThAYIxKJZC+udlRAmGbM0XLeniEJSs8uEgHPGuHSe1XsOLSQ== + +is-glob@^4.0.0, is-glob@^4.0.1, is-glob@^4.0.3: + version "4.0.3" + resolved "https://registry.yarnpkg.com/is-glob/-/is-glob-4.0.3.tgz#64f61e42cbbb2eec2071a9dac0b28ba1e65d5084" + integrity sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg== + dependencies: + is-extglob "^2.1.1" + +is-negative-zero@^2.0.2: + version "2.0.2" + resolved "https://registry.yarnpkg.com/is-negative-zero/-/is-negative-zero-2.0.2.tgz#7bf6f03a28003b8b3965de3ac26f664d765f3150" + integrity sha512-dqJvarLawXsFbNDeJW7zAz8ItJ9cd28YufuuFzh0G8pNHjJMnY08Dv7sYX2uF5UpQOwieAeOExEYAWWfu7ZZUA== + +is-number-object@^1.0.4: + version "1.0.7" + resolved "https://registry.yarnpkg.com/is-number-object/-/is-number-object-1.0.7.tgz#59d50ada4c45251784e9904f5246c742f07a42fc" + integrity sha512-k1U0IRzLMo7ZlYIfzRu23Oh6MiIFasgpb9X76eqfFZAqwH44UI4KTBvBYIZ1dSL9ZzChTB9ShHfLkR4pdW5krQ== + dependencies: + has-tostringtag "^1.0.0" + +is-number@^7.0.0: + version "7.0.0" + resolved "https://registry.yarnpkg.com/is-number/-/is-number-7.0.0.tgz#7535345b896734d5f80c4d06c50955527a14f12b" + integrity sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng== + +is-path-inside@^3.0.3: + version "3.0.3" + resolved "https://registry.yarnpkg.com/is-path-inside/-/is-path-inside-3.0.3.tgz#d231362e53a07ff2b0e0ea7fed049161ffd16283" + integrity sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ== + +is-potential-custom-element-name@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/is-potential-custom-element-name/-/is-potential-custom-element-name-1.0.1.tgz#171ed6f19e3ac554394edf78caa05784a45bebb5" + integrity sha512-bCYeRA2rVibKZd+s2625gGnGF/t7DSqDs4dP7CrLA1m7jKWz6pps0LpYLJN8Q64HtmPKJ1hrN3nzPNKFEKOUiQ== + +is-regex@^1.1.4: + version "1.1.4" + resolved "https://registry.yarnpkg.com/is-regex/-/is-regex-1.1.4.tgz#eef5663cd59fa4c0ae339505323df6854bb15958" + integrity sha512-kvRdxDsxZjhzUX07ZnLydzS1TU/TJlTUHHY4YLL87e37oUA49DfkLqgy+VjFocowy29cKvcSiu+kIv728jTTVg== + dependencies: + call-bind "^1.0.2" + has-tostringtag "^1.0.0" + +is-shared-array-buffer@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/is-shared-array-buffer/-/is-shared-array-buffer-1.0.2.tgz#8f259c573b60b6a32d4058a1a07430c0a7344c79" + integrity sha512-sqN2UDu1/0y6uvXyStCOzyhAjCSlHceFoMKJW8W9EU9cvic/QdsZ0kEU93HEy3IUEFZIiH/3w+AH/UQbPHNdhA== + dependencies: + call-bind "^1.0.2" + +is-stream@^2.0.0: + version "2.0.1" + resolved "https://registry.yarnpkg.com/is-stream/-/is-stream-2.0.1.tgz#fac1e3d53b97ad5a9d0ae9cef2389f5810a5c077" + integrity sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg== + +is-string@^1.0.5, is-string@^1.0.7: + version "1.0.7" + resolved "https://registry.yarnpkg.com/is-string/-/is-string-1.0.7.tgz#0dd12bf2006f255bb58f695110eff7491eebc0fd" + integrity sha512-tE2UXzivje6ofPW7l23cjDOMa09gb7xlAqG6jG5ej6uPV32TlWP3NKPigtaGeHNu9fohccRYvIiZMfOOnOYUtg== + dependencies: + has-tostringtag "^1.0.0" + +is-symbol@^1.0.2, is-symbol@^1.0.3: + version "1.0.4" + resolved "https://registry.yarnpkg.com/is-symbol/-/is-symbol-1.0.4.tgz#a6dac93b635b063ca6872236de88910a57af139c" + integrity sha512-C/CPBqKWnvdcxqIARxyOh4v1UUEOCHpgDa0WYgpKDFMszcrPcffg5uhwSgPCLD2WWxmq6isisz87tzT01tuGhg== + dependencies: + has-symbols "^1.0.2" + +is-typed-array@^1.1.10, is-typed-array@^1.1.12, is-typed-array@^1.1.9: + version "1.1.12" + resolved "https://registry.yarnpkg.com/is-typed-array/-/is-typed-array-1.1.12.tgz#d0bab5686ef4a76f7a73097b95470ab199c57d4a" + integrity sha512-Z14TF2JNG8Lss5/HMqt0//T9JeHXttXy5pH/DBU4vi98ozO2btxzq9MwYDZYnKwU8nRsz/+GVFVRDq3DkVuSPg== + dependencies: + which-typed-array "^1.1.11" + +is-typedarray@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/is-typedarray/-/is-typedarray-1.0.0.tgz#e479c80858df0c1b11ddda6940f96011fcda4a9a" + integrity sha512-cyA56iCMHAh5CdzjJIa4aohJyeO1YbwLi3Jc35MmRU6poroFjIGZzUzupGiRPOjgHg9TLu43xbpwXk523fMxKA== + +is-weakref@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/is-weakref/-/is-weakref-1.0.2.tgz#9529f383a9338205e89765e0392efc2f100f06f2" + integrity sha512-qctsuLZmIQ0+vSSMfoVvyFe2+GSEvnmZ2ezTup1SBse9+twCCeial6EEi3Nc2KFcf6+qz2FBPnjXsk8xhKSaPQ== + dependencies: + call-bind "^1.0.2" + +isarray@1.0.0, isarray@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/isarray/-/isarray-1.0.0.tgz#bb935d48582cba168c06834957a54a3e07124f11" + integrity sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ== + +isarray@^2.0.5: + version "2.0.5" + resolved "https://registry.yarnpkg.com/isarray/-/isarray-2.0.5.tgz#8af1e4c1221244cc62459faf38940d4e644a5723" + integrity sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw== + +isexe@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/isexe/-/isexe-2.0.0.tgz#e8fbf374dc556ff8947a10dcb0572d633f2cfa10" + integrity sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw== + +isobject@^2.0.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/isobject/-/isobject-2.1.0.tgz#f065561096a3f1da2ef46272f815c840d87e0c89" + integrity sha512-+OUdGJlgjOBZDfxnDjYYG6zp487z0JGNQq3cYQYg5f5hKR+syHMsaztzGeml/4kGG55CSpKSpWTY+jYGgsHLgA== + dependencies: + isarray "1.0.0" + +istanbul-lib-coverage@^3.0.0, istanbul-lib-coverage@^3.2.0: + version "3.2.2" + resolved "https://registry.yarnpkg.com/istanbul-lib-coverage/-/istanbul-lib-coverage-3.2.2.tgz#2d166c4b0644d43a39f04bf6c2edd1e585f31756" + integrity sha512-O8dpsF+r0WV/8MNRKfnmrtCWhuKjxrq2w+jpzBL5UZKTi2LeVWnWOmWRxFlesJONmc+wLAGvKQZEOanko0LFTg== + +istanbul-lib-instrument@^5.0.4, istanbul-lib-instrument@^5.1.0: + version "5.2.1" + resolved "https://registry.yarnpkg.com/istanbul-lib-instrument/-/istanbul-lib-instrument-5.2.1.tgz#d10c8885c2125574e1c231cacadf955675e1ce3d" + integrity sha512-pzqtp31nLv/XFOzXGuvhCb8qhjmTVo5vjVk19XE4CRlSWz0KoeJ3bw9XsA7nOp9YBf4qHjwBxkDzKcME/J29Yg== + dependencies: + "@babel/core" "^7.12.3" + "@babel/parser" "^7.14.7" + "@istanbuljs/schema" "^0.1.2" + istanbul-lib-coverage "^3.2.0" + semver "^6.3.0" + +istanbul-lib-report@^3.0.0: + version "3.0.1" + resolved "https://registry.yarnpkg.com/istanbul-lib-report/-/istanbul-lib-report-3.0.1.tgz#908305bac9a5bd175ac6a74489eafd0fc2445a7d" + integrity sha512-GCfE1mtsHGOELCU8e/Z7YWzpmybrx/+dSTfLrvY8qRmaY6zXTKWn6WQIjaAFw069icm6GVMNkgu0NzI4iPZUNw== + dependencies: + istanbul-lib-coverage "^3.0.0" + make-dir "^4.0.0" + supports-color "^7.1.0" + +istanbul-lib-source-maps@^4.0.0: + version "4.0.1" + resolved "https://registry.yarnpkg.com/istanbul-lib-source-maps/-/istanbul-lib-source-maps-4.0.1.tgz#895f3a709fcfba34c6de5a42939022f3e4358551" + integrity sha512-n3s8EwkdFIJCG3BPKBYvskgXGoy88ARzvegkitk60NxRdwltLOTaH7CUiMRXvwYorl0Q712iEjcWB+fK/MrWVw== + dependencies: + debug "^4.1.1" + istanbul-lib-coverage "^3.0.0" + source-map "^0.6.1" + +istanbul-reports@^3.1.3: + version "3.1.6" + resolved "https://registry.yarnpkg.com/istanbul-reports/-/istanbul-reports-3.1.6.tgz#2544bcab4768154281a2f0870471902704ccaa1a" + integrity sha512-TLgnMkKg3iTDsQ9PbPTdpfAK2DzjF9mqUG7RMgcQl8oFjad8ob4laGxv5XV5U9MAfx8D6tSJiUyuAwzLicaxlg== + dependencies: + html-escaper "^2.0.0" + istanbul-lib-report "^3.0.0" + +jest-changed-files@^27.5.1: + version "27.5.1" + resolved "https://registry.yarnpkg.com/jest-changed-files/-/jest-changed-files-27.5.1.tgz#a348aed00ec9bf671cc58a66fcbe7c3dfd6a68f5" + integrity sha512-buBLMiByfWGCoMsLLzGUUSpAmIAGnbR2KJoMN10ziLhOLvP4e0SlypHnAel8iqQXTrcbmfEY9sSqae5sgUsTvw== + dependencies: + "@jest/types" "^27.5.1" + execa "^5.0.0" + throat "^6.0.1" + +jest-circus@^27.5.1: + version "27.5.1" + resolved "https://registry.yarnpkg.com/jest-circus/-/jest-circus-27.5.1.tgz#37a5a4459b7bf4406e53d637b49d22c65d125ecc" + integrity sha512-D95R7x5UtlMA5iBYsOHFFbMD/GVA4R/Kdq15f7xYWUfWHBto9NYRsOvnSauTgdF+ogCpJ4tyKOXhUifxS65gdw== + dependencies: + "@jest/environment" "^27.5.1" + "@jest/test-result" "^27.5.1" + "@jest/types" "^27.5.1" + "@types/node" "*" + chalk "^4.0.0" + co "^4.6.0" + dedent "^0.7.0" + expect "^27.5.1" + is-generator-fn "^2.0.0" + jest-each "^27.5.1" + jest-matcher-utils "^27.5.1" + jest-message-util "^27.5.1" + jest-runtime "^27.5.1" + jest-snapshot "^27.5.1" + jest-util "^27.5.1" + pretty-format "^27.5.1" + slash "^3.0.0" + stack-utils "^2.0.3" + throat "^6.0.1" + +jest-cli@^27.4.7: + version "27.5.1" + resolved "https://registry.yarnpkg.com/jest-cli/-/jest-cli-27.5.1.tgz#278794a6e6458ea8029547e6c6cbf673bd30b145" + integrity sha512-Hc6HOOwYq4/74/c62dEE3r5elx8wjYqxY0r0G/nFrLDPMFRu6RA/u8qINOIkvhxG7mMQ5EJsOGfRpI8L6eFUVw== + dependencies: + "@jest/core" "^27.5.1" + "@jest/test-result" "^27.5.1" + "@jest/types" "^27.5.1" + chalk "^4.0.0" + exit "^0.1.2" + graceful-fs "^4.2.9" + import-local "^3.0.2" + jest-config "^27.5.1" + jest-util "^27.5.1" + jest-validate "^27.5.1" + prompts "^2.0.1" + yargs "^16.2.0" + +jest-config@^27.5.1: + version "27.5.1" + resolved "https://registry.yarnpkg.com/jest-config/-/jest-config-27.5.1.tgz#5c387de33dca3f99ad6357ddeccd91bf3a0e4a41" + integrity sha512-5sAsjm6tGdsVbW9ahcChPAFCk4IlkQUknH5AvKjuLTSlcO/wCZKyFdn7Rg0EkC+OGgWODEy2hDpWB1PgzH0JNA== + dependencies: + "@babel/core" "^7.8.0" + "@jest/test-sequencer" "^27.5.1" + "@jest/types" "^27.5.1" + babel-jest "^27.5.1" + chalk "^4.0.0" + ci-info "^3.2.0" + deepmerge "^4.2.2" + glob "^7.1.1" + graceful-fs "^4.2.9" + jest-circus "^27.5.1" + jest-environment-jsdom "^27.5.1" + jest-environment-node "^27.5.1" + jest-get-type "^27.5.1" + jest-jasmine2 "^27.5.1" + jest-regex-util "^27.5.1" + jest-resolve "^27.5.1" + jest-runner "^27.5.1" + jest-util "^27.5.1" + jest-validate "^27.5.1" + micromatch "^4.0.4" + parse-json "^5.2.0" + pretty-format "^27.5.1" + slash "^3.0.0" + strip-json-comments "^3.1.1" + +jest-diff@^27.5.1: + version "27.5.1" + resolved "https://registry.yarnpkg.com/jest-diff/-/jest-diff-27.5.1.tgz#a07f5011ac9e6643cf8a95a462b7b1ecf6680def" + integrity sha512-m0NvkX55LDt9T4mctTEgnZk3fmEg3NRYutvMPWM/0iPnkFj2wIeF45O1718cMSOFO1vINkqmxqD8vE37uTEbqw== + dependencies: + chalk "^4.0.0" + diff-sequences "^27.5.1" + jest-get-type "^27.5.1" + pretty-format "^27.5.1" + +jest-docblock@^27.5.1: + version "27.5.1" + resolved "https://registry.yarnpkg.com/jest-docblock/-/jest-docblock-27.5.1.tgz#14092f364a42c6108d42c33c8cf30e058e25f6c0" + integrity sha512-rl7hlABeTsRYxKiUfpHrQrG4e2obOiTQWfMEH3PxPjOtdsfLQO4ReWSZaQ7DETm4xu07rl4q/h4zcKXyU0/OzQ== + dependencies: + detect-newline "^3.0.0" + +jest-docblock@^29.0.0: + version "29.7.0" + resolved "https://registry.yarnpkg.com/jest-docblock/-/jest-docblock-29.7.0.tgz#8fddb6adc3cdc955c93e2a87f61cfd350d5d119a" + integrity sha512-q617Auw3A612guyaFgsbFeYpNP5t2aoUNLwBUbc/0kD1R4t9ixDbyFTHd1nok4epoVFpr7PmeWHrhvuV3XaJ4g== + dependencies: + detect-newline "^3.0.0" + +jest-each@^27.5.1: + version "27.5.1" + resolved "https://registry.yarnpkg.com/jest-each/-/jest-each-27.5.1.tgz#5bc87016f45ed9507fed6e4702a5b468a5b2c44e" + integrity sha512-1Ff6p+FbhT/bXQnEouYy00bkNSY7OUpfIcmdl8vZ31A1UUaurOLPA8a8BbJOF2RDUElwJhmeaV7LnagI+5UwNQ== + dependencies: + "@jest/types" "^27.5.1" + chalk "^4.0.0" + jest-get-type "^27.5.1" + jest-util "^27.5.1" + pretty-format "^27.5.1" + +jest-environment-jsdom@^27.5.1: + version "27.5.1" + resolved "https://registry.yarnpkg.com/jest-environment-jsdom/-/jest-environment-jsdom-27.5.1.tgz#ea9ccd1fc610209655a77898f86b2b559516a546" + integrity sha512-TFBvkTC1Hnnnrka/fUb56atfDtJ9VMZ94JkjTbggl1PEpwrYtUBKMezB3inLmWqQsXYLcMwNoDQwoBTAvFfsfw== + dependencies: + "@jest/environment" "^27.5.1" + "@jest/fake-timers" "^27.5.1" + "@jest/types" "^27.5.1" + "@types/node" "*" + jest-mock "^27.5.1" + jest-util "^27.5.1" + jsdom "^16.6.0" + +jest-environment-node@^27.5.1: + version "27.5.1" + resolved "https://registry.yarnpkg.com/jest-environment-node/-/jest-environment-node-27.5.1.tgz#dedc2cfe52fab6b8f5714b4808aefa85357a365e" + integrity sha512-Jt4ZUnxdOsTGwSRAfKEnE6BcwsSPNOijjwifq5sDFSA2kesnXTvNqKHYgM0hDq3549Uf/KzdXNYn4wMZJPlFLw== + dependencies: + "@jest/environment" "^27.5.1" + "@jest/fake-timers" "^27.5.1" + "@jest/types" "^27.5.1" + "@types/node" "*" + jest-mock "^27.5.1" + jest-util "^27.5.1" + +jest-get-type@^27.5.1: + version "27.5.1" + resolved "https://registry.yarnpkg.com/jest-get-type/-/jest-get-type-27.5.1.tgz#3cd613c507b0f7ace013df407a1c1cd578bcb4f1" + integrity sha512-2KY95ksYSaK7DMBWQn6dQz3kqAf3BB64y2udeG+hv4KfSOb9qwcYQstTJc1KCbsix+wLZWZYN8t7nwX3GOBLRw== + +jest-haste-map@^27.5.1: + version "27.5.1" + resolved "https://registry.yarnpkg.com/jest-haste-map/-/jest-haste-map-27.5.1.tgz#9fd8bd7e7b4fa502d9c6164c5640512b4e811e7f" + integrity sha512-7GgkZ4Fw4NFbMSDSpZwXeBiIbx+t/46nJ2QitkOjvwPYyZmqttu2TDSimMHP1EkPOi4xUZAN1doE5Vd25H4Jng== + dependencies: + "@jest/types" "^27.5.1" + "@types/graceful-fs" "^4.1.2" + "@types/node" "*" + anymatch "^3.0.3" + fb-watchman "^2.0.0" + graceful-fs "^4.2.9" + jest-regex-util "^27.5.1" + jest-serializer "^27.5.1" + jest-util "^27.5.1" + jest-worker "^27.5.1" + micromatch "^4.0.4" + walker "^1.0.7" + optionalDependencies: + fsevents "^2.3.2" + +jest-jasmine2@^27.5.1: + version "27.5.1" + resolved "https://registry.yarnpkg.com/jest-jasmine2/-/jest-jasmine2-27.5.1.tgz#a037b0034ef49a9f3d71c4375a796f3b230d1ac4" + integrity sha512-jtq7VVyG8SqAorDpApwiJJImd0V2wv1xzdheGHRGyuT7gZm6gG47QEskOlzsN1PG/6WNaCo5pmwMHDf3AkG2pQ== + dependencies: + "@jest/environment" "^27.5.1" + "@jest/source-map" "^27.5.1" + "@jest/test-result" "^27.5.1" + "@jest/types" "^27.5.1" + "@types/node" "*" + chalk "^4.0.0" + co "^4.6.0" + expect "^27.5.1" + is-generator-fn "^2.0.0" + jest-each "^27.5.1" + jest-matcher-utils "^27.5.1" + jest-message-util "^27.5.1" + jest-runtime "^27.5.1" + jest-snapshot "^27.5.1" + jest-util "^27.5.1" + pretty-format "^27.5.1" + throat "^6.0.1" + +jest-leak-detector@^27.5.1: + version "27.5.1" + resolved "https://registry.yarnpkg.com/jest-leak-detector/-/jest-leak-detector-27.5.1.tgz#6ec9d54c3579dd6e3e66d70e3498adf80fde3fb8" + integrity sha512-POXfWAMvfU6WMUXftV4HolnJfnPOGEu10fscNCA76KBpRRhcMN2c8d3iT2pxQS3HLbA+5X4sOUPzYO2NUyIlHQ== + dependencies: + jest-get-type "^27.5.1" + pretty-format "^27.5.1" + +jest-matcher-utils@^27.5.1: + version "27.5.1" + resolved "https://registry.yarnpkg.com/jest-matcher-utils/-/jest-matcher-utils-27.5.1.tgz#9c0cdbda8245bc22d2331729d1091308b40cf8ab" + integrity sha512-z2uTx/T6LBaCoNWNFWwChLBKYxTMcGBRjAt+2SbP929/Fflb9aa5LGma654Rz8z9HLxsrUaYzxE9T/EFIL/PAw== + dependencies: + chalk "^4.0.0" + jest-diff "^27.5.1" + jest-get-type "^27.5.1" + pretty-format "^27.5.1" + +jest-message-util@^27.5.1: + version "27.5.1" + resolved "https://registry.yarnpkg.com/jest-message-util/-/jest-message-util-27.5.1.tgz#bdda72806da10d9ed6425e12afff38cd1458b6cf" + integrity sha512-rMyFe1+jnyAAf+NHwTclDz0eAaLkVDdKVHHBFWsBWHnnh5YeJMNWWsv7AbFYXfK3oTqvL7VTWkhNLu1jX24D+g== + dependencies: + "@babel/code-frame" "^7.12.13" + "@jest/types" "^27.5.1" + "@types/stack-utils" "^2.0.0" + chalk "^4.0.0" + graceful-fs "^4.2.9" + micromatch "^4.0.4" + pretty-format "^27.5.1" + slash "^3.0.0" + stack-utils "^2.0.3" + +jest-mock@^27.5.1: + version "27.5.1" + resolved "https://registry.yarnpkg.com/jest-mock/-/jest-mock-27.5.1.tgz#19948336d49ef4d9c52021d34ac7b5f36ff967d6" + integrity sha512-K4jKbY1d4ENhbrG2zuPWaQBvDly+iZ2yAW+T1fATN78hc0sInwn7wZB8XtlNnvHug5RMwV897Xm4LqmPM4e2Og== + dependencies: + "@jest/types" "^27.5.1" + "@types/node" "*" + +jest-pnp-resolver@^1.2.2: + version "1.2.3" + resolved "https://registry.yarnpkg.com/jest-pnp-resolver/-/jest-pnp-resolver-1.2.3.tgz#930b1546164d4ad5937d5540e711d4d38d4cad2e" + integrity sha512-+3NpwQEnRoIBtx4fyhblQDPgJI0H1IEIkX7ShLUjPGA7TtUTvI1oiKi3SR4oBR0hQhQR80l4WAe5RrXBwWMA8w== + +jest-regex-util@^27.5.1: + version "27.5.1" + resolved "https://registry.yarnpkg.com/jest-regex-util/-/jest-regex-util-27.5.1.tgz#4da143f7e9fd1e542d4aa69617b38e4a78365b95" + integrity sha512-4bfKq2zie+x16okqDXjXn9ql2B0dScQu+vcwe4TvFVhkVyuWLqpZrZtXxLLWoXYgn0E87I6r6GRYHF7wFZBUvg== + +jest-resolve-dependencies@^27.5.1: + version "27.5.1" + resolved "https://registry.yarnpkg.com/jest-resolve-dependencies/-/jest-resolve-dependencies-27.5.1.tgz#d811ecc8305e731cc86dd79741ee98fed06f1da8" + integrity sha512-QQOOdY4PE39iawDn5rzbIePNigfe5B9Z91GDD1ae/xNDlu9kaat8QQ5EKnNmVWPV54hUdxCVwwj6YMgR2O7IOg== + dependencies: + "@jest/types" "^27.5.1" + jest-regex-util "^27.5.1" + jest-snapshot "^27.5.1" + +jest-resolve@^27.5.1: + version "27.5.1" + resolved "https://registry.yarnpkg.com/jest-resolve/-/jest-resolve-27.5.1.tgz#a2f1c5a0796ec18fe9eb1536ac3814c23617b384" + integrity sha512-FFDy8/9E6CV83IMbDpcjOhumAQPDyETnU2KZ1O98DwTnz8AOBsW/Xv3GySr1mOZdItLR+zDZ7I/UdTFbgSOVCw== + dependencies: + "@jest/types" "^27.5.1" + chalk "^4.0.0" + graceful-fs "^4.2.9" + jest-haste-map "^27.5.1" + jest-pnp-resolver "^1.2.2" + jest-util "^27.5.1" + jest-validate "^27.5.1" + resolve "^1.20.0" + resolve.exports "^1.1.0" + slash "^3.0.0" + +jest-runner@^27.5.1: + version "27.5.1" + resolved "https://registry.yarnpkg.com/jest-runner/-/jest-runner-27.5.1.tgz#071b27c1fa30d90540805c5645a0ec167c7b62e5" + integrity sha512-g4NPsM4mFCOwFKXO4p/H/kWGdJp9V8kURY2lX8Me2drgXqG7rrZAx5kv+5H7wtt/cdFIjhqYx1HrlqWHaOvDaQ== + dependencies: + "@jest/console" "^27.5.1" + "@jest/environment" "^27.5.1" + "@jest/test-result" "^27.5.1" + "@jest/transform" "^27.5.1" + "@jest/types" "^27.5.1" + "@types/node" "*" + chalk "^4.0.0" + emittery "^0.8.1" + graceful-fs "^4.2.9" + jest-docblock "^27.5.1" + jest-environment-jsdom "^27.5.1" + jest-environment-node "^27.5.1" + jest-haste-map "^27.5.1" + jest-leak-detector "^27.5.1" + jest-message-util "^27.5.1" + jest-resolve "^27.5.1" + jest-runtime "^27.5.1" + jest-util "^27.5.1" + jest-worker "^27.5.1" + source-map-support "^0.5.6" + throat "^6.0.1" + +jest-runtime@^27.5.1: + version "27.5.1" + resolved "https://registry.yarnpkg.com/jest-runtime/-/jest-runtime-27.5.1.tgz#4896003d7a334f7e8e4a53ba93fb9bcd3db0a1af" + integrity sha512-o7gxw3Gf+H2IGt8fv0RiyE1+r83FJBRruoA+FXrlHw6xEyBsU8ugA6IPfTdVyA0w8HClpbK+DGJxH59UrNMx8A== + dependencies: + "@jest/environment" "^27.5.1" + "@jest/fake-timers" "^27.5.1" + "@jest/globals" "^27.5.1" + "@jest/source-map" "^27.5.1" + "@jest/test-result" "^27.5.1" + "@jest/transform" "^27.5.1" + "@jest/types" "^27.5.1" + chalk "^4.0.0" + cjs-module-lexer "^1.0.0" + collect-v8-coverage "^1.0.0" + execa "^5.0.0" + glob "^7.1.3" + graceful-fs "^4.2.9" + jest-haste-map "^27.5.1" + jest-message-util "^27.5.1" + jest-mock "^27.5.1" + jest-regex-util "^27.5.1" + jest-resolve "^27.5.1" + jest-snapshot "^27.5.1" + jest-util "^27.5.1" + slash "^3.0.0" + strip-bom "^4.0.0" + +jest-serializer@^27.5.1: + version "27.5.1" + resolved "https://registry.yarnpkg.com/jest-serializer/-/jest-serializer-27.5.1.tgz#81438410a30ea66fd57ff730835123dea1fb1f64" + integrity sha512-jZCyo6iIxO1aqUxpuBlwTDMkzOAJS4a3eYz3YzgxxVQFwLeSA7Jfq5cbqCY+JLvTDrWirgusI/0KwxKMgrdf7w== + dependencies: + "@types/node" "*" + graceful-fs "^4.2.9" + +jest-snapshot@^27.5.1: + version "27.5.1" + resolved "https://registry.yarnpkg.com/jest-snapshot/-/jest-snapshot-27.5.1.tgz#b668d50d23d38054a51b42c4039cab59ae6eb6a1" + integrity sha512-yYykXI5a0I31xX67mgeLw1DZ0bJB+gpq5IpSuCAoyDi0+BhgU/RIrL+RTzDmkNTchvDFWKP8lp+w/42Z3us5sA== + dependencies: + "@babel/core" "^7.7.2" + "@babel/generator" "^7.7.2" + "@babel/plugin-syntax-typescript" "^7.7.2" + "@babel/traverse" "^7.7.2" + "@babel/types" "^7.0.0" + "@jest/transform" "^27.5.1" + "@jest/types" "^27.5.1" + "@types/babel__traverse" "^7.0.4" + "@types/prettier" "^2.1.5" + babel-preset-current-node-syntax "^1.0.0" + chalk "^4.0.0" + expect "^27.5.1" + graceful-fs "^4.2.9" + jest-diff "^27.5.1" + jest-get-type "^27.5.1" + jest-haste-map "^27.5.1" + jest-matcher-utils "^27.5.1" + jest-message-util "^27.5.1" + jest-util "^27.5.1" + natural-compare "^1.4.0" + pretty-format "^27.5.1" + semver "^7.3.2" + +jest-util@^27.5.1: + version "27.5.1" + resolved "https://registry.yarnpkg.com/jest-util/-/jest-util-27.5.1.tgz#3ba9771e8e31a0b85da48fe0b0891fb86c01c2f9" + integrity sha512-Kv2o/8jNvX1MQ0KGtw480E/w4fBCDOnH6+6DmeKi6LZUIlKA5kwY0YNdlzaWTiVgxqAqik11QyxDOKk543aKXw== + dependencies: + "@jest/types" "^27.5.1" + "@types/node" "*" + chalk "^4.0.0" + ci-info "^3.2.0" + graceful-fs "^4.2.9" + picomatch "^2.2.3" + +jest-validate@^27.5.1: + version "27.5.1" + resolved "https://registry.yarnpkg.com/jest-validate/-/jest-validate-27.5.1.tgz#9197d54dc0bdb52260b8db40b46ae668e04df067" + integrity sha512-thkNli0LYTmOI1tDB3FI1S1RTp/Bqyd9pTarJwL87OIBFuqEb5Apv5EaApEudYg4g86e3CT6kM0RowkhtEnCBQ== + dependencies: + "@jest/types" "^27.5.1" + camelcase "^6.2.0" + chalk "^4.0.0" + jest-get-type "^27.5.1" + leven "^3.1.0" + pretty-format "^27.5.1" + +jest-watcher@^27.5.1: + version "27.5.1" + resolved "https://registry.yarnpkg.com/jest-watcher/-/jest-watcher-27.5.1.tgz#71bd85fb9bde3a2c2ec4dc353437971c43c642a2" + integrity sha512-z676SuD6Z8o8qbmEGhoEUFOM1+jfEiL3DXHK/xgEiG2EyNYfFG60jluWcupY6dATjfEsKQuibReS1djInQnoVw== + dependencies: + "@jest/test-result" "^27.5.1" + "@jest/types" "^27.5.1" + "@types/node" "*" + ansi-escapes "^4.2.1" + chalk "^4.0.0" + jest-util "^27.5.1" + string-length "^4.0.1" + +jest-worker@^27.5.1: + version "27.5.1" + resolved "https://registry.yarnpkg.com/jest-worker/-/jest-worker-27.5.1.tgz#8d146f0900e8973b106b6f73cc1e9a8cb86f8db0" + integrity sha512-7vuh85V5cdDofPyxn58nrPjBktZo0u9x1g8WtjQol+jZDaE+fhN+cIvTj11GndBnMnyfrUOG1sZQxCdjKh+DKg== + dependencies: + "@types/node" "*" + merge-stream "^2.0.0" + supports-color "^8.0.0" + +jest@27.4.7: + version "27.4.7" + resolved "https://registry.yarnpkg.com/jest/-/jest-27.4.7.tgz#87f74b9026a1592f2da05b4d258e57505f28eca4" + integrity sha512-8heYvsx7nV/m8m24Vk26Y87g73Ba6ueUd0MWed/NXMhSZIm62U/llVbS0PJe1SHunbyXjJ/BqG1z9bFjGUIvTg== + dependencies: + "@jest/core" "^27.4.7" + import-local "^3.0.2" + jest-cli "^27.4.7" + +joi@^17.11.0: + version "17.11.0" + resolved "https://registry.yarnpkg.com/joi/-/joi-17.11.0.tgz#aa9da753578ec7720e6f0ca2c7046996ed04fc1a" + integrity sha512-NgB+lZLNoqISVy1rZocE9PZI36bL/77ie924Ri43yEvi9GUUMPeyVIr8KdFTMUlby1p0PBYMk9spIxEUQYqrJQ== + dependencies: + "@hapi/hoek" "^9.0.0" + "@hapi/topo" "^5.0.0" + "@sideway/address" "^4.1.3" + "@sideway/formula" "^3.0.1" + "@sideway/pinpoint" "^2.0.0" + +js-tokens@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-4.0.0.tgz#19203fb59991df98e3a287050d4647cdeaf32499" + integrity sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ== + +js-yaml@^3.13.1: + version "3.14.1" + resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-3.14.1.tgz#dae812fdb3825fa306609a8717383c50c36a0537" + integrity sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g== + dependencies: + argparse "^1.0.7" + esprima "^4.0.0" + +js-yaml@^4.1.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-4.1.0.tgz#c1fb65f8f5017901cdd2c951864ba18458a10602" + integrity sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA== + dependencies: + argparse "^2.0.1" + +jsdom@^16.6.0: + version "16.7.0" + resolved "https://registry.yarnpkg.com/jsdom/-/jsdom-16.7.0.tgz#918ae71965424b197c819f8183a754e18977b710" + integrity sha512-u9Smc2G1USStM+s/x1ru5Sxrl6mPYCbByG1U/hUmqaVsm4tbNyS7CicOSRyuGQYZhTu0h84qkZZQ/I+dzizSVw== + dependencies: + abab "^2.0.5" + acorn "^8.2.4" + acorn-globals "^6.0.0" + cssom "^0.4.4" + cssstyle "^2.3.0" + data-urls "^2.0.0" + decimal.js "^10.2.1" + domexception "^2.0.1" + escodegen "^2.0.0" + form-data "^3.0.0" + html-encoding-sniffer "^2.0.1" + http-proxy-agent "^4.0.1" + https-proxy-agent "^5.0.0" + is-potential-custom-element-name "^1.0.1" + nwsapi "^2.2.0" + parse5 "6.0.1" + saxes "^5.0.1" + symbol-tree "^3.2.4" + tough-cookie "^4.0.0" + w3c-hr-time "^1.0.2" + w3c-xmlserializer "^2.0.0" + webidl-conversions "^6.1.0" + whatwg-encoding "^1.0.5" + whatwg-mimetype "^2.3.0" + whatwg-url "^8.5.0" + ws "^7.4.6" + xml-name-validator "^3.0.0" + +jsesc@^2.5.1: + version "2.5.2" + resolved "https://registry.yarnpkg.com/jsesc/-/jsesc-2.5.2.tgz#80564d2e483dacf6e8ef209650a67df3f0c283a4" + integrity sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA== + +json-buffer@3.0.1: + version "3.0.1" + resolved "https://registry.yarnpkg.com/json-buffer/-/json-buffer-3.0.1.tgz#9338802a30d3b6605fbe0613e094008ca8c05a13" + integrity sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ== + +json-parse-even-better-errors@^2.3.0: + version "2.3.1" + resolved "https://registry.yarnpkg.com/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz#7c47805a94319928e05777405dc12e1f7a4ee02d" + integrity sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w== + +json-schema-traverse@^0.4.1: + version "0.4.1" + resolved "https://registry.yarnpkg.com/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz#69f6a87d9513ab8bb8fe63bdb0979c448e684660" + integrity sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg== + +json-stable-stringify-without-jsonify@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz#9db7b59496ad3f3cfef30a75142d2d930ad72651" + integrity sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw== + +json5@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/json5/-/json5-1.0.2.tgz#63d98d60f21b313b77c4d6da18bfa69d80e1d593" + integrity sha512-g1MWMLBiz8FKi1e4w0UyVL3w+iJceWAFBAaBnnGKOpNa5f8TLktkbre1+s6oICydWAm+HRUGTmI+//xv2hvXYA== + dependencies: + minimist "^1.2.0" + +json5@^2.2.2, json5@^2.2.3: + version "2.2.3" + resolved "https://registry.yarnpkg.com/json5/-/json5-2.2.3.tgz#78cd6f1a19bdc12b73db5ad0c61efd66c1e29283" + integrity sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg== + +keyv@^4.5.3: + version "4.5.4" + resolved "https://registry.yarnpkg.com/keyv/-/keyv-4.5.4.tgz#a879a99e29452f942439f2a405e3af8b31d4de93" + integrity sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw== + dependencies: + json-buffer "3.0.1" + +kleur@^3.0.3: + version "3.0.3" + resolved "https://registry.yarnpkg.com/kleur/-/kleur-3.0.3.tgz#a79c9ecc86ee1ce3fa6206d1216c501f147fc07e" + integrity sha512-eTIzlVOSUR+JxdDFepEYcBMtZ9Qqdef+rnzWdRZuMbOywu5tO2w2N7rqjoANZ5k9vywhL6Br1VRjUIgTQx4E8w== + +leven@^3.1.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/leven/-/leven-3.1.0.tgz#77891de834064cccba82ae7842bb6b14a13ed7f2" + integrity sha512-qsda+H8jTaUaN/x5vzW2rzc+8Rw4TAQ/4KjB46IwK5VH+IlVeeeje/EoZRpiXvIqjFgK84QffqPztGI3VBLG1A== + +levn@^0.4.1: + version "0.4.1" + resolved "https://registry.yarnpkg.com/levn/-/levn-0.4.1.tgz#ae4562c007473b932a6200d403268dd2fffc6ade" + integrity sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ== + dependencies: + prelude-ls "^1.2.1" + type-check "~0.4.0" + +lilconfig@2.0.5: + version "2.0.5" + resolved "https://registry.yarnpkg.com/lilconfig/-/lilconfig-2.0.5.tgz#19e57fd06ccc3848fd1891655b5a447092225b25" + integrity sha512-xaYmXZtTHPAw5m+xLN8ab9C+3a8YmV3asNSPOATITbtwrfbwaLJj8h66H1WMIpALCkqsIzK3h7oQ+PdX+LQ9Eg== + +line-column@~1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/line-column/-/line-column-1.0.2.tgz#d25af2936b6f4849172b312e4792d1d987bc34a2" + integrity sha512-Ktrjk5noGYlHsVnYWh62FLVs4hTb8A3e+vucNZMgPeAOITdshMSgv4cCZQeRDjm7+goqmo6+liZwTXo+U3sVww== + dependencies: + isarray "^1.0.0" + isobject "^2.0.0" + +lines-and-columns@^1.1.6: + version "1.2.4" + resolved "https://registry.yarnpkg.com/lines-and-columns/-/lines-and-columns-1.2.4.tgz#eca284f75d2965079309dc0ad9255abb2ebc1632" + integrity sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg== + +lint-staged@^12.3.7: + version "12.5.0" + resolved "https://registry.yarnpkg.com/lint-staged/-/lint-staged-12.5.0.tgz#d6925747480ae0e380d13988522f9dd8ef9126e3" + integrity sha512-BKLUjWDsKquV/JuIcoQW4MSAI3ggwEImF1+sB4zaKvyVx1wBk3FsG7UK9bpnmBTN1pm7EH2BBcMwINJzCRv12g== + dependencies: + cli-truncate "^3.1.0" + colorette "^2.0.16" + commander "^9.3.0" + debug "^4.3.4" + execa "^5.1.1" + lilconfig "2.0.5" + listr2 "^4.0.5" + micromatch "^4.0.5" + normalize-path "^3.0.0" + object-inspect "^1.12.2" + pidtree "^0.5.0" + string-argv "^0.3.1" + supports-color "^9.2.2" + yaml "^1.10.2" + +listr2@^4.0.5: + version "4.0.5" + resolved "https://registry.yarnpkg.com/listr2/-/listr2-4.0.5.tgz#9dcc50221583e8b4c71c43f9c7dfd0ef546b75d5" + integrity sha512-juGHV1doQdpNT3GSTs9IUN43QJb7KHdF9uqg7Vufs/tG9VTzpFphqF4pm/ICdAABGQxsyNn9CiYA3StkI6jpwA== + dependencies: + cli-truncate "^2.1.0" + colorette "^2.0.16" + log-update "^4.0.0" + p-map "^4.0.0" + rfdc "^1.3.0" + rxjs "^7.5.5" + through "^2.3.8" + wrap-ansi "^7.0.0" + +locate-path@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/locate-path/-/locate-path-5.0.0.tgz#1afba396afd676a6d42504d0a67a3a7eb9f62aa0" + integrity sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g== + dependencies: + p-locate "^4.1.0" + +locate-path@^6.0.0: + version "6.0.0" + resolved "https://registry.yarnpkg.com/locate-path/-/locate-path-6.0.0.tgz#55321eb309febbc59c4801d931a72452a681d286" + integrity sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw== + dependencies: + p-locate "^5.0.0" + +lodash.memoize@^4.1.2: + version "4.1.2" + resolved "https://registry.yarnpkg.com/lodash.memoize/-/lodash.memoize-4.1.2.tgz#bcc6c49a42a2840ed997f323eada5ecd182e0bfe" + integrity sha512-t7j+NzmgnQzTAYXcsHYLgimltOV1MXHtlOWf6GjL9Kj8GK5FInw5JotxvbOs+IvV1/Dzo04/fCGfLVs7aXb4Ag== + +lodash.merge@^4.6.2: + version "4.6.2" + resolved "https://registry.yarnpkg.com/lodash.merge/-/lodash.merge-4.6.2.tgz#558aa53b43b661e1925a0afdfa36a9a1085fe57a" + integrity sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ== + +lodash@^4.17.21, lodash@^4.7.0: + version "4.17.21" + resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.21.tgz#679591c564c3bffaae8454cf0b3df370c3d6911c" + integrity sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg== + +log-update@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/log-update/-/log-update-4.0.0.tgz#589ecd352471f2a1c0c570287543a64dfd20e0a1" + integrity sha512-9fkkDevMefjg0mmzWFBW8YkFP91OrizzkW3diF7CpG+S2EYdy4+TVfGwz1zeF8x7hCx1ovSPTOE9Ngib74qqUg== + dependencies: + ansi-escapes "^4.3.0" + cli-cursor "^3.1.0" + slice-ansi "^4.0.0" + wrap-ansi "^6.2.0" + +lru-cache@^5.1.1: + version "5.1.1" + resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-5.1.1.tgz#1da27e6710271947695daf6848e847f01d84b920" + integrity sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w== + dependencies: + yallist "^3.0.2" + +lru-cache@^6.0.0: + version "6.0.0" + resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-6.0.0.tgz#6d6fe6570ebd96aaf90fcad1dafa3b2566db3a94" + integrity sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA== + dependencies: + yallist "^4.0.0" + +make-dir@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/make-dir/-/make-dir-4.0.0.tgz#c3c2307a771277cd9638305f915c29ae741b614e" + integrity sha512-hXdUTZYIVOt1Ex//jAQi+wTZZpUpwBj/0QsOzqegb3rGMMeJiSEu5xLHnYfBrRV4RH2+OCSOO95Is/7x1WJ4bw== + dependencies: + semver "^7.5.3" + +makeerror@1.0.12: + version "1.0.12" + resolved "https://registry.yarnpkg.com/makeerror/-/makeerror-1.0.12.tgz#3e5dd2079a82e812e983cc6610c4a2cb0eaa801a" + integrity sha512-JmqCvUhmt43madlpFzG4BQzG2Z3m6tvQDNKdClZnO3VbIudJYmxsT0FNJMeiB2+JTSlTQTSbU8QdesVmwJcmLg== + dependencies: + tmpl "1.0.5" + +merge-stream@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/merge-stream/-/merge-stream-2.0.0.tgz#52823629a14dd00c9770fb6ad47dc6310f2c1f60" + integrity sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w== + +merge2@^1.3.0, merge2@^1.4.1: + version "1.4.1" + resolved "https://registry.yarnpkg.com/merge2/-/merge2-1.4.1.tgz#4368892f885e907455a6fd7dc55c0c9d404990ae" + integrity sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg== + +micromatch@^4.0.4, micromatch@^4.0.5: + version "4.0.5" + resolved "https://registry.yarnpkg.com/micromatch/-/micromatch-4.0.5.tgz#bc8999a7cbbf77cdc89f132f6e467051b49090c6" + integrity sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA== + dependencies: + braces "^3.0.2" + picomatch "^2.3.1" + +mime-db@1.52.0: + version "1.52.0" + resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.52.0.tgz#bbabcdc02859f4987301c856e3387ce5ec43bf70" + integrity sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg== + +mime-types@^2.1.12: + version "2.1.35" + resolved "https://registry.yarnpkg.com/mime-types/-/mime-types-2.1.35.tgz#381a871b62a734450660ae3deee44813f70d959a" + integrity sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw== + dependencies: + mime-db "1.52.0" + +mimic-fn@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/mimic-fn/-/mimic-fn-2.1.0.tgz#7ed2c2ccccaf84d3ffcb7a69b57711fc2083401b" + integrity sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg== + +minimatch@^3.0.4, minimatch@^3.0.5, minimatch@^3.1.1, minimatch@^3.1.2: + version "3.1.2" + resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.1.2.tgz#19cd194bfd3e428f049a70817c038d89ab4be35b" + integrity sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw== + dependencies: + brace-expansion "^1.1.7" + +minimatch@^9.0.3: + version "9.0.3" + resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-9.0.3.tgz#a6e00c3de44c3a542bfaae70abfc22420a6da825" + integrity sha512-RHiac9mvaRw0x3AYRgDC1CxAP7HTcNrrECeA8YYJeWnpo+2Q5CegtZjaotWTWxDG3UeGA1coE05iH1mPjT/2mg== + dependencies: + brace-expansion "^2.0.1" + +minimist@^1.2.0, minimist@^1.2.6, minimist@^1.2.8: + version "1.2.8" + resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.8.tgz#c1a464e7693302e082a075cee0c057741ac4772c" + integrity sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA== + +ms@2.1.2: + version "2.1.2" + resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.2.tgz#d09d1f357b443f493382a8eb3ccd183872ae6009" + integrity sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w== + +ms@^2.1.1: + version "2.1.3" + resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.3.tgz#574c8138ce1d2b5861f0b44579dbadd60c6615b2" + integrity sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA== + +nanoid@^3.3.6: + version "3.3.7" + resolved "https://registry.yarnpkg.com/nanoid/-/nanoid-3.3.7.tgz#d0c301a691bc8d54efa0a2226ccf3fe2fd656bd8" + integrity sha512-eSRppjcPIatRIMC1U6UngP8XFcz8MQWGQdt1MTBQ7NaAmvXDfvNxbvWV3x2y6CdEUciCSsDHDQZbhYaB8QEo2g== + +natural-compare@^1.4.0: + version "1.4.0" + resolved "https://registry.yarnpkg.com/natural-compare/-/natural-compare-1.4.0.tgz#4abebfeed7541f2c27acfb29bdbbd15c8d5ba4f7" + integrity sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw== + +node-int64@^0.4.0: + version "0.4.0" + resolved "https://registry.yarnpkg.com/node-int64/-/node-int64-0.4.0.tgz#87a9065cdb355d3182d8f94ce11188b825c68a3b" + integrity sha512-O5lz91xSOeoXP6DulyHfllpq+Eg00MWitZIbtPfoSEvqIHdl5gfcY6hYzDWnj0qD5tz52PI08u9qUvSVeUBeHw== + +node-releases@^2.0.13: + version "2.0.13" + resolved "https://registry.yarnpkg.com/node-releases/-/node-releases-2.0.13.tgz#d5ed1627c23e3461e819b02e57b75e4899b1c81d" + integrity sha512-uYr7J37ae/ORWdZeQ1xxMJe3NtdmqMC/JZK+geofDrkLUApKRHPd18/TxtBOJ4A0/+uUIliorNrfYV6s1b02eQ== + +normalize-path@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/normalize-path/-/normalize-path-3.0.0.tgz#0dcd69ff23a1c9b11fd0978316644a0388216a65" + integrity sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA== + +npm-run-path@^4.0.1: + version "4.0.1" + resolved "https://registry.yarnpkg.com/npm-run-path/-/npm-run-path-4.0.1.tgz#b7ecd1e5ed53da8e37a55e1c2269e0b97ed748ea" + integrity sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw== + dependencies: + path-key "^3.0.0" + +nwsapi@^2.2.0: + version "2.2.7" + resolved "https://registry.yarnpkg.com/nwsapi/-/nwsapi-2.2.7.tgz#738e0707d3128cb750dddcfe90e4610482df0f30" + integrity sha512-ub5E4+FBPKwAZx0UwIQOjYWGHTEq5sPqHQNRN8Z9e4A7u3Tj1weLJsL59yH9vmvqEtBHaOmT6cYQKIZOxp35FQ== + +object-inspect@^1.12.2, object-inspect@^1.13.1, object-inspect@^1.9.0: + version "1.13.1" + resolved "https://registry.yarnpkg.com/object-inspect/-/object-inspect-1.13.1.tgz#b96c6109324ccfef6b12216a956ca4dc2ff94bc2" + integrity sha512-5qoj1RUiKOMsCCNLV1CBiPYE10sziTsnmNxkAI/rZhiD63CF7IqdFGC/XzjWjpSgLf0LxXX3bDFIh0E18f6UhQ== + +object-keys@^1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/object-keys/-/object-keys-1.1.1.tgz#1c47f272df277f3b1daf061677d9c82e2322c60e" + integrity sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA== + +object.assign@^4.1.4: + version "4.1.4" + resolved "https://registry.yarnpkg.com/object.assign/-/object.assign-4.1.4.tgz#9673c7c7c351ab8c4d0b516f4343ebf4dfb7799f" + integrity sha512-1mxKf0e58bvyjSCtKYY4sRe9itRk3PJpquJOjeIkz885CczcI4IvJJDLPS72oowuSh+pBxUFROpX+TU++hxhZQ== + dependencies: + call-bind "^1.0.2" + define-properties "^1.1.4" + has-symbols "^1.0.3" + object-keys "^1.1.1" + +object.fromentries@^2.0.7: + version "2.0.7" + resolved "https://registry.yarnpkg.com/object.fromentries/-/object.fromentries-2.0.7.tgz#71e95f441e9a0ea6baf682ecaaf37fa2a8d7e616" + integrity sha512-UPbPHML6sL8PI/mOqPwsH4G6iyXcCGzLin8KvEPenOZN5lpCNBZZQ+V62vdjB1mQHrmqGQt5/OJzemUA+KJmEA== + dependencies: + call-bind "^1.0.2" + define-properties "^1.2.0" + es-abstract "^1.22.1" + +object.groupby@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/object.groupby/-/object.groupby-1.0.1.tgz#d41d9f3c8d6c778d9cbac86b4ee9f5af103152ee" + integrity sha512-HqaQtqLnp/8Bn4GL16cj+CUYbnpe1bh0TtEaWvybszDG4tgxCJuRpV8VGuvNaI1fAnI4lUJzDG55MXcOH4JZcQ== + dependencies: + call-bind "^1.0.2" + define-properties "^1.2.0" + es-abstract "^1.22.1" + get-intrinsic "^1.2.1" + +object.values@^1.1.7: + version "1.1.7" + resolved "https://registry.yarnpkg.com/object.values/-/object.values-1.1.7.tgz#617ed13272e7e1071b43973aa1655d9291b8442a" + integrity sha512-aU6xnDFYT3x17e/f0IiiwlGPTy2jzMySGfUB4fq6z7CV8l85CWHDk5ErhyhpfDHhrOMwGFhSQkhMGHaIotA6Ng== + dependencies: + call-bind "^1.0.2" + define-properties "^1.2.0" + es-abstract "^1.22.1" + +once@^1.3.0: + version "1.4.0" + resolved "https://registry.yarnpkg.com/once/-/once-1.4.0.tgz#583b1aa775961d4b113ac17d9c50baef9dd76bd1" + integrity sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w== + dependencies: + wrappy "1" + +onetime@^5.1.0, onetime@^5.1.2: + version "5.1.2" + resolved "https://registry.yarnpkg.com/onetime/-/onetime-5.1.2.tgz#d0e96ebb56b07476df1dd9c4806e5237985ca45e" + integrity sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg== + dependencies: + mimic-fn "^2.1.0" + +optionator@^0.9.3: + version "0.9.3" + resolved "https://registry.yarnpkg.com/optionator/-/optionator-0.9.3.tgz#007397d44ed1872fdc6ed31360190f81814e2c64" + integrity sha512-JjCoypp+jKn1ttEFExxhetCKeJt9zhAgAve5FXHixTvFDW/5aEktX9bufBKLRRMdU7bNtpLfcGu94B3cdEJgjg== + dependencies: + "@aashutoshrathi/word-wrap" "^1.2.3" + deep-is "^0.1.3" + fast-levenshtein "^2.0.6" + levn "^0.4.1" + prelude-ls "^1.2.1" + type-check "^0.4.0" + +p-limit@^2.2.0: + version "2.3.0" + resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-2.3.0.tgz#3dd33c647a214fdfffd835933eb086da0dc21db1" + integrity sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w== + dependencies: + p-try "^2.0.0" + +p-limit@^3.0.2: + version "3.1.0" + resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-3.1.0.tgz#e1daccbe78d0d1388ca18c64fea38e3e57e3706b" + integrity sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ== + dependencies: + yocto-queue "^0.1.0" + +p-locate@^4.1.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/p-locate/-/p-locate-4.1.0.tgz#a3428bb7088b3a60292f66919278b7c297ad4f07" + integrity sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A== + dependencies: + p-limit "^2.2.0" + +p-locate@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/p-locate/-/p-locate-5.0.0.tgz#83c8315c6785005e3bd021839411c9e110e6d834" + integrity sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw== + dependencies: + p-limit "^3.0.2" + +p-map@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/p-map/-/p-map-4.0.0.tgz#bb2f95a5eda2ec168ec9274e06a747c3e2904d2b" + integrity sha512-/bjOqmgETBYB5BoEeGVea8dmvHb2m9GLy1E9W43yeyfP6QQCZGFNa+XRceJEuDB6zqr+gKpIAmlLebMpykw/MQ== + dependencies: + aggregate-error "^3.0.0" + +p-try@^2.0.0: + version "2.2.0" + resolved "https://registry.yarnpkg.com/p-try/-/p-try-2.2.0.tgz#cb2868540e313d61de58fafbe35ce9004d5540e6" + integrity sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ== + +parent-module@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/parent-module/-/parent-module-1.0.1.tgz#691d2709e78c79fae3a156622452d00762caaaa2" + integrity sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g== + dependencies: + callsites "^3.0.0" + +parse-json@^5.2.0: + version "5.2.0" + resolved "https://registry.yarnpkg.com/parse-json/-/parse-json-5.2.0.tgz#c76fc66dee54231c962b22bcc8a72cf2f99753cd" + integrity sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg== + dependencies: + "@babel/code-frame" "^7.0.0" + error-ex "^1.3.1" + json-parse-even-better-errors "^2.3.0" + lines-and-columns "^1.1.6" + +parse5@6.0.1, parse5@~6.0.1: + version "6.0.1" + resolved "https://registry.yarnpkg.com/parse5/-/parse5-6.0.1.tgz#e1a1c085c569b3dc08321184f19a39cc27f7c30b" + integrity sha512-Ofn/CTFzRGTTxwpNEs9PP93gXShHcTq255nzRYSKe8AkVpZY7e1fpmTfOyoIvjP5HG7Z2ZM7VS9PPhQGW2pOpw== + +path-exists@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/path-exists/-/path-exists-4.0.0.tgz#513bdbe2d3b95d7762e8c1137efa195c6c61b5b3" + integrity sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w== + +path-is-absolute@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/path-is-absolute/-/path-is-absolute-1.0.1.tgz#174b9268735534ffbc7ace6bf53a5a9e1b5c5f5f" + integrity sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg== + +path-key@^3.0.0, path-key@^3.1.0: + version "3.1.1" + resolved "https://registry.yarnpkg.com/path-key/-/path-key-3.1.1.tgz#581f6ade658cbba65a0d3380de7753295054f375" + integrity sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q== + +path-parse@^1.0.7: + version "1.0.7" + resolved "https://registry.yarnpkg.com/path-parse/-/path-parse-1.0.7.tgz#fbc114b60ca42b30d9daf5858e4bd68bbedb6735" + integrity sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw== + +path-type@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/path-type/-/path-type-4.0.0.tgz#84ed01c0a7ba380afe09d90a8c180dcd9d03043b" + integrity sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw== + +picocolors@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/picocolors/-/picocolors-1.0.0.tgz#cb5bdc74ff3f51892236eaf79d68bc44564ab81c" + integrity sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ== + +picomatch@^2.0.4, picomatch@^2.2.3, picomatch@^2.3.1: + version "2.3.1" + resolved "https://registry.yarnpkg.com/picomatch/-/picomatch-2.3.1.tgz#3ba3833733646d9d3e4995946c1365a67fb07a42" + integrity sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA== + +pidtree@^0.5.0: + version "0.5.0" + resolved "https://registry.yarnpkg.com/pidtree/-/pidtree-0.5.0.tgz#ad5fbc1de78b8a5f99d6fbdd4f6e4eee21d1aca1" + integrity sha512-9nxspIM7OpZuhBxPg73Zvyq7j1QMPMPsGKTqRc2XOaFQauDvoNz9fM1Wdkjmeo7l9GXOZiRs97sPkuayl39wjA== + +pirates@^4.0.4: + version "4.0.6" + resolved "https://registry.yarnpkg.com/pirates/-/pirates-4.0.6.tgz#3018ae32ecfcff6c29ba2267cbf21166ac1f36b9" + integrity sha512-saLsH7WeYYPiD25LDuLRRY/i+6HaPYr6G1OUlN39otzkSTxKnubR9RTxS3/Kk50s1g2JTgFwWQDQyplC5/SHZg== + +pkg-dir@^4.2.0: + version "4.2.0" + resolved "https://registry.yarnpkg.com/pkg-dir/-/pkg-dir-4.2.0.tgz#f099133df7ede422e81d1d8448270eeb3e4261f3" + integrity sha512-HRDzbaKjC+AOWVXxAU/x54COGeIv9eb+6CkDSQoNTt4XyWoIJvuPsXizxu/Fr23EiekbtZwmh1IcIG/l/a10GQ== + dependencies: + find-up "^4.0.0" + +postcss-selector-parser@~6.0.11: + version "6.0.13" + resolved "https://registry.yarnpkg.com/postcss-selector-parser/-/postcss-selector-parser-6.0.13.tgz#d05d8d76b1e8e173257ef9d60b706a8e5e99bf1b" + integrity sha512-EaV1Gl4mUEV4ddhDnv/xtj7sxwrwxdetHdWUGnT4VJQf+4d05v6lHYZr8N573k5Z0BViss7BDhfWtKS3+sfAqQ== + dependencies: + cssesc "^3.0.0" + util-deprecate "^1.0.2" + +postcss-value-parser@~4.2.0: + version "4.2.0" + resolved "https://registry.yarnpkg.com/postcss-value-parser/-/postcss-value-parser-4.2.0.tgz#723c09920836ba6d3e5af019f92bc0971c02e514" + integrity sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ== + +postcss@~8.4.20: + version "8.4.31" + resolved "https://registry.yarnpkg.com/postcss/-/postcss-8.4.31.tgz#92b451050a9f914da6755af352bdc0192508656d" + integrity sha512-PS08Iboia9mts/2ygV3eLpY5ghnUcfLV/EXTOW1E2qYxJKGGBUtNjN76FYHnMs36RmARn41bC0AZmn+rR0OVpQ== + dependencies: + nanoid "^3.3.6" + picocolors "^1.0.0" + source-map-js "^1.0.2" + +prelude-ls@^1.2.1: + version "1.2.1" + resolved "https://registry.yarnpkg.com/prelude-ls/-/prelude-ls-1.2.1.tgz#debc6489d7a6e6b0e7611888cec880337d316396" + integrity sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g== + +prettier-plugin-apex@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/prettier-plugin-apex/-/prettier-plugin-apex-2.0.1.tgz#35bb37fbf7d779f8a83e25ecd02e133a16cd903a" + integrity sha512-S64zate3iXPKiBKHf27YRapIAPPd1wQ/u5IOcWwSHNgoJv15I14HhoUB/WOKXtxFb0ZH5MO1nF8gRGWXLajwlA== + dependencies: + jest-docblock "^29.0.0" + wait-on "^7.0.0" + +prettier@^3.1.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/prettier/-/prettier-3.1.0.tgz#c6d16474a5f764ea1a4a373c593b779697744d5e" + integrity sha512-TQLvXjq5IAibjh8EpBIkNKxO749UEWABoiIZehEPiY4GNpVdhaFKqSTu+QrlU6D2dPAfubRmtJTi4K4YkQ5eXw== + +pretty-format@^27.5.1: + version "27.5.1" + resolved "https://registry.yarnpkg.com/pretty-format/-/pretty-format-27.5.1.tgz#2181879fdea51a7a5851fb39d920faa63f01d88e" + integrity sha512-Qb1gy5OrP5+zDf2Bvnzdl3jsTf1qXVMazbvCoKhtKqVs4/YK4ozX4gKQJJVyNe+cajNPn0KoC0MC3FUmaHWEmQ== + dependencies: + ansi-regex "^5.0.1" + ansi-styles "^5.0.0" + react-is "^17.0.1" + +pretty-format@^29.5.0: + version "29.7.0" + resolved "https://registry.yarnpkg.com/pretty-format/-/pretty-format-29.7.0.tgz#ca42c758310f365bfa71a0bda0a807160b776812" + integrity sha512-Pdlw/oPxN+aXdmM9R00JVC9WVFoCLTKJvDVLgmJ+qAffBMxsV85l/Lu7sNx4zSzPyoL2euImuEwHhOXdEgNFZQ== + dependencies: + "@jest/schemas" "^29.6.3" + ansi-styles "^5.0.0" + react-is "^18.0.0" + +prompts@^2.0.1: + version "2.4.2" + resolved "https://registry.yarnpkg.com/prompts/-/prompts-2.4.2.tgz#7b57e73b3a48029ad10ebd44f74b01722a4cb069" + integrity sha512-NxNv/kLguCA7p3jE8oL2aEBsrJWgAakBpgmgK6lpPWV+WuOmY6r2/zbAVnP+T8bQlA0nzHXSJSJW0Hq7ylaD2Q== + dependencies: + kleur "^3.0.3" + sisteransi "^1.0.5" + +proxy-from-env@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/proxy-from-env/-/proxy-from-env-1.1.0.tgz#e102f16ca355424865755d2c9e8ea4f24d58c3e2" + integrity sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg== + +psl@^1.1.33: + version "1.9.0" + resolved "https://registry.yarnpkg.com/psl/-/psl-1.9.0.tgz#d0df2a137f00794565fcaf3b2c00cd09f8d5a5a7" + integrity sha512-E/ZsdU4HLs/68gYzgGTkMicWTLPdAftJLfJFlLUAAKZGkStNU72sZjT66SnMDVOfOWY/YAoiD7Jxa9iHvngcag== + +punycode@^2.1.0, punycode@^2.1.1: + version "2.3.1" + resolved "https://registry.yarnpkg.com/punycode/-/punycode-2.3.1.tgz#027422e2faec0b25e1549c3e1bd8309b9133b6e5" + integrity sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg== + +querystringify@^2.1.1: + version "2.2.0" + resolved "https://registry.yarnpkg.com/querystringify/-/querystringify-2.2.0.tgz#3345941b4153cb9d082d8eee4cda2016a9aef7f6" + integrity sha512-FIqgj2EUvTa7R50u0rGsyTftzjYmv/a3hO345bZNrqabNqjtgiDMgmo4mkUjd+nzU5oF3dClKqFIPUKybUyqoQ== + +queue-microtask@^1.2.2: + version "1.2.3" + resolved "https://registry.yarnpkg.com/queue-microtask/-/queue-microtask-1.2.3.tgz#4929228bbc724dfac43e0efb058caf7b6cfb6243" + integrity sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A== + +react-is@^17.0.1: + version "17.0.2" + resolved "https://registry.yarnpkg.com/react-is/-/react-is-17.0.2.tgz#e691d4a8e9c789365655539ab372762b0efb54f0" + integrity sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w== + +react-is@^18.0.0: + version "18.2.0" + resolved "https://registry.yarnpkg.com/react-is/-/react-is-18.2.0.tgz#199431eeaaa2e09f86427efbb4f1473edb47609b" + integrity sha512-xWGDIW6x921xtzPkhiULtthJHoJvBbF3q26fzloPCK0hsvxtPVelvftw3zjbHWSkR2km9Z+4uxbDDK/6Zw9B8w== + +regexp-to-ast@0.5.0: + version "0.5.0" + resolved "https://registry.yarnpkg.com/regexp-to-ast/-/regexp-to-ast-0.5.0.tgz#56c73856bee5e1fef7f73a00f1473452ab712a24" + integrity sha512-tlbJqcMHnPKI9zSrystikWKwHkBqu2a/Sgw01h3zFjvYrMxEDYHzzoMZnUrbIfpTFEsoRnnviOXNCzFiSc54Qw== + +regexp.prototype.flags@^1.5.0, regexp.prototype.flags@^1.5.1: + version "1.5.1" + resolved "https://registry.yarnpkg.com/regexp.prototype.flags/-/regexp.prototype.flags-1.5.1.tgz#90ce989138db209f81492edd734183ce99f9677e" + integrity sha512-sy6TXMN+hnP/wMy+ISxg3krXx7BAtWVO4UouuCN/ziM9UEne0euamVNafDfvC83bRNr95y0V5iijeDQFUNpvrg== + dependencies: + call-bind "^1.0.2" + define-properties "^1.2.0" + set-function-name "^2.0.0" + +require-directory@^2.1.1: + version "2.1.1" + resolved "https://registry.yarnpkg.com/require-directory/-/require-directory-2.1.1.tgz#8c64ad5fd30dab1c976e2344ffe7f792a6a6df42" + integrity sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q== + +requires-port@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/requires-port/-/requires-port-1.0.0.tgz#925d2601d39ac485e091cf0da5c6e694dc3dcaff" + integrity sha512-KigOCHcocU3XODJxsu8i/j8T9tzT4adHiecwORRQ0ZZFcp7ahwXuRU1m+yuO90C5ZUyGeGfocHDI14M3L3yDAQ== + +resolve-cwd@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/resolve-cwd/-/resolve-cwd-3.0.0.tgz#0f0075f1bb2544766cf73ba6a6e2adfebcb13f2d" + integrity sha512-OrZaX2Mb+rJCpH/6CpSqt9xFVpN++x01XnN2ie9g6P5/3xelLAkXWVADpdz1IHD/KFfEXyE6V0U01OQ3UO2rEg== + dependencies: + resolve-from "^5.0.0" + +resolve-from@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/resolve-from/-/resolve-from-4.0.0.tgz#4abcd852ad32dd7baabfe9b40e00a36db5f392e6" + integrity sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g== + +resolve-from@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/resolve-from/-/resolve-from-5.0.0.tgz#c35225843df8f776df21c57557bc087e9dfdfc69" + integrity sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw== + +resolve.exports@^1.1.0: + version "1.1.1" + resolved "https://registry.yarnpkg.com/resolve.exports/-/resolve.exports-1.1.1.tgz#05cfd5b3edf641571fd46fa608b610dda9ead999" + integrity sha512-/NtpHNDN7jWhAaQ9BvBUYZ6YTXsRBgfqWFWP7BZBaoMJO/I3G5OFzvTuWNlZC3aPjins1F+TNrLKsGbH4rfsRQ== + +resolve@^1.20.0, resolve@^1.22.4, resolve@~1.22.1: + version "1.22.8" + resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.22.8.tgz#b6c87a9f2aa06dfab52e3d70ac8cde321fa5a48d" + integrity sha512-oKWePCxqpd6FlLvGV1VU0x7bkPmmCNolxzjMf4NczoDnQcIWrAF+cPtZn5i6n+RfD2d9i0tzpKnG6Yk168yIyw== + dependencies: + is-core-module "^2.13.0" + path-parse "^1.0.7" + supports-preserve-symlinks-flag "^1.0.0" + +restore-cursor@^3.1.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/restore-cursor/-/restore-cursor-3.1.0.tgz#39f67c54b3a7a58cea5236d95cf0034239631f7e" + integrity sha512-l+sSefzHpj5qimhFSE5a8nufZYAM3sBSVMAPtYkmC+4EH2anSGaEMXSD0izRQbu9nfyQ9y5JrVmp7E8oZrUjvA== + dependencies: + onetime "^5.1.0" + signal-exit "^3.0.2" + +reusify@^1.0.4: + version "1.0.4" + resolved "https://registry.yarnpkg.com/reusify/-/reusify-1.0.4.tgz#90da382b1e126efc02146e90845a88db12925d76" + integrity sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw== + +rfdc@^1.3.0: + version "1.3.0" + resolved "https://registry.yarnpkg.com/rfdc/-/rfdc-1.3.0.tgz#d0b7c441ab2720d05dc4cf26e01c89631d9da08b" + integrity sha512-V2hovdzFbOi77/WajaSMXk2OLm+xNIeQdMMuB7icj7bk6zi2F8GGAxigcnDFpJHbNyNcgyJDiP+8nOrY5cZGrA== + +rimraf@^3.0.0, rimraf@^3.0.2: + version "3.0.2" + resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-3.0.2.tgz#f1a5402ba6220ad52cc1282bac1ae3aa49fd061a" + integrity sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA== + dependencies: + glob "^7.1.3" + +run-parallel@^1.1.9: + version "1.2.0" + resolved "https://registry.yarnpkg.com/run-parallel/-/run-parallel-1.2.0.tgz#66d1368da7bdf921eb9d95bd1a9229e7f21a43ee" + integrity sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA== + dependencies: + queue-microtask "^1.2.2" + +rxjs@^7.5.5, rxjs@^7.8.1: + version "7.8.1" + resolved "https://registry.yarnpkg.com/rxjs/-/rxjs-7.8.1.tgz#6f6f3d99ea8044291efd92e7c7fcf562c4057543" + integrity sha512-AA3TVj+0A2iuIoQkWEK/tqFjBq2j+6PO6Y0zJcvzLAFhEFIO3HL0vls9hWLncZbAAbK0mar7oZ4V079I/qPMxg== + dependencies: + tslib "^2.1.0" + +safe-array-concat@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/safe-array-concat/-/safe-array-concat-1.0.1.tgz#91686a63ce3adbea14d61b14c99572a8ff84754c" + integrity sha512-6XbUAseYE2KtOuGueyeobCySj9L4+66Tn6KQMOPQJrAJEowYKW/YR/MGJZl7FdydUdaFu4LYyDZjxf4/Nmo23Q== + dependencies: + call-bind "^1.0.2" + get-intrinsic "^1.2.1" + has-symbols "^1.0.3" + isarray "^2.0.5" + +safe-regex-test@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/safe-regex-test/-/safe-regex-test-1.0.0.tgz#793b874d524eb3640d1873aad03596db2d4f2295" + integrity sha512-JBUUzyOgEwXQY1NuPtvcj/qcBDbDmEvWufhlnXZIm75DEHp+afM1r1ujJpJsV/gSM4t59tpDyPi1sd6ZaPFfsA== + dependencies: + call-bind "^1.0.2" + get-intrinsic "^1.1.3" + is-regex "^1.1.4" + +"safer-buffer@>= 2.1.2 < 3": + version "2.1.2" + resolved "https://registry.yarnpkg.com/safer-buffer/-/safer-buffer-2.1.2.tgz#44fa161b0187b9549dd84bb91802f9bd8385cd6a" + integrity sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg== + +saxes@^5.0.1: + version "5.0.1" + resolved "https://registry.yarnpkg.com/saxes/-/saxes-5.0.1.tgz#eebab953fa3b7608dbe94e5dadb15c888fa6696d" + integrity sha512-5LBh1Tls8c9xgGjw3QrMwETmTMVk0oFgvrFSvWx62llR2hcEInrKNZ2GZCCuuy2lvWrdl5jhbpeqc5hRYKFOcw== + dependencies: + xmlchars "^2.2.0" + +semver@^6.3.0, semver@^6.3.1: + version "6.3.1" + resolved "https://registry.yarnpkg.com/semver/-/semver-6.3.1.tgz#556d2ef8689146e46dcea4bfdd095f3434dffcb4" + integrity sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA== + +semver@^7.3.2, semver@^7.3.7, semver@^7.5.3, semver@^7.5.4: + version "7.5.4" + resolved "https://registry.yarnpkg.com/semver/-/semver-7.5.4.tgz#483986ec4ed38e1c6c48c34894a9182dbff68a6e" + integrity sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA== + dependencies: + lru-cache "^6.0.0" + +set-function-length@^1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/set-function-length/-/set-function-length-1.1.1.tgz#4bc39fafb0307224a33e106a7d35ca1218d659ed" + integrity sha512-VoaqjbBJKiWtg4yRcKBQ7g7wnGnLV3M8oLvVWwOk2PdYY6PEFegR1vezXR0tw6fZGF9csVakIRjrJiy2veSBFQ== + dependencies: + define-data-property "^1.1.1" + get-intrinsic "^1.2.1" + gopd "^1.0.1" + has-property-descriptors "^1.0.0" + +set-function-name@^2.0.0: + version "2.0.1" + resolved "https://registry.yarnpkg.com/set-function-name/-/set-function-name-2.0.1.tgz#12ce38b7954310b9f61faa12701620a0c882793a" + integrity sha512-tMNCiqYVkXIZgc2Hnoy2IvC/f8ezc5koaRFkCjrpWzGpCd3qbZXPzVy9MAZzK1ch/X0jvSkojys3oqJN0qCmdA== + dependencies: + define-data-property "^1.0.1" + functions-have-names "^1.2.3" + has-property-descriptors "^1.0.0" + +shebang-command@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/shebang-command/-/shebang-command-2.0.0.tgz#ccd0af4f8835fbdc265b82461aaf0c36663f34ea" + integrity sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA== + dependencies: + shebang-regex "^3.0.0" + +shebang-regex@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/shebang-regex/-/shebang-regex-3.0.0.tgz#ae16f1644d873ecad843b0307b143362d4c42172" + integrity sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A== + +side-channel@^1.0.4: + version "1.0.4" + resolved "https://registry.yarnpkg.com/side-channel/-/side-channel-1.0.4.tgz#efce5c8fdc104ee751b25c58d4290011fa5ea2cf" + integrity sha512-q5XPytqFEIKHkGdiMIrY10mvLRvnQh42/+GoBlFW3b2LXLE2xxJpZFdm94we0BaoV3RwJyGqg5wS7epxTv0Zvw== + dependencies: + call-bind "^1.0.0" + get-intrinsic "^1.0.2" + object-inspect "^1.9.0" + +signal-exit@^3.0.2, signal-exit@^3.0.3: + version "3.0.7" + resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-3.0.7.tgz#a9a1767f8af84155114eaabd73f99273c8f59ad9" + integrity sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ== + +sisteransi@^1.0.5: + version "1.0.5" + resolved "https://registry.yarnpkg.com/sisteransi/-/sisteransi-1.0.5.tgz#134d681297756437cc05ca01370d3a7a571075ed" + integrity sha512-bLGGlR1QxBcynn2d5YmDX4MGjlZvy2MRBDRNHLJ8VI6l6+9FUiyTFNJ0IveOSP0bcXgVDPRcfGqA0pjaqUpfVg== + +slash@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/slash/-/slash-3.0.0.tgz#6539be870c165adbd5240220dbe361f1bc4d4634" + integrity sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q== + +slice-ansi@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/slice-ansi/-/slice-ansi-3.0.0.tgz#31ddc10930a1b7e0b67b08c96c2f49b77a789787" + integrity sha512-pSyv7bSTC7ig9Dcgbw9AuRNUb5k5V6oDudjZoMBSr13qpLBG7tB+zgCkARjq7xIUgdz5P1Qe8u+rSGdouOOIyQ== + dependencies: + ansi-styles "^4.0.0" + astral-regex "^2.0.0" + is-fullwidth-code-point "^3.0.0" + +slice-ansi@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/slice-ansi/-/slice-ansi-4.0.0.tgz#500e8dd0fd55b05815086255b3195adf2a45fe6b" + integrity sha512-qMCMfhY040cVHT43K9BFygqYbUPFZKHOg7K73mtTWJRb8pyP3fzf4Ixd5SzdEJQ6MRUg/WBnOLxghZtKKurENQ== + dependencies: + ansi-styles "^4.0.0" + astral-regex "^2.0.0" + is-fullwidth-code-point "^3.0.0" + +slice-ansi@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/slice-ansi/-/slice-ansi-5.0.0.tgz#b73063c57aa96f9cd881654b15294d95d285c42a" + integrity sha512-FC+lgizVPfie0kkhqUScwRu1O/lF6NOgJmlCgK+/LYxDCTk8sGelYaHDhFcDN+Sn3Cv+3VSa4Byeo+IMCzpMgQ== + dependencies: + ansi-styles "^6.0.0" + is-fullwidth-code-point "^4.0.0" + +source-map-js@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/source-map-js/-/source-map-js-1.0.2.tgz#adbc361d9c62df380125e7f161f71c826f1e490c" + integrity sha512-R0XvVJ9WusLiqTCEiGCmICCMplcCkIwwR11mOSD9CR5u+IXYdiseeEuXCVAjS54zqwkLcPNnmU4OeJ6tUrWhDw== + +source-map-support@^0.5.6: + version "0.5.21" + resolved "https://registry.yarnpkg.com/source-map-support/-/source-map-support-0.5.21.tgz#04fe7c7f9e1ed2d662233c28cb2b35b9f63f6e4f" + integrity sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w== + dependencies: + buffer-from "^1.0.0" + source-map "^0.6.0" + +source-map@^0.6.0, source-map@^0.6.1, source-map@~0.6.1: + version "0.6.1" + resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.6.1.tgz#74722af32e9614e9c287a8d0bbde48b5e2f1a263" + integrity sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g== + +source-map@^0.7.3: + version "0.7.4" + resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.7.4.tgz#a9bbe705c9d8846f4e08ff6765acf0f1b0898656" + integrity sha512-l3BikUxvPOcn5E74dZiq5BGsTb5yEwhaTSzccU6t4sDOH8NWJCstKO5QT2CvtFoK6F0saL7p9xHAqHOlCPJygA== + +sprintf-js@~1.0.2: + version "1.0.3" + resolved "https://registry.yarnpkg.com/sprintf-js/-/sprintf-js-1.0.3.tgz#04e6926f662895354f3dd015203633b857297e2c" + integrity sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g== + +stack-utils@^2.0.3: + version "2.0.6" + resolved "https://registry.yarnpkg.com/stack-utils/-/stack-utils-2.0.6.tgz#aaf0748169c02fc33c8232abccf933f54a1cc34f" + integrity sha512-XlkWvfIm6RmsWtNJx+uqtKLS8eqFbxUg0ZzLXqY0caEy9l7hruX8IpiDnjsLavoBgqCCR71TqWO8MaXYheJ3RQ== + dependencies: + escape-string-regexp "^2.0.0" + +string-argv@^0.3.1: + version "0.3.2" + resolved "https://registry.yarnpkg.com/string-argv/-/string-argv-0.3.2.tgz#2b6d0ef24b656274d957d54e0a4bbf6153dc02b6" + integrity sha512-aqD2Q0144Z+/RqG52NeHEkZauTAUWJO8c6yTftGJKO3Tja5tUgIfmIl6kExvhtxSDP7fXB6DvzkfMpCd/F3G+Q== + +string-length@^4.0.1: + version "4.0.2" + resolved "https://registry.yarnpkg.com/string-length/-/string-length-4.0.2.tgz#a8a8dc7bd5c1a82b9b3c8b87e125f66871b6e57a" + integrity sha512-+l6rNN5fYHNhZZy41RXsYptCjA2Igmq4EG7kZAYFQI1E1VTXarr6ZPXBg6eq7Y6eK4FEhY6AJlyuFIb/v/S0VQ== + dependencies: + char-regex "^1.0.2" + strip-ansi "^6.0.0" + +string-width@^4.1.0, string-width@^4.2.0, string-width@^4.2.3: + version "4.2.3" + resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.3.tgz#269c7117d27b05ad2e536830a8ec895ef9c6d010" + integrity sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g== + dependencies: + emoji-regex "^8.0.0" + is-fullwidth-code-point "^3.0.0" + strip-ansi "^6.0.1" + +string-width@^5.0.0: + version "5.1.2" + resolved "https://registry.yarnpkg.com/string-width/-/string-width-5.1.2.tgz#14f8daec6d81e7221d2a357e668cab73bdbca794" + integrity sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA== + dependencies: + eastasianwidth "^0.2.0" + emoji-regex "^9.2.2" + strip-ansi "^7.0.1" + +string.prototype.matchall@^4.0.8: + version "4.0.10" + resolved "https://registry.yarnpkg.com/string.prototype.matchall/-/string.prototype.matchall-4.0.10.tgz#a1553eb532221d4180c51581d6072cd65d1ee100" + integrity sha512-rGXbGmOEosIQi6Qva94HUjgPs9vKW+dkG7Y8Q5O2OYkWL6wFaTRZO8zM4mhP94uX55wgyrXzfS2aGtGzUL7EJQ== + dependencies: + call-bind "^1.0.2" + define-properties "^1.2.0" + es-abstract "^1.22.1" + get-intrinsic "^1.2.1" + has-symbols "^1.0.3" + internal-slot "^1.0.5" + regexp.prototype.flags "^1.5.0" + set-function-name "^2.0.0" + side-channel "^1.0.4" + +string.prototype.trim@^1.2.8: + version "1.2.8" + resolved "https://registry.yarnpkg.com/string.prototype.trim/-/string.prototype.trim-1.2.8.tgz#f9ac6f8af4bd55ddfa8895e6aea92a96395393bd" + integrity sha512-lfjY4HcixfQXOfaqCvcBuOIapyaroTXhbkfJN3gcB1OtyupngWK4sEET9Knd0cXd28kTUqu/kHoV4HKSJdnjiQ== + dependencies: + call-bind "^1.0.2" + define-properties "^1.2.0" + es-abstract "^1.22.1" + +string.prototype.trimend@^1.0.7: + version "1.0.7" + resolved "https://registry.yarnpkg.com/string.prototype.trimend/-/string.prototype.trimend-1.0.7.tgz#1bb3afc5008661d73e2dc015cd4853732d6c471e" + integrity sha512-Ni79DqeB72ZFq1uH/L6zJ+DKZTkOtPIHovb3YZHQViE+HDouuU4mBrLOLDn5Dde3RF8qw5qVETEjhu9locMLvA== + dependencies: + call-bind "^1.0.2" + define-properties "^1.2.0" + es-abstract "^1.22.1" + +string.prototype.trimstart@^1.0.7: + version "1.0.7" + resolved "https://registry.yarnpkg.com/string.prototype.trimstart/-/string.prototype.trimstart-1.0.7.tgz#d4cdb44b83a4737ffbac2d406e405d43d0184298" + integrity sha512-NGhtDFu3jCEm7B4Fy0DpLewdJQOZcQ0rGbwQ/+stjnrp2i+rlKeCvos9hOIeCmqwratM47OBxY7uFZzjxHXmrg== + dependencies: + call-bind "^1.0.2" + define-properties "^1.2.0" + es-abstract "^1.22.1" + +strip-ansi@^6.0.0, strip-ansi@^6.0.1: + version "6.0.1" + resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-6.0.1.tgz#9e26c63d30f53443e9489495b2105d37b67a85d9" + integrity sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A== + dependencies: + ansi-regex "^5.0.1" + +strip-ansi@^7.0.1: + version "7.1.0" + resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-7.1.0.tgz#d5b6568ca689d8561370b0707685d22434faff45" + integrity sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ== + dependencies: + ansi-regex "^6.0.1" + +strip-bom@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/strip-bom/-/strip-bom-3.0.0.tgz#2334c18e9c759f7bdd56fdef7e9ae3d588e68ed3" + integrity sha512-vavAMRXOgBVNF6nyEEmL3DBK19iRpDcoIwW+swQ+CbGiu7lju6t+JklA1MHweoWtadgt4ISVUsXLyDq34ddcwA== + +strip-bom@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/strip-bom/-/strip-bom-4.0.0.tgz#9c3505c1db45bcedca3d9cf7a16f5c5aa3901878" + integrity sha512-3xurFv5tEgii33Zi8Jtp55wEIILR9eh34FAW00PZf+JnSsTmV/ioewSgQl97JHvgjoRGwPShsWm+IdrxB35d0w== + +strip-final-newline@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/strip-final-newline/-/strip-final-newline-2.0.0.tgz#89b852fb2fcbe936f6f4b3187afb0a12c1ab58ad" + integrity sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA== + +strip-json-comments@^3.1.1: + version "3.1.1" + resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-3.1.1.tgz#31f1281b3832630434831c310c01cccda8cbe006" + integrity sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig== + +supports-color@^5.3.0: + version "5.5.0" + resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-5.5.0.tgz#e2e69a44ac8772f78a1ec0b35b689df6530efc8f" + integrity sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow== + dependencies: + has-flag "^3.0.0" + +supports-color@^7.0.0, supports-color@^7.1.0: + version "7.2.0" + resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-7.2.0.tgz#1b7dcdcb32b8138801b3e478ba6a51caa89648da" + integrity sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw== + dependencies: + has-flag "^4.0.0" + +supports-color@^8.0.0: + version "8.1.1" + resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-8.1.1.tgz#cd6fc17e28500cff56c1b86c0a7fd4a54a73005c" + integrity sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q== + dependencies: + has-flag "^4.0.0" + +supports-color@^9.2.2: + version "9.4.0" + resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-9.4.0.tgz#17bfcf686288f531db3dea3215510621ccb55954" + integrity sha512-VL+lNrEoIXww1coLPOmiEmK/0sGigko5COxI09KzHc2VJXJsQ37UaQ+8quuxjDeA7+KnLGTWRyOXSLLR2Wb4jw== + +supports-hyperlinks@^2.0.0: + version "2.3.0" + resolved "https://registry.yarnpkg.com/supports-hyperlinks/-/supports-hyperlinks-2.3.0.tgz#3943544347c1ff90b15effb03fc14ae45ec10624" + integrity sha512-RpsAZlpWcDwOPQA22aCH4J0t7L8JmAvsCxfOSEwm7cQs3LshN36QaTkwd70DnBOXDWGssw2eUoc8CaRWT0XunA== + dependencies: + has-flag "^4.0.0" + supports-color "^7.0.0" + +supports-preserve-symlinks-flag@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz#6eda4bd344a3c94aea376d4cc31bc77311039e09" + integrity sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w== + +symbol-tree@^3.2.4: + version "3.2.4" + resolved "https://registry.yarnpkg.com/symbol-tree/-/symbol-tree-3.2.4.tgz#430637d248ba77e078883951fb9aa0eed7c63fa2" + integrity sha512-9QNk5KwDF+Bvz+PyObkmSYjI5ksVUYtjW7AU22r2NKcfLJcXp96hkDWU3+XndOsUb+AQ9QhfzfCT2O+CNWT5Tw== + +terminal-link@^2.0.0: + version "2.1.1" + resolved "https://registry.yarnpkg.com/terminal-link/-/terminal-link-2.1.1.tgz#14a64a27ab3c0df933ea546fba55f2d078edc994" + integrity sha512-un0FmiRUQNr5PJqy9kP7c40F5BOfpGlYTrxonDChEZB7pzZxRNp/bt+ymiy9/npwXya9KH99nJ/GXFIiUkYGFQ== + dependencies: + ansi-escapes "^4.2.1" + supports-hyperlinks "^2.0.0" + +test-exclude@^6.0.0: + version "6.0.0" + resolved "https://registry.yarnpkg.com/test-exclude/-/test-exclude-6.0.0.tgz#04a8698661d805ea6fa293b6cb9e63ac044ef15e" + integrity sha512-cAGWPIyOHU6zlmg88jwm7VRyXnMN7iV68OGAbYDk/Mh/xC/pzVPlQtY6ngoIH/5/tciuhGfvESU8GrHrcxD56w== + dependencies: + "@istanbuljs/schema" "^0.1.2" + glob "^7.1.4" + minimatch "^3.0.4" + +text-table@^0.2.0: + version "0.2.0" + resolved "https://registry.yarnpkg.com/text-table/-/text-table-0.2.0.tgz#7f5ee823ae805207c00af2df4a84ec3fcfa570b4" + integrity sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw== + +throat@^6.0.1: + version "6.0.2" + resolved "https://registry.yarnpkg.com/throat/-/throat-6.0.2.tgz#51a3fbb5e11ae72e2cf74861ed5c8020f89f29fe" + integrity sha512-WKexMoJj3vEuK0yFEapj8y64V0A6xcuPuK9Gt1d0R+dzCSJc0lHqQytAbSB4cDAK0dWh4T0E2ETkoLE2WZ41OQ== + +through@^2.3.8: + version "2.3.8" + resolved "https://registry.yarnpkg.com/through/-/through-2.3.8.tgz#0dd4c9ffaabc357960b1b724115d7e0e86a2e1f5" + integrity sha512-w89qg7PI8wAdvX60bMDP+bFoD5Dvhm9oLheFp5O4a2QF0cSBGsBX4qZmadPMvVqlLJBBci+WqGGOAPvcDeNSVg== + +tmpl@1.0.5: + version "1.0.5" + resolved "https://registry.yarnpkg.com/tmpl/-/tmpl-1.0.5.tgz#8683e0b902bb9c20c4f726e3c0b69f36518c07cc" + integrity sha512-3f0uOEAQwIqGuWW2MVzYg8fV/QNnc/IpuJNG837rLuczAaLVHslWHZQj4IGiEl5Hs3kkbhwL9Ab7Hrsmuj+Smw== + +to-fast-properties@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/to-fast-properties/-/to-fast-properties-2.0.0.tgz#dc5e698cbd079265bc73e0377681a4e4e83f616e" + integrity sha512-/OaKK0xYrs3DmxRYqL/yDc+FxFUVYhDlXMhRmv3z915w2HF1tnN1omB354j8VUGO/hbRzyD6Y3sA7v7GS/ceog== + +to-regex-range@^5.0.1: + version "5.0.1" + resolved "https://registry.yarnpkg.com/to-regex-range/-/to-regex-range-5.0.1.tgz#1648c44aae7c8d988a326018ed72f5b4dd0392e4" + integrity sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ== + dependencies: + is-number "^7.0.0" + +tough-cookie@^4.0.0: + version "4.1.3" + resolved "https://registry.yarnpkg.com/tough-cookie/-/tough-cookie-4.1.3.tgz#97b9adb0728b42280aa3d814b6b999b2ff0318bf" + integrity sha512-aX/y5pVRkfRnfmuX+OdbSdXvPe6ieKX/G2s7e98f4poJHnqH3281gDPm/metm6E/WRamfx7WC4HUqkWHfQHprw== + dependencies: + psl "^1.1.33" + punycode "^2.1.1" + universalify "^0.2.0" + url-parse "^1.5.3" + +tr46@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/tr46/-/tr46-2.1.0.tgz#fa87aa81ca5d5941da8cbf1f9b749dc969a4e240" + integrity sha512-15Ih7phfcdP5YxqiB+iDtLoaTz4Nd35+IiAv0kQ5FNKHzXgdWqPoTIqEDDJmXceQt4JZk6lVPT8lnDlPpGDppw== + dependencies: + punycode "^2.1.1" + +tsconfig-paths@^3.14.2: + version "3.14.2" + resolved "https://registry.yarnpkg.com/tsconfig-paths/-/tsconfig-paths-3.14.2.tgz#6e32f1f79412decd261f92d633a9dc1cfa99f088" + integrity sha512-o/9iXgCYc5L/JxCHPe3Hvh8Q/2xm5Z+p18PESBU6Ff33695QnCHBEjcytY2q19ua7Mbl/DavtBOLq+oG0RCL+g== + dependencies: + "@types/json5" "^0.0.29" + json5 "^1.0.2" + minimist "^1.2.6" + strip-bom "^3.0.0" + +tslib@^1.8.1: + version "1.14.1" + resolved "https://registry.yarnpkg.com/tslib/-/tslib-1.14.1.tgz#cf2d38bdc34a134bcaf1091c41f6619e2f672d00" + integrity sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg== + +tslib@^2.1.0: + version "2.6.2" + resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.6.2.tgz#703ac29425e7b37cd6fd456e92404d46d1f3e4ae" + integrity sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q== + +tsutils@^3.21.0: + version "3.21.0" + resolved "https://registry.yarnpkg.com/tsutils/-/tsutils-3.21.0.tgz#b48717d394cea6c1e096983eed58e9d61715b623" + integrity sha512-mHKK3iUXL+3UF6xL5k0PEhKRUBKPBCv/+RkEOpjRWxxx27KKRBmmA60A9pgOUvMi8GKhRMPEmjBRPzs2W7O1OA== + dependencies: + tslib "^1.8.1" + +type-check@^0.4.0, type-check@~0.4.0: + version "0.4.0" + resolved "https://registry.yarnpkg.com/type-check/-/type-check-0.4.0.tgz#07b8203bfa7056c0657050e3ccd2c37730bab8f1" + integrity sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew== + dependencies: + prelude-ls "^1.2.1" + +type-detect@4.0.8: + version "4.0.8" + resolved "https://registry.yarnpkg.com/type-detect/-/type-detect-4.0.8.tgz#7646fb5f18871cfbb7749e69bd39a6388eb7450c" + integrity sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g== + +type-fest@^0.20.2: + version "0.20.2" + resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.20.2.tgz#1bf207f4b28f91583666cb5fbd327887301cd5f4" + integrity sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ== + +type-fest@^0.21.3: + version "0.21.3" + resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.21.3.tgz#d260a24b0198436e133fa26a524a6d65fa3b2e37" + integrity sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w== + +typed-array-buffer@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/typed-array-buffer/-/typed-array-buffer-1.0.0.tgz#18de3e7ed7974b0a729d3feecb94338d1472cd60" + integrity sha512-Y8KTSIglk9OZEr8zywiIHG/kmQ7KWyjseXs1CbSo8vC42w7hg2HgYTxSWwP0+is7bWDc1H+Fo026CpHFwm8tkw== + dependencies: + call-bind "^1.0.2" + get-intrinsic "^1.2.1" + is-typed-array "^1.1.10" + +typed-array-byte-length@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/typed-array-byte-length/-/typed-array-byte-length-1.0.0.tgz#d787a24a995711611fb2b87a4052799517b230d0" + integrity sha512-Or/+kvLxNpeQ9DtSydonMxCx+9ZXOswtwJn17SNLvhptaXYDJvkFFP5zbfU/uLmvnBJlI4yrnXRxpdWH/M5tNA== + dependencies: + call-bind "^1.0.2" + for-each "^0.3.3" + has-proto "^1.0.1" + is-typed-array "^1.1.10" + +typed-array-byte-offset@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/typed-array-byte-offset/-/typed-array-byte-offset-1.0.0.tgz#cbbe89b51fdef9cd6aaf07ad4707340abbc4ea0b" + integrity sha512-RD97prjEt9EL8YgAgpOkf3O4IF9lhJFr9g0htQkm0rchFp/Vx7LW5Q8fSXXub7BXAODyUQohRMyOc3faCPd0hg== + dependencies: + available-typed-arrays "^1.0.5" + call-bind "^1.0.2" + for-each "^0.3.3" + has-proto "^1.0.1" + is-typed-array "^1.1.10" + +typed-array-length@^1.0.4: + version "1.0.4" + resolved "https://registry.yarnpkg.com/typed-array-length/-/typed-array-length-1.0.4.tgz#89d83785e5c4098bec72e08b319651f0eac9c1bb" + integrity sha512-KjZypGq+I/H7HI5HlOoGHkWUUGq+Q0TPhQurLbyrVrvnKTBgzLhIJ7j6J/XTQOi0d1RjyZ0wdas8bKs2p0x3Ng== + dependencies: + call-bind "^1.0.2" + for-each "^0.3.3" + is-typed-array "^1.1.9" + +typedarray-to-buffer@^3.1.5: + version "3.1.5" + resolved "https://registry.yarnpkg.com/typedarray-to-buffer/-/typedarray-to-buffer-3.1.5.tgz#a97ee7a9ff42691b9f783ff1bc5112fe3fca9080" + integrity sha512-zdu8XMNEDepKKR+XYOXAVPtWui0ly0NtohUscw+UmaHiAWT8hrV1rr//H6V+0DvJ3OQ19S979M0laLfX8rm82Q== + dependencies: + is-typedarray "^1.0.0" + +unbox-primitive@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/unbox-primitive/-/unbox-primitive-1.0.2.tgz#29032021057d5e6cdbd08c5129c226dff8ed6f9e" + integrity sha512-61pPlCD9h51VoreyJ0BReideM3MDKMKnh6+V9L08331ipq6Q8OFXZYiqP6n/tbHx4s5I9uRhcye6BrbkizkBDw== + dependencies: + call-bind "^1.0.2" + has-bigints "^1.0.2" + has-symbols "^1.0.3" + which-boxed-primitive "^1.0.2" + +undici-types@~5.26.4: + version "5.26.5" + resolved "https://registry.yarnpkg.com/undici-types/-/undici-types-5.26.5.tgz#bcd539893d00b56e964fd2657a4866b221a65617" + integrity sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA== + +universalify@^0.2.0: + version "0.2.0" + resolved "https://registry.yarnpkg.com/universalify/-/universalify-0.2.0.tgz#6451760566fa857534745ab1dde952d1b1761be0" + integrity sha512-CJ1QgKmNg3CwvAv/kOFmtnEN05f0D/cn9QntgNOQlQF9dgvVTHj3t+8JPdjqawCHk7V/KA+fbUqzZ9XWhcqPUg== + +update-browserslist-db@^1.0.13: + version "1.0.13" + resolved "https://registry.yarnpkg.com/update-browserslist-db/-/update-browserslist-db-1.0.13.tgz#3c5e4f5c083661bd38ef64b6328c26ed6c8248c4" + integrity sha512-xebP81SNcPuNpPP3uzeW1NYXxI3rxyJzF3pD6sH4jE7o/IX+WtSpwnVU+qIsDPyk0d3hmFQ7mjqc6AtV604hbg== + dependencies: + escalade "^3.1.1" + picocolors "^1.0.0" + +uri-js@^4.2.2: + version "4.4.1" + resolved "https://registry.yarnpkg.com/uri-js/-/uri-js-4.4.1.tgz#9b1a52595225859e55f669d928f88c6c57f2a77e" + integrity sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg== + dependencies: + punycode "^2.1.0" + +url-parse@^1.5.3: + version "1.5.10" + resolved "https://registry.yarnpkg.com/url-parse/-/url-parse-1.5.10.tgz#9d3c2f736c1d75dd3bd2be507dcc111f1e2ea9c1" + integrity sha512-WypcfiRhfeUP9vvF0j6rw0J3hrWrw6iZv3+22h6iRMJ/8z1Tj6XfLP4DsUix5MhMPnXpiHDoKyoZ/bdCkwBCiQ== + dependencies: + querystringify "^2.1.1" + requires-port "^1.0.0" + +util-deprecate@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/util-deprecate/-/util-deprecate-1.0.2.tgz#450d4dc9fa70de732762fbd2d4a28981419a0ccf" + integrity sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw== + +v8-to-istanbul@^8.1.0: + version "8.1.1" + resolved "https://registry.yarnpkg.com/v8-to-istanbul/-/v8-to-istanbul-8.1.1.tgz#77b752fd3975e31bbcef938f85e9bd1c7a8d60ed" + integrity sha512-FGtKtv3xIpR6BYhvgH8MI/y78oT7d8Au3ww4QIxymrCtZEh5b8gCw2siywE+puhEmuWKDtmfrvF5UlB298ut3w== + dependencies: + "@types/istanbul-lib-coverage" "^2.0.1" + convert-source-map "^1.6.0" + source-map "^0.7.3" + +w3c-hr-time@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/w3c-hr-time/-/w3c-hr-time-1.0.2.tgz#0a89cdf5cc15822df9c360543676963e0cc308cd" + integrity sha512-z8P5DvDNjKDoFIHK7q8r8lackT6l+jo/Ye3HOle7l9nICP9lf1Ci25fy9vHd0JOWewkIFzXIEig3TdKT7JQ5fQ== + dependencies: + browser-process-hrtime "^1.0.0" + +w3c-xmlserializer@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/w3c-xmlserializer/-/w3c-xmlserializer-2.0.0.tgz#3e7104a05b75146cc60f564380b7f683acf1020a" + integrity sha512-4tzD0mF8iSiMiNs30BiLO3EpfGLZUT2MSX/G+o7ZywDzliWQ3OPtTZ0PTC3B3ca1UAf4cJMHB+2Bf56EriJuRA== + dependencies: + xml-name-validator "^3.0.0" + +wait-on@^7.0.0: + version "7.2.0" + resolved "https://registry.yarnpkg.com/wait-on/-/wait-on-7.2.0.tgz#d76b20ed3fc1e2bebc051fae5c1ff93be7892928" + integrity sha512-wCQcHkRazgjG5XoAq9jbTMLpNIjoSlZslrJ2+N9MxDsGEv1HnFoVjOCexL0ESva7Y9cu350j+DWADdk54s4AFQ== + dependencies: + axios "^1.6.1" + joi "^17.11.0" + lodash "^4.17.21" + minimist "^1.2.8" + rxjs "^7.8.1" + +walker@^1.0.7: + version "1.0.8" + resolved "https://registry.yarnpkg.com/walker/-/walker-1.0.8.tgz#bd498db477afe573dc04185f011d3ab8a8d7653f" + integrity sha512-ts/8E8l5b7kY0vlWLewOkDXMmPdLcVV4GmOQLyxuSswIJsweeFZtAsMF7k1Nszz+TYBQrlYRmzOnr398y1JemQ== + dependencies: + makeerror "1.0.12" + +webidl-conversions@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/webidl-conversions/-/webidl-conversions-5.0.0.tgz#ae59c8a00b121543a2acc65c0434f57b0fc11aff" + integrity sha512-VlZwKPCkYKxQgeSbH5EyngOmRp7Ww7I9rQLERETtf5ofd9pGeswWiOtogpEO850jziPRarreGxn5QIiTqpb2wA== + +webidl-conversions@^6.1.0: + version "6.1.0" + resolved "https://registry.yarnpkg.com/webidl-conversions/-/webidl-conversions-6.1.0.tgz#9111b4d7ea80acd40f5270d666621afa78b69514" + integrity sha512-qBIvFLGiBpLjfwmYAaHPXsn+ho5xZnGvyGvsarywGNc8VyQJUMHJ8OBKGGrPER0okBeMDaan4mNBlgBROxuI8w== + +whatwg-encoding@^1.0.5: + version "1.0.5" + resolved "https://registry.yarnpkg.com/whatwg-encoding/-/whatwg-encoding-1.0.5.tgz#5abacf777c32166a51d085d6b4f3e7d27113ddb0" + integrity sha512-b5lim54JOPN9HtzvK9HFXvBma/rnfFeqsic0hSpjtDbVxR3dJKLc+KB4V6GgiGOvl7CY/KNh8rxSo9DKQrnUEw== + dependencies: + iconv-lite "0.4.24" + +whatwg-mimetype@^2.3.0: + version "2.3.0" + resolved "https://registry.yarnpkg.com/whatwg-mimetype/-/whatwg-mimetype-2.3.0.tgz#3d4b1e0312d2079879f826aff18dbeeca5960fbf" + integrity sha512-M4yMwr6mAnQz76TbJm914+gPpB/nCwvZbJU28cUD6dR004SAxDLOOSUaB1JDRqLtaOV/vi0IC5lEAGFgrjGv/g== + +whatwg-url@^8.0.0, whatwg-url@^8.5.0: + version "8.7.0" + resolved "https://registry.yarnpkg.com/whatwg-url/-/whatwg-url-8.7.0.tgz#656a78e510ff8f3937bc0bcbe9f5c0ac35941b77" + integrity sha512-gAojqb/m9Q8a5IV96E3fHJM70AzCkgt4uXYX2O7EmuyOnLrViCQlsEBmF9UQIu3/aeAIp2U17rtbpZWNntQqdg== + dependencies: + lodash "^4.7.0" + tr46 "^2.1.0" + webidl-conversions "^6.1.0" + +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" + integrity sha512-bwZdv0AKLpplFY2KZRX6TvyuN7ojjr7lwkg6ml0roIy9YeuSr7JS372qlNW18UQYzgYK9ziGcerWqZOmEn9VNg== + dependencies: + is-bigint "^1.0.1" + is-boolean-object "^1.1.0" + is-number-object "^1.0.4" + is-string "^1.0.5" + is-symbol "^1.0.3" + +which-typed-array@^1.1.11, which-typed-array@^1.1.13: + version "1.1.13" + resolved "https://registry.yarnpkg.com/which-typed-array/-/which-typed-array-1.1.13.tgz#870cd5be06ddb616f504e7b039c4c24898184d36" + integrity sha512-P5Nra0qjSncduVPEAr7xhoF5guty49ArDTwzJ/yNuPIbZppyRxFQsRCWrocxIY+CnMVG+qfbU2FmDKyvSGClow== + dependencies: + available-typed-arrays "^1.0.5" + call-bind "^1.0.4" + for-each "^0.3.3" + gopd "^1.0.1" + has-tostringtag "^1.0.0" + +which@^2.0.1: + version "2.0.2" + resolved "https://registry.yarnpkg.com/which/-/which-2.0.2.tgz#7c6a8dd0a636a0327e10b59c9286eee93f3f51b1" + integrity sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA== + dependencies: + isexe "^2.0.0" + +wrap-ansi@^6.2.0: + version "6.2.0" + resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-6.2.0.tgz#e9393ba07102e6c91a3b221478f0257cd2856e53" + integrity sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA== + dependencies: + ansi-styles "^4.0.0" + string-width "^4.1.0" + strip-ansi "^6.0.0" + +wrap-ansi@^7.0.0: + version "7.0.0" + resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-7.0.0.tgz#67e145cff510a6a6984bdf1152911d69d2eb9e43" + integrity sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q== + dependencies: + ansi-styles "^4.0.0" + string-width "^4.1.0" + strip-ansi "^6.0.0" + +wrappy@1: + version "1.0.2" + resolved "https://registry.yarnpkg.com/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f" + integrity sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ== + +write-file-atomic@^3.0.0: + version "3.0.3" + resolved "https://registry.yarnpkg.com/write-file-atomic/-/write-file-atomic-3.0.3.tgz#56bd5c5a5c70481cd19c571bd39ab965a5de56e8" + integrity sha512-AvHcyZ5JnSfq3ioSyjrBkH9yW4m7Ayk8/9My/DD9onKeu/94fwrMocemO2QAJFAlnnDN+ZDS+ZjAR5ua1/PV/Q== + dependencies: + imurmurhash "^0.1.4" + is-typedarray "^1.0.0" + signal-exit "^3.0.2" + typedarray-to-buffer "^3.1.5" + +ws@^7.4.6: + version "7.5.9" + resolved "https://registry.yarnpkg.com/ws/-/ws-7.5.9.tgz#54fa7db29f4c7cec68b1ddd3a89de099942bb591" + integrity sha512-F+P9Jil7UiSKSkppIiD94dN07AwvFixvLIj1Og1Rl9GGMuNipJnV9JzjD6XuqmAeiswGvUmNLjr5cFuXwNS77Q== + +xml-name-validator@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/xml-name-validator/-/xml-name-validator-3.0.0.tgz#6ae73e06de4d8c6e47f9fb181f78d648ad457c6a" + integrity sha512-A5CUptxDsvxKJEU3yO6DuWBSJz/qizqzJKOMIfUJHETbBw/sFaDxgd6fxm1ewUaM0jZ444Fc5vC5ROYurg/4Pw== + +xmlchars@^2.2.0: + version "2.2.0" + resolved "https://registry.yarnpkg.com/xmlchars/-/xmlchars-2.2.0.tgz#060fe1bcb7f9c76fe2a17db86a9bc3ab894210cb" + integrity sha512-JZnDKK8B0RCDw84FNdDAIpZK+JuJw+s7Lz8nksI7SIuU3UXJJslUthsi+uWBUYOwPFwW7W7PRLRfUKpxjtjFCw== + +y18n@^5.0.5: + version "5.0.8" + resolved "https://registry.yarnpkg.com/y18n/-/y18n-5.0.8.tgz#7f4934d0f7ca8c56f95314939ddcd2dd91ce1d55" + integrity sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA== + +yallist@^3.0.2: + version "3.1.1" + resolved "https://registry.yarnpkg.com/yallist/-/yallist-3.1.1.tgz#dbb7daf9bfd8bac9ab45ebf602b8cbad0d5d08fd" + integrity sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g== + +yallist@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/yallist/-/yallist-4.0.0.tgz#9bb92790d9c0effec63be73519e11a35019a3a72" + integrity sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A== + +yaml@^1.10.2: + version "1.10.2" + resolved "https://registry.yarnpkg.com/yaml/-/yaml-1.10.2.tgz#2301c5ffbf12b467de8da2333a459e29e7920e4b" + integrity sha512-r3vXyErRCYJ7wg28yvBY5VSoAF8ZvlcW9/BwUzEtUsjvX/DKs24dIkuwjtuprwJJHsbyUbLApepYTR1BN4uHrg== + +yargs-parser@^20.2.2: + version "20.2.9" + resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-20.2.9.tgz#2eb7dc3b0289718fc295f362753845c41a0c94ee" + integrity sha512-y11nGElTIV+CT3Zv9t7VKl+Q3hTQoT9a1Qzezhhl6Rp21gJ/IVTW7Z3y9EWXhuUBC2Shnf+DX0antecpAwSP8w== + +yargs-parser@^21.1.1: + version "21.1.1" + resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-21.1.1.tgz#9096bceebf990d21bb31fa9516e0ede294a77d35" + integrity sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw== + +yargs@^16.2.0: + version "16.2.0" + resolved "https://registry.yarnpkg.com/yargs/-/yargs-16.2.0.tgz#1c82bf0f6b6a66eafce7ef30e376f49a12477f66" + integrity sha512-D1mvvtDG0L5ft/jGWkLpG1+m0eQxOfaBvTNELraWj22wSVUMWxZUvYgJYcKh6jGGIkJFhH4IZPQhR4TKpc8mBw== + dependencies: + cliui "^7.0.2" + escalade "^3.1.1" + get-caller-file "^2.0.5" + require-directory "^2.1.1" + string-width "^4.2.0" + y18n "^5.0.5" + yargs-parser "^20.2.2" + +yargs@~17.6.2: + version "17.6.2" + resolved "https://registry.yarnpkg.com/yargs/-/yargs-17.6.2.tgz#2e23f2944e976339a1ee00f18c77fedee8332541" + integrity sha512-1/9UrdHjDZc0eOU0HxOHoS78C69UD3JRMvzlJ7S79S2nTaWRA/whGCTV8o9e/N/1Va9YIV7Q4sOxD8VV4pCWOw== + dependencies: + cliui "^8.0.1" + escalade "^3.1.1" + get-caller-file "^2.0.5" + require-directory "^2.1.1" + string-width "^4.2.3" + y18n "^5.0.5" + yargs-parser "^21.1.1" + +yocto-queue@^0.1.0: + version "0.1.0" + resolved "https://registry.yarnpkg.com/yocto-queue/-/yocto-queue-0.1.0.tgz#0294eb3dee05028d31ee1a5fa2c556a6aaf10a1b" + integrity sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==