Skip to content

Commit ef4144c

Browse files
Support limiting files added to self-hosted packages (#149)
## Motivation for the change, related issues Our self-hosted `@wp-playground/remote` package currently includes WordPress files when it should only include type definitions. Let's fix this. Fixes #146 ## Implementation details This updates our package-for-self-hosting Nx executor to support the package.json [files property](https://docs.npmjs.com/cli/v11/configuring-npm/package-json#files) which the `@wp-playground/remote` uses to limit its published files. ## Testing Instructions (or ideally a Blueprint) - Before applying this patch, run `npx nx run-many --all --target=package-for-self-hosting --hostingBaseUrl=http://127.0.0.1:1234` to get a baseline for comparison. - Apply this patch - Run `npx nx run-many --all --target=package-for-self-hosting --hostingBaseUrl=http://127.0.0.1:2345` - Compare the files in the packages created under `dist/packages-for-self-hosting`. - The only differences should be the different package.json dependency URLs and the files that are removed from `@wp-playground/remote` after this fix.
1 parent 35f7356 commit ef4144c

File tree

1 file changed

+53
-3
lines changed
  • packages/nx-extensions/src/executors/package-for-self-hosting

1 file changed

+53
-3
lines changed

packages/nx-extensions/src/executors/package-for-self-hosting/executor.ts

Lines changed: 53 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import type { ExecutorContext } from '@nx/devkit';
55
import { joinPathFragments, logger } from '@nx/devkit';
66
import type { PackageForSelfHostingExecutorSchema } from './schema';
77
import * as tar from 'tar-fs';
8+
import { globSync } from 'glob';
89

910
export default async function packageForSelfHostingExecutor(
1011
options: PackageForSelfHostingExecutorSchema,
@@ -102,15 +103,64 @@ export default async function packageForSelfHostingExecutor(
102103
const tarballPath = path.join(tarballOutputDir, tarballFileName);
103104
const tarballWriteStream = fs.createWriteStream(tarballPath);
104105

106+
// NOTE: A package can declare which files should be included when it is installed
107+
// as a dependency by declaring a "files" property in its package.json.
108+
// https://docs.npmjs.com/cli/v11/configuring-npm/package-json#files
109+
//
110+
// We use it to limit the published files for some packages and need to support it here.
111+
let globs = packageJson.files ? packageJson.files : ['**/*'];
112+
// NOTE: There were issues with figuring out how to resolve absolute globs
113+
// that were actually relative to the project root, so we just make all globs relative.
114+
globs = globs.map(function makeGlobRelative(glob: string) {
115+
return glob.startsWith('/') ? glob.slice(1) : glob;
116+
});
117+
const matchingPaths = globSync(globs, { cwd: builtPackagePath });
118+
119+
const matchingFiles = new Set<string>();
120+
const matchingDirs: string[] = [];
121+
for (const matchingPath of matchingPaths) {
122+
const absolutePath = path.join(builtPackagePath, matchingPath);
123+
if (fs.statSync(absolutePath).isDirectory()) {
124+
matchingDirs.push(matchingPath);
125+
} else {
126+
matchingFiles.add(matchingPath);
127+
}
128+
}
129+
105130
await new Promise((resolve, reject) => {
106131
const pack = tar.pack(builtPackagePath, {
107-
ignore: function isPackageJson(name) {
108-
return (
132+
// NOTE: AFAICT, tar-fs does not support specifying multiple directories
133+
// to add to the tarball, so we tell it to add everything and then exclude
134+
// undesired files using this ignore() function.
135+
ignore(name) {
136+
// Ignore package.json because we will add a patched version later
137+
if (
109138
path.dirname(name) === builtPackagePath &&
110139
path.basename(name) === 'package.json'
140+
) {
141+
return true;
142+
}
143+
144+
const relativeName = path.relative(builtPackagePath, name);
145+
if (matchingFiles.has(relativeName)) {
146+
// This file is specifically included with the package.
147+
return false;
148+
}
149+
150+
const isMatchingDirChild = matchingDirs.some(
151+
(dir) =>
152+
dir === relativeName ||
153+
relativeName.startsWith(`${dir}/`)
111154
);
155+
if (isMatchingDirChild) {
156+
// This file is under a directory that is included with the package.
157+
return false;
158+
}
159+
160+
return true;
112161
},
113-
map: function prefixWithPackageDir(header) {
162+
map(header) {
163+
// Place all files under a top-level 'package' directory as expected by npm.
114164
header.name = path.join('package', header.name);
115165
return header;
116166
},

0 commit comments

Comments
 (0)