Skip to content

Commit 93c2018

Browse files
clydinKeen Yee Liau
authored and
Keen Yee Liau
committedMar 30, 2020
fix(@angular-devkit/schematics): fully resolve schematic entries within packages
Fixes: #17085
1 parent 3cd2048 commit 93c2018

File tree

1 file changed

+53
-12
lines changed

1 file changed

+53
-12
lines changed
 

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

+53-12
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ import {
1010
InvalidJsonCharacterException,
1111
UnexpectedEndOfInputException,
1212
} from '@angular-devkit/core';
13-
import { dirname, extname, join, resolve } from 'path';
13+
import { dirname, join, resolve } from 'path';
1414
import { RuleFactory } from '../src';
1515
import {
1616
FileSystemCollectionDesc,
@@ -39,26 +39,67 @@ export class NodePackageDoesNotSupportSchematics extends BaseException {
3939
export class NodeModulesEngineHost extends FileSystemEngineHostBase {
4040
constructor(private readonly paths?: string[]) { super(); }
4141

42-
protected _resolveCollectionPath(name: string): string {
42+
private resolve(name: string, requester?: string, references = new Set<string>()): string {
43+
if (requester) {
44+
if (references.has(requester)) {
45+
references.add(requester);
46+
throw new Error(
47+
'Circular schematic reference detected: ' + JSON.stringify(Array.from(references)),
48+
);
49+
} else {
50+
references.add(requester);
51+
}
52+
}
53+
54+
const relativeBase = requester ? dirname(requester) : process.cwd();
4355
let collectionPath: string | undefined = undefined;
44-
if (name.startsWith('.') || name.startsWith('/')) {
45-
name = resolve(name);
56+
57+
if (name.startsWith('.')) {
58+
name = resolve(relativeBase, name);
4659
}
4760

48-
if (extname(name)) {
49-
// When having an extension let's just resolve the provided path.
50-
collectionPath = require.resolve(name, { paths: this.paths });
51-
} else {
52-
const packageJsonPath = require.resolve(join(name, 'package.json'), { paths: this.paths });
61+
const resolveOptions = {
62+
paths: requester ? [dirname(requester), ...(this.paths || [])] : this.paths,
63+
};
64+
65+
// Try to resolve as a package
66+
try {
67+
const packageJsonPath = require.resolve(join(name, 'package.json'), resolveOptions);
5368
const { schematics } = require(packageJsonPath);
5469

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

59-
collectionPath = resolve(dirname(packageJsonPath), schematics);
74+
collectionPath = this.resolve(schematics, packageJsonPath, references);
75+
} catch (e) {
76+
if (e.code !== 'MODULE_NOT_FOUND') {
77+
throw e;
78+
}
6079
}
6180

81+
// If not a package, try to resolve as a file
82+
if (!collectionPath) {
83+
try {
84+
collectionPath = require.resolve(name, resolveOptions);
85+
} catch (e) {
86+
if (e.code !== 'MODULE_NOT_FOUND') {
87+
throw e;
88+
}
89+
}
90+
}
91+
92+
// If not a package or a file, error
93+
if (!collectionPath) {
94+
throw new CollectionCannotBeResolvedException(name);
95+
}
96+
97+
return collectionPath;
98+
}
99+
100+
protected _resolveCollectionPath(name: string): string {
101+
const collectionPath = this.resolve(name);
102+
62103
try {
63104
readJsonFile(collectionPath);
64105

@@ -68,10 +109,10 @@ export class NodeModulesEngineHost extends FileSystemEngineHostBase {
68109
e instanceof InvalidJsonCharacterException || e instanceof UnexpectedEndOfInputException
69110
) {
70111
throw new InvalidCollectionJsonException(name, collectionPath, e);
112+
} else {
113+
throw e;
71114
}
72115
}
73-
74-
throw new CollectionCannotBeResolvedException(name);
75116
}
76117

77118
protected _resolveReferenceString(refString: string, parentPath: string) {

0 commit comments

Comments
 (0)
Please sign in to comment.