Commit 539130a
Changed files (5)
docs/cli.md
@@ -106,10 +106,10 @@ zx --shell=/bin/another/sh script.mjs
## `--prefer-local, -l`
-Prefer locally installed packages bins.
+Prefer locally installed packages and binaries.
```bash
-zx --shell=/bin/bash script.mjs
+zx --prefer-local=/external/node_modules/or/nm-root script.mjs
```
## `--prefix & --postfix`
man/zx.1
@@ -20,7 +20,7 @@ prefix all commands
.SS --postfix=<command>
postfix all commands
.SS --prefer-local, -l
-prefer locally installed packages bins
+prefer locally installed packages and binaries
.SS --eval=<js>, -e
evaluate script
.SS --ext=<.mjs>
src/cli.ts
@@ -63,7 +63,7 @@ export function printUsage() {
--shell=<path> custom shell binary
--prefix=<command> prefix all commands
--postfix=<command> postfix all commands
- --prefer-local, -l prefer locally installed packages bins
+ --prefer-local, -l prefer locally installed packages and binaries
--cwd=<path> set current directory
--eval=<js>, -e evaluate script
--ext=<.mjs> script extension
@@ -81,8 +81,10 @@ export function printUsage() {
// prettier-ignore
export const argv: minimist.ParsedArgs = parseArgv(process.argv.slice(2), {
+ default: { ['prefer-local']: false },
+ // exclude 'prefer-local' to let minimist infer the type
string: ['shell', 'prefix', 'postfix', 'eval', 'cwd', 'ext', 'registry', 'env'],
- boolean: ['version', 'help', 'quiet', 'verbose', 'install', 'repl', 'experimental', 'prefer-local'],
+ boolean: ['version', 'help', 'quiet', 'verbose', 'install', 'repl', 'experimental'],
alias: { e: 'eval', i: 'install', v: 'version', h: 'help', l: 'prefer-local', 'env-file': 'env' },
stopEarly: true,
parseBoolean: true,
@@ -126,19 +128,22 @@ async function runScript(
scriptPath: string,
tempPath: string
): Promise<void> {
- const rmTemp = () => fs.rmSync(tempPath, { force: true })
+ let nm = ''
+ const rmTemp = () => {
+ fs.rmSync(tempPath, { force: true, recursive: true })
+ nm && fs.rmSync(nm, { force: true, recursive: true })
+ }
try {
if (tempPath) {
scriptPath = tempPath
await fs.writeFile(tempPath, script)
}
-
+ const cwd = path.dirname(scriptPath)
+ if (typeof argv.preferLocal === 'string') {
+ nm = linkNodeModules(cwd, argv.preferLocal)
+ }
if (argv.install) {
- await installDeps(
- parseDeps(script),
- path.dirname(scriptPath),
- argv.registry
- )
+ await installDeps(parseDeps(script), cwd, argv.registry)
}
injectGlobalRequire(scriptPath)
@@ -151,6 +156,20 @@ async function runScript(
}
}
+function linkNodeModules(cwd: string, external: string): string {
+ const nm = 'node_modules'
+ const alias = path.resolve(cwd, nm)
+ const target =
+ path.basename(external) === nm
+ ? path.resolve(external)
+ : path.resolve(external, nm)
+
+ if (fs.existsSync(alias) || !fs.existsSync(target)) return ''
+
+ fs.symlinkSync(target, alias, 'junction')
+ return target
+}
+
async function readScript() {
const [firstArg] = argv._
let script = ''
test/cli.test.js
@@ -186,6 +186,30 @@ describe('cli', () => {
}
})
+ test('supports --prefer-local to load modules', async () => {
+ const cwd = tmpdir()
+ const external = tmpdir()
+ await fs.outputJson(path.join(external, 'node_modules/a/package.json'), {
+ name: 'a',
+ version: '1.0.0',
+ type: 'module',
+ exports: './index.js',
+ })
+ await fs.outputFile(
+ path.join(external, 'node_modules/a/index.js'),
+ `
+export const a = 'AAA'
+`
+ )
+ const script = `
+import {a} from 'a'
+console.log(a);
+`
+ const out =
+ await $`node build/cli.js --cwd=${cwd} --prefer-local=${external} --test <<< ${script}`
+ assert.equal(out.stdout, 'AAA\n')
+ })
+
test('scripts from https 200', async () => {
const resp = await fs.readFile(path.resolve('test/fixtures/echo.http'))
const port = await getPort()
.size-limit.json
@@ -9,7 +9,7 @@
{
"name": "zx/index",
"path": "build/*.{js,cjs}",
- "limit": "812 kB",
+ "limit": "812.1 kB",
"brotli": false,
"gzip": false
},
@@ -30,7 +30,7 @@
{
"name": "all",
"path": "build/*",
- "limit": "850.3 kB",
+ "limit": "851 kB",
"brotli": false,
"gzip": false
}