feat: devtool indicator auto-visibility based on NODE_ENV (#1624)
Some checks failed
all-good: Did all the other checks pass? / all-good (push) Has been cancelled
Ensure Prisma migrations are in sync with the schema / check_prisma_migrations (22.x) (push) Has been cancelled
Docker Server Build and Push / Docker Build and Push Server (push) Has been cancelled
Docker Server Build and Run / docker (push) Has been cancelled
Runs E2E API Tests (Local Emulator) / E2E Tests (Local Emulator, Node ${{ matrix.node-version }}) (22.x) (push) Has been cancelled
Runs E2E API Tests / E2E Tests (Node ${{ matrix.node-version }}, Freestyle ${{ matrix.freestyle-mode }}) (mock, 22.x) (push) Has been cancelled
Runs E2E API Tests / E2E Tests (Node ${{ matrix.node-version }}, Freestyle ${{ matrix.freestyle-mode }}) (prod, 22.x) (push) Has been cancelled
Runs E2E API Tests with custom port prefix / build (22.x) (push) Has been cancelled
Runs E2E Fallback Tests / E2E Fallback Tests (Node ${{ matrix.node-version }}) (22.x) (push) Has been cancelled
Lint & build / lint_and_build (24) (push) Has been cancelled
Publish npm packages / publish (push) Has been cancelled
Publish Swift SDK to prerelease repo / publish (push) Has been cancelled
TOC Generator / TOC Generator (push) Has been cancelled

This commit is contained in:
Konsti Wohlwend 2026-06-19 16:47:02 -07:00 committed by GitHub
parent a9d77bbf63
commit e3202a331c
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 33 additions and 10 deletions

View File

@ -5,6 +5,7 @@ import { captureError } from "@hexclave/shared/dist/utils/errors";
import { runAsynchronously } from "@hexclave/shared/dist/utils/promises";
import { isLocalhost } from "@hexclave/shared/dist/utils/urls";
import { canMountIntoDom } from "../in-page-ui/dom";
import { envVars } from "../generated/env";
import type { createDevTool as CreateDevToolFn } from "./dev-tool-core";
// Hexclave rebrand: UI-only local pref — straight rename (one-time reset is harmless)
@ -19,10 +20,28 @@ function getOverride(): boolean | null {
return null;
}
let activeDevToolOption: true | "auto" | undefined = undefined;
function shouldShow(): boolean {
const override = getOverride();
if (override !== null) return override;
if (!canMountIntoDom()) return false;
// If devTool was explicitly set to true, always show
if (activeDevToolOption === true) return true;
// "auto" behavior (the default):
const nodeEnv = envVars.NODE_ENV;
if (nodeEnv !== undefined) {
// NODE_ENV is available (bundler/process env exists) — only show in development
return nodeEnv === "development";
}
// NODE_ENV not found (no process.env/import.meta) — show on localhost or file: protocol
try {
const url = new URL(window.location.href);
if (url.protocol === "file:") return true;
} catch {}
return isLocalhost(window.location.href);
}
@ -68,17 +87,19 @@ function tryMount() {
/**
* Mounts the Hexclave dev tool on the page.
*
* - Only renders on localhost (or when overridden via console)
* - Lazily loads the dev tool UI via dynamic import
* - Returns a cleanup function to unmount
* Visibility is determined by the `devTool` option:
* - `true`: always show
* - `false`: never show (caller gates this mountDevTool won't be called)
* - `"auto"` / `undefined`: show based on NODE_ENV or localhost/file: heuristics
*
* Console commands (also work in production):
* HexclaveDevTool.enable() force-show the dev tool
* HexclaveDevTool.disable() force-hide the dev tool
* HexclaveDevTool.reset() revert to default (localhost-only)
* HexclaveDevTool.reset() revert to auto behavior
*/
export function mountDevTool(app: StackClientApp<true>): () => void {
export function mountDevTool(app: StackClientApp<true>, devToolOption?: boolean | "auto"): () => void {
activeApp = app;
activeDevToolOption = devToolOption === false ? undefined : devToolOption ?? undefined;
tryMount();
// Capture the cleanup created by THIS specific mount call so that React
@ -126,7 +147,7 @@ if (typeof window !== 'undefined') {
activeCleanup();
activeCleanup = null;
}
console.log('[Stack DevTool] Reset to default (visible on localhost only).');
console.log('[Stack DevTool] Reset to default (auto-detect based on NODE_ENV or localhost/file: origin).');
},
};
}

View File

@ -763,7 +763,7 @@ export class _HexclaveClientAppImplIncomplete<HasTokenStore extends boolean, Pro
// IF_PLATFORM js-like
if (isBrowserLike() && resolvedOptions.devTool !== false) {
mountDevTool(this as any);
mountDevTool(this as any, resolvedOptions.devTool);
}
if (isBrowserLike()) {
// Independent of the dev tool: the clickmap overlay only ever renders

View File

@ -22,11 +22,13 @@ export type StackClientAppConstructorOptions<HasTokenStore extends boolean, Proj
inheritsFrom?: StackClientApp<any, any>,
/**
* Whether to show the Hexclave dev tool indicator in browser-like development environments.
* Whether to show the Hexclave dev tool indicator in browser-like environments.
*
* Defaults to true.
* - `true`: always show
* - `false`: never show
* - `"auto"` (default): show based on NODE_ENV or origin heuristics
*/
devTool?: boolean,
devTool?: boolean | "auto",
/**
* By default, the Stack app will automatically prefetch some data from Stack's server when this app is first