@base44-preview/vite-plugin 0.1.0-dev.e65cc11 → 0.1.0-dev.ec354c8

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.
@@ -0,0 +1,12 @@
1
+ declare const HTMLElement: {
2
+ new (): {};
3
+ };
4
+ export declare class ErrorOverlay extends HTMLElement {
5
+ static getOverlayHTML(): string;
6
+ close(): void;
7
+ static sendErrorToParent(error: Error, title: string, details: string | undefined, componentName: string | undefined): void;
8
+ constructor(error: Error);
9
+ }
10
+ export declare const errorOverlayCode: string;
11
+ export {};
12
+ //# sourceMappingURL=ErrorOverlay.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ErrorOverlay.d.ts","sourceRoot":"","sources":["../src/ErrorOverlay.ts"],"names":[],"mappings":"AAGA,QAAA,MAAQ,WAAW;;CAA0B,CAAC;AAE9C,qBAAa,YAAa,SAAQ,WAAW;IAC3C,MAAM,CAAC,cAAc;IAMrB,KAAK;IAIL,MAAM,CAAC,iBAAiB,CACtB,KAAK,EAAE,KAAK,EACZ,KAAK,EAAE,MAAM,EACb,OAAO,EAAE,MAAM,GAAG,SAAS,EAC3B,aAAa,EAAE,MAAM,GAAG,SAAS;gBAqBvB,KAAK,EAAE,KAAK;CAuBzB;AAGD,eAAO,MAAM,gBAAgB,QAG5B,CAAC"}
@@ -0,0 +1,51 @@
1
+ /// <reference lib="dom" />
2
+ // Make HTMLElement available in non-browser environments
3
+ const { HTMLElement = class {
4
+ } } = globalThis;
5
+ export class ErrorOverlay extends HTMLElement {
6
+ static getOverlayHTML() {
7
+ return `
8
+ <div>
9
+ </div>
10
+ `;
11
+ }
12
+ close() {
13
+ this.parentNode?.removeChild(this);
14
+ }
15
+ static sendErrorToParent(error, title, details, componentName) {
16
+ // Send error to parent using framewire
17
+ if (globalThis.window?.parent) {
18
+ try {
19
+ globalThis.window.parent?.postMessage({
20
+ type: "app_error",
21
+ error: { title, details, componentName, originalError: error },
22
+ }, "*");
23
+ }
24
+ catch (error) {
25
+ console.warn("Failed to send error to iframe parent:", error?.message);
26
+ }
27
+ }
28
+ }
29
+ constructor(error) {
30
+ super();
31
+ const stack = error?.stack;
32
+ let componentName = stack?.match(/at\s+(\w+)\s+\(eval/)?.[1];
33
+ if (componentName === "eval") {
34
+ componentName = undefined;
35
+ }
36
+ const title = componentName
37
+ ? `in ${componentName}: ${error.message?.toString()}`
38
+ : error.message?.toString();
39
+ const details = error?.stack;
40
+ // Call editor frame with the error (via post message)
41
+ ErrorOverlay.sendErrorToParent(error, title, details, componentName);
42
+ // Create the overlay element using HTML template
43
+ const overlay = document.createElement("div");
44
+ overlay.innerHTML = ErrorOverlay.getOverlayHTML();
45
+ // Add to DOM
46
+ document.body.appendChild(overlay);
47
+ }
48
+ }
49
+ // vite/react-plugin transpiles classes with _SomeClass, so we need to replace all _ErrorOverlay with ErrorOverlay
50
+ export const errorOverlayCode = ErrorOverlay.toString().replaceAll("_ErrorOverlay", "ErrorOverlay");
51
+ //# sourceMappingURL=ErrorOverlay.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ErrorOverlay.js","sourceRoot":"","sources":["../src/ErrorOverlay.ts"],"names":[],"mappings":"AAAA,2BAA2B;AAE3B,yDAAyD;AACzD,MAAM,EAAE,WAAW,GAAG;CAAQ,EAAE,GAAG,UAAU,CAAC;AAE9C,MAAM,OAAO,YAAa,SAAQ,WAAW;IAC3C,MAAM,CAAC,cAAc;QACnB,OAAO;;;KAGN,CAAC;IACJ,CAAC;IACD,KAAK;QACF,IAAY,CAAC,UAAU,EAAE,WAAW,CAAC,IAAI,CAAC,CAAC;IAC9C,CAAC;IAED,MAAM,CAAC,iBAAiB,CACtB,KAAY,EACZ,KAAa,EACb,OAA2B,EAC3B,aAAiC;QAEjC,uCAAuC;QACvC,IAAI,UAAU,CAAC,MAAM,EAAE,MAAM,EAAE,CAAC;YAC9B,IAAI,CAAC;gBACH,UAAU,CAAC,MAAM,CAAC,MAAM,EAAE,WAAW,CACnC;oBACE,IAAI,EAAE,WAAW;oBACjB,KAAK,EAAE,EAAE,KAAK,EAAE,OAAO,EAAE,aAAa,EAAE,aAAa,EAAE,KAAK,EAAE;iBAC/D,EACD,GAAG,CACJ,CAAC;YACJ,CAAC;YAAC,OAAO,KAAK,EAAE,CAAC;gBACf,OAAO,CAAC,IAAI,CACV,wCAAwC,EACvC,KAAe,EAAE,OAAO,CAC1B,CAAC;YACJ,CAAC;QACH,CAAC;IACH,CAAC;IAED,YAAY,KAAY;QACtB,KAAK,EAAE,CAAC;QAER,MAAM,KAAK,GAAG,KAAK,EAAE,KAAK,CAAC;QAC3B,IAAI,aAAa,GAAG,KAAK,EAAE,KAAK,CAAC,qBAAqB,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC;QAC7D,IAAI,aAAa,KAAK,MAAM,EAAE,CAAC;YAC7B,aAAa,GAAG,SAAS,CAAC;QAC5B,CAAC;QACD,MAAM,KAAK,GAAG,aAAa;YACzB,CAAC,CAAC,MAAM,aAAa,KAAK,KAAK,CAAC,OAAO,EAAE,QAAQ,EAAE,EAAE;YACrD,CAAC,CAAC,KAAK,CAAC,OAAO,EAAE,QAAQ,EAAE,CAAC;QAC9B,MAAM,OAAO,GAAG,KAAK,EAAE,KAAK,CAAC;QAE7B,sDAAsD;QACtD,YAAY,CAAC,iBAAiB,CAAC,KAAK,EAAE,KAAK,EAAE,OAAO,EAAE,aAAa,CAAC,CAAC;QAErE,iDAAiD;QACjD,MAAM,OAAO,GAAG,QAAQ,CAAC,aAAa,CAAC,KAAK,CAAC,CAAC;QAC9C,OAAO,CAAC,SAAS,GAAG,YAAY,CAAC,cAAc,EAAE,CAAC;QAElD,aAAa;QACb,QAAQ,CAAC,IAAI,CAAC,WAAW,CAAC,OAAO,CAAC,CAAC;IACrC,CAAC;CACF;AAED,kHAAkH;AAClH,MAAM,CAAC,MAAM,gBAAgB,GAAG,YAAY,CAAC,QAAQ,EAAE,CAAC,UAAU,CAChE,eAAe,EACf,cAAc,CACf,CAAC"}
@@ -0,0 +1,3 @@
1
+ import type { Plugin } from "vite";
2
+ export declare function errorOverlayPlugin(): Plugin;
3
+ //# sourceMappingURL=error-overlay-plugin.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"error-overlay-plugin.d.ts","sourceRoot":"","sources":["../src/error-overlay-plugin.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,MAAM,CAAC;AAEnC,wBAAgB,kBAAkB,IAa3B,MAAM,CACZ"}
@@ -0,0 +1,14 @@
1
+ import { errorOverlayCode } from "./ErrorOverlay.js";
2
+ export function errorOverlayPlugin() {
3
+ return {
4
+ name: "error-overlay",
5
+ transform(code, id, opts = {}) {
6
+ if (opts?.ssr)
7
+ return;
8
+ if (!id.includes("vite/dist/client/client.mjs"))
9
+ return;
10
+ return code.replace("class ErrorOverlay", errorOverlayCode + "\nclass OldErrorOverlay");
11
+ },
12
+ };
13
+ }
14
+ //# sourceMappingURL=error-overlay-plugin.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"error-overlay-plugin.js","sourceRoot":"","sources":["../src/error-overlay-plugin.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,gBAAgB,EAAE,MAAM,mBAAmB,CAAC;AAGrD,MAAM,UAAU,kBAAkB;IAChC,OAAO;QACL,IAAI,EAAE,eAAe;QACrB,SAAS,CAAC,IAAI,EAAE,EAAE,EAAE,IAAI,GAAG,EAAE;YAC3B,IAAI,IAAI,EAAE,GAAG;gBAAE,OAAO;YAEtB,IAAI,CAAC,EAAE,CAAC,QAAQ,CAAC,6BAA6B,CAAC;gBAAE,OAAO;YAExD,OAAO,IAAI,CAAC,OAAO,CACjB,oBAAoB,EACpB,gBAAgB,GAAG,yBAAyB,CAC7C,CAAC;QACJ,CAAC;KACQ,CAAC;AACd,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,EAAc,MAAM,MAAM,CAAC;AAG/C,MAAM,CAAC,OAAO,UAAU,UAAU,CAChC,IAAI,GAAE;IACJ,gBAAgB,CAAC,EAAE,OAAO,CAAC;CACvB,GA6HD,MAAM,CACZ"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,EAAc,MAAM,MAAM,CAAC;AAK/C,MAAM,CAAC,OAAO,UAAU,UAAU,CAChC,IAAI,GAAE;IACJ,gBAAgB,CAAC,EAAE,OAAO,CAAC;CACvB,GAiID,MAAM,CACZ"}
package/dist/index.js CHANGED
@@ -1,11 +1,14 @@
1
1
  import { loadEnv } from "vite";
2
+ import { errorOverlayPlugin } from "./error-overlay-plugin.js";
3
+ import { visualEditPlugin } from "./visual-edit-plugin.js";
2
4
  export default function vitePlugin(opts = {}) {
3
5
  const { legacySDKImports = false } = opts;
4
6
  return {
5
7
  name: "base44",
8
+ enforce: "pre",
6
9
  config: ({ mode }) => {
7
10
  const env = loadEnv(mode ?? "development", process.cwd(), "");
8
- const isRunningInSandbox = process.env.BASE44_SANDBOX_MODE === "true";
11
+ const isRunningInSandbox = env.BASE44_SANDBOX_MODE === "true";
9
12
  return {
10
13
  resolve: {
11
14
  alias: {
@@ -26,6 +29,9 @@ export default function vitePlugin(opts = {}) {
26
29
  });
27
30
  },
28
31
  },
32
+ ...(mode === "development"
33
+ ? [errorOverlayPlugin(), visualEditPlugin()]
34
+ : []),
29
35
  ],
30
36
  server: {
31
37
  host: "0.0.0.0", // Bind to all interfaces for container access
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,OAAO,EAAE,MAAM,MAAM,CAAC;AAE/B,MAAM,CAAC,OAAO,UAAU,UAAU,CAChC,OAEI,EAAE;IAEN,MAAM,EAAE,gBAAgB,GAAG,KAAK,EAAE,GAAG,IAAI,CAAC;IAE1C,OAAO;QACL,IAAI,EAAE,QAAQ;QACd,MAAM,EAAE,CAAC,EAAE,IAAI,EAAE,EAAE,EAAE;YACnB,MAAM,GAAG,GAAG,OAAO,CAAC,IAAI,IAAI,aAAa,EAAE,OAAO,CAAC,GAAG,EAAE,EAAE,EAAE,CAAC,CAAC;YAC9D,MAAM,kBAAkB,GAAG,OAAO,CAAC,GAAG,CAAC,mBAAmB,KAAK,MAAM,CAAC;YAEtE,OAAO;gBACL,OAAO,EAAE;oBACP,KAAK,EAAE;wBACL,IAAI,EAAE,OAAO;qBACd;iBACF;gBACD,GAAG,CAAC,kBAAkB;oBACpB,CAAC,CAAE;wBACC,OAAO,EAAE;4BACP;gCACE,IAAI,EAAE,YAAY;gCAClB,eAAe,CAAC,MAAM;oCACpB,MAAM,CAAC,WAAW,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,GAAG,EAAE,IAAI,EAAE,EAAE;wCACxC,yBAAyB;wCACzB,GAAG,CAAC,SAAS,CAAC,iBAAiB,EAAE,UAAU,CAAC,CAAC;wCAC7C,GAAG,CAAC,SAAS,CACX,yBAAyB,EACzB,oBAAoB,CACrB,CAAC;wCACF,IAAI,EAAE,CAAC;oCACT,CAAC,CAAC,CAAC;gCACL,CAAC;6BACF;yBACF;wBACD,MAAM,EAAE;4BACN,IAAI,EAAE,SAAS,EAAE,8CAA8C;4BAC/D,IAAI,EAAE,IAAI;4BACV,UAAU,EAAE,IAAI;4BAChB,oDAAoD;4BACpD,YAAY,EAAE,IAAI;4BAClB,KAAK,EAAE;gCACL,gEAAgE;gCAChE,UAAU,EAAE,IAAI;gCAChB,QAAQ,EAAE,GAAG,EAAE,uCAAuC;6BACvD;4BACD,GAAG,EAAE;gCACH,QAAQ,EAAE,KAAK;gCACf,UAAU,EAAE,GAAG;6BAChB;yBACF;wBACD,KAAK,EAAE;4BACL,aAAa,EAAE;gCACb,MAAM,CAAC,OAAO,EAAE,IAAI;oCAClB,sCAAsC;oCACtC,IACE,OAAO,CAAC,IAAI,KAAK,mBAAmB;wCACpC,OAAO,CAAC,IAAI,KAAK,gBAAgB,EACjC,CAAC;wCACD,MAAM,IAAI,KAAK,CAAC,iBAAiB,OAAO,CAAC,OAAO,EAAE,CAAC,CAAC;oCACtD,CAAC;oCACD,iCAAiC;oCACjC,IAAI,CAAC,OAAO,CAAC,CAAC;gCAChB,CAAC;6BACF;yBACF;qBACsB;oBAC3B,CAAC,CAAC,EAAE,CAAC;gBACP,YAAY,EAAE;oBACZ,cAAc,EAAE;wBACd,MAAM,EAAE;4BACN,KAAK,EAAE,KAAK;yBACb;wBACD,GAAG,CAAC,gBAAgB;4BAClB,CAAC,CAAC;gCACE,MAAM,EAAE;oCACN,gCAAgC,EAAE,IAAI,CAAC,SAAS,CAC9C,GAAG,CAAC,kBAAkB,CACvB;oCACD,qCAAqC,EAAE,IAAI,CAAC,SAAS,CACnD,GAAG,CAAC,uBAAuB,CAC5B;iCACF;6BACF;4BACH,CAAC,CAAC,EAAE,CAAC;qBACR;iBACF;aACF,CAAC;QACJ,CAAC;QACD,SAAS,CAAC,MAAM,EAAE,QAAQ,EAAE,OAAO;YACjC,IAAI,gBAAgB,EAAE,CAAC;gBACrB,IAAI,MAAM,CAAC,QAAQ,CAAC,WAAW,CAAC,EAAE,CAAC;oBACjC,OAAO,IAAI,CAAC,OAAO,CACjB,yCAAyC,EACzC,QAAQ,EACR,OAAO,CACR,CAAC;gBACJ,CAAC;gBAED,IAAI,MAAM,CAAC,QAAQ,CAAC,YAAY,CAAC,EAAE,CAAC;oBAClC,OAAO,IAAI,CAAC,OAAO,CACjB,0CAA0C,EAC1C,QAAQ,EACR,OAAO,CACR,CAAC;gBACJ,CAAC;gBAED,IAAI,MAAM,CAAC,QAAQ,CAAC,eAAe,CAAC,EAAE,CAAC;oBACrC,OAAO,IAAI,CAAC,OAAO,CACjB,6CAA6C,EAC7C,QAAQ,EACR,OAAO,CACR,CAAC;gBACJ,CAAC;gBAED,IAAI,MAAM,CAAC,QAAQ,CAAC,UAAU,CAAC,EAAE,CAAC;oBAChC,OAAO,IAAI,CAAC,OAAO,CACjB,uCAAuC,EACvC,QAAQ,EACR,OAAO,CACR,CAAC;gBACJ,CAAC;YACH,CAAC;YAED,OAAO,IAAI,CAAC;QACd,CAAC;KACQ,CAAC;AACd,CAAC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,11 @@
1
+ export declare function visualEditPlugin(): {
2
+ name: string;
3
+ enforce: string;
4
+ order: string;
5
+ transformIndexHtml(html: any): any;
6
+ transform(code: any, id: any): {
7
+ code: any;
8
+ map: null;
9
+ } | null;
10
+ };
11
+ //# sourceMappingURL=visual-edit-plugin.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"visual-edit-plugin.d.ts","sourceRoot":"","sources":["../src/visual-edit-plugin.ts"],"names":[],"mappings":"AAkGA,wBAAgB,gBAAgB;;;;6BAMH,GAAG;oBAKZ,GAAG,MAAM,GAAG;;;;EA4J/B"}
@@ -0,0 +1,228 @@
1
+ import { parse } from "@babel/parser";
2
+ import { default as traverse } from "@babel/traverse";
3
+ import { default as generate } from "@babel/generator";
4
+ import * as t from "@babel/types";
5
+ // Helper function to check if JSX element contains dynamic content
6
+ function checkIfElementHasDynamicContent(jsxElement) {
7
+ let hasDynamicContent = false;
8
+ // Helper function to check if any node contains dynamic patterns
9
+ function checkNodeForDynamicContent(node) {
10
+ // JSX expressions like {variable}, {func()}, {obj.prop}
11
+ if (t.isJSXExpressionContainer(node)) {
12
+ const expression = node.expression;
13
+ // Skip empty expressions {}
14
+ if (t.isJSXEmptyExpression(expression)) {
15
+ return false;
16
+ }
17
+ // Any non-literal expression is considered dynamic
18
+ if (!t.isLiteral(expression)) {
19
+ return true;
20
+ }
21
+ }
22
+ // Template literals with expressions `Hello ${name}`
23
+ if (t.isTemplateLiteral(node) && node.expressions.length > 0) {
24
+ return true;
25
+ }
26
+ // Member expressions like props.title, state.value
27
+ if (t.isMemberExpression(node)) {
28
+ return true;
29
+ }
30
+ // Function calls like getData(), format()
31
+ if (t.isCallExpression(node)) {
32
+ return true;
33
+ }
34
+ // Conditional expressions like condition ? "yes" : "no"
35
+ if (t.isConditionalExpression(node)) {
36
+ return true;
37
+ }
38
+ // Identifier references (could be props, state, variables)
39
+ if (t.isIdentifier(node)) {
40
+ // Common dynamic identifiers
41
+ const dynamicNames = [
42
+ "props",
43
+ "state",
44
+ "data",
45
+ "item",
46
+ "value",
47
+ "text",
48
+ "content",
49
+ ];
50
+ if (dynamicNames.some((name) => node.name.includes(name))) {
51
+ return true;
52
+ }
53
+ }
54
+ return false;
55
+ }
56
+ // Recursively traverse all child nodes
57
+ function traverseNode(node) {
58
+ if (checkNodeForDynamicContent(node)) {
59
+ hasDynamicContent = true;
60
+ return;
61
+ }
62
+ // Recursively check child nodes
63
+ Object.keys(node).forEach((key) => {
64
+ const value = node[key];
65
+ if (Array.isArray(value)) {
66
+ value.forEach((child) => {
67
+ if (child && typeof child === "object" && child.type) {
68
+ traverseNode(child);
69
+ }
70
+ });
71
+ }
72
+ else if (value && typeof value === "object" && value.type) {
73
+ traverseNode(value);
74
+ }
75
+ });
76
+ }
77
+ // Check all children of the JSX element
78
+ jsxElement.children.forEach((child) => {
79
+ if (hasDynamicContent)
80
+ return; // Early exit if already found dynamic content
81
+ traverseNode(child);
82
+ });
83
+ return hasDynamicContent;
84
+ }
85
+ export function visualEditPlugin() {
86
+ return {
87
+ name: "visual-edit-transform",
88
+ enforce: "pre",
89
+ order: "pre",
90
+ // Inject Tailwind CDN for visual editing capabilities
91
+ transformIndexHtml(html) {
92
+ // Inject the Tailwind CSS CDN script right before the closing </head> tag
93
+ const tailwindScript = ` <!-- Tailwind CSS CDN for visual editing -->\n <script src="https://cdn.tailwindcss.com"></script>\n `;
94
+ return html.replace("</head>", tailwindScript + "</head>");
95
+ },
96
+ transform(code, id) {
97
+ // Skip node_modules and visual-edit-agent itself
98
+ if (id.includes("node_modules") || id.includes("visual-edit-agent")) {
99
+ return null;
100
+ }
101
+ // Process JS/JSX/TS/TSX files
102
+ if (!id.match(/\.(jsx?|tsx?)$/)) {
103
+ return null;
104
+ }
105
+ // Extract filename from path, preserving pages/ or components/ structure
106
+ const pathParts = id.split("/");
107
+ let filename;
108
+ // Check if this is a pages or components file
109
+ if (id.includes("/pages/")) {
110
+ const pagesIndex = pathParts.findIndex((part) => part === "pages");
111
+ if (pagesIndex >= 0 && pagesIndex < pathParts.length - 1) {
112
+ // Get all parts from 'pages' to the file, preserving nested structure
113
+ const relevantParts = pathParts.slice(pagesIndex, pathParts.length);
114
+ const lastPart = relevantParts[relevantParts.length - 1];
115
+ // Remove file extension from the last part
116
+ relevantParts[relevantParts.length - 1] = lastPart.includes(".")
117
+ ? lastPart.split(".")[0]
118
+ : lastPart;
119
+ filename = relevantParts.join("/");
120
+ }
121
+ else {
122
+ filename = pathParts[pathParts.length - 1];
123
+ if (filename.includes(".")) {
124
+ filename = filename.split(".")[0];
125
+ }
126
+ }
127
+ }
128
+ else if (id.includes("/components/")) {
129
+ const componentsIndex = pathParts.findIndex((part) => part === "components");
130
+ if (componentsIndex >= 0 && componentsIndex < pathParts.length - 1) {
131
+ // Get all parts from 'components' to the file, preserving nested structure
132
+ const relevantParts = pathParts.slice(componentsIndex, pathParts.length);
133
+ const lastPart = relevantParts[relevantParts.length - 1];
134
+ // Remove file extension from the last part
135
+ relevantParts[relevantParts.length - 1] = lastPart.includes(".")
136
+ ? lastPart.split(".")[0]
137
+ : lastPart;
138
+ filename = relevantParts.join("/");
139
+ }
140
+ else {
141
+ filename = pathParts[pathParts.length - 1];
142
+ if (filename.includes(".")) {
143
+ filename = filename.split(".")[0];
144
+ }
145
+ }
146
+ }
147
+ else {
148
+ // For other files (like layout), just use the filename
149
+ filename = pathParts[pathParts.length - 1];
150
+ if (filename.includes(".")) {
151
+ filename = filename.split(".")[0];
152
+ }
153
+ }
154
+ try {
155
+ // Parse the code into an AST
156
+ const ast = parse(code, {
157
+ sourceType: "module",
158
+ plugins: [
159
+ "jsx",
160
+ "typescript",
161
+ "decorators-legacy",
162
+ "classProperties",
163
+ "objectRestSpread",
164
+ "functionBind",
165
+ "exportDefaultFrom",
166
+ "exportNamespaceFrom",
167
+ "dynamicImport",
168
+ "nullishCoalescingOperator",
169
+ "optionalChaining",
170
+ "asyncGenerators",
171
+ "bigInt",
172
+ "optionalCatchBinding",
173
+ "throwExpressions",
174
+ ],
175
+ });
176
+ // Traverse the AST and add source location and dynamic content attributes to JSX elements
177
+ let elementsProcessed = 0;
178
+ traverse.default(ast, {
179
+ JSXElement(path) {
180
+ const jsxElement = path.node;
181
+ const openingElement = jsxElement.openingElement;
182
+ // Skip fragments
183
+ if (t.isJSXFragment(jsxElement))
184
+ return;
185
+ // Skip if already has source location attribute
186
+ const hasSourceLocation = openingElement.attributes.some((attr) => t.isJSXAttribute(attr) &&
187
+ t.isJSXIdentifier(attr.name) &&
188
+ attr.name.name === "data-source-location");
189
+ if (hasSourceLocation)
190
+ return;
191
+ // Get line and column from AST node location
192
+ const { line, column } = openingElement.loc?.start || {
193
+ line: 1,
194
+ column: 0,
195
+ };
196
+ // Create the source location attribute
197
+ const sourceLocationAttr = t.jsxAttribute(t.jsxIdentifier("data-source-location"), t.stringLiteral(`${filename}:${line}:${column}`));
198
+ // Check if element has dynamic content
199
+ const isDynamic = checkIfElementHasDynamicContent(jsxElement);
200
+ // Create the dynamic content attribute
201
+ const dynamicContentAttr = t.jsxAttribute(t.jsxIdentifier("data-dynamic-content"), t.stringLiteral(isDynamic ? "true" : "false"));
202
+ // Add both attributes to the beginning of the attributes array
203
+ openingElement.attributes.unshift(sourceLocationAttr, dynamicContentAttr);
204
+ elementsProcessed++;
205
+ },
206
+ });
207
+ // Generate the code back from the AST
208
+ const result = generate.default(ast, {
209
+ compact: false,
210
+ concise: false,
211
+ retainLines: true,
212
+ });
213
+ return {
214
+ code: result.code,
215
+ map: null,
216
+ };
217
+ }
218
+ catch (error) {
219
+ console.error("Failed to add source location to JSX:", error);
220
+ return {
221
+ code: code, // Return original code on failure
222
+ map: null,
223
+ };
224
+ }
225
+ },
226
+ };
227
+ }
228
+ //# sourceMappingURL=visual-edit-plugin.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"visual-edit-plugin.js","sourceRoot":"","sources":["../src/visual-edit-plugin.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@base44-preview/vite-plugin",
3
- "version": "0.1.0-dev.e65cc11",
3
+ "version": "0.1.0-dev.ec354c8",
4
4
  "description": "The Vite plugin for base44 based applications",
5
5
  "type": "module",
6
6
  "license": "MIT",
@@ -17,8 +17,16 @@
17
17
  "build": "tsc"
18
18
  },
19
19
  "devDependencies": {
20
+ "@types/babel__generator": "^7.27.0",
21
+ "@types/babel__traverse": "^7.28.0",
20
22
  "@types/node": "^24.6.2",
21
23
  "typescript": "^5.9.3",
22
24
  "vite": "^7.1.9"
25
+ },
26
+ "dependencies": {
27
+ "@babel/generator": "^7.28.5",
28
+ "@babel/parser": "^7.28.5",
29
+ "@babel/traverse": "^7.28.5",
30
+ "@babel/types": "^7.28.5"
23
31
  }
24
32
  }
@@ -0,0 +1,71 @@
1
+ /// <reference lib="dom" />
2
+
3
+ // Make HTMLElement available in non-browser environments
4
+ const { HTMLElement = class {} } = globalThis;
5
+
6
+ export class ErrorOverlay extends HTMLElement {
7
+ static getOverlayHTML() {
8
+ return `
9
+ <div>
10
+ </div>
11
+ `;
12
+ }
13
+ close() {
14
+ (this as any).parentNode?.removeChild(this);
15
+ }
16
+
17
+ static sendErrorToParent(
18
+ error: Error,
19
+ title: string,
20
+ details: string | undefined,
21
+ componentName: string | undefined
22
+ ) {
23
+ // Send error to parent using framewire
24
+ if (globalThis.window?.parent) {
25
+ try {
26
+ globalThis.window.parent?.postMessage(
27
+ {
28
+ type: "app_error",
29
+ error: { title, details, componentName, originalError: error },
30
+ },
31
+ "*"
32
+ );
33
+ } catch (error) {
34
+ console.warn(
35
+ "Failed to send error to iframe parent:",
36
+ (error as Error)?.message
37
+ );
38
+ }
39
+ }
40
+ }
41
+
42
+ constructor(error: Error) {
43
+ super();
44
+
45
+ const stack = error?.stack;
46
+ let componentName = stack?.match(/at\s+(\w+)\s+\(eval/)?.[1];
47
+ if (componentName === "eval") {
48
+ componentName = undefined;
49
+ }
50
+ const title = componentName
51
+ ? `in ${componentName}: ${error.message?.toString()}`
52
+ : error.message?.toString();
53
+ const details = error?.stack;
54
+
55
+ // Call editor frame with the error (via post message)
56
+ ErrorOverlay.sendErrorToParent(error, title, details, componentName);
57
+
58
+ // Create the overlay element using HTML template
59
+ const overlay = document.createElement("div");
60
+ overlay.innerHTML = ErrorOverlay.getOverlayHTML();
61
+
62
+ // Add to DOM
63
+ document.body.appendChild(overlay);
64
+ }
65
+ }
66
+
67
+ // vite/react-plugin transpiles classes with _SomeClass, so we need to replace all _ErrorOverlay with ErrorOverlay
68
+ export const errorOverlayCode = ErrorOverlay.toString().replaceAll(
69
+ "_ErrorOverlay",
70
+ "ErrorOverlay"
71
+ );
@@ -0,0 +1,18 @@
1
+ import { errorOverlayCode } from "./ErrorOverlay.js";
2
+ import type { Plugin } from "vite";
3
+
4
+ export function errorOverlayPlugin() {
5
+ return {
6
+ name: "error-overlay",
7
+ transform(code, id, opts = {}) {
8
+ if (opts?.ssr) return;
9
+
10
+ if (!id.includes("vite/dist/client/client.mjs")) return;
11
+
12
+ return code.replace(
13
+ "class ErrorOverlay",
14
+ errorOverlayCode + "\nclass OldErrorOverlay"
15
+ );
16
+ },
17
+ } as Plugin;
18
+ }
package/src/index.ts CHANGED
@@ -1,5 +1,7 @@
1
1
  import type { Plugin, UserConfig } from "vite";
2
2
  import { loadEnv } from "vite";
3
+ import { errorOverlayPlugin } from "./error-overlay-plugin.js";
4
+ import { visualEditPlugin } from "./visual-edit-plugin.js";
3
5
 
4
6
  export default function vitePlugin(
5
7
  opts: {
@@ -10,9 +12,10 @@ export default function vitePlugin(
10
12
 
11
13
  return {
12
14
  name: "base44",
15
+ enforce: "pre",
13
16
  config: ({ mode }) => {
14
17
  const env = loadEnv(mode ?? "development", process.cwd(), "");
15
- const isRunningInSandbox = process.env.BASE44_SANDBOX_MODE === "true";
18
+ const isRunningInSandbox = env.BASE44_SANDBOX_MODE === "true";
16
19
 
17
20
  return {
18
21
  resolve: {
@@ -37,6 +40,9 @@ export default function vitePlugin(
37
40
  });
38
41
  },
39
42
  },
43
+ ...(mode === "development"
44
+ ? [errorOverlayPlugin(), visualEditPlugin()]
45
+ : []),
40
46
  ],
41
47
  server: {
42
48
  host: "0.0.0.0", // Bind to all interfaces for container access
@@ -0,0 +1,266 @@
1
+ import { parse } from "@babel/parser";
2
+ import { default as traverse } from "@babel/traverse";
3
+ import { default as generate } from "@babel/generator";
4
+ import * as t from "@babel/types";
5
+
6
+ // Helper function to check if JSX element contains dynamic content
7
+ function checkIfElementHasDynamicContent(jsxElement: any) {
8
+ let hasDynamicContent = false;
9
+
10
+ // Helper function to check if any node contains dynamic patterns
11
+ function checkNodeForDynamicContent(node: any) {
12
+ // JSX expressions like {variable}, {func()}, {obj.prop}
13
+ if (t.isJSXExpressionContainer(node)) {
14
+ const expression = node.expression;
15
+
16
+ // Skip empty expressions {}
17
+ if (t.isJSXEmptyExpression(expression)) {
18
+ return false;
19
+ }
20
+
21
+ // Any non-literal expression is considered dynamic
22
+ if (!t.isLiteral(expression)) {
23
+ return true;
24
+ }
25
+ }
26
+
27
+ // Template literals with expressions `Hello ${name}`
28
+ if (t.isTemplateLiteral(node) && node.expressions.length > 0) {
29
+ return true;
30
+ }
31
+
32
+ // Member expressions like props.title, state.value
33
+ if (t.isMemberExpression(node)) {
34
+ return true;
35
+ }
36
+
37
+ // Function calls like getData(), format()
38
+ if (t.isCallExpression(node)) {
39
+ return true;
40
+ }
41
+
42
+ // Conditional expressions like condition ? "yes" : "no"
43
+ if (t.isConditionalExpression(node)) {
44
+ return true;
45
+ }
46
+
47
+ // Identifier references (could be props, state, variables)
48
+ if (t.isIdentifier(node)) {
49
+ // Common dynamic identifiers
50
+ const dynamicNames = [
51
+ "props",
52
+ "state",
53
+ "data",
54
+ "item",
55
+ "value",
56
+ "text",
57
+ "content",
58
+ ];
59
+ if (dynamicNames.some((name) => node.name.includes(name))) {
60
+ return true;
61
+ }
62
+ }
63
+
64
+ return false;
65
+ }
66
+
67
+ // Recursively traverse all child nodes
68
+ function traverseNode(node: any) {
69
+ if (checkNodeForDynamicContent(node)) {
70
+ hasDynamicContent = true;
71
+ return;
72
+ }
73
+
74
+ // Recursively check child nodes
75
+ Object.keys(node).forEach((key) => {
76
+ const value = node[key];
77
+
78
+ if (Array.isArray(value)) {
79
+ value.forEach((child) => {
80
+ if (child && typeof child === "object" && child.type) {
81
+ traverseNode(child);
82
+ }
83
+ });
84
+ } else if (value && typeof value === "object" && value.type) {
85
+ traverseNode(value);
86
+ }
87
+ });
88
+ }
89
+
90
+ // Check all children of the JSX element
91
+ jsxElement.children.forEach((child: any) => {
92
+ if (hasDynamicContent) return; // Early exit if already found dynamic content
93
+ traverseNode(child);
94
+ });
95
+
96
+ return hasDynamicContent;
97
+ }
98
+
99
+ export function visualEditPlugin() {
100
+ return {
101
+ name: "visual-edit-transform",
102
+ enforce: "pre",
103
+ order: "pre",
104
+ // Inject Tailwind CDN for visual editing capabilities
105
+ transformIndexHtml(html: any) {
106
+ // Inject the Tailwind CSS CDN script right before the closing </head> tag
107
+ const tailwindScript = ` <!-- Tailwind CSS CDN for visual editing -->\n <script src="https://cdn.tailwindcss.com"></script>\n `;
108
+ return html.replace("</head>", tailwindScript + "</head>");
109
+ },
110
+ transform(code: any, id: any) {
111
+ // Skip node_modules and visual-edit-agent itself
112
+ if (id.includes("node_modules") || id.includes("visual-edit-agent")) {
113
+ return null;
114
+ }
115
+
116
+ // Process JS/JSX/TS/TSX files
117
+ if (!id.match(/\.(jsx?|tsx?)$/)) {
118
+ return null;
119
+ }
120
+
121
+ // Extract filename from path, preserving pages/ or components/ structure
122
+ const pathParts = id.split("/");
123
+ let filename;
124
+
125
+ // Check if this is a pages or components file
126
+ if (id.includes("/pages/")) {
127
+ const pagesIndex = pathParts.findIndex((part: any) => part === "pages");
128
+ if (pagesIndex >= 0 && pagesIndex < pathParts.length - 1) {
129
+ // Get all parts from 'pages' to the file, preserving nested structure
130
+ const relevantParts = pathParts.slice(pagesIndex, pathParts.length);
131
+ const lastPart = relevantParts[relevantParts.length - 1];
132
+ // Remove file extension from the last part
133
+ relevantParts[relevantParts.length - 1] = lastPart.includes(".")
134
+ ? lastPart.split(".")[0]
135
+ : lastPart;
136
+ filename = relevantParts.join("/");
137
+ } else {
138
+ filename = pathParts[pathParts.length - 1];
139
+ if (filename.includes(".")) {
140
+ filename = filename.split(".")[0];
141
+ }
142
+ }
143
+ } else if (id.includes("/components/")) {
144
+ const componentsIndex = pathParts.findIndex(
145
+ (part: any) => part === "components"
146
+ );
147
+ if (componentsIndex >= 0 && componentsIndex < pathParts.length - 1) {
148
+ // Get all parts from 'components' to the file, preserving nested structure
149
+ const relevantParts = pathParts.slice(
150
+ componentsIndex,
151
+ pathParts.length
152
+ );
153
+ const lastPart = relevantParts[relevantParts.length - 1];
154
+ // Remove file extension from the last part
155
+ relevantParts[relevantParts.length - 1] = lastPart.includes(".")
156
+ ? lastPart.split(".")[0]
157
+ : lastPart;
158
+ filename = relevantParts.join("/");
159
+ } else {
160
+ filename = pathParts[pathParts.length - 1];
161
+ if (filename.includes(".")) {
162
+ filename = filename.split(".")[0];
163
+ }
164
+ }
165
+ } else {
166
+ // For other files (like layout), just use the filename
167
+ filename = pathParts[pathParts.length - 1];
168
+ if (filename.includes(".")) {
169
+ filename = filename.split(".")[0];
170
+ }
171
+ }
172
+
173
+ try {
174
+ // Parse the code into an AST
175
+ const ast = parse(code, {
176
+ sourceType: "module",
177
+ plugins: [
178
+ "jsx",
179
+ "typescript",
180
+ "decorators-legacy",
181
+ "classProperties",
182
+ "objectRestSpread",
183
+ "functionBind",
184
+ "exportDefaultFrom",
185
+ "exportNamespaceFrom",
186
+ "dynamicImport",
187
+ "nullishCoalescingOperator",
188
+ "optionalChaining",
189
+ "asyncGenerators",
190
+ "bigInt",
191
+ "optionalCatchBinding",
192
+ "throwExpressions",
193
+ ],
194
+ });
195
+
196
+ // Traverse the AST and add source location and dynamic content attributes to JSX elements
197
+ let elementsProcessed = 0;
198
+ traverse.default(ast, {
199
+ JSXElement(path) {
200
+ const jsxElement = path.node;
201
+ const openingElement = jsxElement.openingElement;
202
+
203
+ // Skip fragments
204
+ if (t.isJSXFragment(jsxElement)) return;
205
+
206
+ // Skip if already has source location attribute
207
+ const hasSourceLocation = openingElement.attributes.some(
208
+ (attr) =>
209
+ t.isJSXAttribute(attr) &&
210
+ t.isJSXIdentifier(attr.name) &&
211
+ attr.name.name === "data-source-location"
212
+ );
213
+
214
+ if (hasSourceLocation) return;
215
+
216
+ // Get line and column from AST node location
217
+ const { line, column } = openingElement.loc?.start || {
218
+ line: 1,
219
+ column: 0,
220
+ };
221
+
222
+ // Create the source location attribute
223
+ const sourceLocationAttr = t.jsxAttribute(
224
+ t.jsxIdentifier("data-source-location"),
225
+ t.stringLiteral(`${filename}:${line}:${column}`)
226
+ );
227
+
228
+ // Check if element has dynamic content
229
+ const isDynamic = checkIfElementHasDynamicContent(jsxElement);
230
+
231
+ // Create the dynamic content attribute
232
+ const dynamicContentAttr = t.jsxAttribute(
233
+ t.jsxIdentifier("data-dynamic-content"),
234
+ t.stringLiteral(isDynamic ? "true" : "false")
235
+ );
236
+
237
+ // Add both attributes to the beginning of the attributes array
238
+ openingElement.attributes.unshift(
239
+ sourceLocationAttr,
240
+ dynamicContentAttr
241
+ );
242
+ elementsProcessed++;
243
+ },
244
+ });
245
+
246
+ // Generate the code back from the AST
247
+ const result = generate.default(ast, {
248
+ compact: false,
249
+ concise: false,
250
+ retainLines: true,
251
+ });
252
+
253
+ return {
254
+ code: result.code,
255
+ map: null,
256
+ };
257
+ } catch (error) {
258
+ console.error("Failed to add source location to JSX:", error);
259
+ return {
260
+ code: code, // Return original code on failure
261
+ map: null,
262
+ };
263
+ }
264
+ },
265
+ };
266
+ }