supersaas-api-client 1.1.0 → 2.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.
Files changed (47) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/actions.yaml +21 -0
  3. data/.gitignore +3 -0
  4. data/.rubocop.yml +1 -0
  5. data/.rubocop_todo.yml +296 -0
  6. data/Gemfile +5 -3
  7. data/Gemfile.lock +34 -7
  8. data/README.md +109 -58
  9. data/Rakefile +8 -6
  10. data/bin/console +4 -3
  11. data/examples/appointments.rb +70 -42
  12. data/examples/forms.rb +20 -22
  13. data/examples/groups.rb +20 -0
  14. data/examples/promotions.rb +32 -0
  15. data/examples/schedules.rb +23 -11
  16. data/examples/users.rb +31 -23
  17. data/lib/supersaas-api-client/api/appointments.rb +37 -25
  18. data/lib/supersaas-api-client/api/base_api.rb +69 -23
  19. data/lib/supersaas-api-client/api/forms.rb +16 -9
  20. data/lib/supersaas-api-client/api/groups.rb +12 -0
  21. data/lib/supersaas-api-client/api/promotions.rb +29 -0
  22. data/lib/supersaas-api-client/api/schedules.rb +14 -4
  23. data/lib/supersaas-api-client/api/users.rb +28 -15
  24. data/lib/supersaas-api-client/client.rb +106 -36
  25. data/lib/supersaas-api-client/exception.rb +3 -1
  26. data/lib/supersaas-api-client/models/appointment.rb +9 -12
  27. data/lib/supersaas-api-client/models/base_model.rb +4 -1
  28. data/lib/supersaas-api-client/models/field_list.rb +12 -0
  29. data/lib/supersaas-api-client/models/form.rb +5 -2
  30. data/lib/supersaas-api-client/models/group.rb +7 -0
  31. data/lib/supersaas-api-client/models/promotion.rb +7 -0
  32. data/lib/supersaas-api-client/models/resource.rb +3 -1
  33. data/lib/supersaas-api-client/models/schedule.rb +3 -1
  34. data/lib/supersaas-api-client/models/slot.rb +4 -6
  35. data/lib/supersaas-api-client/models/super_form.rb +7 -0
  36. data/lib/supersaas-api-client/models/user.rb +5 -8
  37. data/lib/supersaas-api-client/version.rb +4 -2
  38. data/lib/supersaas-api-client.rb +3 -1
  39. data/lib/supersaas.rb +23 -15
  40. data/supersaas-api-client.gemspec +19 -18
  41. metadata +52 -38
  42. data/test/appointments_test.rb +0 -99
  43. data/test/client_test.rb +0 -46
  44. data/test/forms_test.rb +0 -22
  45. data/test/schedules_test.rb +0 -19
  46. data/test/test_helper.rb +0 -23
  47. data/test/users_test.rb +0 -68
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'net/http'
2
4
  require 'uri'
3
5
  require 'json'
@@ -24,8 +26,8 @@ module Supersaas
24
26
  attr_accessor :account_name, :api_key, :host, :dry_run, :verbose
25
27
  attr_reader :last_request
26
28
 
27
- def initialize(configuration=nil)
28
- configuration = configuration || Configuration.new
29
+ def initialize(configuration = nil)
30
+ configuration ||= Configuration.new
29
31
  @account_name = configuration.account_name
30
32
  @api_key = configuration.api_key
31
33
  @host = configuration.host
@@ -33,32 +35,70 @@ module Supersaas
33
35
  @verbose = configuration.verbose
34
36
  end
35
37
 
36
- def appointments; @appointments ||= Appointments.new(self); end
37
- def forms; @forms ||= Forms.new(self); end
38
- def schedules; @schedules ||= Schedules.new(self); end
39
- def users; @users ||= Users.new(self); end
38
+ def appointments
39
+ @appointments ||= Appointments.new(self)
40
+ end
41
+
42
+ def forms
43
+ @forms ||= Forms.new(self)
44
+ end
45
+
46
+ def schedules
47
+ @schedules ||= Schedules.new(self)
48
+ end
49
+
50
+ def users
51
+ @users ||= Users.new(self)
52
+ end
40
53
 
41
- def get(path, query={})
54
+ def promotions
55
+ @promotions ||= Promotions.new(self)
56
+ end
57
+
58
+ def groups
59
+ @groups ||= Groups.new(self)
60
+ end
61
+
62
+ def get(path, query = {})
42
63
  request(:get, path, {}, query)
43
64
  end
