Skip to content

fix(npm): improves root handling and resolve to local font files when possible#367

Open
florian-lefebvre wants to merge 1 commit intomainfrom
fix/npm-provider-misc
Open

fix(npm): improves root handling and resolve to local font files when possible#367
florian-lefebvre wants to merge 1 commit intomainfrom
fix/npm-provider-misc

Conversation

@florian-lefebvre
Copy link
Copy Markdown
Collaborator

@florian-lefebvre florian-lefebvre commented Apr 6, 2026

Reported at withastro/astro#16218.

While digging the reproduction, I uncovered a few bugs:

  1. The key was missing .json, making it harder to debug
  2. Defaulting root to '.' causes a bunch of issues when manipulating paths. I updated it to process.cwd() which does the same thing. I updated tests to set it back to '.' to make it easier to mock
  3. When resolving local fonts, URLs would be proxied to the CDN which defeats the purpose of using local files. Now, we compute paths to local font files

Summary by CodeRabbit

  • Bug Fixes

    • Updated npm provider to resolve the root directory to the current working directory by default instead of the literal '.' value.
  • Code Quality

    • Refactored font URL resolution logic for improved maintainability.
    • Removed unnecessary code comments.
    • Enhanced TypeScript configuration with Node.js type definitions.

Comment thread src/providers/npm.ts
const npmFetch = $fetch.create({ baseURL: cdn })
const readFile = providerOptions.readFile
const root = providerOptions.root || '.'
const root = stripTrailingSlash(providerOptions.root || await import('node:process').then(m => m.cwd()))
Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

An eslint rules requires us to use the module instead of the global. I decided to use a dynamic import to use it as a last resort, eg. in browser envs (although I doubt this is the primary usecase)

@codecov
Copy link
Copy Markdown

codecov bot commented Apr 6, 2026

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 98.78%. Comparing base (62bb93e) to head (1c2b327).
⚠️ Report is 1 commits behind head on main.

Additional details and impacted files
@@            Coverage Diff             @@
##             main     #367      +/-   ##
==========================================
+ Coverage   98.48%   98.78%   +0.30%     
==========================================
  Files          12       12              
  Lines         658      656       -2     
  Branches      171      170       -1     
==========================================
  Hits          648      648              
+ Misses         10        8       -2     

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai bot commented Apr 6, 2026

📝 Walkthrough

Walkthrough

This PR updates the npm provider to resolve the root option from process.cwd() by default instead of the literal '.' string, converts the npm provider factory to async initialization, refactors URL transformation logic into a reusable transformUrls() function, normalizes paths by stripping trailing slashes, updates the cache key format to include .json extension, and adds Node.js type definitions to TypeScript configuration.

Changes

Cohort / File(s) Summary
Documentation
README.md
Updated default value documentation for npm provider's root option from '.' to process.cwd().
Google Provider
src/providers/google.ts
Removed two inline ESLint suppression comments (e18e/prefer-array-to-sorted) without changing runtime behavior.
NPM Provider Implementation
src/providers/npm.ts
Converted factory callback to async, changed root default resolution to process.cwd(), introduced stripTrailingSlash() for path normalization, refactored URL transformation into new transformUrls(fontFaces, transformFn) function, and updated cache key format to include .json extension.
NPM Provider Tests
test/providers/npm.test.ts
Updated test cases to explicitly configure root: '.' for local resolution scenarios, changed assertions to expect local filesystem paths under /node_modules/ instead of CDN URLs, and restructured "supports custom root directory" test to verify behavior across multiple root variants.
TypeScript Configuration
tsconfig.json
Added "types": ["node"] to compiler options to include Node.js global type definitions.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~30 minutes

Possibly related PRs

Suggested reviewers

  • danielroe

Poem

🐰 Through process.cwd() paths, I hop with glee,
Async awaits and transformations flow free,
Trailing slashes trimmed in the forest of code,
Cache keys now JSON-stamped down the road,
A refactor most clean, organized and bright! ✨

🚥 Pre-merge checks | ✅ 2 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 14.29% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly identifies the main changes: improving root handling and enabling local font file resolution in the npm provider, which aligns with the primary objectives of the PR.

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

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch fix/npm-provider-misc

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
Contributor

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

🧹 Nitpick comments (2)
src/providers/npm.ts (2)

316-316: Cache key format change will orphan existing entries.

Adding .json to the cache key is a breaking change for cached data. Existing cache entries without the .json suffix will become unreachable and remain orphaned until they expire (one week). This isn't a functional issue—just be aware that users may see cache misses after upgrading.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/providers/npm.ts` at line 316, The cache key was changed to include a
".json" suffix in the const key =
`npm:${pkgName}/${cssFile}-${hash(options)}.json`, which will orphan existing
entries; revert to the previous key format or implement backward-compatibility
in the cache read path by attempting the old key (e.g., const oldKey =
`npm:${pkgName}/${cssFile}-${hash(options)}`) when fetching and, if found,
either migrate it to the new key or use it directly, and ensure any cache write
still uses the chosen canonical key so subsequent reads are consistent (update
the code around the key variable usage to try oldKey before new key and migrate
if necessary).

132-137: Consider handling backslashes for Windows compatibility.

The stripTrailingSlash() function only handles forward slashes. On Windows, paths might use backslashes. Consider also stripping trailing backslashes.

♻️ Optional fix for Windows compatibility
 function stripTrailingSlash(str: string): string {
-  if (str.endsWith('/')) {
-    return str.slice(0, -1)
+  if (str.endsWith('/') || str.endsWith('\\')) {
+    return str.slice(0, -1)
   }
   return str
 }
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/providers/npm.ts` around lines 132 - 137, stripTrailingSlash currently
only trims a trailing forward slash; update the function (stripTrailingSlash) to
also handle Windows backslashes by trimming any trailing forward or backslash
characters (e.g., treat both '/' and '\' as trailing separators) so paths like
"C:\path\" are normalized; implement by removing trailing slash/backslash
characters (use a single logic that strips both types) and return the cleaned
string from stripTrailingSlash.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Nitpick comments:
In `@src/providers/npm.ts`:
- Line 316: The cache key was changed to include a ".json" suffix in the const
key = `npm:${pkgName}/${cssFile}-${hash(options)}.json`, which will orphan
existing entries; revert to the previous key format or implement
backward-compatibility in the cache read path by attempting the old key (e.g.,
const oldKey = `npm:${pkgName}/${cssFile}-${hash(options)}`) when fetching and,
if found, either migrate it to the new key or use it directly, and ensure any
cache write still uses the chosen canonical key so subsequent reads are
consistent (update the code around the key variable usage to try oldKey before
new key and migrate if necessary).
- Around line 132-137: stripTrailingSlash currently only trims a trailing
forward slash; update the function (stripTrailingSlash) to also handle Windows
backslashes by trimming any trailing forward or backslash characters (e.g.,
treat both '/' and '\' as trailing separators) so paths like "C:\path\" are
normalized; implement by removing trailing slash/backslash characters (use a
single logic that strips both types) and return the cleaned string from
stripTrailingSlash.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 35712c94-45eb-4bf1-9a4e-d1490dd94853

📥 Commits

Reviewing files that changed from the base of the PR and between 62bb93e and 1c2b327.

📒 Files selected for processing (5)
  • README.md
  • src/providers/google.ts
  • src/providers/npm.ts
  • test/providers/npm.test.ts
  • tsconfig.json

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.

1 participant