gurl 1.0.0.pre.alpha
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/bin/gurl +4 -0
- data/lib/core/builder/base.rb +83 -0
- data/lib/core/builder/base_support/flag_concern.rb +56 -0
- data/lib/core/main.rb +44 -0
- data/lib/core/main_pipeline/builder_fetcher.rb +16 -0
- data/lib/core/main_pipeline/builder_runner.rb +29 -0
- data/lib/core/main_pipeline/parse_options.rb +48 -0
- data/lib/core/main_pipeline/path_fetcher.rb +33 -0
- data/lib/core/service/base.rb +23 -0
- data/lib/core/service/response.rb +30 -0
- data/lib/gurl.rb +16 -0
- metadata +68 -0
checksums.yaml
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
---
|
|
2
|
+
SHA256:
|
|
3
|
+
metadata.gz: 1a768efa1cf346a124d593c8fd1351fd142187ac6aff5b7dff9d9ca8c3df6718
|
|
4
|
+
data.tar.gz: 99be94f373b5a07681cabfcdd5a160258407f6584bcdf2033f712b847728582e
|
|
5
|
+
SHA512:
|
|
6
|
+
metadata.gz: d38e2df77a70083e914dbb1e34b9a9b4a0fa03fac84808668851ba44d395411df25c09e7671d9c05e871256ebcae17300d3d945a2842498e51a7dd83f028dd1a
|
|
7
|
+
data.tar.gz: df21e6ef1db8de5d126a938b683b501a70ee6bb73938b6bc2b056e7211b979b9edfa06657446df6630996b7d07a42a6c508c832f8ac358e7cf922d41ac4e5df9
|
data/bin/gurl
ADDED
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
GET = 'GET'
|
|
4
|
+
POST = 'POST'
|
|
5
|
+
PUT = 'PUT'
|
|
6
|
+
PATCH = 'PATCH'
|
|
7
|
+
DELETE = 'DELETE'
|
|
8
|
+
|
|
9
|
+
module Builder
|
|
10
|
+
class Base
|
|
11
|
+
include BaseSupport::FlagConcern
|
|
12
|
+
|
|
13
|
+
def initialize
|
|
14
|
+
@url = ''
|
|
15
|
+
@method = GET
|
|
16
|
+
@headers = []
|
|
17
|
+
@data = nil
|
|
18
|
+
@params = []
|
|
19
|
+
|
|
20
|
+
self.class.ancestors.reverse_each do |ancestor|
|
|
21
|
+
next unless ancestor.instance_methods(false).include?(:start)
|
|
22
|
+
|
|
23
|
+
ancestor.instance_method(:start).bind_call(self)
|
|
24
|
+
end
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
def build(**options)
|
|
28
|
+
execute
|
|
29
|
+
one_line = options[:one_line]
|
|
30
|
+
|
|
31
|
+
parts = ['curl']
|
|
32
|
+
parts << _build_url
|
|
33
|
+
parts << "-X #{@method}" if @method != GET
|
|
34
|
+
@headers.each do |k, v|
|
|
35
|
+
parts << "-H '#{k}: #{v}'"
|
|
36
|
+
end
|
|
37
|
+
parts << data_to_curl_argument(one_line) if @data
|
|
38
|
+
parts.join(' ')
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
def execute; end
|
|
42
|
+
|
|
43
|
+
private
|
|
44
|
+
|
|
45
|
+
def data_to_curl_argument(one_line)
|
|
46
|
+
return "-d @- << EOF\n #{@data}\nEOF" unless one_line || !@data.include?("\n")
|
|
47
|
+
|
|
48
|
+
"-d '#{@data.split("\n").map(&:strip).join(' ')}'"
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
def url(url_argument)
|
|
52
|
+
@url = url_argument
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
def method(method_argument)
|
|
56
|
+
@method = method_argument
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
def header(key, value)
|
|
60
|
+
@headers << [key, value]
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
def query_param(key, value)
|
|
64
|
+
@params << [key, value]
|
|
65
|
+
end
|
|
66
|
+
|
|
67
|
+
def body(body_argument)
|
|
68
|
+
@data = body_argument
|
|
69
|
+
end
|
|
70
|
+
|
|
71
|
+
def json_body(json_body_argument)
|
|
72
|
+
require 'json'
|
|
73
|
+
@data = JSON.pretty_generate(json_body_argument)
|
|
74
|
+
end
|
|
75
|
+
|
|
76
|
+
def _build_url
|
|
77
|
+
return @url unless @params.any?
|
|
78
|
+
|
|
79
|
+
q = @params.map { |k, v| "#{k}=#{v}" }.join('&')
|
|
80
|
+
"#{@url}?#{q}"
|
|
81
|
+
end
|
|
82
|
+
end
|
|
83
|
+
end
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Builder
|
|
4
|
+
module BaseSupport
|
|
5
|
+
module FlagConcern
|
|
6
|
+
def process_flags(opts)
|
|
7
|
+
_flags.each do |names, block|
|
|
8
|
+
opts.on(*names, &block)
|
|
9
|
+
end
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
private
|
|
13
|
+
|
|
14
|
+
def flag(name, *list_options, **options)
|
|
15
|
+
return _flag_variables[name] if _flag_variables.key?(name)
|
|
16
|
+
|
|
17
|
+
flag_args = _build_flag_arguments(name, *list_options, **options)
|
|
18
|
+
|
|
19
|
+
_add_flag(flag_args) { |value| _flag_variables[name] = value }
|
|
20
|
+
nil
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
def _build_flag_arguments(name, *list_options, label: nil)
|
|
24
|
+
bool = list_options.include?(:bool)
|
|
25
|
+
shorten = list_options.include?(:shorten)
|
|
26
|
+
one_char_only = name.length == 1
|
|
27
|
+
|
|
28
|
+
flag_args = []
|
|
29
|
+
flag_args << _long_flag_for(name, bool) unless one_char_only
|
|
30
|
+
flag_args << _short_flag_for(name, bool) if shorten || one_char_only
|
|
31
|
+
flag_args << (label || "Sets #{name}")
|
|
32
|
+
flag_args
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
def _short_flag_for(name, bool)
|
|
36
|
+
"-#{name[0]}#{'ARG' unless bool}"
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
def _long_flag_for(name, bool)
|
|
40
|
+
"--#{name}#{'=ARG' unless bool}"
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
def _add_flag(flag_args, &block)
|
|
44
|
+
_flags[flag_args] = block
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
def _flags
|
|
48
|
+
@_flags ||= {}
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
def _flag_variables
|
|
52
|
+
@_flag_variables ||= {}
|
|
53
|
+
end
|
|
54
|
+
end
|
|
55
|
+
end
|
|
56
|
+
end
|
data/lib/core/main.rb
ADDED
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
class Main
|
|
4
|
+
class << self
|
|
5
|
+
def execute
|
|
6
|
+
MainPipeline::BuilderRunner
|
|
7
|
+
.call(builder, main_options(builder))
|
|
8
|
+
.error { exit(_1[:exit_status]) }
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
private
|
|
12
|
+
|
|
13
|
+
def path
|
|
14
|
+
@path ||=
|
|
15
|
+
MainPipeline::PathFetcher
|
|
16
|
+
.call(user_builders_dir)
|
|
17
|
+
.error { exit_without_builder(1) }
|
|
18
|
+
.ok
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
def user_builders_dir
|
|
22
|
+
@user_builders_dir ||= Pathname.new(Dir.pwd)
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
def builder
|
|
26
|
+
@builder ||=
|
|
27
|
+
MainPipeline::BuilderFetcher
|
|
28
|
+
.call(path, user_builders_dir)
|
|
29
|
+
.ok
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
def main_options(target_builder = nil)
|
|
33
|
+
MainPipeline::ParseOptions
|
|
34
|
+
.call(target_builder)
|
|
35
|
+
.error { exit(1) }
|
|
36
|
+
.ok
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
def exit_without_builder(status = 0)
|
|
40
|
+
main_options
|
|
41
|
+
exit(status)
|
|
42
|
+
end
|
|
43
|
+
end
|
|
44
|
+
end
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module MainPipeline
|
|
4
|
+
class BuilderFetcher < Service::Base
|
|
5
|
+
def call(path, user_builders_dir)
|
|
6
|
+
cls = path
|
|
7
|
+
.relative_path_from(user_builders_dir)
|
|
8
|
+
.each_filename
|
|
9
|
+
.to_a
|
|
10
|
+
.tap { |parts| parts[-1] = parts[-1].delete_suffix('.rb') }
|
|
11
|
+
.map { |p| p.split('_').map!(&:capitalize).join }
|
|
12
|
+
.inject(Object) { |acc, name| acc.const_get(name) }
|
|
13
|
+
ok(cls.new)
|
|
14
|
+
end
|
|
15
|
+
end
|
|
16
|
+
end
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'English'
|
|
4
|
+
module MainPipeline
|
|
5
|
+
class BuilderRunner < Service::Base
|
|
6
|
+
def call(builder, main_options)
|
|
7
|
+
curl_command = builder.build(**main_options)
|
|
8
|
+
verbose_output(curl_command) if main_options[:verbose]
|
|
9
|
+
|
|
10
|
+
run(curl_command)
|
|
11
|
+
ok
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
private
|
|
15
|
+
|
|
16
|
+
def run(curl_command)
|
|
17
|
+
system(curl_command)
|
|
18
|
+
return error({ exit_status: $CHILD_STATUS.exitstatus }) unless $CHILD_STATUS.success?
|
|
19
|
+
|
|
20
|
+
puts
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
def verbose_output(curl_command)
|
|
24
|
+
puts "\e[32mRunning:\e[0m"
|
|
25
|
+
puts curl_command
|
|
26
|
+
puts "\e[34mOutput:\e[0m"
|
|
27
|
+
end
|
|
28
|
+
end
|
|
29
|
+
end
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module MainPipeline
|
|
4
|
+
class ParseOptions < Service::Base
|
|
5
|
+
def call(builder)
|
|
6
|
+
# NOTE: the line below is necessary to load flags in builder#execute
|
|
7
|
+
builder&.execute
|
|
8
|
+
|
|
9
|
+
main_options = {}
|
|
10
|
+
option_parser = build_option_parser(builder, main_options)
|
|
11
|
+
return unless option_parser
|
|
12
|
+
|
|
13
|
+
option_parser.parse!
|
|
14
|
+
|
|
15
|
+
ok(main_options)
|
|
16
|
+
rescue OptionParser::InvalidOption => e
|
|
17
|
+
puts e.message
|
|
18
|
+
error
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
private
|
|
22
|
+
|
|
23
|
+
def build_option_parser(builder, main_options)
|
|
24
|
+
OptionParser.new do |opts|
|
|
25
|
+
opts.banner = 'Usage: gurl FILE [options]'
|
|
26
|
+
opts.separator ''
|
|
27
|
+
opts.separator 'Global options:'
|
|
28
|
+
opts.on('-v', '--verbose', 'Enable verbose output') { main_options[:verbose] = true }
|
|
29
|
+
opts.on('--one-line', 'Generate cURL command as a single line') { main_options[:one_line] = true }
|
|
30
|
+
add_help_flag(opts)
|
|
31
|
+
add_builder_flags(opts, builder) if builder
|
|
32
|
+
end
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
def add_builder_flags(opts, builder)
|
|
36
|
+
opts.separator ''
|
|
37
|
+
opts.separator 'Builder-specific flags:'
|
|
38
|
+
builder.process_flags(opts)
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
def add_help_flag(opts)
|
|
42
|
+
opts.on('-h', '--help', 'Show this help message') do
|
|
43
|
+
puts opts
|
|
44
|
+
exit
|
|
45
|
+
end
|
|
46
|
+
end
|
|
47
|
+
end
|
|
48
|
+
end
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module MainPipeline
|
|
4
|
+
class PathFetcher < Service::Base
|
|
5
|
+
def call(user_builders_dir)
|
|
6
|
+
return if argv_empty?
|
|
7
|
+
|
|
8
|
+
arg_path = ARGV[0]
|
|
9
|
+
arg_path += '.rb' unless arg_path.end_with?('.rb')
|
|
10
|
+
|
|
11
|
+
path = user_builders_dir + arg_path
|
|
12
|
+
return unless path_exists?(path)
|
|
13
|
+
|
|
14
|
+
ok(path.realpath)
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
def path_exists?(path)
|
|
18
|
+
return true if path.exist?
|
|
19
|
+
|
|
20
|
+
puts "File does not exist: #{path}"
|
|
21
|
+
error
|
|
22
|
+
false
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
def argv_empty?
|
|
26
|
+
return false if ARGV.any?
|
|
27
|
+
|
|
28
|
+
puts 'Path not specified'
|
|
29
|
+
error
|
|
30
|
+
true
|
|
31
|
+
end
|
|
32
|
+
end
|
|
33
|
+
end
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Service
|
|
4
|
+
class Base
|
|
5
|
+
def self.call(*args)
|
|
6
|
+
instance = new
|
|
7
|
+
instance.call(*args)
|
|
8
|
+
instance.response
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
attr_reader :response
|
|
12
|
+
|
|
13
|
+
private
|
|
14
|
+
|
|
15
|
+
def error(error_data = nil)
|
|
16
|
+
@response = Response.new(:error, error_data)
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
def ok(success_data = nil)
|
|
20
|
+
@response = Response.new(:ok, success_data)
|
|
21
|
+
end
|
|
22
|
+
end
|
|
23
|
+
end
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Service
|
|
4
|
+
class Response
|
|
5
|
+
attr_reader :data
|
|
6
|
+
|
|
7
|
+
def initialize(status, data)
|
|
8
|
+
@status = status
|
|
9
|
+
@data = data
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
def ok
|
|
13
|
+
yield(data) if ok? && block_given?
|
|
14
|
+
data
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
def error
|
|
18
|
+
yield(data) if error? && block_given?
|
|
19
|
+
self
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
def ok?
|
|
23
|
+
@status == :ok
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
def error?
|
|
27
|
+
@status == :error
|
|
28
|
+
end
|
|
29
|
+
end
|
|
30
|
+
end
|
data/lib/gurl.rb
ADDED
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
#!/usr/bin/env ruby
|
|
2
|
+
# frozen_string_literal: true
|
|
3
|
+
|
|
4
|
+
require 'pathname'
|
|
5
|
+
require 'open3'
|
|
6
|
+
require 'optparse'
|
|
7
|
+
require 'bundler/setup'
|
|
8
|
+
require 'zeitwerk'
|
|
9
|
+
Bundler.require(:default)
|
|
10
|
+
|
|
11
|
+
loader = Zeitwerk::Loader.new
|
|
12
|
+
loader.push_dir(Dir.pwd)
|
|
13
|
+
loader.push_dir(File.join(__dir__, 'core'))
|
|
14
|
+
loader.setup
|
|
15
|
+
|
|
16
|
+
Main.execute
|
metadata
ADDED
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
|
2
|
+
name: gurl
|
|
3
|
+
version: !ruby/object:Gem::Version
|
|
4
|
+
version: 1.0.0.pre.alpha
|
|
5
|
+
platform: ruby
|
|
6
|
+
authors:
|
|
7
|
+
- Hikari Luz
|
|
8
|
+
autorequire:
|
|
9
|
+
bindir: bin
|
|
10
|
+
cert_chain: []
|
|
11
|
+
date: 2026-02-27 00:00:00.000000000 Z
|
|
12
|
+
dependencies:
|
|
13
|
+
- !ruby/object:Gem::Dependency
|
|
14
|
+
name: zeitwerk
|
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
|
16
|
+
requirements:
|
|
17
|
+
- - "~>"
|
|
18
|
+
- !ruby/object:Gem::Version
|
|
19
|
+
version: '2.6'
|
|
20
|
+
type: :runtime
|
|
21
|
+
prerelease: false
|
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
23
|
+
requirements:
|
|
24
|
+
- - "~>"
|
|
25
|
+
- !ruby/object:Gem::Version
|
|
26
|
+
version: '2.6'
|
|
27
|
+
description: Utility tool for building and executing cURL commands using Ruby.
|
|
28
|
+
email: hikaridesuyoo@gmail.com
|
|
29
|
+
executables:
|
|
30
|
+
- gurl
|
|
31
|
+
extensions: []
|
|
32
|
+
extra_rdoc_files: []
|
|
33
|
+
files:
|
|
34
|
+
- bin/gurl
|
|
35
|
+
- lib/core/builder/base.rb
|
|
36
|
+
- lib/core/builder/base_support/flag_concern.rb
|
|
37
|
+
- lib/core/main.rb
|
|
38
|
+
- lib/core/main_pipeline/builder_fetcher.rb
|
|
39
|
+
- lib/core/main_pipeline/builder_runner.rb
|
|
40
|
+
- lib/core/main_pipeline/parse_options.rb
|
|
41
|
+
- lib/core/main_pipeline/path_fetcher.rb
|
|
42
|
+
- lib/core/service/base.rb
|
|
43
|
+
- lib/core/service/response.rb
|
|
44
|
+
- lib/gurl.rb
|
|
45
|
+
homepage:
|
|
46
|
+
licenses:
|
|
47
|
+
- GPL-3.0
|
|
48
|
+
metadata: {}
|
|
49
|
+
post_install_message:
|
|
50
|
+
rdoc_options: []
|
|
51
|
+
require_paths:
|
|
52
|
+
- lib
|
|
53
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
|
54
|
+
requirements:
|
|
55
|
+
- - ">="
|
|
56
|
+
- !ruby/object:Gem::Version
|
|
57
|
+
version: 3.0.0
|
|
58
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
|
59
|
+
requirements:
|
|
60
|
+
- - ">"
|
|
61
|
+
- !ruby/object:Gem::Version
|
|
62
|
+
version: 1.3.1
|
|
63
|
+
requirements: []
|
|
64
|
+
rubygems_version: 3.4.10
|
|
65
|
+
signing_key:
|
|
66
|
+
specification_version: 4
|
|
67
|
+
summary: Build cURL commands with Ruby
|
|
68
|
+
test_files: []
|