fix(readPackage): implement try option#263
Conversation
Closes unjs#257 - Updated `readPackage` to accept a generic `Opts` to inherit the `try` boolean from `exsolve`. - Wrapped the `findPackage` and file reading logic in a try-catch block. - When an error is thrown and `try: true` is provided, it catches the error and returns `undefined` instead of throwing.
|
Note Reviews pausedIt looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the Use the following commands to manage reviews:
Use the checkboxes below for quick actions:
📝 WalkthroughWalkthroughreadPackage gains a Changes
Sequence Diagram(s)sequenceDiagram
participant Client
participant readPackage
participant Resolver
participant Cache
participant FS
participant Parser
Client->>readPackage: call(id, options)
readPackage->>Resolver: resolve path (guarded)
alt resolve error & options.try == true
Resolver-->>readPackage: error
readPackage-->>Client: return undefined
else
Resolver-->>readPackage: resolved path
readPackage->>Cache: check cached entry (guarded)
alt cache hit
Cache-->>readPackage: cached package
readPackage-->>Client: return package
else
readPackage->>FS: read file (try/catch)
alt read/parsing error & options.try == true
FS-->>readPackage: error
readPackage-->>Client: return undefined
else
FS-->>readPackage: file content
readPackage->>Parser: parse to PackageJson
Parser-->>readPackage: package object
readPackage->>Cache: store
readPackage-->>Client: return package
end
end
end
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~20 minutes Poem
🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches🧪 Generate unit tests (beta)
Tip 💬 Introducing Slack Agent: The best way for teams to turn conversations into code.Slack Agent is built on CodeRabbit's deep understanding of your code, so your team can collaborate across the entire SDLC without losing context.
Built for teams:
One agent for your entire SDLC. Right inside Slack. Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Actionable comments posted: 2
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In `@src/packagejson/utils.ts`:
- Around line 76-104: The current try/catch around findPackage, fsp.readFile and
the parsing logic hides parser errors when options.try is true; refactor so the
try only wraps findPackage(id, options) and the readFile(resolvedPath) call
(i.e., resolve/read failures), then perform parsing (using
parseJSON5/parseYAML/parseJSON/parseJSONC) outside that try so parse errors
propagate; keep the cache logic (cache.has, cache.get, cache.set) around
resolution/read and parsing as appropriate, and still return undefined when
options.try is set only for resolve/read failures while letting malformed
JSON/YAML/JSONC throw normally.
- Around line 72-75: The return-type conditional for readPackage is unsound
because callers can pass a runtime options.try boolean but ResolveOptions and
ReadOptions do not declare try, and the generic conditional only narrows for
literal true; update the option typing so options.try is known: add an optional
try?: boolean property to the shared option type(s) (or create overloads for
readPackage that accept { try: true } and { try?: false | undefined }) so that
the signature of readPackage (and the referenced ResolveOptions & ReadOptions)
correctly reflects that passing try at runtime yields Promise<PackageJson |
undefined> when truthy and Promise<PackageJson> otherwise; reference:
readPackage, ResolveOptions, ReadOptions, and the options.try access around line
100.
- Expose `try?: boolean` in ReadOptions - Narrow generic types based on `Opts["try"]`, not just literal `true` - Scope `try` option solely to resolve/read failures, and let parsing errors propagate
There was a problem hiding this comment.
Actionable comments posted: 2
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In `@src/packagejson/utils.ts`:
- Around line 72-75: The conditional return type on readPackage using "true
extends Opts['try']" causes Opts["try"] to widen to boolean|undefined and
incorrectly makes the return type PackageJson|undefined for normal calls; change
the typing to overloads or tighten the Opts generic so non-try calls return
Promise<PackageJson>. Concretely, replace the single generic signature of
readPackage<Opts extends ResolveOptions & ReadOptions> with two overloads (one
where Opts extends { try: true } returning Promise<PackageJson|undefined> and
one where Opts does not include try returning Promise<PackageJson>), or
constrain the generic like Opts extends ResolveOptions & ReadOptions & ({ try?:
never } | { try: true }) so callers using readPackage(...) without try get
Promise<PackageJson> while calls with try: true get the optional result; update
the implementation signature to match the overloads.
In `@src/resolve/types.ts`:
- Around line 25-29: The shared ReadOptions.try flag is documented as applying
to all readers but only honored in readPackage; either implement the try
behavior in the other consumers (readTSConfig, readPackageJSON, updatePackage)
so they catch parse/read errors and return undefined when opts.try is true, or
remove try from the shared type and add a function-specific option (e.g.,
ReadTSConfigOptions.try, ReadPackageJSONOptions.try) to avoid misleading
callers; locate the usages in the readTSConfig, readPackageJSON, and
updatePackage functions and modify their error handling to mirror readPackage's
try logic or adjust the type definitions accordingly.
ℹ️ Review info
⚙️ Run configuration
Configuration used: defaults
Review profile: CHILL
Plan: Pro
Run ID: 97c44527-2731-4149-bc6c-f132da2cbcb8
📒 Files selected for processing (3)
src/packagejson/utils.tssrc/resolve/types.tstest/index.test.ts
|
I've updated the PR to address the CodeRabbit feedback. The |
There was a problem hiding this comment.
♻️ Duplicate comments (1)
src/packagejson/utils.ts (1)
77-84:⚠️ Potential issue | 🟠 Major
try: trueoverload should requireoptions(and add a boolean fallback overload).Line 79 currently makes the
try: trueoverload callable withoutoptions, which can still widen common calls likereadPackage(). Also, callers withtry: booleanhave no explicit overload path today.Suggested overload shape
export async function readPackage( - id?: string, - options?: ReadPackageOptions & { try: true }, + id: string | undefined, + options: ReadPackageOptions & { try: true }, ): Promise<PackageJson | undefined>; export async function readPackage( id?: string, options?: ReadPackageOptions & { try?: false | undefined }, ): Promise<PackageJson>; +export async function readPackage( + id?: string, + options?: ReadPackageOptions, +): Promise<PackageJson | undefined>;🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@src/packagejson/utils.ts` around lines 77 - 84, The overloads for readPackage are too permissive: the overload with { try: true } must require the options parameter (so callers can't call readPackage() and inadvertently match the optional-try overload), and you should add a boolean-fallback overload to handle callers passing a runtime try: boolean. Update the readPackage overloads so the { try: true } variant takes options: ReadPackageOptions & { try: true } (non-optional) and add an overload for options?: ReadPackageOptions & { try?: boolean } that returns Promise<PackageJson | undefined>, keeping the existing { try?: false } overload returning Promise<PackageJson>; reference the readPackage function signatures to locate and change the overloads.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Duplicate comments:
In `@src/packagejson/utils.ts`:
- Around line 77-84: The overloads for readPackage are too permissive: the
overload with { try: true } must require the options parameter (so callers can't
call readPackage() and inadvertently match the optional-try overload), and you
should add a boolean-fallback overload to handle callers passing a runtime try:
boolean. Update the readPackage overloads so the { try: true } variant takes
options: ReadPackageOptions & { try: true } (non-optional) and add an overload
for options?: ReadPackageOptions & { try?: boolean } that returns
Promise<PackageJson | undefined>, keeping the existing { try?: false } overload
returning Promise<PackageJson>; reference the readPackage function signatures to
locate and change the overloads.
|
I've added the additional boolean-fallback overload to |
There was a problem hiding this comment.
Actionable comments posted: 1
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In `@src/packagejson/utils.ts`:
- Around line 283-286: The call to readPackage in updatePackage currently uses a
type assertion to force { try: false } but may still receive { try: true } at
runtime, causing pkg to be undefined; update the call inside updatePackage to
pass an explicit options object with try: false (e.g., pass {...options, try:
false}) to guarantee runtime behavior, remove the subsequent guard that handles
pkg being undefined (the throw referencing resolvedPath) if updatePackage is
intended to be strict, and ensure the reference to pkg and resolvedPath remain
correct after this change.
|
I've updated the PR again to address the latest CodeRabbit feedback!
|
There was a problem hiding this comment.
Actionable comments posted: 1
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In `@src/packagejson/utils.ts`:
- Around line 72-75: Update the JSDoc for the readPackage function to reference
ReadPackageOptions (not ResolveOptions) and to document the new behavior:
explain that the options parameter accepts ReadPackageOptions and that the
return may be undefined when options.try is true; also adjust the `@returns`
description to state it "resolves to the parsed package object or undefined if
options.try is true" and mention supported file formats (package.json,
package.json5, package.yaml) and the id defaulting to cwd to match the function
signature.
|
I've updated the JSDoc for |
|
@pi0 I've addressed the feedback from CodeRabbit (updated the type signatures, overloads, and added documentation for the option) and the checks are passing. Could you please take a look when you have a moment? Let me know if you need anything else! |
|
Hi @pi0, I've addressed all the feedback from CodeRabbit (updated type signatures, overloads, and added tests). Ready for review. Thanks! |
Summary
Implements the
tryoption inside thereadPackageutility, which suppresses exceptions and returnsundefinedwhen set totrue.Problem
Closes #257
resolves nuxt/cli#1179
Currently,
readPackageinherits thetryoption viaexsolve'sResolveOptions, but the boolean is completely ignored inpkg-types, causing errors to be thrown unexpectedly.Solution
readPackagesignature with a genericOptsto correctly type the conditional return valuePackageJson | undefined.try-catchblock.undefinedifoptions.tryis truthy.Checklist
vitest runtests pass successfullySummary by CodeRabbit
New Features
Improvements
Tests