From 94fc7d1a8241040dd72b32a0b2bf1f7247608a66 Mon Sep 17 00:00:00 2001 From: Oleksii Golub Date: Tue, 2 Jan 2024 23:50:41 +0200 Subject: [PATCH 1/4] update example folder --- .../classes/B2BSyncCheckInventory.cls | 48 +- .../B2BSyncCheckInventory.cls-meta.xml | 2 +- .../classes/B2BSyncCheckInventoryTest.cls | 33 - .../B2BSyncCheckInventoryTest.cls-meta.xml | 2 +- .../checkout-main/classes/B2BSyncDelivery.cls | 38 +- .../classes/B2BSyncDelivery.cls-meta.xml | 2 +- .../classes/B2BSyncDeliveryTest.cls-meta.xml | 2 +- .../checkout-main/classes/B2BSyncPricing.cls | 56 +- .../classes/B2BSyncPricing.cls-meta.xml | 2 +- .../classes/B2BSyncPricingTest.cls-meta.xml | 2 +- examples/checkout-main/classes/B2BSyncTax.cls | 324 +++--- .../flows/Checkout_Main_Checkout.flow | 2 +- ...ith_Salesforce_Pricing_and_Promotions.flow | 2 +- examples/checkout-main/readme.md | 16 +- examples/checkout-reentrant/README.md | 17 +- .../classes/B2BCheckInventorySample.cls | 63 +- .../B2BCheckInventorySample.cls-meta.xml | 2 +- .../classes/B2BCheckInventorySampleTest.cls | 66 +- .../B2BCheckInventorySampleTest.cls-meta.xml | 2 +- .../classes/B2BDeliverySample.cls | 59 +- .../classes/B2BDeliverySample.cls-meta.xml | 2 +- .../classes/B2BDeliverySampleTest.cls | 48 +- .../B2BDeliverySampleTest.cls-meta.xml | 2 +- .../integrations/classes/B2BPricingSample.cls | 88 +- .../classes/B2BPricingSample.cls-meta.xml | 2 +- .../classes/B2BPricingSampleTest.cls | 50 +- .../classes/B2BPricingSampleTest.cls-meta.xml | 2 +- .../integrations/classes/B2BTaxSample.cls | 50 +- .../classes/B2BTaxSample.cls-meta.xml | 2 +- .../integrations/classes/B2BTaxSampleTest.cls | 61 +- .../classes/B2BTaxSampleTest.cls-meta.xml | 2 +- .../Heroku_test_for_B2B_lightning.remoteSite | 2 +- .../Salesforce.namedCredential | 3 +- examples/lwc/README.md | 14 +- .../billingAddressSelector.js | 2 +- .../lwc/cardPaymentMethod/constants.js | 4 +- .../navigationButtons.js-meta.xml | 2 +- .../default/lwc/paymentMethod/constants.js | 4 +- .../lwc/paymentMethod/paymentMethod.html | 16 +- .../lwc/paymentMethod/paymentMethod.js | 69 +- .../paymentMethod/paymentMethod.js-meta.xml | 2 +- examples/lwc/yarn.lock | 1017 ++++++++++++----- .../users/sharing-settings-setup/package.xml | 4 + 43 files changed, 1326 insertions(+), 862 deletions(-) diff --git a/examples/checkout-main/classes/B2BSyncCheckInventory.cls b/examples/checkout-main/classes/B2BSyncCheckInventory.cls index ad7da9e0..1d3cc3c2 100644 --- a/examples/checkout-main/classes/B2BSyncCheckInventory.cls +++ b/examples/checkout-main/classes/B2BSyncCheckInventory.cls @@ -1,5 +1,9 @@ // This class verifies that there is sufficient inventory to cover the buyer's order global with sharing class B2BSyncCheckInventory { + // You MUST change this to be your service or you must launch your own Heroku Service + // and add the host in Setup | Security | Remote site settings. + private static String httpHost = 'https://example.com'; + private static Boolean useHTTPService = false; // This invocable method only expects one ID @InvocableMethod(callout=true label='Ensure sufficient inventory' description='Runs a synchronous version of check inventory' category='B2B Commerce') public static void syncCheckInventory(List cartIds) { @@ -34,8 +38,15 @@ global with sharing class B2BSyncCheckInventory { throw new CalloutException(errorMessage); } - // Get all available quantities for products in the cart (cart items) from an external service. - Map quantitiesFromExternalService = getQuantitiesFromExternalService(cartId, quantitiesFromSalesforce.keySet()); + // Following snippet of code fetches a mocked static json response from getQuantitiesFromStaticResponse. + // Another example that demonstrates how to call a live 3rd party HTTP Service to fetch the desired + // response is implemented in getQuantitiesFromExternalService method. + Map quantitiesFromExternalService = null; + if(useHTTPService) { + quantitiesFromExternalService = getQuantitiesFromExternalService(cartId, quantitiesFromSalesforce.keySet()); + } else { + quantitiesFromExternalService = getQuantitiesFromStaticResponse(cartId, quantitiesFromSalesforce.keySet()); + } // For each cart item SKU, check that the quantity from the external service // is greater or equal to the quantity in the cart. @@ -57,11 +68,26 @@ global with sharing class B2BSyncCheckInventory { } } } + + private static Map getQuantitiesFromStaticResponse(ID cartId, Set skus) { + if (skus.isEmpty()) { + return (Map) JSON.deserializeUntyped('{"error":"Input SKUs list is empty or undefined."}'); + } + String responseJson = '{'; + for (String sku : skus) { + responseJson = responseJson + '"'+sku+'"'; + responseJson = responseJson + ':'; + responseJson = responseJson + '9999.00'; + responseJson = responseJson + ','; + } + responseJson = responseJson.removeEnd(',') + '}'; + return (Map) JSON.deserializeUntyped(responseJson); + } private static Map getQuantitiesFromExternalService (ID cartId, Set skus) { Http http = new Http(); HttpRequest request = new HttpRequest(); - Integer SuccessfulHttpRequest = 200; + Integer successfulHttpRequest = 200; // Encode the product SKUs to avoid any invalid characters in the request URL. Set encodedSkus = new Set(); @@ -69,8 +95,7 @@ global with sharing class B2BSyncCheckInventory { encodedSkus.add(EncodingUtil.urlEncode(sku, 'UTF-8')); } - // To access the service below, add endpoint = https://b2b-commerce-test.herokuapp.com in Setup | Security | Remote site settings. - request.setEndpoint('https://b2b-commerce-test.herokuapp.com/get-inventory?skus=' + JSON.serialize(encodedSkus)); + request.setEndpoint(httpHost + '/get-inventory?skus=' + JSON.serialize(encodedSkus)); request.setMethod('GET'); HttpResponse response = http.send(request); // If the request is successful, parse the JSON response. @@ -80,16 +105,15 @@ global with sharing class B2BSyncCheckInventory { // The external service returns the exact list of SKUs it receives // and an available quantity of 9999 for each SKU. // If the cart has an item with a quantity higher than 9999, the integration returns an error. - if (response.getStatusCode() == SuccessfulHttpRequest) { + if (response.getStatusCode() == successfulHttpRequest) { Map quantitiesFromExternalService = (Map) JSON.deserializeUntyped(response.getBody()); return quantitiesFromExternalService; + } else if(response.getStatusCode() == 404) { + throw new CalloutException ('404. You must create a sample application or add your own service which returns a valid response'); + } else { + throw new CalloutException ('There was a problem with the request. Error: ' + response.getStatusCode()); } - else { - String errorMessage = 'There was a problem with the request. Error: ' + response.getStatusCode(); - // Sync non-user errors skip saveCartValidationOutputError - throw new CalloutException(errorMessage); - } - } + } private static void saveCartValidationOutputError(String errorMessage, Id cartId) { // To propagate the error to the user, we need to add a new CartValidationOutput record. diff --git a/examples/checkout-main/classes/B2BSyncCheckInventory.cls-meta.xml b/examples/checkout-main/classes/B2BSyncCheckInventory.cls-meta.xml index 4b0bc9f3..dd61d1f9 100644 --- a/examples/checkout-main/classes/B2BSyncCheckInventory.cls-meta.xml +++ b/examples/checkout-main/classes/B2BSyncCheckInventory.cls-meta.xml @@ -1,5 +1,5 @@ - 55.0 + 52.0 Active diff --git a/examples/checkout-main/classes/B2BSyncCheckInventoryTest.cls b/examples/checkout-main/classes/B2BSyncCheckInventoryTest.cls index c998bf25..031e750d 100644 --- a/examples/checkout-main/classes/B2BSyncCheckInventoryTest.cls +++ b/examples/checkout-main/classes/B2BSyncCheckInventoryTest.cls @@ -14,45 +14,12 @@ public class B2BSyncCheckInventoryTest { } @isTest static void testWhenExternalServiceQuantityIsLargerThanTheCartItemQuantityASuccessStatusIsReturned() { - // Because test methods do not support Web service callouts, we create a mock response based on a static resource. - // To create the static resource from the Developer Console, select File | New | Static Resource - StaticResourceCalloutMock mock = new StaticResourceCalloutMock(); - mock.setStaticResource('GetInventoryResource'); - mock.setStatusCode(200); - mock.setHeader('Content-Type', 'application/json;charset=UTF-8'); Test.startTest(); - // Associate the callout with a mock response. - Test.setMock(HttpCalloutMock.class, mock); - // Test: execute the integration for the test cart ID. WebCart webCart = [SELECT Id FROM WebCart WHERE Name = 'Cart' LIMIT 1]; List webCarts = new List{webCart.Id}; B2BSyncCheckInventory.syncCheckInventory(webCarts); - // No status is returned from the syncCheckInventory check, but if no exception is thrown, the test passes - - Test.stopTest(); - } - - @isTest static void testWhenExternalServiceCallFailsAFailedStatusIsReturnedAndACartValidationOutputEntryIsNotCreated() { - // Because test methods do not support Web service callouts, we create a mock response based on a static resource. - // To create the static resource from the Developer Console, select File | New | Static Resource - StaticResourceCalloutMock mock = new StaticResourceCalloutMock(); - mock.setStaticResource('GetInventoryResource'); - // The web service call returns an error code. - mock.setStatusCode(404); - mock.setHeader('Content-Type', 'application/json;charset=UTF-8'); - Test.startTest(); - // Associate the callout with a mock response. - Test.setMock(HttpCalloutMock.class, mock); - - // Test: execute the integration for the test cart ID. - WebCart webCart = [SELECT Id FROM WebCart WHERE Name = 'Cart' LIMIT 1]; - List webCarts = new List{webCart.Id}; - - String expectedErrorMessage = 'There was a problem with the request. Error: 404'; - executeAndEnsureFailure(expectedErrorMessage, webCarts, false); - Test.stopTest(); } diff --git a/examples/checkout-main/classes/B2BSyncCheckInventoryTest.cls-meta.xml b/examples/checkout-main/classes/B2BSyncCheckInventoryTest.cls-meta.xml index 4b0bc9f3..dd61d1f9 100644 --- a/examples/checkout-main/classes/B2BSyncCheckInventoryTest.cls-meta.xml +++ b/examples/checkout-main/classes/B2BSyncCheckInventoryTest.cls-meta.xml @@ -1,5 +1,5 @@ - 55.0 + 52.0 Active diff --git a/examples/checkout-main/classes/B2BSyncDelivery.cls b/examples/checkout-main/classes/B2BSyncDelivery.cls index 89b90999..8081f679 100644 --- a/examples/checkout-main/classes/B2BSyncDelivery.cls +++ b/examples/checkout-main/classes/B2BSyncDelivery.cls @@ -1,6 +1,10 @@ // This class determines if we can ship to the buyer's shipping address and creates // CartDeliveryGroupMethods for the different options and prices the buyer may choose from public class B2BSyncDelivery { + // You MUST change this to be your service or you must launch your own Heroku Service + // and add the host in Setup | Security | Remote site settings. + private static String httpHost = 'https://example.com'; + private static Boolean useHTTPService = false; // This invocable method only expects one ID @InvocableMethod(callout=true label='Prepare the Delivery Method Options' description='Runs a synchronous version of delivery method preparation' category='B2B Commerce') public static void syncDelivery(List cartIds) { @@ -24,8 +28,13 @@ public class B2BSyncDelivery { // Used to increase the cost by a multiple of the number of items in the cart (useful for testing but should not be done in the final code) Integer numberOfUniqueItems = [SELECT count() from cartItem WHERE CartId = :cartId WITH SECURITY_ENFORCED]; - // Get shipping options, including aspects like rates and carriers, from the external service. - ShippingOptionsAndRatesFromExternalService[] shippingOptionsAndRatesFromExternalService = getShippingOptionsAndRatesFromExternalService(cartId, numberOfUniqueItems); + // Both implementations are just samples returning hardcoded Shipping options and MUST not be used in production systems. + ShippingOptionsAndRatesFromExternalService[] shippingOptionsAndRatesFromExternalService = null; + if(useHTTPService) { + shippingOptionsAndRatesFromExternalService = getShippingOptionsAndRatesFromExternalService(cartId, numberOfUniqueItems); + } else { + shippingOptionsAndRatesFromExternalService = getShippingOptionsAndRatesFromMockedService(cartId, numberOfUniqueItems); + } // On re-entry of the checkout flow delete all previous CartDeliveryGroupMethods for the given cartDeliveryGroupId delete [SELECT Id FROM CartDeliveryGroupMethod WHERE CartDeliveryGroupId = :cartDeliveryGroupId WITH SECURITY_ENFORCED]; @@ -58,13 +67,8 @@ public class B2BSyncDelivery { } } - // Don't hit Heroku Server: You can uncomment out this if you want to remove the Heroku Service from this class. Comment out the - // method below instead. - /* - private static ShippingOptionsAndRatesFromExternalService[] getShippingOptionsAndRatesFromExternalService (String id, Integer numberOfUniqueItems) { - // Don't actually call heroku + private static ShippingOptionsAndRatesFromExternalService[] getShippingOptionsAndRatesFromMockedService (String id, Integer numberOfUniqueItems) { ShippingOptionsAndRatesFromExternalService[] shippingOptions = new List(); - // To access the service below, you may need to add endpoint = https://b2b-commerce-test.herokuapp.com in Setup | Security | Remote site settings. // If the request is successful, parse the JSON response. // The response looks like this: // [{"status":"calculated","rate":{"name":"Delivery Method 1","serviceName":"Test Carrier 1","serviceCode":"SNC9600","shipmentCost":11.99,"otherCost":5.99}}, @@ -84,18 +88,17 @@ public class B2BSyncDelivery { )); } return shippingOptions; - }*/ + } // Do hit Heroku Server: You can comment this out and uncomment out the above class if you don't want to hit the Heroku Service. private static ShippingOptionsAndRatesFromExternalService[] getShippingOptionsAndRatesFromExternalService (String cartId, Integer numberOfUniqueItems) { - final Integer SuccessfulHttpRequest = 200; + final Integer successfulHttpRequest = 200; ShippingOptionsAndRatesFromExternalService[] shippingOptions = new List(); Http http = new Http(); HttpRequest request = new HttpRequest(); - // To access the service below, you may need to add endpoint = https://b2b-commerce-test.herokuapp.com in Setup | Security | Remote site settings. - request.setEndpoint('https://b2b-commerce-test.herokuapp.com/calculate-shipping-rates-winter-21'); + request.setEndpoint(httpHost + '/calculate-shipping-rates-winter-21'); request.setMethod('GET'); HttpResponse response = http.send(request); @@ -103,7 +106,7 @@ public class B2BSyncDelivery { // The response looks like this: // [{"status":"calculated","rate":{"name":"Delivery Method 1","serviceName":"Test Carrier 1","serviceCode":"SNC9600","shipmentCost":11.99,"otherCost":5.99}}, // {"status":"calculated","rate":{"name":"Delivery Method 2","serviceName":"Test Carrier 2","serviceCode":"SNC9600","shipmentCost":15.99,"otherCost":6.99}}] - if (response.getStatusCode() == SuccessfulHttpRequest) { + if (response.getStatusCode() == successfulHttpRequest) { List results = (List) JSON.deserializeUntyped(response.getBody()); for (Object result: results) { Map subresult = (Map) result; @@ -117,11 +120,10 @@ public class B2BSyncDelivery { )); } return shippingOptions; - } - else { - String errorMessage = 'There was a problem with the request. Error: ' + response.getStatusCode(); - // Sync non-user errors skip saveCartValidationOutputError - throw new CalloutException (errorMessage); + } else if(response.getStatusCode() == 404) { + throw new CalloutException ('404. You must create a sample application or add your own service which returns a valid response'); + } else { + throw new CalloutException ('There was a problem with the request. Error: ' + response.getStatusCode()); } } diff --git a/examples/checkout-main/classes/B2BSyncDelivery.cls-meta.xml b/examples/checkout-main/classes/B2BSyncDelivery.cls-meta.xml index 4b0bc9f3..dd61d1f9 100644 --- a/examples/checkout-main/classes/B2BSyncDelivery.cls-meta.xml +++ b/examples/checkout-main/classes/B2BSyncDelivery.cls-meta.xml @@ -1,5 +1,5 @@ - 55.0 + 52.0 Active diff --git a/examples/checkout-main/classes/B2BSyncDeliveryTest.cls-meta.xml b/examples/checkout-main/classes/B2BSyncDeliveryTest.cls-meta.xml index 4b0bc9f3..dd61d1f9 100644 --- a/examples/checkout-main/classes/B2BSyncDeliveryTest.cls-meta.xml +++ b/examples/checkout-main/classes/B2BSyncDeliveryTest.cls-meta.xml @@ -1,5 +1,5 @@ - 55.0 + 52.0 Active diff --git a/examples/checkout-main/classes/B2BSyncPricing.cls b/examples/checkout-main/classes/B2BSyncPricing.cls index 5d0ef470..e9251ed8 100644 --- a/examples/checkout-main/classes/B2BSyncPricing.cls +++ b/examples/checkout-main/classes/B2BSyncPricing.cls @@ -1,6 +1,10 @@ // This sample is for the situation when the pricing is validated in an external service. // For Salesforce internal price validation please see the corresponding documentation. public with sharing class B2BSyncPricing { + // You MUST change this to be your service or you must launch your own Heroku Service + // and add the host in Setup | Security | Remote site settings. + private static String httpHost = 'https://example.com'; + private static Boolean useHTTPService = false; // This invocable method only expects one ID @InvocableMethod(callout=true label='Price the cart' description='Runs a synchronous version of pricing' category='B2B Commerce') public static void syncPricing(List cartIds) { @@ -34,11 +38,17 @@ public with sharing class B2BSyncPricing { } salesPricesFromSalesforce.put(cartItem.Sku, cartItem.SalesPrice); } - - // Get all sale prices for the products in the cart (cart items) from an external service - // for the customer who owns the cart. - Map salesPricesFromExternalService = getSalesPricesFromExternalService(cartId, salesPricesFromSalesforce.keySet(), Id.valueOf(customerId)); - + + // Following snippet of code fetches a mocked static json response from getSalesPricesFromStaticResponse. + // Another example that demonstrates how to call a live 3rd party HTTP Service to fetch the desired + // response is implemented in getSalesPricesFromExternalService method. + Map salesPricesFromExternalService = null; + if(useHTTPService) { + salesPricesFromExternalService = getSalesPricesFromExternalService(cartId, salesPricesFromSalesforce.keySet(), Id.valueOf(customerId)); + } else { + salesPricesFromExternalService = getSalesPricesFromStaticResponse(cartId, salesPricesFromSalesforce.keySet(), Id.valueOf(customerId)); + } + // For each cart item SKU, check that the price from the external service // is the same as the sale price in the cart. // If that is not true, set the integration status to "Failed". @@ -76,10 +86,30 @@ public with sharing class B2BSyncPricing { } } + private static Map getSalesPricesFromStaticResponse(String cartId, Set skus, String customerId) { + if (skus.isEmpty()) { + return (Map) JSON.deserializeUntyped('{"error":"Input SKUs list is empty or undefined."}'); + } + + String responseJson = '{'; + for(String sku : skus) { + Double price = 0.00; + if (sku == 'SKU_FOR_TEST') { + price = 100.00; + } + responseJson = responseJson + '"'+sku+'"'; + responseJson = responseJson + ':'; + responseJson = responseJson + price; + responseJson = responseJson + ','; + } + responseJson = responseJson.removeEnd(',') + '}'; + return (Map) JSON.deserializeUntyped(responseJson); + } + private static Map getSalesPricesFromExternalService(String cartId, Set skus, String customerId) { Http http = new Http(); HttpRequest request = new HttpRequest(); - Integer SuccessfulHttpRequest = 200; + Integer successfulHttpRequest = 200; // Encode the product SKUs to avoid any invalid characters in the request URL. Set encodedSkus = new Set(); @@ -87,8 +117,7 @@ public with sharing class B2BSyncPricing { encodedSkus.add(EncodingUtil.urlEncode(sku, 'UTF-8')); } - // To access the service below you may need to add endpoint = https://b2b-commerce-test.herokuapp.com in Setup | Security | Remote site settings. - request.setEndpoint('https://b2b-commerce-test.herokuapp.com/get-sales-prices?customerId=' + request.setEndpoint(httpHost + '/get-sales-prices?customerId=' + customerId + '&skus=' + JSON.serialize(encodedSkus)); request.setMethod('GET'); HttpResponse response = http.send(request); @@ -98,14 +127,13 @@ public with sharing class B2BSyncPricing { // Because this is a sample only and we want this integration to return success in order to allow the checkout to pass, // the external service created for this sample returns the exact list of SKUs it receives, // and the same sale price 0.00 for each SKU. - if (response.getStatusCode() == SuccessfulHttpRequest) { + if (response.getStatusCode() == successfulHttpRequest) { Map salesPricesFromExternalService = (Map) JSON.deserializeUntyped(response.getBody()); return salesPricesFromExternalService; - } - else { - String errorMessage = 'There was a problem with the request. Error: ' + response.getStatusCode(); - // Sync non-user errors skip saveCartValidationOutputError - throw new CalloutException (errorMessage); + } else if(response.getStatusCode() == 404) { + throw new CalloutException ('404. You must create a sample application or add your own service which returns a valid response'); + } else { + throw new CalloutException ('There was a problem with the request. Error: ' + response.getStatusCode()); } } diff --git a/examples/checkout-main/classes/B2BSyncPricing.cls-meta.xml b/examples/checkout-main/classes/B2BSyncPricing.cls-meta.xml index 4b0bc9f3..dd61d1f9 100644 --- a/examples/checkout-main/classes/B2BSyncPricing.cls-meta.xml +++ b/examples/checkout-main/classes/B2BSyncPricing.cls-meta.xml @@ -1,5 +1,5 @@ - 55.0 + 52.0 Active diff --git a/examples/checkout-main/classes/B2BSyncPricingTest.cls-meta.xml b/examples/checkout-main/classes/B2BSyncPricingTest.cls-meta.xml index 4b0bc9f3..dd61d1f9 100644 --- a/examples/checkout-main/classes/B2BSyncPricingTest.cls-meta.xml +++ b/examples/checkout-main/classes/B2BSyncPricingTest.cls-meta.xml @@ -1,5 +1,5 @@ - 55.0 + 52.0 Active diff --git a/examples/checkout-main/classes/B2BSyncTax.cls b/examples/checkout-main/classes/B2BSyncTax.cls index e5fe6c33..8056db44 100644 --- a/examples/checkout-main/classes/B2BSyncTax.cls +++ b/examples/checkout-main/classes/B2BSyncTax.cls @@ -1,5 +1,9 @@ // Determines the taxes for the cart public class B2BSyncTax { + // You MUST change this to be your service or you must launch your own Heroku Service + // and add the host in Setup | Security | Remote site settings. + private static String httpHost = 'https://example.com'; + private static Boolean useHTTPService = false; // This invocable method only expects one ID @InvocableMethod(callout=true label='Prepare the taxes' description='Runs a synchronous version of taxes' category='B2B Commerce') public static void syncTax(List cartIds) { @@ -16,172 +20,204 @@ public class B2BSyncTax { } private static void startCartProcessSync(Id cartId) { + // If there are any Products with null SKU throw exception. + CartItem[] nullSKUs = [SELECT Id FROM CartItem WHERE CartId=:cartId AND Type='Product' AND Sku=null]; + if (!nullSKUs.isEmpty()) { + String errorMessage = 'The SKUs for all products in your cart must be defined.'; + saveCartValidationOutputError(errorMessage, cartId); + throw new CalloutException (errorMessage); + } + // In the Spring '20 release, there should be one delivery group per cart. // In the future, when multiple delivery groups can be created, // this sample should be updated to loop through all delivery groups. - // We need to get the ID of the delivery group in order to get the DeliverTo info. - Id cartDeliveryGroupId = [SELECT CartDeliveryGroupId FROM CartItem WHERE CartId = :cartId WITH SECURITY_ENFORCED][0].CartDeliveryGroupId; - CartDeliveryGroup deliveryGroup = [SELECT DeliverToState, DeliverToCountry FROM CartDeliveryGroup WHERE Id = :cartDeliveryGroupId WITH SECURITY_ENFORCED][0]; + Id cartDeliveryGroupId = [SELECT CartDeliveryGroupId FROM CartItem WHERE CartId = :cartId][0].CartDeliveryGroupId; + CartDeliveryGroup deliveryGroup = [SELECT DeliverToState, DeliverToCountry FROM CartDeliveryGroup WHERE Id = :cartDeliveryGroupId][0]; + String taxType = [SELECT TaxType FROM WebCart WHERE Id = :cartId][0].TaxType; - // Get all SKUs, the cart item IDs, and the total prices from the cart items. - Map cartItemIdsBySKU = new Map(); - Map cartItemTotalPriceBySKU = new Map(); - for (CartItem cartItem : [SELECT Sku, TotalPrice, Type FROM CartItem WHERE CartId = :cartId WITH SECURITY_ENFORCED]) { - String cartItemSKU = ''; - if (cartItem.Type == 'Product') { - if (String.isBlank(cartItem.Sku)) { - String errorMessage = 'The SKUs for all products in your cart must be defined.'; - saveCartValidationOutputError(errorMessage, cartId); - throw new CalloutException (errorMessage); - } - cartItemSKU = cartItem.Sku; - } - else if (cartItem.Type == 'Charge') { - // This is an example for a Cart Item of type shipping charge. - // For simplicity and testing purposes, we just assign some SKU to this charge so that the taxation external service returns some value. - cartItemSKU = 'ChargeSKU'; - } - cartItemIdsBySKU.put(cartItemSKU, cartItem.Id); - cartItemTotalPriceBySKU.put(cartItemSKU, cartItem.TotalPrice); - } + Map cartItemsMap = new Map([SELECT Id, Sku, Quantity, TotalLineAmount, AdjustmentAmount, (Select Id, TotalAmount from CartItemPriceAdjustments) FROM CartItem WHERE CartId = :cartId]); + + // Following snippet of code fetches a mocked static json response from getDataFromStaticResponse. + // Another example that demonstrates how to call a live 3rd party HTTP Service to fetch the desired + // response is implemented in getDataFromExternalService method. - // Get the tax rates and tax amounts from an external service - // Other parameters will be passed here, like ship_from, bill_to, more details about the ship_to, etc. - Map rateAndAmountFromExternalServicePerSku = getTaxRatesAndAmountsFromExternalService( - cartId, cartItemTotalPriceBySKU, deliveryGroup.DeliverToState, deliveryGroup.DeliverToCountry - ); + Map dataFromService = null; + if(useHTTPService) { + dataFromService = getDataFromExternalService(cartItemsMap, deliveryGroup.DeliverToState, deliveryGroup.DeliverToCountry, taxType); + } else { + dataFromService = getDataFromStaticResponse(cartItemsMap, deliveryGroup.DeliverToState, deliveryGroup.DeliverToCountry, taxType); + } // If there are taxes from a previously cancelled checkout, delete them. - List cartItemIds = cartItemIdsBySKU.values(); - delete [SELECT Id FROM CartTax WHERE CartItemId IN :cartItemIds WITH SECURITY_ENFORCED]; + delete [SELECT Id FROM CartTax WHERE CartItemId IN (Select Id FROM CartItem WHERE CartId = :cartId)]; // For each cart item, insert a new tax line in the CartTax entity. - // The total tax is automatically rolled up to TotalLineTaxAmount in the corresponding CartItem line. - CartTax[] cartTaxestoInsert = new CartTax[]{}; - for (String sku : cartItemIdsBySKU.keySet()) { - TaxDataFromExternalService rateAndAmountFromExternalService = rateAndAmountFromExternalServicePerSku.get(sku); - if (rateAndAmountFromExternalService == null) { - String errorMessage = 'The product with sku ' + sku + ' could not be found in the external system'; - saveCartValidationOutputError(errorMessage, cartId); - throw new CalloutException (errorMessage); + // The total tax is automatically rolled up to TotalLineTaxAmount in the corresponding CartItem line. + CartTax[] cartTaxestoInsert = new CartTax[]{}; + + List cartItemsList = new List(cartItemsMap.values()); + + for (CartItem cartItemToUpdate : cartItemsList) { + // Update CartItem with taxes + String cartItemId = cartItemToUpdate.id; + Map cartItemsMapFromService = (Map) dataFromService.get(cartItemId); + cartItemToUpdate.AdjustmentTaxAmount = (Decimal)cartItemsMapFromService.get('adjustmentTaxAmount'); + cartItemToUpdate.NetUnitPrice = (Decimal)cartItemsMapFromService.get('netUnitPrice'); + cartItemToUpdate.GrossUnitPrice = (Decimal)cartItemsMapFromService.get('grossUnitPrice'); + + CartTax tax = new CartTax( + Amount = (Decimal)cartItemsMapFromService.get('taxAmount'), + CartItemId = cartItemId, + Name = (String)cartItemsMapFromService.get('taxName'), + TaxCalculationDate = Date.today(), + TaxRate = (Decimal)cartItemsMapFromService.get('taxRate'), + TaxType = 'Actual' + ); + cartTaxestoInsert.add(tax); + + List itemTaxList = (List)cartItemsMapFromService.get('itemizedPromotionTaxAmounts'); + for (Object cipaTax : itemTaxList) { + CartTax promoTax = new CartTax( + Amount = (Decimal)((Map) cipaTax).get('taxAmount'), + CartItemId = cartItemId, + Name = (String)cartItemsMapFromService.get('taxName'), + TaxCalculationDate = Date.today(), + TaxRate = (Decimal)cartItemsMapFromService.get('taxRate'), + TaxType = 'Actual', + CartItemPriceAdjustmentId = (String)((Map) cipaTax).get('id') + ); + cartTaxestoInsert.add(promoTax); + } } - // If the sku was found in the external system, add a new CartTax line for that sku - // The following fields from CartTax can be filled in: - // Amount (required): Calculated tax amount. - // CartItemId (required): ID of the cart item. - // Description (optional): Description of CartTax. - // Name (required): Name of the tax. - // TaxCalculationDate (required): Calculation date for this tax line. - // TaxRate (optional): The percentage value of the tax. Null if the tax is a flat amount. - // TaxType (required): The type of tax, e.g. Actual or Estimated. - CartTax tax = new CartTax( - Amount = rateAndAmountFromExternalService.getAmount(), - CartItemId = cartItemIdsBySKU.get(sku), - Name = rateAndAmountFromExternalService.getTaxName(), - TaxCalculationDate = Date.today(), - TaxRate = rateAndAmountFromExternalService.getRate(), - TaxType = 'Actual' - ); - cartTaxestoInsert.add(tax); - } - insert(cartTaxestoInsert); + + update(cartItemsList); + insert(cartTaxestoInsert); } - - private static Map getTaxRatesAndAmountsFromExternalService ( - String cartId, Map cartItemTotalAmountBySKU, String state, String country) { - Http http = new Http(); - HttpRequest request = new HttpRequest(); - Integer SuccessfulHttpRequest = 200; - String encodedState = (state == null) ? '' : EncodingUtil.urlEncode(state, 'UTF-8').replace('+', '%20'); - String encodedCountry = (country == null) ? '' : EncodingUtil.urlEncode(country, 'UTF-8').replace('+', '%20'); + + private static Map getDataFromStaticResponse(Map cartItemsMap, String state, String country, String taxType) { + if (cartItemsMap == null) { + return (Map) JSON.deserializeUntyped('{"error":"Input SKUs list is empty or undefined."}'); + } + Double taxRate = 0.15; + String responseJson = '{'; + for (ID key : cartItemsMap.keySet()) { + CartItem cartItem = cartItemsMap.get(key); + Id cartItemId = cartItem.Id; + + Double amount = cartItem.TotalLineAmount==null ? 0.00 : cartItem.TotalLineAmount; + Double tierAdjustment = cartItem.AdjustmentAmount==null ? 0.00 : cartItem.AdjustmentAmount; + Double quantity = cartItem.Quantity==null ? 0.00 : cartItem.Quantity; - Map encodedCartItemTotalAmountBySKU = new Map(); - for(String sku: cartItemTotalAmountBySKU.keySet()) { - encodedCartItemTotalAmountBySKU.put(EncodingUtil.urlEncode(sku, 'UTF-8'), cartItemTotalAmountBySKU.get(sku)); + if(country == null || country == 'US' || country == 'United States') { + taxRate = 0.08; + String [] noSalesTaxUSStates = new String [] {'AK', 'DE', 'MT', 'NH', 'OR'}; + if (noSalesTaxUSStates.contains(state)) { + taxRate = 0.00; + } } - // To access the service below, you may need to add endpoint = https://b2b-commerce-test.herokuapp.com in Setup | Security | Remote site settings. - String requestURL = 'https://b2b-commerce-test.herokuapp.com/get-tax-rates?state=' + encodedState - + '&country=' + encodedCountry - + '&amountsBySKU=' + JSON.serialize(encodedCartItemTotalAmountBySKU); - request.setEndpoint(requestURL); - request.setMethod('GET'); - HttpResponse response = http.send(request); + Double itemizedPromotionTax = 0.00; + Double [] itemizedPromotionTaxArr = new Double [] {}; + Double netUnitPrice = 0.00; + Double grossUnitPrice = 0.00; + + Double multiplier = 0.00; - // If the request is successful, parse the JSON response; - // The response includes the tax amount, rate, and name for each SKU. It looks something like this: - // {"SKU_1_september10-1568355297":{"taxAmount":2.8229012971048855,"taxRate":0.08,"taxName":"GST"},"SKU_0_september10-1568355296":{"taxAmount":5.0479003481482385,"taxRate":0.08,"taxName":"GST"}} - if (response.getStatusCode() == SuccessfulHttpRequest) { - Map resultsFromExternalServiceBySKU = (Map) JSON.deserializeUntyped(response.getBody()); - Map taxDataFromExternalServiceBySKU = new Map(); - for (String sku : resultsFromExternalServiceBySKU.keySet()) { - Map rateAndAmountFromExternalService = (Map) resultsFromExternalServiceBySKU.get(sku); - taxDataFromExternalServiceBySKU.put(sku, new TaxDataFromExternalService( - (Decimal)rateAndAmountFromExternalService.get('taxRate'), - (Decimal)rateAndAmountFromExternalService.get('taxAmount'), - (String)rateAndAmountFromExternalService.get('taxName') - )); - } - return taxDataFromExternalServiceBySKU; + if(taxType == 'Gross') { + multiplier = taxRate / (1 + taxRate); + } else { + multiplier = taxRate; } - else { - String errorMessage = 'There was a problem with the request. Error: ' + response.getStatusCode(); - // Sync non-user errors skip saveCartValidationOutputError - throw new CalloutException (errorMessage); + + Double cartItemTax = amount * multiplier; + Double tierAdjustmentTax = (tierAdjustment!=null ? tierAdjustment : 0.00) * multiplier; + + CartItemPriceAdjustment [] itemizedPromotions = cartItem.CartItemPriceAdjustments; + + String itemizedPromotionTaxResp = '['; + for(CartItemPriceAdjustment itemAdj : itemizedPromotions) { + Double itemTaxAmount = (itemAdj.TotalAmount!=null ? itemAdj.TotalAmount : 0.00) * multiplier; + itemizedPromotionTaxResp = itemizedPromotionTaxResp + '{'; + itemizedPromotionTaxResp = itemizedPromotionTaxResp + '"id": "' + itemAdj.Id + '",'; + itemizedPromotionTaxResp = itemizedPromotionTaxResp + '"taxAmount": ' + itemTaxAmount; + itemizedPromotionTaxResp = itemizedPromotionTaxResp + '},'; + itemizedPromotionTax = itemizedPromotionTax + itemTaxAmount; } - } - - // Structure to store the tax data retrieved from external service - // This simplifies our ability to access it when storing it in Salesforce's CartTax entity - Class TaxDataFromExternalService { - private Decimal rate; - private Decimal amount; - private String taxName; - - public TaxDataFromExternalService () { - rate = 0.0; - amount = 0.0; - taxName = ''; - } - - public TaxDataFromExternalService (Decimal someRate, Decimal someAmount, String someTaxName) { - rate = someRate; - amount = someAmount; - taxName = someTaxName; - } - - public Decimal getRate() { - return rate; - } - - public Decimal getAmount() { - return amount; + itemizedPromotionTaxResp = itemizedPromotionTaxResp.removeEnd(',') + ']'; + + if(taxType == 'Gross') { + grossUnitPrice = amount / quantity; + netUnitPrice = (amount - cartItemTax) / quantity; + } else { + grossUnitPrice = (amount + cartItemTax) / quantity; + netUnitPrice = amount / quantity; + } + + responseJson = responseJson + '"'+cartItemId+'":'; + responseJson = responseJson + '{'; + responseJson = responseJson + '"cartItemId": "' + cartItemId + '",'; + responseJson = responseJson + '"taxAmount": ' + cartItemTax + ','; + responseJson = responseJson + '"adjustmentTaxAmount": ' + tierAdjustmentTax + ','; + + responseJson = responseJson + '"itemizedPromotionTaxAmounts": '; + responseJson = responseJson + itemizedPromotionTaxResp; + responseJson = responseJson + ','; + + responseJson = responseJson + '"totalItemizedPromotionTaxAmount": ' + itemizedPromotionTax + ','; + responseJson = responseJson + '"grossUnitPrice": ' + grossUnitPrice + ','; + responseJson = responseJson + '"netUnitPrice": ' + netUnitPrice + ','; + responseJson = responseJson + '"taxRate": ' + taxRate + ','; + responseJson = responseJson + '"taxName": "GST"'; + responseJson = responseJson + '},'; } - public String getTaxName() { - return taxName; - } + responseJson = responseJson.removeEnd(',') + '}'; + return (Map) JSON.deserializeUntyped(responseJson); } + private static Map getDataFromExternalService ( + Map cartItemsMap, String state, String country, String taxType) { + + String requestURL = httpHost + '/get-tax-rates-with-adjustments-post'; + String requestBody = '{"state":"'+state+'", "country":"'+country+'", "taxType":"'+taxType+'", '+'"amountsBySKU":'+JSON.serialize(cartItemsMap)+'}'; + Http http = new Http(); + HttpRequest request = new HttpRequest(); + request.setEndpoint(requestURL); + request.setMethod('POST'); + request.setHeader('Content-Type', 'application/json'); + request.setBody(requestBody); + HttpResponse response = http.send(request); + + // If the request is successful, parse the JSON response + if (response.getStatusCode() == 200) { + Map resultsFromExternalService = (Map) JSON.deserializeUntyped(response.getBody()); + return resultsFromExternalService; + } else if(response.getStatusCode() == 404) { + throw new CalloutException ('404. You must create a sample application or add your own service which returns a valid response'); + } else { + throw new CalloutException ('There was a problem with the request. Error: ' + response.getStatusCode()); + } + } + private static void saveCartValidationOutputError(String errorMessage, Id cartId) { - // For the error to be propagated to the user, we need to add a new CartValidationOutput record. - // The following fields must be populated: - // BackgroundOperationId: Foreign Key to the BackgroundOperation - // CartId: Foreign key to the WebCart that this validation line is for - // Level (required): One of the following - Info, Error, or Warning - // Message (optional): Message displayed to the user (maximum 255 characters) - // Name (required): The name of this CartValidationOutput record. For example CartId - // RelatedEntityId (required): Foreign key to WebCart, CartItem, CartDeliveryGroup - // Type (required): One of the following - SystemError, Inventory, Taxes, Pricing, Shipping, Entitlement, Other - CartValidationOutput cartValidationError = new CartValidationOutput( - CartId = cartId, - Level = 'Error', - Message = errorMessage.left(255), - Name = (String)cartId, - RelatedEntityId = cartId, - Type = 'Taxes' - ); - insert(cartValidationError); + // For the error to be propagated to the user, we need to add a new CartValidationOutput record. + // The following fields must be populated: + // BackgroundOperationId: Foreign Key to the BackgroundOperation + // CartId: Foreign key to the WebCart that this validation line is for + // Level (required): One of the following - Info, Error, or Warning + // Message (optional): Message displayed to the user (maximum 255 characters) + // Name (required): The name of this CartValidationOutput record. For example CartId + // RelatedEntityId (required): Foreign key to WebCart, CartItem, CartDeliveryGroup + // Type (required): One of the following - SystemError, Inventory, Taxes, Pricing, Shipping, Entitlement, Other + CartValidationOutput cartValidationError = new CartValidationOutput( + CartId = cartId, + Level = 'Error', + Message = errorMessage.left(255), + Name = (String)cartId, + RelatedEntityId = cartId, + Type = 'Taxes' + ); + insert(cartValidationError); } } \ No newline at end of file diff --git a/examples/checkout-main/flows/Checkout_Main_Checkout.flow b/examples/checkout-main/flows/Checkout_Main_Checkout.flow index 42b65a20..b76dbe68 100644 --- a/examples/checkout-main/flows/Checkout_Main_Checkout.flow +++ b/examples/checkout-main/flows/Checkout_Main_Checkout.flow @@ -258,7 +258,7 @@ This node does not have any inputs and produces a warning when saved. If an exte - 55.0 + 52.0 This node is here for cosmetic purposes. It helps make the flow easier to read, but is not a necessary technical component. Beatification_No_Logic2 diff --git a/examples/checkout-main/flows/Checkout_Main_with_Salesforce_Pricing_and_Promotions.flow b/examples/checkout-main/flows/Checkout_Main_with_Salesforce_Pricing_and_Promotions.flow index 8f4c5343..fd176739 100644 --- a/examples/checkout-main/flows/Checkout_Main_with_Salesforce_Pricing_and_Promotions.flow +++ b/examples/checkout-main/flows/Checkout_Main_with_Salesforce_Pricing_and_Promotions.flow @@ -235,7 +235,7 @@ This may fallback to asynchronous mode even if it's marked synchronous, so - 55.0 + 52.0 This node is here for cosmetic purposes. It helps make the flow easier to read, but is not a necessary technical component. Beatification_No_Logic2 diff --git a/examples/checkout-main/readme.md b/examples/checkout-main/readme.md index 77222063..8d7c7c87 100644 --- a/examples/checkout-main/readme.md +++ b/examples/checkout-main/readme.md @@ -1,21 +1,25 @@ # B2B Synchronous Checkout + The Lightning B2B Commerce checkout has several moving parts that work together to make a highly customizable checkout. This guide contains a general checkout implementation that you can use in your own org. When deployed, this package sets up a basic checkout in your org, including a framework of flows. The Synchronous Checkout differs from the [Asynchronous Checkout](../checkout-async) in several important ways. It's no longer re-entrant and being synchronous means that if the integrations take too long, the checkout may fail. However, this checkout is simpler, contains a built in previous button and should be a bit faster. ## SFDX Scratch Org + If you are creating a brand new scratch org, the easiest way to install is to: + 1. Go to the [SFDX directory](../../sfdx) 1. Delete the force-app folder. - * rm -rf force-app + - rm -rf force-app 1. Convert the examples to the force-app directory. With no flag specified, it will copy over the synchronous files by default. - * ./convert-examples-to-sfdx.sh + - ./convert-examples-to-sfdx.sh 1. Follow the remaining instructions to deploy using sfdx. ## Use Metadata API to deploy this using Workbench: + 1. If you haven't already, clone this repository. -1. Set up the [B2B Advanced Reference Components](../lwc). *Note:* When you complete these steps, if you've already set up a store, skip the Usage section and skip the step for creating an org -1. From this folder as your current location, create a .zip file: zip -r -x readme.md -X .zip * +1. Set up the [B2B Advanced Reference Components](../lwc). _Note:_ When you complete these steps, if you've already set up a store, skip the Usage section and skip the step for creating an org +1. From this folder as your current location, create a .zip file: zip -r -x readme.md -X .zip \* 1. Open Workbench and go to migration -> deploy. 1. Select the file you created ( .zip ). 1. Check the Single Package checkbox on that page. @@ -23,14 +27,16 @@ If you are creating a brand new scratch org, the easiest way to install is to: 1. Click Deploy. ## Flow + Flows are central to the checkout process. Our example contains both of the flows you need to make a working checkout, including the primary flow (Simple B2B Checkout) and one subflow for handling errors. Import the example flows into your org to avoid starting from scratch and get a head start on the checkout process. After importing your flows and creating a store, make sure your store uses the checkout you created here. To do so, navigate to Experience Builder in your store. ## Navigate to the Checkout page. + From the content pane, select the checkout component. Find the Checkout Flow Name attribute. Select your primary Checkout Flow. Don't select any of the flows with Subflow in the name even if they are available. ## Enabling Promotions and Using built in Pricing -Salesforce provides engines for Pricing and Promotions. We have provided a second main flow that includes Salesforce pricing and promotions. This flow is slightly more complicated and uses more subflows, but comes with some more functionality. Some of the integrations, Pricing and Promotions, run asynchronously which can cause delays during checkout. \ No newline at end of file +Salesforce provides engines for Pricing and Promotions. We have provided a second main flow that includes Salesforce pricing and promotions. This flow is slightly more complicated and uses more subflows, but comes with some more functionality. Some of the integrations, Pricing and Promotions, run asynchronously which can cause delays during checkout. diff --git a/examples/checkout-reentrant/README.md b/examples/checkout-reentrant/README.md index a68689fd..62afd546 100644 --- a/examples/checkout-reentrant/README.md +++ b/examples/checkout-reentrant/README.md @@ -1,21 +1,25 @@ # B2B Asynchronous Checkout + The Lightning B2B Commerce checkout has several moving parts that work together to make a highly customizable checkout. This guide contains a general checkout implementation that you can use in your own org. When deployed, this package sets up a basic checkout in your org, including a framework of flows. The checkout included in this package is re-entrant. Re-entrancy saves a buyer’s spot in a checkout so they can start a checkout, leave, and come back to complete it later. With this feature, the checkout also functions if the buyer has two checkout tabs open at the same time. This iteration of the Checkout by default tokenizes the buyer's credit information allowing for the payment screen to come before the Checkout summary screen. The payment screen is also customizable and can be found in the [lwc directory](../lwc). ## SFDX Scratch Org + If you are creating a brand new scratch org, the easiest way to install is to: + 1. Go to the [SFDX directory](../../sfdx) 1. Delete the force-app folder. - * rm -rf force-app + - rm -rf force-app 1. Convert the examples to the force-app directory. With the async flow flag, this will install the asynchronous checkout instead of the synchronous one. - * ./convert-examples-to-sfdx.sh -f async + - ./convert-examples-to-sfdx.sh -f async 1. Follow the remaining instructions to deploy using sfdx. ## Use Metadata API to deploy this using Workbench: + 1. If you haven't already, clone this repository. -1. Set up the [B2B Advanced Reference Components](../lwc). *Note:* When you complete these steps, if you've already set up a store, skip the Usage section and skip the step for creating an org -1. From this folder as your current location, create a .zip file: zip -r -x README.md -X .zip * +1. Set up the [B2B Advanced Reference Components](../lwc). _Note:_ When you complete these steps, if you've already set up a store, skip the Usage section and skip the step for creating an org +1. From this folder as your current location, create a .zip file: zip -r -x README.md -X .zip \* 1. Open Workbench and go to migration -> deploy. 1. Select the file you created ( .zip ). 1. Check the Single Package checkbox on that page. @@ -23,22 +27,27 @@ If you are creating a brand new scratch org, the easiest way to install is to: 1. Click Deploy. ## Managed and Unmanaged Flows + There are two versions of each flow in this package. Some flows are marked with an Unmanaged package type and have a version prefix (Summer 2021, for example). Other flows have a Managed Installed package type. The Unmanaged versions of the flows are uploaded as part of this example and are your primary focus. They can be modified when necessary to suit the needs of individual checkouts. You can disregard the Managed Installed flows except to use as reference. The Managed Installed versions are automatically updated each release, which is convenient, but unstable. If your checkout relies on the behavior of a previous release, automatic updates could break your implementation. We suggest using the unmanaged flows. ## Flow + Flows are central to the checkout process. Our example contains all the flows you need to make a working checkout, including the primary flow (Checkout Flow) and many subflows. Subflows have a “Subflow” prefix in their names. Import the example flows into your org to avoid starting from scratch and get a head start on the checkout process. After importing your flows and creating a store, make sure your store uses the checkout you created here. To do so, navigate to Experience Builder in your store. ## Navigate to the Checkout page. + From the content pane, select the checkout component. Find the Checkout Flow Name attribute. Select your primary Checkout Flow. Don't select any of the flows with Subflow in the name even if they are available. ## Flow Naming + Checkout flows are prefixed with the version of the software they are expected to work with. For example, if you see a flow labelled "(Spring 2021) Checkout Flow", the flow was designed and tested to work with the Spring 2021 release. This naming structure is used primarily for convenience and transparency. Flows still work in future versions of the software, regardless of name. ## Payments + You can find additional information in [Payment Method Tokenization](https://developer.salesforce.com/docs/atlas.en-us.chatterapi.meta/chatterapi/connect_resources_payment_method_tokenization.htm) and [Payment Authorization](https://developer.salesforce.com/docs/atlas.en-us.chatterapi.meta/chatterapi/connect_resources_payment_auth.htm) diff --git a/examples/checkout/integrations/classes/B2BCheckInventorySample.cls b/examples/checkout/integrations/classes/B2BCheckInventorySample.cls index d57f3a9c..1b276915 100644 --- a/examples/checkout/integrations/classes/B2BCheckInventorySample.cls +++ b/examples/checkout/integrations/classes/B2BCheckInventorySample.cls @@ -1,6 +1,10 @@ // This must implement the sfdc_checkout.CartInventoryValidation interface // in order to be processed by the checkout flow and used for your Check Inventory integration. global with sharing class B2BCheckInventorySample implements sfdc_checkout.CartInventoryValidation { + // You MUST change this to be your service or you must launch your own Heroku Service + // and add the host in Setup | Security | Remote site settings. + private static String httpHost = 'https://example.com'; + private static Boolean useHTTPService = false; global sfdc_checkout.IntegrationStatus startCartProcessAsync(sfdc_checkout.IntegrationInfo jobInfo, ID cartId) { sfdc_checkout.IntegrationStatus integStatus = new sfdc_checkout.IntegrationStatus(); try { @@ -29,17 +33,26 @@ global with sharing class B2BCheckInventorySample implements sfdc_checkout.CartI cartId ); } - + + // Following snippet of code fetches a mocked static json response from getQuantitiesFromStaticResponse. + // Another example that demonstrates how to call a live 3rd party HTTP Service to fetch the desired + // response is implemented in getQuantitiesFromExternalService method. + // Get all available quantities for products in the cart (cart items) from an external service. - Map quantitiesFromExternalService = getQuantitiesFromExternalService(quantitiesFromSalesforce.keySet()); + Map quantitiesFromService = null; + if(useHTTPService) { + quantitiesFromService = getQuantitiesFromExternalService(quantitiesFromSalesforce.keySet()); + } else { + quantitiesFromService = getQuantitiesFromStaticResponse(quantitiesFromSalesforce.keySet()); + } // For each cart item SKU, check that the quantity from the external service // is greater or equal to the quantity in the cart. // If that is not true, set the integration status to "Failed". for (String sku : quantitiesFromSalesforce.keySet()) { Decimal quantityFromSalesforce = quantitiesFromSalesforce.get(sku); - Decimal quantityFromExternalService = (Decimal)quantitiesFromExternalService.get(sku); - if (quantityFromExternalService == null){ + Decimal quantityFromService = (Decimal) quantitiesFromService.get(sku); + if (quantityFromService == null){ String errorMessage = 'The product with sku ' + sku + ' could not be found in the external system'; return integrationStatusFailedWithCartValidationOutputError( integStatus, @@ -47,11 +60,10 @@ global with sharing class B2BCheckInventorySample implements sfdc_checkout.CartI jobInfo, cartId ); - } - else if (quantityFromExternalService < quantityFromSalesforce){ - String errorMessage = 'Insufficient quantity for the product with sku ' + sku + ': ' + } else if (quantityFromService < quantityFromSalesforce){ + String errorMessage = 'Insufficient quantity for the product with sku ' + sku + ': ' + quantityFromSalesforce + ' needed, but only ' - + quantityFromExternalService + ' available.'; + + quantityFromService + ' available.'; return integrationStatusFailedWithCartValidationOutputError( integStatus, errorMessage, @@ -78,11 +90,26 @@ global with sharing class B2BCheckInventorySample implements sfdc_checkout.CartI } return integStatus; } - + + private Map getQuantitiesFromStaticResponse(Set skus) { + if (skus.isEmpty()) { + return (Map) JSON.deserializeUntyped('{"error":"Input SKUs list is empty or undefined."}'); + } + String responseJson = '{'; + for (String sku : skus) { + responseJson = responseJson + '"'+sku+'"'; + responseJson = responseJson + ':'; + responseJson = responseJson + '9999.00'; + responseJson = responseJson + ','; + } + responseJson = responseJson.removeEnd(',') + '}'; + return (Map) JSON.deserializeUntyped(responseJson); + } + private Map getQuantitiesFromExternalService (Set skus) { Http http = new Http(); HttpRequest request = new HttpRequest(); - Integer SuccessfulHttpRequest = 200; + Integer successfulHttpRequest = 200; // Encode the product SKUs to avoid any invalid characters in the request URL. Set encodedSkus = new Set(); @@ -90,8 +117,7 @@ global with sharing class B2BCheckInventorySample implements sfdc_checkout.CartI encodedSkus.add(EncodingUtil.urlEncode(sku, 'UTF-8')); } - // To access the service below, add endpoint = https://b2b-commerce-test.herokuapp.com in Setup | Security | Remote site settings. - request.setEndpoint('https://b2b-commerce-test.herokuapp.com/get-inventory?skus=' + JSON.serialize(encodedSkus)); + request.setEndpoint(httpHost + '/get-inventory?skus=' + JSON.serialize(encodedSkus)); request.setMethod('GET'); HttpResponse response = http.send(request); // If the request is successful, parse the JSON response. @@ -101,15 +127,16 @@ global with sharing class B2BCheckInventorySample implements sfdc_checkout.CartI // The external service returns the exact list of SKUs it receives // and an available quantity of 9999 for each SKU. // If the cart has an item with a quantity higher than 9999, the integration returns an error. - if (response.getStatusCode() == SuccessfulHttpRequest) { + if (response.getStatusCode() == successfulHttpRequest) { Map quantitiesFromExternalService = (Map) JSON.deserializeUntyped(response.getBody()); return quantitiesFromExternalService; - } - else { + } else if(response.getStatusCode() == 404) { + throw new CalloutException ('404. You must create a sample application or add your own service which returns a valid response'); + } else { throw new CalloutException ('There was a problem with the request. Error: ' + response.getStatusCode()); } - } - + } + private sfdc_checkout.IntegrationStatus integrationStatusFailedWithCartValidationOutputError( sfdc_checkout.IntegrationStatus integrationStatus, String errorMessage, sfdc_checkout.IntegrationInfo jobInfo, Id cartId) { integrationStatus.status = sfdc_checkout.IntegrationStatus.Status.FAILED; @@ -134,4 +161,4 @@ global with sharing class B2BCheckInventorySample implements sfdc_checkout.CartI insert(cartValidationError); return integrationStatus; } -} \ No newline at end of file +} diff --git a/examples/checkout/integrations/classes/B2BCheckInventorySample.cls-meta.xml b/examples/checkout/integrations/classes/B2BCheckInventorySample.cls-meta.xml index 4b0bc9f3..b1a915c9 100644 --- a/examples/checkout/integrations/classes/B2BCheckInventorySample.cls-meta.xml +++ b/examples/checkout/integrations/classes/B2BCheckInventorySample.cls-meta.xml @@ -1,5 +1,5 @@ - 55.0 + 59.0 Active diff --git a/examples/checkout/integrations/classes/B2BCheckInventorySampleTest.cls b/examples/checkout/integrations/classes/B2BCheckInventorySampleTest.cls index ca0adc1a..6d68e86b 100644 --- a/examples/checkout/integrations/classes/B2BCheckInventorySampleTest.cls +++ b/examples/checkout/integrations/classes/B2BCheckInventorySampleTest.cls @@ -3,27 +3,18 @@ public class B2BCheckInventorySampleTest { @testSetup static void setup() { Account account = new Account(Name='TestAccount'); insert account; - WebStore webStore = new WebStore(Name='TestWebStore', DefaultLanguage='en_US'); + WebStore webStore = new WebStore(Name='TestWebStore', SupportedLanguages='en_US', DefaultLanguage='en_US'); insert webStore; WebCart cart = new WebCart(Name='Cart', WebStoreId=webStore.Id, AccountId=account.Id); insert cart; CartDeliveryGroup cartDeliveryGroup = new CartDeliveryGroup(CartId=cart.Id, Name='Default Delivery'); insert cartDeliveryGroup; - + insertCartItem(cart.Id, cartDeliveryGroup.Id); } - + @isTest static void testWhenExternalServiceQuantityIsLargerThanTheCartItemQuantityASuccessStatusIsReturned() { - // Because test methods do not support Web service callouts, we create a mock response based on a static resource. - // To create the static resource from the Developer Console, select File | New | Static Resource - StaticResourceCalloutMock mock = new StaticResourceCalloutMock(); - mock.setStaticResource('GetInventoryResource'); - mock.setStatusCode(200); - mock.setHeader('Content-Type', 'application/json;charset=UTF-8'); Test.startTest(); - // Associate the callout with a mock response. - Test.setMock(HttpCalloutMock.class, mock); - // Test: execute the integration for the test cart ID. B2BCheckInventorySample apexSample = new B2BCheckInventorySample(); WebCart webCart = [SELECT Id FROM WebCart WHERE Name = 'Cart' LIMIT 1]; @@ -31,34 +22,7 @@ public class B2BCheckInventorySampleTest { System.assertEquals(sfdc_checkout.IntegrationStatus.Status.SUCCESS, integrationResult.status); Test.stopTest(); } - - @isTest static void testWhenExternalServiceCallFailsAFailedStatusIsReturnedAndACartValidationOutputEntryIsCreated() { - // Because test methods do not support Web service callouts, we create a mock response based on a static resource. - // To create the static resource from the Developer Console, select File | New | Static Resource - StaticResourceCalloutMock mock = new StaticResourceCalloutMock(); - mock.setStaticResource('GetInventoryResource'); - // The web service call returns an error code. - mock.setStatusCode(404); - mock.setHeader('Content-Type', 'application/json;charset=UTF-8'); - Test.startTest(); - // Associate the callout with a mock response. - Test.setMock(HttpCalloutMock.class, mock); - - // Test: execute the integration for the test cart ID and integration info. - B2BCheckInventorySample apexSample = new B2BCheckInventorySample(); - sfdc_checkout.IntegrationInfo integInfo = new sfdc_checkout.IntegrationInfo(); - integInfo.jobId = null; - WebCart webCart = [SELECT Id FROM WebCart WHERE Name = 'Cart' LIMIT 1]; - sfdc_checkout.IntegrationStatus integrationResult = apexSample.startCartProcessAsync(integInfo, webCart.Id); - - // Validate: IntegrationStatus.Status is FAILED. - // and a new CartValidationOutput record with level 'Error' was created. - System.assertEquals(sfdc_checkout.IntegrationStatus.Status.FAILED, integrationResult.status); - List cartValidationOutputs = [SELECT Id FROM CartValidationOutput WHERE Level = 'Error']; - System.assertEquals(1, cartValidationOutputs.size()); - Test.stopTest(); - } - + // This test ensures that when the cart is empty that check inventory returns an error @isTest static void testEmptyCartHasError() { // Empty the cart before the test @@ -77,8 +41,8 @@ public class B2BCheckInventorySampleTest { System.assertEquals(sfdc_checkout.IntegrationStatus.Status.FAILED, integrationResult.status); List cartValidationOutputs = [SELECT Id, Message FROM CartValidationOutput WHERE Level = 'Error']; System.assertEquals(1, cartValidationOutputs.size()); - - // Validate: The sample text that the cart is empty is returned as the failure output + + // Validate: The sample text that the cart is empty is returned as the failure output System.assertEquals('Looks like your cart is empty.', cartValidationOutputs.get(0).Message); Test.stopTest(); @@ -112,8 +76,8 @@ public class B2BCheckInventorySampleTest { System.assertEquals(sfdc_checkout.IntegrationStatus.Status.FAILED, integrationResult.status); List cartValidationOutputs = [SELECT Id, Message FROM CartValidationOutput WHERE Level = 'Error']; System.assertEquals(1, cartValidationOutputs.size()); - - // Validate: The sample text that a product SKU is missing is returned as the failure output + + // Validate: The sample text that a product SKU is missing is returned as the failure output System.assertEquals('The SKUs for all products in your cart must be defined.', cartValidationOutputs.get(0).Message); Test.stopTest(); @@ -127,21 +91,21 @@ public class B2BCheckInventorySampleTest { insertCartItem(cartId, cartDeliveryGroups.get(0).Id); } - + // Inserts a cart item that matches the cart and cart delivery group static void insertCartItem(String cartId, String cartDeliveryGroupId) { CartItem cartItem = new CartItem( - CartId=cartId, - Sku='SKU_Test1', - Quantity=3.0, - Type='Product', - Name='TestProduct', + CartId=cartId, + Sku='SKU_Test1', + Quantity=3.0, + Type='Product', + Name='TestProduct', CartDeliveryGroupId=cartDeliveryGroupId ); insert cartItem; } - // Deletes the single cart item + // Deletes the single cart item static void deleteCartItem() { CartItem cartItem = [SELECT Id FROM CartItem WHERE Name = 'TestProduct' LIMIT 1]; delete cartItem; diff --git a/examples/checkout/integrations/classes/B2BCheckInventorySampleTest.cls-meta.xml b/examples/checkout/integrations/classes/B2BCheckInventorySampleTest.cls-meta.xml index 4b0bc9f3..b1a915c9 100644 --- a/examples/checkout/integrations/classes/B2BCheckInventorySampleTest.cls-meta.xml +++ b/examples/checkout/integrations/classes/B2BCheckInventorySampleTest.cls-meta.xml @@ -1,5 +1,5 @@ - 55.0 + 59.0 Active diff --git a/examples/checkout/integrations/classes/B2BDeliverySample.cls b/examples/checkout/integrations/classes/B2BDeliverySample.cls index 48f974f3..9775648e 100644 --- a/examples/checkout/integrations/classes/B2BDeliverySample.cls +++ b/examples/checkout/integrations/classes/B2BDeliverySample.cls @@ -1,6 +1,10 @@ // This must implement the sfdc_checkout.CartShippingCharges interface // in order to be processed by the checkout flow for the "Shipping" integration global with sharing class B2BDeliverySample implements sfdc_checkout.CartShippingCharges { + // You MUST change this to be your service or you must launch your own Heroku Service + // and add the host in Setup | Security | Remote site settings. + private static String httpHost = 'https://example.com'; + private static Boolean useHTTPService = false; global sfdc_checkout.IntegrationStatus startCartProcessAsync(sfdc_checkout.IntegrationInfo jobInfo, Id cartId) { sfdc_checkout.IntegrationStatus integStatus = new sfdc_checkout.IntegrationStatus(); try { @@ -10,8 +14,17 @@ global with sharing class B2BDeliverySample implements sfdc_checkout.CartShippin // Used to increase the cost by a multiple of the number of items in the cart (useful for testing but should not be done in the final code) Integer numberOfUniqueItems = [SELECT count() from cartItem WHERE CartId = :cartId WITH SECURITY_ENFORCED]; - // Get shipping options, including aspects like rates and carriers, from the external service. - ShippingOptionsAndRatesFromExternalService[] shippingOptionsAndRatesFromExternalService = getShippingOptionsAndRatesFromExternalService(numberOfUniqueItems); + // Following snippet of code fetches a static json response with 2 mocked sample shipping methods. + // Another example that demonstrates how to call a live 3rd party HTTP Service to fetch the desired response is implemented + // in getShippingOptionsAndRatesFromExternalService method. + + // Both implementations are just samples returning hardcoded Shipping options and MUST not be used in production systems. + ShippingOptionsAndRatesFromExternalService[] shippingOptionsAndRatesFromExternalService = null; + if(useHTTPService) { + shippingOptionsAndRatesFromExternalService = getShippingOptionsAndRatesFromExternalService(numberOfUniqueItems); + } else { + shippingOptionsAndRatesFromExternalService = getShippingOptionsAndRatesFromMockedService(numberOfUniqueItems); + } // On re-entry of the checkout flow delete all previous CartDeliveryGroupMethods for the given cartDeliveryGroupId delete [SELECT Id FROM CartDeliveryGroupMethod WHERE CartDeliveryGroupId = :cartDeliveryGroupId WITH SECURITY_ENFORCED]; @@ -63,15 +76,44 @@ global with sharing class B2BDeliverySample implements sfdc_checkout.CartShippin return integStatus; } + /** + This method provides an alternative to retrieve Shipping Options if http call needs to be bypassed. + This method uses a hardcoded sample response and MUST not be used in production systems. + */ + private ShippingOptionsAndRatesFromExternalService[] getShippingOptionsAndRatesFromMockedService (Integer numberOfUniqueItems) { + ShippingOptionsAndRatesFromExternalService[] shippingOptions = new List(); + String responseBody = getShippingOptionsResponse(); + List results = (List) JSON.deserializeUntyped(responseBody); + for (Object result: results) { + Map subresult = (Map) result; + Map providerAndRate = (Map) subresult.get('rate'); + shippingOptions.add( new ShippingOptionsAndRatesFromExternalService( + (String) providerAndRate.get('name'), + (String) providerAndRate.get('serviceCode'), + (Decimal) providerAndRate.get('shipmentCost') * numberOfUniqueItems, + (Decimal) providerAndRate.get('otherCost'), + (String) providerAndRate.get('serviceName') + )); + } + return shippingOptions; + } + + private String getShippingOptionsResponse() { + String name1 = 'Delivery Method 1'; + String name2 = 'Delivery Method 2'; + String serviceName1 = 'Test Carrier 1'; + String serviceName2 = 'Test Carrier 2'; + return '[{"status":"calculated","rate":{"name":"'+name1+'","serviceName":"'+serviceName1+'","serviceCode":"SNC9600","shipmentCost":11.99,"otherCost":5.99}},{"status":"calculated","rate":{"name":"'+name2+'","serviceName":"'+serviceName2+'","serviceCode":"SNC9600","shipmentCost":15.99,"otherCost":6.99}}]'; + } + private ShippingOptionsAndRatesFromExternalService[] getShippingOptionsAndRatesFromExternalService (Integer numberOfUniqueItems) { - final Integer SuccessfulHttpRequest = 200; + final Integer successfulHttpRequest = 200; ShippingOptionsAndRatesFromExternalService[] shippingOptions = new List(); Http http = new Http(); HttpRequest request = new HttpRequest(); - // To access the service below, you may need to add endpoint = https://b2b-commerce-test.herokuapp.com in Setup | Security | Remote site settings. - request.setEndpoint('https://b2b-commerce-test.herokuapp.com/calculate-shipping-rates-winter-21'); + request.setEndpoint(httpHost + '/calculate-shipping-rates-winter-21'); request.setMethod('GET'); HttpResponse response = http.send(request); @@ -79,7 +121,7 @@ global with sharing class B2BDeliverySample implements sfdc_checkout.CartShippin // The response looks like this: // [{"status":"calculated","rate":{"name":"Delivery Method 1","serviceName":"Test Carrier 1","serviceCode":"SNC9600","shipmentCost":11.99,"otherCost":5.99}}, // {"status":"calculated","rate":{"name":"Delivery Method 2","serviceName":"Test Carrier 2","serviceCode":"SNC9600","shipmentCost":15.99,"otherCost":6.99}}] - if (response.getStatusCode() == SuccessfulHttpRequest) { + if (response.getStatusCode() == successfulHttpRequest) { List results = (List) JSON.deserializeUntyped(response.getBody()); for (Object result: results) { Map subresult = (Map) result; @@ -93,8 +135,9 @@ global with sharing class B2BDeliverySample implements sfdc_checkout.CartShippin )); } return shippingOptions; - } - else { + } else if(response.getStatusCode() == 404) { + throw new CalloutException ('404. You must create a sample application or add your own service which returns a valid response'); + } else { throw new CalloutException ('There was a problem with the request. Error: ' + response.getStatusCode()); } } diff --git a/examples/checkout/integrations/classes/B2BDeliverySample.cls-meta.xml b/examples/checkout/integrations/classes/B2BDeliverySample.cls-meta.xml index 4b0bc9f3..b1a915c9 100644 --- a/examples/checkout/integrations/classes/B2BDeliverySample.cls-meta.xml +++ b/examples/checkout/integrations/classes/B2BDeliverySample.cls-meta.xml @@ -1,5 +1,5 @@ - 55.0 + 59.0 Active diff --git a/examples/checkout/integrations/classes/B2BDeliverySampleTest.cls b/examples/checkout/integrations/classes/B2BDeliverySampleTest.cls index d369c549..1abeee35 100644 --- a/examples/checkout/integrations/classes/B2BDeliverySampleTest.cls +++ b/examples/checkout/integrations/classes/B2BDeliverySampleTest.cls @@ -3,34 +3,24 @@ private class B2BDeliverySampleTest { @testSetup static void setup() { Account testAccount = new Account(Name='TestAccount'); insert testAccount; - WebStore testWebStore = new WebStore(Name='TestWebStore', DefaultLanguage='en_US'); + WebStore testWebStore = new WebStore(Name='TestWebStore', SupportedLanguages='en_US', DefaultLanguage='en_US'); insert testWebStore; - + Account account = [SELECT Id FROM Account WHERE Name='TestAccount' LIMIT 1]; WebStore webStore = [SELECT Id FROM WebStore WHERE Name='TestWebStore' LIMIT 1]; WebCart cart = new WebCart(Name='Cart', WebStoreId=webStore.Id, AccountId=account.Id); insert cart; - + CartDeliveryGroup cartDeliveryGroup = new CartDeliveryGroup(CartId=cart.Id, Name='Default Delivery 1'); insert cartDeliveryGroup; CartItem cartItem = new CartItem(CartId=cart.Id, Type='Product', Name='TestProduct', CartDeliveryGroupId=cartDeliveryGroup.Id); insert cartItem; - } - + @isTest static void testIntegrationRunsSuccessfully() { - // Because test methods don't support Web service callouts, we create a mock response based on a static resource. - // To create the static resource from the Developer Console, select File | New | Static Resource - StaticResourceCalloutMock mock = new StaticResourceCalloutMock(); - mock.setStaticResource('GetDeliveryRatesResource'); - mock.setStatusCode(200); - mock.setHeader('Content-Type', 'application/json;charset=UTF-8'); Test.startTest(); - // Associate the callout with a mock response. - Test.setMock(HttpCalloutMock.class, mock); - // Test: execute the integration for the test cart ID. B2BDeliverySample apexSample = new B2BDeliverySample(); sfdc_checkout.IntegrationInfo integInfo = new sfdc_checkout.IntegrationInfo(); @@ -41,32 +31,4 @@ private class B2BDeliverySampleTest { System.assertEquals(sfdc_checkout.IntegrationStatus.Status.SUCCESS, integrationResult.status); Test.stopTest(); } - - - @isTest static void testWhenExternalServiceCallFailsAFailedStatusIsReturnedAndACartValidationOutputEntryIsCreated() { - // Because test methods do not support Web service callouts, we create a mock response based on a static resource. - // To create the static resource from the the Developer Console, select File | New | Static Resource - StaticResourceCalloutMock mock = new StaticResourceCalloutMock(); - mock.setStaticResource('GetDeliveryRatesResource'); - // The web service call returns an error code. - mock.setStatusCode(404); - mock.setHeader('Content-Type', 'application/json;charset=UTF-8'); - Test.startTest(); - // Associate the callout with a mock response. - Test.setMock(HttpCalloutMock.class, mock); - - // Test: execute the integration for the test cart ID and integration info. - B2BDeliverySample apexSample = new B2BDeliverySample(); - sfdc_checkout.IntegrationInfo integInfo = new sfdc_checkout.IntegrationInfo(); - integInfo.jobId = null; - WebCart webCart = [SELECT Id FROM WebCart WHERE Name = 'Cart' LIMIT 1]; - sfdc_checkout.IntegrationStatus integrationResult = apexSample.startCartProcessAsync(integInfo, webCart.Id); - - // Validate: IntegrationStatus.Status is FAILED - // and a new CartValidationOutput record with level 'Error' was created. - System.assertEquals(sfdc_checkout.IntegrationStatus.Status.FAILED, integrationResult.status); - List cartValidationOutputs = [SELECT Id FROM CartValidationOutput WHERE Level = 'Error']; - System.assertEquals(1, cartValidationOutputs.size()); - Test.stopTest(); - } -} \ No newline at end of file +} diff --git a/examples/checkout/integrations/classes/B2BDeliverySampleTest.cls-meta.xml b/examples/checkout/integrations/classes/B2BDeliverySampleTest.cls-meta.xml index 4b0bc9f3..b1a915c9 100644 --- a/examples/checkout/integrations/classes/B2BDeliverySampleTest.cls-meta.xml +++ b/examples/checkout/integrations/classes/B2BDeliverySampleTest.cls-meta.xml @@ -1,5 +1,5 @@ - 55.0 + 59.0 Active diff --git a/examples/checkout/integrations/classes/B2BPricingSample.cls b/examples/checkout/integrations/classes/B2BPricingSample.cls index 7298f4c5..4a57c6d4 100644 --- a/examples/checkout/integrations/classes/B2BPricingSample.cls +++ b/examples/checkout/integrations/classes/B2BPricingSample.cls @@ -3,16 +3,20 @@ // This must implement the sfdc_checkout.CartPriceCalculations interface // in order to be processed by the checkout flow and used for your Price Calculations integration. global with sharing class B2BPricingSample implements sfdc_checkout.CartPriceCalculations { + // You MUST change this to be your service or you must launch your own Heroku Service + // and add the host in Setup | Security | Remote site settings. + private static String httpHost = 'https://example.com'; + private static Boolean useHTTPService = false; global sfdc_checkout.IntegrationStatus startCartProcessAsync(sfdc_checkout.IntegrationInfo jobInfo, Id cartId) { sfdc_checkout.IntegrationStatus integStatus = new sfdc_checkout.IntegrationStatus(); try { // To retrieve sale prices for a customer, get the cart owner's ID and pass it to the external service. - // + // // In the real-life scenario, the ID will probably be an external ID // that identifies the customer in the external system, // but for simplicity we are using the Salesforce ID in this sample. Id customerId = [SELECT OwnerId FROM WebCart WHERE id = :cartId WITH SECURITY_ENFORCED][0].OwnerId; - + // Get all SKUs and their sale prices (customer-specific prices) from the cart items. Map salesPricesFromSalesforce = new Map(); for (CartItem cartItem : [SELECT Sku, SalesPrice FROM CartItem WHERE CartId = :cartId AND Type = 'Product' WITH SECURITY_ENFORCED]) { @@ -27,17 +31,23 @@ global with sharing class B2BPricingSample implements sfdc_checkout.CartPriceCal } salesPricesFromSalesforce.put(cartItem.Sku, cartItem.SalesPrice); } - - // Get all sale prices for the products in the cart (cart items) from an external service - // for the customer who owns the cart. - Map salesPricesFromExternalService = getSalesPricesFromExternalService(salesPricesFromSalesforce.keySet(), Id.valueOf(customerId)); - + + // Following snippet of code fetches a mocked static json response from getSalesPricesFromStaticResponse. + // Another example that demonstrates how to call a live 3rd party HTTP Service to fetch the desired + // response is implemented in getSalesPricesFromExternalService method. + Map salesPricesFromService = null; + if(useHTTPService) { + salesPricesFromService = getSalesPricesFromExternalService(salesPricesFromSalesforce.keySet(), Id.valueOf(customerId)); + } else { + salesPricesFromService = getSalesPricesFromStaticResponse(salesPricesFromSalesforce.keySet(), Id.valueOf(customerId)); + } + // For each cart item SKU, check that the price from the external service // is the same as the sale price in the cart. // If that is not true, set the integration status to "Failed". for (String sku : salesPricesFromSalesforce.keySet()) { Decimal salesPriceFromSalesforce = salesPricesFromSalesforce.get(sku); - Decimal salesPriceFromExternalService = (Decimal)salesPricesFromExternalService.get(sku); + Decimal salesPriceFromExternalService = (Decimal)salesPricesFromService.get(sku); if (salesPriceFromExternalService == null){ String errorMessage = 'The product with sku ' + sku + ' could not be found in the external system'; return integrationStatusFailedWithCartValidationOutputError( @@ -46,22 +56,22 @@ global with sharing class B2BPricingSample implements sfdc_checkout.CartPriceCal jobInfo, cartId ); - } + } else if (salesPriceFromExternalService != salesPriceFromSalesforce){ // Add your logic here for when the price from your external service // does not match what we have in Salesforce. // For example, you may want to cause your pricing integration to fail. // EXAMPLE: integStatus.status = sfdc_checkout.IntegrationStatus.Status.FAILED; - // + // // Our Heroku external service is a test service and returns a sale price of 0.00 for any SKU except 'SKU_FOR_TEST'. // If the SKU of the product is 'SKU_FOR_TEST', the price returned by the external service is 100. // For testing purposes, we set the integration status to SUCCESS if salesPriceFromExternalService is 0.00, - // regardless of the value of the Salesforce price + // regardless of the value of the Salesforce price if (salesPriceFromExternalService == 0.00){ integStatus.status = sfdc_checkout.IntegrationStatus.Status.SUCCESS; } else { - String errorMessage = 'The sale price has changed for the product with sku ' + sku + ': was ' + String errorMessage = 'The sale price has changed for the product with sku ' + sku + ': was ' + salesPriceFromSalesforce + ', but now is ' + salesPriceFromExternalService + '.'; return integrationStatusFailedWithCartValidationOutputError( @@ -71,7 +81,7 @@ global with sharing class B2BPricingSample implements sfdc_checkout.CartPriceCal cartId ); } - // ----- End of the section that is only for testing. + // ----- End of the section that is only for testing. } else { // If the prices in the external system are the same as the prices in Salesforce, set integration status as SUCCESS. @@ -92,22 +102,37 @@ global with sharing class B2BPricingSample implements sfdc_checkout.CartPriceCal } return integStatus; } - - private Map getSalesPricesFromExternalService (Set skus, String customerId) { - Http http = new Http(); - HttpRequest request = new HttpRequest(); - Integer SuccessfulHttpRequest = 200; - // Encode the product SKUs to avoid any invalid characters in the request URL. - Set encodedSkus = new Set(); - for (String sku : skus) { - encodedSkus.add(EncodingUtil.urlEncode(sku, 'UTF-8')); + private Map getSalesPricesFromStaticResponse(Set skus, String customerId) { + if (skus.isEmpty()) { + return (Map) JSON.deserializeUntyped('{"error":"Input SKUs list is empty or undefined."}'); } - // To access the service below you may need to add endpoint = https://b2b-commerce-test.herokuapp.com in Setup | Security | Remote site settings. - request.setEndpoint('https://b2b-commerce-test.herokuapp.com/get-sales-prices?customerId=' - + customerId + '&skus=' + JSON.serialize(encodedSkus)); - request.setMethod('GET'); + String responseJson = '{'; + for(String sku : skus) { + Double price = 0.00; + if (sku == 'SKU_FOR_TEST') { + price = 100.00; + } + responseJson = responseJson + '"'+sku+'"'; + responseJson = responseJson + ':'; + responseJson = responseJson + price; + responseJson = responseJson + ','; + } + responseJson = responseJson.removeEnd(',') + '}'; + return (Map) JSON.deserializeUntyped(responseJson); + } + + private Map getSalesPricesFromExternalService(Set skus, String customerId) { + Integer successfulHttpRequest = 200; + Http http = new Http(); + HttpRequest request = new HttpRequest(); + String requestURL = httpHost + '/get-sales-prices'; + String requestBody = '{"skus":' + JSON.serialize(skus) + '}'; + request.setEndpoint(requestURL); + request.setMethod('POST'); + request.setHeader('Content-Type', 'application/json'); + request.setBody(requestBody); HttpResponse response = http.send(request); // If the request is successful, parse the JSON response. // The response includes the sale price for each SKU and looks something like this: @@ -115,15 +140,16 @@ global with sharing class B2BPricingSample implements sfdc_checkout.CartPriceCal // Because this is a sample only and we want this integration to return success in order to allow the checkout to pass, // the external service created for this sample returns the exact list of SKUs it receives, // and the same sale price 0.00 for each SKU. - if (response.getStatusCode() == SuccessfulHttpRequest) { + if (response.getStatusCode() == successfulHttpRequest) { Map salesPricesFromExternalService = (Map) JSON.deserializeUntyped(response.getBody()); return salesPricesFromExternalService; - } - else { + } else if(response.getStatusCode() == 404) { + throw new CalloutException ('404. You must create a sample application or add your own service which returns a valid response'); + } else { throw new CalloutException ('There was a problem with the request. Error: ' + response.getStatusCode()); } } - + private sfdc_checkout.IntegrationStatus integrationStatusFailedWithCartValidationOutputError( sfdc_checkout.IntegrationStatus integrationStatus, String errorMessage, sfdc_checkout.IntegrationInfo jobInfo, Id cartId) { integrationStatus.status = sfdc_checkout.IntegrationStatus.Status.FAILED; @@ -148,4 +174,4 @@ global with sharing class B2BPricingSample implements sfdc_checkout.CartPriceCal insert(cartValidationError); return integrationStatus; } -} \ No newline at end of file +} diff --git a/examples/checkout/integrations/classes/B2BPricingSample.cls-meta.xml b/examples/checkout/integrations/classes/B2BPricingSample.cls-meta.xml index 4b0bc9f3..b1a915c9 100644 --- a/examples/checkout/integrations/classes/B2BPricingSample.cls-meta.xml +++ b/examples/checkout/integrations/classes/B2BPricingSample.cls-meta.xml @@ -1,5 +1,5 @@ - 55.0 + 59.0 Active diff --git a/examples/checkout/integrations/classes/B2BPricingSampleTest.cls b/examples/checkout/integrations/classes/B2BPricingSampleTest.cls index 6f2fe547..feae0670 100644 --- a/examples/checkout/integrations/classes/B2BPricingSampleTest.cls +++ b/examples/checkout/integrations/classes/B2BPricingSampleTest.cls @@ -3,32 +3,23 @@ public class B2BPricingSampleTest { @testSetup static void setup() { Account testAccount = new Account(Name='TestAccount'); insert testAccount; - WebStore testWebStore = new WebStore(Name='TestWebStore', DefaultLanguage='en_US'); + WebStore testWebStore = new WebStore(Name='TestWebStore', SupportedLanguages='en_US', DefaultLanguage='en_US'); insert testWebStore; - + Account account = [SELECT Id FROM Account WHERE Name='TestAccount' LIMIT 1]; WebStore webStore = [SELECT Id FROM WebStore WHERE Name='TestWebStore' LIMIT 1]; WebCart cart = new WebCart(Name='Cart', WebStoreId=webStore.Id, AccountId=account.Id); insert cart; - + CartDeliveryGroup cartDeliveryGroup = new CartDeliveryGroup(CartId=cart.Id, Name='Default Delivery'); insert cartDeliveryGroup; - + CartItem cartItem = new CartItem(CartId=cart.Id, Sku='SKU_Test1', SalesPrice=10.00, Quantity=3.0, Type='Product', Name='TestProduct', CartDeliveryGroupId=cartDeliveryGroup.Id); insert cartItem; } - + @isTest static void testWhenSalesPriceIsCorrectSuccessStatusIsReturned() { - // Because test methods do not support Web service callouts, we create a mock response based on a static resource. - // To create the static resource from the Developer Console, select File | New | Static Resource - StaticResourceCalloutMock mock = new StaticResourceCalloutMock(); - mock.setStaticResource('GetSalesPricesResource'); - mock.setStatusCode(200); - mock.setHeader('Content-Type', 'application/json;charset=UTF-8'); Test.startTest(); - // Associate the callout with a mock response. - Test.setMock(HttpCalloutMock.class, mock); - // Test: execute the integration for the test cart ID. B2BPricingSample apexSample = new B2BPricingSample(); WebCart webCart = [SELECT Id FROM WebCart WHERE Name = 'Cart' LIMIT 1]; @@ -36,33 +27,6 @@ public class B2BPricingSampleTest { System.assertEquals(sfdc_checkout.IntegrationStatus.Status.SUCCESS, integrationResult.status); Test.stopTest(); } - - @isTest static void testWhenExternalServiceCallFailsAFailedStatusIsReturnedAndACartValidationOutputEntryIsCreated() { - // Because test methods do not support Web service callouts, we create a mock response based on a static resource. - // To create the static resource from the Developer Console, select File | New | Static Resource - StaticResourceCalloutMock mock = new StaticResourceCalloutMock(); - mock.setStaticResource('GetSalesPricesResource'); - // The web service call returns an error code. - mock.setStatusCode(404); - mock.setHeader('Content-Type', 'application/json;charset=UTF-8'); - Test.startTest(); - // Associate the callout with a mock response. - Test.setMock(HttpCalloutMock.class, mock); - - // Test: execute the integration for the test cart ID and integration info. - B2BPricingSample apexSample = new B2BPricingSample(); - sfdc_checkout.IntegrationInfo integInfo = new sfdc_checkout.IntegrationInfo(); - integInfo.jobId = null; - WebCart webCart = [SELECT Id FROM WebCart WHERE Name = 'Cart' LIMIT 1]; - sfdc_checkout.IntegrationStatus integrationResult = apexSample.startCartProcessAsync(integInfo, webCart.Id); - - // Validate: IntegrationStatus.Status is FAILED - // and a new CartValidationOutput record with level 'Error' was created. - System.assertEquals(sfdc_checkout.IntegrationStatus.Status.FAILED, integrationResult.status); - List cartValidationOutputs = [SELECT Id FROM CartValidationOutput WHERE Level = 'Error']; - System.assertEquals(1, cartValidationOutputs.size()); - Test.stopTest(); - } @isTest static void testProductsWithNoSkuHasError() { Test.startTest(); @@ -90,8 +54,8 @@ public class B2BPricingSampleTest { System.assertEquals(sfdc_checkout.IntegrationStatus.Status.FAILED, integrationResult.status); List cartValidationOutputs = [SELECT Id, Message FROM CartValidationOutput WHERE Level = 'Error']; System.assertEquals(1, cartValidationOutputs.size()); - - // Validate: The sample text that a product SKU is missing is returned as the failure output + + // Validate: The sample text that a product SKU is missing is returned as the failure output System.assertEquals('The SKUs for all products in your cart must be defined.', cartValidationOutputs.get(0).Message); Test.stopTest(); diff --git a/examples/checkout/integrations/classes/B2BPricingSampleTest.cls-meta.xml b/examples/checkout/integrations/classes/B2BPricingSampleTest.cls-meta.xml index 4b0bc9f3..b1a915c9 100644 --- a/examples/checkout/integrations/classes/B2BPricingSampleTest.cls-meta.xml +++ b/examples/checkout/integrations/classes/B2BPricingSampleTest.cls-meta.xml @@ -1,5 +1,5 @@ - 55.0 + 59.0 Active diff --git a/examples/checkout/integrations/classes/B2BTaxSample.cls b/examples/checkout/integrations/classes/B2BTaxSample.cls index 9f932007..04a2450d 100644 --- a/examples/checkout/integrations/classes/B2BTaxSample.cls +++ b/examples/checkout/integrations/classes/B2BTaxSample.cls @@ -1,6 +1,11 @@ // This must implement the sfdc_checkout.CartTaxCalculations interface // in order to be processed by the checkout flow and used for your Taxes integration. global with sharing class B2BTaxSample implements sfdc_checkout.CartTaxCalculations { + // You MUST change this to be your service or you must launch your own Heroku Service + // and add the host in Setup | Security | Remote site settings. + private static String httpHost = 'https://example.com'; + private static Boolean useHTTPService = false; + private class ApplicationException extends Exception {} global sfdc_checkout.IntegrationStatus startCartProcessAsync(sfdc_checkout.IntegrationInfo jobInfo, Id cartId) { sfdc_checkout.IntegrationStatus integStatus = new sfdc_checkout.IntegrationStatus(); try { @@ -38,11 +43,16 @@ global with sharing class B2BTaxSample implements sfdc_checkout.CartTaxCalculati cartItemTotalPriceBySKU.put(cartItemSKU, cartItem.TotalPrice); } - // Get the tax rates and tax amounts from an external service - // Other parameters will be passed here, like ship_from, bill_to, more details about the ship_to, etc. - Map rateAndAmountFromExternalServicePerSku = getTaxRatesAndAmountsFromExternalService( - cartItemTotalPriceBySKU, deliveryGroup.DeliverToState, deliveryGroup.DeliverToCountry - ); + // Following snippet of code fetches a mocked static json response from getDataFromStaticResponse. + // Another example that demonstrates how to call a live 3rd party HTTP Service to fetch the desired + // response is implemented in getDataFromExternalService method. + + Map rateAndAmountFromExternalServicePerSku = null; + if(useHTTPService) { + rateAndAmountFromExternalServicePerSku = getTaxRatesAndAmountsFromExternalService(cartItemTotalPriceBySKU, deliveryGroup.DeliverToState, deliveryGroup.DeliverToCountry); + } else { + rateAndAmountFromExternalServicePerSku = getDataFromStaticResponse(cartItemTotalPriceBySKU, deliveryGroup.DeliverToState, deliveryGroup.DeliverToCountry); + } // If there are taxes from a previously cancelled checkout, delete them. List cartItemIds = cartItemIdsBySKU.values(); @@ -96,12 +106,30 @@ global with sharing class B2BTaxSample implements sfdc_checkout.CartTaxCalculati } return integStatus; } + + private Map getDataFromStaticResponse(Map cartItemTotalAmountBySKU, String state, String country) { + if (cartItemTotalAmountBySKU == null) { + throw new ApplicationException('Input SKUs list is empty or undefined.'); + } + + Decimal taxRate = 0.08; + + Map taxDataFromStaticServiceBySKU = new Map(); + for (String sku : cartItemTotalAmountBySKU.keySet()) { + taxDataFromStaticServiceBySKU.put(sku, new TaxDataFromExternalService( + taxRate, + cartItemTotalAmountBySKU.get(sku) * taxRate, + 'GST' + )); + } + return taxDataFromStaticServiceBySKU; + } private Map getTaxRatesAndAmountsFromExternalService ( Map cartItemTotalAmountBySKU, String state, String country) { Http http = new Http(); HttpRequest request = new HttpRequest(); - Integer SuccessfulHttpRequest = 200; + Integer successfulHttpRequest = 200; String encodedState = (state == null) ? '' : EncodingUtil.urlEncode(state, 'UTF-8').replace('+', '%20'); String encodedCountry = (country == null) ? '' : EncodingUtil.urlEncode(country, 'UTF-8').replace('+', '%20'); @@ -110,8 +138,7 @@ global with sharing class B2BTaxSample implements sfdc_checkout.CartTaxCalculati encodedCartItemTotalAmountBySKU.put(EncodingUtil.urlEncode(sku, 'UTF-8'), cartItemTotalAmountBySKU.get(sku)); } - // To access the service below, you may need to add endpoint = https://b2b-commerce-test.herokuapp.com in Setup | Security | Remote site settings. - String requestURL = 'https://b2b-commerce-test.herokuapp.com/get-tax-rates?state=' + encodedState + String requestURL = httpHost + '/get-tax-rates?state=' + encodedState + '&country=' + encodedCountry + '&amountsBySKU=' + JSON.serialize(encodedCartItemTotalAmountBySKU); request.setEndpoint(requestURL); @@ -121,7 +148,7 @@ global with sharing class B2BTaxSample implements sfdc_checkout.CartTaxCalculati // If the request is successful, parse the JSON response; // The response includes the tax amount, rate, and name for each SKU. It looks something like this: // {"SKU_1_september10-1568355297":{"taxAmount":2.8229012971048855,"taxRate":0.08,"taxName":"GST"},"SKU_0_september10-1568355296":{"taxAmount":5.0479003481482385,"taxRate":0.08,"taxName":"GST"}} - if (response.getStatusCode() == SuccessfulHttpRequest) { + if (response.getStatusCode() == successfulHttpRequest) { Map resultsFromExternalServiceBySKU = (Map) JSON.deserializeUntyped(response.getBody()); Map taxDataFromExternalServiceBySKU = new Map(); for (String sku : resultsFromExternalServiceBySKU.keySet()) { @@ -133,8 +160,9 @@ global with sharing class B2BTaxSample implements sfdc_checkout.CartTaxCalculati )); } return taxDataFromExternalServiceBySKU; - } - else { + } else if(response.getStatusCode() == 404) { + throw new CalloutException ('404. You must create a sample application or add your own service which returns a valid response'); + } else { throw new CalloutException ('There was a problem with the request. Error: ' + response.getStatusCode()); } } diff --git a/examples/checkout/integrations/classes/B2BTaxSample.cls-meta.xml b/examples/checkout/integrations/classes/B2BTaxSample.cls-meta.xml index 4b0bc9f3..b1a915c9 100644 --- a/examples/checkout/integrations/classes/B2BTaxSample.cls-meta.xml +++ b/examples/checkout/integrations/classes/B2BTaxSample.cls-meta.xml @@ -1,5 +1,5 @@ - 55.0 + 59.0 Active diff --git a/examples/checkout/integrations/classes/B2BTaxSampleTest.cls b/examples/checkout/integrations/classes/B2BTaxSampleTest.cls index 71dc745b..e44c21f9 100644 --- a/examples/checkout/integrations/classes/B2BTaxSampleTest.cls +++ b/examples/checkout/integrations/classes/B2BTaxSampleTest.cls @@ -3,41 +3,32 @@ public class B2BTaxSampleTest { @testSetup static void setup() { Account account = new Account(Name='TestAccount'); insert account; - WebStore webStore = new WebStore(Name='TestWebStore', DefaultLanguage='en_US'); + WebStore webStore = new WebStore(Name='TestWebStore', SupportedLanguages='en_US', DefaultLanguage='en_US'); insert webStore; WebCart cart = new WebCart(Name='Cart', WebStoreId=webStore.Id, AccountId=account.Id); insert cart; CartDeliveryGroup cartDeliveryGroup = new CartDeliveryGroup(CartId=cart.Id, Name='Default Delivery'); insert cartDeliveryGroup; - + CartItem cartItem = new CartItem( - CartId=cart.Id, - Sku='SKU_Test1', - Quantity=3.0, - Type='Product', - Name='TestProduct', + CartId=cart.Id, + Sku='SKU_Test1', + Quantity=3.0, + Type='Product', + Name='TestProduct', CartDeliveryGroupId=cartDeliveryGroup.Id ); insert cartItem; } - + @isTest static void testCartTaxForCartItemSuccessfullyInserted() { - // Because test methods don't support Web service callouts, we create a mock response based on a static resource. - // To create the static resource from the Developer Console, select File | New | Static Resource - StaticResourceCalloutMock mock = new StaticResourceCalloutMock(); - mock.setStaticResource('GetTaxesResource'); - mock.setStatusCode(200); - mock.setHeader('Content-Type', 'application/json;charset=UTF-8'); Test.startTest(); - // Associate the callout with a mock response. - Test.setMock(HttpCalloutMock.class, mock); - // Test: execute the integration for the test cart ID. B2BTaxSample apexSample = new B2BTaxSample(); Id webCartId = [SELECT Id FROM WebCart WHERE Name = 'Cart' LIMIT 1].Id; Id cartItemId = [SELECT Id FROM CartItem WHERE CartId = :webCartId LIMIT 1].Id; sfdc_checkout.IntegrationStatus integrationResult = apexSample.startCartProcessAsync(null, webCartId); - + // Verify: the integration executed successfully // and the new CartTax record is inserted. System.assertEquals(sfdc_checkout.IntegrationStatus.Status.SUCCESS, integrationResult.status); @@ -45,37 +36,9 @@ public class B2BTaxSampleTest { System.assertEquals(1, cartTaxesForCartItem.size()); Test.stopTest(); } - - @isTest static void testWhenExternalServiceCallFailsAFailedStatusIsReturnedAndACartValidationOutputEntryIsCreated() { - // Because test methods don't support Web service callouts, we create a mock response based on a static resource. - // To create the static resource from the Developer Console, select File | New | Static Resource - StaticResourceCalloutMock mock = new StaticResourceCalloutMock(); - mock.setStaticResource('GetInventoryResource'); - // The web service call returns an error code. - mock.setStatusCode(404); - mock.setHeader('Content-Type', 'application/json;charset=UTF-8'); - Test.startTest(); - // Associate the callout with a mock response. - Test.setMock(HttpCalloutMock.class, mock); - - // Test: execute the integration for the test cart ID and integration info. - B2BTaxSample apexSample = new B2BTaxSample(); - sfdc_checkout.IntegrationInfo integInfo = new sfdc_checkout.IntegrationInfo(); - integInfo.jobId = null; - WebCart webCart = [SELECT Id FROM WebCart WHERE Name = 'Cart' LIMIT 1]; - sfdc_checkout.IntegrationStatus integrationResult = apexSample.startCartProcessAsync(integInfo, webCart.Id); - - // Validate: IntegrationStatus.Status is FAILED - // and a new CartValidationOutput record with level 'Error' was created. - System.assertEquals(sfdc_checkout.IntegrationStatus.Status.FAILED, integrationResult.status); - List cartValidationOutputs = [SELECT Id FROM CartValidationOutput WHERE Level = 'Error']; - System.assertEquals(1, cartValidationOutputs.size()); - Test.stopTest(); - } @isTest static void testProductsWithNoSkuHasError() { Test.startTest(); - WebCart webCart = [SELECT Id FROM WebCart WHERE Name = 'Cart' LIMIT 1]; List cartDeliveryGroups = [SELECT Id FROM CartDeliveryGroup WHERE CartId = :webCart.Id LIMIT 1]; @@ -99,12 +62,12 @@ public class B2BTaxSampleTest { System.assertEquals(sfdc_checkout.IntegrationStatus.Status.FAILED, integrationResult.status); List cartValidationOutputs = [SELECT Id, Message FROM CartValidationOutput WHERE Level = 'Error']; System.assertEquals(1, cartValidationOutputs.size()); - - // Validate: The sample text that a product SKU is missing is returned as the failure output + + // Validate: The sample text that a product SKU is missing is returned as the failure output System.assertEquals('The SKUs for all products in your cart must be defined.', cartValidationOutputs.get(0).Message); Test.stopTest(); // Remove the invalid cart item delete cartItemWithNoSku; } -} \ No newline at end of file +} diff --git a/examples/checkout/integrations/classes/B2BTaxSampleTest.cls-meta.xml b/examples/checkout/integrations/classes/B2BTaxSampleTest.cls-meta.xml index 4b0bc9f3..b1a915c9 100644 --- a/examples/checkout/integrations/classes/B2BTaxSampleTest.cls-meta.xml +++ b/examples/checkout/integrations/classes/B2BTaxSampleTest.cls-meta.xml @@ -1,5 +1,5 @@ - 55.0 + 59.0 Active diff --git a/examples/checkout/integrations/remoteSiteSettings/Heroku_test_for_B2B_lightning.remoteSite b/examples/checkout/integrations/remoteSiteSettings/Heroku_test_for_B2B_lightning.remoteSite index 8a1af702..cb939f96 100644 --- a/examples/checkout/integrations/remoteSiteSettings/Heroku_test_for_B2B_lightning.remoteSite +++ b/examples/checkout/integrations/remoteSiteSettings/Heroku_test_for_B2B_lightning.remoteSite @@ -2,5 +2,5 @@ false true - https://b2b-commerce-test.herokuapp.com + https://example.com diff --git a/examples/checkout/payment-gateway-integration/Salesforce/namedCredentials/Salesforce.namedCredential b/examples/checkout/payment-gateway-integration/Salesforce/namedCredentials/Salesforce.namedCredential index 05a0b9a3..4c364973 100644 --- a/examples/checkout/payment-gateway-integration/Salesforce/namedCredentials/Salesforce.namedCredential +++ b/examples/checkout/payment-gateway-integration/Salesforce/namedCredentials/Salesforce.namedCredential @@ -8,5 +8,4 @@ NamedUser Password UserName - Password - \ No newline at end of file + diff --git a/examples/lwc/README.md b/examples/lwc/README.md index ba4f807f..88455421 100644 --- a/examples/lwc/README.md +++ b/examples/lwc/README.md @@ -14,7 +14,7 @@ This repository is an SFDX project that you can deploy directly to an org and mo 1. If you haven't already, clone this repository. 1. If you haven't already, create a B2B Commerce org. - Optional: Use the included [project-scratch-def.json](config/project-scratch-def.json), e.g. `sfdx force:org:create -f ./config/project-scratch-def.json` + Optional: Use the included [project-scratch-def.json](config/project-scratch-def.json), e.g. `sfdx force:org:create -f ./config/project-scratch-def.json` 1. Push the source code in this repository to the new org, e.g. `sfdx force:source:push -u `. 1. Grant permissions to the APEX class (do this only once): @@ -47,7 +47,7 @@ When LMS is supported in B2B Commerce for Lightning (Safe Harbor), we’ll updat The productDetails component demonstrates how to call an external API. In our example, we call a [Demo Inventory Manager](https://inventorymanagerdemo.herokuapp.com/api/inventory/) External Service, which returns a product’s availability as a simple Boolean value. To enable this demo service in your org: 1. From Setup, enter Remote Site Settings in the Quick Find box, then select Remote Site Settings. - This page displays a list of any remote sites that are already registered. It provides additional information about each site, including remote site name and URL. + This page displays a list of any remote sites that are already registered. It provides additional information about each site, including remote site name and URL. 1. Click New Remote Site. 1. For the Remote Site Name, enter Demo Inventory Manager. 1. For the remote site URL, enter https://inventorymanagerdemo.herokuapp.com. @@ -56,11 +56,11 @@ The productDetails component demonstrates how to call an external API. In our ex ## Search-specific Steps (to use Named Credentials) -Connect APIs for search don't have Apex enabled yet. So we can call those Connect APIs only through REST from Apex classes. For security reasons, the Lightning Component framework places restrictions on making API calls from JavaScript. +Connect APIs for search don't have Apex enabled yet. So we can call those Connect APIs only through REST from Apex classes. For security reasons, the Lightning Component framework places restrictions on making API calls from JavaScript. -* To call third-party APIs from your component’s JavaScript, add the API endpoint as a CSP Trusted Site. -* To call Salesforce APIs, make the API calls from your component’s Apex controller. Use a named credential to authenticate to Salesforce. (Documentation is [here](https://developer.salesforce.com/docs/atlas.en-us.lightning.meta/lightning/apex_api_calls.htm) and [here](https://developer.salesforce.com/docs/atlas.en-us.228.0.apexcode.meta/apexcode/apex_callouts_named_credentials.htm).) -* Create a Named Credential callout. The steps are documented [here](/examples/lwc/docs/NamedCredentials.md). +- To call third-party APIs from your component’s JavaScript, add the API endpoint as a CSP Trusted Site. +- To call Salesforce APIs, make the API calls from your component’s Apex controller. Use a named credential to authenticate to Salesforce. (Documentation is [here](https://developer.salesforce.com/docs/atlas.en-us.lightning.meta/lightning/apex_api_calls.htm) and [here](https://developer.salesforce.com/docs/atlas.en-us.228.0.apexcode.meta/apexcode/apex_callouts_named_credentials.htm).) +- Create a Named Credential callout. The steps are documented [here](/examples/lwc/docs/NamedCredentials.md). ## Known Issues @@ -70,4 +70,4 @@ Debugging with the flow typically requires impersonating a buyer [Run flow as an 1. Don't debug and instead run as the buyer within the store relying on errors sent to the email specified in `Process Automation Settings` to find problems. 1. If you know the buyer's account you can make a change in [B2BPaymentController.cls](force-app/main/default/classes/B2BPaymentController.cls). Directions are specified near the top of `getPaymentInfo()`. -1. You can also make a change in the `getUserAccountInfo()` method in [B2BUtils.cls](force-app/main/default/classes/B2BUtils.cls). Here you would put the ID of the user instead of the call to `UserInfo.getUserId();`. This was not documented within the class as the effects would be farther reaching than in B2BPaymentController.cls. \ No newline at end of file +1. You can also make a change in the `getUserAccountInfo()` method in [B2BUtils.cls](force-app/main/default/classes/B2BUtils.cls). Here you would put the ID of the user instead of the call to `UserInfo.getUserId();`. This was not documented within the class as the effects would be farther reaching than in B2BPaymentController.cls. diff --git a/examples/lwc/force-app/main/default/lwc/billingAddressSelector/billingAddressSelector.js b/examples/lwc/force-app/main/default/lwc/billingAddressSelector/billingAddressSelector.js index f0fd8393..f6ef58c3 100644 --- a/examples/lwc/force-app/main/default/lwc/billingAddressSelector/billingAddressSelector.js +++ b/examples/lwc/force-app/main/default/lwc/billingAddressSelector/billingAddressSelector.js @@ -53,7 +53,7 @@ export default class AddressSelector extends LightningElement { * The title of the billing address selector. * @type {String} */ - title = 'Billing Address'; + @api title; /** * Determines if the billing address selector field should be required. diff --git a/examples/lwc/force-app/main/default/lwc/cardPaymentMethod/constants.js b/examples/lwc/force-app/main/default/lwc/cardPaymentMethod/constants.js index 293afae5..5d56c15d 100644 --- a/examples/lwc/force-app/main/default/lwc/cardPaymentMethod/constants.js +++ b/examples/lwc/force-app/main/default/lwc/cardPaymentMethod/constants.js @@ -17,8 +17,8 @@ export const labels = { CvvPlaceholder: 'Enter a CVV...', ExpiryMonthPlaceholder: 'MM', ExpiryYearPlaceholder: 'YYYY', - CvvPlaceholder: 'Enter a CVV...', - CvvInfo: 'Find the CVC/CVV security code on the back of your credit card. The code is three or four digits, depending on the card.' + CvvInfo: + 'Find the CVC/CVV security code on the back of your credit card. The code is three or four digits, depending on the card.' }; export const cardLabels = { diff --git a/examples/lwc/force-app/main/default/lwc/navigationButtons/navigationButtons.js-meta.xml b/examples/lwc/force-app/main/default/lwc/navigationButtons/navigationButtons.js-meta.xml index 8bfc0eaa..87b4b7b4 100644 --- a/examples/lwc/force-app/main/default/lwc/navigationButtons/navigationButtons.js-meta.xml +++ b/examples/lwc/force-app/main/default/lwc/navigationButtons/navigationButtons.js-meta.xml @@ -14,4 +14,4 @@ - \ No newline at end of file + diff --git a/examples/lwc/force-app/main/default/lwc/paymentMethod/constants.js b/examples/lwc/force-app/main/default/lwc/paymentMethod/constants.js index 4084e43e..828fe110 100644 --- a/examples/lwc/force-app/main/default/lwc/paymentMethod/constants.js +++ b/examples/lwc/force-app/main/default/lwc/paymentMethod/constants.js @@ -1,9 +1,9 @@ -export const PaymentTypeEnum = Object.freeze({ +export const PaymentTypeEnum = Object.freeze({ PONUMBER: 'PurchaseOrderNumber', CARDPAYMENT: 'CardPayment' }); -export const labels = { +export const labels = { paymentMethodHeader: 'Payment Method', purchaseOrderOptionLabel: 'Purchase Order', purchaseOrderEntryHeader: 'Enter PO Number', diff --git a/examples/lwc/force-app/main/default/lwc/paymentMethod/paymentMethod.html b/examples/lwc/force-app/main/default/lwc/paymentMethod/paymentMethod.html index f8ebf036..00f93c2e 100644 --- a/examples/lwc/force-app/main/default/lwc/paymentMethod/paymentMethod.html +++ b/examples/lwc/force-app/main/default/lwc/paymentMethod/paymentMethod.html @@ -19,7 +19,6 @@
-
diff --git a/examples/lwc/force-app/main/default/lwc/paymentMethod/paymentMethod.js b/examples/lwc/force-app/main/default/lwc/paymentMethod/paymentMethod.js index 04fd9089..6bb627db 100644 --- a/examples/lwc/force-app/main/default/lwc/paymentMethod/paymentMethod.js +++ b/examples/lwc/force-app/main/default/lwc/paymentMethod/paymentMethod.js @@ -1,5 +1,8 @@ import { LightningElement, api, track } from 'lwc'; -import { FlowNavigationNextEvent, FlowNavigationBackEvent } from 'lightning/flowSupport'; +import { + FlowNavigationNextEvent, + FlowNavigationBackEvent +} from 'lightning/flowSupport'; import * as Constants from './constants'; import getPaymentInfo from '@salesforce/apex/B2BPaymentController.getPaymentInfo'; @@ -121,7 +124,7 @@ export default class PaymentMethod extends LightningElement { @api nextButtonLabel = 'Next'; /** - * The list of labels used in the cmp. + * The list of labels used in the cmp. * @type {String} */ get labels() { @@ -232,7 +235,10 @@ export default class PaymentMethod extends LightningElement { * @returns {Boolean} True if "BACK" is found, False otherwise */ get canGoPrevious() { - return (this.availableActions && this.availableActions.some(element => element == 'BACK')); + return ( + this.availableActions && + this.availableActions.some((element) => element == 'BACK') + ); } /** @@ -264,7 +270,7 @@ export default class PaymentMethod extends LightningElement { get isPoNumberSelected() { return ( this.actualSelectedPaymentType === - Constants.PaymentTypeEnum.PONUMBER && !this.hidePurchaseOrder + Constants.PaymentTypeEnum.PONUMBER && !this.hidePurchaseOrder ); } @@ -276,8 +282,10 @@ export default class PaymentMethod extends LightningElement { */ get actualSelectedPaymentType() { return this.hidePurchaseOrder - ? Constants.PaymentTypeEnum.CARDPAYMENT - : (this.hideCreditCard ? Constants.PaymentTypeEnum.PONUMBER : this._selectedPaymentType); + ? Constants.PaymentTypeEnum.CARDPAYMENT + : this.hideCreditCard + ? Constants.PaymentTypeEnum.PONUMBER + : this._selectedPaymentType; } /** @@ -340,12 +348,9 @@ export default class PaymentMethod extends LightningElement { return; } - const poInput = this.getComponent('[data-po-number]'); + const poInput = this.getComponent('[data-po-number]'); // Make sure that PO input is valid first - if ( - poInput != null && - !poInput.reportValidity() - ) { + if (poInput != null && !poInput.reportValidity()) { return; } @@ -358,13 +363,15 @@ export default class PaymentMethod extends LightningElement { cartId: this.cartId, billingAddress: selectedAddressResult.address, paymentInfo: paymentInfo - }).then(() => { - // After making the server calls, navigate NEXT in the flow - const navigateNextEvent = new FlowNavigationNextEvent(); - this.dispatchEvent(navigateNextEvent); - }).catch((error) => { - this._purchaseOrderErrorMessage = error.body.message; - }); + }) + .then(() => { + // After making the server calls, navigate NEXT in the flow + const navigateNextEvent = new FlowNavigationNextEvent(); + this.dispatchEvent(navigateNextEvent); + }) + .catch((error) => { + this._purchaseOrderErrorMessage = error.body.message; + }); } else { if (selectedAddressResult.error) { this._creditCardErrorMessage = selectedAddressResult.error; @@ -387,19 +394,21 @@ export default class PaymentMethod extends LightningElement { const creditCardData = this.getCreditCardFromComponent( creditPaymentComponent ); - + setPayment({ paymentType: this.selectedPaymentType, cartId: this.cartId, billingAddress: selectedAddressResult.address, paymentInfo: creditCardData - }).then(() => { - // After making the server calls, navigate NEXT in the flow - const navigateNextEvent = new FlowNavigationNextEvent(); - this.dispatchEvent(navigateNextEvent); - }).catch((error) => { - this._creditCardErrorMessage = error.body.message; - }); + }) + .then(() => { + // After making the server calls, navigate NEXT in the flow + const navigateNextEvent = new FlowNavigationNextEvent(); + this.dispatchEvent(navigateNextEvent); + }) + .catch((error) => { + this._creditCardErrorMessage = error.body.message; + }); } } @@ -414,7 +423,11 @@ export default class PaymentMethod extends LightningElement { return { error: 'Billing Address is required' }; } } else { - return { address: this._addresses.filter(add => add.id === this.selectedBillingAddress)[0] }; + return { + address: this._addresses.filter( + (add) => add.id === this.selectedBillingAddress + )[0] + }; } return {}; @@ -441,7 +454,7 @@ export default class PaymentMethod extends LightningElement { */ handleChangeSelectedAddress(event) { const address = event.detail.address; - if (address.id !== null && (address.id).startsWith('8lW')) { + if (address.id !== null && address.id.startsWith('8lW')) { this._selectedBillingAddress = address.id; } else { this._selectedBillingAddress = ''; diff --git a/examples/lwc/force-app/main/default/lwc/paymentMethod/paymentMethod.js-meta.xml b/examples/lwc/force-app/main/default/lwc/paymentMethod/paymentMethod.js-meta.xml index d17d9588..c029a8ff 100644 --- a/examples/lwc/force-app/main/default/lwc/paymentMethod/paymentMethod.js-meta.xml +++ b/examples/lwc/force-app/main/default/lwc/paymentMethod/paymentMethod.js-meta.xml @@ -34,4 +34,4 @@ - \ No newline at end of file + diff --git a/examples/lwc/yarn.lock b/examples/lwc/yarn.lock index 1afd7c43..a2959a43 100644 --- a/examples/lwc/yarn.lock +++ b/examples/lwc/yarn.lock @@ -1251,17 +1251,17 @@ resolved "https://registry.yarnpkg.com/@salesforce/wire-service-jest-util/-/wire-service-jest-util-2.4.2.tgz#dd61563e55337c5420e3ae2137d10cd3b1711e40" integrity sha512-yYf1AUhvxhEP9fJLrakogkdbNtrBiRprED+N6Vd3oGydDZrShdPwmYgqLKkzFR0HUw00LiSWaUO19yS1z6n0HA== -"@sideway/address@^4.1.0": - version "4.1.0" - resolved "https://registry.yarnpkg.com/@sideway/address/-/address-4.1.0.tgz#0b301ada10ac4e0e3fa525c90615e0b61a72b78d" - integrity sha512-wAH/JYRXeIFQRsxerIuLjgUu2Xszam+O5xKeatJ4oudShOOirfmsQ1D6LL54XOU2tizpCYku+s1wmU0SYdpoSA== +"@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.0": - version "3.0.0" - resolved "https://registry.yarnpkg.com/@sideway/formula/-/formula-3.0.0.tgz#fe158aee32e6bd5de85044be615bc08478a0a13c" - integrity sha512-vHe7wZ4NOXVfkoRb8T5otiENVlT7a3IAiw7H5M2+GO+9CDgcVUUsX1zalAztCmwyOr2RUTGJdgB+ZvSVqmdHmg== +"@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" @@ -1498,15 +1498,20 @@ ansi-escapes@^4.2.1, ansi-escapes@^4.3.0: type-fest "^0.11.0" ansi-regex@^4.1.0: - version "4.1.0" - resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-4.1.0.tgz#8b9f8f08cf1acb843756a839ca8c7e3168c51997" - integrity sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg== + version "4.1.1" + resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-4.1.1.tgz#164daac87ab2d6f6db3a29875e2d1766582dabed" + integrity sha512-ILlv4k/3f6vfQ4OoP2AGvirOktlQ98ZEL1k9FaQjxa3L1abBgbuTDAdPOpvbGncC0BTVQrl+OM8xZGK6tWXt7g== ansi-regex@^5.0.0: version "5.0.0" resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-5.0.0.tgz#388539f55179bf39339c81af30a654d69f87cb75" integrity sha512-bY6fj56OUQ0hU1KjFNDQuJFezqKdrAyFdIevADiqrWHwSlbmBNMHp5ak2f40Pm8JTFyM2mqxkG6ngkHO11f/lg== +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-styles@^3.2.0, ansi-styles@^3.2.1: version "3.2.1" resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-3.2.1.tgz#41fbb20243e50b12be0f04b8dedbf07520ce841d" @@ -1559,6 +1564,14 @@ arr-union@^3.1.0: resolved "https://registry.yarnpkg.com/arr-union/-/arr-union-3.1.0.tgz#e39b09aea9def866a8f206e288af63919bae39c4" integrity sha1-45sJrqne+Gao8gbiiK9jkZuuOcQ= +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-equal@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/array-equal/-/array-equal-1.0.0.tgz#8c2a5ef2472fd9ea742b04c77a75093ba2757c93" @@ -1628,6 +1641,11 @@ atob@^2.1.2: resolved "https://registry.yarnpkg.com/atob/-/atob-2.1.2.tgz#6d9517eb9e030d2436666651e86bd9f6f13533c9" integrity sha512-Wm6ukoaOGJi/73p/cl2GvLjTI5JM1k/O14isD73YML8StrH/7/lRFgmg8nICZgD3bZZvjwCGxtMOD3wWNAu8cg== +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== + aws-sign2@~0.7.0: version "0.7.0" resolved "https://registry.yarnpkg.com/aws-sign2/-/aws-sign2-0.7.0.tgz#b46e890934a9591f2d2f6f86d7e6a9f1b3fe76a8" @@ -1643,13 +1661,6 @@ axe-core@4.0.2: resolved "https://registry.yarnpkg.com/axe-core/-/axe-core-4.0.2.tgz#c7cf7378378a51fcd272d3c09668002a4990b1cb" integrity sha512-arU1h31OGFu+LPrOLGZ7nB45v940NMDMEJeNmbutu57P+UFDVnkZg3e+J1I2HJRZ9hT7gO8J91dn/PMrAiKakA== -axios@^0.19.2: - version "0.19.2" - resolved "https://registry.yarnpkg.com/axios/-/axios-0.19.2.tgz#3ea36c5d8818d0d5f8a8a97a6d36b86cdc00cb27" - integrity sha512-fjgm5MvRHLhx+osE2xoekY70AhARk3a6hkN+3Io1jc00jtquGvxYlKlsFUhmUET0V5te6CcZI7lcv2Ym61mjHA== - dependencies: - follow-redirects "1.5.10" - axios@^0.20.0: version "0.20.0" resolved "https://registry.yarnpkg.com/axios/-/axios-0.20.0.tgz#057ba30f04884694993a8cd07fa394cff11c50bd" @@ -1657,6 +1668,13 @@ axios@^0.20.0: dependencies: follow-redirects "^1.10.0" +axios@^0.21.1: + version "0.21.4" + resolved "https://registry.yarnpkg.com/axios/-/axios-0.21.4.tgz#c67b90dc0568e5c1cf2b0b858c43ba28e2eda575" + integrity sha512-ut5vewkiu8jjGBdqpM44XxjuCjq9LAKeHVmoVfHVzy8eHgxxq8SbAVQNovDA8mVi05kP0Ea/n/UzcSHcTJQfNg== + dependencies: + follow-redirects "^1.14.0" + babel-eslint@~10.1.0: version "10.1.0" resolved "https://registry.yarnpkg.com/babel-eslint/-/babel-eslint-10.1.0.tgz#6968e568a910b78fb3779cdd8b6ac2f479943232" @@ -1859,14 +1877,15 @@ browser-resolve@^1.11.3: resolve "1.1.7" browserslist@^4.0.0, browserslist@^4.6.3: - version "4.14.5" - resolved "https://registry.yarnpkg.com/browserslist/-/browserslist-4.14.5.tgz#1c751461a102ddc60e40993639b709be7f2c4015" - integrity sha512-Z+vsCZIvCBvqLoYkBFTwEYH3v5MCQbsAjp50ERycpOjnPmolg1Gjy4+KaWWpm8QOJt9GHkhdqAl14NpCX73CWA== + version "4.16.6" + resolved "https://registry.yarnpkg.com/browserslist/-/browserslist-4.16.6.tgz#d7901277a5a88e554ed305b183ec9b0c08f66fa2" + integrity sha512-Wspk/PqO+4W9qp5iUTJsa1B/QrYn1keNCcEP5OvP7WBwT4KaDly0uONYmC6Xa3Z5IqnUgS0KcgLYu1l74x0ZXQ== dependencies: - caniuse-lite "^1.0.30001135" - electron-to-chromium "^1.3.571" - escalade "^3.1.0" - node-releases "^1.1.61" + caniuse-lite "^1.0.30001219" + colorette "^1.2.2" + electron-to-chromium "^1.3.723" + escalade "^3.1.1" + node-releases "^1.1.71" bser@2.1.1: version "2.1.1" @@ -1895,6 +1914,14 @@ cache-base@^1.0.1: union-value "^1.0.0" unset-value "^1.0.0" +call-bind@^1.0.0, call-bind@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/call-bind/-/call-bind-1.0.2.tgz#b1d4e89e688119c3c9a903ad30abb2f6a919be3c" + integrity sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA== + dependencies: + function-bind "^1.1.1" + get-intrinsic "^1.0.2" + callsites@^3.0.0: version "3.1.0" resolved "https://registry.yarnpkg.com/callsites/-/callsites-3.1.0.tgz#b3630abd8943432f54b3f0519238e33cd7df2f73" @@ -1920,11 +1947,16 @@ caniuse-db@^1.0.30000977: resolved "https://registry.yarnpkg.com/caniuse-db/-/caniuse-db-1.0.30001151.tgz#f9816358ecbd430dcf2eb21293e6fa6b99fbae29" integrity sha512-uIflPNeE7YWzYZ13tqk5Em6YiR6bIqZC8JFkQwZGCadOiZJhPrff1AD9XiPDlE2RS7Ffoo39w9MBd5zjA9J2lw== -caniuse-lite@^1.0.0, caniuse-lite@^1.0.30001135: +caniuse-lite@^1.0.0: version "1.0.30001151" resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001151.tgz#1ddfde5e6fff02aad7940b4edb7d3ac76b0cb00b" integrity sha512-Zh3sHqskX6mHNrqUerh+fkf0N72cMxrmflzje/JyVImfpknscMnkeJrlFGJcqTmaa0iszdYptGpWMJCRQDkBVw== +caniuse-lite@^1.0.30001219: + version "1.0.30001439" + resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001439.tgz#ab7371faeb4adff4b74dad1718a6fd122e45d9cb" + integrity sha512-1MgUzEkoMO6gKfXflStpYgZDlFM7M/ck/bgfVCACO5vnAf0fXoNVHdWtqGU+MYca+4bL9Z5bpOVmR33cWW9G2A== + capture-exit@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/capture-exit/-/capture-exit-2.0.0.tgz#fb953bfaebeb781f62898239dabb426d08a509a4" @@ -2082,9 +2114,9 @@ color-name@^1.0.0, color-name@^1.1.4, color-name@~1.1.4: integrity sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA== color-string@^1.5.4: - version "1.5.4" - resolved "https://registry.yarnpkg.com/color-string/-/color-string-1.5.4.tgz#dd51cd25cfee953d138fe4002372cc3d0e504cb6" - integrity sha512-57yF5yt8Xa3czSEW1jfQDE79Idk0+AkN/4KWad6tbdxUmAs3MvjxlWSWD4deYytcRfoZ9nhKyFl1kj5tBvidbw== + version "1.5.5" + resolved "https://registry.yarnpkg.com/color-string/-/color-string-1.5.5.tgz#65474a8f0e7439625f3d27a6a19d89fc45223014" + integrity sha512-jgIoum0OfQfq9Whcfc2z/VhCNcmQjWbey6qBX0vqt7YICflUmBCh9E9CiQD5GSJ+Uehixm3NUwHVhqUAWRivZg== dependencies: color-name "^1.0.0" simple-swizzle "^0.2.2" @@ -2097,6 +2129,11 @@ color@^3.0.0: color-convert "^1.9.1" color-string "^1.5.4" +colorette@^1.2.2: + version "1.2.2" + resolved "https://registry.yarnpkg.com/colorette/-/colorette-1.2.2.tgz#cbcc79d5e99caea2dbf10eb3a26fd8b3e6acfa94" + integrity sha512-MKGMzyfeuutC/ZJ1cba9NqcNpfeqMUcYmyF1ZFY6/Cn7CNSAKx6a+s48sqLqyAiZuaP2TcqMhoo+dlwFnVxT9w== + combined-stream@^1.0.6, combined-stream@~1.0.6: version "1.0.8" resolved "https://registry.yarnpkg.com/combined-stream/-/combined-stream-1.0.8.tgz#c3d45a8b34fd730631a110a8a2520682b31d5a7f" @@ -2339,13 +2376,6 @@ data-urls@^1.1.0: whatwg-mimetype "^2.2.0" whatwg-url "^7.0.0" -debug@=3.1.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/debug/-/debug-3.1.0.tgz#5bb5a0672628b64149566ba16819e61518c67261" - integrity sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g== - dependencies: - ms "2.0.0" - debug@^2.2.0, debug@^2.3.3, debug@^2.6.9: version "2.6.9" resolved "https://registry.yarnpkg.com/debug/-/debug-2.6.9.tgz#5d128515df134ff327e90a4c93f4e077a536341f" @@ -2373,9 +2403,9 @@ decamelize@^1.2.0: integrity sha1-9lNNFRSCabIDUue+4m9QH5oZEpA= decode-uri-component@^0.2.0: - version "0.2.0" - resolved "https://registry.yarnpkg.com/decode-uri-component/-/decode-uri-component-0.2.0.tgz#eb3913333458775cb84cd1a1fae062106bb87545" - integrity sha1-6zkTMzRYd1y4TNGh+uBiEGu4dUU= + version "0.2.2" + resolved "https://registry.yarnpkg.com/decode-uri-component/-/decode-uri-component-0.2.2.tgz#e69dbe25d37941171dd540e024c444cd5188e1e9" + integrity sha512-FqUYQ+8o158GyGTrMFJms9qh3CqTKvAqgqsTnkLI8sKu0028orqBhxNMFkFen0zGyg6epACD32pjVk58ngIErQ== dedent@^0.7.0: version "0.7.0" @@ -2399,6 +2429,14 @@ define-properties@^1.1.3: dependencies: object-keys "^1.0.12" +define-properties@^1.1.4: + version "1.2.0" + resolved "https://registry.yarnpkg.com/define-properties/-/define-properties-1.2.0.tgz#52988570670c9eacedd8064f4a990f2405849bd5" + integrity sha512-xvqAVKGfT1+UAvPwKTVw/njhdQ8ZhXK4lI0bCIuCMrp2up9nPnaDftrLtmpTazqd1o+UY4zgzU+avtMbDP+ldA== + dependencies: + has-property-descriptors "^1.0.0" + object-keys "^1.1.1" + define-property@^0.2.5: version "0.2.5" resolved "https://registry.yarnpkg.com/define-property/-/define-property-0.2.5.tgz#c35b1ef918ec3c990f9a5bc57be04aacec5c8116" @@ -2504,10 +2542,10 @@ ecc-jsbn@~0.1.1: jsbn "~0.1.0" safer-buffer "^2.1.0" -electron-to-chromium@^1.3.571: - version "1.3.583" - resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.3.583.tgz#47a9fde74740b1205dba96db2e433132964ba3ee" - integrity sha512-L9BwLwJohjZW9mQESI79HRzhicPk1DFgM+8hOCfGgGCFEcA3Otpv7QK6SGtYoZvfQfE3wKLh0Hd5ptqUFv3gvQ== +electron-to-chromium@^1.3.723: + version "1.3.754" + resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.3.754.tgz#afbe69177ad7aae968c3bbeba129dc70dcc37cf4" + integrity sha512-Q50dJbfYYRtwK3G9mFP/EsJVzlgcYwKxFjbXmvVa1lDAbdviPcT9QOpFoufDApub4j0hBfDRL6v3lWNLEdEDXQ== emoji-regex@^7.0.1: version "7.0.3" @@ -2562,7 +2600,7 @@ es-abstract@^1.17.0, es-abstract@^1.17.0-next.1, es-abstract@^1.17.2: string.prototype.trimend "^1.0.1" string.prototype.trimstart "^1.0.1" -es-abstract@^1.18.0-next.0, es-abstract@^1.18.0-next.1: +es-abstract@^1.18.0-next.0: version "1.18.0-next.1" resolved "https://registry.yarnpkg.com/es-abstract/-/es-abstract-1.18.0-next.1.tgz#6e3a0a4bda717e5023ab3b8e90bec36108d22c68" integrity sha512-I4UGspA0wpZXWENrdA0uHbnhte683t3qT/1VFH9aX2dA5PPSf6QW5HHXf5HImaqPmjXaVeVk4RGWnaylmV7uAA== @@ -2580,6 +2618,55 @@ es-abstract@^1.18.0-next.0, es-abstract@^1.18.0-next.1: string.prototype.trimend "^1.0.1" string.prototype.trimstart "^1.0.1" +es-abstract@^1.19.0, es-abstract@^1.20.4: + version "1.21.2" + resolved "https://registry.yarnpkg.com/es-abstract/-/es-abstract-1.21.2.tgz#a56b9695322c8a185dc25975aa3b8ec31d0e7eff" + integrity sha512-y/B5POM2iBnIxCiernH1G7rC9qQoM77lLIMQLuob0zhp8C56Po81+2Nj0WFKnd0pNReDTnkYryc+zhOzpEIROg== + dependencies: + array-buffer-byte-length "^1.0.0" + available-typed-arrays "^1.0.5" + call-bind "^1.0.2" + es-set-tostringtag "^2.0.1" + es-to-primitive "^1.2.1" + function.prototype.name "^1.1.5" + get-intrinsic "^1.2.0" + get-symbol-description "^1.0.0" + globalthis "^1.0.3" + gopd "^1.0.1" + has "^1.0.3" + has-property-descriptors "^1.0.0" + has-proto "^1.0.1" + has-symbols "^1.0.3" + 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.10" + is-weakref "^1.0.2" + object-inspect "^1.12.3" + object-keys "^1.1.1" + object.assign "^4.1.4" + regexp.prototype.flags "^1.4.3" + safe-regex-test "^1.0.0" + string.prototype.trim "^1.2.7" + string.prototype.trimend "^1.0.6" + string.prototype.trimstart "^1.0.6" + typed-array-length "^1.0.4" + unbox-primitive "^1.0.2" + which-typed-array "^1.1.9" + +es-set-tostringtag@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/es-set-tostringtag/-/es-set-tostringtag-2.0.1.tgz#338d502f6f674301d710b80c8592de8a15f09cd8" + integrity sha512-g3OMbtlwY3QewlqAiMLI47KywjWZoEytKr8pf6iTC8uJq5bIAH52Z9pnQ8pVL6whrCto53JZDuUIsifGeLorTg== + dependencies: + get-intrinsic "^1.1.3" + has "^1.0.3" + has-tostringtag "^1.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" @@ -2589,7 +2676,7 @@ es-to-primitive@^1.2.1: is-date-object "^1.0.1" is-symbol "^1.0.2" -escalade@^3.1.0, escalade@^3.1.1: +escalade@^3.1.1: version "3.1.1" resolved "https://registry.yarnpkg.com/escalade/-/escalade-3.1.1.tgz#d8cfdc7000965c5a0174b4a82eaa5c0552742e40" integrity sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw== @@ -2599,6 +2686,11 @@ escape-string-regexp@^1.0.5: resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz#1b61c0562190a8dff6ae3bb2cf0200ca130b86d4" integrity sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ= +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== + escodegen@^1.11.1: version "1.14.3" resolved "https://registry.yarnpkg.com/escodegen/-/escodegen-1.14.3.tgz#4e7b81fba61581dc97582ed78cab7f0e8d63f503" @@ -3024,18 +3116,23 @@ flatted@^2.0.0: resolved "https://registry.yarnpkg.com/flatted/-/flatted-2.0.2.tgz#4575b21e2bcee7434aa9be662f4b7b5f9c2b5138" integrity sha512-r5wGx7YeOwNWNlCA0wQ86zKyDLMQr+/RB8xy74M4hTphfmjlijTSSXGuH8rnvKZnfT9i+75zmd8jcKdMR4O6jA== -follow-redirects@1.5.10: - version "1.5.10" - resolved "https://registry.yarnpkg.com/follow-redirects/-/follow-redirects-1.5.10.tgz#7b7a9f9aea2fdff36786a94ff643ed07f4ff5e2a" - integrity sha512-0V5l4Cizzvqt5D44aTXbFZz+FtyXV1vrDN6qrelxtfYQKW0KO0W2T/hkE8xvGa/540LkZlkaUjO4ailYTFtHVQ== - dependencies: - debug "=3.1.0" - follow-redirects@^1.10.0: version "1.13.0" resolved "https://registry.yarnpkg.com/follow-redirects/-/follow-redirects-1.13.0.tgz#b42e8d93a2a7eea5ed88633676d6597bc8e384db" integrity sha512-aq6gF1BEKje4a9i9+5jimNFIpq4Q1WiwBToeRK5NvZBd/TRsmW8BsJfOEGkr76TbOyPVD3OVDN910EcUNtRYEA== +follow-redirects@^1.14.0: + version "1.15.2" + resolved "https://registry.yarnpkg.com/follow-redirects/-/follow-redirects-1.15.2.tgz#b460864144ba63f2681096f274c4e57026da2c13" + integrity sha512-VQLG33o04KaQ8uYi2tVNbdrWp1QWxNNea+nmIB4EVM28v0hmP17z7aG1+wAkNzVq4KeXTq3221ye5qTJP91JwA== + +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" + for-in@^1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/for-in/-/for-in-1.0.2.tgz#81068d295a8142ec0ac726c6e2200c30fb6d5e80" @@ -3077,11 +3174,26 @@ function-bind@^1.1.1: resolved "https://registry.yarnpkg.com/function-bind/-/function-bind-1.1.1.tgz#a56899d3ea3c9bab874bb9773b7c5ede92f4895d" integrity sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A== +function.prototype.name@^1.1.5: + version "1.1.5" + resolved "https://registry.yarnpkg.com/function.prototype.name/-/function.prototype.name-1.1.5.tgz#cce0505fe1ffb80503e6f9e46cc64e46a12a9621" + integrity sha512-uN7m/BzVKQnCUF/iW8jYea67v++2u7m5UgENbHRtdDVclOUP+FMPlCNdmk0h/ysGyo2tavMJEDqJAkJdRa1vMA== + dependencies: + call-bind "^1.0.2" + define-properties "^1.1.3" + es-abstract "^1.19.0" + functions-have-names "^1.2.2" + functional-red-black-tree@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/functional-red-black-tree/-/functional-red-black-tree-1.0.1.tgz#1b0ab3bd553b2a0d6399d29c0e3ea0b252078327" integrity sha1-GwqzvVU7Kg1jmdKcDj6gslIHgyc= +functions-have-names@^1.2.2: + 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.1: version "1.0.0-beta.1" resolved "https://registry.yarnpkg.com/gensync/-/gensync-1.0.0-beta.1.tgz#58f4361ff987e5ff6e1e7a210827aa371eaac269" @@ -3092,6 +3204,15 @@ get-caller-file@^2.0.1, get-caller-file@^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: + version "1.2.0" + resolved "https://registry.yarnpkg.com/get-intrinsic/-/get-intrinsic-1.2.0.tgz#7ad1dc0535f3a2904bba075772763e5051f6d05f" + integrity sha512-L049y6nFOuom5wGyRc3/gdTLO94dySVKRACj1RmJZBQXlbTMhtNIgkWkUHq+jYmZvKf14EW1EoJnnjbmoHij0Q== + dependencies: + function-bind "^1.1.1" + has "^1.0.3" + has-symbols "^1.0.3" + get-own-enumerable-property-symbols@^3.0.0: version "3.0.2" resolved "https://registry.yarnpkg.com/get-own-enumerable-property-symbols/-/get-own-enumerable-property-symbols-3.0.2.tgz#b5fde77f22cbe35f390b4e089922c50bce6ef664" @@ -3121,6 +3242,14 @@ get-stream@^5.0.0: dependencies: pump "^3.0.0" +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" + get-value@^2.0.3, get-value@^2.0.6: version "2.0.6" resolved "https://registry.yarnpkg.com/get-value/-/get-value-2.0.6.tgz#dc15ca1c672387ca76bd37ac0a395ba2042a2c28" @@ -3134,9 +3263,9 @@ getpass@^0.1.1: assert-plus "^1.0.0" glob-parent@^5.0.0, glob-parent@^5.1.0: - version "5.1.1" - resolved "https://registry.yarnpkg.com/glob-parent/-/glob-parent-5.1.1.tgz#b6c1ef417c4e5663ea498f1c45afac6916bbc229" - integrity sha512-FnI+VGOpnlGHWZxthPGR+QhR78fuiK0sNLkHQv+bL9fQi57lNNdquIbna/WrfROrolq8GK5Ek6BiMwqL/voRYQ== + 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" @@ -3164,6 +3293,20 @@ globals@^12.1.0: dependencies: type-fest "^0.8.1" +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" + +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.1.2, graceful-fs@^4.2.4: version "4.2.4" resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.4.tgz#2256bde14d3632958c465ebc96dc467ca07a29fb" @@ -3187,6 +3330,11 @@ har-validator@~5.1.3: ajv "^6.12.3" har-schema "^2.0.0" +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" @@ -3197,11 +3345,35 @@ has-flag@^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.0" + resolved "https://registry.yarnpkg.com/has-property-descriptors/-/has-property-descriptors-1.0.0.tgz#610708600606d36961ed04c196193b6a607fa861" + integrity sha512-62DVLZGoiEBDHQyqG4w9xCuZ7eJEwNmJRWw2VY84Oedb7WFcA27fiEVe8oUQx9hAUJ4ekurquucTGwsyO1XGdQ== + dependencies: + get-intrinsic "^1.1.1" + +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.1: version "1.0.1" resolved "https://registry.yarnpkg.com/has-symbols/-/has-symbols-1.0.1.tgz#9f5214758a44196c406d9bd76cebf81ec2dd31e8" integrity sha512-PLcsoqu++dmEIZB+6totNFKq/7Do+Z0u4oT0zKOJNl3lYK6vGwwu2hjHs+68OEZbTjiUE9bgOABXbP/GvrS0Kg== +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" + has-value@^0.3.1: version "0.3.1" resolved "https://registry.yarnpkg.com/has-value/-/has-value-0.3.1.tgz#7b1f58bada62ca827ec0a2078025654845995e1f" @@ -3251,9 +3423,9 @@ hex-color-regex@^1.1.0: integrity sha512-l9sfDFsuqtOqKDsQdqrMRk0U85RZc0RtOR9yPI7mRVOa4FsR/BVnZ0shmQRM96Ji99kYZP/7hn1cedc1+ApsTQ== hosted-git-info@^2.1.4: - version "2.8.8" - resolved "https://registry.yarnpkg.com/hosted-git-info/-/hosted-git-info-2.8.8.tgz#7539bd4bc1e0e0a895815a2e0262420b12858488" - integrity sha512-f/wzC2QaWBs7t9IYqB4T3sR1xviIViXJRJTWBlx2Gf3g0Xi5vI7Yy4koXQ1c9OYDGHN9sBy1DQ2AB8fqZBWhUg== + version "2.8.9" + resolved "https://registry.yarnpkg.com/hosted-git-info/-/hosted-git-info-2.8.9.tgz#dffc0bf9a21c02209090f2aa69429e1414daf3f9" + integrity sha512-mxIDAb9Lsm6DoOJ7xH+5+X4y1LU/4Hi50L9C5sIswK3JzULS4bwk1FvjdBgvYR4bzT4tuUQiC15FE2f5HbLvYw== hsl-regex@^1.0.0: version "1.0.0" @@ -3368,6 +3540,15 @@ inherits@2: 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.5" + resolved "https://registry.yarnpkg.com/internal-slot/-/internal-slot-1.0.5.tgz#f2a2ee21f668f8627a4667f309dc0f4fb6674986" + integrity sha512-Y+R5hJrzs52QCG2laLn4udYVnxsfny9CpOhNhUvk/SSSVyF6T27FzRbF0sroPidSu3X8oEAkOn2K804mjpt6UQ== + dependencies: + get-intrinsic "^1.2.0" + has "^1.0.3" + side-channel "^1.0.4" + ip-regex@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/ip-regex/-/ip-regex-2.1.0.tgz#fa78bf5d2e6913c911ce9f819ee5146bb6d844e9" @@ -3392,6 +3573,15 @@ is-accessor-descriptor@^1.0.0: dependencies: kind-of "^6.0.0" +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" @@ -3402,11 +3592,31 @@ is-arrayish@^0.3.1: resolved "https://registry.yarnpkg.com/is-arrayish/-/is-arrayish-0.3.2.tgz#4574a2ae56f7ab206896fb431eaeed066fdf8f03" integrity sha512-eVRqCvVlZbuw3GrM63ovNSNAeA1K16kaR/LRY/92w0zxQ5/1YzwblUX652i4Xs9RwAGjW9d9y6X88t8OaAJfWQ== +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-buffer@^1.1.5: version "1.1.6" resolved "https://registry.yarnpkg.com/is-buffer/-/is-buffer-1.1.6.tgz#efaa2ea9daa0d7ab2ea13a97b2b8ad51fefbe8be" integrity sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w== +is-callable@^1.1.3, 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-callable@^1.1.4, is-callable@^1.2.2: version "1.2.2" resolved "https://registry.yarnpkg.com/is-callable/-/is-callable-1.2.2.tgz#c7c6715cd22d4ddb48d3e19970223aceabb080d9" @@ -3431,10 +3641,10 @@ is-color-stop@^1.0.0: rgb-regex "^1.0.1" rgba-regex "^1.0.0" -is-core-module@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/is-core-module/-/is-core-module-2.0.0.tgz#58531b70aed1db7c0e8d4eb1a0a2d1ddd64bd12d" - integrity sha512-jq1AH6C8MuteOoBPwkxHafmByhL9j5q4OaPGdbuD+ZtQJVzH+i6E3BJDQcBA09k57i2Hh2yQbEG8yObZ0jdlWw== +is-core-module@^2.9.0: + version "2.11.0" + resolved "https://registry.yarnpkg.com/is-core-module/-/is-core-module-2.11.0.tgz#ad4cb3e3863e814523c96f3f58d26cc570ff0144" + integrity sha512-RRjxlvLDkD1YJwDbroBHMb+cukurkDWNyHx7D3oNB5x9rb5ogcksMC5wHCadcXoo67gVr/+3GFySh3134zi6rw== dependencies: has "^1.0.3" @@ -3524,6 +3734,18 @@ is-negative-zero@^2.0.0: resolved "https://registry.yarnpkg.com/is-negative-zero/-/is-negative-zero-2.0.0.tgz#9553b121b0fac28869da9ed459e20c7543788461" integrity sha1-lVOxIbD6wohp2p7UWeIMdUN4hGE= +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@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/is-number/-/is-number-3.0.0.tgz#24fd6201a4782cf50561c810276afc7d12d71195" @@ -3560,11 +3782,26 @@ is-regex@^1.1.1: dependencies: has-symbols "^1.0.1" +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-regexp@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/is-regexp/-/is-regexp-1.0.0.tgz#fd2d883545c46bac5a633e7b9a09e87fa2cb5069" integrity sha1-/S2INUXEa6xaYz57mgnof6LLUGk= +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@^1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/is-stream/-/is-stream-1.1.0.tgz#12d4a3dd4e68e0b79ceb8dbc84173ae80d91ca44" @@ -3580,6 +3817,13 @@ is-string@^1.0.5: resolved "https://registry.yarnpkg.com/is-string/-/is-string-1.0.5.tgz#40493ed198ef3ff477b8c7f92f644ec82a5cd3a6" integrity sha512-buY6VNRjhQMiF1qWDouloZlQbRhDPCebwxSjxMjxgemYT46YMd2NR0/H+fBhEfWX4A/w9TBJ+ol+okqJKFE6vQ== +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-svg@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/is-svg/-/is-svg-3.0.0.tgz#9321dbd29c212e5ca99c4fa9794c714bcafa2f75" @@ -3594,11 +3838,36 @@ is-symbol@^1.0.2: dependencies: has-symbols "^1.0.1" +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.9: + version "1.1.10" + resolved "https://registry.yarnpkg.com/is-typed-array/-/is-typed-array-1.1.10.tgz#36a5b5cb4189b575d1a3e4b08536bfb485801e3f" + integrity sha512-PJqgEHiWZvMpaFZ3uTc8kHPM4+4ADTlDniuQL7cU/UDA0Ql7F70yGfHph3cLNe+c9toaigv+DFzTJKhc2CtO6A== + dependencies: + available-typed-arrays "^1.0.5" + call-bind "^1.0.2" + for-each "^0.3.3" + gopd "^1.0.1" + has-tostringtag "^1.0.0" + is-typedarray@^1.0.0, is-typedarray@~1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/is-typedarray/-/is-typedarray-1.0.0.tgz#e479c80858df0c1b11ddda6940f96011fcda4a9a" integrity sha1-5HnICFjfDBsR3dppQPlgEfzaSpo= +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" + is-windows@^1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/is-windows/-/is-windows-1.0.2.tgz#d1850eb9791ecd18e6182ce12a30f396634bb19d" @@ -4083,15 +4352,15 @@ jest@25.5.4: import-local "^3.0.2" jest-cli "^25.5.4" -joi@^17.1.1: - version "17.3.0" - resolved "https://registry.yarnpkg.com/joi/-/joi-17.3.0.tgz#f1be4a6ce29bc1716665819ac361dfa139fff5d2" - integrity sha512-Qh5gdU6niuYbUIUV5ejbsMiiFmBdw8Kcp8Buj2JntszCkCfxJ9Cz76OtHxOZMPXrt5810iDIXs+n1nNVoquHgg== +joi@^17.3.0: + version "17.8.4" + resolved "https://registry.yarnpkg.com/joi/-/joi-17.8.4.tgz#f2d91ab8acd3cca4079ba70669c65891739234aa" + integrity sha512-jjdRHb5WtL+KgSHvOULQEPPv4kcl+ixd1ybOFQq3rWLgEEqc03QMmilodL0GVJE14U/SQDXkUhQUSZANGDH/AA== dependencies: "@hapi/hoek" "^9.0.0" "@hapi/topo" "^5.0.0" - "@sideway/address" "^4.1.0" - "@sideway/formula" "^3.0.0" + "@sideway/address" "^4.1.3" + "@sideway/formula" "^3.0.1" "@sideway/pinpoint" "^2.0.0" js-tokens@^4.0.0: @@ -4339,10 +4608,10 @@ lodash.uniq@^4.5.0: resolved "https://registry.yarnpkg.com/lodash.uniq/-/lodash.uniq-4.5.0.tgz#d0225373aeb652adc1bc82e4945339a842754773" integrity sha1-0CJTc662Uq3BvILklFM5qEJ1R3M= -lodash@^4.17.10, lodash@^4.17.13, lodash@^4.17.14, lodash@^4.17.15, lodash@^4.17.19: - version "4.17.20" - resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.20.tgz#b44a9b6297bcb698f1c51a3545a2b3b368d59c52" - integrity sha512-PlhdFcillOINfeV7Ni6oF1TAEayyZBoZ8bcshTHqOYJYlrqzRK5hagpagky5o4HfCzzd1TRkXPMFq6cKk9rGmA== +lodash@^4.17.10, lodash@^4.17.13, lodash@^4.17.14, lodash@^4.17.15, lodash@^4.17.19, lodash@^4.17.21: + version "4.17.21" + resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.21.tgz#679591c564c3bffaae8454cf0b3df370c3d6911c" + integrity sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg== log-symbols@^4.0.0: version "4.0.0" @@ -4368,6 +4637,13 @@ lolex@^5.0.0: dependencies: "@sinonjs/commons" "^1.7.0" +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" + magic-string@^0.25.5: version "0.25.7" resolved "https://registry.yarnpkg.com/magic-string/-/magic-string-0.25.7.tgz#3f497d6fd34c669c6798dcb821f2ef31f5445051" @@ -4382,12 +4658,12 @@ make-dir@^3.0.0: dependencies: semver "^6.0.0" -makeerror@1.0.x: - version "1.0.11" - resolved "https://registry.yarnpkg.com/makeerror/-/makeerror-1.0.11.tgz#e01a5c9109f2af79660e4e8b9587790184f5a96c" - integrity sha1-4BpckQnyr3lmDk6LlYd5AYT1qWw= +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.x" + tmpl "1.0.5" map-cache@^0.2.2: version "0.2.2" @@ -4480,9 +4756,9 @@ minimatch@^3.0.4: brace-expansion "^1.1.7" minimist@^1.1.1, minimist@^1.2.0, minimist@^1.2.5: - version "1.2.5" - resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.5.tgz#67d66014b66a6a8aaa0c083c5fd58df4e4e97602" - integrity sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw== + version "1.2.6" + resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.6.tgz#8637a5b759ea0d6e98702cfb3a9283323c93af44" + integrity sha512-Jsjnk4bw3YJqYzbdyBiNsPWHPfO++UGG749Cxs6peCu5Xg4nrena6OVxOYxrQTqww0Jmwt+Ref8rggumkTLz9Q== mixin-deep@^1.2.0: version "1.3.2" @@ -4564,10 +4840,10 @@ node-notifier@^6.0.0: shellwords "^0.1.1" which "^1.3.1" -node-releases@^1.1.61: - version "1.1.64" - resolved "https://registry.yarnpkg.com/node-releases/-/node-releases-1.1.64.tgz#71b4ae988e9b1dd7c1ffce58dd9e561752dfebc5" - integrity sha512-Iec8O9166/x2HRMJyLLLWkd0sFFLrFNy+Xf+JQfSQsdBJzPcHpNl3JQ9gD4j+aJxmCa25jNsIbM4bmACtSbkSg== +node-releases@^1.1.71: + version "1.1.73" + resolved "https://registry.yarnpkg.com/node-releases/-/node-releases-1.1.73.tgz#dd4e81ddd5277ff846b80b52bb40c49edf7a7b20" + integrity sha512-uW7fodD6pyW2FZNZnp/Z3hvWKeEW1Y8R1+1CnErE8cXFXzl5blBOoVB41CvMer6P6Q0S5FXDwcHgFd1Wj0U9zg== normalize-package-data@^2.3.2, normalize-package-data@^2.5.0: version "2.5.0" @@ -4636,6 +4912,11 @@ object-copy@^0.1.0: define-property "^0.2.5" kind-of "^3.0.3" +object-inspect@^1.12.3, object-inspect@^1.9.0: + version "1.12.3" + resolved "https://registry.yarnpkg.com/object-inspect/-/object-inspect-1.12.3.tgz#ba62dffd67ee256c8c086dfae69e016cd1f198b9" + integrity sha512-geUvdk7c+eizMNUDkRpW1wJwgfOiOeHbxBR/hLXK1aT6zmVSO0jsQcs7fj6MGw89jC/cjGfLcNOrtMYtGqm81g== + object-inspect@^1.8.0: version "1.8.0" resolved "https://registry.yarnpkg.com/object-inspect/-/object-inspect-1.8.0.tgz#df807e5ecf53a609cc6bfe93eac3cc7be5b3a9d0" @@ -4663,6 +4944,16 @@ object.assign@^4.1.0, object.assign@^4.1.1: has-symbols "^1.0.1" object-keys "^1.1.1" +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.getownpropertydescriptors@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/object.getownpropertydescriptors/-/object.getownpropertydescriptors-2.1.0.tgz#369bf1f9592d8ab89d712dced5cb81c7c5352649" @@ -4857,10 +5148,10 @@ path-key@^3.0.0, path-key@^3.1.0: resolved "https://registry.yarnpkg.com/path-key/-/path-key-3.1.1.tgz#581f6ade658cbba65a0d3380de7753295054f375" integrity sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q== -path-parse@^1.0.6: - version "1.0.6" - resolved "https://registry.yarnpkg.com/path-parse/-/path-parse-1.0.6.tgz#d62dbb5679405d72c4737ec58600e9ddcf06d24c" - integrity sha512-GSmOT2EbHrINBf9SR7CDELwlJ8AENk3Qn7OikK4nFYAu3Ote2+JYNVvkpAEQm3/TLNEJFD/xZJjzyxg3KBWOzw== +path-parse@^1.0.6, 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@^2.0.0: version "2.0.0" @@ -5204,9 +5495,9 @@ postcss-value-parser@^4.0.2, postcss-value-parser@~4.1.0: integrity sha512-97DXOFbQJhk71ne5/Mt6cOu6yxsSfM0QGQyl0L25Gca4yGWEGJaig7l7gbCX623VqTBNGLRLaVUCnNkcedlRSQ== postcss@^7.0.0, postcss@^7.0.1, postcss@^7.0.27, postcss@~7.0.32: - version "7.0.35" - resolved "https://registry.yarnpkg.com/postcss/-/postcss-7.0.35.tgz#d2be00b998f7f211d8a276974079f2e92b970e24" - integrity sha512-3QT8bBJeX/S5zKTTjTCIjRF3If4avAT6kqxcASlTWEtAFCb9NH0OUxNDfgZSWdP5fJnBYCMEWkIFfWeugjzYMg== + version "7.0.36" + resolved "https://registry.yarnpkg.com/postcss/-/postcss-7.0.36.tgz#056f8cffa939662a8f5905950c07d5285644dfcb" + integrity sha512-BebJSIUMwJHRH0HAQoxN4u1CN86glsrwsW0q7T+/m44eXOUAxSNdHRkNZPYz5vVUbg17hFgOQDE7fZk7li3pZw== dependencies: chalk "^2.4.2" source-map "^0.6.1" @@ -5309,9 +5600,14 @@ q@^1.1.2: integrity sha1-fjL3W0E4EpHQRhHxvxQQmsAGUdc= qs@~6.5.2: - version "6.5.2" - resolved "https://registry.yarnpkg.com/qs/-/qs-6.5.2.tgz#cb3ae806e8740444584ef154ce8ee98d403f3e36" - integrity sha512-N5ZAX4/LxJmF+7wN74pUD6qAh9/wnvdQcjq9TZjevvXzSUo7bfmw91saqMjzGS2xq91/odN2dW/WOl7qQHNDGA== + version "6.5.3" + resolved "https://registry.yarnpkg.com/qs/-/qs-6.5.3.tgz#3aeeffc91967ef6e35c0e488ef46fb296ab76aad" + integrity sha512-qxXIEh4pCGfHICj1mAJQ2/2XVZkjCDTcEgfoSQxc/fYivUZxTkk7L3bDBJSoNrEzXI17oUO5Dp07ktqE5KzczA== + +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@^16.12.0: version "16.13.1" @@ -5319,14 +5615,14 @@ react-is@^16.12.0: integrity sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ== react-is@^17.0.1: - version "17.0.1" - resolved "https://registry.yarnpkg.com/react-is/-/react-is-17.0.1.tgz#5b3531bd76a645a4c9fb6e693ed36419e3301339" - integrity sha512-NAnt2iGDXohE5LI7uBnLnqvLQMtzhkiAOLXTmv+qnF9Ky7xAPcX8Up/xWIhxvLVGJvuLiNc4xQLtuqDRzb4fSA== + 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== read-pkg-up@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/read-pkg-up/-/read-pkg-up-2.0.0.tgz#6b72a8048984e0c41e79510fd5e9fa99b3b549be" - integrity sha1-a3KoBImE4MQeeVEP1en6mbO1Sb4= + integrity sha512-1orxQfbWGUiTn9XsPlChs6rLie/AV9jwZTGmu2NZw/CUDJQchXJFYE0Fq5j7+n558T1JhDWLdhyd1Zj+wLY//w== dependencies: find-up "^2.0.0" read-pkg "^2.0.0" @@ -5343,7 +5639,7 @@ read-pkg-up@^7.0.1: read-pkg@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/read-pkg/-/read-pkg-2.0.0.tgz#8ef1c0623c6a6db0dc6713c4bfac46332b2368f8" - integrity sha1-jvHAYjxqbbDcZxPEv6xGMysjaPg= + integrity sha512-eFIBOPW7FGjzBuk3hdXEuNSiTZS/xEMlH49HxMyzb0hyPfu4EhVjT2DH32K1hSSmVq4sebAWnZuuY5auISUTGA== dependencies: load-json-file "^2.0.0" normalize-package-data "^2.3.2" @@ -5364,22 +5660,22 @@ realpath-native@^2.0.0: resolved "https://registry.yarnpkg.com/realpath-native/-/realpath-native-2.0.0.tgz#7377ac429b6e1fd599dc38d08ed942d0d7beb866" integrity sha512-v1SEYUOXXdbBZK8ZuNgO4TBjamPsiSgcFr0aP+tEKpQZK8vooEUqV6nm6Cv502mX4NF2EfsnVqtNAHG+/6Ur1Q== -regenerate-unicode-properties@^8.2.0: - version "8.2.0" - resolved "https://registry.yarnpkg.com/regenerate-unicode-properties/-/regenerate-unicode-properties-8.2.0.tgz#e5de7111d655e7ba60c057dbe9ff37c87e65cdec" - integrity sha512-F9DjY1vKLo/tPePDycuH3dn9H1OTPIkVD9Kz4LODu+F2C75mgjAJ7x/gwy6ZcSNRAAkhNlJSOHRe8k3p+K9WhA== +regenerate-unicode-properties@^9.0.0: + version "9.0.0" + resolved "https://registry.yarnpkg.com/regenerate-unicode-properties/-/regenerate-unicode-properties-9.0.0.tgz#54d09c7115e1f53dc2314a974b32c1c344efe326" + integrity sha512-3E12UeNSPfjrgwjkR81m5J7Aw/T55Tu7nUyZVQYCKEOs+2dkxEY+DpPtZzO4YruuiPb7NkYLVcyJC4+zCbk5pA== dependencies: - regenerate "^1.4.0" + regenerate "^1.4.2" -regenerate@^1.4.0: - version "1.4.1" - resolved "https://registry.yarnpkg.com/regenerate/-/regenerate-1.4.1.tgz#cad92ad8e6b591773485fbe05a485caf4f457e6f" - integrity sha512-j2+C8+NtXQgEKWk49MMP5P/u2GhnahTtVkRIHr5R5lVRlbKvmQ+oS+A5aLKWp2ma5VkT8sh6v+v4hbH0YHR66A== +regenerate@^1.4.2: + version "1.4.2" + resolved "https://registry.yarnpkg.com/regenerate/-/regenerate-1.4.2.tgz#b9346d8827e8f5a32f7ba29637d398b69014848a" + integrity sha512-zrceR/XhGYU/d/opr2EKO7aRHUeiBI8qjtfHqADTwZd6Szfy16la6kqD0MIUs5z5hx6AaKa+PixpPrR289+I0A== regenerator-runtime@^0.13.4: - version "0.13.7" - resolved "https://registry.yarnpkg.com/regenerator-runtime/-/regenerator-runtime-0.13.7.tgz#cac2dacc8a1ea675feaabaeb8ae833898ae46f55" - integrity sha512-a54FxoJDIr27pgf7IgeQGxmqUNYrcV338lf/6gH456HZ/PhX+5BcwHXG9ajESmwe6WRO0tAzRUrRmNONWgkrew== + version "0.13.11" + resolved "https://registry.yarnpkg.com/regenerator-runtime/-/regenerator-runtime-0.13.11.tgz#f6dca3e7ceec20590d07ada785636a90cdca17f9" + integrity sha512-kY1AZVr2Ra+t+piVaJ4gxaFaReZVH40AKNo7UCX6W+dEwBo/2oZJzqfuN1qLq1oL45o56cPaTXELwrTh8Fpggg== regenerator-transform@^0.13.3: version "0.13.4" @@ -5401,49 +5697,58 @@ regexp-to-ast@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.4.3: + version "1.4.3" + resolved "https://registry.yarnpkg.com/regexp.prototype.flags/-/regexp.prototype.flags-1.4.3.tgz#87cab30f80f66660181a3bb7bf5981a872b367ac" + integrity sha512-fjggEOO3slI6Wvgjwflkc4NFRCTZAu5CnNfBd5qOMYhWdn67nJBBu34/TkD++eeFmd8C9r9jfXJ27+nSiRkSUA== + dependencies: + call-bind "^1.0.2" + define-properties "^1.1.3" + functions-have-names "^1.2.2" + regexpp@^3.1.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/regexpp/-/regexpp-3.1.0.tgz#206d0ad0a5648cffbdb8ae46438f3dc51c9f78e2" - integrity sha512-ZOIzd8yVsQQA7j8GCSlPGXwg5PfmA1mrq0JP4nGhh54LaKN3xdai/vHUDu74pKwV8OxseMS65u2NImosQcSD0Q== + version "3.2.0" + resolved "https://registry.yarnpkg.com/regexpp/-/regexpp-3.2.0.tgz#0425a2768d8f23bad70ca4b90461fa2f1213e1b2" + integrity sha512-pq2bWo9mVD43nbts2wGv17XLiNLya+GklZ8kaDLV2Z08gDCsGpnKn9BFMepvWuHCbyVvY7J5o5+BVvoQbmlJLg== regexpu-core@^4.1.3: - version "4.7.1" - resolved "https://registry.yarnpkg.com/regexpu-core/-/regexpu-core-4.7.1.tgz#2dea5a9a07233298fbf0db91fa9abc4c6e0f8ad6" - integrity sha512-ywH2VUraA44DZQuRKzARmw6S66mr48pQVva4LBeRhcOltJ6hExvWly5ZjFLYo67xbIxb6W1q4bAGtgfEl20zfQ== - dependencies: - regenerate "^1.4.0" - regenerate-unicode-properties "^8.2.0" - regjsgen "^0.5.1" - regjsparser "^0.6.4" - unicode-match-property-ecmascript "^1.0.4" - unicode-match-property-value-ecmascript "^1.2.0" - -regjsgen@^0.5.1: + version "4.8.0" + resolved "https://registry.yarnpkg.com/regexpu-core/-/regexpu-core-4.8.0.tgz#e5605ba361b67b1718478501327502f4479a98f0" + integrity sha512-1F6bYsoYiz6is+oz70NWur2Vlh9KWtswuRuzJOfeYUrfPX2o8n74AnUVaOGDbUqVGO9fNHu48/pjJO4sNVwsOg== + dependencies: + regenerate "^1.4.2" + regenerate-unicode-properties "^9.0.0" + regjsgen "^0.5.2" + regjsparser "^0.7.0" + unicode-match-property-ecmascript "^2.0.0" + unicode-match-property-value-ecmascript "^2.0.0" + +regjsgen@^0.5.2: version "0.5.2" resolved "https://registry.yarnpkg.com/regjsgen/-/regjsgen-0.5.2.tgz#92ff295fb1deecbf6ecdab2543d207e91aa33733" integrity sha512-OFFT3MfrH90xIW8OOSyUrk6QHD5E9JOTeGodiJeBS3J6IwlgzJMNE/1bZklWz5oTg+9dCMyEetclvCVXOPoN3A== -regjsparser@^0.6.4: - version "0.6.4" - resolved "https://registry.yarnpkg.com/regjsparser/-/regjsparser-0.6.4.tgz#a769f8684308401a66e9b529d2436ff4d0666272" - integrity sha512-64O87/dPDgfk8/RQqC4gkZoGyyWFIEUTTh80CU6CWuK5vkCGyekIx+oKcEIYtP/RAxSQltCZHCNu/mdd7fqlJw== +regjsparser@^0.7.0: + version "0.7.0" + resolved "https://registry.yarnpkg.com/regjsparser/-/regjsparser-0.7.0.tgz#a6b667b54c885e18b52554cb4960ef71187e9968" + integrity sha512-A4pcaORqmNMDVwUjWoTzuhwMGpP+NykpfqAsEgI1FSH/EzC7lrN5TMd+kN8YCovX+jMpu8eaqXgXPCa0g8FQNQ== dependencies: jsesc "~0.5.0" remove-trailing-separator@^1.0.1: version "1.1.0" resolved "https://registry.yarnpkg.com/remove-trailing-separator/-/remove-trailing-separator-1.1.0.tgz#c24bce2a283adad5bc3f58e0d48249b92379d8ef" - integrity sha1-wkvOKig62tW8P1jg1IJJuSN52O8= + integrity sha512-/hS+Y0u3aOfIETiaiirUFwDBDzmXPvO+jAfKTitUngIPzdKc6Z0LoFjM/CK5PL4C+eKwHohlHAb6H0VFfmmUsw== repeat-element@^1.1.2: - version "1.1.3" - resolved "https://registry.yarnpkg.com/repeat-element/-/repeat-element-1.1.3.tgz#782e0d825c0c5a3bb39731f84efee6b742e6b1ce" - integrity sha512-ahGq0ZnV5m5XtZLMb+vP76kcAM5nkLqk0lpqAuojSKGgQtn4eRi4ZZGm2olo2zKFH+sMsWaqOCW1dqAnOru72g== + version "1.1.4" + resolved "https://registry.yarnpkg.com/repeat-element/-/repeat-element-1.1.4.tgz#be681520847ab58c7568ac75fbfad28ed42d39e9" + integrity sha512-LFiNfRcSu7KK3evMyYOuCzv3L10TW7yC1G2/+StMjK8Y6Vqd2MG7r/Qjw4ghtuCOjFvlnms/iMmLqpvW/ES/WQ== repeat-string@^1.6.1: version "1.6.1" resolved "https://registry.yarnpkg.com/repeat-string/-/repeat-string-1.6.1.tgz#8dcae470e1c88abc2d600fff4a776286da75e637" - integrity sha1-jcrkcOHIirwtYA//Sndihtp15jc= + integrity sha512-PV0dzCYDNfRi1jCDbJzpW7jNNDRuCOG/jI5ctQcGKt/clZD+YcPS3yIlWuTJMmESC8aevCFmWJy5wjAFgNqN6w== request-promise-core@1.1.4: version "1.1.4" @@ -5490,7 +5795,7 @@ request@^2.88.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 sha1-jGStX9MNqxyXbiNE/+f3kqam30I= + integrity sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q== require-main-filename@^2.0.0: version "2.0.0" @@ -5517,20 +5822,21 @@ resolve-from@^5.0.0: resolve-url@^0.2.1: version "0.2.1" resolved "https://registry.yarnpkg.com/resolve-url/-/resolve-url-0.2.1.tgz#2c637fe77c893afd2a663fe21aa9080068e2052a" - integrity sha1-LGN/53yJOv0qZj/iGqkIAGjiBSo= + integrity sha512-ZuF55hVUQaaczgOIwqWzkEcEidmlD/xl44x1UZnhOXcYuFN2S6+rcxpG+C1N3So0wvNI3DmJICUFfu2SxhBmvg== resolve@1.1.7: version "1.1.7" resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.1.7.tgz#203114d82ad2c5ed9e8e0411b3932875e889e97b" - integrity sha1-IDEU2CrSxe2ejgQRs5ModeiJ6Xs= + integrity sha512-9znBF0vBcaSN3W2j7wKvdERPwqTxSpCq+if5C0WoTCyV9n24rua28jeuQ2pL/HOf+yUe/Mef+H/5p60K0Id3bg== resolve@^1.10.0, resolve@^1.12.0, resolve@^1.13.1, resolve@^1.17.0, resolve@^1.3.2, resolve@^1.8.1: - version "1.18.1" - resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.18.1.tgz#018fcb2c5b207d2a6424aee361c5a266da8f4130" - integrity sha512-lDfCPaMKfOJXjy0dPayzPdF1phampNWr3qFCjAu+rw/qbQmr5jWH5xN2hwh9QKfw9E5v4hwV7A+jrCmL8yjjqA== + version "1.22.1" + resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.22.1.tgz#27cb2ebb53f91abb49470a928bba7558066ac177" + integrity sha512-nBpuuYuY5jFsli/JIs1oldw6fOQCBioohqWZg/2hiaOybXOft4lonv85uDOKXdf8rhyK159cxU5cDcK/NKk8zw== dependencies: - is-core-module "^2.0.0" - path-parse "^1.0.6" + is-core-module "^2.9.0" + path-parse "^1.0.7" + supports-preserve-symlinks-flag "^1.0.0" resolve@~1.17.0: version "1.17.0" @@ -5560,12 +5866,12 @@ reusify@^1.0.4: rgb-regex@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/rgb-regex/-/rgb-regex-1.0.1.tgz#c0e0d6882df0e23be254a475e8edd41915feaeb1" - integrity sha1-wODWiC3w4jviVKR16O3UGRX+rrE= + integrity sha512-gDK5mkALDFER2YLqH6imYvK6g02gpNGM4ILDZ472EwWfXZnC2ZEpoB2ECXTyOVUKuk/bPJZMzwQPBYICzP+D3w== rgba-regex@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/rgba-regex/-/rgba-regex-1.0.0.tgz#43374e2e2ca0968b0ef1523460b7d730ff22eeb3" - integrity sha1-QzdOLiyglosO8VI0YLfXMP8i7rM= + integrity sha512-zgn5OjNQXLUTdq8m17KdaicF6w89TZs8ZU8y0AYENIU6wG8GG6LLm0yLSiPY8DmaYmHdgRW8rnApjoT0fQRfMg== rimraf@2.6.3: version "2.6.3" @@ -5594,14 +5900,16 @@ rsvp@^4.8.4: integrity sha512-nfMOlASu9OnRJo1mbEk2cz0D56a1MBNrJ7orjRZQG10XDyuvwksKbuXNp6qa+kbn839HwjwhBzhFmdsaEAfauA== run-parallel@^1.1.9: - version "1.1.9" - resolved "https://registry.yarnpkg.com/run-parallel/-/run-parallel-1.1.9.tgz#c9dd3a7cf9f4b2c4b6244e173a6ed866e61dd679" - integrity sha512-DEqnSRTDw/Tc3FXf49zedI638Z9onwUotBMiUFKmrO2sdFKIbXamXGQ3Axd4qgphxKB4kw/qP1w5kTxnfU1B9Q== + 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@^6.5.5, rxjs@^6.6.2: - version "6.6.3" - resolved "https://registry.yarnpkg.com/rxjs/-/rxjs-6.6.3.tgz#8ca84635c4daa900c0d3967a6ee7ac60271ee552" - integrity sha512-trsQc+xYYXZ3urjOiJOuCOa5N3jAZ3eiSpQB5hIT8zGlL2QfnHLJ2r7GMkBGuIausdJN1OneaI6gQlsqNHHmZQ== +rxjs@^6.6.2, rxjs@^6.6.3: + version "6.6.7" + resolved "https://registry.yarnpkg.com/rxjs/-/rxjs-6.6.7.tgz#90ac018acabf491bf65044235d5863c4dab804c9" + integrity sha512-hTdwr+7yYNIT5n4AMYp85KA6yw2Va0FLa3Rguvbpa4W3I5xynaBZo41cM3XM+4Q6fRMj3sBYIR1VAmZMXYJvRQ== dependencies: tslib "^1.9.0" @@ -5615,10 +5923,19 @@ safe-buffer@~5.1.1: resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.1.2.tgz#991ec69d296e0313747d59bdfd2b745c35f8828d" integrity sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g== +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" + safe-regex@^1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/safe-regex/-/safe-regex-1.1.0.tgz#40a3669f3b077d1e943d44629e157dd48023bf2e" - integrity sha1-QKNmnzsHfR6UPURinhV91IAjvy4= + integrity sha512-aJXcif4xnaNUzvUuC5gcb46oTS7zvg4jpMTnuqtrEPlR3vFr4pxtdTwaF1Qs3Enjn9HK+ZlwQui+a7z0SywIzg== dependencies: ret "~0.1.10" @@ -5657,7 +5974,7 @@ saxes@^3.1.9: semver-compare@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/semver-compare/-/semver-compare-1.0.0.tgz#0dee216a1c941ab37e9efb1788f6afc5ff5537fc" - integrity sha1-De4hahyUGrN+nvsXiPavxf9VN/w= + integrity sha512-YM3/ITh2MJ5MtzaM429anh+x2jiLVjqILF4m4oyQB18W7Ggea7BfqdH/wGMK7dDiMghv/6WG7znWMwUDzJiXow== semver-regex@^2.0.0: version "2.0.0" @@ -5665,24 +5982,26 @@ semver-regex@^2.0.0: integrity sha512-mUdIBBvdn0PLOeP3TEkMH7HHeUP3GjsXCwKarjv/kGmUFOYg1VqEemKhoQpWMu6X2I8kHeuVdGibLGkVK+/5Qw== "semver@2 || 3 || 4 || 5", semver@^5.4.1, semver@^5.5.0, semver@^5.5.1: - version "5.7.1" - resolved "https://registry.yarnpkg.com/semver/-/semver-5.7.1.tgz#a954f931aeba508d307bbf069eff0c01c96116f7" - integrity sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ== + version "5.7.2" + resolved "https://registry.yarnpkg.com/semver/-/semver-5.7.2.tgz#48d55db737c3287cd4835e17fa13feace1c41ef8" + integrity sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g== semver@^6.0.0, semver@^6.1.2, semver@^6.3.0: - version "6.3.0" - resolved "https://registry.yarnpkg.com/semver/-/semver-6.3.0.tgz#ee0a64c8af5e8ceea67687b133761e1becbd1d3d" - integrity sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw== + version "6.3.1" + resolved "https://registry.yarnpkg.com/semver/-/semver-6.3.1.tgz#556d2ef8689146e46dcea4bfdd095f3434dffcb4" + integrity sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA== semver@^7.2.1, semver@^7.3.2: - version "7.3.2" - resolved "https://registry.yarnpkg.com/semver/-/semver-7.3.2.tgz#604962b052b81ed0786aae84389ffba70ffd3938" - integrity sha512-OrOb32TeeambH6UrhtShmF7CRDqhL6/5XpPNp2DuRH6+9QLw/orhp72j87v8Qa1ScDkvrrBNpZcDejAirJmfXQ== + 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-blocking@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/set-blocking/-/set-blocking-2.0.0.tgz#045f9782d011ae9a6803ddd382b24392b3d890f7" - integrity sha1-BF+XgtARrppoA93TgrJDkrPYkPc= + integrity sha512-KiKBS8AnWGEyLzofFfmvKwpdPzqiy16LvQfK3yv/fVH7Bj13/wl3JSR1J+rfgRE9q7xUJK4qvgS8raSOeLUehw== set-value@^2.0.0, set-value@^2.0.1: version "2.0.1" @@ -5697,7 +6016,7 @@ set-value@^2.0.0, set-value@^2.0.1: shebang-command@^1.2.0: version "1.2.0" resolved "https://registry.yarnpkg.com/shebang-command/-/shebang-command-1.2.0.tgz#44aac65b695b03398968c39f363fee5deafdf1ea" - integrity sha1-RKrGW2lbAzmJaMOfNj/uXer98eo= + integrity sha512-EV3L1+UQWGor21OmnvojK36mhg+TyIKDh3iFBKBohr5xeXIhNBcx8oWdgkTEEQ+BEFFYdLRuqMfd5L84N1V5Vg== dependencies: shebang-regex "^1.0.0" @@ -5711,7 +6030,7 @@ shebang-command@^2.0.0: shebang-regex@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/shebang-regex/-/shebang-regex-1.0.0.tgz#da42f49740c0b42db2ca9728571cb190c98efea3" - integrity sha1-2kL0l0DAtC2yypcoVxyxkMmO/qM= + integrity sha512-wpoSFAxys6b2a2wHZ1XpDSgD7N9iVjg29Ph9uV/uaP9Ex/KXlkTZTeddxDPSYQpgvzKLGJke2UU0AzoGCjNIvQ== shebang-regex@^3.0.0: version "3.0.0" @@ -5723,15 +6042,24 @@ shellwords@^0.1.1: resolved "https://registry.yarnpkg.com/shellwords/-/shellwords-0.1.1.tgz#d6b9181c1a48d397324c84871efbcfc73fc0654b" integrity sha512-vFwSUfQvqybiICwZY5+DAWIPLKsWO31Q91JSKl3UYv+K5c2QRPzn0qzec6QPu1Qc9eHYItiP3NdJqNVqetYAww== +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.0, signal-exit@^3.0.2: - version "3.0.3" - resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-3.0.3.tgz#a1410c2edd8f077b08b4e253c8eacfcaf057461c" - integrity sha512-VUJ49FC8U1OxwZLxIbTTrDvLnf/6TDgxZcK8wxR8zs13xpx7xbG60ndBlhNrFi2EMuFRoeDoJO7wthSLq42EjA== + 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== simple-swizzle@^0.2.2: version "0.2.2" resolved "https://registry.yarnpkg.com/simple-swizzle/-/simple-swizzle-0.2.2.tgz#a4da6b635ffcccca33f70d17cb92592de95e557a" - integrity sha1-pNprY1/8zMoz9w0Xy5JZLeleVXo= + integrity sha512-JA//kQgZtbuY83m+xT+tXJkmJncGMTFT+C+g2h2R9uxkYIrE2yy9sgmcLhCnw57/WSD+Eh3J97FPEDFnbXnDUg== dependencies: is-arrayish "^0.3.1" @@ -5814,22 +6142,22 @@ source-map-resolve@^0.5.0: urix "^0.1.0" source-map-support@^0.5.6, source-map-support@~0.5.12: - version "0.5.19" - resolved "https://registry.yarnpkg.com/source-map-support/-/source-map-support-0.5.19.tgz#a98b62f86dcaf4f67399648c085291ab9e8fed61" - integrity sha512-Wonm7zOCIJzBGQdB+thsPar0kYuCIzYvxZwlBa87yi/Mdjv7Tip2cyVbLj5o0cFPN4EVkuTwb3GDDyUx2DGnGw== + 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-url@^0.4.0: - version "0.4.0" - resolved "https://registry.yarnpkg.com/source-map-url/-/source-map-url-0.4.0.tgz#3e935d7ddd73631b97659956d55128e87b5084a3" - integrity sha1-PpNdfd1zYxuXZZlW1VEo6HtQhKM= + version "0.4.1" + resolved "https://registry.yarnpkg.com/source-map-url/-/source-map-url-0.4.1.tgz#0af66605a745a5a2f91cf1bbf8a7afbc283dec56" + integrity sha512-cPiFOTLUKvJFIg4SKVScy4ilPPW6rFgMgfuZJPNoDuMs3nC1HbMUycBoJw77xFIp6z1UJQJOfx6C9GMH80DiTw== source-map@^0.5.0, source-map@^0.5.6: version "0.5.7" resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.5.7.tgz#8a039d2d1021d22d1ea14c80d8ea468ba2ef3fcc" - integrity sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w= + integrity sha512-LbrmJOMUSdEVxIKvdcJzQC+nQhe8FUZQTXQy6+I75skNgn3OoQ0DZA8YnFa7gp8tqtL3KPf1kmo0R5DoApeSGQ== source-map@^0.6.0, source-map@^0.6.1, source-map@~0.6.1: version "0.6.1" @@ -5837,9 +6165,9 @@ source-map@^0.6.0, source-map@^0.6.1, source-map@~0.6.1: integrity sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g== source-map@^0.7.3: - version "0.7.3" - resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.7.3.tgz#5302f8169031735226544092e64981f751750383" - integrity sha512-CkCj6giN3S+n9qrYiBTX5gystlENnRW5jZeNLHpe6aue+SrHcG5VYwujhW9s4dY31mEGsxBDrHR6oI69fTXsaQ== + version "0.7.4" + resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.7.4.tgz#a9bbe705c9d8846f4e08ff6765acf0f1b0898656" + integrity sha512-l3BikUxvPOcn5E74dZiq5BGsTb5yEwhaTSzccU6t4sDOH8NWJCstKO5QT2CvtFoK6F0saL7p9xHAqHOlCPJygA== sourcemap-codec@^1.4.4: version "1.4.8" @@ -5847,9 +6175,9 @@ sourcemap-codec@^1.4.4: integrity sha512-9NykojV5Uih4lgo5So5dtw+f0JgJX30KCNI8gwhz2J9A15wD0Ml6tjHKwf6fTSa6fAdVBdZeNOs9eJ71qCk8vA== spdx-correct@^3.0.0: - version "3.1.1" - resolved "https://registry.yarnpkg.com/spdx-correct/-/spdx-correct-3.1.1.tgz#dece81ac9c1e6713e5f7d1b6f17d468fa53d89a9" - integrity sha512-cOYcUWwhCuHCXi49RhFRCyJEK3iPj1Ziz9DpViV3tbZOwXD49QzIN3MpOLJNxh2qwq2lJJZaKMVw9qNi4jTC0w== + version "3.2.0" + resolved "https://registry.yarnpkg.com/spdx-correct/-/spdx-correct-3.2.0.tgz#4f5ab0668f0059e34f9c00dce331784a12de4e9c" + integrity sha512-kN9dJbvnySHULIluDHy32WHRUu3Og7B9sbY7tsFLctQkIqnMh3hErYgdMjTYuqmcXX+lK5T1lnUt3G7zNswmZA== dependencies: spdx-expression-parse "^3.0.0" spdx-license-ids "^3.0.0" @@ -5868,9 +6196,9 @@ spdx-expression-parse@^3.0.0: spdx-license-ids "^3.0.0" spdx-license-ids@^3.0.0: - version "3.0.6" - resolved "https://registry.yarnpkg.com/spdx-license-ids/-/spdx-license-ids-3.0.6.tgz#c80757383c28abf7296744998cbc106ae8b854ce" - integrity sha512-+orQK83kyMva3WyPf59k1+Y525csj5JejicWut55zeTWANuN17qSiSLUXWtzHeNWORSvT7GLDJ/E/XiIWoXBTw== + version "3.0.13" + resolved "https://registry.yarnpkg.com/spdx-license-ids/-/spdx-license-ids-3.0.13.tgz#7189a474c46f8d47c7b0da4b987bb45e908bd2d5" + integrity sha512-XkD+zwiqXHikFZm4AX/7JSCXA98U5Db4AFd5XUg/+9UNtnH75+Z9KxtpYiJZx36mUDVOwH83pl7yvCer6ewM3w== split-string@^3.0.1, split-string@^3.0.2: version "3.1.0" @@ -5882,12 +6210,12 @@ split-string@^3.0.1, split-string@^3.0.2: sprintf-js@~1.0.2: version "1.0.3" resolved "https://registry.yarnpkg.com/sprintf-js/-/sprintf-js-1.0.3.tgz#04e6926f662895354f3dd015203633b857297e2c" - integrity sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw= + integrity sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g== sshpk@^1.7.0: - version "1.16.1" - resolved "https://registry.yarnpkg.com/sshpk/-/sshpk-1.16.1.tgz#fb661c0bef29b39db40769ee39fa70093d6f6877" - integrity sha512-HXXqVUq7+pcKeLqqZj6mHFUMvXtOJt1uoUx09pFW6011inTMxqI8BA8PM95myrIyyKwdnzjdFjLiE6KBPVtJIg== + version "1.17.0" + resolved "https://registry.yarnpkg.com/sshpk/-/sshpk-1.17.0.tgz#578082d92d4fe612b13007496e543fa0fbcbe4c5" + integrity sha512-/9HIEs1ZXGhSPE8X6Ccm7Nam1z8KcoCqPdI7ecm1N33EzAetWahvQWVqLZtaZQ+IDKX4IyA2o0gBzqIMkAagHQ== dependencies: asn1 "~0.2.3" assert-plus "^1.0.0" @@ -5905,14 +6233,16 @@ stable@^0.1.8: integrity sha512-ji9qxRnOVfcuLDySj9qzhGSEFVobyt1kIOSkj1qZzYLzq7Tos/oUUWvotUPQLlrsidqsK6tBH89Bc9kL5zHA6w== stack-utils@^1.0.1: - version "1.0.2" - resolved "https://registry.yarnpkg.com/stack-utils/-/stack-utils-1.0.2.tgz#33eba3897788558bebfc2db059dc158ec36cebb8" - integrity sha512-MTX+MeG5U994cazkjd/9KNAapsHnibjMLnfXodlkXw76JEea0UiNzrqidzo1emMwk7w5Qhc9jd4Bn9TBb1MFwA== + version "1.0.5" + resolved "https://registry.yarnpkg.com/stack-utils/-/stack-utils-1.0.5.tgz#a19b0b01947e0029c8e451d5d61a498f5bb1471b" + integrity sha512-KZiTzuV3CnSnSvgMRrARVCj+Ht7rMbauGDK0LdVFRGyenwdylpajAp4Q0i6SX8rEmbTpMMf6ryq2gb8pPq2WgQ== + dependencies: + escape-string-regexp "^2.0.0" static-extend@^0.1.1: version "0.1.2" resolved "https://registry.yarnpkg.com/static-extend/-/static-extend-0.1.2.tgz#60809c39cbff55337226fd5e0b520f341f1fb5c6" - integrity sha1-YICcOcv/VTNyJv1eC1IPNB8ftcY= + integrity sha512-72E9+uLc27Mt718pMHt9VMNiAL4LMsmDbBva8mxWUCkT07fSzEGMYUCk0XWY6lp0j6RBAG4cJ3mWuZv2OE3s0g== dependencies: define-property "^0.2.5" object-copy "^0.1.0" @@ -5920,7 +6250,7 @@ static-extend@^0.1.1: stealthy-require@^1.1.1: version "1.1.1" resolved "https://registry.yarnpkg.com/stealthy-require/-/stealthy-require-1.1.1.tgz#35b09875b4ff49f26a777e509b3090a3226bf24b" - integrity sha1-NbCYdbT/SfJqd35QmzCQoyJr8ks= + integrity sha512-ZnWpYnYugiOVEY5GkcuJK1io5V8QmNYChG62gSit9pQVGErXtrKuPC55ITaVSukmMta5qpMU7vqLt2Lnni4f/g== string-argv@0.3.1: version "0.3.1" @@ -5945,29 +6275,40 @@ string-width@^3.0.0: strip-ansi "^5.1.0" string-width@^4.1.0, string-width@^4.2.0: - version "4.2.0" - resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.0.tgz#952182c46cc7b2c313d1596e623992bd163b72b5" - integrity sha512-zUz5JD+tgqtuDjMhwIg5uFVV3dtqZ9yQJlZVfq4I01/K5Paj5UHj7VyrQOJvzawSVlKpObApbfD0Ed6yJc+1eg== + 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.0" + strip-ansi "^6.0.1" -string.prototype.trimend@^1.0.1: - version "1.0.2" - resolved "https://registry.yarnpkg.com/string.prototype.trimend/-/string.prototype.trimend-1.0.2.tgz#6ddd9a8796bc714b489a3ae22246a208f37bfa46" - integrity sha512-8oAG/hi14Z4nOVP0z6mdiVZ/wqjDtWSLygMigTzAb+7aPEDTleeFf+WrF+alzecxIRkckkJVn+dTlwzJXORATw== +string.prototype.trim@^1.2.7: + version "1.2.7" + resolved "https://registry.yarnpkg.com/string.prototype.trim/-/string.prototype.trim-1.2.7.tgz#a68352740859f6893f14ce3ef1bb3037f7a90533" + integrity sha512-p6TmeT1T3411M8Cgg9wBTMRtY2q9+PNy9EV1i2lIXUN/btt763oIfxwN3RR8VU6wHX8j/1CFy0L+YuThm6bgOg== dependencies: - define-properties "^1.1.3" - es-abstract "^1.18.0-next.1" + call-bind "^1.0.2" + define-properties "^1.1.4" + es-abstract "^1.20.4" -string.prototype.trimstart@^1.0.1: - version "1.0.2" - resolved "https://registry.yarnpkg.com/string.prototype.trimstart/-/string.prototype.trimstart-1.0.2.tgz#22d45da81015309cd0cdd79787e8919fc5c613e7" - integrity sha512-7F6CdBTl5zyu30BJFdzSTlSlLPwODC23Od+iLoVH8X6+3fvDPPuBVVj9iaB1GOsSTSIgVfsfm27R2FGrAPznWg== +string.prototype.trimend@^1.0.1, string.prototype.trimend@^1.0.6: + version "1.0.6" + resolved "https://registry.yarnpkg.com/string.prototype.trimend/-/string.prototype.trimend-1.0.6.tgz#c4a27fa026d979d79c04f17397f250a462944533" + integrity sha512-JySq+4mrPf9EsDBEDYMOb/lM7XQLulwg5R/m1r0PXEFqrV0qHvl58sdTilSXtKOflCsK2E8jxf+GKC0T07RWwQ== dependencies: - define-properties "^1.1.3" - es-abstract "^1.18.0-next.1" + call-bind "^1.0.2" + define-properties "^1.1.4" + es-abstract "^1.20.4" + +string.prototype.trimstart@^1.0.1, string.prototype.trimstart@^1.0.6: + version "1.0.6" + resolved "https://registry.yarnpkg.com/string.prototype.trimstart/-/string.prototype.trimstart-1.0.6.tgz#e90ab66aa8e4007d92ef591bbf3cd422c56bdcf4" + integrity sha512-omqjMDaY92pbn5HOX7f9IccLA+U1tA9GvtU4JrodiXFfYB7jPzzHpRzpglLAjtUV6bB557zwClJezTqnAiYnQA== + dependencies: + call-bind "^1.0.2" + define-properties "^1.1.4" + es-abstract "^1.20.4" stringify-object@^3.3.0: version "3.3.0" @@ -5985,17 +6326,17 @@ strip-ansi@^5.1.0, strip-ansi@^5.2.0: dependencies: ansi-regex "^4.1.0" -strip-ansi@^6.0.0: - version "6.0.0" - resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-6.0.0.tgz#0b1571dd7669ccd4f3e06e14ef1eed26225ae532" - integrity sha512-AuvKTrTfQNYNIctbR1K/YGTR1756GycPsg7b9bdV9Duqur4gv6aKqHXah67Z8ImS7WEz5QVcOtlfW2rZEugt6w== +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.0" + ansi-regex "^5.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 sha1-IzTBjpx1n3vdVv3vfprj1YjmjtM= + integrity sha512-vavAMRXOgBVNF6nyEEmL3DBK19iRpDcoIwW+swQ+CbGiu7lju6t+JklA1MHweoWtadgt4ISVUsXLyDq34ddcwA== strip-bom@^4.0.0: version "4.0.0" @@ -6005,7 +6346,7 @@ strip-bom@^4.0.0: strip-eof@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/strip-eof/-/strip-eof-1.0.0.tgz#bb43ff5598a6eb05d89b59fcd129c983313606bf" - integrity sha1-u0P/VZim6wXYm1n80SnJgzE2Br8= + integrity sha512-7FCwGGmx8mD5xQd3RPUvnSpUXHM3BWuzjtpD4TXsfcZ9EL4azvVVUscFYwD9nx8Kh+uCBC00XBtAykoMHwTh8Q== strip-final-newline@^2.0.0: version "2.0.0" @@ -6048,13 +6389,18 @@ supports-color@^7.0.0, supports-color@^7.1.0: has-flag "^4.0.0" supports-hyperlinks@^2.0.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/supports-hyperlinks/-/supports-hyperlinks-2.1.0.tgz#f663df252af5f37c5d49bbd7eeefa9e0b9e59e47" - integrity sha512-zoE5/e+dnEijk6ASB6/qrK+oYdm2do1hjoLWrqUC/8WEIW1gbxFcKuBof7sW8ArN6e+AYvsE8HBGiVRWL/F5CA== + 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== + svgo@^1.0.0: version "1.3.2" resolved "https://registry.yarnpkg.com/svgo/-/svgo-1.3.2.tgz#b6dc511c063346c9e415b81e43401145b96d4167" @@ -6098,9 +6444,9 @@ terminal-link@^2.0.0: supports-hyperlinks "^2.0.0" terser@~4.8.0: - version "4.8.0" - resolved "https://registry.yarnpkg.com/terser/-/terser-4.8.0.tgz#63056343d7c70bb29f3af665865a46fe03a0df17" - integrity sha512-EAPipTNeWsb/3wLPeup1tVPaXfIaU68xMnVdPafIL1TV05OhASArYyIfFvnvJCNrR2NIOvDVNNTFRa+Re2MWyw== + version "4.8.1" + resolved "https://registry.yarnpkg.com/terser/-/terser-4.8.1.tgz#a00e5634562de2239fd404c649051bf6fc21144f" + integrity sha512-4GnLC0x667eJG0ewJTa6z/yXrbLGv80D9Ru6HIpCQmO+Q4PfEtBFi0ObSckqwL6VyQv/7ENJieXHo2ANmdQwgw== dependencies: commander "^2.20.0" source-map "~0.6.1" @@ -6118,7 +6464,7 @@ test-exclude@^6.0.0: text-table@^0.2.0: version "0.2.0" resolved "https://registry.yarnpkg.com/text-table/-/text-table-0.2.0.tgz#7f5ee823ae805207c00af2df4a84ec3fcfa570b4" - integrity sha1-f17oI66AUgfACvLfSoTsP8+lcLQ= + integrity sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw== throat@^5.0.0: version "5.0.0" @@ -6128,34 +6474,34 @@ throat@^5.0.0: through@^2.3.8: version "2.3.8" resolved "https://registry.yarnpkg.com/through/-/through-2.3.8.tgz#0dd4c9ffaabc357960b1b724115d7e0e86a2e1f5" - integrity sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU= + integrity sha512-w89qg7PI8wAdvX60bMDP+bFoD5Dvhm9oLheFp5O4a2QF0cSBGsBX4qZmadPMvVqlLJBBci+WqGGOAPvcDeNSVg== timsort@^0.3.0: version "0.3.0" resolved "https://registry.yarnpkg.com/timsort/-/timsort-0.3.0.tgz#405411a8e7e6339fe64db9a234de11dc31e02bd4" - integrity sha1-QFQRqOfmM5/mTbmiNN4R3DHgK9Q= + integrity sha512-qsdtZH+vMoCARQtyod4imc2nIJwg9Cc7lPRrw9CzF8ZKR0khdr8+2nX80PBhET3tcyTtJDxAffGh2rXH4tyU8A== -tmpl@1.0.x: - version "1.0.4" - resolved "https://registry.yarnpkg.com/tmpl/-/tmpl-1.0.4.tgz#23640dd7b42d00433911140820e5cf440e521dd1" - integrity sha1-I2QN17QtAEM5ERQIIOXPRA5SHdE= +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 sha1-3F5pjL0HkmW8c+A3doGk5Og/YW4= + integrity sha512-/OaKK0xYrs3DmxRYqL/yDc+FxFUVYhDlXMhRmv3z915w2HF1tnN1omB354j8VUGO/hbRzyD6Y3sA7v7GS/ceog== to-object-path@^0.3.0: version "0.3.0" resolved "https://registry.yarnpkg.com/to-object-path/-/to-object-path-0.3.0.tgz#297588b7b0e7e0ac08e04e672f85c1f4999e17af" - integrity sha1-KXWIt7Dn4KwI4E5nL4XB9JmeF68= + integrity sha512-9mWHdnGRuh3onocaHzukyvCZhzvr6tiflAy/JRFXcJX0TjgfWA9pk9t8CMbzmBE4Jfw58pXbkngtBtqYxzNEyg== dependencies: kind-of "^3.0.2" to-regex-range@^2.1.0: version "2.1.1" resolved "https://registry.yarnpkg.com/to-regex-range/-/to-regex-range-2.1.1.tgz#7c80c17b9dfebe599e27367e0d4dd5590141db38" - integrity sha1-fIDBe53+vlmeJzZ+DU3VWQFB2zg= + integrity sha512-ZZWNfCjUokXXDGXFpZehJIkZqq91BcULFq/Pi7M5i4JnxXdhMKAK682z8bCW3o8Hj1wuuzoKcW3DfVzaP6VuNg== dependencies: is-number "^3.0.0" repeat-string "^1.6.1" @@ -6197,14 +6543,14 @@ tough-cookie@^3.0.1: tr46@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/tr46/-/tr46-1.0.1.tgz#a8b13fd6bfd2489519674ccde55ba3693b706d09" - integrity sha1-qLE/1r/SSJUZZ0zN5VujaTtwbQk= + integrity sha512-dTpowEjclQ7Kgx5SdBkqRzVhERQXov8/l9Ft9dVM9fmg0W0KQSVaXX9T4i6twCPNtYiZM53lpSSUAwJbFPOHxA== dependencies: punycode "^2.1.0" trim-right@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/trim-right/-/trim-right-1.0.1.tgz#cb2e1203067e0c8de1f614094b9fe45704ea6003" - integrity sha1-yy4SAwZ+DI3h9hQJS5/kVwTqYAM= + integrity sha512-WZGXGstmCWgeevgTL54hrCuw1dyMQIzWy7ZfqRJfSmJZBwklI15egmQytFP6bPidmw3M8d5yEowl1niq4vmqZw== tslib@^1.8.1, tslib@^1.9.0: version "1.14.1" @@ -6212,23 +6558,23 @@ tslib@^1.8.1, tslib@^1.9.0: integrity sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg== tsutils@^3.17.1: - version "3.17.1" - resolved "https://registry.yarnpkg.com/tsutils/-/tsutils-3.17.1.tgz#ed719917f11ca0dee586272b2ac49e015a2dd759" - integrity sha512-kzeQ5B8H3w60nFY2g8cJIuH7JDpsALXySGtwGJ0p2LSjLgay3NdIpqq5SoOBe46bKDW2iq25irHCr8wjomUS2g== + 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" tunnel-agent@^0.6.0: version "0.6.0" resolved "https://registry.yarnpkg.com/tunnel-agent/-/tunnel-agent-0.6.0.tgz#27a5dea06b36b04a0a9966774b290868f0fc40fd" - integrity sha1-J6XeoGs2sEoKmWZ3SykIaPD8QP0= + integrity sha512-McnNiV1l8RYeY8tBgEpuodCC1mLUdbSN+CYBL7kJsJNInOP8UjDDEwdk6Mw60vdLLrr5NHKZhMAOSrR2NZuQ+w== dependencies: safe-buffer "^5.0.1" tweetnacl@^0.14.3, tweetnacl@~0.14.0: version "0.14.5" resolved "https://registry.yarnpkg.com/tweetnacl/-/tweetnacl-0.14.5.tgz#5ae68177f192d4456269d108afa93ff8743f4f64" - integrity sha1-WuaBd/GS1EViadEIr6k/+HQ/T2Q= + integrity sha512-KXXFFdAbFXY4geFIwoyNK+f5Z1b7swfXABfL7HXCmoIWMKU3dmS26672A4EeQtDzLKy7SXmfBu51JolvEKwtGA== type-check@^0.4.0, type-check@~0.4.0: version "0.4.0" @@ -6240,7 +6586,7 @@ type-check@^0.4.0, type-check@~0.4.0: type-check@~0.3.2: version "0.3.2" resolved "https://registry.yarnpkg.com/type-check/-/type-check-0.3.2.tgz#5884cab512cf1d355e3fb784f30804b2b520db72" - integrity sha1-WITKtRLPHTVeP7eE8wgEsrUg23I= + integrity sha512-ZCmOJdvOWDBYJlzAoFkC+Q0+bUyEOS1ltgp1MGU03fqHG+dbi9tBFU2Rd9QKiDZFAYrhPh2JUf7rZRIuHRKtOg== dependencies: prelude-ls "~1.1.2" @@ -6264,6 +6610,15 @@ type-fest@^0.8.1: resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.8.1.tgz#09e249ebde851d3b1e48d27c105444667f17b83d" integrity sha512-4dbzIzqvjtgiM5rw1k5rEHtBANKmdudhGyBEajN01fEyhaAIhsoKNy6y7+IN93IfpFtwY9iqi7kD+xwKhQsNJA== +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" @@ -6271,28 +6626,38 @@ typedarray-to-buffer@^3.1.5: dependencies: is-typedarray "^1.0.0" -unicode-canonical-property-names-ecmascript@^1.0.4: - version "1.0.4" - resolved "https://registry.yarnpkg.com/unicode-canonical-property-names-ecmascript/-/unicode-canonical-property-names-ecmascript-1.0.4.tgz#2619800c4c825800efdd8343af7dd9933cbe2818" - integrity sha512-jDrNnXWHd4oHiTZnx/ZG7gtUTVp+gCcTTKr8L0HjlwphROEW3+Him+IpvC+xcJEFegapiMZyZe02CyuOnRmbnQ== +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" -unicode-match-property-ecmascript@^1.0.4: - version "1.0.4" - resolved "https://registry.yarnpkg.com/unicode-match-property-ecmascript/-/unicode-match-property-ecmascript-1.0.4.tgz#8ed2a32569961bce9227d09cd3ffbb8fed5f020c" - integrity sha512-L4Qoh15vTfntsn4P1zqnHulG0LdXgjSO035fEpdtp6YxXhMT51Q6vgM5lYdG/5X3MjS+k/Y9Xw4SFCY9IkR0rg== +unicode-canonical-property-names-ecmascript@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/unicode-canonical-property-names-ecmascript/-/unicode-canonical-property-names-ecmascript-2.0.0.tgz#301acdc525631670d39f6146e0e77ff6bbdebddc" + integrity sha512-yY5PpDlfVIU5+y/BSCxAJRBIS1Zc2dDG3Ujq+sR0U+JjUevW2JhocOF+soROYDSaAezOzOKuyyixhD6mBknSmQ== + +unicode-match-property-ecmascript@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/unicode-match-property-ecmascript/-/unicode-match-property-ecmascript-2.0.0.tgz#54fd16e0ecb167cf04cf1f756bdcc92eba7976c3" + integrity sha512-5kaZCrbp5mmbz5ulBkDkbY0SsPOjKqVS35VpL9ulMPfSl0J0Xsm+9Evphv9CoIZFwre7aJoa94AY6seMKGVN5Q== dependencies: - unicode-canonical-property-names-ecmascript "^1.0.4" - unicode-property-aliases-ecmascript "^1.0.4" + unicode-canonical-property-names-ecmascript "^2.0.0" + unicode-property-aliases-ecmascript "^2.0.0" -unicode-match-property-value-ecmascript@^1.2.0: - version "1.2.0" - resolved "https://registry.yarnpkg.com/unicode-match-property-value-ecmascript/-/unicode-match-property-value-ecmascript-1.2.0.tgz#0d91f600eeeb3096aa962b1d6fc88876e64ea531" - integrity sha512-wjuQHGQVofmSJv1uVISKLE5zO2rNGzM/KCYZch/QQvez7C1hUhBIuZ701fYXExuufJFMPhv2SyL8CyoIfMLbIQ== +unicode-match-property-value-ecmascript@^2.0.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/unicode-match-property-value-ecmascript/-/unicode-match-property-value-ecmascript-2.1.0.tgz#cb5fffdcd16a05124f5a4b0bf7c3770208acbbe0" + integrity sha512-qxkjQt6qjg/mYscYMC0XKRn3Rh0wFPlfxB0xkt9CfyTvpX1Ra0+rAmdX2QyAobptSEvuy4RtpPRui6XkV+8wjA== -unicode-property-aliases-ecmascript@^1.0.4: - version "1.1.0" - resolved "https://registry.yarnpkg.com/unicode-property-aliases-ecmascript/-/unicode-property-aliases-ecmascript-1.1.0.tgz#dd57a99f6207bedff4628abefb94c50db941c8f4" - integrity sha512-PqSoPh/pWetQ2phoj5RLiaqIk4kCNwoV3CI+LfGmWLKI3rE3kl1h59XpX2BjgDrmbxD9ARtQobPGU1SguCYuQg== +unicode-property-aliases-ecmascript@^2.0.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/unicode-property-aliases-ecmascript/-/unicode-property-aliases-ecmascript-2.1.0.tgz#43d41e3be698bd493ef911077c9b131f827e8ccd" + integrity sha512-6t3foTQI9qne+OZoVQB/8x8rk2k1eVy1gRXhV3oFQ5T6R1dqQ1xtin3XqSlx3+ATBkliTaR/hHyJBm+LVPNM8w== union-value@^1.0.0: version "1.0.1" @@ -6307,37 +6672,37 @@ union-value@^1.0.0: uniq@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/uniq/-/uniq-1.0.1.tgz#b31c5ae8254844a3a8281541ce2b04b865a734ff" - integrity sha1-sxxa6CVIRKOoKBVBzisEuGWnNP8= + integrity sha512-Gw+zz50YNKPDKXs+9d+aKAjVwpjNwqzvNpLigIruT4HA9lMZNdMqs9x07kKHB/L9WRzqp4+DlTU5s4wG2esdoA== uniqs@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/uniqs/-/uniqs-2.0.0.tgz#ffede4b36b25290696e6e165d4a59edb998e6b02" - integrity sha1-/+3ks2slKQaW5uFl1KWe25mOawI= + integrity sha512-mZdDpf3vBV5Efh29kMw5tXoup/buMgxLzOt/XKFKcVmi+15ManNQWr6HfZ2aiZTYlYixbdNJ0KFmIZIv52tHSQ== unquote@~1.1.1: version "1.1.1" resolved "https://registry.yarnpkg.com/unquote/-/unquote-1.1.1.tgz#8fded7324ec6e88a0ff8b905e7c098cdc086d544" - integrity sha1-j97XMk7G6IoP+LkF58CYzcCG1UQ= + integrity sha512-vRCqFv6UhXpWxZPyGDh/F3ZpNv8/qo7w6iufLpQg9aKnQ71qM4B5KiI7Mia9COcjEhrO9LueHpMYjYzsWH3OIg== unset-value@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/unset-value/-/unset-value-1.0.0.tgz#8376873f7d2335179ffb1e6fc3a8ed0dfc8ab559" - integrity sha1-g3aHP30jNRef+x5vw6jtDfyKtVk= + integrity sha512-PcA2tsuGSF9cnySLHTLSh2qrQiJ70mn+r+Glzxv2TWZblxsxCC52BDlZoPCsz7STd9pN7EZetkWZBAvk4cgZdQ== dependencies: has-value "^0.3.1" isobject "^3.0.0" uri-js@^4.2.2: - version "4.4.0" - resolved "https://registry.yarnpkg.com/uri-js/-/uri-js-4.4.0.tgz#aa714261de793e8a82347a7bcc9ce74e86f28602" - integrity sha512-B0yRTzYdUCCn9n+F4+Gh4yIDtMQcaJsmYBDsTSG8g/OejKBodLQ2IHfN3bM7jUsRXndopT7OIXWdYqc1fjmV6g== + 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" urix@^0.1.0: version "0.1.0" resolved "https://registry.yarnpkg.com/urix/-/urix-0.1.0.tgz#da937f7a62e21fec1fd18d49b35c2935067a6c72" - integrity sha1-2pN/emLiH+wf0Y1Js1wpNQZ6bHI= + integrity sha512-Am1ousAhSLBeB9cG/7k7r2R0zj50uDRlZHPGbazid5s9rlF1F/QKYObEKSIunSjIOkJZqwRRLpvewjEkM7pSqg== use@^3.1.0: version "3.1.1" @@ -6347,7 +6712,7 @@ use@^3.1.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 sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8= + integrity sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw== util.promisify@~1.0.0: version "1.0.1" @@ -6365,9 +6730,9 @@ uuid@^3.3.2: integrity sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A== v8-compile-cache@^2.0.3: - version "2.1.1" - resolved "https://registry.yarnpkg.com/v8-compile-cache/-/v8-compile-cache-2.1.1.tgz#54bc3cdd43317bca91e35dcaf305b1a7237de745" - integrity sha512-8OQ9CL+VWyt3JStj7HX7/ciTL2V3Rl1Wf5OL+SNTm0yK1KvtReVulksyeRnCANHHuUxHlQig+JJDlUhBt1NQDQ== + version "2.3.0" + resolved "https://registry.yarnpkg.com/v8-compile-cache/-/v8-compile-cache-2.3.0.tgz#2de19618c66dc247dcfb6f99338035d8245a2cee" + integrity sha512-l8lCEmLcLYZh4nbunNZvQCJc5pv7+RCwa8q/LdUx8u7lsWvPDKmpodJAJNwkAhJC//dFY48KuIEmjtd4RViDrA== v8-to-istanbul@^4.1.3: version "4.1.4" @@ -6394,7 +6759,7 @@ vendors@^1.0.0: verror@1.10.0: version "1.10.0" resolved "https://registry.yarnpkg.com/verror/-/verror-1.10.0.tgz#3a105ca17053af55d6e270c1f8288682e18da400" - integrity sha1-OhBcoXBTr1XW4nDB+CiGguGNpAA= + integrity sha512-ZZKSmDAEFOijERBLkmYfJ+vmk3w+7hOLYDNkRCuRuMJGEmqYNCNLyBBFwWKVMhfwaEF3WOd0Zlw86U/WC/+nYw== dependencies: assert-plus "^1.0.0" core-util-is "1.0.2" @@ -6417,22 +6782,22 @@ w3c-xmlserializer@^1.1.2: xml-name-validator "^3.0.0" wait-on@^5.0.0: - version "5.2.0" - resolved "https://registry.yarnpkg.com/wait-on/-/wait-on-5.2.0.tgz#6711e74422523279714a36d52cf49fb47c9d9597" - integrity sha512-U1D9PBgGw2XFc6iZqn45VBubw02VsLwnZWteQ1au4hUVHasTZuFSKRzlTB2dqgLhji16YVI8fgpEpwUdCr8B6g== + version "5.3.0" + resolved "https://registry.yarnpkg.com/wait-on/-/wait-on-5.3.0.tgz#584e17d4b3fe7b46ac2b9f8e5e102c005c2776c7" + integrity sha512-DwrHrnTK+/0QFaB9a8Ol5Lna3k7WvUR4jzSKmz0YaPBpuN2sACyiPVKVfj6ejnjcajAcvn3wlbTyMIn9AZouOg== dependencies: - axios "^0.19.2" - joi "^17.1.1" - lodash "^4.17.19" + axios "^0.21.1" + joi "^17.3.0" + lodash "^4.17.21" minimist "^1.2.5" - rxjs "^6.5.5" + rxjs "^6.6.3" walker@^1.0.7, walker@~1.0.5: - version "1.0.7" - resolved "https://registry.yarnpkg.com/walker/-/walker-1.0.7.tgz#2f7f9b8fd10d677262b18a884e28d19618e028fb" - integrity sha1-L3+bj9ENZ3JisYqITijRlhjgKPs= + 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.x" + makeerror "1.0.12" webidl-conversions@^4.0.2: version "4.0.2" @@ -6460,15 +6825,38 @@ whatwg-url@^7.0.0: tr46 "^1.0.1" webidl-conversions "^4.0.2" +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-module@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/which-module/-/which-module-2.0.0.tgz#d9ef07dce77b9902b8a3a8fa4b31c3e3f7e6e87a" - integrity sha1-2e8H3Od7mQK4o6j6SzHD4/fm6Ho= + integrity sha512-B+enWhmw6cjfVC7kS8Pj9pCrKSc5txArRyaYGe088shv/FGWH+0Rjx/xPgtsWfsUtS27FkP697E4DDhgrgoc0Q== which-pm-runs@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/which-pm-runs/-/which-pm-runs-1.0.0.tgz#670b3afbc552e0b55df6b7780ca74615f23ad1cb" - integrity sha1-Zws6+8VS4LVd9rd4DKdGFfI60cs= + version "1.1.0" + resolved "https://registry.yarnpkg.com/which-pm-runs/-/which-pm-runs-1.1.0.tgz#35ccf7b1a0fce87bd8b92a478c9d045785d3bf35" + integrity sha512-n1brCuqClxfFfq/Rb0ICg9giSZqCS+pLtccdag6C2HyufBrh3fBOiy9nb6ggRMvWOVH5GrdJskj5iGTZNxd7SA== + +which-typed-array@^1.1.9: + version "1.1.9" + resolved "https://registry.yarnpkg.com/which-typed-array/-/which-typed-array-1.1.9.tgz#307cf898025848cf995e795e8423c7f337efbde6" + integrity sha512-w9c4xkx6mPidwp7180ckYWfMmvxpjlZuIudNtDf4N/tTAUB8VJbX25qZoAsrtGuYNnGw3pa0AXgbGKRB8/EceA== + dependencies: + available-typed-arrays "^1.0.5" + call-bind "^1.0.2" + for-each "^0.3.3" + gopd "^1.0.1" + has-tostringtag "^1.0.0" + is-typed-array "^1.1.10" which@^1.2.9, which@^1.3.1: version "1.3.1" @@ -6485,9 +6873,9 @@ which@^2.0.1, which@^2.0.2: isexe "^2.0.0" word-wrap@^1.2.3, word-wrap@~1.2.3: - version "1.2.3" - resolved "https://registry.yarnpkg.com/word-wrap/-/word-wrap-1.2.3.tgz#610636f6b1f703891bd34771ccb17fb93b47079c" - integrity sha512-Hz/mrNwitNRh/HUAtM/VT/5VH+ygD6DV7mYKZAtHOrbs8U7lvPS6xf7EJKMF0uW1KJCl0H701g3ZGus+muE5vQ== + version "1.2.5" + resolved "https://registry.yarnpkg.com/word-wrap/-/word-wrap-1.2.5.tgz#d2c45c6dd4fbce621a66f136cbe328afd0410b34" + integrity sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA== wrap-ansi@^6.2.0: version "6.2.0" @@ -6510,7 +6898,7 @@ wrap-ansi@^7.0.0: wrappy@1: version "1.0.2" resolved "https://registry.yarnpkg.com/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f" - integrity sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8= + integrity sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ== write-file-atomic@^3.0.0: version "3.0.3" @@ -6530,9 +6918,9 @@ write@1.0.3: mkdirp "^0.5.1" ws@^7.0.0: - version "7.3.1" - resolved "https://registry.yarnpkg.com/ws/-/ws-7.3.1.tgz#d0547bf67f7ce4f12a72dfe31262c68d7dc551c8" - integrity sha512-D3RuNkynyHmEJIpD2qrgVkc9DQ23OrN/moAwZX4L8DfvszsJxpjQuUq3LMx6HoYji9fbIOBY18XWBsAux1ZZUA== + 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" @@ -6545,19 +6933,24 @@ xmlchars@^2.1.1: integrity sha512-JZnDKK8B0RCDw84FNdDAIpZK+JuJw+s7Lz8nksI7SIuU3UXJJslUthsi+uWBUYOwPFwW7W7PRLRfUKpxjtjFCw== y18n@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/y18n/-/y18n-4.0.0.tgz#95ef94f85ecc81d007c264e190a120f0a3c8566b" - integrity sha512-r9S/ZyXu/Xu9q1tYlpsLIsa3EeLXXk0VwlxqTcFRfg9EhMW+17kbt9G0NrgCmhGb5vT2hyhJZLfDGx+7+5Uj/w== + version "4.0.3" + resolved "https://registry.yarnpkg.com/y18n/-/y18n-4.0.3.tgz#b5f259c82cd6e336921efd7bfd8bf560de9eeedf" + integrity sha512-JKhqTOwSrqNA1NY5lSztJ1GrBiUodLMmIZuLiDaMRJ+itFd+ABVE8XBjOvIWL+rSqNDC74LCSFmlb/U4UZ4hJQ== -y18n@^5.0.2: - version "5.0.4" - resolved "https://registry.yarnpkg.com/y18n/-/y18n-5.0.4.tgz#0ab2db89dd5873b5ec4682d8e703e833373ea897" - integrity sha512-deLOfD+RvFgrpAmSZgfGdWYE+OKyHcVHaRQ7NphG/63scpRvTHHeQMAxGGvaLVGJ+HYVcCXlzcTK0ZehFf+eHQ== +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@^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.0: - version "1.10.0" - resolved "https://registry.yarnpkg.com/yaml/-/yaml-1.10.0.tgz#3b593add944876077d4d683fee01081bd9fff31e" - integrity sha512-yr2icI4glYaNG+KWONODapy2/jDdMSDnrONSjblABjD9B4Z5LgiircSt8m8sRZFNi08kG9Sm0uSHtEmP3zaEGg== + version "1.10.2" + resolved "https://registry.yarnpkg.com/yaml/-/yaml-1.10.2.tgz#2301c5ffbf12b467de8da2333a459e29e7920e4b" + integrity sha512-r3vXyErRCYJ7wg28yvBY5VSoAF8ZvlcW9/BwUzEtUsjvX/DKs24dIkuwjtuprwJJHsbyUbLApepYTR1BN4uHrg== yargs-parser@^18.1.1, yargs-parser@^18.1.2: version "18.1.3" @@ -6568,9 +6961,9 @@ yargs-parser@^18.1.1, yargs-parser@^18.1.2: decamelize "^1.2.0" yargs-parser@^20.2.2: - version "20.2.3" - resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-20.2.3.tgz#92419ba867b858c868acf8bae9bf74af0dd0ce26" - integrity sha512-emOFRT9WVHw03QSvN5qor9QQT9+sw5vwxfYweivSMHTcAXPefwVae2FjO7JJjj8hCE4CzPOPeFM83VwT29HCww== + 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@^15.3.1: version "15.4.1" @@ -6590,16 +6983,16 @@ yargs@^15.3.1: yargs-parser "^18.1.2" yargs@^16.0.2: - version "16.1.0" - resolved "https://registry.yarnpkg.com/yargs/-/yargs-16.1.0.tgz#fc333fe4791660eace5a894b39d42f851cd48f2a" - integrity sha512-upWFJOmDdHN0syLuESuvXDmrRcWd1QafJolHskzaw79uZa7/x53gxQKiR07W59GWY1tFhhU/Th9DrtSfpS782g== + 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.2" + y18n "^5.0.5" yargs-parser "^20.2.2" yargs@~15.3.1: diff --git a/examples/users/sharing-settings-setup/package.xml b/examples/users/sharing-settings-setup/package.xml index a7b36e1b..6211a63e 100644 --- a/examples/users/sharing-settings-setup/package.xml +++ b/examples/users/sharing-settings-setup/package.xml @@ -4,6 +4,10 @@ ProductCatalog CustomObject + + ProductMedia + CustomObject + ElectronicMediaGroup CustomObject From 7d9eb1355bf9fcd8468a4413ac6d7df74b7e4d88 Mon Sep 17 00:00:00 2001 From: Oleksii Golub Date: Wed, 3 Jan 2024 02:09:27 +0200 Subject: [PATCH 2/4] added .idea folder to git ignore --- .gitignore | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitignore b/.gitignore index 9b1b8d55..8a0d0cce 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,4 @@ .sfdx sfdx/force-app .DS_Store +.idea From 68fed61a5280a267a35ccd03e1cf75558fdc552b Mon Sep 17 00:00:00 2001 From: Oleksii Golub Date: Wed, 3 Jan 2024 02:11:55 +0200 Subject: [PATCH 3/4] update readme and update bash scripts to use sf and remove deprecation --- sfdx/README.md | 61 ++++++++++++----------- sfdx/convert-examples-to-sfdx.sh | 20 ++++---- sfdx/quickstart-create-and-setup-store.sh | 16 +++--- 3 files changed, 50 insertions(+), 47 deletions(-) diff --git a/sfdx/README.md b/sfdx/README.md index f2b9aa2a..68573fbc 100755 --- a/sfdx/README.md +++ b/sfdx/README.md @@ -6,10 +6,13 @@ This repository provides configuration files and scripts that a Salesforce devel ## Getting Started -### SFDX Setup -1. Before continuing with the steps below, see [Salesforce DX Setup Guide](https://developer.salesforce.com/docs/atlas.en-us.sfdx_setup.meta/sfdx_setup/sfdx_setup_intro.htm) to setup SFDX. +### SF Setup +1. Before continuing with the steps below, see [Install SF CLI](https://developer.salesforce.com/docs/atlas.en-us.sfdx_setup.meta/sfdx_setup/sfdx_setup_install_cli.htm). -2. Additionally, please install the 1Commerce SFDX Plugin: https://github.com/forcedotcom/sfdx-1commerce-plugin + +2. Additionally, please install the _commerce-on-lightning_ SF Plugin: https://github.com/forcedotcom/commerce-on-lightning + - sf plugins install @salesforce/commerce + - sf plugins install shane-sfdx-plugins ### Quick Start @@ -38,25 +41,25 @@ From the sfdx directory, run the script: that will convert the examples from the metadata API format to the SFDX format and add them to the "path" you have specified in the sfdx-project.json file. 3. Create a scratch org using SFDX. -If you don't have a dev hub already authorized, do that now by running + If you don't have a dev hub already authorized, do that now by running ``` -sfdx force:auth:web:login -d +sf org login web -d ``` This will open a new browser window where you have to enter the credentials of your Dev Hub. The -d option will set that Dev Hub as your default one. Once you're logged in, the Dev Hub is authorized and you can close the browser. The Dev Hub will manage your future scratch orgs. Make sure that your current directory is sfdx. Run the following command to create a scratch org and specify the username for the administrator in an email format: ``` -sfdx force:org:create -f config/project-scratch-def.json username= -s -d +sf org create scratch -f config/project-scratch-def.json --username= -d -y ``` This command may take a while to run (minutes, but not more than 5-10 minutes) and you won't see output while it's running. A password for your user is auto-generated but it's hidden. To open the new org: ``` -sfdx force:org:open +sf org open ``` Note: if that fails, you might need to first set that new scratch org as your default org with ``` -sfdx force:config:set defaultusername= +sf config set defaultusername= ``` Notice that the existing settings in the ```project-scratch-def.json``` file will enable all the necessary licenses and org perms and prefs required for Lightning B2B. If the scratch org creation is successful you should not need to modify any org perms or prefs. This is only available for the scratch orgs though, and will not work for developer edition orgs, sandboxes or other environments. For those orgs, follow the [B2B Commerce on Lightning Experience Setup Guide](https://resources.docs.salesforce.com/latest/latest/en-us/sfdc/pdf/b2b_standalone_setup.pdf). @@ -73,7 +76,7 @@ You are done! #### Push Samples This is taken care of in step 4 of the Quick Start instructions above. However, if you wish to push updated samples to the new org: ``` -sfdx force:source:push -f +sf project deploy start -c ``` #### Setup Store This is also triggered by step 4 of the Quick Start instructions above. You would only need to run this step if you wanted to setup a store again. If you have a store already created (from the previous step or because you created it manually), first, make sure to adjust configuration settings such as Username and/or Email in the definition file for your Buyer User at config/buyer-user-def.json. Then run the following script to setup your store: @@ -81,18 +84,18 @@ This is also triggered by step 4 of the Quick Start instructions above. You woul ./quickstart-setup-store.sh ``` This script will: - - register the Apex classes needed for checkout integrations and map them to your store - - associate the clone of the checkout flow to the checkout component in your store - - add the Customer Community Plus Profile clone to the list of members for the store - - import Products and necessary related store data in order to get you started - - create a Buyer User and attach a Buyer Profile to it - - create a Buyer Account and add it to the relevant Buyer Group - - add Contact Point Addresses for Shipping and Billing to your new buyer Account - - activate the store - - publish your store so that the changes are reflected - - build the search index for your store - - set a password for the new Buyer User and display the user details (including user name and password) - - setup Guest Browsing by default for B2C stores +- register the Apex classes needed for checkout integrations and map them to your store +- associate the clone of the checkout flow to the checkout component in your store +- add the Customer Community Plus Profile clone to the list of members for the store +- import Products and necessary related store data in order to get you started +- create a Buyer User and attach a Buyer Profile to it +- create a Buyer Account and add it to the relevant Buyer Group +- add Contact Point Addresses for Shipping and Billing to your new buyer Account +- activate the store +- publish your store so that the changes are reflected +- build the search index for your store +- set a password for the new Buyer User and display the user details (including user name and password) +- setup Guest Browsing by default for B2C stores 7. Your new store is almost ready to go! Before you log in as the Buyer User, you need to perform these last steps manually: @@ -103,16 +106,16 @@ By default, a mocked gateway (SalesforceAdapter) integration has been set up. Y ./quickstart-setup-payments.sh ``` -For further customizations to your gateway, see the documentation [here](https://developer.salesforce.com/docs/atlas.en-us.apexcode.meta/apexcode/apex_commercepayments_adapter_intro.htm). +For further customizations to your gateway, see the documentation [here](https://developer.salesforce.com/docs/atlas.en-us.apexcode.meta/apexcode/apex_commercepayments_adapter_intro.htm). - 7.2 Enable Guest Browsing -By default, Guest Browsing has been disabled for B2B stores but enabled in B2C stores. Even if Guest Browsing is currently disabled in your store, you can enable it by running +By default, Guest Browsing has been disabled for B2B stores but enabled in B2C stores. Even if Guest Browsing is currently disabled in your store, you can enable it by running ``` ./enable-guest-browsing.sh ``` -If you have used Quick Start to setup your store, the name of your Buyer Group will be "BUYERGROUP_FROM_QUICKSTART_1". +If you have used Quick Start to setup your store, the name of your Buyer Group will be "BUYERGROUP_FROM_QUICKSTART_1". ## The `sfdx-project.json` File @@ -125,10 +128,10 @@ The `sfdcLoginUrl` specifies the default login URL to use when authorizing an or The `packageDirectories` filepath tells VS Code and Salesforce CLI where the metadata files for your project are stored. You need at least one package directory set in your file. The default setting is shown below. If you set the value of the `packageDirectories` property called `path` to `force-app`, by default your metadata goes in the `force-app` directory. If you want to change that directory to something like `src`, simply change the `path` value and make sure the directory you’re pointing to exists. ```json "packageDirectories" : [ - { - "path": "force-app", - "default": true - } +{ +"path": "force-app", +"default": true +} ] ``` ## Working with Source @@ -149,7 +152,7 @@ Once installed, you should be able actually take a cart through checkout as a bu ## Enabling Promotions and Using built in Pricing - Salesforce provides engines for Pricing and Promotions. We have provided a second main flow that includes Salesforce pricing and promotions. This flow is slightly more complicated and uses more subflows, but comes with some more functionality. Some of the integrations, Pricing and Promotions, run asynchronously which can cause delays during checkout +Salesforce provides engines for Pricing and Promotions. We have provided a second main flow that includes Salesforce pricing and promotions. This flow is slightly more complicated and uses more subflows, but comes with some more functionality. Some of the integrations, Pricing and Promotions, run asynchronously which can cause delays during checkout ## Installing the Re-entrant flow diff --git a/sfdx/convert-examples-to-sfdx.sh b/sfdx/convert-examples-to-sfdx.sh index 305877be..f408e0dd 100755 --- a/sfdx/convert-examples-to-sfdx.sh +++ b/sfdx/convert-examples-to-sfdx.sh @@ -16,17 +16,17 @@ done # Makes sure a "force-app" directory exists, as later commands depend on this directory mkdir -p force-app -sfdx force:mdapi:convert -r ../examples/checkout/payment-gateway-integration/Salesforce/ -sfdx force:mdapi:convert -r ../examples/checkout/notifications/ +sf project convert mdapi -r ../examples/checkout/payment-gateway-integration/Salesforce/ +sf project convert mdapi -r ../examples/checkout/notifications/ -sfdx force:mdapi:convert -r ../examples/users/buyer-user-profile-setup/ -sfdx force:mdapi:convert -r ../examples/users/sharing-settings-setup/ +sf project convert mdapi -r ../examples/users/buyer-user-profile-setup/ +sf project convert mdapi -r ../examples/users/sharing-settings-setup/ -sfdx force:mdapi:convert -r ../examples/diagnostic/commerce-diagnostic-event-setup/ +sf project convert mdapi -r ../examples/diagnostic/commerce-diagnostic-event-setup/ -# Contains some files that are only used for asynchronous checkouts, but others are shared for sync as well -sfdx force:mdapi:convert -r ../examples/checkout/integrations/ -sfdx force:mdapi:convert -r ../tests/integration/ +# Contains some files that are only used for asynchronous checkouts, but others are shared for sync as well +sf project convert mdapi -r ../examples/checkout/integrations/ +sf project convert mdapi -r ../tests/integration/ # Payments related changes newdir="force-app/main/default/lwc/" @@ -44,10 +44,10 @@ cp -r ../examples/lwc/force-app/main/default/lwc/navigationButtons force-app/mai if [[ "$flow" = "reentrant" ]] then # Re-entrant Checkout - sfdx force:mdapi:convert -r ../examples/checkout-reentrant + sf project convert mdapi -r ../examples/checkout-reentrant printf "\nConverted the re-entrant checkout flow.\n" else # Main Checkout - sfdx force:mdapi:convert -r ../examples/checkout-main + sf project convert mdapi -r ../examples/checkout-main printf "\nConverted the main checkout flow.\n" fi diff --git a/sfdx/quickstart-create-and-setup-store.sh b/sfdx/quickstart-create-and-setup-store.sh index fdf1bf24..0b6bb45a 100755 --- a/sfdx/quickstart-create-and-setup-store.sh +++ b/sfdx/quickstart-create-and-setup-store.sh @@ -1,12 +1,10 @@ #!/bin/bash # Use this command to create a new store. # The name of the store can be passed as a parameter. +export SF_NPM_REGISTRY="http://platform-cli-registry.eng.sfdc.net:4880/" +export SF_S3_HOST="http://platform-cli-s3.eng.sfdc.net:9000/sfdx/media/salesforce-cli" -export SFDX_NPM_REGISTRY="http://platform-cli-registry.eng.sfdc.net:4880/" -export SFDX_S3_HOST="http://platform-cli-s3.eng.sfdc.net:9000/sfdx/media/salesforce-cli" - -#templateName="b2c-lite-storefront" -templateName="B2B Commerce" +templateName="B2B Commerce (LWR)" function echo_attention() { local green='\033[0;32m' @@ -28,7 +26,9 @@ then else storename=$1 fi -sfdx force:community:create --name "$storename" --templatename "B2B Commerce" --urlpathprefix "$storename" --description "Store $storename created by Quick Start script." + +sf community create --name "$storename" --template-name "$templateName" --url-path-prefix "$storename" --description "Store $storename created by Quick Start script." + echo "" storeId="" @@ -36,7 +36,7 @@ storeId="" while [ -z "${storeId}" ]; do echo_attention "Store not yet created, waiting 10 seconds..." - storeId=$(sfdx force:data:soql:query -q "SELECT Id FROM WebStore WHERE Name='${storename}' LIMIT 1" -r csv |tail -n +2) + storeId=$(sf data query -q "SELECT Id FROM WebStore WHERE Name='${storename}' LIMIT 1" -r csv |tail -n +2) sleep 10 done @@ -47,7 +47,7 @@ echo "" echo_attention "Pushing store sources..." set -x -sfdx force:source:push -f +sf project deploy start -c set +x echo "" From c2c0cebe4fc66c8d89b23bc7948de656ea8a5488 Mon Sep 17 00:00:00 2001 From: Oleksii Golub Date: Wed, 3 Jan 2024 17:01:29 +0200 Subject: [PATCH 4/4] fix metadata NamedCredential --- .../Salesforce/namedCredentials/Salesforce.namedCredential | 1 + 1 file changed, 1 insertion(+) diff --git a/examples/checkout/payment-gateway-integration/Salesforce/namedCredentials/Salesforce.namedCredential b/examples/checkout/payment-gateway-integration/Salesforce/namedCredentials/Salesforce.namedCredential index 4c364973..3b7a1967 100644 --- a/examples/checkout/payment-gateway-integration/Salesforce/namedCredentials/Salesforce.namedCredential +++ b/examples/checkout/payment-gateway-integration/Salesforce/namedCredentials/Salesforce.namedCredential @@ -8,4 +8,5 @@ NamedUser Password UserName + Password