Skip to content

Commit e905f74

Browse files
authored
Yarn Plug'n'Play: Implementation (#6382)
* Initial pnp implementation * Adds the pnp-env directory for quick checks * Improves the "yarn node" command so that it works with pnp Branch: yarn-node-pnp * Adds the pnp tests to the pkg-tests testsuite Branch: pkg-tests * Fixes various issues with the pnp map generation Branch: pnp-map-improvements * Remove the scriptsPrependNodePath option Branch: lifecycle-wrappers-remove-option * Adds tests to ensure that the lifecycle scripts are called with the right binaries Branch: lifecycle-wrappers-tests * Fixes linting Branch: lifecycle-wrappers-flowlint * Improve the error message when an optional required dependency hasn't been installed Branch: lifecycle-wrappers-improve-pnp-error * Implements lifecycle wrappers Branch: lifecycle-wrappers-main * Adds .pnp.js files to the gitignore * Fallbacks to the toplevel dependencies when a transitive dependency cannot be resolved * Fixes an issue inside the pkg-tests helper Branch: pkg-tests-helper-definition * Improves the fixtures so that they also return info about their dev and peer dependencies Branch: dev-peer-fixtures * Finishes to hide plugnplay behind a yarnrc option (`plugnplay-experimental`) Branch: option-plugnplay-experimental * Adds failing tests for pnp peer dependencies Branch: pnp-peer-dependencies-failing * Prettifies the generated pnp files * Adds the plugnplay flag to the integrity check * Removes the pnp file at link-time if installing with pnp disabled * Improves pnp maps compatibility * Prevents "yarn check" from checking the node_modules existence when under pnp * Adds a missing package to the request cache * Fixes tests Branch: pnp-fix-tests * Reimplements the resolution to correctly account for peer dependencies Branch: better-faster-stronger * Externalizes the creation of proxy scripts Branch: portable-proxy-scripts * Implements support for `yarn run` within pnp-enabled installations Branch: pnp-yarn-run * Makes it possible for dependency binaries to require their own dependencies Branch: pnp-yarn-run-dependencies * Moves the pnp embed api into its own file * Adds the test folder to Jest error messages Branch: jest-better-message * Improves peer dependency tests Branch: peer-deps-tests * Adds tests for require.resolve Branch: require-resolve-tests * Refactors the pnp file Branch: pnp-file-refactoring * Updates the build-webpack script to include a custom resolver Branch: webpack-resolver * Fixes tests Branch: fix-tests * Generates virtual when using peer dependencies Branch: virtual-packages * Refactors the generated pnp files to use the newly generated maps Branch: pnp-refactor-find * Implements Module._findPath Branch: module-findpath * Adds tests for workspaces Branch: workspace-tests * Fixes top level detection Branch: fix-top-level-detection * Implements workspaces support in pnp Branch: pnp-workspaces * Automatically adds workspaces as dependencies of the top-level Branch: auto-workspace-dependencies * Updates the cache path to include the 'node_modules' string Branch: node-modules-cache * Prevents pnp from bootstrapping when running non-pnp-installed scripts Branch: fix-npm-run * Installs peer dependencies symlinks inside a project folder Branch: per-project-virtual-deps * Adds a sample application that showcases webpack, babel, react, jest Branch: sample-app * Ignores the .pnp directory Branch: ignore-pnp * Implements a blacklist that throws nicer errors when a package is required through a realpath'd path. Branch: location-blacklist * Changes the order the locations are matched to package locators Branch: location-to-locator-match-order * Automatically adds packages as dependencies of themselves if possible Branch: implicit-self * Updates the node resolution Branch: node-resolution-improvements * Ensures that binaries are set as executable in the cache Branch: chmod-bins * Disables integrity checks when running under pnp Branch: pnp-no-integrity * Makes the .pnp.js file an actual executable that can be used as a resolution server Branch: pnp-executable * Removes pnp-env * Fixes a few tests * Fixes snapshots * Fixes the lockfile not being written when using pnp Branch: fix-lockfile * Fixes the `yarn node` command being incorrectly forwarded arguments Branch: fix-yarn-node * Uses symlinks instead of a script for bin indirection to allow calling them directly through Node Branch: bin-symlinks * Adds a `yarn bin <name>` command that returns the path of the specified bin on the disk Branch: yarn-bin-name * Implements an --into option to yarn node/yarn run Branch: opt-into * Implements the `--pnp` option Branch: pnp-option * Adds new tests for checking that packages are correctly locked Branch: lock-tests * Bugfixes This diff ships with two fixes: - Fixes calling a pnp script from a non-pnp scripts - Fixes relative requires from binaries It also adds tests for all those cases Branch: bugfixes * Fixes workspace registration Branch: workspace-registration-fix * Uses --enable-pnp (alias --pnp) and --disable-pnp Branch: instalconfig-pnp * Adds the issuer into the error messages when requesting a package one shouldn't have access to. Branch: via-issuer * Implements extendedQualifiedPathResolution Branch: extended-qualified-path-resolution * Changes the return of the pnp daemon to return json data * Implements custom shebangs for the pnp file * Changes the return of the pnp-exposed functions to return null with builtins * Various fixes & improvements * Adds a test, prettier, fixes a test * Don't iterate on the registries * Renames YARN_PLUGNPLAY_EXPERIMENTAL into YARN_PLUGNPLAY_OVERRIDE * Avoids touching the .pnp.js file when it doesn't need to change * Reworks the cache path to contain the "node_modules/<pkg-name>" string * Shims resolve#isCore * Improves error messages * Fixes the environment cast to allow passing false/0 * Implements a pnp blacklist settings * Fixes the fallback resolution to use _resolveFilename instead of _finePath * Fixes fallback relative path resolution * Implements require.cache * Prevents pnp from being enabled on Windows * Removes absolute paths from the pnp files * Implements a super basic offline cache integration * feat(pnp): eject package command (#92) * test(pnp): support ejecting packages * feat(pnp): eject package command * test(pnp): use fs.readdir instead of fs.readdirSync * test(pnp): do not expect specific error message * refactor(pnp): move eject logic to package linker * fix(pnp): change ejected folder to .pnp/ejected/pkgName-pkgVersion/node_modules/pkgName * fix(pnp): do not re-eject package * test(pnp): do not rely on installConfig * Fixes yarn bin * Preserves the node_modules components in zip paths * Fixes the offline cache * Adds a VERSIONS field into the generated resolver * Exposes the "extensions" option to "resolveRequest" * Renames yarn eject into yarn unplug * Tweaks yarn unplug * Removes packageMainEntry from the package information * Makes "unplug" print the list of unplugged packages * Unplugs postinstall packages automatically * Renames things * Adds a warning on Windows to notify that PnP settings are ignored at the moment * Fixes the default shebang * Exports pnpapi * Reworks the resolve shim to only affect liftoff * Guards the pnp file against fs extensions * Fixes the resolve shim * Fixes a broken test * Re-enables the focus tests * Stops relying on bash for test scripts * Fixes nohoist * Revert "Fixes a broken test" This reverts commit 84358aa. * Ensures that the getPackageInformation function returns an absolute path
1 parent 5682d55 commit e905f74

File tree

109 files changed

+5030
-501
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

109 files changed

+5030
-501
lines changed

.babelrc

+1
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,7 @@
5252
"stage-0"
5353
],
5454
"plugins": [
55+
["babel-plugin-inline-import", { "extensions": [ ".tpl.js" ] }],
5556
["transform-inline-imports-commonjs"],
5657
["transform-runtime", { "polyfill": false, "regenerator": true }]
5758
]

