wowsql-sdk 3.0.1 → 3.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 +4 -4
- data/README.md +557 -325
- data/lib/wowsql/auth.rb +2 -2
- data/lib/wowsql/client.rb +60 -60
- data/lib/wowsql/query_builder.rb +197 -226
- data/lib/wowsql/schema.rb +22 -5
- data/lib/wowsql/storage.rb +2 -2
- data/lib/wowsql/table.rb +123 -110
- metadata +1 -1
data/lib/wowsql/auth.rb
CHANGED
|
@@ -91,12 +91,12 @@ module WOWSQL
|
|
|
91
91
|
|
|
92
92
|
# @param project_url [String] Project subdomain or full URL
|
|
93
93
|
# @param api_key [String] API key for authentication
|
|
94
|
-
# @param base_domain [String] Base domain (default: "
|
|
94
|
+
# @param base_domain [String] Base domain (default: "wowsqlconnect.com")
|
|
95
95
|
# @param secure [Boolean] Use HTTPS (default: true)
|
|
96
96
|
# @param timeout [Integer] Request timeout in seconds (default: 30)
|
|
97
97
|
# @param verify_ssl [Boolean] Verify SSL certificates (default: true)
|
|
98
98
|
# @param token_storage [TokenStorage, nil] Optional token storage
|
|
99
|
-
def initialize(project_url, api_key, base_domain: '
|
|
99
|
+
def initialize(project_url, api_key, base_domain: 'wowsqlconnect.com', secure: true,
|
|
100
100
|
timeout: 30, verify_ssl: true, token_storage: nil)
|
|
101
101
|
@api_key = api_key
|
|
102
102
|
@timeout = timeout
|
data/lib/wowsql/client.rb
CHANGED
|
@@ -4,104 +4,93 @@ require_relative 'exceptions'
|
|
|
4
4
|
require_relative 'table'
|
|
5
5
|
|
|
6
6
|
module WOWSQL
|
|
7
|
-
#
|
|
7
|
+
# WowSQL client for PostgREST-native database operations.
|
|
8
8
|
#
|
|
9
|
-
#
|
|
10
|
-
# Use Service Role Key or Anonymous Key for authentication.
|
|
11
|
-
#
|
|
12
|
-
# Key Types:
|
|
13
|
-
# - Service Role Key: Full access to all database operations (server-side)
|
|
14
|
-
# - Anonymous Key: Public access with limited permissions (client-side)
|
|
9
|
+
# All requests are sent directly to the PostgREST endpoint (/rest/v1).
|
|
15
10
|
#
|
|
16
11
|
# @example
|
|
17
|
-
# client = WOWSQL::WOWSQLClient.new(
|
|
18
|
-
#
|
|
19
|
-
# "wowbase_service_..."
|
|
20
|
-
# )
|
|
21
|
-
# users = client.table("users").get
|
|
12
|
+
# client = WOWSQL::WOWSQLClient.new("myproject", "wowsql_anon_...")
|
|
13
|
+
# result = client.table("users").get
|
|
22
14
|
class WOWSQLClient
|
|
23
|
-
attr_reader :api_url, :api_key, :timeout, :verify_ssl
|
|
15
|
+
attr_reader :api_url, :api_key, :timeout, :verify_ssl, :last_content_range
|
|
24
16
|
|
|
25
|
-
# @param project_url [String]
|
|
26
|
-
# @param api_key
|
|
27
|
-
# @param base_domain [String]
|
|
28
|
-
# @param secure
|
|
29
|
-
# @param timeout
|
|
30
|
-
# @param verify_ssl
|
|
31
|
-
def initialize(project_url, api_key,
|
|
32
|
-
|
|
33
|
-
|
|
17
|
+
# @param project_url [String] Project slug, domain, or full URL
|
|
18
|
+
# @param api_key [String] Anonymous or service role key
|
|
19
|
+
# @param base_domain [String] Base domain appended when project_url is a slug (default: wowsqlconnect.com)
|
|
20
|
+
# @param secure [Boolean] Use HTTPS (default: true)
|
|
21
|
+
# @param timeout [Integer] Request timeout in seconds (default: 30)
|
|
22
|
+
# @param verify_ssl [Boolean] Verify SSL certificates (default: true)
|
|
23
|
+
def initialize(project_url, api_key,
|
|
24
|
+
base_domain: 'wowsqlconnect.com',
|
|
25
|
+
secure: true,
|
|
26
|
+
timeout: 30,
|
|
27
|
+
verify_ssl: true)
|
|
28
|
+
@api_key = api_key
|
|
29
|
+
@timeout = timeout
|
|
34
30
|
@verify_ssl = verify_ssl
|
|
31
|
+
@last_content_range = nil
|
|
35
32
|
|
|
36
|
-
if project_url.start_with?('http://'
|
|
37
|
-
|
|
38
|
-
if
|
|
39
|
-
|
|
40
|
-
@api_url = "#{base_url}/api/v2"
|
|
41
|
-
else
|
|
42
|
-
@api_url = "#{base_url}/api/v2"
|
|
43
|
-
end
|
|
33
|
+
if project_url.start_with?('http://', 'https://')
|
|
34
|
+
base = project_url.chomp('/')
|
|
35
|
+
base = base.split('/api').first if base.include?('/api')
|
|
36
|
+
@base_url = base
|
|
44
37
|
else
|
|
45
38
|
protocol = secure ? 'https' : 'http'
|
|
46
39
|
if project_url.include?(".#{base_domain}") || project_url.end_with?(base_domain)
|
|
47
|
-
@
|
|
40
|
+
@base_url = "#{protocol}://#{project_url}"
|
|
48
41
|
else
|
|
49
|
-
@
|
|
42
|
+
@base_url = "#{protocol}://#{project_url}.#{base_domain}"
|
|
50
43
|
end
|
|
51
44
|
end
|
|
52
45
|
|
|
46
|
+
@api_url = "#{@base_url}/rest/v1"
|
|
47
|
+
|
|
53
48
|
ssl_options = verify_ssl ? {} : { verify: false }
|
|
54
49
|
|
|
55
50
|
@conn = Faraday.new(url: @api_url, ssl: ssl_options) do |f|
|
|
56
|
-
f.request
|
|
51
|
+
f.request :json
|
|
57
52
|
f.response :json
|
|
58
|
-
f.adapter
|
|
53
|
+
f.adapter Faraday.default_adapter
|
|
59
54
|
f.options.timeout = timeout
|
|
60
55
|
end
|
|
61
56
|
|
|
62
|
-
@conn.headers['
|
|
57
|
+
@conn.headers['apikey'] = api_key
|
|
63
58
|
@conn.headers['Content-Type'] = 'application/json'
|
|
64
59
|
end
|
|
65
60
|
|
|
66
|
-
#
|
|
61
|
+
# Return a Table interface for the given table name.
|
|
67
62
|
#
|
|
68
|
-
# @param table_name [String]
|
|
69
|
-
# @return [Table]
|
|
63
|
+
# @param table_name [String]
|
|
64
|
+
# @return [Table]
|
|
70
65
|
def table(table_name)
|
|
71
66
|
Table.new(self, table_name)
|
|
72
67
|
end
|
|
73
68
|
|
|
74
|
-
#
|
|
75
|
-
#
|
|
76
|
-
# @return [Array<String>] List of table names
|
|
77
|
-
def list_tables
|
|
78
|
-
response = request('GET', '/tables', nil, nil)
|
|
79
|
-
response['tables'] || []
|
|
80
|
-
end
|
|
81
|
-
|
|
82
|
-
# Get table schema information.
|
|
83
|
-
#
|
|
84
|
-
# @param table_name [String] Name of the table
|
|
85
|
-
# @return [Hash] Table schema with columns and primary key
|
|
86
|
-
def get_table_schema(table_name)
|
|
87
|
-
request('GET', "/tables/#{table_name}/schema", nil, nil)
|
|
88
|
-
end
|
|
89
|
-
|
|
90
|
-
# Close the HTTP connection.
|
|
69
|
+
# Close the HTTP connection (no-op, provided for API parity).
|
|
91
70
|
def close
|
|
92
71
|
@conn.close if @conn.respond_to?(:close)
|
|
93
72
|
end
|
|
94
73
|
|
|
95
|
-
# Make HTTP request to
|
|
96
|
-
|
|
74
|
+
# Make an HTTP request to the PostgREST endpoint.
|
|
75
|
+
#
|
|
76
|
+
# @param method [String] HTTP method
|
|
77
|
+
# @param path [String] Path (relative to /rest/v1)
|
|
78
|
+
# @param params [Hash, nil] Query parameters
|
|
79
|
+
# @param json [Hash, nil] Request body
|
|
80
|
+
# @param headers [Hash, nil] Additional headers (e.g. Prefer, on-conflict)
|
|
81
|
+
# @return [Array, Hash, nil]
|
|
82
|
+
def request(method, path, params = nil, json = nil, headers = nil)
|
|
97
83
|
response = @conn.public_send(method.downcase, path) do |req|
|
|
98
|
-
req.params
|
|
99
|
-
req.body
|
|
84
|
+
req.params = params if params
|
|
85
|
+
req.body = json if json
|
|
86
|
+
req.headers = req.headers.merge(headers) if headers
|
|
100
87
|
end
|
|
101
88
|
|
|
89
|
+
@last_content_range = response.headers['content-range']
|
|
90
|
+
|
|
102
91
|
if response.status >= 400
|
|
103
92
|
error_data = response.body.is_a?(Hash) ? response.body : {}
|
|
104
|
-
error_msg
|
|
93
|
+
error_msg = error_data['message'] || error_data['detail'] || "Request failed with status #{response.status}"
|
|
105
94
|
raise WOWSQLError.new(error_msg, response.status, error_data)
|
|
106
95
|
end
|
|
107
96
|
|
|
@@ -109,5 +98,16 @@ module WOWSQL
|
|
|
109
98
|
rescue Faraday::Error => e
|
|
110
99
|
raise WOWSQLError.new("Request failed: #{e.message}")
|
|
111
100
|
end
|
|
101
|
+
|
|
102
|
+
# Parse total count from a Content-Range header value.
|
|
103
|
+
#
|
|
104
|
+
# @param header [String, nil] e.g. "0-19/100"
|
|
105
|
+
# @param fallback [Integer]
|
|
106
|
+
# @return [Integer]
|
|
107
|
+
def self.parse_total_from_content_range(header, fallback)
|
|
108
|
+
return fallback unless header&.include?('/')
|
|
109
|
+
val = header.split('/').last.to_i
|
|
110
|
+
val > 0 ? val : fallback
|
|
111
|
+
end
|
|
112
112
|
end
|
|
113
113
|
end
|