rage-rb 0.1.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.
@@ -0,0 +1,202 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "set"
4
+
5
+ module Rage::Router
6
+ class Node
7
+ STATIC = 0
8
+ PARAMETRIC = 1
9
+ WILDCARD = 2
10
+
11
+ attr_reader :is_leaf_node, :handler_storage, :kind
12
+
13
+ def initialize
14
+ @is_leaf_node = false
15
+ @routes = nil
16
+ @handler_storage = nil
17
+ end
18
+
19
+ def add_route(route, constrainer)
20
+ @routes ||= []
21
+ @handler_storage ||= HandlerStorage.new
22
+
23
+ @is_leaf_node = true
24
+ @routes << route
25
+ @handler_storage.add_handler(constrainer, route)
26
+ end
27
+ end
28
+
29
+ class ParentNode < Node
30
+ attr_reader :static_children
31
+
32
+ def initialize
33
+ super
34
+ @static_children = {}
35
+ end
36
+
37
+ def find_static_matching_child(path, path_index)
38
+ static_child = @static_children[path[path_index]]
39
+
40
+ if !static_child || !static_child.match_prefix.call(path, path_index)
41
+ return nil
42
+ end
43
+
44
+ static_child
45
+ end
46
+
47
+ def create_static_child(path)
48
+ if path.length == 0
49
+ return self
50
+ end
51
+
52
+ static_child = @static_children[path[0]]
53
+ if static_child
54
+ i = 1
55
+ while i < static_child.prefix.length
56
+ if path[i] != static_child.prefix[i]
57
+ static_child = static_child.split(self, i)
58
+ break
59
+ end
60
+ i += 1
61
+ end
62
+
63
+ return static_child.create_static_child(path[i, path.length - i])
64
+ end
65
+
66
+ @static_children[path[0]] = StaticNode.new(path)
67
+ end
68
+ end
69
+
70
+ class StaticNode < ParentNode
71
+ attr_reader :prefix, :match_prefix
72
+
73
+ def initialize(prefix)
74
+ super()
75
+ @prefix = prefix
76
+ @wildcard_child = nil
77
+ @parametric_children = []
78
+ @kind = Node::STATIC
79
+
80
+ compile_prefix_match
81
+ end
82
+
83
+ def create_parametric_child(static_suffix, node_path)
84
+ parametric_child = @parametric_children[0]
85
+
86
+ if parametric_child
87
+ parametric_child.node_paths.add(node_path)
88
+ return parametric_child
89
+ end
90
+
91
+ parametric_child = ParametricNode.new(static_suffix, node_path)
92
+ @parametric_children << parametric_child
93
+ @parametric_children.sort! do |child1, child2|
94
+ if child1.static_suffix.nil?
95
+ 1
96
+ elsif child2.static_suffix.nil?
97
+ -1
98
+ elsif child2.static_suffix.end_with?(child1.static_suffix)
99
+ 1
100
+ elsif child1.static_suffix.end_with?(child2.static_suffix)
101
+ -1
102
+ else
103
+ 0
104
+ end
105
+ end
106
+
107
+ parametric_child
108
+ end
109
+
110
+ def create_wildcard_child
111
+ @wildcard_child ||= WildcardNode.new
112
+ end
113
+
114
+ def split(parent_node, length)
115
+ parent_prefix = @prefix[0, length]
116
+ child_prefix = @prefix[length, @prefix.length - length]
117
+
118
+ @prefix = child_prefix
119
+ compile_prefix_match
120
+
121
+ static_node = StaticNode.new(parent_prefix)
122
+ static_node.static_children[child_prefix[0]] = self
123
+ parent_node.static_children[parent_prefix[0]] = static_node
124
+
125
+ static_node
126
+ end
127
+
128
+ def get_next_node(path, path_index, node_stack, params_count)
129
+ node = find_static_matching_child(path, path_index)
130
+ parametric_brother_node_index = 0
131
+
132
+ unless node
133
+ return @wildcard_child if @parametric_children.empty?
134
+
135
+ node = @parametric_children[0]
136
+ parametric_brother_node_index = 1
137
+ end
138
+
139
+ if @wildcard_child
140
+ node_stack << {
141
+ params_count: params_count,
142
+ brother_path_index: path_index,
143
+ brother_node: @wildcard_child
144
+ }
145
+ end
146
+
147
+ i = @parametric_children.length - 1
148
+ while i >= parametric_brother_node_index
149
+ node_stack << {
150
+ params_count: params_count,
151
+ brother_path_index: path_index,
152
+ brother_node: @parametric_children[i]
153
+ }
154
+ i -= 1
155
+ end
156
+
157
+ node
158
+ end
159
+
160
+ private
161
+
162
+ def compile_prefix_match
163
+ if @prefix.length == 1
164
+ @match_prefix = ->(_, _) { true }
165
+ return
166
+ end
167
+
168
+ lines = (1...@prefix.length).map do |i|
169
+ "path[i + #{i}]&.ord == #{@prefix[i].ord}"
170
+ end
171
+
172
+ @match_prefix = eval("->(path, i) { #{lines.join(" && ")} }")
173
+ end
174
+ end
175
+
176
+ class ParametricNode < ParentNode
177
+ attr_reader :static_suffix, :node_paths
178
+
179
+ def initialize(static_suffix, node_path)
180
+ super()
181
+ @static_suffix = static_suffix
182
+ @kind = Node::PARAMETRIC
183
+
184
+ @node_paths = Set.new([node_path])
185
+ end
186
+
187
+ def get_next_node(path, path_index, _, _)
188
+ find_static_matching_child(path, path_index)
189
+ end
190
+ end
191
+
192
+ class WildcardNode < Node
193
+ def initialize
194
+ super
195
+ @kind = Node::WILDCARD
196
+ end
197
+
198
+ def get_next_node(*)
199
+ nil
200
+ end
201
+ end
202
+ end
@@ -0,0 +1,50 @@
1
+ # frozen_string_literal: true
2
+
3
+ class Rage::Router::Strategies::Host
4
+ attr_reader :name, :must_match_when_derived
5
+
6
+ def initialize
7
+ @name = "host"
8
+ @must_match_when_derived = false
9
+ end
10
+
11
+ def storage
12
+ HostStorage.new
13
+ end
14
+
15
+ def custom?
16
+ false
17
+ end
18
+
19
+ def validate(value)
20
+ if !value.is_a?(String) && !value.is_a?(Regexp)
21
+ raise "Host should be a string or a Regexp"
22
+ end
23
+ end
24
+
25
+ class HostStorage
26
+ def initialize
27
+ @hosts = {}
28
+ @regexp_hosts = []
29
+ end
30
+
31
+ def get(host)
32
+ exact = @hosts[host]
33
+ return exact if exact
34
+
35
+ @regexp_hosts.each do |regexp|
36
+ return regexp[:value] if regexp[:host] =~ host.to_s
37
+ end
38
+
39
+ nil
40
+ end
41
+
42
+ def set(host, value)
43
+ if host.is_a?(Regexp)
44
+ @regexp_hosts << { host: host, value: value }
45
+ else
46
+ @hosts[host] = value
47
+ end
48
+ end
49
+ end
50
+ end
data/lib/rage/setup.rb ADDED
@@ -0,0 +1,6 @@
1
+ Iodine.patch_rack
2
+
3
+ project_root = Pathname.new(".").expand_path
4
+
5
+ Dir["#{project_root}/app/**/*.rb"].each { |path| require_relative path }
6
+ require_relative "#{project_root}/config/routes"
@@ -0,0 +1,6 @@
1
+ source "https://rubygems.org"
2
+
3
+ gem "rage"
4
+
5
+ # Build JSON APIs with ease
6
+ # gem "alba"
@@ -0,0 +1,2 @@
1
+ class ApplicationController < RageController::API
2
+ end
@@ -0,0 +1,4 @@
1
+ require "bundler/setup"
2
+ Bundler.require(:default)
3
+
4
+ require "rage/setup"
@@ -0,0 +1,3 @@
1
+ Rage.routes.draw do
2
+ root to: ->(env) { [200, {}, "It works!"] }
3
+ end
@@ -0,0 +1,3 @@
1
+ require_relative "config/application"
2
+
3
+ run Rage.application
File without changes
File without changes
File without changes
@@ -0,0 +1,5 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Rage
4
+ VERSION = "0.1.0"
5
+ end
data/lib/rage.rb ADDED
@@ -0,0 +1,40 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "rack"
4
+ require "json"
5
+ require "iodine"
6
+
7
+ module Rage
8
+ def self.application
9
+ Application.new(__router)
10
+ end
11
+
12
+ def self.routes
13
+ Rage::Router::DSL.new(__router)
14
+ end
15
+
16
+ def self.__router
17
+ @__router ||= Rage::Router::Backend.new
18
+ end
19
+
20
+ module Router
21
+ module Strategies
22
+ end
23
+ end
24
+ end
25
+
26
+ module RageController
27
+ end
28
+
29
+ require_relative "rage/application"
30
+ require_relative "rage/fiber"
31
+ require_relative "rage/fiber_scheduler"
32
+
33
+ require_relative "rage/router/strategies/host"
34
+ require_relative "rage/router/backend"
35
+ require_relative "rage/router/constrainer"
36
+ require_relative "rage/router/dsl"
37
+ require_relative "rage/router/handler_storage"
38
+ require_relative "rage/router/node"
39
+
40
+ require_relative "rage/controller/api"
data/rage.gemspec ADDED
@@ -0,0 +1,33 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "lib/rage/version"
4
+
5
+ Gem::Specification.new do |spec|
6
+ spec.name = "rage-rb"
7
+ spec.version = Rage::VERSION
8
+ spec.authors = ["Roman Samoilov"]
9
+ spec.email = ["rsamoi@icloud.com"]
10
+
11
+ spec.summary = "Fast web framework compatible with Rails."
12
+ spec.homepage = "https://github.com/rage-rb/rage"
13
+ spec.license = "MIT"
14
+ spec.required_ruby_version = ">= 3.0.0"
15
+
16
+ spec.metadata["homepage_uri"] = spec.homepage
17
+ spec.metadata["source_code_uri"] = "https://github.com/rage-rb/rage"
18
+
19
+ # Specify which files should be added to the gem when it is released.
20
+ # The `git ls-files -z` loads the files in the RubyGem that have been added into git.
21
+ spec.files = Dir.chdir(__dir__) do
22
+ `git ls-files -z`.split("\x0").reject do |f|
23
+ (File.expand_path(f) == __FILE__) || f.start_with?(*%w[bin/ test/ spec/ features/ .git .circleci appveyor])
24
+ end
25
+ end
26
+ spec.bindir = "exe"
27
+ spec.executables = ["rage"]
28
+ spec.require_paths = ["lib"]
29
+
30
+ spec.add_dependency "thor"
31
+ spec.add_dependency "rack", "~> 2.0"
32
+ spec.add_dependency "rage-iodine", "~> 1.0"
33
+ end
metadata ADDED
@@ -0,0 +1,120 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: rage-rb
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - Roman Samoilov
8
+ autorequire:
9
+ bindir: exe
10
+ cert_chain: []
11
+ date: 2023-09-15 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: thor
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ">="
18
+ - !ruby/object:Gem::Version
19
+ version: '0'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ">="
25
+ - !ruby/object:Gem::Version
26
+ version: '0'
27
+ - !ruby/object:Gem::Dependency
28
+ name: rack
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: '2.0'
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: '2.0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: rage-iodine
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - "~>"
46
+ - !ruby/object:Gem::Version
47
+ version: '1.0'
48
+ type: :runtime
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - "~>"
53
+ - !ruby/object:Gem::Version
54
+ version: '1.0'
55
+ description:
56
+ email:
57
+ - rsamoi@icloud.com
58
+ executables:
59
+ - rage
60
+ extensions: []
61
+ extra_rdoc_files: []
62
+ files:
63
+ - ".rspec"
64
+ - CHANGELOG.md
65
+ - CODE_OF_CONDUCT.md
66
+ - Gemfile
67
+ - LICENSE.txt
68
+ - README.md
69
+ - Rakefile
70
+ - exe/rage
71
+ - lib/rage.rb
72
+ - lib/rage/application.rb
73
+ - lib/rage/cli.rb
74
+ - lib/rage/controller/api.rb
75
+ - lib/rage/fiber.rb
76
+ - lib/rage/fiber_scheduler.rb
77
+ - lib/rage/router/README.md
78
+ - lib/rage/router/backend.rb
79
+ - lib/rage/router/constrainer.rb
80
+ - lib/rage/router/dsl.rb
81
+ - lib/rage/router/handler_storage.rb
82
+ - lib/rage/router/node.rb
83
+ - lib/rage/router/strategies/host.rb
84
+ - lib/rage/setup.rb
85
+ - lib/rage/templates/Gemfile
86
+ - lib/rage/templates/app-controllers-application_controller.rb
87
+ - lib/rage/templates/config-application.rb
88
+ - lib/rage/templates/config-routes.rb
89
+ - lib/rage/templates/config.ru
90
+ - lib/rage/templates/lib-.keep
91
+ - lib/rage/templates/log-.keep
92
+ - lib/rage/templates/public-.keep
93
+ - lib/rage/version.rb
94
+ - rage.gemspec
95
+ homepage: https://github.com/rage-rb/rage
96
+ licenses:
97
+ - MIT
98
+ metadata:
99
+ homepage_uri: https://github.com/rage-rb/rage
100
+ source_code_uri: https://github.com/rage-rb/rage
101
+ post_install_message:
102
+ rdoc_options: []
103
+ require_paths:
104
+ - lib
105
+ required_ruby_version: !ruby/object:Gem::Requirement
106
+ requirements:
107
+ - - ">="
108
+ - !ruby/object:Gem::Version
109
+ version: 3.0.0
110
+ required_rubygems_version: !ruby/object:Gem::Requirement
111
+ requirements:
112
+ - - ">="
113
+ - !ruby/object:Gem::Version
114
+ version: '0'
115
+ requirements: []
116
+ rubygems_version: 3.4.10
117
+ signing_key:
118
+ specification_version: 4
119
+ summary: Fast web framework compatible with Rails.
120
+ test_files: []