easy_talk 0.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 +7 -0
- data/.rubocop.yml +14 -0
- data/CHANGELOG.md +0 -0
- data/CONSTRAINTS.md +70 -0
- data/LICENSE.txt +21 -0
- data/README.md +186 -0
- data/Rakefile +12 -0
- data/easy_talk.gemspec +38 -0
- data/lib/easy_talk/builder.rb +51 -0
- data/lib/easy_talk/builders/all_of_builder.rb +11 -0
- data/lib/easy_talk/builders/any_of_builder.rb +11 -0
- data/lib/easy_talk/builders/base_builder.rb +58 -0
- data/lib/easy_talk/builders/boolean_builder.rb +24 -0
- data/lib/easy_talk/builders/composition_builder.rb +64 -0
- data/lib/easy_talk/builders/date_builder.rb +18 -0
- data/lib/easy_talk/builders/datetime_builder.rb +18 -0
- data/lib/easy_talk/builders/integer_builder.rb +28 -0
- data/lib/easy_talk/builders/null_builder.rb +16 -0
- data/lib/easy_talk/builders/number_builder.rb +27 -0
- data/lib/easy_talk/builders/object_builder.rb +72 -0
- data/lib/easy_talk/builders/one_of_builder.rb +11 -0
- data/lib/easy_talk/builders/ref_array_builder.rb +25 -0
- data/lib/easy_talk/builders/string_builder.rb +27 -0
- data/lib/easy_talk/builders/time_builder.rb +16 -0
- data/lib/easy_talk/builders/typed_array_builder.rb +51 -0
- data/lib/easy_talk/builders/union_builder.rb +35 -0
- data/lib/easy_talk/keywords.rb +37 -0
- data/lib/easy_talk/model.rb +105 -0
- data/lib/easy_talk/property.rb +80 -0
- data/lib/easy_talk/schema_definition.rb +42 -0
- data/lib/easy_talk/sorbet_extension.rb +15 -0
- data/lib/easy_talk/types/all_of.rb +32 -0
- data/lib/easy_talk/types/any_of.rb +39 -0
- data/lib/easy_talk/types/base_composer.rb +23 -0
- data/lib/easy_talk/types/one_of.rb +31 -0
- data/lib/easy_talk/version.rb +5 -0
- data/lib/easy_talk.rb +28 -0
- metadata +139 -0
@@ -0,0 +1,27 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative 'base_builder'
|
4
|
+
|
5
|
+
module EasyTalk
|
6
|
+
module Builders
|
7
|
+
# Builder class for number properties.
|
8
|
+
class NumberBuilder < BaseBuilder
|
9
|
+
VALID_OPTIONS = {
|
10
|
+
multiple_of: { type: T.any(Integer, Float), key: :multipleOf },
|
11
|
+
minimum: { type: T.any(Integer, Float), key: :minimum },
|
12
|
+
maximum: { type: T.any(Integer, Float), key: :maximum },
|
13
|
+
exclusive_minimum: { type: T.any(Integer, Float), key: :exclusiveMinimum },
|
14
|
+
exclusive_maximum: { type: T.any(Integer, Float), key: :exclusiveMaximum },
|
15
|
+
enum: { type: T::Array[T.any(Integer, Float)], key: :enum },
|
16
|
+
const: { type: T.any(Integer, Float), key: :const },
|
17
|
+
default: { type: T.any(Integer, Float), key: :default }
|
18
|
+
}.freeze
|
19
|
+
|
20
|
+
# Initializes a new instance of the NumberBuilder class.
|
21
|
+
sig { params(name: Symbol, _type: T.untyped, constraints: Hash).void }
|
22
|
+
def initialize(name, _type = nil, constraints = {})
|
23
|
+
super(name, { type: 'number' }, constraints, VALID_OPTIONS)
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
@@ -0,0 +1,72 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module EasyTalk
|
4
|
+
module Builders
|
5
|
+
# Builder class for json schema objects.
|
6
|
+
class ObjectBuilder < BaseBuilder
|
7
|
+
extend T::Sig
|
8
|
+
|
9
|
+
attr_reader :klass, :schema
|
10
|
+
|
11
|
+
VALID_OPTIONS = {
|
12
|
+
properties: { type: T::Hash[Symbol, T.untyped], key: :properties },
|
13
|
+
additional_properties: { type: T::Boolean, key: :additionalProperties },
|
14
|
+
subschemas: { type: T::Array[T.untyped], key: :subschemas },
|
15
|
+
required: { type: T::Array[Symbol], key: :required },
|
16
|
+
defs: { type: T.untyped, key: :$defs },
|
17
|
+
allOf: { type: T.untyped, key: :allOf },
|
18
|
+
anyOf: { type: T.untyped, key: :anyOf },
|
19
|
+
oneOf: { type: T.untyped, key: :oneOf },
|
20
|
+
not: { type: T.untyped, key: :not }
|
21
|
+
}.freeze
|
22
|
+
|
23
|
+
sig { params(schema_definition: EasyTalk::SchemaDefinition).void }
|
24
|
+
def initialize(schema_definition)
|
25
|
+
@schema_definition = schema_definition
|
26
|
+
@schema = schema_definition.schema.dup
|
27
|
+
@required_properties = []
|
28
|
+
name = schema_definition.name ? schema_definition.name.to_sym : :klass
|
29
|
+
super(name, { type: 'object' }, options, VALID_OPTIONS)
|
30
|
+
end
|
31
|
+
|
32
|
+
private
|
33
|
+
|
34
|
+
def properties_from_schema_definition(properties)
|
35
|
+
properties.each_with_object({}) do |(property_name, options), context|
|
36
|
+
@required_properties << property_name unless options[:type].respond_to?(:nilable?) && options[:type].nilable?
|
37
|
+
context[property_name] = Property.new(property_name, options[:type], options[:constraints])
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
def subschemas_from_schema_definition(subschemas)
|
42
|
+
subschemas.each do |subschema|
|
43
|
+
definitions = subschema.items.each_with_object({}) do |item, hash|
|
44
|
+
hash[item.name] = item.schema
|
45
|
+
end
|
46
|
+
schema[:defs] = definitions
|
47
|
+
references = subschema.items.map do |item|
|
48
|
+
{ '$ref': item.ref_template }
|
49
|
+
end
|
50
|
+
schema[subschema.name] = references
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
def options
|
55
|
+
subschemas_from_schema_definition(subschemas)
|
56
|
+
@options = schema
|
57
|
+
@options[:properties] = properties_from_schema_definition(properties)
|
58
|
+
@options[:required] = @required_properties
|
59
|
+
@options.reject! { |_key, value| [nil, [], {}].include?(value) }
|
60
|
+
@options
|
61
|
+
end
|
62
|
+
|
63
|
+
def properties
|
64
|
+
schema.delete(:properties) || {}
|
65
|
+
end
|
66
|
+
|
67
|
+
def subschemas
|
68
|
+
schema.delete(:subschemas) || []
|
69
|
+
end
|
70
|
+
end
|
71
|
+
end
|
72
|
+
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative 'base_builder'
|
4
|
+
|
5
|
+
module EasyTalk
|
6
|
+
module Builders
|
7
|
+
# Builder class for array properties.
|
8
|
+
class RefArrayBuilder < BaseBuilder
|
9
|
+
# Initializes a new instance of the ArrayBuilder class.
|
10
|
+
sig { params(name: Symbol).void }
|
11
|
+
def initialize(name)
|
12
|
+
super(name, { type: 'array' }, options, {})
|
13
|
+
end
|
14
|
+
|
15
|
+
private
|
16
|
+
|
17
|
+
sig { void }
|
18
|
+
# Updates the option types for the array builder.
|
19
|
+
def update_option_types
|
20
|
+
VALID_OPTIONS[:enum][:type] = T::Array[@inner_type]
|
21
|
+
VALID_OPTIONS[:const][:type] = T::Array[@inner_type]
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
@@ -0,0 +1,27 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative 'base_builder'
|
4
|
+
require 'sorbet-runtime' # Add the import statement for the T module
|
5
|
+
|
6
|
+
module EasyTalk
|
7
|
+
module Builders
|
8
|
+
# Builder class for string properties.
|
9
|
+
class StringBuilder < BaseBuilder
|
10
|
+
extend T::Sig
|
11
|
+
VALID_OPTIONS = {
|
12
|
+
format: { type: String, key: :format },
|
13
|
+
pattern: { type: String, key: :pattern },
|
14
|
+
min_length: { type: Integer, key: :minLength },
|
15
|
+
max_length: { type: Integer, key: :maxLength },
|
16
|
+
enum: { type: T::Array[String], key: :enum },
|
17
|
+
const: { type: String, key: :const },
|
18
|
+
default: { type: String, key: :default }
|
19
|
+
}.freeze
|
20
|
+
|
21
|
+
sig { params(name: Symbol, _type: T.untyped, constraints: Hash).void }
|
22
|
+
def initialize(name, _type = nil, constraints = {})
|
23
|
+
super(name, { type: 'string' }, constraints, VALID_OPTIONS)
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative 'base_builder'
|
4
|
+
|
5
|
+
module EasyTalk
|
6
|
+
module Builders
|
7
|
+
# Builder class for time properties.
|
8
|
+
class TimeBuilder < StringBuilder
|
9
|
+
def schema
|
10
|
+
super.tap do |schema|
|
11
|
+
schema[:format] = 'time'
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
@@ -0,0 +1,51 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module EasyTalk
|
4
|
+
module Builders
|
5
|
+
# Builder class for array properties.
|
6
|
+
class TypedArrayBuilder < BaseBuilder
|
7
|
+
VALID_OPTIONS = {
|
8
|
+
min_items: { type: Integer, key: :minItems },
|
9
|
+
max_items: { type: Integer, key: :maxItems },
|
10
|
+
unique_items: { type: T::Boolean, key: :uniqueItems },
|
11
|
+
enum: { type: T::Array[T.untyped], key: :enum },
|
12
|
+
const: { type: T::Array[T.untyped], key: :const }
|
13
|
+
}.freeze
|
14
|
+
|
15
|
+
attr_reader :type
|
16
|
+
|
17
|
+
sig { params(name: Symbol, type: T.untyped, constraints: Hash).void }
|
18
|
+
def initialize(name, type, constraints = {})
|
19
|
+
@name = name
|
20
|
+
@type = type
|
21
|
+
update_option_types
|
22
|
+
super(name, { type: 'array' }, constraints, VALID_OPTIONS)
|
23
|
+
end
|
24
|
+
|
25
|
+
private
|
26
|
+
|
27
|
+
# Modifies the schema to include the `items` property.
|
28
|
+
#
|
29
|
+
# @return [Hash] The built schema.
|
30
|
+
sig { returns(T::Hash[Symbol, T.untyped]) }
|
31
|
+
def schema
|
32
|
+
super.tap do |schema|
|
33
|
+
schema[:items] = Property.new(@name, inner_type, {}).build
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
def inner_type
|
38
|
+
return unless type.is_a?(T::Types::TypedArray)
|
39
|
+
|
40
|
+
type.type.raw_type
|
41
|
+
end
|
42
|
+
|
43
|
+
sig { void }
|
44
|
+
# Updates the option types for the array builder.
|
45
|
+
def update_option_types
|
46
|
+
VALID_OPTIONS[:enum][:type] = T::Array[inner_type]
|
47
|
+
VALID_OPTIONS[:const][:type] = T::Array[inner_type]
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
@@ -0,0 +1,35 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative 'base_builder'
|
4
|
+
|
5
|
+
module EasyTalk
|
6
|
+
module Builders
|
7
|
+
# Base builder class for array-type properties.
|
8
|
+
class UnionBuilder
|
9
|
+
extend T::Sig
|
10
|
+
sig { params(name: Symbol, type: T.untyped, constraints: T.untyped).void }
|
11
|
+
def initialize(name, type, constraints)
|
12
|
+
@name = name
|
13
|
+
@type = type
|
14
|
+
@constraints = constraints
|
15
|
+
@context = {}
|
16
|
+
end
|
17
|
+
|
18
|
+
def build
|
19
|
+
@context[@name] = {
|
20
|
+
'anyOf' => schemas
|
21
|
+
}
|
22
|
+
end
|
23
|
+
|
24
|
+
def schemas
|
25
|
+
types.map do |type|
|
26
|
+
Property.new(@name, type, @constraints).build
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
def types
|
31
|
+
@type.types
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
@@ -0,0 +1,37 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module EasyTalk
|
4
|
+
KEYWORDS = %i[
|
5
|
+
description
|
6
|
+
type
|
7
|
+
title
|
8
|
+
property
|
9
|
+
required
|
10
|
+
items
|
11
|
+
additional_items
|
12
|
+
pattern_properties
|
13
|
+
additional_properties
|
14
|
+
dependencies
|
15
|
+
dependent_required
|
16
|
+
format
|
17
|
+
content_media_type
|
18
|
+
content_encoding
|
19
|
+
enum
|
20
|
+
const
|
21
|
+
default
|
22
|
+
examples
|
23
|
+
max_length
|
24
|
+
min_length
|
25
|
+
pattern
|
26
|
+
maximum
|
27
|
+
exclusive_maximum
|
28
|
+
minimum
|
29
|
+
exclusive_minimum
|
30
|
+
multiple_of
|
31
|
+
max_items
|
32
|
+
min_items
|
33
|
+
unique_items
|
34
|
+
max_properties
|
35
|
+
min_properties
|
36
|
+
].freeze
|
37
|
+
end
|
@@ -0,0 +1,105 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'json'
|
4
|
+
require 'active_support'
|
5
|
+
require 'active_support/core_ext'
|
6
|
+
require 'active_support/time'
|
7
|
+
require 'active_support/concern'
|
8
|
+
require 'active_support/json'
|
9
|
+
require_relative 'builder'
|
10
|
+
require_relative 'schema_definition'
|
11
|
+
|
12
|
+
module EasyTalk
|
13
|
+
# The Model module can be included in a class to add JSON schema definition and generation support.
|
14
|
+
module Model
|
15
|
+
def self.included(base)
|
16
|
+
base.extend(ClassMethods)
|
17
|
+
|
18
|
+
base.singleton_class.instance_eval do
|
19
|
+
define_method(:inherited) do |subclass|
|
20
|
+
super(subclass)
|
21
|
+
subclass.extend(SubclassExtension)
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
# This module provides extension methods for subclasses with schema definitions.
|
27
|
+
module SubclassExtension
|
28
|
+
# Returns true if the class inherits a schema.
|
29
|
+
def inherits_schema?
|
30
|
+
true
|
31
|
+
end
|
32
|
+
|
33
|
+
# Returns the superclass that the class inherits from.
|
34
|
+
def inherits_from
|
35
|
+
superclass
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
# Module containing class-level methods for defining and accessing the schema of a model.
|
40
|
+
#
|
41
|
+
# This module provides methods for defining and accessing the JSON schema of a model.
|
42
|
+
# It includes methods for defining the schema, retrieving the schema definition,
|
43
|
+
# and generating the JSON schema for the model.
|
44
|
+
#
|
45
|
+
# Example usage:
|
46
|
+
#
|
47
|
+
# class MyModel
|
48
|
+
# extend ClassMethods
|
49
|
+
#
|
50
|
+
# define_schema do
|
51
|
+
# # schema definition goes here
|
52
|
+
# end
|
53
|
+
# end
|
54
|
+
#
|
55
|
+
# MyModel.json_schema #=> returns the JSON schema for MyModel
|
56
|
+
#
|
57
|
+
# MyModel.schema_definition #=> returns the unvalidated schema definition for MyModel
|
58
|
+
#
|
59
|
+
# MyModel.ref_template #=> returns the reference template for MyModel
|
60
|
+
#
|
61
|
+
# MyModel.inherits_schema? #=> returns false
|
62
|
+
#
|
63
|
+
# MyModel.schema #=> returns the validated schema for MyModel
|
64
|
+
#
|
65
|
+
# MyModel.schema_definition #=> returns the unvalidated schema definition for MyModel
|
66
|
+
#
|
67
|
+
# MyModel.json_schema #=> returns the JSON schema for MyModel
|
68
|
+
#
|
69
|
+
# @see SchemaDefinition
|
70
|
+
# @see Builder
|
71
|
+
module ClassMethods
|
72
|
+
def schema
|
73
|
+
@schema ||= Builder.new(schema_definition).schema
|
74
|
+
end
|
75
|
+
|
76
|
+
def inherits_schema?
|
77
|
+
false
|
78
|
+
end
|
79
|
+
|
80
|
+
def ref_template
|
81
|
+
"#/$defs/#{name}"
|
82
|
+
end
|
83
|
+
|
84
|
+
# Returns the JSON schema for the model.
|
85
|
+
def json_schema
|
86
|
+
@json_schema ||= begin
|
87
|
+
schema = Builder.new(schema_definition).schema
|
88
|
+
schema.to_json
|
89
|
+
end
|
90
|
+
end
|
91
|
+
|
92
|
+
# Define the schema using the provided block.
|
93
|
+
def define_schema(&block)
|
94
|
+
raise ArgumentError, 'The class must have a name' unless name.present?
|
95
|
+
|
96
|
+
@schema_definition = SchemaDefinition.new(name)
|
97
|
+
@schema_definition.instance_eval(&block)
|
98
|
+
end
|
99
|
+
|
100
|
+
def schema_definition
|
101
|
+
@schema_definition ||= {}
|
102
|
+
end
|
103
|
+
end
|
104
|
+
end
|
105
|
+
end
|
@@ -0,0 +1,80 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'json'
|
4
|
+
require_relative 'builders/integer_builder'
|
5
|
+
require_relative 'builders/number_builder'
|
6
|
+
require_relative 'builders/boolean_builder'
|
7
|
+
require_relative 'builders/null_builder'
|
8
|
+
require_relative 'builders/string_builder'
|
9
|
+
require_relative 'builders/date_builder'
|
10
|
+
require_relative 'builders/datetime_builder'
|
11
|
+
require_relative 'builders/time_builder'
|
12
|
+
require_relative 'builders/any_of_builder'
|
13
|
+
require_relative 'builders/all_of_builder'
|
14
|
+
require_relative 'builders/one_of_builder'
|
15
|
+
require_relative 'builders/typed_array_builder'
|
16
|
+
require_relative 'builders/union_builder'
|
17
|
+
|
18
|
+
# frozen_string_literal: true
|
19
|
+
|
20
|
+
module EasyTalk
|
21
|
+
# Property class for building a JSON schema property.
|
22
|
+
class Property
|
23
|
+
extend T::Sig
|
24
|
+
attr_reader :name, :type, :constraints
|
25
|
+
|
26
|
+
TYPE_TO_BUILDER = {
|
27
|
+
'String' => Builders::StringBuilder,
|
28
|
+
'Integer' => Builders::IntegerBuilder,
|
29
|
+
'Float' => Builders::NumberBuilder,
|
30
|
+
'BigDecimal' => Builders::NumberBuilder,
|
31
|
+
'T::Boolean' => Builders::BooleanBuilder,
|
32
|
+
'NilClass' => Builders::NullBuilder,
|
33
|
+
'Date' => Builders::DateBuilder,
|
34
|
+
'DateTime' => Builders::DatetimeBuilder,
|
35
|
+
'Time' => Builders::TimeBuilder,
|
36
|
+
'anyOf' => Builders::AnyOfBuilder,
|
37
|
+
'allOf' => Builders::AllOfBuilder,
|
38
|
+
'oneOf' => Builders::OneOfBuilder,
|
39
|
+
'T::Types::TypedArray' => Builders::TypedArrayBuilder,
|
40
|
+
'T::Types::Union' => Builders::UnionBuilder
|
41
|
+
}.freeze
|
42
|
+
|
43
|
+
# Initializes a new instance of the Property class.
|
44
|
+
# @param name [Symbol] The name of the property.
|
45
|
+
# @param type [Object] The type of the property.
|
46
|
+
# @param constraints [Hash] The property constraints.
|
47
|
+
# @raise [ArgumentError] If the property type is missing.
|
48
|
+
sig do
|
49
|
+
params(name: Symbol, type: T.any(String, Object),
|
50
|
+
constraints: T::Hash[Symbol, T.untyped]).void
|
51
|
+
end
|
52
|
+
def initialize(name, type = nil, constraints = {})
|
53
|
+
@name = name
|
54
|
+
@type = type
|
55
|
+
@constraints = constraints
|
56
|
+
raise ArgumentError, 'property type is missing' if type.blank?
|
57
|
+
end
|
58
|
+
|
59
|
+
def build
|
60
|
+
if type.is_a?(T::Types::Simple)
|
61
|
+
@type = type.raw_type
|
62
|
+
return self
|
63
|
+
end
|
64
|
+
|
65
|
+
if builder
|
66
|
+
builder.new(name, type, constraints).build
|
67
|
+
else
|
68
|
+
type.respond_to?(:schema) ? type.schema : 'object'
|
69
|
+
end
|
70
|
+
end
|
71
|
+
|
72
|
+
def as_json(*_args)
|
73
|
+
build.as_json
|
74
|
+
end
|
75
|
+
|
76
|
+
def builder
|
77
|
+
TYPE_TO_BUILDER[type.class.name.to_s] || TYPE_TO_BUILDER[type.name.to_s]
|
78
|
+
end
|
79
|
+
end
|
80
|
+
end
|
@@ -0,0 +1,42 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'pry-byebug'
|
4
|
+
require_relative 'keywords'
|
5
|
+
|
6
|
+
module EasyTalk
|
7
|
+
#
|
8
|
+
#= EasyTalk \SchemaDefinition
|
9
|
+
# SchemaDefinition provides the methods for defining a schema within the define_schema block.
|
10
|
+
# The @schema is a hash that contains the unvalidated schema definition for the model.
|
11
|
+
# A SchemaDefinition instanace is the passed to the Builder.build_schema method to validate and compile the schema.
|
12
|
+
class SchemaDefinition
|
13
|
+
extend T::Sig
|
14
|
+
extend T::AnyOf
|
15
|
+
extend T::OneOf
|
16
|
+
extend T::AllOf
|
17
|
+
|
18
|
+
attr_reader :name, :schema
|
19
|
+
|
20
|
+
def initialize(name)
|
21
|
+
@schema = {}
|
22
|
+
@name = name
|
23
|
+
end
|
24
|
+
|
25
|
+
EasyTalk::KEYWORDS.each do |keyword|
|
26
|
+
define_method(keyword) do |*values|
|
27
|
+
@schema[keyword] = values.size > 1 ? values : values.first
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
def compose(*subschemas)
|
32
|
+
@schema[:subschemas] ||= []
|
33
|
+
@schema[:subschemas] += subschemas
|
34
|
+
end
|
35
|
+
|
36
|
+
sig { params(name: Symbol, type: T.untyped, constraints: T.untyped).void }
|
37
|
+
def property(name, type, **constraints)
|
38
|
+
@schema[:properties] ||= {}
|
39
|
+
@schema[:properties][name] = { type:, constraints: }
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
@@ -0,0 +1,15 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# This module provides additional functionality for working with Sorbet types.
|
4
|
+
module SorbetExtension
|
5
|
+
# Checks if the types in the collection include the NilClass type.
|
6
|
+
#
|
7
|
+
# @return [Boolean] true if the types include NilClass, false otherwise.
|
8
|
+
def nilable?
|
9
|
+
types.any? do |type|
|
10
|
+
type.respond_to?(:raw_type) && type.raw_type == NilClass
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
T::Types::Union.include SorbetExtension
|
@@ -0,0 +1,32 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative 'base_composer'
|
4
|
+
# The EasyTalk module provides a collection of types for composing schemas.
|
5
|
+
module EasyTalk
|
6
|
+
# The `Types` module provides a collection of classes for composing different types.
|
7
|
+
module Types
|
8
|
+
# Represents a composition type that allows all of the specified types.
|
9
|
+
class AllOf < BaseComposer
|
10
|
+
def self.name
|
11
|
+
:allOf
|
12
|
+
end
|
13
|
+
|
14
|
+
def name
|
15
|
+
:allOf
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
module T
|
22
|
+
# no-doc
|
23
|
+
module AllOf
|
24
|
+
# Creates a new instance of `EasyTalk::Types::AllOf` with the given arguments.
|
25
|
+
#
|
26
|
+
# @param args [Array] the list of arguments to be passed to the `EasyTalk::Types::AllOf` constructor
|
27
|
+
# @return [EasyTalk::Types::AllOf] a new instance of `EasyTalk::Types::AllOf`
|
28
|
+
def self.[](*args)
|
29
|
+
EasyTalk::Types::AllOf.new(*args)
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
@@ -0,0 +1,39 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative 'base_composer'
|
4
|
+
module EasyTalk
|
5
|
+
module Types
|
6
|
+
# The `Types` module provides a collection of composers for defining different types.
|
7
|
+
#
|
8
|
+
# This module contains composers for various types such as `AnyOf`, `AllOf`, etc.
|
9
|
+
# Each composer is responsible for defining the behavior and properties of its respective type.
|
10
|
+
class AnyOf < BaseComposer
|
11
|
+
# Returns the name of the AnyOf composer.
|
12
|
+
#
|
13
|
+
# @return [Symbol] The name of the composer.
|
14
|
+
def self.name
|
15
|
+
:anyOf
|
16
|
+
end
|
17
|
+
|
18
|
+
# Returns the name of the AnyOf composer.
|
19
|
+
#
|
20
|
+
# @return [Symbol] The name of the composer.
|
21
|
+
def name
|
22
|
+
:anyOf
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
module T
|
29
|
+
# no-doc
|
30
|
+
module AnyOf
|
31
|
+
# Creates a new instance of `EasyTalk::Types::AnyOf` with the given arguments.
|
32
|
+
#
|
33
|
+
# @param args [Array] the list of arguments to be passed to the `EasyTalk::Types::AnyOf` constructor
|
34
|
+
# @return [EasyTalk::Types::AnyOf] a new instance of `EasyTalk::Types::AnyOf`
|
35
|
+
def self.[](*args)
|
36
|
+
EasyTalk::Types::AnyOf.new(*args)
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module EasyTalk
|
4
|
+
module Types
|
5
|
+
# no-doc
|
6
|
+
class BaseComposer
|
7
|
+
extend T::Sig
|
8
|
+
extend T::Generic
|
9
|
+
|
10
|
+
Elem = type_member
|
11
|
+
|
12
|
+
sig { returns(T::Array[Elem]) }
|
13
|
+
attr_reader :items
|
14
|
+
|
15
|
+
# Initializes a new instance of the BaseComposer class.
|
16
|
+
#
|
17
|
+
# @param args [Array] the items to be assigned to the instance variable @items
|
18
|
+
def initialize(*args)
|
19
|
+
@items = args
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
@@ -0,0 +1,31 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative 'base_composer'
|
4
|
+
module EasyTalk
|
5
|
+
module Types
|
6
|
+
# Represents a composition type that allows one of the specified types.
|
7
|
+
class OneOf < BaseComposer
|
8
|
+
# Returns the name of the composition type.
|
9
|
+
def self.name
|
10
|
+
:oneOf
|
11
|
+
end
|
12
|
+
|
13
|
+
# Returns the name of the composition type.
|
14
|
+
def name
|
15
|
+
:oneOf
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
module T
|
22
|
+
# Creates a new instance of `EasyTalk::Types::OneOf` with the given arguments.
|
23
|
+
#
|
24
|
+
# @param args [Array] the list of arguments to be passed to the `EasyTalk::Types::OneOf` constructor
|
25
|
+
# @return [EasyTalk::Types::OneOf] a new instance of `EasyTalk::Types::OneOf`
|
26
|
+
module OneOf
|
27
|
+
def self.[](*args)
|
28
|
+
EasyTalk::Types::OneOf.new(*args)
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|