ruflet 0.0.14 → 0.0.16
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 +4 -4
- data/README.md +40 -1
- data/lib/ruflet/cli/android_sdk.rb +306 -0
- data/lib/ruflet/cli/build_command.rb +408 -30
- data/lib/ruflet/cli/environment_setup.rb +241 -0
- data/lib/ruflet/cli/extra_command.rb +15 -3
- data/lib/ruflet/cli/flutter_sdk.rb +87 -9
- data/lib/ruflet/cli/new_command.rb +41 -7
- data/lib/ruflet/cli/run_command.rb +106 -167
- data/lib/ruflet/cli.rb +13 -0
- data/lib/ruflet/version.rb +1 -1
- metadata +5 -2
|
@@ -17,12 +17,18 @@ require "yaml"
|
|
|
17
17
|
module Ruflet
|
|
18
18
|
module CLI
|
|
19
19
|
module RunCommand
|
|
20
|
+
DEFAULT_BACKEND_PORTS = {
|
|
21
|
+
"web" => 8550,
|
|
22
|
+
"desktop" => 8560,
|
|
23
|
+
"mobile" => 8570
|
|
24
|
+
}.freeze
|
|
25
|
+
|
|
20
26
|
def command_run(args)
|
|
21
|
-
options = { target: "mobile", requested_port:
|
|
27
|
+
options = { target: "mobile", requested_port: nil }
|
|
22
28
|
parser = OptionParser.new do |o|
|
|
23
29
|
o.on("--web") { options[:target] = "web" }
|
|
24
30
|
o.on("--desktop") { options[:target] = "desktop" }
|
|
25
|
-
o.on("--port PORT", Integer) { |v| options[:requested_port] = v }
|
|
31
|
+
o.on("--port PORT", Integer, "Backend port (defaults: web 8550, desktop 8560, mobile 8570)") { |v| options[:requested_port] = v }
|
|
26
32
|
end
|
|
27
33
|
parser.parse!(args)
|
|
28
34
|
|
|
@@ -34,18 +40,33 @@ module Ruflet
|
|
|
34
40
|
return 1
|
|
35
41
|
end
|
|
36
42
|
|
|
37
|
-
|
|
43
|
+
requested_port = options[:requested_port] || default_backend_port(options[:target])
|
|
44
|
+
selected_port = resolve_backend_port(options[:target], requested_port: requested_port)
|
|
38
45
|
return 1 unless selected_port
|
|
39
46
|
env = {
|
|
40
47
|
"RUFLET_TARGET" => options[:target],
|
|
41
48
|
"RUFLET_SUPPRESS_SERVER_BANNER" => "1",
|
|
42
|
-
"RUFLET_PORT" => selected_port.to_s
|
|
49
|
+
"RUFLET_PORT" => selected_port.to_s,
|
|
50
|
+
"RUFLET_STRICT_PORT" => "1"
|
|
43
51
|
}
|
|
44
52
|
apply_local_ruflet_dev_overrides(env)
|
|
45
53
|
assets_dir = File.join(File.dirname(script_path), "assets")
|
|
46
54
|
env["RUFLET_ASSETS_DIR"] = assets_dir if File.directory?(assets_dir)
|
|
47
55
|
|
|
48
|
-
|
|
56
|
+
# Web: the Ruby backend serves the Flutter web client itself (same
|
|
57
|
+
# origin/port as /ws), so no separate static server or proxy is needed.
|
|
58
|
+
if options[:target] == "web"
|
|
59
|
+
web_dir = detect_web_client_dir
|
|
60
|
+
if web_dir
|
|
61
|
+
env["RUFLET_WEB_CLIENT_DIR"] = web_dir
|
|
62
|
+
else
|
|
63
|
+
warn "Ruflet web client unavailable for version #{ruflet_version}."
|
|
64
|
+
warn "Install the matching GitHub release client before running --web."
|
|
65
|
+
return 1
|
|
66
|
+
end
|
|
67
|
+
end
|
|
68
|
+
|
|
69
|
+
print_run_banner(target: options[:target], requested_port: requested_port, port: selected_port)
|
|
49
70
|
print_mobile_qr_hint(port: selected_port) if options[:target] == "mobile"
|
|
50
71
|
|
|
51
72
|
gemfile_path = find_nearest_gemfile(Dir.pwd)
|
|
@@ -150,16 +171,14 @@ module Ruflet
|
|
|
150
171
|
|
|
151
172
|
def print_run_banner(target:, requested_port:, port:)
|
|
152
173
|
if port != requested_port.to_i
|
|
153
|
-
puts "
|
|
174
|
+
puts "Port #{requested_port} is busy; using #{port} for #{target}."
|
|
154
175
|
end
|
|
155
176
|
if target == "desktop"
|
|
156
177
|
puts "Ruflet desktop URL: http://localhost:#{port}"
|
|
157
178
|
elsif target == "mobile"
|
|
158
179
|
puts "Ruflet target: #{target}"
|
|
159
|
-
else
|
|
160
|
-
puts "Ruflet target: #{target}"
|
|
161
|
-
puts "Ruflet URL: http://localhost:#{port}"
|
|
162
180
|
end
|
|
181
|
+
# web: launch_web_client prints the single app URL after the server boots
|
|
163
182
|
end
|
|
164
183
|
|
|
165
184
|
def launch_target_client(target, port)
|
|
@@ -175,30 +194,19 @@ module Ruflet
|
|
|
175
194
|
end
|
|
176
195
|
end
|
|
177
196
|
|
|
197
|
+
# The Ruby backend (Ruflet::Server) serves the Flutter web client on its
|
|
198
|
+
# own port, so the client loads and opens its websocket on that same
|
|
199
|
+
# origin. The prebuilt web client derives its backend from Uri.base, so
|
|
200
|
+
# the public URL stays clean and dynamic port selection works naturally.
|
|
178
201
|
def launch_web_client(port)
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
web_port = find_available_port(port + 1)
|
|
186
|
-
web_pid = Process.spawn("python3", "-m", "http.server", web_port.to_s, "--bind", "127.0.0.1", chdir: web_dir, out: File::NULL, err: File::NULL)
|
|
187
|
-
Process.detach(web_pid)
|
|
188
|
-
wait_for_server_boot(web_port)
|
|
189
|
-
backend_url = "http://localhost:#{port}"
|
|
190
|
-
web_url = "http://localhost:#{web_port}/?#{URI.encode_www_form(url: backend_url)}"
|
|
191
|
-
browser_pid = open_in_browser_app_mode(web_url)
|
|
192
|
-
open_in_browser(web_url) if browser_pid.nil?
|
|
193
|
-
puts "Ruflet web client: #{web_url}"
|
|
194
|
-
puts "Ruflet backend ws: ws://localhost:#{port}/ws"
|
|
195
|
-
[web_pid, browser_pid].compact
|
|
196
|
-
rescue Errno::ENOENT
|
|
197
|
-
warn "python3 is required to host web client locally."
|
|
198
|
-
warn "Install Python 3 and rerun."
|
|
199
|
-
[]
|
|
202
|
+
url = "http://localhost:#{port}/"
|
|
203
|
+
browser_pid = open_in_browser_app_mode(url)
|
|
204
|
+
open_in_browser(url) if browser_pid.nil?
|
|
205
|
+
puts "Ruflet web app: #{url}"
|
|
206
|
+
[browser_pid].compact
|
|
200
207
|
rescue StandardError => e
|
|
201
|
-
warn "Failed to
|
|
208
|
+
warn "Failed to open web client: #{e.class}: #{e.message}"
|
|
209
|
+
warn "Open it manually: http://localhost:#{port}/"
|
|
202
210
|
[]
|
|
203
211
|
end
|
|
204
212
|
|
|
@@ -286,7 +294,7 @@ module Ruflet
|
|
|
286
294
|
end
|
|
287
295
|
|
|
288
296
|
def launch_desktop_client(url)
|
|
289
|
-
cmd =
|
|
297
|
+
cmd = detect_desktop_client_command(url)
|
|
290
298
|
unless cmd
|
|
291
299
|
warn "Desktop client executable not found."
|
|
292
300
|
warn "Set RUFLET_CLIENT_DIR to your client path."
|
|
@@ -307,119 +315,37 @@ module Ruflet
|
|
|
307
315
|
[]
|
|
308
316
|
end
|
|
309
317
|
|
|
310
|
-
def
|
|
311
|
-
|
|
312
|
-
return nil unless respond_to?(:ensure_flutter_client_dir, true)
|
|
313
|
-
return nil unless respond_to?(:prepare_flutter_client, true)
|
|
314
|
-
return nil unless respond_to?(:ensure_flutter!, true)
|
|
315
|
-
|
|
316
|
-
platform = host_platform_name
|
|
317
|
-
return nil unless %w[macos windows linux].include?(platform)
|
|
318
|
-
|
|
319
|
-
ensure_ruflet_build_assets(verbose: false) if respond_to?(:ensure_ruflet_build_assets, true)
|
|
320
|
-
client_dir = ensure_flutter_client_dir(verbose: false)
|
|
321
|
-
return nil unless client_dir
|
|
322
|
-
|
|
323
|
-
config = project_run_config
|
|
324
|
-
tools = ensure_flutter!("run", client_dir: client_dir)
|
|
325
|
-
env = build_tool_env(tools[:env], platform, client_dir)
|
|
326
|
-
return nil unless prepare_flutter_client(
|
|
327
|
-
client_dir,
|
|
328
|
-
platform: platform,
|
|
329
|
-
tools: tools,
|
|
330
|
-
config: config,
|
|
331
|
-
self_contained: false,
|
|
332
|
-
verbose: false
|
|
333
|
-
)
|
|
334
|
-
|
|
335
|
-
[
|
|
336
|
-
env,
|
|
337
|
-
tools[:flutter],
|
|
338
|
-
"run",
|
|
339
|
-
"-d",
|
|
340
|
-
platform,
|
|
341
|
-
"--target",
|
|
342
|
-
"lib/main.server.dart",
|
|
343
|
-
"--dart-define",
|
|
344
|
-
"RUFLET_BACKEND_URL=#{url}"
|
|
345
|
-
]
|
|
346
|
-
rescue StandardError => e
|
|
347
|
-
warn "Project desktop client setup failed: #{e.class}: #{e.message}"
|
|
348
|
-
nil
|
|
349
|
-
end
|
|
350
|
-
|
|
351
|
-
def project_run_requires_managed_client?
|
|
352
|
-
return false unless defined?(Ruflet::CLI::BuildCommand::CLIENT_EXTENSION_MAP)
|
|
353
|
-
|
|
354
|
-
services = Array(project_run_config["services"]).map { |value| normalize_run_extension_key(value) }.compact
|
|
355
|
-
return false if services.empty?
|
|
356
|
-
|
|
357
|
-
extension_keys = Ruflet::CLI::BuildCommand::CLIENT_EXTENSION_MAP.keys
|
|
358
|
-
(services & extension_keys).any?
|
|
359
|
-
end
|
|
360
|
-
|
|
361
|
-
def project_run_config
|
|
362
|
-
config_path = ENV["RUFLET_CONFIG"] || (File.file?("ruflet.yaml") ? "ruflet.yaml" : "ruflet.yml")
|
|
363
|
-
return {} unless File.file?(config_path)
|
|
364
|
-
|
|
365
|
-
YAML.safe_load(File.read(config_path), aliases: true) || {}
|
|
366
|
-
rescue StandardError
|
|
367
|
-
{}
|
|
368
|
-
end
|
|
318
|
+
def detect_desktop_client_command(url)
|
|
319
|
+
root = configured_client_root
|
|
369
320
|
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
return nil if key.empty?
|
|
321
|
+
command = desktop_client_command_from_root(root, url)
|
|
322
|
+
return command if command
|
|
373
323
|
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
key.gsub!(/\Aservice_/, "")
|
|
377
|
-
key
|
|
324
|
+
cached_root = ensure_prebuilt_client(desktop: true)
|
|
325
|
+
desktop_client_command_from_root(cached_root, url)
|
|
378
326
|
end
|
|
379
327
|
|
|
380
|
-
def
|
|
381
|
-
root = ENV["RUFLET_CLIENT_DIR"]
|
|
382
|
-
root = File.expand_path("ruflet_client", Dir.pwd) if root.to_s.strip.empty?
|
|
383
|
-
root = nil unless Dir.exist?(root)
|
|
384
|
-
root ||= ensure_prebuilt_client(desktop: true)
|
|
328
|
+
def desktop_client_command_from_root(root, url)
|
|
385
329
|
return nil unless root && Dir.exist?(root)
|
|
386
330
|
|
|
387
331
|
host_os = RbConfig::CONFIG["host_os"]
|
|
388
332
|
if host_os.match?(/darwin/i)
|
|
389
|
-
app_path =
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
File.join(root, "desktop", "ruflet_client.app")
|
|
393
|
-
].find do |candidate|
|
|
394
|
-
bin = File.join(candidate, "Contents", "MacOS", "ruflet_client")
|
|
395
|
-
File.file?(bin) && File.executable?(bin) && ensure_macos_file_picker_entitlement(candidate)
|
|
396
|
-
end
|
|
397
|
-
return [File.join(app_path, "Contents", "MacOS", "ruflet_client"), url] if app_path
|
|
333
|
+
app_path = File.join(root, "desktop", "ruflet_client.app")
|
|
334
|
+
bin = File.join(app_path, "Contents", "MacOS", "ruflet_client")
|
|
335
|
+
return [bin, url] if File.file?(bin) && File.executable?(bin) && ensure_macos_file_picker_entitlement(app_path)
|
|
398
336
|
elsif host_os.match?(/mswin|mingw|cygwin/i)
|
|
399
|
-
exe = File.join(root, "
|
|
400
|
-
prebuilt = File.join(root, "desktop", "ruflet_client.exe")
|
|
401
|
-
exe = prebuilt if !File.file?(exe) && File.file?(prebuilt)
|
|
337
|
+
exe = File.join(root, "desktop", "ruflet_client.exe")
|
|
402
338
|
return [exe, url] if File.file?(exe)
|
|
403
339
|
else
|
|
404
|
-
direct = File.join(root, "
|
|
405
|
-
prebuilt_direct = File.join(root, "desktop", "ruflet_client")
|
|
406
|
-
direct = prebuilt_direct if !File.file?(direct) && File.file?(prebuilt_direct)
|
|
340
|
+
direct = File.join(root, "desktop", "ruflet_client")
|
|
407
341
|
return [direct, url] if File.file?(direct)
|
|
408
|
-
bundle_dir = File.join(root, "build", "linux", "x64", "release", "bundle")
|
|
409
|
-
if Dir.exist?(bundle_dir)
|
|
410
|
-
candidate = Dir.children(bundle_dir).map { |f| File.join(bundle_dir, f) }
|
|
411
|
-
.find { |path| File.file?(path) && File.executable?(path) }
|
|
412
|
-
return [candidate, url] if candidate
|
|
413
|
-
end
|
|
414
342
|
end
|
|
415
343
|
|
|
416
344
|
nil
|
|
417
345
|
end
|
|
418
346
|
|
|
419
347
|
def detect_web_client_dir
|
|
420
|
-
root =
|
|
421
|
-
root = File.expand_path("ruflet_client", Dir.pwd) if root.to_s.strip.empty?
|
|
422
|
-
root = nil unless Dir.exist?(root)
|
|
348
|
+
root = configured_client_root
|
|
423
349
|
root ||= ensure_prebuilt_client(web: true)
|
|
424
350
|
return nil unless root && Dir.exist?(root)
|
|
425
351
|
|
|
@@ -431,6 +357,14 @@ module Ruflet
|
|
|
431
357
|
nil
|
|
432
358
|
end
|
|
433
359
|
|
|
360
|
+
def configured_client_root
|
|
361
|
+
root = ENV["RUFLET_CLIENT_DIR"].to_s.strip
|
|
362
|
+
return nil if root.empty?
|
|
363
|
+
|
|
364
|
+
expanded = File.expand_path(root)
|
|
365
|
+
Dir.exist?(expanded) ? expanded : nil
|
|
366
|
+
end
|
|
367
|
+
|
|
434
368
|
def ensure_prebuilt_client(web: false, desktop: false, platform: nil, force: false)
|
|
435
369
|
platform ||= host_platform_name
|
|
436
370
|
return nil if platform.nil?
|
|
@@ -445,10 +379,12 @@ module Ruflet
|
|
|
445
379
|
return nil if desktop_asset.nil?
|
|
446
380
|
wanted_assets << { kind: :desktop, name: desktop_asset, platform: platform }
|
|
447
381
|
end
|
|
448
|
-
|
|
449
|
-
|
|
382
|
+
cached = prebuilt_assets_present?(cache_root, web: web, desktop: desktop, platform: platform)
|
|
383
|
+
compatible_cache = cached && compatible_client_cache?(cache_root, platform: platform)
|
|
384
|
+
if !force && (wanted_assets.empty? || compatible_cache)
|
|
450
385
|
return cache_root
|
|
451
386
|
end
|
|
387
|
+
force = true if cached && !compatible_cache
|
|
452
388
|
|
|
453
389
|
release = fetch_release_for_version
|
|
454
390
|
return nil unless release
|
|
@@ -544,11 +480,33 @@ module Ruflet
|
|
|
544
480
|
end
|
|
545
481
|
|
|
546
482
|
def fetch_release_for_version
|
|
547
|
-
|
|
548
|
-
release_by_tag(
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
|
|
483
|
+
client_release_tags.each do |tag|
|
|
484
|
+
release = release_by_tag(tag)
|
|
485
|
+
return release if release
|
|
486
|
+
end
|
|
487
|
+
|
|
488
|
+
nil
|
|
489
|
+
end
|
|
490
|
+
|
|
491
|
+
def client_release_tags
|
|
492
|
+
channel = ENV["RUFLET_CLIENT_CHANNEL"].to_s.strip
|
|
493
|
+
unless channel.empty?
|
|
494
|
+
raise ArgumentError, "Invalid RUFLET_CLIENT_CHANNEL" unless channel.match?(/\A[A-Za-z0-9._-]+\z/)
|
|
495
|
+
|
|
496
|
+
return [channel]
|
|
497
|
+
end
|
|
498
|
+
|
|
499
|
+
["v#{ruflet_version}", ruflet_version]
|
|
500
|
+
end
|
|
501
|
+
|
|
502
|
+
def compatible_client_cache?(root, platform:)
|
|
503
|
+
manifest = read_client_manifest(root)
|
|
504
|
+
return false unless manifest
|
|
505
|
+
|
|
506
|
+
manifest["schema"] == 1 &&
|
|
507
|
+
manifest["ruflet_version"] == ruflet_version &&
|
|
508
|
+
manifest["platform"] == platform &&
|
|
509
|
+
client_release_tags.include?(manifest["release_tag"])
|
|
552
510
|
end
|
|
553
511
|
|
|
554
512
|
def ruflet_version
|
|
@@ -558,10 +516,6 @@ module Ruflet
|
|
|
558
516
|
Ruflet::VERSION
|
|
559
517
|
end
|
|
560
518
|
|
|
561
|
-
def release_latest
|
|
562
|
-
github_get_json("https://api.github.com/repos/AdamMusa/Ruflet/releases/latest")
|
|
563
|
-
end
|
|
564
|
-
|
|
565
519
|
def release_by_tag(tag)
|
|
566
520
|
github_get_json("https://api.github.com/repos/AdamMusa/Ruflet/releases/tags/#{tag}")
|
|
567
521
|
rescue StandardError
|
|
@@ -731,19 +685,6 @@ module Ruflet
|
|
|
731
685
|
nil
|
|
732
686
|
end
|
|
733
687
|
|
|
734
|
-
def ensure_client_manifest(root, platform:)
|
|
735
|
-
return if read_client_manifest(root)
|
|
736
|
-
|
|
737
|
-
assets = []
|
|
738
|
-
assets << { "kind" => "web", "platform" => platform, "asset_name" => nil } if File.file?(File.join(root, "web", "index.html"))
|
|
739
|
-
if prebuilt_desktop_present?(root, platform: platform)
|
|
740
|
-
assets << { "kind" => "desktop", "platform" => platform, "asset_name" => nil }
|
|
741
|
-
end
|
|
742
|
-
return if assets.empty?
|
|
743
|
-
|
|
744
|
-
write_client_manifest(root, platform: platform, release: nil, assets: assets)
|
|
745
|
-
end
|
|
746
|
-
|
|
747
688
|
def write_client_manifest(root, platform:, release:, assets:)
|
|
748
689
|
FileUtils.mkdir_p(root)
|
|
749
690
|
payload = {
|
|
@@ -776,26 +717,24 @@ module Ruflet
|
|
|
776
717
|
port = start_port.to_i
|
|
777
718
|
|
|
778
719
|
max_attempts.times do
|
|
779
|
-
|
|
780
|
-
|
|
781
|
-
|
|
782
|
-
rescue Errno::EACCES, Errno::EPERM
|
|
783
|
-
probe = TCPServer.new("127.0.0.1", port)
|
|
784
|
-
end
|
|
785
|
-
probe.close
|
|
786
|
-
return port
|
|
787
|
-
rescue Errno::EADDRINUSE, Errno::EACCES, Errno::EPERM
|
|
788
|
-
port += 1
|
|
789
|
-
end
|
|
720
|
+
return port if port_available?(port)
|
|
721
|
+
|
|
722
|
+
port += 1
|
|
790
723
|
end
|
|
791
724
|
|
|
792
|
-
|
|
725
|
+
nil
|
|
726
|
+
end
|
|
727
|
+
|
|
728
|
+
def default_backend_port(target)
|
|
729
|
+
DEFAULT_BACKEND_PORTS.fetch(target.to_s, DEFAULT_BACKEND_PORTS.fetch("mobile"))
|
|
793
730
|
end
|
|
794
731
|
|
|
795
|
-
def resolve_backend_port(
|
|
732
|
+
def resolve_backend_port(target, requested_port: nil)
|
|
796
733
|
base = requested_port.to_i
|
|
797
|
-
base =
|
|
798
|
-
find_available_port(base)
|
|
734
|
+
base = default_backend_port(target) if base <= 0
|
|
735
|
+
selected = find_available_port(base)
|
|
736
|
+
warn "No available Ruflet port found starting at #{base}." unless selected
|
|
737
|
+
selected
|
|
799
738
|
end
|
|
800
739
|
|
|
801
740
|
def port_available?(port)
|
|
@@ -807,7 +746,7 @@ module Ruflet
|
|
|
807
746
|
probe = TCPServer.new("127.0.0.1", port)
|
|
808
747
|
end
|
|
809
748
|
true
|
|
810
|
-
rescue Errno::EADDRINUSE
|
|
749
|
+
rescue Errno::EADDRINUSE, Errno::EACCES, Errno::EPERM
|
|
811
750
|
false
|
|
812
751
|
ensure
|
|
813
752
|
probe&.close
|
data/lib/ruflet/cli.rb
CHANGED
|
@@ -2,10 +2,23 @@
|
|
|
2
2
|
|
|
3
3
|
require "optparse"
|
|
4
4
|
|
|
5
|
+
# Project files (pbxproj, plists, embedded runtime sources) are UTF-8; never
|
|
6
|
+
# depend on the caller's locale for reading them.
|
|
7
|
+
Encoding.default_external = Encoding::UTF_8 if Encoding.default_external == Encoding::US_ASCII
|
|
8
|
+
|
|
9
|
+
# Provisioning (downloads, package installs, SDK extraction) can run for
|
|
10
|
+
# minutes. When stdout is not a TTY (CI logs, pipes, editor consoles) Ruby
|
|
11
|
+
# buffers it, so progress notes would only appear once the whole run finishes.
|
|
12
|
+
# Unbuffer both streams so the pipeline reports progress as it happens.
|
|
13
|
+
$stdout.sync = true
|
|
14
|
+
$stderr.sync = true
|
|
15
|
+
|
|
5
16
|
require_relative "version"
|
|
6
17
|
require_relative "cli/templates"
|
|
7
18
|
require_relative "cli/new_command"
|
|
8
19
|
require_relative "cli/flutter_sdk"
|
|
20
|
+
require_relative "cli/environment_setup"
|
|
21
|
+
require_relative "cli/android_sdk"
|
|
9
22
|
require_relative "cli/run_command"
|
|
10
23
|
require_relative "cli/update_command"
|
|
11
24
|
require_relative "cli/build_command"
|
data/lib/ruflet/version.rb
CHANGED
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: ruflet
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.0.
|
|
4
|
+
version: 0.0.16
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- AdamMusa
|
|
@@ -37,7 +37,9 @@ files:
|
|
|
37
37
|
- assets/splash.png
|
|
38
38
|
- bin/ruflet
|
|
39
39
|
- lib/ruflet/cli.rb
|
|
40
|
+
- lib/ruflet/cli/android_sdk.rb
|
|
40
41
|
- lib/ruflet/cli/build_command.rb
|
|
42
|
+
- lib/ruflet/cli/environment_setup.rb
|
|
41
43
|
- lib/ruflet/cli/extra_command.rb
|
|
42
44
|
- lib/ruflet/cli/flutter_sdk.rb
|
|
43
45
|
- lib/ruflet/cli/new_command.rb
|
|
@@ -47,7 +49,8 @@ files:
|
|
|
47
49
|
- lib/ruflet/version.rb
|
|
48
50
|
- lib/ruflet_cli.rb
|
|
49
51
|
homepage: https://github.com/AdamMusa/Ruflet
|
|
50
|
-
licenses:
|
|
52
|
+
licenses:
|
|
53
|
+
- MIT
|
|
51
54
|
metadata: {}
|
|
52
55
|
rdoc_options: []
|
|
53
56
|
require_paths:
|