toycol 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: 102026f42040d677807fb5fe1cd08797f564951096c15ac2c0150a757cc82926
4
- data.tar.gz: d7b4312381d610821b197f688c871acbe26a6d70146c67441d23cbd52a0ed697
3
+ metadata.gz: a9cd0de8dd5ec5a48e22a49c8198492a96162c9ff922a07c897e3af7cdfe779a
4
+ data.tar.gz: 938b7f68fef82731d61c1937c2ed53753c1bbb301c49434cc6d538edb6f862f9
5
5
  SHA512:
6
- metadata.gz: 11eb3611d926c804f1f0d632f40daf2a37b7f663bdb449c69c2353d608dba87161723f4380d5dedfa78a46f1d264dde625b9bdd30ba6dda6e64eed12964f83cf
7
- data.tar.gz: 9c38815ef3861ad35ac635f713fb2f6b459ee6cbc64cbe9da56ec355381a5f21c30189e28ebe92f961406b99d9349631b52571729fd8c290d94cd61c0eefd4ea
6
+ metadata.gz: 53e62c64e3f418da9e0f7068482531bab41466e6d73d560e8bf74ae900cf2587a61d810365eea15f01f194592c70b563320ffe93f170810e4fa6f443f3a73837
7
+ data.tar.gz: 112910c06cdb28e5f8690fd18373a2d418a466b075cc0ff793816aed2475acb1ccf5657ae8cfb7b3c321cefc1bde44e5a34fd9b9024f3c20d14047938adf6121
@@ -0,0 +1,20 @@
1
+ ---
2
+ name: Feature request
3
+ about: Suggest an idea for this project
4
+ title: "[FEATURE]"
5
+ labels: enhancement
6
+ assignees: ''
7
+
8
+ ---
9
+
10
+ ## Is your feature request related to a problem? Please describe.
11
+ A clear and concise description of what the problem is. Ex. I'm always frustrated when [...]
12
+
13
+ ## Describe the solution you'd like
14
+ A clear and concise description of what you want to happen.
15
+
16
+ ## Describe alternatives you've considered
17
+ A clear and concise description of any alternative solutions or features you've considered.
18
+
19
+ ## Additional context
20
+ Add any other context or screenshots about the feature request here.
@@ -0,0 +1,5 @@
1
+ # frozen_string_literal: true
2
+
3
+ source "https://rubygems.org"
4
+
5
+ gem "toycol", path: "../../"
@@ -0,0 +1,13 @@
1
+ Toycol::Protocol.define do
2
+ request.path do |message|
3
+ %r{(?<path>\/\w*)}.match(message)[:path]
4
+ end
5
+
6
+ request.query do |message|
7
+ %r{\?(?<query>.+)}.match(message) { |m| m[:query] }
8
+ end
9
+
10
+ request.http_method do |message|
11
+ "GET"
12
+ end
13
+ end
@@ -0,0 +1,21 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "rack"
4
+ require "toycol"
5
+
6
+ Toycol::Protocol.use
7
+
8
+ class App
9
+ def call(env)
10
+ case env["REQUEST_METHOD"]
11
+ when "GET"
12
+ [
13
+ 200,
14
+ { "Content-Type" => "text/html" },
15
+ ["This app has no protocol name\n"]
16
+ ]
17
+ end
18
+ end
19
+ end
20
+
21
+ run App.new
@@ -1,5 +1,3 @@
1
- # frozen_string_literal: true
2
-
3
1
  Toycol::Protocol.define(:duck) do
