@replohq/sdk 2.5.0 → 2.7.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.
Files changed (47) hide show
  1. package/_vendor/replo-utils/lib/json.mjs +4 -4
  2. package/_vendor/replo-utils/lib/misc.mjs +726 -4
  3. package/_vendor/replo-utils/lib/object.mjs +3 -3
  4. package/_vendor/schemas/contentCollection.d.ts +2 -2
  5. package/_vendor/schemas/contentEntry.mjs +3 -3
  6. package/_vendor/schemas/contentManifest.mjs +6 -6
  7. package/_vendor/schemas/routing/locale.d.ts +1 -1
  8. package/_vendor/schemas/routing/locale.mjs +0 -5
  9. package/_vendor/schemas/routing/rules.d.ts +1 -1
  10. package/_vendor/schemas/routing/rules.mjs +0 -5
  11. package/analytics/pixel-meta.d.ts +14 -0
  12. package/analytics/pixel-meta.js +28 -0
  13. package/analytics/replo-first-party-pixel.d.ts +5 -4
  14. package/analytics/replo-first-party-pixel.js +7 -3
  15. package/analytics/replo-pixel-from-meta.d.ts +7 -0
  16. package/analytics/replo-pixel-from-meta.js +27 -0
  17. package/analytics/replo-pixel-script.d.ts +3 -1
  18. package/analytics/replo-pixel-script.js +4 -2
  19. package/cart/buy-now-action.d.ts +2 -13
  20. package/cart/buy-now-action.js +11 -75
  21. package/cart/checkout-actions.d.ts +34 -0
  22. package/cart/checkout-actions.js +27 -0
  23. package/cart/checkout-appearance.d.ts +35 -0
  24. package/cart/checkout-appearance.js +131 -0
  25. package/cart/checkout-session-actions.d.ts +20 -0
  26. package/cart/checkout-session-actions.js +12 -0
  27. package/cart/checkout.d.ts +110 -0
  28. package/cart/checkout.js +420 -0
  29. package/cart/start-stripe-checkout.d.ts +40 -0
  30. package/cart/start-stripe-checkout.js +75 -0
  31. package/{chunk-TTEBDCWT.mjs → chunk-4YTXURVN.mjs} +2 -2
  32. package/{chunk-O4QBR4QC.mjs → chunk-DMJ5VUD6.mjs} +2 -2
  33. package/{chunk-OPKMOW43.mjs → chunk-GNIXARC7.mjs} +1 -1
  34. package/{chunk-XWWFRIXV.mjs → chunk-N4WC2Z43.mjs} +1 -1
  35. package/{chunk-PSYP2DYM.mjs → chunk-QYGRVXWQ.mjs} +1 -1
  36. package/env.d.ts +1 -0
  37. package/env.js +1 -0
  38. package/gateways/canopy-api.d.ts +97 -0
  39. package/gateways/canopy-api.js +120 -0
  40. package/lib/buildMetadata.js +3 -3
  41. package/package.json +14 -4
  42. package/_vendor/replo-utils/lib/errors.d.ts +0 -84
  43. package/_vendor/schemas/errors.d.ts +0 -450
  44. package/_vendor/schemas/generated/errors.d.ts +0 -64
  45. package/chunk-XGXJOHUY.mjs +0 -724
  46. package/chunk-XSMYSAKY.mjs +0 -78
  47. /package/{chunk-ZPDXVFCR.mjs → chunk-JBCOJHZN.mjs} +0 -0
@@ -1,4 +1,4 @@
1
- import { isObjectLike_default, baseGetTag_default, isArray_default } from './chunk-ZPDXVFCR.mjs';
1
+ import { isObjectLike_default, baseGetTag_default, isArray_default } from './chunk-JBCOJHZN.mjs';
2
2
 
3
3
  var numberTag = "[object Number]";
4
4
  function isNumber(value) {
@@ -1,4 +1,4 @@
1
- import { isObjectLike_default, root_default, freeGlobal_default, baseGetTag_default, isObject_default, isArray_default } from './chunk-ZPDXVFCR.mjs';
1
+ import { isObjectLike_default, root_default, freeGlobal_default, baseGetTag_default, isObject_default, isArray_default } from './chunk-JBCOJHZN.mjs';
2
2
 
3
3
  var asyncTag = "[object AsyncFunction]";
4
4
  var funcTag = "[object Function]";
@@ -1,4 +1,4 @@
1
- import { omit } from './chunk-O4QBR4QC.mjs';
1
+ import { omit } from './chunk-DMJ5VUD6.mjs';
2
2
 
3
3
  function parseJsonOrNull(json) {
4
4
  try {
package/env.d.ts CHANGED
@@ -3,6 +3,7 @@ type Env = {
3
3
  PROJECT_ID: string;
4
4
  ANALYTICS_FIRE_API_URL?: string;
5
5
  REPLO_ANALYTICS_PIXEL_URL?: string;
6
+ REPLO_SITE_VERSION?: string;
6
7
  CHECKOUT_PROVIDER?: "shopify" | "stripe" | "none";
7
8
  };
8
9
  export declare const getEnv: () => Promise<Env>;
package/env.js CHANGED
@@ -7,6 +7,7 @@ const envSchema = z.object({
7
7
  PROJECT_ID: z.uuid(),
8
8
  ANALYTICS_FIRE_API_URL: z.string().optional(),
9
9
  REPLO_ANALYTICS_PIXEL_URL: z.string().optional(),
10
+ REPLO_SITE_VERSION: z.string().optional(),
10
11
  CHECKOUT_PROVIDER: z.enum(["shopify", "stripe", "none"]).optional()
11
12
  });
12
13
  const wranglerConfigSchema = z.object({ vars: envSchema });
@@ -1,4 +1,5 @@
1
1
  import type { Cart } from "../cart/cart-schema";
2
+ import type { CartLineAttribute } from "../cart/cart-types";
2
3
  import type { StorefrontCountryCode } from "../loaders/markets";
3
4
  import * as z from "zod";
4
5
  import { CanopyError } from "../lib/canopy-error";
@@ -24,6 +25,68 @@ declare const reconciledCartLineSchema: z.ZodDiscriminatedUnion<[z.ZodObject<{
24
25
  status: z.ZodLiteral<"unavailable">;
25
26
  }, z.core.$strip>], "status">;
26
27
  export type ReconciledCartLine = z.infer<typeof reconciledCartLineSchema>;
28
+ declare const createdStripeSessionSchema: z.ZodObject<{
29
+ url: z.ZodNullable<z.ZodString>;
30
+ form: z.ZodOptional<z.ZodNullable<z.ZodObject<{
31
+ clientSecret: z.ZodString;
32
+ publishableKey: z.ZodString;
33
+ stripeAccountId: z.ZodString;
34
+ hasLiveShipping: z.ZodBoolean;
35
+ }, z.core.$strip>>>;
36
+ }, z.core.$strip>;
37
+ declare const outOfStockSchema: z.ZodObject<{
38
+ result: z.ZodLiteral<"outOfStock">;
39
+ variants: z.ZodArray<z.ZodObject<{
40
+ variantId: z.ZodString;
41
+ available: z.ZodNumber;
42
+ }, z.core.$strip>>;
43
+ }, z.core.$strip>;
44
+ declare const checkoutUpdateOutcomeSchema: z.ZodDiscriminatedUnion<[z.ZodObject<{
45
+ type: z.ZodLiteral<"accept">;
46
+ }, z.core.$strip>, z.ZodObject<{
47
+ type: z.ZodLiteral<"reject">;
48
+ message: z.ZodString;
49
+ }, z.core.$strip>], "type">;
50
+ /**
51
+ * What the embedded checkout form shows after a cart or address change:
52
+ * `accept`, or `reject` with a message for the buyer.
53
+ */
54
+ export type CheckoutUpdateOutcome = z.infer<typeof checkoutUpdateOutcomeSchema>;
55
+ declare const crossSellSchema: z.ZodObject<{
56
+ productId: z.ZodString;
57
+ variantId: z.ZodString;
58
+ title: z.ZodString;
59
+ variantTitle: z.ZodNullable<z.ZodString>;
60
+ imageUrl: z.ZodNullable<z.ZodString>;
61
+ unitPriceMinor: z.ZodNumber;
62
+ currencyCode: z.ZodString;
63
+ }, z.core.$strip>;
64
+ /** A product offered beside the cart: one variant of a live product. */
65
+ export type CrossSell = z.infer<typeof crossSellSchema>;
66
+ declare const addCrossSellOutcomeSchema: z.ZodDiscriminatedUnion<[z.ZodObject<{
67
+ type: z.ZodLiteral<"accept">;
68
+ products: z.ZodArray<z.ZodObject<{
69
+ productId: z.ZodString;
70
+ variantId: z.ZodString;
71
+ title: z.ZodString;
72
+ variantTitle: z.ZodNullable<z.ZodString>;
73
+ imageUrl: z.ZodNullable<z.ZodString>;
74
+ unitPriceMinor: z.ZodNumber;
75
+ currencyCode: z.ZodString;
76
+ }, z.core.$strip>>;
77
+ }, z.core.$strip>, z.ZodObject<{
78
+ type: z.ZodLiteral<"reject">;
79
+ message: z.ZodString;
80
+ }, z.core.$strip>], "type">;
81
+ export type AddCrossSellOutcome = z.infer<typeof addCrossSellOutcomeSchema>;
82
+ export type CheckoutAddress = {
83
+ country: string;
84
+ line1: string;
85
+ line2: string | null;
86
+ city: string | null;
87
+ state: string | null;
88
+ postalCode: string | null;
89
+ };
27
90
  export declare function shouldIncludeInactiveProducts(): boolean;
28
91
  declare class CanopyApiGateway {
29
92
  private apiHost;
@@ -125,6 +188,40 @@ declare class CanopyApiGateway {
125
188
  value: string;
126
189
  }[];
127
190
  }): Promise<Cart>;
191
+ private _stripeCheckoutPost;
192
+ /**
193
+ * Opens a Stripe Checkout session for a cart. A hosted request's body is
194
+ * exactly what every published SDK sends, so canopy treats it the same.
195
+ */
196
+ createStripeCheckoutSession({ checkoutAttemptId, lines, successUrl, cancelUrl, uiMode, }: {
197
+ checkoutAttemptId: string;
198
+ lines: {
199
+ variantId: string;
200
+ quantity: number;
201
+ properties: CartLineAttribute[];
202
+ }[];
203
+ successUrl: string;
204
+ cancelUrl: string;
205
+ uiMode: "hosted" | "form";
206
+ }): Promise<{
207
+ result: "created";
208
+ session: z.infer<typeof createdStripeSessionSchema>;
209
+ } | {
210
+ result: "restartCheckout";
211
+ message: string;
212
+ } | z.infer<typeof outOfStockSchema>>;
213
+ updateCheckoutShipping(body: {
214
+ sessionId: string;
215
+ address: CheckoutAddress;
216
+ }): Promise<CheckoutUpdateOutcome>;
217
+ findCrossSells(body: {
218
+ sessionId: string | null;
219
+ excludeVariantIds: string[];
220
+ }): Promise<CrossSell[]>;
221
+ addCrossSell(body: {
222
+ sessionId: string;
223
+ variantId: string;
224
+ }): Promise<AddCrossSellOutcome>;
128
225
  }
129
226
  export declare function getCanopyApiGateway(): Promise<CanopyApiGateway>;
130
227
  export {};
@@ -49,6 +49,46 @@ const reconciledCartLineSchema = z.discriminatedUnion("status", [
49
49
  const reconcileCartLinesResponseSchema = z.object({
50
50
  lines: z.array(reconciledCartLineSchema)
51
51
  });
52
+ const createdStripeSessionSchema = z.object({
53
+ url: z.string().nullable(),
54
+ form: z.object({
55
+ clientSecret: z.string(),
56
+ publishableKey: z.string(),
57
+ stripeAccountId: z.string(),
58
+ hasLiveShipping: z.boolean()
59
+ }).nullish()
60
+ });
61
+ const outOfStockSchema = z.object({
62
+ result: z.literal("outOfStock"),
63
+ variants: z.array(
64
+ z.object({ variantId: z.string(), available: z.number().int().min(0) })
65
+ )
66
+ });
67
+ const restartCheckoutSchema = z.object({
68
+ error: z.literal("checkoutUnavailable"),
69
+ retry: z.literal("newAttempt"),
70
+ message: z.string().min(1)
71
+ });
72
+ const checkoutUpdateOutcomeSchema = z.discriminatedUnion("type", [
73
+ z.object({ type: z.literal("accept") }),
74
+ z.object({ type: z.literal("reject"), message: z.string() })
75
+ ]);
76
+ const crossSellSchema = z.object({
77
+ productId: z.string(),
78
+ variantId: z.string(),
79
+ title: z.string(),
80
+ variantTitle: z.string().nullable(),
81
+ imageUrl: z.string().nullable(),
82
+ unitPriceMinor: z.number(),
83
+ currencyCode: z.string()
84
+ });
85
+ const addCrossSellOutcomeSchema = z.discriminatedUnion("type", [
86
+ z.object({
87
+ type: z.literal("accept"),
88
+ products: z.array(crossSellSchema)
89
+ }),
90
+ z.object({ type: z.literal("reject"), message: z.string() })
91
+ ]);
52
92
  function shouldIncludeInactiveProducts() {
53
93
  return Boolean(process.env.IS_REPLO_SANDBOX);
54
94
  }
@@ -241,6 +281,86 @@ If you're running locally, make sure the canopy-api cloudflare worker is running
241
281
  }) {
242
282
  return this._cartPost("/replace-attributes", { cartId, attributes });
243
283
  }
284
+ async _stripeCheckoutPost({
285
+ path,
286
+ body,
287
+ schema
288
+ }) {
289
+ const env = await getEnv();
290
+ const response = await this._post(
291
+ `${this.baseUrl}/api/v1/stripe-checkout/${path}`,
292
+ { projectId: env.PROJECT_ID, ...body }
293
+ );
294
+ if (!response.ok) {
295
+ throw new CanopyApiGatewayError({
296
+ message: `Stripe checkout ${path} failed: ${response.status} ${response.statusText}`,
297
+ statusCode: response.status
298
+ });
299
+ }
300
+ return schema.parse(await response.json());
301
+ }
302
+ async createStripeCheckoutSession({
303
+ checkoutAttemptId,
304
+ lines,
305
+ successUrl,
306
+ cancelUrl,
307
+ uiMode
308
+ }) {
309
+ const env = await getEnv();
310
+ const response = await this._post(
311
+ `${this.baseUrl}/api/v1/stripe-checkout/create-session`,
312
+ {
313
+ cartId: checkoutAttemptId,
314
+ checkoutAttemptId,
315
+ lines,
316
+ projectId: env.PROJECT_ID,
317
+ successUrl,
318
+ cancelUrl,
319
+ ...uiMode === "form" ? { uiMode } : {}
320
+ }
321
+ );
322
+ if (!response.ok) {
323
+ const restart = response.status === 409 ? restartCheckoutSchema.safeParse(await response.json()) : null;
324
+ if (restart?.success) {
325
+ return { result: "restartCheckout", message: restart.data.message };
326
+ }
327
+ throw new CanopyApiGatewayError({
328
+ message: `Failed to create Stripe checkout session: ${response.status} ${response.statusText}`,
329
+ statusCode: response.status
330
+ });
331
+ }
332
+ const payload = await response.json();
333
+ const outOfStock = outOfStockSchema.safeParse(payload);
334
+ if (outOfStock.success) {
335
+ return outOfStock.data;
336
+ }
337
+ return {
338
+ result: "created",
339
+ session: createdStripeSessionSchema.parse(payload)
340
+ };
341
+ }
342
+ async updateCheckoutShipping(body) {
343
+ return await this._stripeCheckoutPost({
344
+ path: "update-shipping",
345
+ body,
346
+ schema: checkoutUpdateOutcomeSchema
347
+ });
348
+ }
349
+ async findCrossSells(body) {
350
+ const { products } = await this._stripeCheckoutPost({
351
+ path: "cross-sells",
352
+ body,
353
+ schema: z.object({ products: z.array(crossSellSchema) })
354
+ });
355
+ return products;
356
+ }
357
+ async addCrossSell(body) {
358
+ return await this._stripeCheckoutPost({
359
+ path: "add-cross-sell",
360
+ body,
361
+ schema: addCrossSellOutcomeSchema
362
+ });
363
+ }
244
364
  }
245
365
  async function getCanopyApiGateway() {
246
366
  return CanopyApiGateway.setup();
@@ -1,7 +1,7 @@
1
1
  export const BUILD_METADATA = {
2
2
  "packageName": "@replohq/sdk",
3
- "version": "2.5.0",
3
+ "version": "2.7.0",
4
4
  "branch": "HEAD",
5
- "commit": "f408d4d2ca21640258e7b9a8d20c5a92515cf9d6",
6
- "builtAt": "2026-10-22T19:30:37.074Z"
5
+ "commit": "1aa1f09e1dd141b243b7bb3b1ff1bc947fa01371",
6
+ "builtAt": "2026-10-23T05:44:46.035Z"
7
7
  };
package/package.json CHANGED
@@ -1,12 +1,12 @@
1
1
  {
2
2
  "name": "@replohq/sdk",
3
- "version": "2.5.0",
3
+ "version": "2.7.0",
4
4
  "reploBuild": {
5
5
  "packageName": "@replohq/sdk",
6
- "version": "2.5.0",
6
+ "version": "2.7.0",
7
7
  "branch": "HEAD",
8
- "commit": "f408d4d2ca21640258e7b9a8d20c5a92515cf9d6",
9
- "builtAt": "2026-10-22T19:30:37.074Z"
8
+ "commit": "1aa1f09e1dd141b243b7bb3b1ff1bc947fa01371",
9
+ "builtAt": "2026-10-23T05:44:46.035Z"
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",
@@ -49,6 +49,14 @@
49
49
  "types": "./cart/buy-now-action.d.ts",
50
50
  "default": "./cart/buy-now-action.js"
51
51
  },
52
+ "./cart/checkout": {
53
+ "types": "./cart/checkout.d.ts",
54
+ "default": "./cart/checkout.js"
55
+ },
56
+ "./cart/checkout-actions": {
57
+ "types": "./cart/checkout-actions.d.ts",
58
+ "default": "./cart/checkout-actions.js"
59
+ },
52
60
  "./cart/utils/cart-utils": {
53
61
  "types": "./cart/utils/cart-utils.d.ts",
54
62
  "default": "./cart/utils/cart-utils.js"
@@ -310,6 +318,8 @@
310
318
  "dependencies": {
311
319
  "@formatjs/intl-localematcher": "^0.8.13",
312
320
  "@kachingappz/bundles-react": "0.5.3",
321
+ "@stripe/react-stripe-js": "7.0.0",
322
+ "@stripe/stripe-js": "10.1.0",
313
323
  "negotiator": "^1.0.0",
314
324
  "react-markdown": "^9.1.0",
315
325
  "remark-gfm": "^4.0.1",
@@ -1,84 +0,0 @@
1
- type ValueOfType<ObjectType> = ObjectType[keyof ObjectType];
2
- /**
3
- * Mostly taken from
4
- * https://gist.githubusercontent.com/scokmen/f813c904ef79022e84ab2409574d1b45/raw/cd8709a2fccb005bb53e9bfb2461e07d40b4e8d8/HttpStatusCode.ts
5
- */
6
- export declare const HTTP_STATUS_CODES: {
7
- readonly CONTINUE: 100;
8
- readonly SWITCHING_PROTOCOLS: 101;
9
- readonly PROCESSING: 102;
10
- readonly OK: 200;
11
- readonly CREATED: 201;
12
- readonly ACCEPTED: 202;
13
- readonly NON_AUTHORITATIVE_INFORMATION: 203;
14
- readonly NO_CONTENT: 204;
15
- readonly RESET_CONTENT: 205;
16
- readonly PARTIAL_CONTENT: 206;
17
- readonly MULTI_STATUS: 207;
18
- readonly ALREADY_REPORTED: 208;
19
- readonly IM_USED: 226;
20
- readonly MULTIPLE_CHOICES: 300;
21
- readonly MOVED_PERMANENTLY: 301;
22
- readonly FOUND: 302;
23
- readonly SEE_OTHER: 303;
24
- readonly NOT_MODIFIED: 304;
25
- readonly USE_PROXY: 305;
26
- readonly SWITCH_PROXY: 306;
27
- readonly TEMPORARY_REDIRECT: 307;
28
- readonly PERMANENT_REDIRECT: 308;
29
- readonly BAD_REQUEST: 400;
30
- readonly UNAUTHORIZED: 401;
31
- readonly PAYMENT_REQUIRED: 402;
32
- readonly FORBIDDEN: 403;
33
- readonly NOT_FOUND: 404;
34
- readonly METHOD_NOT_ALLOWED: 405;
35
- readonly NOT_ACCEPTABLE: 406;
36
- readonly PROXY_AUTHENTICATION_REQUIRED: 407;
37
- readonly REQUEST_TIMEOUT: 408;
38
- readonly CONFLICT: 409;
39
- readonly GONE: 410;
40
- readonly LENGTH_REQUIRED: 411;
41
- readonly PRECONDITION_FAILED: 412;
42
- readonly PAYLOAD_TOO_LARGE: 413;
43
- readonly URI_TOO_LONG: 414;
44
- readonly UNSUPPORTED_MEDIA_TYPE: 415;
45
- readonly RANGE_NOT_SATISFIABLE: 416;
46
- readonly EXPECTATION_FAILED: 417;
47
- readonly I_AM_A_TEAPOT: 418;
48
- readonly MISDIRECTED_REQUEST: 421;
49
- readonly UNPROCESSABLE_ENTITY: 422;
50
- readonly LOCKED: 423;
51
- readonly FAILED_DEPENDENCY: 424;
52
- readonly UPGRADE_REQUIRED: 426;
53
- readonly PRECONDITION_REQUIRED: 428;
54
- readonly TOO_MANY_REQUESTS: 429;
55
- readonly REQUEST_HEADER_FIELDS_TOO_LARGE: 431;
56
- readonly UNAVAILABLE_FOR_LEGAL_REASONS: 451;
57
- readonly INTERNAL_SERVER_ERROR: 500;
58
- readonly NOT_IMPLEMENTED: 501;
59
- readonly BAD_GATEWAY: 502;
60
- readonly SERVICE_UNAVAILABLE: 503;
61
- readonly GATEWAY_TIMEOUT: 504;
62
- readonly HTTP_VERSION_NOT_SUPPORTED: 505;
63
- readonly VARIANT_ALSO_NEGOTIATES: 506;
64
- readonly INSUFFICIENT_STORAGE: 507;
65
- readonly LOOP_DETECTED: 508;
66
- readonly NOT_EXTENDED: 510;
67
- readonly NETWORK_AUTHENTICATION_REQUIRED: 511;
68
- readonly UPSTREAM_WEBSERVER_ERROR: 520;
69
- };
70
- export type HttpStatusCode = ValueOfType<typeof HTTP_STATUS_CODES>;
71
- /**
72
- * Checks if an error message indicates a network error (e.g., connectivity issues,
73
- * request timeouts, DNS failures). These errors typically don't need to be tracked
74
- * in error monitoring systems like Sentry since they're user-side connectivity issues.
75
- */
76
- export declare function isNetworkErrorMessage(message: string): boolean;
77
- /**
78
- * Extracts a human-readable message from an unknown caught value. If the value
79
- * is an Error, returns its message; otherwise falls back to the provided
80
- * fallback string or `String(error)`.
81
- */
82
- export declare function getErrorMessage(error: unknown, fallback?: string): string;
83
- export declare function appendErrorId(detail: string, errorId: string | null | undefined): string;
84
- export {};