1
+ // @ts -check
2
+
3
+ /** @type {import('@yarnpkg/types') } */
4
+ const { defineConfig} = require ( '@yarnpkg/types' ) ;
5
+
6
+ /**
7
+ * @typedef {import('@yarnpkg/types').Yarn.Constraints.Context } Context
8
+ * @typedef {import('@yarnpkg/types').Yarn.Constraints.Workspace } Workspace
9
+ * @typedef {import('@yarnpkg/types').Yarn.Constraints.Dependency } Dependency
10
+ */
11
+
12
+ /**
13
+ * Enforce that react-native-macos declares a peer dependency on react-native on release branches,
14
+ * except on the main branch, where there is no published version of React Native to align to.
15
+ * @param {Context } context
16
+ */
17
+ function expectReactNativePeerDependency ( { Yarn} ) {
18
+ const rnmWorkspace = Yarn . workspace ( { ident : 'react-native-macos' } ) ;
19
+ if ( ! rnmWorkspace ) {
20
+ // Report error on root workspace since react-native-macos doesn't exist
21
+ Yarn . workspace ( ) . error ( 'react-native-macos workspace must exist in the monorepo' ) ;
22
+ return ;
23
+ }
24
+
25
+ // Check if react-native-macos version is 1000.0.0 - implying we are on the main branch
26
+ const isMainBranch = rnmWorkspace . manifest . version === '1000.0.0' ;
27
+ if ( ! isMainBranch ) {
28
+ const rnPeerDependency = rnmWorkspace . pkg . peerDependencies . get ( 'react-native' ) ;
29
+ if ( ! rnPeerDependency ) {
30
+ rnmWorkspace . error ( 'react-native-macos must declare a peer dependency on react-native on release branches' ) ;
31
+ }
32
+ }
33
+ }
34
+
35
+ /**
36
+ * Enforce that all @react-native/ scoped packages use the same version
37
+ * as the react-native peer dependency declared in react-native-macos.
38
+ * On the main branch, enforce that we use workspace:* for @react-native/ packages.
39
+ * @param {Context } context
40
+ */
41
+ function enforceReactNativeVersionConsistency ( { Yarn} ) {
42
+ const rnmWorkspace = Yarn . workspace ( { ident : 'react-native-macos' } ) ;
43
+ if ( ! rnmWorkspace ) {
44
+ // Report error on root workspace since react-native-macos doesn't exist
45
+ Yarn . workspace ( ) . error ( 'react-native-macos workspace must exist in the monorepo' ) ;
46
+ return ;
47
+ }
48
+
49
+ // Check if react-native-macos version is 1000.0.0 - implying we are on the main branch
50
+ const isMainBranch = rnmWorkspace . manifest . version === '1000.0.0' ;
51
+
52
+ let targetVersion ;
53
+ if ( isMainBranch ) {
54
+ // On main branch, use workspace:* for @react-native/ packages
55
+ targetVersion = 'workspace:*' ;
56
+ } else {
57
+ const rnPeerDependency = rnmWorkspace . pkg . peerDependencies . get ( 'react-native' ) ;
58
+ if ( ! rnPeerDependency ) {
59
+ rnmWorkspace . error ( 'react-native-macos must declare a peer dependency on react-native on release branches' ) ;
60
+ return ;
61
+ }
62
+ targetVersion = rnPeerDependency ;
63
+ } // Enforce this version on all @react -native/ scoped packages across all workspaces
64
+ for ( const dependency of Yarn . dependencies ( ) ) {
65
+ if ( dependency . ident . startsWith ( '@react-native/' ) ) {
66
+ // Check if the target package is private (not published)
67
+ const targetWorkspace = Yarn . workspace ( { ident : dependency . ident } ) ;
68
+ const isPrivatePackage = targetWorkspace && targetWorkspace . manifest . private ;
69
+
70
+ if ( isPrivatePackage ) {
71
+ // Private packages should always use workspace:* since they're not published
72
+ dependency . update ( 'workspace:*' ) ;
73
+ } else {
74
+ dependency . update ( targetVersion ) ;
75
+ }
76
+ }
77
+ }
78
+ }
79
+
80
+ /**
81
+ * Enforce that all @react-native-macos/ scoped packages use the same version
82
+ * as react-native-macos, but only for non-private packages.
83
+ * @param {Context } context
84
+ */
85
+ function enforceReactNativeMacosVersionConsistency ( { Yarn} ) {
86
+ const rnmWorkspace = Yarn . workspace ( { ident : 'react-native-macos' } ) ;
87
+ if ( ! rnmWorkspace ) {
88
+ // Report error on root workspace since react-native-macos doesn't exist
89
+ Yarn . workspace ( ) . error ( 'react-native-macos workspace must exist in the monorepo' ) ;
90
+ return ;
91
+ }
92
+
93
+ const targetVersion = rnmWorkspace . manifest . version ;
94
+ if ( ! targetVersion ) {
95
+ rnmWorkspace . error ( 'react-native-macos must have a version' ) ;
96
+ return ;
97
+ }
98
+
99
+ // Enforce this version on all non-private @react-native-macos/ scoped packages
100
+ for ( const workspace of Yarn . workspaces ( ) ) {
101
+ const isReactNativeMacosScoped = workspace . ident && workspace . ident . startsWith ( '@react-native-macos/' ) ;
102
+ const isPrivate = workspace . manifest . private ;
103
+
104
+ if ( isReactNativeMacosScoped && ! isPrivate ) {
105
+ workspace . set ( 'version' , targetVersion ) ;
106
+ }
107
+ }
108
+ }
109
+
110
+ module . exports = defineConfig ( {
111
+ constraints : async ctx => {
112
+ expectReactNativePeerDependency ( ctx ) ;
113
+ enforceReactNativeVersionConsistency ( ctx ) ;
114
+ enforceReactNativeMacosVersionConsistency ( ctx ) ;
115
+ } ,
116
+ } ) ;
0 commit comments