Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(in-4412): logger in magento api #1559

Merged
merged 13 commits into from
Dec 12, 2024
Merged
5 changes: 5 additions & 0 deletions .changeset/grumpy-eels-care.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@vue-storefront/magento-api": minor
---

[CHANGED] Replaced `consola` with Alokai Logger. To learn more about logger, visit [Alokai Logger](https://docs.alokai.com/middleware/guides/logging/).
1 change: 0 additions & 1 deletion packages/api-client/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,6 @@
"@vue-storefront/magento-types": "2.0.0",
"@vue-storefront/middleware": "^5.1.0",
"agentkeepalive": "^4.2.1",
"consola": "^3.1.0",
"dotenv": "^16.0.1",
"graphql": "^16.3.0",
"graphql-tag": "^2.12.6",
Expand Down
8 changes: 5 additions & 3 deletions packages/api-client/src/api/cmsPage/index.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
import { ApolloQueryResult } from "@apollo/client/core";
import consola from "consola";
import type { CustomHeaders } from "@vue-storefront/magento-types";
import { CmsPageQuery, CmsPageQueryVariables, CustomQuery } from "@vue-storefront/magento-types";
import gql from "graphql-tag";
import { getLogger } from "@vue-storefront/middleware";
import cmsPageQuery from "./cmsPage";
import { Context } from "../../types/context";
import getHeaders from "../getHeaders";
Expand Down Expand Up @@ -71,6 +71,8 @@ export async function cmsPage(
customQuery: CustomQuery = { cmsPage: "cmsPage" },
customHeaders: CustomHeaders = {}
): Promise<ApolloQueryResult<CmsPageQuery>> {
const logger = getLogger(context);

try {
const { cmsPage: cmsPageGQL } = context.extendQuery(customQuery, {
cmsPage: {
Expand All @@ -91,15 +93,15 @@ export async function cmsPage(
} catch (error) {
// For error in data we don't throw 500, because it's not server error
if (error.graphQLErrors) {
consola.debug(error);
logger.error(error);

return {
...error,
errors: error.graphQLErrors,
data: null,
};
}
consola.error(error);

throw error.networkError?.result || error;
}
}
8 changes: 5 additions & 3 deletions packages/api-client/src/api/productDetails/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import type {
ProductDetailsQueryVariables,
} from "@vue-storefront/magento-types";
import gql from "graphql-tag";
import consola from "consola";
import { getLogger } from "@vue-storefront/middleware";
import productDetailsQuery from "./productDetailsQuery";
import type { Context } from "../../types/context";
import getHeaders from "../getHeaders";
Expand Down Expand Up @@ -111,6 +111,8 @@ export async function productDetails(
customQuery: CustomQuery = { productDetails: "productDetails" },
customHeaders: CustomHeaders = {}
): Promise<ApolloQueryResult<ProductDetailsQuery>> {
const logger = getLogger(context);

const defaultParams = {
pageSize: 10,
currentPage: 1,
Expand Down Expand Up @@ -148,15 +150,15 @@ export async function productDetails(
} catch (error) {
// For error in data we don't throw 500, because it's not server error
if (error.graphQLErrors) {
consola.debug(error);
logger.error(error);

return {
...error,
errors: error.graphQLErrors,
data: null,
};
}
consola.error(error);

throw error.networkError?.result || error;
}
}
8 changes: 5 additions & 3 deletions packages/api-client/src/api/products/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import {
ProductsListQueryVariables,
} from "@vue-storefront/magento-types";
import gql from "graphql-tag";
import consola from "consola";
import { getLogger } from "@vue-storefront/middleware";
import productsListQuery from "./productsList";
import { Context } from "../../types/context";
import getHeaders from "../getHeaders";
Expand Down Expand Up @@ -111,6 +111,8 @@ export async function products(
customQuery: CustomQuery = { products: "products" },
customHeaders: CustomHeaders = {}
): Promise<ApolloQueryResult<ProductsListQuery>> {
const logger = getLogger(context);

const defaultParams = {
pageSize: 10,
currentPage: 1,
Expand Down Expand Up @@ -148,15 +150,15 @@ export async function products(
} catch (error) {
// For error in data we don't throw 500, because it's not server error
if (error.graphQLErrors) {
consola.debug(error);
logger.error(error);

return {
...error,
errors: error.graphQLErrors,
data: null,
};
}
consola.error(error);

throw error.networkError?.result || error;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import { GraphQLError } from "graphql";
import type { CustomHeaders } from "@vue-storefront/magento-types";
import { RequestPasswordResetEmailMutation, RequestPasswordResetEmailMutationVariables } from "@vue-storefront/magento-types";
import gql from "graphql-tag";
import consola from "consola";
import { getLogger } from "@vue-storefront/middleware";
import recaptchaValidator from "../../helpers/recaptcha/recaptchaValidator";
import requestPasswordResetEmailMutation from "./requestPasswordResetEmail";
import { Context } from "../../types/context";
Expand All @@ -28,6 +28,8 @@ export async function requestPasswordResetEmail(
input: RequestPasswordResetEmailMutationVariables,
customHeaders: CustomHeaders = {}
): Promise<FetchResult<RequestPasswordResetEmailMutation>> {
const logger = getLogger(context);

const { recaptchaToken, ...variables } = input;

if (context.config.recaptcha.isEnabled) {
Expand All @@ -44,7 +46,7 @@ export async function requestPasswordResetEmail(
}
}

consola.debug("[VSF: Magento] requestPasswordResetEmail", JSON.stringify(input, null, 2));
logger.debug(`Requesting password reset email with input`, { input });
const result = await context.client.mutate<RequestPasswordResetEmailMutation, RequestPasswordResetEmailMutationVariables>({
mutation: gql`
${requestPasswordResetEmailMutation}
Expand Down
6 changes: 4 additions & 2 deletions packages/api-client/src/api/resetPassword/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import { GraphQLError } from "graphql";
import type { CustomHeaders } from "@vue-storefront/magento-types";
import { ResetPasswordMutation, ResetPasswordMutationVariables } from "@vue-storefront/magento-types";
import gql from "graphql-tag";
import consola from "consola";
import { getLogger } from "@vue-storefront/middleware";
import resetPasswordMutation from "./resetPassword";
import { Context } from "../../types/context";
import recaptchaValidator from "../../helpers/recaptcha/recaptchaValidator";
Expand All @@ -30,6 +30,8 @@ export async function resetPassword(
input: ResetPasswordMutationVariables,
customHeaders: CustomHeaders = {}
): Promise<FetchResult<ResetPasswordMutation>> {
const logger = getLogger(context);

const { recaptchaToken, ...variables } = input;

if (context.config.recaptcha.isEnabled) {
Expand All @@ -46,7 +48,7 @@ export async function resetPassword(
}
}

consola.debug("[VSF: Magento] requestPasswordResetEmail", JSON.stringify(input, null, 2));
logger.debug("Initiating password reset request with input", { input });
const result = await context.client.mutate<ResetPasswordMutation, ResetPasswordMutationVariables>({
mutation: gql`
${resetPasswordMutation}
Expand Down
21 changes: 12 additions & 9 deletions packages/api-client/src/helpers/magentoLink/graphQl.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import { onError } from "@apollo/client/link/error";
import { RetryLink } from "@apollo/client/link/retry";
import { setContext } from "@apollo/client/link/context";
import AgentKeepAlive from "agentkeepalive";
import consola from "consola";
import { getLogger, type AlokaiContainer } from "@vue-storefront/middleware";
import { handleRetry } from "./linkHandlers";
import { Config } from "../../types/setup";
import possibleTypes from "../../types/possibleTypes.json";
Expand All @@ -15,8 +15,10 @@ const agent = new HttpsAgent({
timeout: 30000,
});

const createErrorHandler = () =>
const createErrorHandler = (alokai: AlokaiContainer) =>
onError(({ graphQLErrors, networkError }) => {
const logger = getLogger(alokai);

if (graphQLErrors) {
graphQLErrors.forEach(({ message, locations, path, extensions }) => {
// Mute all GraphQL authorization errors
Expand All @@ -26,27 +28,28 @@ const createErrorHandler = () =>

if (!message.includes("Resource Owner Password Credentials Grant")) {
if (!locations) {
consola.error(`[GraphQL error]: Message: ${message}, Path: ${path}`);
logger.error(message, { path });
return;
}

const parsedLocations = locations.map(({ column, line }) => `[column: ${column}, line: ${line}]`);

consola.error(`[GraphQL error]: Message: ${message}, Location: ${parsedLocations.join(", ")}, Path: ${path}`);
logger.error(message, { path, location: parsedLocations.join(", ") });
}
});
}

if (networkError) {
consola.error(`[Network error]: ${networkError}`);
logger.error(networkError, { type: "Network Error" });
}
});

export const apolloLinkFactory = (
settings: Config,
handlers?: {
handlers: {
apolloLink?: ApolloLink;
}
},
alokai: AlokaiContainer
) => {
const baseLink =
handlers?.apolloLink ||
Expand All @@ -66,10 +69,10 @@ export const apolloLinkFactory = (
...settings.customApolloHttpLinkOptions,
});

const onErrorLink = createErrorHandler();
const onErrorLink = createErrorHandler(alokai);

const errorRetry = new RetryLink({
attempts: handleRetry(),
attempts: handleRetry({ alokai }),
delay: () => 0,
});

Expand Down
16 changes: 9 additions & 7 deletions packages/api-client/src/helpers/magentoLink/index.ts
Original file line number Diff line number Diff line change
@@ -1,14 +1,16 @@
import consola from "consola";
import { type AlokaiContainer } from "@vue-storefront/middleware";
import { Config } from "../../types/setup";
import { apolloLinkFactory } from "./graphQl";
import { linkFactory } from "./linkHandlers";

export const createMagentoConnection = (settings: Config) => {
consola.debug("createMagentoConnection");

const apolloLink = apolloLinkFactory(settings, {
apolloLink: linkFactory({ state: settings.state }),
});
export const createMagentoConnection = (settings: Config, alokai: AlokaiContainer) => {
const apolloLink = apolloLinkFactory(
settings,
{
apolloLink: linkFactory({ state: settings.state, alokai }),
},
alokai
);

return {
apolloLink,
Expand Down
42 changes: 26 additions & 16 deletions packages/api-client/src/helpers/magentoLink/linkHandlers.ts
Original file line number Diff line number Diff line change
@@ -1,38 +1,48 @@
import { setContext } from "@apollo/client/link/context";
import consola from "consola";
import { getLogger, type AlokaiContainer } from "@vue-storefront/middleware";
import { ConfigState } from "../../types/setup";

export const handleRetry = () => (count, operation, error) => {
if (count > 3) {
return false;
}
export const handleRetry =
({ alokai }: { alokai: AlokaiContainer }) =>
(retryCount, operation, error) => {
const logger = getLogger(alokai);

if (retryCount > 3) {
return false;
}

if (error?.result?.message === "invalid_token") {
consola.debug(`Apollo retry-link, the operation (${operation.operationName}) sent with wrong token, creating a new one... (attempt: ${count})`);
return true;
}
if (error?.result?.message === "invalid_token") {
const { operationName } = operation;
logger.error(`Invalid token used for operation ${operationName}, Apollo retry-link will refresh the token and retry`, {
operation,
retryCount,
});
return true;
}

return false;
};
return false;
};

export const linkFactory = ({ state }: { state: ConfigState }) =>
export const linkFactory = ({ state, alokai }: { state: ConfigState; alokai: AlokaiContainer }) =>
setContext((apolloReq, { headers }) => {
consola.debug("Apollo linkFactory", apolloReq.operationName);
const logger = getLogger(alokai);

logger.debug(`Apollo linkFactory ${apolloReq.operationName}`);

const Store: string = state.getStore();
const token: string = state.getCustomerToken();
const currency: string = state.getCurrency();

if (currency) {
consola.debug("Apollo currencyLinkFactory, finished, currency: ", currency);
logger.debug(`Finished executing Apollo currencyLinkFactory.`, { currency });
}

if (Store) {
consola.debug("Apollo storeLinkFactory, finished, storeId: ", Store);
logger.debug(`Finished executing Apollo storeLinkFactory.`, { Store });
}

if (token) {
consola.debug("Apollo authLinkFactory, finished, token: ", token);
logger.debug(`Finished executing Apollo authLinkFactory.`, { token });
}

return {
Expand Down
10 changes: 5 additions & 5 deletions packages/api-client/src/index.server.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/* istanbul ignore file */
import { ApiClientExtension, apiClientFactory } from "@vue-storefront/middleware";
import { type AlokaiContainer, ApiClientExtension, apiClientFactory } from "@vue-storefront/middleware";
import * as api from "./api";
import { defaultSettings } from "./helpers/apiClient/defaultSettings";
import { createMagentoConnection } from "./helpers/magentoLink";
Expand All @@ -13,7 +13,7 @@ const buildConfig = (settings: Config) =>
state: settings.state || defaultSettings.state,
} as unknown as Config);

const init = (settings: Config) => {
const init = (settings: Config, alokai: AlokaiContainer) => {
const config = buildConfig(settings);

if (settings.client) {
Expand All @@ -30,7 +30,7 @@ const init = (settings: Config) => {
};
}

const { apolloLink } = createMagentoConnection(config);
const { apolloLink } = createMagentoConnection(config, alokai);

const client = apolloClientFactory({
link: apolloLink,
Expand All @@ -52,9 +52,9 @@ const init = (settings: Config) => {
};
};

const onCreate = (settings: Config): { config: Config; client: ClientInstance } => {
const onCreate = (settings: Config, alokai: AlokaiContainer): { config: Config; client: ClientInstance } => {
if (!settings?.client) {
return init(settings);
return init(settings, alokai);
}

const config = buildConfig(settings);
Expand Down
Loading
Loading