yasmina-motor-ruby 0.0.8

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (80) hide show
  1. checksums.yaml +7 -0
  2. data/.fern/metadata.json +10 -0
  3. data/.fern/replay.lock +10 -0
  4. data/.fernignore +4 -0
  5. data/.rubocop.yml +103 -0
  6. data/CONTRIBUTING.md +120 -0
  7. data/LICENSE +21 -0
  8. data/README.md +173 -0
  9. data/Rakefile +20 -0
  10. data/custom.gemspec.rb +16 -0
  11. data/lib/yasminaai/client.rb +37 -0
  12. data/lib/yasminaai/environment.rb +9 -0
  13. data/lib/yasminaai/errors/api_error.rb +8 -0
  14. data/lib/yasminaai/errors/client_error.rb +17 -0
  15. data/lib/yasminaai/errors/redirect_error.rb +8 -0
  16. data/lib/yasminaai/errors/response_error.rb +42 -0
  17. data/lib/yasminaai/errors/server_error.rb +11 -0
  18. data/lib/yasminaai/errors/timeout_error.rb +8 -0
  19. data/lib/yasminaai/internal/errors/constraint_error.rb +10 -0
  20. data/lib/yasminaai/internal/errors/type_error.rb +10 -0
  21. data/lib/yasminaai/internal/http/base_request.rb +51 -0
  22. data/lib/yasminaai/internal/http/raw_client.rb +215 -0
  23. data/lib/yasminaai/internal/iterators/cursor_item_iterator.rb +28 -0
  24. data/lib/yasminaai/internal/iterators/cursor_page_iterator.rb +63 -0
  25. data/lib/yasminaai/internal/iterators/item_iterator.rb +65 -0
  26. data/lib/yasminaai/internal/iterators/offset_item_iterator.rb +30 -0
  27. data/lib/yasminaai/internal/iterators/offset_page_iterator.rb +103 -0
  28. data/lib/yasminaai/internal/json/request.rb +41 -0
  29. data/lib/yasminaai/internal/json/serializable.rb +25 -0
  30. data/lib/yasminaai/internal/multipart/multipart_encoder.rb +141 -0
  31. data/lib/yasminaai/internal/multipart/multipart_form_data.rb +78 -0
  32. data/lib/yasminaai/internal/multipart/multipart_form_data_part.rb +51 -0
  33. data/lib/yasminaai/internal/multipart/multipart_request.rb +40 -0
  34. data/lib/yasminaai/internal/types/array.rb +47 -0
  35. data/lib/yasminaai/internal/types/boolean.rb +34 -0
  36. data/lib/yasminaai/internal/types/enum.rb +56 -0
  37. data/lib/yasminaai/internal/types/hash.rb +36 -0
  38. data/lib/yasminaai/internal/types/model/field.rb +38 -0
  39. data/lib/yasminaai/internal/types/model.rb +208 -0
  40. data/lib/yasminaai/internal/types/type.rb +35 -0
  41. data/lib/yasminaai/internal/types/union.rb +161 -0
  42. data/lib/yasminaai/internal/types/unknown.rb +15 -0
  43. data/lib/yasminaai/internal/types/utils.rb +116 -0
  44. data/lib/yasminaai/ot_ps/client.rb +79 -0
  45. data/lib/yasminaai/ot_ps/types/post_issue_otp_request.rb +21 -0
  46. data/lib/yasminaai/ot_ps/types/post_quote_otp_request.rb +15 -0
  47. data/lib/yasminaai/policies/client.rb +144 -0
  48. data/lib/yasminaai/policies/types/get_policies_car_policy_request.rb +11 -0
  49. data/lib/yasminaai/policies/types/get_policies_request.rb +35 -0
  50. data/lib/yasminaai/policies/types/post_policies_request.rb +21 -0
  51. data/lib/yasminaai/quotes/client.rb +164 -0
  52. data/lib/yasminaai/quotes/types/delete_quote_requests_id_request.rb +11 -0
  53. data/lib/yasminaai/quotes/types/delete_quote_requests_id_response.rb +11 -0
  54. data/lib/yasminaai/quotes/types/get_quote_requests_id_request.rb +11 -0
  55. data/lib/yasminaai/quotes/types/get_quote_requests_request.rb +17 -0
  56. data/lib/yasminaai/quotes/types/post_quote_requests_request.rb +37 -0
  57. data/lib/yasminaai/quotes/types/post_quote_requests_request_accept_language.rb +13 -0
  58. data/lib/yasminaai/quotes/types/post_quote_requests_request_drivers_item.rb +15 -0
  59. data/lib/yasminaai/types/bad_request_error_body.rb +11 -0
  60. data/lib/yasminaai/types/benefit.rb +21 -0
  61. data/lib/yasminaai/types/company_quote.rb +25 -0
  62. data/lib/yasminaai/types/company_quote_type.rb +12 -0
  63. data/lib/yasminaai/types/error.rb +11 -0
  64. data/lib/yasminaai/types/paginated_policy_response.rb +35 -0
  65. data/lib/yasminaai/types/paginated_quote_response.rb +35 -0
  66. data/lib/yasminaai/types/pagination_link.rb +13 -0
  67. data/lib/yasminaai/types/policy.rb +39 -0
  68. data/lib/yasminaai/types/policy_aggregates.rb +14 -0
  69. data/lib/yasminaai/types/policy_month_aggregate.rb +11 -0
  70. data/lib/yasminaai/types/quote_price.rb +19 -0
  71. data/lib/yasminaai/types/quote_request_aggregates.rb +12 -0
  72. data/lib/yasminaai/types/quote_response.rb +37 -0
  73. data/lib/yasminaai/types/quote_response_drivers_item.rb +13 -0
  74. data/lib/yasminaai/types/quote_response_quotes_item.rb +25 -0
  75. data/lib/yasminaai/types/quote_response_quotes_item_type.rb +12 -0
  76. data/lib/yasminaai/types/unauthorized_error_body.rb +11 -0
  77. data/lib/yasminaai/version.rb +5 -0
  78. data/lib/yasminaai.rb +72 -0
  79. data/reference.md +872 -0
  80. metadata +121 -0
