Skip to content

Conversation

@BobbieGoede
Copy link
Owner

@BobbieGoede BobbieGoede commented Jul 12, 2025

Summary by CodeRabbit

  • New Features

    • Introduced a new function to hoist TypeScript type declarations for specified dependencies in Nuxt projects.
    • Added a GitHub Actions workflow for preview releases triggered on pull requests with specific labels.
    • Added a script to switch Nuxt versions easily.
    • Added a Usage section in the documentation for the new hoisting utility.
  • Bug Fixes

    • Improved TypeScript configuration to ensure correct type resolution for hoisted dependencies.
  • Chores

    • Updated and reorganized dependencies in the package configuration.
    • Enhanced TypeScript and build configuration files for better compatibility.
    • Minor formatting and whitespace adjustments in documentation and workflow files.
    • Updated .gitignore to exclude environment variable files.
  • Refactor

    • Changed module exports to use named exports for improved clarity and usage.

@BobbieGoede BobbieGoede self-assigned this Jul 12, 2025
@coderabbitai
Copy link

coderabbitai bot commented Jul 12, 2025

✅ Actions performed

Review triggered.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

@coderabbitai
Copy link

coderabbitai bot commented Jul 12, 2025

Walkthrough

The changes introduce a new hoistDependencies utility for managing TypeScript type paths in Nuxt projects, update dependency declarations in package.json, and adjust configuration files for TypeScript and build tooling. Minor whitespace and formatting adjustments were made in documentation and workflow files. The module's public API now exports hoistDependencies instead of a default function. A new GitHub Actions workflow and a shell script for switching Nuxt versions were also added, and .env was added to .gitignore.

Changes

Files / Group Change Summary
.github/workflows/release.yml Changed tag pattern quotes from single to double; added newline at end of file.
.github/workflows/preview-release.yml Added new workflow for preview releases triggered on PRs and branch pushes with label-based conditional job run.
.gitignore Added .env to ignore list.
README.md Added Usage section for hoistDependencies with example; removed HTML comment and trailing blank lines.
package.json Added repository and bugs metadata; reorganized dependencies; added peer/runtime dependencies; updated devDependencies.
src/hoist.ts Added new module for hoisting TypeScript type declarations for Nuxt dependencies.
src/index.ts Removed default export; re-exported hoistDependencies as named export.
tsconfig.json Expanded lib array, added "@types/node" to types, reformatted include.
tsdown.config.ts Changed entry to ./src/index.ts, updated import/export formatting to use double quotes and added semicolon.
scripts/switch-nuxt.sh Added new shell script to switch Nuxt version via pnpm install.

Sequence Diagram(s)

sequenceDiagram
    participant User
    participant Nuxt
    participant hoistDependencies
    participant pkg-types
    participant exsolve

    User->>hoistDependencies: Call with (hoist: string[], nuxt?)
    hoistDependencies->>Nuxt: Get Nuxt context and rootDir
    hoistDependencies->>pkg-types: Read root package.json
    hoistDependencies->>hoistDependencies: Filter out already declared packages
    loop For each package to hoist
        hoistDependencies->>exsolve: Resolve type path for package
    end
    hoistDependencies->>Nuxt: Merge resolved paths into Nitro tsConfig
    hoistDependencies->>Nuxt: Hook into prepare:types to inject paths
Loading

Poem

A hop, a skip, a code refactor,
Dependencies now hoist much faster!
Types resolved with gentle care,
While configs sparkle everywhere.
The rabbit leaps with glee anew,
For Nuxt and TypeScript—cheers to you! 🐇✨

✨ Finishing Touches
  • 📝 Generate Docstrings

🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>, please review it.
    • Explain this complex logic.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query. Examples:
    • @coderabbitai explain this code block.
    • @coderabbitai modularize this function.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbitai read src/utils.ts and explain its main purpose.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.
    • @coderabbitai help me debug CodeRabbit configuration file.

Support

Need help? Create a ticket on our support page for assistance with any issues or questions.

Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments.

