Skip to content

Commit 793a240

Browse files
Merge pull request #1049 from heygen-com/fix/studio-import-meta-env-guard
fix(studio): guard import.meta.env for non-Vite bundlers
2 parents 179b09e + 377f081 commit 793a240

2 files changed

Lines changed: 18 additions & 38 deletions

File tree

packages/studio/src/telemetry/client.test.ts

Lines changed: 3 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -2,20 +2,11 @@
22

33
import { describe, expect, it, vi, beforeEach } from "vitest";
44

5-
// `shouldTrack()` reads `POSTHOG_API_KEY` from module-level const that's
6-
// evaluated at module load time, so changing `import.meta.env` after import
7-
// has no effect on the key. Each test resets module cache and re-imports.
5+
// `shouldTrack()` reads module-level constants evaluated at module load time,
6+
// so changing env after import has no effect. Each test resets module cache.
87

98
const OPT_OUT_KEY = "hyperframes-studio:telemetryDisabled";
109

11-
function setKey(value: string | undefined): void {
12-
if (value === undefined) {
13-
delete (import.meta.env as Record<string, unknown>).VITE_HYPERFRAMES_POSTHOG_KEY;
14-
} else {
15-
(import.meta.env as Record<string, unknown>).VITE_HYPERFRAMES_POSTHOG_KEY = value;
16-
}
17-
}
18-
1910
function setNoTelemetry(value: string | undefined): void {
2011
if (value === undefined) {
2112
delete (import.meta.env as Record<string, unknown>).VITE_HYPERFRAMES_NO_TELEMETRY;
@@ -37,29 +28,16 @@ async function loadShouldTrack(): Promise<() => boolean> {
3728
describe("studio client shouldTrack", () => {
3829
beforeEach(() => {
3930
setDev(false);
40-
setKey("phc_test_key");
4131
setNoTelemetry(undefined);
4232
localStorage.clear();
4333
vi.unstubAllGlobals();
4434
});
4535

46-
it("returns true when key is configured, not in dev mode, and no opt-outs", async () => {
36+
it("returns true when not in dev mode and no opt-outs", async () => {
4737
const shouldTrack = await loadShouldTrack();
4838
expect(shouldTrack()).toBe(true);
4939
});
5040

51-
it("returns false when API key does not start with phc_", async () => {
52-
setKey("not_a_real_key");
53-
const shouldTrack = await loadShouldTrack();
54-
expect(shouldTrack()).toBe(false);
55-
});
56-
57-
it("returns false when API key is empty string", async () => {
58-
setKey("");
59-
const shouldTrack = await loadShouldTrack();
60-
expect(shouldTrack()).toBe(false);
61-
});
62-
6341
it("returns false when user has opted out via localStorage", async () => {
6442
localStorage.setItem(OPT_OUT_KEY, "1");
6543
const shouldTrack = await loadShouldTrack();
@@ -93,7 +71,6 @@ describe("studio client shouldTrack", () => {
9371
it("memoizes its decision after the first call", async () => {
9472
const shouldTrack = await loadShouldTrack();
9573
const first = shouldTrack();
96-
// Flip an underlying input — memoized return must not change.
9774
localStorage.setItem(OPT_OUT_KEY, "1");
9875
expect(shouldTrack()).toBe(first);
9976
});

packages/studio/src/telemetry/client.ts

Lines changed: 15 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -7,15 +7,9 @@
77
import { getAnonymousId, hasShownNotice, isOptedOut, markNoticeShown } from "./config";
88
import { getBrowserSystemMeta } from "./system";
99

10-
// HeyGen's PostHog project key — write-only, safe to embed in client code.
11-
// OSS builds can override via `VITE_HYPERFRAMES_POSTHOG_KEY` at build time,
12-
// or set it to an empty string to disable telemetry entirely.
13-
const POSTHOG_API_KEY =
14-
(import.meta.env.VITE_HYPERFRAMES_POSTHOG_KEY as string | undefined) ??
15-
"phc_zjjbX0PnWxERXrMHhkEJWj9A9BhGVLRReICgsfTMmpx";
16-
const POSTHOG_HOST =
17-
(import.meta.env.VITE_HYPERFRAMES_POSTHOG_HOST as string | undefined) ??
18-
"https://us.i.posthog.com";
10+
// Write-only PostHog project key, safe to embed in client code.
11+
const POSTHOG_API_KEY = "phc_zjjbX0PnWxERXrMHhkEJWj9A9BhGVLRReICgsfTMmpx";
12+
const POSTHOG_HOST = "https://us.i.posthog.com";
1913
const FLUSH_INTERVAL_MS = 1_000;
2014

2115
type EventProperties = Record<string, string | number | boolean | undefined>;
@@ -41,15 +35,24 @@ function isApiKeyConfigured(): boolean {
4135
// VITE_HYPERFRAMES_NO_TELEMETRY mirrors the CLI's HYPERFRAMES_NO_TELEMETRY=1
4236
// opt-out so HeyGen's own dev/CI builds can suppress telemetry from the studio
4337
// bundle the same way. Vite injects it at build time. Accepts "1" or "true".
38+
// `import.meta.env` may be undefined in non-Vite bundlers (Next.js Turbopack).
4439
function isBuildTimeOptOut(): boolean {
45-
const v = import.meta.env.VITE_HYPERFRAMES_NO_TELEMETRY as string | undefined;
46-
return v === "1" || v === "true";
40+
try {
41+
const v = import.meta.env.VITE_HYPERFRAMES_NO_TELEMETRY as string | undefined;
42+
return v === "1" || v === "true";
43+
} catch {
44+
return false;
45+
}
4746
}
4847

4948
// `import.meta.env.DEV` is true under `vite dev` / `vite preview`. Auto-suppress
5049
// so developers running `hyperframes preview` don't pollute production telemetry.
5150
function isViteDevMode(): boolean {
52-
return import.meta.env.DEV === true;
51+
try {
52+
return import.meta.env.DEV === true;
53+
} catch {
54+
return false;
55+
}
5356
}
5457

5558
export function shouldTrack(): boolean {

0 commit comments

Comments
 (0)