Skip to content

Commit 081111f

Browse files
michaelfaithalan-agius4
authored andcommitted
fix(@angular-devkit/schematics): running external schematics with yarn pnp
This change addresses an issue encountered when running external schematics from a yarn pnp workspace. The function used to resolve a collection json using node used recursion in a way that it effectively walked itself into an exception. Then if the exception is the type it expected, it would keep going. This was flawed in that yarn with pnp throws a different type of error when it failed to load the mis-constructed collection path (e.g. `/node_modules/@schematics/angular/collection.json/package.json`). `ENOTDIR` instead of `MODULE_NOT_FOUND`. This process of intentionally / knowingly walking into an exception seems problematic in general. So, I addressed it by removing the recursion that was used mainly because there's a similar need to construct the collection path from a relative path in the package.json as there is to construct the collection path from a relative path that's passed in. Rather than leaning on the recursion to do this, I added the logic at the time we pull the schematics path from the package, and move on. Since the recursion was removed, the infinite recursion safety check at the start wasn't needed anymore. I've tested this in both yarn pnp and non-pnp environments.
1 parent 65e5331 commit 081111f

File tree

1 file changed

+13
-14
lines changed

1 file changed

+13
-14
lines changed

packages/angular_devkit/schematics/tools/node-module-engine-host.ts

Lines changed: 13 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -33,18 +33,7 @@ export class NodeModulesEngineHost extends FileSystemEngineHostBase {
3333
super();
3434
}
3535

36-
private resolve(name: string, requester?: string, references = new Set<string>()): string {
37-
if (requester) {
38-
if (references.has(requester)) {
39-
references.add(requester);
40-
throw new Error(
41-
'Circular schematic reference detected: ' + JSON.stringify(Array.from(references)),
42-
);
43-
} else {
44-
references.add(requester);
45-
}
46-
}
47-
36+
private resolve(name: string, requester?: string): string {
4837
const relativeBase = requester ? dirname(requester) : process.cwd();
4938
let collectionPath: string | undefined = undefined;
5039

@@ -57,6 +46,7 @@ export class NodeModulesEngineHost extends FileSystemEngineHostBase {
5746
};
5847

5948
// Try to resolve as a package
49+
let possibleCollectionPath = name;
6050
try {
6151
const packageJsonPath = require.resolve(join(name, 'package.json'), resolveOptions);
6252
const { schematics } = require(packageJsonPath);
@@ -65,7 +55,16 @@ export class NodeModulesEngineHost extends FileSystemEngineHostBase {
6555
throw new NodePackageDoesNotSupportSchematics(name);
6656
}
6757

68-
collectionPath = this.resolve(schematics, packageJsonPath, references);
58+
// If this is a relative path to the collection, then create the collection
59+
// path in relation to the package path
60+
if (schematics.startsWith('.')) {
61+
const packageDirectory = dirname(packageJsonPath);
62+
collectionPath = resolve(packageDirectory, schematics);
63+
}
64+
// Otherwise use the path as-is to attempt resolution
65+
else {
66+
possibleCollectionPath = schematics;
67+
}
6968
} catch (e) {
7069
if ((e as NodeJS.ErrnoException).code !== 'MODULE_NOT_FOUND') {
7170
throw e;
@@ -75,7 +74,7 @@ export class NodeModulesEngineHost extends FileSystemEngineHostBase {
7574
// If not a package, try to resolve as a file
7675
if (!collectionPath) {
7776
try {
78-
collectionPath = require.resolve(name, resolveOptions);
77+
collectionPath = require.resolve(possibleCollectionPath, resolveOptions);
7978
} catch (e) {
8079
if ((e as NodeJS.ErrnoException).code !== 'MODULE_NOT_FOUND') {
8180
throw e;

0 commit comments

Comments
 (0)