Skip to content

Unable to generate a scoped library with v6 rc0 #10172

Closed
angular/devkit
#646

Description

@ocombe

Versions

Angular CLI: 6.0.0-rc.0
Node: 8.9.3
OS: win32 x64
Angular: 6.0.0-rc.1
... animations, common, compiler, compiler-cli, core, forms
... http, language-service, platform-browser
... platform-browser-dynamic, router

@angular/cli: 6.0.0-rc.0
@angular-devkit/architect: 0.0.10
@angular-devkit/build-angular: 0.0.10
@angular-devkit/build-ng-packagr: 0.0.4
@angular-devkit/build-optimizer: 0.4.9
@angular-devkit/core: 0.4.9
@angular-devkit/schematics: 0.5.0
@ngtools/json-schema: 1.1.0
@ngtools/webpack: 6.0.0-beta.9
@schematics/angular: 0.5.0
@schematics/update: 0.5.0
typescript: 2.7.2
webpack: 4.1.0

Repro steps

  • Create a new cli project with ng new xxx
  • cd into the new project
  • Try to generate a library with a scoped name: ng g library @xxx/core

Observed behavior

It throws the following error in the shell:

Could not find an NgModule. Use the skip-import option to skip importing in NgModule.

Desired behavior

It should generate a library named @xxx/core in the folder projects/xxx-core or maybe projects/xxx/core or even projects/core with the correct package name @xxx/core in the package.json file.

If it's not possible, then it should throw an error message that explains that it doesn't support scoped package names.

Activity

  1. added 2 commits that reference this issue on Apr 6, 2018
    8a28fc9
    70595cf
  2. about-code commented on Apr 7, 2018

    @about-code

    I suggest to generate a folder structure where the package name is a correct directory path structure - similar to how scoped packages are installed into the node_modules folder.

    So when generating a scoped package with ng g library @xxx/core where the package name in package.json will be @xxx/core CLI should generate a folder structure

     |-@xxx
        |-core
           |-package.json
    

    Not only would it be compatible with npm layout. It is likely to work better with VSCode's auto-import suggestions. For example consider a monorepo folder structure similar to the Angular repos. You would probably generate a library in the packages folder then.

    ${PROJECT_ROOT}
        |-node_modules
        |-packages
        |    |-@xxx
        |    |    |-core
        |    |       |-package.json
        |    |       |-index.ts
        |    |-@foo
        |    |    |-bar
        |    |       |-src
        |    |           |-Foo.ts
        |    |       |-package.json
        |    |       |-index.ts
        |    |-...
        |-tsconfig.json
    

    Now if you attempt to use a class Foo exported by index.ts of package @foo/bar you ideally want
    VSCode to suggest an absolute import

    import {Foo} from "@foo/bar";

    I've been successful to make this work in VSCode 1.19 but it temporarily stopped working in 1.20 or 1.21 after some refactorings in VSCode. Absolute path imports should be working again with latest VSCode versions and with TS 2.8. once microsoft/TypeScript#22249 is resolved (see also microsoft/vscode#43575)

    VSCode auto-import with absolute paths required some prerequisites in 1.19:

    • @foo/bar must be a valid path in the directory referenced via baseUrl in tsconfig.json
    • @foo/bar must be declared as a dependency in the importing package's package.json (that of @xxx/core)
    • baseUrl and a generic path mapping must be set in tsconfig.json

    Example tsconfig.json

    "baseUrl": "./packages",
    "paths": {
        "*": ["./*", "../node_modules/*"]
    }
    

    Generating the full package name as a directory structure would also make it easier to compile an application from a monorepo structure. For example you could make webpack resolve "@foo/bar" from the packages folder by configuring

    module: { 
         resolve: ["./packages", "./node_modules"]
    }
    

    in your webpack config. Then you can compile and bundle libs in the monorepo into an application without having to link them with npm link at all because TS and webpack can directly resolve them from packages rather than node_modules.

  3. added 4 commits that reference this issue on Apr 9, 2018
    284a7ba
    55413ee
    2f16d7a
    6996de1
  4. added this to the v6.0.0 milestone on Apr 12, 2018
  5. added
    P3An issue that is relevant to core functions, but does not impede progress. Important, but not urgent
    and removed on Apr 12, 2018
  6. gms1 commented on Apr 22, 2018

    @gms1

    Ideally, the directory should be configurable regardless of the package name

    Anyway, @foo/bar is a valid package name and a valid directory subtree. Why is this hocus-pocus with the directory name needed at all?

    see
    Brocco/devkit@6996de1

    +    validateProjectName(options.name);
    +
    +    // If scoped project (i.e. "@foo/bar"), convert projectDir to "foo/bar".
    +    const packageName = options.name;
    +    let scopeName = '';
    +    if (/^@.*\/.*/.test(options.name)) {
    +      const [scope, name] = options.name.split('/');
    +      scopeName = scope.replace(/^@/, '');
    +      options.name = name;
    +    }
    +
    
  7. added a commit that references this issue on Apr 23, 2018
    f6ab37f
  8. 1 remaining item

  9. added 5 commits that reference this issue on Apr 23, 2018
    d218225
    693ec98
    7a0de49
    04df87b
    bbd62fe
  10. added a commit that references this issue on Apr 25, 2018
    62ebcd3
  11. about-code commented on Apr 25, 2018

    @about-code

    @gms1 Brocco has answered the reasoning in one of the commit discussions. They drop the @ because it causes problems with path auto-completion on mac and windows console terminals, which they want to provide to users working a lot on the terminal (or from within VSCode e.g.).

    As far as I understood instead of a generic path mapping (which would be possible when sticking to package name convention) the CLI will generate a path mapping for each lib in tsconfig.json which maps a package import path including the @ onto a filesystem path without the @. So eventually, there will be no difference in how you would import a package in source code. Writing import from "@foo/bar" will work.

  12. about-code commented on Apr 25, 2018

    @about-code
  13. added a commit that references this issue on Jun 6, 2018
    82bf0a4
  14. CharlyRipp commented on Aug 2, 2018

    @CharlyRipp

    I see the logic made it up but I'm unable to generate a new project with a scope:

    ➜ ng new "@foo/bar"
    Schematic input does not validate against the Schema: {"name":"@foo/bar","version":"6.1.2","newProjectRoot":"projects","skipInstall":false,"linkCli":false,"skipGit":false,"commit":null}
    Errors:
    
      Data path ".name" should match format "html-selector".
    

    Is this as expected for now or should I open a separate issue?

    This does however function with ng g library @foo/bar, generating ./projects/foo/bar with a properly scoped package name.

  15. angular-automatic-lock-bot commented on Sep 8, 2019

    @angular-automatic-lock-bot

    This issue has been automatically locked due to inactivity.
    Please file a new issue if you are encountering a similar or related problem.

    Read more about our automatic conversation locking policy.

    This action has been performed automatically by a bot.

  16. locked and limited conversation to collaborators on Sep 8, 2019
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    P3An issue that is relevant to core functions, but does not impede progress. Important, but not urgentseverity3: broken

    Type

    No type

    Projects

    No projects

      Milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions