chore(utils): add src/utils barrel file — 418 deep imports across 188 files; 3 export-name collisions block export *

Open
#929 0 comments 0 reactions 0 assignees View on GitHub

Maintainers usually reply within 1 day

Nobody has claimed this yet.

Assessment

Difficulty
4/5
Estimated time
3-5 days
Newbie friendliness
48/100
Issue type
Refactor
Clarity
Clearly specified
Activity status
Active
Tech stack
eslint, typescript, vite

Research direction

Start by reading the existing src/utils/cosmos/index.ts barrel and inspect the three collision pairs in encodingUtils.ts/nodePortal.ts, sngSchedule.ts/scheduledSng.ts, and accountUtils.ts/b52AccountUtils.ts, along with their callers. Then add the top-level and bridge barrels, migrate consumer imports, and configure ESLint to block deep imports. Run yarn build, yarn test, and yarn lint; done means all acceptance criteria pass, including unchanged chunk sizes.

Written by the indexing model from the issue text.

Description

architecture refactor tech debt

Problem

src/utils/ has 78 source modules (plus bridge/ and cosmos/ subfolders) and no barrel file. Every consumer deep-imports individual modules, so imports pile up at the top of components:

  • 418 separate from "../utils/..." import statements across 188 files
  • Worst offenders: components/playPage/Table.tsx (13 utils import lines), pages/TableAdminPage.tsx (12), pages/Dashboard.tsx (11), components/Footer/PokerActionPanel.tsx (11)
// today — Table.tsx has 13 of these lines
import { hasElements } from "../../utils/guards";
import { formatWinnings } from "../../utils/formatUtils";
import { colors } from "../../utils/colorConfig";
// ...10 more

// with a barrel
import { hasElements, formatWinnings, colors } from "../../utils";

Beyond the noise, deep imports mean every move/rename inside utils/ touches dozens of call sites, and there is no single place that defines the public surface of the utils layer.

What exists today (code pass)

  • src/utils/cosmos/index.ts already exists — the pattern has precedent inside utils itself; the top level never got one.
  • All utils use named exports only (zero export default), so the barrel is pure export * from "./x" re-exports — Vite/Rollup tree-shakes these fine in an app build.
  • Three export-name collisions block a blind export * and must be resolved first. They are not copy-paste duplicates — each pair is two different functions sharing a name:
Name File A File B Conflict
base64ToHex encodingUtils.ts nodePortal.ts Different output: lowercase with 0x prefix vs UPPERCASE without prefix. Callers depend on the format, so they can't be merged blindly — rename the nodePortal one (e.g. base64ToHexUpper) or converge callers onto encodingUtils deliberately.
formatCountdown sngSchedule.ts scheduledSng.ts Different signatures and semantics: (msRemaining) with days + "Starting now" vs (untilMs, nowMs) h:mm:ss. (That sngSchedule.ts and scheduledSng.ts both exist is its own smell.)
getPublicKey accountUtils.ts b52AccountUtils.ts accountUtils derives an ETH public key from a private key; b52AccountUtils reads the stored cosmos address from localStorage — it doesn't return a public key at all. Rename it to what it does (e.g. getStoredCosmosAddress).

Proposal (scoped to src/utils/ only, for now)

  1. Resolve the three collisions by renaming to intent (above) and updating their call sites. Each rename is mechanical and independently committable.
  2. Add src/utils/index.ts with export * from "./<module>" for every source module; re-export the subfolders via their own barrels (export * from "./cosmos", add a tiny bridge/index.ts). Exclude test files. Keep the barrel re-export-only — no logic, no side-effectful module loads.
  3. Migrate the 418 imports to from "../utils" (mechanical codemod / find-replace; no behavior change).
  4. Enforce it: ESLint no-restricted-imports on **/utils/* (allowing utils itself and intra-utils relative imports), so deep imports don't creep back.
  5. New-utils convention: adding a util = add the module + its .test.ts + one barrel line (document in CLAUDE.md's utils section).

Out of scope for this issue (follow-ups if this proves out): barrels for hooks/, components/ui/ (#42 already tracks the component library surface), apis/.

Note on bundle size

ui#779 (first-load JS) is the reason to keep the barrel pure: export * of side-effect-free modules tree-shakes cleanly under Rollup, but a barrel that executes anything at import time would pull the whole utils layer into every chunk. Acceptance includes verifying chunk sizes don't regress.

Prior art / related

  • src/utils/cosmos/index.ts — existing in-repo precedent
  • block52/poker-vm#1635 (closed) — same pattern applied to engine manager imports
  • #42 (open) — component library index.ts does this for components/ui/
  • #779 (open) — bundle-size context for keeping the barrel pure

Acceptance criteria

  • Three name collisions renamed (base64ToHex ×2, formatCountdown ×2, getPublicKey ×2) with call sites updated
  • src/utils/index.ts + src/utils/bridge/index.ts added, re-export-only
  • All consumer imports migrated to the barrel (no remaining deep utils/* imports outside src/utils/)
  • ESLint rule preventing new deep imports
  • yarn build chunk sizes unchanged (± noise) — no tree-shaking regression
  • yarn test and yarn lint green
Dominant language
TypeScript
Stars
2
Forks
5
Avg merge
22h 35m
Merged PRs (30d)
91

Getting set up

We have not checked this project's setup files yet. Start from its README, and see our first-contribution guide for the general steps.

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

More from block52/ui

All issues in block52/ui

Similar issues

More TypeScript issues

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.