diff --git a/lib/index.js b/lib/index.js index 5212c87..3627be1 100644 --- a/lib/index.js +++ b/lib/index.js @@ -165,14 +165,34 @@ class PackWalker extends IgnoreWalker { // copies the root's `ignoreFiles` value, but we don't want to respect package.json for // subdirectories, so we override it with a list that intentionally omits package.json walkerOpt (entry, opts) { + let ignoreFiles = [ + defaultRules, + '.npmignore', + '.gitignore', + strictRules, + ] + + // however, if we have a tree, and we have workspaces, and the directory we're about + // to step into is a workspace, then we _do_ want to respect its package.json + if (this.tree && this.tree.workspaces) { + const workspaceDirs = [...this.tree.workspaces.values()] + .map((dir) => dir.replace(/\\/g, '/')) + + const entryPath = join(this.path, entry).replace(/\\/g, '/') + if (workspaceDirs.includes(entryPath)) { + ignoreFiles = [ + defaultRules, + 'package.json', + '.npmignore', + '.gitignore', + strictRules, + ] + } + } + return { ...super.walkerOpt(entry, opts), - ignoreFiles: [ - defaultRules, - '.npmignore', - '.gitignore', - strictRules, - ], + ignoreFiles, // we map over our own requiredFiles and pass ones that are within this entry requiredFiles: this.requiredFiles .map((file) => { diff --git a/test/bundled-file-in-workspace.js b/test/bundled-file-in-workspace.js new file mode 100644 index 0000000..695eb26 --- /dev/null +++ b/test/bundled-file-in-workspace.js @@ -0,0 +1,88 @@ +'use strict' + +const t = require('tap') +const packlist = require('../') + +t.test('correctly filters files from workspace subdirectory', async (t) => { + const pkg = t.testdir({ + 'package.json': JSON.stringify({ + name: 'root', + version: '1.0.0', + files: ['docs/*.txt'], + main: 'index.js', + workspaces: ['./docs'], + }), + 'index.js': '', + docs: { + 'package.json': JSON.stringify({ + name: 'docs', + version: '1.0.0', + main: 'index.js', + files: ['*.txt'], + }), + 'bar.txt': '', + 'foo.txt': '', + 'readme.md': '', + test: { + 'index.js': '', + }, + }, + }) + + const files = await packlist({ path: pkg }) + t.same(files, [ + 'index.js', + 'package.json', + 'docs/readme.md', // readme.md is always included + 'docs/bar.txt', + 'docs/foo.txt', + ]) +}) + +t.test('does not filter based on package.json if subdirectory is not a workspace', async (t) => { + const pkg = t.testdir({ + 'package.json': JSON.stringify({ + name: 'root', + version: '1.0.0', + files: ['docs/*.txt'], + main: 'index.js', + // this test needs a workspace to exist, but that workspace cannot be the one we include + // files from + workspaces: ['./unrelated'], + }), + 'index.js': '', + docs: { + 'package.json': JSON.stringify({ + name: 'docs', + version: '1.0.0', + main: 'index.js', + files: ['bar.txt', 'foo.txt'], + }), + 'bar.txt': '', + 'baz.txt': '', + 'foo.txt': '', + 'readme.md': '', + test: { + 'index.js': '', + }, + }, + unrelated: { + 'package.json': JSON.stringify({ + name: 'unrelated', + version: '1.0.0', + main: 'index.js', + }), + 'index.js': '', + }, + }) + + const files = await packlist({ path: pkg }) + t.same(files, [ + 'index.js', + 'package.json', + 'docs/readme.md', // readme.md is always included + 'docs/bar.txt', + 'docs/baz.txt', // was _not_ filtered + 'docs/foo.txt', + ]) +})