CodeRabbit Commands (Invoked using PR comments)

  • @coderabbitai pause to pause the reviews on a PR.
  • @coderabbitai resume to resume the paused reviews.
  • @coderabbitai review to trigger an incremental review. This is useful when automatic reviews are disabled for the repository.
  • @coderabbitai full review to do a full review from scratch and review all the files again.
  • @coderabbitai summary to regenerate the summary of the PR.
  • @coderabbitai generate docstrings to generate docstrings for this PR.
  • @coderabbitai generate sequence diagram to generate a sequence diagram of the changes in this PR.
  • @coderabbitai resolve resolve all the CodeRabbit review comments.
  • @coderabbitai configuration to show the current CodeRabbit configuration for the repository.
  • @coderabbitai help to get help.

Other keywords and placeholders

  • Add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai anywhere in the PR title to generate the title automatically.

CodeRabbit Configuration File (.coderabbit.yaml)

  • You can programmatically configure CodeRabbit by adding a .coderabbit.yaml file to the root of your repository.
  • Please see the configuration documentation for more information.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json

Documentation and Community

  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

Copy link

@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: 4

🧹 Nitpick comments (3)
src/hoist.ts (3)

15-34: Consider improving error handling specificity.

The function correctly handles the happy path and gracefully falls back to null on errors. However, the catch block silently swallows all errors, which might make debugging difficult.

Consider logging errors or being more specific about which errors to catch:

  } catch {
    return null;
  }

Could be improved to:

  } catch (error) {
    // Log for debugging purposes in development
    if (process.env.NODE_ENV === 'development') {
      console.debug(`Failed to resolve type path for ${path}:`, error);
    }
    return null;
  }

77-96: Consider documenting the side effects of configuration mutation.

The function modifies Nuxt configuration objects in place, which could have unexpected side effects. While this appears to be the intended behavior, it should be documented.

Add JSDoc comments to clarify the behavior:

/**
+ * Hoists TypeScript type declarations for specified dependencies by configuring
+ * path mappings in Nuxt and Nitro TypeScript configurations.
+ * 
+ * @param hoist - Array of package names to hoist
+ * @param nuxt - Nuxt instance (optional, uses current context if not provided)
+ * 
+ * @remarks This function modifies the Nuxt configuration in place by setting
+ * TypeScript path mappings for better type resolution when shamefully-hoist=false.
 */
