yescode 1.0.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,56 @@
1
+ module Yescode
2
+ module RequestCache
3
+ def self.store
4
+ Thread.current[:request_cache] ||= {}
5
+ end
6
+
7
+ def self.store=(store)
8
+ Thread.current[:request_cache] = store
9
+ end
10
+
11
+ def self.clear!
12
+ Thread.current[:request_cache] = {}
13
+ end
14
+
15
+ def self.begin!
16
+ Thread.current[:request_cache_active] = true
17
+ end
18
+
19
+ def self.end!
20
+ Thread.current[:request_cache_active] = false
21
+ end
22
+
23
+ def self.active?
24
+ Thread.current[:request_cache_active] || false
25
+ end
26
+
27
+ def self.read(key)
28
+ store[key]
29
+ end
30
+
31
+ def self.[](key)
32
+ store[key]
33
+ end
34
+
35
+ def self.write(key, value)
36
+ store[key] = value
37
+ end
38
+
39
+ def self.[]=(key, value)
40
+ store[key] = value
41
+ end
42
+
43
+ def self.exist?(key)
44
+ store.key?(key)
45
+ end
46
+
47
+ def self.fetch(key)
48
+ store[key] = yield unless exist?(key)
49
+ store[key]
50
+ end
51
+
52
+ def self.delete(key, &block)
53
+ store.delete(key, &block)
54
+ end
55
+ end
56
+ end
@@ -0,0 +1,78 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Yescode
4
+ class RouteNotFound < StandardError; end
5
+ class RouteClassDoesNotExist < StandardError; end
6
+ class RouteMethodDoesNotExist < StandardError; end
7
+ class NotFoundError < StandardError; end
8
+ class ServerError < StandardError; end
9
+
10
+ class Router
11
+ using Refinements
12
+
13
+ class << self
14
+ attr_accessor :logger
15
+ end
16
+
17
+ def initialize(app, routes)
18
+ @app = app
19
+ @routes = routes
20
+ @logger = self.class.logger
21
+ end
22
+
23
+ def call(env)
24
+ path_info = env[Rack::PATH_INFO]
25
+ request_method = env[Rack::REQUEST_METHOD]
26
+ params = {}
27
+ route = @routes[request_method].find do |r|
28
+ path = Regexp.new("^#{r.first.gsub(/:(\w+)/, '(?<\1>[a-zA-Z0-9_\-=]+)')}$")
29
+ params = path_info.match(path)&.named_captures
30
+ end
31
+
32
+ raise RouteNotFound unless route
33
+
34
+ params.merge!(env[Rack::RACK_REQUEST_FORM_HASH] || {})
35
+ .transform_keys!(&:to_sym)
36
+ env["params"] = params
37
+ _, class_name, method = route
38
+ klass = nil
39
+ begin
40
+ klass = Object.const_get(class_name)
41
+ rescue NameError => e
42
+ raise RouteClassDoesNotExist, e.message
43
+ end
44
+ obj = klass.new(env)
45
+ raise RouteMethodDoesNotExist, "#{class_name}##{method} does not exist" unless obj.respond_to?(method)
46
+
47
+ @logger&.info(msg: "Request dispatched", route: "#{class_name}##{method}", params: params.except(:_csrf))
48
+ klass.before_actions&.each do |before_action|
49
+ obj.send(before_action)
50
+ end
51
+ response = obj.public_send(method)
52
+ raise NotFoundError if response.nil?
53
+
54
+ case response
55
+ when YesView
56
+ response.csrf_name = obj.csrf_name
57
+ response.csrf_value = obj.csrf_value
58
+ response.assets = @app.assets.to_h
59
+ response.session = obj.session
60
+ response.ajax = env.key?("HTTP_YES_AJAX")
61
+ layout = klass.layout
62
+ content = response.render(response.template)
63
+ content = response.render(layout.template, content:) if layout && response.class < layout.class
64
+ obj.ok content
65
+ else
66
+ response
67
+ end
68
+ rescue NotFoundError, RouteNotFound
69
+ raise if Env.development?
70
+
71
+ [404, { "content-type" => "text/html" }, File.open("public/404.html")]
72
+ rescue StandardError
73
+ raise if Env.development?
74
+
75
+ [500, { "content-type" => "text/html" }, File.open("public/500.html")]
76
+ end
77
+ end
78
+ end
@@ -0,0 +1,23 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Yescode
4
+ class Strings
5
+ SNAKE_CASE_REGEX = /\B([A-Z])/
6
+
7
+ class << self
8
+ def snake_case(str)
9
+ str.gsub(SNAKE_CASE_REGEX, '_\1').downcase
10
+ end
11
+
12
+ def camel_case(str)
13
+ return str if !str.include?('_') && str =~ /[A-Z]+.*/
14
+
15
+ str.split('_').map(&:capitalize).join
16
+ end
17
+
18
+ def pascal_case(str)
19
+ camel_case(str).capitalize
20
+ end
21
+ end
22
+ end
23
+ end
data/lib/yescode.rb ADDED
@@ -0,0 +1,48 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "digest"
4
+ require "logger"
5
+ require "net/smtp"
6
+ require "mail"
7
+ require "rack"
8
+ require "rack/csrf"
9
+ require "stringio"
10
+ require "sqlite3"
11
+
12
+ require "yescode/request_cache"
13
+ require "yescode/request_cache/middleware"
14
+ require "yescode/refinements"
15
+ require "yescode/emote"
16
+ require "yescode/strings"
17
+ require "yescode/env"
18
+ require "yescode/logfmt_formatter"
19
+ require "yescode/router"
20
+ require "yescode/database"
21
+ require "yescode/queries"
22
+ require "yescode/assets"
23
+ require "yescode/asset_compiler"
24
+ require "yescode/generator"
25
+
26
+ require "yes_static"
27
+ require "yes_logger"
28
+ require "yes_rack_logger"
29
+ require "yes_routes"
30
+ require "yes_controller"
31
+ require "yes_view"
32
+ require "yes_record"
33
+ require "yes_mail"
34
+ require "yes_app"
35
+
36
+ def require_all(paths)
37
+ paths.each do |path|
38
+ if path.end_with?("*")
39
+ Dir[path].sort.each do |f|
40
+ next unless f.end_with?("rb")
41
+
42
+ require f
43
+ end
44
+ else
45
+ require path
46
+ end
47
+ end
48
+ end
data/yescode.gemspec ADDED
@@ -0,0 +1,41 @@
1
+ # frozen_string_literal: true
2
+
3
+ Gem::Specification.new do |spec|
4
+ spec.platform = Gem::Platform::RUBY
5
+ spec.name = "yescode"
6
+ spec.version = "1.0.0"
7
+ spec.author = "Sean Walker"
8
+ spec.email = "sean@swlkr.com"
9
+
10
+ spec.summary = "A ruby mvc web framework"
11
+ spec.description = "This gem helps you write mvc web applications"
12
+ spec.homepage = "https://github.com/swlkr/yescode"
13
+ spec.license = "MIT"
14
+
15
+ if spec.respond_to?(:metadata)
16
+ spec.metadata["homepage_uri"] = spec.homepage
17
+ spec.metadata["source_code_uri"] = "https://github.com/swlkr/yescode"
18
+ spec.metadata["changelog_uri"] = "https://github.com/swlkr/yescode/blob/main/CHANGELOG.md"
19
+ else
20
+ raise "RubyGems 2.0 or newer is required to protect against " \
21
+ "public gem pushes."
22
+ end
23
+
24
+ # Specify which files should be added to the gem when it is released.
25
+ # The `git ls-files -z` loads the files in the RubyGem that have been added into git.
26
+ spec.files = Dir.chdir(File.expand_path(__dir__)) do
27
+ `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(docs|examples|test|Dockerfile|\.rubocop\.yml|\.solargraph\.yml|\.github)/}) }
28
+ end
29
+ spec.bindir = "exe"
30
+ spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
31
+ spec.require_paths = ["lib"]
32
+ spec.required_ruby_version = ">= 3.1.0"
33
+
34
+ spec.add_development_dependency "minitest", "~> 5.14"
35
+
36
+ spec.add_dependency "mail", "2.7.1"
37
+ spec.add_dependency "net-smtp", "0.3.1"
38
+ spec.add_dependency "rack", "2.2.3"
39
+ spec.add_dependency "rack_csrf", "2.6.0"
40
+ spec.add_dependency "sqlite3", "1.4.2"
41
+ end
metadata ADDED
@@ -0,0 +1,161 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: yescode
3
+ version: !ruby/object:Gem::Version
4
+ version: 1.0.0
5
+ platform: ruby
6
+ authors:
7
+ - Sean Walker
8
+ autorequire:
9
+ bindir: exe
10
+ cert_chain: []
11
+ date: 2022-05-11 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: minitest
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '5.14'
20
+ type: :development
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '5.14'
27
+ - !ruby/object:Gem::Dependency
28
+ name: mail
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - '='
32
+ - !ruby/object:Gem::Version
33
+ version: 2.7.1
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - '='
39
+ - !ruby/object:Gem::Version
40
+ version: 2.7.1
41
+ - !ruby/object:Gem::Dependency
42
+ name: net-smtp
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - '='
46
+ - !ruby/object:Gem::Version
47
+ version: 0.3.1
48
+ type: :runtime
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - '='
53
+ - !ruby/object:Gem::Version
54
+ version: 0.3.1
55
+ - !ruby/object:Gem::Dependency
56
+ name: rack
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - '='
60
+ - !ruby/object:Gem::Version
61
+ version: 2.2.3
62
+ type: :runtime
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - '='
67
+ - !ruby/object:Gem::Version
68
+ version: 2.2.3
69
+ - !ruby/object:Gem::Dependency
70
+ name: rack_csrf
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - '='
74
+ - !ruby/object:Gem::Version
75
+ version: 2.6.0
76
+ type: :runtime
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - '='
81
+ - !ruby/object:Gem::Version
82
+ version: 2.6.0
83
+ - !ruby/object:Gem::Dependency
84
+ name: sqlite3
85
+ requirement: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - '='
88
+ - !ruby/object:Gem::Version
89
+ version: 1.4.2
90
+ type: :runtime
91
+ prerelease: false
92
+ version_requirements: !ruby/object:Gem::Requirement
93
+ requirements:
94
+ - - '='
95
+ - !ruby/object:Gem::Version
96
+ version: 1.4.2
97
+ description: This gem helps you write mvc web applications
98
+ email: sean@swlkr.com
99
+ executables:
100
+ - yescode
101
+ extensions: []
102
+ extra_rdoc_files: []
103
+ files:
104
+ - CHANGELOG.md
105
+ - Dockerfile
106
+ - Gemfile
107
+ - LICENSE
108
+ - README.md
109
+ - exe/yescode
110
+ - lib/yes_app.rb
111
+ - lib/yes_controller.rb
112
+ - lib/yes_logger.rb
113
+ - lib/yes_mail.rb
114
+ - lib/yes_rack_logger.rb
115
+ - lib/yes_record.rb
116
+ - lib/yes_routes.rb
117
+ - lib/yes_static.rb
118
+ - lib/yes_view.rb
119
+ - lib/yescode.rb
120
+ - lib/yescode/asset.rb
121
+ - lib/yescode/asset_compiler.rb
122
+ - lib/yescode/assets.rb
123
+ - lib/yescode/database.rb
124
+ - lib/yescode/emote.rb
125
+ - lib/yescode/env.rb
126
+ - lib/yescode/generator.rb
127
+ - lib/yescode/logfmt_formatter.rb
128
+ - lib/yescode/queries.rb
129
+ - lib/yescode/refinements.rb
130
+ - lib/yescode/request_cache.rb
131
+ - lib/yescode/request_cache/middleware.rb
132
+ - lib/yescode/router.rb
133
+ - lib/yescode/strings.rb
134
+ - yescode.gemspec
135
+ homepage: https://github.com/swlkr/yescode
136
+ licenses:
137
+ - MIT
138
+ metadata:
139
+ homepage_uri: https://github.com/swlkr/yescode
140
+ source_code_uri: https://github.com/swlkr/yescode
141
+ changelog_uri: https://github.com/swlkr/yescode/blob/main/CHANGELOG.md
142
+ post_install_message:
143
+ rdoc_options: []
144
+ require_paths:
145
+ - lib
146
+ required_ruby_version: !ruby/object:Gem::Requirement
147
+ requirements:
148
+ - - ">="
149
+ - !ruby/object:Gem::Version
150
+ version: 3.1.0
151
+ required_rubygems_version: !ruby/object:Gem::Requirement
152
+ requirements:
153
+ - - ">="
154
+ - !ruby/object:Gem::Version
155
+ version: '0'
156
+ requirements: []
157
+ rubygems_version: 3.3.7
158
+ signing_key:
159
+ specification_version: 4
160
+ summary: A ruby mvc web framework
161
+ test_files: []