easy_talk_two 1.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 +36 -0
- data/CHANGELOG.md +127 -0
- data/CONSTRAINTS.md +70 -0
- data/LICENSE.txt +21 -0
- data/README.md +1060 -0
- data/Rakefile +11 -0
- data/docs/.gitignore +5 -0
- data/docs/404.html +25 -0
- data/docs/Gemfile +38 -0
- data/docs/_config.yml +53 -0
- data/docs/_posts/2024-05-07-welcome-to-jekyll.markdown +29 -0
- data/docs/about.markdown +18 -0
- data/docs/index.markdown +7 -0
- data/lib/easy_talk/active_record_schema_builder.rb +299 -0
- data/lib/easy_talk/builders/base_builder.rb +65 -0
- data/lib/easy_talk/builders/boolean_builder.rb +23 -0
- data/lib/easy_talk/builders/collection_helpers.rb +12 -0
- data/lib/easy_talk/builders/composition_builder.rb +77 -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 +180 -0
- data/lib/easy_talk/builders/string_builder.rb +27 -0
- data/lib/easy_talk/builders/temporal_builder.rb +49 -0
- data/lib/easy_talk/builders/typed_array_builder.rb +56 -0
- data/lib/easy_talk/builders/union_builder.rb +37 -0
- data/lib/easy_talk/configuration.rb +29 -0
- data/lib/easy_talk/errors.rb +8 -0
- data/lib/easy_talk/errors_helper.rb +147 -0
- data/lib/easy_talk/keywords.rb +37 -0
- data/lib/easy_talk/model.rb +197 -0
- data/lib/easy_talk/property.rb +130 -0
- data/lib/easy_talk/schema_definition.rb +78 -0
- data/lib/easy_talk/sorbet_extension.rb +15 -0
- data/lib/easy_talk/tools/function_builder.rb +40 -0
- data/lib/easy_talk/types/base_composer.rb +23 -0
- data/lib/easy_talk/types/composer.rb +88 -0
- data/lib/easy_talk/version.rb +5 -0
- data/lib/easy_talk.rb +29 -0
- metadata +265 -0
@@ -0,0 +1,197 @@
|
|
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 'active_model'
|
10
|
+
require_relative 'builders/object_builder'
|
11
|
+
require_relative 'schema_definition'
|
12
|
+
require_relative 'active_record_schema_builder'
|
13
|
+
|
14
|
+
module EasyTalk
|
15
|
+
# The `Model` module is a mixin that provides functionality for defining and accessing the schema of a model.
|
16
|
+
#
|
17
|
+
# It includes methods for defining the schema, retrieving the schema definition,
|
18
|
+
# and generating the JSON schema for the model.
|
19
|
+
#
|
20
|
+
# Example usage:
|
21
|
+
#
|
22
|
+
# class Person
|
23
|
+
# include EasyTalk::Model
|
24
|
+
#
|
25
|
+
# define_schema do
|
26
|
+
# property :name, String, description: 'The person\'s name'
|
27
|
+
# property :age, Integer, description: 'The person\'s age'
|
28
|
+
# end
|
29
|
+
# end
|
30
|
+
#
|
31
|
+
# Person.json_schema #=> returns the JSON schema for Person
|
32
|
+
# jim = Person.new(name: 'Jim', age: 30)
|
33
|
+
# jim.valid? #=> returns true
|
34
|
+
#
|
35
|
+
# @see SchemaDefinition
|
36
|
+
module Model
|
37
|
+
def self.included(base)
|
38
|
+
base.include ActiveModel::API # Include ActiveModel::API in the class including EasyTalk::Model
|
39
|
+
base.include ActiveModel::Validations
|
40
|
+
base.extend ActiveModel::Callbacks
|
41
|
+
base.extend(ClassMethods)
|
42
|
+
base.include(InstanceMethods)
|
43
|
+
|
44
|
+
# Apply ActiveRecord-specific functionality if appropriate
|
45
|
+
return unless defined?(ActiveRecord) && base.ancestors.include?(ActiveRecord::Base)
|
46
|
+
|
47
|
+
base.extend(ActiveRecordClassMethods)
|
48
|
+
end
|
49
|
+
|
50
|
+
module InstanceMethods
|
51
|
+
def initialize(attributes = {})
|
52
|
+
@additional_properties = {}
|
53
|
+
super
|
54
|
+
end
|
55
|
+
|
56
|
+
def method_missing(method_name, *args)
|
57
|
+
method_string = method_name.to_s
|
58
|
+
if method_string.end_with?('=')
|
59
|
+
property_name = method_string.chomp('=')
|
60
|
+
if self.class.additional_properties_allowed?
|
61
|
+
@additional_properties[property_name] = args.first
|
62
|
+
else
|
63
|
+
super
|
64
|
+
end
|
65
|
+
elsif self.class.additional_properties_allowed? && @additional_properties.key?(method_string)
|
66
|
+
@additional_properties[method_string]
|
67
|
+
else
|
68
|
+
super
|
69
|
+
end
|
70
|
+
end
|
71
|
+
|
72
|
+
def respond_to_missing?(method_name, include_private = false)
|
73
|
+
method_string = method_name.to_s
|
74
|
+
method_string.end_with?('=') ? method_string.chomp('=') : method_string
|
75
|
+
self.class.additional_properties_allowed? || super
|
76
|
+
end
|
77
|
+
|
78
|
+
# Add to_hash method to convert defined properties to hash
|
79
|
+
def to_hash
|
80
|
+
return {} unless self.class.properties
|
81
|
+
|
82
|
+
self.class.properties.each_with_object({}) do |prop, hash|
|
83
|
+
hash[prop.to_s] = send(prop)
|
84
|
+
end
|
85
|
+
end
|
86
|
+
|
87
|
+
# Override as_json to include both defined and additional properties
|
88
|
+
def as_json(_options = {})
|
89
|
+
to_hash.merge(@additional_properties)
|
90
|
+
end
|
91
|
+
end
|
92
|
+
|
93
|
+
# Module containing class-level methods for defining and accessing the schema of a model.
|
94
|
+
module ClassMethods
|
95
|
+
# Returns the schema for the model.
|
96
|
+
#
|
97
|
+
# @return [Schema] The schema for the model.
|
98
|
+
def schema
|
99
|
+
@schema ||= if defined?(@schema_definition) && @schema_definition
|
100
|
+
# Schema defined explicitly via define_schema
|
101
|
+
build_schema(@schema_definition)
|
102
|
+
elsif respond_to?(:active_record_schema_definition)
|
103
|
+
# ActiveRecord model without explicit schema definition
|
104
|
+
build_schema(active_record_schema_definition)
|
105
|
+
else
|
106
|
+
# Default case - empty schema
|
107
|
+
{}
|
108
|
+
end
|
109
|
+
end
|
110
|
+
|
111
|
+
# Returns the reference template for the model.
|
112
|
+
#
|
113
|
+
# @return [String] The reference template for the model.
|
114
|
+
def ref_template
|
115
|
+
"#/$defs/#{name}"
|
116
|
+
end
|
117
|
+
|
118
|
+
def properties
|
119
|
+
@properties ||= begin
|
120
|
+
return unless schema[:properties].present?
|
121
|
+
|
122
|
+
schema[:properties].keys.map(&:to_sym)
|
123
|
+
end
|
124
|
+
end
|
125
|
+
|
126
|
+
# Returns the JSON schema for the model.
|
127
|
+
#
|
128
|
+
# @return [Hash] The JSON schema for the model.
|
129
|
+
def json_schema
|
130
|
+
@json_schema ||= schema.as_json
|
131
|
+
end
|
132
|
+
|
133
|
+
# Define the schema for the model using the provided block.
|
134
|
+
#
|
135
|
+
# @yield The block to define the schema.
|
136
|
+
# @raise [ArgumentError] If the class does not have a name.
|
137
|
+
def define_schema(&block)
|
138
|
+
raise ArgumentError, 'The class must have a name' unless name.present?
|
139
|
+
|
140
|
+
@schema_definition = SchemaDefinition.new(name)
|
141
|
+
@schema_definition.instance_eval(&block)
|
142
|
+
attr_accessor(*properties)
|
143
|
+
|
144
|
+
@schema_definition
|
145
|
+
end
|
146
|
+
|
147
|
+
# Returns the unvalidated schema definition for the model.
|
148
|
+
#
|
149
|
+
# @return [SchemaDefinition] The unvalidated schema definition for the model.
|
150
|
+
def schema_definition
|
151
|
+
@schema_definition ||= {}
|
152
|
+
end
|
153
|
+
|
154
|
+
def additional_properties_allowed?
|
155
|
+
@schema_definition&.schema&.fetch(:additional_properties, false)
|
156
|
+
end
|
157
|
+
|
158
|
+
# Builds the schema using the provided schema definition.
|
159
|
+
# This is the convergence point for all schema generation.
|
160
|
+
#
|
161
|
+
# @param schema_definition [SchemaDefinition] The schema definition.
|
162
|
+
# @return [Schema] The validated schema.
|
163
|
+
def build_schema(schema_definition)
|
164
|
+
Builders::ObjectBuilder.new(schema_definition).build
|
165
|
+
end
|
166
|
+
end
|
167
|
+
|
168
|
+
# Module containing ActiveRecord-specific methods for schema generation
|
169
|
+
module ActiveRecordClassMethods
|
170
|
+
# Gets a SchemaDefinition that's built from the ActiveRecord database schema
|
171
|
+
#
|
172
|
+
# @return [SchemaDefinition] A schema definition built from the database
|
173
|
+
def active_record_schema_definition
|
174
|
+
@active_record_schema_definition ||= ActiveRecordSchemaBuilder.new(self).build_schema_definition
|
175
|
+
end
|
176
|
+
|
177
|
+
# Store enhancements to be applied to the schema
|
178
|
+
#
|
179
|
+
# @return [Hash] The schema enhancements
|
180
|
+
def schema_enhancements
|
181
|
+
@schema_enhancements ||= {}
|
182
|
+
end
|
183
|
+
|
184
|
+
# Enhance the generated schema with additional information
|
185
|
+
#
|
186
|
+
# @param enhancements [Hash] The schema enhancements
|
187
|
+
# @return [void]
|
188
|
+
def enhance_schema(enhancements)
|
189
|
+
@schema_enhancements = enhancements
|
190
|
+
# Clear cached values to force regeneration
|
191
|
+
@active_record_schema_definition = nil
|
192
|
+
@schema = nil
|
193
|
+
@json_schema = nil
|
194
|
+
end
|
195
|
+
end
|
196
|
+
end
|
197
|
+
end
|
@@ -0,0 +1,130 @@
|
|
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/temporal_builder'
|
10
|
+
require_relative 'builders/composition_builder'
|
11
|
+
require_relative 'builders/typed_array_builder'
|
12
|
+
require_relative 'builders/union_builder'
|
13
|
+
|
14
|
+
# frozen_string_literal: true
|
15
|
+
|
16
|
+
# EasyTalk module provides classes for building JSON schema properties.
|
17
|
+
#
|
18
|
+
# This module contains the `Property` class, which is used to build a JSON schema property.
|
19
|
+
# It also defines a constant `TYPE_TO_BUILDER` which maps property types to their respective builders.
|
20
|
+
#
|
21
|
+
# Example usage:
|
22
|
+
# property = EasyTalk::Property.new(:name, 'String', minLength: 3, maxLength: 50)
|
23
|
+
# property.build
|
24
|
+
#
|
25
|
+
# @see EasyTalk::Property
|
26
|
+
module EasyTalk
|
27
|
+
# Property class for building a JSON schema property.
|
28
|
+
class Property
|
29
|
+
extend T::Sig
|
30
|
+
attr_reader :name, :type, :constraints
|
31
|
+
|
32
|
+
TYPE_TO_BUILDER = {
|
33
|
+
'String' => Builders::StringBuilder,
|
34
|
+
'Integer' => Builders::IntegerBuilder,
|
35
|
+
'Float' => Builders::NumberBuilder,
|
36
|
+
'BigDecimal' => Builders::NumberBuilder,
|
37
|
+
'T::Boolean' => Builders::BooleanBuilder,
|
38
|
+
'TrueClass' => Builders::BooleanBuilder,
|
39
|
+
'NilClass' => Builders::NullBuilder,
|
40
|
+
'Date' => Builders::TemporalBuilder::DateBuilder,
|
41
|
+
'DateTime' => Builders::TemporalBuilder::DatetimeBuilder,
|
42
|
+
'Time' => Builders::TemporalBuilder::TimeBuilder,
|
43
|
+
'anyOf' => Builders::CompositionBuilder::AnyOfBuilder,
|
44
|
+
'allOf' => Builders::CompositionBuilder::AllOfBuilder,
|
45
|
+
'oneOf' => Builders::CompositionBuilder::OneOfBuilder,
|
46
|
+
'T::Types::TypedArray' => Builders::TypedArrayBuilder,
|
47
|
+
'T::Types::Union' => Builders::UnionBuilder
|
48
|
+
}.freeze
|
49
|
+
|
50
|
+
# Initializes a new instance of the Property class.
|
51
|
+
# @param name [Symbol] The name of the property.
|
52
|
+
# @param type [Object] The type of the property.
|
53
|
+
# @param constraints [Hash] The property constraints.
|
54
|
+
# @raise [ArgumentError] If the property type is missing.
|
55
|
+
sig do
|
56
|
+
params(name: Symbol, type: T.any(String, Object),
|
57
|
+
constraints: T::Hash[Symbol, T.untyped]).void
|
58
|
+
end
|
59
|
+
def initialize(name, type = nil, constraints = {})
|
60
|
+
@name = name
|
61
|
+
@type = type
|
62
|
+
@constraints = constraints
|
63
|
+
raise ArgumentError, 'property type is missing' if type.blank?
|
64
|
+
end
|
65
|
+
|
66
|
+
# Builds the property based on the specified type, constraints, and builder.
|
67
|
+
#
|
68
|
+
# If the type responds to the `schema` method, it returns the schema of the type.
|
69
|
+
# Otherwise, it returns 'object'.
|
70
|
+
#
|
71
|
+
# If a builder is specified, it uses the builder to build the property.
|
72
|
+
# The arguments passed to the builder depend on whether the builder is a collection type or not.
|
73
|
+
#
|
74
|
+
# @return [Object] The built property.
|
75
|
+
def build
|
76
|
+
if nilable_type?
|
77
|
+
build_nilable_schema
|
78
|
+
elsif builder
|
79
|
+
args = builder.collection_type? ? [name, type, constraints] : [name, constraints]
|
80
|
+
builder.new(*args).build
|
81
|
+
elsif type.respond_to?(:schema)
|
82
|
+
# merge the top-level constraints from *this* property
|
83
|
+
# e.g. :title, :description, :default, etc
|
84
|
+
type.schema.merge!(constraints)
|
85
|
+
else
|
86
|
+
'object'
|
87
|
+
end
|
88
|
+
end
|
89
|
+
|
90
|
+
# Converts the object to a JSON representation.
|
91
|
+
#
|
92
|
+
# @param _args [Array] Optional arguments
|
93
|
+
# @return [Hash] The JSON representation of the object
|
94
|
+
def as_json(*_args)
|
95
|
+
build.as_json
|
96
|
+
end
|
97
|
+
|
98
|
+
# Returns the builder associated with the property type.
|
99
|
+
#
|
100
|
+
# The builder is responsible for constructing the property based on its type.
|
101
|
+
# It looks up the builder based on the type's class name or name.
|
102
|
+
#
|
103
|
+
# @return [Builder] The builder associated with the property type.
|
104
|
+
def builder
|
105
|
+
@builder ||= TYPE_TO_BUILDER[type.class.name.to_s] || TYPE_TO_BUILDER[type.name.to_s]
|
106
|
+
end
|
107
|
+
|
108
|
+
private
|
109
|
+
|
110
|
+
def nilable_type?
|
111
|
+
return unless type.respond_to?(:types)
|
112
|
+
return unless type.types.all? { |t| t.respond_to?(:raw_type) }
|
113
|
+
|
114
|
+
type.types.any? { |t| t.raw_type == NilClass }
|
115
|
+
end
|
116
|
+
|
117
|
+
def build_nilable_schema
|
118
|
+
# Extract the non-nil type from the Union
|
119
|
+
actual_type = type.types.find { |t| t != NilClass }
|
120
|
+
|
121
|
+
# Create a property with the actual type
|
122
|
+
non_nil_schema = Property.new(name, actual_type, constraints).build
|
123
|
+
|
124
|
+
# Merge the types into an array
|
125
|
+
non_nil_schema.merge(
|
126
|
+
type: [non_nil_schema[:type], 'null']
|
127
|
+
)
|
128
|
+
end
|
129
|
+
end
|
130
|
+
end
|
@@ -0,0 +1,78 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative 'keywords'
|
4
|
+
require_relative 'types/composer'
|
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, schema = {})
|
21
|
+
@schema = schema
|
22
|
+
@schema[:additional_properties] = false unless schema.key?(:additional_properties)
|
23
|
+
@name = name
|
24
|
+
end
|
25
|
+
|
26
|
+
EasyTalk::KEYWORDS.each do |keyword|
|
27
|
+
define_method(keyword) do |*values|
|
28
|
+
@schema[keyword] = values.size > 1 ? values : values.first
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
def compose(*subschemas)
|
33
|
+
@schema[:subschemas] ||= []
|
34
|
+
@schema[:subschemas] += subschemas
|
35
|
+
end
|
36
|
+
|
37
|
+
sig do
|
38
|
+
params(name: T.any(Symbol, String), type: T.untyped, constraints: T.untyped, blk: T.nilable(T.proc.void)).void
|
39
|
+
end
|
40
|
+
def property(name, type, constraints = {}, &blk)
|
41
|
+
validate_property_name(name)
|
42
|
+
@schema[:properties] ||= {}
|
43
|
+
|
44
|
+
if block_given?
|
45
|
+
raise ArgumentError, 'Block-style sub-schemas are no longer supported. Use class references as types instead.'
|
46
|
+
end
|
47
|
+
|
48
|
+
@schema[:properties][name] = { type:, constraints: }
|
49
|
+
end
|
50
|
+
|
51
|
+
def validate_property_name(name)
|
52
|
+
return if name.to_s.match?(/^[A-Za-z_][A-Za-z0-9_]*$/)
|
53
|
+
|
54
|
+
raise InvalidPropertyNameError,
|
55
|
+
"Invalid property name '#{name}'. Must start with letter/underscore and contain only letters, numbers, underscores"
|
56
|
+
end
|
57
|
+
|
58
|
+
def optional?
|
59
|
+
@schema[:optional]
|
60
|
+
end
|
61
|
+
|
62
|
+
# Helper method for nullable and optional properties
|
63
|
+
def nullable_optional_property(name, type, constraints = {}, &blk)
|
64
|
+
# Ensure type is nilable
|
65
|
+
nilable_type = if type.respond_to?(:nilable?) && type.nilable?
|
66
|
+
type
|
67
|
+
else
|
68
|
+
T.nilable(type)
|
69
|
+
end
|
70
|
+
|
71
|
+
# Ensure constraints include optional: true
|
72
|
+
constraints = constraints.merge(optional: true)
|
73
|
+
|
74
|
+
# Call standard property method
|
75
|
+
property(name, nilable_type, constraints)
|
76
|
+
end
|
77
|
+
end
|
78
|
+
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,40 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module EasyTalk
|
4
|
+
module Tools
|
5
|
+
# FunctionBuilder is a module that builds a hash with the function type and function details.
|
6
|
+
# The return value is typically passed as argument to LLM function calling APIs.
|
7
|
+
module FunctionBuilder
|
8
|
+
class << self
|
9
|
+
# Creates a new function object based on the given model.
|
10
|
+
#
|
11
|
+
# @param [Model] model The EasyTalk model containing the function details.
|
12
|
+
# @return [Hash] The function object.
|
13
|
+
def new(model)
|
14
|
+
{
|
15
|
+
type: 'function',
|
16
|
+
function: {
|
17
|
+
name: generate_function_name(model),
|
18
|
+
description: generate_function_description(model),
|
19
|
+
parameters: model.json_schema
|
20
|
+
}
|
21
|
+
}
|
22
|
+
end
|
23
|
+
|
24
|
+
def generate_function_name(model)
|
25
|
+
model.schema.fetch(:title, model.name)
|
26
|
+
end
|
27
|
+
|
28
|
+
def generate_function_description(model)
|
29
|
+
if model.respond_to?(:instructions)
|
30
|
+
raise Instructor::Error, 'The instructions must be a string' unless model.instructions.is_a?(String)
|
31
|
+
|
32
|
+
model.instructions
|
33
|
+
else
|
34
|
+
"Correctly extracted `#{model.name}` with all the required parameters and correct types."
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
40
|
+
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,88 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative 'base_composer'
|
4
|
+
|
5
|
+
module EasyTalk
|
6
|
+
module Types
|
7
|
+
# Base class for composition types
|
8
|
+
class Composer < BaseComposer
|
9
|
+
# Returns the name of the composition type.
|
10
|
+
def self.name
|
11
|
+
raise NotImplementedError, "#{self.class.name} must implement the name method"
|
12
|
+
end
|
13
|
+
|
14
|
+
# Returns the name of the composition type.
|
15
|
+
def name
|
16
|
+
self.class.name
|
17
|
+
end
|
18
|
+
|
19
|
+
# Represents a composition type that allows all of the specified types.
|
20
|
+
class AllOf < Composer
|
21
|
+
def self.name
|
22
|
+
:allOf
|
23
|
+
end
|
24
|
+
|
25
|
+
def name
|
26
|
+
:allOf
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
# Represents a composition type that allows any of the specified types.
|
31
|
+
class AnyOf < Composer
|
32
|
+
def self.name
|
33
|
+
:anyOf
|
34
|
+
end
|
35
|
+
|
36
|
+
def name
|
37
|
+
:anyOf
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
# Represents a composition type that allows one of the specified types.
|
42
|
+
class OneOf < Composer
|
43
|
+
def self.name
|
44
|
+
:oneOf
|
45
|
+
end
|
46
|
+
|
47
|
+
def name
|
48
|
+
:oneOf
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
# Shorthand module for accessing the AllOf composer
|
56
|
+
module T
|
57
|
+
module AllOf
|
58
|
+
# Creates a new instance of `EasyTalk::Types::Composer::AllOf` with the given arguments.
|
59
|
+
#
|
60
|
+
# @param args [Array] the list of arguments to be passed to the constructor
|
61
|
+
# @return [EasyTalk::Types::Composer::AllOf] a new instance
|
62
|
+
def self.[](*args)
|
63
|
+
EasyTalk::Types::Composer::AllOf.new(*args)
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
67
|
+
# Shorthand module for accessing the AnyOf composer
|
68
|
+
module AnyOf
|
69
|
+
# Creates a new instance of `EasyTalk::Types::Composer::AnyOf` with the given arguments.
|
70
|
+
#
|
71
|
+
# @param args [Array] the list of arguments to be passed to the constructor
|
72
|
+
# @return [EasyTalk::Types::Composer::AnyOf] a new instance
|
73
|
+
def self.[](*args)
|
74
|
+
EasyTalk::Types::Composer::AnyOf.new(*args)
|
75
|
+
end
|
76
|
+
end
|
77
|
+
|
78
|
+
# Shorthand module for accessing the OneOf composer
|
79
|
+
module OneOf
|
80
|
+
# Creates a new instance of `EasyTalk::Types::Composer::OneOf` with the given arguments.
|
81
|
+
#
|
82
|
+
# @param args [Array] the list of arguments to be passed to the constructor
|
83
|
+
# @return [EasyTalk::Types::Composer::OneOf] a new instance
|
84
|
+
def self.[](*args)
|
85
|
+
EasyTalk::Types::Composer::OneOf.new(*args)
|
86
|
+
end
|
87
|
+
end
|
88
|
+
end
|
data/lib/easy_talk.rb
ADDED
@@ -0,0 +1,29 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# The EasyTalk module is the main namespace for the gem.
|
4
|
+
module EasyTalk
|
5
|
+
require 'sorbet-runtime'
|
6
|
+
require 'easy_talk/sorbet_extension'
|
7
|
+
require 'easy_talk/errors'
|
8
|
+
require 'easy_talk/errors_helper'
|
9
|
+
require 'easy_talk/configuration'
|
10
|
+
require 'easy_talk/types/composer'
|
11
|
+
require 'easy_talk/model'
|
12
|
+
require 'easy_talk/property'
|
13
|
+
require 'easy_talk/schema_definition'
|
14
|
+
require 'easy_talk/tools/function_builder'
|
15
|
+
require 'easy_talk/version'
|
16
|
+
|
17
|
+
def self.assert_valid_property_options(property_name, options, *valid_keys)
|
18
|
+
valid_keys.flatten!
|
19
|
+
options.each_key do |k|
|
20
|
+
next if valid_keys.include?(k)
|
21
|
+
|
22
|
+
ErrorHelper.raise_unknown_option_error(property_name: property_name, option: options, valid_options: valid_keys)
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
def self.configure_nilable_behavior(nilable_is_optional = false)
|
27
|
+
configuration.nilable_is_optional = nilable_is_optional
|
28
|
+
end
|
29
|
+
end
|