kangaru 0.1.2 → 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 15146a85b29524ce8435963bbc25601017d72cafef5cf69331b920219bad4113
4
- data.tar.gz: de9a21f5cb27508169c1fec64b60f7a2aeacbb0beaac0b3fa1392288ea5f7728
3
+ metadata.gz: db7c4419e9f9d9661c4d12498fcb5450cde2f209958f0bb7249a39dec4a93b54
4
+ data.tar.gz: 43b3237bf249c4c4a3ef59eddbd4328a7b03a0084d9c69296557bab93d0b1492
5
5
  SHA512:
6
- metadata.gz: 03d7d75d0b7c98d7ea7cfa74390fe9bd16ad8d0c02ee7d9e5cc61499b8f545fb90cbf0b8a0361851088b59066f91c0ca24f429747c084d9984ededdd233c5363
7
- data.tar.gz: 9ec21c22c2f17b8943e546060fe872d08f43c38038970abdfdafb867eff1a7d134931069ae03eae832171ab280433bf236ca22635c3fa1c59d0bd76382dfa6c4
6
+ metadata.gz: c2c5dff9c5ecd0a4401261203f6c89d5837b7824dae3e88d8dd1ad7683f7ae9b65200892d81f4d20d181acca253c5b4dab9b48c24dae32c069dd3ddcea8fd5d9
7
+ data.tar.gz: 6b1c7bbef5ef7a08437b5bd33b7fcfa8d2106bd29b52f8df7e56a228caff297fd22df609b96d8a6828390d6bc503bf4105fab52064efb1b4e146866e81a30162
data/.rubocop.yml CHANGED
@@ -73,3 +73,5 @@ RSpec/NestedGroups:
73
73
  Enabled: false
74
74
  RSpec/SharedExamples:
75
75
  Enabled: false
76
+ RSpec/ExampleLength:
77
+ Max: 7
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- kangaru (0.1.2)
4
+ kangaru (0.2.0)
5
5
  colorize (~> 1.1)
6
6
  erb (~> 4.0)
7
7
  sequel (~> 5.72)
@@ -2,8 +2,12 @@ module Kangaru
2
2
  class Application
3
3
  extend Forwardable
4
4
 
5
+ class InvalidConfigError < StandardError; end
6
+
5
7
  attr_reader :paths, :namespace, :database
6
8
 
9
+ attr_accessor :config_path
10
+
7
11
  def initialize(source:, namespace:)
8
12
  @paths = Paths.new(source:)
9
13
  @namespace = namespace
@@ -34,7 +38,9 @@ module Kangaru
34
38
  def apply_config!
35
39
  raise "config already applied" if configured?
36
40
 
37
- config.import_external_config!
41
+ config.import!(config_path) unless config_path.nil?
42
+
43
+ validate_config!
38
44
 
39
45
  @database = setup_database!
40
46
  @configured = true
@@ -46,6 +52,12 @@ module Kangaru
46
52
  router.resolve(request)
47
53
  end
48
54
 
55
+ def const_get(const)
56
+ return unless namespace.const_defined?(const)
57
+
58
+ namespace.const_get(const)
59
+ end
60
+
49
61
  def_delegators :paths, :view_path
50
62
 
51
63
  private
@@ -65,6 +77,14 @@ module Kangaru
65
77
  end
66
78
  end
67
79
 
80
+ def validate_config!
81
+ return if config.valid?
82
+
83
+ message = config.errors.map(&:full_message).join(", ")
84
+
85
+ raise InvalidConfigError, message
86
+ end
87
+
68
88
  def setup_database!
69
89
  return unless config.database.adaptor
70
90
 
@@ -22,6 +22,10 @@ module Kangaru
22
22
  def initialize(**attributes)
23
23
  attributes = self.class.defaults.merge(**attributes)
24
24
 
25
+ merge!(**attributes)
26
+ end
27
+
28
+ def merge!(**attributes)
25
29
  attributes.slice(*self.class.attributes).each do |attr, value|
26
30
  instance_variable_set(:"@#{attr}", value)
27
31
  end
@@ -3,18 +3,19 @@ module Kangaru
3
3
  module Configurable
4
4
  extend Concern
5
5
 
6
- using Patches::Constantise
6
+ using Patches::Inflections
7
7
 
8
8
  class_methods do
9
- def configurator_name
9
+ def configurator_key
10
10
  (name || raise("class name not set"))
11
- .gsub(/^(.*?)::/, "\\1::Configurators::")
12
- .concat("Configurator")
11
+ .gsub(/^.*::/, "")
12
+ .to_snakecase
13
+ .to_sym
13
14
  end
14
15
  end
15
16
 
16
17
  def config
17
- Kangaru.application!.config.for(self.class.configurator_name) ||
18
+ Kangaru.application!.config[self.class.configurator_key] ||
18
19
  raise("inferred configurator not set by application")
19
20
  end
20
21
  end
@@ -1,27 +1,38 @@
1
1
  module Kangaru
2
2
  class Config
3
+ using Patches::Symboliser
4
+
3
5
  attr_reader :configurators
4
6
 
5
7
  def initialize
6
8
  @configurators = set_configurators!
7
9
  end
8
10
 
11
+ def import!(path)
12
+ read_external_config(path).each do |key, config|
13
+ configurators[key]&.merge!(**config)
14
+ end
15
+ end
16
+
9
17
  def serialise
10
18
  configurators.transform_values(&:serialise)
11
19
  end
12
20
 
13
- def import_external_config!
14
- return unless external_config_exists?
21
+ def [](key)
22
+ configurators[key.to_sym]
23
+ end
15
24
 
16
- @external = Configurators::ExternalConfigurator
17
- .from_yaml_file(application.config_path)
25
+ def valid?
26
+ validate
27
+ errors.empty?
18
28
  end
19
29
 
20
- # Returns the configurator instance with the given class name.
21
- def for(configurator_name)
22
- configurators.values.find do |configurator|
23
- configurator.class.name == configurator_name # rubocop:disable Style
24
- end
30
+ def validate
31
+ configurators.each_value(&:validate)
32
+ end
33
+
34
+ def errors
35
+ configurators.values.flat_map(&:errors)
25
36
  end
26
37
 
27
38
  private
@@ -38,8 +49,10 @@ module Kangaru
38
49
  end
39
50
  end
40
51
 
41
- def external_config_exists?
42
- application.config_path && File.exist?(application.config_path)
52
+ def read_external_config(path)
53
+ return {} unless File.exist?(path)
54
+
55
+ YAML.load_file(path)&.symbolise || {}
43
56
  end
44
57
  end
45
58
  end
@@ -0,0 +1,21 @@
1
+ module Kangaru
2
+ class Configurator
3
+ include Concerns::AttributesConcern
4
+ include Concerns::Validatable
5
+
6
+ using Patches::Inflections
7
+
8
+ def self.key
9
+ to_s.gsub(/^.*::(?!.*::)/, "")
10
+ .delete_suffix("Configurator")
11
+ .to_snakecase
12
+ .to_sym
13
+ end
14
+
15
+ def serialise
16
+ self.class.attributes.to_h do |setting|
17
+ [setting, send(setting)]
18
+ end.compact
19
+ end
20
+ end
21
+ end
@@ -1,12 +1,21 @@
1
1
  module Kangaru
2
2
  module Configurators
3
- # These are not set as accessors by Config instances as they are abstract.
4
- BASE_CONFIGURATORS = [Configurator, OpenConfigurator].freeze
5
-
6
3
  def self.classes
7
- constants.map { |constant| const_get(constant) }
8
- .select { |constant| constant.is_a?(Class) }
9
- .reject { |constant| BASE_CONFIGURATORS.include?(constant) }
4
+ load_classes(self) + load_classes(application_configurators)
5
+ end
6
+
7
+ def self.application_configurators
8
+ Kangaru.application&.const_get(:Configurators)
10
9
  end
10
+
11
+ def self.load_classes(root)
12
+ return [] if root.nil?
13
+
14
+ root.constants.map { |const| root.const_get(const) }
15
+ .select { |const| const.is_a?(Class) }
16
+ end
17
+
18
+ private_class_method :application_configurators
19
+ private_class_method :load_classes
11
20
  end
12
21
  end
@@ -12,6 +12,10 @@ module Kangaru
12
12
  Kangaru.application!.configure(env, &)
13
13
  end
14
14
 
15
+ def import_config_from!(path)
16
+ Kangaru.application!.config_path = path
17
+ end
18
+
15
19
  def apply_config!
16
20
  Kangaru.application!.apply_config!
17
21
  end
@@ -1,3 +1,3 @@
1
1
  module Kangaru
2
- VERSION = "0.1.2".freeze
2
+ VERSION = "0.2.0".freeze
3
3
  end
@@ -2,10 +2,16 @@ module Kangaru
2
2
  class Application
3
3
  extend Forwardable
4
4
 
5
+ class InvalidConfigError < StandardError
6
+ end
7
+
5
8
  attr_reader paths: Paths
6
9
  attr_reader namespace: Module
7
- attr_reader config: Config
8
10
  attr_reader database: Database?