44
65
 
45
- def post(path, params={}, query={})
66
+ def post(path, params = {}, query = {})
46
67
  request(:post, path, params, query)
47
68
  end
48
69
 
49
- def put(path, params={}, query={})
70
+ def put(path, params = {}, query = {})
50
71
  request(:put, path, params, query)
51
72
  end
52
73
 
53
- def delete(path, params={}, query={})
74
+ def delete(path, params = {}, query = {})
54
75
  request(:delete, path, params, query)
55
76
  end
56
77
 
57
78
  private
58
79
 
59
- def request(http_method, path, params={}, query={})
60
- raise Supersaas::Exception.new("Account name not configured. Call `Supersaas::Client.configure`.") unless account_name && account_name.size
61
- raise Supersaas::Exception.new("Account api key not configured. Call `Supersaas::Client.configure`.") unless api_key && api_key.size
80
+ # The rate limiter allows a maximum of 4 requests within the specified time window
81
+ WINDOW_SIZE = 1 # seconds
82
+ MAX_PER_WINDOW = 4
83
+ def throttle
84
+ # A queue to store timestamps of requests made within the rate limiting window
85
+ @queue ||= Array.new(MAX_PER_WINDOW)
86
+ # Represents the timestamp of the oldest request within the time window
87
+ oldest_request = @queue.push(Time.now).shift
88
+ # This ensures that the client does not make requests faster than the defined rate limit
89
+ if oldest_request && (d = Time.now - oldest_request) < WINDOW_SIZE
90
+ sleep WINDOW_SIZE - d
91
+ end
92
+ end
93
+
94
+ def request(http_method, path, params = {}, query = {})
95
+ throttle
96
+ unless account_name&.size
97
+ raise Supersaas::Exception, 'Account name not configured. Call `Supersaas::Client.configure`.'
98
+ end
99
+ unless api_key&.size
100
+ raise Supersaas::Exception, 'Account api key not configured. Call `Supersaas::Client.configure`.'
101
+ end
62
102
 
63
103
  uri = URI.parse(host)
64
104
  http = Net::HTTP.new(uri.host, uri.port)
@@ -68,7 +108,7 @@ module Supersaas
68
108
  query = delete_blank_values query
69
109
 
70
110
  path = "/api#{path}.json"
71
- path += "?#{URI.encode_www_form(query)}" if query.keys.size > 0
111
+ path += "?#{URI.encode_www_form(query)}" if query.keys.size.positive?
72
112
 
73
113
  case http_method
74
114
  when :get
@@ -83,7 +123,8 @@ module Supersaas
83
123
  req = Net::HTTP::Delete.new(path)
84
124
  req.body = params.to_json
85
125
  else
86
- raise Supersaas::Exception.new("Invalid HTTP Method: #{http_method}. Only `:get`, `:post`, `:put`, `:delete` supported.")
126
+ raise Supersaas::Exception,
127
+ "Invalid HTTP Method: #{http_method}. Only `:get`, `:post`, `:put`, `:delete` supported."
87
128
  end
88
129
 
89
130
  req.basic_auth account_name, api_key
@@ -93,10 +134,10 @@ module Supersaas
93
134
  req['User-Agent'] = self.class.user_agent
94
135
 
95
136
  if verbose
96
- puts "### SuperSaaS Client Request:"
137
+ puts '### SuperSaaS Client Request:'
97
138
  puts "#{http_method} #{path}"
98
139
  puts params.to_json
99
- puts "------------------------------"
140
+ puts '------------------------------'
100
141
  end
101
142
 
102
143
  @last_request = req
@@ -106,42 +147,71 @@ module Supersaas
106
147
  res = http.request(req)
107
148
  rescue Timeout::Error, Errno::EINVAL, Errno::ECONNRESET, EOFError,
108
149
  Net::HTTPBadResponse, Net::HTTPHeaderSyntaxError, Net::ProtocolError => e
109
- raise Supersaas::Exception.new("HTTP Request Error (#{uri}#{path}): #{e.message}")
150
+ raise Supersaas::Exception, "HTTP Request Error (#{uri}#{path}): #{e.message}"
110
151
  end
111
152
 
112
153
  if verbose
113
- puts "Response:"
154
+ puts 'Response:'
155
+ puts res.inspect
114
156
  puts res.body
115
- puts "=============================="
157
+ puts '=============================='
116
158
  end
117
159
 
118
160
  code = res.code.to_i
119
161
  case code
120
162
  when 200, 201
