booqable 1.0.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/.rspec +2 -0
- data/.rubocop.yml +11 -0
- data/CHANGELOG.md +5 -0
- data/CODE_OF_CONDUCT.md +132 -0
- data/LICENSE.txt +21 -0
- data/README.md +403 -0
- data/Rakefile +12 -0
- data/lib/booqable/auth.rb +114 -0
- data/lib/booqable/client.rb +81 -0
- data/lib/booqable/configurable.rb +143 -0
- data/lib/booqable/default.rb +215 -0
- data/lib/booqable/error.rb +428 -0
- data/lib/booqable/http.rb +383 -0
- data/lib/booqable/json_api_serializer.rb +266 -0
- data/lib/booqable/middleware/auth/api_key.rb +46 -0
- data/lib/booqable/middleware/auth/oauth.rb +88 -0
- data/lib/booqable/middleware/auth/single_use.rb +157 -0
- data/lib/booqable/middleware/base.rb +7 -0
- data/lib/booqable/middleware/raise_error.rb +29 -0
- data/lib/booqable/oauth_client.rb +72 -0
- data/lib/booqable/rate_limit.rb +51 -0
- data/lib/booqable/resource_proxy.rb +149 -0
- data/lib/booqable/resources.json +74 -0
- data/lib/booqable/resources.rb +68 -0
- data/lib/booqable/version.rb +5 -0
- data/lib/booqable.rb +85 -0
- data/sig/booqable.rbs +324 -0
- metadata +174 -0
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
module Booqable
|
|
2
|
+
# Resource-related methods for {Booqable::Client}
|
|
3
|
+
#
|
|
4
|
+
# This module dynamically defines methods for each resource listed in the
|
|
5
|
+
# `resources.json` file. Each resource method returns a {ResourceProxy} that
|
|
6
|
+
# provides standard CRUD operations for that resource type.
|
|
7
|
+
#
|
|
8
|
+
# The resources.json file can contain either simple strings or hash mappings
|
|
9
|
+
# for aliases. For example:
|
|
10
|
+
#
|
|
11
|
+
# @example resources.json structure
|
|
12
|
+
# [
|
|
13
|
+
# "orders",
|
|
14
|
+
# "customers",
|
|
15
|
+
# { "order_status_transitions": "transitions" }
|
|
16
|
+
# ]
|
|
17
|
+
#
|
|
18
|
+
# This would define the following methods on {Booqable::Client}:
|
|
19
|
+
# - `orders` - returns ResourceProxy for orders
|
|
20
|
+
# - `customers` - returns ResourceProxy for customers
|
|
21
|
+
# - `order_status_transitions` - returns ResourceProxy for order_status_transitions
|
|
22
|
+
# - `transitions` - alias for order_status_transitions
|
|
23
|
+
#
|
|
24
|
+
# @example Using resource methods
|
|
25
|
+
# client = Booqable::Client.new
|
|
26
|
+
#
|
|
27
|
+
# # Access orders resource
|
|
28
|
+
# orders = client.orders
|
|
29
|
+
# all_orders = orders.list
|
|
30
|
+
#
|
|
31
|
+
# # Access customers resource
|
|
32
|
+
# customers = client.customers
|
|
33
|
+
# customer = customers.find("123")
|
|
34
|
+
#
|
|
35
|
+
# # Access order status transitions directly
|
|
36
|
+
# order_status_transitions = client.order_status_transitions
|
|
37
|
+
#
|
|
38
|
+
# # Access order status transitions with alias
|
|
39
|
+
# transitions = client.transitions
|
|
40
|
+
#
|
|
41
|
+
# @see ResourceProxy
|
|
42
|
+
module Resources
|
|
43
|
+
# Path to the resources definition file
|
|
44
|
+
RESOURCES_FILE_PATH = File.join(File.dirname(__FILE__), "resources.json")
|
|
45
|
+
|
|
46
|
+
# All resources loaded from the resources.json file
|
|
47
|
+
ALL_RESOURCES = JSON.parse(File.read(RESOURCES_FILE_PATH))
|
|
48
|
+
|
|
49
|
+
ALL_RESOURCES.each do |resource|
|
|
50
|
+
resource_name = resource.is_a?(Hash) ? resource.keys.first : resource
|
|
51
|
+
resource_alias = resource.is_a?(Hash) ? resource.values.first : nil
|
|
52
|
+
|
|
53
|
+
# Dynamically define resource method
|
|
54
|
+
# @return [ResourceProxy] Resource proxy for the specified resource
|
|
55
|
+
define_method(resource_name) do
|
|
56
|
+
ResourceProxy.new(self, resource_name)
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
next unless resource_alias
|
|
60
|
+
|
|
61
|
+
# Dynamically define resource alias method
|
|
62
|
+
# @return [ResourceProxy] Resource proxy for the specified resource
|
|
63
|
+
define_method(resource_alias) do
|
|
64
|
+
ResourceProxy.new(self, resource_name)
|
|
65
|
+
end
|
|
66
|
+
end
|
|
67
|
+
end
|
|
68
|
+
end
|
data/lib/booqable.rb
ADDED
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
# Dependencies
|
|
4
|
+
require "faraday"
|
|
5
|
+
require "faraday/retry"
|
|
6
|
+
require "json"
|
|
7
|
+
require "sawyer"
|
|
8
|
+
require "sawyer/link_parsers/simple"
|
|
9
|
+
|
|
10
|
+
# Internal
|
|
11
|
+
require_relative "booqable/version"
|
|
12
|
+
require_relative "booqable/rate_limit"
|
|
13
|
+
require_relative "booqable/error"
|
|
14
|
+
require_relative "booqable/oauth_client"
|
|
15
|
+
require_relative "booqable/middleware/base"
|
|
16
|
+
require_relative "booqable/middleware/raise_error"
|
|
17
|
+
require_relative "booqable/middleware/auth/oauth"
|
|
18
|
+
require_relative "booqable/middleware/auth/api_key"
|
|
19
|
+
require_relative "booqable/middleware/auth/single_use"
|
|
20
|
+
require_relative "booqable/resource_proxy"
|
|
21
|
+
require_relative "booqable/json_api_serializer"
|
|
22
|
+
require_relative "booqable/default"
|
|
23
|
+
require_relative "booqable/configurable"
|
|
24
|
+
require_relative "booqable/resources"
|
|
25
|
+
require_relative "booqable/auth"
|
|
26
|
+
require_relative "booqable/http"
|
|
27
|
+
require_relative "booqable/client"
|
|
28
|
+
|
|
29
|
+
# Main Booqable module providing access to the Booqable API
|
|
30
|
+
#
|
|
31
|
+
# @example Basic usage
|
|
32
|
+
# Booqable.configure do |config|
|
|
33
|
+
# config.api_key = "your_api_key"
|
|
34
|
+
# config.company_id = "your_company"
|
|
35
|
+
# end
|
|
36
|
+
#
|
|
37
|
+
# orders = Booqable.orders.list(include: "customer,items")
|
|
38
|
+
# orders.each do |order|
|
|
39
|
+
# order.items.each do |item|
|
|
40
|
+
# # Process each item in the order
|
|
41
|
+
# end
|
|
42
|
+
# end
|
|
43
|
+
#
|
|
44
|
+
module Booqable
|
|
45
|
+
class << self
|
|
46
|
+
include Booqable::Configurable
|
|
47
|
+
|
|
48
|
+
# API client based on configured options {Configurable}
|
|
49
|
+
#
|
|
50
|
+
# @return [Booqable::Client] API wrapper
|
|
51
|
+
def client
|
|
52
|
+
return @client if defined?(@client) && @client.same_options?(options)
|
|
53
|
+
|
|
54
|
+
@client = Booqable::Client.new(options)
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
private
|
|
58
|
+
|
|
59
|
+
# Delegates respond_to? calls to the client
|
|
60
|
+
#
|
|
61
|
+
# @param method_name [Symbol] the method name to check
|
|
62
|
+
# @param include_private [Boolean] whether to include private methods
|
|
63
|
+
# @return [Boolean] true if the client responds to the method
|
|
64
|
+
def respond_to_missing?(method_name, include_private = false)
|
|
65
|
+
client.respond_to?(method_name, include_private)
|
|
66
|
+
end
|
|
67
|
+
|
|
68
|
+
# Delegates method calls to the client when the client responds to them
|
|
69
|
+
#
|
|
70
|
+
# @param method_name [Symbol] the method name being called
|
|
71
|
+
# @param args [Array] arguments passed to the method
|
|
72
|
+
# @param block [Proc] block passed to the method
|
|
73
|
+
# @return [Object] the result of calling the method on the client
|
|
74
|
+
# @raise [NoMethodError] when neither the module nor client respond to the method
|
|
75
|
+
def method_missing(method_name, *args, &block)
|
|
76
|
+
if client.respond_to?(method_name)
|
|
77
|
+
return client.send(method_name, *args, &block)
|
|
78
|
+
end
|
|
79
|
+
|
|
80
|
+
super
|
|
81
|
+
end
|
|
82
|
+
end
|
|
83
|
+
end
|
|
84
|
+
|
|
85
|
+
Booqable.setup
|
data/sig/booqable.rbs
ADDED
|
@@ -0,0 +1,324 @@
|
|
|
1
|
+
module Booqable
|
|
2
|
+
VERSION: String
|
|
3
|
+
|
|
4
|
+
# Configuration options for {Client}
|
|
5
|
+
module Configurable
|
|
6
|
+
@api_domain: String?
|
|
7
|
+
@api_endpoint: String?
|
|
8
|
+
@api_key: String?
|
|
9
|
+
@api_version: String | Integer?
|
|
10
|
+
@auto_paginate: bool?
|
|
11
|
+
@client_id: String?
|
|
12
|
+
@client_secret: String?
|
|
13
|
+
@company_id: String?
|
|
14
|
+
@connection_options: Hash[Symbol, untyped]?
|
|
15
|
+
@debug: bool?
|
|
16
|
+
@default_media_type: String?
|
|
17
|
+
@middleware: Faraday::RackBuilder?
|
|
18
|
+
@no_retries: bool?
|
|
19
|
+
@per_page: Integer?
|
|
20
|
+
@proxy: String?
|
|
21
|
+
@read_token: Proc?
|
|
22
|
+
@redirect_uri: String?
|
|
23
|
+
@single_use_token: String?
|
|
24
|
+
@single_use_token_algorithm: String?
|
|
25
|
+
@single_use_token_company_id: String?
|
|
26
|
+
@single_use_token_expiration_period: Integer?
|
|
27
|
+
@single_use_token_private_key: String?
|
|
28
|
+
@single_use_token_secret: String?
|
|
29
|
+
@single_use_token_user_id: String?
|
|
30
|
+
@ssl_verify_mode: Integer?
|
|
31
|
+
@user_agent: String?
|
|
32
|
+
@write_token: Proc?
|
|
33
|
+
|
|
34
|
+
attr_accessor api_domain: String?
|
|
35
|
+
attr_accessor api_endpoint: String?
|
|
36
|
+
attr_accessor api_key: String?
|
|
37
|
+
attr_accessor api_version: String | Integer?
|
|
38
|
+
attr_accessor auto_paginate: bool?
|
|
39
|
+
attr_accessor client_id: String?
|
|
40
|
+
attr_accessor client_secret: String?
|
|
41
|
+
attr_accessor company_id: String?
|
|
42
|
+
attr_accessor connection_options: Hash[Symbol, untyped]?
|
|
43
|
+
attr_accessor debug: bool?
|
|
44
|
+
attr_accessor default_media_type: String?
|
|
45
|
+
attr_accessor middleware: Faraday::RackBuilder?
|
|
46
|
+
attr_accessor no_retries: bool?
|
|
47
|
+
attr_accessor per_page: Integer?
|
|
48
|
+
attr_accessor proxy: String?
|
|
49
|
+
attr_accessor read_token: Proc?
|
|
50
|
+
attr_accessor redirect_uri: String?
|
|
51
|
+
attr_accessor single_use_token: String?
|
|
52
|
+
attr_accessor single_use_token_algorithm: String?
|
|
53
|
+
attr_accessor single_use_token_company_id: String?
|
|
54
|
+
attr_accessor single_use_token_expiration_period: Integer?
|
|
55
|
+
attr_accessor single_use_token_private_key: String?
|
|
56
|
+
attr_accessor single_use_token_secret: String?
|
|
57
|
+
attr_accessor single_use_token_user_id: String?
|
|
58
|
+
attr_accessor ssl_verify_mode: Integer?
|
|
59
|
+
attr_accessor user_agent: String?
|
|
60
|
+
attr_accessor write_token: Proc?
|
|
61
|
+
|
|
62
|
+
module ConfigurableClass
|
|
63
|
+
def keys: () -> Array[Symbol]
|
|
64
|
+
end
|
|
65
|
+
|
|
66
|
+
extend ConfigurableClass
|
|
67
|
+
|
|
68
|
+
def configure: () { (self) -> void } -> void
|
|
69
|
+
def reset!: () -> self
|
|
70
|
+
alias setup reset!
|
|
71
|
+
def same_options?: (Hash[Symbol, untyped] opts) -> bool
|
|
72
|
+
def debug?: () -> bool
|
|
73
|
+
|
|
74
|
+
private
|
|
75
|
+
|
|
76
|
+
def api_protocol: () -> String
|
|
77
|
+
def options: () -> Hash[Symbol, untyped]
|
|
78
|
+
end
|
|
79
|
+
|
|
80
|
+
# Resource-related methods for {Booqable::Client}
|
|
81
|
+
module Resources
|
|
82
|
+
RESOURCES_FILE_PATH: String
|
|
83
|
+
ALL_RESOURCES: Array[String | Hash[String, String]]
|
|
84
|
+
|
|
85
|
+
def method_missing: (Symbol method_name, *untyped args) -> ResourceProxy
|
|
86
|
+
end
|
|
87
|
+
|
|
88
|
+
# Authentication methods for {Booqable::Client}
|
|
89
|
+
module Auth
|
|
90
|
+
def authenticate_with_code: (String code) -> void
|
|
91
|
+
def inject_auth_middleware: (Faraday::Builder builder) -> void
|
|
92
|
+
def oauth_client: () -> OAuthClient?
|
|
93
|
+
def oauth_authenticated?: () -> bool
|
|
94
|
+
def api_key_authenticated?: () -> bool
|
|
95
|
+
def single_use_token_authenticated?: () -> bool
|
|
96
|
+
end
|
|
97
|
+
|
|
98
|
+
# HTTP request methods for {Booqable::Client}
|
|
99
|
+
module HTTP
|
|
100
|
+
CONVENIENCE_HEADERS: Set[Symbol]
|
|
101
|
+
|
|
102
|
+
@last_response: Sawyer::Response?
|
|
103
|
+
@faraday: Faraday::Connection?
|
|
104
|
+
@faraday_builder: Faraday::RackBuilder?
|
|
105
|
+
@agent: Sawyer::Agent?
|
|
106
|
+
@logger: Logger?
|
|
107
|
+
|
|
108
|
+
def get: (String url, ?Hash[Symbol, untyped] options) -> Sawyer::Resource
|
|
109
|
+
def post: (String url, ?Hash[Symbol, untyped] options) -> Sawyer::Resource
|
|
110
|
+
def put: (String url, ?Hash[Symbol, untyped] options) -> Sawyer::Resource
|
|
111
|
+
def patch: (String url, ?Hash[Symbol, untyped] options) -> Sawyer::Resource
|
|
112
|
+
def delete: (String url, ?Hash[Symbol, untyped] options) -> Sawyer::Resource
|
|
113
|
+
def head: (String url, ?Hash[Symbol, untyped] options) -> Sawyer::Resource
|
|
114
|
+
def request: (Symbol method, String path, untyped data, ?Hash[Symbol, untyped] options) -> Sawyer::Resource
|
|
115
|
+
def normalized_path: (String path) -> String
|
|
116
|
+
def last_response: () -> Sawyer::Response?
|
|
117
|
+
def paginate: (String url, ?Hash[Symbol, untyped] options) -> Array[untyped]
|
|
118
|
+
def rate_limit: () -> RateLimit
|
|
119
|
+
def faraday: () -> Faraday::Connection
|
|
120
|
+
def default_headers: () -> Hash[Symbol, String]
|
|
121
|
+
def faraday_options: () -> Hash[Symbol, untyped]
|
|
122
|
+
def faraday_builder: () -> Faraday::RackBuilder
|
|
123
|
+
def agent: () -> Sawyer::Agent
|
|
124
|
+
def logger: () -> Logger?
|
|
125
|
+
def sawyer_options: () -> Hash[Symbol, untyped]
|
|
126
|
+
def sawyer_serializer: () -> JsonApiSerializer
|
|
127
|
+
def last_response_body: () -> Hash[Symbol, untyped]?
|
|
128
|
+
def parse_options_with_convenience_headers: (Hash[Symbol, untyped] options) -> Hash[Symbol, untyped]
|
|
129
|
+
def response_data_with_correct_encoding: (Sawyer::Response response) -> untyped
|
|
130
|
+
def api_endpoint: () -> String
|
|
131
|
+
end
|
|
132
|
+
|
|
133
|
+
# Client for the Booqable API
|
|
134
|
+
class Client
|
|
135
|
+
include Configurable
|
|
136
|
+
include Resources
|
|
137
|
+
include Auth
|
|
138
|
+
include HTTP
|
|
139
|
+
|
|
140
|
+
SECRETS: Array[String]
|
|
141
|
+
|
|
142
|
+
def initialize: (?Hash[Symbol, untyped] options) -> void
|
|
143
|
+
def inspect: () -> String
|
|
144
|
+
end
|
|
145
|
+
|
|
146
|
+
# Generic resource proxy for API collections
|
|
147
|
+
class ResourceProxy
|
|
148
|
+
@client: Client
|
|
149
|
+
@resource: String
|
|
150
|
+
|
|
151
|
+
def initialize: (Client client, String | Symbol resource_name) -> void
|
|
152
|
+
def list: (?Hash[Symbol, untyped] params) -> Array[untyped]
|
|
153
|
+
def find: (String | Integer id, ?Hash[Symbol, untyped] params) -> Hash[Symbol, untyped]
|
|
154
|
+
def create: (?Hash[Symbol, untyped] attrs) -> Hash[Symbol, untyped]
|
|
155
|
+
def update: (String | Integer id, ?Hash[Symbol, untyped] attrs) -> Hash[Symbol, untyped]
|
|
156
|
+
|
|
157
|
+
private
|
|
158
|
+
|
|
159
|
+
attr_reader client: Client
|
|
160
|
+
|
|
161
|
+
def request: (*untyped args) -> untyped
|
|
162
|
+
def paginate: (*untyped args) -> untyped
|
|
163
|
+
end
|
|
164
|
+
|
|
165
|
+
# OAuth2 client for Booqable API authentication
|
|
166
|
+
class OAuthClient
|
|
167
|
+
TOKEN_ENDPOINT: String
|
|
168
|
+
|
|
169
|
+
@client: OAuth2::Client
|
|
170
|
+
@redirect_uri: String
|
|
171
|
+
|
|
172
|
+
def initialize: (base_url: String, client_id: String, client_secret: String, redirect_uri: String) -> void
|
|
173
|
+
def get_token_from_code: (String code, ?scope: String) -> OAuth2::AccessToken
|
|
174
|
+
end
|
|
175
|
+
|
|
176
|
+
# Rate limit information from API responses
|
|
177
|
+
class RateLimit < Struct[Integer?]
|
|
178
|
+
attr_accessor limit: Integer?
|
|
179
|
+
attr_accessor remaining: Integer?
|
|
180
|
+
attr_accessor resets_in: Integer?
|
|
181
|
+
|
|
182
|
+
def self.from_response: (untyped response) -> RateLimit
|
|
183
|
+
end
|
|
184
|
+
|
|
185
|
+
# Custom error class for rescuing from all Booqable errors
|
|
186
|
+
class Error < StandardError
|
|
187
|
+
attr_reader context: RateLimit?
|
|
188
|
+
|
|
189
|
+
@response: Hash[Symbol, untyped]?
|
|
190
|
+
@data: untyped
|
|
191
|
+
|
|
192
|
+
def self.from_response: (Hash[Symbol, untyped] response) -> nil
|
|
193
|
+
def self.error_class_from_response: (Hash[Symbol, untyped] response) -> Error?
|
|
194
|
+
def self.error_for_400: (String body) -> singleton(Error)
|
|
195
|
+
def self.error_for_402: (String body) -> singleton(Error)
|
|
196
|
+
def self.error_for_404: (String body) -> singleton(Error)
|
|
197
|
+
def self.error_for_422: (String body) -> singleton(Error)
|
|
198
|
+
def self.error_for_503: (String body) -> singleton(Error)
|
|
199
|
+
|
|
200
|
+
def initialize: (?Hash[Symbol, untyped]? response) -> void
|
|
201
|
+
def build_error_context: () -> void
|
|
202
|
+
def errors: () -> Array[Hash[Symbol, untyped]]
|
|
203
|
+
def response_status: () -> Integer
|
|
204
|
+
def response_headers: () -> Hash[Symbol, untyped]
|
|
205
|
+
def response_body: () -> String
|
|
206
|
+
|
|
207
|
+
private
|
|
208
|
+
|
|
209
|
+
def data: () -> untyped
|
|
210
|
+
def response_message: () -> String?
|
|
211
|
+
def response_error: () -> String?
|
|
212
|
+
def response_error_summary: () -> String?
|
|
213
|
+
def build_error_message: () -> String?
|
|
214
|
+
def redact_url: (String url_string) -> String
|
|
215
|
+
end
|
|
216
|
+
|
|
217
|
+
# Error classes
|
|
218
|
+
class ClientError < Error; end
|
|
219
|
+
class BadRequest < ClientError; end
|
|
220
|
+
class ReadOnlyAttribute < ClientError; end
|
|
221
|
+
class UnknownAttribute < ClientError; end
|
|
222
|
+
class FieldsInWrongFormat < ClientError; end
|
|
223
|
+
class ExtraFieldsInWrongFormat < ClientError; end
|
|
224
|
+
class PageShouldBeAnObject < ClientError; end
|
|
225
|
+
class FailedTypecasting < ClientError; end
|
|
226
|
+
class InvalidFilter < ClientError; end
|
|
227
|
+
class RequiredFilter < ClientError; end
|
|
228
|
+
class Unauthorized < ClientError; end
|
|
229
|
+
class PaymentRequired < ClientError; end
|
|
230
|
+
class FeatureNotEnabled < PaymentRequired; end
|
|
231
|
+
class TrialExpired < PaymentRequired; end
|
|
232
|
+
class Forbidden < ClientError; end
|
|
233
|
+
class TooManyRequests < Forbidden; end
|
|
234
|
+
class NotFound < ClientError; end
|
|
235
|
+
class CompanyNotFound < NotFound; end
|
|
236
|
+
class MethodNotAllowed < ClientError; end
|
|
237
|
+
class NotAcceptable < ClientError; end
|
|
238
|
+
class Conflict < ClientError; end
|
|
239
|
+
class Deprecated < ClientError; end
|
|
240
|
+
class UnsupportedMediaType < ClientError; end
|
|
241
|
+
class Locked < ClientError; end
|
|
242
|
+
class UnprocessableEntity < ClientError; end
|
|
243
|
+
class InvalidDateTimeFormat < UnprocessableEntity; end
|
|
244
|
+
class InvalidDateFormat < UnprocessableEntity; end
|
|
245
|
+
class ServerError < Error; end
|
|
246
|
+
class InternalServerError < ServerError; end
|
|
247
|
+
class NotImplemented < ServerError; end
|
|
248
|
+
class BadGateway < ServerError; end
|
|
249
|
+
class ServiceUnavailable < ServerError; end
|
|
250
|
+
class ReadOnlyMode < ServerError; end
|
|
251
|
+
class ConfigArgumentError < ArgumentError; end
|
|
252
|
+
class CompanyRequired < ArgumentError; end
|
|
253
|
+
class SingleUseTokenCompanyIdRequired < ArgumentError; end
|
|
254
|
+
class SingleUseTokenUserIdRequired < ArgumentError; end
|
|
255
|
+
class SingleUseTokenAlgorithmRequired < ConfigArgumentError; end
|
|
256
|
+
class PrivateKeyOrSecretRequired < ConfigArgumentError; end
|
|
257
|
+
class UnsupportedAPIVersion < ConfigArgumentError; end
|
|
258
|
+
class RequiredAuthParamMissing < ArgumentError; end
|
|
259
|
+
|
|
260
|
+
RATE_LIMITED_ERRORS: Array[singleton(Error)]
|
|
261
|
+
|
|
262
|
+
# JSON API serializer
|
|
263
|
+
class JsonApiSerializer
|
|
264
|
+
def self.any_json: () -> JsonApiSerializer
|
|
265
|
+
def decode: (String body) -> Hash[Symbol, untyped]
|
|
266
|
+
def encode: (Hash[Symbol, untyped] data) -> String
|
|
267
|
+
end
|
|
268
|
+
|
|
269
|
+
# Default configuration options
|
|
270
|
+
module Default
|
|
271
|
+
USER_AGENT: String
|
|
272
|
+
MEDIA_TYPE: String
|
|
273
|
+
RETRY_OPTIONS: Hash[Symbol, untyped]
|
|
274
|
+
MIDDLEWARE: Faraday::RackBuilder
|
|
275
|
+
|
|
276
|
+
module DefaultClass
|
|
277
|
+
def options: () -> Hash[Symbol, untyped]
|
|
278
|
+
def api_domain: () -> String
|
|
279
|
+
def api_version: () -> Integer
|
|
280
|
+
def api_endpoint: () -> String?
|
|
281
|
+
def auto_paginate: () -> String?
|
|
282
|
+
def client_id: () -> String?
|
|
283
|
+
def client_secret: () -> String?
|
|
284
|
+
def company_id: () -> String?
|
|
285
|
+
def redirect_uri: () -> String?
|
|
286
|
+
def connection_options: () -> Hash[Symbol, untyped]?
|
|
287
|
+
def default_media_type: () -> String
|
|
288
|
+
def middleware: () -> Faraday::RackBuilder
|
|
289
|
+
def per_page: () -> Integer?
|
|
290
|
+
def proxy: () -> String?
|
|
291
|
+
def ssl_verify_mode: () -> Integer
|
|
292
|
+
def user_agent: () -> String
|
|
293
|
+
def read_token: () -> Proc
|
|
294
|
+
def write_token: () -> Proc
|
|
295
|
+
def api_key: () -> String?
|
|
296
|
+
def single_use_token: () -> String?
|
|
297
|
+
def single_use_token_algorithm: () -> String?
|
|
298
|
+
def single_use_token_secret: () -> String?
|
|
299
|
+
def single_use_token_private_key: () -> String?
|
|
300
|
+
def single_use_token_expiration_period: () -> Integer
|
|
301
|
+
def single_use_token_company_id: () -> String?
|
|
302
|
+
def single_use_token_user_id: () -> String?
|
|
303
|
+
def debug: () -> bool
|
|
304
|
+
def no_retries: () -> bool
|
|
305
|
+
end
|
|
306
|
+
|
|
307
|
+
extend DefaultClass
|
|
308
|
+
end
|
|
309
|
+
|
|
310
|
+
# Module methods
|
|
311
|
+
def self.client: () -> Client
|
|
312
|
+
def self.configure: () { (self) -> void } -> void
|
|
313
|
+
def self.reset!: () -> self
|
|
314
|
+
alias self.setup self.reset!
|
|
315
|
+
def self.same_options?: (Hash[Symbol, untyped] opts) -> bool
|
|
316
|
+
def self.debug?: () -> bool
|
|
317
|
+
|
|
318
|
+
private
|
|
319
|
+
|
|
320
|
+
def self.respond_to_missing?: (Symbol method_name, ?bool include_private) -> bool
|
|
321
|
+
def self.method_missing: (Symbol method_name, *untyped args) ?{ (*untyped) -> untyped } -> untyped
|
|
322
|
+
|
|
323
|
+
include Configurable
|
|
324
|
+
end
|
metadata
ADDED
|
@@ -0,0 +1,174 @@
|
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
|
2
|
+
name: booqable
|
|
3
|
+
version: !ruby/object:Gem::Version
|
|
4
|
+
version: 1.0.0
|
|
5
|
+
platform: ruby
|
|
6
|
+
authors:
|
|
7
|
+
- Hrvoje Šimić
|
|
8
|
+
autorequire:
|
|
9
|
+
bindir: exe
|
|
10
|
+
cert_chain: []
|
|
11
|
+
date: 2025-10-24 00:00:00.000000000 Z
|
|
12
|
+
dependencies:
|
|
13
|
+
- !ruby/object:Gem::Dependency
|
|
14
|
+
name: faraday
|
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
|
16
|
+
requirements:
|
|
17
|
+
- - "~>"
|
|
18
|
+
- !ruby/object:Gem::Version
|
|
19
|
+
version: '2.13'
|
|
20
|
+
type: :runtime
|
|
21
|
+
prerelease: false
|
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
23
|
+
requirements:
|
|
24
|
+
- - "~>"
|
|
25
|
+
- !ruby/object:Gem::Version
|
|
26
|
+
version: '2.13'
|
|
27
|
+
- !ruby/object:Gem::Dependency
|
|
28
|
+
name: faraday-retry
|
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
|
30
|
+
requirements:
|
|
31
|
+
- - "~>"
|
|
32
|
+
- !ruby/object:Gem::Version
|
|
33
|
+
version: '2.3'
|
|
34
|
+
type: :runtime
|
|
35
|
+
prerelease: false
|
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
37
|
+
requirements:
|
|
38
|
+
- - "~>"
|
|
39
|
+
- !ruby/object:Gem::Version
|
|
40
|
+
version: '2.3'
|
|
41
|
+
- !ruby/object:Gem::Dependency
|
|
42
|
+
name: sawyer
|
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
|
44
|
+
requirements:
|
|
45
|
+
- - "~>"
|
|
46
|
+
- !ruby/object:Gem::Version
|
|
47
|
+
version: '0.9'
|
|
48
|
+
type: :runtime
|
|
49
|
+
prerelease: false
|
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
51
|
+
requirements:
|
|
52
|
+
- - "~>"
|
|
53
|
+
- !ruby/object:Gem::Version
|
|
54
|
+
version: '0.9'
|
|
55
|
+
- !ruby/object:Gem::Dependency
|
|
56
|
+
name: multi_json
|
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
|
58
|
+
requirements:
|
|
59
|
+
- - "~>"
|
|
60
|
+
- !ruby/object:Gem::Version
|
|
61
|
+
version: '1.15'
|
|
62
|
+
type: :runtime
|
|
63
|
+
prerelease: false
|
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
65
|
+
requirements:
|
|
66
|
+
- - "~>"
|
|
67
|
+
- !ruby/object:Gem::Version
|
|
68
|
+
version: '1.15'
|
|
69
|
+
- !ruby/object:Gem::Dependency
|
|
70
|
+
name: addressable
|
|
71
|
+
requirement: !ruby/object:Gem::Requirement
|
|
72
|
+
requirements:
|
|
73
|
+
- - "~>"
|
|
74
|
+
- !ruby/object:Gem::Version
|
|
75
|
+
version: '2.8'
|
|
76
|
+
type: :runtime
|
|
77
|
+
prerelease: false
|
|
78
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
79
|
+
requirements:
|
|
80
|
+
- - "~>"
|
|
81
|
+
- !ruby/object:Gem::Version
|
|
82
|
+
version: '2.8'
|
|
83
|
+
- !ruby/object:Gem::Dependency
|
|
84
|
+
name: oauth2
|
|
85
|
+
requirement: !ruby/object:Gem::Requirement
|
|
86
|
+
requirements:
|
|
87
|
+
- - "~>"
|
|
88
|
+
- !ruby/object:Gem::Version
|
|
89
|
+
version: '2.0'
|
|
90
|
+
type: :runtime
|
|
91
|
+
prerelease: false
|
|
92
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
93
|
+
requirements:
|
|
94
|
+
- - "~>"
|
|
95
|
+
- !ruby/object:Gem::Version
|
|
96
|
+
version: '2.0'
|
|
97
|
+
- !ruby/object:Gem::Dependency
|
|
98
|
+
name: jwt
|
|
99
|
+
requirement: !ruby/object:Gem::Requirement
|
|
100
|
+
requirements:
|
|
101
|
+
- - "~>"
|
|
102
|
+
- !ruby/object:Gem::Version
|
|
103
|
+
version: '3.1'
|
|
104
|
+
type: :runtime
|
|
105
|
+
prerelease: false
|
|
106
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
107
|
+
requirements:
|
|
108
|
+
- - "~>"
|
|
109
|
+
- !ruby/object:Gem::Version
|
|
110
|
+
version: '3.1'
|
|
111
|
+
description: Ruby toolkit for the Booqable API. Provides a simple interface to interact
|
|
112
|
+
with all Booqable API endpoints including orders, customers, products, and more.
|
|
113
|
+
email:
|
|
114
|
+
- services@booqable.com
|
|
115
|
+
executables: []
|
|
116
|
+
extensions: []
|
|
117
|
+
extra_rdoc_files: []
|
|
118
|
+
files:
|
|
119
|
+
- ".rspec"
|
|
120
|
+
- ".rubocop.yml"
|
|
121
|
+
- CHANGELOG.md
|
|
122
|
+
- CODE_OF_CONDUCT.md
|
|
123
|
+
- LICENSE.txt
|
|
124
|
+
- README.md
|
|
125
|
+
- Rakefile
|
|
126
|
+
- lib/booqable.rb
|
|
127
|
+
- lib/booqable/auth.rb
|
|
128
|
+
- lib/booqable/client.rb
|
|
129
|
+
- lib/booqable/configurable.rb
|
|
130
|
+
- lib/booqable/default.rb
|
|
131
|
+
- lib/booqable/error.rb
|
|
132
|
+
- lib/booqable/http.rb
|
|
133
|
+
- lib/booqable/json_api_serializer.rb
|
|
134
|
+
- lib/booqable/middleware/auth/api_key.rb
|
|
135
|
+
- lib/booqable/middleware/auth/oauth.rb
|
|
136
|
+
- lib/booqable/middleware/auth/single_use.rb
|
|
137
|
+
- lib/booqable/middleware/base.rb
|
|
138
|
+
- lib/booqable/middleware/raise_error.rb
|
|
139
|
+
- lib/booqable/oauth_client.rb
|
|
140
|
+
- lib/booqable/rate_limit.rb
|
|
141
|
+
- lib/booqable/resource_proxy.rb
|
|
142
|
+
- lib/booqable/resources.json
|
|
143
|
+
- lib/booqable/resources.rb
|
|
144
|
+
- lib/booqable/version.rb
|
|
145
|
+
- sig/booqable.rbs
|
|
146
|
+
homepage: https://github.com/booqable/booqable.rb
|
|
147
|
+
licenses:
|
|
148
|
+
- MIT
|
|
149
|
+
metadata:
|
|
150
|
+
homepage_uri: https://github.com/booqable/booqable.rb
|
|
151
|
+
source_code_uri: https://github.com/booqable/booqable.rb
|
|
152
|
+
changelog_uri: https://github.com/booqable/booqable.rb/blob/master/CHANGELOG.md
|
|
153
|
+
documentation_uri: https://developers.booqable.com/
|
|
154
|
+
bug_tracker_uri: https://github.com/booqable/booqable.rb/issues
|
|
155
|
+
post_install_message:
|
|
156
|
+
rdoc_options: []
|
|
157
|
+
require_paths:
|
|
158
|
+
- lib
|
|
159
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
|
160
|
+
requirements:
|
|
161
|
+
- - ">="
|
|
162
|
+
- !ruby/object:Gem::Version
|
|
163
|
+
version: 3.2.0
|
|
164
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
|
165
|
+
requirements:
|
|
166
|
+
- - ">="
|
|
167
|
+
- !ruby/object:Gem::Version
|
|
168
|
+
version: '0'
|
|
169
|
+
requirements: []
|
|
170
|
+
rubygems_version: 3.5.22
|
|
171
|
+
signing_key:
|
|
172
|
+
specification_version: 4
|
|
173
|
+
summary: Official Booqable API client for Ruby.
|
|
174
|
+
test_files: []
|