diff --git a/.oxlintrc.json b/.oxlintrc.json index 8bdeecf3..7b935ea7 100755 --- a/.oxlintrc.json +++ b/.oxlintrc.json @@ -29,16 +29,22 @@ "no-async-await": "off", "no-console": "off", "no-magic-numbers": "warn", + "no-map-spread": "off", + "no-misused-promises": "off", + "no-optional-chaining": "off", "no-rest-spread-properties": "off", "no-ternary": "off", + "no-undefined": "off", + "no-unused-expressions": "off", + "no-void": "off", + "prefer-await-to-then": "off", + "promise/prefer-await-to-callbacks": "off", "sort-imports": "off", "typescript/array-type": ["error", { "default": "generic", "readonly": "generic" }], + "typescript/consistent-indexed-object-style": ["error", "record"], "typescript/consistent-type-imports": "error", - "prefer-await-to-then": "off", - "no-void": "off", - "no-optional-chaining": "off", - "no-unused-expressions": "off", - "no-misused-promises": "off", + "typescript/explicit-function-return-type": "warn", + "unicorn/prefer-dom-node-dataset": "off", "yoda": ["error", "never"] } } diff --git a/STUFF.md b/STUFF.md new file mode 100644 index 00000000..81ce1ee5 --- /dev/null +++ b/STUFF.md @@ -0,0 +1,79 @@ +I'll see you soup + +- Thèmes + - LS_COLORS (Vivid ?) + - bat + - eza (?) + - fdfind + - fish + - gitui + - helix + - wezterm + - yazi + - zed + - zellij + +Google API +AIzaSyDGe62r-bDxvNuDCP6HIfWIJAMvelFxU1s +402628219773-hl8niqniiiklf15f9biou8g06pbm9sac.apps.googleusercontent.com +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 + +- Code promo ? +- La commande peut être associée au panier. + - Vu que l'on passe par l'API REST, le panier est dissocié de la commande. + - Il est possible de fixer le hash du panier dans la commande avec la fonction set_cart_hash de WC_Order. + - Cela permet par la suite d'utiliser la fonction cancel_order WC_Order à l'annulation de cette dernière lors du retour au Panier depuis Stripe. + - Ce ne sera possible qu'en utilisant un endpoint personnalisé réalisant ces opérations plutôt que l'API REST. + - Dans l'idéal, +- Ajouter un bouton "Reset cart" quelque part pour tout réinitialiser (et appeler cancel_order si implémenté) + +--- + +- BadRequestError + - reponse.status === 400 + - reponse.body = { + code: string, + message: string (différenciation sur le message ?), + data: { + status: number (400), + } + } + +--- + +Stripe +pk_live_51D0BbTIKBol0AhpghF9b6lJ4ZjPXWaNRzBgxtcUTdbV8OC2OpHxSbkMoEEgCHEPSs6E6NISfdMv92t9OnKqKh0sH00N6tgi6HW +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 + +--- + +- Chargement de la page + - Récupération des informations à la génération de la page + - Panier + - Code promo + - Mode de livraison + - Sous-totaux + - Total + - Adresses + - Récupération des informations dans le LocalStorage + - Code promo + - Mode de livraison + - Adresses + + - À l'injection de données du LocalStorage + - Mettre à jour les sous-totaux + + - À l'appui sur le bouton de calcul de la livraison et au succès de la requête + - Mettre à jour les méthodes de livraison + - Mettre à jour les sous-totaux et le total + - Sauvegarder les nouvelles données dans le LocalStorage + +- Événements à créer + - MiseAJourCodePromo + - Se déclenche quand le champ du Code promo est modifié + - MiseAJourProduits + - Se déclenche quand une des lignes du Panier est modifiée (addition/soustraction/suppression) + - MiseAJourMethodeLivraison + - Se déclence quand le choix de la Méthode de livraison est modifié + - MiseAJourAdresses + - Se déclenche quand un des champs du formulaire des adresses est modifié diff --git a/composer.lock b/composer.lock index d68eedf3..9283e425 100755 --- a/composer.lock +++ b/composer.lock @@ -646,16 +646,16 @@ }, { "name": "illuminate/collections", - "version": "v11.36.1", + "version": "v11.37.0", "source": { "type": "git", "url": "https://github.com/illuminate/collections.git", - "reference": "21868f9ac221a42d4346dc56495d11ab7e0d339a" + "reference": "9100b083eeb85d38d78fc1de28f7326596ab2eda" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/illuminate/collections/zipball/21868f9ac221a42d4346dc56495d11ab7e0d339a", - "reference": "21868f9ac221a42d4346dc56495d11ab7e0d339a", + "url": "https://api.github.com/repos/illuminate/collections/zipball/9100b083eeb85d38d78fc1de28f7326596ab2eda", + "reference": "9100b083eeb85d38d78fc1de28f7326596ab2eda", "shasum": "" }, "require": { @@ -698,11 +698,11 @@ "issues": "https://github.com/laravel/framework/issues", "source": "https://github.com/laravel/framework" }, - "time": "2024-12-13T13:58:10+00:00" + "time": "2024-12-18T14:14:45+00:00" }, { "name": "illuminate/conditionable", - "version": "v11.36.1", + "version": "v11.37.0", "source": { "type": "git", "url": "https://github.com/illuminate/conditionable.git", @@ -748,7 +748,7 @@ }, { "name": "illuminate/contracts", - "version": "v11.36.1", + "version": "v11.37.0", "source": { "type": "git", "url": "https://github.com/illuminate/contracts.git", @@ -796,7 +796,7 @@ }, { "name": "illuminate/macroable", - "version": "v11.36.1", + "version": "v11.37.0", "source": { "type": "git", "url": "https://github.com/illuminate/macroable.git", @@ -842,16 +842,16 @@ }, { "name": "illuminate/support", - "version": "v11.36.1", + "version": "v11.37.0", "source": { "type": "git", "url": "https://github.com/illuminate/support.git", - "reference": "fba1ff58e30fa280248ce3db9b18d6341c6ac339" + "reference": "388c916b143a104e732cbaf7e6b19cd7a4e21a1e" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/illuminate/support/zipball/fba1ff58e30fa280248ce3db9b18d6341c6ac339", - "reference": "fba1ff58e30fa280248ce3db9b18d6341c6ac339", + "url": "https://api.github.com/repos/illuminate/support/zipball/388c916b143a104e732cbaf7e6b19cd7a4e21a1e", + "reference": "388c916b143a104e732cbaf7e6b19cd7a4e21a1e", "shasum": "" }, "require": { @@ -875,7 +875,7 @@ }, "suggest": { "illuminate/filesystem": "Required to use the Composer class (^11.0).", - "laravel/serializable-closure": "Required to use the once function (^1.3).", + "laravel/serializable-closure": "Required to use the once function (^1.3|^2.0).", "league/commonmark": "Required to use Str::markdown() and Stringable::markdown() (^2.6).", "league/uri": "Required to use the Uri class (^7.5.1).", "ramsey/uuid": "Required to use Str::uuid() (^4.7).", @@ -915,7 +915,7 @@ "issues": "https://github.com/laravel/framework/issues", "source": "https://github.com/laravel/framework" }, - "time": "2024-12-17T20:20:09+00:00" + "time": "2024-12-20T14:43:22+00:00" }, { "name": "laravel/helpers", @@ -1223,16 +1223,16 @@ }, { "name": "nesbot/carbon", - "version": "3.8.3", + "version": "3.8.4", "source": { "type": "git", - "url": "https://github.com/briannesbitt/Carbon.git", - "reference": "f01cfa96468f4c38325f507ab81a4f1d2cd93cfe" + "url": "https://github.com/CarbonPHP/carbon.git", + "reference": "129700ed449b1f02d70272d2ac802357c8c30c58" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/briannesbitt/Carbon/zipball/f01cfa96468f4c38325f507ab81a4f1d2cd93cfe", - "reference": "f01cfa96468f4c38325f507ab81a4f1d2cd93cfe", + "url": "https://api.github.com/repos/CarbonPHP/carbon/zipball/129700ed449b1f02d70272d2ac802357c8c30c58", + "reference": "129700ed449b1f02d70272d2ac802357c8c30c58", "shasum": "" }, "require": { @@ -1325,7 +1325,7 @@ "type": "tidelift" } ], - "time": "2024-12-21T18:03:19+00:00" + "time": "2024-12-27T09:25:35+00:00" }, { "name": "oscarotero/env", @@ -2381,12 +2381,12 @@ }, "type": "library", "extra": { + "thanks": { + "url": "https://github.com/symfony/contracts", + "name": "symfony/contracts" + }, "branch-alias": { "dev-main": "3.5-dev" - }, - "thanks": { - "name": "symfony/contracts", - "url": "https://github.com/symfony/contracts" } }, "autoload": { @@ -2901,16 +2901,16 @@ }, { "name": "symfony/translation", - "version": "v7.2.0", + "version": "v7.2.2", "source": { "type": "git", "url": "https://github.com/symfony/translation.git", - "reference": "dc89e16b44048ceecc879054e5b7f38326ab6cc5" + "reference": "e2674a30132b7cc4d74540d6c2573aa363f05923" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/translation/zipball/dc89e16b44048ceecc879054e5b7f38326ab6cc5", - "reference": "dc89e16b44048ceecc879054e5b7f38326ab6cc5", + "url": "https://api.github.com/repos/symfony/translation/zipball/e2674a30132b7cc4d74540d6c2573aa363f05923", + "reference": "e2674a30132b7cc4d74540d6c2573aa363f05923", "shasum": "" }, "require": { @@ -2976,7 +2976,7 @@ "description": "Provides tools to internationalize your application", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/translation/tree/v7.2.0" + "source": "https://github.com/symfony/translation/tree/v7.2.2" }, "funding": [ { @@ -2992,7 +2992,7 @@ "type": "tidelift" } ], - "time": "2024-11-12T20:47:56+00:00" + "time": "2024-12-07T08:18:10+00:00" }, { "name": "symfony/translation-contracts", @@ -3013,12 +3013,12 @@ }, "type": "library", "extra": { + "thanks": { + "url": "https://github.com/symfony/contracts", + "name": "symfony/contracts" + }, "branch-alias": { "dev-main": "3.5-dev" - }, - "thanks": { - "name": "symfony/contracts", - "url": "https://github.com/symfony/contracts" } }, "autoload": { @@ -3148,21 +3148,21 @@ }, { "name": "timber/timber", - "version": "v2.3.0", + "version": "v2.3.1", "source": { "type": "git", "url": "https://github.com/timber/timber.git", - "reference": "55acea4414eac6ea9d0a11a102af37cf13f219b2" + "reference": "3f6e73feadf5d547dff4992f645805da7fbc4d3a" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/timber/timber/zipball/55acea4414eac6ea9d0a11a102af37cf13f219b2", - "reference": "55acea4414eac6ea9d0a11a102af37cf13f219b2", + "url": "https://api.github.com/repos/timber/timber/zipball/3f6e73feadf5d547dff4992f645805da7fbc4d3a", + "reference": "3f6e73feadf5d547dff4992f645805da7fbc4d3a", "shasum": "" }, "require": { "php": "^8.1", - "twig/twig": "^3.5" + "twig/twig": "^3.17" }, "require-dev": { "ergebnis/composer-normalize": "^2.28", @@ -3177,7 +3177,7 @@ "squizlabs/php_codesniffer": "^3.0", "symplify/easy-coding-standard": "^12.2", "szepeviktor/phpstan-wordpress": "^1.1", - "twig/cache-extra": "^3.3", + "twig/cache-extra": "^3.17", "wpackagist-plugin/advanced-custom-fields": "^6.0", "wpackagist-plugin/co-authors-plus": "^3.6", "yoast/wp-test-utils": "^1.2" @@ -3246,20 +3246,20 @@ "type": "open_collective" } ], - "time": "2024-11-08T09:38:16+00:00" + "time": "2024-12-23T13:04:50+00:00" }, { "name": "twig/twig", - "version": "v3.17.1", + "version": "v3.18.0", "source": { "type": "git", "url": "https://github.com/twigphp/Twig.git", - "reference": "677ef8da6497a03048192aeeb5aa3018e379ac71" + "reference": "acffa88cc2b40dbe42eaf3a5025d6c0d4600cc50" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/twigphp/Twig/zipball/677ef8da6497a03048192aeeb5aa3018e379ac71", - "reference": "677ef8da6497a03048192aeeb5aa3018e379ac71", + "url": "https://api.github.com/repos/twigphp/Twig/zipball/acffa88cc2b40dbe42eaf3a5025d6c0d4600cc50", + "reference": "acffa88cc2b40dbe42eaf3a5025d6c0d4600cc50", "shasum": "" }, "require": { @@ -3314,7 +3314,7 @@ ], "support": { "issues": "https://github.com/twigphp/Twig/issues", - "source": "https://github.com/twigphp/Twig/tree/v3.17.1" + "source": "https://github.com/twigphp/Twig/tree/v3.18.0" }, "funding": [ { @@ -3326,7 +3326,7 @@ "type": "tidelift" } ], - "time": "2024-12-12T09:58:10+00:00" + "time": "2024-12-29T10:51:50+00:00" }, { "name": "vlucas/phpdotenv", @@ -3596,15 +3596,15 @@ }, { "name": "wpackagist-plugin/woocommerce", - "version": "9.5.1", + "version": "9.5.2", "source": { "type": "svn", "url": "https://plugins.svn.wordpress.org/woocommerce/", - "reference": "tags/9.5.1" + "reference": "tags/9.5.2" }, "dist": { "type": "zip", - "url": "https://downloads.wordpress.org/plugin/woocommerce.9.5.1.zip" + "url": "https://downloads.wordpress.org/plugin/woocommerce.9.5.2.zip" }, "require": { "composer/installers": "^1.0 || ^2.0" @@ -3614,15 +3614,15 @@ }, { "name": "wpackagist-plugin/wp-mail-logging", - "version": "1.13.1", + "version": "1.14.0", "source": { "type": "svn", "url": "https://plugins.svn.wordpress.org/wp-mail-logging/", - "reference": "tags/1.13.1" + "reference": "tags/1.14.0" }, "dist": { "type": "zip", - "url": "https://downloads.wordpress.org/plugin/wp-mail-logging.1.13.1.zip" + "url": "https://downloads.wordpress.org/plugin/wp-mail-logging.1.14.0.zip" }, "require": { "composer/installers": "^1.0 || ^2.0" @@ -3650,15 +3650,15 @@ }, { "name": "wpackagist-plugin/wp-openapi", - "version": "1.0.17", + "version": "1.0.18", "source": { "type": "svn", "url": "https://plugins.svn.wordpress.org/wp-openapi/", - "reference": "tags/1.0.17" + "reference": "tags/1.0.18" }, "dist": { "type": "zip", - "url": "https://downloads.wordpress.org/plugin/wp-openapi.1.0.17.zip" + "url": "https://downloads.wordpress.org/plugin/wp-openapi.1.0.18.zip" }, "require": { "composer/installers": "^1.0 || ^2.0" @@ -3784,16 +3784,16 @@ }, { "name": "phpstan/phpstan", - "version": "2.0.4", + "version": "2.1.1", "source": { "type": "git", "url": "https://github.com/phpstan/phpstan.git", - "reference": "50d276fc3bf1430ec315f2f109bbde2769821524" + "reference": "cd6e973e04b4c2b94c86e8612b5a65f0da0e08e7" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/phpstan/phpstan/zipball/50d276fc3bf1430ec315f2f109bbde2769821524", - "reference": "50d276fc3bf1430ec315f2f109bbde2769821524", + "url": "https://api.github.com/repos/phpstan/phpstan/zipball/cd6e973e04b4c2b94c86e8612b5a65f0da0e08e7", + "reference": "cd6e973e04b4c2b94c86e8612b5a65f0da0e08e7", "shasum": "" }, "require": { @@ -3838,7 +3838,7 @@ "type": "github" } ], - "time": "2024-12-17T17:14:01+00:00" + "time": "2025-01-05T16:43:48+00:00" }, { "name": "roave/security-advisories", @@ -3846,12 +3846,12 @@ "source": { "type": "git", "url": "https://github.com/Roave/SecurityAdvisories.git", - "reference": "abbccc97f36a9c78f033525c019d310433f22b57" + "reference": "19bf84017a308ac32893551b899bac74d2aba856" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/Roave/SecurityAdvisories/zipball/abbccc97f36a9c78f033525c019d310433f22b57", - "reference": "abbccc97f36a9c78f033525c019d310433f22b57", + "url": "https://api.github.com/repos/Roave/SecurityAdvisories/zipball/19bf84017a308ac32893551b899bac74d2aba856", + "reference": "19bf84017a308ac32893551b899bac74d2aba856", "shasum": "" }, "conflict": { @@ -3973,7 +3973,7 @@ "datatables/datatables": "<1.10.10", "david-garcia/phpwhois": "<=4.3.1", "dbrisinajumi/d2files": "<1", - "dcat/laravel-admin": "<=2.1.3", + "dcat/laravel-admin": "<=2.1.3|==2.2.0.0-beta|==2.2.2.0-beta", "derhansen/fe_change_pwd": "<2.0.5|>=3,<3.0.3", "derhansen/sf_event_mgt": "<4.3.1|>=5,<5.1.1|>=7,<7.4", "desperado/xml-bundle": "<=0.1.7", @@ -4095,6 +4095,7 @@ "grumpydictator/firefly-iii": "<6.1.17", "gugoan/economizzer": "<=0.9.0.0-beta1", "guzzlehttp/guzzle": "<6.5.8|>=7,<7.4.5", + "guzzlehttp/oauth-subscriber": "<0.8.1", "guzzlehttp/psr7": "<1.9.1|>=2,<2.4.5", "haffner/jh_captcha": "<=2.1.3|>=3,<=3.0.2", "harvesthq/chosen": "<1.8.7", @@ -4140,7 +4141,7 @@ "james-heinrich/phpthumb": "<1.7.12", "jasig/phpcas": "<1.3.3", "jcbrand/converse.js": "<3.3.3", - "joelbutcher/socialstream": "<6.2", + "joelbutcher/socialstream": "<5.6|>=6,<6.2", "johnbillion/wp-crontrol": "<1.16.2", "joomla/application": "<1.0.13", "joomla/archive": "<1.1.12|>=2,<2.0.1", @@ -4255,10 +4256,11 @@ "neos/media-browser": "<7.3.19|>=8,<8.0.16|>=8.1,<8.1.11|>=8.2,<8.2.11|>=8.3,<8.3.9", "neos/neos": ">=1.1,<1.1.3|>=1.2,<1.2.13|>=2,<2.0.4|>=2.3,<3.0.20|>=3.1,<3.1.18|>=3.2,<3.2.14|>=3.3,<5.3.10|>=7,<7.0.9|>=7.1,<7.1.7|>=7.2,<7.2.6|>=7.3,<7.3.4|>=8,<8.0.2", "neos/swiftmailer": "<5.4.5", + "netcarver/textile": "<=4.1.2", "netgen/tagsbundle": ">=3.4,<3.4.11|>=4,<4.0.15", "nette/application": ">=2,<2.0.19|>=2.1,<2.1.13|>=2.2,<2.2.10|>=2.3,<2.3.14|>=2.4,<2.4.16|>=3,<3.0.6", "nette/nette": ">=2,<2.0.19|>=2.1,<2.1.13", - "nilsteampassnet/teampass": "<3.0.10", + "nilsteampassnet/teampass": "<3.1.3.1-dev", "nonfiction/nterchange": "<4.1.1", "notrinos/notrinos-erp": "<=0.7", "noumo/easyii": "<=0.9", @@ -4319,10 +4321,10 @@ "phpmailer/phpmailer": "<6.5", "phpmussel/phpmussel": ">=1,<1.6", "phpmyadmin/phpmyadmin": "<5.2.1", - "phpmyfaq/phpmyfaq": "<3.2.5|==3.2.5", + "phpmyfaq/phpmyfaq": "<3.2.5|==3.2.5|>=3.2.10,<=4.0.1", "phpoffice/common": "<0.2.9", "phpoffice/phpexcel": "<1.8.1", - "phpoffice/phpspreadsheet": "<1.29.4|>=2,<2.1.3|>=2.2,<2.3.2|>=3.3,<3.4", + "phpoffice/phpspreadsheet": "<=1.29.6|>=2,<=2.1.5|>=2.2,<=2.3.4|>=3,<3.7", "phpseclib/phpseclib": "<2.0.47|>=3,<3.0.36", "phpservermon/phpservermon": "<3.6", "phpsysinfo/phpsysinfo": "<3.4.3", @@ -4401,7 +4403,7 @@ "shopware/storefront": "<=6.4.8.1|>=6.5.8,<6.5.8.7-dev", "shopxo/shopxo": "<=6.1", "showdoc/showdoc": "<2.10.4", - "shuchkin/simplexlsx": ">=1.0.12,<1.1.12", + "shuchkin/simplexlsx": ">=1.0.12,<1.1.13", "silverstripe-australia/advancedreports": ">=1,<=2", "silverstripe/admin": "<1.13.19|>=2,<2.1.8", "silverstripe/assets": ">=1,<1.11.1", @@ -4448,6 +4450,7 @@ "squizlabs/php_codesniffer": ">=1,<2.8.1|>=3,<3.0.1", "ssddanbrown/bookstack": "<24.05.1", "starcitizentools/citizen-skin": ">=2.6.3,<2.31", + "starcitizentools/tabber-neue": ">=1.9.1,<2.7.2", "statamic/cms": "<=5.16", "stormpath/sdk": "<9.9.99", "studio-42/elfinder": "<=2.1.64", @@ -4512,18 +4515,20 @@ "t3s/content-consent": "<1.0.3|>=2,<2.0.2", "tastyigniter/tastyigniter": "<3.3", "tcg/voyager": "<=1.4", - "tecnickcom/tcpdf": "<=6.7.5", + "tecnickcom/tc-lib-pdf-font": "<2.6.4", + "tecnickcom/tcpdf": "<6.8", "terminal42/contao-tablelookupwizard": "<3.3.5", "thelia/backoffice-default-template": ">=2.1,<2.1.2", "thelia/thelia": ">=2.1,<2.1.3", "theonedemon/phpwhois": "<=4.2.5", "thinkcmf/thinkcmf": "<6.0.8", - "thorsten/phpmyfaq": "<4", + "thorsten/phpmyfaq": "<=4.0.1", "tikiwiki/tiki-manager": "<=17.1", "timber/timber": ">=0.16.6,<1.23.1|>=1.24,<1.24.1|>=2,<2.1", "tinymce/tinymce": "<7.2", "tinymighty/wiki-seo": "<1.2.2", "titon/framework": "<9.9.99", + "tltneon/lgsl": "<7", "tobiasbg/tablepress": "<=2.0.0.0-RC1", "topthink/framework": "<6.0.17|>=6.1,<=8.0.4", "topthink/think": "<=6.1.1", @@ -4601,7 +4606,7 @@ "xpressengine/xpressengine": "<3.0.15", "yab/quarx": "<2.4.5", "yeswiki/yeswiki": "<=4.4.4", - "yetiforce/yetiforce-crm": "<=6.4", + "yetiforce/yetiforce-crm": "<6.5", "yidashi/yii2cmf": "<=2", "yii2mod/yii2-cms": "<1.9.2", "yiisoft/yii": "<1.1.29", @@ -4691,7 +4696,7 @@ "type": "tidelift" } ], - "time": "2024-12-20T16:05:39+00:00" + "time": "2025-01-07T18:06:22+00:00" }, { "name": "squizlabs/php_codesniffer", diff --git a/dprint.json b/dprint.json index d2c3ef7e..2d0a3e2b 100755 --- a/dprint.json +++ b/dprint.json @@ -79,7 +79,7 @@ "https://plugins.dprint.dev/typescript-0.93.3.wasm", "https://plugins.dprint.dev/json-0.19.4.wasm", "https://plugins.dprint.dev/markdown-0.17.8.wasm", - "https://plugins.dprint.dev/toml-0.6.3.wasm", + "https://plugins.dprint.dev/toml-0.6.4.wasm", "https://plugins.dprint.dev/g-plane/malva-v0.11.1.wasm", "https://plugins.dprint.dev/g-plane/markup_fmt-v0.18.0.wasm", "https://plugins.dprint.dev/g-plane/pretty_yaml-v0.5.0.wasm", diff --git a/package.json b/package.json index dd9b735b..0dcf9ad3 100755 --- a/package.json +++ b/package.json @@ -8,57 +8,57 @@ "packageManager": "pnpm@9.14.4", "main": "index.js", "keywords": [], - "scripts": { - "knip": "knip", - "test": "echo \"Error: no test specified\" && exit 1" - }, + "scripts": { "knip": "knip", "test": "echo \"Error: no test specified\" && exit 1" }, "dependencies": { "@mobily/ts-belt": "4.0.0-rc.5", - "@sentry/browser": "8.47.0", + "@sentry/browser": "8.48.0", "@swan-io/boxed": "^3.2.0", "a11y-dialog": "^8.1.1", + "chalk": "^5.4.1", "lit-html": "^3.2.1", + "loglevel": "^1.9.2", + "loglevel-plugin-prefix": "^0.8.4", "optics-ts": "^2.4.1", "purify-ts": "^2.1.0", "ts-pattern": "^5.6.0", - "valibot": "1.0.0-beta.9" + "valibot": "1.0.0-beta.11" }, "devDependencies": { "@biomejs/biome": "^1.9.4", "@eslint/js": "^9.17.0", "@prettier/plugin-php": "^0.22.2", "@prettier/plugin-xml": "^3.4.1", - "@sentry/core": "^8.47.0", + "@sentry/core": "^8.48.0", "@swc/cli": "0.5.2", "@types/eslint__js": "^8.42.3", - "@types/node": "^22.10.2", + "@types/node": "^22.10.5", "@vitejs/plugin-legacy": "^6.0.0", "better-typescript-lib": "^2.10.0", - "browserslist": "^4.24.3", + "browserslist": "^4.24.4", "eslint": "^9.17.0", - "eslint-plugin-oxlint": "^0.15.2", - "eslint-plugin-perfectionist": "^4.4.0", + "eslint-plugin-oxlint": "^0.15.5", + "eslint-plugin-perfectionist": "^4.6.0", "fdir": "^6.4.2", "globals": "^15.14.0", "knip": "^5.41.1", - "oxlint": "^0.15.3", + "oxlint": "^0.15.5", "picomatch": "^4.0.2", "prettier": "^3.4.2", "prettier-plugin-pkg": "^0.18.1", "prettier-plugin-sh": "^0.14.0", - "sass-embedded": "^1.83.0", + "sass-embedded": "^1.83.1", "stylelint": "^16.12.0", - "stylelint-config-clean-order": "^6.1.0", + "stylelint-config-clean-order": "^7.0.0", "stylelint-config-sass-guidelines": "^12.1.0", "stylelint-config-standard-scss": "^14.0.0", "stylelint-declaration-block-no-ignored-properties": "^2.8.0", "stylelint-plugin-logical-css": "^1.2.1", "typescript": "5.8.0-dev.20241122", - "typescript-eslint": "^8.18.1", - "vite": "^6.0.5", + "typescript-eslint": "^8.19.1", + "vite": "^6.0.7", "vite-plugin-manifest-sri": "^0.2.0", "vite-plugin-node-polyfills": "^0.22.0", - "vite-plugin-valibot-env": "^0.9.2", + "vite-plugin-valibot-env": "^0.9.3", "vite-tsconfig-paths": "^5.1.4", "wp-types": "^4.67.0" }, @@ -72,15 +72,8 @@ "ios >0 and last 3 years" ], "knip": { - "entry": [ - "web/app/themes/haiku-atelier-2024/src/scripts/*.ts" - ], - "project": [ - "web/app/themes/haiku-atelier-2024/src/scripts/**/*.{js,ts,d.ts}" - ] + "entry": ["web/app/themes/haiku-atelier-2024/src/scripts/*.ts"], + "project": ["web/app/themes/haiku-atelier-2024/src/scripts/**/*.{js,ts,d.ts}"] }, - "trustedDependencies": [ - "@biomejs/biome", - "@parcel/watcher" - ] + "trustedDependencies": ["@biomejs/biome", "@parcel/watcher"] } diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index ea01c22c..0909418d 100755 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -12,17 +12,26 @@ importers: specifier: 4.0.0-rc.5 version: 4.0.0-rc.5 '@sentry/browser': - specifier: 8.47.0 - version: 8.47.0 + specifier: 8.48.0 + version: 8.48.0 '@swan-io/boxed': specifier: ^3.2.0 version: 3.2.0(typescript@5.8.0-dev.20241122) a11y-dialog: specifier: ^8.1.1 version: 8.1.1 + chalk: + specifier: ^5.4.1 + version: 5.4.1 lit-html: specifier: ^3.2.1 version: 3.2.1 + loglevel: + specifier: ^1.9.2 + version: 1.9.2 + loglevel-plugin-prefix: + specifier: ^0.8.4 + version: 0.8.4 optics-ts: specifier: ^2.4.1 version: 2.4.1 @@ -33,8 +42,8 @@ importers: specifier: ^5.6.0 version: 5.6.0 valibot: - specifier: 1.0.0-beta.9 - version: 1.0.0-beta.9(typescript@5.8.0-dev.20241122) + specifier: 1.0.0-beta.11 + version: 1.0.0-beta.11(typescript@5.8.0-dev.20241122) devDependencies: '@biomejs/biome': specifier: ^1.9.4 @@ -49,8 +58,8 @@ importers: specifier: ^3.4.1 version: 3.4.1(prettier@3.4.2) '@sentry/core': - specifier: ^8.47.0 - version: 8.47.0 + specifier: ^8.48.0 + version: 8.48.0 '@swc/cli': specifier: 0.5.2 version: 0.5.2(@swc/core@1.9.1) @@ -58,26 +67,26 @@ importers: specifier: ^8.42.3 version: 8.42.3 '@types/node': - specifier: ^22.10.2 - version: 22.10.2 + specifier: ^22.10.5 + version: 22.10.5 '@vitejs/plugin-legacy': specifier: ^6.0.0 - version: 6.0.0(terser@5.36.0)(vite@6.0.5(@types/node@22.10.2)(jiti@2.4.2)(sass-embedded@1.83.0)(sass@1.80.6)(terser@5.36.0)) + version: 6.0.0(terser@5.36.0)(vite@6.0.7(@types/node@22.10.5)(jiti@2.4.2)(sass-embedded@1.83.1)(sass@1.80.6)(terser@5.36.0)) better-typescript-lib: specifier: ^2.10.0 version: 2.10.0(typescript@5.8.0-dev.20241122) browserslist: - specifier: ^4.24.3 - version: 4.24.3 + specifier: ^4.24.4 + version: 4.24.4 eslint: specifier: ^9.17.0 version: 9.17.0(jiti@2.4.2) eslint-plugin-oxlint: - specifier: ^0.15.2 - version: 0.15.2 + specifier: ^0.15.5 + version: 0.15.5 eslint-plugin-perfectionist: - specifier: ^4.4.0 - version: 4.4.0(eslint@9.17.0(jiti@2.4.2))(typescript@5.8.0-dev.20241122) + specifier: ^4.6.0 + version: 4.6.0(eslint@9.17.0(jiti@2.4.2))(typescript@5.8.0-dev.20241122) fdir: specifier: ^6.4.2 version: 6.4.2(picomatch@4.0.2) @@ -86,10 +95,10 @@ importers: version: 15.14.0 knip: specifier: ^5.41.1 - version: 5.41.1(@types/node@22.10.2)(typescript@5.8.0-dev.20241122) + version: 5.41.1(@types/node@22.10.5)(typescript@5.8.0-dev.20241122) oxlint: - specifier: ^0.15.3 - version: 0.15.3 + specifier: ^0.15.5 + version: 0.15.5 picomatch: specifier: ^4.0.2 version: 4.0.2 @@ -103,14 +112,14 @@ importers: specifier: ^0.14.0 version: 0.14.0(prettier@3.4.2) sass-embedded: - specifier: ^1.83.0 - version: 1.83.0 + specifier: ^1.83.1 + version: 1.83.1 stylelint: specifier: ^16.12.0 version: 16.12.0(typescript@5.8.0-dev.20241122) stylelint-config-clean-order: - specifier: ^6.1.0 - version: 6.1.0(stylelint@16.12.0(typescript@5.8.0-dev.20241122)) + specifier: ^7.0.0 + version: 7.0.0(stylelint@16.12.0(typescript@5.8.0-dev.20241122)) stylelint-config-sass-guidelines: specifier: ^12.1.0 version: 12.1.0(postcss@8.4.49)(stylelint@16.12.0(typescript@5.8.0-dev.20241122)) @@ -127,23 +136,23 @@ importers: specifier: 5.8.0-dev.20241122 version: 5.8.0-dev.20241122 typescript-eslint: - specifier: ^8.18.1 - version: 8.18.1(eslint@9.17.0(jiti@2.4.2))(typescript@5.8.0-dev.20241122) + specifier: ^8.19.1 + version: 8.19.1(eslint@9.17.0(jiti@2.4.2))(typescript@5.8.0-dev.20241122) vite: - specifier: ^6.0.5 - version: 6.0.5(@types/node@22.10.2)(jiti@2.4.2)(sass-embedded@1.83.0)(sass@1.80.6)(terser@5.36.0) + specifier: ^6.0.7 + version: 6.0.7(@types/node@22.10.5)(jiti@2.4.2)(sass-embedded@1.83.1)(sass@1.80.6)(terser@5.36.0) vite-plugin-manifest-sri: specifier: ^0.2.0 version: 0.2.0 vite-plugin-node-polyfills: specifier: ^0.22.0 - version: 0.22.0(rollup@4.29.1)(vite@6.0.5(@types/node@22.10.2)(jiti@2.4.2)(sass-embedded@1.83.0)(sass@1.80.6)(terser@5.36.0)) + version: 0.22.0(rollup@4.30.1)(vite@6.0.7(@types/node@22.10.5)(jiti@2.4.2)(sass-embedded@1.83.1)(sass@1.80.6)(terser@5.36.0)) vite-plugin-valibot-env: - specifier: ^0.9.2 - version: 0.9.2(valibot@1.0.0-beta.9(typescript@5.8.0-dev.20241122))(vite@6.0.5(@types/node@22.10.2)(jiti@2.4.2)(sass-embedded@1.83.0)(sass@1.80.6)(terser@5.36.0)) + specifier: ^0.9.3 + version: 0.9.3(valibot@1.0.0-beta.11(typescript@5.8.0-dev.20241122))(vite@6.0.7(@types/node@22.10.5)(jiti@2.4.2)(sass-embedded@1.83.1)(sass@1.80.6)(terser@5.36.0)) vite-tsconfig-paths: specifier: ^5.1.4 - version: 5.1.4(typescript@5.8.0-dev.20241122)(vite@6.0.5(@types/node@22.10.2)(jiti@2.4.2)(sass-embedded@1.83.0)(sass@1.80.6)(terser@5.36.0)) + version: 5.1.4(typescript@5.8.0-dev.20241122)(vite@6.0.7(@types/node@22.10.5)(jiti@2.4.2)(sass-embedded@1.83.1)(sass@1.80.6)(terser@5.36.0)) wp-types: specifier: ^4.67.0 version: 4.67.0 @@ -813,146 +822,152 @@ packages: '@dual-bundle/import-meta-resolve@4.1.0': resolution: {integrity: sha512-+nxncfwHM5SgAtrVzgpzJOI1ol0PkumhVo469KCf9lUi21IGcY90G98VuHm9VRrUypmAzawAHO9bs6hqeADaVg==} - '@esbuild/aix-ppc64@0.24.0': - resolution: {integrity: sha512-WtKdFM7ls47zkKHFVzMz8opM7LkcsIp9amDUBIAWirg70RM71WRSjdILPsY5Uv1D42ZpUfaPILDlfactHgsRkw==} + '@esbuild/aix-ppc64@0.24.2': + resolution: {integrity: sha512-thpVCb/rhxE/BnMLQ7GReQLLN8q9qbHmI55F4489/ByVg2aQaQ6kbcLb6FHkocZzQhxc4gx0sCk0tJkKBFzDhA==} engines: {node: '>=18'} cpu: [ppc64] os: [aix] - '@esbuild/android-arm64@0.24.0': - resolution: {integrity: sha512-Vsm497xFM7tTIPYK9bNTYJyF/lsP590Qc1WxJdlB6ljCbdZKU9SY8i7+Iin4kyhV/KV5J2rOKsBQbB77Ab7L/w==} + '@esbuild/android-arm64@0.24.2': + resolution: {integrity: sha512-cNLgeqCqV8WxfcTIOeL4OAtSmL8JjcN6m09XIgro1Wi7cF4t/THaWEa7eL5CMoMBdjoHOTh/vwTO/o2TRXIyzg==} engines: {node: '>=18'} cpu: [arm64] os: [android] - '@esbuild/android-arm@0.24.0': - resolution: {integrity: sha512-arAtTPo76fJ/ICkXWetLCc9EwEHKaeya4vMrReVlEIUCAUncH7M4bhMQ+M9Vf+FFOZJdTNMXNBrWwW+OXWpSew==} + '@esbuild/android-arm@0.24.2': + resolution: {integrity: sha512-tmwl4hJkCfNHwFB3nBa8z1Uy3ypZpxqxfTQOcHX+xRByyYgunVbZ9MzUUfb0RxaHIMnbHagwAxuTL+tnNM+1/Q==} engines: {node: '>=18'} cpu: [arm] os: [android] - '@esbuild/android-x64@0.24.0': - resolution: {integrity: sha512-t8GrvnFkiIY7pa7mMgJd7p8p8qqYIz1NYiAoKc75Zyv73L3DZW++oYMSHPRarcotTKuSs6m3hTOa5CKHaS02TQ==} + '@esbuild/android-x64@0.24.2': + resolution: {integrity: sha512-B6Q0YQDqMx9D7rvIcsXfmJfvUYLoP722bgfBlO5cGvNVb5V/+Y7nhBE3mHV9OpxBf4eAS2S68KZztiPaWq4XYw==} engines: {node: '>=18'} cpu: [x64] os: [android] - '@esbuild/darwin-arm64@0.24.0': - resolution: {integrity: sha512-CKyDpRbK1hXwv79soeTJNHb5EiG6ct3efd/FTPdzOWdbZZfGhpbcqIpiD0+vwmpu0wTIL97ZRPZu8vUt46nBSw==} + '@esbuild/darwin-arm64@0.24.2': + resolution: {integrity: sha512-kj3AnYWc+CekmZnS5IPu9D+HWtUI49hbnyqk0FLEJDbzCIQt7hg7ucF1SQAilhtYpIujfaHr6O0UHlzzSPdOeA==} engines: {node: '>=18'} cpu: [arm64] os: [darwin] - '@esbuild/darwin-x64@0.24.0': - resolution: {integrity: sha512-rgtz6flkVkh58od4PwTRqxbKH9cOjaXCMZgWD905JOzjFKW+7EiUObfd/Kav+A6Gyud6WZk9w+xu6QLytdi2OA==} + '@esbuild/darwin-x64@0.24.2': + resolution: {integrity: sha512-WeSrmwwHaPkNR5H3yYfowhZcbriGqooyu3zI/3GGpF8AyUdsrrP0X6KumITGA9WOyiJavnGZUwPGvxvwfWPHIA==} engines: {node: '>=18'} cpu: [x64] os: [darwin] - '@esbuild/freebsd-arm64@0.24.0': - resolution: {integrity: sha512-6Mtdq5nHggwfDNLAHkPlyLBpE5L6hwsuXZX8XNmHno9JuL2+bg2BX5tRkwjyfn6sKbxZTq68suOjgWqCicvPXA==} + '@esbuild/freebsd-arm64@0.24.2': + resolution: {integrity: sha512-UN8HXjtJ0k/Mj6a9+5u6+2eZ2ERD7Edt1Q9IZiB5UZAIdPnVKDoG7mdTVGhHJIeEml60JteamR3qhsr1r8gXvg==} engines: {node: '>=18'} cpu: [arm64] os: [freebsd] - '@esbuild/freebsd-x64@0.24.0': - resolution: {integrity: sha512-D3H+xh3/zphoX8ck4S2RxKR6gHlHDXXzOf6f/9dbFt/NRBDIE33+cVa49Kil4WUjxMGW0ZIYBYtaGCa2+OsQwQ==} + '@esbuild/freebsd-x64@0.24.2': + resolution: {integrity: sha512-TvW7wE/89PYW+IevEJXZ5sF6gJRDY/14hyIGFXdIucxCsbRmLUcjseQu1SyTko+2idmCw94TgyaEZi9HUSOe3Q==} engines: {node: '>=18'} cpu: [x64] os: [freebsd] - '@esbuild/linux-arm64@0.24.0': - resolution: {integrity: sha512-TDijPXTOeE3eaMkRYpcy3LarIg13dS9wWHRdwYRnzlwlA370rNdZqbcp0WTyyV/k2zSxfko52+C7jU5F9Tfj1g==} + '@esbuild/linux-arm64@0.24.2': + resolution: {integrity: sha512-7HnAD6074BW43YvvUmE/35Id9/NB7BeX5EoNkK9obndmZBUk8xmJJeU7DwmUeN7tkysslb2eSl6CTrYz6oEMQg==} engines: {node: '>=18'} cpu: [arm64] os: [linux] - '@esbuild/linux-arm@0.24.0': - resolution: {integrity: sha512-gJKIi2IjRo5G6Glxb8d3DzYXlxdEj2NlkixPsqePSZMhLudqPhtZ4BUrpIuTjJYXxvF9njql+vRjB2oaC9XpBw==} + '@esbuild/linux-arm@0.24.2': + resolution: {integrity: sha512-n0WRM/gWIdU29J57hJyUdIsk0WarGd6To0s+Y+LwvlC55wt+GT/OgkwoXCXvIue1i1sSNWblHEig00GBWiJgfA==} engines: {node: '>=18'} cpu: [arm] os: [linux] - '@esbuild/linux-ia32@0.24.0': - resolution: {integrity: sha512-K40ip1LAcA0byL05TbCQ4yJ4swvnbzHscRmUilrmP9Am7//0UjPreh4lpYzvThT2Quw66MhjG//20mrufm40mA==} + '@esbuild/linux-ia32@0.24.2': + resolution: {integrity: sha512-sfv0tGPQhcZOgTKO3oBE9xpHuUqguHvSo4jl+wjnKwFpapx+vUDcawbwPNuBIAYdRAvIDBfZVvXprIj3HA+Ugw==} engines: {node: '>=18'} cpu: [ia32] os: [linux] - '@esbuild/linux-loong64@0.24.0': - resolution: {integrity: sha512-0mswrYP/9ai+CU0BzBfPMZ8RVm3RGAN/lmOMgW4aFUSOQBjA31UP8Mr6DDhWSuMwj7jaWOT0p0WoZ6jeHhrD7g==} + '@esbuild/linux-loong64@0.24.2': + resolution: {integrity: sha512-CN9AZr8kEndGooS35ntToZLTQLHEjtVB5n7dl8ZcTZMonJ7CCfStrYhrzF97eAecqVbVJ7APOEe18RPI4KLhwQ==} engines: {node: '>=18'} cpu: [loong64] os: [linux] - '@esbuild/linux-mips64el@0.24.0': - resolution: {integrity: sha512-hIKvXm0/3w/5+RDtCJeXqMZGkI2s4oMUGj3/jM0QzhgIASWrGO5/RlzAzm5nNh/awHE0A19h/CvHQe6FaBNrRA==} + '@esbuild/linux-mips64el@0.24.2': + resolution: {integrity: sha512-iMkk7qr/wl3exJATwkISxI7kTcmHKE+BlymIAbHO8xanq/TjHaaVThFF6ipWzPHryoFsesNQJPE/3wFJw4+huw==} engines: {node: '>=18'} cpu: [mips64el] os: [linux] - '@esbuild/linux-ppc64@0.24.0': - resolution: {integrity: sha512-HcZh5BNq0aC52UoocJxaKORfFODWXZxtBaaZNuN3PUX3MoDsChsZqopzi5UupRhPHSEHotoiptqikjN/B77mYQ==} + '@esbuild/linux-ppc64@0.24.2': + resolution: {integrity: sha512-shsVrgCZ57Vr2L8mm39kO5PPIb+843FStGt7sGGoqiiWYconSxwTiuswC1VJZLCjNiMLAMh34jg4VSEQb+iEbw==} engines: {node: '>=18'} cpu: [ppc64] os: [linux] - '@esbuild/linux-riscv64@0.24.0': - resolution: {integrity: sha512-bEh7dMn/h3QxeR2KTy1DUszQjUrIHPZKyO6aN1X4BCnhfYhuQqedHaa5MxSQA/06j3GpiIlFGSsy1c7Gf9padw==} + '@esbuild/linux-riscv64@0.24.2': + resolution: {integrity: sha512-4eSFWnU9Hhd68fW16GD0TINewo1L6dRrB+oLNNbYyMUAeOD2yCK5KXGK1GH4qD/kT+bTEXjsyTCiJGHPZ3eM9Q==} engines: {node: '>=18'} cpu: [riscv64] os: [linux] - '@esbuild/linux-s390x@0.24.0': - resolution: {integrity: sha512-ZcQ6+qRkw1UcZGPyrCiHHkmBaj9SiCD8Oqd556HldP+QlpUIe2Wgn3ehQGVoPOvZvtHm8HPx+bH20c9pvbkX3g==} + '@esbuild/linux-s390x@0.24.2': + resolution: {integrity: sha512-S0Bh0A53b0YHL2XEXC20bHLuGMOhFDO6GN4b3YjRLK//Ep3ql3erpNcPlEFed93hsQAjAQDNsvcK+hV90FubSw==} engines: {node: '>=18'} cpu: [s390x] os: [linux] - '@esbuild/linux-x64@0.24.0': - resolution: {integrity: sha512-vbutsFqQ+foy3wSSbmjBXXIJ6PL3scghJoM8zCL142cGaZKAdCZHyf+Bpu/MmX9zT9Q0zFBVKb36Ma5Fzfa8xA==} + '@esbuild/linux-x64@0.24.2': + resolution: {integrity: sha512-8Qi4nQcCTbLnK9WoMjdC9NiTG6/E38RNICU6sUNqK0QFxCYgoARqVqxdFmWkdonVsvGqWhmm7MO0jyTqLqwj0Q==} engines: {node: '>=18'} cpu: [x64] os: [linux] - '@esbuild/netbsd-x64@0.24.0': - resolution: {integrity: sha512-hjQ0R/ulkO8fCYFsG0FZoH+pWgTTDreqpqY7UnQntnaKv95uP5iW3+dChxnx7C3trQQU40S+OgWhUVwCjVFLvg==} + '@esbuild/netbsd-arm64@0.24.2': + resolution: {integrity: sha512-wuLK/VztRRpMt9zyHSazyCVdCXlpHkKm34WUyinD2lzK07FAHTq0KQvZZlXikNWkDGoT6x3TD51jKQ7gMVpopw==} + engines: {node: '>=18'} + cpu: [arm64] + os: [netbsd] + + '@esbuild/netbsd-x64@0.24.2': + resolution: {integrity: sha512-VefFaQUc4FMmJuAxmIHgUmfNiLXY438XrL4GDNV1Y1H/RW3qow68xTwjZKfj/+Plp9NANmzbH5R40Meudu8mmw==} engines: {node: '>=18'} cpu: [x64] os: [netbsd] - '@esbuild/openbsd-arm64@0.24.0': - resolution: {integrity: sha512-MD9uzzkPQbYehwcN583yx3Tu5M8EIoTD+tUgKF982WYL9Pf5rKy9ltgD0eUgs8pvKnmizxjXZyLt0z6DC3rRXg==} + '@esbuild/openbsd-arm64@0.24.2': + resolution: {integrity: sha512-YQbi46SBct6iKnszhSvdluqDmxCJA+Pu280Av9WICNwQmMxV7nLRHZfjQzwbPs3jeWnuAhE9Jy0NrnJ12Oz+0A==} engines: {node: '>=18'} cpu: [arm64] os: [openbsd] - '@esbuild/openbsd-x64@0.24.0': - resolution: {integrity: sha512-4ir0aY1NGUhIC1hdoCzr1+5b43mw99uNwVzhIq1OY3QcEwPDO3B7WNXBzaKY5Nsf1+N11i1eOfFcq+D/gOS15Q==} + '@esbuild/openbsd-x64@0.24.2': + resolution: {integrity: sha512-+iDS6zpNM6EnJyWv0bMGLWSWeXGN/HTaF/LXHXHwejGsVi+ooqDfMCCTerNFxEkM3wYVcExkeGXNqshc9iMaOA==} engines: {node: '>=18'} cpu: [x64] os: [openbsd] - '@esbuild/sunos-x64@0.24.0': - resolution: {integrity: sha512-jVzdzsbM5xrotH+W5f1s+JtUy1UWgjU0Cf4wMvffTB8m6wP5/kx0KiaLHlbJO+dMgtxKV8RQ/JvtlFcdZ1zCPA==} + '@esbuild/sunos-x64@0.24.2': + resolution: {integrity: sha512-hTdsW27jcktEvpwNHJU4ZwWFGkz2zRJUz8pvddmXPtXDzVKTTINmlmga3ZzwcuMpUvLw7JkLy9QLKyGpD2Yxig==} engines: {node: '>=18'} cpu: [x64] os: [sunos] - '@esbuild/win32-arm64@0.24.0': - resolution: {integrity: sha512-iKc8GAslzRpBytO2/aN3d2yb2z8XTVfNV0PjGlCxKo5SgWmNXx82I/Q3aG1tFfS+A2igVCY97TJ8tnYwpUWLCA==} + '@esbuild/win32-arm64@0.24.2': + resolution: {integrity: sha512-LihEQ2BBKVFLOC9ZItT9iFprsE9tqjDjnbulhHoFxYQtQfai7qfluVODIYxt1PgdoyQkz23+01rzwNwYfutxUQ==} engines: {node: '>=18'} cpu: [arm64] os: [win32] - '@esbuild/win32-ia32@0.24.0': - resolution: {integrity: sha512-vQW36KZolfIudCcTnaTpmLQ24Ha1RjygBo39/aLkM2kmjkWmZGEJ5Gn9l5/7tzXA42QGIoWbICfg6KLLkIw6yw==} + '@esbuild/win32-ia32@0.24.2': + resolution: {integrity: sha512-q+iGUwfs8tncmFC9pcnD5IvRHAzmbwQ3GPS5/ceCyHdjXubwQWI12MKWSNSMYLJMq23/IUCvJMS76PDqXe1fxA==} engines: {node: '>=18'} cpu: [ia32] os: [win32] - '@esbuild/win32-x64@0.24.0': - resolution: {integrity: sha512-7IAFPrjSQIJrGsK6flwg7NFmwBoSTyF3rl7If0hNUFQU4ilTsEPL6GuMuU9BfIWVVGuRnuIidkSMC+c0Otu8IA==} + '@esbuild/win32-x64@0.24.2': + resolution: {integrity: sha512-7VTgWzgMGvup6aSqDPLiW5zHaxYJGTO4OokMjIlrCtf+VpEL+cXKtCvg723iguPYI5oaUNdS+/V7OU2gvXVWEg==} engines: {node: '>=18'} cpu: [x64] os: [win32] @@ -1148,43 +1163,43 @@ packages: resolution: {integrity: sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==} engines: {node: '>= 8'} - '@oxlint/darwin-arm64@0.15.3': - resolution: {integrity: sha512-6isglmWrI3XxNR+V2KDURRg8bo3JpoTGUs1BqEuwZISz0tIEU5kVZ3Zba4vNz6Rp79lfA18ueYTB5NKonWaYOg==} + '@oxlint/darwin-arm64@0.15.5': + resolution: {integrity: sha512-LqUh/+iRwj2mIDMqiYOjf2nx/BjpMVY+2PQvpOgSd2mNXrudD02KUTNCVSTAhUuGe86SYQblFgBz2cYfbTUa9A==} cpu: [arm64] os: [darwin] - '@oxlint/darwin-x64@0.15.3': - resolution: {integrity: sha512-wKn+eITIIpcXPU7hiWVHezAKONT/Vz6q9TUZFiYQFytF7sGAt0APZshe5tbjGTZ8XTR6wQ5wDETwdornHXCNFg==} + '@oxlint/darwin-x64@0.15.5': + resolution: {integrity: sha512-3AdgAKrZsZ1Tk4XW5GosNKfRk5tdAzYgZl/9lJSCJr2I5mN6hrTn/WTIJv4tJrLlQbFsD++5R5HCQblp9vfFNg==} cpu: [x64] os: [darwin] - '@oxlint/linux-arm64-gnu@0.15.3': - resolution: {integrity: sha512-AZUOtb3OfK8xDZJfk60AwgTKEpa6zJdvjrwuk8Qqz4tPqLJpk4KSJmfNMzbYzy689m27ur+ix1p/7JAxwvckRg==} + '@oxlint/linux-arm64-gnu@0.15.5': + resolution: {integrity: sha512-iKqoRSn+aIYqku99xBFzhZFaRXTIpFhFIh37MFjzhPvvVN5qQjxBzvePfuI1eTVuttviELKP5eR5sSUP2aDKxw==} cpu: [arm64] os: [linux] - '@oxlint/linux-arm64-musl@0.15.3': - resolution: {integrity: sha512-HIeyrgE11KFkSRpVjBRWOux78OITDqlOiC8plC2RDrLvSj205MaA1GYYyIMMv/FuyWdGMOAHOetn5vWbyJJctQ==} + '@oxlint/linux-arm64-musl@0.15.5': + resolution: {integrity: sha512-pYNCI9iqPcma8hIuJb/v40mOjuWtJjYaOxbDvSecjtKb9EFqZu9A9WDhgg766S+8o1Iit72LLtSq7q0cyh7+ww==} cpu: [arm64] os: [linux] - '@oxlint/linux-x64-gnu@0.15.3': - resolution: {integrity: sha512-cDHQaDCpuqFFYTohM+xw4120hzBSWaOVIZqq0ROUEX/qi+nnR9XMKE/fJf8xiHJznFlV6ANsiMLY939uur8OKw==} + '@oxlint/linux-x64-gnu@0.15.5': + resolution: {integrity: sha512-jDrA5vSdEhKov1aMFvWLzFpuGneVhryLXTqcbqdUzZOe1Ss1S2XhRabHwLlhDRemCA4Id7fdgZ5qCNrzhUsTdQ==} cpu: [x64] os: [linux] - '@oxlint/linux-x64-musl@0.15.3': - resolution: {integrity: sha512-6PVIi0XXhlpFoBh0k2fP9wioU8MiktkqnYHxOv7EM7HggjAzpRMJqQmgwWcww3RU5R7T4wnZNzrUPPqI7+Ejmw==} + '@oxlint/linux-x64-musl@0.15.5': + resolution: {integrity: sha512-eS4ANgxQCNnGG1aeQ28cUTr/3iitFF9TBK1BfTn3+WW3Nvkfcxo+u2L5tKEq+cxytHuu9hqEpTn1AvNyAH3MQw==} cpu: [x64] os: [linux] - '@oxlint/win32-arm64@0.15.3': - resolution: {integrity: sha512-CAvFXTZ6pwHHMHTmRgev/QcS4vD2UeH4e68DxgslPrib6ivTGz2EvtVbrVuVsuS27WQuKTy06e9RW339dk4pHg==} + '@oxlint/win32-arm64@0.15.5': + resolution: {integrity: sha512-oJPS+dTlwgVoSb6ieH/4MP+LPxZUMPsUr5k0YLpisMEEfccGXLaGzWKfzgi5dzlOsN6EUr2NgcFaqpa8tRiq8w==} cpu: [arm64] os: [win32] - '@oxlint/win32-x64@0.15.3': - resolution: {integrity: sha512-sXBPSxDoOELlkUbjXfXqlfig3jw67ylrZn+URke/TZMknY1uNEsFTg9+89t8km65eC8SZSE9rnZVyjK8iaEJXA==} + '@oxlint/win32-x64@0.15.5': + resolution: {integrity: sha512-rvk3CN0U37w7OlLvkD1TqqcLvoQdWVtTAF5KckuASOeYo/0cuzNFIvo/7cHYmvewQXuYULxvUHGTzxWYSmVPjQ==} cpu: [x64] os: [win32] @@ -1298,126 +1313,126 @@ packages: rollup: optional: true - '@rollup/rollup-android-arm-eabi@4.29.1': - resolution: {integrity: sha512-ssKhA8RNltTZLpG6/QNkCSge+7mBQGUqJRisZ2MDQcEGaK93QESEgWK2iOpIDZ7k9zPVkG5AS3ksvD5ZWxmItw==} + '@rollup/rollup-android-arm-eabi@4.30.1': + resolution: {integrity: sha512-pSWY+EVt3rJ9fQ3IqlrEUtXh3cGqGtPDH1FQlNZehO2yYxCHEX1SPsz1M//NXwYfbTlcKr9WObLnJX9FsS9K1Q==} cpu: [arm] os: [android] - '@rollup/rollup-android-arm64@4.29.1': - resolution: {integrity: sha512-CaRfrV0cd+NIIcVVN/jx+hVLN+VRqnuzLRmfmlzpOzB87ajixsN/+9L5xNmkaUUvEbI5BmIKS+XTwXsHEb65Ew==} + '@rollup/rollup-android-arm64@4.30.1': + resolution: {integrity: sha512-/NA2qXxE3D/BRjOJM8wQblmArQq1YoBVJjrjoTSBS09jgUisq7bqxNHJ8kjCHeV21W/9WDGwJEWSN0KQ2mtD/w==} cpu: [arm64] os: [android] - '@rollup/rollup-darwin-arm64@4.29.1': - resolution: {integrity: sha512-2ORr7T31Y0Mnk6qNuwtyNmy14MunTAMx06VAPI6/Ju52W10zk1i7i5U3vlDRWjhOI5quBcrvhkCHyF76bI7kEw==} + '@rollup/rollup-darwin-arm64@4.30.1': + resolution: {integrity: sha512-r7FQIXD7gB0WJ5mokTUgUWPl0eYIH0wnxqeSAhuIwvnnpjdVB8cRRClyKLQr7lgzjctkbp5KmswWszlwYln03Q==} cpu: [arm64] os: [darwin] - '@rollup/rollup-darwin-x64@4.29.1': - resolution: {integrity: sha512-j/Ej1oanzPjmN0tirRd5K2/nncAhS9W6ICzgxV+9Y5ZsP0hiGhHJXZ2JQ53iSSjj8m6cRY6oB1GMzNn2EUt6Ng==} + '@rollup/rollup-darwin-x64@4.30.1': + resolution: {integrity: sha512-x78BavIwSH6sqfP2xeI1hd1GpHL8J4W2BXcVM/5KYKoAD3nNsfitQhvWSw+TFtQTLZ9OmlF+FEInEHyubut2OA==} cpu: [x64] os: [darwin] - '@rollup/rollup-freebsd-arm64@4.29.1': - resolution: {integrity: sha512-91C//G6Dm/cv724tpt7nTyP+JdN12iqeXGFM1SqnljCmi5yTXriH7B1r8AD9dAZByHpKAumqP1Qy2vVNIdLZqw==} + '@rollup/rollup-freebsd-arm64@4.30.1': + resolution: {integrity: sha512-HYTlUAjbO1z8ywxsDFWADfTRfTIIy/oUlfIDmlHYmjUP2QRDTzBuWXc9O4CXM+bo9qfiCclmHk1x4ogBjOUpUQ==} cpu: [arm64] os: [freebsd] - '@rollup/rollup-freebsd-x64@4.29.1': - resolution: {integrity: sha512-hEioiEQ9Dec2nIRoeHUP6hr1PSkXzQaCUyqBDQ9I9ik4gCXQZjJMIVzoNLBRGet+hIUb3CISMh9KXuCcWVW/8w==} + '@rollup/rollup-freebsd-x64@4.30.1': + resolution: {integrity: sha512-1MEdGqogQLccphhX5myCJqeGNYTNcmTyaic9S7CG3JhwuIByJ7J05vGbZxsizQthP1xpVx7kd3o31eOogfEirw==} cpu: [x64] os: [freebsd] - '@rollup/rollup-linux-arm-gnueabihf@4.29.1': - resolution: {integrity: sha512-Py5vFd5HWYN9zxBv3WMrLAXY3yYJ6Q/aVERoeUFwiDGiMOWsMs7FokXihSOaT/PMWUty/Pj60XDQndK3eAfE6A==} + '@rollup/rollup-linux-arm-gnueabihf@4.30.1': + resolution: {integrity: sha512-PaMRNBSqCx7K3Wc9QZkFx5+CX27WFpAMxJNiYGAXfmMIKC7jstlr32UhTgK6T07OtqR+wYlWm9IxzennjnvdJg==} cpu: [arm] os: [linux] - '@rollup/rollup-linux-arm-musleabihf@4.29.1': - resolution: {integrity: sha512-RiWpGgbayf7LUcuSNIbahr0ys2YnEERD4gYdISA06wa0i8RALrnzflh9Wxii7zQJEB2/Eh74dX4y/sHKLWp5uQ==} + '@rollup/rollup-linux-arm-musleabihf@4.30.1': + resolution: {integrity: sha512-B8Rcyj9AV7ZlEFqvB5BubG5iO6ANDsRKlhIxySXcF1axXYUyqwBok+XZPgIYGBgs7LDXfWfifxhw0Ik57T0Yug==} cpu: [arm] os: [linux] - '@rollup/rollup-linux-arm64-gnu@4.29.1': - resolution: {integrity: sha512-Z80O+taYxTQITWMjm/YqNoe9d10OX6kDh8X5/rFCMuPqsKsSyDilvfg+vd3iXIqtfmp+cnfL1UrYirkaF8SBZA==} + '@rollup/rollup-linux-arm64-gnu@4.30.1': + resolution: {integrity: sha512-hqVyueGxAj3cBKrAI4aFHLV+h0Lv5VgWZs9CUGqr1z0fZtlADVV1YPOij6AhcK5An33EXaxnDLmJdQikcn5NEw==} cpu: [arm64] os: [linux] - '@rollup/rollup-linux-arm64-musl@4.29.1': - resolution: {integrity: sha512-fOHRtF9gahwJk3QVp01a/GqS4hBEZCV1oKglVVq13kcK3NeVlS4BwIFzOHDbmKzt3i0OuHG4zfRP0YoG5OF/rA==} + '@rollup/rollup-linux-arm64-musl@4.30.1': + resolution: {integrity: sha512-i4Ab2vnvS1AE1PyOIGp2kXni69gU2DAUVt6FSXeIqUCPIR3ZlheMW3oP2JkukDfu3PsexYRbOiJrY+yVNSk9oA==} cpu: [arm64] os: [linux] - '@rollup/rollup-linux-loongarch64-gnu@4.29.1': - resolution: {integrity: sha512-5a7q3tnlbcg0OodyxcAdrrCxFi0DgXJSoOuidFUzHZ2GixZXQs6Tc3CHmlvqKAmOs5eRde+JJxeIf9DonkmYkw==} + '@rollup/rollup-linux-loongarch64-gnu@4.30.1': + resolution: {integrity: sha512-fARcF5g296snX0oLGkVxPmysetwUk2zmHcca+e9ObOovBR++9ZPOhqFUM61UUZ2EYpXVPN1redgqVoBB34nTpQ==} cpu: [loong64] os: [linux] - '@rollup/rollup-linux-powerpc64le-gnu@4.29.1': - resolution: {integrity: sha512-9b4Mg5Yfz6mRnlSPIdROcfw1BU22FQxmfjlp/CShWwO3LilKQuMISMTtAu/bxmmrE6A902W2cZJuzx8+gJ8e9w==} + '@rollup/rollup-linux-powerpc64le-gnu@4.30.1': + resolution: {integrity: sha512-GLrZraoO3wVT4uFXh67ElpwQY0DIygxdv0BNW9Hkm3X34wu+BkqrDrkcsIapAY+N2ATEbvak0XQ9gxZtCIA5Rw==} cpu: [ppc64] os: [linux] - '@rollup/rollup-linux-riscv64-gnu@4.29.1': - resolution: {integrity: sha512-G5pn0NChlbRM8OJWpJFMX4/i8OEU538uiSv0P6roZcbpe/WfhEO+AT8SHVKfp8qhDQzaz7Q+1/ixMy7hBRidnQ==} + '@rollup/rollup-linux-riscv64-gnu@4.30.1': + resolution: {integrity: sha512-0WKLaAUUHKBtll0wvOmh6yh3S0wSU9+yas923JIChfxOaaBarmb/lBKPF0w/+jTVozFnOXJeRGZ8NvOxvk/jcw==} cpu: [riscv64] os: [linux] - '@rollup/rollup-linux-s390x-gnu@4.29.1': - resolution: {integrity: sha512-WM9lIkNdkhVwiArmLxFXpWndFGuOka4oJOZh8EP3Vb8q5lzdSCBuhjavJsw68Q9AKDGeOOIHYzYm4ZFvmWez5g==} + '@rollup/rollup-linux-s390x-gnu@4.30.1': + resolution: {integrity: sha512-GWFs97Ruxo5Bt+cvVTQkOJ6TIx0xJDD/bMAOXWJg8TCSTEK8RnFeOeiFTxKniTc4vMIaWvCplMAFBt9miGxgkA==} cpu: [s390x] os: [linux] - '@rollup/rollup-linux-x64-gnu@4.29.1': - resolution: {integrity: sha512-87xYCwb0cPGZFoGiErT1eDcssByaLX4fc0z2nRM6eMtV9njAfEE6OW3UniAoDhX4Iq5xQVpE6qO9aJbCFumKYQ==} + '@rollup/rollup-linux-x64-gnu@4.30.1': + resolution: {integrity: sha512-UtgGb7QGgXDIO+tqqJ5oZRGHsDLO8SlpE4MhqpY9Llpzi5rJMvrK6ZGhsRCST2abZdBqIBeXW6WPD5fGK5SDwg==} cpu: [x64] os: [linux] - '@rollup/rollup-linux-x64-musl@4.29.1': - resolution: {integrity: sha512-xufkSNppNOdVRCEC4WKvlR1FBDyqCSCpQeMMgv9ZyXqqtKBfkw1yfGMTUTs9Qsl6WQbJnsGboWCp7pJGkeMhKA==} + '@rollup/rollup-linux-x64-musl@4.30.1': + resolution: {integrity: sha512-V9U8Ey2UqmQsBT+xTOeMzPzwDzyXmnAoO4edZhL7INkwQcaW1Ckv3WJX3qrrp/VHaDkEWIBWhRwP47r8cdrOow==} cpu: [x64] os: [linux] - '@rollup/rollup-win32-arm64-msvc@4.29.1': - resolution: {integrity: sha512-F2OiJ42m77lSkizZQLuC+jiZ2cgueWQL5YC9tjo3AgaEw+KJmVxHGSyQfDUoYR9cci0lAywv2Clmckzulcq6ig==} + '@rollup/rollup-win32-arm64-msvc@4.30.1': + resolution: {integrity: sha512-WabtHWiPaFF47W3PkHnjbmWawnX/aE57K47ZDT1BXTS5GgrBUEpvOzq0FI0V/UYzQJgdb8XlhVNH8/fwV8xDjw==} cpu: [arm64] os: [win32] - '@rollup/rollup-win32-ia32-msvc@4.29.1': - resolution: {integrity: sha512-rYRe5S0FcjlOBZQHgbTKNrqxCBUmgDJem/VQTCcTnA2KCabYSWQDrytOzX7avb79cAAweNmMUb/Zw18RNd4mng==} + '@rollup/rollup-win32-ia32-msvc@4.30.1': + resolution: {integrity: sha512-pxHAU+Zv39hLUTdQQHUVHf4P+0C47y/ZloorHpzs2SXMRqeAWmGghzAhfOlzFHHwjvgokdFAhC4V+6kC1lRRfw==} cpu: [ia32] os: [win32] - '@rollup/rollup-win32-x64-msvc@4.29.1': - resolution: {integrity: sha512-+10CMg9vt1MoHj6x1pxyjPSMjHTIlqs8/tBztXvPAx24SKs9jwVnKqHJumlH/IzhaPUaj3T6T6wfZr8okdXaIg==} + '@rollup/rollup-win32-x64-msvc@4.30.1': + resolution: {integrity: sha512-D6qjsXGcvhTjv0kI4fU8tUuBDF/Ueee4SVX79VfNDXZa64TfCW1Slkb6Z7O1p7vflqZjcmOVdZlqf8gvJxc6og==} cpu: [x64] os: [win32] '@sec-ant/readable-stream@0.4.1': resolution: {integrity: sha512-831qok9r2t8AlxLko40y2ebgSDhenenCatLVeW/uBtnHPyhHOvG0C7TvfgecV+wHzIm5KUICgzmVpWS+IMEAeg==} - '@sentry-internal/browser-utils@8.47.0': - resolution: {integrity: sha512-vOXzYzHTKkahTLDzWWIA4EiVCQ+Gk+7xGWUlNcR2ZiEPBqYZVb5MjsUozAcc7syrSUy6WicyFjcomZ3rlCVQhg==} + '@sentry-internal/browser-utils@8.48.0': + resolution: {integrity: sha512-pLtu0Fa1Ou0v3M1OEO1MB1EONJVmXEGtoTwFRCO1RPQI2ulmkG6BikINClFG5IBpoYKZ33WkEXuM6U5xh+pdZg==} engines: {node: '>=14.18'} - '@sentry-internal/feedback@8.47.0': - resolution: {integrity: sha512-IAiIemTQIalxAOYhUENs9bZ8pMNgJnX3uQSuY7v0gknEqClOGpGkG04X/cxCmtJUj1acZ9ShTGDxoh55a+ggAQ==} + '@sentry-internal/feedback@8.48.0': + resolution: {integrity: sha512-6PwcJNHVPg0EfZxmN+XxVOClfQpv7MBAweV8t9i5l7VFr8sM/7wPNSeU/cG7iK19Ug9ZEkBpzMOe3G4GXJ5bpw==} engines: {node: '>=14.18'} - '@sentry-internal/replay-canvas@8.47.0': - resolution: {integrity: sha512-M4W9UGouEeELbGbP3QsXLDVtGiQSZoWJlKwqMWyqdQgZuLoKw0S33+60t6teLVMhuQZR0UI9VJTF5coiXysnnA==} + '@sentry-internal/replay-canvas@8.48.0': + resolution: {integrity: sha512-LdivLfBXXB9us1aAc6XaL7/L2Ob4vi3C/fEOXElehg3qHjX6q6pewiv5wBvVXGX1NfZTRvu+X11k6TZoxKsezw==} engines: {node: '>=14.18'} - '@sentry-internal/replay@8.47.0': - resolution: {integrity: sha512-G/S40ZBORj0HSMLw/uVC6YDEPN/dqVk901vf4VYfml686DEhJrZesfAfp5SydJumQ0NKZQrdtvny+BWnlI5H1w==} + '@sentry-internal/replay@8.48.0': + resolution: {integrity: sha512-csILVupc5RkrsTrncuUTGmlB56FQSFjXPYWG8I8yBTGlXEJ+o8oTuF6+55R4vbw3EIzBveXWi4kEBbnQlXW/eg==} engines: {node: '>=14.18'} - '@sentry/browser@8.47.0': - resolution: {integrity: sha512-K6BzHisykmbFy/wORtGyfsAlw7ShevLALzu3ReZZZ18dVubO1bjSNjkZQU9MJD5Jcb9oLwkq89n3N9XIBfvdRA==} + '@sentry/browser@8.48.0': + resolution: {integrity: sha512-fuuVULB5/1vI8NoIwXwR3xwhJJqk+y4RdSdajExGF7nnUDBpwUJyXsmYJnOkBO+oLeEs58xaCpotCKiPUNnE3g==} engines: {node: '>=14.18'} - '@sentry/core@8.47.0': - resolution: {integrity: sha512-iSEJZMe3DOcqBFZQAqgA3NB2lCWBc4Gv5x/SCri/TVg96wAlss4VrUunSI2Mp0J4jJ5nJcJ2ChqHSBAU48k3FA==} + '@sentry/core@8.48.0': + resolution: {integrity: sha512-VGwYgTfLpvJ5LRO5A+qWo1gpo6SfqaGXL9TOzVgBucAdpzbrYHpZ87sEarDVq/4275uk1b0S293/mfsskFczyw==} engines: {node: '>=14.18'} '@sindresorhus/is@5.6.0': @@ -1551,57 +1566,57 @@ packages: '@types/json-schema@7.0.15': resolution: {integrity: sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==} - '@types/node@22.10.2': - resolution: {integrity: sha512-Xxr6BBRCAOQixvonOye19wnzyDiUtTeqldOOmj3CkeblonbccA12PFwlufvRdrpjXxqnmUaeiU5EOA+7s5diUQ==} + '@types/node@22.10.5': + resolution: {integrity: sha512-F8Q+SeGimwOo86fiovQh8qiXfFEh2/ocYv7tU5pJ3EXMSSxk1Joj5wefpFK2fHTf/N6HKGSxIDBT9f3gCxXPkQ==} '@types/trusted-types@2.0.7': resolution: {integrity: sha512-ScaPdn1dQczgbl0QFTeTOmVHFULt394XJgOQNoyVhZ6r2vLnMLJfBPd53SB52T/3G36VI1/g2MZaX0cwDuXsfw==} - '@typescript-eslint/eslint-plugin@8.18.1': - resolution: {integrity: sha512-Ncvsq5CT3Gvh+uJG0Lwlho6suwDfUXH0HztslDf5I+F2wAFAZMRwYLEorumpKLzmO2suAXZ/td1tBg4NZIi9CQ==} + '@typescript-eslint/eslint-plugin@8.19.1': + resolution: {integrity: sha512-tJzcVyvvb9h/PB96g30MpxACd9IrunT7GF9wfA9/0TJ1LxGOJx1TdPzSbBBnNED7K9Ka8ybJsnEpiXPktolTLg==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} peerDependencies: '@typescript-eslint/parser': ^8.0.0 || ^8.0.0-alpha.0 eslint: ^8.57.0 || ^9.0.0 typescript: '>=4.8.4 <5.8.0' - '@typescript-eslint/parser@8.18.1': - resolution: {integrity: sha512-rBnTWHCdbYM2lh7hjyXqxk70wvon3p2FyaniZuey5TrcGBpfhVp0OxOa6gxr9Q9YhZFKyfbEnxc24ZnVbbUkCA==} + '@typescript-eslint/parser@8.19.1': + resolution: {integrity: sha512-67gbfv8rAwawjYx3fYArwldTQKoYfezNUT4D5ioWetr/xCrxXxvleo3uuiFuKfejipvq+og7mjz3b0G2bVyUCw==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} peerDependencies: eslint: ^8.57.0 || ^9.0.0 typescript: '>=4.8.4 <5.8.0' - '@typescript-eslint/scope-manager@8.18.1': - resolution: {integrity: sha512-HxfHo2b090M5s2+/9Z3gkBhI6xBH8OJCFjH9MhQ+nnoZqxU3wNxkLT+VWXWSFWc3UF3Z+CfPAyqdCTdoXtDPCQ==} + '@typescript-eslint/scope-manager@8.19.1': + resolution: {integrity: sha512-60L9KIuN/xgmsINzonOcMDSB8p82h95hoBfSBtXuO4jlR1R9L1xSkmVZKgCPVfavDlXihh4ARNjXhh1gGnLC7Q==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - '@typescript-eslint/type-utils@8.18.1': - resolution: {integrity: sha512-jAhTdK/Qx2NJPNOTxXpMwlOiSymtR2j283TtPqXkKBdH8OAMmhiUfP0kJjc/qSE51Xrq02Gj9NY7MwK+UxVwHQ==} + '@typescript-eslint/type-utils@8.19.1': + resolution: {integrity: sha512-Rp7k9lhDKBMRJB/nM9Ksp1zs4796wVNyihG9/TU9R6KCJDNkQbc2EOKjrBtLYh3396ZdpXLtr/MkaSEmNMtykw==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} peerDependencies: eslint: ^8.57.0 || ^9.0.0 typescript: '>=4.8.4 <5.8.0' - '@typescript-eslint/types@8.18.1': - resolution: {integrity: sha512-7uoAUsCj66qdNQNpH2G8MyTFlgerum8ubf21s3TSM3XmKXuIn+H2Sifh/ES2nPOPiYSRJWAk0fDkW0APBWcpfw==} + '@typescript-eslint/types@8.19.1': + resolution: {integrity: sha512-JBVHMLj7B1K1v1051ZaMMgLW4Q/jre5qGK0Ew6UgXz1Rqh+/xPzV1aW581OM00X6iOfyr1be+QyW8LOUf19BbA==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - '@typescript-eslint/typescript-estree@8.18.1': - resolution: {integrity: sha512-z8U21WI5txzl2XYOW7i9hJhxoKKNG1kcU4RzyNvKrdZDmbjkmLBo8bgeiOJmA06kizLI76/CCBAAGlTlEeUfyg==} + '@typescript-eslint/typescript-estree@8.19.1': + resolution: {integrity: sha512-jk/TZwSMJlxlNnqhy0Eod1PNEvCkpY6MXOXE/WLlblZ6ibb32i2We4uByoKPv1d0OD2xebDv4hbs3fm11SMw8Q==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} peerDependencies: typescript: '>=4.8.4 <5.8.0' - '@typescript-eslint/utils@8.18.1': - resolution: {integrity: sha512-8vikiIj2ebrC4WRdcAdDcmnu9Q/MXXwg+STf40BVfT8exDqBCUPdypvzcUPxEqRGKg9ALagZ0UWcYCtn+4W2iQ==} + '@typescript-eslint/utils@8.19.1': + resolution: {integrity: sha512-IxG5gLO0Ne+KaUc8iW1A+XuKLd63o4wlbI1Zp692n1xojCl/THvgIKXJXBZixTh5dd5+yTJ/VXH7GJaaw21qXA==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} peerDependencies: eslint: ^8.57.0 || ^9.0.0 typescript: '>=4.8.4 <5.8.0' - '@typescript-eslint/visitor-keys@8.18.1': - resolution: {integrity: sha512-Vj0WLm5/ZsD013YeUKn+K0y8p1M0jPpxOkKdbD1wB0ns53a5piVY02zjf072TblEweAbcYiFiPoSMF3kp+VhhQ==} + '@typescript-eslint/visitor-keys@8.19.1': + resolution: {integrity: sha512-fzmjU8CHK853V/avYZAvuVut3ZTfwN5YtMaoi+X9Y9MA9keaWNHC3zEQ9zvyX/7Hj+5JkNyK1l7TOR2hevHB6Q==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} '@vitejs/plugin-legacy@6.0.0': @@ -1733,8 +1748,8 @@ packages: balanced-match@2.0.0: resolution: {integrity: sha512-1ugUSr8BHXRnK23KfuYS+gVMC3LB8QGH9W1iGtDPsNWoQbgtXSExkBu2aDR4epiGWZOjZsj6lDl/N/AqqTC3UA==} - bare-events@2.5.0: - resolution: {integrity: sha512-/E8dDe9dsbLyh2qrZ64PEPadOQ0F4gbl1sUJOrmph7xOiIxfY8vwab/4bFLh4Y88/Hk/ujKcrQKc+ps0mv873A==} + bare-events@2.5.3: + resolution: {integrity: sha512-pCO3aoRJ0MBiRMu8B7vUga0qL3L7gO1+SW7ku6qlSsMLwuhaawnuvZDyzJY/kyC63Un0XAB0OPUcfF1eTO/V+Q==} base64-js@1.5.1: resolution: {integrity: sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==} @@ -1801,8 +1816,8 @@ packages: peerDependencies: browserslist: '*' - browserslist@4.24.3: - resolution: {integrity: sha512-1CPmv8iobE2fyRMV97dAcMVegvvWKxmq94hkLiAkUGwKVTyDLw33K+ZxiFrREKmmps4rIw6grcCFCnTMSZ/YiA==} + browserslist@4.24.4: + resolution: {integrity: sha512-KDi1Ny1gSePi1vm0q4oxSF8b4DR44GF4BbmS2YdhPLOEqd8pDviZOGH/GsmRwoWJ2+5Lr085X7naowMwKHDG1A==} engines: {node: ^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7} hasBin: true @@ -1855,6 +1870,10 @@ packages: resolution: {integrity: sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==} engines: {node: '>=10'} + chalk@5.4.1: + resolution: {integrity: sha512-zgVZuo2WcZgfUEmsn6eO3kINexW8RAE4maiQ8QNs8CtpPCSyMiYsULR3HQYkm3w8FIA3SberyMJMSldGsW+U3w==} + engines: {node: ^12.17.0 || ^14.13 || >=16.0.0} + chevrotain@7.1.1: resolution: {integrity: sha512-wy3mC1x4ye+O+QkEinVJkPf5u2vsrDIYW9G7ZuwFl6v/Yu0LwUuT2POsb+NUWApebyxfkQq6+yDfRExbnI5rcw==} @@ -1918,11 +1937,11 @@ packages: convert-source-map@2.0.0: resolution: {integrity: sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==} - core-js-compat@3.39.0: - resolution: {integrity: sha512-VgEUx3VwlExr5no0tXlBt+silBvhTryPwCXRI2Id1PN8WTKu7MreethvddqOubrYxkFdv/RnYrqlv1sFNAUelw==} + core-js-compat@3.40.0: + resolution: {integrity: sha512-0XEDpr5y5mijvw8Lbc6E5AkjrHfp7eEoPlu36SWeAbcL8fn1G1ANe8DBlo2XoNN89oVpxWwOjYIPVzR4ZvsKCQ==} - core-js@3.39.0: - resolution: {integrity: sha512-raM0ew0/jJUqkJ0E6e8UDtl+y/7ktFivgWvqw8dNSQeNWoSDLvQ1H/RN3aPXB9tBd4/FhyR4RDPGhsNIMsAn7g==} + core-js@3.40.0: + resolution: {integrity: sha512-7vsMc/Lty6AGnn7uFpYT56QesI5D2Y/UkgKounk87OP9Z2H9Z8kj6jzcSGAxFmUtDOS0ntK6lbQz+Nsa0Jj6mQ==} core-util-is@1.0.3: resolution: {integrity: sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==} @@ -2030,8 +2049,8 @@ packages: easy-table@1.2.0: resolution: {integrity: sha512-OFzVOv03YpvtcWGe5AayU5G2hgybsg3iqA6drU8UaoZyB9jLGMTrz9+asnLp/E+6qPh88yEI1gvyZFZ41dmgww==} - electron-to-chromium@1.5.75: - resolution: {integrity: sha512-Lf3++DumRE/QmweGjU+ZcKqQ+3bKkU/qjaKYhIJKEOhgIO9Xs6IiAQFkfFoj+RhgDk4LUeNsLo6plExHqSyu6Q==} + electron-to-chromium@1.5.79: + resolution: {integrity: sha512-nYOxJNxQ9Om4EC88BE4pPoNI8xwSFf8pU/BAeOl4Hh/b/i6V4biTAzwV7pXi3ARKeoYO5JZKMIXTryXSVer5RA==} elliptic@6.6.1: resolution: {integrity: sha512-RaddvvMatK2LJHqFJ+YA4WysVN5Ita9E35botqIYspQ4TkRAlCicdzKOjlyv/1Za5RyTNn7di//eEV0uTAfe3g==} @@ -2062,8 +2081,8 @@ packages: resolution: {integrity: sha512-MZ4iQ6JwHOBQjahnjwaC1ZtIBH+2ohjamzAO3oaHcXYup7qxjF2fixyH+Q71voWHeOkI2q/TnJao/KfXYIZWbw==} engines: {node: '>= 0.4'} - esbuild@0.24.0: - resolution: {integrity: sha512-FuLPevChGDshgSicjisSooU0cemp/sGXR841D5LHMB7mTVOmsEHcAxaH3irL53+8YDIeVNQEySh4DaYU/iuPqQ==} + esbuild@0.24.2: + resolution: {integrity: sha512-+9egpBW8I3CD5XPe0n6BfT5fxLzxrlDzqydF3aviG+9ni1lDC/OvMHcxqEFV0+LANZG5R1bFMWfUrjVsdwxJvA==} engines: {node: '>=18'} hasBin: true @@ -2075,11 +2094,11 @@ packages: resolution: {integrity: sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==} engines: {node: '>=10'} - eslint-plugin-oxlint@0.15.2: - resolution: {integrity: sha512-/Ff9m+qVPRqqRJO9J0fqCnjPolY7Az2rKZMmc2gtTofvlHmYFhbBnwTGMMulM1eUUJ+/a7WbAc1V+Pho74pHfA==} + eslint-plugin-oxlint@0.15.5: + resolution: {integrity: sha512-oPkAGZ2ZJfHmHPiVa+aMN7Sotw1Hh/ZKJnxWnrlhVTQzgOBox9lXG0rHvYeyeewSLjuL/hyT67+IZ64nw8k55g==} - eslint-plugin-perfectionist@4.4.0: - resolution: {integrity: sha512-B78pWxCsA2sClourpWEmWziCcjEsAEyxsNV5G6cxxteu/NI0/2en9XZUONf5e/+O+dgoLZsEPHQEhnIxJcnUvA==} + eslint-plugin-perfectionist@4.6.0: + resolution: {integrity: sha512-kOswTebUK0LlYExRwqz7YQtvyTUIRsKfp8XrwBBeHGh2e8MBOS6K+7VvG6HpmNckyKySi1I96uPeAlptMFGcRQ==} engines: {node: ^18.0.0 || >=20.0.0} peerDependencies: eslint: '>=8.0.0' @@ -2154,8 +2173,8 @@ packages: fast-fifo@1.3.2: resolution: {integrity: sha512-/d9sfos4yxzpwkDkuN7k2SqFKtYNmCTzgfEpz82x34IM9/zc8KGxQoXg1liNC/izpRM/MBdt44Nmx41ZWqk+FQ==} - fast-glob@3.3.2: - resolution: {integrity: sha512-oX2ruAFQwf/Orj8m737Y5adxDQO0LAB7/S5MnxCdTNDd4p6BsyIVsv9JQsATbTSq8KHRpLwIHbVlUNatxd+1Ow==} + fast-glob@3.3.3: + resolution: {integrity: sha512-7MptL8U0cqcFdzIzwOTHoilX9x5BrNqye7Z/LuC7kCMRio1EMSyqRK3BEAUD7sXRq4iT4AzTVuZdhgQ2TCvYLg==} engines: {node: '>=8.6.0'} fast-json-stable-stringify@2.1.0: @@ -2164,15 +2183,15 @@ packages: fast-levenshtein@2.0.6: resolution: {integrity: sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==} - fast-uri@3.0.3: - resolution: {integrity: sha512-aLrHthzCjH5He4Z2H9YZ+v6Ujb9ocRuW6ZzkJQOrTxleEijANq4v1TsaPaVG1PZcuurEzrLcWRyYBYXD5cEiaw==} + fast-uri@3.0.5: + resolution: {integrity: sha512-5JnBCWpFlMo0a3ciDy/JckMzzv1U9coZrIhedq+HXxxUfDTAiS0LA8OKVao4G9BxmCVck/jtA5r3KAtRWEyD8Q==} fastest-levenshtein@1.0.16: resolution: {integrity: sha512-eRnCtTTtGZFpQCwhJiUOuxPQWRXVKYDn0b2PeHfXL6/Zi53SLAzAHfVhVWK2AryC/WH05kGfxhFIPvTF0SXQzg==} engines: {node: '>= 4.9.1'} - fastq@1.17.1: - resolution: {integrity: sha512-sRVD3lWVIXWg6By68ZN7vho9a1pQcN/WBFaAAsDDFzlJjvoGx0P8z7V1t72grFJfJhu3YPZBuu25f7Kaw2jN1w==} + fastq@1.18.0: + resolution: {integrity: sha512-QKHXPW0hD8g4UET03SdOdunzSouc9N4AuHdsX8XNcTsuz+yYFILVNIX4l9yHABMhiEI9Db0JTTIpu0wB+Y1QQw==} fdir@6.4.2: resolution: {integrity: sha512-KnhMXsKSPZlAhp7+IjUkRZKPb4fUyccpDrdFXbi4QL1qkmFh9kVY09Yox+n4MaOb3lHZ1Tv829C3oaaXoMYPDQ==} @@ -2247,8 +2266,12 @@ packages: resolution: {integrity: sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==} engines: {node: '>=6.9.0'} - get-intrinsic@1.2.6: - resolution: {integrity: sha512-qxsEs+9A+u85HhllWJJFicJfPDhRmjzoYdl64aMWW9yRIJmSyxdn8IEkuIM530/7T+lv0TIHd8L6Q/ra0tEoeA==} + get-intrinsic@1.2.7: + resolution: {integrity: sha512-VW6Pxhsrk0KAOqs3WEd0klDiF/+V7gQOpAvY1jVU/LHmaD/kQO4523aiJuikX/QAKYiW6x8Jh+RJej1almdtCA==} + engines: {node: '>= 0.4'} + + get-proto@1.0.1: + resolution: {integrity: sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g==} engines: {node: '>= 0.4'} get-stream@6.0.1: @@ -2419,8 +2442,8 @@ packages: resolution: {integrity: sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==} engines: {node: '>=8'} - is-generator-function@1.0.10: - resolution: {integrity: sha512-jsEjy9l3yiXEQ+PsXdmBwEPcOxaXWLspKdplFUVI9vq1iZgIekeC0L167qeu86czQaxed3q/Uzuw0swL0irL8A==} + is-generator-function@1.1.0: + resolution: {integrity: sha512-nPUB5km40q9e8UfN/Zc24eLlzdSf9OfKByBw9CIdw4H1giPMeA0OIJvbchsCu4npfI2QcMVBsGEBHKZ7wLTWmQ==} engines: {node: '>= 0.4'} is-glob@4.0.3: @@ -2443,6 +2466,10 @@ packages: resolution: {integrity: sha512-VRSzKkbMm5jMDoKLbltAkFQ5Qr7VDiTFGXxYFXXowVj387GeGNOCsOH6Msy00SGZ3Fp84b1Naa1psqgcCIEP5Q==} engines: {node: '>=0.10.0'} + is-regex@1.2.1: + resolution: {integrity: sha512-MjYsKHO5O7mCsmRGxWcLWheFqN9DJ/2TmngvjKXihe6efViPqc274+Fx/4fYj/r03+ESvBdTXK0V6tA3rgez1g==} + engines: {node: '>= 0.4'} + is-stream@2.0.1: resolution: {integrity: sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==} engines: {node: '>=8'} @@ -2520,10 +2547,6 @@ packages: resolution: {integrity: sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==} engines: {node: '>=0.10.0'} - kleur@4.1.5: - resolution: {integrity: sha512-o+NO+8WrRiQEE4/7nwRJhN1HWpVmJm511pBHUxPLtp0BUISzlBplORYSmTclCnJvQq2tKu/sgl3xVpkc7ZWuQQ==} - engines: {node: '>=6'} - knip@5.41.1: resolution: {integrity: sha512-yNpCCe2REU7U3VRvMASnXSEtfEC2HmOoDW9Vp9teQ9FktJYnuagvSZD3xWq8Ru7sPABkmvbC5TVWuMzIaeADNA==} engines: {node: '>=18.6.0'} @@ -2561,9 +2584,12 @@ packages: lodash.truncate@4.4.2: resolution: {integrity: sha512-jttmRe7bRse52OsWIMDLaXxWqRAmtIUccAQ3garviCqJjafXOfNMO0yMfNpdD6zbGaTU0P5Nz7e7gAT6cKmJRw==} - log-symbols@7.0.0: - resolution: {integrity: sha512-zrc91EDk2M+2AXo/9BTvK91pqb7qrPg2nX/Hy+u8a5qQlbaOflCKO+6SqgZ+M+xUFxGdKTgwnGiL96b1W3ikRA==} - engines: {node: '>=18'} + loglevel-plugin-prefix@0.8.4: + resolution: {integrity: sha512-WpG9CcFAOjz/FtNht+QJeGpvVl/cdR6P0z6OcXSkr8wFJOsV2GRj2j10JLfjuA4aYkcKCNIEqRGCyTife9R8/g==} + + loglevel@1.9.2: + resolution: {integrity: sha512-HgMmCqIJSAKqo68l0rS2AanEWfkxaZ5wNiEFb5ggm08lDs9Xl2KxBlX3PTcaD2chBM1gXAYf491/M2Rv8Jwayg==} + engines: {node: '>= 0.6.0'} lowercase-keys@3.0.0: resolution: {integrity: sha512-ozCC6gdQ+glXOQsveKD0YsDy8DSQFjDTz4zyzEHNV5+JP5D62LmfDZ6o1cycFx9ouG940M5dE8C8CTewdj2YWQ==} @@ -2716,8 +2742,8 @@ packages: os-browserify@0.3.0: resolution: {integrity: sha512-gjcpUc3clBf9+210TRaDWbf+rZZZEshZ+DlXMRCeAjp0xhTrnQsKHypIy1J3d5hKdUzj69t708EHtU8P6bUn0A==} - oxlint@0.15.3: - resolution: {integrity: sha512-kOAt0EC/oluYTcfRu6yg8+QkYMq6uibvEW+hx5nKsX320+VYEw1ChNBRcfSLCtJwA+k6X/CGxk2MN2Nddw70sQ==} + oxlint@0.15.5: + resolution: {integrity: sha512-hpckVhX+oiDyxYk7rwHqxZAmtOAQxQbkvxGM9NTQ3dTQC8X/5zcoBA9cZdrjVENA2TXrjg7l2qmkkzX7seteoQ==} engines: {node: '>=14.*'} hasBin: true @@ -2785,8 +2811,8 @@ packages: pend@1.2.0: resolution: {integrity: sha512-F3asv42UuXchdzt+xXqfW1OGlVBe+mxa2mqI0pg5yAHZPvFmY3Y6drSf/GQ1A86WgWEN9Kzh/WrgKa6iGcHXLg==} - php-parser@3.2.1: - resolution: {integrity: sha512-WT5AMqe39ZdqAxp9Yp7uR6e3clBWlT1dxHHs49GmnDx2d+975NEiLSVy2tRGLdSC9tgdQOLiN1Yz54g1d2cZDQ==} + php-parser@3.2.2: + resolution: {integrity: sha512-voj3rzCJmEbwHwH3QteON28wA6K+JbcaJEofyUZkUXmcViiXofjbSbcE5PtqtjX6nstnnAEYCFoRq0mkjP5/cg==} picocolors@1.1.1: resolution: {integrity: sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==} @@ -2986,8 +3012,8 @@ packages: ripemd160@2.0.2: resolution: {integrity: sha512-ii4iagi25WusVoiC4B4lq7pbXfAp3D9v5CwfkY33vffw2+pkDjY1D8GaN7spsxvCSx8dkPqOZCEZyfxcmJG2IA==} - rollup@4.29.1: - resolution: {integrity: sha512-RaJ45M/kmJUzSWDs1Nnd5DdV4eerC98idtUOVr6FfKcgxqvjwHmxc5upLF9qZU9EpsVzzhleFahrT3shLuJzIw==} + rollup@4.30.1: + resolution: {integrity: sha512-mlJ4glW020fPuLi7DkM/lN97mYEZGWeqBnrljzN0gs7GLctqX3lNWxKQ7Gl712UAX+6fog/L3jh4gb7R6aVi3w==} engines: {node: '>=18.0.0', npm: '>=8.0.0'} hasBin: true @@ -3003,128 +3029,132 @@ packages: safe-buffer@5.2.1: resolution: {integrity: sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==} - sass-embedded-android-arm64@1.83.0: - resolution: {integrity: sha512-GBiCvM4a2rkWBLdYDxI6XYnprfk5U5c81g69RC2X6kqPuzxzx8qTArQ9M6keFK4+iDQ5N9QTwFCr0KbZTn+ZNQ==} + safe-regex-test@1.1.0: + resolution: {integrity: sha512-x/+Cz4YrimQxQccJf5mKEbIa1NzeCRNI5Ecl/ekmlYaampdNLPalVyIcCZNNH3MvmqBugV5TMYZXv0ljslUlaw==} + engines: {node: '>= 0.4'} + + sass-embedded-android-arm64@1.83.1: + resolution: {integrity: sha512-S63rlLPGCA9FCqYYOobDJrwcuBX0zbSOl7y0jT9DlfqeqNOkC6NIT1id6RpMFCs3uhd4gbBS2E/5WPv5J5qwbw==} engines: {node: '>=14.0.0'} cpu: [arm64] os: [android] - sass-embedded-android-arm@1.83.0: - resolution: {integrity: sha512-uwFSXzJlfbd4Px189xE5l+cxN8+TQpXdQgJec7TIrb4HEY7imabtpYufpVdqUVwT1/uiis5V4+qIEC4Vl5XObQ==} + sass-embedded-android-arm@1.83.1: + resolution: {integrity: sha512-FKfrmwDG84L5cfn8fmIew47qnCFFUdcoOTCzOw8ROItkRhLLH0hnIm6gEpG5T6OFf6kxzUxvE9D0FvYQUznZrw==} engines: {node: '>=14.0.0'} cpu: [arm] os: [android] - sass-embedded-android-ia32@1.83.0: - resolution: {integrity: sha512-5ATPdGo2SICqAhiJl/Z8KQ23zH4sGgobGgux0TnrNtt83uHZ+r+To/ubVJ7xTkZxed+KJZnIpolGD8dQyQqoTg==} + sass-embedded-android-ia32@1.83.1: + resolution: {integrity: sha512-AGlY2vFLJhF2hN0qOz12f4eDs6x0b5BUapOpgfRrqQLHIfJhxkvi39bInsiBgQ57U0jb4I7AaS2e2e+sj7+Rqw==} engines: {node: '>=14.0.0'} cpu: [ia32] os: [android] - sass-embedded-android-riscv64@1.83.0: - resolution: {integrity: sha512-aveknUOB8GZewOzVn2Uwk+DKcncTR50Q6vtzslNMGbYnxtgQNHzy8A1qVEviNUruex+pHofppeMK4iMPFAbiEQ==} + sass-embedded-android-riscv64@1.83.1: + resolution: {integrity: sha512-OyU4AnfAUVd/wBaT60XvHidmQdaEsVUnxvI71oyPM/id1v97aWTZX3SmGkwGb7uA/q6Soo2uNalgvOSNJn7PwA==} engines: {node: '>=14.0.0'} cpu: [riscv64] os: [android] - sass-embedded-android-x64@1.83.0: - resolution: {integrity: sha512-WqIay/72ncyf9Ph4vS742J3a73wZihWmzFUwpn1OD6lme1Aj4eWzWIve5IVnlTEJgcZcDHu6ECID9IZgehJKoA==} + sass-embedded-android-x64@1.83.1: + resolution: {integrity: sha512-NY5rwffhF4TnhXVErZnfFIjHqU3MNoWxCuSHumRN3dDI8hp8+IF59W5+Qw9AARlTXvyb+D0u5653aLSea5F40w==} engines: {node: '>=14.0.0'} cpu: [x64] os: [android] - sass-embedded-darwin-arm64@1.83.0: - resolution: {integrity: sha512-XQl9QqgxFFIPm/CzHhmppse5o9ocxrbaAdC2/DAnlAqvYWBBtgFqPjGoYlej13h9SzfvNoogx+y9r+Ap+e+hYg==} + sass-embedded-darwin-arm64@1.83.1: + resolution: {integrity: sha512-w1SBcSkIgIWgUfB7IKcPoTbSwnS3Kag5PVv3e3xfW6ZCsDweYZLQntUd2WGgaoekdm1uIbVuvPxnDH2t880iGQ==} engines: {node: '>=14.0.0'} cpu: [arm64] os: [darwin] - sass-embedded-darwin-x64@1.83.0: - resolution: {integrity: sha512-ERQ7Tvp1kFOW3ux4VDFIxb7tkYXHYc+zJpcrbs0hzcIO5ilIRU2tIOK1OrNwrFO6Qxyf7AUuBwYKLAtIU/Nz7g==} + sass-embedded-darwin-x64@1.83.1: + resolution: {integrity: sha512-RWrmLtUhEP5kvcGOAFdr99/ebZ/eW9z3FAktLldvgl2k96WSTC1Zr2ctL0E+Y+H3uLahEZsshIFk6RkVIRKIsA==} engines: {node: '>=14.0.0'} cpu: [x64] os: [darwin] - sass-embedded-linux-arm64@1.83.0: - resolution: {integrity: sha512-syEAVTJt4qhaMLxrSwOWa46zdqHJdnqJkLUK+t9aCr8xqBZLPxSUeIGji76uOehQZ1C+KGFj6n9xstHN6wzOJw==} + sass-embedded-linux-arm64@1.83.1: + resolution: {integrity: sha512-HVIytzj8OO18fmBY6SVRIYErcJ+Nd9a5RNF6uArav/CqvwPLATlUV8dwqSyWQIzSsQUhDF/vFIlJIoNLKKzD3A==} engines: {node: '>=14.0.0'} cpu: [arm64] os: [linux] - sass-embedded-linux-arm@1.83.0: - resolution: {integrity: sha512-baG9RYBJxUFmqwDNC9h9ZFElgJoyO3jgHGjzEZ1wHhIS9anpG+zZQvO8bHx3dBpKEImX+DBeLX+CxsFR9n81gQ==} + sass-embedded-linux-arm@1.83.1: + resolution: {integrity: sha512-y7rHuRgjg2YM284rin068PsEdthPljSGb653Slut5Wba4A2IP11UNVraSl6Je2AYTuoPRjQX0g7XdsrjXlzC3g==} engines: {node: '>=14.0.0'} cpu: [arm] os: [linux] - sass-embedded-linux-ia32@1.83.0: - resolution: {integrity: sha512-RRBxQxMpoxu5+XcSSc6QR/o9asEwUzR8AbCS83RaXcdTIHTa/CccQsiAoDDoPlRsMTLqnzs0LKL4CfOsf7zBbA==} + sass-embedded-linux-ia32@1.83.1: + resolution: {integrity: sha512-/pc+jHllyvfaYYLTRCoXseRc4+V3Z7IDPqsviTcfVdICAoR9mgK2RtIuIZanhm1NP/lDylDOgvj1NtjcA2dNvg==} engines: {node: '>=14.0.0'} cpu: [ia32] os: [linux] - sass-embedded-linux-musl-arm64@1.83.0: - resolution: {integrity: sha512-Y7juhPHClUO2H5O+u+StRy6SEAcwZ+hTEk5WJdEmo1Bb1gDtfHvJaWB/iFZJ2tW0W1e865AZeUrC4OcOFjyAQA==} + sass-embedded-linux-musl-arm64@1.83.1: + resolution: {integrity: sha512-wjSIYYqdIQp3DjliSTYNFg04TVqQf/3Up/Stahol0Qf/TTjLkjHHtT2jnDaZI5GclHi2PVJqQF3wEGB8bGJMzQ==} engines: {node: '>=14.0.0'} cpu: [arm64] os: [linux] - sass-embedded-linux-musl-arm@1.83.0: - resolution: {integrity: sha512-Yc7u2TelCfBab+PRob9/MNJFh3EooMiz4urvhejXkihTiKSHGCv5YqDdtWzvyb9tY2Jb7YtYREVuHwfdVn3dTQ==} + sass-embedded-linux-musl-arm@1.83.1: + resolution: {integrity: sha512-sFM8GXOVoeR91j9MiwNRcFXRpTA7u4185SaGuvUjcRMb84mHvtWOJPGDvgZqbWdVClBRJp6J7+CShliWngy/og==} engines: {node: '>=14.0.0'} cpu: [arm] os: [linux] - sass-embedded-linux-musl-ia32@1.83.0: - resolution: {integrity: sha512-arQeYwGmwXV8byx5G1PtSzZWW1jbkfR5qrIHMEbTFSAvAxpqjgSvCvrHMOFd73FcMxVaYh4BX9LQNbKinkbEdg==} + sass-embedded-linux-musl-ia32@1.83.1: + resolution: {integrity: sha512-iwhTH5gwmoGt3VH6dn4WV8N6eWvthKAvUX5XPURq7e9KEsc7QP8YNHagwaAJh7TAPopb32buyEg6oaUmzxUI+Q==} engines: {node: '>=14.0.0'} cpu: [ia32] os: [linux] - sass-embedded-linux-musl-riscv64@1.83.0: - resolution: {integrity: sha512-E6uzlIWz59rut+Z3XR6mLG915zNzv07ISvj3GUNZENdHM7dF8GQ//ANoIpl5PljMQKp89GnYdvo6kj2gnaBf/g==} + sass-embedded-linux-musl-riscv64@1.83.1: + resolution: {integrity: sha512-FjFNWHU1n0Q6GpK1lAHQL5WmzlPjL8DTVLkYW2A/dq8EsutAdi3GfpeyWZk9bte8kyWdmPUWG3BHlnQl22xdoA==} engines: {node: '>=14.0.0'} cpu: [riscv64] os: [linux] - sass-embedded-linux-musl-x64@1.83.0: - resolution: {integrity: sha512-eAMK6tyGqvqr21r9g8BnR3fQc1rYFj85RGduSQ3xkITZ6jOAnOhuU94N5fwRS852Hpws0lXhET+7JHXgg3U18w==} + sass-embedded-linux-musl-x64@1.83.1: + resolution: {integrity: sha512-BUfYR5TIDvgGHWhxSIKwTJocXU88ECZ0BW89RJqtvr7m83fKdf5ylTFCOieU7BwcA7SORUeZzcQzVFIdPUM3BQ==} engines: {node: '>=14.0.0'} cpu: [x64] os: [linux] - sass-embedded-linux-riscv64@1.83.0: - resolution: {integrity: sha512-Ojpi78pTv02sy2fUYirRGXHLY3fPnV/bvwuC2i5LwPQw2LpCcFyFTtN0c5h4LJDk9P6wr+/ZB/JXU8tHIOlK+Q==} + sass-embedded-linux-riscv64@1.83.1: + resolution: {integrity: sha512-KOBGSpMrJi8y+H+za3vAAVQImPUvQa5eUrvTbbOl+wkU7WAGhOu8xrxgmYYiz3pZVBBcfRjz4I2jBcDFKJmWSw==} engines: {node: '>=14.0.0'} cpu: [riscv64] os: [linux] - sass-embedded-linux-x64@1.83.0: - resolution: {integrity: sha512-3iLjlXdoPfgZRtX4odhRvka1BQs5mAXqfCtDIQBgh/o0JnGPzJIWWl9bYLpHxK8qb+uyVBxXYgXpI0sCzArBOw==} + sass-embedded-linux-x64@1.83.1: + resolution: {integrity: sha512-swUsMHKqlEU9dZQ/I5WADDaXz+QkmJS27x/Oeh+oz41YgZ0ppKd0l4Vwjn0LgOQn+rxH1zLFv6xXDycvj68F/w==} engines: {node: '>=14.0.0'} cpu: [x64] os: [linux] - sass-embedded-win32-arm64@1.83.0: - resolution: {integrity: sha512-iOHw/8/t2dlTW3lOFwG5eUbiwhEyGWawivlKWJ8lkXH7fjMpVx2VO9zCFAm8RvY9xOHJ9sf1L7g5bx3EnNP9BQ==} + sass-embedded-win32-arm64@1.83.1: + resolution: {integrity: sha512-6lONEBN5TaFD5L/y68zUugryXqm4RAFuLdaOPeZQRu+7ay/AmfhtFYfE5gRssnIcIx1nlcoq7zA3UX+SN2jo1Q==} engines: {node: '>=14.0.0'} cpu: [arm64] os: [win32] - sass-embedded-win32-ia32@1.83.0: - resolution: {integrity: sha512-2PxNXJ8Pad4geVcTXY4rkyTr5AwbF8nfrCTDv0ulbTvPhzX2mMKEGcBZUXWn5BeHZTBc6whNMfS7d5fQXR9dDQ==} + sass-embedded-win32-ia32@1.83.1: + resolution: {integrity: sha512-HxZDkAE9n6Gb8Rz6xd67VHuo5FkUSQ4xPb7cHKa4pE0ndwH5Oc0uEhbqjJobpgmnuTm1rQYNU2nof1sFhy2MFA==} engines: {node: '>=14.0.0'} cpu: [ia32] os: [win32] - sass-embedded-win32-x64@1.83.0: - resolution: {integrity: sha512-muBXkFngM6eLTNqOV0FQi7Dv9s+YRQ42Yem26mosdan/GmJQc81deto6uDTgrYn+bzFNmiXcOdfm+0MkTWK3OQ==} + sass-embedded-win32-x64@1.83.1: + resolution: {integrity: sha512-5Q0aPfUaqRek8Ee1AqTUIC0o6yQSA8QwyhCgh7upsnHG3Ltm8pkJOYjzm+UgYPJeoMNppDjdDlRGQISE7qzd4g==} engines: {node: '>=14.0.0'} cpu: [x64] os: [win32] - sass-embedded@1.83.0: - resolution: {integrity: sha512-/8cYZeL39evUqe0o//193na51Q1VWZ61qhxioQvLJwOtWIrX+PgNhCyD8RSuTtmzc4+6+waFZf899bfp/MCUwA==} + sass-embedded@1.83.1: + resolution: {integrity: sha512-LdKG6nxLEzpXbMUt0if12PhUNonGvy91n7IWHOZRZjvA6AWm9oVdhpO+KEXN/Sc+jjGvQeQcav9+Z8DwmII/pA==} engines: {node: '>=16.0.0'} hasBin: true @@ -3280,8 +3310,8 @@ packages: style-search@0.1.0: resolution: {integrity: sha512-Dj1Okke1C3uKKwQcetra4jSuk0DqbzbYtXipzFlFMZtowbF1x7BKJwB9AayVMyFARvU8EDrZdcax4At/452cAg==} - stylelint-config-clean-order@6.1.0: - resolution: {integrity: sha512-Xe1U0stw57Evdcx+7q7XYAniyE7XAKv/bwfH9LcsFCcKTPZflzTiJLXGkQUsPMlA4cfMyxEebqm5bRN2doTD3w==} + stylelint-config-clean-order@7.0.0: + resolution: {integrity: sha512-R28w1xNliIbem3o+VIrNjAU8cMgxrGlDoXVqWW7lJ1OvSDsmNGj5aKSW6Xm7i5PK4E99T3Hs19BJFni5IbE56g==} peerDependencies: stylelint: '>=14' @@ -3419,11 +3449,11 @@ packages: resolution: {integrity: sha512-lbDrTLVsHhOMljPscd0yitpozq7Ga2M5Cvez5AjGg8GASBjtt6iERCAJ93yommPmz62fb45oFIXHEZ3u9bfJEA==} engines: {node: '>=14.16'} - ts-api-utils@1.4.3: - resolution: {integrity: sha512-i3eMG77UTMD0hZhgRS562pv83RC6ukSAC2GMNWc+9dieh/+jDM5u5YG+NHX6VNDRHQcHwmsTHctP9LhbC3WxVw==} - engines: {node: '>=16'} + ts-api-utils@2.0.0: + resolution: {integrity: sha512-xCt/TOAc+EOHS1XPnijD3/yzpH6qg2xppZO1YDqGoVsNXfQfzHpOdNuXwrwOU8u4ITXJyDCTyt8w5g1sZv9ynQ==} + engines: {node: '>=18.12'} peerDependencies: - typescript: '>=4.2.0' + typescript: '>=4.8.4' ts-pattern@5.6.0: resolution: {integrity: sha512-SL8u60X5+LoEy9tmQHWCdPc2hhb2pKI6I1tU5Jue3v8+iRqZdcT3mWPwKKJy1fMfky6uha82c8ByHAE8PMhKHw==} @@ -3448,8 +3478,8 @@ packages: resolution: {integrity: sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==} engines: {node: '>= 0.8.0'} - typescript-eslint@8.18.1: - resolution: {integrity: sha512-Mlaw6yxuaDEPQvb/2Qwu3/TfgeBHy9iTJ3mTwe7OvpPmF6KPQjVOfGyEJpPv6Ez2C34OODChhXrzYw/9phI0MQ==} + typescript-eslint@8.19.1: + resolution: {integrity: sha512-LKPUQpdEMVOeKluHi8md7rwLcoXHhwvWp3x+sJkMuq3gGm9yaYJtPo8sRZSblMFJ5pcOGCAak/scKf1mvZDlQw==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} peerDependencies: eslint: ^8.57.0 || ^9.0.0 @@ -3491,8 +3521,8 @@ packages: resolution: {integrity: sha512-6t3foTQI9qne+OZoVQB/8x8rk2k1eVy1gRXhV3oFQ5T6R1dqQ1xtin3XqSlx3+ATBkliTaR/hHyJBm+LVPNM8w==} engines: {node: '>=4'} - update-browserslist-db@1.1.1: - resolution: {integrity: sha512-R8UzCaa9Az+38REPiJ1tXlImTJXlVfgHZsglwBD/k6nj76ctsH1E3q4doGrukiLQd3sGQYu56r5+lo5r94l29A==} + update-browserslist-db@1.1.2: + resolution: {integrity: sha512-PPypAm5qvlD7XMZC3BujecnaOxwhrtoFR+Dqkk5Aa/6DssiH0ibKoketaj9w8LP7Bont1rYeoV5plxD7RTEPRg==} hasBin: true peerDependencies: browserslist: '>= 4.21.0' @@ -3510,8 +3540,8 @@ packages: util@0.12.5: resolution: {integrity: sha512-kZf/K6hEIrWHI6XqOFUiiMa+79wE/D8Q+NCNAWclkyg3b4d2k7s0QGepNjiABc+aR3N1PAyHL7p6UcLY6LmrnA==} - valibot@1.0.0-beta.9: - resolution: {integrity: sha512-yEX8gMAZ2R1yI2uwOO4NCtVnJQx36zn3vD0omzzj9FhcoblvPukENIiRZXKZwCnqSeV80bMm8wNiGhQ0S8fiww==} + valibot@1.0.0-beta.11: + resolution: {integrity: sha512-Ztl5Iks1Ql7Z6CwkS5oyqguN3G8tmUiNlsHpqbDt6DLMpm+eu+n8Q7f921gI3uHvNZ8xDVkd4cEJP5t+lELOfw==} peerDependencies: typescript: '>=5' peerDependenciesMeta: @@ -3529,8 +3559,8 @@ packages: peerDependencies: vite: ^2.0.0 || ^3.0.0 || ^4.0.0 || ^5.0.0 - vite-plugin-valibot-env@0.9.2: - resolution: {integrity: sha512-eVScFRYYufR5q/QJf+Ayr9ckHgg2zNJDIMMP8qIawTUeInRhsI0Q7n0BnJmrS5lOMEM9VLZrEXnPTa9aTa/TvA==} + vite-plugin-valibot-env@0.9.3: + resolution: {integrity: sha512-ybWoQI3u9LdxeTnQkoASplUCgHIGUUs6JWWjSrVPKrcMPLxPv5QkA2EUFhkxKnwZ/KQX2k7YQfavN54CMFvQNQ==} engines: {node: ^18.0.0 || ^20.0.0 || >=22.0.0} peerDependencies: valibot: '>=0.30 <2.0.0' @@ -3544,8 +3574,8 @@ packages: vite: optional: true - vite@6.0.5: - resolution: {integrity: sha512-akD5IAH/ID5imgue2DYhzsEwCi0/4VKY31uhMLEYJwPP4TiUp8pL5PIK+Wo7H8qT8JY9i+pVfPydcFPYD1EL7g==} + vite@6.0.7: + resolution: {integrity: sha512-RDt8r/7qx9940f8FcOIAH9PTViRrghKaK2K1jY3RaAURrEUbm9Du1mJ72G+jlhtG3WwodnfzY8ORQZbBavZEAQ==} engines: {node: ^18.0.0 || ^20.0.0 || >=22.0.0} hasBin: true peerDependencies: @@ -3629,10 +3659,6 @@ packages: resolution: {integrity: sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==} engines: {node: '>=10'} - yoctocolors@2.1.1: - resolution: {integrity: sha512-GQHQqAopRhwU8Kt1DDM8NjibDXHC8eoh1erhGAJPEyveY9qqVeXvVikNKrDz69sHowPMorbPUrH/mx8c50eiBQ==} - engines: {node: '>=18'} - zod-validation-error@3.4.0: resolution: {integrity: sha512-ZOPR9SVY6Pb2qqO5XHt+MkkTRxGXb4EVtnjc9JpXUOtUB1T9Ru7mZOT361AN3MsetVe7R0a1KZshJDZdgp9miQ==} engines: {node: '>=18.0.0'} @@ -3693,7 +3719,7 @@ snapshots: dependencies: '@babel/compat-data': 7.26.3 '@babel/helper-validator-option': 7.25.9 - browserslist: 4.24.3 + browserslist: 4.24.4 lru-cache: 5.1.1 semver: 6.3.1 @@ -4249,7 +4275,7 @@ snapshots: babel-plugin-polyfill-corejs2: 0.4.12(@babel/core@7.26.0) babel-plugin-polyfill-corejs3: 0.10.6(@babel/core@7.26.0) babel-plugin-polyfill-regenerator: 0.6.3(@babel/core@7.26.0) - core-js-compat: 3.39.0 + core-js-compat: 3.40.0 semver: 6.3.1 transitivePeerDependencies: - supports-color @@ -4415,76 +4441,79 @@ snapshots: '@dual-bundle/import-meta-resolve@4.1.0': {} - '@esbuild/aix-ppc64@0.24.0': + '@esbuild/aix-ppc64@0.24.2': optional: true - '@esbuild/android-arm64@0.24.0': + '@esbuild/android-arm64@0.24.2': optional: true - '@esbuild/android-arm@0.24.0': + '@esbuild/android-arm@0.24.2': optional: true - '@esbuild/android-x64@0.24.0': + '@esbuild/android-x64@0.24.2': optional: true - '@esbuild/darwin-arm64@0.24.0': + '@esbuild/darwin-arm64@0.24.2': optional: true - '@esbuild/darwin-x64@0.24.0': + '@esbuild/darwin-x64@0.24.2': optional: true - '@esbuild/freebsd-arm64@0.24.0': + '@esbuild/freebsd-arm64@0.24.2': optional: true - '@esbuild/freebsd-x64@0.24.0': + '@esbuild/freebsd-x64@0.24.2': optional: true - '@esbuild/linux-arm64@0.24.0': + '@esbuild/linux-arm64@0.24.2': optional: true - '@esbuild/linux-arm@0.24.0': + '@esbuild/linux-arm@0.24.2': optional: true - '@esbuild/linux-ia32@0.24.0': + '@esbuild/linux-ia32@0.24.2': optional: true - '@esbuild/linux-loong64@0.24.0': + '@esbuild/linux-loong64@0.24.2': optional: true - '@esbuild/linux-mips64el@0.24.0': + '@esbuild/linux-mips64el@0.24.2': optional: true - '@esbuild/linux-ppc64@0.24.0': + '@esbuild/linux-ppc64@0.24.2': optional: true - '@esbuild/linux-riscv64@0.24.0': + '@esbuild/linux-riscv64@0.24.2': optional: true - '@esbuild/linux-s390x@0.24.0': + '@esbuild/linux-s390x@0.24.2': optional: true - '@esbuild/linux-x64@0.24.0': + '@esbuild/linux-x64@0.24.2': optional: true - '@esbuild/netbsd-x64@0.24.0': + '@esbuild/netbsd-arm64@0.24.2': optional: true - '@esbuild/openbsd-arm64@0.24.0': + '@esbuild/netbsd-x64@0.24.2': optional: true - '@esbuild/openbsd-x64@0.24.0': + '@esbuild/openbsd-arm64@0.24.2': optional: true - '@esbuild/sunos-x64@0.24.0': + '@esbuild/openbsd-x64@0.24.2': optional: true - '@esbuild/win32-arm64@0.24.0': + '@esbuild/sunos-x64@0.24.2': optional: true - '@esbuild/win32-ia32@0.24.0': + '@esbuild/win32-arm64@0.24.2': optional: true - '@esbuild/win32-x64@0.24.0': + '@esbuild/win32-ia32@0.24.2': + optional: true + + '@esbuild/win32-x64@0.24.2': optional: true '@eslint-community/eslint-utils@4.4.1(eslint@9.17.0(jiti@2.4.2))': @@ -4643,30 +4672,30 @@ snapshots: '@nodelib/fs.walk@1.2.8': dependencies: '@nodelib/fs.scandir': 2.1.5 - fastq: 1.17.1 + fastq: 1.18.0 - '@oxlint/darwin-arm64@0.15.3': + '@oxlint/darwin-arm64@0.15.5': optional: true - '@oxlint/darwin-x64@0.15.3': + '@oxlint/darwin-x64@0.15.5': optional: true - '@oxlint/linux-arm64-gnu@0.15.3': + '@oxlint/linux-arm64-gnu@0.15.5': optional: true - '@oxlint/linux-arm64-musl@0.15.3': + '@oxlint/linux-arm64-musl@0.15.5': optional: true - '@oxlint/linux-x64-gnu@0.15.3': + '@oxlint/linux-x64-gnu@0.15.5': optional: true - '@oxlint/linux-x64-musl@0.15.3': + '@oxlint/linux-x64-musl@0.15.5': optional: true - '@oxlint/win32-arm64@0.15.3': + '@oxlint/win32-arm64@0.15.5': optional: true - '@oxlint/win32-x64@0.15.3': + '@oxlint/win32-x64@0.15.5': optional: true '@parcel/watcher-android-arm64@2.5.0': @@ -4733,7 +4762,7 @@ snapshots: '@prettier/plugin-php@0.22.2(prettier@3.4.2)': dependencies: linguist-languages: 7.27.0 - php-parser: 3.2.1 + php-parser: 3.2.2 prettier: 3.4.2 '@prettier/plugin-xml@3.4.1(prettier@3.4.2)': @@ -4741,108 +4770,108 @@ snapshots: '@xml-tools/parser': 1.0.11 prettier: 3.4.2 - '@rollup/plugin-inject@5.0.5(rollup@4.29.1)': + '@rollup/plugin-inject@5.0.5(rollup@4.30.1)': dependencies: - '@rollup/pluginutils': 5.1.4(rollup@4.29.1) + '@rollup/pluginutils': 5.1.4(rollup@4.30.1) estree-walker: 2.0.2 magic-string: 0.30.17 optionalDependencies: - rollup: 4.29.1 + rollup: 4.30.1 - '@rollup/pluginutils@5.1.4(rollup@4.29.1)': + '@rollup/pluginutils@5.1.4(rollup@4.30.1)': dependencies: '@types/estree': 1.0.6 estree-walker: 2.0.2 picomatch: 4.0.2 optionalDependencies: - rollup: 4.29.1 + rollup: 4.30.1 - '@rollup/rollup-android-arm-eabi@4.29.1': + '@rollup/rollup-android-arm-eabi@4.30.1': optional: true - '@rollup/rollup-android-arm64@4.29.1': + '@rollup/rollup-android-arm64@4.30.1': optional: true - '@rollup/rollup-darwin-arm64@4.29.1': + '@rollup/rollup-darwin-arm64@4.30.1': optional: true - '@rollup/rollup-darwin-x64@4.29.1': + '@rollup/rollup-darwin-x64@4.30.1': optional: true - '@rollup/rollup-freebsd-arm64@4.29.1': + '@rollup/rollup-freebsd-arm64@4.30.1': optional: true - '@rollup/rollup-freebsd-x64@4.29.1': + '@rollup/rollup-freebsd-x64@4.30.1': optional: true - '@rollup/rollup-linux-arm-gnueabihf@4.29.1': + '@rollup/rollup-linux-arm-gnueabihf@4.30.1': optional: true - '@rollup/rollup-linux-arm-musleabihf@4.29.1': + '@rollup/rollup-linux-arm-musleabihf@4.30.1': optional: true - '@rollup/rollup-linux-arm64-gnu@4.29.1': + '@rollup/rollup-linux-arm64-gnu@4.30.1': optional: true - '@rollup/rollup-linux-arm64-musl@4.29.1': + '@rollup/rollup-linux-arm64-musl@4.30.1': optional: true - '@rollup/rollup-linux-loongarch64-gnu@4.29.1': + '@rollup/rollup-linux-loongarch64-gnu@4.30.1': optional: true - '@rollup/rollup-linux-powerpc64le-gnu@4.29.1': + '@rollup/rollup-linux-powerpc64le-gnu@4.30.1': optional: true - '@rollup/rollup-linux-riscv64-gnu@4.29.1': + '@rollup/rollup-linux-riscv64-gnu@4.30.1': optional: true - '@rollup/rollup-linux-s390x-gnu@4.29.1': + '@rollup/rollup-linux-s390x-gnu@4.30.1': optional: true - '@rollup/rollup-linux-x64-gnu@4.29.1': + '@rollup/rollup-linux-x64-gnu@4.30.1': optional: true - '@rollup/rollup-linux-x64-musl@4.29.1': + '@rollup/rollup-linux-x64-musl@4.30.1': optional: true - '@rollup/rollup-win32-arm64-msvc@4.29.1': + '@rollup/rollup-win32-arm64-msvc@4.30.1': optional: true - '@rollup/rollup-win32-ia32-msvc@4.29.1': + '@rollup/rollup-win32-ia32-msvc@4.30.1': optional: true - '@rollup/rollup-win32-x64-msvc@4.29.1': + '@rollup/rollup-win32-x64-msvc@4.30.1': optional: true '@sec-ant/readable-stream@0.4.1': {} - '@sentry-internal/browser-utils@8.47.0': + '@sentry-internal/browser-utils@8.48.0': dependencies: - '@sentry/core': 8.47.0 + '@sentry/core': 8.48.0 - '@sentry-internal/feedback@8.47.0': + '@sentry-internal/feedback@8.48.0': dependencies: - '@sentry/core': 8.47.0 + '@sentry/core': 8.48.0 - '@sentry-internal/replay-canvas@8.47.0': + '@sentry-internal/replay-canvas@8.48.0': dependencies: - '@sentry-internal/replay': 8.47.0 - '@sentry/core': 8.47.0 + '@sentry-internal/replay': 8.48.0 + '@sentry/core': 8.48.0 - '@sentry-internal/replay@8.47.0': + '@sentry-internal/replay@8.48.0': dependencies: - '@sentry-internal/browser-utils': 8.47.0 - '@sentry/core': 8.47.0 + '@sentry-internal/browser-utils': 8.48.0 + '@sentry/core': 8.48.0 - '@sentry/browser@8.47.0': + '@sentry/browser@8.48.0': dependencies: - '@sentry-internal/browser-utils': 8.47.0 - '@sentry-internal/feedback': 8.47.0 - '@sentry-internal/replay': 8.47.0 - '@sentry-internal/replay-canvas': 8.47.0 - '@sentry/core': 8.47.0 + '@sentry-internal/browser-utils': 8.48.0 + '@sentry-internal/feedback': 8.48.0 + '@sentry-internal/replay': 8.48.0 + '@sentry-internal/replay-canvas': 8.48.0 + '@sentry/core': 8.48.0 - '@sentry/core@8.47.0': {} + '@sentry/core@8.48.0': {} '@sindresorhus/is@5.6.0': {} @@ -4873,7 +4902,7 @@ snapshots: '@swc/counter': 0.1.3 '@xhmikosr/bin-wrapper': 13.0.5 commander: 8.3.0 - fast-glob: 3.3.2 + fast-glob: 3.3.3 minimatch: 9.0.5 piscina: 4.8.0 semver: 7.6.3 @@ -4953,101 +4982,101 @@ snapshots: '@types/json-schema@7.0.15': {} - '@types/node@22.10.2': + '@types/node@22.10.5': dependencies: undici-types: 6.20.0 '@types/trusted-types@2.0.7': {} - '@typescript-eslint/eslint-plugin@8.18.1(@typescript-eslint/parser@8.18.1(eslint@9.17.0(jiti@2.4.2))(typescript@5.8.0-dev.20241122))(eslint@9.17.0(jiti@2.4.2))(typescript@5.8.0-dev.20241122)': + '@typescript-eslint/eslint-plugin@8.19.1(@typescript-eslint/parser@8.19.1(eslint@9.17.0(jiti@2.4.2))(typescript@5.8.0-dev.20241122))(eslint@9.17.0(jiti@2.4.2))(typescript@5.8.0-dev.20241122)': dependencies: '@eslint-community/regexpp': 4.12.1 - '@typescript-eslint/parser': 8.18.1(eslint@9.17.0(jiti@2.4.2))(typescript@5.8.0-dev.20241122) - '@typescript-eslint/scope-manager': 8.18.1 - '@typescript-eslint/type-utils': 8.18.1(eslint@9.17.0(jiti@2.4.2))(typescript@5.8.0-dev.20241122) - '@typescript-eslint/utils': 8.18.1(eslint@9.17.0(jiti@2.4.2))(typescript@5.8.0-dev.20241122) - '@typescript-eslint/visitor-keys': 8.18.1 + '@typescript-eslint/parser': 8.19.1(eslint@9.17.0(jiti@2.4.2))(typescript@5.8.0-dev.20241122) + '@typescript-eslint/scope-manager': 8.19.1 + '@typescript-eslint/type-utils': 8.19.1(eslint@9.17.0(jiti@2.4.2))(typescript@5.8.0-dev.20241122) + '@typescript-eslint/utils': 8.19.1(eslint@9.17.0(jiti@2.4.2))(typescript@5.8.0-dev.20241122) + '@typescript-eslint/visitor-keys': 8.19.1 eslint: 9.17.0(jiti@2.4.2) graphemer: 1.4.0 ignore: 5.3.2 natural-compare: 1.4.0 - ts-api-utils: 1.4.3(typescript@5.8.0-dev.20241122) + ts-api-utils: 2.0.0(typescript@5.8.0-dev.20241122) typescript: 5.8.0-dev.20241122 transitivePeerDependencies: - supports-color - '@typescript-eslint/parser@8.18.1(eslint@9.17.0(jiti@2.4.2))(typescript@5.8.0-dev.20241122)': + '@typescript-eslint/parser@8.19.1(eslint@9.17.0(jiti@2.4.2))(typescript@5.8.0-dev.20241122)': dependencies: - '@typescript-eslint/scope-manager': 8.18.1 - '@typescript-eslint/types': 8.18.1 - '@typescript-eslint/typescript-estree': 8.18.1(typescript@5.8.0-dev.20241122) - '@typescript-eslint/visitor-keys': 8.18.1 + '@typescript-eslint/scope-manager': 8.19.1 + '@typescript-eslint/types': 8.19.1 + '@typescript-eslint/typescript-estree': 8.19.1(typescript@5.8.0-dev.20241122) + '@typescript-eslint/visitor-keys': 8.19.1 debug: 4.4.0 eslint: 9.17.0(jiti@2.4.2) typescript: 5.8.0-dev.20241122 transitivePeerDependencies: - supports-color - '@typescript-eslint/scope-manager@8.18.1': + '@typescript-eslint/scope-manager@8.19.1': dependencies: - '@typescript-eslint/types': 8.18.1 - '@typescript-eslint/visitor-keys': 8.18.1 + '@typescript-eslint/types': 8.19.1 + '@typescript-eslint/visitor-keys': 8.19.1 - '@typescript-eslint/type-utils@8.18.1(eslint@9.17.0(jiti@2.4.2))(typescript@5.8.0-dev.20241122)': + '@typescript-eslint/type-utils@8.19.1(eslint@9.17.0(jiti@2.4.2))(typescript@5.8.0-dev.20241122)': dependencies: - '@typescript-eslint/typescript-estree': 8.18.1(typescript@5.8.0-dev.20241122) - '@typescript-eslint/utils': 8.18.1(eslint@9.17.0(jiti@2.4.2))(typescript@5.8.0-dev.20241122) + '@typescript-eslint/typescript-estree': 8.19.1(typescript@5.8.0-dev.20241122) + '@typescript-eslint/utils': 8.19.1(eslint@9.17.0(jiti@2.4.2))(typescript@5.8.0-dev.20241122) debug: 4.4.0 eslint: 9.17.0(jiti@2.4.2) - ts-api-utils: 1.4.3(typescript@5.8.0-dev.20241122) + ts-api-utils: 2.0.0(typescript@5.8.0-dev.20241122) typescript: 5.8.0-dev.20241122 transitivePeerDependencies: - supports-color - '@typescript-eslint/types@8.18.1': {} + '@typescript-eslint/types@8.19.1': {} - '@typescript-eslint/typescript-estree@8.18.1(typescript@5.8.0-dev.20241122)': + '@typescript-eslint/typescript-estree@8.19.1(typescript@5.8.0-dev.20241122)': dependencies: - '@typescript-eslint/types': 8.18.1 - '@typescript-eslint/visitor-keys': 8.18.1 + '@typescript-eslint/types': 8.19.1 + '@typescript-eslint/visitor-keys': 8.19.1 debug: 4.4.0 - fast-glob: 3.3.2 + fast-glob: 3.3.3 is-glob: 4.0.3 minimatch: 9.0.5 semver: 7.6.3 - ts-api-utils: 1.4.3(typescript@5.8.0-dev.20241122) + ts-api-utils: 2.0.0(typescript@5.8.0-dev.20241122) typescript: 5.8.0-dev.20241122 transitivePeerDependencies: - supports-color - '@typescript-eslint/utils@8.18.1(eslint@9.17.0(jiti@2.4.2))(typescript@5.8.0-dev.20241122)': + '@typescript-eslint/utils@8.19.1(eslint@9.17.0(jiti@2.4.2))(typescript@5.8.0-dev.20241122)': dependencies: '@eslint-community/eslint-utils': 4.4.1(eslint@9.17.0(jiti@2.4.2)) - '@typescript-eslint/scope-manager': 8.18.1 - '@typescript-eslint/types': 8.18.1 - '@typescript-eslint/typescript-estree': 8.18.1(typescript@5.8.0-dev.20241122) + '@typescript-eslint/scope-manager': 8.19.1 + '@typescript-eslint/types': 8.19.1 + '@typescript-eslint/typescript-estree': 8.19.1(typescript@5.8.0-dev.20241122) eslint: 9.17.0(jiti@2.4.2) typescript: 5.8.0-dev.20241122 transitivePeerDependencies: - supports-color - '@typescript-eslint/visitor-keys@8.18.1': + '@typescript-eslint/visitor-keys@8.19.1': dependencies: - '@typescript-eslint/types': 8.18.1 + '@typescript-eslint/types': 8.19.1 eslint-visitor-keys: 4.2.0 - '@vitejs/plugin-legacy@6.0.0(terser@5.36.0)(vite@6.0.5(@types/node@22.10.2)(jiti@2.4.2)(sass-embedded@1.83.0)(sass@1.80.6)(terser@5.36.0))': + '@vitejs/plugin-legacy@6.0.0(terser@5.36.0)(vite@6.0.7(@types/node@22.10.5)(jiti@2.4.2)(sass-embedded@1.83.1)(sass@1.80.6)(terser@5.36.0))': dependencies: '@babel/core': 7.26.0 '@babel/preset-env': 7.26.0(@babel/core@7.26.0) - browserslist: 4.24.3 - browserslist-to-esbuild: 2.1.1(browserslist@4.24.3) - core-js: 3.39.0 + browserslist: 4.24.4 + browserslist-to-esbuild: 2.1.1(browserslist@4.24.4) + core-js: 3.40.0 magic-string: 0.30.17 regenerator-runtime: 0.14.1 systemjs: 6.15.1 terser: 5.36.0 - vite: 6.0.5(@types/node@22.10.2)(jiti@2.4.2)(sass-embedded@1.83.0)(sass@1.80.6)(terser@5.36.0) + vite: 6.0.7(@types/node@22.10.5)(jiti@2.4.2)(sass-embedded@1.83.1)(sass@1.80.6)(terser@5.36.0) transitivePeerDependencies: - supports-color @@ -5148,7 +5177,7 @@ snapshots: ajv@8.17.1: dependencies: fast-deep-equal: 3.1.3 - fast-uri: 3.0.3 + fast-uri: 3.0.5 json-schema-traverse: 1.0.0 require-from-string: 2.0.2 @@ -5199,7 +5228,7 @@ snapshots: dependencies: '@babel/core': 7.26.0 '@babel/helper-define-polyfill-provider': 0.6.3(@babel/core@7.26.0) - core-js-compat: 3.39.0 + core-js-compat: 3.40.0 transitivePeerDependencies: - supports-color @@ -5214,7 +5243,7 @@ snapshots: balanced-match@2.0.0: {} - bare-events@2.5.0: + bare-events@2.5.3: optional: true base64-js@1.5.1: {} @@ -5319,17 +5348,17 @@ snapshots: dependencies: pako: 1.0.11 - browserslist-to-esbuild@2.1.1(browserslist@4.24.3): + browserslist-to-esbuild@2.1.1(browserslist@4.24.4): dependencies: - browserslist: 4.24.3 + browserslist: 4.24.4 meow: 13.2.0 - browserslist@4.24.3: + browserslist@4.24.4: dependencies: caniuse-lite: 1.0.30001690 - electron-to-chromium: 1.5.75 + electron-to-chromium: 1.5.79 node-releases: 2.0.19 - update-browserslist-db: 1.1.1(browserslist@4.24.3) + update-browserslist-db: 1.1.2(browserslist@4.24.4) buffer-builder@0.2.0: {} @@ -5367,13 +5396,13 @@ snapshots: dependencies: call-bind-apply-helpers: 1.0.1 es-define-property: 1.0.1 - get-intrinsic: 1.2.6 + get-intrinsic: 1.2.7 set-function-length: 1.2.2 call-bound@1.0.3: dependencies: call-bind-apply-helpers: 1.0.1 - get-intrinsic: 1.2.6 + get-intrinsic: 1.2.7 callsites@3.1.0: {} @@ -5384,6 +5413,8 @@ snapshots: ansi-styles: 4.3.0 supports-color: 7.2.0 + chalk@5.4.1: {} + chevrotain@7.1.1: dependencies: regexp-to-ast: 0.5.0 @@ -5433,11 +5464,11 @@ snapshots: convert-source-map@2.0.0: {} - core-js-compat@3.39.0: + core-js-compat@3.40.0: dependencies: - browserslist: 4.24.3 + browserslist: 4.24.4 - core-js@3.39.0: {} + core-js@3.40.0: {} core-util-is@1.0.3: {} @@ -5567,7 +5598,7 @@ snapshots: optionalDependencies: wcwidth: 1.0.1 - electron-to-chromium@1.5.75: {} + electron-to-chromium@1.5.79: {} elliptic@6.6.1: dependencies: @@ -5600,45 +5631,46 @@ snapshots: dependencies: es-errors: 1.3.0 - esbuild@0.24.0: + esbuild@0.24.2: optionalDependencies: - '@esbuild/aix-ppc64': 0.24.0 - '@esbuild/android-arm': 0.24.0 - '@esbuild/android-arm64': 0.24.0 - '@esbuild/android-x64': 0.24.0 - '@esbuild/darwin-arm64': 0.24.0 - '@esbuild/darwin-x64': 0.24.0 - '@esbuild/freebsd-arm64': 0.24.0 - '@esbuild/freebsd-x64': 0.24.0 - '@esbuild/linux-arm': 0.24.0 - '@esbuild/linux-arm64': 0.24.0 - '@esbuild/linux-ia32': 0.24.0 - '@esbuild/linux-loong64': 0.24.0 - '@esbuild/linux-mips64el': 0.24.0 - '@esbuild/linux-ppc64': 0.24.0 - '@esbuild/linux-riscv64': 0.24.0 - '@esbuild/linux-s390x': 0.24.0 - '@esbuild/linux-x64': 0.24.0 - '@esbuild/netbsd-x64': 0.24.0 - '@esbuild/openbsd-arm64': 0.24.0 - '@esbuild/openbsd-x64': 0.24.0 - '@esbuild/sunos-x64': 0.24.0 - '@esbuild/win32-arm64': 0.24.0 - '@esbuild/win32-ia32': 0.24.0 - '@esbuild/win32-x64': 0.24.0 + '@esbuild/aix-ppc64': 0.24.2 + '@esbuild/android-arm': 0.24.2 + '@esbuild/android-arm64': 0.24.2 + '@esbuild/android-x64': 0.24.2 + '@esbuild/darwin-arm64': 0.24.2 + '@esbuild/darwin-x64': 0.24.2 + '@esbuild/freebsd-arm64': 0.24.2 + '@esbuild/freebsd-x64': 0.24.2 + '@esbuild/linux-arm': 0.24.2 + '@esbuild/linux-arm64': 0.24.2 + '@esbuild/linux-ia32': 0.24.2 + '@esbuild/linux-loong64': 0.24.2 + '@esbuild/linux-mips64el': 0.24.2 + '@esbuild/linux-ppc64': 0.24.2 + '@esbuild/linux-riscv64': 0.24.2 + '@esbuild/linux-s390x': 0.24.2 + '@esbuild/linux-x64': 0.24.2 + '@esbuild/netbsd-arm64': 0.24.2 + '@esbuild/netbsd-x64': 0.24.2 + '@esbuild/openbsd-arm64': 0.24.2 + '@esbuild/openbsd-x64': 0.24.2 + '@esbuild/sunos-x64': 0.24.2 + '@esbuild/win32-arm64': 0.24.2 + '@esbuild/win32-ia32': 0.24.2 + '@esbuild/win32-x64': 0.24.2 escalade@3.2.0: {} escape-string-regexp@4.0.0: {} - eslint-plugin-oxlint@0.15.2: + eslint-plugin-oxlint@0.15.5: dependencies: jsonc-parser: 3.3.1 - eslint-plugin-perfectionist@4.4.0(eslint@9.17.0(jiti@2.4.2))(typescript@5.8.0-dev.20241122): + eslint-plugin-perfectionist@4.6.0(eslint@9.17.0(jiti@2.4.2))(typescript@5.8.0-dev.20241122): dependencies: - '@typescript-eslint/types': 8.18.1 - '@typescript-eslint/utils': 8.18.1(eslint@9.17.0(jiti@2.4.2))(typescript@5.8.0-dev.20241122) + '@typescript-eslint/types': 8.19.1 + '@typescript-eslint/utils': 8.19.1(eslint@9.17.0(jiti@2.4.2))(typescript@5.8.0-dev.20241122) eslint: 9.17.0(jiti@2.4.2) natural-orderby: 5.0.0 transitivePeerDependencies: @@ -5747,7 +5779,7 @@ snapshots: fast-fifo@1.3.2: {} - fast-glob@3.3.2: + fast-glob@3.3.3: dependencies: '@nodelib/fs.stat': 2.0.5 '@nodelib/fs.walk': 1.2.8 @@ -5759,11 +5791,11 @@ snapshots: fast-levenshtein@2.0.6: {} - fast-uri@3.0.3: {} + fast-uri@3.0.5: {} fastest-levenshtein@1.0.16: {} - fastq@1.17.1: + fastq@1.18.0: dependencies: reusify: 1.0.4 @@ -5832,19 +5864,24 @@ snapshots: gensync@1.0.0-beta.2: {} - get-intrinsic@1.2.6: + get-intrinsic@1.2.7: dependencies: call-bind-apply-helpers: 1.0.1 - dunder-proto: 1.0.1 es-define-property: 1.0.1 es-errors: 1.3.0 es-object-atoms: 1.0.0 function-bind: 1.1.2 + get-proto: 1.0.1 gopd: 1.2.0 has-symbols: 1.1.0 hasown: 2.0.2 math-intrinsics: 1.1.0 + get-proto@1.0.1: + dependencies: + dunder-proto: 1.0.1 + es-object-atoms: 1.0.0 + get-stream@6.0.1: {} get-stream@9.0.1: @@ -5880,7 +5917,7 @@ snapshots: dependencies: array-union: 2.1.0 dir-glob: 3.0.1 - fast-glob: 3.3.2 + fast-glob: 3.3.3 ignore: 5.3.2 merge2: 1.4.1 slash: 3.0.0 @@ -5999,9 +6036,12 @@ snapshots: is-fullwidth-code-point@3.0.0: {} - is-generator-function@1.0.10: + is-generator-function@1.1.0: dependencies: + call-bound: 1.0.3 + get-proto: 1.0.1 has-tostringtag: 1.0.2 + safe-regex-test: 1.1.0 is-glob@4.0.3: dependencies: @@ -6018,6 +6058,13 @@ snapshots: is-plain-object@5.0.0: {} + is-regex@1.2.1: + dependencies: + call-bound: 1.0.3 + gopd: 1.2.0 + has-tostringtag: 1.0.2 + hasown: 2.0.2 + is-stream@2.0.1: {} is-stream@4.0.1: {} @@ -6066,16 +6113,14 @@ snapshots: kind-of@6.0.3: {} - kleur@4.1.5: {} - - knip@5.41.1(@types/node@22.10.2)(typescript@5.8.0-dev.20241122): + knip@5.41.1(@types/node@22.10.5)(typescript@5.8.0-dev.20241122): dependencies: '@nodelib/fs.walk': 1.2.8 '@snyk/github-codeowners': 1.1.0 - '@types/node': 22.10.2 + '@types/node': 22.10.5 easy-table: 1.2.0 enhanced-resolve: 5.18.0 - fast-glob: 3.3.2 + fast-glob: 3.3.3 jiti: 2.4.2 js-yaml: 4.1.0 minimist: 1.2.8 @@ -6114,10 +6159,9 @@ snapshots: lodash.truncate@4.4.2: {} - log-symbols@7.0.0: - dependencies: - is-unicode-supported: 2.1.0 - yoctocolors: 2.1.1 + loglevel-plugin-prefix@0.8.4: {} + + loglevel@1.9.2: {} lowercase-keys@3.0.0: {} @@ -6273,16 +6317,16 @@ snapshots: os-browserify@0.3.0: {} - oxlint@0.15.3: + oxlint@0.15.5: optionalDependencies: - '@oxlint/darwin-arm64': 0.15.3 - '@oxlint/darwin-x64': 0.15.3 - '@oxlint/linux-arm64-gnu': 0.15.3 - '@oxlint/linux-arm64-musl': 0.15.3 - '@oxlint/linux-x64-gnu': 0.15.3 - '@oxlint/linux-x64-musl': 0.15.3 - '@oxlint/win32-arm64': 0.15.3 - '@oxlint/win32-x64': 0.15.3 + '@oxlint/darwin-arm64': 0.15.5 + '@oxlint/darwin-x64': 0.15.5 + '@oxlint/linux-arm64-gnu': 0.15.5 + '@oxlint/linux-arm64-musl': 0.15.5 + '@oxlint/linux-x64-gnu': 0.15.5 + '@oxlint/linux-x64-musl': 0.15.5 + '@oxlint/win32-arm64': 0.15.5 + '@oxlint/win32-x64': 0.15.5 p-cancelable@3.0.0: {} @@ -6344,7 +6388,7 @@ snapshots: pend@1.2.0: {} - php-parser@3.2.1: {} + php-parser@3.2.2: {} picocolors@1.1.1: {} @@ -6529,29 +6573,29 @@ snapshots: hash-base: 3.0.5 inherits: 2.0.4 - rollup@4.29.1: + rollup@4.30.1: dependencies: '@types/estree': 1.0.6 optionalDependencies: - '@rollup/rollup-android-arm-eabi': 4.29.1 - '@rollup/rollup-android-arm64': 4.29.1 - '@rollup/rollup-darwin-arm64': 4.29.1 - '@rollup/rollup-darwin-x64': 4.29.1 - '@rollup/rollup-freebsd-arm64': 4.29.1 - '@rollup/rollup-freebsd-x64': 4.29.1 - '@rollup/rollup-linux-arm-gnueabihf': 4.29.1 - '@rollup/rollup-linux-arm-musleabihf': 4.29.1 - '@rollup/rollup-linux-arm64-gnu': 4.29.1 - '@rollup/rollup-linux-arm64-musl': 4.29.1 - '@rollup/rollup-linux-loongarch64-gnu': 4.29.1 - '@rollup/rollup-linux-powerpc64le-gnu': 4.29.1 - '@rollup/rollup-linux-riscv64-gnu': 4.29.1 - '@rollup/rollup-linux-s390x-gnu': 4.29.1 - '@rollup/rollup-linux-x64-gnu': 4.29.1 - '@rollup/rollup-linux-x64-musl': 4.29.1 - '@rollup/rollup-win32-arm64-msvc': 4.29.1 - '@rollup/rollup-win32-ia32-msvc': 4.29.1 - '@rollup/rollup-win32-x64-msvc': 4.29.1 + '@rollup/rollup-android-arm-eabi': 4.30.1 + '@rollup/rollup-android-arm64': 4.30.1 + '@rollup/rollup-darwin-arm64': 4.30.1 + '@rollup/rollup-darwin-x64': 4.30.1 + '@rollup/rollup-freebsd-arm64': 4.30.1 + '@rollup/rollup-freebsd-x64': 4.30.1 + '@rollup/rollup-linux-arm-gnueabihf': 4.30.1 + '@rollup/rollup-linux-arm-musleabihf': 4.30.1 + '@rollup/rollup-linux-arm64-gnu': 4.30.1 + '@rollup/rollup-linux-arm64-musl': 4.30.1 + '@rollup/rollup-linux-loongarch64-gnu': 4.30.1 + '@rollup/rollup-linux-powerpc64le-gnu': 4.30.1 + '@rollup/rollup-linux-riscv64-gnu': 4.30.1 + '@rollup/rollup-linux-s390x-gnu': 4.30.1 + '@rollup/rollup-linux-x64-gnu': 4.30.1 + '@rollup/rollup-linux-x64-musl': 4.30.1 + '@rollup/rollup-win32-arm64-msvc': 4.30.1 + '@rollup/rollup-win32-ia32-msvc': 4.30.1 + '@rollup/rollup-win32-x64-msvc': 4.30.1 fsevents: 2.3.3 run-parallel@1.2.0: @@ -6566,67 +6610,73 @@ snapshots: safe-buffer@5.2.1: {} - sass-embedded-android-arm64@1.83.0: + safe-regex-test@1.1.0: + dependencies: + call-bound: 1.0.3 + es-errors: 1.3.0 + is-regex: 1.2.1 + + sass-embedded-android-arm64@1.83.1: optional: true - sass-embedded-android-arm@1.83.0: + sass-embedded-android-arm@1.83.1: optional: true - sass-embedded-android-ia32@1.83.0: + sass-embedded-android-ia32@1.83.1: optional: true - sass-embedded-android-riscv64@1.83.0: + sass-embedded-android-riscv64@1.83.1: optional: true - sass-embedded-android-x64@1.83.0: + sass-embedded-android-x64@1.83.1: optional: true - sass-embedded-darwin-arm64@1.83.0: + sass-embedded-darwin-arm64@1.83.1: optional: true - sass-embedded-darwin-x64@1.83.0: + sass-embedded-darwin-x64@1.83.1: optional: true - sass-embedded-linux-arm64@1.83.0: + sass-embedded-linux-arm64@1.83.1: optional: true - sass-embedded-linux-arm@1.83.0: + sass-embedded-linux-arm@1.83.1: optional: true - sass-embedded-linux-ia32@1.83.0: + sass-embedded-linux-ia32@1.83.1: optional: true - sass-embedded-linux-musl-arm64@1.83.0: + sass-embedded-linux-musl-arm64@1.83.1: optional: true - sass-embedded-linux-musl-arm@1.83.0: + sass-embedded-linux-musl-arm@1.83.1: optional: true - sass-embedded-linux-musl-ia32@1.83.0: + sass-embedded-linux-musl-ia32@1.83.1: optional: true - sass-embedded-linux-musl-riscv64@1.83.0: + sass-embedded-linux-musl-riscv64@1.83.1: optional: true - sass-embedded-linux-musl-x64@1.83.0: + sass-embedded-linux-musl-x64@1.83.1: optional: true - sass-embedded-linux-riscv64@1.83.0: + sass-embedded-linux-riscv64@1.83.1: optional: true - sass-embedded-linux-x64@1.83.0: + sass-embedded-linux-x64@1.83.1: optional: true - sass-embedded-win32-arm64@1.83.0: + sass-embedded-win32-arm64@1.83.1: optional: true - sass-embedded-win32-ia32@1.83.0: + sass-embedded-win32-ia32@1.83.1: optional: true - sass-embedded-win32-x64@1.83.0: + sass-embedded-win32-x64@1.83.1: optional: true - sass-embedded@1.83.0: + sass-embedded@1.83.1: dependencies: '@bufbuild/protobuf': 2.2.3 buffer-builder: 0.2.0 @@ -6637,26 +6687,26 @@ snapshots: sync-child-process: 1.0.2 varint: 6.0.0 optionalDependencies: - sass-embedded-android-arm: 1.83.0 - sass-embedded-android-arm64: 1.83.0 - sass-embedded-android-ia32: 1.83.0 - sass-embedded-android-riscv64: 1.83.0 - sass-embedded-android-x64: 1.83.0 - sass-embedded-darwin-arm64: 1.83.0 - sass-embedded-darwin-x64: 1.83.0 - sass-embedded-linux-arm: 1.83.0 - sass-embedded-linux-arm64: 1.83.0 - sass-embedded-linux-ia32: 1.83.0 - sass-embedded-linux-musl-arm: 1.83.0 - sass-embedded-linux-musl-arm64: 1.83.0 - sass-embedded-linux-musl-ia32: 1.83.0 - sass-embedded-linux-musl-riscv64: 1.83.0 - sass-embedded-linux-musl-x64: 1.83.0 - sass-embedded-linux-riscv64: 1.83.0 - sass-embedded-linux-x64: 1.83.0 - sass-embedded-win32-arm64: 1.83.0 - sass-embedded-win32-ia32: 1.83.0 - sass-embedded-win32-x64: 1.83.0 + sass-embedded-android-arm: 1.83.1 + sass-embedded-android-arm64: 1.83.1 + sass-embedded-android-ia32: 1.83.1 + sass-embedded-android-riscv64: 1.83.1 + sass-embedded-android-x64: 1.83.1 + sass-embedded-darwin-arm64: 1.83.1 + sass-embedded-darwin-x64: 1.83.1 + sass-embedded-linux-arm: 1.83.1 + sass-embedded-linux-arm64: 1.83.1 + sass-embedded-linux-ia32: 1.83.1 + sass-embedded-linux-musl-arm: 1.83.1 + sass-embedded-linux-musl-arm64: 1.83.1 + sass-embedded-linux-musl-ia32: 1.83.1 + sass-embedded-linux-musl-riscv64: 1.83.1 + sass-embedded-linux-musl-x64: 1.83.1 + sass-embedded-linux-riscv64: 1.83.1 + sass-embedded-linux-x64: 1.83.1 + sass-embedded-win32-arm64: 1.83.1 + sass-embedded-win32-ia32: 1.83.1 + sass-embedded-win32-x64: 1.83.1 sass@1.80.6: dependencies: @@ -6686,7 +6736,7 @@ snapshots: define-data-property: 1.1.4 es-errors: 1.3.0 function-bind: 1.1.2 - get-intrinsic: 1.2.6 + get-intrinsic: 1.2.7 gopd: 1.2.0 has-property-descriptors: 1.0.2 @@ -6716,14 +6766,14 @@ snapshots: dependencies: call-bound: 1.0.3 es-errors: 1.3.0 - get-intrinsic: 1.2.6 + get-intrinsic: 1.2.7 object-inspect: 1.13.3 side-channel-weakmap@1.0.2: dependencies: call-bound: 1.0.3 es-errors: 1.3.0 - get-intrinsic: 1.2.6 + get-intrinsic: 1.2.7 object-inspect: 1.13.3 side-channel-map: 1.0.1 @@ -6786,7 +6836,7 @@ snapshots: queue-tick: 1.0.1 text-decoder: 1.2.3 optionalDependencies: - bare-events: 2.5.0 + bare-events: 2.5.3 string-width@4.2.3: dependencies: @@ -6824,7 +6874,7 @@ snapshots: style-search@0.1.0: {} - stylelint-config-clean-order@6.1.0(stylelint@16.12.0(typescript@5.8.0-dev.20241122)): + stylelint-config-clean-order@7.0.0(stylelint@16.12.0(typescript@5.8.0-dev.20241122)): dependencies: stylelint: 16.12.0(typescript@5.8.0-dev.20241122) stylelint-order: 6.0.4(stylelint@16.12.0(typescript@5.8.0-dev.20241122)) @@ -6902,7 +6952,7 @@ snapshots: css-functions-list: 3.2.3 css-tree: 3.1.0 debug: 4.4.0 - fast-glob: 3.3.2 + fast-glob: 3.3.3 fastest-levenshtein: 1.0.16 file-entry-cache: 9.1.0 global-modules: 2.0.0 @@ -7002,7 +7052,7 @@ snapshots: '@tokenizer/token': 0.3.0 ieee754: 1.2.1 - ts-api-utils@1.4.3(typescript@5.8.0-dev.20241122): + ts-api-utils@2.0.0(typescript@5.8.0-dev.20241122): dependencies: typescript: 5.8.0-dev.20241122 @@ -7020,11 +7070,11 @@ snapshots: dependencies: prelude-ls: 1.2.1 - typescript-eslint@8.18.1(eslint@9.17.0(jiti@2.4.2))(typescript@5.8.0-dev.20241122): + typescript-eslint@8.19.1(eslint@9.17.0(jiti@2.4.2))(typescript@5.8.0-dev.20241122): dependencies: - '@typescript-eslint/eslint-plugin': 8.18.1(@typescript-eslint/parser@8.18.1(eslint@9.17.0(jiti@2.4.2))(typescript@5.8.0-dev.20241122))(eslint@9.17.0(jiti@2.4.2))(typescript@5.8.0-dev.20241122) - '@typescript-eslint/parser': 8.18.1(eslint@9.17.0(jiti@2.4.2))(typescript@5.8.0-dev.20241122) - '@typescript-eslint/utils': 8.18.1(eslint@9.17.0(jiti@2.4.2))(typescript@5.8.0-dev.20241122) + '@typescript-eslint/eslint-plugin': 8.19.1(@typescript-eslint/parser@8.19.1(eslint@9.17.0(jiti@2.4.2))(typescript@5.8.0-dev.20241122))(eslint@9.17.0(jiti@2.4.2))(typescript@5.8.0-dev.20241122) + '@typescript-eslint/parser': 8.19.1(eslint@9.17.0(jiti@2.4.2))(typescript@5.8.0-dev.20241122) + '@typescript-eslint/utils': 8.19.1(eslint@9.17.0(jiti@2.4.2))(typescript@5.8.0-dev.20241122) eslint: 9.17.0(jiti@2.4.2) typescript: 5.8.0-dev.20241122 transitivePeerDependencies: @@ -7054,9 +7104,9 @@ snapshots: unicode-property-aliases-ecmascript@2.1.0: {} - update-browserslist-db@1.1.1(browserslist@4.24.3): + update-browserslist-db@1.1.2(browserslist@4.24.4): dependencies: - browserslist: 4.24.3 + browserslist: 4.24.4 escalade: 3.2.0 picocolors: 1.1.1 @@ -7075,11 +7125,11 @@ snapshots: dependencies: inherits: 2.0.4 is-arguments: 1.2.0 - is-generator-function: 1.0.10 + is-generator-function: 1.1.0 is-typed-array: 1.1.15 which-typed-array: 1.1.18 - valibot@1.0.0-beta.9(typescript@5.8.0-dev.20241122): + valibot@1.0.0-beta.11(typescript@5.8.0-dev.20241122): optionalDependencies: typescript: 5.8.0-dev.20241122 @@ -7087,43 +7137,42 @@ snapshots: vite-plugin-manifest-sri@0.2.0: {} - vite-plugin-node-polyfills@0.22.0(rollup@4.29.1)(vite@6.0.5(@types/node@22.10.2)(jiti@2.4.2)(sass-embedded@1.83.0)(sass@1.80.6)(terser@5.36.0)): + vite-plugin-node-polyfills@0.22.0(rollup@4.30.1)(vite@6.0.7(@types/node@22.10.5)(jiti@2.4.2)(sass-embedded@1.83.1)(sass@1.80.6)(terser@5.36.0)): dependencies: - '@rollup/plugin-inject': 5.0.5(rollup@4.29.1) + '@rollup/plugin-inject': 5.0.5(rollup@4.30.1) node-stdlib-browser: 1.3.0 - vite: 6.0.5(@types/node@22.10.2)(jiti@2.4.2)(sass-embedded@1.83.0)(sass@1.80.6)(terser@5.36.0) + vite: 6.0.7(@types/node@22.10.5)(jiti@2.4.2)(sass-embedded@1.83.1)(sass@1.80.6)(terser@5.36.0) transitivePeerDependencies: - rollup - vite-plugin-valibot-env@0.9.2(valibot@1.0.0-beta.9(typescript@5.8.0-dev.20241122))(vite@6.0.5(@types/node@22.10.2)(jiti@2.4.2)(sass-embedded@1.83.0)(sass@1.80.6)(terser@5.36.0)): + vite-plugin-valibot-env@0.9.3(valibot@1.0.0-beta.11(typescript@5.8.0-dev.20241122))(vite@6.0.7(@types/node@22.10.5)(jiti@2.4.2)(sass-embedded@1.83.1)(sass@1.80.6)(terser@5.36.0)): dependencies: - kleur: 4.1.5 - log-symbols: 7.0.0 - valibot: 1.0.0-beta.9(typescript@5.8.0-dev.20241122) - vite: 6.0.5(@types/node@22.10.2)(jiti@2.4.2)(sass-embedded@1.83.0)(sass@1.80.6)(terser@5.36.0) + is-unicode-supported: 2.1.0 + valibot: 1.0.0-beta.11(typescript@5.8.0-dev.20241122) + vite: 6.0.7(@types/node@22.10.5)(jiti@2.4.2)(sass-embedded@1.83.1)(sass@1.80.6)(terser@5.36.0) - vite-tsconfig-paths@5.1.4(typescript@5.8.0-dev.20241122)(vite@6.0.5(@types/node@22.10.2)(jiti@2.4.2)(sass-embedded@1.83.0)(sass@1.80.6)(terser@5.36.0)): + vite-tsconfig-paths@5.1.4(typescript@5.8.0-dev.20241122)(vite@6.0.7(@types/node@22.10.5)(jiti@2.4.2)(sass-embedded@1.83.1)(sass@1.80.6)(terser@5.36.0)): dependencies: debug: 4.4.0 globrex: 0.1.2 tsconfck: 3.1.4(typescript@5.8.0-dev.20241122) optionalDependencies: - vite: 6.0.5(@types/node@22.10.2)(jiti@2.4.2)(sass-embedded@1.83.0)(sass@1.80.6)(terser@5.36.0) + vite: 6.0.7(@types/node@22.10.5)(jiti@2.4.2)(sass-embedded@1.83.1)(sass@1.80.6)(terser@5.36.0) transitivePeerDependencies: - supports-color - typescript - vite@6.0.5(@types/node@22.10.2)(jiti@2.4.2)(sass-embedded@1.83.0)(sass@1.80.6)(terser@5.36.0): + vite@6.0.7(@types/node@22.10.5)(jiti@2.4.2)(sass-embedded@1.83.1)(sass@1.80.6)(terser@5.36.0): dependencies: - esbuild: 0.24.0 + esbuild: 0.24.2 postcss: 8.4.49 - rollup: 4.29.1 + rollup: 4.30.1 optionalDependencies: - '@types/node': 22.10.2 + '@types/node': 22.10.5 fsevents: 2.3.3 jiti: 2.4.2 sass: 1.80.6 - sass-embedded: 1.83.0 + sass-embedded: 1.83.1 terser: 5.36.0 vm-browserify@1.1.2: {} @@ -7172,8 +7221,6 @@ snapshots: yocto-queue@0.1.0: {} - yoctocolors@2.1.1: {} - zod-validation-error@3.4.0(zod@3.24.1): dependencies: zod: 3.24.1 diff --git a/web/app/themes/haiku-atelier-2024/src/scripts/constantes/evenements.ts b/web/app/themes/haiku-atelier-2024/src/scripts/constantes/evenements.ts index 6f897c04..9baf0749 100755 --- a/web/app/themes/haiku-atelier-2024/src/scripts/constantes/evenements.ts +++ b/web/app/themes/haiku-atelier-2024/src/scripts/constantes/evenements.ts @@ -1,5 +1,5 @@ export const ADRESSES_MAJ = "adressesMaj"; export const CODE_PROMO_MAJ = "codePromoMaj"; -export const METHODES_LIVRAISON_MAJ = "methodesLivraisonMaj"; +export const SHIPPING_RATES_UPDATED = "shippingRatesUpdated"; export const PRODUITS_MAJ = "produitsMaj"; -export const TOTAUX_MAJ = "totauxMaj"; +export const TOTALS_UPDATED = "totalsUpdated"; diff --git a/web/app/themes/haiku-atelier-2024/src/scripts/gaffe.ts b/web/app/themes/haiku-atelier-2024/src/scripts/gaffe.ts index 6b3cb2ec..c8d414bc 100755 --- a/web/app/themes/haiku-atelier-2024/src/scripts/gaffe.ts +++ b/web/app/themes/haiku-atelier-2024/src/scripts/gaffe.ts @@ -73,4 +73,4 @@ const client = new BrowserClient({ /* Initialise la configuration */ getCurrentScope().setClient(client); -client.init(); +// client.init(); diff --git a/web/app/themes/haiku-atelier-2024/src/scripts/lib/arrays.ts b/web/app/themes/haiku-atelier-2024/src/scripts/lib/arrays.ts new file mode 100644 index 00000000..52ad6bd2 --- /dev/null +++ b/web/app/themes/haiku-atelier-2024/src/scripts/lib/arrays.ts @@ -0,0 +1,12 @@ +export const forEach = (fn: (_1: T) => void) => (xs: Array): void => { + xs.forEach(fn); +}; + +export const forEachWithIndex = (fn: (_1: T, _2: number) => void) => (xs: Array): void => { + xs.forEach(fn); +}; + +export const map = (fn: (_1: T) => void) => (xs: Array): Array => { + xs.map(fn); + return xs; +}; diff --git a/web/app/themes/haiku-atelier-2024/src/scripts/lib/dom.ts b/web/app/themes/haiku-atelier-2024/src/scripts/lib/dom.ts index 7b4c8962..1e76e58c 100755 --- a/web/app/themes/haiku-atelier-2024/src/scripts/lib/dom.ts +++ b/web/app/themes/haiku-atelier-2024/src/scripts/lib/dom.ts @@ -1,19 +1,25 @@ import { A, G, pipe } from "@mobily/ts-belt"; -import { Either, identity, Left, Maybe, Right } from "purify-ts"; +import { Either, identity, Left, Right } from "purify-ts"; -import type { ElementParent } from "./types/dom.d.ts"; +import type { ParentElement } from "./types/dom.d.ts"; +import { ATTRIBUT_CHARGEMENT, ATTRIBUT_DESACTIVE } from "../constantes/dom.ts"; +import { logger } from "../logging.ts"; +import { lanceAnimationCycleLoading } from "./animations.ts"; import { + BadRequestError, creeSyntaxError, ERREUR_SELECTEUR_INEXISTANT, ERREUR_SYNTAXE_INVALIDE, - ErreurEntreeInexistante, - type NonExistingKeyError, + ForbiddenError, + NotFoundError, reporteEtLeveErreur, + ServerError, + UnauthorizedError, } from "./erreurs"; export const recupereElementAvecSelecteur = - (parent: ElementParent) => (selecteur: string): Either => + (parent: ParentElement) => (selecteur: string): Either => Either // Retourne une SyntaxError dans un Left si le sélecteur est invalide .encase(() => parent.querySelector(selecteur)) @@ -24,8 +30,8 @@ export const recupereElementAvecSelecteur = G.isNotNullable(e) ? Right(e) : Left(creeSyntaxError(ERREUR_SELECTEUR_INEXISTANT(selecteur))) ); -export const recupereElementsAvecSelecteur = - (parent: ElementParent) => (selecteur: string): Either> => +export const getDOMElementsWithSelector = + (parent: ParentElement) => (selecteur: string): Either> => Either // Retourne une SyntaxError dans un Left si le sélecteur est invalide .encase(() => pipe(parent.querySelectorAll(selecteur), Array.from)) @@ -62,29 +68,86 @@ export const html = (strings: TemplateStringsArray, ...args: Array) => template => template.content, ); -/** - * Récupère une entrée dans le Stockage de Session (`storageSession`) sous forme d'`Either`. - * - * @param cle La clé de l'entrée. - * @returns Un `Either` avec une `NonExistingKeyError` si la clé est absente (`Left`), la - * valeur de l'entrée sinon (`Right`). - */ -export const eitherSessionStorageGet = (cle: string): Either => - Maybe - .fromNullable(sessionStorage.getItem(cle)) - .toEither(ErreurEntreeInexistante(`Clé ${cle} absente dans le stockage de session.`)); - /** * Convertis une chaîne JSON en un objet JavaScript sous forme d'`Either`. * @param chaine La chaîne à convertir. * @returns Un `Either` avec une `SyntaxError` si la chaîne est invalide, un objet JS sinon * (`Right`). */ -export const eitherJsonParse = (chaine: string): Either => +export const safeJsonParse = (chaine: string): Either => Either.encase(() => JSON.parse(chaine)); -/** TODO */ -export const accorderCibleASelecteur = ( +/** + * Vérifie qu'un sélecteur s'applique à l'élément DOM d'une cible d'événement (un `EventTarget`) donnée. + * La fonction agit comme un garde de type. + * + * @returns Un booléen + */ +export const targetMatchesSelector = ( cible: EventTarget | null, selecteur: string, ): cible is E => cible !== null && (cible as HTMLElement).matches(selecteur); + +export const recupereElementsDocumentEither: ( + selecteur: string, +) => Either> = getDOMElementsWithSelector(document); + +export const recupereElementDocumentEither: ( + selecteur: string, +) => Either = recupereElementAvecSelecteur(document); + +/** + * Fonction utilitaire pour récupérer un Élément selon un sélecteur au sein du Document. + * + * @param selecteur Le sélecteur de l'Élément recherché. + * @throws Une SyntaxError si l'Élément n'est pas trouvé. + * @returns Un Élément. + */ +export const mustGetEleInDocument = (selecteur: string): E => + pipe( + recupereElementDocumentEither(selecteur), + recupereElementOuLeve, + ); + +export const mustGetEleInParent = (parent: ParentElement) => (selector: string) => + pipe(recupereElementAvecSelecteur(parent)(selector), recupereElementOuLeve); + +/** + * Fonction utilitaire pour récupérer des Éléments selon un sélecteur au sein du Document. + * + * @param selecteur Le sélecteur des Éléments recherchés. + * @throws Une SyntaxError si aucun Élément n'est trouvé. + * @returns Un tableau d'Éléments. + */ +export const mustGetElesInDocument = (selecteur: string): Array => + pipe( + recupereElementsDocumentEither(selecteur), + recupereElementsOuLeve, + ); + +export const setButtonLoadingState = (button: HTMLButtonElement, isLoading: boolean): void => { + logger.debug("majEtatChargementBouton", button, isLoading); + if (isLoading) { + // Désactive le Bouton pour empêcher des requêtes concurrentes + button.setAttribute(ATTRIBUT_DESACTIVE, ""); + button.setAttribute(ATTRIBUT_CHARGEMENT, ""); + // Lance un cycle d'animation sur le texte de chargement + lanceAnimationCycleLoading(button, 500); + } else { + // Désactive l'animation de chargement et rend le Bouton de nouveau cliquable + button.removeAttribute(ATTRIBUT_CHARGEMENT); + button.removeAttribute(ATTRIBUT_DESACTIVE); + } +}; + +export const estErreurHttp = (erreur: unknown) => + erreur instanceof BadRequestError + || erreur instanceof ForbiddenError + || erreur instanceof NotFoundError + || erreur instanceof ServerError + || erreur instanceof UnauthorizedError; + +export const estErreurFetch = (erreur: unknown) => + erreur instanceof DOMException + || erreur instanceof TypeError + || erreur instanceof Error; diff --git a/web/app/themes/haiku-atelier-2024/src/scripts/lib/evenements/panier.ts b/web/app/themes/haiku-atelier-2024/src/scripts/lib/evenements/panier.ts index 14fdb6a6..aba342ce 100755 --- a/web/app/themes/haiku-atelier-2024/src/scripts/lib/evenements/panier.ts +++ b/web/app/themes/haiku-atelier-2024/src/scripts/lib/evenements/panier.ts @@ -1,19 +1,26 @@ import type { WCStoreCartTotals, WCStoreShippingRateShippingRate } from "../types/api/cart"; -import { ADRESSES_MAJ, CODE_PROMO_MAJ, METHODES_LIVRAISON_MAJ, TOTAUX_MAJ } from "../../constantes/evenements"; +import { ADRESSES_MAJ, CODE_PROMO_MAJ, SHIPPING_RATES_UPDATED, TOTALS_UPDATED } from "../../constantes/evenements"; export const ADRESSES_MAJ_EVENT = new CustomEvent(ADRESSES_MAJ, {}); export const CODE_PROMO_MAJ_EVENT = new CustomEvent(CODE_PROMO_MAJ, {}); -export const MethodesLivraisonMajEvent = (methodes: ReadonlyArray) => - new CustomEvent(METHODES_LIVRAISON_MAJ, { detail: { methodes } }); +// Interfaces -export interface MethodesLivraisonMajEvent extends Event { - detail: { methodes: ReadonlyArray }; +export interface UpdatedShippingRatesEvent extends Event { + detail: { refresh_methods: boolean; shipping_rates: ReadonlyArray }; +} +export interface UpdatedTotalsEvent extends Event { + detail: { totals: WCStoreCartTotals }; } -export const TotauxMajEvent = (totaux: WCStoreCartTotals) => new CustomEvent(TOTAUX_MAJ, { detail: { totaux } }); +// Méthodes -export interface TotauxMajEvent extends Event { - detail: { totaux: WCStoreCartTotals }; -} +export const createUpdatedShippingRatesEvent = ( + shipping_rates: ReadonlyArray, + refresh_methods: boolean, +): UpdatedShippingRatesEvent => + new CustomEvent(SHIPPING_RATES_UPDATED, { detail: { refresh_methods, shipping_rates } }); + +export const createUpdatedTotalsEvent = (totals: WCStoreCartTotals): UpdatedTotalsEvent => + new CustomEvent(TOTALS_UPDATED, { detail: { totals } }); diff --git a/web/app/themes/haiku-atelier-2024/src/scripts/lib/local-storage.ts b/web/app/themes/haiku-atelier-2024/src/scripts/lib/local-storage.ts index d8bfb837..aa4cb0c4 100755 --- a/web/app/themes/haiku-atelier-2024/src/scripts/lib/local-storage.ts +++ b/web/app/themes/haiku-atelier-2024/src/scripts/lib/local-storage.ts @@ -2,9 +2,9 @@ import type { GenericSchema, InferOutput, ValiError } from "valibot"; import { Either, Maybe } from "purify-ts"; -import { eitherJsonParse } from "./dom.ts"; +import { safeJsonParse } from "./dom.ts"; import { ErreurEntreeInexistante, type NonExistingKeyError } from "./erreurs.ts"; -import { eitherValiParseCurried } from "./validation.ts"; +import { safeSchemaParse, safeSchemaParseCurried } from "./validation.ts"; export type GetLocalStorage = Either, InferOutput>; type ErreursGetLocalStorage = @@ -24,13 +24,18 @@ export const eitherGetLocalStorage = (cle: string): Either(cle: string, valeur: V): Either => +export const eitherSetLocalStorage = (cle: string, valeur: V): Either => Either.encase(() => { localStorage.setItem(cle, JSON.stringify(valeur)); return valeur; }); -export const getAndParseLocalStorage = (cle: string, schema: S): GetLocalStorage => - eitherGetLocalStorage(cle) - .chain(eitherJsonParse) - .chain(eitherValiParseCurried(schema)); +export const getLocalStorageByKey = (key: string, schema: S): GetLocalStorage => + eitherGetLocalStorage(key) + .chain(safeJsonParse) + .chain(safeSchemaParseCurried(schema)); + +export const setLocalStorageByKey = + (key: string, schema: S) => + (value: unknown): Either, InferOutput> => + safeSchemaParse(value, schema).chain(v => eitherSetLocalStorage(key, v)); diff --git a/web/app/themes/haiku-atelier-2024/src/scripts/lib/messages.ts b/web/app/themes/haiku-atelier-2024/src/scripts/lib/messages.ts index 330f9440..a3bad9c7 100755 --- a/web/app/themes/haiku-atelier-2024/src/scripts/lib/messages.ts +++ b/web/app/themes/haiku-atelier-2024/src/scripts/lib/messages.ts @@ -8,13 +8,13 @@ import type { MessageMajContenuPanier, MessageMajContenuPanierDonnees, } from "./types/messages"; -import type { ReponseSimplifiee } from "./types/reseau"; +import type { SimplifiedResponse } from "./types/reseau"; import { NOM_CANAL_BOUTON_PANIER, NOM_CANAL_CONTENU_PANIER, TYPES_MESSAGES } from "../constantes/messages.ts"; import { reporteErreur } from "./erreurs.ts"; import { WCErrorSchema } from "./schemas/api/erreurs.ts"; import { MessageMajBoutonPanierSchema, MessageMajContenuPanierSchema } from "./schemas/messages.ts"; -import { eitherValiParse } from "./validation.ts"; +import { safeSchemaParse } from "./validation.ts"; const canalPostMessage = (canal: BroadcastChannel, message: unknown): BroadcastChannel => { canal.postMessage(message); @@ -77,7 +77,7 @@ export const valideMessageMajContenuPanier = ( .ifLeft(erreur => reporteErreur(erreur)); // Correspondances -export const reponseEstCodeErreurWC = (reponse: ReponseSimplifiee, codeErreurWC: string): boolean => - eitherValiParse(reponse, WCErrorSchema) +export const reponseEstCodeErreurWC = (reponse: SimplifiedResponse, codeErreurWC: string): boolean => + safeSchemaParse(reponse, WCErrorSchema) .map(v => v.body.code === codeErreurWC) .orDefault(false); diff --git a/web/app/themes/haiku-atelier-2024/src/scripts/lib/reseau.ts b/web/app/themes/haiku-atelier-2024/src/scripts/lib/reseau.ts index 9570dd28..ad569903 100755 --- a/web/app/themes/haiku-atelier-2024/src/scripts/lib/reseau.ts +++ b/web/app/themes/haiku-atelier-2024/src/scripts/lib/reseau.ts @@ -3,7 +3,7 @@ import { EitherAsync } from "purify-ts"; import { match, P } from "ts-pattern"; import { type GenericSchema, parse } from "valibot"; -import type { HttpCodeErrors, ReponseSimplifiee } from "./types/reseau"; +import type { HttpCodeErrors, SimplifiedResponse } from "./types/reseau"; import { ENTETE_WC_NONCE } from "../constantes/api.ts"; import { @@ -126,7 +126,27 @@ export const postBackend = (args: ArgumentsPostBackendWC): Promise => }, ); -export const eitherAsyncFetch = (f: Promise): EitherAsync => +export const prefilledPostBackend = + (nonce: string, authString?: string) => + (route: string, body: BodyInit, needsAuthString: boolean): Promise => + fetch( + route, + { + body: body, + credentials: "same-origin", + headers: { + Accept: "application/json", + "Content-Type": "application/json", + [ENTETE_WC_NONCE]: nonce, + ...(authString && needsAuthString && { Authorization: `Basic ${authString}` }), + }, + method: "POST", + mode: "same-origin", + signal: AbortSignal.timeout(5000), + }, + ); + +export const safeFetch = (f: Promise): EitherAsync => EitherAsync(async () => await f); // TODO: Ne traite pas du tout les Erreurs @@ -146,14 +166,14 @@ export const traiteReponseBackendWCSelonCodesHTTP = pipe(e, ErreurInconnue, leveErreur)); // Réponses Simplifiées -export const creeReponseSimplifiee = async (reponse: Response): Promise => { +export const newPartialResponse = async (reponse: Response): Promise => { return { body: await reponse.json(), status: reponse.status, }; }; -export const traiteErreursBackendWooCommerce = (rs: ReponseSimplifiee): HttpCodeErrors => { +export const traiteErreursBackendWooCommerce = (rs: SimplifiedResponse): HttpCodeErrors => { return match(rs) .with({ status: 400 }, () => new BadRequestError()) .with({ status: 401 }, () => new UnauthorizedError()) diff --git a/web/app/themes/haiku-atelier-2024/src/scripts/lib/safe-arrays.ts b/web/app/themes/haiku-atelier-2024/src/scripts/lib/safe-arrays.ts new file mode 100644 index 00000000..75cd9850 --- /dev/null +++ b/web/app/themes/haiku-atelier-2024/src/scripts/lib/safe-arrays.ts @@ -0,0 +1,11 @@ +import { Maybe } from "purify-ts"; + +/** + * Retourne sous forme d'un Maybe le premier élément d'un tableau. + * @param xs Le tableau dont on souhaite le premier élément. + * @returns Un Just avec le premier élément du tableau, un None sinon. + */ +export const first = (xs: Array): Maybe => Maybe.fromNullable(xs.at(0)); + +export const find = (predicateFn: (_1: T) => boolean) => (xs: Array): Maybe => + Maybe.fromNullable(xs.find(predicateFn)); diff --git a/web/app/themes/haiku-atelier-2024/src/scripts/lib/types/api/cart.d.ts b/web/app/themes/haiku-atelier-2024/src/scripts/lib/types/api/cart.d.ts index 41a5cdb3..70c4c1fe 100755 --- a/web/app/themes/haiku-atelier-2024/src/scripts/lib/types/api/cart.d.ts +++ b/web/app/themes/haiku-atelier-2024/src/scripts/lib/types/api/cart.d.ts @@ -1,9 +1,13 @@ import type { InferOutput } from "valibot"; import type { WCStoreCartItemSchema, WCStoreCartSchema, WCStoreCartTotalsSchema } from "../../schemas/api/cart.ts"; -import type { WCStoreShippingRateShippingRateSchema } from "../../schemas/api/couts-livraison.ts"; +import type { + WCStoreShippingRateSchema, + WCStoreShippingRateShippingRateSchema, +} from "../../schemas/api/couts-livraison.ts"; export type WCStoreCart = InferOutput; export type WCStoreCartItem = InferOutput; export type WCStoreCartTotals = InferOutput; +export type WCStoreShippingRate = InferOutput; export type WCStoreShippingRateShippingRate = InferOutput; diff --git a/web/app/themes/haiku-atelier-2024/src/scripts/lib/types/dom.d.ts b/web/app/themes/haiku-atelier-2024/src/scripts/lib/types/dom.d.ts index 10e5e7ed..273e2214 100755 --- a/web/app/themes/haiku-atelier-2024/src/scripts/lib/types/dom.d.ts +++ b/web/app/themes/haiku-atelier-2024/src/scripts/lib/types/dom.d.ts @@ -1,2 +1,2 @@ /** Type union des parents possibles pour un `querySelector`. */ -export type ElementParent = Document | Element; +export type ParentElement = Document | Element; diff --git a/web/app/themes/haiku-atelier-2024/src/scripts/lib/types/pages.d.ts b/web/app/themes/haiku-atelier-2024/src/scripts/lib/types/pages.d.ts index a9e5ba66..459f8b7e 100755 --- a/web/app/themes/haiku-atelier-2024/src/scripts/lib/types/pages.d.ts +++ b/web/app/themes/haiku-atelier-2024/src/scripts/lib/types/pages.d.ts @@ -1,4 +1,4 @@ -export type EtatsPageGenerique = { +export type GenericPageState = { /** Une chaîne pour l'authentification de requêtes vers la nouvelle API (v3) du backend WooCommerce. */ authString: string; /** Un nonce pour l'authentification de requêtes API vers le backend WooCommerce. */ diff --git a/web/app/themes/haiku-atelier-2024/src/scripts/lib/types/reseau.d.ts b/web/app/themes/haiku-atelier-2024/src/scripts/lib/types/reseau.d.ts index 82d0c584..e9a27a88 100755 --- a/web/app/themes/haiku-atelier-2024/src/scripts/lib/types/reseau.d.ts +++ b/web/app/themes/haiku-atelier-2024/src/scripts/lib/types/reseau.d.ts @@ -10,7 +10,7 @@ export type HttpCodeErrors = | ServerError | UnauthorizedError; -export interface ReponseSimplifiee { +export interface SimplifiedResponse { body: unknown; status: number; } diff --git a/web/app/themes/haiku-atelier-2024/src/scripts/lib/utils.ts b/web/app/themes/haiku-atelier-2024/src/scripts/lib/utils.ts index 3b9ec899..45246068 100755 --- a/web/app/themes/haiku-atelier-2024/src/scripts/lib/utils.ts +++ b/web/app/themes/haiku-atelier-2024/src/scripts/lib/utils.ts @@ -1,30 +1,7 @@ -import { D, pipe } from "@mobily/ts-belt"; +import { D } from "@mobily/ts-belt"; import { type Either, Maybe } from "purify-ts"; -import { ATTRIBUT_CHARGEMENT, ATTRIBUT_DESACTIVE } from "../constantes/dom.ts"; -import { lanceAnimationCycleLoading } from "./animations.ts"; -import { - recupereElementAvecSelecteur, - recupereElementOuLeve, - recupereElementsAvecSelecteur, - recupereElementsOuLeve, -} from "./dom.ts"; -import { - BadRequestError, - CleNonTrouveError, - ForbiddenError, - NotFoundError, - ServerError, - UnauthorizedError, -} from "./erreurs.ts"; - -export const recupereElementsDocumentEither: ( - selecteur: string, -) => Either> = recupereElementsAvecSelecteur(document); - -export const recupereElementDocumentEither: ( - selecteur: string, -) => Either = recupereElementAvecSelecteur(document); +import { CleNonTrouveError } from "./erreurs"; /** * TODO @@ -35,55 +12,3 @@ export const propEither = (cle: K) => (donnees: T): Either .toEither( new CleNonTrouveError(`La clé « ${String(cle)} » n'a pas été trouvé dans l'objet.`), ); - -/** - * Fonction utilitaire pour récupérer un Élément selon un sélecteur au sein du Document. - * - * @param selecteur Le sélecteur de l'Élément recherché. - * @throws Une SyntaxError si l'Élément n'est pas trouvé. - * @returns Un Élément. - */ -export const recupereEleOuLeve = (selecteur: string): E => - pipe( - recupereElementDocumentEither(selecteur), - recupereElementOuLeve, - ); - -/** - * Fonction utilitaire pour récupérer des Éléments selon un sélecteur au sein du Document. - * - * @param selecteur Le sélecteur des Éléments recherchés. - * @throws Une SyntaxError si aucun Élément n'est trouvé. - * @returns Un tableau d'Éléments. - */ -export const recupereElesOuLeve = (selecteur: string): Array => - pipe( - recupereElementsDocumentEither(selecteur), - recupereElementsOuLeve, - ); - -export const majEtatChargementBouton = (bouton: HTMLButtonElement, activation: boolean): void => { - if (activation) { - // Désactive le Bouton pour empêcher des requêtes concurrentes - bouton.setAttribute(ATTRIBUT_DESACTIVE, ""); - bouton.setAttribute(ATTRIBUT_CHARGEMENT, ""); - // Lance un cycle d'animation sur le texte de chargement - lanceAnimationCycleLoading(bouton, 500); - } else { - // Désactive l'animation de chargement et rend le Bouton de nouveau cliquable - bouton.removeAttribute(ATTRIBUT_CHARGEMENT); - bouton.removeAttribute(ATTRIBUT_DESACTIVE); - } -}; - -export const estErreurHttp = (erreur: unknown) => - erreur instanceof BadRequestError - || erreur instanceof ForbiddenError - || erreur instanceof NotFoundError - || erreur instanceof ServerError - || erreur instanceof UnauthorizedError; - -export const estErreurFetch = (erreur: unknown) => - erreur instanceof DOMException - || erreur instanceof TypeError - || erreur instanceof Error; diff --git a/web/app/themes/haiku-atelier-2024/src/scripts/lib/validation.ts b/web/app/themes/haiku-atelier-2024/src/scripts/lib/validation.ts index 16652479..9aca71ae 100755 --- a/web/app/themes/haiku-atelier-2024/src/scripts/lib/validation.ts +++ b/web/app/themes/haiku-atelier-2024/src/scripts/lib/validation.ts @@ -5,11 +5,11 @@ import { Either } from "purify-ts"; import { type GenericSchema, type InferOutput, parse, type ValiError } from "valibot"; -export const eitherValiParse = ( +export const safeSchemaParse = ( valeur: unknown, schema: Schema, ): Either, InferOutput> => Either.encase(() => parse(schema, valeur)); -export const eitherValiParseCurried = +export const safeSchemaParseCurried = (schema: S) => (valeur: unknown): Either, InferOutput> => Either.encase(() => parse(schema, valeur)); diff --git a/web/app/themes/haiku-atelier-2024/src/scripts/logging.ts b/web/app/themes/haiku-atelier-2024/src/scripts/logging.ts new file mode 100644 index 00000000..96922a82 --- /dev/null +++ b/web/app/themes/haiku-atelier-2024/src/scripts/logging.ts @@ -0,0 +1,21 @@ +import chalk from "chalk"; +import log, { type Logger } from "loglevel"; +import prefix from "loglevel-plugin-prefix"; + +const colors = { + DEBUG: chalk.cyan, + ERROR: chalk.red, + INFO: chalk.blue, + TRACE: chalk.magenta, + WARN: chalk.yellow, +}; + +export const logger: Logger = log.noConflict() as Logger; +logger.enableAll(true); +logger.setDefaultLevel("DEBUG"); +prefix.reg(logger); +prefix.apply(logger, { + format(level, _, timestamp) { + return `${chalk.gray(`[${timestamp}]`)} ${colors[level.toUpperCase()](level)}`; + }, +}); diff --git a/web/app/themes/haiku-atelier-2024/src/scripts/page-panier/scripts-page-panier-adresses.ts b/web/app/themes/haiku-atelier-2024/src/scripts/page-panier/scripts-page-panier-adresses.ts index ba11a843..2a6656fd 100755 --- a/web/app/themes/haiku-atelier-2024/src/scripts/page-panier/scripts-page-panier-adresses.ts +++ b/web/app/themes/haiku-atelier-2024/src/scripts/page-panier/scripts-page-panier-adresses.ts @@ -1,30 +1,20 @@ import { pipe } from "@mobily/ts-belt"; -import { find as arrayFind, map as arrayMap } from "@mobily/ts-belt/Array"; +import { find as arrayFind } from "@mobily/ts-belt/Array"; import { map as dictMap, values as dictValues } from "@mobily/ts-belt/Dict"; import { trim as stringTrim } from "@mobily/ts-belt/String"; import { EitherAsync, Maybe } from "purify-ts"; import { match, P } from "ts-pattern"; import { type AnySchema, ValiError } from "valibot"; -import type { WCStoreCart, WCStoreShippingRateShippingRate } from "../lib/types/api/cart"; +import type { WCStoreBillingAddress, WCStoreShippingAddress } from "../lib/types/api/adresses"; +import type { WCStoreCart, WCStoreShippingRate, WCStoreShippingRateShippingRate } from "../lib/types/api/cart"; import type { WCStoreCartUpdateCustomerArgs } from "../lib/types/api/cart-update-customer"; -import type { WCStoreShippingRateShippingRates } from "../lib/types/api/couts-livraison"; import type { WCV3Order, WCV3OrdersArgs } from "../lib/types/api/v3/orders"; -import type { EtatsPageGenerique } from "../lib/types/pages"; +import type { GenericPageState } from "../lib/types/pages"; import type { FetchErrors, HttpCodeErrors } from "../lib/types/reseau"; import { ROUTE_API_MAJ_CLIENT, ROUTE_API_NOUVELLE_COMMANDES } from "../constantes/api"; -import { - ATTRIBUT_CHARGEMENT, - ATTRIBUT_LIVRAISON_VALIDEE, - SELECTEUR_BOUTON_ACTIONS_FORMULAIRE, - SELECTEUR_BOUTON_SEPARATION_ADRESSES, - SELECTEUR_CONTENEUR_METHODES_LIVRAISON, - SELECTEUR_ENTREES_PANIER, - SELECTEUR_FORMULAIRE_PANIER, - SELECTEUR_INSTRUCTIONS_CLIENT, - SELECTEUR_MESSAGE_FORMULAIRE_ADRESSES, -} from "../constantes/dom"; +import { ATTRIBUT_CHARGEMENT, ATTRIBUT_LIVRAISON_VALIDEE } from "../constantes/dom"; import { NOM_CANAL_REVALIDATION_LIVRAISON } from "../constantes/messages"; import { ERREUR_ADRESSE_MAUVAIS_CODE_POSTAL, @@ -32,42 +22,36 @@ import { ERREUR_GENERIQUE_RESEAU, ERREUR_GENERIQUE_SOUMISSION_ADRESSES, } from "../constantes/messages-utilisateur"; -import { leveErreur, type NonExistingKeyError, reporteErreur, reporteEtJournaliseErreur } from "../lib/erreurs"; +import { estErreurFetch, estErreurHttp, setButtonLoadingState } from "../lib/dom"; +import { reporteEtJournaliseErreur } from "../lib/erreurs"; import { ErreurAdresseInvalide } from "../lib/erreurs/adresses"; -import { ADRESSES_MAJ_EVENT, MethodesLivraisonMajEvent, TotauxMajEvent } from "../lib/evenements/panier"; -import { getAndParseLocalStorage } from "../lib/local-storage"; +import { + ADRESSES_MAJ_EVENT, + createUpdatedShippingRatesEvent, + createUpdatedTotalsEvent, +} from "../lib/evenements/panier"; import { emetUniqueMessageBroadcastChannel } from "../lib/messages"; import { diviseParCent } from "../lib/nombres"; -import { creeReponseSimplifiee, eitherAsyncFetch, postBackend, traiteErreursBackendWooCommerce } from "../lib/reseau"; +import { newPartialResponse, prefilledPostBackend, safeFetch, traiteErreursBackendWooCommerce } from "../lib/reseau"; +import { find, first } from "../lib/safe-arrays"; import { WCStoreCartSchema } from "../lib/schemas/api/cart"; import { WCStoreCartUpdateCustomerArgsSchema } from "../lib/schemas/api/cart-update-customer"; -import { WCStoreShippingRateShippingRatesSchema } from "../lib/schemas/api/couts-livraison"; import { estWCAddressError } from "../lib/schemas/api/erreurs"; import { WCV3OrdersArgsSchema, WCV3OrderSchema } from "../lib/schemas/api/v3/orders"; -import { - estErreurFetch, - estErreurHttp, - majEtatChargementBouton, - recupereElementsDocumentEither, - recupereEleOuLeve, -} from "../lib/utils"; -import { eitherValiParse } from "../lib/validation"; -import { genereHtmlMethodesLivraison } from "./scripts-page-panier-methodes-livraison"; +import { safeSchemaParse } from "../lib/validation"; +import { logger } from "../logging"; +import { E } from "./scripts-page-panier-elements"; +import { getShippingRatesLS } from "./scripts-page-panier-local-storage"; + +interface Addresses { + billing_address: WCStoreBillingAddress; + shipping_address: WCStoreShippingAddress; +} // @ts-expect-error -- États injectés par le modèle PHP // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment -- États injectés par le modèle PHP -const ETATS_PAGE: EtatsPageGenerique = _etats; - -const E = { - BOUTON_ACTIONS_FORMULAIRE: recupereEleOuLeve(SELECTEUR_BOUTON_ACTIONS_FORMULAIRE), - BOUTON_SEPARATION_ADRESSES: recupereEleOuLeve(SELECTEUR_BOUTON_SEPARATION_ADRESSES), - CONTENEUR_METHODES_LIVRAISON: recupereEleOuLeve(SELECTEUR_CONTENEUR_METHODES_LIVRAISON), - ENTREES_PANIER_EITHER: recupereElementsDocumentEither(SELECTEUR_ENTREES_PANIER), - FORMULAIRE_PANIER: recupereEleOuLeve(SELECTEUR_FORMULAIRE_PANIER), - INSTRUCTIONS_CLIENT: recupereEleOuLeve(SELECTEUR_INSTRUCTIONS_CLIENT), - MESSAGE_ADRESSES: recupereEleOuLeve(SELECTEUR_MESSAGE_FORMULAIRE_ADRESSES), -}; - +const ETATS_PAGE: GenericPageState = _etats; +const postBackend = prefilledPostBackend(ETATS_PAGE.nonce, ETATS_PAGE.authString); /** * Initialise les Émetteurs d'Événements sur divers parties du Panier. * @@ -75,126 +59,138 @@ const E = { * * @returns void */ -export const initialiseEmetteursEvenementsFormulairePanier = (): void => { +export const initCartFormEventEmiters = (): void => { + logger.debug("ADRESSES", "initCartFormEventEmiters"); E.FORMULAIRE_PANIER.addEventListener("change", (): void => { + logger.info("ADRESSES", "Changement du Formulaire Panier"); Maybe .fromFalsy(E.FORMULAIRE_PANIER.checkValidity()) .ifJust((): boolean => window.dispatchEvent(ADRESSES_MAJ_EVENT)); }); }; -export const initialiseBoutonCalculLivraison = (): void => { - // Déclenche la requête pour la soumission des adresses +export const getAddressesFromForm = (formFields: Record, areAddressesMerged: boolean): Addresses => { + logger.debug("ADDRESSES", "getAddressesFromForm"); + return { + billing_address: { + address_1: formFields["facturation-adresse"] ?? formFields["livraison-adresse"] ?? "", + address_2: "", + city: formFields["facturation-ville"] ?? formFields["livraison-ville"] ?? "", + company: "", + country: areAddressesMerged ? formFields["facturation-pays"] ?? "" : formFields["livraison-pays"] ?? "", + email: formFields["facturation-email"] ?? formFields["livraison-email"] ?? "", + first_name: formFields["facturation-prenom"] ?? formFields["livraison-prenom"] ?? "", + last_name: formFields["facturation-nom"] ?? formFields["livraison-nom"] ?? "", + phone: formFields["facturation-telephone"] ?? formFields["livraison-telephone"] ?? "", + postcode: formFields["facturation-code-postal"] ?? formFields["livraison-code-postal"] ?? "", + state: formFields["facturation-region-etat"] ?? formFields["livraison-region-etat"] ?? "", + }, + shipping_address: { + address_1: formFields["livraison-adresse"] ?? "", + address_2: "", + city: formFields["livraison-ville"] ?? "", + company: "", + country: formFields["livraison-pays"] ?? "", + first_name: formFields["livraison-prenom"] ?? "", + last_name: formFields["livraison-nom"] ?? "", + phone: formFields["livraison-telephone"] ?? "", + postcode: formFields["livraison-code-postal"] ?? "", + state: formFields["livraison-region-etat"] ?? "", + }, + }; +}; + +export const initShippingCalculationButton = (): void => { + logger.debug("ADRESSES", "initShippingCalculationButton"); + // Déclenche au clic sur le Bouton de soumission du Formulaire la requête pour le calcul des frais de livraison E.BOUTON_ACTIONS_FORMULAIRE.addEventListener("click", (event: Event): void => { + logger.info("ADRESSES", "Demande de calcul des frais de livraison de la commande"); Maybe // Ne fais rien si le Formulaire n'est pas valide .fromFalsy(E.FORMULAIRE_PANIER.checkValidity()) // Ne fais rien si la livraison a déjà été validée - .chainNullable((): boolean | null => - E.BOUTON_ACTIONS_FORMULAIRE.hasAttribute(ATTRIBUT_LIVRAISON_VALIDEE) ? null : true + .chainNullable((): boolean | undefined => + E.BOUTON_ACTIONS_FORMULAIRE.hasAttribute(ATTRIBUT_LIVRAISON_VALIDEE) ? undefined : true ) .ifJust((): void => { event.preventDefault(); - /** Les données du Formulaire sans caractères vides. */ - const donneesFormulaire: Record = pipe( + /** Les données du Formulaire transformées pour la requête vers le Backend. */ + const formArgs: WCStoreCartUpdateCustomerArgs = pipe( Object.fromEntries(new FormData(E.FORMULAIRE_PANIER)) as Record, - dictMap(stringTrim), + fields => dictMap(fields, stringTrim), + fields => getAddressesFromForm(fields, E.BOUTON_SEPARATION_ADRESSES.checked), ); - /** Les données du Formulaire transformées en arguments pour la requête vers le Backend. */ - const argumentsFormulaire: WCStoreCartUpdateCustomerArgs = { - billing_address: { - address_1: donneesFormulaire["facturation-adresse"] ?? donneesFormulaire["livraison-adresse"] ?? "", - address_2: "", - city: donneesFormulaire["facturation-ville"] ?? donneesFormulaire["livraison-ville"] ?? "", - company: "", - country: E.BOUTON_SEPARATION_ADRESSES.checked - ? donneesFormulaire["facturation-pays"] ?? "" - : donneesFormulaire["livraison-pays"] ?? "", - email: donneesFormulaire["facturation-email"] ?? donneesFormulaire["livraison-email"] ?? "", - first_name: donneesFormulaire["facturation-prenom"] ?? donneesFormulaire["livraison-prenom"] ?? "", - last_name: donneesFormulaire["facturation-nom"] ?? donneesFormulaire["livraison-nom"] ?? "", - phone: donneesFormulaire["facturation-telephone"] ?? donneesFormulaire["livraison-telephone"] ?? "", - postcode: donneesFormulaire["facturation-code-postal"] ?? donneesFormulaire["livraison-code-postal"] ?? "", - state: donneesFormulaire["facturation-region-etat"] ?? donneesFormulaire["livraison-region-etat"] ?? "", - }, - shipping_address: { - address_1: donneesFormulaire["livraison-adresse"] ?? "", - address_2: "", - city: donneesFormulaire["livraison-ville"] ?? "", - company: "", - country: donneesFormulaire["livraison-pays"] ?? "", - first_name: donneesFormulaire["livraison-prenom"] ?? "", - last_name: donneesFormulaire["livraison-nom"] ?? "", - phone: donneesFormulaire["livraison-telephone"] ?? "", - postcode: donneesFormulaire["livraison-code-postal"] ?? "", - state: donneesFormulaire["livraison-region-etat"] ?? "", - }, - }; + logger.debug("ADRESSES", "initShippingCalculationButton", "formArgs", formArgs); // Réalise la requête et traite sa réponse void EitherAsync - .liftEither(eitherValiParse(argumentsFormulaire, WCStoreCartUpdateCustomerArgsSchema)) - .ifRight((): void => { - // Désactive le Bouton pour empêcher des requêtes concurrentes - majEtatChargementBouton(E.BOUTON_ACTIONS_FORMULAIRE, true); - }) + .liftEither(safeSchemaParse(formArgs, WCStoreCartUpdateCustomerArgsSchema)) + // Désactive le Bouton pour empêcher des requêtes concurrentes + .ifRight((): void => setButtonLoadingState(E.BOUTON_ACTIONS_FORMULAIRE, true)) .chain((args: WCStoreCartUpdateCustomerArgs) => - eitherAsyncFetch( - postBackend({ corps: JSON.stringify(args), nonce: ETATS_PAGE.nonce, route: ROUTE_API_MAJ_CLIENT }), - ) + safeFetch(postBackend(ROUTE_API_MAJ_CLIENT, JSON.stringify(args), false)) ) - .chain((rs: Response) => - EitherAsync(async ({ throwE }): Promise => - match(await creeReponseSimplifiee(rs)) + .chain((rs: Response) => { + logger.debug("ADRESSES", "initShippingCalculationButton", "rs", rs); + return EitherAsync(async ({ throwE }): Promise => + match(await newPartialResponse(rs)) .with({ status: 200 }, (rs): unknown => rs.body) .with( { body: P.when(body => estWCAddressError(body)), status: 400 }, (rs): never => throwE(new ErreurAdresseInvalide(rs.body.data.params)), ) .otherwise((rs): never => throwE(traiteErreursBackendWooCommerce(rs))) - ) - ) - .chain((body: unknown) => EitherAsync.liftEither(eitherValiParse(body, WCStoreCartSchema))) + ); + }) + .chain((b: unknown) => EitherAsync.liftEither(safeSchemaParse(b, WCStoreCartSchema))) .ifRight((cart: WCStoreCart): void => { - const localStorageSelectedMethod = getAndParseLocalStorage( - "shipping_rates", - WCStoreShippingRateShippingRatesSchema, - ) - .toMaybe() - .chainNullable(arrayFind(m => m.selected)); + logger.debug("ADRESSES", "initShippingCalculationButton", "cart", cart); - const updatedMethods = Maybe - .fromNullable(cart.shipping_rates.at(0)) - .chainNullable(xs => xs.shipping_rates) - .map(arrayMap(m => { - // Sélectionne la Méthode précédemment choisie - localStorageSelectedMethod.ifJust(mls => { - m.selected = m.method_id === mls.method_id; - }); - m.price = diviseParCent(m.price); - return m; - })) - .ifJust(xs => { - // Met à jour les Méthodes de livraison - window.dispatchEvent(MethodesLivraisonMajEvent(xs)); + /** La méthode de livraison sélectionnée dans le LocalStorage */ + const oldSelectedRateLS = getShippingRatesLS() + .chain(find(sr => sr.selected)) + .ifJust(sr => logger.debug("ADRESSES", "initShippingCalculationButton", "oldSelectedRateLS", sr)); - // Met à jour les Totaux - const selectedMethod = xs.find(m => m.selected)!; - const newTotals = { - ...cart.totals, - total_discount: diviseParCent(cart.totals.total_discount), - total_items: diviseParCent(cart.totals.total_items), - total_price: diviseParCent(cart.totals.total_items) - diviseParCent(cart.totals.total_discount) - + selectedMethod.price, - total_shipping: selectedMethod.price, - }; - window.dispatchEvent(TotauxMajEvent(newTotals)); - }) + /* Les méthodes de livraison mises à jour avec le nouveau choix de l'Utilisateur. */ + const updatedRates = first(cart.shipping_rates) + .chainNullable((sr: WCStoreShippingRate) => sr.shipping_rates) + .map((srs: Array) => + srs.map((sr: WCStoreShippingRateShippingRate, index: number) => { + // Sélectionne la nouvelle méthode demandée OU la première si le LocalStorage n'a pas été défini + oldSelectedRateLS.caseOf({ + Just: sm => { + sr.selected = sr.method_id === sm.method_id; + }, + Nothing: () => { + sr.selected = index === 0; + }, + }); + + // Formate le prix correctement + sr.price = diviseParCent(sr.price); + + return sr; + }) + ) .orDefault([]); + logger.debug("ADRESSES", "initShippingCalculationButton", "updatedRates", updatedRates); + // Met à jour les Méthodes de livraison dans le LocalStorage et le DOM + window.dispatchEvent(createUpdatedShippingRatesEvent(updatedRates, true)); + + // Met à jour les Totaux + const newShippingPrice = updatedRates.find(m => m.selected)?.price ?? 0; + const newTotals = { + ...cart.totals, + total_discount: diviseParCent(cart.totals.total_discount), + total_items: diviseParCent(cart.totals.total_items), + total_price: diviseParCent(cart.totals.total_items) - diviseParCent(cart.totals.total_discount) + + newShippingPrice, + total_shipping: newShippingPrice, + }; + logger.debug("ADRESSES", "initShippingCalculationButton", "newTotals", newTotals); + window.dispatchEvent(createUpdatedTotalsEvent(newTotals)); - // Affiche les nouvelles Méthodes à l'Utilisateur - genereHtmlMethodesLivraison(E.CONTENEUR_METHODES_LIVRAISON, updatedMethods); // Réinitialise le Message affiché à l'Utiisateur E.MESSAGE_ADRESSES.textContent = " "; // Active le Bouton pour la création de la Commande @@ -206,10 +202,12 @@ export const initialiseBoutonCalculLivraison = (): void => { match(err) .with(P.instanceOf(ValiError), (e: ValiError): void => { reporteEtJournaliseErreur(e); + console.error(e.issues); E.MESSAGE_ADRESSES.textContent = ERREUR_GENERIQUE_SOUMISSION_ADRESSES; }) .with(P.instanceOf(ErreurAdresseInvalide), (e: ErreurAdresseInvalide): void => { reporteEtJournaliseErreur(e); + // TODO: Créer une fonction pour traiter les cas d'erreurs spécifiques match(e.problemes) .when( // TODO: Créer une fonction utilitaire @@ -236,158 +234,103 @@ export const initialiseBoutonCalculLivraison = (): void => { E.BOUTON_ACTIONS_FORMULAIRE.textContent = "Submit your addresses"; }, ) - .finally((): void => { - // Désactive l'animation de chargement et rend le Bouton de nouveau cliquable - majEtatChargementBouton(E.BOUTON_ACTIONS_FORMULAIRE, false); - }) + // Désactive l'animation de chargement et rend le Bouton de nouveau cliquable + .finally((): void => setButtonLoadingState(E.BOUTON_ACTIONS_FORMULAIRE, false)) .run(); }) .ifNothing((): void => event.preventDefault()); }); }; -export const initialiseBoutonCreationCommande = (): void => { - // Créé la Commande au clic sur le Bouton +export const initOrderCreationButton = (): void => { + logger.debug("ADRESSES", "initOrderCreationButton"); + // Créé la Commande au clic sur le Bouton de soumission du Formulaire E.BOUTON_ACTIONS_FORMULAIRE.addEventListener("click", (event: Event): void => { + logger.info("ADRESSES", "Demande de création de commande"); Maybe // Ne fais rien si le Formulaire n'est pas valide .fromFalsy( E.FORMULAIRE_PANIER.checkValidity() && E.BOUTON_ACTIONS_FORMULAIRE.hasAttribute(ATTRIBUT_LIVRAISON_VALIDEE), ) - // Active l'état de chargement .ifJust((): void => { event.preventDefault(); - /** Les données du Formulaire sans caractères vides. */ - const donneesFormulaire: Record = pipe( + const formFields: Record = pipe( Object.fromEntries(new FormData(E.FORMULAIRE_PANIER)) as Record, dictMap(stringTrim), ); /** La méthode de livraison sélectionnée ; interrompt la requête si incorrect. */ - const methodeLivraison: WCStoreShippingRateShippingRate = getAndParseLocalStorage( - "shipping_rates", - WCStoreShippingRateShippingRatesSchema, - ) - .ifLeft((erreur: NonExistingKeyError | SyntaxError | ValiError): void => { - match(erreur) - .with(P.instanceOf(ValiError), (e): void => { - reporteErreur(e); - console.error(e.issues); - }) - .otherwise(reporteEtJournaliseErreur); - - localStorage.removeItem("shipping_rates"); - + const selectedRateLS: WCStoreShippingRateShippingRate = getShippingRatesLS() + .ifNothing((): void => { // Rétablis le Formulaire à son état d'origine E.MESSAGE_ADRESSES.textContent = ERREUR_GENERIQUE_SOUMISSION_ADRESSES; emetUniqueMessageBroadcastChannel(NOM_CANAL_REVALIDATION_LIVRAISON, true); - // Interrompt la requête - leveErreur(erreur); + throw new Error("LocalStorage indisponible."); }) - .toMaybe() - .chainNullable((methodes: WCStoreShippingRateShippingRates) => methodes.at(0)) + .chain(first) .orDefault({}); + logger.debug("ADRESSES", "initOrderCreationButton", "selectedRateLS", selectedRateLS); /** Les Produits du Panier. */ - const produitsPanier = E.ENTREES_PANIER_EITHER + const cartProducts = E.ENTREES_PANIER .orDefault([]) - .map((entree: HTMLElement) => ({ - product_id: Number(entree.getAttribute("data-id-produit")), - quantity: Number(entree.getAttribute("data-quantite")), - ...(entree.getAttribute("data-id-variation") && { - variation_id: Number(entree.getAttribute("data-id-variation")), + .map((entry: HTMLElement) => ({ + product_id: Number(entry.getAttribute("data-id-produit")), + quantity: Number(entry.getAttribute("data-quantite")), + ...(entry.getAttribute("data-id-variation") && { + variation_id: Number(entry.getAttribute("data-id-variation")), }), })); + logger.debug("ADRESSES", "initOrderCreationButton", "cartProducts", cartProducts); - /** Les données du Formulaire transformées en arguments pour la requête vers le Backend. */ - const argumentsFormulaire: WCV3OrdersArgs = { - billing: { - address_1: donneesFormulaire["facturation-adresse"] ?? donneesFormulaire["livraison-adresse"] ?? "", - address_2: "", - city: donneesFormulaire["facturation-ville"] ?? donneesFormulaire["livraison-ville"] ?? "", - company: "", - country: E.BOUTON_SEPARATION_ADRESSES.checked - ? donneesFormulaire["facturation-pays"] ?? "" - : donneesFormulaire["livraison-pays"] ?? "", - email: donneesFormulaire["facturation-email"] ?? donneesFormulaire["livraison-email"] ?? "", - first_name: donneesFormulaire["facturation-prenom"] ?? donneesFormulaire["livraison-prenom"] ?? "", - last_name: donneesFormulaire["facturation-nom"] ?? donneesFormulaire["livraison-nom"] ?? "", - phone: donneesFormulaire["facturation-telephone"] ?? donneesFormulaire["livraison-telephone"] ?? "", - postcode: donneesFormulaire["facturation-code-postal"] ?? donneesFormulaire["livraison-code-postal"] ?? "", - state: donneesFormulaire["facturation-region-etat"] ?? donneesFormulaire["livraison-region-etat"] ?? "", - }, - currency: methodeLivraison.currency_code, + /** Les données du Formulaire transformées pour la requête vers le Backend. */ + const formArgs: WCV3OrdersArgs = { + ...getAddressesFromForm(formFields, E.BOUTON_SEPARATION_ADRESSES.checked), + currency: selectedRateLS.currency_code, customer_note: E.INSTRUCTIONS_CLIENT.value, - line_items: produitsPanier, - shipping: { - address_1: donneesFormulaire["livraison-adresse"] ?? "", - address_2: "", - city: donneesFormulaire["livraison-ville"] ?? "", - company: "", - country: donneesFormulaire["livraison-pays"] ?? "", - first_name: donneesFormulaire["livraison-prenom"] ?? "", - last_name: donneesFormulaire["livraison-nom"] ?? "", - phone: donneesFormulaire["livraison-telephone"] ?? "", - postcode: donneesFormulaire["livraison-code-postal"] ?? "", - state: donneesFormulaire["livraison-region-etat"] ?? "", - }, + line_items: cartProducts, shipping_lines: [ { - method_id: methodeLivraison.method_id, - method_title: methodeLivraison.name, - total: pipe(diviseParCent(methodeLivraison.price), String), + method_id: selectedRateLS.method_id, + method_title: selectedRateLS.name, + total: pipe(diviseParCent(selectedRateLS.price), String), }, ], }; + logger.debug("ADRESSES", "initOrderCreationButton", "formArgs", formArgs); // Réalise la requête et traite sa réponse void EitherAsync - // 1. Valide les Arguments de la Requête - .liftEither(eitherValiParse(argumentsFormulaire, WCV3OrdersArgsSchema)) - // 2. Exécute un Effet pour empêcher les requêtes concurrentes et lancer une animation de chargement - .ifRight((): void => { - // Désactive le Bouton pour empêcher des requêtes concurrentes - majEtatChargementBouton(E.BOUTON_ACTIONS_FORMULAIRE, true); - }) - // 3. Exécute la requête via fetch sous form d'EitherAsync + .liftEither(safeSchemaParse(formArgs, WCV3OrdersArgsSchema)) + // Désactive le Bouton pour empêcher des requêtes concurrentes + .ifRight((): void => setButtonLoadingState(E.BOUTON_ACTIONS_FORMULAIRE, true)) .chain((args: WCV3OrdersArgs) => - eitherAsyncFetch( - postBackend({ - authString: ETATS_PAGE.authString, - corps: JSON.stringify(args), - nonce: ETATS_PAGE.nonce, - route: ROUTE_API_NOUVELLE_COMMANDES, - }), - ) + safeFetch(postBackend(ROUTE_API_NOUVELLE_COMMANDES, JSON.stringify(args), true)) ) - // 4. Traite les cas d'Erreurs et récupère le Corps de la Réponse - .chain((reponse: Response) => + .chain((rs: Response) => EitherAsync(async ({ throwE }): Promise => - match(await creeReponseSimplifiee(reponse)) + match(await newPartialResponse(rs)) .with({ status: 201 }, (rs): unknown => rs.body) .otherwise((rs): never => throwE(traiteErreursBackendWooCommerce(rs))) ) ) - // 5. Vérifie le Schéma de la Réponse - .chain((corps: unknown) => EitherAsync.liftEither(eitherValiParse(corps, WCV3OrderSchema))) - // 6. Exécute un Effet pour la mise à jour du DOM avec les Résultats - .ifRight((commande: WCV3Order): void => { + .chain((b: unknown) => EitherAsync.liftEither(safeSchemaParse(b, WCV3OrderSchema))) + .ifRight((order: WCV3Order): void => { E.BOUTON_ACTIONS_FORMULAIRE.removeAttribute(ATTRIBUT_CHARGEMENT); E.BOUTON_ACTIONS_FORMULAIRE.textContent = "OK!"; E.MESSAGE_ADRESSES.textContent = " "; // Redirige vers Stripe - // Maybe - // .fromNullable(new URL(`https://${window.location.host}/checkout`)) - // .ifJust(url => url.searchParams.append("order_key", commande.order_key)) - // .ifJust(url => url.searchParams.append("order_id", String(commande.id))) - // .ifJust(url => location.assign(url)); + Maybe + .fromNullable(new URL(`https://${window.location.host}/checkout`)) + .ifJust(url => url.searchParams.append("order_key", order.order_key)) + .ifJust(url => url.searchParams.append("order_id", String(order.id))) + .ifJust(url => location.assign(url)); }) - // 7. Traite les Erreurs et affiche un message à l'Utilisateur - .ifLeft((erreur: FetchErrors | HttpCodeErrors | ValiError): void => { - match(erreur) + .ifLeft((err: FetchErrors | HttpCodeErrors | ValiError): void => { + match(err) .with(P.instanceOf(ValiError), (e: ValiError): void => { reporteEtJournaliseErreur(e); console.error(e.issues); @@ -404,7 +347,7 @@ export const initialiseBoutonCreationCommande = (): void => { .exhaustive(); // Désactive l'animation de chargement et rend le Bouton de nouveau cliquable - majEtatChargementBouton(E.BOUTON_ACTIONS_FORMULAIRE, false); + setButtonLoadingState(E.BOUTON_ACTIONS_FORMULAIRE, false); E.BOUTON_ACTIONS_FORMULAIRE.textContent = "Checkout"; }) .run(); diff --git a/web/app/themes/haiku-atelier-2024/src/scripts/page-panier/scripts-page-panier-code-promo.ts b/web/app/themes/haiku-atelier-2024/src/scripts/page-panier/scripts-page-panier-code-promo.ts index 1ba18031..49634135 100755 --- a/web/app/themes/haiku-atelier-2024/src/scripts/page-panier/scripts-page-panier-code-promo.ts +++ b/web/app/themes/haiku-atelier-2024/src/scripts/page-panier/scripts-page-panier-code-promo.ts @@ -10,8 +10,8 @@ import { ValiError } from "valibot"; import type { WCStoreCart } from "../lib/types/api/cart"; import type { WCStoreCartApplyCouponArgs } from "../lib/types/api/cart-apply-coupon"; import type { WCStoreCartRemoveCouponArgs } from "../lib/types/api/cart-remove-coupon"; -import type { EtatsPageGenerique } from "../lib/types/pages"; -import type { ReponseSimplifiee } from "../lib/types/reseau"; +import type { GenericPageState } from "../lib/types/pages"; +import type { SimplifiedResponse } from "../lib/types/reseau"; import { ROUTE_API_APPLIQUE_COUPON, ROUTE_API_RETIRE_COUPON } from "../constantes/api"; import { ERREUR_CODE_PROMO_INVALIDE } from "../constantes/api/erreurs"; @@ -21,16 +21,10 @@ import { ATTRIBUT_DESACTIVE, ATTRIBUT_HIDDEN, SELECTEUR_BOUTON_CODE_PROMO, - SELECTEUR_CHAMP_CODE_PROMO, - SELECTEUR_ENSEMBLE_CODE_PROMO, - SELECTEUR_MESSAGE_CODE_PROMO, - SELECTEUR_TOTAL_PANIER, - SELECTEUR_TOTAL_REDUCTION, - SELECTEUR_TOTAL_REDUCTION_VALEUR, } from "../constantes/dom"; import { NOM_CANAL_REVALIDATION_LIVRAISON } from "../constantes/messages"; import { lanceAnimationCycleLoading } from "../lib/animations"; -import { accorderCibleASelecteur } from "../lib/dom"; +import { targetMatchesSelector } from "../lib/dom"; import { reporteErreur, ServerError } from "../lib/erreurs"; import { ErreurCodePromoInvalide } from "../lib/erreurs/codes-promo"; import { CODE_PROMO_MAJ_EVENT } from "../lib/evenements/panier"; @@ -41,22 +35,12 @@ import { postBackend } from "../lib/reseau"; import { WCStoreCartSchema } from "../lib/schemas/api/cart"; import { WCStoreCartApplyCouponArgsSchema } from "../lib/schemas/api/cart-apply-coupon"; import { WCStoreCartRemoveCouponArgsSchema } from "../lib/schemas/api/cart-remove-coupon"; -import { recupereEleOuLeve } from "../lib/utils"; -import { eitherValiParse } from "../lib/validation"; +import { safeSchemaParse } from "../lib/validation"; +import { E } from "./scripts-page-panier-elements"; // @ts-expect-error -- États injectés par le modèle PHP // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment -- États injectés par le modèle PHP -const ETATS_PAGE: EtatsPageGenerique = _etats; - -const E = { - BOUTON_CODE_PROMO: recupereEleOuLeve(SELECTEUR_BOUTON_CODE_PROMO), - CHAMP_CODE_PROMO: recupereEleOuLeve(SELECTEUR_CHAMP_CODE_PROMO), - ENSEMBLE_CODE_PROMO: recupereEleOuLeve(SELECTEUR_ENSEMBLE_CODE_PROMO), - MESSAGE_CODE_PROMO: recupereEleOuLeve(SELECTEUR_MESSAGE_CODE_PROMO), - TOTAL_PANIER: recupereEleOuLeve(SELECTEUR_TOTAL_PANIER), - TOTAL_REDUCTION_LIGNE: recupereEleOuLeve(SELECTEUR_TOTAL_REDUCTION), - TOTAL_REDUCTION_VALEUR: recupereEleOuLeve(SELECTEUR_TOTAL_REDUCTION_VALEUR), -}; +const ETATS_PAGE: GenericPageState = _etats; export const initialiseElementsCodePromo = (): void => { const recupereValeurCodePromo = (): null | string => @@ -75,7 +59,7 @@ export const initialiseElementsCodePromo = (): void => { .with( { cible: P.when((cible: EventTarget | null) => - accorderCibleASelecteur(cible, SELECTEUR_BOUTON_CODE_PROMO) + targetMatchesSelector(cible, SELECTEUR_BOUTON_CODE_PROMO) ), codePromoPresent: false, valeurCodePromo: P.string, @@ -83,7 +67,7 @@ export const initialiseElementsCodePromo = (): void => { ({ valeurCodePromo }) => void EitherAsync // Vérifie le Schéma des arguments - .liftEither(eitherValiParse({ code: valeurCodePromo }, WCStoreCartApplyCouponArgsSchema)) + .liftEither(safeSchemaParse({ code: valeurCodePromo }, WCStoreCartApplyCouponArgsSchema)) .ifRight(() => { // Désactive le Bouton pour empêcher des requêtes concurrentes E.BOUTON_CODE_PROMO.setAttribute(ATTRIBUT_DESACTIVE, ""); @@ -105,7 +89,7 @@ export const initialiseElementsCodePromo = (): void => { // Traite les cas d'Erreur .chain((reponse: Response) => EitherAsync(async ({ throwE }) => { - const reponseSimplifiee: ReponseSimplifiee = { + const reponseSimplifiee: SimplifiedResponse = { body: await reponse.json(), status: reponse.status, }; @@ -121,7 +105,7 @@ export const initialiseElementsCodePromo = (): void => { }) ) // Vérifie le Schéma de la Réponse du backend - .chain((corpsReponse: unknown) => EitherAsync.liftEither(eitherValiParse(corpsReponse, WCStoreCartSchema))) + .chain((corpsReponse: unknown) => EitherAsync.liftEither(safeSchemaParse(corpsReponse, WCStoreCartSchema))) // Déclenche les mises à jour du DOM avec les données du nouveau Panier .ifRight((panier: WCStoreCart) => { E.ENSEMBLE_CODE_PROMO.toggleAttribute(ATTRIBUT_CODE_PROMO_PRESENT); @@ -186,13 +170,13 @@ export const initialiseElementsCodePromo = (): void => { // Un code promo est présent sous forme de chaîne .with( { - cible: P.when(cible => accorderCibleASelecteur(cible, SELECTEUR_BOUTON_CODE_PROMO)), + cible: P.when(cible => targetMatchesSelector(cible, SELECTEUR_BOUTON_CODE_PROMO)), codePromoPresent: true, valeurCodePromo: P.string, }, ({ valeurCodePromo }) => void EitherAsync - .liftEither(eitherValiParse({ code: valeurCodePromo }, WCStoreCartRemoveCouponArgsSchema)) + .liftEither(safeSchemaParse({ code: valeurCodePromo }, WCStoreCartRemoveCouponArgsSchema)) .ifRight(() => { E.BOUTON_CODE_PROMO.setAttribute(ATTRIBUT_DESACTIVE, ""); E.BOUTON_CODE_PROMO.setAttribute(ATTRIBUT_CHARGEMENT, ""); @@ -212,7 +196,7 @@ export const initialiseElementsCodePromo = (): void => { return await reponse.json(); }) ) - .chain((corpsReponse: unknown) => EitherAsync.liftEither(eitherValiParse(corpsReponse, WCStoreCartSchema))) + .chain((corpsReponse: unknown) => EitherAsync.liftEither(safeSchemaParse(corpsReponse, WCStoreCartSchema))) .ifRight((panier: WCStoreCart) => { E.ENSEMBLE_CODE_PROMO.toggleAttribute(ATTRIBUT_CODE_PROMO_PRESENT); E.ENSEMBLE_CODE_PROMO.reset(); diff --git a/web/app/themes/haiku-atelier-2024/src/scripts/page-panier/scripts-page-panier-elements.ts b/web/app/themes/haiku-atelier-2024/src/scripts/page-panier/scripts-page-panier-elements.ts new file mode 100644 index 00000000..e54422c3 --- /dev/null +++ b/web/app/themes/haiku-atelier-2024/src/scripts/page-panier/scripts-page-panier-elements.ts @@ -0,0 +1,48 @@ +import { + SELECTEUR_BOUTON_ACTIONS_FORMULAIRE, + SELECTEUR_BOUTON_CODE_PROMO, + SELECTEUR_BOUTON_SEPARATION_ADRESSES, + SELECTEUR_CHAMP_CODE_PROMO, + SELECTEUR_CONTENEUR_METHODES_LIVRAISON, + SELECTEUR_CONTENEUR_PANIER, + SELECTEUR_ENSEMBLE_CODE_PROMO, + SELECTEUR_ENTREES_PANIER, + SELECTEUR_FORMULAIRE_FACTURATION, + SELECTEUR_FORMULAIRE_PANIER, + SELECTEUR_INSTRUCTIONS_CLIENT, + SELECTEUR_MESSAGE_CODE_PROMO, + SELECTEUR_MESSAGE_FORMULAIRE_ADRESSES, + SELECTEUR_SOUS_TOTAL_LIVRAISON_COUT, + SELECTEUR_SOUS_TOTAL_PRODUITS, + SELECTEUR_TOTAL_PANIER, + SELECTEUR_TOTAL_REDUCTION, + SELECTEUR_TOTAL_REDUCTION_VALEUR, +} from "../constantes/dom"; +import { mustGetEleInDocument, recupereElementsDocumentEither } from "../lib/dom"; + +export const E = { + BOUTON_ACTIONS_FORMULAIRE: mustGetEleInDocument(SELECTEUR_BOUTON_ACTIONS_FORMULAIRE), + BOUTON_CODE_PROMO: mustGetEleInDocument(SELECTEUR_BOUTON_CODE_PROMO), + BOUTON_SEPARATION_ADRESSES: mustGetEleInDocument(SELECTEUR_BOUTON_SEPARATION_ADRESSES), + CHAMP_CODE_PROMO: mustGetEleInDocument(SELECTEUR_CHAMP_CODE_PROMO), + CONTENEUR_METHODES_LIVRAISON: mustGetEleInDocument(SELECTEUR_CONTENEUR_METHODES_LIVRAISON), + CONTENEUR_PANIER: mustGetEleInDocument(SELECTEUR_CONTENEUR_PANIER), + ENSEMBLE_CODE_PROMO: mustGetEleInDocument(SELECTEUR_ENSEMBLE_CODE_PROMO), + ENTREES_PANIER: recupereElementsDocumentEither( + SELECTEUR_ENTREES_PANIER, + ), + FORMULAIRE_FACTURATION: mustGetEleInDocument(SELECTEUR_FORMULAIRE_FACTURATION), + FORMULAIRE_PANIER: mustGetEleInDocument(SELECTEUR_FORMULAIRE_PANIER), + INSTRUCTIONS_CLIENT: mustGetEleInDocument(SELECTEUR_INSTRUCTIONS_CLIENT), + MESSAGE_ADRESSES: mustGetEleInDocument(SELECTEUR_MESSAGE_FORMULAIRE_ADRESSES), + MESSAGE_CODE_PROMO: mustGetEleInDocument(SELECTEUR_MESSAGE_CODE_PROMO), + SOUS_TOTAL_LIVRAISON_VALEUR: mustGetEleInDocument(SELECTEUR_SOUS_TOTAL_LIVRAISON_COUT), + SOUS_TOTAL_PRODUITS: mustGetEleInDocument(SELECTEUR_SOUS_TOTAL_PRODUITS), + SOUS_TOTAL_PRODUITS_VALEUR: mustGetEleInDocument(SELECTEUR_SOUS_TOTAL_PRODUITS), + SOUS_TOTAL_REDUCTION: mustGetEleInDocument(SELECTEUR_TOTAL_REDUCTION_VALEUR), + SOUS_TOTAL_REDUCTION_VALEUR: mustGetEleInDocument(SELECTEUR_TOTAL_REDUCTION_VALEUR), + TOTAL_PANIER: mustGetEleInDocument(SELECTEUR_TOTAL_PANIER), + TOTAL_PANIER_VALEUR: mustGetEleInDocument(SELECTEUR_TOTAL_PANIER), + TOTAL_REDUCTION_LIGNE: mustGetEleInDocument(SELECTEUR_TOTAL_REDUCTION), + TOTAL_REDUCTION_VALEUR: mustGetEleInDocument(SELECTEUR_TOTAL_REDUCTION_VALEUR), +}; diff --git a/web/app/themes/haiku-atelier-2024/src/scripts/page-panier/scripts-page-panier-evenement.ts b/web/app/themes/haiku-atelier-2024/src/scripts/page-panier/scripts-page-panier-evenement.ts index 356a209b..bebf4ba5 100755 --- a/web/app/themes/haiku-atelier-2024/src/scripts/page-panier/scripts-page-panier-evenement.ts +++ b/web/app/themes/haiku-atelier-2024/src/scripts/page-panier/scripts-page-panier-evenement.ts @@ -1,28 +1,15 @@ import { Either } from "purify-ts"; -import type { MethodesLivraisonMajEvent, TotauxMajEvent } from "../lib/evenements/panier"; +import type { UpdatedShippingRatesEvent, UpdatedTotalsEvent } from "../lib/evenements/panier"; -import { - ATTRIBUT_LIVRAISON_VALIDEE, - SELECTEUR_BOUTON_ACTIONS_FORMULAIRE, - SELECTEUR_SOUS_TOTAL_LIVRAISON_COUT, - SELECTEUR_SOUS_TOTAL_PRODUITS, - SELECTEUR_TOTAL_PANIER, - SELECTEUR_TOTAL_REDUCTION_VALEUR, -} from "../constantes/dom"; -import { ADRESSES_MAJ, CODE_PROMO_MAJ, METHODES_LIVRAISON_MAJ, TOTAUX_MAJ } from "../constantes/evenements"; +import { ATTRIBUT_LIVRAISON_VALIDEE } from "../constantes/dom"; +import { ADRESSES_MAJ, CODE_PROMO_MAJ, SHIPPING_RATES_UPDATED, TOTALS_UPDATED } from "../constantes/evenements"; import { reporteEtJournaliseErreur } from "../lib/erreurs"; -import { setLocalStorage } from "../lib/local-storage"; +import { eitherSetLocalStorage } from "../lib/local-storage"; import { formateEnEuros } from "../lib/nombres"; -import { recupereEleOuLeve } from "../lib/utils"; - -const E = { - BOUTON_ACTIONS_FORMULAIRE: recupereEleOuLeve(SELECTEUR_BOUTON_ACTIONS_FORMULAIRE), - SOUS_TOTAL_LIVRAISON_VALEUR: recupereEleOuLeve(SELECTEUR_SOUS_TOTAL_LIVRAISON_COUT), - SOUS_TOTAL_PRODUITS_VALEUR: recupereEleOuLeve(SELECTEUR_SOUS_TOTAL_PRODUITS), - SOUS_TOTAL_REDUCTION_VALEUR: recupereEleOuLeve(SELECTEUR_TOTAL_REDUCTION_VALEUR), - TOTAL_PANIER_VALEUR: recupereEleOuLeve(SELECTEUR_TOTAL_PANIER), -}; +import { logger } from "../logging"; +import { E } from "./scripts-page-panier-elements"; +import { generateShippingRatesHTML } from "./scripts-page-panier-methodes-livraison"; /** * Réinitialise le bouton de soumission du Formulaire en revenant à l'étape de validation des adresses. @@ -48,23 +35,29 @@ export const souscrisEvenementsPanier = (): void => { reinitialiseValidationLivraison(); }); - window.addEventListener(METHODES_LIVRAISON_MAJ, (event: Event): void => { + window.addEventListener(SHIPPING_RATES_UPDATED, (event: Event): void => { Either // La vérification du schéma se fait à l'émission - .encase(() => (event as MethodesLivraisonMajEvent).detail.methodes) - .chain(ms => setLocalStorage("shipping_rates", ms)) - .ifLeft(reporteEtJournaliseErreur) + .encase(() => (event as UpdatedShippingRatesEvent).detail) // Met à jour le DOM - .ifRight(ms => console.debug("methods", ms)) - .toMaybe() - .chainNullable(xs => xs.find(m => m.selected)); + .ifRight(event => { + logger.info("ShippingRatesUpdatedEvent", "shipping_rates", event); + // Met à jour les Méthodes à l'Utilisateur si demandé + // Il peut y en avoir aucune + if (event.refresh_methods) { + generateShippingRatesHTML(E.CONTENEUR_METHODES_LIVRAISON, event.shipping_rates); + } + }) + // Met à jour le LocalStorage + .chain(event => eitherSetLocalStorage("shipping_rates", event.shipping_rates)) + .ifLeft(reporteEtJournaliseErreur); }); - window.addEventListener(TOTAUX_MAJ, (event: Event): void => { + window.addEventListener(TOTALS_UPDATED, (event: Event): void => { Either // La vérification du Schéma se fait à l'émission - .encase(() => (event as TotauxMajEvent).detail.totaux) - .chain(ts => setLocalStorage("totals", ts)) + .encase(() => (event as UpdatedTotalsEvent).detail.totals) + .chain(ts => eitherSetLocalStorage("totals", ts)) .ifLeft(reporteEtJournaliseErreur) // Met à jour le DOM .ifRight(ts => { diff --git a/web/app/themes/haiku-atelier-2024/src/scripts/page-panier/scripts-page-panier-local-storage.ts b/web/app/themes/haiku-atelier-2024/src/scripts/page-panier/scripts-page-panier-local-storage.ts new file mode 100644 index 00000000..6a1b0776 --- /dev/null +++ b/web/app/themes/haiku-atelier-2024/src/scripts/page-panier/scripts-page-panier-local-storage.ts @@ -0,0 +1,21 @@ +import type { Maybe } from "purify-ts"; + +import type { WCStoreShippingRateShippingRates } from "../lib/types/api/couts-livraison"; + +import { reporteEtJournaliseErreur } from "../lib/erreurs"; +import { getLocalStorageByKey, setLocalStorageByKey } from "../lib/local-storage"; +import { WCStoreShippingRateShippingRatesSchema } from "../lib/schemas/api/couts-livraison"; + +/* LS = LocalStorage */ + +export const getShippingRatesLS = (): Maybe => + getLocalStorageByKey("shipping_rates", WCStoreShippingRateShippingRatesSchema) + .ifLeft(reporteEtJournaliseErreur) + .toMaybe(); + +export const setShippingRatesLS = ( + shippingRates: WCStoreShippingRateShippingRates, +): Maybe => + setLocalStorageByKey("shipping_rates", WCStoreShippingRateShippingRatesSchema)(shippingRates) + .ifLeft(reporteEtJournaliseErreur) + .toMaybe(); diff --git a/web/app/themes/haiku-atelier-2024/src/scripts/page-panier/scripts-page-panier-methodes-livraison.ts b/web/app/themes/haiku-atelier-2024/src/scripts/page-panier/scripts-page-panier-methodes-livraison.ts index 3930428a..ffe06ebf 100755 --- a/web/app/themes/haiku-atelier-2024/src/scripts/page-panier/scripts-page-panier-methodes-livraison.ts +++ b/web/app/themes/haiku-atelier-2024/src/scripts/page-panier/scripts-page-panier-methodes-livraison.ts @@ -1,81 +1,73 @@ -import { find as arrayFind, forEach as arrayForEach, map as arrayMap } from "@mobily/ts-belt/Array"; +import { forEach as arrayForEach, map as arrayMap } from "@mobily/ts-belt/Array"; import { html, render, type TemplateResult } from "lit-html"; -import type { WCStoreShippingRateShippingRate } from "../lib/types/api/cart"; +import type { WCStoreCartTotals, WCStoreShippingRateShippingRate } from "../lib/types/api/cart"; +import type { WCStoreShippingRateShippingRates } from "../lib/types/api/couts-livraison"; -import { ATTRIBUT_HIDDEN, SELECTEUR_CONTENEUR_METHODES_LIVRAISON } from "../constantes/dom"; -import { recupereElementsAvecSelecteur } from "../lib/dom"; +import { ATTRIBUT_HIDDEN } from "../constantes/dom"; +import { forEach, map } from "../lib/arrays"; +import { getDOMElementsWithSelector } from "../lib/dom"; import { reporteEtJournaliseErreur } from "../lib/erreurs"; -import { MethodesLivraisonMajEvent, TotauxMajEvent } from "../lib/evenements/panier"; -import { getAndParseLocalStorage } from "../lib/local-storage"; +import { createUpdatedShippingRatesEvent, createUpdatedTotalsEvent } from "../lib/evenements/panier"; +import { getLocalStorageByKey } from "../lib/local-storage"; import { formateEnEuros } from "../lib/nombres"; +import { find } from "../lib/safe-arrays"; import { WCStoreCartTotalsSchema } from "../lib/schemas/api/cart"; -import { WCStoreShippingRateShippingRatesSchema } from "../lib/schemas/api/couts-livraison"; -import { recupereEleOuLeve } from "../lib/utils"; +import { logger } from "../logging"; +import { E } from "./scripts-page-panier-elements"; +import { getShippingRatesLS } from "./scripts-page-panier-local-storage"; -const E = { - CONTENEUR_METHODES_LIVRAISON: recupereEleOuLeve(SELECTEUR_CONTENEUR_METHODES_LIVRAISON), -}; +export const initShippingRatesChoicesActions = (): void => { + logger.debug("METHODES_LIVRAISON", "initShippingRatesChoicesActions"); + getDOMElementsWithSelector(E.CONTENEUR_METHODES_LIVRAISON)("input") + .ifRight(forEach((el: HTMLInputElement): void => + el.addEventListener("click", (event: MouseEvent): void => { + logger.info("METHODES_LIVRAISON", "Clic sur un choix de méthode de livraison"); -/** - * Créé un Événement MethodesLivraisonMaj déclenché quand l'Utilisateur change son choix avec en corps un object ShippingRates - * À l'Émission, sauvegarde les méthodes mises à jour dans le LocalStorage et met à jour le DOM - * Le déclenchement de la mise à jour des adresses déclenche aussi cet Événement. - * Le LocalStorage est comparé avec la Réponse, et si la méthode jusqe-là sélectionnée est présente dans la Réponse, la mise à jour du DOM doit se faire en conservant ce choix. - */ - -export const initialiseBoutonsChoixMethodesLivraison = (): void => { - recupereElementsAvecSelecteur(E.CONTENEUR_METHODES_LIVRAISON)("input").ifRight( - arrayForEach((i): void => - i.addEventListener("click", (evenement: MouseEvent): void => { - getAndParseLocalStorage("shipping_rates", WCStoreShippingRateShippingRatesSchema) - .ifLeft(reporteEtJournaliseErreur) - .map(arrayMap(m => { - // Met à jour la Méthode sélectionnée - m.selected = m.method_id === (evenement.target as HTMLInputElement).value; - return m; + // Récupère les méthodes du LocalStorage et les met à jour avec le nouveau choix + getShippingRatesLS() + // Met à jour la sélection de la Méthode + .map(map((sr: WCStoreShippingRateShippingRate) => { + sr.selected = sr.method_id === (event.target as HTMLInputElement).value; + return sr; })) - // Émet l'Événement de màj des Méthodes - .ifRight(xs => window.dispatchEvent(MethodesLivraisonMajEvent(xs))) - .toMaybe() - .chainNullable(arrayFind(m => m.selected)) - .ifJust(m => { - // Émet l'Événement de màj des Totaux - getAndParseLocalStorage("totals", WCStoreCartTotalsSchema) + // Met à jour les Méthodes de livraison dans le LocalStorage et le DOM + .ifJust((srs: WCStoreShippingRateShippingRates): void => { + window.dispatchEvent(createUpdatedShippingRatesEvent(srs, false)); + }) + // Met à jour les totaux dans le LocalStorage et le DOM + .chain(find(sr => sr.selected)) + .ifJust((sr: WCStoreShippingRateShippingRate): void => { + getLocalStorageByKey("totals", WCStoreCartTotalsSchema) .ifLeft(reporteEtJournaliseErreur) - .map(ts => { - ts.total_shipping = m.price; - ts.total_price = ts.total_items - ts.total_discount + m.price; + .map((ts: WCStoreCartTotals): WCStoreCartTotals => { + ts.total_shipping = sr.price; + ts.total_price = ts.total_items - ts.total_discount + sr.price; return ts; }) - .ifRight(t => window.dispatchEvent(TotauxMajEvent(t))); + .ifRight((ts: WCStoreCartTotals): void => { + window.dispatchEvent(createUpdatedTotalsEvent(ts)); + }); }); }) - ), - ); + )); }; -export const genereHtmlMethodesLivraison = ( - conteneur: HTMLElement, - methodes: ReadonlyArray, +export const generateShippingRatesHTML = ( + container: HTMLElement, + shippingRates: ReadonlyArray, ): void => { - // Cache les méthodes s'il n'y en a pas - if (methodes.length === 0) { - conteneur.setAttribute(ATTRIBUT_HIDDEN, ""); + // Cache les méthodes s'il n'y en a pas sans continuer + if (shippingRates.length === 0) { + container.setAttribute(ATTRIBUT_HIDDEN, ""); return; } // Retire les méthodes de livraison initiales - recupereElementsAvecSelecteur(conteneur)("div[data-methode-initiale]").ifRight(arrayForEach(div => div.remove())); + getDOMElementsWithSelector(container)("div[data-methode-initiale]").ifRight(arrayForEach(div => div.remove())); - const methodeSelectionnee: string = getAndParseLocalStorage("shipping_rates", WCStoreShippingRateShippingRatesSchema) - .ifLeft(reporteEtJournaliseErreur) - .toMaybe() - .chainNullable(arrayFind(m => m.selected)) - .map(m => m.method_id) - .orDefault(""); - - const methodesHtml: ReadonlyArray = arrayMap(methodes, methode => { + const selectedShippingRate: string = shippingRates.find(sr => sr.selected)?.method_id ?? ""; + const shippingRatesHTML: ReadonlyArray = arrayMap(shippingRates, methode => { return html`
`; }); // Ajoute les nouveaux Produits dans le DOM - conteneur.removeAttribute(ATTRIBUT_HIDDEN); - render(methodesHtml, conteneur); + container.removeAttribute(ATTRIBUT_HIDDEN); + render(shippingRatesHTML, container); // Recréé les Écouteurs de clic sur les choix de méthodes - initialiseBoutonsChoixMethodesLivraison(); + initShippingRatesChoicesActions(); }; diff --git a/web/app/themes/haiku-atelier-2024/src/scripts/page-panier/scripts-page-panier-panneau-produits.ts b/web/app/themes/haiku-atelier-2024/src/scripts/page-panier/scripts-page-panier-panneau-produits.ts index 54a238a6..fca9481d 100755 --- a/web/app/themes/haiku-atelier-2024/src/scripts/page-panier/scripts-page-panier-panneau-produits.ts +++ b/web/app/themes/haiku-atelier-2024/src/scripts/page-panier/scripts-page-panier-panneau-produits.ts @@ -9,9 +9,8 @@ import { type AnySchema, ValiError } from "valibot"; import type { WCStoreCart } from "../lib/types/api/cart"; import type { WCStoreCartRemoveItemArgs } from "../lib/types/api/cart-remove-item"; import type { WCStoreCartUpdateItemArgs } from "../lib/types/api/cart-update-item"; -import type { ElementParent } from "../lib/types/dom"; -import type { EtatsPageGenerique } from "../lib/types/pages"; -import type { FetchErrors } from "../lib/types/reseau"; +import type { GenericPageState } from "../lib/types/pages"; +import type { FetchErrors, HttpCodeErrors } from "../lib/types/reseau"; import { ROUTE_API_MAJ_ARTICLE_PANIER, ROUTE_API_RETIRE_ARTICLE_PANIER } from "../constantes/api"; import { @@ -21,10 +20,9 @@ import { SELECTEUR_BOUTON_SOUSTRACTION_QUANTITE, SELECTEUR_BOUTON_SUPPRESSION_PANIER, SELECTEUR_CHAMP_QUANTITE_LIGNE_PANIER, - SELECTEUR_ENTREES_PANIER, } from "../constantes/dom"; import { NOM_CANAL_REVALIDATION_LIVRAISON } from "../constantes/messages"; -import { recupereElementAvecSelecteur, recupereElementOuLeve } from "../lib/dom"; +import { mustGetEleInParent } from "../lib/dom"; import { BadRequestError, reporteErreur, ServerError } from "../lib/erreurs"; import { emetMessageMajBoutonPanier, @@ -32,164 +30,146 @@ import { emetUniqueMessageBroadcastChannel, } from "../lib/messages"; import { diviseParCent } from "../lib/nombres"; -import { creeReponseSimplifiee, eitherAsyncFetch, postBackend } from "../lib/reseau"; +import { newPartialResponse, postBackend, safeFetch, traiteErreursBackendWooCommerce } from "../lib/reseau"; import { WCStoreCartSchema } from "../lib/schemas/api/cart"; import { WCStoreCartRemoveItemArgsSchema } from "../lib/schemas/api/cart-remove-item"; import { WCStoreCartUpdateItemArgsSchema } from "../lib/schemas/api/cart-update-item"; -import { recupereElementsDocumentEither } from "../lib/utils"; -import { eitherValiParse } from "../lib/validation"; +import { safeSchemaParse } from "../lib/validation"; +import { E } from "./scripts-page-panier-elements"; // @ts-expect-error -- États injectés par le modèle PHP // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment -- États injectés par le modèle PHP -const ETATS_PAGE: EtatsPageGenerique = _etats; +const PAGE_STATE: GenericPageState = _etats; -type ElementsEntreePanier = { - boutonAddition: HTMLButtonElement; - boutonSoustraction: HTMLButtonElement; - boutonSuppression: HTMLButtonElement; - champQuantite: HTMLInputElement; +type CartEntryInteractiveElements = { + additionButton: HTMLButtonElement; + deletionButton: HTMLButtonElement; + quantityInput: HTMLInputElement; + substractionButton: HTMLButtonElement; }; -const E = { - ENTREES_PANIER: recupereElementsDocumentEither(SELECTEUR_ENTREES_PANIER), -}; - -// TODO: Tout ça est bien compliqué -const recupereEleDansEntreeOuLeve = (entree: ElementParent) => (selecteur: string) => - pipe(recupereElementAvecSelecteur(entree)(selecteur), recupereElementOuLeve); - -const recupereElementsEntreePanier = (entree: HTMLElement): ElementsEntreePanier => { - const recupereElementDansEntree = recupereEleDansEntreeOuLeve(entree); +const getCartEntryInteractiveEles = (entree: HTMLElement): CartEntryInteractiveElements => { + const mustGetEle = mustGetEleInParent(entree); return { - boutonAddition: recupereElementDansEntree(SELECTEUR_BOUTON_ADDITION_QUANTITE), - boutonSoustraction: recupereElementDansEntree(SELECTEUR_BOUTON_SOUSTRACTION_QUANTITE), - boutonSuppression: recupereElementDansEntree(SELECTEUR_BOUTON_SUPPRESSION_PANIER), - champQuantite: recupereElementDansEntree(SELECTEUR_CHAMP_QUANTITE_LIGNE_PANIER), + additionButton: mustGetEle(SELECTEUR_BOUTON_ADDITION_QUANTITE), + deletionButton: mustGetEle(SELECTEUR_BOUTON_SUPPRESSION_PANIER), + quantityInput: mustGetEle(SELECTEUR_CHAMP_QUANTITE_LIGNE_PANIER), + substractionButton: mustGetEle(SELECTEUR_BOUTON_SOUSTRACTION_QUANTITE), }; }; /** * Met à jour l'état d'activation des Boutons d'action sur chaque Entrée du Panier. -* @param activation Le nouvel état d'activation (activé/désactivé). +* @param activated Le nouvel état d'activation (activé/désactivé). * @returns Rien. */ -export const majActivationBoutons = (activation: boolean) => (entrees: ReadonlyArray): void => - arrayForEach(entrees, (entree: ElementsEntreePanier): void => { - if (activation) { - // Active les Boutons - Number(entree.champQuantite.value) === 1 - ? entree.boutonSoustraction.setAttribute(ATTRIBUT_DESACTIVE, "") - : entree.boutonSoustraction.removeAttribute(ATTRIBUT_DESACTIVE); - entree.boutonAddition.removeAttribute(ATTRIBUT_DESACTIVE); - entree.boutonSuppression.removeAttribute(ATTRIBUT_DESACTIVE); - entree.boutonSuppression.textContent = "Remove"; - } else { - // Désactive les Boutons - entree.boutonSoustraction.setAttribute(ATTRIBUT_DESACTIVE, ""); - entree.boutonAddition.setAttribute(ATTRIBUT_DESACTIVE, ""); - entree.boutonSuppression.setAttribute(ATTRIBUT_DESACTIVE, ""); - entree.boutonSuppression.textContent = "Loading"; - } - }); +export const toggleCartEntryButtons = + (activated: boolean) => (cartEntries: ReadonlyArray): void => + arrayForEach(cartEntries, (e: CartEntryInteractiveElements): void => { + if (activated) { + // Active les Boutons + Number(e.quantityInput.value) === 1 + ? e.substractionButton.setAttribute(ATTRIBUT_DESACTIVE, "") + : e.substractionButton.removeAttribute(ATTRIBUT_DESACTIVE); + e.additionButton.removeAttribute(ATTRIBUT_DESACTIVE); + e.deletionButton.removeAttribute(ATTRIBUT_DESACTIVE); + e.deletionButton.textContent = "Remove"; + } else { + // Désactive les Boutons + e.substractionButton.setAttribute(ATTRIBUT_DESACTIVE, ""); + e.additionButton.setAttribute(ATTRIBUT_DESACTIVE, ""); + e.deletionButton.setAttribute(ATTRIBUT_DESACTIVE, ""); + e.deletionButton.textContent = "Loading"; + } + }); export const initialiseActionsEntreesPanier = (): void => { // Initialise des actions uniquement si des Entrées dans le Panier existent - E.ENTREES_PANIER.ifRight((entrees: Array) => - arrayForEach(entrees, (entree: HTMLElement): void => { - /** Retire l'entrée du DOM si la clé Panier n'existe pas et arrête précocement */ - const clePanier: string = Maybe - .fromNullable(entree.getAttribute(ATTRIBUT_CLE_PANIER)) - .ifNothing(() => { - entree.remove(); - }) + E.ENTREES_PANIER.ifRight((cartEntries: Array) => + arrayForEach(cartEntries, (entry: HTMLElement): void => { + // Retire l'entrée du DOM si la clé Panier n'existe pas puis arrête précocement + const entryKey: string = Maybe + .fromNullable(entry.getAttribute(ATTRIBUT_CLE_PANIER)) + .ifNothing(() => entry.remove()) .orDefault("CLE_PANIER_INEXISTANTE"); - /** */ - const E_P: ElementsEntreePanier = recupereElementsEntreePanier(entree); + const entryButtons: CartEntryInteractiveElements = getCartEntryInteractiveEles(entry); - entree.addEventListener("click", (evenement: Event): void => { - // Délégation d'Événements - match(evenement.target) - .with(P.nullish, () => console.error(evenement.target)) - // Bouton d'addition + entry.addEventListener("click", (event: Event): void => { + // Discrimine en fonction de l'Élément cliqué (délégation d'Événements) + match(event.target) + // Cas impossible + .with(P.nullish, () => console.error(event.target)) + // Clic sur le Bouton d'addition .when( - (cible: EventTarget) => (cible as HTMLElement).matches(SELECTEUR_BOUTON_ADDITION_QUANTITE), + (target: EventTarget) => (target as HTMLElement).matches(SELECTEUR_BOUTON_ADDITION_QUANTITE), (): void => { - Maybe - // Nécessaire pour que l'on ait une valeur à incrémenter - .fromNullable(E_P.champQuantite.valueAsNumber) - .ifJust((valeur: number) => { - // Réalise la requête et traite sa réponse - void EitherAsync - // 1. Valide les Arguments de la Requête - .liftEither( - eitherValiParse({ key: clePanier, quantity: valeur + 1 }, WCStoreCartUpdateItemArgsSchema), - ) - // 2. Exécute un Effet pour empêcher les requêtes concurrentes - .ifRight(() => pipe(entrees, arrayMap(recupereElementsEntreePanier), majActivationBoutons(false))) - // 3. Exécute la requête via fetch sous forme d'EitherAsync - .chain((args: WCStoreCartUpdateItemArgs) => - eitherAsyncFetch(postBackend({ - corps: JSON.stringify(args), - nonce: ETATS_PAGE.nonce, - route: ROUTE_API_MAJ_ARTICLE_PANIER, - })) - ) - // 4. Traite les cas d'Erreurs et récupère le Corps de la Réponse - .chain((reponse: Response) => - EitherAsync(async ({ throwE }) => - // Simplifie les données à matcher - match(await creeReponseSimplifiee(reponse)) - .with({ status: 500 }, () => throwE(new ServerError("500 Server Error"))) - .with({ status: 400 }, () => throwE(new BadRequestError("400 Bad Request Error"))) - .with({ status: 200 }, r => r.body) - .otherwise(erreur => throwE(new Error(`Erreur inconnue ${String(erreur.status)}`))) - ) - ) - // 5. Vérifie le Schéma de la Réponse - .chain((corps: unknown) => EitherAsync.liftEither(eitherValiParse(corps, WCStoreCartSchema))) - // 6. Exécute un Effet pour la mise à jour du DOM avec les Résultats - .ifRight((panier: WCStoreCart): void => { - // Émet un Message avec le nouveau nombre de Produits dans le Panier - emetMessageMajBoutonPanier({ quantiteProduits: panier.items_count }); - // Émet un Message avec le nouveau contenu du Panier - emetMessageMajContenuPanier({ - produits: panier.items, - sousTotalProduits: diviseParCent(panier.totals.total_items), - sousTotalReduction: diviseParCent(panier.totals.total_discount), - totalPanier: diviseParCent(panier.totals.total_price), - }); - // Émet un Message pour réinitialiser la validation de la livraison - emetUniqueMessageBroadcastChannel(NOM_CANAL_REVALIDATION_LIVRAISON, true); - }) - // 7. Traite les Erreurs et affiche un message à l'Utilisateur - .ifLeft( - (erreur: BadRequestError | FetchErrors | ServerError | ValiError): void => { - match(erreur) - .with(P.instanceOf(ValiError), e => { - reporteErreur(e); - console.error(e.issues); - // E.MESSAGE_ADRESSES.textContent = ERREUR_GENERIQUE_SOUMISSION_ADRESSES; - }) - .with(P.instanceOf(ServerError), P.instanceOf(BadRequestError), e => { - reporteErreur(e); - console.error(e); - // E.MESSAGE_ADRESSES.textContent = ERREUR_GENERIQUE_SOUMISSION_ADRESSES; - }) - .with(P.instanceOf(DOMException), P.instanceOf(TypeError), P.instanceOf(Error), e => { - reporteErreur(e); - console.error(e); - // E.MESSAGE_ADRESSES.textContent = ERREUR_GENERIQUE_RESEAU; - }) - .exhaustive(); - }, - ) - .finally(() => { - // Réactive les Boutons - pipe(entrees, arrayMap(recupereElementsEntreePanier), majActivationBoutons(true)); - }) - .run(); - }); + void EitherAsync + .liftEither( + Maybe + // Une valeur à incrémenter doit exister + .fromNullable(entryButtons.quantityInput.valueAsNumber) + .toEither(new Error("Quantité manquante pour cette ligne du Panier !")), + ) + .chain(q => + EitherAsync.liftEither( + safeSchemaParse({ key: entryKey, quantity: q + 1 }, WCStoreCartUpdateItemArgsSchema), + ) + ) + .ifRight(() => pipe(cartEntries, arrayMap(getCartEntryInteractiveEles), toggleCartEntryButtons(false))) + .chain((args: WCStoreCartUpdateItemArgs) => + safeFetch(postBackend({ + corps: JSON.stringify(args), + nonce: PAGE_STATE.nonce, + route: ROUTE_API_MAJ_ARTICLE_PANIER, + })) + ) + .chain((r: Response) => + EitherAsync(async ({ throwE }) => + match(await newPartialResponse(r)) + .with({ status: 200 }, r => r.body) + .otherwise((rs): never => throwE(traiteErreursBackendWooCommerce(rs))) + ) + ) + .chain((b: unknown) => EitherAsync.liftEither(safeSchemaParse(b, WCStoreCartSchema))) + .ifRight((c: WCStoreCart): void => { + // Émet un Message avec le nouveau nombre de Produits dans le Panier + emetMessageMajBoutonPanier({ quantiteProduits: c.items_count }); + // Émet un Message avec le nouveau contenu du Panier + emetMessageMajContenuPanier({ + produits: c.items, + sousTotalProduits: diviseParCent(c.totals.total_items), + sousTotalReduction: diviseParCent(c.totals.total_discount), + totalPanier: diviseParCent(c.totals.total_price), + }); + // Émet un Message pour réinitialiser la validation de la livraison + emetUniqueMessageBroadcastChannel(NOM_CANAL_REVALIDATION_LIVRAISON, true); + }) + .ifLeft( + (err: FetchErrors | HttpCodeErrors | ValiError): void => { + match(err) + .with(P.instanceOf(ValiError), e => { + reporteErreur(e); + console.error(e.issues); + // E.MESSAGE_ADRESSES.textContent = ERREUR_GENERIQUE_SOUMISSION_ADRESSES; + }) + .with(P.instanceOf(ServerError), P.instanceOf(BadRequestError), e => { + reporteErreur(e); + console.error(e); + // E.MESSAGE_ADRESSES.textContent = ERREUR_GENERIQUE_SOUMISSION_ADRESSES; + }) + .with(P.instanceOf(DOMException), P.instanceOf(TypeError), P.instanceOf(Error), e => { + reporteErreur(e); + console.error(e); + // E.MESSAGE_ADRESSES.textContent = ERREUR_GENERIQUE_RESEAU; + }) + .exhaustive(); + }, + ) + .finally(() => { + pipe(cartEntries, arrayMap(getCartEntryInteractiveEles), toggleCartEntryButtons(true)); + }) + .run(); }, ) // Bouton de soustraction @@ -198,22 +178,24 @@ export const initialiseActionsEntreesPanier = (): void => { (): void => { Maybe // Nécessaire pour que l'on ait une valeur à incrémenter - .fromNullable(E_P.champQuantite.valueAsNumber) + .fromNullable(entryButtons.quantityInput.valueAsNumber) .filter(valeur => valeur > 1) .ifJust((valeur: number) => { // Réalise la requête et traite sa réponse void EitherAsync // 1. Valide les Arguments de la Requête .liftEither( - eitherValiParse({ key: clePanier, quantity: valeur - 1 }, WCStoreCartUpdateItemArgsSchema), + safeSchemaParse({ key: entryKey, quantity: valeur - 1 }, WCStoreCartUpdateItemArgsSchema), ) // 2. Exécute un Effet pour empêcher les requêtes concurrentes - .ifRight(() => pipe(entrees, arrayMap(recupereElementsEntreePanier), majActivationBoutons(false))) + .ifRight(() => + pipe(cartEntries, arrayMap(getCartEntryInteractiveEles), toggleCartEntryButtons(false)) + ) // 3. Exécute la requête via fetch sous forme d'EitherAsync .chain((args: WCStoreCartUpdateItemArgs) => - eitherAsyncFetch(postBackend({ + safeFetch(postBackend({ corps: JSON.stringify(args), - nonce: ETATS_PAGE.nonce, + nonce: PAGE_STATE.nonce, route: ROUTE_API_MAJ_ARTICLE_PANIER, })) ) @@ -221,7 +203,7 @@ export const initialiseActionsEntreesPanier = (): void => { .chain((reponse: Response) => EitherAsync(async ({ throwE }) => // Simplifie les données à matcher - match(await creeReponseSimplifiee(reponse)) + match(await newPartialResponse(reponse)) .with({ status: 500 }, () => throwE(new ServerError("500 Server Error"))) .with({ status: 400 }, () => throwE(new BadRequestError("400 Bad Request Error"))) .with({ status: 200 }, r => r.body) @@ -229,7 +211,7 @@ export const initialiseActionsEntreesPanier = (): void => { ) ) // 5. Vérifie le Schéma de la Réponse - .chain((corps: unknown) => EitherAsync.liftEither(eitherValiParse(corps, WCStoreCartSchema))) + .chain((corps: unknown) => EitherAsync.liftEither(safeSchemaParse(corps, WCStoreCartSchema))) // 6. Exécute un Effet pour la mise à jour du DOM avec les Résultats .ifRight((panier: WCStoreCart): void => { // Émet un Message avec le nouveau nombre de Produits dans le Panier @@ -268,7 +250,7 @@ export const initialiseActionsEntreesPanier = (): void => { ) .finally(() => { // Réactive les Boutons - pipe(entrees, arrayMap(recupereElementsEntreePanier), majActivationBoutons(true)); + pipe(cartEntries, arrayMap(getCartEntryInteractiveEles), toggleCartEntryButtons(true)); }) .run(); }); @@ -280,19 +262,21 @@ export const initialiseActionsEntreesPanier = (): void => { (): void => { Maybe // TODO: Pourquoi ? - .fromNullable(E_P.champQuantite.valueAsNumber) + .fromNullable(entryButtons.quantityInput.valueAsNumber) .ifJust(() => { // Réalise la requête et traite sa réponse void EitherAsync // 1. Valide les Arguments de la Requête - .liftEither(eitherValiParse({ key: clePanier }, WCStoreCartRemoveItemArgsSchema)) + .liftEither(safeSchemaParse({ key: entryKey }, WCStoreCartRemoveItemArgsSchema)) // 2. Exécute un Effet pour empêcher les requêtes concurrentes - .ifRight(() => pipe(entrees, arrayMap(recupereElementsEntreePanier), majActivationBoutons(false))) + .ifRight(() => + pipe(cartEntries, arrayMap(getCartEntryInteractiveEles), toggleCartEntryButtons(false)) + ) // 3. Exécute la requête via fetch sous forme d'EitherAsync .chain((args: WCStoreCartRemoveItemArgs) => - eitherAsyncFetch(postBackend({ + safeFetch(postBackend({ corps: JSON.stringify(args), - nonce: ETATS_PAGE.nonce, + nonce: PAGE_STATE.nonce, route: ROUTE_API_RETIRE_ARTICLE_PANIER, })) ) @@ -300,7 +284,7 @@ export const initialiseActionsEntreesPanier = (): void => { .chain((reponse: Response) => EitherAsync(async ({ throwE }) => // Simplifie les données à matcher - match(await creeReponseSimplifiee(reponse)) + match(await newPartialResponse(reponse)) .with({ status: 500 }, () => throwE(new ServerError("500 Server Error"))) .with({ status: 400 }, () => throwE(new BadRequestError("400 Bad Request Error"))) .with({ status: 200 }, r => r.body) @@ -308,7 +292,7 @@ export const initialiseActionsEntreesPanier = (): void => { ) ) // 5. Vérifie le Schéma de la Réponse - .chain((corps: unknown) => EitherAsync.liftEither(eitherValiParse(corps, WCStoreCartSchema))) + .chain((corps: unknown) => EitherAsync.liftEither(safeSchemaParse(corps, WCStoreCartSchema))) // 6. Exécute un Effet pour la mise à jour du DOM avec les Résultats .ifRight((panier: WCStoreCart): void => { // Émet un Message avec le nouveau nombre de Produits dans le Panier @@ -324,7 +308,7 @@ export const initialiseActionsEntreesPanier = (): void => { emetUniqueMessageBroadcastChannel(NOM_CANAL_REVALIDATION_LIVRAISON, true); // Retire l'entrée du Panier du DOM - entree.remove(); + entry.remove(); }) // 7. Traite les Erreurs et affiche un message à l'Utilisateur .ifLeft( @@ -350,13 +334,13 @@ export const initialiseActionsEntreesPanier = (): void => { ) .finally(() => { // Réactive les Boutons - pipe(entrees, arrayMap(recupereElementsEntreePanier), majActivationBoutons(true)); + pipe(cartEntries, arrayMap(getCartEntryInteractiveEles), toggleCartEntryButtons(true)); }) .run(); }); }, ) - .run(); + .otherwise(_ => {}); }); }) ); diff --git a/web/app/themes/haiku-atelier-2024/src/scripts/scripts-bouton-panier.ts b/web/app/themes/haiku-atelier-2024/src/scripts/scripts-bouton-panier.ts index b7a62ba5..edc57dd6 100755 --- a/web/app/themes/haiku-atelier-2024/src/scripts/scripts-bouton-panier.ts +++ b/web/app/themes/haiku-atelier-2024/src/scripts/scripts-bouton-panier.ts @@ -2,22 +2,21 @@ * Scripts pour la mise à jour trans-fenêtres/trans-onglets du Bouton du Panier. */ -import { pipe } from "@mobily/ts-belt"; - import type { MessageMajBoutonPanier } from "./lib/types/messages"; import { ATTRIBUT_CONTIENT_ARTICLES, SELECTEUR_BOUTON_PANIER } from "./constantes/dom.ts"; import { NOM_CANAL_BOUTON_PANIER } from "./constantes/messages.ts"; -import { recupereElementOuLeve } from "./lib/dom.ts"; +import { mustGetEleInDocument } from "./lib/dom.ts"; import { valideMessageMajBoutonPanier } from "./lib/messages.ts"; -import { recupereElementDocumentEither } from "./lib/utils.ts"; +/** + * Initialise les interactions et la mise à jour du bouton « Panier » contenant le nombre d'articles dans le Panier. + * + * @returns void + */ const initialiseBoutonPanier = (): void => { - /** Le « Bouton » vers le Panier dont le texte est un indicateur du nombre de Produits dedans. */ - const BOUTON_PANIER: HTMLAnchorElement = pipe( - recupereElementDocumentEither(SELECTEUR_BOUTON_PANIER), - recupereElementOuLeve, - ); + /** Le « Bouton » vers le Panier avec un indicateur de la quantité de Produits ajoutés. */ + const BOUTON_PANIER: HTMLAnchorElement = mustGetEleInDocument(SELECTEUR_BOUTON_PANIER); const CANAL_BOUTON_PANIER: BroadcastChannel = new BroadcastChannel(NOM_CANAL_BOUTON_PANIER); CANAL_BOUTON_PANIER.onmessage = (evenementMessage: MessageEvent): void => { @@ -35,6 +34,6 @@ const initialiseBoutonPanier = (): void => { }); }; -document.addEventListener("DOMContentLoaded", () => { +document.addEventListener("DOMContentLoaded", (): void => { initialiseBoutonPanier(); }); diff --git a/web/app/themes/haiku-atelier-2024/src/scripts/scripts-bouton-retour-sommet.ts b/web/app/themes/haiku-atelier-2024/src/scripts/scripts-bouton-retour-sommet.ts index 4c769c85..c04bae8c 100755 --- a/web/app/themes/haiku-atelier-2024/src/scripts/scripts-bouton-retour-sommet.ts +++ b/web/app/themes/haiku-atelier-2024/src/scripts/scripts-bouton-retour-sommet.ts @@ -10,22 +10,13 @@ import { ATTRIBUT_TABINDEX, SELECTEUR_BOUTON_MENU_MOBILE, } from "./constantes/dom"; -import { recupereEleOuLeve } from "./lib/utils"; - -/** - * 1. Récupérer la hauteur de l'écran et la hauteur de la page. - * 2. Si la page fait moins de 3 fois la hauteur de l'écran, arrêter. - * 3. Recommencer l'opération si la page est redimensionnée (ResizeObserver). - * 4. Quand l'Utilisateur dépasse le seuil de 3 fois la hauteur de l'écran, faire apparaître le bouton. - * 5. Le faire disparaître quand il retourne en-deça. - * 6. Au clic dessus, aller sur l'ancre au sommet de la page et faire disparaître le bouton. - */ +import { mustGetEleInDocument } from "./lib/dom"; const E = { - BOUTON_MENU_MOBILE: recupereEleOuLeve(SELECTEUR_BOUTON_MENU_MOBILE), - BOUTON_RETOUR_SOMMET: recupereEleOuLeve("#bouton-retour-haut"), - CORPS_HTML: recupereEleOuLeve("body"), - IMAGE_BOUTON: recupereEleOuLeve("#bouton-retour-haut img"), + BOUTON_MENU_MOBILE: mustGetEleInDocument(SELECTEUR_BOUTON_MENU_MOBILE), + BOUTON_RETOUR_SOMMET: mustGetEleInDocument("#bouton-retour-haut"), + CORPS_HTML: mustGetEleInDocument("body"), + IMAGE_BOUTON: mustGetEleInDocument("#bouton-retour-haut img"), }; /** Le ratio minimum hauteur de page/hauteur de la fenêtre à atteindre pour que le Bouton soit nécessaire. */ @@ -47,6 +38,7 @@ const majDefilementY = (): number => window.scrollY; /** * @param estVisible + * @returns void */ const majVisibiliteBouton = (estVisible: boolean): void => { if (estVisible) { diff --git a/web/app/themes/haiku-atelier-2024/src/scripts/scripts-menu-categories.ts b/web/app/themes/haiku-atelier-2024/src/scripts/scripts-menu-categories.ts index bc1a6dda..01f6e2ff 100755 --- a/web/app/themes/haiku-atelier-2024/src/scripts/scripts-menu-categories.ts +++ b/web/app/themes/haiku-atelier-2024/src/scripts/scripts-menu-categories.ts @@ -4,17 +4,17 @@ import { A } from "@mobily/ts-belt"; import { match } from "ts-pattern"; import { SELECTEUR_ENTREE_MENU_CATEGORIES_PRODUITS, SELECTEUR_MENU_CATEGORIES_PRODUITS } from "./constantes/dom.ts"; -import { recupereEleOuLeve, recupereElesOuLeve } from "./lib/utils.ts"; +import { mustGetEleInDocument, mustGetElesInDocument } from "./lib/dom.ts"; document.addEventListener("DOMContentLoaded", (): void => { - const MENU_CATEGORIES_PRODUITS: HTMLElement = recupereEleOuLeve(SELECTEUR_MENU_CATEGORIES_PRODUITS); - const ENTREES_MENU_CATEGORIES_PRODUITS: Array = recupereElesOuLeve( + const MENU_CATEGORIES_PRODUITS: HTMLElement = mustGetEleInDocument(SELECTEUR_MENU_CATEGORIES_PRODUITS); + const ENTREES_MENU_CATEGORIES_PRODUITS: Array = mustGetElesInDocument( SELECTEUR_ENTREE_MENU_CATEGORIES_PRODUITS, ); A.forEachWithIndex( [ENTREES_MENU_CATEGORIES_PRODUITS.at(0), ENTREES_MENU_CATEGORIES_PRODUITS.at(-1)], - (index, entreeMenu) => { + (index, entreeMenu): void => { if (!entreeMenu) return; new IntersectionObserver( diff --git a/web/app/themes/haiku-atelier-2024/src/scripts/scripts-menu-mobile.ts b/web/app/themes/haiku-atelier-2024/src/scripts/scripts-menu-mobile.ts index 0401f463..17c4bf1f 100755 --- a/web/app/themes/haiku-atelier-2024/src/scripts/scripts-menu-mobile.ts +++ b/web/app/themes/haiku-atelier-2024/src/scripts/scripts-menu-mobile.ts @@ -6,13 +6,13 @@ import { A, O, pipe } from "@mobily/ts-belt"; import A11yDialog from "a11y-dialog"; import { ATTRIBUT_MENU_MOBILE_ACTIVE, SELECTEUR_BOUTON_MENU_MOBILE, SELECTEUR_MENU_MOBILE } from "./constantes/dom.ts"; -import { recupereEleOuLeve } from "./lib/utils.ts"; +import { mustGetEleInDocument } from "./lib/dom.ts"; // Éléments d'intérêt const E = { - BOUTON_MENU_MOBILE: recupereEleOuLeve(SELECTEUR_BOUTON_MENU_MOBILE), - CORPS_HTML: recupereEleOuLeve("body"), - MENU_MOBILE: recupereEleOuLeve(SELECTEUR_MENU_MOBILE), + BOUTON_MENU_MOBILE: mustGetEleInDocument(SELECTEUR_BOUTON_MENU_MOBILE), + CORPS_HTML: mustGetEleInDocument("body"), + MENU_MOBILE: mustGetEleInDocument(SELECTEUR_MENU_MOBILE), }; const initialiseBoutonMenuMobile = (): void => { diff --git a/web/app/themes/haiku-atelier-2024/src/scripts/scripts-page-a-propos.ts b/web/app/themes/haiku-atelier-2024/src/scripts/scripts-page-a-propos.ts index 2320111b..cc1554e3 100755 --- a/web/app/themes/haiku-atelier-2024/src/scripts/scripts-page-a-propos.ts +++ b/web/app/themes/haiku-atelier-2024/src/scripts/scripts-page-a-propos.ts @@ -13,16 +13,16 @@ import { SELECTEUR_CONTENEUR_STORYTELLING_A_PROPOS, SELECTEUR_EPINGLE, } from "./constantes/dom.ts"; -import { recupereEleOuLeve, recupereElesOuLeve } from "./lib/utils.ts"; +import { mustGetEleInDocument, mustGetElesInDocument } from "./lib/dom.ts"; /** Le Conteneur des images du storytelling. */ -const CONTENEUR_STORYTELLING = recupereEleOuLeve( +const CONTENEUR_STORYTELLING = mustGetEleInDocument( SELECTEUR_CONTENEUR_STORYTELLING_A_PROPOS, ); /** */ -const EPINGLES = recupereElesOuLeve(SELECTEUR_EPINGLE); +const EPINGLES = mustGetElesInDocument(SELECTEUR_EPINGLE); /** */ -const BOITES_TEXTE = recupereElesOuLeve(SELECTEUR_BOITE_TEXTE); +const BOITES_TEXTE = mustGetElesInDocument(SELECTEUR_BOITE_TEXTE); /** */ const ENSEMBLES_EPINGLES_BOITES_TEXTE = new Map(); A.forEachWithIndex(EPINGLES, (index, epingle) => { diff --git a/web/app/themes/haiku-atelier-2024/src/scripts/scripts-page-accueil.ts b/web/app/themes/haiku-atelier-2024/src/scripts/scripts-page-accueil.ts index 27abdff3..cf89d4a8 100755 --- a/web/app/themes/haiku-atelier-2024/src/scripts/scripts-page-accueil.ts +++ b/web/app/themes/haiku-atelier-2024/src/scripts/scripts-page-accueil.ts @@ -8,17 +8,17 @@ import { SELECTEUR_CONTENEUR_STORYTELLING, SELECTEUR_IMAGES_STORYTELLING, } from "./constantes/dom.ts"; +import { mustGetEleInDocument, mustGetElesInDocument } from "./lib/dom.ts"; import { estEntreDeuxNombres } from "./lib/nombres.ts"; -import { recupereEleOuLeve, recupereElesOuLeve } from "./lib/utils.ts"; const initialiseScrollStorytelling = (): void => { const E = { /** Le conteneur des images du storytelling. */ - CONTENEUR_STORYTELLING: recupereEleOuLeve(".storytelling__conteneur"), + CONTENEUR_STORYTELLING: mustGetEleInDocument(".storytelling__conteneur"), /** Les images du storytelling. */ - IMAGES_STORYTELLING: recupereElesOuLeve(SELECTEUR_IMAGES_STORYTELLING), + IMAGES_STORYTELLING: mustGetElesInDocument(SELECTEUR_IMAGES_STORYTELLING), /** Le bloc contenant le storytelling. */ - STORYTELLING: recupereEleOuLeve(SELECTEUR_CONTENEUR_STORYTELLING), + STORYTELLING: mustGetEleInDocument(SELECTEUR_CONTENEUR_STORYTELLING), }; /** La hauteur d'une image du storytelling. */ diff --git a/web/app/themes/haiku-atelier-2024/src/scripts/scripts-page-boutique.ts b/web/app/themes/haiku-atelier-2024/src/scripts/scripts-page-boutique.ts index a32b9c8e..68ef0e41 100755 --- a/web/app/themes/haiku-atelier-2024/src/scripts/scripts-page-boutique.ts +++ b/web/app/themes/haiku-atelier-2024/src/scripts/scripts-page-boutique.ts @@ -10,7 +10,7 @@ import { ValiError } from "valibot"; import type { APIFetchErrors } from "./lib/types/api/erreurs"; import type { WCV3Products, WCV3ProductsArgs } from "./lib/types/api/v3/products.ts"; -import type { EtatsPageGenerique } from "./lib/types/pages"; +import type { GenericPageState } from "./lib/types/pages"; import { ROUTE_API_NOUVELLE_PRODUCTS } from "./constantes/api.ts"; import { @@ -23,48 +23,53 @@ import { SELECTEUR_GRILLE_PRODUITS, } from "./constantes/dom.ts"; import { lanceAnimationCycleLoading } from "./lib/animations.ts"; -import { html } from "./lib/dom.ts"; +import { html, mustGetEleInDocument } from "./lib/dom.ts"; import { BadRequestError, reporteErreur, ServerError } from "./lib/erreurs.ts"; -import { creeReponseSimplifiee, getBackendAvecParametresUrl } from "./lib/reseau.ts"; +import { newPartialResponse, getBackendAvecParametresUrl } from "./lib/reseau.ts"; import { WCV3ProductsArgsSchema, WCV3ProductsSchema } from "./lib/schemas/api/v3/products.ts"; -import { recupereEleOuLeve } from "./lib/utils.ts"; -import { eitherValiParse } from "./lib/validation.ts"; +import { safeSchemaParse } from "./lib/validation.ts"; + +type APIProductsErrors = + | APIFetchErrors + | ValiError + | ValiError; // @ts-expect-error -- États injectés par le modèle PHP // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment -- États injectés par le modèle PHP -const ETATS_PAGE: EtatsPageGenerique = _etats; +const ETATS_PAGE: GenericPageState = _etats; + +// Numéros magiques +const PRODUCTS_PER_PAGE = 12; // Éléments d'intérêt const E = { - BOUTON_PLUS_DE_PRODUITS: recupereEleOuLeve(SELECTEUR_BOUTON_PLUS_PRODUITS), - GRILLE_PRODUITS: recupereEleOuLeve(SELECTEUR_GRILLE_PRODUITS), + BOUTON_PLUS_DE_PRODUITS: mustGetEleInDocument(SELECTEUR_BOUTON_PLUS_PRODUITS), + GRILLE_PRODUITS: mustGetEleInDocument(SELECTEUR_GRILLE_PRODUITS), }; /** * TODO */ const initialisePageBoutique = (): void => { + /** ID de la Catégorie de Produits si la Page courante est l'Archive d'une Catégorie. */ const idCategorieProduits: null | string = E.GRILLE_PRODUITS.getAttribute(ATTRIBUT_ID_CATEGORIE_PRODUITS); E.BOUTON_PLUS_DE_PRODUITS.addEventListener("click", (): void => { + /** Le numéro de page demandée par l'Utilisateur. */ const nouveauNumeroPage = Number(E.GRILLE_PRODUITS.getAttribute(ATTRIBUT_PAGE)) + 1; + /** Les arguments passés à la requête auprès Backend pour la nouvelle page de Produits. */ const args: WCV3ProductsArgs = { page: nouveauNumeroPage, - per_page: 12, + per_page: PRODUCTS_PER_PAGE, // Ajoute conditionnellement la Catégorie de Produits ...(idCategorieProduits && { category: idCategorieProduits }), }; - type APIProductsErrors = - | APIFetchErrors - | ValiError - | ValiError; - void EitherAsync // 1. Valide les Arguments de la Requête - .liftEither(eitherValiParse(args, WCV3ProductsArgsSchema)) + .liftEither(safeSchemaParse(args, WCV3ProductsArgsSchema)) // 2. Exécute un Effet pour empêcher les requêtes concurrentes et lancer une animation de chargement - .ifRight(() => { + .ifRight((): void => { // Désactive le Bouton pour empêcher des requêtes concurrentes E.BOUTON_PLUS_DE_PRODUITS.setAttribute(ATTRIBUT_DESACTIVE, ""); E.BOUTON_PLUS_DE_PRODUITS.setAttribute(ATTRIBUT_CHARGEMENT, ""); @@ -86,7 +91,7 @@ const initialisePageBoutique = (): void => { // 4. Traite les cas d'Erreurs et récupère le Corps de la Réponse .chain((reponse: Response) => EitherAsync(async ({ throwE }) => { - return match(await creeReponseSimplifiee(reponse)) + return match(await newPartialResponse(reponse)) .with({ status: 500 }, () => throwE(new ServerError("500 Server Error"))) .with({ status: 400 }, () => throwE(new BadRequestError("400 Server Error"))) .with({ status: 200 }, r => r.body) @@ -94,11 +99,11 @@ const initialisePageBoutique = (): void => { }) ) // 5. Vérifie le Schéma de la Réponse - .chain((corpsReponse: unknown) => EitherAsync.liftEither(eitherValiParse(corpsReponse, WCV3ProductsSchema))) + .chain((corpsReponse: unknown) => EitherAsync.liftEither(safeSchemaParse(corpsReponse, WCV3ProductsSchema))) // 6. Exécute un Effet pour la mise à jour du DOM avec les Résultats .ifRight((donnees: WCV3Products) => { - // Cache le bouton s'il y a moins de 12 Produits disponibles (que l'on est à la dernière page) - if (donnees.length < 12) { + // Cache le bouton s'il y a moins de PRODUCTS_PER_PAGE Produits disponibles (que l'on est à la dernière page) + if (donnees.length < PRODUCTS_PER_PAGE) { E.BOUTON_PLUS_DE_PRODUITS.toggleAttribute(ATTRIBUT_HIDDEN); } @@ -106,7 +111,7 @@ const initialisePageBoutique = (): void => { const fragment: DocumentFragment = document.createDocumentFragment(); // Créé les Éléments
à insérer - for (const produit of donnees.slice(0, 12)) { + for (const produit of donnees.slice(0, PRODUCTS_PER_PAGE)) { pipe( html`
diff --git a/web/app/themes/haiku-atelier-2024/src/scripts/scripts-page-panier.ts b/web/app/themes/haiku-atelier-2024/src/scripts/scripts-page-panier.ts index e1bc8864..222b11d3 100755 --- a/web/app/themes/haiku-atelier-2024/src/scripts/scripts-page-panier.ts +++ b/web/app/themes/haiku-atelier-2024/src/scripts/scripts-page-panier.ts @@ -2,7 +2,7 @@ import type { ValiError } from "valibot"; import { D, pipe } from "@mobily/ts-belt"; import { forEach as arrayForEach } from "@mobily/ts-belt/Array"; -import { type Either, Maybe } from "purify-ts"; +import { Maybe } from "purify-ts"; import type { MessageMajContenuPanierSchema } from "./lib/schemas/messages.ts"; import type { WCStoreCartItem } from "./lib/types/api/cart"; @@ -14,32 +14,26 @@ import { ATTRIBUT_DESACTIVE, ATTRIBUT_HIDDEN, SELECTEUR_BOUTON_ADDITION_QUANTITE, - SELECTEUR_BOUTON_SEPARATION_ADRESSES, SELECTEUR_BOUTON_SOUSTRACTION_QUANTITE, SELECTEUR_BOUTON_SUPPRESSION_PANIER, SELECTEUR_CHAMP_QUANTITE_LIGNE_PANIER, - SELECTEUR_CONTENEUR_PANIER, - SELECTEUR_ENTREES_PANIER, - SELECTEUR_FORMULAIRE_FACTURATION, SELECTEUR_PRIX_LIGNE_PANIER, - SELECTEUR_SOUS_TOTAL_PRODUITS, - SELECTEUR_TOTAL_PANIER, - SELECTEUR_TOTAL_REDUCTION_VALEUR, } from "./constantes/dom.ts"; import { NOM_CANAL_BOUTON_PANIER, NOM_CANAL_CONTENU_PANIER } from "./constantes/messages.ts"; -import { recupereElementAvecSelecteur, recupereElementOuLeve, recupereElementsAvecSelecteur } from "./lib/dom.ts"; +import { getDOMElementsWithSelector, recupereElementAvecSelecteur, recupereElementOuLeve } from "./lib/dom.ts"; import { type CleNonTrouveError, reporteErreur } from "./lib/erreurs.ts"; import { valideMessageMajBoutonPanier, valideMessageMajContenuPanier } from "./lib/messages.ts"; import { arrondisADeuxDecimales, diviseParCent, formateEnEuros, inverseNombre } from "./lib/nombres.ts"; -import { propEither, recupereElementsDocumentEither, recupereEleOuLeve } from "./lib/utils.ts"; +import { propEither } from "./lib/utils.ts"; import { - initialiseBoutonCalculLivraison, - initialiseBoutonCreationCommande, - initialiseEmetteursEvenementsFormulairePanier, + initCartFormEventEmiters, + initOrderCreationButton, + initShippingCalculationButton, } from "./page-panier/scripts-page-panier-adresses.ts"; import { initialiseElementsCodePromo } from "./page-panier/scripts-page-panier-code-promo.ts"; +import { E } from "./page-panier/scripts-page-panier-elements.ts"; import { souscrisEvenementsPanier } from "./page-panier/scripts-page-panier-evenement.ts"; -import { initialiseBoutonsChoixMethodesLivraison } from "./page-panier/scripts-page-panier-methodes-livraison.ts"; +import { initShippingRatesChoicesActions } from "./page-panier/scripts-page-panier-methodes-livraison.ts"; import { initialiseActionsEntreesPanier } from "./page-panier/scripts-page-panier-panneau-produits.ts"; type ElementsEntreePanier = { @@ -60,19 +54,6 @@ type EtatsPage = { // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment -- États injectés par le modèle PHP const ETATS_PAGE: EtatsPage = _etats; -// Éléments d'intérêt -const ENTREES_PANIER_EITHER: Either> = recupereElementsDocumentEither( - SELECTEUR_ENTREES_PANIER, -); -const CONTENEUR_PANIER: HTMLElement = recupereEleOuLeve(SELECTEUR_CONTENEUR_PANIER); -const SOUS_TOTAL_PRODUITS: HTMLElement = recupereEleOuLeve(SELECTEUR_SOUS_TOTAL_PRODUITS); -const SOUS_TOTAL_REDUCTION: HTMLSpanElement = recupereEleOuLeve(SELECTEUR_TOTAL_REDUCTION_VALEUR); -const TOTAL_PANIER: HTMLParagraphElement = recupereEleOuLeve(SELECTEUR_TOTAL_PANIER); -const BOUTON_SEPARATION_ADRESSES: HTMLInputElement = recupereEleOuLeve( - SELECTEUR_BOUTON_SEPARATION_ADRESSES, -); -const FORMULAIRE_FACTURATION: HTMLDivElement = recupereEleOuLeve(SELECTEUR_FORMULAIRE_FACTURATION); - /** * Fonction utilitaire pour récupérer un Élément dans une ligne (entrée) du Panier, en levant une * Erreur s'il n'existe pas. @@ -112,7 +93,7 @@ const initialiseMajConteneurPanier = (): void => { .map(D.getUnsafe("donnees")) // Met à jour l'Attribut de présence de Produits dans le Panier .ifRight((donnees: MessageMajBoutonPanierDonnees) => { - CONTENEUR_PANIER.setAttribute(ATTRIBUT_CONTIENT_ARTICLES, String(donnees.quantiteProduits !== 0)); + E.CONTENEUR_PANIER.setAttribute(ATTRIBUT_CONTIENT_ARTICLES, String(donnees.quantiteProduits !== 0)); }); }; }; @@ -126,7 +107,7 @@ const initialiseMajContenuPanier = (): void => { .ifRight((donnees: MessageMajContenuPanierDonnees) => { donnees.produits.forEach((ligne: WCStoreCartItem) => { // Met à jour les entrées du Panier - ENTREES_PANIER_EITHER.ifRight((entrees: Array) => { + E.ENTREES_PANIER.ifRight((entrees: Array) => { Maybe .fromNullable(entrees.find(entree => entree.getAttribute(ATTRIBUT_CLE_PANIER) === ligne.key)) .ifJust((entree: HTMLElement) => { @@ -149,41 +130,41 @@ const initialiseMajContenuPanier = (): void => { }); // Met à jour les totaux du Panier - SOUS_TOTAL_PRODUITS.textContent = formateEnEuros(donnees.sousTotalProduits); - SOUS_TOTAL_REDUCTION.textContent = pipe( + E.SOUS_TOTAL_PRODUITS.textContent = formateEnEuros(donnees.sousTotalProduits); + E.SOUS_TOTAL_REDUCTION.textContent = pipe( inverseNombre(donnees.sousTotalReduction), arrondisADeuxDecimales, formateEnEuros, ); - TOTAL_PANIER.textContent = pipe(arrondisADeuxDecimales(donnees.totalPanier), formateEnEuros); + E.TOTAL_PANIER.textContent = pipe(arrondisADeuxDecimales(donnees.totalPanier), formateEnEuros); }); }); }) // Reporte tout Erreur et réactive les Boutons .ifLeft((erreur: CleNonTrouveError | ValiError) => { reporteErreur(erreur); - ENTREES_PANIER_EITHER.ifRight(entrees => majEtatsActivationBoutons(entrees)); + E.ENTREES_PANIER.ifRight(entrees => majEtatsActivationBoutons(entrees)); }); }; }; const initialiseMajFormulairesPanier = (): void => { - BOUTON_SEPARATION_ADRESSES.addEventListener("click", (): void => { + E.BOUTON_SEPARATION_ADRESSES.addEventListener("click", (): void => { Maybe - .fromFalsy(BOUTON_SEPARATION_ADRESSES.checked) + .fromFalsy(E.BOUTON_SEPARATION_ADRESSES.checked) // Les Adresses sont séparées .ifJust((): void => { // Rend visible le formulaire de facturation - FORMULAIRE_FACTURATION.removeAttribute(ATTRIBUT_HIDDEN); - recupereElementsAvecSelecteur(FORMULAIRE_FACTURATION)("input, select").ifRight( + E.FORMULAIRE_FACTURATION.removeAttribute(ATTRIBUT_HIDDEN); + getDOMElementsWithSelector(E.FORMULAIRE_FACTURATION)("input, select").ifRight( arrayForEach(champ => champ.removeAttribute(ATTRIBUT_DESACTIVE)), ); }) // Les Adresses sont combinées .ifNothing((): void => { // Cache le formulaire de facturation - FORMULAIRE_FACTURATION.setAttribute(ATTRIBUT_HIDDEN, ""); - recupereElementsAvecSelecteur(FORMULAIRE_FACTURATION)( + E.FORMULAIRE_FACTURATION.setAttribute(ATTRIBUT_HIDDEN, ""); + getDOMElementsWithSelector(E.FORMULAIRE_FACTURATION)( "input, select", ).ifRight(arrayForEach(champ => { champ.setAttribute(ATTRIBUT_DESACTIVE, ""); @@ -194,14 +175,14 @@ const initialiseMajFormulairesPanier = (): void => { }; document.addEventListener("DOMContentLoaded", (): void => { - initialiseEmetteursEvenementsFormulairePanier(); + initCartFormEventEmiters(); souscrisEvenementsPanier(); initialiseActionsEntreesPanier(); - initialiseBoutonsChoixMethodesLivraison(); + initShippingRatesChoicesActions(); initialiseMajConteneurPanier(); initialiseMajContenuPanier(); initialiseMajFormulairesPanier(); - initialiseBoutonCalculLivraison(); - initialiseBoutonCreationCommande(); + initShippingCalculationButton(); + initOrderCreationButton(); initialiseElementsCodePromo(); }); diff --git a/web/app/themes/haiku-atelier-2024/src/scripts/scripts-page-produit.ts b/web/app/themes/haiku-atelier-2024/src/scripts/scripts-page-produit.ts index ab215400..c63b1f24 100755 --- a/web/app/themes/haiku-atelier-2024/src/scripts/scripts-page-produit.ts +++ b/web/app/themes/haiku-atelier-2024/src/scripts/scripts-page-produit.ts @@ -33,14 +33,14 @@ import { SELECTEUR_SELECTEUR_QUANTITE, } from "./constantes/dom"; import { lanceAnimationCycleLoading } from "./lib/animations.ts"; +import { recupereElementDocumentEither, mustGetEleInDocument, mustGetElesInDocument } from "./lib/dom.ts"; import { BadRequestError, reporteErreur, ServerError } from "./lib/erreurs.ts"; import { estHTMLSelectElement } from "./lib/gardes.ts"; import { emetMessageMajBoutonPanier } from "./lib/messages.ts"; -import { creeReponseSimplifiee, eitherAsyncFetch, postBackend } from "./lib/reseau.ts"; +import { newPartialResponse, safeFetch, postBackend } from "./lib/reseau.ts"; import { WCStoreCartAddItemArgsSchema } from "./lib/schemas/api/cart-add-item.ts"; import { WCStoreCartSchema } from "./lib/schemas/api/cart.ts"; -import { recupereElementDocumentEither, recupereEleOuLeve, recupereElesOuLeve } from "./lib/utils.ts"; -import { eitherValiParse } from "./lib/validation.ts"; +import { safeSchemaParse } from "./lib/validation.ts"; type EnsembleLienContenu = [HTMLAnchorElement, HTMLElement]; /** États utiles pour les scripts de la page. */ @@ -67,18 +67,18 @@ const deplieToutesSections = (ensembleLiensContenus: Array) // Éléments d'intérêt const E = { - BOUTON_AJOUT_PANIER: recupereEleOuLeve(SELECTEUR_BOUTON_AJOUT_PANIER), - CONTENEUR_FLECHES_DEFILEMENT: recupereEleOuLeve(SELECTEUR_CONTENEUR_FLECHES_DEFILEMENT), - FLECHE_DEFILEMENT_DROITE: recupereEleOuLeve(SELECTEUR_FLECHE_DEFILEMENT_DROITE), - FLECHE_DEFILEMENT_GAUCHE: recupereEleOuLeve(SELECTEUR_FLECHE_DEFILEMENT_GAUCHE), + BOUTON_AJOUT_PANIER: mustGetEleInDocument(SELECTEUR_BOUTON_AJOUT_PANIER), + CONTENEUR_FLECHES_DEFILEMENT: mustGetEleInDocument(SELECTEUR_CONTENEUR_FLECHES_DEFILEMENT), + FLECHE_DEFILEMENT_DROITE: mustGetEleInDocument(SELECTEUR_FLECHE_DEFILEMENT_DROITE), + FLECHE_DEFILEMENT_GAUCHE: mustGetEleInDocument(SELECTEUR_FLECHE_DEFILEMENT_GAUCHE), IMAGES: A.flat([ - recupereEleOuLeve(SELECTEUR_IMAGE_COLONNE_GAUCHE), - recupereElesOuLeve(SELECTEUR_IMAGES_COLONNE_DROITE), + mustGetEleInDocument(SELECTEUR_IMAGE_COLONNE_GAUCHE), + mustGetElesInDocument(SELECTEUR_IMAGES_COLONNE_DROITE), ]), - LIENS_ONGLETS: recupereElesOuLeve(SELECTEUR_LIENS_ONGLETS), - PHOTOS_PRODUIT: recupereEleOuLeve(SELECTEUR_PHOTOS_PRODUIT), - PRIX_PRODUIT: recupereEleOuLeve(SELECTEUR_PRIX_PRODUIT), - SECTIONS_CONTENUS: recupereElesOuLeve(SELECTEUR_SECTIONS_CONTENUS), + LIENS_ONGLETS: mustGetElesInDocument(SELECTEUR_LIENS_ONGLETS), + PHOTOS_PRODUIT: mustGetEleInDocument(SELECTEUR_PHOTOS_PRODUIT), + PRIX_PRODUIT: mustGetEleInDocument(SELECTEUR_PRIX_PRODUIT), + SECTIONS_CONTENUS: mustGetElesInDocument(SELECTEUR_SECTIONS_CONTENUS), SELECTEUR_VARIATION: recupereElementDocumentEither(SELECTEUR_SELECTEUR_QUANTITE), }; @@ -201,7 +201,7 @@ const ajouteProduitAuPanier = (): void => { // Réalise la Requête et traite sa Réponse void EitherAsync // 1. Valide les arguments de la Requête - .liftEither(eitherValiParse(argsRequete, WCStoreCartAddItemArgsSchema)) + .liftEither(safeSchemaParse(argsRequete, WCStoreCartAddItemArgsSchema)) // 2. Exécute un Effet pour empêcher les requêtes concurrentes et lancer une animation de chargement .ifRight(() => { // Désactive le Bouton pour empêcher des requêtes concurrentes @@ -213,7 +213,7 @@ const ajouteProduitAuPanier = (): void => { }) // 3. Exécute la requête via fetch sous forme d'EitherAsync .chain((args: WCStoreCartAddItemArgs) => - eitherAsyncFetch( + safeFetch( postBackend({ corps: JSON.stringify(args), nonce: ETATS_PAGE.nonce, @@ -225,7 +225,7 @@ const ajouteProduitAuPanier = (): void => { .chain((reponse: Response) => EitherAsync(async ({ throwE }) => // Simplifie les données à matcher - match(await creeReponseSimplifiee(reponse)) + match(await newPartialResponse(reponse)) .with({ status: 500 }, () => throwE(new ServerError("500 Server Error"))) .with({ status: 400 }, () => throwE(new BadRequestError("400 Bad Request Error"))) .with({ status: 201 }, r => r.body) @@ -233,7 +233,7 @@ const ajouteProduitAuPanier = (): void => { ) ) // 5. Vérifie le Schéma de la Réponse - .chain((corpsReponse: unknown) => EitherAsync.liftEither(eitherValiParse(corpsReponse, WCStoreCartSchema))) + .chain((corpsReponse: unknown) => EitherAsync.liftEither(safeSchemaParse(corpsReponse, WCStoreCartSchema))) // 6. Exécute un Effet pour la mise à jour du DOM avec les Résultats .ifRight((panier: WCStoreCart) => pipe(