Problem
branded-ui-react/no-external-call-in-pure-ui is useful as an architecture gate, but today it treats every external call inside inline Branded UI declarations the same way.
That makes gradual adoption hard in a real codebase because very different call kinds need different policies:
- React/runtime hooks such as
useState, useEffect, useForm are strong signals that behavior should move to a Binding/model hook.
- UI-owned translation hooks may be intentionally allowed by project policy.
- Pure or presentation helpers such as
cn, predicates, formatters, and simple mapping helpers may be acceptable in Pure UI.
- Domain/model helpers such as validation, normalization, filtering, and field-error extraction may be architecture smells, but teams may want to migrate them separately from hook bans.
The current allowedCalls option helps for exact names, but it is too coarse for this rollout: it cannot express "warn/error on hooks first, allow translations, review model helpers later" without either allowlisting many names or reporting many acceptable helper calls.
Concrete downstream audit
Against a Branded UI-migrated frontend using @jayjnu/oxlint-plugin-branded-ui-react@0.1.1, enabling no-external-call-in-pure-ui on frontend/src reported:
109 total diagnostics across 27 files
67 hook-call diagnostics across 25 files
42 non-hook/helper diagnostics across 8 files
Hook diagnostics:
16 useState
1 useEffect
1 useForm
46 useXxxTranslation
3 useMemberCredentialStateLabel
Non-hook/helper diagnostics:
16 validation helpers validateName, validateEndpoint, validateCredential, validateAuthHeader, getFieldError
10 callback/ref helpers previewRef, <expression>
6 builtin/collection Boolean, appLocales.map, providerTypes.map
4 predicates isThemePreference, isAppLocale, isProgressState, isFailureState
3 presentation helpers badgeVariant, progressDescription, failureDescription
2 transforms filterGatewayKeyList, normalizeMcpServerFormValues
1 styling helper cn
Some of these are useful findings: validation/normalization/filtering probably belong in a model hook or Binding. Others, like Boolean, .map, cn, and presentation-only mapping, are not useful blockers for adopting a hook ban.
Requested capability
Please consider adding rule granularity so projects can adopt this rule incrementally. Possible shapes:
- A mode focused on hooks first:
{
"branded-ui-react/no-external-call-in-pure-ui": [
"warn",
{ "mode": "hooks-only" }
]
}
- Pattern-based allow/deny lists:
{
"allowedCallPatterns": ["^use.*Translation$", "^cn$", "^Boolean$", "\\.map$"],
"deniedCallPatterns": ["^use(State|Effect|Form)$"]
}
- Import/module-aware policy:
{
"allowedModules": ["@/shared/ui/**", "@/shared/i18n/**"],
"deniedModules": ["@tanstack/react-form", "react"]
}
- Separate rules, for example:
no-hook-call-in-pure-ui
no-model-helper-call-in-pure-ui
- keep
no-external-call-in-pure-ui as the strict all-calls mode
Expected outcome
A project should be able to start with a low-noise policy such as:
- allow UI-owned translation hooks;
- warn on
useState, useEffect, useForm inside Pure UI;
- later migrate validation/normalization/filtering helpers into model hooks;
- avoid noise from builtin/presentation helpers.
This would keep the rule useful as an architecture guard without forcing teams to choose between "off" and "strict all external calls".
Problem
branded-ui-react/no-external-call-in-pure-uiis useful as an architecture gate, but today it treats every external call inside inline Branded UI declarations the same way.That makes gradual adoption hard in a real codebase because very different call kinds need different policies:
useState,useEffect,useFormare strong signals that behavior should move to a Binding/model hook.cn, predicates, formatters, and simple mapping helpers may be acceptable in Pure UI.The current
allowedCallsoption helps for exact names, but it is too coarse for this rollout: it cannot express "warn/error on hooks first, allow translations, review model helpers later" without either allowlisting many names or reporting many acceptable helper calls.Concrete downstream audit
Against a Branded UI-migrated frontend using
@jayjnu/oxlint-plugin-branded-ui-react@0.1.1, enablingno-external-call-in-pure-uionfrontend/srcreported:Hook diagnostics:
Non-hook/helper diagnostics:
Some of these are useful findings: validation/normalization/filtering probably belong in a model hook or Binding. Others, like
Boolean,.map,cn, and presentation-only mapping, are not useful blockers for adopting a hook ban.Requested capability
Please consider adding rule granularity so projects can adopt this rule incrementally. Possible shapes:
{ "branded-ui-react/no-external-call-in-pure-ui": [ "warn", { "mode": "hooks-only" } ] }{ "allowedCallPatterns": ["^use.*Translation$", "^cn$", "^Boolean$", "\\.map$"], "deniedCallPatterns": ["^use(State|Effect|Form)$"] }{ "allowedModules": ["@/shared/ui/**", "@/shared/i18n/**"], "deniedModules": ["@tanstack/react-form", "react"] }no-hook-call-in-pure-uino-model-helper-call-in-pure-uino-external-call-in-pure-uias the strict all-calls modeExpected outcome
A project should be able to start with a low-noise policy such as:
useState,useEffect,useForminside Pure UI;This would keep the rule useful as an architecture guard without forcing teams to choose between "off" and "strict all external calls".