@faststore/api 2.2.0-alpha.0 → 2.2.0-alpha.10
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 +97 -165
- 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 +97 -165
- package/dist/api.esm.js.map +1 -1
- package/dist/index.d.ts +2 -2
- package/dist/platforms/vtex/clients/commerce/index.d.ts +0 -1
- package/dist/platforms/vtex/clients/commerce/types/OrderForm.d.ts +17 -17
- package/dist/platforms/vtex/clients/index.d.ts +0 -1
- package/dist/platforms/vtex/index.d.ts +2 -2
- package/dist/platforms/vtex/resolvers/mutation.d.ts +2 -2
- package/dist/platforms/vtex/resolvers/validateCart.d.ts +2 -2
- package/dist/platforms/vtex/utils/sanitizeHtml.d.ts +17 -0
- package/package.json +7 -5
- package/src/platforms/vtex/clients/commerce/index.ts +37 -36
- package/src/platforms/vtex/clients/commerce/types/OrderForm.ts +17 -17
- package/src/platforms/vtex/index.ts +1 -1
- package/src/platforms/vtex/resolvers/validateCart.ts +6 -38
- package/src/platforms/vtex/utils/enhanceSku.ts +11 -1
- package/src/platforms/vtex/utils/sanitizeHtml.ts +21 -0
- package/src/platforms/vtex/utils/shouldUpdateShippingData.ts +49 -102
- package/dist/platforms/vtex/utils/getCookies.d.ts +0 -1
- package/src/platforms/vtex/utils/getCookies.ts +0 -8
package/dist/index.d.ts
CHANGED
|
@@ -124,7 +124,7 @@ export declare const getResolvers: (options: Options) => {
|
|
|
124
124
|
parentAssemblyBinding: import("./__generated__/schema").Maybe<string>;
|
|
125
125
|
productCategoryIds: string;
|
|
126
126
|
priceTags: string[];
|
|
127
|
-
manualPrice: number;
|
|
127
|
+
manualPrice: number | null;
|
|
128
128
|
measurementUnit: string;
|
|
129
129
|
additionalInfo: {
|
|
130
130
|
brandName: string;
|
|
@@ -139,7 +139,7 @@ export declare const getResolvers: (options: Options) => {
|
|
|
139
139
|
sellerChain: string[];
|
|
140
140
|
availability: string;
|
|
141
141
|
unitMultiplier: number;
|
|
142
|
-
skuSpecifications
|
|
142
|
+
skuSpecifications?: import("./platforms/vtex/clients/commerce/types/OrderForm").SKUSpecification[] | null | undefined;
|
|
143
143
|
priceDefinition: {
|
|
144
144
|
calculatedSellingPrice: number;
|
|
145
145
|
sellingPrices: import("./platforms/vtex/clients/commerce/types/OrderForm").SellingPrice[];
|
|
@@ -64,7 +64,6 @@ export declare const VtexCommerce: ({ account, environment, incrementAddress }:
|
|
|
64
64
|
address: ({ postalCode, country, }: AddressInput) => Promise<Address>;
|
|
65
65
|
};
|
|
66
66
|
session: (search: string) => Promise<Session>;
|
|
67
|
-
getSessionOrder: () => Promise<Session>;
|
|
68
67
|
subscribeToNewsletter: (data: {
|
|
69
68
|
name: string;
|
|
70
69
|
email: string;
|
|
@@ -31,7 +31,7 @@ export interface OrderFormItem {
|
|
|
31
31
|
parentAssemblyBinding: string | null;
|
|
32
32
|
productCategoryIds: string;
|
|
33
33
|
priceTags: string[];
|
|
34
|
-
manualPrice: number;
|
|
34
|
+
manualPrice: number | null;
|
|
35
35
|
measurementUnit: string;
|
|
36
36
|
additionalInfo: {
|
|
37
37
|
brandName: string;
|
|
@@ -46,7 +46,7 @@ export interface OrderFormItem {
|
|
|
46
46
|
sellerChain: string[];
|
|
47
47
|
availability: string;
|
|
48
48
|
unitMultiplier: number;
|
|
49
|
-
skuSpecifications
|
|
49
|
+
skuSpecifications?: SKUSpecification[] | null;
|
|
50
50
|
priceDefinition: {
|
|
51
51
|
calculatedSellingPrice: number;
|
|
52
52
|
sellingPrices: SellingPrice[];
|
|
@@ -127,7 +127,7 @@ export interface OrderForm {
|
|
|
127
127
|
currencyGroupSize: number;
|
|
128
128
|
startsWithCurrencySymbol: boolean;
|
|
129
129
|
};
|
|
130
|
-
currencyLocale:
|
|
130
|
+
currencyLocale: number;
|
|
131
131
|
currencySymbol: string;
|
|
132
132
|
saveUserData: boolean;
|
|
133
133
|
timeZone: string;
|
|
@@ -138,7 +138,7 @@ export interface OrderForm {
|
|
|
138
138
|
customData: OrderFormCustomData | null;
|
|
139
139
|
itemMetadata: {
|
|
140
140
|
items: MetadataItem[];
|
|
141
|
-
};
|
|
141
|
+
} | null;
|
|
142
142
|
hooksData: any | null;
|
|
143
143
|
ratesAndBenefitsData: {
|
|
144
144
|
rateAndBenefitsIdentifiers: any[];
|
|
@@ -217,21 +217,21 @@ export interface PaymentData {
|
|
|
217
217
|
availableTokens: any[];
|
|
218
218
|
}
|
|
219
219
|
export interface ClientProfileData {
|
|
220
|
-
email: string;
|
|
221
|
-
firstName: string;
|
|
222
|
-
lastName: string;
|
|
223
|
-
document: string;
|
|
224
|
-
documentType: string;
|
|
225
|
-
phone: string;
|
|
226
|
-
corporateName: string;
|
|
227
|
-
tradeName: string;
|
|
228
|
-
corporateDocument: string;
|
|
229
|
-
stateInscription: string;
|
|
230
|
-
corporatePhone: string;
|
|
220
|
+
email: string | null;
|
|
221
|
+
firstName: string | null;
|
|
222
|
+
lastName: string | null;
|
|
223
|
+
document: string | null;
|
|
224
|
+
documentType: string | null;
|
|
225
|
+
phone: string | null;
|
|
226
|
+
corporateName: string | null;
|
|
227
|
+
tradeName: string | null;
|
|
228
|
+
corporateDocument: string | null;
|
|
229
|
+
stateInscription: string | null;
|
|
230
|
+
corporatePhone: string | null;
|
|
231
231
|
isCorporate: boolean;
|
|
232
232
|
profileCompleteOnLoading: boolean;
|
|
233
233
|
profileErrorOnLoading: boolean;
|
|
234
|
-
customerClass: string;
|
|
234
|
+
customerClass: string | null;
|
|
235
235
|
}
|
|
236
236
|
export interface ShippingData {
|
|
237
237
|
address: CheckoutAddress | null;
|
|
@@ -295,7 +295,7 @@ export interface AvailableDeliveryWindows {
|
|
|
295
295
|
startDateUtc: string;
|
|
296
296
|
endDateUtc: string;
|
|
297
297
|
price: number;
|
|
298
|
-
|
|
298
|
+
lisPrice?: number;
|
|
299
299
|
tax: number;
|
|
300
300
|
}
|
|
301
301
|
export interface DeliveryId {
|
|
@@ -57,7 +57,6 @@ export declare const getClients: (options: Options, ctx: Context) => {
|
|
|
57
57
|
address: ({ postalCode, country, }: import("./commerce/types/Address").AddressInput) => Promise<import("./commerce/types/Address").Address>;
|
|
58
58
|
};
|
|
59
59
|
session: (search: string) => Promise<import("./commerce/types/Session").Session>;
|
|
60
|
-
getSessionOrder: () => Promise<import("./commerce/types/Session").Session>;
|
|
61
60
|
subscribeToNewsletter: (data: {
|
|
62
61
|
name: string;
|
|
63
62
|
email: string;
|
|
@@ -152,7 +152,7 @@ export declare const getResolvers: (_: Options) => {
|
|
|
152
152
|
parentAssemblyBinding: string | null;
|
|
153
153
|
productCategoryIds: string;
|
|
154
154
|
priceTags: string[];
|
|
155
|
-
manualPrice: number;
|
|
155
|
+
manualPrice: number | null;
|
|
156
156
|
measurementUnit: string;
|
|
157
157
|
additionalInfo: {
|
|
158
158
|
brandName: string;
|
|
@@ -167,7 +167,7 @@ export declare const getResolvers: (_: Options) => {
|
|
|
167
167
|
sellerChain: string[];
|
|
168
168
|
availability: string;
|
|
169
169
|
unitMultiplier: number;
|
|
170
|
-
skuSpecifications
|
|
170
|
+
skuSpecifications?: import("./clients/commerce/types/OrderForm").SKUSpecification[] | null | undefined;
|
|
171
171
|
priceDefinition: {
|
|
172
172
|
calculatedSellingPrice: number;
|
|
173
173
|
sellingPrices: import("./clients/commerce/types/OrderForm").SellingPrice[];
|
|
@@ -25,7 +25,7 @@ export declare const Mutation: {
|
|
|
25
25
|
parentAssemblyBinding: string | null;
|
|
26
26
|
productCategoryIds: string;
|
|
27
27
|
priceTags: string[];
|
|
28
|
-
manualPrice: number;
|
|
28
|
+
manualPrice: number | null;
|
|
29
29
|
measurementUnit: string;
|
|
30
30
|
additionalInfo: {
|
|
31
31
|
brandName: string;
|
|
@@ -40,7 +40,7 @@ export declare const Mutation: {
|
|
|
40
40
|
sellerChain: string[];
|
|
41
41
|
availability: string;
|
|
42
42
|
unitMultiplier: number;
|
|
43
|
-
skuSpecifications
|
|
43
|
+
skuSpecifications?: import("../clients/commerce/types/OrderForm").SKUSpecification[] | null | undefined;
|
|
44
44
|
priceDefinition: {
|
|
45
45
|
calculatedSellingPrice: number;
|
|
46
46
|
sellingPrices: import("../clients/commerce/types/OrderForm").SellingPrice[];
|
|
@@ -39,7 +39,7 @@ export declare const validateCart: (_: unknown, { cart: { order }, session }: Mu
|
|
|
39
39
|
parentAssemblyBinding: string | null;
|
|
40
40
|
productCategoryIds: string;
|
|
41
41
|
priceTags: string[];
|
|
42
|
-
manualPrice: number;
|
|
42
|
+
manualPrice: number | null;
|
|
43
43
|
measurementUnit: string;
|
|
44
44
|
additionalInfo: {
|
|
45
45
|
brandName: string;
|
|
@@ -54,7 +54,7 @@ export declare const validateCart: (_: unknown, { cart: { order }, session }: Mu
|
|
|
54
54
|
sellerChain: string[];
|
|
55
55
|
availability: string;
|
|
56
56
|
unitMultiplier: number;
|
|
57
|
-
skuSpecifications
|
|
57
|
+
skuSpecifications?: import("../clients/commerce/types/OrderForm").SKUSpecification[] | null | undefined;
|
|
58
58
|
priceDefinition: {
|
|
59
59
|
calculatedSellingPrice: number;
|
|
60
60
|
sellingPrices: import("../clients/commerce/types/OrderForm").SellingPrice[];
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import sanitizeHtmlLib from 'sanitize-html';
|
|
2
|
+
/**
|
|
3
|
+
* For now, we're using sanitize-html's default set
|
|
4
|
+
* of allowed tags and attributes, which don't even include img elements
|
|
5
|
+
*
|
|
6
|
+
* It is known many client depends on pontentially vulnerable tags, such as script tags
|
|
7
|
+
* We chose to be restrictive at first, and document those restrictions later.
|
|
8
|
+
*
|
|
9
|
+
* When expanding the set of allowed tags and attributes, please consider performance, privacy and security.
|
|
10
|
+
*
|
|
11
|
+
* This possibily breaks compatibility with Portal and Store Framework,
|
|
12
|
+
* which both allows an enormous amount of tags and attributes
|
|
13
|
+
*
|
|
14
|
+
* This was a thoughtful decision that can be reviewed in the future given
|
|
15
|
+
* research was made to back up those changes.
|
|
16
|
+
*/
|
|
17
|
+
export declare const sanitizeHtml: (dirty: Parameters<typeof sanitizeHtmlLib>[0], options?: Parameters<typeof sanitizeHtmlLib>[1]) => string;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@faststore/api",
|
|
3
|
-
"version": "2.2.0-alpha.
|
|
3
|
+
"version": "2.2.0-alpha.10",
|
|
4
4
|
"license": "MIT",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"typings": "dist/index.d.ts",
|
|
@@ -32,15 +32,17 @@
|
|
|
32
32
|
"dataloader": "^2.1.0",
|
|
33
33
|
"fast-deep-equal": "^3.1.3",
|
|
34
34
|
"isomorphic-unfetch": "^3.1.0",
|
|
35
|
-
"p-limit": "^3.1.0"
|
|
35
|
+
"p-limit": "^3.1.0",
|
|
36
|
+
"sanitize-html": "^2.11.0"
|
|
36
37
|
},
|
|
37
38
|
"devDependencies": {
|
|
38
39
|
"@envelop/core": "^2.6.0",
|
|
39
|
-
"@faststore/eslint-config": "^2.2.0-alpha.
|
|
40
|
-
"@faststore/shared": "^2.2.0-alpha.
|
|
40
|
+
"@faststore/eslint-config": "^2.2.0-alpha.10",
|
|
41
|
+
"@faststore/shared": "^2.2.0-alpha.10",
|
|
41
42
|
"@graphql-codegen/cli": "2.2.0",
|
|
42
43
|
"@graphql-codegen/typescript": "2.2.2",
|
|
43
44
|
"@types/express": "^4.17.16",
|
|
45
|
+
"@types/sanitize-html": "^2.9.1",
|
|
44
46
|
"concurrently": "^6.2.1",
|
|
45
47
|
"eslint": "7.32.0",
|
|
46
48
|
"express": "^4.17.3",
|
|
@@ -56,5 +58,5 @@
|
|
|
56
58
|
"@envelop/core": "^1 || ^2",
|
|
57
59
|
"graphql": "^15.6.0"
|
|
58
60
|
},
|
|
59
|
-
"gitHead": "
|
|
61
|
+
"gitHead": "183808da50c3c697de08a478918d1da1dcd8d938"
|
|
60
62
|
}
|
|
@@ -15,7 +15,6 @@ import type {
|
|
|
15
15
|
} from './types/Simulation'
|
|
16
16
|
import type { Session } from './types/Session'
|
|
17
17
|
import type { Channel } from '../../utils/channel'
|
|
18
|
-
import { getCookie } from '../../utils/getCookies'
|
|
19
18
|
import type { SalesChannel } from './types/SalesChannel'
|
|
20
19
|
import { MasterDataResponse } from './types/Newsletter'
|
|
21
20
|
import type { Address, AddressInput } from './types/Address'
|
|
@@ -122,7 +121,6 @@ export const VtexCommerce = (
|
|
|
122
121
|
selectedAddresses: selectedAddresses,
|
|
123
122
|
clearAddressIfPostalCodeNotFound: incrementAddress,
|
|
124
123
|
}
|
|
125
|
-
|
|
126
124
|
return fetchAPI(
|
|
127
125
|
`${base}/api/checkout/pub/orderForm/${id}/attachments/shippingData`,
|
|
128
126
|
{
|
|
@@ -131,7 +129,7 @@ export const VtexCommerce = (
|
|
|
131
129
|
headers: {
|
|
132
130
|
'content-type': 'application/json',
|
|
133
131
|
cookie: ctx.headers.cookie,
|
|
134
|
-
}
|
|
132
|
+
},
|
|
135
133
|
}
|
|
136
134
|
)
|
|
137
135
|
},
|
|
@@ -150,10 +148,19 @@ export const VtexCommerce = (
|
|
|
150
148
|
refreshOutdatedData: refreshOutdatedData.toString(),
|
|
151
149
|
sc: salesChannel,
|
|
152
150
|
})
|
|
151
|
+
const requestInit: RequestInit = ctx.headers
|
|
152
|
+
? {
|
|
153
|
+
...BASE_INIT,
|
|
154
|
+
headers: {
|
|
155
|
+
'content-type': 'application/json',
|
|
156
|
+
cookie: ctx.headers.cookie,
|
|
157
|
+
},
|
|
158
|
+
}
|
|
159
|
+
: BASE_INIT
|
|
153
160
|
|
|
154
161
|
return fetchAPI(
|
|
155
162
|
`${base}/api/checkout/pub/orderForm/${id}?${params.toString()}`,
|
|
156
|
-
|
|
163
|
+
requestInit
|
|
157
164
|
)
|
|
158
165
|
},
|
|
159
166
|
updateOrderFormItems: ({
|
|
@@ -174,16 +181,31 @@ export const VtexCommerce = (
|
|
|
174
181
|
sc: salesChannel,
|
|
175
182
|
})
|
|
176
183
|
|
|
184
|
+
const items = JSON.stringify({
|
|
185
|
+
orderItems,
|
|
186
|
+
noSplitItem: !shouldSplitItem,
|
|
187
|
+
})
|
|
188
|
+
|
|
189
|
+
const requestInit: RequestInit = ctx.headers
|
|
190
|
+
? {
|
|
191
|
+
headers: {
|
|
192
|
+
'content-type': 'application/json',
|
|
193
|
+
cookie: ctx.headers.cookie,
|
|
194
|
+
},
|
|
195
|
+
body: items,
|
|
196
|
+
method: 'PATCH',
|
|
197
|
+
}
|
|
198
|
+
: {
|
|
199
|
+
headers: {
|
|
200
|
+
'content-type': 'application/json',
|
|
201
|
+
},
|
|
202
|
+
body: items,
|
|
203
|
+
method: 'PATCH',
|
|
204
|
+
}
|
|
205
|
+
|
|
177
206
|
return fetchAPI(
|
|
178
207
|
`${base}/api/checkout/pub/orderForm/${id}/items?${params}`,
|
|
179
|
-
|
|
180
|
-
...BASE_INIT,
|
|
181
|
-
body: JSON.stringify({
|
|
182
|
-
orderItems,
|
|
183
|
-
noSplitItem: !shouldSplitItem,
|
|
184
|
-
}),
|
|
185
|
-
method: 'PATCH',
|
|
186
|
-
}
|
|
208
|
+
requestInit
|
|
187
209
|
)
|
|
188
210
|
},
|
|
189
211
|
setCustomData: ({
|
|
@@ -243,34 +265,13 @@ export const VtexCommerce = (
|
|
|
243
265
|
'items',
|
|
244
266
|
'profile.id,profile.email,profile.firstName,profile.lastName,store.channel,store.countryCode,store.cultureInfo,store.currencyCode,store.currencySymbol'
|
|
245
267
|
)
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
return fetchAPI(`${base}/api/sessions?${params.toString()}`, {
|
|
249
|
-
method: 'GET',
|
|
250
|
-
headers: {
|
|
251
|
-
'content-type': 'application/json',
|
|
252
|
-
cookie: ctx.headers.cookie,
|
|
253
|
-
},
|
|
254
|
-
})
|
|
255
|
-
} else {
|
|
256
|
-
// cookie unset -> create session
|
|
257
|
-
return fetchAPI(`${base}/api/sessions?${params.toString()}`, {
|
|
258
|
-
method: 'POST',
|
|
259
|
-
headers: {
|
|
260
|
-
'content-type': 'application/json',
|
|
261
|
-
cookie: ctx.headers.cookie,
|
|
262
|
-
},
|
|
263
|
-
body: '{}',
|
|
264
|
-
})
|
|
265
|
-
}
|
|
266
|
-
},
|
|
267
|
-
getSessionOrder: (): Promise<Session> => {
|
|
268
|
-
return fetchAPI(`${base}/api/sessions?items=public.orderFormId`, {
|
|
269
|
-
method: 'GET',
|
|
268
|
+
return fetchAPI(`${base}/api/sessions?${params.toString()}`, {
|
|
269
|
+
method: 'POST',
|
|
270
270
|
headers: {
|
|
271
271
|
'content-type': 'application/json',
|
|
272
272
|
cookie: ctx.headers.cookie,
|
|
273
273
|
},
|
|
274
|
+
body: '{}',
|
|
274
275
|
})
|
|
275
276
|
},
|
|
276
277
|
subscribeToNewsletter: (data: {
|
|
@@ -33,7 +33,7 @@ export interface OrderFormItem {
|
|
|
33
33
|
parentAssemblyBinding: string | null
|
|
34
34
|
productCategoryIds: string
|
|
35
35
|
priceTags: string[]
|
|
36
|
-
manualPrice: number
|
|
36
|
+
manualPrice: number | null
|
|
37
37
|
measurementUnit: string
|
|
38
38
|
additionalInfo: {
|
|
39
39
|
brandName: string
|
|
@@ -48,7 +48,7 @@ export interface OrderFormItem {
|
|
|
48
48
|
sellerChain: string[]
|
|
49
49
|
availability: string
|
|
50
50
|
unitMultiplier: number
|
|
51
|
-
skuSpecifications
|
|
51
|
+
skuSpecifications?: SKUSpecification[] | null
|
|
52
52
|
priceDefinition: {
|
|
53
53
|
calculatedSellingPrice: number
|
|
54
54
|
sellingPrices: SellingPrice[]
|
|
@@ -135,7 +135,7 @@ export interface OrderForm {
|
|
|
135
135
|
currencyGroupSize: number
|
|
136
136
|
startsWithCurrencySymbol: boolean
|
|
137
137
|
}
|
|
138
|
-
currencyLocale:
|
|
138
|
+
currencyLocale: number
|
|
139
139
|
currencySymbol: string
|
|
140
140
|
saveUserData: boolean
|
|
141
141
|
timeZone: string
|
|
@@ -146,7 +146,7 @@ export interface OrderForm {
|
|
|
146
146
|
customData: OrderFormCustomData | null
|
|
147
147
|
itemMetadata: {
|
|
148
148
|
items: MetadataItem[]
|
|
149
|
-
}
|
|
149
|
+
} | null
|
|
150
150
|
hooksData: any | null
|
|
151
151
|
ratesAndBenefitsData: {
|
|
152
152
|
rateAndBenefitsIdentifiers: any[]
|
|
@@ -229,21 +229,21 @@ export interface PaymentData {
|
|
|
229
229
|
}
|
|
230
230
|
|
|
231
231
|
export interface ClientProfileData {
|
|
232
|
-
email: string
|
|
233
|
-
firstName: string
|
|
234
|
-
lastName: string
|
|
235
|
-
document: string
|
|
236
|
-
documentType: string
|
|
237
|
-
phone: string
|
|
238
|
-
corporateName: string
|
|
239
|
-
tradeName: string
|
|
240
|
-
corporateDocument: string
|
|
241
|
-
stateInscription: string
|
|
242
|
-
corporatePhone: string
|
|
232
|
+
email: string | null
|
|
233
|
+
firstName: string | null
|
|
234
|
+
lastName: string | null
|
|
235
|
+
document: string | null
|
|
236
|
+
documentType: string | null
|
|
237
|
+
phone: string | null
|
|
238
|
+
corporateName: string | null
|
|
239
|
+
tradeName: string | null
|
|
240
|
+
corporateDocument: string | null
|
|
241
|
+
stateInscription: string | null
|
|
242
|
+
corporatePhone: string | null
|
|
243
243
|
isCorporate: boolean
|
|
244
244
|
profileCompleteOnLoading: boolean
|
|
245
245
|
profileErrorOnLoading: boolean
|
|
246
|
-
customerClass: string
|
|
246
|
+
customerClass: string | null
|
|
247
247
|
}
|
|
248
248
|
|
|
249
249
|
export interface ShippingData {
|
|
@@ -314,7 +314,7 @@ export interface AvailableDeliveryWindows {
|
|
|
314
314
|
startDateUtc: string,
|
|
315
315
|
endDateUtc: string,
|
|
316
316
|
price: number,
|
|
317
|
-
|
|
317
|
+
lisPrice?: number,
|
|
318
318
|
tax: number,
|
|
319
319
|
}
|
|
320
320
|
|
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
import deepEquals from 'fast-deep-equal'
|
|
2
2
|
|
|
3
3
|
import { mutateChannelContext, mutateLocaleContext } from '../utils/contex'
|
|
4
|
-
import { getCookie } from '../utils/getCookies'
|
|
5
4
|
import { md5 } from '../utils/md5'
|
|
6
5
|
import {
|
|
7
6
|
attachmentToPropertyValue,
|
|
@@ -128,7 +127,10 @@ const joinItems = (form: OrderForm) => {
|
|
|
128
127
|
const [item] = items
|
|
129
128
|
const quantity = items.reduce((acc, i) => acc + i.quantity, 0)
|
|
130
129
|
const totalPrice = items.reduce(
|
|
131
|
-
(acc, i) =>
|
|
130
|
+
(acc, i) =>
|
|
131
|
+
acc +
|
|
132
|
+
(i?.priceDefinition?.total ??
|
|
133
|
+
(i?.quantity ?? 0) * (i?.sellingPrice ?? 0)),
|
|
132
134
|
0
|
|
133
135
|
)
|
|
134
136
|
|
|
@@ -205,19 +207,6 @@ const isOrderFormStale = (form: OrderForm) => {
|
|
|
205
207
|
return newEtag !== oldEtag
|
|
206
208
|
}
|
|
207
209
|
|
|
208
|
-
async function getOrderNumberFromSession(
|
|
209
|
-
headers: Record<string, string> = {},
|
|
210
|
-
commerce: Context['clients']['commerce']
|
|
211
|
-
) {
|
|
212
|
-
const cookieSession = getCookie('vtex_session', headers.cookie)
|
|
213
|
-
|
|
214
|
-
if (cookieSession) {
|
|
215
|
-
const { namespaces } = await commerce.getSessionOrder()
|
|
216
|
-
return namespaces.public?.orderFormId?.value ?? undefined
|
|
217
|
-
}
|
|
218
|
-
return
|
|
219
|
-
}
|
|
220
|
-
|
|
221
210
|
// Returns the regionalized orderForm
|
|
222
211
|
const getOrderForm = async (id: string, { clients: { commerce } }: Context) => {
|
|
223
212
|
return commerce.checkout.orderForm({
|
|
@@ -301,15 +290,10 @@ export const validateCart = async (
|
|
|
301
290
|
{ cart: { order }, session }: MutationValidateCartArgs,
|
|
302
291
|
ctx: Context
|
|
303
292
|
) => {
|
|
304
|
-
const {
|
|
305
|
-
orderNumber: orderNumberFromCart,
|
|
306
|
-
acceptedOffer,
|
|
307
|
-
shouldSplitItem,
|
|
308
|
-
} = order
|
|
293
|
+
const { orderNumber, acceptedOffer, shouldSplitItem } = order
|
|
309
294
|
const {
|
|
310
295
|
clients: { commerce },
|
|
311
296
|
loaders: { skuLoader },
|
|
312
|
-
headers,
|
|
313
297
|
} = ctx
|
|
314
298
|
|
|
315
299
|
const channel = session?.channel
|
|
@@ -323,25 +307,10 @@ export const validateCart = async (
|
|
|
323
307
|
mutateLocaleContext(ctx, locale)
|
|
324
308
|
}
|
|
325
309
|
|
|
326
|
-
const orderNumberFromSession = await getOrderNumberFromSession(
|
|
327
|
-
headers,
|
|
328
|
-
commerce
|
|
329
|
-
)
|
|
330
|
-
const orderNumber = orderNumberFromSession ?? orderNumberFromCart ?? ''
|
|
331
|
-
|
|
332
310
|
// Step1: Get OrderForm from VTEX Commerce
|
|
333
311
|
const orderForm = await getOrderForm(orderNumber, ctx)
|
|
334
312
|
|
|
335
|
-
// Step1.
|
|
336
|
-
// Social Selling: the vtex_session cookie contains a new orderForm id with Social Selling data
|
|
337
|
-
// My Orders: the customer clicks on reordering through generating a new cart and when returning to the faststore, this information needs to be returned by vtex_session cookie.
|
|
338
|
-
// New session: a new user enters the website and has no orderForm attributed to it (has no relation to the vtex_session cookie).
|
|
339
|
-
// In all cases, the origin orderForm should replace the copy that's in the browser
|
|
340
|
-
if (orderForm.orderFormId != orderNumberFromCart) {
|
|
341
|
-
return orderFormToCart(orderForm, skuLoader)
|
|
342
|
-
}
|
|
343
|
-
|
|
344
|
-
// Step1.2: Check if another system changed the orderForm with this orderNumber
|
|
313
|
+
// Step1.5: Check if another system changed the orderForm with this orderNumber
|
|
345
314
|
// If so, this means the user interacted with this cart elsewhere and expects
|
|
346
315
|
// to see this new cart state instead of what's stored on the user's browser.
|
|
347
316
|
const isStale = isOrderFormStale(orderForm)
|
|
@@ -403,7 +372,6 @@ export const validateCart = async (
|
|
|
403
372
|
if (changes.length === 0) {
|
|
404
373
|
return null
|
|
405
374
|
}
|
|
406
|
-
|
|
407
375
|
// Step4: Apply delta changes to order form
|
|
408
376
|
const updatedOrderForm = await commerce.checkout
|
|
409
377
|
// update orderForm items
|
|
@@ -1,8 +1,18 @@
|
|
|
1
1
|
import type { Product, Item } from '../clients/search/types/ProductSearchResult'
|
|
2
|
+
import { sanitizeHtml } from './sanitizeHtml'
|
|
2
3
|
|
|
3
4
|
export type EnhancedSku = Item & { isVariantOf: Product }
|
|
4
5
|
|
|
6
|
+
function sanitizeProduct(product: Product): Product {
|
|
7
|
+
return {
|
|
8
|
+
...product,
|
|
9
|
+
description: product.description
|
|
10
|
+
? sanitizeHtml(product.description)
|
|
11
|
+
: product.description,
|
|
12
|
+
}
|
|
13
|
+
}
|
|
14
|
+
|
|
5
15
|
export const enhanceSku = (item: Item, product: Product): EnhancedSku => ({
|
|
6
16
|
...item,
|
|
7
|
-
isVariantOf: product,
|
|
17
|
+
isVariantOf: sanitizeProduct(product),
|
|
8
18
|
})
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import sanitizeHtmlLib from 'sanitize-html'
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* For now, we're using sanitize-html's default set
|
|
5
|
+
* of allowed tags and attributes, which don't even include img elements
|
|
6
|
+
*
|
|
7
|
+
* It is known many client depends on pontentially vulnerable tags, such as script tags
|
|
8
|
+
* We chose to be restrictive at first, and document those restrictions later.
|
|
9
|
+
*
|
|
10
|
+
* When expanding the set of allowed tags and attributes, please consider performance, privacy and security.
|
|
11
|
+
*
|
|
12
|
+
* This possibily breaks compatibility with Portal and Store Framework,
|
|
13
|
+
* which both allows an enormous amount of tags and attributes
|
|
14
|
+
*
|
|
15
|
+
* This was a thoughtful decision that can be reviewed in the future given
|
|
16
|
+
* research was made to back up those changes.
|
|
17
|
+
*/
|
|
18
|
+
export const sanitizeHtml = (
|
|
19
|
+
dirty: Parameters<typeof sanitizeHtmlLib>[0],
|
|
20
|
+
options?: Parameters<typeof sanitizeHtmlLib>[1]
|
|
21
|
+
) => sanitizeHtmlLib(dirty, options)
|