.gitignore

+2
Original file line numberDiff line numberDiff line change
@@ -21,5 +21,7 @@ test/fixtures/**/.fbkpm
2121
/__tests__/fixtures/request-cache/GET/localhost/.bin
2222
.idea
2323
.yarn-meta
24+
.pnp.js
25+
.pnp
2426
/packages/lockfile/index.js
2527
.vscode/

__tests__/commands/install/integration.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -236,7 +236,7 @@ test('changes the cache path when bumping the cache version', () =>
236236

237237
await mockConstants(config, {CACHE_VERSION: 42}, async config => {
238238
await cache(config, reporter, {}, ['dir']);
239-
expect((JSON.parse(String(inOut.read())): any).data).toMatch(/[\\\/]v42[\\\/]?$/);
239+
expect((JSON.parse(String(inOut.read())): any).data).toMatch(/[\\\/]v42([\\\/].*)?$/);
240240
});
241241
}));
242242

__tests__/integration.js

+1
Original file line numberDiff line numberDiff line change
@@ -506,6 +506,7 @@ test('relative cache folder', async () => {
506506

507507
const [stdoutOutput, _] = await runYarn(['cache', 'dir'], {cwd: `${base}/sub`});
508508

509+
// The dirname is to remove the "v2" part
509510
expect(await fs.realpath(path.dirname(stdoutOutput.toString()))).toEqual(await fs.realpath(`${base}/foo`));
510511
});
511512

