@faststore/api 4.9.3-dev.0 → 4.9.3-dev.2
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/cjs/index.js +46 -46
- package/dist/cjs/index.js.map +1 -1
- package/dist/es/index.mjs +1169 -1075
- package/dist/es/index.mjs.map +1 -1
- package/dist/src/observability/telemetry.d.ts +2 -0
- package/dist/src/observability/telemetry.d.ts.map +1 -1
- package/dist/src/platforms/vtex/index.d.ts +1 -1
- package/dist/src/platforms/vtex/resolvers/index.d.ts +1 -1
- package/dist/src/platforms/vtex/resolvers/mutation.d.ts +1 -1
- package/dist/src/platforms/vtex/resolvers/validateCart.d.ts.map +1 -1
- package/dist/src/platforms/vtex/resolvers/validateSession.d.ts +1 -1
- package/dist/src/platforms/vtex/resolvers/validateSession.d.ts.map +1 -1
- package/dist/src/platforms/vtex/utils/cartSalesChannel.d.ts +8 -0
- package/dist/src/platforms/vtex/utils/cartSalesChannel.d.ts.map +1 -1
- package/dist/src/platforms/vtex/utils/sessionChannel.d.ts +39 -4
- package/dist/src/platforms/vtex/utils/sessionChannel.d.ts.map +1 -1
- package/package.json +3 -3
- package/src/observability/telemetry.ts +2 -1
- package/src/platforms/vtex/resolvers/validateCart.ts +75 -11
- package/src/platforms/vtex/resolvers/validateSession.ts +147 -9
- package/src/platforms/vtex/utils/cartSalesChannel.ts +33 -0
- package/src/platforms/vtex/utils/sessionChannel.ts +105 -12
|
@@ -1,32 +1,125 @@
|
|
|
1
1
|
import type { Channel } from './channel'
|
|
2
2
|
import ChannelMarshal from './channel'
|
|
3
3
|
|
|
4
|
+
/**
|
|
5
|
+
* Why the session SC must not be replaced by Session Manager:
|
|
6
|
+
* - `orderForm`: adopted from an orderForm with items (e.g. after Quick Order);
|
|
7
|
+
* kept until the cart is empty.
|
|
8
|
+
* - `url`: derived from the URL by localization; always sent to Checkout.
|
|
9
|
+
*
|
|
10
|
+
* Lives only in the raw `channel` JSON string so the public `Channel` type
|
|
11
|
+
* stays unchanged.
|
|
12
|
+
*/
|
|
13
|
+
export type SalesChannelSource = 'orderForm' | 'url'
|
|
14
|
+
|
|
15
|
+
const parseRawChannel = (channel: string | null | undefined) => {
|
|
16
|
+
try {
|
|
17
|
+
return JSON.parse(channel ?? '') ?? {}
|
|
18
|
+
} catch {
|
|
19
|
+
return {}
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
* Reads the marker from the raw channel string. A `url` marker only means
|
|
25
|
+
* something while localization is enabled; a leftover one (e.g. after a store
|
|
26
|
+
* turns localization off) is ignored so Session Manager decides again.
|
|
27
|
+
*/
|
|
28
|
+
export function salesChannelSourceOf(
|
|
29
|
+
channel: string | null | undefined,
|
|
30
|
+
{ localizationEnabled = true }: { localizationEnabled?: boolean } = {}
|
|
31
|
+
): SalesChannelSource | undefined {
|
|
32
|
+
const source = parseRawChannel(channel).salesChannelSource
|
|
33
|
+
|
|
34
|
+
if (source === 'url') {
|
|
35
|
+
return localizationEnabled ? source : undefined
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
return source === 'orderForm' ? source : undefined
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
/** Whether the store config enables localization (URL-derived SC). */
|
|
42
|
+
export const isLocalizationEnabled = (
|
|
43
|
+
discoveryConfig: Record<string, unknown> | undefined
|
|
44
|
+
) =>
|
|
45
|
+
Boolean(
|
|
46
|
+
(discoveryConfig?.localization as { enabled?: boolean } | undefined)
|
|
47
|
+
?.enabled
|
|
48
|
+
)
|
|
49
|
+
|
|
50
|
+
/**
|
|
51
|
+
* SC that Session Manager rejected (401/403) for this shopper after it was
|
|
52
|
+
* adopted from the orderForm. validateCart must not adopt it again, otherwise
|
|
53
|
+
* adoption and rejection would loop.
|
|
54
|
+
*/
|
|
55
|
+
export function rejectedSalesChannelOf(
|
|
56
|
+
channel: string | null | undefined
|
|
57
|
+
): string | undefined {
|
|
58
|
+
const rejected = parseRawChannel(channel).rejectedSalesChannel
|
|
59
|
+
|
|
60
|
+
return typeof rejected === 'string' || typeof rejected === 'number'
|
|
61
|
+
? String(rejected) || undefined
|
|
62
|
+
: undefined
|
|
63
|
+
}
|
|
64
|
+
|
|
4
65
|
/**
|
|
5
66
|
* Builds the session `channel` string after Session Manager responds.
|
|
6
67
|
*
|
|
7
|
-
*
|
|
8
|
-
*
|
|
9
|
-
*
|
|
68
|
+
* Session Manager is the SC authority, except when the client channel carries
|
|
69
|
+
* a `salesChannelSource` marker: then the client SC is kept and the marker is
|
|
70
|
+
* re-emitted so it survives this validation. A recorded rejection is also
|
|
71
|
+
* re-emitted until Session Manager resolves that SC for the shopper.
|
|
10
72
|
*/
|
|
11
73
|
export function channelAfterSessionManager(
|
|
12
74
|
channel: Required<Channel>,
|
|
13
75
|
storeChannelValue: string | null | undefined,
|
|
14
76
|
regionId: string | null | undefined,
|
|
15
|
-
sellerId: string | undefined
|
|
77
|
+
sellerId: string | undefined,
|
|
78
|
+
salesChannelSource?: SalesChannelSource,
|
|
79
|
+
rejectedSalesChannel?: string
|
|
16
80
|
): string {
|
|
17
|
-
const hasExplicitSalesChannel = channel.hasOnlyDefaultSalesChannel === false
|
|
18
|
-
|
|
19
81
|
const storeSalesChannel = storeChannelValue ?? undefined
|
|
20
82
|
const resolvedRegionId = regionId ?? channel.regionId
|
|
83
|
+
const salesChannel = salesChannelSource
|
|
84
|
+
? channel.salesChannel || storeSalesChannel
|
|
85
|
+
: (storeSalesChannel ?? channel.salesChannel)
|
|
86
|
+
const keepRejection =
|
|
87
|
+
rejectedSalesChannel != null &&
|
|
88
|
+
rejectedSalesChannel !== String(salesChannel ?? '')
|
|
21
89
|
|
|
22
90
|
return ChannelMarshal.stringify({
|
|
23
|
-
salesChannel
|
|
24
|
-
? channel.salesChannel || storeSalesChannel
|
|
25
|
-
: (storeSalesChannel ?? channel.salesChannel),
|
|
91
|
+
salesChannel,
|
|
26
92
|
regionId: resolvedRegionId ?? undefined,
|
|
27
93
|
seller: sellerId,
|
|
28
|
-
hasOnlyDefaultSalesChannel:
|
|
29
|
-
|
|
30
|
-
|
|
94
|
+
hasOnlyDefaultSalesChannel: !storeSalesChannel,
|
|
95
|
+
...(salesChannelSource ? { salesChannelSource } : {}),
|
|
96
|
+
...(keepRejection ? { rejectedSalesChannel } : {}),
|
|
31
97
|
})
|
|
32
98
|
}
|
|
99
|
+
|
|
100
|
+
/** Checkout answers with this SC when an orderForm request carries no `sc`. */
|
|
101
|
+
const PLATFORM_DEFAULT_SALES_CHANNEL = '1'
|
|
102
|
+
|
|
103
|
+
/**
|
|
104
|
+
* SC to request from Session Manager. FastStore 4.6–4.9 could move a session
|
|
105
|
+
* to the SC 1 fallback of an empty orderForm and pin it there. When an
|
|
106
|
+
* unmarked session is on SC 1 but the store runs on another SC, ask for the
|
|
107
|
+
* store SC instead: if Session Manager assigns SC 1 on purpose (e.g. by
|
|
108
|
+
* profile), it still answers SC 1.
|
|
109
|
+
*/
|
|
110
|
+
export function salesChannelToRequest(
|
|
111
|
+
channel: Required<Channel>,
|
|
112
|
+
salesChannelSource: SalesChannelSource | undefined,
|
|
113
|
+
storeSalesChannel: string | undefined,
|
|
114
|
+
search: string
|
|
115
|
+
): string {
|
|
116
|
+
const salesChannel = String(channel.salesChannel ?? '')
|
|
117
|
+
const isStuckOnFallback =
|
|
118
|
+
salesChannelSource === undefined &&
|
|
119
|
+
salesChannel === PLATFORM_DEFAULT_SALES_CHANNEL &&
|
|
120
|
+
!!storeSalesChannel &&
|
|
121
|
+
storeSalesChannel !== PLATFORM_DEFAULT_SALES_CHANNEL &&
|
|
122
|
+
!new URLSearchParams(search).has('sc')
|
|
123
|
+
|
|
124
|
+
return isStuckOnFallback ? storeSalesChannel : salesChannel
|
|
125
|
+
}
|