ember-cli / ember-cli

The Ember.js command line utility.
https://cli.emberjs.com
MIT License
3.26k stars 1.16k forks source link

Can not generate a new project if ember-cli is installed in yarn workspace #9328

Open jelhan opened 4 years ago

jelhan commented 4 years ago

Ember CLI wrongly assumes being inside an Ember CLI project if ember-cli is installed in yarn workspace. When running ember new <app-name> and ember addon <addon-name> it throws You cannot use the new/addon command inside an ember-cli project.

Use case

Installing ember-cli in workspace would have some benefits:

  1. No need to install ember-cli globally or to use npx to create new ember projects.
  2. Version used to generate new projects can be controlled per workspace and shared with colleagues.
  3. Generating a new project using an ember-cli installed in workspace is as fast as if using a globally installed version. It's much faster than using npx.

Reproduction

To reproduce create a yarn workspace and install ember-cli in it:

  1. mkdir test-workspace && cd test-workspace/
  2. create package.json with the following content:
    {
      "private": true,
      "workspaces": [
        "packages/*"
      ]
    }5
  3. yarn add -W ember-cli
  4. mkdir packages

Running ember new test-app or ember new test-addon in ./packages fails:

$ ember new test-project
You cannot use the new command inside an ember-cli project.

$ ember addon test-project
You cannot use the addon command inside an ember-cli project.

Debug

The assertion is thrown here: https://github.com/ember-cli/ember-cli/blob/627934f91b2aa0e19b041fdb1b547873c1855793/lib/models/command.js#L279-L281

The isWithinProject method of Command is initialized with return value of isEmberCLIProject method of Project: https://github.com/ember-cli/ember-cli/blob/627934f91b2aa0e19b041fdb1b547873c1855793/lib/models/command.js#L86

The isEmberCLIProject method checks if ember-cli is in dependencies: https://github.com/ember-cli/ember-cli/blob/066e9efc9034e8ddde57151ebf76d35398037c20/lib/models/project.js#L187-L197

The dependencies are read by dependencies method: https://github.com/ember-cli/ember-cli/blob/066e9efc9034e8ddde57151ebf76d35398037c20/lib/models/project.js#L355-L374

As no argument is passed it uses pkg property, which is passed in when initializing the Project instance: https://github.com/ember-cli/ember-cli/blob/066e9efc9034e8ddde57151ebf76d35398037c20/lib/models/project.js#L27-L43

If I got the in-source comment right it should only be initialized using the static closestSync method: https://github.com/ember-cli/ember-cli/blob/066e9efc9034e8ddde57151ebf76d35398037c20/lib/models/project.js#L645-L679

That one uses the findupPath function to find a package.json in any parent directory: https://github.com/ember-cli/ember-cli/blob/066e9efc9034e8ddde57151ebf76d35398037c20/lib/models/project.js#L772-L779

findupPath throws if it does not find a package.json. But that should be the expected in most cases. :confused:

jelhan commented 4 years ago

Continued my debugging session and noticed that the Project is not initialized with closestSync method directly but with projectOrnullProject static method: https://github.com/ember-cli/ember-cli/blob/066e9efc9034e8ddde57151ebf76d35398037c20/lib/cli/index.js#L135

It catches the error thrown by findupPath if no package.json is found at all. So maybe modifying findupPath to ignore package.json found if it contains workspaces path might be all what is needed?