Files
zeekay 7200114387 Merge upstream/dev (52 commits) + sweep yarn → pnpm
Upstream merge brings 52 commits from safe-global/safe-wallet-monorepo
into the luxfi/safe-wallet@dev fork.

Conflicts resolved:
- yarn.lock: deleted (we are on pnpm)
- apps/web/package.json: kept pnpm version + brand build scripts
  (build:safe / build:lux / build:hanzo) plus upstream's new
  generate-version.mjs step
- apps/mobile/.../Signer/appKit.ts: took upstream's import pattern
  for shared/projectId, shared/metadata, shared/mmkvStorageAdapter

Yarn sweep applied to 42 files (docs, github-actions, workflows, AGENTS,
specs, codemods, scripts, READMEs). Net result: zero yarn-* command
references anywhere outside node_modules.

  ❯ pnpm is the law in this fork. No yarn.
2026-05-27 03:25:16 -07:00

4.1 KiB

Quickstart: Bridge Feature Refactor

Feature: 002-bridge-refactor
Date: 2026-01-15

Prerequisites

  • Node.js and Yarn 4 installed
  • Repository cloned and dependencies installed (pnpm install)
  • On the feature branch (002-bridge-refactor)

Implementation Order

Follow this sequence to minimize broken state during refactoring:

Step 1: Create Barrel Files (No Breaking Changes)

Create the new barrel files without modifying existing code:

# Create the new files
touch apps/web/src/features/bridge/index.ts
touch apps/web/src/features/bridge/types.ts
touch apps/web/src/features/bridge/constants.ts
touch apps/web/src/features/bridge/components/index.ts
touch apps/web/src/features/bridge/hooks/index.ts

Step 2: Populate Constants

Move constants from components to constants.ts:

  1. Copy BRIDGE_WIDGET_URL from components/BridgeWidget/index.tsx
  2. Copy LOCAL_STORAGE_CONSENT_KEY from components/Bridge/index.tsx

Step 3: Populate Hook Barrel

Export hooks from hooks/index.ts:

export { useIsBridgeFeatureEnabled } from './useIsBridgeFeatureEnabled'
export { useIsGeoblockedFeatureEnabled } from './useIsGeoblockedFeatureEnabled'

Step 4: Populate Component Barrel

Export components from components/index.ts:

export { Bridge } from './Bridge'
export { BridgeWidget } from './BridgeWidget'

Step 5: Populate Root Barrel

Create the public API in index.ts with lazy-loaded default export.

Step 6: Update Internal Imports

Update components to import from constants.ts instead of defining inline.

Step 7: Update External Imports

Update files outside the feature to use the public API:

  • pages/bridge.tsx
  • services/analytics/tx-tracking.ts

Step 8: Verify

Run all checks:

pnpm --filter @safe-global/web type-check
pnpm --filter @safe-global/web lint
pnpm --filter @safe-global/web test --testPathPattern=bridge
pnpm --filter @safe-global/web build

Key Files Reference

Public API (index.ts)

import dynamic from 'next/dynamic'

export type {} from './types'
export { useIsBridgeFeatureEnabled, useIsGeoblockedFeatureEnabled } from './hooks'
export { BRIDGE_WIDGET_URL, LOCAL_STORAGE_CONSENT_KEY } from './constants'

const Bridge = dynamic(() => import('./components/Bridge').then((mod) => ({ default: mod.Bridge })), { ssr: false })

export default Bridge

Constants (constants.ts)

export const BRIDGE_WIDGET_URL = 'https://iframe.jumper.exchange/bridge'
export const LOCAL_STORAGE_CONSENT_KEY = 'bridgeConsent'

Hooks Barrel (hooks/index.ts)

export { useIsBridgeFeatureEnabled } from './useIsBridgeFeatureEnabled'
export { useIsGeoblockedFeatureEnabled } from './useIsGeoblockedFeatureEnabled'

Components Barrel (components/index.ts)

export { Bridge } from './Bridge'
export { BridgeWidget } from './BridgeWidget'

Verification Checklist

After implementation:

  • All new files created per target structure
  • No TypeScript errors (pnpm --filter @safe-global/web type-check)
  • No ESLint warnings for internal imports (pnpm --filter @safe-global/web lint)
  • All bridge tests pass (pnpm --filter @safe-global/web test --testPathPattern=bridge)
  • Build succeeds (pnpm --filter @safe-global/web build)
  • Bridge chunk visible in .next/static/chunks/

Rollback

If issues arise, the refactoring can be reverted by:

  1. Deleting the new barrel files
  2. Restoring original imports in modified files
  3. The feature will work as before since no logic was changed

Common Issues

Import Cycle Errors

If you see import cycle warnings, ensure:

  • Components import constants from ../../constants, not from sibling components
  • The root index.ts only imports from barrel files, not individual files

Test Import Errors

The test file BridgeWidget/index.test.tsx imports _getAppData directly. This is acceptable since:

  • It's within the feature boundary
  • The underscore prefix indicates it's internal
  • ESLint rules only restrict imports from outside the feature