react_native_util 0.2.2 → 0.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: bac5388f9ceda5e72b4a54c717f742c5a56c07f0a7b7489a9cac567469cfe728
4
- data.tar.gz: aea447d8cf31bb2d9feb5b4eb42ec8d869071ced5036f722049fabd38f17b00b
3
+ metadata.gz: 7f874dfbe6f26ca09e59e9392f1e6591d09148b6a34aba766a41feea3bb2957e
4
+ data.tar.gz: 6ccfddce4c25414ef398924bb426dc0191851fb40c1ad6477e19f1eb3970b6cf
5
5
  SHA512:
6
- metadata.gz: e3f3375ad84f084472f36eeac3ae9a6ce2a0fda11a88bb32055a45940c7c39919daea4c5056b75650c130e509f964751e3ae70aeac0b445ef886eefad8f6fc1f
7
- data.tar.gz: 89fcadbf7b2e9db331dd7bab9e3d066a1e06b4c2bd9117560ba79b58c5b871a1a658bf6bbe7bcd5ff6f3d60330d23202e71a79d94b78caa76a8491334aef9179
6
+ metadata.gz: 798ac753cc2ca53970ee8def6a65f24159a69b300e1259864ee59bc9d888aed2323d282bf053e7a78dd9d57f1f4f267d56b471ab0e0bb02ea365aff2ff4e9f13
7
+ data.tar.gz: bfd1a390de9180aed09a3a7da175a938a25743c99233937b499a21eab4c04961d6d35553f1676c44af4f3db3b89705f762dbb377c434b55ff8d602365a5dfaf4
data/README.md CHANGED
@@ -13,9 +13,13 @@ Community utility CLI for React Native projects.
13
13
 
14
14
  _macOS required_
15
15
 
16
+ It's not necessary to install yarn or react-native-cli separately when
17
+ installing from the Homebrew tap with `brew install jdee/tap/react_native_util`.
18
+ They will be installed as required dependencies. If they are not present when
19
+ running from RubyGems, the react_pod command will fail.
16
20
  ```bash
17
- brew install yarn # Not necessary if installing from Homebrew tap
18
- npm install -g react-native-cli
21
+ brew install yarn
22
+ brew install react-native-cli
19
23
  ```
20
24
 
21
25
  ## Installation
@@ -56,35 +60,35 @@ git status
56
60
 
57
61
  _Typical command output:_
