mirror of
https://github.com/block/buzz.git
synced 2026-11-04 08:21:48 +00:00
1. Migration: existing users auto-seed experimental features as enabled
on first load (no feature loss on upgrade). New installs get opt-in UX.
2. Reactivity: SettingsView uses useFeatureSnapshot() so section list
updates instantly when toggles change (fixes stale useMemo deps).
3. Standards: Switch component replaces raw checkboxes, data-testid on
every toggle (feature-toggle-{id}, feature-toggle-dev-global).
4. Tests: 11 unit tests for resolveEnabled covering all tiers + edge cases.
5. Architecture: @features-manifest Vite alias replaces fragile ../../../../
relative import. Test loader also resolves the alias.
6. Versioned localStorage: keys now use -v1 suffix aligned to manifest version.
7. Cache: JSON.parse result cached across hook instances per render cycle.
8. Dev warning: console.warn in dev when getFeature() returns undefined.
Signed-off-by: Taylor Ho <taylorkmho@gmail.com>
34 lines
1.2 KiB
JavaScript
34 lines
1.2 KiB
JavaScript
import { fileURLToPath } from "node:url";
|
|
import path from "node:path";
|
|
|
|
const srcRoot = path.resolve(
|
|
path.dirname(fileURLToPath(import.meta.url)),
|
|
"src",
|
|
);
|
|
|
|
const repoRoot = path.resolve(path.dirname(fileURLToPath(import.meta.url)), "..");
|
|
|
|
export function resolve(specifier, context, nextResolve) {
|
|
if (specifier === "@features-manifest") {
|
|
const resolved = path.join(repoRoot, "features.json");
|
|
return nextResolve(resolved, context);
|
|
}
|
|
if (specifier.startsWith("@/")) {
|
|
const resolved = `${srcRoot}/${specifier.slice(2)}.ts`;
|
|
return nextResolve(resolved, context);
|
|
}
|
|
// Resolve extensionless relative TS imports (e.g. `./parseImeta`) — the app's
|
|
// bundler adds the extension, but node's ESM resolver does not. Without this,
|
|
// any .ts that relative-imports a sibling .ts can't be imported from a test,
|
|
// which previously forced stale inlined copies of the source under test.
|
|
if (
|
|
(specifier.startsWith("./") || specifier.startsWith("../")) &&
|
|
!path.extname(specifier) &&
|
|
context.parentURL
|
|
) {
|
|
const resolved = new URL(`${specifier}.ts`, context.parentURL).href;
|
|
return nextResolve(resolved, context);
|
|
}
|
|
return nextResolve(specifier, context);
|
|
}
|