@base44-preview/vite-plugin 0.2.20-pr.27.3c8770e → 0.2.20-pr.29.d7fd4ea

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 (42) hide show
  1. package/dist/html-injections-plugin.d.ts +2 -4
  2. package/dist/html-injections-plugin.d.ts.map +1 -1
  3. package/dist/html-injections-plugin.js +65 -42
  4. package/dist/html-injections-plugin.js.map +1 -1
  5. package/dist/injections/analytics-tracker.js +0 -1
  6. package/dist/injections/analytics-tracker.js.map +1 -1
  7. package/dist/injections/navigation-notifier.d.ts +1 -2
  8. package/dist/injections/navigation-notifier.d.ts.map +1 -1
  9. package/dist/injections/navigation-notifier.js +2 -2
  10. package/dist/injections/navigation-notifier.js.map +1 -1
  11. package/dist/injections/sandbox-hmr-notifier.d.ts +1 -4
  12. package/dist/injections/sandbox-hmr-notifier.d.ts.map +1 -1
  13. package/dist/injections/sandbox-hmr-notifier.js +4 -4
  14. package/dist/injections/sandbox-hmr-notifier.js.map +1 -1
  15. package/dist/injections/sandbox-mount-observer.d.ts +1 -2
  16. package/dist/injections/sandbox-mount-observer.d.ts.map +1 -1
  17. package/dist/injections/sandbox-mount-observer.js +2 -2
  18. package/dist/injections/sandbox-mount-observer.js.map +1 -1
  19. package/dist/injections/unhandled-errors-handlers.d.ts +1 -4
  20. package/dist/injections/unhandled-errors-handlers.d.ts.map +1 -1
  21. package/dist/injections/unhandled-errors-handlers.js +67 -69
  22. package/dist/injections/unhandled-errors-handlers.js.map +1 -1
  23. package/dist/injections/visual-edit-agent.d.ts +1 -1
  24. package/dist/injections/visual-edit-agent.d.ts.map +1 -1
  25. package/dist/injections/visual-edit-agent.js +40 -1
  26. package/dist/injections/visual-edit-agent.js.map +1 -1
  27. package/package.json +2 -8
  28. package/src/html-injections-plugin.ts +88 -53
  29. package/src/injections/analytics-tracker.ts +0 -2
  30. package/src/injections/navigation-notifier.ts +1 -2
  31. package/src/injections/sandbox-hmr-notifier.ts +3 -4
  32. package/src/injections/sandbox-mount-observer.ts +2 -2
  33. package/src/injections/unhandled-errors-handlers.ts +80 -84
  34. package/src/injections/visual-edit-agent.ts +57 -2
  35. package/README.md +0 -93
  36. package/dist/bridge.d.ts +0 -20
  37. package/dist/bridge.d.ts.map +0 -1
  38. package/dist/bridge.js +0 -33
  39. package/dist/bridge.js.map +0 -1
  40. package/dist/statics/index.mjs +0 -2
  41. package/dist/statics/index.mjs.map +0 -1
  42. 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.3c8770e",
3
+ "version": "0.2.20-pr.29.d7fd4ea",
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,6 +1,15 @@
1
1
  import type { Plugin, HtmlTagDescriptor } from "vite";
2
2
  import { loadEnv } from "vite";
3
3
 
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
+
4
13
  const ANALYTICS_TRACKER_SCRIPT = `
5
14
  let lastPath = "";
6
15
  function getPageNameFromPath(path) {
@@ -33,19 +42,59 @@ window.addEventListener("popstate", trackPageView);
33
42
  trackPageView();
34
43
  `;
35
44
 
36
- interface HtmlInjectionOptions {
37
- hmrNotifier: boolean;
38
- navigationNotifier: boolean;
39
- visualEditAgent: boolean;
40
- analyticsTracker: boolean;
41
- }
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
+ };
42
77
 
