corvée(lint) applique des suggestions de lint Oxlint
This commit is contained in:
parent
c66cf7faba
commit
498ae877a1
6 changed files with 64 additions and 36 deletions
|
|
@ -1,14 +1,16 @@
|
|||
import { Console, Context, Effect, Layer, Match, pipe, Schedule, Schema, SchemaIssue } from "effect";
|
||||
import { SchemaError } from "effect/Schema";
|
||||
import type { SchemaError } from "effect/Schema";
|
||||
import type {
|
||||
HttpClientError,
|
||||
} from "effect/unstable/http";
|
||||
import {
|
||||
FetchHttpClient,
|
||||
HttpClient,
|
||||
HttpClientError,
|
||||
HttpClientRequest,
|
||||
HttpClientResponse,
|
||||
} from "effect/unstable/http";
|
||||
import { HttpClientErrorSchema } from "effect/unstable/http/HttpClientError";
|
||||
import type { CartProduct } from "../schemas/api.ts";
|
||||
import type { CartProduct, GetProducts } from "../schemas/api.ts";
|
||||
import { WooCommerceCart } from "../schemas/cart.ts";
|
||||
|
||||
/** Le nombre maximal d'essais pour une Requête. */
|
||||
|
|
@ -16,20 +18,21 @@ const MAX_RETRIES = 3;
|
|||
/** Le temps d'attente avant de réessayer une Requête. */
|
||||
const RETRY_WAIT_TIME = "1 seconds";
|
||||
|
||||
type APIError = APIRequestError | APIResponseError;
|
||||
|
||||
type APIResponse<T> = T | WooCommerceError;
|
||||
|
||||
/** Décrit une Erreur survenue au traitement d'une `Request`. */
|
||||
class APIRequestError extends Schema.TaggedErrorClass<APIRequestError>()("APIRequestError", {
|
||||
message: Schema.String,
|
||||
cause: Schema.Union([Schema.Defect, HttpClientErrorSchema]),
|
||||
message: Schema.String,
|
||||
}) {}
|
||||
|
||||
/** Décrit une Erreur survenue au traitement d'une `Response`. */
|
||||
class APIResponseError extends Schema.TaggedErrorClass<APIResponseError>()("APIResponseError", {
|
||||
message: Schema.String,
|
||||
cause: Schema.Union([Schema.Defect, HttpClientErrorSchema]),
|
||||
message: Schema.String,
|
||||
}) {}
|
||||
|
||||
type APIError = APIRequestError | APIResponseError;
|
||||
|
||||
class WooCommerceErrorBody extends Schema.Class<WooCommerceErrorBody>("WooCommerceErrorBody")({
|
||||
code: Schema.String,
|
||||
data: Schema.Struct({
|
||||
|
|
@ -37,13 +40,12 @@ class WooCommerceErrorBody extends Schema.Class<WooCommerceErrorBody>("WooCommer
|
|||
}),
|
||||
message: Schema.String,
|
||||
}) {}
|
||||
|
||||
class WooCommerceError extends Schema.Class<WooCommerceError>("WooCommerceError")({
|
||||
body: WooCommerceErrorBody,
|
||||
status: Schema.Number,
|
||||
}) {}
|
||||
|
||||
type APIResponse<T> = T | WooCommerceError;
|
||||
|
||||
/** Client `fetch` contenant les options et en-têtes de Requêtes pré-renseignées. */
|
||||
const APIFetchClient = FetchHttpClient.layer.pipe(
|
||||
Layer.provide(
|
||||
|
|
@ -81,22 +83,22 @@ class APIClient extends Context.Service<APIClient>()("haikuatelier.fr/APIClient"
|
|||
const matchAPIError = (error: HttpClientError.HttpClientError | SchemaError): APIError => {
|
||||
if (error._tag === "SchemaError") {
|
||||
return new APIRequestError({
|
||||
message: `Erreur lors du parsage du corps de la Requête :${SchemaIssue.makeFormatterDefault()(error.issue)}`,
|
||||
cause: error,
|
||||
message: `Erreur lors du parsage du corps de la Requête :${SchemaIssue.makeFormatterDefault()(error.issue)}`,
|
||||
});
|
||||
} else {
|
||||
return Match.typeTags<HttpClientError.HttpClientErrorReason, APIError>()({
|
||||
DecodeError: cause => new APIResponseError({ cause, message: "Le corps de la Réponse ne peut être lu" }),
|
||||
EmptyBodyError: cause => new APIResponseError({ cause, message: "Un corps vide ne peut être lu" }),
|
||||
EncodeError: cause => new APIRequestError({ cause, message: "Le corps de la Requête ne peut être lu" }),
|
||||
InvalidUrlError: cause => new APIRequestError({ cause, message: "L'URL de la Requête n'est pas valide" }),
|
||||
StatusCodeError: cause =>
|
||||
new APIResponseError({ cause, message: "Le code HTTP de la Réponse correspond à un échec" }),
|
||||
TransportError: (cause): APIError =>
|
||||
new APIRequestError({
|
||||
cause,
|
||||
message: "Un problème réseau empêche l'exécution de la Requête",
|
||||
}),
|
||||
EncodeError: cause => new APIRequestError({ cause, message: "Le corps de la Requête ne peut être lu" }),
|
||||
InvalidUrlError: cause => new APIRequestError({ cause, message: "L'URL de la Requête n'est pas valide" }),
|
||||
StatusCodeError: cause =>
|
||||
new APIResponseError({ cause, message: "Le code HTTP de la Réponse correspond à un échec" }),
|
||||
DecodeError: cause => new APIResponseError({ cause, message: "Le corps de la Réponse ne peut être lu" }),
|
||||
EmptyBodyError: cause => new APIResponseError({ cause, message: "Un corps vide ne peut être lu" }),
|
||||
})(error.reason);
|
||||
}
|
||||
};
|
||||
|
|
@ -109,7 +111,7 @@ class APIClient extends Context.Service<APIClient>()("haikuatelier.fr/APIClient"
|
|||
return yield* Effect.succeed(error);
|
||||
});
|
||||
|
||||
const AddProductToCart = Effect.fn("AppClient.AddProductToCart")(
|
||||
const AddProductToCart = Effect.fn("APIClient.AddProductToCart")(
|
||||
function*(nonce: string, productToAdd: CartProduct): Effect.fn.Return<APIResponse<WooCommerceCart>, APIError> {
|
||||
const request = pipe(
|
||||
HttpClientRequest.post(`/wp-json/wc/store/cart/add-item`),
|
||||
|
|
@ -132,7 +134,28 @@ class APIClient extends Context.Service<APIClient>()("haikuatelier.fr/APIClient"
|
|||
},
|
||||
);
|
||||
|
||||
return { AddProductToCart };
|
||||
const GetProducts = Effect.fn("APIClient.GetProducts")(
|
||||
function*(nonce: string, authString: string, queryParams: GetProducts) {
|
||||
const request = pipe(
|
||||
HttpClientRequest.get(`/wp-json/wc/store/products`),
|
||||
HttpClientRequest.setHeader("Nonce", nonce),
|
||||
HttpClientRequest.bearerToken(authString),
|
||||
// Le corps de la Requête a été validée en amont, on peut utiliser Unsafe.
|
||||
HttpClientRequest.setUrlParams(queryParams),
|
||||
);
|
||||
|
||||
const response = yield* pipe(
|
||||
haikuHTTPClient.execute(request),
|
||||
Effect.flatMap(HttpClientResponse.schemaBodyJson(Schema.Unknown)),
|
||||
Effect.mapError(error => matchAPIError(error)),
|
||||
Effect.tapError(error => printErrorAsSuccinctMessage(error)),
|
||||
);
|
||||
|
||||
return response;
|
||||
},
|
||||
);
|
||||
|
||||
return { AddProductToCart, GetProducts };
|
||||
}),
|
||||
}) {
|
||||
static readonly Live = Layer.effect(this, this.make).pipe(Layer.provide(APIFetchClient));
|
||||
|
|
|
|||
|
|
@ -31,7 +31,7 @@ const getAllSelectorFromParent =
|
|||
pipe(
|
||||
parent.querySelectorAll<E>(selector),
|
||||
// Convertis NodeListOf en Array.
|
||||
(xs: NodeListOf<E>) => Array.from<E>(xs),
|
||||
(xs: NodeListOf<E>) => [...xs],
|
||||
(xs: Array<E>) => Option.liftPredicate(FxArray.isReadonlyArrayNonEmpty)(xs),
|
||||
);
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,9 @@
|
|||
import { Effect } from "effect";
|
||||
import { ATTRIBUT_CHARGEMENT, ATTRIBUT_DESACTIVE } from "../../scripts/constantes/dom.ts";
|
||||
|
||||
const setLoadingState = Effect.fn("setLoadingState")(function*(element: HTMLElement, isLoading: boolean) {
|
||||
element.toggleAttribute(ATTRIBUT_DESACTIVE, isLoading);
|
||||
element.toggleAttribute(ATTRIBUT_CHARGEMENT, isLoading);
|
||||
});
|
||||
|
||||
export { setLoadingState };
|
||||
|
|
@ -1,18 +1,18 @@
|
|||
import { Context, Effect, flow, Layer, pipe, Schedule, Schema } from "effect";
|
||||
import { FetchHttpClient, HttpClient, HttpClientRequest, HttpClientResponse } from "effect/unstable/http";
|
||||
import { HttpClientError } from "effect/unstable/http/HttpClientError";
|
||||
|
||||
class Todo extends Schema.Class<Todo>("Todo")({
|
||||
userId: Schema.Number,
|
||||
id: Schema.Number,
|
||||
title: Schema.String,
|
||||
completed: Schema.Boolean,
|
||||
}) {}
|
||||
import type { HttpClientError } from "effect/unstable/http/HttpClientError";
|
||||
|
||||
class FetchClientError extends Schema.TaggedErrorClass<FetchClientError>()("FetchClientError", {
|
||||
cause: Schema.Defect,
|
||||
}) {}
|
||||
|
||||
class Todo extends Schema.Class<Todo>("Todo")({
|
||||
completed: Schema.Boolean,
|
||||
id: Schema.Number,
|
||||
title: Schema.String,
|
||||
userId: Schema.Number,
|
||||
}) {}
|
||||
|
||||
class FetchClientExample extends Context.Service<FetchClientExample, {
|
||||
readonly allTodos: Effect.Effect<ReadonlyArray<Todo>, FetchClientError>;
|
||||
createTodo(todo: Omit<Todo, "id">): Effect.Effect<Todo, FetchClientError>;
|
||||
|
|
@ -75,8 +75,8 @@ class FetchClientExample extends Context.Service<FetchClientExample, {
|
|||
|
||||
return FetchClientExample.of({
|
||||
allTodos,
|
||||
getTodo,
|
||||
createTodo,
|
||||
getTodo,
|
||||
});
|
||||
}),
|
||||
).pipe(
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
// oxlint-disable typescript/dot-notation
|
||||
import type { SchemaError } from "effect/Schema";
|
||||
|
||||
// oxlint-disable typescript/dot-notation
|
||||
import {
|
||||
Array as FxArray,
|
||||
Console,
|
||||
|
|
@ -21,6 +21,7 @@ import type { APIError } from "../../scripts-effect/lib/api.ts";
|
|||
import type { DetailEnsemble } from "./types.d.ts";
|
||||
|
||||
import { APIClient } from "../../scripts-effect/lib/api.ts";
|
||||
import { setLoadingState } from "../../scripts-effect/lib/elements.ts";
|
||||
import { CartProduct } from "../../scripts-effect/schemas/api.ts";
|
||||
import { WooCommerceCart } from "../../scripts-effect/schemas/cart.ts";
|
||||
import { Product, ProductVariation, ProductVariationAttribute } from "../../scripts-effect/schemas/product.ts";
|
||||
|
|
@ -98,11 +99,6 @@ class ProductPageDOM extends Context.Service<ProductPageDOM>()(
|
|||
);
|
||||
});
|
||||
|
||||
const setLoadingState = Effect.fn("setLoadingState")(function*(element: HTMLElement, isLoading: boolean) {
|
||||
element.toggleAttribute(ATTRIBUT_DESACTIVE, isLoading);
|
||||
element.toggleAttribute(ATTRIBUT_CHARGEMENT, isLoading);
|
||||
});
|
||||
|
||||
const detailButtonClickHandler = Effect.fn("detailButtonClickHandler")(
|
||||
function*(evt: Event) {
|
||||
// Empêche la pollution de l'historique de navigation
|
||||
|
|
@ -232,7 +228,7 @@ class ProductPageDOM extends Context.Service<ProductPageDOM>()(
|
|||
// Désactive les interactions le temps de la requête.
|
||||
yield* setLoadingState(AddToCartButton, true);
|
||||
yield* SubscriptionRef.set(AddToCartButtonText, "Adding Product...");
|
||||
// lanceAnimationCycleLoading(AddToCartButton, 500);
|
||||
// LanceAnimationCycleLoading(AddToCartButton, 500);
|
||||
|
||||
// Exécute la Requête auprès du backend.
|
||||
const newCart = yield* API.AddProductToCart(PageStates.nonce, requestBody);
|
||||
|
|
|
|||
|
|
@ -7,7 +7,7 @@ class ProductPageMessages extends Context.Service<ProductPageMessages>()("haikua
|
|||
const { AddToCartButton } = yield* ProductPageElements;
|
||||
|
||||
const AddToCartButtonText = yield* SubscriptionRef.make("Add to cart");
|
||||
// const AddToCartErrorText = yield* SubscriptionRef.make<Option.Option<string>>(Option.none());
|
||||
// Const AddToCartErrorText = yield* SubscriptionRef.make<Option.Option<string>>(Option.none());
|
||||
|
||||
const initAddToCartButtonUpdates = Effect.fn("initAddToCartButtonUpdates")(function*() {
|
||||
return yield* pipe(
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue