@replohq/sandbox-runtime 0.2.0 → 1.0.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 (51) hide show
  1. package/_vendor/schemas/componentPreview.d.ts +68 -0
  2. package/_vendor/schemas/componentPreview.mjs +97 -0
  3. package/_vendor/schemas/generated/componentPreview.d.ts +30 -0
  4. package/_vendor/schemas/generated/componentPreview.mjs +1 -0
  5. package/_vendor/schemas/generated/selectModeIframeRpc.d.ts +8 -0
  6. package/_vendor/schemas/loaderKeys.d.ts +57 -0
  7. package/_vendor/schemas/selectModeIframeRpc.d.ts +21 -1
  8. package/_vendor/schemas/selectModeIframeRpc.mjs +11 -3
  9. package/buildMetadata.d.ts +9 -0
  10. package/buildMetadata.js +7 -0
  11. package/buildMetadata.js.map +7 -0
  12. package/next/component-preview-href.d.ts +5 -0
  13. package/next/component-preview-href.js +14 -0
  14. package/next/component-preview-href.js.map +7 -0
  15. package/next/component-preview-navigation.d.ts +1 -0
  16. package/next/component-preview-navigation.js +66 -0
  17. package/next/component-preview-navigation.js.map +7 -0
  18. package/next/component-preview.d.ts +4 -1
  19. package/next/component-preview.js +49 -14
  20. package/next/component-preview.js.map +2 -2
  21. package/package.json +12 -5
  22. package/select-mode/EditorSelection.js +8 -2
  23. package/select-mode/EditorSelection.js.map +2 -2
  24. package/select-mode/fiber.d.ts +12 -17
  25. package/select-mode/fiber.js +228 -64
  26. package/select-mode/fiber.js.map +2 -2
  27. package/select-mode/hooks/useEditModeStateMachine.js +2 -0
  28. package/select-mode/hooks/useEditModeStateMachine.js.map +2 -2
  29. package/select-mode/hooks/useOptimisticOverrides.js +2 -2
  30. package/select-mode/hooks/useOptimisticOverrides.js.map +2 -2
  31. package/select-mode/hooks/useParentMessaging.js +21 -1
  32. package/select-mode/hooks/useParentMessaging.js.map +2 -2
  33. package/select-mode/hooks/useSelectModeController.js +2 -0
  34. package/select-mode/hooks/useSelectModeController.js.map +2 -2
  35. package/select-mode/hooks/useSelectionHover.d.ts +4 -5
  36. package/select-mode/hooks/useSelectionHover.js +21 -3
  37. package/select-mode/hooks/useSelectionHover.js.map +2 -2
  38. package/select-mode/hooks/useSelectionInteractions.js +12 -11
  39. package/select-mode/hooks/useSelectionInteractions.js.map +2 -2
  40. package/select-mode/hooks/useSelectionScrollSync.d.ts +3 -4
  41. package/select-mode/hooks/useSelectionScrollSync.js +4 -9
  42. package/select-mode/hooks/useSelectionScrollSync.js.map +2 -2
  43. package/select-mode/hooks/useSiblingResolution.d.ts +2 -2
  44. package/select-mode/hooks/useSiblingResolution.js +10 -47
  45. package/select-mode/hooks/useSiblingResolution.js.map +2 -2
  46. package/select-mode/iframeRpcChannel.d.ts +7 -1
  47. package/select-mode/selectModeSession.d.ts +1 -0
  48. package/select-mode/selectModeSession.js.map +2 -2
  49. package/select-mode/selectionFrame.d.ts +13 -17
  50. package/select-mode/selectionFrame.js +18 -5
  51. package/select-mode/selectionFrame.js.map +2 -2
