@replohq/sandbox-runtime 1.3.0 → 1.4.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/LinkInterceptor.js
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
"use client";
|
|
2
2
|
import { useEffect } from "react";
|
|
3
3
|
import { displayModeStore } from "./select-mode/displayModeStore";
|
|
4
|
+
const EXTERNAL_NAVIGATION_HANDLER_KEY = "__reploExternalNavigationHandler";
|
|
4
5
|
function blockNavigation(event) {
|
|
5
6
|
event.preventDefault();
|
|
6
7
|
event.stopPropagation();
|
|
@@ -25,14 +26,20 @@ function shouldInterceptNavigationForAgentPreview() {
|
|
|
25
26
|
}
|
|
26
27
|
return new URLSearchParams(window.location.search).get("__reploAgentPreview") === "1";
|
|
27
28
|
}
|
|
28
|
-
function
|
|
29
|
+
function resolveUrl(rawUrl) {
|
|
29
30
|
try {
|
|
30
|
-
|
|
31
|
-
|
|
31
|
+
return new URL(
|
|
32
|
+
typeof rawUrl === "string" ? rawUrl : rawUrl.href,
|
|
33
|
+
window.location.href
|
|
34
|
+
);
|
|
32
35
|
} catch {
|
|
33
36
|
return null;
|
|
34
37
|
}
|
|
35
38
|
}
|
|
39
|
+
function urlLeavesSandbox(rawUrl) {
|
|
40
|
+
const resolved = resolveUrl(rawUrl);
|
|
41
|
+
return resolved === null ? null : resolved.origin !== window.location.origin;
|
|
42
|
+
}
|
|
36
43
|
function LinkInterceptor() {
|
|
37
44
|
useEffect(() => {
|
|
38
45
|
if (!shouldInterceptNavigationForAgentPreview()) {
|
|
@@ -43,25 +50,34 @@ function LinkInterceptor() {
|
|
|
43
50
|
const originalReplaceState = history.replaceState;
|
|
44
51
|
const navigation = getWindowNavigation();
|
|
45
52
|
const reportNavigated = (rawUrl) => {
|
|
46
|
-
let route;
|
|
47
|
-
try {
|
|
48
|
-
route = new URL(
|
|
49
|
-
typeof rawUrl === "string" ? rawUrl : rawUrl.href,
|
|
50
|
-
window.location.href
|
|
51
|
-
).pathname;
|
|
52
|
-
} catch {
|
|
53
|
-
route = String(rawUrl);
|
|
54
|
-
}
|
|
55
53
|
window.parent.postMessage(
|
|
56
54
|
{
|
|
57
55
|
type: "replo:navigated",
|
|
58
|
-
route
|
|
56
|
+
route: resolveUrl(rawUrl)?.pathname ?? String(rawUrl)
|
|
57
|
+
},
|
|
58
|
+
"*"
|
|
59
|
+
);
|
|
60
|
+
};
|
|
61
|
+
const openInParent = (rawUrl) => {
|
|
62
|
+
const resolved = resolveUrl(rawUrl);
|
|
63
|
+
if (!resolved) {
|
|
64
|
+
return;
|
|
65
|
+
}
|
|
66
|
+
window.parent.postMessage(
|
|
67
|
+
{
|
|
68
|
+
type: "replo:open-external",
|
|
69
|
+
url: resolved.toString()
|
|
59
70
|
},
|
|
60
71
|
"*"
|
|
61
72
|
);
|
|
62
73
|
};
|
|
74
|
+
Reflect.set(window, EXTERNAL_NAVIGATION_HANDLER_KEY, (url) => {
|
|
75
|
+
openInParent(url);
|
|
76
|
+
return true;
|
|
77
|
+
});
|
|
63
78
|
window.open = function(url, target, features) {
|
|
64
79
|
if (url !== void 0 && url !== "" && urlLeavesSandbox(url) === true) {
|
|
80
|
+
openInParent(url);
|
|
65
81
|
return null;
|
|
66
82
|
}
|
|
67
83
|
return originalWindowOpen.call(window, url, target, features);
|
|
@@ -92,6 +108,7 @@ function LinkInterceptor() {
|
|
|
92
108
|
return;
|
|
93
109
|
}
|
|
94
110
|
event.preventDefault?.();
|
|
111
|
+
openInParent(destinationUrl);
|
|
95
112
|
};
|
|
96
113
|
const handleClick = (event) => {
|
|
97
114
|
if (displayModeStore.getSnapshot() === "selection") {
|
|
@@ -115,10 +132,12 @@ function LinkInterceptor() {
|
|
|
115
132
|
const linkTarget = link.getAttribute("target");
|
|
116
133
|
if (linkTarget && linkTarget !== "_self") {
|
|
117
134
|
blockNavigation(event);
|
|
135
|
+
openInParent(href);
|
|
118
136
|
return;
|
|
119
137
|
}
|
|
120
138
|
if (urlLeavesSandbox(href) === true) {
|
|
121
139
|
blockNavigation(event);
|
|
140
|
+
openInParent(href);
|
|
122
141
|
return;
|
|
123
142
|
}
|
|
124
143
|
if (event.button !== 0 || event.metaKey || event.ctrlKey || event.shiftKey || event.altKey) {
|
|
@@ -137,6 +156,7 @@ function LinkInterceptor() {
|
|
|
137
156
|
navigation?.addEventListener("navigate", handleNavigate);
|
|
138
157
|
document.addEventListener("click", handleClick, true);
|
|
139
158
|
return () => {
|
|
159
|
+
Reflect.deleteProperty(window, EXTERNAL_NAVIGATION_HANDLER_KEY);
|
|
140
160
|
window.open = originalWindowOpen;
|
|
141
161
|
history.pushState = originalPushState;
|
|
142
162
|
history.replaceState = originalReplaceState;
|
package/LinkInterceptor.js.map
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../LinkInterceptor.tsx"],
|
|
4
|
-
"sourcesContent": ["\"use client\";\n\nimport { useEffect } from \"react\";\n\nimport { displayModeStore } from \"./select-mode/displayModeStore\";\n\ntype NavigationNavigateEvent = {\n destination?: { url?: string };\n preventDefault?: () => void;\n};\n\ntype NavigationLike = {\n addEventListener: (\n type: \"navigate\",\n listener: (event: NavigationNavigateEvent) => void,\n ) => void;\n removeEventListener: (\n type: \"navigate\",\n listener: (event: NavigationNavigateEvent) => void,\n ) => void;\n};\n\nfunction blockNavigation(event: MouseEvent) {\n event.preventDefault();\n event.stopPropagation();\n event.stopImmediatePropagation();\n}\n\nfunction isNavigationLike(value: unknown): value is NavigationLike {\n if (typeof value !== \"object\" || value === null) {\n return false;\n }\n\n return (\n typeof Reflect.get(value, \"addEventListener\") === \"function\" &&\n typeof Reflect.get(value, \"removeEventListener\") === \"function\"\n );\n}\n\nfunction getWindowNavigation() {\n const navigation = Reflect.get(window, \"navigation\");\n return isNavigationLike(navigation) ? navigation : null;\n}\n\nfunction shouldInterceptNavigationForAgentPreview() {\n if (typeof window === \"undefined\") {\n return false;\n }\n\n if (window.parent === window) {\n return false;\n }\n\n return (\n new URLSearchParams(window.location.search).get(\"__reploAgentPreview\") ===\n \"1\"\n );\n}\n\nfunction
|
|
5
|
-
"mappings": ";AAEA,SAAS,iBAAiB;AAE1B,SAAS,wBAAwB;
|
|
4
|
+
"sourcesContent": ["\"use client\";\n\nimport { useEffect } from \"react\";\n\nimport { displayModeStore } from \"./select-mode/displayModeStore\";\n\ntype NavigationNavigateEvent = {\n destination?: { url?: string };\n preventDefault?: () => void;\n};\n\ntype NavigationLike = {\n addEventListener: (\n type: \"navigate\",\n listener: (event: NavigationNavigateEvent) => void,\n ) => void;\n removeEventListener: (\n type: \"navigate\",\n listener: (event: NavigationNavigateEvent) => void,\n ) => void;\n};\n\n// NOTE (Max, 2026-08-26): Shared by name with @replohq/sdk's `navigateExternal`\n// (packages/sdk/lib/external-navigation.ts) rather than by import \u2014 the two\n// packages publish independently and must not depend on each other.\nconst EXTERNAL_NAVIGATION_HANDLER_KEY = \"__reploExternalNavigationHandler\";\n\nfunction blockNavigation(event: MouseEvent) {\n event.preventDefault();\n event.stopPropagation();\n event.stopImmediatePropagation();\n}\n\nfunction isNavigationLike(value: unknown): value is NavigationLike {\n if (typeof value !== \"object\" || value === null) {\n return false;\n }\n\n return (\n typeof Reflect.get(value, \"addEventListener\") === \"function\" &&\n typeof Reflect.get(value, \"removeEventListener\") === \"function\"\n );\n}\n\nfunction getWindowNavigation() {\n const navigation = Reflect.get(window, \"navigation\");\n return isNavigationLike(navigation) ? navigation : null;\n}\n\nfunction shouldInterceptNavigationForAgentPreview() {\n if (typeof window === \"undefined\") {\n return false;\n }\n\n if (window.parent === window) {\n return false;\n }\n\n return (\n new URLSearchParams(window.location.search).get(\"__reploAgentPreview\") ===\n \"1\"\n );\n}\n\nfunction resolveUrl(rawUrl: string | URL): URL | null {\n try {\n return new URL(\n typeof rawUrl === \"string\" ? rawUrl : rawUrl.href,\n window.location.href,\n );\n } catch {\n return null;\n }\n}\n\nfunction urlLeavesSandbox(rawUrl: string | URL): boolean | null {\n const resolved = resolveUrl(rawUrl);\n return resolved === null ? null : resolved.origin !== window.location.origin;\n}\n\nexport default function LinkInterceptor() {\n // eslint-disable-next-line replo/no-use-effect -- Browser navigation APIs must be patched at client runtime and restored when the interceptor unmounts.\n useEffect(() => {\n if (!shouldInterceptNavigationForAgentPreview()) {\n return;\n }\n\n const originalWindowOpen = window.open;\n const originalPushState = history.pushState;\n const originalReplaceState = history.replaceState;\n const navigation = getWindowNavigation();\n\n // Tell the parent editor where the site's own navigation went so it can\n // keep its URL, page list, and select-mode in sync without reloading the\n // iframe. A fact, not a request: it is only sent once a navigation is\n // actually happening.\n const reportNavigated = (rawUrl: string | URL) => {\n window.parent.postMessage(\n {\n type: \"replo:navigated\",\n route: resolveUrl(rawUrl)?.pathname ?? String(rawUrl),\n },\n \"*\",\n );\n };\n\n // A navigation that leaves the sandbox cannot happen in place: checkout\n // providers refuse to be framed and the iframe has no `allow-popups`. Hand\n // the destination to the editor, which opens it in a real browser tab.\n const openInParent = (rawUrl: string | URL) => {\n const resolved = resolveUrl(rawUrl);\n if (!resolved) {\n return;\n }\n window.parent.postMessage(\n {\n type: \"replo:open-external\",\n url: resolved.toString(),\n },\n \"*\",\n );\n };\n\n Reflect.set(window, EXTERNAL_NAVIGATION_HANDLER_KEY, (url: string) => {\n openInParent(url);\n return true;\n });\n\n window.open = function (\n url?: string | URL,\n target?: string,\n features?: string,\n ) {\n if (url !== undefined && url !== \"\" && urlLeavesSandbox(url) === true) {\n openInParent(url);\n return null;\n }\n\n return originalWindowOpen.call(window, url, target, features);\n };\n\n // The history patches are where client-side navigations are reported:\n // next/link cancels its click and routes through pushState, so the click\n // handler below cannot know whether the site actually navigated \u2014 these\n // patches fire exactly when it did (link clicks and programmatic\n // router.push/redirects alike).\n history.pushState = function (\n state: Parameters<History[\"pushState\"]>[0],\n unused: string,\n url?: string | URL | null,\n ) {\n if (url && urlLeavesSandbox(url) === true) {\n return;\n }\n\n const result = originalPushState.call(history, state, unused, url);\n if (url) {\n reportNavigated(url);\n }\n return result;\n };\n\n history.replaceState = function (\n state: Parameters<History[\"replaceState\"]>[0],\n unused: string,\n url?: string | URL | null,\n ) {\n if (url && urlLeavesSandbox(url) === true) {\n return;\n }\n\n const result = originalReplaceState.call(history, state, unused, url);\n if (url) {\n reportNavigated(url);\n }\n return result;\n };\n\n const handleNavigate = (event: NavigationNavigateEvent) => {\n const destinationUrl = event.destination?.url;\n if (\n destinationUrl === undefined ||\n destinationUrl === \"\" ||\n urlLeavesSandbox(destinationUrl) !== true\n ) {\n return;\n }\n\n event.preventDefault?.();\n openInParent(destinationUrl);\n };\n\n const handleClick = (event: MouseEvent) => {\n // While select mode is active a link click must select the element, not\n // navigate. `useSelectionInteractions` prevents the default nav, but this\n // sibling capture listener would still post `replo:navigate` and move the\n // preview off the page \u2014 `stopPropagation` there can't suppress a\n // listener on the same node, so we bail out here explicitly.\n if (displayModeStore.getSnapshot() === \"selection\") {\n return;\n }\n\n const target = event.target;\n\n if (!(target instanceof Element)) {\n return;\n }\n\n const link = target.closest(\"a[href]\");\n\n if (!(link instanceof HTMLAnchorElement)) {\n return;\n }\n\n const href = link.getAttribute(\"href\");\n if (!href) {\n return;\n }\n\n if (href.startsWith(\"#\")) {\n return;\n }\n\n const linkTarget = link.getAttribute(\"target\");\n if (linkTarget && linkTarget !== \"_self\") {\n blockNavigation(event);\n openInParent(href);\n return;\n }\n\n if (urlLeavesSandbox(href) === true) {\n blockNavigation(event);\n openInParent(href);\n return;\n }\n\n // A modified click (new tab / etc.) is the browser's to handle \u2014 the\n // iframe sandbox has no `allow-popups`, so it can't escape anyway.\n // Don't hijack it or tell the parent we navigated.\n if (\n event.button !== 0 ||\n event.metaKey ||\n event.ctrlKey ||\n event.shiftKey ||\n event.altKey\n ) {\n return;\n }\n\n // A download link never navigates, so there is nothing to report.\n if (link.hasAttribute(\"download\")) {\n return;\n }\n\n // Let the site navigate itself \u2014 next/link does an instant client-side\n // transition, exactly like a normal Next.js app \u2014 instead of cancelling\n // the click and making the parent editor tear down and reload the whole\n // preview iframe. next/link navigations are reported by the pushState\n // patch above; this deferred report covers plain anchors the browser\n // itself navigates (a full document load inside the iframe). Deferred a\n // microtask because this capture listener runs before the site's own\n // handlers: a cancelled click (next/link included) navigates nothing.\n queueMicrotask(() => {\n if (event.defaultPrevented) {\n return;\n }\n reportNavigated(href);\n });\n };\n\n navigation?.addEventListener(\"navigate\", handleNavigate);\n document.addEventListener(\"click\", handleClick, true);\n\n return () => {\n Reflect.deleteProperty(window, EXTERNAL_NAVIGATION_HANDLER_KEY);\n window.open = originalWindowOpen;\n history.pushState = originalPushState;\n history.replaceState = originalReplaceState;\n navigation?.removeEventListener(\"navigate\", handleNavigate);\n document.removeEventListener(\"click\", handleClick, true);\n };\n }, []);\n\n return null;\n}\n"],
|
|
5
|
+
"mappings": ";AAEA,SAAS,iBAAiB;AAE1B,SAAS,wBAAwB;AAqBjC,MAAM,kCAAkC;AAExC,SAAS,gBAAgB,OAAmB;AAC1C,QAAM,eAAe;AACrB,QAAM,gBAAgB;AACtB,QAAM,yBAAyB;AACjC;AAEA,SAAS,iBAAiB,OAAyC;AACjE,MAAI,OAAO,UAAU,YAAY,UAAU,MAAM;AAC/C,WAAO;AAAA,EACT;AAEA,SACE,OAAO,QAAQ,IAAI,OAAO,kBAAkB,MAAM,cAClD,OAAO,QAAQ,IAAI,OAAO,qBAAqB,MAAM;AAEzD;AAEA,SAAS,sBAAsB;AAC7B,QAAM,aAAa,QAAQ,IAAI,QAAQ,YAAY;AACnD,SAAO,iBAAiB,UAAU,IAAI,aAAa;AACrD;AAEA,SAAS,2CAA2C;AAClD,MAAI,OAAO,WAAW,aAAa;AACjC,WAAO;AAAA,EACT;AAEA,MAAI,OAAO,WAAW,QAAQ;AAC5B,WAAO;AAAA,EACT;AAEA,SACE,IAAI,gBAAgB,OAAO,SAAS,MAAM,EAAE,IAAI,qBAAqB,MACrE;AAEJ;AAEA,SAAS,WAAW,QAAkC;AACpD,MAAI;AACF,WAAO,IAAI;AAAA,MACT,OAAO,WAAW,WAAW,SAAS,OAAO;AAAA,MAC7C,OAAO,SAAS;AAAA,IAClB;AAAA,EACF,QAAQ;AACN,WAAO;AAAA,EACT;AACF;AAEA,SAAS,iBAAiB,QAAsC;AAC9D,QAAM,WAAW,WAAW,MAAM;AAClC,SAAO,aAAa,OAAO,OAAO,SAAS,WAAW,OAAO,SAAS;AACxE;AAEe,SAAR,kBAAmC;AAExC,YAAU,MAAM;AACd,QAAI,CAAC,yCAAyC,GAAG;AAC/C;AAAA,IACF;AAEA,UAAM,qBAAqB,OAAO;AAClC,UAAM,oBAAoB,QAAQ;AAClC,UAAM,uBAAuB,QAAQ;AACrC,UAAM,aAAa,oBAAoB;AAMvC,UAAM,kBAAkB,CAAC,WAAyB;AAChD,aAAO,OAAO;AAAA,QACZ;AAAA,UACE,MAAM;AAAA,UACN,OAAO,WAAW,MAAM,GAAG,YAAY,OAAO,MAAM;AAAA,QACtD;AAAA,QACA;AAAA,MACF;AAAA,IACF;AAKA,UAAM,eAAe,CAAC,WAAyB;AAC7C,YAAM,WAAW,WAAW,MAAM;AAClC,UAAI,CAAC,UAAU;AACb;AAAA,MACF;AACA,aAAO,OAAO;AAAA,QACZ;AAAA,UACE,MAAM;AAAA,UACN,KAAK,SAAS,SAAS;AAAA,QACzB;AAAA,QACA;AAAA,MACF;AAAA,IACF;AAEA,YAAQ,IAAI,QAAQ,iCAAiC,CAAC,QAAgB;AACpE,mBAAa,GAAG;AAChB,aAAO;AAAA,IACT,CAAC;AAED,WAAO,OAAO,SACZ,KACA,QACA,UACA;AACA,UAAI,QAAQ,UAAa,QAAQ,MAAM,iBAAiB,GAAG,MAAM,MAAM;AACrE,qBAAa,GAAG;AAChB,eAAO;AAAA,MACT;AAEA,aAAO,mBAAmB,KAAK,QAAQ,KAAK,QAAQ,QAAQ;AAAA,IAC9D;AAOA,YAAQ,YAAY,SAClB,OACA,QACA,KACA;AACA,UAAI,OAAO,iBAAiB,GAAG,MAAM,MAAM;AACzC;AAAA,MACF;AAEA,YAAM,SAAS,kBAAkB,KAAK,SAAS,OAAO,QAAQ,GAAG;AACjE,UAAI,KAAK;AACP,wBAAgB,GAAG;AAAA,MACrB;AACA,aAAO;AAAA,IACT;AAEA,YAAQ,eAAe,SACrB,OACA,QACA,KACA;AACA,UAAI,OAAO,iBAAiB,GAAG,MAAM,MAAM;AACzC;AAAA,MACF;AAEA,YAAM,SAAS,qBAAqB,KAAK,SAAS,OAAO,QAAQ,GAAG;AACpE,UAAI,KAAK;AACP,wBAAgB,GAAG;AAAA,MACrB;AACA,aAAO;AAAA,IACT;AAEA,UAAM,iBAAiB,CAAC,UAAmC;AACzD,YAAM,iBAAiB,MAAM,aAAa;AAC1C,UACE,mBAAmB,UACnB,mBAAmB,MACnB,iBAAiB,cAAc,MAAM,MACrC;AACA;AAAA,MACF;AAEA,YAAM,iBAAiB;AACvB,mBAAa,cAAc;AAAA,IAC7B;AAEA,UAAM,cAAc,CAAC,UAAsB;AAMzC,UAAI,iBAAiB,YAAY,MAAM,aAAa;AAClD;AAAA,MACF;AAEA,YAAM,SAAS,MAAM;AAErB,UAAI,EAAE,kBAAkB,UAAU;AAChC;AAAA,MACF;AAEA,YAAM,OAAO,OAAO,QAAQ,SAAS;AAErC,UAAI,EAAE,gBAAgB,oBAAoB;AACxC;AAAA,MACF;AAEA,YAAM,OAAO,KAAK,aAAa,MAAM;AACrC,UAAI,CAAC,MAAM;AACT;AAAA,MACF;AAEA,UAAI,KAAK,WAAW,GAAG,GAAG;AACxB;AAAA,MACF;AAEA,YAAM,aAAa,KAAK,aAAa,QAAQ;AAC7C,UAAI,cAAc,eAAe,SAAS;AACxC,wBAAgB,KAAK;AACrB,qBAAa,IAAI;AACjB;AAAA,MACF;AAEA,UAAI,iBAAiB,IAAI,MAAM,MAAM;AACnC,wBAAgB,KAAK;AACrB,qBAAa,IAAI;AACjB;AAAA,MACF;AAKA,UACE,MAAM,WAAW,KACjB,MAAM,WACN,MAAM,WACN,MAAM,YACN,MAAM,QACN;AACA;AAAA,MACF;AAGA,UAAI,KAAK,aAAa,UAAU,GAAG;AACjC;AAAA,MACF;AAUA,qBAAe,MAAM;AACnB,YAAI,MAAM,kBAAkB;AAC1B;AAAA,QACF;AACA,wBAAgB,IAAI;AAAA,MACtB,CAAC;AAAA,IACH;AAEA,gBAAY,iBAAiB,YAAY,cAAc;AACvD,aAAS,iBAAiB,SAAS,aAAa,IAAI;AAEpD,WAAO,MAAM;AACX,cAAQ,eAAe,QAAQ,+BAA+B;AAC9D,aAAO,OAAO;AACd,cAAQ,YAAY;AACpB,cAAQ,eAAe;AACvB,kBAAY,oBAAoB,YAAY,cAAc;AAC1D,eAAS,oBAAoB,SAAS,aAAa,IAAI;AAAA,IACzD;AAAA,EACF,GAAG,CAAC,CAAC;AAEL,SAAO;AACT;",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|
|
@@ -19,6 +19,8 @@ var DATA_LOADER_KEYS = {
|
|
|
19
19
|
YOTPO_PRODUCT_REVIEW_AGGREGATE: "yotpo.product_review_aggregate",
|
|
20
20
|
REVIEWS_IO_PRODUCT_REVIEWS: "reviews_io.product_reviews",
|
|
21
21
|
REVIEWS_IO_PRODUCT_REVIEW_AGGREGATE: "reviews_io.product_review_aggregate",
|
|
22
|
+
LOOX_PRODUCT_REVIEWS: "loox.product_reviews",
|
|
23
|
+
LOOX_PRODUCT_REVIEW_AGGREGATE: "loox.product_review_aggregate",
|
|
22
24
|
STATSIG_EXPERIMENT: "statsig.experiment",
|
|
23
25
|
CONTENTFUL_ENTRY: "contentful.entry",
|
|
24
26
|
CONTENTFUL_ENTRIES: "contentful.entries"
|
|
@@ -28,6 +28,8 @@ export declare const DATA_LOADER_KEYS: {
|
|
|
28
28
|
readonly YOTPO_PRODUCT_REVIEW_AGGREGATE: "yotpo.product_review_aggregate";
|
|
29
29
|
readonly REVIEWS_IO_PRODUCT_REVIEWS: "reviews_io.product_reviews";
|
|
30
30
|
readonly REVIEWS_IO_PRODUCT_REVIEW_AGGREGATE: "reviews_io.product_review_aggregate";
|
|
31
|
+
readonly LOOX_PRODUCT_REVIEWS: "loox.product_reviews";
|
|
32
|
+
readonly LOOX_PRODUCT_REVIEW_AGGREGATE: "loox.product_review_aggregate";
|
|
31
33
|
readonly STATSIG_EXPERIMENT: "statsig.experiment";
|
|
32
34
|
readonly CONTENTFUL_ENTRY: "contentful.entry";
|
|
33
35
|
readonly CONTENTFUL_ENTRIES: "contentful.entries";
|
|
@@ -51,6 +53,8 @@ export declare const dataLoaderKeySchema: z.ZodEnum<{
|
|
|
51
53
|
"yotpo.product_review_aggregate": "yotpo.product_review_aggregate";
|
|
52
54
|
"reviews_io.product_reviews": "reviews_io.product_reviews";
|
|
53
55
|
"reviews_io.product_review_aggregate": "reviews_io.product_review_aggregate";
|
|
56
|
+
"loox.product_reviews": "loox.product_reviews";
|
|
57
|
+
"loox.product_review_aggregate": "loox.product_review_aggregate";
|
|
54
58
|
"statsig.experiment": "statsig.experiment";
|
|
55
59
|
"contentful.entry": "contentful.entry";
|
|
56
60
|
"contentful.entries": "contentful.entries";
|
package/buildMetadata.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
export const BUILD_METADATA = {
|
|
2
2
|
"packageName": "@replohq/sandbox-runtime",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.4.0",
|
|
4
4
|
"branch": "HEAD",
|
|
5
|
-
"commit": "
|
|
6
|
-
"builtAt": "2026-08-
|
|
5
|
+
"commit": "24d52db6a49bcade4693ce801896805675d114fe",
|
|
6
|
+
"builtAt": "2026-08-27T00:53:21.140Z"
|
|
7
7
|
};
|
package/package.json
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@replohq/sandbox-runtime",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.4.0",
|
|
4
4
|
"reploBuild": {
|
|
5
5
|
"packageName": "@replohq/sandbox-runtime",
|
|
6
|
-
"version": "1.
|
|
6
|
+
"version": "1.4.0",
|
|
7
7
|
"branch": "HEAD",
|
|
8
|
-
"commit": "
|
|
9
|
-
"builtAt": "2026-08-
|
|
8
|
+
"commit": "24d52db6a49bcade4693ce801896805675d114fe",
|
|
9
|
+
"builtAt": "2026-08-27T00:53:21.140Z"
|
|
10
10
|
},
|
|
11
11
|
"description": "Replo sandbox runtime — editor integration for agent-built Next.js sites.",
|
|
12
12
|
"license": "SEE LICENSE IN LICENSE",
|