Skip to content

Regression: unable to resolve schematics via package name #17085

@Vortex375

Description

@Vortex375

🐞 Bug report

Command (mark with an x)

  • [ x ] generate
  • [ x ] add
  • [ x ] update

Is this a regression?

Yes, it used to work in Angular <= 8.x

Description

I have a library "@mycompany/mylib" and a separate package containing its schematics called "@mycompany/mylib-schematics".

I used to have this entry in the library's package.json file:

"schematics": "@mycompany/mylib-schematics/collection.json"

And this worked fine.

When executing, for example ng generate @mycompany/mylib:foo it would correctly resolve the collection.json file residing in "node_modules/@mycompany/mylib-schematics" and execute the schematic.

With Angular 9 this does not work anymore. I can no longer specify a package name in the "schematics" property of the package.json file. The path specified there is always resolved relative to the package.json location. I can make it work again if I change it to this:

"schematics": "../mylib-schematics/collection.json"

The problem is within packages/angular_devkit/schematics/tools/node-module-engine-host.ts:

  protected _resolveCollectionPath(name: string): string {
    let collectionPath: string | undefined = undefined;
    if (name.startsWith('.') || name.startsWith('/')) {
      name = resolve(name);
    }

    if (extname(name)) {
      // When having an extension let's just resolve the provided path.
      collectionPath = require.resolve(name, { paths: this.paths });
    } else {
      const packageJsonPath = require.resolve(join(name, 'package.json'), { paths: this.paths });
      const { schematics } = require(packageJsonPath);

      if (!schematics || typeof schematics !== 'string') {
        throw new NodePackageDoesNotSupportSchematics(name);
      }

// !!!
// the below line is wrong: it should only try to resolve it that way if the path starts with '.' or '/'
// (i.e. when dealing with a relative or absolute path)
// otherwise it should use require.resolve() like above
// !!!
      collectionPath = resolve(dirname(packageJsonPath), schematics);
    }

🔬 Minimal Reproduction

As described above, create a library and add a "collections" property to its package.json that points to another node_module, then try to "ng generate".

package.json of "@mycompany/mylib":

"schematics": "@mycompany/mylib-schematics/collection.json"

ng generate @mycompany/mylib:foo:

An unhandled exception occurred: Collection "@mycompany/mylib" cannot be resolved.

🔥 Exception or Error

[error] Error: Collection "@mycompany/mylib" cannot be resolved.
    at NodeModulesEngineHost._resolveCollectionPath (test-project/node_modules/@angular-devkit/schematics/tools/node-module-engine-host.js:55:15)
    at NodeModulesEngineHost.createCollectionDescription (test-project/node_modules/@angular-devkit/schematics/tools/file-system-engine-host-base.js:109:27)
    at SchematicEngine._createCollectionDescription (test-project/node_modules/@angular-devkit/schematics/src/engine/engine.js:147:40)
    at SchematicEngine.createCollection (test-project/node_modules/@angular-devkit/schematics/src/engine/engine.js:140:43)
    at GenerateCommand.getCollection (test-project/node_modules/@angular/cli/models/schematic-command.js:127:35)
    at GenerateCommand.initialize (test-project/node_modules/@angular/cli/models/schematic-command.js:43:37)
    at async GenerateCommand.initialize (test-project/node_modules/@angular/cli/commands/generate-impl.js:12:9)
    at async GenerateCommand.validateAndRun (test-project/node_modules/@angular/cli/models/command.js:124:9)
    at async Object.runCommand (test-project/node_modules/@angular/cli/models/command-runner.js:201:24)
    at async default_1 (test-project/node_modules/@angular/cli/lib/cli/index.js:62:31)

🌍 Your Environment


Angular CLI: 9.0.2
Node: 12.14.1
OS: darwin x64

Angular: 9.0.1
... animations, common, compiler, compiler-cli, core, forms
... language-service, localize, platform-browser
... platform-browser-dynamic, router
Ivy Workspace: Yes

Package                            Version
------------------------------------------------------------
@angular-devkit/architect          0.900.2
@angular-devkit/build-angular      0.900.2
@angular-devkit/build-optimizer    0.900.2
@angular-devkit/build-webpack      0.900.2
@angular-devkit/core               9.0.2
@angular-devkit/schematics         9.0.2
@angular/cdk                       9.0.0
@angular/cli                       9.0.2
@angular/material                  9.0.0
@angular/material-moment-adapter   9.0.0
@ngtools/webpack                   9.0.2
@schematics/angular                9.0.2
@schematics/update                 0.900.2
rxjs                               6.5.3
typescript                         3.7.5
webpack                            4.41.2

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions