spree_api 5.6.0.rc6 → 5.6.1

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 (25) hide show
  1. checksums.yaml +4 -4
  2. data/app/controllers/spree/api/v3/admin/admin_users_controller.rb +1 -1
  3. data/app/controllers/spree/api/v3/admin/channels_controller.rb +2 -1
  4. data/app/controllers/spree/api/v3/admin/custom_field_definitions_controller.rb +2 -1
  5. data/app/controllers/spree/api/v3/admin/exports_controller.rb +10 -8
  6. data/app/controllers/spree/api/v3/admin/imports_controller.rb +37 -9
  7. data/app/controllers/spree/api/v3/store/customer/credit_cards_controller.rb +7 -0
  8. data/app/controllers/spree/api/v3/store/products/filters_controller.rb +2 -1
  9. data/app/serializers/spree/api/v3/admin/admin_user_serializer.rb +14 -1
  10. data/app/serializers/spree/api/v3/admin/custom_field_definition_serializer.rb +5 -1
  11. data/app/serializers/spree/api/v3/admin/media_serializer.rb +6 -1
  12. data/app/serializers/spree/api/v3/asset_serializer.rb +10 -2
  13. data/app/serializers/spree/api/v3/export_serializer.rb +9 -1
  14. data/app/serializers/spree/api/v3/import_row_serializer.rb +6 -1
  15. data/app/serializers/spree/api/v3/import_serializer.rb +11 -2
  16. data/app/serializers/spree/api/v3/invitation_serializer.rb +14 -1
  17. data/app/serializers/spree/api/v3/product_filter_sort_option_serializer.rb +2 -2
  18. data/app/serializers/spree/api/v3/report_serializer.rb +7 -1
  19. data/app/serializers/spree/api/v3/stock_movement_serializer.rb +6 -1
  20. data/app/serializers/spree/api/v3/stock_transfer_serializer.rb +5 -2
  21. data/app/serializers/spree/api/v3/wishlist_item_serializer.rb +8 -1
  22. data/app/services/spree/api/v3/filters_aggregator.rb +1 -1
  23. data/config/routes.rb +1 -0
  24. data/lib/spree/api/openapi/schema_helper.rb +18 -0
  25. metadata +6 -6
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 9f86ce456fb13e7e6f1fac5a39a1ad7f0a4befe5dc959a88c80b3bcaa3689b57
4
- data.tar.gz: 4df7f39849201749a3b5a26337a009a36ab0b9fc4b4588d5d90accf859368ec7
3
+ metadata.gz: 4feafcfd958681a7548cc9a2e043d7748e98d40fb34426c2aac5cbdc17599472
4
+ data.tar.gz: fce6786a2b4f6a41c32a26c34510172032ad9d57095058729261ea90cfc28f1f
5
5
  SHA512:
6
- metadata.gz: 7fa240df22e6815d24910c37e32b873a8dae7a4e0ded6c00430e7d895e287ae3ae6e78cb11fcbb52d4930f876e48e22bf8be7353eb317722789772a17ceb6aa9
7
- data.tar.gz: b4623924dc7d63bb2abae38790fa31c5140392e6838cce8c1c530fd6314110856fcf55c8c5c8a2c01a81fff58a1a7106787a3f3615d1b0f0dd16af4b911c027c
6
+ metadata.gz: 975ceabf8977c54e813177f08cf270e8688dc64e6e446d176e46310696ffc8672dcfb940c19eb0f4c7eace5b765e5883932eca08d973c432e4389539b27709af
7
+ data.tar.gz: 9c0ad20112afb852ff2cedd8421f6853a5ce098b0feb435d6346ca015d1190ac891ac38138f98e526bfc973e6f16afb27aadc0917065c236d33ea4023fe34f30
@@ -60,7 +60,7 @@ module Spree
60
60
  end
61
61
 
62
62
  def collection_includes
63
- [{ role_users: :role, avatar_attachment: :blob }]
63
+ [{ role_users: :role, avatar_attachment: :blob }, :stores]
64
64
  end
65
65
 
66
66
  # Restrict to users with a role assignment on the current store.
@@ -44,7 +44,8 @@ module Spree
44
44
  end
45
45
 
46
46
  def permitted_params