121
- json_body(res)
122
- when 422, 400
123
- json_body(res)
163
+ if http_method == :post && res['location'] =~ /www.supersaas.com/
164
+ res['location']
165
+ else
166
+ json_body(res)
167
+ end
168
+ else
169
+ handle_errors(code, res)
170
+ end
171
+ end
172
+
173
+ def handle_errors(code, res)
174
+ print_errors(res)
175
+ case code
176
+ when 422
177
+ raise Supersaas::Exception, 'HTTP Request Error: Unprocessable Content'
178
+ when 400
179
+ raise Supersaas::Exception, 'HTTP Request Error: Bad Request'
124
180
  when 401
125
- raise Supersaas::Exception.new("HTTP Request Error: Unauthorised")
181
+ raise Supersaas::Exception, 'HTTP Request Error: Unauthorised'
126
182
  when 404
127
- raise Supersaas::Exception.new("HTTP Request Error: Not Found")
183
+ raise Supersaas::Exception, 'HTTP Request Error: Not Found'
184
+ when 501
185
+ raise Supersaas::Exception, 'Not yet implemented for service type schedule'
186
+ when 403
187
+ raise Supersaas::Exception, 'Unauthorized'
188
+ when 405
189
+ raise Supersaas::Exception, 'Not available for capacity type schedule'
128
190
  else
129
- {}
191
+ raise Supersaas::Exception, "HTTP Request Error: #{code}"
130
192
  end
131
193
  end
132
194
 
133
- def json_body(res)
134
- begin
135
- res.body && res.body.size ? JSON.parse(res.body) : {}
136
- rescue JSON::ParserError
137
- {}
195
+ def print_errors(res)
196
+ json_body = json_body(res)
197
+ return unless json_body[:errors]
198
+
199
+ errors each do |error|
200
+ puts "Error code: #{error['code']}, #{error['title']}"
138
201
  end
139
202
  end
140
203
 
204
+ def json_body(res)
205
+ res.body&.size ? JSON.parse(res.body) : {}
206
+ rescue JSON::ParserError
207
+ {}
208
+ end
209
+
141
210
  def delete_blank_values(hash)
142
211
  return hash unless hash
143
- hash.delete_if do |k, v|
144
- v = v.delete_if { |k2, v2| v2.nil? } if (v.is_a?(Hash))
212
+
213
+ hash.delete_if do |_k, v|
214
+ v = v.compact if v.is_a?(Hash)
145
215
  v.nil? || v == ''
146
216
  end
147
217
  end
@@ -152,12 +222,12 @@ module Supersaas
152
222
  attr_accessor :account_name, :host, :api_key, :dry_run, :verbose
153
223
 
154
224
  def initialize
155
- @account_name = ENV['SSS_API_ACCOUNT_NAME']
156
- @api_key = ENV['SSS_API_KEY']
225
+ @account_name = ENV.fetch('SSS_API_ACCOUNT_NAME', nil)
226
+ @api_key = ENV.fetch('SSS_API_KEY', nil)
157
227
  @host = DEFAULT_HOST
158
228
  @dry_run = false
159
229
  @verbose = false
160
230
  end
161
231
  end
162
232
  end
163
- end
233
+ end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Supersaas
2
4
  class Exception < StandardError
3
5
  @field = nil
@@ -5,4 +7,4 @@ module Supersaas
5
7
 
6
8
  attr_accessor :field, :code
7
9
  end
8
- end
10
+ end
@@ -1,22 +1,19 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Supersaas
2
4
  class Appointment < BaseModel
3
- attr_accessor :address, :country, :created_by, :created_on, :deleted, :description, :email, :field_1, :field_2, :field_1_r, :field_2_r, :finish, :form_id, :full_name, :id, :mobile, :name, :phone, :price, :res_name, :resource_id, :schedule_id, :schedule_name, :service_id, :service_name, :slot_id, :start, :status, :super_field, :updated_by, :updated_on, :user_id, :waitlisted
5
+ attr_accessor :address, :country, :created_by, :created_on, :deleted, :description, :email, :field_1, :field_2,
6
+ :field_1_r, :field_2_r, :finish, :form_id, :full_name, :id, :mobile, :name, :phone, :price, :res_name,
7
+ :resource_id, :schedule_id, :schedule_name, :service_id, :service_name, :slot_id, :start, :status,
8
+ :super_field, :updated_by, :updated_on, :user_id, :waitlisted
4
9
  attr_reader :form, :slot
5
10
 
6
11
  def form=(value)