__tests__/lifecycle-scripts.js

+5-5
Original file line numberDiff line numberDiff line change
@@ -48,31 +48,31 @@ async function execCommand(cmd: string, packageName: string, env = process.env):
4848

4949
test.concurrent('should add the global yarnrc arguments to the command line', async () => {
5050
const stdout = await execCommand('cache dir', 'yarnrc-cli');
51-
expect(stdout.replace(/\\/g, '/')).toMatch(/^(C:)?\/tmp\/foobar\/v[0-9]+\n$/);
51+
expect(stdout.replace(/\\/g, '/')).toMatch(/^(C:)?\/tmp\/foobar\/v[0-9]+(\/.*)?\n$/);
5252
});
5353

5454
test.concurrent(
5555
'should add the command-specific yarnrc arguments to the command line if the command name matches',
5656
async () => {
5757
const stdout = await execCommand('cache dir', 'yarnrc-cli-command-specific-ok');
58-
expect(stdout.replace(/\\/g, '/')).toMatch(/^(C:)?\/tmp\/foobar\/v[0-9]+\n$/);
58+
expect(stdout.replace(/\\/g, '/')).toMatch(/^(C:)?\/tmp\/foobar\/v[0-9]+(\/.*)?\n$/);
5959
},
6060
);
6161

6262
test.concurrent("should not add the command-specific yarnrc arguments if the command name doesn't match", async () => {
6363
const stdout = await execCommand('cache dir', 'yarnrc-cli-command-specific-ko');
64-
expect(stdout.replace(/\\/g, '/')).not.toMatch(/^(C:)?\/tmp\/foobar\/v[0-9]+\n$/);
64+
expect(stdout.replace(/\\/g, '/')).not.toMatch(/^(C:)?\/tmp\/foobar\/v[0-9]+(\/.*)?\n$/);
6565
});
6666

6767
test.concurrent('should allow overriding the yarnrc values from the command line', async () => {
6868
const stdout = await execCommand('cache dir --cache-folder /tmp/toto', 'yarnrc-cli');
69-
expect(stdout.replace(/\\/g, '/')).toMatch(/^(C:)?\/tmp\/toto\/v[0-9]+\n$/);
69+
expect(stdout.replace(/\\/g, '/')).toMatch(/^(C:)?\/tmp\/toto\/v[0-9]+(\/.*)?\n$/);
7070
});
7171

7272
// Test disabled for now, cf rc.js
7373
test.concurrent('should resolve the yarnrc values relative to where the file lives', async () => {
7474
const stdout = await execCommand('cache dir', 'yarnrc-cli-relative');
75-
expect(stdout.replace(/\\/g, '/')).toMatch(/^(C:)?(\/[^\/]+)+\/foobar\/hello\/world\/v[0-9]+\n$/);
75+
expect(stdout.replace(/\\/g, '/')).toMatch(/^(C:)?(\/[^\/]+)+\/foobar\/hello\/world\/v[0-9]+(\/.*)?\n$/);
7676
});
7777

