Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,8 @@ The same as above, but will just continue if the file does not exist.
- `opts.nodeExecPath` - _String_ - sets the path to the Node.js executable.
- `opts.createCmdFile` - _Boolean_ - is `true` on Windows by default. If true, creates a cmd file.
- `opts.createPwshFile` - _Boolean_ - is `true` by default. If true, creates a powershell file.
- `opts.progArgs` - String - optional arguments that will be prepend to any CLI arguments
- `opts.progArgs` - _String_ - optional arguments that will be prepended to any CLI arguments.
- `opts.stripShellExtensionFromShim` - _Boolean_ - is `true` by default. If true, strips common shell extensions from the name of the `to` argument before creating the shims.

```javascript
const cmdShim = require('@zkochan/cmd-shim')
Expand Down
16 changes: 15 additions & 1 deletion src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,13 @@ export interface Options {
nodeExecPath?: string

prependToPath?: string

/**
* If common shell extensions should be stripped from target name.
*
* @default true
*/
stripShellExtensionFromShim?: boolean
}

/**
Expand Down Expand Up @@ -119,6 +126,7 @@ const DEFAULT_OPTIONS = {
// Create PowerShell file by default if the option hasn't been specified
createPwshFile: true,
createCmdFile: isWindows,
stripShellExtensionFromShim: true
}
/**
* Map from extensions of files that this module is frequently used for to their runtime.
Expand Down Expand Up @@ -152,7 +160,13 @@ function ingestOptions (opts?: Options): InternalOptions {
*/
export async function cmdShim (src: string, to: string, opts?: Options): Promise<void> {
const opts_ = ingestOptions(opts)
await cmdShim_(src, to, opts_)
// strip shell extensions that might cause confusion
// e.g., the sh shim of the powershell script.ps1 will be named script.ps1
// but it will be an sh script with a ps1 extension causing confusion for powershell
const target = opts_.stripShellExtensionFromShim
? to.replace(/\.(cmd|bat|ps1|sh)$/i, "")
: to
await cmdShim_(src, target, opts_)
}

/**
Expand Down
30 changes: 30 additions & 0 deletions test/e2e.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import fs from 'node:fs'
import path from 'node:path'
import { describe, test, snapshot } from 'node:test'
import assert from 'node:assert/strict'
import cmdExtension from 'cmd-extension'

snapshot.setDefaultSnapshotSerializers([
(value) => typeof value === 'string' ? `\n${value.replaceAll('\r', '')}` : JSON.stringify(value),
Expand Down Expand Up @@ -108,3 +109,32 @@ describeOnPosix('sh shim uses POSIX runtime from PATH', () => {
assert.doesNotMatch(r.stderr, /node\.exe/)
})
})

describe('create a shim of a pwsh shim with the same name in another location', () => {
// https://github.com/pnpm/cmd-shim/issues/10#issuecomment-4681988320
// If the option `stripShellExtensionFromShim` is true, it should strip common shell
// extensions (e.g., `.ps1`) from the end of the `to` argument name.
// Otherwise, it should leave `to` name as it is.
test('generate shims with opts.stripShellExtensionFromShim true/false', async (t) => {
const tempDir = tempy.directory()
const srcDir = path.join(tempDir, 'src')
const toDir_strip = path.join(tempDir, 'to', 'strip')
const toDir_noSrip = path.join(tempDir, 'to', 'noStrip')
fs.mkdirSync(srcDir, { recursive: true })
fs.mkdirSync(toDir_strip, { recursive: true })
fs.mkdirSync(toDir_noSrip, { recursive: true })

const src = path.join(srcDir, 'script.ps1')
fs.writeFileSync(src, 'Write-Output "Hello from ps1 script!"\r\n', 'utf8')

const to_strip = path.join(toDir_strip, 'script.ps1')
await cmdShim(src, to_strip, { createCmdFile: true, stripShellExtensionFromShim: true })
const files_strip = fs.readdirSync(toDir_strip).sort()
assert.deepStrictEqual(files_strip, ['script', `script${cmdExtension}`, 'script.ps1'])

const to_noStrip = path.join(toDir_noSrip, 'script.ps1')
await cmdShim(src, to_noStrip, { createCmdFile: true, stripShellExtensionFromShim: false })
const files_noStrip = fs.readdirSync(toDir_noSrip).sort()
assert.deepStrictEqual(files_noStrip, ['script.ps1', `script.ps1${cmdExtension}`, 'script.ps1.ps1'])
})
})
Comment thread
coderabbitai[bot] marked this conversation as resolved.
Loading