diff --git a/.eslintignore b/.eslintignore new file mode 100644 index 0000000000..5c9cc1e65f --- /dev/null +++ b/.eslintignore @@ -0,0 +1,2 @@ +dist +__fixtures__ diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index c7ee4553b4..0f60c0ff63 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -5,7 +5,6 @@ on: branches: - main - next - - "test/*" pull_request: types: [assigned, opened, synchronize, reopened, labeled] @@ -17,6 +16,8 @@ env: NX_CLOUD_ACCESS_TOKEN: ${{ secrets.NX_CLOUD_ACCESS_TOKEN }} NX_CLOUD_DISTRIBUTED_EXECUTION: true NX_BRANCH: ${{ github.event.number || github.ref_name }} + NX_VERBOSE_LOGGING: true + NX_CLOUD_NUMBER_OF_RETRIES: 1 jobs: main: @@ -27,8 +28,15 @@ jobs: with: fetch-depth: 0 - - name: Derive appropriate SHAs for base and head for `nx affected` commands - uses: nrwl/nx-set-shas@v3 + - uses: nrwl/nx-set-shas@v3 + + - name: Set NX_RUN_GROUP + shell: bash + run: echo "NX_RUN_GROUP=$GITHUB_RUN_ID-$GITHUB_RUN_ATTEMPT-linux" >> $GITHUB_ENV + + - name: Log NX_RUN_GROUP + shell: bash + run: echo "NX_RUN_GROUP is ${{ env.NX_RUN_GROUP }}" - name: Install primary node version (see volta config in package.json) and dependencies uses: ./.github/actions/install-node-and-dependencies @@ -38,15 +46,15 @@ jobs: with: cmd1: npx nx-cloud record -- npx nx format:check cmd2: npx nx-cloud record -- npx nx workspace-lint - cmd3: npx nx-cloud record -- npm run ci:lint - cmd4: npx nx run-many --target=lint --all --parallel=3 - # TODO: update this once project targets are converted - cmd5: npx nx run-many --target=test --projects=\"libs-*,nx-*\" --parallel=3 + cmd3: npx nx run-many -t build --parallel=3 + cmd4: npx nx run-many -t lint --parallel=3 + cmd5: npx nx run-many -t test --parallel=3 --ci --maxWorkers=2 + cmd6: npx nx run integration:integration --ci --maxWorkers=2 # e2e tests for everything except the primary task runner - - run: PUBLISHED_VERSION=999.9.9-e2e.0 npx nx run-many --target=run-e2e-tests-process --parallel=1 + - run: PUBLISHED_VERSION=999.9.9-e2e.0 npx nx run-many --t e2e --parallel=1 - - name: Stop all running agents for this CI run + - name: Stop all running agents for Nx Run Group ${{ env.NX_RUN_GROUP }} # It's important that we always run this step, otherwise in the case of any failures in preceding non-Nx steps, the agents will keep running and waste billable minutes if: ${{ always() }} run: npx nx-cloud stop-all-agents @@ -60,6 +68,14 @@ jobs: steps: - uses: actions/checkout@v3 + - name: Set NX_RUN_GROUP + shell: bash + run: echo "NX_RUN_GROUP=$GITHUB_RUN_ID-$GITHUB_RUN_ATTEMPT-linux" >> $GITHUB_ENV + + - name: Log NX_RUN_GROUP + shell: bash + run: echo "NX_RUN_GROUP is ${{ env.NX_RUN_GROUP }}" + - name: Configure git metadata run: | git config --global user.email test@example.com @@ -68,14 +84,86 @@ jobs: - name: Install primary node version (see volta config in package.json) and dependencies uses: ./.github/actions/install-node-and-dependencies - - run: npm run e2e-start-local-registry + - name: Start Nx Agent ${{ matrix.agent }} + run: npx nx-cloud start-agent + env: + NX_AGENT_NAME: ${{ matrix.agent }} + NX_RUN_GROUP: ${{ env.NX_RUN_GROUP }} + + windows-main: + name: Nx Cloud - Windows Main Job + runs-on: windows-latest + env: + LERNA_OS_TYPE: windows + steps: + - uses: actions/checkout@v3 - - run: PUBLISHED_VERSION=999.9.9-e2e.0 npm run e2e-build-package-publish + - name: Set NX_RUN_GROUP + shell: bash + run: echo "NX_RUN_GROUP=$GITHUB_RUN_ID-$GITHUB_RUN_ATTEMPT-windows" >> $GITHUB_ENV + + - name: Log NX_RUN_GROUP + shell: bash + run: echo "NX_RUN_GROUP is ${{ env.NX_RUN_GROUP }}" + + - name: Install primary node version (see volta config in package.json) and dependencies + uses: ./.github/actions/install-node-and-dependencies + + - name: Run parallel distributed unit and integration tests on windows + shell: bash + # From old maintainer regarding integration tests: "import is NOT TESTED in windows because pain and suffering" + run: | + pids=() + npx nx run integration:integration --ci --maxWorkers=2 --testPathIgnorePatterns=lerna-import.spec.ts & + pids+=($!) + + # Ignored specs currently failing on windows + # TODO: investigate why + npx nx run-many -t test --parallel=3 --ci --maxWorkers=2 --testTimeout=45000 --testPathIgnorePatterns=create-symlink.spec.ts --testPathIgnorePatterns=get-two-factor-auth-required.spec.ts --testPathIgnorePatterns=version-lifecycle-scripts.spec.ts --testPathIgnorePatterns=version-allow-branch.spec.ts --testPathIgnorePatterns=version-message.spec.ts --testPathIgnorePatterns=version-conventional-commits.spec.ts --testPathIgnorePatterns=version-bump-prerelease.spec.ts --testPathIgnorePatterns=version-bump.spec.ts --testPathIgnorePatterns=version-git-hosted-siblings.spec.ts --testPathIgnorePatterns=version-command.spec.ts --testPathIgnorePatterns=bootstrap-command.spec.ts --testPathIgnorePatterns=import-command.spec.ts --testPathIgnorePatterns=publish-command.spec.ts --testPathIgnorePatterns=publish-licenses.spec.ts --testPathIgnorePatterns=publish-lifecycle-scripts.spec.ts --testPathIgnorePatterns=publish-tagging.spec.ts --testPathIgnorePatterns=publish-relative-file-specifiers.spec.ts & + + pids+=($!) + + for pid in "${pids[@]}"; do + wait "$pid" + done + + - name: Stop all running agents for Nx Run Group ${{ env.NX_RUN_GROUP }} + # It's important that we always run this step, otherwise in the case of any failures in preceding non-Nx steps, the agents will keep running and waste billable minutes + if: ${{ always() }} + run: npx nx-cloud stop-all-agents + + windows-agents: + name: Nx Cloud - Windows Agent ${{ matrix.agent }} + runs-on: windows-latest + strategy: + matrix: + agent: [1, 2, 3, 4] + env: + LERNA_OS_TYPE: windows + steps: + - uses: actions/checkout@v3 + + - name: Set NX_RUN_GROUP + shell: bash + run: echo "NX_RUN_GROUP=$GITHUB_RUN_ID-$GITHUB_RUN_ATTEMPT-windows" >> $GITHUB_ENV + + - name: Log NX_RUN_GROUP + shell: bash + run: echo "NX_RUN_GROUP is ${{ env.NX_RUN_GROUP }}" + + - name: Configure git metadata + run: | + git config --global user.email test@example.com + git config --global user.name "Tester McPerson" + + - name: Install primary node version (see volta config in package.json) and dependencies + uses: ./.github/actions/install-node-and-dependencies - name: Start Nx Agent ${{ matrix.agent }} run: npx nx-cloud start-agent env: - NX_AGENT_NAME: ${{matrix.agent}} + NX_AGENT_NAME: ${{ matrix.agent }} + NX_RUN_GROUP: ${{ env.NX_RUN_GROUP }} # Isolated e2e tests for the task runner which become too flaky if nested through further node child processes task-runner-e2e: @@ -125,50 +213,3 @@ jobs: if: ${{ steps.check_affected.outputs.is_affected }} run: e2e/run/task-runner/src/run-tests.sh shell: bash - - # TODO: migrate to cacheable/distributable targets - test: - runs-on: ubuntu-latest - strategy: - fail-fast: false - matrix: - node: [14, "16.15.0", 18] - script: ["ci:test:unit", "ci:test:integration"] - steps: - - uses: actions/checkout@v3 - - - name: Configure git metadata - run: | - git config --global user.email test@example.com - git config --global user.name "Tester McPerson" - - - name: Install node version ${{ matrix.node }} and dependencies - uses: ./.github/actions/install-node-and-dependencies - with: - node-version: ${{ matrix.node }} - - - run: npm run ${{ matrix.script }} - - # TODO: migrate to cacheable/distributable targets - windows: - runs-on: windows-latest - strategy: - fail-fast: false - matrix: - script: ["ci:test:unit", "ci:test:integration"] - subset: [publish, non-publish] - steps: - - uses: actions/checkout@v3 - - - name: Configure git metadata - run: | - git config --global user.email test@example.com - git config --global user.name "Tester McPerson" - - - name: Install primary node version (see volta config in package.json) and dependencies - uses: ./.github/actions/install-node-and-dependencies - - - run: npm run ${{ matrix.script }} - env: - LERNA_CI_TYPE: ${{ matrix.subset }} - LERNA_OS_TYPE: windows diff --git a/.github/workflows/other-node-versions.yml b/.github/workflows/other-node-versions.yml new file mode 100644 index 0000000000..2f0fb029c0 --- /dev/null +++ b/.github/workflows/other-node-versions.yml @@ -0,0 +1,146 @@ +name: Other Node Versions + +on: + workflow_dispatch: + schedule: + # Every day at 7:30am UTC + - cron: "30 7 * * *" + +concurrency: + group: ${{ github.workflow }}-${{ github.event.number || github.ref }} + cancel-in-progress: true + +env: + NX_CLOUD_ACCESS_TOKEN: ${{ secrets.NX_CLOUD_ACCESS_TOKEN }} + NX_CLOUD_DISTRIBUTED_EXECUTION: true + NX_BRANCH: ${{ github.event.number || github.ref_name }} + NX_VERBOSE_LOGGING: true + +jobs: + set-node-versions: + name: Set Node Versions + runs-on: ubuntu-latest + outputs: + node-versions: ${{ steps.node-matrix.outputs.node-versions }} + steps: + - name: Set node matrix + id: node-matrix + # These versions intentionally do not contain our primary major version because that has already been tested by ci.yml + # 19 is included so that we can test npm v9 + # + # TODO: Investigate unit test failure on v19 + # TODO: ^14.15.0 is currently failing e2e because of later JS usage in our e2e-utils, so we need to address that + run: | + NODE_VERSIONS_JSON_ARRAY=$(node -e "console.log(JSON.stringify(['18']));") + echo $NODE_VERSIONS_JSON_ARRAY + echo "node-versions=$NODE_VERSIONS_JSON_ARRAY" >> $GITHUB_OUTPUT + + main: + name: Nx Cloud - Main Job - node-${{ matrix.node }} + needs: set-node-versions + runs-on: ubuntu-latest + strategy: + # Do not kill all versions of node just because one version failed + fail-fast: false + matrix: + node: ${{ fromJson(needs.set-node-versions.outputs.node-versions) }} + steps: + - uses: actions/checkout@v3 + with: + fetch-depth: 0 + + - name: Derive appropriate SHAs for base and head for `nx affected` commands + uses: nrwl/nx-set-shas@v3 + + - name: Set NX_RUN_GROUP + shell: bash + run: echo "NX_RUN_GROUP=$GITHUB_RUN_ID-$GITHUB_RUN_ATTEMPT-node-${{ matrix.node }}" >> $GITHUB_ENV + + - name: Log NX_RUN_GROUP + shell: bash + run: echo "NX_RUN_GROUP is ${{ env.NX_RUN_GROUP }}" + + - name: Install node v${{ matrix.node }} and dependencies + uses: ./.github/actions/install-node-and-dependencies + with: + node-version: ${{ matrix.node }} + + - name: Install pnpm + run: npm install -g pnpm + shell: bash + + - run: pnpm --version + shell: bash + + - name: Run parallel distributed tests on each node version + uses: jameshenry/parallel-bash-commands@v1 + with: + cmd1: npx nx run-many -t test --parallel=3 --ci --maxWorkers=2 + cmd2: npx nx run integration:integration --ci --maxWorkers=2 + + # e2e tests for everything except the primary task runner + - run: PUBLISHED_VERSION=999.9.9-e2e.0 npx nx run-many --target=run-e2e-tests-process --parallel=1 + + - name: Configure git metadata + run: | + git config --global user.email test@example.com + git config --global user.name "Tester McPerson" + + - name: Prepare e2e tests for task-runner + run: npx nx prepare-for-e2e e2e-run-task-runner + shell: bash + env: + NX_CLOUD_DISTRIBUTED_EXECUTION: false + + - name: Run e2e tests for task-runner + run: e2e/run/task-runner/src/run-tests.sh + shell: bash + env: + NX_CLOUD_DISTRIBUTED_EXECUTION: false + + - name: Stop all running agents for Nx Run Group ${{ env.NX_RUN_GROUP }} + # It's important that we always run this step, otherwise in the case of any failures in preceding non-Nx steps, the agents will keep running and waste billable minutes + if: ${{ always() }} + run: npx nx-cloud stop-all-agents + + agents: + name: Nx Cloud - Agent - node-${{ matrix.node }}-agent-${{ matrix.agent }} + needs: set-node-versions + runs-on: ubuntu-latest + strategy: + # Do not kill all versions of node just because one version failed + fail-fast: false + matrix: + node: ${{ fromJson(needs.set-node-versions.outputs.node-versions) }} + # Create 2 agents per node version + agent: [1, 2] + steps: + - uses: actions/checkout@v3 + + - name: Configure git metadata + run: | + git config --global user.email test@example.com + git config --global user.name "Tester McPerson" + + - name: Set NX_RUN_GROUP + shell: bash + run: echo "NX_RUN_GROUP=$GITHUB_RUN_ID-$GITHUB_RUN_ATTEMPT-node-${{ matrix.node }}" >> $GITHUB_ENV + + - name: Log NX_RUN_GROUP + shell: bash + run: echo "NX_RUN_GROUP is ${{ env.NX_RUN_GROUP }}" + + - name: Install node v${{ matrix.node }} and dependencies + uses: ./.github/actions/install-node-and-dependencies + with: + node-version: ${{ matrix.node }} + + - run: npm run e2e-start-local-registry + + - run: NX_VERBOSE_LOGGING=true PUBLISHED_VERSION=999.9.9-e2e.0 npm run e2e-build-package-publish + + - name: Start Nx Agent node-${{ matrix.node }}-agent-${{ matrix.agent }} + run: npx nx-cloud start-agent + env: + NX_AGENT_NAME: node-${{ matrix.node }}-agent-${{ matrix.agent }} + NX_RUN_GROUP: ${{ env.NX_RUN_GROUP }} diff --git a/.npmrc b/.npmrc index 7102ef60ff..3625ccdb59 100644 --- a/.npmrc +++ b/.npmrc @@ -1,2 +1,5 @@ # just in case a private registry is configured in ~/.npmrc registry = https://registry.npmjs.org/ + +# TODO: remove this once esbuild 0.17 is officially supported in @nrwl/esbuild +legacy-peer-deps = true diff --git a/.prettierignore b/.prettierignore index c0ee904502..71e89c5276 100644 --- a/.prettierignore +++ b/.prettierignore @@ -1,5 +1,6 @@ -# Ignore json configuration files in fixtures, sometimes they are intentonally malformed +# Ignore relevant files in fixtures, sometimes they are intentonally malformed **/__fixtures__/**/*.json +**/__fixtures__/**/*.md dist tmp \ No newline at end of file diff --git a/CHANGELOG.md b/CHANGELOG.md index c3f46e8d1d..588e774043 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,6 +3,19 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +# [6.5.0](https://github.com/lerna/lerna/compare/v6.4.1...6.5.0) (2023-02-13) + +### Bug Fixes + +- **create:** normalize quotes and indents in generated test and lib files ([#3529](https://github.com/lerna/lerna/issues/3529)) ([ad39fe2](https://github.com/lerna/lerna/commit/ad39fe2e4ca4e76cb7be6af83e8fbbc60d0935ce)) +- **repair:** re-enable repair generators ([#3497](https://github.com/lerna/lerna/issues/3497)) ([510c3e9](https://github.com/lerna/lerna/commit/510c3e993be09f8f070dd07ca3ee7d352d00e491)) + +### Features + +- **publish:** add --include-private option for testing private packages ([#3503](https://github.com/lerna/lerna/issues/3503)) ([fa1f490](https://github.com/lerna/lerna/commit/fa1f4900a658982d87888c1c7c5eef3697c5b31b)) +- **publish:** recover from network failure ([#3513](https://github.com/lerna/lerna/issues/3513)) ([f03ee3e](https://github.com/lerna/lerna/commit/f03ee3e2efe052d3b21dcb3b15cdad15f5ded499)) +- **run:** allow multiple script targets to be triggered at once ([#3527](https://github.com/lerna/lerna/issues/3527)) ([937b02a](https://github.com/lerna/lerna/commit/937b02aea4b3a62236aa8998eef127753f47c87c)) + ## [6.4.1](https://github.com/lerna/lerna/compare/v6.4.0...v6.4.1) (2023-01-12) ### Bug Fixes @@ -78,7 +91,7 @@ As of version 6.0.0, Lerna will now delegate the implementation details of the ` If for some reason you wish to opt in to the legacy task-runner implementation details (powered by `p-map` and `p-queue`), you can do so by setting `"useNx": false` in your lerna.json. (Please let us know via a Github issue if you feel the need to do that, however, as in general the new task-runner should just work how you expect it to as a lerna user). -### Interactive configurtion for `lerna run` caching and task pipelines via the new `lerna add-caching` command +### Interactive configuration for `lerna run` caching and task pipelines via the new `lerna add-caching` command When using the modern task-runner implementation described above, the way to get the most out of it is to tell it about the outputs of your various scripts, and also any relationships that exist between them (such as needing to run the `build` script before the `test`, for example). @@ -92,7 +105,7 @@ By default the modern task runner powered by Nx will automatically load `.env` f For more details about what `.env` files will be loaded by default please see: https://nx.dev/recipes/environment-variables/define-environment-variables -### Obselete options in `lerna run` with the new task-runner implementation +### Obsolete options in `lerna run` with the new task-runner implementation There are certain legacy options for `lerna run` which are no longer applicable to the modern task-runner. Please see full details about those flags, and the reason behind their obselence, here: diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index ed26137949..9f02d39230 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -24,10 +24,12 @@ npm ci # given this is a clean install on an existing project, npm ci can be use Currently, the [source](https://github.com/lerna/lerna/tree/main) is split up into a few categories: -- [utils](https://github.com/lerna/lerna/tree/main/utils): shared packages to run git, npm, fs, and more. -- [core](https://github.com/lerna/lerna/tree/main/core): basic building blocks, including Package-related abstractions and the command superclass. -- [commands](https://github.com/lerna/lerna/tree/main/commands): each command has an `initialize` and `execute` function. - - These commands are consumed as yargs subcommands in [core/cli/index.js](https://github.com/lerna/lerna/blob/main/core/cli/index.js), which is required from the executable [`core/lerna/cli.js`](https://github.com/lerna/lerna/blob/main/core/lerna/cli.js). +- [e2e](https://github.com/lerna/lerna/tree/main/e2e): latest test code which runs the `lerna` CLI as close to how a user does as possible +- [integration](https://github.com/lerna/lerna/tree/main/integration): legacy test code which exists somewhere between unit and e2e testing in terms of abstraction. New e2e tests should be preferred over new tests here because they are higher value. +- [libs](https://github.com/lerna/lerna/tree/main/libs): source code which gets composed into packages for publishing, or which assists with other things such as unit and e2e testing +- [packages](https://github.com/lerna/lerna/tree/main/packages): the packages which get published to npm +- [tools](https://github.com/lerna/lerna/tree/main/tools): utility scripts, node_module patches etc which help with maintaining the repository +- [website](https://github.com/lerna/lerna/tree/main/website): source code for https://lerna.js.org, which ultimately gets published to Github pages from https://github.com/lerna/website for historical reasons ## Submission Guidelines @@ -56,67 +58,50 @@ This project follows [GitHub's standard forking model](https://guides.github.com ### Run Unit Tests ```sh -$ npm test +# Run all unit tests +npm test -# watch for changes -$ npm test -- --watch - -# For a specific file (e.g., in core/command/__tests__/command.test.js) -$ npm test -- --watch core/command -``` +# Watch all unit tests for changes +npm test -- --watch -By default, `npm test` also runs the linter. -You can skip this by calling `jest` directly: - -```sh -$ npx jest -$ npx jest --watch -$ npx jest --config jest.integration.js +# Test a specific project or package +npx nx test core +npx nx test lerna # etc -``` -### Coverage - -If you would like to check test coverage, run the coverage script, then open -`coverage/lcov-report/index.html` in your favorite browser. - -```sh -$ npm test -- --coverage - -# OS X -$ open coverage/lcov-report/index.html - -# Linux -$ xdg-open coverage/lcov-report/index.html +# Watch a specific project or package's tests +npx nx test core --watch +npx nx test lerna --watch +# etc ``` ### Run Integration Tests ```sh -$ npm run integration +npm run integration # test a specific file -$ npm run integration -- lerna-publish +npm run integration -- --testFile lerna-add.spec.ts # watch for changes -$ npm run integration -- --watch +npm run integration -- --watch # watch a specific file -$ npm run integration -- --watch lerna-publish +npm run integration -- --testFile lerna-add.spec.ts --watch ``` ### Linting ```sh -$ npm run lint +npm run lint ``` -It's also a good idea to hook up your editor to an eslint plugin. +It's also a good idea to hook up your editor to an ESLint extension (such as `vscode-eslint`). To fix lint errors from the command line: ```sh -$ npm run lint -- --fix +npm run lint -- --fix ``` ### Local CLI Testing @@ -129,7 +114,7 @@ You will need two different terminal windows for this as one of them will contai - Run `npm adduser --registry http://localhost:4873` in Terminal 2 (real credentials are not required, you just need to be logged in. You can use test/test/test@test.io.) - Run `npm run local-registry enable` in Terminal 2 -- Run `npm run local-release 999.9.9 --local` in Terminal 2 - you can choose any nonexistent version number here, but it's recommended to use something which is different from the current major +- Run `npm run lerna-release 999.9.9 --local` in Terminal 2 - you can choose any nonexistent version number here, but it's recommended to use something which is different from the current major You can then install your local version of lerna wherever you want by leveraging the `--registry` flag on the npm/npx client. @@ -217,5 +202,5 @@ The root `.env` file is _never_ placed under version control. Once that's done, run the release script and await glory: ```sh -npm run release +npx env-cmd npm run lerna-release -- --local false ``` diff --git a/FAQ.md b/FAQ.md deleted file mode 100644 index 6ccf368b24..0000000000 --- a/FAQ.md +++ /dev/null @@ -1,85 +0,0 @@ -# Frequently asked questions - -_This document is a work in progress._ - -## How do I add a package to my Lerna repository? - -For any packages that you add to your Lerna repository, instead of running -`npm install` you should run [`lerna bootstrap`][bootstrap]. This will take into -account the existing projects in the `packages` folder as well as -external dependencies. - -### New packages - -Create a directory for your package in the `packages` folder, and run `npm init` -as normal to create the `package.json` for your new package. - -### Existing packages - -You can use [`lerna import `][import] to transfer an existing package -into your Lerna repository; this command will preserve the commit history. - -[`lerna import `][import] takes a local path rather than a URL. In this -case you will need to have the repo you wish to link to on your file system. - -[bootstrap]: https://github.com/lerna/lerna/blob/main/commands/bootstrap/README.md -[import]: https://github.com/lerna/lerna/blob/main/commands/import/README.md - -## How do I retry publishing if `publish` fails? - -Sometimes, `lerna publish` does not work. Your network may have had a hiccup, you may have not been logged on to npm, etc. - -If the `lerna.json` has not yet been updated, simply try `lerna publish` again. - -If it has been updated, you can force re-publish. `lerna publish --force-publish $(ls packages/)` - -## The bootstrap process is really slow, what can I do? - -Projects having many packages inside them could take a very long time to bootstrap. - -You can significantly reduce the time spent in `lerna bootstrap` if you turn -on hoisting, see the [hoisting docs](./doc/hoist.md) for more information. - -In combination with that you may increase the bootstrap performance even more by -[using yarn as an npm client](https://github.com/lerna/lerna/blob/main/commands/bootstrap/README.md#usage) instead of `npm`. - -## Root `package.json` - -The root `package.json`, at the very least, is how you install `lerna` locally during a CI build. -You should also put your testing, linting and similar tasks there to run them from root -as running them separately from each package is slower. The root can also hold all the "hoisted" packages, -which speeds up bootstrapping when using the [`--hoist`][hoist] flag. - -[hoist]: https://github.com/lerna/lerna/blob/main/doc/hoist.md - -## CI setup - -As mentioned above root `package.json` is responsible for installing `lerna` locally. You need to automate `bootstrap` though. -This can be achieved by putting it as npm script to use it during CI phases. - -Example root `package.json`: - -```json -{ - "name": "my-monorepo", - "private": true, - "devDependencies": { - "eslint": "^3.19.0", - "jest": "^20.0.4", - "lerna": "^2.0.0" - }, - "scripts": { - "bootstrap": "lerna bootstrap --hoist", - "pretest": "eslint packages", - "test": "jest" - } -} -``` - -Example CircleCI's configuration file (`circle.yml`): - -```yml -dependencies: - post: - - npm run bootstrap -``` diff --git a/README.md b/README.md index 53265391f9..41c54d422e 100644 --- a/README.md +++ b/README.md @@ -12,7 +12,7 @@

-Lerna is a fast modern build system for managing and publishing multiple JavaScript/TypeScript packages from the same repository. +Lerna is a fast, modern build system for managing and publishing multiple JavaScript/TypeScript packages from the same repository.


@@ -30,7 +30,7 @@ Lerna is a fast modern build system for managing and publishing multiple JavaScr Semantic Release - + Commitizen friendly @@ -106,4 +106,4 @@ Thanks goes to these wonderful people ([emoji key](https://allcontributors.org/d -This project follows the [all-contributors](https://github.com/all-contributors/all-contributors) specification. Contributions of any kind welcome! \ No newline at end of file +This project follows the [all-contributors](https://github.com/all-contributors/all-contributors) specification. Contributions of any kind welcome! diff --git a/commands/__mocks__/@lerna/collect-updates.js b/commands/__mocks__/@lerna/collect-updates.js deleted file mode 100644 index 99eff0d560..0000000000 --- a/commands/__mocks__/@lerna/collect-updates.js +++ /dev/null @@ -1,26 +0,0 @@ -"use strict"; - -const { collectPackages, getPackagesForOption } = jest.requireActual("@lerna/collect-updates"); - -// collectUpdates.setUpdated(cwd, packageNames...) -// otherwise, enables everything -const updated = new Map(); - -const mockCollectUpdates = jest.fn((filteredPackages, packageGraph, { cwd }) => { - const targets = updated.get(cwd); - const updates = targets ? new Map(targets.map((name) => [name, packageGraph.get(name)])) : packageGraph; - - return Array.from(updates.values()); -}); - -const setUpdated = (cwd, ...names) => updated.set(cwd, names); - -// isolate tests -afterEach(() => { - updated.clear(); -}); - -module.exports.collectUpdates = mockCollectUpdates; -module.exports.collectUpdates.setUpdated = setUpdated; -module.exports.collectPackages = collectPackages; -module.exports.getPackagesForOption = getPackagesForOption; diff --git a/commands/__mocks__/@lerna/conventional-commits.js b/commands/__mocks__/@lerna/conventional-commits.js deleted file mode 100644 index 6d9e672b1f..0000000000 --- a/commands/__mocks__/@lerna/conventional-commits.js +++ /dev/null @@ -1,23 +0,0 @@ -"use strict"; - -const fs = jest.requireActual("fs-extra"); -const path = require("path"); -const semver = require("semver"); - -const mockRecommendVersion = jest.fn().mockName("recommendVersion"); -const mockUpdateChangelog = jest.fn().mockName("updateChangelog"); - -mockRecommendVersion.mockImplementation((node) => semver.inc(node.version, "patch")); - -mockUpdateChangelog.mockImplementation((pkg) => { - const filePath = path.join(pkg.location, "CHANGELOG.md"); - - // grumble grumble re-implementing the implementation - return fs.outputFile(filePath, "changelog", "utf8").then(() => ({ - logPath: filePath, - newEntry: pkg.version ? `${pkg.name} - ${pkg.version}` : pkg.name, - })); -}); - -exports.recommendVersion = mockRecommendVersion; -exports.updateChangelog = mockUpdateChangelog; diff --git a/commands/__mocks__/@lerna/github-client.js b/commands/__mocks__/@lerna/github-client.js deleted file mode 100644 index 3645e97b02..0000000000 --- a/commands/__mocks__/@lerna/github-client.js +++ /dev/null @@ -1,24 +0,0 @@ -"use strict"; - -const releases = new Map(); - -// keep test data isolated -afterEach(() => { - releases.clear(); -}); - -const client = { - repos: { - createRelease: jest.fn((opts) => { - releases.set(opts.name, opts); - return Promise.resolve(); - }), - }, -}; - -module.exports.createGitHubClient = jest.fn(() => client); -module.exports.createGitHubClient.releases = releases; -module.exports.parseGitRepo = () => ({ - owner: "lerna", - name: "lerna", -}); diff --git a/commands/__mocks__/@lerna/gitlab-client.js b/commands/__mocks__/@lerna/gitlab-client.js deleted file mode 100644 index 3899c3c183..0000000000 --- a/commands/__mocks__/@lerna/gitlab-client.js +++ /dev/null @@ -1,20 +0,0 @@ -"use strict"; - -const releases = new Map(); - -// keep test data isolated -afterEach(() => { - releases.clear(); -}); - -const client = { - repos: { - createRelease: jest.fn((opts) => { - releases.set(opts.name, opts); - return Promise.resolve(); - }), - }, -}; - -module.exports.createGitLabClient = jest.fn(() => client); -module.exports.createGitLabClient.releases = releases; diff --git a/commands/__mocks__/@lerna/has-npm-version.js b/commands/__mocks__/@lerna/has-npm-version.js deleted file mode 100644 index 18cbed9319..0000000000 --- a/commands/__mocks__/@lerna/has-npm-version.js +++ /dev/null @@ -1,5 +0,0 @@ -"use strict"; - -const mockHasNpmVersion = jest.fn(() => true); - -module.exports.hasNpmVersion = mockHasNpmVersion; diff --git a/commands/__mocks__/@lerna/npm-publish.js b/commands/__mocks__/@lerna/npm-publish.js deleted file mode 100644 index a7aca4042f..0000000000 --- a/commands/__mocks__/@lerna/npm-publish.js +++ /dev/null @@ -1,24 +0,0 @@ -"use strict"; - -const registry = new Map(); - -// by default, act like a spy that populates registry -const mockNpmPublish = jest.fn((pkg, tarData, opts) => { - registry.set(pkg.name, opts.tag); - - return Promise.resolve(); -}); - -// a convenient format for assertions -function order() { - return Array.from(registry.keys()); -} - -// keep test data isolated -afterEach(() => { - registry.clear(); -}); - -module.exports.npmPublish = mockNpmPublish; -module.exports.npmPublish.order = order; -module.exports.npmPublish.registry = registry; diff --git a/commands/__mocks__/@lerna/output.js b/commands/__mocks__/@lerna/output.js deleted file mode 100644 index ff4a1af028..0000000000 --- a/commands/__mocks__/@lerna/output.js +++ /dev/null @@ -1,17 +0,0 @@ -"use strict"; - -const chalk = require("chalk"); -const { multiLineTrimRight } = require("@lerna-test/helpers"); - -// keep snapshots stable cross-platform -chalk.level = 0; - -// @lerna/output is just a wrapper around console.log -const mockOutput = jest.fn(); - -function logged() { - return mockOutput.mock.calls.map((args) => multiLineTrimRight(args[0])).join("\n"); -} - -module.exports.output = mockOutput; -module.exports.output.logged = logged; diff --git a/commands/__mocks__/@lerna/pack-directory.js b/commands/__mocks__/@lerna/pack-directory.js deleted file mode 100644 index be17d0448a..0000000000 --- a/commands/__mocks__/@lerna/pack-directory.js +++ /dev/null @@ -1,20 +0,0 @@ -"use strict"; - -const registry = new Set(); - -const mockPackDirectory = jest.fn((pkg) => { - registry.add(pkg.name); - - return Promise.resolve({ - filename: `${pkg.name}-MOCKED.tgz`, - tarFilePath: `/TEMP_DIR/${pkg.name}-MOCKED.tgz`, - }); -}); - -// keep test data isolated -afterEach(() => { - registry.clear(); -}); - -module.exports.packDirectory = mockPackDirectory; -module.exports.packDirectory.registry = registry; diff --git a/commands/__mocks__/@lerna/prompt.js b/commands/__mocks__/@lerna/prompt.js deleted file mode 100644 index de81c97cdb..0000000000 --- a/commands/__mocks__/@lerna/prompt.js +++ /dev/null @@ -1,30 +0,0 @@ -"use strict"; - -let choiceIndices = []; -afterEach(() => { - choiceIndices = []; -}); - -const mockConfirm = jest.fn(() => Promise.resolve(true)); -const mockSelect = jest.fn((_, { choices }) => { - // default selection is "patch" - const idx = choiceIndices.shift() || 0; - - // each choice => { value: '', name: '' } - return Promise.resolve(choices[idx].value); -}); -const mockInput = jest.fn(() => Promise.resolve()); - -exports.promptConfirmation = mockConfirm; -exports.promptSelectOne = mockSelect; -exports.promptTextInput = mockInput; - -const semverIndex = new Map( - ["patch", "minor", "major", "prepatch", "preminor", "premajor", "PRERELEASE", "CUSTOM"].map( - (keyword, idx) => [keyword, idx] - ) -); - -mockSelect.chooseBump = (keyword) => { - choiceIndices.push(semverIndex.get(keyword)); -}; diff --git a/commands/__mocks__/@lerna/run-lifecycle.js b/commands/__mocks__/@lerna/run-lifecycle.js deleted file mode 100644 index 05d56aef5b..0000000000 --- a/commands/__mocks__/@lerna/run-lifecycle.js +++ /dev/null @@ -1,19 +0,0 @@ -"use strict"; - -const mockRunLifecycle = jest.fn((pkg) => Promise.resolve(pkg)); -const mockCreateRunner = jest.fn((opts) => (pkg, stage) => { - // no longer the actual API, but approximates inner logic of default export - if (pkg.scripts[stage]) { - return mockRunLifecycle(pkg, stage, opts); - } - - return Promise.resolve(); -}); - -function getOrderedCalls() { - return mockRunLifecycle.mock.calls.map(([pkg, script]) => [pkg.name, script]); -} - -module.exports.runLifecycle = mockRunLifecycle; -module.exports.createRunner = mockCreateRunner; -module.exports.runLifecycle.getOrderedCalls = getOrderedCalls; diff --git a/commands/add/CHANGELOG.md b/commands/add/CHANGELOG.md deleted file mode 100644 index c5226770cb..0000000000 --- a/commands/add/CHANGELOG.md +++ /dev/null @@ -1,629 +0,0 @@ -# Change Log - -All notable changes to this project will be documented in this file. -See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. - -## [6.4.1](https://github.com/lerna/lerna/compare/v6.4.0...v6.4.1) (2023-01-12) - -**Note:** Version bump only for package @lerna/add - -# [6.4.0](https://github.com/lerna/lerna/compare/v6.3.0...v6.4.0) (2023-01-05) - -**Note:** Version bump only for package @lerna/add - -# [6.3.0](https://github.com/lerna/lerna/compare/v6.2.0...v6.3.0) (2022-12-26) - -**Note:** Version bump only for package @lerna/add - -# [6.2.0](https://github.com/lerna/lerna/compare/v6.1.0...v6.2.0) (2022-12-13) - -**Note:** Version bump only for package @lerna/add - -# [6.1.0](https://github.com/lerna/lerna/compare/v6.0.3...v6.1.0) (2022-11-29) - -**Note:** Version bump only for package @lerna/add - -## [6.0.3](https://github.com/lerna/lerna/compare/v6.0.2...v6.0.3) (2022-11-07) - -**Note:** Version bump only for package @lerna/add - -## [6.0.2](https://github.com/lerna/lerna/compare/v6.0.1...v6.0.2) (2022-11-02) - -**Note:** Version bump only for package @lerna/add - -## [6.0.1](https://github.com/lerna/lerna/compare/v6.0.0...v6.0.1) (2022-10-14) - -**Note:** Version bump only for package @lerna/add - -# [6.0.0](https://github.com/lerna/lerna/compare/v6.0.0-alpha.2...v6.0.0) (2022-10-12) - -**Note:** Version bump only for package @lerna/add - -# [6.0.0-alpha.2](https://github.com/lerna/lerna/compare/v6.0.0-alpha.1...v6.0.0-alpha.2) (2022-10-12) - -**Note:** Version bump only for package @lerna/add - -# [6.0.0-alpha.1](https://github.com/lerna/lerna/compare/v5.6.2...v6.0.0-alpha.1) (2022-10-09) - -# [6.0.0-alpha.0](https://github.com/lerna/lerna/compare/v5.6.1...v6.0.0-alpha.0) (2022-10-07) - -**Note:** Version bump only for package @lerna/add - -## [5.6.2](https://github.com/lerna/lerna/compare/v5.6.1...v5.6.2) (2022-10-09) - -**Note:** Version bump only for package @lerna/add - -## [5.6.1](https://github.com/lerna/lerna/compare/v5.6.0...v5.6.1) (2022-09-30) - -**Note:** Version bump only for package @lerna/add - -# [5.6.0](https://github.com/lerna/lerna/compare/v5.5.4...v5.6.0) (2022-09-29) - -**Note:** Version bump only for package @lerna/add - -## [5.5.4](https://github.com/lerna/lerna/compare/v5.5.3...v5.5.4) (2022-09-28) - -**Note:** Version bump only for package @lerna/add - -## [5.5.3](https://github.com/lerna/lerna/compare/v5.5.2...v5.5.3) (2022-09-28) - -**Note:** Version bump only for package @lerna/add - -## [5.5.2](https://github.com/lerna/lerna/compare/v5.5.1...v5.5.2) (2022-09-20) - -**Note:** Version bump only for package @lerna/add - -## [5.5.1](https://github.com/lerna/lerna/compare/v5.5.0...v5.5.1) (2022-09-09) - -**Note:** Version bump only for package @lerna/add - -# [5.5.0](https://github.com/lerna/lerna/compare/v5.4.3...v5.5.0) (2022-08-31) - -### Features - -- pnpm workspaces support ([#3284](https://github.com/lerna/lerna/issues/3284)) ([1b18dbe](https://github.com/lerna/lerna/commit/1b18dbeb03e98c70b5428a9fe457781a59f8d65d)) - -## [5.4.3](https://github.com/lerna/lerna/compare/v5.4.2...v5.4.3) (2022-08-16) - -**Note:** Version bump only for package @lerna/add - -## [5.4.2](https://github.com/lerna/lerna/compare/v5.4.1...v5.4.2) (2022-08-14) - -**Note:** Version bump only for package @lerna/add - -## [5.4.1](https://github.com/lerna/lerna/compare/v5.4.0...v5.4.1) (2022-08-12) - -**Note:** Version bump only for package @lerna/add - -# [5.4.0](https://github.com/lerna/lerna/compare/v5.3.0...v5.4.0) (2022-08-08) - -**Note:** Version bump only for package @lerna/add - -# [5.3.0](https://github.com/lerna/lerna/compare/v5.2.0...v5.3.0) (2022-07-27) - -**Note:** Version bump only for package @lerna/add - -# [5.2.0](https://github.com/lerna/lerna/compare/v5.1.8...v5.2.0) (2022-07-22) - -**Note:** Version bump only for package @lerna/add - -## [5.1.8](https://github.com/lerna/lerna/compare/v5.1.7...v5.1.8) (2022-07-07) - -**Note:** Version bump only for package @lerna/add - -## [5.1.7](https://github.com/lerna/lerna/compare/v5.1.6...v5.1.7) (2022-07-06) - -**Note:** Version bump only for package @lerna/add - -## [5.1.6](https://github.com/lerna/lerna/compare/v5.1.5...v5.1.6) (2022-06-24) - -**Note:** Version bump only for package @lerna/add - -## [5.1.5](https://github.com/lerna/lerna/compare/v5.1.4...v5.1.5) (2022-06-24) - -**Note:** Version bump only for package @lerna/add - -## [5.1.4](https://github.com/lerna/lerna/compare/v5.1.3...v5.1.4) (2022-06-15) - -**Note:** Version bump only for package @lerna/add - -## [5.1.3](https://github.com/lerna/lerna/compare/v5.1.2...v5.1.3) (2022-06-15) - -**Note:** Version bump only for package @lerna/add - -## [5.1.2](https://github.com/lerna/lerna/compare/v5.1.1...v5.1.2) (2022-06-13) - -**Note:** Version bump only for package @lerna/add - -## [5.1.1](https://github.com/lerna/lerna/compare/v5.1.0...v5.1.1) (2022-06-09) - -### Bug Fixes - -- allow maintenance LTS node 14 engines starting at 14.15.0 ([#3161](https://github.com/lerna/lerna/issues/3161)) ([72305e4](https://github.com/lerna/lerna/commit/72305e4dbab607a2d87ae4efa6ee577c93a9dda9)) - -# [5.1.0](https://github.com/lerna/lerna/compare/v5.0.0...v5.1.0) (2022-06-07) - -**Note:** Version bump only for package @lerna/add - -# [5.1.0-alpha.0](https://github.com/lerna/lerna/compare/v4.0.0...v5.1.0-alpha.0) (2022-05-25) - -**Note:** Version bump only for package @lerna/add - -# [5.0.0](https://github.com/lerna/lerna/compare/v4.0.0...v5.0.0) (2022-05-24) - -**Note:** Version bump only for package @lerna/add - -# [4.0.0](https://github.com/lerna/lerna/compare/v3.22.1...v4.0.0) (2021-02-10) - -### Features - -- **deps:** Bump dependencies ([affed1c](https://github.com/lerna/lerna/commit/affed1ce0fce91f01b0a9eafe357db2d985b974f)) -- Consume named exports of sibling modules ([63499e3](https://github.com/lerna/lerna/commit/63499e33652bc78fe23751875d74017e2f16a689)) -- **deps:** @evocateur/pacote -> pacote@^11.1.13 ([99b4217](https://github.com/lerna/lerna/commit/99b4217ed143527a45969f3a46f1bd9b84999d68)) -- **deps:** npm-package-arg@^8.1.0 ([12c8923](https://github.com/lerna/lerna/commit/12c892342d33b86a00ee2cf9079f9b26fe316dc6)) -- **deps:** p-map@^4.0.0 ([92b1364](https://github.com/lerna/lerna/commit/92b1364735e1f2cf379cf1047c60c4fb897d55f5)) -- **deps:** semver@^7.3.2 ([003ad66](https://github.com/lerna/lerna/commit/003ad6641fab8b4e3a82251ebffd27061bd6a31b)) -- Drop support for Node v6.x & v8.x ([ff4bb4d](https://github.com/lerna/lerna/commit/ff4bb4da215555e3bb136f5af09b5cbc631e57bb)) - -### BREAKING CHANGES - -- Node v6.x & v8.x are no longer supported. Please upgrade to the latest LTS release. - -Here's the gnarly one-liner I used to make these changes: - -``` -npx lerna exec --concurrency 1 --stream -- 'json -I -f package.json -e '"'"'this.engines=this.engines||{};this.engines.node=">= 10.18.0"'"'" -``` - -(requires `npm i -g json` beforehand) - -# [3.21.0](https://github.com/lerna/lerna/compare/v3.20.2...v3.21.0) (2020-05-13) - -**Note:** Version bump only for package @lerna/add - -# [3.20.0](https://github.com/lerna/lerna/compare/v3.19.0...v3.20.0) (2019-12-27) - -**Note:** Version bump only for package @lerna/add - -# [3.19.0](https://github.com/lerna/lerna/compare/v3.18.5...v3.19.0) (2019-11-20) - -### Features - -- **add:** Add `--peer` option to save target in `peerDependencies` ([#2334](https://github.com/lerna/lerna/issues/2334)) ([e12bf6a](https://github.com/lerna/lerna/commit/e12bf6a6af636e8ac0c0085144325f36505fc8d9)) - -## [3.18.5](https://github.com/lerna/lerna/compare/v3.18.4...v3.18.5) (2019-11-20) - -**Note:** Version bump only for package @lerna/add - -## [3.18.4](https://github.com/lerna/lerna/compare/v3.18.3...v3.18.4) (2019-11-08) - -### Bug Fixes - -- **filter-options:** Ensure `--include-merged-tags` is available to all `--since`-filterable commands ([287bcd8](https://github.com/lerna/lerna/commit/287bcd8b5c8dbb2dc4def5c933d0b4917c34813e)), closes [#2332](https://github.com/lerna/lerna/issues/2332) - -# [3.18.0](https://github.com/lerna/lerna/compare/v3.17.0...v3.18.0) (2019-10-15) - -### Features - -- **filter-options:** Add `--exclude-dependents` option ([ff50e29](https://github.com/lerna/lerna/commit/ff50e299aa990b121e1bd987548252376177c68a)), closes [#2198](https://github.com/lerna/lerna/issues/2198) -- **filter-options:** Rename `--include-filtered-*` options ([f2c3a92](https://github.com/lerna/lerna/commit/f2c3a92fe41b6fdc5d11269f0f2c3e27761b4c85)) - -# [3.17.0](https://github.com/lerna/lerna/compare/v3.16.5...v3.17.0) (2019-10-10) - -**Note:** Version bump only for package @lerna/add - -## [3.16.5](https://github.com/lerna/lerna/compare/v3.16.4...v3.16.5) (2019-10-07) - -**Note:** Version bump only for package @lerna/add - -## [3.16.2](https://github.com/lerna/lerna/compare/v3.16.1...v3.16.2) (2019-07-22) - -**Note:** Version bump only for package @lerna/add - -## [3.16.1](https://github.com/lerna/lerna/compare/v3.16.0...v3.16.1) (2019-07-19) - -**Note:** Version bump only for package @lerna/add - -# [3.16.0](https://github.com/lerna/lerna/compare/v3.15.0...v3.16.0) (2019-07-18) - -### Bug Fixes - -- **deps:** Bump `@evocateur/pacote` ([03e4797](https://github.com/lerna/lerna/commit/03e4797)) -- **deps:** Update forked npm libs ([4d67426](https://github.com/lerna/lerna/commit/4d67426)) - -### Features - -- **deps:** `p-map@^2.1.0` ([9e58394](https://github.com/lerna/lerna/commit/9e58394)) -- **deps:** `semver@^6.2.0` ([d8016d9](https://github.com/lerna/lerna/commit/d8016d9)) - -# [3.15.0](https://github.com/lerna/lerna/compare/v3.14.2...v3.15.0) (2019-06-09) - -### Bug Fixes - -- **deps:** Consume forked npm libs ([bdd4fa1](https://github.com/lerna/lerna/commit/bdd4fa1)) - -## [3.14.2](https://github.com/lerna/lerna/compare/v3.14.1...v3.14.2) (2019-06-09) - -**Note:** Version bump only for package @lerna/add - -# [3.14.0](https://github.com/lerna/lerna/compare/v3.13.4...v3.14.0) (2019-05-14) - -### Bug Fixes - -- **add:** Never pass filter options to nested bootstrap ([9a5a29c](https://github.com/lerna/lerna/commit/9a5a29c)), closes [#1989](https://github.com/lerna/lerna/issues/1989) - -## [3.13.3](https://github.com/lerna/lerna/compare/v3.13.2...v3.13.3) (2019-04-17) - -**Note:** Version bump only for package @lerna/add - -## [3.13.1](https://github.com/lerna/lerna/compare/v3.13.0...v3.13.1) (2019-02-26) - -### Bug Fixes - -- **deps:** pacote ^9.5.0 ([cdc2e17](https://github.com/lerna/lerna/commit/cdc2e17)) - -# [3.13.0](https://github.com/lerna/lerna/compare/v3.12.1...v3.13.0) (2019-02-15) - -### Features - -- **meta:** Add `repository.directory` field to package.json ([aec5023](https://github.com/lerna/lerna/commit/aec5023)) -- **meta:** Normalize package.json `homepage` field ([abeb4dc](https://github.com/lerna/lerna/commit/abeb4dc)) - -## [3.12.1](https://github.com/lerna/lerna/compare/v3.12.0...v3.12.1) (2019-02-14) - -**Note:** Version bump only for package @lerna/add - -# [3.12.0](https://github.com/lerna/lerna/compare/v3.11.1...v3.12.0) (2019-02-14) - -**Note:** Version bump only for package @lerna/add - -# [3.11.0](https://github.com/lerna/lerna/compare/v3.10.8...v3.11.0) (2019-02-08) - -### Bug Fixes - -- **deps:** Explicit npm-package-arg ^6.1.0 ([4b20791](https://github.com/lerna/lerna/commit/4b20791)) -- **deps:** Explicit pacote ^9.4.1 ([44d05bf](https://github.com/lerna/lerna/commit/44d05bf)) -- **deps:** Remove unused libnpm (replaced by direct sub-packages) ([1caeb28](https://github.com/lerna/lerna/commit/1caeb28)) - -## [3.10.6](https://github.com/lerna/lerna/compare/v3.10.5...v3.10.6) (2019-01-19) - -### Bug Fixes - -- **options:** Document negated boolean options explicitly ([8bc9669](https://github.com/lerna/lerna/commit/8bc9669)) - -## [3.10.5](https://github.com/lerna/lerna/compare/v3.10.4...v3.10.5) (2019-01-11) - -**Note:** Version bump only for package @lerna/add - -## [3.10.4](https://github.com/lerna/lerna/compare/v3.10.3...v3.10.4) (2019-01-10) - -### Bug Fixes - -- **add:** Do not scope chained bootstrap ([d9d4bc4](https://github.com/lerna/lerna/commit/d9d4bc4)) - -## [3.10.3](https://github.com/lerna/lerna/compare/v3.10.2...v3.10.3) (2019-01-10) - -**Note:** Version bump only for package @lerna/add - -## [3.10.2](https://github.com/lerna/lerna/compare/v3.10.1...v3.10.2) (2019-01-09) - -**Note:** Version bump only for package @lerna/add - -## [3.10.1](https://github.com/lerna/lerna/compare/v3.10.0...v3.10.1) (2019-01-09) - -**Note:** Version bump only for package @lerna/add - -# [3.10.0](https://github.com/lerna/lerna/compare/v3.9.1...v3.10.0) (2019-01-08) - -**Note:** Version bump only for package @lerna/add - -## [3.9.1](https://github.com/lerna/lerna/compare/v3.9.0...v3.9.1) (2019-01-08) - -**Note:** Version bump only for package @lerna/add - -# [3.9.0](https://github.com/lerna/lerna/compare/v3.8.5...v3.9.0) (2019-01-08) - -**Note:** Version bump only for package @lerna/add - -## [3.8.5](https://github.com/lerna/lerna/compare/v3.8.4...v3.8.5) (2019-01-05) - -**Note:** Version bump only for package @lerna/add - -## [3.8.2](https://github.com/lerna/lerna/compare/v3.8.1...v3.8.2) (2019-01-03) - -**Note:** Version bump only for package @lerna/add - -## [3.8.1](https://github.com/lerna/lerna/compare/v3.8.0...v3.8.1) (2018-12-31) - -**Note:** Version bump only for package @lerna/add - -## [3.7.2](https://github.com/lerna/lerna/compare/v3.7.1...v3.7.2) (2018-12-21) - -**Note:** Version bump only for package @lerna/add - -## [3.7.1](https://github.com/lerna/lerna/compare/v3.7.0...v3.7.1) (2018-12-20) - -**Note:** Version bump only for package @lerna/add - -# [3.7.0](https://github.com/lerna/lerna/compare/v3.6.0...v3.7.0) (2018-12-19) - -### Bug Fixes - -- **add:** Snapshot opts passed to pacote.manifest() ([d0f0dbc](https://github.com/lerna/lerna/commit/d0f0dbc)) - -# [3.6.0](https://github.com/lerna/lerna/compare/v3.5.1...v3.6.0) (2018-12-07) - -### Bug Fixes - -- **add:** Validate local package version ([#1804](https://github.com/lerna/lerna/issues/1804)) ([ed6e2db](https://github.com/lerna/lerna/commit/ed6e2db)), closes [#1799](https://github.com/lerna/lerna/issues/1799) - -### Features - -- **add:** Add --no-bootstrap option ([89bb928](https://github.com/lerna/lerna/commit/89bb928)) -- Migrate existing usage to libnpm ([0d3a786](https://github.com/lerna/lerna/commit/0d3a786)), closes [#1767](https://github.com/lerna/lerna/issues/1767) - -# [3.5.0](https://github.com/lerna/lerna/compare/v3.4.3...v3.5.0) (2018-11-27) - -**Note:** Version bump only for package @lerna/add - -## [3.4.1](https://github.com/lerna/lerna/compare/v3.4.0...v3.4.1) (2018-10-04) - -### Bug Fixes - -- **add:** Allow --registry option ([597606c](https://github.com/lerna/lerna/commit/597606c)) - - - -## [3.3.2](https://github.com/lerna/lerna/compare/v3.3.1...v3.3.2) (2018-09-12) - -**Note:** Version bump only for package @lerna/add - - - -## [3.3.1](https://github.com/lerna/lerna/compare/v3.3.0...v3.3.1) (2018-09-11) - -**Note:** Version bump only for package @lerna/add - - - -# [3.3.0](https://github.com/lerna/lerna/compare/v3.2.1...v3.3.0) (2018-09-06) - -**Note:** Version bump only for package @lerna/add - - - -# [3.2.0](https://github.com/lerna/lerna/compare/v3.1.4...v3.2.0) (2018-08-28) - -### Bug Fixes - -- **add:** Order short flags first in help output, clarify description ([8efb549](https://github.com/lerna/lerna/commit/8efb549)) - -### Features - -- **add:** Add examples to `--help` output ([#1612](https://github.com/lerna/lerna/issues/1612)) ([2ab62c1](https://github.com/lerna/lerna/commit/2ab62c1)), closes [#1608](https://github.com/lerna/lerna/issues/1608) - - - -## [3.1.4](https://github.com/lerna/lerna/compare/v3.1.3...v3.1.4) (2018-08-21) - -**Note:** Version bump only for package @lerna/add - - - -## [3.1.3](https://github.com/lerna/lerna/compare/v3.1.2...v3.1.3) (2018-08-21) - -### Bug Fixes - -- **add:** Avoid passing bad scope to pacote ([ad649bf](https://github.com/lerna/lerna/commit/ad649bf)), closes [#1592](https://github.com/lerna/lerna/issues/1592) - - - -## [3.1.2](https://github.com/lerna/lerna/compare/v3.1.1...v3.1.2) (2018-08-20) - -### Bug Fixes - -- Setup instance.filteredPackages explicitly ([32357f8](https://github.com/lerna/lerna/commit/32357f8)) - - - -## [3.1.1](https://github.com/lerna/lerna/compare/v3.1.0...v3.1.1) (2018-08-17) - -### Bug Fixes - -- **add:** Compose bootstrap to avoid extra logs ([3c534eb](https://github.com/lerna/lerna/commit/3c534eb)) -- **add:** Use `pacote` to resolve third-party registry authentication woes ([a0fbf46](https://github.com/lerna/lerna/commit/a0fbf46)), closes [#1572](https://github.com/lerna/lerna/issues/1572) [#1539](https://github.com/lerna/lerna/issues/1539) - - - -# [3.1.0](https://github.com/lerna/lerna/compare/v3.0.6...v3.1.0) (2018-08-17) - -**Note:** Version bump only for package @lerna/add - - - -## [3.0.6](https://github.com/lerna/lerna/compare/v3.0.5...v3.0.6) (2018-08-16) - -**Note:** Version bump only for package @lerna/add - - - -## [3.0.5](https://github.com/lerna/lerna/compare/v3.0.4...v3.0.5) (2018-08-15) - -**Note:** Version bump only for package @lerna/add - - - -## [3.0.4](https://github.com/lerna/lerna/compare/v3.0.3...v3.0.4) (2018-08-14) - -**Note:** Version bump only for package @lerna/add - - - -# [3.0.0](https://github.com/lerna/lerna/compare/v3.0.0-rc.0...v3.0.0) (2018-08-10) - -### Bug Fixes - -- **add:** Always use POSIX paths when computing relative file: specifiers ([ffe354f](https://github.com/lerna/lerna/commit/ffe354f)) -- **add:** Support explicit & implicit relative file: specifiers ([41f231f](https://github.com/lerna/lerna/commit/41f231f)) - - - -# [3.0.0-rc.0](https://github.com/lerna/lerna/compare/v3.0.0-beta.21...v3.0.0-rc.0) (2018-07-27) - -### Features - -- Add description from --help summary [skip ci] ([9b65d8e](https://github.com/lerna/lerna/commit/9b65d8e)) -- **add:** Add `--exact` option to `lerna add` ([#1478](https://github.com/lerna/lerna/issues/1478)) ([346d156](https://github.com/lerna/lerna/commit/346d156)), closes [#1470](https://github.com/lerna/lerna/issues/1470) - - - -# [3.0.0-beta.21](https://github.com/lerna/lerna/compare/v3.0.0-beta.20...v3.0.0-beta.21) (2018-05-12) - -**Note:** Version bump only for package @lerna/add - - - -# [3.0.0-beta.20](https://github.com/lerna/lerna/compare/v3.0.0-beta.19...v3.0.0-beta.20) (2018-05-07) - -**Note:** Version bump only for package @lerna/add - - - -# [3.0.0-beta.19](https://github.com/lerna/lerna/compare/v3.0.0-beta.18...v3.0.0-beta.19) (2018-05-03) - -### Bug Fixes - -- **add:** Configure `--dev` as boolean option ([#1390](https://github.com/lerna/lerna/issues/1390)) ([75b91bd](https://github.com/lerna/lerna/commit/75b91bd)) - - - -# [3.0.0-beta.18](https://github.com/lerna/lerna/compare/v3.0.0-beta.17...v3.0.0-beta.18) (2018-04-24) - -**Note:** Version bump only for package @lerna/add - - - -# [3.0.0-beta.17](https://github.com/lerna/lerna/compare/v3.0.0-beta.16...v3.0.0-beta.17) (2018-04-13) - -### Features - -- **add:** Use directory globs to filter targeted packages ([39fa7b6](https://github.com/lerna/lerna/commit/39fa7b6)) - -### BREAKING CHANGES - -- **add:** `lerna add` now only supports adding one dependency at a time. It is much more valuable to filter by directory globs, anyway. - - - -# [3.0.0-beta.15](https://github.com/lerna/lerna/compare/v3.0.0-beta.14...v3.0.0-beta.15) (2018-04-09) - -**Note:** Version bump only for package @lerna/add - - - -# [3.0.0-beta.14](https://github.com/lerna/lerna/compare/v3.0.0-beta.13...v3.0.0-beta.14) (2018-04-03) - -**Note:** Version bump only for package @lerna/add - - - -# [3.0.0-beta.13](https://github.com/lerna/lerna/compare/v3.0.0-beta.12...v3.0.0-beta.13) (2018-03-31) - -**Note:** Version bump only for package @lerna/add - - - -# [3.0.0-beta.12](https://github.com/lerna/lerna/compare/v3.0.0-beta.11...v3.0.0-beta.12) (2018-03-30) - -### Features - -- **package:** Add `serialize()` method ([fdec3ac](https://github.com/lerna/lerna/commit/fdec3ac)) -- **package:** Add Map-like get/set methods, remove raw json getter ([707d1f0](https://github.com/lerna/lerna/commit/707d1f0)) - -### BREAKING CHANGES - -- **package:** The `Package` class no longer provides direct access to the JSON object - used to construct the instance. Map-like `get()`/`set(val)` methods are - available to modify the internal representation. - - - -# [3.0.0-beta.11](https://github.com/lerna/lerna/compare/v3.0.0-beta.10...v3.0.0-beta.11) (2018-03-29) - -**Note:** Version bump only for package @lerna/add - - - -# [3.0.0-beta.10](https://github.com/lerna/lerna/compare/v3.0.0-beta.9...v3.0.0-beta.10) (2018-03-27) - -### Bug Fixes - -- **add:** Use bootstrap factory, not handler ([dbfc891](https://github.com/lerna/lerna/commit/dbfc891)) - -### Features - -- **commands:** Delay require of command instantiation ([a1284f3](https://github.com/lerna/lerna/commit/a1284f3)) - -### BREAKING CHANGES - -- **commands:** The default export of command packages is now a factory, not the subclass (which is now a named export). - - - -# [3.0.0-beta.9](https://github.com/lerna/lerna/compare/v3.0.0-beta.8...v3.0.0-beta.9) (2018-03-24) - -### Features - -- **command:** Rename this.repository -> this.project ([43e98a0](https://github.com/lerna/lerna/commit/43e98a0)) - - - -# [3.0.0-beta.8](https://github.com/lerna/lerna/compare/v3.0.0-beta.7...v3.0.0-beta.8) (2018-03-22) - -### Bug Fixes - -- **add:** Support tag and version specifiers ([5df0fc8](https://github.com/lerna/lerna/commit/5df0fc8)), closes [#1306](https://github.com/lerna/lerna/issues/1306) - - - -# [3.0.0-beta.7](https://github.com/lerna/lerna/compare/v3.0.0-beta.6...v3.0.0-beta.7) (2018-03-20) - -**Note:** Version bump only for package @lerna/add - - - -# [3.0.0-beta.6](https://github.com/lerna/lerna/compare/v3.0.0-beta.5...v3.0.0-beta.6) (2018-03-19) - -**Note:** Version bump only for package @lerna/add - - - -# [3.0.0-beta.5](https://github.com/lerna/lerna/compare/v3.0.0-beta.4...v3.0.0-beta.5) (2018-03-19) - -**Note:** Version bump only for package @lerna/add - - - -# [3.0.0-beta.4](https://github.com/lerna/lerna/compare/v3.0.0-beta.3...v3.0.0-beta.4) (2018-03-19) - -### Bug Fixes - -- Use correct instance property override ([9249221](https://github.com/lerna/lerna/commit/9249221)) - - - -# [3.0.0-beta.3](https://github.com/lerna/lerna/compare/v3.0.0-beta.2...v3.0.0-beta.3) (2018-03-15) - -**Note:** Version bump only for package @lerna/add - - - -# [3.0.0-beta.2](https://github.com/lerna/lerna/compare/v3.0.0-beta.1...v3.0.0-beta.2) (2018-03-10) - -**Note:** Version bump only for package @lerna/add - - - -# [3.0.0-beta.1](https://github.com/lerna/lerna/compare/v3.0.0-beta.0...v3.0.0-beta.1) (2018-03-09) - -**Note:** Version bump only for package @lerna/add diff --git a/commands/add/README.md b/commands/add/README.md deleted file mode 100644 index 0a987690b6..0000000000 --- a/commands/add/README.md +++ /dev/null @@ -1,70 +0,0 @@ -# `@lerna/add` - -> Add a dependency to matched packages - -Install [lerna](https://www.npmjs.com/package/lerna) for access to the `lerna` CLI. - -## Usage - -```sh -$ lerna add [@version] [--dev] [--exact] [--peer] -``` - -Add local or remote `package` as dependency to packages in the current Lerna repo. Note that only a single package can be added at a time compared to `yarn add` or `npm install`. - -When run, this command will: - -1. Add `package` to each applicable package. Applicable are packages that are not `package` and are in scope -2. Bootstrap packages with changes to their manifest file (`package.json`) - -If no `version` specifier is provided, it defaults to the `latest` dist-tag, just like `npm install`. - -## Options - -`lerna add` accepts all [filter flags](https://www.npmjs.com/package/@lerna/filter-options). - -### `--dev` - -Add the new package to `devDependencies` instead of `dependencies`. - -### `--exact` - -```sh -$ lerna add --exact -``` - -Add the new package with an exact version (e.g., `1.0.1`) rather than the default `^` semver range (e.g., `^1.0.1`). - -### `--peer` - -Add the new package to `peerDependencies` instead of `dependencies`. - -### `--registry ` - -Use a custom registry to install the targeted package. - -### `--no-bootstrap` - -Skip the chained `lerna bootstrap`. - -## Examples - -```sh -# Adds the module-1 package to the packages in the 'prefix-' prefixed folders -lerna add module-1 packages/prefix-* - -# Install module-1 to module-2 -lerna add module-1 --scope=module-2 - -# Install module-1 to module-2 in devDependencies -lerna add module-1 --scope=module-2 --dev - -# Install module-1 to module-2 in peerDependencies -lerna add module-1 --scope=module-2 --peer - -# Install module-1 in all modules except module-1 -lerna add module-1 - -# Install babel-core in all modules -lerna add babel-core -``` diff --git a/commands/add/__tests__/__fixtures__/unchanged/packages/package-1/package.json b/commands/add/__tests__/__fixtures__/unchanged/packages/package-1/package.json deleted file mode 100644 index 653428e4b5..0000000000 --- a/commands/add/__tests__/__fixtures__/unchanged/packages/package-1/package.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "name": "@test/package-1", - "version": "1.0.0", - "dependencies": { - }, - "devDependencies": { - } -} diff --git a/commands/add/__tests__/add-command.test.js b/commands/add/__tests__/add-command.test.js deleted file mode 100644 index f22d70c63e..0000000000 --- a/commands/add/__tests__/add-command.test.js +++ /dev/null @@ -1,342 +0,0 @@ -"use strict"; - -jest.mock("@lerna/bootstrap"); -jest.mock("pacote"); - -// mocked or stubbed modules -const bootstrap = require("@lerna/bootstrap"); -const pacote = require("pacote"); - -// helpers -const initFixture = require("@lerna-test/helpers").initFixtureFactory(__dirname); -const { getPackages } = require("@lerna/project"); - -// file under test -const lernaAdd = require("@lerna-test/helpers").commandRunner(require("../command")); - -// assertion helpers -expect.extend(require("@lerna-test/helpers/pkg-matchers")); - -describe("AddCommand", () => { - // we already have enough tests of BootstrapCommand - bootstrap.mockResolvedValue(); - // we don't need network requests during unit tests - pacote.manifest.mockResolvedValue({ version: "1.0.0" }); - - it("should throw without packages", async () => { - const testDir = await initFixture("basic"); - const command = lernaAdd(testDir)(); - - await expect(command).rejects.toThrow(/^Not enough non-option arguments/); - }); - - it("should throw for locally unsatisfiable version ranges", async () => { - const testDir = await initFixture("basic"); - const command = lernaAdd(testDir)("@test/package-1@2"); - - await expect(command).rejects.toThrow(/Requested range not satisfiable:/); - }); - - it("should throw for adding local package without specified version", async () => { - const testDir = await initFixture("unspecified-version"); - const command = lernaAdd(testDir)("@test/package-1"); - - await expect(command).rejects.toThrow(/Requested package has no version:/); - }); - - it("should throw when using pnpm", async () => { - const testDir = await initFixture("pnpm"); - const command = lernaAdd(testDir)("@test/package-1"); - - await expect(command).rejects.toThrow( - "Add is not supported when using `pnpm` workspaces. Use `pnpm` directly to add dependencies to packages: https://pnpm.io/cli/add" - ); - }); - - it("should reference remote dependencies", async () => { - const testDir = await initFixture("basic"); - - await lernaAdd(testDir)("tiny-tarball"); - const [pkg1, pkg2, pkg3, pkg4] = await getPackages(testDir); - - expect(pkg1).toDependOn("tiny-tarball"); - expect(pkg2).toDependOn("tiny-tarball"); - expect(pkg3).toDependOn("tiny-tarball"); - expect(pkg4).toDependOn("tiny-tarball"); - - expect(pacote.manifest).toHaveBeenLastCalledWith( - expect.objectContaining({ - // an npm-package-arg Result - name: "tiny-tarball", - fetchSpec: "latest", - registry: true, - type: "tag", - }), - expect.objectContaining({ - // an npm-conf snapshot - registry: "https://registry.npmjs.org/", - }) - ); - }); - - it("should reference local dependencies", async () => { - const testDir = await initFixture("basic"); - - await lernaAdd(testDir)("@test/package-1"); - const [, pkg2, pkg3, pkg4] = await getPackages(testDir); - - expect(pkg2).toDependOn("@test/package-1"); - expect(pkg3).toDependOn("@test/package-1"); - expect(pkg4).toDependOn("@test/package-1"); - }); - - it("should reference current caret range if unspecified", async () => { - const testDir = await initFixture("basic"); - - await lernaAdd(testDir)("@test/package-1"); - await lernaAdd(testDir)("@test/package-2"); - const [pkg1, pkg2] = await getPackages(testDir); - - expect(pkg1).toDependOn("@test/package-2", "^2.0.0"); - expect(pkg2).toDependOn("@test/package-1", "^1.0.0"); - }); - - it("should reference specified range", async () => { - const testDir = await initFixture("basic"); - - await lernaAdd(testDir)("@test/package-1@~1"); - const [, pkg2] = await getPackages(testDir); - - expect(pkg2).toDependOn("@test/package-1", "~1"); - }); - - it("should reference exact version if --exact", async () => { - const testDir = await initFixture("basic"); - - await lernaAdd(testDir)("@test/package-1", "--exact"); - const [, pkg2] = await getPackages(testDir); - - expect(pkg2).toDependOn("@test/package-1", "1.0.0", { - exact: true, - }); - }); - - it("adds explicit local file: specifier as file: specifier", async () => { - const testDir = await initFixture("basic"); - - await lernaAdd(testDir)("@test/package-1@file:packages/package-1"); - const [, pkg2] = await getPackages(testDir); - - expect(pkg2).toDependOn("@test/package-1", "file:../package-1"); - }); - - it("adds local dep as file: specifier when existing relationships are file: specifiers", async () => { - const testDir = await initFixture("existing"); - const [, , pkg3] = await getPackages(testDir); - - pkg3.updateLocalDependency({ name: "@test/package-2", type: "directory" }, "file:../package-2", ""); - await pkg3.serialize(); - - await lernaAdd(testDir)("@test/package-1"); - const [, pkg2] = await getPackages(testDir); - - expect(pkg2).toDependOn("@test/package-1", "file:../package-1"); - }); - - it("should add target package to devDependencies", async () => { - const testDir = await initFixture("basic"); - - await lernaAdd(testDir)("@test/package-1", "--dev"); - const [, pkg2, pkg3, pkg4] = await getPackages(testDir); - - expect(pkg2).toDevDependOn("@test/package-1"); - expect(pkg3).toDevDependOn("@test/package-1"); - expect(pkg4).toDevDependOn("@test/package-1"); - }); - - it("should add target package to devDependencies with alias", async () => { - const testDir = await initFixture("basic"); - - await lernaAdd(testDir)("-D", "@test/package-1"); - const [, pkg2] = await getPackages(testDir); - - expect(pkg2).toDevDependOn("@test/package-1"); - }); - - describe("peerDependencies", () => { - it("should add target package to peerDependencies", async () => { - const testDir = await initFixture("basic"); - - await lernaAdd(testDir)("@test/package-1", "--peer"); - const [, pkg2, pkg3, pkg4] = await getPackages(testDir); - - expect(pkg2).toPeerDependOn("@test/package-1"); - expect(pkg3).toPeerDependOn("@test/package-1"); - expect(pkg4).toPeerDependOn("@test/package-1"); - }); - - it("should add target package to peerDependencies with alias", async () => { - const testDir = await initFixture("basic"); - - await lernaAdd(testDir)("-P", "@test/package-1"); - const [, pkg2] = await getPackages(testDir); - - expect(pkg2).toPeerDependOn("@test/package-1"); - }); - }); - - it("should not reference packages to themeselves", async () => { - const testDir = await initFixture("basic"); - - await lernaAdd(testDir)("@test/package-1"); - const [pkg1] = await getPackages(testDir); - - expect(pkg1).not.toDependOn("@test/package-1"); - }); - - it("filters targets by optional directory globs", async () => { - const testDir = await initFixture("basic"); - - await lernaAdd(testDir)("@test/package-1", "packages/package-2"); - const [, pkg2, pkg3, pkg4] = await getPackages(testDir); - - expect(pkg2).toDependOn("@test/package-1"); - expect(pkg3).not.toDevDependOn("@test/package-1"); - expect(pkg4).not.toDevDependOn("@test/package-1"); - }); - - it("should retain existing dependencies", async () => { - const testDir = await initFixture("existing"); - - await lernaAdd(testDir)("@test/package-2"); - const [pkg1] = await getPackages(testDir); - - expect(pkg1).toDependOn("pify"); - }); - - it("should retain existing devDependencies", async () => { - const testDir = await initFixture("existing"); - - await lernaAdd(testDir)("@test/package-1", "--dev"); - const [, pkg2] = await getPackages(testDir); - - expect(pkg2).toDevDependOn("file-url"); - }); - - it("supports tag specifiers", async () => { - const testDir = await initFixture("basic"); - - await lernaAdd(testDir)("tiny-tarball@latest"); - const [pkg1] = await getPackages(testDir); - - expect(pkg1).toDependOn("tiny-tarball", "^1.0.0"); - }); - - it("supports version specifiers (exact)", async () => { - const testDir = await initFixture("basic"); - - await lernaAdd(testDir)("tiny-tarball@1.0.0"); - const [pkg1] = await getPackages(testDir); - - expect(pkg1).toDependOn("tiny-tarball", "1.0.0", { exact: true }); - }); - - it("accepts --registry option", async () => { - const testDir = await initFixture("basic"); - - pacote.manifest.mockImplementationOnce(() => { - const err = new Error("ENOTFOUND"); - return Promise.reject(err); - }); - - const command = lernaAdd(testDir)( - "@my-own/private-idaho", - "--registry", - "http://registry.cuckoo-banana-pants.com/" - ); - - // obviously this registry doesn't exist, thus it will always error - await expect(command).rejects.toThrow(/ENOTFOUND/); - - expect(pacote.manifest).toHaveBeenLastCalledWith( - expect.objectContaining({ - name: "@my-own/private-idaho", - }), - expect.objectContaining({ - registry: "http://registry.cuckoo-banana-pants.com/", - }) - ); - }); - - it("should bootstrap changed packages", async () => { - const testDir = await initFixture("basic"); - - await lernaAdd(testDir)("@test/package-1"); - - expect(bootstrap).toHaveBeenLastCalledWith( - expect.objectContaining({ - args: [], - cwd: testDir, - composed: "add", - }) - ); - }); - - it("should not pass filter options to bootstrap", async () => { - const testDir = await initFixture("existing"); - - await lernaAdd(testDir)( - "@test/package-2", - "--scope=@test/package-1", - "--ignore=@test/package-3", - "--no-private", - "--since=deadbeef", - "--include-filtered-dependents", - "--include-filtered-dependencies" - ); - const [pkg1] = await getPackages(testDir); - - expect(pkg1).toDependOn("@test/package-2"); - expect(bootstrap).toHaveBeenLastCalledWith( - expect.objectContaining({ - scope: undefined, - ignore: undefined, - private: undefined, - since: undefined, - excludeDependents: undefined, - includeDependents: undefined, - includeDependencies: undefined, - }) - ); - }); - - it("should not bootstrap unchanged packages", async () => { - const testDir = await initFixture("unchanged"); - - await lernaAdd(testDir)("@test/package-1"); - - expect(bootstrap).not.toHaveBeenCalled(); - }); - - it("skips bootstrap with --no-bootstrap", async () => { - const testDir = await initFixture("basic"); - - await lernaAdd(testDir)("@test/package-1", "--no-bootstrap"); - const [, pkg2] = await getPackages(testDir); - - expect(bootstrap).not.toHaveBeenCalled(); - expect(pkg2).toDependOn("@test/package-1", "^1.0.0"); - }); - - it("should reset a dependency from caret to exact", async () => { - const testDir = await initFixture("basic"); - - await lernaAdd(testDir)("@test/package-1"); - await lernaAdd(testDir)("@test/package-1", "--exact"); - const [, pkg2] = await getPackages(testDir); - - expect(pkg2).toDependOn("@test/package-1", "1.0.0", { - exact: true, - }); - }); -}); diff --git a/commands/add/command.js b/commands/add/command.js deleted file mode 100644 index 3c982c0806..0000000000 --- a/commands/add/command.js +++ /dev/null @@ -1,74 +0,0 @@ -"use strict"; - -const { filterOptions } = require("@lerna/filter-options"); - -/** - * @see https://github.com/yargs/yargs/blob/master/docs/advanced.md#providing-a-command-module - */ -exports.command = "add [globs..]"; - -exports.describe = "Add a single dependency to matched packages"; - -exports.builder = (yargs) => { - yargs - .positional("pkg", { - describe: "Package name to add as a dependency", - type: "string", - }) - .positional("globs", { - describe: "Optional package directory globs to match", - type: "array", - }) - .options({ - D: { - group: "Command Options:", - type: "boolean", - alias: "dev", - describe: "Save to devDependencies", - }, - E: { - group: "Command Options:", - type: "boolean", - alias: "exact", - describe: "Save version exactly", - }, - P: { - group: "Command Options:", - type: "boolean", - alias: "peer", - describe: "Save to peerDependencies", - }, - registry: { - group: "Command Options:", - describe: "Use the specified registry for all npm client operations.", - type: "string", - requiresArg: true, - }, - "no-bootstrap": { - group: "Command Options:", - describe: "Do not automatically chain `lerna bootstrap` after changes are made.", - type: "boolean", - }, - bootstrap: { - // proxy for --no-bootstrap - hidden: true, - type: "boolean", - }, - }) - .example( - "$0 add module-1 packages/prefix-*", - "Adds the module-1 package to the packages in the 'prefix-' prefixed folders" - ) - .example("$0 add module-1 --scope=module-2", "Install module-1 to module-2") - .example("$0 add module-1 --scope=module-2 --dev", "Install module-1 to module-2 in devDependencies") - .example("$0 add module-1 --scope=module-2 --peer", "Install module-1 to module-2 in peerDependencies") - .example("$0 add module-1", "Install module-1 in all modules except module-1") - .example("$0 add module-1 --no-bootstrap", "Skip automatic `lerna bootstrap`") - .example("$0 add babel-core", "Install babel-core in all modules"); - - return filterOptions(yargs); -}; - -exports.handler = function handler(argv) { - return require(".")(argv); -}; diff --git a/commands/add/index.js b/commands/add/index.js deleted file mode 100644 index c0c02c323e..0000000000 --- a/commands/add/index.js +++ /dev/null @@ -1,237 +0,0 @@ -"use strict"; - -const dedent = require("dedent"); -const npa = require("npm-package-arg"); -const pMap = require("p-map"); -const path = require("path"); -const pacote = require("pacote"); -const semver = require("semver"); - -const { Command } = require("@lerna/command"); -const npmConf = require("@lerna/npm-conf"); -const bootstrap = require("@lerna/bootstrap"); -const { ValidationError } = require("@lerna/validation-error"); -const { getFilteredPackages } = require("@lerna/filter-options"); -const { getRangeToReference } = require("./lib/get-range-to-reference"); - -module.exports = factory; - -function factory(argv) { - return new AddCommand(argv); -} - -class AddCommand extends Command { - get requiresGit() { - return false; - } - - get dependencyType() { - if (this.options.dev) { - return "devDependencies"; - } - if (this.options.peer) { - return "peerDependencies"; - } - return "dependencies"; - } - - initialize() { - if (this.options.npmClient === "pnpm") { - throw new ValidationError( - "EPNPMNOTSUPPORTED", - "Add is not supported when using `pnpm` workspaces. Use `pnpm` directly to add dependencies to packages: https://pnpm.io/cli/add" - ); - } - - this.spec = npa(this.options.pkg); - this.dirs = new Set(this.options.globs.map((fp) => path.resolve(this.project.rootPath, fp))); - this.selfSatisfied = this.packageSatisfied(); - - // https://docs.npmjs.com/misc/config#save-prefix - this.savePrefix = this.options.exact ? "" : "^"; - - if (this.packageGraph.has(this.spec.name) && !this.selfSatisfied) { - const available = this.packageGraph.get(this.spec.name).version; - - throw new ValidationError( - "ENOTSATISFIED", - dedent` - Requested range not satisfiable: - ${this.spec.name}@${this.spec.fetchSpec} (available: ${available}) - ` - ); - } - - let chain = Promise.resolve(); - - chain = chain.then(() => this.getPackageVersion()); - chain = chain.then((version) => { - if (version == null) { - throw new ValidationError( - "ENOTSATISFIED", - dedent` - Requested package has no version: ${this.spec.name} - ` - ); - } - this.spec.version = version; - }); - - chain = chain.then(() => getFilteredPackages(this.packageGraph, this.execOpts, this.options)); - chain = chain.then((filteredPackages) => { - this.filteredPackages = filteredPackages; - }); - - chain = chain.then(() => this.collectPackagesToChange()); - chain = chain.then((packagesToChange) => { - this.packagesToChange = packagesToChange; - }); - - return chain.then(() => { - const proceed = this.packagesToChange.length > 0; - - if (!proceed) { - this.logger.warn(`No packages found where ${this.spec.name} can be added.`); - } - - return proceed; - }); - } - - execute() { - const numberOfPackages = `${this.packagesToChange.length} package${ - this.packagesToChange.length > 1 ? "s" : "" - }`; - - this.logger.info("", `Adding ${this.spec.name} in ${numberOfPackages}`); - - let chain = Promise.resolve(); - - chain = chain.then(() => this.makeChanges()); - - if (this.options.bootstrap !== false) { - chain = chain.then(() => { - const argv = Object.assign({}, this.options, { - args: [], - cwd: this.project.rootPath, - // silence initial cli version logging, etc - composed: "add", - // NEVER pass filter-options, it is very bad - scope: undefined, - ignore: undefined, - private: undefined, - since: undefined, - excludeDependents: undefined, - includeDependents: undefined, - includeDependencies: undefined, - }); - - return bootstrap(argv); - }); - } - - return chain; - } - - collectPackagesToChange() { - const { name: targetName } = this.spec; - let result = this.filteredPackages; - - // Skip packages that only would install themselves - if (this.packageGraph.has(targetName)) { - result = result.filter((pkg) => pkg.name !== targetName); - } - - // Skip packages that are not selected by dir globs - if (this.dirs.size) { - result = result.filter((pkg) => this.dirs.has(pkg.location)); - } - - // Skip packages without actual changes to manifest - result = result.filter((pkg) => { - const deps = this.getPackageDeps(pkg); - - // Check if one of the packages to install necessitates a change to pkg's manifest - if (!(targetName in deps)) { - return true; - } - - return getRangeToReference(this.spec, deps, pkg.location, this.savePrefix) !== deps[targetName]; - }); - - return result; - } - - makeChanges() { - const { name: targetName } = this.spec; - - return pMap(this.packagesToChange, (pkg) => { - const deps = this.getPackageDeps(pkg); - const range = getRangeToReference(this.spec, deps, pkg.location, this.savePrefix); - - this.logger.verbose("add", `${targetName}@${range} to ${this.dependencyType} in ${pkg.name}`); - deps[targetName] = range; - - return pkg.serialize(); - }); - } - - getPackageDeps(pkg) { - let deps = pkg.get(this.dependencyType); - - if (!deps) { - deps = {}; - pkg.set(this.dependencyType, deps); - } - - return deps; - } - - getPackageVersion() { - if (this.selfSatisfied) { - const node = this.packageGraph.get(this.spec.name); - - return Promise.resolve(this.spec.saveRelativeFileSpec ? node.location : node.version); - } - - // @see https://github.com/zkat/pacote/blob/latest/lib/util/opt-check.js - const opts = npmConf({ - includeDeprecated: false, - // we can't pass everything, as our --scope conflicts with pacote's --scope - registry: this.options.registry, - }); - - return pacote.manifest(this.spec, opts.snapshot).then((pkg) => pkg.version); - } - - packageSatisfied() { - const { name, fetchSpec } = this.spec; - const pkg = this.packageGraph.get(name); - - if (!pkg) { - return false; - } - - // an explicit "file:packages/foo" always saves as a relative "file:../foo" - if (this.spec.type === "directory" && fetchSpec === pkg.location) { - this.spec.saveRelativeFileSpec = true; - - return true; - } - - // existing relative file spec means local dep should be added the same way - this.spec.saveRelativeFileSpec = Array.from(this.packageGraph.values()).some( - (node) => - node.localDependencies.size && - Array.from(node.localDependencies.values()).some((resolved) => resolved.type === "directory") - ); - - if (fetchSpec === "latest") { - return true; - } - - return semver.intersects(pkg.version, fetchSpec); - } -} - -module.exports.AddCommand = AddCommand; diff --git a/commands/add/lib/get-range-to-reference.js b/commands/add/lib/get-range-to-reference.js deleted file mode 100644 index aad0f04ae6..0000000000 --- a/commands/add/lib/get-range-to-reference.js +++ /dev/null @@ -1,32 +0,0 @@ -"use strict"; - -const npa = require("npm-package-arg"); -const path = require("path"); -const semver = require("semver"); - -module.exports.getRangeToReference = getRangeToReference; - -/** @typedef {import("npm-package-arg").Result & { version: string; saveRelativeFileSpec?: boolean; }} DecoratedSpec */ - -/** - * Determine version range used when serializing changes or choosing packages to change. - * @param {DecoratedSpec} spec - * @param {Record} deps - * @param {string} loc - * @param {string} prefix - */ -function getRangeToReference(spec, deps, loc, prefix) { - const current = deps[spec.name]; - const resolved = spec.type === "tag" ? `${prefix}${spec.version}` : spec.fetchSpec; - - if (spec.saveRelativeFileSpec) { - // "version" has been resolved to pkg.location in getPackageVersion() - return npa.resolve(spec.name, path.relative(loc, spec.version), loc).saveSpec; - } - - if (prefix && current && semver.intersects(current, resolved)) { - return current; - } - - return resolved; -} diff --git a/commands/add/package.json b/commands/add/package.json deleted file mode 100644 index 393929b28d..0000000000 --- a/commands/add/package.json +++ /dev/null @@ -1,47 +0,0 @@ -{ - "name": "@lerna/add", - "version": "6.4.1", - "description": "Add a dependency to matched packages", - "keywords": [ - "lerna", - "command" - ], - "homepage": "https://lerna.js.org", - "license": "MIT", - "author": { - "name": "Daniel Stockman", - "url": "https://github.com/evocateur" - }, - "files": [ - "command.js", - "index.js", - "lib" - ], - "main": "index.js", - "engines": { - "node": "^14.15.0 || >=16.0.0" - }, - "publishConfig": { - "access": "public" - }, - "repository": { - "type": "git", - "url": "git+https://github.com/lerna/lerna.git", - "directory": "commands/add" - }, - "scripts": { - "test": "echo \"Run tests from root\" && exit 1" - }, - "dependencies": { - "@lerna/bootstrap": "file:../bootstrap", - "@lerna/command": "file:../../core/command", - "@lerna/filter-options": "file:../../core/filter-options", - "@lerna/npm-conf": "file:../../utils/npm-conf", - "@lerna/validation-error": "file:../../core/validation-error", - "dedent": "^0.7.0", - "npm-package-arg": "8.1.1", - "p-map": "^4.0.0", - "pacote": "^13.6.1", - "semver": "^7.3.4" - } -} diff --git a/commands/bootstrap/CHANGELOG.md b/commands/bootstrap/CHANGELOG.md deleted file mode 100644 index 124ce7ab8e..0000000000 --- a/commands/bootstrap/CHANGELOG.md +++ /dev/null @@ -1,664 +0,0 @@ -# Change Log - -All notable changes to this project will be documented in this file. -See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. - -## [6.4.1](https://github.com/lerna/lerna/compare/v6.4.0...v6.4.1) (2023-01-12) - -**Note:** Version bump only for package @lerna/bootstrap - -# [6.4.0](https://github.com/lerna/lerna/compare/v6.3.0...v6.4.0) (2023-01-05) - -**Note:** Version bump only for package @lerna/bootstrap - -# [6.3.0](https://github.com/lerna/lerna/compare/v6.2.0...v6.3.0) (2022-12-26) - -**Note:** Version bump only for package @lerna/bootstrap - -# [6.2.0](https://github.com/lerna/lerna/compare/v6.1.0...v6.2.0) (2022-12-13) - -**Note:** Version bump only for package @lerna/bootstrap - -# [6.1.0](https://github.com/lerna/lerna/compare/v6.0.3...v6.1.0) (2022-11-29) - -**Note:** Version bump only for package @lerna/bootstrap - -## [6.0.3](https://github.com/lerna/lerna/compare/v6.0.2...v6.0.3) (2022-11-07) - -**Note:** Version bump only for package @lerna/bootstrap - -## [6.0.2](https://github.com/lerna/lerna/compare/v6.0.1...v6.0.2) (2022-11-02) - -**Note:** Version bump only for package @lerna/bootstrap - -## [6.0.1](https://github.com/lerna/lerna/compare/v6.0.0...v6.0.1) (2022-10-14) - -**Note:** Version bump only for package @lerna/bootstrap - -# [6.0.0](https://github.com/lerna/lerna/compare/v6.0.0-alpha.2...v6.0.0) (2022-10-12) - -**Note:** Version bump only for package @lerna/bootstrap - -# [6.0.0-alpha.2](https://github.com/lerna/lerna/compare/v6.0.0-alpha.1...v6.0.0-alpha.2) (2022-10-12) - -**Note:** Version bump only for package @lerna/bootstrap - -# [6.0.0-alpha.1](https://github.com/lerna/lerna/compare/v5.6.2...v6.0.0-alpha.1) (2022-10-09) - -# [6.0.0-alpha.0](https://github.com/lerna/lerna/compare/v5.6.1...v6.0.0-alpha.0) (2022-10-07) - -**Note:** Version bump only for package @lerna/bootstrap - -## [5.6.2](https://github.com/lerna/lerna/compare/v5.6.1...v5.6.2) (2022-10-09) - -### Bug Fixes - -- **bootstrap:** reject-cycles when using workspaces ([#3168](https://github.com/lerna/lerna/issues/3168)) ([8a47a6d](https://github.com/lerna/lerna/commit/8a47a6d55a871eb6ce1c0e620a3cea2b92bf76ea)) - -## [5.6.1](https://github.com/lerna/lerna/compare/v5.6.0...v5.6.1) (2022-09-30) - -**Note:** Version bump only for package @lerna/bootstrap - -# [5.6.0](https://github.com/lerna/lerna/compare/v5.5.4...v5.6.0) (2022-09-29) - -**Note:** Version bump only for package @lerna/bootstrap - -## [5.5.4](https://github.com/lerna/lerna/compare/v5.5.3...v5.5.4) (2022-09-28) - -**Note:** Version bump only for package @lerna/bootstrap - -## [5.5.3](https://github.com/lerna/lerna/compare/v5.5.2...v5.5.3) (2022-09-28) - -**Note:** Version bump only for package @lerna/bootstrap - -## [5.5.2](https://github.com/lerna/lerna/compare/v5.5.1...v5.5.2) (2022-09-20) - -**Note:** Version bump only for package @lerna/bootstrap - -## [5.5.1](https://github.com/lerna/lerna/compare/v5.5.0...v5.5.1) (2022-09-09) - -**Note:** Version bump only for package @lerna/bootstrap - -# [5.5.0](https://github.com/lerna/lerna/compare/v5.4.3...v5.5.0) (2022-08-31) - -### Features - -- pnpm workspaces support ([#3284](https://github.com/lerna/lerna/issues/3284)) ([1b18dbe](https://github.com/lerna/lerna/commit/1b18dbeb03e98c70b5428a9fe457781a59f8d65d)) - -## [5.4.3](https://github.com/lerna/lerna/compare/v5.4.2...v5.4.3) (2022-08-16) - -**Note:** Version bump only for package @lerna/bootstrap - -## [5.4.2](https://github.com/lerna/lerna/compare/v5.4.1...v5.4.2) (2022-08-14) - -**Note:** Version bump only for package @lerna/bootstrap - -## [5.4.1](https://github.com/lerna/lerna/compare/v5.4.0...v5.4.1) (2022-08-12) - -**Note:** Version bump only for package @lerna/bootstrap - -# [5.4.0](https://github.com/lerna/lerna/compare/v5.3.0...v5.4.0) (2022-08-08) - -**Note:** Version bump only for package @lerna/bootstrap - -# [5.3.0](https://github.com/lerna/lerna/compare/v5.2.0...v5.3.0) (2022-07-27) - -### Bug Fixes - -- **run-lifecycle:** lifecycle events should run to completion in series ([#3262](https://github.com/lerna/lerna/issues/3262)) ([2f51588](https://github.com/lerna/lerna/commit/2f51588f3686ab9bb015a12294f3eca11cb41fad)) - -# [5.2.0](https://github.com/lerna/lerna/compare/v5.1.8...v5.2.0) (2022-07-22) - -### Features - -- **init:** default useNx and useWorkspaces to true for new lerna workspaces ([#3255](https://github.com/lerna/lerna/issues/3255)) ([a0e83e5](https://github.com/lerna/lerna/commit/a0e83e5220f6e3d30b96b60bbaf14c5392653c2e)) - -## [5.1.8](https://github.com/lerna/lerna/compare/v5.1.7...v5.1.8) (2022-07-07) - -**Note:** Version bump only for package @lerna/bootstrap - -## [5.1.7](https://github.com/lerna/lerna/compare/v5.1.6...v5.1.7) (2022-07-06) - -**Note:** Version bump only for package @lerna/bootstrap - -## [5.1.6](https://github.com/lerna/lerna/compare/v5.1.5...v5.1.6) (2022-06-24) - -**Note:** Version bump only for package @lerna/bootstrap - -## [5.1.5](https://github.com/lerna/lerna/compare/v5.1.4...v5.1.5) (2022-06-24) - -**Note:** Version bump only for package @lerna/bootstrap - -## [5.1.4](https://github.com/lerna/lerna/compare/v5.1.3...v5.1.4) (2022-06-15) - -**Note:** Version bump only for package @lerna/bootstrap - -## [5.1.3](https://github.com/lerna/lerna/compare/v5.1.2...v5.1.3) (2022-06-15) - -**Note:** Version bump only for package @lerna/bootstrap - -## [5.1.2](https://github.com/lerna/lerna/compare/v5.1.1...v5.1.2) (2022-06-13) - -### Bug Fixes - -- update all transitive inclusions of ansi-regex ([#3166](https://github.com/lerna/lerna/issues/3166)) ([56eaa15](https://github.com/lerna/lerna/commit/56eaa153283be3b1e7d7793d3266fc51801fad8e)) - -## [5.1.1](https://github.com/lerna/lerna/compare/v5.1.0...v5.1.1) (2022-06-09) - -### Bug Fixes - -- allow maintenance LTS node 14 engines starting at 14.15.0 ([#3161](https://github.com/lerna/lerna/issues/3161)) ([72305e4](https://github.com/lerna/lerna/commit/72305e4dbab607a2d87ae4efa6ee577c93a9dda9)) - -# [5.1.0](https://github.com/lerna/lerna/compare/v5.0.0...v5.1.0) (2022-06-07) - -### Features - -- handle the edge cases in the lerna-nx integration ([c6808fc](https://github.com/lerna/lerna/commit/c6808fc8f2dfe793bf72a64cf2d3909e0bdabba8)) - -# [5.1.0-alpha.0](https://github.com/lerna/lerna/compare/v4.0.0...v5.1.0-alpha.0) (2022-05-25) - -### Bug Fixes - -- replace read-package-tree with @npmcli/arborist ([#3133](https://github.com/lerna/lerna/issues/3133)) ([f1c10a4](https://github.com/lerna/lerna/commit/f1c10a40fe667e5012a60e9b372a8e7996465de1)) - -# [5.0.0](https://github.com/lerna/lerna/compare/v4.0.0...v5.0.0) (2022-05-24) - -### Bug Fixes - -- replace read-package-tree with @npmcli/arborist ([#3133](https://github.com/lerna/lerna/issues/3133)) ([f1c10a4](https://github.com/lerna/lerna/commit/f1c10a40fe667e5012a60e9b372a8e7996465de1)) - -# [4.0.0](https://github.com/lerna/lerna/compare/v3.22.1...v4.0.0) (2021-02-10) - -### Features - -- **deps:** Bump dependencies ([affed1c](https://github.com/lerna/lerna/commit/affed1ce0fce91f01b0a9eafe357db2d985b974f)) -- Consume named exports of sibling modules ([63499e3](https://github.com/lerna/lerna/commit/63499e33652bc78fe23751875d74017e2f16a689)) -- **deps:** get-port@^5.1.1 ([b1b2275](https://github.com/lerna/lerna/commit/b1b2275237f16a26e6f96deffee8b0f72d8ce17d)) -- **deps:** multimatch@^5.0.0 ([0172526](https://github.com/lerna/lerna/commit/017252644cfd2394e77680673bae0e31ffa58d5e)) -- **deps:** npm-package-arg@^8.1.0 ([12c8923](https://github.com/lerna/lerna/commit/12c892342d33b86a00ee2cf9079f9b26fe316dc6)) -- **deps:** p-finally -> Promise.prototype.finally() ([028db04](https://github.com/lerna/lerna/commit/028db045b1221df000a2b98c5dceb1e4915a7806)) -- **deps:** p-finally@^2.0.1 ([165e47e](https://github.com/lerna/lerna/commit/165e47e722acf6462cf0b4e3a7d0e14d3971e7fb)) -- **deps:** p-map-series@^2.1.0 ([7f68076](https://github.com/lerna/lerna/commit/7f680767e0b3c7a15f951c51d4975150fb6e9112)) -- **deps:** p-map@^4.0.0 ([92b1364](https://github.com/lerna/lerna/commit/92b1364735e1f2cf379cf1047c60c4fb897d55f5)) -- **deps:** p-waterfall@^2.1.0 ([7b7ea50](https://github.com/lerna/lerna/commit/7b7ea503e8371e7f663fd604bff51aebfe9e7b33)) -- **deps:** read-package-tree@^5.3.1 ([3311780](https://github.com/lerna/lerna/commit/331178049e61f3c401a074d27e84d12856e3494e)) -- **deps:** semver@^7.3.2 ([003ad66](https://github.com/lerna/lerna/commit/003ad6641fab8b4e3a82251ebffd27061bd6a31b)) -- Drop support for Node v6.x & v8.x ([ff4bb4d](https://github.com/lerna/lerna/commit/ff4bb4da215555e3bb136f5af09b5cbc631e57bb)) - -### BREAKING CHANGES - -- Node v6.x & v8.x are no longer supported. Please upgrade to the latest LTS release. - -Here's the gnarly one-liner I used to make these changes: - -``` -npx lerna exec --concurrency 1 --stream -- 'json -I -f package.json -e '"'"'this.engines=this.engines||{};this.engines.node=">= 10.18.0"'"'" -``` - -(requires `npm i -g json` beforehand) - -# [3.21.0](https://github.com/lerna/lerna/compare/v3.20.2...v3.21.0) (2020-05-13) - -**Note:** Version bump only for package @lerna/bootstrap - -# [3.20.0](https://github.com/lerna/lerna/compare/v3.19.0...v3.20.0) (2019-12-27) - -**Note:** Version bump only for package @lerna/bootstrap - -## [3.18.5](https://github.com/lerna/lerna/compare/v3.18.4...v3.18.5) (2019-11-20) - -### Bug Fixes - -- Auto-fix prettier formatting ([5344820](https://github.com/lerna/lerna/commit/5344820fc65da081d17f7fd2adb50ffe7101905b)) - -## [3.18.4](https://github.com/lerna/lerna/compare/v3.18.3...v3.18.4) (2019-11-08) - -### Bug Fixes - -- **filter-options:** Ensure `--include-merged-tags` is available to all `--since`-filterable commands ([287bcd8](https://github.com/lerna/lerna/commit/287bcd8b5c8dbb2dc4def5c933d0b4917c34813e)), closes [#2332](https://github.com/lerna/lerna/issues/2332) - -# [3.18.0](https://github.com/lerna/lerna/compare/v3.17.0...v3.18.0) (2019-10-15) - -### Bug Fixes - -- **bootstrap:** Move all filter logging into get-filtered-packages method ([54dca56](https://github.com/lerna/lerna/commit/54dca563efb13ad88d478ac31668f6e13a1d99e7)) -- **options:** Explicit `--force-local` ([6948a11](https://github.com/lerna/lerna/commit/6948a11dbc2f845db78a2c666d0ea8160612e41e)) -- **options:** Explicit `--use-workspaces` ([ac8385d](https://github.com/lerna/lerna/commit/ac8385d77e931397b68b068ded7ac83dd1a19d68)) - -### Features - -- Upgrade to yargs@14 ([5e60213](https://github.com/lerna/lerna/commit/5e60213e93e3ee229a9341a14e420ed2401001dd)) -- **filter-options:** Rename `--include-filtered-*` options ([f2c3a92](https://github.com/lerna/lerna/commit/f2c3a92fe41b6fdc5d11269f0f2c3e27761b4c85)) - -# [3.17.0](https://github.com/lerna/lerna/compare/v3.16.5...v3.17.0) (2019-10-10) - -### Features - -- **link:** Use `publishConfig.directory` as symlink source if it exists to allow linking sub-directories ([#2274](https://github.com/lerna/lerna/issues/2274)) ([d04ce8e](https://github.com/lerna/lerna/commit/d04ce8e10503003e498c44d0db5ff455054d7d71)) - -## [3.16.5](https://github.com/lerna/lerna/compare/v3.16.4...v3.16.5) (2019-10-07) - -### Bug Fixes - -- **bootstrap:** Run lifecycle scripts in topological queue instead of batches ([#2224](https://github.com/lerna/lerna/issues/2224)) ([d8d33f7](https://github.com/lerna/lerna/commit/d8d33f7)) - -## [3.16.2](https://github.com/lerna/lerna/compare/v3.16.1...v3.16.2) (2019-07-22) - -**Note:** Version bump only for package @lerna/bootstrap - -## [3.16.1](https://github.com/lerna/lerna/compare/v3.16.0...v3.16.1) (2019-07-19) - -**Note:** Version bump only for package @lerna/bootstrap - -# [3.16.0](https://github.com/lerna/lerna/compare/v3.15.0...v3.16.0) (2019-07-18) - -### Features - -- **bootstrap:** Add `--strict` option to enable throwing when `--hoist` warns ([#2140](https://github.com/lerna/lerna/issues/2140)) ([91437b5](https://github.com/lerna/lerna/commit/91437b5)) -- **deps:** `get-port@^4.2.0` ([778ae6a](https://github.com/lerna/lerna/commit/778ae6a)) -- **deps:** `multimatch@^3.0.0` ([968b0d7](https://github.com/lerna/lerna/commit/968b0d7)) -- **deps:** `p-map@^2.1.0` ([9e58394](https://github.com/lerna/lerna/commit/9e58394)) -- **deps:** `semver@^6.2.0` ([d8016d9](https://github.com/lerna/lerna/commit/d8016d9)) - -# [3.15.0](https://github.com/lerna/lerna/compare/v3.14.2...v3.15.0) (2019-06-09) - -**Note:** Version bump only for package @lerna/bootstrap - -## [3.14.2](https://github.com/lerna/lerna/compare/v3.14.1...v3.14.2) (2019-06-09) - -### Bug Fixes - -- **bootstrap:** Respect `--force-local` option ([#2104](https://github.com/lerna/lerna/issues/2104)) ([c2fb639](https://github.com/lerna/lerna/commit/c2fb639)) - -# [3.14.0](https://github.com/lerna/lerna/compare/v3.13.4...v3.14.0) (2019-05-14) - -**Note:** Version bump only for package @lerna/bootstrap - -## [3.13.3](https://github.com/lerna/lerna/compare/v3.13.2...v3.13.3) (2019-04-17) - -**Note:** Version bump only for package @lerna/bootstrap - -## [3.13.1](https://github.com/lerna/lerna/compare/v3.13.0...v3.13.1) (2019-02-26) - -**Note:** Version bump only for package @lerna/bootstrap - -# [3.13.0](https://github.com/lerna/lerna/compare/v3.12.1...v3.13.0) (2019-02-15) - -### Features - -- **meta:** Add `repository.directory` field to package.json ([aec5023](https://github.com/lerna/lerna/commit/aec5023)) -- **meta:** Normalize package.json `homepage` field ([abeb4dc](https://github.com/lerna/lerna/commit/abeb4dc)) - -## [3.12.1](https://github.com/lerna/lerna/compare/v3.12.0...v3.12.1) (2019-02-14) - -**Note:** Version bump only for package @lerna/bootstrap - -# [3.12.0](https://github.com/lerna/lerna/compare/v3.11.1...v3.12.0) (2019-02-14) - -**Note:** Version bump only for package @lerna/bootstrap - -# [3.11.0](https://github.com/lerna/lerna/compare/v3.10.8...v3.11.0) (2019-02-08) - -### Bug Fixes - -- **deps:** Explicit npm-package-arg ^6.1.0 ([4b20791](https://github.com/lerna/lerna/commit/4b20791)) -- **deps:** Explicit npmlog ^4.1.2 ([571c2e2](https://github.com/lerna/lerna/commit/571c2e2)) -- **deps:** Remove unused libnpm (replaced by direct sub-packages) ([1caeb28](https://github.com/lerna/lerna/commit/1caeb28)) - -## [3.10.6](https://github.com/lerna/lerna/compare/v3.10.5...v3.10.6) (2019-01-19) - -**Note:** Version bump only for package @lerna/bootstrap - -## [3.10.5](https://github.com/lerna/lerna/compare/v3.10.4...v3.10.5) (2019-01-11) - -**Note:** Version bump only for package @lerna/bootstrap - -## [3.10.4](https://github.com/lerna/lerna/compare/v3.10.3...v3.10.4) (2019-01-10) - -### Bug Fixes - -- **bootstrap:** Do not `npm ci` when hoisting ([27516b9](https://github.com/lerna/lerna/commit/27516b9)), closes [#1865](https://github.com/lerna/lerna/issues/1865) - -## [3.10.3](https://github.com/lerna/lerna/compare/v3.10.2...v3.10.3) (2019-01-10) - -### Bug Fixes - -- **bootstrap:** When filtering, only bootstrap filtered packages ([71174e4](https://github.com/lerna/lerna/commit/71174e4)), closes [#1421](https://github.com/lerna/lerna/issues/1421) [#1766](https://github.com/lerna/lerna/issues/1766) - -## [3.10.2](https://github.com/lerna/lerna/compare/v3.10.1...v3.10.2) (2019-01-09) - -### Bug Fixes - -- **bootstrap:** Remove fancy root lifecycle execution, it was foolish ([9f80722](https://github.com/lerna/lerna/commit/9f80722)), closes [#1857](https://github.com/lerna/lerna/issues/1857) - -## [3.10.1](https://github.com/lerna/lerna/compare/v3.10.0...v3.10.1) (2019-01-09) - -**Note:** Version bump only for package @lerna/bootstrap - -# [3.10.0](https://github.com/lerna/lerna/compare/v3.9.1...v3.10.0) (2019-01-08) - -**Note:** Version bump only for package @lerna/bootstrap - -## [3.9.1](https://github.com/lerna/lerna/compare/v3.9.0...v3.9.1) (2019-01-08) - -### Bug Fixes - -- **bootstrap:** Don't pass `--ignore-scripts` to `npm install` ([e602838](https://github.com/lerna/lerna/commit/e602838)), closes [#1855](https://github.com/lerna/lerna/issues/1855) -- **bootstrap:** Prevent recursive execution from all install lifecycles ([ea9dbbe](https://github.com/lerna/lerna/commit/ea9dbbe)) - -# [3.9.0](https://github.com/lerna/lerna/compare/v3.8.5...v3.9.0) (2019-01-08) - -### Bug Fixes - -- **bootstrap:** Only run install lifecycles once-per-package, in topological order ([929ae22](https://github.com/lerna/lerna/commit/929ae22)) - -### Features - -- **bootstrap:** Add `--ignore-prepublish` option ([f14fc06](https://github.com/lerna/lerna/commit/f14fc06)) -- **bootstrap:** Run root install lifecycles where appropriate ([944e36f](https://github.com/lerna/lerna/commit/944e36f)) - -## [3.8.5](https://github.com/lerna/lerna/compare/v3.8.4...v3.8.5) (2019-01-05) - -**Note:** Version bump only for package @lerna/bootstrap - -## [3.8.2](https://github.com/lerna/lerna/compare/v3.8.1...v3.8.2) (2019-01-03) - -### Bug Fixes - -- **bootstrap:** Bail out of hoisted recursive lifecycles ([169c943](https://github.com/lerna/lerna/commit/169c943)), closes [#1125](https://github.com/lerna/lerna/issues/1125) - -## [3.8.1](https://github.com/lerna/lerna/compare/v3.8.0...v3.8.1) (2018-12-31) - -### Bug Fixes - -- **progress:** Correctly avoid progress where we don't want it ([0de3df9](https://github.com/lerna/lerna/commit/0de3df9)) -- **progress:** Enable progress during logging setup, correcting default ([da81e60](https://github.com/lerna/lerna/commit/da81e60)) - -## [3.7.2](https://github.com/lerna/lerna/compare/v3.7.1...v3.7.2) (2018-12-21) - -**Note:** Version bump only for package @lerna/bootstrap - -## [3.7.1](https://github.com/lerna/lerna/compare/v3.7.0...v3.7.1) (2018-12-20) - -### Bug Fixes - -- **bootstrap:** Pulse progress bar during execution ([b38a151](https://github.com/lerna/lerna/commit/b38a151)) - -# [3.7.0](https://github.com/lerna/lerna/compare/v3.6.0...v3.7.0) (2018-12-19) - -### Bug Fixes - -- **bootstrap:** Use run-lifecycle factory instead of manual filtering ([d32feaa](https://github.com/lerna/lerna/commit/d32feaa)) - -# [3.6.0](https://github.com/lerna/lerna/compare/v3.5.1...v3.6.0) (2018-12-07) - -### Features - -- **bootstrap:** Support `--force-local` option ([#1807](https://github.com/lerna/lerna/issues/1807)) ([25572af](https://github.com/lerna/lerna/commit/25572af)), closes [#1763](https://github.com/lerna/lerna/issues/1763) -- Migrate existing usage to libnpm ([0d3a786](https://github.com/lerna/lerna/commit/0d3a786)), closes [#1767](https://github.com/lerna/lerna/issues/1767) - -# [3.5.0](https://github.com/lerna/lerna/compare/v3.4.3...v3.5.0) (2018-11-27) - -### Bug Fixes - -- prettier ([001a6df](https://github.com/lerna/lerna/commit/001a6df)) - -## [3.4.1](https://github.com/lerna/lerna/compare/v3.4.0...v3.4.1) (2018-10-04) - -### Bug Fixes - -- **bootstrap:** Constrain npm-conf argument object to options.registry only ([987fd26](https://github.com/lerna/lerna/commit/987fd26)) - - - -## [3.3.2](https://github.com/lerna/lerna/compare/v3.3.1...v3.3.2) (2018-09-12) - -**Note:** Version bump only for package @lerna/bootstrap - - - -## [3.3.1](https://github.com/lerna/lerna/compare/v3.3.0...v3.3.1) (2018-09-11) - -**Note:** Version bump only for package @lerna/bootstrap - - - -# [3.3.0](https://github.com/lerna/lerna/compare/v3.2.1...v3.3.0) (2018-09-06) - -### Bug Fixes - -- **run-lifecycle:** Propagate exit code when execution fails ([4763f95](https://github.com/lerna/lerna/commit/4763f95)), closes [#1495](https://github.com/lerna/lerna/issues/1495) - - - -# [3.2.0](https://github.com/lerna/lerna/compare/v3.1.4...v3.2.0) (2018-08-28) - -**Note:** Version bump only for package @lerna/bootstrap - - - -## [3.1.4](https://github.com/lerna/lerna/compare/v3.1.3...v3.1.4) (2018-08-21) - -**Note:** Version bump only for package @lerna/bootstrap - - - -## [3.1.3](https://github.com/lerna/lerna/compare/v3.1.2...v3.1.3) (2018-08-21) - -### Bug Fixes - -- **global-options:** Move env defaults to command superclass ([6d8e405](https://github.com/lerna/lerna/commit/6d8e405)), closes [#1449](https://github.com/lerna/lerna/issues/1449) - - - -## [3.1.2](https://github.com/lerna/lerna/compare/v3.1.1...v3.1.2) (2018-08-20) - -### Bug Fixes - -- Setup instance.filteredPackages explicitly ([32357f8](https://github.com/lerna/lerna/commit/32357f8)) -- **bootstrap:** Remove redundant duplicate name check ([c2405a1](https://github.com/lerna/lerna/commit/c2405a1)) - - - -# [3.1.0](https://github.com/lerna/lerna/compare/v3.0.6...v3.1.0) (2018-08-17) - -**Note:** Version bump only for package @lerna/bootstrap - - - -## [3.0.6](https://github.com/lerna/lerna/compare/v3.0.5...v3.0.6) (2018-08-16) - -**Note:** Version bump only for package @lerna/bootstrap - - - -## [3.0.5](https://github.com/lerna/lerna/compare/v3.0.4...v3.0.5) (2018-08-15) - -**Note:** Version bump only for package @lerna/bootstrap - - - -## [3.0.4](https://github.com/lerna/lerna/compare/v3.0.3...v3.0.4) (2018-08-14) - -**Note:** Version bump only for package @lerna/bootstrap - - - -# [3.0.0](https://github.com/lerna/lerna/compare/v3.0.0-rc.0...v3.0.0) (2018-08-10) - -**Note:** Version bump only for package @lerna/bootstrap - - - -# [3.0.0-rc.0](https://github.com/lerna/lerna/compare/v3.0.0-beta.21...v3.0.0-rc.0) (2018-07-27) - -### Features - -- Add description from --help summary [skip ci] ([9b65d8e](https://github.com/lerna/lerna/commit/9b65d8e)) -- **cli:** Upgrade to Yargs 12 ([7899ab8](https://github.com/lerna/lerna/commit/7899ab8)) - - - -# [3.0.0-beta.21](https://github.com/lerna/lerna/compare/v3.0.0-beta.20...v3.0.0-beta.21) (2018-05-12) - -**Note:** Version bump only for package @lerna/bootstrap - - - -# [3.0.0-beta.20](https://github.com/lerna/lerna/compare/v3.0.0-beta.19...v3.0.0-beta.20) (2018-05-07) - -**Note:** Version bump only for package @lerna/bootstrap - - - -# [3.0.0-beta.19](https://github.com/lerna/lerna/compare/v3.0.0-beta.18...v3.0.0-beta.19) (2018-05-03) - -**Note:** Version bump only for package @lerna/bootstrap - - - -# [3.0.0-beta.18](https://github.com/lerna/lerna/compare/v3.0.0-beta.17...v3.0.0-beta.18) (2018-04-24) - -**Note:** Version bump only for package @lerna/bootstrap - - - -# [3.0.0-beta.17](https://github.com/lerna/lerna/compare/v3.0.0-beta.16...v3.0.0-beta.17) (2018-04-13) - -### Bug Fixes - -- **bootstrap:** Pass npm-conf to feature predicate instead of directly reading process.env ([b4af3c9](https://github.com/lerna/lerna/commit/b4af3c9)) -- **bootstrap:** Pluralize log text ([#1232](https://github.com/lerna/lerna/issues/1232)) ([5c74760](https://github.com/lerna/lerna/commit/5c74760)) - - - -# [3.0.0-beta.15](https://github.com/lerna/lerna/compare/v3.0.0-beta.14...v3.0.0-beta.15) (2018-04-09) - -### Features - -- **bootstrap:** Use `npm ci` with `--ci` option ([#1360](https://github.com/lerna/lerna/issues/1360)) ([d7e33c6](https://github.com/lerna/lerna/commit/d7e33c6)) - - - -# [3.0.0-beta.14](https://github.com/lerna/lerna/compare/v3.0.0-beta.13...v3.0.0-beta.14) (2018-04-03) - -### Bug Fixes - -- **logging:** Log failures from package scripts once, not twice ([436cfe1](https://github.com/lerna/lerna/commit/436cfe1)) - - - -# [3.0.0-beta.13](https://github.com/lerna/lerna/compare/v3.0.0-beta.12...v3.0.0-beta.13) (2018-03-31) - -### Features - -- Enable progress bars only when necessary ([b766c83](https://github.com/lerna/lerna/commit/b766c83)) - - - -# [3.0.0-beta.12](https://github.com/lerna/lerna/compare/v3.0.0-beta.11...v3.0.0-beta.12) (2018-03-30) - -### Features - -- **package:** Add Map-like get/set methods, remove raw json getter ([707d1f0](https://github.com/lerna/lerna/commit/707d1f0)) -- **project:** Merge `package` and `packageJson` into `manifest` ([9a47ff7](https://github.com/lerna/lerna/commit/9a47ff7)) - -### BREAKING CHANGES - -- **package:** The `Package` class no longer provides direct access to the JSON object - used to construct the instance. Map-like `get()`/`set(val)` methods are - available to modify the internal representation. - - - -# [3.0.0-beta.11](https://github.com/lerna/lerna/compare/v3.0.0-beta.10...v3.0.0-beta.11) (2018-03-29) - -### Features - -- **bootstrap:** Inherit stdio during root-only install ([fd8c391](https://github.com/lerna/lerna/commit/fd8c391)) -- **bootstrap:** Short-circuit when local file: specifiers are detected in the root ([d8a8f03](https://github.com/lerna/lerna/commit/d8a8f03)) -- Support `optionalDependencies` ([b73e19d](https://github.com/lerna/lerna/commit/b73e19d)), closes [#121](https://github.com/lerna/lerna/issues/121) - - - -# [3.0.0-beta.10](https://github.com/lerna/lerna/compare/v3.0.0-beta.9...v3.0.0-beta.10) (2018-03-27) - -### Features - -- **commands:** Delay require of command instantiation ([a1284f3](https://github.com/lerna/lerna/commit/a1284f3)) - -### BREAKING CHANGES - -- **commands:** The default export of command packages is now a factory, not the subclass (which is now a named export). - - - -# [3.0.0-beta.9](https://github.com/lerna/lerna/compare/v3.0.0-beta.8...v3.0.0-beta.9) (2018-03-24) - -### Features - -- **command:** Rename this.repository -> this.project ([43e98a0](https://github.com/lerna/lerna/commit/43e98a0)) -- **project:** Normalize config.commands -> config.command ([24e55e3](https://github.com/lerna/lerna/commit/24e55e3)) - - - -# [3.0.0-beta.8](https://github.com/lerna/lerna/compare/v3.0.0-beta.7...v3.0.0-beta.8) (2018-03-22) - -### Features - -- **utils:** Add "vendored" npm-conf ([9c24a25](https://github.com/lerna/lerna/commit/9c24a25)) - - - -# [3.0.0-beta.7](https://github.com/lerna/lerna/compare/v3.0.0-beta.6...v3.0.0-beta.7) (2018-03-20) - -**Note:** Version bump only for package @lerna/bootstrap - - - -# [3.0.0-beta.6](https://github.com/lerna/lerna/compare/v3.0.0-beta.5...v3.0.0-beta.6) (2018-03-19) - -**Note:** Version bump only for package @lerna/bootstrap - - - -# [3.0.0-beta.5](https://github.com/lerna/lerna/compare/v3.0.0-beta.4...v3.0.0-beta.5) (2018-03-19) - -### Bug Fixes - -- **bootstrap:** Move --hoist/--nohoist coerce into class ([8877aa0](https://github.com/lerna/lerna/commit/8877aa0)), closes [#1337](https://github.com/lerna/lerna/issues/1337) - - - -# [3.0.0-beta.4](https://github.com/lerna/lerna/compare/v3.0.0-beta.3...v3.0.0-beta.4) (2018-03-19) - -### Bug Fixes - -- Respect durable hoist configuration ([2081640](https://github.com/lerna/lerna/commit/2081640)), closes [#1325](https://github.com/lerna/lerna/issues/1325) - - - -# [3.0.0-beta.3](https://github.com/lerna/lerna/compare/v3.0.0-beta.2...v3.0.0-beta.3) (2018-03-15) - -**Note:** Version bump only for package @lerna/bootstrap - - - -# [3.0.0-beta.2](https://github.com/lerna/lerna/compare/v3.0.0-beta.1...v3.0.0-beta.2) (2018-03-10) - -### Bug Fixes - -- Move @lerna/has-dependency-installed into bootstrap/lib ([c09ccbd](https://github.com/lerna/lerna/commit/c09ccbd)) - -### Features - -- Rename @lerna/fs-utils => @lerna/rimraf-dir ([30451ed](https://github.com/lerna/lerna/commit/30451ed)) -- Replace @lerna/match-package-name with multimatch ([423f82c](https://github.com/lerna/lerna/commit/423f82c)) - - - -# [3.0.0-beta.1](https://github.com/lerna/lerna/compare/v3.0.0-beta.0...v3.0.0-beta.1) (2018-03-09) - -### Bug Fixes - -- **filter-options:** require a git repo when using --since ([d21b66e](https://github.com/lerna/lerna/commit/d21b66e)), closes [#822](https://github.com/lerna/lerna/issues/822) diff --git a/commands/bootstrap/README.md b/commands/bootstrap/README.md deleted file mode 100644 index 09009114fc..0000000000 --- a/commands/bootstrap/README.md +++ /dev/null @@ -1,275 +0,0 @@ -# `@lerna/bootstrap` - -> Link local packages together and install remaining package dependencies - -Install [lerna](https://www.npmjs.com/package/lerna) for access to the `lerna` CLI. - -## Usage - -```sh -$ lerna bootstrap -``` - -Bootstrap the packages in the current Lerna repo. -Installs all of their dependencies and links any cross-dependencies. - -When run, this command will: - -1. `npm install` all external dependencies of each package. -2. Symlink together all Lerna `packages` that are dependencies of each other. -3. `npm run prepublish` in all bootstrapped packages (unless `--ignore-prepublish` is passed). -4. `npm run prepare` in all bootstrapped packages. - -`lerna bootstrap` accepts all [filter flags](https://www.npmjs.com/package/@lerna/filter-options). - -Pass extra arguments to npm client by placing them after `--`: - -```sh -$ lerna bootstrap -- --production --no-optional -``` - -May also be configured in `lerna.json`: - -```js -{ - ... - "npmClient": "yarn", - "npmClientArgs": ["--production", "--no-optional"] -} -``` - -### --hoist [glob] - -Install external dependencies matching `glob` at the repo root so they're -available to all packages. Any binaries from these dependencies will be -linked into dependent package `node_modules/.bin/` directories so they're -available for npm scripts. If the option is present but no `glob` is given -the default is `**` (hoist everything). This option only affects the -`bootstrap` command. - -```sh -$ lerna bootstrap --hoist -``` - -For background on `--hoist`, see the [hoist documentation](https://github.com/lerna/lerna/blob/main/doc/hoist.md). - -Note: If packages depend on different _versions_ of an external dependency, -the most commonly used version will be hoisted, and a warning will be emitted. - -Note: `--hoist` is [incompatible with `file:` specifiers](https://github.com/lerna/lerna/issues/1679#issuecomment-461544321). Use one or the other. - -Note: `--hoist` [no longer accepts multiple string values](https://github.com/lerna/lerna/issues/2307) since [v3.18.0](https://github.com/lerna/lerna/releases/tag/v3.18.0). Use the following instead: - -a. Wrap string values by quotes: -``` -$ lerna bootstrap --hoist "{rollup,postcss-cli,webpack-cli,babel-loader,npm-run-all}" -``` - -b. Specify the list of values in `lerna.json`: -```json -{ - "command": { - "bootstrap": { - "hoist": [ - "rollup", - "postcss-cli", - "webpack-cli", - "babel-loader", - "npm-run-all" - ] - } - }, - ... -} -``` - - -### --strict - -When used in conjunction with hoist will throw an error and stop bootstrapping after emitting the version warnings. Has no effect if you aren't hoisting, or if there are no version warnings. - -```sh -$ lerna bootstrap --hoist --strict -``` - -### --nohoist [glob] - -Do _not_ install external dependencies matching `glob` at the repo root. This -can be used to opt out of hoisting for certain dependencies. - -```sh -$ lerna bootstrap --hoist --nohoist=babel-* -``` - -### --ignore - -```sh -$ lerna bootstrap --ignore component-* -``` - -The `--ignore` flag, when used with the `bootstrap` command, can also be set in `lerna.json` under the `command.bootstrap.ignore` key. The command-line flag will take precedence over this option. - -**Example** - -```json -{ - "version": "0.0.0", - "command": { - "bootstrap": { - "ignore": "component-*" - } - } -} -``` - -> Hint: The glob is matched against the package name defined in `package.json`, -> not the directory name the package lives in. - -## Options - -### `--ignore-prepublish` - -Skip prepublish lifecycle scripts run by default in bootstrapped packages. -Note, this lifecycle is [deprecated](https://docs.npmjs.com/misc/scripts#deprecation-note), -and will likely be removed in the next major version of Lerna. - -```sh -$ lerna bootstrap --ignore-prepublish -``` - -### `--ignore-scripts` - -Skip any lifecycle scripts normally run (`prepare`, etc) in bootstrapped packages. - -```sh -$ lerna bootstrap --ignore-scripts -``` - -### `--registry ` - -When run with this flag, forwarded npm commands will use the specified registry for your package(s). - -This is useful if you do not want to explicitly set up your registry -configuration in all of your package.json files individually when e.g. using -private registries. - -### `--npm-client ` - -Must be an executable that knows how to install npm package dependencies. -The default `--npm-client` is `npm`. - -```sh -$ lerna bootstrap --npm-client=yarn -``` - -May also be configured in `lerna.json`: - -```js -{ - ... - "npmClient": "yarn" -} -``` - -### `--use-workspaces` - -Enables integration with [Yarn Workspaces](https://github.com/yarnpkg/rfcs/blob/master/implemented/0000-workspaces-install-phase-1.md) (available since yarn@0.27+). -The values in the array are the commands in which Lerna will delegate operation to Yarn (currently only bootstrapping). -If `--use-workspaces` is true then `packages` will be overridden by the value from `package.json/workspaces.`, and both `--ignore` and `--scope` will be ignored. -May also be configured in `lerna.json`: - -```js -{ - ... - "npmClient": "yarn", - "useWorkspaces": true -} -``` - -The root-level package.json must also include a `workspaces` array: - -```json -{ - "private": true, - "devDependencies": { - "lerna": "^2.2.0" - }, - "workspaces": ["packages/*"] -} -``` - -This list is broadly similar to lerna's `packages` config (a list of globs matching directories with a package.json), -except it does not support recursive globs (`"**"`, a.k.a. "globstars"). - -### `--no-ci` - -When using the default `--npm-client`, `lerna bootstrap` will call [`npm ci`](https://docs.npmjs.com/cli/ci) instead of `npm install` in CI environments. -To disable this behavior, pass `--no-ci`: - -```sh -$ lerna bootstrap --no-ci -``` - -To _force_ it during a local install (where it is not automatically enabled), pass `--ci`: - -```sh -$ lerna bootstrap --ci -``` - -This can be useful for "clean" re-installs, or initial installations after fresh cloning. - -### `--force-local` - -```sh -$ 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. - -- `babel-generator` and `source-map` (among others) are dependencies of `babel-core`. -- `babel-core`'s [`package.json`](https://github.com/babel/babel/blob/13c961d29d76ccd38b1fc61333a874072e9a8d6a/packages/babel-core/package.json#L28-L47) lists both these packages as keys in `dependencies`, as shown below. - -```js -// babel-core package.json -{ - "name": "babel-core", - ... - "dependencies": { - ... - "babel-generator": "^6.9.0", - ... - "source-map": "^0.5.0" - } -} -``` - -- Lerna checks if each dependency is also part of the Lerna repo. - - In this example, `babel-generator` can be an internal dependency, while `source-map` is always an external dependency. - - The version of `babel-generator` in the `package.json` of `babel-core` is satisfied by `packages/babel-generator`, passing for an internal dependency. - - `source-map` is `npm install`ed (or `yarn`ed) like normal. -- `packages/babel-core/node_modules/babel-generator` symlinks to `packages/babel-generator` -- This allows nested directory imports - -## Notes - -- When a dependency version in a package is not satisfied by a package of the same name in the repo, it will be `npm install`ed (or `yarn`ed) like normal. -- Dist-tags, like `latest`, do not satisfy [semver](https://semver.npmjs.com/) ranges. -- Circular dependencies result in circular symlinks which _may_ impact your editor/IDE. - -[Webstorm](https://www.jetbrains.com/webstorm/) locks up when circular symlinks are present. To prevent this, add `node_modules` to the list of ignored files and folders in `Preferences | Editor | File Types | Ignored files and folders`. diff --git a/commands/bootstrap/__tests__/bootstrap-command.test.js b/commands/bootstrap/__tests__/bootstrap-command.test.js deleted file mode 100644 index d9693ff8c7..0000000000 --- a/commands/bootstrap/__tests__/bootstrap-command.test.js +++ /dev/null @@ -1,706 +0,0 @@ -"use strict"; - -jest.mock("@lerna/rimraf-dir"); -jest.mock("@lerna/npm-install"); -jest.mock("@lerna/run-lifecycle"); -jest.mock("@lerna/create-symlink"); - -const fs = require("fs-extra"); -const path = require("path"); - -// mocked or stubbed modules -const { rimrafDir } = require("@lerna/rimraf-dir"); -const { npmInstall, npmInstallDependencies } = require("@lerna/npm-install"); -const { runLifecycle } = require("@lerna/run-lifecycle"); -const { createSymlink } = require("@lerna/create-symlink"); -const { hasNpmVersion } = require("@lerna/has-npm-version"); - -// helpers -const initFixture = require("@lerna-test/helpers").initFixtureFactory(__dirname); -const { normalizeRelativeDir } = require("@lerna-test/helpers"); -const { updateLernaConfig } = require("@lerna-test/helpers"); - -// file under test -const lernaBootstrap = require("@lerna-test/helpers").commandRunner(require("../command")); - -// assertion helpers -const installedPackagesInDirectories = (testDir) => - npmInstallDependencies.mock.calls.reduce((obj, [pkg, dependencies]) => { - const relative = normalizeRelativeDir(testDir, pkg.location); - obj[relative || "ROOT"] = dependencies; - return obj; - }, {}); - -const removedDirectories = (testDir) => - rimrafDir.mock.calls.map(([directory]) => normalizeRelativeDir(testDir, directory)); - -const symlinkedDirectories = (testDir) => - createSymlink.mock.calls - .slice() - // ensure sort is always consistent, despite promise variability - .sort((a, b) => { - // two-dimensional path sort - if (b[0] === a[0]) { - if (b[1] === a[1]) { - // ignore third field - return 0; - } - - return b[1] < a[1] ? 1 : -1; - } - - return b[0] < a[0] ? 1 : -1; - }) - .map(([src, dest, type]) => ({ - _src: normalizeRelativeDir(testDir, src), - dest: normalizeRelativeDir(testDir, dest), - type, - })); - -describe("BootstrapCommand", () => { - beforeEach(() => { - jest.setTimeout(60000); - }); - - // stub rimraf because we trust isaacs - rimrafDir.mockResolvedValue(); - - // we stub npmInstall in most tests because - // we already have enough tests of npmInstall - npmInstall.mockResolvedValue(); - npmInstallDependencies.mockResolvedValue(); - - // stub runLifecycle because it is a huge source - // of slowness when running tests for no good reason - runLifecycle.mockResolvedValue(); - - // the underlying implementation of symlinkBinary and symlinkDependencies - createSymlink.mockResolvedValue(); - - describe("lifecycle scripts", () => { - const npmLifecycleEvent = process.env.npm_lifecycle_event; - - afterEach(() => { - process.env.npm_lifecycle_event = npmLifecycleEvent; - delete process.env.LERNA_EXEC_PATH; - delete process.env.LERNA_ROOT_PATH; - }); - - it("should run preinstall, postinstall and prepublish scripts", async () => { - const testDir = await initFixture("lifecycle-scripts"); - - await lernaBootstrap(testDir)(); - - expect(runLifecycle.getOrderedCalls()).toEqual([ - ["package-preinstall", "preinstall"], - ["package-postinstall", "postinstall"], - ["package-prepublish", "prepublish"], - ]); - }); - - it("does not run prepublish scripts with --ignore-prepublish", async () => { - const testDir = await initFixture("lifecycle-scripts"); - - await lernaBootstrap(testDir)("--ignore-prepublish"); - - expect(runLifecycle.getOrderedCalls()).toEqual([ - ["package-preinstall", "preinstall"], - ["package-postinstall", "postinstall"], - ]); - }); - - it("shouldn't run lifecycle scripts with --ignore-scripts", async () => { - const testDir = await initFixture("ignored-scripts"); - - await lernaBootstrap(testDir)("--ignore-scripts"); - - expect(runLifecycle).not.toHaveBeenCalled(); - expect(npmInstallDependencies).toHaveBeenCalledWith( - expect.objectContaining({ - name: "package-prepare", - }), - ["tiny-tarball@^1.0.0"], - expect.objectContaining({ - npmClientArgs: ["--ignore-scripts"], - }) - ); - }); - - it("should not recurse from hoisted root lifecycle", async () => { - const testDir = await initFixture("lifecycle-scripts"); - - process.env.LERNA_EXEC_PATH = testDir; - process.env.LERNA_ROOT_PATH = testDir; - - await lernaBootstrap(testDir)(); - - expect(runLifecycle).not.toHaveBeenCalled(); - }); - }); - - describe("with pnpm", () => { - it("should throw validation error", async () => { - const testDir = await initFixture("pnpm"); - const command = lernaBootstrap(testDir)(); - - await expect(command).rejects.toThrow( - "Bootstrapping with pnpm is not supported. Use pnpm directly to manage dependencies: https://pnpm.io/cli/install" - ); - }); - }); - - describe("with hoisting", () => { - it("should hoist", async () => { - const testDir = await initFixture("basic"); - - await lernaBootstrap(testDir)("--hoist"); - - expect(installedPackagesInDirectories(testDir)).toMatchSnapshot(); - expect(removedDirectories(testDir)).toMatchSnapshot(); - - // root includes explicit dependencies and hoisted from leaves - expect(npmInstallDependencies).toHaveBeenCalledWith( - expect.objectContaining({ - name: "basic", - }), - ["bar@^2.0.0", "foo@^1.0.0", "@test/package-1@^0.0.0"], - { - registry: undefined, - npmClient: "npm", - npmClientArgs: [], - mutex: undefined, - // npmGlobalStyle is not included at all - } - ); - - // foo@0.1.2 differs from the more common foo@^1.0.0 - expect(npmInstallDependencies).toHaveBeenLastCalledWith( - expect.objectContaining({ - name: "package-3", - }), - ["foo@0.1.12"], - expect.objectContaining({ - npmGlobalStyle: true, - }) - ); - }); - - it("should not hoist when disallowed", async () => { - const testDir = await initFixture("basic"); - - await lernaBootstrap(testDir)("--hoist", "--nohoist", "@test/package-1"); - - expect(installedPackagesInDirectories(testDir)).toMatchSnapshot(); - expect(removedDirectories(testDir)).toMatchSnapshot(); - }); - - it("should not hoist when disallowed from lerna.json", async () => { - const testDir = await initFixture("basic"); - - await updateLernaConfig(testDir, { - hoist: true, - nohoist: ["@test/package-1"], - }); - await lernaBootstrap(testDir)(); - - expect(installedPackagesInDirectories(testDir)).toMatchSnapshot(); - }); - }); - - describe("with --npm-client and --hoist", () => { - it("should throw", async () => { - const testDir = await initFixture("yarn-hoist"); - const command = lernaBootstrap(testDir)(); - - await expect(command).rejects.toThrow( - "--hoist is not supported with --npm-client=yarn, use yarn workspaces instead" - ); - }); - }); - - describe("with --hoist and --strict", () => { - it("should throw if there's a hoist warning", async () => { - const testDir = await initFixture("basic"); - const command = lernaBootstrap(testDir)("--hoist", "--strict"); - - await expect(command).rejects.toThrow("Package version inconsistencies found"); - }); - }); - - describe("with --ci", () => { - it("should call npmInstall with ci subCommand if on npm 5.7.0 or later", async () => { - const testDir = await initFixture("ci"); - - await lernaBootstrap(testDir)("--ci"); - - expect(hasNpmVersion).toHaveBeenLastCalledWith(">=5.7.0"); - expect(npmInstallDependencies.mock.calls[0][2]).toEqual({ - subCommand: "ci", - registry: undefined, - npmClient: "npm", - npmClientArgs: [], - npmGlobalStyle: false, - mutex: undefined, - }); - }); - - it("should not pass subCommand to npmInstall if on npm version earlier than 5.7.0", async () => { - const testDir = await initFixture("ci"); - - hasNpmVersion.mockReturnValueOnce(false); - - await lernaBootstrap(testDir)("--ci"); - - expect(npmInstallDependencies.mock.calls[0][2]).toEqual({ - registry: undefined, - npmClient: "npm", - npmClientArgs: [], - npmGlobalStyle: false, - mutex: undefined, - }); - }); - - it("should not run npm ci when hoisting", async () => { - const testDir = await initFixture("basic"); - - await lernaBootstrap(testDir)("--hoist", "package-*", "--ci"); - - expect(npmInstallDependencies.mock.calls[0][2]).toMatchObject({ - subCommand: "install", // not "ci" - npmClient: "npm", - npmClientArgs: ["--no-save"], - }); - }); - - it("respects config file { ci: false }", async () => { - const testDir = await initFixture("ci"); - - await updateLernaConfig(testDir, { - command: { - bootstrap: { - ci: false, - }, - }, - }); - await lernaBootstrap(testDir)(); - - expect(hasNpmVersion).not.toHaveBeenCalled(); - expect(npmInstallDependencies.mock.calls[0][2]).toEqual({ - registry: undefined, - npmClient: "npm", - npmClientArgs: [], - npmGlobalStyle: false, - mutex: undefined, - }); - }); - }); - - describe("with local package dependencies", () => { - it("should bootstrap packages", async () => { - const testDir = await initFixture("basic"); - - await lernaBootstrap(testDir)(); - - expect(installedPackagesInDirectories(testDir)).toMatchSnapshot(); - expect(symlinkedDirectories(testDir)).toMatchSnapshot(); - }); - - it("should not bootstrap ignored packages", async () => { - const testDir = await initFixture("basic"); - - await lernaBootstrap(testDir)("--ignore", "{@test/package-2,package-4}"); - - expect(installedPackagesInDirectories(testDir)).toMatchSnapshot(); - expect(symlinkedDirectories(testDir)).toMatchSnapshot(); - }); - - it("should only bootstrap scoped packages", async () => { - const testDir = await initFixture("basic"); - - await lernaBootstrap(testDir)("--scope", "package-@(3|4)"); - - expect(installedPackagesInDirectories(testDir)).toMatchSnapshot(); - expect(symlinkedDirectories(testDir)).toMatchSnapshot(); - }); - - it("should respect --force-local", async () => { - const testDir = await initFixture("basic"); - - await lernaBootstrap(testDir)("--scope", "@test/package-1", "--scope", "package-4", "--force-local"); - - expect(installedPackagesInDirectories(testDir)).toMatchSnapshot(); - expect(symlinkedDirectories(testDir)).toMatchSnapshot(); - }); - - it("should respect --force-local when a single package is in scope", async () => { - const testDir = await initFixture("basic"); - - await lernaBootstrap(testDir)("--scope", "package-4", "--force-local"); - - // no packages were installed from the registry - const installed = installedPackagesInDirectories(testDir); - expect(installed["packages/package-4"] || []).toEqual([]); - - // package-3 was resolved as a local symlink - const symlinked = symlinkedDirectories(testDir); - expect(symlinked).toContainEqual({ - _src: "packages/package-3", - dest: "packages/package-4/node_modules/package-3", - type: "junction", - }); - }); - - it("should respect --contents argument during linking step", 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"); - - await lernaBootstrap(testDir)("--scope", "@test/package-2", "--ci"); - - expect(installedPackagesInDirectories(testDir)).toMatchSnapshot(); - expect(symlinkedDirectories(testDir)).toMatchSnapshot(); - expect(npmInstallDependencies.mock.calls[0][2]).toMatchObject({ - subCommand: "install", // not "ci" - npmClient: "npm", - npmClientArgs: ["--no-save"], - }); - }); - - it("should not update yarn.lock when filtering", async () => { - const testDir = await initFixture("basic"); - - await lernaBootstrap(testDir)("--scope", "@test/package-2", "--npm-client", "yarn", "--ci"); - - expect(npmInstallDependencies.mock.calls[0][2]).toMatchObject({ - npmClient: "yarn", - npmClientArgs: ["--pure-lockfile"], - }); - }); - - it("never installs with global style", async () => { - const testDir = await initFixture("basic"); - - await lernaBootstrap(testDir)(); - - expect(npmInstallDependencies).toHaveBeenCalledWith( - expect.objectContaining({ - name: "@test/package-2", - }), - expect.arrayContaining(["foo@^1.0.0"]), - expect.objectContaining({ - npmGlobalStyle: false, - }) - ); - }); - }); - - describe("with multiple package locations", () => { - it("should bootstrap packages", async () => { - const testDir = await initFixture("extra"); - - await lernaBootstrap(testDir)(); - - expect(installedPackagesInDirectories(testDir)).toMatchSnapshot(); - expect(symlinkedDirectories(testDir)).toMatchSnapshot(); - expect(runLifecycle.getOrderedCalls()).toEqual([["@test/package-1", "prepublish"]]); - }); - - it("should not bootstrap ignored packages", async () => { - const testDir = await initFixture("extra"); - - await lernaBootstrap(testDir)("--ignore", "package-@(3|4)"); - - expect(installedPackagesInDirectories(testDir)).toMatchSnapshot(); - }); - - it("bootstraps dependencies not included by --scope with --include-filtered-dependencies", async () => { - const testDir = await initFixture("extra"); - - // we scope to package-2 only but should still install package-1 as it is a dependency of package-2 - await lernaBootstrap(testDir)("--scope", "package-2", "--include-filtered-dependencies"); - - expect(installedPackagesInDirectories(testDir)).toMatchSnapshot(); - }); - - it("bootstraps dependencies excluded by --ignore with --include-filtered-dependencies", async () => { - const testDir = await initFixture("extra"); - - // we ignore package 1 but it should still be installed because it is a dependency of package-2 - await lernaBootstrap(testDir)( - "--ignore", - "{@test/package-1,package-@(3|4)}", - "--include-filtered-dependencies" - ); - - expect(installedPackagesInDirectories(testDir)).toMatchSnapshot(); - }); - - it("hoists appropriately", async () => { - const testDir = await initFixture("extra"); - - await lernaBootstrap(testDir)("--hoist"); - - expect(installedPackagesInDirectories(testDir)).toMatchSnapshot(); - expect(symlinkedDirectories(testDir)).toMatchSnapshot(); - }); - }); - - describe("with external dependencies that haven't been installed", () => { - it("should get installed", async () => { - const testDir = await initFixture("cold"); - - await lernaBootstrap(testDir)(); - - expect(installedPackagesInDirectories(testDir)).toMatchSnapshot(); - }); - - it("gets network mutex when --npm-client=yarn", async () => { - const testDir = await initFixture("cold"); - - await lernaBootstrap(testDir)("--npm-client", "yarn"); - - expect(npmInstallDependencies.mock.calls[0][2]).toMatchObject({ - npmClient: "yarn", - mutex: expect.stringMatching(/^network:\d+$/), - }); - }); - - it("gets user defined mutex when --npm-client=yarn", async () => { - const testDir = await initFixture("cold"); - - await lernaBootstrap(testDir)("--npm-client", "yarn", "--mutex", "file:/test/this/path"); - - expect(npmInstallDependencies.mock.calls[0][2]).toMatchObject({ - npmClient: "yarn", - mutex: "file:/test/this/path", - }); - }); - - it("hoists appropriately", async () => { - const testDir = await initFixture("cold"); - - await updateLernaConfig(testDir, { - hoist: true, - }); - await lernaBootstrap(testDir)(); - - expect(installedPackagesInDirectories(testDir)).toMatchSnapshot(); - expect(symlinkedDirectories(testDir)).toMatchSnapshot(); - }); - }); - - describe("with external dependencies that have already been installed", () => { - it("should not get re-installed", async () => { - const testDir = await initFixture("warm"); - - await lernaBootstrap(testDir)(); - - expect(npmInstallDependencies).not.toHaveBeenCalled(); - }); - - it("hoists appropriately", async () => { - const testDir = await initFixture("warm"); - - await updateLernaConfig(testDir, { - command: { - bootstrap: { - hoist: true, - }, - }, - }); - await lernaBootstrap(testDir)(); - - expect(installedPackagesInDirectories(testDir)).toMatchSnapshot(); - expect(symlinkedDirectories(testDir)).toMatchSnapshot(); - }); - }); - - describe("with at least one external dependency to install", () => { - it("should install all dependencies", async () => { - const testDir = await initFixture("tepid"); - - await lernaBootstrap(testDir)(); - - expect(installedPackagesInDirectories(testDir)).toMatchSnapshot(); - }); - - it("hoists appropriately", async () => { - const testDir = await initFixture("tepid"); - - await lernaBootstrap(testDir)("--hoist"); - - expect(installedPackagesInDirectories(testDir)).toMatchSnapshot(); - expect(symlinkedDirectories(testDir)).toMatchSnapshot(); - }); - }); - - describe("with package peerDependencies", () => { - it("does not bootstrap peerDependencies", async () => { - const testDir = await initFixture("peer"); - - await lernaBootstrap(testDir)(); - - expect(npmInstallDependencies).not.toHaveBeenCalled(); - }); - }); - - describe("with registry config", () => { - it("should install packages from registry", async () => { - const testDir = await initFixture("registries"); - - await lernaBootstrap(testDir)(); - - expect(installedPackagesInDirectories(testDir)).toMatchSnapshot(); - expect(npmInstallDependencies).toHaveBeenLastCalledWith( - expect.objectContaining({ - name: "@test/package-1", - }), - expect.arrayContaining(["foo@^1.0.0"]), - expect.objectContaining({ - registry: "https://my-secure-registry/npm", - npmClient: "npm", - npmGlobalStyle: false, - }) - ); - }); - }); - - describe("with remaining arguments", () => { - describe("by default", () => { - it("should turn it into npmClientArgs", async () => { - const testDir = await initFixture("npm-client-args-1"); - - await lernaBootstrap(testDir)("--", "--no-optional", "--production"); - - expect(npmInstallDependencies.mock.calls[0][2]).toMatchObject({ - npmClientArgs: ["--no-optional", "--production"], - }); - }); - }); - - describe("and configured npmClientArgs option", () => { - it("should merge both together", async () => { - const testDir = await initFixture("npm-client-args-2"); - - await lernaBootstrap(testDir)("--", "--no-optional"); - - expect(npmInstallDependencies.mock.calls[0][2]).toMatchObject({ - npmClientArgs: ["--production", "--no-optional"], - }); - }); - }); - }); - - describe("with yarn workspaces", () => { - it("should use workspaces feature when installing", async () => { - const testDir = await initFixture("yarn-workspaces"); - - await lernaBootstrap(testDir)(); - - expect(npmInstallDependencies).not.toHaveBeenCalled(); - expect(npmInstall).toHaveBeenLastCalledWith( - expect.objectContaining({ name: "root" }), - expect.objectContaining({ - npmClient: "yarn", - mutex: expect.stringMatching(/^network:\d+$/), - }) - ); - }); - - it("errors when package.json workspaces exists but --use-workspaces is not enabled", async () => { - const testDir = await initFixture("yarn-workspaces"); - const command = lernaBootstrap(testDir)("--no-use-workspaces"); - - await expect(command).rejects.toThrow( - "Yarn workspaces are configured in package.json, but not enabled in lerna.json!" - ); - }); - }); - - describe("with relative file: specifiers in root dependencies", () => { - it("only installs in the root", async () => { - const testDir = await initFixture("relative-file-specs"); - - await lernaBootstrap(testDir)(); - - expect(npmInstallDependencies).not.toHaveBeenCalled(); - expect(npmInstall).toHaveBeenLastCalledWith( - expect.objectContaining({ name: "relative-file-specs" }), - expect.objectContaining({ - npmClient: "npm", - stdio: "inherit", - }) - ); - }); - }); - - describe("with duplicate package names", () => { - it("throws an error", async () => { - const testDir = await initFixture("duplicate-package-names"); - const command = lernaBootstrap(testDir)(); - - await expect(command).rejects.toThrow(`Package name "package-1" used in multiple packages`); - }); - }); - - describe("in a cyclical repo", () => { - it("should throw an error with --reject-cycles", async () => { - const testDir = await initFixture("toposort"); - const command = lernaBootstrap(testDir)("--reject-cycles"); - - await expect(command).rejects.toThrow("Dependency cycles detected, you should fix these!"); - }); - it("should throw an error with --reject-cycles when using yarn-workspaces", async () => { - const testDir = await initFixture("yarn-workspaces-cyclic"); - const command = lernaBootstrap(testDir)("--reject-cycles"); - - await expect(command).rejects.toThrow("Dependency cycles detected, you should fix these!"); - }); - }); - - it("succeeds in repositories with zero packages", async () => { - const testDir = await initFixture("zero-pkgs"); - - const result = await lernaBootstrap(testDir)(); - - // cheesy workaround for jest's expectation of assertions - expect(result).toBeDefined(); - }); - - it("does not require an initialized git repo", async () => { - const testDir = await initFixture("zero-pkgs"); - - await fs.remove(path.join(testDir, ".git")); - - const result = await lernaBootstrap(testDir)(); - - // cheesy workaround for jest's expectation of assertions - expect(result).toBeDefined(); - }); - - it("requires a git repo when using --since", async () => { - const testDir = await initFixture("zero-pkgs"); - - await fs.remove(path.join(testDir, ".git")); - - const command = lernaBootstrap(testDir)("--since", "some-branch"); - - await expect(command).rejects.toThrow("this is not a git repository"); - }); - - describe("with force-local", () => { - it("links all packages", async () => { - const testDir = await initFixture("force-local"); - - await lernaBootstrap(testDir)("--force-local"); - - expect(symlinkedDirectories(testDir)).toMatchSnapshot(); - }); - }); -}); diff --git a/commands/bootstrap/command.js b/commands/bootstrap/command.js deleted file mode 100644 index 3d25c65231..0000000000 --- a/commands/bootstrap/command.js +++ /dev/null @@ -1,87 +0,0 @@ -"use strict"; - -const { filterOptions } = require("@lerna/filter-options"); - -/** - * @see https://github.com/yargs/yargs/blob/master/docs/advanced.md#providing-a-command-module - */ -exports.command = "bootstrap"; - -exports.describe = "Link local packages together and install remaining package dependencies"; - -exports.builder = (yargs) => { - yargs - .example( - "$0 bootstrap -- --no-optional", - "# execute `npm install --no-optional` in bootstrapped packages" - ) - .parserConfiguration({ - "populate--": true, - }) - .options({ - hoist: { - group: "Command Options:", - describe: "Install external dependencies matching [glob] to the repo root", - defaultDescription: "'**'", - }, - nohoist: { - group: "Command Options:", - describe: "Don't hoist external dependencies matching [glob] to the repo root", - type: "string", - requiresArg: true, - }, - mutex: { - hidden: true, - // untyped and hidden on purpose - }, - "ignore-prepublish": { - group: "Command Options:", - describe: "Don't run prepublish lifecycle scripts in bootstrapped packages.", - type: "boolean", - }, - "ignore-scripts": { - group: "Command Options:", - describe: "Don't run _any_ lifecycle scripts in bootstrapped packages", - type: "boolean", - }, - "npm-client": { - group: "Command Options:", - describe: "Executable used to install dependencies (npm, yarn, pnpm, ...)", - type: "string", - requiresArg: true, - }, - registry: { - group: "Command Options:", - describe: "Use the specified registry for all npm client operations.", - type: "string", - requiresArg: true, - }, - strict: { - group: "Command Options:", - describe: "Don't allow warnings when hoisting as it causes longer bootstrap times and other issues.", - type: "boolean", - }, - "use-workspaces": { - group: "Command Options:", - describe: "Enable integration with Yarn workspaces.", - type: "boolean", - }, - "force-local": { - group: "Command Options:", - describe: "Force local sibling links regardless of version range match", - 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 filterOptions(yargs); -}; - -exports.handler = function handler(argv) { - return require(".")(argv); -}; diff --git a/commands/bootstrap/index.js b/commands/bootstrap/index.js deleted file mode 100644 index 65fc30d30f..0000000000 --- a/commands/bootstrap/index.js +++ /dev/null @@ -1,603 +0,0 @@ -"use strict"; - -const dedent = require("dedent"); -const getPort = require("get-port"); -const npa = require("npm-package-arg"); -const path = require("path"); -const pMap = require("p-map"); -const pMapSeries = require("p-map-series"); -const pWaterfall = require("p-waterfall"); - -const { Command } = require("@lerna/command"); -const { rimrafDir } = require("@lerna/rimraf-dir"); -const { hasNpmVersion } = require("@lerna/has-npm-version"); -const { npmInstall, npmInstallDependencies } = require("@lerna/npm-install"); -const { createRunner } = require("@lerna/run-lifecycle"); -const { runTopologically } = require("@lerna/run-topologically"); -const { symlinkBinary } = require("@lerna/symlink-binary"); -const { symlinkDependencies } = require("@lerna/symlink-dependencies"); -const { ValidationError } = require("@lerna/validation-error"); -const { getFilteredPackages } = require("@lerna/filter-options"); -const { PackageGraph } = require("@lerna/package-graph"); -const { pulseTillDone } = require("@lerna/pulse-till-done"); - -const { hasDependencyInstalled } = require("./lib/has-dependency-installed"); -const { isHoistedPackage } = require("./lib/is-hoisted-package"); - -module.exports = factory; - -function factory(argv) { - return new BootstrapCommand(argv); -} - -class BootstrapCommand extends Command { - get requiresGit() { - return false; - } - - initialize() { - const { registry, npmClient = "npm", npmClientArgs = [], mutex, hoist, nohoist } = this.options; - - if (npmClient === "pnpm") { - throw new ValidationError( - "EWORKSPACES", - "Bootstrapping with pnpm is not supported. Use pnpm directly to manage dependencies: https://pnpm.io/cli/install" - ); - } - - if (npmClient === "yarn" && hoist) { - throw new ValidationError( - "EWORKSPACES", - dedent` - --hoist is not supported with --npm-client=yarn, use yarn workspaces instead - A guide is available at https://yarnpkg.com/blog/2017/08/02/introducing-workspaces/ - ` - ); - } - - if ( - npmClient === "yarn" && - this.project.manifest.get("workspaces") && - this.options.useWorkspaces !== true - ) { - throw new ValidationError( - "EWORKSPACES", - dedent` - Yarn workspaces are configured in package.json, but not enabled in lerna.json! - Please choose one: useWorkspaces = true in lerna.json, or remove package.json workspaces config - ` - ); - } - - // postinstall and prepare are commonly used to call `lerna bootstrap`, - // but we need to avoid recursive execution when `--hoist` is enabled - const { LERNA_EXEC_PATH = "leaf", LERNA_ROOT_PATH = "root" } = process.env; - - if (LERNA_EXEC_PATH === LERNA_ROOT_PATH) { - this.logger.warn("bootstrap", "Skipping recursive execution"); - - return false; - } - - if (hoist) { - let hoisting; - - if (hoist === true) { - // lerna.json `hoist: true` - hoisting = ["**"]; - } else { - // `--hoist ...` or lerna.json `hoist: [...]` - hoisting = [].concat(hoist); - } - - if (nohoist) { - if (!Array.isArray(nohoist)) { - // `--nohoist` single - hoisting = hoisting.concat(`!${nohoist}`); - } else { - // `--nohoist` multiple or lerna.json `nohoist: [...]` - hoisting = hoisting.concat(nohoist.map((str) => `!${str}`)); - } - } - - this.logger.verbose("hoist", "using globs %j", hoisting); - this.hoisting = hoisting; - } - - this.runPackageLifecycle = createRunner({ registry }); - this.npmConfig = { - registry, - npmClient, - npmClientArgs, - mutex, - }; - - if (npmClient === "npm" && this.options.ci && hasNpmVersion(">=5.7.0")) { - // never `npm ci` when hoisting - this.npmConfig.subCommand = this.hoisting ? "install" : "ci"; - - if (this.hoisting) { - // don't mutate lockfiles in CI - this.npmConfig.npmClientArgs.unshift("--no-save"); - } - } - - // lerna bootstrap ... -- - const doubleDashArgs = this.options["--"] || []; - if (doubleDashArgs.length) { - this.npmConfig.npmClientArgs = [...npmClientArgs, ...doubleDashArgs]; - } - - // do not run any lifecycle scripts (if configured) - if (this.options.ignoreScripts) { - this.npmConfig.npmClientArgs.unshift("--ignore-scripts"); - } - - this.targetGraph = this.options.forceLocal - ? new PackageGraph(this.packageGraph.rawPackageList, "allDependencies", "forceLocal") - : this.packageGraph; - - let chain = Promise.resolve(); - - chain = chain.then(() => { - return getFilteredPackages(this.targetGraph, this.execOpts, this.options); - }); - - 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"); - - // an explicit --scope, --ignore, or --since should only symlink the targeted packages, no others - this.targetGraph = new PackageGraph(filteredPackages, "allDependencies", this.options.forceLocal); - - // never automatically --save or modify lockfiles - this.npmConfig.npmClientArgs.unshift(npmClient === "yarn" ? "--pure-lockfile" : "--no-save"); - - // never attempt `npm ci`, it would always fail - if (this.npmConfig.subCommand === "ci") { - this.npmConfig.subCommand = "install"; - } - } - }); - - chain = chain.then(() => { - if (npmClient === "yarn" && !mutex) { - return getPort({ port: 42424, host: "0.0.0.0" }).then((port) => { - this.npmConfig.mutex = `network:${port}`; - this.logger.silly("npmConfig", this.npmConfig); - }); - } - - this.logger.silly("npmConfig", this.npmConfig); - }); - - return chain; - } - - execute() { - if (this.options.useWorkspaces || this.rootHasLocalFileDependencies()) { - if (this.options.rejectCycles) { - this.packageGraph.collapseCycles({ rejectCycles: this.options.rejectCycles }); - } - return this.installRootPackageOnly(); - } - - const filteredLength = this.filteredPackages.length; - const packageCountLabel = `${filteredLength} package${filteredLength > 1 ? "s" : ""}`; - const scriptsEnabled = this.options.ignoreScripts !== true; - - // root install does not need progress bar - this.enableProgressBar(); - this.logger.info("", `Bootstrapping ${packageCountLabel}`); - - // conditional task queue - const tasks = []; - - if (scriptsEnabled) { - tasks.push(() => this.runLifecycleInPackages("preinstall")); - } - - tasks.push( - () => this.getDependenciesToInstall(), - (result) => this.installExternalDependencies(result), - () => this.symlinkPackages() - ); - - if (scriptsEnabled) { - tasks.push( - () => this.runLifecycleInPackages("install"), - () => this.runLifecycleInPackages("postinstall") - ); - - if (!this.options.ignorePrepublish) { - tasks.push(() => this.runLifecycleInPackages("prepublish")); - } - - // "run on local npm install without any arguments", AFTER prepublish - tasks.push(() => this.runLifecycleInPackages("prepare")); - } - - return pWaterfall(tasks).then(() => { - this.logger.success("", `Bootstrapped ${packageCountLabel}`); - }); - } - - installRootPackageOnly() { - this.logger.info("bootstrap", "root only"); - - // don't hide yarn or npm output - this.npmConfig.stdio = "inherit"; - - return npmInstall(this.project.manifest, this.npmConfig); - } - - /** - * If the root manifest has local dependencies with `file:` specifiers, - * all the complicated bootstrap logic should be skipped in favor of - * npm5's package-locked auto-hoisting. - * @returns {Boolean} - */ - rootHasLocalFileDependencies() { - const rootDependencies = Object.assign({}, this.project.manifest.dependencies); - - return Object.keys(rootDependencies).some( - (name) => - this.targetGraph.has(name) && - npa.resolve(name, rootDependencies[name], this.project.rootPath).type === "directory" - ); - } - - runLifecycleInPackages(stage) { - this.logger.verbose("lifecycle", stage); - - if (!this.filteredPackages.length) { - return; - } - - const tracker = this.logger.newItem(stage); - - const mapPackageWithScript = (pkg) => - this.runPackageLifecycle(pkg, stage).then(() => { - tracker.completeWork(1); - }); - - tracker.addWork(this.filteredPackages.length); - - const runner = this.toposort - ? runTopologically(this.filteredPackages, mapPackageWithScript, { - concurrency: this.concurrency, - rejectCycles: this.options.rejectCycles, - }) - : pMap(this.filteredPackages, mapPackageWithScript, { concurrency: this.concurrency }); - - return runner.finally(() => tracker.finish()); - } - - hoistedDirectory(dependency) { - return path.join(this.project.rootPath, "node_modules", dependency); - } - - hoistedPackageJson(dependency) { - try { - // eslint-disable-next-line import/no-dynamic-require, global-require - return require(path.join(this.hoistedDirectory(dependency), "package.json")); - } catch (e) { - // Pass. - return {}; - } - } - - /** - * Return a object of root and leaf dependencies to install - * @returns {Object} - */ - getDependenciesToInstall() { - // Configuration for what packages to hoist may be in lerna.json or it may - // come in as command line options. - const rootPkg = this.project.manifest; - - // This will contain entries for each hoistable dependency. - const rootSet = new Set(); - - // This will map packages to lists of unhoistable dependencies - const leaves = new Map(); - - /** - * Map of dependencies to install - * - * Map { - * "": Map { - * "": Set { "", "", ... } - * } - * } - * - * Example: - * - * Map { - * "react": Map { - * "15.x": Set { "my-component1", "my-component2", "my-component3" }, - * "^0.14.0": Set { "my-component4" }, - * } - * } - */ - const depsToInstall = new Map(); - const filteredNodes = new Map( - this.filteredPackages.map((pkg) => [pkg.name, this.targetGraph.get(pkg.name)]) - ); - - // collect root dependency versions - const mergedRootDeps = Object.assign( - {}, - rootPkg.devDependencies, - rootPkg.optionalDependencies, - rootPkg.dependencies - ); - const rootExternalVersions = new Map( - Object.keys(mergedRootDeps).map((externalName) => [externalName, mergedRootDeps[externalName]]) - ); - - // seed the root dependencies - rootExternalVersions.forEach((version, externalName) => { - const externalDependents = new Set(); - const record = new Map(); - - record.set(version, externalDependents); - depsToInstall.set(externalName, record); - }); - - // build a map of external dependencies to install - for (const [leafName, leafNode] of filteredNodes) { - for (const [externalName, resolved] of leafNode.externalDependencies) { - // rawSpec is something like "^1.2.3" - const version = resolved.rawSpec; - const record = - depsToInstall.get(externalName) || depsToInstall.set(externalName, new Map()).get(externalName); - const externalDependents = record.get(version) || record.set(version, new Set()).get(version); - - externalDependents.add(leafName); - } - } - - const rootActions = []; - const leafActions = []; - // We don't want to exit on the first hoist issue, but log them all and then exit - let strictExitOnWarning = false; - - // determine where each dependency will be installed - for (const [externalName, externalDependents] of depsToInstall) { - let rootVersion; - - if (this.hoisting && isHoistedPackage(externalName, this.hoisting)) { - const commonVersion = Array.from(externalDependents.keys()).reduce((a, b) => - externalDependents.get(a).size > externalDependents.get(b).size ? a : b - ); - - // Get the version required by the repo root (if any). - // If the root doesn't have a dependency on this package then we'll - // install the most common dependency there. - rootVersion = rootExternalVersions.get(externalName) || commonVersion; - - if (rootVersion !== commonVersion) { - this.logger.warn( - "EHOIST_ROOT_VERSION", - `The repository root depends on ${externalName}@${rootVersion}, ` + - `which differs from the more common ${externalName}@${commonVersion}.` - ); - if (this.options.strict) { - strictExitOnWarning = true; - } - } - - const dependents = Array.from(externalDependents.get(rootVersion)).map( - (leafName) => this.targetGraph.get(leafName).pkg - ); - - // remove collection so leaves don't repeat it - externalDependents.delete(rootVersion); - - // Install the best version we can in the repo root. - // Even if it's already installed there we still need to make sure any - // binaries are linked to the packages that depend on them. - rootActions.push(() => - hasDependencyInstalled(rootPkg, externalName, rootVersion).then((isSatisfied) => { - rootSet.add({ - name: externalName, - dependents, - dependency: `${externalName}@${rootVersion}`, - isSatisfied, - }); - }) - ); - } - - // Add less common versions to package installs. - for (const [leafVersion, leafDependents] of externalDependents) { - for (const leafName of leafDependents) { - if (rootVersion) { - this.logger.warn( - "EHOIST_PKG_VERSION", - `"${leafName}" package depends on ${externalName}@${leafVersion}, ` + - `which differs from the hoisted ${externalName}@${rootVersion}.` - ); - if (this.options.strict) { - strictExitOnWarning = true; - } - } - - const leafNode = this.targetGraph.get(leafName); - const leafRecord = leaves.get(leafNode) || leaves.set(leafNode, new Set()).get(leafNode); - - // only install dependency if it's not already installed - leafActions.push(() => - hasDependencyInstalled(leafNode.pkg, externalName, leafVersion).then((isSatisfied) => { - leafRecord.add({ - dependency: `${externalName}@${leafVersion}`, - isSatisfied, - }); - }) - ); - } - } - } - if (this.options.strict && strictExitOnWarning) { - throw new ValidationError( - "EHOISTSTRICT", - "Package version inconsistencies found while hoisting. Fix the above warnings and retry." - ); - } - - return pMapSeries([...rootActions, ...leafActions], (el) => el()).then(() => { - this.logger.silly("root dependencies", JSON.stringify(rootSet, null, 2)); - this.logger.silly("leaf dependencies", JSON.stringify(leaves, null, 2)); - - return { rootSet, leaves }; - }); - } - - /** - * Install external dependencies for all packages - * @returns {Promise} - */ - installExternalDependencies({ leaves, rootSet }) { - const tracker = this.logger.newItem("install dependencies"); - const rootPkg = this.project.manifest; - const actions = []; - - // Start root install first, if any, since it's likely to take the longest. - if (rootSet.size) { - // If we have anything to install in the root then we'll install - // _everything_ that needs to go there. This is important for - // consistent behavior across npm clients. - const root = Array.from(rootSet); - - actions.push(() => { - const depsToInstallInRoot = root.some(({ isSatisfied }) => !isSatisfied) - ? root.map(({ dependency }) => dependency) - : []; - - if (depsToInstallInRoot.length) { - tracker.info("hoist", "Installing hoisted dependencies into root"); - } - - const promise = npmInstallDependencies(rootPkg, depsToInstallInRoot, this.npmConfig); - - return pulseTillDone(promise) - .then(() => - // Link binaries into dependent packages so npm scripts will - // have access to them. - pMapSeries(root, ({ name, dependents }) => { - const { bin } = this.hoistedPackageJson(name); - - if (bin) { - return pMap(dependents, (pkg) => { - const src = this.hoistedDirectory(name); - - return symlinkBinary(src, pkg); - }); - } - }) - ) - .then(() => { - tracker.info("hoist", "Finished bootstrapping root"); - tracker.completeWork(1); - }); - }); - - // Remove any hoisted dependencies that may have previously been - // installed in package directories. - actions.push(() => { - // Compute the list of candidate directories synchronously - const candidates = root - .filter((dep) => dep.dependents.length) - .reduce((list, { name, dependents }) => { - const dirs = dependents - .filter((pkg) => pkg.nodeModulesLocation !== rootPkg.nodeModulesLocation) - .map((pkg) => path.join(pkg.nodeModulesLocation, name)); - - return list.concat(dirs); - }, []); - - if (!candidates.length) { - tracker.verbose("hoist", "nothing to prune"); - tracker.completeWork(1); // the action "work" - - return; - } - - tracker.info("hoist", "Pruning hoisted dependencies"); - tracker.silly("prune", candidates); - tracker.addWork(candidates.length); - - return pMap( - candidates, - (dirPath) => - pulseTillDone(rimrafDir(dirPath)).then(() => { - tracker.verbose("prune", dirPath); - tracker.completeWork(1); - }), - // these are mostly no-ops in the vast majority of cases - { concurrency: this.concurrency } - ).then(() => { - tracker.info("hoist", "Finished pruning hoisted dependencies"); - tracker.completeWork(1); // the action "work" - }); - }); - } - - const leafNpmConfig = Object.assign({}, this.npmConfig, { - // Use `npm install --global-style` for leaves when hoisting is enabled - npmGlobalStyle: !!this.options.hoist, - }); - - // Install anything that needs to go into the leaves. - leaves.forEach((leafRecord, leafNode) => { - const deps = Array.from(leafRecord); - - // If we have any unsatisfied deps then we need to install everything. - // This is important for consistent behavior across npm clients. - if (deps.some(({ isSatisfied }) => !isSatisfied)) { - actions.push(() => { - const dependencies = deps.map(({ dependency }) => dependency); - const promise = npmInstallDependencies(leafNode.pkg, dependencies, leafNpmConfig); - - return pulseTillDone(promise).then(() => { - tracker.verbose("installed leaf", leafNode.name); - tracker.completeWork(1); - }); - }); - } - }); - - if (actions.length) { - tracker.info("", "Installing external dependencies"); - tracker.verbose("actions", "%d actions, concurrency %d", actions.length, this.concurrency); - tracker.addWork(actions.length); - } - - return pMap(actions, (act) => act(), { concurrency: this.concurrency }).finally(() => tracker.finish()); - } - - /** - * Symlink all packages to the packages/node_modules directory - * Symlink package binaries to dependent packages' node_modules/.bin directory - * @returns {Promise} - */ - symlinkPackages() { - return symlinkDependencies( - this.filteredPackages, - this.targetGraph, - this.logger.newItem("bootstrap dependencies") - ); - } -} - -module.exports.BootstrapCommand = BootstrapCommand; diff --git a/commands/bootstrap/lib/has-dependency-installed.js b/commands/bootstrap/lib/has-dependency-installed.js deleted file mode 100644 index e07779dad6..0000000000 --- a/commands/bootstrap/lib/has-dependency-installed.js +++ /dev/null @@ -1,50 +0,0 @@ -"use strict"; - -const log = require("npmlog"); -const Arborist = require("@npmcli/arborist"); -const semver = require("semver"); - -/** @typedef {Map} InstalledDependencies dependency name -> installed version */ - -// cache installed lookups -/** @type {Map} */ -const cache = new Map(); - -module.exports.hasDependencyInstalled = hasDependencyInstalled; - -/** - * Determine if a dependency has already been installed for this package - * @param {import("@lerna/package").Package} pkg The Package instance to check for installed dependency - * @param {string} depName Name of the dependency - * @param {string} needVersion version to test with - */ -function hasDependencyInstalled(pkg, depName, needVersion) { - log.silly("hasDependencyInstalled", pkg.name, depName); - - return getInstalled(pkg).then( - (versions) => versions.has(depName) && semver.satisfies(versions.get(depName), needVersion) - ); -} - -/** - * @param {import("@lerna/package").Package} pkg - * @returns {Promise} - */ -function getInstalled(pkg) { - if (cache.has(pkg)) { - return Promise.resolve(cache.get(pkg)); - } - const arb = new Arborist({ - path: pkg.location, - }); - return arb.loadActual().then((tree) => { - /** @type {InstalledDependencies} */ - const deps = new Map(); - - for (const [dependencyName, node] of tree.children.entries()) { - deps.set(dependencyName, node.version); - } - cache.set(pkg, deps); - return deps; - }); -} diff --git a/commands/bootstrap/lib/is-hoisted-package.js b/commands/bootstrap/lib/is-hoisted-package.js deleted file mode 100644 index a01bfa8d83..0000000000 --- a/commands/bootstrap/lib/is-hoisted-package.js +++ /dev/null @@ -1,13 +0,0 @@ -"use strict"; - -const multimatch = require("multimatch"); - -module.exports.isHoistedPackage = isHoistedPackage; - -/** - * @param {string} name - * @param {string[]} hoisting - */ -function isHoistedPackage(name, hoisting) { - return multimatch([name], hoisting).length > 0; -} diff --git a/commands/bootstrap/package.json b/commands/bootstrap/package.json deleted file mode 100644 index bd0cc4415c..0000000000 --- a/commands/bootstrap/package.json +++ /dev/null @@ -1,59 +0,0 @@ -{ - "name": "@lerna/bootstrap", - "version": "6.4.1", - "description": "Link local packages together and install remaining package dependencies", - "keywords": [ - "lerna", - "command" - ], - "homepage": "https://lerna.js.org", - "license": "MIT", - "author": { - "name": "Daniel Stockman", - "url": "https://github.com/evocateur" - }, - "files": [ - "command.js", - "index.js", - "lib" - ], - "main": "index.js", - "engines": { - "node": "^14.15.0 || >=16.0.0" - }, - "publishConfig": { - "access": "public" - }, - "repository": { - "type": "git", - "url": "git+https://github.com/lerna/lerna.git", - "directory": "commands/bootstrap" - }, - "scripts": { - "test": "echo \"Run tests from root\" && exit 1" - }, - "dependencies": { - "@lerna/command": "file:../../core/command", - "@lerna/filter-options": "file:../../core/filter-options", - "@lerna/has-npm-version": "file:../../utils/has-npm-version", - "@lerna/npm-install": "file:../../utils/npm-install", - "@lerna/package-graph": "file:../../core/package-graph", - "@lerna/pulse-till-done": "file:../../utils/pulse-till-done", - "@lerna/rimraf-dir": "file:../../utils/rimraf-dir", - "@lerna/run-lifecycle": "file:../../utils/run-lifecycle", - "@lerna/run-topologically": "file:../../utils/run-topologically", - "@lerna/symlink-binary": "file:../../utils/symlink-binary", - "@lerna/symlink-dependencies": "file:../../utils/symlink-dependencies", - "@lerna/validation-error": "file:../../core/validation-error", - "@npmcli/arborist": "5.3.0", - "dedent": "^0.7.0", - "get-port": "^5.1.1", - "multimatch": "^5.0.0", - "npm-package-arg": "8.1.1", - "npmlog": "^6.0.2", - "p-map": "^4.0.0", - "p-map-series": "^2.1.0", - "p-waterfall": "^2.1.1", - "semver": "^7.3.4" - } -} diff --git a/commands/changed/CHANGELOG.md b/commands/changed/CHANGELOG.md deleted file mode 100644 index 92e70e9584..0000000000 --- a/commands/changed/CHANGELOG.md +++ /dev/null @@ -1,578 +0,0 @@ -# Change Log - -All notable changes to this project will be documented in this file. -See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. - -## [6.4.1](https://github.com/lerna/lerna/compare/v6.4.0...v6.4.1) (2023-01-12) - -**Note:** Version bump only for package @lerna/changed - -# [6.4.0](https://github.com/lerna/lerna/compare/v6.3.0...v6.4.0) (2023-01-05) - -**Note:** Version bump only for package @lerna/changed - -# [6.3.0](https://github.com/lerna/lerna/compare/v6.2.0...v6.3.0) (2022-12-26) - -**Note:** Version bump only for package @lerna/changed - -# [6.2.0](https://github.com/lerna/lerna/compare/v6.1.0...v6.2.0) (2022-12-13) - -**Note:** Version bump only for package @lerna/changed - -# [6.1.0](https://github.com/lerna/lerna/compare/v6.0.3...v6.1.0) (2022-11-29) - -**Note:** Version bump only for package @lerna/changed - -## [6.0.3](https://github.com/lerna/lerna/compare/v6.0.2...v6.0.3) (2022-11-07) - -**Note:** Version bump only for package @lerna/changed - -## [6.0.2](https://github.com/lerna/lerna/compare/v6.0.1...v6.0.2) (2022-11-02) - -**Note:** Version bump only for package @lerna/changed - -## [6.0.1](https://github.com/lerna/lerna/compare/v6.0.0...v6.0.1) (2022-10-14) - -**Note:** Version bump only for package @lerna/changed - -# [6.0.0](https://github.com/lerna/lerna/compare/v6.0.0-alpha.2...v6.0.0) (2022-10-12) - -**Note:** Version bump only for package @lerna/changed - -# [6.0.0-alpha.2](https://github.com/lerna/lerna/compare/v6.0.0-alpha.1...v6.0.0-alpha.2) (2022-10-12) - -**Note:** Version bump only for package @lerna/changed - -# [6.0.0-alpha.1](https://github.com/lerna/lerna/compare/v5.6.2...v6.0.0-alpha.1) (2022-10-09) - -# [6.0.0-alpha.0](https://github.com/lerna/lerna/compare/v5.6.1...v6.0.0-alpha.0) (2022-10-07) - -**Note:** Version bump only for package @lerna/changed - -## [5.6.2](https://github.com/lerna/lerna/compare/v5.6.1...v5.6.2) (2022-10-09) - -**Note:** Version bump only for package @lerna/changed - -## [5.6.1](https://github.com/lerna/lerna/compare/v5.6.0...v5.6.1) (2022-09-30) - -**Note:** Version bump only for package @lerna/changed - -# [5.6.0](https://github.com/lerna/lerna/compare/v5.5.4...v5.6.0) (2022-09-29) - -**Note:** Version bump only for package @lerna/changed - -## [5.5.4](https://github.com/lerna/lerna/compare/v5.5.3...v5.5.4) (2022-09-28) - -**Note:** Version bump only for package @lerna/changed - -## [5.5.3](https://github.com/lerna/lerna/compare/v5.5.2...v5.5.3) (2022-09-28) - -**Note:** Version bump only for package @lerna/changed - -## [5.5.2](https://github.com/lerna/lerna/compare/v5.5.1...v5.5.2) (2022-09-20) - -**Note:** Version bump only for package @lerna/changed - -## [5.5.1](https://github.com/lerna/lerna/compare/v5.5.0...v5.5.1) (2022-09-09) - -**Note:** Version bump only for package @lerna/changed - -# [5.5.0](https://github.com/lerna/lerna/compare/v5.4.3...v5.5.0) (2022-08-31) - -**Note:** Version bump only for package @lerna/changed - -## [5.4.3](https://github.com/lerna/lerna/compare/v5.4.2...v5.4.3) (2022-08-16) - -**Note:** Version bump only for package @lerna/changed - -## [5.4.2](https://github.com/lerna/lerna/compare/v5.4.1...v5.4.2) (2022-08-14) - -**Note:** Version bump only for package @lerna/changed - -## [5.4.1](https://github.com/lerna/lerna/compare/v5.4.0...v5.4.1) (2022-08-12) - -**Note:** Version bump only for package @lerna/changed - -# [5.4.0](https://github.com/lerna/lerna/compare/v5.3.0...v5.4.0) (2022-08-08) - -**Note:** Version bump only for package @lerna/changed - -# [5.3.0](https://github.com/lerna/lerna/compare/v5.2.0...v5.3.0) (2022-07-27) - -**Note:** Version bump only for package @lerna/changed - -# [5.2.0](https://github.com/lerna/lerna/compare/v5.1.8...v5.2.0) (2022-07-22) - -**Note:** Version bump only for package @lerna/changed - -## [5.1.8](https://github.com/lerna/lerna/compare/v5.1.7...v5.1.8) (2022-07-07) - -**Note:** Version bump only for package @lerna/changed - -## [5.1.7](https://github.com/lerna/lerna/compare/v5.1.6...v5.1.7) (2022-07-06) - -**Note:** Version bump only for package @lerna/changed - -## [5.1.6](https://github.com/lerna/lerna/compare/v5.1.5...v5.1.6) (2022-06-24) - -**Note:** Version bump only for package @lerna/changed - -## [5.1.5](https://github.com/lerna/lerna/compare/v5.1.4...v5.1.5) (2022-06-24) - -**Note:** Version bump only for package @lerna/changed - -## [5.1.4](https://github.com/lerna/lerna/compare/v5.1.3...v5.1.4) (2022-06-15) - -**Note:** Version bump only for package @lerna/changed - -## [5.1.3](https://github.com/lerna/lerna/compare/v5.1.2...v5.1.3) (2022-06-15) - -**Note:** Version bump only for package @lerna/changed - -## [5.1.2](https://github.com/lerna/lerna/compare/v5.1.1...v5.1.2) (2022-06-13) - -**Note:** Version bump only for package @lerna/changed - -## [5.1.1](https://github.com/lerna/lerna/compare/v5.1.0...v5.1.1) (2022-06-09) - -### Bug Fixes - -- allow maintenance LTS node 14 engines starting at 14.15.0 ([#3161](https://github.com/lerna/lerna/issues/3161)) ([72305e4](https://github.com/lerna/lerna/commit/72305e4dbab607a2d87ae4efa6ee577c93a9dda9)) - -# [5.1.0](https://github.com/lerna/lerna/compare/v5.0.0...v5.1.0) (2022-06-07) - -**Note:** Version bump only for package @lerna/changed - -# [5.1.0-alpha.0](https://github.com/lerna/lerna/compare/v4.0.0...v5.1.0-alpha.0) (2022-05-25) - -**Note:** Version bump only for package @lerna/changed - -# [5.0.0](https://github.com/lerna/lerna/compare/v4.0.0...v5.0.0) (2022-05-24) - -**Note:** Version bump only for package @lerna/changed - -# [4.0.0](https://github.com/lerna/lerna/compare/v3.22.1...v4.0.0) (2021-02-10) - -### Features - -- Consume named exports of sibling modules ([63499e3](https://github.com/lerna/lerna/commit/63499e33652bc78fe23751875d74017e2f16a689)) -- Drop support for Node v6.x & v8.x ([ff4bb4d](https://github.com/lerna/lerna/commit/ff4bb4da215555e3bb136f5af09b5cbc631e57bb)) - -### BREAKING CHANGES - -- Node v6.x & v8.x are no longer supported. Please upgrade to the latest LTS release. - -Here's the gnarly one-liner I used to make these changes: - -``` -npx lerna exec --concurrency 1 --stream -- 'json -I -f package.json -e '"'"'this.engines=this.engines||{};this.engines.node=">= 10.18.0"'"'" -``` - -(requires `npm i -g json` beforehand) - -# [3.21.0](https://github.com/lerna/lerna/compare/v3.20.2...v3.21.0) (2020-05-13) - -**Note:** Version bump only for package @lerna/changed - -# [3.20.0](https://github.com/lerna/lerna/compare/v3.19.0...v3.20.0) (2019-12-27) - -**Note:** Version bump only for package @lerna/changed - -## [3.18.5](https://github.com/lerna/lerna/compare/v3.18.4...v3.18.5) (2019-11-20) - -### Bug Fixes - -- Auto-fix prettier formatting ([5344820](https://github.com/lerna/lerna/commit/5344820fc65da081d17f7fd2adb50ffe7101905b)) - -## [3.18.4](https://github.com/lerna/lerna/compare/v3.18.3...v3.18.4) (2019-11-08) - -### Bug Fixes - -- **changed:** Copy relevant options from version, do not inherit ([6bd77ba](https://github.com/lerna/lerna/commit/6bd77ba60afd496e0f612aca7a56b8a9c8270436)) - -## [3.18.3](https://github.com/lerna/lerna/compare/v3.18.2...v3.18.3) (2019-10-22) - -**Note:** Version bump only for package @lerna/changed - -## [3.18.2](https://github.com/lerna/lerna/compare/v3.18.1...v3.18.2) (2019-10-21) - -**Note:** Version bump only for package @lerna/changed - -# [3.18.0](https://github.com/lerna/lerna/compare/v3.17.0...v3.18.0) (2019-10-15) - -**Note:** Version bump only for package @lerna/changed - -## [3.16.5](https://github.com/lerna/lerna/compare/v3.16.4...v3.16.5) (2019-10-07) - -**Note:** Version bump only for package @lerna/changed - -## [3.16.4](https://github.com/lerna/lerna/compare/v3.16.3...v3.16.4) (2019-07-24) - -**Note:** Version bump only for package @lerna/changed - -## [3.16.2](https://github.com/lerna/lerna/compare/v3.16.1...v3.16.2) (2019-07-22) - -**Note:** Version bump only for package @lerna/changed - -## [3.16.1](https://github.com/lerna/lerna/compare/v3.16.0...v3.16.1) (2019-07-19) - -**Note:** Version bump only for package @lerna/changed - -# [3.16.0](https://github.com/lerna/lerna/compare/v3.15.0...v3.16.0) (2019-07-18) - -### Features - -- **listable:** Output JSON adjacency list with `--graph` ([9457a21](https://github.com/lerna/lerna/commit/9457a21)), closes [#1970](https://github.com/lerna/lerna/issues/1970) - -# [3.15.0](https://github.com/lerna/lerna/compare/v3.14.2...v3.15.0) (2019-06-09) - -**Note:** Version bump only for package @lerna/changed - -## [3.14.2](https://github.com/lerna/lerna/compare/v3.14.1...v3.14.2) (2019-06-09) - -**Note:** Version bump only for package @lerna/changed - -## [3.14.1](https://github.com/lerna/lerna/compare/v3.14.0...v3.14.1) (2019-05-15) - -**Note:** Version bump only for package @lerna/changed - -# [3.14.0](https://github.com/lerna/lerna/compare/v3.13.4...v3.14.0) (2019-05-14) - -**Note:** Version bump only for package @lerna/changed - -## [3.13.4](https://github.com/lerna/lerna/compare/v3.13.3...v3.13.4) (2019-04-24) - -**Note:** Version bump only for package @lerna/changed - -## [3.13.3](https://github.com/lerna/lerna/compare/v3.13.2...v3.13.3) (2019-04-17) - -**Note:** Version bump only for package @lerna/changed - -## [3.13.2](https://github.com/lerna/lerna/compare/v3.13.1...v3.13.2) (2019-04-08) - -**Note:** Version bump only for package @lerna/changed - -## [3.13.1](https://github.com/lerna/lerna/compare/v3.13.0...v3.13.1) (2019-02-26) - -**Note:** Version bump only for package @lerna/changed - -# [3.13.0](https://github.com/lerna/lerna/compare/v3.12.1...v3.13.0) (2019-02-15) - -### Features - -- **listable:** Output newline-delimited JSON with `--ndjson` ([742781b](https://github.com/lerna/lerna/commit/742781b)) -- **meta:** Add `repository.directory` field to package.json ([aec5023](https://github.com/lerna/lerna/commit/aec5023)) -- **meta:** Normalize package.json `homepage` field ([abeb4dc](https://github.com/lerna/lerna/commit/abeb4dc)) - -## [3.12.1](https://github.com/lerna/lerna/compare/v3.12.0...v3.12.1) (2019-02-14) - -**Note:** Version bump only for package @lerna/changed - -# [3.12.0](https://github.com/lerna/lerna/compare/v3.11.1...v3.12.0) (2019-02-14) - -**Note:** Version bump only for package @lerna/changed - -## [3.11.1](https://github.com/lerna/lerna/compare/v3.11.0...v3.11.1) (2019-02-11) - -**Note:** Version bump only for package @lerna/changed - -# [3.11.0](https://github.com/lerna/lerna/compare/v3.10.8...v3.11.0) (2019-02-08) - -**Note:** Version bump only for package @lerna/changed - -## [3.10.8](https://github.com/lerna/lerna/compare/v3.10.7...v3.10.8) (2019-02-01) - -**Note:** Version bump only for package @lerna/changed - -## [3.10.6](https://github.com/lerna/lerna/compare/v3.10.5...v3.10.6) (2019-01-19) - -**Note:** Version bump only for package @lerna/changed - -## [3.10.5](https://github.com/lerna/lerna/compare/v3.10.4...v3.10.5) (2019-01-11) - -**Note:** Version bump only for package @lerna/changed - -## [3.10.1](https://github.com/lerna/lerna/compare/v3.10.0...v3.10.1) (2019-01-09) - -**Note:** Version bump only for package @lerna/changed - -# [3.10.0](https://github.com/lerna/lerna/compare/v3.9.1...v3.10.0) (2019-01-08) - -**Note:** Version bump only for package @lerna/changed - -# [3.9.0](https://github.com/lerna/lerna/compare/v3.8.5...v3.9.0) (2019-01-08) - -**Note:** Version bump only for package @lerna/changed - -## [3.8.5](https://github.com/lerna/lerna/compare/v3.8.4...v3.8.5) (2019-01-05) - -**Note:** Version bump only for package @lerna/changed - -## [3.8.2](https://github.com/lerna/lerna/compare/v3.8.1...v3.8.2) (2019-01-03) - -**Note:** Version bump only for package @lerna/changed - -## [3.8.1](https://github.com/lerna/lerna/compare/v3.8.0...v3.8.1) (2018-12-31) - -**Note:** Version bump only for package @lerna/changed - -# [3.8.0](https://github.com/lerna/lerna/compare/v3.7.2...v3.8.0) (2018-12-21) - -**Note:** Version bump only for package @lerna/changed - -## [3.7.2](https://github.com/lerna/lerna/compare/v3.7.1...v3.7.2) (2018-12-21) - -**Note:** Version bump only for package @lerna/changed - -## [3.7.1](https://github.com/lerna/lerna/compare/v3.7.0...v3.7.1) (2018-12-20) - -**Note:** Version bump only for package @lerna/changed - -# [3.7.0](https://github.com/lerna/lerna/compare/v3.6.0...v3.7.0) (2018-12-19) - -**Note:** Version bump only for package @lerna/changed - -# [3.6.0](https://github.com/lerna/lerna/compare/v3.5.1...v3.6.0) (2018-12-07) - -### Features - -- **listable:** Add --toposort option ([b387881](https://github.com/lerna/lerna/commit/b387881)), closes [#1652](https://github.com/lerna/lerna/issues/1652) - -# [3.5.0](https://github.com/lerna/lerna/compare/v3.4.3...v3.5.0) (2018-11-27) - -### Features - -- **version:** Add `--include-merged-tags` option ([#1712](https://github.com/lerna/lerna/issues/1712)) ([7ee05d7](https://github.com/lerna/lerna/commit/7ee05d7)) - -## [3.4.1](https://github.com/lerna/lerna/compare/v3.4.0...v3.4.1) (2018-10-04) - -**Note:** Version bump only for package @lerna/changed - - - -## [3.3.2](https://github.com/lerna/lerna/compare/v3.3.1...v3.3.2) (2018-09-12) - -**Note:** Version bump only for package @lerna/changed - - - -## [3.3.1](https://github.com/lerna/lerna/compare/v3.3.0...v3.3.1) (2018-09-11) - -**Note:** Version bump only for package @lerna/changed - - - -# [3.3.0](https://github.com/lerna/lerna/compare/v3.2.1...v3.3.0) (2018-09-06) - -**Note:** Version bump only for package @lerna/changed - - - -# [3.2.0](https://github.com/lerna/lerna/compare/v3.1.4...v3.2.0) (2018-08-28) - -**Note:** Version bump only for package @lerna/changed - - - -## [3.1.3](https://github.com/lerna/lerna/compare/v3.1.2...v3.1.3) (2018-08-21) - -**Note:** Version bump only for package @lerna/changed - - - -## [3.1.2](https://github.com/lerna/lerna/compare/v3.1.1...v3.1.2) (2018-08-20) - -### Bug Fixes - -- Use packageGraph.rawPackageList instead of misleading instance.filteredPackages ([2e2abdc](https://github.com/lerna/lerna/commit/2e2abdc)) - - - -# [3.1.0](https://github.com/lerna/lerna/compare/v3.0.6...v3.1.0) (2018-08-17) - -### Bug Fixes - -- **command:** Detect composed commands more accurately ([1e51b39](https://github.com/lerna/lerna/commit/1e51b39)) - - - -## [3.0.6](https://github.com/lerna/lerna/compare/v3.0.5...v3.0.6) (2018-08-16) - -**Note:** Version bump only for package @lerna/changed - - - -## [3.0.5](https://github.com/lerna/lerna/compare/v3.0.4...v3.0.5) (2018-08-15) - -**Note:** Version bump only for package @lerna/changed - - - -## [3.0.2](https://github.com/lerna/lerna/compare/v3.0.1...v3.0.2) (2018-08-11) - -**Note:** Version bump only for package @lerna/changed - - - -# [3.0.0](https://github.com/lerna/lerna/compare/v3.0.0-rc.0...v3.0.0) (2018-08-10) - -### Features - -- Split `lerna version` from of `lerna publish` ([#1522](https://github.com/lerna/lerna/issues/1522)) ([8b97394](https://github.com/lerna/lerna/commit/8b97394)), closes [#277](https://github.com/lerna/lerna/issues/277) [#936](https://github.com/lerna/lerna/issues/936) [#956](https://github.com/lerna/lerna/issues/956) [#961](https://github.com/lerna/lerna/issues/961) [#1056](https://github.com/lerna/lerna/issues/1056) [#1118](https://github.com/lerna/lerna/issues/1118) [#1385](https://github.com/lerna/lerna/issues/1385) [#1483](https://github.com/lerna/lerna/issues/1483) [#1494](https://github.com/lerna/lerna/issues/1494) -- **changed:** Support list output options ([6ecdd83](https://github.com/lerna/lerna/commit/6ecdd83)) - -### BREAKING CHANGES - -- **changed:** The package names emitted to stdout are no longer prefixed by a "- ", and private packages are no longer displayed by default. -- - `--preid` now defaults to "alpha" during prereleases: - - The previous default for this option was undefined, which led to an awkward "1.0.1-0" result when passed to `semver.inc()`. - - The new default "alpha" yields a much more useful "1.0.1-alpha.0" result. Any previous prerelease ID will be preserved, just as it was before. - -- `--no-verify` is no longer passed to `git commit` by default, but controlled by the new `--commit-hooks` option: - - The previous behavior was too overzealous, and the new option operates exactly like the corresponding [npm version](https://docs.npmjs.com/cli/version#commit-hooks) option of the same name. - - As long as your pre-commit hooks are properly scoped to ignore changes in package.json files, this change should not affect you. If that is not the case, you may pass `--no-commit-hooks` to restore the previous behavior. - - - -# [3.0.0-rc.0](https://github.com/lerna/lerna/compare/v3.0.0-beta.21...v3.0.0-rc.0) (2018-07-27) - -### Bug Fixes - -- **changed:** Clarify early exit log message ([b132c3a](https://github.com/lerna/lerna/commit/b132c3a)) - -### Code Refactoring - -- **collect-updates:** Make argument signature explicit ([e6ba19f](https://github.com/lerna/lerna/commit/e6ba19f)) - -### Features - -- Add description from --help summary [skip ci] ([9b65d8e](https://github.com/lerna/lerna/commit/9b65d8e)) -- **cli:** Upgrade to Yargs 12 ([7899ab8](https://github.com/lerna/lerna/commit/7899ab8)) -- **command:** Remove .defaultOptions() from option resolution stack ([2b27a54](https://github.com/lerna/lerna/commit/2b27a54)) -- Count packages affected in command summary logging ([5f5e585](https://github.com/lerna/lerna/commit/5f5e585)) - -### BREAKING CHANGES - -- **collect-updates:** Instead of an opaque command instance, distinct positional arguments are required. - - - -# [3.0.0-beta.21](https://github.com/lerna/lerna/compare/v3.0.0-beta.20...v3.0.0-beta.21) (2018-05-12) - -**Note:** Version bump only for package @lerna/changed - - - -# [3.0.0-beta.20](https://github.com/lerna/lerna/compare/v3.0.0-beta.19...v3.0.0-beta.20) (2018-05-07) - -**Note:** Version bump only for package @lerna/changed - - - -# [3.0.0-beta.19](https://github.com/lerna/lerna/compare/v3.0.0-beta.18...v3.0.0-beta.19) (2018-05-03) - -**Note:** Version bump only for package @lerna/changed - - - -# [3.0.0-beta.18](https://github.com/lerna/lerna/compare/v3.0.0-beta.17...v3.0.0-beta.18) (2018-04-24) - -**Note:** Version bump only for package @lerna/changed - - - -# [3.0.0-beta.17](https://github.com/lerna/lerna/compare/v3.0.0-beta.16...v3.0.0-beta.17) (2018-04-13) - -**Note:** Version bump only for package @lerna/changed - - - -# [3.0.0-beta.15](https://github.com/lerna/lerna/compare/v3.0.0-beta.14...v3.0.0-beta.15) (2018-04-09) - -**Note:** Version bump only for package @lerna/changed - - - -# [3.0.0-beta.14](https://github.com/lerna/lerna/compare/v3.0.0-beta.13...v3.0.0-beta.14) (2018-04-03) - -**Note:** Version bump only for package @lerna/changed - - - -# [3.0.0-beta.13](https://github.com/lerna/lerna/compare/v3.0.0-beta.12...v3.0.0-beta.13) (2018-03-31) - -### Features - -- Enable progress bars only when necessary ([b766c83](https://github.com/lerna/lerna/commit/b766c83)) - - - -# [3.0.0-beta.12](https://github.com/lerna/lerna/compare/v3.0.0-beta.11...v3.0.0-beta.12) (2018-03-30) - -**Note:** Version bump only for package @lerna/changed - - - -# [3.0.0-beta.11](https://github.com/lerna/lerna/compare/v3.0.0-beta.10...v3.0.0-beta.11) (2018-03-29) - -**Note:** Version bump only for package @lerna/changed - - - -# [3.0.0-beta.10](https://github.com/lerna/lerna/compare/v3.0.0-beta.9...v3.0.0-beta.10) (2018-03-27) - -### Features - -- **commands:** Delay require of command instantiation ([a1284f3](https://github.com/lerna/lerna/commit/a1284f3)) - -### BREAKING CHANGES - -- **commands:** The default export of command packages is now a factory, not the subclass (which is now a named export). - - - -# [3.0.0-beta.9](https://github.com/lerna/lerna/compare/v3.0.0-beta.8...v3.0.0-beta.9) (2018-03-24) - -### Features - -- **project:** Normalize config.commands -> config.command ([24e55e3](https://github.com/lerna/lerna/commit/24e55e3)) - - - -# [3.0.0-beta.8](https://github.com/lerna/lerna/compare/v3.0.0-beta.7...v3.0.0-beta.8) (2018-03-22) - -**Note:** Version bump only for package @lerna/changed - - - -# [3.0.0-beta.7](https://github.com/lerna/lerna/compare/v3.0.0-beta.6...v3.0.0-beta.7) (2018-03-20) - -**Note:** Version bump only for package @lerna/changed - - - -# [3.0.0-beta.4](https://github.com/lerna/lerna/compare/v3.0.0-beta.3...v3.0.0-beta.4) (2018-03-19) - -**Note:** Version bump only for package @lerna/changed - - - -# [3.0.0-beta.3](https://github.com/lerna/lerna/compare/v3.0.0-beta.2...v3.0.0-beta.3) (2018-03-15) - -**Note:** Version bump only for package @lerna/changed - - - -# [3.0.0-beta.2](https://github.com/lerna/lerna/compare/v3.0.0-beta.1...v3.0.0-beta.2) (2018-03-10) - -**Note:** Version bump only for package @lerna/changed - - - -# [3.0.0-beta.1](https://github.com/lerna/lerna/compare/v3.0.0-beta.0...v3.0.0-beta.1) (2018-03-09) - -**Note:** Version bump only for package @lerna/changed diff --git a/commands/changed/README.md b/commands/changed/README.md deleted file mode 100644 index f17fcf013c..0000000000 --- a/commands/changed/README.md +++ /dev/null @@ -1,39 +0,0 @@ -# `@lerna/changed` - -> List local packages that have changed since the last tagged release - -Install [lerna](https://www.npmjs.com/package/lerna) for access to the `lerna` CLI. - -## Usage - -The output of `lerna changed` is a list of packages that would be the subjects of the next `lerna version` or `lerna publish` execution. - -```sh -$ lerna changed -package-1 -package-2 -``` - -**Note:** `lerna.json` configuration for `lerna publish` _and_ `lerna version` also affects -`lerna changed`, e.g. `command.publish.ignoreChanges`. - -## Options - -`lerna changed` supports all of the flags supported by [`lerna ls`](https://github.com/lerna/lerna/tree/main/commands/list#options): - -- [`--json`](https://github.com/lerna/lerna/tree/main/commands/list#--json) -- [`--ndjson`](https://github.com/lerna/lerna/tree/main/commands/list#--ndjson) -- [`-a`, `--all`](https://github.com/lerna/lerna/tree/main/commands/list#--all) -- [`-l`, `--long`](https://github.com/lerna/lerna/tree/main/commands/list#--long) -- [`-p`, `--parseable`](https://github.com/lerna/lerna/tree/main/commands/list#--parseable) -- [`--toposort`](https://github.com/lerna/lerna/tree/main/commands/list#--toposort) -- [`--graph`](https://github.com/lerna/lerna/tree/main/commands/list#--graph) - -Unlike `lerna ls`, however, `lerna changed` **does not** support [filter options](https://www.npmjs.com/package/@lerna/filter-options), as filtering is not supported by `lerna version` or `lerna publish`. - -`lerna changed` supports the following options of [`lerna version`](https://github.com/lerna/lerna/tree/main/commands/version#options) (the others are irrelevant): - -- [`--conventional-graduate`](https://github.com/lerna/lerna/tree/main/commands/version#--conventional-graduate). -- [`--force-publish`](https://github.com/lerna/lerna/tree/main/commands/version#--force-publish). -- [`--ignore-changes`](https://github.com/lerna/lerna/tree/main/commands/version#--ignore-changes). -- [`--include-merged-tags`](https://github.com/lerna/lerna/tree/main/commands/version#--include-merged-tags). diff --git a/commands/changed/__tests__/changed-command.test.js b/commands/changed/__tests__/changed-command.test.js deleted file mode 100644 index c9776c00bd..0000000000 --- a/commands/changed/__tests__/changed-command.test.js +++ /dev/null @@ -1,178 +0,0 @@ -"use strict"; - -// mocked modules -const { collectUpdates } = require("@lerna/collect-updates"); -const { output } = require("@lerna/output"); - -// helpers -const initFixture = require("@lerna-test/helpers").initFixtureFactory(__dirname); -const { loggingOutput } = require("@lerna-test/helpers/logging-output"); -const { updateLernaConfig } = require("@lerna-test/helpers"); - -// file under test -const lernaChanged = require("@lerna-test/helpers").commandRunner(require("../command")); - -// remove quotes around top-level strings -expect.addSnapshotSerializer({ - test(val) { - return typeof val === "string"; - }, - serialize(val, config, indentation, depth) { - // top-level strings don't need quotes, but nested ones do (object properties, etc) - return depth ? `"${val}"` : val; - }, -}); - -// normalize temp directory paths in snapshots -expect.addSnapshotSerializer(require("@lerna-test/helpers/serializers/serialize-tempdir")); - -describe("ChangedCommand", () => { - let cwd; - - beforeAll(async () => { - cwd = await initFixture("normal"); - }); - - it("lists changed packages", async () => { - collectUpdates.setUpdated(cwd, "package-2", "package-3"); - - await lernaChanged(cwd)(); - - expect(output.logged()).toMatchInlineSnapshot(` -package-2 -package-3 -`); - }); - - it("passes --force-publish to update collector", async () => { - await lernaChanged(cwd)("--force-publish"); - - expect(output.logged()).toMatchInlineSnapshot(` -package-1 -package-2 -package-3 -package-4 -`); - expect(collectUpdates).toHaveBeenLastCalledWith( - expect.any(Array), - expect.any(Object), - expect.objectContaining({ cwd }), - expect.objectContaining({ forcePublish: true }) - ); - }); - - it("passes --ignore-changes to update collector", async () => { - await lernaChanged(cwd)("--ignore-changes", "**/cli-ignore"); - - expect(collectUpdates).toHaveBeenLastCalledWith( - expect.any(Array), - expect.any(Object), - expect.objectContaining({ cwd }), - expect.objectContaining({ ignoreChanges: ["**/cli-ignore"] }) - ); - }); - - it("reads durable ignoreChanges config from version namespace", async () => { - await updateLernaConfig(cwd, { - command: { - version: { - ignoreChanges: ["**/durable-ignore"], - }, - }, - }); - - await lernaChanged(cwd)(); - - expect(collectUpdates).toHaveBeenLastCalledWith( - expect.any(Array), - expect.any(Object), - expect.objectContaining({ cwd }), - expect.objectContaining({ ignoreChanges: ["**/durable-ignore"] }) - ); - }); - - it("passes --include-merged-tags to update collector", async () => { - await lernaChanged(cwd)("--include-merged-tags"); - - expect(collectUpdates).toHaveBeenLastCalledWith( - expect.any(Array), - expect.any(Object), - expect.objectContaining({ cwd }), - expect.objectContaining({ includeMergedTags: true }) - ); - }); - - it("passes --conventional-graduate to update collector", async () => { - await lernaChanged(cwd)("--conventional-graduate=*"); - - expect(collectUpdates).toHaveBeenLastCalledWith( - expect.any(Array), - expect.any(Object), - expect.objectContaining({ cwd }), - expect.objectContaining({ conventionalGraduate: "*", conventionalCommits: true }) - ); - }); - - it("warns when --force-publish superseded by --conventional-graduate", async () => { - await lernaChanged(cwd)("--conventional-graduate", "foo", "--force-publish", "bar"); - - const [logMessage] = loggingOutput("warn"); - expect(logMessage).toBe("--force-publish superseded by --conventional-graduate"); - }); - - it("lists changed private packages with --all", async () => { - collectUpdates.setUpdated(cwd, "package-5"); - - await lernaChanged(cwd)("--all"); - - expect(output.logged()).toBe("package-5 (PRIVATE)"); - }); - - it("exits non-zero when there are no changed packages", async () => { - collectUpdates.setUpdated(cwd); - - await lernaChanged(cwd)(); - - expect(process.exitCode).toBe(1); - - // reset exit code - process.exitCode = undefined; - }); - - it("supports all listable flags", async () => { - await lernaChanged(cwd)("-alp"); - - expect(output.logged()).toMatchInlineSnapshot(` -__TEST_ROOTDIR__/packages/package-1:package-1:1.0.0 -__TEST_ROOTDIR__/packages/package-2:package-2:1.0.0 -__TEST_ROOTDIR__/packages/package-3:package-3:1.0.0 -__TEST_ROOTDIR__/packages/package-4:package-4:1.0.0 -__TEST_ROOTDIR__/packages/package-5:package-5:1.0.0:PRIVATE -`); - }); - - it("outputs a stringified array of result objects with --json", async () => { - collectUpdates.setUpdated(cwd, "package-2", "package-3"); - - await lernaChanged(cwd)("--json"); - - // Output should be a parseable string - const jsonOutput = JSON.parse(output.logged()); - expect(jsonOutput).toMatchInlineSnapshot(` -Array [ - Object { - "location": "__TEST_ROOTDIR__/packages/package-2", - "name": "package-2", - "private": false, - "version": "1.0.0", - }, - Object { - "location": "__TEST_ROOTDIR__/packages/package-3", - "name": "package-3", - "private": false, - "version": "1.0.0", - }, -] -`); - }); -}); diff --git a/commands/changed/command.js b/commands/changed/command.js deleted file mode 100644 index baf92c6422..0000000000 --- a/commands/changed/command.js +++ /dev/null @@ -1,50 +0,0 @@ -"use strict"; - -const listable = require("@lerna/listable"); - -/** - * @see https://github.com/yargs/yargs/blob/master/docs/advanced.md#providing-a-command-module - */ -exports.command = "changed"; - -exports.aliases = ["updated"]; - -exports.describe = "List local packages that have changed since the last tagged release"; - -exports.builder = (yargs) => { - const opts = { - // only the relevant bits from `lerna version` - "conventional-commits": { - // fallback for overzealous --conventional-graduate - hidden: true, - type: "boolean", - }, - "conventional-graduate": { - describe: "Detect currently prereleased packages that would change to a non-prerelease version.", - // type must remain ambiguous because it is overloaded (boolean _or_ string _or_ array) - }, - "force-publish": { - describe: "Always include targeted packages when detecting changed packages, skipping default logic.", - // type must remain ambiguous because it is overloaded (boolean _or_ string _or_ array) - }, - "ignore-changes": { - describe: [ - "Ignore changes in files matched by glob(s) when detecting changed packages.", - "Pass --no-ignore-changes to completely disable.", - ].join("\n"), - type: "array", - }, - "include-merged-tags": { - describe: "Include tags from merged branches when detecting changed packages.", - type: "boolean", - }, - }; - - yargs.options(opts).group(Object.keys(opts), "Command Options:"); - - return listable.options(yargs, "Output Options:"); -}; - -exports.handler = function handler(argv) { - return require(".")(argv); -}; diff --git a/commands/changed/index.js b/commands/changed/index.js deleted file mode 100644 index 8c385843ef..0000000000 --- a/commands/changed/index.js +++ /dev/null @@ -1,64 +0,0 @@ -"use strict"; - -const { Command } = require("@lerna/command"); -const { collectUpdates } = require("@lerna/collect-updates"); -const listable = require("@lerna/listable"); -const { output } = require("@lerna/output"); - -module.exports = factory; - -function factory(argv) { - return new ChangedCommand(argv); -} - -class ChangedCommand extends Command { - get otherCommandConfigs() { - // back-compat - return ["version", "publish"]; - } - - initialize() { - if (this.options.conventionalGraduate) { - // provide artificial --conventional-commits so --conventional-graduate works - this.options.conventionalCommits = true; - - if (this.options.forcePublish) { - this.logger.warn("option", "--force-publish superseded by --conventional-graduate"); - } - } - - const updates = collectUpdates( - this.packageGraph.rawPackageList, - this.packageGraph, - this.execOpts, - this.options - ); - - this.result = listable.format( - updates.map((node) => node.pkg), - this.options - ); - - if (this.result.count === 0) { - this.logger.info("", "No changed packages found"); - - process.exitCode = 1; - - // prevents execute() - return false; - } - } - - execute() { - output(this.result.text); - - this.logger.success( - "found", - "%d %s ready to publish", - this.result.count, - this.result.count === 1 ? "package" : "packages" - ); - } -} - -module.exports.ChangedCommand = ChangedCommand; diff --git a/commands/changed/package.json b/commands/changed/package.json deleted file mode 100644 index ca54fa24ac..0000000000 --- a/commands/changed/package.json +++ /dev/null @@ -1,40 +0,0 @@ -{ - "name": "@lerna/changed", - "version": "6.4.1", - "description": "List local packages that have changed since the last tagged release", - "keywords": [ - "lerna", - "command" - ], - "homepage": "https://lerna.js.org", - "license": "MIT", - "author": { - "name": "Daniel Stockman", - "url": "https://github.com/evocateur" - }, - "files": [ - "command.js", - "index.js" - ], - "main": "index.js", - "engines": { - "node": "^14.15.0 || >=16.0.0" - }, - "publishConfig": { - "access": "public" - }, - "repository": { - "type": "git", - "url": "git+https://github.com/lerna/lerna.git", - "directory": "commands/changed" - }, - "scripts": { - "test": "echo \"Run tests from root\" && exit 1" - }, - "dependencies": { - "@lerna/collect-updates": "file:../../utils/collect-updates", - "@lerna/command": "file:../../core/command", - "@lerna/listable": "file:../../utils/listable", - "@lerna/output": "file:../../utils/output" - } -} diff --git a/commands/clean/CHANGELOG.md b/commands/clean/CHANGELOG.md deleted file mode 100644 index 0ffb221709..0000000000 --- a/commands/clean/CHANGELOG.md +++ /dev/null @@ -1,478 +0,0 @@ -# Change Log - -All notable changes to this project will be documented in this file. -See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. - -## [6.4.1](https://github.com/lerna/lerna/compare/v6.4.0...v6.4.1) (2023-01-12) - -**Note:** Version bump only for package @lerna/clean - -# [6.4.0](https://github.com/lerna/lerna/compare/v6.3.0...v6.4.0) (2023-01-05) - -**Note:** Version bump only for package @lerna/clean - -# [6.3.0](https://github.com/lerna/lerna/compare/v6.2.0...v6.3.0) (2022-12-26) - -**Note:** Version bump only for package @lerna/clean - -# [6.2.0](https://github.com/lerna/lerna/compare/v6.1.0...v6.2.0) (2022-12-13) - -**Note:** Version bump only for package @lerna/clean - -# [6.1.0](https://github.com/lerna/lerna/compare/v6.0.3...v6.1.0) (2022-11-29) - -**Note:** Version bump only for package @lerna/clean - -## [6.0.3](https://github.com/lerna/lerna/compare/v6.0.2...v6.0.3) (2022-11-07) - -**Note:** Version bump only for package @lerna/clean - -## [6.0.2](https://github.com/lerna/lerna/compare/v6.0.1...v6.0.2) (2022-11-02) - -**Note:** Version bump only for package @lerna/clean - -## [6.0.1](https://github.com/lerna/lerna/compare/v6.0.0...v6.0.1) (2022-10-14) - -**Note:** Version bump only for package @lerna/clean - -# [6.0.0](https://github.com/lerna/lerna/compare/v6.0.0-alpha.2...v6.0.0) (2022-10-12) - -**Note:** Version bump only for package @lerna/clean - -# [6.0.0-alpha.2](https://github.com/lerna/lerna/compare/v6.0.0-alpha.1...v6.0.0-alpha.2) (2022-10-12) - -**Note:** Version bump only for package @lerna/clean - -# [6.0.0-alpha.1](https://github.com/lerna/lerna/compare/v5.6.2...v6.0.0-alpha.1) (2022-10-09) - -# [6.0.0-alpha.0](https://github.com/lerna/lerna/compare/v5.6.1...v6.0.0-alpha.0) (2022-10-07) - -**Note:** Version bump only for package @lerna/clean - -## [5.6.2](https://github.com/lerna/lerna/compare/v5.6.1...v5.6.2) (2022-10-09) - -**Note:** Version bump only for package @lerna/clean - -## [5.6.1](https://github.com/lerna/lerna/compare/v5.6.0...v5.6.1) (2022-09-30) - -**Note:** Version bump only for package @lerna/clean - -# [5.6.0](https://github.com/lerna/lerna/compare/v5.5.4...v5.6.0) (2022-09-29) - -**Note:** Version bump only for package @lerna/clean - -## [5.5.4](https://github.com/lerna/lerna/compare/v5.5.3...v5.5.4) (2022-09-28) - -**Note:** Version bump only for package @lerna/clean - -## [5.5.3](https://github.com/lerna/lerna/compare/v5.5.2...v5.5.3) (2022-09-28) - -**Note:** Version bump only for package @lerna/clean - -## [5.5.2](https://github.com/lerna/lerna/compare/v5.5.1...v5.5.2) (2022-09-20) - -**Note:** Version bump only for package @lerna/clean - -## [5.5.1](https://github.com/lerna/lerna/compare/v5.5.0...v5.5.1) (2022-09-09) - -**Note:** Version bump only for package @lerna/clean - -# [5.5.0](https://github.com/lerna/lerna/compare/v5.4.3...v5.5.0) (2022-08-31) - -**Note:** Version bump only for package @lerna/clean - -## [5.4.3](https://github.com/lerna/lerna/compare/v5.4.2...v5.4.3) (2022-08-16) - -**Note:** Version bump only for package @lerna/clean - -## [5.4.2](https://github.com/lerna/lerna/compare/v5.4.1...v5.4.2) (2022-08-14) - -**Note:** Version bump only for package @lerna/clean - -## [5.4.1](https://github.com/lerna/lerna/compare/v5.4.0...v5.4.1) (2022-08-12) - -**Note:** Version bump only for package @lerna/clean - -# [5.4.0](https://github.com/lerna/lerna/compare/v5.3.0...v5.4.0) (2022-08-08) - -**Note:** Version bump only for package @lerna/clean - -# [5.3.0](https://github.com/lerna/lerna/compare/v5.2.0...v5.3.0) (2022-07-27) - -**Note:** Version bump only for package @lerna/clean - -# [5.2.0](https://github.com/lerna/lerna/compare/v5.1.8...v5.2.0) (2022-07-22) - -**Note:** Version bump only for package @lerna/clean - -## [5.1.8](https://github.com/lerna/lerna/compare/v5.1.7...v5.1.8) (2022-07-07) - -**Note:** Version bump only for package @lerna/clean - -## [5.1.7](https://github.com/lerna/lerna/compare/v5.1.6...v5.1.7) (2022-07-06) - -**Note:** Version bump only for package @lerna/clean - -## [5.1.6](https://github.com/lerna/lerna/compare/v5.1.5...v5.1.6) (2022-06-24) - -**Note:** Version bump only for package @lerna/clean - -## [5.1.5](https://github.com/lerna/lerna/compare/v5.1.4...v5.1.5) (2022-06-24) - -**Note:** Version bump only for package @lerna/clean - -## [5.1.4](https://github.com/lerna/lerna/compare/v5.1.3...v5.1.4) (2022-06-15) - -**Note:** Version bump only for package @lerna/clean - -## [5.1.3](https://github.com/lerna/lerna/compare/v5.1.2...v5.1.3) (2022-06-15) - -**Note:** Version bump only for package @lerna/clean - -## [5.1.2](https://github.com/lerna/lerna/compare/v5.1.1...v5.1.2) (2022-06-13) - -**Note:** Version bump only for package @lerna/clean - -## [5.1.1](https://github.com/lerna/lerna/compare/v5.1.0...v5.1.1) (2022-06-09) - -### Bug Fixes - -- allow maintenance LTS node 14 engines starting at 14.15.0 ([#3161](https://github.com/lerna/lerna/issues/3161)) ([72305e4](https://github.com/lerna/lerna/commit/72305e4dbab607a2d87ae4efa6ee577c93a9dda9)) - -# [5.1.0](https://github.com/lerna/lerna/compare/v5.0.0...v5.1.0) (2022-06-07) - -**Note:** Version bump only for package @lerna/clean - -# [5.1.0-alpha.0](https://github.com/lerna/lerna/compare/v4.0.0...v5.1.0-alpha.0) (2022-05-25) - -**Note:** Version bump only for package @lerna/clean - -# [5.0.0](https://github.com/lerna/lerna/compare/v4.0.0...v5.0.0) (2022-05-24) - -**Note:** Version bump only for package @lerna/clean - -# [4.0.0](https://github.com/lerna/lerna/compare/v3.22.1...v4.0.0) (2021-02-10) - -### Features - -- **deps:** Bump dependencies ([affed1c](https://github.com/lerna/lerna/commit/affed1ce0fce91f01b0a9eafe357db2d985b974f)) -- Consume named exports of sibling modules ([63499e3](https://github.com/lerna/lerna/commit/63499e33652bc78fe23751875d74017e2f16a689)) -- **deps:** p-map-series@^2.1.0 ([7f68076](https://github.com/lerna/lerna/commit/7f680767e0b3c7a15f951c51d4975150fb6e9112)) -- **deps:** p-map@^4.0.0 ([92b1364](https://github.com/lerna/lerna/commit/92b1364735e1f2cf379cf1047c60c4fb897d55f5)) -- **deps:** p-waterfall@^2.1.0 ([7b7ea50](https://github.com/lerna/lerna/commit/7b7ea503e8371e7f663fd604bff51aebfe9e7b33)) -- Drop support for Node v6.x & v8.x ([ff4bb4d](https://github.com/lerna/lerna/commit/ff4bb4da215555e3bb136f5af09b5cbc631e57bb)) - -### BREAKING CHANGES - -- Node v6.x & v8.x are no longer supported. Please upgrade to the latest LTS release. - -Here's the gnarly one-liner I used to make these changes: - -``` -npx lerna exec --concurrency 1 --stream -- 'json -I -f package.json -e '"'"'this.engines=this.engines||{};this.engines.node=">= 10.18.0"'"'" -``` - -(requires `npm i -g json` beforehand) - -# [3.21.0](https://github.com/lerna/lerna/compare/v3.20.2...v3.21.0) (2020-05-13) - -**Note:** Version bump only for package @lerna/clean - -# [3.20.0](https://github.com/lerna/lerna/compare/v3.19.0...v3.20.0) (2019-12-27) - -**Note:** Version bump only for package @lerna/clean - -## [3.18.5](https://github.com/lerna/lerna/compare/v3.18.4...v3.18.5) (2019-11-20) - -**Note:** Version bump only for package @lerna/clean - -## [3.18.4](https://github.com/lerna/lerna/compare/v3.18.3...v3.18.4) (2019-11-08) - -### Bug Fixes - -- **filter-options:** Ensure `--include-merged-tags` is available to all `--since`-filterable commands ([287bcd8](https://github.com/lerna/lerna/commit/287bcd8b5c8dbb2dc4def5c933d0b4917c34813e)), closes [#2332](https://github.com/lerna/lerna/issues/2332) - -# [3.18.0](https://github.com/lerna/lerna/compare/v3.17.0...v3.18.0) (2019-10-15) - -**Note:** Version bump only for package @lerna/clean - -## [3.16.5](https://github.com/lerna/lerna/compare/v3.16.4...v3.16.5) (2019-10-07) - -**Note:** Version bump only for package @lerna/clean - -# [3.16.0](https://github.com/lerna/lerna/compare/v3.15.0...v3.16.0) (2019-07-18) - -### Features - -- **deps:** `p-map@^2.1.0` ([9e58394](https://github.com/lerna/lerna/commit/9e58394)) - -# [3.15.0](https://github.com/lerna/lerna/compare/v3.14.2...v3.15.0) (2019-06-09) - -**Note:** Version bump only for package @lerna/clean - -## [3.14.2](https://github.com/lerna/lerna/compare/v3.14.1...v3.14.2) (2019-06-09) - -**Note:** Version bump only for package @lerna/clean - -# [3.14.0](https://github.com/lerna/lerna/compare/v3.13.4...v3.14.0) (2019-05-14) - -**Note:** Version bump only for package @lerna/clean - -## [3.13.3](https://github.com/lerna/lerna/compare/v3.13.2...v3.13.3) (2019-04-17) - -**Note:** Version bump only for package @lerna/clean - -## [3.13.1](https://github.com/lerna/lerna/compare/v3.13.0...v3.13.1) (2019-02-26) - -**Note:** Version bump only for package @lerna/clean - -# [3.13.0](https://github.com/lerna/lerna/compare/v3.12.1...v3.13.0) (2019-02-15) - -### Features - -- **meta:** Add `repository.directory` field to package.json ([aec5023](https://github.com/lerna/lerna/commit/aec5023)) -- **meta:** Normalize package.json `homepage` field ([abeb4dc](https://github.com/lerna/lerna/commit/abeb4dc)) - -## [3.12.1](https://github.com/lerna/lerna/compare/v3.12.0...v3.12.1) (2019-02-14) - -**Note:** Version bump only for package @lerna/clean - -# [3.12.0](https://github.com/lerna/lerna/compare/v3.11.1...v3.12.0) (2019-02-14) - -**Note:** Version bump only for package @lerna/clean - -# [3.11.0](https://github.com/lerna/lerna/compare/v3.10.8...v3.11.0) (2019-02-08) - -**Note:** Version bump only for package @lerna/clean - -## [3.10.6](https://github.com/lerna/lerna/compare/v3.10.5...v3.10.6) (2019-01-19) - -**Note:** Version bump only for package @lerna/clean - -## [3.10.1](https://github.com/lerna/lerna/compare/v3.10.0...v3.10.1) (2019-01-09) - -**Note:** Version bump only for package @lerna/clean - -# [3.10.0](https://github.com/lerna/lerna/compare/v3.9.1...v3.10.0) (2019-01-08) - -**Note:** Version bump only for package @lerna/clean - -# [3.9.0](https://github.com/lerna/lerna/compare/v3.8.5...v3.9.0) (2019-01-08) - -**Note:** Version bump only for package @lerna/clean - -## [3.8.5](https://github.com/lerna/lerna/compare/v3.8.4...v3.8.5) (2019-01-05) - -**Note:** Version bump only for package @lerna/clean - -## [3.8.1](https://github.com/lerna/lerna/compare/v3.8.0...v3.8.1) (2018-12-31) - -### Bug Fixes - -- **progress:** Correctly avoid progress where we don't want it ([0de3df9](https://github.com/lerna/lerna/commit/0de3df9)) -- **progress:** Enable progress during logging setup, correcting default ([da81e60](https://github.com/lerna/lerna/commit/da81e60)) - -## [3.7.2](https://github.com/lerna/lerna/compare/v3.7.1...v3.7.2) (2018-12-21) - -**Note:** Version bump only for package @lerna/clean - -## [3.7.1](https://github.com/lerna/lerna/compare/v3.7.0...v3.7.1) (2018-12-20) - -### Bug Fixes - -- **clean:** Pulse progress bar during execution ([f1202de](https://github.com/lerna/lerna/commit/f1202de)) - -# [3.7.0](https://github.com/lerna/lerna/compare/v3.6.0...v3.7.0) (2018-12-19) - -**Note:** Version bump only for package @lerna/clean - -# [3.6.0](https://github.com/lerna/lerna/compare/v3.5.1...v3.6.0) (2018-12-07) - -**Note:** Version bump only for package @lerna/clean - -# [3.5.0](https://github.com/lerna/lerna/compare/v3.4.3...v3.5.0) (2018-11-27) - -**Note:** Version bump only for package @lerna/clean - - - -## [3.3.2](https://github.com/lerna/lerna/compare/v3.3.1...v3.3.2) (2018-09-12) - -**Note:** Version bump only for package @lerna/clean - - - -## [3.3.1](https://github.com/lerna/lerna/compare/v3.3.0...v3.3.1) (2018-09-11) - -**Note:** Version bump only for package @lerna/clean - - - -# [3.3.0](https://github.com/lerna/lerna/compare/v3.2.1...v3.3.0) (2018-09-06) - -**Note:** Version bump only for package @lerna/clean - - - -## [3.1.3](https://github.com/lerna/lerna/compare/v3.1.2...v3.1.3) (2018-08-21) - -**Note:** Version bump only for package @lerna/clean - - - -## [3.1.2](https://github.com/lerna/lerna/compare/v3.1.1...v3.1.2) (2018-08-20) - -### Bug Fixes - -- Setup instance.filteredPackages explicitly ([32357f8](https://github.com/lerna/lerna/commit/32357f8)) - - - -# [3.1.0](https://github.com/lerna/lerna/compare/v3.0.6...v3.1.0) (2018-08-17) - -**Note:** Version bump only for package @lerna/clean - - - -## [3.0.6](https://github.com/lerna/lerna/compare/v3.0.5...v3.0.6) (2018-08-16) - -**Note:** Version bump only for package @lerna/clean - - - -## [3.0.5](https://github.com/lerna/lerna/compare/v3.0.4...v3.0.5) (2018-08-15) - -### Bug Fixes - -- **options:** Provide -y alias for --yes ([3ea460c](https://github.com/lerna/lerna/commit/3ea460c)) - - - -# [3.0.0](https://github.com/lerna/lerna/compare/v3.0.0-rc.0...v3.0.0) (2018-08-10) - -**Note:** Version bump only for package @lerna/clean - - - -# [3.0.0-rc.0](https://github.com/lerna/lerna/compare/v3.0.0-beta.21...v3.0.0-rc.0) (2018-07-27) - -### Features - -- Add description from --help summary [skip ci] ([9b65d8e](https://github.com/lerna/lerna/commit/9b65d8e)) -- **cli:** Upgrade to Yargs 12 ([7899ab8](https://github.com/lerna/lerna/commit/7899ab8)) - - - -# [3.0.0-beta.21](https://github.com/lerna/lerna/compare/v3.0.0-beta.20...v3.0.0-beta.21) (2018-05-12) - -**Note:** Version bump only for package @lerna/clean - - - -# [3.0.0-beta.20](https://github.com/lerna/lerna/compare/v3.0.0-beta.19...v3.0.0-beta.20) (2018-05-07) - -**Note:** Version bump only for package @lerna/clean - - - -# [3.0.0-beta.19](https://github.com/lerna/lerna/compare/v3.0.0-beta.18...v3.0.0-beta.19) (2018-05-03) - -**Note:** Version bump only for package @lerna/clean - - - -# [3.0.0-beta.18](https://github.com/lerna/lerna/compare/v3.0.0-beta.17...v3.0.0-beta.18) (2018-04-24) - -**Note:** Version bump only for package @lerna/clean - - - -# [3.0.0-beta.17](https://github.com/lerna/lerna/compare/v3.0.0-beta.16...v3.0.0-beta.17) (2018-04-13) - -**Note:** Version bump only for package @lerna/clean - - - -# [3.0.0-beta.15](https://github.com/lerna/lerna/compare/v3.0.0-beta.14...v3.0.0-beta.15) (2018-04-09) - -**Note:** Version bump only for package @lerna/clean - - - -# [3.0.0-beta.14](https://github.com/lerna/lerna/compare/v3.0.0-beta.13...v3.0.0-beta.14) (2018-04-03) - -**Note:** Version bump only for package @lerna/clean - - - -# [3.0.0-beta.13](https://github.com/lerna/lerna/compare/v3.0.0-beta.12...v3.0.0-beta.13) (2018-03-31) - -### Features - -- Enable progress bars only when necessary ([b766c83](https://github.com/lerna/lerna/commit/b766c83)) - - - -# [3.0.0-beta.12](https://github.com/lerna/lerna/compare/v3.0.0-beta.11...v3.0.0-beta.12) (2018-03-30) - -**Note:** Version bump only for package @lerna/clean - - - -# [3.0.0-beta.11](https://github.com/lerna/lerna/compare/v3.0.0-beta.10...v3.0.0-beta.11) (2018-03-29) - -**Note:** Version bump only for package @lerna/clean - - - -# [3.0.0-beta.10](https://github.com/lerna/lerna/compare/v3.0.0-beta.9...v3.0.0-beta.10) (2018-03-27) - -### Features - -- **commands:** Delay require of command instantiation ([a1284f3](https://github.com/lerna/lerna/commit/a1284f3)) - -### BREAKING CHANGES - -- **commands:** The default export of command packages is now a factory, not the subclass (which is now a named export). - - - -# [3.0.0-beta.9](https://github.com/lerna/lerna/compare/v3.0.0-beta.8...v3.0.0-beta.9) (2018-03-24) - -### Features - -- **command:** Rename this.repository -> this.project ([43e98a0](https://github.com/lerna/lerna/commit/43e98a0)) - - - -# [3.0.0-beta.7](https://github.com/lerna/lerna/compare/v3.0.0-beta.6...v3.0.0-beta.7) (2018-03-20) - -**Note:** Version bump only for package @lerna/clean - - - -# [3.0.0-beta.4](https://github.com/lerna/lerna/compare/v3.0.0-beta.3...v3.0.0-beta.4) (2018-03-19) - -**Note:** Version bump only for package @lerna/clean - - - -# [3.0.0-beta.3](https://github.com/lerna/lerna/compare/v3.0.0-beta.2...v3.0.0-beta.3) (2018-03-15) - -**Note:** Version bump only for package @lerna/clean - - - -# [3.0.0-beta.2](https://github.com/lerna/lerna/compare/v3.0.0-beta.1...v3.0.0-beta.2) (2018-03-10) - -### Features - -- Rename @lerna/fs-utils => @lerna/rimraf-dir ([30451ed](https://github.com/lerna/lerna/commit/30451ed)) - - - -# [3.0.0-beta.1](https://github.com/lerna/lerna/compare/v3.0.0-beta.0...v3.0.0-beta.1) (2018-03-09) - -### Bug Fixes - -- **filter-options:** require a git repo when using --since ([d21b66e](https://github.com/lerna/lerna/commit/d21b66e)), closes [#822](https://github.com/lerna/lerna/issues/822) diff --git a/commands/clean/README.md b/commands/clean/README.md deleted file mode 100644 index bd4fa5d1fa..0000000000 --- a/commands/clean/README.md +++ /dev/null @@ -1,18 +0,0 @@ -# `@lerna/clean` - -> Remove the node_modules directory from all packages - -Install [lerna](https://www.npmjs.com/package/lerna) for access to the `lerna` CLI. - -## Usage - -```sh -$ lerna clean -``` - -Remove the `node_modules` directory from all packages. - -`lerna clean` accepts all [filter flags](https://www.npmjs.com/package/@lerna/filter-options), as well as `--yes`. - - -> `lerna clean` does not remove modules from the root `node_modules` directory, even if you have the `--hoist` option enabled. diff --git a/commands/clean/__tests__/__fixtures__/integration/packages/package-2/package.json b/commands/clean/__tests__/__fixtures__/integration/packages/package-2/package.json deleted file mode 100644 index bc751b727c..0000000000 --- a/commands/clean/__tests__/__fixtures__/integration/packages/package-2/package.json +++ /dev/null @@ -1,7 +0,0 @@ -{ - "name": "@test/package-2", - "version": "1.0.0", - "dependencies": { - "@test/package-1": "1.0.0" - } -} diff --git a/commands/clean/__tests__/clean-command.test.js b/commands/clean/__tests__/clean-command.test.js deleted file mode 100644 index b6d2e56ee9..0000000000 --- a/commands/clean/__tests__/clean-command.test.js +++ /dev/null @@ -1,110 +0,0 @@ -"use strict"; - -jest.mock("@lerna/rimraf-dir"); -jest.mock("@lerna/prompt"); - -const fs = require("fs-extra"); -const path = require("path"); - -// mocked or stubbed modules -const { rimrafDir } = require("@lerna/rimraf-dir"); -const { promptConfirmation } = require("@lerna/prompt"); - -// helpers -const initFixture = require("@lerna-test/helpers").initFixtureFactory(__dirname); -const { normalizeRelativeDir } = require("@lerna-test/helpers"); - -// file under test -const lernaClean = require("@lerna-test/helpers").commandRunner(require("../command")); - -// assertion helpers -const removedDirectories = (testDir) => - rimrafDir.mock.calls.map(([directory]) => normalizeRelativeDir(testDir, directory)); - -describe("CleanCommand", () => { - // stub rimraf because we trust isaacs - // .mockResolvedValue() doesn't work when you want to reject it later - rimrafDir.mockImplementation(() => Promise.resolve()); - - promptConfirmation.mockResolvedValue(true); - - describe("basic tests", () => { - it("should rm -rf the node_modules", async () => { - const testDir = await initFixture("basic"); - - await lernaClean(testDir)(); - - expect(promptConfirmation).toHaveBeenCalled(); - expect(removedDirectories(testDir)).toEqual([ - "packages/package-1/node_modules", - "packages/package-2/node_modules", - "packages/package-3/node_modules", - ]); - }); - - it("exits early when confirmation is rejected", async () => { - const testDir = await initFixture("basic"); - - promptConfirmation.mockResolvedValueOnce(false); - - await lernaClean(testDir)(); - - expect(removedDirectories(testDir)).toEqual([]); - }); - - it("should be possible to skip asking for confirmation", async () => { - const testDir = await initFixture("basic"); - - await lernaClean(testDir)("--yes"); - - expect(promptConfirmation).not.toHaveBeenCalled(); - }); - - it("should only clean scoped packages", async () => { - const testDir = await initFixture("basic"); - - await lernaClean(testDir)("--scope", "package-1"); - - expect(removedDirectories(testDir)).toEqual(["packages/package-1/node_modules"]); - }); - - it("should not clean ignored packages", async () => { - const testDir = await initFixture("basic"); - - await lernaClean(testDir)("--ignore", "package-2", "--ignore", "@test/package-3"); - - expect(removedDirectories(testDir)).toEqual(["packages/package-1/node_modules"]); - }); - - it("exits non-zero when rimraf errors egregiously", async () => { - rimrafDir.mockImplementationOnce(() => Promise.reject(new Error("whoops"))); - - const testDir = await initFixture("basic"); - const command = lernaClean(testDir)(); - - await expect(command).rejects.toThrow("whoops"); - }); - - it("requires a git repo when using --since", async () => { - const testDir = await initFixture("basic"); - - await fs.remove(path.join(testDir, ".git")); - - const command = lernaClean(testDir)("--since", "some-branch"); - await expect(command).rejects.toThrow("this is not a git repository"); - }); - }); - - describe("--include-filtered-dependencies", () => { - it("should not remove node_modules from unaffiliated packages", async () => { - const testDir = await initFixture("include-filtered-dependencies"); - - await lernaClean(testDir)("--scope", "@test/package-2", "--include-filtered-dependencies"); - - expect(removedDirectories(testDir)).toEqual([ - "packages/package-2/node_modules", - "packages/package-1/node_modules", - ]); - }); - }); -}); diff --git a/commands/clean/command.js b/commands/clean/command.js deleted file mode 100644 index bf10cf2c2b..0000000000 --- a/commands/clean/command.js +++ /dev/null @@ -1,27 +0,0 @@ -"use strict"; - -const { filterOptions } = require("@lerna/filter-options"); - -/** - * @see https://github.com/yargs/yargs/blob/master/docs/advanced.md#providing-a-command-module - */ -exports.command = "clean"; - -exports.describe = "Remove the node_modules directory from all packages"; - -exports.builder = (yargs) => { - yargs.options({ - y: { - group: "Command Options:", - describe: "Skip all confirmation prompts", - alias: "yes", - type: "boolean", - }, - }); - - return filterOptions(yargs); -}; - -exports.handler = function handler(argv) { - return require(".")(argv); -}; diff --git a/commands/clean/index.js b/commands/clean/index.js deleted file mode 100644 index 7b8112a9a9..0000000000 --- a/commands/clean/index.js +++ /dev/null @@ -1,67 +0,0 @@ -"use strict"; - -const path = require("path"); -const pMap = require("p-map"); - -const { Command } = require("@lerna/command"); -const { rimrafDir } = require("@lerna/rimraf-dir"); -const { promptConfirmation } = require("@lerna/prompt"); -const { getFilteredPackages } = require("@lerna/filter-options"); -const { pulseTillDone } = require("@lerna/pulse-till-done"); - -module.exports = factory; - -function factory(argv) { - return new CleanCommand(argv); -} - -class CleanCommand extends Command { - get requiresGit() { - return false; - } - - initialize() { - let chain = Promise.resolve(); - - chain = chain.then(() => getFilteredPackages(this.packageGraph, this.execOpts, this.options)); - chain = chain.then((filteredPackages) => { - this.directoriesToDelete = filteredPackages.map((pkg) => pkg.nodeModulesLocation); - }); - - return chain.then(() => { - if (this.options.yes) { - return true; - } - - this.logger.info("", "Removing the following directories:"); - this.logger.info( - "clean", - this.directoriesToDelete.map((dir) => path.relative(this.project.rootPath, dir)).join("\n") - ); - - return promptConfirmation("Proceed?"); - }); - } - - execute() { - this.enableProgressBar(); - - const tracker = this.logger.newItem("clean"); - const mapper = (dirPath) => { - tracker.info("clean", "removing", dirPath); - - return pulseTillDone(rimrafDir(dirPath)).then(() => { - tracker.completeWork(1); - }); - }; - - tracker.addWork(this.directoriesToDelete.length); - - return pMap(this.directoriesToDelete, mapper, { concurrency: this.concurrency }).then(() => { - tracker.finish(); - this.logger.success("clean", "finished"); - }); - } -} - -module.exports.CleanCommand = CleanCommand; diff --git a/commands/clean/package.json b/commands/clean/package.json deleted file mode 100644 index afd772a625..0000000000 --- a/commands/clean/package.json +++ /dev/null @@ -1,44 +0,0 @@ -{ - "name": "@lerna/clean", - "version": "6.4.1", - "description": "Remove the node_modules directory from all packages", - "keywords": [ - "lerna", - "command" - ], - "homepage": "https://lerna.js.org", - "license": "MIT", - "author": { - "name": "Daniel Stockman", - "url": "https://github.com/evocateur" - }, - "files": [ - "command.js", - "index.js" - ], - "main": "index.js", - "engines": { - "node": "^14.15.0 || >=16.0.0" - }, - "publishConfig": { - "access": "public" - }, - "repository": { - "type": "git", - "url": "git+https://github.com/lerna/lerna.git", - "directory": "commands/clean" - }, - "scripts": { - "test": "echo \"Run tests from root\" && exit 1" - }, - "dependencies": { - "@lerna/command": "file:../../core/command", - "@lerna/filter-options": "file:../../core/filter-options", - "@lerna/prompt": "file:../../core/prompt", - "@lerna/pulse-till-done": "file:../../utils/pulse-till-done", - "@lerna/rimraf-dir": "file:../../utils/rimraf-dir", - "p-map": "^4.0.0", - "p-map-series": "^2.1.0", - "p-waterfall": "^2.1.1" - } -} diff --git a/commands/create/CHANGELOG.md b/commands/create/CHANGELOG.md deleted file mode 100644 index ad6a0e3d8d..0000000000 --- a/commands/create/CHANGELOG.md +++ /dev/null @@ -1,512 +0,0 @@ -# Change Log - -All notable changes to this project will be documented in this file. -See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. - -## [6.4.1](https://github.com/lerna/lerna/compare/v6.4.0...v6.4.1) (2023-01-12) - -**Note:** Version bump only for package @lerna/create - -# [6.4.0](https://github.com/lerna/lerna/compare/v6.3.0...v6.4.0) (2023-01-05) - -### Features - -- **create:** support relative path from root as lerna create location ([#3478](https://github.com/lerna/lerna/issues/3478)) ([82825ce](https://github.com/lerna/lerna/commit/82825ce98b43720cb7034e98f2b388ab14882bbf)) - -# [6.3.0](https://github.com/lerna/lerna/compare/v6.2.0...v6.3.0) (2022-12-26) - -**Note:** Version bump only for package @lerna/create - -# [6.2.0](https://github.com/lerna/lerna/compare/v6.1.0...v6.2.0) (2022-12-13) - -**Note:** Version bump only for package @lerna/create - -# [6.1.0](https://github.com/lerna/lerna/compare/v6.0.3...v6.1.0) (2022-11-29) - -**Note:** Version bump only for package @lerna/create - -## [6.0.3](https://github.com/lerna/lerna/compare/v6.0.2...v6.0.3) (2022-11-07) - -**Note:** Version bump only for package @lerna/create - -## [6.0.2](https://github.com/lerna/lerna/compare/v6.0.1...v6.0.2) (2022-11-02) - -**Note:** Version bump only for package @lerna/create - -## [6.0.1](https://github.com/lerna/lerna/compare/v6.0.0...v6.0.1) (2022-10-14) - -**Note:** Version bump only for package @lerna/create - -# [6.0.0](https://github.com/lerna/lerna/compare/v6.0.0-alpha.2...v6.0.0) (2022-10-12) - -**Note:** Version bump only for package @lerna/create - -# [6.0.0-alpha.2](https://github.com/lerna/lerna/compare/v6.0.0-alpha.1...v6.0.0-alpha.2) (2022-10-12) - -**Note:** Version bump only for package @lerna/create - -# [6.0.0-alpha.1](https://github.com/lerna/lerna/compare/v5.6.2...v6.0.0-alpha.1) (2022-10-09) - -# [6.0.0-alpha.0](https://github.com/lerna/lerna/compare/v5.6.1...v6.0.0-alpha.0) (2022-10-07) - -**Note:** Version bump only for package @lerna/create - -## [5.6.2](https://github.com/lerna/lerna/compare/v5.6.1...v5.6.2) (2022-10-09) - -### Bug Fixes - -- **create:** remove unused globby dep ([#3360](https://github.com/lerna/lerna/issues/3360)) ([e873f0c](https://github.com/lerna/lerna/commit/e873f0c0b35275cd2568f43a945a84fbae364c2e)) - -## [5.6.1](https://github.com/lerna/lerna/compare/v5.6.0...v5.6.1) (2022-09-30) - -**Note:** Version bump only for package @lerna/create - -# [5.6.0](https://github.com/lerna/lerna/compare/v5.5.4...v5.6.0) (2022-09-29) - -**Note:** Version bump only for package @lerna/create - -## [5.5.4](https://github.com/lerna/lerna/compare/v5.5.3...v5.5.4) (2022-09-28) - -**Note:** Version bump only for package @lerna/create - -## [5.5.3](https://github.com/lerna/lerna/compare/v5.5.2...v5.5.3) (2022-09-28) - -**Note:** Version bump only for package @lerna/create - -## [5.5.2](https://github.com/lerna/lerna/compare/v5.5.1...v5.5.2) (2022-09-20) - -**Note:** Version bump only for package @lerna/create - -## [5.5.1](https://github.com/lerna/lerna/compare/v5.5.0...v5.5.1) (2022-09-09) - -**Note:** Version bump only for package @lerna/create - -# [5.5.0](https://github.com/lerna/lerna/compare/v5.4.3...v5.5.0) (2022-08-31) - -**Note:** Version bump only for package @lerna/create - -## [5.4.3](https://github.com/lerna/lerna/compare/v5.4.2...v5.4.3) (2022-08-16) - -**Note:** Version bump only for package @lerna/create - -## [5.4.2](https://github.com/lerna/lerna/compare/v5.4.1...v5.4.2) (2022-08-14) - -**Note:** Version bump only for package @lerna/create - -## [5.4.1](https://github.com/lerna/lerna/compare/v5.4.0...v5.4.1) (2022-08-12) - -**Note:** Version bump only for package @lerna/create - -# [5.4.0](https://github.com/lerna/lerna/compare/v5.3.0...v5.4.0) (2022-08-08) - -### Bug Fixes - -- **create:** default test script no longer errors ([#3266](https://github.com/lerna/lerna/issues/3266)) ([dfd30fa](https://github.com/lerna/lerna/commit/dfd30fa1b141512c66998ce95777246c38eb1019)) - -# [5.3.0](https://github.com/lerna/lerna/compare/v5.2.0...v5.3.0) (2022-07-27) - -**Note:** Version bump only for package @lerna/create - -# [5.2.0](https://github.com/lerna/lerna/compare/v5.1.8...v5.2.0) (2022-07-22) - -**Note:** Version bump only for package @lerna/create - -## [5.1.8](https://github.com/lerna/lerna/compare/v5.1.7...v5.1.8) (2022-07-07) - -**Note:** Version bump only for package @lerna/create - -## [5.1.7](https://github.com/lerna/lerna/compare/v5.1.6...v5.1.7) (2022-07-06) - -**Note:** Version bump only for package @lerna/create - -## [5.1.6](https://github.com/lerna/lerna/compare/v5.1.5...v5.1.6) (2022-06-24) - -**Note:** Version bump only for package @lerna/create - -## [5.1.5](https://github.com/lerna/lerna/compare/v5.1.4...v5.1.5) (2022-06-24) - -**Note:** Version bump only for package @lerna/create - -## [5.1.4](https://github.com/lerna/lerna/compare/v5.1.3...v5.1.4) (2022-06-15) - -**Note:** Version bump only for package @lerna/create - -## [5.1.3](https://github.com/lerna/lerna/compare/v5.1.2...v5.1.3) (2022-06-15) - -**Note:** Version bump only for package @lerna/create - -## [5.1.2](https://github.com/lerna/lerna/compare/v5.1.1...v5.1.2) (2022-06-13) - -**Note:** Version bump only for package @lerna/create - -## [5.1.1](https://github.com/lerna/lerna/compare/v5.1.0...v5.1.1) (2022-06-09) - -### Bug Fixes - -- allow maintenance LTS node 14 engines starting at 14.15.0 ([#3161](https://github.com/lerna/lerna/issues/3161)) ([72305e4](https://github.com/lerna/lerna/commit/72305e4dbab607a2d87ae4efa6ee577c93a9dda9)) - -# [5.1.0](https://github.com/lerna/lerna/compare/v5.0.0...v5.1.0) (2022-06-07) - -**Note:** Version bump only for package @lerna/create - -# [5.1.0-alpha.0](https://github.com/lerna/lerna/compare/v4.0.0...v5.1.0-alpha.0) (2022-05-25) - -**Note:** Version bump only for package @lerna/create - -# [5.0.0](https://github.com/lerna/lerna/compare/v4.0.0...v5.0.0) (2022-05-24) - -**Note:** Version bump only for package @lerna/create - -# [4.0.0](https://github.com/lerna/lerna/compare/v3.22.1...v4.0.0) (2021-02-10) - -### Bug Fixes - -- **create:** Use main as default Github branch ([1a951e9](https://github.com/lerna/lerna/commit/1a951e92376b2aff2e1866791a0ae0b03f19515d)) - -### Features - -- **deps:** Bump dependencies ([affed1c](https://github.com/lerna/lerna/commit/affed1ce0fce91f01b0a9eafe357db2d985b974f)) -- Consume named exports of sibling modules ([63499e3](https://github.com/lerna/lerna/commit/63499e33652bc78fe23751875d74017e2f16a689)) -- **deps:** @evocateur/pacote -> pacote@^11.1.13 ([99b4217](https://github.com/lerna/lerna/commit/99b4217ed143527a45969f3a46f1bd9b84999d68)) -- **deps:** camelcase -> yargs-parser/camelCase ([d966e8b](https://github.com/lerna/lerna/commit/d966e8b3d36ad9eb02f656b73d9b41882ca7b208)) -- **deps:** execa@^4.1.0 ([9051dca](https://github.com/lerna/lerna/commit/9051dcab1a68b56db09b82ab0345c5f36bcfee2d)) -- **deps:** fs-extra@^9.0.1 ([2f6f4e0](https://github.com/lerna/lerna/commit/2f6f4e066d5a41b4cd508b3405ac1d0a342932dc)) -- **deps:** globby@^11.0.1 ([6cb5bbe](https://github.com/lerna/lerna/commit/6cb5bbec5599cdd93d314ffdc4abea8822e48075)) -- **deps:** init-package-json@^2.0.1 ([4042e8e](https://github.com/lerna/lerna/commit/4042e8e0a73427d1f9585ff285554e2a954b7be6)) -- **deps:** npm-package-arg@^8.1.0 ([12c8923](https://github.com/lerna/lerna/commit/12c892342d33b86a00ee2cf9079f9b26fe316dc6)) -- **deps:** p-reduce@^2.1.0 ([fd4289a](https://github.com/lerna/lerna/commit/fd4289ad20fd9ce5921b83d97f82984abf4f65b0)) -- **deps:** pify@^5.0.0 ([6b34452](https://github.com/lerna/lerna/commit/6b3445219f0f022411a7cb282b0ba39a072e2ef2)) -- **deps:** semver@^7.3.2 ([003ad66](https://github.com/lerna/lerna/commit/003ad6641fab8b4e3a82251ebffd27061bd6a31b)) -- **deps:** slash@^3.0.0 ([5dec383](https://github.com/lerna/lerna/commit/5dec383109bcd1cce9abbc80796369db9314acc9)) -- **deps:** whatwg-url@^8.4.0 ([5dfb7f0](https://github.com/lerna/lerna/commit/5dfb7f0ee196a0c9b9010339d512a5b5b9b75a47)) -- Drop support for Node v6.x & v8.x ([ff4bb4d](https://github.com/lerna/lerna/commit/ff4bb4da215555e3bb136f5af09b5cbc631e57bb)) - -### BREAKING CHANGES - -- Node v6.x & v8.x are no longer supported. Please upgrade to the latest LTS release. - -Here's the gnarly one-liner I used to make these changes: - -``` -npx lerna exec --concurrency 1 --stream -- 'json -I -f package.json -e '"'"'this.engines=this.engines||{};this.engines.node=">= 10.18.0"'"'" -``` - -(requires `npm i -g json` beforehand) - -# [3.22.0](https://github.com/lerna/lerna/compare/v3.21.0...v3.22.0) (2020-05-24) - -### Bug Fixes - -- **create:** Use correct variable name in generated CLI output ([#2547](https://github.com/lerna/lerna/issues/2547)) ([a1fd622](https://github.com/lerna/lerna/commit/a1fd622a55e3dbbf47a6a166c01fe17636cd0a76)) - -# [3.21.0](https://github.com/lerna/lerna/compare/v3.20.2...v3.21.0) (2020-05-13) - -**Note:** Version bump only for package @lerna/create - -## [3.18.5](https://github.com/lerna/lerna/compare/v3.18.4...v3.18.5) (2019-11-20) - -**Note:** Version bump only for package @lerna/create - -# [3.18.0](https://github.com/lerna/lerna/compare/v3.17.0...v3.18.0) (2019-10-15) - -**Note:** Version bump only for package @lerna/create - -## [3.16.5](https://github.com/lerna/lerna/compare/v3.16.4...v3.16.5) (2019-10-07) - -**Note:** Version bump only for package @lerna/create - -# [3.16.0](https://github.com/lerna/lerna/compare/v3.15.0...v3.16.0) (2019-07-18) - -### Bug Fixes - -- **deps:** Bump `@evocateur/pacote` ([03e4797](https://github.com/lerna/lerna/commit/03e4797)) -- **deps:** Update forked npm libs ([4d67426](https://github.com/lerna/lerna/commit/4d67426)) - -### Features - -- **deps:** `fs-extra@^8.1.0` ([313287f](https://github.com/lerna/lerna/commit/313287f)) -- **deps:** `globby@^9.2.0` ([d9aa249](https://github.com/lerna/lerna/commit/d9aa249)) -- **deps:** `pify@^4.0.1` ([f8ee7e6](https://github.com/lerna/lerna/commit/f8ee7e6)) -- **deps:** `semver@^6.2.0` ([d8016d9](https://github.com/lerna/lerna/commit/d8016d9)) -- **deps:** `slash@^2.0.0` ([bedd6af](https://github.com/lerna/lerna/commit/bedd6af)) - -# [3.15.0](https://github.com/lerna/lerna/compare/v3.14.2...v3.15.0) (2019-06-09) - -### Bug Fixes - -- **deps:** Consume forked npm libs ([bdd4fa1](https://github.com/lerna/lerna/commit/bdd4fa1)) - -## [3.14.2](https://github.com/lerna/lerna/compare/v3.14.1...v3.14.2) (2019-06-09) - -**Note:** Version bump only for package @lerna/create - -# [3.14.0](https://github.com/lerna/lerna/compare/v3.13.4...v3.14.0) (2019-05-14) - -**Note:** Version bump only for package @lerna/create - -## [3.13.3](https://github.com/lerna/lerna/compare/v3.13.2...v3.13.3) (2019-04-17) - -**Note:** Version bump only for package @lerna/create - -## [3.13.1](https://github.com/lerna/lerna/compare/v3.13.0...v3.13.1) (2019-02-26) - -### Bug Fixes - -- **deps:** pacote ^9.5.0 ([cdc2e17](https://github.com/lerna/lerna/commit/cdc2e17)) - -# [3.13.0](https://github.com/lerna/lerna/compare/v3.12.1...v3.13.0) (2019-02-15) - -### Features - -- **meta:** Add `repository.directory` field to package.json ([aec5023](https://github.com/lerna/lerna/commit/aec5023)) -- **meta:** Normalize package.json `homepage` field ([abeb4dc](https://github.com/lerna/lerna/commit/abeb4dc)) - -# [3.12.0](https://github.com/lerna/lerna/compare/v3.11.1...v3.12.0) (2019-02-14) - -**Note:** Version bump only for package @lerna/create - -# [3.11.0](https://github.com/lerna/lerna/compare/v3.10.8...v3.11.0) (2019-02-08) - -### Bug Fixes - -- **create:** Bump camelcase ([e58a1d0](https://github.com/lerna/lerna/commit/e58a1d0)) -- **deps:** Explicit npm-package-arg ^6.1.0 ([4b20791](https://github.com/lerna/lerna/commit/4b20791)) -- **deps:** Explicit pacote ^9.4.1 ([44d05bf](https://github.com/lerna/lerna/commit/44d05bf)) -- **deps:** Remove unused libnpm (replaced by direct sub-packages) ([1caeb28](https://github.com/lerna/lerna/commit/1caeb28)) - -## [3.10.6](https://github.com/lerna/lerna/compare/v3.10.5...v3.10.6) (2019-01-19) - -**Note:** Version bump only for package @lerna/create - -# [3.10.0](https://github.com/lerna/lerna/compare/v3.9.1...v3.10.0) (2019-01-08) - -**Note:** Version bump only for package @lerna/create - -## [3.8.5](https://github.com/lerna/lerna/compare/v3.8.4...v3.8.5) (2019-01-05) - -**Note:** Version bump only for package @lerna/create - -## [3.8.1](https://github.com/lerna/lerna/compare/v3.8.0...v3.8.1) (2018-12-31) - -**Note:** Version bump only for package @lerna/create - -## [3.7.2](https://github.com/lerna/lerna/compare/v3.7.1...v3.7.2) (2018-12-21) - -**Note:** Version bump only for package @lerna/create - -## [3.7.1](https://github.com/lerna/lerna/compare/v3.7.0...v3.7.1) (2018-12-20) - -**Note:** Version bump only for package @lerna/create - -# [3.7.0](https://github.com/lerna/lerna/compare/v3.6.0...v3.7.0) (2018-12-19) - -### Bug Fixes - -- **create:** Pass options snapshot to pacote.manifest() ([6116680](https://github.com/lerna/lerna/commit/6116680)) - -# [3.6.0](https://github.com/lerna/lerna/compare/v3.5.1...v3.6.0) (2018-12-07) - -### Features - -- Migrate existing usage to libnpm ([0d3a786](https://github.com/lerna/lerna/commit/0d3a786)), closes [#1767](https://github.com/lerna/lerna/issues/1767) -- **create:** Migrate `npm info` subprocess to libnpm.manifest ([65a1d1b](https://github.com/lerna/lerna/commit/65a1d1b)) - -# [3.5.0](https://github.com/lerna/lerna/compare/v3.4.3...v3.5.0) (2018-11-27) - -### Bug Fixes - -- prettier ([001a6df](https://github.com/lerna/lerna/commit/001a6df)) - -## [3.4.1](https://github.com/lerna/lerna/compare/v3.4.0...v3.4.1) (2018-10-04) - -**Note:** Version bump only for package @lerna/create - - - -## [3.3.1](https://github.com/lerna/lerna/compare/v3.3.0...v3.3.1) (2018-09-11) - -### Bug Fixes - -- **create:** Upgrade whatwg-url to ^7.0.0 ([00842d6](https://github.com/lerna/lerna/commit/00842d6)) - - - -# [3.3.0](https://github.com/lerna/lerna/compare/v3.2.1...v3.3.0) (2018-09-06) - -### Features - -- **deps:** Upgrade fs-extra to ^7.0.0 ([042b1a3](https://github.com/lerna/lerna/commit/042b1a3)) - - - -## [3.1.3](https://github.com/lerna/lerna/compare/v3.1.2...v3.1.3) (2018-08-21) - -**Note:** Version bump only for package @lerna/create - - - -## [3.1.2](https://github.com/lerna/lerna/compare/v3.1.1...v3.1.2) (2018-08-20) - -**Note:** Version bump only for package @lerna/create - - - -# [3.1.0](https://github.com/lerna/lerna/compare/v3.0.6...v3.1.0) (2018-08-17) - -**Note:** Version bump only for package @lerna/create - - - -## [3.0.6](https://github.com/lerna/lerna/compare/v3.0.5...v3.0.6) (2018-08-16) - -### Bug Fixes - -- **create:** Use whatwg-url instead of node 8.x-dependent URL class ([8701b79](https://github.com/lerna/lerna/commit/8701b79)) - - - -## [3.0.5](https://github.com/lerna/lerna/compare/v3.0.4...v3.0.5) (2018-08-15) - -### Bug Fixes - -- **options:** Provide -y alias for --yes ([3ea460c](https://github.com/lerna/lerna/commit/3ea460c)) - - - -# [3.0.0](https://github.com/lerna/lerna/compare/v3.0.0-rc.0...v3.0.0) (2018-08-10) - -### Bug Fixes - -- **create:** Use filename without scope when generating imports from test file ([acfd48b](https://github.com/lerna/lerna/commit/acfd48b)) - - - -# [3.0.0-rc.0](https://github.com/lerna/lerna/compare/v3.0.0-beta.21...v3.0.0-rc.0) (2018-07-27) - -### Features - -- Upgrade to fs-extra 6 ([079d873](https://github.com/lerna/lerna/commit/079d873)) -- **cli:** Upgrade to Yargs 12 ([7899ab8](https://github.com/lerna/lerna/commit/7899ab8)) - - - -# [3.0.0-beta.21](https://github.com/lerna/lerna/compare/v3.0.0-beta.20...v3.0.0-beta.21) (2018-05-12) - -**Note:** Version bump only for package @lerna/create - - - -# [3.0.0-beta.20](https://github.com/lerna/lerna/compare/v3.0.0-beta.19...v3.0.0-beta.20) (2018-05-07) - -**Note:** Version bump only for package @lerna/create - - - -# [3.0.0-beta.19](https://github.com/lerna/lerna/compare/v3.0.0-beta.18...v3.0.0-beta.19) (2018-05-03) - -**Note:** Version bump only for package @lerna/create - - - -# [3.0.0-beta.18](https://github.com/lerna/lerna/compare/v3.0.0-beta.17...v3.0.0-beta.18) (2018-04-24) - -**Note:** Version bump only for package @lerna/create - - - -# [3.0.0-beta.17](https://github.com/lerna/lerna/compare/v3.0.0-beta.16...v3.0.0-beta.17) (2018-04-13) - -**Note:** Version bump only for package @lerna/create - - - -# [3.0.0-beta.15](https://github.com/lerna/lerna/compare/v3.0.0-beta.14...v3.0.0-beta.15) (2018-04-09) - -**Note:** Version bump only for package @lerna/create - - - -# [3.0.0-beta.14](https://github.com/lerna/lerna/compare/v3.0.0-beta.13...v3.0.0-beta.14) (2018-04-03) - -### Bug Fixes - -- **create:** Actually publish the module data helper ([4775cc4](https://github.com/lerna/lerna/commit/4775cc4)) - - - -# [3.0.0-beta.13](https://github.com/lerna/lerna/compare/v3.0.0-beta.12...v3.0.0-beta.13) (2018-03-31) - -### Features - -- Enable progress bars only when necessary ([b766c83](https://github.com/lerna/lerna/commit/b766c83)) - - - -# [3.0.0-beta.12](https://github.com/lerna/lerna/compare/v3.0.0-beta.11...v3.0.0-beta.12) (2018-03-30) - -### Bug Fixes - -- **create:** Silently ignore missing builtin npmrc ([1523520](https://github.com/lerna/lerna/commit/1523520)), closes [#1353](https://github.com/lerna/lerna/issues/1353) - -### Features - -- **package:** Add Map-like get/set methods, remove raw json getter ([707d1f0](https://github.com/lerna/lerna/commit/707d1f0)) -- **project:** Merge `package` and `packageJson` into `manifest` ([9a47ff7](https://github.com/lerna/lerna/commit/9a47ff7)) - -### BREAKING CHANGES - -- **package:** The `Package` class no longer provides direct access to the JSON object - used to construct the instance. Map-like `get()`/`set(val)` methods are - available to modify the internal representation. - - - -# [3.0.0-beta.11](https://github.com/lerna/lerna/compare/v3.0.0-beta.10...v3.0.0-beta.11) (2018-03-29) - -**Note:** Version bump only for package @lerna/create - - - -# [3.0.0-beta.10](https://github.com/lerna/lerna/compare/v3.0.0-beta.9...v3.0.0-beta.10) (2018-03-27) - -### Features - -- **commands:** Delay require of command instantiation ([a1284f3](https://github.com/lerna/lerna/commit/a1284f3)) - -### BREAKING CHANGES - -- **commands:** The default export of command packages is now a factory, not the subclass (which is now a named export). - - - -# [3.0.0-beta.9](https://github.com/lerna/lerna/compare/v3.0.0-beta.8...v3.0.0-beta.9) (2018-03-24) - -### Features - -- **command:** Rename this.repository -> this.project ([43e98a0](https://github.com/lerna/lerna/commit/43e98a0)) - - - -# [3.0.0-beta.8](https://github.com/lerna/lerna/compare/v3.0.0-beta.7...v3.0.0-beta.8) (2018-03-22) - -### Bug Fixes - -- **create:** Skip repository property when git remote is missing ([98c8be6](https://github.com/lerna/lerna/commit/98c8be6)) - -### Features - -- **utils:** Add "vendored" npm-conf ([9c24a25](https://github.com/lerna/lerna/commit/9c24a25)) - - - -# [3.0.0-beta.7](https://github.com/lerna/lerna/compare/v3.0.0-beta.6...v3.0.0-beta.7) (2018-03-20) - -**Note:** Version bump only for package @lerna/create - - - -# [3.0.0-beta.4](https://github.com/lerna/lerna/compare/v3.0.0-beta.3...v3.0.0-beta.4) (2018-03-19) - -### Features - -- Add `lerna create` command ([#1326](https://github.com/lerna/lerna/issues/1326)) ([f15b224](https://github.com/lerna/lerna/commit/f15b224)) diff --git a/commands/create/README.md b/commands/create/README.md deleted file mode 100644 index 0c5b7c2248..0000000000 --- a/commands/create/README.md +++ /dev/null @@ -1,41 +0,0 @@ -# `@lerna/create` - -> Create a new lerna-managed package - -Install [lerna](https://www.npmjs.com/package/lerna) for access to the `lerna` CLI. - -## Usage - -``` -lerna create [loc] - -Create a new lerna-managed package - -Positionals: - name The package name (including scope), which must be locally unique _and_ - publicly available [string] [required] - loc A custom package location, defaulting to the first configured package - location. The location must match a configured packages directory. - [string] -``` - -**Note**: For more info on how Lerna package directories are configured, see https://lerna.js.org/docs/faq#how-does-lerna-detect-packages. - -``` -Command Options: - --access When using a scope, set publishConfig.access value - [choices: "public", "restricted"] [default: public] - --bin Package has an executable. Customize with --bin - [default: ] - --description Package description [string] - --dependencies A list of package dependencies [array] - --es-module Initialize a transpiled ES Module - --homepage The package homepage, defaulting to a subpath of the root - pkg.homepage [string] - --keywords A list of package keywords [array] - --license The desired package license (SPDX identifier) [default: ISC] - --private Make the new package private, never published - --registry Configure the package's publishConfig.registry [string] - --tag Configure the package's publishConfig.tag [string] - --yes Skip all prompts, accepting default values -``` diff --git a/commands/create/__tests__/__snapshots__/create-command.test.js.snap b/commands/create/__tests__/__snapshots__/create-command.test.js.snap deleted file mode 100644 index 5cd0776b21..0000000000 --- a/commands/create/__tests__/__snapshots__/create-command.test.js.snap +++ /dev/null @@ -1,439 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`CreateCommand creates a stub cli 1`] = ` -diff --git a/packages/my-cli/README.md b/packages/my-cli/README.md -new file mode 100644 -index SHA..SHA ---- /dev/null -+++ b/packages/my-cli/README.md -@@ -0,0 +1,13 @@ -+# \`my-cli\` -+ -+> TODO: description -+ -+## Usage -+ -+\`\`\` -+npm -g i my-cli -+ -+my-cli --help -+ -+// TODO: DEMONSTRATE API -+\`\`\` -diff --git a/packages/my-cli/__tests__/cli.test.js b/packages/my-cli/__tests__/cli.test.js -new file mode 100644 -index SHA..SHA ---- /dev/null -+++ b/packages/my-cli/__tests__/cli.test.js -@@ -0,0 +1,8 @@ -+'use strict'; -+ -+const cli = require('../lib/cli'); -+ -+describe('my-cli cli', () => { -+ // const argv = cli(cwd).parse(['args']); -+ it('needs tests'); -+}); -diff --git a/packages/my-cli/__tests__/my-cli.test.js b/packages/my-cli/__tests__/my-cli.test.js -new file mode 100644 -index SHA..SHA ---- /dev/null -+++ b/packages/my-cli/__tests__/my-cli.test.js -@@ -0,0 +1,7 @@ -+'use strict'; -+ -+const myCli = require('..'); -+const assert = require('assert').strict; -+ -+assert.strictEqual(myCli(), 'Hello from myCli'); -+console.info("myCli tests passed"); -diff --git a/packages/my-cli/bin/my-cli b/packages/my-cli/bin/my-cli -new file mode 100755 -index SHA..SHA ---- /dev/null -+++ b/packages/my-cli/bin/my-cli -@@ -0,0 +1,6 @@ -+#!/usr/bin/env node -+ -+'use strict'; -+ -+// eslint-disable-next-line no-unused-expressions -+require('../lib/cli')().parse(process.argv.slice(2)); -diff --git a/packages/my-cli/lib/cli.js b/packages/my-cli/lib/cli.js -new file mode 100644 -index SHA..SHA ---- /dev/null -+++ b/packages/my-cli/lib/cli.js -@@ -0,0 +1,26 @@ -+'use strict'; -+ -+const factory = require('yargs/yargs'); -+const myCli = require('./my-cli'); -+ -+module.exports = cli; -+ -+function cli(cwd) { -+ const parser = factory(null, cwd); -+ -+ parser.alias('h', 'help'); -+ parser.alias('v', 'version'); -+ -+ parser.usage( -+ "$0", -+ "TODO: description", -+ yargs => { -+ yargs.options({ -+ // TODO: options -+ }); -+ }, -+ argv => myCli(argv) -+ ); -+ -+ return parser; -+} -diff --git a/packages/my-cli/lib/my-cli.js b/packages/my-cli/lib/my-cli.js -new file mode 100644 -index SHA..SHA ---- /dev/null -+++ b/packages/my-cli/lib/my-cli.js -@@ -0,0 +1,7 @@ -+'use strict'; -+ -+module.exports = myCli; -+ -+function myCli() { -+ return "Hello from myCli"; -+} -diff --git a/packages/my-cli/package.json b/packages/my-cli/package.json -new file mode 100644 -index SHA..SHA ---- /dev/null -+++ b/packages/my-cli/package.json -@@ -0,0 +1,34 @@ -+{ -+ "name": "my-cli", -+ "version": "1.2.3", -+ "description": "Now I’m the model of a modern major general / The venerated Virginian veteran whose men are all / Lining up, to put me up on a pedestal / Writin’ letters to relatives / Embellishin’ my elegance and eloquence / But the elephant is in the room / The truth is in ya face when ya hear the British cannons go / BOOM", -+ "keywords": [], -+ "author": "Tester McPerson (http://example.com)", -+ "license": "ISC", -+ "main": "lib/my-cli.js", -+ "bin": { -+ "my-cli": "bin/my-cli" -+ }, -+ "directories": { -+ "lib": "lib", -+ "test": "__tests__" -+ }, -+ "files": [ -+ "bin", -+ "lib" -+ ], -+ "repository": { -+ "type": "git", -+ "url": "git+https://github.com/test/test.git" -+ }, -+ "scripts": { -+ "test": "node ./__tests__/my-cli.test.js" -+ }, -+ "dependencies": { -+ "yargs": "^1.0.0-mocked" -+ }, -+ "bugs": { -+ "url": "https://github.com/test/test/issues" -+ }, -+ "homepage": "https://github.com/test/test#readme" -+} -`; - -exports[`CreateCommand creates a stub cli with transpiled output 1`] = ` -diff --git a/packages/my-es-cli/README.md b/packages/my-es-cli/README.md -new file mode 100644 -index SHA..SHA ---- /dev/null -+++ b/packages/my-es-cli/README.md -@@ -0,0 +1,13 @@ -+# \`my-es-cli\` -+ -+> TODO: description -+ -+## Usage -+ -+\`\`\` -+npm -g i my-es-cli -+ -+my-es-cli --help -+ -+// TODO: DEMONSTRATE API -+\`\`\` -diff --git a/packages/my-es-cli/__tests__/cli.test.js b/packages/my-es-cli/__tests__/cli.test.js -new file mode 100644 -index SHA..SHA ---- /dev/null -+++ b/packages/my-es-cli/__tests__/cli.test.js -@@ -0,0 +1,6 @@ -+import cli from '../src/cli'; -+ -+describe('my-es-cli cli', () => { -+ // const argv = cli(cwd).parse(['args']); -+ it('needs tests'); -+}); -diff --git a/packages/my-es-cli/__tests__/my-es-cli.test.js b/packages/my-es-cli/__tests__/my-es-cli.test.js -new file mode 100644 -index SHA..SHA ---- /dev/null -+++ b/packages/my-es-cli/__tests__/my-es-cli.test.js -@@ -0,0 +1,5 @@ -+import myEsCli from '../src/my-es-cli.js'; -+import { strict as assert } from 'assert'; -+ -+assert.strictEqual(myEsCli(), 'Hello from myEsCli'); -+console.info("myEsCli tests passed"); -diff --git a/packages/my-es-cli/bin/my-es-cli b/packages/my-es-cli/bin/my-es-cli -new file mode 100755 -index SHA..SHA ---- /dev/null -+++ b/packages/my-es-cli/bin/my-es-cli -@@ -0,0 +1,6 @@ -+#!/usr/bin/env node -+ -+'use strict'; -+ -+// eslint-disable-next-line no-unused-expressions -+require('../dist/cli').default().parse(process.argv.slice(2)); -diff --git a/packages/my-es-cli/package.json b/packages/my-es-cli/package.json -new file mode 100644 -index SHA..SHA ---- /dev/null -+++ b/packages/my-es-cli/package.json -@@ -0,0 +1,36 @@ -+{ -+ "name": "my-es-cli", -+ "version": "1.2.3", -+ "description": "Now I’m the model of a modern major general / The venerated Virginian veteran whose men are all / Lining up, to put me up on a pedestal / Writin’ letters to relatives / Embellishin’ my elegance and eloquence / But the elephant is in the room / The truth is in ya face when ya hear the British cannons go / BOOM", -+ "keywords": [], -+ "author": "Tester McPerson (http://example.com)", -+ "license": "ISC", -+ "main": "dist/my-es-cli.js", -+ "module": "dist/my-es-cli.module.js", -+ "bin": { -+ "my-es-cli": "bin/my-es-cli" -+ }, -+ "directories": { -+ "lib": "dist", -+ "test": "__tests__" -+ }, -+ "files": [ -+ "bin", -+ "dist" -+ ], -+ "repository": { -+ "type": "git", -+ "url": "git+https://github.com/test/test.git" -+ }, -+ "scripts": { -+ "test": "node ./__tests__/my-es-cli.test.js" -+ }, -+ "dependencies": { -+ "yargs": "^1.0.0-mocked" -+ }, -+ "type": "module", -+ "bugs": { -+ "url": "https://github.com/test/test/issues" -+ }, -+ "homepage": "https://github.com/test/test#readme" -+} -diff --git a/packages/my-es-cli/src/cli.js b/packages/my-es-cli/src/cli.js -new file mode 100644 -index SHA..SHA ---- /dev/null -+++ b/packages/my-es-cli/src/cli.js -@@ -0,0 +1,24 @@ -+import factory from 'yargs/yargs'; -+import myEsCli from './my-es-cli'; -+ -+export default cli; -+ -+function cli(cwd) { -+ const parser = factory(null, cwd); -+ -+ parser.alias('h', 'help'); -+ parser.alias('v', 'version'); -+ -+ parser.usage( -+ "$0", -+ "TODO: description", -+ yargs => { -+ yargs.options({ -+ // TODO: options -+ }); -+ }, -+ argv => myEsCli(argv) -+ ); -+ -+ return parser; -+} -diff --git a/packages/my-es-cli/src/my-es-cli.js b/packages/my-es-cli/src/my-es-cli.js -new file mode 100644 -index SHA..SHA ---- /dev/null -+++ b/packages/my-es-cli/src/my-es-cli.js -@@ -0,0 +1,3 @@ -+export default function myEsCli() { -+ return "Hello from myEsCli"; -+} -`; - -exports[`CreateCommand creates a stub package 1`] = ` -diff --git a/packages/my-pkg/README.md b/packages/my-pkg/README.md -new file mode 100644 -index SHA..SHA ---- /dev/null -+++ b/packages/my-pkg/README.md -@@ -0,0 +1,11 @@ -+# \`my-pkg\` -+ -+> TODO: description -+ -+## Usage -+ -+\`\`\` -+const myPkg = require('my-pkg'); -+ -+// TODO: DEMONSTRATE API -+\`\`\` -diff --git a/packages/my-pkg/__tests__/my-pkg.test.js b/packages/my-pkg/__tests__/my-pkg.test.js -new file mode 100644 -index SHA..SHA ---- /dev/null -+++ b/packages/my-pkg/__tests__/my-pkg.test.js -@@ -0,0 +1,7 @@ -+'use strict'; -+ -+const myPkg = require('..'); -+const assert = require('assert').strict; -+ -+assert.strictEqual(myPkg(), 'Hello from myPkg'); -+console.info("myPkg tests passed"); -diff --git a/packages/my-pkg/lib/my-pkg.js b/packages/my-pkg/lib/my-pkg.js -new file mode 100644 -index SHA..SHA ---- /dev/null -+++ b/packages/my-pkg/lib/my-pkg.js -@@ -0,0 +1,7 @@ -+'use strict'; -+ -+module.exports = myPkg; -+ -+function myPkg() { -+ return "Hello from myPkg"; -+} -diff --git a/packages/my-pkg/package.json b/packages/my-pkg/package.json -new file mode 100644 -index SHA..SHA ---- /dev/null -+++ b/packages/my-pkg/package.json -@@ -0,0 +1,27 @@ -+{ -+ "name": "my-pkg", -+ "version": "1.2.3", -+ "description": "Now I’m the model of a modern major general / The venerated Virginian veteran whose men are all / Lining up, to put me up on a pedestal / Writin’ letters to relatives / Embellishin’ my elegance and eloquence / But the elephant is in the room / The truth is in ya face when ya hear the British cannons go / BOOM", -+ "keywords": [], -+ "author": "Tester McPerson (http://example.com)", -+ "license": "ISC", -+ "main": "lib/my-pkg.js", -+ "directories": { -+ "lib": "lib", -+ "test": "__tests__" -+ }, -+ "files": [ -+ "lib" -+ ], -+ "repository": { -+ "type": "git", -+ "url": "git+https://github.com/test/test.git" -+ }, -+ "scripts": { -+ "test": "node ./__tests__/my-pkg.test.js" -+ }, -+ "bugs": { -+ "url": "https://github.com/test/test/issues" -+ }, -+ "homepage": "https://github.com/test/test#readme" -+} -`; - -exports[`CreateCommand creates a stub package with transpiled output 1`] = ` -diff --git a/packages/my-pkg/README.md b/packages/my-pkg/README.md -new file mode 100644 -index SHA..SHA ---- /dev/null -+++ b/packages/my-pkg/README.md -@@ -0,0 +1,11 @@ -+# \`my-pkg\` -+ -+> TODO: description -+ -+## Usage -+ -+\`\`\` -+import myPkg from 'my-pkg'; -+ -+// TODO: DEMONSTRATE API -+\`\`\` -diff --git a/packages/my-pkg/__tests__/my-pkg.test.js b/packages/my-pkg/__tests__/my-pkg.test.js -new file mode 100644 -index SHA..SHA ---- /dev/null -+++ b/packages/my-pkg/__tests__/my-pkg.test.js -@@ -0,0 +1,5 @@ -+import myPkg from '../src/my-pkg.js'; -+import { strict as assert } from 'assert'; -+ -+assert.strictEqual(myPkg(), 'Hello from myPkg'); -+console.info("myPkg tests passed"); -diff --git a/packages/my-pkg/package.json b/packages/my-pkg/package.json -new file mode 100644 -index SHA..SHA ---- /dev/null -+++ b/packages/my-pkg/package.json -@@ -0,0 +1,29 @@ -+{ -+ "name": "my-pkg", -+ "version": "1.2.3", -+ "description": "Now I’m the model of a modern major general / The venerated Virginian veteran whose men are all / Lining up, to put me up on a pedestal / Writin’ letters to relatives / Embellishin’ my elegance and eloquence / But the elephant is in the room / The truth is in ya face when ya hear the British cannons go / BOOM", -+ "keywords": [], -+ "author": "Tester McPerson (http://example.com)", -+ "license": "ISC", -+ "main": "dist/my-pkg.js", -+ "module": "dist/my-pkg.module.js", -+ "directories": { -+ "lib": "dist", -+ "test": "__tests__" -+ }, -+ "files": [ -+ "dist" -+ ], -+ "repository": { -+ "type": "git", -+ "url": "git+https://github.com/test/test.git" -+ }, -+ "scripts": { -+ "test": "node ./__tests__/my-pkg.test.js" -+ }, -+ "type": "module", -+ "bugs": { -+ "url": "https://github.com/test/test/issues" -+ }, -+ "homepage": "https://github.com/test/test#readme" -+} -diff --git a/packages/my-pkg/src/my-pkg.js b/packages/my-pkg/src/my-pkg.js -new file mode 100644 -index SHA..SHA ---- /dev/null -+++ b/packages/my-pkg/src/my-pkg.js -@@ -0,0 +1,3 @@ -+export default function myPkg() { -+ return "Hello from myPkg"; -+} -`; diff --git a/commands/create/__tests__/create-command.test.js b/commands/create/__tests__/create-command.test.js deleted file mode 100644 index 966d4cfa5f..0000000000 --- a/commands/create/__tests__/create-command.test.js +++ /dev/null @@ -1,375 +0,0 @@ -"use strict"; - -jest.mock("pacote"); - -const fs = require("fs-extra"); -const path = require("path"); -const execa = require("execa"); -const slash = require("slash"); - -// mocked modules -const pacote = require("pacote"); - -// helpers -const initFixture = require("@lerna-test/helpers").initFixtureFactory(__dirname); -const { gitAdd } = require("@lerna-test/helpers"); - -// file under test -const lernaCreate = require("@lerna-test/helpers").commandRunner(require("../command")); - -// stabilize commit SHA -expect.addSnapshotSerializer(require("@lerna-test/helpers/serializers/serialize-git-sha")); - -// assertion helpers -const addRemote = (cwd, remote = "origin", url = "git@github.com:test/test.git") => - execa("git", ["remote", "add", remote, url], { cwd }); - -const diffStaged = (cwd, ...args) => - execa("git", ["diff", "--cached", ...args], { cwd }).then((result) => result.stdout); - -const initRemoteFixture = (fixtureName) => - initFixture(fixtureName).then((cwd) => addRemote(cwd).then(() => cwd)); - -const gitLsOthers = (cwd, ...args) => - execa("git", ["ls-files", "--others", "--exclude-standard", ...args], { cwd }).then( - (result) => result.stdout - ); - -const listUntracked = async (cwd) => { - const list = await gitLsOthers(cwd, "-z"); - - return list.split("\0").map((fp) => slash(fp)); -}; - -const manifestCreated = async (cwd) => { - const file = await gitLsOthers(cwd, "--", "**/package.json"); - - return fs.readJSON(path.join(cwd, file)); -}; - -describe("CreateCommand", () => { - pacote.manifest.mockImplementation(() => Promise.resolve({ version: "1.0.0-mocked" })); - - // preserve value from @lerna-test/helpers/npm/set-npm-userconfig - const userconfig = process.env.npm_config_userconfig; - - afterEach(() => { - // some tests delete or mangle this - if (process.env.npm_config_userconfig !== userconfig) { - process.env.npm_config_userconfig = userconfig; - } - }); - - it("requires a name argument", async () => { - const cwd = await initFixture("basic"); - const command = lernaCreate(cwd)(); - - await expect(command).rejects.toThrow("Not enough non-option arguments"); - }); - - it("throws when adding a git dependency", async () => { - const cwd = await initRemoteFixture("basic"); - const command = lernaCreate(cwd)( - "git-pkg", - "--dependencies", - "git+ssh://git@notgithub.com/user/foo#semver:^1.2.3" - ); - - await expect(command).rejects.toThrow("Do not use git dependencies"); - }); - - it("creates a stub package", async () => { - const cwd = await initRemoteFixture("basic"); - - await lernaCreate(cwd)("my-pkg"); - await gitAdd(cwd, "."); - - const result = await diffStaged(cwd); - expect(result).toMatchSnapshot(); - }); - - it("creates a stub package with a scoped name", async () => { - const cwd = await initRemoteFixture("basic"); - - await lernaCreate(cwd)("@my-org/my-pkg"); - - const result = await listUntracked(cwd); - expect(result).toContain("packages/my-pkg/lib/my-pkg.js"); - }); - - it("creates a stub package with transpiled output", async () => { - const cwd = await initRemoteFixture("basic"); - - await lernaCreate(cwd)("my-pkg", "--es-module"); - await gitAdd(cwd, "."); - - const result = await diffStaged(cwd); - expect(result).toMatchSnapshot(); - }); - - it("creates a stub cli", async () => { - const cwd = await initRemoteFixture("basic"); - - await lernaCreate(cwd)("my-cli", "--bin"); - await gitAdd(cwd, "."); - - if (process.platform === "win32") { - // windows sucks at file permissions - await gitAdd(cwd, "--chmod", "+x", "--", path.normalize("packages/my-cli/bin/my-cli")); - } - - const result = await diffStaged(cwd); - expect(result).toMatchSnapshot(); - - // yargs is automatically added when CLI is stubbed - expect(pacote.manifest).toHaveBeenLastCalledWith( - expect.objectContaining({ - name: "yargs", - type: "tag", - fetchSpec: "latest", - }), - expect.objectContaining({ - // an npm-conf snapshot - registry: "https://registry.npmjs.org/", - }) - ); - }); - - it("creates a stub cli with a custom name", async () => { - const cwd = await initRemoteFixture("basic"); - - await lernaCreate(cwd)("my-cli", "--bin", "yay"); - - const result = await listUntracked(cwd); - expect(result).toContain("packages/my-cli/bin/yay"); - }); - - it("creates a stub cli with transpiled output", async () => { - const cwd = await initRemoteFixture("basic"); - - await lernaCreate(cwd)("my-es-cli", "--bin", "--es-module"); - await gitAdd(cwd, "."); - - if (process.platform === "win32") { - // windows sucks at file permissions - await gitAdd(cwd, "--chmod", "+x", "--", path.normalize("packages/my-es-cli/bin/my-es-cli")); - } - - const result = await diffStaged(cwd); - expect(result).toMatchSnapshot(); - }); - - it("defaults user name and email to git config", async () => { - const cwd = await initRemoteFixture("basic"); - const name = "Git McGitterson"; - const email = "test@git-fallback.com"; - - // overwrite test defaults so it's really obvious - await execa("git", ["config", "user.name", name], { cwd }); - await execa("git", ["config", "user.email", email], { cwd }); - - // ignore test defaults as well as ~/.npmrc - process.env.npm_config_userconfig = "/dev/null"; - - await lernaCreate(cwd)("git-fallback"); - - expect(await manifestCreated(cwd)).toHaveProperty("author", `${name} <${email}>`); - }); - - it("overrides init-license with --license", async () => { - const cwd = await initRemoteFixture("basic"); - - await lernaCreate(cwd)("license-override", "--license", "MIT"); - - expect(await manifestCreated(cwd)).toHaveProperty("license", "MIT"); - }); - - it("sets private:true with --private", async () => { - const cwd = await initRemoteFixture("basic"); - - await lernaCreate(cwd)("private-pkg", "--private"); - - expect(await manifestCreated(cwd)).toHaveProperty("private", true); - }); - - it("defaults to npm_config_init_version when independent", async () => { - const cwd = await initRemoteFixture("independent"); - - process.env.npm_config_init_version = "100.0.0"; - - await lernaCreate(cwd)("indy-pkg"); - - delete process.env.npm_config_init_version; - - expect(await manifestCreated(cwd)).toHaveProperty("version", "100.0.0"); - }); - - it("allows choice of package location", async () => { - const cwd = await initRemoteFixture("custom-location"); - - await lernaCreate(cwd)("custom-pkg", "modules"); - - const result = await listUntracked(cwd); - expect(result).toContain("modules/custom-pkg/package.json"); - }); - - it("adds local dependencies", async () => { - const cwd = await initRemoteFixture("independent"); - - await lernaCreate(cwd)("foo-pkg", "--dependencies", "sibling-pkg"); - - expect(await manifestCreated(cwd)).toHaveProperty("dependencies", { - "sibling-pkg": "^2.0.0", - }); - }); - - it("adds local dependency as relative file specifier when others exist", async () => { - const cwd = await initRemoteFixture("relative-file-spec"); - - await lernaCreate(cwd)("foo-pkg", "--dependencies", "sibling-pkg"); - - expect(await manifestCreated(cwd)).toHaveProperty("dependencies", { - "sibling-pkg": "file:../sibling-pkg", - }); - }); - - it("reuses existing external dependency version", async () => { - const cwd = await initRemoteFixture("independent"); - - await lernaCreate(cwd)("foo-pkg", "--dependencies", "pify"); - - expect(await manifestCreated(cwd)).toHaveProperty("dependencies", { - pify: "^2.3.0", - }); - }); - - it("supports external dependency version specifier", async () => { - const cwd = await initRemoteFixture("independent"); - - await lernaCreate(cwd)("foo-pkg", "--dependencies", "bar@1.0.0", "baz@^2.0.0", "qux@~3.0.0"); - - expect(await manifestCreated(cwd)).toHaveProperty("dependencies", { - bar: "1.0.0", - baz: "^2.0.0", - qux: "~3.0.0", - }); - }); - - it("respects npm_config_save_exact", async () => { - const cwd = await initRemoteFixture("independent"); - - process.env.npm_config_save_exact = "true"; - - await lernaCreate(cwd)("foo-pkg", "--dependencies", "sibling-pkg"); - - delete process.env.npm_config_save_exact; - - expect(await manifestCreated(cwd)).toHaveProperty("dependencies", { - "sibling-pkg": "2.0.0", - }); - }); - - it("defaults homepage to a subpath of root homepage when it exists", async () => { - const cwd = await initRemoteFixture("independent"); - const rootManifest = path.join(cwd, "package.json"); - const json = await fs.readJSON(rootManifest); - - json.homepage = "https://github.com/test/test"; - await fs.writeJSON(rootManifest, json); - - await lernaCreate(cwd)("foo-pkg"); - - expect(await manifestCreated(cwd)).toHaveProperty( - "homepage", - "https://github.com/test/test/tree/main/packages/foo-pkg#readme" - ); - }); - - it("appends to pathname of non-github root homepage", async () => { - const cwd = await initRemoteFixture("independent"); - const rootManifest = path.join(cwd, "package.json"); - const json = await fs.readJSON(rootManifest); - - json.homepage = "https://bitbucket.com/test/test"; - await fs.writeJSON(rootManifest, json); - - await lernaCreate(cwd)("foo-pkg"); - - expect(await manifestCreated(cwd)).toHaveProperty( - "homepage", - // no doubt wrong, but just illustrative of condition - "https://bitbucket.com/test/test/packages/foo-pkg" - ); - }); - - it("does not mutate explicit --homepage pathname", async () => { - const cwd = await initRemoteFixture("basic"); - - await lernaCreate(cwd)("foo-pkg", "--homepage", "http://google.com/"); - - expect(await manifestCreated(cwd)).toHaveProperty("homepage", "http://google.com/"); - }); - - it("defaults schemeless homepage to http://", async () => { - const cwd = await initRemoteFixture("basic"); - - await lernaCreate(cwd)("foo-pkg", "--homepage", "google.com"); - - expect(await manifestCreated(cwd)).toHaveProperty("homepage", "http://google.com/"); - }); - - it("overrides default publishConfig.access with --access=restricted", async () => { - const cwd = await initRemoteFixture("basic"); - - await lernaCreate(cwd)("@foo/pkg", "--access", "restricted"); - - expect(await manifestCreated(cwd)).toHaveProperty("publishConfig", { - access: "restricted", - }); - }); - - it("sets non-public publishConfig.registry with --registry", async () => { - const cwd = await initRemoteFixture("basic"); - - await lernaCreate(cwd)("@foo/pkg", "--registry", "http://my-private-registry.com/"); - - expect(await manifestCreated(cwd)).toHaveProperty("publishConfig", { - registry: "http://my-private-registry.com/", - }); - }); - - it("sets publishConfig.tag with --tag", async () => { - const cwd = await initRemoteFixture("basic"); - - await lernaCreate(cwd)("@foo/pkg", "--tag", "next"); - - expect(await manifestCreated(cwd)).toHaveProperty("publishConfig", { - access: "public", - tag: "next", - }); - }); - - it("skips repository field when git remote is missing", async () => { - const cwd = await initFixture("basic"); - - await lernaCreate(cwd)("a-pkg"); - - expect(await manifestCreated(cwd)).not.toHaveProperty("repository"); - }); - - it("adds type field when using esModule", async () => { - const cwd = await initFixture("basic"); - - await lernaCreate(cwd)("a-pkg", "--es-module"); - - expect(await manifestCreated(cwd)).toHaveProperty("type", "module"); - }); - - it("skips type field when not using esModule", async () => { - const cwd = await initFixture("basic"); - - await lernaCreate(cwd)("a-pkg"); - - expect(await manifestCreated(cwd)).not.toHaveProperty("type"); - }); -}); diff --git a/commands/create/command.js b/commands/create/command.js deleted file mode 100644 index 9a367fe4eb..0000000000 --- a/commands/create/command.js +++ /dev/null @@ -1,91 +0,0 @@ -"use strict"; - -/** - * @see https://github.com/yargs/yargs/blob/master/docs/advanced.md#providing-a-command-module - */ -exports.command = "create [loc]"; - -exports.describe = "Create a new lerna-managed package"; - -exports.builder = (yargs) => { - yargs - .positional("name", { - describe: "The package name (including scope), which must be locally unique _and_ publicly available", - type: "string", - }) - .positional("loc", { - describe: "A custom package location, defaulting to the first configured package location", - type: "string", - }) - .options({ - access: { - group: "Command Options:", - defaultDescription: "public", - describe: "When using a scope, set publishConfig.access value", - choices: ["public", "restricted"], - }, - bin: { - group: "Command Options:", - defaultDescription: "", - describe: "Package has an executable. Customize with --bin ", - }, - description: { - group: "Command Options:", - describe: "Package description", - type: "string", - }, - dependencies: { - group: "Command Options:", - describe: "A list of package dependencies", - type: "array", - }, - "es-module": { - group: "Command Options:", - describe: "Initialize a transpiled ES Module", - type: "boolean", - }, - homepage: { - group: "Command Options:", - describe: "The package homepage, defaulting to a subpath of the root pkg.homepage", - type: "string", - }, - keywords: { - group: "Command Options:", - describe: "A list of package keywords", - type: "array", - }, - license: { - group: "Command Options:", - defaultDescription: "ISC", - describe: "The desired package license (SPDX identifier)", - type: "string", - }, - private: { - group: "Command Options:", - describe: "Make the new package private, never published to any external registry", - type: "boolean", - }, - registry: { - group: "Command Options:", - describe: "Configure the package's publishConfig.registry", - type: "string", - }, - tag: { - group: "Command Options:", - describe: "Configure the package's publishConfig.tag", - type: "string", - }, - y: { - group: "Command Options:", - describe: "Skip all prompts, accepting default values", - alias: "yes", - type: "boolean", - }, - }); - - return yargs; -}; - -exports.handler = function handler(argv) { - return require(".")(argv); -}; diff --git a/commands/create/index.js b/commands/create/index.js deleted file mode 100644 index 95560f3795..0000000000 --- a/commands/create/index.js +++ /dev/null @@ -1,554 +0,0 @@ -"use strict"; - -const fs = require("fs-extra"); -const path = require("path"); -const os = require("os"); -const { camelCase } = require("yargs-parser"); -const dedent = require("dedent"); -const initPackageJson = require("pify")(require("init-package-json")); -const pacote = require("pacote"); -const npa = require("npm-package-arg"); -const pReduce = require("p-reduce"); -const slash = require("slash"); - -const { Command } = require("@lerna/command"); -const childProcess = require("@lerna/child-process"); -const npmConf = require("@lerna/npm-conf"); -const { ValidationError } = require("@lerna/validation-error"); -const { builtinNpmrc } = require("./lib/builtin-npmrc"); -const { catFile } = require("./lib/cat-file"); - -const LERNA_MODULE_DATA = require.resolve("./lib/lerna-module-data.js"); -const DEFAULT_DESCRIPTION = [ - "Now I’m the model of a modern major general", - "The venerated Virginian veteran whose men are all", - "Lining up, to put me up on a pedestal", - "Writin’ letters to relatives", - "Embellishin’ my elegance and eloquence", - "But the elephant is in the room", - "The truth is in ya face when ya hear the British cannons go", - "BOOM", -].join(" / "); - -module.exports = factory; - -function factory(argv) { - return new CreateCommand(argv); -} - -class CreateCommand extends Command { - initialize() { - const { - bin, - description = DEFAULT_DESCRIPTION, - esModule, - keywords, - license, - loc: pkgLocation, - name: pkgName, - yes, - } = this.options; - - // npm-package-arg handles all the edge-cases with scopes - const { name, scope } = npa(pkgName); - - if (!name && pkgName.includes("/")) { - throw new ValidationError( - "ENOPKGNAME", - "Invalid package name. Use the positional to specify package directory.\nSee https://github.com/lerna/lerna/tree/main/commands/create#usage for details." - ); - } - - // optional scope is _not_ included in the directory name - this.dirName = scope ? name.split("/").pop() : name; - this.pkgName = name; - - this.pkgsDir = this._getPackagesDir(pkgLocation); - - this.camelName = camelCase(this.dirName); - - // when transpiling, src => dist; otherwise everything in lib - this.outDir = esModule ? "dist" : "lib"; - this.targetDir = path.resolve(this.pkgsDir, this.dirName); - - this.binDir = path.join(this.targetDir, "bin"); - this.binFileName = bin === true ? this.dirName : bin; - - this.libDir = path.join(this.targetDir, esModule ? "src" : "lib"); - this.libFileName = `${this.dirName}.js`; - - this.testDir = path.join(this.targetDir, "__tests__"); - this.testFileName = `${this.dirName}.test.js`; - - this.conf = npmConf({ - description, - esModule, - keywords, - scope, - yes, - }); - - // consume "builtin" npm config, if it exists (matches npm cli behaviour) - this.conf.addFile(builtinNpmrc(), "builtin"); - - // always set init-main, it's half of the whole point of this module - this.conf.set("init-main", `${this.outDir}/${this.libFileName}`); - - if (esModule) { - this.conf.set("init-es-module", `${this.outDir}/${this.dirName}.module.js`); - } - - // allow default init-version when independent versioning enabled - if (!this.project.isIndependent()) { - this.conf.set("init-version", this.project.version); - } - - // default author metadata with git config - if (this.conf.get("init-author-name") === "") { - this.conf.set("init-author-name", this.gitConfig("user.name")); - } - - if (this.conf.get("init-author-email") === "") { - this.conf.set("init-author-email", this.gitConfig("user.email")); - } - - // override npm_config_init_license if --license provided - if (license) { - this.conf.set("init-license", license); - } - - // pass --private into module data without aggravating eslint - if (this.options.private) { - this.conf.set("private", true); - } - - // silence output if logging is silenced - // istanbul ignore else - if (this.options.loglevel === "silent") { - this.conf.set("silent", true); - } - - // save read-package-json the trouble - if (this.binFileName) { - this.conf.set("bin", { - [this.binFileName]: `bin/${this.binFileName}`, - }); - } - - // setting _both_ pkg.bin and pkg.directories.bin is an error - // https://docs.npmjs.com/files/package.json#directoriesbin - this.conf.set("directories", { - lib: this.outDir, - test: "__tests__", - }); - - this.setFiles(); - this.setHomepage(); - this.setPublishConfig(); - this.setRepository(); - - return Promise.resolve(this.setDependencies()); - } - - _getPackagesDir(pkgLocation) { - const packageParentDirs = this.project.packageParentDirs; - - if (!pkgLocation) { - return packageParentDirs[0]; - } - - const normalizedPkgLocation = path - .resolve(this.project.rootPath, path.normalize(pkgLocation)) - .toLowerCase(); - const packageParentDirsLower = packageParentDirs.map((p) => p.toLowerCase()); - - // using indexOf over includes due to platform differences (/private/tmp should match /tmp on macOS) - const matchingPathIndex = packageParentDirsLower.findIndex((p) => p.indexOf(normalizedPkgLocation) > -1); - - if (matchingPathIndex > -1) { - return packageParentDirs[matchingPathIndex]; - } - - throw new ValidationError( - "ENOPKGDIR", - `Location "${pkgLocation}" is not configured as a workspace directory.` - ); - } - - execute() { - let chain = Promise.resolve(); - - chain = chain.then(() => fs.mkdirp(this.libDir)); - chain = chain.then(() => fs.mkdirp(this.testDir)); - chain = chain.then(() => Promise.all([this.writeReadme(), this.writeLibFile(), this.writeTestFile()])); - - if (this.binFileName) { - chain = chain.then(() => fs.mkdirp(this.binDir)); - chain = chain.then(() => Promise.all([this.writeBinFile(), this.writeCliFile(), this.writeCliTest()])); - } - - chain = chain.then(() => initPackageJson(this.targetDir, LERNA_MODULE_DATA, this.conf)); - - return chain.then((data) => { - if (this.options.esModule) { - this.logger.notice( - "✔", - dedent` - Ensure '${path.relative(".", this.pkgsDir)}/*/${this.outDir}' has been added to ./.gitignore - Ensure rollup or babel build scripts are in the root - ` - ); - } - - this.logger.success( - "create", - `New package ${data.name} created at ./${path.relative(".", this.targetDir)}` - ); - }); - } - - gitConfig(prop) { - return childProcess.execSync("git", ["config", "--get", prop], this.execOpts); - } - - collectExternalVersions() { - // collect all current externalDependencies - const extVersions = new Map(); - - for (const { externalDependencies } of this.packageGraph.values()) { - for (const [name, resolved] of externalDependencies) { - extVersions.set(name, resolved.fetchSpec); - } - } - - return extVersions; - } - - hasLocalRelativeFileSpec() { - // if any local dependencies are specified as `file:../dir`, - // all new local dependencies should be created thusly - for (const { localDependencies } of this.packageGraph.values()) { - for (const spec of localDependencies.values()) { - if (spec.type === "directory") { - return true; - } - } - } - } - - resolveRelative(depNode) { - // a relative file: specifier is _always_ posix - const relPath = path.relative(this.targetDir, depNode.location); - const spec = npa.resolve(depNode.name, relPath, this.targetDir); - - return slash(spec.saveSpec); - } - - setDependencies() { - const inputs = new Set((this.options.dependencies || []).sort()); - - // add yargs if a bin is required - if (this.options.bin) { - inputs.add("yargs"); - } - - if (!inputs.size) { - return; - } - - const exts = this.collectExternalVersions(); - const localRelative = this.hasLocalRelativeFileSpec(); - const savePrefix = this.conf.get("save-exact") ? "" : this.conf.get("save-prefix"); - const pacoteOpts = this.conf.snapshot; - - const decideVersion = (spec) => { - if (this.packageGraph.has(spec.name)) { - // sibling dependency - const depNode = this.packageGraph.get(spec.name); - - if (localRelative) { - // a local `file:../foo` specifier - return this.resolveRelative(depNode); - } - - // yarn workspace or lerna packages config - return `${savePrefix}${depNode.version}`; - } - - if (spec.type === "tag" && spec.fetchSpec === "latest") { - // resolve the latest version - if (exts.has(spec.name)) { - // from local external dependency - return exts.get(spec.name); - } - - // from registry - return pacote.manifest(spec, pacoteOpts).then((pkg) => `${savePrefix}${pkg.version}`); - } - - if (spec.type === "git") { - throw new ValidationError("EGIT", "Do not use git dependencies"); - } - - // TODO: resolve this if it's weird? (foo@1, bar@^2, etc) - return spec.rawSpec; - }; - - let chain = Promise.resolve(); - - chain = chain.then(() => - pReduce( - inputs, - (obj, input) => { - const spec = npa(input); - - return Promise.resolve(spec) - .then(decideVersion) - .then((version) => { - obj[spec.name] = version; - - return obj; - }); - }, - {} - ) - ); - - chain = chain.then((dependencies) => { - this.conf.set("dependencies", dependencies); - }); - - return chain; - } - - setFiles() { - // no need to glob for files we already know - const files = [this.outDir]; - - if (this.options.bin) { - files.unshift("bin"); - } - - this.conf.set("files", files); - } - - setHomepage() { - // allow --homepage override, but otherwise use root pkg.homepage, if it exists - let { homepage = this.project.manifest.get("homepage") } = this.options; - - if (!homepage) { - // normalize-package-data will backfill from hosted-git-info, if possible - return; - } - - // allow schemeless URLs (but don't blow up in URL constructor) - if (homepage.indexOf("http") !== 0) { - homepage = `http://${homepage}`; - } - - const hurl = new URL(homepage); - const relativeTarget = path.relative(this.project.rootPath, this.targetDir); - - if (hurl.hostname.match("github")) { - hurl.pathname = path.posix.join(hurl.pathname, "tree/main", relativeTarget); - // TODO: get actual upstream HEAD branch name - // current remote: git rev-parse --abbrev-ref --symbolic-full-name @{u} - // upstream HEAD: git symbolic-ref --short refs/remotes/origin/HEAD - hurl.hash = "readme"; - } else if (!this.options.homepage) { - // don't mutate an explicit --homepage value - hurl.pathname = path.posix.join(hurl.pathname, relativeTarget); - } - - this.conf.set("homepage", hurl.href); - } - - setPublishConfig() { - const scope = this.conf.get("scope"); - const registry = this.options.registry || this.conf.get(`${scope}:registry`) || this.conf.get("registry"); - const isPublicRegistry = registry === this.conf.root.registry; - const publishConfig = {}; - - if (scope && isPublicRegistry) { - publishConfig.access = this.options.access || "public"; - } - - if (registry && !isPublicRegistry) { - publishConfig.registry = registry; - } - - if (this.options.tag) { - publishConfig.tag = this.options.tag; - } - - if (Object.keys(publishConfig).length) { - this.conf.set("publishConfig", publishConfig); - } - } - - setRepository() { - try { - const url = childProcess.execSync("git", ["remote", "get-url", "origin"], this.execOpts); - - this.conf.set("repository", url); - } catch (err) { - this.logger.warn("ENOREMOTE", "No git remote found, skipping repository property"); - } - } - - writeReadme() { - const readmeContent = dedent` - # \`${this.pkgName}\` - - > ${this.options.description || "TODO: description"} - - ## Usage - - \`\`\` - ${ - // eslint-disable-next-line no-nested-ternary - this.options.bin - ? dedent` - npm -g i ${this.pkgName} - - ${this.binFileName} --help - ` - : this.options.esModule - ? `import ${this.camelName} from '${this.pkgName}';` - : `const ${this.camelName} = require('${this.pkgName}');` - } - - // TODO: DEMONSTRATE API - \`\`\` - `; - - return catFile(this.targetDir, "README.md", readmeContent); - } - - writeLibFile() { - const libContent = this.options.esModule - ? dedent` - export default function ${this.camelName}() { - return "Hello from ${this.camelName}"; - } - ` - : dedent` - 'use strict'; - - module.exports = ${this.camelName}; - - function ${this.camelName}() { - return "Hello from ${this.camelName}"; - } - `; - - return catFile(this.libDir, this.libFileName, libContent); - } - - writeTestFile() { - const testContent = this.options.esModule - ? dedent` - import ${this.camelName} from '../src/${this.dirName}.js'; - import { strict as assert } from 'assert'; - - assert.strictEqual(${this.camelName}(), 'Hello from ${this.camelName}'); - console.info("${this.camelName} tests passed"); - ` - : dedent` - 'use strict'; - - const ${this.camelName} = require('..'); - const assert = require('assert').strict; - - assert.strictEqual(${this.camelName}(), 'Hello from ${this.camelName}'); - console.info("${this.camelName} tests passed"); - `; - - return catFile(this.testDir, this.testFileName, testContent); - } - - writeCliFile() { - const cliFileName = "cli.js"; - const cliContent = [ - this.options.esModule - ? dedent` - import factory from 'yargs/yargs'; - import ${this.camelName} from './${this.dirName}'; - - export default cli; - ` - : dedent` - 'use strict'; - - const factory = require('yargs/yargs'); - const ${this.camelName} = require('./${this.dirName}'); - - module.exports = cli; - `, - "", // blank line - dedent` - function cli(cwd) { - const parser = factory(null, cwd); - - parser.alias('h', 'help'); - parser.alias('v', 'version'); - - parser.usage( - "$0", - "TODO: description", - yargs => { - yargs.options({ - // TODO: options - }); - }, - argv => ${this.camelName}(argv) - ); - - return parser; - } - `, - ].join(os.EOL); - - return catFile(this.libDir, cliFileName, cliContent); - } - - writeCliTest() { - const cliTestFileName = "cli.test.js"; - const cliTestContent = [ - this.options.esModule - ? dedent` - import cli from '../src/cli'; - ` - : dedent` - 'use strict'; - - const cli = require('../lib/cli'); - `, - "", // blank line - dedent` - describe('${this.pkgName} cli', () => { - // const argv = cli(cwd).parse(['args']); - it('needs tests'); - }); - `, - ].join(os.EOL); - - return catFile(this.testDir, cliTestFileName, cliTestContent); - } - - writeBinFile() { - const binContent = dedent` - #!/usr/bin/env node - - 'use strict'; - - // eslint-disable-next-line no-unused-expressions - require('../${this.outDir}/cli')${ - this.options.esModule ? ".default" : "" - }().parse(process.argv.slice(2));`; - - return catFile(this.binDir, this.binFileName, binContent, { mode: 0o755 }); - } -} - -module.exports.CreateCommand = CreateCommand; diff --git a/commands/create/lib/builtin-npmrc.js b/commands/create/lib/builtin-npmrc.js deleted file mode 100644 index d5fb397edc..0000000000 --- a/commands/create/lib/builtin-npmrc.js +++ /dev/null @@ -1,22 +0,0 @@ -"use strict"; - -const fs = require("fs-extra"); -const path = require("path"); - -module.exports.builtinNpmrc = builtinNpmrc; - -function builtinNpmrc() { - let resolvedPath = ""; - - try { - // e.g., /usr/local/lib/node_modules/npm/npmrc - resolvedPath = path.resolve( - fs.realpathSync(path.join(path.dirname(process.execPath), "npm")), - "../../npmrc" - ); - } catch (err) { - // ignore - } - - return resolvedPath; -} diff --git a/commands/create/lib/cat-file.js b/commands/create/lib/cat-file.js deleted file mode 100644 index f3f043c9e8..0000000000 --- a/commands/create/lib/cat-file.js +++ /dev/null @@ -1,16 +0,0 @@ -"use strict"; - -const fs = require("fs-extra"); -const path = require("path"); - -module.exports.catFile = catFile; - -/** - * @param {string} baseDir - * @param {string} fileName - * @param {string} content - * @param {string | import('fs-extra').WriteFileOptions} [opts] - */ -function catFile(baseDir, fileName, content, opts = "utf8") { - return fs.writeFile(path.join(baseDir, fileName), `${content}\n`, opts); -} diff --git a/commands/create/package.json b/commands/create/package.json deleted file mode 100644 index d7e035a743..0000000000 --- a/commands/create/package.json +++ /dev/null @@ -1,53 +0,0 @@ -{ - "name": "@lerna/create", - "version": "6.4.1", - "description": "Create a new lerna-managed package", - "keywords": [ - "lerna", - "command" - ], - "homepage": "https://lerna.js.org", - "license": "MIT", - "author": { - "name": "Daniel Stockman", - "url": "https://github.com/evocateur" - }, - "files": [ - "command.js", - "index.js", - "lib" - ], - "main": "index.js", - "engines": { - "node": "^14.15.0 || >=16.0.0" - }, - "publishConfig": { - "access": "public" - }, - "repository": { - "type": "git", - "url": "git+https://github.com/lerna/lerna.git", - "directory": "commands/create" - }, - "scripts": { - "test": "echo \"Run tests from root\" && exit 1" - }, - "dependencies": { - "@lerna/child-process": "file:../../core/child-process", - "@lerna/command": "file:../../core/command", - "@lerna/npm-conf": "file:../../utils/npm-conf", - "@lerna/validation-error": "file:../../core/validation-error", - "dedent": "^0.7.0", - "fs-extra": "^9.1.0", - "init-package-json": "^3.0.2", - "npm-package-arg": "8.1.1", - "p-reduce": "^2.1.0", - "pacote": "^13.6.1", - "pify": "^5.0.0", - "semver": "^7.3.4", - "slash": "^3.0.0", - "validate-npm-package-license": "^3.0.4", - "validate-npm-package-name": "^4.0.0", - "yargs-parser": "20.2.4" - } -} diff --git a/commands/diff/CHANGELOG.md b/commands/diff/CHANGELOG.md deleted file mode 100644 index f60218c5a4..0000000000 --- a/commands/diff/CHANGELOG.md +++ /dev/null @@ -1,454 +0,0 @@ -# Change Log - -All notable changes to this project will be documented in this file. -See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. - -## [6.4.1](https://github.com/lerna/lerna/compare/v6.4.0...v6.4.1) (2023-01-12) - -**Note:** Version bump only for package @lerna/diff - -# [6.4.0](https://github.com/lerna/lerna/compare/v6.3.0...v6.4.0) (2023-01-05) - -**Note:** Version bump only for package @lerna/diff - -# [6.3.0](https://github.com/lerna/lerna/compare/v6.2.0...v6.3.0) (2022-12-26) - -**Note:** Version bump only for package @lerna/diff - -# [6.2.0](https://github.com/lerna/lerna/compare/v6.1.0...v6.2.0) (2022-12-13) - -**Note:** Version bump only for package @lerna/diff - -# [6.1.0](https://github.com/lerna/lerna/compare/v6.0.3...v6.1.0) (2022-11-29) - -**Note:** Version bump only for package @lerna/diff - -## [6.0.3](https://github.com/lerna/lerna/compare/v6.0.2...v6.0.3) (2022-11-07) - -**Note:** Version bump only for package @lerna/diff - -## [6.0.2](https://github.com/lerna/lerna/compare/v6.0.1...v6.0.2) (2022-11-02) - -**Note:** Version bump only for package @lerna/diff - -## [6.0.1](https://github.com/lerna/lerna/compare/v6.0.0...v6.0.1) (2022-10-14) - -**Note:** Version bump only for package @lerna/diff - -# [6.0.0](https://github.com/lerna/lerna/compare/v6.0.0-alpha.2...v6.0.0) (2022-10-12) - -**Note:** Version bump only for package @lerna/diff - -# [6.0.0-alpha.2](https://github.com/lerna/lerna/compare/v6.0.0-alpha.1...v6.0.0-alpha.2) (2022-10-12) - -**Note:** Version bump only for package @lerna/diff - -# [6.0.0-alpha.1](https://github.com/lerna/lerna/compare/v5.6.2...v6.0.0-alpha.1) (2022-10-09) - -# [6.0.0-alpha.0](https://github.com/lerna/lerna/compare/v5.6.1...v6.0.0-alpha.0) (2022-10-07) - -**Note:** Version bump only for package @lerna/diff - -## [5.6.2](https://github.com/lerna/lerna/compare/v5.6.1...v5.6.2) (2022-10-09) - -**Note:** Version bump only for package @lerna/diff - -## [5.6.1](https://github.com/lerna/lerna/compare/v5.6.0...v5.6.1) (2022-09-30) - -**Note:** Version bump only for package @lerna/diff - -# [5.6.0](https://github.com/lerna/lerna/compare/v5.5.4...v5.6.0) (2022-09-29) - -**Note:** Version bump only for package @lerna/diff - -## [5.5.4](https://github.com/lerna/lerna/compare/v5.5.3...v5.5.4) (2022-09-28) - -**Note:** Version bump only for package @lerna/diff - -## [5.5.3](https://github.com/lerna/lerna/compare/v5.5.2...v5.5.3) (2022-09-28) - -**Note:** Version bump only for package @lerna/diff - -## [5.5.2](https://github.com/lerna/lerna/compare/v5.5.1...v5.5.2) (2022-09-20) - -**Note:** Version bump only for package @lerna/diff - -## [5.5.1](https://github.com/lerna/lerna/compare/v5.5.0...v5.5.1) (2022-09-09) - -**Note:** Version bump only for package @lerna/diff - -# [5.5.0](https://github.com/lerna/lerna/compare/v5.4.3...v5.5.0) (2022-08-31) - -**Note:** Version bump only for package @lerna/diff - -## [5.4.3](https://github.com/lerna/lerna/compare/v5.4.2...v5.4.3) (2022-08-16) - -**Note:** Version bump only for package @lerna/diff - -## [5.4.2](https://github.com/lerna/lerna/compare/v5.4.1...v5.4.2) (2022-08-14) - -**Note:** Version bump only for package @lerna/diff - -## [5.4.1](https://github.com/lerna/lerna/compare/v5.4.0...v5.4.1) (2022-08-12) - -**Note:** Version bump only for package @lerna/diff - -# [5.4.0](https://github.com/lerna/lerna/compare/v5.3.0...v5.4.0) (2022-08-08) - -**Note:** Version bump only for package @lerna/diff - -# [5.3.0](https://github.com/lerna/lerna/compare/v5.2.0...v5.3.0) (2022-07-27) - -**Note:** Version bump only for package @lerna/diff - -# [5.2.0](https://github.com/lerna/lerna/compare/v5.1.8...v5.2.0) (2022-07-22) - -**Note:** Version bump only for package @lerna/diff - -## [5.1.8](https://github.com/lerna/lerna/compare/v5.1.7...v5.1.8) (2022-07-07) - -**Note:** Version bump only for package @lerna/diff - -## [5.1.7](https://github.com/lerna/lerna/compare/v5.1.6...v5.1.7) (2022-07-06) - -**Note:** Version bump only for package @lerna/diff - -## [5.1.6](https://github.com/lerna/lerna/compare/v5.1.5...v5.1.6) (2022-06-24) - -**Note:** Version bump only for package @lerna/diff - -## [5.1.5](https://github.com/lerna/lerna/compare/v5.1.4...v5.1.5) (2022-06-24) - -**Note:** Version bump only for package @lerna/diff - -## [5.1.4](https://github.com/lerna/lerna/compare/v5.1.3...v5.1.4) (2022-06-15) - -**Note:** Version bump only for package @lerna/diff - -## [5.1.3](https://github.com/lerna/lerna/compare/v5.1.2...v5.1.3) (2022-06-15) - -**Note:** Version bump only for package @lerna/diff - -## [5.1.2](https://github.com/lerna/lerna/compare/v5.1.1...v5.1.2) (2022-06-13) - -### Bug Fixes - -- update all transitive inclusions of ansi-regex ([#3166](https://github.com/lerna/lerna/issues/3166)) ([56eaa15](https://github.com/lerna/lerna/commit/56eaa153283be3b1e7d7793d3266fc51801fad8e)) - -## [5.1.1](https://github.com/lerna/lerna/compare/v5.1.0...v5.1.1) (2022-06-09) - -### Bug Fixes - -- allow maintenance LTS node 14 engines starting at 14.15.0 ([#3161](https://github.com/lerna/lerna/issues/3161)) ([72305e4](https://github.com/lerna/lerna/commit/72305e4dbab607a2d87ae4efa6ee577c93a9dda9)) - -# [5.1.0](https://github.com/lerna/lerna/compare/v5.0.0...v5.1.0) (2022-06-07) - -**Note:** Version bump only for package @lerna/diff - -# [5.1.0-alpha.0](https://github.com/lerna/lerna/compare/v4.0.0...v5.1.0-alpha.0) (2022-05-25) - -**Note:** Version bump only for package @lerna/diff - -# [5.0.0](https://github.com/lerna/lerna/compare/v4.0.0...v5.0.0) (2022-05-24) - -**Note:** Version bump only for package @lerna/diff - -# [4.0.0](https://github.com/lerna/lerna/compare/v3.22.1...v4.0.0) (2021-02-10) - -### Features - -- Consume named exports of sibling modules ([63499e3](https://github.com/lerna/lerna/commit/63499e33652bc78fe23751875d74017e2f16a689)) -- **deps:** execa@^4.1.0 ([9051dca](https://github.com/lerna/lerna/commit/9051dcab1a68b56db09b82ab0345c5f36bcfee2d)) -- Drop support for Node v6.x & v8.x ([ff4bb4d](https://github.com/lerna/lerna/commit/ff4bb4da215555e3bb136f5af09b5cbc631e57bb)) - -### BREAKING CHANGES - -- Node v6.x & v8.x are no longer supported. Please upgrade to the latest LTS release. - -Here's the gnarly one-liner I used to make these changes: - -``` -npx lerna exec --concurrency 1 --stream -- 'json -I -f package.json -e '"'"'this.engines=this.engines||{};this.engines.node=">= 10.18.0"'"'" -``` - -(requires `npm i -g json` beforehand) - -# [3.21.0](https://github.com/lerna/lerna/compare/v3.20.2...v3.21.0) (2020-05-13) - -**Note:** Version bump only for package @lerna/diff - -## [3.18.5](https://github.com/lerna/lerna/compare/v3.18.4...v3.18.5) (2019-11-20) - -**Note:** Version bump only for package @lerna/diff - -# [3.18.0](https://github.com/lerna/lerna/compare/v3.17.0...v3.18.0) (2019-10-15) - -**Note:** Version bump only for package @lerna/diff - -## [3.16.5](https://github.com/lerna/lerna/compare/v3.16.4...v3.16.5) (2019-10-07) - -**Note:** Version bump only for package @lerna/diff - -# [3.16.0](https://github.com/lerna/lerna/compare/v3.15.0...v3.16.0) (2019-07-18) - -**Note:** Version bump only for package @lerna/diff - -# [3.15.0](https://github.com/lerna/lerna/compare/v3.14.2...v3.15.0) (2019-06-09) - -**Note:** Version bump only for package @lerna/diff - -## [3.14.2](https://github.com/lerna/lerna/compare/v3.14.1...v3.14.2) (2019-06-09) - -**Note:** Version bump only for package @lerna/diff - -# [3.14.0](https://github.com/lerna/lerna/compare/v3.13.4...v3.14.0) (2019-05-14) - -**Note:** Version bump only for package @lerna/diff - -## [3.13.3](https://github.com/lerna/lerna/compare/v3.13.2...v3.13.3) (2019-04-17) - -**Note:** Version bump only for package @lerna/diff - -## [3.13.1](https://github.com/lerna/lerna/compare/v3.13.0...v3.13.1) (2019-02-26) - -**Note:** Version bump only for package @lerna/diff - -# [3.13.0](https://github.com/lerna/lerna/compare/v3.12.1...v3.13.0) (2019-02-15) - -### Features - -- **meta:** Add `repository.directory` field to package.json ([aec5023](https://github.com/lerna/lerna/commit/aec5023)) -- **meta:** Normalize package.json `homepage` field ([abeb4dc](https://github.com/lerna/lerna/commit/abeb4dc)) - -# [3.12.0](https://github.com/lerna/lerna/compare/v3.11.1...v3.12.0) (2019-02-14) - -**Note:** Version bump only for package @lerna/diff - -# [3.11.0](https://github.com/lerna/lerna/compare/v3.10.8...v3.11.0) (2019-02-08) - -### Bug Fixes - -- **deps:** Explicit npmlog ^4.1.2 ([571c2e2](https://github.com/lerna/lerna/commit/571c2e2)) -- **deps:** Remove unused libnpm (replaced by direct sub-packages) ([1caeb28](https://github.com/lerna/lerna/commit/1caeb28)) - -## [3.10.6](https://github.com/lerna/lerna/compare/v3.10.5...v3.10.6) (2019-01-19) - -**Note:** Version bump only for package @lerna/diff - -# [3.10.0](https://github.com/lerna/lerna/compare/v3.9.1...v3.10.0) (2019-01-08) - -**Note:** Version bump only for package @lerna/diff - -## [3.8.5](https://github.com/lerna/lerna/compare/v3.8.4...v3.8.5) (2019-01-05) - -**Note:** Version bump only for package @lerna/diff - -## [3.8.1](https://github.com/lerna/lerna/compare/v3.8.0...v3.8.1) (2018-12-31) - -**Note:** Version bump only for package @lerna/diff - -## [3.7.2](https://github.com/lerna/lerna/compare/v3.7.1...v3.7.2) (2018-12-21) - -**Note:** Version bump only for package @lerna/diff - -## [3.7.1](https://github.com/lerna/lerna/compare/v3.7.0...v3.7.1) (2018-12-20) - -**Note:** Version bump only for package @lerna/diff - -# [3.7.0](https://github.com/lerna/lerna/compare/v3.6.0...v3.7.0) (2018-12-19) - -**Note:** Version bump only for package @lerna/diff - -# [3.6.0](https://github.com/lerna/lerna/compare/v3.5.1...v3.6.0) (2018-12-07) - -### Features - -- Migrate existing usage to libnpm ([0d3a786](https://github.com/lerna/lerna/commit/0d3a786)), closes [#1767](https://github.com/lerna/lerna/issues/1767) - -# [3.5.0](https://github.com/lerna/lerna/compare/v3.4.3...v3.5.0) (2018-11-27) - -**Note:** Version bump only for package @lerna/diff - - - -# [3.3.0](https://github.com/lerna/lerna/compare/v3.2.1...v3.3.0) (2018-09-06) - -**Note:** Version bump only for package @lerna/diff - - - -## [3.1.3](https://github.com/lerna/lerna/compare/v3.1.2...v3.1.3) (2018-08-21) - -**Note:** Version bump only for package @lerna/diff - - - -## [3.1.2](https://github.com/lerna/lerna/compare/v3.1.1...v3.1.2) (2018-08-20) - -**Note:** Version bump only for package @lerna/diff - - - -# [3.1.0](https://github.com/lerna/lerna/compare/v3.0.6...v3.1.0) (2018-08-17) - -**Note:** Version bump only for package @lerna/diff - - - -## [3.0.6](https://github.com/lerna/lerna/compare/v3.0.5...v3.0.6) (2018-08-16) - -**Note:** Version bump only for package @lerna/diff - - - -## [3.0.5](https://github.com/lerna/lerna/compare/v3.0.4...v3.0.5) (2018-08-15) - -**Note:** Version bump only for package @lerna/diff - - - -# [3.0.0](https://github.com/lerna/lerna/compare/v3.0.0-rc.0...v3.0.0) (2018-08-10) - -**Note:** Version bump only for package @lerna/diff - - - -# [3.0.0-rc.0](https://github.com/lerna/lerna/compare/v3.0.0-beta.21...v3.0.0-rc.0) (2018-07-27) - -### Features - -- Add description from --help summary [skip ci] ([9b65d8e](https://github.com/lerna/lerna/commit/9b65d8e)) -- **project:** Move collect-packages into getPackages() method ([06b88d4](https://github.com/lerna/lerna/commit/06b88d4)) - - - -# [3.0.0-beta.21](https://github.com/lerna/lerna/compare/v3.0.0-beta.20...v3.0.0-beta.21) (2018-05-12) - -**Note:** Version bump only for package @lerna/diff - - - -# [3.0.0-beta.20](https://github.com/lerna/lerna/compare/v3.0.0-beta.19...v3.0.0-beta.20) (2018-05-07) - -**Note:** Version bump only for package @lerna/diff - - - -# [3.0.0-beta.19](https://github.com/lerna/lerna/compare/v3.0.0-beta.18...v3.0.0-beta.19) (2018-05-03) - -**Note:** Version bump only for package @lerna/diff - - - -# [3.0.0-beta.18](https://github.com/lerna/lerna/compare/v3.0.0-beta.17...v3.0.0-beta.18) (2018-04-24) - -### Bug Fixes - -- **diff:** Diff since last release in branch, _not_ most recent global tag ([9879fef](https://github.com/lerna/lerna/commit/9879fef)) - -### Features - -- **diff:** Move diff-only git utilities ([47dc0e2](https://github.com/lerna/lerna/commit/47dc0e2)) - -### BREAKING CHANGES - -- **diff:** Don't use GitUtilities. - - - -# [3.0.0-beta.17](https://github.com/lerna/lerna/compare/v3.0.0-beta.16...v3.0.0-beta.17) (2018-04-13) - -**Note:** Version bump only for package @lerna/diff - - - -# [3.0.0-beta.15](https://github.com/lerna/lerna/compare/v3.0.0-beta.14...v3.0.0-beta.15) (2018-04-09) - -**Note:** Version bump only for package @lerna/diff - - - -# [3.0.0-beta.14](https://github.com/lerna/lerna/compare/v3.0.0-beta.13...v3.0.0-beta.14) (2018-04-03) - -**Note:** Version bump only for package @lerna/diff - - - -# [3.0.0-beta.13](https://github.com/lerna/lerna/compare/v3.0.0-beta.12...v3.0.0-beta.13) (2018-03-31) - -### Features - -- Enable progress bars only when necessary ([b766c83](https://github.com/lerna/lerna/commit/b766c83)) - - - -# [3.0.0-beta.12](https://github.com/lerna/lerna/compare/v3.0.0-beta.11...v3.0.0-beta.12) (2018-03-30) - -### Features - -- **package:** Add `serialize()` method ([fdec3ac](https://github.com/lerna/lerna/commit/fdec3ac)) -- **package:** Add Map-like get/set methods, remove raw json getter ([707d1f0](https://github.com/lerna/lerna/commit/707d1f0)) - -### BREAKING CHANGES - -- **package:** The `Package` class no longer provides direct access to the JSON object - used to construct the instance. Map-like `get()`/`set(val)` methods are - available to modify the internal representation. - - - -# [3.0.0-beta.11](https://github.com/lerna/lerna/compare/v3.0.0-beta.10...v3.0.0-beta.11) (2018-03-29) - -**Note:** Version bump only for package @lerna/diff - - - -# [3.0.0-beta.10](https://github.com/lerna/lerna/compare/v3.0.0-beta.9...v3.0.0-beta.10) (2018-03-27) - -### Features - -- **commands:** Delay require of command instantiation ([a1284f3](https://github.com/lerna/lerna/commit/a1284f3)) - -### BREAKING CHANGES - -- **commands:** The default export of command packages is now a factory, not the subclass (which is now a named export). - - - -# [3.0.0-beta.9](https://github.com/lerna/lerna/compare/v3.0.0-beta.8...v3.0.0-beta.9) (2018-03-24) - -### Features - -- **command:** Rename this.repository -> this.project ([43e98a0](https://github.com/lerna/lerna/commit/43e98a0)) - - - -# [3.0.0-beta.7](https://github.com/lerna/lerna/compare/v3.0.0-beta.6...v3.0.0-beta.7) (2018-03-20) - -**Note:** Version bump only for package @lerna/diff - - - -# [3.0.0-beta.4](https://github.com/lerna/lerna/compare/v3.0.0-beta.3...v3.0.0-beta.4) (2018-03-19) - -**Note:** Version bump only for package @lerna/diff - - - -# [3.0.0-beta.3](https://github.com/lerna/lerna/compare/v3.0.0-beta.2...v3.0.0-beta.3) (2018-03-15) - -**Note:** Version bump only for package @lerna/diff - - - -# [3.0.0-beta.2](https://github.com/lerna/lerna/compare/v3.0.0-beta.1...v3.0.0-beta.2) (2018-03-10) - -**Note:** Version bump only for package @lerna/diff - - - -# [3.0.0-beta.1](https://github.com/lerna/lerna/compare/v3.0.0-beta.0...v3.0.0-beta.1) (2018-03-09) - -### Features - -- **diff:** filter diff output with --ignore-changes ([c27c2e0](https://github.com/lerna/lerna/commit/c27c2e0)) diff --git a/commands/diff/README.md b/commands/diff/README.md deleted file mode 100644 index 04f5935fc9..0000000000 --- a/commands/diff/README.md +++ /dev/null @@ -1,19 +0,0 @@ -# `@lerna/diff` - -> Diff all packages or a single package since the last release - -Install [lerna](https://www.npmjs.com/package/lerna) for access to the `lerna` CLI. - -## Usage - -```sh -$ lerna diff [package] - -$ lerna diff -# diff a specific package -$ lerna diff package-name -``` - -Diff all packages or a single package since the last release. - -> Similar to `lerna changed`. This command runs `git diff`. diff --git a/commands/diff/__tests__/diff-command.test.js b/commands/diff/__tests__/diff-command.test.js deleted file mode 100644 index 4a3fe5264f..0000000000 --- a/commands/diff/__tests__/diff-command.test.js +++ /dev/null @@ -1,115 +0,0 @@ -"use strict"; - -const execa = require("execa"); -const fs = require("fs-extra"); -const path = require("path"); -const { getPackages } = require("@lerna/project"); - -// mocked modules -const childProcess = require("@lerna/child-process"); - -// helpers -const initFixture = require("@lerna-test/helpers").initFixtureFactory(__dirname); -const { gitAdd } = require("@lerna-test/helpers"); -const { gitCommit } = require("@lerna-test/helpers"); -const { gitInit } = require("@lerna-test/helpers"); -const { gitTag } = require("@lerna-test/helpers"); - -// file under test -const lernaDiff = require("@lerna-test/helpers").commandRunner(require("../command")); - -// stabilize commit SHA -expect.addSnapshotSerializer(require("@lerna-test/helpers/serializers/serialize-git-sha")); - -describe("DiffCommand", () => { - // overwrite spawn so we get piped stdout, not inherited - childProcess.spawn = jest.fn((...args) => execa(...args)); - - it("should diff packages from the first commit", async () => { - const cwd = await initFixture("basic"); - const [pkg1] = await getPackages(cwd); - const rootReadme = path.join(cwd, "README.md"); - - await pkg1.set("changed", 1).serialize(); - await fs.outputFile(rootReadme, "change outside packages glob"); - await gitAdd(cwd, "-A"); - await gitCommit(cwd, "changed"); - - const { stdout } = await lernaDiff(cwd)(); - expect(stdout).toMatchSnapshot(); - }); - - it("should diff packages from the most recent tag", async () => { - const cwd = await initFixture("basic"); - const [pkg1] = await getPackages(cwd); - - await pkg1.set("changed", 1).serialize(); - await gitAdd(cwd, "-A"); - await gitCommit(cwd, "changed"); - await gitTag(cwd, "v1.0.1"); - - await pkg1.set("sinceLastTag", true).serialize(); - await gitAdd(cwd, "-A"); - await gitCommit(cwd, "changed"); - - const { stdout } = await lernaDiff(cwd)(); - expect(stdout).toMatchSnapshot(); - }); - - it("should diff a specific package", async () => { - const cwd = await initFixture("basic"); - const [pkg1, pkg2] = await getPackages(cwd); - - await pkg1.set("changed", 1).serialize(); - await pkg2.set("changed", 1).serialize(); - await gitAdd(cwd, "-A"); - await gitCommit(cwd, "changed"); - - const { stdout } = await lernaDiff(cwd)("package-2"); - expect(stdout).toMatchSnapshot(); - }); - - it("passes diff exclude globs configured with --ignored-changes", async () => { - const cwd = await initFixture("basic"); - const [pkg1] = await getPackages(cwd); - - await pkg1.set("changed", 1).serialize(); - await fs.outputFile(path.join(pkg1.location, "README.md"), "ignored change"); - await gitAdd(cwd, "-A"); - await gitCommit(cwd, "changed"); - - const { stdout } = await lernaDiff(cwd)("--ignore-changes", "**/README.md"); - expect(stdout).toMatchSnapshot(); - }); - - it("should error when attempting to diff a package that doesn't exist", async () => { - const cwd = await initFixture("basic"); - const command = lernaDiff(cwd)("missing"); - - await expect(command).rejects.toThrow("Cannot diff, the package 'missing' does not exist."); - }); - - it("should error when running in a repository without commits", async () => { - const cwd = await initFixture("basic"); - - await fs.remove(path.join(cwd, ".git")); - await gitInit(cwd); - - const command = lernaDiff(cwd)("package-1"); - await expect(command).rejects.toThrow("Cannot diff, there are no commits in this repository yet."); - }); - - it("should error when git diff exits non-zero", async () => { - const cwd = await initFixture("basic"); - - childProcess.spawn.mockImplementationOnce(() => { - const nonZero = new Error("An actual non-zero, not git diff pager SIGPIPE"); - nonZero.exitCode = 1; - - throw nonZero; - }); - - const command = lernaDiff(cwd)("package-1"); - await expect(command).rejects.toThrow("An actual non-zero, not git diff pager SIGPIPE"); - }); -}); diff --git a/commands/diff/command.js b/commands/diff/command.js deleted file mode 100644 index 37e80aeb39..0000000000 --- a/commands/diff/command.js +++ /dev/null @@ -1,28 +0,0 @@ -"use strict"; - -/** - * @see https://github.com/yargs/yargs/blob/master/docs/advanced.md#providing-a-command-module - */ -exports.command = "diff [pkgName]"; - -exports.describe = "Diff all packages or a single package since the last release"; - -exports.builder = (yargs) => - yargs - .positional("pkgName", { - describe: "An optional package name to filter the diff output", - }) - .options({ - "ignore-changes": { - group: "Command Options:", - describe: "Ignore changes in files matched by glob(s).", - type: "array", - }, - }) - .epilogue( - "When ignoreChanges is configured in lerna.json, pass --no-ignore-changes to include ignored files." - ); - -exports.handler = function handler(argv) { - return require(".")(argv); -}; diff --git a/commands/diff/index.js b/commands/diff/index.js deleted file mode 100644 index 218d9ce3af..0000000000 --- a/commands/diff/index.js +++ /dev/null @@ -1,61 +0,0 @@ -"use strict"; - -const childProcess = require("@lerna/child-process"); -const { Command } = require("@lerna/command"); -const { ValidationError } = require("@lerna/validation-error"); -const { getLastCommit } = require("./lib/get-last-commit"); -const { hasCommit } = require("./lib/has-commit"); - -module.exports = factory; - -function factory(argv) { - return new DiffCommand(argv); -} - -class DiffCommand extends Command { - initialize() { - const packageName = this.options.pkgName; - - let targetPackage; - - if (packageName) { - targetPackage = this.packageGraph.get(packageName); - - if (!targetPackage) { - throw new ValidationError("ENOPKG", `Cannot diff, the package '${packageName}' does not exist.`); - } - } - - if (!hasCommit(this.execOpts)) { - throw new ValidationError("ENOCOMMITS", "Cannot diff, there are no commits in this repository yet."); - } - - const args = ["diff", getLastCommit(this.execOpts), "--color=auto"]; - - if (targetPackage) { - args.push("--", targetPackage.location); - } else { - args.push("--", ...this.project.packageParentDirs); - } - - if (this.options.ignoreChanges) { - this.options.ignoreChanges.forEach((ignorePattern) => { - // https://stackoverflow.com/a/21079437 - args.push(`:(exclude,glob)${ignorePattern}`); - }); - } - - this.args = args; - } - - execute() { - return childProcess.spawn("git", this.args, this.execOpts).catch((err) => { - if (err.exitCode) { - // quitting the diff viewer is not an error - throw err; - } - }); - } -} - -module.exports.DiffCommand = DiffCommand; diff --git a/commands/diff/lib/get-last-commit.js b/commands/diff/lib/get-last-commit.js deleted file mode 100644 index d22144a9a5..0000000000 --- a/commands/diff/lib/get-last-commit.js +++ /dev/null @@ -1,38 +0,0 @@ -"use strict"; - -const log = require("npmlog"); -const childProcess = require("@lerna/child-process"); - -module.exports.getLastCommit = getLastCommit; - -/** - * @param {import("@lerna/child-process").ExecOpts} execOpts - */ -function getLastCommit(execOpts) { - if (hasTags(execOpts)) { - log.silly("getLastTagInBranch"); - - return childProcess.execSync("git", ["describe", "--tags", "--abbrev=0"], execOpts); - } - - log.silly("getFirstCommit"); - return childProcess.execSync("git", ["rev-list", "--max-parents=0", "HEAD"], execOpts); -} - -/** - * @param {import("@lerna/child-process").ExecOpts} opts - */ -function hasTags(opts) { - let result = false; - - try { - result = !!childProcess.execSync("git", ["tag"], opts); - } catch (err) { - log.warn("ENOTAGS", "No git tags were reachable from this branch!"); - log.verbose("hasTags error", err); - } - - log.verbose("hasTags", result); - - return result; -} diff --git a/commands/diff/lib/has-commit.js b/commands/diff/lib/has-commit.js deleted file mode 100644 index c7488f1fa5..0000000000 --- a/commands/diff/lib/has-commit.js +++ /dev/null @@ -1,24 +0,0 @@ -"use strict"; - -const log = require("npmlog"); -const childProcess = require("@lerna/child-process"); - -module.exports.hasCommit = hasCommit; - -/** - * @param {import("@lerna/child-process").ExecOpts} opts - */ -function hasCommit(opts) { - log.silly("hasCommit"); - let retVal; - - try { - childProcess.execSync("git", ["log"], opts); - retVal = true; - } catch (e) { - retVal = false; - } - - log.verbose("hasCommit", retVal); - return retVal; -} diff --git a/commands/diff/package.json b/commands/diff/package.json deleted file mode 100644 index 7c41c1f407..0000000000 --- a/commands/diff/package.json +++ /dev/null @@ -1,41 +0,0 @@ -{ - "name": "@lerna/diff", - "version": "6.4.1", - "description": "Diff all packages or a single package since the last release", - "keywords": [ - "lerna", - "command" - ], - "homepage": "https://lerna.js.org", - "license": "MIT", - "author": { - "name": "Daniel Stockman", - "url": "https://github.com/evocateur" - }, - "files": [ - "command.js", - "index.js", - "lib" - ], - "main": "index.js", - "engines": { - "node": "^14.15.0 || >=16.0.0" - }, - "publishConfig": { - "access": "public" - }, - "repository": { - "type": "git", - "url": "git+https://github.com/lerna/lerna.git", - "directory": "commands/diff" - }, - "scripts": { - "test": "echo \"Run tests from root\" && exit 1" - }, - "dependencies": { - "@lerna/child-process": "file:../../core/child-process", - "@lerna/command": "file:../../core/command", - "@lerna/validation-error": "file:../../core/validation-error", - "npmlog": "^6.0.2" - } -} diff --git a/commands/exec/CHANGELOG.md b/commands/exec/CHANGELOG.md deleted file mode 100644 index ce04b0b63b..0000000000 --- a/commands/exec/CHANGELOG.md +++ /dev/null @@ -1,505 +0,0 @@ -# Change Log - -All notable changes to this project will be documented in this file. -See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. - -## [6.4.1](https://github.com/lerna/lerna/compare/v6.4.0...v6.4.1) (2023-01-12) - -**Note:** Version bump only for package @lerna/exec - -# [6.4.0](https://github.com/lerna/lerna/compare/v6.3.0...v6.4.0) (2023-01-05) - -**Note:** Version bump only for package @lerna/exec - -# [6.3.0](https://github.com/lerna/lerna/compare/v6.2.0...v6.3.0) (2022-12-26) - -**Note:** Version bump only for package @lerna/exec - -# [6.2.0](https://github.com/lerna/lerna/compare/v6.1.0...v6.2.0) (2022-12-13) - -**Note:** Version bump only for package @lerna/exec - -# [6.1.0](https://github.com/lerna/lerna/compare/v6.0.3...v6.1.0) (2022-11-29) - -**Note:** Version bump only for package @lerna/exec - -## [6.0.3](https://github.com/lerna/lerna/compare/v6.0.2...v6.0.3) (2022-11-07) - -**Note:** Version bump only for package @lerna/exec - -## [6.0.2](https://github.com/lerna/lerna/compare/v6.0.1...v6.0.2) (2022-11-02) - -**Note:** Version bump only for package @lerna/exec - -## [6.0.1](https://github.com/lerna/lerna/compare/v6.0.0...v6.0.1) (2022-10-14) - -**Note:** Version bump only for package @lerna/exec - -# [6.0.0](https://github.com/lerna/lerna/compare/v6.0.0-alpha.2...v6.0.0) (2022-10-12) - -**Note:** Version bump only for package @lerna/exec - -# [6.0.0-alpha.2](https://github.com/lerna/lerna/compare/v6.0.0-alpha.1...v6.0.0-alpha.2) (2022-10-12) - -**Note:** Version bump only for package @lerna/exec - -# [6.0.0-alpha.1](https://github.com/lerna/lerna/compare/v5.6.2...v6.0.0-alpha.1) (2022-10-09) - -# [6.0.0-alpha.0](https://github.com/lerna/lerna/compare/v5.6.1...v6.0.0-alpha.0) (2022-10-07) - -**Note:** Version bump only for package @lerna/exec - -## [5.6.2](https://github.com/lerna/lerna/compare/v5.6.1...v5.6.2) (2022-10-09) - -**Note:** Version bump only for package @lerna/exec - -## [5.6.1](https://github.com/lerna/lerna/compare/v5.6.0...v5.6.1) (2022-09-30) - -**Note:** Version bump only for package @lerna/exec - -# [5.6.0](https://github.com/lerna/lerna/compare/v5.5.4...v5.6.0) (2022-09-29) - -**Note:** Version bump only for package @lerna/exec - -## [5.5.4](https://github.com/lerna/lerna/compare/v5.5.3...v5.5.4) (2022-09-28) - -**Note:** Version bump only for package @lerna/exec - -## [5.5.3](https://github.com/lerna/lerna/compare/v5.5.2...v5.5.3) (2022-09-28) - -**Note:** Version bump only for package @lerna/exec - -## [5.5.2](https://github.com/lerna/lerna/compare/v5.5.1...v5.5.2) (2022-09-20) - -**Note:** Version bump only for package @lerna/exec - -## [5.5.1](https://github.com/lerna/lerna/compare/v5.5.0...v5.5.1) (2022-09-09) - -**Note:** Version bump only for package @lerna/exec - -# [5.5.0](https://github.com/lerna/lerna/compare/v5.4.3...v5.5.0) (2022-08-31) - -**Note:** Version bump only for package @lerna/exec - -## [5.4.3](https://github.com/lerna/lerna/compare/v5.4.2...v5.4.3) (2022-08-16) - -**Note:** Version bump only for package @lerna/exec - -## [5.4.2](https://github.com/lerna/lerna/compare/v5.4.1...v5.4.2) (2022-08-14) - -**Note:** Version bump only for package @lerna/exec - -## [5.4.1](https://github.com/lerna/lerna/compare/v5.4.0...v5.4.1) (2022-08-12) - -**Note:** Version bump only for package @lerna/exec - -# [5.4.0](https://github.com/lerna/lerna/compare/v5.3.0...v5.4.0) (2022-08-08) - -**Note:** Version bump only for package @lerna/exec - -# [5.3.0](https://github.com/lerna/lerna/compare/v5.2.0...v5.3.0) (2022-07-27) - -**Note:** Version bump only for package @lerna/exec - -# [5.2.0](https://github.com/lerna/lerna/compare/v5.1.8...v5.2.0) (2022-07-22) - -**Note:** Version bump only for package @lerna/exec - -## [5.1.8](https://github.com/lerna/lerna/compare/v5.1.7...v5.1.8) (2022-07-07) - -**Note:** Version bump only for package @lerna/exec - -## [5.1.7](https://github.com/lerna/lerna/compare/v5.1.6...v5.1.7) (2022-07-06) - -**Note:** Version bump only for package @lerna/exec - -## [5.1.6](https://github.com/lerna/lerna/compare/v5.1.5...v5.1.6) (2022-06-24) - -**Note:** Version bump only for package @lerna/exec - -## [5.1.5](https://github.com/lerna/lerna/compare/v5.1.4...v5.1.5) (2022-06-24) - -**Note:** Version bump only for package @lerna/exec - -## [5.1.4](https://github.com/lerna/lerna/compare/v5.1.3...v5.1.4) (2022-06-15) - -**Note:** Version bump only for package @lerna/exec - -## [5.1.3](https://github.com/lerna/lerna/compare/v5.1.2...v5.1.3) (2022-06-15) - -**Note:** Version bump only for package @lerna/exec - -## [5.1.2](https://github.com/lerna/lerna/compare/v5.1.1...v5.1.2) (2022-06-13) - -**Note:** Version bump only for package @lerna/exec - -## [5.1.1](https://github.com/lerna/lerna/compare/v5.1.0...v5.1.1) (2022-06-09) - -### Bug Fixes - -- allow maintenance LTS node 14 engines starting at 14.15.0 ([#3161](https://github.com/lerna/lerna/issues/3161)) ([72305e4](https://github.com/lerna/lerna/commit/72305e4dbab607a2d87ae4efa6ee577c93a9dda9)) - -# [5.1.0](https://github.com/lerna/lerna/compare/v5.0.0...v5.1.0) (2022-06-07) - -**Note:** Version bump only for package @lerna/exec - -# [5.1.0-alpha.0](https://github.com/lerna/lerna/compare/v4.0.0...v5.1.0-alpha.0) (2022-05-25) - -**Note:** Version bump only for package @lerna/exec - -# [5.0.0](https://github.com/lerna/lerna/compare/v4.0.0...v5.0.0) (2022-05-24) - -**Note:** Version bump only for package @lerna/exec - -# [4.0.0](https://github.com/lerna/lerna/compare/v3.22.1...v4.0.0) (2021-02-10) - -### Features - -- Consume named exports of sibling modules ([63499e3](https://github.com/lerna/lerna/commit/63499e33652bc78fe23751875d74017e2f16a689)) -- **deps:** execa@^4.1.0 ([9051dca](https://github.com/lerna/lerna/commit/9051dcab1a68b56db09b82ab0345c5f36bcfee2d)) -- **deps:** p-map@^4.0.0 ([92b1364](https://github.com/lerna/lerna/commit/92b1364735e1f2cf379cf1047c60c4fb897d55f5)) -- Drop support for Node v6.x & v8.x ([ff4bb4d](https://github.com/lerna/lerna/commit/ff4bb4da215555e3bb136f5af09b5cbc631e57bb)) - -### BREAKING CHANGES - -- Node v6.x & v8.x are no longer supported. Please upgrade to the latest LTS release. - -Here's the gnarly one-liner I used to make these changes: - -``` -npx lerna exec --concurrency 1 --stream -- 'json -I -f package.json -e '"'"'this.engines=this.engines||{};this.engines.node=">= 10.18.0"'"'" -``` - -(requires `npm i -g json` beforehand) - -# [3.21.0](https://github.com/lerna/lerna/compare/v3.20.2...v3.21.0) (2020-05-13) - -**Note:** Version bump only for package @lerna/exec - -# [3.20.0](https://github.com/lerna/lerna/compare/v3.19.0...v3.20.0) (2019-12-27) - -### Bug Fixes - -- **collect-dependents:** Avoid skipping dependents of cyclic dependencies ([#2380](https://github.com/lerna/lerna/issues/2380)) ([bd19a34](https://github.com/lerna/lerna/commit/bd19a34debf3344e94386b4ffd4b3fe87efb4641)) - -### Features - -- Add `--profile` option to `lerna exec` and `lerna run` ([#2376](https://github.com/lerna/lerna/issues/2376)) ([6290174](https://github.com/lerna/lerna/commit/62901748f818516d58efdfd955eacb447e270351)) - -## [3.18.5](https://github.com/lerna/lerna/compare/v3.18.4...v3.18.5) (2019-11-20) - -**Note:** Version bump only for package @lerna/exec - -## [3.18.4](https://github.com/lerna/lerna/compare/v3.18.3...v3.18.4) (2019-11-08) - -### Bug Fixes - -- **filter-options:** Ensure `--include-merged-tags` is available to all `--since`-filterable commands ([287bcd8](https://github.com/lerna/lerna/commit/287bcd8b5c8dbb2dc4def5c933d0b4917c34813e)), closes [#2332](https://github.com/lerna/lerna/issues/2332) - -# [3.18.0](https://github.com/lerna/lerna/compare/v3.17.0...v3.18.0) (2019-10-15) - -### Features - -- Upgrade to yargs@14 ([5e60213](https://github.com/lerna/lerna/commit/5e60213e93e3ee229a9341a14e420ed2401001dd)) - -## [3.16.5](https://github.com/lerna/lerna/compare/v3.16.4...v3.16.5) (2019-10-07) - -**Note:** Version bump only for package @lerna/exec - -# [3.16.0](https://github.com/lerna/lerna/compare/v3.15.0...v3.16.0) (2019-07-18) - -### Bug Fixes - -- **package-graph:** Flatten cycles to avoid skipping packages ([#2185](https://github.com/lerna/lerna/issues/2185)) ([b335763](https://github.com/lerna/lerna/commit/b335763)) - -### Features - -- **deps:** `p-map@^2.1.0` ([9e58394](https://github.com/lerna/lerna/commit/9e58394)) - -# [3.15.0](https://github.com/lerna/lerna/compare/v3.14.2...v3.15.0) (2019-06-09) - -**Note:** Version bump only for package @lerna/exec - -## [3.14.2](https://github.com/lerna/lerna/compare/v3.14.1...v3.14.2) (2019-06-09) - -**Note:** Version bump only for package @lerna/exec - -# [3.14.0](https://github.com/lerna/lerna/compare/v3.13.4...v3.14.0) (2019-05-14) - -### Features - -- **exec:** Add just-in-time queue management ([23736e5](https://github.com/lerna/lerna/commit/23736e5)) - -## [3.13.3](https://github.com/lerna/lerna/compare/v3.13.2...v3.13.3) (2019-04-17) - -### Bug Fixes - -- **child-process:** Centralize `exitCode` translation from string codes into numbers ([09c0103](https://github.com/lerna/lerna/commit/09c0103)), closes [#2031](https://github.com/lerna/lerna/issues/2031) -- **exec:** Handle node string error codes before setting process.exitCode ([#2031](https://github.com/lerna/lerna/issues/2031)) ([c599c64](https://github.com/lerna/lerna/commit/c599c64)) - -## [3.13.1](https://github.com/lerna/lerna/compare/v3.13.0...v3.13.1) (2019-02-26) - -**Note:** Version bump only for package @lerna/exec - -# [3.13.0](https://github.com/lerna/lerna/compare/v3.12.1...v3.13.0) (2019-02-15) - -### Features - -- **meta:** Add `repository.directory` field to package.json ([aec5023](https://github.com/lerna/lerna/commit/aec5023)) -- **meta:** Normalize package.json `homepage` field ([abeb4dc](https://github.com/lerna/lerna/commit/abeb4dc)) - -## [3.12.1](https://github.com/lerna/lerna/compare/v3.12.0...v3.12.1) (2019-02-14) - -**Note:** Version bump only for package @lerna/exec - -# [3.12.0](https://github.com/lerna/lerna/compare/v3.11.1...v3.12.0) (2019-02-14) - -**Note:** Version bump only for package @lerna/exec - -# [3.11.0](https://github.com/lerna/lerna/compare/v3.10.8...v3.11.0) (2019-02-08) - -**Note:** Version bump only for package @lerna/exec - -## [3.10.6](https://github.com/lerna/lerna/compare/v3.10.5...v3.10.6) (2019-01-19) - -### Bug Fixes - -- **exec:** Tweak description ([68a0685](https://github.com/lerna/lerna/commit/68a0685)) -- **options:** Document negated boolean options explicitly ([8bc9669](https://github.com/lerna/lerna/commit/8bc9669)) - -## [3.10.1](https://github.com/lerna/lerna/compare/v3.10.0...v3.10.1) (2019-01-09) - -**Note:** Version bump only for package @lerna/exec - -# [3.10.0](https://github.com/lerna/lerna/compare/v3.9.1...v3.10.0) (2019-01-08) - -**Note:** Version bump only for package @lerna/exec - -# [3.9.0](https://github.com/lerna/lerna/compare/v3.8.5...v3.9.0) (2019-01-08) - -**Note:** Version bump only for package @lerna/exec - -## [3.8.5](https://github.com/lerna/lerna/compare/v3.8.4...v3.8.5) (2019-01-05) - -**Note:** Version bump only for package @lerna/exec - -## [3.8.1](https://github.com/lerna/lerna/compare/v3.8.0...v3.8.1) (2018-12-31) - -**Note:** Version bump only for package @lerna/exec - -## [3.7.2](https://github.com/lerna/lerna/compare/v3.7.1...v3.7.2) (2018-12-21) - -**Note:** Version bump only for package @lerna/exec - -## [3.7.1](https://github.com/lerna/lerna/compare/v3.7.0...v3.7.1) (2018-12-20) - -**Note:** Version bump only for package @lerna/exec - -# [3.7.0](https://github.com/lerna/lerna/compare/v3.6.0...v3.7.0) (2018-12-19) - -**Note:** Version bump only for package @lerna/exec - -# [3.6.0](https://github.com/lerna/lerna/compare/v3.5.1...v3.6.0) (2018-12-07) - -**Note:** Version bump only for package @lerna/exec - -# [3.5.0](https://github.com/lerna/lerna/compare/v3.4.3...v3.5.0) (2018-11-27) - -**Note:** Version bump only for package @lerna/exec - - - -## [3.3.2](https://github.com/lerna/lerna/compare/v3.3.1...v3.3.2) (2018-09-12) - -**Note:** Version bump only for package @lerna/exec - - - -# [3.3.0](https://github.com/lerna/lerna/compare/v3.2.1...v3.3.0) (2018-09-06) - -### Bug Fixes - -- Propagate exit codes from failed executions ([af9c70b](https://github.com/lerna/lerna/commit/af9c70b)), closes [#1374](https://github.com/lerna/lerna/issues/1374) [#1653](https://github.com/lerna/lerna/issues/1653) - - - -## [3.1.3](https://github.com/lerna/lerna/compare/v3.1.2...v3.1.3) (2018-08-21) - -**Note:** Version bump only for package @lerna/exec - - - -## [3.1.2](https://github.com/lerna/lerna/compare/v3.1.1...v3.1.2) (2018-08-20) - -### Bug Fixes - -- Setup instance.filteredPackages explicitly ([32357f8](https://github.com/lerna/lerna/commit/32357f8)) - - - -# [3.1.0](https://github.com/lerna/lerna/compare/v3.0.6...v3.1.0) (2018-08-17) - -**Note:** Version bump only for package @lerna/exec - - - -## [3.0.6](https://github.com/lerna/lerna/compare/v3.0.5...v3.0.6) (2018-08-16) - -**Note:** Version bump only for package @lerna/exec - - - -## [3.0.5](https://github.com/lerna/lerna/compare/v3.0.4...v3.0.5) (2018-08-15) - -**Note:** Version bump only for package @lerna/exec - - - -## [3.0.2](https://github.com/lerna/lerna/compare/v3.0.1...v3.0.2) (2018-08-11) - -### Bug Fixes - -- **exec:** Allow config files to override defaults ([2335149](https://github.com/lerna/lerna/commit/2335149)) - - - -# [3.0.0](https://github.com/lerna/lerna/compare/v3.0.0-rc.0...v3.0.0) (2018-08-10) - -**Note:** Version bump only for package @lerna/exec - - - -# [3.0.0-rc.0](https://github.com/lerna/lerna/compare/v3.0.0-beta.21...v3.0.0-rc.0) (2018-07-27) - -### Features - -- Add description from --help summary [skip ci] ([9b65d8e](https://github.com/lerna/lerna/commit/9b65d8e)) -- **cli:** Upgrade to Yargs 12 ([7899ab8](https://github.com/lerna/lerna/commit/7899ab8)) -- **command:** Remove .defaultOptions() from option resolution stack ([2b27a54](https://github.com/lerna/lerna/commit/2b27a54)) -- Count packages affected in command summary logging ([5f5e585](https://github.com/lerna/lerna/commit/5f5e585)) - - - -# [3.0.0-beta.21](https://github.com/lerna/lerna/compare/v3.0.0-beta.20...v3.0.0-beta.21) (2018-05-12) - -### Bug Fixes - -- **child-process:** Prevent duplicate logs when any package-oriented execution fails ([d3a8128](https://github.com/lerna/lerna/commit/d3a8128)) - - - -# [3.0.0-beta.20](https://github.com/lerna/lerna/compare/v3.0.0-beta.19...v3.0.0-beta.20) (2018-05-07) - -**Note:** Version bump only for package @lerna/exec - - - -# [3.0.0-beta.19](https://github.com/lerna/lerna/compare/v3.0.0-beta.18...v3.0.0-beta.19) (2018-05-03) - -**Note:** Version bump only for package @lerna/exec - - - -# [3.0.0-beta.18](https://github.com/lerna/lerna/compare/v3.0.0-beta.17...v3.0.0-beta.18) (2018-04-24) - -**Note:** Version bump only for package @lerna/exec - - - -# [3.0.0-beta.17](https://github.com/lerna/lerna/compare/v3.0.0-beta.16...v3.0.0-beta.17) (2018-04-13) - -**Note:** Version bump only for package @lerna/exec - - - -# [3.0.0-beta.15](https://github.com/lerna/lerna/compare/v3.0.0-beta.14...v3.0.0-beta.15) (2018-04-09) - -**Note:** Version bump only for package @lerna/exec - - - -# [3.0.0-beta.14](https://github.com/lerna/lerna/compare/v3.0.0-beta.13...v3.0.0-beta.14) (2018-04-03) - -### Bug Fixes - -- **logging:** Log failures from package scripts once, not twice ([436cfe1](https://github.com/lerna/lerna/commit/436cfe1)) - - - -# [3.0.0-beta.13](https://github.com/lerna/lerna/compare/v3.0.0-beta.12...v3.0.0-beta.13) (2018-03-31) - -### Bug Fixes - -- Use ValidationError instead of Error ([bea6bc3](https://github.com/lerna/lerna/commit/bea6bc3)) - -### Features - -- Enable progress bars only when necessary ([b766c83](https://github.com/lerna/lerna/commit/b766c83)) - - - -# [3.0.0-beta.12](https://github.com/lerna/lerna/compare/v3.0.0-beta.11...v3.0.0-beta.12) (2018-03-30) - -### Features - -- Add --no-prefix for streaming output ([#1352](https://github.com/lerna/lerna/issues/1352)) ([36c1fad](https://github.com/lerna/lerna/commit/36c1fad)) - - - -# [3.0.0-beta.11](https://github.com/lerna/lerna/compare/v3.0.0-beta.10...v3.0.0-beta.11) (2018-03-29) - -### Bug Fixes - -- **exec:** Clarify --no-bail option ([6e4c6fd](https://github.com/lerna/lerna/commit/6e4c6fd)) - - - -# [3.0.0-beta.10](https://github.com/lerna/lerna/compare/v3.0.0-beta.9...v3.0.0-beta.10) (2018-03-27) - -### Features - -- **commands:** Delay require of command instantiation ([a1284f3](https://github.com/lerna/lerna/commit/a1284f3)) - -### BREAKING CHANGES - -- **commands:** The default export of command packages is now a factory, not the subclass (which is now a named export). - - - -# [3.0.0-beta.9](https://github.com/lerna/lerna/compare/v3.0.0-beta.8...v3.0.0-beta.9) (2018-03-24) - -### Features - -- **command:** Rename this.repository -> this.project ([43e98a0](https://github.com/lerna/lerna/commit/43e98a0)) - - - -# [3.0.0-beta.7](https://github.com/lerna/lerna/compare/v3.0.0-beta.6...v3.0.0-beta.7) (2018-03-20) - -**Note:** Version bump only for package @lerna/exec - - - -# [3.0.0-beta.4](https://github.com/lerna/lerna/compare/v3.0.0-beta.3...v3.0.0-beta.4) (2018-03-19) - -**Note:** Version bump only for package @lerna/exec - - - -# [3.0.0-beta.3](https://github.com/lerna/lerna/compare/v3.0.0-beta.2...v3.0.0-beta.3) (2018-03-15) - -**Note:** Version bump only for package @lerna/exec - - - -# [3.0.0-beta.2](https://github.com/lerna/lerna/compare/v3.0.0-beta.1...v3.0.0-beta.2) (2018-03-10) - -**Note:** Version bump only for package @lerna/exec - - - -# [3.0.0-beta.1](https://github.com/lerna/lerna/compare/v3.0.0-beta.0...v3.0.0-beta.1) (2018-03-09) - -### Bug Fixes - -- **filter-options:** require a git repo when using --since ([d21b66e](https://github.com/lerna/lerna/commit/d21b66e)), closes [#822](https://github.com/lerna/lerna/issues/822) diff --git a/commands/exec/README.md b/commands/exec/README.md deleted file mode 100644 index 529210d807..0000000000 --- a/commands/exec/README.md +++ /dev/null @@ -1,105 +0,0 @@ -# `@lerna/exec` - -> Execute an arbitrary command in each package - -Install [lerna](https://www.npmjs.com/package/lerna) for access to the `lerna` CLI. - -## Usage - -```sh -$ lerna exec -- [..args] # runs the command in all packages -$ lerna exec -- rm -rf ./node_modules -$ lerna exec -- protractor conf.js -``` - -Run an arbitrary command in each package. -A double-dash (`--`) is necessary to pass dashed flags to the spawned command, but is not necessary when all the arguments are positional. - -The name of the current package is available through the environment variable `LERNA_PACKAGE_NAME`: - -```sh -$ lerna exec -- npm view \$LERNA_PACKAGE_NAME -``` - -You may also run a script located in the root dir, in a complicated dir structure through the environment variable `LERNA_ROOT_PATH`: - -```sh -$ lerna exec -- node \$LERNA_ROOT_PATH/scripts/some-script.js -``` - -## Options - -`lerna exec` accepts all [filter flags](https://www.npmjs.com/package/@lerna/filter-options). - -```sh -$ lerna exec --scope my-component -- ls -la -``` - -> The commands are spawned in parallel, using the concurrency given (except with `--parallel`). -> The output is piped through, so not deterministic. -> If you want to run the command in one package after another, use it like this: - -```sh -$ lerna exec --concurrency 1 -- ls -la -``` - -### `--stream` - -Stream output from child processes immediately, prefixed with the originating -package name. This allows output from different packages to be interleaved. - -```sh -$ lerna exec --stream -- babel src -d lib -``` - -### `--parallel` - -Similar to `--stream`, but completely disregards concurrency and topological sorting, running a given command or script immediately in all matching packages with prefixed streaming output. This is the preferred flag for long-running processes such as `babel src -d lib -w` run over many packages. - -```sh -$ lerna exec --parallel -- babel src -d lib -w -``` - -> **Note:** It is advised to constrain the scope of this command when using -> the `--parallel` flag, as spawning dozens of subprocesses may be -> harmful to your shell's equanimity (or maximum file descriptor limit, -> for example). YMMV - -### `--no-bail` - -```sh -# Run a command, ignoring non-zero (error) exit codes -$ lerna exec --no-bail -``` - -By default, `lerna exec` will exit with an error if _any_ execution returns a non-zero exit code. -Pass `--no-bail` to disable this behavior, executing in _all_ packages regardless of exit code. - -### `--no-prefix` - -Disable package name prefixing when output is streaming (`--stream` _or_ `--parallel`). -This option can be useful when piping results to other processes, such as editor plugins. - -### `--profile` - -Profiles the command executions and produces a performance profile which can be analyzed using DevTools in a -Chromium-based browser (direct url: `devtools://devtools/bundled/devtools_app.html`). The profile shows a timeline of -the command executions where each execution is assigned to an open slot. The number of slots is determined by the -`--concurrency` option and the number of open slots is determined by `--concurrency` minus the number of ongoing -operations. The end result is a visualization of the parallel execution of your commands. - -The default location of the performance profile output is at the root of your project. - -```sh -$ lerna exec --profile -- -``` - -> **Note:** Lerna will only profile when topological sorting is enabled (i.e. without `--parallel` and `--no-sort`). - -### `--profile-location ` - -You can provide a custom location for the performance profile output. The path provided will be resolved relative to the current working directory. - -```sh -$ lerna exec --profile --profile-location=logs/profile/ -- -``` diff --git a/commands/exec/__tests__/__fixtures__/include-filtered-dependencies/packages/package-2/package.json b/commands/exec/__tests__/__fixtures__/include-filtered-dependencies/packages/package-2/package.json deleted file mode 100644 index bc751b727c..0000000000 --- a/commands/exec/__tests__/__fixtures__/include-filtered-dependencies/packages/package-2/package.json +++ /dev/null @@ -1,7 +0,0 @@ -{ - "name": "@test/package-2", - "version": "1.0.0", - "dependencies": { - "@test/package-1": "1.0.0" - } -} diff --git a/commands/exec/__tests__/exec-command.test.js b/commands/exec/__tests__/exec-command.test.js deleted file mode 100644 index fa7c43e350..0000000000 --- a/commands/exec/__tests__/exec-command.test.js +++ /dev/null @@ -1,281 +0,0 @@ -"use strict"; - -const path = require("path"); -const fs = require("fs-extra"); -const globby = require("globby"); - -// mocked modules -const childProcess = require("@lerna/child-process"); - -// helpers -const initFixture = require("@lerna-test/helpers").initFixtureFactory(__dirname); -const { loggingOutput } = require("@lerna-test/helpers/logging-output"); -const { normalizeRelativeDir } = require("@lerna-test/helpers"); - -// file under test -const lernaExec = require("@lerna-test/helpers").commandRunner(require("../command")); - -// assertion helpers -const calledInPackages = () => childProcess.spawn.mock.calls.map(([, , opts]) => path.basename(opts.cwd)); - -const execInPackagesStreaming = (testDir) => - childProcess.spawnStreaming.mock.calls.reduce((arr, [command, params, opts, prefix]) => { - const dir = normalizeRelativeDir(testDir, opts.cwd); - arr.push([dir, command, `(prefix: ${prefix})`].concat(params).join(" ")); - return arr; - }, []); - -describe("ExecCommand", () => { - // TODO: it's very suspicious that mockResolvedValue() doesn't work here - childProcess.spawn = jest.fn(() => Promise.resolve({ exitCode: 0 })); - childProcess.spawnStreaming = jest.fn(() => Promise.resolve({ exitCode: 0 })); - - afterEach(() => { - process.exitCode = undefined; - }); - - describe("in a basic repo", () => { - // working dir is never mutated - let testDir; - - beforeAll(async () => { - testDir = await initFixture("basic"); - }); - - it("should complain if invoked without command", async () => { - const command = lernaExec(testDir)("--parallel"); - - await expect(command).rejects.toThrow("A command to execute is required"); - }); - - it("rejects with execution error", async () => { - childProcess.spawn.mockImplementationOnce((cmd, args) => { - const boom = new Error("execution error"); - - boom.failed = true; - boom.exitCode = 123; - boom.command = [cmd].concat(args).join(" "); - - throw boom; - }); - - const command = lernaExec(testDir)("boom"); - - await expect(command).rejects.toThrow( - expect.objectContaining({ - message: "execution error", - command: "boom", - }) - ); - expect(process.exitCode).toBe(123); - }); - - it("should ignore execution errors with --no-bail", async () => { - childProcess.spawn.mockImplementationOnce((cmd, args, { pkg }) => { - const boom = new Error(pkg.name); - - boom.failed = true; - boom.exitCode = 456; - boom.cmd = [cmd].concat(args).join(" "); - - // --no-bail passes { reject: false } to execa, so throwing is inappropriate - return Promise.resolve(boom); - }); - - await lernaExec(testDir)("boom", "--no-bail", "--", "--shaka", "--lakka"); - - // command doesn't throw, but it _does_ set exitCode - expect(process.exitCode).toBe(456); - - expect(childProcess.spawn).toHaveBeenCalledTimes(2); - expect(childProcess.spawn).toHaveBeenLastCalledWith( - "boom", - ["--shaka", "--lakka"], - expect.objectContaining({ - reject: false, - }) - ); - }); - - it("should filter packages with `ignore`", async () => { - await lernaExec(testDir)("ls", "--ignore", "package-1"); - - expect(childProcess.spawn).toHaveBeenCalledTimes(1); - expect(childProcess.spawn).toHaveBeenLastCalledWith("ls", [], { - cwd: path.join(testDir, "packages/package-2"), - pkg: expect.objectContaining({ - name: "package-2", - }), - env: expect.objectContaining({ - LERNA_PACKAGE_NAME: "package-2", - LERNA_ROOT_PATH: testDir, - }), - extendEnv: false, - reject: true, - shell: true, - }); - }); - - it("should run a command", async () => { - await lernaExec(testDir)("ls"); - - expect(childProcess.spawn).toHaveBeenCalledTimes(2); - expect(calledInPackages()).toEqual(["package-1", "package-2"]); - }); - - it("should run a command with parameters", async () => { - await lernaExec(testDir)("ls", "--", "-la"); - - expect(childProcess.spawn).toHaveBeenCalledTimes(2); - expect(childProcess.spawn).toHaveBeenLastCalledWith("ls", ["-la"], expect.any(Object)); - }); - - it("runs a command for a given scope", async () => { - await lernaExec(testDir)("ls", "--scope", "package-1"); - - expect(calledInPackages()).toEqual(["package-1"]); - }); - - it("does not run a command for ignored packages", async () => { - await lernaExec(testDir)("ls", "--ignore", "package-@(2|3|4)"); - - expect(calledInPackages()).toEqual(["package-1"]); - }); - - it("executes a command in all packages with --parallel", async () => { - await lernaExec(testDir)("--parallel", "ls"); - - expect(execInPackagesStreaming(testDir)).toEqual([ - "packages/package-1 ls (prefix: package-1)", - "packages/package-2 ls (prefix: package-2)", - ]); - }); - - it("omits package prefix with --parallel --no-prefix", async () => { - await lernaExec(testDir)("--parallel", "--no-prefix", "ls"); - - expect(execInPackagesStreaming(testDir)).toEqual([ - "packages/package-1 ls (prefix: false)", - "packages/package-2 ls (prefix: false)", - ]); - }); - - it("executes a command in all packages with --stream", async () => { - await lernaExec(testDir)("--stream", "ls"); - - expect(execInPackagesStreaming(testDir)).toEqual([ - "packages/package-1 ls (prefix: package-1)", - "packages/package-2 ls (prefix: package-2)", - ]); - }); - - it("omits package prefix with --stream --no-prefix", async () => { - await lernaExec(testDir)("--stream", "--no-prefix", "ls"); - - expect(execInPackagesStreaming(testDir)).toEqual([ - "packages/package-1 ls (prefix: false)", - "packages/package-2 ls (prefix: false)", - ]); - }); - - it("does not explode with filter flags", async () => { - await lernaExec(testDir)( - "ls", - "--no-private", - "--since", - "--include-merged-tags", - "--exclude-dependents", - "--include-dependencies" - ); - - expect(calledInPackages()).toEqual(["package-1", "package-2"]); - }); - }); - - describe("with --profile", () => { - it("executes a profiled command in all packages", async () => { - const cwd = await initFixture("basic"); - - await lernaExec(cwd)("--profile", "--", "ls"); - - const [profileLocation] = await globby("Lerna-Profile-*.json", { cwd, absolute: true }); - const json = await fs.readJson(profileLocation); - - expect(json).toMatchObject([ - { - name: "package-1", - ph: "X", - ts: expect.any(Number), - pid: 1, - tid: expect.any(Number), - dur: expect.any(Number), - }, - { - name: "package-2", - }, - ]); - }); - - it("accepts --profile-location", async () => { - const cwd = await initFixture("basic"); - - await lernaExec(cwd)("--profile", "--profile-location", "foo/bar", "--", "ls"); - - const [profileLocation] = await globby("foo/bar/Lerna-Profile-*.json", { cwd, absolute: true }); - const exists = await fs.exists(profileLocation); - - expect(exists).toBe(true); - }); - }); - - describe("with --no-sort", () => { - it("runs commands in lexical (not topological) order", async () => { - const testDir = await initFixture("toposort"); - - await lernaExec(testDir)("ls", "--no-sort"); - - expect(calledInPackages()).toEqual([ - "package-cycle-1", - "package-cycle-2", - "package-cycle-extraneous-1", - "package-cycle-extraneous-2", - "package-dag-1", - "package-dag-2a", - "package-dag-2b", - "package-dag-3", - "package-standalone", - ]); - }); - }); - - describe("in a cyclical repo", () => { - it("warns when cycles are encountered", async () => { - const testDir = await initFixture("toposort"); - - await lernaExec(testDir)("ls", "--concurrency", "1"); - - const [logMessage] = loggingOutput("warn"); - expect(logMessage).toMatch("Dependency cycles detected, you should fix these!"); - expect(logMessage).toMatch("package-cycle-1 -> package-cycle-2 -> package-cycle-1"); - - expect(calledInPackages()).toEqual([ - "package-dag-1", - "package-standalone", - "package-dag-2a", - "package-dag-2b", - "package-cycle-1", - "package-cycle-2", - "package-dag-3", - "package-cycle-extraneous-1", - "package-cycle-extraneous-2", - ]); - }); - - it("throws an error with --reject-cycles", async () => { - const testDir = await initFixture("toposort"); - const command = lernaExec(testDir)("ls", "--reject-cycles"); - - await expect(command).rejects.toThrow("Dependency cycles detected, you should fix these!"); - }); - }); -}); diff --git a/commands/exec/command.js b/commands/exec/command.js deleted file mode 100644 index 5e97dd2ca6..0000000000 --- a/commands/exec/command.js +++ /dev/null @@ -1,77 +0,0 @@ -"use strict"; - -const { filterOptions } = require("@lerna/filter-options"); - -/** - * @see https://github.com/yargs/yargs/blob/master/docs/advanced.md#providing-a-command-module - */ -exports.command = "exec [cmd] [args..]"; - -exports.describe = "Execute an arbitrary command in each package"; - -exports.builder = (yargs) => { - yargs - .example("$0 exec ls -- --la", "# execute `ls -la` in all packages") - .example("$0 exec -- ls --la", "# execute `ls -la` in all packages, keeping cmd outside") - .parserConfiguration({ - "populate--": true, - }) - .positional("cmd", { - describe: "The command to execute. Any command flags must be passed after --", - type: "string", - }) - .positional("args", { - describe: "Positional arguments (not recognized by lerna) to send to command", - type: "string", - }) - .options({ - stream: { - group: "Command Options:", - describe: "Stream output with lines prefixed by originating package name.", - type: "boolean", - }, - parallel: { - group: "Command Options:", - describe: "Execute command with unlimited concurrency, streaming prefixed output.", - type: "boolean", - }, - "no-bail": { - group: "Command Options:", - describe: "Continue executing command despite non-zero exit in a given package.", - type: "boolean", - }, - bail: { - // proxy for --no-bail - hidden: true, - type: "boolean", - }, - // This option controls prefix for stream output so that it can be disabled to be friendly - // to tools like Visual Studio Code to highlight the raw results - "no-prefix": { - group: "Command Options:", - describe: "Do not prefix streaming output.", - type: "boolean", - }, - prefix: { - // proxy for --no-prefix - hidden: true, - type: "boolean", - }, - profile: { - group: "Command Options:", - describe: "Profile command executions and output performance profile to default location.", - type: "boolean", - }, - "profile-location": { - group: "Command Options:", - describe: "Output performance profile to custom location instead of default project root.", - type: "string", - }, - }); - - return filterOptions(yargs); -}; - -exports.handler = function handler(argv) { - return require(".")(argv); -}; diff --git a/commands/exec/index.js b/commands/exec/index.js deleted file mode 100644 index 7c8598369a..0000000000 --- a/commands/exec/index.js +++ /dev/null @@ -1,175 +0,0 @@ -"use strict"; - -const pMap = require("p-map"); - -const childProcess = require("@lerna/child-process"); -const { Command } = require("@lerna/command"); -const { Profiler } = require("@lerna/profiler"); -const { runTopologically } = require("@lerna/run-topologically"); -const { ValidationError } = require("@lerna/validation-error"); -const { getFilteredPackages } = require("@lerna/filter-options"); - -module.exports = factory; - -function factory(argv) { - return new ExecCommand(argv); -} - -class ExecCommand extends Command { - get requiresGit() { - return false; - } - - initialize() { - const dashedArgs = this.options["--"] || []; - - this.command = this.options.cmd || dashedArgs.shift(); - this.args = (this.options.args || []).concat(dashedArgs); - - if (!this.command) { - throw new ValidationError("ENOCOMMAND", "A command to execute is required"); - } - - // inverted boolean options - this.bail = this.options.bail !== false; - this.prefix = this.options.prefix !== false; - - // accessing properties of process.env can be expensive, - // so cache it here to reduce churn during tighter loops - this.env = Object.assign({}, process.env); - - let chain = Promise.resolve(); - - chain = chain.then(() => getFilteredPackages(this.packageGraph, this.execOpts, this.options)); - chain = chain.then((filteredPackages) => { - this.filteredPackages = filteredPackages; - }); - - return chain.then(() => { - this.count = this.filteredPackages.length; - this.packagePlural = this.count === 1 ? "package" : "packages"; - this.joinedCommand = [this.command].concat(this.args).join(" "); - }); - } - - execute() { - this.logger.info( - "", - "Executing command in %d %s: %j", - this.count, - this.packagePlural, - this.joinedCommand - ); - - let chain = Promise.resolve(); - - if (this.options.parallel) { - chain = chain.then(() => this.runCommandInPackagesParallel()); - } else if (this.toposort) { - chain = chain.then(() => this.runCommandInPackagesTopological()); - } else { - chain = chain.then(() => this.runCommandInPackagesLexical()); - } - - if (this.bail) { - // only the first error is caught - chain = chain.catch((err) => { - process.exitCode = err.exitCode; - - // rethrow to halt chain and log properly - throw err; - }); - } else { - // detect error (if any) from collected results - chain = chain.then((results) => { - /* istanbul ignore else */ - if (results.some((result) => result.failed)) { - // propagate "highest" error code, it's probably the most useful - const codes = results.filter((result) => result.failed).map((result) => result.exitCode); - const exitCode = Math.max(...codes, 1); - - this.logger.error("", "Received non-zero exit code %d during execution", exitCode); - process.exitCode = exitCode; - } - }); - } - - return chain.then(() => { - this.logger.success( - "exec", - "Executed command in %d %s: %j", - this.count, - this.packagePlural, - this.joinedCommand - ); - }); - } - - getOpts(pkg) { - // these options are passed _directly_ to execa - return { - cwd: pkg.location, - shell: true, - extendEnv: false, - env: Object.assign({}, this.env, { - LERNA_PACKAGE_NAME: pkg.name, - LERNA_ROOT_PATH: this.project.rootPath, - }), - reject: this.bail, - pkg, - }; - } - - getRunner() { - return this.options.stream - ? (pkg) => this.runCommandInPackageStreaming(pkg) - : (pkg) => this.runCommandInPackageCapturing(pkg); - } - - runCommandInPackagesTopological() { - let profiler; - let runner; - - if (this.options.profile) { - profiler = new Profiler({ - concurrency: this.concurrency, - log: this.logger, - outputDirectory: this.options.profileLocation || this.project.rootPath, - }); - - const callback = this.getRunner(); - runner = (pkg) => profiler.run(() => callback(pkg), pkg.name); - } else { - runner = this.getRunner(); - } - - let chain = runTopologically(this.filteredPackages, runner, { - concurrency: this.concurrency, - rejectCycles: this.options.rejectCycles, - }); - - if (profiler) { - chain = chain.then((results) => profiler.output().then(() => results)); - } - - return chain; - } - - runCommandInPackagesParallel() { - return pMap(this.filteredPackages, (pkg) => this.runCommandInPackageStreaming(pkg)); - } - - runCommandInPackagesLexical() { - return pMap(this.filteredPackages, this.getRunner(), { concurrency: this.concurrency }); - } - - runCommandInPackageStreaming(pkg) { - return childProcess.spawnStreaming(this.command, this.args, this.getOpts(pkg), this.prefix && pkg.name); - } - - runCommandInPackageCapturing(pkg) { - return childProcess.spawn(this.command, this.args, this.getOpts(pkg)); - } -} - -module.exports.ExecCommand = ExecCommand; diff --git a/commands/exec/package.json b/commands/exec/package.json deleted file mode 100644 index a1924596df..0000000000 --- a/commands/exec/package.json +++ /dev/null @@ -1,43 +0,0 @@ -{ - "name": "@lerna/exec", - "version": "6.4.1", - "description": "Execute an arbitrary command in each package", - "keywords": [ - "lerna", - "command" - ], - "homepage": "https://lerna.js.org", - "license": "MIT", - "author": { - "name": "Daniel Stockman", - "url": "https://github.com/evocateur" - }, - "files": [ - "command.js", - "index.js" - ], - "main": "index.js", - "engines": { - "node": "^14.15.0 || >=16.0.0" - }, - "publishConfig": { - "access": "public" - }, - "repository": { - "type": "git", - "url": "git+https://github.com/lerna/lerna.git", - "directory": "commands/exec" - }, - "scripts": { - "test": "echo \"Run tests from root\" && exit 1" - }, - "dependencies": { - "@lerna/child-process": "file:../../core/child-process", - "@lerna/command": "file:../../core/command", - "@lerna/filter-options": "file:../../core/filter-options", - "@lerna/profiler": "file:../../utils/profiler", - "@lerna/run-topologically": "file:../../utils/run-topologically", - "@lerna/validation-error": "file:../../core/validation-error", - "p-map": "^4.0.0" - } -} diff --git a/commands/import/CHANGELOG.md b/commands/import/CHANGELOG.md deleted file mode 100644 index 9f8e0ec8f9..0000000000 --- a/commands/import/CHANGELOG.md +++ /dev/null @@ -1,491 +0,0 @@ -# Change Log - -All notable changes to this project will be documented in this file. -See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. - -## [6.4.1](https://github.com/lerna/lerna/compare/v6.4.0...v6.4.1) (2023-01-12) - -**Note:** Version bump only for package @lerna/import - -# [6.4.0](https://github.com/lerna/lerna/compare/v6.3.0...v6.4.0) (2023-01-05) - -**Note:** Version bump only for package @lerna/import - -# [6.3.0](https://github.com/lerna/lerna/compare/v6.2.0...v6.3.0) (2022-12-26) - -**Note:** Version bump only for package @lerna/import - -# [6.2.0](https://github.com/lerna/lerna/compare/v6.1.0...v6.2.0) (2022-12-13) - -**Note:** Version bump only for package @lerna/import - -# [6.1.0](https://github.com/lerna/lerna/compare/v6.0.3...v6.1.0) (2022-11-29) - -**Note:** Version bump only for package @lerna/import - -## [6.0.3](https://github.com/lerna/lerna/compare/v6.0.2...v6.0.3) (2022-11-07) - -**Note:** Version bump only for package @lerna/import - -## [6.0.2](https://github.com/lerna/lerna/compare/v6.0.1...v6.0.2) (2022-11-02) - -**Note:** Version bump only for package @lerna/import - -## [6.0.1](https://github.com/lerna/lerna/compare/v6.0.0...v6.0.1) (2022-10-14) - -**Note:** Version bump only for package @lerna/import - -# [6.0.0](https://github.com/lerna/lerna/compare/v6.0.0-alpha.2...v6.0.0) (2022-10-12) - -**Note:** Version bump only for package @lerna/import - -# [6.0.0-alpha.2](https://github.com/lerna/lerna/compare/v6.0.0-alpha.1...v6.0.0-alpha.2) (2022-10-12) - -**Note:** Version bump only for package @lerna/import - -# [6.0.0-alpha.1](https://github.com/lerna/lerna/compare/v5.6.2...v6.0.0-alpha.1) (2022-10-09) - -# [6.0.0-alpha.0](https://github.com/lerna/lerna/compare/v5.6.1...v6.0.0-alpha.0) (2022-10-07) - -**Note:** Version bump only for package @lerna/import - -## [5.6.2](https://github.com/lerna/lerna/compare/v5.6.1...v5.6.2) (2022-10-09) - -**Note:** Version bump only for package @lerna/import - -## [5.6.1](https://github.com/lerna/lerna/compare/v5.6.0...v5.6.1) (2022-09-30) - -**Note:** Version bump only for package @lerna/import - -# [5.6.0](https://github.com/lerna/lerna/compare/v5.5.4...v5.6.0) (2022-09-29) - -**Note:** Version bump only for package @lerna/import - -## [5.5.4](https://github.com/lerna/lerna/compare/v5.5.3...v5.5.4) (2022-09-28) - -**Note:** Version bump only for package @lerna/import - -## [5.5.3](https://github.com/lerna/lerna/compare/v5.5.2...v5.5.3) (2022-09-28) - -**Note:** Version bump only for package @lerna/import - -## [5.5.2](https://github.com/lerna/lerna/compare/v5.5.1...v5.5.2) (2022-09-20) - -**Note:** Version bump only for package @lerna/import - -## [5.5.1](https://github.com/lerna/lerna/compare/v5.5.0...v5.5.1) (2022-09-09) - -**Note:** Version bump only for package @lerna/import - -# [5.5.0](https://github.com/lerna/lerna/compare/v5.4.3...v5.5.0) (2022-08-31) - -**Note:** Version bump only for package @lerna/import - -## [5.4.3](https://github.com/lerna/lerna/compare/v5.4.2...v5.4.3) (2022-08-16) - -**Note:** Version bump only for package @lerna/import - -## [5.4.2](https://github.com/lerna/lerna/compare/v5.4.1...v5.4.2) (2022-08-14) - -**Note:** Version bump only for package @lerna/import - -## [5.4.1](https://github.com/lerna/lerna/compare/v5.4.0...v5.4.1) (2022-08-12) - -**Note:** Version bump only for package @lerna/import - -# [5.4.0](https://github.com/lerna/lerna/compare/v5.3.0...v5.4.0) (2022-08-08) - -**Note:** Version bump only for package @lerna/import - -# [5.3.0](https://github.com/lerna/lerna/compare/v5.2.0...v5.3.0) (2022-07-27) - -**Note:** Version bump only for package @lerna/import - -# [5.2.0](https://github.com/lerna/lerna/compare/v5.1.8...v5.2.0) (2022-07-22) - -**Note:** Version bump only for package @lerna/import - -## [5.1.8](https://github.com/lerna/lerna/compare/v5.1.7...v5.1.8) (2022-07-07) - -**Note:** Version bump only for package @lerna/import - -## [5.1.7](https://github.com/lerna/lerna/compare/v5.1.6...v5.1.7) (2022-07-06) - -**Note:** Version bump only for package @lerna/import - -## [5.1.6](https://github.com/lerna/lerna/compare/v5.1.5...v5.1.6) (2022-06-24) - -**Note:** Version bump only for package @lerna/import - -## [5.1.5](https://github.com/lerna/lerna/compare/v5.1.4...v5.1.5) (2022-06-24) - -**Note:** Version bump only for package @lerna/import - -## [5.1.4](https://github.com/lerna/lerna/compare/v5.1.3...v5.1.4) (2022-06-15) - -**Note:** Version bump only for package @lerna/import - -## [5.1.3](https://github.com/lerna/lerna/compare/v5.1.2...v5.1.3) (2022-06-15) - -**Note:** Version bump only for package @lerna/import - -## [5.1.2](https://github.com/lerna/lerna/compare/v5.1.1...v5.1.2) (2022-06-13) - -**Note:** Version bump only for package @lerna/import - -## [5.1.1](https://github.com/lerna/lerna/compare/v5.1.0...v5.1.1) (2022-06-09) - -### Bug Fixes - -- allow maintenance LTS node 14 engines starting at 14.15.0 ([#3161](https://github.com/lerna/lerna/issues/3161)) ([72305e4](https://github.com/lerna/lerna/commit/72305e4dbab607a2d87ae4efa6ee577c93a9dda9)) - -# [5.1.0](https://github.com/lerna/lerna/compare/v5.0.0...v5.1.0) (2022-06-07) - -**Note:** Version bump only for package @lerna/import - -# [5.1.0-alpha.0](https://github.com/lerna/lerna/compare/v4.0.0...v5.1.0-alpha.0) (2022-05-25) - -**Note:** Version bump only for package @lerna/import - -# [5.0.0](https://github.com/lerna/lerna/compare/v4.0.0...v5.0.0) (2022-05-24) - -**Note:** Version bump only for package @lerna/import - -# [4.0.0](https://github.com/lerna/lerna/compare/v3.22.1...v4.0.0) (2021-02-10) - -### Bug Fixes - -- **import:** Better handling of "Patch is empty" ([#2588](https://github.com/lerna/lerna/issues/2588)) ([0497bc7](https://github.com/lerna/lerna/commit/0497bc73043b2b646cc614f54187b68ba007000e)) - -### Features - -- **deps:** Bump dependencies ([affed1c](https://github.com/lerna/lerna/commit/affed1ce0fce91f01b0a9eafe357db2d985b974f)) -- Consume named exports of sibling modules ([63499e3](https://github.com/lerna/lerna/commit/63499e33652bc78fe23751875d74017e2f16a689)) -- **deps:** execa@^4.1.0 ([9051dca](https://github.com/lerna/lerna/commit/9051dcab1a68b56db09b82ab0345c5f36bcfee2d)) -- **deps:** fs-extra@^9.0.1 ([2f6f4e0](https://github.com/lerna/lerna/commit/2f6f4e066d5a41b4cd508b3405ac1d0a342932dc)) -- **deps:** p-map-series@^2.1.0 ([7f68076](https://github.com/lerna/lerna/commit/7f680767e0b3c7a15f951c51d4975150fb6e9112)) -- Drop support for Node v6.x & v8.x ([ff4bb4d](https://github.com/lerna/lerna/commit/ff4bb4da215555e3bb136f5af09b5cbc631e57bb)) - -### BREAKING CHANGES - -- Node v6.x & v8.x are no longer supported. Please upgrade to the latest LTS release. - -Here's the gnarly one-liner I used to make these changes: - -``` -npx lerna exec --concurrency 1 --stream -- 'json -I -f package.json -e '"'"'this.engines=this.engines||{};this.engines.node=">= 10.18.0"'"'" -``` - -(requires `npm i -g json` beforehand) - -# [3.22.0](https://github.com/lerna/lerna/compare/v3.21.0...v3.22.0) (2020-05-24) - -### Bug Fixes - -- **import:** Support non-ASCII characters in file paths ([#2441](https://github.com/lerna/lerna/issues/2441)) ([c74ffa4](https://github.com/lerna/lerna/commit/c74ffa4b31503ab8cd537ac2a9c9c15494f81a0c)) - -# [3.21.0](https://github.com/lerna/lerna/compare/v3.20.2...v3.21.0) (2020-05-13) - -**Note:** Version bump only for package @lerna/import - -## [3.18.5](https://github.com/lerna/lerna/compare/v3.18.4...v3.18.5) (2019-11-20) - -**Note:** Version bump only for package @lerna/import - -# [3.18.0](https://github.com/lerna/lerna/compare/v3.17.0...v3.18.0) (2019-10-15) - -**Note:** Version bump only for package @lerna/import - -## [3.16.5](https://github.com/lerna/lerna/compare/v3.16.4...v3.16.5) (2019-10-07) - -**Note:** Version bump only for package @lerna/import - -# [3.16.0](https://github.com/lerna/lerna/compare/v3.15.0...v3.16.0) (2019-07-18) - -### Features - -- **deps:** `fs-extra@^8.1.0` ([313287f](https://github.com/lerna/lerna/commit/313287f)) - -# [3.15.0](https://github.com/lerna/lerna/compare/v3.14.2...v3.15.0) (2019-06-09) - -**Note:** Version bump only for package @lerna/import - -## [3.14.2](https://github.com/lerna/lerna/compare/v3.14.1...v3.14.2) (2019-06-09) - -**Note:** Version bump only for package @lerna/import - -# [3.14.0](https://github.com/lerna/lerna/compare/v3.13.4...v3.14.0) (2019-05-14) - -### Features - -- **import:** Add `--preserve-commit` option ([#2079](https://github.com/lerna/lerna/issues/2079)) ([6a7448d](https://github.com/lerna/lerna/commit/6a7448d)) - -## [3.13.4](https://github.com/lerna/lerna/compare/v3.13.3...v3.13.4) (2019-04-24) - -### Bug Fixes - -- **import:** Avoid "unrecognized input" error from colors when using `--flatten` ([#2037](https://github.com/lerna/lerna/issues/2037)) ([51625fa](https://github.com/lerna/lerna/commit/51625fa)), closes [#1644](https://github.com/lerna/lerna/issues/1644) - -## [3.13.3](https://github.com/lerna/lerna/compare/v3.13.2...v3.13.3) (2019-04-17) - -**Note:** Version bump only for package @lerna/import - -## [3.13.1](https://github.com/lerna/lerna/compare/v3.13.0...v3.13.1) (2019-02-26) - -**Note:** Version bump only for package @lerna/import - -# [3.13.0](https://github.com/lerna/lerna/compare/v3.12.1...v3.13.0) (2019-02-15) - -### Features - -- **meta:** Add `repository.directory` field to package.json ([aec5023](https://github.com/lerna/lerna/commit/aec5023)) -- **meta:** Normalize package.json `homepage` field ([abeb4dc](https://github.com/lerna/lerna/commit/abeb4dc)) - -# [3.12.0](https://github.com/lerna/lerna/compare/v3.11.1...v3.12.0) (2019-02-14) - -**Note:** Version bump only for package @lerna/import - -# [3.11.0](https://github.com/lerna/lerna/compare/v3.10.8...v3.11.0) (2019-02-08) - -**Note:** Version bump only for package @lerna/import - -## [3.10.6](https://github.com/lerna/lerna/compare/v3.10.5...v3.10.6) (2019-01-19) - -### Bug Fixes - -- **import:** Ensure compatibility with root-level package globs ([#1875](https://github.com/lerna/lerna/issues/1875)) ([16ab98d](https://github.com/lerna/lerna/commit/16ab98d)), closes [#1872](https://github.com/lerna/lerna/issues/1872) - -# [3.10.0](https://github.com/lerna/lerna/compare/v3.9.1...v3.10.0) (2019-01-08) - -**Note:** Version bump only for package @lerna/import - -## [3.8.5](https://github.com/lerna/lerna/compare/v3.8.4...v3.8.5) (2019-01-05) - -**Note:** Version bump only for package @lerna/import - -## [3.8.1](https://github.com/lerna/lerna/compare/v3.8.0...v3.8.1) (2018-12-31) - -### Bug Fixes - -- **progress:** Correctly avoid progress where we don't want it ([0de3df9](https://github.com/lerna/lerna/commit/0de3df9)) -- **progress:** Enable progress during logging setup, correcting default ([da81e60](https://github.com/lerna/lerna/commit/da81e60)) - -## [3.7.2](https://github.com/lerna/lerna/compare/v3.7.1...v3.7.2) (2018-12-21) - -**Note:** Version bump only for package @lerna/import - -## [3.7.1](https://github.com/lerna/lerna/compare/v3.7.0...v3.7.1) (2018-12-20) - -### Bug Fixes - -- **import:** Pulse progress bar during execution ([b552e22](https://github.com/lerna/lerna/commit/b552e22)) - -# [3.7.0](https://github.com/lerna/lerna/compare/v3.6.0...v3.7.0) (2018-12-19) - -**Note:** Version bump only for package @lerna/import - -# [3.6.0](https://github.com/lerna/lerna/compare/v3.5.1...v3.6.0) (2018-12-07) - -**Note:** Version bump only for package @lerna/import - -# [3.5.0](https://github.com/lerna/lerna/compare/v3.4.3...v3.5.0) (2018-11-27) - -**Note:** Version bump only for package @lerna/import - - - -## [3.3.1](https://github.com/lerna/lerna/compare/v3.3.0...v3.3.1) (2018-09-11) - -### Bug Fixes - -- **import:** Handle filepaths with spaces more robustly ([#1655](https://github.com/lerna/lerna/issues/1655)) ([b084293](https://github.com/lerna/lerna/commit/b084293)) - - - -# [3.3.0](https://github.com/lerna/lerna/compare/v3.2.1...v3.3.0) (2018-09-06) - -### Features - -- **deps:** Upgrade fs-extra to ^7.0.0 ([042b1a3](https://github.com/lerna/lerna/commit/042b1a3)) - - - -## [3.1.3](https://github.com/lerna/lerna/compare/v3.1.2...v3.1.3) (2018-08-21) - -**Note:** Version bump only for package @lerna/import - - - -## [3.1.2](https://github.com/lerna/lerna/compare/v3.1.1...v3.1.2) (2018-08-20) - -**Note:** Version bump only for package @lerna/import - - - -# [3.1.0](https://github.com/lerna/lerna/compare/v3.0.6...v3.1.0) (2018-08-17) - -**Note:** Version bump only for package @lerna/import - - - -## [3.0.6](https://github.com/lerna/lerna/compare/v3.0.5...v3.0.6) (2018-08-16) - -**Note:** Version bump only for package @lerna/import - - - -## [3.0.5](https://github.com/lerna/lerna/compare/v3.0.4...v3.0.5) (2018-08-15) - -### Bug Fixes - -- **options:** Provide -y alias for --yes ([3ea460c](https://github.com/lerna/lerna/commit/3ea460c)) - - - -# [3.0.0](https://github.com/lerna/lerna/compare/v3.0.0-rc.0...v3.0.0) (2018-08-10) - -**Note:** Version bump only for package @lerna/import - - - -# [3.0.0-rc.0](https://github.com/lerna/lerna/compare/v3.0.0-beta.21...v3.0.0-rc.0) (2018-07-27) - -### Features - -- Add description from --help summary [skip ci] ([9b65d8e](https://github.com/lerna/lerna/commit/9b65d8e)) -- Upgrade to fs-extra 6 ([079d873](https://github.com/lerna/lerna/commit/079d873)) -- **cli:** Upgrade to Yargs 12 ([7899ab8](https://github.com/lerna/lerna/commit/7899ab8)) - - - -# [3.0.0-beta.21](https://github.com/lerna/lerna/compare/v3.0.0-beta.20...v3.0.0-beta.21) (2018-05-12) - -**Note:** Version bump only for package @lerna/import - - - -# [3.0.0-beta.20](https://github.com/lerna/lerna/compare/v3.0.0-beta.19...v3.0.0-beta.20) (2018-05-07) - -**Note:** Version bump only for package @lerna/import - - - -# [3.0.0-beta.19](https://github.com/lerna/lerna/compare/v3.0.0-beta.18...v3.0.0-beta.19) (2018-05-03) - -**Note:** Version bump only for package @lerna/import - - - -# [3.0.0-beta.18](https://github.com/lerna/lerna/compare/v3.0.0-beta.17...v3.0.0-beta.18) (2018-04-24) - -### Features - -- **git-utils:** Devolve getCurrentSHA() to consumers ([ecbc1d3](https://github.com/lerna/lerna/commit/ecbc1d3)) -- **import:** Inline GitUtilities.getWorkspaceRoot() ([925080e](https://github.com/lerna/lerna/commit/925080e)) - -### BREAKING CHANGES - -- **git-utils:** Don't use GitUtilities. -- **import:** GitUtilities.getWorkspaceRoot no longer exists. You shouldn't be using GitUtilities. - - - -# [3.0.0-beta.17](https://github.com/lerna/lerna/compare/v3.0.0-beta.16...v3.0.0-beta.17) (2018-04-13) - -**Note:** Version bump only for package @lerna/import - - - -# [3.0.0-beta.16](https://github.com/lerna/lerna/compare/v3.0.0-beta.15...v3.0.0-beta.16) (2018-04-10) - -### Bug Fixes - -- **import:** Rebase patch copies, too ([f6bae80](https://github.com/lerna/lerna/commit/f6bae80)) - - - -# [3.0.0-beta.15](https://github.com/lerna/lerna/compare/v3.0.0-beta.14...v3.0.0-beta.15) (2018-04-09) - -**Note:** Version bump only for package @lerna/import - - - -# [3.0.0-beta.14](https://github.com/lerna/lerna/compare/v3.0.0-beta.13...v3.0.0-beta.14) (2018-04-03) - -**Note:** Version bump only for package @lerna/import - - - -# [3.0.0-beta.13](https://github.com/lerna/lerna/compare/v3.0.0-beta.12...v3.0.0-beta.13) (2018-03-31) - -### Bug Fixes - -- Use ValidationError instead of Error ([bea6bc3](https://github.com/lerna/lerna/commit/bea6bc3)) - -### Features - -- Enable progress bars only when necessary ([b766c83](https://github.com/lerna/lerna/commit/b766c83)) - - - -# [3.0.0-beta.12](https://github.com/lerna/lerna/compare/v3.0.0-beta.11...v3.0.0-beta.12) (2018-03-30) - -**Note:** Version bump only for package @lerna/import - - - -# [3.0.0-beta.11](https://github.com/lerna/lerna/compare/v3.0.0-beta.10...v3.0.0-beta.11) (2018-03-29) - -**Note:** Version bump only for package @lerna/import - - - -# [3.0.0-beta.10](https://github.com/lerna/lerna/compare/v3.0.0-beta.9...v3.0.0-beta.10) (2018-03-27) - -### Features - -- **commands:** Delay require of command instantiation ([a1284f3](https://github.com/lerna/lerna/commit/a1284f3)) - -### BREAKING CHANGES - -- **commands:** The default export of command packages is now a factory, not the subclass (which is now a named export). - - - -# [3.0.0-beta.9](https://github.com/lerna/lerna/compare/v3.0.0-beta.8...v3.0.0-beta.9) (2018-03-24) - -### Features - -- **command:** Rename this.repository -> this.project ([43e98a0](https://github.com/lerna/lerna/commit/43e98a0)) - - - -# [3.0.0-beta.7](https://github.com/lerna/lerna/compare/v3.0.0-beta.6...v3.0.0-beta.7) (2018-03-20) - -**Note:** Version bump only for package @lerna/import - - - -# [3.0.0-beta.4](https://github.com/lerna/lerna/compare/v3.0.0-beta.3...v3.0.0-beta.4) (2018-03-19) - -**Note:** Version bump only for package @lerna/import - - - -# [3.0.0-beta.3](https://github.com/lerna/lerna/compare/v3.0.0-beta.2...v3.0.0-beta.3) (2018-03-15) - -**Note:** Version bump only for package @lerna/import - - - -# [3.0.0-beta.2](https://github.com/lerna/lerna/compare/v3.0.0-beta.1...v3.0.0-beta.2) (2018-03-10) - -### Features - -- Replace @lerna/fs-utils dependency with fs-extra ([9c35a86](https://github.com/lerna/lerna/commit/9c35a86)) - - - -# [3.0.0-beta.1](https://github.com/lerna/lerna/compare/v3.0.0-beta.0...v3.0.0-beta.1) (2018-03-09) - -**Note:** Version bump only for package @lerna/import diff --git a/commands/import/README.md b/commands/import/README.md deleted file mode 100644 index c12d488d1a..0000000000 --- a/commands/import/README.md +++ /dev/null @@ -1,64 +0,0 @@ -# `@lerna/import` - -> Import a package into the monorepo with commit history - -Install [lerna](https://www.npmjs.com/package/lerna) for access to the `lerna` CLI. - -## Usage - -```sh -$ lerna import -``` - -Import the package at ``, with commit history, -into `packages/`. Original commit authors, dates and messages -are preserved. Commits are applied to the current branch. - -This is useful for gathering pre-existing standalone packages into a Lerna -repo. Each commit is modified to make changes relative to the package -directory. So, for example, the commit that added `package.json` will -instead add `packages//package.json`. - -_Note_: If you're importing an external repository on a new lerna repository, then do remember to have at least one commit. - -```bash -# Getting started with Lerna -$ git init lerna-repo && cd lerna-repo -$ npx lerna init -$ npm install - -# Adding a commit -$ git add . -$ git commit -m "Initial lerna commit" # Without a commit, import command would fail - -# Importing other repository -$ npx lerna import -``` - -## Options - -### `--flatten` - -When importing repositories with merge commits with conflicts, the import command will fail trying to apply all commits. The user can use this flag to ask for import of "flat" history, i.e. with each merge commit as a single change the merge introduced. - -``` -$ lerna import ~/Product --flatten -``` - -### `--dest` - -When importing repositories, you can specify the destination directory by the directory listed in lerna.json. - -``` -$ lerna import ~/Product --dest=utilities -``` - -### `--preserve-commit` - -Each git commit has an **author** and a **committer** (with a separate date for each). Usually they're the same person (and date), but since `lerna import` re-creates each commit from the external repository, the **committer** becomes the current git user (and date). This is *technically* correct, but may be undesirable, for example, on Github, which displays both the **author** and **committer** if they're different people, leading to potentially confusing history/blames on imported commits. - -Enabling this option preserves the original **committer** (and commit date) to avoid such issues. - -``` -$ lerna import ~/Product --preserve-commit -``` diff --git a/commands/import/__tests__/__fixtures__/multi-packages/lerna.json b/commands/import/__tests__/__fixtures__/multi-packages/lerna.json deleted file mode 100644 index b5a2f7f9c2..0000000000 --- a/commands/import/__tests__/__fixtures__/multi-packages/lerna.json +++ /dev/null @@ -1,7 +0,0 @@ -{ - "version": "1.0.0", - "packages": [ - "core/*", - "packages/*" - ] -} \ No newline at end of file diff --git a/commands/import/__tests__/__fixtures__/multi-packages/package.json b/commands/import/__tests__/__fixtures__/multi-packages/package.json deleted file mode 100644 index 352e581a92..0000000000 --- a/commands/import/__tests__/__fixtures__/multi-packages/package.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "name": "multi-packages" -} \ No newline at end of file diff --git a/commands/import/__tests__/import-command.test.js b/commands/import/__tests__/import-command.test.js deleted file mode 100644 index 0046203d2b..0000000000 --- a/commands/import/__tests__/import-command.test.js +++ /dev/null @@ -1,356 +0,0 @@ -"use strict"; - -jest.mock("@lerna/prompt"); - -const execa = require("execa"); -const fs = require("fs-extra"); -const path = require("path"); -const pathExists = require("path-exists"); - -// mocked or stubbed modules -const { promptConfirmation } = require("@lerna/prompt"); - -// helpers -const initNamedFixture = require("@lerna-test/helpers").initNamedFixtureFactory(__dirname); -const initFixture = require("@lerna-test/helpers").initFixtureFactory(__dirname); -const { gitAdd } = require("@lerna-test/helpers"); -const { gitCommit } = require("@lerna-test/helpers"); -const { updateLernaConfig } = require("@lerna-test/helpers"); - -// file under test -const lernaImport = require("@lerna-test/helpers").commandRunner(require("../command")); - -// assertion helpers -const lastCommitInDir = (cwd) => - execa("git", ["log", "-1", "--format=%s"], { cwd }).then((result) => result.stdout); - -describe("ImportCommand", () => { - promptConfirmation.mockResolvedValue(true); - - describe("import", () => { - const initBasicFixtures = async () => { - const externalDir = await initFixture("external", "Init external commit"); - const testDir = await initFixture("basic"); - return [testDir, externalDir]; - }; - - it("creates a module in packages location with imported commit history", async () => { - const [testDir, externalDir] = await initBasicFixtures(); - const packageJson = path.join(testDir, "packages", path.basename(externalDir), "package.json"); - - await lernaImport(testDir)(externalDir); - - expect(await lastCommitInDir(testDir)).toBe("Init external commit"); - expect(await pathExists(packageJson)).toBe(true); - }); - - it("imports a repo with conflicted merge commits when run with --flatten", async () => { - const [testDir, externalDir] = await initBasicFixtures(); - const branchName = "conflict_branch"; - const conflictedFileName = "conflicted-file.txt"; - const conflictedFile = path.join(externalDir, conflictedFileName); - const newFilePath = path.join(testDir, "packages", path.basename(externalDir), conflictedFileName); - - await fs.writeFile(conflictedFile, "initial content"); - await gitAdd(externalDir, conflictedFileName); - await gitCommit(externalDir, "Initial content written"); - - await execa("git", ["checkout", "-b", branchName], { cwd: externalDir }); - - await fs.writeFile(conflictedFile, "branch content"); - await gitAdd(externalDir, conflictedFileName); - await gitCommit(externalDir, "branch content written"); - - await execa("git", ["checkout", "main"], { cwd: externalDir }); - - await fs.writeFile(conflictedFile, "main content"); - await gitAdd(externalDir, conflictedFileName); - await gitCommit(externalDir, "main content written"); - - try { - await execa("git", ["merge", branchName], { cwd: externalDir }); - } catch (e) { - // skip - } - - await fs.writeFile(conflictedFile, "merged content"); - await gitAdd(externalDir, conflictedFileName); - await gitCommit(externalDir, "Branch merged"); - - await lernaImport(testDir)(externalDir, "--flatten"); - - expect(await lastCommitInDir(testDir)).toBe("Branch merged"); - expect(await pathExists(newFilePath)).toBe(true); - }); - - it("imports a repo into the root directory when packages are located there", async () => { - const externalDir = await initNamedFixture("myapp-foo", "external", "myapp-foo init commit"); - const testDir = await initFixture("root-packages"); - - await lernaImport(testDir)(externalDir); - - expect(await lastCommitInDir(testDir)).toBe("myapp-foo init commit"); - expect(await pathExists(path.join(testDir, "myapp-foo/old-file"))).toBe(true); - expect(await pathExists(path.join(testDir, "myapp-foo/package.json"))).toBe(true); - }); - - it("supports moved files within the external repo", async () => { - const [testDir, externalDir] = await initBasicFixtures(); - const newFilePath = path.join(testDir, "packages", path.basename(externalDir), "new-file"); - - await execa("git", ["mv", "old-file", "new-file"], { cwd: externalDir }); - await gitCommit(externalDir, "Moved old-file to new-file"); - - await lernaImport(testDir)(externalDir); - - expect(await lastCommitInDir(testDir)).toBe("Moved old-file to new-file"); - expect(await pathExists(newFilePath)).toBe(true); - }); - - it("supports filepaths that have spaces within the external repo", async () => - Promise.all( - // running the same test with and without --flatten - [true, false].map(async (shouldFlatten) => { - const externalDir = await initFixture("files-with-spaces", "Init external commit"); - const testDir = await initFixture("basic"); - const newPackagePath = path.join(testDir, "packages", path.basename(externalDir)); - const newFilePath = path.join(newPackagePath, "file with spaces"); - const newDeepFilePath = path.resolve(newPackagePath, "subfolder b/file"); - - if (shouldFlatten) { - await lernaImport(testDir)(externalDir, "--flatten"); - } else { - await lernaImport(testDir)(externalDir); - } - - expect(await lastCommitInDir(testDir)).toBe("Init external commit"); - expect(await pathExists(newFilePath)).toBe(true); - expect(await pathExists(newDeepFilePath)).toBe(true); - }) - )); - - it("supports filepaths that have non-ascii char within the external repo", async () => - Promise.all( - // running the same test with and without --flatten - [true, false].map(async (shouldFlatten) => { - const externalDir = await initFixture("files-with-non-ascii-char", "Init external commit"); - const testDir = await initFixture("basic"); - const newPackagePath = path.join(testDir, "packages", path.basename(externalDir)); - - await fs.copy(path.join(externalDir, "檔案"), path.join(externalDir, "檔案-copy")); - await gitAdd(externalDir, "檔案-copy"); - await gitCommit(externalDir, "copy"); - - await fs.move(path.join(externalDir, "檔案"), path.join(externalDir, "檔案-rename")); - await gitAdd(externalDir, "檔案", "檔案-rename"); - await gitCommit(externalDir, "rename"); - - const copyFilePath = path.join(newPackagePath, "檔案-copy"); - const renameFilePath = path.join(newPackagePath, "檔案-rename"); - - if (shouldFlatten) { - await lernaImport(testDir)(externalDir, "--flatten"); - } else { - await lernaImport(testDir)(externalDir); - } - - expect(await lastCommitInDir(testDir)).toBe("rename"); - expect(await pathExists(copyFilePath)).toBe(true); - expect(await pathExists(renameFilePath)).toBe(true); - }) - )); - - it("skips empty patches with --flatten", async () => { - const [testDir, externalDir] = await initBasicFixtures(); - const filePath = path.join(externalDir, "file.txt"); - - await fs.writeFile(filePath, "non-empty content"); - await gitAdd(externalDir, filePath); - await gitCommit(externalDir, "Non-empty commit"); - - await execa("git", ["commit", "--allow-empty", "-m", "Empty commit"], { cwd: externalDir }); - - await lernaImport(testDir)(externalDir, "--flatten"); - - expect(await lastCommitInDir(testDir)).toBe("Non-empty commit"); - }); - - it("exits early when confirmation is rejected", async () => { - const [testDir, externalDir] = await initBasicFixtures(); - - promptConfirmation.mockResolvedValueOnce(false); - - await lernaImport(testDir)(externalDir); - - expect(await lastCommitInDir(testDir)).toBe("Init commit"); - }); - - it("preserves original committer and date with --preserve-commit", async () => - Promise.all( - // running the same test with and without --preserve-commit - [true, false].map(async (shouldPreserve) => { - const [testDir, externalDir] = await initBasicFixtures(); - const filePath = path.join(externalDir, "old-file"); - let expectedEmail; - let expectedName; - - await execa("git", ["config", "user.name", "'test-name'"], { cwd: externalDir }); - await execa("git", ["config", "user.email", "'test-email@foo.bar'"], { cwd: externalDir }); - await fs.writeFile(filePath, "non-empty content"); - await gitAdd(externalDir, filePath); - await gitCommit(externalDir, "Non-empty commit"); - - if (shouldPreserve) { - await lernaImport(testDir)(externalDir, "--preserve-commit"); - // original committer - expectedEmail = "test-email@foo.bar"; - expectedName = "test-name"; - } else { - await lernaImport(testDir)(externalDir); - // whatever the current git user is - expectedEmail = execa.sync("git", ["config", "user.email"], { cwd: testDir }).stdout; - expectedName = execa.sync("git", ["config", "user.name"], { cwd: testDir }).stdout; - } - - expect(execa.sync("git", ["log", "-1", "--format=%cn <%ce>"], { cwd: testDir }).stdout).toBe( - `${expectedName} <${expectedEmail}>` - ); - }) - )); - - it("allows skipping confirmation prompt", async () => { - const [testDir, externalDir] = await initBasicFixtures(); - await lernaImport(testDir)(externalDir, "--yes"); - - expect(promptConfirmation).not.toHaveBeenCalled(); - }); - - it("errors without an argument", async () => { - const [testDir] = await initBasicFixtures(); - - const command = lernaImport(testDir)(); - await expect(command).rejects.toThrow("Not enough non-option arguments: got 0, need at least 1"); - }); - - it("errors when external directory is missing", async () => { - const [testDir, externalDir] = await initBasicFixtures(); - const missing = `${externalDir}_invalidSuffix`; - - const command = lernaImport(testDir)(missing); - await expect(command).rejects.toThrow(`No repository found at "${missing}"`); - }); - - it("errors when external package.json is missing", async () => { - const [testDir, externalDir] = await initBasicFixtures(); - - await fs.unlink(path.join(externalDir, "package.json")); - - const command = lernaImport(testDir)(externalDir); - await expect(command).rejects.toThrow( - expect.objectContaining({ - message: expect.stringContaining("package.json"), - code: "MODULE_NOT_FOUND", - }) - ); - }); - - it("errors when external package.json has no name property", async () => { - const [testDir, externalDir] = await initBasicFixtures(); - const packageJson = path.join(externalDir, "package.json"); - - await fs.writeFile(packageJson, "{}"); - - const command = lernaImport(testDir)(externalDir); - await expect(command).rejects.toThrow(`No package name specified in "${packageJson}"`); - }); - - it("errors if target directory exists", async () => { - const [testDir, externalDir] = await initBasicFixtures(); - const targetDir = path.join(testDir, "packages", path.basename(externalDir)); - const relativePath = path.relative(testDir, targetDir); - - await fs.ensureDir(targetDir); - - const command = lernaImport(testDir)(externalDir); - await expect(command).rejects.toThrow(`Target directory already exists "${relativePath}"`); - }); - - it("infers correct target directory given packages glob", async () => { - const [testDir, externalDir] = await initBasicFixtures(); - const targetDir = path.join(testDir, "pkg", path.basename(externalDir)); - const relativePath = path.relative(testDir, targetDir); - - await fs.ensureDir(targetDir); - - await updateLernaConfig(testDir, { - packages: ["pkg/*"], - }); - - const command = lernaImport(testDir)(externalDir); - await expect(command).rejects.toThrow(`Target directory already exists "${relativePath}"`); - }); - - it("errors if repo has uncommitted changes", async () => { - const [testDir, externalDir] = await initBasicFixtures(); - const uncommittedFile = path.join(testDir, "uncommittedFile"); - - await fs.writeFile(uncommittedFile, "stuff"); - await gitAdd(testDir, uncommittedFile); - - const command = lernaImport(testDir)(externalDir); - await expect(command).rejects.toThrow("Local repository has un-committed changes"); - }); - - it("does not remove custom subject prefixes in [brackets]", async () => { - const [testDir, externalDir] = await initBasicFixtures(); - const newFilePath = path.join(testDir, "packages", path.basename(externalDir), "new-file"); - - await execa("git", ["mv", "old-file", "new-file"], { cwd: externalDir }); - await gitCommit(externalDir, "[ISSUE-10] Moved old-file to new-file"); - - await lernaImport(testDir)(externalDir); - - expect(await lastCommitInDir(testDir)).toBe("[ISSUE-10] Moved old-file to new-file"); - expect(await pathExists(newFilePath)).toBe(true); - }); - }); - - describe("with non-root Lerna dir", () => { - // #1197 - it("creates a module in packages location with imported commit history", async () => { - const externalDir = await initFixture("external", "Init external commit"); - const rootDir = await initFixture("lerna-not-in-root"); - const testDir = path.join(rootDir, "subdir"); - const packageJson = path.join(testDir, "packages", path.basename(externalDir), "package.json"); - - await lernaImport(testDir)(externalDir); - - expect(await lastCommitInDir(rootDir)).toBe("Init external commit"); - expect(await pathExists(packageJson)).toBe(true); - }); - }); - - describe("with multi-packages Lerna dir", () => { - it("creates a module in specified package directory", async () => { - const externalDir = await initFixture("external", "Init external commit"); - const testDir = await initFixture("multi-packages"); - - const packageJson = path.join(testDir, "packages", path.basename(externalDir), "package.json"); - - await lernaImport(testDir)(externalDir, "--dest=packages"); - - expect(await lastCommitInDir(testDir)).toBe("Init external commit"); - expect(await pathExists(packageJson)).toBe(true); - }); - - it("throws error when the package directory does not match with config", async () => { - const externalDir = await initFixture("external", "Init external commit"); - const testDir = await initFixture("multi-packages"); - - const command = lernaImport(testDir)(externalDir, "--dest=components"); - await expect(command).rejects.toThrow( - "--dest does not match with the package directories: core,packages" - ); - }); - }); -}); diff --git a/commands/import/command.js b/commands/import/command.js deleted file mode 100644 index 9ee07a5648..0000000000 --- a/commands/import/command.js +++ /dev/null @@ -1,39 +0,0 @@ -"use strict"; - -/** - * @see https://github.com/yargs/yargs/blob/master/docs/advanced.md#providing-a-command-module - */ -exports.command = "import "; - -exports.describe = "Import a package into the monorepo with commit history"; - -exports.builder = (yargs) => - yargs - .positional("dir", { describe: "The path to an external git repository that contains an npm package" }) - .options({ - flatten: { - group: "Command Options:", - describe: "Import each merge commit as a single change the merge introduced", - type: "boolean", - }, - dest: { - group: "Command Options:", - describe: "Import destination directory for the external git repository", - type: "string", - }, - "preserve-commit": { - group: "Command Options:", - describe: "Preserve original committer in addition to original author", - type: "boolean", - }, - y: { - group: "Command Options:", - describe: "Skip all confirmation prompts", - alias: "yes", - type: "boolean", - }, - }); - -exports.handler = function handler(argv) { - return require(".")(argv); -}; diff --git a/commands/import/index.js b/commands/import/index.js deleted file mode 100644 index 459fed0bc8..0000000000 --- a/commands/import/index.js +++ /dev/null @@ -1,296 +0,0 @@ -"use strict"; - -const dedent = require("dedent"); -const fs = require("fs-extra"); -const path = require("path"); -const pMapSeries = require("p-map-series"); - -const childProcess = require("@lerna/child-process"); -const { Command } = require("@lerna/command"); -const { promptConfirmation } = require("@lerna/prompt"); -const { ValidationError } = require("@lerna/validation-error"); -const { pulseTillDone } = require("@lerna/pulse-till-done"); - -module.exports = factory; - -function factory(argv) { - return new ImportCommand(argv); -} - -class ImportCommand extends Command { - gitParamsForTargetCommits() { - const params = ["log", "--format=%h"]; - if (this.options.flatten) { - params.push("--first-parent"); - } - return params; - } - - initialize() { - const inputPath = this.options.dir; - - const externalRepoPath = path.resolve(inputPath); - const externalRepoBase = path.basename(externalRepoPath); - - this.externalExecOpts = Object.assign({}, this.execOpts, { - cwd: externalRepoPath, - }); - - let stats; - - try { - stats = fs.statSync(externalRepoPath); - } catch (e) { - if (e.code === "ENOENT") { - throw new ValidationError("ENOENT", `No repository found at "${inputPath}"`); - } - - throw e; - } - - if (!stats.isDirectory()) { - throw new ValidationError("ENODIR", `Input path "${inputPath}" is not a directory`); - } - - const packageJson = path.join(externalRepoPath, "package.json"); - // eslint-disable-next-line import/no-dynamic-require, global-require - const packageName = require(packageJson).name; - - if (!packageName) { - throw new ValidationError("ENOPKG", `No package name specified in "${packageJson}"`); - } - - // Compute a target directory relative to the Lerna root - const targetBase = this.getTargetBase(); - if (this.getPackageDirectories().indexOf(targetBase) === -1) { - throw new ValidationError( - "EDESTDIR", - `--dest does not match with the package directories: ${this.getPackageDirectories()}` - ); - } - const targetDir = path.join(targetBase, externalRepoBase); - - // Compute a target directory relative to the Git root - const gitRepoRoot = this.getWorkspaceRoot(); - const lernaRootRelativeToGitRoot = path.relative(gitRepoRoot, this.project.rootPath); - this.targetDirRelativeToGitRoot = path.join(lernaRootRelativeToGitRoot, targetDir); - - if (fs.existsSync(path.resolve(this.project.rootPath, targetDir))) { - throw new ValidationError("EEXISTS", `Target directory already exists "${targetDir}"`); - } - - this.commits = this.externalExecSync("git", this.gitParamsForTargetCommits()).split("\n").reverse(); - // this.commits = this.externalExecSync("git", [ - // "rev-list", - // "--no-merges", - // "--topo-order", - // "--reverse", - // "HEAD", - // ]).split("\n"); - - if (!this.commits.length) { - throw new ValidationError("NOCOMMITS", `No git commits to import at "${inputPath}"`); - } - - if (this.options.preserveCommit) { - // Back these up since they'll change for each commit - this.origGitEmail = this.execSync("git", ["config", "user.email"]); - this.origGitName = this.execSync("git", ["config", "user.name"]); - } - - // Stash the repo's pre-import head away in case something goes wrong. - this.preImportHead = this.getCurrentSHA(); - - if (this.execSync("git", ["diff-index", "HEAD"])) { - throw new ValidationError("ECHANGES", "Local repository has un-committed changes"); - } - - this.logger.info( - "", - `About to import ${this.commits.length} commits from ${inputPath} into ${targetDir}` - ); - - if (this.options.yes) { - return true; - } - - return promptConfirmation("Are you sure you want to import these commits onto the current branch?"); - } - - getPackageDirectories() { - return this.project.packageConfigs.filter((p) => p.endsWith("*")).map((p) => path.dirname(p)); - } - - getTargetBase() { - if (this.options.dest) { - return this.options.dest; - } - - return this.getPackageDirectories().shift() || "packages"; - } - - getCurrentSHA() { - return this.execSync("git", ["rev-parse", "HEAD"]); - } - - getWorkspaceRoot() { - return this.execSync("git", ["rev-parse", "--show-toplevel"]); - } - - execSync(cmd, args) { - return childProcess.execSync(cmd, args, this.execOpts); - } - - externalExecSync(cmd, args) { - return childProcess.execSync(cmd, args, this.externalExecOpts); - } - - createPatchForCommit(sha) { - let patch = null; - - if (this.options.flatten) { - const diff = this.externalExecSync("git", [ - "log", - "--reverse", - "--first-parent", - "-p", - "-m", - "--pretty=email", - "--stat", - "--binary", - "-1", - "--color=never", - sha, - // custom git prefixes for accurate parsing of filepaths (#1655) - `--src-prefix=COMPARE_A/`, - `--dst-prefix=COMPARE_B/`, - ]); - const version = this.externalExecSync("git", ["--version"]).replace(/git version /g, ""); - - patch = `${diff}\n--\n${version}`; - } else { - patch = this.externalExecSync("git", [ - "format-patch", - "-1", - sha, - "--stdout", - // custom git prefixes for accurate parsing of filepaths (#1655) - `--src-prefix=COMPARE_A/`, - `--dst-prefix=COMPARE_B/`, - ]); - } - - const formattedTarget = this.targetDirRelativeToGitRoot.replace(/\\/g, "/"); - const replacement = `$1/${formattedTarget}`; - - // Create a patch file for this commit and prepend the target directory - // to all affected files. This moves the git history for the entire - // external repository into the package subdirectory, commit by commit. - return patch - .replace(/^([-+]{3} "?COMPARE_[AB])/gm, replacement) - .replace(/^(diff --git "?COMPARE_A)/gm, replacement) - .replace(/^(diff --git (?! "?COMPARE_B\/).+ "?COMPARE_B)/gm, replacement) - .replace(/^(copy (from|to)) ("?)/gm, `$1 $3${formattedTarget}/`) - .replace(/^(rename (from|to)) ("?)/gm, `$1 $3${formattedTarget}/`); - } - - getGitUserFromSha(sha) { - return { - email: this.externalExecSync("git", ["show", "-s", "--format='%ae'", sha]), - name: this.externalExecSync("git", ["show", "-s", "--format='%an'", sha]), - }; - } - - configureGitUser({ email, name }) { - this.execSync("git", ["config", "user.email", `"${email}"`]); - this.execSync("git", ["config", "user.name", `"${name}"`]); - } - - execute() { - this.enableProgressBar(); - - const tracker = this.logger.newItem("execute"); - const mapper = (sha) => { - tracker.info(sha); - - const patch = this.createPatchForCommit(sha); - const procArgs = ["am", "-3", "--keep-non-patch"]; - - if (this.options.preserveCommit) { - this.configureGitUser(this.getGitUserFromSha(sha)); - procArgs.push("--committer-date-is-author-date"); - } - - // Apply the modified patch to the current lerna repository, preserving - // original commit date, author and message. - // - // Fall back to three-way merge, which can help with duplicate commits - // due to merge history. - const proc = childProcess.exec("git", procArgs, this.execOpts); - - proc.stdin.end(patch); - - return pulseTillDone(proc) - .then(() => { - tracker.completeWork(1); - }) - .catch((err) => { - // Getting commit diff to see if it's empty - const diff = this.externalExecSync("git", ["diff", "-s", `${sha}^!`]).trim(); - if (diff === "") { - tracker.completeWork(1); - - // Automatically skip empty commits - return childProcess.exec("git", ["am", "--skip"], this.execOpts); - } - - err.sha = sha; - throw err; - }); - }; - - tracker.addWork(this.commits.length); - - return pMapSeries(this.commits, mapper) - .then(() => { - tracker.finish(); - - if (this.options.preserveCommit) { - this.configureGitUser({ - email: this.origGitEmail, - name: this.origGitName, - }); - } - - this.logger.success("import", "finished"); - }) - .catch((err) => { - tracker.finish(); - - if (this.options.preserveCommit) { - this.configureGitUser({ - email: this.origGitEmail, - name: this.origGitName, - }); - } - - this.logger.error("import", `Rolling back to previous HEAD (commit ${this.preImportHead})`); - - // Abort the failed `git am` and roll back to previous HEAD. - this.execSync("git", ["am", "--abort"]); - this.execSync("git", ["reset", "--hard", this.preImportHead]); - - throw new ValidationError( - "EIMPORT", - dedent` - Failed to apply commit ${err.sha}. - ${err.message} - - You may try again with --flatten to import flat history. - ` - ); - }); - } -} - -module.exports.ImportCommand = ImportCommand; diff --git a/commands/import/package.json b/commands/import/package.json deleted file mode 100644 index c98a1b44ef..0000000000 --- a/commands/import/package.json +++ /dev/null @@ -1,44 +0,0 @@ -{ - "name": "@lerna/import", - "version": "6.4.1", - "description": "Import a package into the monorepo with commit history", - "keywords": [ - "lerna", - "command" - ], - "homepage": "https://lerna.js.org", - "license": "MIT", - "author": { - "name": "Daniel Stockman", - "url": "https://github.com/evocateur" - }, - "files": [ - "command.js", - "index.js" - ], - "main": "index.js", - "engines": { - "node": "^14.15.0 || >=16.0.0" - }, - "publishConfig": { - "access": "public" - }, - "repository": { - "type": "git", - "url": "git+https://github.com/lerna/lerna.git", - "directory": "commands/import" - }, - "scripts": { - "test": "echo \"Run tests from root\" && exit 1" - }, - "dependencies": { - "@lerna/child-process": "file:../../core/child-process", - "@lerna/command": "file:../../core/command", - "@lerna/prompt": "file:../../core/prompt", - "@lerna/pulse-till-done": "file:../../utils/pulse-till-done", - "@lerna/validation-error": "file:../../core/validation-error", - "dedent": "^0.7.0", - "fs-extra": "^9.1.0", - "p-map-series": "^2.1.0" - } -} diff --git a/commands/info/CHANGELOG.md b/commands/info/CHANGELOG.md deleted file mode 100644 index c2df4b9a6b..0000000000 --- a/commands/info/CHANGELOG.md +++ /dev/null @@ -1,190 +0,0 @@ -# Change Log - -All notable changes to this project will be documented in this file. -See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. - -## [6.4.1](https://github.com/lerna/lerna/compare/v6.4.0...v6.4.1) (2023-01-12) - -**Note:** Version bump only for package @lerna/info - -# [6.4.0](https://github.com/lerna/lerna/compare/v6.3.0...v6.4.0) (2023-01-05) - -**Note:** Version bump only for package @lerna/info - -# [6.3.0](https://github.com/lerna/lerna/compare/v6.2.0...v6.3.0) (2022-12-26) - -**Note:** Version bump only for package @lerna/info - -# [6.2.0](https://github.com/lerna/lerna/compare/v6.1.0...v6.2.0) (2022-12-13) - -**Note:** Version bump only for package @lerna/info - -# [6.1.0](https://github.com/lerna/lerna/compare/v6.0.3...v6.1.0) (2022-11-29) - -**Note:** Version bump only for package @lerna/info - -## [6.0.3](https://github.com/lerna/lerna/compare/v6.0.2...v6.0.3) (2022-11-07) - -**Note:** Version bump only for package @lerna/info - -## [6.0.2](https://github.com/lerna/lerna/compare/v6.0.1...v6.0.2) (2022-11-02) - -**Note:** Version bump only for package @lerna/info - -## [6.0.1](https://github.com/lerna/lerna/compare/v6.0.0...v6.0.1) (2022-10-14) - -**Note:** Version bump only for package @lerna/info - -# [6.0.0](https://github.com/lerna/lerna/compare/v6.0.0-alpha.2...v6.0.0) (2022-10-12) - -**Note:** Version bump only for package @lerna/info - -# [6.0.0-alpha.2](https://github.com/lerna/lerna/compare/v6.0.0-alpha.1...v6.0.0-alpha.2) (2022-10-12) - -**Note:** Version bump only for package @lerna/info - -# [6.0.0-alpha.1](https://github.com/lerna/lerna/compare/v5.6.2...v6.0.0-alpha.1) (2022-10-09) - -# [6.0.0-alpha.0](https://github.com/lerna/lerna/compare/v5.6.1...v6.0.0-alpha.0) (2022-10-07) - -**Note:** Version bump only for package @lerna/info - -## [5.6.2](https://github.com/lerna/lerna/compare/v5.6.1...v5.6.2) (2022-10-09) - -**Note:** Version bump only for package @lerna/info - -## [5.6.1](https://github.com/lerna/lerna/compare/v5.6.0...v5.6.1) (2022-09-30) - -**Note:** Version bump only for package @lerna/info - -# [5.6.0](https://github.com/lerna/lerna/compare/v5.5.4...v5.6.0) (2022-09-29) - -### Features - -- **repair:** add lerna repair command ([#3314](https://github.com/lerna/lerna/issues/3314)) ([7defab3](https://github.com/lerna/lerna/commit/7defab3434687fc8e17f921250846aa279ac3df3)) - -## [5.5.4](https://github.com/lerna/lerna/compare/v5.5.3...v5.5.4) (2022-09-28) - -**Note:** Version bump only for package @lerna/info - -## [5.5.3](https://github.com/lerna/lerna/compare/v5.5.2...v5.5.3) (2022-09-28) - -**Note:** Version bump only for package @lerna/info - -## [5.5.2](https://github.com/lerna/lerna/compare/v5.5.1...v5.5.2) (2022-09-20) - -**Note:** Version bump only for package @lerna/info - -## [5.5.1](https://github.com/lerna/lerna/compare/v5.5.0...v5.5.1) (2022-09-09) - -**Note:** Version bump only for package @lerna/info - -# [5.5.0](https://github.com/lerna/lerna/compare/v5.4.3...v5.5.0) (2022-08-31) - -### Features - -- **repair:** add lerna repair command ([#3302](https://github.com/lerna/lerna/issues/3302)) ([aae1a2b](https://github.com/lerna/lerna/commit/aae1a2bed1cd2d61ed7b86013d7e6108415cfbcd)) - -### Reverts - -- Revert "feat(repair): add lerna repair command" (#3313) ([d261112](https://github.com/lerna/lerna/commit/d261112ede3256ec1c68a22943ae8854ec9fb906)), closes [#3313](https://github.com/lerna/lerna/issues/3313) [#3302](https://github.com/lerna/lerna/issues/3302) - -## [5.4.3](https://github.com/lerna/lerna/compare/v5.4.2...v5.4.3) (2022-08-16) - -**Note:** Version bump only for package @lerna/info - -## [5.4.2](https://github.com/lerna/lerna/compare/v5.4.1...v5.4.2) (2022-08-14) - -**Note:** Version bump only for package @lerna/info - -## [5.4.1](https://github.com/lerna/lerna/compare/v5.4.0...v5.4.1) (2022-08-12) - -**Note:** Version bump only for package @lerna/info - -# [5.4.0](https://github.com/lerna/lerna/compare/v5.3.0...v5.4.0) (2022-08-08) - -**Note:** Version bump only for package @lerna/info - -# [5.3.0](https://github.com/lerna/lerna/compare/v5.2.0...v5.3.0) (2022-07-27) - -**Note:** Version bump only for package @lerna/info - -# [5.2.0](https://github.com/lerna/lerna/compare/v5.1.8...v5.2.0) (2022-07-22) - -**Note:** Version bump only for package @lerna/info - -## [5.1.8](https://github.com/lerna/lerna/compare/v5.1.7...v5.1.8) (2022-07-07) - -**Note:** Version bump only for package @lerna/info - -## [5.1.7](https://github.com/lerna/lerna/compare/v5.1.6...v5.1.7) (2022-07-06) - -**Note:** Version bump only for package @lerna/info - -## [5.1.6](https://github.com/lerna/lerna/compare/v5.1.5...v5.1.6) (2022-06-24) - -**Note:** Version bump only for package @lerna/info - -## [5.1.5](https://github.com/lerna/lerna/compare/v5.1.4...v5.1.5) (2022-06-24) - -**Note:** Version bump only for package @lerna/info - -## [5.1.4](https://github.com/lerna/lerna/compare/v5.1.3...v5.1.4) (2022-06-15) - -**Note:** Version bump only for package @lerna/info - -## [5.1.3](https://github.com/lerna/lerna/compare/v5.1.2...v5.1.3) (2022-06-15) - -**Note:** Version bump only for package @lerna/info - -## [5.1.2](https://github.com/lerna/lerna/compare/v5.1.1...v5.1.2) (2022-06-13) - -**Note:** Version bump only for package @lerna/info - -## [5.1.1](https://github.com/lerna/lerna/compare/v5.1.0...v5.1.1) (2022-06-09) - -### Bug Fixes - -- allow maintenance LTS node 14 engines starting at 14.15.0 ([#3161](https://github.com/lerna/lerna/issues/3161)) ([72305e4](https://github.com/lerna/lerna/commit/72305e4dbab607a2d87ae4efa6ee577c93a9dda9)) - -# [5.1.0](https://github.com/lerna/lerna/compare/v5.0.0...v5.1.0) (2022-06-07) - -**Note:** Version bump only for package @lerna/info - -# [5.1.0-alpha.0](https://github.com/lerna/lerna/compare/v4.0.0...v5.1.0-alpha.0) (2022-05-25) - -**Note:** Version bump only for package @lerna/info - -# [5.0.0](https://github.com/lerna/lerna/compare/v4.0.0...v5.0.0) (2022-05-24) - -**Note:** Version bump only for package @lerna/info - -# [4.0.0](https://github.com/lerna/lerna/compare/v3.22.1...v4.0.0) (2021-02-10) - -### Features - -- **deps:** Bump dependencies ([affed1c](https://github.com/lerna/lerna/commit/affed1ce0fce91f01b0a9eafe357db2d985b974f)) -- Consume named exports of sibling modules ([63499e3](https://github.com/lerna/lerna/commit/63499e33652bc78fe23751875d74017e2f16a689)) -- Drop support for Node v6.x & v8.x ([ff4bb4d](https://github.com/lerna/lerna/commit/ff4bb4da215555e3bb136f5af09b5cbc631e57bb)) - -### BREAKING CHANGES - -- Node v6.x & v8.x are no longer supported. Please upgrade to the latest LTS release. - -Here's the gnarly one-liner I used to make these changes: - -``` -npx lerna exec --concurrency 1 --stream -- 'json -I -f package.json -e '"'"'this.engines=this.engines||{};this.engines.node=">= 10.18.0"'"'" -``` - -(requires `npm i -g json` beforehand) - -# [3.21.0](https://github.com/lerna/lerna/compare/v3.20.2...v3.21.0) (2020-05-13) - -**Note:** Version bump only for package @lerna/info - -# [3.20.0](https://github.com/lerna/lerna/compare/v3.19.0...v3.20.0) (2019-12-27) - -### Features - -- **cli:** Add new `info` command to output information about local environment ([#2106](https://github.com/lerna/lerna/issues/2106)) ([7abfe43](https://github.com/lerna/lerna/commit/7abfe43426197fbc7f18c44b0c994324609fc769)) diff --git a/commands/info/README.md b/commands/info/README.md deleted file mode 100644 index d75ad8d325..0000000000 --- a/commands/info/README.md +++ /dev/null @@ -1,28 +0,0 @@ -# `@lerna/info` - -> Print local environment information - -Install [lerna](https://www.npmjs.com/package/lerna) for access to the `lerna` CLI. - -## Usage - -The `info` command prints local environment information that proves to be useful especially while submitting bug reports. - -`lerna info` - -```bash -Environment Info: - - System: - OS: Linux 4.18 Ubuntu 18.10 (Cosmic Cuttlefish) - CPU: (4) x64 Intel(R) Core(TM) i5-7200U CPU @ 2.50GHz - Binaries: - Node: 8.11.4 - /usr/bin/node - Yarn: 1.17.0-0 - /usr/local/bin/yarn - npm: 6.9.0 - /usr/local/bin/npm - Browsers: - Chrome: 74.0.3729.157 - Firefox: 66.0.5 - npmPackages: - lerna: 3.14.1 -``` diff --git a/commands/info/__tests__/info-command.test.js b/commands/info/__tests__/info-command.test.js deleted file mode 100644 index 954953d640..0000000000 --- a/commands/info/__tests__/info-command.test.js +++ /dev/null @@ -1,26 +0,0 @@ -"use strict"; - -jest.mock("envinfo"); - -const path = require("path"); -const envinfo = require("envinfo"); - -envinfo.run.mockResolvedValue("MOCK_ENVINFO"); - -// helper -const { output } = require("@lerna/output"); - -// file under test -const lernaInfo = require("@lerna-test/helpers").commandRunner(require("../command")); - -it("outputs result of envinfo()", async () => { - // project fixture is irrelevant, no actual changes are made - await lernaInfo(path.resolve(__dirname, "../../.."))(); - - expect(envinfo.run).toHaveBeenLastCalledWith( - expect.objectContaining({ - npmPackages: ["lerna"], - }) - ); - expect(output.logged()).toMatch("MOCK_ENVINFO"); -}); diff --git a/commands/info/command.js b/commands/info/command.js deleted file mode 100644 index 9c2e16bd5e..0000000000 --- a/commands/info/command.js +++ /dev/null @@ -1,12 +0,0 @@ -"use strict"; - -/** - * @see https://github.com/yargs/yargs/blob/master/docs/advanced.md#providing-a-command-module - */ -exports.command = "info"; - -exports.describe = "Prints debugging information about the local environment"; - -exports.handler = function handler(argv) { - return require(".")(argv); -}; diff --git a/commands/info/index.js b/commands/info/index.js deleted file mode 100644 index 443506fdab..0000000000 --- a/commands/info/index.js +++ /dev/null @@ -1,30 +0,0 @@ -"use strict"; - -const { Command } = require("@lerna/command"); -const { output } = require("@lerna/output"); -const envinfo = require("envinfo"); - -module.exports = factory; - -function factory(argv) { - return new InfoCommand(argv); -} - -class InfoCommand extends Command { - // eslint-disable-next-line - initialize() {} - // eslint-disable-next-line - execute() { - output("\n Environment info:"); - envinfo - .run({ - System: ["OS", "CPU"], - Binaries: ["Node", "Yarn", "npm"], - Utilities: ["Git"], - npmPackages: ["lerna"], - }) - .then(output); - } -} - -module.exports.InfoCommand = InfoCommand; diff --git a/commands/info/package.json b/commands/info/package.json deleted file mode 100644 index d44e36dd88..0000000000 --- a/commands/info/package.json +++ /dev/null @@ -1,39 +0,0 @@ -{ - "name": "@lerna/info", - "version": "6.4.1", - "description": "Prints local environment information", - "keywords": [ - "lerna", - "command" - ], - "homepage": "https://lerna.js.org", - "license": "MIT", - "author": { - "name": "James George", - "url": "https://github.com/jamesgeorge007" - }, - "files": [ - "command.js", - "index.js" - ], - "main": "index.js", - "engines": { - "node": "^14.15.0 || >=16.0.0" - }, - "publishConfig": { - "access": "public" - }, - "repository": { - "type": "git", - "url": "git+https://github.com/lerna/lerna.git", - "directory": "commands/info" - }, - "scripts": { - "test": "echo \"Run tests from root\" && exit 1" - }, - "dependencies": { - "@lerna/command": "file:../../core/command", - "@lerna/output": "file:../../utils/output", - "envinfo": "^7.7.4" - } -} diff --git a/commands/init/CHANGELOG.md b/commands/init/CHANGELOG.md deleted file mode 100644 index 802dcdafc7..0000000000 --- a/commands/init/CHANGELOG.md +++ /dev/null @@ -1,478 +0,0 @@ -# Change Log - -All notable changes to this project will be documented in this file. -See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. - -## [6.4.1](https://github.com/lerna/lerna/compare/v6.4.0...v6.4.1) (2023-01-12) - -**Note:** Version bump only for package @lerna/init - -# [6.4.0](https://github.com/lerna/lerna/compare/v6.3.0...v6.4.0) (2023-01-05) - -**Note:** Version bump only for package @lerna/init - -# [6.3.0](https://github.com/lerna/lerna/compare/v6.2.0...v6.3.0) (2022-12-26) - -**Note:** Version bump only for package @lerna/init - -# [6.2.0](https://github.com/lerna/lerna/compare/v6.1.0...v6.2.0) (2022-12-13) - -**Note:** Version bump only for package @lerna/init - -# [6.1.0](https://github.com/lerna/lerna/compare/v6.0.3...v6.1.0) (2022-11-29) - -**Note:** Version bump only for package @lerna/init - -## [6.0.3](https://github.com/lerna/lerna/compare/v6.0.2...v6.0.3) (2022-11-07) - -**Note:** Version bump only for package @lerna/init - -## [6.0.2](https://github.com/lerna/lerna/compare/v6.0.1...v6.0.2) (2022-11-02) - -**Note:** Version bump only for package @lerna/init - -## [6.0.1](https://github.com/lerna/lerna/compare/v6.0.0...v6.0.1) (2022-10-14) - -**Note:** Version bump only for package @lerna/init - -# [6.0.0](https://github.com/lerna/lerna/compare/v6.0.0-alpha.2...v6.0.0) (2022-10-12) - -**Note:** Version bump only for package @lerna/init - -# [6.0.0-alpha.2](https://github.com/lerna/lerna/compare/v6.0.0-alpha.1...v6.0.0-alpha.2) (2022-10-12) - -**Note:** Version bump only for package @lerna/init - -# [6.0.0-alpha.1](https://github.com/lerna/lerna/compare/v5.6.2...v6.0.0-alpha.1) (2022-10-09) - -# [6.0.0-alpha.0](https://github.com/lerna/lerna/compare/v5.6.1...v6.0.0-alpha.0) (2022-10-07) - -**Note:** Version bump only for package @lerna/init - -## [5.6.2](https://github.com/lerna/lerna/compare/v5.6.1...v5.6.2) (2022-10-09) - -**Note:** Version bump only for package @lerna/init - -## [5.6.1](https://github.com/lerna/lerna/compare/v5.6.0...v5.6.1) (2022-09-30) - -**Note:** Version bump only for package @lerna/init - -# [5.6.0](https://github.com/lerna/lerna/compare/v5.5.4...v5.6.0) (2022-09-29) - -**Note:** Version bump only for package @lerna/init - -## [5.5.4](https://github.com/lerna/lerna/compare/v5.5.3...v5.5.4) (2022-09-28) - -**Note:** Version bump only for package @lerna/init - -## [5.5.3](https://github.com/lerna/lerna/compare/v5.5.2...v5.5.3) (2022-09-28) - -**Note:** Version bump only for package @lerna/init - -## [5.5.2](https://github.com/lerna/lerna/compare/v5.5.1...v5.5.2) (2022-09-20) - -**Note:** Version bump only for package @lerna/init - -## [5.5.1](https://github.com/lerna/lerna/compare/v5.5.0...v5.5.1) (2022-09-09) - -**Note:** Version bump only for package @lerna/init - -# [5.5.0](https://github.com/lerna/lerna/compare/v5.4.3...v5.5.0) (2022-08-31) - -**Note:** Version bump only for package @lerna/init - -## [5.4.3](https://github.com/lerna/lerna/compare/v5.4.2...v5.4.3) (2022-08-16) - -**Note:** Version bump only for package @lerna/init - -## [5.4.2](https://github.com/lerna/lerna/compare/v5.4.1...v5.4.2) (2022-08-14) - -**Note:** Version bump only for package @lerna/init - -## [5.4.1](https://github.com/lerna/lerna/compare/v5.4.0...v5.4.1) (2022-08-12) - -**Note:** Version bump only for package @lerna/init - -# [5.4.0](https://github.com/lerna/lerna/compare/v5.3.0...v5.4.0) (2022-08-08) - -### Features - -- **init:** create .gitignore with lerna init ([#3270](https://github.com/lerna/lerna/issues/3270)) ([3461348](https://github.com/lerna/lerna/commit/3461348bc5e2d511d16d9537227e8b884bf6558b)) - -# [5.3.0](https://github.com/lerna/lerna/compare/v5.2.0...v5.3.0) (2022-07-27) - -**Note:** Version bump only for package @lerna/init - -# [5.2.0](https://github.com/lerna/lerna/compare/v5.1.8...v5.2.0) (2022-07-22) - -### Features - -- add json schema for lerna.json ([#3229](https://github.com/lerna/lerna/issues/3229)) ([5075eae](https://github.com/lerna/lerna/commit/5075eae0d0aa8db52f619b9a6d8fdc9934ba24f7)) -- **init:** default useNx and useWorkspaces to true for new lerna workspaces ([#3255](https://github.com/lerna/lerna/issues/3255)) ([a0e83e5](https://github.com/lerna/lerna/commit/a0e83e5220f6e3d30b96b60bbaf14c5392653c2e)) - -## [5.1.8](https://github.com/lerna/lerna/compare/v5.1.7...v5.1.8) (2022-07-07) - -**Note:** Version bump only for package @lerna/init - -## [5.1.7](https://github.com/lerna/lerna/compare/v5.1.6...v5.1.7) (2022-07-06) - -**Note:** Version bump only for package @lerna/init - -## [5.1.6](https://github.com/lerna/lerna/compare/v5.1.5...v5.1.6) (2022-06-24) - -**Note:** Version bump only for package @lerna/init - -## [5.1.5](https://github.com/lerna/lerna/compare/v5.1.4...v5.1.5) (2022-06-24) - -**Note:** Version bump only for package @lerna/init - -## [5.1.4](https://github.com/lerna/lerna/compare/v5.1.3...v5.1.4) (2022-06-15) - -**Note:** Version bump only for package @lerna/init - -## [5.1.3](https://github.com/lerna/lerna/compare/v5.1.2...v5.1.3) (2022-06-15) - -**Note:** Version bump only for package @lerna/init - -## [5.1.2](https://github.com/lerna/lerna/compare/v5.1.1...v5.1.2) (2022-06-13) - -**Note:** Version bump only for package @lerna/init - -## [5.1.1](https://github.com/lerna/lerna/compare/v5.1.0...v5.1.1) (2022-06-09) - -### Bug Fixes - -- allow maintenance LTS node 14 engines starting at 14.15.0 ([#3161](https://github.com/lerna/lerna/issues/3161)) ([72305e4](https://github.com/lerna/lerna/commit/72305e4dbab607a2d87ae4efa6ee577c93a9dda9)) - -# [5.1.0](https://github.com/lerna/lerna/compare/v5.0.0...v5.1.0) (2022-06-07) - -**Note:** Version bump only for package @lerna/init - -# [5.1.0-alpha.0](https://github.com/lerna/lerna/compare/v4.0.0...v5.1.0-alpha.0) (2022-05-25) - -**Note:** Version bump only for package @lerna/init - -# [5.0.0](https://github.com/lerna/lerna/compare/v4.0.0...v5.0.0) (2022-05-24) - -**Note:** Version bump only for package @lerna/init - -# [4.0.0](https://github.com/lerna/lerna/compare/v3.22.1...v4.0.0) (2021-02-10) - -### Features - -- **deps:** Bump dependencies ([affed1c](https://github.com/lerna/lerna/commit/affed1ce0fce91f01b0a9eafe357db2d985b974f)) -- Consume named exports of sibling modules ([63499e3](https://github.com/lerna/lerna/commit/63499e33652bc78fe23751875d74017e2f16a689)) -- **deps:** fs-extra@^9.0.1 ([2f6f4e0](https://github.com/lerna/lerna/commit/2f6f4e066d5a41b4cd508b3405ac1d0a342932dc)) -- **deps:** p-map@^4.0.0 ([92b1364](https://github.com/lerna/lerna/commit/92b1364735e1f2cf379cf1047c60c4fb897d55f5)) -- **deps:** write-json-file@^4.3.0 ([d552c53](https://github.com/lerna/lerna/commit/d552c533c45489a1774f3c3b9ae8d15fc5d3b2a8)) -- Drop support for Node v6.x & v8.x ([ff4bb4d](https://github.com/lerna/lerna/commit/ff4bb4da215555e3bb136f5af09b5cbc631e57bb)) - -### BREAKING CHANGES - -- Node v6.x & v8.x are no longer supported. Please upgrade to the latest LTS release. - -Here's the gnarly one-liner I used to make these changes: - -``` -npx lerna exec --concurrency 1 --stream -- 'json -I -f package.json -e '"'"'this.engines=this.engines||{};this.engines.node=">= 10.18.0"'"'" -``` - -(requires `npm i -g json` beforehand) - -# [3.21.0](https://github.com/lerna/lerna/compare/v3.20.2...v3.21.0) (2020-05-13) - -**Note:** Version bump only for package @lerna/init - -## [3.18.5](https://github.com/lerna/lerna/compare/v3.18.4...v3.18.5) (2019-11-20) - -**Note:** Version bump only for package @lerna/init - -# [3.18.0](https://github.com/lerna/lerna/compare/v3.17.0...v3.18.0) (2019-10-15) - -**Note:** Version bump only for package @lerna/init - -## [3.16.5](https://github.com/lerna/lerna/compare/v3.16.4...v3.16.5) (2019-10-07) - -**Note:** Version bump only for package @lerna/init - -# [3.16.0](https://github.com/lerna/lerna/compare/v3.15.0...v3.16.0) (2019-07-18) - -### Features - -- **deps:** `fs-extra@^8.1.0` ([313287f](https://github.com/lerna/lerna/commit/313287f)) -- **deps:** `p-map@^2.1.0` ([9e58394](https://github.com/lerna/lerna/commit/9e58394)) -- **deps:** `write-json-file@^3.2.0` ([4fa7dea](https://github.com/lerna/lerna/commit/4fa7dea)) - -# [3.15.0](https://github.com/lerna/lerna/compare/v3.14.2...v3.15.0) (2019-06-09) - -**Note:** Version bump only for package @lerna/init - -## [3.14.2](https://github.com/lerna/lerna/compare/v3.14.1...v3.14.2) (2019-06-09) - -**Note:** Version bump only for package @lerna/init - -# [3.14.0](https://github.com/lerna/lerna/compare/v3.13.4...v3.14.0) (2019-05-14) - -**Note:** Version bump only for package @lerna/init - -## [3.13.3](https://github.com/lerna/lerna/compare/v3.13.2...v3.13.3) (2019-04-17) - -**Note:** Version bump only for package @lerna/init - -## [3.13.1](https://github.com/lerna/lerna/compare/v3.13.0...v3.13.1) (2019-02-26) - -**Note:** Version bump only for package @lerna/init - -# [3.13.0](https://github.com/lerna/lerna/compare/v3.12.1...v3.13.0) (2019-02-15) - -### Features - -- **meta:** Add `repository.directory` field to package.json ([aec5023](https://github.com/lerna/lerna/commit/aec5023)) -- **meta:** Normalize package.json `homepage` field ([abeb4dc](https://github.com/lerna/lerna/commit/abeb4dc)) - -# [3.12.0](https://github.com/lerna/lerna/compare/v3.11.1...v3.12.0) (2019-02-14) - -**Note:** Version bump only for package @lerna/init - -# [3.11.0](https://github.com/lerna/lerna/compare/v3.10.8...v3.11.0) (2019-02-08) - -**Note:** Version bump only for package @lerna/init - -## [3.10.6](https://github.com/lerna/lerna/compare/v3.10.5...v3.10.6) (2019-01-19) - -**Note:** Version bump only for package @lerna/init - -# [3.10.0](https://github.com/lerna/lerna/compare/v3.9.1...v3.10.0) (2019-01-08) - -**Note:** Version bump only for package @lerna/init - -## [3.8.5](https://github.com/lerna/lerna/compare/v3.8.4...v3.8.5) (2019-01-05) - -**Note:** Version bump only for package @lerna/init - -## [3.8.1](https://github.com/lerna/lerna/compare/v3.8.0...v3.8.1) (2018-12-31) - -**Note:** Version bump only for package @lerna/init - -## [3.7.2](https://github.com/lerna/lerna/compare/v3.7.1...v3.7.2) (2018-12-21) - -**Note:** Version bump only for package @lerna/init - -## [3.7.1](https://github.com/lerna/lerna/compare/v3.7.0...v3.7.1) (2018-12-20) - -**Note:** Version bump only for package @lerna/init - -# [3.7.0](https://github.com/lerna/lerna/compare/v3.6.0...v3.7.0) (2018-12-19) - -**Note:** Version bump only for package @lerna/init - -# [3.6.0](https://github.com/lerna/lerna/compare/v3.5.1...v3.6.0) (2018-12-07) - -**Note:** Version bump only for package @lerna/init - -# [3.5.0](https://github.com/lerna/lerna/compare/v3.4.3...v3.5.0) (2018-11-27) - -**Note:** Version bump only for package @lerna/init - - - -# [3.3.0](https://github.com/lerna/lerna/compare/v3.2.1...v3.3.0) (2018-09-06) - -### Features - -- **deps:** Upgrade fs-extra to ^7.0.0 ([042b1a3](https://github.com/lerna/lerna/commit/042b1a3)) - - - -## [3.1.3](https://github.com/lerna/lerna/compare/v3.1.2...v3.1.3) (2018-08-21) - -**Note:** Version bump only for package @lerna/init - - - -## [3.1.2](https://github.com/lerna/lerna/compare/v3.1.1...v3.1.2) (2018-08-20) - -**Note:** Version bump only for package @lerna/init - - - -# [3.1.0](https://github.com/lerna/lerna/compare/v3.0.6...v3.1.0) (2018-08-17) - -**Note:** Version bump only for package @lerna/init - - - -## [3.0.6](https://github.com/lerna/lerna/compare/v3.0.5...v3.0.6) (2018-08-16) - -### Bug Fixes - -- **init:** Consume lernaVersion from options, not instance property ([89e31d2](https://github.com/lerna/lerna/commit/89e31d2)) - - - -## [3.0.5](https://github.com/lerna/lerna/compare/v3.0.4...v3.0.5) (2018-08-15) - -**Note:** Version bump only for package @lerna/init - - - -# [3.0.0](https://github.com/lerna/lerna/compare/v3.0.0-rc.0...v3.0.0) (2018-08-10) - -**Note:** Version bump only for package @lerna/init - - - -# [3.0.0-rc.0](https://github.com/lerna/lerna/compare/v3.0.0-beta.21...v3.0.0-rc.0) (2018-07-27) - -### Features - -- Add description from --help summary [skip ci] ([9b65d8e](https://github.com/lerna/lerna/commit/9b65d8e)) -- Upgrade to fs-extra 6 ([079d873](https://github.com/lerna/lerna/commit/079d873)) -- **cli:** Upgrade to Yargs 12 ([7899ab8](https://github.com/lerna/lerna/commit/7899ab8)) -- **command:** Remove .defaultOptions() from option resolution stack ([2b27a54](https://github.com/lerna/lerna/commit/2b27a54)) - - - -# [3.0.0-beta.21](https://github.com/lerna/lerna/compare/v3.0.0-beta.20...v3.0.0-beta.21) (2018-05-12) - -**Note:** Version bump only for package @lerna/init - - - -# [3.0.0-beta.20](https://github.com/lerna/lerna/compare/v3.0.0-beta.19...v3.0.0-beta.20) (2018-05-07) - -**Note:** Version bump only for package @lerna/init - - - -# [3.0.0-beta.19](https://github.com/lerna/lerna/compare/v3.0.0-beta.18...v3.0.0-beta.19) (2018-05-03) - -**Note:** Version bump only for package @lerna/init - - - -# [3.0.0-beta.18](https://github.com/lerna/lerna/compare/v3.0.0-beta.17...v3.0.0-beta.18) (2018-04-24) - -### Features - -- **command:** Move GitUtilities.isInitialized into class method ([abecfcc](https://github.com/lerna/lerna/commit/abecfcc)) -- **init:** Inline GitUtilities.init() ([6e401e1](https://github.com/lerna/lerna/commit/6e401e1)) - -### BREAKING CHANGES - -- **init:** GitUtilities.init() no longer exists. You shouldn't be using GitUtilities. -- **command:** GitUtilities.isInitialized no longer exists. You shouldn't be using GitUtilities. - - - -# [3.0.0-beta.17](https://github.com/lerna/lerna/compare/v3.0.0-beta.16...v3.0.0-beta.17) (2018-04-13) - -**Note:** Version bump only for package @lerna/init - - - -# [3.0.0-beta.15](https://github.com/lerna/lerna/compare/v3.0.0-beta.14...v3.0.0-beta.15) (2018-04-09) - -**Note:** Version bump only for package @lerna/init - - - -# [3.0.0-beta.14](https://github.com/lerna/lerna/compare/v3.0.0-beta.13...v3.0.0-beta.14) (2018-04-03) - -**Note:** Version bump only for package @lerna/init - - - -# [3.0.0-beta.13](https://github.com/lerna/lerna/compare/v3.0.0-beta.12...v3.0.0-beta.13) (2018-03-31) - -**Note:** Version bump only for package @lerna/init - - - -# [3.0.0-beta.12](https://github.com/lerna/lerna/compare/v3.0.0-beta.11...v3.0.0-beta.12) (2018-03-30) - -### Features - -- **package:** Add `serialize()` method ([fdec3ac](https://github.com/lerna/lerna/commit/fdec3ac)) -- **package:** Add Map-like get/set methods, remove raw json getter ([707d1f0](https://github.com/lerna/lerna/commit/707d1f0)) -- **project:** Merge `package` and `packageJson` into `manifest` ([9a47ff7](https://github.com/lerna/lerna/commit/9a47ff7)) - -### BREAKING CHANGES - -- **package:** The `Package` class no longer provides direct access to the JSON object - used to construct the instance. Map-like `get()`/`set(val)` methods are - available to modify the internal representation. - - - -# [3.0.0-beta.11](https://github.com/lerna/lerna/compare/v3.0.0-beta.10...v3.0.0-beta.11) (2018-03-29) - -**Note:** Version bump only for package @lerna/init - - - -# [3.0.0-beta.10](https://github.com/lerna/lerna/compare/v3.0.0-beta.9...v3.0.0-beta.10) (2018-03-27) - -### Features - -- **commands:** Delay require of command instantiation ([a1284f3](https://github.com/lerna/lerna/commit/a1284f3)) - -### BREAKING CHANGES - -- **commands:** The default export of command packages is now a factory, not the subclass (which is now a named export). - - - -# [3.0.0-beta.9](https://github.com/lerna/lerna/compare/v3.0.0-beta.8...v3.0.0-beta.9) (2018-03-24) - -### Features - -- **command:** Rename this.repository -> this.project ([43e98a0](https://github.com/lerna/lerna/commit/43e98a0)) -- **project:** Normalize config.commands -> config.command ([24e55e3](https://github.com/lerna/lerna/commit/24e55e3)) -- **project:** Use cosmiconfig to locate and read lerna.json ([b8c2789](https://github.com/lerna/lerna/commit/b8c2789)) - - - -# [3.0.0-beta.8](https://github.com/lerna/lerna/compare/v3.0.0-beta.7...v3.0.0-beta.8) (2018-03-22) - -### Features - -- **init:** Improve ex-nihilo output ([7b80e07](https://github.com/lerna/lerna/commit/7b80e07)) - - - -# [3.0.0-beta.7](https://github.com/lerna/lerna/compare/v3.0.0-beta.6...v3.0.0-beta.7) (2018-03-20) - -### Bug Fixes - -- **cli:** Retrieve correct version ([bb2c5e8](https://github.com/lerna/lerna/commit/bb2c5e8)) - - - -# [3.0.0-beta.4](https://github.com/lerna/lerna/compare/v3.0.0-beta.3...v3.0.0-beta.4) (2018-03-19) - -**Note:** Version bump only for package @lerna/init - - - -# [3.0.0-beta.3](https://github.com/lerna/lerna/compare/v3.0.0-beta.2...v3.0.0-beta.3) (2018-03-15) - -### Bug Fixes - -- fs-extra dependency is a caret range, not exact ([81556d0](https://github.com/lerna/lerna/commit/81556d0)) - - - -# [3.0.0-beta.2](https://github.com/lerna/lerna/compare/v3.0.0-beta.1...v3.0.0-beta.2) (2018-03-10) - -### Features - -- Replace @lerna/fs-utils dependency with fs-extra ([9c35a86](https://github.com/lerna/lerna/commit/9c35a86)) - - - -# [3.0.0-beta.1](https://github.com/lerna/lerna/compare/v3.0.0-beta.0...v3.0.0-beta.1) (2018-03-09) - -### Bug Fixes - -- **init:** lerna init does not, in fact, require git ([d1d69c7](https://github.com/lerna/lerna/commit/d1d69c7)) diff --git a/commands/init/README.md b/commands/init/README.md deleted file mode 100644 index 1a0fdf28f0..0000000000 --- a/commands/init/README.md +++ /dev/null @@ -1,64 +0,0 @@ -# `@lerna/init` - -> Create a new Lerna repo or upgrade an existing repo to the current version of Lerna - -Install [lerna](https://www.npmjs.com/package/lerna) for access to the `lerna` CLI. - -## Usage - -```sh -$ lerna init -``` - -Create a new Lerna repo or upgrade an existing repo to the current version of Lerna. - -> Lerna assumes the repo has already been initialized with `git init`. - -When run, this command will: - -1. Add `lerna` as a [`devDependency`](https://docs.npmjs.com/files/package.json#devdependencies) in `package.json` if it doesn't already exist. -2. Create a `lerna.json` config file to store the `version` number. -3. Generate a `.gitignore` file if one doesn't already exist. - -Example output on a new git repo: - -```sh -$ lerna init -lerna info version v2.0.0 -lerna info Updating package.json -lerna info Creating lerna.json -lerna success Initialized Lerna files -``` - -## Options - -### `--independent` - -```sh -$ lerna init --independent -``` - -This flag tells Lerna to use independent versioning mode. - -### `--exact` - -```sh -$ lerna init --exact -``` - -By default, `lerna init` will use a caret range when adding or updating -the local version of `lerna`, just like `npm install --save-dev lerna`. - -To retain the `lerna` 1.x behavior of "exact" comparison, pass this flag. -It will configure `lerna.json` to enforce exact match for all subsequent executions. - -```json -{ - "command": { - "init": { - "exact": true - } - }, - "version": "0.0.0" -} -``` diff --git a/commands/init/__tests__/init-command.test.js b/commands/init/__tests__/init-command.test.js deleted file mode 100644 index f226cfaf59..0000000000 --- a/commands/init/__tests__/init-command.test.js +++ /dev/null @@ -1,449 +0,0 @@ -"use strict"; - -const fs = require("fs-extra"); -const path = require("path"); -const tempy = require("tempy"); - -const { loggingOutput } = require("@lerna-test/helpers/logging-output"); - -// helpers -const initFixture = require("@lerna-test/helpers").initFixtureFactory(__dirname); - -// file under test -const lernaInit = require("@lerna-test/helpers").commandRunner(require("../command")); - -describe("InitCommand", () => { - const lernaVersion = "__TEST_VERSION__"; - - it("should link to docs site after success", async () => { - const testDir = tempy.directory(); - - await lernaInit(testDir)(); - - const logMessages = loggingOutput("info"); - expect(logMessages).toContain( - "New to Lerna? Check out the docs: https://lerna.js.org/docs/getting-started" - ); - }); - - describe("in an empty directory", () => { - it("initializes git repo with lerna files", async () => { - const testDir = tempy.directory(); - - await lernaInit(testDir)(); - - const [lernaJson, pkgJson, packagesDirExists, gitDirExists] = await Promise.all([ - fs.readJSON(path.join(testDir, "lerna.json")), - fs.readJSON(path.join(testDir, "package.json")), - fs.exists(path.join(testDir, "packages")), - fs.exists(path.join(testDir, ".git")), - ]); - - expect(lernaJson).toMatchInlineSnapshot(` - Object { - "$schema": "node_modules/lerna/schemas/lerna-schema.json", - "useWorkspaces": true, - "version": "0.0.0", - } - `); - expect(pkgJson).toMatchInlineSnapshot(` - Object { - "devDependencies": Object { - "lerna": "^__TEST_VERSION__", - }, - "name": "root", - "private": true, - "workspaces": Array [ - "packages/*", - ], - } - `); - expect(packagesDirExists).toBe(true); - expect(gitDirExists).toBe(true); - }); - - it("initializes .gitignore", async () => { - const testDir = tempy.directory(); - - await lernaInit(testDir)(); - - const gitIgnorePath = path.join(testDir, ".gitignore"); - const gitIgnoreContent = await fs.readFile(gitIgnorePath, "utf8"); - - expect(gitIgnoreContent).toMatchInlineSnapshot(`"node_modules/"`); - }); - - it("initializes git repo with lerna files in independent mode", async () => { - const testDir = tempy.directory(); - - await lernaInit(testDir)("--independent"); - - expect(await fs.readJSON(path.join(testDir, "lerna.json"))).toHaveProperty("version", "independent"); - }); - - describe("with --exact", () => { - it("uses exact version when adding lerna dependency", async () => { - const testDir = tempy.directory(); - - await lernaInit(testDir)("--exact"); - - expect(await fs.readJSON(path.join(testDir, "package.json"))).toMatchObject({ - devDependencies: { - lerna: lernaVersion, - }, - }); - }); - - it("sets lerna.json command.init.exact to true", async () => { - const testDir = tempy.directory(); - - await lernaInit(testDir)("--exact"); - - expect(await fs.readJSON(path.join(testDir, "lerna.json"))).toMatchObject({ - $schema: "node_modules/lerna/schemas/lerna-schema.json", - command: { - init: { - exact: true, - }, - }, - }); - }); - }); - - it("creates packages directory", async () => { - const testDir = tempy.directory(); - - await lernaInit(testDir)(); - - expect(fs.existsSync(path.join(testDir, "packages"))).toBe(true); - }); - }); - - describe("in a subdirectory of a git repo", () => { - it("creates lerna files", async () => { - const dir = await initFixture("empty"); - const testDir = path.join(dir, "subdir"); - - await fs.ensureDir(testDir); - await lernaInit(testDir)(); - - const [lernaJson, pkgJson, packagesDirExists] = await Promise.all([ - fs.readJSON(path.join(testDir, "lerna.json")), - fs.readJSON(path.join(testDir, "package.json")), - fs.exists(path.join(testDir, "packages")), - ]); - - expect(lernaJson).toMatchInlineSnapshot(` - Object { - "$schema": "node_modules/lerna/schemas/lerna-schema.json", - "useWorkspaces": true, - "version": "0.0.0", - } - `); - expect(pkgJson).toMatchInlineSnapshot(` - Object { - "devDependencies": Object { - "lerna": "^__TEST_VERSION__", - }, - "name": "root", - "private": true, - "workspaces": Array [ - "packages/*", - ], - } - `); - expect(packagesDirExists).toBe(true); - }); - }); - - describe("when .gitignore exists", () => { - it("does not change existing .gitignore", async () => { - const testDir = await tempy.directory(); - - const gitIgnorePath = path.join(testDir, ".gitignore"); - await fs.writeFile(gitIgnorePath, "dist/"); - - await lernaInit(testDir)(); - - const gitIgnoreContent = await fs.readFile(gitIgnorePath, "utf8"); - - expect(gitIgnoreContent).toMatchInlineSnapshot(`"dist/"`); - }); - }); - - describe("when package.json exists", () => { - it("adds lerna to sorted devDependencies", async () => { - const testDir = await initFixture("has-package"); - const pkgJsonPath = path.join(testDir, "package.json"); - - await fs.outputJSON(pkgJsonPath, { - devDependencies: { - alpha: "first", - omega: "last", - }, - }); - - await lernaInit(testDir)(); - - expect(await fs.readJSON(pkgJsonPath)).toMatchObject({ - devDependencies: { - alpha: "first", - lerna: `^${lernaVersion}`, - omega: "last", - }, - }); - }); - - it("updates existing lerna in devDependencies", async () => { - const testDir = await initFixture("has-package"); - const pkgJsonPath = path.join(testDir, "package.json"); - - await fs.outputJSON(pkgJsonPath, { - dependencies: { - alpha: "first", - omega: "last", - }, - devDependencies: { - lerna: "0.1.100", - }, - }); - - await lernaInit(testDir)(); - - expect(await fs.readJSON(pkgJsonPath)).toMatchObject({ - dependencies: { - alpha: "first", - omega: "last", - }, - devDependencies: { - lerna: `^${lernaVersion}`, - }, - }); - }); - - it("updates existing lerna in sorted dependencies", async () => { - const testDir = await initFixture("has-package"); - const pkgJsonPath = path.join(testDir, "package.json"); - - await fs.outputJSON(pkgJsonPath, { - dependencies: { - alpha: "first", - lerna: "0.1.100", - omega: "last", - }, - }); - - await lernaInit(testDir)(); - - expect(await fs.readJSON(pkgJsonPath)).toMatchObject({ - dependencies: { - alpha: "first", - lerna: `^${lernaVersion}`, - omega: "last", - }, - }); - }); - - describe("when workspaces are already configured", () => { - it("does not overwrite existing workspaces", async () => { - const testDir = await initFixture("has-package"); - const pkgJsonPath = path.join(testDir, "package.json"); - - await fs.outputJSON(pkgJsonPath, { - workspaces: ["modules/*", "others/*"], - }); - - await lernaInit(testDir)(); - - expect(await fs.readJSON(pkgJsonPath)).toMatchObject({ - workspaces: ["modules/*", "others/*"], - }); - }); - }); - - describe("when workspaces are not yet configured", () => { - it("sets workspaces to include default packages location", async () => { - const testDir = await initFixture("has-package"); - const pkgJsonPath = path.join(testDir, "package.json"); - - await lernaInit(testDir)(); - - expect(await fs.readJSON(pkgJsonPath)).toMatchObject({ - workspaces: ["packages/*"], - }); - }); - }); - }); - - describe("when lerna.json exists", () => { - describe("when useWorkspaces is false or missing", () => { - it("updates to explicitly set $schema, and packages", async () => { - const testDir = await initFixture("has-lerna"); - const lernaJsonPath = path.join(testDir, "lerna.json"); - - await fs.outputJSON(lernaJsonPath, { - lerna: "0.1.100", - version: "1.2.3", - }); - - await lernaInit(testDir)(); - - expect(await fs.readJSON(lernaJsonPath)).toMatchInlineSnapshot(` - Object { - "$schema": "node_modules/lerna/schemas/lerna-schema.json", - "packages": Array [ - "packages/*", - ], - "useWorkspaces": false, - "version": "1.2.3", - } - `); - }); - }); - - it("creates package.json without workspaces configured", async () => { - const testDir = await initFixture("has-lerna"); - const lernaJsonPath = path.join(testDir, "lerna.json"); - const packageJsonPath = path.join(testDir, "package.json"); - - await fs.outputJSON(lernaJsonPath, { - lerna: "0.1.100", - version: "1.2.3", - }); - - await lernaInit(testDir)(); - - expect(await fs.readJSON(packageJsonPath)).toMatchInlineSnapshot(` - Object { - "devDependencies": Object { - "lerna": "^__TEST_VERSION__", - }, - "name": "root", - "private": true, - } - `); - }); - - it("creates package directories when glob is configured", async () => { - const testDir = await initFixture("has-lerna"); - const lernaJsonPath = path.join(testDir, "lerna.json"); - - await fs.outputJSON(lernaJsonPath, { - version: "1.2.3", - packages: ["modules/*"], - }); - - await lernaInit(testDir)(); - - expect(await fs.exists(path.join(testDir, "modules"))).toBe(true); - }); - - describe("when useNx is false", () => { - it("preserves useNx false", async () => { - const testDir = await initFixture("has-lerna"); - const lernaJsonPath = path.join(testDir, "lerna.json"); - - await fs.outputJSON(lernaJsonPath, { - lerna: "0.1.100", - version: "1.2.3", - useNx: false, - }); - - await lernaInit(testDir)(); - - expect(await fs.readJSON(lernaJsonPath)).toMatchInlineSnapshot(` - Object { - "$schema": "node_modules/lerna/schemas/lerna-schema.json", - "packages": Array [ - "packages/*", - ], - "useNx": false, - "useWorkspaces": false, - "version": "1.2.3", - } - `); - - expect(await fs.readJSON(path.join(testDir, "package.json"))).toMatchInlineSnapshot(` - Object { - "devDependencies": Object { - "lerna": "^__TEST_VERSION__", - }, - "name": "root", - "private": true, - } - `); - }); - }); - - describe("when useNx is true", () => { - it("removes useNx true as it would do nothing", async () => { - const testDir = await initFixture("has-lerna"); - const lernaJsonPath = path.join(testDir, "lerna.json"); - - await fs.outputJSON(lernaJsonPath, { - lerna: "0.1.100", - version: "1.2.3", - useNx: true, - }); - - await lernaInit(testDir)(); - - expect(await fs.readJSON(lernaJsonPath)).toMatchInlineSnapshot(` - Object { - "$schema": "node_modules/lerna/schemas/lerna-schema.json", - "packages": Array [ - "packages/*", - ], - "useWorkspaces": false, - "version": "1.2.3", - } - `); - }); - }); - }); - - describe("when re-initializing with --exact", () => { - it("sets lerna.json command.init.exact to true and explicitly sets useWorkspaces, $schema, and packages", async () => { - const testDir = await initFixture("updates"); - const lernaJsonPath = path.join(testDir, "lerna.json"); - const pkgJsonPath = path.join(testDir, "package.json"); - - await fs.outputJSON(lernaJsonPath, { - lerna: "0.1.100", - commands: { - bootstrap: { - hoist: true, - }, - }, - $schema: "node_modules/lerna/schemas/lerna-schema.json", - version: "1.2.3", - }); - await fs.outputJSON(pkgJsonPath, { - devDependencies: { - lerna: lernaVersion, - }, - }); - - await lernaInit(testDir)("--exact"); - - expect(await fs.readJSON(lernaJsonPath)).toMatchInlineSnapshot(` - Object { - "$schema": "node_modules/lerna/schemas/lerna-schema.json", - "command": Object { - "bootstrap": Object { - "hoist": true, - }, - "init": Object { - "exact": true, - }, - }, - "packages": Array [ - "packages/*", - ], - "useWorkspaces": false, - "version": "1.2.3", - } - `); - }); - }); -}); diff --git a/commands/init/command.js b/commands/init/command.js deleted file mode 100644 index 832b846889..0000000000 --- a/commands/init/command.js +++ /dev/null @@ -1,24 +0,0 @@ -"use strict"; - -/** - * @see https://github.com/yargs/yargs/blob/master/docs/advanced.md#providing-a-command-module - */ -exports.command = "init"; - -exports.describe = "Create a new Lerna repo or upgrade an existing repo to the current version of Lerna."; - -exports.builder = { - exact: { - describe: "Specify lerna dependency version in package.json without a caret (^)", - type: "boolean", - }, - independent: { - describe: "Version packages independently", - alias: "i", - type: "boolean", - }, -}; - -exports.handler = function handler(argv) { - return require(".")(argv); -}; diff --git a/commands/init/index.js b/commands/init/index.js deleted file mode 100644 index 62ffc51377..0000000000 --- a/commands/init/index.js +++ /dev/null @@ -1,184 +0,0 @@ -"use strict"; - -const fs = require("fs-extra"); -const path = require("path"); -const pMap = require("p-map"); -const writeJsonFile = require("write-json-file"); - -const { Command } = require("@lerna/command"); -const childProcess = require("@lerna/child-process"); -const { Project } = require("@lerna/project"); - -module.exports = factory; - -function factory(argv) { - return new InitCommand(argv); -} - -class InitCommand extends Command { - get requiresGit() { - return false; - } - - runValidations() { - this.logger.verbose(this.name, "skipping validations"); - } - - runPreparations() { - this.logger.verbose(this.name, "skipping preparations"); - } - - initialize() { - this.exact = this.options.exact; - this.lernaVersion = this.options.lernaVersion; - - if (!this.gitInitialized()) { - this.logger.info("", "Initializing Git repository"); - - return childProcess.exec("git", ["init"], this.execOpts); - } - } - - execute() { - let chain = Promise.resolve(); - - chain = chain.then(() => this.ensureGitIgnore()); - chain = chain.then(() => this.ensureConfig()); - chain = chain.then(() => this.ensurePackagesDir()); - - return chain.then(() => { - this.logger.success("", "Initialized Lerna files"); - this.logger.info("", "New to Lerna? Check out the docs: https://lerna.js.org/docs/getting-started"); - }); - } - - ensureGitIgnore() { - const gitIgnorePath = path.join(this.project.rootPath, ".gitignore"); - - let chain = Promise.resolve(); - - if (!fs.existsSync(gitIgnorePath)) { - this.logger.info("", "Creating .gitignore"); - chain = chain.then(() => fs.writeFile(gitIgnorePath, "node_modules/")); - } - - return chain; - } - - ensureConfig() { - const hasExistingLernaConfig = !!this.project.version; - const hasExistingPackageJson = !!this.project.manifest; - - const useNx = !hasExistingLernaConfig || this.project.config.useNx !== false; - const useWorkspaces = !hasExistingLernaConfig || this.project.config.useWorkspaces === true; - - let chain = Promise.resolve(); - - if (!hasExistingPackageJson) { - this.logger.info("", "Creating package.json"); - - // initialize with default indentation so write-pkg doesn't screw it up with tabs - chain = chain.then(() => { - const pkg = { - name: "root", - private: true, - }; - - if (useWorkspaces) { - pkg.workspaces = [Project.PACKAGE_GLOB]; - } - - return writeJsonFile(path.join(this.project.rootPath, "package.json"), pkg, { indent: 2 }); - }); - } else { - this.logger.info("", "Updating package.json"); - - chain = chain.then(() => { - if (useWorkspaces && !this.project.manifest.get("workspaces")) { - this.project.manifest.set("workspaces", [Project.PACKAGE_GLOB]); - - return this.project.manifest.serialize(); - } - }); - } - - // add dependencies to package.json - chain = chain.then(() => { - const rootPkg = this.project.manifest; - - const setDependency = ({ name, version }) => { - let targetDependencies; - - if (rootPkg.dependencies && rootPkg.dependencies[name]) { - targetDependencies = rootPkg.dependencies; - } else { - if (!rootPkg.devDependencies) { - rootPkg.set("devDependencies", {}); - } - - targetDependencies = rootPkg.devDependencies; - } - - targetDependencies[name] = this.exact ? version : `^${version}`; - }; - - setDependency({ name: "lerna", version: this.lernaVersion }); - - return rootPkg.serialize(); - }); - - chain = chain.then(() => { - let version; - - if (this.options.independent) { - version = "independent"; - } else if (this.project.version) { - version = this.project.version; - } else { - version = "0.0.0"; - } - - if (!hasExistingLernaConfig) { - this.logger.info("", "Creating lerna.json"); - } else { - this.logger.info("", "Updating lerna.json"); - - if (!useWorkspaces && !this.project.config.packages) { - Object.assign(this.project.config, { - packages: [Project.PACKAGE_GLOB], - }); - } - } - - delete this.project.config.lerna; // no longer relevant - - if (this.exact) { - // ensure --exact is preserved for future init commands - const commandConfig = this.project.config.command || (this.project.config.command = {}); - const initConfig = commandConfig.init || (commandConfig.init = {}); - - initConfig.exact = true; - } - - Object.assign(this.project.config, { - $schema: "node_modules/lerna/schemas/lerna-schema.json", - useWorkspaces, - version, - // Only set if explicitly disabling - useNx: useNx === false ? false : undefined, - }); - - return this.project.serializeConfig(); - }); - - return chain; - } - - ensurePackagesDir() { - this.logger.info("", "Creating packages directory"); - - return pMap(this.project.packageParentDirs, (dir) => fs.mkdirp(dir)); - } -} - -module.exports.InitCommand = InitCommand; diff --git a/commands/init/package.json b/commands/init/package.json deleted file mode 100644 index 4b604f564b..0000000000 --- a/commands/init/package.json +++ /dev/null @@ -1,42 +0,0 @@ -{ - "name": "@lerna/init", - "version": "6.4.1", - "description": "Create a new Lerna repo or upgrade an existing repo to the current version of Lerna", - "keywords": [ - "lerna", - "command" - ], - "homepage": "https://lerna.js.org", - "license": "MIT", - "author": { - "name": "Daniel Stockman", - "url": "https://github.com/evocateur" - }, - "files": [ - "command.js", - "index.js" - ], - "main": "index.js", - "engines": { - "node": "^14.15.0 || >=16.0.0" - }, - "publishConfig": { - "access": "public" - }, - "repository": { - "type": "git", - "url": "git+https://github.com/lerna/lerna.git", - "directory": "commands/init" - }, - "scripts": { - "test": "echo \"Run tests from root\" && exit 1" - }, - "dependencies": { - "@lerna/child-process": "file:../../core/child-process", - "@lerna/command": "file:../../core/command", - "@lerna/project": "file:../../core/project", - "fs-extra": "^9.1.0", - "p-map": "^4.0.0", - "write-json-file": "^4.3.0" - } -} diff --git a/commands/link/CHANGELOG.md b/commands/link/CHANGELOG.md deleted file mode 100644 index e79628722c..0000000000 --- a/commands/link/CHANGELOG.md +++ /dev/null @@ -1,447 +0,0 @@ -# Change Log - -All notable changes to this project will be documented in this file. -See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. - -## [6.4.1](https://github.com/lerna/lerna/compare/v6.4.0...v6.4.1) (2023-01-12) - -**Note:** Version bump only for package @lerna/link - -# [6.4.0](https://github.com/lerna/lerna/compare/v6.3.0...v6.4.0) (2023-01-05) - -**Note:** Version bump only for package @lerna/link - -# [6.3.0](https://github.com/lerna/lerna/compare/v6.2.0...v6.3.0) (2022-12-26) - -**Note:** Version bump only for package @lerna/link - -# [6.2.0](https://github.com/lerna/lerna/compare/v6.1.0...v6.2.0) (2022-12-13) - -**Note:** Version bump only for package @lerna/link - -# [6.1.0](https://github.com/lerna/lerna/compare/v6.0.3...v6.1.0) (2022-11-29) - -**Note:** Version bump only for package @lerna/link - -## [6.0.3](https://github.com/lerna/lerna/compare/v6.0.2...v6.0.3) (2022-11-07) - -**Note:** Version bump only for package @lerna/link - -## [6.0.2](https://github.com/lerna/lerna/compare/v6.0.1...v6.0.2) (2022-11-02) - -**Note:** Version bump only for package @lerna/link - -## [6.0.1](https://github.com/lerna/lerna/compare/v6.0.0...v6.0.1) (2022-10-14) - -**Note:** Version bump only for package @lerna/link - -# [6.0.0](https://github.com/lerna/lerna/compare/v6.0.0-alpha.2...v6.0.0) (2022-10-12) - -**Note:** Version bump only for package @lerna/link - -# [6.0.0-alpha.2](https://github.com/lerna/lerna/compare/v6.0.0-alpha.1...v6.0.0-alpha.2) (2022-10-12) - -**Note:** Version bump only for package @lerna/link - -# [6.0.0-alpha.1](https://github.com/lerna/lerna/compare/v5.6.2...v6.0.0-alpha.1) (2022-10-09) - -# [6.0.0-alpha.0](https://github.com/lerna/lerna/compare/v5.6.1...v6.0.0-alpha.0) (2022-10-07) - -**Note:** Version bump only for package @lerna/link - -## [5.6.2](https://github.com/lerna/lerna/compare/v5.6.1...v5.6.2) (2022-10-09) - -**Note:** Version bump only for package @lerna/link - -## [5.6.1](https://github.com/lerna/lerna/compare/v5.6.0...v5.6.1) (2022-09-30) - -**Note:** Version bump only for package @lerna/link - -# [5.6.0](https://github.com/lerna/lerna/compare/v5.5.4...v5.6.0) (2022-09-29) - -**Note:** Version bump only for package @lerna/link - -## [5.5.4](https://github.com/lerna/lerna/compare/v5.5.3...v5.5.4) (2022-09-28) - -**Note:** Version bump only for package @lerna/link - -## [5.5.3](https://github.com/lerna/lerna/compare/v5.5.2...v5.5.3) (2022-09-28) - -**Note:** Version bump only for package @lerna/link - -## [5.5.2](https://github.com/lerna/lerna/compare/v5.5.1...v5.5.2) (2022-09-20) - -**Note:** Version bump only for package @lerna/link - -## [5.5.1](https://github.com/lerna/lerna/compare/v5.5.0...v5.5.1) (2022-09-09) - -**Note:** Version bump only for package @lerna/link - -# [5.5.0](https://github.com/lerna/lerna/compare/v5.4.3...v5.5.0) (2022-08-31) - -### Features - -- pnpm workspaces support ([#3284](https://github.com/lerna/lerna/issues/3284)) ([1b18dbe](https://github.com/lerna/lerna/commit/1b18dbeb03e98c70b5428a9fe457781a59f8d65d)) - -## [5.4.3](https://github.com/lerna/lerna/compare/v5.4.2...v5.4.3) (2022-08-16) - -**Note:** Version bump only for package @lerna/link - -## [5.4.2](https://github.com/lerna/lerna/compare/v5.4.1...v5.4.2) (2022-08-14) - -**Note:** Version bump only for package @lerna/link - -## [5.4.1](https://github.com/lerna/lerna/compare/v5.4.0...v5.4.1) (2022-08-12) - -**Note:** Version bump only for package @lerna/link - -# [5.4.0](https://github.com/lerna/lerna/compare/v5.3.0...v5.4.0) (2022-08-08) - -**Note:** Version bump only for package @lerna/link - -# [5.3.0](https://github.com/lerna/lerna/compare/v5.2.0...v5.3.0) (2022-07-27) - -**Note:** Version bump only for package @lerna/link - -# [5.2.0](https://github.com/lerna/lerna/compare/v5.1.8...v5.2.0) (2022-07-22) - -**Note:** Version bump only for package @lerna/link - -## [5.1.8](https://github.com/lerna/lerna/compare/v5.1.7...v5.1.8) (2022-07-07) - -**Note:** Version bump only for package @lerna/link - -## [5.1.7](https://github.com/lerna/lerna/compare/v5.1.6...v5.1.7) (2022-07-06) - -**Note:** Version bump only for package @lerna/link - -## [5.1.6](https://github.com/lerna/lerna/compare/v5.1.5...v5.1.6) (2022-06-24) - -**Note:** Version bump only for package @lerna/link - -## [5.1.5](https://github.com/lerna/lerna/compare/v5.1.4...v5.1.5) (2022-06-24) - -**Note:** Version bump only for package @lerna/link - -## [5.1.4](https://github.com/lerna/lerna/compare/v5.1.3...v5.1.4) (2022-06-15) - -**Note:** Version bump only for package @lerna/link - -## [5.1.3](https://github.com/lerna/lerna/compare/v5.1.2...v5.1.3) (2022-06-15) - -**Note:** Version bump only for package @lerna/link - -## [5.1.2](https://github.com/lerna/lerna/compare/v5.1.1...v5.1.2) (2022-06-13) - -**Note:** Version bump only for package @lerna/link - -## [5.1.1](https://github.com/lerna/lerna/compare/v5.1.0...v5.1.1) (2022-06-09) - -### Bug Fixes - -- allow maintenance LTS node 14 engines starting at 14.15.0 ([#3161](https://github.com/lerna/lerna/issues/3161)) ([72305e4](https://github.com/lerna/lerna/commit/72305e4dbab607a2d87ae4efa6ee577c93a9dda9)) - -# [5.1.0](https://github.com/lerna/lerna/compare/v5.0.0...v5.1.0) (2022-06-07) - -**Note:** Version bump only for package @lerna/link - -# [5.1.0-alpha.0](https://github.com/lerna/lerna/compare/v4.0.0...v5.1.0-alpha.0) (2022-05-25) - -**Note:** Version bump only for package @lerna/link - -# [5.0.0](https://github.com/lerna/lerna/compare/v4.0.0...v5.0.0) (2022-05-24) - -**Note:** Version bump only for package @lerna/link - -# [4.0.0](https://github.com/lerna/lerna/compare/v3.22.1...v4.0.0) (2021-02-10) - -### Features - -- Consume named exports of sibling modules ([63499e3](https://github.com/lerna/lerna/commit/63499e33652bc78fe23751875d74017e2f16a689)) -- **deps:** p-map@^4.0.0 ([92b1364](https://github.com/lerna/lerna/commit/92b1364735e1f2cf379cf1047c60c4fb897d55f5)) -- **deps:** slash@^3.0.0 ([5dec383](https://github.com/lerna/lerna/commit/5dec383109bcd1cce9abbc80796369db9314acc9)) -- Drop support for Node v6.x & v8.x ([ff4bb4d](https://github.com/lerna/lerna/commit/ff4bb4da215555e3bb136f5af09b5cbc631e57bb)) - -### BREAKING CHANGES - -- Node v6.x & v8.x are no longer supported. Please upgrade to the latest LTS release. - -Here's the gnarly one-liner I used to make these changes: - -``` -npx lerna exec --concurrency 1 --stream -- 'json -I -f package.json -e '"'"'this.engines=this.engines||{};this.engines.node=">= 10.18.0"'"'" -``` - -(requires `npm i -g json` beforehand) - -# [3.21.0](https://github.com/lerna/lerna/compare/v3.20.2...v3.21.0) (2020-05-13) - -**Note:** Version bump only for package @lerna/link - -## [3.18.5](https://github.com/lerna/lerna/compare/v3.18.4...v3.18.5) (2019-11-20) - -**Note:** Version bump only for package @lerna/link - -# [3.18.0](https://github.com/lerna/lerna/compare/v3.17.0...v3.18.0) (2019-10-15) - -**Note:** Version bump only for package @lerna/link - -# [3.17.0](https://github.com/lerna/lerna/compare/v3.16.5...v3.17.0) (2019-10-10) - -### Features - -- **link:** Use `publishConfig.directory` as symlink source if it exists to allow linking sub-directories ([#2274](https://github.com/lerna/lerna/issues/2274)) ([d04ce8e](https://github.com/lerna/lerna/commit/d04ce8e10503003e498c44d0db5ff455054d7d71)) - -## [3.16.5](https://github.com/lerna/lerna/compare/v3.16.4...v3.16.5) (2019-10-07) - -**Note:** Version bump only for package @lerna/link - -## [3.16.2](https://github.com/lerna/lerna/compare/v3.16.1...v3.16.2) (2019-07-22) - -**Note:** Version bump only for package @lerna/link - -# [3.16.0](https://github.com/lerna/lerna/compare/v3.15.0...v3.16.0) (2019-07-18) - -### Features - -- **deps:** `p-map@^2.1.0` ([9e58394](https://github.com/lerna/lerna/commit/9e58394)) -- **deps:** `slash@^2.0.0` ([bedd6af](https://github.com/lerna/lerna/commit/bedd6af)) - -# [3.15.0](https://github.com/lerna/lerna/compare/v3.14.2...v3.15.0) (2019-06-09) - -**Note:** Version bump only for package @lerna/link - -## [3.14.2](https://github.com/lerna/lerna/compare/v3.14.1...v3.14.2) (2019-06-09) - -**Note:** Version bump only for package @lerna/link - -# [3.14.0](https://github.com/lerna/lerna/compare/v3.13.4...v3.14.0) (2019-05-14) - -**Note:** Version bump only for package @lerna/link - -## [3.13.3](https://github.com/lerna/lerna/compare/v3.13.2...v3.13.3) (2019-04-17) - -**Note:** Version bump only for package @lerna/link - -## [3.13.1](https://github.com/lerna/lerna/compare/v3.13.0...v3.13.1) (2019-02-26) - -**Note:** Version bump only for package @lerna/link - -# [3.13.0](https://github.com/lerna/lerna/compare/v3.12.1...v3.13.0) (2019-02-15) - -### Features - -- **meta:** Add `repository.directory` field to package.json ([aec5023](https://github.com/lerna/lerna/commit/aec5023)) -- **meta:** Normalize package.json `homepage` field ([abeb4dc](https://github.com/lerna/lerna/commit/abeb4dc)) - -# [3.12.0](https://github.com/lerna/lerna/compare/v3.11.1...v3.12.0) (2019-02-14) - -**Note:** Version bump only for package @lerna/link - -# [3.11.0](https://github.com/lerna/lerna/compare/v3.10.8...v3.11.0) (2019-02-08) - -**Note:** Version bump only for package @lerna/link - -## [3.10.6](https://github.com/lerna/lerna/compare/v3.10.5...v3.10.6) (2019-01-19) - -**Note:** Version bump only for package @lerna/link - -# [3.10.0](https://github.com/lerna/lerna/compare/v3.9.1...v3.10.0) (2019-01-08) - -**Note:** Version bump only for package @lerna/link - -## [3.8.5](https://github.com/lerna/lerna/compare/v3.8.4...v3.8.5) (2019-01-05) - -**Note:** Version bump only for package @lerna/link - -## [3.8.1](https://github.com/lerna/lerna/compare/v3.8.0...v3.8.1) (2018-12-31) - -**Note:** Version bump only for package @lerna/link - -## [3.7.2](https://github.com/lerna/lerna/compare/v3.7.1...v3.7.2) (2018-12-21) - -**Note:** Version bump only for package @lerna/link - -## [3.7.1](https://github.com/lerna/lerna/compare/v3.7.0...v3.7.1) (2018-12-20) - -**Note:** Version bump only for package @lerna/link - -# [3.7.0](https://github.com/lerna/lerna/compare/v3.6.0...v3.7.0) (2018-12-19) - -**Note:** Version bump only for package @lerna/link - -# [3.6.0](https://github.com/lerna/lerna/compare/v3.5.1...v3.6.0) (2018-12-07) - -**Note:** Version bump only for package @lerna/link - -# [3.5.0](https://github.com/lerna/lerna/compare/v3.4.3...v3.5.0) (2018-11-27) - -**Note:** Version bump only for package @lerna/link - - - -# [3.3.0](https://github.com/lerna/lerna/compare/v3.2.1...v3.3.0) (2018-09-06) - -**Note:** Version bump only for package @lerna/link - - - -## [3.1.4](https://github.com/lerna/lerna/compare/v3.1.3...v3.1.4) (2018-08-21) - -**Note:** Version bump only for package @lerna/link - - - -## [3.1.3](https://github.com/lerna/lerna/compare/v3.1.2...v3.1.3) (2018-08-21) - -**Note:** Version bump only for package @lerna/link - - - -## [3.1.2](https://github.com/lerna/lerna/compare/v3.1.1...v3.1.2) (2018-08-20) - -**Note:** Version bump only for package @lerna/link - - - -# [3.1.0](https://github.com/lerna/lerna/compare/v3.0.6...v3.1.0) (2018-08-17) - -**Note:** Version bump only for package @lerna/link - - - -## [3.0.6](https://github.com/lerna/lerna/compare/v3.0.5...v3.0.6) (2018-08-16) - -**Note:** Version bump only for package @lerna/link - - - -## [3.0.5](https://github.com/lerna/lerna/compare/v3.0.4...v3.0.5) (2018-08-15) - -**Note:** Version bump only for package @lerna/link - - - -# [3.0.0](https://github.com/lerna/lerna/compare/v3.0.0-rc.0...v3.0.0) (2018-08-10) - -**Note:** Version bump only for package @lerna/link - - - -# [3.0.0-rc.0](https://github.com/lerna/lerna/compare/v3.0.0-beta.21...v3.0.0-rc.0) (2018-07-27) - -### Features - -- Add description from --help summary [skip ci] ([9b65d8e](https://github.com/lerna/lerna/commit/9b65d8e)) -- **cli:** Upgrade to Yargs 12 ([7899ab8](https://github.com/lerna/lerna/commit/7899ab8)) -- **command:** Remove .defaultOptions() from option resolution stack ([2b27a54](https://github.com/lerna/lerna/commit/2b27a54)) - - - -# [3.0.0-beta.21](https://github.com/lerna/lerna/compare/v3.0.0-beta.20...v3.0.0-beta.21) (2018-05-12) - -**Note:** Version bump only for package @lerna/link - - - -# [3.0.0-beta.20](https://github.com/lerna/lerna/compare/v3.0.0-beta.19...v3.0.0-beta.20) (2018-05-07) - -**Note:** Version bump only for package @lerna/link - - - -# [3.0.0-beta.19](https://github.com/lerna/lerna/compare/v3.0.0-beta.18...v3.0.0-beta.19) (2018-05-03) - -**Note:** Version bump only for package @lerna/link - - - -# [3.0.0-beta.18](https://github.com/lerna/lerna/compare/v3.0.0-beta.17...v3.0.0-beta.18) (2018-04-24) - -**Note:** Version bump only for package @lerna/link - - - -# [3.0.0-beta.17](https://github.com/lerna/lerna/compare/v3.0.0-beta.16...v3.0.0-beta.17) (2018-04-13) - -### Features - -- **link:** Add 'convert' subcommand to aid migration to local file: specifiers ([f59bf3c](https://github.com/lerna/lerna/commit/f59bf3c)) - - - -# [3.0.0-beta.15](https://github.com/lerna/lerna/compare/v3.0.0-beta.14...v3.0.0-beta.15) (2018-04-09) - -**Note:** Version bump only for package @lerna/link - - - -# [3.0.0-beta.14](https://github.com/lerna/lerna/compare/v3.0.0-beta.13...v3.0.0-beta.14) (2018-04-03) - -**Note:** Version bump only for package @lerna/link - - - -# [3.0.0-beta.13](https://github.com/lerna/lerna/compare/v3.0.0-beta.12...v3.0.0-beta.13) (2018-03-31) - -**Note:** Version bump only for package @lerna/link - - - -# [3.0.0-beta.12](https://github.com/lerna/lerna/compare/v3.0.0-beta.11...v3.0.0-beta.12) (2018-03-30) - -**Note:** Version bump only for package @lerna/link - - - -# [3.0.0-beta.11](https://github.com/lerna/lerna/compare/v3.0.0-beta.10...v3.0.0-beta.11) (2018-03-29) - -**Note:** Version bump only for package @lerna/link - - - -# [3.0.0-beta.10](https://github.com/lerna/lerna/compare/v3.0.0-beta.9...v3.0.0-beta.10) (2018-03-27) - -### Features - -- **commands:** Delay require of command instantiation ([a1284f3](https://github.com/lerna/lerna/commit/a1284f3)) - -### BREAKING CHANGES - -- **commands:** The default export of command packages is now a factory, not the subclass (which is now a named export). - - - -# [3.0.0-beta.9](https://github.com/lerna/lerna/compare/v3.0.0-beta.8...v3.0.0-beta.9) (2018-03-24) - -**Note:** Version bump only for package @lerna/link - - - -# [3.0.0-beta.7](https://github.com/lerna/lerna/compare/v3.0.0-beta.6...v3.0.0-beta.7) (2018-03-20) - -**Note:** Version bump only for package @lerna/link - - - -# [3.0.0-beta.4](https://github.com/lerna/lerna/compare/v3.0.0-beta.3...v3.0.0-beta.4) (2018-03-19) - -**Note:** Version bump only for package @lerna/link - - - -# [3.0.0-beta.3](https://github.com/lerna/lerna/compare/v3.0.0-beta.2...v3.0.0-beta.3) (2018-03-15) - -**Note:** Version bump only for package @lerna/link - - - -# [3.0.0-beta.2](https://github.com/lerna/lerna/compare/v3.0.0-beta.1...v3.0.0-beta.2) (2018-03-10) - -**Note:** Version bump only for package @lerna/link - - - -# [3.0.0-beta.1](https://github.com/lerna/lerna/compare/v3.0.0-beta.0...v3.0.0-beta.1) (2018-03-09) - -**Note:** Version bump only for package @lerna/link diff --git a/commands/link/README.md b/commands/link/README.md deleted file mode 100644 index 3d34c8b6fc..0000000000 --- a/commands/link/README.md +++ /dev/null @@ -1,35 +0,0 @@ -# `@lerna/link` - -> Symlink together all packages that are dependencies of each other - -Install [lerna](https://www.npmjs.com/package/lerna) for access to the `lerna` CLI. - -## Usage - -```sh -$ lerna link -``` - -Symlink together all Lerna `packages` that are dependencies of each other in the current Lerna repo. - -## Options - -### `--force-local` - -```sh -$ 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`). \ No newline at end of file diff --git a/commands/link/__tests__/__fixtures__/with-contents/packages/package-3/package.json b/commands/link/__tests__/__fixtures__/with-contents/packages/package-3/package.json deleted file mode 100644 index 21c24c72ff..0000000000 --- a/commands/link/__tests__/__fixtures__/with-contents/packages/package-3/package.json +++ /dev/null @@ -1,15 +0,0 @@ -{ - "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" - } -} diff --git a/commands/link/__tests__/link-command.test.js b/commands/link/__tests__/link-command.test.js deleted file mode 100644 index c906c7f499..0000000000 --- a/commands/link/__tests__/link-command.test.js +++ /dev/null @@ -1,246 +0,0 @@ -"use strict"; - -jest.mock("@lerna/create-symlink"); - -// mocked or stubbed modules -const { createSymlink } = require("@lerna/create-symlink"); - -// helpers -const initFixture = require("@lerna-test/helpers").initFixtureFactory(__dirname); -const { normalizeRelativeDir } = require("@lerna-test/helpers"); - -// file under test -const lernaLink = require("@lerna-test/helpers").commandRunner(require("../command")); - -// assertion helpers -const symlinkedDirectories = (testDir) => - createSymlink.mock.calls - .slice() - // ensure sort is always consistent, despite promise variability - .sort((a, b) => { - // two-dimensional path sort - if (b[0] === a[0]) { - if (b[1] === a[1]) { - // ignore third field - return 0; - } - - return b[1] < a[1] ? 1 : -1; - } - - return b[0] < a[0] ? 1 : -1; - }) - .map(([src, dest, type]) => ({ - _src: normalizeRelativeDir(testDir, src), - dest: normalizeRelativeDir(testDir, dest), - type, - })); - -describe("LinkCommand", () => { - // the underlying implementation of symlinkDependencies - createSymlink.mockResolvedValue(); - - describe("with local package dependencies", () => { - it("should symlink all packages", async () => { - const testDir = await initFixture("basic"); - await lernaLink(testDir)(); - - expect(symlinkedDirectories(testDir)).toMatchInlineSnapshot(` - Array [ - Object { - "_src": "packages/package-1", - "dest": "packages/package-2/node_modules/@test/package-1", - "type": "junction", - }, - Object { - "_src": "packages/package-1", - "dest": "packages/package-3/node_modules/@test/package-1", - "type": "junction", - }, - Object { - "_src": "packages/package-2", - "dest": "packages/package-3/node_modules/@test/package-2", - "type": "junction", - }, - Object { - "_src": "packages/package-2/cli.js", - "dest": "packages/package-3/node_modules/.bin/package-2", - "type": "exec", - }, - Object { - "_src": "packages/package-3", - "dest": "packages/package-4/node_modules/package-3", - "type": "junction", - }, - Object { - "_src": "packages/package-3/cli1.js", - "dest": "packages/package-4/node_modules/.bin/package3cli1", - "type": "exec", - }, - Object { - "_src": "packages/package-3/cli2.js", - "dest": "packages/package-4/node_modules/.bin/package3cli2", - "type": "exec", - }, - ] - `); - }); - }); - - 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"); - await lernaLink(testDir)(); - - expect(symlinkedDirectories(testDir)).toMatchInlineSnapshot(` - Array [ - Object { - "_src": "packages/package-1", - "dest": "packages/package-2/node_modules/@test/package-1", - "type": "junction", - }, - Object { - "_src": "packages/package-1", - "dest": "packages/package-3/node_modules/@test/package-1", - "type": "junction", - }, - Object { - "_src": "packages/package-1", - "dest": "packages/package-4/node_modules/@test/package-1", - "type": "junction", - }, - Object { - "_src": "packages/package-2", - "dest": "packages/package-3/node_modules/@test/package-2", - "type": "junction", - }, - Object { - "_src": "packages/package-2/cli.js", - "dest": "packages/package-3/node_modules/.bin/package-2", - "type": "exec", - }, - Object { - "_src": "packages/package-3", - "dest": "packages/package-4/node_modules/package-3", - "type": "junction", - }, - Object { - "_src": "packages/package-3/cli1.js", - "dest": "packages/package-4/node_modules/.bin/package3cli1", - "type": "exec", - }, - Object { - "_src": "packages/package-3/cli2.js", - "dest": "packages/package-4/node_modules/.bin/package3cli2", - "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", - }, - ] - `); - }); - }); - - describe("with pnpm", () => { - it("should throw validation error", async () => { - const testDir = await initFixture("pnpm"); - const command = lernaLink(testDir)(); - - await expect(command).rejects.toThrow( - "Link is not supported with pnpm workspaces, since pnpm will automatically link dependencies during `pnpm install`. See the pnpm docs for details: https://pnpm.io/workspaces" - ); - }); - }); -}); diff --git a/commands/link/command.js b/commands/link/command.js deleted file mode 100644 index 2a8c851ac1..0000000000 --- a/commands/link/command.js +++ /dev/null @@ -1,36 +0,0 @@ -"use strict"; - -/** - * @see https://github.com/yargs/yargs/blob/master/docs/advanced.md#providing-a-command-module - */ -exports.command = "link"; - -exports.describe = "Symlink together all packages that are dependencies of each other"; - -exports.builder = (yargs) => { - yargs.options({ - "force-local": { - group: "Command Options:", - 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( - "convert", - "Replace local sibling version ranges with relative file: specifiers", - () => {}, - handler - ); -}; - -exports.handler = handler; -function handler(argv) { - return require(".")(argv); -} diff --git a/commands/link/index.js b/commands/link/index.js deleted file mode 100644 index 56ddfcf73a..0000000000 --- a/commands/link/index.js +++ /dev/null @@ -1,89 +0,0 @@ -"use strict"; - -const path = require("path"); -const pMap = require("p-map"); -const slash = require("slash"); -const { Command } = require("@lerna/command"); -const { PackageGraph } = require("@lerna/package-graph"); -const { symlinkDependencies } = require("@lerna/symlink-dependencies"); -const { ValidationError } = require("@lerna/validation-error"); - -module.exports = factory; - -function factory(argv) { - return new LinkCommand(argv); -} - -class LinkCommand extends Command { - get requiresGit() { - return false; - } - - initialize() { - if (this.options.npmClient === "pnpm") { - throw new ValidationError( - "EWORKSPACES", - "Link is not supported with pnpm workspaces, since pnpm will automatically link dependencies during `pnpm install`. See the pnpm docs for details: https://pnpm.io/workspaces" - ); - } - - this.allPackages = this.packageGraph.rawPackageList; - - if (this.options.contents) { - // globally override directory to link - for (const pkg of this.allPackages) { - pkg.contents = this.options.contents; - } - } - - this.targetGraph = this.options.forceLocal - ? new PackageGraph(this.allPackages, "allDependencies", "forceLocal") - : this.packageGraph; - } - - execute() { - if (this.options._.pop() === "convert") { - return this.convertLinksToFileSpecs(); - } - - return symlinkDependencies(this.allPackages, this.targetGraph, this.logger.newItem("link dependencies")); - } - - convertLinksToFileSpecs() { - const rootPkg = this.project.manifest; - const rootDependencies = {}; - const hoisted = {}; - const changed = new Set(); - const savePrefix = "file:"; - - for (const targetNode of this.targetGraph.values()) { - const resolved = { name: targetNode.name, type: "directory" }; - - // install root file: specifiers to avoid bootstrap - rootDependencies[targetNode.name] = targetNode.pkg.resolved.saveSpec; - - for (const depNode of targetNode.localDependents.values()) { - const depVersion = slash(path.relative(depNode.pkg.location, targetNode.pkg.location)); - // console.log("\n%s\n %j: %j", depNode.name, name, `${savePrefix}${depVersion}`); - - depNode.pkg.updateLocalDependency(resolved, depVersion, savePrefix); - changed.add(depNode); - } - - if (targetNode.pkg.devDependencies) { - // hoist _all_ devDependencies to the root - Object.assign(hoisted, targetNode.pkg.devDependencies); - targetNode.pkg.set("devDependencies", {}); - changed.add(targetNode); - } - } - - // mutate project manifest, completely overwriting existing dependencies - rootPkg.set("dependencies", rootDependencies); - rootPkg.set("devDependencies", Object.assign(rootPkg.get("devDependencies") || {}, hoisted)); - - return pMap(changed, (node) => node.pkg.serialize()).then(() => rootPkg.serialize()); - } -} - -module.exports.LinkCommand = LinkCommand; diff --git a/commands/link/package.json b/commands/link/package.json deleted file mode 100644 index 69ba1e4001..0000000000 --- a/commands/link/package.json +++ /dev/null @@ -1,42 +0,0 @@ -{ - "name": "@lerna/link", - "version": "6.4.1", - "description": "Symlink together all packages that are dependencies of each other", - "keywords": [ - "lerna", - "command" - ], - "homepage": "https://lerna.js.org", - "license": "MIT", - "author": { - "name": "Daniel Stockman", - "url": "https://github.com/evocateur" - }, - "files": [ - "command.js", - "index.js" - ], - "main": "index.js", - "engines": { - "node": "^14.15.0 || >=16.0.0" - }, - "publishConfig": { - "access": "public" - }, - "repository": { - "type": "git", - "url": "git+https://github.com/lerna/lerna.git", - "directory": "commands/link" - }, - "scripts": { - "test": "echo \"Run tests from root\" && exit 1" - }, - "dependencies": { - "@lerna/command": "file:../../core/command", - "@lerna/package-graph": "file:../../core/package-graph", - "@lerna/symlink-dependencies": "file:../../utils/symlink-dependencies", - "@lerna/validation-error": "file:../../core/validation-error", - "p-map": "^4.0.0", - "slash": "^3.0.0" - } -} diff --git a/commands/list/CHANGELOG.md b/commands/list/CHANGELOG.md deleted file mode 100644 index f31c58c01c..0000000000 --- a/commands/list/CHANGELOG.md +++ /dev/null @@ -1,481 +0,0 @@ -# Change Log - -All notable changes to this project will be documented in this file. -See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. - -## [6.4.1](https://github.com/lerna/lerna/compare/v6.4.0...v6.4.1) (2023-01-12) - -**Note:** Version bump only for package @lerna/list - -# [6.4.0](https://github.com/lerna/lerna/compare/v6.3.0...v6.4.0) (2023-01-05) - -**Note:** Version bump only for package @lerna/list - -# [6.3.0](https://github.com/lerna/lerna/compare/v6.2.0...v6.3.0) (2022-12-26) - -**Note:** Version bump only for package @lerna/list - -# [6.2.0](https://github.com/lerna/lerna/compare/v6.1.0...v6.2.0) (2022-12-13) - -**Note:** Version bump only for package @lerna/list - -# [6.1.0](https://github.com/lerna/lerna/compare/v6.0.3...v6.1.0) (2022-11-29) - -**Note:** Version bump only for package @lerna/list - -## [6.0.3](https://github.com/lerna/lerna/compare/v6.0.2...v6.0.3) (2022-11-07) - -**Note:** Version bump only for package @lerna/list - -## [6.0.2](https://github.com/lerna/lerna/compare/v6.0.1...v6.0.2) (2022-11-02) - -**Note:** Version bump only for package @lerna/list - -## [6.0.1](https://github.com/lerna/lerna/compare/v6.0.0...v6.0.1) (2022-10-14) - -**Note:** Version bump only for package @lerna/list - -# [6.0.0](https://github.com/lerna/lerna/compare/v6.0.0-alpha.2...v6.0.0) (2022-10-12) - -**Note:** Version bump only for package @lerna/list - -# [6.0.0-alpha.2](https://github.com/lerna/lerna/compare/v6.0.0-alpha.1...v6.0.0-alpha.2) (2022-10-12) - -**Note:** Version bump only for package @lerna/list - -# [6.0.0-alpha.1](https://github.com/lerna/lerna/compare/v5.6.2...v6.0.0-alpha.1) (2022-10-09) - -# [6.0.0-alpha.0](https://github.com/lerna/lerna/compare/v5.6.1...v6.0.0-alpha.0) (2022-10-07) - -**Note:** Version bump only for package @lerna/list - -## [5.6.2](https://github.com/lerna/lerna/compare/v5.6.1...v5.6.2) (2022-10-09) - -**Note:** Version bump only for package @lerna/list - -## [5.6.1](https://github.com/lerna/lerna/compare/v5.6.0...v5.6.1) (2022-09-30) - -**Note:** Version bump only for package @lerna/list - -# [5.6.0](https://github.com/lerna/lerna/compare/v5.5.4...v5.6.0) (2022-09-29) - -**Note:** Version bump only for package @lerna/list - -## [5.5.4](https://github.com/lerna/lerna/compare/v5.5.3...v5.5.4) (2022-09-28) - -**Note:** Version bump only for package @lerna/list - -## [5.5.3](https://github.com/lerna/lerna/compare/v5.5.2...v5.5.3) (2022-09-28) - -**Note:** Version bump only for package @lerna/list - -## [5.5.2](https://github.com/lerna/lerna/compare/v5.5.1...v5.5.2) (2022-09-20) - -**Note:** Version bump only for package @lerna/list - -## [5.5.1](https://github.com/lerna/lerna/compare/v5.5.0...v5.5.1) (2022-09-09) - -**Note:** Version bump only for package @lerna/list - -# [5.5.0](https://github.com/lerna/lerna/compare/v5.4.3...v5.5.0) (2022-08-31) - -**Note:** Version bump only for package @lerna/list - -## [5.4.3](https://github.com/lerna/lerna/compare/v5.4.2...v5.4.3) (2022-08-16) - -**Note:** Version bump only for package @lerna/list - -## [5.4.2](https://github.com/lerna/lerna/compare/v5.4.1...v5.4.2) (2022-08-14) - -**Note:** Version bump only for package @lerna/list - -## [5.4.1](https://github.com/lerna/lerna/compare/v5.4.0...v5.4.1) (2022-08-12) - -**Note:** Version bump only for package @lerna/list - -# [5.4.0](https://github.com/lerna/lerna/compare/v5.3.0...v5.4.0) (2022-08-08) - -**Note:** Version bump only for package @lerna/list - -# [5.3.0](https://github.com/lerna/lerna/compare/v5.2.0...v5.3.0) (2022-07-27) - -**Note:** Version bump only for package @lerna/list - -# [5.2.0](https://github.com/lerna/lerna/compare/v5.1.8...v5.2.0) (2022-07-22) - -**Note:** Version bump only for package @lerna/list - -## [5.1.8](https://github.com/lerna/lerna/compare/v5.1.7...v5.1.8) (2022-07-07) - -**Note:** Version bump only for package @lerna/list - -## [5.1.7](https://github.com/lerna/lerna/compare/v5.1.6...v5.1.7) (2022-07-06) - -**Note:** Version bump only for package @lerna/list - -## [5.1.6](https://github.com/lerna/lerna/compare/v5.1.5...v5.1.6) (2022-06-24) - -**Note:** Version bump only for package @lerna/list - -## [5.1.5](https://github.com/lerna/lerna/compare/v5.1.4...v5.1.5) (2022-06-24) - -**Note:** Version bump only for package @lerna/list - -## [5.1.4](https://github.com/lerna/lerna/compare/v5.1.3...v5.1.4) (2022-06-15) - -**Note:** Version bump only for package @lerna/list - -## [5.1.3](https://github.com/lerna/lerna/compare/v5.1.2...v5.1.3) (2022-06-15) - -**Note:** Version bump only for package @lerna/list - -## [5.1.2](https://github.com/lerna/lerna/compare/v5.1.1...v5.1.2) (2022-06-13) - -**Note:** Version bump only for package @lerna/list - -## [5.1.1](https://github.com/lerna/lerna/compare/v5.1.0...v5.1.1) (2022-06-09) - -### Bug Fixes - -- allow maintenance LTS node 14 engines starting at 14.15.0 ([#3161](https://github.com/lerna/lerna/issues/3161)) ([72305e4](https://github.com/lerna/lerna/commit/72305e4dbab607a2d87ae4efa6ee577c93a9dda9)) - -# [5.1.0](https://github.com/lerna/lerna/compare/v5.0.0...v5.1.0) (2022-06-07) - -**Note:** Version bump only for package @lerna/list - -# [5.1.0-alpha.0](https://github.com/lerna/lerna/compare/v4.0.0...v5.1.0-alpha.0) (2022-05-25) - -**Note:** Version bump only for package @lerna/list - -# [5.0.0](https://github.com/lerna/lerna/compare/v4.0.0...v5.0.0) (2022-05-24) - -**Note:** Version bump only for package @lerna/list - -# [4.0.0](https://github.com/lerna/lerna/compare/v3.22.1...v4.0.0) (2021-02-10) - -### Features - -- Consume named exports of sibling modules ([63499e3](https://github.com/lerna/lerna/commit/63499e33652bc78fe23751875d74017e2f16a689)) -- Drop support for Node v6.x & v8.x ([ff4bb4d](https://github.com/lerna/lerna/commit/ff4bb4da215555e3bb136f5af09b5cbc631e57bb)) - -### BREAKING CHANGES - -- Node v6.x & v8.x are no longer supported. Please upgrade to the latest LTS release. - -Here's the gnarly one-liner I used to make these changes: - -``` -npx lerna exec --concurrency 1 --stream -- 'json -I -f package.json -e '"'"'this.engines=this.engines||{};this.engines.node=">= 10.18.0"'"'" -``` - -(requires `npm i -g json` beforehand) - -# [3.21.0](https://github.com/lerna/lerna/compare/v3.20.2...v3.21.0) (2020-05-13) - -**Note:** Version bump only for package @lerna/list - -# [3.20.0](https://github.com/lerna/lerna/compare/v3.19.0...v3.20.0) (2019-12-27) - -**Note:** Version bump only for package @lerna/list - -## [3.18.5](https://github.com/lerna/lerna/compare/v3.18.4...v3.18.5) (2019-11-20) - -**Note:** Version bump only for package @lerna/list - -## [3.18.4](https://github.com/lerna/lerna/compare/v3.18.3...v3.18.4) (2019-11-08) - -**Note:** Version bump only for package @lerna/list - -# [3.18.0](https://github.com/lerna/lerna/compare/v3.17.0...v3.18.0) (2019-10-15) - -**Note:** Version bump only for package @lerna/list - -## [3.16.5](https://github.com/lerna/lerna/compare/v3.16.4...v3.16.5) (2019-10-07) - -**Note:** Version bump only for package @lerna/list - -# [3.16.0](https://github.com/lerna/lerna/compare/v3.15.0...v3.16.0) (2019-07-18) - -### Features - -- **listable:** Output JSON adjacency list with `--graph` ([9457a21](https://github.com/lerna/lerna/commit/9457a21)), closes [#1970](https://github.com/lerna/lerna/issues/1970) - -# [3.15.0](https://github.com/lerna/lerna/compare/v3.14.2...v3.15.0) (2019-06-09) - -**Note:** Version bump only for package @lerna/list - -## [3.14.2](https://github.com/lerna/lerna/compare/v3.14.1...v3.14.2) (2019-06-09) - -**Note:** Version bump only for package @lerna/list - -# [3.14.0](https://github.com/lerna/lerna/compare/v3.13.4...v3.14.0) (2019-05-14) - -**Note:** Version bump only for package @lerna/list - -## [3.13.3](https://github.com/lerna/lerna/compare/v3.13.2...v3.13.3) (2019-04-17) - -**Note:** Version bump only for package @lerna/list - -## [3.13.1](https://github.com/lerna/lerna/compare/v3.13.0...v3.13.1) (2019-02-26) - -### Bug Fixes - -- **list:** Restore empty `--json` array output when no results ([2c925bd](https://github.com/lerna/lerna/commit/2c925bd)), closes [#1945](https://github.com/lerna/lerna/issues/1945) - -# [3.13.0](https://github.com/lerna/lerna/compare/v3.12.1...v3.13.0) (2019-02-15) - -### Features - -- **listable:** Output newline-delimited JSON with `--ndjson` ([742781b](https://github.com/lerna/lerna/commit/742781b)) -- **meta:** Add `repository.directory` field to package.json ([aec5023](https://github.com/lerna/lerna/commit/aec5023)) -- **meta:** Normalize package.json `homepage` field ([abeb4dc](https://github.com/lerna/lerna/commit/abeb4dc)) - -## [3.12.1](https://github.com/lerna/lerna/compare/v3.12.0...v3.12.1) (2019-02-14) - -### Bug Fixes - -- **list:** Do not emit empty stdout when there are no results ([ba54439](https://github.com/lerna/lerna/commit/ba54439)) - -# [3.12.0](https://github.com/lerna/lerna/compare/v3.11.1...v3.12.0) (2019-02-14) - -**Note:** Version bump only for package @lerna/list - -# [3.11.0](https://github.com/lerna/lerna/compare/v3.10.8...v3.11.0) (2019-02-08) - -**Note:** Version bump only for package @lerna/list - -## [3.10.6](https://github.com/lerna/lerna/compare/v3.10.5...v3.10.6) (2019-01-19) - -**Note:** Version bump only for package @lerna/list - -## [3.10.1](https://github.com/lerna/lerna/compare/v3.10.0...v3.10.1) (2019-01-09) - -**Note:** Version bump only for package @lerna/list - -# [3.10.0](https://github.com/lerna/lerna/compare/v3.9.1...v3.10.0) (2019-01-08) - -**Note:** Version bump only for package @lerna/list - -# [3.9.0](https://github.com/lerna/lerna/compare/v3.8.5...v3.9.0) (2019-01-08) - -**Note:** Version bump only for package @lerna/list - -## [3.8.5](https://github.com/lerna/lerna/compare/v3.8.4...v3.8.5) (2019-01-05) - -**Note:** Version bump only for package @lerna/list - -## [3.8.1](https://github.com/lerna/lerna/compare/v3.8.0...v3.8.1) (2018-12-31) - -**Note:** Version bump only for package @lerna/list - -## [3.7.2](https://github.com/lerna/lerna/compare/v3.7.1...v3.7.2) (2018-12-21) - -**Note:** Version bump only for package @lerna/list - -## [3.7.1](https://github.com/lerna/lerna/compare/v3.7.0...v3.7.1) (2018-12-20) - -**Note:** Version bump only for package @lerna/list - -# [3.7.0](https://github.com/lerna/lerna/compare/v3.6.0...v3.7.0) (2018-12-19) - -**Note:** Version bump only for package @lerna/list - -# [3.6.0](https://github.com/lerna/lerna/compare/v3.5.1...v3.6.0) (2018-12-07) - -### Features - -- **listable:** Add --toposort option ([b387881](https://github.com/lerna/lerna/commit/b387881)), closes [#1652](https://github.com/lerna/lerna/issues/1652) - -# [3.5.0](https://github.com/lerna/lerna/compare/v3.4.3...v3.5.0) (2018-11-27) - -**Note:** Version bump only for package @lerna/list - - - -## [3.3.2](https://github.com/lerna/lerna/compare/v3.3.1...v3.3.2) (2018-09-12) - -**Note:** Version bump only for package @lerna/list - - - -# [3.3.0](https://github.com/lerna/lerna/compare/v3.2.1...v3.3.0) (2018-09-06) - -**Note:** Version bump only for package @lerna/list - - - -## [3.1.3](https://github.com/lerna/lerna/compare/v3.1.2...v3.1.3) (2018-08-21) - -**Note:** Version bump only for package @lerna/list - - - -## [3.1.2](https://github.com/lerna/lerna/compare/v3.1.1...v3.1.2) (2018-08-20) - -### Bug Fixes - -- Setup instance.filteredPackages explicitly ([32357f8](https://github.com/lerna/lerna/commit/32357f8)) - - - -# [3.1.0](https://github.com/lerna/lerna/compare/v3.0.6...v3.1.0) (2018-08-17) - -**Note:** Version bump only for package @lerna/list - - - -## [3.0.6](https://github.com/lerna/lerna/compare/v3.0.5...v3.0.6) (2018-08-16) - -**Note:** Version bump only for package @lerna/list - - - -## [3.0.5](https://github.com/lerna/lerna/compare/v3.0.4...v3.0.5) (2018-08-15) - -**Note:** Version bump only for package @lerna/list - - - -# [3.0.0](https://github.com/lerna/lerna/compare/v3.0.0-rc.0...v3.0.0) (2018-08-10) - -### Features - -- **list:** Extract [@lerna](https://github.com/lerna)/listable utility ([bf56018](https://github.com/lerna/lerna/commit/bf56018)) -- **list:** Improve scriptability with several new options ([2e204af](https://github.com/lerna/lerna/commit/2e204af)) - -### BREAKING CHANGES - -- **list:** The default output of `lerna ls` no longer shows version strings or private packages. - -- The new alias `lerna la` resembles the old output, with the addition of relative path to the package -- The new alias `lerna ll` is a shortcut for the new `--long` option -- A new `--parseable` option has been added to aid magical piping incantations - - - -# [3.0.0-rc.0](https://github.com/lerna/lerna/compare/v3.0.0-beta.21...v3.0.0-rc.0) (2018-07-27) - -### Features - -- Add description from --help summary [skip ci] ([9b65d8e](https://github.com/lerna/lerna/commit/9b65d8e)) -- **cli:** Upgrade to Yargs 12 ([7899ab8](https://github.com/lerna/lerna/commit/7899ab8)) -- **command:** Remove .defaultOptions() from option resolution stack ([2b27a54](https://github.com/lerna/lerna/commit/2b27a54)) -- **ls:** Log number of packages listed ([855fff6](https://github.com/lerna/lerna/commit/855fff6)) -- **project:** Move collect-packages into getPackages() method ([06b88d4](https://github.com/lerna/lerna/commit/06b88d4)) -- Count packages affected in command summary logging ([5f5e585](https://github.com/lerna/lerna/commit/5f5e585)) - - - -# [3.0.0-beta.21](https://github.com/lerna/lerna/compare/v3.0.0-beta.20...v3.0.0-beta.21) (2018-05-12) - -**Note:** Version bump only for package @lerna/list - - - -# [3.0.0-beta.20](https://github.com/lerna/lerna/compare/v3.0.0-beta.19...v3.0.0-beta.20) (2018-05-07) - -**Note:** Version bump only for package @lerna/list - - - -# [3.0.0-beta.19](https://github.com/lerna/lerna/compare/v3.0.0-beta.18...v3.0.0-beta.19) (2018-05-03) - -**Note:** Version bump only for package @lerna/list - - - -# [3.0.0-beta.18](https://github.com/lerna/lerna/compare/v3.0.0-beta.17...v3.0.0-beta.18) (2018-04-24) - -### Features - -- **filters:** Add `--include-filtered-dependents` flag ([#1393](https://github.com/lerna/lerna/issues/1393)) ([2838260](https://github.com/lerna/lerna/commit/2838260)) - - - -# [3.0.0-beta.17](https://github.com/lerna/lerna/compare/v3.0.0-beta.16...v3.0.0-beta.17) (2018-04-13) - -**Note:** Version bump only for package @lerna/list - - - -# [3.0.0-beta.15](https://github.com/lerna/lerna/compare/v3.0.0-beta.14...v3.0.0-beta.15) (2018-04-09) - -**Note:** Version bump only for package @lerna/list - - - -# [3.0.0-beta.14](https://github.com/lerna/lerna/compare/v3.0.0-beta.13...v3.0.0-beta.14) (2018-04-03) - -**Note:** Version bump only for package @lerna/list - - - -# [3.0.0-beta.13](https://github.com/lerna/lerna/compare/v3.0.0-beta.12...v3.0.0-beta.13) (2018-03-31) - -### Features - -- Enable progress bars only when necessary ([b766c83](https://github.com/lerna/lerna/commit/b766c83)) - - - -# [3.0.0-beta.12](https://github.com/lerna/lerna/compare/v3.0.0-beta.11...v3.0.0-beta.12) (2018-03-30) - -**Note:** Version bump only for package @lerna/list - - - -# [3.0.0-beta.11](https://github.com/lerna/lerna/compare/v3.0.0-beta.10...v3.0.0-beta.11) (2018-03-29) - -**Note:** Version bump only for package @lerna/list - - - -# [3.0.0-beta.10](https://github.com/lerna/lerna/compare/v3.0.0-beta.9...v3.0.0-beta.10) (2018-03-27) - -### Features - -- **commands:** Delay require of command instantiation ([a1284f3](https://github.com/lerna/lerna/commit/a1284f3)) - -### BREAKING CHANGES - -- **commands:** The default export of command packages is now a factory, not the subclass (which is now a named export). - - - -# [3.0.0-beta.9](https://github.com/lerna/lerna/compare/v3.0.0-beta.8...v3.0.0-beta.9) (2018-03-24) - -**Note:** Version bump only for package @lerna/list - - - -# [3.0.0-beta.7](https://github.com/lerna/lerna/compare/v3.0.0-beta.6...v3.0.0-beta.7) (2018-03-20) - -**Note:** Version bump only for package @lerna/list - - - -# [3.0.0-beta.4](https://github.com/lerna/lerna/compare/v3.0.0-beta.3...v3.0.0-beta.4) (2018-03-19) - -**Note:** Version bump only for package @lerna/list - - - -# [3.0.0-beta.3](https://github.com/lerna/lerna/compare/v3.0.0-beta.2...v3.0.0-beta.3) (2018-03-15) - -**Note:** Version bump only for package @lerna/list - - - -# [3.0.0-beta.2](https://github.com/lerna/lerna/compare/v3.0.0-beta.1...v3.0.0-beta.2) (2018-03-10) - -### Features - -- Replace @lerna/match-package-name with multimatch ([423f82c](https://github.com/lerna/lerna/commit/423f82c)) - - - -# [3.0.0-beta.1](https://github.com/lerna/lerna/compare/v3.0.0-beta.0...v3.0.0-beta.1) (2018-03-09) - -### Features - -- **filter-options:** Exclude private packages with --no-private ([6674d18](https://github.com/lerna/lerna/commit/6674d18)) diff --git a/commands/list/README.md b/commands/list/README.md deleted file mode 100644 index e747d54b6e..0000000000 --- a/commands/list/README.md +++ /dev/null @@ -1,173 +0,0 @@ -# `@lerna/list` - -> List local packages - -Install [lerna](https://www.npmjs.com/package/lerna) for access to the `lerna` CLI. - -## Usage - -The `list` subcommand is aliased to several convenient shorthands (similar to [`npm ls`](https://docs.npmjs.com/cli/ls)): - -- `lerna ls`: Identical to `lerna list`, which is itself analogous to the `ls` command -- `lerna ll`: Equivalent to `lerna ls -l`, showing [long](#--long) output -- `lerna la`: Equivalent to `lerna ls -la`, showing [all](#--all) packages (including private ones) - -```sh -$ lerna ls -package-1 -package-2 -``` - -You might notice extra logging from `lerna` when running these commands in your shell. -Rest assured they will not infect your piped incantations, -as all logs are emitted to `stderr`, not `stdout`. - -In any case, you can always pass `--loglevel silent` to create pristine chains of magical shell wizardry. - -## Options - -- [`--json`](#--json) -- [`--ndjson`](#--ndjson) -- [`-a`, `--all`](#--all) -- [`-l`, `--long`](#--long) -- [`-p`, `--parseable`](#--parseable) -- [`--toposort`](#--toposort) -- [`--graph`](#--graph) - -`lerna ls` also respects all available [Filter Flags](https://www.npmjs.com/package/@lerna/filter-options). - -### `--json` - -Show information as a JSON array. - -```sh -$ lerna ls --json -[ - { - "name": "package-1", - "version": "1.0.0", - "private": false, - "location": "/path/to/packages/pkg-1" - }, - { - "name": "package-2", - "version": "1.0.0", - "private": false, - "location": "/path/to/packages/pkg-2" - } -] -``` - -**Tip:** Pipe to the [`json`](http://trentm.com/json/) utility to pick out individual properties: - -```sh -$ lerna ls --json --all | json -a -c 'this.private === true' name -package-3 -``` - -### `--ndjson` - -Show information as [newline-delimited JSON](http://ndjson.org). - -```sh -$ lerna ls --ndjson -{"name":"package-1","version":"1.0.0","private":false,"location":"/path/to/packages/pkg-1"} -{"name":"package-2","version":"1.0.0","private":false,"location":"/path/to/packages/pkg-2"} -``` - -### `--all` - -Alias: `-a` - -Show private packages that are hidden by default. - -```sh -$ lerna ls --all -package-1 -package-2 -package-3 (private) -``` - -### `--long` - -Alias: `-l` - -Show extended information. - -```sh -$ lerna ls --long -package-1 v1.0.1 packages/pkg-1 -package-2 v1.0.2 packages/pkg-2 - -$ lerna ls -la -package-1 v1.0.1 packages/pkg-1 -package-2 v1.0.2 packages/pkg-2 -package-3 v1.0.3 packages/pkg-3 (private) -``` - -### `--parseable` - -Alias: `-p` - -Show parseable output instead of columnified view. - -By default, each line of the output is an absolute path to a package. - -In `--long` output, each line is a `:`-separated list: `::[:flags..]` - -```sh -$ lerna ls --parseable -/path/to/packages/pkg-1 -/path/to/packages/pkg-2 - -$ lerna ls -pl -/path/to/packages/pkg-1:package-1:1.0.1 -/path/to/packages/pkg-2:package-2:1.0.2 - -$ lerna ls -pla -/path/to/packages/pkg-1:package-1:1.0.1 -/path/to/packages/pkg-2:package-2:1.0.2 -/path/to/packages/pkg-3:package-3:1.0.3:PRIVATE -``` - -### `--toposort` - -Sort packages in topological order (dependencies before dependents) instead of lexical by directory. - -```sh -$ json dependencies { - describe("in a basic repo", () => { - let testDir; - - beforeAll(async () => { - testDir = await initFixture("basic"); - }); - - it("should list public packages", async () => { - await lernaLs(testDir)(); - expect(output.logged()).toMatchInlineSnapshot(` -package-1 -package-2 -package-3 -package-4 -`); - }); - - it("should also list private packages with --all", async () => { - await lernaLs(testDir)("--all"); - expect(output.logged()).toMatchInlineSnapshot(` -package-1 -package-2 -package-3 -package-4 -package-5 (PRIVATE) -`); - }); - - it("lists public package versions and relative paths with --long", async () => { - await lernaLs(testDir)("--long"); - expect(output.logged()).toMatchInlineSnapshot(` -package-1 v1.0.0 packages/package-1 -package-2 v1.0.0 packages/package-2 -package-3 v1.0.0 packages/package-3 -package-4 v1.0.0 packages/package-4 -`); - }); - - it("lists all package versions and relative paths with --long --all", async () => { - await lernaLs(testDir)("-la"); - expect(output.logged()).toMatchInlineSnapshot(` -package-1 v1.0.0 packages/package-1 -package-2 v1.0.0 packages/package-2 -package-3 v1.0.0 packages/package-3 -package-4 v1.0.0 packages/package-4 -package-5 v1.0.0 packages/package-5 (PRIVATE) -`); - }); - - it("lists public package locations with --parseable", async () => { - await lernaLs(testDir)("--parseable"); - expect(output.logged()).toMatchInlineSnapshot(` -__TEST_ROOTDIR__/packages/package-1 -__TEST_ROOTDIR__/packages/package-2 -__TEST_ROOTDIR__/packages/package-3 -__TEST_ROOTDIR__/packages/package-4 -`); - }); - - it("lists all package locations with --parseable --all", async () => { - await lernaLs(testDir)("-pa"); - expect(output.logged()).toMatchInlineSnapshot(` -__TEST_ROOTDIR__/packages/package-1 -__TEST_ROOTDIR__/packages/package-2 -__TEST_ROOTDIR__/packages/package-3 -__TEST_ROOTDIR__/packages/package-4 -__TEST_ROOTDIR__/packages/package-5 -`); - }); - - it("lists public package locations with --parseable --long", async () => { - await lernaLs(testDir)("--parseable", "--long"); - expect(output.logged()).toMatchInlineSnapshot(` -__TEST_ROOTDIR__/packages/package-1:package-1:1.0.0 -__TEST_ROOTDIR__/packages/package-2:package-2:1.0.0 -__TEST_ROOTDIR__/packages/package-3:package-3:1.0.0 -__TEST_ROOTDIR__/packages/package-4:package-4:1.0.0 -`); - }); - - it("lists all package locations with --parseable --long --all", async () => { - await lernaLs(testDir)("-pal"); - expect(output.logged()).toMatchInlineSnapshot(` -__TEST_ROOTDIR__/packages/package-1:package-1:1.0.0 -__TEST_ROOTDIR__/packages/package-2:package-2:1.0.0 -__TEST_ROOTDIR__/packages/package-3:package-3:1.0.0 -__TEST_ROOTDIR__/packages/package-4:package-4:1.0.0 -__TEST_ROOTDIR__/packages/package-5:package-5:1.0.0:PRIVATE -`); - }); - - it("lists packages matching --scope", async () => { - await lernaLs(testDir)("--scope", "package-1"); - expect(output.logged()).toMatchInlineSnapshot(`package-1`); - }); - - it("does not list packages matching --ignore", async () => { - await lernaLs(testDir)("--ignore", "package-@(2|3|4|5)"); - expect(output.logged()).toMatchInlineSnapshot(`package-1`); - }); - - it("does not list private packages with --no-private", async () => { - await lernaLs(testDir)("--no-private"); - expect(output.logged()).not.toMatch("package-5 v1.0.0 (private)"); - }); - - it("does not emit empty stdout", async () => { - collectUpdates.setUpdated(testDir); - await lernaLs(testDir)("--since", "deadbeef"); - expect(output).not.toHaveBeenCalled(); - expect(collectUpdates).toHaveBeenLastCalledWith( - expect.any(Array), - expect.any(Map), - expect.any(Object), - expect.objectContaining({ since: "deadbeef" }) - ); - }); - }); - - describe("in a repo with packages outside of packages/", () => { - it("should list packages", async () => { - const testDir = await initFixture("extra"); - await lernaLs(testDir)(); - expect(output.logged()).toMatchInlineSnapshot(` -package-3 -package-1 -package-2 -`); - }); - }); - - describe("--include-filtered-dependencies", () => { - it("should list packages, including filtered ones", async () => { - const testDir = await initFixture("include-filtered-dependencies"); - await lernaLs(testDir)("--scope", "@test/package-2", "--include-filtered-dependencies"); - expect(output.logged()).toMatchInlineSnapshot(` -@test/package-2 -@test/package-1 -`); - }); - }); - - describe("--include-filtered-dependents", () => { - it("should list packages, including filtered ones", async () => { - const testDir = await initFixture("include-filtered-dependencies"); - await lernaLs(testDir)("--scope", "@test/package-1", "--include-filtered-dependents"); - expect(output.logged()).toMatchInlineSnapshot(` -@test/package-1 -@test/package-2 -`); - }); - }); - - describe("with an undefined version", () => { - it("replaces version with MISSING", async () => { - const testDir = await initFixture("undefined-version"); - await lernaLs(testDir)("--long"); - expect(output.logged()).toMatchInlineSnapshot(`package-1 MISSING packages/package-1`); - }); - - it("appends MISSING flag to long parseable output", async () => { - const testDir = await initFixture("undefined-version"); - await lernaLs(testDir)("--long", "--parseable"); - expect(output.logged()).toMatchInlineSnapshot(`__TEST_ROOTDIR__/packages/package-1:package-1:MISSING`); - }); - }); - - describe("--json", () => { - it("should list packages as json objects", async () => { - const testDir = await initFixture("basic"); - await lernaLs(testDir)("--json", "-a"); - - // Output should be a parseable string - const jsonOutput = JSON.parse(output.logged()); - expect(jsonOutput).toEqual([ - { - location: expect.stringContaining("package-1"), - name: "package-1", - private: false, - version: "1.0.0", - }, - { - location: expect.stringContaining("package-2"), - name: "package-2", - private: false, - version: "1.0.0", - }, - { - location: expect.stringContaining("package-3"), - name: "package-3", - private: false, - version: "1.0.0", - }, - { - location: expect.stringContaining("package-4"), - name: "package-4", - private: false, - version: "1.0.0", - }, - { - location: expect.stringContaining("package-5"), - name: "package-5", - private: true, - version: "1.0.0", - }, - ]); - }); - - it("emits empty array with no results", async () => { - const testDir = await initFixture("basic"); - - collectUpdates.setUpdated(testDir); - await lernaLs(testDir)("--since", "deadbeef", "--json"); - - expect(JSON.parse(output.logged())).toEqual([]); - }); - }); - - describe("in a Yarn workspace", () => { - it("should use package.json/workspaces setting", async () => { - const testDir = await initFixture("yarn-workspaces"); - await lernaLs(testDir)(); - expect(output.logged()).toMatchInlineSnapshot(` -package-1 -package-2 -`); - }); - }); - - describe("with terribly complicated dependency cycles", () => { - // for reference: 1->2, 1->3, 1->4, 2->4, 2->5, 3->4, 3->6, 4->1, 4->4, 5->4, 6->4, 7->4 - // We design the package tree in a very specific way. We want to test several different things - // * A package depending on itself isn't added twice (package 4) - // * A package being added twice in the same stage of the expansion isn't added twice (package 4) - // * A package that has already been processed wont get added twice (package 1) - it("should list all packages with no repeats", async () => { - const testDir = await initFixture("cycles-and-repeated-deps"); - await lernaLs(testDir)("--scope", "package-1", "--include-filtered-dependencies"); - - // should follow all transitive deps and pass all packages except 7 with no repeats - expect(output.logged()).toMatchInlineSnapshot(` -package-1 -package-2 -package-3 -package-4 -package-5 -package-6 -`); - }); - }); - - describe("with fancy 'packages' configuration", () => { - it("lists globstar-nested packages", async () => { - const testDir = await initFixture("globstar"); - await lernaLs(testDir)(); - expect(output.logged()).toMatchInlineSnapshot(` -globstar -package-2 -package-4 -package-1 -package-3 -package-5 -`); - }); - - it("lists packages under explicitly configured node_modules directories", async () => { - const testDir = await initFixture("explicit-node-modules"); - await lernaLs(testDir)(); - expect(output.logged()).toMatchInlineSnapshot(` -alle-pattern-root -package-1 -package-2 -package-3 -package-4 -@scoped/package-5 -`); - }); - - it("throws an error when globstars and explicit node_modules configs are mixed", async () => { - const testDir = await initFixture("mixed-globstar"); - const command = lernaLs(testDir)(); - - await expect(command).rejects.toThrow("An explicit node_modules package path does not allow globstars"); - }); - }); -}); diff --git a/commands/list/command.js b/commands/list/command.js deleted file mode 100644 index b672e3debb..0000000000 --- a/commands/list/command.js +++ /dev/null @@ -1,23 +0,0 @@ -"use strict"; - -const { filterOptions } = require("@lerna/filter-options"); -const listable = require("@lerna/listable"); - -/** - * @see https://github.com/yargs/yargs/blob/master/docs/advanced.md#providing-a-command-module - */ -exports.command = "list"; - -exports.aliases = ["ls", "la", "ll"]; - -exports.describe = "List local packages"; - -exports.builder = (yargs) => { - listable.options(yargs); - - return filterOptions(yargs); -}; - -exports.handler = function handler(argv) { - return require(".")(argv); -}; diff --git a/commands/list/index.js b/commands/list/index.js deleted file mode 100644 index d6dc750c83..0000000000 --- a/commands/list/index.js +++ /dev/null @@ -1,45 +0,0 @@ -"use strict"; - -const { Command } = require("@lerna/command"); -const listable = require("@lerna/listable"); -const { output } = require("@lerna/output"); -const { getFilteredPackages } = require("@lerna/filter-options"); - -module.exports = factory; - -function factory(argv) { - return new ListCommand(argv); -} - -class ListCommand extends Command { - get requiresGit() { - return false; - } - - initialize() { - let chain = Promise.resolve(); - - chain = chain.then(() => getFilteredPackages(this.packageGraph, this.execOpts, this.options)); - chain = chain.then((filteredPackages) => { - this.result = listable.format(filteredPackages, this.options); - }); - - return chain; - } - - execute() { - // piping to `wc -l` should not yield 1 when no packages matched - if (this.result.text.length) { - output(this.result.text); - } - - this.logger.success( - "found", - "%d %s", - this.result.count, - this.result.count === 1 ? "package" : "packages" - ); - } -} - -module.exports.ListCommand = ListCommand; diff --git a/commands/list/package.json b/commands/list/package.json deleted file mode 100644 index 1873b1d4c6..0000000000 --- a/commands/list/package.json +++ /dev/null @@ -1,40 +0,0 @@ -{ - "name": "@lerna/list", - "version": "6.4.1", - "description": "List local packages", - "keywords": [ - "lerna", - "command" - ], - "homepage": "https://lerna.js.org", - "license": "MIT", - "author": { - "name": "Daniel Stockman", - "url": "https://github.com/evocateur" - }, - "files": [ - "command.js", - "index.js" - ], - "main": "index.js", - "engines": { - "node": "^14.15.0 || >=16.0.0" - }, - "publishConfig": { - "access": "public" - }, - "repository": { - "type": "git", - "url": "git+https://github.com/lerna/lerna.git", - "directory": "commands/list" - }, - "scripts": { - "test": "echo \"Run tests from root\" && exit 1" - }, - "dependencies": { - "@lerna/command": "file:../../core/command", - "@lerna/filter-options": "file:../../core/filter-options", - "@lerna/listable": "file:../../utils/listable", - "@lerna/output": "file:../../utils/output" - } -} diff --git a/commands/publish/CHANGELOG.md b/commands/publish/CHANGELOG.md deleted file mode 100644 index 9712b29d92..0000000000 --- a/commands/publish/CHANGELOG.md +++ /dev/null @@ -1,945 +0,0 @@ -# Change Log - -All notable changes to this project will be documented in this file. -See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. - -## [6.4.1](https://github.com/lerna/lerna/compare/v6.4.0...v6.4.1) (2023-01-12) - -**Note:** Version bump only for package @lerna/publish - -# [6.4.0](https://github.com/lerna/lerna/compare/v6.3.0...v6.4.0) (2023-01-05) - -**Note:** Version bump only for package @lerna/publish - -# [6.3.0](https://github.com/lerna/lerna/compare/v6.2.0...v6.3.0) (2022-12-26) - -**Note:** Version bump only for package @lerna/publish - -# [6.2.0](https://github.com/lerna/lerna/compare/v6.1.0...v6.2.0) (2022-12-13) - -### Features - -- **publish:** add --summary-file option ([#2653](https://github.com/lerna/lerna/issues/2653)) ([027d943](https://github.com/lerna/lerna/commit/027d9433b7bb0ca1de5fa593ed411e012af57623)) - -# [6.1.0](https://github.com/lerna/lerna/compare/v6.0.3...v6.1.0) (2022-11-29) - -**Note:** Version bump only for package @lerna/publish - -## [6.0.3](https://github.com/lerna/lerna/compare/v6.0.2...v6.0.3) (2022-11-07) - -### Bug Fixes - -- **publish:** support inconsistent workspace prefix usage ([#3413](https://github.com/lerna/lerna/issues/3413)) ([da2274b](https://github.com/lerna/lerna/commit/da2274ba68f75082e3d0399241c27038f99da40a)) - -## [6.0.2](https://github.com/lerna/lerna/compare/v6.0.1...v6.0.2) (2022-11-02) - -### Bug Fixes - -- **publish:** remove workspace prefix on publish ([#3397](https://github.com/lerna/lerna/issues/3397)) ([1f0e546](https://github.com/lerna/lerna/commit/1f0e54697ef4526251684478c9dcdd6447e3123c)) - -## [6.0.1](https://github.com/lerna/lerna/compare/v6.0.0...v6.0.1) (2022-10-14) - -**Note:** Version bump only for package @lerna/publish - -# [6.0.0](https://github.com/lerna/lerna/compare/v6.0.0-alpha.2...v6.0.0) (2022-10-12) - -**Note:** Version bump only for package @lerna/publish - -# [6.0.0-alpha.2](https://github.com/lerna/lerna/compare/v6.0.0-alpha.1...v6.0.0-alpha.2) (2022-10-12) - -**Note:** Version bump only for package @lerna/publish - -# [6.0.0-alpha.1](https://github.com/lerna/lerna/compare/v5.6.2...v6.0.0-alpha.1) (2022-10-09) - -# [6.0.0-alpha.0](https://github.com/lerna/lerna/compare/v5.6.1...v6.0.0-alpha.0) (2022-10-07) - -**Note:** Version bump only for package @lerna/publish - -## [5.6.2](https://github.com/lerna/lerna/compare/v5.6.1...v5.6.2) (2022-10-09) - -**Note:** Version bump only for package @lerna/publish - -## [5.6.1](https://github.com/lerna/lerna/compare/v5.6.0...v5.6.1) (2022-09-30) - -**Note:** Version bump only for package @lerna/publish - -# [5.6.0](https://github.com/lerna/lerna/compare/v5.5.4...v5.6.0) (2022-09-29) - -**Note:** Version bump only for package @lerna/publish - -## [5.5.4](https://github.com/lerna/lerna/compare/v5.5.3...v5.5.4) (2022-09-28) - -**Note:** Version bump only for package @lerna/publish - -## [5.5.3](https://github.com/lerna/lerna/compare/v5.5.2...v5.5.3) (2022-09-28) - -**Note:** Version bump only for package @lerna/publish - -## [5.5.2](https://github.com/lerna/lerna/compare/v5.5.1...v5.5.2) (2022-09-20) - -**Note:** Version bump only for package @lerna/publish - -## [5.5.1](https://github.com/lerna/lerna/compare/v5.5.0...v5.5.1) (2022-09-09) - -**Note:** Version bump only for package @lerna/publish - -# [5.5.0](https://github.com/lerna/lerna/compare/v5.4.3...v5.5.0) (2022-08-31) - -**Note:** Version bump only for package @lerna/publish - -## [5.4.3](https://github.com/lerna/lerna/compare/v5.4.2...v5.4.3) (2022-08-16) - -**Note:** Version bump only for package @lerna/publish - -## [5.4.2](https://github.com/lerna/lerna/compare/v5.4.1...v5.4.2) (2022-08-14) - -**Note:** Version bump only for package @lerna/publish - -## [5.4.1](https://github.com/lerna/lerna/compare/v5.4.0...v5.4.1) (2022-08-12) - -**Note:** Version bump only for package @lerna/publish - -# [5.4.0](https://github.com/lerna/lerna/compare/v5.3.0...v5.4.0) (2022-08-08) - -**Note:** Version bump only for package @lerna/publish - -# [5.3.0](https://github.com/lerna/lerna/compare/v5.2.0...v5.3.0) (2022-07-27) - -### Features - -- **publish:** include all dependencies in package graph by default, allow no-sort ([#3263](https://github.com/lerna/lerna/issues/3263)) ([3b0c79c](https://github.com/lerna/lerna/commit/3b0c79cd9ea2abb9399b22cb05348b9b2c31fdce)) - -# [5.2.0](https://github.com/lerna/lerna/compare/v5.1.8...v5.2.0) (2022-07-22) - -### Features - -- **publish:** disable legacy `verifyAccess` behavior by default ([#3249](https://github.com/lerna/lerna/issues/3249)) ([94174c1](https://github.com/lerna/lerna/commit/94174c1ff2ce20b9fef33a68bc62ba0d17207942)) - -## [5.1.8](https://github.com/lerna/lerna/compare/v5.1.7...v5.1.8) (2022-07-07) - -**Note:** Version bump only for package @lerna/publish - -## [5.1.7](https://github.com/lerna/lerna/compare/v5.1.6...v5.1.7) (2022-07-06) - -**Note:** Version bump only for package @lerna/publish - -## [5.1.6](https://github.com/lerna/lerna/compare/v5.1.5...v5.1.6) (2022-06-24) - -**Note:** Version bump only for package @lerna/publish - -## [5.1.5](https://github.com/lerna/lerna/compare/v5.1.4...v5.1.5) (2022-06-24) - -**Note:** Version bump only for package @lerna/publish - -## [5.1.4](https://github.com/lerna/lerna/compare/v5.1.3...v5.1.4) (2022-06-15) - -**Note:** Version bump only for package @lerna/publish - -## [5.1.3](https://github.com/lerna/lerna/compare/v5.1.2...v5.1.3) (2022-06-15) - -**Note:** Version bump only for package @lerna/publish - -## [5.1.2](https://github.com/lerna/lerna/compare/v5.1.1...v5.1.2) (2022-06-13) - -### Bug Fixes - -- update all transitive inclusions of ansi-regex ([#3166](https://github.com/lerna/lerna/issues/3166)) ([56eaa15](https://github.com/lerna/lerna/commit/56eaa153283be3b1e7d7793d3266fc51801fad8e)) - -## [5.1.1](https://github.com/lerna/lerna/compare/v5.1.0...v5.1.1) (2022-06-09) - -### Bug Fixes - -- allow maintenance LTS node 14 engines starting at 14.15.0 ([#3161](https://github.com/lerna/lerna/issues/3161)) ([72305e4](https://github.com/lerna/lerna/commit/72305e4dbab607a2d87ae4efa6ee577c93a9dda9)) - -# [5.1.0](https://github.com/lerna/lerna/compare/v5.0.0...v5.1.0) (2022-06-07) - -### Features - -- handle the edge cases in the lerna-nx integration ([c6808fc](https://github.com/lerna/lerna/commit/c6808fc8f2dfe793bf72a64cf2d3909e0bdabba8)) - -# [5.1.0-alpha.0](https://github.com/lerna/lerna/compare/v4.0.0...v5.1.0-alpha.0) (2022-05-25) - -**Note:** Version bump only for package @lerna/publish - -# [5.0.0](https://github.com/lerna/lerna/compare/v4.0.0...v5.0.0) (2022-05-24) - -**Note:** Version bump only for package @lerna/publish - -# [4.0.0](https://github.com/lerna/lerna/compare/v3.22.1...v4.0.0) (2021-02-10) - -### Bug Fixes - -- Improve accuracy of JSDoc type annotations ([1ec69f0](https://github.com/lerna/lerna/commit/1ec69f0e0f7a3f1e0c74dbacb17fab2d7b7a8a44)) - -### Features - -- **deps:** Bump dependencies ([affed1c](https://github.com/lerna/lerna/commit/affed1ce0fce91f01b0a9eafe357db2d985b974f)) -- Consume named exports of sibling modules ([63499e3](https://github.com/lerna/lerna/commit/63499e33652bc78fe23751875d74017e2f16a689)) -- **deps:** @evocateur/libnpmaccess -> libnpmaccess@^4.0.1 ([7974b35](https://github.com/lerna/lerna/commit/7974b351e53575503dd881c639b53d820e4f525e)) -- **deps:** @evocateur/npm-registry-fetch -> npm-registry-fetch@^9.0.0 ([6df42f2](https://github.com/lerna/lerna/commit/6df42f2caf0887c38870c07a9f850dae0e9c4253)) -- **deps:** @evocateur/pacote -> pacote@^11.1.13 ([99b4217](https://github.com/lerna/lerna/commit/99b4217ed143527a45969f3a46f1bd9b84999d68)) -- **deps:** execa@^4.1.0 ([9051dca](https://github.com/lerna/lerna/commit/9051dcab1a68b56db09b82ab0345c5f36bcfee2d)) -- **deps:** fs-extra@^9.0.1 ([2f6f4e0](https://github.com/lerna/lerna/commit/2f6f4e066d5a41b4cd508b3405ac1d0a342932dc)) -- **deps:** npm-package-arg@^8.1.0 ([12c8923](https://github.com/lerna/lerna/commit/12c892342d33b86a00ee2cf9079f9b26fe316dc6)) -- **deps:** p-finally -> Promise.prototype.finally() ([028db04](https://github.com/lerna/lerna/commit/028db045b1221df000a2b98c5dceb1e4915a7806)) -- **deps:** p-finally@^2.0.1 ([165e47e](https://github.com/lerna/lerna/commit/165e47e722acf6462cf0b4e3a7d0e14d3971e7fb)) -- **deps:** p-map@^4.0.0 ([92b1364](https://github.com/lerna/lerna/commit/92b1364735e1f2cf379cf1047c60c4fb897d55f5)) -- **deps:** p-pipe@^3.1.0 ([489f59e](https://github.com/lerna/lerna/commit/489f59e28657a039becb4cdba5a1955043c73cf1)) -- **deps:** semver@^7.3.2 ([003ad66](https://github.com/lerna/lerna/commit/003ad6641fab8b4e3a82251ebffd27061bd6a31b)) -- **publish:** Remove figgy-pudding ([caf823e](https://github.com/lerna/lerna/commit/caf823e01e9eb5463b452b929a74dbc83ffc5df7)) -- Drop support for Node v6.x & v8.x ([ff4bb4d](https://github.com/lerna/lerna/commit/ff4bb4da215555e3bb136f5af09b5cbc631e57bb)) - -### BREAKING CHANGES - -- Node v6.x & v8.x are no longer supported. Please upgrade to the latest LTS release. - -Here's the gnarly one-liner I used to make these changes: - -``` -npx lerna exec --concurrency 1 --stream -- 'json -I -f package.json -e '"'"'this.engines=this.engines||{};this.engines.node=">= 10.18.0"'"'" -``` - -(requires `npm i -g json` beforehand) - -## [3.22.1](https://github.com/lerna/lerna/compare/v3.22.0...v3.22.1) (2020-06-09) - -### Bug Fixes - -- Move [#2445](https://github.com/lerna/lerna/issues/2445) behind `--no-granular-pathspec` option ([b3da937](https://github.com/lerna/lerna/commit/b3da937a61199ac71ed44b184ed36ff131237165)), closes [#2598](https://github.com/lerna/lerna/issues/2598) - -# [3.22.0](https://github.com/lerna/lerna/compare/v3.21.0...v3.22.0) (2020-05-24) - -### Bug Fixes - -- **publish:** Avoid errors when files are ignored by git ([#2445](https://github.com/lerna/lerna/issues/2445)) ([448f2ae](https://github.com/lerna/lerna/commit/448f2aee7258febc15c131c1128688326a52778f)), closes [#2151](https://github.com/lerna/lerna/issues/2151) -- **publish:** Avoid exception when publishing 1st version ([#2485](https://github.com/lerna/lerna/issues/2485)) ([5d80285](https://github.com/lerna/lerna/commit/5d802851d156e20e1bac4107e68b7280e078a51b)) -- **publish:** Support `--tag-version-prefix` in `--canary` mode ([#2435](https://github.com/lerna/lerna/issues/2435)) ([611c38e](https://github.com/lerna/lerna/commit/611c38edb07d18fc92a20ba44edab715519a203d)) - -# [3.21.0](https://github.com/lerna/lerna/compare/v3.20.2...v3.21.0) (2020-05-13) - -### Bug Fixes - -- **publish:** Canary releases without previous tags should not explode ([c9eb590](https://github.com/lerna/lerna/commit/c9eb590bf867889a188598322bb4552db7a34dfc)) - -### Features - -- **version:** Ignore private packages completely with `--no-private` ([a9b9f97](https://github.com/lerna/lerna/commit/a9b9f97457e4e4b0cac7f4ce562458d921a1f9be)) - -## [3.20.2](https://github.com/lerna/lerna/compare/v3.20.1...v3.20.2) (2020-01-02) - -**Note:** Version bump only for package @lerna/publish - -## [3.20.1](https://github.com/lerna/lerna/compare/v3.20.0...v3.20.1) (2019-12-29) - -**Note:** Version bump only for package @lerna/publish - -# [3.20.0](https://github.com/lerna/lerna/compare/v3.19.0...v3.20.0) (2019-12-27) - -### Features - -- **publish:** Add `--legacy-auth` flag ([#2347](https://github.com/lerna/lerna/issues/2347)) ([0e9bda7](https://github.com/lerna/lerna/commit/0e9bda769d944e3f0b9218ec1ecfaf63273baf11)) - -## [3.18.5](https://github.com/lerna/lerna/compare/v3.18.4...v3.18.5) (2019-11-20) - -### Bug Fixes - -- Auto-fix prettier formatting ([5344820](https://github.com/lerna/lerna/commit/5344820fc65da081d17f7fd2adb50ffe7101905b)) - -## [3.18.4](https://github.com/lerna/lerna/compare/v3.18.3...v3.18.4) (2019-11-08) - -**Note:** Version bump only for package @lerna/publish - -## [3.18.3](https://github.com/lerna/lerna/compare/v3.18.2...v3.18.3) (2019-10-22) - -**Note:** Version bump only for package @lerna/publish - -## [3.18.2](https://github.com/lerna/lerna/compare/v3.18.1...v3.18.2) (2019-10-21) - -**Note:** Version bump only for package @lerna/publish - -## [3.18.1](https://github.com/lerna/lerna/compare/v3.18.0...v3.18.1) (2019-10-15) - -**Note:** Version bump only for package @lerna/publish - -# [3.18.0](https://github.com/lerna/lerna/compare/v3.17.0...v3.18.0) (2019-10-15) - -### Bug Fixes - -- **options:** Explicit `--ignore-prepublish` ([fa21723](https://github.com/lerna/lerna/commit/fa217231c95d306bfdd3ffaf348c936a3232c998)) -- **options:** Explicit `--ignore-scripts` ([efcb3bd](https://github.com/lerna/lerna/commit/efcb3bd2a9591f5380abb349a09ae1f1b802de29)) -- **options:** Explicit `--pre-dist-tag` ([1d9552c](https://github.com/lerna/lerna/commit/1d9552c431ea78184ff51dc66f01de3314edb42e)) - -## [3.16.5](https://github.com/lerna/lerna/compare/v3.16.4...v3.16.5) (2019-10-07) - -**Note:** Version bump only for package @lerna/publish - -## [3.16.4](https://github.com/lerna/lerna/compare/v3.16.3...v3.16.4) (2019-07-24) - -### Bug Fixes - -- **publish:** Pass correct arguments to packDirectory() ([b1aade3](https://github.com/lerna/lerna/commit/b1aade3)) - -## [3.16.3](https://github.com/lerna/lerna/compare/v3.16.2...v3.16.3) (2019-07-23) - -### Bug Fixes - -- **publish:** Identify tagged packages correctly with custom `--tag-version-prefix` ([f4cbd4d](https://github.com/lerna/lerna/commit/f4cbd4d)), closes [#2195](https://github.com/lerna/lerna/issues/2195) - -## [3.16.2](https://github.com/lerna/lerna/compare/v3.16.1...v3.16.2) (2019-07-22) - -**Note:** Version bump only for package @lerna/publish - -## [3.16.1](https://github.com/lerna/lerna/compare/v3.16.0...v3.16.1) (2019-07-19) - -**Note:** Version bump only for package @lerna/publish - -# [3.16.0](https://github.com/lerna/lerna/compare/v3.15.0...v3.16.0) (2019-07-18) - -### Bug Fixes - -- **deps:** Bump `@evocateur/pacote` ([03e4797](https://github.com/lerna/lerna/commit/03e4797)) -- **deps:** Update forked npm libs ([4d67426](https://github.com/lerna/lerna/commit/4d67426)) -- **publish:** Add `--graph-type` option to control packages included in topological sort ([#2152](https://github.com/lerna/lerna/issues/2152)) ([ae87669](https://github.com/lerna/lerna/commit/ae87669)), closes [#1437](https://github.com/lerna/lerna/issues/1437) -- **publish:** Allow `--no-verify-access` to prevent checking for account-level 2FA ([ce58d8f](https://github.com/lerna/lerna/commit/ce58d8f)) -- **publish:** OTP cache should be seeded from conf value, not CLI directly ([cf56622](https://github.com/lerna/lerna/commit/cf56622)) -- **publish:** Propagate root license into custom publish directories ([d410a58](https://github.com/lerna/lerna/commit/d410a58)), closes [#2157](https://github.com/lerna/lerna/issues/2157) - -### Features - -- **deps:** `fs-extra@^8.1.0` ([313287f](https://github.com/lerna/lerna/commit/313287f)) -- **deps:** `p-map@^2.1.0` ([9e58394](https://github.com/lerna/lerna/commit/9e58394)) -- **deps:** `semver@^6.2.0` ([d8016d9](https://github.com/lerna/lerna/commit/d8016d9)) -- **publish:** Eager prompt for OTP when account-level 2FA is enabled ([4f893d1](https://github.com/lerna/lerna/commit/4f893d1)) - -# [3.15.0](https://github.com/lerna/lerna/compare/v3.14.2...v3.15.0) (2019-06-09) - -### Bug Fixes - -- **deps:** Consume forked npm libs ([bdd4fa1](https://github.com/lerna/lerna/commit/bdd4fa1)) - -## [3.14.2](https://github.com/lerna/lerna/compare/v3.14.1...v3.14.2) (2019-06-09) - -### Bug Fixes - -- **publish:** Allow per-leaf subdirectory publishing ([ea861d9](https://github.com/lerna/lerna/commit/ea861d9)), closes [#2109](https://github.com/lerna/lerna/issues/2109) - -## [3.14.1](https://github.com/lerna/lerna/compare/v3.14.0...v3.14.1) (2019-05-15) - -**Note:** Version bump only for package @lerna/publish - -# [3.14.0](https://github.com/lerna/lerna/compare/v3.13.4...v3.14.0) (2019-05-14) - -### Features - -- **conventional-commits:** Add conventional prerelease/graduation ([#1991](https://github.com/lerna/lerna/issues/1991)) ([5d84b61](https://github.com/lerna/lerna/commit/5d84b61)), closes [#1433](https://github.com/lerna/lerna/issues/1433) [#1675](https://github.com/lerna/lerna/issues/1675) -- **dist-tag:** Prompt for OTP when required ([af870bb](https://github.com/lerna/lerna/commit/af870bb)) -- **publish:** Add `--otp` option ([6fcbc36](https://github.com/lerna/lerna/commit/6fcbc36)), closes [#2076](https://github.com/lerna/lerna/issues/2076) -- **publish:** Add just-in-time queue management ([ae6471c](https://github.com/lerna/lerna/commit/ae6471c)) -- **publish:** Add OTP prompt during publish ([#2084](https://github.com/lerna/lerna/issues/2084)) ([c56bda1](https://github.com/lerna/lerna/commit/c56bda1)), closes [#1091](https://github.com/lerna/lerna/issues/1091) - -## [3.13.4](https://github.com/lerna/lerna/compare/v3.13.3...v3.13.4) (2019-04-24) - -**Note:** Version bump only for package @lerna/publish - -## [3.13.3](https://github.com/lerna/lerna/compare/v3.13.2...v3.13.3) (2019-04-17) - -### Bug Fixes - -- **docs:** Add missing docs for `--tag-version-prefix` ([#2035](https://github.com/lerna/lerna/issues/2035)) ([ff9c476](https://github.com/lerna/lerna/commit/ff9c476)), closes [#1924](https://github.com/lerna/lerna/issues/1924) - -## [3.13.2](https://github.com/lerna/lerna/compare/v3.13.1...v3.13.2) (2019-04-08) - -### Bug Fixes - -- **lifecycles:** Avoid duplicating 'rooted leaf' lifecycles ([a7ad9b6](https://github.com/lerna/lerna/commit/a7ad9b6)) - -## [3.13.1](https://github.com/lerna/lerna/compare/v3.13.0...v3.13.1) (2019-02-26) - -### Bug Fixes - -- **deps:** pacote ^9.5.0 ([cdc2e17](https://github.com/lerna/lerna/commit/cdc2e17)) - -# [3.13.0](https://github.com/lerna/lerna/compare/v3.12.1...v3.13.0) (2019-02-15) - -### Features - -- **meta:** Add `repository.directory` field to package.json ([aec5023](https://github.com/lerna/lerna/commit/aec5023)) -- **meta:** Normalize package.json `homepage` field ([abeb4dc](https://github.com/lerna/lerna/commit/abeb4dc)) - -## [3.12.1](https://github.com/lerna/lerna/compare/v3.12.0...v3.12.1) (2019-02-14) - -**Note:** Version bump only for package @lerna/publish - -# [3.12.0](https://github.com/lerna/lerna/compare/v3.11.1...v3.12.0) (2019-02-14) - -### Bug Fixes - -- **publish:** Check for git describe error explicitly ([237d1c5](https://github.com/lerna/lerna/commit/237d1c5)) -- **publish:** Make the missing license warning clearer and more actionable ([#1921](https://github.com/lerna/lerna/issues/1921)) ([8a71ac4](https://github.com/lerna/lerna/commit/8a71ac4)) -- **publish:** Revert foolhardy refactoring (5e975e0) ([a6733a2](https://github.com/lerna/lerna/commit/a6733a2)) - -### Features - -- **publish:** Add `--git-head` option to preserve gitless `from-package` metadata ([3d18f2f](https://github.com/lerna/lerna/commit/3d18f2f)), closes [#1933](https://github.com/lerna/lerna/issues/1933) -- **publish:** Allow `from-package` positional to run without a git repo ([df49bfc](https://github.com/lerna/lerna/commit/df49bfc)), closes [#1933](https://github.com/lerna/lerna/issues/1933) - -## [3.11.1](https://github.com/lerna/lerna/compare/v3.11.0...v3.11.1) (2019-02-11) - -**Note:** Version bump only for package @lerna/publish - -# [3.11.0](https://github.com/lerna/lerna/compare/v3.10.8...v3.11.0) (2019-02-08) - -### Bug Fixes - -- **deps:** Explicit libnpmaccess ^3.0.1 ([6ba3d1d](https://github.com/lerna/lerna/commit/6ba3d1d)) -- **deps:** Explicit libnpmpublish ^1.1.1 ([a506d96](https://github.com/lerna/lerna/commit/a506d96)) -- **deps:** Explicit npm-package-arg ^6.1.0 ([4b20791](https://github.com/lerna/lerna/commit/4b20791)) -- **deps:** Explicit npm-registry-fetch ^3.9.0 ([a83c487](https://github.com/lerna/lerna/commit/a83c487)) -- **deps:** Explicit npmlog ^4.1.2 ([571c2e2](https://github.com/lerna/lerna/commit/571c2e2)) -- **deps:** Explicit pacote ^9.4.1 ([44d05bf](https://github.com/lerna/lerna/commit/44d05bf)) -- **deps:** Remove unused libnpm (replaced by direct sub-packages) ([1caeb28](https://github.com/lerna/lerna/commit/1caeb28)) -- **publish:** Correct silly log heading ([f1dc3fc](https://github.com/lerna/lerna/commit/f1dc3fc)) - -## [3.10.8](https://github.com/lerna/lerna/compare/v3.10.7...v3.10.8) (2019-02-01) - -### Bug Fixes - -- **publish:** Skip private package lookup ([#1905](https://github.com/lerna/lerna/issues/1905)) ([f9e18fa](https://github.com/lerna/lerna/commit/f9e18fa)) - -## [3.10.7](https://github.com/lerna/lerna/compare/v3.10.6...v3.10.7) (2019-01-22) - -**Note:** Version bump only for package @lerna/publish - -## [3.10.6](https://github.com/lerna/lerna/compare/v3.10.5...v3.10.6) (2019-01-19) - -### Bug Fixes - -- **options:** Document negated boolean options explicitly ([8bc9669](https://github.com/lerna/lerna/commit/8bc9669)) -- **publish:** Map packument requests concurrently directly from package graph ([c79a827](https://github.com/lerna/lerna/commit/c79a827)) - -## [3.10.5](https://github.com/lerna/lerna/compare/v3.10.4...v3.10.5) (2019-01-11) - -**Note:** Version bump only for package @lerna/publish - -## [3.10.3](https://github.com/lerna/lerna/compare/v3.10.2...v3.10.3) (2019-01-10) - -**Note:** Version bump only for package @lerna/publish - -## [3.10.1](https://github.com/lerna/lerna/compare/v3.10.0...v3.10.1) (2019-01-09) - -**Note:** Version bump only for package @lerna/publish - -# [3.10.0](https://github.com/lerna/lerna/compare/v3.9.1...v3.10.0) (2019-01-08) - -### Bug Fixes - -- **publish:** Correctly determine canary version when `--include-merged-tags` present ([fb2a1b2](https://github.com/lerna/lerna/commit/fb2a1b2)), closes [#1820](https://github.com/lerna/lerna/issues/1820) - -# [3.9.0](https://github.com/lerna/lerna/compare/v3.8.5...v3.9.0) (2019-01-08) - -**Note:** Version bump only for package @lerna/publish - -## [3.8.5](https://github.com/lerna/lerna/compare/v3.8.4...v3.8.5) (2019-01-05) - -### Bug Fixes - -- **publish:** Deprecate `--npm-tag`, replaced by `--dist-tag` ([196d663](https://github.com/lerna/lerna/commit/196d663)) -- **publish:** Ensure pkg.publishConfig is handled correctly when promoting dist-tags ([af1c2ad](https://github.com/lerna/lerna/commit/af1c2ad)) -- **publish:** Tweak progress logging ([5a04145](https://github.com/lerna/lerna/commit/5a04145)) - -## [3.8.4](https://github.com/lerna/lerna/compare/v3.8.3...v3.8.4) (2019-01-03) - -### Bug Fixes - -- **publish:** Pass username to access.lsPackages() ([31982a1](https://github.com/lerna/lerna/commit/31982a1)) - -## [3.8.3](https://github.com/lerna/lerna/compare/v3.8.2...v3.8.3) (2019-01-03) - -### Bug Fixes - -- **publish:** Give up trying to validate third-party registries ([b44f2f9](https://github.com/lerna/lerna/commit/b44f2f9)), closes [#1685](https://github.com/lerna/lerna/issues/1685) [#1687](https://github.com/lerna/lerna/issues/1687) - -## [3.8.2](https://github.com/lerna/lerna/compare/v3.8.1...v3.8.2) (2019-01-03) - -### Bug Fixes - -- **publish:** Avoid recursive root lifecycle execution ([e133134](https://github.com/lerna/lerna/commit/e133134)) -- **publish:** Run root prepublish lifecycle if it exists ([c5676bb](https://github.com/lerna/lerna/commit/c5676bb)) - -## [3.8.1](https://github.com/lerna/lerna/compare/v3.8.0...v3.8.1) (2018-12-31) - -### Bug Fixes - -- **progress:** Correctly avoid progress where we don't want it ([0de3df9](https://github.com/lerna/lerna/commit/0de3df9)) -- **progress:** Enable progress during logging setup, correcting default ([da81e60](https://github.com/lerna/lerna/commit/da81e60)) -- **publish:** --canary should also respect --include-merged-tags ([462b15c](https://github.com/lerna/lerna/commit/462b15c)), closes [#1820](https://github.com/lerna/lerna/issues/1820) - -# [3.8.0](https://github.com/lerna/lerna/compare/v3.7.2...v3.8.0) (2018-12-21) - -### Bug Fixes - -- **publish:** Heighten dist-tag success log level to distinguish from noisy fetch logging ([f1f0871](https://github.com/lerna/lerna/commit/f1f0871)) -- **publish:** Unhide options shared with version command ([09fccd3](https://github.com/lerna/lerna/commit/09fccd3)) - -### Features - -- **publish:** Add --contents option ([5e790e5](https://github.com/lerna/lerna/commit/5e790e5)), closes [#1817](https://github.com/lerna/lerna/issues/1817) - -## [3.7.2](https://github.com/lerna/lerna/compare/v3.7.1...v3.7.2) (2018-12-21) - -### Bug Fixes - -- **pack-directory:** Accept lazy Package, passing directory as second parameter ([c6819c0](https://github.com/lerna/lerna/commit/c6819c0)) -- **publish:** Re-order --git-reset flag in options ([0653af9](https://github.com/lerna/lerna/commit/0653af9)) -- **publish:** Remove unused --npm-client option ([4e7eaef](https://github.com/lerna/lerna/commit/4e7eaef)) - -## [3.7.1](https://github.com/lerna/lerna/compare/v3.7.0...v3.7.1) (2018-12-20) - -### Bug Fixes - -- **publish:** Do not pass this.logger into conf, it does not respect log.level ([9bcd503](https://github.com/lerna/lerna/commit/9bcd503)) -- **publish:** Pulse progress bar during execution ([49b8771](https://github.com/lerna/lerna/commit/49b8771)) - -# [3.7.0](https://github.com/lerna/lerna/compare/v3.6.0...v3.7.0) (2018-12-19) - -### Bug Fixes - -- **publish:** Remove unused dependency ([d4ab6c4](https://github.com/lerna/lerna/commit/d4ab6c4)) -- **publish:** Short-circuit retries for npm username validation ([ca4dd95](https://github.com/lerna/lerna/commit/ca4dd95)) - -### Features - -- **npm-publish:** Use libnpm/publish instead of subprocess execution ([433275e](https://github.com/lerna/lerna/commit/433275e)) -- **publish:** Add npm-session, npm-version, and user-agent fields to libnpm/fetch config ([5edb27d](https://github.com/lerna/lerna/commit/5edb27d)) -- **publish:** Refresh package manifests after prepare/prepublishOnly lifecycle ([e6b31f8](https://github.com/lerna/lerna/commit/e6b31f8)) -- **publish:** Use [@lerna](https://github.com/lerna)/pack-directory instead of subprocess npm pack ([fd7299f](https://github.com/lerna/lerna/commit/fd7299f)) -- **publish:** Use libnpm/publish instead of subprocess execution ([58fda8d](https://github.com/lerna/lerna/commit/58fda8d)) - -# [3.6.0](https://github.com/lerna/lerna/compare/v3.5.1...v3.6.0) (2018-12-07) - -### Bug Fixes - -- **pkg:** Exclude **mocks** from package tarball ([4017f37](https://github.com/lerna/lerna/commit/4017f37)) - -### Features - -- Migrate existing usage to libnpm ([0d3a786](https://github.com/lerna/lerna/commit/0d3a786)), closes [#1767](https://github.com/lerna/lerna/issues/1767) -- **npm-dist-tag:** Use fetch API instead of CLI to make changes ([54008c6](https://github.com/lerna/lerna/commit/54008c6)) -- **publish:** Add a "from-package" positional argument ([#1708](https://github.com/lerna/lerna/issues/1708)) ([16611be](https://github.com/lerna/lerna/commit/16611be)), closes [#1648](https://github.com/lerna/lerna/issues/1648) -- **publish:** Attempt profile retrieval before whoami endpoint during user validation ([38097d8](https://github.com/lerna/lerna/commit/38097d8)) - -## [3.5.1](https://github.com/lerna/lerna/compare/v3.5.0...v3.5.1) (2018-11-29) - -### Bug Fixes - -- **publish:** Pass explicit list of files to checkout instead of globs ([a4c57c2](https://github.com/lerna/lerna/commit/a4c57c2)), closes [#1786](https://github.com/lerna/lerna/issues/1786) - -# [3.5.0](https://github.com/lerna/lerna/compare/v3.4.3...v3.5.0) (2018-11-27) - -### Bug Fixes - -- **publish:** Ignore non-release tags when detecting `from-git` ([#1782](https://github.com/lerna/lerna/issues/1782)) ([3cb7465](https://github.com/lerna/lerna/commit/3cb7465)) -- **version:** Add friendly error message when remote branch doesn't exist ([#1741](https://github.com/lerna/lerna/issues/1741)) ([cd34b48](https://github.com/lerna/lerna/commit/cd34b48)) -- **version:** Don't version private packages lacking a version field ([#1654](https://github.com/lerna/lerna/issues/1654)) ([578bb19](https://github.com/lerna/lerna/commit/578bb19)) - -### Features - -- **publish:** Add option `--no-git-reset` to leave unstaged changes in working tree ([#1791](https://github.com/lerna/lerna/issues/1791)) ([eae5619](https://github.com/lerna/lerna/commit/eae5619)) - -## [3.4.3](https://github.com/lerna/lerna/compare/v3.4.2...v3.4.3) (2018-10-10) - -### Bug Fixes - -- **publish:** Use correct field name when limiting retries ([76589d4](https://github.com/lerna/lerna/commit/76589d4)) - -## [3.4.2](https://github.com/lerna/lerna/compare/v3.4.1...v3.4.2) (2018-10-09) - -### Bug Fixes - -- **publish:** Prevent retries during access validation so third-party registries are skipped faster ([a89ae62](https://github.com/lerna/lerna/commit/a89ae62)) -- **publish:** Use modern auth resolution ([7ba41a6](https://github.com/lerna/lerna/commit/7ba41a6)) - -## [3.4.1](https://github.com/lerna/lerna/compare/v3.4.0...v3.4.1) (2018-10-04) - -### Bug Fixes - -- **publish:** Overwrite Yarn registry proxy when encountered ([f7fdc77](https://github.com/lerna/lerna/commit/f7fdc77)) -- **publish:** Set token on npm config, allow third-party registries to remain non-compliant ([06a9479](https://github.com/lerna/lerna/commit/06a9479)) - - - -# [3.4.0](https://github.com/lerna/lerna/compare/v3.3.2...v3.4.0) (2018-09-14) - -### Features - -- **publish:** Use APIs for validation queries instead of CLI ([65fc603](https://github.com/lerna/lerna/commit/65fc603)) - - - -## [3.3.2](https://github.com/lerna/lerna/compare/v3.3.1...v3.3.2) (2018-09-12) - -### Bug Fixes - -- **publish:** Allow `--force-publish` in a canary release ([b97d9a3](https://github.com/lerna/lerna/commit/b97d9a3)), closes [#1638](https://github.com/lerna/lerna/issues/1638) - - - -## [3.3.1](https://github.com/lerna/lerna/compare/v3.3.0...v3.3.1) (2018-09-11) - -**Note:** Version bump only for package @lerna/publish - - - -# [3.3.0](https://github.com/lerna/lerna/compare/v3.2.1...v3.3.0) (2018-09-06) - -### Bug Fixes - -- **describe-ref:** Fallback refCount is the number of commits since beginning of repository ([6dfea52](https://github.com/lerna/lerna/commit/6dfea52)) - -### Features - -- **deps:** Upgrade fs-extra to ^7.0.0 ([042b1a3](https://github.com/lerna/lerna/commit/042b1a3)) - - - -## [3.2.1](https://github.com/lerna/lerna/compare/v3.2.0...v3.2.1) (2018-08-28) - -### Bug Fixes - -- **publish:** Use package version as fallback for independent canary bump ([989a3b5](https://github.com/lerna/lerna/commit/989a3b5)), closes [#1614](https://github.com/lerna/lerna/issues/1614) - - - -# [3.2.0](https://github.com/lerna/lerna/compare/v3.1.4...v3.2.0) (2018-08-28) - -### Bug Fixes - -- **publish:** Call synthetic prepublishOnly lifecycle before packing ([dda9812](https://github.com/lerna/lerna/commit/dda9812)), closes [#1169](https://github.com/lerna/lerna/issues/1169) - -### Features - -- **publish:** Support prepack/postpack lifecycle in root manifest ([9df88a4](https://github.com/lerna/lerna/commit/9df88a4)) - - - -## [3.1.3](https://github.com/lerna/lerna/compare/v3.1.2...v3.1.3) (2018-08-21) - -**Note:** Version bump only for package @lerna/publish - - - -## [3.1.2](https://github.com/lerna/lerna/compare/v3.1.1...v3.1.2) (2018-08-20) - -### Bug Fixes - -- **publish:** Allow composed version command to decide when to verify working tree ([e61aa67](https://github.com/lerna/lerna/commit/e61aa67)) -- Use packageGraph.rawPackageList instead of misleading instance.filteredPackages ([2e2abdc](https://github.com/lerna/lerna/commit/2e2abdc)) - - - -# [3.1.0](https://github.com/lerna/lerna/compare/v3.0.6...v3.1.0) (2018-08-17) - -### Bug Fixes - -- **command:** Detect composed commands more accurately ([1e51b39](https://github.com/lerna/lerna/commit/1e51b39)) -- **command:** Log lerna CLI version with less ambiguity ([67494e7](https://github.com/lerna/lerna/commit/67494e7)) -- **publish:** Throw errors if --canary attempted on unclean tree or tagged release ([5da0e42](https://github.com/lerna/lerna/commit/5da0e42)) - - - -## [3.0.6](https://github.com/lerna/lerna/compare/v3.0.5...v3.0.6) (2018-08-16) - -**Note:** Version bump only for package @lerna/publish - - - -## [3.0.5](https://github.com/lerna/lerna/compare/v3.0.4...v3.0.5) (2018-08-15) - -### Bug Fixes - -- **help:** Insert line break before describing boolean negations ([da2f886](https://github.com/lerna/lerna/commit/da2f886)) -- **options:** Provide -y alias for --yes ([3ea460c](https://github.com/lerna/lerna/commit/3ea460c)) -- **publish:** Add confirmation prompt before execution ([47766e5](https://github.com/lerna/lerna/commit/47766e5)), closes [#1566](https://github.com/lerna/lerna/issues/1566) -- **publish:** Get tagged packages from merge commit ([#1567](https://github.com/lerna/lerna/issues/1567)) ([fc771d9](https://github.com/lerna/lerna/commit/fc771d9)) -- **version:** Log skipped publish when composed ([89645b7](https://github.com/lerna/lerna/commit/89645b7)) - - - -## [3.0.4](https://github.com/lerna/lerna/compare/v3.0.3...v3.0.4) (2018-08-14) - -### Bug Fixes - -- **publish:** Do not ping third-party registries ([42f4fdd](https://github.com/lerna/lerna/commit/42f4fdd)), closes [#1560](https://github.com/lerna/lerna/issues/1560) -- **publish:** Only pass `--json` to `npm pack` when npm >= 5.10.0 ([71babce](https://github.com/lerna/lerna/commit/71babce)), closes [#1558](https://github.com/lerna/lerna/issues/1558) -- **publish:** Run publish from leaf nodes again ([3d348ec](https://github.com/lerna/lerna/commit/3d348ec)), closes [#1560](https://github.com/lerna/lerna/issues/1560) - - - -## [3.0.3](https://github.com/lerna/lerna/compare/v3.0.2...v3.0.3) (2018-08-11) - -### Bug Fixes - -- **publish:** Restore deprecated `--skip-npm` functionality ([cb47cb6](https://github.com/lerna/lerna/commit/cb47cb6)), closes [#1553](https://github.com/lerna/lerna/issues/1553) - - - -## [3.0.2](https://github.com/lerna/lerna/compare/v3.0.1...v3.0.2) (2018-08-11) - -### Bug Fixes - -- **publish:** Add default for --tag-version-prefix ([f159442](https://github.com/lerna/lerna/commit/f159442)) -- **publish:** Allow disabling of registry and package verification ([0bfdff5](https://github.com/lerna/lerna/commit/0bfdff5)), closes [#1552](https://github.com/lerna/lerna/issues/1552) - - - -## [3.0.1](https://github.com/lerna/lerna/compare/v3.0.0...v3.0.1) (2018-08-10) - -### Bug Fixes - -- **publish:** Allow unpublished packages to pass access verification ([3a7348c](https://github.com/lerna/lerna/commit/3a7348c)) - - - -# [3.0.0](https://github.com/lerna/lerna/compare/v3.0.0-rc.0...v3.0.0) (2018-08-10) - -### Bug Fixes - -- **publish:** Improve `npm pack` experience ([627cfc2](https://github.com/lerna/lerna/commit/627cfc2)) - -### Features - -- Split `lerna version` from of `lerna publish` ([#1522](https://github.com/lerna/lerna/issues/1522)) ([8b97394](https://github.com/lerna/lerna/commit/8b97394)), closes [#277](https://github.com/lerna/lerna/issues/277) [#936](https://github.com/lerna/lerna/issues/936) [#956](https://github.com/lerna/lerna/issues/956) [#961](https://github.com/lerna/lerna/issues/961) [#1056](https://github.com/lerna/lerna/issues/1056) [#1118](https://github.com/lerna/lerna/issues/1118) [#1385](https://github.com/lerna/lerna/issues/1385) [#1483](https://github.com/lerna/lerna/issues/1483) [#1494](https://github.com/lerna/lerna/issues/1494) -- **publish:** Run `npm pack` before `npm publish` ([8d80b2c](https://github.com/lerna/lerna/commit/8d80b2c)) -- **publish:** Validate npm registry and package access prerequisites ([ebc8ba6](https://github.com/lerna/lerna/commit/ebc8ba6)), closes [#55](https://github.com/lerna/lerna/issues/55) [#1045](https://github.com/lerna/lerna/issues/1045) [#1347](https://github.com/lerna/lerna/issues/1347) - -### BREAKING CHANGES - -- - `--preid` now defaults to "alpha" during prereleases: - - The previous default for this option was undefined, which led to an awkward "1.0.1-0" result when passed to `semver.inc()`. - - The new default "alpha" yields a much more useful "1.0.1-alpha.0" result. Any previous prerelease ID will be preserved, just as it was before. - -- `--no-verify` is no longer passed to `git commit` by default, but controlled by the new `--commit-hooks` option: - - The previous behavior was too overzealous, and the new option operates exactly like the corresponding [npm version](https://docs.npmjs.com/cli/version#commit-hooks) option of the same name. - - As long as your pre-commit hooks are properly scoped to ignore changes in package.json files, this change should not affect you. If that is not the case, you may pass `--no-commit-hooks` to restore the previous behavior. - - - -# [3.0.0-rc.0](https://github.com/lerna/lerna/compare/v3.0.0-beta.21...v3.0.0-rc.0) (2018-07-27) - -### Bug Fixes - -- **core/package:** Serialize hosted git URLs with original protocol/shorthand ([60ff432](https://github.com/lerna/lerna/commit/60ff432)), closes [#1499](https://github.com/lerna/lerna/issues/1499) -- **publish:** Add default description 'npm' for --npm-client ([649048c](https://github.com/lerna/lerna/commit/649048c)) -- **publish:** Avoid fs-extra warning on 32-bit machines ([e908d23](https://github.com/lerna/lerna/commit/e908d23)) -- **publish:** Do not leave unstaged changes with --skip-git ([2d497ed](https://github.com/lerna/lerna/commit/2d497ed)) -- **publish:** Exit early when publishing w/o commits ([#1453](https://github.com/lerna/lerna/issues/1453)) ([6cbae35](https://github.com/lerna/lerna/commit/6cbae35)), closes [#773](https://github.com/lerna/lerna/issues/773) -- **publish:** Pass --repo-version argument through semver.valid() ([272e9f1](https://github.com/lerna/lerna/commit/272e9f1)), closes [#1483](https://github.com/lerna/lerna/issues/1483) -- **publish:** Update lerna.json version after root preversion lifecycle ([7b3817c](https://github.com/lerna/lerna/commit/7b3817c)), closes [#1495](https://github.com/lerna/lerna/issues/1495) - -### Code Refactoring - -- **collect-updates:** Make argument signature explicit ([e6ba19f](https://github.com/lerna/lerna/commit/e6ba19f)) - -### Features - -- Add description from --help summary [skip ci] ([9b65d8e](https://github.com/lerna/lerna/commit/9b65d8e)) -- **cli:** Upgrade to Yargs 12 ([7899ab8](https://github.com/lerna/lerna/commit/7899ab8)) -- **command:** Remove .defaultOptions() from option resolution stack ([2b27a54](https://github.com/lerna/lerna/commit/2b27a54)) -- Count packages affected in command summary logging ([5f5e585](https://github.com/lerna/lerna/commit/5f5e585)) -- **publish:** Add --require-scripts option to opt-in to raw JS lifecycle scripts ([054392b](https://github.com/lerna/lerna/commit/054392b)) -- **publish:** Add `--amend` flag ([#1422](https://github.com/lerna/lerna/issues/1422)) ([ef5f0db](https://github.com/lerna/lerna/commit/ef5f0db)) -- **publish:** Ensure published packages contain a LICENSE file ([#1465](https://github.com/lerna/lerna/issues/1465)) ([5863564](https://github.com/lerna/lerna/commit/5863564)), closes [#1213](https://github.com/lerna/lerna/issues/1213) - -### BREAKING CHANGES - -- **publish:** External `$PKGDIR/scripts/{pre,post}publish.js` lifecycles are now opt-in instead of automatic. Pass `--require-scripts` explicitly to restore previous functionality. -- **collect-updates:** Instead of an opaque command instance, distinct positional arguments are required. - - - -# [3.0.0-beta.21](https://github.com/lerna/lerna/compare/v3.0.0-beta.20...v3.0.0-beta.21) (2018-05-12) - -**Note:** Version bump only for package @lerna/publish - - - -# [3.0.0-beta.20](https://github.com/lerna/lerna/compare/v3.0.0-beta.19...v3.0.0-beta.20) (2018-05-07) - -**Note:** Version bump only for package @lerna/publish - - - -# [3.0.0-beta.19](https://github.com/lerna/lerna/compare/v3.0.0-beta.18...v3.0.0-beta.19) (2018-05-03) - -### Bug Fixes - -- **publish:** Include all packages during global major bump ([#1391](https://github.com/lerna/lerna/issues/1391)) ([9cebed1](https://github.com/lerna/lerna/commit/9cebed1)), closes [#1383](https://github.com/lerna/lerna/issues/1383) - - - -# [3.0.0-beta.18](https://github.com/lerna/lerna/compare/v3.0.0-beta.17...v3.0.0-beta.18) (2018-04-24) - -### Bug Fixes - -- **git-utils:** Pass `--follow-tags` to `git push` ([6907e90](https://github.com/lerna/lerna/commit/6907e90)) - -### Features - -- **command:** Move GitUtilities.isInitialized into class method ([abecfcc](https://github.com/lerna/lerna/commit/abecfcc)) -- **git-utils:** Devolve getCurrentSHA() to consumers ([ecbc1d3](https://github.com/lerna/lerna/commit/ecbc1d3)) -- **git-utils:** Devolve getShortSHA() to consumers ([95d179d](https://github.com/lerna/lerna/commit/95d179d)) -- **publish:** Move publish-only git utilities ([5594749](https://github.com/lerna/lerna/commit/5594749)) - -### BREAKING CHANGES - -- **git-utils:** Don't use GitUtilities! -- **git-utils:** Don't use GitUtilities. -- **command:** GitUtilities.isInitialized no longer exists. You shouldn't be using GitUtilities. -- **publish:** Many named exports of GitUtilities are no longer provided. Don't use GitUtilities, it's a bad pattern. - - - -# [3.0.0-beta.17](https://github.com/lerna/lerna/compare/v3.0.0-beta.16...v3.0.0-beta.17) (2018-04-13) - -**Note:** Version bump only for package @lerna/publish - - - -# [3.0.0-beta.15](https://github.com/lerna/lerna/compare/v3.0.0-beta.14...v3.0.0-beta.15) (2018-04-09) - -### Features - -- **conventional-commits:** Support local file presets ([a1bff40](https://github.com/lerna/lerna/commit/a1bff40)) - - - -# [3.0.0-beta.14](https://github.com/lerna/lerna/compare/v3.0.0-beta.13...v3.0.0-beta.14) (2018-04-03) - -### Bug Fixes - -- **publish:** Ensure optionalDependencies are updated during publish to registry ([559b731](https://github.com/lerna/lerna/commit/559b731)) - - - -# [3.0.0-beta.13](https://github.com/lerna/lerna/compare/v3.0.0-beta.12...v3.0.0-beta.13) (2018-03-31) - -### Features - -- Enable progress bars only when necessary ([b766c83](https://github.com/lerna/lerna/commit/b766c83)) - - - -# [3.0.0-beta.12](https://github.com/lerna/lerna/compare/v3.0.0-beta.11...v3.0.0-beta.12) (2018-03-30) - -### Features - -- **package:** Add `serialize()` method ([fdec3ac](https://github.com/lerna/lerna/commit/fdec3ac)) -- **package:** Add Map-like get/set methods, remove raw json getter ([707d1f0](https://github.com/lerna/lerna/commit/707d1f0)) -- **project:** Merge `package` and `packageJson` into `manifest` ([9a47ff7](https://github.com/lerna/lerna/commit/9a47ff7)) - -### BREAKING CHANGES - -- **package:** The `Package` class no longer provides direct access to the JSON object - used to construct the instance. Map-like `get()`/`set(val)` methods are - available to modify the internal representation. - - - -# [3.0.0-beta.11](https://github.com/lerna/lerna/compare/v3.0.0-beta.10...v3.0.0-beta.11) (2018-03-29) - -### Bug Fixes - -- **publish:** Write temporary annotations once, not repeatedly ([6abae76](https://github.com/lerna/lerna/commit/6abae76)) - -### Features - -- Execute atomic publish lifecycle during lerna publish ([#1348](https://github.com/lerna/lerna/issues/1348)) ([45efa24](https://github.com/lerna/lerna/commit/45efa24)) -- Support `optionalDependencies` ([b73e19d](https://github.com/lerna/lerna/commit/b73e19d)), closes [#121](https://github.com/lerna/lerna/issues/121) - - - -# [3.0.0-beta.10](https://github.com/lerna/lerna/compare/v3.0.0-beta.9...v3.0.0-beta.10) (2018-03-27) - -### Features - -- **commands:** Delay require of command instantiation ([a1284f3](https://github.com/lerna/lerna/commit/a1284f3)) - -### BREAKING CHANGES - -- **commands:** The default export of command packages is now a factory, not the subclass (which is now a named export). - - - -# [3.0.0-beta.9](https://github.com/lerna/lerna/compare/v3.0.0-beta.8...v3.0.0-beta.9) (2018-03-24) - -### Bug Fixes - -- **publish:** Split `--skip-*` properly, leave working tree clean ([5b4b2c9](https://github.com/lerna/lerna/commit/5b4b2c9)) - -### Features - -- **command:** Rename this.repository -> this.project ([43e98a0](https://github.com/lerna/lerna/commit/43e98a0)) -- **project:** Use cosmiconfig to locate and read lerna.json ([b8c2789](https://github.com/lerna/lerna/commit/b8c2789)) - -### BREAKING CHANGES - -- **publish:** Previously, gitHead annotations were leftover if `--skip-npm` was passed, - despite no actual requirement for that property when no publishing is going on. - -Now, all publish-related operations are truly skipped with `--skip-npm`, -and all git commit/push-related operations are skipped with `--skip-git`. -Passing `--skip-npm` will now also always push to remote, which represents -a breaking change from 2.x behavior. - -Thanks @KingScooty for raising the issue! - - - -# [3.0.0-beta.8](https://github.com/lerna/lerna/compare/v3.0.0-beta.7...v3.0.0-beta.8) (2018-03-22) - -### Features - -- **utils:** Add "vendored" npm-conf ([9c24a25](https://github.com/lerna/lerna/commit/9c24a25)) - - - -# [3.0.0-beta.7](https://github.com/lerna/lerna/compare/v3.0.0-beta.6...v3.0.0-beta.7) (2018-03-20) - -**Note:** Version bump only for package @lerna/publish - - - -# [3.0.0-beta.4](https://github.com/lerna/lerna/compare/v3.0.0-beta.3...v3.0.0-beta.4) (2018-03-19) - -**Note:** Version bump only for package @lerna/publish - - - -# [3.0.0-beta.3](https://github.com/lerna/lerna/compare/v3.0.0-beta.2...v3.0.0-beta.3) (2018-03-15) - -### Features - -- Check for upstream changes before attempting to publish ([#1317](https://github.com/lerna/lerna/issues/1317)) ([cef0a69](https://github.com/lerna/lerna/commit/cef0a69)) -- Upstream changes warn in CI, throw locally ([4de055d](https://github.com/lerna/lerna/commit/4de055d)), closes [#1177](https://github.com/lerna/lerna/issues/1177) [#1317](https://github.com/lerna/lerna/issues/1317) -- **publish:** Add logging when `--skip-git` or `--skip-npm` are passed ([#1319](https://github.com/lerna/lerna/issues/1319)) ([8eef9ff](https://github.com/lerna/lerna/commit/8eef9ff)) - - - -# [3.0.0-beta.2](https://github.com/lerna/lerna/compare/v3.0.0-beta.1...v3.0.0-beta.2) (2018-03-10) - -**Note:** Version bump only for package @lerna/publish - - - -# [3.0.0-beta.1](https://github.com/lerna/lerna/compare/v3.0.0-beta.0...v3.0.0-beta.1) (2018-03-09) - -### Bug Fixes - -- **publish:** Checkout manifest changes serially ([ce4a4b1](https://github.com/lerna/lerna/commit/ce4a4b1)) -- **publish:** default root manifest name when missing ([a504d7e](https://github.com/lerna/lerna/commit/a504d7e)), closes [#1305](https://github.com/lerna/lerna/issues/1305) -- **publish:** Respect pkg.publishConfig.tag ([04b256a](https://github.com/lerna/lerna/commit/04b256a)), closes [#1311](https://github.com/lerna/lerna/issues/1311) -- **publish:** work around yarn "link:" intransigency ([ddfb517](https://github.com/lerna/lerna/commit/ddfb517)), closes [npm/npm#15900](https://github.com/npm/npm/issues/15900) [yarnpkg/yarn#4212](https://github.com/yarnpkg/yarn/issues/4212) diff --git a/commands/publish/README.md b/commands/publish/README.md deleted file mode 100644 index ceb7b9fd35..0000000000 --- a/commands/publish/README.md +++ /dev/null @@ -1,431 +0,0 @@ -# `@lerna/publish` - -> Publish packages in the current project - -Install [lerna](https://www.npmjs.com/package/lerna) for access to the `lerna` CLI. - -## Usage - -```sh -lerna publish # publish packages that have changed since the last release -lerna publish from-git # explicitly publish packages tagged in the current commit -lerna publish from-package # explicitly publish packages where the latest version is not present in the registry -``` - -When run, this command does one of the following things: - -- Publish packages updated since the last release (calling [`lerna version`](https://github.com/lerna/lerna/tree/main/commands/version#readme) behind the scenes). - - This is the legacy behavior of lerna 2.x -- Publish packages tagged in the current commit (`from-git`). -- Publish packages in the latest commit where the version is not present in the registry (`from-package`). -- Publish an unversioned "canary" release of packages (and their dependents) updated in the previous commit. - -> Lerna will never publish packages which are marked as private (`"private": true` in the `package.json`). - -During all publish operations, appropriate [lifecycle scripts](#lifecycle-scripts) are called in the root and per-package (unless disabled by [`--ignore-scripts](#--ignore-scripts)). - -Check out [Per-Package Configuration](#per-package-configuration) for more details about publishing scoped packages, custom registries, and custom dist-tags. - -## Positionals - -### bump `from-git` - -In addition to the semver keywords supported by [`lerna version`](https://github.com/lerna/lerna/tree/main/commands/version#positionals), -`lerna publish` also supports the `from-git` keyword. -This will identify packages tagged by `lerna version` and publish them to npm. -This is useful in CI scenarios where you wish to manually increment versions, -but have the package contents themselves consistently published by an automated process. - -### bump `from-package` - -Similar to the `from-git` keyword except the list of packages to publish is determined by inspecting each `package.json` -and determining if any package version is not present in the registry. Any versions not present in the registry will -be published. -This is useful when a previous `lerna publish` failed to publish all packages to the registry. - -## Options - -`lerna publish` supports all of the options provided by [`lerna version`](https://github.com/lerna/lerna/tree/main/commands/version#options) in addition to the following: - -- [`--canary`](#--canary) -- [`--contents `](#--contents-dir) -- [`--dist-tag `](#--dist-tag-tag) -- [`--git-head `](#--git-head-sha) -- [`--graph-type `](#--graph-type-alldependencies) -- [`--ignore-scripts`](#--ignore-scripts) -- [`--ignore-prepublish`](#--ignore-prepublish) -- [`--legacy-auth`](#--legacy-auth) -- [`--no-git-reset`](#--no-git-reset) -- [`--no-granular-pathspec`](#--no-granular-pathspec) -- [`--verify-access`](#--verify-access) -- [`--otp`](#--otp) -- [`--preid`](#--preid) -- [`--pre-dist-tag `](#--pre-dist-tag-tag) -- [`--registry `](#--registry-url) -- [`--tag-version-prefix`](#--tag-version-prefix) -- [`--temp-tag`](#--temp-tag) -- [`--yes`](#--yes) -- [`--summary-file `](#--summary-file) - -### `--canary` - -```sh -lerna publish --canary -# 1.0.0 => 1.0.1-alpha.0+${SHA} of packages changed since the previous commit -# a subsequent canary publish will yield 1.0.1-alpha.1+${SHA}, etc - -lerna publish --canary --preid beta -# 1.0.0 => 1.0.1-beta.0+${SHA} - -# The following are equivalent: -lerna publish --canary minor -lerna publish --canary preminor -# 1.0.0 => 1.1.0-alpha.0+${SHA} -``` - -When run with this flag, `lerna publish` publishes packages in a more granular way (per commit). -Before publishing to npm, it creates the new `version` tag by taking the current `version`, bumping it to the next _minor_ version, adding the provided meta suffix (defaults to `alpha`) and appending the current git sha (ex: `1.0.0` becomes `1.1.0-alpha.0+81e3b443`). - -If you have publish canary releases from multiple active development branches in CI, -it is recommended to customize the [`--preid`](#--preid) and [`--dist-tag `](#--dist-tag-tag) on a per-branch basis to avoid clashing versions. - -> The intended use case for this flag is a per commit level release or nightly release. - -### `--contents ` - -Subdirectory to publish. Must apply to ALL packages, and MUST contain a package.json file. -Package lifecycles will still be run in the original leaf directory. -You should probably use one of those lifecycles (`prepare`, `prepublishOnly`, or `prepack`) to _create_ the subdirectory and whatnot. - -If you're into unnecessarily complicated publishing, this will give you joy. - -```sh -lerna publish --contents dist -# publish the "dist" subfolder of every Lerna-managed leaf package -``` - -**NOTE:** You should wait until the `postpublish` lifecycle phase (root or leaf) to clean up this generated subdirectory, -as the generated package.json is used during package upload (_after_ `postpack`). - -### `--dist-tag ` - -```sh -lerna publish --dist-tag next -``` - -When run with this flag, `lerna publish` will publish to npm with the given npm [dist-tag](https://docs.npmjs.com/cli/dist-tag) (defaults to `latest`). - -This option can be used to publish a [`prerelease`](http://carrot.is/coding/npm_prerelease) or `beta` version under a non-`latest` dist-tag, helping consumers avoid automatically upgrading to prerelease-quality code. - -> Note: the `latest` tag is the one that is used when a user runs `npm install my-package`. -> To install a different tag, a user can run `npm install my-package@prerelease`. - -### `--force-publish` - -To be used with [`--canary`](#--canary) to publish a canary version of all packages in your monorepo. This flag can be helpful when you need to make canary releases of packages beyond what was changed in the most recent commit. - -``` -lerna publish --canary --force-publish -``` - -### `--git-head ` - -Explicit SHA to set as [`gitHead`](https://github.com/npm/read-package-json/blob/67f2d8d501e2621441a8235b08d589fbeeb7dba6/read-json.js#L327) on manifests when packing tarballs, only allowed with [`from-package`](#bump-from-package) positional. - -For example, when publishing from AWS CodeBuild (where `git` is not available), -you could use this option to pass the appropriate [environment variable](https://docs.aws.amazon.com/codebuild/latest/userguide/build-env-ref-env-vars.html) to use for this package metadata: - -```sh -lerna publish from-package --git-head ${CODEBUILD_RESOLVED_SOURCE_VERSION} -``` - -Under all other circumstances, this value is derived from a local `git` command. - -### `--graph-type ` - -Set which kind of dependencies to use when building a package graph. The default value is `dependencies`, whereby only packages listed in the `dependencies` section of a package's `package.json` are included. Pass `all` to include both `dependencies` _and_ `devDependencies` when constructing the package graph and determining topological order. - -When using traditional peer + dev dependency pairs, this option should be configured to `all` so the peers are always published before their dependents. - -```sh -lerna publish --graph-type all -``` - -Configured via `lerna.json`: - -```json -{ - "command": { - "publish": { - "graphType": "all" - } - } -} -``` - -### `--ignore-scripts` - -When passed, this flag will disable running [lifecycle scripts](#lifecycle-scripts) during `lerna publish`. - -### `--ignore-prepublish` - -When passed, this flag will disable running [deprecated](https://docs.npmjs.com/misc/scripts#prepublish-and-prepare) [`prepublish` scripts](#lifecycle-scripts) during `lerna publish`. - -### `--legacy-auth` - -When publishing packages that require authentication but you are working with an internally hosted NPM Registry that only uses the legacy Base64 version of username:password. This is the same as the NPM publish `_auth` flag. - -```sh -lerna publish --legacy-auth aGk6bW9t -``` - -### `--no-git-reset` - -By default, `lerna publish` ensures any changes to the working tree have been reset. - -To avoid this, pass `--no-git-reset`. This can be especially useful when used as part of a CI pipeline in conjunction with the `--canary` flag. For instance, the `package.json` version numbers which have been bumped may need to be used in subsequent CI pipeline steps (such as Docker builds). - -```sh -lerna publish --no-git-reset -``` - -### `--no-granular-pathspec` - -By default, `lerna publish` will attempt (if enabled) to `git checkout` _only_ the leaf package manifests that are temporarily modified during the publishing process. This yields the equivalent of `git checkout -- packages/*/package.json`, but tailored to _exactly_ what changed. - -If you **know** you need different behavior, you'll understand: Pass `--no-granular-pathspec` to make the git command _literally_ `git checkout -- .`. By opting into this [pathspec](https://git-scm.com/docs/gitglossary#Documentation/gitglossary.txt-aiddefpathspecapathspec), you must have all intentionally unversioned content properly ignored. - -This option makes the most sense configured in lerna.json, as you really don't want to mess it up: - -```json -{ - "version": "independent", - "granularPathspec": false -} -``` - -The root-level configuration is intentional, as this also covers the [identically-named option in `lerna version`](https://github.com/lerna/lerna/tree/main/commands/version#--no-granular-pathspec). - -### `--verify-access` - -Historically, `lerna` attempted to fast-fail on authorization/authentication issues by performing some preemptive npm API requests using the given token. These days, however, there are multiple types of tokens that npm supports and they have varying levels of access rights, so there is no one-size fits all solution for this preemptive check and it is more appropriate to allow requests to npm to simply fail with appropriate errors for the given token. For this reason, the legacy `--verify-access` behavior is disabled by default and will likely be removed in a future major version. - -For now, though, if you pass this flag you can opt into the legacy behavior and `lerna` will preemptively perform this verification before it attempts to publish any packages. - -You should NOT use this option if: - -1. You are using a third-party registry that does not support `npm access ls-packages` -2. You are using an authentication token without read access, such as a [npm automation access token](https://docs.npmjs.com/creating-and-viewing-access-tokens#creating-access-tokens) - -### `--otp` - -When publishing packages that require two-factor authentication, you can specify a [one-time password](https://docs.npmjs.com/about-two-factor-authentication) using `--otp`: - -```sh -lerna publish --otp 123456 -``` - -> Please keep in mind that one-time passwords expire within 30 seconds of their generation. If it expires during publish operations, a prompt will request a refreshed value before continuing. - -### `--preid` - -Unlike the `lerna version` option of the same name, this option only applies to [`--canary`](#--canary) version calculation. - -```sh -lerna publish --canary -# uses the next semantic prerelease version, e.g. -# 1.0.0 => 1.0.1-alpha.0 - -lerna publish --canary --preid next -# uses the next semantic prerelease version with a specific prerelease identifier, e.g. -# 1.0.0 => 1.0.1-next.0 -``` - -When run with this flag, `lerna publish --canary` will increment `premajor`, `preminor`, `prepatch`, or `prerelease` semver -bumps using the specified [prerelease identifier](http://semver.org/#spec-item-9). - -### `--pre-dist-tag ` - -```sh -lerna publish --pre-dist-tag next -``` - -Works the same as [`--dist-tag`](#--dist-tag-tag), except only applies to packages being released with a prerelease version. - -### `--registry ` - -When run with this flag, forwarded npm commands will use the specified registry for your package(s). - -This is useful if you do not want to explicitly set up your registry -configuration in all of your package.json files individually when e.g. using -private registries. - -### `--tag-version-prefix` - -This option allows to provide custom prefix instead of the default one: `v`. - -Keep in mind, if splitting `lerna version` and `lerna publish`, you need to pass it to both commands: - -```bash -# locally -lerna version --tag-version-prefix='' - -# on ci -lerna publish from-git --tag-version-prefix='' -``` - -You could also configure this at the root level of lerna.json, applying to both commands equally: - -```json -{ - "tagVersionPrefix": "", - "packages": ["packages/*"], - "version": "independent" -} -``` - -### `--temp-tag` - -When passed, this flag will alter the default publish process by first publishing -all changed packages to a temporary dist-tag (`lerna-temp`) and then moving the -new version(s) to the dist-tag configured by [`--dist-tag`](#--dist-tag-tag) (default `latest`). - -This is not generally necessary, as Lerna will publish packages in topological -order (all dependencies before dependents) by default. - -### `--yes` - -```sh -lerna publish --canary --yes -# skips `Are you sure you want to publish the above changes?` -``` - -When run with this flag, `lerna publish` will skip all confirmation prompts. -Useful in [Continuous integration (CI)](https://en.wikipedia.org/wiki/Continuous_integration) to automatically answer the publish confirmation prompt. - -### `--summary-file` - -```sh -# Will create a summary file in the root directory, i.e. `./lerna-publish-summary.json` -lerna publish --canary --yes --summary-file -# Will create a summary file in the provided directory, i.e. `./some/other/dir/lerna-publish-summary.json` -lerna publish --canary --yes --summary-file ./some/other/dir - -``` - -When run with this flag, a json summary report will be generated after all packages have been successfully published (see below for an example). - -```json -[ - { - "packageName": "package1", - "version": "v1.0.1-alpha" - }, - { - "packageName": "package2", - "version": "v2.0.1-alpha" - } -] -``` - -## Deprecated Options - -### `--no-verify-access` - -The legacy preemptive access verification is now off by default, so `--no-verify-access` is not needed. Requests will fail with appropriate errors when not authorized correctly. To opt-in to the legacy access verification, use [`--verify-access`](#--verify-access). - -### `--skip-npm` - -Call [`lerna version`](https://github.com/lerna/lerna/tree/main/commands/version#readme) directly, instead. - -## Per-Package Configuration - -A leaf package can be configured with special [`publishConfig`](https://docs.npmjs.com/files/package.json#publishconfig) that in _certain_ circumstances changes the behavior of `lerna publish`. - -### `publishConfig.access` - -To publish packages with a scope (e.g., `@mycompany/rocks`), you must set [`access`](https://docs.npmjs.com/misc/config#access): - -```json - "publishConfig": { - "access": "public" - } -``` - -- If this field is set for a package _without_ a scope, it **will** fail. -- If you _want_ your scoped package to remain private (i.e., `"restricted"`), there is no need to set this value. - - Note that this is **not** the same as setting `"private": true` in a leaf package; if the `private` field is set, that package will _never_ be published under any circumstances. - -### `publishConfig.registry` - -You can customize the registry on a per-package basis by setting [`registry`](https://docs.npmjs.com/misc/config#registry): - -```json - "publishConfig": { - "registry": "http://my-awesome-registry.com/" - } -``` - -- Passing [`--registry`](#--registry-url) applies globally, and in some cases isn't what you want. - -### `publishConfig.tag` - -You can customize the dist-tag on a per-package basis by setting [`tag`](https://docs.npmjs.com/misc/config#tag): - -```json - "publishConfig": { - "tag": "flippin-sweet" - } -``` - -- Passing [`--dist-tag`](#--dist-tag-tag) will _overwrite_ this value. -- This value is _always_ ignored when [`--canary`](#--canary) is passed. - -### `publishConfig.directory` - -This _non-standard_ field allows you to customize the published subdirectory just like [`--contents`](#--contents-dir), but on a per-package basis. All other caveats of `--contents` still apply. - -```json - "publishConfig": { - "directory": "dist" - } -``` - - - -## Lifecycle Scripts - -```js -// prepublish: Run BEFORE the package is packed and published. -// prepare: Run BEFORE the package is packed and published, AFTER prepublish, BEFORE prepublishOnly. -// prepublishOnly: Run BEFORE the package is packed and published, ONLY on npm publish. -// prepack: Run BEFORE a tarball is packed. -// postpack: Run AFTER the tarball has been generated and moved to its final destination. -// publish: Run AFTER the package is published. -// postpublish: Run AFTER the package is published. -``` - -Lerna will run [npm lifecycle scripts](https://docs.npmjs.com/misc/scripts#description) during `lerna publish` in the following order: - -1. If versioning implicitly, run all [version lifecycle scripts](https://github.com/lerna/lerna/tree/main/commands/version#lifecycle-scripts) -2. Run `prepublish` lifecycle in root, if [enabled](#--ignore-prepublish) -3. Run `prepare` lifecycle in root -4. Run `prepublishOnly` lifecycle in root -5. Run `prepack` lifecycle in root -6. For each changed package, in topological order (all dependencies before dependents): - 1. Run `prepublish` lifecycle, if [enabled](#--ignore-prepublish) - 2. Run `prepare` lifecycle - 3. Run `prepublishOnly` lifecycle - 4. Run `prepack` lifecycle - 5. Create package tarball in temp directory via [JS API](https://github.com/lerna/lerna/tree/main/utils/pack-directory#readme) - 6. Run `postpack` lifecycle -7. Run `postpack` lifecycle in root -8. For each changed package, in topological order (all dependencies before dependents): - 1. Publish package to configured [registry](#--registry-url) via [JS API](https://github.com/lerna/lerna/tree/main/utils/npm-publish#readme) - 2. Run `publish` lifecycle - 3. Run `postpublish` lifecycle -9. Run `publish` lifecycle in root - - To avoid recursive calls, don't use this root lifecycle to run `lerna publish` -10. Run `postpublish` lifecycle in root -11. Update temporary dist-tag to latest, if [enabled](#--temp-tag) diff --git a/commands/publish/__tests__/create-temp-licenses.test.js b/commands/publish/__tests__/create-temp-licenses.test.js deleted file mode 100644 index 05ca0fa7c1..0000000000 --- a/commands/publish/__tests__/create-temp-licenses.test.js +++ /dev/null @@ -1,82 +0,0 @@ -"use strict"; - -const fs = require("fs-extra"); -const path = require("path"); -const { Project } = require("@lerna/project"); -const initFixture = require("@lerna-test/helpers").initFixtureFactory(__dirname); -const { createTempLicenses } = require("../lib/create-temp-licenses"); - -describe("createTempLicenses", () => { - it("copies root license into package location", async () => { - const cwd = await initFixture("licenses"); - const project = new Project(cwd); - const [pkg] = await project.getPackages(); - - await createTempLicenses(project.licensePath, [pkg]); - - const licenseWritten = await fs.pathExists(path.join(pkg.location, "LICENSE")); - expect(licenseWritten).toBe(true); - }); - - it("copies root license into package contents", async () => { - const cwd = await initFixture("licenses"); - const project = new Project(cwd); - const [pkg] = await project.getPackages(); - - // automagical "contents" setter creates absolute path - pkg.contents = "dist"; - - await createTempLicenses(project.licensePath, [pkg]); - - const licenseWritten = await fs.pathExists(path.join(pkg.contents, "LICENSE")); - expect(licenseWritten).toBe(true); - }); - - it("copies root license into package publishConfig.directory", async () => { - const cwd = await initFixture("licenses"); - const project = new Project(cwd); - const [pkg] = await project.getPackages(); - - // automagical "contents" getter creates absolute path - await pkg.set("publishConfig", { directory: "build" }).serialize(); - - await createTempLicenses(project.licensePath, [pkg]); - - const licenseWritten = await fs.pathExists(path.join(pkg.contents, "LICENSE")); - expect(licenseWritten).toBe(true); - }); - - it("copies root license with extension into package location", async () => { - const cwd = await initFixture("licenses"); - const project = new Project(cwd); - const [pkg] = await project.getPackages(); - - await fs.move(path.join(cwd, "LICENSE"), path.join(cwd, "LICENSE.md")); - await createTempLicenses(project.licensePath, [pkg]); - - const licenseWritten = await fs.pathExists(path.join(pkg.location, "LICENSE.md")); - expect(licenseWritten).toBe(true); - }); - - it("skips copying when root license is missing", async () => { - const cwd = await initFixture("licenses"); - const project = new Project(cwd); - const [pkg] = await project.getPackages(); - - await createTempLicenses(undefined, [pkg]); - - const licenseWritten = await fs.pathExists(path.join(pkg.location, "LICENSE")); - expect(licenseWritten).toBe(false); - }); - - it("skips copying when there are no packages to be licensed", async () => { - const cwd = await initFixture("licenses"); - const project = new Project(cwd); - const [pkg] = await project.getPackages(); - - await createTempLicenses(project.licensePath, []); - - const licenseWritten = await fs.pathExists(path.join(pkg.location, "LICENSE")); - expect(licenseWritten).toBe(false); - }); -}); diff --git a/commands/publish/__tests__/get-current-sha.test.js b/commands/publish/__tests__/get-current-sha.test.js deleted file mode 100644 index 57a19ffe41..0000000000 --- a/commands/publish/__tests__/get-current-sha.test.js +++ /dev/null @@ -1,10 +0,0 @@ -"use strict"; - -const initFixture = require("@lerna-test/helpers").initFixtureFactory(__dirname); -const { getCurrentSHA } = require("../lib/get-current-sha"); - -test("getCurrentSHA", async () => { - const cwd = await initFixture("root-manifest-only"); - - expect(getCurrentSHA({ cwd })).toMatch(/^[0-9a-f]{40}$/); -}); diff --git a/commands/publish/__tests__/get-npm-username.test.js b/commands/publish/__tests__/get-npm-username.test.js deleted file mode 100644 index 8154f3f985..0000000000 --- a/commands/publish/__tests__/get-npm-username.test.js +++ /dev/null @@ -1,106 +0,0 @@ -"use strict"; - -jest.mock("npm-registry-fetch"); - -const fetch = require("npm-registry-fetch"); -const { loggingOutput } = require("@lerna-test/helpers/logging-output"); -const { getNpmUsername } = require("../lib/get-npm-username"); - -fetch.json.mockImplementation(() => Promise.resolve({ username: "lerna-test" })); - -describe("getNpmUsername", () => { - const origConsoleError = console.error; - - beforeEach(() => { - console.error = jest.fn(); - }); - - afterEach(() => { - console.error = origConsoleError; - }); - - test("fetches whoami endpoint after profile 404", async () => { - fetch.json.mockImplementationOnce(() => { - const err = new Error("third-party profile fail"); - - err.code = "E404"; - - return Promise.reject(err); - }); - const opts = { registry: "such-config-wow" }; - - const username = await getNpmUsername(opts); - - expect(username).toBe("lerna-test"); - expect(fetch.json).toHaveBeenLastCalledWith("/-/whoami", expect.objectContaining({ fetchRetries: 0 })); - }); - - test("throws an error when successful fetch yields empty username", async () => { - fetch.json.mockImplementationOnce(() => Promise.resolve({ username: undefined })); - - await expect(getNpmUsername({ stub: true })).rejects.toThrow( - "You must be logged in to publish packages. Use `npm login` and try again." - ); - expect(console.error).not.toHaveBeenCalled(); - }); - - test("logs failure message before throwing validation error", async () => { - fetch.json.mockImplementationOnce(() => { - const err = new Error("legacy npm Enterprise profile fail"); - - err.code = "E500"; - - return Promise.reject(err); - }); - fetch.json.mockImplementationOnce(() => { - const err = new Error("third-party whoami fail"); - - err.code = "E404"; - - return Promise.reject(err); - }); - - const opts = { registry: "https://registry.npmjs.org/" }; - - await expect(getNpmUsername(opts)).rejects.toThrow( - "Authentication error. Use `npm whoami` to troubleshoot." - ); - expect(console.error).toHaveBeenCalledWith("third-party whoami fail"); - }); - - test("logs failure message when npm returns forbidden response", async () => { - fetch.json.mockImplementationOnce(() => { - const err = new Error("npm profile fail due to insufficient permissions"); - - err.code = "E403"; - - return Promise.reject(err); - }); - - const opts = { registry: "https://registry.npmjs.org/" }; - - await expect(getNpmUsername(opts)).rejects.toThrow( - "Access verification failed. Ensure that your npm access token has both read and write access, or remove the verifyAccess option to skip this verification. Note that npm automation tokens do NOT have read access (https://docs.npmjs.com/creating-and-viewing-access-tokens)." - ); - expect(console.error).toHaveBeenCalledWith("npm profile fail due to insufficient permissions"); - }); - - test("allows third-party registries to fail with a stern warning", async () => { - fetch.json.mockImplementationOnce(() => { - const err = new Error("many third-party registries do not support npm whoami"); - - err.code = "E401"; - - return Promise.reject(err); - }); - - const opts = { registry: "http://my-own-private-idaho.com" }; - - const username = await getNpmUsername(opts); - - expect(username).toBeUndefined(); - expect(loggingOutput("warn")).toContain( - "Unable to determine npm username from third-party registry, this command will likely fail soon!" - ); - }); -}); diff --git a/commands/publish/__tests__/get-packages-without-license.test.js b/commands/publish/__tests__/get-packages-without-license.test.js deleted file mode 100644 index 03dec74700..0000000000 --- a/commands/publish/__tests__/get-packages-without-license.test.js +++ /dev/null @@ -1,15 +0,0 @@ -"use strict"; - -const { Project } = require("@lerna/project"); -const initFixture = require("@lerna-test/helpers").initFixtureFactory(__dirname); -const { getPackagesWithoutLicense } = require("../lib/get-packages-without-license"); - -test("getPackagesWithoutLicense", async () => { - const cwd = await initFixture("licenses"); - const project = new Project(cwd); - - const [pkg1, pkg2] = await project.getPackages(); - const packagesToBeLicensed = await getPackagesWithoutLicense(project, [pkg1, pkg2]); - - expect(packagesToBeLicensed).toEqual([pkg1]); -}); diff --git a/commands/publish/__tests__/get-two-factor-auth-required.test.js b/commands/publish/__tests__/get-two-factor-auth-required.test.js deleted file mode 100644 index 6727dbf911..0000000000 --- a/commands/publish/__tests__/get-two-factor-auth-required.test.js +++ /dev/null @@ -1,102 +0,0 @@ -"use strict"; - -jest.mock("../lib/get-profile-data"); - -const { loggingOutput } = require("@lerna-test/helpers/logging-output"); -const { getProfileData } = require("../lib/get-profile-data"); -const { getTwoFactorAuthRequired } = require("../lib/get-two-factor-auth-required"); - -getProfileData.mockImplementation(() => Promise.resolve({ tfa: {} })); - -describe("getTwoFactorAuthRequired", () => { - const origConsoleError = console.error; - - beforeEach(() => { - console.error = jest.fn(); - }); - - afterEach(() => { - console.error = origConsoleError; - }); - - it("resolves true if tfa.mode === 'auth-and-writes'", async () => { - getProfileData.mockResolvedValueOnce({ - tfa: { - mode: "auth-and-writes", - }, - }); - - const result = await getTwoFactorAuthRequired(); - expect(result).toBe(true); - expect(getProfileData).toHaveBeenLastCalledWith(expect.objectContaining({ fetchRetries: 0 })); - }); - - it("resolves false if tfa.mode !== 'auth-and-writes'", async () => { - getProfileData.mockResolvedValueOnce({ - tfa: { - mode: "auth-only", - }, - }); - - const result = await getTwoFactorAuthRequired(); - expect(result).toBe(false); - }); - - it("resolves false if tfa.pending === true", async () => { - getProfileData.mockResolvedValueOnce({ - tfa: { - pending: true, - mode: "ignored", - }, - }); - - const result = await getTwoFactorAuthRequired(); - expect(result).toBe(false); - }); - - it("resolves false after profile 404", async () => { - getProfileData.mockImplementationOnce(() => { - const err = new Error("third-party profile fail"); - - err.code = "E404"; - - return Promise.reject(err); - }); - - const result = await getTwoFactorAuthRequired(); - - expect(result).toBe(false); - expect(console.error).not.toHaveBeenCalled(); - }); - - it("resolves false after profile 500", async () => { - getProfileData.mockImplementationOnce(() => { - const err = new Error("legacy npm Enterprise profile fail"); - - err.code = "E500"; - - return Promise.reject(err); - }); - - const opts = { registry: "such-registry-wow" }; - const result = await getTwoFactorAuthRequired(opts); - - expect(result).toBe(false); - expect(loggingOutput("warn")).toContain( - `Registry "${opts.registry}" does not support 'npm profile get', skipping two-factor auth check...` - ); - }); - - it("logs unexpected failure message before throwing validation error", async () => { - getProfileData.mockImplementationOnce(() => { - const err = new Error("zomg explosions"); - - err.code = "E401"; - - return Promise.reject(err); - }); - - await expect(getTwoFactorAuthRequired()).rejects.toThrow("Unable to obtain two-factor auth mode"); - expect(console.error).toHaveBeenCalledWith("zomg explosions"); - }); -}); diff --git a/commands/publish/__tests__/get-unpublished-packages.test.js b/commands/publish/__tests__/get-unpublished-packages.test.js deleted file mode 100644 index 2122b086a3..0000000000 --- a/commands/publish/__tests__/get-unpublished-packages.test.js +++ /dev/null @@ -1,92 +0,0 @@ -"use strict"; - -jest.mock("pacote"); - -// mocked module(s) -const pacote = require("pacote"); - -// helpers -const { PackageGraph } = require("@lerna/package-graph"); -const { getPackages } = require("@lerna/project"); -const initFixture = require("@lerna-test/helpers").initFixtureFactory(__dirname); - -// file under test -const { getUnpublishedPackages } = require("../lib/get-unpublished-packages"); - -pacote.packument.mockImplementation(async (pkg) => { - if (pkg === "package-1") { - return { - versions: {}, - }; - } - - if (pkg === "package-2") { - return { - versions: { - "1.0.0": {}, - }, - }; - } - - throw new Error("package does not exist"); -}); - -test("getUnpublishedPackages", async () => { - const cwd = await initFixture("licenses-names"); - const packages = await getPackages(cwd); - const packageGraph = new PackageGraph(packages); - - const opts = {}; - const pkgs = await getUnpublishedPackages(packageGraph, opts); - - expect(pacote.packument).toHaveBeenCalledWith("package-1", opts); - expect(pkgs).toMatchInlineSnapshot(` -Array [ - PackageGraphNode { - "externalDependencies": Map {}, - "localDependencies": Map {}, - "localDependents": Map {}, - "name": "package-1", - }, - PackageGraphNode { - "externalDependencies": Map {}, - "localDependencies": Map {}, - "localDependents": Map {}, - "name": "package-3", - }, - PackageGraphNode { - "externalDependencies": Map {}, - "localDependencies": Map {}, - "localDependents": Map {}, - "name": "package-4", - }, - PackageGraphNode { - "externalDependencies": Map {}, - "localDependencies": Map {}, - "localDependents": Map {}, - "name": "package-5", - }, -] -`); -}); - -test("getUnpublishedPackages with private package", async () => { - const cwd = await initFixture("public-private"); - const packages = await getPackages(cwd); - const packageGraph = new PackageGraph(packages); - - const opts = {}; - const pkgs = await getUnpublishedPackages(packageGraph, opts); - - expect(pacote.packument).toHaveBeenCalledWith("package-1", opts); - expect(pkgs).toMatchInlineSnapshot(` -Array [ - PackageGraphNode { - "externalDependencies": Map {}, - "localDependencies": Map {}, - "localDependents": Map {}, - "name": "package-1", - }, -] -`); -}); diff --git a/commands/publish/__tests__/git-checkout.test.js b/commands/publish/__tests__/git-checkout.test.js deleted file mode 100644 index f265cc128a..0000000000 --- a/commands/publish/__tests__/git-checkout.test.js +++ /dev/null @@ -1,34 +0,0 @@ -"use strict"; - -const execa = require("execa"); -const fs = require("fs-extra"); -const path = require("path"); -const initFixture = require("@lerna-test/helpers").initFixtureFactory(__dirname); -const { gitCheckout } = require("../lib/git-checkout"); - -test("gitCheckout files", async () => { - const cwd = await initFixture("no-interdependencies"); - const files = ["package-1", "package-2"].map((name) => path.join("packages", name, "package.json")); - - await Promise.all(files.map((fp) => fs.writeJSON(path.join(cwd, fp), { foo: "bar" }))); - await gitCheckout(files, { granularPathspec: true }, { cwd }); - - const { stdout: modified } = await execa("git", ["ls-files", "--modified"], { cwd }); - expect(modified).toBe(""); -}); - -test("gitCheckout files with .gitignored files", async () => { - const cwd = await initFixture("no-interdependencies"); - const files = ["package-1", "package-2", "package-3"].map((name) => - path.join("packages", name, "package.json") - ); - - // simulate a "dynamic", intentionally unversioned package by gitignoring it - await fs.writeFile(path.join(cwd, ".gitignore"), "packages/package-3/*", "utf8"); - - await Promise.all(files.map((fp) => fs.outputJSON(path.join(cwd, fp), { foo: "bar" }))); - await gitCheckout(files, { granularPathspec: false }, { cwd }); - - const { stdout: modified } = await execa("git", ["ls-files", "--others"], { cwd }); - expect(modified).toBe("packages/package-3/package.json"); -}); diff --git a/commands/publish/__tests__/publish-canary.test.js b/commands/publish/__tests__/publish-canary.test.js deleted file mode 100644 index e99ee0499f..0000000000 --- a/commands/publish/__tests__/publish-canary.test.js +++ /dev/null @@ -1,443 +0,0 @@ -"use strict"; - -// we're actually testing integration with git -jest.unmock("@lerna/collect-updates"); - -// local modules _must_ be explicitly mocked -jest.mock("../lib/get-packages-without-license"); -jest.mock("../lib/verify-npm-package-access"); -jest.mock("../lib/get-npm-username"); -jest.mock("../lib/get-two-factor-auth-required"); - -const fs = require("fs-extra"); -const path = require("path"); -const childProcess = require("@lerna/child-process"); - -// mocked modules -const writePkg = require("write-pkg"); -const { npmPublish } = require("@lerna/npm-publish"); -const { promptConfirmation } = require("@lerna/prompt"); -const { throwIfUncommitted } = require("@lerna/check-working-tree"); - -// helpers -const initFixture = require("@lerna-test/helpers").initFixtureFactory(__dirname); -const { gitAdd } = require("@lerna-test/helpers"); -const { gitTag } = require("@lerna-test/helpers"); -const { gitCommit } = require("@lerna-test/helpers"); -const { loggingOutput } = require("@lerna-test/helpers/logging-output"); - -// test command -const lernaPublish = require("@lerna-test/helpers").commandRunner(require("../command")); - -// stabilize commit SHA -expect.addSnapshotSerializer(require("@lerna-test/helpers/serializers/serialize-git-sha")); - -async function initTaggedFixture(fixtureName, tagVersionPrefix = "v") { - const cwd = await initFixture(fixtureName); - - if (fixtureName.indexOf("independent") > -1) { - await Promise.all([ - gitTag(cwd, "package-1@1.0.0"), - gitTag(cwd, "package-2@2.0.0"), - gitTag(cwd, "package-3@3.0.0"), - gitTag(cwd, "package-4@4.0.0"), - gitTag(cwd, "package-5@5.0.0"), - ]); - } else { - await gitTag(cwd, `${tagVersionPrefix}1.0.0`); - } - - return cwd; -} - -/** - * ALL canary tests _require_ an actual commit _past_ the original tag, - * as a canary release on the same commit as a tagged release is non-sensical. - * - * @param {String} cwd Current working directory - * @param {Array[String]..} tuples Any number of [filePath, fileContent] configs - */ -async function setupChanges(cwd, ...tuples) { - await Promise.all( - tuples.map(([filePath, content]) => fs.outputFile(path.join(cwd, filePath), content, "utf8")) - ); - await gitAdd(cwd, "."); - await gitCommit(cwd, "setup"); -} - -test("publish --canary", async () => { - const cwd = await initTaggedFixture("normal"); - - await setupChanges( - cwd, - ["packages/package-1/all-your-base.js", "belong to us"], - ["packages/package-4/non-matching-semver.js", "senpai noticed me"] - ); - await lernaPublish(cwd)("--canary"); - - expect(promptConfirmation).toHaveBeenLastCalledWith("Are you sure you want to publish these packages?"); - expect(npmPublish.registry).toMatchInlineSnapshot(` -Map { - "package-1" => "canary", - "package-4" => "canary", - "package-2" => "canary", - "package-3" => "canary", -} -`); - expect(writePkg.updatedVersions()).toMatchInlineSnapshot(` -Object { - "package-1": 1.0.1-alpha.0+SHA, - "package-2": 1.0.1-alpha.0+SHA, - "package-3": 1.0.1-alpha.0+SHA, - "package-4": 1.0.1-alpha.0+SHA, -} -`); -}); - -test("publish --canary --preid beta", async () => { - const cwd = await initTaggedFixture("normal"); - - await setupChanges(cwd, ["packages/package-1/all-your-base.js", "belong to us"]); - await lernaPublish(cwd)("--canary", "--preid", "beta"); - - expect(writePkg.updatedVersions()).toMatchInlineSnapshot(` -Object { - "package-1": 1.0.1-beta.0+SHA, - "package-2": 1.0.1-beta.0+SHA, - "package-3": 1.0.1-beta.0+SHA, -} -`); -}); - -test("publish --canary --tag-version-prefix='abc'", async () => { - const cwd = await initTaggedFixture("normal", "abc"); - - await setupChanges(cwd, ["packages/package-1/all-your-base.js", "belong to us"]); - await lernaPublish(cwd)("--canary", "--tag-version-prefix", "abc"); - - expect(writePkg.updatedVersions()).toMatchInlineSnapshot(` -Object { - "package-1": 1.0.1-alpha.0+SHA, - "package-2": 1.0.1-alpha.0+SHA, - "package-3": 1.0.1-alpha.0+SHA, -} -`); -}); - -test("publish --canary ", async () => { - const cwd = await initTaggedFixture("normal"); - - await setupChanges(cwd, ["packages/package-1/all-your-base.js", "belong to us"]); - await lernaPublish(cwd)("--canary", "prerelease"); - // prerelease === prepatch, which is the default - - expect(writePkg.updatedVersions()).toMatchInlineSnapshot(` -Object { - "package-1": 1.0.1-alpha.0+SHA, - "package-2": 1.0.1-alpha.0+SHA, - "package-3": 1.0.1-alpha.0+SHA, -} -`); -}); - -test("publish --canary --independent", async () => { - const cwd = await initTaggedFixture("independent"); - - await setupChanges(cwd, ["packages/package-1/all-your-base.js", "belong to us"]); - await lernaPublish(cwd)("--canary", "preminor"); - - expect(writePkg.updatedVersions()).toMatchInlineSnapshot(` -Object { - "package-1": 1.1.0-alpha.0+SHA, - "package-2": 2.1.0-alpha.0+SHA, - "package-3": 3.1.0-alpha.0+SHA, -} -`); -}); - -test("publish --canary addresses unpublished package", async () => { - const cwd = await initTaggedFixture("independent"); - - await setupChanges( - cwd, - [ - "packages/package-6/package.json", - JSON.stringify({ - name: "package-6", - // npm init starts at 1.0.0, - // but an unpublished 1.0.0 should be 1.0.0-alpha.0, n'est-ce pas? - version: "0.1.0", - }), - ], - ["packages/package-6/new-kids.js", "on the block"] - ); - await lernaPublish(cwd)("--canary", "premajor"); - - // there have been two commits since the beginning of the repo - expect(writePkg.updatedVersions()).toMatchInlineSnapshot(` -Object { - "package-6": 1.0.0-alpha.1+SHA, -} -`); -}); - -describe("publish --canary differential", () => { - test("source", async () => { - const cwd = await initTaggedFixture("snake-graph"); - - await setupChanges(cwd, ["packages/package-1/all-your-base.js", "belong to us"]); - await lernaPublish(cwd)("--canary", "patch"); - - expect(writePkg.updatedVersions()).toMatchInlineSnapshot(` -Object { - "package-1": 1.0.1-alpha.0+SHA, - "package-2": 1.0.1-alpha.0+SHA, - "package-3": 1.0.1-alpha.0+SHA, - "package-4": 1.0.1-alpha.0+SHA, - "package-5": 1.0.1-alpha.0+SHA, -} -`); - }); - - test("internal", async () => { - const cwd = await initTaggedFixture("snake-graph"); - - await setupChanges(cwd, ["packages/package-3/malcolm.js", "in the middle"]); - await lernaPublish(cwd)("--canary", "minor"); - - expect(writePkg.updatedVersions()).toMatchInlineSnapshot(` -Object { - "package-3": 1.1.0-alpha.0+SHA, - "package-4": 1.1.0-alpha.0+SHA, - "package-5": 1.1.0-alpha.0+SHA, -} -`); - }); - - test("pendant", async () => { - const cwd = await initTaggedFixture("snake-graph"); - - await setupChanges(cwd, ["packages/package-5/celine-dion.js", "all by myself"]); - await lernaPublish(cwd)("--canary", "major"); - - expect(writePkg.updatedVersions()).toMatchInlineSnapshot(` -Object { - "package-5": 2.0.0-alpha.0+SHA, -} -`); - }); -}); - -describe("publish --canary sequential", () => { - let cwd; - - beforeAll(async () => { - cwd = await initTaggedFixture("snake-independent"); - }); - - test("1. pendant", async () => { - await setupChanges(cwd, ["packages/package-5/celine-dion.js", "all by myself"]); - await lernaPublish(cwd)("--canary"); - - expect(writePkg.updatedVersions()).toMatchInlineSnapshot(` -Object { - "package-5": 5.0.1-alpha.0+SHA, -} -`); - }); - - test("2. internal", async () => { - await setupChanges(cwd, ["packages/package-3/malcolm.js", "in the middle"]); - await lernaPublish(cwd)("--canary"); - - expect(writePkg.updatedVersions()).toMatchInlineSnapshot(` -Object { - "package-3": 3.0.1-alpha.1+SHA, - "package-4": 4.0.1-alpha.1+SHA, - "package-5": 5.0.1-alpha.1+SHA, -} -`); - }); - - test("3. source", async () => { - await setupChanges(cwd, ["packages/package-1/all-your-base.js", "belong to us"]); - await lernaPublish(cwd)("--canary"); - - expect(writePkg.updatedVersions()).toMatchInlineSnapshot(` -Object { - "package-1": 1.0.1-alpha.2+SHA, - "package-2": 2.0.1-alpha.2+SHA, - "package-3": 3.0.1-alpha.2+SHA, - "package-4": 4.0.1-alpha.2+SHA, - "package-5": 5.0.1-alpha.2+SHA, -} -`); - }); - - test("4. internal", async () => { - await setupChanges(cwd, ["packages/package-3/malcolm.js", "tucker"]); - await lernaPublish(cwd)("--canary"); - - expect(writePkg.updatedVersions()).toMatchInlineSnapshot(` -Object { - "package-3": 3.0.1-alpha.3+SHA, - "package-4": 4.0.1-alpha.3+SHA, - "package-5": 5.0.1-alpha.3+SHA, -} -`); - }); - - test("5. pendant", async () => { - await setupChanges(cwd, ["packages/package-5/celine-dion.js", "my heart will go on"]); - await lernaPublish(cwd)("--canary"); - - expect(writePkg.updatedVersions()).toMatchInlineSnapshot(` -Object { - "package-5": 5.0.1-alpha.4+SHA, -} -`); - }); -}); - -test("publish --canary on tagged release exits early", async () => { - const cwd = await initTaggedFixture("normal"); - - await lernaPublish(cwd)("--canary"); - - const logMessages = loggingOutput("success"); - expect(logMessages).toContain("Current HEAD is already released, skipping change detection."); - expect(logMessages).toContain("No changed packages to publish"); -}); - -test("publish --canary --force-publish on tagged release avoids early exit", async () => { - const cwd = await initTaggedFixture("normal"); - - await lernaPublish(cwd)("--canary", "--force-publish"); - - const logMessages = loggingOutput("warn"); - expect(logMessages).toContain("all packages"); - // lerna WARN force-publish all packages - - expect(writePkg.updatedVersions()).toMatchInlineSnapshot(` -Object { - "package-1": 1.0.1-alpha.0+SHA, - "package-2": 1.0.1-alpha.0+SHA, - "package-3": 1.0.1-alpha.0+SHA, - "package-4": 1.0.1-alpha.0+SHA, -} -`); -}); - -test("publish --canary --force-publish on tagged release avoids early exit", async () => { - const cwd = await initTaggedFixture("independent"); - - // canary committish needs to have a parent, but still tagged on same revision - await setupChanges(cwd, ["packages/package-5/arbitrary.js", "change"]); - await gitTag(cwd, "package-5@5.0.1"); - - // there are no _actual_ changes to package-2 or any of its dependencies - await lernaPublish(cwd)("--canary", "--force-publish", "package-2"); - - const logMessages = loggingOutput("warn"); - expect(logMessages).toContain("package-2"); - // lerna WARN force-publish package-2 - - expect(writePkg.updatedVersions()).toMatchInlineSnapshot(` -Object { - "package-2": 2.0.1-alpha.0+SHA, - "package-3": 3.0.1-alpha.0+SHA, -} -`); -}); - -test("publish --canary with dirty tree throws error", async () => { - throwIfUncommitted.mockImplementationOnce(() => { - throw new Error("uncommitted"); - }); - - const cwd = await initTaggedFixture("normal"); - const command = lernaPublish(cwd)("--canary"); - - await expect(command).rejects.toThrow("uncommitted"); - // notably different than the actual message, but good enough here -}); - -test("publish --canary --git-head throws an error", async () => { - const cwd = await initFixture("normal"); - const command = lernaPublish(cwd)("--canary", "--git-head", "deadbeef"); - - await expect(command).rejects.toThrow( - expect.objectContaining({ - prefix: "EGITHEAD", - }) - ); -}); - -test("publish --canary --include-merged-tags calls git describe correctly", async () => { - const spy = jest.spyOn(childProcess, "exec"); - const cwd = await initTaggedFixture("normal"); - - await lernaPublish(cwd)("--canary", "--include-merged-tags"); - - expect(spy).toHaveBeenCalledWith( - "git", - // notably lacking "--first-parent" - ["describe", "--always", "--long", "--dirty", "--match", "v*.*.*"], - expect.objectContaining({ cwd }) - ); -}); - -test("publish --canary without _any_ tags", async () => { - const cwd = await initFixture("normal"); - await lernaPublish(cwd)("--canary"); - - expect(writePkg.updatedVersions()).toMatchInlineSnapshot(` - Object { - "package-1": 1.0.1-alpha.0+SHA, - "package-2": 1.0.1-alpha.0+SHA, - "package-3": 1.0.1-alpha.0+SHA, - "package-4": 1.0.1-alpha.0+SHA, - } - `); -}); - -test("publish --canary without _any_ tags (independent)", async () => { - const cwd = await initFixture("independent"); - await lernaPublish(cwd)("--canary"); - - expect(writePkg.updatedVersions()).toMatchInlineSnapshot(` - Object { - "package-1": 1.0.1-alpha.0+SHA, - "package-2": 2.0.1-alpha.0+SHA, - "package-3": 3.0.1-alpha.0+SHA, - "package-4": 4.0.1-alpha.0+SHA, - } - `); -}); - -test("publish --canary --no-private", async () => { - // mostly to say, "yay you didn't explode!" - // publish always skips private packages already - const cwd = await initTaggedFixture("independent"); - await setupChanges( - cwd, - ["packages/package-1/all-your-base.js", "belong to us"], - [ - "packages/package-3/package.json", - JSON.stringify({ - name: "package-3", - version: "3.0.0", - private: true, - }), - ] - ); - - await lernaPublish(cwd)("--canary", "--no-private"); - - expect(writePkg.updatedVersions()).toMatchInlineSnapshot(` - Object { - "package-1": 1.0.1-alpha.0+SHA, - "package-2": 2.0.1-alpha.0+SHA, - } - `); -}); diff --git a/commands/publish/__tests__/publish-command.test.js b/commands/publish/__tests__/publish-command.test.js deleted file mode 100644 index 372185edba..0000000000 --- a/commands/publish/__tests__/publish-command.test.js +++ /dev/null @@ -1,600 +0,0 @@ -"use strict"; - -jest.mock("@lerna/otplease"); - -// local modules _must_ be explicitly mocked -jest.mock("../lib/get-packages-without-license"); -jest.mock("../lib/verify-npm-package-access"); -jest.mock("../lib/get-npm-username"); -jest.mock("../lib/get-two-factor-auth-required"); -jest.mock("../lib/get-unpublished-packages"); -jest.mock("../lib/git-checkout"); -// FIXME: better mock for version command -jest.mock("../../version/lib/git-push"); -jest.mock("../../version/lib/is-anything-committed"); -jest.mock("../../version/lib/is-behind-upstream"); -jest.mock("../../version/lib/remote-branch-exists"); - -// mocked or stubbed modules -const { getOneTimePassword } = require("@lerna/otplease"); -const npmDistTag = require("@lerna/npm-dist-tag"); -const { npmPublish } = require("@lerna/npm-publish"); -const { packDirectory } = require("@lerna/pack-directory"); -const { promptConfirmation } = require("@lerna/prompt"); -const { collectUpdates } = require("@lerna/collect-updates"); -const { getNpmUsername } = require("../lib/get-npm-username"); -const { verifyNpmPackageAccess } = require("../lib/verify-npm-package-access"); -const { getTwoFactorAuthRequired } = require("../lib/get-two-factor-auth-required"); -const { gitCheckout } = require("../lib/git-checkout"); - -// helpers -const { commitChangeToPackage } = require("@lerna-test/helpers"); -const { loggingOutput } = require("@lerna-test/helpers/logging-output"); -const initFixture = require("@lerna-test/helpers").initFixtureFactory(__dirname); -const path = require("path"); -const fs = require("fs-extra"); - -const fsmain = require("fs"); - -// file under test -const lernaPublish = require("@lerna-test/helpers").commandRunner(require("../command")); - -gitCheckout.mockImplementation(() => Promise.resolve()); - -describe("PublishCommand", () => { - describe("cli validation", () => { - let cwd; - - beforeAll(async () => { - cwd = await initFixture("normal"); - }); - - it("exits early when no changes found", async () => { - collectUpdates.setUpdated(cwd); - - await lernaPublish(cwd)(); - - const logMessages = loggingOutput("success"); - expect(logMessages).toContain("No changed packages to publish"); - expect(verifyNpmPackageAccess).not.toHaveBeenCalled(); - }); - - it("exits non-zero with --scope", async () => { - const command = lernaPublish(cwd)("--scope", "package-1"); - - await expect(command).rejects.toThrow( - expect.objectContaining({ - exitCode: 1, - message: "Unknown argument: scope", - }) - ); - }); - - it("exits non-zero with --since", async () => { - const command = lernaPublish(cwd)("--since", "main"); - - await expect(command).rejects.toThrow( - expect.objectContaining({ - exitCode: 1, - message: "Unknown argument: since", - }) - ); - }); - - it("errors when --git-head is passed without from-package positional", async () => { - const command = lernaPublish(cwd)("--git-head", "deadbeef"); - - await expect(command).rejects.toThrow( - expect.objectContaining({ - name: "ValidationError", - message: "--git-head is only allowed with 'from-package' positional", - }) - ); - }); - }); - - describe("with implied versioning", () => { - it("publishes changed packages", async () => { - const testDir = await initFixture("normal"); - - await lernaPublish(testDir)(); - - expect(promptConfirmation).toHaveBeenLastCalledWith("Are you sure you want to publish these packages?"); - expect(packDirectory.registry).toMatchInlineSnapshot(` -Set { - "package-1", - "package-4", - "package-2", - "package-3", -} -`); - expect(npmPublish.registry).toMatchInlineSnapshot(` -Map { - "package-1" => "latest", - "package-4" => "latest", - "package-2" => "latest", - "package-3" => "latest", -} -`); - expect(npmPublish.order()).toEqual([ - "package-1", - "package-4", - "package-2", - "package-3", - // package-5 is private - ]); - expect(npmDistTag.remove).not.toHaveBeenCalled(); - expect(npmDistTag.add).not.toHaveBeenCalled(); - - expect(getNpmUsername).not.toHaveBeenCalled(); - expect(verifyNpmPackageAccess).not.toHaveBeenCalled(); - - expect(gitCheckout).toHaveBeenCalledWith( - // the list of changed files has been asserted many times already - expect.any(Array), - { granularPathspec: true }, - { cwd: testDir } - ); - }); - - it("publishes changed independent packages", async () => { - const testDir = await initFixture("independent"); - - await lernaPublish(testDir)(); - - expect(npmPublish.order()).toEqual([ - "package-1", - "package-4", - "package-2", - "package-3", - // package-5 is private - ]); - }); - - it("--skip-npm yields immediately to VersionCommand with warning", async () => { - const cwd = await initFixture("normal"); - - await lernaPublish(cwd)("--skip-npm"); - - expect(npmPublish.order()).toHaveLength(0); - - const logMessages = loggingOutput("warn"); - expect(logMessages).toContain("Instead of --skip-npm, call `lerna version` directly"); - }); - - it("throws an error in fixed mode when --independent is passed", async () => { - const testDir = await initFixture("normal"); - const command = lernaPublish(testDir)("--independent"); - - await expect(command).rejects.toThrow("independent"); - }); - }); - - describe("--graph-type", () => { - it("produces a topological ordering that _includes_ devDependencies when value is not set", async () => { - const cwd = await initFixture("normal"); - - await lernaPublish(cwd)(); - - expect(npmPublish.order()).toEqual([ - "package-1", - "package-4", - "package-2", - // package-3 has a peer/devDependency on package-2 - "package-3", - // package-5 is private - ]); - }); - - it("produces a topological ordering that _includes_ devDependencies when value is 'all'", async () => { - const cwd = await initFixture("normal"); - - await lernaPublish(cwd)("--graph-type", "all"); - - expect(npmPublish.order()).toEqual([ - "package-1", - "package-4", - "package-2", - // package-3 has a peer/devDependency on package-2 - "package-3", - // package-5 is private - ]); - }); - - it("produces a topological ordering that _excludes_ devDependencies when value is 'dependencies' (DEPRECATED)", async () => { - const cwd = await initFixture("normal"); - - await lernaPublish(cwd)("--graph-type", "dependencies"); - - expect(npmPublish.order()).toEqual([ - "package-1", - // package-3 has a peer/devDependency on package-2 - "package-3", - "package-4", - "package-2", - // package-5 is private - ]); - - const logMessages = loggingOutput("warn"); - expect(logMessages).toMatchInlineSnapshot(` - Array [ - "--graph-type=dependencies is deprecated and will be removed in lerna v6. If you have a use-case you feel requires it please open an issue to discuss: https://github.com/lerna/lerna/issues/new/choose", - ] - `); - }); - - it("throws an error when value is _not_ 'all' or 'dependencies'", async () => { - const testDir = await initFixture("normal"); - const command = lernaPublish(testDir)("--graph-type", "poopy-pants"); - - await expect(command).rejects.toThrow("poopy-pants"); - }); - }); - - describe("--no-sort", () => { - it("produces a lexical ordering when --no-sort is set", async () => { - const cwd = await initFixture("normal"); - - await lernaPublish(cwd)("--no-sort"); - - expect(npmPublish.order()).toEqual([ - "package-1", - "package-2", - "package-3", - "package-4", - // package-5 is private - ]); - }); - }); - - describe("--otp", () => { - getOneTimePassword.mockImplementation(() => Promise.resolve("654321")); - - it("passes one-time password to npm commands", async () => { - const testDir = await initFixture("normal"); - const otp = "123456"; - - // cli option skips prompt - getTwoFactorAuthRequired.mockResolvedValueOnce(true); - - await lernaPublish(testDir)("--otp", otp); - - expect(npmPublish).toHaveBeenCalledWith( - expect.objectContaining({ name: "package-1" }), - "/TEMP_DIR/package-1-MOCKED.tgz", - expect.objectContaining({ otp }), - expect.objectContaining({ otp }) - ); - expect(getOneTimePassword).not.toHaveBeenCalled(); - }); - - it("prompts for OTP when option missing, account-level 2FA enabled, and verify access is true", async () => { - const testDir = await initFixture("normal"); - - getTwoFactorAuthRequired.mockResolvedValueOnce(true); - - await lernaPublish(testDir)("--verify-access", true); - - expect(npmPublish).toHaveBeenCalledWith( - expect.objectContaining({ name: "package-1" }), - "/TEMP_DIR/package-1-MOCKED.tgz", - expect.objectContaining({ otp: undefined }), - expect.objectContaining({ otp: "654321" }) - ); - expect(getOneTimePassword).toHaveBeenLastCalledWith("Enter OTP:"); - }); - - it("defers OTP prompt when option missing, account-level 2FA enabled, and verify access is not true", async () => { - const testDir = await initFixture("normal"); - - getTwoFactorAuthRequired.mockResolvedValueOnce(true); - - await lernaPublish(testDir)(); - - expect(npmPublish).toHaveBeenCalledWith( - expect.objectContaining({ name: "package-1" }), - "/TEMP_DIR/package-1-MOCKED.tgz", - expect.objectContaining({ otp: undefined }), - expect.objectContaining({ otp: undefined }) - ); - expect(getOneTimePassword).not.toHaveBeenCalled(); - }); - }); - - describe("--legacy-auth", () => { - it("passes auth to npm commands", async () => { - const testDir = await initFixture("normal"); - const data = "hi:mom"; - const auth = Buffer.from(data).toString("base64"); - - await lernaPublish(testDir)("--legacy-auth", auth); - - expect(npmPublish).toHaveBeenCalledWith( - expect.objectContaining({ name: "package-1" }), - "/TEMP_DIR/package-1-MOCKED.tgz", - expect.objectContaining({ "auth-type": "legacy", _auth: auth }), - expect.objectContaining({ otp: undefined }) - ); - }); - }); - - describe("--registry", () => { - it("passes registry to npm commands", async () => { - const testDir = await initFixture("normal"); - const registry = "https://my-private-registry"; - - await lernaPublish(testDir)("--registry", registry); - - expect(npmPublish).toHaveBeenCalledWith( - expect.objectContaining({ name: "package-1" }), - "/TEMP_DIR/package-1-MOCKED.tgz", - expect.objectContaining({ registry }), - expect.objectContaining({ otp: undefined }) - ); - }); - - it("overwrites yarn registry proxy with https://registry.npmjs.org/", async () => { - const testDir = await initFixture("normal"); - const registry = "https://registry.yarnpkg.com"; - - await lernaPublish(testDir)("--registry", registry); - - expect(npmPublish).toHaveBeenCalledWith( - expect.objectContaining({ name: "package-1" }), - "/TEMP_DIR/package-1-MOCKED.tgz", - expect.objectContaining({ registry: "https://registry.npmjs.org/" }), - expect.objectContaining({ otp: undefined }) - ); - - const logMessages = loggingOutput("warn"); - expect(logMessages).toContain("Yarn's registry proxy is broken, replacing with public npm registry"); - expect(logMessages).toContain("If you don't have an npm token, you should exit and run `npm login`"); - }); - - it("skips validation on any other third-party registry", async () => { - const testDir = await initFixture("normal"); - const registry = "https://my-incompatible-registry.com"; - - await lernaPublish(testDir)("--registry", registry); - - const logMessages = loggingOutput("notice"); - expect(logMessages).toContain("Skipping all user and access validation due to third-party registry"); - }); - }); - - describe("--summary-file", () => { - it("skips creating the summary file", async () => { - const cwd = await initFixture("normal"); - const fsSpy = jest.spyOn(fs, "writeFileSync"); - await lernaPublish(cwd); - - expect(fsSpy).not.toHaveBeenCalled(); - }); - - it("creates the summary file within the provided directory", async () => { - const cwd = await initFixture("normal"); - const fsSpy = jest.spyOn(fsmain, "writeFileSync"); - await lernaPublish(cwd)("--summary-file", "./outputs"); - - const expectedJsonResponse = [ - { packageName: "package-1", version: "1.0.1" }, - { packageName: "package-2", version: "1.0.1" }, - { packageName: "package-3", version: "1.0.1" }, - { packageName: "package-4", version: "1.0.1" }, - ]; - expect(fsSpy).toHaveBeenCalled(); - expect(fsSpy).toHaveBeenCalledWith( - "./outputs/lerna-publish-summary.json", - JSON.stringify(expectedJsonResponse) - ); - }); - - it("creates the summary file at the root when no custom directory is provided", async () => { - const cwd = await initFixture("normal"); - const fsSpy = jest.spyOn(fsmain, "writeFileSync"); - await lernaPublish(cwd)("--summary-file"); - - const expectedJsonResponse = [ - { packageName: "package-1", version: "1.0.1" }, - { packageName: "package-2", version: "1.0.1" }, - { packageName: "package-3", version: "1.0.1" }, - { packageName: "package-4", version: "1.0.1" }, - ]; - expect(fsSpy).toHaveBeenCalled(); - expect(fsSpy).toHaveBeenCalledWith( - "./lerna-publish-summary.json", - JSON.stringify(expectedJsonResponse) - ); - }); - }); - describe("--verify-access", () => { - it("publishes packages after verifying the user's access to each package", async () => { - const testDir = await initFixture("normal"); - - await lernaPublish(testDir)("--verify-access"); - - expect(promptConfirmation).toHaveBeenLastCalledWith("Are you sure you want to publish these packages?"); - expect(packDirectory.registry).toMatchInlineSnapshot(` -Set { - "package-1", - "package-4", - "package-2", - "package-3", -} -`); - expect(npmPublish.registry).toMatchInlineSnapshot(` -Map { - "package-1" => "latest", - "package-4" => "latest", - "package-2" => "latest", - "package-3" => "latest", -} -`); - expect(npmPublish.order()).toEqual([ - "package-1", - "package-4", - "package-2", - "package-3", - // package-5 is private - ]); - expect(npmDistTag.remove).not.toHaveBeenCalled(); - expect(npmDistTag.add).not.toHaveBeenCalled(); - - expect(getNpmUsername).toHaveBeenCalled(); - expect(getNpmUsername).toHaveBeenLastCalledWith( - expect.objectContaining({ registry: "https://registry.npmjs.org/" }) - ); - - expect(verifyNpmPackageAccess).toHaveBeenCalled(); - expect(verifyNpmPackageAccess).toHaveBeenLastCalledWith( - expect.any(Array), - "lerna-test", - expect.objectContaining({ registry: "https://registry.npmjs.org/" }) - ); - - expect(getTwoFactorAuthRequired).toHaveBeenCalled(); - expect(getTwoFactorAuthRequired).toHaveBeenLastCalledWith(expect.objectContaining({ otp: undefined })); - - expect(gitCheckout).toHaveBeenCalledWith( - expect.any(Array), - { granularPathspec: true }, - { cwd: testDir } - ); - }); - }); - - describe("--no-verify-access", () => { - it("shows warning that this is the default behavior and that this option is no longer needed", async () => { - const cwd = await initFixture("normal"); - - await lernaPublish(cwd)("--no-verify-access"); - - const logMessages = loggingOutput("warn"); - expect(logMessages).toContain( - "--verify-access=false and --no-verify-access are no longer needed, because the legacy preemptive access verification is now disabled by default. Requests will fail with appropriate errors when not authorized correctly." - ); - }); - - it("skips package access verification", async () => { - const cwd = await initFixture("normal"); - - await lernaPublish(cwd)("--no-verify-access"); - - expect(verifyNpmPackageAccess).not.toHaveBeenCalled(); - }); - - it("is implied when npm username is undefined", async () => { - getNpmUsername.mockImplementationOnce(() => Promise.resolve()); - - const cwd = await initFixture("normal"); - - await lernaPublish(cwd)("--registry", "https://my-private-registry"); - - expect(verifyNpmPackageAccess).not.toHaveBeenCalled(); - }); - }); - - describe("--no-git-reset", () => { - it("skips git checkout of package manifests", async () => { - const cwd = await initFixture("normal"); - - await lernaPublish(cwd)("--no-git-reset"); - - expect(gitCheckout).not.toHaveBeenCalled(); - }); - }); - - // TODO: (major) make --no-granular-pathspec the default - describe("--no-granular-pathspec", () => { - it("resets staged changes globally", async () => { - const cwd = await initFixture("normal"); - - await lernaPublish(cwd)("--no-granular-pathspec"); - - expect(gitCheckout).toHaveBeenCalledWith( - // the list of changed files has been asserted many times already - expect.any(Array), - { granularPathspec: false }, - { cwd } - ); - }); - - it("consumes configuration from lerna.json", async () => { - const cwd = await initFixture("normal"); - - await fs.outputJSON(path.join(cwd, "lerna.json"), { - version: "1.0.0", - granularPathspec: false, - }); - await lernaPublish(cwd)(); - - expect(gitCheckout).toHaveBeenCalledWith( - // the list of changed files has been asserted many times already - expect.any(Array), - { granularPathspec: false }, - { cwd } - ); - }); - }); - - describe("--contents", () => { - it("allows you to do fancy angular crap", async () => { - const cwd = await initFixture("lifecycle"); - - await lernaPublish(cwd)("--contents", "dist"); - - const [[pkgOne, dirOne, opts], [pkgTwo, dirTwo]] = packDirectory.mock.calls; - - // second argument to packDirectory() is the location, _not_ the contents - expect(dirOne).toBe(pkgOne.location); - expect(dirTwo).toBe(pkgTwo.location); - - expect(pkgOne.contents).toBe(path.join(pkgOne.location, "dist")); - expect(pkgTwo.contents).toBe(path.join(pkgTwo.location, "dist")); - - // opts is a snapshot of npm-conf instance - expect(packDirectory).toHaveBeenCalledWith(pkgOne, dirOne, opts); - expect(packDirectory).toHaveBeenCalledWith(pkgTwo, dirTwo, opts); - }); - }); - - describe("publishConfig.directory", () => { - it("mimics effect of --contents, but per-package", async () => { - const cwd = await initFixture("lifecycle"); - - await commitChangeToPackage(cwd, "package-1", "chore: setup", { - publishConfig: { - directory: "dist", - }, - }); - - await lernaPublish(cwd)(); - - expect(packDirectory).toHaveBeenCalledWith( - expect.objectContaining({ - name: "package-1", - contents: path.join(cwd, "packages/package-1/dist"), - }), - path.join(cwd, "packages/package-1"), - expect.any(Object) - ); - expect(packDirectory).toHaveBeenCalledWith( - expect.objectContaining({ - name: "package-2", - contents: path.join(cwd, "packages/package-2"), - }), - path.join(cwd, "packages/package-2"), - expect.any(Object) - ); - }); - }); - - describe("in a cyclical repo", () => { - it("should throw an error with --reject-cycles", async () => { - const testDir = await initFixture("toposort"); - const command = lernaPublish(testDir)("--reject-cycles"); - - await expect(command).rejects.toThrow("Dependency cycles detected, you should fix these!"); - }); - }); -}); diff --git a/commands/publish/__tests__/publish-from-git.test.js b/commands/publish/__tests__/publish-from-git.test.js deleted file mode 100644 index 5c068eb10b..0000000000 --- a/commands/publish/__tests__/publish-from-git.test.js +++ /dev/null @@ -1,152 +0,0 @@ -"use strict"; - -// we're actually testing integration with git -jest.unmock("@lerna/collect-updates"); - -// local modules _must_ be explicitly mocked -jest.mock("../lib/get-packages-without-license"); -jest.mock("../lib/verify-npm-package-access"); -jest.mock("../lib/get-npm-username"); -jest.mock("../lib/get-two-factor-auth-required"); -jest.mock("../lib/get-unpublished-packages"); -// FIXME: better mock for version command -jest.mock("../../version/lib/git-push"); -jest.mock("../../version/lib/is-anything-committed"); -jest.mock("../../version/lib/is-behind-upstream"); -jest.mock("../../version/lib/remote-branch-exists"); - -// mocked or stubbed modules -const { npmPublish } = require("@lerna/npm-publish"); -const { promptConfirmation } = require("@lerna/prompt"); -const { output } = require("@lerna/output"); -const { throwIfUncommitted } = require("@lerna/check-working-tree"); - -// helpers -const { loggingOutput } = require("@lerna-test/helpers/logging-output"); -const { gitTag } = require("@lerna-test/helpers"); -const initFixture = require("@lerna-test/helpers").initFixtureFactory(__dirname); - -// file under test -const lernaPublish = require("@lerna-test/helpers").commandRunner(require("../command")); - -describe("publish from-git", () => { - it("publishes tagged packages", async () => { - const cwd = await initFixture("normal"); - - await gitTag(cwd, "v1.0.0"); - await lernaPublish(cwd)("from-git"); - - // called from chained describeRef() - expect(throwIfUncommitted).toHaveBeenCalled(); - - expect(promptConfirmation).toHaveBeenLastCalledWith("Are you sure you want to publish these packages?"); - expect(output.logged()).toMatch("Found 4 packages to publish:"); - expect(npmPublish.order()).toEqual([ - "package-1", - "package-4", - "package-2", - "package-3", - // package-5 is private - ]); - }); - - it("publishes tagged packages, lexically sorted when --no-sort is present", async () => { - const cwd = await initFixture("normal"); - - await gitTag(cwd, "v1.0.0"); - await lernaPublish(cwd)("from-git", "--no-sort"); - - // called from chained describeRef() - expect(throwIfUncommitted).toHaveBeenCalled(); - - expect(promptConfirmation).toHaveBeenLastCalledWith("Are you sure you want to publish these packages?"); - expect(output.logged()).toMatch("Found 4 packages to publish:"); - expect(npmPublish.order()).toEqual([ - "package-1", - "package-2", - "package-3", - "package-4", - // package-5 is private - ]); - }); - - it("publishes tagged independent packages", async () => { - const cwd = await initFixture("independent"); - - await Promise.all([ - gitTag(cwd, "package-1@1.0.0"), - gitTag(cwd, "package-2@2.0.0"), - gitTag(cwd, "package-3@3.0.0"), - gitTag(cwd, "package-4@4.0.0"), - gitTag(cwd, "package-5@5.0.0"), - ]); - await lernaPublish(cwd)("from-git"); - - expect(npmPublish.order()).toEqual([ - "package-1", - "package-4", - "package-2", - "package-3", - // package-5 is private - ]); - }); - - it("publishes packages matching custom --tag-version-prefix", async () => { - const cwd = await initFixture("normal"); - - await gitTag(cwd, "foo/1.0.0"); - await lernaPublish(cwd)("from-git", "--tag-version-prefix", "foo/"); - - expect(npmPublish.order()).toEqual([ - "package-1", - "package-4", - "package-2", - "package-3", - // package-5 is private - ]); - }); - - it("only publishes independent packages with matching tags", async () => { - const cwd = await initFixture("independent"); - - await gitTag(cwd, "package-3@3.0.0"); - await lernaPublish(cwd)("from-git"); - - expect(output.logged()).toMatch("Found 1 package to publish:"); - expect(npmPublish.order()).toEqual(["package-3"]); - }); - - it("exits early when the current commit is not tagged", async () => { - const cwd = await initFixture("normal"); - - await lernaPublish(cwd)("from-git"); - - expect(npmPublish).not.toHaveBeenCalled(); - - const logMessages = loggingOutput("info"); - expect(logMessages).toContain("No tagged release found"); - }); - - it("throws an error when uncommitted changes are present", async () => { - throwIfUncommitted.mockImplementationOnce(() => { - throw new Error("uncommitted"); - }); - - const cwd = await initFixture("normal"); - const command = lernaPublish(cwd)("from-git"); - - await expect(command).rejects.toThrow("uncommitted"); - // notably different than the actual message, but good enough here - }); - - it("throws an error when --git-head is passed", async () => { - const cwd = await initFixture("normal"); - const command = lernaPublish(cwd)("from-git", "--git-head", "deadbeef"); - - await expect(command).rejects.toThrow( - expect.objectContaining({ - prefix: "EGITHEAD", - }) - ); - }); -}); diff --git a/commands/publish/__tests__/publish-from-package.test.js b/commands/publish/__tests__/publish-from-package.test.js deleted file mode 100644 index 5d12b6f6a0..0000000000 --- a/commands/publish/__tests__/publish-from-package.test.js +++ /dev/null @@ -1,134 +0,0 @@ -"use strict"; - -// local modules _must_ be explicitly mocked -jest.mock("../lib/get-packages-without-license"); -jest.mock("../lib/verify-npm-package-access"); -jest.mock("../lib/get-npm-username"); -jest.mock("../lib/get-two-factor-auth-required"); -jest.mock("../lib/get-unpublished-packages"); -// FIXME: better mock for version command -jest.mock("../../version/lib/git-push"); -jest.mock("../../version/lib/is-anything-committed"); -jest.mock("../../version/lib/is-behind-upstream"); -jest.mock("../../version/lib/remote-branch-exists"); - -const fs = require("fs-extra"); -const path = require("path"); - -// mocked or stubbed modules -const writePkg = require("write-pkg"); -const { npmPublish } = require("@lerna/npm-publish"); -const { promptConfirmation } = require("@lerna/prompt"); -const { output } = require("@lerna/output"); -const { throwIfUncommitted } = require("@lerna/check-working-tree"); -const { getUnpublishedPackages } = require("../lib/get-unpublished-packages"); - -// helpers -const { loggingOutput } = require("@lerna-test/helpers/logging-output"); -const initFixture = require("@lerna-test/helpers").initFixtureFactory(__dirname); - -// file under test -const lernaPublish = require("@lerna-test/helpers").commandRunner(require("../command")); - -describe("publish from-package", () => { - it("publishes unpublished packages", async () => { - const cwd = await initFixture("normal"); - - getUnpublishedPackages.mockImplementationOnce((packageGraph) => { - const pkgs = packageGraph.rawPackageList.slice(1, 3); - return pkgs.map((pkg) => packageGraph.get(pkg.name)); - }); - - await lernaPublish(cwd)("from-package"); - - expect(promptConfirmation).toHaveBeenLastCalledWith("Are you sure you want to publish these packages?"); - expect(output.logged()).toMatch("Found 2 packages to publish:"); - expect(npmPublish.order()).toEqual(["package-2", "package-3"]); - }); - - it("publishes unpublished independent packages", async () => { - const cwd = await initFixture("independent"); - - getUnpublishedPackages.mockImplementationOnce((packageGraph) => Array.from(packageGraph.values())); - - await lernaPublish(cwd)("from-package"); - - expect(npmPublish.order()).toEqual([ - "package-1", - "package-4", - "package-2", - "package-3", - // package-5 is private - ]); - }); - - it("publishes unpublished independent packages, lexically sorted when --no-sort is present", async () => { - const cwd = await initFixture("independent"); - - getUnpublishedPackages.mockImplementationOnce((packageGraph) => Array.from(packageGraph.values())); - - await lernaPublish(cwd)("from-package", "--no-sort"); - - expect(npmPublish.order()).toEqual([ - "package-1", - "package-2", - "package-3", - "package-4", - // package-5 is private - ]); - }); - - it("exits early when all packages are published", async () => { - const cwd = await initFixture("normal"); - - await lernaPublish(cwd)("from-package"); - - expect(npmPublish).not.toHaveBeenCalled(); - - const logMessages = loggingOutput("notice"); - expect(logMessages).toContain("No unpublished release found"); - }); - - it("throws an error when uncommitted changes are present", async () => { - throwIfUncommitted.mockImplementationOnce(() => { - throw new Error("uncommitted"); - }); - - const cwd = await initFixture("normal"); - const command = lernaPublish(cwd)("from-package"); - - await expect(command).rejects.toThrow("uncommitted"); - // notably different than the actual message, but good enough here - }); - - it("does not require a git repo", async () => { - getUnpublishedPackages.mockImplementationOnce((packageGraph) => [packageGraph.get("package-1")]); - - const cwd = await initFixture("independent"); - - // nuke the git repo first - await fs.remove(path.join(cwd, ".git")); - await lernaPublish(cwd)("from-package"); - - expect(npmPublish).toHaveBeenCalled(); - expect(writePkg.updatedManifest("package-1")).not.toHaveProperty("gitHead"); - - const logMessages = loggingOutput("notice"); - expect(logMessages).toContain("Unable to verify working tree, proceed at your own risk"); - expect(logMessages).toContain( - "Unable to set temporary gitHead property, it will be missing from registry metadata" - ); - expect(logMessages).toContain("Unable to reset working tree changes, this probably isn't a git repo."); - }); - - it("accepts --git-head override", async () => { - getUnpublishedPackages.mockImplementationOnce((packageGraph) => [packageGraph.get("package-1")]); - - const cwd = await initFixture("independent"); - - await lernaPublish(cwd)("from-package", "--git-head", "deadbeef"); - - expect(npmPublish).toHaveBeenCalled(); - expect(writePkg.updatedManifest("package-1").gitHead).toBe("deadbeef"); - }); -}); diff --git a/commands/publish/__tests__/publish-licenses.test.js b/commands/publish/__tests__/publish-licenses.test.js deleted file mode 100644 index 2715135387..0000000000 --- a/commands/publish/__tests__/publish-licenses.test.js +++ /dev/null @@ -1,102 +0,0 @@ -"use strict"; - -// local modules _must_ be explicitly mocked -jest.mock("../lib/verify-npm-package-access"); -jest.mock("../lib/get-npm-username"); -jest.mock("../lib/get-two-factor-auth-required"); -jest.mock("../lib/create-temp-licenses", () => ({ createTempLicenses: jest.fn(() => Promise.resolve()) })); -jest.mock("../lib/remove-temp-licenses", () => ({ removeTempLicenses: jest.fn(() => Promise.resolve()) })); -// FIXME: better mock for version command -jest.mock("../../version/lib/git-push"); -jest.mock("../../version/lib/is-anything-committed"); -jest.mock("../../version/lib/is-behind-upstream"); -jest.mock("../../version/lib/remote-branch-exists"); - -const fs = require("fs-extra"); -const path = require("path"); - -// mocked modules -const { packDirectory } = require("@lerna/pack-directory"); -const { createTempLicenses } = require("../lib/create-temp-licenses"); -const { removeTempLicenses } = require("../lib/remove-temp-licenses"); - -// helpers -const initFixture = require("@lerna-test/helpers").initFixtureFactory(__dirname); -const { loggingOutput } = require("@lerna-test/helpers/logging-output"); - -// test command -const lernaPublish = require("@lerna-test/helpers").commandRunner(require("../command")); - -describe("licenses", () => { - it("makes a temporary copy of the root license text if package has none", async () => { - const cwd = await initFixture("licenses"); - const packagesToBeLicensed = [expect.objectContaining({ name: "package-1" })]; - - await lernaPublish(cwd)(); - - expect(createTempLicenses).toHaveBeenLastCalledWith(path.join(cwd, "LICENSE"), packagesToBeLicensed); - expect(removeTempLicenses).toHaveBeenLastCalledWith(packagesToBeLicensed); - }); - - it("removes all temporary licenses on error", async () => { - packDirectory.mockImplementationOnce(() => Promise.reject(new Error("boom"))); - - const cwd = await initFixture("licenses"); - const command = lernaPublish(cwd)(); - - await expect(command).rejects.toThrow("boom"); - - expect(removeTempLicenses).toHaveBeenCalledTimes(1); - expect(removeTempLicenses).toHaveBeenLastCalledWith([expect.objectContaining({ name: "package-1" })]); - }); - - it("does not override original error when removal rejects", async () => { - packDirectory.mockImplementationOnce(() => Promise.reject(new Error("boom"))); - removeTempLicenses.mockImplementationOnce(() => Promise.reject(new Error("shaka-lakka"))); - - const cwd = await initFixture("licenses"); - const command = lernaPublish(cwd)(); - - await expect(command).rejects.toThrow("boom"); - }); - - it("warns when packages need a license and the root license file is missing", async () => { - const cwd = await initFixture("licenses-missing"); - - await lernaPublish(cwd)(); - - const [warning] = loggingOutput("warn"); - expect(warning).toMatchInlineSnapshot(` -"Packages package-1 and package-3 are missing a license. -One way to fix this is to add a LICENSE.md file to the root of this repository. -See https://choosealicense.com for additional guidance." -`); - - expect(createTempLicenses).toHaveBeenLastCalledWith(undefined, []); - expect(removeTempLicenses).toHaveBeenLastCalledWith([]); - }); - - it("warns when one package needs a license", async () => { - const cwd = await initFixture("licenses"); - - // remove root license so warning is triggered - await fs.remove(path.join(cwd, "LICENSE")); - - await lernaPublish(cwd)(); - - const [warning] = loggingOutput("warn"); - expect(warning).toMatch("Package package-1 is missing a license."); - }); - - it("warns when multiple packages need a license", async () => { - const cwd = await initFixture("licenses-missing"); - - // simulate _all_ packages missing a license - await fs.remove(path.join(cwd, "packages/package-2/LICENSE")); - - await lernaPublish(cwd)(); - - const [warning] = loggingOutput("warn"); - expect(warning).toMatch("Packages package-1, package-2, and package-3 are missing a license."); - }); -}); diff --git a/commands/publish/__tests__/publish-lifecycle-scripts.test.js b/commands/publish/__tests__/publish-lifecycle-scripts.test.js deleted file mode 100644 index 3ca4a8ffe6..0000000000 --- a/commands/publish/__tests__/publish-lifecycle-scripts.test.js +++ /dev/null @@ -1,160 +0,0 @@ -"use strict"; - -// local modules _must_ be explicitly mocked -jest.mock("../lib/get-packages-without-license"); -jest.mock("../lib/verify-npm-package-access"); -jest.mock("../lib/get-npm-username"); -jest.mock("../lib/get-two-factor-auth-required"); -// FIXME: better mock for version command -jest.mock("../../version/lib/git-push"); -jest.mock("../../version/lib/is-anything-committed"); -jest.mock("../../version/lib/is-behind-upstream"); -jest.mock("../../version/lib/remote-branch-exists"); - -// mocked modules -const { packDirectory } = require("@lerna/pack-directory"); -const { runLifecycle } = require("@lerna/run-lifecycle"); -const loadJsonFile = require("load-json-file"); - -// helpers -const initFixture = require("@lerna-test/helpers").initFixtureFactory(__dirname); -const path = require("path"); - -// test command -const lernaPublish = require("@lerna-test/helpers").commandRunner(require("../command")); - -describe("lifecycle scripts", () => { - const npmLifecycleEvent = process.env.npm_lifecycle_event; - - afterEach(() => { - process.env.npm_lifecycle_event = npmLifecycleEvent; - }); - - it("calls publish lifecycle scripts for root and packages", async () => { - const cwd = await initFixture("lifecycle"); - - await lernaPublish(cwd)(); - - ["prepare", "prepublishOnly", "prepack", "postpack", "postpublish"].forEach((script) => { - // "lifecycle" is the root manifest name - expect(runLifecycle).toHaveBeenCalledWith( - expect.objectContaining({ name: "lifecycle" }), - script, - expect.any(Object) - ); - }); - - // package-2 only has prepublish lifecycle - expect(packDirectory).toHaveBeenCalledWith( - expect.objectContaining({ name: "package-2" }), - path.join(cwd, "packages/package-2"), - expect.objectContaining({ - "ignore-prepublish": false, - "ignore-scripts": false, - }) - ); - - expect(runLifecycle.getOrderedCalls()).toEqual([ - // TODO: separate from VersionCommand details - ["lifecycle", "preversion"], - ["package-1", "preversion"], - ["package-1", "version"], - ["lifecycle", "version"], - ["package-1", "postversion"], - ["lifecycle", "postversion"], - // publish-specific - ["lifecycle", "prepublish"], - ["lifecycle", "prepare"], - ["lifecycle", "prepublishOnly"], - ["lifecycle", "prepack"], - ["lifecycle", "postpack"], - ["lifecycle", "postpublish"], - ]); - - expect(Array.from(loadJsonFile.registry.keys())).toStrictEqual([ - "/packages/package-1", - "/packages/package-2", - ]); - }); - - it("does not execute recursive root scripts", async () => { - const cwd = await initFixture("lifecycle"); - - process.env.npm_lifecycle_event = "prepublish"; - - await lernaPublish(cwd)(); - - expect(runLifecycle.getOrderedCalls()).toEqual([ - // TODO: separate from VersionCommand details - ["lifecycle", "preversion"], - ["package-1", "preversion"], - ["package-1", "version"], - ["lifecycle", "version"], - ["package-1", "postversion"], - ["lifecycle", "postversion"], - // publish-specific - ["lifecycle", "prepare"], - ["lifecycle", "prepublishOnly"], - ["lifecycle", "prepack"], - ["lifecycle", "postpack"], - ]); - }); - - it("does not duplicate rooted leaf scripts", async () => { - const cwd = await initFixture("lifecycle-rooted-leaf"); - - await lernaPublish(cwd)(); - - expect(runLifecycle.getOrderedCalls()).toEqual([ - // TODO: separate from VersionCommand details - ["package-1", "preversion"], - ["package-1", "version"], - ["lifecycle-rooted-leaf", "preversion"], - ["lifecycle-rooted-leaf", "version"], - ["lifecycle-rooted-leaf", "postversion"], - ["package-1", "postversion"], - // NO publish-specific root lifecycles should be duplicated - // (they are all run by pack-directory and npm-publish) - ]); - }); - - it("respects --ignore-prepublish", async () => { - const cwd = await initFixture("lifecycle"); - - await lernaPublish(cwd)("--ignore-prepublish"); - - expect(packDirectory).toHaveBeenCalledWith( - expect.objectContaining({ name: "package-2" }), - path.join(cwd, "packages/package-2"), - expect.objectContaining({ - "ignore-prepublish": true, - }) - ); - - // runLifecycle() is _called_ with "prepublish" for root, - // but it does not actually execute, and is tested elsewhere - }); - - it("respects --ignore-scripts", async () => { - const cwd = await initFixture("lifecycle"); - - await lernaPublish(cwd)("--ignore-scripts"); - - // despite all the scripts being passed to runLifecycle() (and implicitly, packDirectory()), - // none of them will actually execute as long as opts["ignore-scripts"] is provided - expect(runLifecycle).toHaveBeenCalledWith( - expect.objectContaining({ name: "lifecycle" }), - "prepare", - expect.objectContaining({ - "ignore-scripts": true, - }) - ); - expect(packDirectory).toHaveBeenCalledWith( - expect.objectContaining({ name: "package-2" }), - path.join(cwd, "packages/package-2"), - expect.objectContaining({ - "ignore-scripts": true, - }) - ); - }); -}); diff --git a/commands/publish/__tests__/publish-relative-file-specifiers.test.js b/commands/publish/__tests__/publish-relative-file-specifiers.test.js deleted file mode 100644 index 1c1cd2c6cd..0000000000 --- a/commands/publish/__tests__/publish-relative-file-specifiers.test.js +++ /dev/null @@ -1,124 +0,0 @@ -"use strict"; - -// we're actually testing integration with git -jest.unmock("@lerna/collect-updates"); - -// local modules _must_ be explicitly mocked -jest.mock("../lib/get-packages-without-license"); -jest.mock("../lib/verify-npm-package-access"); -jest.mock("../lib/get-npm-username"); -jest.mock("../lib/get-two-factor-auth-required"); -// FIXME: better mock for version command -jest.mock("../../version/lib/git-push"); -jest.mock("../../version/lib/is-anything-committed"); -jest.mock("../../version/lib/is-behind-upstream"); -jest.mock("../../version/lib/remote-branch-exists"); - -const fs = require("fs-extra"); -const path = require("path"); - -// mocked modules -const writePkg = require("write-pkg"); - -// helpers -const initFixture = require("@lerna-test/helpers").initFixtureFactory(__dirname); -const { gitAdd } = require("@lerna-test/helpers"); -const { gitTag } = require("@lerna-test/helpers"); -const { gitCommit } = require("@lerna-test/helpers"); - -// test command -const lernaPublish = require("@lerna-test/helpers").commandRunner(require("../command")); - -describe("relative 'file:' specifiers", () => { - const setupChanges = async (cwd, pkgRoot = "packages") => { - await fs.outputFile(path.join(cwd, `${pkgRoot}/package-1/hello.js`), "world"); - await gitAdd(cwd, "."); - await gitCommit(cwd, "setup"); - }; - - it("overwrites relative link with local version before npm publish but after git commit", async () => { - const cwd = await initFixture("relative-file-specs"); - - await gitTag(cwd, "v1.0.0"); - await setupChanges(cwd); - await lernaPublish(cwd)("major", "--yes"); - - expect(writePkg.updatedVersions()).toEqual({ - "package-1": "2.0.0", - "package-2": "2.0.0", - "package-3": "2.0.0", - "package-4": "2.0.0", - "package-5": "2.0.0", - "package-6": "2.0.0", - "package-7": "2.0.0", - }); - - // notably missing is package-1, which has no relative file: dependencies - expect(writePkg.updatedManifest("package-2").dependencies).toMatchObject({ - "package-1": "^2.0.0", - }); - expect(writePkg.updatedManifest("package-3").dependencies).toMatchObject({ - "package-2": "^2.0.0", - }); - expect(writePkg.updatedManifest("package-4").optionalDependencies).toMatchObject({ - "package-3": "^2.0.0", - }); - expect(writePkg.updatedManifest("package-5").dependencies).toMatchObject({ - "package-4": "^2.0.0", - // all fixed versions are bumped when major - "package-6": "^2.0.0", - }); - // private packages do not need local version resolution - expect(writePkg.updatedManifest("package-7").dependencies).toMatchObject({ - "package-1": "file:../package-1", - }); - }); - - it("falls back to existing relative version when it is not updated", async () => { - const cwd = await initFixture("relative-independent"); - - await gitTag(cwd, "package-1@1.0.0"); - await setupChanges(cwd); - await lernaPublish(cwd)("minor", "--yes"); - - expect(writePkg.updatedVersions()).toEqual({ - "package-1": "1.1.0", - "package-2": "2.1.0", - "package-3": "3.1.0", - "package-4": "4.1.0", - "package-5": "5.1.0", - }); - - // package-4 was updated, but package-6 was not - expect(writePkg.updatedManifest("package-5").dependencies).toMatchObject({ - "package-4": "^4.1.0", - "package-6": "^6.0.0", - }); - }); - - it("respects --exact", async () => { - const cwd = await initFixture("relative-independent"); - - await gitTag(cwd, "package-1@1.0.0"); - await setupChanges(cwd); - await lernaPublish(cwd)("patch", "--yes", "--exact"); - - // package-4 was updated, but package-6 was not - expect(writePkg.updatedManifest("package-5").dependencies).toMatchObject({ - "package-4": "4.0.1", - "package-6": "6.0.0", - }); - }); - - it("works around npm-incompatible link: specifiers", async () => { - const cwd = await initFixture("yarn-link-spec"); - - await gitTag(cwd, "v1.0.0"); - await setupChanges(cwd, "workspaces"); - await lernaPublish(cwd)("major", "--yes"); - - expect(writePkg.updatedManifest("package-2").dependencies).toMatchObject({ - "package-1": "^2.0.0", - }); - }); -}); diff --git a/commands/publish/__tests__/publish-tagging.test.js b/commands/publish/__tests__/publish-tagging.test.js deleted file mode 100644 index 96a0984f67..0000000000 --- a/commands/publish/__tests__/publish-tagging.test.js +++ /dev/null @@ -1,170 +0,0 @@ -"use strict"; - -// local modules _must_ be explicitly mocked -jest.mock("../lib/get-packages-without-license"); -jest.mock("../lib/verify-npm-package-access"); -jest.mock("../lib/get-npm-username"); -jest.mock("../lib/get-two-factor-auth-required"); -// FIXME: better mock for version command -jest.mock("../../version/lib/git-push"); -jest.mock("../../version/lib/is-anything-committed"); -jest.mock("../../version/lib/is-behind-upstream"); -jest.mock("../../version/lib/remote-branch-exists"); - -// mocked modules -const { collectUpdates } = require("@lerna/collect-updates"); -const npmDistTag = require("@lerna/npm-dist-tag"); -const { npmPublish } = require("@lerna/npm-publish"); - -// helpers -const initFixture = require("@lerna-test/helpers").initFixtureFactory(__dirname); - -// test command -const lernaPublish = require("@lerna-test/helpers").commandRunner(require("../command")); - -test("publish --dist-tag next", async () => { - const cwd = await initFixture("normal"); - - collectUpdates.setUpdated(cwd, "package-1"); - - await lernaPublish(cwd)("--dist-tag", "next"); - - expect(npmPublish.registry.get("package-1")).toBe("next"); - expect(npmDistTag.remove).not.toHaveBeenCalled(); -}); - -test("publish --dist-tag nightly --canary", async () => { - const cwd = await initFixture("normal"); - - collectUpdates.setUpdated(cwd, "package-2"); - - await lernaPublish(cwd)("--dist-tag", "nightly", "--canary"); - - expect(npmPublish.registry.get("package-2")).toBe("nightly"); - expect(npmDistTag.remove).not.toHaveBeenCalled(); -}); - -test("publish --npm-tag deprecated", async () => { - const cwd = await initFixture("normal"); - - collectUpdates.setUpdated(cwd, "package-3"); - - await lernaPublish(cwd)("--npm-tag", "deprecated"); - - expect(npmPublish.registry.get("package-3")).toBe("deprecated"); - expect(npmDistTag.remove).not.toHaveBeenCalled(); -}); - -test("publish --temp-tag", async () => { - const cwd = await initFixture("integration"); - - await lernaPublish(cwd)("--temp-tag"); - - expect(npmPublish.registry).toMatchInlineSnapshot(` -Map { - "@integration/package-1" => "lerna-temp", - "@integration/package-2" => "lerna-temp", -} -`); - - const conf = expect.objectContaining({ - tag: "latest", - }); - const cache = expect.objectContaining({ - otp: undefined, - }); - - expect(npmDistTag.remove).toHaveBeenCalledWith("@integration/package-1@1.0.1", "lerna-temp", conf, cache); - expect(npmDistTag.remove).toHaveBeenCalledWith("@integration/package-2@1.0.1", "lerna-temp", conf, cache); - - expect(npmDistTag.add).toHaveBeenCalledWith("@integration/package-1@1.0.1", "CUSTOM", conf, cache); // <-- - expect(npmDistTag.add).toHaveBeenCalledWith("@integration/package-2@1.0.1", "latest", conf, cache); -}); - -test("publish --dist-tag beta --temp-tag", async () => { - const cwd = await initFixture("integration"); - - await lernaPublish(cwd)("--dist-tag", "beta", "--temp-tag"); - - expect(npmPublish.registry).toMatchInlineSnapshot(` -Map { - "@integration/package-1" => "lerna-temp", - "@integration/package-2" => "lerna-temp", -} -`); - - const conf = expect.objectContaining({ - tag: "beta", - }); - const cache = expect.objectContaining({ - otp: undefined, - }); - - expect(npmDistTag.add).toHaveBeenCalledWith("@integration/package-1@1.0.1", "beta", conf, cache); // <-- - expect(npmDistTag.add).toHaveBeenCalledWith("@integration/package-2@1.0.1", "beta", conf, cache); -}); - -test("publish prerelease --pre-dist-tag beta", async () => { - const cwd = await initFixture("normal"); - - collectUpdates.setUpdated(cwd, "package-1"); - - await lernaPublish(cwd)("prerelease", "--pre-dist-tag", "beta"); - - expect(npmPublish.registry.get("package-1")).toBe("beta"); - expect(npmDistTag.remove).not.toHaveBeenCalled(); -}); - -test("publish non-prerelease --pre-dist-tag beta", async () => { - const cwd = await initFixture("normal"); - - collectUpdates.setUpdated(cwd, "package-1"); - - await lernaPublish(cwd)("--pre-dist-tag", "beta"); - - expect(npmPublish.registry.get("package-1")).toBe("latest"); - expect(npmDistTag.remove).not.toHaveBeenCalled(); -}); - -test("publish non-prerelease --dist-tag next --pre-dist-tag beta", async () => { - const cwd = await initFixture("normal"); - - collectUpdates.setUpdated(cwd, "package-1"); - - await lernaPublish(cwd)("--dist-tag", "next", "--pre-dist-tag", "beta"); - - expect(npmPublish.registry.get("package-1")).toBe("next"); - expect(npmDistTag.remove).not.toHaveBeenCalled(); -}); - -test("publish --pre-dist-tag beta --temp-tag", async () => { - const cwd = await initFixture("integration"); - - await lernaPublish(cwd)( - "prerelease", - "--dist-tag", - "next", - "--preid", - "beta", - "--pre-dist-tag", - "beta", - "--temp-tag" - ); - - expect(npmPublish.registry).toMatchInlineSnapshot(` -Map { - "@integration/package-1" => "lerna-temp", - "@integration/package-2" => "lerna-temp", -} -`); - - const conf = expect.objectContaining({ - tag: "next", - }); - const cache = expect.objectContaining({ - otp: undefined, - }); - - expect(npmDistTag.add).toHaveBeenCalledWith("@integration/package-1@1.0.1-beta.0", "beta", conf, cache); - expect(npmDistTag.add).toHaveBeenCalledWith("@integration/package-2@1.0.1-beta.0", "beta", conf, cache); -}); diff --git a/commands/publish/__tests__/remove-temp-licenses.test.js b/commands/publish/__tests__/remove-temp-licenses.test.js deleted file mode 100644 index 45377a2ba7..0000000000 --- a/commands/publish/__tests__/remove-temp-licenses.test.js +++ /dev/null @@ -1,37 +0,0 @@ -"use strict"; - -const fs = require("fs-extra"); -const path = require("path"); -const { Project } = require("@lerna/project"); -const initFixture = require("@lerna-test/helpers").initFixtureFactory(__dirname); -const { removeTempLicenses } = require("../lib/remove-temp-licenses"); - -describe("removeTempLicenses", () => { - it("removes license file from target packages", async () => { - const cwd = await initFixture("licenses-names"); - const project = new Project(cwd); - const [pkg] = await project.getPackages(); - - // mimic decoration in createTempLicenses() - pkg.licensePath = path.join(pkg.location, "LICENSE"); - - await removeTempLicenses([pkg]); - - const tempLicensePresent = await fs.pathExists(pkg.licensePath); - expect(tempLicensePresent).toBe(false); - }); - - it("skips removal when no target packages exist", async () => { - const cwd = await initFixture("licenses-names"); - const project = new Project(cwd); - const [pkg] = await project.getPackages(); - - // mimic decoration in createTempLicenses() - pkg.licensePath = path.join(pkg.location, "LICENSE"); - - await removeTempLicenses([]); - - const licensePresent = await fs.pathExists(pkg.licensePath); - expect(licensePresent).toBe(true); - }); -}); diff --git a/commands/publish/__tests__/verify-npm-package-access.test.js b/commands/publish/__tests__/verify-npm-package-access.test.js deleted file mode 100644 index f5c73b6f89..0000000000 --- a/commands/publish/__tests__/verify-npm-package-access.test.js +++ /dev/null @@ -1,154 +0,0 @@ -"use strict"; - -jest.mock("libnpmaccess"); - -const access = require("libnpmaccess"); -const { getPackages } = require("@lerna/project"); -const { loggingOutput } = require("@lerna-test/helpers/logging-output"); -const initFixture = require("@lerna-test/helpers").initFixtureFactory(__dirname); -const { verifyNpmPackageAccess } = require("../lib/verify-npm-package-access"); - -access.lsPackages.mockImplementation(() => - Promise.resolve({ - "package-1": "read-write", - "package-2": "read-write", - }) -); - -describe("verifyNpmPackageAccess", () => { - const origConsoleError = console.error; - - let cwd; - - beforeAll(async () => { - cwd = await initFixture("lifecycle"); - }); - - beforeEach(() => { - console.error = jest.fn(); - }); - - afterEach(() => { - console.error = origConsoleError; - }); - - test("validates that all packages have read-write permission", async () => { - const packages = await getPackages(cwd); - const opts = { registry: "https://registry.npmjs.org/" }; - - await verifyNpmPackageAccess(packages, "lerna-test", opts); - - expect(access.lsPackages).toHaveBeenLastCalledWith( - "lerna-test", - expect.objectContaining({ - registry: "https://registry.npmjs.org/", - fetchRetries: 0, - }) - ); - }); - - test("allows unpublished packages to pass", async () => { - const packages = await getPackages(cwd); - const opts = { registry: "https://registry.npmjs.org/" }; - - access.lsPackages.mockImplementationOnce(() => - Promise.resolve({ - "package-1": "read-write", - // unpublished packages don't show up in ls-packages - // "package-2": "read-write", - }) - ); - - await verifyNpmPackageAccess(packages, "lerna-test", opts); - - expect(access.lsPackages).toHaveBeenCalled(); - }); - - test("allows null result to pass with warning", async () => { - const packages = await getPackages(cwd); - const opts = { registry: "https://registry.npmjs.org/" }; - - access.lsPackages.mockImplementationOnce(() => - // access.lsPackages() returns null when _no_ results returned - Promise.resolve(null) - ); - - await verifyNpmPackageAccess(packages, "lerna-test", opts); - - const [logMessage] = loggingOutput("warn"); - expect(logMessage).toBe( - "The logged-in user does not have any previously-published packages, skipping permission checks..." - ); - }); - - test("throws EACCESS when any package does not have read-write permission", async () => { - const packages = await getPackages(cwd); - const opts = { registry: "https://registry.npmjs.org/" }; - - access.lsPackages.mockImplementationOnce(() => - Promise.resolve({ - "package-1": "read-write", - "package-2": "read-only", - }) - ); - - const result = verifyNpmPackageAccess(packages, "lerna-test", opts); - await expect(result).rejects.toThrow(`You do not have write permission required to publish "package-2"`); - expect(console.error).not.toHaveBeenCalled(); - }); - - test("passes when npm Enterprise registry returns E500", async () => { - const packages = await getPackages(cwd); - const registry = "http://outdated-npm-enterprise.mycompany.com:12345/"; - const opts = { registry }; - - access.lsPackages.mockImplementationOnce(() => { - const err = new Error("npm-enterprise-what"); - err.code = "E500"; - return Promise.reject(err); - }); - - await verifyNpmPackageAccess(packages, "lerna-test", opts); - - const [logMessage] = loggingOutput("warn"); - expect(logMessage).toMatch( - `Registry "${registry}" does not support \`npm access ls-packages\`, skipping permission checks...` - ); - expect(console.error).not.toHaveBeenCalled(); - }); - - test("passes when Artifactory registry returns E404", async () => { - const packages = await getPackages(cwd); - const registry = "https://artifactory-partial-implementation.corpnet.mycompany.com/"; - const opts = { registry }; - - access.lsPackages.mockImplementationOnce(() => { - const err = new Error("artifactory-why"); - err.code = "E404"; - return Promise.reject(err); - }); - - await verifyNpmPackageAccess(packages, "lerna-test", opts); - - const [logMessage] = loggingOutput("warn"); - expect(logMessage).toMatch( - `Registry "${registry}" does not support \`npm access ls-packages\`, skipping permission checks...` - ); - expect(console.error).not.toHaveBeenCalled(); - }); - - test("logs unexpected failure message before throwing EWHOAMI", async () => { - const packages = await getPackages(cwd); - const opts = {}; - - access.lsPackages.mockImplementationOnce(() => { - const err = new Error("gonna-need-a-bigger-boat"); - - return Promise.reject(err); - }); - - const result = verifyNpmPackageAccess(packages, "lerna-test", opts); - await expect(result).rejects.toThrow("Authentication error. Use `npm whoami` to troubleshoot."); - expect(console.error).toHaveBeenCalledWith("gonna-need-a-bigger-boat"); - }); -}); diff --git a/commands/publish/command.js b/commands/publish/command.js deleted file mode 100644 index 586c774f71..0000000000 --- a/commands/publish/command.js +++ /dev/null @@ -1,181 +0,0 @@ -"use strict"; - -const log = require("npmlog"); -const versionCommand = require("@lerna/version/command"); - -/** - * @see https://github.com/yargs/yargs/blob/master/docs/advanced.md#providing-a-command-module - */ -exports.command = "publish [bump]"; - -exports.describe = "Publish packages in the current project."; - -exports.builder = (yargs) => { - const opts = { - c: { - describe: "Publish packages after every successful merge using the sha as part of the tag.", - alias: "canary", - type: "boolean", - }, - // preid is copied from ../version/command because a whitelist for one option isn't worth it - preid: { - describe: "Specify the prerelease identifier when publishing a prerelease", - type: "string", - requiresArg: true, - defaultDescription: "alpha", - }, - contents: { - describe: "Subdirectory to publish. Must apply to ALL packages.", - type: "string", - requiresArg: true, - defaultDescription: ".", - }, - "dist-tag": { - describe: "Publish packages with the specified npm dist-tag", - type: "string", - requiresArg: true, - }, - "legacy-auth": { - describe: "Legacy Base64 Encoded username and password.", - type: "string", - }, - "pre-dist-tag": { - describe: "Publish prerelease packages with the specified npm dist-tag", - type: "string", - requiresArg: true, - }, - "git-head": { - describe: - "Explicit SHA to set as gitHead when packing tarballs, only allowed with 'from-package' positional.", - type: "string", - requiresArg: true, - }, - "graph-type": { - describe: "Type of dependency to use when determining package hierarchy.", - choices: ["all", "dependencies"], - defaultDescription: "dependencies", - }, - "ignore-prepublish": { - describe: "Disable deprecated 'prepublish' lifecycle script", - type: "boolean", - }, - "ignore-scripts": { - describe: "Disable all lifecycle scripts", - type: "boolean", - }, - // TODO: (major) make --no-granular-pathspec the default - "no-granular-pathspec": { - describe: "Do not reset changes file-by-file, but globally.", - type: "boolean", - }, - "granular-pathspec": { - // proxy for --no-granular-pathspec - hidden: true, - // describe: "Reset changes file-by-file, not globally.", - type: "boolean", - }, - otp: { - describe: "Supply a one-time password for publishing with two-factor authentication.", - type: "string", - requiresArg: true, - }, - registry: { - describe: "Use the specified registry for all npm client operations.", - type: "string", - requiresArg: true, - }, - "require-scripts": { - describe: "Execute ./scripts/prepublish.js and ./scripts/postpublish.js, relative to package root.", - type: "boolean", - }, - "no-git-reset": { - describe: "Do not reset changes to working tree after publishing is complete.", - type: "boolean", - }, - "git-reset": { - // proxy for --no-git-reset - hidden: true, - type: "boolean", - }, - "temp-tag": { - describe: "Create a temporary tag while publishing.", - type: "boolean", - }, - "no-verify-access": { - // proxy for --verify-access - describe: "Do not verify package read-write access for current npm user.", - type: "boolean", - }, - "verify-access": { - describe: "Verify package read-write access for current npm user.", - type: "boolean", - }, - "summary-file": { - // generate lerna publish json output. - describe: - "Generate a json summary report after all packages have been successfully published, you can pass an optional path for where to save the file.", - type: "string", - }, - }; - - composeVersionOptions(yargs); - - yargs.options(opts); - - // "unhide" duplicate options - const { hiddenOptions } = yargs.getOptions(); - const sharedKeys = ["preid", "y", "ignore-scripts"]; - - for (const sharedKey of sharedKeys) { - hiddenOptions.splice( - hiddenOptions.findIndex((k) => k === sharedKey), - 1 - ); - } - - yargs.group(Object.keys(opts).concat(sharedKeys), "Command Options:"); - - return yargs - .option("npm-tag", { - // TODO: remove in next major release - hidden: true, - conflicts: "dist-tag", - type: "string", - requiresArg: true, - }) - .option("verify-registry", { - // TODO: remove in next major release - hidden: true, - type: "boolean", - }) - .option("skip-npm", { - // TODO: remove in next major release - // deprecation notice handled in initialize() - hidden: true, - type: "boolean", - }) - .check((argv) => { - /* eslint-disable no-param-reassign */ - if (argv.npmTag) { - argv.distTag = argv.npmTag; - argv["dist-tag"] = argv.npmTag; - delete argv.npmTag; - delete argv["npm-tag"]; - log.warn("deprecated", "--npm-tag has been renamed --dist-tag"); - } - /* eslint-enable no-param-reassign */ - - return argv; - }); -}; - -exports.handler = function handler(argv) { - return require(".")(argv); -}; - -function composeVersionOptions(yargs) { - versionCommand.addBumpPositional(yargs, ["from-git", "from-package"]); - versionCommand.builder(yargs, "publish"); - - return yargs; -} diff --git a/commands/publish/index.js b/commands/publish/index.js deleted file mode 100644 index 716c8764f5..0000000000 --- a/commands/publish/index.js +++ /dev/null @@ -1,913 +0,0 @@ -"use strict"; - -const os = require("os"); -const fs = require("fs"); -const path = require("path"); -const crypto = require("crypto"); -const pMap = require("p-map"); -const pPipe = require("p-pipe"); -const semver = require("semver"); - -const { Command } = require("@lerna/command"); -const { ValidationError } = require("@lerna/validation-error"); -const { describeRef } = require("@lerna/describe-ref"); -const { throwIfUncommitted } = require("@lerna/check-working-tree"); -const { promptConfirmation } = require("@lerna/prompt"); -const { output } = require("@lerna/output"); -const { collectUpdates } = require("@lerna/collect-updates"); -const npmConf = require("@lerna/npm-conf"); -const npmDistTag = require("@lerna/npm-dist-tag"); -const { npmPublish } = require("@lerna/npm-publish"); -const { packDirectory } = require("@lerna/pack-directory"); -const { logPacked } = require("@lerna/log-packed"); -const { createRunner } = require("@lerna/run-lifecycle"); -const { runTopologically } = require("@lerna/run-topologically"); -const { pulseTillDone } = require("@lerna/pulse-till-done"); -const versionCommand = require("@lerna/version"); -const { prereleaseIdFromVersion } = require("@lerna/prerelease-id-from-version"); -const { getOneTimePassword } = require("@lerna/otplease"); - -const { createTempLicenses } = require("./lib/create-temp-licenses"); -const { getCurrentSHA } = require("./lib/get-current-sha"); -const { getCurrentTags } = require("./lib/get-current-tags"); -const { getUnpublishedPackages } = require("./lib/get-unpublished-packages"); -const { getNpmUsername } = require("./lib/get-npm-username"); -const { getTaggedPackages } = require("./lib/get-tagged-packages"); -const { getPackagesWithoutLicense } = require("./lib/get-packages-without-license"); -const { gitCheckout } = require("./lib/git-checkout"); -const { removeTempLicenses } = require("./lib/remove-temp-licenses"); -const { verifyNpmPackageAccess } = require("./lib/verify-npm-package-access"); -const { getTwoFactorAuthRequired } = require("./lib/get-two-factor-auth-required"); - -module.exports = factory; - -function factory(argv) { - return new PublishCommand(argv); -} - -class PublishCommand extends Command { - get otherCommandConfigs() { - // back-compat - return ["version"]; - } - - get requiresGit() { - // `lerna publish from-package` doesn't _need_ git, per se - return this.options.bump !== "from-package"; - } - - configureProperties() { - super.configureProperties(); - - // For publish we want to enable topological sorting by default, but allow users to override with --no-sort - this.toposort = this.options.sort !== false; - - // Defaults are necessary here because yargs defaults - // override durable options provided by a config file - const { - // prettier-ignore - exact, - gitHead, - gitReset, - tagVersionPrefix = "v", - verifyAccess, - } = this.options; - - if (this.requiresGit && gitHead) { - throw new ValidationError("EGITHEAD", "--git-head is only allowed with 'from-package' positional"); - } - - // https://docs.npmjs.com/misc/config#save-prefix - this.savePrefix = exact ? "" : "^"; - - // https://docs.npmjs.com/misc/config#tag-version-prefix - this.tagPrefix = tagVersionPrefix; - // TODO: properly inherit from npm-conf - - // inverted boolean options are only respected if prefixed with `--no-`, e.g. `--no-verify-access` - this.gitReset = gitReset !== false; - - // consumed by npm-registry-fetch (via libnpmpublish) - this.npmSession = crypto.randomBytes(8).toString("hex"); - - this.verifyAccess = verifyAccess; - } - - get userAgent() { - // consumed by npm-registry-fetch (via libnpmpublish) - return `lerna/${this.options.lernaVersion}/node@${process.version}+${process.arch} (${process.platform})`; - } - - initialize() { - if (this.options.verifyAccess === false) { - this.logger.warn( - "verify-access", - "--verify-access=false and --no-verify-access are no longer needed, because the legacy preemptive access verification is now disabled by default. Requests will fail with appropriate errors when not authorized correctly." - ); - } - - if (this.options.graphType === "dependencies") { - this.logger.warn( - "graph-type", - "--graph-type=dependencies is deprecated and will be removed in lerna v6. If you have a use-case you feel requires it please open an issue to discuss: https://github.com/lerna/lerna/issues/new/choose" - ); - } - - if (this.options.skipNpm) { - // TODO: remove in next major release - this.logger.warn("deprecated", "Instead of --skip-npm, call `lerna version` directly"); - - return versionCommand(this.argv).then(() => false); - } - - if (this.options.canary) { - this.logger.info("canary", "enabled"); - } - - if (this.options.requireScripts) { - this.logger.info("require-scripts", "enabled"); - } - - // npmSession and user-agent are consumed by npm-registry-fetch (via libnpmpublish) - this.logger.verbose("session", this.npmSession); - this.logger.verbose("user-agent", this.userAgent); - - this.conf = npmConf({ - lernaCommand: "publish", - _auth: this.options.legacyAuth, - npmSession: this.npmSession, - npmVersion: this.userAgent, - otp: this.options.otp, - registry: this.options.registry, - "ignore-prepublish": this.options.ignorePrepublish, - "ignore-scripts": this.options.ignoreScripts, - }); - - // cache to hold a one-time-password across publishes - this.otpCache = { otp: this.conf.get("otp") }; - - this.conf.set("user-agent", this.userAgent, "cli"); - - if (this.conf.get("registry") === "https://registry.yarnpkg.com") { - this.logger.warn("", "Yarn's registry proxy is broken, replacing with public npm registry"); - this.logger.warn("", "If you don't have an npm token, you should exit and run `npm login`"); - - this.conf.set("registry", "https://registry.npmjs.org/", "cli"); - } - - // inject --dist-tag into opts, if present - const distTag = this.getDistTag(); - - if (distTag) { - this.conf.set("tag", distTag.trim(), "cli"); - } - - // a "rooted leaf" is the regrettable pattern of adding "." to the "packages" config in lerna.json - this.hasRootedLeaf = this.packageGraph.has(this.project.manifest.name); - - if (this.hasRootedLeaf) { - this.logger.info("publish", "rooted leaf detected, skipping synthetic root lifecycles"); - } - - this.runPackageLifecycle = createRunner(this.options); - - // don't execute recursively if run from a poorly-named script - this.runRootLifecycle = /^(pre|post)?publish$/.test(process.env.npm_lifecycle_event) - ? (stage) => { - this.logger.warn("lifecycle", "Skipping root %j because it has already been called", stage); - } - : (stage) => this.runPackageLifecycle(this.project.manifest, stage); - - let chain = Promise.resolve(); - - if (this.options.bump === "from-git") { - chain = chain.then(() => this.detectFromGit()); - } else if (this.options.bump === "from-package") { - chain = chain.then(() => this.detectFromPackage()); - } else if (this.options.canary) { - chain = chain.then(() => this.detectCanaryVersions()); - } else { - chain = chain.then(() => versionCommand(this.argv)); - } - - return chain.then((result) => { - if (!result) { - // early return from nested VersionCommand - return false; - } - - if (!result.updates.length) { - this.logger.success("No changed packages to publish"); - - // still exits zero, aka "ok" - return false; - } - - // (occasionally) redundant private filtering necessary to handle nested VersionCommand - this.updates = result.updates.filter((node) => !node.pkg.private); - this.updatesVersions = new Map(result.updatesVersions); - - this.packagesToPublish = this.updates.map((node) => node.pkg); - - if (this.options.contents) { - // globally override directory to publish - for (const pkg of this.packagesToPublish) { - pkg.contents = this.options.contents; - } - } - - if (result.needsConfirmation) { - // only confirm for --canary, bump === "from-git", - // or bump === "from-package", as VersionCommand - // has its own confirmation prompt - return this.confirmPublish(); - } - - return true; - }); - } - - execute() { - this.enableProgressBar(); - this.logger.info("publish", "Publishing packages to npm..."); - - let chain = Promise.resolve(); - - chain = chain.then(() => this.prepareRegistryActions()); - chain = chain.then(() => this.prepareLicenseActions()); - - if (this.options.canary) { - chain = chain.then(() => this.updateCanaryVersions()); - } - - chain = chain.then(() => this.resolveLocalDependencyLinks()); - chain = chain.then(() => this.resolveWorkspaceDependencyLinks()); - chain = chain.then(() => this.annotateGitHead()); - chain = chain.then(() => this.serializeChanges()); - chain = chain.then(() => this.packUpdated()); - chain = chain.then(() => this.publishPacked()); - - if (this.gitReset) { - chain = chain.then(() => this.resetChanges()); - } - - if (this.options.tempTag) { - chain = chain.then(() => this.npmUpdateAsLatest()); - } - - return chain.then(() => { - const count = this.packagesToPublish.length; - - output("Successfully published:"); - - if (this.options.summaryFile !== undefined) { - // create a json object and output it to a file location. - const filePath = this.options.summaryFile - ? `${this.options.summaryFile}/lerna-publish-summary.json` - : "./lerna-publish-summary.json"; - const jsonObject = this.packagesToPublish.map((pkg) => { - return { - packageName: pkg.name, - version: pkg.version, - }; - }); - output(jsonObject); - try { - fs.writeFileSync(filePath, JSON.stringify(jsonObject)); - output("Publish summary created: ", filePath); - } catch (error) { - output("Failed to create the summary report", error); - } - } else { - const message = this.packagesToPublish.map((pkg) => ` - ${pkg.name}@${pkg.version}`); - output(message.join(os.EOL)); - } - - this.logger.success("published", "%d %s", count, count === 1 ? "package" : "packages"); - }); - } - - verifyWorkingTreeClean() { - return describeRef(this.execOpts).then(throwIfUncommitted); - } - - detectFromGit() { - const matchingPattern = this.project.isIndependent() ? "*@*" : `${this.tagPrefix}*.*.*`; - - let chain = Promise.resolve(); - - // attempting to publish a tagged release with local changes is not allowed - chain = chain - .then(() => this.verifyWorkingTreeClean()) - .catch((err) => { - // an execa error is thrown when git suffers a fatal error (such as no git repository present) - if (err.failed && /git describe/.test(err.command)) { - // (we tried) - this.logger.silly("EWORKINGTREE", err.message); - this.logger.notice("FYI", "Unable to verify working tree, proceed at your own risk"); - } else { - // validation errors should be preserved - throw err; - } - }); - - chain = chain.then(() => getCurrentTags(this.execOpts, matchingPattern)); - chain = chain.then((taggedPackageNames) => { - if (!taggedPackageNames.length) { - this.logger.notice("from-git", "No tagged release found"); - - return []; - } - - if (this.project.isIndependent()) { - return taggedPackageNames.map((name) => this.packageGraph.get(name)); - } - - return getTaggedPackages(this.packageGraph, this.project.rootPath, this.execOpts); - }); - - // private packages are never published, full stop. - chain = chain.then((updates) => updates.filter((node) => !node.pkg.private)); - - return chain.then((updates) => { - const updatesVersions = updates.map((node) => [node.name, node.version]); - - return { - updates, - updatesVersions, - needsConfirmation: true, - }; - }); - } - - detectFromPackage() { - let chain = Promise.resolve(); - - // attempting to publish a release with local changes is not allowed - chain = chain - .then(() => this.verifyWorkingTreeClean()) - .catch((err) => { - // an execa error is thrown when git suffers a fatal error (such as no git repository present) - if (err.failed && /git describe/.test(err.command)) { - // (we tried) - this.logger.silly("EWORKINGTREE", err.message); - this.logger.notice("FYI", "Unable to verify working tree, proceed at your own risk"); - } else { - // validation errors should be preserved - throw err; - } - }); - - // private packages are already omitted by getUnpublishedPackages() - chain = chain.then(() => getUnpublishedPackages(this.packageGraph, this.conf.snapshot)); - chain = chain.then((unpublished) => { - if (!unpublished.length) { - this.logger.notice("from-package", "No unpublished release found"); - } - - return unpublished; - }); - - return chain.then((updates) => { - const updatesVersions = updates.map((node) => [node.name, node.version]); - - return { - updates, - updatesVersions, - needsConfirmation: true, - }; - }); - } - - detectCanaryVersions() { - const { cwd } = this.execOpts; - const { - bump = "prepatch", - preid = "alpha", - ignoreChanges, - forcePublish, - includeMergedTags, - } = this.options; - // "prerelease" and "prepatch" are identical, for our purposes - const release = bump.startsWith("pre") ? bump.replace("release", "patch") : `pre${bump}`; - - let chain = Promise.resolve(); - - // attempting to publish a canary release with local changes is not allowed - chain = chain - .then(() => this.verifyWorkingTreeClean()) - .catch((err) => { - // an execa error is thrown when git suffers a fatal error (such as no git repository present) - if (err.failed && /git describe/.test(err.command)) { - // (we tried) - this.logger.silly("EWORKINGTREE", err.message); - this.logger.notice("FYI", "Unable to verify working tree, proceed at your own risk"); - } else { - // validation errors should be preserved - throw err; - } - }); - - // find changed packages since last release, if any - chain = chain.then(() => - collectUpdates(this.packageGraph.rawPackageList, this.packageGraph, this.execOpts, { - bump: "prerelease", - canary: true, - ignoreChanges, - forcePublish, - includeMergedTags, - // private packages are never published, don't bother describing their refs. - }).filter((node) => !node.pkg.private) - ); - - const makeVersion = - (fallback) => - ({ lastVersion = fallback, refCount, sha }) => { - // the next version is bumped without concern for preid or current index - const nextVersion = semver.inc(lastVersion.replace(this.tagPrefix, ""), release.replace("pre", "")); - - // semver.inc() starts a new prerelease at .0, git describe starts at .1 - // and build metadata is always ignored when comparing dependency ranges - return `${nextVersion}-${preid}.${Math.max(0, refCount - 1)}+${sha}`; - }; - - if (this.project.isIndependent()) { - // each package is described against its tags only - chain = chain.then((updates) => - pMap(updates, (node) => - describeRef( - { - match: `${node.name}@*`, - cwd, - }, - includeMergedTags - ) - // an unpublished package will have no reachable git tag - .then(makeVersion(node.version)) - .then((version) => [node.name, version]) - ).then((updatesVersions) => ({ - updates, - updatesVersions, - })) - ); - } else { - // all packages are described against the last tag - chain = chain.then((updates) => - describeRef( - { - match: `${this.tagPrefix}*.*.*`, - cwd, - }, - includeMergedTags - ) - // a repo with no tags should default to whatever lerna.json claims - .then(makeVersion(this.project.version)) - .then((version) => updates.map((node) => [node.name, version])) - .then((updatesVersions) => ({ - updates, - updatesVersions, - })) - ); - } - - return chain.then(({ updates, updatesVersions }) => ({ - updates, - updatesVersions, - needsConfirmation: true, - })); - } - - confirmPublish() { - const count = this.packagesToPublish.length; - const message = this.packagesToPublish.map( - (pkg) => ` - ${pkg.name} => ${this.updatesVersions.get(pkg.name)}` - ); - - output(""); - output(`Found ${count} ${count === 1 ? "package" : "packages"} to publish:`); - output(message.join(os.EOL)); - output(""); - - if (this.options.yes) { - this.logger.info("auto-confirmed"); - return true; - } - - return promptConfirmation("Are you sure you want to publish these packages?"); - } - - prepareLicenseActions() { - return Promise.resolve() - .then(() => getPackagesWithoutLicense(this.project, this.packagesToPublish)) - .then((packagesWithoutLicense) => { - if (packagesWithoutLicense.length && !this.project.licensePath) { - this.packagesToBeLicensed = []; - - const names = packagesWithoutLicense.map((pkg) => pkg.name); - const noun = names.length > 1 ? "Packages" : "Package"; - const verb = names.length > 1 ? "are" : "is"; - const list = - names.length > 1 - ? `${names.slice(0, -1).join(", ")}${names.length > 2 ? "," : ""} and ${ - names[names.length - 1] /* oxford commas _are_ that important */ - }` - : names[0]; - - this.logger.warn( - "ENOLICENSE", - "%s %s %s missing a license.\n%s\n%s", - noun, - list, - verb, - "One way to fix this is to add a LICENSE.md file to the root of this repository.", - "See https://choosealicense.com for additional guidance." - ); - } else { - this.packagesToBeLicensed = packagesWithoutLicense; - } - }); - } - - prepareRegistryActions() { - let chain = Promise.resolve(); - - if (this.conf.get("registry") !== "https://registry.npmjs.org/") { - this.logger.notice("", "Skipping all user and access validation due to third-party registry"); - this.logger.notice("", "Make sure you're authenticated properly ¯\\_(ツ)_/¯"); - - return chain; - } - - /* istanbul ignore if */ - if (process.env.LERNA_INTEGRATION) { - return chain; - } - - if (this.verifyAccess) { - // validate user has valid npm credentials first, - // by far the most common form of failed execution - chain = chain.then(() => getNpmUsername(this.conf.snapshot)); - chain = chain.then((username) => { - // if no username was retrieved, don't bother validating - if (username) { - return verifyNpmPackageAccess(this.packagesToPublish, username, this.conf.snapshot); - } - }); - - // read profile metadata to determine if account-level 2FA is enabled - chain = chain.then(() => getTwoFactorAuthRequired(this.conf.snapshot)); - chain = chain.then((isRequired) => { - // notably, this still doesn't handle package-level 2FA requirements - this.twoFactorAuthRequired = isRequired; - }); - } - - return chain; - } - - updateCanaryVersions() { - return pMap(this.updates, (node) => { - node.pkg.set("version", this.updatesVersions.get(node.name)); - - for (const [depName, resolved] of node.localDependencies) { - // other canary versions need to be updated, non-canary is a no-op - const depVersion = this.updatesVersions.get(depName) || this.packageGraph.get(depName).pkg.version; - - // it no longer matters if we mutate the shared Package instance - node.pkg.updateLocalDependency(resolved, depVersion, this.savePrefix); - } - - // writing changes to disk handled in serializeChanges() - }); - } - - resolveLocalDependencyLinks() { - // resolve relative file: links to their actual version range - const updatesWithLocalLinks = this.updates.filter((node) => - Array.from(node.localDependencies.values()).some((resolved) => resolved.type === "directory") - ); - - return pMap(updatesWithLocalLinks, (node) => { - for (const [depName, resolved] of node.localDependencies) { - // regardless of where the version comes from, we can't publish "file:../sibling-pkg" specs - const depVersion = this.updatesVersions.get(depName) || this.packageGraph.get(depName).pkg.version; - - // it no longer matters if we mutate the shared Package instance - node.pkg.updateLocalDependency(resolved, depVersion, this.savePrefix); - } - - // writing changes to disk handled in serializeChanges() - }); - } - - resolveWorkspaceDependencyLinks() { - // resolve relative workspace: links to their actual version range - const updatesWithWorkspaceLinks = this.updates.filter((node) => - Array.from(node.localDependencies.values()).some((resolved) => !!resolved.workspaceSpec) - ); - - return pMap(updatesWithWorkspaceLinks, (node) => { - for (const [depName, resolved] of node.localDependencies) { - // only update local dependencies with workspace: links - if (resolved.workspaceSpec) { - let depVersion; - let savePrefix; - if (resolved.workspaceAlias) { - depVersion = this.updatesVersions.get(depName) || this.packageGraph.get(depName).pkg.version; - savePrefix = resolved.workspaceAlias === "*" ? "" : resolved.workspaceAlias; - } else { - const specMatch = resolved.workspaceSpec.match(/^workspace:([~^]?)(.*)/); - savePrefix = specMatch[1]; - depVersion = specMatch[2]; - } - - // it no longer matters if we mutate the shared Package instance - node.pkg.updateLocalDependency(resolved, depVersion, savePrefix, { retainWorkspacePrefix: false }); - } - } - - // writing changes to disk handled in serializeChanges() - }); - } - - annotateGitHead() { - try { - const gitHead = this.options.gitHead || getCurrentSHA(this.execOpts); - - for (const pkg of this.packagesToPublish) { - // provide gitHead property that is normally added during npm publish - pkg.set("gitHead", gitHead); - } - } catch (err) { - // from-package should be _able_ to run without git, but at least we tried - this.logger.silly("EGITHEAD", err.message); - this.logger.notice( - "FYI", - "Unable to set temporary gitHead property, it will be missing from registry metadata" - ); - } - - // writing changes to disk handled in serializeChanges() - } - - serializeChanges() { - return pMap(this.packagesToPublish, (pkg) => pkg.serialize()); - } - - resetChanges() { - // the package.json files are changed (by gitHead if not --canary) - // and we should always __attempt_ to leave the working tree clean - const { cwd } = this.execOpts; - const gitOpts = { - granularPathspec: this.options.granularPathspec !== false, - }; - const dirtyManifests = [this.project.manifest] - .concat(this.packagesToPublish) - .map((pkg) => path.relative(cwd, pkg.manifestLocation)); - - return gitCheckout(dirtyManifests, gitOpts, this.execOpts).catch((err) => { - this.logger.silly("EGITCHECKOUT", err.message); - this.logger.notice("FYI", "Unable to reset working tree changes, this probably isn't a git repo."); - }); - } - - execScript(pkg, script) { - const scriptLocation = path.join(pkg.location, "scripts", script); - - try { - // eslint-disable-next-line import/no-dynamic-require, global-require - require(scriptLocation); - } catch (ex) { - this.logger.silly("execScript", `No ${script} script found at ${scriptLocation}`); - } - - return pkg; - } - - removeTempLicensesOnError(error) { - return Promise.resolve() - .then(() => - removeTempLicenses(this.packagesToBeLicensed).catch((removeError) => { - this.logger.error( - "licenses", - "error removing temporary license files", - removeError.stack || removeError - ); - }) - ) - .then(() => { - // restore original error into promise chain - throw error; - }); - } - - requestOneTimePassword() { - // if OTP has already been provided, skip prompt - if (this.otpCache.otp) { - return; - } - - return Promise.resolve() - .then(() => getOneTimePassword("Enter OTP:")) - .then((otp) => { - this.otpCache.otp = otp; - }); - } - - topoMapPackages(mapper) { - return runTopologically(this.packagesToPublish, mapper, { - concurrency: this.concurrency, - rejectCycles: this.options.rejectCycles, - /** - * Previously `publish` had unique default behavior for graph creation vs other commands: it would only consider dependencies when finding - * edges by default (i.e. relationships between packages specified via devDependencies would be ignored). It was documented to be the case - * in order to try and reduce the chance of dependency cycles. - * - * We are removing this behavior altogether in v6 because we do not want to have different ways of constructing the graph, - * only different ways of utilizing it (e.g. --no-sort vs topological sort). - * - * Therefore until we remove graphType altogether in v6, we provide a way for users to opt into the old default behavior - * by setting the `graphType` option to `dependencies`. - */ - graphType: this.options.graphType === "dependencies" ? "dependencies" : "allDependencies", - }); - } - - packUpdated() { - const tracker = this.logger.newItem("npm pack"); - - tracker.addWork(this.packagesToPublish.length); - - let chain = Promise.resolve(); - - chain = chain.then(() => createTempLicenses(this.project.licensePath, this.packagesToBeLicensed)); - - if (!this.hasRootedLeaf) { - // despite being deprecated for years... - chain = chain.then(() => this.runRootLifecycle("prepublish")); - - // these lifecycles _should_ never be employed to run `lerna publish`... - chain = chain.then(() => this.runPackageLifecycle(this.project.manifest, "prepare")); - chain = chain.then(() => this.runPackageLifecycle(this.project.manifest, "prepublishOnly")); - chain = chain.then(() => this.runPackageLifecycle(this.project.manifest, "prepack")); - } - - const opts = this.conf.snapshot; - const mapper = pPipe( - ...[ - this.options.requireScripts && ((pkg) => this.execScript(pkg, "prepublish")), - - (pkg) => - pulseTillDone(packDirectory(pkg, pkg.location, opts)).then((packed) => { - tracker.verbose("packed", path.relative(this.project.rootPath, pkg.contents)); - tracker.completeWork(1); - - // store metadata for use in this.publishPacked() - pkg.packed = packed; - - // manifest may be mutated by any previous lifecycle - return pkg.refresh(); - }), - ].filter(Boolean) - ); - - chain = chain.then(() => { - if (this.toposort) { - return this.topoMapPackages(mapper); - } - return pMap(this.packagesToPublish, mapper, { concurrency: this.concurrency }); - }); - - chain = chain.then(() => removeTempLicenses(this.packagesToBeLicensed)); - - // remove temporary license files if _any_ error occurs _anywhere_ in the promise chain - chain = chain.catch((error) => this.removeTempLicensesOnError(error)); - - if (!this.hasRootedLeaf) { - chain = chain.then(() => this.runPackageLifecycle(this.project.manifest, "postpack")); - } - - return chain.finally(() => tracker.finish()); - } - - publishPacked() { - const tracker = this.logger.newItem("publish"); - - tracker.addWork(this.packagesToPublish.length); - - let chain = Promise.resolve(); - - // if account-level 2FA is enabled, prime the OTP cache - if (this.twoFactorAuthRequired) { - chain = chain.then(() => this.requestOneTimePassword()); - } - - const opts = Object.assign(this.conf.snapshot, { - // distTag defaults to "latest" OR whatever is in pkg.publishConfig.tag - // if we skip temp tags we should tag with the proper value immediately - tag: this.options.tempTag ? "lerna-temp" : this.conf.get("tag"), - }); - - const mapper = pPipe( - ...[ - (pkg) => { - const preDistTag = this.getPreDistTag(pkg); - const tag = !this.options.tempTag && preDistTag ? preDistTag : opts.tag; - const pkgOpts = Object.assign({}, opts, { tag }); - - return pulseTillDone(npmPublish(pkg, pkg.packed.tarFilePath, pkgOpts, this.otpCache)).then(() => { - tracker.success("published", pkg.name, pkg.version); - tracker.completeWork(1); - - logPacked(pkg.packed); - - return pkg; - }); - }, - - this.options.requireScripts && ((pkg) => this.execScript(pkg, "postpublish")), - ].filter(Boolean) - ); - - chain = chain.then(() => { - if (this.toposort) { - return this.topoMapPackages(mapper); - } - return pMap(this.packagesToPublish, mapper, { concurrency: this.concurrency }); - }); - - if (!this.hasRootedLeaf) { - // cyclical "publish" lifecycles are automatically skipped - chain = chain.then(() => this.runRootLifecycle("publish")); - chain = chain.then(() => this.runRootLifecycle("postpublish")); - } - - return chain.finally(() => tracker.finish()); - } - - npmUpdateAsLatest() { - const tracker = this.logger.newItem("npmUpdateAsLatest"); - - tracker.addWork(this.packagesToPublish.length); - tracker.showProgress(); - - let chain = Promise.resolve(); - - const opts = this.conf.snapshot; - const getDistTag = (publishConfig) => { - if (opts.tag === "latest" && publishConfig && publishConfig.tag) { - return publishConfig.tag; - } - - return opts.tag; - }; - const mapper = (pkg) => { - const spec = `${pkg.name}@${pkg.version}`; - const preDistTag = this.getPreDistTag(pkg); - const distTag = preDistTag || getDistTag(pkg.get("publishConfig")); - - return Promise.resolve() - .then(() => pulseTillDone(npmDistTag.remove(spec, "lerna-temp", opts, this.otpCache))) - .then(() => pulseTillDone(npmDistTag.add(spec, distTag, opts, this.otpCache))) - .then(() => { - tracker.success("dist-tag", "%s@%s => %j", pkg.name, pkg.version, distTag); - tracker.completeWork(1); - - return pkg; - }); - }; - - chain = chain.then(() => { - if (this.toposort) { - return this.topoMapPackages(mapper); - } - return pMap(this.packagesToPublish, mapper, { concurrency: this.concurrency }); - }); - - return chain.finally(() => tracker.finish()); - } - - getDistTag() { - if (this.options.distTag) { - return this.options.distTag; - } - - if (this.options.canary) { - return "canary"; - } - - // undefined defaults to "latest" OR whatever is in pkg.publishConfig.tag - } - - getPreDistTag(pkg) { - if (!this.options.preDistTag) { - return; - } - const isPrerelease = prereleaseIdFromVersion(pkg.version); - if (isPrerelease) { - return this.options.preDistTag; - } - } -} - -module.exports.PublishCommand = PublishCommand; diff --git a/commands/publish/lib/__mocks__/get-npm-username.js b/commands/publish/lib/__mocks__/get-npm-username.js deleted file mode 100644 index fd0fb26d7f..0000000000 --- a/commands/publish/lib/__mocks__/get-npm-username.js +++ /dev/null @@ -1,6 +0,0 @@ -"use strict"; - -// to mock user modules, you _must_ call `jest.mock('./path/to/module')` -const mockGetNpmUsername = jest.fn(() => Promise.resolve("lerna-test")); - -module.exports.getNpmUsername = mockGetNpmUsername; diff --git a/commands/publish/lib/__mocks__/get-packages-without-license.js b/commands/publish/lib/__mocks__/get-packages-without-license.js deleted file mode 100644 index b9a63fb8b4..0000000000 --- a/commands/publish/lib/__mocks__/get-packages-without-license.js +++ /dev/null @@ -1,4 +0,0 @@ -"use strict"; - -// to mock user modules, you _must_ call `jest.mock('./path/to/module')` -module.exports.getPackagesWithoutLicense = jest.fn(() => Promise.resolve([])); diff --git a/commands/publish/lib/__mocks__/get-two-factor-auth-required.js b/commands/publish/lib/__mocks__/get-two-factor-auth-required.js deleted file mode 100644 index b4cbd449c3..0000000000 --- a/commands/publish/lib/__mocks__/get-two-factor-auth-required.js +++ /dev/null @@ -1,6 +0,0 @@ -"use strict"; - -// to mock user modules, you _must_ call `jest.mock('./path/to/module')` -const mockGetTwoFactorAuthRequired = jest.fn(() => Promise.resolve(false)); - -module.exports.getTwoFactorAuthRequired = mockGetTwoFactorAuthRequired; diff --git a/commands/publish/lib/__mocks__/get-unpublished-packages.js b/commands/publish/lib/__mocks__/get-unpublished-packages.js deleted file mode 100644 index a0390d5120..0000000000 --- a/commands/publish/lib/__mocks__/get-unpublished-packages.js +++ /dev/null @@ -1,3 +0,0 @@ -"use strict"; - -module.exports.getUnpublishedPackages = jest.fn(() => Promise.resolve([])); diff --git a/commands/publish/lib/__mocks__/verify-npm-package-access.js b/commands/publish/lib/__mocks__/verify-npm-package-access.js deleted file mode 100644 index d83c769b1d..0000000000 --- a/commands/publish/lib/__mocks__/verify-npm-package-access.js +++ /dev/null @@ -1,6 +0,0 @@ -"use strict"; - -// to mock user modules, you _must_ call `jest.mock('./path/to/module')` -const mockVerifyNpmPackageAccess = jest.fn(() => Promise.resolve()); - -module.exports.verifyNpmPackageAccess = mockVerifyNpmPackageAccess; diff --git a/commands/publish/lib/create-temp-licenses.js b/commands/publish/lib/create-temp-licenses.js deleted file mode 100644 index b4f311684a..0000000000 --- a/commands/publish/lib/create-temp-licenses.js +++ /dev/null @@ -1,33 +0,0 @@ -"use strict"; - -const fs = require("fs-extra"); -const path = require("path"); -const pMap = require("p-map"); - -module.exports.createTempLicenses = createTempLicenses; - -/** - * Create temporary license files. - * @param {string} srcLicensePath - * @param {Packages[]} packagesToBeLicensed - */ -function createTempLicenses(srcLicensePath, packagesToBeLicensed) { - if (!srcLicensePath || !packagesToBeLicensed.length) { - return Promise.resolve(); - } - - // license file might have an extension, so let's allow it - const licenseFileName = path.basename(srcLicensePath); - const options = { - // make an effort to keep package contents stable over time - preserveTimestamps: process.arch !== "ia32", - // (give up on 32-bit architecture to avoid fs-extra warning) - }; - - // store target path for removal later - packagesToBeLicensed.forEach((pkg) => { - pkg.licensePath = path.join(pkg.contents, licenseFileName); - }); - - return pMap(packagesToBeLicensed, (pkg) => fs.copy(srcLicensePath, pkg.licensePath, options)); -} diff --git a/commands/publish/lib/fetch-config.js b/commands/publish/lib/fetch-config.js deleted file mode 100644 index b24f258218..0000000000 --- a/commands/publish/lib/fetch-config.js +++ /dev/null @@ -1,27 +0,0 @@ -"use strict"; - -const log = require("npmlog"); - -module.exports.getFetchConfig = getFetchConfig; - -/** - * Create a merged options object suitable for npm-registry-fetch. - * @param {{ [key: string]: unknown }} options - * @param {Partial} [extra] - * @returns {FetchConfig} - */ -function getFetchConfig(options, extra) { - return { - log, - ...options, - ...extra, - }; -} - -/** - * @typedef {object} FetchConfig - * @property {number} [fetchRetries] - * @property {typeof log} log - * @property {string} [registry] - * @property {string} [username] - */ diff --git a/commands/publish/lib/get-current-sha.js b/commands/publish/lib/get-current-sha.js deleted file mode 100644 index 12c03ad3b1..0000000000 --- a/commands/publish/lib/get-current-sha.js +++ /dev/null @@ -1,19 +0,0 @@ -"use strict"; - -const log = require("npmlog"); -const childProcess = require("@lerna/child-process"); - -module.exports.getCurrentSHA = getCurrentSHA; - -/** - * Retrieve current SHA from git. - * @param {import("@lerna/child-process").ExecOpts} opts - */ -function getCurrentSHA(opts) { - log.silly("getCurrentSHA"); - - const sha = childProcess.execSync("git", ["rev-parse", "HEAD"], opts); - log.verbose("getCurrentSHA", sha); - - return sha; -} diff --git a/commands/publish/lib/get-current-tags.js b/commands/publish/lib/get-current-tags.js deleted file mode 100644 index c666ed4587..0000000000 --- a/commands/publish/lib/get-current-tags.js +++ /dev/null @@ -1,38 +0,0 @@ -"use strict"; - -const log = require("npmlog"); -const npa = require("npm-package-arg"); -const childProcess = require("@lerna/child-process"); - -module.exports.getCurrentTags = getCurrentTags; - -/** - * Retrieve a list of git tags pointing to the current HEAD that match the provided pattern. - * @param {import("@lerna/child-process").ExecOpts} execOpts - * @param {string} matchingPattern - * @returns {string[]} - */ -function getCurrentTags(execOpts, matchingPattern) { - log.silly("getCurrentTags", "matching %j", matchingPattern); - - const opts = Object.assign({}, execOpts, { - // don't reject due to non-zero exit code when there are no results - reject: false, - }); - - return childProcess - .exec("git", ["tag", "--sort", "version:refname", "--points-at", "HEAD", "--list", matchingPattern], opts) - .then((result) => { - const lines = result.stdout.split("\n").filter(Boolean); - - if (matchingPattern === "*@*") { - // independent mode does not respect tagVersionPrefix, - // but embeds the package name in the tag "prefix" - return lines.map((tag) => npa(tag).name); - } - - // "fixed" mode can have a custom tagVersionPrefix, - // but it doesn't really matter as it is not used to extract package names - return lines; - }); -} diff --git a/commands/publish/lib/get-npm-username.js b/commands/publish/lib/get-npm-username.js deleted file mode 100644 index 68e81a95f0..0000000000 --- a/commands/publish/lib/get-npm-username.js +++ /dev/null @@ -1,72 +0,0 @@ -"use strict"; - -const { ValidationError } = require("@lerna/validation-error"); -const { getFetchConfig } = require("./fetch-config"); -const { getProfileData } = require("./get-profile-data"); -const { getWhoAmI } = require("./get-whoami"); - -module.exports.getNpmUsername = getNpmUsername; - -/** - * Retrieve username of logged-in user. - * @param {import("./fetch-config").FetchConfig} options - * @returns {Promise} - */ -function getNpmUsername(options) { - const opts = getFetchConfig(options, { - // don't wait forever for third-party failures to be dealt with - fetchRetries: 0, - }); - - opts.log.info("", "Verifying npm credentials"); - - return getProfileData(opts) - .catch((err) => { - // Many third-party registries do not implement the user endpoint - // Legacy npm Enterprise returns E500 instead of E404 - if (err.code === "E500" || err.code === "E404") { - return getWhoAmI(opts); - } - - // re-throw 401 Unauthorized (and all other unexpected errors) - throw err; - }) - .then(success, failure); - - function success(result) { - opts.log.silly("get npm username", "received %j", result); - - if (!result.username) { - throw new ValidationError( - "ENEEDAUTH", - "You must be logged in to publish packages. Use `npm login` and try again." - ); - } - - return result.username; - } - - // catch request errors, not auth expired errors - function failure(err) { - // Log the error cleanly to stderr - opts.log.pause(); - console.error(err.message); // eslint-disable-line no-console - opts.log.resume(); - - if (opts.registry === "https://registry.npmjs.org/") { - if (err.code === "E403") { - throw new ValidationError( - "ENEEDAUTH", - "Access verification failed. Ensure that your npm access token has both read and write access, or remove the verifyAccess option to skip this verification. Note that npm automation tokens do NOT have read access (https://docs.npmjs.com/creating-and-viewing-access-tokens)." - ); - } - - throw new ValidationError("EWHOAMI", "Authentication error. Use `npm whoami` to troubleshoot."); - } - - opts.log.warn( - "EWHOAMI", - "Unable to determine npm username from third-party registry, this command will likely fail soon!" - ); - } -} diff --git a/commands/publish/lib/get-packages-without-license.js b/commands/publish/lib/get-packages-without-license.js deleted file mode 100644 index a633706d18..0000000000 --- a/commands/publish/lib/get-packages-without-license.js +++ /dev/null @@ -1,21 +0,0 @@ -"use strict"; - -const path = require("path"); - -module.exports.getPackagesWithoutLicense = getPackagesWithoutLicense; - -/** - * Retrieve a list of packages that lack a license file. - * @param {Project} project - * @param {Package[]} packagesToPublish - * @returns {Package[]} - */ -function getPackagesWithoutLicense(project, packagesToPublish) { - return project.getPackageLicensePaths().then((licensePaths) => { - // this assumes any existing license is a sibling of package.json, which is pretty safe - // it also dedupes package locations, since we don't care about duplicate license files - const licensed = new Set(licensePaths.map((lp) => path.dirname(lp))); - - return packagesToPublish.filter((pkg) => !licensed.has(pkg.location)); - }); -} diff --git a/commands/publish/lib/get-profile-data.js b/commands/publish/lib/get-profile-data.js deleted file mode 100644 index 62e097346b..0000000000 --- a/commands/publish/lib/get-profile-data.js +++ /dev/null @@ -1,39 +0,0 @@ -"use strict"; - -const fetch = require("npm-registry-fetch"); -const { pulseTillDone } = require("@lerna/pulse-till-done"); - -module.exports.getProfileData = getProfileData; - -/** - * Retrieve profile data of logged-in user. - * @param {import("./fetch-config").FetchConfig} opts - * @returns {Promise} - */ -function getProfileData(opts) { - opts.log.verbose("", "Retrieving npm user profile"); - - return pulseTillDone(fetch.json("/-/npm/v1/user", opts)).then((data) => { - opts.log.silly("npm profile get", "received %j", data); - - return Object.assign( - // remap to match legacy whoami format - { username: data.name }, - data - ); - }); -} - -/** - * @typedef {object} ProfileData - * @property {{ pending: boolean; mode: 'auth-and-writes' | 'auth-only' }} tfa - * @property {string} name - * @property {string} username legacy field alias of `name` - * @property {string} email - * @property {boolean} email_verified - * @property {string} created - * @property {string} updated - * @property {string} [fullname] - * @property {string} [twitter] - * @property {string} [github] - */ diff --git a/commands/publish/lib/get-tagged-packages.js b/commands/publish/lib/get-tagged-packages.js deleted file mode 100644 index 3d931cbee1..0000000000 --- a/commands/publish/lib/get-tagged-packages.js +++ /dev/null @@ -1,29 +0,0 @@ -"use strict"; - -const path = require("path"); -const log = require("npmlog"); -const childProcess = require("@lerna/child-process"); - -module.exports.getTaggedPackages = getTaggedPackages; - -/** - * Retrieve a list of graph nodes for packages that were tagged in a non-independent release. - * @param {import("@lerna/package-graph").PackageGraph} packageGraph - * @param {string} rootPath - * @param {import("@lerna/child-process").ExecOpts} execOpts - * @returns {Promise} - */ -function getTaggedPackages(packageGraph, rootPath, execOpts) { - log.silly("getTaggedPackages"); - - // @see https://stackoverflow.com/a/424142/5707 - // FIXME: --root is only necessary for tests :P - return childProcess - .exec("git", ["diff-tree", "--name-only", "--no-commit-id", "--root", "-r", "-c", "HEAD"], execOpts) - .then(({ stdout }) => { - const manifests = stdout.split("\n").filter((fp) => path.basename(fp) === "package.json"); - const locations = new Set(manifests.map((fp) => path.join(rootPath, path.dirname(fp)))); - - return Array.from(packageGraph.values()).filter((node) => locations.has(node.location)); - }); -} diff --git a/commands/publish/lib/get-two-factor-auth-required.js b/commands/publish/lib/get-two-factor-auth-required.js deleted file mode 100644 index 986dea8324..0000000000 --- a/commands/publish/lib/get-two-factor-auth-required.js +++ /dev/null @@ -1,55 +0,0 @@ -"use strict"; - -const { ValidationError } = require("@lerna/validation-error"); -const { getFetchConfig } = require("./fetch-config"); -const { getProfileData } = require("./get-profile-data"); - -module.exports.getTwoFactorAuthRequired = getTwoFactorAuthRequired; - -/** - * Determine if the logged-in user has enabled two-factor auth. - * @param {import("./fetch-config").FetchConfig} options - * @returns {Promise} - */ -function getTwoFactorAuthRequired(options) { - const opts = getFetchConfig(options, { - // don't wait forever for third-party failures to be dealt with - fetchRetries: 0, - }); - - opts.log.info("", "Checking two-factor auth mode"); - - return getProfileData(opts).then(success, failure); - - function success(result) { - opts.log.silly("2FA", result.tfa); - - if (result.tfa.pending) { - // if 2FA is pending, it is disabled - return false; - } - - return result.tfa.mode === "auth-and-writes"; - } - - function failure(err) { - // pass if registry does not support profile endpoint - if (err.code === "E500" || err.code === "E404") { - // most likely a private registry (npm Enterprise, verdaccio, etc) - opts.log.warn( - "EREGISTRY", - `Registry "${opts.registry}" does not support 'npm profile get', skipping two-factor auth check...` - ); - - // don't log redundant errors - return false; - } - - // Log the error cleanly to stderr - opts.log.pause(); - console.error(err.message); // eslint-disable-line no-console - opts.log.resume(); - - throw new ValidationError("ETWOFACTOR", "Unable to obtain two-factor auth mode"); - } -} diff --git a/commands/publish/lib/get-unpublished-packages.js b/commands/publish/lib/get-unpublished-packages.js deleted file mode 100644 index 156febba64..0000000000 --- a/commands/publish/lib/get-unpublished-packages.js +++ /dev/null @@ -1,39 +0,0 @@ -"use strict"; - -const log = require("npmlog"); -const pMap = require("p-map"); -const pacote = require("pacote"); - -module.exports.getUnpublishedPackages = getUnpublishedPackages; - -/** - * Retrieve a list of graph nodes for packages that need to be published. - * @param {import("@lerna/package-graph").PackageGraph} packageGraph - * @param {import("./fetch-config").FetchConfig} opts - * @returns {Promise} - */ -function getUnpublishedPackages(packageGraph, opts) { - log.silly("getUnpublishedPackages"); - - let chain = Promise.resolve(); - - // don't bother attempting to get the packument for private packages - const graphNodesToCheck = Array.from(packageGraph.values()).filter(({ pkg }) => !pkg.private); - - const mapper = (pkg) => - pacote.packument(pkg.name, opts).then( - (packument) => { - if (packument.versions === undefined || packument.versions[pkg.version] === undefined) { - return pkg; - } - }, - () => { - log.warn("", "Unable to determine published version, assuming %j unpublished.", pkg.name); - return pkg; - } - ); - - chain = chain.then(() => pMap(graphNodesToCheck, mapper, { concurrency: 4 })); - - return chain.then((results) => results.filter(Boolean)); -} diff --git a/commands/publish/lib/get-whoami.js b/commands/publish/lib/get-whoami.js deleted file mode 100644 index 4c9d30e07e..0000000000 --- a/commands/publish/lib/get-whoami.js +++ /dev/null @@ -1,27 +0,0 @@ -"use strict"; - -const fetch = require("npm-registry-fetch"); -const { pulseTillDone } = require("@lerna/pulse-till-done"); - -module.exports.getWhoAmI = getWhoAmI; - -/** - * Retrieve logged-in user's username via legacy API. - * @param {import("./fetch-config").FetchConfig} opts - * @returns {WhoIAm} - */ -function getWhoAmI(opts) { - opts.log.verbose("", "Retrieving npm username"); - - return pulseTillDone(fetch.json("/-/whoami", opts)).then((data) => { - opts.log.silly("npm whoami", "received %j", data); - - // { username: String } - return data; - }); -} - -/** - * @typedef {object} WhoIAm - * @property {string} username - */ diff --git a/commands/publish/lib/git-checkout.js b/commands/publish/lib/git-checkout.js deleted file mode 100644 index 303e43e58f..0000000000 --- a/commands/publish/lib/git-checkout.js +++ /dev/null @@ -1,20 +0,0 @@ -"use strict"; - -const log = require("npmlog"); -const childProcess = require("@lerna/child-process"); - -module.exports.gitCheckout = gitCheckout; - -/** - * Reset files modified by publish steps. - * @param {string[]} stagedFiles - * @param {{ granularPathspec: boolean; }} gitOpts - * @param {import("@lerna/child-process").ExecOpts} execOpts - */ -function gitCheckout(stagedFiles, gitOpts, execOpts) { - const files = gitOpts.granularPathspec ? stagedFiles : "."; - - log.silly("gitCheckout", files); - - return childProcess.exec("git", ["checkout", "--"].concat(files), execOpts); -} diff --git a/commands/publish/lib/remove-temp-licenses.js b/commands/publish/lib/remove-temp-licenses.js deleted file mode 100644 index 2644c8c7a8..0000000000 --- a/commands/publish/lib/remove-temp-licenses.js +++ /dev/null @@ -1,18 +0,0 @@ -"use strict"; - -const fs = require("fs-extra"); -const pMap = require("p-map"); - -module.exports.removeTempLicenses = removeTempLicenses; - -/** - * Remove temporary license files. - * @param {Package[]} packagesToBeLicensed - */ -function removeTempLicenses(packagesToBeLicensed) { - if (!packagesToBeLicensed.length) { - return Promise.resolve(); - } - - return pMap(packagesToBeLicensed, (pkg) => fs.remove(pkg.licensePath)); -} diff --git a/commands/publish/lib/verify-npm-package-access.js b/commands/publish/lib/verify-npm-package-access.js deleted file mode 100644 index 97e8a000ce..0000000000 --- a/commands/publish/lib/verify-npm-package-access.js +++ /dev/null @@ -1,69 +0,0 @@ -"use strict"; - -const access = require("libnpmaccess"); -const { pulseTillDone } = require("@lerna/pulse-till-done"); -const { ValidationError } = require("@lerna/validation-error"); -const { getFetchConfig } = require("./fetch-config"); - -module.exports.verifyNpmPackageAccess = verifyNpmPackageAccess; - -/** - * Throw an error if the logged-in user does not have read-write access to all packages. - * @param {{ name: string; }[]} packages - * @param {string} username - * @param {import("./fetch-config").FetchConfig} options - * @returns {Promise} - */ -function verifyNpmPackageAccess(packages, username, options) { - const opts = getFetchConfig(options, { - // don't wait forever for third-party failures to be dealt with - fetchRetries: 0, - }); - - opts.log.silly("verifyNpmPackageAccess"); - - return pulseTillDone(access.lsPackages(username, opts)).then(success, failure); - - function success(result) { - // when _no_ results received, access.lsPackages returns null - // we can only assume that the packages in question have never been published - if (result === null) { - opts.log.warn( - "", - "The logged-in user does not have any previously-published packages, skipping permission checks..." - ); - } else { - for (const pkg of packages) { - if (pkg.name in result && result[pkg.name] !== "read-write") { - throw new ValidationError( - "EACCESS", - `You do not have write permission required to publish "${pkg.name}"` - ); - } - } - } - } - - function failure(err) { - // pass if registry does not support ls-packages endpoint - if (err.code === "E500" || err.code === "E404") { - // most likely a private registry (npm Enterprise, verdaccio, etc) - opts.log.warn( - "EREGISTRY", - "Registry %j does not support `npm access ls-packages`, skipping permission checks...", - // registry - opts.registry - ); - - // don't log redundant errors - return; - } - - // Log the error cleanly to stderr - opts.log.pause(); - console.error(err.message); // eslint-disable-line no-console - opts.log.resume(); - - throw new ValidationError("EWHOAMI", "Authentication error. Use `npm whoami` to troubleshoot."); - } -} diff --git a/commands/publish/package.json b/commands/publish/package.json deleted file mode 100644 index aee3a32d89..0000000000 --- a/commands/publish/package.json +++ /dev/null @@ -1,67 +0,0 @@ -{ - "name": "@lerna/publish", - "version": "6.4.1", - "description": "Publish packages in the current project", - "keywords": [ - "lerna", - "command" - ], - "homepage": "https://lerna.js.org", - "license": "MIT", - "author": { - "name": "Daniel Stockman", - "url": "https://github.com/evocateur" - }, - "files": [ - "command.js", - "index.js", - "lib", - "!lib/__mocks__" - ], - "main": "index.js", - "engines": { - "node": "^14.15.0 || >=16.0.0" - }, - "publishConfig": { - "access": "public" - }, - "repository": { - "type": "git", - "url": "git+https://github.com/lerna/lerna.git", - "directory": "commands/publish" - }, - "scripts": { - "test": "echo \"Run tests from root\" && exit 1", - "work": "sleep 3 && echo publish && exit 1" - }, - "dependencies": { - "@lerna/check-working-tree": "file:../../utils/check-working-tree", - "@lerna/child-process": "file:../../core/child-process", - "@lerna/collect-updates": "file:../../utils/collect-updates", - "@lerna/command": "file:../../core/command", - "@lerna/describe-ref": "file:../../utils/describe-ref", - "@lerna/log-packed": "file:../../utils/log-packed", - "@lerna/npm-conf": "file:../../utils/npm-conf", - "@lerna/npm-dist-tag": "file:../../utils/npm-dist-tag", - "@lerna/npm-publish": "file:../../utils/npm-publish", - "@lerna/otplease": "file:../../core/otplease", - "@lerna/output": "file:../../utils/output", - "@lerna/pack-directory": "file:../../utils/pack-directory", - "@lerna/prerelease-id-from-version": "file:../../utils/prerelease-id-from-version", - "@lerna/prompt": "file:../../core/prompt", - "@lerna/pulse-till-done": "file:../../utils/pulse-till-done", - "@lerna/run-lifecycle": "file:../../utils/run-lifecycle", - "@lerna/run-topologically": "file:../../utils/run-topologically", - "@lerna/validation-error": "file:../../core/validation-error", - "@lerna/version": "file:../version", - "fs-extra": "^9.1.0", - "libnpmaccess": "^6.0.3", - "npm-package-arg": "8.1.1", - "npm-registry-fetch": "^13.3.0", - "npmlog": "^6.0.2", - "p-map": "^4.0.0", - "p-pipe": "^3.1.0", - "pacote": "^13.6.1", - "semver": "^7.3.4" - } -} diff --git a/commands/run/CHANGELOG.md b/commands/run/CHANGELOG.md deleted file mode 100644 index d4d4bc1610..0000000000 --- a/commands/run/CHANGELOG.md +++ /dev/null @@ -1,538 +0,0 @@ -# Change Log - -All notable changes to this project will be documented in this file. -See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. - -## [6.4.1](https://github.com/lerna/lerna/compare/v6.4.0...v6.4.1) (2023-01-12) - -### Bug Fixes - -- **run:** resolve erroneous failures ([#3495](https://github.com/lerna/lerna/issues/3495)) ([24d0d5c](https://github.com/lerna/lerna/commit/24d0d5c43b857f8da0d2e06b76bb3ee79fda51ff)) - -# [6.4.0](https://github.com/lerna/lerna/compare/v6.3.0...v6.4.0) (2023-01-05) - -### Bug Fixes - -- **run:** add explicit nx dependency ([#3486](https://github.com/lerna/lerna/issues/3486)) ([7e39397](https://github.com/lerna/lerna/commit/7e3939780df597ba6f1f0352299c2b5e77c7e824)) - -# [6.3.0](https://github.com/lerna/lerna/compare/v6.2.0...v6.3.0) (2022-12-26) - -**Note:** Version bump only for package @lerna/run - -# [6.2.0](https://github.com/lerna/lerna/compare/v6.1.0...v6.2.0) (2022-12-13) - -**Note:** Version bump only for package @lerna/run - -# [6.1.0](https://github.com/lerna/lerna/compare/v6.0.3...v6.1.0) (2022-11-29) - -### Bug Fixes - -- **run:** detect target configuration in package.json files ([#3432](https://github.com/lerna/lerna/issues/3432)) ([798aae1](https://github.com/lerna/lerna/commit/798aae14656c9fbbde62bd941fe3a11450112f3b)) - -## [6.0.3](https://github.com/lerna/lerna/compare/v6.0.2...v6.0.3) (2022-11-07) - -**Note:** Version bump only for package @lerna/run - -## [6.0.2](https://github.com/lerna/lerna/compare/v6.0.1...v6.0.2) (2022-11-02) - -**Note:** Version bump only for package @lerna/run - -## [6.0.1](https://github.com/lerna/lerna/compare/v6.0.0...v6.0.1) (2022-10-14) - -### Bug Fixes - -- **run:** allow for loading of env files to be skipped ([#3375](https://github.com/lerna/lerna/issues/3375)) ([5dbd904](https://github.com/lerna/lerna/commit/5dbd904009ede4cc952fc7f8cbafebf6b12d81a1)) - -# [6.0.0](https://github.com/lerna/lerna/compare/v6.0.0-alpha.2...v6.0.0) (2022-10-12) - -**Note:** Version bump only for package @lerna/run - -# [6.0.0-alpha.2](https://github.com/lerna/lerna/compare/v6.0.0-alpha.1...v6.0.0-alpha.2) (2022-10-12) - -### Bug Fixes - -- **run:** update docs for v6 ([#3366](https://github.com/lerna/lerna/issues/3366)) ([130f490](https://github.com/lerna/lerna/commit/130f4906bee3e240ea9ad9245dfb0fe208668dae)) - -# [6.0.0-alpha.1](https://github.com/lerna/lerna/compare/v5.6.2...v6.0.0-alpha.1) (2022-10-09) - -# [6.0.0-alpha.0](https://github.com/lerna/lerna/compare/v5.6.1...v6.0.0-alpha.0) (2022-10-07) - -**Note:** Version bump only for package @lerna/run - -## [5.6.2](https://github.com/lerna/lerna/compare/v5.6.1...v5.6.2) (2022-10-09) - -**Note:** Version bump only for package @lerna/run - -## [5.6.1](https://github.com/lerna/lerna/compare/v5.6.0...v5.6.1) (2022-09-30) - -**Note:** Version bump only for package @lerna/run - -# [5.6.0](https://github.com/lerna/lerna/compare/v5.5.4...v5.6.0) (2022-09-29) - -### Bug Fixes - -- **run:** only defer to Nx when targetDefaults are defined in nx.json ([#3349](https://github.com/lerna/lerna/issues/3349)) ([51f80d9](https://github.com/lerna/lerna/commit/51f80d901fceb285677bd55ef2a456f3fb264c13)) - -## [5.5.4](https://github.com/lerna/lerna/compare/v5.5.3...v5.5.4) (2022-09-28) - -**Note:** Version bump only for package @lerna/run - -## [5.5.3](https://github.com/lerna/lerna/compare/v5.5.2...v5.5.3) (2022-09-28) - -### Bug Fixes - -- **run:** fully defer to Nx for dep detection when nx.json exists ([#3345](https://github.com/lerna/lerna/issues/3345)) ([fef2ae6](https://github.com/lerna/lerna/commit/fef2ae6c13b35330b2367d89a63e539f2646f04e)) - -## [5.5.2](https://github.com/lerna/lerna/compare/v5.5.1...v5.5.2) (2022-09-20) - -### Bug Fixes - -- **run:** missing `fs-extra` dependency declaration ([#3332](https://github.com/lerna/lerna/issues/3332)) ([068830e](https://github.com/lerna/lerna/commit/068830e95f0552a33db3ea678092134372a40af1)) -- **run:** warn on incompatible arguments with useNx ([#3326](https://github.com/lerna/lerna/issues/3326)) ([ebf6542](https://github.com/lerna/lerna/commit/ebf654240aa1c0c67d7f1ba5dec458c14edd5c32)) - -## [5.5.1](https://github.com/lerna/lerna/compare/v5.5.0...v5.5.1) (2022-09-09) - -### Bug Fixes - -- **run:** exclude dependencies with --scope when nx.json is not present ([#3316](https://github.com/lerna/lerna/issues/3316)) ([99a13a9](https://github.com/lerna/lerna/commit/99a13a9bae2020f2773d21c4109148a59b1ec2d6)) - -# [5.5.0](https://github.com/lerna/lerna/compare/v5.4.3...v5.5.0) (2022-08-31) - -### Features - -- pnpm workspaces support ([#3284](https://github.com/lerna/lerna/issues/3284)) ([1b18dbe](https://github.com/lerna/lerna/commit/1b18dbeb03e98c70b5428a9fe457781a59f8d65d)) - -## [5.4.3](https://github.com/lerna/lerna/compare/v5.4.2...v5.4.3) (2022-08-16) - -**Note:** Version bump only for package @lerna/run - -## [5.4.2](https://github.com/lerna/lerna/compare/v5.4.1...v5.4.2) (2022-08-14) - -**Note:** Version bump only for package @lerna/run - -## [5.4.1](https://github.com/lerna/lerna/compare/v5.4.0...v5.4.1) (2022-08-12) - -**Note:** Version bump only for package @lerna/run - -# [5.4.0](https://github.com/lerna/lerna/compare/v5.3.0...v5.4.0) (2022-08-08) - -**Note:** Version bump only for package @lerna/run - -# [5.3.0](https://github.com/lerna/lerna/compare/v5.2.0...v5.3.0) (2022-07-27) - -**Note:** Version bump only for package @lerna/run - -# [5.2.0](https://github.com/lerna/lerna/compare/v5.1.8...v5.2.0) (2022-07-22) - -### Features - -- **init:** default useNx and useWorkspaces to true for new lerna workspaces ([#3255](https://github.com/lerna/lerna/issues/3255)) ([a0e83e5](https://github.com/lerna/lerna/commit/a0e83e5220f6e3d30b96b60bbaf14c5392653c2e)) - -## [5.1.8](https://github.com/lerna/lerna/compare/v5.1.7...v5.1.8) (2022-07-07) - -**Note:** Version bump only for package @lerna/run - -## [5.1.7](https://github.com/lerna/lerna/compare/v5.1.6...v5.1.7) (2022-07-06) - -### Bug Fixes - -- **run:** add double quotes around script target containing colon ([#3218](https://github.com/lerna/lerna/issues/3218)) ([ead461e](https://github.com/lerna/lerna/commit/ead461eba284d8d2efb0da3f18ce87fb5ae42bd2)) - -## [5.1.6](https://github.com/lerna/lerna/compare/v5.1.5...v5.1.6) (2022-06-24) - -### Bug Fixes - -- lerna run parallel should maximize concurrency with useNx ([#3205](https://github.com/lerna/lerna/issues/3205)) ([f80d03c](https://github.com/lerna/lerna/commit/f80d03c17b06146b097f904ee066728d6580090d)) - -## [5.1.5](https://github.com/lerna/lerna/compare/v5.1.4...v5.1.5) (2022-06-24) - -**Note:** Version bump only for package @lerna/run - -## [5.1.4](https://github.com/lerna/lerna/compare/v5.1.3...v5.1.4) (2022-06-15) - -### Bug Fixes - -- correctly detect if target dependencies are set ([5845f6b](https://github.com/lerna/lerna/commit/5845f6bf53fd562978fd0ee2265a9ec602b4c335)) - -## [5.1.3](https://github.com/lerna/lerna/compare/v5.1.2...v5.1.3) (2022-06-15) - -**Note:** Version bump only for package @lerna/run - -## [5.1.2](https://github.com/lerna/lerna/compare/v5.1.1...v5.1.2) (2022-06-13) - -**Note:** Version bump only for package @lerna/run - -## [5.1.1](https://github.com/lerna/lerna/compare/v5.1.0...v5.1.1) (2022-06-09) - -### Bug Fixes - -- allow maintenance LTS node 14 engines starting at 14.15.0 ([#3161](https://github.com/lerna/lerna/issues/3161)) ([72305e4](https://github.com/lerna/lerna/commit/72305e4dbab607a2d87ae4efa6ee577c93a9dda9)) - -# [5.1.0](https://github.com/lerna/lerna/compare/v5.0.0...v5.1.0) (2022-06-07) - -### Features - -- add experimental support to run tasks via Nx ([1c35828](https://github.com/lerna/lerna/commit/1c358286c8425d1720580859c4b42e15a3b15eac)) -- handle the edge cases in the lerna-nx integration ([c6808fc](https://github.com/lerna/lerna/commit/c6808fc8f2dfe793bf72a64cf2d3909e0bdabba8)) - -# [5.1.0-alpha.0](https://github.com/lerna/lerna/compare/v4.0.0...v5.1.0-alpha.0) (2022-05-25) - -### Features - -- add experimental support to run tasks via Nx ([1c35828](https://github.com/lerna/lerna/commit/1c358286c8425d1720580859c4b42e15a3b15eac)) - -# [5.0.0](https://github.com/lerna/lerna/compare/v4.0.0...v5.0.0) (2022-05-24) - -**Note:** Version bump only for package @lerna/run - -# [4.0.0](https://github.com/lerna/lerna/compare/v3.22.1...v4.0.0) (2021-02-10) - -### Features - -- Consume named exports of sibling modules ([63499e3](https://github.com/lerna/lerna/commit/63499e33652bc78fe23751875d74017e2f16a689)) -- **deps:** execa@^4.1.0 ([9051dca](https://github.com/lerna/lerna/commit/9051dcab1a68b56db09b82ab0345c5f36bcfee2d)) -- **deps:** p-map@^4.0.0 ([92b1364](https://github.com/lerna/lerna/commit/92b1364735e1f2cf379cf1047c60c4fb897d55f5)) -- Drop support for Node v6.x & v8.x ([ff4bb4d](https://github.com/lerna/lerna/commit/ff4bb4da215555e3bb136f5af09b5cbc631e57bb)) - -### BREAKING CHANGES - -- Node v6.x & v8.x are no longer supported. Please upgrade to the latest LTS release. - -Here's the gnarly one-liner I used to make these changes: - -``` -npx lerna exec --concurrency 1 --stream -- 'json -I -f package.json -e '"'"'this.engines=this.engines||{};this.engines.node=">= 10.18.0"'"'" -``` - -(requires `npm i -g json` beforehand) - -# [3.21.0](https://github.com/lerna/lerna/compare/v3.20.2...v3.21.0) (2020-05-13) - -**Note:** Version bump only for package @lerna/run - -# [3.20.0](https://github.com/lerna/lerna/compare/v3.19.0...v3.20.0) (2019-12-27) - -### Bug Fixes - -- **collect-dependents:** Avoid skipping dependents of cyclic dependencies ([#2380](https://github.com/lerna/lerna/issues/2380)) ([bd19a34](https://github.com/lerna/lerna/commit/bd19a34debf3344e94386b4ffd4b3fe87efb4641)) - -### Features - -- Add `--profile` option to `lerna exec` and `lerna run` ([#2376](https://github.com/lerna/lerna/issues/2376)) ([6290174](https://github.com/lerna/lerna/commit/62901748f818516d58efdfd955eacb447e270351)) - -## [3.18.5](https://github.com/lerna/lerna/compare/v3.18.4...v3.18.5) (2019-11-20) - -**Note:** Version bump only for package @lerna/run - -## [3.18.4](https://github.com/lerna/lerna/compare/v3.18.3...v3.18.4) (2019-11-08) - -### Bug Fixes - -- **filter-options:** Ensure `--include-merged-tags` is available to all `--since`-filterable commands ([287bcd8](https://github.com/lerna/lerna/commit/287bcd8b5c8dbb2dc4def5c933d0b4917c34813e)), closes [#2332](https://github.com/lerna/lerna/issues/2332) - -# [3.18.0](https://github.com/lerna/lerna/compare/v3.17.0...v3.18.0) (2019-10-15) - -### Features - -- Upgrade to yargs@14 ([5e60213](https://github.com/lerna/lerna/commit/5e60213e93e3ee229a9341a14e420ed2401001dd)) - -## [3.16.5](https://github.com/lerna/lerna/compare/v3.16.4...v3.16.5) (2019-10-07) - -**Note:** Version bump only for package @lerna/run - -# [3.16.0](https://github.com/lerna/lerna/compare/v3.15.0...v3.16.0) (2019-07-18) - -### Bug Fixes - -- **package-graph:** Flatten cycles to avoid skipping packages ([#2185](https://github.com/lerna/lerna/issues/2185)) ([b335763](https://github.com/lerna/lerna/commit/b335763)) - -### Features - -- **deps:** `p-map@^2.1.0` ([9e58394](https://github.com/lerna/lerna/commit/9e58394)) - -# [3.15.0](https://github.com/lerna/lerna/compare/v3.14.2...v3.15.0) (2019-06-09) - -**Note:** Version bump only for package @lerna/run - -## [3.14.2](https://github.com/lerna/lerna/compare/v3.14.1...v3.14.2) (2019-06-09) - -**Note:** Version bump only for package @lerna/run - -# [3.14.0](https://github.com/lerna/lerna/compare/v3.13.4...v3.14.0) (2019-05-14) - -### Features - -- **run:** Add just-in-time queue management ([#2045](https://github.com/lerna/lerna/issues/2045)) ([6eca172](https://github.com/lerna/lerna/commit/6eca172)) -- **run:** Extract `@lerna/run-topologically` ([3a8b175](https://github.com/lerna/lerna/commit/3a8b175)) - -## [3.13.3](https://github.com/lerna/lerna/compare/v3.13.2...v3.13.3) (2019-04-17) - -**Note:** Version bump only for package @lerna/run - -## [3.13.1](https://github.com/lerna/lerna/compare/v3.13.0...v3.13.1) (2019-02-26) - -**Note:** Version bump only for package @lerna/run - -# [3.13.0](https://github.com/lerna/lerna/compare/v3.12.1...v3.13.0) (2019-02-15) - -### Features - -- **meta:** Add `repository.directory` field to package.json ([aec5023](https://github.com/lerna/lerna/commit/aec5023)) -- **meta:** Normalize package.json `homepage` field ([abeb4dc](https://github.com/lerna/lerna/commit/abeb4dc)) - -## [3.12.1](https://github.com/lerna/lerna/compare/v3.12.0...v3.12.1) (2019-02-14) - -**Note:** Version bump only for package @lerna/run - -# [3.12.0](https://github.com/lerna/lerna/compare/v3.11.1...v3.12.0) (2019-02-14) - -**Note:** Version bump only for package @lerna/run - -# [3.11.0](https://github.com/lerna/lerna/compare/v3.10.8...v3.11.0) (2019-02-08) - -**Note:** Version bump only for package @lerna/run - -## [3.10.6](https://github.com/lerna/lerna/compare/v3.10.5...v3.10.6) (2019-01-19) - -### Bug Fixes - -- **options:** Document negated boolean options explicitly ([8bc9669](https://github.com/lerna/lerna/commit/8bc9669)) -- **run:** Re-order --npm-client in help output ([bfa89bf](https://github.com/lerna/lerna/commit/bfa89bf)) - -## [3.10.1](https://github.com/lerna/lerna/compare/v3.10.0...v3.10.1) (2019-01-09) - -**Note:** Version bump only for package @lerna/run - -# [3.10.0](https://github.com/lerna/lerna/compare/v3.9.1...v3.10.0) (2019-01-08) - -**Note:** Version bump only for package @lerna/run - -# [3.9.0](https://github.com/lerna/lerna/compare/v3.8.5...v3.9.0) (2019-01-08) - -**Note:** Version bump only for package @lerna/run - -## [3.8.5](https://github.com/lerna/lerna/compare/v3.8.4...v3.8.5) (2019-01-05) - -**Note:** Version bump only for package @lerna/run - -## [3.8.1](https://github.com/lerna/lerna/compare/v3.8.0...v3.8.1) (2018-12-31) - -**Note:** Version bump only for package @lerna/run - -## [3.7.2](https://github.com/lerna/lerna/compare/v3.7.1...v3.7.2) (2018-12-21) - -**Note:** Version bump only for package @lerna/run - -## [3.7.1](https://github.com/lerna/lerna/compare/v3.7.0...v3.7.1) (2018-12-20) - -**Note:** Version bump only for package @lerna/run - -# [3.7.0](https://github.com/lerna/lerna/compare/v3.6.0...v3.7.0) (2018-12-19) - -**Note:** Version bump only for package @lerna/run - -# [3.6.0](https://github.com/lerna/lerna/compare/v3.5.1...v3.6.0) (2018-12-07) - -**Note:** Version bump only for package @lerna/run - -# [3.5.0](https://github.com/lerna/lerna/compare/v3.4.3...v3.5.0) (2018-11-27) - -### Features - -- **run:** Log package name and timing in runScriptInPackageCapturing ([#1781](https://github.com/lerna/lerna/issues/1781)) ([b69a728](https://github.com/lerna/lerna/commit/b69a728)) - - - -## [3.3.2](https://github.com/lerna/lerna/compare/v3.3.1...v3.3.2) (2018-09-12) - -**Note:** Version bump only for package @lerna/run - - - -# [3.3.0](https://github.com/lerna/lerna/compare/v3.2.1...v3.3.0) (2018-09-06) - -### Bug Fixes - -- Propagate exit codes from failed executions ([af9c70b](https://github.com/lerna/lerna/commit/af9c70b)), closes [#1374](https://github.com/lerna/lerna/issues/1374) [#1653](https://github.com/lerna/lerna/issues/1653) - - - -## [3.1.3](https://github.com/lerna/lerna/compare/v3.1.2...v3.1.3) (2018-08-21) - -**Note:** Version bump only for package @lerna/run - - - -## [3.1.2](https://github.com/lerna/lerna/compare/v3.1.1...v3.1.2) (2018-08-20) - -### Bug Fixes - -- Setup instance.filteredPackages explicitly ([32357f8](https://github.com/lerna/lerna/commit/32357f8)) - - - -# [3.1.0](https://github.com/lerna/lerna/compare/v3.0.6...v3.1.0) (2018-08-17) - -**Note:** Version bump only for package @lerna/run - - - -## [3.0.6](https://github.com/lerna/lerna/compare/v3.0.5...v3.0.6) (2018-08-16) - -**Note:** Version bump only for package @lerna/run - - - -## [3.0.5](https://github.com/lerna/lerna/compare/v3.0.4...v3.0.5) (2018-08-15) - -**Note:** Version bump only for package @lerna/run - - - -## [3.0.2](https://github.com/lerna/lerna/compare/v3.0.1...v3.0.2) (2018-08-11) - -### Bug Fixes - -- **run:** Allow config files to override defaults ([f15b6fb](https://github.com/lerna/lerna/commit/f15b6fb)) - - - -# [3.0.0](https://github.com/lerna/lerna/compare/v3.0.0-rc.0...v3.0.0) (2018-08-10) - -**Note:** Version bump only for package @lerna/run - - - -# [3.0.0-rc.0](https://github.com/lerna/lerna/compare/v3.0.0-beta.21...v3.0.0-rc.0) (2018-07-27) - -### Features - -- Add description from --help summary [skip ci] ([9b65d8e](https://github.com/lerna/lerna/commit/9b65d8e)) -- **cli:** Upgrade to Yargs 12 ([7899ab8](https://github.com/lerna/lerna/commit/7899ab8)) -- **command:** Remove .defaultOptions() from option resolution stack ([2b27a54](https://github.com/lerna/lerna/commit/2b27a54)) -- Count packages affected in command summary logging ([5f5e585](https://github.com/lerna/lerna/commit/5f5e585)) - - - -# [3.0.0-beta.21](https://github.com/lerna/lerna/compare/v3.0.0-beta.20...v3.0.0-beta.21) (2018-05-12) - -### Bug Fixes - -- **child-process:** Prevent duplicate logs when any package-oriented execution fails ([d3a8128](https://github.com/lerna/lerna/commit/d3a8128)) - - - -# [3.0.0-beta.20](https://github.com/lerna/lerna/compare/v3.0.0-beta.19...v3.0.0-beta.20) (2018-05-07) - -**Note:** Version bump only for package @lerna/run - - - -# [3.0.0-beta.19](https://github.com/lerna/lerna/compare/v3.0.0-beta.18...v3.0.0-beta.19) (2018-05-03) - -**Note:** Version bump only for package @lerna/run - - - -# [3.0.0-beta.18](https://github.com/lerna/lerna/compare/v3.0.0-beta.17...v3.0.0-beta.18) (2018-04-24) - -**Note:** Version bump only for package @lerna/run - - - -# [3.0.0-beta.17](https://github.com/lerna/lerna/compare/v3.0.0-beta.16...v3.0.0-beta.17) (2018-04-13) - -**Note:** Version bump only for package @lerna/run - - - -# [3.0.0-beta.15](https://github.com/lerna/lerna/compare/v3.0.0-beta.14...v3.0.0-beta.15) (2018-04-09) - -**Note:** Version bump only for package @lerna/run - - - -# [3.0.0-beta.14](https://github.com/lerna/lerna/compare/v3.0.0-beta.13...v3.0.0-beta.14) (2018-04-03) - -### Bug Fixes - -- **logging:** Log failures from package scripts once, not twice ([436cfe1](https://github.com/lerna/lerna/commit/436cfe1)) - - - -# [3.0.0-beta.13](https://github.com/lerna/lerna/compare/v3.0.0-beta.12...v3.0.0-beta.13) (2018-03-31) - -### Bug Fixes - -- Use ValidationError instead of Error ([bea6bc3](https://github.com/lerna/lerna/commit/bea6bc3)) -- **run:** Exit early when no packages contain the targeted lifecycle ([c8a5526](https://github.com/lerna/lerna/commit/c8a5526)) - -### Features - -- Enable progress bars only when necessary ([b766c83](https://github.com/lerna/lerna/commit/b766c83)) - - - -# [3.0.0-beta.12](https://github.com/lerna/lerna/compare/v3.0.0-beta.11...v3.0.0-beta.12) (2018-03-30) - -### Features - -- Add --no-prefix for streaming output ([#1352](https://github.com/lerna/lerna/issues/1352)) ([36c1fad](https://github.com/lerna/lerna/commit/36c1fad)) - - - -# [3.0.0-beta.11](https://github.com/lerna/lerna/compare/v3.0.0-beta.10...v3.0.0-beta.11) (2018-03-29) - -### Features - -- **run:** Add --no-bail option ([893fcc8](https://github.com/lerna/lerna/commit/893fcc8)), closes [#1351](https://github.com/lerna/lerna/issues/1351) - - - -# [3.0.0-beta.10](https://github.com/lerna/lerna/compare/v3.0.0-beta.9...v3.0.0-beta.10) (2018-03-27) - -### Features - -- **commands:** Delay require of command instantiation ([a1284f3](https://github.com/lerna/lerna/commit/a1284f3)) - -### BREAKING CHANGES - -- **commands:** The default export of command packages is now a factory, not the subclass (which is now a named export). - - - -# [3.0.0-beta.9](https://github.com/lerna/lerna/compare/v3.0.0-beta.8...v3.0.0-beta.9) (2018-03-24) - -**Note:** Version bump only for package @lerna/run - - - -# [3.0.0-beta.7](https://github.com/lerna/lerna/compare/v3.0.0-beta.6...v3.0.0-beta.7) (2018-03-20) - -**Note:** Version bump only for package @lerna/run - - - -# [3.0.0-beta.4](https://github.com/lerna/lerna/compare/v3.0.0-beta.3...v3.0.0-beta.4) (2018-03-19) - -**Note:** Version bump only for package @lerna/run - - - -# [3.0.0-beta.3](https://github.com/lerna/lerna/compare/v3.0.0-beta.2...v3.0.0-beta.3) (2018-03-15) - -**Note:** Version bump only for package @lerna/run - - - -# [3.0.0-beta.2](https://github.com/lerna/lerna/compare/v3.0.0-beta.1...v3.0.0-beta.2) (2018-03-10) - -**Note:** Version bump only for package @lerna/run - - - -# [3.0.0-beta.1](https://github.com/lerna/lerna/compare/v3.0.0-beta.0...v3.0.0-beta.1) (2018-03-09) - -### Bug Fixes - -- **filter-options:** require a git repo when using --since ([d21b66e](https://github.com/lerna/lerna/commit/d21b66e)), closes [#822](https://github.com/lerna/lerna/issues/822) diff --git a/commands/run/README.md b/commands/run/README.md deleted file mode 100644 index 4e1553d012..0000000000 --- a/commands/run/README.md +++ /dev/null @@ -1,122 +0,0 @@ -# `@lerna/run` - -> Run an npm script in each package that contains that script - -Install [lerna](https://www.npmjs.com/package/lerna) for access to the `lerna` CLI. - -## Usage - -```sh -$ lerna run