@faststore/api 1.12.50 → 1.12.51
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/dist/api.cjs.development.js +174 -4
- package/dist/api.cjs.development.js.map +1 -1
- package/dist/api.cjs.production.min.js +1 -1
- package/dist/api.cjs.production.min.js.map +1 -1
- package/dist/api.esm.js +174 -4
- package/dist/api.esm.js.map +1 -1
- package/dist/platforms/vtex/clients/fetch.d.ts +5 -1
- package/dist/platforms/vtex/index.d.ts +5 -0
- package/dist/platforms/vtex/utils/cookies.d.ts +52 -0
- package/package.json +2 -2
- package/src/platforms/vtex/clients/commerce/index.ts +47 -4
- package/src/platforms/vtex/clients/fetch.ts +13 -1
- package/src/platforms/vtex/index.ts +6 -0
- package/src/platforms/vtex/utils/cookies.ts +157 -0
package/dist/api.esm.js
CHANGED
|
@@ -18,7 +18,7 @@ import { trace, context, SpanKind } from '@opentelemetry/api';
|
|
|
18
18
|
import { SeverityNumber } from '@opentelemetry/api-logs';
|
|
19
19
|
|
|
20
20
|
var name = "@faststore/api";
|
|
21
|
-
var version = "1.12.
|
|
21
|
+
var version = "1.12.50";
|
|
22
22
|
var license = "MIT";
|
|
23
23
|
var main = "dist/index.js";
|
|
24
24
|
var typings = "dist/index.d.ts";
|
|
@@ -88,7 +88,7 @@ var packageJson = {
|
|
|
88
88
|
};
|
|
89
89
|
|
|
90
90
|
const USER_AGENT = `${packageJson.name}@${packageJson.version}`;
|
|
91
|
-
const fetchAPI = async (info, init) => {
|
|
91
|
+
const fetchAPI = async (info, init, options) => {
|
|
92
92
|
const response = await fetch(info, { ...init,
|
|
93
93
|
headers: { ...(init == null ? void 0 : init.headers),
|
|
94
94
|
'User-Agent': USER_AGENT
|
|
@@ -96,6 +96,10 @@ const fetchAPI = async (info, init) => {
|
|
|
96
96
|
});
|
|
97
97
|
|
|
98
98
|
if (response.ok) {
|
|
99
|
+
if (options != null && options.storeCookies) {
|
|
100
|
+
options.storeCookies(response.headers);
|
|
101
|
+
}
|
|
102
|
+
|
|
99
103
|
return response.status !== 204 ? response.json() : undefined;
|
|
100
104
|
}
|
|
101
105
|
|
|
@@ -104,17 +108,169 @@ const fetchAPI = async (info, init) => {
|
|
|
104
108
|
throw new Error(text);
|
|
105
109
|
};
|
|
106
110
|
|
|
111
|
+
const MATCH_FIRST_SET_COOKIE_KEY_VALUE = /^([^=]+)=([^;]*)/;
|
|
112
|
+
/**
|
|
113
|
+
* Splits a combined `set-cookie` header value (cookies joined by `, `) into
|
|
114
|
+
* individual cookies. Commas inside `expires=...` dates are kept.
|
|
115
|
+
*/
|
|
116
|
+
|
|
117
|
+
const splitSetCookieHeader = value => value.split(/,(?=\s*[^;,=\s]+=)/).map(setCookie => setCookie.trim());
|
|
118
|
+
/**
|
|
119
|
+
* Returns every `set-cookie` value of a fetch response.
|
|
120
|
+
*
|
|
121
|
+
* `Headers.getSetCookie()` only exists on Node >= 18.14 (undici). FastStore v1
|
|
122
|
+
* stores may still run on Node 16, where isomorphic-unfetch falls back to
|
|
123
|
+
* node-fetch v2, which exposes repeated headers through `raw()` instead.
|
|
124
|
+
*/
|
|
125
|
+
|
|
126
|
+
|
|
127
|
+
const getSetCookies = headers => {
|
|
128
|
+
const maybeHeaders = headers;
|
|
129
|
+
|
|
130
|
+
if (typeof maybeHeaders.getSetCookie === 'function') {
|
|
131
|
+
return maybeHeaders.getSetCookie();
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
if (typeof maybeHeaders.raw === 'function') {
|
|
135
|
+
var _maybeHeaders$raw$set;
|
|
136
|
+
|
|
137
|
+
return (_maybeHeaders$raw$set = maybeHeaders.raw()['set-cookie']) != null ? _maybeHeaders$raw$set : [];
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
const setCookie = headers.get('set-cookie');
|
|
141
|
+
return setCookie ? splitSetCookieHeader(setCookie) : [];
|
|
142
|
+
};
|
|
143
|
+
/**
|
|
144
|
+
* This function updates the ctx.storage.cookies, that is used in each request.
|
|
145
|
+
*
|
|
146
|
+
* ctx.storage.cookies is a Map<string[1], Record<string, string>[2]> where,
|
|
147
|
+
* [1] cookie key
|
|
148
|
+
* [2] {
|
|
149
|
+
* value: cookie value,
|
|
150
|
+
* setCookie: setCookie used in browser response
|
|
151
|
+
* }
|
|
152
|
+
*/
|
|
153
|
+
|
|
154
|
+
const updatesContextStorageCookies = (ctx, setCookieValue) => {
|
|
155
|
+
const matchCookie = setCookieValue.match(MATCH_FIRST_SET_COOKIE_KEY_VALUE);
|
|
156
|
+
|
|
157
|
+
if (matchCookie) {
|
|
158
|
+
const cookieKey = matchCookie[1];
|
|
159
|
+
const cookieValue = matchCookie[2];
|
|
160
|
+
ctx.storage.cookies.set(cookieKey, {
|
|
161
|
+
value: cookieValue,
|
|
162
|
+
setCookie: setCookieValue
|
|
163
|
+
});
|
|
164
|
+
}
|
|
165
|
+
};
|
|
166
|
+
const setCookie = (ctx, headers) => {
|
|
167
|
+
getSetCookies(headers).forEach(setCookieValue => updatesContextStorageCookies(ctx, setCookieValue));
|
|
168
|
+
};
|
|
169
|
+
const getStoreCookie = ctx => headers => setCookie(ctx, headers);
|
|
170
|
+
/**
|
|
171
|
+
* This function returns a modified copy of the original cookie header (ctx.headers.cookie from the first request)
|
|
172
|
+
* with the cookie values that comes in each request (ctx.storage.cookies).
|
|
173
|
+
* If there is no cookies in storage, the ctx.headers?.cookie is used
|
|
174
|
+
*
|
|
175
|
+
* ctx.storage.cookies is a Map<string[1], Record<string, string>[2]> where,
|
|
176
|
+
* [1] cookie key
|
|
177
|
+
* [2] {
|
|
178
|
+
* value: cookie value,
|
|
179
|
+
* setCookie: setCookie used in browser response
|
|
180
|
+
* }
|
|
181
|
+
*/
|
|
182
|
+
|
|
183
|
+
const getUpdatedCookie = ctx => {
|
|
184
|
+
var _ctx$headers;
|
|
185
|
+
|
|
186
|
+
if (!((_ctx$headers = ctx.headers) != null && _ctx$headers.cookie)) {
|
|
187
|
+
return null;
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
const contextStorageCookies = Array.from(ctx.storage.cookies.entries());
|
|
191
|
+
|
|
192
|
+
if (contextStorageCookies.length === 0) {
|
|
193
|
+
return ctx.headers.cookie;
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
return contextStorageCookies.reduce((existingCookies, [storageCookieKey, {
|
|
197
|
+
value: storageCookieValue
|
|
198
|
+
}]) => updatesCookieValueByKey(existingCookies, storageCookieKey, storageCookieValue), ctx.headers.cookie);
|
|
199
|
+
};
|
|
200
|
+
const getWithCookie = ctx => function withCookie(headers) {
|
|
201
|
+
const updatedCookie = getUpdatedCookie(ctx);
|
|
202
|
+
|
|
203
|
+
if (!updatedCookie) {
|
|
204
|
+
return headers;
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
return { ...headers,
|
|
208
|
+
cookie: updatedCookie
|
|
209
|
+
};
|
|
210
|
+
};
|
|
211
|
+
/**
|
|
212
|
+
* This function updates the cookie value based on its key
|
|
213
|
+
*
|
|
214
|
+
* const existingCookies = 'key=value1; key2=; key3=value3';
|
|
215
|
+
* const storageCookieKey = 'key2';
|
|
216
|
+
* const storageCookieValue = 'value2'
|
|
217
|
+
*
|
|
218
|
+
* updatesCookieValueByKey(existingCookies, storageCookieKey, storageCookieValue) returns 'key=value1; key2=value2; key3=value3';
|
|
219
|
+
*/
|
|
220
|
+
|
|
221
|
+
const updatesCookieValueByKey = (existingCookies, storageCookieKey, storageCookieValue) => {
|
|
222
|
+
const MATCH_COOKIE_KEY_VALUE = new RegExp(`(${storageCookieKey})=([^;]*)`);
|
|
223
|
+
const cookieParts = existingCookies.match(MATCH_COOKIE_KEY_VALUE); // replaces original cookie with the one coming from storage
|
|
224
|
+
|
|
225
|
+
if (cookieParts) {
|
|
226
|
+
return existingCookies.replace(cookieParts[0], `${cookieParts[1]}=${storageCookieValue}`);
|
|
227
|
+
} // add new storage cookie to the original list of cookies
|
|
228
|
+
|
|
229
|
+
|
|
230
|
+
return `${existingCookies};${storageCookieKey}=${storageCookieValue}`;
|
|
231
|
+
};
|
|
232
|
+
|
|
107
233
|
const BASE_INIT = {
|
|
108
234
|
method: 'POST',
|
|
109
235
|
headers: {
|
|
110
236
|
'content-type': 'application/json'
|
|
111
237
|
}
|
|
112
238
|
};
|
|
239
|
+
|
|
240
|
+
const getHeader = (headers, name) => {
|
|
241
|
+
const value = headers == null ? void 0 : headers[name];
|
|
242
|
+
return Array.isArray(value) ? value[0] : value;
|
|
243
|
+
};
|
|
244
|
+
/**
|
|
245
|
+
* Host the Checkout API uses as the domain of the cookies it sets. Checkout
|
|
246
|
+
* only honors it for hosts registered in the account, so a forged value is
|
|
247
|
+
* ignored there.
|
|
248
|
+
*/
|
|
249
|
+
|
|
250
|
+
|
|
251
|
+
const getForwardedHost = headers => {
|
|
252
|
+
var _getHeader;
|
|
253
|
+
|
|
254
|
+
// Proxies may append values: "client, proxy". Only the first one is the store host.
|
|
255
|
+
const host = ((_getHeader = getHeader(headers, 'x-forwarded-host')) == null ? void 0 : _getHeader.split(',')[0].trim()) || getHeader(headers, 'host') || '';
|
|
256
|
+
return host.trim().replace(/^www\./, '');
|
|
257
|
+
};
|
|
258
|
+
|
|
113
259
|
const VtexCommerce = ({
|
|
114
260
|
account,
|
|
115
261
|
environment
|
|
116
262
|
}, ctx) => {
|
|
117
263
|
const base = `https://${account}.${environment}.com.br`;
|
|
264
|
+
const storeCookies = getStoreCookie(ctx);
|
|
265
|
+
const withCookie = getWithCookie(ctx);
|
|
266
|
+
const forwardedHost = getForwardedHost(ctx.headers); // Checkout calls forward the shopper cookies and keep the cookies Checkout
|
|
267
|
+
// sets (e.g. CheckoutOrderFormOwnership) so they can reach the browser.
|
|
268
|
+
|
|
269
|
+
const checkoutHeaders = () => withCookie({
|
|
270
|
+
'content-type': 'application/json',
|
|
271
|
+
'X-FORWARDED-HOST': forwardedHost
|
|
272
|
+
});
|
|
273
|
+
|
|
118
274
|
return {
|
|
119
275
|
catalog: {
|
|
120
276
|
salesChannel: sc => fetchAPI(`${base}/api/catalog_system/pub/saleschannel/${sc}`),
|
|
@@ -165,7 +321,10 @@ const VtexCommerce = ({
|
|
|
165
321
|
}
|
|
166
322
|
|
|
167
323
|
return fetchAPI(`${base}/api/checkout/pub/orderForm/${id}/attachments/shippingData`, { ...BASE_INIT,
|
|
324
|
+
headers: checkoutHeaders(),
|
|
168
325
|
body: JSON.stringify(body)
|
|
326
|
+
}, {
|
|
327
|
+
storeCookies
|
|
169
328
|
});
|
|
170
329
|
},
|
|
171
330
|
orderForm: ({
|
|
@@ -180,7 +339,11 @@ const VtexCommerce = ({
|
|
|
180
339
|
refreshOutdatedData: refreshOutdatedData.toString(),
|
|
181
340
|
sc: salesChannel
|
|
182
341
|
});
|
|
183
|
-
return fetchAPI(`${base}/api/checkout/pub/orderForm/${id}?${params.toString()}`, BASE_INIT
|
|
342
|
+
return fetchAPI(`${base}/api/checkout/pub/orderForm/${id}?${params.toString()}`, { ...BASE_INIT,
|
|
343
|
+
headers: checkoutHeaders()
|
|
344
|
+
}, {
|
|
345
|
+
storeCookies
|
|
346
|
+
});
|
|
184
347
|
},
|
|
185
348
|
updateOrderFormItems: ({
|
|
186
349
|
id,
|
|
@@ -194,11 +357,14 @@ const VtexCommerce = ({
|
|
|
194
357
|
sc: salesChannel
|
|
195
358
|
});
|
|
196
359
|
return fetchAPI(`${base}/api/checkout/pub/orderForm/${id}/items?${params}`, { ...BASE_INIT,
|
|
360
|
+
headers: checkoutHeaders(),
|
|
197
361
|
body: JSON.stringify({
|
|
198
362
|
orderItems,
|
|
199
363
|
noSplitItem: !shouldSplitItem
|
|
200
364
|
}),
|
|
201
365
|
method: 'PATCH'
|
|
366
|
+
}, {
|
|
367
|
+
storeCookies
|
|
202
368
|
});
|
|
203
369
|
},
|
|
204
370
|
setCustomData: ({
|
|
@@ -208,10 +374,13 @@ const VtexCommerce = ({
|
|
|
208
374
|
value
|
|
209
375
|
}) => {
|
|
210
376
|
return fetchAPI(`${base}/api/checkout/pub/orderForm/${id}/customData/${appId}/${key}`, { ...BASE_INIT,
|
|
377
|
+
headers: checkoutHeaders(),
|
|
211
378
|
body: JSON.stringify({
|
|
212
379
|
value
|
|
213
380
|
}),
|
|
214
381
|
method: 'PUT'
|
|
382
|
+
}, {
|
|
383
|
+
storeCookies
|
|
215
384
|
});
|
|
216
385
|
},
|
|
217
386
|
region: async ({
|
|
@@ -2464,7 +2633,8 @@ const getContextFactory = options => ctx => {
|
|
|
2464
2633
|
ctx.storage = {
|
|
2465
2634
|
channel: ChannelMarshal.parse(options.channel),
|
|
2466
2635
|
flags: (_options$flags = options.flags) != null ? _options$flags : {},
|
|
2467
|
-
locale: options.locale
|
|
2636
|
+
locale: options.locale,
|
|
2637
|
+
cookies: new Map()
|
|
2468
2638
|
};
|
|
2469
2639
|
ctx.clients = getClients(options, ctx);
|
|
2470
2640
|
ctx.loaders = getLoaders(options, ctx);
|