@decocms/apps-wake 8.1.0-next.0 → 8.1.0-next.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (94) hide show
  1. package/dist/index.d.ts +3 -0
  2. package/dist/index.d.ts.map +1 -0
  3. package/dist/index.js +4 -0
  4. package/dist/index.js.map +1 -0
  5. package/dist/storefront.d.ts +14 -0
  6. package/dist/storefront.d.ts.map +1 -0
  7. package/dist/storefront.js +14 -0
  8. package/dist/storefront.js.map +1 -0
  9. package/dist/storefrontTypes.d.ts +7 -0
  10. package/dist/storefrontTypes.d.ts.map +1 -0
  11. package/dist/storefrontTypes.js +2 -0
  12. package/dist/storefrontTypes.js.map +1 -0
  13. package/dist/utils/client.d.ts +12 -0
  14. package/dist/utils/client.d.ts.map +1 -0
  15. package/dist/utils/client.js +2 -0
  16. package/dist/utils/client.js.map +1 -0
  17. package/dist/utils/gql.d.ts +16 -0
  18. package/dist/utils/gql.d.ts.map +1 -0
  19. package/dist/utils/gql.js +16 -0
  20. package/dist/utils/gql.js.map +1 -0
  21. package/dist/utils/graphql/queries.d.ts +117 -0
  22. package/dist/utils/graphql/queries.d.ts.map +1 -0
  23. package/dist/utils/graphql/queries.js +1323 -0
  24. package/dist/utils/graphql/queries.js.map +1 -0
  25. package/dist/utils/graphql/storefront.graphql.gen.d.ts +10344 -0
  26. package/dist/utils/graphql/storefront.graphql.gen.d.ts.map +1 -0
  27. package/dist/utils/graphql/storefront.graphql.gen.js +9 -0
  28. package/dist/utils/graphql/storefront.graphql.gen.js.map +1 -0
  29. package/dist/utils/graphqlOperationName.d.ts +36 -0
  30. package/dist/utils/graphqlOperationName.d.ts.map +1 -0
  31. package/dist/utils/graphqlOperationName.js +59 -0
  32. package/dist/utils/graphqlOperationName.js.map +1 -0
  33. package/dist/wakeClient.d.ts +54 -0
  34. package/dist/wakeClient.d.ts.map +1 -0
  35. package/dist/wakeClient.js +85 -0
  36. package/dist/wakeClient.js.map +1 -0
  37. package/package.json +26 -37
  38. package/src/index.ts +3 -63
  39. package/src/storefront.ts +1 -1
  40. package/src/storefrontTypes.ts +1 -1
  41. package/src/utils/gql.ts +1 -2
  42. package/src/utils/graphql/queries.ts +1 -1
  43. package/src/wakeClient.ts +3 -3
  44. package/src/__tests__/wakeClient.test.ts +0 -136
  45. package/src/actions/cart/addCoupon.ts +0 -43
  46. package/src/actions/cart/addItem.ts +0 -10
  47. package/src/actions/cart/addItems.ts +0 -50
  48. package/src/actions/cart/addKit.ts +0 -53
  49. package/src/actions/cart/partnerAssociate.ts +0 -48
  50. package/src/actions/cart/partnerDisassociate.ts +0 -43
  51. package/src/actions/cart/removeCoupon.ts +0 -39
  52. package/src/actions/cart/removeKit.ts +0 -56
  53. package/src/actions/cart/updateItemQuantity.ts +0 -69
  54. package/src/actions/newsletter/register.ts +0 -32
  55. package/src/actions/notifyme.ts +0 -28
  56. package/src/actions/review/create.ts +0 -30
  57. package/src/actions/shippingSimulation.ts +0 -60
  58. package/src/actions/submmitForm.ts +0 -25
  59. package/src/actions/wishlist/addProduct.ts +0 -43
  60. package/src/actions/wishlist/removeProduct.ts +0 -45
  61. package/src/client.ts +0 -123
  62. package/src/commerceLoaders.ts +0 -137
  63. package/src/handlers/sitemap.ts +0 -61
  64. package/src/loaders/cart.ts +0 -46
  65. package/src/loaders/partners.ts +0 -58
  66. package/src/loaders/productDetailsPage.ts +0 -174
  67. package/src/loaders/productList.ts +0 -262
  68. package/src/loaders/productListingPage.ts +0 -333
  69. package/src/loaders/proxy.ts +0 -79
  70. package/src/loaders/recommendations.ts +0 -84
  71. package/src/loaders/shop.ts +0 -37
  72. package/src/loaders/suggestion.ts +0 -67
  73. package/src/loaders/user.ts +0 -48
  74. package/src/loaders/wishlist.ts +0 -40
  75. package/src/manifest.gen.ts +0 -69
  76. package/src/mod.ts +0 -88
  77. package/src/registry.ts +0 -9
  78. package/src/utils/authError.ts +0 -107
  79. package/src/utils/authenticate.ts +0 -42
  80. package/src/utils/capitalize.ts +0 -9
  81. package/src/utils/cart.ts +0 -33
  82. package/src/utils/cookies.ts +0 -82
  83. package/src/utils/getVariations.ts +0 -47
  84. package/src/utils/graphql.ts +0 -72
  85. package/src/utils/httpError.ts +0 -15
  86. package/src/utils/instrumentedFetch.ts +0 -46
  87. package/src/utils/operationRouter.ts +0 -51
  88. package/src/utils/parseHeaders.ts +0 -19
  89. package/src/utils/partner.ts +0 -34
  90. package/src/utils/requestCtx.ts +0 -41
  91. package/src/utils/transform.ts +0 -460
  92. package/src/utils/types.ts +0 -6
  93. package/src/utils/user.ts +0 -9
  94. package/tsconfig.json +0 -7
