3
3
import { readFile , writeFile } from 'node:fs/promises'
4
4
5
5
import fg from 'fast-glob'
6
- import { valid , satisfies } from 'semver'
6
+ import { valid , satisfies , gte } from 'semver'
7
7
8
8
const FUTURE_NEXT_PATCH_VERSION = '14.999.0'
9
9
10
+ const NEXT_VERSION_REQUIRES_REACT_19 = '14.3.0-canary.45'
11
+ // TODO: Update this when React 19 is released
12
+ const REACT_19_VERSION = '19.0.0-rc-3f1436cca1-20240516'
13
+ const REACT_18_VERSION = '18.2.0'
14
+
10
15
/**
11
16
* Check if current next version satisfies a semver constraint
12
17
* @param {string } condition Semver constraint
@@ -20,6 +25,17 @@ export function nextVersionSatisfies(condition) {
20
25
return satisfies ( checkVersion , condition ) || version === condition
21
26
}
22
27
28
+ /**
29
+ * Check if current next version requires React 19
30
+ * @param {string } version Next version
31
+ * @returns {boolean } True if current next version requires React 19
32
+ */
33
+
34
+ export function nextVersionRequiresReact19 ( version ) {
35
+ // @ts -expect-error Mistake in semver types
36
+ return gte ( version , NEXT_VERSION_REQUIRES_REACT_19 , { includePrerelease : true } )
37
+ }
38
+
23
39
/**
24
40
* Finds all package.json in fixture directory and updates 'next' version to a given version
25
41
* If there is test.dependencies.next, it will only update if the version satisfies the constraint in that field
@@ -29,12 +45,13 @@ export function nextVersionSatisfies(condition) {
29
45
* @param {string } [options.logPrefix] Text to prefix logs with
30
46
* @param {'update' | 'revert' } [options.operation] This just informs log output wording, otherwise it has no effect
31
47
* @param {boolean } [options.silent] Doesn't produce any logs if truthy
48
+ * @param {boolean } [options.updateReact] Update React version to match Next version
32
49
* @returns {Promise<void> }
33
50
*/
34
51
export async function setNextVersionInFixture (
35
52
cwd ,
36
53
version ,
37
- { logPrefix = '' , operation = 'update' , silent = false } = { } ,
54
+ { logPrefix = '' , operation = 'update' , silent = false , updateReact = true } = { } ,
38
55
) {
39
56
// use NEXT_RESOLVED_VERSION env var if exists and if passed version matches version from NEXT_VERSION
40
57
// otherwise use whatever is passed
@@ -65,7 +82,7 @@ export async function setNextVersionInFixture(
65
82
if ( packageJson . dependencies ?. next ) {
66
83
const versionConstraint = packageJson . test ?. dependencies ?. next
67
84
// We can't use semver to check "canary" or "latest", so we use a fake future minor version
68
- const checkVersion = isSemverVersion ? version : FUTURE_NEXT_PATCH_VERSION
85
+ const checkVersion = isSemverVersion ? resolvedVersion : FUTURE_NEXT_PATCH_VERSION
69
86
if (
70
87
operation === 'update' &&
71
88
versionConstraint &&
@@ -80,6 +97,12 @@ export async function setNextVersionInFixture(
80
97
return
81
98
}
82
99
packageJson . dependencies . next = version
100
+ if ( updateReact && nextVersionRequiresReact19 ( checkVersion ) ) {
101
+ const reactVersion = operation === 'update' ? REACT_19_VERSION : REACT_18_VERSION
102
+ packageJson . dependencies . react = reactVersion
103
+ packageJson . dependencies [ 'react-dom' ] = reactVersion
104
+ }
105
+
83
106
await writeFile ( packageJsonPath , JSON . stringify ( packageJson , null , 2 ) + '\n' )
84
107
}
85
108
} ) ,
0 commit comments