kirei 0.2.0 → 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 +4 -4
- data/README.md +40 -24
- data/bin/kirei +1 -1
- data/kirei.gemspec +4 -3
- data/lib/cli/commands/new_app/base_directories.rb +1 -1
- data/lib/cli/commands/new_app/execute.rb +3 -2
- data/lib/cli/commands/new_app/files/app.rb +9 -3
- data/lib/cli/commands/new_app/files/config_ru.rb +1 -1
- data/lib/cli/commands/new_app/files/db_rake.rb +51 -3
- data/lib/cli/commands/new_app/files/irbrc.rb +1 -1
- data/lib/cli/commands/new_app/files/rakefile.rb +1 -1
- data/lib/cli/commands/new_app/files/routes.rb +49 -12
- data/lib/cli/commands/new_app/files/sorbet_config.rb +25 -0
- data/lib/kirei/app.rb +73 -56
- data/lib/kirei/controller.rb +44 -0
- data/lib/kirei/logger.rb +8 -8
- data/lib/kirei/{base_model.rb → model.rb} +5 -5
- data/lib/kirei/routing/base.rb +156 -0
- data/lib/kirei/routing/nilable_hooks_type.rb +10 -0
- data/lib/kirei/{middleware.rb → routing/rack_env_type.rb} +1 -10
- data/lib/kirei/routing/rack_response_type.rb +15 -0
- data/lib/kirei/routing/router.rb +86 -0
- data/lib/kirei/version.rb +1 -1
- data/lib/kirei.rb +27 -2
- data/sorbet/rbi/shims/base_model.rbi +1 -1
- metadata +29 -13
- data/lib/boot.rb +0 -23
- data/lib/kirei/app_base.rb +0 -72
- data/lib/kirei/base_controller.rb +0 -16
- data/lib/kirei/router.rb +0 -61
data/lib/kirei/logger.rb
CHANGED
@@ -17,12 +17,12 @@ module Kirei
|
|
17
17
|
#
|
18
18
|
# You can define a custom log transformer to transform the logline:
|
19
19
|
#
|
20
|
-
# Kirei::
|
20
|
+
# Kirei::App.config.log_transformer = Proc.new { _1 }
|
21
21
|
#
|
22
|
-
# By default, "meta" is flattened, and sensitive values are masked using see `Kirei::
|
22
|
+
# By default, "meta" is flattened, and sensitive values are masked using see `Kirei::App.config.sensitive_keys`.
|
23
23
|
# You can also build on top of the provided log transformer:
|
24
24
|
#
|
25
|
-
# Kirei::
|
25
|
+
# Kirei::App.config.log_transformer = Proc.new do |meta|
|
26
26
|
# flattened_meta = Kirei::Logger.flatten_hash_and_mask_sensitive_values(meta)
|
27
27
|
# # Do something with the flattened meta
|
28
28
|
# flattened_meta.map { _1.to_json }
|
@@ -85,7 +85,7 @@ module Kirei
|
|
85
85
|
).void
|
86
86
|
end
|
87
87
|
def call(level:, label:, meta: {})
|
88
|
-
Kirei::
|
88
|
+
Kirei::App.config.log_default_metadata.each_pair do |key, value|
|
89
89
|
meta[key] ||= value
|
90
90
|
end
|
91
91
|
|
@@ -94,7 +94,7 @@ module Kirei
|
|
94
94
|
# Source: https://opentelemetry.io/docs/concepts/semantic-conventions/
|
95
95
|
#
|
96
96
|
meta[:"service.instance.id"] ||= Thread.current[:request_id]
|
97
|
-
meta[:"service.name"] ||= Kirei::
|
97
|
+
meta[:"service.name"] ||= Kirei::App.config.app_name
|
98
98
|
|
99
99
|
# The Ruby logger only accepts one string as the only argument
|
100
100
|
@queue << { level: level, label: label, meta: meta }
|
@@ -108,12 +108,12 @@ module Kirei
|
|
108
108
|
level = log_data.fetch(:level)
|
109
109
|
label = log_data.fetch(:label)
|
110
110
|
meta = T.let(log_data.fetch(:meta), T::Hash[Symbol, T.untyped])
|
111
|
-
meta[:"service.version"] ||= Kirei::
|
111
|
+
meta[:"service.version"] ||= Kirei::App.version
|
112
112
|
meta[:timestamp] ||= Time.now.utc.iso8601
|
113
113
|
meta[:level] ||= level.to_s.upcase
|
114
114
|
meta[:label] ||= label
|
115
115
|
|
116
|
-
log_transformer =
|
116
|
+
log_transformer = App.config.log_transformer
|
117
117
|
|
118
118
|
loglines = if log_transformer
|
119
119
|
log_transformer.call(meta)
|
@@ -137,7 +137,7 @@ module Kirei
|
|
137
137
|
).returns(String)
|
138
138
|
end
|
139
139
|
def self.mask(k, v)
|
140
|
-
return Kirei::Logger::FILTERED if
|
140
|
+
return Kirei::Logger::FILTERED if App.config.sensitive_keys.any? { k.match?(_1) }
|
141
141
|
|
142
142
|
v
|
143
143
|
end
|
@@ -2,7 +2,7 @@
|
|
2
2
|
# frozen_string_literal: true
|
3
3
|
|
4
4
|
module Kirei
|
5
|
-
module
|
5
|
+
module Model
|
6
6
|
extend T::Sig
|
7
7
|
extend T::Helpers
|
8
8
|
|
@@ -115,7 +115,7 @@ module Kirei
|
|
115
115
|
|
116
116
|
sig { override.returns(Sequel::Dataset) }
|
117
117
|
def db
|
118
|
-
|
118
|
+
App.raw_db_connection[table_name.to_sym]
|
119
119
|
end
|
120
120
|
|
121
121
|
sig do
|
@@ -166,7 +166,7 @@ module Kirei
|
|
166
166
|
def wrap_jsonb_non_primivitives!(attributes)
|
167
167
|
# setting `@raw_db_connection.wrap_json_primitives = true`
|
168
168
|
# only works on JSON primitives, but not on blank hashes/arrays
|
169
|
-
return unless
|
169
|
+
return unless App.config.db_extensions.include?(:pg_json)
|
170
170
|
|
171
171
|
attributes.each_pair do |key, value|
|
172
172
|
next unless value.is_a?(Hash) || value.is_a?(Array)
|
@@ -196,7 +196,7 @@ module Kirei
|
|
196
196
|
).returns(T::Array[T.attached_class])
|
197
197
|
end
|
198
198
|
def resolve(query, strict = nil)
|
199
|
-
strict_loading = strict.nil? ?
|
199
|
+
strict_loading = strict.nil? ? App.config.db_strict_type_resolving : strict
|
200
200
|
|
201
201
|
query.map do |row|
|
202
202
|
row = T.cast(row, T::Hash[Symbol, T.untyped])
|
@@ -212,7 +212,7 @@ module Kirei
|
|
212
212
|
).returns(T.nilable(T.attached_class))
|
213
213
|
end
|
214
214
|
def resolve_first(query, strict = nil)
|
215
|
-
strict_loading = strict.nil? ?
|
215
|
+
strict_loading = strict.nil? ? App.config.db_strict_type_resolving : strict
|
216
216
|
|
217
217
|
resolve(query.limit(1), strict_loading).first
|
218
218
|
end
|
@@ -0,0 +1,156 @@
|
|
1
|
+
# typed: strict
|
2
|
+
# frozen_string_literal: true
|
3
|
+
|
4
|
+
# rubocop:disable Metrics/all
|
5
|
+
|
6
|
+
module Kirei
|
7
|
+
module Routing
|
8
|
+
class Base
|
9
|
+
extend T::Sig
|
10
|
+
|
11
|
+
sig { params(params: T::Hash[String, T.untyped]).void }
|
12
|
+
def initialize(params: {})
|
13
|
+
@router = T.let(Router.instance, Router)
|
14
|
+
@params = T.let(params, T::Hash[String, T.untyped])
|
15
|
+
end
|
16
|
+
|
17
|
+
sig { returns(T::Hash[String, T.untyped]) }
|
18
|
+
attr_reader :params
|
19
|
+
|
20
|
+
sig { params(env: RackEnvType).returns(RackResponseType) }
|
21
|
+
def call(env)
|
22
|
+
http_verb = Router::Verb.deserialize(env.fetch("REQUEST_METHOD"))
|
23
|
+
req_path = T.cast(env.fetch("REQUEST_PATH"), String)
|
24
|
+
#
|
25
|
+
# TODO: reject requests from unexpected hosts -> allow configuring allowed hosts in a `cors.rb` file
|
26
|
+
# ( offer a scaffold for this file )
|
27
|
+
# -> use https://github.com/cyu/rack-cors ?
|
28
|
+
#
|
29
|
+
|
30
|
+
route = Router.instance.get(http_verb, req_path)
|
31
|
+
return [404, {}, ["Not Found"]] if route.nil?
|
32
|
+
|
33
|
+
params = case route.verb
|
34
|
+
when Router::Verb::GET
|
35
|
+
query = T.cast(env.fetch("QUERY_STRING"), String)
|
36
|
+
query.split("&").to_h do |p|
|
37
|
+
k, v = p.split("=")
|
38
|
+
k = T.cast(k, String)
|
39
|
+
[k, v]
|
40
|
+
end
|
41
|
+
when Router::Verb::POST, Router::Verb::PUT, Router::Verb::PATCH
|
42
|
+
# TODO: based on content-type, parse the body differently
|
43
|
+
# build-in support for JSON & XML
|
44
|
+
body = T.cast(env.fetch("rack.input"), T.any(IO, StringIO))
|
45
|
+
res = Oj.load(body.read, Kirei::OJ_OPTIONS)
|
46
|
+
body.rewind # TODO: maybe don't rewind if we don't need to?
|
47
|
+
T.cast(res, T::Hash[String, T.untyped])
|
48
|
+
else
|
49
|
+
Logger.logger.warn("Unsupported HTTP verb: #{http_verb.serialize} send to #{req_path}")
|
50
|
+
{}
|
51
|
+
end
|
52
|
+
|
53
|
+
req_id = T.cast(env["HTTP_X_REQUEST_ID"], T.nilable(String))
|
54
|
+
req_id ||= "req_#{App.environment}_#{SecureRandom.uuid}"
|
55
|
+
Thread.current[:request_id] = req_id
|
56
|
+
|
57
|
+
controller = route.controller
|
58
|
+
before_hooks = collect_hooks(controller, :before_hooks)
|
59
|
+
run_hooks(before_hooks)
|
60
|
+
|
61
|
+
status, headers, body = T.cast(
|
62
|
+
controller.new(params: params).public_send(route.action),
|
63
|
+
RackResponseType,
|
64
|
+
)
|
65
|
+
|
66
|
+
after_hooks = collect_hooks(controller, :after_hooks)
|
67
|
+
run_hooks(after_hooks)
|
68
|
+
|
69
|
+
headers["X-Request-Id"] ||= req_id
|
70
|
+
|
71
|
+
default_headers.each do |header_name, default_value|
|
72
|
+
headers[header_name] ||= default_value
|
73
|
+
end
|
74
|
+
|
75
|
+
[
|
76
|
+
status,
|
77
|
+
headers,
|
78
|
+
body,
|
79
|
+
]
|
80
|
+
end
|
81
|
+
|
82
|
+
#
|
83
|
+
# Kirei::App#render
|
84
|
+
# * "status": defaults to 200
|
85
|
+
# * "headers": defaults to an empty hash
|
86
|
+
#
|
87
|
+
sig do
|
88
|
+
params(
|
89
|
+
body: String,
|
90
|
+
status: Integer,
|
91
|
+
headers: T::Hash[String, String],
|
92
|
+
).returns(RackResponseType)
|
93
|
+
end
|
94
|
+
def render(body, status: 200, headers: {})
|
95
|
+
# merge default headers
|
96
|
+
# support a "type" to set content-type header? (or default to json, and users must set the header themselves for other types?)
|
97
|
+
[
|
98
|
+
status,
|
99
|
+
headers,
|
100
|
+
[body],
|
101
|
+
]
|
102
|
+
end
|
103
|
+
|
104
|
+
sig { returns(T::Hash[String, String]) }
|
105
|
+
def default_headers
|
106
|
+
# "Access-Control-Allow-Origin": the user should set that
|
107
|
+
{
|
108
|
+
# security relevant headers
|
109
|
+
"X-Frame-Options" => "DENY",
|
110
|
+
"X-Content-Type-Options" => "nosniff",
|
111
|
+
"X-XSS-Protection" => "1; mode=block", # for legacy clients/browsers
|
112
|
+
"Strict-Transport-Security" => "max-age=31536000; includeSubDomains", # for HTTPS
|
113
|
+
"Cache-Control" => "no-store", # the user should set that if caching is needed
|
114
|
+
"Referrer-Policy" => "strict-origin-when-cross-origin",
|
115
|
+
"Content-Security-Policy" => "default-src 'none'; frame-ancestors 'none'",
|
116
|
+
|
117
|
+
# other headers
|
118
|
+
"Content-Type" => "application/json; charset=utf-8",
|
119
|
+
}
|
120
|
+
end
|
121
|
+
|
122
|
+
sig { params(hooks: NilableHooksType).void }
|
123
|
+
private def run_hooks(hooks)
|
124
|
+
return if hooks.nil? || hooks.empty?
|
125
|
+
|
126
|
+
hooks.each(&:call)
|
127
|
+
end
|
128
|
+
|
129
|
+
sig do
|
130
|
+
params(
|
131
|
+
controller: T.class_of(Controller),
|
132
|
+
hooks_type: Symbol,
|
133
|
+
).returns(NilableHooksType)
|
134
|
+
end
|
135
|
+
private def collect_hooks(controller, hooks_type)
|
136
|
+
result = T.let(Set.new, T::Set[T.proc.void])
|
137
|
+
|
138
|
+
controller.ancestors.reverse.each do |ancestor|
|
139
|
+
next unless ancestor < Controller
|
140
|
+
|
141
|
+
supported_hooks = %i[before_hooks after_hooks]
|
142
|
+
unless supported_hooks.include?(hooks_type)
|
143
|
+
raise "Unexpected hook type, got #{hooks_type}, expected one of: #{supported_hooks.join(",")}"
|
144
|
+
end
|
145
|
+
|
146
|
+
hooks = T.let(ancestor.public_send(hooks_type), NilableHooksType)
|
147
|
+
result.merge(hooks) if hooks&.any?
|
148
|
+
end
|
149
|
+
|
150
|
+
result
|
151
|
+
end
|
152
|
+
end
|
153
|
+
end
|
154
|
+
end
|
155
|
+
|
156
|
+
# rubocop:enable Metrics/all
|
@@ -2,16 +2,7 @@
|
|
2
2
|
# frozen_string_literal: true
|
3
3
|
|
4
4
|
module Kirei
|
5
|
-
module
|
6
|
-
# https://github.com/rack/rack/blob/main/UPGRADE-GUIDE.md#rack-3-upgrade-guide
|
7
|
-
RackResponseType = T.type_alias do
|
8
|
-
[
|
9
|
-
Integer,
|
10
|
-
T::Hash[String, String], # in theory, the values are allowed to be arrays of integers for binary representations
|
11
|
-
T.any(T::Array[String], Proc),
|
12
|
-
]
|
13
|
-
end
|
14
|
-
|
5
|
+
module Routing
|
15
6
|
RackEnvType = T.type_alias do
|
16
7
|
T::Hash[
|
17
8
|
String,
|
@@ -0,0 +1,15 @@
|
|
1
|
+
# typed: strict
|
2
|
+
# frozen_string_literal: true
|
3
|
+
|
4
|
+
module Kirei
|
5
|
+
module Routing
|
6
|
+
# https://github.com/rack/rack/blob/main/UPGRADE-GUIDE.md#rack-3-upgrade-guide
|
7
|
+
RackResponseType = T.type_alias do
|
8
|
+
[
|
9
|
+
Integer, # status
|
10
|
+
T::Hash[String, String], # headers. Values may be arrays of integers for binary representations
|
11
|
+
T.any(T::Array[String], Proc), # body
|
12
|
+
]
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
@@ -0,0 +1,86 @@
|
|
1
|
+
# typed: strict
|
2
|
+
# frozen_string_literal: true
|
3
|
+
|
4
|
+
require("singleton")
|
5
|
+
|
6
|
+
module Kirei
|
7
|
+
module Routing
|
8
|
+
#
|
9
|
+
# Usage:
|
10
|
+
#
|
11
|
+
# Router.add_routes([
|
12
|
+
# Route.new(
|
13
|
+
# verb: Kirei::Router::Verb::GET,
|
14
|
+
# path: "/livez",
|
15
|
+
# controller: Controllers::HealthController,
|
16
|
+
# action: "livez",
|
17
|
+
# ),
|
18
|
+
# ])
|
19
|
+
#
|
20
|
+
class Router
|
21
|
+
extend T::Sig
|
22
|
+
include ::Singleton
|
23
|
+
|
24
|
+
class Verb < T::Enum
|
25
|
+
enums do
|
26
|
+
# idempotent
|
27
|
+
GET = new("GET")
|
28
|
+
# non-idempotent
|
29
|
+
POST = new("POST")
|
30
|
+
# idempotent
|
31
|
+
PUT = new("PUT")
|
32
|
+
# non-idempotent
|
33
|
+
PATCH = new("PATCH")
|
34
|
+
# non-idempotent
|
35
|
+
DELETE = new("DELETE")
|
36
|
+
# idempotent
|
37
|
+
HEAD = new("HEAD")
|
38
|
+
# idempotent
|
39
|
+
OPTIONS = new("OPTIONS")
|
40
|
+
# idempotent
|
41
|
+
TRACE = new("TRACE")
|
42
|
+
# non-idempotent
|
43
|
+
CONNECT = new("CONNECT")
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
class Route < T::Struct
|
48
|
+
const :verb, Verb
|
49
|
+
const :path, String
|
50
|
+
const :controller, T.class_of(Controller)
|
51
|
+
const :action, String
|
52
|
+
end
|
53
|
+
|
54
|
+
RoutesHash = T.type_alias do
|
55
|
+
T::Hash[String, Route]
|
56
|
+
end
|
57
|
+
|
58
|
+
sig { void }
|
59
|
+
def initialize
|
60
|
+
@routes = T.let({}, RoutesHash)
|
61
|
+
end
|
62
|
+
|
63
|
+
sig { returns(RoutesHash) }
|
64
|
+
attr_reader :routes
|
65
|
+
|
66
|
+
sig do
|
67
|
+
params(
|
68
|
+
verb: Verb,
|
69
|
+
path: String,
|
70
|
+
).returns(T.nilable(Route))
|
71
|
+
end
|
72
|
+
def get(verb, path)
|
73
|
+
key = "#{verb.serialize} #{path}"
|
74
|
+
routes[key]
|
75
|
+
end
|
76
|
+
|
77
|
+
sig { params(routes: T::Array[Route]).void }
|
78
|
+
def self.add_routes(routes)
|
79
|
+
routes.each do |route|
|
80
|
+
key = "#{route.verb.serialize} #{route.path}"
|
81
|
+
instance.routes[key] = route
|
82
|
+
end
|
83
|
+
end
|
84
|
+
end
|
85
|
+
end
|
86
|
+
end
|
data/lib/kirei/version.rb
CHANGED
data/lib/kirei.rb
CHANGED
@@ -1,7 +1,30 @@
|
|
1
1
|
# typed: strict
|
2
2
|
# frozen_string_literal: true
|
3
3
|
|
4
|
-
|
4
|
+
# This is the entrypoint into the application,
|
5
|
+
# This file loads first, hence we don't have Sorbet loaded yet.
|
6
|
+
|
7
|
+
#
|
8
|
+
# Load Order is important!
|
9
|
+
#
|
10
|
+
|
11
|
+
# First: check if all gems are installed correctly
|
12
|
+
require "bundler/setup"
|
13
|
+
|
14
|
+
# Second: load all gems (runtime dependencies only)
|
15
|
+
require "logger"
|
16
|
+
require "sorbet-runtime"
|
17
|
+
require "oj"
|
18
|
+
require "rack"
|
19
|
+
require "pg"
|
20
|
+
require "sequel" # "sequel_pg" is auto-required by "sequel"
|
21
|
+
|
22
|
+
# Third: load all application code
|
23
|
+
require("zeitwerk")
|
24
|
+
loader = Zeitwerk::Loader.for_gem(warn_on_extra_files: false)
|
25
|
+
loader.ignore("#{__dir__}/cli")
|
26
|
+
loader.ignore("#{__dir__}/cli.rb")
|
27
|
+
loader.setup
|
5
28
|
|
6
29
|
module Kirei
|
7
30
|
extend T::Sig
|
@@ -40,6 +63,8 @@ module Kirei
|
|
40
63
|
end
|
41
64
|
end
|
42
65
|
|
66
|
+
loader.eager_load
|
67
|
+
|
43
68
|
Kirei.configure(&:itself)
|
44
69
|
|
45
|
-
Kirei::Logger.logger.info("Kirei (#{Kirei::VERSION}) booted
|
70
|
+
Kirei::Logger.logger.info("Kirei (v#{Kirei::VERSION}) booted.")
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: kirei
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.3.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Ludwig Reinmiedl
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2024-
|
11
|
+
date: 2024-05-13 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: oj
|
@@ -52,6 +52,20 @@ dependencies:
|
|
52
52
|
- - "~>"
|
53
53
|
- !ruby/object:Gem::Version
|
54
54
|
version: '1.0'
|
55
|
+
- !ruby/object:Gem::Dependency
|
56
|
+
name: zeitwerk
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
58
|
+
requirements:
|
59
|
+
- - "~>"
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '2.5'
|
62
|
+
type: :runtime
|
63
|
+
prerelease: false
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
65
|
+
requirements:
|
66
|
+
- - "~>"
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: '2.5'
|
55
69
|
- !ruby/object:Gem::Dependency
|
56
70
|
name: puma
|
57
71
|
requirement: !ruby/object:Gem::Requirement
|
@@ -123,9 +137,9 @@ dependencies:
|
|
123
137
|
- !ruby/object:Gem::Version
|
124
138
|
version: '1.0'
|
125
139
|
description: |
|
126
|
-
Kirei is a
|
140
|
+
Kirei is a Ruby micro/REST-framework for building scalable and performant microservices.
|
127
141
|
It is built from the ground up to be clean and easy to use.
|
128
|
-
|
142
|
+
It is a Rack app, and uses Sorbet for typing, Sequel as an ORM, Zeitwerk for autoloading, and Puma as a web server.
|
129
143
|
It strives to have zero magic and to be as explicit as possible.
|
130
144
|
email:
|
131
145
|
- lud@reinmiedl.com
|
@@ -140,7 +154,6 @@ files:
|
|
140
154
|
- README.md
|
141
155
|
- bin/kirei
|
142
156
|
- kirei.gemspec
|
143
|
-
- lib/boot.rb
|
144
157
|
- lib/cli.rb
|
145
158
|
- lib/cli/commands/new_app/base_directories.rb
|
146
159
|
- lib/cli/commands/new_app/execute.rb
|
@@ -150,17 +163,20 @@ files:
|
|
150
163
|
- lib/cli/commands/new_app/files/irbrc.rb
|
151
164
|
- lib/cli/commands/new_app/files/rakefile.rb
|
152
165
|
- lib/cli/commands/new_app/files/routes.rb
|
166
|
+
- lib/cli/commands/new_app/files/sorbet_config.rb
|
153
167
|
- lib/cli/commands/start.rb
|
154
168
|
- lib/kirei.rb
|
155
169
|
- lib/kirei/app.rb
|
156
|
-
- lib/kirei/app_base.rb
|
157
|
-
- lib/kirei/base_controller.rb
|
158
|
-
- lib/kirei/base_model.rb
|
159
170
|
- lib/kirei/config.rb
|
171
|
+
- lib/kirei/controller.rb
|
160
172
|
- lib/kirei/helpers.rb
|
161
173
|
- lib/kirei/logger.rb
|
162
|
-
- lib/kirei/
|
163
|
-
- lib/kirei/
|
174
|
+
- lib/kirei/model.rb
|
175
|
+
- lib/kirei/routing/base.rb
|
176
|
+
- lib/kirei/routing/nilable_hooks_type.rb
|
177
|
+
- lib/kirei/routing/rack_env_type.rb
|
178
|
+
- lib/kirei/routing/rack_response_type.rb
|
179
|
+
- lib/kirei/routing/router.rb
|
164
180
|
- lib/kirei/version.rb
|
165
181
|
- sorbet/rbi/shims/base_model.rbi
|
166
182
|
homepage: https://github.com/swiknaba/kirei
|
@@ -184,9 +200,9 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
184
200
|
- !ruby/object:Gem::Version
|
185
201
|
version: '0'
|
186
202
|
requirements: []
|
187
|
-
rubygems_version: 3.5.
|
203
|
+
rubygems_version: 3.5.9
|
188
204
|
signing_key:
|
189
205
|
specification_version: 4
|
190
|
-
summary: Kirei is a
|
191
|
-
|
206
|
+
summary: Kirei is a typed Ruby micro/REST-framework for building scalable and performant
|
207
|
+
microservices.
|
192
208
|
test_files: []
|
data/lib/boot.rb
DELETED
@@ -1,23 +0,0 @@
|
|
1
|
-
# typed: false
|
2
|
-
# frozen_string_literal: true
|
3
|
-
|
4
|
-
# This is the entrypoint into the application,
|
5
|
-
# This file loads first, hence we don't have Sorbet loaded yet.
|
6
|
-
|
7
|
-
#
|
8
|
-
# Load Order is important!
|
9
|
-
#
|
10
|
-
|
11
|
-
# First: check if all gems are installed correctly
|
12
|
-
require "bundler/setup"
|
13
|
-
|
14
|
-
# Second: load all gems (runtime dependencies only)
|
15
|
-
require "logger"
|
16
|
-
require "sorbet-runtime"
|
17
|
-
require "oj"
|
18
|
-
require "rack"
|
19
|
-
require "pg"
|
20
|
-
require "sequel" # "sequel_pg" is auto-required by "sequel"
|
21
|
-
|
22
|
-
# Third: load all application code
|
23
|
-
Dir[File.join(__dir__, "kirei/**/*.rb")].each { require(_1) }
|
data/lib/kirei/app_base.rb
DELETED
@@ -1,72 +0,0 @@
|
|
1
|
-
# typed: strict
|
2
|
-
# frozen_string_literal: true
|
3
|
-
|
4
|
-
require_relative("app")
|
5
|
-
|
6
|
-
module Kirei
|
7
|
-
class AppBase < Kirei::App
|
8
|
-
class << self
|
9
|
-
extend T::Sig
|
10
|
-
|
11
|
-
# convenience method since "Kirei.configuration" must be nilable since it is nil
|
12
|
-
# at the beginning of initilization of the app
|
13
|
-
sig { returns(Kirei::Config) }
|
14
|
-
def config
|
15
|
-
T.must(Kirei.configuration)
|
16
|
-
end
|
17
|
-
|
18
|
-
sig { returns(Pathname) }
|
19
|
-
def root
|
20
|
-
defined?(::APP_ROOT) ? Pathname.new(::APP_ROOT) : Pathname.new(Dir.pwd)
|
21
|
-
end
|
22
|
-
|
23
|
-
sig { returns(String) }
|
24
|
-
def version
|
25
|
-
@version = T.let(@version, T.nilable(String))
|
26
|
-
@version ||= ENV.fetch("APP_VERSION", nil)
|
27
|
-
@version ||= ENV.fetch("GIT_SHA", nil)
|
28
|
-
@version ||= T.must(
|
29
|
-
`command -v git && git rev-parse --short HEAD`.to_s.split("\n").last,
|
30
|
-
).freeze # localhost
|
31
|
-
end
|
32
|
-
|
33
|
-
sig { returns(String) }
|
34
|
-
def environment
|
35
|
-
ENV.fetch("RACK_ENV", "development")
|
36
|
-
end
|
37
|
-
|
38
|
-
sig { returns(String) }
|
39
|
-
def default_db_name
|
40
|
-
@default_db_name ||= T.let("#{config.app_name}_#{environment}".freeze, T.nilable(String))
|
41
|
-
end
|
42
|
-
|
43
|
-
sig { returns(String) }
|
44
|
-
def default_db_url
|
45
|
-
@default_db_url ||= T.let(
|
46
|
-
ENV.fetch("DATABASE_URL", "postgresql://localhost:5432/#{default_db_name}"),
|
47
|
-
T.nilable(String),
|
48
|
-
)
|
49
|
-
end
|
50
|
-
|
51
|
-
sig { returns(Sequel::Database) }
|
52
|
-
def raw_db_connection
|
53
|
-
@raw_db_connection = T.let(@raw_db_connection, T.nilable(Sequel::Database))
|
54
|
-
return @raw_db_connection unless @raw_db_connection.nil?
|
55
|
-
|
56
|
-
# calling "Sequel.connect" creates a new connection
|
57
|
-
@raw_db_connection = Sequel.connect(AppBase.config.db_url || default_db_url)
|
58
|
-
|
59
|
-
config.db_extensions.each do |ext|
|
60
|
-
T.cast(@raw_db_connection, Sequel::Database).extension(ext)
|
61
|
-
end
|
62
|
-
|
63
|
-
if config.db_extensions.include?(:pg_json)
|
64
|
-
# https://github.com/jeremyevans/sequel/blob/5.75.0/lib/sequel/extensions/pg_json.rb#L8
|
65
|
-
@raw_db_connection.wrap_json_primitives = true
|
66
|
-
end
|
67
|
-
|
68
|
-
@raw_db_connection
|
69
|
-
end
|
70
|
-
end
|
71
|
-
end
|
72
|
-
end
|
@@ -1,16 +0,0 @@
|
|
1
|
-
# typed: strict
|
2
|
-
# frozen_string_literal: true
|
3
|
-
|
4
|
-
require_relative("app")
|
5
|
-
|
6
|
-
module Kirei
|
7
|
-
class BaseController < Kirei::App
|
8
|
-
extend T::Sig
|
9
|
-
# register(Sinatra::Namespace)
|
10
|
-
|
11
|
-
# before do
|
12
|
-
# Thread.current[:request_id] = request.env["HTTP_X_REQUEST_ID"].presence ||
|
13
|
-
# "req_#{AppBase.environment}_#{SecureRandom.uuid}"
|
14
|
-
# end
|
15
|
-
end
|
16
|
-
end
|