@zkochan/cmd-shim 2.2.3 → 3.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (4) hide show
  1. package/README.md +1 -0
  2. package/index.d.ts +47 -0
  3. package/index.js +112 -17
  4. package/package.json +8 -7
package/README.md CHANGED
@@ -39,6 +39,7 @@ The same as above, but will just continue if the file does not exist.
39
39
  - `opts.preserveSymlinks` - _Boolean_ - if true, `--preserve-symlinks` is added to the options passed to NodeJS.
40
40
  - `opts.nodePath` - _String_ - sets the [NODE_PATH](https://nodejs.org/api/cli.html#cli_node_path_path) env variable.
41
41
  - `opts.createCmdFile` - _Boolean_ - is `true` on Windows by default. If true, creates a cmd file.
42
+ - `opts.createPwshFile` - _Boolean_ - is `true` by default. If true, creates a powershell file.
42
43
 
43
44
  ```javascript
44
45
  const cmdShim = require('@zkochan/cmd-shim')
package/index.d.ts ADDED
@@ -0,0 +1,47 @@
1
+
2
+ interface Options {
3
+ /**
4
+ * If a PowerShell script should be created.
5
+ *
6
+ * @default true
7
+ */
8
+ createPwshFile?: boolean;
9
+
10
+ /**
11
+ * If a Windows Command Prompt script should be created.
12
+ *
13
+ * @default false
14
+ */
15
+ createCmdFile?: boolean;
16
+
17
+ /**
18
+ * If symbolic links should be preserved.
19
+ *
20
+ * @default false
21
+ */
22
+ preserveSymlinks?: boolean;
23
+
24
+ /**
25
+ * The path to the executable file.
26
+ */
27
+ prog?: string;
28
+
29
+ /**
30
+ * The arguments to initialize the `node` process with.
31
+ */
32
+ args?: string;
33
+
34
+ /**
35
+ * The value of the $NODE_PATH environment variable.
36
+ *
37
+ * The single `string` format is only kept for legacy compatibility,
38
+ * and the array form should be preferred.
39
+ */
40
+ nodePath?: string | string[];
41
+ }
42
+
43
+ declare function cmdShim(src: string, to: string, opts: Options): Promise<void>
44
+ declare namespace cmdShim {
45
+ function cmdShimIfExists(src: string, to: string, opts: Options): Promise<void>
46
+ }
47
+ export = cmdShim;
package/index.js CHANGED
@@ -19,6 +19,8 @@ const path = require('path')
19
19
  const isWindows = require('is-windows')
20
20
  const shebangExpr = /^#!\s*(?:\/usr\/bin\/env)?\s*([^ \t]+)(.*)$/
21
21
  const DEFAULT_OPTIONS = {
22
+ // Create PowerShell file by default if the option hasn't been specified
23
+ createPwshFile: true,
22
24
  createCmdFile: isWindows()
23
25
  }
24
26
 
@@ -42,12 +44,16 @@ function cmdShim (src, to, opts) {
42
44
  }
43
45
 
44
46
  function cmdShim_ (src, to, opts) {
45
- return Promise.all([rm(to), opts.createCmdFile && rm(`${to}.cmd`)])
47
+ return Promise.all([
48
+ rm(to),
49
+ rm(`${to}.ps1`),
50
+ opts.createCmdFile && rm(`${to}.cmd`)
51
+ ])
46
52
  .then(() => writeShim(src, to, opts))
47
53
  }
48
54
 
49
55
  function writeShim (src, to, opts) {
50
- opts = opts || {}
56
+ opts = Object.assign({}, DEFAULT_OPTIONS, opts)
51
57
  const defaultArgs = opts.preserveSymlinks ? '--preserve-symlinks' : ''
52
58
  // make a cmd file and a sh script
53
59
  // First, check if the bin is a #! of some sort.
@@ -61,7 +67,7 @@ function writeShim (src, to, opts) {
61
67
  const shebang = firstLine.match(shebangExpr)
62
68
  if (!shebang) return writeShim_(src, to, Object.assign({}, opts, {args: defaultArgs}))
63
69
  const prog = shebang[1]
64
- const args = shebang[2] && (defaultArgs && (shebang[2] + ' ' + defaultArgs) || shebang[2]) || defaultArgs
70
+ const args = (shebang[2] && ((defaultArgs && (shebang[2] + ' ' + defaultArgs)) || shebang[2])) || defaultArgs
65
71
  return writeShim_(src, to, Object.assign({}, opts, {prog, args}))
66
72
  })
67
73
  .catch(() => writeShim_(src, to, Object.assign({}, opts, {args: defaultArgs})))
@@ -69,24 +75,32 @@ function writeShim (src, to, opts) {
69
75
  }
70
76
 
71
77
  function writeShim_ (src, to, opts) {
72
- opts = opts || {}
78
+ opts = Object.assign({}, DEFAULT_OPTIONS, opts)
73
79
  let shTarget = path.relative(path.dirname(to), src)
74
80
  let target = shTarget.split('/').join('\\')
75
81
  let longProg
76
82
  let prog = opts.prog
77
83
  let shProg = prog && prog.split('\\').join('/')
78
84
  let shLongProg
85
+ let pwshProg = shProg && `"${shProg}$exe"`
86
+ let pwshLongProg
79
87
  shTarget = shTarget.split('\\').join('/')
80
88
  let args = opts.args || ''
89
+ let {
90
+ win32: nodePath,
91
+ posix: shNodePath
92
+ } = normalizePathEnvVar(opts.nodePath)
81
93
  if (!prog) {
82
94
  prog = `"%~dp0\\${target}"`
83
95
  shProg = `"$basedir/${shTarget}"`
96
+ pwshProg = shProg
84
97
  args = ''
85
98
  target = ''
86
99
  shTarget = ''
87
100
  } else {
88
101
  longProg = `"%~dp0\\${prog}.exe"`
89
102
  shLongProg = '"$basedir/' + prog + '"'
103
+ pwshLongProg = `"$basedir/${prog}$exe"`
90
104
  target = `"%~dp0\\${target}"`
91
105
  shTarget = `"$basedir/${shTarget}"`
92
106
  }
@@ -100,7 +114,7 @@ function writeShim_ (src, to, opts) {
100
114
  // SET PATHEXT=%PATHEXT:;.JS;=;%
101
115
  // node "%~dp0\.\node_modules\npm\bin\npm-cli.js" %*
102
116
  // )
103
- cmd = opts.nodePath ? `@SET NODE_PATH=${opts.nodePath}\r\n` : ''
117
+ cmd = nodePath ? `@SET NODE_PATH=${nodePath}\r\n` : ''
104
118
  if (longProg) {
105
119
  cmd += '@IF EXIST ' + longProg + ' (\r\n' +
106
120
  ' ' + longProg + ' ' + args + ' ' + target + ' %*\r\n' +
@@ -131,17 +145,16 @@ function writeShim_ (src, to, opts) {
131
145
  // exit $ret
132
146
 
133
147
  let sh = '#!/bin/sh\n'
134
- const env = opts.nodePath ? `NODE_PATH="${opts.nodePath}" ` : ''
148
+ sh = sh +
149
+ "basedir=$(dirname \"$(echo \"$0\" | sed -e 's,\\\\,/,g')\")\n" +
150
+ '\n' +
151
+ 'case `uname` in\n' +
152
+ ' *CYGWIN*) basedir=`cygpath -w "$basedir"`;;\n' +
153
+ 'esac\n' +
154
+ '\n'
155
+ const env = opts.nodePath ? `NODE_PATH="${shNodePath}" ` : ''
135
156
 
136
157
  if (shLongProg) {
137
- sh = sh +
138
- "basedir=$(dirname \"$(echo \"$0\" | sed -e 's,\\\\,/,g')\")\n" +
139
- '\n' +
140
- 'case `uname` in\n' +
141
- ' *CYGWIN*) basedir=`cygpath -w "$basedir"`;;\n' +
142
- 'esac\n' +
143
- '\n'
144
-
145
158
  sh = sh +
146
159
  'if [ -x ' + shLongProg + ' ]; then\n' +
147
160
  ' ' + env + shLongProg + ' ' + args + ' ' + shTarget + ' "$@"\n' +
@@ -152,20 +165,102 @@ function writeShim_ (src, to, opts) {
152
165
  'fi\n' +
153
166
  'exit $ret\n'
154
167
  } else {
155
- sh = env + shProg + ' ' + args + ' ' + shTarget + ' "$@"\n' +
168
+ sh = sh + env + shProg + ' ' + args + ' ' + shTarget + ' "$@"\n' +
156
169
  'exit $?\n'
157
170
  }
158
171
 
172
+ // #!/usr/bin/env pwsh
173
+ // $basedir=Split-Path $MyInvocation.MyCommand.Definition -Parent
174
+ //
175
+ // $ret=0
176
+ // $exe = ""
177
+ // if ($PSVersionTable.PSVersion -lt "6.0" -or $IsWindows) {
178
+ // # Fix case when both the Windows and Linux builds of Node
179
+ // # are installed in the same directory
180
+ // $exe = ".exe"
181
+ // }
182
+ // if (Test-Path "$basedir/node") {
183
+ // & "$basedir/node$exe" "$basedir/node_modules/npm/bin/npm-cli.js" $args
184
+ // $ret=$LASTEXITCODE
185
+ // } else {
186
+ // & "node$exe" "$basedir/node_modules/npm/bin/npm-cli.js" $args
187
+ // $ret=$LASTEXITCODE
188
+ // }
189
+ // exit $ret
190
+ let pwsh = '#!/usr/bin/env pwsh\n' +
191
+ '$basedir=Split-Path $MyInvocation.MyCommand.Definition -Parent\n' +
192
+ '\n' +
193
+ '$exe=""\n' +
194
+ (opts.nodePath ? '$env_node_path=$env:NODE_PATH\n' +
195
+ `$env:NODE_PATH="${nodePath}"\n` : '') +
196
+ 'if ($PSVersionTable.PSVersion -lt "6.0" -or $IsWindows) {\n' +
197
+ ' # Fix case when both the Windows and Linux builds of Node\n' +
198
+ ' # are installed in the same directory\n' +
199
+ ' $exe=".exe"\n' +
200
+ '}'
201
+ if (opts.nodePath) {
202
+ pwsh = pwsh +
203
+ ' else {\n' +
204
+ ` $env:NODE_PATH="${shNodePath}"\n` +
205
+ '}'
206
+ }
207
+ pwsh += '\n'
208
+ if (shLongProg) {
209
+ pwsh = pwsh +
210
+ '$ret=0\n' +
211
+ `if (Test-Path ${pwshLongProg}) {\n` +
212
+ ` & ${pwshLongProg} ${args} ${shTarget} $args\n` +
213
+ ' $ret=$LASTEXITCODE\n' +
214
+ '} else {\n' +
215
+ ` & ${pwshProg} ${args} ${shTarget} $args\n` +
216
+ ' $ret=$LASTEXITCODE\n' +
217
+ '}\n' +
218
+ (opts.nodePath ? '$env:NODE_PATH=$env_node_path\n' : '') +
219
+ 'exit $ret\n'
220
+ } else {
221
+ pwsh = pwsh +
222
+ `& ${pwshProg} ${args} ${shTarget} $args\n` +
223
+ (opts.nodePath ? '$env:NODE_PATH=$env_node_path\n' : '') +
224
+ 'exit $LASTEXITCODE\n'
225
+ }
226
+
159
227
  return Promise.all([
160
228
  opts.createCmdFile && fs.writeFile(to + '.cmd', cmd, 'utf8'),
229
+ opts.createPwshFile && fs.writeFile(`${to}.ps1`, pwsh, 'utf8'),
161
230
  fs.writeFile(to, sh, 'utf8')
162
231
  ])
163
- .then(() => chmodShim(to, opts.createCmdFile))
232
+ .then(() => chmodShim(to, opts))
164
233
  }
165
234
 
166
- function chmodShim (to, createCmdFile) {
235
+ function chmodShim (to, {createCmdFile, createPwshFile}) {
167
236
  return Promise.all([
168
237
  fs.chmod(to, 0o755),
238
+ createPwshFile && fs.chmod(`${to}.ps1`, 0o755),
169
239
  createCmdFile && fs.chmod(`${to}.cmd`, 0o755)
170
240
  ])
171
241
  }
242
+
243
+ /**
244
+ * @param {string|string[]} nodePath
245
+ * @returns {{win32:string,posix:string}}
246
+ */
247
+ function normalizePathEnvVar (nodePath) {
248
+ if (!nodePath) {
249
+ return {
250
+ win32: nodePath,
251
+ posix: nodePath
252
+ }
253
+ }
254
+ let split = (typeof nodePath === 'string' ? nodePath.split(path.delimiter) : Array.from(nodePath))
255
+ let result = {}
256
+ for (let i = 0; i < split.length; i++) {
257
+ const win32 = split[i].split('/').join('\\')
258
+ const posix = isWindows() ? split[i].split('\\').join('/').replace(/^([^:\\/]*):/, (_, $1) => `/mnt/${$1.toLowerCase()}`) : split[i]
259
+
260
+ result.win32 = result.win32 ? `${result.win32};${win32}` : win32
261
+ result.posix = result.posix ? `${result.posix}:${posix}` : posix
262
+
263
+ result[i] = {win32, posix}
264
+ }
265
+ return result
266
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@zkochan/cmd-shim",
3
- "version": "2.2.3",
3
+ "version": "3.1.0",
4
4
  "description": "Used in pnpm for command line application support",
5
5
  "author": {
6
6
  "name": "Zoltan Kochan",
@@ -8,13 +8,15 @@
8
8
  "url": "http://kochan.io"
9
9
  },
10
10
  "scripts": {
11
- "test:unit": "tape test/*.js | tap-diff",
11
+ "test:unit": "tape test/*.js",
12
12
  "test": "standard && npm run test:unit && mos test",
13
13
  "md": "mos"
14
14
  },
15
15
  "files": [
16
+ "index.d.ts",
16
17
  "index.js"
17
18
  ],
19
+ "types": "index.d.ts",
18
20
  "repository": {
19
21
  "type": "git",
20
22
  "url": "https://github.com/pnpm/cmd-shim.git"
@@ -28,14 +30,13 @@
28
30
  "devDependencies": {
29
31
  "mos": "^1.3.1",
30
32
  "mos-plugin-readme": "^1.0.4",
31
- "rimraf": "~2.2.8",
32
- "standard": "^8.5.0",
33
- "tap-diff": "^0.1.1",
33
+ "rimraf": "^2.6.2",
34
+ "standard": "^11.0.1",
34
35
  "tape": "^4.6.2",
35
- "tape-promise": "^2.0.0"
36
+ "tape-promise": "^3.0.0"
36
37
  },
37
38
  "engines": {
38
- "node": ">=4"
39
+ "node": ">=6"
39
40
  },
40
41
  "mos": {
41
42
  "plugins": [