smart_schema 0.12.1 → 0.12.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.
Files changed (82) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +12 -0
  3. data/.rspec +3 -0
  4. data/.rubocop.yml +20 -0
  5. data/CHANGELOG.md +106 -0
  6. data/CODE_OF_CONDUCT.md +74 -0
  7. data/Gemfile +5 -0
  8. data/Gemfile.lock +266 -0
  9. data/LICENSE.txt +21 -0
  10. data/README.md +305 -0
  11. data/Rakefile +21 -0
  12. data/bin/console +8 -0
  13. data/bin/setup +8 -0
  14. data/lib/smart_core/schema/checker/reconciler/constructor.rb +60 -0
  15. data/lib/smart_core/schema/checker/reconciler/matcher/options.rb +33 -0
  16. data/lib/smart_core/schema/checker/reconciler/matcher/result.rb +87 -0
  17. data/lib/smart_core/schema/checker/reconciler/matcher/result_finalizer.rb +186 -0
  18. data/lib/smart_core/schema/checker/reconciler/matcher.rb +62 -0
  19. data/lib/smart_core/schema/checker/reconciler.rb +106 -0
  20. data/lib/smart_core/schema/checker/rules/base.rb +110 -0
  21. data/lib/smart_core/schema/checker/rules/extra_keys/failure.rb +24 -0
  22. data/lib/smart_core/schema/checker/rules/extra_keys/result.rb +37 -0
  23. data/lib/smart_core/schema/checker/rules/extra_keys/success.rb +30 -0
  24. data/lib/smart_core/schema/checker/rules/extra_keys.rb +31 -0
  25. data/lib/smart_core/schema/checker/rules/optional.rb +27 -0
  26. data/lib/smart_core/schema/checker/rules/options/empty.rb +43 -0
  27. data/lib/smart_core/schema/checker/rules/options/filled.rb +49 -0
  28. data/lib/smart_core/schema/checker/rules/options/type.rb +88 -0
  29. data/lib/smart_core/schema/checker/rules/options.rb +60 -0
  30. data/lib/smart_core/schema/checker/rules/required.rb +27 -0
  31. data/lib/smart_core/schema/checker/rules/requirement/optional.rb +36 -0
  32. data/lib/smart_core/schema/checker/rules/requirement/required.rb +36 -0
  33. data/lib/smart_core/schema/checker/rules/requirement/result.rb +95 -0
  34. data/lib/smart_core/schema/checker/rules/requirement.rb +9 -0
  35. data/lib/smart_core/schema/checker/rules/result/base.rb +44 -0
  36. data/lib/smart_core/schema/checker/rules/result/failure.rb +41 -0
  37. data/lib/smart_core/schema/checker/rules/result/success.rb +15 -0
  38. data/lib/smart_core/schema/checker/rules/result.rb +9 -0
  39. data/lib/smart_core/schema/checker/rules/type_aliases.rb +57 -0
  40. data/lib/smart_core/schema/checker/rules/verifier/result.rb +75 -0
  41. data/lib/smart_core/schema/checker/rules/verifier.rb +74 -0
  42. data/lib/smart_core/schema/checker/rules.rb +89 -0
  43. data/lib/smart_core/schema/checker/verifiable_hash.rb +65 -0
  44. data/lib/smart_core/schema/checker.rb +106 -0
  45. data/lib/smart_core/schema/configuration.rb +33 -0
  46. data/lib/smart_core/schema/dsl.rb +81 -0
  47. data/lib/smart_core/schema/errors.rb +65 -0
  48. data/lib/smart_core/schema/key_control.rb +39 -0
  49. data/lib/smart_core/schema/plugins/abstract.rb +55 -0
  50. data/lib/smart_core/schema/plugins/access_mixin.rb +47 -0
  51. data/lib/smart_core/schema/plugins/dry_types/dry_types/abstract_factory.rb +99 -0
  52. data/lib/smart_core/schema/plugins/dry_types/dry_types/operation/base.rb +9 -0
  53. data/lib/smart_core/schema/plugins/dry_types/dry_types/operation/cast.rb +21 -0
  54. data/lib/smart_core/schema/plugins/dry_types/dry_types/operation/valid.rb +16 -0
  55. data/lib/smart_core/schema/plugins/dry_types/dry_types/operation/validate.rb +19 -0
  56. data/lib/smart_core/schema/plugins/dry_types/dry_types/operation.rb +12 -0
  57. data/lib/smart_core/schema/plugins/dry_types/dry_types.rb +10 -0
  58. data/lib/smart_core/schema/plugins/dry_types/errors.rb +13 -0
  59. data/lib/smart_core/schema/plugins/dry_types.rb +27 -0
  60. data/lib/smart_core/schema/plugins/registry.rb +158 -0
  61. data/lib/smart_core/schema/plugins/registry_interface.rb +63 -0
  62. data/lib/smart_core/schema/plugins.rb +17 -0
  63. data/lib/smart_core/schema/result.rb +62 -0
  64. data/lib/smart_core/schema/type_system/interop/abstract_factory.rb +92 -0
  65. data/lib/smart_core/schema/type_system/interop/aliasing/alias_list.rb +131 -0
  66. data/lib/smart_core/schema/type_system/interop/aliasing.rb +72 -0
  67. data/lib/smart_core/schema/type_system/interop/operation.rb +30 -0
  68. data/lib/smart_core/schema/type_system/interop.rb +128 -0
  69. data/lib/smart_core/schema/type_system/registry.rb +162 -0
  70. data/lib/smart_core/schema/type_system/registry_interface.rb +87 -0
  71. data/lib/smart_core/schema/type_system/smart_types/abstract_factory.rb +99 -0
  72. data/lib/smart_core/schema/type_system/smart_types/operation/base.rb +8 -0
  73. data/lib/smart_core/schema/type_system/smart_types/operation/cast.rb +16 -0
  74. data/lib/smart_core/schema/type_system/smart_types/operation/valid.rb +16 -0
  75. data/lib/smart_core/schema/type_system/smart_types/operation/validate.rb +16 -0
  76. data/lib/smart_core/schema/type_system/smart_types/operation.rb +13 -0
  77. data/lib/smart_core/schema/type_system/smart_types.rb +48 -0
  78. data/lib/smart_core/schema/type_system.rb +16 -0
  79. data/lib/smart_core/schema/version.rb +14 -0
  80. data/lib/smart_core/schema.rb +67 -0
  81. data/smart_schema.gemspec +46 -0
  82. metadata +83 -3
