Skip to content
New issue

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

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

Already on GitHub? Sign in to your account

Unable to generate a scoped library with v6 rc0 #10172

Closed
ocombe opened this issue Apr 4, 2018 · 6 comments · Fixed by angular/devkit#646
Closed

Unable to generate a scoped library with v6 rc0 #10172

ocombe opened this issue Apr 4, 2018 · 6 comments · Fixed by angular/devkit#646
Labels
P3 An issue that is relevant to core functions, but does not impede progress. Important, but not urgent severity3: broken
Milestone

Comments

@ocombe
Copy link
Contributor

ocombe commented Apr 4, 2018

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.

@about-code
Copy link

about-code commented Apr 7, 2018

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.

@hansl hansl added this to the v6.0.0 milestone Apr 12, 2018
@hansl hansl added severity3: broken P3 An issue that is relevant to core functions, but does not impede progress. Important, but not urgent and removed 6.0.0-rc labels Apr 12, 2018
@gms1
Copy link

gms1 commented Apr 22, 2018

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;
+    }
+

hansl pushed a commit to angular/devkit that referenced this issue Apr 25, 2018
@about-code
Copy link

@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.

@about-code
Copy link

@gms1 See here angular/devkit#646 (comment)

@CharlyRipp
Copy link

CharlyRipp commented Aug 2, 2018

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.

@angular-automatic-lock-bot
Copy link

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.

@angular-automatic-lock-bot angular-automatic-lock-bot bot locked and limited conversation to collaborators Sep 8, 2019
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
P3 An issue that is relevant to core functions, but does not impede progress. Important, but not urgent severity3: broken
Projects
None yet
Development

Successfully merging a pull request may close this issue.

7 participants