tina4ruby 0.5.0 → 0.5.2

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: b0b50ab236443af5d0a22150e466096fe58320867bc2e557ee7d5ad986960131
4
- data.tar.gz: 1605da392f7f7ef57dca0a1f03f1d8b83ce15a614c6d8af5c918af2065c5da25
3
+ metadata.gz: 699bbf680f46c379b0961743db6833320d732307a16bbc4d69e2ca5f408ee7d9
4
+ data.tar.gz: 761653a1180fd152e9eeeb3527d154381616985d53c0143f24cae5c316aa4461
5
5
  SHA512:
6
- metadata.gz: 129fe8850e1e77686dbf6cbd2c08c6ac0aed1fe7ce18db0d59f5dbc1a5241edb0d8ed66edef9c6ebc082c54d5e74e43689a6b2038df8a4b9556aa74a8bfc60a4
7
- data.tar.gz: 1119a3c72f04b6dbaf5f00a8e5301632fec5573609c50c75ee1982c2b432e125bf5b0a94f8998c2231f59181093208b9ed9e71232b3136747a95c10af139ff6c
6
+ metadata.gz: 27dd9fec865fc4e66c1bb68ffbf785b71130625b3ce560edcae24c7ff5ce4cc481a86bae5b7ac169a81529c279bf50a49df43c1f55606060081bfc433eda6cab
7
+ data.tar.gz: 1693f488ddea8df352c85833f412f7346b658644a1de6da5a05cc0dce4baa0a6262d2af26f0ffc6413f7182c513e03eb530851b169c79d7b6feb90f46935fd2a
@@ -0,0 +1,54 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Tina4
4
+ # Lightweight dependency injection container.
5
+ #
6
+ # Tina4.register(:mailer, MailService.new) # concrete instance
7
+ # Tina4.register(:db) { Database.new(ENV["DB_URL"]) } # lazy factory
8
+ # Tina4.resolve(:mailer) # => MailService instance
9
+ #
10
+ module Container
11
+ class << self
12
+ def registry
13
+ @registry ||= {}
14
+ end
15
+
16
+ # Register a service by name.
17
+ # Pass an instance directly, or a block for lazy instantiation.
18
+ def register(name, instance = nil, &factory)
19
+ raise ArgumentError, "provide an instance or a block, not both" if instance && factory
20
+ raise ArgumentError, "provide an instance or a block" unless instance || factory
21
+
22
+ registry[name.to_sym] = if factory
23
+ { factory: factory, instance: nil }
24
+ else
25
+ { factory: nil, instance: instance }
26
+ end
27
+ end
28
+
29
+ # Resolve a service by name.
30
+ # Lazy factories are called once and memoized.
31
+ def resolve(name)
32
+ entry = registry[name.to_sym]
33
+ raise KeyError, "service not registered: #{name}" unless entry
34
+
35
+ if entry[:instance]
36
+ entry[:instance]
37
+ elsif entry[:factory]
38
+ entry[:instance] = entry[:factory].call
39
+ entry[:instance]
40
+ end
41
+ end
42
+
43
+ # Check if a service is registered.
44
+ def registered?(name)
45
+ registry.key?(name.to_sym)
46
+ end
47
+
48
+ # Remove all registrations (useful in tests).
49
+ def clear!
50
+ @registry = {}
51
+ end
52
+ end
53
+ end
54
+ end
@@ -125,8 +125,8 @@ module Tina4
125
125
  end
126
126
 
127
127
  def serve_openapi_json
128
- spec = Tina4::Swagger.generate
129
- [200, { "content-type" => "application/json; charset=utf-8" }, [JSON.generate(spec)]]
128
+ @openapi_json ||= JSON.generate(Tina4::Swagger.generate)
129
+ [200, { "content-type" => "application/json; charset=utf-8" }, [@openapi_json]]
130
130
  end
131
131
 
132
132
  def handle_403
@@ -125,9 +125,11 @@ module Tina4
125
125
  content
126
126
  end
127
127
 
