Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(link): Use publishConfig.directory as symlink source if it exists to allow linking sub-directories #2274

Merged
merged 16 commits into from Oct 10, 2019
Merged
Show file tree
Hide file tree
Changes from 15 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
12 changes: 12 additions & 0 deletions commands/bootstrap/README.md
Expand Up @@ -198,6 +198,18 @@ $ lerna bootstrap --force-local

When passed, this flag causes the `bootstrap` command to always symlink local dependencies regardless of matching version range.

### `publishConfig.directory`

This _non-standard_ field allows you to customize the symlinked subdirectory that will be the _source_ directory of the symlink, just like how the published package would be consumed.

```json
"publishConfig": {
"directory": "dist"
}
```

In this example, when this package is bootstrapped and linked, the `dist` directory will be the source directory (e.g. `package-1/dist => node_modules/package-1`).

## How It Works

Let's use `babel` as an example.
Expand Down
@@ -0,0 +1,4 @@
{
"ci": false,
kamranayub marked this conversation as resolved.
Show resolved Hide resolved
"version": "1.0.0"
}
@@ -0,0 +1,8 @@
{
"name": "basic",
"version": "monorepo",
"private": true,
"dependencies": {
"bar": "^2.0.0"
}
}
@@ -0,0 +1,4 @@
{
"name": "@test/package-1",
"version": "1.0.0"
}
@@ -0,0 +1,3 @@
#!/usr/bin/env node
/* eslint-disable node/shebang */
console.log("Hello, world!");
@@ -0,0 +1,8 @@
{
"name": "@test/package-2",
"version": "1.0.0",
"bin": "cli.js",
"dependencies": {
"@test/package-1": "^10.0.0"
}
}
@@ -0,0 +1,3 @@
#!/usr/bin/env node
/* eslint-disable node/shebang */
console.log("Hello, world!");
@@ -0,0 +1,3 @@
#!/usr/bin/env node
/* eslint-disable node/shebang */
console.log("Hello, world!");
@@ -0,0 +1,12 @@
{
"name": "@test/package-3",
"version": "1.0.0",
"bin": {
"package3cli1": "cli1.js",
"package3cli2": "cli2.js"
},
"devDependencies": {
"@test/package-1": "^10.0.0",
"@test/package-2": "^10.0.0"
}
}
@@ -0,0 +1,8 @@
{
"name": "package-4",
"version": "1.0.0",
"dependencies": {
"@test/package-1": "^10.0.0",
"@test/package-3": "^10.0.0"
}
}
Expand Up @@ -313,6 +313,46 @@ Array [
]
`;

exports[`BootstrapCommand with local package dependencies should respect --contents when linking directories 1`] = `
Array [
Object {
"_src": "packages/package-1/dist",
"dest": "packages/package-2/node_modules/@test/package-1",
"type": "junction",
},
Object {
"_src": "packages/package-1/dist",
"dest": "packages/package-3/node_modules/@test/package-1",
"type": "junction",
},
Object {
"_src": "packages/package-2/dist",
"dest": "packages/package-3/node_modules/@test/package-2",
"type": "junction",
},
Object {
"_src": "packages/package-2/dist/cli.js",
"dest": "packages/package-3/node_modules/.bin/package-2",
"type": "exec",
},
Object {
"_src": "packages/package-3/dist",
"dest": "packages/package-4/node_modules/package-3",
"type": "junction",
},
Object {
"_src": "packages/package-3/dist/cli1.js",
"dest": "packages/package-4/node_modules/.bin/package3cli1",
"type": "exec",
},
Object {
"_src": "packages/package-3/dist/cli2.js",
"dest": "packages/package-4/node_modules/.bin/package3cli2",
"type": "exec",
},
]
`;

exports[`BootstrapCommand with local package dependencies should respect --force-local 1`] = `
Object {
"packages/package-1": Array [
Expand Down
8 changes: 8 additions & 0 deletions commands/bootstrap/__tests__/bootstrap-command.test.js
Expand Up @@ -345,6 +345,14 @@ describe("BootstrapCommand", () => {
});
});

