Skip to content

feat(config): enable unwrapSingleRootDir by default#23

Merged
fbosch merged 3 commits into
masterfrom
feature/unwrap-single-root-dir-by-default
Feb 4, 2026
Merged

feat(config): enable unwrapSingleRootDir by default#23
fbosch merged 3 commits into
masterfrom
feature/unwrap-single-root-dir-by-default

Conversation

@fbosch

@fbosch fbosch commented Feb 4, 2026

Copy link
Copy Markdown
Owner

Summary

Enable unwrap single root directory by default for cleaner materialized output structure.

Changes

  • Default unwrapSingleRootDir changed from false to true
  • Relaxed source ID validation to allow dots and at-signs
  • ID validation now checks for path separators instead of alphanumeric pattern
  • Added blank-string check to ID validation

Summary by CodeRabbit

  • New Features

    • Single-root directory unwrapping is now enabled by default; materialized output will flatten when nested under a single directory.
  • Bug Fixes

    • Source ID validation updated: blank IDs, path-separator characters and certain reserved characters are now rejected; dots and at-signs are allowed.
  • Tests

    • Test expectations updated to reflect new unwrapping and validation behavior.
  • Documentation

    • README default behavior updated to reflect the new unwrap setting.

Copilot AI review requested due to automatic review settings February 4, 2026 18:36
@coderabbitai

coderabbitai Bot commented Feb 4, 2026

Copy link
Copy Markdown

Warning

Rate limit exceeded

@fbosch has exceeded the limit for the number of commits that can be reviewed per hour. Please wait 19 minutes and 40 seconds before requesting another review.

⌛ How to resolve this issue?

After the wait time has elapsed, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

We recommend that you space out your commits to avoid hitting the rate limit.

🚦 How do rate limits work?

CodeRabbit enforces hourly rate limits for each developer per organization.

Our paid plans have higher rate limits than the trial, open-source and free plans. In all cases, we re-allow further reviews after a brief timeout.

Please see our FAQ for further information.

📝 Walkthrough

Walkthrough

Default for unwrapSingleRootDir changed from false to true, altering materialization defaults so single-directory roots are unwrapped by default and affecting how files are placed during materialization and related tests.

Changes

Cohort / File(s) Summary
Documentation & Config
README.md, src/config/index.ts
Default unwrapSingleRootDir changed from false to true in README and DEFAULT_CONFIG.
Materialization Logic
src/cache/materialize.ts
resolveMaterializeParams now defaults unwrapSingleRootDir to true, changing how unwrapPrefix is computed and where materialized files are placed.
Source ID Validation
src/source-id.ts
Replaced SAFE_ID_PATTERN with INVALID_ID_PATTERN, added blank-string check and null-char check, and broadened invalid-character error messaging to include path separators/reserved characters.
Tests — include/exclude & materialize
tests/sync-include-exclude.test.js, tests/sync-materialize.test.js
Assertions updated to expect flattened paths (e.g., guide.md, README.md at root) and to test unwrap toggling behavior; removed some explicit unwrapSingleRootDir settings.
Tests — edge cases & security/validation
tests/edge-cases.test.js, tests/edge-cases-security.test.js, tests/edge-cases-validation.test.js
Error expectation regexes updated to reference sources.0.id and mention path separators/reserved chars; tests adjusted for flattened materialized paths and for allowing dots/@ in IDs.
Misc / Manifest
package.json, ... (manifest lines)
Minor manifest/summary line edits reflecting the change (small line count adjustments).

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Poem

🐰 I nibbled the defaults and found something new,
Single-root bouquets now bloom into view.
No folders entangled, just files in the light—
A hop, a small change, and the tree feels just right. 🥕

🚥 Pre-merge checks | ✅ 3
✅ Passed checks (3 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly and specifically describes the main change: enabling unwrapSingleRootDir by default, which aligns with the core modifications across config, materialization logic, and all affected tests.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.

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

✨ Finishing touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch feature/unwrap-single-root-dir-by-default

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.

@pkg-pr-new

pkg-pr-new Bot commented Feb 4, 2026

Copy link
Copy Markdown

Open in StackBlitz

npx https://pkg.pr.new/fbosch/docs-cache@23

commit: f1d1154

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 0

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
src/cache/materialize.ts (1)

172-179: ⚠️ Potential issue | 🔴 Critical

Pass unwrapSingleRootDir to computeManifestHash call to align with materializeSource.

The computeManifestHash call (line 587–596 in sync.ts) omits the unwrapSingleRootDir parameter while materializeSource explicitly passes it. When source.unwrapSingleRootDir is false, this causes a mismatch: the materialized manifest is generated without unwrapping, but the hash is computed with unwrapping enabled (the default). This triggers false cache invalidation and unnecessary re-materialization.

Add unwrapSingleRootDir: source.unwrapSingleRootDir to the computeManifestHash parameters.

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

This PR changes the default value of unwrapSingleRootDir from false to true, which will automatically flatten single-directory hierarchies in materialized output for a cleaner structure.

Changes:

  • Updated default configuration to enable unwrapSingleRootDir by default
  • Updated documentation to reflect the new default value
  • Adjusted test expectations to account for unwrapped directory structures

Reviewed changes

Copilot reviewed 6 out of 6 changed files in this pull request and generated no comments.

Show a summary per file
File Description
src/config/index.ts Changed unwrapSingleRootDir default from false to true in DEFAULT_CONFIG
src/cache/materialize.ts Updated fallback default value for unwrapSingleRootDir parameter from false to true
README.md Updated documentation table to indicate new default value of true
tests/sync-materialize.test.js Adjusted test expectations for unwrapped paths; removed explicit unwrapSingleRootDir: true setting since it's now the default; added assertion for disabled unwrap case
tests/sync-include-exclude.test.js Updated path assertions to expect unwrapped structure when single root directory exists
tests/edge-cases-security.test.js Updated deeply nested directory test to expect fully unwrapped path

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🤖 Fix all issues with AI agents
In `@src/source-id.ts`:
- Line 1: The current INVALID_ID_PATTERN only denies a small set of characters
and misses control/whitespace characters and Windows reserved names/trailing
dots/spaces; update validation to (1) expand the denylist to include control
characters and whitespace (e.g., \u0000-\u001F and \u007F and \s), (2) normalize
the ID by trimming trailing spaces/dots before checking reserved names, and (3)
explicitly reject Windows device names (CON, PRN, AUX, NUL, COM1..COM9,
LPT1..LPT9) case-insensitively; locate and modify the INVALID_ID_PATTERN and the
ID validation logic (the function/main validation path that uses
INVALID_ID_PATTERN and the checks around lines referenced 24-27) to perform
normalization first then apply the reserved-name check and the stricter pattern
rejection.
🧹 Nitpick comments (3)
tests/edge-cases-validation.test.js (1)

39-40: Tighten the error regex to avoid false positives.

The alternation currently passes if either sources.0.id or the generic phrase matches, which can let unrelated error messages slip through. Consider requiring the ID label and the invalid-character wording.

♻️ Suggested update
-		/sources\.0\.id|path separators|reserved characters/i,
+		/sources\.0\.id.*(path separators|reserved characters)/i,
-		/sources\.0\.id|path separators|reserved characters/i,
+		/sources\.0\.id.*(path separators|reserved characters)/i,

Also applies to: 50-51

tests/edge-cases.test.js (2)

36-37: Make invalid‑ID error expectations more specific.

The current alternation can pass on partial matches. Requiring the ID label plus the invalid‑character wording makes the test assert the intended message.

♻️ Suggested update
-		/sources\.0\.id|path separators|reserved characters/i,
+		/sources\.0\.id.*(path separators|reserved characters)/i,
-			/sources\.0\.id|path separators|reserved characters/i,
+			/sources\.0\.id.*(path separators|reserved characters)/i,

Also applies to: 49-50


129-130: Tighten the blank‑ID error regex.

/sources\.0\.id|blank/i will pass if either token appears. Consider requiring the ID label plus “blank”.

♻️ Suggested update
-await assert.rejects(() => loadConfig(configPath), /sources\.0\.id|blank/i);
+await assert.rejects(() => loadConfig(configPath), /sources\.0\.id.*blank/i);

Comment thread src/source-id.ts
@fbosch fbosch merged commit df883dc into master Feb 4, 2026
13 checks passed
@fbosch fbosch deleted the feature/unwrap-single-root-dir-by-default branch February 4, 2026 18:59
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.

2 participants