@@ -0,0 +1,68 @@
1
+ import { z } from "zod";
2
+ export declare const MAX_COMPONENT_PREVIEW_PROPS_BYTES: number;
3
+ export declare const componentPreviewPropNameSchema: z.ZodString;
4
+ export declare const componentPreviewPropsSchema: z.ZodRecord<z.ZodString, z.ZodJSONSchema>;
5
+ export declare const COMPONENT_PREVIEW_IFRAME_RPC_CHANNEL_ID: "replo:component-preview-iframe-rpc";
6
+ export declare const COMPONENT_PREVIEW_IFRAME_RPC_CHANNEL_VERSION: 1;
7
+ export declare const websiteBuilderToComponentPreviewMethodConfig: {
8
+ setProps: {
9
+ inputSchema: z.ZodObject<{
10
+ props: z.ZodRecord<z.ZodString, z.ZodJSONSchema>;
11
+ sourceRevision: z.ZodString;
12
+ }, z.core.$strip>;
13
+ outputSchema: z.ZodVoid;
14
+ };
15
+ };
16
+ export declare const componentPreviewToWebsiteBuilderMethodConfig: {
17
+ iframeReady: {
18
+ inputSchema: z.ZodUndefined;
19
+ outputSchema: z.ZodVoid;
20
+ };
21
+ };
22
+ export declare const componentPreviewProductReferenceSchema: z.ZodObject<{
23
+ type: z.ZodLiteral<"product">;
24
+ loaderKey: z.ZodEnum<{
25
+ "shopify_storefront.product": "shopify_storefront.product";
26
+ "replo_products.product": "replo_products.product";
27
+ }>;
28
+ productId: z.ZodString;
29
+ }, z.core.$strict>;
30
+ export declare const componentPreviewPathSchema: z.ZodString;
31
+ export declare const componentPreviewSelectionSchema: z.ZodObject<{
32
+ siteId: z.ZodUUID;
33
+ componentPath: z.ZodString;
34
+ }, z.core.$strip>;
35
+ export declare const componentPreviewComponentSchema: z.ZodObject<{
36
+ path: z.ZodString;
37
+ name: z.ZodString;
38
+ }, z.core.$strip>;
39
+ export declare const componentPreviewIndexSchema: z.ZodDiscriminatedUnion<[z.ZodObject<{
40
+ status: z.ZodLiteral<"unavailable">;
41
+ }, z.core.$strip>, z.ZodObject<{
42
+ status: z.ZodLiteral<"ready">;
43
+ components: z.ZodArray<z.ZodObject<{
44
+ path: z.ZodString;
45
+ name: z.ZodString;
46
+ }, z.core.$strip>>;
47
+ }, z.core.$strip>], "status">;
48
+ export declare const componentPreviewSourceFileSchema: z.ZodObject<{
49
+ path: z.ZodString;
50
+ content: z.ZodString;
51
+ }, z.core.$strip>;
52
+ export declare const componentPreviewSourceSchema: z.ZodObject<{
53
+ component: z.ZodObject<{
54
+ path: z.ZodString;
55
+ name: z.ZodString;
56
+ }, z.core.$strip>;
57
+ files: z.ZodArray<z.ZodObject<{
58
+ path: z.ZodString;
59
+ content: z.ZodString;
60
+ }, z.core.$strip>>;
61
+ revision: z.ZodString;
62
+ }, z.core.$strip>;
63
+ export declare const componentPreviewPreparationSchema: z.ZodDiscriminatedUnion<[z.ZodObject<{
64
+ status: z.ZodLiteral<"ready">;
65
+ pathname: z.ZodString;
66
+ }, z.core.$strip>, z.ZodObject<{
67
+ status: z.ZodLiteral<"siteUpdateRequired">;
68
+ }, z.core.$strip>], "status">;
@@ -0,0 +1,97 @@
1
+ import { z } from 'zod';
2
+
3
+ // ../schemas/componentPreview.ts
4
+ var DATA_LOADER_KEYS = {
5
+ SHOPIFY_PRODUCT: "shopify_storefront.product",
6
+ SHOPIFY_COLLECTION: "shopify_storefront.collection",
7
+ SHOPIFY_COLLECTION_PRODUCTS: "shopify_storefront.collection_products",
8
+ SHOPIFY_METAOBJECT: "shopify_storefront.metaobject",
9
+ SHOPIFY_METAOBJECTS: "shopify_storefront.metaobjects",
10
+ REPLO_PRODUCT: "replo_products.product",
11
+ OKENDO_PRODUCT_REVIEWS: "okendo.product_reviews",
12
+ OKENDO_PRODUCT_REVIEW_AGGREGATE: "okendo.product_review_aggregate",
13
+ REBUY_RECOMMENDATIONS: "rebuy.recommendations",
14
+ LEVANTA_PRODUCT: "levanta_products.product",
15
+ SMILE_IO_VIP_TIERS: "smile_io.vip_tiers",
16
+ SMILE_IO_EARNING_RULES: "smile_io.earning_rules",
17
+ SMILE_IO_REWARDS: "smile_io.rewards",
18
+ YOTPO_PRODUCT_REVIEWS: "yotpo.product_reviews",
19
+ YOTPO_PRODUCT_REVIEW_AGGREGATE: "yotpo.product_review_aggregate",
20
+ REVIEWS_IO_PRODUCT_REVIEWS: "reviews_io.product_reviews",
21
+ REVIEWS_IO_PRODUCT_REVIEW_AGGREGATE: "reviews_io.product_review_aggregate",
22
+ STATSIG_EXPERIMENT: "statsig.experiment",
23
+ CONTENTFUL_ENTRY: "contentful.entry",
24
+ CONTENTFUL_ENTRIES: "contentful.entries"
25
+ };
26
+ z.enum(Object.values(DATA_LOADER_KEYS));
27
+
28
+ // ../schemas/componentPreview.ts
29
+ var MAX_COMPONENT_PREVIEW_PROPS_BYTES = 16 * 1024;
30
+ var componentPreviewPropNameSchema = z.string().min(1).max(80).regex(/^[A-Za-z_$][\w$]*$/u).refine((name) => {
31
+ return !["__proto__", "constructor", "dangerouslySetInnerHTML"].includes(
32
+ name
33
+ );
34
+ }, "Unsafe prop name");
35
+ var componentPreviewPropsSchema = z.record(z.string(), z.json());
36
+ var COMPONENT_PREVIEW_IFRAME_RPC_CHANNEL_ID = "replo:component-preview-iframe-rpc";
37
+ var COMPONENT_PREVIEW_IFRAME_RPC_CHANNEL_VERSION = 1;
38
+ var websiteBuilderToComponentPreviewMethodConfig = {
39
+ setProps: {
40
+ inputSchema: z.object({
41
+ props: componentPreviewPropsSchema,
42
+ sourceRevision: z.string().min(1)
43
+ }),
44
+ outputSchema: z.void()
45
+ }
46
+ };
47
+ var componentPreviewToWebsiteBuilderMethodConfig = {
48
+ iframeReady: {
49
+ inputSchema: z.undefined(),
50
+ outputSchema: z.void()
51
+ }
52
+ };
53
+ var componentPreviewProductReferenceSchema = z.object({
54
+ type: z.literal("product"),
55
+ loaderKey: z.enum([
56
+ DATA_LOADER_KEYS.SHOPIFY_PRODUCT,
57
+ DATA_LOADER_KEYS.REPLO_PRODUCT
58
+ ]),
59
+ productId: z.string().min(1)
60
+ }).strict().describe("ComponentPreviewProductReference");
61
+ var componentPreviewPathSchema = z.string().regex(
62
+ /^components\/[\w$.-]+\.tsx$/u,
63
+ "Component paths must be top-level TSX files in components/"
64
+ );
65
+ var componentPreviewSelectionSchema = z.object({
66
+ siteId: z.uuid(),
67
+ componentPath: componentPreviewPathSchema
68
+ });
69
+ var componentPreviewComponentSchema = z.object({
70
+ path: componentPreviewPathSchema,
71
+ name: z.string().min(1).max(120)
72
+ }).describe("ComponentPreviewComponent");
73
+ var componentPreviewIndexSchema = z.discriminatedUnion("status", [
74
+ z.object({ status: z.literal("unavailable") }),
75
+ z.object({
76
+ status: z.literal("ready"),
77
+ components: z.array(componentPreviewComponentSchema)
78
+ })
79
+ ]).describe("ComponentPreviewIndex");
80
+ var componentPreviewSourceFileSchema = z.object({
81
+ path: z.string().min(1),
82
+ content: z.string()
83
+ }).describe("ComponentPreviewSourceFile");
84
+ var componentPreviewSourceSchema = z.object({
85
+ component: componentPreviewComponentSchema,
86
+ files: z.array(componentPreviewSourceFileSchema),
87
+ revision: z.string().min(1)
88
+ }).describe("ComponentPreviewSource");
89
+ var componentPreviewPreparationSchema = z.discriminatedUnion("status", [
90
+ z.object({
91
+ status: z.literal("ready"),
92
+ pathname: z.string().regex(/^\/[A-Za-z0-9/_-]+$/u)
93
+ }),
94
+ z.object({ status: z.literal("siteUpdateRequired") })
95
+ ]).describe("ComponentPreviewPreparation");
96
+
97
+ export { COMPONENT_PREVIEW_IFRAME_RPC_CHANNEL_ID, COMPONENT_PREVIEW_IFRAME_RPC_CHANNEL_VERSION, MAX_COMPONENT_PREVIEW_PROPS_BYTES, componentPreviewComponentSchema, componentPreviewIndexSchema, componentPreviewPathSchema, componentPreviewPreparationSchema, componentPreviewProductReferenceSchema, componentPreviewPropNameSchema, componentPreviewPropsSchema, componentPreviewSelectionSchema, componentPreviewSourceFileSchema, componentPreviewSourceSchema, componentPreviewToWebsiteBuilderMethodConfig, websiteBuilderToComponentPreviewMethodConfig };
@@ -0,0 +1,30 @@
1
+ export type ComponentPreviewComponent = {
2
+ path: string;
3
+ name: string;
4
+ };
5
+ export type ComponentPreviewProductReference = {
6
+ type: "product";
7
+ loaderKey: "shopify_storefront.product" | "replo_products.product";
8
+ productId: string;
9
+ };
10
+ export type ComponentPreviewIndex = {
11
+ status: "unavailable";
12
+ } | {
13
+ status: "ready";
14
+ components: ComponentPreviewComponent[];
15
+ };
16
+ export type ComponentPreviewSourceFile = {
17
+ path: string;
18
+ content: string;
19
+ };
20
+ export type ComponentPreviewSource = {
21
+ component: ComponentPreviewComponent;
22
+ files: ComponentPreviewSourceFile[];
23
+ revision: string;
24
+ };
25
+ export type ComponentPreviewPreparation = {
26
+ status: "ready";
27
+ pathname: string;
28
+ } | {
29
+ status: "siteUpdateRequired";
30
+ };
@@ -1,4 +1,11 @@
1
1
  import type { DisplayMode, SelectModeSelectionType, SelectModeOptimisticUpdatePayload, SelectModeFormatCommand, SelectableData, SelectModeBoundingRect, SelectModeClickPosition, SelectModeSelectionRect, SelectModeTiptapActiveMarks } from "./selectMode";