@@ -1,84 +0,0 @@
1
- import type { Product } from "@decocms/apps-commerce/types";
2
- import { getWakeClient } from "../client";
3
- import { handleAuthError } from "../utils/authError";
4
- import { getVariations } from "../utils/getVariations";
5
- import { ProductRecommendations } from "../utils/graphql/queries";
6
- import type {
7
- ProductFragment,
8
- ProductRecommendationsQuery,
9
- } from "../utils/graphql/storefront.graphql.gen";
10
- import { getPartnerCookie } from "../utils/partner";
11
- import { currentRequestHeaders, currentUrl, forwardedHeaders } from "../utils/requestCtx";
12
- import { parseSlug, toProduct } from "../utils/transform";
13
- import type { RequestURLParam } from "../utils/types";
14
-
15
- export interface Props {
16
- /**
17
- * @default DEFAULT
18
- * @description Algorithm type
19
- */
20
- algorithm: "DEFAULT";
21
- quantity: number;
22
- slug: RequestURLParam;
23
- /** @description Retrieve variantions for each product. */
24
- getVariations?: boolean;
25
- }
26
-
27
- /**
28
- * @title Wake Integration - Product Recommendations
29
- * @description Product Recommendations loader
30
- */
31
- const productRecommendationsLoader = async (props: Props): Promise<Product[] | null> => {
32
- const url = currentUrl();
33
- const storefront = getWakeClient();
34
- const { slug, quantity, algorithm = "DEFAULT" } = props;
35
- const partnerAccessToken = getPartnerCookie(currentRequestHeaders());
36
-
37
- const headers = forwardedHeaders();
38
-
39
- const { id: productId } = parseSlug(slug);
40
-
41
- let data: ProductRecommendationsQuery | undefined;
42
- try {
43
- data = await storefront.query<ProductRecommendationsQuery>(
44
- ProductRecommendations,
45
- { quantity, productId, algorithm, partnerAccessToken },
46
- headers,
47
- );
48
- } catch (error: unknown) {
49
- handleAuthError(error, "load product recommendations");
50
- }
51
-
52
- const products = data?.productRecommendations;
53
-
54
- if (!Array.isArray(products)) {
55
- return null;
56
- }
57
-
58
- const productIDs = products.map((i) => i?.productId).filter((id): id is number => id != null);
59
-
60
- const variations = props.getVariations ? await getVariations(productIDs, url, headers) : [];
61
-
62
- return products
63
- ?.filter((p): p is ProductFragment => Boolean(p))
64
- .map((variant) => {
65
- const productVariations = variations?.filter(
66
- (v) => v.inProductGroupWithID === variant.productId,
67
- );
68
-
69
- return toProduct(variant, { base: url }, productVariations);
70
- });
71
- };
72
-
73
- export const cache = "stale-while-revalidate";
74
-
75
- export const cacheKey = (props: Props): string | null => {
76
- // Avoid cross-tenant cache bleed when a partner token is present
77
- if (getPartnerCookie(currentRequestHeaders())) {
78
- return null;
79
- }
80
-
81
- return `wake:recommendations:${props.slug}:${props.quantity}:${props.algorithm}:${props.getVariations ?? false}`;
82
- };
83
-
84
- export default productRecommendationsLoader;
@@ -1,37 +0,0 @@
1
- import { getWakeClient } from "../client";
2
- import { handleAuthError } from "../utils/authError";
3
- import { Shop } from "../utils/graphql/queries";
4
- import type { ShopQuery } from "../utils/graphql/storefront.graphql.gen";
5
- import { getPartnerCookie } from "../utils/partner";
6
- import { currentRequestHeaders, forwardedHeaders } from "../utils/requestCtx";
7
-
8
- /**
9
- * @title Wake Integration - Shop Infos
10
- * @description Shop Infos loader
11
- */
12
- const shopInfos = async (): Promise<ShopQuery["shop"] | undefined> => {
13
- const storefront = getWakeClient();
14
- const headers = forwardedHeaders();
15
-
16
- let data: ShopQuery;
17
- try {
18
- data = await storefront.query<ShopQuery>(Shop, {}, headers);
19
- } catch (error: unknown) {
20
- handleAuthError(error, "load shop information");
21
- }
22
-
23
- return data?.shop ?? undefined;
24
- };
25
-
26
- export const cache = "stale-while-revalidate";
27
-
28
- export const cacheKey = (): string | null => {
29
- // Avoid cross-tenant cache bleed when a partner token is present
30
- if (getPartnerCookie(currentRequestHeaders())) {
31
- return null;
32
- }
33
-
34
- return "wake:shop";
35
- };
36
-
37
- export default shopInfos;
@@ -1,67 +0,0 @@
1
- import type { Suggestion } from "@decocms/apps-commerce/types";
2
- import { getWakeClient } from "../client";
3
- import { handleAuthError } from "../utils/authError";
4
- import { Autocomplete } from "../utils/graphql/queries";
5
- import type { AutocompleteQuery, ProductFragment } from "../utils/graphql/storefront.graphql.gen";
6
- import { getPartnerCookie } from "../utils/partner";
7
- import { currentRequestHeaders, currentUrl, forwardedHeaders } from "../utils/requestCtx";
8
- import { toProduct } from "../utils/transform";
9
-
10
- export interface Props {
11
- query: string;
12
- limit?: number;
13
- }
14
-
15
- /**
16
- * @title Wake Integration
17
- * @description Product Suggestion loader
18
- */
19
- const loader = async (props: Props): Promise<Suggestion | null> => {
20
- const storefront = getWakeClient();
21
- const { query, limit = 10 } = props;
22
-
23
- const partnerAccessToken = getPartnerCookie(currentRequestHeaders());
24
- const headers = forwardedHeaders();
25
- const url = currentUrl();
26
-
27
- if (!query) return null;
28
-
29
- let data: AutocompleteQuery | undefined;
30
- try {
31
- data = await storefront.query<AutocompleteQuery>(
32
- Autocomplete,
33
- { query, limit, partnerAccessToken },
34
- headers,
35
- );
36
- } catch (error: unknown) {
37
- handleAuthError(error, "load product suggestions");
38
- }
39
-
40
- const { products: wakeProducts, suggestions = [] } = data?.autocomplete ?? {};
41
-
42
- if (!wakeProducts?.length && !suggestions?.length) return null;
43
-
44
- const products = wakeProducts
45
- ?.filter((node): node is ProductFragment => Boolean(node))
46
- .map((node) => toProduct(node, { base: url }));
47
-
48
- return {
49
- products: products,
50
- searches: suggestions?.filter(Boolean)?.map((suggestion) => ({
51
- term: suggestion!,
52
- })),
53
- };
54
- };
55
-
56
- export const cache = "no-cache";
57
-
58
- export const cacheKey = (props: Props): string | null => {
59
- // Avoid cross-tenant cache bleed when a partner token is present
60
- if (getPartnerCookie(currentRequestHeaders())) {
61
- return null;
62
- }
63
-
64
- return `wake:suggestion:${props.query}:${props.limit ?? 10}`;
65
- };
66
-
67
- export default loader;
@@ -1,48 +0,0 @@
1
- import type { Person } from "@decocms/apps-commerce/types";
2
- import { getWakeClient } from "../client";
3
- import { handleAuthError } from "../utils/authError";
4
- import authenticate from "../utils/authenticate";
5
- import { GetUser } from "../utils/graphql/queries";
6
- import type { GetUserQuery } from "../utils/graphql/storefront.graphql.gen";
7
- import { forwardedHeaders } from "../utils/requestCtx";
8
-
9
- /**
10
- * @title Wake Integration
11
- * @description User loader
12
- */
13
- const userLoader = async (): Promise<Person | null> => {
14
- const storefront = getWakeClient();
15
- const headers = forwardedHeaders();
16
-
17
- const customerAccessToken = await authenticate();
18
-
19
- if (!customerAccessToken) return null;
20
-
21
- let data: GetUserQuery | undefined;
22
- try {
23
- data = await storefront.query<GetUserQuery>(GetUser, { customerAccessToken }, headers);
24
- } catch (error: unknown) {
25
- handleAuthError(error, "load user data");
26
- }
27
-
28
- const customer = data?.customer;
29
-
30
- if (!customer) return null;
31
-
32
- return {
33
- "@id": String(customer.id ?? customer.customerId),
34
- email: customer.email ?? undefined,
35
- givenName: customer.customerName ?? undefined,
36
- gender:
37
- customer.gender === "Masculino"
38
- ? "https://schema.org/Male"
39
- : customer.gender === "Feminino"
40
- ? "https://schema.org/Female"
41
- : undefined,
42
- };
43
- };
44
-
45
- export default userLoader;
46
-
47
- // User-specific response; must not be cached/shared.
48
- export const cache = "no-store";
@@ -1,40 +0,0 @@
1
- import { getWakeClient } from "../client";
2
- import { handleAuthError } from "../utils/authError";
3
- import authenticate from "../utils/authenticate";
4
- import { GetWishlist } from "../utils/graphql/queries";
5
- import type {
6
- GetWishlistQuery,
7
- WishlistReducedProductFragment,
8
- } from "../utils/graphql/storefront.graphql.gen";
9
- import { forwardedHeaders } from "../utils/requestCtx";
10
-
11
- /**
12
- * @title Wake Integration
13
- * @description Product Wishlist loader
14
- */
15
- const loader = async (): Promise<WishlistReducedProductFragment[]> => {
16
- const storefront = getWakeClient();
17
- const headers = forwardedHeaders();
18
-
19
- const customerAccessToken = await authenticate();
20
-
21
- if (!customerAccessToken) return [];
22
-
23
- let data: GetWishlistQuery | undefined;
24
- try {
25
- data = await storefront.query<GetWishlistQuery>(GetWishlist, { customerAccessToken }, headers);
26
- } catch (error: unknown) {
27
- handleAuthError(error, "load wishlist");
28
- }
29
-
30
- return (
31
- data?.customer?.wishlist?.products?.filter((p): p is WishlistReducedProductFragment =>
32
- Boolean(p),
33
- ) ?? []
34
- );
35
- };
36
-
37
- export default loader;
38
-
39
- // User-specific wishlist data; must not be cached/shared.
40
- export const cache = "no-store";
@@ -1,69 +0,0 @@
1
- // AUTO-GENERATED-STYLE manifest — mirrors scripts/generate-manifests.ts output.
2
- // Lists every loader/action module keyed by its CMS resolve path.
3
-
4
- import * as actions_cart_addCoupon from "./actions/cart/addCoupon";
5
- import * as actions_cart_addItem from "./actions/cart/addItem";
6
- import * as actions_cart_addItems from "./actions/cart/addItems";
7
- import * as actions_cart_addKit from "./actions/cart/addKit";
8
- import * as actions_cart_partnerAssociate from "./actions/cart/partnerAssociate";
9
- import * as actions_cart_partnerDisassociate from "./actions/cart/partnerDisassociate";
10
- import * as actions_cart_removeCoupon from "./actions/cart/removeCoupon";
11
- import * as actions_cart_removeKit from "./actions/cart/removeKit";
12
- import * as actions_cart_updateItemQuantity from "./actions/cart/updateItemQuantity";
13
- import * as actions_newsletter_register from "./actions/newsletter/register";
14
- import * as actions_notifyme from "./actions/notifyme";
15
- import * as actions_review_create from "./actions/review/create";
16
- import * as actions_shippingSimulation from "./actions/shippingSimulation";
17
- import * as actions_submmitForm from "./actions/submmitForm";
18
- import * as actions_wishlist_addProduct from "./actions/wishlist/addProduct";
19
- import * as actions_wishlist_removeProduct from "./actions/wishlist/removeProduct";
20
- import * as loaders_cart from "./loaders/cart";
21
- import * as loaders_partners from "./loaders/partners";
22
- import * as loaders_productDetailsPage from "./loaders/productDetailsPage";
23
- import * as loaders_productList from "./loaders/productList";
24
- import * as loaders_productListingPage from "./loaders/productListingPage";
25
- import * as loaders_proxy from "./loaders/proxy";
26
- import * as loaders_recommendations from "./loaders/recommendations";
27
- import * as loaders_shop from "./loaders/shop";
28
- import * as loaders_suggestion from "./loaders/suggestion";
29
- import * as loaders_user from "./loaders/user";
30
- import * as loaders_wishlist from "./loaders/wishlist";
31
-
32
- const manifest = {
33
- name: "wake",
34
- loaders: {
35
- "wake/loaders/cart": loaders_cart,
36
- "wake/loaders/partners": loaders_partners,
37
- "wake/loaders/productDetailsPage": loaders_productDetailsPage,
38
- "wake/loaders/productList": loaders_productList,
39
- "wake/loaders/productListingPage": loaders_productListingPage,
40
- "wake/loaders/proxy": loaders_proxy,
41
- "wake/loaders/recommendations": loaders_recommendations,
42
- "wake/loaders/shop": loaders_shop,
43
- "wake/loaders/suggestion": loaders_suggestion,
44
- "wake/loaders/user": loaders_user,
45
- "wake/loaders/wishlist": loaders_wishlist,
46
- },
47
- actions: {
48
- "wake/actions/cart/addCoupon": actions_cart_addCoupon,
49
- "wake/actions/cart/addItem": actions_cart_addItem,
50
- "wake/actions/cart/addItems": actions_cart_addItems,
51
- "wake/actions/cart/addKit": actions_cart_addKit,
52
- "wake/actions/cart/partnerAssociate": actions_cart_partnerAssociate,
53
- "wake/actions/cart/partnerDisassociate": actions_cart_partnerDisassociate,
54
- "wake/actions/cart/removeCoupon": actions_cart_removeCoupon,
55
- "wake/actions/cart/removeKit": actions_cart_removeKit,
56
- "wake/actions/cart/updateItemQuantity": actions_cart_updateItemQuantity,
57
- "wake/actions/newsletter/register": actions_newsletter_register,
58
- "wake/actions/notifyme": actions_notifyme,
59
- "wake/actions/review/create": actions_review_create,
60
- "wake/actions/shippingSimulation": actions_shippingSimulation,
61
- "wake/actions/submmitForm": actions_submmitForm,
62
- "wake/actions/wishlist/addProduct": actions_wishlist_addProduct,
63
- "wake/actions/wishlist/removeProduct": actions_wishlist_removeProduct,
64
- },
65
- sections: {},
66
- } as const;
67
-
68
- export type Manifest = typeof manifest;
69
- export default manifest;
package/src/mod.ts DELETED
@@ -1,88 +0,0 @@
1
- /**
2
- * Wake app module — standard autoconfig contract.
3
- *
4
- * Exports `configure` following the AppModContract pattern; the framework's
5
- * `autoconfigApps()` calls it generically. Ported from the deco-cx/apps Deno
6
- * Wake integration.
7
- */
8
-
9
- import type { AppDefinition, AppHandler, ResolveSecretFn } from "@decocms/apps-commerce/app-types";
10
- import {
11
- configureWake,
12
- getWakeAdminTokenFromEnv,
13
- getWakeStorefrontTokenFromEnv,
14
- type WakeConfig,
15
- } from "./client";
16
- import Sitemap from "./handlers/sitemap";
17
- import manifest from "./manifest.gen";
18
-
19
- /** @title Wake */
20
- export interface Props {
21
- /**
22
- * @title Account Name
23
- * @description erploja2 etc
24
- */
25
- account: string;
26
- /**
27
- * @title Checkout Url
28
- * @description https://secure.sprint55.com.br — checkout/login domain
29
- */
30
- checkoutUrl: string;
31
- /**
32
- * @description Use Wake as backend platform
33
- * @hide true
34
- */
35
- platform?: "wake";
36
- }
37
-
38
- export interface WakeState {
39
- config: WakeConfig;
40
- }
41
-
42
- /**
43
- * Configure the Wake app from CMS block data.
44
- *
45
- * The Wake tokens are NOT stored in the CMS block — they come only from
46
- * environment variables (`WAKE_TOKEN` storefront, `WAKE_KEY` admin), so
47
- * `resolveSecret` is intentionally unused. Returns null if the account or the
48
- * storefront token env var is missing.
49
- */
50
- export async function configure(
51
- block: Record<string, unknown> | null | undefined,
52
- _resolveSecret: ResolveSecretFn,
53
- ): Promise<AppDefinition<WakeState> | null> {
54
- if (!block?.account) return null;
55
-
56
- const storefrontToken = getWakeStorefrontTokenFromEnv();
57
- if (!storefrontToken) return null;
58
-
59
- const config: WakeConfig = {
60
- account: block.account as string,
61
- checkoutUrl: (block.checkoutUrl as string) ?? "",
62
- storefrontToken,
63
- storefrontEndpoint: block.storefrontEndpoint as string | undefined,
64
- token: getWakeAdminTokenFromEnv(),
65
- };
66
-
67
- // Bridge: maintain global singleton for backward compat
68
- configureWake(config);
69
-
70
- return {
71
- name: "wake",
72
- manifest,
73
- state: { config },
74
- };
75
- }
76
-
77
- /** HTTP handlers exposed by the app (not part of the loader/action manifest). */
78
- export const handlers: Record<string, AppHandler> = {
79
- "wake/handlers/sitemap": (props, request) => Sitemap(props)(request),
80
- };
81
-
82
- /** Placeholder preview for CMS editor — evolves when admin supports it. */
83
- export const preview = undefined;
84
-
85
- /** Default export for schema generation and Deno-style app bridges. */
86
- export default function Wake(props: Props) {
87
- return { state: props };
88
- }
package/src/registry.ts DELETED
@@ -1,9 +0,0 @@
1
- import type { AppRegistryEntry } from "@decocms/apps-commerce/registry";
2
-
3
- export const WAKE_REGISTRY_ENTRY: AppRegistryEntry = {
4
- blockKey: "deco-wake",
5
- module: () => import("./mod"),
6
- displayName: "Wake",
7
- category: "commerce",
8
- description: "Wake Commerce (Storefront API) integration",
9
- };
@@ -1,107 +0,0 @@
1
- /**
2
- * Best-effort dev detection without the deco runtime `context`.
3
- * Treats anything other than an explicit production NODE_ENV as dev.
4
- */
5
- const isDevEnv = (): boolean => {
6
- const env = (globalThis as { process?: { env?: Record<string, string | undefined> } }).process
7
- ?.env;
8
- return (env?.NODE_ENV ?? "development") !== "production";
9
- };
10
-
11
- /**
12
- * Checks if an error is an authentication error and throws a user-friendly error
13
- * with development guidance if in development mode.
14
- */
15
- export function handleAuthError(error: unknown, operationContext: string = "operation"): never {
16
- const errorObj = error as {
17
- message?: string;
18
- extensions?: { code?: string };
19
- };
20
-
21
- if (
22
- errorObj?.message?.includes("AUTH_NOT_AUTHENTICATED") ||
23
- errorObj?.extensions?.code === "AUTH_NOT_AUTHENTICATED" ||
24
- errorObj?.message?.includes("unauthorized")
25
- ) {
26
- if (isDevEnv()) {
27
- console.error(`
28
- 🔐 Wake API Authentication Error 🔐
29
-
30
- Failed to ${operationContext} due to missing or invalid Wake API tokens.
31
-
32
- This error occurs when:
33
- - Wake Storefront Token is missing or invalid
34
- - Wake API Token is missing or invalid
35
- - Tokens are configured but expired
36
-
37
- To fix (Development):
38
- 1. Create a .env file in your project root
39
- 2. Add these environment variables:
40
- WAKE_TOKEN=your_storefront_token_here
41
- WAKE_KEY=your_api_token_here
42
-
43
- To fix (Production):
44
- 1. Go to deco.cx admin
45
- 2. Find the Wake app configuration
46
- 3. Set up secrets for Storefront Token and API Token
47
-
48
- For help: https://wakecommerce.readme.io/docs/storefront-api-criacao-e-autenticacao-do-token
49
- `);
50
- }
51
-
52
- // Throw a more user-friendly error for the frontend
53
- const authError = new Error(
54
- `Authentication failed (while trying to ${operationContext}) — Wake API tokens are missing or invalid`,
55
- );
56
- authError.cause = error;
57
- throw authError;
58
- }
59
-
60
- // Re-throw if not an auth error
61
- throw error;
62
- }
63
-
64
- /**
65
- * Checks if an error is an authentication error without throwing.
66
- */
67
- export function isAuthError(error: unknown): boolean {
68
- const errorObj = error as {
69
- message?: string;
70
- extensions?: { code?: string };
71
- status?: number;
72
- response?: { status?: number };
73
- errors?: Array<{ message?: string; extensions?: { code?: string } }>;
74
- };
75
-
76
- // Normalize text for case-insensitive comparison
77
- const msg = (errorObj?.message ?? "").toLowerCase();
78
- const code = (errorObj?.extensions?.code ?? "").toUpperCase();
79
-
80
- // Check HTTP status codes
81
- const httpStatus = errorObj?.status ?? errorObj?.response?.status;
82
-
83
- // Check for aggregate errors (multiple errors in an array)
84
- const isAggregate =
85
- Array.isArray(errorObj?.errors) &&
86
- errorObj.errors.some(
87
- (e) =>
88
- String(e?.message ?? "")
89
- .toLowerCase()
90
- .includes("unauthorized") ||
91
- String(e?.extensions?.code ?? "").toUpperCase() === "UNAUTHENTICATED" ||
92
- String(e?.extensions?.code ?? "").toUpperCase() === "AUTH_NOT_AUTHENTICATED" ||
93
- String(e?.extensions?.code ?? "").toUpperCase() === "FORBIDDEN",
94
- );
95
-
96
- return !!(
97
- msg.includes("auth_not_authenticated") ||
98
- msg.includes("unauthorized") ||
99
- msg.includes("forbidden") ||
100
- code === "AUTH_NOT_AUTHENTICATED" ||
101
- code === "UNAUTHENTICATED" ||
102
- code === "FORBIDDEN" ||
103
- httpStatus === 401 ||
104
- httpStatus === 403 ||
105
- isAggregate
106
- );
107
- }
@@ -1,42 +0,0 @@
1
- import { withFetchTimeout } from "@decocms/blocks/sdk/fetchTimeout";
2
- import { RequestContext } from "@decocms/blocks/sdk/requestContext";
3
- import { getCheckoutUrl } from "../client";
4
- import type { UserAuthenticate } from "./client";
5
- import { getUserCookie } from "./user";
6
-
7
- const fetchSafe = withFetchTimeout();
8
-
9
- /**
10
- * Exchange the `fbits-login` cookie for a Wake `CustomerAccessToken` via the
11
- * checkout REST endpoint `GET /api/Login/Get`, forwarding the incoming request
12
- * headers (cookies) so Wake can resolve the logged-in customer.
13
- *
14
- * Returns `null` when there is no login cookie or the exchange fails.
15
- */
16
- const authenticate = async (): Promise<string | null> => {
17
- const req = RequestContext.current?.request;
18
- if (!req) return null;
19
-
20
- const loginCookie = getUserCookie(req.headers);
21
- if (!loginCookie) return null;
22
-
23
- try {
24
- // Forward only the Cookie header (carries `fbits-login`) rather than the
25
- // whole incoming header set — the checkout endpoint only needs the session
26
- // cookie to resolve the customer.
27
- const forwardHeaders = new Headers();
28
- const cookie = req.headers.get("cookie");
29
- if (cookie) forwardHeaders.set("cookie", cookie);
30
-
31
- const response = await fetchSafe(new URL("/api/Login/Get", getCheckoutUrl()).href, {
32
- headers: forwardHeaders,
33
- });
34
- if (!response.ok) return null;
35
- const data = (await response.json()) as UserAuthenticate | null;
36
- return data?.CustomerAccessToken ?? null;
37
- } catch {
38
- return null;
39
- }
40
- };
41
-
42
- export default authenticate;
@@ -1,9 +0,0 @@
1
- export const capitalize = (str: string) => {
2
- const arr = str.split(" ");
3
-
4
- for (let i = 0; i < arr.length; i++) {
5
- arr[i] = arr[i].charAt(0).toUpperCase() + arr[i].slice(1);
6
- }
7
-
8
- return arr.join(" ");
9
- };
package/src/utils/cart.ts DELETED
@@ -1,33 +0,0 @@
1
- import { getCookies, setCookie } from "./cookies";
2
- import { isSecureRequest } from "./requestCtx";
3
-
4
- const CART_COOKIE = "carrinho-id";
5
-
6
- const TEN_DAYS_MS = 10 * 24 * 3600 * 1_000;
7
-
8
- export const getCartCookie = (headers: Headers): string | undefined => {
9
- const cookies = getCookies(headers);
10
-
11
- return cookies[CART_COOKIE];
12
- };
13
-
14
- export const setCartCookie = (headers: Headers, cartId: string) =>
15
- setCookie(headers, {
16
- name: CART_COOKIE,
17
- value: cartId,
18
- path: "/",
19
- expires: new Date(Date.now() + TEN_DAYS_MS),
20
- // Not HttpOnly: the client mirrors this cookie via `setClientCookie`.
21
- // Secure only on HTTPS — a Secure cookie is dropped over http:// (localhost dev).
22
- secure: isSecureRequest(),
23
- sameSite: "Lax",
24
- });
25
-
26
- /** Browser-only: mirror the cart id into a client-readable cookie. */
27
- export const setClientCookie = (value: string) => {
28
- const date = new Date(Date.now() + TEN_DAYS_MS);
29
- const expires = `; expires=${date.toUTCString()}`;
30
-
31
- // biome-ignore lint/suspicious/noDocumentCookie: browser-only mirror of the cart id for client reads
32
- document.cookie = `${CART_COOKIE}=${value || ""}${expires}; path=/`;
33
- };