forked from facebook/react-native
-
Notifications
You must be signed in to change notification settings - Fork 166
Expand file tree
/
Copy pathyarn.config.cjs
More file actions
189 lines (166 loc) · 6.9 KB
/
yarn.config.cjs
File metadata and controls
189 lines (166 loc) · 6.9 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
// @ts-check
/** @type {import('@yarnpkg/types')} */
const {defineConfig} = require('@yarnpkg/types');
/**
* @typedef {import('@yarnpkg/types').Yarn.Constraints.Context} Context
* @typedef {import('@yarnpkg/types').Yarn.Constraints.Workspace} Workspace
* @typedef {import('@yarnpkg/types').Yarn.Constraints.Dependency} Dependency
*/
// Helpers
// These packages in tools/ were private upstream in React Native and don't follow the same versioning as the public packages
const PACKAGES_TO_IGNORE = ['@react-native/eslint', 'public-api'];
/**
* Get the React Native macOS workspace
* @param {Context} context
* @returns {Workspace | null} Workspace
*/
const getReactNativeMacOSWorkspace = ({Yarn}) => {
const rnmWorkspace = Yarn.workspace({ident: 'react-native-macos'});
if (!rnmWorkspace) {
// Report error on root workspace since react-native-macos doesn't exist
Yarn.workspace().error('react-native-macos workspace must exist in the monorepo');
}
return rnmWorkspace;
}
/**
* Get the peer dependency on react-native declared by react-native-macos
* @param {Context} context
* @returns {string | undefined} Peer dependency version
*/
const getReactNativePeerDependency = ({Yarn}) => {
const rnmWorkspace = getReactNativeMacOSWorkspace({Yarn});
const rnPeerDependency = rnmWorkspace?.pkg.peerDependencies.get('react-native');
if (!rnPeerDependency) {
rnmWorkspace?.error('react-native-macos must declare a peer dependency on react-native on release branches');
}
return rnPeerDependency;
}
/**
* // Check if react-native-macos version is 1000.0.0, implying we are on the main branch
* @param {Context} context
* @returns {boolean}
*/
const isMainBranch = ({Yarn}) => {
const rnmWorkspace = getReactNativeMacOSWorkspace({Yarn});
return rnmWorkspace?.manifest.version === '1000.0.0';
}
// Constraints
/**
* Enforce that all @react-native/ scoped packages are private
* @param {Context} context
*/
function enforcePrivateReactNativeScopedPackages({Yarn}) {
for (const workspace of Yarn.workspaces()) {
if (workspace.ident?.startsWith('@react-native/') && !PACKAGES_TO_IGNORE.includes(workspace.ident)) {
workspace.set('private', true);
}
}
}
/**
* Enforce that react-native-macos declares a peer dependency on react-native on release branches,
* and that this version is consistent across all @react-native/ scoped packages.
* Do not enforce on the main branch, where there is no published version of React Native to align to.
* @param {Context} context
*/
function enforceReactNativeVersionConsistency({Yarn}) {
if (!isMainBranch({Yarn})) {
const reactNativePeerDependency = getReactNativePeerDependency({Yarn});
// Enforce this version on all @react-native/ scoped packages
for (const workspace of Yarn.workspaces()) {
if (workspace.ident?.startsWith('@react-native/') && !PACKAGES_TO_IGNORE.includes(workspace.ident)) {
workspace.set('version', reactNativePeerDependency);
}
}
}
}
/**
* Enforce that all @react-native/ scoped dependencies use the same version
* as the react-native peer dependency declared in react-native-macos.
* Do not enforce on the main branch, where there is no published version of React Native to align to.
* @param {Context} context
*/
function enforceReactNativeDependencyConsistency({Yarn}) {
for (const dependency of Yarn.dependencies()) {
if (dependency.ident.startsWith('@react-native/')) {
if (!isMainBranch({Yarn})) {
const reactNativeVersion = getReactNativePeerDependency({Yarn});
const isRNM = dependency.workspace.ident === 'react-native-macos';
const isRNMForkedPackage = dependency.workspace.ident?.startsWith('@react-native-macos/');
if (isRNM || isRNMForkedPackage) {
// Don't use `workspace:*` for packages we publish until nx release with Yarn 4 supports it.
dependency.update(reactNativeVersion);
} else {
dependency.update('workspace:*');
}
} else {
dependency.update('workspace:*');
}
}
}
}
/**
* Enforce that all public @react-native-macos/ scoped packages' versions
* are consistent with react-native-macos
* Do not enforce on the main branch, where we do not publish nightlies yet.
* @param {Context} context
*/
function enforceReactNativeMacosVersionConsistency({Yarn}) {
if (!isMainBranch({Yarn})) {
const rnmWorkspace = getReactNativeMacOSWorkspace({Yarn});
const rnmVersion = rnmWorkspace?.manifest.version;
// Enforce this version on all non-private @react-native-macos/ scoped packages
for (const workspace of Yarn.workspaces()) {
const isReactNativeMacosScoped = workspace.ident && workspace.ident.startsWith('@react-native-macos/');
const isPrivate = workspace.manifest.private;
if (isReactNativeMacosScoped && !isPrivate) {
workspace.set('version', rnmVersion);
}
}
}
}
/**
* Enforce that all @react-native-macos/ scoped dependencies use the same version
* as the react-native-macos
* Do not enforce on the main branch, where there is no published version of React Native to align to.
* @param {Context} context
*/
function enforceReactNativeMacOSDependencyConsistency({Yarn}) {
const rnmWorkspace = getReactNativeMacOSWorkspace({Yarn});
const rnmVersion = rnmWorkspace?.manifest.version;
for (const dependency of Yarn.dependencies()) {
if (dependency.ident.startsWith('@react-native-macos/')) {
if (!isMainBranch({Yarn})) {
dependency.update(rnmVersion);
} else {
dependency.update('workspace:*');
}
}
}
}
/**
* Enforce that private @react-native-macos/ scoped packages (i.e. internal
* tooling that is not forked from upstream) have a fixed version of 0.1.0.
* These packages do not track the react-native-macos release version.
* @param {Context} context
*/
function enforceReactNativeMacosPrivatePackageVersion({Yarn}) {
if (!isMainBranch({Yarn})) {
for (const workspace of Yarn.workspaces()) {
const isReactNativeMacosScoped = workspace.ident?.startsWith('@react-native-macos/');
const isPrivate = workspace.manifest.private;
if (isReactNativeMacosScoped && isPrivate) {
workspace.set('version', '0.1.0');
}
}
}
}
module.exports = defineConfig({
constraints: async ctx => {
enforcePrivateReactNativeScopedPackages(ctx);
enforceReactNativeVersionConsistency(ctx);
enforceReactNativeDependencyConsistency(ctx);
enforceReactNativeMacosVersionConsistency(ctx);
enforceReactNativeMacOSDependencyConsistency(ctx);
enforceReactNativeMacosPrivatePackageVersion(ctx);
},
});