Thanks to visit codestin.com
Credit goes to github.com

Skip to content

fix(readPackage): implement try option#263

Open
Sigmabrogz wants to merge 6 commits into
unjs:mainfrom
Sigmabrogz:fix/readpackage-try-option
Open

fix(readPackage): implement try option#263
Sigmabrogz wants to merge 6 commits into
unjs:mainfrom
Sigmabrogz:fix/readpackage-try-option

Conversation

@Sigmabrogz
Copy link
Copy Markdown

@Sigmabrogz Sigmabrogz commented Mar 11, 2026

Summary

Implements the try option inside the readPackage utility, which suppresses exceptions and returns undefined when set to true.

Problem

Closes #257
resolves nuxt/cli#1179
Currently, readPackage inherits the try option via exsolve's ResolveOptions, but the boolean is completely ignored in pkg-types, causing errors to be thrown unexpectedly.

Solution

  • Refactored readPackage signature with a generic Opts to correctly type the conditional return value PackageJson | undefined.
  • Wrapped the implementation in a try-catch block.
  • Catches errors and returns undefined if options.try is truthy.
  • Handled TypeScript constraints effectively.

Checklist

  • Code builds without errors
  • vitest run tests pass successfully
  • Linting and typechecks pass

Summary by CodeRabbit

  • New Features

    • Optional "try mode" for reading package data: reads can return undefined instead of throwing.
  • Improvements

    • Update operation now enforces failure when package is missing or unparsable.
    • Stronger, safer handling and typing for package read/update flows.
  • Tests

    • Tests hardened to tolerate undefined package reads (use optional access when asserting fields).

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.
@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented Mar 11, 2026

Note

Reviews paused

It 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 reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review
📝 Walkthrough

Walkthrough

readPackage gains a try option with overloads; resolution, cache lookup, and file read/parsing are guarded to return undefined when try: true. updatePackage now calls readPackage in non-try mode and writes back updated package as PackageJson. Tests use optional chaining for safe assertions.

Changes

Cohort / File(s) Summary
Package read/write logic
src/packagejson/utils.ts
Added ReadPackageOptions = ResolveOptions & ReadOptions & { try?: boolean }; introduced readPackage overloads and implementation that guards resolve/cache/read/parse to return undefined when try: true. updatePackage calls readPackage with try: false, ensures top-level keys exist on proxy, and writes updated object cast to PackageJson.
Tests
test/index.test.ts
Replaced direct property accesses with optional chaining (e.g., package_?.name, package_?.version) to tolerate readPackage returning undefined in try mode.

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
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Poem

🐰 I slipped a gentle try into the lane,
So missing files dance off without a pain.
I peek, I parse, then quietly sigh,
If nothing's found, I let it be "undefined"—bye! 🥕

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 66.67% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title 'fix(readPackage): implement try option' directly describes the main change: implementing the try option in readPackage, which aligns with the primary objective.
Linked Issues check ✅ Passed The PR fully implements the required functionality: readPackage now catches resolve/read errors when try: true and returns undefined instead of throwing, with proper TypeScript overloads for conditional return types [#257].
Out of Scope Changes check ✅ Passed All changes are directly related to implementing the try option: readPackage refactored with overloads, try-catch error handling, and test assertions updated to handle undefined returns. No unrelated modifications detected.
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

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.

  • Generate code and open pull requests
  • Plan features and break down work
  • Investigate incidents and troubleshoot customer tickets together
  • Automate recurring tasks and respond to alerts with triggers
  • Summarize progress and report instantly

Built for teams:

  • Shared memory across your entire org—no repeating context
  • Per-thread sandboxes to safely plan and execute work
  • Governance built-in—scoped access, auditability, and budget controls

One agent for your entire SDLC. Right inside Slack.

👉 Get started


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.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

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.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 1d6ac90a-5176-44c2-9831-492e2b0e08e9

📥 Commits

Reviewing files that changed from the base of the PR and between 65402c6 and c0db2e8.

📒 Files selected for processing (1)
  • src/packagejson/utils.ts

Comment thread src/packagejson/utils.ts Outdated
Comment thread src/packagejson/utils.ts
- 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
Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

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

📥 Commits

Reviewing files that changed from the base of the PR and between c0db2e8 and cdc1881.

📒 Files selected for processing (3)
  • src/packagejson/utils.ts
  • src/resolve/types.ts
  • test/index.test.ts

Comment thread src/packagejson/utils.ts Outdated
Comment thread src/resolve/types.ts Outdated
@Sigmabrogz
Copy link
Copy Markdown
Author

I've updated the PR to address the CodeRabbit feedback. The try option is now removed from the shared ReadOptions type and correctly implemented via overloads on readPackage to prevent widening of options.try to boolean | undefined and to ensure proper return types. Also, parse errors throw normally as previously implemented.

Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

♻️ Duplicate comments (1)
src/packagejson/utils.ts (1)

77-84: ⚠️ Potential issue | 🟠 Major

try: true overload should require options (and add a boolean fallback overload).

Line 79 currently makes the try: true overload callable without options, which can still widen common calls like readPackage(). Also, callers with try: boolean have 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.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 54a09aa1-4232-4c54-bd1e-8cc221619341

📥 Commits

Reviewing files that changed from the base of the PR and between cdc1881 and 36801ef.

📒 Files selected for processing (1)
  • src/packagejson/utils.ts

@Sigmabrogz
Copy link
Copy Markdown
Author

I've added the additional boolean-fallback overload to readPackage and required the options parameter for the { try: true } overload to prevent widening as suggested.

Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

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.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 64e8cfc8-f2ce-4729-a6dc-37332921bea4

📥 Commits

Reviewing files that changed from the base of the PR and between 36801ef and 7ca8293.

📒 Files selected for processing (1)
  • src/packagejson/utils.ts

Comment thread src/packagejson/utils.ts Outdated
@Sigmabrogz
Copy link
Copy Markdown
Author

I've updated the PR again to address the latest CodeRabbit feedback!

  • Changed the 3rd readPackage overload to properly accept a generic ReadPackageOptions without { try?: boolean } so it cleanly acts as the fallback for runtime boolean while requiring options in the { try: true } overload.
  • Updated updatePackage to explicitly pass { ...options, try: false } to guarantee it never returns undefined, and removed the now-unnecessary null check on pkg.

Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

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.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 295dca7c-f29d-4aed-9514-67a4f067f341

📥 Commits

Reviewing files that changed from the base of the PR and between 7ca8293 and 2669860.

📒 Files selected for processing (1)
  • src/packagejson/utils.ts

Comment thread src/packagejson/utils.ts Outdated
@Sigmabrogz
Copy link
Copy Markdown
Author

Sigmabrogz commented Mar 13, 2026

I've updated the JSDoc for readPackage to reference ReadPackageOptions and document the try: true behavior where it returns undefined!

@Sigmabrogz
Copy link
Copy Markdown
Author

@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!

@Sigmabrogz
Copy link
Copy Markdown
Author

Hi @pi0, I've addressed all the feedback from CodeRabbit (updated type signatures, overloads, and added tests). Ready for review. Thanks!

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.

readPackage's try option is unimplemented Error when initializing nuxt app with arguments

1 participant