ruflet_cli 0.0.1
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 +7 -0
- data/README.md +3 -0
- data/bin/ruflet +6 -0
- data/lib/ruflet/cli/build_command.rb +64 -0
- data/lib/ruflet/cli/new_command.rb +44 -0
- data/lib/ruflet/cli/run_command.rb +175 -0
- data/lib/ruflet/cli/templates.rb +94 -0
- data/lib/ruflet/cli.rb +53 -0
- data/lib/ruflet/version.rb +5 -0
- data/lib/ruflet_cli.rb +3 -0
- metadata +63 -0
checksums.yaml
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
---
|
|
2
|
+
SHA256:
|
|
3
|
+
metadata.gz: c2afb6fb7d347d71d74263f24813988c2b1dbd8f9fa686483983ac5e9a304035
|
|
4
|
+
data.tar.gz: 8ca131cf5f28652f03fe6b78ede64c114e2aa9f54bef456889b3ab548c4d09d2
|
|
5
|
+
SHA512:
|
|
6
|
+
metadata.gz: c425acd4231c1b8ee4b9b8528420d77de3142d935af203675493da4ca2848dc8fea8a2c3e7f6e109feab106546b7c93a8ac027934f1675e0a9dd5260489f5a64
|
|
7
|
+
data.tar.gz: 1ebf882ccd5fb64c1a6741cf48e78adb85f95e579a42b85938556961e8b0c21ad2fdb983518eda64b28a9a31a272f5d5a99a1752db56196831a432ee92e6dcf6
|
data/README.md
ADDED
data/bin/ruflet
ADDED
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Ruflet
|
|
4
|
+
module CLI
|
|
5
|
+
module BuildCommand
|
|
6
|
+
def command_build(args)
|
|
7
|
+
platform = (args.shift || "").downcase
|
|
8
|
+
if platform.empty?
|
|
9
|
+
warn "Usage: ruflet build <apk|ios|aab|web|macos|windows|linux>"
|
|
10
|
+
return 1
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
flutter_cmd = flutter_build_command(platform)
|
|
14
|
+
unless flutter_cmd
|
|
15
|
+
warn "Unsupported build target: #{platform}"
|
|
16
|
+
return 1
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
client_dir = detect_flutter_client_dir
|
|
20
|
+
unless client_dir
|
|
21
|
+
warn "Could not find Flutter client directory."
|
|
22
|
+
warn "Set RUFLET_CLIENT_DIR or place client at ./ruflet_client"
|
|
23
|
+
return 1
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
ok = system(*flutter_cmd, chdir: client_dir)
|
|
27
|
+
ok ? 0 : 1
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
private
|
|
31
|
+
|
|
32
|
+
def detect_flutter_client_dir
|
|
33
|
+
env_dir = ENV["RUFLET_CLIENT_DIR"]
|
|
34
|
+
return env_dir if env_dir && Dir.exist?(env_dir)
|
|
35
|
+
|
|
36
|
+
local = File.expand_path("ruflet_client", Dir.pwd)
|
|
37
|
+
return local if Dir.exist?(local)
|
|
38
|
+
|
|
39
|
+
nil
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
def flutter_build_command(platform)
|
|
43
|
+
case platform
|
|
44
|
+
when "apk", "android"
|
|
45
|
+
["flutter", "build", "apk"]
|
|
46
|
+
when "aab", "appbundle"
|
|
47
|
+
["flutter", "build", "appbundle"]
|
|
48
|
+
when "ios"
|
|
49
|
+
["flutter", "build", "ios", "--no-codesign"]
|
|
50
|
+
when "web"
|
|
51
|
+
["flutter", "build", "web"]
|
|
52
|
+
when "macos"
|
|
53
|
+
["flutter", "build", "macos"]
|
|
54
|
+
when "windows"
|
|
55
|
+
["flutter", "build", "windows"]
|
|
56
|
+
when "linux"
|
|
57
|
+
["flutter", "build", "linux"]
|
|
58
|
+
else
|
|
59
|
+
nil
|
|
60
|
+
end
|
|
61
|
+
end
|
|
62
|
+
end
|
|
63
|
+
end
|
|
64
|
+
end
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "fileutils"
|
|
4
|
+
|
|
5
|
+
module Ruflet
|
|
6
|
+
module CLI
|
|
7
|
+
module NewCommand
|
|
8
|
+
def command_new(args)
|
|
9
|
+
app_name = args.shift
|
|
10
|
+
if app_name.nil? || app_name.strip.empty?
|
|
11
|
+
warn "Usage: ruflet new <appname>"
|
|
12
|
+
return 1
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
root = File.expand_path(app_name, Dir.pwd)
|
|
16
|
+
if Dir.exist?(root)
|
|
17
|
+
warn "Directory already exists: #{root}"
|
|
18
|
+
return 1
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
FileUtils.mkdir_p(root)
|
|
22
|
+
FileUtils.mkdir_p(File.join(root, ".bundle"))
|
|
23
|
+
File.write(File.join(root, "main.rb"), format(Ruflet::CLI::MAIN_TEMPLATE, app_title: humanize_name(File.basename(root))))
|
|
24
|
+
File.write(File.join(root, "Gemfile"), Ruflet::CLI::GEMFILE_TEMPLATE)
|
|
25
|
+
File.write(File.join(root, ".bundle", "config"), Ruflet::CLI::BUNDLE_CONFIG_TEMPLATE)
|
|
26
|
+
File.write(File.join(root, "README.md"), format(Ruflet::CLI::README_TEMPLATE, app_name: File.basename(root)))
|
|
27
|
+
|
|
28
|
+
project_name = File.basename(root)
|
|
29
|
+
puts "Ruflet app created: #{project_name}"
|
|
30
|
+
puts "Run:"
|
|
31
|
+
puts " cd #{project_name}"
|
|
32
|
+
puts " bundle install"
|
|
33
|
+
puts " bundle exec ruflet run main"
|
|
34
|
+
0
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
private
|
|
38
|
+
|
|
39
|
+
def humanize_name(name)
|
|
40
|
+
name.to_s.gsub(/[_-]+/, " ").split.map(&:capitalize).join(" ")
|
|
41
|
+
end
|
|
42
|
+
end
|
|
43
|
+
end
|
|
44
|
+
end
|
|
@@ -0,0 +1,175 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "optparse"
|
|
4
|
+
require "rbconfig"
|
|
5
|
+
require "socket"
|
|
6
|
+
|
|
7
|
+
module Ruflet
|
|
8
|
+
module CLI
|
|
9
|
+
module RunCommand
|
|
10
|
+
def command_run(args)
|
|
11
|
+
options = { target: "mobile" }
|
|
12
|
+
parser = OptionParser.new do |o|
|
|
13
|
+
o.on("--web") { options[:target] = "web" }
|
|
14
|
+
o.on("--mobile") { options[:target] = "mobile" }
|
|
15
|
+
o.on("--desktop") { options[:target] = "desktop" }
|
|
16
|
+
end
|
|
17
|
+
parser.parse!(args)
|
|
18
|
+
|
|
19
|
+
script_token = args.shift || "main"
|
|
20
|
+
script_path = resolve_script(script_token)
|
|
21
|
+
unless script_path
|
|
22
|
+
warn "Script not found: #{script_token}"
|
|
23
|
+
warn "Expected: ./#{script_token}.rb, ./#{script_token}, or explicit file path."
|
|
24
|
+
return 1
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
selected_port = find_available_port(8550)
|
|
28
|
+
env = {
|
|
29
|
+
"RUFLET_TARGET" => options[:target],
|
|
30
|
+
"RUFLET_SUPPRESS_SERVER_BANNER" => "1",
|
|
31
|
+
"RUFLET_PORT" => selected_port.to_s
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
puts "Requested port 8550 is busy; bound to #{selected_port}" if selected_port != 8550
|
|
35
|
+
print_mobile_qr_hint(port: selected_port) if options[:target] == "mobile"
|
|
36
|
+
|
|
37
|
+
cmd =
|
|
38
|
+
if File.file?(File.expand_path("Gemfile", Dir.pwd))
|
|
39
|
+
env["BUNDLE_PATH"] = "vendor/bundle"
|
|
40
|
+
env["BUNDLE_DISABLE_SHARED_GEMS"] = "true"
|
|
41
|
+
bundle_ready = system(env, "bundle", "check", out: File::NULL, err: File::NULL)
|
|
42
|
+
return 1 unless bundle_ready || system(env, "bundle", "install")
|
|
43
|
+
|
|
44
|
+
["bundle", "exec", RbConfig.ruby, script_path]
|
|
45
|
+
else
|
|
46
|
+
[RbConfig.ruby, script_path]
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
child_pid = Process.spawn(env, *cmd, pgroup: true)
|
|
50
|
+
forward_signal = lambda do |signal|
|
|
51
|
+
begin
|
|
52
|
+
Process.kill(signal, -child_pid)
|
|
53
|
+
rescue Errno::ESRCH
|
|
54
|
+
nil
|
|
55
|
+
end
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
previous_int = Signal.trap("INT") { forward_signal.call("INT") }
|
|
59
|
+
previous_term = Signal.trap("TERM") { forward_signal.call("TERM") }
|
|
60
|
+
|
|
61
|
+
_pid, status = Process.wait2(child_pid)
|
|
62
|
+
status.success? ? 0 : (status.exitstatus || 1)
|
|
63
|
+
ensure
|
|
64
|
+
Signal.trap("INT", previous_int) if defined?(previous_int) && previous_int
|
|
65
|
+
Signal.trap("TERM", previous_term) if defined?(previous_term) && previous_term
|
|
66
|
+
|
|
67
|
+
if defined?(child_pid) && child_pid
|
|
68
|
+
begin
|
|
69
|
+
Process.kill("TERM", -child_pid)
|
|
70
|
+
rescue Errno::ESRCH
|
|
71
|
+
nil
|
|
72
|
+
end
|
|
73
|
+
end
|
|
74
|
+
end
|
|
75
|
+
|
|
76
|
+
private
|
|
77
|
+
|
|
78
|
+
def resolve_script(token)
|
|
79
|
+
path = File.expand_path(token, Dir.pwd)
|
|
80
|
+
return path if File.file?(path)
|
|
81
|
+
|
|
82
|
+
candidate = File.expand_path("#{token}.rb", Dir.pwd)
|
|
83
|
+
return candidate if File.file?(candidate)
|
|
84
|
+
|
|
85
|
+
nil
|
|
86
|
+
end
|
|
87
|
+
|
|
88
|
+
def print_mobile_qr_hint(port: 8550)
|
|
89
|
+
host = best_lan_host
|
|
90
|
+
payload = "http://#{host}:#{port}"
|
|
91
|
+
|
|
92
|
+
puts
|
|
93
|
+
puts "Ruflet mobile connect URL:"
|
|
94
|
+
puts " #{payload}"
|
|
95
|
+
puts "Ruflet server ws URL:"
|
|
96
|
+
puts " ws://0.0.0.0:#{port}/ws"
|
|
97
|
+
puts "Scan this QR from ruflet_client (Connect -> Scan QR):"
|
|
98
|
+
print_ascii_qr(payload)
|
|
99
|
+
puts
|
|
100
|
+
rescue StandardError => e
|
|
101
|
+
warn "QR setup failed: #{e.class}: #{e.message}"
|
|
102
|
+
end
|
|
103
|
+
|
|
104
|
+
def find_available_port(start_port, max_attempts: 100)
|
|
105
|
+
port = start_port.to_i
|
|
106
|
+
|
|
107
|
+
max_attempts.times do
|
|
108
|
+
begin
|
|
109
|
+
begin
|
|
110
|
+
probe = TCPServer.new("0.0.0.0", port)
|
|
111
|
+
rescue Errno::EACCES, Errno::EPERM
|
|
112
|
+
probe = TCPServer.new("127.0.0.1", port)
|
|
113
|
+
end
|
|
114
|
+
probe.close
|
|
115
|
+
return port
|
|
116
|
+
rescue Errno::EADDRINUSE
|
|
117
|
+
port += 1
|
|
118
|
+
end
|
|
119
|
+
end
|
|
120
|
+
|
|
121
|
+
start_port
|
|
122
|
+
end
|
|
123
|
+
|
|
124
|
+
def best_lan_host
|
|
125
|
+
ips = Socket.ip_address_list
|
|
126
|
+
addr = ips.find { |ip| ip.ipv4_private? && !ip.ipv4_loopback? }
|
|
127
|
+
return addr.ip_address if addr
|
|
128
|
+
|
|
129
|
+
"127.0.0.1"
|
|
130
|
+
end
|
|
131
|
+
|
|
132
|
+
def print_ascii_qr(payload)
|
|
133
|
+
begin
|
|
134
|
+
require "rqrcode"
|
|
135
|
+
rescue LoadError
|
|
136
|
+
puts "(Install 'rqrcode' gem in CLI package for terminal QR rendering.)"
|
|
137
|
+
return
|
|
138
|
+
end
|
|
139
|
+
|
|
140
|
+
q = RQRCode::QRCode.new(payload)
|
|
141
|
+
border = 1
|
|
142
|
+
core = q.modules
|
|
143
|
+
size = core.length + (2 * border)
|
|
144
|
+
|
|
145
|
+
matrix = Array.new(size) do |y|
|
|
146
|
+
Array.new(size) do |x|
|
|
147
|
+
cy = y - border
|
|
148
|
+
cx = x - border
|
|
149
|
+
cy >= 0 && cx >= 0 && cy < core.length && cx < core.length && core[cy][cx]
|
|
150
|
+
end
|
|
151
|
+
end
|
|
152
|
+
|
|
153
|
+
y = 0
|
|
154
|
+
while y < size
|
|
155
|
+
line = +""
|
|
156
|
+
(0...size).each do |x|
|
|
157
|
+
top = matrix[y][x]
|
|
158
|
+
bottom = (y + 1 < size) ? matrix[y + 1][x] : false
|
|
159
|
+
line << if top && bottom
|
|
160
|
+
"\u2588"
|
|
161
|
+
elsif top
|
|
162
|
+
"\u2580"
|
|
163
|
+
elsif bottom
|
|
164
|
+
"\u2584"
|
|
165
|
+
else
|
|
166
|
+
" "
|
|
167
|
+
end
|
|
168
|
+
end
|
|
169
|
+
puts line
|
|
170
|
+
y += 2
|
|
171
|
+
end
|
|
172
|
+
end
|
|
173
|
+
end
|
|
174
|
+
end
|
|
175
|
+
end
|
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Ruflet
|
|
4
|
+
module CLI
|
|
5
|
+
MAIN_TEMPLATE = <<~RUBY
|
|
6
|
+
require "ruflet"
|
|
7
|
+
|
|
8
|
+
class MainApp < Ruflet::App
|
|
9
|
+
def initialize
|
|
10
|
+
super
|
|
11
|
+
@count = 0
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
def view(page)
|
|
15
|
+
page.title = "Counter Demo"
|
|
16
|
+
page.vertical_alignment = Ruflet::MainAxisAlignment::CENTER
|
|
17
|
+
page.horizontal_alignment = Ruflet::CrossAxisAlignment::CENTER
|
|
18
|
+
count_text = page.text(value: @count.to_s, size: 40)
|
|
19
|
+
|
|
20
|
+
page.add(
|
|
21
|
+
page.container(
|
|
22
|
+
expand: true,
|
|
23
|
+
padding: 24,
|
|
24
|
+
content: page.column(
|
|
25
|
+
expand: true,
|
|
26
|
+
alignment: Ruflet::MainAxisAlignment::CENTER,
|
|
27
|
+
horizontal_alignment: Ruflet::CrossAxisAlignment::CENTER,
|
|
28
|
+
spacing: 12,
|
|
29
|
+
controls: [
|
|
30
|
+
page.text(value: "You have pushed the button this many times:"),
|
|
31
|
+
count_text
|
|
32
|
+
]
|
|
33
|
+
)
|
|
34
|
+
),
|
|
35
|
+
appbar: page.app_bar(
|
|
36
|
+
title: page.text(value: "Counter Demo")
|
|
37
|
+
),
|
|
38
|
+
floating_action_button: page.fab(
|
|
39
|
+
page.icon(icon: Ruflet::MaterialIcons::ADD),
|
|
40
|
+
on_click: ->(_e) {
|
|
41
|
+
@count += 1
|
|
42
|
+
page.update(count_text, value: @count.to_s)
|
|
43
|
+
}
|
|
44
|
+
)
|
|
45
|
+
)
|
|
46
|
+
end
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
MainApp.new.run
|
|
50
|
+
|
|
51
|
+
RUBY
|
|
52
|
+
|
|
53
|
+
GEMFILE_TEMPLATE = <<~GEMFILE
|
|
54
|
+
source "https://rubygems.org"
|
|
55
|
+
|
|
56
|
+
RUFLET_GIT = "https://github.com/AdamMusa/Ruflet.git"
|
|
57
|
+
RUFLET_BRANCH = "main"
|
|
58
|
+
|
|
59
|
+
gem "ruflet_server", git: RUFLET_GIT, branch: RUFLET_BRANCH, glob: "packages/ruflet_server/*.gemspec"
|
|
60
|
+
gem "ruflet", git: RUFLET_GIT, branch: RUFLET_BRANCH, glob: "packages/ruflet/*.gemspec"
|
|
61
|
+
GEMFILE
|
|
62
|
+
|
|
63
|
+
BUNDLE_CONFIG_TEMPLATE = <<~YAML
|
|
64
|
+
---
|
|
65
|
+
BUNDLE_PATH: "vendor/bundle"
|
|
66
|
+
BUNDLE_DISABLE_SHARED_GEMS: "true"
|
|
67
|
+
YAML
|
|
68
|
+
|
|
69
|
+
README_TEMPLATE = <<~MD
|
|
70
|
+
# %<app_name>s
|
|
71
|
+
|
|
72
|
+
Ruflet app.
|
|
73
|
+
|
|
74
|
+
## Setup
|
|
75
|
+
|
|
76
|
+
```bash
|
|
77
|
+
bundle install
|
|
78
|
+
```
|
|
79
|
+
|
|
80
|
+
## Run
|
|
81
|
+
|
|
82
|
+
```bash
|
|
83
|
+
bundle exec ruflet run main
|
|
84
|
+
```
|
|
85
|
+
|
|
86
|
+
## Build
|
|
87
|
+
|
|
88
|
+
```bash
|
|
89
|
+
bundle exec ruflet build apk
|
|
90
|
+
bundle exec ruflet build ios
|
|
91
|
+
```
|
|
92
|
+
MD
|
|
93
|
+
end
|
|
94
|
+
end
|
data/lib/ruflet/cli.rb
ADDED
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "optparse"
|
|
4
|
+
|
|
5
|
+
require_relative "cli/templates"
|
|
6
|
+
require_relative "cli/new_command"
|
|
7
|
+
require_relative "cli/run_command"
|
|
8
|
+
require_relative "cli/build_command"
|
|
9
|
+
|
|
10
|
+
module Ruflet
|
|
11
|
+
module CLI
|
|
12
|
+
extend self
|
|
13
|
+
extend NewCommand
|
|
14
|
+
extend RunCommand
|
|
15
|
+
extend BuildCommand
|
|
16
|
+
|
|
17
|
+
def run(argv = ARGV)
|
|
18
|
+
command = (argv.shift || "help").downcase
|
|
19
|
+
|
|
20
|
+
case command
|
|
21
|
+
when "new", "bootstrap", "init"
|
|
22
|
+
command_new(argv)
|
|
23
|
+
when "run"
|
|
24
|
+
command_run(argv)
|
|
25
|
+
when "build"
|
|
26
|
+
command_build(argv)
|
|
27
|
+
when "help", "-h", "--help"
|
|
28
|
+
print_help
|
|
29
|
+
0
|
|
30
|
+
else
|
|
31
|
+
warn "Unknown command: #{command}"
|
|
32
|
+
print_help
|
|
33
|
+
1
|
|
34
|
+
end
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
def print_help
|
|
38
|
+
puts <<~HELP
|
|
39
|
+
Ruflet CLI
|
|
40
|
+
|
|
41
|
+
Commands:
|
|
42
|
+
ruflet new <appname>
|
|
43
|
+
ruflet run [scriptname|path] [--web|--mobile|--desktop]
|
|
44
|
+
ruflet build <apk|ios|aab|web|macos|windows|linux>
|
|
45
|
+
HELP
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
def bootstrap(path)
|
|
49
|
+
command_new([path || Dir.pwd])
|
|
50
|
+
0
|
|
51
|
+
end
|
|
52
|
+
end
|
|
53
|
+
end
|
data/lib/ruflet_cli.rb
ADDED
metadata
ADDED
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
|
2
|
+
name: ruflet_cli
|
|
3
|
+
version: !ruby/object:Gem::Version
|
|
4
|
+
version: 0.0.1
|
|
5
|
+
platform: ruby
|
|
6
|
+
authors:
|
|
7
|
+
- AdamMusa
|
|
8
|
+
bindir: bin
|
|
9
|
+
cert_chain: []
|
|
10
|
+
date: 1980-01-02 00:00:00.000000000 Z
|
|
11
|
+
dependencies:
|
|
12
|
+
- !ruby/object:Gem::Dependency
|
|
13
|
+
name: rqrcode
|
|
14
|
+
requirement: !ruby/object:Gem::Requirement
|
|
15
|
+
requirements:
|
|
16
|
+
- - "~>"
|
|
17
|
+
- !ruby/object:Gem::Version
|
|
18
|
+
version: '2.2'
|
|
19
|
+
type: :runtime
|
|
20
|
+
prerelease: false
|
|
21
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
22
|
+
requirements:
|
|
23
|
+
- - "~>"
|
|
24
|
+
- !ruby/object:Gem::Version
|
|
25
|
+
version: '2.2'
|
|
26
|
+
description: Ruflet command line interface for creating and running Ruflet apps.
|
|
27
|
+
email:
|
|
28
|
+
- adammusa2222@gmail.com
|
|
29
|
+
executables:
|
|
30
|
+
- ruflet
|
|
31
|
+
extensions: []
|
|
32
|
+
extra_rdoc_files: []
|
|
33
|
+
files:
|
|
34
|
+
- README.md
|
|
35
|
+
- bin/ruflet
|
|
36
|
+
- lib/ruflet/cli.rb
|
|
37
|
+
- lib/ruflet/cli/build_command.rb
|
|
38
|
+
- lib/ruflet/cli/new_command.rb
|
|
39
|
+
- lib/ruflet/cli/run_command.rb
|
|
40
|
+
- lib/ruflet/cli/templates.rb
|
|
41
|
+
- lib/ruflet/version.rb
|
|
42
|
+
- lib/ruflet_cli.rb
|
|
43
|
+
homepage: https://github.com/AdamMusa/Ruflet
|
|
44
|
+
licenses: []
|
|
45
|
+
metadata: {}
|
|
46
|
+
rdoc_options: []
|
|
47
|
+
require_paths:
|
|
48
|
+
- lib
|
|
49
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
|
50
|
+
requirements:
|
|
51
|
+
- - ">="
|
|
52
|
+
- !ruby/object:Gem::Version
|
|
53
|
+
version: '3.1'
|
|
54
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
|
55
|
+
requirements:
|
|
56
|
+
- - ">="
|
|
57
|
+
- !ruby/object:Gem::Version
|
|
58
|
+
version: '0'
|
|
59
|
+
requirements: []
|
|
60
|
+
rubygems_version: 3.7.2
|
|
61
|
+
specification_version: 4
|
|
62
|
+
summary: Ruflet CLI package.
|
|
63
|
+
test_files: []
|