43
78
  export function htmlInjectionsPlugin({
44
79
  hmrNotifier,
45
80
  navigationNotifier,
46
81
  visualEditAgent,
47
82
  analyticsTracker,
48
- }: HtmlInjectionOptions): Plugin {
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
+
49
98
  let resolvedEnv: Record<string, string> = {};
50
99
 
51
100
  return {
@@ -57,58 +106,44 @@ export function htmlInjectionsPlugin({
57
106
  },
58
107
  transformIndexHtml: {
59
108
  handler(_html, ctx) {
60
- const tags: HtmlTagDescriptor[] = [];
61
109
  const currentMode = ctx.server ? "dev" : "production";
62
110
 
63
- if (currentMode === "dev") {
64
- // Dev mode: use sandbox-bridge dynamic loader
65
- const options = JSON.stringify({
66
- hmrNotifier,
67
- navigationNotifier,
68
- visualEditAgent,
69
- unhandledErrors: true,
70
- mountObserver: true,
71
- });
72
- tags.push({
73
- tag: "script",
74
- attrs: { type: "module" },
75
- children: [
76
- `if (window.self !== window.top) {`,
77
- ` (async () => {`,
78
- ` try {`,
79
- ` const mode = new URLSearchParams(location.search).get("sandbox-bridge");`,
80
- ` const url = mode === "local"`,
81
- ` ? "https://localhost:3201/index.mjs"`,
82
- ` : "/node_modules/@base44/vite-plugin/dist/statics/index.mjs";`,
83
- ` const mod = await import(url);`,
84
- ` if (typeof mod.init === "function") mod.init(${options}, import.meta.hot);`,
85
- ` } catch (e) {`,
86
- ` console.error("[sandbox-bridge] Failed to load:", e);`,
87
- ` }`,
88
- ` })();`,
89
- `}`,
90
- ].join("\n"),
91
- injectTo: "head",
92
- });
93
- }
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
+ );
94
126
 
95
- // Production: inline analytics tracker with env var replacement
96
- if (currentMode === "production" && analyticsTracker) {
97
- let content = ANALYTICS_TRACKER_SCRIPT;
98
- content = content.replace(
99
- /import\.meta\.env\.(\w+)/g,
100
- (_, envKey) => JSON.stringify(resolvedEnv[envKey] ?? "")
101
- );
102
- tags.push({
103
- tag: "script",
104
- attrs: { type: "module" },
105
- children: content,
106
- injectTo: "head",
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
+ };
107
143
  });
108
- }
109
144
 
110
145
  return tags;
111
146
  },
112
147
  },
113
- };
148
+ } as Plugin;
114
149
  }
@@ -1,8 +1,6 @@
1
1
  // Analytics tracker - tracks page views in production
2
2
  // This script is only injected in production builds
3
3
 
4
- /// <reference types="vite/client" />
5
-
6
4
  let lastPath = "";
7
5
 
8
6
  function getPageNameFromPath(path: string): string | null {
@@ -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;
@@ -216,6 +216,16 @@ export function setupVisualEditAgent() {
216
216
  centerY: rect.top + rect.height / 2,
217
217
  };
218
218
 
219
+ // Collect allowed element attributes
220
+ const ALLOWED_ATTRIBUTES: string[] = ["src"];
221
+ const attributes: Record<string, string> = {};
222
+ for (const attr of ALLOWED_ATTRIBUTES) {
223
+ const val = element.getAttribute(attr);
224
+ if (val !== null) {
225
+ attributes[attr] = val;
226
+ }
227
+ }
228
+
219
229
  // Send message to parent window with element info including position
220
230
  const svgElement = element as SVGElement;
221
231
  const elementData = {
@@ -232,6 +242,7 @@ export function setupVisualEditAgent() {
232
242
  linenumber: htmlElement.dataset.linenumber,
233
243
  filename: htmlElement.dataset.filename,
234
244
  position: elementPosition,
245
+ attributes,
235
246
  };
236
247
  window.parent.postMessage(elementData, "*");
237
248
  };
@@ -279,6 +290,31 @@ export function setupVisualEditAgent() {
279
290
  }, 50);
280
291
  };
281
292
 
293
+ // Update element attribute by visual selector ID
294
+ const updateElementAttribute = (
295
+ visualSelectorId: string,
296
+ attribute: string,
297
+ value: string
298
+ ) => {
299
+ const elements = findElementsById(visualSelectorId);
300
+ if (elements.length === 0) return;
301
+
302
+ elements.forEach((element) => {
303
+ element.setAttribute(attribute, value);
304
+ });
305
+
306
+ // Reposition overlays after attribute change (e.g. image src swap can affect layout)
307
+ setTimeout(() => {
308
+ if (selectedElementId === visualSelectorId) {
309
+ selectedOverlays.forEach((overlay, index) => {
310
+ if (index < elements.length) {
311
+ positionOverlay(overlay, elements[index]!);
312
+ }
313
+ });
314
+ }
315
+ }, 50);
316
+ };
317
+
282
318
  // Update element content by visual selector ID
283
319
  const updateElementContent = (visualSelectorId: string, content: string) => {
284
320
  const elements = findElementsById(visualSelectorId);
@@ -394,6 +430,25 @@ export function setupVisualEditAgent() {
394
430
  }
395
431
  break;
396
432
 
433
+ case "update-attribute":
434
+ if (
435
+ message.data &&
436
+ message.data.attribute !== undefined &&
437
+ message.data.value !== undefined
438
+ ) {
439
+ updateElementAttribute(
440
+ message.data.visualSelectorId,
441
+ message.data.attribute,
442
+ message.data.value
443
+ );
444
+ } else {
445
+ console.warn(
446
+ "[VisualEditAgent] Invalid update-attribute message:",
447
+ message
448
+ );
449
+ }
450
+ break;
451
+
397
452
  case "unselect-element":
398
453
  unselectElement();
399
454
  break;
@@ -558,4 +613,4 @@ export function setupVisualEditAgent() {
558
613
 
559
614
  // Send ready message to parent
560
615
  window.parent.postMessage({ type: "visual-edit-agent-ready" }, "*");
561
- }
616
+ }
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"}