@@ -0,0 +1,141 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Yasminaai
4
+ module Internal
5
+ module Multipart
6
+ # Encodes parameters into a `multipart/form-data` payload as described by RFC
7
+ # 2388:
8
+ #
9
+ # https://tools.ietf.org/html/rfc2388
10
+ #
11
+ # This is most useful for transferring file-like objects.
12
+ #
13
+ # Parameters should be added with `#encode`. When ready, use `#body` to get
14
+ # the encoded result and `#content_type` to get the value that should be
15
+ # placed in the `Content-Type` header of a subsequent request (which includes
16
+ # a boundary value).
17
+ #
18
+ # This abstraction is heavily inspired by Stripe's multipart/form-data implementation,
19
+ # which can be found here:
20
+ #
21
+ # https://github.com/stripe/stripe-ruby/blob/ca00b676f04ac421cf5cb5ff0325f243651677b6/lib/stripe/multipart_encoder.rb#L18
22
+ #
23
+ # @api private
24
+ class Encoder
25
+ CONTENT_TYPE = "multipart/form-data"
26
+ CRLF = "\r\n"
27
+
28
+ attr_reader :boundary, :body
29
+
30
+ def initialize
31
+ # Chose the same number of random bytes that Go uses in its standard
32
+ # library implementation. Easily enough entropy to ensure that it won't
33
+ # be present in a file we're sending.
34
+ @boundary = SecureRandom.hex(30)
35
+
36
+ @body = String.new
37
+ @closed = false
38
+ @first_field = true
39
+ end
40
+
41
+ # Gets the content type string including the boundary.
42
+ #
43
+ # @return [String] The content type with boundary
44
+ def content_type
45
+ "#{CONTENT_TYPE}; boundary=#{@boundary}"
46
+ end
47
+
48
+ # Encode the given FormData object into a multipart/form-data payload.
49
+ #
50
+ # @param form_data [FormData] The form data to encode
51
+ # @return [String] The encoded body.
52
+ def encode(form_data)
53
+ return "" if form_data.parts.empty?
54
+
55
+ form_data.parts.each do |part|
56
+ write_part(part)
57
+ end
58
+ close
59
+
60
+ @body
61
+ end
62
+
63
+ # Writes a FormDataPart to the encoder.
64
+ #
65
+ # @param part [FormDataPart] The part to write
66
+ # @return [nil]
67
+ def write_part(part)
68
+ raise "Cannot write to closed encoder" if @closed
69
+
70
+ write_field(
71
+ name: part.name,
72
+ data: part.contents,
73
+ filename: part.filename,
74
+ headers: part.headers
75
+ )
76
+
77
+ nil
78
+ end
79
+
80
+ # Writes a field to the encoder.
81
+ #
82
+ # @param name [String] The field name
83
+ # @param data [String] The field data
84
+ # @param filename [String, nil] Optional filename
85
+ # @param headers [Hash<String, String>, nil] Optional additional headers
86
+ # @return [nil]
87
+ def write_field(name:, data:, filename: nil, headers: nil)
88
+ raise "Cannot write to closed encoder" if @closed
89
+
90
+ if @first_field
91
+ @first_field = false
92
+ else
93
+ @body << CRLF
94
+ end
95
+
96
+ @body << "--#{@boundary}#{CRLF}"
97
+ @body << %(Content-Disposition: form-data; name="#{escape(name.to_s)}")
98
+ @body << %(; filename="#{escape(filename)}") if filename
99
+ @body << CRLF
100
+
101
+ if headers
102
+ headers.each do |key, value|
103
+ @body << "#{key}: #{value}#{CRLF}"
104
+ end
105
+ elsif filename
106
+ # Default content type for files.
107
+ @body << "Content-Type: application/octet-stream#{CRLF}"
108
+ end
109
+
110
+ @body << CRLF
111
+ @body << data.to_s
112
+
113
+ nil
114
+ end
115
+
116
+ # Finalizes the encoder by writing the final boundary.
117
+ #
118
+ # @return [nil]
119
+ def close
120
+ raise "Encoder already closed" if @closed
121
+
122
+ @body << CRLF
123
+ @body << "--#{@boundary}--"
124
+ @closed = true
125
+
126
+ nil
127
+ end
128
+
129
+ private
130
+
131
+ # Escapes quotes for use in header values and replaces line breaks with spaces.
132
+ #
133
+ # @param str [String] The string to escape
134
+ # @return [String] The escaped string
135
+ def escape(str)
136
+ str.to_s.gsub('"', "%22").tr("\n", " ").tr("\r", " ")
137
+ end
138
+ end
139
+ end
140
+ end
141
+ end
@@ -0,0 +1,78 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Yasminaai
4
+ module Internal
5
+ module Multipart
6
+ # @api private
7
+ class FormData
8
+ # @return [Array<FormDataPart>] The parts in this multipart form data.
9
+ attr_reader :parts
10
+
11
+ # @return [Encoder] The encoder for this multipart form data.
12
+ private attr_reader :encoder
13
+
14
+ def initialize
15
+ @encoder = Encoder.new
16
+ @parts = []
17
+ end
18
+
19
+ # Adds a new part to the multipart form data.
20
+ #
21
+ # @param name [String] The name of the form field
22
+ # @param value [String, Integer, Float, Boolean, #read] The value of the field
23
+ # @param content_type [String, nil] Optional content type
24
+ # @return [self] Returns self for chaining
25
+ def add(name:, value:, content_type: nil)
26
+ headers = content_type ? { "Content-Type" => content_type } : nil
27
+ add_part(FormDataPart.new(name:, value:, headers:))
28
+ end
29
+
30
+ # Adds a file to the multipart form data.
31
+ #
32
+ # @param name [String] The name of the form field
33
+ # @param file [#read] The file or readable object
34
+ # @param filename [String, nil] Optional filename (defaults to basename of path for File objects)
35
+ # @param content_type [String, nil] Optional content type (e.g. "image/png")
36
+ # @return [self] Returns self for chaining
37
+ def add_file(name:, file:, filename: nil, content_type: nil)
38
+ headers = content_type ? { "Content-Type" => content_type } : nil
39
+ filename ||= filename_for(file)
40
+ add_part(FormDataPart.new(name:, value: file, filename:, headers:))
41
+ end
42
+
43
+ # Adds a pre-created part to the multipart form data.
44
+ #
45
+ # @param part [FormDataPart] The part to add
46
+ # @return [self] Returns self for chaining
47
+ def add_part(part)
48
+ @parts << part
49
+ self
50
+ end
51
+
52
+ # Gets the content type string including the boundary.
53
+ #
54
+ # @return [String] The content type with boundary.
55
+ def content_type
56
+ @encoder.content_type
57
+ end
58
+
59
+ # Encode the multipart form data into a multipart/form-data payload.
60
+ #
61
+ # @return [String] The encoded body.
62
+ def encode
63
+ @encoder.encode(self)
64
+ end
65
+
66
+ private
67
+
68
+ def filename_for(file)
69
+ if file.is_a?(::File) || file.respond_to?(:path)
70
+ ::File.basename(file.path)
71
+ elsif file.respond_to?(:name)
72
+ file.name
73
+ end
74
+ end
75
+ end
76
+ end
77
+ end
78
+ end
@@ -0,0 +1,51 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "securerandom"
4
+
5
+ module Yasminaai
6
+ module Internal
7
+ module Multipart
8
+ # @api private
9
+ class FormDataPart
10
+ attr_reader :name, :contents, :filename, :headers
11
+
12
+ # @param name [String] The name of the form field
13
+ # @param value [String, Integer, Float, Boolean, File, #read] The value of the field
14
+ # @param filename [String, nil] Optional filename for file uploads
15
+ # @param headers [Hash<String, String>, nil] Optional additional headers
16
+ def initialize(name:, value:, filename: nil, headers: nil)
17
+ @name = name
18
+ @contents = convert_to_content(value)
19
+ @filename = filename
20
+ @headers = headers
21
+ end
22
+
23
+ # Converts the part to a hash suitable for serialization.
24
+ #
25
+ # @return [Hash] A hash representation of the part
26
+ def to_hash
27
+ result = {
28
+ name: @name,
29
+ contents: @contents
30
+ }
31
+ result[:filename] = @filename if @filename
32
+ result[:headers] = @headers if @headers
33
+ result
34
+ end
35
+
36
+ private
37
+
38
+ # Converts various types of values to a content representation
39
+ # @param value [String, Integer, Float, Boolean, #read] The value to convert
40
+ # @return [String] The string representation of the value
41
+ def convert_to_content(value)
42
+ if value.respond_to?(:read)
43
+ value.read
44
+ else
45
+ value.to_s
46
+ end
47
+ end
48
+ end
49
+ end
50
+ end
51
+ end
@@ -0,0 +1,40 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Yasminaai
4
+ module Internal
5
+ module Multipart
6
+ # @api private
7
+ class Request < Yasminaai::Internal::Http::BaseRequest
8
+ attr_reader :body
9
+
10
+ # @param base_url [String] The base URL for the request
11
+ # @param path [String] The path for the request
12
+ # @param method [Symbol] The HTTP method for the request (:get, :post, etc.)
13
+ # @param headers [Hash] Additional headers for the request (optional)
14
+ # @param query [Hash] Query parameters for the request (optional)
15
+ # @param body [MultipartFormData, nil] The multipart form data for the request (optional)
16
+ # @param request_options [Yasminaai::RequestOptions, Hash{Symbol=>Object}, nil]
17
+ def initialize(base_url:, path:, method:, headers: {}, query: {}, body: nil, request_options: {})
18
+ super(base_url:, path:, method:, headers:, query:, request_options:)
19
+
20
+ @body = body
21
+ end
22
+
23
+ # @return [Hash] The encoded HTTP request headers.
24
+ # @param protected_keys [Array<String>] Header keys set by the SDK client (e.g. auth, metadata)
25
+ # that must not be overridden by additional_headers from request_options.
26
+ def encode_headers(protected_keys: [])
27
+ sdk_headers = {
28
+ "Content-Type" => @body.content_type
29
+ }.merge(@headers)
30
+ merge_additional_headers(sdk_headers, protected_keys:)
31
+ end
32
+
33
+ # @return [String, nil] The encoded HTTP request body.
34
+ def encode_body
35
+ @body&.encode
36
+ end
37
+ end
38
+ end
39
+ end
40
+ end
@@ -0,0 +1,47 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Yasminaai
4
+ module Internal
5
+ module Types
6
+ # An array of a specific type
7
+ class Array
8
+ include Yasminaai::Internal::Types::Type
9
+
10
+ attr_reader :type
11
+
12
+ class << self
13
+ # Instantiates a new `Array` of a given type
14
+ #
15
+ # @param type [Object] The member type of this array
16
+ #
17
+ # @return [Yasminaai::Internal::Types::Array]
18
+ def [](type)
19
+ new(type)
20
+ end
21
+ end
22
+
23
+ # @api private
24
+ def initialize(type)
25
+ @type = type
26
+ end
27
+
28
+ # Coerces a value into this array
29
+ #
30
+ # @param value [Object]
31
+ # @option strict [Boolean]
32
+ # @return [::Array]
33
+ def coerce(value, strict: strict?)
34
+ unless value.is_a?(::Array)
35
+ raise Errors::TypeError, "cannot coerce `#{value.class}` to Array<#{type}>" if strict
36
+
37
+ return value
38
+ end
39
+
40
+ value.map do |element|
41
+ Utils.coerce(type, element, strict: strict)
42
+ end
43
+ end
44
+ end
45
+ end
46
+ end
47
+ end
@@ -0,0 +1,34 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Yasminaai
4
+ module Internal
5
+ module Types
6
+ module Boolean
7
+ extend Yasminaai::Internal::Types::Union
8
+
9
+ member TrueClass
10
+ member FalseClass
11
+
12
+ # Overrides the base coercion method for enums to allow integer and string values to become booleans
13
+ #
14
+ # @param value [Object]
15
+ # @option strict [Boolean]
16
+ # @return [Object]
17
+ def self.coerce(value, strict: strict?)
18
+ case value
19
+ when TrueClass, FalseClass
20
+ return value
21
+ when Integer
22
+ return value == 1
23
+ when String
24
+ return %w[1 true].include?(value)
25
+ end
26
+
27
+ raise Errors::TypeError, "cannot coerce `#{value.class}` to Boolean" if strict
28
+
29
+ value
30
+ end
31
+ end
32
+ end
33
+ end
34
+ end
@@ -0,0 +1,56 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Yasminaai
4
+ module Internal
5
+ module Types
6
+ # Module for defining enums
7
+ module Enum
8
+ include Type
9
+
10
+ # @api private
11
+ #
12
+ # @return [Array<Object>]
13
+ def values
14
+ @values ||= constants.map { |c| const_get(c) }
15
+ end
16
+
17
+ # @api private
18
+ def finalize!
19
+ values
20
+ end
21
+
22
+ # @api private
23
+ def strict?
24
+ @strict ||= false
25
+ end
26
+
27
+ # @api private
28
+ def strict!
29
+ @strict = true
30
+ end
31
+
32
+ def coerce(value, strict: strict?)
33
+ coerced_value = Utils.coerce(Symbol, value)
34
+
35
+ return coerced_value if values.include?(coerced_value)
36
+
37
+ raise Errors::TypeError, "`#{value}` not in enum #{self}" if strict
38
+
39
+ value
40
+ end
41
+
42
+ # Parse JSON string and coerce to the enum value
43
+ #
44
+ # @param str [String] JSON string to parse
45
+ # @return [String] The enum value
46
+ def load(str)
47
+ coerce(::JSON.parse(str))
48
+ end
49
+
50
+ def inspect
51
+ "#{name}[#{values.join(", ")}]"
52
+ end
53
+ end
54
+ end
55
+ end
56
+ end
@@ -0,0 +1,36 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Yasminaai
4
+ module Internal
5
+ module Types
6
+ class Hash
7
+ include Type
8
+
9
+ attr_reader :key_type, :value_type
10
+
11
+ class << self
12
+ def [](key_type, value_type)
13
+ new(key_type, value_type)
14
+ end
15
+ end
16
+
17
+ def initialize(key_type, value_type)
18
+ @key_type = key_type
19
+ @value_type = value_type
20
+ end
21
+
22
+ def coerce(value, strict: strict?)
23
+ unless value.is_a?(::Hash)
24
+ raise Errors::TypeError, "not hash" if strict
25
+
26
+ return value
27
+ end
28
+
29
+ value.to_h do |k, v|
30
+ [Utils.coerce(key_type, k, strict: strict), Utils.coerce(value_type, v, strict: strict)]
31
+ end
32
+ end
33
+ end
34
+ end
35
+ end
36
+ end
@@ -0,0 +1,38 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Yasminaai
4
+ module Internal
5
+ module Types
6
+ class Model
7
+ # Definition of a field on a model
8
+ class Field
9
+ SENSITIVE_FIELD_NAMES = %i[
10
+ password secret token api_key apikey access_token refresh_token
11
+ client_secret client_id credential bearer authorization
12
+ ].freeze
13
+
14
+ attr_reader :name, :type, :optional, :nullable, :api_name, :value, :default
15
+
16
+ def initialize(name:, type:, optional: false, nullable: false, api_name: nil, value: nil, default: nil)
17
+ @name = name.to_sym
18
+ @type = type
19
+ @optional = optional
20
+ @nullable = nullable
21
+ @api_name = api_name || name.to_s
22
+ @value = value
23
+ @default = default
24
+ end
25
+
26
+ def literal?
27
+ !value.nil?
28
+ end
29
+
30
+ def sensitive?
31
+ SENSITIVE_FIELD_NAMES.include?(@name) ||
32
+ SENSITIVE_FIELD_NAMES.any? { |sensitive| @name.to_s.include?(sensitive.to_s) }
33
+ end
34
+ end
35
+ end
36
+ end
37
+ end
38
+ end