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.
- checksums.yaml +4 -4
- data/.gitignore +12 -0
- data/.rspec +3 -0
- data/.rubocop.yml +20 -0
- data/CHANGELOG.md +106 -0
- data/CODE_OF_CONDUCT.md +74 -0
- data/Gemfile +5 -0
- data/Gemfile.lock +266 -0
- data/LICENSE.txt +21 -0
- data/README.md +305 -0
- data/Rakefile +21 -0
- data/bin/console +8 -0
- data/bin/setup +8 -0
- data/lib/smart_core/schema/checker/reconciler/constructor.rb +60 -0
- data/lib/smart_core/schema/checker/reconciler/matcher/options.rb +33 -0
- data/lib/smart_core/schema/checker/reconciler/matcher/result.rb +87 -0
- data/lib/smart_core/schema/checker/reconciler/matcher/result_finalizer.rb +186 -0
- data/lib/smart_core/schema/checker/reconciler/matcher.rb +62 -0
- data/lib/smart_core/schema/checker/reconciler.rb +106 -0
- data/lib/smart_core/schema/checker/rules/base.rb +110 -0
- data/lib/smart_core/schema/checker/rules/extra_keys/failure.rb +24 -0
- data/lib/smart_core/schema/checker/rules/extra_keys/result.rb +37 -0
- data/lib/smart_core/schema/checker/rules/extra_keys/success.rb +30 -0
- data/lib/smart_core/schema/checker/rules/extra_keys.rb +31 -0
- data/lib/smart_core/schema/checker/rules/optional.rb +27 -0
- data/lib/smart_core/schema/checker/rules/options/empty.rb +43 -0
- data/lib/smart_core/schema/checker/rules/options/filled.rb +49 -0
- data/lib/smart_core/schema/checker/rules/options/type.rb +88 -0
- data/lib/smart_core/schema/checker/rules/options.rb +60 -0
- data/lib/smart_core/schema/checker/rules/required.rb +27 -0
- data/lib/smart_core/schema/checker/rules/requirement/optional.rb +36 -0
- data/lib/smart_core/schema/checker/rules/requirement/required.rb +36 -0
- data/lib/smart_core/schema/checker/rules/requirement/result.rb +95 -0
- data/lib/smart_core/schema/checker/rules/requirement.rb +9 -0
- data/lib/smart_core/schema/checker/rules/result/base.rb +44 -0
- data/lib/smart_core/schema/checker/rules/result/failure.rb +41 -0
- data/lib/smart_core/schema/checker/rules/result/success.rb +15 -0
- data/lib/smart_core/schema/checker/rules/result.rb +9 -0
- data/lib/smart_core/schema/checker/rules/type_aliases.rb +57 -0
- data/lib/smart_core/schema/checker/rules/verifier/result.rb +75 -0
- data/lib/smart_core/schema/checker/rules/verifier.rb +74 -0
- data/lib/smart_core/schema/checker/rules.rb +89 -0
- data/lib/smart_core/schema/checker/verifiable_hash.rb +65 -0
- data/lib/smart_core/schema/checker.rb +106 -0
- data/lib/smart_core/schema/configuration.rb +33 -0
- data/lib/smart_core/schema/dsl.rb +81 -0
- data/lib/smart_core/schema/errors.rb +65 -0
- data/lib/smart_core/schema/key_control.rb +39 -0
- data/lib/smart_core/schema/plugins/abstract.rb +55 -0
- data/lib/smart_core/schema/plugins/access_mixin.rb +47 -0
- data/lib/smart_core/schema/plugins/dry_types/dry_types/abstract_factory.rb +99 -0
- data/lib/smart_core/schema/plugins/dry_types/dry_types/operation/base.rb +9 -0
- data/lib/smart_core/schema/plugins/dry_types/dry_types/operation/cast.rb +21 -0
- data/lib/smart_core/schema/plugins/dry_types/dry_types/operation/valid.rb +16 -0
- data/lib/smart_core/schema/plugins/dry_types/dry_types/operation/validate.rb +19 -0
- data/lib/smart_core/schema/plugins/dry_types/dry_types/operation.rb +12 -0
- data/lib/smart_core/schema/plugins/dry_types/dry_types.rb +10 -0
- data/lib/smart_core/schema/plugins/dry_types/errors.rb +13 -0
- data/lib/smart_core/schema/plugins/dry_types.rb +27 -0
- data/lib/smart_core/schema/plugins/registry.rb +158 -0
- data/lib/smart_core/schema/plugins/registry_interface.rb +63 -0
- data/lib/smart_core/schema/plugins.rb +17 -0
- data/lib/smart_core/schema/result.rb +62 -0
- data/lib/smart_core/schema/type_system/interop/abstract_factory.rb +92 -0
- data/lib/smart_core/schema/type_system/interop/aliasing/alias_list.rb +131 -0
- data/lib/smart_core/schema/type_system/interop/aliasing.rb +72 -0
- data/lib/smart_core/schema/type_system/interop/operation.rb +30 -0
- data/lib/smart_core/schema/type_system/interop.rb +128 -0
- data/lib/smart_core/schema/type_system/registry.rb +162 -0
- data/lib/smart_core/schema/type_system/registry_interface.rb +87 -0
- data/lib/smart_core/schema/type_system/smart_types/abstract_factory.rb +99 -0
- data/lib/smart_core/schema/type_system/smart_types/operation/base.rb +8 -0
- data/lib/smart_core/schema/type_system/smart_types/operation/cast.rb +16 -0
- data/lib/smart_core/schema/type_system/smart_types/operation/valid.rb +16 -0
- data/lib/smart_core/schema/type_system/smart_types/operation/validate.rb +16 -0
- data/lib/smart_core/schema/type_system/smart_types/operation.rb +13 -0
- data/lib/smart_core/schema/type_system/smart_types.rb +48 -0
- data/lib/smart_core/schema/type_system.rb +16 -0
- data/lib/smart_core/schema/version.rb +14 -0
- data/lib/smart_core/schema.rb +67 -0
- data/smart_schema.gemspec +46 -0
- 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
|