Repository navigation
Expand file tree
/
Copy pathstartWithVersionSelector.ts
More file actions
127 lines (109 loc) · 5.22 KB
/
Copy pathstartWithVersionSelector.ts
File metadata and controls
127 lines (109 loc) · 5.22 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
// Copyright (c) Microsoft Corporation. All rights reserved. Licensed under the MIT license.
// See LICENSE in the project root for license information.
/* eslint-disable no-console */
// NOTE: Since startWithVersionSelector.ts is loaded in the same process as start.ts, any dependencies that
// we import here may become side-by-side versions. We want to minimize any dependencies.
import * as path from 'node:path';
import * as fs from 'node:fs';
import type { IPackageJson } from '@rushstack/node-core-library';
import { getToolParameterNamesFromArgs } from './utilities/CliUtilities';
import { Constants } from './utilities/Constants';
// Excerpted from PackageJsonLookup.tryGetPackageFolderFor()
function tryGetPackageFolderFor(resolvedFileOrFolderPath: string): string | undefined {
// Two lookups are required, because get() cannot distinguish the undefined value
// versus a missing key.
// if (this._packageFolderCache.has(resolvedFileOrFolderPath)) {
// return this._packageFolderCache.get(resolvedFileOrFolderPath);
// }
// Is resolvedFileOrFolderPath itself a folder with a package.json file? If so, return it.
if (fs.existsSync(path.join(resolvedFileOrFolderPath, 'package.json'))) {
// this._packageFolderCache.set(resolvedFileOrFolderPath, resolvedFileOrFolderPath);
return resolvedFileOrFolderPath;
}
// Otherwise go up one level
const parentFolder: string | undefined = path.dirname(resolvedFileOrFolderPath);
if (!parentFolder || parentFolder === resolvedFileOrFolderPath) {
// We reached the root directory without finding a package.json file,
// so cache the negative result
// this._packageFolderCache.set(resolvedFileOrFolderPath, undefined);
return undefined; // no match
}
// Recurse upwards, caching every step along the way
const parentResult: string | undefined = tryGetPackageFolderFor(parentFolder);
// Cache the parent's answer as well
// this._packageFolderCache.set(resolvedFileOrFolderPath, parentResult);
return parentResult;
}
/**
* When Heft is invoked via the shell path, we examine the project's package.json dependencies and try to load
* the locally installed version of Heft. This avoids accidentally building using the wrong version of Heft.
* Use "heft --unmanaged" to bypass this feature.
*/
function tryStartLocalHeft(): boolean {
const toolParameters: Set<string> = getToolParameterNamesFromArgs();
if (toolParameters.has(Constants.unmanagedParameterLongName)) {
console.log(
`Bypassing the Heft version selector because ${JSON.stringify(Constants.unmanagedParameterLongName)} ` +
'was specified.'
);
console.log();
return false;
} else if (toolParameters.has(Constants.debugParameterLongName)) {
// The unmanaged flag could be undiscoverable if it's not in their locally installed version
console.log(
'Searching for a locally installed version of Heft. Use the ' +
`${JSON.stringify(Constants.unmanagedParameterLongName)} flag if you want to avoid this.`
);
}
// Find the package.json file that governs the current folder location
const projectFolder: string | undefined = tryGetPackageFolderFor(process.cwd());
if (projectFolder) {
let heftEntryPoint: string;
try {
const packageJsonPath: string = path.join(projectFolder, 'package.json');
const packageJsonContent: string = fs.readFileSync(packageJsonPath).toString();
let packageJson: IPackageJson;
try {
packageJson = JSON.parse(packageJsonContent);
} catch (error) {
throw new Error(`Error parsing ${packageJsonPath}:` + (error as Error).message);
}
// Does package.json have a dependency on Heft?
if (
!(packageJson.dependencies && packageJson.dependencies[Constants.heftPackageName]) &&
!(packageJson.devDependencies && packageJson.devDependencies[Constants.heftPackageName])
) {
// No explicit dependency on Heft
return false;
}
// To avoid a loading the "resolve" NPM package, let's assume that the Heft dependency must be
// installed as "<projectFolder>/node_modules/@rushstack/heft".
const heftFolder: string = path.join(projectFolder, 'node_modules', Constants.heftPackageName);
// Try the new output layout first, then fall back to the legacy layout
const commonJsHeftEntryPoint: string = path.join(heftFolder, 'lib-commonjs', 'start.js');
if (!fs.existsSync(commonJsHeftEntryPoint)) {
const legacyHeftEntryPoint: string = path.join(heftFolder, 'lib', 'start.js');
if (!fs.existsSync(legacyHeftEntryPoint)) {
throw new Error(
`Unable to find Heft entry point: ${commonJsHeftEntryPoint} or ${legacyHeftEntryPoint}`
);
} else {
heftEntryPoint = legacyHeftEntryPoint;
}
} else {
heftEntryPoint = commonJsHeftEntryPoint;
}
} catch (error) {
throw new Error('Error probing for local Heft version: ' + (error as Error).message);
}
require(heftEntryPoint);
// We found and successfully invoked the local Heft
return true;
}
// We couldn't find the package folder
return false;
}
if (!tryStartLocalHeft()) {
// A project Heft dependency was not found, so launch the unmanaged version.
require('./start.js');
}