-
-
Notifications
You must be signed in to change notification settings - Fork 1.8k
Expand file tree
/
Copy pathutil.ts
More file actions
205 lines (174 loc) · 5.61 KB
/
util.ts
File metadata and controls
205 lines (174 loc) · 5.61 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
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
import { parseSemver } from '@sentry/core';
import * as fs from 'fs';
import { createRequire } from 'module';
import * as path from 'path';
/**
* Returns the version of Next.js installed in the project, or undefined if it cannot be determined.
*/
export function getNextjsVersion(): string | undefined {
const nextjsPackageJsonPath = resolveNextjsPackageJson();
if (nextjsPackageJsonPath) {
try {
const nextjsPackageJson: { version: string } = JSON.parse(
fs.readFileSync(nextjsPackageJsonPath, { encoding: 'utf-8' }),
);
return nextjsPackageJson.version;
} catch {
// noop
}
}
return undefined;
}
function resolveNextjsPackageJson(): string | undefined {
try {
return createRequire(`${process.cwd()}/`).resolve('next/package.json');
} catch {
return undefined;
}
}
/**
* Checks if the current Next.js version supports the runAfterProductionCompile hook.
* This hook was introduced in Next.js 15.4.1. (https://github.com/vercel/next.js/pull/77345)
*
* @param version - version string to check.
* @returns true if Next.js version is 15.4.1 or higher
*/
export function supportsProductionCompileHook(version: string): boolean {
const versionToCheck = version;
if (!versionToCheck) {
return false;
}
const { major, minor, patch } = parseSemver(versionToCheck);
if (major === undefined || minor === undefined || patch === undefined) {
return false;
}
if (major > 15) {
return true;
}
// For major version 15, check if it's 15.4.1 or higher
if (major === 15) {
if (minor > 4) {
return true;
}
if (minor === 4 && patch >= 1) {
return true;
}
return false;
}
return false;
}
/**
* Checks if the current Next.js version supports native debug ids for turbopack.
* This feature was first introduced in Next.js v15.6.0-canary.36 and marked stable in Next.js v16
*
* @param version - version string to check.
* @returns true if Next.js version supports native debug ids for turbopack builds
*/
export function supportsNativeDebugIds(version: string): boolean {
if (!version) {
return false;
}
const { major, minor, prerelease } = parseSemver(version);
if (major === undefined || minor === undefined) {
return false;
}
// Next.js 16+ supports native debug ids
if (major >= 16) {
return true;
}
// For Next.js 15, check if it's 15.6.0-canary.36+
if (major === 15 && prerelease?.startsWith('canary.')) {
// Any canary version 15.7+ supports native debug ids
if (minor > 6) {
return true;
}
// For 15.6 canary versions, check if it's canary.36 or higher
if (minor === 6) {
const canaryNumber = parseInt(prerelease.split('.')[1] || '0', 10);
if (canaryNumber >= 36) {
return true;
}
}
}
return false;
}
/**
* Checks if the given Next.js version requires the `experimental.instrumentationHook` option.
* Next.js 15.0.0 and higher (including certain RC and canary versions) no longer require this option
* and will print a warning if it is set.
*
* @param version - version string to check.
* @returns true if the version requires the instrumentationHook option to be set
*/
export function requiresInstrumentationHook(version: string): boolean {
if (!version) {
return true; // Default to requiring it if version cannot be determined
}
const { major, minor, patch, prerelease } = parseSemver(version);
if (major === undefined || minor === undefined || patch === undefined) {
return true; // Default to requiring it if parsing fails
}
// Next.js 16+ never requires the hook
if (major >= 16) {
return false;
}
// Next.js 14 and below always require the hook
if (major < 15) {
return true;
}
// At this point, we know it's Next.js 15.x.y
// Stable releases (15.0.0+) don't require the hook
if (!prerelease) {
return false;
}
// Next.js 15.x.y with x > 0 or y > 0 don't require the hook
if (minor > 0 || patch > 0) {
return false;
}
// Check specific prerelease versions that don't require the hook
if (prerelease.startsWith('rc.')) {
const rcNumber = parseInt(prerelease.split('.')[1] || '0', 10);
return rcNumber === 0; // Only rc.0 requires the hook
}
if (prerelease.startsWith('canary.')) {
const canaryNumber = parseInt(prerelease.split('.')[1] || '0', 10);
return canaryNumber < 124; // canary.124+ doesn't require the hook
}
// All other 15.0.0 prerelease versions (alpha, beta, etc.) require the hook
return true;
}
/**
* Determines which bundler is actually being used based on environment variables,
* and CLI flags.
*
* @returns 'turbopack' or 'webpack'
*/
export function detectActiveBundler(): 'turbopack' | 'webpack' {
const turbopackEnv = process.env.TURBOPACK;
// Check if TURBOPACK env var is set to a truthy value (excluding falsy strings like 'false', '0', '')
const isTurbopackEnabled = turbopackEnv && turbopackEnv !== 'false' && turbopackEnv !== '0';
if (isTurbopackEnabled || process.argv.includes('--turbo')) {
return 'turbopack';
} else {
return 'webpack';
}
}
/**
* Extract modules from project directory's package.json
*/
export function getPackageModules(projectDir: string): Record<string, string> {
try {
const packageJson = path.join(projectDir, 'package.json');
const packageJsonContent = fs.readFileSync(packageJson, 'utf8');
const packageJsonObject = JSON.parse(packageJsonContent) as {
dependencies?: Record<string, string>;
devDependencies?: Record<string, string>;
};
return {
...packageJsonObject.dependencies,
...packageJsonObject.devDependencies,
};
} catch {
return {};
}
}