apigratis-sdk-ruby 0.0.1

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 (45) hide show
  1. checksums.yaml +7 -0
  2. data/CHANGELOG.md +27 -0
  3. data/LICENSE +21 -0
  4. data/README.md +330 -0
  5. data/SECURITY.md +32 -0
  6. data/lib/api_brasil/client.rb +252 -0
  7. data/lib/api_brasil/core/env.rb +34 -0
  8. data/lib/api_brasil/core/errors.rb +167 -0
  9. data/lib/api_brasil/core/http_client.rb +342 -0
  10. data/lib/api_brasil/core/retry.rb +69 -0
  11. data/lib/api_brasil/core/transport/faraday_transport.rb +76 -0
  12. data/lib/api_brasil/core/transport/net_http_transport.rb +126 -0
  13. data/lib/api_brasil/core/transport.rb +114 -0
  14. data/lib/api_brasil/generated/catalog.rb +526 -0
  15. data/lib/api_brasil/legacy/service.rb +155 -0
  16. data/lib/api_brasil/services/base_service.rb +49 -0
  17. data/lib/api_brasil/services/data/bulk_service.rb +26 -0
  18. data/lib/api_brasil/services/data/cep_service.rb +58 -0
  19. data/lib/api_brasil/services/data/chip_virtual_service.rb +40 -0
  20. data/lib/api_brasil/services/data/consulta_service.rb +97 -0
  21. data/lib/api_brasil/services/data/correios_service.rb +23 -0
  22. data/lib/api_brasil/services/data/dados_service.rb +30 -0
  23. data/lib/api_brasil/services/data/database_ip_service.rb +19 -0
  24. data/lib/api_brasil/services/data/fipe_service.rb +61 -0
  25. data/lib/api_brasil/services/data/proxies.rb +146 -0
  26. data/lib/api_brasil/services/data/ura_service.rb +26 -0
  27. data/lib/api_brasil/services/data/vehicles_service.rb +46 -0
  28. data/lib/api_brasil/services/device_proxy_service.rb +46 -0
  29. data/lib/api_brasil/services/messaging/evolution_service.rb +38 -0
  30. data/lib/api_brasil/services/messaging/sms_service.rb +40 -0
  31. data/lib/api_brasil/services/messaging/whats_meow_service.rb +30 -0
  32. data/lib/api_brasil/services/messaging/whatsapp_service.rb +120 -0
  33. data/lib/api_brasil/services/platform/account_service.rb +138 -0
  34. data/lib/api_brasil/services/platform/auth_service.rb +204 -0
  35. data/lib/api_brasil/services/platform/bearer_rate_limit_service.rb +29 -0
  36. data/lib/api_brasil/services/platform/catalog_service.rb +111 -0
  37. data/lib/api_brasil/services/platform/devices_service.rb +73 -0
  38. data/lib/api_brasil/services/platform/ip_whitelist_service.rb +73 -0
  39. data/lib/api_brasil/services/platform/payments_service.rb +124 -0
  40. data/lib/api_brasil/services/platform/reports_service.rb +96 -0
  41. data/lib/api_brasil/version.rb +6 -0
  42. data/lib/api_brasil.rb +72 -0
  43. data/lib/apigratis-sdk-ruby.rb +5 -0
  44. data/lib/apigratis.rb +11 -0
  45. metadata +149 -0
@@ -0,0 +1,126 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "net/http"
4
+ require "openssl"
5
+ require "timeout"
6
+ require "uri"
7
+ require "json"
8
+
9
+ module ApiBrasil
10
+ module Core
11
+ module Transport
12
+ # Transporte padrao, sem dependencias: usa apenas `net/http` da stdlib.
13
+ class NetHttpTransport < Base
14
+ # Verbos suportados -> classe de requisicao do `net/http`.
15
+ METHODS = {
16
+ "GET" => Net::HTTP::Get,
17
+ "HEAD" => Net::HTTP::Head,
18
+ "POST" => Net::HTTP::Post,
19
+ "PUT" => Net::HTTP::Put,
20
+ "PATCH" => Net::HTTP::Patch,
21
+ "DELETE" => Net::HTTP::Delete
22
+ }.freeze
23
+
24
+ # Limite de redirecionamentos seguidos automaticamente.
25
+ MAX_REDIRECTS = 5
26
+
27
+ # Erros de conexao tratados como `NetworkError`.
28
+ NETWORK_ERRORS = [
29
+ SocketError,
30
+ IOError,
31
+ SystemCallError,
32
+ OpenSSL::SSL::SSLError,
33
+ Net::HTTPBadResponse,
34
+ Net::ProtocolError
35
+ ].freeze
36
+
37
+ # @param options [Hash] opcoes extras do `Net::HTTP`
38
+ # (ex: `proxy_address`, `proxy_port`, `verify_mode`, `ca_file`)
39
+ def initialize(options = {})
40
+ super()
41
+ @options = options || {}
42
+ end
43
+
44
+ # @param request [Request]
45
+ # @return [Response]
46
+ def request(request)
47
+ perform(request, request.url, MAX_REDIRECTS)
48
+ end
49
+
50
+ private
51
+
52
+ def perform(request, url, redirects_left)
53
+ uri = URI.parse(url)
54
+ response = execute(request, uri)
55
+
56
+ if redirect?(response.code.to_i) && redirects_left.positive?
57
+ location = response["location"]
58
+ return perform(request, URI.join(url, location).to_s, redirects_left - 1) if location
59
+ end
60
+
61
+ Response.new(
62
+ response.code.to_i,
63
+ normalize_headers(response),
64
+ Transport.decode_body(request, response.body)
65
+ )
66
+ end
67
+
68
+ def execute(request, uri)
69
+ http = build_http(uri, request.timeout_ms)
70
+ http.request(build_net_request(request, uri))
71
+ rescue Timeout::Error => e # Net::OpenTimeout, Net::ReadTimeout e Net::WriteTimeout herdam daqui
72
+ raise Errors::TimeoutError.new(
73
+ "Tempo limite de #{request.timeout_ms.to_i}ms excedido em #{request.method} #{uri}.",
74
+ previous: e
75
+ )
76
+ rescue *NETWORK_ERRORS => e
77
+ raise Errors::NetworkError.new(
78
+ "Falha de rede em #{request.method} #{uri}: #{e.message}",
79
+ previous: e
80
+ )
81
+ end
82
+
83
+ def build_http(uri, timeout_ms)
84
+ # `:ENV` mantem o comportamento padrao de respeitar http_proxy/https_proxy.
85
+ proxy_address = @options.key?(:proxy_address) ? @options[:proxy_address] : :ENV
86
+ http = Net::HTTP.new(uri.host, uri.port, proxy_address, @options[:proxy_port],
87
+ @options[:proxy_user], @options[:proxy_pass])
88
+ http.use_ssl = uri.scheme == "https"
89
+ http.verify_mode = @options[:verify_mode] if @options.key?(:verify_mode)
90
+ http.ca_file = @options[:ca_file] if @options[:ca_file]
91
+
92
+ if timeout_ms.to_i.positive?
93
+ seconds = timeout_ms.to_f / 1000
94
+ http.open_timeout = seconds
95
+ http.read_timeout = seconds
96
+ http.write_timeout = seconds if http.respond_to?(:write_timeout=)
97
+ end
98
+
99
+ http
100
+ end
101
+
102
+ def build_net_request(request, uri)
103
+ klass = METHODS[request.method]
104
+ raise Errors::NetworkError, "Metodo HTTP nao suportado: #{request.method}" if klass.nil?
105
+
106
+ path = uri.request_uri
107
+ net_request = klass.new(path)
108
+ request.headers.each { |name, value| net_request[name.to_s] = value.to_s }
109
+ net_request.body = request.body unless request.body.nil?
110
+
111
+ net_request
112
+ end
113
+
114
+ def redirect?(status)
115
+ [301, 302, 303, 307, 308].include?(status)
116
+ end
117
+
118
+ def normalize_headers(response)
119
+ response.each_header.with_object({}) do |(name, value), acc|
120
+ acc[name.to_s.downcase] = value
121
+ end
122
+ end
123
+ end
124
+ end
125
+ end
126
+ end
@@ -0,0 +1,114 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "json"
4
+
5
+ require_relative "errors"
6
+
7
+ module ApiBrasil
8
+ module Core
9
+ # Camada de transporte HTTP da SDK. A implementacao padrao usa a stdlib
10
+ # (`NetHttpTransport`), com uso automatico do Faraday quando ele ja esta
11
+ # carregado no processo (`FaradayTransport`); injete a sua para usar
12
+ # proxies, outro cliente HTTP, mocks de teste etc.
13
+ #
14
+ # Contrato: retorna a resposta para QUALQUER status HTTP; lanca
15
+ # `NetworkError`/`TimeoutError` apenas quando nao houve resposta.
16
+ module Transport
17
+ # Requisicao entregue a camada de transporte - ja com URL absoluta,
18
+ # headers montados e corpo serializado.
19
+ class Request
20
+ # @return [String] verbo HTTP em maiusculas
21
+ attr_reader :method
22
+
23
+ # @return [String] URL absoluta
24
+ attr_reader :url
25
+
26
+ # @return [Hash{String => String}]
27
+ attr_reader :headers
28
+
29
+ # @return [String, nil] corpo ja serializado (JSON)
30
+ attr_reader :body
31
+
32
+ # @return [Integer, nil] timeout em milissegundos
33
+ attr_reader :timeout_ms
34
+
35
+ # @return [String, nil] `json` (padrao), `raw`/`arraybuffer` ou `stream`
36
+ attr_reader :response_type
37
+
38
+ def initialize(method, url, headers: {}, body: nil, timeout_ms: nil, response_type: nil)
39
+ @method = method.to_s.upcase
40
+ @url = url
41
+ @headers = headers || {}
42
+ @body = body
43
+ @timeout_ms = timeout_ms
44
+ @response_type = response_type
45
+ end
46
+ end
47
+
48
+ # Resposta devolvida pela camada de transporte.
49
+ class Response
50
+ # @return [Integer]
51
+ attr_reader :status
52
+
53
+ # @return [Hash{String => String}] headers com nomes em minusculas
54
+ attr_reader :headers
55
+
56
+ # @return [Object] corpo ja decodificado (JSON -> Hash; texto; binario)
57
+ attr_reader :data
58
+
59
+ def initialize(status, headers = {}, data = nil)
60
+ @status = status
61
+ @headers = headers || {}
62
+ @data = data
63
+ end
64
+ end
65
+
66
+ # Interface do transporte. Implemente `#request` recebendo um
67
+ # `Transport::Request` e devolvendo um `Transport::Response`.
68
+ class Base
69
+ # @param _request [Request]
70
+ # @return [Response]
71
+ def request(_request)
72
+ raise NotImplementedError, "#{self.class}#request precisa ser implementado."
73
+ end
74
+ end
75
+
76
+ # Tipos de resposta que nao devem ser decodificados como JSON.
77
+ RAW_RESPONSE_TYPES = %w[raw arraybuffer stream].freeze
78
+
79
+ module_function
80
+
81
+ # Transporte padrao: Faraday quando ja carregado, senao `net/http`.
82
+ #
83
+ # @return [Base]
84
+ def default
85
+ return FaradayTransport.new if defined?(::Faraday)
86
+
87
+ NetHttpTransport.new
88
+ end
89
+
90
+ # Decodifica o corpo conforme o `response_type` pedido.
91
+ #
92
+ # @param request [Request]
93
+ # @param raw [String, nil]
94
+ # @return [Object, nil]
95
+ def decode_body(request, raw)
96
+ return raw if RAW_RESPONSE_TYPES.include?(request.response_type)
97
+ return nil if raw.nil? || raw.empty?
98
+
99
+ begin
100
+ JSON.parse(raw)
101
+ rescue JSON::ParserError
102
+ raw
103
+ end
104
+ end
105
+ end
106
+
107
+ # Aliases com os mesmos nomes usados nas SDKs PHP/Node/Go/Dart.
108
+ TransportRequest = Transport::Request
109
+ TransportResponse = Transport::Response
110
+ end
111
+ end
112
+
113
+ require_relative "transport/net_http_transport"
114
+ require_relative "transport/faraday_transport"