7878
test.concurrent(

__tests__/package-resolver.js

+3-3
Original file line numberDiff line numberDiff line change
@@ -13,8 +13,8 @@ jasmine.DEFAULT_TIMEOUT_INTERVAL = 90000;
1313

1414
const path = require('path');
1515

16-
// regexp which verifies that cache path contains semver + hash
17-
const cachePathRe = /-\d+\.\d+\.\d+-[\dabcdef]{40}$/;
16+
// regexp which verifies that the cache path contains a path component ending with semver + hash
17+
const cachePathRe = /-\d+\.\d+\.\d+-[\dabcdef]{40}[\\\/]/;
1818

1919
async function createEnv(configOptions): Object {
2020
const lockfile = new Lockfile();
@@ -82,7 +82,7 @@ addTest(
8282
8383
'npm',
8484
async cacheFolder => {
85-
const folder = path.join(cacheFolder, 'npm-@foo', 'bar');
85+
const folder = path.join(cacheFolder, 'npm-@foo-bar', 'node_modules', '@foo', 'bar');
8686
await fs.mkdirp(folder);
8787
await fs.writeFile(
8888
path.join(folder, constants.METADATA_FILENAME),

package.json

+1
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,7 @@
5757
"babel-eslint": "^7.2.3",
5858
"babel-loader": "^6.2.5",
5959
"babel-plugin-array-includes": "^2.0.3",
60+
"babel-plugin-inline-import": "^2.0.6",
6061
"babel-plugin-transform-builtin-extend": "^1.1.2",
6162
"babel-plugin-transform-inline-imports-commonjs": "^1.0.0",
6263
"babel-plugin-transform-runtime": "^6.4.3",

packages/pkg-tests/package.json

+1-1
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010
"babel-preset-env": "^1.6.1",
1111
"babel-preset-flow": "^6.23.0",
1212
"flow-bin": "^0.66.0",
13-
"jest": "^22.3.0",
13+
"jest": "^23.0.0",
1414
"prettier": "^1.10.2"
1515
},
1616
"scripts": {

packages/pkg-tests/pkg-tests-core/sources/utils/fs.js

+6-2
Original file line numberDiff line numberDiff line change
@@ -174,8 +174,12 @@ exports.readJson = async function readJson(source: string): Promise<any> {
174174
}
175175
};
176176

177-
exports.chmod = function chmod(target: string, mod: number): Promise<void> {
178-
return fs.chmod(target, mod);
177+
exports.chmod = async function chmod(target: string, mod: number): Promise<void> {
178+
await fs.chmod(target, mod);
179+
};
180+
181+
exports.realpath = function realpath(source: string): Promise<string> {
182+
return fs.realpath(source);
179183
};
180184

181185
exports.makeFakeBinary = async function(

packages/pkg-tests/pkg-tests-core/sources/utils/tests.js

+37-8
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,17 @@ export type PackageRunDriver = (
2222

2323
export type PackageDriver = any;
2424

25+
let whitelist = new Map();
26+
27+
exports.setPackageWhitelist = async function whitelistPackages(
28+
packages: Map<string, Set<string>>,
29+
fn: () => Promise<void>,
30+
) {
31+
whitelist = packages;
32+
await fn();
33+
whitelist = new Map();
34+
};
35+
2536
exports.getPackageRegistry = function getPackageRegistry(): Promise<PackageRegistry> {
2637
if (getPackageRegistry.promise) {
2738
return getPackageRegistry.promise;
@@ -182,7 +193,12 @@ exports.startPackageServer = function startPackageServer(): Promise<string> {
182193
return processError(res, 404, `Package not found: ${name}`);
183194
}
184195

185-
const versions = Array.from(packageEntry.keys());
196+
let versions = Array.from(packageEntry.keys());
197+
198+
const whitelistedVersions = whitelist.get(name);
199+
if (whitelistedVersions) {
200+
versions = versions.filter(version => whitelistedVersions.has(version));
201+
}
186202

187203
const data = JSON.stringify({
188204
name,
@@ -300,29 +316,42 @@ exports.generatePkgDriver = function generatePkgDriver({runDriver}: {|runDriver:
300316
}
301317

302318
return async function(): Promise<void> {
303-
const path = await fsUtils.createTemporaryFolder();
319+
const path = await fsUtils.realpath(await fsUtils.createTemporaryFolder());
304320

305321
const registryUrl = await exports.startPackageServer();
306322

307323
// Writes a new package.json file into our temporary directory
308324
await fsUtils.writeJson(`${path}/package.json`, await deepResolve(packageJson));
309325

310326
const run = (...args) => {
327+
let callDefinition = {};
328+
329+
if (args.length > 0 && typeof args[args.length - 1] === 'object') {
330+
callDefinition = args.pop();
331+
}
332+
311333
return runDriver(path, args, {
312334
registryUrl,
335+
...definition,
313336
...subDefinition,
337+
...callDefinition,
314338
});
315339
};
316340

317341
const source = async script => {
318-
return JSON.parse((await run('node', '-p', `JSON.stringify(${script})`)).stdout.toString());
342+
return JSON.parse((await run('node', '-p', `JSON.stringify((() => ${script})())`)).stdout.toString());
319343
};
320344

321-
await fn({
322-
path,
323-
run,
324-
source,
325-
});
345+
try {
346+
await fn({
347+
path,
348+
run,
349+
source,
350+
});
351+
} catch (error) {
352+
error.message = `Temporary fixture folder: ${path}\n\n` + error.message;
353+
throw error;
354+
}
326355
};
327356
};
328357

packages/pkg-tests/pkg-tests-fixtures/default-index.js

+5-3
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,9 @@
22

33
module.exports = require(`./package.json`);
44

5-
for (const key of Object.keys(module.exports.dependencies || {})) {
6-
// $FlowFixMe The whole point of this file is to be dynamic
7-
module.exports.dependencies[key] = require(key);
5+
for (const key of [`dependencies`, `devDependencies`, `peerDependencies`]) {
6+
for (const dep of Object.keys(module.exports[key] || {})) {
7+
// $FlowFixMe The whole point of this file is to be dynamic
8+
module.exports[key][dep] = require(dep);
9+
}
810
}
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,10 @@
1+
/* @flow */
2+
13
module.exports = require(`./package.json`);
24

3-
for (const key of Object.keys(module.exports.dependencies || {})) {
4-
module.exports.dependencies[key] = require(key);
5+
for (const key of [`dependencies`, `devDependencies`, `peerDependencies`]) {
6+
for (const dep of Object.keys(module.exports[key] || {})) {
7+
// $FlowFixMe The whole point of this file is to be dynamic
8+
module.exports[key][dep] = require(dep);
9+
}
510
}
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,10 @@
1+
/* @flow */
2+
13
module.exports = require(`./package.json`);
24

3-
for (const key of Object.keys(module.exports.dependencies || {})) {
4-
module.exports.dependencies[key] = require(key);
5+
for (const key of [`dependencies`, `devDependencies`, `peerDependencies`]) {
6+
for (const dep of Object.keys(module.exports[key] || {})) {
7+
// $FlowFixMe The whole point of this file is to be dynamic
8+
module.exports[key][dep] = require(dep);
9+
}
510
}
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,10 @@
1+
/* @flow */
2+
13
module.exports = require(`./package.json`);
24

3-
for (const key of Object.keys(module.exports.dependencies || {})) {
4-
module.exports.dependencies[key] = require(key);
5+
for (const key of [`dependencies`, `devDependencies`, `peerDependencies`]) {
6+
for (const dep of Object.keys(module.exports[key] || {})) {
7+
// $FlowFixMe The whole point of this file is to be dynamic
8+
module.exports[key][dep] = require(dep);
9+
}
510
}
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,10 @@
1+
/* @flow */
2+
13
module.exports = require(`./package.json`);
24

3-
for (const key of Object.keys(module.exports.dependencies || {})) {
4-
module.exports.dependencies[key] = require(key);
5+
for (const key of [`dependencies`, `devDependencies`, `peerDependencies`]) {
6+
for (const dep of Object.keys(module.exports[key] || {})) {
7+
// $FlowFixMe The whole point of this file is to be dynamic
8+
module.exports[key][dep] = require(dep);
9+
}
510
}
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,10 @@
1+
/* @flow */
2+
13
module.exports = require(`./package.json`);
24

3-
for (const key of Object.keys(module.exports.dependencies || {})) {
4-
module.exports.dependencies[key] = require(key);
5+
for (const key of [`dependencies`, `devDependencies`, `peerDependencies`]) {
6+
for (const dep of Object.keys(module.exports[key] || {})) {
7+
// $FlowFixMe The whole point of this file is to be dynamic
8+
module.exports[key][dep] = require(dep);
9+
}
510
}
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,10 @@
1+
/* @flow */
2+
13
module.exports = require(`./package.json`);
24

3-
for (const key of Object.keys(module.exports.dependencies || {})) {
4-
module.exports.dependencies[key] = require(key);
5+
for (const key of [`dependencies`, `devDependencies`, `peerDependencies`]) {
6+
for (const dep of Object.keys(module.exports[key] || {})) {
7+
// $FlowFixMe The whole point of this file is to be dynamic
8+
module.exports[key][dep] = require(dep);
9+
}
510
}
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,10 @@
1+
/* @flow */
2+
13
module.exports = require(`./package.json`);
24

3-
for (const key of Object.keys(module.exports.dependencies || {})) {
4-
module.exports.dependencies[key] = require(key);
5+
for (const key of [`dependencies`, `devDependencies`, `peerDependencies`]) {
6+
for (const dep of Object.keys(module.exports[key] || {})) {
7+
// $FlowFixMe The whole point of this file is to be dynamic
8+
module.exports[key][dep] = require(dep);
9+
}
510
}
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,10 @@
1+
/* @flow */
2+
13
module.exports = require(`./package.json`);
24

3-
for (const key of Object.keys(module.exports.dependencies || {})) {
4-
module.exports.dependencies[key] = require(key);
5+
for (const key of [`dependencies`, `devDependencies`, `peerDependencies`]) {
6+
for (const dep of Object.keys(module.exports[key] || {})) {
7+
// $FlowFixMe The whole point of this file is to be dynamic
8+
module.exports[key][dep] = require(dep);
9+
}
510
}
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,10 @@
1+
/* @flow */
2+
13
module.exports = require(`./package.json`);
24

3-
for (const key of Object.keys(module.exports.dependencies || {})) {
4-
module.exports.dependencies[key] = require(key);
5+
for (const key of [`dependencies`, `devDependencies`, `peerDependencies`]) {
6+
for (const dep of Object.keys(module.exports[key] || {})) {
7+
// $FlowFixMe The whole point of this file is to be dynamic
8+
module.exports[key][dep] = require(dep);
9+
}
510
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
#!/usr/bin/env node
2+
3+
console.log(process.cwd());
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
#!/usr/bin/env node
2+
3+
const secret = require('./secret');
4+
5+
console.log(secret);
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
#!/usr/bin/env node
2+
3+
const noDeps = require('no-deps');
4+
5+
console.log(noDeps.name);
6+
console.log(noDeps.version);
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
#!/usr/bin/env node
2+
3+
for (let t = 2; t < process.argv.length; ++t) {
4+
console.log(process.argv[t]);
5+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
/* @flow */
2+
3+
module.exports = require(`./package.json`);
4+
5+
for (const key of [`dependencies`, `devDependencies`, `peerDependencies`]) {
6+
for (const dep of Object.keys(module.exports[key] || {})) {
7+
// $FlowFixMe The whole point of this file is to be dynamic
8+
module.exports[key][dep] = require(dep);
9+
}
10+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
{
2+
"name": "has-bin-entries",
3+
"version": "1.0.0",
4+
"bin": {
5+
"has-bin-entries": "./bin.js",
6+
"has-bin-entries-with-require": "./bin-with-require.js",
7+
"has-bin-entries-with-relative-require": "./bin-with-relative-require.js",
8+
"has-bin-entries-get-pwd": "./bin-get-pwd.js"
9+
},
10+
"dependencies": {
11+
"no-deps": "1.0.0"
12+
}
13+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
module.exports = 42;
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,10 @@
1+
/* @flow */
2+
13
module.exports = require(`./package.json`);
24

3-
for (const key of Object.keys(module.exports.dependencies || {})) {
4-
module.exports.dependencies[key] = require(key);
5+
for (const key of [`dependencies`, `devDependencies`, `peerDependencies`]) {
6+
for (const dep of Object.keys(module.exports[key] || {})) {
7+
// $FlowFixMe The whole point of this file is to be dynamic
8+
module.exports[key][dep] = require(dep);
9+
}
510
}

0 commit comments

Comments
 (0)