47
- params.permit(:name, :code, :active, :default, :preferred_order_routing_strategy)
47
+ params.permit(:name, :code, :active, :default, :preferred_order_routing_strategy,
48
+ :preferred_storefront_access, :preferred_guest_checkout)
48
49
  end
49
50
 
50
51
  private
@@ -25,7 +25,8 @@ module Spree
25
25
  # API → DB column rename lands in 6.0 and this controller stays flat.
26
26
  def permitted_params
27
27
  params.permit(:namespace, :key, :label, :field_type,
28
- :resource_type, :storefront_visible)
28
+ :resource_type, :storefront_visible,
29
+ :searchable, :sortable)
29
30
  end
30
31
  end
31
32
  end
@@ -106,17 +106,19 @@ module Spree
106
106
 
107
107
  # Returns the registered Export subclass matching `name`, or nil.
108
108
  #
109
- # The constantize target comes from `available_types` (a trusted
110
- # in-process registry), not from the request — `name` is only used
111
- # to *select* an entry in the allowlist. This keeps the data flow
112
- # from user input → trusted-string → `constantize` legible to
113
- # static analyzers (CodeQL otherwise flags the inverse pattern of
114
- # gating user input with `include?` before calling `constantize`).
109
+ # Takes the API shorthand (`"products"`), the same value the
110
+ # serializer emits. The fully-qualified class name is also accepted so
111
+ # a `type` read back from the API round-trips either way.
112
+ #
113
+ # The class comes from `available_types` (a trusted in-process
114
+ # registry), not from the request — `name` is only used to *select* an
115
+ # entry in the allowlist, which also keeps the data flow legible to
116
+ # static analyzers (no `constantize` on user input at all).
115
117
  def resolve_export_type(name)
116
118
  return nil if name.blank?
117
119
 
118
- target = Spree::Export.available_types.map(&:to_s).find { |t| t == name.to_s }
119
- target&.constantize
120
+ name = name.to_s
121
+ Spree::Export.available_types.find { |type| type.api_type == name || type.to_s == name }
120
122
  end
121
123
 
122
124
  private
@@ -150,13 +150,37 @@ module Spree
150
150
  )
151
151
  end
152
152
 
153
- headers = klass.new.schema_fields.map { |field| field[:name] }
154
- send_data ::CSV.generate_line(headers),
155
- filename: "#{klass.name.demodulize.underscore}_import_template.csv",
153
+ import = klass.new
154
+ send_data import.template_csv,
155
+ filename: import.template_csv_filename,
156
156
  type: 'text/csv',
157
157
  disposition: 'attachment'
158
158
  end
159
159
 
160
+ # GET /api/v3/admin/imports/example?type=products
161
+ #
162
+ # Redirects to the populated example CSV for the type — the counterpart
163
+ # to `template` above. 404s for a type that ships no example file.
164
+ #
165
+ # The client can't build this URL itself: it is pinned to the
166
+ # installed Spree version, and exposing that version over the API
167
+ # would fingerprint the deployment for anyone matching CVEs. Resolving
168
+ # it here keeps the version server-side.
169
+ def example
170
+ klass = resolve_import_type(params[:type])
171
+ url = klass&.sample_csv_url
172
+
173
+ unless url
174
+ return render_error(
175
+ code: Spree::Api::V3::ErrorHandler::ERROR_CODES[:record_not_found],
176
+ message: 'No example CSV for this import type',
177
+ status: :not_found
178
+ )
179
+ end
180
+
181
+ redirect_to url, allow_other_host: true, status: :found
182
+ end
183
+
160
184
  protected
161
185
 
162
186
  def model_class
@@ -215,15 +239,19 @@ module Spree
215
239
 
216
240
  # Returns the registered Import subclass matching `name`, or nil.
217
241
  #
218
- # The constantize target comes from `available_types` (a trusted
219
- # in-process registry), not from the request — `name` is only used
220
- # to *select* an entry in the allowlist (same pattern as
242
+ # Takes the API shorthand (`"products"`), the same value the
243
+ # serializer emits. The fully-qualified class name is also accepted so
244
+ # a `type` read back from the API round-trips either way.
245
+ #
246
+ # The class comes from `available_types` (a trusted in-process
247
+ # registry), not from the request — `name` is only used to *select* an
248
+ # entry in the allowlist (same pattern as
221
249
  # ExportsController#resolve_export_type).