58
62
  ```
59
- 2019-05-12T11:42:03-07:00 react_native_util react_pod v0.2.2
60
- [✔] yarn install success in 10.9 s
61
- 2019-05-12T11:42:14-07:00 Darwin 18.5.0 x86_64
62
- 2019-05-12T11:42:14-07:00 Ruby 2.6.3: ~/.rvm/rubies/ruby-2.6.3/bin/ruby
63
- 2019-05-12T11:42:14-07:00 RubyGems 3.0.3: ~/.rvm/rubies/ruby-2.6.3/bin/gem
64
- 2019-05-12T11:42:14-07:00 Bundler 1.17.2: ~/.rvm/gems/ruby-2.6.3/bin/bundle
65
- 2019-05-12T11:42:14-07:00 react-native-cli: /usr/local/bin/react-native
66
- 2019-05-12T11:42:14-07:00 react-native-cli: 2.0.1
67
- 2019-05-12T11:42:14-07:00 react-native: 0.59.8
68
- 2019-05-12T11:42:15-07:00 yarn 1.16.0: /usr/local/bin/yarn
69
- 2019-05-12T11:42:15-07:00 cocoapods 1.6.1: ~/.rvm/gems/ruby-2.6.3/bin/pod
70
- 2019-05-12T11:42:15-07:00 cocoapods-core: 1.6.1
71
- 2019-05-12T11:42:15-07:00 package.json:
72
- 2019-05-12T11:42:15-07:00 app name: "TestApp"
73
- 2019-05-12T11:42:15-07:00 Found Xcode project at ~/github/jdee/react_native_util/examples/TestApp/ios/TestApp.xcodeproj
74
- 2019-05-12T11:42:15-07:00 Dependencies:
75
- 2019-05-12T11:42:15-07:00 react-native-webview
76
- 2019-05-12T11:42:15-07:00 Unlinking dependencies
77
- [✔] react-native unlink react-native-webview success in 0.7 s
78
- 2019-05-12T11:42:16-07:00 Removing Libraries from TestApp
79
- 2019-05-12T11:42:16-07:00 Removing Libraries from TestAppTests
80
- 2019-05-12T11:42:16-07:00 Removing Libraries group
81
- 2019-05-12T11:42:16-07:00 Generating ios/Podfile
82
- 2019-05-12T11:42:16-07:00 Linking dependencies
63
+ 2019-05-12T15:37:50-07:00 react_native_util react_pod v0.3.0
64
+ [✔] yarn install success in 7.2 s
65
+ 2019-05-12T15:37:57-07:00 Darwin 18.5.0 x86_64
66
+ 2019-05-12T15:37:57-07:00 Ruby 2.6.3: ~/.rvm/rubies/ruby-2.6.3/bin/ruby
67
+ 2019-05-12T15:37:57-07:00 RubyGems 3.0.3: ~/.rvm/rubies/ruby-2.6.3/bin/gem
68
+ 2019-05-12T15:37:57-07:00 Bundler 1.17.2: ~/.rvm/gems/ruby-2.6.3/bin/bundle
69
+ 2019-05-12T15:37:57-07:00 react-native-cli: /usr/local/bin/react-native
70
+ 2019-05-12T15:37:57-07:00 react-native-cli: 2.0.1
71
+ 2019-05-12T15:37:57-07:00 react-native: 0.59.8
72
+ 2019-05-12T15:37:58-07:00 yarn 1.16.0: /usr/local/bin/yarn
73
+ 2019-05-12T15:37:58-07:00 cocoapods 1.6.1: ~/.rvm/gems/ruby-2.6.3/bin/pod
74
+ 2019-05-12T15:37:58-07:00 cocoapods-core: 1.6.1
75
+ 2019-05-12T15:37:58-07:00 package.json:
76
+ 2019-05-12T15:37:58-07:00 app name: "TestApp"
77
+ 2019-05-12T15:37:58-07:00 Found Xcode project at ~/github/jdee/react_native_util/examples/TestApp/ios/TestApp.xcodeproj
78
+ 2019-05-12T15:37:58-07:00 Dependencies:
79
+ 2019-05-12T15:37:58-07:00 react-native-webview
80
+ 2019-05-12T15:37:58-07:00 Unlinking dependencies
81
+ [✔] react-native unlink react-native-webview success in 0.6 s
82
+ 2019-05-12T15:37:59-07:00 Removing Libraries from TestApp
83
+ 2019-05-12T15:37:59-07:00 Removing Libraries from TestAppTests
84
+ 2019-05-12T15:37:59-07:00 Removing Libraries group
85
+ 2019-05-12T15:37:59-07:00 Generating ios/Podfile
86
+ 2019-05-12T15:37:59-07:00 Linking dependencies
83
87
  [✔] react-native link react-native-webview success in 0.5 s
84
- 2019-05-12T11:42:17-07:00 Generating Pods project and ios/TestApp.xcworkspace
85
- [✔] pod install success in 8.2 s
86
- 2019-05-12T11:42:25-07:00 Conversion complete ✅
87
- 2019-05-12T11:42:25-07:00 $ open ios/TestApp.xcworkspace
88
+ 2019-05-12T15:37:59-07:00 Generating Pods project and ios/TestApp.xcworkspace
89
+ [✔] pod install success in 12.2 s
90
+ 2019-05-12T15:38:12-07:00 Conversion complete ✅
91
+ 2019-05-12T15:38:12-07:00 $ open ios/TestApp.xcworkspace
88
92
  ```
89
93
 
