fino 1.0.3 → 1.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.
- checksums.yaml +4 -4
- data/README.md +9 -7
- data/lib/fino/cache/memory.rb +46 -7
- data/lib/fino/configuration.rb +5 -1
- data/lib/fino/definition/section.rb +14 -0
- data/lib/fino/definition/setting.rb +46 -0
- data/lib/fino/library.rb +50 -23
- data/lib/fino/metadata.rb +13 -0
- data/lib/fino/pipe/cache.rb +37 -0
- data/lib/fino/{pipeline/adapter.rb → pipe/storage.rb} +3 -1
- data/lib/fino/pipe.rb +23 -0
- data/lib/fino/pipeline.rb +17 -22
- data/lib/fino/registry.rb +41 -11
- data/lib/fino/setting.rb +33 -4
- data/lib/fino/settings/boolean.rb +4 -1
- data/lib/fino/version.rb +2 -1
- data/lib/fino.rb +29 -9
- metadata +10 -18
- data/lib/fino/cache/null.rb +0 -9
- data/lib/fino/engine.rb +0 -5
- data/lib/fino/pipeline/cache.rb +0 -21
- data/lib/fino/redis/adapter.rb +0 -41
- data/lib/fino/redis.rb +0 -9
- data/lib/fino/setting_definition.rb +0 -39
- data/lib/fino/ui/app/controllers/fino/ui/application_controller.rb +0 -4
- data/lib/fino/ui/app/controllers/fino/ui/settings_controller.rb +0 -33
- data/lib/fino/ui/config/initializers/inflections.rb +0 -5
- data/lib/fino/ui/config/routes.rb +0 -7
- data/lib/fino/ui/engine.rb +0 -21
- data/lib/fino/ui.rb +0 -8
- data/lib/fino-redis.rb +0 -3
- data/lib/fino-ui.rb +0 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: a2820a64cf64defc88202ae9e9ee7140efe02246c812e33cfe6ce07877f68b9e
|
4
|
+
data.tar.gz: 6b2b9c1cf4ae0ac28ad60912e0a5026cf01901b3a6006c03ecf1f5550e3f0c80
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 76444316536ac50999142e41abba7dbc4939832a138fb6ad3bf06bf7fb1700b3007f842b874b513789dbeec101ab3c7110818e6f862bd58bd83be06e2cca9251
|
7
|
+
data.tar.gz: 3120460c8c7ee45f2be9f38e00dd12150a81e93d36b8bd7a932c16f73b2061e0d0c7c431d50431244cb2e66b9ee4faa11799d96b120716a1a29f0e5b4b68e8b3
|
data/README.md
CHANGED
@@ -51,24 +51,26 @@ end
|
|
51
51
|
### Work with settings
|
52
52
|
|
53
53
|
```ruby
|
54
|
-
Fino.value(:model, :openai) #=> "gpt-4o"
|
55
|
-
Fino.value(:temperature, :openai) #=> 0.7
|
54
|
+
Fino.value(:model, at: :openai) #=> "gpt-4o"
|
55
|
+
Fino.value(:temperature, at: :openai) #=> 0.7
|
56
56
|
|
57
|
-
Fino.
|
58
|
-
|
57
|
+
Fino.values(:model, :temperature, at: :openai) #=> ["gpt-4", 0.7]
|
58
|
+
|
59
|
+
Fino.set(model: "gpt-5", at: :openai)
|
60
|
+
Fino.value(:model, at: :openai) #=> "gpt-5"
|
59
61
|
```
|
60
62
|
|
61
63
|
### Manage settings via UI
|
62
64
|
|
63
65
|
```ruby
|
64
|
-
gem "fino-
|
66
|
+
gem "fino-rails"
|
65
67
|
```
|
66
68
|
|
67
|
-
Mount Fino
|
69
|
+
Mount Fino Rails engine in your `config/routes.rb`:
|
68
70
|
|
69
71
|
```ruby
|
70
72
|
Rails.application.routes.draw do
|
71
|
-
mount Fino::
|
73
|
+
mount Fino::Rails::Engine, at: "/fino"
|
72
74
|
end
|
73
75
|
```
|
74
76
|
|
data/lib/fino/cache/memory.rb
CHANGED
@@ -5,18 +5,57 @@ class Fino::Cache::Memory
|
|
5
5
|
|
6
6
|
def initialize(expires_in:)
|
7
7
|
@hash = {}
|
8
|
-
@expirator = Fino::Expirator.new(ttl: expires_in)
|
8
|
+
@expirator = Fino::Expirator.new(ttl: expires_in) if expires_in
|
9
9
|
end
|
10
10
|
|
11
|
-
def
|
12
|
-
|
11
|
+
def exist?(key)
|
12
|
+
hash.key?(key)
|
13
13
|
ensure
|
14
|
-
|
15
|
-
|
16
|
-
|
14
|
+
expire_if_needed
|
15
|
+
end
|
16
|
+
|
17
|
+
def read(key)
|
18
|
+
hash[key]
|
19
|
+
ensure
|
20
|
+
expire_if_needed
|
17
21
|
end
|
18
22
|
|
19
23
|
def write(key, value)
|
20
|
-
|
24
|
+
hash[key] = value
|
25
|
+
end
|
26
|
+
|
27
|
+
def fetch(key, &block)
|
28
|
+
hash.fetch(key) do
|
29
|
+
write(key, block.call)
|
30
|
+
end
|
31
|
+
ensure
|
32
|
+
expire_if_needed
|
33
|
+
end
|
34
|
+
|
35
|
+
def fetch_multi(keys, &block)
|
36
|
+
missing_keys = keys - hash.keys
|
37
|
+
|
38
|
+
if missing_keys.any?
|
39
|
+
results = block.call(missing_keys)
|
40
|
+
|
41
|
+
results.each do |key, value|
|
42
|
+
write(key, value)
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
hash.values_at(*keys)
|
47
|
+
ensure
|
48
|
+
expire_if_needed
|
49
|
+
end
|
50
|
+
|
51
|
+
private
|
52
|
+
|
53
|
+
attr_reader :hash, :expirator
|
54
|
+
|
55
|
+
def expire_if_needed
|
56
|
+
expirator&.when_ready do
|
57
|
+
Fino.logger.debug { "Expiring all cache entries" }
|
58
|
+
hash.clear
|
59
|
+
end
|
21
60
|
end
|
22
61
|
end
|
data/lib/fino/configuration.rb
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
class Fino::Configuration
|
4
|
-
attr_reader :registry, :adapter_builder_block, :cache_builder_block
|
4
|
+
attr_reader :registry, :adapter_builder_block, :cache_builder_block, :pipeline_builder_block
|
5
5
|
|
6
6
|
def initialize(registry)
|
7
7
|
@registry = registry
|
@@ -15,6 +15,10 @@ class Fino::Configuration
|
|
15
15
|
@cache_builder_block = block
|
16
16
|
end
|
17
17
|
|
18
|
+
def pipeline(&block)
|
19
|
+
@pipeline_builder_block = block
|
20
|
+
end
|
21
|
+
|
18
22
|
def settings(&)
|
19
23
|
Fino::Registry::DSL.new(registry).instance_eval(&)
|
20
24
|
end
|
@@ -0,0 +1,46 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
class Fino::Definition::Setting
|
4
|
+
attr_reader :setting_name, :section_definition, :type, :options
|
5
|
+
|
6
|
+
def initialize(type:, setting_name:, section_definition: nil, **options)
|
7
|
+
@setting_name = setting_name
|
8
|
+
@section_definition = section_definition
|
9
|
+
@type = type
|
10
|
+
@options = options
|
11
|
+
end
|
12
|
+
|
13
|
+
def type_class # rubocop:disable Metrics/MethodLength
|
14
|
+
@type_class ||=
|
15
|
+
case type
|
16
|
+
when :string
|
17
|
+
Fino::Settings::String
|
18
|
+
when :integer
|
19
|
+
Fino::Settings::Integer
|
20
|
+
when :float
|
21
|
+
Fino::Settings::Float
|
22
|
+
when :boolean
|
23
|
+
Fino::Settings::Boolean
|
24
|
+
else
|
25
|
+
raise "Unknown type #{type}"
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
def default
|
30
|
+
return @default if defined?(@default)
|
31
|
+
|
32
|
+
@default = options[:default]
|
33
|
+
end
|
34
|
+
|
35
|
+
def description
|
36
|
+
options[:description]
|
37
|
+
end
|
38
|
+
|
39
|
+
def path
|
40
|
+
@path ||= [setting_name, section_definition&.name].compact
|
41
|
+
end
|
42
|
+
|
43
|
+
def key
|
44
|
+
@key ||= path.reverse.join("/")
|
45
|
+
end
|
46
|
+
end
|
data/lib/fino/library.rb
CHANGED
@@ -7,49 +7,76 @@ class Fino::Library
|
|
7
7
|
@configuration = configuration
|
8
8
|
end
|
9
9
|
|
10
|
-
def value(
|
11
|
-
setting(
|
10
|
+
def value(setting_name, at: nil)
|
11
|
+
setting(setting_name, at: at).value
|
12
12
|
end
|
13
13
|
|
14
|
-
def
|
15
|
-
|
14
|
+
def values(*setting_names, at: nil)
|
15
|
+
settings(*setting_names, at: at).map(&:value)
|
16
16
|
end
|
17
17
|
|
18
|
-
def
|
19
|
-
pipeline.
|
18
|
+
def setting(setting_name, at: nil)
|
19
|
+
pipeline.read(build_setting_definition(setting_name, at: at))
|
20
20
|
end
|
21
21
|
|
22
|
-
def
|
23
|
-
|
22
|
+
def settings(*setting_names, at: Fino::EMPTINESS)
|
23
|
+
setting_definitions =
|
24
|
+
if setting_names.empty? && at.equal?(Fino::EMPTINESS)
|
25
|
+
configuration.registry.setting_definitions
|
26
|
+
elsif at.equal?(Fino::EMPTINESS)
|
27
|
+
setting_names.map { |name| build_setting_definition(name) }
|
28
|
+
elsif setting_names.empty?
|
29
|
+
configuration.registry.setting_definitions(at: at)
|
30
|
+
else
|
31
|
+
setting_names.map { |name| build_setting_definition(name, at: at) }
|
32
|
+
end
|
24
33
|
|
25
|
-
pipeline.
|
26
|
-
|
27
|
-
|
28
|
-
|
34
|
+
pipeline.read_multi(setting_definitions)
|
35
|
+
end
|
36
|
+
|
37
|
+
def set(**setting_names_to_values)
|
38
|
+
at = setting_names_to_values.delete(:at)
|
39
|
+
|
40
|
+
setting_names_to_values.each do |setting_name, value|
|
41
|
+
setting_definition = build_setting_definition(setting_name, at: at)
|
42
|
+
|
43
|
+
pipeline.write(
|
44
|
+
setting_definition,
|
45
|
+
setting_definition.type_class.deserialize(value)
|
46
|
+
)
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
def slice(**mapping)
|
51
|
+
setting_definitions = mapping.each_with_object([]) do |(section_name, setting_names), memo|
|
52
|
+
Array(setting_names).each do |setting_name|
|
53
|
+
memo << build_setting_definition(setting_name, at: section_name)
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
pipeline.read_multi(setting_definitions)
|
29
58
|
end
|
30
59
|
|
31
60
|
private
|
32
61
|
|
33
62
|
attr_reader :configuration
|
34
63
|
|
35
|
-
def build_setting_definition(
|
36
|
-
configuration.registry.
|
64
|
+
def build_setting_definition(setting_name, at: nil)
|
65
|
+
configuration.registry.setting_definition(setting_name.to_s, at&.to_s)
|
37
66
|
end
|
38
67
|
|
39
68
|
def pipeline
|
40
|
-
@pipeline ||= Fino::Pipeline.new.tap do |p|
|
41
|
-
p.use Fino::
|
42
|
-
p.
|
69
|
+
@pipeline ||= Fino::Pipeline.new(storage).tap do |p|
|
70
|
+
p.use Fino::Pipe::Cache, cache if cache
|
71
|
+
p.instance_exec(&configuration.pipeline_builder_block) if configuration.pipeline_builder_block
|
43
72
|
end
|
44
73
|
end
|
45
74
|
|
46
|
-
def
|
47
|
-
|
48
|
-
|
49
|
-
@cache = configuration.cache_builder_block&.call
|
75
|
+
def storage
|
76
|
+
Fino::Pipe::Storage.new(configuration.adapter_builder_block.call)
|
50
77
|
end
|
51
78
|
|
52
|
-
def
|
53
|
-
@
|
79
|
+
def cache
|
80
|
+
defined?(@cache) ? @cache : @cache = configuration.cache_builder_block&.call
|
54
81
|
end
|
55
82
|
end
|
@@ -0,0 +1,13 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative "./version"
|
4
|
+
|
5
|
+
module Fino
|
6
|
+
module_function
|
7
|
+
|
8
|
+
def metadata(spec)
|
9
|
+
spec.metadata["source_code_uri"] = spec.homepage
|
10
|
+
spec.metadata["bug_tracker_uri"] = "#{spec.homepage}/issues"
|
11
|
+
spec.metadata["rubygems_mfa_required"] = "true"
|
12
|
+
end
|
13
|
+
end
|
@@ -0,0 +1,37 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
class Fino::Pipe::Cache
|
4
|
+
include Fino::Pipe
|
5
|
+
|
6
|
+
def initialize(pipe, cache)
|
7
|
+
super(pipe)
|
8
|
+
@cache = cache
|
9
|
+
end
|
10
|
+
|
11
|
+
def read(setting_definition)
|
12
|
+
cache.fetch(setting_definition.key) do
|
13
|
+
pipe.read(setting_definition)
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
def read_multi(setting_definitions)
|
18
|
+
cache.fetch_multi(setting_definitions.map(&:key)) do |missing_keys|
|
19
|
+
uncached_setting_definitions = setting_definitions.filter { |sd| missing_keys.include?(sd.key) }
|
20
|
+
|
21
|
+
missing_keys.zip(pipe.read_multi(uncached_setting_definitions))
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
def write(setting_definition, value)
|
26
|
+
pipe.write(setting_definition, value)
|
27
|
+
|
28
|
+
cache.write(
|
29
|
+
setting_definition.key,
|
30
|
+
setting_definition.type_class.build(setting_definition, value)
|
31
|
+
)
|
32
|
+
end
|
33
|
+
|
34
|
+
private
|
35
|
+
|
36
|
+
attr_reader :cache
|
37
|
+
end
|
data/lib/fino/pipe.rb
ADDED
@@ -0,0 +1,23 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Fino::Pipe
|
4
|
+
def initialize(pipe)
|
5
|
+
@pipe = pipe
|
6
|
+
end
|
7
|
+
|
8
|
+
def read(setting_definition)
|
9
|
+
raise NotImplementedError
|
10
|
+
end
|
11
|
+
|
12
|
+
def read_multi(setting_definitions)
|
13
|
+
raise NotImplementedError
|
14
|
+
end
|
15
|
+
|
16
|
+
def write(setting_definition, value)
|
17
|
+
raise NotImplementedError
|
18
|
+
end
|
19
|
+
|
20
|
+
private
|
21
|
+
|
22
|
+
attr_reader :pipe
|
23
|
+
end
|
data/lib/fino/pipeline.rb
CHANGED
@@ -1,38 +1,33 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
class Fino::Pipeline
|
4
|
-
|
5
|
-
@pipes = pipes
|
6
|
-
end
|
4
|
+
extend Forwardable
|
7
5
|
|
8
|
-
|
9
|
-
@pipes << pipe
|
10
|
-
end
|
6
|
+
def_delegators :pipeline, *Fino::Pipe.public_instance_methods
|
11
7
|
|
12
|
-
def
|
13
|
-
|
8
|
+
def initialize(storage, pipes = [])
|
9
|
+
@storage = storage
|
10
|
+
@pipes = pipes
|
11
|
+
@pipe_wrapper = ->(pipe) { pipe }
|
14
12
|
end
|
15
13
|
|
16
|
-
def
|
17
|
-
|
18
|
-
|
19
|
-
return settings if settings
|
20
|
-
end
|
14
|
+
def use(pipe_class, *args, **kwargs, &block)
|
15
|
+
pipes << ->(pipe) { pipe_class.new(pipe, *args, **kwargs, &block) }
|
16
|
+
@pipeline = nil
|
21
17
|
end
|
22
18
|
|
23
|
-
def
|
24
|
-
@
|
25
|
-
|
26
|
-
end
|
27
|
-
|
28
|
-
value
|
19
|
+
def wrap(&block)
|
20
|
+
@pipe_wrapper = block
|
21
|
+
@pipeline = nil
|
29
22
|
end
|
30
23
|
|
31
24
|
private
|
32
25
|
|
33
|
-
|
34
|
-
|
35
|
-
|
26
|
+
attr_reader :storage, :pipes, :pipe_wrapper
|
27
|
+
|
28
|
+
def pipeline
|
29
|
+
@pipeline ||= pipes.inject(pipe_wrapper.call(storage)) do |pipe, builder|
|
30
|
+
pipe_wrapper.call(builder.call(pipe))
|
36
31
|
end
|
37
32
|
end
|
38
33
|
end
|
data/lib/fino/registry.rb
CHANGED
@@ -3,17 +3,17 @@
|
|
3
3
|
class Fino::Registry
|
4
4
|
class DSL
|
5
5
|
class SectionDSL
|
6
|
-
def initialize(
|
7
|
-
@
|
6
|
+
def initialize(section_definition, registry)
|
7
|
+
@section_definition = section_definition
|
8
8
|
@registry = registry
|
9
9
|
end
|
10
10
|
|
11
11
|
def setting(setting_name, type, **)
|
12
12
|
@registry.register(
|
13
|
-
Fino::
|
13
|
+
Fino::Definition::Setting.new(
|
14
14
|
type: type,
|
15
15
|
setting_name: setting_name,
|
16
|
-
|
16
|
+
section_definition: @section_definition,
|
17
17
|
**
|
18
18
|
)
|
19
19
|
)
|
@@ -26,7 +26,7 @@ class Fino::Registry
|
|
26
26
|
|
27
27
|
def setting(setting_name, type, **)
|
28
28
|
@registry.register(
|
29
|
-
Fino::
|
29
|
+
Fino::Definition::Setting.new(
|
30
30
|
type: type,
|
31
31
|
setting_name: setting_name,
|
32
32
|
**
|
@@ -35,7 +35,14 @@ class Fino::Registry
|
|
35
35
|
end
|
36
36
|
|
37
37
|
def section(section_name, options = {}, &)
|
38
|
-
|
38
|
+
section_definition = Fino::Definition::Section.new(
|
39
|
+
name: section_name,
|
40
|
+
**options
|
41
|
+
)
|
42
|
+
|
43
|
+
@registry.register_section(section_definition)
|
44
|
+
|
45
|
+
SectionDSL.new(section_definition, @registry).instance_eval(&)
|
39
46
|
end
|
40
47
|
end
|
41
48
|
|
@@ -43,22 +50,45 @@ class Fino::Registry
|
|
43
50
|
|
44
51
|
using Fino::Ext::Hash
|
45
52
|
|
46
|
-
attr_reader :
|
53
|
+
attr_reader :setting_definitions, :section_definitions
|
47
54
|
|
48
55
|
def initialize
|
49
|
-
@setting_definitions_by_path = {}
|
50
56
|
@setting_definitions = []
|
57
|
+
@setting_definitions_by_path = {}
|
58
|
+
|
59
|
+
@section_definitions = []
|
60
|
+
@section_definitions_by_name = {}
|
51
61
|
end
|
52
62
|
|
53
|
-
def
|
54
|
-
@setting_definitions_by_path.dig(*path.reverse).tap do |definition|
|
63
|
+
def setting_definition(*path)
|
64
|
+
@setting_definitions_by_path.dig(*path.compact.reverse).tap do |definition|
|
55
65
|
raise UnknownSetting, "Unknown setting: #{path.compact.join('.')}" unless definition
|
56
66
|
end
|
57
67
|
end
|
58
68
|
|
69
|
+
def setting_definitions(at: Fino::EMPTINESS)
|
70
|
+
case at
|
71
|
+
when Fino::EMPTINESS
|
72
|
+
@setting_definitions
|
73
|
+
when nil
|
74
|
+
@setting_definitions.select { |d| d.section_definition.nil? }
|
75
|
+
else
|
76
|
+
@setting_definitions_by_path[at&.to_s]&.values || []
|
77
|
+
end
|
78
|
+
end
|
79
|
+
|
80
|
+
def section_definition(section_name)
|
81
|
+
@section_definitions_by_name[section_name.to_s]
|
82
|
+
end
|
83
|
+
|
59
84
|
def register(setting_definition)
|
60
85
|
@setting_definitions << setting_definition
|
61
86
|
|
62
|
-
@setting_definitions_by_path.deep_set(setting_definition, *setting_definition.path)
|
87
|
+
@setting_definitions_by_path.deep_set(setting_definition, *setting_definition.path.map(&:to_s))
|
88
|
+
end
|
89
|
+
|
90
|
+
def register_section(section_definition)
|
91
|
+
@section_definitions << section_definition
|
92
|
+
@section_definitions_by_name.deep_set(section_definition, section_definition.name.to_s)
|
63
93
|
end
|
64
94
|
end
|
data/lib/fino/setting.rb
CHANGED
@@ -1,8 +1,6 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
module Fino::Setting
|
4
|
-
UNSET_VALUE = Object.new.freeze
|
5
|
-
|
6
4
|
def self.included(base)
|
7
5
|
base.extend(ClassMethods)
|
8
6
|
end
|
@@ -19,7 +17,7 @@ module Fino::Setting
|
|
19
17
|
def build(setting_definition, raw_value, *options)
|
20
18
|
new(
|
21
19
|
setting_definition,
|
22
|
-
raw_value.equal?(
|
20
|
+
raw_value.equal?(Fino::EMPTINESS) ? setting_definition.options[:default] : deserialize(raw_value),
|
23
21
|
*options
|
24
22
|
)
|
25
23
|
end
|
@@ -38,11 +36,42 @@ module Fino::Setting
|
|
38
36
|
definition.setting_name
|
39
37
|
end
|
40
38
|
|
39
|
+
def key
|
40
|
+
definition.key
|
41
|
+
end
|
42
|
+
|
43
|
+
def type
|
44
|
+
definition.type
|
45
|
+
end
|
46
|
+
|
47
|
+
def type_class
|
48
|
+
definition.type_class
|
49
|
+
end
|
50
|
+
|
51
|
+
def section_definition
|
52
|
+
definition.section_definition
|
53
|
+
end
|
54
|
+
|
41
55
|
def section_name
|
42
|
-
definition.
|
56
|
+
definition.section_definition&.name
|
43
57
|
end
|
44
58
|
|
45
59
|
def default
|
46
60
|
definition.default
|
47
61
|
end
|
62
|
+
|
63
|
+
def description
|
64
|
+
definition.description
|
65
|
+
end
|
66
|
+
|
67
|
+
def inspect
|
68
|
+
attributes = [
|
69
|
+
"key=#{key.inspect}",
|
70
|
+
"type=#{type_class.inspect}",
|
71
|
+
"value=#{value.inspect}",
|
72
|
+
"default=#{default.inspect}"
|
73
|
+
]
|
74
|
+
|
75
|
+
"#<#{self.class.name} #{attributes.join(', ')}>"
|
76
|
+
end
|
48
77
|
end
|
data/lib/fino/version.rb
CHANGED
data/lib/fino.rb
CHANGED
@@ -5,8 +5,8 @@ require "zeitwerk"
|
|
5
5
|
|
6
6
|
module Fino
|
7
7
|
module Configurable
|
8
|
-
def configure(&)
|
9
|
-
configuration.instance_eval(&)
|
8
|
+
def configure(&block)
|
9
|
+
configuration.instance_eval(&block)
|
10
10
|
end
|
11
11
|
|
12
12
|
private
|
@@ -21,8 +21,10 @@ module Fino
|
|
21
21
|
|
22
22
|
def_delegators :library,
|
23
23
|
:value,
|
24
|
+
:values,
|
24
25
|
:setting,
|
25
|
-
:
|
26
|
+
:settings,
|
27
|
+
:slice,
|
26
28
|
:set
|
27
29
|
|
28
30
|
module_function
|
@@ -35,6 +37,8 @@ module Fino
|
|
35
37
|
extend Configurable
|
36
38
|
extend SettingsAccessible
|
37
39
|
|
40
|
+
EMPTINESS = Object.new.freeze
|
41
|
+
|
38
42
|
module_function
|
39
43
|
|
40
44
|
def library
|
@@ -45,6 +49,20 @@ module Fino
|
|
45
49
|
@registry ||= Fino::Registry.new
|
46
50
|
end
|
47
51
|
|
52
|
+
def logger
|
53
|
+
@logger ||= begin
|
54
|
+
require "logger"
|
55
|
+
|
56
|
+
Logger.new($stdout).tap do |l|
|
57
|
+
l.progname = name
|
58
|
+
l.level = ENV.fetch("FINO_LOG_LEVEL", "info")
|
59
|
+
l.formatter = proc do |severity, datetime, progname, msg|
|
60
|
+
"[#{progname}] #{severity}: #{msg}\n"
|
61
|
+
end
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
48
66
|
def root
|
49
67
|
File.expand_path("..", __dir__)
|
50
68
|
end
|
@@ -55,17 +73,19 @@ Zeitwerk::Loader.for_gem.tap do |l|
|
|
55
73
|
|
56
74
|
l.ignore(
|
57
75
|
[
|
58
|
-
|
59
|
-
root_relative_path.call("lib/fino
|
60
|
-
root_relative_path.call("lib/fino/
|
76
|
+
# Fino Rails
|
77
|
+
root_relative_path.call("lib/fino-rails.rb"),
|
78
|
+
root_relative_path.call("lib/fino/rails.rb"),
|
79
|
+
root_relative_path.call("lib/fino/rails/"),
|
61
80
|
|
81
|
+
# Fino Redis
|
62
82
|
root_relative_path.call("lib/fino-redis.rb"),
|
63
83
|
root_relative_path.call("lib/fino/redis.rb"),
|
64
84
|
root_relative_path.call("lib/fino/redis/"),
|
65
85
|
|
66
|
-
|
86
|
+
# Other
|
87
|
+
root_relative_path.call("lib/fino/metadata.rb"),
|
88
|
+
root_relative_path.call("lib/fino/railtie.rb")
|
67
89
|
]
|
68
90
|
)
|
69
91
|
end.setup
|
70
|
-
|
71
|
-
require "fino/engine" if defined?(Rails)
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: fino
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.0
|
4
|
+
version: 1.1.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Egor Iskrenkov
|
@@ -30,44 +30,36 @@ extensions: []
|
|
30
30
|
extra_rdoc_files: []
|
31
31
|
files:
|
32
32
|
- README.md
|
33
|
-
- lib/fino-redis.rb
|
34
|
-
- lib/fino-ui.rb
|
35
33
|
- lib/fino.rb
|
36
34
|
- lib/fino/adapter.rb
|
37
35
|
- lib/fino/cache.rb
|
38
36
|
- lib/fino/cache/memory.rb
|
39
|
-
- lib/fino/cache/null.rb
|
40
37
|
- lib/fino/configuration.rb
|
41
|
-
- lib/fino/
|
38
|
+
- lib/fino/definition/section.rb
|
39
|
+
- lib/fino/definition/setting.rb
|
42
40
|
- lib/fino/error.rb
|
43
41
|
- lib/fino/expirator.rb
|
44
42
|
- lib/fino/ext/hash.rb
|
45
43
|
- lib/fino/library.rb
|
44
|
+
- lib/fino/metadata.rb
|
45
|
+
- lib/fino/pipe.rb
|
46
|
+
- lib/fino/pipe/cache.rb
|
47
|
+
- lib/fino/pipe/storage.rb
|
46
48
|
- lib/fino/pipeline.rb
|
47
|
-
- lib/fino/pipeline/adapter.rb
|
48
|
-
- lib/fino/pipeline/cache.rb
|
49
|
-
- lib/fino/redis.rb
|
50
|
-
- lib/fino/redis/adapter.rb
|
51
49
|
- lib/fino/registry.rb
|
52
50
|
- lib/fino/setting.rb
|
53
|
-
- lib/fino/setting_definition.rb
|
54
51
|
- lib/fino/settings/boolean.rb
|
55
52
|
- lib/fino/settings/float.rb
|
56
53
|
- lib/fino/settings/integer.rb
|
57
54
|
- lib/fino/settings/section.rb
|
58
55
|
- lib/fino/settings/string.rb
|
59
|
-
- lib/fino/ui.rb
|
60
|
-
- lib/fino/ui/app/controllers/fino/ui/application_controller.rb
|
61
|
-
- lib/fino/ui/app/controllers/fino/ui/settings_controller.rb
|
62
|
-
- lib/fino/ui/config/initializers/inflections.rb
|
63
|
-
- lib/fino/ui/config/routes.rb
|
64
|
-
- lib/fino/ui/engine.rb
|
65
56
|
- lib/fino/version.rb
|
66
57
|
homepage: https://github.com/eiskrenkov/fino
|
67
|
-
licenses:
|
58
|
+
licenses:
|
59
|
+
- MIT
|
68
60
|
metadata:
|
69
|
-
homepage_uri: https://github.com/eiskrenkov/fino
|
70
61
|
source_code_uri: https://github.com/eiskrenkov/fino
|
62
|
+
bug_tracker_uri: https://github.com/eiskrenkov/fino/issues
|
71
63
|
rubygems_mfa_required: 'true'
|
72
64
|
rdoc_options: []
|
73
65
|
require_paths:
|
data/lib/fino/cache/null.rb
DELETED
data/lib/fino/engine.rb
DELETED
data/lib/fino/pipeline/cache.rb
DELETED
@@ -1,21 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
class Fino::Pipeline::Cache
|
4
|
-
def initialize(cache)
|
5
|
-
@cache = cache
|
6
|
-
end
|
7
|
-
|
8
|
-
def read(setting_definition, &)
|
9
|
-
cache.fetch(setting_definition.key, &)
|
10
|
-
end
|
11
|
-
|
12
|
-
def read_multi(setting_definitions, &); end
|
13
|
-
|
14
|
-
def write(setting_definition, value)
|
15
|
-
cache.write(setting_definition.key, setting_definition.type_class.build(setting_definition, value))
|
16
|
-
end
|
17
|
-
|
18
|
-
private
|
19
|
-
|
20
|
-
attr_reader :cache
|
21
|
-
end
|
data/lib/fino/redis/adapter.rb
DELETED
@@ -1,41 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
class Fino::Redis::Adapter
|
4
|
-
include Fino::Adapter
|
5
|
-
|
6
|
-
DEFAULT_REDIS_NAMESPACE = "fino"
|
7
|
-
VALUE_KEY = "v"
|
8
|
-
|
9
|
-
def initialize(redis, namespace: DEFAULT_REDIS_NAMESPACE)
|
10
|
-
@redis = redis
|
11
|
-
@redis_namespace = namespace
|
12
|
-
end
|
13
|
-
|
14
|
-
def read(setting_definition)
|
15
|
-
redis.hgetall(redis_key_for(setting_definition))
|
16
|
-
end
|
17
|
-
|
18
|
-
def write(setting_definition, value)
|
19
|
-
redis.hset(redis_key_for(setting_definition), VALUE_KEY, setting_definition.type_class.serialize(value))
|
20
|
-
end
|
21
|
-
|
22
|
-
def read_multi(setting_definitions)
|
23
|
-
keys = setting_definitions.map { |definition| redis_key_for(definition) }
|
24
|
-
|
25
|
-
redis.pipelined do |pipeline|
|
26
|
-
keys.each { |key| pipeline.hgetall(key) }
|
27
|
-
end
|
28
|
-
end
|
29
|
-
|
30
|
-
def fetch_value_from(raw_adapter_data)
|
31
|
-
raw_adapter_data.key?(VALUE_KEY) ? raw_adapter_data.delete(VALUE_KEY) : Fino::Setting::UNSET_VALUE
|
32
|
-
end
|
33
|
-
|
34
|
-
private
|
35
|
-
|
36
|
-
attr_reader :redis, :redis_namespace
|
37
|
-
|
38
|
-
def redis_key_for(setting_definition)
|
39
|
-
"#{redis_namespace}:#{setting_definition.path.join(':')}"
|
40
|
-
end
|
41
|
-
end
|
data/lib/fino/redis.rb
DELETED
@@ -1,39 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
class Fino::SettingDefinition
|
4
|
-
attr_reader :setting_name, :section_name, :type, :options
|
5
|
-
|
6
|
-
def initialize(type:, setting_name:, section_name: nil, **options)
|
7
|
-
@setting_name = setting_name
|
8
|
-
@section_name = section_name
|
9
|
-
@type = type
|
10
|
-
@options = options
|
11
|
-
end
|
12
|
-
|
13
|
-
def type_class
|
14
|
-
case type
|
15
|
-
when :string
|
16
|
-
Fino::Settings::String
|
17
|
-
when :integer
|
18
|
-
Fino::Settings::Integer
|
19
|
-
when :float
|
20
|
-
Fino::Settings::Float
|
21
|
-
when :boolean
|
22
|
-
Fino::Settings::Boolean
|
23
|
-
else
|
24
|
-
raise "Unknown type #{type}"
|
25
|
-
end
|
26
|
-
end
|
27
|
-
|
28
|
-
def default
|
29
|
-
options[:default]
|
30
|
-
end
|
31
|
-
|
32
|
-
def path
|
33
|
-
@path ||= [setting_name, section_name].compact
|
34
|
-
end
|
35
|
-
|
36
|
-
def key
|
37
|
-
path.join("_")
|
38
|
-
end
|
39
|
-
end
|
@@ -1,33 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
class Fino::UI::SettingsController < Fino::UI::ApplicationController
|
4
|
-
def index
|
5
|
-
@settings = Fino.library.all
|
6
|
-
end
|
7
|
-
|
8
|
-
def edit
|
9
|
-
setting_path = parse_setting_path(params[:key])
|
10
|
-
|
11
|
-
@setting = Fino.setting(*setting_path)
|
12
|
-
end
|
13
|
-
|
14
|
-
def update
|
15
|
-
begin
|
16
|
-
# Parse the key to create the setting path
|
17
|
-
setting_path = parse_setting_path(params[:key])
|
18
|
-
|
19
|
-
# Update the setting using the correct API
|
20
|
-
Fino.set(params[:value], *setting_path)
|
21
|
-
|
22
|
-
redirect_to root_path, notice: "Setting updated successfully"
|
23
|
-
rescue Fino::Registry::UnknownSetting
|
24
|
-
redirect_to root_path, alert: "Setting not found"
|
25
|
-
end
|
26
|
-
end
|
27
|
-
|
28
|
-
private
|
29
|
-
|
30
|
-
def parse_setting_path(key)
|
31
|
-
key.split('.').map(&:to_sym).reverse
|
32
|
-
end
|
33
|
-
end
|
data/lib/fino/ui/engine.rb
DELETED
@@ -1,21 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
require "fino-ui"
|
4
|
-
|
5
|
-
class Fino::UI::Engine < Rails::Engine
|
6
|
-
isolate_namespace Fino::UI
|
7
|
-
|
8
|
-
paths["app"] << root.join("lib", "fino", "ui", "app")
|
9
|
-
paths["config/initializers"] << root.join("lib", "fino", "ui", "config", "initializers")
|
10
|
-
|
11
|
-
initializer "fino.ui.append_view_paths" do |_app|
|
12
|
-
ActiveSupport.on_load :action_controller do
|
13
|
-
prepend_view_path Fino::UI::Engine.root.join("lib", "fino", "ui", "app", "views")
|
14
|
-
end
|
15
|
-
end
|
16
|
-
|
17
|
-
initializer "fino.ui.load_routes", before: :add_routing_paths do |app|
|
18
|
-
custom_routes = root.join("lib", "fino", "ui", "config", "routes.rb")
|
19
|
-
app.routes_reloader.paths << custom_routes.to_s
|
20
|
-
end
|
21
|
-
end
|
data/lib/fino/ui.rb
DELETED
data/lib/fino-redis.rb
DELETED
data/lib/fino-ui.rb
DELETED