222
250
  def resolve_import_type(name)
223
251
  return nil if name.blank?
224
252
 
225
- target = Spree::Import.available_types.map(&:to_s).find { |t| t == name.to_s }
226
- target&.constantize
253
+ name = name.to_s
254
+ Spree::Import.available_types.find { |type| type.api_type == name || type.to_s == name }
227
255
  end
228
256
 
229
257
  private
@@ -241,7 +269,7 @@ module Spree
241
269
 
242
270
  def import_class
243
271
  case action_name
244
- when 'create', 'template' then resolve_import_type(params[:type])
272
+ when 'create', 'template', 'example' then resolve_import_type(params[:type])
245
273
  else find_resource.class
246
274
  end
247
275
  end
@@ -16,6 +16,13 @@ module Spree
16
16
  :credit_cards
17
17
  end
18
18
 
19
+ # Customers are global; a saved card belongs to the store-scoped
20
+ # payment method it was created against, so the nested collection is
21
+ # bound to the current store's payment methods.
22
+ def scope
23
+ @parent.credit_cards.where(payment_method_id: current_store.payment_methods.select(:id))
24
+ end
25
+
19
26
  def model_class
20
27
  Spree::CreditCard
21
28
  end
@@ -44,7 +44,8 @@ module Spree
44
44
  search_query,
45
45
  search_filters&.sort_by(&:first)&.to_json,
46
46
  max_updated,
47
- product_count
47
+ product_count,
48
+ search_provider.metafield_schema.schema_version
48
49
  ]
49
50
 
50
51
  parts.compact.join('/')
@@ -9,7 +9,8 @@ module Spree
9
9
  full_name: [:string, nullable: true],
10
10
  selected_locale: [:string, nullable: true],
11
11
  avatar_url: [:string, nullable: true],
12
- roles: 'Array<{ id: string; name: string }>'
12
+ roles: 'Array<{ id: string; name: string }>',
13
+ stores: 'Array<{ id: string; name: string; code: string }>'
13
14
 
14
15
  attributes :email, :first_name, :last_name, :full_name, :selected_locale,
15
16
  created_at: :iso8601, updated_at: :iso8601
@@ -30,6 +31,18 @@ module Spree
30
31
  scope = scope.where(resource: store) if store
31
32
  scope.includes(:role).map { |ru| { id: ru.role.prefixed_id, name: ru.role.name } }
32
33
  end
34
+
35
+ # Every store this user holds a role on (via `Spree::RoleUser`) —
36
+ # unlike `roles`, deliberately NOT scoped to the current store, so
37
+ # the dashboard store switcher can offer all accessible stores.
38
+ # Dedupe/sort happen in Ruby (not `.distinct.order`) so the staff
39
+ # index's `collection_includes` preload is used instead of firing
40
+ # an extra query per user.
41
+ attribute :stores do |user|
42
+ user.stores.uniq.sort_by(&:name).map do |store|
43
+ { id: store.prefixed_id, name: store.name, code: store.code }
44
+ end
45
+ end
33
46
  end
34
47
  end
35
48
  end
@@ -10,9 +10,13 @@ module Spree
10
10
  label: :string,
11
11
  field_type: Spree::Metafield::FIELD_TYPE_TOKENS,
12
12
  resource_type: :string,
13
- storefront_visible: :boolean
13
+ storefront_visible: :boolean,
14
+ searchable: :boolean,
15
+ sortable: :boolean,
16
+ filter_key: :string
14
17
 
15
18
  attributes :namespace, :key, :label, :field_type, :resource_type, :storefront_visible,
19
+ :searchable, :sortable, :filter_key,
16
20
  created_at: :iso8601, updated_at: :iso8601
17
21
  end
18
22
  end
@@ -33,7 +33,12 @@ module Spree
33
33
  end
34
34
  end
35
35
 
36
- attributes :metadata, :viewable_type
36
+ attributes :metadata
37
+
38
+ # `"product"` / `"variant"`, not the polymorphic class name.
39
+ attribute :viewable_type do |asset|
40
+ Spree::Base.polymorphic_api_type(asset.viewable_type)
41
+ end
37
42
  end
38
43
  end
39
44
  end