2
+ export type IframeRuntimeBuildMetadata = {
3
+ packageName: string;
4
+ version: string;
5
+ branch: string | null;
6
+ commit: string | null;
7
+ builtAt: string | null;
8
+ };
2
9
  export type SelectModeParentMessage = {
3
10
  method: "setDisplayMode";
4
11
  data: {
@@ -46,6 +53,7 @@ export type SelectModeParentMessage = {
46
53
  };
47
54
  export type SelectModeIframeMessage = {
48
55
  method: "iframeReady";
56
+ data?: IframeRuntimeBuildMetadata;
49
57
  } | {
50
58
  method: "elementSelected";
51
59
  data: {
@@ -0,0 +1,57 @@
1
+ import { z } from "zod";
2
+ /**
3
+ * Shared data-loader key constants. Both the integration registry and the
4
+ * dependency resolver import from here so the strings are never duplicated.
5
+ *
6
+ * These keys serve double duty: they identify which backend loader to invoke
7
+ * AND are used as React Query cache key prefixes. Loader components
8
+ * internally construct queryKey as `[loaderKey, args]`.
9
+ *
10
+ * Naming convention: `<integration>.<objectType>` or
11
+ * `<integration>.<objectType>_<qualifier>`.
12
+ */
13
+ export declare const DATA_LOADER_KEYS: {
14
+ readonly SHOPIFY_PRODUCT: "shopify_storefront.product";
15
+ readonly SHOPIFY_COLLECTION: "shopify_storefront.collection";
16
+ readonly SHOPIFY_COLLECTION_PRODUCTS: "shopify_storefront.collection_products";
17
+ readonly SHOPIFY_METAOBJECT: "shopify_storefront.metaobject";
18
+ readonly SHOPIFY_METAOBJECTS: "shopify_storefront.metaobjects";
19
+ readonly REPLO_PRODUCT: "replo_products.product";
20
+ readonly OKENDO_PRODUCT_REVIEWS: "okendo.product_reviews";
21
+ readonly OKENDO_PRODUCT_REVIEW_AGGREGATE: "okendo.product_review_aggregate";
22
+ readonly REBUY_RECOMMENDATIONS: "rebuy.recommendations";
23
+ readonly LEVANTA_PRODUCT: "levanta_products.product";
24
+ readonly SMILE_IO_VIP_TIERS: "smile_io.vip_tiers";
25
+ readonly SMILE_IO_EARNING_RULES: "smile_io.earning_rules";
26
+ readonly SMILE_IO_REWARDS: "smile_io.rewards";
27
+ readonly YOTPO_PRODUCT_REVIEWS: "yotpo.product_reviews";
28
+ readonly YOTPO_PRODUCT_REVIEW_AGGREGATE: "yotpo.product_review_aggregate";
29
+ readonly REVIEWS_IO_PRODUCT_REVIEWS: "reviews_io.product_reviews";
30
+ readonly REVIEWS_IO_PRODUCT_REVIEW_AGGREGATE: "reviews_io.product_review_aggregate";
31
+ readonly STATSIG_EXPERIMENT: "statsig.experiment";
32
+ readonly CONTENTFUL_ENTRY: "contentful.entry";
33
+ readonly CONTENTFUL_ENTRIES: "contentful.entries";
34
+ };
35
+ export type DataLoaderKey = (typeof DATA_LOADER_KEYS)[keyof typeof DATA_LOADER_KEYS];
36
+ export declare const dataLoaderKeySchema: z.ZodEnum<{
37
+ "shopify_storefront.product": "shopify_storefront.product";
38
+ "shopify_storefront.collection": "shopify_storefront.collection";
39
+ "shopify_storefront.collection_products": "shopify_storefront.collection_products";
40
+ "shopify_storefront.metaobject": "shopify_storefront.metaobject";
41
+ "shopify_storefront.metaobjects": "shopify_storefront.metaobjects";
42
+ "replo_products.product": "replo_products.product";
43
+ "okendo.product_reviews": "okendo.product_reviews";
44
+ "okendo.product_review_aggregate": "okendo.product_review_aggregate";
45
+ "rebuy.recommendations": "rebuy.recommendations";
46
+ "levanta_products.product": "levanta_products.product";
47
+ "smile_io.vip_tiers": "smile_io.vip_tiers";
48
+ "smile_io.earning_rules": "smile_io.earning_rules";
49
+ "smile_io.rewards": "smile_io.rewards";
50
+ "yotpo.product_reviews": "yotpo.product_reviews";
51
+ "yotpo.product_review_aggregate": "yotpo.product_review_aggregate";
52
+ "reviews_io.product_reviews": "reviews_io.product_reviews";
53
+ "reviews_io.product_review_aggregate": "reviews_io.product_review_aggregate";
54
+ "statsig.experiment": "statsig.experiment";
55
+ "contentful.entry": "contentful.entry";
56
+ "contentful.entries": "contentful.entries";
57
+ }>;
@@ -2,6 +2,13 @@ import type { SelectModeIframeMessage, SelectModeParentMessage } from "./generat
2
2
  import { z } from "zod";
3
3
  export declare const SELECT_MODE_IFRAME_RPC_CHANNEL_ID: "replo:select-mode-iframe-rpc";
4
4
  export declare const SELECT_MODE_IFRAME_RPC_CHANNEL_VERSION: 1;
5
+ export declare const iframeRuntimeBuildMetadataSchema: z.ZodObject<{
6
+ packageName: z.ZodString;
7
+ version: z.ZodString;
8
+ branch: z.ZodNullable<z.ZodString>;
9
+ commit: z.ZodNullable<z.ZodString>;
10
+ builtAt: z.ZodNullable<z.ZodString>;
11
+ }, z.core.$strip>;
5
12
  export declare const websiteBuilderToCanopyMethodConfig: {
6
13
  symbolicateSelectedElement: {
7
14
  inputSchema: z.ZodObject<{
@@ -280,7 +287,13 @@ export declare const canopyToWebsiteBuilderMethodConfig: {
280
287
  timeoutMs: number;
281
288
  };
282
289
  iframeReady: {
283
- inputSchema: z.ZodUndefined;
290
+ inputSchema: z.ZodOptional<z.ZodObject<{
291
+ packageName: z.ZodString;
292
+ version: z.ZodString;
293
+ branch: z.ZodNullable<z.ZodString>;
294
+ commit: z.ZodNullable<z.ZodString>;
295
+ builtAt: z.ZodNullable<z.ZodString>;
296
+ }, z.core.$strip>>;
284
297
  outputSchema: z.ZodVoid;
285
298
  };
286
299
  elementSelected: {
@@ -629,6 +642,13 @@ export declare const selectModeParentMessageSchema: z.ZodDiscriminatedUnion<[z.Z
629
642
  }, z.core.$strip>], "method">;
630
643
  export declare const selectModeIframeMessageSchema: z.ZodDiscriminatedUnion<[z.ZodObject<{
631
644
  method: z.ZodLiteral<"iframeReady">;
645
+ data: z.ZodOptional<z.ZodObject<{
646
+ packageName: z.ZodString;
647
+ version: z.ZodString;
648
+ branch: z.ZodNullable<z.ZodString>;
649
+ commit: z.ZodNullable<z.ZodString>;
650
+ builtAt: z.ZodNullable<z.ZodString>;
651
+ }, z.core.$strip>>;
632
652
  }, z.core.$strip>, z.ZodObject<{
633
653
  method: z.ZodLiteral<"elementSelected">;
634
654
  data: z.ZodObject<{
@@ -5,6 +5,13 @@ import { z } from 'zod';
5
5
 
6
6
  var SELECT_MODE_IFRAME_RPC_CHANNEL_ID = "replo:select-mode-iframe-rpc";
7
7
  var SELECT_MODE_IFRAME_RPC_CHANNEL_VERSION = 1;
8
+ var iframeRuntimeBuildMetadataSchema = z.object({
9
+ packageName: z.string(),
10
+ version: z.string(),
11
+ branch: z.string().nullable(),
12
+ commit: z.string().nullable(),
13
+ builtAt: z.string().nullable()
14
+ }).describe("IframeRuntimeBuildMetadata");
8
15
  var websiteBuilderToCanopyMethodConfig = {
9
16
  symbolicateSelectedElement: {
10
17
  inputSchema: selectedElementSchema,
@@ -78,7 +85,7 @@ var canopyToWebsiteBuilderMethodConfig = {
78
85
  timeoutMs: 5e3
79
86
  },
80
87
  iframeReady: {
81
- inputSchema: z.undefined(),
88
+ inputSchema: iframeRuntimeBuildMetadataSchema.optional(),
82
89
  outputSchema: z.void()
83
90
  },
84
91
  elementSelected: {
@@ -181,7 +188,8 @@ var selectModeParentMessageSchema = z.discriminatedUnion("method", [
181
188
  ]).describe("SelectModeParentMessage");
182
189
  var selectModeIframeMessageSchema = z.discriminatedUnion("method", [
183
190
  z.object({
184
- method: z.literal("iframeReady")
191
+ method: z.literal("iframeReady"),
192
+ data: iframeRuntimeBuildMetadataSchema.optional()
185
193
  }),
186
194
  z.object({
187
195
  method: z.literal("elementSelected"),
@@ -220,4 +228,4 @@ var selectModeIframeMessageSchema = z.discriminatedUnion("method", [
220
228
  })
221
229
  ]).describe("SelectModeIframeMessage");
222
230
 
223
- export { SELECT_MODE_IFRAME_RPC_CHANNEL_ID, SELECT_MODE_IFRAME_RPC_CHANNEL_VERSION, canopyToWebsiteBuilderMethodConfig, selectModeIframeMessageSchema, selectModeParentMessageSchema, websiteBuilderToCanopyMethodConfig };
231
+ export { SELECT_MODE_IFRAME_RPC_CHANNEL_ID, SELECT_MODE_IFRAME_RPC_CHANNEL_VERSION, canopyToWebsiteBuilderMethodConfig, iframeRuntimeBuildMetadataSchema, selectModeIframeMessageSchema, selectModeParentMessageSchema, websiteBuilderToCanopyMethodConfig };
@@ -0,0 +1,9 @@
1
+ type BuildMetadata = {
2
+ packageName: string;
3
+ version: string;
4
+ branch: string | null;
5
+ commit: string | null;
6
+ builtAt: string | null;
7
+ };
8
+ export declare const BUILD_METADATA: BuildMetadata;
9
+ export {};
@@ -0,0 +1,7 @@
1
+ export const BUILD_METADATA = {
2
+ "packageName": "@replohq/sandbox-runtime",
3
+ "version": "1.0.0",
4
+ "branch": "HEAD",
5
+ "commit": "1818d468bc1a4ba23ac3fad1b296eb8f2f94155c",
6
+ "builtAt": "2026-08-19T03:50:51.141Z"
7
+ };
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../buildMetadata.ts"],
4
+ "sourcesContent": ["type BuildMetadata = {\n packageName: string;\n version: string;\n branch: string | null;\n commit: string | null;\n builtAt: string | null;\n};\n\nexport const BUILD_METADATA: BuildMetadata = {\n packageName: \"@replohq/sandbox-runtime\",\n version: \"0.0.0-dev\",\n branch: null,\n commit: null,\n builtAt: null,\n};\n"],
5
+ "mappings": "AAQO,MAAM,iBAAgC;AAAA,EAC3C,aAAa;AAAA,EACb,SAAS;AAAA,EACT,QAAQ;AAAA,EACR,QAAQ;AAAA,EACR,SAAS;AACX;",
6
+ "names": []
7
+ }
@@ -0,0 +1,5 @@
1
+ export declare function getComponentPreviewHref({ currentUrl, props, sourceRevision, }: {
2
+ currentUrl: string;
3
+ props: Record<string, unknown>;
4
+ sourceRevision: string;
5
+ }): string;
@@ -0,0 +1,14 @@
1
+ function getComponentPreviewHref({
2
+ currentUrl,
3
+ props,
4
+ sourceRevision
5
+ }) {
6
+ const url = new URL(currentUrl);
7
+ url.searchParams.set("props", JSON.stringify(props));
8
+ url.searchParams.set("sourceRevision", sourceRevision);
9
+ return `${url.pathname}${url.search}${url.hash}`;
10
+ }
11
+ export {
12
+ getComponentPreviewHref
13
+ };
14
+ //# sourceMappingURL=component-preview-href.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../next/component-preview-href.ts"],
4
+ "sourcesContent": ["export function getComponentPreviewHref({\n currentUrl,\n props,\n sourceRevision,\n}: {\n currentUrl: string;\n props: Record<string, unknown>;\n sourceRevision: string;\n}) {\n const url = new URL(currentUrl);\n url.searchParams.set(\"props\", JSON.stringify(props));\n url.searchParams.set(\"sourceRevision\", sourceRevision);\n return `${url.pathname}${url.search}${url.hash}`;\n}\n"],
5
+ "mappings": "AAAO,SAAS,wBAAwB;AAAA,EACtC;AAAA,EACA;AAAA,EACA;AACF,GAIG;AACD,QAAM,MAAM,IAAI,IAAI,UAAU;AAC9B,MAAI,aAAa,IAAI,SAAS,KAAK,UAAU,KAAK,CAAC;AACnD,MAAI,aAAa,IAAI,kBAAkB,cAAc;AACrD,SAAO,GAAG,IAAI,QAAQ,GAAG,IAAI,MAAM,GAAG,IAAI,IAAI;AAChD;",
6
+ "names": []
7
+ }
@@ -0,0 +1 @@
1
+ export declare function ComponentPreviewNavigation(): null;
@@ -0,0 +1,66 @@
1
+ "use client";
2
+ import { useMemo } from "react";
3
+ import { useRouter } from "next/navigation";
4
+ import { useIframeRpcChannel } from "../_vendor/replo-utils/react/use-iframe-rpc-channel.mjs";
5
+ import {
6
+ COMPONENT_PREVIEW_IFRAME_RPC_CHANNEL_ID,
7
+ COMPONENT_PREVIEW_IFRAME_RPC_CHANNEL_VERSION,
8
+ componentPreviewToWebsiteBuilderMethodConfig,
9
+ websiteBuilderToComponentPreviewMethodConfig
10
+ } from "../_vendor/schemas/componentPreview.mjs";
11
+ import {
12
+ createIframeRpcChannel,
13
+ createIframeRpcRemote
14
+ } from "../_vendor/schemas/iframeRpcChannel.mjs";
15
+ import { getComponentPreviewHref } from "./component-preview-href";
16
+ function ComponentPreviewNavigation() {
17
+ const router = useRouter();
18
+ useIframeRpcChannel(
19
+ useMemo(() => {
20
+ if (typeof window === "undefined" || !document.referrer) {
21
+ return null;
22
+ }
23
+ const parentOrigin = new URL(document.referrer).origin;
24
+ const rpcChannel = createIframeRpcChannel({
25
+ subscriberWindow: window,
26
+ channelIdentifier: COMPONENT_PREVIEW_IFRAME_RPC_CHANNEL_ID,
27
+ version: COMPONENT_PREVIEW_IFRAME_RPC_CHANNEL_VERSION,
28
+ getTargetWindow: () => {
29
+ return window.parent === window ? null : window.parent;
30
+ },
31
+ targetOrigin: parentOrigin,
32
+ isExpectedMessage: (event) => {
33
+ return event.source === window.parent && event.origin === parentOrigin;
34
+ },
35
+ outgoingMethods: componentPreviewToWebsiteBuilderMethodConfig,
36
+ incomingMethods: websiteBuilderToComponentPreviewMethodConfig,
37
+ handlers: {
38
+ setProps: ({ props, sourceRevision }) => {
39
+ const nextHref = getComponentPreviewHref({
40
+ currentUrl: window.location.href,
41
+ props,
42
+ sourceRevision
43
+ });
44
+ const currentHref = `${window.location.pathname}${window.location.search}${window.location.hash}`;
45
+ if (nextHref !== currentHref) {
46
+ router.replace(nextHref, { scroll: false });
47
+ }
48
+ }
49
+ }
50
+ });
51
+ return {
52
+ ...rpcChannel,
53
+ subscribe() {
54
+ const unsubscribe = rpcChannel.subscribe();
55
+ createIframeRpcRemote(rpcChannel).iframeReady();
56
+ return unsubscribe;
57
+ }
58
+ };
59
+ }, [router])
60
+ );
61
+ return null;
62
+ }
63
+ export {
64
+ ComponentPreviewNavigation
65
+ };
66
+ //# sourceMappingURL=component-preview-navigation.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../next/component-preview-navigation.tsx"],
4
+ "sourcesContent": ["\"use client\";\n\nimport { useMemo } from \"react\";\n\nimport { useRouter } from \"next/navigation\";\n\nimport { useIframeRpcChannel } from \"replo-utils/react/use-iframe-rpc-channel\";\nimport {\n COMPONENT_PREVIEW_IFRAME_RPC_CHANNEL_ID,\n COMPONENT_PREVIEW_IFRAME_RPC_CHANNEL_VERSION,\n componentPreviewToWebsiteBuilderMethodConfig,\n websiteBuilderToComponentPreviewMethodConfig,\n} from \"schemas/componentPreview\";\nimport {\n createIframeRpcChannel,\n createIframeRpcRemote,\n} from \"schemas/iframeRpcChannel\";\n\nimport { getComponentPreviewHref } from \"./component-preview-href\";\n\nexport function ComponentPreviewNavigation() {\n const router = useRouter();\n useIframeRpcChannel(\n useMemo(() => {\n if (typeof window === \"undefined\" || !document.referrer) {\n return null;\n }\n const parentOrigin = new URL(document.referrer).origin;\n const rpcChannel = createIframeRpcChannel({\n subscriberWindow: window,\n channelIdentifier: COMPONENT_PREVIEW_IFRAME_RPC_CHANNEL_ID,\n version: COMPONENT_PREVIEW_IFRAME_RPC_CHANNEL_VERSION,\n getTargetWindow: () => {\n return window.parent === window ? null : window.parent;\n },\n targetOrigin: parentOrigin,\n isExpectedMessage: (event) => {\n return (\n event.source === window.parent && event.origin === parentOrigin\n );\n },\n outgoingMethods: componentPreviewToWebsiteBuilderMethodConfig,\n incomingMethods: websiteBuilderToComponentPreviewMethodConfig,\n handlers: {\n setProps: ({ props, sourceRevision }) => {\n const nextHref = getComponentPreviewHref({\n currentUrl: window.location.href,\n props,\n sourceRevision,\n });\n const currentHref = `${window.location.pathname}${window.location.search}${window.location.hash}`;\n if (nextHref !== currentHref) {\n router.replace(nextHref, { scroll: false });\n }\n },\n },\n });\n return {\n ...rpcChannel,\n subscribe() {\n const unsubscribe = rpcChannel.subscribe();\n createIframeRpcRemote(rpcChannel).iframeReady();\n return unsubscribe;\n },\n };\n }, [router]),\n );\n\n return null;\n}\n"],
5
+ "mappings": ";AAEA,SAAS,eAAe;AAExB,SAAS,iBAAiB;AAE1B,SAAS,2BAA2B;AACpC;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,OACK;AACP;AAAA,EACE;AAAA,EACA;AAAA,OACK;AAEP,SAAS,+BAA+B;AAEjC,SAAS,6BAA6B;AAC3C,QAAM,SAAS,UAAU;AACzB;AAAA,IACE,QAAQ,MAAM;AACZ,UAAI,OAAO,WAAW,eAAe,CAAC,SAAS,UAAU;AACvD,eAAO;AAAA,MACT;AACA,YAAM,eAAe,IAAI,IAAI,SAAS,QAAQ,EAAE;AAChD,YAAM,aAAa,uBAAuB;AAAA,QACxC,kBAAkB;AAAA,QAClB,mBAAmB;AAAA,QACnB,SAAS;AAAA,QACT,iBAAiB,MAAM;AACrB,iBAAO,OAAO,WAAW,SAAS,OAAO,OAAO;AAAA,QAClD;AAAA,QACA,cAAc;AAAA,QACd,mBAAmB,CAAC,UAAU;AAC5B,iBACE,MAAM,WAAW,OAAO,UAAU,MAAM,WAAW;AAAA,QAEvD;AAAA,QACA,iBAAiB;AAAA,QACjB,iBAAiB;AAAA,QACjB,UAAU;AAAA,UACR,UAAU,CAAC,EAAE,OAAO,eAAe,MAAM;AACvC,kBAAM,WAAW,wBAAwB;AAAA,cACvC,YAAY,OAAO,SAAS;AAAA,cAC5B;AAAA,cACA;AAAA,YACF,CAAC;AACD,kBAAM,cAAc,GAAG,OAAO,SAAS,QAAQ,GAAG,OAAO,SAAS,MAAM,GAAG,OAAO,SAAS,IAAI;AAC/F,gBAAI,aAAa,aAAa;AAC5B,qBAAO,QAAQ,UAAU,EAAE,QAAQ,MAAM,CAAC;AAAA,YAC5C;AAAA,UACF;AAAA,QACF;AAAA,MACF,CAAC;AACD,aAAO;AAAA,QACL,GAAG;AAAA,QACH,YAAY;AACV,gBAAM,cAAc,WAAW,UAAU;AACzC,gCAAsB,UAAU,EAAE,YAAY;AAC9C,iBAAO;AAAA,QACT;AAAA,MACF;AAAA,IACF,GAAG,CAAC,MAAM,CAAC;AAAA,EACb;AAEA,SAAO;AACT;",
6
+ "names": []
7
+ }
@@ -1,5 +1,8 @@
1
1
  import type { ComponentType } from "react";
2
- export declare function createComponentPreviewPage(Component: ComponentType<Record<string, unknown>>): ({ searchParams, }: {
2
+ import type { ComponentPreviewProductReference } from "../_vendor/schemas/generated/componentPreview";
3
+ export declare function createComponentPreviewPage(Component: ComponentType<Record<string, unknown>>, options?: {
4
+ getProduct: (reference: ComponentPreviewProductReference) => Promise<unknown>;
5
+ }): ({ searchParams, }: {
3
6
  searchParams: Promise<{
4
7
  props?: string | string[];
5
8
  }>;
@@ -1,35 +1,70 @@
1
- import { jsx } from "react/jsx-runtime";
2
- const MAX_PREVIEW_PROPS_BYTES = 16 * 1024;
1
+ import { Fragment, jsx, jsxs } from "react/jsx-runtime";
2
+ import {
3
+ componentPreviewProductReferenceSchema,
4
+ componentPreviewPropsSchema,
5
+ MAX_COMPONENT_PREVIEW_PROPS_BYTES
6
+ } from "../_vendor/schemas/componentPreview.mjs";
7
+ import { DocumentReadyBeacon } from "../DocumentReadyBeacon";
8
+ import { NextErrorReporter } from "../NextErrorReporter";
9
+ import { ComponentPreviewNavigation } from "./component-preview-navigation";
3
10
  const BLOCKED_PROP_NAMES = /* @__PURE__ */ new Set([
4
11
  "__proto__",
5
12
  "constructor",
6
13
  "dangerouslySetInnerHTML"
7
14
  ]);
8
- function getPreviewProps(value) {
9
- if (value === null || typeof value !== "object" || Array.isArray(value)) {
15
+ async function getPreviewProps({
16
+ value,
17
+ getProduct
18
+ }) {
19
+ const previewPropsResult = componentPreviewPropsSchema.safeParse(value);
20
+ if (!previewPropsResult.success) {
10
21
  return {};
11
22
  }
12
- return Object.fromEntries(
13
- Object.entries(value).filter(([name]) => !BLOCKED_PROP_NAMES.has(name))
14
- );
23
+ const previewProps = {};
24
+ for (const [name, propValue] of Object.entries(previewPropsResult.data)) {
25
+ if (BLOCKED_PROP_NAMES.has(name)) {
26
+ continue;
27
+ }
28
+ const productReferenceResult = componentPreviewProductReferenceSchema.safeParse(propValue);
29
+ if (!productReferenceResult.success) {
30
+ previewProps[name] = propValue;
31
+ continue;
32
+ }
33
+ if (getProduct) {
34
+ previewProps[name] = await getProduct(productReferenceResult.data);
35
+ }
36
+ }
37
+ return previewProps;
15
38
  }
16
- function parseProps(value) {
17
- if (typeof value !== "string" || new TextEncoder().encode(value).byteLength > MAX_PREVIEW_PROPS_BYTES) {
39
+ async function parseProps({
40
+ value,
41
+ getProduct
42
+ }) {
43
+ if (typeof value !== "string" || new TextEncoder().encode(value).byteLength > MAX_COMPONENT_PREVIEW_PROPS_BYTES) {
18
44
  return {};
19
45
  }
46
+ let parsed;
20
47
  try {
21
- const parsed = JSON.parse(value);
22
- return getPreviewProps(parsed);
48
+ parsed = JSON.parse(value);
23
49
  } catch {
24
50
  return {};
25
51
  }
52
+ return await getPreviewProps({ value: parsed, getProduct });
26
53
  }
27
- function createComponentPreviewPage(Component) {
54
+ function createComponentPreviewPage(Component, options) {
28
55
  return async function ComponentPreviewPage({
29
56
  searchParams
30
57
  }) {
31
- const props = parseProps((await searchParams).props);
32
- return /* @__PURE__ */ jsx(Component, { ...props });
58
+ const props = await parseProps({
59
+ value: (await searchParams).props,
60
+ getProduct: options?.getProduct
61
+ });
62
+ return /* @__PURE__ */ jsxs(Fragment, { children: [
63
+ /* @__PURE__ */ jsx(ComponentPreviewNavigation, {}),
64
+ /* @__PURE__ */ jsx(DocumentReadyBeacon, {}),
65
+ /* @__PURE__ */ jsx(NextErrorReporter, {}),
66
+ /* @__PURE__ */ jsx(Component, { ...props })
67
+ ] });
33
68
  };
34
69
  }
35
70
  export {
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../next/component-preview.tsx"],
4
- "sourcesContent": ["import type { ComponentType } from \"react\";\n\nconst MAX_PREVIEW_PROPS_BYTES = 16 * 1024;\nconst BLOCKED_PROP_NAMES = new Set([\n \"__proto__\",\n \"constructor\",\n \"dangerouslySetInnerHTML\",\n]);\n\nfunction getPreviewProps(value: unknown): Record<string, unknown> {\n if (value === null || typeof value !== \"object\" || Array.isArray(value)) {\n return {};\n }\n\n return Object.fromEntries(\n Object.entries(value).filter(([name]) => !BLOCKED_PROP_NAMES.has(name)),\n );\n}\n\nfunction parseProps(value: string | string[] | undefined) {\n if (\n typeof value !== \"string\" ||\n new TextEncoder().encode(value).byteLength > MAX_PREVIEW_PROPS_BYTES\n ) {\n return {};\n }\n try {\n const parsed: unknown = JSON.parse(value);\n return getPreviewProps(parsed);\n } catch {\n return {};\n }\n}\n\nexport function createComponentPreviewPage(\n Component: ComponentType<Record<string, unknown>>,\n) {\n return async function ComponentPreviewPage({\n searchParams,\n }: {\n searchParams: Promise<{ props?: string | string[] }>;\n }) {\n const props = parseProps((await searchParams).props);\n return <Component {...props} />;\n };\n}\n"],
5
- "mappings": "AA2CW;AAzCX,MAAM,0BAA0B,KAAK;AACrC,MAAM,qBAAqB,oBAAI,IAAI;AAAA,EACjC;AAAA,EACA;AAAA,EACA;AACF,CAAC;AAED,SAAS,gBAAgB,OAAyC;AAChE,MAAI,UAAU,QAAQ,OAAO,UAAU,YAAY,MAAM,QAAQ,KAAK,GAAG;AACvE,WAAO,CAAC;AAAA,EACV;AAEA,SAAO,OAAO;AAAA,IACZ,OAAO,QAAQ,KAAK,EAAE,OAAO,CAAC,CAAC,IAAI,MAAM,CAAC,mBAAmB,IAAI,IAAI,CAAC;AAAA,EACxE;AACF;AAEA,SAAS,WAAW,OAAsC;AACxD,MACE,OAAO,UAAU,YACjB,IAAI,YAAY,EAAE,OAAO,KAAK,EAAE,aAAa,yBAC7C;AACA,WAAO,CAAC;AAAA,EACV;AACA,MAAI;AACF,UAAM,SAAkB,KAAK,MAAM,KAAK;AACxC,WAAO,gBAAgB,MAAM;AAAA,EAC/B,QAAQ;AACN,WAAO,CAAC;AAAA,EACV;AACF;AAEO,SAAS,2BACd,WACA;AACA,SAAO,eAAe,qBAAqB;AAAA,IACzC;AAAA,EACF,GAEG;AACD,UAAM,QAAQ,YAAY,MAAM,cAAc,KAAK;AACnD,WAAO,oBAAC,aAAW,GAAG,OAAO;AAAA,EAC/B;AACF;",
4
+ "sourcesContent": ["import type { ComponentType } from \"react\";\nimport type { ComponentPreviewProductReference } from \"schemas/generated/componentPreview\";\n\nimport {\n componentPreviewProductReferenceSchema,\n componentPreviewPropsSchema,\n MAX_COMPONENT_PREVIEW_PROPS_BYTES,\n} from \"schemas/componentPreview\";\n\nimport { DocumentReadyBeacon } from \"../DocumentReadyBeacon\";\nimport { NextErrorReporter } from \"../NextErrorReporter\";\nimport { ComponentPreviewNavigation } from \"./component-preview-navigation\";\n\nconst BLOCKED_PROP_NAMES = new Set([\n \"__proto__\",\n \"constructor\",\n \"dangerouslySetInnerHTML\",\n]);\n\nasync function getPreviewProps({\n value,\n getProduct,\n}: {\n value: unknown;\n getProduct?: (\n reference: ComponentPreviewProductReference,\n ) => Promise<unknown>;\n}): Promise<Record<string, unknown>> {\n const previewPropsResult = componentPreviewPropsSchema.safeParse(value);\n if (!previewPropsResult.success) {\n return {};\n }\n\n const previewProps: Record<string, unknown> = {};\n for (const [name, propValue] of Object.entries(previewPropsResult.data)) {\n if (BLOCKED_PROP_NAMES.has(name)) {\n continue;\n }\n const productReferenceResult =\n componentPreviewProductReferenceSchema.safeParse(propValue);\n if (!productReferenceResult.success) {\n previewProps[name] = propValue;\n continue;\n }\n if (getProduct) {\n previewProps[name] = await getProduct(productReferenceResult.data);\n }\n }\n return previewProps;\n}\n\nasync function parseProps({\n value,\n getProduct,\n}: {\n value: string | string[] | undefined;\n getProduct?: (\n reference: ComponentPreviewProductReference,\n ) => Promise<unknown>;\n}) {\n if (\n typeof value !== \"string\" ||\n new TextEncoder().encode(value).byteLength >\n MAX_COMPONENT_PREVIEW_PROPS_BYTES\n ) {\n return {};\n }\n let parsed: unknown;\n try {\n parsed = JSON.parse(value);\n } catch {\n return {};\n }\n return await getPreviewProps({ value: parsed, getProduct });\n}\n\nexport function createComponentPreviewPage(\n Component: ComponentType<Record<string, unknown>>,\n options?: {\n getProduct: (\n reference: ComponentPreviewProductReference,\n ) => Promise<unknown>;\n },\n) {\n return async function ComponentPreviewPage({\n searchParams,\n }: {\n searchParams: Promise<{ props?: string | string[] }>;\n }) {\n const props = await parseProps({\n value: (await searchParams).props,\n getProduct: options?.getProduct,\n });\n return (\n <>\n <ComponentPreviewNavigation />\n <DocumentReadyBeacon />\n <NextErrorReporter />\n <Component {...props} />\n </>\n );\n };\n}\n"],
5
+ "mappings": "AA8FM,mBACE,KADF;AA3FN;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,OACK;AAEP,SAAS,2BAA2B;AACpC,SAAS,yBAAyB;AAClC,SAAS,kCAAkC;AAE3C,MAAM,qBAAqB,oBAAI,IAAI;AAAA,EACjC;AAAA,EACA;AAAA,EACA;AACF,CAAC;AAED,eAAe,gBAAgB;AAAA,EAC7B;AAAA,EACA;AACF,GAKqC;AACnC,QAAM,qBAAqB,4BAA4B,UAAU,KAAK;AACtE,MAAI,CAAC,mBAAmB,SAAS;AAC/B,WAAO,CAAC;AAAA,EACV;AAEA,QAAM,eAAwC,CAAC;AAC/C,aAAW,CAAC,MAAM,SAAS,KAAK,OAAO,QAAQ,mBAAmB,IAAI,GAAG;AACvE,QAAI,mBAAmB,IAAI,IAAI,GAAG;AAChC;AAAA,IACF;AACA,UAAM,yBACJ,uCAAuC,UAAU,SAAS;AAC5D,QAAI,CAAC,uBAAuB,SAAS;AACnC,mBAAa,IAAI,IAAI;AACrB;AAAA,IACF;AACA,QAAI,YAAY;AACd,mBAAa,IAAI,IAAI,MAAM,WAAW,uBAAuB,IAAI;AAAA,IACnE;AAAA,EACF;AACA,SAAO;AACT;AAEA,eAAe,WAAW;AAAA,EACxB;AAAA,EACA;AACF,GAKG;AACD,MACE,OAAO,UAAU,YACjB,IAAI,YAAY,EAAE,OAAO,KAAK,EAAE,aAC9B,mCACF;AACA,WAAO,CAAC;AAAA,EACV;AACA,MAAI;AACJ,MAAI;AACF,aAAS,KAAK,MAAM,KAAK;AAAA,EAC3B,QAAQ;AACN,WAAO,CAAC;AAAA,EACV;AACA,SAAO,MAAM,gBAAgB,EAAE,OAAO,QAAQ,WAAW,CAAC;AAC5D;AAEO,SAAS,2BACd,WACA,SAKA;AACA,SAAO,eAAe,qBAAqB;AAAA,IACzC;AAAA,EACF,GAEG;AACD,UAAM,QAAQ,MAAM,WAAW;AAAA,MAC7B,QAAQ,MAAM,cAAc;AAAA,MAC5B,YAAY,SAAS;AAAA,IACvB,CAAC;AACD,WACE,iCACE;AAAA,0BAAC,8BAA2B;AAAA,MAC5B,oBAAC,uBAAoB;AAAA,MACrB,oBAAC,qBAAkB;AAAA,MACnB,oBAAC,aAAW,GAAG,OAAO;AAAA,OACxB;AAAA,EAEJ;AACF;",
6
6
  "names": []
7
7
  }