squarespace_api 0.0.4

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/.rspec +1 -0
  3. data/Gemfile +3 -0
  4. data/Gemfile.lock +79 -0
  5. data/README.md +3 -0
  6. data/lib/helper/string.rb +13 -0
  7. data/lib/helper/uri_component_builder.rb +14 -0
  8. data/lib/squarespace_api/client.rb +50 -0
  9. data/lib/squarespace_api/config.rb +27 -0
  10. data/lib/squarespace_api/connection.rb +110 -0
  11. data/lib/squarespace_api/paginated_fetch.rb +13 -0
  12. data/lib/squarespace_api/resource.rb +19 -0
  13. data/lib/squarespace_api/resource_group.rb +35 -0
  14. data/lib/squarespace_api/resource_group_actions.rb +70 -0
  15. data/lib/squarespace_api/resource_groups/inventory.rb +17 -0
  16. data/lib/squarespace_api/resource_groups/inventory_adjustments.rb +8 -0
  17. data/lib/squarespace_api/resource_groups/order_fulfillments.rb +8 -0
  18. data/lib/squarespace_api/resource_groups/orders.rb +18 -0
  19. data/lib/squarespace_api/resource_groups/product_images.rb +29 -0
  20. data/lib/squarespace_api/resource_groups/product_variant_images.rb +8 -0
  21. data/lib/squarespace_api/resource_groups/product_variants.rb +8 -0
  22. data/lib/squarespace_api/resource_groups/products.rb +19 -0
  23. data/lib/squarespace_api/resource_groups/profiles.rb +23 -0
  24. data/lib/squarespace_api/resource_groups/store_pages.rb +14 -0
  25. data/lib/squarespace_api/resource_groups/tokens.rb +14 -0
  26. data/lib/squarespace_api/resource_groups/transactions.rb +19 -0
  27. data/lib/squarespace_api/resource_groups/webhook_subscriptions.rb +22 -0
  28. data/lib/squarespace_api/resources/website.rb +7 -0
  29. data/lib/squarespace_api/version.rb +3 -0
  30. data/lib/squarespace_api.rb +26 -0
  31. data/spec/fixtures/order_response.json +126 -0
  32. data/spec/fixtures/orders_response.json +151 -0
  33. data/spec/spec_helper.rb +9 -0
  34. data/spec/squarespace_api/client_spec.rb +80 -0
  35. data/spec/squarespace_api/config_spec.rb +23 -0
  36. data/spec/squarespace_api/connection_spec.rb +58 -0
  37. data/spec/squarespace_api/resource_group_actions_spec.rb +71 -0
  38. data/spec/squarespace_api/resource_groups/orders_spec.rb +18 -0
  39. data/spec/squarespace_api/resource_groups/product_images_spec.rb +25 -0
  40. data/spec/squarespace_api/resource_groups/tokens_spec.rb +32 -0
  41. data/spec/squarespace_api/resource_groups/webhook_subscriptions_spec.rb +29 -0
  42. data/spec/squarespace_api/resource_spec.rb +19 -0
  43. data/spec/squarespace_api_spec.rb +21 -0
  44. data/squarespace_api.gemspec +22 -0
  45. metadata +196 -0
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: fc908a714e0fa1658267c8753adcbd9085e87bd2b0b46a108231e06b53a20f6b
4
+ data.tar.gz: 18a4ba216bc82ab428b5ee8c7352f4f8a23d9ab98630f6a469961860242a8871
5
+ SHA512:
6
+ metadata.gz: b2f62e190db5adc017b6d47933fc0e5fe28e10199098c1f148a1f4d2a10b7e5ec7efc95392f6afc22a2a53844d893733e1c815abba7d42135744332593640189
7
+ data.tar.gz: 73283ff1f0f272f39b3cd46c8db5651ae8316539663276f6225b0608c2304a637c02e37fd9d529fb300b33e1436a3f874a871cd014db148ce4d339b0d377999a
data/.rspec ADDED
@@ -0,0 +1 @@
1
+ --require spec_helper
data/Gemfile ADDED
@@ -0,0 +1,3 @@
1
+ source 'https://rubygems.org'
2
+
3
+ gemspec
data/Gemfile.lock ADDED
@@ -0,0 +1,79 @@
1
+ PATH
2
+ remote: .
3
+ specs:
4
+ squarespace_api (0.0.3)
5
+ faraday
6
+ faraday_middleware
7
+ json
8
+ yaml
9
+
10
+ GEM
11
+ remote: https://rubygems.org/
12
+ specs:
13
+ addressable (2.8.0)
14
+ public_suffix (>= 2.0.2, < 5.0)
15
+ coderay (1.1.3)
16
+ crack (0.4.5)
17
+ rexml
18
+ diff-lcs (1.4.4)
19
+ faraday (1.7.0)
20
+ faraday-em_http (~> 1.0)
21
+ faraday-em_synchrony (~> 1.0)
22
+ faraday-excon (~> 1.1)
23
+ faraday-httpclient (~> 1.0.1)
24
+ faraday-net_http (~> 1.0)
25
+ faraday-net_http_persistent (~> 1.1)
26
+ faraday-patron (~> 1.0)
27
+ faraday-rack (~> 1.0)
28
+ multipart-post (>= 1.2, < 3)
29
+ ruby2_keywords (>= 0.0.4)
30
+ faraday-em_http (1.0.0)
31
+ faraday-em_synchrony (1.0.0)
32
+ faraday-excon (1.1.0)
33
+ faraday-httpclient (1.0.1)
34
+ faraday-net_http (1.0.1)
35
+ faraday-net_http_persistent (1.2.0)
36
+ faraday-patron (1.0.0)
37
+ faraday-rack (1.0.0)
38
+ faraday_middleware (1.1.0)
39
+ faraday (~> 1.0)
40
+ hashdiff (1.0.1)
41
+ json (2.5.1)
42
+ method_source (1.0.0)
43
+ multipart-post (2.1.1)
44
+ pry (0.14.1)
45
+ coderay (~> 1.1)
46
+ method_source (~> 1.0)
47
+ public_suffix (4.0.6)
48
+ rexml (3.2.5)
49
+ rspec (3.10.0)
50
+ rspec-core (~> 3.10.0)
51
+ rspec-expectations (~> 3.10.0)
52
+ rspec-mocks (~> 3.10.0)
53
+ rspec-core (3.10.1)
54
+ rspec-support (~> 3.10.0)
55
+ rspec-expectations (3.10.1)
56
+ diff-lcs (>= 1.2.0, < 2.0)
57
+ rspec-support (~> 3.10.0)
58
+ rspec-mocks (3.10.2)
59
+ diff-lcs (>= 1.2.0, < 2.0)
60
+ rspec-support (~> 3.10.0)
61
+ rspec-support (3.10.2)
62
+ ruby2_keywords (0.0.5)
63
+ webmock (3.14.0)
64
+ addressable (>= 2.8.0)
65
+ crack (>= 0.3.2)
66
+ hashdiff (>= 0.4.0, < 2.0.0)
67
+ yaml (0.1.1)
68
+
69
+ PLATFORMS
70
+ ruby
71
+
72
+ DEPENDENCIES
73
+ pry
74
+ rspec
75
+ squarespace_api!
76
+ webmock
77
+
78
+ BUNDLED WITH
79
+ 1.17.3
data/README.md ADDED
@@ -0,0 +1,3 @@
1
+ # Squarespace Api
2
+
3
+ Ruby interface to the Squarespace API
@@ -0,0 +1,13 @@
1
+ class String
2
+ def to_snakecase
3
+ self.gsub(/::/, '/').
4
+ gsub(/([A-Z]+)([A-Z][a-z])/,'\1_\2').
5
+ gsub(/([a-z\d])([A-Z])/,'\1_\2').
6
+ tr("-", "_").
7
+ downcase
8
+ end
9
+
10
+ def to_camelcase
11
+ self.split('_').collect(&:capitalize).join
12
+ end
13
+ end
@@ -0,0 +1,14 @@
1
+ class UriComponentBuidler
2
+ def self.construct(path, params)
3
+ path = path.dup
4
+ path_params = path.split('/').select { |s| s.start_with?(':') }.map { |s| s[1..-1].to_sym }
5
+
6
+ path_params.each do |key|
7
+ raise ArgumentError, "#{key} should be passed in params" unless params[key]
8
+ path.sub!(":#{key}", params[key].to_s)
9
+ params.delete(key)
10
+ end
11
+
12
+ path.end_with?('/') ? path[0..-2] : path
13
+ end
14
+ end
@@ -0,0 +1,50 @@
1
+ module SquarespaceApi
2
+ class Client
3
+ def initialize(config = nil)
4
+ @config = config || SquarespaceApi.config
5
+ @connection = Connection.new(@config)
6
+ end
7
+
8
+ %w(
9
+ orders
10
+ order_fulfillments
11
+ products
12
+ product_variants
13
+ product_images
14
+ product_variant_images
15
+ profiles
16
+ store_pages
17
+ inventory
18
+ inventory_adjustments
19
+ transactions
20
+ webhook_subscriptions
21
+ tokens
22
+ ).each do |resource|
23
+ define_method(resource) do
24
+ @connection.with_app_session do
25
+ return instance_variable_get(:"@_#{resource}") if instance_variable_get(:"@_#{resource}")
26
+ instance_variable_set(
27
+ :"@_#{resource}",
28
+ Module
29
+ .const_get("SquarespaceApi::ResourceGroups::#{resource.to_camelcase}")
30
+ .new(connection: @connection)
31
+ )
32
+ end
33
+ end
34
+ end
35
+
36
+ %w(website).each do |resource|
37
+ define_method(resource) do
38
+ @connection.with_app_session do
39
+ Module.const_get("SquarespaceApi::Resources::#{resource.to_camelcase}").new(connection: @connection).get
40
+ end
41
+ end
42
+ end
43
+
44
+ def build_oauth_authorize_url(params)
45
+ @config.oauth_base_url +
46
+ '/authorize?' +
47
+ { client_id: @config.client_id }.merge(params).map { |k, v| "#{k}=#{v}" }.join('&')
48
+ end
49
+ end
50
+ end
@@ -0,0 +1,27 @@
1
+ module SquarespaceApi
2
+ class Config
3
+ STABLE_VERSION = '1.0'.freeze
4
+ attr_accessor :client_id, :client_secret,
5
+ :api_version, :access_token,
6
+ :base_url
7
+
8
+ def initialize(options = {})
9
+ @api_version = options[:api_version] || STABLE_VERSION
10
+ @access_token = options[:access_token]
11
+ @client_id = options[:client_id] || ENV['SQUARESPACE_CLIENT_ID']
12
+ @client_secret = options[:client_secret] || ENV['SQUARESPACE_CLIENT_SECRET']
13
+ end
14
+
15
+ def base_url
16
+ "https://api.squarespace.com".freeze
17
+ end
18
+
19
+ def oauth_base_url
20
+ "https://login.squarespace.com/api/1/login/oauth/provider".freeze
21
+ end
22
+
23
+ def encoded_oauth_token
24
+ Base64.strict_encode64("#{client_id}:#{client_secret}").to_s
25
+ end
26
+ end
27
+ end
@@ -0,0 +1,110 @@
1
+ require 'securerandom'
2
+ require "faraday"
3
+ require 'faraday_middleware'
4
+ require "json"
5
+
6
+ module SquarespaceApi
7
+ class Connection
8
+ DEFAULT_HEADERS = {
9
+ 'Content-Type' => 'application/json',
10
+ 'User-Agent' => 'SquarespaceApi'
11
+ }.freeze
12
+
13
+ attr_reader :config
14
+
15
+ def initialize(config)
16
+ @config = config
17
+ @connection = Faraday.new do |connection|
18
+ connection.headers = DEFAULT_HEADERS
19
+ connection.response :json
20
+ end
21
+
22
+ initialize_app_session if config.access_token
23
+ end
24
+
25
+ def get(path, params: {}, headers: {})
26
+ handle_response(connection.get(path, params, connection.headers.merge(headers)))
27
+ end
28
+
29
+ def post(path, params: {}, headers: {})
30
+ handle_response(connection.post(path, params, connection.headers.merge(headers)))
31
+ end
32
+
33
+ def delete(path, params: {}, headers: {})
34
+ handle_response(connection.delete(path, params, connection.headers.merge(headers)))
35
+ end
36
+
37
+ def upload_file(path, file_path)
38
+ temp_connection = Faraday.new(url: api_base_url) do |f|
39
+ f.request :multipart
40
+ f.response :json
41
+ f.headers = DEFAULT_HEADERS.merge(
42
+ 'Authorization' => "Bearer #{config.access_token}",
43
+ 'Content-Type' => 'multipart/form-data',
44
+ )
45
+ end.post(path, { file: Faraday::FilePart.new(file_path, 'text/x-ruby') })
46
+ end
47
+
48
+ def with_idempotency_key
49
+ @connection.headers['Idempotency-Key'] = SecureRandom.hex
50
+ yield
51
+ end
52
+
53
+ def with_app_session
54
+ initialize_app_session
55
+ yield
56
+ end
57
+
58
+ def initialize_app_session
59
+ @connection.headers['Authorization'] = "Bearer #{config.access_token}"
60
+ @connection.url_prefix = api_base_url
61
+ self
62
+ end
63
+
64
+ def with_oauth_session
65
+ initialize_oauth_session
66
+ yield
67
+ end
68
+
69
+ def initialize_oauth_session
70
+ @connection.headers['Authorization'] = "Basic #{config.encoded_oauth_token}"
71
+ @connection.url_prefix = config.oauth_base_url
72
+ self
73
+ end
74
+
75
+ private
76
+
77
+ attr_reader :connection
78
+
79
+ def api_base_url
80
+ "#{config.base_url}/#{config.api_version}"
81
+ end
82
+
83
+ def handle_response(response)
84
+ return response if response.success?
85
+ error_message = response.body.dig('message')
86
+ case response.status
87
+ when 400
88
+ raise SquarespaceApi::Errors::BadRequest, error_message
89
+ when 401
90
+ raise SquarespaceApi::Errors::Unauthorized, error_message
91
+ when 404
92
+ raise SquarespaceApi::Errors::NotFound, error_message
93
+ when 405
94
+ raise SquarespaceApi::Errors::MethodNotAllowed, error_message
95
+ when 429
96
+ raise SquarespaceApi::Errors::TooManyRequests, error_message
97
+ else
98
+ response
99
+ end
100
+ end
101
+ end
102
+
103
+ module Errors
104
+ class BadRequest < StandardError; end
105
+ class Unauthorized < StandardError; end
106
+ class NotFound < StandardError; end
107
+ class MethodNotAllowed < StandardError; end
108
+ class TooManyRequests < StandardError; end
109
+ end
110
+ end
@@ -0,0 +1,13 @@
1
+ module SquarespaceApi
2
+ module PaginatedFetch
3
+ def self.build(params = {}, &_block)
4
+ loop do
5
+ response = yield(params)
6
+
7
+ has_next_page = response.dig('pagination', 'hasNextPage').to_s == 'true'
8
+ break unless has_next_page
9
+ params = { cursor: response.dig('pagination', 'nextPageCursor') }
10
+ end
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,19 @@
1
+ module SquarespaceApi
2
+ class Resource
3
+ def initialize(connection:)
4
+ @connection = connection
5
+ end
6
+
7
+ def resource_path
8
+ self.class::PATH
9
+ end
10
+
11
+ def get
12
+ connection.get(resource_path).body
13
+ end
14
+
15
+ protected
16
+
17
+ attr_reader :connection
18
+ end
19
+ end
@@ -0,0 +1,35 @@
1
+ module SquarespaceApi
2
+ class ResourceGroup
3
+ def initialize(connection:)
4
+ @connection = connection
5
+ end
6
+
7
+ protected
8
+
9
+ attr_reader :connection, :resource, :resource_path
10
+
11
+ def resource_path
12
+ resources_path + "/:id"
13
+ end
14
+
15
+ def resources_path
16
+ self.class::PATH
17
+ end
18
+
19
+ def parse(response)
20
+ response.body || true
21
+ end
22
+
23
+ def parse_collection
24
+ raise 'This method should be implemented in a subclass.'
25
+ end
26
+
27
+ class << self
28
+ def allowed_actions(*args)
29
+ args.each do |action|
30
+ self.send(:include, Module.const_get("SquarespaceApi::ResourceGroupActions::#{action.to_s.to_camelcase}"))
31
+ end
32
+ end
33
+ end
34
+ end
35
+ end
@@ -0,0 +1,70 @@
1
+ require 'squarespace_api/paginated_fetch'
2
+ require 'helper/uri_component_builder'
3
+
4
+ module SquarespaceApi
5
+ module ResourceGroupActions
6
+ module All
7
+ def all(params = {}, &_block)
8
+ PaginatedFetch.build(params) do |paginated_params|
9
+ response = parse_collection(
10
+ connection
11
+ .get(UriComponentBuidler.construct(resources_path, paginated_params), params: paginated_params)
12
+ )
13
+ return response unless block_given?
14
+ yield(response)
15
+ response
16
+ end
17
+ end
18
+
19
+ alias_method :where, :all
20
+ end
21
+
22
+ module Find
23
+ def find(id, params = {})
24
+ parse(
25
+ connection
26
+ .get(UriComponentBuidler.construct(resource_path, params.merge(id: id)))
27
+ )
28
+ end
29
+ end
30
+
31
+ module FindByIds
32
+ def find_by_ids(ids = [])
33
+ parse_collection(
34
+ connection
35
+ .get(UriComponentBuidler.construct(resource_path, { id: ids.join(",") }))
36
+ )
37
+ end
38
+ end
39
+
40
+ module Create
41
+ def create(params = {})
42
+ connection.with_idempotency_key do
43
+ parse(
44
+ connection
45
+ .post(UriComponentBuidler.construct(resources_path, params), params: params.to_json)
46
+ )
47
+ end
48
+ end
49
+ end
50
+
51
+ module Update
52
+ def update(id, params = {})
53
+ params = params.merge(id: id)
54
+ parse(
55
+ connection
56
+ .post(UriComponentBuidler.construct(resource_path, params), params: params.to_json)
57
+ )
58
+ end
59
+ end
60
+
61
+ module Delete
62
+ def delete(id, params = {})
63
+ parse(
64
+ connection
65
+ .delete(UriComponentBuidler.construct(resource_path, params.merge(id: id)))
66
+ )
67
+ end
68
+ end
69
+ end
70
+ end