@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.
Files changed (139) hide show
  1. package/package.json +7 -52
  2. package/src/index.ts +10 -28
  3. package/src/utils/constants.ts +2 -56
  4. package/src/utils/cookieSanitizer.ts +59 -59
  5. package/src/utils/operationRouter.ts +75 -65
  6. package/src/utils/types.ts +709 -1557
  7. package/src/vtexClient.ts +354 -343
  8. package/src/README.md +0 -6
  9. package/src/__conformance__/upstream.test.ts +0 -158
  10. package/src/__tests__/client-segment-cookie.test.ts +0 -255
  11. package/src/__tests__/client-set-cookie-forward.test.ts +0 -257
  12. package/src/__tests__/schemas.test.ts +0 -71
  13. package/src/actions/address.ts +0 -250
  14. package/src/actions/analytics/sendEvent.ts +0 -86
  15. package/src/actions/auth.ts +0 -333
  16. package/src/actions/checkout.ts +0 -659
  17. package/src/actions/index.ts +0 -11
  18. package/src/actions/masterData.ts +0 -168
  19. package/src/actions/misc.ts +0 -188
  20. package/src/actions/newsletter.ts +0 -105
  21. package/src/actions/orders.ts +0 -34
  22. package/src/actions/profile.ts +0 -201
  23. package/src/actions/session.ts +0 -85
  24. package/src/actions/trigger.ts +0 -43
  25. package/src/actions/wishlist.ts +0 -114
  26. package/src/client.ts +0 -724
  27. package/src/commerceLoaders.ts +0 -267
  28. package/src/hooks/__tests__/createCart.render.test.ts +0 -114
  29. package/src/hooks/__tests__/createCart.test.ts +0 -92
  30. package/src/hooks/__tests__/createUseCart.test.ts +0 -184
  31. package/src/hooks/__tests__/createUseUser.test.ts +0 -48
  32. package/src/hooks/__tests__/createUseWishlist.test.ts +0 -87
  33. package/src/hooks/cartQuery.ts +0 -204
  34. package/src/hooks/createCart.ts +0 -427
  35. package/src/hooks/createUseCart.ts +0 -360
  36. package/src/hooks/createUseUser.ts +0 -153
  37. package/src/hooks/createUseWishlist.ts +0 -242
  38. package/src/hooks/index.ts +0 -25
  39. package/src/hooks/useAutocomplete.ts +0 -83
  40. package/src/hooks/useCart.ts +0 -243
  41. package/src/hooks/useUser.ts +0 -78
  42. package/src/hooks/useWishlist.ts +0 -119
  43. package/src/invoke.ts +0 -235
  44. package/src/loaders/ProductDetailsPage.ts +0 -1
  45. package/src/loaders/ProductList.ts +0 -1
  46. package/src/loaders/ProductListingPage.ts +0 -1
  47. package/src/loaders/__tests__/legacyProductList.test.ts +0 -157
  48. package/src/loaders/address.ts +0 -115
  49. package/src/loaders/autocomplete.ts +0 -56
  50. package/src/loaders/brands.ts +0 -44
  51. package/src/loaders/cart/attachments.ts +0 -53
  52. package/src/loaders/cart/full.ts +0 -67
  53. package/src/loaders/cart/gifts.ts +0 -43
  54. package/src/loaders/cart/orderFormId.ts +0 -31
  55. package/src/loaders/cart/shipping.test.ts +0 -125
  56. package/src/loaders/cart/shipping.ts +0 -136
  57. package/src/loaders/cart/summary.ts +0 -36
  58. package/src/loaders/cart.ts +0 -52
  59. package/src/loaders/catalog.ts +0 -163
  60. package/src/loaders/collections.ts +0 -55
  61. package/src/loaders/index.ts +0 -20
  62. package/src/loaders/intelligentSearch/__tests__/productListingPage.test.ts +0 -51
  63. package/src/loaders/intelligentSearch/productDetailsPage.ts +0 -111
  64. package/src/loaders/intelligentSearch/productList.ts +0 -170
  65. package/src/loaders/intelligentSearch/productListingPage.ts +0 -525
  66. package/src/loaders/intelligentSearch/suggestions.ts +0 -44
  67. package/src/loaders/legacy/productDetailsPage.ts +0 -1
  68. package/src/loaders/legacy/productList.ts +0 -1
  69. package/src/loaders/legacy/relatedProductsLoader.ts +0 -79
  70. package/src/loaders/legacy.ts +0 -710
  71. package/src/loaders/logistics.ts +0 -111
  72. package/src/loaders/minicart.ts +0 -78
  73. package/src/loaders/navbar.ts +0 -26
  74. package/src/loaders/orders.ts +0 -92
  75. package/src/loaders/pageType.ts +0 -68
  76. package/src/loaders/paths/PDPDefaultPath.ts +0 -51
  77. package/src/loaders/payment.ts +0 -97
  78. package/src/loaders/productListFull.ts +0 -157
  79. package/src/loaders/profile.ts +0 -138
  80. package/src/loaders/promotion.ts +0 -30
  81. package/src/loaders/search.ts +0 -124
  82. package/src/loaders/session.ts +0 -83
  83. package/src/loaders/user.ts +0 -87
  84. package/src/loaders/wishlist.ts +0 -89
  85. package/src/loaders/wishlistProducts.ts +0 -69
  86. package/src/loaders/workflow/products.ts +0 -62
  87. package/src/loaders/workflow.ts +0 -316
  88. package/src/logo.png +0 -0
  89. package/src/manifest.gen.ts +0 -89
  90. package/src/middleware.cacheHeaders.test.ts +0 -44
  91. package/src/middleware.ts +0 -240
  92. package/src/mod.ts +0 -173
  93. package/src/registry.ts +0 -9
  94. package/src/schemas.gen.ts +0 -3191
  95. package/src/schemas.ts +0 -30
  96. package/src/types.ts +0 -248
  97. package/src/utils/__tests__/cartProjection.test.ts +0 -118
  98. package/src/utils/__tests__/cookieSanitizer.test.ts +0 -162
  99. package/src/utils/__tests__/fetch.test.ts +0 -80
  100. package/src/utils/__tests__/fetchCache.test.ts +0 -155
  101. package/src/utils/__tests__/instrumentedFetch.test.ts +0 -158
  102. package/src/utils/__tests__/intelligentSearch.test.ts +0 -88
  103. package/src/utils/__tests__/minicart.test.ts +0 -184
  104. package/src/utils/__tests__/operationRouter.test.ts +0 -227
  105. package/src/utils/__tests__/resilience.test.ts +0 -205
  106. package/src/utils/__tests__/resourceRange.test.ts +0 -32
  107. package/src/utils/__tests__/simulationCache.test.ts +0 -40
  108. package/src/utils/__tests__/sitemap.test.ts +0 -185
  109. package/src/utils/__tests__/slugify.test.ts +0 -31
  110. package/src/utils/__tests__/storefrontBaseUrl.test.ts +0 -61
  111. package/src/utils/__tests__/transform.test.ts +0 -1111
  112. package/src/utils/accountLoaders.ts +0 -203
  113. package/src/utils/authHelpers.ts +0 -85
  114. package/src/utils/batch.ts +0 -18
  115. package/src/utils/buildOfferShelf.test.ts +0 -59
  116. package/src/utils/cartProjection.ts +0 -96
  117. package/src/utils/cookies.ts +0 -167
  118. package/src/utils/enrichment.ts +0 -556
  119. package/src/utils/fetch.ts +0 -111
  120. package/src/utils/fetchCache.ts +0 -55
  121. package/src/utils/index.ts +0 -19
  122. package/src/utils/instrumentedFetch.ts +0 -98
  123. package/src/utils/intelligentSearch.ts +0 -96
  124. package/src/utils/legacy.ts +0 -139
  125. package/src/utils/minicart.ts +0 -139
  126. package/src/utils/pickAndOmit.ts +0 -25
  127. package/src/utils/proxy.ts +0 -495
  128. package/src/utils/resilience.ts +0 -352
  129. package/src/utils/resourceRange.ts +0 -10
  130. package/src/utils/segment.ts +0 -152
  131. package/src/utils/similars.ts +0 -35
  132. package/src/utils/simulationCache.ts +0 -73
  133. package/src/utils/sitemap.ts +0 -283
  134. package/src/utils/slugCache.ts +0 -28
  135. package/src/utils/slugify.ts +0 -13
  136. package/src/utils/transform.ts +0 -1691
  137. package/src/utils/vtexId.ts +0 -151
  138. package/src/vtexClient.test.ts +0 -204
  139. 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
- });
@@ -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;