Skip to content

Commit 0ba837b

Browse files
clydinfilipesilva
authored andcommitted
refactor(@angular/cli): use custom scoped require instead of global
To support the eventual conversion of the `@angular/cli` package to ESM, the usage of the global require function must be removed as it is not supported in ESM code. Node.js does have the facility to create custom require functions that can be used when the need to synchronously load a file at runtime is required. Such cases have now been converted to use custom require functions where appropriate.
1 parent ab3db39 commit 0ba837b

File tree

2 files changed

+18
-13
lines changed

2 files changed

+18
-13
lines changed

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

Lines changed: 13 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
*/
88

99
import { execSync } from 'child_process';
10-
import * as path from 'path';
10+
import nodeModule from 'module';
1111
import { Command } from '../models/command';
1212
import { colors } from '../utilities/color';
1313
import { getPackageManager } from '../utilities/package-manager';
@@ -28,11 +28,15 @@ interface PartialPackageInfo {
2828
export class VersionCommand extends Command<VersionCommandSchema> {
2929
public static aliases = ['v'];
3030

31+
private readonly localRequire = nodeModule.createRequire(__filename);
32+
// Trailing slash is used to allow the path to be treated as a directory
33+
private readonly workspaceRequire = nodeModule.createRequire(this.context.root + '/');
34+
3135
async run() {
32-
const cliPackage: PartialPackageInfo = require('../package.json');
36+
const cliPackage: PartialPackageInfo = this.localRequire('../package.json');
3337
let workspacePackage: PartialPackageInfo | undefined;
3438
try {
35-
workspacePackage = require(path.resolve(this.context.root, 'package.json'));
39+
workspacePackage = this.workspaceRequire('./package.json');
3640
} catch {}
3741

3842
const [nodeMajor] = process.versions.node.split('.').map((part) => Number(part));
@@ -151,28 +155,28 @@ export class VersionCommand extends Command<VersionCommandSchema> {
151155
}
152156

153157
private getVersion(moduleName: string): string {
154-
let packagePath;
158+
let packageInfo: PartialPackageInfo | undefined;
155159
let cliOnly = false;
156160

157161
// Try to find the package in the workspace
158162
try {
159-
packagePath = require.resolve(`${moduleName}/package.json`, { paths: [this.context.root] });
163+
packageInfo = this.workspaceRequire(`${moduleName}/package.json`);
160164
} catch {}
161165

162166
// If not found, try to find within the CLI
163-
if (!packagePath) {
167+
if (!packageInfo) {
164168
try {
165-
packagePath = require.resolve(`${moduleName}/package.json`);
169+
packageInfo = this.localRequire(`${moduleName}/package.json`);
166170
cliOnly = true;
167171
} catch {}
168172
}
169173

170174
let version: string | undefined;
171175

172176
// If found, attempt to get the version
173-
if (packagePath) {
177+
if (packageInfo) {
174178
try {
175-
version = require(packagePath).version + (cliOnly ? ' (cli-only)' : '');
179+
version = packageInfo.version + (cliOnly ? ' (cli-only)' : '');
176180
} catch {}
177181
}
178182

packages/angular/cli/models/schematic-engine-host.ts

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -121,7 +121,8 @@ function wrap(
121121
moduleCache: Map<string, unknown>,
122122
exportName?: string,
123123
): () => unknown {
124-
const scopedRequire = nodeModule.createRequire(schematicFile);
124+
const hostRequire = nodeModule.createRequire(__filename);
125+
const schematicRequire = nodeModule.createRequire(schematicFile);
125126

126127
const customRequire = function (id: string) {
127128
if (legacyModules[id]) {
@@ -131,13 +132,13 @@ function wrap(
131132
// Resolve from inside the `@angular/cli` project
132133
const packagePath = require.resolve(id);
133134

134-
return require(packagePath);
135+
return hostRequire(packagePath);
135136
} else if (id.startsWith('.') || id.startsWith('@angular/cdk')) {
136137
// Wrap relative files inside the schematic collection
137138
// Also wrap `@angular/cdk`, it contains helper utilities that import core schematic packages
138139

139140
// Resolve from the original file
140-
const modulePath = scopedRequire.resolve(id);
141+
const modulePath = schematicRequire.resolve(id);
141142

142143
// Use cached module if available
143144
const cachedModule = moduleCache.get(modulePath);
@@ -159,7 +160,7 @@ function wrap(
159160
}
160161

161162
// All others are required directly from the original file
162-
return scopedRequire(id);
163+
return schematicRequire(id);
163164
};
164165

165166
// Setup a wrapper function to capture the module's exports

0 commit comments

Comments
 (0)