Skip to content

refactor: introduce an @ path alias to replace deep relative imports, enforced with eslint (#3210) - #3240

Merged
frano-m merged 9 commits into
mainfrom
fran/3210-path-alias
Sep 29, 2026
Merged

frano-m merged 9 commits into
mainfrom
fran/3210-path-alias

Conversation

@frano-m

@frano-m frano-m commented Sep 21, 2026 •

Copy link
Copy Markdown
Contributor

Summary

Closes #3210

Adds a @/* root path alias, rewrites every out-of-subtree import to use it, and enforces the convention with ESLint.

Changes

  • tsconfig: adds "@/*": ["./*"] and drops baseUrl, so bare root imports like constants/routes no longer resolve. The unused images/* path is also removed.

  • Imports: 331 specifiers across 125 files now use @/… instead of ../.

  • @types → types: the directory is renamed so imports read @/types/network. A @types/* alias was rejected because it would shadow npm @types/ packages.

  • Lint rule (eslint.config.mjs): any .. segment in an import specifier is an error. One regex, PARENT_SEGMENT_PATTERN, covers:

    • static import, import type, export … from and export * (@typescript-eslint/no-restricted-imports)
    • dynamic import() and require(), with string or template-literal specifiers (no-restricted-syntax)

    ./ stays allowed for same-directory and descendant imports.

Decisions

  • Bare root imports: no lint rule. Without baseUrl they fail to compile, unless an installed npm package has the same name as a top-level folder (config, utils, …), in which case the package wins. No installed package does today. A rule that lists the top-level folders would need updating by hand, so we deliberately don't have one.
  • MDX: not linted. Every .mdx file is compiled at runtime by next-mdx-remote serialize(), which can't resolve imports; components come in through the components prop. No .mdx file contains an import or export.
  • Prettier: prettier-plugin-organize-imports sorts @/ among scoped packages, and check-format passes.
  • Scripts: esrun honours tsconfig paths, so scripts/ uses the alias and is linted like everything else.

Verification

  • npm run lint (0 errors, 8 pre-existing warnings), npm run check-format and npx tsc --noEmit pass.
  • npm run build-dev:data-portal passes.
  • The rule was run against a sample file in .ts, .tsx, .js, .jsx, .mjs, .cjs and .styles.ts. It flags ../x, ../../x, ./a/../../x, .., export * from "../x", export { x } from "../x", import("../x"), import(`../x/${y}`), import(`${y}/../x`), require("../x") and require(`../x`). It allows ./x, @/x, ..foo, import(`./x/${y}`) and require(`./x/${y}`).

🤖 Generated with Claude Code

frano-m and others added 2 commits September 21, 2026 18:58
… enforced with eslint (#3210)

add the `@/*` root alias to tsconfig and the codemod that rewrites
out-of-subtree imports to use it. the rewrite itself lands in the next
commit so the script can be reviewed apart from its output.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01AsKeyxfv4ZT3FdQaqtGBdV
… enforced with eslint (#3210)

rename `@types` to `types` so the alias reads as `@/types/...`, apply the
codemod (331 specifiers across 125 files), and add `no-restricted-imports`
so `../` and bare baseurl paths fail lint.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01AsKeyxfv4ZT3FdQaqtGBdV

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot review overview

🟡 Changes recommended

One or more issues must be addressed before approval.

Get a fresh assessment by requesting another Copilot review.

Review effort: Lite
Findings: 1 High severity · 1 Medium severity

Open (2)
What changed in this PR

Introduces a repository-wide @/* root alias, migrates deep imports, and enforces the convention through ESLint.

Changes:

  • Adds TypeScript path aliasing and renames @types to types.
  • Adds and runs a codemod for cross-subtree imports.
  • Adds ESLint restrictions for deep-relative and bare root imports.
File Description
views/​SearchView/​searchView.tsx Updated as part of this pull request.
views/​SearchView/​hooks/​useSearchCategory.ts Updated as part of this pull request.
views/​SearchView/​hooks/​useSearch.ts Updated as part of this pull request.
views/​SearchView/​hooks/​common/​utils.ts Updated as part of this pull request.
views/​SearchView/​components/​Results/​results.tsx Updated as part of this pull request.
views/​SearchView/​components/​Pagination/​pagination.tsx Updated as part of this pull request.
views/​HomeView/​homeView.tsx Updated as part of this pull request.
viewModelBuilders/​viewModelBuilders.tsx Updated as part of this pull request.
viewModelBuilders/​dataDictionaryMapper/​columnDefs.ts Updated as part of this pull request.
utils/​trackerNetwork.ts Updated as part of this pull request.
utils/​trackerAtlasPages.ts Updated as part of this pull request.
utils/​summary.ts Updated as part of this pull request.
utils/​networkPublicationPages.ts Updated as part of this pull request.
utils/​networkPages.ts Updated as part of this pull request.
utils/​network.ts Updated as part of this pull request.
utils/​homePage.ts Updated as part of this pull request.
utils/​docPages.ts Updated as part of this pull request.
utils/​datasets.ts Updated as part of this pull request.
utils/​availableNetworks.ts Updated as part of this pull request.
utils/​atlasPages.ts Updated as part of this pull request.
utils/​atlases.ts Updated as part of this pull request.
types/​theme.d.ts Updated as part of this pull request.
types/​network.ts Updated as part of this pull request.
types/​global.d.ts Updated as part of this pull request.
tsconfig.json Updated as part of this pull request.
site-config/​data-portal/​prod/​config.ts Updated as part of this pull request.
site-config/​data-portal/​dev/​themeOptions.ts Updated as part of this pull request.
site-config/​data-portal/​dev/​socialMedia.ts Updated as part of this pull request.
site-config/​data-portal/​dev/​navigation/​privacy.ts Updated as part of this pull request.
site-config/​data-portal/​dev/​navigation/​metadata.ts Updated as part of this pull request.
site-config/​data-portal/​dev/​navigation/​help.ts Updated as part of this pull request.
site-config/​data-portal/​dev/​navigation/​guides.ts Updated as part of this pull request.
site-config/​data-portal/​dev/​navigation/​dcpUpdates.ts Updated as part of this pull request.
site-config/​data-portal/​dev/​navigation/​contribute.ts Updated as part of this pull request.
site-config/​data-portal/​dev/​navigation/​contact.ts Updated as part of this pull request.
site-config/​data-portal/​dev/​navigation/​apis.ts Updated as part of this pull request.
site-config/​data-portal/​dev/​navigation/​about.ts Updated as part of this pull request.
site-config/​data-portal/​dev/​layout/​floating.ts Updated as part of this pull request.
site-config/​data-portal/​dev/​config.tsx Updated as part of this pull request.
site-config/​data-portal/​dev/​common/​utils.ts Updated as part of this pull request.
scripts/​complete-biccn-publications.ts Updated as part of this pull request.
scripts/​codemod-path-alias.ts Updated as part of this pull request.
pages/​search/​index.tsx Updated as part of this pull request.
pages/​metadata/​[dictionary]/​index.tsx Updated as part of this pull request.
pages/​index.tsx Updated as part of this pull request.
pages/​hca-bio-networks/​index.tsx Updated as part of this pull request.
pages/​hca-bio-networks/​[network]/​publications.tsx Updated as part of this pull request.
pages/​hca-bio-networks/​[network]/​index.tsx Updated as part of this pull request.
pages/​hca-bio-networks/​[network]/​atlases/​[atlas]/​source-datasets.tsx Updated as part of this pull request.
pages/​hca-bio-networks/​[network]/​atlases/​[atlas]/​index.tsx Updated as part of this pull request.
pages/​hca-bio-networks/​[network]/​atlases/​[atlas]/​datasets.tsx Updated as part of this pull request.
pages/​[...slug].tsx Updated as part of this pull request.
pages/​_app.tsx Updated as part of this pull request.
package.json Updated as part of this pull request.
hooks/​useSiteConfig.tsx Updated as part of this pull request.
hooks/​useNetworkList.ts Updated as part of this pull request.
eslint.config.mjs Updated as part of this pull request.
docs/​common/​utils.ts Updated as part of this pull request.
docs/​common/​constants.ts Updated as part of this pull request.
contexts/​networkContext.ts Updated as part of this pull request.
contexts/​atlasContext.ts Updated as part of this pull request.
constants/​networks.ts Updated as part of this pull request.
constants/​datasets.ts Updated as part of this pull request.
constants/​componentAtlases.ts Updated as part of this pull request.
constants/​biccn-publications.json.d.ts Updated as part of this pull request.
constants/​analysisPortals.ts Updated as part of this pull request.
config/​config.ts Updated as part of this pull request.
components/​Layout/​components/​Content/​components/​Link/​link.tsx Updated as part of this pull request.
components/​Home/​components/​SectionStayUpToDate/​sectionStayUpToDate.tsx Updated as part of this pull request.
components/​Home/​components/​SectionStayUpToDate/​sectionStayUpToDate.styles.ts Updated as part of this pull request.
components/​Home/​components/​SectionHero/​sectionHero.tsx Updated as part of this pull request.
components/​Home/​components/​SectionHero/​components/​SummaryCounts/​summaryCounts.tsx Updated as part of this pull request.
components/​Home/​components/​SectionBioNetworkAtlases/​sectionBioNetworkAtlases.tsx Updated as part of this pull request.
components/​HCABioNetworks/​Network/​components/​Publications/​components/​MainColumn/​mainColumn.tsx Updated as part of this pull request.
components/​HCABioNetworks/​Network/​components/​Publications/​components/​MainColumn/​components/​Publication/​publication.tsx Updated as part of this pull request.
components/​HCABioNetworks/​Network/​components/​Overview/​components/​SideColumn/​sideColumn.tsx Updated as part of this pull request.
components/​HCABioNetworks/​Network/​components/​Overview/​components/​MainColumn/​mainColumn.tsx Updated as part of this pull request.
components/​HCABioNetworks/​Network/​components/​Overview/​components/​MainColumn/​constants.ts Updated as part of this pull request.
components/​HCABioNetworks/​Network/​components/​Overview/​components/​MainColumn/​components/​NetworkAtlasesEmpty/​networkAtlasesEmpty.tsx Updated as part of this pull request.
components/​HCABioNetworks/​Network/​components/​common/​Tabs/​tabs.tsx Updated as part of this pull request.
components/​HCABioNetworks/​Network/​components/​common/​Hero/​hero.tsx Updated as part of this pull request.
components/​HCABioNetworks/​Network/​Atlas/​components/​SourceDatasets/​components/​MainColumn/​types.ts Updated as part of this pull request.
components/​HCABioNetworks/​Network/​Atlas/​components/​SourceDatasets/​components/​MainColumn/​sourceDatasets.tsx Updated as part of this pull request.
components/​HCABioNetworks/​Network/​Atlas/​components/​SourceDatasets/​components/​MainColumn/​mainColumn.tsx Updated as part of this pull request.
components/​HCABioNetworks/​Network/​Atlas/​components/​SourceDatasets/​components/​MainColumn/​components/​table/​viewBuilder.tsx Updated as part of this pull request.
components/​HCABioNetworks/​Network/​Atlas/​components/​SourceDatasets/​components/​MainColumn/​components/​table/​utils.ts Updated as part of this pull request.
components/​HCABioNetworks/​Network/​Atlas/​components/​SourceDatasets/​components/​MainColumn/​components/​table/​meta.ts Updated as part of this pull request.
components/​HCABioNetworks/​Network/​Atlas/​components/​SourceDatasets/​components/​MainColumn/​components/​table/​hook.ts Updated as part of this pull request.
components/​HCABioNetworks/​Network/​Atlas/​components/​SourceDatasets/​components/​MainColumn/​components/​table/​components/​FileNameCell/​types.ts Updated as part of this pull request.
components/​HCABioNetworks/​Network/​Atlas/​components/​SourceDatasets/​components/​MainColumn/​components/​table/​components/​FileNameCell/​fileNameCell.tsx Updated as part of this pull request.
components/​HCABioNetworks/​Network/​Atlas/​components/​SourceDatasets/​components/​MainColumn/​components/​table/​components/​FileNameCell/​components/​Citation/​citation.tsx Updated as part of this pull request.
components/​HCABioNetworks/​Network/​Atlas/​components/​SourceDatasets/​components/​MainColumn/​components/​table/​columns.ts Updated as part of this pull request.
components/​HCABioNetworks/​Network/​Atlas/​components/​SourceDatasets/​components/​MainColumn/​components/​table/​accessor.ts Updated as part of this pull request.
components/​HCABioNetworks/​Network/​Atlas/​components/​Overview/​components/​SideColumn/​utils.ts Updated as part of this pull request.
components/​HCABioNetworks/​Network/​Atlas/​components/​Overview/​components/​SideColumn/​sideColumn.tsx Updated as part of this pull request.
components/​HCABioNetworks/​Network/​Atlas/​components/​Overview/​components/​MainColumn/​utils.ts Updated as part of this pull request.
components/​HCABioNetworks/​Network/​Atlas/​components/​Overview/​components/​MainColumn/​mainColumn.tsx Updated as part of this pull request.
components/​HCABioNetworks/​Network/​Atlas/​components/​Overview/​components/​MainColumn/​constants.ts Updated as part of this pull request.
components/​HCABioNetworks/​Network/​Atlas/​components/​Overview/​components/​MainColumn/​components/​AnalysisPortalCell/​analysisPortalCell.tsx Updated as part of this pull request.
components/​HCABioNetworks/​Network/​Atlas/​components/​Datasets/​components/​MainColumn/​projects/​components/​Table/​options.ts Updated as part of this pull request.
components/​HCABioNetworks/​Network/​Atlas/​components/​Datasets/​components/​MainColumn/​mainColumn.tsx Updated as part of this pull request.
components/​HCABioNetworks/​Network/​Atlas/​components/​common/​Tabs/​tabs.tsx Updated as part of this pull request.
components/​HCABioNetworks/​Network/​Atlas/​components/​common/​Hero/​hero.tsx Updated as part of this pull request.
components/​HCABioNetworks/​components/​Index/​components/​MainColumn/​mainColumn.tsx Updated as part of this pull request.
components/​HCABioNetworks/​components/​Index/​components/​MainColumn/​constants.ts Updated as part of this pull request.
components/​DataDictionary/​components/​TableCell/​utils.ts Updated as part of this pull request.
components/​DataDictionary/​components/​TableCell/​components/​FieldCell/​utils.ts Updated as part of this pull request.
components/​DataDictionary/​components/​TableCell/​components/​FieldCell/​fieldCell.tsx Updated as part of this pull request.
components/​DataDictionary/​components/​TableCell/​components/​FieldCell/​constants.ts Updated as part of this pull request.
components/​DataDictionary/​components/​TableCell/​components/​DetailCell/​utils.ts Updated as part of this pull request.
components/​DataDictionary/​components/​TableCell/​components/​DetailCell/​detailCell.tsx Updated as part of this pull request.
components/​common/​Table/​components/​Cell/​components/​TrackerDownloadCell/​trackerDownloadCell.tsx Updated as part of this pull request.
components/​common/​Table/​components/​Cell/​components/​TrackerDownloadCell/​components/​Dialog/​dialog.tsx Updated as part of this pull request.
components/​common/​Table/​components/​Cell/​components/​PinnedNTagCell/​utils.tsx Updated as part of this pull request.
components/​common/​Table/​components/​Cell/​components/​CXGDownloadCell/​cxgDownloadCell.tsx Updated as part of this pull request.
components/​common/​Table/​components/​Cell/​components/​CXGDownloadCell/​components/​CXGDownloadDialogForm/​cxgDownloadDialogForm.tsx Updated as part of this pull request.
components/​common/​Table/​components/​Cell/​components/​CXGDownloadCell/​components/​CXGDownloadDialogForm/​components/​CXGDownloadRadio/​cxgDownloadRadio.tsx Updated as part of this pull request.
components/​common/​Table/​components/​Cell/​components/​CXGDownloadCell/​components/​CXGDownloadDialogForm/​components/​CXGDownloadFileSize/​cxgDownloadFileSize.tsx Updated as part of this pull request.
components/​common/​Table/​components/​Cell/​components/​CXGDownloadCell/​components/​CXGDownloadDialog/​cxgDownloadDialog.tsx Updated as part of this pull request.
components/​common/​Table/​components/​Cell/​components/​BioNetworkCell/​bioNetworkCell.tsx Updated as part of this pull request.
components/​common/​Section/​components/​References/​references.tsx Updated as part of this pull request.
components/​common/​Section/​components/​Publications/​publications.tsx Updated as part of this pull request.
components/​common/​Section/​components/​HCABiologicalNetwork/​HCABiologicalNetwork.tsx Updated as part of this pull request.
components/​common/​Section/​components/​HCABiologicalNetwork/​HCABiologicalNetwork.styles.ts Updated as part of this pull request.
components/​common/​Section/​components/​Coordinators/​coordinators.tsx Updated as part of this pull request.
components/​common/​IconLink/​iconLink.tsx Updated as part of this pull request.
components/​common/​Hero/​components/​Title/​components/​HeroTitle/​heroTitle.tsx Updated as part of this pull request.
components/​common/​Filters/​components/​ColumnFilterTags/​columnFilterTags.tsx Updated as part of this pull request.
components/​common/​Filters/​components/​ColumnFilters/​columnFilters.tsx Updated as part of this pull request.
components/​About/​components/​Attributions/​attributions.tsx Updated as part of this pull request.
apis/​tracker/​api.ts Updated as part of this pull request.

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Comment thread scripts/codemod-path-alias.ts Outdated
Comment thread eslint.config.mjs Outdated
…ngs (#3210)

skip scoped packages so `@types/node` is never rewritten, normalise
`./../` traversal in the codemod, and cover `..`, `./..` and `import type`
in the lint rule via the typescript-eslint variant.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01AsKeyxfv4ZT3FdQaqtGBdV

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot review overview

🟡 Changes recommended

The ESLint rule and codemod leave gaps for nested traversal and exact top-level bare imports.

Get a fresh assessment by requesting another Copilot review.

Review effort: Lite
Findings: 1 Medium severity

Open (1)
Resolved since last review (2)
Previously missed (2)

In code that hasn't changed since last review

Medium severity Top-level barrel imports bypass alias deny list

eslint.config.mjs:134

The bare-path deny list contains only directory/*, so a direct top-level barrel import such as from "components" is not restricted even though components/index.tsx is a valid baseUrl resolution. This leaves the new alias convention unenforced for exact top-level module names; include the exact names (or use one pattern covering both the name and its subpaths).

Low severity Codemod misses exact top-level barrel imports

scripts/​codemod-path-alias.ts:83

The rest.length > 0 guard leaves a valid baseUrl import such as from "components" unchanged, even though it resolves to the root barrel at components/index.tsx. That means the codemod does not cover all baseUrl-relative imports; rewrite exact top-level directory names as well as their subpaths.

Comment thread eslint.config.mjs Outdated
nested traversal such as `./components/../../../constants/routes` slipped
past patterns anchored to the start of the specifier.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01AsKeyxfv4ZT3FdQaqtGBdV

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot review overview

🔵 Needs a closer look

Bare components and content imports remain outside codemod and ESLint enforcement.

Review effort: Lite
Findings: None

Resolved since last review (1)
Previously missed (2)

In code that hasn't changed since last review

Medium severity Reject bare root imports for components and content

eslint.config.mjs:119

These patterns only cover descendants such as components/foo; they do not reject the valid bare root imports components and content, which resolve through components/index.tsx and content/index.tsx. A new import using either form would bypass the @/ convention, so add exact-root patterns as well as the wildcard patterns.

Medium severity Rewrite bare root imports to the @​/ alias

scripts/​codemod-path-alias.ts:83

The rest.length > 0 guard leaves valid bare root imports such as components and content unchanged. Both directories have an index.tsx, so baseUrl: "." resolves these specifiers; the codemod therefore does not convert every bare baseUrl import to the required @/ form. Rewrite known top-level directory specifiers even when there is no slash (or distinguish packages from directories by checking their entrypoint).

…x file (#3210)

`components`, `content` and `pages` resolve bare through their index.tsx
under `baseUrl: "."`. the lint rule now lists them as anchored exact
patterns and the codemod rewrites them when an index file exists.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01AsKeyxfv4ZT3FdQaqtGBdV
@frano-m

frano-m commented Sep 23, 2026

Copy link
Copy Markdown
Contributor Author

see above

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot review overview

🔵 Needs a closer look

The codemod does not rewrite .. imports, leaving an unresolved lint-conformance issue.

Review effort: Lite
Findings: None

@NoopDog NoopDog left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Review of the @/ alias change. I found no correctness problems in the rewritten imports. The comments below cover gaps in the lint rule's coverage and some cleanups in the codemod. I couldn't run ESLint locally (wrong Node version), so the rule-coverage points come from reading typescript-eslint's documented behaviour, not from lint runs.

Comment thread eslint.config.mjs Outdated
Comment thread tsconfig.json Outdated
Comment thread tsconfig.json Outdated
Comment thread eslint.config.mjs Outdated
Comment thread scripts/codemod-path-alias.ts Outdated
Comment thread scripts/codemod-path-alias.ts Outdated
Comment thread scripts/codemod-path-alias.ts Outdated
Comment thread scripts/codemod-path-alias.ts Outdated
…the @ alias (#3210)

without baseurl every bare root path is a compile error, so the eslint
bare list goes. the images/* alias was dead. no-restricted-syntax now
catches `..` in dynamic import() and require(), and the rule covers js
files. the one-off codemod is removed; it stays in this pr's history.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01AsKeyxfv4ZT3FdQaqtGBdV
@NoopDog

NoopDog commented Sep 24, 2026

Copy link
Copy Markdown
Collaborator

I reviewed head d0f19986 and found no correctness bugs. tsc --noEmit passes, no old-style imports are left (../, bare-root, images/*, @types), and the new rule catches ../ in static and dynamic imports, export … from, export * and require().

Please fix

  • The PR description is out of date. It still describes scripts/codemod-path-alias.ts, npm run codemod:path-alias, a rule banning bare root imports and a two-commit layout. d0f19986 removed all of these.

Gaps in the lint rule

  1. Template-literal imports get past it (eslint.config.mjs:123). The selectors only match a plain string, so import(`../constants/${name}`) and require(`../x`) go unflagged. I confirmed this with a test file. This one is cheap to close.
  2. MDX isn't linted (eslint.config.mjs:101). .mdx content can contain imports, and import X from "../../components/Foo" in a description.mdx wouldn't be caught.
  3. An npm package could silently take over a bare import (eslint.config.mjs:97). The comment says bare root imports fail to compile, but that only holds while no npm package shares a top-level folder name (config, utils, constants, common, types). Such a package would win silently, and the last commit removed the rule that would have caught this.

Items 2 and 3 may be fine to leave, as long as that's a deliberate choice.

Nits

  • The .. regex appears in two selectors and overlaps the glob patterns at line 111. It could be one constant next to RELATIVE_IMPORT_MESSAGE.
  • The new block repeats the files glob from the block above. A block with no files already applies to every linted file.

…lve parent imports (#3210)

share one parent-segment regex between the static and dynamic import checks,
drop the redundant files glob, and document why bare root imports are unguarded.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
@frano-m

frano-m commented Sep 28, 2026

Copy link
Copy Markdown
Contributor Author

Thanks. Addressed in 0bbd18de:

Please fix

  • PR description: rewritten to match the current branch. It no longer mentions the codemod, npm run codemod:path-alias, the bare-import rule or the two-commit layout.

Gaps in the lint rule

  1. Template-literal imports: fixed. Each static chunk of a template literal is now checked, so import(`../constants/${name}`) and require(`../x`) are flagged. While there I also closed three similar gaps: concatenated specifiers (import("../x/" + y)), require.resolve("../x") / require.context("../x"), and typeof import("../x") types.
  2. MDX: left as is, on purpose. Every .mdx file is compiled at runtime by next-mdx-remote serialize(), which can't resolve imports; components come in through the components prop. No .mdx file has an import or export today, and none sit under pages/, which is the only place @next/mdx would compile them.
  3. npm package taking over a bare import: left as is, on purpose. I checked, and no installed package matches any of our top-level folder names today. A guard would mean keeping a list of top-level folders up to date by hand, which is why the earlier rule was dropped. The eslint comment now states this case and says it is deliberately unguarded.

Nits

  • The .. regex is now one constant, PARENT_SEGMENT_PATTERN, next to RELATIVE_IMPORT_MESSAGE. The static-import rule uses it through its regex option, replacing the overlapping globs, and so do the dynamic-import selectors.
  • Removed the repeated files glob. I confirmed the rule still applies to .ts, .tsx, .js, .jsx, .mjs, .cjs and .styles.ts.

I tested the rule on a sample file: every parent-import form above is flagged, while ./x, @/x, ..foo, import(`./x/${y}`) and typeof import("./x") are not. Lint (0 errors), prettier, tsc --noEmit and build-dev:data-portal pass.

@NoopDog NoopDog left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Approving with feedback. I checked all 357 rewritten specifiers across 129 files and each resolves to the same file as before. tsc --noEmit passes and eslint . gives 0 errors and 8 warnings, matching the description. scripts/ still resolves @/ via esrun's esbuild.

The inline comments are all minor and about the new lint rule in eslint.config.mjs: false positives on non-specifier .. strings, a comment that overstates concatenation coverage, and flat-config override behavior worth guarding against. None of them block merging.

Comment thread eslint.config.mjs Outdated
Comment thread eslint.config.mjs Outdated
Comment thread eslint.config.mjs
replace the no-restricted-syntax selectors with a custom rule that joins the
static text of the specifier argument, so strings elsewhere in the call are
ignored and concatenated specifiers are caught. note that the block must stay
last for no-restricted-imports.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
@frano-m
frano-m merged commit 19bc93f into main Sep 29, 2026
1 check passed
@frano-m
frano-m deleted the fran/3210-path-alias branch September 29, 2026 06:48
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

refactor: introduce an @ path alias to replace deep relative imports, and enforce it with eslint

3 participants