7
- if value.is_a?(Hash)
8
- @form = Supersaas::Form.new(value)
9
- else
10
- @form = value
11
- end
12
+ @form = value.is_a?(Hash) ? Supersaas::Form.new(value) : value
12
13
  end
13
14
 
14
15
  def slot=(value)
15
- if value.is_a?(Hash)
16
- @slot = Supersaas::Slot.new(value)
17
- else
18
- @slot = value
19
- end
16
+ @slot = value.is_a?(Hash) ? Supersaas::Slot.new(value) : value
20
17
  end
21
18
  end
22
- end
19
+ end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Supersaas
2
4
  class BaseModel
3
5
  attr_accessor :errors
@@ -12,8 +14,9 @@ module Supersaas
12
14
 
13
15
  def assign_attributes(attributes)
14
16
  attributes.each do |key, value|
17
+ self.class.module_eval { attr_accessor key }
15
18
  public_send("#{key}=", value) if respond_to?("#{key}=")
16
19
  end
17
20
  end
18
21
  end
19
- end
22
+ end
@@ -0,0 +1,12 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Supersaas
4
+ class FieldList < BaseModel
5
+ attr_accessor :name, :type, :label, :advanced
6
+ attr_reader :spec
7
+
8
+ def spec=(value)
9
+ @spec = value.is_a?(Array) ? value.map { |attributes| JSON.parse(attributes) } : value
10
+ end
11
+ end
12
+ end
@@ -1,5 +1,8 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Supersaas
2
4
  class Form < BaseModel
3
- attr_accessor :content, :created_on, :deleted, :id, :reservation_process_id, :super_form_id, :uniq, :updated_name, :updated_on, :user_id
5
+ attr_accessor :content, :created_on, :deleted, :id, :reservation_process_id, :super_form_id, :uniq, :updated_name,
6
+ :updated_on, :user_id
4
7
  end
5
- end
8
+ end
@@ -0,0 +1,7 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Supersaas
4
+ class Group < BaseModel
5
+ attr_accessor :id, :name
6
+ end
7
+ end
@@ -0,0 +1,7 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Supersaas
4
+ class Promotion < BaseModel
5
+ attr_accessor :id, :code, :description, :usage
6
+ end
7
+ end
@@ -1,5 +1,7 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Supersaas
2
4
  class Resource < BaseModel
3
5
  attr_accessor :id, :name
4
6
  end
5
- end
7
+ end
@@ -1,5 +1,7 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Supersaas
2
4
  class Schedule < BaseModel
3
5
  attr_accessor :id, :name
4
6
  end
5
- end
7
+ end
@@ -1,14 +1,12 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Supersaas
2
4
  class Slot < BaseModel
3
5
  attr_accessor :count, :description, :finish, :id, :location, :name, :start, :title
4
6
  attr_reader :bookings
5
7
 
6
8
  def bookings=(value)
7
- if value.is_a?(Array)
8
- @bookings = value.map {|attributes| Supersaas::Appointment.new(attributes) }
9
- else
10
- @bookings = value
11
- end
9
+ @bookings = value.is_a?(Array) ? value.map { |attributes| Supersaas::Appointment.new(attributes) } : value
12
10
  end
13
11
  end
14
- end
12
+ end
@@ -0,0 +1,7 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Supersaas
4
+ class SuperForm < BaseModel
5
+ attr_accessor :id, :name
6
+ end
7
+ end
@@ -1,16 +1,13 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Supersaas
2
4
  class User < BaseModel
3
- ROLES = [3, 4, -1]
5
+ ROLES = [3, 4, -1].freeze
4
6
 
5
- attr_accessor :address, :country, :created_on, :credit, :email, :field_1, :field_2, :fk, :full_name, :id, :mobile, :name, :phone, :role, :super_field
6
7
  attr_reader :form
7
8
 
8
9
  def form=(value)
9
- if value.is_a?(Hash)
10
- @form = Supersaas::Form.new(value)
11
- else
12
- @form = value
13
- end
10
+ @form = value.is_a?(Hash) ? Supersaas::Form.new(value) : value
14
11
  end
15
12
  end
16
- end
13
+ end
@@ -1,4 +1,6 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Supersaas
2
- API_VERSION = '2'
3
- VERSION = '1.1.0'
4
+ API_VERSION = '3'
5
+ VERSION = '2.0.0'
4
6
  end
@@ -1 +1,3 @@
1
- require_relative './supersaas'
1
+ # frozen_string_literal: true
2
+
3
+ require_relative 'supersaas'
data/lib/supersaas.rb CHANGED
@@ -1,15 +1,23 @@
1
- require "supersaas-api-client/version"
2
- require "supersaas-api-client/exception"
3
- require "supersaas-api-client/models/base_model"
4
- require "supersaas-api-client/models/appointment"
5
- require "supersaas-api-client/models/form"
6
- require "supersaas-api-client/models/resource"
7
- require "supersaas-api-client/models/schedule"
8
- require "supersaas-api-client/models/slot"
9
- require "supersaas-api-client/models/user"
10
- require "supersaas-api-client/api/base_api"
11
- require "supersaas-api-client/api/appointments"
12
- require "supersaas-api-client/api/forms"
13
- require "supersaas-api-client/api/schedules"
14
- require "supersaas-api-client/api/users"
15
- require "supersaas-api-client/client"
1
+ # frozen_string_literal: true
2
+
3
+ require 'supersaas-api-client/version'
4
+ require 'supersaas-api-client/exception'
5
+ require 'supersaas-api-client/models/base_model'
6
+ require 'supersaas-api-client/models/appointment'
7
+ require 'supersaas-api-client/models/field_list'
8
+ require 'supersaas-api-client/models/form'
9
+ require 'supersaas-api-client/models/super_form'
10
+ require 'supersaas-api-client/models/group'
11
+ require 'supersaas-api-client/models/resource'
12
+ require 'supersaas-api-client/models/schedule'
13
+ require 'supersaas-api-client/models/promotion'
14
+ require 'supersaas-api-client/models/slot'
15
+ require 'supersaas-api-client/models/user'
16
+ require 'supersaas-api-client/api/base_api'
17
+ require 'supersaas-api-client/api/appointments'
18
+ require 'supersaas-api-client/api/forms'
19
+ require 'supersaas-api-client/api/schedules'
20
+ require 'supersaas-api-client/api/groups'
21
+ require 'supersaas-api-client/api/promotions'
22
+ require 'supersaas-api-client/api/users'
23
+ require 'supersaas-api-client/client'
@@ -1,27 +1,28 @@
1
- $:.push File.expand_path('../lib', __FILE__)
1
+ # frozen_string_literal: true
2
2
 
3
- require "supersaas-api-client/version"
3
+ $LOAD_PATH.push File.expand_path('lib', __dir__)
4
+
5
+ require 'supersaas-api-client/version'
4
6
 
5
7
  Gem::Specification.new do |spec|
6
- spec.name = "supersaas-api-client"
8
+ spec.name = 'supersaas-api-client'
7
9
  spec.version = Supersaas::VERSION
8
- spec.authors = ["Travis Dunn"]
9
- spec.email = ["travis@supersaas.com"]
10
+ spec.authors = ['Kaarle Kulvik']
11
+ spec.email = ['kaarle@supersaas.com']
10
12
 
11
- spec.summary = %q{Online bookings/appointments/calendars using the SuperSaaS scheduling platform.}
12
- spec.description = %q{Online appointment scheduler for any type of business. Flexible and affordable booking software that can be integrated into any site. Free basic version.}
13
- spec.homepage = "https://www.supersaas.com"
14
- spec.license = "MIT"
13
+ spec.summary = 'Manage appointments and users on the SuperSaaS scheduling platform'
14
+ spec.description = 'Online appointment scheduling for any type of business. Flexible and affordable booking software that can be integrated into any site. Free basic version.'
15
+ spec.homepage = 'https://www.supersaas.com'
16
+ spec.license = 'MIT'
15
17
 
16
- spec.files = `git ls-files -z`.split("\x0").reject do |f|
17
- f.match(%r{^(test)/})
18
- end
19
- spec.test_files = Dir['test/**/*']
20
- spec.bindir = "bin"
18
+ spec.files = `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^test/}) }
19
+ spec.bindir = 'bin'
21
20
  spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
22
- spec.require_paths = ["lib"]
21
+ spec.require_paths = ['lib']
23
22
 
24
- spec.add_development_dependency "bundler", "~> 1.17.3"
25
- spec.add_development_dependency "rake", "~> 10.0"
26
- spec.add_development_dependency "minitest", "~> 5.0"
23
+ spec.add_development_dependency 'bundler'
24
+ spec.add_development_dependency 'minitest'
25
+ spec.add_development_dependency 'rake'
26
+ spec.add_development_dependency 'rubocop'
27
+ spec.metadata['rubygems_mfa_required'] = 'true'
27
28
  end