Skip to content

Commit 712be61

Browse files
authored
feat: peer dependencies validation (#9019)
## Summary Adding peer dependency version validation to both Reanimated and Worklets, parallel to the one enforced with the compatibility table. This will help build tools such as RN Repo to easily obtain compatible version ranges for compilation. After merging I'll backport this PR to both Reanimated 4.2 and Worklets 0.7 and release patch versions with updates to `peerDependencies`. ## Test plan Fiddle with `package.json` of Reanimated/Worklets and their version and see that the script works correctly. I also added a CI step that would verify this data on our releases.
1 parent adbbd15 commit 712be61

7 files changed

Lines changed: 138 additions & 8 deletions

File tree

.github/workflows/reanimated-static-checks.yml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,9 @@ jobs:
4040
run: yarn build
4141

4242
# Checks
43+
- name: Validate peer dependency versions
44+
working-directory: ${{ env.PACKAGE_PATH }}
45+
run: yarn validate-peers
4346
- name: Check TypeScript types
4447
working-directory: ${{ env.PACKAGE_PATH }}
4548
run: yarn type:check

.github/workflows/worklets-static-checks.yml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,9 @@ jobs:
4242
run: yarn workspace react-native-reanimated build
4343

4444
# Checks
45+
- name: Validate peer dependency versions
46+
working-directory: ${{ env.PACKAGE_PATH }}
47+
run: yarn validate-peers
4548
- name: Check TypeScript types
4649
working-directory: ${{ env.PACKAGE_PATH }}
4750
run: yarn type:check

packages/react-native-reanimated/RELEASE.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,8 @@ Reanimated follows [semver](https://semver.org/) whenever applicable.
3232

3333
5. Update the **Compatibility** in `packages/react-native-reanimated/compatibility.json`
3434

35+
6. Update `peerDependencies` in `packages/react-native-reanimated/package.json` to align with the versions declared in the **Compatibility** file.
36+
3537
6. Install Pods:
3638
* <details><summary>Reanimated v4</summary>
3739

packages/react-native-reanimated/package.json

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,8 @@
3636
"type:check:strict:app": "yarn workspace common-app type:check:strict",
3737
"build": "yarn workspace react-native-worklets build && bob build",
3838
"circular-dependency-check": "yarn madge --extensions js,jsx --circular lib",
39-
"tree-shake:check:web": "yarn is-tree-shakable --resolution web"
39+
"tree-shake:check:web": "yarn is-tree-shakable --resolution web",
40+
"validate-peers": "node ../../scripts/validate-compatibility-peer-dependencies.js"
4041
},
4142
"main": "lib/module/index",
4243
"module": "lib/module/index",
@@ -96,8 +97,8 @@
9697
},
9798
"peerDependencies": {
9899
"react": "*",
99-
"react-native": "*",
100-
"react-native-worklets": ">=0.7.0"
100+
"react-native": "0.81 - 0.84",
101+
"react-native-worklets": "*"
101102
},
102103
"devDependencies": {
103104
"@babel/core": "7.28.4",

packages/react-native-worklets/package.json

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,8 @@
3737
"type:check:app": "yarn workspace common-app type:check",
3838
"type:check:plugin": "yarn workspace babel-plugin-worklets type:check",
3939
"type:check:tests": "../../scripts/test-ts.sh __typetests__",
40-
"tree-shake:check:web": "yarn is-tree-shakable --resolution web"
40+
"tree-shake:check:web": "yarn is-tree-shakable --resolution web",
41+
"validate-peers": "node ../../scripts/validate-compatibility-peer-dependencies.js"
4142
},
4243
"repository": {
4344
"type": "git",
@@ -54,7 +55,7 @@
5455
"@babel/core": "*",
5556
"@react-native/metro-config": "*",
5657
"react": "*",
57-
"react-native": "*"
58+
"react-native": "0.79 - 0.84"
5859
},
5960
"dependencies": {
6061
"@babel/plugin-transform-arrow-functions": "7.27.1",
Lines changed: 120 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,120 @@
1+
'use strict';
2+
3+
const fs = require('node:fs');
4+
const path = require('node:path');
5+
const semver = require('semver');
6+
7+
let status = 0;
8+
9+
function main() {
10+
const packageJson = readJson('package.json');
11+
const packageVersion = packageJson.version;
12+
const peerDeps = packageJson.peerDependencies;
13+
14+
const reactNativePeerRange = semver.validRange(peerDeps['react-native']);
15+
if (!reactNativePeerRange) {
16+
throw new Error(
17+
`Invalid semver range for react-native peer dependency: "${peerDeps['react-native']}".`
18+
);
19+
}
20+
21+
const compatibility = readJson('compatibility.json');
22+
const currentCompatibility = getCurrentCompatibility(
23+
compatibility?.fabric || compatibility,
24+
packageVersion
25+
);
26+
const compatibilityReactNativeRange = getRangeFromCompatibility(
27+
currentCompatibility['react-native']
28+
);
29+
30+
validateRanges(
31+
'react-native',
32+
reactNativePeerRange,
33+
compatibilityReactNativeRange
34+
);
35+
36+
if (!semver.prerelease(packageVersion) && peerDeps['react-native-worklets']) {
37+
const workletsPeerRange = semver.validRange(
38+
peerDeps['react-native-worklets']
39+
);
40+
if (!workletsPeerRange) {
41+
throw new Error(
42+
`Invalid semver range for react-native-worklets peer dependency: "${peerDeps['react-native-worklets']}".`
43+
);
44+
}
45+
46+
const compatibilityWorkletsRange = getRangeFromCompatibility(
47+
currentCompatibility['react-native-worklets']
48+
);
49+
50+
validateRanges(
51+
'react-native-worklets',
52+
workletsPeerRange,
53+
compatibilityWorkletsRange
54+
);
55+
}
56+
}
57+
58+
/**
59+
* @param {string} library
60+
* @param {string | semver.Range} range1
61+
* @param {string | semver.Range} range2
62+
*/
63+
function validateRanges(library, range1, range2) {
64+
if (!semver.subset(range1, range2) || !semver.subset(range2, range1)) {
65+
console.error(
66+
`Mismatch between ${library} peer dependency ranges: "${range1}" vs "${range2}".`
67+
);
68+
status = 1;
69+
}
70+
}
71+
72+
/**
73+
* @param {string} filePath
74+
* @returns {any} Parsed JSON content of the file at the given relative path.
75+
*/
76+
function readJson(filePath) {
77+
const resolvedPath = path.resolve(filePath);
78+
return JSON.parse(fs.readFileSync(resolvedPath, 'utf8'));
79+
}
80+
81+
/**
82+
* @param {{ [x: string]: any }} compatibility
83+
* @param {string} packageVersion
84+
* @returns {Record<string, string[]>} Compatibility data for the given version.
85+
*/
86+
function getCurrentCompatibility(compatibility, packageVersion) {
87+
if (packageVersion.includes('main') || packageVersion.includes('nightly')) {
88+
return compatibility['nightly'];
89+
}
90+
for (const range in compatibility) {
91+
if (semver.satisfies(packageVersion, range)) {
92+
return compatibility[range];
93+
}
94+
}
95+
throw new Error(
96+
`No compatibility data found for version "${packageVersion}".`
97+
);
98+
}
99+
100+
/**
101+
* @param {string[]} versions
102+
* @returns {string} A semver range string that represents the given list of
103+
* versions.
104+
*/
105+
function getRangeFromCompatibility(versions) {
106+
if (versions.length === 1) {
107+
return versions[0];
108+
}
109+
const range = semver.validRange(
110+
versions[0] + ' - ' + versions[versions.length - 1]
111+
);
112+
if (!range) {
113+
throw new Error(
114+
`Invalid version range generated from compatibility data: "${versions[0]} - ${versions[versions.length - 1]}".`
115+
);
116+
}
117+
return range;
118+
}
119+
120+
main();

yarn.lock

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -28369,8 +28369,8 @@ __metadata:
2836928369
typescript: "npm:5.8.3"
2837028370
peerDependencies:
2837128371
react: "*"
28372-
react-native: "*"
28373-
react-native-worklets: ">=0.7.0"
28372+
react-native: 0.81 - 0.84
28373+
react-native-worklets: "*"
2837428374
languageName: unknown
2837528375
linkType: soft
2837628376

@@ -28525,7 +28525,7 @@ __metadata:
2852528525
"@babel/core": "*"
2852628526
"@react-native/metro-config": "*"
2852728527
react: "*"
28528-
react-native: "*"
28528+
react-native: 0.79 - 0.84
2852928529
languageName: unknown
2853028530
linkType: soft
2853128531

0 commit comments

Comments
 (0)