it("should respect --contents when linking directories", async () => {
const testDir = await initFixture("basic");

await lernaBootstrap(testDir)("--contents", "dist");

expect(symlinkedDirectories(testDir)).toMatchSnapshot();
});

it("should not update package.json when filtering", async () => {
const testDir = await initFixture("basic");

Expand Down
6 changes: 6 additions & 0 deletions commands/bootstrap/command.js
Expand Up @@ -58,6 +58,12 @@ exports.builder = yargs => {
describe: "Don't allow warnings when hoisting as it causes longer bootstrap times and other issues.",
type: "boolean",
},
contents: {
group: "Command Options:",
describe: "Subdirectory to use as the source of any links. Must apply to ALL packages.",
type: "string",
defaultDescription: ".",
},
});

return filterable(yargs);
Expand Down
7 changes: 7 additions & 0 deletions commands/bootstrap/index.js
Expand Up @@ -160,6 +160,13 @@ class BootstrapCommand extends Command {
chain = chain.then(filteredPackages => {
this.filteredPackages = filteredPackages;

if (this.options.contents) {
// globally override directory to link
for (const pkg of filteredPackages) {
pkg.contents = this.options.contents;
}
}

if (filteredPackages.length !== this.targetGraph.size && !this.options.forceLocal) {
this.logger.warn("bootstrap", "Installing local packages that do not match filters from registry");

Expand Down
12 changes: 12 additions & 0 deletions commands/link/README.md
Expand Up @@ -21,3 +21,15 @@ $ lerna link --force-local
```

When passed, this flag causes the `link` command to always symlink local dependencies regardless of matching version range.

### `publishConfig.directory`

This _non-standard_ field allows you to customize the symlinked subdirectory that will be the _source_ directory of the symlink, just like how the published package would be consumed.

```json
"publishConfig": {
"directory": "dist"
}
```

In this example, when this package is linked, the `dist` directory will be the source directory (e.g. `package-1/dist => node_modules/package-1`).
3 changes: 3 additions & 0 deletions commands/link/__tests__/__fixtures__/with-contents/lerna.json
@@ -0,0 +1,3 @@
{
"version": "1.0.0"
}
@@ -0,0 +1,3 @@
{
"name": "independent"
}
@@ -0,0 +1,7 @@
{
"name": "@test/package-1",
"version": "1.0.0",
"publishConfig": {
"directory": "dist"
evocateur marked this conversation as resolved.
Show resolved Hide resolved
}
}
@@ -0,0 +1,3 @@
#!/usr/bin/env node
/* eslint-disable node/shebang */
console.log("Hello, world!");
@@ -0,0 +1,11 @@
{
"name": "@test/package-2",
"version": "1.0.0",
"publishConfig": {
"directory": "dist"
},
"bin": "cli.js",
"dependencies": {
"@test/package-1": "^1.0.0"
}
}
@@ -0,0 +1,3 @@
#!/usr/bin/env node
/* eslint-disable node/shebang */
console.log("Hello, world!");
@@ -0,0 +1,3 @@
#!/usr/bin/env node
/* eslint-disable node/shebang */
console.log("Hello, world!");
@@ -0,0 +1,3 @@
#!/usr/bin/env node
/* eslint-disable node/shebang */
console.log("Hello, world!");
@@ -0,0 +1,15 @@
{
"name": "package-3",
"version": "1.0.0",
"publishConfig": {
"directory": "dist"
},
"bin": {
"package3cli1": "cli1.js",
"package3cli2": "cli2.js"
},
"devDependencies": {
"@test/package-1": "^1.0.0",
"@test/package-2": "^1.0.0"
}
}
@@ -0,0 +1,3 @@
#!/usr/bin/env node
/* eslint-disable node/shebang */
console.log("Hello, world!");
@@ -0,0 +1,3 @@
#!/usr/bin/env node
/* eslint-disable node/shebang */
console.log("Hello, world!");
@@ -0,0 +1,11 @@
{
"name": "package-4",
"version": "1.0.0",
"publishConfig": {
"directory": "dist"
},
"dependencies": {
"@test/package-1": "^0.0.0",
"package-3": "^1.0.0"
}
}
94 changes: 94 additions & 0 deletions commands/link/__tests__/link-command.test.js
Expand Up @@ -87,6 +87,53 @@ Array [
});
});

describe("with publishConfig.directory", () => {
it("should symlink sub-directory of package folders and bin directories", async () => {
const testDir = await initFixture("with-contents");
await lernaLink(testDir)();

expect(symlinkedDirectories(testDir)).toMatchInlineSnapshot(`
Array [
Object {
"_src": "packages/package-1/dist",
"dest": "packages/package-2/node_modules/@test/package-1",
"type": "junction",
},
Object {
"_src": "packages/package-1/dist",
"dest": "packages/package-3/node_modules/@test/package-1",
"type": "junction",
},
Object {
"_src": "packages/package-2/dist",
"dest": "packages/package-3/node_modules/@test/package-2",
"type": "junction",
},
Object {
"_src": "packages/package-2/dist/cli.js",
"dest": "packages/package-3/node_modules/.bin/package-2",
"type": "exec",
},
Object {
"_src": "packages/package-3/dist",
"dest": "packages/package-4/node_modules/package-3",
"type": "junction",
},
Object {
"_src": "packages/package-3/dist/cli1.js",
"dest": "packages/package-4/node_modules/.bin/package3cli1",
"type": "exec",
},
Object {
"_src": "packages/package-3/dist/cli2.js",
"dest": "packages/package-4/node_modules/.bin/package3cli2",
"type": "exec",
},
]
`);
});
});

describe("with --force-local", () => {
it("should force symlink of all packages", async () => {
const testDir = await initFixture("force-local");
Expand Down Expand Up @@ -135,6 +182,53 @@ Array [
"type": "exec",
},
]
`);
});
});

