Skip to content

fix!: strip shell extensions from shim target name#57

Open
nadalaba wants to merge 1 commit into
pnpm:mainfrom
nadalaba:pnpm/shims-of-shims
Open

fix!: strip shell extensions from shim target name#57
nadalaba wants to merge 1 commit into
pnpm:mainfrom
nadalaba:pnpm/shims-of-shims

Conversation

@nadalaba

@nadalaba nadalaba commented Jun 11, 2026

Copy link
Copy Markdown

Generating a sh shim for a PowerShell script currently produces a shim named script.ps1, which makes PowerShell treat it as a PowerShell script.

BREAKING CHANGE: strip common shell extensions from the target/to name before creating the shims by default. This behavior can be reverted by setting new option stripShellExtensionFromShim: false.

Fix #10

Summary by CodeRabbit

  • New Features
    • Added stripShellExtensionFromShim option (enabled by default) to control whether common shell extensions are removed from shim naming, preventing ambiguous extension combinations.
  • Documentation
    • Updated API docs for progArgs to reflect its optional nature and improved wording, and documented the new stripShellExtensionFromShim option.
  • Tests
    • Added an end-to-end regression test covering shim filename behavior when the option is enabled vs. disabled.

@qodo-free-for-open-source-projects

Copy link
Copy Markdown

PR Summary by Qodo

fix!: strip shell extensions from target shim name (support shims of shims)
🐞 Bug fix 🧪 Tests 🕐 10-20 Minutes

Grey Divider

Walkthroughs

Description
• Strip common shell extensions from the target shim basename by default.
• Prevent generating an sh shim with a misleading .ps1/.cmd/.sh extension.
• Add an opt-out flag and an e2e regression test for issue #10.
Diagram
graph TD
  A["Consumer code"] --> B["cmdShim(src,to,opts)"] --> C{"Strip ext?"}
  C -- "yes" --> D["Normalize target name"] --> E["cmdShim_()"] --> F["writeAllShims()"] --> G["sh/.cmd/.ps1 shims"]
  C -- "no" --> E
Loading
High-Level Assessment

The following are alternative approaches to this PR:

1. Strip only for the sh shim variant
  • ➕ Potentially less surprising for callers that intentionally want .ps1/.cmd-named targets
  • ➖ Requires changing writeAllShims signature/behavior to allow per-variant basenames
  • ➖ Still leaves edge cases where the 'no-extension' shim conflicts with the provided extension name
2. Enforce/validate that `to` must be extensionless
  • ➕ Makes the API contract explicit; avoids silent renaming
  • ➖ More disruptive (hard breaking change) and adds new failure modes for existing callers
  • ➖ Doesn’t help callers that are already passing paths with extensions and expecting it to work
3. Conditionally strip only when `to` extension mismatches detected runtime
  • ➕ More precise; preserves extensions when they match the source runtime
  • ➖ More complex and runtime-detection dependent (can be ambiguous/unknown)
  • ➖ Harder to reason about and test across platforms

Recommendation: The chosen approach (strip common shell extensions by default, with an explicit opt-out) is the best tradeoff: it fixes the real-world confusion/bug scenario (sh shim ending in .ps1) without requiring callers to redesign how they compute to, while still providing an escape hatch for workflows that relied on the old naming.

Grey Divider

File Changes

Bug fix (1)
index.ts Add default target-name normalization via stripShellExtensionFromShim +15/-1

Add default target-name normalization via stripShellExtensionFromShim

• Introduces a new option, stripShellExtensionFromShim (default true), and uses it to strip common shell extensions from the provided 'to' path before shim generation. This prevents creating sh shims whose filenames mislead shell/runtime association (e.g., an sh shim named *.ps1).

src/index.ts


Tests (1)
e2e.test.js Add regression test for shims-of-shims with .ps1 target name +24/-0

Add regression test for shims-of-shims with .ps1 target name

• Adds an end-to-end test asserting that when 'to' ends with .ps1 and stripping is enabled, the generated outputs use an extensionless base name for sh/cmd shims while still producing a .ps1 shim file. Imports cmd-extension to make the expected Windows cmd shim filename platform-correct.

test/e2e.test.js


Grey Divider

Qodo Logo

@coderabbitai

coderabbitai Bot commented Jun 11, 2026

Copy link
Copy Markdown

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 6fe3e657-3836-4092-a754-a34591061ec0

📥 Commits

Reviewing files that changed from the base of the PR and between 12ecd50 and e2a4563.

📒 Files selected for processing (3)
  • README.md
  • src/index.ts
  • test/e2e.test.js
✅ Files skipped from review due to trivial changes (1)
  • README.md
🚧 Files skipped from review as they are similar to previous changes (2)
  • test/e2e.test.js
  • src/index.ts

📝 Walkthrough

Walkthrough

Adds a new stripShellExtensionFromShim option (default true) that strips trailing .cmd, .bat, .ps1, and .sh from the shim target before generating shims; includes README documentation and an e2e regression test.

Changes

Shell Extension Stripping

