@@ -13,8 +13,8 @@ type Configs = {
13
13
skipSemVerFor : Platforms [ ] ;
14
14
skipCodeFor : Platforms [ ] ;
15
15
root : string ;
16
- pbxprojPath : string ;
17
- buildGradlePath : string ;
16
+ pbxprojPath : ( ) => string ;
17
+ buildGradlePath : ( ) => string ;
18
18
} ;
19
19
20
20
// -- FP
@@ -30,7 +30,7 @@ const pipe2 = <A1, A2, R>(
30
30
31
31
const replace = ( expr : string | RegExp , replacement : string , str : string ) => {
32
32
return str . replace ( expr , replacement ) ;
33
- }
33
+ } ;
34
34
35
35
// -- Specializations
36
36
@@ -42,11 +42,12 @@ const writeFile = (fPath: string, file: string) => {
42
42
fs . writeFileSync ( fPath , file , "utf8" ) ;
43
43
} ;
44
44
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 ) ! ) ;
47
48
48
- return first ;
49
- }
49
+ return first ;
50
+ } ;
50
51
51
52
const incrementSemVer = ( current : string , type : SemVer | undefined ) => {
52
53
const [ major , minor , patch ] = parseSemVer ( current ) ;
@@ -66,28 +67,27 @@ const incrementSemVer = (current: string, type: SemVer | undefined) => {
66
67
throw new Error ( `'${ type } ' is not a semver type` ) ;
67
68
} ;
68
69
69
-
70
70
// -- Managers
71
71
72
72
abstract class BaseFileManager {
73
- private readonly basePath : string ;
73
+ private readonly basePath : ( ) => string ;
74
74
protected content : string | null = null ;
75
75
76
- constructor ( basePath : string ) {
76
+ constructor ( basePath : ( ) => string ) {
77
77
this . basePath = basePath ;
78
78
}
79
79
80
80
protected read ( ) {
81
81
if ( this . content === null ) {
82
- this . content = fs . readFileSync ( this . basePath , "utf8" ) ;
82
+ this . content = fs . readFileSync ( this . basePath ( ) , "utf8" ) ;
83
83
}
84
84
85
85
return this . content ;
86
86
}
87
87
88
88
write ( ) {
89
89
if ( this . content ) {
90
- return writeFile ( this . basePath , this . content ) ;
90
+ return writeFile ( this . basePath ( ) , this . content ) ;
91
91
}
92
92
}
93
93
}
@@ -170,18 +170,24 @@ class BuildGradleManager extends BaseFileManager {
170
170
}
171
171
172
172
class PackageJSONManager {
173
- private readonly basePath : string ;
174
- private content : {
173
+ private readonly basePath : ( ) => string ;
174
+ public content : {
175
175
version : string ;
176
176
} | null = null ;
177
177
178
- constructor ( basePath : string ) {
178
+ constructor ( basePath : ( ) => string ) {
179
179
this . basePath = basePath ;
180
180
}
181
181
182
182
private read ( ) {
183
183
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 ) ;
185
191
}
186
192
187
193
return this . content ! ;
@@ -190,7 +196,7 @@ class PackageJSONManager {
190
196
write ( ) {
191
197
if ( this . content ) {
192
198
return writeFile (
193
- this . basePath ,
199
+ this . basePath ( ) ,
194
200
JSON . stringify ( this . content , null , 2 ) ,
195
201
) ;
196
202
}
@@ -208,26 +214,24 @@ class PackageJSONManager {
208
214
}
209
215
}
210
216
211
- export class ProjectFilesManager {
217
+ class ProjectFilesManager {
212
218
readonly configs : Configs ;
213
219
readonly pbx : PBXManager ;
214
220
readonly buildGradle : BuildGradleManager ;
215
221
readonly packageJSON : PackageJSONManager ;
216
222
217
223
constructor ( configs : Configs ) {
218
- const {
219
- root,
220
- pbxprojPath,
221
- buildGradlePath,
222
- } = configs ;
224
+ const { root, pbxprojPath, buildGradlePath } = configs ;
223
225
224
226
this . configs = configs ;
225
227
this . buildGradle = new BuildGradleManager ( buildGradlePath ) ;
226
228
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
+ ) ;
231
235
}
232
236
233
237
syncSemver ( semverString : string ) {
@@ -309,6 +313,82 @@ export class ProjectFilesManager {
309
313
}
310
314
}
311
315
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
+ } ) ;
314
394
} ;
0 commit comments