@@ -4,7 +4,10 @@ module Spree
4
4
  module Api
5
5
  module V3
6
6
  class AssetSerializer < BaseSerializer
7
- typelize type: [:string, nullable: true], viewable_type: :string,
7
+ # `type` is not exposed: Spree::Image/Spree::Video were collapsed into
8
+ # Spree::Asset, so the STI column is a legacy vestige with no subclasses
9
+ # — `media_type` is the discriminator (see MediaSerializer).
10
+ typelize media_type: :string, viewable_type: :string,
8
11
  viewable_id: :string, position: [:number, nullable: true],
9
12
  alt: [:string, nullable: true]
10
13
 
@@ -12,7 +15,12 @@ module Spree
12
15
  asset.viewable&.prefixed_id
13
16
  end
14
17
 
15
- attributes :type, :viewable_type, :position, :alt,
18
+ # `"product"` / `"variant"`, not the polymorphic class name.
19
+ attribute :viewable_type do |asset|
20
+ Spree::Base.polymorphic_api_type(asset.viewable_type)
21
+ end
22
+
23
+ attributes :media_type, :position, :alt,
16
24
  created_at: :iso8601, updated_at: :iso8601
17
25
  end
18
26
  end
@@ -7,9 +7,17 @@ module Spree
7
7
  typelize number: :string, type: [:string, nullable: true], format: [:string, nullable: true],
8
8
  user_id: [:string, nullable: true]
9
9
 
10
- attributes :number, :type, :format,
10
+ attributes :number, :format,
11
11
  created_at: :iso8601, updated_at: :iso8601
12
12
 
13
+ # Wire shorthand (`"products"`), not the Ruby class name — clients
14
+ # shouldn't have to know or parse `Spree::Exports::Products`. Read from
15
+ # the STI column rather than the instance's class so a record loaded as
16
+ # the base Spree::Export still reports its real type.
17
+ attribute :type do |export|
18
+ Spree::Export.api_type_for(export.type)
19
+ end
20
+
13
21
  attribute :user_id do |export|
14
22
  export.user&.prefixed_id
15
23
  end
@@ -8,13 +8,18 @@ module Spree
8
8
  status: :string, validation_errors: [:string, nullable: true],
9
9
  item_type: [:string, nullable: true], item_id: [:string, nullable: true]
10
10
 
11
- attributes :row_number, :status, :validation_errors, :item_type,
11
+ attributes :row_number, :status, :validation_errors,
12
12
  created_at: :iso8601, updated_at: :iso8601
13
13
 
14
14
  attribute :import_id do |row|
15
15
  row.import&.prefixed_id
16
16
  end
17
17
 
18
+ # `"product"` / `"variant"`, not the polymorphic class name.
19
+ attribute :item_type do |row|
20
+ Spree::Base.polymorphic_api_type(row.item_type)
21
+ end
22
+
18
23
  attribute :item_id do |row|
19
24
  row.item&.prefixed_id
20
25
  end
@@ -8,15 +8,24 @@ module Spree
8
8
  owner_type: [:string, nullable: true], owner_id: [:string, nullable: true],
9
9
  user_id: [:string, nullable: true], rows_count: :number
10
10
 
11
- attributes :number, :type, :rows_count,
11
+ attributes :number, :rows_count,
12
12
  created_at: :iso8601, updated_at: :iso8601
13
13
 
14
+ # Wire shorthand (`"products"`), not the Ruby class name — clients
15
+ # shouldn't have to know or parse `Spree::Imports::Products`. Read from
16
+ # the STI column rather than the instance's class so a record loaded as
17
+ # the base Spree::Import still reports its real type.
18
+ attribute :type do |import|
19
+ Spree::Import.api_type_for(import.type)
20
+ end
21
+
14
22
  attribute :status do |import|
15
23
  import.status.to_s
16
24
  end
17
25
 
26
+ # `"store"` / `"vendor"`, not the polymorphic class name.
18
27
  attribute :owner_type do |import|
19
- import.owner_type
28
+ Spree::Base.polymorphic_api_type(import.owner_type)
20
29
  end
21
30
 
22
31
  attribute :owner_id do |import|
@@ -11,13 +11,26 @@ module Spree
11
11
  role_id: [:string, nullable: true],
12
12
  expires_at: [:string, nullable: true], accepted_at: [:string, nullable: true]
