feat(shadcn/registry): add safe ENOENT stat
handling | handle fallback case for non-file paths | #5
#8396
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.
PR: Improve Registry Path Handling in Monorepo Environments
🛠️ Changes Summary
utils.ts
add
Pick<RegistryItem, "files" | "dependencies">
to replacePick<z.infer<typeof registryItemSchema>, "files" | "dependencies">
add
removeFiles?: string[]
as a return type inrecursivelyResolveFileImports
add
const stat = await getStatsOrNonFile(resolvedFilePath)
to replaceconst stat = await fs.stat(resolvedFilePath)
add fallback logic into handle case under
if (!stat.isFile()) {
and return{ dependencies: [], files: [originalFile], removeFiles: [filePath] }
build.ts
resolveRegistryItems
to remove files fromregistry.items
whose paths are listed inresults.removeFiles
.Reason
existing
RegistryItem = z.infer<typeof registryItemSchema>
is already in theregistry/schema
.removing unresolvable file path from registry item before it catches in
Error reading file in registry build:
since new resolved file path is added as a replacement for it.getStatsOrNonFile
suppressesENOENT: no such file or directory, stat
and avoid crash, so that flow could try to get an alternative path.aliases like
@/components/somewhere/some-thing.tsx
usually fails here. so it could try to get an alternative path by usingtryAlternativePath
which leveragestsconfig-paths
. it will resolve the first correct matching file path.since alternative path is added, remaining
failed
file path
is added toremoveFiles
to get removed fromregistry.items
PR roadmap introduces several refactors and new utility functions to improve how the
shadcn registry:build
CLI handles failed aliased import paths, especially in monorepo setups using path aliases (e.g.@/components/...
).🐛 Problem
In monorepos, adding a registry component like:
...and running:
Would fail with:
fs.stat()
is called before the alias is resolved bytsconfig-paths
, causing the CLI to crash ungracefully.💡 Why This Happens
In a monorepo, files from multiple workspaces may be referenced using aliases (
@
,@ui
, etc.). If these aliases aren't fully resolved to disk paths, the CLI crashes when trying to access them directly viafs.stat
.The current logic fails here:
When
fs.stat()
is called on an invalid or unresolved path, it throws anENOENT
error, causing the CLI to crash ungracefully.🧭 Roadmap
part of a multi step effort to enable the registry CLI to handle path aliases gracefully in monorepo environments.
determineFileType()
to its own file (utils/registry/determine-file-type.ts
) 🚀 (awaiting merge refactor(registry/utils): movedetermineFileType
todetermine-file-type.ts
| #1 #8299)createRegistryFile()
util for creating registry file shape 🚀 (awaiting merge refactor(registry/utils): replace inline original file creation withcreateRegistryFile
utility | #2 #8313)getStatsOrNonFile()
to gracefully suppress ENOENT errors 🚀 (awaiting merge refactor(shadcn/registry): addgetStatsOrNonFile
util with graceful fallback onENOENT
| #3 #8373)re
tryAlternativePath()
to retry common alias misresolves 🚀 (awaiting merge refactor(shadcn/registry): addtryAlternativePath
|resolvePathWithOptions
util to resolve an alt path to a failed path | #4 #8389)!stat.isFile()
and handle returned suppressed files in registry build command'sresolveRegistryItems
✅ (this PR)Each change is isolated for clean diffs.
🧱 Directory Structure (for Context)
my monorepo structure to understand the issue:
tsconfig.json
📚 Notes
tsconfig-paths
is used, but currentfs.stat()
happens before alias resolution in some cases.🔗 Follow-Ups
"first-match"
,"last-match"
,"manual"
via customtsconfig
extension.