easy_talk 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
|