13
13
 
14
- attributes :email, :resource_type, :inviter_type, :invitee_type,
14
+ attributes :email,
15
15
  created_at: :iso8601, updated_at: :iso8601
16
16
 
17
17
  attribute :status do |invitation|
18
18
  invitation.status.to_s
19
19
  end
20
20
 
21
+ # `"store"` / `"admin_user"`, not the polymorphic class names.
22
+ attribute :resource_type do |invitation|
23
+ Spree::Base.polymorphic_api_type(invitation.resource_type)
24
+ end
25
+
26
+ attribute :inviter_type do |invitation|
27
+ Spree::Base.polymorphic_api_type(invitation.inviter_type)
28
+ end
29
+
30
+ attribute :invitee_type do |invitation|
31
+ Spree::Base.polymorphic_api_type(invitation.invitee_type)
32
+ end
33
+
21
34
  attribute :resource_id do |invitation|
22
35
  invitation.resource&.prefixed_id
23
36
  end
@@ -2,9 +2,9 @@ module Spree
2
2
  module Api
3
3
  module V3
4
4
  class ProductFilterSortOptionSerializer < BaseSerializer
5
- typelize id: :string
5
+ typelize id: :string, label: 'string | null'
6
6
 
7
- attributes :id
7
+ attributes :id, :label
8
8
  end
9
9
  end
10
10
  end
@@ -9,7 +9,13 @@ module Spree
9
9
  currency: [:string, nullable: true],
10
10
  date_from: [:string, nullable: true], date_to: [:string, nullable: true]
11
11
 
12
- attributes :type, :currency
12
+ attributes :currency
13
+
14
+ # Wire shorthand (`"sales_total"`), not the Ruby class name — clients
15
+ # shouldn't have to know or parse `Spree::Reports::SalesTotal`.
16
+ attribute :type do |report|
17
+ Spree::Report.api_type_for(report.type)
18
+ end
13
19
 
14
20
  attribute :user_id do |report|
15
21
  report.user&.prefixed_id
@@ -8,9 +8,14 @@ module Spree
8
8
  originator_type: [:string, nullable: true], originator_id: [:string, nullable: true],
9
9
  stock_item_id: [:string, nullable: true]
10
10
 
11
- attributes :quantity, :action, :originator_type,
11
+ attributes :quantity, :action,
12
12
  created_at: :iso8601, updated_at: :iso8601
13
13
 
14
+ # `"shipment"` / `"stock_transfer"`, not the polymorphic class name.
15
+ attribute :originator_type do |movement|
16
+ Spree::Base.polymorphic_api_type(movement.originator_type)
17
+ end
18
+
14
19
  attribute :originator_id do |movement|
15
20
  movement.originator&.prefixed_id
16
21
  end
@@ -4,12 +4,15 @@ module Spree
4
4
  module Api
5
5
  module V3
6
6
  class StockTransferSerializer < BaseSerializer
7
- typelize number: [:string, nullable: true], type: [:string, nullable: true],
7
+ # `type` is not exposed: Spree::StockTransfer has no STI subclasses, so
8
+ # the column is a legacy vestige that is always nil. The admin
9
+ # serializer already omits it.
10
+ typelize number: [:string, nullable: true],
8
11
  reference: [:string, nullable: true],
9
12
  source_location_id: [:string, nullable: true],
10
13
  destination_location_id: [:string, nullable: true]
11
14
 
12
- attributes :number, :type, :reference,
15
+ attributes :number, :reference,
13
16
  created_at: :iso8601, updated_at: :iso8601
14
17
 
15
18
  attribute :source_location_id do |transfer|
@@ -2,12 +2,17 @@ module Spree
2
2
  module Api
3
3
  module V3
4
4
  class WishlistItemSerializer < BaseSerializer
5
- typelize variant_id: :string, wishlist_id: :string, quantity: :number
5
+ typelize variant_id: :string, wishlist_id: :string, quantity: :number,
6
+ product_id: :string
6
7
 
7
8
  attribute :variant_id do |wished_item|
8
9
  wished_item.variant&.prefixed_id
9
10
  end
10
11
 
12
+ attribute :product_id do |wished_item|
13
+ wished_item.product&.prefixed_id
14
+ end
15
+
11
16
  attribute :wishlist_id do |wished_item|
