2024-12-02

This commit is contained in:
gcch 2024-12-02 10:40:47 +01:00
commit 8613e0698c
12 changed files with 272 additions and 399 deletions

View file

@ -1,210 +0,0 @@
{
"_api.sn6CvYBX.js": {
"file": "api.sn6CvYBX.js",
"name": "api",
"integrity": "sha512-IHCUEXhZ0jGYLByQuCrZLLyT33rn+dZ+vE3cqzGnYODtRBf20xpDudhp9dJBYHK2WHuPXUO9TQ9RG23/UFKgEA=="
},
"_exports.B0KsqwcX.js": {
"file": "exports.B0KsqwcX.js",
"name": "exports",
"integrity": "sha512-4J3P0kXIHBndu9OwcKNN5eaSkK9pPXeILC4nQ0G6BGXo8TkHVbpNq1vtKhif4bJKmPB7BCfEN1qxrabF9002uw=="
},
"_gardes.DBQSoZA5.js": {
"file": "gardes.DBQSoZA5.js",
"name": "gardes",
"integrity": "sha512-h25A7ttXwwAmgkVObii1ElP0ao+/PYIq9q0VE0n5rvVF+MqaI6OKp+eSIWDHsmrNy0gfjOcakIFQjc9wKXaJmg=="
},
"_index-c1cc4c86.C0keEzN6.js": {
"file": "index-c1cc4c86.C0keEzN6.js",
"name": "index-c1cc4c86",
"imports": [
"_utils.CpY6lC-L.js"
],
"integrity": "sha512-+eWqf9Np9p4PooSLS38x1vueotM7CUQhE4+TOsEUOTiq71SJMJTKLhnmPu7pfs5vAPsfyFOLTcY6Y53Axdz0mg=="
},
"_index.CeK6pfoJ.js": {
"file": "index.CeK6pfoJ.js",
"name": "index",
"integrity": "sha512-1w99lJFYDu79R+hHxMxvYeqYSoK7veDPlF8Rzbs6qf56698A9BJslhj7GsDepyEXmawU05g6EBusu5e8sFgSjw=="
},
"_messages.Cfpdtehd.js": {
"file": "messages.Cfpdtehd.js",
"name": "messages",
"imports": [
"_validation.BxHP2h2i.js",
"_utils.CpY6lC-L.js",
"_exports.B0KsqwcX.js"
],
"integrity": "sha512-MAd2Uap9aHnb+4eD+JmEmuzmw9R5xyPrcExBzRRtRAB3C8CbHSj2qa5yyzEi/MRfY/poaALRYw9UR1wu7Eu3vw=="
},
"_nombres.BEH5KeJK.js": {
"file": "nombres.BEH5KeJK.js",
"name": "nombres",
"imports": [
"_exports.B0KsqwcX.js"
],
"integrity": "sha512-1YnZOciujiT2HT/ZEw/euv5CloN9v5BmWGlK1YB11pz6eUte9jCuf0LVSNytze7aKVABgieyPytilJKfkrhITA=="
},
"_reseau.BTSNCA1g.js": {
"file": "reseau.BTSNCA1g.js",
"name": "reseau",
"imports": [
"_api.sn6CvYBX.js",
"_utils.CpY6lC-L.js"
],
"integrity": "sha512-5XlkhlMl2cjhO3WGGBiZjs3fTwPUHssKwGsx4T8P9Fob5Ui0Rm7ibULQRGBBC9XyoBdci6HCqSvYJWVh4CJ3/w=="
},
"_utils.CpY6lC-L.js": {
"file": "utils.CpY6lC-L.js",
"name": "utils",
"imports": [
"_exports.B0KsqwcX.js"
],
"integrity": "sha512-S5zwOSk60GPiiMWS2FvWLFbj2M9UezotF8SDogLT3nyhwcVwlwhX1v2VkteSlxzRysxGfQoTLZ9A60dQYCQ2ww=="
},
"_validation.BxHP2h2i.js": {
"file": "validation.BxHP2h2i.js",
"name": "validation",
"imports": [
"_utils.CpY6lC-L.js"
],
"integrity": "sha512-wO9O4uiE8p6HzOs3vrR5dq03/lSRYBxnM3b15rDK9IB4ANkkpUD8BBWu+5jLYHndbmCX/bNNYDOHvEKga9HXTg=="
},
"web/app/themes/haiku-atelier-2024/src/scripts/gaffe.ts": {
"file": "gaffe.js",
"name": "gaffe",
"src": "web/app/themes/haiku-atelier-2024/src/scripts/gaffe.ts",
"isEntry": true,
"imports": [
"_api.sn6CvYBX.js",
"_exports.B0KsqwcX.js"
],
"integrity": "sha512-slFdBLR4oN3CEi9YpXwX0sYUyTTWc6xTSgNtNRHBUyrQCFc3Hv0khwd52Ao/80gELsToD3/otO+SH3Vhq3Ttrg=="
},
"web/app/themes/haiku-atelier-2024/src/scripts/scripts-bouton-panier.ts": {
"file": "scripts-bouton-panier.js",
"name": "scripts-bouton-panier",
"src": "web/app/themes/haiku-atelier-2024/src/scripts/scripts-bouton-panier.ts",
"isEntry": true,
"imports": [
"_utils.CpY6lC-L.js",
"_messages.Cfpdtehd.js",
"_exports.B0KsqwcX.js",
"_validation.BxHP2h2i.js"
],
"integrity": "sha512-oYY9nW57p388NsZjHHwp+hAdsp1bB0EUVNnSLhfhSl+wROZ1XwjXeVZKUV0Val2dUhA6Eu5iHdufzIcWoHMZTw=="
},
"web/app/themes/haiku-atelier-2024/src/scripts/scripts-bouton-retour-sommet.ts": {
"file": "scripts-bouton-retour-sommet.js",
"name": "scripts-bouton-retour-sommet",
"src": "web/app/themes/haiku-atelier-2024/src/scripts/scripts-bouton-retour-sommet.ts",
"isEntry": true,
"imports": [
"_utils.CpY6lC-L.js",
"_exports.B0KsqwcX.js",
"_index-c1cc4c86.C0keEzN6.js"
],
"integrity": "sha512-uodiNu9VatWMjE3otfIawNnfI5dfPse56Yy+18M7dvkuW9eKVsLzPhgL9TuoO3uATKTIAuc9dhRP4nEKx6Fglg=="
},
"web/app/themes/haiku-atelier-2024/src/scripts/scripts-menu-categories.ts": {
"file": "scripts-menu-categories.js",
"name": "scripts-menu-categories",
"src": "web/app/themes/haiku-atelier-2024/src/scripts/scripts-menu-categories.ts",
"isEntry": true,
"imports": [
"_index.CeK6pfoJ.js",
"_utils.CpY6lC-L.js",
"_exports.B0KsqwcX.js"
],
"integrity": "sha512-da/GHRU53343rznuQbNy0XHyfMeqGu779Ut2c8PGEfhaAYVOn64HBwJ08CZltOfl9VJHvcFl1Bc1GYVzWfV3OQ=="
},
"web/app/themes/haiku-atelier-2024/src/scripts/scripts-menu-mobile.ts": {
"file": "scripts-menu-mobile.js",
"name": "scripts-menu-mobile",
"src": "web/app/themes/haiku-atelier-2024/src/scripts/scripts-menu-mobile.ts",
"isEntry": true,
"imports": [
"_utils.CpY6lC-L.js",
"_exports.B0KsqwcX.js",
"_index-c1cc4c86.C0keEzN6.js"
],
"integrity": "sha512-OpH8rcFhryaJkylejvd+lBz/8471rvL531zUUSh1EW0j6vuZ7xlZkZnw/InUskptCAea/2RBfiN5F/SbMNycNQ=="
},
"web/app/themes/haiku-atelier-2024/src/scripts/scripts-page-a-propos.ts": {
"file": "scripts-page-a-propos.js",
"name": "scripts-page-a-propos",
"src": "web/app/themes/haiku-atelier-2024/src/scripts/scripts-page-a-propos.ts",
"isEntry": true,
"imports": [
"_utils.CpY6lC-L.js",
"_exports.B0KsqwcX.js",
"_index-c1cc4c86.C0keEzN6.js"
],
"integrity": "sha512-nlGl2dpx7IQoeyluJxLOqt2TEojjRoE5N1zzDCmlgCObDuJHONjMnW1AgTMFIQPFrLDdr+4ko829NGO6aZySiA=="
},
"web/app/themes/haiku-atelier-2024/src/scripts/scripts-page-accueil.ts": {
"file": "scripts-page-accueil.js",
"name": "scripts-page-accueil",
"src": "web/app/themes/haiku-atelier-2024/src/scripts/scripts-page-accueil.ts",
"isEntry": true,
"imports": [
"_utils.CpY6lC-L.js",
"_nombres.BEH5KeJK.js",
"_exports.B0KsqwcX.js",
"_index-c1cc4c86.C0keEzN6.js"
],
"integrity": "sha512-pnghMb+57OAqAQZOzwx5ByQNSuzIB9AO75cgYEB2mwrcJ7BE2HxkFPAiFeDf7Et/l+bRnLUiFlF5DXQG4Plffw=="
},
"web/app/themes/haiku-atelier-2024/src/scripts/scripts-page-boutique.ts": {
"file": "scripts-page-boutique.js",
"name": "scripts-page-boutique",
"src": "web/app/themes/haiku-atelier-2024/src/scripts/scripts-page-boutique.ts",
"isEntry": true,
"imports": [
"_index.CeK6pfoJ.js",
"_validation.BxHP2h2i.js",
"_api.sn6CvYBX.js",
"_utils.CpY6lC-L.js",
"_reseau.BTSNCA1g.js",
"_exports.B0KsqwcX.js"
],
"integrity": "sha512-eLiXDKtS0NQp3xgqb+TzTLgkFg5SDLeZKlNC0g7xcJm10yFWv1mQaTUcG7oA80hEkFR3wWGk8Ywlf3snGcQfDg=="
},
"web/app/themes/haiku-atelier-2024/src/scripts/scripts-page-panier.ts": {
"file": "scripts-page-panier.js",
"name": "scripts-page-panier",
"src": "web/app/themes/haiku-atelier-2024/src/scripts/scripts-page-panier.ts",
"isEntry": true,
"imports": [
"_utils.CpY6lC-L.js",
"_messages.Cfpdtehd.js",
"_nombres.BEH5KeJK.js",
"_index.CeK6pfoJ.js",
"_validation.BxHP2h2i.js",
"_api.sn6CvYBX.js",
"_reseau.BTSNCA1g.js",
"_exports.B0KsqwcX.js",
"_index-c1cc4c86.C0keEzN6.js",
"_gardes.DBQSoZA5.js"
],
"integrity": "sha512-f+g2Aj4Ngwii3Y2CgGpZt1bG8DL9UmgB2UhRiket/6PlnMmk4OZ57ji0tZdq022TjAud7Ll4OOSWzTMf+WPZnQ=="
},
"web/app/themes/haiku-atelier-2024/src/scripts/scripts-page-produit.ts": {
"file": "scripts-page-produit.js",
"name": "scripts-page-produit",
"src": "web/app/themes/haiku-atelier-2024/src/scripts/scripts-page-produit.ts",
"isEntry": true,
"imports": [
"_index.CeK6pfoJ.js",
"_validation.BxHP2h2i.js",
"_api.sn6CvYBX.js",
"_utils.CpY6lC-L.js",
"_gardes.DBQSoZA5.js",
"_messages.Cfpdtehd.js",
"_reseau.BTSNCA1g.js",
"_exports.B0KsqwcX.js",
"_index-c1cc4c86.C0keEzN6.js"
],
"integrity": "sha512-TxxHyGL6JJUksf+8ohB0NoUpIwxvn/iroG7A0QiEzmJk17snbdNZH5WHfyNHmTo26T19KjkTsNwXqzURce9n8Q=="
}
}

View file

@ -100,7 +100,7 @@ $total_panier = Number::format(floatval(WC()->cart->get_totals()["total"]), prec
foreach (WC()->cart->get_cart() as $cle_panier => $article_panier) {
$panier[$cle_panier] = [
"attributs" => recupere_et_formate_attributs_produit($article_panier["data"]?->get_attributes()),
// "attributs" => recupere_et_formate_attributs_produit($article_panier["data"]?->get_attributes()),
"cle" => $cle_panier,
"id_produit" => $article_panier["product_id"],
"id_variation" => $article_panier["variation_id"],

View file

@ -57,7 +57,7 @@ const client = new BrowserClient({
environment: import.meta.env.VITE_MODE,
integrations: [
breadcrumbsIntegration(),
captureConsoleIntegration(),
captureConsoleIntegration({ levels: ["warn", "error"] }),
dedupeIntegration(),
functionToStringIntegration(),
globalHandlersIntegration(),

View file

@ -33,6 +33,12 @@ export class DOMElementAbsentError extends Error {
this.name = "DOMElementAbsentError";
}
}
export class ForbiddenError extends Error {
constructor(message = "403 ForbiddenError") {
super(message);
this.name = "ForbiddenError";
}
}
export class NonExistingKeyError extends Error {
constructor(message: unknown) {
super(JSON.stringify(message));
@ -107,6 +113,16 @@ export const reporteErreur = <E extends Error>(erreur: E): string => captureExce
* @returns never Lève une Erreur et ne retourne donc rien.
*/
export const reporteEtLeveErreur = <E extends Error>(erreur: E): never => {
reporteErreur<E>(erreur);
reporteErreur(erreur);
throw erreur;
};
export const reporteEtJournaliseErreur = <E extends Error>(erreur: E): void => {
reporteErreur(erreur);
console.error(erreur);
};
export const reporteEtRetourneErreur = <E extends Error>(erreur: E): E => {
reporteErreur(erreur);
return erreur;
};

View file

@ -3,15 +3,20 @@ import { EitherAsync } from "purify-ts";
import { match, P } from "ts-pattern";
import { type GenericSchema, parse } from "valibot";
import type { ReponseSimplifiee } from "./types/reseau";
import type { HttpCodeErrors, ReponseSimplifiee } from "./types/reseau";
import { ENTETE_WC_NONCE } from "../constantes/api.ts";
import {
BadRequestError,
ErreurInconnue,
ForbiddenError,
leveBadRequestError,
leveErreur,
leveNotFoundError,
leveUnauthorizedError,
NotFoundError,
ServerError,
UnauthorizedError,
type UnknownError,
} from "./erreurs.ts";
import { estWCError } from "./schemas/api/erreurs.ts";
@ -147,3 +152,13 @@ export const creeReponseSimplifiee = async (reponse: Response): Promise<ReponseS
status: reponse.status,
};
};
export const traiteErreursBackendWooCommerce = (rs: ReponseSimplifiee): HttpCodeErrors => {
return match(rs)
.with({ status: 400 }, () => new BadRequestError())
.with({ status: 401 }, () => new UnauthorizedError())
.with({ status: 403 }, () => new ForbiddenError())
.with({ status: 404 }, () => new NotFoundError())
.with({ status: 500 }, () => new ServerError())
.otherwise(rs => new Error(String(rs.status)));
};

View file

@ -1,5 +1,15 @@
import type { BadRequestError, ForbiddenError, NotFoundError, ServerError, UnauthorizedError } from "../erreurs";
export type FetchErrors = DOMException | Error | TypeError;
export type HttpCodeErrors =
| BadRequestError
| Error
| ForbiddenError
| NotFoundError
| ServerError
| UnauthorizedError;
export interface ReponseSimplifiee {
body: unknown;
status: number;

View file

@ -9,7 +9,14 @@ import {
recupereElementsAvecSelecteur,
recupereElementsOuLeve,
} from "./dom.ts";
import { CleNonTrouveError } from "./erreurs.ts";
import {
BadRequestError,
CleNonTrouveError,
ForbiddenError,
NotFoundError,
ServerError,
UnauthorizedError,
} from "./erreurs.ts";
export const recupereElementsDocumentEither: <E extends Element = Element>(
selecteur: string,
@ -68,3 +75,15 @@ export const majEtatChargementBouton = (bouton: HTMLButtonElement, activation: b
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;

View file

@ -13,7 +13,7 @@ import type { WCStoreShippingRateShippingRates } from "../lib/types/api/couts-li
import type { APIFetchErrors } from "../lib/types/api/erreurs";
import type { WCV3Order, WCV3OrdersArgs } from "../lib/types/api/v3/orders";
import type { EtatsPageGenerique } from "../lib/types/pages";
import type { FetchErrors } from "../lib/types/reseau";
import type { FetchErrors, HttpCodeErrors } from "../lib/types/reseau";
import { ROUTE_API_MAJ_CLIENT, ROUTE_API_NOUVELLE_COMMANDES } from "../constantes/api";
import {
@ -36,17 +36,30 @@ import {
ERREUR_GENERIQUE_SOUMISSION_ADRESSES,
} from "../constantes/messages-utilisateur";
import { eitherJsonParse, eitherSessionStorageGet } from "../lib/dom";
import { BadRequestError, leveErreur, NonExistingKeyError, reporteErreur, ServerError } from "../lib/erreurs";
import {
BadRequestError,
leveErreur,
NonExistingKeyError,
reporteErreur,
reporteEtJournaliseErreur,
ServerError,
} from "../lib/erreurs";
import { ErreurAdresseInvalide } from "../lib/erreurs/adresses";
import { emetUniqueMessageBroadcastChannel } from "../lib/messages";
import { diviseParCent, formateEnEuros } from "../lib/nombres";
import { creeReponseSimplifiee, eitherAsyncFetch, postBackend } from "../lib/reseau";
import { creeReponseSimplifiee, eitherAsyncFetch, postBackend, traiteErreursBackendWooCommerce } from "../lib/reseau";
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 { majEtatChargementBouton, recupereElementsDocumentEither, recupereEleOuLeve } from "../lib/utils";
import {
estErreurFetch,
estErreurHttp,
majEtatChargementBouton,
recupereElementsDocumentEither,
recupereEleOuLeve,
} from "../lib/utils";
import { eitherParse } from "../lib/validation";
// @ts-expect-error -- États injectés par le modèle PHP
@ -159,18 +172,16 @@ export const initialiseBoutonCalculLivraison = (): void => {
)
// 4. Traite les cas d'Erreurs et récupère le Corps de la Réponse
.chain((reponse: Response) =>
EitherAsync<BadRequestError | ErreurAdresseInvalide | ServerError, unknown>(async ({ throwE }) =>
EitherAsync<ErreurAdresseInvalide | HttpCodeErrors, unknown>(async ({ throwE }) =>
// Simplifie les données à matcher
match(await creeReponseSimplifiee(reponse))
.with({ status: 200 }, rs => rs.body)
// Problème d'adresse
.with({
body: P.when(body => estWCAddressError(body)),
status: 400,
}, (r): never => throwE(new ErreurAdresseInvalide(r.body.data.params)))
.with({ status: 400 }, (): never => throwE(new BadRequestError("400 Bad Request Error")))
.with({ status: 500 }, (): never => throwE(new ServerError("500 Server Error")))
.otherwise((rs): never => throwE(new Error(`Erreur inconnue ${String(rs.status)}`)))
.with(
{ body: P.when(body => estWCAddressError(body)), status: 400 },
(r): never => throwE(new ErreurAdresseInvalide(r.body.data.params)),
)
.otherwise((rs): never => throwE(traiteErreursBackendWooCommerce(rs)))
)
)
// 5. Vérifie le Schéma de la Réponse
@ -202,21 +213,30 @@ export const initialiseBoutonCalculLivraison = (): void => {
})
// 7. Traite les Erreurs et affiche un message à l'Utilisateur
.ifLeft(
(
erreur: BadRequestError | ErreurAdresseInvalide | FetchErrors | ServerError | ValiError<AnySchema>,
): void => {
(erreur: ErreurAdresseInvalide | FetchErrors | HttpCodeErrors | ValiError<AnySchema>): void => {
match(erreur)
.with(P.instanceOf(ValiError), (e): void => {
reporteErreur(e);
.when(estErreurHttp, (e): void => {
reporteEtJournaliseErreur(e);
E.MESSAGE_ADRESSES.textContent = ERREUR_GENERIQUE_SOUMISSION_ADRESSES;
})
.when(estErreurFetch, (e): void => {
reporteEtJournaliseErreur(e);
E.MESSAGE_ADRESSES.textContent = ERREUR_GENERIQUE_RESEAU;
})
.with(P.instanceOf(ValiError), (e: ValiError<AnySchema>): void => {
reporteEtJournaliseErreur(e);
console.error(e.issues);
E.MESSAGE_ADRESSES.textContent = ERREUR_GENERIQUE_SOUMISSION_ADRESSES;
})
.with(P.instanceOf(ErreurAdresseInvalide), (e): void => {
reporteErreur(e);
console.error(e, e.problemes);
.with(P.instanceOf(ErreurAdresseInvalide), (e: ErreurAdresseInvalide): void => {
reporteEtJournaliseErreur(e);
console.error(e.problemes);
match(e.problemes)
.when(
// TODO: Créer une fonction utilitaire
p => pipe(dictValues(p), arrayFind(c => c === "The provided postcode is not valid")),
// TODO: Créer une fonction utililtaire pour fixer le texte d'un message
(): void => {
E.MESSAGE_ADRESSES.textContent = ERREUR_ADRESSE_MAUVAIS_CODE_POSTAL;
},
@ -225,16 +245,6 @@ export const initialiseBoutonCalculLivraison = (): void => {
E.MESSAGE_ADRESSES.textContent = ERREUR_GENERIQUE_SOUMISSION_ADRESSES;
});
})
.with(P.instanceOf(ServerError), P.instanceOf(BadRequestError), (e): void => {
reporteErreur(e);
console.error(e);
E.MESSAGE_ADRESSES.textContent = ERREUR_GENERIQUE_SOUMISSION_ADRESSES;
})
.with(P.instanceOf(DOMException), P.instanceOf(TypeError), P.instanceOf(Error), (e): void => {
reporteErreur(e);
console.error(e);
E.MESSAGE_ADRESSES.textContent = ERREUR_GENERIQUE_RESEAU;
})
.exhaustive();
E.BOUTON_ACTIONS_FORMULAIRE.textContent = "Submit your addresses";