describe("with --contents", () => {
it("should symlink sub-directory of package folders and bin directories", async () => {
const testDir = await initFixture("with-contents");
await lernaLink(testDir)("--contents", "build");

expect(symlinkedDirectories(testDir)).toMatchInlineSnapshot(`
Array [
Object {
"_src": "packages/package-1/build",
"dest": "packages/package-2/node_modules/@test/package-1",
"type": "junction",
},
Object {
"_src": "packages/package-1/build",
"dest": "packages/package-3/node_modules/@test/package-1",
"type": "junction",
},
Object {
"_src": "packages/package-2/build",
"dest": "packages/package-3/node_modules/@test/package-2",
"type": "junction",
},
Object {
"_src": "packages/package-2/build/cli.js",
"dest": "packages/package-3/node_modules/.bin/package-2",
"type": "exec",
},
Object {
"_src": "packages/package-3/build",
"dest": "packages/package-4/node_modules/package-3",
"type": "junction",
},
Object {
"_src": "packages/package-3/build/cli1.js",
"dest": "packages/package-4/node_modules/.bin/package3cli1",
"type": "exec",
},
Object {
"_src": "packages/package-3/build/cli2.js",
"dest": "packages/package-4/node_modules/.bin/package3cli2",
"type": "exec",
},
]
`);
});
});
Expand Down
6 changes: 6 additions & 0 deletions commands/link/command.js
Expand Up @@ -14,6 +14,12 @@ exports.builder = yargs => {
describe: "Force local sibling links regardless of version range match",
type: "boolean",
},
contents: {
group: "Command Options:",
describe: "Subdirectory to use as the source of the symlink. Must apply to ALL packages.",
type: "string",
defaultDescription: ".",
},
});

return yargs.command(
Expand Down