flex_commerce_api 0.6.57

Sign up to get free protection for your applications and to get access to all the features.
Files changed (170) hide show
  1. checksums.yaml +7 -0
  2. data/.env.example +6 -0
  3. data/.gitignore +14 -0
  4. data/.rspec +4 -0
  5. data/.rubocop.yml +1065 -0
  6. data/.ruby-gemset +1 -0
  7. data/.ruby-version +1 -0
  8. data/.travis.yml +3 -0
  9. data/Gemfile +4 -0
  10. data/LICENSE.txt +21 -0
  11. data/README.md +56 -0
  12. data/Rakefile +1 -0
  13. data/app/models/address.rb +41 -0
  14. data/app/models/asset_file.rb +26 -0
  15. data/app/models/asset_folder.rb +14 -0
  16. data/app/models/bundle.rb +20 -0
  17. data/app/models/bundle_group.rb +15 -0
  18. data/app/models/cart.rb +136 -0
  19. data/app/models/category.rb +70 -0
  20. data/app/models/category_tree.rb +11 -0
  21. data/app/models/component.rb +8 -0
  22. data/app/models/container_coupon.rb +12 -0
  23. data/app/models/country.rb +11 -0
  24. data/app/models/coupon.rb +18 -0
  25. data/app/models/customer_account.rb +96 -0
  26. data/app/models/customer_account_authentication.rb +5 -0
  27. data/app/models/customer_segment.rb +6 -0
  28. data/app/models/customer_segment_member.rb +6 -0
  29. data/app/models/data_attribute.rb +6 -0
  30. data/app/models/data_store_record.rb +9 -0
  31. data/app/models/data_store_type.rb +9 -0
  32. data/app/models/discount_summary.rb +12 -0
  33. data/app/models/email.rb +5 -0
  34. data/app/models/ewis_opt_in.rb +8 -0
  35. data/app/models/external_url.rb +6 -0
  36. data/app/models/free_shipping_promotion.rb +12 -0
  37. data/app/models/import.rb +6 -0
  38. data/app/models/import_entry.rb +6 -0
  39. data/app/models/line_item.rb +34 -0
  40. data/app/models/line_item_discount.rb +7 -0
  41. data/app/models/markdown_price.rb +11 -0
  42. data/app/models/menu.rb +36 -0
  43. data/app/models/menu_item.rb +7 -0
  44. data/app/models/menu_item_item.rb +5 -0
  45. data/app/models/note.rb +18 -0
  46. data/app/models/order.rb +38 -0
  47. data/app/models/password_recovery.rb +20 -0
  48. data/app/models/payment_address_verification.rb +13 -0
  49. data/app/models/payment_process.rb +13 -0
  50. data/app/models/payment_provider.rb +15 -0
  51. data/app/models/payment_transaction.rb +13 -0
  52. data/app/models/product.rb +99 -0
  53. data/app/models/product_asset_file.rb +12 -0
  54. data/app/models/promotion.rb +19 -0
  55. data/app/models/promotion_qualifying_product_exclusion.rb +8 -0
  56. data/app/models/redirect.rb +14 -0
  57. data/app/models/refund.rb +14 -0
  58. data/app/models/remote_address.rb +22 -0
  59. data/app/models/remote_line_item.rb +11 -0
  60. data/app/models/remote_order.rb +15 -0
  61. data/app/models/remote_shipping_method.rb +12 -0
  62. data/app/models/report.rb +18 -0
  63. data/app/models/report_invocation.rb +18 -0
  64. data/app/models/retail_store.rb +18 -0
  65. data/app/models/role.rb +6 -0
  66. data/app/models/search_suggestion.rb +17 -0
  67. data/app/models/section.rb +9 -0
  68. data/app/models/session.rb +8 -0
  69. data/app/models/shipping_method.rb +26 -0
  70. data/app/models/slug.rb +19 -0
  71. data/app/models/static_page.rb +60 -0
  72. data/app/models/static_page_folder.rb +8 -0
  73. data/app/models/stock_level.rb +21 -0
  74. data/app/models/tax_code.rb +6 -0
  75. data/app/models/taxonomy.rb +5 -0
  76. data/app/models/template.rb +9 -0
  77. data/app/models/template_component.rb +11 -0
  78. data/app/models/template_definition.rb +12 -0
  79. data/app/models/template_section.rb +12 -0
  80. data/app/models/user.rb +8 -0
  81. data/app/models/user_profile.rb +6 -0
  82. data/app/models/v2/create_order.rb +10 -0
  83. data/app/models/v2/deallocate_order.rb +10 -0
  84. data/app/models/v2/line_item.rb +9 -0
  85. data/app/models/v2/order.rb +9 -0
  86. data/app/models/v2/unallocate_order.rb +10 -0
  87. data/app/models/variant.rb +18 -0
  88. data/app/models/webhook.rb +17 -0
  89. data/app/services/param_to_shql.rb +72 -0
  90. data/app/services/surrogate_keys.rb +44 -0
  91. data/bin/console +14 -0
  92. data/bin/setup +7 -0
  93. data/config/locales/payments.en.yml +3 -0
  94. data/flex-commerce-api.gemspec +41 -0
  95. data/lib/flex_commerce.rb +95 -0
  96. data/lib/flex_commerce_api.rb +21 -0
  97. data/lib/flex_commerce_api/api_base.rb +11 -0
  98. data/lib/flex_commerce_api/base_resource.rb +250 -0
  99. data/lib/flex_commerce_api/config.rb +55 -0
  100. data/lib/flex_commerce_api/error/access_denied.rb +6 -0
  101. data/lib/flex_commerce_api/error/bad_request.rb +10 -0
  102. data/lib/flex_commerce_api/error/base.rb +12 -0
  103. data/lib/flex_commerce_api/error/client_error.rb +7 -0
  104. data/lib/flex_commerce_api/error/connection_error.rb +6 -0
  105. data/lib/flex_commerce_api/error/internal_server.rb +37 -0
  106. data/lib/flex_commerce_api/error/not_found.rb +13 -0
  107. data/lib/flex_commerce_api/error/record_invalid.rb +16 -0
  108. data/lib/flex_commerce_api/error/unexpected_status.rb +7 -0
  109. data/lib/flex_commerce_api/errors.rb +13 -0
  110. data/lib/flex_commerce_api/json_api_client_extension/builder.rb +28 -0
  111. data/lib/flex_commerce_api/json_api_client_extension/capture_surrogate_keys_middleware.rb +16 -0
  112. data/lib/flex_commerce_api/json_api_client_extension/flexible_connection.rb +59 -0
  113. data/lib/flex_commerce_api/json_api_client_extension/has_many_association_proxy.rb +60 -0
  114. data/lib/flex_commerce_api/json_api_client_extension/included_data.rb +27 -0
  115. data/lib/flex_commerce_api/json_api_client_extension/json_format_middleware.rb +20 -0
  116. data/lib/flex_commerce_api/json_api_client_extension/logging_middleware.rb +24 -0
  117. data/lib/flex_commerce_api/json_api_client_extension/paginator.rb +26 -0
  118. data/lib/flex_commerce_api/json_api_client_extension/parse_json.rb +23 -0
  119. data/lib/flex_commerce_api/json_api_client_extension/parsers/parser.rb +16 -0
  120. data/lib/flex_commerce_api/json_api_client_extension/previewed_request_middleware.rb +17 -0
  121. data/lib/flex_commerce_api/json_api_client_extension/remote_builder.rb +29 -0
  122. data/lib/flex_commerce_api/json_api_client_extension/requestor.rb +42 -0
  123. data/lib/flex_commerce_api/json_api_client_extension/save_request_body_middleware.rb +20 -0
  124. data/lib/flex_commerce_api/json_api_client_extension/status_middleware.rb +40 -0
  125. data/lib/flex_commerce_api/v2/api_base.rb +13 -0
  126. data/lib/flex_commerce_api/version.rb +3 -0
  127. data/lib/json_erb.rb +9 -0
  128. data/lib/json_struct.rb +73 -0
  129. data/lib/patches.rb +4 -0
  130. data/lib/patches/json_api_client/resource.rb +50 -0
  131. data/lib/paypal_express.rb +3 -0
  132. data/lib/paypal_express/additional_info.rb +45 -0
  133. data/lib/paypal_express/api.rb +86 -0
  134. data/lib/paypal_express/auth.rb +83 -0
  135. data/lib/paypal_express/cart_shipping_method.rb +38 -0
  136. data/lib/paypal_express/exception/access_denied.rb +10 -0
  137. data/lib/paypal_express/exception/connection_error.rb +10 -0
  138. data/lib/paypal_express/exception/not_authorized.rb +10 -0
  139. data/lib/paypal_express/exception/transaction.rb +15 -0
  140. data/lib/paypal_express/generate_summary.rb +118 -0
  141. data/lib/paypal_express/process/paypal_params.rb +123 -0
  142. data/lib/paypal_express/process/response_parser.rb +146 -0
  143. data/lib/paypal_express/setup.rb +94 -0
  144. data/lib/paypal_express/shipping_methods_for_cart.rb +46 -0
  145. data/lib/retry.rb +20 -0
  146. data/schemas/jsonapi/schema.json +370 -0
  147. data/schemas/shift/v1/documents/collection/address.json +45 -0
  148. data/schemas/shift/v1/documents/collection/asset_file.json +43 -0
  149. data/schemas/shift/v1/documents/collection/asset_folder.json +43 -0
  150. data/schemas/shift/v1/documents/collection/customer_account.json +50 -0
  151. data/schemas/shift/v1/documents/collection/markdown_price.json +43 -0
  152. data/schemas/shift/v1/documents/collection/product.json +43 -0
  153. data/schemas/shift/v1/documents/collection/variant.json +43 -0
  154. data/schemas/shift/v1/documents/member/address.json +39 -0
  155. data/schemas/shift/v1/documents/member/asset_file.json +37 -0
  156. data/schemas/shift/v1/documents/member/asset_folder.json +39 -0
  157. data/schemas/shift/v1/documents/member/customer_account.json +44 -0
  158. data/schemas/shift/v1/documents/member/markdown_price.json +37 -0
  159. data/schemas/shift/v1/documents/member/product.json +39 -0
  160. data/schemas/shift/v1/documents/member/variant.json +46 -0
  161. data/schemas/shift/v1/resources/address.json +130 -0
  162. data/schemas/shift/v1/resources/asset_file.json +146 -0
  163. data/schemas/shift/v1/resources/asset_folder.json +188 -0
  164. data/schemas/shift/v1/resources/customer_account.json +339 -0
  165. data/schemas/shift/v1/resources/markdown_price.json +52 -0
  166. data/schemas/shift/v1/resources/product.json +230 -0
  167. data/schemas/shift/v1/resources/variant.json +298 -0
  168. data/tasks/json_schema.thor +275 -0
  169. data/todo.md +8 -0
  170. metadata +470 -0
