@base44-preview/vite-plugin 0.2.20-pr.27.c07198f → 0.2.20-pr.33.42f673d

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 (44) hide show
  1. package/dist/html-injections-plugin.d.ts +3 -4
  2. package/dist/html-injections-plugin.d.ts.map +1 -1
  3. package/dist/html-injections-plugin.js +110 -33
  4. package/dist/html-injections-plugin.js.map +1 -1
  5. package/dist/index.d.ts +1 -0
  6. package/dist/index.d.ts.map +1 -1
  7. package/dist/index.js +3 -2
  8. package/dist/index.js.map +1 -1
  9. package/dist/injections/navigation-notifier.d.ts +1 -2
  10. package/dist/injections/navigation-notifier.d.ts.map +1 -1
  11. package/dist/injections/navigation-notifier.js +2 -2
  12. package/dist/injections/navigation-notifier.js.map +1 -1
  13. package/dist/injections/sandbox-hmr-notifier.d.ts +1 -4
  14. package/dist/injections/sandbox-hmr-notifier.d.ts.map +1 -1
  15. package/dist/injections/sandbox-hmr-notifier.js +4 -4
  16. package/dist/injections/sandbox-hmr-notifier.js.map +1 -1
  17. package/dist/injections/sandbox-mount-observer.d.ts +1 -2
  18. package/dist/injections/sandbox-mount-observer.d.ts.map +1 -1
  19. package/dist/injections/sandbox-mount-observer.js +2 -2
  20. package/dist/injections/sandbox-mount-observer.js.map +1 -1
  21. package/dist/injections/unhandled-errors-handlers.d.ts +1 -4
  22. package/dist/injections/unhandled-errors-handlers.d.ts.map +1 -1
  23. package/dist/injections/unhandled-errors-handlers.js +67 -69
  24. package/dist/injections/unhandled-errors-handlers.js.map +1 -1
  25. package/dist/injections/visual-edit-agent.d.ts +1 -1
  26. package/dist/injections/visual-edit-agent.d.ts.map +1 -1
  27. package/dist/injections/visual-edit-agent.js +1 -1
  28. package/dist/injections/visual-edit-agent.js.map +1 -1
  29. package/package.json +2 -8
  30. package/src/html-injections-plugin.ts +138 -40
  31. package/src/index.ts +4 -1
  32. package/src/injections/navigation-notifier.ts +1 -2
  33. package/src/injections/sandbox-hmr-notifier.ts +3 -4
  34. package/src/injections/sandbox-mount-observer.ts +2 -2
  35. package/src/injections/unhandled-errors-handlers.ts +80 -84
  36. package/src/injections/visual-edit-agent.ts +2 -2
  37. package/README.md +0 -93
  38. package/dist/bridge.d.ts +0 -20
  39. package/dist/bridge.d.ts.map +0 -1
  40. package/dist/bridge.js +0 -33
  41. package/dist/bridge.js.map +0 -1
  42. package/dist/statics/index.mjs +0 -2
  43. package/dist/statics/index.mjs.map +0 -1
  44. package/src/bridge.ts +0 -37
