fix(guardrails): exempt typed resources+/actions+ data endpoints from no-restricted-paths#31
Merged
Conversation
… no-restricted-paths
import-x/no-restricted-paths cannot distinguish a type-only import, so it
flagged a UI component's `import type {action}` from a typed data endpoint
(the `useFetcher<typeof action>` pattern). routes/resources+ and
routes/actions+ are no-UI, typed data endpoints the UI layer is meant to
consume.
Add `except: ['actions+', 'resources+']` to the three UI zones (pages,
components, hooks/state). `except` resolves relative to each zone's `from`;
only `routes` contains those subfolders, so the exemption is scoped to route
imports of the endpoints. The services, utils, and types zones get no
exemption, so the carve-out stays within the UI layer.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What
Exempt typed
routes/resources+androutes/actions+data endpoints from theimport-x/no-restricted-pathsarchitecture boundary, for the UI layers only.Why
import-x/no-restricted-pathscannot distinguish a type-only import.resources+andactions+are no-UI, typed data endpoints (direct children ofapp/routes/, siblings of_public+/_session+/_legal+) that the UI layer is explicitly meant to consume — theuseFetcher<typeof action>pattern requires a UI component toimport type {action}from aresources+/actions+endpoint. Without a carve-out the rule flags that type-only edge as a boundary violation.exceptresolves relative to each zone'sfrom. Onlyroutescontainsactions+/resources+subfolders, so listing them inexceptscopes the exemption to route imports of those endpoints. Real UI routes under_public+/_session+/_legal+stay fully restricted.Zones touched
except: ['actions+', 'resources+']is added to exactly three zones — the UI layers:from: [./app/routes], target./app/pagesfrom: [./app/routes, ./app/pages], target./app/componentsfrom: [./app/routes, ./app/pages, ./app/components], target[./app/hooks, ./app/state]The same three messages gain
Typed \resources+`/`actions+` data endpoints are exempt.`, and the function JSDoc documents the carve-out.The services, utils, and types zones deliberately get no exemption, so the carve-out cannot leak past the UI layer into the data/leaf layers.
Verification
The repo has no test suite, so I ran a functional rule check: drove the built guardrails config (pulled live from the
distbundle, not a hand-copied replica) through ESLint's flat-configLinteragainst a fixture tree mirroring the realapp/layout, using theno-restricted-pathsrule fromeslint-plugin-import-x@4.16.2withcreateNodeResolverandbasePathset to the fixture root.All assertions pass (5/5):
routes/resources+routes/actions+routes/_public+(real UI route)routes/resources+(no leak)pnpm build(tsup + tsc) andpnpm lintboth pass clean.🤖 Generated with Claude Code