11
+
12
+ attr_accessor config_path: String
13
+
14
+ attr_reader config: Config
9
15
  attr_reader router: Router
10
16
 
11
17
  def initialize: (source: String, namespace: Module) -> void
@@ -18,6 +24,9 @@ module Kangaru
18
24
 
19
25
  def run!: (*String) -> void
20
26
 
27
+ def const_get: (String | Symbol) -> Module?
28
+ | (String | Symbol) -> Class?
29
+
21
30
  # Delegated to paths
22
31
  def view_path: (*String, ?ext: Symbol?) -> Pathname
23
32
 
@@ -29,6 +38,8 @@ module Kangaru
29
38
 
30
39
  attr_reader autoloader: Zeitwerk::Loader
31
40
 
41
+ def validate_config!: -> void
42
+
32
43
  def setup_database!: -> Database?
33
44
  end
34
45
  end
@@ -20,6 +20,8 @@ module Kangaru
20
20
  def instance_methods: -> Array[Symbol]
21
21
 
22
22
  def initialize: (**untyped) -> void
23
+
24
+ def merge!: (**untyped) -> void
23
25
  end
24
26
  end
25
27
  end
@@ -5,11 +5,11 @@ module Kangaru
5
5
  extend ClassMethods
6
6
 
7
7
  module ClassMethods
8
- def configurator_name: -> String
8
+ def configurator_key: -> Symbol
9
9
  end
10
10
 
11
11
  def name: -> String
12
- def config: [C < Configurators::Configurator] -> C
12
+ def config: -> untyped
13
13
  end
14
14
  end
15
15
  end
@@ -1,27 +1,29 @@
1
1
  module Kangaru
2
2
  class Config
3
- type configurator = Configurators::Configurator
4
-
5
- attr_reader configurators: Hash[Symbol, configurator]
3
+ attr_reader configurators: Hash[Symbol, Configurator]
6
4
 
7
5
  def initialize: -> void
8
6
 
7
+ def import!: (String) -> void
8
+
9
9
  def serialise: -> Hash[Symbol, Hash[Symbol, untyped]]
10
10
 
11
- def import_external_config!: -> void
11
+ def []: (Symbol) -> Configurator?
12
+
13
+ def valid?: -> bool
14
+
15
+ def validate: -> void
12
16
 
13
- def for: (String) -> untyped
17
+ def errors: -> Array[Validation::Error]
14
18
 
15
- # Configurators
16
- attr_reader application: Configurators::ApplicationConfigurator
17
- attr_reader database: Configurators::DatabaseConfigurator
18
- attr_reader external: Configurators::ExternalConfigurator
19
- attr_reader request: Configurators::RequestConfigurator
19
+ # Native Configurators
20
+ attr_reader database: Configurators::DatabaseConfigurator
21
+ attr_reader request: Configurators::RequestConfigurator
20
22
 
21
23
  private
22
24
 
23
- def set_configurators!: -> Hash[Symbol, configurator]
25
+ def set_configurators!: -> Hash[Symbol, Configurator]
24
26
 
25
- def external_config_exists?: -> bool
27
+ def read_external_config: (String) -> Hash[Symbol, untyped]
26
28
  end
27
29
  end
@@ -0,0 +1,15 @@
1
+ module Kangaru
2
+ class Configurator
3
+ include Concerns::AttributesConcern
4
+ extend Concerns::AttributesConcern::ClassMethods
5
+
6
+ include Concerns::Validatable
7
+ extend Concerns::Validatable::ClassMethods
8
+
9
+ def self.key: -> Symbol
10
+
11
+ def self.name: -> String
12
+
13
+ def serialise: -> Hash[Symbol, untyped]
14
+ end
15
+ end
@@ -1,7 +1,11 @@
1
1
  module Kangaru
2
2
  module Configurators
3
- BASE_CONFIGURATORS: Array[singleton(Configurator)]
4
-
5
3
  def self.classes: -> Array[singleton(Configurator)]
4
+
5
+ private
6
+
7
+ def self.application_configurators: -> Module?
8
+
9
+ def self.load_classes: (Module?) -> Array[singleton(Configurator)]
6
10
  end
7
11
  end
@@ -9,6 +9,8 @@ module Kangaru
9
9
 
10
10
  def apply_config!: -> void
11
11
 
12
+ def import_config_from!: (String) -> void
13
+
12
14
  def database: -> Database?
13
15
  end
14
16
 
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: kangaru
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.2
4
+ version: 0.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Chris Welham
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2023-11-08 00:00:00.000000000 Z
11
+ date: 2023-11-12 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: colorize
@@ -107,12 +107,9 @@ files:
107
107
  - lib/kangaru/concerns/configurable.rb
108
108
  - lib/kangaru/concerns/validatable.rb
109
109
  - lib/kangaru/config.rb
110
+ - lib/kangaru/configurator.rb
110
111
  - lib/kangaru/configurators.rb
111
- - lib/kangaru/configurators/application_configurator.rb
112
- - lib/kangaru/configurators/configurator.rb
113
112
  - lib/kangaru/configurators/database_configurator.rb
114
- - lib/kangaru/configurators/external_configurator.rb
115
- - lib/kangaru/configurators/open_configurator.rb
116
113
  - lib/kangaru/configurators/request_configurator.rb
117
114
  - lib/kangaru/controller.rb
118
115
  - lib/kangaru/database.rb
@@ -159,12 +156,9 @@ files:
159
156
  - sig/kangaru/concerns/configurable.rbs
160
157
  - sig/kangaru/concerns/validatable.rbs
161
158
  - sig/kangaru/config.rbs
159
+ - sig/kangaru/configurator.rbs
162
160
  - sig/kangaru/configurators.rbs
163
- - sig/kangaru/configurators/application_configurator.rbs
164
- - sig/kangaru/configurators/configurator.rbs
165
161
  - sig/kangaru/configurators/database_configurator.rbs
166
- - sig/kangaru/configurators/external_configurator.rbs
167
- - sig/kangaru/configurators/open_configurator.rbs
168
162
  - sig/kangaru/configurators/request_configurator.rbs
169
163
  - sig/kangaru/controller.rbs
170
164
  - sig/kangaru/database.rbs
@@ -1,7 +0,0 @@
1
- module Kangaru
2
- module Configurators
3
- class ApplicationConfigurator < Configurator
4
- attr_accessor :config_path
5
- end
6
- end
7
- end
@@ -1,22 +0,0 @@
1
- module Kangaru
2
- module Configurators
3
- class Configurator
4
- include Concerns::AttributesConcern
5
-
6
- using Patches::Inflections
7
-
8
- def self.key
9
- to_s.gsub(/^.*::(?!.*::)/, "")
10
- .delete_suffix("Configurator")
11
- .to_snakecase
12
- .to_sym
13
- end
14
-
15
- def serialise
16
- self.class.attributes.to_h do |setting|
17
- [setting, send(setting)]
18
- end.compact
19
- end
20
- end
21
- end
22
- end
@@ -1,6 +0,0 @@
1
- module Kangaru
2
- module Configurators
3
- class ExternalConfigurator < OpenConfigurator
4
- end
5
- end
6
- end
@@ -1,33 +0,0 @@
1
- # Similar to a standard configurator, except on initialisation, it will set
2
- # accessors for every attribute specified. This means that the super call will
3
- # lead to each value being set as if the accessor was defined in the class.
4
- module Kangaru
5
- module Configurators
6
- class OpenConfigurator < Configurator
7
- using Patches::Symboliser
8
-
9
- def initialize(**)
10
- set_accessors!(**)
11
-
12
- super
13
- end
14
-
15
- # Import contents of a yaml file
16
- def self.from_yaml_file(path)
17
- raise "path does not exist" unless File.exist?(path)
18
-
19
- attributes = YAML.load_file(path).symbolise
20
-
21
- new(**attributes)
22
- end
23
-
24
- private
25
-
26
- def set_accessors!(**attributes)
27
- attributes.each_key do |key|
28
- self.class.class_eval { attr_accessor key }
29
- end
30
- end
31
- end
32
- end
33
- end
@@ -1,7 +0,0 @@
1
- module Kangaru
2
- module Configurators
3
- class ApplicationConfigurator < Configurator
4
- attr_accessor config_path: String
5
- end
6
- end
7
- end
@@ -1,14 +0,0 @@
1
- module Kangaru
2
- module Configurators
3
- class Configurator
4
- include Concerns::AttributesConcern
5
- extend Concerns::AttributesConcern::ClassMethods
6
-
7
- def self.key: -> Symbol
8
-
9
- def self.name: -> String
10
-
11
- def serialise: -> Hash[Symbol, untyped]
12
- end
13
- end
14
- end
@@ -1,6 +0,0 @@
1
- module Kangaru
2
- module Configurators
3
- class ExternalConfigurator < OpenConfigurator
4
- end
5
- end
6
- end
@@ -1,11 +0,0 @@
1
- module Kangaru
2
- module Configurators
3
- class OpenConfigurator < Configurator
4
- def self.from_yaml_file: (String) -> instance
5
-
6
- private
7
-
8
- def set_accessors!: (**untyped) -> void
9
- end
10
- end
11
- end