@pylonsync/functions 0.3.250 → 0.3.251

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@pylonsync/functions",
3
- "version": "0.3.250",
3
+ "version": "0.3.251",
4
4
  "description": "TypeScript function runtime for pylon — defines server-side queries, mutations, and actions.",
5
5
  "type": "module",
6
6
  "main": "src/index.ts",
@@ -7,6 +7,20 @@
7
7
  // the dispatch arm) so projects without SSR routes pay nothing — no
8
8
  // react-dom dependency requirement, no startup cost.
9
9
 
10
+ /**
11
+ * Is the runtime in dev mode? MUST match the Rust host's `is_dev_mode()`
12
+ * (crates/runtime/src/frontend.rs): `PYLON_DEV_MODE` is on ONLY for the exact
13
+ * strings "1" or "true" (case-insensitive). A bare `if (process.env.PYLON_DEV_MODE)`
14
+ * is WRONG — the string "false"/"0" is truthy in JS, so an explicit
15
+ * `PYLON_DEV_MODE=false` on a PROD machine would wrongly enable dev behavior
16
+ * (e.g. the live-reload `<script>` was being injected into prod pages, whose
17
+ * EventSource then 404-retried `/_pylon/dev/live` forever).
18
+ */
19
+ export function isDevMode(): boolean {
20
+ const v = process.env.PYLON_DEV_MODE;
21
+ return v === "1" || v?.toLowerCase() === "true";
22
+ }
23
+
10
24
  /**
11
25
  * The message payload the host sends. Matches RenderRouteMessage in
12
26
  * crates/functions/src/protocol.rs.
@@ -856,7 +870,7 @@ export function buildHydrationTail(args: {
856
870
  } else {
857
871
  tail += `<script>console.warn(${JSON.stringify(`[pylon ssr] hydration disabled: ${args.manifestErr}`)})</script>`;
858
872
  }
859
- if (process.env.PYLON_DEV_MODE) tail += DEV_LIVE_RELOAD_SNIPPET;
873
+ if (isDevMode()) tail += DEV_LIVE_RELOAD_SNIPPET;
860
874
  return tail;
861
875
  }
862
876
 
@@ -1741,8 +1755,7 @@ export async function handleRenderRoute(
1741
1755
  // In dev, send the full stack as the message so the host can paint a
1742
1756
  // useful error overlay instead of an opaque 500. In prod, send only the
1743
1757
  // message (the host shows a generic page; the stack stays in logs).
1744
- const devMode =
1745
- process.env.PYLON_DEV_MODE === "1" || process.env.PYLON_DEV_MODE === "true";
1758
+ const devMode = isDevMode();
1746
1759
  send({
1747
1760
  type: "error",
1748
1761
  call_id: msg.call_id,
@@ -22,8 +22,46 @@ import {
22
22
  computeRevalidateSecs,
23
23
  computeWantsStream,
24
24
  diffCommittedResponse,
25
+ isDevMode,
25
26
  } from "./ssr-runtime";
26
27
 
28
+ // ---------------------------------------------------------------------------
29
+ // isDevMode — must match the Rust host's is_dev_mode() exactly
30
+ // ---------------------------------------------------------------------------
31
+
32
+ describe("isDevMode (PYLON_DEV_MODE parity with Rust host)", () => {
33
+ const orig = process.env.PYLON_DEV_MODE;
34
+ const set = (v: string | undefined) => {
35
+ if (v === undefined) delete process.env.PYLON_DEV_MODE;
36
+ else process.env.PYLON_DEV_MODE = v;
37
+ };
38
+
39
+ test("ONLY '1' / 'true' (case-insensitive) are dev; 'false'/'0'/unset are NOT", () => {
40
+ try {
41
+ set("1");
42
+ expect(isDevMode()).toBe(true);
43
+ set("true");
44
+ expect(isDevMode()).toBe(true);
45
+ set("TRUE");
46
+ expect(isDevMode()).toBe(true);
47
+ // The bug this guards: a prod machine explicitly set PYLON_DEV_MODE=false,
48
+ // and `if (process.env.PYLON_DEV_MODE)` treated the truthy STRING "false"
49
+ // as dev → injected the live-reload script → EventSource 404-looped on
50
+ // /_pylon/dev/live in prod.
51
+ set("false");
52
+ expect(isDevMode()).toBe(false);
53
+ set("0");
54
+ expect(isDevMode()).toBe(false);
55
+ set("");
56
+ expect(isDevMode()).toBe(false);
57
+ set(undefined);
58
+ expect(isDevMode()).toBe(false);
59
+ } finally {
60
+ set(orig);
61
+ }
62
+ });
63
+ });
64
+
27
65
  // ---------------------------------------------------------------------------
28
66
  // Pure verdict logic
29
67
  // ---------------------------------------------------------------------------