@decocms/apps 0.20.1
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.
- package/.github/workflows/release.yml +34 -0
- package/.releaserc.json +25 -0
- package/commerce/components/Image.tsx +209 -0
- package/commerce/components/JsonLd.tsx +285 -0
- package/commerce/sdk/analytics.ts +24 -0
- package/commerce/sdk/formatPrice.ts +23 -0
- package/commerce/sdk/url.ts +9 -0
- package/commerce/sdk/useOffer.ts +75 -0
- package/commerce/sdk/useVariantPossibilities.ts +43 -0
- package/commerce/types/commerce.ts +1105 -0
- package/commerce/utils/canonical.ts +11 -0
- package/commerce/utils/constants.ts +9 -0
- package/commerce/utils/filters.ts +10 -0
- package/commerce/utils/productToAnalyticsItem.ts +67 -0
- package/commerce/utils/stateByZip.ts +50 -0
- package/knip.json +19 -0
- package/package.json +77 -0
- package/shopify/actions/cart/addItems.ts +37 -0
- package/shopify/actions/cart/updateCoupons.ts +32 -0
- package/shopify/actions/cart/updateItems.ts +32 -0
- package/shopify/actions/user/signIn.ts +45 -0
- package/shopify/actions/user/signUp.ts +36 -0
- package/shopify/client.ts +58 -0
- package/shopify/index.ts +32 -0
- package/shopify/init.ts +40 -0
- package/shopify/loaders/ProductDetailsPage.ts +35 -0
- package/shopify/loaders/ProductList.ts +101 -0
- package/shopify/loaders/ProductListingPage.ts +180 -0
- package/shopify/loaders/RelatedProducts.ts +45 -0
- package/shopify/loaders/cart.ts +73 -0
- package/shopify/loaders/shop.ts +40 -0
- package/shopify/loaders/user.ts +44 -0
- package/shopify/utils/admin/admin.ts +57 -0
- package/shopify/utils/admin/queries.ts +29 -0
- package/shopify/utils/cart.ts +28 -0
- package/shopify/utils/cookies.ts +85 -0
- package/shopify/utils/enums.ts +438 -0
- package/shopify/utils/graphql.ts +69 -0
- package/shopify/utils/storefront/queries.ts +530 -0
- package/shopify/utils/storefront/storefront.graphql.gen.ts +113 -0
- package/shopify/utils/transform.ts +436 -0
- package/shopify/utils/types.ts +191 -0
- package/shopify/utils/user.ts +23 -0
- package/shopify/utils/utils.ts +164 -0
- package/tsconfig.json +11 -0
- package/vtex/README.md +6 -0
- package/vtex/actions/address.ts +211 -0
- package/vtex/actions/auth.ts +337 -0
- package/vtex/actions/checkout.ts +497 -0
- package/vtex/actions/index.ts +11 -0
- package/vtex/actions/masterData.ts +170 -0
- package/vtex/actions/misc.ts +196 -0
- package/vtex/actions/newsletter.ts +108 -0
- package/vtex/actions/orders.ts +37 -0
- package/vtex/actions/profile.ts +119 -0
- package/vtex/actions/session.ts +87 -0
- package/vtex/actions/trigger.ts +43 -0
- package/vtex/actions/wishlist.ts +116 -0
- package/vtex/client.ts +423 -0
- package/vtex/hooks/index.ts +4 -0
- package/vtex/hooks/useAutocomplete.ts +89 -0
- package/vtex/hooks/useCart.ts +219 -0
- package/vtex/hooks/useUser.ts +78 -0
- package/vtex/hooks/useWishlist.ts +119 -0
- package/vtex/index.ts +14 -0
- package/vtex/inline-loaders/productDetailsPage.ts +75 -0
- package/vtex/inline-loaders/productList.ts +163 -0
- package/vtex/inline-loaders/productListingPage.ts +447 -0
- package/vtex/inline-loaders/relatedProducts.ts +83 -0
- package/vtex/inline-loaders/suggestions.ts +49 -0
- package/vtex/inline-loaders/workflowProducts.ts +68 -0
- package/vtex/invoke.ts +202 -0
- package/vtex/loaders/address.ts +120 -0
- package/vtex/loaders/brands.ts +51 -0
- package/vtex/loaders/cart.ts +49 -0
- package/vtex/loaders/catalog.ts +165 -0
- package/vtex/loaders/collections.ts +57 -0
- package/vtex/loaders/index.ts +19 -0
- package/vtex/loaders/legacy.ts +671 -0
- package/vtex/loaders/logistics.ts +115 -0
- package/vtex/loaders/navbar.ts +29 -0
- package/vtex/loaders/orders.ts +103 -0
- package/vtex/loaders/pageType.ts +62 -0
- package/vtex/loaders/payment.ts +107 -0
- package/vtex/loaders/profile.ts +138 -0
- package/vtex/loaders/promotion.ts +33 -0
- package/vtex/loaders/search.ts +127 -0
- package/vtex/loaders/session.ts +91 -0
- package/vtex/loaders/user.ts +89 -0
- package/vtex/loaders/wishlist.ts +89 -0
- package/vtex/loaders/wishlistProducts.ts +81 -0
- package/vtex/loaders/workflow.ts +323 -0
- package/vtex/logo.png +0 -0
- package/vtex/middleware.ts +229 -0
- package/vtex/types.ts +248 -0
- package/vtex/utils/batch.ts +21 -0
- package/vtex/utils/cookies.ts +76 -0
- package/vtex/utils/enrichment.ts +540 -0
- package/vtex/utils/fetchCache.ts +150 -0
- package/vtex/utils/index.ts +17 -0
- package/vtex/utils/intelligentSearch.ts +84 -0
- package/vtex/utils/legacy.ts +155 -0
- package/vtex/utils/pickAndOmit.ts +30 -0
- package/vtex/utils/proxy.ts +196 -0
- package/vtex/utils/resourceRange.ts +10 -0
- package/vtex/utils/segment.ts +163 -0
- package/vtex/utils/similars.ts +38 -0
- package/vtex/utils/sitemap.ts +133 -0
- package/vtex/utils/slugCache.ts +32 -0
- package/vtex/utils/slugify.ts +13 -0
- package/vtex/utils/transform.ts +1331 -0
- package/vtex/utils/types.ts +1884 -0
- package/vtex/utils/vtexId.ts +103 -0
|
@@ -0,0 +1,115 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* VTEX Logistics & Sales-Channel API loaders.
|
|
3
|
+
* Pure async functions — require configureVtex() to have been called.
|
|
4
|
+
*
|
|
5
|
+
* Ported from deco-cx/apps:
|
|
6
|
+
* vtex/loaders/logistics/getSalesChannelById.ts
|
|
7
|
+
* vtex/loaders/logistics/listPickupPoints.ts
|
|
8
|
+
* vtex/loaders/logistics/listPickupPointsByLocation.ts
|
|
9
|
+
* vtex/loaders/logistics/listSalesChannelById.ts (actually lists all)
|
|
10
|
+
* vtex/loaders/logistics/listStockByStore.ts
|
|
11
|
+
*
|
|
12
|
+
* @see https://developers.vtex.com/docs/api-reference/logistics-api
|
|
13
|
+
*/
|
|
14
|
+
import { vtexFetch } from "../client";
|
|
15
|
+
|
|
16
|
+
// ---------------------------------------------------------------------------
|
|
17
|
+
// Types
|
|
18
|
+
// ---------------------------------------------------------------------------
|
|
19
|
+
|
|
20
|
+
export interface ProductBalance {
|
|
21
|
+
warehouseId: string;
|
|
22
|
+
warehouseName: string;
|
|
23
|
+
totalQuantity: number;
|
|
24
|
+
reservedQuantity: number;
|
|
25
|
+
hasUnlimitedQuantity: boolean;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
export interface PickupPointsByLocationOpts {
|
|
29
|
+
geoCoordinates?: number[];
|
|
30
|
+
postalCode?: string;
|
|
31
|
+
countryCode?: string;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
export interface PickupPointsResponse<T = any> {
|
|
35
|
+
paging: { page: number; pageSize: number; total: number; pages: number };
|
|
36
|
+
items: Array<{ distance: number; pickupPoint: T }>;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
// ---------------------------------------------------------------------------
|
|
40
|
+
// Sales Channels
|
|
41
|
+
// ---------------------------------------------------------------------------
|
|
42
|
+
|
|
43
|
+
/**
|
|
44
|
+
* Get a single sales channel by ID (public API).
|
|
45
|
+
* @see https://developers.vtex.com/docs/api-reference/catalog-api#get-/api/catalog_system/pub/saleschannel/-salesChannelId-
|
|
46
|
+
*/
|
|
47
|
+
export async function getSalesChannelById<T = any>(id: string): Promise<T> {
|
|
48
|
+
return vtexFetch<T>(`/api/catalog_system/pub/saleschannel/${id}`);
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
/**
|
|
52
|
+
* List all sales channels (private API — requires appKey/appToken).
|
|
53
|
+
* @see https://developers.vtex.com/docs/api-reference/catalog-api#get-/api/catalog_system/pvt/saleschannel/list
|
|
54
|
+
*/
|
|
55
|
+
export async function listSalesChannels<T = any>(): Promise<T[]> {
|
|
56
|
+
return vtexFetch<T[]>("/api/catalog_system/pvt/saleschannel/list");
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
// ---------------------------------------------------------------------------
|
|
60
|
+
// Pickup Points
|
|
61
|
+
// ---------------------------------------------------------------------------
|
|
62
|
+
|
|
63
|
+
/**
|
|
64
|
+
* List all configured pickup points (private API — requires appKey/appToken).
|
|
65
|
+
* @see https://developers.vtex.com/docs/api-reference/logistics-api#get-/api/logistics/pvt/configuration/pickuppoints
|
|
66
|
+
*/
|
|
67
|
+
export async function listPickupPoints<T = any>(): Promise<T[]> {
|
|
68
|
+
return vtexFetch<T[]>("/api/logistics/pvt/configuration/pickuppoints");
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
/**
|
|
72
|
+
* Search pickup points near a geographic location (public API).
|
|
73
|
+
* Pass either `geoCoordinates` (lon/lat array) **or** `postalCode` + `countryCode`.
|
|
74
|
+
*
|
|
75
|
+
* @see https://developers.vtex.com/docs/api-reference/checkout-api#get-/api/checkout/pub/pickup-points
|
|
76
|
+
*/
|
|
77
|
+
export async function listPickupPointsByLocation<T = any>(
|
|
78
|
+
opts: PickupPointsByLocationOpts,
|
|
79
|
+
): Promise<PickupPointsResponse<T>> {
|
|
80
|
+
const params = new URLSearchParams();
|
|
81
|
+
if (opts.geoCoordinates) {
|
|
82
|
+
params.set("geoCoordinates", opts.geoCoordinates.join(","));
|
|
83
|
+
} else {
|
|
84
|
+
if (opts.postalCode) params.set("postalCode", opts.postalCode);
|
|
85
|
+
if (opts.countryCode) params.set("countryCode", opts.countryCode);
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
return vtexFetch<PickupPointsResponse<T>>(
|
|
89
|
+
`/api/checkout/pub/pickup-points?${params}`,
|
|
90
|
+
);
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
// ---------------------------------------------------------------------------
|
|
94
|
+
// Stock / Inventory
|
|
95
|
+
// ---------------------------------------------------------------------------
|
|
96
|
+
|
|
97
|
+
/**
|
|
98
|
+
* List inventory balances for a SKU across all warehouses.
|
|
99
|
+
* @see https://developers.vtex.com/docs/api-reference/logistics-api#get-/api/logistics/pvt/inventory/skus/-skuId-
|
|
100
|
+
*/
|
|
101
|
+
export async function listStockByStore(
|
|
102
|
+
skuId: number,
|
|
103
|
+
): Promise<ProductBalance[]> {
|
|
104
|
+
try {
|
|
105
|
+
const result = await vtexFetch<{
|
|
106
|
+
skuId?: string;
|
|
107
|
+
balance?: ProductBalance[];
|
|
108
|
+
}>(`/api/logistics/pvt/inventory/skus/${skuId}`);
|
|
109
|
+
|
|
110
|
+
return result.balance ?? [];
|
|
111
|
+
} catch (error) {
|
|
112
|
+
console.error("[listStockByStore]", error);
|
|
113
|
+
return [];
|
|
114
|
+
}
|
|
115
|
+
}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* VTEX Navbar (category tree) loader.
|
|
3
|
+
* Pure async function — requires configureVtex() to have been called.
|
|
4
|
+
*
|
|
5
|
+
* Ported from deco-cx/apps:
|
|
6
|
+
* vtex/loaders/navbar.ts
|
|
7
|
+
*
|
|
8
|
+
* @see https://developers.vtex.com/docs/api-reference/catalog-api#get-/api/catalog_system/pub/category/tree/-categoryLevels-
|
|
9
|
+
*/
|
|
10
|
+
import { vtexFetch } from "../client";
|
|
11
|
+
import { categoryTreeToNavbar } from "../utils/transform";
|
|
12
|
+
import type { Category } from "../utils/types";
|
|
13
|
+
import type { SiteNavigationElement } from "../../commerce/types/commerce";
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* Fetch the category tree and transform it into an array of
|
|
17
|
+
* `SiteNavigationElement` nodes suitable for navigation menus.
|
|
18
|
+
*
|
|
19
|
+
* @param levels - Depth of the category tree (default: 2)
|
|
20
|
+
*/
|
|
21
|
+
export async function getNavbar(
|
|
22
|
+
levels: number = 2,
|
|
23
|
+
): Promise<SiteNavigationElement[]> {
|
|
24
|
+
const tree = await vtexFetch<Category[]>(
|
|
25
|
+
`/api/catalog_system/pub/category/tree/${levels}`,
|
|
26
|
+
);
|
|
27
|
+
|
|
28
|
+
return categoryTreeToNavbar(tree);
|
|
29
|
+
}
|
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* VTEX Orders API loaders.
|
|
3
|
+
* Pure async functions — require configureVtex() to have been called.
|
|
4
|
+
*
|
|
5
|
+
* Ported from deco-cx/apps:
|
|
6
|
+
* vtex/loaders/orders/getById.ts
|
|
7
|
+
* vtex/loaders/orders/list.ts
|
|
8
|
+
*
|
|
9
|
+
* @see https://developers.vtex.com/docs/api-reference/orders-api
|
|
10
|
+
*/
|
|
11
|
+
import { vtexFetch } from "../client";
|
|
12
|
+
|
|
13
|
+
// ---------------------------------------------------------------------------
|
|
14
|
+
// getOrderById (authenticated — REST)
|
|
15
|
+
// ---------------------------------------------------------------------------
|
|
16
|
+
|
|
17
|
+
/**
|
|
18
|
+
* Fetch a single user order by its ID.
|
|
19
|
+
* The user must be authenticated or the caller must have OMS permissions.
|
|
20
|
+
*
|
|
21
|
+
* @see https://developers.vtex.com/docs/api-reference/orders-api#get-/api/oms/user/orders/-orderId-
|
|
22
|
+
*/
|
|
23
|
+
export async function getOrderById<T = any>(
|
|
24
|
+
orderId: string,
|
|
25
|
+
authCookie: string,
|
|
26
|
+
): Promise<T> {
|
|
27
|
+
return vtexFetch<T>(`/api/oms/user/orders/${orderId}`, {
|
|
28
|
+
headers: { cookie: authCookie },
|
|
29
|
+
});
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
// ---------------------------------------------------------------------------
|
|
33
|
+
// listOrders (authenticated — REST)
|
|
34
|
+
// ---------------------------------------------------------------------------
|
|
35
|
+
|
|
36
|
+
export interface ListOrdersOpts {
|
|
37
|
+
clientEmail: string;
|
|
38
|
+
page?: string;
|
|
39
|
+
perPage?: string;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
/**
|
|
43
|
+
* List orders for a given client e-mail.
|
|
44
|
+
* The user must be authenticated or the caller must have OMS permissions.
|
|
45
|
+
*
|
|
46
|
+
* @see https://developers.vtex.com/docs/api-reference/orders-api#get-/api/oms/user/orders
|
|
47
|
+
*/
|
|
48
|
+
export async function listOrders<T = any>(
|
|
49
|
+
opts: ListOrdersOpts,
|
|
50
|
+
authCookie: string,
|
|
51
|
+
): Promise<T> {
|
|
52
|
+
const { clientEmail, page = "0", perPage = "15" } = opts;
|
|
53
|
+
const params = new URLSearchParams({
|
|
54
|
+
clientEmail,
|
|
55
|
+
page,
|
|
56
|
+
per_page: perPage,
|
|
57
|
+
});
|
|
58
|
+
|
|
59
|
+
return vtexFetch<T>(`/api/oms/user/orders?${params}`, {
|
|
60
|
+
headers: { cookie: authCookie },
|
|
61
|
+
});
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
// ---------------------------------------------------------------------------
|
|
65
|
+
// getOrderPlaced (order confirmation — Checkout API)
|
|
66
|
+
// ---------------------------------------------------------------------------
|
|
67
|
+
|
|
68
|
+
/**
|
|
69
|
+
* Fetch order details for the order-placed / confirmation page.
|
|
70
|
+
*
|
|
71
|
+
* Accepts either:
|
|
72
|
+
* - An **order group ID** (no hyphen) → returns all orders in the group
|
|
73
|
+
* - A single **order ID** (contains hyphen) → returns that order wrapped in an array
|
|
74
|
+
*
|
|
75
|
+
* The caller must supply an `authCookie` containing at least the
|
|
76
|
+
* VtexIdclientAutCookie, CheckoutDataAccess, and Vtex_CHKO_Auth cookies
|
|
77
|
+
* that VTEX sets after checkout.
|
|
78
|
+
*
|
|
79
|
+
* Ported from deco-cx/apps:
|
|
80
|
+
* vtex/loaders/orderplaced.ts
|
|
81
|
+
*
|
|
82
|
+
* @see https://developers.vtex.com/docs/api-reference/checkout-api#get-/api/checkout/pub/orders/order-group/-orderGroupId-
|
|
83
|
+
*/
|
|
84
|
+
export async function getOrderPlaced<T = any>(
|
|
85
|
+
orderId: string,
|
|
86
|
+
authCookie: string,
|
|
87
|
+
): Promise<T[]> {
|
|
88
|
+
const isOrderGroup = !orderId.includes("-");
|
|
89
|
+
|
|
90
|
+
if (isOrderGroup) {
|
|
91
|
+
return vtexFetch<T[]>(
|
|
92
|
+
`/api/checkout/pub/orders/order-group/${orderId}`,
|
|
93
|
+
{ headers: { cookie: authCookie } },
|
|
94
|
+
);
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
const order = await vtexFetch<T>(
|
|
98
|
+
`/api/checkout/pub/orders/${orderId}`,
|
|
99
|
+
{ headers: { cookie: authCookie } },
|
|
100
|
+
);
|
|
101
|
+
|
|
102
|
+
return [order];
|
|
103
|
+
}
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* VTEX page type resolver.
|
|
3
|
+
*
|
|
4
|
+
* Given a URL path, determines if it corresponds to a product, category,
|
|
5
|
+
* brand, department, collection, search, or 404 in VTEX's catalog.
|
|
6
|
+
*
|
|
7
|
+
* @see https://developers.vtex.com/docs/api-reference/catalog-api#get-/api/catalog_system/pub/portal/pagetype/-path-
|
|
8
|
+
*/
|
|
9
|
+
import { vtexFetch, type PageType } from "../client";
|
|
10
|
+
|
|
11
|
+
export type { PageType };
|
|
12
|
+
|
|
13
|
+
export type VtexPageKind =
|
|
14
|
+
| "product"
|
|
15
|
+
| "category"
|
|
16
|
+
| "department"
|
|
17
|
+
| "subcategory"
|
|
18
|
+
| "brand"
|
|
19
|
+
| "collection"
|
|
20
|
+
| "search"
|
|
21
|
+
| "fulltext"
|
|
22
|
+
| "notfound";
|
|
23
|
+
|
|
24
|
+
/**
|
|
25
|
+
* Resolve a URL path to a VTEX page type.
|
|
26
|
+
*
|
|
27
|
+
* @param urlPath - The path to resolve (e.g., "/shoes/running")
|
|
28
|
+
* @returns The page type with kind normalization, or null on error
|
|
29
|
+
*/
|
|
30
|
+
export async function resolvePageType(
|
|
31
|
+
urlPath: string,
|
|
32
|
+
): Promise<{ pageType: PageType; kind: VtexPageKind } | null> {
|
|
33
|
+
const cleanPath = urlPath.replace(/^\//, "").replace(/\/$/, "");
|
|
34
|
+
if (!cleanPath) return null;
|
|
35
|
+
|
|
36
|
+
try {
|
|
37
|
+
const pt = await vtexFetch<PageType>(
|
|
38
|
+
`/api/catalog_system/pub/portal/pagetype/${cleanPath}`,
|
|
39
|
+
);
|
|
40
|
+
|
|
41
|
+
const kind = normalizeKind(pt.pageType);
|
|
42
|
+
return { pageType: pt, kind };
|
|
43
|
+
} catch {
|
|
44
|
+
return null;
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
function normalizeKind(pageType: PageType["pageType"]): VtexPageKind {
|
|
49
|
+
switch (pageType) {
|
|
50
|
+
case "Product": return "product";
|
|
51
|
+
case "Category": return "category";
|
|
52
|
+
case "Department": return "department";
|
|
53
|
+
case "SubCategory": return "subcategory";
|
|
54
|
+
case "Brand": return "brand";
|
|
55
|
+
case "Collection":
|
|
56
|
+
case "Cluster": return "collection";
|
|
57
|
+
case "Search": return "search";
|
|
58
|
+
case "FullText": return "fulltext";
|
|
59
|
+
case "NotFound":
|
|
60
|
+
default: return "notfound";
|
|
61
|
+
}
|
|
62
|
+
}
|
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* VTEX Payment API loaders.
|
|
3
|
+
* Pure async functions — require configureVtex() to have been called.
|
|
4
|
+
*
|
|
5
|
+
* Ported from deco-cx/apps:
|
|
6
|
+
* vtex/loaders/payment/paymentSystems.ts
|
|
7
|
+
* vtex/loaders/payment/userPayments.ts
|
|
8
|
+
*/
|
|
9
|
+
import { vtexIOGraphQL } from "../client";
|
|
10
|
+
|
|
11
|
+
// ---------------------------------------------------------------------------
|
|
12
|
+
// Types
|
|
13
|
+
// ---------------------------------------------------------------------------
|
|
14
|
+
|
|
15
|
+
export interface PaymentSystem {
|
|
16
|
+
name: string;
|
|
17
|
+
groupName: string;
|
|
18
|
+
requiresDocument: boolean;
|
|
19
|
+
displayDocument: boolean;
|
|
20
|
+
validator: {
|
|
21
|
+
regex: string | null;
|
|
22
|
+
mask: string | null;
|
|
23
|
+
cardCodeMask: string | null;
|
|
24
|
+
cardCodeRegex: string | null;
|
|
25
|
+
};
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
export interface Payment {
|
|
29
|
+
accountStatus: string | null;
|
|
30
|
+
cardNumber: string;
|
|
31
|
+
expirationDate: string;
|
|
32
|
+
id: string;
|
|
33
|
+
isExpired: boolean;
|
|
34
|
+
paymentSystem: string;
|
|
35
|
+
paymentSystemName: string;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
// ---------------------------------------------------------------------------
|
|
39
|
+
// getPaymentSystems (authenticated — VTEX IO GraphQL)
|
|
40
|
+
// ---------------------------------------------------------------------------
|
|
41
|
+
|
|
42
|
+
const PAYMENT_SYSTEMS_QUERY = `query getPaymentSystems {
|
|
43
|
+
paymentSystems {
|
|
44
|
+
name
|
|
45
|
+
groupName
|
|
46
|
+
requiresDocument
|
|
47
|
+
displayDocument
|
|
48
|
+
validator {
|
|
49
|
+
regex
|
|
50
|
+
mask
|
|
51
|
+
cardCodeMask
|
|
52
|
+
cardCodeRegex
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
}`;
|
|
56
|
+
|
|
57
|
+
/**
|
|
58
|
+
* List available payment systems for the authenticated user.
|
|
59
|
+
* Requires a valid VTEX auth cookie.
|
|
60
|
+
*/
|
|
61
|
+
export async function getPaymentSystems(
|
|
62
|
+
authCookie: string,
|
|
63
|
+
): Promise<PaymentSystem[]> {
|
|
64
|
+
const { paymentSystems } = await vtexIOGraphQL<{
|
|
65
|
+
paymentSystems: PaymentSystem[];
|
|
66
|
+
}>(
|
|
67
|
+
{ query: PAYMENT_SYSTEMS_QUERY },
|
|
68
|
+
{ cookie: authCookie },
|
|
69
|
+
);
|
|
70
|
+
|
|
71
|
+
return paymentSystems;
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
// ---------------------------------------------------------------------------
|
|
75
|
+
// getUserPayments (authenticated — VTEX IO GraphQL)
|
|
76
|
+
// ---------------------------------------------------------------------------
|
|
77
|
+
|
|
78
|
+
const USER_PAYMENTS_QUERY = `query getUserPayments {
|
|
79
|
+
profile {
|
|
80
|
+
payments {
|
|
81
|
+
accountStatus
|
|
82
|
+
cardNumber
|
|
83
|
+
expirationDate
|
|
84
|
+
id
|
|
85
|
+
isExpired
|
|
86
|
+
paymentSystem
|
|
87
|
+
paymentSystemName
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
}`;
|
|
91
|
+
|
|
92
|
+
/**
|
|
93
|
+
* List saved payment methods for the authenticated user.
|
|
94
|
+
* Requires a valid VTEX auth cookie.
|
|
95
|
+
*/
|
|
96
|
+
export async function getUserPayments(
|
|
97
|
+
authCookie: string,
|
|
98
|
+
): Promise<Payment[]> {
|
|
99
|
+
const data = await vtexIOGraphQL<{
|
|
100
|
+
profile: { payments: Payment[] } | null;
|
|
101
|
+
}>(
|
|
102
|
+
{ query: USER_PAYMENTS_QUERY },
|
|
103
|
+
{ cookie: authCookie },
|
|
104
|
+
);
|
|
105
|
+
|
|
106
|
+
return data.profile?.payments ?? [];
|
|
107
|
+
}
|
|
@@ -0,0 +1,138 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* VTEX Profile API loaders.
|
|
3
|
+
* Pure async functions — require configureVtex() to have been called.
|
|
4
|
+
*
|
|
5
|
+
* Ported from deco-cx/apps:
|
|
6
|
+
* vtex/loaders/profile/getCurrentProfile.ts
|
|
7
|
+
* vtex/loaders/profile/getProfileByEmail.ts
|
|
8
|
+
*
|
|
9
|
+
* @see https://developers.vtex.com/docs/api-reference/checkout-api
|
|
10
|
+
*/
|
|
11
|
+
import { vtexFetch, vtexIOGraphQL } from "../client";
|
|
12
|
+
|
|
13
|
+
// ---------------------------------------------------------------------------
|
|
14
|
+
// Types
|
|
15
|
+
// ---------------------------------------------------------------------------
|
|
16
|
+
|
|
17
|
+
const ADDRESS_FIELDS = `
|
|
18
|
+
addressType
|
|
19
|
+
receiverName
|
|
20
|
+
addressId
|
|
21
|
+
postalCode
|
|
22
|
+
city
|
|
23
|
+
state
|
|
24
|
+
country
|
|
25
|
+
street
|
|
26
|
+
number
|
|
27
|
+
neighborhood
|
|
28
|
+
complement
|
|
29
|
+
reference
|
|
30
|
+
geoCoordinates
|
|
31
|
+
`;
|
|
32
|
+
|
|
33
|
+
export interface Profile {
|
|
34
|
+
id: string;
|
|
35
|
+
cacheId: string;
|
|
36
|
+
email: string;
|
|
37
|
+
firstName: string;
|
|
38
|
+
lastName: string;
|
|
39
|
+
document: string;
|
|
40
|
+
userId: string;
|
|
41
|
+
birthDate: string;
|
|
42
|
+
gender: string;
|
|
43
|
+
homePhone: string;
|
|
44
|
+
businessPhone: string;
|
|
45
|
+
addresses: Record<string, unknown>[];
|
|
46
|
+
isCorporate: boolean;
|
|
47
|
+
tradeName: string;
|
|
48
|
+
corporateName: string;
|
|
49
|
+
corporateDocument: string;
|
|
50
|
+
stateRegistration: string;
|
|
51
|
+
payments: Record<string, unknown>[];
|
|
52
|
+
customFields: Array<{ key: string; value: string }>;
|
|
53
|
+
passwordLastUpdate: string;
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
// ---------------------------------------------------------------------------
|
|
57
|
+
// getCurrentProfile (authenticated — VTEX IO GraphQL)
|
|
58
|
+
// ---------------------------------------------------------------------------
|
|
59
|
+
|
|
60
|
+
const PROFILE_QUERY = `query getUserProfile($customFields: String) {
|
|
61
|
+
profile(customFields: $customFields) {
|
|
62
|
+
id
|
|
63
|
+
cacheId
|
|
64
|
+
email
|
|
65
|
+
firstName
|
|
66
|
+
lastName
|
|
67
|
+
document
|
|
68
|
+
userId
|
|
69
|
+
birthDate
|
|
70
|
+
gender
|
|
71
|
+
homePhone
|
|
72
|
+
businessPhone
|
|
73
|
+
addresses { ${ADDRESS_FIELDS} }
|
|
74
|
+
isCorporate
|
|
75
|
+
tradeName
|
|
76
|
+
corporateName
|
|
77
|
+
corporateDocument
|
|
78
|
+
stateRegistration
|
|
79
|
+
payments {
|
|
80
|
+
cacheId
|
|
81
|
+
id
|
|
82
|
+
paymentSystem
|
|
83
|
+
paymentSystemName
|
|
84
|
+
cardNumber
|
|
85
|
+
address { ${ADDRESS_FIELDS} }
|
|
86
|
+
isExpired
|
|
87
|
+
expirationDate
|
|
88
|
+
accountStatus
|
|
89
|
+
}
|
|
90
|
+
customFields {
|
|
91
|
+
key
|
|
92
|
+
value
|
|
93
|
+
}
|
|
94
|
+
passwordLastUpdate
|
|
95
|
+
}
|
|
96
|
+
}`;
|
|
97
|
+
|
|
98
|
+
/**
|
|
99
|
+
* Fetch the full profile for the currently authenticated user.
|
|
100
|
+
* Requires a valid VTEX auth cookie.
|
|
101
|
+
*/
|
|
102
|
+
export async function getCurrentProfile(
|
|
103
|
+
authCookie: string,
|
|
104
|
+
customFields?: string[],
|
|
105
|
+
): Promise<Profile> {
|
|
106
|
+
const { profile } = await vtexIOGraphQL<{ profile: Profile }>(
|
|
107
|
+
{
|
|
108
|
+
query: PROFILE_QUERY,
|
|
109
|
+
variables: { customFields: customFields?.join(",") },
|
|
110
|
+
},
|
|
111
|
+
{ cookie: authCookie },
|
|
112
|
+
);
|
|
113
|
+
|
|
114
|
+
return profile;
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
// ---------------------------------------------------------------------------
|
|
118
|
+
// getProfileByEmail (authenticated — REST)
|
|
119
|
+
// ---------------------------------------------------------------------------
|
|
120
|
+
|
|
121
|
+
/**
|
|
122
|
+
* Fetch a checkout profile by e-mail.
|
|
123
|
+
* Requires a valid VTEX auth cookie.
|
|
124
|
+
*
|
|
125
|
+
* @see https://developers.vtex.com/docs/api-reference/checkout-api#get-/api/checkout/pub/profiles
|
|
126
|
+
*/
|
|
127
|
+
export async function getProfileByEmail<T = any>(
|
|
128
|
+
email: string,
|
|
129
|
+
authCookie: string,
|
|
130
|
+
ensureComplete?: boolean,
|
|
131
|
+
): Promise<T> {
|
|
132
|
+
const params = new URLSearchParams({ email });
|
|
133
|
+
if (ensureComplete) params.set("ensureComplete", "true");
|
|
134
|
+
|
|
135
|
+
return vtexFetch<T>(`/api/checkout/pub/profiles?${params}`, {
|
|
136
|
+
headers: { cookie: authCookie },
|
|
137
|
+
});
|
|
138
|
+
}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* VTEX Promotion loader.
|
|
3
|
+
* Pure async function — requires configureVtex() to have been called.
|
|
4
|
+
*
|
|
5
|
+
* Ported from deco-cx/apps:
|
|
6
|
+
* vtex/loaders/getPromotionById.ts
|
|
7
|
+
*
|
|
8
|
+
* @see https://developers.vtex.com/docs/api-reference/promotions-and-taxes-api
|
|
9
|
+
*/
|
|
10
|
+
import { vtexFetch } from "../client";
|
|
11
|
+
import type { Document } from "../utils/types";
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* Fetch a promotion / calculator-configuration by its ID.
|
|
15
|
+
*
|
|
16
|
+
* Note: uses the **pvt** (private) endpoint — requires appKey/appToken
|
|
17
|
+
* or a valid authentication cookie.
|
|
18
|
+
*
|
|
19
|
+
* @param promotionId - The `idCalculatorConfiguration` of the promotion
|
|
20
|
+
* @param authCookie - Optional cookie string for authenticated requests
|
|
21
|
+
*/
|
|
22
|
+
export async function getPromotionById(
|
|
23
|
+
promotionId: string,
|
|
24
|
+
authCookie?: string,
|
|
25
|
+
): Promise<Document[]> {
|
|
26
|
+
const headers: Record<string, string> = {};
|
|
27
|
+
if (authCookie) headers.cookie = authCookie;
|
|
28
|
+
|
|
29
|
+
return vtexFetch<Document[]>(
|
|
30
|
+
`/api/rnb/pvt/calculatorconfiguration/${promotionId}`,
|
|
31
|
+
{ headers },
|
|
32
|
+
);
|
|
33
|
+
}
|