@decocms/apps-vtex 8.1.0-next.0 → 8.1.0-next.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/package.json +7 -52
- package/src/index.ts +10 -28
- package/src/utils/constants.ts +2 -56
- package/src/utils/cookieSanitizer.ts +59 -59
- package/src/utils/operationRouter.ts +75 -65
- package/src/utils/types.ts +709 -1557
- package/src/vtexClient.ts +354 -343
- package/src/README.md +0 -6
- package/src/__conformance__/upstream.test.ts +0 -158
- package/src/__tests__/client-segment-cookie.test.ts +0 -255
- package/src/__tests__/client-set-cookie-forward.test.ts +0 -257
- package/src/__tests__/schemas.test.ts +0 -71
- package/src/actions/address.ts +0 -250
- package/src/actions/analytics/sendEvent.ts +0 -86
- package/src/actions/auth.ts +0 -333
- package/src/actions/checkout.ts +0 -659
- package/src/actions/index.ts +0 -11
- package/src/actions/masterData.ts +0 -168
- package/src/actions/misc.ts +0 -188
- package/src/actions/newsletter.ts +0 -105
- package/src/actions/orders.ts +0 -34
- package/src/actions/profile.ts +0 -201
- package/src/actions/session.ts +0 -85
- package/src/actions/trigger.ts +0 -43
- package/src/actions/wishlist.ts +0 -114
- package/src/client.ts +0 -724
- package/src/commerceLoaders.ts +0 -267
- package/src/hooks/__tests__/createCart.render.test.ts +0 -114
- package/src/hooks/__tests__/createCart.test.ts +0 -92
- package/src/hooks/__tests__/createUseCart.test.ts +0 -184
- package/src/hooks/__tests__/createUseUser.test.ts +0 -48
- package/src/hooks/__tests__/createUseWishlist.test.ts +0 -87
- package/src/hooks/cartQuery.ts +0 -204
- package/src/hooks/createCart.ts +0 -427
- package/src/hooks/createUseCart.ts +0 -360
- package/src/hooks/createUseUser.ts +0 -153
- package/src/hooks/createUseWishlist.ts +0 -242
- package/src/hooks/index.ts +0 -25
- package/src/hooks/useAutocomplete.ts +0 -83
- package/src/hooks/useCart.ts +0 -243
- package/src/hooks/useUser.ts +0 -78
- package/src/hooks/useWishlist.ts +0 -119
- package/src/invoke.ts +0 -235
- package/src/loaders/ProductDetailsPage.ts +0 -1
- package/src/loaders/ProductList.ts +0 -1
- package/src/loaders/ProductListingPage.ts +0 -1
- package/src/loaders/__tests__/legacyProductList.test.ts +0 -157
- package/src/loaders/address.ts +0 -115
- package/src/loaders/autocomplete.ts +0 -56
- package/src/loaders/brands.ts +0 -44
- package/src/loaders/cart/attachments.ts +0 -53
- package/src/loaders/cart/full.ts +0 -67
- package/src/loaders/cart/gifts.ts +0 -43
- package/src/loaders/cart/orderFormId.ts +0 -31
- package/src/loaders/cart/shipping.test.ts +0 -125
- package/src/loaders/cart/shipping.ts +0 -136
- package/src/loaders/cart/summary.ts +0 -36
- package/src/loaders/cart.ts +0 -52
- package/src/loaders/catalog.ts +0 -163
- package/src/loaders/collections.ts +0 -55
- package/src/loaders/index.ts +0 -20
- package/src/loaders/intelligentSearch/__tests__/productListingPage.test.ts +0 -51
- package/src/loaders/intelligentSearch/productDetailsPage.ts +0 -111
- package/src/loaders/intelligentSearch/productList.ts +0 -170
- package/src/loaders/intelligentSearch/productListingPage.ts +0 -525
- package/src/loaders/intelligentSearch/suggestions.ts +0 -44
- package/src/loaders/legacy/productDetailsPage.ts +0 -1
- package/src/loaders/legacy/productList.ts +0 -1
- package/src/loaders/legacy/relatedProductsLoader.ts +0 -79
- package/src/loaders/legacy.ts +0 -710
- package/src/loaders/logistics.ts +0 -111
- package/src/loaders/minicart.ts +0 -78
- package/src/loaders/navbar.ts +0 -26
- package/src/loaders/orders.ts +0 -92
- package/src/loaders/pageType.ts +0 -68
- package/src/loaders/paths/PDPDefaultPath.ts +0 -51
- package/src/loaders/payment.ts +0 -97
- package/src/loaders/productListFull.ts +0 -157
- package/src/loaders/profile.ts +0 -138
- package/src/loaders/promotion.ts +0 -30
- package/src/loaders/search.ts +0 -124
- package/src/loaders/session.ts +0 -83
- package/src/loaders/user.ts +0 -87
- package/src/loaders/wishlist.ts +0 -89
- package/src/loaders/wishlistProducts.ts +0 -69
- package/src/loaders/workflow/products.ts +0 -62
- package/src/loaders/workflow.ts +0 -316
- package/src/logo.png +0 -0
- package/src/manifest.gen.ts +0 -89
- package/src/middleware.cacheHeaders.test.ts +0 -44
- package/src/middleware.ts +0 -240
- package/src/mod.ts +0 -173
- package/src/registry.ts +0 -9
- package/src/schemas.gen.ts +0 -3191
- package/src/schemas.ts +0 -30
- package/src/types.ts +0 -248
- package/src/utils/__tests__/cartProjection.test.ts +0 -118
- package/src/utils/__tests__/cookieSanitizer.test.ts +0 -162
- package/src/utils/__tests__/fetch.test.ts +0 -80
- package/src/utils/__tests__/fetchCache.test.ts +0 -155
- package/src/utils/__tests__/instrumentedFetch.test.ts +0 -158
- package/src/utils/__tests__/intelligentSearch.test.ts +0 -88
- package/src/utils/__tests__/minicart.test.ts +0 -184
- package/src/utils/__tests__/operationRouter.test.ts +0 -227
- package/src/utils/__tests__/resilience.test.ts +0 -205
- package/src/utils/__tests__/resourceRange.test.ts +0 -32
- package/src/utils/__tests__/simulationCache.test.ts +0 -40
- package/src/utils/__tests__/sitemap.test.ts +0 -185
- package/src/utils/__tests__/slugify.test.ts +0 -31
- package/src/utils/__tests__/storefrontBaseUrl.test.ts +0 -61
- package/src/utils/__tests__/transform.test.ts +0 -1111
- package/src/utils/accountLoaders.ts +0 -203
- package/src/utils/authHelpers.ts +0 -85
- package/src/utils/batch.ts +0 -18
- package/src/utils/buildOfferShelf.test.ts +0 -59
- package/src/utils/cartProjection.ts +0 -96
- package/src/utils/cookies.ts +0 -167
- package/src/utils/enrichment.ts +0 -556
- package/src/utils/fetch.ts +0 -111
- package/src/utils/fetchCache.ts +0 -55
- package/src/utils/index.ts +0 -19
- package/src/utils/instrumentedFetch.ts +0 -98
- package/src/utils/intelligentSearch.ts +0 -96
- package/src/utils/legacy.ts +0 -139
- package/src/utils/minicart.ts +0 -139
- package/src/utils/pickAndOmit.ts +0 -25
- package/src/utils/proxy.ts +0 -495
- package/src/utils/resilience.ts +0 -352
- package/src/utils/resourceRange.ts +0 -10
- package/src/utils/segment.ts +0 -152
- package/src/utils/similars.ts +0 -35
- package/src/utils/simulationCache.ts +0 -73
- package/src/utils/sitemap.ts +0 -283
- package/src/utils/slugCache.ts +0 -28
- package/src/utils/slugify.ts +0 -13
- package/src/utils/transform.ts +0 -1691
- package/src/utils/vtexId.ts +0 -151
- package/src/vtexClient.test.ts +0 -204
- package/tsconfig.json +0 -7
|
@@ -1,71 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* End-to-end guard for the acceptance criteria of "real props schemas in
|
|
3
|
-
* /deco/meta": after a site wires VTEX the standard way
|
|
4
|
-
* (createVtexCommerceLoaders → registerCommerceLoaders), the composed meta
|
|
5
|
-
* must publish the real props of the app's loaders/actions — enums included —
|
|
6
|
-
* not the `__resolveType`-only stubs.
|
|
7
|
-
*/
|
|
8
|
-
|
|
9
|
-
import { registerCommerceLoaders } from "@decocms/blocks/cms";
|
|
10
|
-
import { composeMeta, type MetaResponse } from "@decocms/blocks/cms/client";
|
|
11
|
-
import { describe, expect, it } from "vitest";
|
|
12
|
-
import { createVtexCommerceLoaders } from "../commerceLoaders";
|
|
13
|
-
import { registerVtexSchemas } from "../schemas";
|
|
14
|
-
|
|
15
|
-
const b64 = (s: string) => Buffer.from(s).toString("base64");
|
|
16
|
-
|
|
17
|
-
const emptySiteMeta = (): MetaResponse => ({
|
|
18
|
-
major: 1,
|
|
19
|
-
version: "1.0.0",
|
|
20
|
-
namespace: "site",
|
|
21
|
-
site: "test",
|
|
22
|
-
manifest: { blocks: {} },
|
|
23
|
-
schema: { definitions: {}, root: {} },
|
|
24
|
-
});
|
|
25
|
-
|
|
26
|
-
describe("vtex schemas in the composed meta", () => {
|
|
27
|
-
// Mirrors a real site setup: build the loader map (this also registers the
|
|
28
|
-
// real schemas), then register it (which auto-registers the stubs).
|
|
29
|
-
registerCommerceLoaders(createVtexCommerceLoaders());
|
|
30
|
-
registerVtexSchemas();
|
|
31
|
-
const meta = composeMeta(emptySiteMeta());
|
|
32
|
-
const def = (key: string) => meta.schema.definitions[b64(key)];
|
|
33
|
-
|
|
34
|
-
it("publishes real props for the intelligent-search PDP loader (both key forms)", () => {
|
|
35
|
-
for (const key of [
|
|
36
|
-
"vtex/loaders/intelligentSearch/productDetailsPage.ts",
|
|
37
|
-
"vtex/loaders/intelligentSearch/productDetailsPage",
|
|
38
|
-
]) {
|
|
39
|
-
const d = def(key);
|
|
40
|
-
expect(d, key).toBeDefined();
|
|
41
|
-
expect(d.properties.slug, key).toMatchObject({ type: "string" });
|
|
42
|
-
expect(d.properties.__resolveType.enum, key).toEqual([key]);
|
|
43
|
-
expect(d.additionalProperties, key).toBeUndefined();
|
|
44
|
-
}
|
|
45
|
-
});
|
|
46
|
-
|
|
47
|
-
it("publishes the legacy PLP loader with its sort enum preserved", () => {
|
|
48
|
-
const d = def("vtex/loaders/legacy/productListingPage.ts");
|
|
49
|
-
expect(d).toBeDefined();
|
|
50
|
-
expect(d.properties.sort.enum).toContain("OrderByPriceDESC");
|
|
51
|
-
expect(d.properties.sort.enum).toContain("OrderByPriceASC");
|
|
52
|
-
expect(d.properties.count).toMatchObject({ type: "number" });
|
|
53
|
-
expect(d.properties.fq).toMatchObject({ type: "string" });
|
|
54
|
-
});
|
|
55
|
-
|
|
56
|
-
it("publishes real props for a checkout action", () => {
|
|
57
|
-
const d = def("vtex/actions/checkout/addItemsToCart.ts");
|
|
58
|
-
expect(d).toBeDefined();
|
|
59
|
-
expect(d.properties.orderItems).toMatchObject({ type: "array" });
|
|
60
|
-
expect(d.additionalProperties).toBeUndefined();
|
|
61
|
-
});
|
|
62
|
-
|
|
63
|
-
it("keeps the JSON-editor stub shape for keys without a generated schema", () => {
|
|
64
|
-
// Registered by createVtexCommerceLoaders but owned by another namespace —
|
|
65
|
-
// no schemas.gen entry, so the stub (additionalProperties: true) survives.
|
|
66
|
-
const d = def("commerce/loaders/navbar.ts");
|
|
67
|
-
expect(d).toBeDefined();
|
|
68
|
-
expect(d.additionalProperties).toBe(true);
|
|
69
|
-
expect(Object.keys(d.properties)).toEqual(["__resolveType"]);
|
|
70
|
-
});
|
|
71
|
-
});
|
package/src/actions/address.ts
DELETED
|
@@ -1,250 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* VTEX Address management actions (store-graphql).
|
|
3
|
-
* Ported from deco-cx/apps:
|
|
4
|
-
* - vtex/actions/address/create.ts
|
|
5
|
-
* - vtex/actions/address/delete.ts
|
|
6
|
-
* - vtex/actions/address/update.ts
|
|
7
|
-
* @see https://developers.vtex.com/docs/guides/profile-system
|
|
8
|
-
*/
|
|
9
|
-
import { getVtexConfig, vtexFetch } from "../client";
|
|
10
|
-
import { buildAuthCookieHeader } from "../utils/vtexId";
|
|
11
|
-
|
|
12
|
-
// ---------------------------------------------------------------------------
|
|
13
|
-
// Types
|
|
14
|
-
// ---------------------------------------------------------------------------
|
|
15
|
-
|
|
16
|
-
export interface AddressInput {
|
|
17
|
-
addressName: string;
|
|
18
|
-
addressType?: string;
|
|
19
|
-
city?: string;
|
|
20
|
-
complement?: string;
|
|
21
|
-
country?: string;
|
|
22
|
-
geoCoordinates?: number[];
|
|
23
|
-
neighborhood?: string;
|
|
24
|
-
number?: string;
|
|
25
|
-
postalCode?: string;
|
|
26
|
-
receiverName?: string;
|
|
27
|
-
reference?: string;
|
|
28
|
-
state?: string;
|
|
29
|
-
street?: string;
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
export interface SavedAddress {
|
|
33
|
-
id: string;
|
|
34
|
-
cacheId: string;
|
|
35
|
-
addressId: string;
|
|
36
|
-
userId?: string;
|
|
37
|
-
addressName: string;
|
|
38
|
-
addressType: string | null;
|
|
39
|
-
city: string | null;
|
|
40
|
-
complement: string | null;
|
|
41
|
-
country: string | null;
|
|
42
|
-
geoCoordinates: number[] | null;
|
|
43
|
-
neighborhood: string | null;
|
|
44
|
-
number: string | null;
|
|
45
|
-
postalCode: string | null;
|
|
46
|
-
receiverName: string | null;
|
|
47
|
-
reference: string | null;
|
|
48
|
-
state: string | null;
|
|
49
|
-
street: string | null;
|
|
50
|
-
name?: string;
|
|
51
|
-
}
|
|
52
|
-
|
|
53
|
-
export interface DeleteAddressResult {
|
|
54
|
-
cacheId: string;
|
|
55
|
-
addresses: SavedAddress[];
|
|
56
|
-
}
|
|
57
|
-
|
|
58
|
-
export interface UpdateAddressResult {
|
|
59
|
-
cacheId: string;
|
|
60
|
-
addresses: SavedAddress;
|
|
61
|
-
}
|
|
62
|
-
|
|
63
|
-
// ---------------------------------------------------------------------------
|
|
64
|
-
// GraphQL helper (myvtex.com private graphql)
|
|
65
|
-
// ---------------------------------------------------------------------------
|
|
66
|
-
|
|
67
|
-
interface GqlResponse<T> {
|
|
68
|
-
data: T;
|
|
69
|
-
errors?: Array<{ message: string }>;
|
|
70
|
-
}
|
|
71
|
-
|
|
72
|
-
async function gql<T>(
|
|
73
|
-
query: string,
|
|
74
|
-
variables: Record<string, unknown>,
|
|
75
|
-
authCookie: string,
|
|
76
|
-
): Promise<T> {
|
|
77
|
-
const { account } = getVtexConfig();
|
|
78
|
-
const result = await vtexFetch<GqlResponse<T>>(
|
|
79
|
-
`https://${account}.myvtex.com/_v/private/graphql/v1`,
|
|
80
|
-
{
|
|
81
|
-
method: "POST",
|
|
82
|
-
body: JSON.stringify({ query, variables }),
|
|
83
|
-
headers: { Cookie: buildAuthCookieHeader(authCookie, account) },
|
|
84
|
-
},
|
|
85
|
-
);
|
|
86
|
-
if (result.errors?.length) {
|
|
87
|
-
throw new Error(`GraphQL error: ${result.errors[0].message}`);
|
|
88
|
-
}
|
|
89
|
-
return result.data;
|
|
90
|
-
}
|
|
91
|
-
|
|
92
|
-
// ---------------------------------------------------------------------------
|
|
93
|
-
// Mutations
|
|
94
|
-
// ---------------------------------------------------------------------------
|
|
95
|
-
|
|
96
|
-
const SAVE_ADDRESS = `mutation SaveAddress($address: AddressInput!) {
|
|
97
|
-
saveAddress(address: $address) @context(provider: "vtex.store-graphql") {
|
|
98
|
-
addressId
|
|
99
|
-
cacheId
|
|
100
|
-
id
|
|
101
|
-
userId
|
|
102
|
-
receiverName
|
|
103
|
-
complement
|
|
104
|
-
neighborhood
|
|
105
|
-
country
|
|
106
|
-
state
|
|
107
|
-
number
|
|
108
|
-
street
|
|
109
|
-
geoCoordinates
|
|
110
|
-
postalCode
|
|
111
|
-
city
|
|
112
|
-
name
|
|
113
|
-
addressName
|
|
114
|
-
addressType
|
|
115
|
-
}
|
|
116
|
-
}`;
|
|
117
|
-
|
|
118
|
-
const DELETE_ADDRESS = `mutation DeleteAddress($addressId: String) {
|
|
119
|
-
deleteAddress(id: $addressId) {
|
|
120
|
-
cacheId
|
|
121
|
-
addresses {
|
|
122
|
-
addressId: id
|
|
123
|
-
addressType
|
|
124
|
-
addressName
|
|
125
|
-
city
|
|
126
|
-
complement
|
|
127
|
-
country
|
|
128
|
-
neighborhood
|
|
129
|
-
number
|
|
130
|
-
postalCode
|
|
131
|
-
geoCoordinates
|
|
132
|
-
receiverName
|
|
133
|
-
reference
|
|
134
|
-
state
|
|
135
|
-
street
|
|
136
|
-
}
|
|
137
|
-
}
|
|
138
|
-
}`;
|
|
139
|
-
|
|
140
|
-
const UPDATE_ADDRESS = `mutation UpdateAddress($addressId: String!, $addressFields: AddressInput) {
|
|
141
|
-
updateAddress(id: $addressId, fields: $addressFields) @context(provider: "vtex.store-graphql") {
|
|
142
|
-
cacheId
|
|
143
|
-
addresses: address {
|
|
144
|
-
addressId: id
|
|
145
|
-
addressType
|
|
146
|
-
addressName
|
|
147
|
-
city
|
|
148
|
-
complement
|
|
149
|
-
country
|
|
150
|
-
neighborhood
|
|
151
|
-
number
|
|
152
|
-
postalCode
|
|
153
|
-
geoCoordinates
|
|
154
|
-
receiverName
|
|
155
|
-
reference
|
|
156
|
-
state
|
|
157
|
-
street
|
|
158
|
-
}
|
|
159
|
-
}
|
|
160
|
-
}`;
|
|
161
|
-
|
|
162
|
-
// ---------------------------------------------------------------------------
|
|
163
|
-
// Actions
|
|
164
|
-
// ---------------------------------------------------------------------------
|
|
165
|
-
|
|
166
|
-
/** Create a new user address. Requires the user's VtexIdclientAutCookie token. */
|
|
167
|
-
export async function createAddress(
|
|
168
|
-
input: AddressInput,
|
|
169
|
-
authCookie: string,
|
|
170
|
-
): Promise<SavedAddress> {
|
|
171
|
-
const { saveAddress } = await gql<{ saveAddress: SavedAddress }>(
|
|
172
|
-
SAVE_ADDRESS,
|
|
173
|
-
{ address: input },
|
|
174
|
-
authCookie,
|
|
175
|
-
);
|
|
176
|
-
return saveAddress;
|
|
177
|
-
}
|
|
178
|
-
|
|
179
|
-
/** Delete an address by its ID. Returns remaining addresses. */
|
|
180
|
-
export async function deleteAddress(
|
|
181
|
-
addressId: string,
|
|
182
|
-
authCookie: string,
|
|
183
|
-
): Promise<DeleteAddressResult> {
|
|
184
|
-
const { deleteAddress: result } = await gql<{ deleteAddress: DeleteAddressResult }>(
|
|
185
|
-
DELETE_ADDRESS,
|
|
186
|
-
{ addressId },
|
|
187
|
-
authCookie,
|
|
188
|
-
);
|
|
189
|
-
return result;
|
|
190
|
-
}
|
|
191
|
-
|
|
192
|
-
/** Update an existing address. Returns the updated address. */
|
|
193
|
-
export async function updateAddress(
|
|
194
|
-
addressId: string,
|
|
195
|
-
fields: Partial<AddressInput>,
|
|
196
|
-
authCookie: string,
|
|
197
|
-
): Promise<UpdateAddressResult> {
|
|
198
|
-
const { updateAddress: result } = await gql<{ updateAddress: UpdateAddressResult }>(
|
|
199
|
-
UPDATE_ADDRESS,
|
|
200
|
-
{
|
|
201
|
-
addressId,
|
|
202
|
-
addressFields: {
|
|
203
|
-
...fields,
|
|
204
|
-
receiverName: fields.receiverName ?? null,
|
|
205
|
-
complement: fields.complement ?? null,
|
|
206
|
-
},
|
|
207
|
-
},
|
|
208
|
-
authCookie,
|
|
209
|
-
);
|
|
210
|
-
return result;
|
|
211
|
-
}
|
|
212
|
-
|
|
213
|
-
// ---------------------------------------------------------------------------
|
|
214
|
-
// Request-aware wrappers (for COMMERCE_LOADERS / invoke proxy)
|
|
215
|
-
// Handle cookie extraction, postalCode sanitization, and field defaults.
|
|
216
|
-
// ---------------------------------------------------------------------------
|
|
217
|
-
|
|
218
|
-
import { ensureUnsuffixedAuthCookie, getVtexCookies } from "../utils/cookies";
|
|
219
|
-
|
|
220
|
-
function sanitizeAddressInput(props: Record<string, any>): Record<string, any> {
|
|
221
|
-
if (props.postalCode) props.postalCode = props.postalCode.replace(/\D/g, "");
|
|
222
|
-
if (!props.addressName) props.addressName = props.receiverName || `Address ${Date.now()}`;
|
|
223
|
-
if (!props.addressType) props.addressType = "residential";
|
|
224
|
-
return props;
|
|
225
|
-
}
|
|
226
|
-
|
|
227
|
-
export async function createAddressFromRequest(
|
|
228
|
-
props: Record<string, any>,
|
|
229
|
-
request: Request,
|
|
230
|
-
): Promise<SavedAddress> {
|
|
231
|
-
const cookie = ensureUnsuffixedAuthCookie(getVtexCookies(request));
|
|
232
|
-
return createAddress(sanitizeAddressInput(props) as AddressInput, cookie);
|
|
233
|
-
}
|
|
234
|
-
|
|
235
|
-
export async function updateAddressFromRequest(
|
|
236
|
-
props: Record<string, any>,
|
|
237
|
-
request: Request,
|
|
238
|
-
): Promise<UpdateAddressResult> {
|
|
239
|
-
const cookie = ensureUnsuffixedAuthCookie(getVtexCookies(request));
|
|
240
|
-
const { addressId, ...fields } = props;
|
|
241
|
-
return updateAddress(addressId, fields, cookie);
|
|
242
|
-
}
|
|
243
|
-
|
|
244
|
-
export async function deleteAddressFromRequest(
|
|
245
|
-
props: Record<string, any>,
|
|
246
|
-
request: Request,
|
|
247
|
-
): Promise<DeleteAddressResult> {
|
|
248
|
-
const cookie = ensureUnsuffixedAuthCookie(getVtexCookies(request));
|
|
249
|
-
return deleteAddress(props.addressId, cookie);
|
|
250
|
-
}
|
|
@@ -1,86 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* VTEX Intelligent Search analytics event.
|
|
3
|
-
*
|
|
4
|
-
* Reads the IS session/anonymous cookies from the incoming request and POSTs
|
|
5
|
-
* an event to the IS event-api. The configured account is resolved via
|
|
6
|
-
* {@link getVtexConfig}.
|
|
7
|
-
*
|
|
8
|
-
* @see https://developers.vtex.com/docs/api-reference/intelligent-search-api#post-/event-api/v1/-account-/event
|
|
9
|
-
*/
|
|
10
|
-
|
|
11
|
-
import { getVtexConfig, getVtexFetch } from "../../client";
|
|
12
|
-
import { ANONYMOUS_COOKIE, SESSION_COOKIE } from "../../utils/intelligentSearch";
|
|
13
|
-
|
|
14
|
-
export type Props =
|
|
15
|
-
| {
|
|
16
|
-
type: "session.ping";
|
|
17
|
-
url: string;
|
|
18
|
-
}
|
|
19
|
-
| {
|
|
20
|
-
type: "page.cart";
|
|
21
|
-
products: { productId: string; quantity: number }[];
|
|
22
|
-
}
|
|
23
|
-
| {
|
|
24
|
-
type: "page.empty_cart";
|
|
25
|
-
// Empty array would serialize as an invalid JSON schema, so accept anything.
|
|
26
|
-
products: unknown;
|
|
27
|
-
}
|
|
28
|
-
| {
|
|
29
|
-
type: "page.confirmation";
|
|
30
|
-
order: string;
|
|
31
|
-
products: { productId: string; quantity: number; price: number }[];
|
|
32
|
-
}
|
|
33
|
-
| {
|
|
34
|
-
type: "search.click";
|
|
35
|
-
position: number;
|
|
36
|
-
text: string;
|
|
37
|
-
productId: string;
|
|
38
|
-
url: string;
|
|
39
|
-
}
|
|
40
|
-
| {
|
|
41
|
-
type: "search.query";
|
|
42
|
-
url: string;
|
|
43
|
-
text: string;
|
|
44
|
-
misspelled: boolean;
|
|
45
|
-
match: number;
|
|
46
|
-
operator: string;
|
|
47
|
-
locale: string;
|
|
48
|
-
};
|
|
49
|
-
|
|
50
|
-
const readCookie = (cookieHeader: string, name: string): string | undefined => {
|
|
51
|
-
const escaped = name.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
52
|
-
const match = cookieHeader.match(new RegExp(`(?:^|;\\s*)${escaped}=([^;]+)`));
|
|
53
|
-
return match?.[1];
|
|
54
|
-
};
|
|
55
|
-
|
|
56
|
-
/**
|
|
57
|
-
* @title Send Analytics Event
|
|
58
|
-
* @description POST a VTEX Intelligent Search analytics event for the current session.
|
|
59
|
-
*/
|
|
60
|
-
const action = async (props: Props, req: Request): Promise<null> => {
|
|
61
|
-
const { account } = getVtexConfig();
|
|
62
|
-
const cookieHeader = req.headers.get("cookie") ?? "";
|
|
63
|
-
const session = readCookie(cookieHeader, SESSION_COOKIE);
|
|
64
|
-
const anonymous = readCookie(cookieHeader, ANONYMOUS_COOKIE);
|
|
65
|
-
|
|
66
|
-
if (!session || !anonymous) {
|
|
67
|
-
throw new Error("Missing IS Cookies");
|
|
68
|
-
}
|
|
69
|
-
|
|
70
|
-
const url = `https://sp.vtex.com/event-api/v1/${account}/event`;
|
|
71
|
-
await getVtexFetch()(url, {
|
|
72
|
-
method: "POST",
|
|
73
|
-
headers: { "content-type": "application/json" },
|
|
74
|
-
body: JSON.stringify({
|
|
75
|
-
...props,
|
|
76
|
-
session,
|
|
77
|
-
anonymous,
|
|
78
|
-
agent: req.headers.get("user-agent") || "deco-sites/apps",
|
|
79
|
-
}),
|
|
80
|
-
operation: "analytics.event",
|
|
81
|
-
});
|
|
82
|
-
|
|
83
|
-
return null;
|
|
84
|
-
};
|
|
85
|
-
|
|
86
|
-
export default action;
|