package/package.json CHANGED
@@ -1,12 +1,11 @@
1
1
  {
2
2
  "name": "@base44-preview/vite-plugin",
3
- "version": "0.2.20-pr.27.c07198f",
3
+ "version": "0.2.20-pr.33.42f673d",
4
4
  "description": "The Vite plugin for base44 based applications",
5
5
  "type": "module",
6
6
  "license": "MIT",
7
7
  "exports": {
8
8
  ".": "./dist/index.js",
9
- "./bridge": "./dist/bridge.js",
10
9
  "./compat/*": "./compat/*"
11
10
  },
12
11
  "files": [
@@ -16,20 +15,15 @@
16
15
  ],
17
16
  "scripts": {
18
17
  "build": "tsc",
19
- "build:bridge": "tsup",
20
18
  "validate-exports": "node scripts/validate-exports.mjs",
21
- "prepublishOnly": "rm -rf ./dist && npm run build && npm run build:bridge && npm run validate-exports",
22
- "dev": "node dev-server.js",
19
+ "prepublishOnly": "rm -rf ./dist && npm run build && npm run validate-exports",
23
20
  "test:unit": "vitest run"
24
21
  },
25
22
  "devDependencies": {
26
23
  "@types/babel__generator": "^7.27.0",
27
24
  "@types/babel__traverse": "^7.28.0",
28
25
  "@types/node": "^24.6.2",
29
- "cors": "^2.8.5",
30
- "express": "^4.21.2",
31
26
  "jsdom": "^26.0.0",
32
- "tsup": "^8.1.0",
33
27
  "typescript": "^5.9.3",
34
28
  "vite": "^7.1.9",
35
29
  "vitest": "^3.0.0"
@@ -1,51 +1,149 @@
1
- import type { Plugin } from "vite";
1
+ import type { Plugin, HtmlTagDescriptor } from "vite";
2
+ import { loadEnv } from "vite";
2
3
 
3
- interface HtmlInjectionOptions {
4
- hmrNotifier: boolean;
5
- navigationNotifier: boolean;
6
- visualEditAgent: boolean;
4
+ type Injection = {
5
+ /** Script src path for dev mode (served from node_modules) */
6
+ src?: string;
7
+ injectTo: "head" | "body";
8
+ mode: "dev" | "production";
9
+ /** Inline content for production builds (src paths don't work in built output) */
10
+ inlineContent?: string;
11
+ };
12
+
13
+ const ANALYTICS_TRACKER_SCRIPT = `
14
+ let lastPath = "";
15
+ function getPageNameFromPath(path) {
16
+ const segments = path.split("/").filter(Boolean);
17
+ return segments[0] || null;
18
+ }
19
+ function trackPageView() {
20
+ const path = window.location.pathname;
21
+ if (path === lastPath) return;
22
+ lastPath = path;
23
+ const pageName = getPageNameFromPath(path) || "home";
24
+ const appId = import.meta.env.VITE_BASE44_APP_ID;
25
+ const serverUrl = import.meta.env.VITE_BASE44_BACKEND_URL || "";
26
+ if (!appId) return;
27
+ fetch(\`\${serverUrl}/app-logs/\${appId}/log-user-in-app/\${pageName}\`, {
28
+ method: "POST",
29
+ }).catch(() => {});
7
30
  }
31
+ const originalPushState = history.pushState.bind(history);
32
+ history.pushState = function (...args) {
33
+ originalPushState(...args);
34
+ trackPageView();
35
+ };
36
+ const originalReplaceState = history.replaceState.bind(history);
37
+ history.replaceState = function (...args) {
38
+ originalReplaceState(...args);
39
+ trackPageView();
40
+ };
41
+ window.addEventListener("popstate", trackPageView);
42
+ trackPageView();
43
+ `;
44
+
45
+ const INJECTIONS: Record<string, Injection> = {
46
+ unhandledErrors: {
47
+ src: "/node_modules/@base44/vite-plugin/dist/injections/unhandled-errors-handlers.js",
48
+ injectTo: "head",
49
+ mode: "dev",
50
+ },
51
+ sandboxMount: {
52
+ src: "/node_modules/@base44/vite-plugin/dist/injections/sandbox-mount-observer.js",
53
+ injectTo: "body",
54
+ mode: "dev",
55
+ },
56
+ hmrNotifier: {
57
+ src: "/node_modules/@base44/vite-plugin/dist/injections/sandbox-hmr-notifier.js",
58
+ injectTo: "head",
59
+ mode: "dev",
60
+ },
61
+ navigationNotifier: {
62
+ src: "/node_modules/@base44/vite-plugin/dist/injections/navigation-notifier.js",
63
+ injectTo: "head",
64
+ mode: "dev",
65
+ },
66
+ visualEditAgent: {
67
+ src: "/node_modules/@base44/vite-plugin/dist/injections/visual-edit-agent.js",
68
+ injectTo: "body",
69
+ mode: "dev",
70
+ },
71
+ analyticsTracker: {
72
+ injectTo: "head",
73
+ mode: "production",
74
+ inlineContent: ANALYTICS_TRACKER_SCRIPT,
75
+ },
76
+ };
8
77
 
9
78
  export function htmlInjectionsPlugin({
10
79
  hmrNotifier,
11
80
  navigationNotifier,
12
81
  visualEditAgent,
13
- }: HtmlInjectionOptions): Plugin {
82
+ analyticsTracker,
83
+ }: {
84
+ hmrNotifier: boolean;
85
+ navigationNotifier: boolean;
86
+ visualEditAgent: boolean;
87
+ analyticsTracker: boolean;
88
+ }) {
89
+ const enabledInjections: Record<string, boolean> = {
90
+ unhandledErrors: true,
91
+ sandboxMount: true,
92
+ hmrNotifier,
93
+ navigationNotifier,
94
+ visualEditAgent,
95
+ analyticsTracker,
96
+ };
97
+
98
+ let resolvedEnv: Record<string, string> = {};
99
+
14
100
  return {
15
101
  name: "html-injections",
16
- apply: (config) => config.mode !== "production",
17
-
18
- transformIndexHtml() {
19
- const options = JSON.stringify({
20
- hmrNotifier,
21
- navigationNotifier,
22
- visualEditAgent,
23
- unhandledErrors: true,
24
- mountObserver: true,
25
- });
26
- return [
27
- {
28
- tag: "script",
29
- attrs: { type: "module" },
30
- children: [
31
- `if (window.self !== window.top) {`,
32
- ` (async () => {`,
33
- ` try {`,
34
- ` const mode = new URLSearchParams(location.search).get("sandbox-bridge");`,
35
- ` const url = mode === "local"`,
36
- ` ? "https://localhost:3201/index.mjs"`,
37
- ` : "/node_modules/@base44/vite-plugin/dist/statics/index.mjs";`,
38
- ` const mod = await import(url);`,
39
- ` if (typeof mod.init === "function") mod.init(${options}, import.meta.hot);`,
40
- ` } catch (e) {`,
41
- ` console.error("[sandbox-bridge] Failed to load:", e);`,
42
- ` }`,
43
- ` })();`,
44
- `}`,
45
- ].join("\n"),
46
- injectTo: "head",
47
- },
48
- ];
102
+ configResolved(config) {
103
+ // Capture env vars for use in transformIndexHtml
104
+ // loadEnv gets all env vars including VITE_ prefixed ones
105
+ resolvedEnv = loadEnv(config.mode, config.root, "");
49
106
  },
50
- };
107
+ transformIndexHtml: {
108
+ handler(_html, ctx) {
109
+ const currentMode = ctx.server ? "dev" : "production";
110
+
111
+ const tags = Object.entries(INJECTIONS)
112
+ .filter(
113
+ ([key, injection]) =>
114
+ enabledInjections[key] && injection.mode === currentMode
115
+ )
116
+ .map(([, injection]): HtmlTagDescriptor => {
117
+ // Production injections use inline content (src paths don't work in built output)
118
+ if (injection.inlineContent) {
119
+ // Replace import.meta.env references with actual values
120
+ // Vite doesn't replace these in inline script content
121
+ let content = injection.inlineContent;
122
+ content = content.replace(
123
+ /import\.meta\.env\.(\w+)/g,
124
+ (_, envKey) => JSON.stringify(resolvedEnv[envKey] ?? "")
125
+ );
126
+
127
+ return {
128
+ tag: "script",
129
+ attrs: { type: "module" },
130
+ children: content,
131
+ injectTo: injection.injectTo,
132
+ };
133
+ }
134
+ // Dev injections use src path (served from node_modules)
135
+ return {
136
+ tag: "script",
137
+ attrs: {
138
+ src: injection.src,
139
+ type: "module",
140
+ },
141
+ injectTo: injection.injectTo,
142
+ };
143
+ });
144
+
145
+ return tags;
146
+ },
147
+ },
148
+ } as Plugin;
51
149
  }
package/src/index.ts CHANGED
@@ -13,6 +13,7 @@ export default function vitePlugin(
13
13
  hmrNotifier?: boolean;
14
14
  navigationNotifier?: boolean;
15
15
  visualEditAgent?: boolean;
16
+ analyticsTracker?: boolean;
16
17
  } = {}
17
18
  ) {
18
19
  const {
@@ -20,6 +21,7 @@ export default function vitePlugin(
20
21
  hmrNotifier = false,
21
22
  navigationNotifier = false,
22
23
  visualEditAgent = false,
24
+ analyticsTracker = false,
23
25
  } = opts;
24
26
 
25
27
  return [
@@ -215,8 +217,9 @@ export default function vitePlugin(
215
217
  } as Plugin,
216
218
  errorOverlayPlugin(),
217
219
  visualEditPlugin(),
218
- htmlInjectionsPlugin({ hmrNotifier, navigationNotifier, visualEditAgent }),
219
220
  ]
220
221
  : []),
222
+ // HTML injections - handles both dev (sandbox) and production injections
223
+ htmlInjectionsPlugin({ hmrNotifier, navigationNotifier, visualEditAgent, analyticsTracker }),
221
224
  ];
222
225
  }