@@ -0,0 +1,94 @@
1
+ require_relative 'api'
2
+
3
+ # @module FlexCommerce::PaypalExpress
4
+ module FlexCommerce
5
+ module PaypalExpress
6
+ # @class Setup
7
+ #
8
+ # This is the main class, which talks to ActiveMerchant gem to initiate a transaction using Paypal
9
+ class Setup
10
+ include ::FlexCommerce::PaypalExpress::Api
11
+
12
+
13
+ # @initialize
14
+ #
15
+ # @param {FlexCommerce::PaymentProviderSetup} payment_provider_setup
16
+ # @param {FlexCommerce::Cart} cart
17
+ # @param {Paypal Gateway} [gateway_class = ::ActiveMerchant::Billing::PaypalExpressGateway]
18
+ # @param {URL} success_url - Generally Paypal confirmation page
19
+ # @param {URL} cancel_url - Generally new transaction page
20
+ # @param {IP} ip_address - User ip address
21
+ # @param {boolean} [allow_shipping_change = true] - true: display shipping options, false: dont display shipping options
22
+ # @param {URL} callback_url - Generally cart show page
23
+ # @param {FlexCommerce::ShippingMethod} shipping_method_model = FlexCommerce::ShippingMethod
24
+ # @param {boolean} [use_mobile_payments = false]
25
+ # @param {String} [description = nil]
26
+ #
27
+ # @note:
28
+ # For `::ActiveMerchant::Billing::PaypalExpressGateway` to work
29
+ # rails-site should include active merchant gem. Ideally this gem should be included in the gemspec.
30
+ # But as we are using custom gem, which is not published to ruby gems, there is no way of including it within this gem dependency
31
+ def initialize(cart:, gateway_class: ::ActiveMerchant::Billing::PaypalExpressGateway, success_url:, cancel_url:, ip_address:, allow_shipping_change: true, callback_url:, shipping_method_model: FlexCommerce::ShippingMethod, use_mobile_payments: false, description: nil)
32
+ self.gateway_class = gateway_class
33
+ self.cart = cart
34
+ self.allow_shipping_change = allow_shipping_change
35
+ self.success_url = success_url
36
+ self.cancel_url = cancel_url
37
+ self.ip_address = ip_address
38
+ self.callback_url = callback_url
39
+ self.shipping_method_model = shipping_method_model
40
+ self.use_mobile_payments = use_mobile_payments
41
+ self.description = description
42
+ end
43
+
44
+ def call
45
+ validate_shipping_method
46
+
47
+ response = gateway.setup_order(convert_amount(cart.total), paypal_params)
48
+ # If paypal setup went fine, redirect to the paypal page
49
+ if response.success?
50
+ PaypalSetup.new(setup_type: "redirect", redirect_url: gateway.redirect_url_for(response.token, mobile: use_mobile_payments))
51
+ else
52
+ # @TODO Find out where to get the message from and add it
53
+ error = "An error occured communicating with paypal #{response.message} \n\n#{response.params.to_json}. Total sent was #{convert_amount(cart.total)} Parameters sent were \n\n#{paypal_params}"
54
+ raise ::FlexCommerce::PaypalExpress::Exception::AccessDenied.new(error)
55
+ end
56
+ rescue ::FlexCommerce::PaypalExpress::Exception::AccessDenied => exception
57
+ PaypalSetup.new(errors: exception)
58
+ end
59
+
60
+ private
61
+
62
+ attr_accessor :description, :cart, :gateway_class, :success_url, :cancel_url, :ip_address, :allow_shipping_change, :callback_url, :shipping_method_model, :use_mobile_payments
63
+
64
+ def paypal_params
65
+ Process::PaypalParams.new(
66
+ cart: cart,
67
+ success_url: success_url,
68
+ cancel_url: cancel_url,
69
+ ip_address: ip_address,
70
+ allow_shipping_change: allow_shipping_change,
71
+ callback_url: callback_url,
72
+ shipping_method_model: shipping_method_model,
73
+ use_mobile_payments: use_mobile_payments,
74
+ description: description
75
+ ).call
76
+ end
77
+
78
+ # @method shipping_methods
79
+ #
80
+ # @returns shipping methods with promotions applied
81
+ def shipping_methods
82
+ @shipping_methods ||= ShippingMethodsForCart.new(cart: cart, shipping_methods: shipping_method_model.all).call.sort_by(&:total)
83
+ end
84
+
85
+ def validate_shipping_method
86
+ unless cart.shipping_method_id.nil? || shipping_methods.any? {|sm| sm.id == cart.shipping_method_id} then
87
+ raise ::FlexCommerce::PaypalExpress::Exception::AccessDenied.new(I18n.t("payment_setup.shipping_method_not_available"))
88
+ end
89
+ end
90
+ end
91
+
92
+ class PaypalSetup < OpenStruct; end
93
+ end
94
+ end
@@ -0,0 +1,46 @@
1
+ # @module FlexCommerce::PaypalExpress
2
+ module FlexCommerce
3
+ module PaypalExpress
4
+ # @class ShippingMethodsForCart
5
+ #
6
+ # This deals with free shipping promotions and updates the shipping methods accordingly
7
+ class ShippingMethodsForCart
8
+
9
+ include Enumerable
10
+
11
+ def initialize(cart:, shipping_methods:)
12
+ self.cart = cart
13
+ self.shipping_methods = shipping_methods
14
+ self.shipping_promotions = cart.available_shipping_promotions
15
+ end
16
+
17
+ def call
18
+ free_shipping_method_ids = [ ]
19
+ shipping_promotions.reverse.each do |promotion|
20
+ # See if promotion is having a shipping method,
21
+ # and also see if that cart total is eligible for promotion
22
+ if promotion.shipping_methods && can_apply_promotion_to_cart?(promotion: promotion)
23
+ free_shipping_method_ids << promotion.shipping_methods.map(&:id)
24
+ end
25
+ end
26
+
27
+ free_shipping_method_ids.flatten!
28
+ updated_shipping_methods = []
29
+ shipping_methods.each do |shipping_method|
30
+ shipping_method_free = free_shipping_method_ids.include?(shipping_method.id)
31
+ updated_shipping_methods << CartShippingMethod.new(shipping_method, shipping_method_free)
32
+ end
33
+ updated_shipping_methods
34
+ end
35
+
36
+ private
37
+
38
+ attr_accessor :cart, :shipping_methods, :shipping_promotions
39
+
40
+ def can_apply_promotion_to_cart?(promotion:)
41
+ (cart.sub_total - cart.total_discount) >= promotion.minimum_cart_total&.to_i
42
+ end
43
+
44
+ end
45
+ end
46
+ end
@@ -0,0 +1,20 @@
1
+ # frozen_string_literal: true
2
+ module Retry
3
+
4
+ DEFAULT_MAX_NO_OF_RETRIES = 2
5
+ DEFAULT_RESCUE_ERRORS = StandardError
6
+
7
+ def self.call(no_of_retries: DEFAULT_MAX_NO_OF_RETRIES, rescue_errors: DEFAULT_RESCUE_ERRORS, &blk)
8
+ total_attempts = 0
9
+ begin
10
+ blk.call
11
+ rescue rescue_errors => ex
12
+ total_attempts += 1
13
+ retry if total_attempts < no_of_retries
14
+ ensure
15
+ if total_attempts == no_of_retries
16
+ return
17
+ end
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,370 @@
1
+ {
2
+ "$schema": "http://json-schema.org/draft-04/schema#",
3
+ "title": "JSON API Schema",
4
+ "description": "This is a schema for responses in the JSON API format. For more, see http://jsonapi.org",
5
+ "oneOf": [
6
+ {
7
+ "$ref": "#/definitions/success"
8
+ },
9
+ {
10
+ "$ref": "#/definitions/failure"
11
+ },
12
+ {
13
+ "$ref": "#/definitions/info"
14
+ }
15
+ ],
16
+
17
+ "definitions": {
18
+ "success": {
19
+ "type": "object",
20
+ "required": [
21
+ "data"
22
+ ],
23
+ "properties": {
24
+ "data": {
25
+ "$ref": "#/definitions/data"
26
+ },
27
+ "included": {
28
+ "description": "To reduce the number of HTTP requests, servers **MAY** allow responses that include related resources along with the requested primary resources. Such responses are called \"compound documents\".",
29
+ "type": "array",
30
+ "items": {
31
+ "$ref": "#/definitions/resource"
32
+ },
33
+ "uniqueItems": true
34
+ },
35
+ "meta": {
36
+ "$ref": "#/definitions/meta"
37
+ },
38
+ "links": {
39
+ "description": "Link members related to the primary data.",
40
+ "allOf": [
41
+ {
42
+ "$ref": "#/definitions/links"
43
+ },
44
+ {
45
+ "$ref": "#/definitions/pagination"
46
+ }
47
+ ]
48
+ },
49
+ "jsonapi": {
50
+ "$ref": "#/definitions/jsonapi"
51
+ }
52
+ },
53
+ "additionalProperties": false
54
+ },
55
+ "failure": {
56
+ "type": "object",
57
+ "required": [
58
+ "errors"
59
+ ],
60
+ "properties": {
61
+ "errors": {
62
+ "type": "array",
63
+ "items": {
64
+ "$ref": "#/definitions/error"
65
+ },
66
+ "uniqueItems": true
67
+ },
68
+ "meta": {
69
+ "$ref": "#/definitions/meta"
70
+ },
71
+ "jsonapi": {
72
+ "$ref": "#/definitions/jsonapi"
73
+ }
74
+ },
75
+ "additionalProperties": false
76
+ },
77
+ "info": {
78
+ "type": "object",
79
+ "required": [
80
+ "meta"
81
+ ],
82
+ "properties": {
83
+ "meta": {
84
+ "$ref": "#/definitions/meta"
85
+ },
86
+ "links": {
87
+ "$ref": "#/definitions/links"
88
+ },
89
+ "jsonapi": {
90
+ "$ref": "#/definitions/jsonapi"
91
+ }
92
+ },
93
+ "additionalProperties": false
94
+ },
95
+
96
+ "meta": {
97
+ "description": "Non-standard meta-information that can not be represented as an attribute or relationship.",
98
+ "type": "object",
99
+ "additionalProperties": true
100
+ },
101
+ "data": {
102
+ "description": "The document's \"primary data\" is a representation of the resource or collection of resources targeted by a request.",
103
+ "oneOf": [
104
+ {
105
+ "$ref": "#/definitions/resource"
106
+ },
107
+ {
108
+ "description": "An array of resource objects, an array of resource identifier objects, or an empty array ([]), for requests that target resource collections.",
109
+ "type": "array",
110
+ "items": {
111
+ "$ref": "#/definitions/resource"
112
+ },
113
+ "uniqueItems": true
114
+ },
115
+ {
116
+ "description": "null if the request is one that might correspond to a single resource, but doesn't currently.",
117
+ "type": "null"
118
+ }
119
+ ]
120
+ },
121
+ "resource": {
122
+ "description": "\"Resource objects\" appear in a JSON API document to represent resources.",
123
+ "type": "object",
124
+ "required": [
125
+ "type",
126
+ "id"
127
+ ],
128
+ "properties": {
129
+ "type": {
130
+ "type": "string"
131
+ },
132
+ "id": {
133
+ "type": "string"
134
+ },
135
+ "attributes": {
136
+ "$ref": "#/definitions/attributes"
137
+ },
138
+ "relationships": {
139
+ "$ref": "#/definitions/relationships"
140
+ },
141
+ "links": {
142
+ "$ref": "#/definitions/links"
143
+ },
144
+ "meta": {
145
+ "$ref": "#/definitions/meta"
146
+ }
147
+ },
148
+ "additionalProperties": false
149
+ },
150
+
151
+ "links": {
152
+ "description": "A resource object **MAY** contain references to other resource objects (\"relationships\"). Relationships may be to-one or to-many. Relationships can be specified by including a member in a resource's links object.",
153
+ "type": "object",
154
+ "properties": {
155
+ "self": {
156
+ "description": "A `self` member, whose value is a URL for the relationship itself (a \"relationship URL\"). This URL allows the client to directly manipulate the relationship. For example, it would allow a client to remove an `author` from an `article` without deleting the people resource itself.",
157
+ "type": "string",
158
+ "format": "uri"
159
+ },
160
+ "related": {
161
+ "$ref": "#/definitions/link"
162
+ }
163
+ },
164
+ "additionalProperties": true
165
+ },
166
+ "link": {
167
+ "description": "A link **MUST** be represented as either: a string containing the link's URL or a link object.",
168
+ "oneOf": [
169
+ {
170
+ "description": "A string containing the link's URL.",
171
+ "type": "string",
172
+ "format": "uri"
173
+ },
174
+ {
175
+ "type": "object",
176
+ "required": [
177
+ "href"
178
+ ],
179
+ "properties": {
180
+ "href": {
181
+ "description": "A string containing the link's URL.",
182
+ "type": "string",
183
+ "format": "uri"
184
+ },
185
+ "meta": {
186
+ "$ref": "#/definitions/meta"
187
+ }
188
+ }
189
+ }
190
+ ]
191
+ },
192
+
193
+ "attributes": {
194
+ "description": "Members of the attributes object (\"attributes\") represent information about the resource object in which it's defined.",
195
+ "type": "object",
196
+ "patternProperties": {
197
+ "^(?!relationships$|links$)\\w[-\\w_]*$": {
198
+ "description": "Attributes may contain any valid JSON value."
199
+ }
200
+ },
201
+ "additionalProperties": false
202
+ },
203
+
204
+ "relationships": {
205
+ "description": "Members of the relationships object (\"relationships\") represent references from the resource object in which it's defined to other resource objects.",
206
+ "type": "object",
207
+ "patternProperties": {
208
+ "^\\w[-\\w_]*$": {
209
+ "properties": {
210
+ "links": {
211
+ "$ref": "#/definitions/links"
212
+ },
213
+ "data": {
214
+ "description": "Member, whose value represents \"resource linkage\".",
215
+ "oneOf": [
216
+ {
217
+ "$ref": "#/definitions/relationshipToOne"
218
+ },
219
+ {
220
+ "$ref": "#/definitions/relationshipToMany"
221
+ }
222
+ ]
223
+ },
224
+ "meta": {
225
+ "$ref": "#/definitions/meta"
226
+ }
227
+ },
228
+ "additionalProperties": false
229
+ }
230
+ },
231
+ "additionalProperties": false
232
+ },
233
+ "relationshipToOne": {
234
+ "description": "References to other resource objects in a to-one (\"relationship\"). Relationships can be specified by including a member in a resource's links object.",
235
+ "anyOf": [
236
+ {
237
+ "$ref": "#/definitions/empty"
238
+ },
239
+ {
240
+ "$ref": "#/definitions/linkage"
241
+ }
242
+ ]
243
+ },
244
+ "relationshipToMany": {
245
+ "description": "An array of objects each containing \"type\" and \"id\" members for to-many relationships.",
246
+ "type": "array",
247
+ "items": {
248
+ "$ref": "#/definitions/linkage"
249
+ },
250
+ "uniqueItems": true
251
+ },
252
+ "empty": {
253
+ "description": "Describes an empty to-one relationship.",
254
+ "type": "null"
255
+ },
256
+ "linkage": {
257
+ "description": "The \"type\" and \"id\" to non-empty members.",
258
+ "type": "object",
259
+ "required": [
260
+ "type",
261
+ "id"
262
+ ],
263
+ "properties": {
264
+ "type": {
265
+ "type": "string"
266
+ },
267
+ "id": {
268
+ "type": "string"
269
+ },
270
+ "meta": {
271
+ "$ref": "#/definitions/meta"
272
+ }
273
+ },
274
+ "additionalProperties": false
275
+ },
276
+ "pagination": {
277
+ "type": "object",
278
+ "properties": {
279
+ "first": {
280
+ "description": "The first page of data",
281
+ "oneOf": [
282
+ { "type": "string", "format": "uri" },
283
+ { "type": "null" }
284
+ ]
285
+ },
286
+ "last": {
287
+ "description": "The last page of data",
288
+ "oneOf": [
289
+ { "type": "string", "format": "uri" },
290
+ { "type": "null" }
291
+ ]
292
+ },
293
+ "prev": {
294
+ "description": "The previous page of data",
295
+ "oneOf": [
296
+ { "type": "string", "format": "uri" },
297
+ { "type": "null" }
298
+ ]
299
+ },
300
+ "next": {
301
+ "description": "The next page of data",
302
+ "oneOf": [
303
+ { "type": "string", "format": "uri" },
304
+ { "type": "null" }
305
+ ]
306
+ }
307
+ }
308
+ },
309
+
310
+ "jsonapi": {
311
+ "description": "An object describing the server's implementation",
312
+ "type": "object",
313
+ "properties": {
314
+ "version": {
315
+ "type": "string"
316
+ },
317
+ "meta": {
318
+ "$ref": "#/definitions/meta"
319
+ }
320
+ },
321
+ "additionalProperties": false
322
+ },
323
+
324
+ "error": {
325
+ "type": "object",
326
+ "properties": {
327
+ "id": {
328
+ "description": "A unique identifier for this particular occurrence of the problem.",
329
+ "type": "string"
330
+ },
331
+ "links": {
332
+ "$ref": "#/definitions/links"
333
+ },
334
+ "status": {
335
+ "description": "The HTTP status code applicable to this problem, expressed as a string value.",
336
+ "type": "string"
337
+ },
338
+ "code": {
339
+ "description": "An application-specific error code, expressed as a string value.",
340
+ "type": "string"
341
+ },
342
+ "title": {
343
+ "description": "A short, human-readable summary of the problem. It **SHOULD NOT** change from occurrence to occurrence of the problem, except for purposes of localization.",
344
+ "type": "string"
345
+ },
346
+ "detail": {
347
+ "description": "A human-readable explanation specific to this occurrence of the problem.",
348
+ "type": "string"
349
+ },
350
+ "source": {
351
+ "type": "object",
352
+ "properties": {
353
+ "pointer": {
354
+ "description": "A JSON Pointer [RFC6901] to the associated entity in the request document [e.g. \"/data\" for a primary data object, or \"/data/attributes/title\" for a specific attribute].",
355
+ "type": "string"
356
+ },
357
+ "parameter": {
358
+ "description": "A string indicating which query parameter caused the error.",
359
+ "type": "string"
360
+ }
361
+ }
362
+ },
363
+ "meta": {
364
+ "$ref": "#/definitions/meta"
365
+ }
366
+ },
367
+ "additionalProperties": false
368
+ }
369
+ }
370
+ }