export async function hoistDependencies(hoist: string[], nuxt = useNuxt()) {

78-80: Verify defu usage with spread operator.

The use of { ...paths } inside the defu merge might not be necessary since paths is already an object. This could lead to unnecessary object creation.

Consider simplifying the defu usage:

  nuxt.options.nitro.typescript = defu(nuxt.options.nitro.typescript, {
-    tsConfig: { compilerOptions: { paths: { ...paths } } },
+    tsConfig: { compilerOptions: { paths } },
  });

Apply the same pattern to lines 86, 90, and 94.

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between e0c5609 and ecae256.

⛔ Files ignored due to path filters (1)
  • pnpm-lock.yaml is excluded by !**/pnpm-lock.yaml
📒 Files selected for processing (7)
  • .github/workflows/release.yml (2 hunks)
  • README.md (0 hunks)
  • package.json (1 hunks)
  • src/hoist.ts (1 hunks)
  • src/index.ts (1 hunks)
  • tsconfig.json (2 hunks)
  • tsdown.config.ts (1 hunks)
💤 Files with no reviewable changes (1)
  • README.md
🔇 Additional comments (13)
.github/workflows/release.yml (2)

9-9: LGTM: Quote style standardization.

The change from single to double quotes for the tag pattern is a good formatting standardization and doesn't affect functionality.


25-26: LGTM: Added proper file ending.

Adding a newline at the end of the file follows good text file conventions.

tsconfig.json (3)

4-4: LGTM: Enhanced library support.

Adding "dom" and "esnext" to the lib array expands the available JavaScript APIs, which is appropriate for the new hoisting functionality.


9-9: LGTM: Node.js types support.

Adding "@types/node" to the types array aligns with the new devDependency declared in package.json and supports Node.js APIs used in the implementation.


18-18: LGTM: Clean include configuration.

The single-line format for the include array is cleaner and appropriately includes both source and test directories.

tsdown.config.ts (3)

1-1: LGTM: Quote style consistency.

Standardizing on double quotes improves consistency across the configuration file.


4-4: LGTM: Explicit entry point configuration.

Specifying the exact entry file ./src/index.ts is more explicit and aligns with the updated export structure.


5-6: LGTM: Improved formatting.

The formatting improvements with consistent quotes and trailing semicolon enhance code quality.

package.json (2)

37-37: LGTM: Node.js types support.

Adding @types/node as a devDependency aligns with the TypeScript configuration updates and provides proper type support for Node.js APIs.


42-45: LGTM: Proper peer dependency configuration for Nuxt module.

Moving @nuxt/kit and adding @nuxt/schema as peer dependencies is the correct approach for a Nuxt module. The version ranges support both Nuxt 3.16+ and Nuxt 4 RC, providing good compatibility.

src/hoist.ts (3)

1-9: LGTM! Clean and well-organized imports.

The imports are properly structured and include all necessary dependencies for the functionality implemented in this module.


44-48: LGTM! Robust dependency collection logic.

The regular expression correctly identifies nested packages, and the Set-based approach efficiently combines dependencies from both dependencies and devDependencies.


53-61: LGTM! Correct handling of scoped and nested packages.

The logic properly parses scoped packages and correctly skips packages that already exist in package.json dependencies.

Comment on lines +46 to 53
"dependencies": {
"defu": "^6.1.4",
"exsolve": "^1.0.7",
"magic-string": "^0.30.17",
"pathe": "^2.0.3",
"pkg-types": "^2.2.0",
"unplugin": "^2.3.5"
}
Copy link

Choose a reason for hiding this comment

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

💡 Verification agent

🧩 Analysis chain

Verify runtime dependencies are utilized.

The new runtime dependencies appear to support the hoistDependencies functionality, but let's verify they are actually used in the implementation.


🏁 Script executed:

#!/bin/bash
# Verify that all declared dependencies are actually used in the source code
echo "Checking usage of runtime dependencies:"

for dep in "defu" "exsolve" "magic-string" "pathe" "pkg-types" "unplugin"; do
  echo "=== Checking $dep ==="
  rg -l "from ['\"]$dep['\"]|require\(['\"]$dep['\"]" src/
done

Length of output: 1400


Unused runtime dependencies detected

The following packages are declared in package.json but not imported or required anywhere in src/hoist.ts (or elsewhere in src/):

  • magic-string
  • unplugin

Please either remove these entries from your dependencies or add the necessary import/use statements to your implementation.

🤖 Prompt for AI Agents
In package.json lines 46 to 53, the dependencies "magic-string" and "unplugin"
are declared but not used anywhere in the src/ directory, including
src/hoist.ts. To fix this, either remove these two packages from the
dependencies list if they are not needed, or add appropriate import statements
and usage of these packages in the source code where required.

Comment on lines 40 to 48
export async function hoistDependencies(hoist: string[], nuxt = useNuxt()) {
const packageJSON = await readPackageJSON(nuxt.options.rootDir).catch(
() => ({}) as PackageJson,
);
const NESTED_PKG_RE = /^[^@]+\//;
const dependencies = new Set([
...Object.keys(packageJSON.dependencies || {}),
...Object.keys(packageJSON.devDependencies || {}),
]);
Copy link

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

Improve error handling for package.json reading.

The current error handling hides all errors when reading package.json, which could mask important issues like permission problems or malformed JSON.

Consider being more specific about error handling:

  const packageJSON = await readPackageJSON(nuxt.options.rootDir).catch(
-    () => ({}) as PackageJson,
+    (error) => {
+      if (error.code === 'ENOENT') {
+        return {} as PackageJson;
+      }
+      throw error; // Re-throw other errors like permission issues or malformed JSON
+    },
  );
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
export async function hoistDependencies(hoist: string[], nuxt = useNuxt()) {
const packageJSON = await readPackageJSON(nuxt.options.rootDir).catch(
() => ({}) as PackageJson,
);
const NESTED_PKG_RE = /^[^@]+\//;
const dependencies = new Set([
...Object.keys(packageJSON.dependencies || {}),
...Object.keys(packageJSON.devDependencies || {}),
]);
export async function hoistDependencies(hoist: string[], nuxt = useNuxt()) {
const packageJSON = await readPackageJSON(nuxt.options.rootDir).catch(
(error) => {
if (error.code === 'ENOENT') {
return {} as PackageJson;
}
throw error; // Re-throw other errors like permission issues or malformed JSON
},
);
const NESTED_PKG_RE = /^[^@]+\//;
const dependencies = new Set([
...Object.keys(packageJSON.dependencies || {}),
...Object.keys(packageJSON.devDependencies || {}),
]);
}
🤖 Prompt for AI Agents
In src/hoist.ts around lines 40 to 48, the current catch block for reading
package.json suppresses all errors, potentially hiding critical issues. Modify
the error handling to catch only expected errors like file-not-found, and
rethrow or log unexpected errors such as permission issues or malformed JSON.
This can be done by checking the error type or code inside the catch block and
handling accordingly to avoid masking important problems.

Comment on lines 50 to 75
const paths = Object.fromEntries(
await Promise.all(
hoist.map(async (pkg) => {
const [_pkg = pkg, _subpath] = NESTED_PKG_RE.test(pkg)
? pkg.split("/")
: [pkg];
const subpath = _subpath ? "/" + _subpath : "";

// ignore packages that exist in `package.json` as these can be resolved by TypeScript
if (dependencies?.has(_pkg)) {
return [];
}

const path = await resolveTypePath(
_pkg + subpath,
subpath,
nuxt.options.modulesDir,
);
if (path) {
return [[pkg, [path]]];
}

return [];
}),
).then((r) => r.flat()),
);
Copy link

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

Add input validation for the hoist parameter.

The function doesn't validate the input hoist array, which could lead to runtime errors if invalid values are passed.

Add input validation at the beginning of the function:

export async function hoistDependencies(hoist: string[], nuxt = useNuxt()) {
+  if (!Array.isArray(hoist)) {
+    throw new TypeError('hoist parameter must be an array of strings');
+  }
+  
+  if (hoist.some(pkg => typeof pkg !== 'string' || !pkg.trim())) {
+    throw new TypeError('All hoist entries must be non-empty strings');
+  }
+
  const packageJSON = await readPackageJSON(nuxt.options.rootDir).catch(
🤖 Prompt for AI Agents
In src/hoist.ts between lines 50 and 75, the hoist parameter is used without
validation, risking runtime errors if invalid values are passed. Add input
validation at the start of the function to check that hoist is an array and that
each element is a non-empty string. If the validation fails, throw an
appropriate error or handle it gracefully to prevent further processing with
invalid input.

@pkg-pr-new
Copy link

pkg-pr-new bot commented Jul 12, 2025

npm i https://pkg.pr.new/BobbieGoede/nuxt-module-utils@1

commit: 9ee7692

Copy link

@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: 4

♻️ Duplicate comments (2)
src/hoist.ts (2)

35-35: Fix error handling for package.json reading (addresses past feedback).

This issue was previously identified but not yet addressed. The current error handling hides all errors when reading package.json, which could mask important issues like permission problems or malformed JSON.

Apply this fix to be more specific about error handling:

  const packageJSON = await readPackageJSON(nuxt.options.rootDir).catch(
-    () => ({}) as PackageJson,
+    (error) => {
+      if (error.code === 'ENOENT') {
+        return {} as PackageJson;
+      }
+      throw error; // Re-throw other errors like permission issues or malformed JSON
+    },
  );

34-34: Add input validation for the hoist parameter (addresses past feedback).

This issue was previously identified but not yet addressed. The function doesn't validate the input hoist array, which could lead to runtime errors if invalid values are passed.

Add input validation at the beginning of the function:

export async function hoistDependencies(hoist: string[], nuxt = useNuxt()) {
+  if (!Array.isArray(hoist)) {
+    throw new TypeError('hoist parameter must be an array of strings');
+  }
+  
+  if (hoist.some(pkg => typeof pkg !== 'string' || !pkg.trim())) {
+    throw new TypeError('All hoist entries must be non-empty strings');
+  }
+
  const packageJSON = await readPackageJSON(nuxt.options.rootDir).catch(
🧹 Nitpick comments (6)
scripts/switch-nuxt.sh (2)

1-2: Prefer portable she-bang and stricter error flags

#!/bin/sh often maps to different shells (e.g. dash on Debian, bash on macOS). Using /usr/bin/env is more portable, and adding -u/-o pipefail tightens error handling.

-#!/bin/sh
-set -e
+#!/usr/bin/env sh
+set -euo pipefail

2-2: Fail fast when pnpm is missing

A quick availability check gives a clearer error than a cryptic “command not found”.

 set -e
+command -v pnpm >/dev/null 2>&1 || {
+  echo "❌  pnpm is required but not installed." >&2
+  exit 1
+}
.github/workflows/preview-release.yml (2)

24-31: Pin reusable actions to commit SHAs for supply-chain safety.

actions/checkout@v4 and actions/setup-node@v4 are mutable tags.
Consistency and SBOM requirements generally mandate pinning to a specific
commit hash (as you already did for pnpm/action-setup).

Example:

-uses: actions/checkout@v4
+uses: actions/[email protected] # 2f4e... (pin to commit)

Apply the same pattern to actions/setup-node.


27-27: Explicitly set the pnpm version for deterministic builds.

pnpm/action-setup defaults to the latest release, which may introduce
breaking changes unexpectedly. Add the version input to lock the toolchain:

-uses: pnpm/action-setup@a7487c7e89a18df4991f7f222e4898a00d66ddda
+uses: pnpm/action-setup@a7487c7e89a18df4991f7f222e4898a00d66ddda
+with:
+  version: 8.10.0          # keep in sync with packageManager field
src/hoist.ts (2)

13-28: Consider improving error handling specificity.

The resolveTypePath function correctly handles the module resolution logic, but the catch block on line 25 silently swallows all errors. While returning null for resolution failures is appropriate, consider logging unexpected errors for debugging purposes.

  } catch {
+    // Consider logging unexpected errors for debugging
    return null;
  }

49-49: Remove unnecessary optional chaining.

The dependencies variable is always defined as a Set on line 37, so the optional chaining is unnecessary here.

- if (dependencies?.has(_pkg)) {
+ if (dependencies.has(_pkg)) {
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between ecae256 and 921af9f.

⛔ Files ignored due to path filters (1)
  • pnpm-lock.yaml is excluded by !**/pnpm-lock.yaml
📒 Files selected for processing (5)
  • .github/workflows/preview-release.yml (1 hunks)
  • .gitignore (1 hunks)
  • package.json (2 hunks)
  • scripts/switch-nuxt.sh (1 hunks)
  • src/hoist.ts (1 hunks)
✅ Files skipped from review due to trivial changes (1)
  • .gitignore
🚧 Files skipped from review as they are similar to previous changes (1)
  • package.json
🧰 Additional context used
🧬 Code Graph Analysis (1)
src/hoist.ts (1)
src/index.ts (1)
  • hoistDependencies (1-1)
🔇 Additional comments (2)
src/hoist.ts (2)

1-7: LGTM! Clean imports and version detection.

The imports are well-organized and the Nuxt version detection is straightforward and effective.


63-79: LGTM! Proper TypeScript configuration handling.

The function correctly configures TypeScript paths for both Nitro and Nuxt, with appropriate version-specific handling for Nuxt v4. The use of defu for deep merging ensures existing configurations are preserved.

Comment on lines +4 to +8
# Default to 'latest' if no argument is provided
VERSION=${1:-latest}

echo "Switching to nuxt version: $VERSION"
pnpm i nuxt@$VERSION @nuxt/kit@$VERSION @nuxt/schema@$VERSION No newline at end of file
Copy link

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

Harden the install step & keep package.json clean

  1. Quote $VERSION to avoid word-splitting or globbing surprises.
  2. pnpm i adds runtime deps; for a module that only needs Nuxt for local testing you probably want dev deps: pnpm add -D.
  3. If you really need them in peerDependencies, add the --save-peer flag instead of mutating dependencies.
-echo "Switching to nuxt version: $VERSION"
-pnpm i nuxt@$VERSION @nuxt/kit@$VERSION @nuxt/schema@$VERSION
+echo "Switching to Nuxt version: $VERSION"
+# Installs as devDependencies, keeps runtime deps slim.
+pnpm add -D "nuxt@${VERSION}" "@nuxt/kit@${VERSION}" "@nuxt/schema@${VERSION}"
🤖 Prompt for AI Agents
In scripts/switch-nuxt.sh around lines 4 to 8, the script installs Nuxt packages
without quoting the version variable, risking word-splitting or globbing issues.
Also, it uses 'pnpm i' which adds runtime dependencies, but since Nuxt is likely
needed only for local testing, these should be added as dev dependencies using
'pnpm add -D'. If the packages are intended as peer dependencies, use the
'--save-peer' flag instead of modifying dependencies directly. Update the
install command to quote $VERSION and use the appropriate pnpm flags
accordingly.


jobs:
release:
if: ${{ contains(github.event.pull_request.labels.*.name, 'cr-tracked') }}
Copy link

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

if expression can break on push events.

For non-PR events (push), github.event.pull_request is null, so
contains(github.event.pull_request.labels.*.name, 'cr-tracked') throws a
runtime evaluation error and cancels the job.

Guard the check with an event-type predicate:

-if: ${{ contains(github.event.pull_request.labels.*.name, 'cr-tracked') }}
+if: ${{ github.event_name == 'pull_request' && contains(github.event.pull_request.labels.*.name, 'cr-tracked') }}
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
if: ${{ contains(github.event.pull_request.labels.*.name, 'cr-tracked') }}
if: ${{ github.event_name == 'pull_request' && contains(github.event.pull_request.labels.*.name, 'cr-tracked') }}
🤖 Prompt for AI Agents
In .github/workflows/preview-release.yml at line 19, the current if expression
assumes github.event.pull_request exists, which causes runtime errors on push
events where it is null. To fix this, add a guard condition to first check that
the event is a pull_request before accessing pull_request.labels. Modify the if
expression to ensure it only evaluates contains(...) when the event is a
pull_request, preventing errors on push events.

Comment on lines +6 to +7
tags:
- '!**'
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue

Invalid negation pattern for pushed tags – switch to tags-ignore.

push.tags does not support negation ('!**'). Use tags-ignore (or omit the block entirely) to prevent tag-triggered runs, otherwise the workflow will fail to parse.

-    tags:
-      - '!**'
+    tags-ignore:
+      - '**'
🤖 Prompt for AI Agents
In .github/workflows/preview-release.yml at lines 6 to 7, the tags field uses an
invalid negation pattern '!**' which is not supported for push tags. To fix
this, remove the tags block entirely or replace it with a tags-ignore block to
exclude all tags from triggering the workflow. This change will prevent parsing
errors and correctly ignore tag pushes.

Copy link

@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

♻️ Duplicate comments (3)
src/hoist.ts (3)

40-40: Add input validation for the hoist parameter.

The function doesn't validate the input hoist array, which could lead to runtime errors if invalid values are passed.

Add input validation at the beginning of the function:

export async function hoistDependencies(hoist: string[], nuxt = useNuxt()) {
+  if (!Array.isArray(hoist)) {
+    throw new TypeError('hoist parameter must be an array of strings');
+  }
+  
+  if (hoist.some(pkg => typeof pkg !== 'string' || !pkg.trim())) {
+    throw new TypeError('All hoist entries must be non-empty strings');
+  }
+
  const packageJSON = await readPackageJSON(nuxt.options.rootDir).catch(

41-41: Improve error handling for package.json reading.

The current error handling hides all errors when reading package.json, which could mask important issues like permission problems or malformed JSON.

Consider being more specific about error handling:

  const packageJSON = await readPackageJSON(nuxt.options.rootDir).catch(
-    () => ({}) as PackageJson,
+    (error) => {
+      if (error.code === 'ENOENT') {
+        return {} as PackageJson;
+      }
+      throw error; // Re-throw other errors like permission issues or malformed JSON
+    },
  );

42-42: Clarify regex name and improve logic.

The regex NESTED_PKG_RE name is misleading. It's actually checking for packages with subpaths (like lodash/debounce), not nested packages. The pattern /^[^@]+\// also won't work correctly for scoped packages with subpaths like @vue/test-utils/subpath.

- const NESTED_PKG_RE = /^[^@]+\//;
+ const SUBPATH_PKG_RE = /\//;

And update the usage on line 51:

- const [_pkg = pkg, _subpath] = NESTED_PKG_RE.test(pkg) ? pkg.split("/") : [pkg];
+ const [_pkg = pkg, _subpath] = SUBPATH_PKG_RE.test(pkg) ? pkg.split("/", 2) : [pkg];

This will correctly handle both regular packages with subpaths (lodash/debounce) and scoped packages with subpaths (@vue/test-utils/subpath).

🧹 Nitpick comments (4)
src/hoist.ts (4)

55-55: Remove unnecessary optional chaining.

The optional chaining operator is unnecessary here since dependencies is always a Set instance.

-        if (dependencies?.has(_pkg)) {
+        if (dependencies.has(_pkg)) {

70-72: Optimize object spreading for paths.

The current object spreading of paths creates a new object unnecessarily. Use paths directly since it's already the desired structure.

  nuxt.options.nitro.typescript = defu(nuxt.options.nitro.typescript, {
-    tsConfig: { compilerOptions: { paths: { ...paths } } },
+    tsConfig: { compilerOptions: { paths } },
  });

77-79: Optimize object spreading for paths (consistency).

Apply the same optimization as suggested for the Nitro configuration to maintain consistency.

    opts.tsConfig.compilerOptions = defu(opts.tsConfig.compilerOptions, {
-      paths: { ...paths },
+      paths,
    });

82-83: Optimize object spreading for paths (Nuxt v4 configs).

Apply the same optimization to the Nuxt v4 configurations for consistency.

-      opts.nodeTsConfig.compilerOptions = defu(opts.nodeTsConfig.compilerOptions, { paths: { ...paths } });
-      opts.sharedTsConfig.compilerOptions = defu(opts.sharedTsConfig.compilerOptions, { paths: { ...paths } });
+      opts.nodeTsConfig.compilerOptions = defu(opts.nodeTsConfig.compilerOptions, { paths });
+      opts.sharedTsConfig.compilerOptions = defu(opts.sharedTsConfig.compilerOptions, { paths });
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 921af9f and 9ee7692.

📒 Files selected for processing (2)
  • README.md (1 hunks)
  • src/hoist.ts (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • README.md
🔇 Additional comments (1)
src/hoist.ts (1)

1-7: LGTM: Clean imports and version detection.

The imports are well-organized and the Nuxt version detection is straightforward and effective.

/**
* @see [Nuxt source](https://github.com/nuxt/nuxt/blob/a0f9ddfe241bcf555f6305aa10c087a1fe64af87/packages/nuxt/src/core/utils/types.ts#L6)
*/
async function resolveTypePath(path: string, subpath: string, searchPaths = tryUseNuxt()?.options.modulesDir) {
Copy link

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

Add null check for searchPaths parameter.

The searchPaths parameter could be undefined when tryUseNuxt() returns null, which would cause searchPaths?.map() to return undefined and potentially cause issues in resolveModulePath.

-async function resolveTypePath(path: string, subpath: string, searchPaths = tryUseNuxt()?.options.modulesDir) {
+async function resolveTypePath(path: string, subpath: string, searchPaths = tryUseNuxt()?.options.modulesDir || []) {
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
async function resolveTypePath(path: string, subpath: string, searchPaths = tryUseNuxt()?.options.modulesDir) {
async function resolveTypePath(
path: string,
subpath: string,
searchPaths = tryUseNuxt()?.options.modulesDir || []
) {
🤖 Prompt for AI Agents
In src/hoist.ts at line 12, the searchPaths parameter may be undefined if
tryUseNuxt() returns null, leading to errors when calling searchPaths?.map().
Add a null check to ensure searchPaths is defined before using it, or provide a
default empty array to avoid passing undefined to resolveModulePath.

@BobbieGoede BobbieGoede merged commit 3e3333a into main Jul 12, 2025
4 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants