memori-client 0.1.9 → 0.2.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 (102) hide show
  1. checksums.yaml +4 -4
  2. data/backend_overrides.jsonc +4 -0
  3. data/engine_overrides.jsonc +3 -0
  4. data/lib/memori_client/client.rb +49 -0
  5. data/lib/memori_client/client_factory.rb +105 -0
  6. data/lib/memori_client/engine/hmac_helper.rb +1 -1
  7. data/lib/memori_client/http_client.rb +4 -17
  8. data/lib/memori_client/operation.rb +132 -0
  9. data/lib/memori_client/proxy/client.rb +115 -0
  10. data/lib/memori_client/resource.rb +174 -26
  11. data/lib/memori_client/resource_proxy.rb +25 -0
  12. data/lib/memori_client/response.rb +48 -0
  13. data/lib/memori_client/swagger/get_module_and_method.rb +44 -0
  14. data/lib/memori_client/swagger/process_specification.rb +127 -0
  15. data/lib/memori_client/swagger/schema_store.rb +26 -0
  16. data/lib/memori_client.rb +14 -42
  17. data/lib/tasks/memori_client.rake +0 -7
  18. metadata +17 -90
  19. data/doc/MemoriClient::Backend::V1::Asset.md +0 -117
  20. data/doc/MemoriClient::Backend::V2::ActionLog.md +0 -37
  21. data/doc/MemoriClient::Backend::V2::Analysis.md +0 -39
  22. data/doc/MemoriClient::Backend::V2::Asset.md +0 -102
  23. data/doc/MemoriClient::Backend::V2::Badge.md +0 -64
  24. data/doc/MemoriClient::Backend::V2::CompletionConfig.md +0 -115
  25. data/doc/MemoriClient::Backend::V2::ConsumptionLog.md +0 -57
  26. data/doc/MemoriClient::Backend::V2::ImportExport.md +0 -180
  27. data/doc/MemoriClient::Backend::V2::Integration.md +0 -117
  28. data/doc/MemoriClient::Backend::V2::Invitation.md +0 -179
  29. data/doc/MemoriClient::Backend::V2::Memori.md +0 -394
  30. data/doc/MemoriClient::Backend::V2::MemoriList.md +0 -147
  31. data/doc/MemoriClient::Backend::V2::Notification.md +0 -31
  32. data/doc/MemoriClient::Backend::V2::Process.md +0 -64
  33. data/doc/MemoriClient::Backend::V2::Tenant.md +0 -142
  34. data/doc/MemoriClient::Backend::V2::User.md +0 -647
  35. data/doc/MemoriClient::Engine::V2::ChatLog.md +0 -82
  36. data/doc/MemoriClient::Engine::V2::ContextVar.md +0 -46
  37. data/doc/MemoriClient::Engine::V2::CorrelationPair.md +0 -72
  38. data/doc/MemoriClient::Engine::V2::CustomDictionary.md +0 -108
  39. data/doc/MemoriClient::Engine::V2::Dialog.md +0 -152
  40. data/doc/MemoriClient::Engine::V2::EventLog.md +0 -85
  41. data/doc/MemoriClient::Engine::V2::ExpertReference.md +0 -116
  42. data/doc/MemoriClient::Engine::V2::Function.md +0 -140
  43. data/doc/MemoriClient::Engine::V2::Intent.md +0 -225
  44. data/doc/MemoriClient::Engine::V2::LocalizationKey.md +0 -105
  45. data/doc/MemoriClient::Engine::V2::Medium.md +0 -118
  46. data/doc/MemoriClient::Engine::V2::Memory.md +0 -244
  47. data/doc/MemoriClient::Engine::V2::NLP.md +0 -100
  48. data/doc/MemoriClient::Engine::V2::Person.md +0 -114
  49. data/doc/MemoriClient::Engine::V2::Search.md +0 -151
  50. data/doc/MemoriClient::Engine::V2::Session.md +0 -55
  51. data/doc/MemoriClient::Engine::V2::Stat.md +0 -18
  52. data/doc/MemoriClient::Engine::V2::Topic.md +0 -80
  53. data/doc/MemoriClient::Engine::V2::UnansweredQuestion.md +0 -75
  54. data/doc/MemoriClient::Engine::V2::User.md +0 -140
  55. data/doc/MemoriClient::Engine::V2::WebHook.md +0 -67
  56. data/lib/memori_client/backend/resource.rb +0 -39
  57. data/lib/memori_client/backend/resources.rb +0 -16
  58. data/lib/memori_client/backend/v1/asset.rb +0 -120
  59. data/lib/memori_client/backend/v2/action_log.rb +0 -44
  60. data/lib/memori_client/backend/v2/analysis.rb +0 -54
  61. data/lib/memori_client/backend/v2/asset.rb +0 -130
  62. data/lib/memori_client/backend/v2/badge.rb +0 -77
  63. data/lib/memori_client/backend/v2/completion_config.rb +0 -202
  64. data/lib/memori_client/backend/v2/consumption_log.rb +0 -70
  65. data/lib/memori_client/backend/v2/import_export.rb +0 -327
  66. data/lib/memori_client/backend/v2/integration.rb +0 -180
  67. data/lib/memori_client/backend/v2/invitation.rb +0 -252
  68. data/lib/memori_client/backend/v2/memori.rb +0 -954
  69. data/lib/memori_client/backend/v2/memori_list.rb +0 -152
  70. data/lib/memori_client/backend/v2/notification.rb +0 -32
  71. data/lib/memori_client/backend/v2/process.rb +0 -70
  72. data/lib/memori_client/backend/v2/tenant.rb +0 -293
  73. data/lib/memori_client/backend/v2/user.rb +0 -1520
  74. data/lib/memori_client/configuration.rb +0 -20
  75. data/lib/memori_client/engine/resource.rb +0 -13
  76. data/lib/memori_client/engine/resources.rb +0 -21
  77. data/lib/memori_client/engine/v2/chat_log.rb +0 -92
  78. data/lib/memori_client/engine/v2/completion_log.rb +0 -17
  79. data/lib/memori_client/engine/v2/context_var.rb +0 -48
  80. data/lib/memori_client/engine/v2/correlation_pair.rb +0 -99
  81. data/lib/memori_client/engine/v2/custom_dictionary.rb +0 -152
  82. data/lib/memori_client/engine/v2/dialog.rb +0 -223
  83. data/lib/memori_client/engine/v2/event_log.rb +0 -98
  84. data/lib/memori_client/engine/v2/expert_reference.rb +0 -176
  85. data/lib/memori_client/engine/v2/function.rb +0 -220
  86. data/lib/memori_client/engine/v2/intent.rb +0 -336
  87. data/lib/memori_client/engine/v2/localization_key.rb +0 -144
  88. data/lib/memori_client/engine/v2/medium.rb +0 -178
  89. data/lib/memori_client/engine/v2/memori.rb +0 -329
  90. data/lib/memori_client/engine/v2/memory.rb +0 -477
  91. data/lib/memori_client/engine/v2/nlp.rb +0 -137
  92. data/lib/memori_client/engine/v2/person.rb +0 -170
  93. data/lib/memori_client/engine/v2/private/memori.rb +0 -17
  94. data/lib/memori_client/engine/v2/private/memori_block.rb +0 -24
  95. data/lib/memori_client/engine/v2/prompted_question.rb +0 -121
  96. data/lib/memori_client/engine/v2/search.rb +0 -318
  97. data/lib/memori_client/engine/v2/session.rb +0 -80
  98. data/lib/memori_client/engine/v2/stat.rb +0 -20
  99. data/lib/memori_client/engine/v2/topic.rb +0 -88
  100. data/lib/memori_client/engine/v2/unanswered_question.rb +0 -108
  101. data/lib/memori_client/engine/v2/user.rb +0 -152
  102. data/lib/memori_client/engine/v2/web_hook.rb +0 -128
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 2514386c5093864c79a74f317030cf2ab058fbd41a3337decfc5415d8a3182b4
4
- data.tar.gz: e33a09045201dbd2ceea70acf767e73037f368de5223a157b99c1959bd4b7406
3
+ metadata.gz: 7592af5e2d26be8087d2a19c7e5159a4fabbecc4c009975ccbd9578281ab26be
4
+ data.tar.gz: ed1fbe1cbc4af3d2013ec9ea40c9b67bb7a3bd4058dbd7cd220750ff95797368
5
5
  SHA512:
6
- metadata.gz: 258e0813e4c0998df0e1f746d02984a55eb249de7adec552ccedec1b6eb3b906e0e7b43834659e099ec0268891adc6c6914bf7050737f021e7e84e8c3a0207a3
7
- data.tar.gz: '0795c94a010caac4a6697eb1d8833b852eff369e00ee00dab0f2c74d95b8ed980d322f614fd655ee092e059499087d36a9312becefa749071c37ae0cf6f23f38'
6
+ metadata.gz: da3adc611208ccb5ca49c04b5734b9c43e97679956341552a9af2f4f080db316203ad5b4a8ba476a02b1f0ea7c377526dc9435f4cd62b47d2cd7ec30e00ebcf0
7
+ data.tar.gz: f114260a0ee34f9b6085b60201df408419ba554978d83af9e21ee0c329a40cc58364e158f3628ec83ce1ad519d82d592ad729e1eb13e312ab036976924230c1b
@@ -0,0 +1,4 @@
1
+ {
2
+ // TODO: remove
3
+ "get /api/v2/Tenant/{tenantName}": "MemoriClient::Backend::V2::Tenant#get_public_tenant"
4
+ }
@@ -0,0 +1,3 @@
1
+ {
2
+
3
+ }
@@ -0,0 +1,49 @@
1
+ require 'pry'
2
+ class MemoriClient::Client
3
+ attr_reader :version_proxies
4
+ attr_reader :namespace
5
+ attr_reader :kind
6
+ def initialize(namespace:, kind:, uri:, api_root:)
7
+ @namespace = namespace
8
+ @kind = kind
9
+ @uri = uri
10
+ @api_root = api_root
11
+ @version_proxies = {}
12
+ end
13
+
14
+ def load_swagger_spec
15
+ if @swagger.nil?
16
+ @swagger = MemoriClient::Swagger::ProcessSpecification.new(uri: @uri, kind: @kind).call
17
+ @swagger.each do |key, list|
18
+ register_resource(key, list)
19
+ end
20
+ end
21
+ end
22
+
23
+ private
24
+
25
+ def register_resource(key, list)
26
+ _, _, version, klass = key.split('::')
27
+ version.downcase!
28
+ klass = klass.underscore
29
+ if @version_proxies[version].nil?
30
+ version_proxy = MemoriClient::ResourceProxy.new(api_root: @api_root, version: version)
31
+ @version_proxies[version] = version_proxy
32
+ else
33
+ version_proxy = @version_proxies[version]
34
+ end
35
+
36
+ resource = version_proxy.register_resource(klass)
37
+ list.each do |item|
38
+ resource.register_operation(item)
39
+ end
40
+ end
41
+
42
+ def method_missing(method, *args, &block)
43
+ if @version_proxies.key?(method.to_s)
44
+ @version_proxies[method.to_s]
45
+ else
46
+ super
47
+ end
48
+ end
49
+ end
@@ -0,0 +1,105 @@
1
+ # frozen_string_literal: true
2
+
3
+ module MemoriClient
4
+ # ClientFactory is a singleton class responsible for creating and caching
5
+ # MemoriClient::Client instances for different namespaces and kinds.
6
+ #
7
+ # This factory pattern ensures that only one client instance exists per
8
+ # namespace/kind combination, improving performance and resource usage.
9
+ #
10
+ # @example Basic usage
11
+ # factory = MemoriClient::ClientFactory.instance
12
+ # client = factory.get_client(
13
+ # namespace: 'my_app',
14
+ # kind: MemoriClient::ClientFactory::Kinds::BACKEND,
15
+ # uri: 'https://api.example.com',
16
+ # api_root: '/api/v1'
17
+ # )
18
+ #
19
+ # @since 1.0.0
20
+ class ClientFactory
21
+ include Singleton
22
+
23
+ # Defines the available client kinds that can be created by the factory.
24
+ # Each kind represents a different type of service or API endpoint.
25
+ module Kinds
26
+ # Backend API client for core application services
27
+ BACKEND = 'backend'
28
+
29
+ # Engine API client for processing and analysis services
30
+ ENGINE = 'engine'
31
+ end
32
+
33
+ # Initializes a new ClientFactory instance.
34
+ # Sets up empty hashes to cache backend and engine clients by namespace.
35
+ def initialize
36
+ @backend_clients = {}
37
+ @engine_clients = {}
38
+ end
39
+
40
+ # Gets or creates a cached client instance for the specified parameters.
41
+ #
42
+ # This method implements a lazy initialization pattern where clients are
43
+ # only created when first requested and then cached for subsequent use.
44
+ #
45
+ # @param namespace [String] The namespace identifier for the client.
46
+ # Used as a cache key to ensure unique clients per namespace.
47
+ # @param kind [String] The type of client to create.
48
+ # Must be one of the values defined in {Kinds}.
49
+ # @param uri [String] The base URI for the Swagger specification.
50
+ # @param api_root [String] The API root URL.
51
+ #
52
+ # @return [MemoriClient::Client] A cached or newly created client instance.
53
+ #
54
+ # @raise [RuntimeError] If an invalid kind is provided.
55
+ #
56
+ # @example Get a backend client
57
+ # client = factory.get_client(
58
+ # namespace: 'production',
59
+ # kind: Kinds::BACKEND,
60
+ # uri: 'https://api.memori.ai',
61
+ # api_root: '/api/v1'
62
+ # )
63
+ #
64
+ # @example Get an engine client
65
+ # client = factory.get_client(
66
+ # namespace: 'staging',
67
+ # kind: Kinds::ENGINE,
68
+ # uri: 'https://engine.memori.ai',
69
+ # api_root: '/engine/v1'
70
+ # )
71
+ def get_client(namespace:, kind:, uri:, api_root:)
72
+ # Validate that the provided kind is supported
73
+ raise "Invalid kind: #{kind}" unless known_kinds.include?(kind)
74
+
75
+ case kind
76
+ when Kinds::BACKEND
77
+ # Use memoization to return cached client or create new one
78
+ @backend_clients[namespace] ||= MemoriClient::Client.new(namespace: namespace,
79
+ kind: kind,
80
+ uri: uri,
81
+ api_root: api_root)
82
+ when Kinds::ENGINE
83
+ # Use memoization to return cached client or create new one
84
+ @engine_clients[namespace] ||= MemoriClient::Client.new(namespace: namespace,
85
+ kind: kind,
86
+ uri: uri,
87
+ api_root: api_root)
88
+ end
89
+ end
90
+
91
+ private
92
+
93
+ # Returns an array of all known client kinds.
94
+ #
95
+ # This method dynamically retrieves all constants defined in the Kinds module
96
+ # to provide a list of valid client types for validation.
97
+ #
98
+ # @return [Array<String>] Array of valid client kind strings.
99
+ def known_kinds
100
+ Kinds.constants.map do |k|
101
+ Kernel.const_get "MemoriClient::ClientFactory::Kinds::#{k}"
102
+ end
103
+ end
104
+ end
105
+ end
@@ -8,7 +8,7 @@ class MemoriClient::Engine::HMACHelper
8
8
 
9
9
  def initialize(app_id, key, max_delta_secs = 30)
10
10
  # Check arguments
11
- raise ArgumentError, "HMAC: invalid appID" if app_id.nil?
11
+ raise ArgumentError, "HMAC: invalid appID" if app_id.nil? || app_id <= 0 || app_id == ''
12
12
  raise ArgumentError, "HMAC: invalid key" if key.nil? || key.to_s == "00000000-0000-0000-0000-000000000000"
13
13
 
14
14
  # Initialization
@@ -12,7 +12,7 @@ class MemoriClient::HttpClient
12
12
  request = Net::HTTP::Get.new(uri)
13
13
  headers.each { |k, v| request[k] = v }
14
14
  request["Content-Type"] ||= "application/json" unless headers.key?('Content-Type')
15
- request.basic_auth(*basic_auth) if basic_auth.present?
15
+ request.basic_auth(*basic_auth) if !basic_auth.nil?
16
16
 
17
17
  req_options = { use_ssl: uri.scheme == "https" }
18
18
  response = Net::HTTP.start(uri.hostname, uri.port, req_options) do |http|
@@ -35,6 +35,7 @@ class MemoriClient::HttpClient
35
35
  end
36
36
 
37
37
  def post(url, headers: {}, payload:)
38
+ puts "post #{url}"
38
39
  url = URI(url)
39
40
  https = Net::HTTP.new(url.host, url.port)
40
41
  https.use_ssl = url.scheme == 'https'
@@ -47,6 +48,7 @@ class MemoriClient::HttpClient
47
48
  end
48
49
 
49
50
  def post_file(url, file:)
51
+ puts "post_file #{url}"
50
52
  url = URI(url)
51
53
  https = Net::HTTP.new(url.host, url.port)
52
54
  https.use_ssl = url.scheme == 'https'
@@ -71,21 +73,6 @@ class MemoriClient::HttpClient
71
73
  private
72
74
 
73
75
  def handle_response(response, request)
74
- body = response.read_body
75
-
76
- if request['Content-Type'] == 'application/json'
77
- if body.nil? || body == ''
78
- response_body = {}
79
- else
80
- response_body = JSON.parse(body)
81
- end
82
-
83
- [
84
- response.code,
85
- (body.nil? ? {} : response_body)
86
- ]
87
- else
88
- [response.code, body]
89
- end
76
+ MemoriClient::Response.new(response, request: request)
90
77
  end
91
78
  end
@@ -0,0 +1,132 @@
1
+ module MemoriClient
2
+ class Operation
3
+ def initialize(item, version:, key:)
4
+ @item = item
5
+ @version = version
6
+ @key = key
7
+ end
8
+
9
+ def generate_method_code(method)
10
+ module_name = method[:module]
11
+ method_name = method[:method_name]
12
+ qualified_method = [module_name, method_name].join('#')
13
+
14
+ params_list = []
15
+ (method[:params] || {}).each do |k, required|
16
+ if required
17
+ params_list << "#{k}:"
18
+ else
19
+ params_list << "#{k}: nil"
20
+ end
21
+ end
22
+
23
+ params_definition = (method[:spec]['parameters'] || []).map do |param|
24
+ {
25
+ name: param['name'],
26
+ description: param['description'],
27
+ required: param['required'] == true,
28
+ type: param['schema']['type']
29
+ }
30
+ end
31
+
32
+ payload_keys = []
33
+ payload_required_keys = []
34
+
35
+ if method[:request_body]
36
+ params_list << "payload: {}"
37
+
38
+ params_definition << {
39
+ name: 'payload',
40
+ description: 'request payload',
41
+ required: false,
42
+ type: 'Hash',
43
+ }
44
+
45
+ request_body_schema_ref = method.dig(:spec, 'requestBody', 'content', 'application/json', 'schema', '$ref')
46
+
47
+ # Note:
48
+ # capturing required keys is not exact as sometimes there are two keys where
49
+ # only one must be present or at least one.
50
+ # So we report requirement of the key in the documentation but we do not
51
+ # enforce any check on the presence.
52
+ # We validate the valid key instead
53
+ key = request_body_schema_ref.split('/').last
54
+ schema = MemoriClient::Swagger::SchemaStore.instance.get(key)
55
+ required_keys = schema['required'] || []
56
+ schema['properties'].each do |key, value|
57
+ required = value['nullable'] == false || required_keys.include?(key)
58
+ payload_keys << key
59
+ payload_required_keys << key if required
60
+ params_definition << {
61
+ name: "payload.#{key}",
62
+ description: '',
63
+ required: required,
64
+ type: value['type']&.titleize,
65
+ indent: 2
66
+ }
67
+ end
68
+ end
69
+
70
+ payload_keys.sort!
71
+ payload_required_keys.sort!
72
+ signature = "#{method_name}(#{params_list.join(', ')})"
73
+
74
+ params_list_doc = params_definition.each_with_object([]) do |param, acc|
75
+ if param[:indent]
76
+ prefix = " " * param[:indent]
77
+ else
78
+ prefix = ""
79
+ end
80
+ acc << "#{prefix}- `#{param[:name]}`: **#{param[:type]}** #{param[:description]}. #{param[:required] ? 'required' : 'optional' }"
81
+ end.join("\n")
82
+
83
+ optional_payload_code = ''
84
+ if payload_keys.size > 0
85
+ optional_payload_code = <<-EOS
86
+ payload_keys = [
87
+ #{payload_keys.map { |k| " '#{k}'," }.join("\n") }
88
+ ]
89
+ payload_required_keys = %w[#{payload_required_keys.join(' ')}]
90
+ validate_payload!(args[:payload], keys: payload_keys, required: payload_required_keys)
91
+ EOS
92
+ end
93
+
94
+ output = <<-EOS
95
+ ## #{method_name}
96
+
97
+ Summary:
98
+ #{method[:summary].gsub("\n", ' ').gsub("\r", ' ')}
99
+
100
+ Signature: `#{signature}`
101
+ Invokation: `client.#{@version}.#{@key.downcase}.#{signature}`
102
+
103
+ HTTP API: #{method[:method].upcase} #{method[:path]}`
104
+
105
+ EOS
106
+
107
+ if params_list_doc.size > 0
108
+ output << <<-EOS
109
+ Parameters:
110
+
111
+ #{params_list_doc}
112
+ EOS
113
+ end
114
+
115
+ output << "\n"
116
+
117
+ output
118
+ end
119
+
120
+ def markdown_documentation
121
+ # #{@item[:method_name]}
122
+ #{@item[:path]}
123
+ <<~MARKDOWN
124
+ #{generate_method_code(@item)}
125
+ MARKDOWN
126
+ end
127
+
128
+ def spec
129
+ @item
130
+ end
131
+ end
132
+ end
@@ -0,0 +1,115 @@
1
+ require 'net/http'
2
+ require 'json'
3
+ require 'open-uri'
4
+
5
+ # Initialize a DB Proxy Client, which connects to the AIsuru proxy client to interact with
6
+ # backend and engine databases, in read-only mode.
7
+ # Usage:
8
+ #
9
+ # client = AisuruProxyClient.new(base_url: "https://...", api_key: "XXX")
10
+ #
11
+ # Status:
12
+ # client.status
13
+ #
14
+ # Tables list and table information
15
+ # client.tables(id: 'backend', schema: 'memoriai')
16
+ # client.table_schema(id: 'backend', schema: 'memoriai', table: 'ActionLog')
17
+ #
18
+ # SQL Query
19
+ # sql = <<~SQL
20
+ # SELECT * FROM memoriai."ActionLog"
21
+ # LIMIT 10
22
+ # OFFSET 0
23
+ # SQL
24
+ # client.query(id: 'backend', sql: sql)
25
+ class MemoriClient::Proxy::Client
26
+ CONNECTIONS = ['backend', 'engine'].freeze
27
+
28
+ # @param base_url [String] The base URL for the API
29
+ # @param api_key [String] The API key for authentication
30
+ def initialize(base_url:, api_key:)
31
+ @base_url = base_url
32
+ @api_key = api_key
33
+ end
34
+
35
+ # Get the status of the API
36
+ def status
37
+ path = "api/v1/status"
38
+ uri = URI.join(@base_url, path)
39
+ response = get(uri)
40
+ [response.code, response.body]
41
+ end
42
+
43
+ # Get a list of tables for a specific connection
44
+ # @param id [String] The connection ID
45
+ # @param schema [String] The schema name (optional)
46
+ def tables(id:, schema: nil)
47
+ unless CONNECTIONS.include?(id)
48
+ raise ArgumentError, "Invalid connection id: #{id}"
49
+ end
50
+
51
+ path = "api/v1/#{id}/tables"
52
+ path += "?schema=#{schema}" if schema
53
+ uri = URI.join(@base_url, path)
54
+ response = get(uri)
55
+ [response.code, response.body]
56
+ end
57
+
58
+ # Get the schema of a specific table
59
+ # @param id [String] The connection ID
60
+ # @param schema [String] The schema name (optional)
61
+ # @param table [String] The table name
62
+ def table_schema(id:, schema: nil, table:)
63
+ unless CONNECTIONS.include?(id)
64
+ raise ArgumentError, "Invalid connection id: #{id}"
65
+ end
66
+
67
+ path = "api/v1/#{id}/tables/#{table}/schema"
68
+ path += "?schema=#{schema}" if schema
69
+ uri = URI.join(@base_url, path)
70
+ response = get(uri)
71
+ [response.code, response.body]
72
+ end
73
+
74
+ # Execute a SQL query
75
+ # @param id [String] The connection ID
76
+ # @param sql [String] The SQL query
77
+ def query(id:, sql:)
78
+ unless CONNECTIONS.include?(id)
79
+ raise ArgumentError, "Invalid connection id: #{id}"
80
+ end
81
+
82
+ path = "api/v1/#{id}/query"
83
+ uri = URI.join(@base_url, path)
84
+ response = post_raw_content(uri, sql)
85
+ [response.code, response.body]
86
+ end
87
+
88
+ private
89
+
90
+ def get(uri)
91
+ request = Net::HTTP::Get.new(uri)
92
+ request["X-Api-Key"] = @api_key
93
+
94
+ req_options = { use_ssl: uri.scheme == "https" }
95
+ response = Net::HTTP.start(uri.hostname, uri.port, req_options) do |http|
96
+ http.request(request)
97
+ end
98
+ response
99
+ end
100
+
101
+ def post_raw_content(uri, content)
102
+ request = Net::HTTP::Post.new(uri)
103
+ request["X-Api-Key"] = @api_key
104
+ request["Content-Type"] = "text/plain"
105
+ request["Accept"] = "application/json"
106
+ request.body = content
107
+
108
+ req_options = { use_ssl: uri.scheme == "https" }
109
+
110
+ response = Net::HTTP.start(uri.hostname, uri.port, req_options) do |http|
111
+ http.request(request)
112
+ end
113
+ response
114
+ end
115
+ end