Skip to content

Commit 70e460d

Browse files
alan-agius4vikerman
authored andcommitted
refactor: use require.resolve instead of custom resolve (#15906)
1 parent e7bc270 commit 70e460d

File tree

5 files changed

+35
-67
lines changed

5 files changed

+35
-67
lines changed

etc/api/angular_devkit/schematics/tools/index.d.ts

-2
Original file line numberDiff line numberDiff line change
@@ -108,8 +108,6 @@ export declare class InvalidCollectionJsonException extends BaseException {
108108
export declare class NodeModulesEngineHost extends FileSystemEngineHostBase {
109109
constructor();
110110
protected _resolveCollectionPath(name: string): string;
111-
protected _resolvePackageJson(name: string, basedir?: string): string;
112-
protected _resolvePath(name: string, basedir?: string): string;
113111
protected _resolveReferenceString(refString: string, parentPath: string): {
114112
ref: RuleFactory<{}>;
115113
path: string;

packages/angular/cli/commands/add-impl.ts

+11-1
Original file line numberDiff line numberDiff line change
@@ -139,7 +139,17 @@ export class AddCommand extends SchematicCommand<AddCommandSchema> {
139139
}
140140

141141
if (savePackage === false) {
142-
installTempPackage(packageIdentifier.raw, this.logger, packageManager);
142+
// Temporary packages are located in a different directory
143+
// Hence we need to resolve them using the temp path
144+
const tempPath = installTempPackage(packageIdentifier.raw, this.logger, packageManager);
145+
const resolvedCollectionPath = require.resolve(
146+
join(collectionName, 'package.json'),
147+
{
148+
paths: [tempPath],
149+
},
150+
);
151+
152+
collectionName = dirname(resolvedCollectionPath);
143153
} else {
144154
installPackage(packageIdentifier.raw, this.logger, packageManager, savePackage);
145155
}

packages/angular/cli/tasks/install-package.ts

-5
Original file line numberDiff line numberDiff line change
@@ -105,11 +105,6 @@ export function installTempPackage(
105105
tempNodeModules = join(tempPath, 'node_modules');
106106
}
107107

108-
// Needed to resolve schematics from this location since we use a custom
109-
// resolve strategy in '@angular/devkit-core/node'
110-
// todo: this should be removed when we change the resolutions to use require.resolve
111-
process.env.NG_TEMP_MODULES_DIR = tempNodeModules;
112-
113108
return tempNodeModules;
114109
}
115110

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

+14-57
Original file line numberDiff line numberDiff line change
@@ -10,8 +10,7 @@ import {
1010
InvalidJsonCharacterException,
1111
UnexpectedEndOfInputException,
1212
} from '@angular-devkit/core';
13-
import * as core from '@angular-devkit/core/node';
14-
import { dirname, join, resolve as resolvePath } from 'path';
13+
import { dirname, extname, join, resolve } from 'path';
1514
import { RuleFactory } from '../src';
1615
import {
1716
FileSystemCollectionDesc,
@@ -27,7 +26,6 @@ import {
2726
} from './file-system-engine-host-base';
2827
import { readJsonFile } from './file-system-utility';
2928

30-
3129
export class NodePackageDoesNotSupportSchematics extends BaseException {
3230
constructor(name: string) {
3331
super(`Package ${JSON.stringify(name)} was found but does not support schematics.`);
@@ -41,71 +39,30 @@ export class NodePackageDoesNotSupportSchematics extends BaseException {
4139
export class NodeModulesEngineHost extends FileSystemEngineHostBase {
4240
constructor() { super(); }
4341

44-
protected _resolvePackageJson(name: string, basedir = process.cwd()) {
45-
return core.resolve(name, {
46-
basedir,
47-
checkLocal: true,
48-
checkGlobal: true,
49-
resolvePackageJson: true,
50-
});
51-
}
52-
53-
protected _resolvePath(name: string, basedir = process.cwd()) {
54-
// Allow relative / absolute paths.
55-
if (name.startsWith('.') || name.startsWith('/')) {
56-
return resolvePath(basedir, name);
57-
} else {
58-
// If it's a file inside a package, resolve the package then return the file...
59-
if (name.split('/').length > (name[0] == '@' ? 2 : 1)) {
60-
const rest = name.split('/');
61-
const packageName = rest.shift() + (name[0] == '@' ? '/' + rest.shift() : '');
62-
63-
return resolvePath(core.resolve(packageName, {
64-
basedir,
65-
checkLocal: true,
66-
checkGlobal: true,
67-
resolvePackageJson: true,
68-
}), '..', ...rest);
69-
}
70-
71-
return core.resolve(name, {
72-
basedir,
73-
checkLocal: true,
74-
checkGlobal: true,
75-
});
76-
}
77-
}
78-
7942
protected _resolveCollectionPath(name: string): string {
8043
let collectionPath: string | undefined = undefined;
81-
82-
if (name.replace(/\\/g, '/').split('/').length > (name[0] == '@' ? 2 : 1)) {
83-
try {
84-
collectionPath = this._resolvePath(name, process.cwd());
85-
} catch {
86-
}
44+
if (name.startsWith('.') || name.startsWith('/')) {
45+
name = resolve(name);
8746
}
8847

89-
if (!collectionPath) {
90-
let packageJsonPath = this._resolvePackageJson(name, process.cwd());
91-
// If it's a file, use it as is. Otherwise append package.json to it.
92-
if (!core.fs.isFile(packageJsonPath)) {
93-
packageJsonPath = join(packageJsonPath, 'package.json');
94-
}
48+
if (extname(name)) {
49+
// When having an extension let's just resolve the provided path.
50+
collectionPath = require.resolve(name);
51+
} else {
52+
const packageJsonPath = require.resolve(join(name, 'package.json'));
53+
const { schematics } = require(packageJsonPath);
9554

96-
const pkgJsonSchematics = require(packageJsonPath)['schematics'];
97-
if (!pkgJsonSchematics || typeof pkgJsonSchematics != 'string') {
55+
if (!schematics || typeof schematics !== 'string') {
9856
throw new NodePackageDoesNotSupportSchematics(name);
9957
}
100-
collectionPath = this._resolvePath(pkgJsonSchematics, dirname(packageJsonPath));
58+
59+
collectionPath = resolve(dirname(packageJsonPath), schematics);
10160
}
10261

10362
try {
104-
if (collectionPath) {
105-
readJsonFile(collectionPath);
63+
readJsonFile(collectionPath);
10664

107-
return collectionPath;
108-
}
65+
return collectionPath;
10966
} catch (e) {
11067
if (
11168
e instanceof InvalidJsonCharacterException || e instanceof UnexpectedEndOfInputException

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

+10-2
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ import * as os from 'os';
1414
import * as path from 'path';
1515
import { NodeModulesEngineHost } from './node-module-engine-host';
1616

17-
const TMP_DIR = process.env['$TEST_TMPDIR'] || os.tmpdir();
17+
const TMP_DIR = process.env['TEST_TMPDIR'] || os.tmpdir();
1818

1919
describe('NodeModulesEngineHost', () => {
2020
let tmpDir!: string;
@@ -47,8 +47,16 @@ describe('NodeModulesEngineHost', () => {
4747
const engineHost = new NodeModulesEngineHost();
4848
const engine = new SchematicEngine(engineHost);
4949

50+
// Under Bazel 'require.resolve' is patched to use Bazel resolutions from the MANIFEST FILES.
51+
// Adding a temporary file won't be enough to make Bazel aware of this file.
52+
// We provide the full path here just to verify that the underlying logic works
53+
let prefix = '';
54+
if (process.env['BAZEL_TARGET']) {
55+
prefix = path.join(process.cwd(), 'node_modules');
56+
}
57+
5058
expect(() => {
51-
engine.createCollection(path.join('@angular/core', './schematics/migrations.json'));
59+
engine.createCollection(path.join(prefix, '@angular/core', './schematics/migrations.json'));
5260
}).not.toThrow();
5361
});
5462
});

0 commit comments

Comments
 (0)