mirror of
https://github.com/heygen-com/hyperframes.git
synced 2026-09-07 18:26:17 +00:00
## What Removes six Studio feature flags that have been default-`true` for 7+ weeks. Each is reachable under two env names, so this deletes **12 `VITE_STUDIO_*` env vars**: | Flag constant | Env names removed | Default-on since | |---|---|---| | `STUDIO_PREVIEW_MANUAL_EDITING_ENABLED` | `VITE_STUDIO_ENABLE_PREVIEW_MANUAL_DRAGGING`, `VITE_STUDIO_PREVIEW_MANUAL_EDITING_ENABLED` | 2026-05-12 | | `STUDIO_INSPECTOR_PANELS_ENABLED` (+ its `STUDIO_PREVIEW_SELECTION_ENABLED` alias) | `VITE_STUDIO_ENABLE_INSPECTOR_PANELS`, `VITE_STUDIO_INSPECTOR_PANELS_ENABLED` | 2026-05-12 | | `STUDIO_BLOCKS_PANEL_ENABLED` | `VITE_STUDIO_ENABLE_BLOCKS_PANEL`, `VITE_STUDIO_BLOCKS_PANEL_ENABLED` | 2026-05-18 | | `STUDIO_GSAP_PANEL_ENABLED` | `VITE_STUDIO_ENABLE_GSAP_PANEL`, `VITE_STUDIO_GSAP_PANEL_ENABLED` | 2026-05-28 | | `STUDIO_KEYFRAMES_ENABLED` | `VITE_STUDIO_ENABLE_KEYFRAMES`, `VITE_STUDIO_KEYFRAMES_ENABLED` | 2026-06-05 | | `STUDIO_RAZOR_TOOL_ENABLED` | `VITE_STUDIO_ENABLE_RAZOR_TOOL`, `VITE_STUDIO_RAZOR_TOOL_ENABLED` | 2026-06-10 | ## Why Every one of these shipped as a rollout gate, went to `true`, and then stayed. Because none of them was ever flipped back, the `false` branch was unreachable in practice while still costing a real import, a real conditional, and a real "what happens if this is off?" question at ~90 call sites across 25 files. The bigger cost is what the dead branch kept alive. Removing the flags also removes the disabled-Studio code paths that only existed to serve them: - the greyed-out, `disabled`, "Manual editing is temporarily disabled" Inspector button in `StudioHeader` (and the `STUDIO_MANUAL_EDITING_DISABLED_TITLE` constant behind it) - the inspector-off reset `useEffect` in `useDomSelection`, which force-cleared selection and redirected the right panel to Renders - three selection kill-switch early-returns in `useDomSelection` (`applyDomSelection`, `handleTimelineElementSelect`, `applyMarqueeSelection`) - the tab-redirect branch in `normalizeStudioUrlPanelTab`, whose `options.inspectorPanelsEnabled` parameter had no production caller at all (only tests passed it) ## How No behavior change: every flag was removed by keeping its default-`true` side. The call-site edits are three mechanical boolean shapes (`X && rest` → `rest`, `rest && X` → `rest`, `!X || rest` → `rest`), applied by script for uniformity. Everything else (ternaries, `if` guards, unreachable blocks, JSX wrappers that had no other condition) was done by hand and the whole diff was read line by line afterwards. `resolveStudioBooleanEnvFlag` and the `import.meta.env` / `window.__HF_STUDIO_ENV__` plumbing stay: three flags still use them (`STUDIO_FLAT_INSPECTOR_ENABLED`, `STUDIO_SDK_CUTOVER_ENABLED`, `STUDIO_SDK_RESOLVER_SHADOW_ENABLED`). Its unit tests kept their coverage but now exercise a live flag pair instead of retired env names, so no dead `VITE_STUDIO_*` string is left in the repo. Net **-191 lines** (236 insertions, 427 deletions across 25 files); most insertions are reindentation of JSX that lost a wrapper. ### Deliberately not in scope Flags authored by other people are untouched, even where they look similarly settled: - `VITE_STUDIO_ENABLE_FLAT_INSPECTOR` / `VITE_STUDIO_FLAT_INSPECTOR_ENABLED` (default true, but not mine) - `VITE_STUDIO_SDK_CUTOVER_ENABLED`, `VITE_STUDIO_SDK_CUTOVER_FAMILIES`, `VITE_STUDIO_SDK_RESOLVER_SHADOW_ENABLED` (SDK cutover canary, still soaking) - `VITE_HYPERFRAMES_NO_TELEMETRY` Mine but genuinely long-lived configuration rather than rollout gates, so they stay: `VITE_STUDIO_DISCOVERY_PORTS`, `VITE_HYPERFRAMES_FEEDBACK_INTERVAL`, `VITE_HYPERFRAMES_NO_FEEDBACK` (a documented user opt-out), plus the `HYPERFRAMES_*` binary paths, API URLs, cache sizes, and timeouts. `VITE_STUDIO_ENABLE_MOTION_PANEL` / `VITE_STUDIO_MOTION_PANEL_ENABLED` were already retired from production code before this PR; they only survived as placeholder names inside the resolver's unit tests, and this PR swaps those out. ## Test plan - [x] Unit tests added/updated - dropped the two tests asserting removed flag defaults; retargeted the `resolveStudioBooleanEnvFlag` cases at a live flag pair; updated `studioUrlState` tests for the narrowed `normalizeStudioUrlPanelTab` signature (now also asserts an unknown tab returns `null`). - [x] Manual testing performed - see below. - [ ] Documentation updated (if applicable) - not needed; no removed name appears in `docs/`, `skills/`, or `registry/`. (`docs/changelog.mdx` has one historical entry naming `STUDIO_KEYFRAMES_ENABLED`; changelog history is left as written.) ``` packages/studio: bunx vitest run # 280 files, 3116 tests pass, 1 skipped packages/studio: bunx tsc --noEmit # clean bun run build # green (all packages) bunx oxlint <25 changed files> # 0 warnings, 0 errors bunx oxfmt --check <25 changed files> # clean ``` Two extra checks, because part of this diff was script-generated: 1. Zero references to any removed flag constant or env name remain anywhere outside `docs/changelog.mdx`. 2. Diffed every string literal in each changed non-test file against `origin/main`. The only differences are the intended removals: the 12 env names, `"Manual editing is temporarily disabled"`, the `"cursor-not-allowed …"` disabled class, the 3-column `"1fr 1fr 1fr"` grid, and the `"renders"` redirect literals. No user-facing label, tooltip, or class string changed by accident.
78 lines
3.2 KiB
TypeScript
78 lines
3.2 KiB
TypeScript
export type StudioFeatureFlagEnv = Record<string, boolean | string | undefined>;
|
|
|
|
const TRUTHY_ENV_VALUES = new Set(["1", "true", "yes", "on", "enabled"]);
|
|
const FALSY_ENV_VALUES = new Set(["0", "false", "no", "off", "disabled"]);
|
|
|
|
export function resolveStudioBooleanEnvFlag(
|
|
env: StudioFeatureFlagEnv,
|
|
names: string[],
|
|
fallback: boolean,
|
|
): boolean {
|
|
for (const name of names) {
|
|
const value = env[name];
|
|
if (typeof value === "boolean") return value;
|
|
if (typeof value !== "string") continue;
|
|
|
|
const normalized = value.trim().toLowerCase();
|
|
if (!normalized) continue;
|
|
if (TRUTHY_ENV_VALUES.has(normalized)) return true;
|
|
if (FALSY_ENV_VALUES.has(normalized)) return false;
|
|
}
|
|
|
|
return fallback;
|
|
}
|
|
|
|
// `import.meta.env` is a Vite-only extension. In non-Vite ESM hosts
|
|
// (Next.js / Turbopack, Node, jest in some configs) it's undefined,
|
|
// and downstream `env[name]` reads would crash. Fall back to `{}` so
|
|
// every flag resolves to its declared default outside Vite. Direct
|
|
// property access keeps Vite's compile-time transform happy.
|
|
//
|
|
// When the studio is served as a pre-built SPA by the embedded Hono server,
|
|
// `import.meta.env` values were baked at build time. The server injects
|
|
// `window.__HF_STUDIO_ENV__` with any `VITE_STUDIO_*` env vars from the
|
|
// user's shell, so runtime overrides take precedence over baked defaults.
|
|
const runtimeEnv =
|
|
typeof window !== "undefined"
|
|
? ((window as Window & { __HF_STUDIO_ENV__?: StudioFeatureFlagEnv }).__HF_STUDIO_ENV__ ?? {})
|
|
: {};
|
|
const env = { ...(import.meta.env ?? {}), ...runtimeEnv } as StudioFeatureFlagEnv;
|
|
|
|
// Stage 7 Step 3c: SDK cutover — routes inline-style ops through SDK dispatch
|
|
// instead of the server patch-element API. Default false; enable via
|
|
// VITE_STUDIO_SDK_CUTOVER_ENABLED=true. Requires SDK session to be open.
|
|
export const STUDIO_SDK_CUTOVER_ENABLED = resolveStudioBooleanEnvFlag(
|
|
env,
|
|
["VITE_STUDIO_SDK_CUTOVER_ENABLED"],
|
|
false,
|
|
);
|
|
|
|
/** Explicit per-operation-family canary selection; the master flag alone enables nothing. */
|
|
export const STUDIO_SDK_CUTOVER_FAMILIES = resolveEnabledSdkFamilies(
|
|
env,
|
|
STUDIO_SDK_CUTOVER_ENABLED,
|
|
);
|
|
|
|
// Resolver-parity tripwire (telemetry-only, decoupled from cutover).
|
|
// Runs the SDK resolver alongside any edit and emits sdk_resolver_shadow on
|
|
// divergence. Default true; disable via VITE_STUDIO_SDK_RESOLVER_SHADOW_ENABLED=false.
|
|
// Soak gate: retire once zero element_not_found divergences over a clean window.
|
|
export const STUDIO_SDK_RESOLVER_SHADOW_ENABLED = resolveStudioBooleanEnvFlag(
|
|
env,
|
|
["VITE_STUDIO_SDK_RESOLVER_SHADOW_ENABLED"],
|
|
true,
|
|
);
|
|
|
|
// Studio inspector redesign ("Ledger, flat" — design_handoff_studio_inspector):
|
|
// flat identity header/footer/groups. Default true as of v0.7.59+ bug-fix pass
|
|
// (right-aligned values, Stroke select-only, promote-badge overlap, Layout/
|
|
// Style section gating); disable via VITE_STUDIO_FLAT_INSPECTOR_ENABLED=false
|
|
// to fall back to the legacy panel.
|
|
export const STUDIO_FLAT_INSPECTOR_ENABLED = resolveStudioBooleanEnvFlag(
|
|
env,
|
|
["VITE_STUDIO_ENABLE_FLAT_INSPECTOR", "VITE_STUDIO_FLAT_INSPECTOR_ENABLED"],
|
|
true,
|
|
);
|
|
|
|
import { resolveEnabledSdkFamilies } from "../../utils/sdkCutoverPolicy";
|