Skip to content
Merged
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
2 changes: 2 additions & 0 deletions docs/lib/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -151,10 +151,12 @@ const generateFlagsTable = (definitionPool) => {
if (!defaultVal) {
defaultVal = String(def.default)
}
defaultVal = defaultVal.replace(/\n/g, ' ').trim()
let typeVal = def.typeDescription || String(def.type)
if (def.required) {
typeVal = `${typeVal} (required)`
}
typeVal = typeVal.replace(/\n/g, ' ').trim()
const desc = (def.description || '').replace(/\n/g, ' ').trim()
return `| ${flagsStr} | ${defaultVal} | ${typeVal} | ${desc} |`
})
Expand Down
2 changes: 1 addition & 1 deletion lib/commands/publish.js
Original file line number Diff line number Diff line change
Expand Up @@ -287,7 +287,7 @@ class Publish extends BaseCommand {
} else {
manifest = await pacote.manifest(spec, {
...opts,
fullmetadata: true,
fullMetadata: true,
fullReadJson: true,
})
}
Expand Down
6 changes: 5 additions & 1 deletion workspaces/libnpmexec/lib/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -87,8 +87,10 @@ const missingFromTree = async ({ spec, tree, flatOptions, isNpxTree, shallow })
}

// see if the package.json at `path` has an entry that matches `cmd`
// the path is a known-local directory, not a user-supplied dep, so
// allow-directory must not gate this introspection
const hasPkgBin = (path, cmd, flatOptions) =>
pacote.manifest(path, flatOptions)
pacote.manifest(path, { ...flatOptions, allowDirectory: 'all' })
.then(manifest => manifest?.bin?.[cmd]).catch(() => null)

const exec = async (opts) => {
Expand Down Expand Up @@ -147,6 +149,8 @@ const exec = async (opts) => {
// we have to install the local package into the npx cache so that its
// bin links get set up
flatOptions.installLinks = false
// self-execution of a local bin, not a directory dep install
flatOptions.allowDirectory = 'all'
// args[0] will exist when the package is installed
packages.push(p)
yes = true
Expand Down
46 changes: 46 additions & 0 deletions workspaces/libnpmexec/test/local.js
Original file line number Diff line number Diff line change
Expand Up @@ -423,3 +423,49 @@ t.test('global scoped pkg', async t => {
created: 'global/node_modules/@npmcli/create-test/bin-file.js',
})
})

// Regression: local bin lookup must not be gated by allow-directory,
// even when the policy is `none` or `root`.
for (const allowDirectory of ['none', 'root']) {
t.test(`local bin still resolves with allow-directory=${allowDirectory}`, async t => {
const { pkg, fixtures } = createPkg({
version: '1.0.0',
name: '@npmcli/local-pkg-allow-directory-test',
bin: {
a: 'local-bin-test.js',
},
files: {
'local-bin-test.js': { key: 'local-bin', value: 'LOCAL PKG' },
},
})

const { exec, chmod, readOutput, path } = setup(t, {
pkg,
testdir: merge(
fixtures.packages[`@npmcli-local-pkg-allow-directory-test-1.0.0`],
{
node_modules: {
'@npmcli': {
'some-other-pkg-with-same-scope': {},
},
},
}
),
})

const localBin = resolve(path, 'node_modules', '.bin')

await chmod('local-bin-test.js')

await exec({
localBin,
args: ['a', 'argument-a'],
allowDirectory,
})

t.match(await readOutput('local-bin'), {
value: 'LOCAL PKG',
args: ['argument-a'],
})
})
}
Loading