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.
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::AppBase.config.log_transformer = Proc.new { _1 }
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::AppBase.config.sensitive_keys`.
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::AppBase.config.log_transformer = Proc.new do |meta|
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::AppBase.config.log_default_metadata.each_pair do |key, value|
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::AppBase.config.app_name
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::AppBase.version
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 = AppBase.config.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 AppBase.config.sensitive_keys.any? { k.match?(_1) }
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 BaseModel
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
- AppBase.raw_db_connection[table_name.to_sym]
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 AppBase.config.db_extensions.include?(:pg_json)
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? ? AppBase.config.db_strict_type_resolving : strict
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? ? AppBase.config.db_strict_type_resolving : strict
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
@@ -0,0 +1,10 @@
1
+ # typed: strict
2
+ # frozen_string_literal: true
3
+
4
+ module Kirei
5
+ module Routing
6
+ NilableHooksType = T.type_alias do
7
+ T.nilable(T::Set[T.proc.void])
8
+ end
9
+ end
10
+ end
@@ -2,16 +2,7 @@
2
2
  # frozen_string_literal: true
3
3
 
4
4
  module Kirei
5
- module Middleware
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
@@ -2,5 +2,5 @@
2
2
  # frozen_string_literal: true
3
3
 
4
4
  module Kirei
5
- VERSION = "0.2.0"
5
+ VERSION = "0.3.0"
6
6
  end
data/lib/kirei.rb CHANGED
@@ -1,7 +1,30 @@
1
1
  # typed: strict
2
2
  # frozen_string_literal: true
3
3
 
4
- require "boot"
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 successfully!")
70
+ Kirei::Logger.logger.info("Kirei (v#{Kirei::VERSION}) booted.")
@@ -2,7 +2,7 @@
2
2
 
3
3
  # rubocop:disable Style/EmptyMethod
4
4
  module Kirei
5
- module BaseModel
5
+ module Model
6
6
  include Kernel # "self" is a class since we include the module in a class
7
7
  include T::Props::Serializable
8
8
 
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.2.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-03-09 00:00:00.000000000 Z
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 strictly typed Ruby micro/REST-framework for building scaleable and performant microservices.
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
- Kirei is based on Sequel as an ORM, Sorbet for typing, and Sinatra for routing.
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/middleware.rb
163
- - lib/kirei/router.rb
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.6
203
+ rubygems_version: 3.5.9
188
204
  signing_key:
189
205
  specification_version: 4
190
- summary: Kirei is a strictly typed Ruby micro/REST-framework for building scaleable
191
- and performant microservices.
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) }
@@ -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