@@ -1,5 +1,4 @@
1
- /** Intercept pushState / replaceState / popstate and notify the parent of URL changes. */
2
- export function setupNavigationNotifier() {
1
+ if (window.self !== window.top) {
3
2
  let lastUrl = window.location.href;
4
3
 
5
4
  function notifyNavigation() {
@@ -1,9 +1,8 @@
1
- /** Forward Vite HMR lifecycle events (beforeUpdate / afterUpdate) to the parent window. */
2
- export function setupHmrNotifier(hmr: { on(event: string, cb: (...args: any[]) => void): void }) {
3
- hmr.on("vite:beforeUpdate", () => {
1
+ if (import.meta.hot) {
2
+ import.meta.hot.on("vite:beforeUpdate", () => {
4
3
  window.parent?.postMessage({ type: "sandbox:beforeUpdate" }, "*");
5
4
  });
6
- hmr.on("vite:afterUpdate", () => {
5
+ import.meta.hot.on("vite:afterUpdate", () => {
7
6
  window.parent?.postMessage({ type: "sandbox:afterUpdate" }, "*");
8
7
  });
9
8
  }
@@ -1,5 +1,5 @@
1
- /** Observe DOM mutations and notify the parent when instrumented elements are mounted or unmounted. */
2
- export function setupMountObserver() {
1
+
2
+ if (window.self !== window.top) {
3
3
  const observer = new MutationObserver((mutations) => {
4
4
  const nodesAdded = mutations.some(
5
5
  (mutation) => mutation.addedNodes.length > 0
@@ -1,97 +1,93 @@
1
- /** Register global error and unhandled-rejection listeners that report to the parent window. */
1
+ /// <reference types="vite/client" />
2
2
 
3
- const ERROR_SUPPRESSION_TIMEOUT = 10000;
3
+ window.removeEventListener("unhandledrejection", handleUnhandledRejection);
4
+ window.removeEventListener("error", handleWindowError);
4
5
 
5
- export function setupUnhandledErrors(hmr?: { on(event: string, cb: (...args: any[]) => void): void }) {
6
- window.removeEventListener("unhandledrejection", handleUnhandledRejection);
7
- window.removeEventListener("error", handleWindowError);
6
+ window.addEventListener("unhandledrejection", handleUnhandledRejection);
7
+ window.addEventListener("error", handleWindowError);
8
8
 
9
- window.addEventListener("unhandledrejection", handleUnhandledRejection);
10
- window.addEventListener("error", handleWindowError);
9
+ let shouldPropagateErrors = true;
10
+ let suppressionTimer: ReturnType<typeof setTimeout> | null = null;
11
11
 
12
- let shouldPropagateErrors = true;
13
- let suppressionTimer: ReturnType<typeof setTimeout> | null = null;
12
+ if (import.meta.hot) {
13
+ import.meta.hot.on("vite:beforeUpdate", () => {
14
+ shouldPropagateErrors = false;
14
15
 
15
- if (hmr) {
16
- hmr.on("vite:beforeUpdate", () => {
17
- shouldPropagateErrors = false;
18
-
19
- if (suppressionTimer) {
20
- clearTimeout(suppressionTimer);
21
- }
22
-
23
- suppressionTimer = setTimeout(() => {
24
- shouldPropagateErrors = true;
25
- suppressionTimer = null;
26
- }, ERROR_SUPPRESSION_TIMEOUT);
27
- });
28
- hmr.on("vite:beforeFullReload", () => {
29
- shouldPropagateErrors = false;
30
- if (suppressionTimer) {
31
- clearTimeout(suppressionTimer);
32
- suppressionTimer = null;
33
- }
34
- });
35
- }
16
+ if (suppressionTimer) {
17
+ clearTimeout(suppressionTimer);
18
+ }
36
19
 
37
- function onAppError({
38
- title,
39
- details,
40
- componentName,
41
- originalError,
42
- }: {
43
- title: string;
44
- details: string;
45
- componentName: string;
46
- originalError: any;
47
- }) {
48
- if (originalError?.response?.status === 402 || !shouldPropagateErrors) {
49
- return;
20
+ suppressionTimer = setTimeout(() => {
21
+ shouldPropagateErrors = true;
22
+ suppressionTimer = null;
23
+ }, import.meta.env.VITE_HMR_ERROR_SUPPRESSION_DELAY ?? 10000);
24
+ });
25
+ import.meta.hot.on("vite:beforeFullReload", () => {
26
+ shouldPropagateErrors = false;
27
+ if (suppressionTimer) {
28
+ clearTimeout(suppressionTimer);
29
+ suppressionTimer = null;
50
30
  }
51
- window.parent?.postMessage(
52
- {
53
- type: "app_error",
54
- error: {
55
- title: title.toString(),
56
- details: details?.toString(),
57
- componentName: componentName?.toString(),
58
- stack: originalError?.stack?.toString(),
59
- },
60
- },
61
- "*"
62
- );
63
- }
31
+ });
32
+ }
64
33
 
65
- function handleUnhandledRejection(event: any) {
66
- const stack = event.reason.stack;
67
- // extract function name from "at X (eval" where x is the function name
68
- const functionName = stack.match(/at\s+(\w+)\s+\(eval/)?.[1];
69
- const msg = functionName
70
- ? `Error in ${functionName}: ${event.reason.toString()}`
71
- : event.reason.toString();
72
- onAppError({
73
- title: msg,
74
- details: event.reason.toString(),
75
- componentName: functionName,
76
- originalError: event.reason,
77
- });
34
+ function onAppError({
35
+ title,
36
+ details,
37
+ componentName,
38
+ originalError,
39
+ }: {
40
+ title: string;
41
+ details: string;
42
+ componentName: string;
43
+ originalError: any;
44
+ }) {
45
+ if (originalError?.response?.status === 402 || !shouldPropagateErrors) {
46
+ return;
78
47
  }
48
+ window.parent?.postMessage(
49
+ {
50
+ type: "app_error",
51
+ error: {
52
+ title: title.toString(),
53
+ details: details?.toString(),
54
+ componentName: componentName?.toString(),
55
+ stack: originalError?.stack?.toString(),
56
+ },
57
+ },
58
+ "*"
59
+ );
60
+ }
79
61
 
80
- function handleWindowError(event: any) {
81
- const stack = event.error?.stack;
82
- let functionName = stack.match(/at\s+(\w+)\s+\(eval/)?.[1];
83
- if (functionName === "eval") {
84
- functionName = null;
85
- }
62
+ function handleUnhandledRejection(event: any) {
63
+ const stack = event.reason.stack;
64
+ // extract function name from "at X (eval" where x is the function name
65
+ const functionName = stack.match(/at\s+(\w+)\s+\(eval/)?.[1];
66
+ const msg = functionName
67
+ ? `Error in ${functionName}: ${event.reason.toString()}`
68
+ : event.reason.toString();
69
+ onAppError({
70
+ title: msg,
71
+ details: event.reason.toString(),
72
+ componentName: functionName,
73
+ originalError: event.reason,
74
+ });
75
+ }
86
76
 
87
- const msg = functionName
88
- ? `in ${functionName}: ${event.error.toString()}`
89
- : event.error.toString();
90
- onAppError({
91
- title: msg,
92
- details: event.error.toString(),
93
- componentName: functionName,
94
- originalError: event.error,
95
- });
77
+ function handleWindowError(event: any) {
78
+ const stack = event.error?.stack;
79
+ let functionName = stack.match(/at\s+(\w+)\s+\(eval/)?.[1];
80
+ if (functionName === "eval") {
81
+ functionName = null;
96
82
  }
83
+
84
+ const msg = functionName
85
+ ? `in ${functionName}: ${event.error.toString()}`
86
+ : event.error.toString();
87
+ onAppError({
88
+ title: msg,
89
+ details: event.error.toString(),
90
+ componentName: functionName,
91
+ originalError: event.error,
92
+ });
97
93
  }
@@ -1,6 +1,6 @@
1
1
  import { findElementsById, updateElementClasses } from "./utils.js";
2
2
 
3
- export function setupVisualEditAgent() {
3
+ if (window.self !== window.top) {
4
4
  // State variables (replacing React useState/useRef)
5
5
  let isVisualEditMode = false;
6
6
  let isPopoverDragging = false;
@@ -558,4 +558,4 @@ export function setupVisualEditAgent() {
558
558
 
559
559
  // Send ready message to parent
560
560
  window.parent.postMessage({ type: "visual-edit-agent-ready" }, "*");
561
- }
561
+ }
package/README.md DELETED
@@ -1,93 +0,0 @@
1
- # @base44/vite-plugin
2
-
3
- Vite plugin for Base44 applications running in sandboxed iframes. Provides error tracking, HMR notifications, visual editing, navigation tracking, and legacy SDK compatibility.
4
-
5
- ## Installation
6
-
7
- ```bash
8
- npm install @base44/vite-plugin
9
- ```
10
-
11
- ## Usage
12
-
13
- ```ts
14
- // vite.config.ts
15
- import base44 from "@base44/vite-plugin";
16
-
17
- export default {
18
- plugins: [
19
- base44({
20
- legacySDKImports: false,
21
- hmrNotifier: true,
22
- navigationNotifier: true,
23
- visualEditAgent: true,
24
- }),
25
- ],
26
- };
27
- ```
28
-
29
- ### Options
30
-
31
- | Option | Type | Default | Description |
32
- | -------------------- | --------- | ------- | --------------------------------------------------- |
33
- | `legacySDKImports` | `boolean` | `false` | Enable legacy SDK import resolution via compat layer |
34
- | `hmrNotifier` | `boolean` | `false` | Notify parent window of HMR update lifecycle |
35
- | `navigationNotifier` | `boolean` | `false` | Track URL changes and notify parent window |
36
- | `visualEditAgent` | `boolean` | `false` | Enable interactive visual element editing |
37
-
38
- ## Architecture
39
-
40
- ### Plugin Composition
41
-
42
- The plugin registers four sub-plugins when running in a sandbox (`MODAL_SANDBOX_ID` is set):
43
-
44
- 1. **base44** — Core configuration: path aliases (`@/` → `/src/`), environment variables, dependency optimization, and legacy SDK import resolution.
45
- 2. **iframe-hmr** — Sets CORS and `frame-ancestors` headers to allow iframe embedding.
46
- 3. **error-overlay** — Replaces Vite's default error overlay with a custom one that reports errors to the parent window.
47
- 4. **html-injections** — Injects the sandbox bridge script into the HTML.
48
-
49
- Outside a sandbox, only the core plugin runs (with optional API proxy support via `VITE_BASE44_APP_BASE_URL`).
50
-
51
- ### Sandbox Bridge
52
-
53
- The bridge (`src/bridge.ts`) is a single ES module that consolidates all sandbox-side features. Instead of injecting multiple individual `<script>` tags, the HTML injections plugin injects one inline script that dynamically imports the bridge and calls `init()` with the configured options.
54
-
55
- The bridge conditionally sets up:
56
-
57
- - **Error handlers** — Global `error` and `unhandledrejection` listeners that report to the parent via `postMessage`.
58
- - **Mount observer** — `MutationObserver` that detects when instrumented elements (`data-source-location`) are rendered.
59
- - **HMR notifier** — Forwards Vite's `beforeUpdate`/`afterUpdate` events to the parent.
60
- - **Navigation notifier** — Intercepts `pushState`, `replaceState`, and `popstate` to track URL changes.
61
- - **Visual edit agent** — Overlay system for selecting and editing elements with source location awareness.
62
-
63
- ### Local Development
64
-
65
- For developing the bridge itself, you can load it from a local dev server instead of the installed package:
66
-
67
- 1. Generate local HTTPS certificates:
68
- ```bash
69
- mkcert localhost
70
- ```
71
-
72
- 2. Start the dev server (with optional watch mode):
73
- ```bash
74
- npm run dev # serve dist/statics/ on https://localhost:3201
75
- npm run dev -- -w # same, with auto-rebuild on changes
76
- ```
77
-
78
- 3. Add `?sandbox-bridge=local` to your app's URL to load the bridge from `localhost:3201` instead of `node_modules`.
79
-
80
- ### Legacy SDK Compatibility
81
-
82
- When `legacySDKImports` is enabled, imports of `/entities`, `/functions`, `/integrations`, and `/agents` are resolved to compatibility modules in `compat/`. These use `Proxy` objects to route calls to the Base44 SDK client.
83
-
84
- ## Building
85
-
86
- ```bash
87
- npm run build # TypeScript compilation (plugin)
88
- npm run build:bridge # tsup bundle (bridge ES module for browsers)
89
- ```
90
-
91
- ## License
92
-
93
- MIT
package/dist/bridge.d.ts DELETED
@@ -1,20 +0,0 @@
1
- /**
2
- * Sandbox bridge entry point — dynamically imported by the inline script
3
- * injected via html-injections-plugin. Conditionally initialises each
4
- * sandbox-side feature based on the supplied options.
5
- */
6
- /**
7
- * Initialise the sandbox bridge. Called once from the injected inline script.
8
- * @param options Feature flags — each defaults to enabled unless explicitly disabled.
9
- * @param hmr Vite's HMR client (`import.meta.hot`), passed only in dev mode.
10
- */
11
- export declare function init(options?: {
12
- unhandledErrors?: boolean;
13
- mountObserver?: boolean;
14
- hmrNotifier?: boolean;
15
- navigationNotifier?: boolean;
16
- visualEditAgent?: boolean;
17
- }, hmr?: {
18
- on(event: string, cb: (...args: any[]) => void): void;
19
- }): void;
20
- //# sourceMappingURL=bridge.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"bridge.d.ts","sourceRoot":"","sources":["../src/bridge.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAQH;;;;GAIG;AACH,wBAAgB,IAAI,CAClB,OAAO,GAAE;IACP,eAAe,CAAC,EAAE,OAAO,CAAC;IAC1B,aAAa,CAAC,EAAE,OAAO,CAAC;IACxB,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB,kBAAkB,CAAC,EAAE,OAAO,CAAC;IAC7B,eAAe,CAAC,EAAE,OAAO,CAAC;CACtB,EACN,GAAG,CAAC,EAAE;IAAE,EAAE,CAAC,KAAK,EAAE,MAAM,EAAE,EAAE,EAAE,CAAC,GAAG,IAAI,EAAE,GAAG,EAAE,KAAK,IAAI,GAAG,IAAI,CAAA;CAAE,QAWhE"}
package/dist/bridge.js DELETED
@@ -1,33 +0,0 @@
1
- /**
2
- * Sandbox bridge entry point — dynamically imported by the inline script
3
- * injected via html-injections-plugin. Conditionally initialises each
4
- * sandbox-side feature based on the supplied options.
5
- */
6
- import { setupUnhandledErrors } from "./injections/unhandled-errors-handlers.js";
7
- import { setupHmrNotifier } from "./injections/sandbox-hmr-notifier.js";
8
- import { setupMountObserver } from "./injections/sandbox-mount-observer.js";
9
- import { setupNavigationNotifier } from "./injections/navigation-notifier.js";
10
- import { setupVisualEditAgent } from "./injections/visual-edit-agent.js";
11
- /**
12
- * Initialise the sandbox bridge. Called once from the injected inline script.
13
- * @param options Feature flags — each defaults to enabled unless explicitly disabled.
14
- * @param hmr Vite's HMR client (`import.meta.hot`), passed only in dev mode.
15
- */
16
- export function init(options = {}, hmr) {
17
- if (window.self === window.top)
18
- return;
19
- if (globalThis.__sandboxBridgeInitialized)
20
- return;
21
- globalThis.__sandboxBridgeInitialized = true;
22
- if (options.unhandledErrors !== false)
23
- setupUnhandledErrors(hmr);
24
- if (options.mountObserver !== false)
25
- setupMountObserver();
26
- if (options.hmrNotifier && hmr)
27
- setupHmrNotifier(hmr);
28
- if (options.navigationNotifier)
29
- setupNavigationNotifier();
30
- if (options.visualEditAgent)
31
- setupVisualEditAgent();
32
- }
33
- //# sourceMappingURL=bridge.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"bridge.js","sourceRoot":"","sources":["../src/bridge.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EAAE,oBAAoB,EAAE,MAAM,2CAA2C,CAAC;AACjF,OAAO,EAAE,gBAAgB,EAAE,MAAM,sCAAsC,CAAC;AACxE,OAAO,EAAE,kBAAkB,EAAE,MAAM,wCAAwC,CAAC;AAC5E,OAAO,EAAE,uBAAuB,EAAE,MAAM,qCAAqC,CAAC;AAC9E,OAAO,EAAE,oBAAoB,EAAE,MAAM,mCAAmC,CAAC;AAEzE;;;;GAIG;AACH,MAAM,UAAU,IAAI,CAClB,UAMI,EAAE,EACN,GAA+D;IAE/D,IAAI,MAAM,CAAC,IAAI,KAAK,MAAM,CAAC,GAAG;QAAE,OAAO;IACvC,IAAK,UAAkB,CAAC,0BAA0B;QAAE,OAAO;IAC1D,UAAkB,CAAC,0BAA0B,GAAG,IAAI,CAAC;IAEtD,IAAI,OAAO,CAAC,eAAe,KAAK,KAAK;QAAE,oBAAoB,CAAC,GAAG,CAAC,CAAC;IACjE,IAAI,OAAO,CAAC,aAAa,KAAK,KAAK;QAAE,kBAAkB,EAAE,CAAC;IAC1D,IAAI,OAAO,CAAC,WAAW,IAAI,GAAG;QAAE,gBAAgB,CAAC,GAAG,CAAC,CAAC;IACtD,IAAI,OAAO,CAAC,kBAAkB;QAAE,uBAAuB,EAAE,CAAC;IAC1D,IAAI,OAAO,CAAC,eAAe;QAAE,oBAAoB,EAAE,CAAC;AACtD,CAAC"}
@@ -1,2 +0,0 @@
1
- function I(r){window.removeEventListener("unhandledrejection",a),window.removeEventListener("error",f),window.addEventListener("unhandledrejection",a),window.addEventListener("error",f);let d=!0,p=null;r&&(r.on("vite:beforeUpdate",()=>{d=!1,p&&clearTimeout(p),p=setTimeout(()=>{d=!0,p=null},1e4)}),r.on("vite:beforeFullReload",()=>{d=!1,p&&(clearTimeout(p),p=null)}));function g({title:s,details:w,componentName:u,originalError:m}){m?.response?.status===402||!d||window.parent?.postMessage({type:"app_error",error:{title:s.toString(),details:w?.toString(),componentName:u?.toString(),stack:m?.stack?.toString()}},"*")}function a(s){let u=s.reason.stack.match(/at\s+(\w+)\s+\(eval/)?.[1],m=u?`Error in ${u}: ${s.reason.toString()}`:s.reason.toString();g({title:m,details:s.reason.toString(),componentName:u,originalError:s.reason})}function f(s){let u=(s.error?.stack).match(/at\s+(\w+)\s+\(eval/)?.[1];u==="eval"&&(u=null);let m=u?`in ${u}: ${s.error.toString()}`:s.error.toString();g({title:m,details:s.error.toString(),componentName:u,originalError:s.error})}}function x(r){r.on("vite:beforeUpdate",()=>{window.parent?.postMessage({type:"sandbox:beforeUpdate"},"*")}),r.on("vite:afterUpdate",()=>{window.parent?.postMessage({type:"sandbox:afterUpdate"},"*")})}function O(){new MutationObserver(d=>{let p=d.some(a=>a.addedNodes.length>0),g=d.some(a=>a.removedNodes.length>0);(p||g)&&(document.body.querySelectorAll("[data-source-location], [data-dynamic-content]").length>0?window.parent?.postMessage({type:"sandbox:onMounted"},"*"):window.parent?.postMessage({type:"sandbox:onUnmounted"},"*"))}).observe(document.body,{childList:!0,subtree:!0})}function k(){let r=window.location.href;function d(){let a=window.location.href;a!==r&&(r=a,window.parent?.postMessage({type:"app_changed_url",url:a},"*"))}let p=history.pushState.bind(history);history.pushState=function(...a){p(...a),d()};let g=history.replaceState.bind(history);history.replaceState=function(...a){g(...a),d()},window.addEventListener("popstate",d),window.parent?.postMessage({type:"app_changed_url",url:window.location.href},"*")}function E(r){if(!r)return[];let d=Array.from(document.querySelectorAll(`[data-source-location="${r}"]`));return d.length>0?d:Array.from(document.querySelectorAll(`[data-visual-selector-id="${r}"]`))}function C(r,d){r.forEach(p=>{p.setAttribute("class",d)})}function A(){let r=!1,d=!1,p=!1,g=[],a=[],f=[],s=null,w=(n=!1)=>{let e=document.createElement("div");return e.style.position="absolute",e.style.pointerEvents="none",e.style.transition="all 0.1s ease-in-out",e.style.zIndex="9999",n?e.style.border="2px solid #2563EB":(e.style.border="2px solid #95a5fc",e.style.backgroundColor="rgba(99, 102, 241, 0.05)"),e},u=(n,e,t=!1)=>{if(!e||!r)return;e.offsetWidth;let o=e.getBoundingClientRect();n.style.top=`${o.top+window.scrollY}px`,n.style.left=`${o.left+window.scrollX}px`,n.style.width=`${o.width}px`,n.style.height=`${o.height}px`;let i=n.querySelector("div");i||(i=document.createElement("div"),i.textContent=e.tagName.toLowerCase(),i.style.position="absolute",i.style.top="-27px",i.style.left="-2px",i.style.padding="2px 8px",i.style.fontSize="11px",i.style.fontWeight=t?"500":"400",i.style.color=t?"#ffffff":"#526cff",i.style.backgroundColor=t?"#526cff":"#DBEAFE",i.style.borderRadius="3px",i.style.minWidth="24px",i.style.textAlign="center",n.appendChild(i))},m=()=>{g.forEach(n=>{n&&n.parentNode&&n.remove()}),g=[],f=[]},N=n=>{if(!r||d)return;let e=n.target;if(p){m();return}if(e.tagName.toLowerCase()==="path"){m();return}let t=e.closest("[data-source-location], [data-visual-selector-id]");if(!t){m();return}let l=t,o=l.dataset.sourceLocation||l.dataset.visualSelectorId;if(s===o){m();return}let i=E(o||null);m(),i.forEach(c=>{let h=w(!1);document.body.appendChild(h),g.push(h),u(h,c)}),f=i},M=()=>{d||m()},S=n=>{if(!r)return;let e=n.target;if(p){n.preventDefault(),n.stopPropagation(),n.stopImmediatePropagation(),window.parent.postMessage({type:"close-dropdowns"},"*");return}if(e.tagName.toLowerCase()==="path")return;n.preventDefault(),n.stopPropagation(),n.stopImmediatePropagation();let t=e.closest("[data-source-location], [data-visual-selector-id]");if(!t)return;let l=t,o=l.dataset.sourceLocation||l.dataset.visualSelectorId;a.forEach(v=>{v&&v.parentNode&&v.remove()}),a=[],E(o||null).forEach(v=>{let L=w(!0);document.body.appendChild(L),a.push(L),u(L,v,!0)}),s=o||null,m();let c=t.getBoundingClientRect(),h={top:c.top,left:c.left,right:c.right,bottom:c.bottom,width:c.width,height:c.height,centerX:c.left+c.width/2,centerY:c.top+c.height/2},y=t,_={type:"element-selected",tagName:t.tagName,classes:y.className?.baseVal||t.className||"",visualSelectorId:o,content:t.innerText,dataSourceLocation:l.dataset.sourceLocation,isDynamicContent:l.dataset.dynamicContent==="true",linenumber:l.dataset.linenumber,filename:l.dataset.filename,position:h};window.parent.postMessage(_,"*")},H=()=>{a.forEach(n=>{n&&n.parentNode&&n.remove()}),a=[],s=null},R=(n,e)=>{let t=E(n);t.length!==0&&(C(t,e),setTimeout(()=>{s===n&&a.forEach((l,o)=>{o<t.length&&u(l,t[o])}),f.length>0&&f[0]?.dataset?.visualSelectorId===n&&g.forEach((i,c)=>{c<f.length&&u(i,f[c])})},50))},D=(n,e)=>{let t=E(n);t.length!==0&&(t.forEach(l=>{l.innerText=e}),setTimeout(()=>{s===n&&a.forEach((l,o)=>{o<t.length&&u(l,t[o])})},50))},U=n=>{r=n,n?(document.body.style.cursor="crosshair",document.addEventListener("mouseover",N),document.addEventListener("mouseout",M),document.addEventListener("click",S,!0)):(m(),a.forEach(e=>{e&&e.parentNode&&e.remove()}),a=[],f=[],s=null,document.body.style.cursor="default",document.removeEventListener("mouseover",N),document.removeEventListener("mouseout",M),document.removeEventListener("click",S,!0))},T=()=>{if(s){let n=E(s);if(n.length>0){let t=n[0].getBoundingClientRect(),l=window.innerHeight,o=window.innerWidth,i=t.top<l&&t.bottom>0&&t.left<o&&t.right>0,c={top:t.top,left:t.left,right:t.right,bottom:t.bottom,width:t.width,height:t.height,centerX:t.left+t.width/2,centerY:t.top+t.height/2};window.parent.postMessage({type:"element-position-update",position:c,isInViewport:i,visualSelectorId:s},"*")}}},P=n=>{let e=n.data;switch(e.type){case"toggle-visual-edit-mode":U(e.data.enabled);break;case"update-classes":e.data&&e.data.classes!==void 0?R(e.data.visualSelectorId,e.data.classes):console.warn("[VisualEditAgent] Invalid update-classes message:",e);break;case"unselect-element":H();break;case"refresh-page":window.location.reload();break;case"update-content":e.data&&e.data.content!==void 0?D(e.data.visualSelectorId,e.data.content):console.warn("[VisualEditAgent] Invalid update-content message:",e);break;case"request-element-position":if(s){let t=E(s);if(t.length>0){let o=t[0].getBoundingClientRect(),i=window.innerHeight,c=window.innerWidth,h=o.top<i&&o.bottom>0&&o.left<c&&o.right>0,y={top:o.top,left:o.left,right:o.right,bottom:o.bottom,width:o.width,height:o.height,centerX:o.left+o.width/2,centerY:o.top+o.height/2};window.parent.postMessage({type:"element-position-update",position:y,isInViewport:h,visualSelectorId:s},"*")}}break;case"popover-drag-state":e.data&&e.data.isDragging!==void 0&&(d=e.data.isDragging,e.data.isDragging&&m());break;case"dropdown-state":e.data&&e.data.isOpen!==void 0&&(p=e.data.isOpen,e.data.isOpen&&m());break;default:break}},b=()=>{if(s){let n=E(s);a.forEach((e,t)=>{t<n.length&&u(e,n[t])})}f.length>0&&g.forEach((n,e)=>{e<f.length&&u(n,f[e])})};document.querySelectorAll("[data-linenumber]:not([data-visual-selector-id])").forEach((n,e)=>{let t=n,l=`visual-id-${t.dataset.filename}-${t.dataset.linenumber}-${e}`;t.dataset.visualSelectorId=l});let V=new MutationObserver(n=>{n.some(t=>{let l=i=>{if(i.nodeType===Node.ELEMENT_NODE){let c=i;if(c.dataset&&c.dataset.visualSelectorId)return!0;for(let h=0;h<c.children.length;h++)if(l(c.children[h]))return!0}return!1};return t.type==="attributes"&&(t.attributeName==="style"||t.attributeName==="class"||t.attributeName==="width"||t.attributeName==="height")&&l(t.target)})&&setTimeout(b,50)});window.addEventListener("message",P),window.addEventListener("scroll",T,!0),document.addEventListener("scroll",T,!0),window.addEventListener("resize",b),window.addEventListener("scroll",b),V.observe(document.body,{attributes:!0,childList:!0,subtree:!0,attributeFilter:["style","class","width","height"]}),window.parent.postMessage({type:"visual-edit-agent-ready"},"*")}function Z(r={},d){window.self!==window.top&&(globalThis.__sandboxBridgeInitialized||(globalThis.__sandboxBridgeInitialized=!0,r.unhandledErrors!==!1&&I(d),r.mountObserver!==!1&&O(),r.hmrNotifier&&d&&x(d),r.navigationNotifier&&k(),r.visualEditAgent&&A()))}export{Z as init};
2
- //# sourceMappingURL=index.mjs.map