4
2
  custom_status_codes(
5
3
  600 => "I'm afraid you are not a duck..."
@@ -7,11 +5,11 @@ Toycol::Protocol.define(:duck) do
7
5
  additional_request_methods "OTHER"
8
6
 
9
7
  request.path do |message|
10
- %r{(?<path>/\w*)}.match(message)[:path]
8
+ %r{(?<path>\/\w*)}.match(message)[:path]
11
9
  end
12
10
 
13
11
  request.query do |message|
14
- /\?(?<query>.+)/.match(message) { |m| m[:query] }
12
+ %r{\<3(?<query>.+)}.match(message) { |m| m[:query] }
15
13
  end
16
14
 
17
15
  request.http_method do |message|
@@ -2,26 +2,29 @@
2
2
 
3
3
  require "optparse"
4
4
  require_relative "./client"
5
+ require_relative "./template_generator"
5
6
 
6
7
  module Toycol
7
8
  class Command
8
9
  class Options
10
+ @options = {}
11
+
9
12
  class << self
10
13
  def parse!(argv)
11
- options = {}
12
14
  option_parser = create_option_parser
13
15
  sub_command_option_parser = create_sub_command_option_parser
14
16
 
15
17
  begin
16
18
  option_parser.order!(argv)
17
- options[:command] = argv.shift
18
- options[:request_message] = argv.shift if %w[client c].include?(options[:command]) && argv.first != "-h"
19
- sub_command_option_parser[options[:command]].parse!(argv)
19
+ @options[:command] = argv.shift
20
+ @options[:request_message] = argv.shift if request_message?(argv.first)
21
+ @options[:protocol_name] = argv.shift if protocol_name?(argv.first)
22
+ sub_command_option_parser[@options[:command]].parse!(argv)
20
23
  rescue OptionParser::MissingArgument, OptionParser::InvalidOption, ArgumentError => e
21
24
  abort e.message
22
25
  end
23
26
 
24
- options
27
+ @options
25
28
  end
26
29
 
27
30
  def create_option_parser
@@ -45,19 +48,34 @@ module Toycol
45
48
 
46
49
  def create_sub_command_option_parser
47
50
  sub_command_parser = Hash.new { |_k, v| raise ArgumentError, "'#{v}' is not sub command" }
48
- sub_command_parser["client"] = client_option_parser
49
- sub_command_parser["c"] = client_option_parser
50
- sub_command_parser["server"] = server_option_parser
51
- sub_command_parser["s"] = server_option_parser
51
+ sub_command_parser["client"] = client_option_parser
52
+ sub_command_parser["c"] = client_option_parser
53
+ sub_command_parser["server"] = server_option_parser
54
+ sub_command_parser["s"] = server_option_parser
55
+ sub_command_parser["generate"] = generator_option_parser
56
+ sub_command_parser["g"] = generator_option_parser
52
57
  sub_command_parser
53
58
  end
54
59
 
55
60
  private
56
61
 
62
+ def request_message?(arg)
63
+ %w[client c].include?(@options[:command]) \
64
+ && arg != "-p" \
65
+ && arg != "-h"
66
+ end
67
+
68
+ def protocol_name?(arg)
69
+ %w[geberate g].include?(@options[:command]) \
70
+ && arg != "-t" \
71
+ && arg != "-h"
72
+ end
73
+
57
74
  def sub_command_summaries
58
75
  [
59
76
  { name: "client REQUEST_MESSAGE -p PORT", summary: "Send request message to server" },
60
- { name: "server -u SERVER_NAME", summary: "Start proxy and background server" }
77
+ { name: "server -u SERVER_NAME", summary: "Start proxy and background server" },
78
+ { name: "generate NAME -t TYPE", summary: "Generate new protocol or Rack app" }
61
79
  ]
62
80
  end
63
81
 
@@ -89,16 +107,14 @@ module Toycol
89
107
  end
90
108
  end
91
109
 
92
- def client_command_help_messages
93
- [
94
- { name: "client -p=PORT_NUMBER", summary: "Send request to server" }
95
- ]
96
- end
110
+ def generator_option_parser
111
+ OptionParser.new do |opt|
112
+ opt.on("-t TYPE", "--type TYPE", "generate TYPE of template (default: :all)") do |type|
113
+ @options[:template_type] = type
114
+ end
97
115
 
98
- def server_command_help_messages
99
- [
100
- { name: "server -u=SERVER_NAME", summary: "Start proxy & background server" }
101
- ]
116
+ opt.on_head("-h", "--help", "Show this message") { help_command(opt) }
117
+ end
102
118
  end
103
119
 
104
120
  def help_command(parser)
@@ -126,6 +142,9 @@ module Toycol
126
142
  when "server", "s"
127
143
  ARGV.push("-q", "-s", "toycol")
128
144
  Rack::Server.start
145
+ when "generate", "g"
146
+ type = options[:template_type] || "all"
147
+ ::Toycol::TemplateGenerator.generate!(type: type, name: options[:protocol_name])
129
148
  end
130
149
  end
131
150
  end
@@ -17,7 +17,7 @@ module Toycol
17
17
  end
18
18
 
19
19
  # For application which use the protocol
20
- def use(protocol_name)
20
+ def use(protocol_name = nil)
21
21
  @protocol_name = protocol_name
22
22
  end
23
23
 
@@ -0,0 +1,60 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Toycol
4
+ class TemplateGenerator
5
+ class << self
6
+ def generate!(type:, name:)
7
+ raise StandardError, "Unknown Type: This type of template can't be generated" unless valid? type
8
+
9
+ if type == "all"
10
+ new(name, "protocol").generate!
11
+ new(name, "app").generate!
12
+ else
13
+ new(name, type).generate!
14
+ end
15
+ end
16
+
17
+ private
18
+
19
+ def valid?(type)
20
+ %w[all app protocol].include? type
21
+ end
22
+ end
23
+
24
+ def initialize(name, type)
25
+ @name = name
26
+ @type = type
27
+ end
28
+
29
+ def generate!
30
+ raise StandardError, "#{filename} already exists" unless Dir.glob(filename).empty?
31
+
32
+ File.open(filename, "w") { |f| f.print template_text_for_new }
33
+ puts "Generate #{filename} in #{FileUtils.pwd}"
34
+ end
35
+
36
+ private
37
+
38
+ def filename
39
+ @filename ||= case @type
40
+ when "protocol" then "Protocolfile#{@name ? ".#{@name}" : nil}"
41
+ when "app" then "config#{@name ? "_#{@name}" : nil}.ru"
42
+ end
43
+ end
44
+
45
+ def template_text_for_new
46
+ if @name
47
+ template_text.sub(":PROTOCOL_NAME", ":#{@name}")
48
+ else
49
+ template_text.sub("\(:PROTOCOL_NAME\)", "")
50
+ end
51
+ end
52
+
53
+ def template_text
54
+ case @type
55
+ when "protocol" then File.open("lib/toycol/templates/protocol.txt", "r", &:read)
56
+ when "app" then File.open("lib/toycol/templates/application.txt", "r", &:read)
57
+ end
58
+ end
59
+ end
60
+ end
@@ -0,0 +1,22 @@
1
+ require "rack"
2
+ require "toycol"
3
+
4
+ # Specify which protocol to use
5
+ Toycol::Protocol.use(:PROTOCOL_NAME)
6
+
7
+ class App
8
+ def call(env)
9
+ # Define your app on request method, request path, request query etc
10
+ # For example:
11
+ # case env['REQUEST_METHOD']
12
+ # when 'GET'
13
+ # [
14
+ # 200,
15
+ # { 'Content-Type' => 'text/html' },
16
+ # ["Hello, This app is running by :#{name} protocol."]
17
+ # ]
18
+ # end
19
+ end
20
+ end
21
+
22
+ run App.new
@@ -0,0 +1,39 @@
1
+ Toycol::Protocol.define(:PROTOCOL_NAME) do
2
+ # For example
3
+ # client would send:
4
+ # quack, quack /posts<3user_id=1
5
+ # server would interpret client message:
6
+ # GET /posts?user_id=1
7
+
8
+
9
+ # [OPTIONAL] You can define your additional request methods:
10
+ # For example:
11
+ # additional_request_methods OTHER
12
+
13
+ # [OPTIONAL] You can define your own response status code:
14
+ # For example:
15
+ # define_status_codes(
16
+ # 600 => "I'm afraid you are not a duck..."
17
+ # )
18
+
19
+ # [REQUIRED] Define how you parse request path from request message
20
+ request.path do |message|
21
+ # For example:
22
+ # %r{(?<path>\/\w*)}.match(message)[:path]
23
+ end
24
+
25
+ # [REQUIRED] Define how you parse query from request message
26
+ request.query do |message|
27
+ # For example:
28
+ # %r{\<3(?<query>.+)}.match(message) { |m| m[:query] }
29
+ end
30
+
31
+ # [REQUIRED] Define how you parse query from request message
32
+ request.http_method do |message|
33
+ # For example:
34
+ # case message.scan(/quack/).size
35
+ # when 2 then "GET"
36
+ # else "OTHER"
37
+ # end
38
+ end
39
+ end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Toycol
4
- VERSION = "0.2.2"
4
+ VERSION = "0.3.0"
5
5
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: toycol
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
  - Misaki Shioi
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2021-07-24 00:00:00.000000000 Z
11
+ date: 2021-07-25 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rack
@@ -33,6 +33,7 @@ extensions: []
33
33
  extra_rdoc_files: []
34
34
  files:
35
35
  - ".github/ISSUE_TEMPLATE/bug_report.md"
36
+ - ".github/ISSUE_TEMPLATE/feature_request.md"
36
37
  - ".github/dependabot.yml"
37
38
  - ".github/workflows/main.yml"
38
39
  - ".gitignore"
@@ -45,6 +46,9 @@ files:
45
46
  - Rakefile
46
47
  - bin/console
47
48
  - bin/setup
49
+ - examples/anonymous/Gemfile
50
+ - examples/anonymous/Protocolfile
51
+ - examples/anonymous/config.ru
48
52
  - examples/duck/Gemfile
49
53
  - examples/duck/Protocolfile.duck
50
54
  - examples/duck/config_duck.ru
@@ -72,6 +76,9 @@ files:
72
76
  - lib/toycol/protocol.rb
73
77
  - lib/toycol/proxy.rb
74
78
  - lib/toycol/server.rb
79
+ - lib/toycol/template_generator.rb
80
+ - lib/toycol/templates/application.txt
81
+ - lib/toycol/templates/protocol.txt
75
82
  - lib/toycol/version.rb
76
83
  - toycol.gemspec
77
84
  homepage: https://github.com/shioimm/toycol