@base44-preview/vite-plugin 1.0.24-pr.96.c1a9a67 → 1.0.27-pr.98.00a0055

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -48,6 +48,62 @@ The plugin registers four sub-plugins when running in a sandbox (`MODAL_SANDBOX_
48
48
 
49
49
  Outside a sandbox, only the core plugin runs (with optional API proxy support via `VITE_BASE44_APP_BASE_URL`).
50
50
 
51
+ ### Build-status endpoint
52
+
53
+ An opt-in, dev-only (`apply: "serve"`) endpoint that reports the last build /
54
+ compile / HMR error observed by the dev server. It exists solely to let the
55
+ preview backend poll for post-load errors — it is **never** part of a
56
+ production build.
57
+
58
+ Enable it by setting the environment variable at dev-server start:
59
+
60
+ ```bash
61
+ BASE44_BUILD_STATUS_ENABLED=1
62
+ ```
63
+
64
+ The env var is checked when the plugin assembles its plugin list (config load),
65
+ so the generated app's `vite.config.js` does not need to change. When it is
66
+ unset, the build-status sub-plugin is not added to the pipeline at all — its
67
+ `configureServer` hook is never reached.
68
+
69
+ When enabled, the plugin serves:
70
+
71
+ ```
72
+ GET /__build_status
73
+ ```
74
+
75
+ - **Loopback-only.** Requests from any non-loopback `remoteAddress`
76
+ (`127.0.0.1`, `::1`, `::ffff:127.0.0.1`) fall through as if the route did
77
+ not exist. Non-`GET` methods fall through too.
78
+ - **Always `200`.** Health lives in the body, not the status code — a `500`
79
+ would trip the preview proxy's own error path. The body is:
80
+
81
+ ```json
82
+ { "ok": true, "error": null }
83
+ ```
84
+
85
+ or, when an error is outstanding:
86
+
87
+ ```json
88
+ { "ok": false, "error": { "message": "…", "frame": "…", "loc": { "…": 0 } } }
89
+ ```
90
+
91
+ - **Scrubbed.** Even though the endpoint is loopback-only (the backend relays a
92
+ trimmed form onward), the error is size-capped and absolute filesystem paths
93
+ are stripped down to basenames.
94
+ - **Fail-open.** All setup and request handling is wrapped in `try/catch` so a
95
+ bug in this plugin can never break the dev server.
96
+
97
+ How it works: `configureServer` wraps the HMR send channel
98
+ (`server.hot ?? server.ws`). An `error` payload records the last error; a
99
+ successful `update` or `full-reload` clears it.
100
+
101
+ **Cold-start caveat & scope.** Errors thrown *before any client has connected*
102
+ are not sent over the HMR channel, so a boot-time transform failure may briefly
103
+ read `ok: true`. That window is already covered server-side by the existing
104
+ `dev_server_error_classifier` (install / start failures surface as `409`). This
105
+ endpoint's job is **post-load HMR / compile errors**, not cold-start failures.
106
+
51
107
  ### Sandbox Injections
52
108
 
53
109
  In **dev mode**, individual `<script type="module" src="...">` tags are injected for each feature, loaded directly from `node_modules`:
@@ -0,0 +1,8 @@
1
+ import type { Plugin } from "vite";
2
+ /**
3
+ * Produce a trimmed, path-stripped, size-capped view of an HMR error
4
+ * payload. Returns `null` when there is no error.
5
+ */
6
+ export declare function scrub(err: unknown): Record<string, unknown> | null;
7
+ export declare function buildStatusPlugin(): Plugin;
8
+ //# sourceMappingURL=build-status-plugin.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"build-status-plugin.d.ts","sourceRoot":"","sources":["../src/build-status-plugin.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAW,MAAM,EAAiB,MAAM,MAAM,CAAC;AAyE3D;;;GAGG;AACH,wBAAgB,KAAK,CAAC,GAAG,EAAE,OAAO,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI,CA2ClE;AAED,wBAAgB,iBAAiB,IAAI,MAAM,CAsE1C"}
@@ -0,0 +1,170 @@
1
+ /**
2
+ * Opt-in, loopback-gated dev-server endpoint that reports the last
3
+ * build / compile / HMR error observed since the dev server started.
4
+ *
5
+ * `GET /__build_status` responds `200` with a JSON body:
6
+ * { ok: boolean, error: <scrubbed error> | null }
7
+ *
8
+ * The endpoint is:
9
+ * - dev-only (`apply: "serve"`) — it never exists in a production build;
10
+ * - loopback-only — requests from non-loopback addresses fall through.
11
+ *
12
+ * Enablement (the `BASE44_BUILD_STATUS_ENABLED` env-var check) is decided by
13
+ * the caller in `index.ts`, which only adds this plugin to the array when the
14
+ * endpoint is wanted — so `configureServer` here is never even reached when
15
+ * the feature is off.
16
+ *
17
+ * The status is always reported in the body with HTTP `200`, even on error:
18
+ * a `500` here would trip the preview proxy's own error path.
19
+ *
20
+ * Cold-start caveat: errors thrown before any client has connected are not
21
+ * sent over the HMR channel, so a boot-time transform failure may briefly
22
+ * read `ok: true`. That window is covered server-side by the existing
23
+ * dev_server_error_classifier. This endpoint reports post-load
24
+ * HMR / compile errors.
25
+ */
26
+ const ENDPOINT = "/__build_status";
27
+ /** Max characters kept per scrubbed string field. */
28
+ const MAX_FIELD = 4000;
29
+ /** Max characters kept for the code frame. */
30
+ const MAX_FRAME = 2000;
31
+ const LOOPBACK_ADDRESSES = new Set([
32
+ "127.0.0.1",
33
+ "::1",
34
+ "::ffff:127.0.0.1",
35
+ ]);
36
+ function isLoopback(remoteAddress) {
37
+ return remoteAddress !== undefined && LOOPBACK_ADDRESSES.has(remoteAddress);
38
+ }
39
+ function clip(value, max) {
40
+ if (typeof value !== "string" || value.length === 0)
41
+ return undefined;
42
+ return value.length > max ? `${value.slice(0, max)}… [truncated]` : value;
43
+ }
44
+ /**
45
+ * Strip absolute filesystem paths down to their basename so directory
46
+ * structure never leaks. This is loopback-only, but the backend relays a
47
+ * trimmed form, so scrub before it leaves this process.
48
+ */
49
+ function stripPaths(value) {
50
+ return (value
51
+ // Windows: C:\Users\foo\bar\file.ext -> file.ext
52
+ .replace(/[A-Za-z]:\\[^\s:*?"<>|]+/g, (m) => m.split(/[\\/]/).pop() ?? m)
53
+ // POSIX absolute: /Users/foo/bar/file.ext -> file.ext
54
+ .replace(/\/(?:[^\s:/]+\/)+[^\s:/]+/g, (m) => m.split("/").pop() ?? m));
55
+ }
56
+ function scrubString(value, max) {
57
+ const clipped = clip(value, max);
58
+ return clipped === undefined ? undefined : stripPaths(clipped);
59
+ }
60
+ /**
61
+ * Produce a trimmed, path-stripped, size-capped view of an HMR error
62
+ * payload. Returns `null` when there is no error.
63
+ */
64
+ export function scrub(err) {
65
+ if (err === null || err === undefined)
66
+ return null;
67
+ if (typeof err !== "object") {
68
+ const message = scrubString(String(err), MAX_FIELD);
69
+ return message === undefined ? null : { message };
70
+ }
71
+ const e = err;
72
+ const out = {};
73
+ const message = scrubString(e["message"], MAX_FIELD);
74
+ if (message !== undefined)
75
+ out["message"] = message;
76
+ const stack = scrubString(e["stack"], MAX_FIELD);
77
+ if (stack !== undefined)
78
+ out["stack"] = stack;
79
+ const frame = scrubString(e["frame"], MAX_FRAME);
80
+ if (frame !== undefined)
81
+ out["frame"] = frame;
82
+ const id = scrubString(e["id"], MAX_FIELD);
83
+ if (id !== undefined)
84
+ out["id"] = id;
85
+ const plugin = scrubString(e["plugin"], 200);
86
+ if (plugin !== undefined)
87
+ out["plugin"] = plugin;
88
+ const loc = e["loc"];
89
+ if (loc && typeof loc === "object") {
90
+ const l = loc;
91
+ out["loc"] = {
92
+ file: scrubString(l["file"], MAX_FIELD),
93
+ line: typeof l["line"] === "number" ? l["line"] : undefined,
94
+ column: typeof l["column"] === "number" ? l["column"] : undefined,
95
+ };
96
+ }
97
+ // Fall back to a stringified form if we recognised nothing useful.
98
+ if (Object.keys(out).length === 0) {
99
+ const message = scrubString(String(e), MAX_FIELD);
100
+ return message === undefined ? {} : { message };
101
+ }
102
+ return out;
103
+ }
104
+ export function buildStatusPlugin() {
105
+ let lastError = null;
106
+ return {
107
+ name: "base44-build-status",
108
+ apply: "serve",
109
+ configureServer(server) {
110
+ try {
111
+ // Observe the HMR channel: an `error` payload records the last
112
+ // error; a successful `update` / `full-reload` clears it.
113
+ const ch = (server.hot ?? server.ws);
114
+ if (ch && typeof ch.send === "function") {
115
+ const orig = ch.send.bind(ch);
116
+ ch.send = (payload, ...rest) => {
117
+ try {
118
+ const p = payload;
119
+ if (p?.type === "error") {
120
+ lastError = p.err ?? null;
121
+ }
122
+ else if (p?.type === "update" || p?.type === "full-reload") {
123
+ lastError = null;
124
+ }
125
+ }
126
+ catch {
127
+ // Never let bookkeeping break HMR delivery.
128
+ }
129
+ return orig(payload, ...rest);
130
+ };
131
+ }
132
+ server.middlewares.use(ENDPOINT, (req, res, next) => {
133
+ try {
134
+ if (!isLoopback(req.socket?.remoteAddress)) {
135
+ next();
136
+ return;
137
+ }
138
+ if (req.method !== "GET") {
139
+ next();
140
+ return;
141
+ }
142
+ const body = JSON.stringify({
143
+ ok: !lastError,
144
+ error: scrub(lastError),
145
+ });
146
+ // Health lives in the body — keep 200 even on error so the
147
+ // preview proxy doesn't treat this as a server failure.
148
+ res.statusCode = 200;
149
+ res.setHeader("Content-Type", "application/json");
150
+ res.setHeader("Cache-Control", "no-store");
151
+ res.end(body);
152
+ }
153
+ catch {
154
+ // Fail open: a bug here must never break the dev server.
155
+ try {
156
+ next();
157
+ }
158
+ catch {
159
+ // ignore
160
+ }
161
+ }
162
+ });
163
+ }
164
+ catch {
165
+ // Fail open: setup errors must never break the dev server.
166
+ }
167
+ },
168
+ };
169
+ }
170
+ //# sourceMappingURL=build-status-plugin.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"build-status-plugin.js","sourceRoot":"","sources":["../src/build-status-plugin.ts"],"names":[],"mappings":"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"}
@@ -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;AAW/C,MAAM,CAAC,OAAO,UAAU,UAAU,CAChC,IAAI,GAAE;IACJ,gBAAgB,CAAC,EAAE,OAAO,CAAC;IAC3B,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB,kBAAkB,CAAC,EAAE,OAAO,CAAC;IAC7B,eAAe,CAAC,EAAE,OAAO,CAAC;IAC1B,gBAAgB,CAAC,EAAE,OAAO,CAAC;CACvB,iBAiOP"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,EAAc,MAAM,MAAM,CAAC;AAU/C,MAAM,CAAC,OAAO,UAAU,UAAU,CAChC,IAAI,GAAE;IACJ,gBAAgB,CAAC,EAAE,OAAO,CAAC;IAC3B,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB,kBAAkB,CAAC,EAAE,OAAO,CAAC;IAC7B,eAAe,CAAC,EAAE,OAAO,CAAC;IAC1B,gBAAgB,CAAC,EAAE,OAAO,CAAC;CACvB,iBA+NP"}
package/dist/index.js CHANGED
@@ -3,8 +3,8 @@ import { errorOverlayPlugin } from "./error-overlay-plugin.js";
3
3
  import { visualEditPlugin } from "./visual-edit-plugin.js";
4
4
  import { filterPackagesInProject } from "./utils.js";
5
5
  import { htmlInjectionsPlugin } from "./html-injections-plugin.js";
6
+ import { buildStatusPlugin } from "./build-status-plugin.js";
6
7
  const isRunningInSandbox = !!process.env.MODAL_SANDBOX_ID;
7
- const SANDBOX_DEP_CACHE_DIR = "/var/cache/base44-vite-deps";
8
8
  export default function vitePlugin(opts = {}) {
9
9
  const { legacySDKImports = false, hmrNotifier = false, navigationNotifier = false, visualEditAgent = false, analyticsTracker = false, } = opts;
10
10
  return [
@@ -29,17 +29,8 @@ export default function vitePlugin(opts = {}) {
29
29
  ...(isRunningInSandbox
30
30
  ? {
31
31
  logLevel: "error",
32
- // The sandbox /app mount can't rename() dirs from the snapshot
33
- // layer (EXDEV), which breaks the dep optimizer's commit step.
34
- // Keep the dep cache on the container rootfs instead.
35
- cacheDir: SANDBOX_DEP_CACHE_DIR,
36
32
  server: {
37
33
  cors: true,
38
- fs: {
39
- // Explicit allow replaces Vite's defaults, so include the
40
- // app root alongside the external cache dir (served via /@fs/).
41
- allow: [root, SANDBOX_DEP_CACHE_DIR],
42
- },
43
34
  host: "0.0.0.0", // Bind to all interfaces for container access
44
35
  port: 5173,
45
36
  strictPort: true,
@@ -171,6 +162,13 @@ export default function vitePlugin(opts = {}) {
171
162
  : []),
172
163
  // HTML injections - handles both dev (sandbox) and production injections
173
164
  htmlInjectionsPlugin({ hmrNotifier, navigationNotifier, visualEditAgent, analyticsTracker }),
165
+ // Opt-in, loopback-gated dev-server build-status endpoint. Gated here on
166
+ // the BASE44_BUILD_STATUS_ENABLED env var so the generated app's
167
+ // vite.config.js doesn't need to change and the sub-plugin isn't even
168
+ // added to the pipeline when disabled. The endpoint itself is dev-only.
169
+ ...(process.env.BASE44_BUILD_STATUS_ENABLED === "1"
170
+ ? [buildStatusPlugin()]
171
+ : []),
174
172
  ];
175
173
  }
176
174
  //# sourceMappingURL=index.js.map
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,OAAO,EAAE,MAAM,MAAM,CAAC;AAC/B,OAAO,EAAE,kBAAkB,EAAE,MAAM,2BAA2B,CAAC;AAC/D,OAAO,EAAE,gBAAgB,EAAE,MAAM,yBAAyB,CAAC;AAC3D,OAAO,EAAE,uBAAuB,EAAE,MAAM,YAAY,CAAC;AACrD,OAAO,EAAE,oBAAoB,EAAE,MAAM,6BAA6B,CAAC;AACnE,OAAO,EAAE,iBAAiB,EAAE,MAAM,0BAA0B,CAAC;AAE7D,MAAM,kBAAkB,GAAG,CAAC,CAAC,OAAO,CAAC,GAAG,CAAC,gBAAgB,CAAC;AAE1D,MAAM,CAAC,OAAO,UAAU,UAAU,CAChC,OAMI,EAAE;IAEN,MAAM,EACJ,gBAAgB,GAAG,KAAK,EACxB,WAAW,GAAG,KAAK,EACnB,kBAAkB,GAAG,KAAK,EAC1B,eAAe,GAAG,KAAK,EACvB,gBAAgB,GAAG,KAAK,GACzB,GAAG,IAAI,CAAC;IAET,OAAO;QACL;YACE,IAAI,EAAE,QAAQ;YACd,MAAM,EAAE,CAAC,EAAE,IAAI,EAAE,IAAI,GAAG,OAAO,CAAC,GAAG,EAAE,EAAE,EAAE,EAAE;gBACzC,MAAM,GAAG,GAAG,OAAO,CAAC,IAAI,IAAI,aAAa,EAAE,IAAI,EAAE,EAAE,CAAC,CAAC;gBAErD,OAAO;oBACL,OAAO,EAAE;wBACP,KAAK,EAAE;4BACL,IAAI,EAAE,OAAO;yBACd;qBACF;oBACD,GAAG,CAAC,gBAAgB;wBAClB,CAAC,CAAC;4BACE,MAAM,EAAE;gCACN,gCAAgC,EAAE,IAAI,CAAC,SAAS,CAC9C,GAAG,CAAC,kBAAkB,CACvB;gCACD,qCAAqC,EAAE,IAAI,CAAC,SAAS,CACnD,GAAG,CAAC,uBAAuB,CAC5B;6BACF;yBACF;wBACH,CAAC,CAAC,EAAE,CAAC;oBACP,GAAG,CAAC,kBAAkB;wBACpB,CAAC,CAAE;4BACC,QAAQ,EAAE,OAAO;4BACjB,MAAM,EAAE;gCACN,IAAI,EAAE,IAAI;gCACV,IAAI,EAAE,SAAS,EAAE,8CAA8C;gCAC/D,IAAI,EAAE,IAAI;gCACV,UAAU,EAAE,IAAI;gCAChB,oDAAoD;gCACpD,YAAY,EAAE,IAAI;gCAClB,+DAA+D;gCAC/D,iEAAiE;gCACjE,+DAA+D;gCAC/D,uCAAuC;gCACvC,GAAG,CAAC,OAAO,CAAC,GAAG,CAAC,eAAe;oCAC7B,CAAC,CAAC,EAAE,GAAG,EAAE,EAAE,IAAI,EAAE,OAAO,CAAC,GAAG,CAAC,eAAe,EAAE,EAAE;oCAChD,CAAC,CAAC,EAAE,CAAC;gCACP,KAAK,EAAE;oCACL,gEAAgE;oCAChE,UAAU,EAAE,IAAI;oCAChB,QAAQ,EAAE,GAAG,EAAE,uCAAuC;oCACtD,yDAAyD;oCACzD,gBAAgB,EAAE;wCAChB,kBAAkB,EAAE,GAAG;wCACvB,YAAY,EAAE,EAAE;qCACjB;iCACF;6BACF;4BACD,KAAK,EAAE;gCACL,aAAa,EAAE;oCACb,MAAM,CAAC,OAAO,EAAE,IAAI;wCAClB,sCAAsC;wCACtC,IACE,OAAO,CAAC,IAAI,KAAK,mBAAmB;4CACpC,OAAO,CAAC,IAAI,KAAK,gBAAgB,EACjC,CAAC;4CACD,MAAM,IAAI,KAAK,CAAC,iBAAiB,OAAO,CAAC,OAAO,EAAE,CAAC,CAAC;wCACtD,CAAC;wCACD,iCAAiC;wCACjC,IAAI,CAAC,OAAO,CAAC,CAAC;oCAChB,CAAC;iCACF;6BACF;yBACsB;wBAC3B,CAAC,CAAC,CAAC,GAAG,EAAE;4BACJ,IAAI,GAAG,CAAC,wBAAwB,EAAE,CAAC;gCACjC,OAAO,CAAC,GAAG,CACT,mCAAmC,GAAG,CAAC,wBAAwB,EAAE,CAClE,CAAC;gCACF,OAAO;oCACL,MAAM,EAAE;wCACN,KAAK,EAAE;4CACL,MAAM,EAAE;gDACN,MAAM,EAAE,GAAG,CAAC,wBAAwB;gDACpC,YAAY,EAAE,IAAI;6CACnB;yCACF;qCACF;iCACF,CAAC;4BACJ,CAAC;4BACD,OAAO,CAAC,GAAG,CACT,+DAA+D,CAChE,CAAC;4BACF,OAAO,EAAE,CAAC;wBACZ,CAAC,CAAC,EAAE,CAAC;oBACT,YAAY,EAAE;wBACZ,GAAG,CAAC,kBAAkB;4BACpB,CAAC,CAAC;gCACE,OAAO,EAAE,uBAAuB,CAC9B;oCACE,OAAO;oCACP,WAAW;oCACX,eAAe;oCACf,QAAQ;oCACR,QAAQ;oCACR,aAAa;iCACd,EACD,IAAI,CACL;6BACF;4BACH,CAAC,CAAC,EAAE,CAAC;wBACP,cAAc,EAAE;4BACd,MAAM,EAAE;gCACN,KAAK,EAAE,KAAK;6BACb;yBACF;qBACF;iBACF,CAAC;YACJ,CAAC;YACD,KAAK,CAAC,SAAS,CAAC,MAAM,EAAE,QAAQ,EAAE,OAAO;gBACvC,yEAAyE;gBACzE,2EAA2E;gBAC3E,IAAI,gBAAgB,IAAI,CAAC,QAAQ,EAAE,QAAQ,CAAC,OAAO,CAAC,EAAE,CAAC;oBACrD,MAAM,kBAAkB,GAAG,MAAM,IAAI,CAAC,OAAO,CAC3C,MAAM,EACN,QAAQ,EACR,OAAO,CACR,CAAC;oBAEF,IAAI,kBAAkB,EAAE,CAAC;wBACvB,OAAO,kBAAkB,CAAC;oBAC5B,CAAC;oBAED,iFAAiF;oBACjF,uEAAuE;oBACvE,8CAA8C;oBAC9C,IACE,QAAQ,EAAE,QAAQ,CAAC,iBAAiB,CAAC;wBACrC,MAAM,CAAC,UAAU,CAAC,eAAe,CAAC,EAClC,CAAC;wBACD,OAAO,IAAI,CAAC,OAAO,CACjB,MAAM,CAAC,OAAO,CAAC,iBAAiB,EAAE,cAAc,CAAC,EACjD,QAAQ,EACR,OAAO,CACR,CAAC;oBACJ,CAAC;oBAED,iEAAiE;oBACjE,IACE,QAAQ,EAAE,QAAQ,CAAC,QAAQ,CAAC;wBAC5B,CAAC,MAAM,CAAC,WAAW,EAAE,CAAC,QAAQ,CAAC,YAAY,CAAC;4BAC1C,MAAM,CAAC,WAAW,EAAE,CAAC,QAAQ,CAAC,WAAW,CAAC,CAAC,EAC7C,CAAC;wBACD,OAAO,IAAI,CAAC,OAAO,CAAC,cAAc,EAAE,QAAQ,EAAE,OAAO,CAAC,CAAC;oBACzD,CAAC;oBAED,IAAI,MAAM,CAAC,QAAQ,CAAC,WAAW,CAAC,EAAE,CAAC;wBACjC,OAAO,IAAI,CAAC,OAAO,CACjB,yCAAyC,EACzC,QAAQ,EACR,OAAO,CACR,CAAC;oBACJ,CAAC;oBAED,IAAI,MAAM,CAAC,QAAQ,CAAC,YAAY,CAAC,EAAE,CAAC;wBAClC,OAAO,IAAI,CAAC,OAAO,CACjB,0CAA0C,EAC1C,QAAQ,EACR,OAAO,CACR,CAAC;oBACJ,CAAC;oBAED,IAAI,MAAM,CAAC,QAAQ,CAAC,eAAe,CAAC,EAAE,CAAC;wBACrC,OAAO,IAAI,CAAC,OAAO,CACjB,6CAA6C,EAC7C,QAAQ,EACR,OAAO,CACR,CAAC;oBACJ,CAAC;oBAED,IAAI,MAAM,CAAC,QAAQ,CAAC,SAAS,CAAC,EAAE,CAAC;wBAC/B,OAAO,IAAI,CAAC,OAAO,CACjB,uCAAuC,EACvC,QAAQ,EACR,OAAO,CACR,CAAC;oBACJ,CAAC;gBACH,CAAC;gBAED,OAAO,IAAI,CAAC;YACd,CAAC;SACQ;QACX,GAAG,CAAC,kBAAkB;YACpB,CAAC,CAAC;gBACE;oBACE,IAAI,EAAE,YAAY;oBAClB,eAAe,CAAC,MAAM;wBACpB,MAAM,CAAC,WAAW,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,GAAG,EAAE,IAAI,EAAE,EAAE;4BACxC,yBAAyB;4BACzB,GAAG,CAAC,SAAS,CAAC,iBAAiB,EAAE,UAAU,CAAC,CAAC;4BAC7C,GAAG,CAAC,SAAS,CAAC,yBAAyB,EAAE,oBAAoB,CAAC,CAAC;4BAC/D,IAAI,EAAE,CAAC;wBACT,CAAC,CAAC,CAAC;oBACL,CAAC;iBACQ;gBACX,kBAAkB,EAAE;gBACpB,gBAAgB,EAAE;aACnB;YACH,CAAC,CAAC,EAAE,CAAC;QACP,yEAAyE;QACzE,oBAAoB,CAAC,EAAE,WAAW,EAAE,kBAAkB,EAAE,eAAe,EAAE,gBAAgB,EAAE,CAAC;QAC5F,yEAAyE;QACzE,iEAAiE;QACjE,sEAAsE;QACtE,wEAAwE;QACxE,GAAG,CAAC,OAAO,CAAC,GAAG,CAAC,2BAA2B,KAAK,GAAG;YACjD,CAAC,CAAC,CAAC,iBAAiB,EAAE,CAAC;YACvB,CAAC,CAAC,EAAE,CAAC;KACR,CAAC;AACJ,CAAC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@base44-preview/vite-plugin",
3
- "version": "1.0.24-pr.96.c1a9a67",
3
+ "version": "1.0.27-pr.98.00a0055",
4
4
  "description": "The Vite plugin for base44 based applications",
5
5
  "type": "module",
6
6
  "license": "MIT",
@@ -0,0 +1,193 @@
1
+ import type { Connect, Plugin, ViteDevServer } from "vite";
2
+ import type { ServerResponse } from "http";
3
+
4
+ /**
5
+ * Opt-in, loopback-gated dev-server endpoint that reports the last
6
+ * build / compile / HMR error observed since the dev server started.
7
+ *
8
+ * `GET /__build_status` responds `200` with a JSON body:
9
+ * { ok: boolean, error: <scrubbed error> | null }
10
+ *
11
+ * The endpoint is:
12
+ * - dev-only (`apply: "serve"`) — it never exists in a production build;
13
+ * - loopback-only — requests from non-loopback addresses fall through.
14
+ *
15
+ * Enablement (the `BASE44_BUILD_STATUS_ENABLED` env-var check) is decided by
16
+ * the caller in `index.ts`, which only adds this plugin to the array when the
17
+ * endpoint is wanted — so `configureServer` here is never even reached when
18
+ * the feature is off.
19
+ *
20
+ * The status is always reported in the body with HTTP `200`, even on error:
21
+ * a `500` here would trip the preview proxy's own error path.
22
+ *
23
+ * Cold-start caveat: errors thrown before any client has connected are not
24
+ * sent over the HMR channel, so a boot-time transform failure may briefly
25
+ * read `ok: true`. That window is covered server-side by the existing
26
+ * dev_server_error_classifier. This endpoint reports post-load
27
+ * HMR / compile errors.
28
+ */
29
+
30
+ const ENDPOINT = "/__build_status";
31
+
32
+ /** Max characters kept per scrubbed string field. */
33
+ const MAX_FIELD = 4000;
34
+ /** Max characters kept for the code frame. */
35
+ const MAX_FRAME = 2000;
36
+
37
+ type SendChannel = { send: (...args: unknown[]) => void };
38
+
39
+ const LOOPBACK_ADDRESSES = new Set([
40
+ "127.0.0.1",
41
+ "::1",
42
+ "::ffff:127.0.0.1",
43
+ ]);
44
+
45
+ function isLoopback(remoteAddress: string | undefined): boolean {
46
+ return remoteAddress !== undefined && LOOPBACK_ADDRESSES.has(remoteAddress);
47
+ }
48
+
49
+ function clip(value: unknown, max: number): string | undefined {
50
+ if (typeof value !== "string" || value.length === 0) return undefined;
51
+ return value.length > max ? `${value.slice(0, max)}… [truncated]` : value;
52
+ }
53
+
54
+ /**
55
+ * Strip absolute filesystem paths down to their basename so directory
56
+ * structure never leaks. This is loopback-only, but the backend relays a
57
+ * trimmed form, so scrub before it leaves this process.
58
+ */
59
+ function stripPaths(value: string): string {
60
+ return (
61
+ value
62
+ // Windows: C:\Users\foo\bar\file.ext -> file.ext
63
+ .replace(/[A-Za-z]:\\[^\s:*?"<>|]+/g, (m) => m.split(/[\\/]/).pop() ?? m)
64
+ // POSIX absolute: /Users/foo/bar/file.ext -> file.ext
65
+ .replace(/\/(?:[^\s:/]+\/)+[^\s:/]+/g, (m) => m.split("/").pop() ?? m)
66
+ );
67
+ }
68
+
69
+ function scrubString(value: unknown, max: number): string | undefined {
70
+ const clipped = clip(value, max);
71
+ return clipped === undefined ? undefined : stripPaths(clipped);
72
+ }
73
+
74
+ /**
75
+ * Produce a trimmed, path-stripped, size-capped view of an HMR error
76
+ * payload. Returns `null` when there is no error.
77
+ */
78
+ export function scrub(err: unknown): Record<string, unknown> | null {
79
+ if (err === null || err === undefined) return null;
80
+
81
+ if (typeof err !== "object") {
82
+ const message = scrubString(String(err), MAX_FIELD);
83
+ return message === undefined ? null : { message };
84
+ }
85
+
86
+ const e = err as Record<string, unknown>;
87
+ const out: Record<string, unknown> = {};
88
+
89
+ const message = scrubString(e["message"], MAX_FIELD);
90
+ if (message !== undefined) out["message"] = message;
91
+
92
+ const stack = scrubString(e["stack"], MAX_FIELD);
93
+ if (stack !== undefined) out["stack"] = stack;
94
+
95
+ const frame = scrubString(e["frame"], MAX_FRAME);
96
+ if (frame !== undefined) out["frame"] = frame;
97
+
98
+ const id = scrubString(e["id"], MAX_FIELD);
99
+ if (id !== undefined) out["id"] = id;
100
+
101
+ const plugin = scrubString(e["plugin"], 200);
102
+ if (plugin !== undefined) out["plugin"] = plugin;
103
+
104
+ const loc = e["loc"];
105
+ if (loc && typeof loc === "object") {
106
+ const l = loc as Record<string, unknown>;
107
+ out["loc"] = {
108
+ file: scrubString(l["file"], MAX_FIELD),
109
+ line: typeof l["line"] === "number" ? l["line"] : undefined,
110
+ column: typeof l["column"] === "number" ? l["column"] : undefined,
111
+ };
112
+ }
113
+
114
+ // Fall back to a stringified form if we recognised nothing useful.
115
+ if (Object.keys(out).length === 0) {
116
+ const message = scrubString(String(e), MAX_FIELD);
117
+ return message === undefined ? {} : { message };
118
+ }
119
+
120
+ return out;
121
+ }
122
+
123
+ export function buildStatusPlugin(): Plugin {
124
+ let lastError: unknown = null;
125
+
126
+ return {
127
+ name: "base44-build-status",
128
+ apply: "serve",
129
+ configureServer(server: ViteDevServer) {
130
+ try {
131
+ // Observe the HMR channel: an `error` payload records the last
132
+ // error; a successful `update` / `full-reload` clears it.
133
+ const ch = (server.hot ?? server.ws) as unknown as SendChannel | undefined;
134
+ if (ch && typeof ch.send === "function") {
135
+ const orig = ch.send.bind(ch);
136
+ ch.send = (payload: unknown, ...rest: unknown[]) => {
137
+ try {
138
+ const p = payload as { type?: string; err?: unknown } | undefined;
139
+ if (p?.type === "error") {
140
+ lastError = p.err ?? null;
141
+ } else if (p?.type === "update" || p?.type === "full-reload") {
142
+ lastError = null;
143
+ }
144
+ } catch {
145
+ // Never let bookkeeping break HMR delivery.
146
+ }
147
+ return orig(payload, ...rest);
148
+ };
149
+ }
150
+
151
+ server.middlewares.use(
152
+ ENDPOINT,
153
+ (
154
+ req: Connect.IncomingMessage,
155
+ res: ServerResponse,
156
+ next: Connect.NextFunction
157
+ ) => {
158
+ try {
159
+ if (!isLoopback(req.socket?.remoteAddress)) {
160
+ next();
161
+ return;
162
+ }
163
+ if (req.method !== "GET") {
164
+ next();
165
+ return;
166
+ }
167
+
168
+ const body = JSON.stringify({
169
+ ok: !lastError,
170
+ error: scrub(lastError),
171
+ });
172
+ // Health lives in the body — keep 200 even on error so the
173
+ // preview proxy doesn't treat this as a server failure.
174
+ res.statusCode = 200;
175
+ res.setHeader("Content-Type", "application/json");
176
+ res.setHeader("Cache-Control", "no-store");
177
+ res.end(body);
178
+ } catch {
179
+ // Fail open: a bug here must never break the dev server.
180
+ try {
181
+ next();
182
+ } catch {
183
+ // ignore
184
+ }
185
+ }
186
+ }
187
+ );
188
+ } catch {
189
+ // Fail open: setup errors must never break the dev server.
190
+ }
191
+ },
192
+ };
193
+ }
package/src/index.ts CHANGED
@@ -4,11 +4,10 @@ import { errorOverlayPlugin } from "./error-overlay-plugin.js";
4
4
  import { visualEditPlugin } from "./visual-edit-plugin.js";
5
5
  import { filterPackagesInProject } from "./utils.js";
6
6
  import { htmlInjectionsPlugin } from "./html-injections-plugin.js";
7
+ import { buildStatusPlugin } from "./build-status-plugin.js";
7
8
 
8
9
  const isRunningInSandbox = !!process.env.MODAL_SANDBOX_ID;
9
10
 
10
- const SANDBOX_DEP_CACHE_DIR = "/var/cache/base44-vite-deps";
11
-
12
11
  export default function vitePlugin(
13
12
  opts: {
14
13
  legacySDKImports?: boolean;
@@ -53,17 +52,8 @@ export default function vitePlugin(
53
52
  ...(isRunningInSandbox
54
53
  ? ({
55
54
  logLevel: "error",
56
- // The sandbox /app mount can't rename() dirs from the snapshot
57
- // layer (EXDEV), which breaks the dep optimizer's commit step.
58
- // Keep the dep cache on the container rootfs instead.
59
- cacheDir: SANDBOX_DEP_CACHE_DIR,
60
55
  server: {
61
56
  cors: true,
62
- fs: {
63
- // Explicit allow replaces Vite's defaults, so include the
64
- // app root alongside the external cache dir (served via /@fs/).
65
- allow: [root, SANDBOX_DEP_CACHE_DIR],
66
- },
67
57
  host: "0.0.0.0", // Bind to all interfaces for container access
68
58
  port: 5173,
69
59
  strictPort: true,
@@ -240,5 +230,12 @@ export default function vitePlugin(
240
230
  : []),
241
231
  // HTML injections - handles both dev (sandbox) and production injections
242
232
  htmlInjectionsPlugin({ hmrNotifier, navigationNotifier, visualEditAgent, analyticsTracker }),
233
+ // Opt-in, loopback-gated dev-server build-status endpoint. Gated here on
234
+ // the BASE44_BUILD_STATUS_ENABLED env var so the generated app's
235
+ // vite.config.js doesn't need to change and the sub-plugin isn't even
236
+ // added to the pipeline when disabled. The endpoint itself is dev-only.
237
+ ...(process.env.BASE44_BUILD_STATUS_ENABLED === "1"
238
+ ? [buildStatusPlugin()]
239
+ : []),
243
240
  ];
244
241
  }