@@ -13,8 +13,8 @@ type Configs = {
1313 skipSemVerFor : Platforms [ ] ;
1414 skipCodeFor : Platforms [ ] ;
1515 root : string ;
16- pbxprojPath : string ;
17- buildGradlePath : string ;
16+ pbxprojPath : ( ) => string ;
17+ buildGradlePath : ( ) => string ;
1818} ;
1919
2020// -- FP
@@ -30,7 +30,7 @@ const pipe2 = <A1, A2, R>(
3030
3131const replace = ( expr : string | RegExp , replacement : string , str : string ) => {
3232 return str . replace ( expr , replacement ) ;
33- }
33+ } ;
3434
3535// -- Specializations
3636
@@ -42,11 +42,12 @@ const writeFile = (fPath: string, file: string) => {
4242 fs . writeFileSync ( fPath , file , "utf8" ) ;
4343} ;
4444
45- const matchFirst = ( reg : RegExp ) => ( value : string ) => {
46- const [ , first ] = ( [ ] as string [ ] ) . concat ( reg . exec ( value ) ! ) ;
45+ const matchFirst = ( reg : RegExp ) =>
46+ ( value : string ) => {
47+ const [ , first ] = ( [ ] as string [ ] ) . concat ( reg . exec ( value ) ! ) ;
4748
48- return first ;
49- }
49+ return first ;
50+ } ;
5051
5152const incrementSemVer = ( current : string , type : SemVer | undefined ) => {
5253 const [ major , minor , patch ] = parseSemVer ( current ) ;
@@ -66,28 +67,27 @@ const incrementSemVer = (current: string, type: SemVer | undefined) => {
6667 throw new Error ( `'${ type } ' is not a semver type` ) ;
6768} ;
6869
69-
7070// -- Managers
7171
7272abstract class BaseFileManager {
73- private readonly basePath : string ;
73+ private readonly basePath : ( ) => string ;
7474 protected content : string | null = null ;
7575
76- constructor ( basePath : string ) {
76+ constructor ( basePath : ( ) => string ) {
7777 this . basePath = basePath ;
7878 }
7979
8080 protected read ( ) {
8181 if ( this . content === null ) {
82- this . content = fs . readFileSync ( this . basePath , "utf8" ) ;
82+ this . content = fs . readFileSync ( this . basePath ( ) , "utf8" ) ;
8383 }
8484
8585 return this . content ;
8686 }
8787
8888 write ( ) {
8989 if ( this . content ) {
90- return writeFile ( this . basePath , this . content ) ;
90+ return writeFile ( this . basePath ( ) , this . content ) ;
9191 }
9292 }
9393}
@@ -170,18 +170,24 @@ class BuildGradleManager extends BaseFileManager {
170170}
171171
172172class PackageJSONManager {
173- private readonly basePath : string ;
174- private content : {
173+ private readonly basePath : ( ) => string ;
174+ public content : {
175175 version : string ;
176176 } | null = null ;
177177
178- constructor ( basePath : string ) {
178+ constructor ( basePath : ( ) => string ) {
179179 this . basePath = basePath ;
180180 }
181181
182182 private read ( ) {
183183 if ( this . content === null ) {
184- this . content = require ( this . basePath ) ;
184+ // Avoid direct require as it caches
185+ // resolved modules and changes to them
186+ // are going to be persisted in the same process
187+ const raw = fs . readFileSync ( require . resolve ( this . basePath ( ) ) , {
188+ encoding : "utf8" ,
189+ } ) ;
190+ this . content = JSON . parse ( raw ) ;
185191 }
186192
187193 return this . content ! ;
@@ -190,7 +196,7 @@ class PackageJSONManager {
190196 write ( ) {
191197 if ( this . content ) {
192198 return writeFile (
193- this . basePath ,
199+ this . basePath ( ) ,
194200 JSON . stringify ( this . content , null , 2 ) ,
195201 ) ;
196202 }
@@ -208,26 +214,24 @@ class PackageJSONManager {
208214 }
209215}
210216
211- export class ProjectFilesManager {
217+ class ProjectFilesManager {
212218 readonly configs : Configs ;
213219 readonly pbx : PBXManager ;
214220 readonly buildGradle : BuildGradleManager ;
215221 readonly packageJSON : PackageJSONManager ;
216222
217223 constructor ( configs : Configs ) {
218- const {
219- root,
220- pbxprojPath,
221- buildGradlePath,
222- } = configs ;
224+ const { root, pbxprojPath, buildGradlePath } = configs ;
223225
224226 this . configs = configs ;
225227 this . buildGradle = new BuildGradleManager ( buildGradlePath ) ;
226228 this . pbx = new PBXManager ( pbxprojPath ) ;
227- this . packageJSON = new PackageJSONManager ( path . join (
228- root ,
229- "package.json" ,
230- ) ) ;
229+ this . packageJSON = new PackageJSONManager ( ( ) =>
230+ path . join (
231+ root ,
232+ "package.json" ,
233+ )
234+ ) ;
231235 }
232236
233237 syncSemver ( semverString : string ) {
@@ -309,6 +313,82 @@ export class ProjectFilesManager {
309313 }
310314}
311315
312- export const versioner = ( configs : Configs ) => {
313- new ProjectFilesManager ( configs ) . run ( ) ;
316+ // if you want a simple version to use as api
317+ export const apiVersioner = ( configs : Configs ) => {
318+ return new ProjectFilesManager ( configs ) ;
319+ } ;
320+
321+ export const versioner = (
322+ cliConfigs : {
323+ root ?: string ;
324+ project ?: {
325+ ios ?: {
326+ sourceDir ?: string ;
327+ pbxprojPath ?: string ;
328+ xcodeProject ?: {
329+ name : string ;
330+ } ;
331+ } ;
332+ android ?: {
333+ sourceDir ?: string ;
334+ appName ?: string ;
335+ } ;
336+ } ;
337+ } ,
338+ cliArgs : {
339+ skipCodeFor ?: string ;
340+ skipSemverFor ?: string ;
341+ semver ?: string ;
342+ type ?: string ;
343+ } ,
344+ ) => {
345+ if ( cliArgs . skipCodeFor === "all" && cliArgs . skipSemverFor === "all" ) {
346+ // https://i.kym-cdn.com/photos/images/newsfeed/001/240/075/90f.png
347+ console . log ( "My work here is done." ) ;
348+ return ;
349+ }
350+
351+ const required = < T > ( value : T , name : string ) : NonNullable < T > => {
352+ if ( ! value ) {
353+ throw new Error (
354+ `Value for ${ name } is '${ value } ', maybe RN cli broke compatibility?` ,
355+ ) ;
356+ }
357+
358+ return value ! ;
359+ } ;
360+
361+ return apiVersioner ( {
362+ root : required ( cliConfigs . root , "root" ) ,
363+ pbxprojPath : ( ) => {
364+ const iosProject = required ( cliConfigs ?. project ?. ios , "project.ios" ) ;
365+
366+ return iosProject . pbxprojPath || path . join (
367+ required ( iosProject . sourceDir , "project.ios.sourceDir" ) ,
368+ required ( iosProject . xcodeProject , "project.ios.xcodeProject" )
369+ . name
370+ . replace ( ".xcworkspace" , ".xcodeproj" ) ,
371+ "project.pbxproj" ,
372+ ) ;
373+ } ,
374+ buildGradlePath : ( ) => {
375+ const androidProject = required ( cliConfigs ?. project ?. android , "project.android" ) ;
376+
377+ return path . join (
378+ required ( androidProject . sourceDir , "project.android.sourceDir" ) ,
379+ required ( androidProject . appName , "project.android.appName" ) ,
380+ "build.gradle" ,
381+ ) ;
382+ } ,
383+ // code validates these casts, we cast to make api above allow only valid values
384+ // for type checked usages
385+ type : cliArgs . type as SemVer ,
386+ semver : cliArgs . semver ,
387+ skipCodeFor : cliArgs . skipCodeFor
388+ ? cliArgs . skipCodeFor . split ( " " ) as Platforms [ ]
389+ : [ ] ,
390+ skipSemVerFor : cliArgs . skipSemverFor
391+ ? cliArgs . skipSemverFor . split ( " " ) as Platforms [ ]
392+ : [ ] ,
393+ } ) ;
314394} ;
0 commit comments