90
94
  ## Rake task
@@ -112,6 +116,10 @@ ReactNativeUtil::Rake::ReactPodTask.new(
112
116
  require 'react_native_util/converter'
113
117
 
114
118
  Dir.chdir '/path/to/rn/project' do
115
- ReactNativeUtil::Converter.new(repo_update: true).convert_to_react_pod!
119
+ begin
120
+ ReactNativeUtil::Converter.new(repo_update: true).convert_to_react_pod!
121
+ rescue ReactNativeUtil::BaseException => e
122
+ puts "Error from #convert_to_react_pod!: #{e.message}"
123
+ end
116
124
  end
117
125
  ```
@@ -11,6 +11,9 @@ target '<%= app_name %>' do
11
11
  ]
12
12
  pod 'yoga', path: '../node_modules/react-native/ReactCommon/yoga'
13
13
  pod 'Folly', podspec: '../node_modules/react-native/third-party-podspecs/Folly.podspec'
14
+
15
+ # --- react-native link adds pods below this line. ---
16
+
14
17
  end
15
18
 
16
19
  <% if test_target %>
@@ -2,49 +2,29 @@ require 'cocoapods-core'
2
2
  require 'erb'
3
3
  require 'json'
4
4
  require 'rubygems'
5
- require 'tmpdir'
6
- require 'tty/platform'
7
- require 'xcodeproj'
8
- require_relative 'util'
5
+ require_relative 'project'
9
6
 
10
7
  module ReactNativeUtil
11
8
  # Class to perform conversion operations.
12
9
  class Converter
13
10
  include Util
14
11
 
15
- # [Array<String>] Xcode projects from react-native that may be in the Libraries group
16
- DEFAULT_DEPENDENCIES = %w[
17
- ART
18
- React
19
- RCTActionSheet
20
- RCTAnimation
21
- RCTBlob
22
- RCTCameraRoll
23
- RCTGeolocation
24
- RCTImage
25
- RCTLinking
26
- RCTNetwork
27
- RCTPushNotification
28
- RCTSettings
29
- RCTTest
30
- RCTText
31
- RCTVibration
32
- RCTWebSocket
33
- ]
34
-
35
12
  # [String] Path to the Podfile template
36
13
  PODFILE_TEMPLATE_PATH = File.expand_path '../assets/templates/Podfile.erb', __dir__
37
14
 
15
+ REQUIRED_COMMANDS = [:yarn, 'react-native' => 'react-native-cli']
16
+
38
17
  # [Hash] Contents of ./package.json
39
18
  attr_reader :package_json
40
19
 
41
20
  # [String] Full path to Xcode project
42
21
  attr_reader :xcodeproj_path
43
22
 
44
- # [Xcodeproj::Project] Contents of the project at xcodproj_path
45
- attr_reader :xcodeproj
23
+ # [Project] Contents of the project at xcodeproj_path
24
+ attr_reader :project
46
25
 
47
26
  attr_reader :options
27
+ attr_reader :react_project
48
28
  attr_reader :react_podspec
49
29
 
50
30
  def initialize(repo_update: nil)
@@ -56,9 +36,27 @@ module ReactNativeUtil
56
36
  end
57
37
  end
58
38
 
59
- # Convert project to use React pod
60
- # @raise ConversionError on failure
39
+ # Convert project to use React pod. Expects the app's package.json in the
40
+ # current directory.
41
+ #
42
+ # require 'react_native_util/converter'
43
+ #
44
+ # Dir.chdir '/path/to/rn/project' do
45
+ # begin
46
+ # ReactNativeUtil::Converter.new(repo_update: true).convert_to_react_pod!
47
+ # rescue ReactNativeUtil::BaseException => e
48
+ # # All exceptions generated by this gem inherit from
49
+ # # ReactNativeUtil::BaseException.
50
+ # puts "Error from #convert_to_react_pod!: #{e.message}"
51
+ # end
52
+ # end
53
+ #
54
+ # @raise ConversionError on conversion failure
55
+ # @raise ExecutionError on generic command failure
56
+ # @raise Errno::ENOENT if a required command is not present
61
57
  def convert_to_react_pod!
58
+ validate_commands! REQUIRED_COMMANDS
59
+
62
60
  # Make sure no uncommitted changes
63
61
  check_repo_status!
64
62
 
@@ -75,7 +73,7 @@ module ReactNativeUtil
75
73
  load_xcodeproj!
76
74
  log "Found Xcode project at #{xcodeproj_path}"
77
75
 
78
- if libraries_group.nil?
76
+ if project.libraries_group.nil?
79
77
  log "Libraries group not found in #{xcodeproj_path}. No conversion necessary."
80
78
  exit 0
81
79
  end
@@ -87,35 +85,37 @@ module ReactNativeUtil
87
85
  exit 1
88
86
  end
89
87
 
88
+ project.validate_app_target!
89
+
90
90
  load_react_podspec!
91
91
 
92
92
  # 2. Detect native dependencies in Libraries group.
93
93
  log 'Dependencies:'
94
- dependencies.each { |d| log " #{d}" }
94
+ project.dependencies.each { |d| log " #{d}" }
95
95
 
96
96
  # Save for after Libraries removed.
97
- deps_to_add = dependencies
97
+ deps_to_add = project.dependencies
98
98
 
99
99
  # 3. Run react-native unlink for each one.
100
100
  log 'Unlinking dependencies'
101
- dependencies.each do |dep|
101
+ project.dependencies.each do |dep|
102
102
  run_command_with_spinner! 'react-native', 'unlink', dep, log: File.join(Dir.tmpdir, "react-native-unlink-#{dep}.log")
103
103
  end
104
104
 
105
105
  # reload after react-native unlink
106
106
  load_xcodeproj!
107
+ load_react_project!
107
108
 
108
109
  # 4a. Add Start Packager script
109
- validate_app_target!
110
- add_packager_script
110
+ project.add_packager_script_from react_project
111
111
 
112
112
  # Make a note of pod subspecs to replace Libraries group
113
113
  load_subspecs_from_libraries
114
114
 
115
115
  # 4b. Remove Libraries group from Xcode project.
116
- remove_libraries_group_from_project!
116
+ project.remove_libraries_group
117
117
 
118
- xcodeproj.save
118
+ project.save
119
119
 
120
120
  # 5. Generate boilerplate Podfile.
121
121
  generate_podfile!
@@ -207,8 +207,9 @@ module ReactNativeUtil
207
207
  # Load the project at @xcodeproj_path into @xcodeproj
208
208
  # @raise ConversionError on failure
209
209
  def load_xcodeproj!
210
- @xcodeproj = nil # in case of exception on reopen
211
- @xcodeproj = Xcodeproj::Project.open xcodeproj_path
210
+ @project = nil # in case of exception on reopen
211
+ @project = Project.open xcodeproj_path
212
+ @project.app_name = app_name
212
213
  rescue Errno::ENOENT
213
214
  raise ConversionError, "Failed to open #{xcodeproj_path}. File not found."
214
215
  rescue Xcodeproj::PlainInformative => e
@@ -226,72 +227,9 @@ module ReactNativeUtil
226
227
  # rubocop: enable Security/Eval
227
228
  end
228
229
 
229
- # A representation of the Libraries group (if any) from the Xcode project.
230
- # @return the Libraries group
231
- def libraries_group
232
- xcodeproj['Libraries']
233
- end
234
-
235
- # Remove the Libraries group from the xcodeproj in memory.
236
- # Resets @libraries_group to nil as well.
237
- def remove_libraries_group_from_project!
238
- # Remove links against these static libraries
239
- xcodeproj.targets.reject { |t| t.name =~ /-tvOS/ }.each do |t|
240
- remove_libraries_from_target t
241
- end
242
-
243
- log 'Removing Libraries group'
244
- libraries_group.remove_from_project
245
- end
246
-
247
- def remove_libraries_from_target(target)
248
- log "Removing Libraries from #{target.name}"
249
- to_remove = target.frameworks_build_phase.files.select do |file|
250
- path = file.file_ref.pretty_print
251
- next false unless /^lib(.+)\.a$/.match?(path)
252
-
253
- static_libs.include?(path)
254
- end
255
-
256
- to_remove.each { |f| target.frameworks_build_phase.remove_build_file f }
257
- end
258
-
259
- # A list of external dependencies from NPM requiring react-native link.
260
- # @return [Array<String>] a list of NPM package names
261
- def dependencies
262
- return [] if libraries_group.nil?
263
-
264
- dependency_paths.map do |path|
265
- # Find the root above the ios/*.xcodeproj under node_modules
266
- root = File.expand_path '../..', path
267
- File.basename root
268
- end
269
- end
270
-
271
- # Paths to Xcode projects in the Libraries group from external deps.
272
- # @return [Array<String>] a list of absolute paths to Xcode projects
273
- def dependency_paths
274
- return [] if libraries_group.nil?
275
-
276
- paths = libraries_group.children.reject { |c| DEFAULT_DEPENDENCIES.include?(c.name.sub(/\.xcodeproj$/, '')) }.map(&:path)
277
- paths.map { |p| File.expand_path p, File.join(Dir.pwd, 'ios') }
278
- end
279
-
280
- def library_roots
281
- libraries_group.children.map do |library|
282
- File.basename(library.path).sub(/\.xcodeproj$/, '')
283
- end
284
- end
285
-
286
- # All static libraries from the Libraries group
287
- # @return [Array<String>] an array of filenames
288
- def static_libs
289
- library_roots.map { |root| "lib#{root}.a" }
290
- end
291
-
292
230
  def load_subspecs_from_libraries
293
- roots = library_roots - %w[React]
294
- @subspecs_from_libraries = roots.select { |r| DEFAULT_DEPENDENCIES.include?(r) }.map do |root|
231
+ roots = project.library_roots - %w[React]
232
+ @subspecs_from_libraries = roots.select { |r| Project::DEFAULT_DEPENDENCIES.include?(r) }.map do |root|
295
233
  case root
296
234
  when 'RCTLinking'
297
235
  'RCTLinkingIOS'
@@ -308,18 +246,11 @@ module ReactNativeUtil
308
246
  end
309
247
 
310
248
  def app_target
311
- xcodeproj.targets.find { |t| t.name == app_name }
249
+ project.app_target
312
250
  end
313
251
 
314
252
  def test_target
315
- xcodeproj.targets.select(&:test_target_type?).reject { |t| t.name =~ /tvOS/ }.first
316
- end
317
-
318
- # Validate an assumption about the project. TODO: Provide override option.
319
- # @raise ConversionError if an application target is not found with the same name as the project.
320
- def validate_app_target!
321
- raise ConversionError, "Unable to find target #{app_name} in #{xcodeproj_path}." if app_target.nil?
322
- raise ConversionError, "Target #{app_name} is not an application target." unless app_target.product_type == 'com.apple.product-type.application'
253
+ project.test_target
323
254
  end
324
255
 
325
256
  def podfile_path
@@ -353,55 +284,11 @@ module ReactNativeUtil
353
284
  raise ConversionError, 'Uncommitted changes in repo. Please commit or stash before continuing.'
354
285
  end
355
286
 
356
- # Adds the Start Packager script from the React.xcodeproj under node_modules
357
- # to the main application target before deleting React.xcodeproj from the
358
- # Libraries group. Adjusts paths in the script to account for the different
359
- # project location. If React.xcodeproj cannot be opened, or if the relevant
360
- # build phase is not found, a warning is logged, and this step is skipped.
361
- #
362
- # TODO: The build phase is added after all other build phases. Ideally it
363
- # can be moved to the beginning. The packager is independent of the Xcode
364
- # build process. It may be started at any time. Starting it early is an
365
- # optimization that allows it to load while the build is in progress.
366
- # Currently it's possible to simply drag the build phase in Xcode to a
367
- # higher position after running the react_pod command.
368
- def add_packager_script
369
- old_packager_phase = packager_phase_from_react_project
370
- unless old_packager_phase
371
- log 'Could not find packager build phase in React.xcodeproj. Skipping.'.yellow
372
- return
373
- end
374
-
375
- # location of project is different relative to packager script
376
- script = old_packager_phase.shell_script.gsub(%r{../scripts}, '../node_modules/react-native/scripts')
377
-
378
- phase = app_target.new_shell_script_build_phase old_packager_phase.name
379
- phase.shell_script = script
380
- end
381
-
382
- # Returns a Project object with the contents of the React.xcodeproj project
383
- # from node_modules.
384
- # @return [Xcodeproj::Project] a Project object with the contents of React.xcodeproj from node_modules
287
+ # Load the contents of the React.xcodeproj project from node_modules.
385
288
  # @raise Xcodeproj::PlainInformative in case of most failures
386
- def react_project!
387
- return @react_project if @react_project
388
-
389
- path = libraries_group.children.find { |c| c.path =~ /React.xcodeproj/ }.real_path
390
- @react_project = Xcodeproj::Project.open path
391
- end
392
-
393
- # Returns the original Start Packager build phase from the React.xcodeproj
394
- # under node_modules. This contains the original script.
395
- # @return the packager build phase if found
396
- # @return nil if not found or React.xcodeproj cannot be opened
397
- def packager_phase_from_react_project
398
- react_project!.targets.first.build_phases.find { |p| p.name =~ /packager/i }
399
- rescue Errno::ENOENT
400
- log 'Could not open React.xcodeproj. File not found.'
401
- nil
402
- rescue Xcodeproj::PlainInformative => e
403
- log "Could not open React.xcodeproj. #{e.message}"
404
- nil
289
+ def load_react_project!
290
+ path = project.libraries_group.children.find { |c| c.path =~ /React.xcodeproj/ }.real_path
291
+ @react_project = Project.open path
405
292
  end
406
293
  end
407
294
  end
@@ -1,13 +1,13 @@
1
1
  module ReactNativeUtil
2
2
  # Base class for exceptions from this gem
3
- class ReactNativeUtilException < RuntimeError
3
+ class BaseException < RuntimeError
4
4
  end
5
5
 
6
6
  # Exception raised when command execution fails
7
- class ExecutionError < ReactNativeUtilException
7
+ class ExecutionError < BaseException
8
8
  end
9
9
 
10
10
  # Generic conversion error
11
- class ConversionError < ReactNativeUtilException
11
+ class ConversionError < BaseException
12
12
  end
13
13
  end
@@ -1,7 +1,7 @@
1
1
  # Conversion tools for React Native projects
2
2
  module ReactNativeUtil
3
3
  NAME = 'react_native_util'
4
- VERSION = '0.2.2'
4
+ VERSION = '0.3.0'
5
5
  SUMMARY = 'Community utility CLI for React Native projects'
6
6
  DESCRIPTION = 'Automatically modifies a project created with react-native ' \
7
7
  'init to use the React pod from node_modules.'
@@ -0,0 +1,141 @@
1
+ require 'xcodeproj'
2
+ require_relative 'util'
3
+
4
+ module ReactNativeUtil
5
+ class Project < Xcodeproj::Project
6
+ include Util
7
+
8
+ # [Array<String>] Xcode projects from react-native that may be in the Libraries group
9
+ DEFAULT_DEPENDENCIES = %w[
10
+ ART
11
+ React
12
+ RCTActionSheet
13
+ RCTAnimation
14
+ RCTBlob
15
+ RCTCameraRoll
16
+ RCTGeolocation
17
+ RCTImage
18
+ RCTLinking
19
+ RCTNetwork
20
+ RCTPushNotification
21
+ RCTSettings
22
+ RCTTest
23
+ RCTText
24
+ RCTVibration
25
+ RCTWebSocket
26
+ ]
27
+
28
+ attr_accessor :app_name
29
+
30
+ def app_target
31
+ targets.find { |t| t.name == app_name }
32
+ end
33
+
34
+ def test_target
35
+ targets.select(&:test_target_type?).reject { |t| t.name =~ /tvOS/ }.first
36
+ end
37
+
38
+ # Validate an assumption about the project. TODO: Provide override option.
39
+ # @raise ConversionError if an application target is not found with the same name as the project.
40
+ def validate_app_target!
41
+ raise ConversionError, "Unable to find target #{app_name} in #{path}." if app_target.nil?
42
+ raise ConversionError, "Target #{app_name} is not an application target." unless app_target.product_type == 'com.apple.product-type.application'
43
+ end
44
+
45
+ # A representation of the Libraries group (if any) from the Xcode project.
46
+ # @return the Libraries group
47
+ def libraries_group
48
+ self['Libraries']
49
+ end
50
+
51
+ # Remove the Libraries group from the xcodeproj in memory.
52
+ def remove_libraries_group
53
+ # Remove links against these static libraries
54
+ targets.reject { |t| t.name =~ /-tvOS/ }.each do |t|
55
+ remove_libraries_from_target t
56
+ end
57
+
58
+ log 'Removing Libraries group'
59
+ libraries_group.remove_from_project
60
+ end
61
+
62
+ def remove_libraries_from_target(target)
63
+ log "Removing Libraries from #{target.name}"
64
+ to_remove = target.frameworks_build_phase.files.select do |file|
65
+ path = file.file_ref.pretty_print
66
+ next false unless /^lib(.+)\.a$/.match?(path)
67
+
68
+ static_libs.include?(path)
69
+ end
70
+
71
+ to_remove.each { |f| target.frameworks_build_phase.remove_build_file f }
72
+ end
73
+
74
+ # A list of external dependencies from NPM requiring react-native link.
75
+ # @return [Array<String>] a list of NPM package names
76
+ def dependencies
77
+ return [] if libraries_group.nil?
78
+
79
+ dependency_paths.map do |path|
80
+ # Find the root above the ios/*.xcodeproj under node_modules
81
+ root = File.expand_path '../..', path
82
+ File.basename root
83
+ end
84
+ end
85
+
86
+ # Paths to Xcode projects in the Libraries group from external deps.
87
+ # @return [Array<String>] a list of absolute paths to Xcode projects
88
+ def dependency_paths
89
+ return [] if libraries_group.nil?
90
+
91
+ paths = libraries_group.children.reject { |c| DEFAULT_DEPENDENCIES.include?(c.name.sub(/\.xcodeproj$/, '')) }.map(&:path)
92
+ paths.map { |p| File.expand_path p, File.join(Dir.pwd, 'ios') }
93
+ end
94
+
95
+ def library_roots
96
+ libraries_group.children.map do |library|
97
+ File.basename(library.path).sub(/\.xcodeproj$/, '')
98
+ end
99
+ end
100
+
101
+ # Adds the Start Packager script from the React.xcodeproj under node_modules
102
+ # to the main application target before deleting React.xcodeproj from the
103
+ # Libraries group. Adjusts paths in the script to account for the different
104
+ # project location. If the relevant build phase is not found, a warning is
105
+ # logged, and this step is skipped.
106
+ #
107
+ # TODO: The build phase is added after all other build phases. Ideally it
108
+ # can be moved to the beginning. The packager is independent of the Xcode
109
+ # build process. It may be started at any time. Starting it early is an
110
+ # optimization that allows it to load while the build is in progress.
111
+ # Currently it's possible to simply drag the build phase in Xcode to a
112
+ # higher position after running the react_pod command.
113
+ def add_packager_script_from(react_project)
114
+ old_packager_phase = react_project.packager_phase
115
+ unless old_packager_phase
116
+ log 'Could not find packager build phase in React.xcodeproj. Skipping.'.yellow
117
+ return
118
+ end
119
+
120
+ # location of project is different relative to packager script
121
+ script = old_packager_phase.shell_script.gsub(%r{../scripts}, '../node_modules/react-native/scripts')
122
+
123
+ phase = app_target.new_shell_script_build_phase old_packager_phase.name
124
+ phase.shell_script = script
125
+ end
126
+
127
+ # All static libraries from the Libraries group
128
+ # @return [Array<String>] an array of filenames
129
+ def static_libs
130
+ library_roots.map { |root| "lib#{root}.a" }
131
+ end
132
+
133
+ # Returns the original Start Packager build phase (from the React.xcodeproj
134
+ # under node_modules). This contains the original script.
135
+ # @return the packager build phase if found
136
+ # @return nil if not found
137
+ def packager_phase
138
+ targets.first.build_phases.find { |p| p.name =~ /packager/i }
139
+ end
140
+ end
141
+ end
@@ -1,4 +1,6 @@
1
1
  require 'colored'
2
+ require 'tmpdir'
3
+ require 'tty/platform'
2
4
  require 'tty/spinner'
3
5
  require_relative 'core_ext/io'
4
6
  require_relative 'core_ext/regexp'
@@ -90,5 +92,58 @@ module ReactNativeUtil
90
92
  def log(message)
91
93
  STDOUT.log message
92
94
  end
95
+
96
+ # Determine if a specific command is available.
97
+ #
98
+ # @param command [#to_s] A command to check for
99
+ # @return true if found, false otherwise
100
+ def have_command?(command)
101
+ # May be shell-dependent, OS-dependent
102
+ # Kernel#system does not raise Errno::ENOENT when running under the Bundler
103
+ !`which #{command}`.empty?
104
+ end
105
+
106
+ # Validate one or more commands. If the specified command is not
107
+ # available in the PATH (via which), a ConversionError is raised noting
108
+ # the package to be installed (from Homebrew, e.g.).
109
+ #
110
+ # When package names to be installed differ from command names, a Hash
111
+ # may be used. For example:
112
+ # validate_commands! [:yarn, 'react-native' => 'react-native-cli']
113
+ #
114
+ # @param commands [Array, Hash, #to_s] one or more commands to be validated.
115
+ # @raise ConversionError if any command not found
116
+ def validate_commands!(commands)
117
+ errors = []
118
+
119
+ case commands
120
+ when Array
121
+ # Validate each command in the array, accumulating error messages
122
+ # if necessary.
123
+ commands.each do |c|
124
+ begin
125
+ validate_commands! c
126
+ rescue ConversionError => e
127
+ errors += e.message.split("\n")
128
+ end
129
+ end
130
+ when Hash
131
+ # Each key represents a command to check. The value is the package to
132
+ # install if missing.
133
+ commands.each do |key, value|
134
+ next if have_command?(key)
135
+
136
+ errors << "#{key} command not found. Please install #{value} to continue."
137
+ end
138
+ else
139
+ # commands is a single command to be validated. The package name is the
140
+ # same. Usually a symbol or a string, but only has to respond to #to_s.
141
+ errors << "#{commands} command not found. Please install #{commands} to continue." unless have_command? commands
142
+ end
143
+
144
+ return if errors.empty?
145
+
146
+ raise ConversionError, errors.join("\n")
147
+ end
93
148
  end
94
149
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: react_native_util
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.2
4
+ version: 0.3.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Jimmy Dee
@@ -229,6 +229,7 @@ files:
229
229
  - lib/react_native_util/core_ext/string.rb
230
230
  - lib/react_native_util/exceptions.rb
231
231
  - lib/react_native_util/metadata.rb
232
+ - lib/react_native_util/project.rb
232
233
  - lib/react_native_util/rake/react_pod_task.rb
233
234
  - lib/react_native_util/util.rb
234
235
  homepage: https://github.com/jdee/react_native_util