12
17
  wished_item.wishlist&.prefixed_id
13
18
  end
@@ -15,6 +20,8 @@ module Spree
15
20
  attributes :quantity
16
21
 
17
22
  one :variant, resource: proc { Spree.api.variant_serializer }
23
+ one :product, resource: proc { Spree.api.product_serializer },
24
+ if: proc { expand?('product') }
18
25
  end
19
26
  end
20
27
  end
@@ -36,7 +36,7 @@ module Spree
36
36
  end
37
37
 
38
38
  def sort_options
39
- Spree::Taxon::SORT_ORDERS.map { |id| { id: to_api_sort(id) } }
39
+ Spree::Taxon::SORT_ORDERS.map { |id| { id: to_api_sort(id), label: nil } }
40
40
  end
41
41
 
42
42
  # Converts internal sort format ('price asc') to API format ('price', '-price')
data/config/routes.rb CHANGED
@@ -205,6 +205,7 @@ Spree::Core::Engine.add_routes do
205
205
  resources :imports, only: [:index, :show, :create, :destroy] do
206
206
  collection do
207
207
  get :template
208
+ get :example
208
209
  end
209
210
  member do
210
211
  patch :complete_mapping
@@ -155,6 +155,16 @@ module Spree
155
155
  },
156
156
  required: %w[id name]
157
157
  },
158
+ AdminUserStore: {
159
+ type: :object,
160
+ description: 'A store the staff member can access through a role assignment',
161
+ properties: {
162
+ id: { type: :string, description: 'Prefixed store ID', example: 'store_abc123' },
163
+ name: { type: :string, description: 'Store name', example: 'My Store' },
164
+ code: { type: :string, description: 'Store code', example: 'my-store' }
165
+ },
166
+ required: %w[id name code]
167
+ },
158
168
  PreferenceField: {
159
169
  type: :object,
160
170
  description: 'A single configurable preference on a payment method, promotion rule/action, or calculator. The frontend uses `type` + `default` to render a sensible input.',
@@ -305,6 +315,14 @@ module Spree
305
315
  items: { '$ref' => '#/components/schemas/AdminUserRoleAssignment' }
306
316
  }
307
317
  end
318
+
319
+ stores_key = props.key?('stores') ? 'stores' : :stores
320
+ if props[stores_key]
321
+ props[stores_key] = {
322
+ type: :array,
323
+ items: { '$ref' => '#/components/schemas/AdminUserStore' }
324
+ }
325
+ end
308
326
  end
309
327
 
310
328
  # Same Array<{...}> + Array<string> typelize hints that Typelizer
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: spree_api
3
3
  version: !ruby/object:Gem::Version
4
- version: 5.6.0.rc6
4
+ version: 5.6.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Vendo Connect Inc.
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2026-07-23 00:00:00.000000000 Z
11
+ date: 2026-07-28 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rswag-specs
@@ -72,14 +72,14 @@ dependencies:
72
72
  requirements:
73
73
  - - '='
74
74
  - !ruby/object:Gem::Version
75
- version: 5.6.0.rc6
75
+ version: 5.6.1
76
76
  type: :runtime
77
77
  prerelease: false
78
78
  version_requirements: !ruby/object:Gem::Requirement
79
79
  requirements:
80
80
  - - '='
81
81
  - !ruby/object:Gem::Version
82
- version: 5.6.0.rc6
82
+ version: 5.6.1
83
83
  description: Spree's API
84
84
  email:
85
85
  - hello@spreecommerce.org
@@ -384,9 +384,9 @@ licenses:
384
384
  - BSD-3-Clause
385
385
  metadata:
386
386
  bug_tracker_uri: https://github.com/spree/spree/issues
387
- changelog_uri: https://github.com/spree/spree/releases/tag/v5.6.0.rc6
387
+ changelog_uri: https://github.com/spree/spree/releases/tag/v5.6.1
388
388
  documentation_uri: https://docs.spreecommerce.org/
389
- source_code_uri: https://github.com/spree/spree/tree/v5.6.0.rc6
389
+ source_code_uri: https://github.com/spree/spree/tree/v5.6.1
390
390
  post_install_message:
391
391
  rdoc_options: []
392
392
  require_paths: