@replohq/sdk 2.18.3 → 2.20.0
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/_vendor/replo-utils/lib/crypto.d.ts +5 -0
- package/_vendor/schemas/generated/consent.d.ts +13 -1
- package/analytics/analytics-provider.js +3 -1
- package/analytics/get-analytics-sinks.js +7 -4
- package/analytics/replo-pixel-script.d.ts +5 -5
- package/analytics/replo-pixel-script.js +23 -22
- package/cart/hooks/use-add-to-cart.d.ts +17 -4
- package/cart/hooks/use-add-to-cart.js +6 -2
- package/cart/hooks/use-buy-now.d.ts +17 -5
- package/cart/hooks/use-buy-now.js +6 -2
- package/cart/hooks/use-checkout-availability.d.ts +21 -0
- package/cart/hooks/use-checkout-availability.js +71 -0
- package/consent/consent-platform.d.ts +20 -5
- package/consent/consent-platform.js +94 -11
- package/consent/consent-store.d.ts +7 -2
- package/consent/consent-store.js +16 -4
- package/consent/inject-script-descriptors.d.ts +8 -1
- package/consent/inject-script-descriptors.js +23 -0
- package/consent/replo-scripts.d.ts +6 -2
- package/consent/replo-scripts.js +35 -27
- package/consent/script-registration-store.d.ts +2 -0
- package/consent/script-snippets.d.ts +1 -1
- package/consent/types.d.ts +18 -4
- package/consent/usercentrics-consent.d.ts +15 -0
- package/consent/usercentrics-consent.js +96 -0
- package/consent/window-api.js +1 -1
- package/lib/buildMetadata.js +3 -3
- package/loaders/integration-loader-schemas.d.ts +1 -0
- package/loaders/loader-schemas.d.ts +3 -0
- package/loaders/loader-schemas.js +4 -2
- package/package.json +4 -4
- package/providers/canopy-client-config.d.ts +2 -0
- package/providers/replo-provider.js +2 -1
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
import * as v from "valibot";
|
|
2
|
+
const usercentricsDetailsSchema = v.object({
|
|
3
|
+
consent: v.optional(v.object({ type: v.optional(v.string()) })),
|
|
4
|
+
services: v.record(
|
|
5
|
+
v.string(),
|
|
6
|
+
v.object({
|
|
7
|
+
name: v.string(),
|
|
8
|
+
essential: v.optional(v.boolean()),
|
|
9
|
+
consent: v.object({ given: v.boolean() })
|
|
10
|
+
})
|
|
11
|
+
)
|
|
12
|
+
});
|
|
13
|
+
const usercentricsBaseInfoSchema = v.array(
|
|
14
|
+
v.object({
|
|
15
|
+
name: v.string(),
|
|
16
|
+
isEssential: v.optional(v.boolean()),
|
|
17
|
+
consent: v.object({
|
|
18
|
+
status: v.boolean(),
|
|
19
|
+
history: v.optional(v.array(v.object({ type: v.optional(v.string()) })))
|
|
20
|
+
})
|
|
21
|
+
})
|
|
22
|
+
);
|
|
23
|
+
function usercentricsCategories(services) {
|
|
24
|
+
const optionalServices = services.filter((service) => !service.essential);
|
|
25
|
+
const acceptedAll = optionalServices.length > 0 && optionalServices.every((service) => service.given);
|
|
26
|
+
return {
|
|
27
|
+
necessary: true,
|
|
28
|
+
analytics: acceptedAll,
|
|
29
|
+
marketing: acceptedAll,
|
|
30
|
+
preferences: acceptedAll,
|
|
31
|
+
sale_of_data: acceptedAll
|
|
32
|
+
};
|
|
33
|
+
}
|
|
34
|
+
async function readUsercentricsServices() {
|
|
35
|
+
if (window.__ucCmp?.getConsentDetails) {
|
|
36
|
+
const details = v.safeParse(
|
|
37
|
+
usercentricsDetailsSchema,
|
|
38
|
+
await window.__ucCmp.getConsentDetails()
|
|
39
|
+
);
|
|
40
|
+
if (!details.success) {
|
|
41
|
+
console.warn("[Replo] Unreadable Usercentrics consent details");
|
|
42
|
+
return null;
|
|
43
|
+
}
|
|
44
|
+
return {
|
|
45
|
+
services: Object.values(details.output.services).map((service) => ({
|
|
46
|
+
name: service.name,
|
|
47
|
+
given: service.consent.given,
|
|
48
|
+
essential: service.essential === true
|
|
49
|
+
})),
|
|
50
|
+
isExplicit: details.output.consent?.type === "EXPLICIT"
|
|
51
|
+
};
|
|
52
|
+
}
|
|
53
|
+
const rawBaseInfo = window.UC_UI?.getServicesBaseInfo?.();
|
|
54
|
+
if (rawBaseInfo === void 0) {
|
|
55
|
+
return null;
|
|
56
|
+
}
|
|
57
|
+
const baseInfo = v.safeParse(usercentricsBaseInfoSchema, rawBaseInfo);
|
|
58
|
+
if (!baseInfo.success) {
|
|
59
|
+
console.warn("[Replo] Unreadable Usercentrics service info");
|
|
60
|
+
return null;
|
|
61
|
+
}
|
|
62
|
+
return {
|
|
63
|
+
services: baseInfo.output.map((service) => ({
|
|
64
|
+
name: service.name,
|
|
65
|
+
given: service.consent.status,
|
|
66
|
+
essential: service.isEssential === true
|
|
67
|
+
})),
|
|
68
|
+
isExplicit: baseInfo.output.some((service) => {
|
|
69
|
+
return service.consent.history?.at(-1)?.type === "explicit";
|
|
70
|
+
})
|
|
71
|
+
};
|
|
72
|
+
}
|
|
73
|
+
async function readUsercentricsChange(previous) {
|
|
74
|
+
const answer = await readUsercentricsServices();
|
|
75
|
+
if (!answer) {
|
|
76
|
+
return null;
|
|
77
|
+
}
|
|
78
|
+
const categories = usercentricsCategories(answer.services);
|
|
79
|
+
const grantedUsercentricsServices = answer.services.filter((service) => service.given).map((service) => service.name).sort();
|
|
80
|
+
const isUnchanged = categories.analytics === previous.categories.analytics && grantedUsercentricsServices.join() === previous.grantedUsercentricsServices.join();
|
|
81
|
+
const isDecided = answer.isExplicit || answer.services.some((service) => service.given && !service.essential);
|
|
82
|
+
if (isUnchanged && (previous.decidedAt !== null || !isDecided)) {
|
|
83
|
+
return null;
|
|
84
|
+
}
|
|
85
|
+
return {
|
|
86
|
+
categories,
|
|
87
|
+
decidedAt: isDecided ? Date.now() : null,
|
|
88
|
+
grantedUsercentricsServices,
|
|
89
|
+
hasDowngrade: previous.grantedUsercentricsServices.some((name) => {
|
|
90
|
+
return !grantedUsercentricsServices.includes(name);
|
|
91
|
+
})
|
|
92
|
+
};
|
|
93
|
+
}
|
|
94
|
+
export {
|
|
95
|
+
readUsercentricsChange
|
|
96
|
+
};
|
package/consent/window-api.js
CHANGED
|
@@ -30,7 +30,7 @@ const api = {
|
|
|
30
30
|
saleOfDataAllowed: () => isAllowed("sale_of_data"),
|
|
31
31
|
shouldShowBanner: () => {
|
|
32
32
|
const state = consentStore.getSnapshot();
|
|
33
|
-
if (state.cmp
|
|
33
|
+
if (state.cmp && state.cmp !== "replo") {
|
|
34
34
|
return false;
|
|
35
35
|
}
|
|
36
36
|
return state.mode !== "off" && state.decidedAt === null;
|
package/lib/buildMetadata.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
export const BUILD_METADATA = {
|
|
2
2
|
"packageName": "@replohq/sdk",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.20.0",
|
|
4
4
|
"branch": "HEAD",
|
|
5
|
-
"commit": "
|
|
6
|
-
"builtAt": "2026-11-
|
|
5
|
+
"commit": "20365c00f7144702c4a7438ac5d907dc97b5b62a",
|
|
6
|
+
"builtAt": "2026-11-06T20:15:11.914Z"
|
|
7
7
|
};
|
|
@@ -210,6 +210,7 @@ export declare const rebuyRecommendationsOutputSchema: z.ZodObject<{
|
|
|
210
210
|
previewUrl: z.ZodNullable<z.ZodString>;
|
|
211
211
|
}, z.core.$strip>], "kind">>>;
|
|
212
212
|
}, z.core.$strip>>>;
|
|
213
|
+
externalCheckoutUrl: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
213
214
|
}, z.core.$strip>>;
|
|
214
215
|
}, z.core.$strip>;
|
|
215
216
|
export declare const smileEarningRuleSchema: z.ZodObject<{
|
|
@@ -389,6 +389,7 @@ export declare const productSchema: z.ZodObject<{
|
|
|
389
389
|
previewUrl: z.ZodNullable<z.ZodString>;
|
|
390
390
|
}, z.core.$strip>], "kind">>>;
|
|
391
391
|
}, z.core.$strip>>>;
|
|
392
|
+
externalCheckoutUrl: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
392
393
|
}, z.core.$strip>;
|
|
393
394
|
export type Product = z.infer<typeof productSchema>;
|
|
394
395
|
export declare const okendoReviewMediaSchema: z.ZodObject<{
|
|
@@ -640,6 +641,7 @@ export declare const fullProductSchema: z.ZodObject<{
|
|
|
640
641
|
previewUrl: z.ZodNullable<z.ZodString>;
|
|
641
642
|
}, z.core.$strip>], "kind">>>;
|
|
642
643
|
}, z.core.$strip>>;
|
|
644
|
+
externalCheckoutUrl: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
643
645
|
}, z.core.$strip>;
|
|
644
646
|
export declare const fullCollectionSchema: z.ZodObject<{
|
|
645
647
|
id: z.ZodString;
|
|
@@ -834,6 +836,7 @@ export declare const paginatedProductsSchema: z.ZodObject<{
|
|
|
834
836
|
previewUrl: z.ZodNullable<z.ZodString>;
|
|
835
837
|
}, z.core.$strip>], "kind">>>;
|
|
836
838
|
}, z.core.$strip>>>;
|
|
839
|
+
externalCheckoutUrl: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
837
840
|
}, z.core.$strip>>;
|
|
838
841
|
pageInfo: z.ZodObject<{
|
|
839
842
|
hasNextPage: z.ZodBoolean;
|
|
@@ -145,7 +145,8 @@ const productSchema = z.object({
|
|
|
145
145
|
tags: z.array(z.string()).optional(),
|
|
146
146
|
sellingPlanGroups: z.array(sellingPlanGroupSchema).optional(),
|
|
147
147
|
requiresSellingPlan: z.boolean().optional(),
|
|
148
|
-
metafields: z.array(metafieldSchema).optional()
|
|
148
|
+
metafields: z.array(metafieldSchema).optional(),
|
|
149
|
+
externalCheckoutUrl: z.string().nullish()
|
|
149
150
|
});
|
|
150
151
|
const okendoReviewMediaSchema = z.object({
|
|
151
152
|
type: z.string().describe('Okendo media type, e.g. "image" or "video"'),
|
|
@@ -216,7 +217,8 @@ const fullProductSchema = z.object({
|
|
|
216
217
|
tags: z.array(z.string()),
|
|
217
218
|
sellingPlanGroups: z.array(sellingPlanGroupSchema),
|
|
218
219
|
requiresSellingPlan: productSchema.shape.requiresSellingPlan,
|
|
219
|
-
metafields: z.array(metafieldSchema)
|
|
220
|
+
metafields: z.array(metafieldSchema),
|
|
221
|
+
externalCheckoutUrl: productSchema.shape.externalCheckoutUrl
|
|
220
222
|
});
|
|
221
223
|
const fullCollectionSchema = z.object({
|
|
222
224
|
id: z.string(),
|
package/package.json
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@replohq/sdk",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.20.0",
|
|
4
4
|
"reploBuild": {
|
|
5
5
|
"packageName": "@replohq/sdk",
|
|
6
|
-
"version": "2.
|
|
6
|
+
"version": "2.20.0",
|
|
7
7
|
"branch": "HEAD",
|
|
8
|
-
"commit": "
|
|
9
|
-
"builtAt": "2026-11-
|
|
8
|
+
"commit": "20365c00f7144702c4a7438ac5d907dc97b5b62a",
|
|
9
|
+
"builtAt": "2026-11-06T20:15:11.914Z"
|
|
10
10
|
},
|
|
11
11
|
"description": "Replo SDK — cart, analytics, and data loaders for agent-built Next.js sites.",
|
|
12
12
|
"license": "SEE LICENSE IN LICENSE",
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import type { CheckoutProvider } from "../lib/integration-utils";
|
|
1
2
|
import React from "react";
|
|
2
3
|
/**
|
|
3
4
|
* What browser code needs to call canopy-api directly. Resolved from the worker
|
|
@@ -7,6 +8,7 @@ import React from "react";
|
|
|
7
8
|
export type CanopyClientConfig = {
|
|
8
9
|
canopyApiBaseUrl: string;
|
|
9
10
|
projectId: string;
|
|
11
|
+
checkoutProvider: CheckoutProvider;
|
|
10
12
|
};
|
|
11
13
|
export declare function CanopyClientConfigProvider({ config, children, }: React.PropsWithChildren<{
|
|
12
14
|
config: CanopyClientConfig | null;
|
|
@@ -19,7 +19,8 @@ async function ReploProvider({
|
|
|
19
19
|
checkoutProvider = env.CHECKOUT_PROVIDER ?? "none";
|
|
20
20
|
canopyClientConfig = {
|
|
21
21
|
canopyApiBaseUrl: buildBaseUrl(env.CANOPY_API_HOST),
|
|
22
|
-
projectId: env.PROJECT_ID
|
|
22
|
+
projectId: env.PROJECT_ID,
|
|
23
|
+
checkoutProvider
|
|
23
24
|
};
|
|
24
25
|
} catch {
|
|
25
26
|
checkoutProvider = "none";
|