128
+ HTML_ESCAPE = { "&" => "&amp;", "<" => "&lt;", ">" => "&gt;", '"' => "&quot;", "'" => "&#39;" }.freeze
129
+ HTML_ESCAPE_PATTERN = /[&<>"']/
130
+
128
131
  def self.escape_html(str)
129
- str.gsub("&", "&amp;").gsub("<", "&lt;").gsub(">", "&gt;")
130
- .gsub('"', "&quot;").gsub("'", "&#39;")
132
+ str.gsub(HTML_ESCAPE_PATTERN, HTML_ESCAPE)
131
133
  end
132
134
 
133
135
  def self.format_date(value, fmt)
@@ -186,7 +188,7 @@ module Tina4
186
188
  collection_expr = Regexp.last_match(3)
187
189
  body = Regexp.last_match(4)
188
190
  collection = evaluate_expression(collection_expr)
189
- output = ""
191
+ output = +""
190
192
  items = case collection
191
193
  when Array then collection
192
194
  when Hash then collection.to_a
@@ -210,7 +212,7 @@ module Tina4
210
212
  loop_context[key_or_val] = item
211
213
  end
212
214
  sub_engine = TwigEngine.new(loop_context, @base_dir)
213
- output += sub_engine.render(body)
215
+ output << sub_engine.render(body)
214
216
  end
215
217
  output
216
218
  end
@@ -292,24 +294,24 @@ module Tina4
292
294
 
293
295
  def parse_filter_args(args_str)
294
296
  args = []
295
- current = ""
297
+ current = +""
296
298
  in_quote = nil
297
299
  args_str.each_char do |ch|
298
300
  if in_quote
299
301
  if ch == in_quote
300
- current += ch
302
+ current << ch
301
303
  in_quote = nil
302
304
  else
303
- current += ch
305
+ current << ch
304
306
  end
305
307
  elsif ch == '"' || ch == "'"
306
308
  in_quote = ch
307
- current += ch
309
+ current << ch
308
310
  elsif ch == ","
309
311
  args << current.strip
310
- current = ""
312
+ current = +""
311
313
  else
312
- current += ch
314
+ current << ch
313
315
  end
314
316
  end
315
317
  args << current.strip unless current.strip.empty?
data/lib/tina4/version.rb CHANGED
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Tina4
4
- VERSION = "0.5.0"
4
+ VERSION = "0.5.2"
5
5
  end
data/lib/tina4.rb CHANGED
@@ -1,5 +1,13 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ # ── Fast JSON: use oj if available, fall back to stdlib json ──────────
4
+ begin
5
+ require "oj"
6
+ Oj.default_options = { mode: :compat, symbol_keys: false }
7
+ rescue LoadError
8
+ # oj not installed — stdlib json is fine
9
+ end
10
+
3
11
  # ── Core (always loaded) ──────────────────────────────────────────────
4
12
  require_relative "tina4/version"
5
13
  require_relative "tina4/debug"
@@ -18,6 +26,7 @@ require_relative "tina4/auth"
18
26
  require_relative "tina4/session"
19
27
  require_relative "tina4/middleware"
20
28
  require_relative "tina4/localization"
29
+ require_relative "tina4/container"
21
30
  require_relative "tina4/queue"
22
31
 
23
32
  module Tina4
@@ -209,6 +218,15 @@ module Tina4
209
218
  Tina4::Localization.t(key, **options)
210
219
  end
211
220
 
221
+ # DI container shortcuts
222
+ def register(name, instance = nil, &block)
223
+ Tina4::Container.register(name, instance, &block)
224
+ end
225
+
226
+ def resolve(name)
227
+ Tina4::Container.resolve(name)
228
+ end
229
+
212
230
  private
213
231
 
214
232
  # Resolve auth option for route registration
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: tina4ruby
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.5.0
4
+ version: 0.5.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Tina4 Team
@@ -121,6 +121,20 @@ dependencies:
121
121
  - - "~>"
122
122
  - !ruby/object:Gem::Version
123
123
  version: '2.7'
124
+ - !ruby/object:Gem::Dependency
125
+ name: oj
126
+ requirement: !ruby/object:Gem::Requirement
127
+ requirements:
128
+ - - "~>"
129
+ - !ruby/object:Gem::Version
130
+ version: '3.16'
131
+ type: :runtime
132
+ prerelease: false
133
+ version_requirements: !ruby/object:Gem::Requirement
134
+ requirements:
135
+ - - "~>"
136
+ - !ruby/object:Gem::Version
137
+ version: '3.16'
124
138
  - !ruby/object:Gem::Dependency
125
139
  name: webrick
126
140
  requirement: !ruby/object:Gem::Requirement
@@ -235,6 +249,7 @@ files:
235
249
  - lib/tina4/api.rb
236
250
  - lib/tina4/auth.rb
237
251
  - lib/tina4/cli.rb
252
+ - lib/tina4/container.rb
238
253
  - lib/tina4/crud.rb
239
254
  - lib/tina4/database.rb
240
255
  - lib/tina4/database_result.rb