@@ -0,0 +1,74 @@
1
+ # frozen_string_literal: true
2
+
3
+ # @api private
4
+ # @since 0.1.0
5
+ # @version 0.3.0
6
+ module SmartCore::Schema::Checker::Rules::Verifier
7
+ require_relative 'verifier/result'
8
+
9
+ class << self
10
+ # @param rule [SmartCore::Schema::Checker::Rules::Base]
11
+ # @param matcher_options [SmartCore::Schema::Checker::Reconciler::Matcher::Options]
12
+ # @param verifiable_hash [SmartCore::Schema::Checker::VerifiableHash]
13
+ # @return [SmartCore::Schema::Checker::Rules::Verifier::Result]
14
+ #
15
+ # @api private
16
+ # @since 0.1.0
17
+ # @version 0.3.0
18
+ def verify!(rule, matcher_options, verifiable_hash)
19
+ SmartCore::Schema::Checker::Rules::Verifier::Result.new(rule).tap do |result|
20
+ requirement = result << check_requirement(rule, verifiable_hash)
21
+ next result if requirement.required? && requirement.failure?
22
+ next result if requirement.optional? && requirement.success? && !requirement.key_exists?
23
+ result << check_type(rule, verifiable_hash)
24
+ filled = result << check_filled(rule, verifiable_hash)
25
+ result << check_nested(rule, verifiable_hash) if filled.success?
26
+ end
27
+ end
28
+
29
+ private
30
+
31
+ # @param rule [SmartCore::Schema::Checker::Rules::Base]
32
+ # @param verifiable_hash [SmartCore::Schema::Checker::VerifiableHash]
33
+ # @return [SmartCore::Schema::Checker::Rules::Requirement::Result]
34
+ #
35
+ # @api private
36
+ # @since 0.1.0
37
+ def check_requirement(rule, verifiable_hash)
38
+ rule.requirement.validate(verifiable_hash)
39
+ end
40
+
41
+ # @param rule [SmartCore::Schema::Checker::Rules::Base]
42
+ # @param verifiable_hash [SmartCore::Schema::Checker::VerifiableHash]
43
+ # @return [SmartCore::Schema::Checker::Rules::Result::Success]
44
+ # @return [SmartCore::Schema::Checker::Rules::Result::Failure]
45
+ #
46
+ # @api private
47
+ # @since 0.1.0
48
+ def check_type(rule, verifiable_hash)
49
+ rule.options.type.validate(verifiable_hash)
50
+ end
51
+
52
+ # @param rule [SmartCore::Schema::Checker::Rules::Base]
53
+ # @param verifiable_hash [SmartCore::Schema::Checker::VerifiableHash]
54
+ # @return [SmartCore::Schema::Checker::Rules::Result::Success]
55
+ # @return [SmartCore::Schema::Checker::Rules::Result::Failure]
56
+ #
57
+ # @api private
58
+ # @since 0.1.0
59
+ def check_filled(rule, verifiable_hash)
60
+ rule.options.filled.validate(verifiable_hash)
61
+ end
62
+
63
+ # @param rule [SmartCore::Schema::Checker::Rules::Base]
64
+ # @param verifiable_hash [SmartCore::Schema::Checker::VerifiableHash]
65
+ # @return [NilClass, SmartCore::Schema::Checker::Reconciler::Matcher::Result]
66
+ #
67
+ # @api private
68
+ # @since 0.1.0
69
+ def check_nested(rule, verifiable_hash)
70
+ return unless rule.nested_reconciler
71
+ rule.nested_reconciler.__match!(verifiable_hash.extract(rule.schema_key))
72
+ end
73
+ end
74
+ end
@@ -0,0 +1,89 @@
1
+ # frozen_string_literal: true
2
+
3
+ # @api private
4
+ # @since 0.1.0
5
+ # @version 0.8.0
6
+ class SmartCore::Schema::Checker::Rules
7
+ require_relative 'rules/type_aliases'
8
+ require_relative 'rules/base'
9
+ require_relative 'rules/result'
10
+ require_relative 'rules/optional'
11
+ require_relative 'rules/required'
12
+ require_relative 'rules/extra_keys'
13
+ require_relative 'rules/options'
14
+ require_relative 'rules/requirement'
15
+ require_relative 'rules/verifier'
16
+
17
+ # @since 0.1.0
18
+ include Enumerable
19
+
20
+ # @return [void]
21
+ #
22
+ # @api private
23
+ # @since 0.1.0
24
+ # @version 0.8.0
25
+ def initialize
26
+ @rules = {}
27
+ @cache = SmartCore::Engine::Cache.new
28
+ end
29
+
30
+ # @param schema_key [String]
31
+ # @param rule [SmartCore::Schema::Checker::Rules::Base]
32
+ # @return [SmartCore::Schema::Checker::Rules::Base]
33
+ #
34
+ # @api private
35
+ # @since 0.1.0
36
+ # @version 0.8..0
37
+ def []=(schema_key, rule)
38
+ cache.clear
39
+ rules[schema_key] = rule
40
+ end
41
+
42
+ # @param block [Block]
43
+ # @yield [schema_key, rule]
44
+ # @yieldparam schema_key [String]
45
+ # @yieldparam rule [SmartCore::Schema::Checker::Rules::Base]
46
+ # @return [Enumerable]
47
+ #
48
+ # @api private
49
+ # @since 0.1.0
50
+ # @version 0.8.0
51
+ def each(&block)
52
+ block_given? ? rules.each_pair(&block) : rules.each_pair
53
+ end
54
+
55
+ # @param block [Block]
56
+ # @yield [rule]
57
+ # @yieldparam rule [SmartCore::Schema::Checker::Rules::Base]
58
+ # @return [Enumerable]
59
+ #
60
+ # @api private
61
+ # @since 0.1.0
62
+ # @version 0.8.0
63
+ def each_rule(&block)
64
+ block_given? ? rules.each_value(&block) : rules.each_value
65
+ end
66
+
67
+ # @return [Array<String>]
68
+ #
69
+ # @api private
70
+ # @since 0.1.0
71
+ # @version 0.8.0
72
+ def keys
73
+ cache.read(:keys) { rules.keys }
74
+ end
75
+
76
+ private
77
+
78
+ # @return [Hash<String,SmartCore::Schema::Checker::Rules::Base>]
79
+ #
80
+ # @api private
81
+ # @since 0.1.0
82
+ attr_reader :rules
83
+
84
+ # @return [SmartCore::Engine::Cache]
85
+ #
86
+ # @api private
87
+ # @since 0.8.0
88
+ attr_reader :cache
89
+ end
@@ -0,0 +1,65 @@
1
+ # frozen_string_literal: true
2
+
3
+ # @api private
4
+ # @since 0.1.0
5
+ # @version 0.8.0
6
+ class SmartCore::Schema::Checker::VerifiableHash
7
+ # @return [Hash<String|Symbol,Any>]
8
+ #
9
+ # @api private
10
+ # @since 0.1.0
11
+ attr_reader :source
12
+
13
+ # @param source [Hash<String|Symbol,Any>]
14
+ # @return [void]
15
+ #
16
+ # @api private
17
+ # @since 0.1.0
18
+ def initialize(source)
19
+ @source = source
20
+ end
21
+
22
+ # @param key [String]
23
+ # @return [SmartCore::Schema::Checker::VerifiableHash]
24
+ #
25
+ # @api private
26
+ # @since 0.8.0
27
+ def extract(key)
28
+ SmartCore::Schema::Checker::VerifiableHash.new(fetch(key))
29
+ end
30
+
31
+ # @return [Array<String>]
32
+ #
33
+ # @api private
34
+ # @since 0.1.0
35
+ # @version 0.8.0
36
+ def keys
37
+ SmartCore::Schema::KeyControl.normalize_list(source.keys)
38
+ end
39
+
40
+ # @param key [String]
41
+ # @return [Boolean]
42
+ #
43
+ # @api private
44
+ # @since 0.1.0
45
+ # @version 0.8.0
46
+ def key?(key)
47
+ source.key?(key) || source.key?(key.to_sym)
48
+ end
49
+
50
+ # @param key [String]
51
+ # @return [Any]
52
+ #
53
+ # @api private
54
+ # @since 0.1.0
55
+ # @version 0.8.0
56
+ def fetch(key)
57
+ # @note
58
+ # Previously we used exceptional flow "hash.fetch(key) rescue hash.fetch(key.to_sym)".
59
+ # This flow can generate a lot of useless objects during rescuable `KeyError` exception
60
+ # (useless error messages, backtraces, etc, object that was silently suppressed).
61
+ # So, the "if"-#key?-oriented flow is better (generates fewer number of objects statistically)
62
+ source.key?(key) ? source.fetch(key) : source.fetch(key.to_sym)
63
+ end
64
+ alias_method :[], :fetch
65
+ end
@@ -0,0 +1,106 @@
1
+ # frozen_string_literal: true
2
+
3
+ # @api private
4
+ # @since 0.1.0
5
+ # @version 0.9.0
6
+ class SmartCore::Schema::Checker
7
+ require_relative 'checker/verifiable_hash'
8
+ require_relative 'checker/rules'
9
+ require_relative 'checker/reconciler'
10
+
11
+ # @return [void]
12
+ #
13
+ # @api private
14
+ # @since 0.1.0
15
+ # @version 0.9.0
16
+ def initialize
17
+ @reconciler = Reconciler::Constructor.create
18
+ @lock = SmartCore::Engine::ReadWriteLock.new
19
+ end
20
+
21
+ # @param verifiable_hash [Hash<String|Symbol,Any>]
22
+ # @return [SmartCore::Schema::Result]
23
+ #
24
+ # @api private
25
+ # @since 0.1.0
26
+ # @version 0.9.0
27
+ def check!(verifiable_hash)
28
+ @lock.read_sync do
29
+ raise(SmartCore::Schema::ArgumentError, <<~ERROR_MESSAGE) unless verifiable_hash.is_a?(Hash)
30
+ Verifiable hash should be a type of ::Hash
31
+ ERROR_MESSAGE
32
+
33
+ reconciler.__match!(VerifiableHash.new(verifiable_hash)).complete!
34
+ end
35
+ end
36
+
37
+ # @param checker_invokations [Block]
38
+ # @return [void]
39
+ #
40
+ # @api private
41
+ # @since 0.3.0
42
+ # @version 0.9.0
43
+ def invoke_in_pipe(&checker_invokations)
44
+ @lock.write_sync { instance_eval(&checker_invokations) }
45
+ end
46
+
47
+ # @param strict_mode [NilClass, String, Symbol]
48
+ # @return [void]
49
+ #
50
+ # @api private
51
+ # @since 0.3.0
52
+ # @version 0.9.0
53
+ def set_strict_mode(strict_mode)
54
+ @lock.write_sync { apply_strict_mode(strict_mode) }
55
+ end
56
+
57
+ # @param definitions [Block]
58
+ # @return [void]
59
+ #
60
+ # @api private
61
+ # @since 0.1.0
62
+ # @version 0.9.0
63
+ def append_schema_definitions(&definitions)
64
+ @lock.write_sync { add_schema_definitions(&definitions) }
65
+ end
66
+
67
+ # @param another_checker [SmartCore::Schema::Checker]
68
+ # @return [SmartCore::Schema::Checker]
69
+ #
70
+ # @api private
71
+ # @since 0.1.0
72
+ # @version 0.9.0
73
+ def combine_with(another_checker)
74
+ @lock.write_sync { self } # TODO (0.x.0): merge the definitions and return self
75
+ end
76
+
77
+ private
78
+
79
+ # @return [SmartCore::Schema::Checker::Reconciler]
80
+ #
81
+ # @api private
82
+ # @since 0.1.0
83
+ attr_reader :reconciler
84
+
85
+ # @param definitions [Block]
86
+ # @return [void]
87
+ #
88
+ # @api private
89
+ # @since 0.1.0
90
+ def add_schema_definitions(&definitions)
91
+ raise(SmartCore::Schema::ArgumentError, <<~ERROR_MESSAGE) unless block_given?
92
+ Schema definitions is not provided (you should provide Block argument)
93
+ ERROR_MESSAGE
94
+
95
+ Reconciler::Constructor.append_definitions(reconciler, &definitions)
96
+ end
97
+
98
+ # @param strict_mode [NilClass, String, Symbol]
99
+ # @return [void]
100
+ #
101
+ # @api private
102
+ # @since 0.3.0
103
+ def apply_strict_mode(strict_mode)
104
+ Reconciler::Constructor.set_strict_mode(reconciler, strict_mode)
105
+ end
106
+ end
@@ -0,0 +1,33 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'qonfig'
4
+
5
+ # @api public
6
+ # @since 0.12.0
7
+ module SmartCore::Schema::Configuration
8
+ # @since 0.12.0
9
+ include Qonfig::Configurable
10
+
11
+ # @api public
12
+ # @since 0.12.0
13
+ extend SmartCore::Schema::Plugins::AccessMixin
14
+
15
+ class << self
16
+ # @param setting_key [String, Symbol]
17
+ # @return [Qonfig::Settings, Any]
18
+ #
19
+ # @api private
20
+ # @since 0.12.0
21
+ def [](setting_key)
22
+ config[setting_key]
23
+ end
24
+ end
25
+
26
+ # @since 0.12.0
27
+ configuration do
28
+ setting :type_system, :smart_types
29
+ validate :default_type_system do |value|
30
+ SmartCore::Schema::TypeSystem.resolve(value) rescue false
31
+ end
32
+ end
33
+ end
@@ -0,0 +1,81 @@
1
+ # frozen_string_literal: true
2
+
3
+ # @api private
4
+ # @since 0.1.0
5
+ module SmartCore::Schema::DSL
6
+ class << self
7
+ # @param base_klass [Class]
8
+ # @return [void]
9
+ #
10
+ # @api private
11
+ # @since 0.1.0
12
+ def included(base_klass)
13
+ base_klass.instance_variable_set(:@__schema_checker__, SmartCore::Schema::Checker.new)
14
+ base_klass.extend(ClassMethods)
15
+ base_klass.singleton_class.prepend(ClassInheritance)
16
+ end
17
+ end
18
+
19
+ # @api private
20
+ # @since 0.1.0
21
+ module ClassInheritance
22
+ # @param child_klass [Class]
23
+ # @return [void]
24
+ #
25
+ # @api private
26
+ # @since 0.1.0
27
+ def inherited(child_klass)
28
+ child_klass.instance_variable_set(
29
+ :@__schema_checker__,
30
+ SmartCore::Schema::Checker.new.combine_with(__schema_checker__)
31
+ )
32
+ child_klass.singleton_class.prepend(ClassInheritance)
33
+ super
34
+ end
35
+ end
36
+
37
+ # @api private
38
+ # @since 0.1.0
39
+ # @version 0.3.0
40
+ module ClassMethods
41
+ # @return [SmartCore::Schema::Checker]
42
+ #
43
+ # @api private
44
+ # @since 0.1.0
45
+ def __schema_checker__
46
+ @__schema_checker__
47
+ end
48
+
49
+ # @param strict_mode [NilClass, String, Symbol]
50
+ # @param definitions [Block]
51
+ # @return [void]
52
+ #
53
+ # @note nil strict mode means `do not change current mode`
54
+ #
55
+ # @api public
56
+ # @since 0.1.0
57
+ # @version 0.3.0
58
+ def schema(strict_mode = nil, &definitions)
59
+ __schema_checker__.invoke_in_pipe do
60
+ set_strict_mode(strict_mode)
61
+ append_schema_definitions(&definitions)
62
+ end
63
+ end
64
+
65
+ # @return [void]
66
+ #
67
+ # @api public
68
+ # @since 0.3.0
69
+ def strict!
70
+ __schema_checker__.set_strict_mode(:strict)
71
+ end
72
+
73
+ # @return [void]
74
+ #
75
+ # @api public
76
+ # @since 0.3.0
77
+ def non_strict!
78
+ __schema_checker__.set_strict_mode(:non_strict)
79
+ end
80
+ end
81
+ end
@@ -0,0 +1,65 @@
1
+ # frozen_string_literal: true
2
+
3
+ # rubocop:disable Style/StaticClass
4
+ class SmartCore::Schema
5
+ # @api public
6
+ # @since 0.1.0
7
+ Error = Class.new(SmartCore::Error)
8
+
9
+ # @api public
10
+ # @since 0.1.0
11
+ ArgumentError = Class.new(SmartCore::ArgumentError)
12
+
13
+ # @api public
14
+ # @since 0.12.0
15
+ NoTypeAliasError = Class.new(Error)
16
+
17
+ # @api public
18
+ # @since 0.12.0
19
+ PluginError = Class.new(Error)
20
+
21
+ # @api public
22
+ # @since 0.12.0
23
+ UnresolvedPluginDependencyError = Class.new(PluginError)
24
+
25
+ # @api public
26
+ # @since 0.12.0
27
+ AlreadyRegisteredPluginError = Class.new(PluginError)
28
+
29
+ # @api public
30
+ # @since 0.12.0
31
+ UnregisteredPluginError = Class.new(PluginError)
32
+
33
+ # @api public
34
+ # @since 0.12.0
35
+ TypeSystemError = Class.new(Error)
36
+
37
+ # @api public
38
+ # @since 0.5.1
39
+ IncorrectTypeError = Class.new(TypeSystemError)
40
+
41
+ # @api public
42
+ # @since 0.12.0
43
+ TypeAliasNotFoundError = Class.new(TypeSystemError)
44
+
45
+ # @api public
46
+ # @since 0.12.0
47
+ IncorrectTypeSystemInteropError = Class.new(TypeSystemError)
48
+
49
+ # @api public
50
+ # @since 0.12.0
51
+ IncorrectTypeObjectError = Class.new(TypeSystemError)
52
+
53
+ # @api public
54
+ # @since 0.12.0
55
+ UnsupportedTypeSystemError = Class.new(TypeSystemError)
56
+
57
+ # @api public
58
+ # @since 0.12.0
59
+ UnsupportedTypeOperationError = Class.new(TypeSystemError)
60
+
61
+ # @api public
62
+ # @since 0.12.0
63
+ TypeCastingUnsupportedError = Class.new(UnsupportedTypeOperationError)
64
+ end
65
+ # rubocop:enable Style/StaticClass
@@ -0,0 +1,39 @@
1
+ # frozen_string_literal: true
2
+
3
+ # @api private
4
+ # @since 0.1.0
5
+ module SmartCore::Schema::KeyControl
6
+ class << self
7
+ # @param key [String, Symbol]
8
+ # @return [String]
9
+ #
10
+ # @api private
11
+ # @since 0.1.0
12
+ def normalize(key)
13
+ prevent_incompatible!(key)
14
+ key.to_s
15
+ end
16
+
17
+ # @param keys [Array<String,Symbol>]
18
+ # @return [Array<String>]
19
+ #
20
+ # @api private
21
+ # @since 0.1.0
22
+ def normalize_list(keys)
23
+ keys.map { |key| normalize(key) }
24
+ end
25
+
26
+ # @param key [String, Symbol]
27
+ # @return [void]
28
+ #
29
+ # @api private
30
+ # @since 0.1.0
31
+ def prevent_incompatible!(key)
32
+ unless key.is_a?(String) || key.is_a?(Symbol)
33
+ raise(SmartCore::Schema::ArgumentError, <<~ERROR_MESSAGE)
34
+ Schema keys should be a type of string or symbol
35
+ ERROR_MESSAGE
36
+ end
37
+ end
38
+ end
39
+ end
@@ -0,0 +1,55 @@
1
+ # frozen_string_literal: true
2
+
3
+ # @api private
4
+ # @since 0.12.0
5
+ class SmartCore::Schema::Plugins::Abstract
6
+ class << self
7
+ # @param child_klass [Class]
8
+ # @return [void]
9
+ #
10
+ # @api private
11
+ # @since 0.12.0
12
+ def inherited(child_klass)
13
+ child_klass.instance_variable_set(:@__loaded__, false)
14
+ child_klass.instance_variable_set(:@__lock__, SmartCore::Engine::Lock.new)
15
+ super
16
+ end
17
+
18
+ # @return [void]
19
+ #
20
+ # @api private
21
+ # @since 0.12.0
22
+ def load!
23
+ __thread_safe__ do
24
+ unless @__loaded__
25
+ @__loaded__ = true
26
+ install!
27
+ end
28
+ end
29
+ end
30
+
31
+ # @return [Boolean]
32
+ #
33
+ # @api private
34
+ # @since 0.12.0
35
+ def loaded?
36
+ __thread_safe__ { @__loaded__ }
37
+ end
38
+
39
+ private
40
+
41
+ # @return [void]
42
+ #
43
+ # @api private
44
+ # @since 0.12.0
45
+ def install!; end
46
+
47
+ # @return [Any]
48
+ #
49
+ # @api private
50
+ # @since 0.12.0
51
+ def __thread_safe__(&block)
52
+ @__lock__.synchronize(&block)
53
+ end
54
+ end
55
+ end
@@ -0,0 +1,47 @@
1
+ # frozen_string_literal: true
2
+
3
+ # @api private
4
+ # @since 0.12.0
5
+ module SmartCore::Schema::Plugins::AccessMixin
6
+ # @param plugin_name [Symbol, String]
7
+ # @return [void]
8
+ #
9
+ # @see SmartCore::Schema::Plugins
10
+ #
11
+ # @api public
12
+ # @since 0.12.0
13
+ def plugin(plugin_name)
14
+ SmartCore::Schema::Plugins.load(plugin_name)
15
+ end
16
+
17
+ # @return [Array<String>]
18
+ #
19
+ # @see SmartCore::Schema::Plugins
20
+ #
21
+ # @api public
22
+ # @since 0.12.0
23
+ def plugins
24
+ SmartCore::Schema::Plugins.names
25
+ end
26
+
27
+ # @return [Hash<String,Class<SmartCore::Schema::Plugins::Abstract>>]
28
+ #
29
+ # @api private
30
+ # @since 0.12.0
31
+ def loaded_plugins
32
+ SmartCore::Schema::Plugins.loaded_plugins
33
+ end
34
+ alias_method :enabled_plugins, :loaded_plugins
35
+
36
+ # @param plugin_name [String, Symbol]
37
+ # @param plugin_klass [Class<SmartCore::Schema::Plugins::Abstract>]
38
+ # @return [void]
39
+ #
40
+ # @see SmartCore::Schema::Plugins
41
+ #
42
+ # @api public
43
+ # @since 0.12.0
44
+ def register_plugin(plugin_name, plugin_klass)
45
+ SmartCore::Schema::Plugins.register_plugin(plugin_name, plugin_klass)
46
+ end
47
+ end