Skip to content

bug: running "external" schematics in yarn pnp workspace #25648

Closed
@michaelfaith

Description

@michaelfaith

I'm finally getting around to moving a library project that uses @schematics/angular to use PnP, and discovered an issue with some code in the NodeModulesEngineHost within @angular-devkit/schematics. From my code, within a unit test, we're using the SchematicTestRunner's runExternalSchematic function to generate a test project. Running that function from within a pnp environment is throwing the following error:

 ENOTDIR: not a directory, lstat '/node_modules/@schematics/angular/collection.json/package.json'

      21005 |
      21006 | function makeError$1(code, message) {
    > 21007 |   return Object.assign(new Error(`${code}: ${message}`), { code });
            |                        ^
      21008 | }
      21009 | function EBUSY(message) {
      21010 |   return makeError$1(`EBUSY`, message);

      at makeError$1 (../../.pnp.cjs:21007:24)
      at ENOTDIR (../../.pnp.cjs:21025:10)
      at ZipFS.resolveFilename (../../.pnp.cjs:22607:15)
      at ZipFS.realpathSync (../../.pnp.cjs:22398:28)
      at ../../.pnp.cjs:23704:100
      at ../../.pnp.cjs:24200:60
      at ZipOpenFS.getZipSync (../../.pnp.cjs:24329:14)
      at ZipOpenFS.makeCallSync (../../.pnp.cjs:24200:17)
      at ZipOpenFS.realpathSync (../../.pnp.cjs:23696:17)
      at VirtualFS.realpathSync (../../.pnp.cjs:23446:26)
      at PosixFS.realpathSync (../../.pnp.cjs:23197:41)
      at NodePathFS.realpathSync (../../.pnp.cjs:23197:41)
      at maybeRealpathSync (../../.yarn/cache/resolve-patch-6d2631dc64-66cc788f13.zip/node_modules/resolve/lib/sync.js:52:16)
      at resolveSync (../../.yarn/cache/resolve-patch-6d2631dc64-66cc788f13.zip/node_modules/resolve/lib/sync.js:97:25)
      at NodeModulesTestEngineHost.resolve (../angular_devkit/schematics/tools/node-module-engine-host.ts:61:39)
      at NodeModulesTestEngineHost.resolve (../angular_devkit/schematics/tools/node-module-engine-host.ts:68:29)
      at createTestCaseSetup (schematics/test-utils.ts:117:40)

This code seems to be improperly joining the collection.json path and the package.json path (/node_modules/@schematics/angular/collection.json/package.json):

const packageJsonPath = require.resolve(join(name, 'package.json'), resolveOptions);
and yarn doesn't know what to do with that.

This is the code we're running within our test:

const workspaceTree = await runner.runExternalSchematic(
    '@schematics/angular',
    'workspace',
    {
      name: 'workspace',
      version: '7.0.0',
      newProjectRoot: 'projects',
    },
    tree
  );

It seems that the code is trying to blindly grab that path, knowing that this case will fail and hit the catch block, since it then tries an alternative approach just after that. So, my guess is where it's checking the error type, to decide whether to absorb the error or re-throw, it needs to consider this error type too (ENOTDIR)?

} catch (e) {
if ((e as NodeJS.ErrnoException).code !== 'MODULE_NOT_FOUND') {
throw e;
}
}

Seeing as this code isn't in the test-specific class, I suspect (but haven't verified) this might also fail for the @angular-devkit/schematics externalSchematics function.

Reproduction Repo: https://github.com/michaelfaith/ng-schematics-yarn-pnp-bug

Originally posted by @michaelfaith in #16980 (comment)

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions