stir_fry 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,64 @@
1
+ :root {
2
+ --ruby-red: #cc342d;
3
+ --ruby-green: #2e8b57;
4
+ --ink: #2b2b2b;
5
+ --muted: #6b6b6b;
6
+ }
7
+
8
+ * {
9
+ box-sizing: border-box;
10
+ }
11
+
12
+ body {
13
+ margin: 0;
14
+ font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Helvetica, Arial, sans-serif;
15
+ color: var(--ink);
16
+ background: #fafafa;
17
+ }
18
+
19
+ section {
20
+ max-width: 640px;
21
+ margin: 0 auto;
22
+ padding: 2rem 1.5rem;
23
+ }
24
+
25
+ header h1 {
26
+ display: inline-block;
27
+ color: var(--ruby-red);
28
+ border-bottom: 3px solid var(--ruby-green);
29
+ padding-bottom: 0.5rem;
30
+ }
31
+
32
+ .error-page {
33
+ text-align: center;
34
+ padding: 4rem 1.5rem;
35
+ }
36
+
37
+ .error-page__code {
38
+ margin: 0;
39
+ color: var(--ruby-red);
40
+ font-size: 4rem;
41
+ font-weight: 700;
42
+ }
43
+
44
+ .error-page__path {
45
+ display: inline-block;
46
+ margin: 0 0 1rem;
47
+ padding: 0.35rem 0.75rem;
48
+ border: 1px solid var(--ruby-green);
49
+ border-radius: 4px;
50
+ background: #eef6f0;
51
+ color: var(--ink);
52
+ font-family: Menlo, Consolas, "Liberation Mono", monospace;
53
+ font-size: 0.9rem;
54
+ }
55
+
56
+ .error-page__message {
57
+ color: var(--muted);
58
+ }
59
+
60
+ ul.error-page__backtrace {
61
+ color: var(--muted);
62
+ text-align: left;
63
+ list-style-type: none;
64
+ }
@@ -0,0 +1,6 @@
1
+ # frozen_string_literal: true
2
+
3
+ module StirFry
4
+ # VERSION is the release library version
5
+ VERSION = "0.1.0"
6
+ end
data/lib/stir_fry.rb ADDED
@@ -0,0 +1,180 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "semantic_logger"
4
+ require "rbx"
5
+ require "rackup"
6
+ require "logger"
7
+
8
+ ##
9
+ # StirFry as a module provides an entrypoint to starting your app. It is also the
10
+ # namespace that contains the server library that will render the rbx templates.
11
+ module StirFry
12
+ # Error is the main root error for most errors raised by the library. Most of these
13
+ # errors are raised to bail out of a request cycle early and return early.
14
+ class Error < StandardError; end
15
+ # Okay represents a http 200 response.
16
+ class OKAY < Error; end
17
+ # Found represents a http 302 response.
18
+ class Found < Error; end
19
+ # NotModified represents a http 304 response.
20
+ class NotModified < Error; end
21
+ # BadRequest represents a http 400 response.
22
+ class BadRequest < Error; end
23
+ # Unauthorized represents a http 401 response.
24
+ class Unauthorized < Error; end
25
+ # NotFound represents a http 404 response.
26
+ class NotFound < Error; end
27
+ # PreconditionFailed represents a http 412 response.
28
+ class PreconditionFailed < Error; end
29
+ # InternalError represents a http 500 response.
30
+ class InternalError < Error; end
31
+
32
+ autoload :App, "stir_fry/app"
33
+ autoload :Component, "stir_fry/component"
34
+ autoload :Pages, "stir_fry/pages"
35
+ autoload :Request, "stir_fry/request"
36
+ autoload :Response, "stir_fry/response"
37
+ autoload :Middleware, "stir_fry/middleware"
38
+ autoload :Version, "stir_fry/version"
39
+
40
+ SIGNALS = %i[INT TERM].freeze # :nodoc:
41
+
42
+ class << self
43
+ attr_reader :running_server # :nodoc:
44
+
45
+ ##
46
+ # Start the application server for an App.
47
+ #
48
+ # Example:
49
+ #
50
+ # ```ruby
51
+ # class App < StirFry::App
52
+ # get "/" { |request:, response:| response.text("Hello world") }
53
+ # end
54
+ #
55
+ # StirFry.run!(App)
56
+ # ```
57
+ #
58
+ # Options:
59
+ #
60
+ # - port [int] port to listen on for the server.
61
+ # Defaults to 8080 in development and 80 in production.
62
+ # - host [string] host to bind on.
63
+ # Default to `localhost` in development and `0.0.0.0` in production
64
+ # - logger [Logger] logger to output requests and app messages to.
65
+ # Defaults to new semantic logger.
66
+ # - log_level [Symbol] the log level or limit output of the log.
67
+ # options: (:trace, :debug, :info, :warn, :error, :fatal)
68
+ # default: :trace in development and :info in production.
69
+ # - log_format [Symbol] the output format of the semantic logger.
70
+ # options: (:default, :color, :json, :logfmt)
71
+ # - log_stdout disable stdout logging.
72
+ # default: true
73
+ # - log_file set a filepath to output logs to.
74
+ # default: nil, only outputs to stdout.
75
+ #
76
+ def run!(app_klass, **options)
77
+ return unless running_server.nil?
78
+
79
+ Rackup::Handler.default.run(app_klass, **extract_options(app_klass, **options)) do |server|
80
+ at_exit { quit! }
81
+ SIGNALS.each { |signal| chain_trap(signal) { quit! } }
82
+ @logger.info("Server started", **server_info(server))
83
+ server.threaded = true if server.respond_to? :threaded=
84
+ @running_server = server
85
+ end
86
+ ensure
87
+ quit!
88
+ end
89
+
90
+ ##
91
+ # Returns the running status of the server. If `run!` has not already been called
92
+ # then this will return false.
93
+ def running? = !running_server.nil?
94
+
95
+ # Is the set environment setting evaluated from environment variables APP_ENV,
96
+ # RACK_ENV or ENV. It defaults to :development.
97
+ def app_env = @app_env ||= (ENV["APP_ENV"] || ENV["RACK_ENV"] || ENV["ENV"] || :development).to_sym
98
+
99
+ # is the app running in development.
100
+ def development? = app_env == :development
101
+
102
+ # is the app running in test.
103
+ def test? = app_env == :test
104
+
105
+ # is the app running in production
106
+ def production? = app_end == :production
107
+
108
+ # Logger is the app wide logger for any app messages.
109
+ def logger = @logger ||= default_logger(App)
110
+
111
+ ##
112
+ # Stops the running server if it is running. If it is not running then this is
113
+ # a no-op
114
+ def quit!
115
+ return if running_server.nil?
116
+
117
+ running_server.respond_to?(:stop!) ? running_server.stop! : running_server.stop
118
+ end
119
+
120
+ private
121
+
122
+ def extract_options(klass, **options)
123
+ @port = options.fetch(:Port, options.fetch(:port, default_port)) || default_port
124
+ @host = options.fetch(:Host, options.fetch(:host, default_host)) || default_host
125
+ @logger = options.delete(:logger) || default_logger(klass, options)
126
+ dev_null = Logger.new(File.open(File::NULL, "w"))
127
+ {
128
+ # Set the capitalized options in case the downcased options are set.
129
+ Port: @port,
130
+ Host: @host,
131
+ # Disable Rack logging
132
+ Logger: dev_null,
133
+ AccessLog: dev_null
134
+ }.merge(options)
135
+ end
136
+
137
+ def server_info(server)
138
+ {
139
+ port: @port,
140
+ host: @host,
141
+ app_env: @app_env,
142
+ threaded: server.respond_to?(:threaded=),
143
+ server: Rackup::Handler.default.name
144
+ }
145
+ end
146
+
147
+ def default_logger(klass, options = {})
148
+ log_format = options.fetch(:log_format, :color) || :color
149
+ log_stdout = options.fetch(:log_silence, false)
150
+ log_file = options.fetch(:log_file, nil)
151
+
152
+ SemanticLogger.add_signal_handler
153
+ SemanticLogger.application = klass.name.to_s
154
+ SemanticLogger.environment = @app_env
155
+ SemanticLogger.default_level = options.fetch(:log_level, default_log_level) || default_log_level
156
+ SemanticLogger.add_appender(io: $stdout, formatter: log_format) unless log_stdout
157
+ SemanticLogger.add_appender(filename: log_file, formatter: log_format) unless log_file.nil?
158
+ SemanticLogger[klass.name.to_s]
159
+ end
160
+
161
+ def default_port
162
+ development? ? "8080" : "80"
163
+ end
164
+
165
+ def default_host
166
+ development? ? "localhost" : "0.0.0.0"
167
+ end
168
+
169
+ def default_log_level
170
+ development? ? :trace : :info
171
+ end
172
+
173
+ def chain_trap(sig, &)
174
+ prev = Signal.trap(sig) do
175
+ yield
176
+ prev.call if prev.respond_to?(:call)
177
+ end
178
+ end
179
+ end
180
+ end
data/stir_fry.gemspec ADDED
@@ -0,0 +1,45 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "lib/stir_fry/version"
4
+
5
+ Gem::Specification.new do |spec|
6
+ spec.name = "stir_fry"
7
+ spec.version = StirFry::VERSION
8
+ spec.authors = ["Tim Anema"]
9
+ spec.email = ["timanema@gmail.com"]
10
+ spec.summary = "Small simple ruby web framework that feels familiar."
11
+ spec.description = <<~DESC
12
+ Small simple ruby web framework that feels familiar.
13
+ It leverages a JSX like templating language, simple routing definitions
14
+ similar to sinatra and usage of ruby that will make it feel easy and understandable.
15
+ DESC
16
+ spec.homepage = "https://github.com/tanema/stir_fry"
17
+ spec.license = "MIT"
18
+ spec.required_ruby_version = ">= 3.1"
19
+ spec.require_paths = ["lib"]
20
+ spec.metadata = {
21
+ "source_code_uri" => "https://github.com/tanema/stir_fry",
22
+ "changelog_uri" => "https://github.com/tanema/stir_fry/blob/main/CHANGELOG.md",
23
+ "homepage_uri" => spec.homepage,
24
+ "bug_tracker_uri" => "https://github.com/tanema/stir_fry/issues",
25
+ "documentation_uri" => "https://github.com/tanema/stir_fry",
26
+ "rubygems_mfa_required" => "true"
27
+ }
28
+ spec.files = Dir["lib/**/*"] + [
29
+ "README.md",
30
+ "CHANGELOG.md",
31
+ "CODE_OF_CONDUCT.md",
32
+ "Gemfile",
33
+ "LICENSE",
34
+ "Rakefile",
35
+ "stir_fry.gemspec"
36
+ ]
37
+
38
+ spec.add_dependency "mustermann", "~> 3.0"
39
+ spec.add_dependency "rack", ">= 3.0.0", "< 4"
40
+ spec.add_dependency "rack-protection", ">= 3.1"
41
+ spec.add_dependency "rack-session", ">= 2.0.0", "< 3"
42
+ spec.add_dependency "rackup", ">= 2.1"
43
+ spec.add_dependency "rbxrb", ">= 0.1"
44
+ spec.add_dependency "semantic_logger", ">= 5.1"
45
+ end
metadata ADDED
@@ -0,0 +1,180 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: stir_fry
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - Tim Anema
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: mustermann
14
+ requirement: !ruby/object:Gem::Requirement
15
+ requirements:
16
+ - - "~>"
17
+ - !ruby/object:Gem::Version
18
+ version: '3.0'
19
+ type: :runtime
20
+ prerelease: false
21
+ version_requirements: !ruby/object:Gem::Requirement
22
+ requirements:
23
+ - - "~>"
24
+ - !ruby/object:Gem::Version
25
+ version: '3.0'
26
+ - !ruby/object:Gem::Dependency
27
+ name: rack
28
+ requirement: !ruby/object:Gem::Requirement
29
+ requirements:
30
+ - - ">="
31
+ - !ruby/object:Gem::Version
32
+ version: 3.0.0
33
+ - - "<"
34
+ - !ruby/object:Gem::Version
35
+ version: '4'
36
+ type: :runtime
37
+ prerelease: false
38
+ version_requirements: !ruby/object:Gem::Requirement
39
+ requirements:
40
+ - - ">="
41
+ - !ruby/object:Gem::Version
42
+ version: 3.0.0
43
+ - - "<"
44
+ - !ruby/object:Gem::Version
45
+ version: '4'
46
+ - !ruby/object:Gem::Dependency
47
+ name: rack-protection
48
+ requirement: !ruby/object:Gem::Requirement
49
+ requirements:
50
+ - - ">="
51
+ - !ruby/object:Gem::Version
52
+ version: '3.1'
53
+ type: :runtime
54
+ prerelease: false
55
+ version_requirements: !ruby/object:Gem::Requirement
56
+ requirements:
57
+ - - ">="
58
+ - !ruby/object:Gem::Version
59
+ version: '3.1'
60
+ - !ruby/object:Gem::Dependency
61
+ name: rack-session
62
+ requirement: !ruby/object:Gem::Requirement
63
+ requirements:
64
+ - - ">="
65
+ - !ruby/object:Gem::Version
66
+ version: 2.0.0
67
+ - - "<"
68
+ - !ruby/object:Gem::Version
69
+ version: '3'
70
+ type: :runtime
71
+ prerelease: false
72
+ version_requirements: !ruby/object:Gem::Requirement
73
+ requirements:
74
+ - - ">="
75
+ - !ruby/object:Gem::Version
76
+ version: 2.0.0
77
+ - - "<"
78
+ - !ruby/object:Gem::Version
79
+ version: '3'
80
+ - !ruby/object:Gem::Dependency
81
+ name: rackup
82
+ requirement: !ruby/object:Gem::Requirement
83
+ requirements:
84
+ - - ">="
85
+ - !ruby/object:Gem::Version
86
+ version: '2.1'
87
+ type: :runtime
88
+ prerelease: false
89
+ version_requirements: !ruby/object:Gem::Requirement
90
+ requirements:
91
+ - - ">="
92
+ - !ruby/object:Gem::Version
93
+ version: '2.1'
94
+ - !ruby/object:Gem::Dependency
95
+ name: rbxrb
96
+ requirement: !ruby/object:Gem::Requirement
97
+ requirements:
98
+ - - ">="
99
+ - !ruby/object:Gem::Version
100
+ version: '0.1'
101
+ type: :runtime
102
+ prerelease: false
103
+ version_requirements: !ruby/object:Gem::Requirement
104
+ requirements:
105
+ - - ">="
106
+ - !ruby/object:Gem::Version
107
+ version: '0.1'
108
+ - !ruby/object:Gem::Dependency
109
+ name: semantic_logger
110
+ requirement: !ruby/object:Gem::Requirement
111
+ requirements:
112
+ - - ">="
113
+ - !ruby/object:Gem::Version
114
+ version: '5.1'
115
+ type: :runtime
116
+ prerelease: false
117
+ version_requirements: !ruby/object:Gem::Requirement
118
+ requirements:
119
+ - - ">="
120
+ - !ruby/object:Gem::Version
121
+ version: '5.1'
122
+ description: |
123
+ Small simple ruby web framework that feels familiar.
124
+ It leverages a JSX like templating language, simple routing definitions
125
+ similar to sinatra and usage of ruby that will make it feel easy and understandable.
126
+ email:
127
+ - timanema@gmail.com
128
+ executables: []
129
+ extensions: []
130
+ extra_rdoc_files: []
131
+ files:
132
+ - CHANGELOG.md
133
+ - CODE_OF_CONDUCT.md
134
+ - Gemfile
135
+ - LICENSE
136
+ - README.md
137
+ - Rakefile
138
+ - lib/stir_fry.rb
139
+ - lib/stir_fry/app.rb
140
+ - lib/stir_fry/component.rb
141
+ - lib/stir_fry/middleware.rb
142
+ - lib/stir_fry/middleware/logger.rb
143
+ - lib/stir_fry/pages.rb
144
+ - lib/stir_fry/pages/error_page.rb
145
+ - lib/stir_fry/pages/layout.rb
146
+ - lib/stir_fry/pages/not_found_page.rb
147
+ - lib/stir_fry/pages/routes_page.rb
148
+ - lib/stir_fry/request.rb
149
+ - lib/stir_fry/response.rb
150
+ - lib/stir_fry/static/stir_fry.css
151
+ - lib/stir_fry/version.rb
152
+ - stir_fry.gemspec
153
+ homepage: https://github.com/tanema/stir_fry
154
+ licenses:
155
+ - MIT
156
+ metadata:
157
+ source_code_uri: https://github.com/tanema/stir_fry
158
+ changelog_uri: https://github.com/tanema/stir_fry/blob/main/CHANGELOG.md
159
+ homepage_uri: https://github.com/tanema/stir_fry
160
+ bug_tracker_uri: https://github.com/tanema/stir_fry/issues
161
+ documentation_uri: https://github.com/tanema/stir_fry
162
+ rubygems_mfa_required: 'true'
163
+ rdoc_options: []
164
+ require_paths:
165
+ - lib
166
+ required_ruby_version: !ruby/object:Gem::Requirement
167
+ requirements:
168
+ - - ">="
169
+ - !ruby/object:Gem::Version
170
+ version: '3.1'
171
+ required_rubygems_version: !ruby/object:Gem::Requirement
172
+ requirements:
173
+ - - ">="
174
+ - !ruby/object:Gem::Version
175
+ version: '0'
176
+ requirements: []
177
+ rubygems_version: 3.6.9
178
+ specification_version: 4
179
+ summary: Small simple ruby web framework that feels familiar.
180
+ test_files: []