Layer / File(s) Summary
Option type definition and default value
src/index.ts
Options interface gains optional stripShellExtensionFromShim?: boolean field with documentation. DEFAULT_OPTIONS sets this to true.
Extension stripping implementation
src/index.ts
cmdShim conditionally strips trailing .cmd, .bat, .ps1, and .sh from the to target (case-insensitive regex) when the option is enabled, then calls the internal shim writer with the adjusted target.
Documentation and regression test
README.md, test/e2e.test.js
README API docs updated to describe opts.stripShellExtensionFromShim. Test imports cmdExtension for platform-specific assertions and adds a regression test verifying .ps1 extension stripping while still emitting the .ps1 script.

🎯 3 (Moderate) | ⏱️ ~20 minutes

🐰 I hopped through code and trimmed the tail,
Stripped .ps1 so filenames won't derail.
Shims now skip the shell-suffixed chat,
Leaving scripts intact — imagine that! 🥕

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately reflects the main change: implementing automatic stripping of shell extensions from shim target names.
Linked Issues check ✅ Passed The PR addresses the core requirement from issue #10 by automatically stripping common shell extensions (.ps1, .cmd, .sh) from target names to prevent misleading shim filenames.
Out of Scope Changes check ✅ Passed All changes are directly scoped to implementing the shell extension stripping feature: README documentation, Options interface addition, and comprehensive e2e test coverage.
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.

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

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

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.

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

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@README.md`:
- Line 42: Update the README entry for opts.progArgs to fix the grammar: change
the phrase "`will be prepend to any CLI arguments`" to "`will be prepended to
any CLI arguments`" so the description for opts.progArgs reads correctly.

In `@test/e2e.test.js`:
- Line 99: Replace the typo in the inline comment that currently reads "it's s
powershell script" with "it's a powershell script"; locate the comment string
"it's s powershell script" in test/e2e.test.js and update it to the corrected
wording to remove the extra 's'.
- Around line 94-115: The test 'generate shims with {
stripShellExtensionFromShim: true }' assumes Windows behavior (expecting a .cmd
shim) but is not limited to Windows; either wrap this test in describeOnWindows
or make it platform-agnostic by calling cmdShim with createCmdFile: true and
adjusting assertions based on cmdExtension. Locate the test (the async test
calling cmdShim with stripShellExtensionFromShim: true) and update it to use
describeOnWindows(...) or add the option createCmdFile: true and branch the
expected files using cmdExtension so the assertion matches both Windows and
POSIX.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: a8cb064b-dbbd-4183-a3f3-c0a128c5cec7

📥 Commits

Reviewing files that changed from the base of the PR and between bb8df42 and 3624003.

📒 Files selected for processing (3)
  • README.md
  • src/index.ts
  • test/e2e.test.js
📜 Review details
🔇 Additional comments (4)
src/index.ts (3)

87-92: LGTM!


129-129: LGTM!


163-169: LGTM!

README.md (1)

43-43: LGTM!

Comment thread README.md Outdated
Comment thread test/e2e.test.js
Comment thread test/e2e.test.js Outdated
@nadalaba nadalaba changed the title fix!: support creating shims of shims fix!: strip shell extensions from shim target names Jun 11, 2026

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

♻️ Duplicate comments (1)
test/e2e.test.js (1)

94-114: ⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Guard this regression test for Windows-only behavior (or branch expected files by platform).

Line 113 can still fail off-Windows because script${cmdExtension} may collapse to script, creating an impossible expected duplicate. Since this case is explicitly Windows-focused, prefer describeOnWindows(...) here, or compute expectations conditionally.

Suggested minimal fix
-describe('create a shim of a pwsh shim with the same name in another location', () => {
+describeOnWindows('create a shim of a pwsh shim with the same name in another location', () => {
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@test/e2e.test.js` around lines 94 - 114, This Windows-only regression test
("generate shims with { stripShellExtensionFromShim: true }" in
test/e2e.test.js) should be guarded or have platform-specific expectations:
either wrap the test in describeOnWindows(...) (or skip when process.platform
!== 'win32') or compute the expected files array conditionally using
process.platform and cmdExtension so you don't compare duplicate names on
non-Windows; update the assertion to use the platform-aware expected list
instead of the hardcoded ['script', `script${cmdExtension}`, 'script.ps1'].
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Duplicate comments:
In `@test/e2e.test.js`:
- Around line 94-114: This Windows-only regression test ("generate shims with {
stripShellExtensionFromShim: true }" in test/e2e.test.js) should be guarded or
have platform-specific expectations: either wrap the test in
describeOnWindows(...) (or skip when process.platform !== 'win32') or compute
the expected files array conditionally using process.platform and cmdExtension
so you don't compare duplicate names on non-Windows; update the assertion to use
the platform-aware expected list instead of the hardcoded ['script',
`script${cmdExtension}`, 'script.ps1'].

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: dea168d1-e044-42f5-9835-c41a78dbfa5f

📥 Commits

Reviewing files that changed from the base of the PR and between 3624003 and 12ecd50.

📒 Files selected for processing (2)
  • README.md
  • test/e2e.test.js
🚧 Files skipped from review as they are similar to previous changes (1)
  • README.md

@nadalaba nadalaba changed the title fix!: strip shell extensions from shim target names fix!: strip shell extensions from shim target name Jun 12, 2026
@nadalaba nadalaba force-pushed the pnpm/shims-of-shims branch from 12ecd50 to e2a4563 Compare June 16, 2026 14:28
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.

Does cmdShim() support sh / batch (cmd) / pwsh script as src?

1 participant