spree_api 6.0.0 → 6.0.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 (68) hide show
  1. checksums.yaml +4 -4
  2. data/app/controllers/spree/api/v3/admin/invitation_acceptances_controller.rb +8 -4
  3. data/app/controllers/spree/api/v3/admin/sellers_controller.rb +1 -1
  4. data/app/controllers/spree/api/v3/admin/store_controller.rb +23 -7
  5. data/app/controllers/spree/api/v3/seller/invitation_acceptances_controller.rb +15 -5
  6. data/app/controllers/spree/api/v3/store/customers_controller.rb +1 -0
  7. data/app/controllers/spree/api/v3/store/store_controller.rb +25 -0
  8. data/app/serializers/spree/api/v3/address_serializer.rb +2 -0
  9. data/app/serializers/spree/api/v3/admin/address_serializer.rb +2 -0
  10. data/app/serializers/spree/api/v3/admin/category_serializer.rb +1 -3
  11. data/app/serializers/spree/api/v3/admin/claim_serializer.rb +2 -0
  12. data/app/serializers/spree/api/v3/admin/collection_serializer.rb +1 -4
  13. data/app/serializers/spree/api/v3/admin/company_serializer.rb +2 -0
  14. data/app/serializers/spree/api/v3/admin/credit_card_serializer.rb +2 -0
  15. data/app/serializers/spree/api/v3/admin/customer_serializer.rb +2 -0
  16. data/app/serializers/spree/api/v3/admin/delivery_method_serializer.rb +2 -0
  17. data/app/serializers/spree/api/v3/admin/fulfillment_serializer.rb +1 -0
  18. data/app/serializers/spree/api/v3/admin/gift_card_serializer.rb +2 -0
  19. data/app/serializers/spree/api/v3/admin/invitation_serializer.rb +1 -1
  20. data/app/serializers/spree/api/v3/admin/line_item_serializer.rb +1 -0
  21. data/app/serializers/spree/api/v3/admin/media_serializer.rb +2 -0
  22. data/app/serializers/spree/api/v3/admin/newsletter_subscriber_serializer.rb +2 -0
  23. data/app/serializers/spree/api/v3/admin/option_type_serializer.rb +2 -0
  24. data/app/serializers/spree/api/v3/admin/option_value_serializer.rb +2 -0
  25. data/app/serializers/spree/api/v3/admin/order_serializer.rb +2 -0
  26. data/app/serializers/spree/api/v3/admin/payment_method_serializer.rb +2 -0
  27. data/app/serializers/spree/api/v3/admin/payment_serializer.rb +3 -1
  28. data/app/serializers/spree/api/v3/admin/payment_source_serializer.rb +2 -0
  29. data/app/serializers/spree/api/v3/admin/product_serializer.rb +1 -3
  30. data/app/serializers/spree/api/v3/admin/return_serializer.rb +2 -0
  31. data/app/serializers/spree/api/v3/admin/seller_payout_serializer.rb +2 -1
  32. data/app/serializers/spree/api/v3/admin/seller_serializer.rb +4 -0
  33. data/app/serializers/spree/api/v3/admin/store_credit_serializer.rb +2 -0
  34. data/app/serializers/spree/api/v3/admin/store_serializer.rb +3 -4
  35. data/app/serializers/spree/api/v3/admin/variant_serializer.rb +1 -3
  36. data/app/serializers/spree/api/v3/base_serializer.rb +28 -0
  37. data/app/serializers/spree/api/v3/category_serializer.rb +1 -4
  38. data/app/serializers/spree/api/v3/claim_serializer.rb +2 -0
  39. data/app/serializers/spree/api/v3/collection_serializer.rb +1 -4
  40. data/app/serializers/spree/api/v3/company_serializer.rb +2 -0
  41. data/app/serializers/spree/api/v3/credit_card_serializer.rb +2 -0
  42. data/app/serializers/spree/api/v3/customer_serializer.rb +2 -0
  43. data/app/serializers/spree/api/v3/delivery_method_serializer.rb +2 -0
  44. data/app/serializers/spree/api/v3/fulfillment_serializer.rb +2 -0
  45. data/app/serializers/spree/api/v3/gift_card_serializer.rb +1 -0
  46. data/app/serializers/spree/api/v3/line_item_serializer.rb +2 -0
  47. data/app/serializers/spree/api/v3/media_serializer.rb +2 -0
  48. data/app/serializers/spree/api/v3/newsletter_subscriber_serializer.rb +2 -0
  49. data/app/serializers/spree/api/v3/option_type_serializer.rb +2 -0
  50. data/app/serializers/spree/api/v3/option_value_serializer.rb +2 -0
  51. data/app/serializers/spree/api/v3/order_serializer.rb +2 -0
  52. data/app/serializers/spree/api/v3/payment_method_serializer.rb +2 -0
  53. data/app/serializers/spree/api/v3/payment_serializer.rb +3 -1
  54. data/app/serializers/spree/api/v3/payment_source_serializer.rb +2 -0
  55. data/app/serializers/spree/api/v3/product_serializer.rb +1 -4
  56. data/app/serializers/spree/api/v3/return_serializer.rb +2 -0
  57. data/app/serializers/spree/api/v3/seller/invitation_serializer.rb +22 -1
  58. data/app/serializers/spree/api/v3/seller/profile_serializer.rb +1 -1
  59. data/app/serializers/spree/api/v3/seller_serializer.rb +2 -0
  60. data/app/serializers/spree/api/v3/store_credit_serializer.rb +2 -0
  61. data/app/serializers/spree/api/v3/store_serializer.rb +16 -0
  62. data/app/serializers/spree/api/v3/variant_serializer.rb +1 -4
  63. data/app/services/spree/api/v3/request_schema.rb +15 -7
  64. data/config/routes.rb +5 -2
  65. data/lib/spree/api/dependencies.rb +1 -1
  66. data/lib/spree/api/enum_types.rb +2 -1
  67. data/lib/typelizer/open_enums.rb +21 -2
  68. metadata +8 -6
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 02e3a969bdbac77ab7eba1edb5986472deb10d660fbad8b2c51df6e586f97709
4
- data.tar.gz: c3f880037bc5751de97fbccdbcacae67d643c8ddf8aefa66a3ac804d488645a7
3
+ metadata.gz: 88513caab1df4ae8256a450d38b98601d724763697f75cd6bbe92f20986fac7c
4
+ data.tar.gz: 87742481e6e84a33e11080d3c830ca960eb692a243fb6d1b6c926a43f7d951e0
5
5
  SHA512:
6
- metadata.gz: cb6694163e15d45f56831fc65547a3a5728f022dd2d1e0610ea758b844ef05b1a5fd80340fad8cb4b75ef2f525582cd423212a052da3406e2e241822137c64ed
7
- data.tar.gz: 423fe47f6ce5d99bd55eea7613e2594bc3d4c382eee23dd47ff28e1b2b1f43f678c8034c96e12ef6dafd30fa537d946a3f13d0e9c899bdf0f005c93c62c89df5
6
+ metadata.gz: 10e0aa59755c08b5d83f12080be796d2a4a8cd3cbb70e77a47d369853385dc78f3583296534b0482dc76816396a285f6b476c12cc0c1863eac45defedc646f71
7
+ data.tar.gz: fd76b27f733d1acf21c0deb06341cf2cde81de862dc1d1eaaefcb91f2ffb216bafd3c2f24d4f7a09f1a6dbe39d31f66b9e37584561c26e64563099c67a3592bb
@@ -12,7 +12,7 @@ module Spree
12
12
 
13
13
  request_params 'InvitationAcceptParams', action: :accept do |body|
14
14
  body.attribute :password, :string,
15
- description: 'Required when the invitee has no account yet: it creates one. An existing account signs in without it.'
15
+ description: 'Creates the account when the invitee has none yet. An existing account confirms it is theirs with it, unless the request is already signed in as that account.'
16
16
  body.attribute :password_confirmation, :string
17
17
  body.attribute :first_name, :string
18
18
  body.attribute :last_name, :string
@@ -74,10 +74,14 @@ module Spree
74
74
  # implicit: we look the user up by `invitation.email`, never by a
75
75
  # client-supplied email. The token is the credential.
76
76
  def resolve_or_create_invitee(invitation)
77
- existing = Spree.admin_user_class.find_by(email: invitation.email)
78
- return authenticate_existing(existing) if existing
77
+ existing = invitation.invitee_account
78
+ return create_new_invitee(invitation) unless existing
79
79
 
80
- create_new_invitee(invitation)
80
+ # Someone already signed in as the invitee has proven who they are.
81
+ authenticate_user
82
+ return existing if current_user == existing
83
+
84
+ authenticate_existing(existing)
81
85
  end
82
86
 
83
87
  def authenticate_existing(user)
@@ -195,7 +195,7 @@ module Spree
195
195
  # every seller on the page, so it loads once. Applied to the scope
196
196
  # rather than the collection so a single-seller read gets it too.
197
197
  def scope_includes
198
- [:billing_address, :requirement_submissions, { stock_locations: [] },
198
+ [:billing_address, :requirement_submissions, :external_references, { stock_locations: [] },
199
199
  { store: :seller_requirements, logo_attachment: :blob, cover_photo_attachment: :blob }]
200
200
  end
201
201
 
@@ -7,8 +7,15 @@ module Spree
7
7
 
8
8
  request_params :store do |body|
9
9
  body.attribute :name, :string, example: 'My Store'
10
- body.attribute :admin_locale, :string, example: 'en'
11
- body.attribute :timezone, :string, example: 'Europe/Berlin'
10
+ body.attribute :seo_title, :string,
11
+ nullable: true,
12
+ description: "The storefront's default page title, in the store's default language. Translate it through the translations endpoints."
13
+ body.attribute :meta_description, :string,
14
+ nullable: true,
15
+ description: "The storefront's default meta description, in the store's default language."
16
+ body.attribute :admin_locale, :locale, nullable: true, example: 'en',
17
+ description: 'The language the dashboard opens in for every staff member; null lets each use their own.'
18
+ body.attribute :timezone, :time_zone, example: 'Europe/Berlin'
12
19
  body.attribute :weight_unit, :weight_unit
13
20
  body.attribute :unit_system, :string, choices: Spree::Store::UNIT_SYSTEMS
14
21
  body.attribute :storefront_access, :string,
@@ -143,17 +150,19 @@ module Spree
143
150
  # GET /api/v3/admin/store
144
151
  def show
145
152
  authorize! :show, current_store
146
- render json: serialize_store
153
+ render json: in_default_locale { serialize_store }
147
154
  end
148
155
 
149
156
  # PATCH /api/v3/admin/store
150
157
  def update
151
158
  authorize! :update, current_store
152
159
 
153
- if current_store.update(permitted_params)
154
- render json: serialize_store
155
- else
156
- render_validation_error(current_store.errors)
160
+ in_default_locale do
161
+ if current_store.update(permitted_params)
162
+ render json: serialize_store
163
+ else
164
+ render_validation_error(current_store.errors)
165
+ end
157
166
  end
158
167
  end
159
168
 
@@ -177,6 +186,13 @@ module Spree
177
186
 
178
187
  private
179
188
 
189
+ # Settings hold the store's default-language values, whatever locale
190
+ # the request resolved to. Other languages are written through the
191
+ # translations endpoints.
192
+ def in_default_locale(&)
193
+ Mobility.with_locale(current_store.default_locale, &)
194
+ end
195
+
180
196
  def describe(provider_classes)
181
197
  provider_classes.map do |provider_class|
182
198
  {
@@ -24,7 +24,7 @@ module Spree
24
24
 
25
25
  request_params 'InvitationAcceptParams', action: :accept do |body|
26
26
  body.attribute :password, :string,
27
- description: 'Sets the password of a new account, or confirms the password of an existing one.'
27
+ description: 'Sets the password of a new account, or confirms the password of an existing one, unless the request is already signed in as that account.'
28
28
  body.attribute :password_confirmation, :string
29
29
  body.attribute :first_name, :string, description: 'Used only when the invitation creates a new account.'
30
30
  body.attribute :last_name, :string, description: 'Used only when the invitation creates a new account.'
@@ -35,7 +35,7 @@ module Spree
35
35
  return unless load_invitation
36
36
 
37
37
  render json: Spree.api.seller_invitation_serializer.new(
38
- @invitation, params: { store: @invitation.store }
38
+ @invitation, params: { store: @invitation.store, acceptance: true }
39
39
  ).serializable_hash
40
40
  end
41
41
 
@@ -97,10 +97,14 @@ module Spree
97
97
  # implicit: we look the user up by `invitation.email`, never by a
98
98
  # client-supplied email. The token is the credential.
99
99
  def resolve_or_create_invitee(invitation)
100
- existing = Spree.admin_user_class.find_by(email: invitation.email)
101
- return authenticate_existing(existing) if existing
100
+ existing = invitation.invitee_account
101
+ return create_new_invitee(invitation) unless existing
102
102
 
103
- create_new_invitee(invitation)
103
+ # Someone already signed in as the invitee has proven who they are.
104
+ authenticate_user
105
+ return existing if current_user == existing
106
+
107
+ authenticate_existing(existing)
104
108
  end
105
109
 
106
110
  def authenticate_existing(user)
@@ -151,6 +155,12 @@ module Spree
151
155
  user.sellers.map { |seller| { id: seller.prefixed_id, name: seller.name, status: seller.status } }
152
156
  end
153
157
 
158
+ # The plain v3 base expects a storefront token; the session this
159
+ # page may carry is a seller panel one.
160
+ def expected_audience
161
+ Spree::Api::V3::JwtAuthentication::JWT_AUDIENCE_SELLER
162
+ end
163
+
154
164
  def request_env_for_token
155
165
  { ip_address: request.remote_ip, user_agent: request.user_agent&.truncate(255) }
156
166
  end
@@ -111,6 +111,7 @@ module Spree
111
111
  currency: current_currency,
112
112
  user: current_user,
113
113
  includes: [],
114
+ expand: expand_list,
114
115
  hide_prices: hide_prices?
115
116
  }
116
117
  end
@@ -0,0 +1,25 @@
1
+ module Spree
2
+ module Api
3
+ module V3
4
+ module Store
5
+ # Exposes the store the request resolved to, so a storefront can render
6
+ # its name and default SEO metadata in the requested locale.
7
+ class StoreController < Store::BaseController
8
+ # A gated storefront still needs a page title on its sign-in wall.
9
+ allow_guest_storefront_access!
10
+
11
+ # GET /api/v3/store/store
12
+ def show
13
+ render json: serialize_resource(current_store)
14
+ end
15
+
16
+ protected
17
+
18
+ def serializer_class
19
+ Spree.api.store_serializer
20
+ end
21
+ end
22
+ end
23
+ end
24
+ end
25
+ end
@@ -35,6 +35,8 @@ module Spree
35
35
  # The address book the entry belongs to. Null for an address in no
36
36
  # book: one a guest typed in, or the copy a placed order keeps.
37
37
  one :owner, resource: proc { Spree.api.address_owner_serializer }
38
+
39
+ expandable_custom_fields
38
40
  end
39
41
  end
40
42
  end
@@ -28,6 +28,8 @@ module Spree
28
28
  prefixed_id_attributes customer_id: :customer_owner
29
29
 
30
30
  one :owner, resource: proc { Spree.api.admin_address_owner_serializer }
31
+
32
+ expandable_custom_fields admin: true
31
33
  end
32
34
  end
33
35
  end
@@ -28,9 +28,7 @@ module Spree
28
28
  resource: proc { Spree.api.admin_category_serializer },
29
29
  if: proc { expand?('ancestors') }
30
30
 
31
- many :custom_fields,
32
- resource: proc { Spree.api.admin_custom_field_serializer },
33
- if: proc { expand?('custom_fields') }
31
+ expandable_custom_fields admin: true
34
32
  end
35
33
  end
36
34
  end
@@ -26,6 +26,8 @@ module Spree
26
26
  one :reason, resource: proc { Spree.api.admin_claim_reason_serializer }, if: proc { expand?('reason') }
27
27
  one :order, resource: proc { Spree.api.admin_order_serializer }, if: proc { expand?('order') }
28
28
  many :refunds, resource: proc { Spree.api.admin_refund_serializer }, if: proc { expand?('refunds') }
29
+
30
+ expandable_custom_fields admin: true
29
31
  end
30
32
  end
31
33
  end
@@ -18,10 +18,7 @@ module Spree
18
18
  resource: proc { Spree.api.admin_collection_rule_serializer },
19
19
  if: proc { expand?('rules') }
20
20
 
21
- # Override inherited custom_fields to use the admin serializer.
22
- many :custom_fields,
23
- resource: proc { Spree.api.admin_custom_field_serializer },
24
- if: proc { expand?('custom_fields') }
21
+ expandable_custom_fields admin: true
25
22
  end
26
23
  end
27
24
  end
@@ -30,6 +30,8 @@ module Spree
30
30
  many :memberships,
31
31
  resource: proc { Spree.api.admin_company_membership_serializer },
32
32
  if: proc { expand?('memberships') }
33
+
34
+ expandable_custom_fields admin: true
33
35
  end
34
36
  end
35
37
  end
@@ -11,6 +11,8 @@ module Spree
11
11
 
12
12
  attributes :metadata,
13
13
  created_at: :iso8601, updated_at: :iso8601
14
+
15
+ expandable_custom_fields admin: true
14
16
  end
15
17
  end
16
18
  end
@@ -99,6 +99,8 @@ module Spree
99
99
  many :companies,
100
100
  resource: proc { Spree.api.admin_company_serializer },
101
101
  if: proc { expand?('companies') }
102
+
103
+ expandable_custom_fields admin: true
102
104
  end
103
105
  end
104
106
  end
@@ -59,6 +59,8 @@ module Spree
59
59
  calculator = record.calculator
60
60
  { type: calculator.class.api_type, preferences: calculator.serialized_preferences } if calculator
61
61
  end
62
+
63
+ expandable_custom_fields admin: true
62
64
  end
63
65
  end
64
66
  end
@@ -61,6 +61,7 @@ module Spree
61
61
  resource: proc { Spree.api.admin_order_serializer },
62
62
  if: proc { expand?('order') }
63
63
 
64
+ expandable_custom_fields admin: true
64
65
  end
65
66
  end
66
67
  end
@@ -51,6 +51,8 @@ module Spree
51
51
  many :orders,
52
52
  resource: proc { Spree.api.admin_order_serializer },
53
53
  if: proc { expand?('orders') }
54
+
55
+ expandable_custom_fields admin: true
54
56
  end
55
57
  end
56
58
  end
@@ -37,7 +37,7 @@ module Spree
37
37
  # Looked up by email so an admin who's already on another store sees
38
38
  # the password prompt, not a fresh account form.
39
39
  attribute :invitee_exists do |invitation|
40
- Spree.admin_user_class.exists?(email: invitation.email)
40
+ invitation.invitee_account.present?
41
41
  end
42
42
 
43
43
  # Minimal store identity for the unauthenticated acceptance page's
@@ -85,6 +85,7 @@ module Spree
85
85
  resource: proc { Spree.api.admin_tax_category_serializer },
86
86
  if: proc { expand?('tax_category') }
87
87
 
88
+ expandable_custom_fields admin: true
88
89
  end
89
90
  end
90
91
  end
@@ -86,6 +86,8 @@ module Spree
86
86
  attribute :viewable_type do |asset|
87
87
  Spree::Base.polymorphic_api_type(asset.viewable_type)
88
88
  end
89
+
90
+ expandable_custom_fields admin: true
89
91
  end
90
92
  end
91
93
  end
@@ -9,6 +9,8 @@ module Spree
9
9
  # customer-facing serializer so public fields stay in sync.
10
10
  class NewsletterSubscriberSerializer < V3::NewsletterSubscriberSerializer
11
11
  prefixed_id_attributes :customer
12
+
13
+ expandable_custom_fields admin: true
12
14
  end
13
15
  end
14
16
  end
@@ -13,6 +13,8 @@ module Spree
13
13
  many :option_values,
14
14
  resource: proc { Spree.api.admin_option_value_serializer },
15
15
  if: proc { expand?('option_values') }
16
+
17
+ expandable_custom_fields admin: true
16
18
  end
17
19
  end
18
20
  end
@@ -11,6 +11,8 @@ module Spree
11
11
  one :option_type,
12
12
  resource: proc { Spree.api.admin_option_type_serializer },
13
13
  if: proc { expand?('option_type') }
14
+
15
+ expandable_custom_fields admin: true
14
16
  end
15
17
  end
16
18
  end
@@ -198,6 +198,8 @@ module Spree
198
198
  typelize freight_summary: [:FreightSummary, nullable: true]
199
199
 
200
200
  one :freight_summary, resource: proc { Spree.api.admin_freight_summary_serializer }
201
+
202
+ expandable_custom_fields admin: true
201
203
  end
202
204
  end
203
205
  end
@@ -25,6 +25,8 @@ module Spree
25
25
  attribute(:logo_url) { |payment_method| payment_method.class.logo_url }
26
26
  attribute(:docs_url) { |payment_method| payment_method.class.docs_url }
27
27
  attribute(:third_party) { |payment_method| payment_method.class.third_party? }
28
+
29
+ expandable_custom_fields admin: true
28
30
  end
29
31
  end
30
32
  end
@@ -45,7 +45,7 @@ module Spree
45
45
  Spree.api.admin_payment_source_serializer
46
46
  end
47
47
 
48
- serializer.new(payment.source).to_h
48
+ serializer.new(payment.source, params: nested_params('source')).to_h
49
49
  end
50
50
 
51
51
  many :capture_events,
@@ -65,6 +65,8 @@ module Spree
65
65
  many :payment_splits,
66
66
  resource: proc { Spree.api.admin_payment_split_serializer },
67
67
  if: proc { expand?('payment_splits') }
68
+
69
+ expandable_custom_fields admin: true
68
70
  end
69
71
  end
70
72
  end
@@ -7,6 +7,8 @@ module Spree
7
7
 
8
8
  attributes :metadata,
9
9
  created_at: :iso8601, updated_at: :iso8601
10
+
11
+ expandable_custom_fields admin: true
10
12
  end
11
13
  end
12
14
  end
@@ -108,9 +108,7 @@ module Spree
108
108
  resource: proc { Spree.api.admin_collection_serializer },
109
109
  if: proc { expand?('collections') }
110
110
 
111
- many :custom_fields,
112
- resource: proc { Spree.api.admin_custom_field_serializer },
113
- if: proc { expand?('custom_fields') }
111
+ expandable_custom_fields admin: true
114
112
 
115
113
  many :product_publications,
116
114
  resource: proc { Spree.api.admin_product_publication_serializer },
@@ -49,6 +49,8 @@ module Spree
49
49
 
50
50
  # Where the inbound parcel is, as the carrier last reported it.
51
51
  many :deliveries, resource: proc { Spree.api.admin_delivery_serializer }
52
+
53
+ expandable_custom_fields admin: true
52
54
  end
53
55
  end
54
56
  end
@@ -17,7 +17,8 @@ module Spree
17
17
  reference: 'string | null',
18
18
  period_start: 'string | null',
19
19
  period_end: 'string | null',
20
- transfers_count: :number
20
+ transfers_count: :number,
21
+ metadata: 'Record<string, unknown>'
21
22
 
22
23
  attributes :status, :currency, :reference, :metadata,
23
24
  period_start: :iso8601, period_end: :iso8601,
@@ -6,6 +6,8 @@ module Spree
6
6
  # shopper also gets, plus the operational state and the settlement and
7
7
  # tax configuration only the operator sets.
8
8
  class SellerSerializer < V3::SellerSerializer
9
+ include Concerns::ExternalReferencesAttribute
10
+
9
11
  typelize status: [:string, enum: Spree::Seller.statuses, enum_type_name: 'SellerStatus'],
10
12
  legal_name: [:string, nullable: true],
11
13
  registration_number: [:string, nullable: true],
@@ -75,6 +77,8 @@ module Spree
75
77
  one :returns_address,
76
78
  resource: proc { Spree.api.admin_address_serializer },
77
79
  if: proc { |seller| seller.returns_address.present? }
80
+
81
+ expandable_custom_fields admin: true
78
82
  end
79
83
  end
80
84
  end
@@ -52,6 +52,8 @@ module Spree
52
52
  one :customer,
53
53
  resource: proc { Spree.api.admin_customer_serializer },
54
54
  if: proc { expand?('customer') }
55
+
56
+ expandable_custom_fields admin: true
55
57
  end
56
58
  end
57
59
  end
@@ -2,10 +2,10 @@ module Spree
2
2
  module Api
3
3
  module V3
4
4
  module Admin
5
- class StoreSerializer < V3::BaseSerializer
6
- typelize name: :string, url: :string, code: :string, api_url: :string,
5
+ class StoreSerializer < V3::StoreSerializer
6
+ typelize url: :string, code: :string, api_url: :string,
7
7
  default_currency: [:string, enum: Spree::Money::Rounding::CURRENCY_CODES, enum_type_name: 'CurrencyCode'], default_locale: [:string, enum: Spree::Locales::ALL, enum_type_name: 'LocaleCode'],
8
- default_country_code: [:string, nullable: true],
8
+ default_country_code: [:string, nullable: true, enum: Spree::IsoData.country_codes, enum_type_name: 'CountryCode'],
9
9
  supported_currencies: [:string, multi: true, enum: Spree::Money::Rounding::CURRENCY_CODES, enum_type_name: 'CurrencyCode'],
10
10
  supported_locales: [:string, multi: true, enum: Spree::Locales::ALL, enum_type_name: 'LocaleCode'],
11
11
  available_locales: [:string, multi: true, enum: Spree::Locales::ALL, enum_type_name: 'LocaleCode'],
@@ -20,7 +20,6 @@ module Spree
20
20
  metadata: 'Record<string, unknown>'
21
21
 
22
22
  attributes :metadata,
23
- :name,
24
23
  :code,
25
24
  :default_currency,
26
25
  :default_locale,
@@ -112,9 +112,7 @@ module Spree
112
112
  resource: proc { Spree.api.admin_price_serializer },
113
113
  if: proc { expand?('prices') }
114
114
 
115
- many :custom_fields,
116
- resource: proc { Spree.api.admin_custom_field_serializer },
117
- if: proc { expand?('custom_fields') }
115
+ expandable_custom_fields admin: true
118
116
 
119
117
  many :stock_levels,
120
118
  resource: proc { Spree.api.admin_stock_level_serializer },
@@ -152,6 +152,12 @@ module Spree
152
152
  }.freeze
153
153
  private_constant :PREFERENCE_LIST_NAMES
154
154
 
155
+ # Settings declared with a code format share the code list request
156
+ # bodies take, so a value read back is the type a write takes.
157
+ FORMAT_CODE_LISTS = { 'iso-country' => :country, 'currency' => :currency, 'locale' => :locale,
158
+ 'timezone' => :time_zone }.freeze
159
+ private_constant :FORMAT_CODE_LISTS
160
+
155
161
  def self.preference_type_hint(schema, name)
156
162
  types = Array(schema['type'])
157
163
  options = {}
@@ -165,6 +171,9 @@ module Spree
165
171
  if schema['enum']
166
172
  options[:enum] = schema['enum'].compact
167
173
  options[:enum_type_name] = PREFERENCE_LIST_NAMES[name.to_sym] if PREFERENCE_LIST_NAMES.key?(name.to_sym)
174
+ elsif (code_list = FORMAT_CODE_LISTS[(schema['items'] || schema)['format']])
175
+ options[:enum_type_name], values = Spree::Api::V3::RequestSchema::CODE_LISTS.fetch(code_list)
176
+ options[:enum] = values.call
168
177
  end
169
178
  options.empty? ? hint : [hint, options]
170
179
  end
@@ -192,6 +201,25 @@ module Spree
192
201
  end
193
202
  end
194
203
 
204
+ # Declares the opt-in `custom_fields` expand. The Store API sends only
205
+ # values whose definition is storefront visible; Admin API serializers
206
+ # pass `admin: true` to send every value.
207
+ #
208
+ # @param admin [Boolean] whether to send every value rather than only storefront visible ones
209
+ # @return [void]
210
+ def self.expandable_custom_fields(admin: false)
211
+ if admin
212
+ many :custom_fields,
213
+ resource: proc { Spree.api.admin_custom_field_serializer },
214
+ if: proc { expand?('custom_fields') }
215
+ else
216
+ many :storefront_custom_fields,
217
+ key: :custom_fields,
218
+ resource: proc { Spree.api.custom_field_serializer },
219
+ if: proc { expand?('custom_fields') }
220
+ end
221
+ end
222
+
195
223
  # Plain decimal notation. BigDecimal renders 0.06 as "0.6e-1", which
196
224
  # is what a client would otherwise print beside a unit.
197
225
  #
@@ -50,10 +50,7 @@ module Spree
50
50
  resource: proc { Spree.api.category_serializer },
51
51
  if: proc { expand?('ancestors') }
52
52
 
53
- many :storefront_custom_fields,
54
- key: :custom_fields,
55
- resource: proc { Spree.api.custom_field_serializer },
56
- if: proc { expand?('custom_fields') }
53
+ expandable_custom_fields
57
54
  end
58
55
  end
59
56
  end
@@ -42,6 +42,8 @@ module Spree
42
42
  many :claim_line_items,
43
43
  resource: proc { Spree.api.claim_line_item_serializer },
44
44
  if: proc { expand?('claim_line_items') }
45
+
46
+ expandable_custom_fields
45
47
  end
46
48
  end
47
49
  end
@@ -29,10 +29,7 @@ module Spree
29
29
  image_url_for(collection.square_image)
30
30
  end
31
31
 
32
- many :storefront_custom_fields,
33
- key: :custom_fields,
34
- resource: proc { Spree.api.custom_field_serializer },
35
- if: proc { expand?('custom_fields') }
32
+ expandable_custom_fields
36
33
  end
37
34
  end
38
35
  end
@@ -25,6 +25,8 @@ module Spree
25
25
  { 'id' => node.prefixed_id, 'name' => node.name, 'kind' => node.kind }
26
26
  end
27
27
  end
28
+
29
+ expandable_custom_fields
28
30
  end
29
31
  end
30
32
  end
@@ -7,6 +7,8 @@ module Spree
7
7
  gateway_payment_profile_id: [:string, nullable: true]
8
8
 
9
9
  attributes :brand, :last4, :month, :year, :name, :default, :gateway_payment_profile_id
10
+
11
+ expandable_custom_fields
10
12
  end
11
13
  end
12
14
  end
@@ -54,6 +54,8 @@ module Spree
54
54
  many :customer_groups,
55
55
  proc { |groups, params| groups.for_store(params&.dig(:store) || Spree::Current.store) },
56
56
  resource: proc { Spree.api.customer_group_serializer }
57
+
58
+ expandable_custom_fields
57
59
  end
58
60
  end
59
61
  end
@@ -15,6 +15,8 @@ module Spree
15
15
  attribute :digital, &:digital?
16
16
  attribute :pickup, &:pickup?
17
17
  attribute :pickup_point, &:pickup_point?
18
+
19
+ expandable_custom_fields
18
20
  end
19
21
  end
20
22
  end
@@ -59,6 +59,8 @@ module Spree
59
59
  one :stock_location, resource: proc { Spree.api.stock_location_serializer }
60
60
  many :delivery_rates, resource: proc { Spree.api.delivery_rate_serializer }
61
61
  many :tax_lines, resource: proc { Spree.api.tax_line_serializer }, if: proc { expand?('tax_lines') }
62
+
63
+ expandable_custom_fields
62
64
  end
63
65
  end
64
66
  end
@@ -51,6 +51,7 @@ module Spree
51
51
 
52
52
  attribute :active, &:active?
53
53
 
54
+ expandable_custom_fields
54
55
  end
55
56
  end
56
57
  end
@@ -73,6 +73,8 @@ module Spree
73
73
  # exactly-one-adjustable rule makes the nested view complete, and the
74
74
  # owner already carries the tax totals.
75
75
  many :tax_lines, resource: proc { Spree.api.tax_line_serializer }, if: proc { expand?('tax_lines') }
76
+
77
+ expandable_custom_fields
76
78
  end
77
79
  end
78
80
  end
@@ -99,6 +99,8 @@ module Spree
99
99
  def url_helpers
100
100
  Rails.application.routes.url_helpers
101
101
  end
102
+
103
+ expandable_custom_fields
102
104
  end
103
105
  end
104
106
  end
@@ -21,6 +21,8 @@ module Spree
21
21
  attribute :customer_id do |subscriber|
22
22
  subscriber.customer&.prefixed_id if current_user && subscriber.customer_id == current_user.id
23
23
  end
24
+
25
+ expandable_custom_fields
24
26
  end
25
27
  end
26
28
  end
@@ -5,6 +5,8 @@ module Spree
5
5
  typelize name: :string, label: :string, position: :number, kind: [:string, enum: Spree::OptionType::KINDS, enum_type_name: 'OptionTypeKind']
6
6
 
7
7
  attributes :name, :label, :position, :kind
8
+
9
+ expandable_custom_fields
8
10
  end
9
11
  end
10
12
  end
@@ -21,6 +21,8 @@ module Spree
21
21
  attribute :image_url do |option_value|
22
22
  image_url_for(option_value.image)
23
23
  end
24
+
25
+ expandable_custom_fields
24
26
  end
25
27
  end
26
28
  end
@@ -79,6 +79,8 @@ module Spree
79
79
  one :shipping_address, resource: proc { Spree.api.address_serializer }
80
80
  one :gift_card, resource: proc { Spree.api.gift_card_serializer }
81
81
  one :market, resource: proc { Spree.api.market_serializer }
82
+
83
+ expandable_custom_fields
82
84
  end
83
85
  end
84
86
  end
@@ -14,6 +14,8 @@ module Spree
14
14
  attribute :session_required, &:session_required?
15
15
 
16
16
  attribute :source_required, &:source_required?
17
+
18
+ expandable_custom_fields
17
19
  end
18
20
  end
19
21
  end
@@ -42,10 +42,12 @@ module Spree
42
42
  Spree.api.payment_source_serializer
43
43
  end
44
44
 
45
- serializer.new(payment.source).to_h
45
+ serializer.new(payment.source, params: nested_params('source')).to_h
46
46
  end
47
47
 
48
48
  one :payment_method, resource: proc { Spree.api.payment_method_serializer }
49
+
50
+ expandable_custom_fields
49
51
  end
50
52
  end
51
53
  end
@@ -5,6 +5,8 @@ module Spree
5
5
  typelize gateway_payment_profile_id: [:string, nullable: true]
6
6
 
7
7
  attributes :gateway_payment_profile_id
8
+
9
+ expandable_custom_fields
8
10
  end
9
11
  end
10
12
  end
@@ -137,10 +137,7 @@ module Spree
137
137
  resource: proc { Spree.api.category_serializer },
138
138
  if: proc { expand?('categories') }
139
139
 
140
- many :storefront_custom_fields,
141
- key: :custom_fields,
142
- resource: proc { Spree.api.custom_field_serializer },
143
- if: proc { expand?('custom_fields') }
140
+ expandable_custom_fields
144
141
 
145
142
  typelize prior_price: ['PriceHistory', nullable: true],
146
143
  seller_id: [:string, nullable: true]
@@ -44,6 +44,8 @@ module Spree
44
44
  many :return_line_items,
45
45
  resource: proc { Spree.api.return_line_item_serializer },
46
46
  if: proc { expand?('return_line_items') }
47
+
48
+ expandable_custom_fields
47
49
  end
48
50
  end
49
51
  end
@@ -5,12 +5,33 @@ module Spree
5
5
  class InvitationSerializer < V3::BaseSerializer
6
6
  typelize email: :string, status: [:string, enum: Spree::Invitation.statuses, enum_type_name: 'InvitationStatus'],
7
7
  expires_at: [:string, nullable: true],
8
- accepted_at: [:string, nullable: true]
8
+ accepted_at: [:string, nullable: true],
9
+ inviter_email: :string,
10
+ invitee_exists: [:boolean, optional: true],
11
+ seller: '{ id: string; name: string }'
9
12
 
10
13
  attributes :email,
11
14
  created_at: :iso8601, expires_at: :iso8601, accepted_at: :iso8601
12
15
 
13
16
  attributes status: :string
17
+
18
+ attribute :inviter_email do |invitation|
19
+ invitation.inviter.email
20
+ end
21
+
22
+ # Drives the acceptance page's sign-in vs sign-up branch, so only the
23
+ # public lookup carries it: whoever holds the emailed link already
24
+ # knows the address. A seller's team screen does not get to learn
25
+ # which addresses hold accounts elsewhere on the marketplace.
26
+ attribute :invitee_exists, if: proc { params[:acceptance] } do |invitation|
27
+ invitation.invitee_account.present?
28
+ end
29
+
30
+ # The smallest shape the acceptance page's title ("Join <seller>")
31
+ # needs; the page is public, so nothing more of the seller goes out.
32
+ attribute :seller do |invitation|
33
+ { id: invitation.resource.prefixed_id, name: invitation.resource.name }
34
+ end
14
35
  end
15
36
  end
16
37
  end
@@ -17,7 +17,7 @@ module Spree
17
17
  products_count: :number,
18
18
  default_currency: [:string, enum: Spree::Money::Rounding::CURRENCY_CODES, enum_type_name: 'CurrencyCode'],
19
19
  supported_currencies: [:string, multi: true, enum: Spree::Money::Rounding::CURRENCY_CODES, enum_type_name: 'CurrencyCode'],
20
- timezone: [:string, nullable: true]
20
+ timezone: [:string, nullable: true, enum: Spree::TimeZones::SUGGESTED, enum_type_name: 'TimeZone']
21
21
 
22
22
  attributes :timezone,
23
23
  :status, :legal_name, :registration_number,
@@ -42,6 +42,8 @@ module Spree
42
42
  many :policies,
43
43
  resource: proc { Spree.api.policy_serializer },
44
44
  if: proc { expand?('policies') }
45
+
46
+ expandable_custom_fields
45
47
  end
46
48
  end
47
49
  end
@@ -7,6 +7,8 @@ module Spree
7
7
  money_attributes :amount, :amount_used, :amount_remaining, :display_amount,
8
8
  :display_amount_used, :display_amount_remaining
9
9
  attributes :currency
10
+
11
+ expandable_custom_fields
10
12
  end
11
13
  end
12
14
  end
@@ -0,0 +1,16 @@
1
+ module Spree
2
+ module Api
3
+ module V3
4
+ # The current store's public identity and default SEO metadata, in the
5
+ # request's locale. Missing translations fall back to the store's default
6
+ # locale.
7
+ class StoreSerializer < BaseSerializer
8
+ typelize name: :string,
9
+ seo_title: [:string, nullable: true],
10
+ meta_description: [:string, nullable: true]
11
+
12
+ attributes :name, :seo_title, :meta_description
13
+ end
14
+ end
15
+ end
16
+ end
@@ -127,10 +127,7 @@ module Spree
127
127
 
128
128
  many :option_values, resource: proc { Spree.api.option_value_serializer }
129
129
 
130
- many :storefront_custom_fields,
131
- key: :custom_fields,
132
- resource: proc { Spree.api.custom_field_serializer },
133
- if: proc { expand?('custom_fields') }
130
+ expandable_custom_fields
134
131
 
135
132
  typelize prior_price: ['PriceHistory', nullable: true]
136
133
 
@@ -40,22 +40,25 @@ module Spree
40
40
  datetime: { type: :string, format: :'date-time' },
41
41
  id: { type: :string },
42
42
  any: {},
43
- # Codes from the closed lists below.
43
+ # Codes from the lists below.
44
44
  country: { type: :string },
45
45
  currency: { type: :string },
46
46
  locale: { type: :string },
47
+ time_zone: { type: :string },
47
48
  weight_unit: { type: :string },
48
49
  dimension_unit: { type: :string }
49
50
  }.freeze
50
51
 
51
- # The closed lists a code field takes, published once per API as a
52
- # named component — the same `CountryCode`, `CurrencyCode` and
53
- # `WeightUnit` types the serializers declare, so a value read from a
54
- # response is the type a request takes.
52
+ # The lists a code field takes, published once per API as a named
53
+ # component — the same `CountryCode`, `CurrencyCode` and `WeightUnit`
54
+ # types the serializers declare, so a value read from a response is the
55
+ # type a request takes. A list `Typelizer::OpenEnums` does not close
56
+ # only suggests its values.
55
57
  CODE_LISTS = {
56
58
  country: ['CountryCode', -> { Spree::IsoData.country_codes }],
57
59
  currency: ['CurrencyCode', -> { Spree::Money::Rounding::CURRENCY_CODES }],
58
60
  locale: ['LocaleCode', -> { Spree::Locales::ALL }],
61
+ time_zone: ['TimeZone', -> { Spree::TimeZones::SUGGESTED }],
59
62
  weight_unit: ['WeightUnit', -> { Spree::Variant::WEIGHT_UNITS }],
60
63
  dimension_unit: ['DimensionUnit', -> { Spree::Variant::DIMENSION_UNITS }]
61
64
  }.freeze
@@ -348,7 +351,12 @@ module Spree
348
351
  next unless CODE_LISTS.key?(field.kind)
349
352
 
350
353
  name, values = CODE_LISTS[field.kind]
351
- lists[name] = { type: :string, enum: values.call }
354
+ lists[name] = if Typelizer::OpenEnums.closed?(name)
355
+ { type: :string, enum: values.call }
356
+ else
357
+ Typelizer::OpenEnums.open_schema({ type: :string }, values.call)
358
+ .merge(description: Typelizer::OpenEnums.description(name)).compact
359
+ end
352
360
  end
353
361
  end
354
362
 
@@ -469,7 +477,7 @@ module Spree
469
477
 
470
478
  # The same open list the serializers publish (`enum_type_name`):
471
479
  # clients autocomplete the built-in values and still accept any other.
472
- { anyOf: [schema.merge(enum: field.enum), schema] }
480
+ Typelizer::OpenEnums.open_schema(schema, field.enum)
473
481
  end
474
482
  end
475
483
  end
data/config/routes.rb CHANGED
@@ -22,6 +22,9 @@ Spree::Core::Engine.add_routes do
22
22
  # Current channel context (never a list — see Store::ChannelController)
23
23
  resource :channel, only: [:show], controller: 'channel'
24
24
 
25
+ # Current store context (name and default SEO metadata, localized)
26
+ resource :store, only: [:show], controller: 'store'
27
+
25
28
  # Catalog
26
29
  resources :products, only: [:index, :show] do
27
30
  collection do
@@ -287,9 +290,9 @@ Spree::Core::Engine.add_routes do
287
290
  resource :store, only: [:show, :update], controller: 'store' do
288
291
  get :data_sources
289
292
  end
290
- # The store's own custom fields, addressed by its id like every other
293
+ # The store's own custom fields and translations, addressed by its id like every other
291
294
  # parent. The controller only ever resolves the current store.
292
- resources :stores, only: [], concerns: :custom_fieldable
295
+ resources :stores, only: [], concerns: [:custom_fieldable, :translatable]
293
296
 
294
297
  # Staff & access (invitations, admin users, roles, API keys)
295
298
  resources :admin_users, only: [:index, :show, :update, :destroy]
@@ -18,7 +18,7 @@ module Spree
18
18
  product_filter_sort_option media_event return return_line_item exchange exchange_line_item claim
19
19
  claim_line_item return_reason claim_reason digital_asset export gift_card_batch import import_row
20
20
  invitation newsletter_subscriber promotion refund stock_level stock_movement stock_reservation
21
- stock_transfer company company_membership company_invitation seller file_upload file_upload_target].freeze
21
+ stock_transfer company company_membership company_invitation seller file_upload file_upload_target store].freeze
22
22
 
23
23
  ADMIN_SERIALIZERS =
24
24
  %i[country state locale applied_promotion discount tax_line cart delivery_zone delivery_profile
@@ -110,7 +110,8 @@ module Spree
110
110
  type = "export type #{name} = (typeof #{constant})[number] | (string & {})"
111
111
  type = "export type #{name} =\n | (typeof #{constant})[number]\n | (string & {})" if type.length > LINE_WIDTH
112
112
 
113
- "\n/** The built-in values of `#{name}`. Extensions may add more. */\n#{line}\n#{type}\n"
113
+ summary = Typelizer::OpenEnums.description(name) || "The built-in values of `#{name}`. Extensions may add more."
114
+ "\n/** #{summary} */\n#{line}\n#{type}\n"
114
115
  end
115
116
  end
116
117
  end
@@ -34,6 +34,25 @@ module Typelizer
34
34
  TaxRemittance UnitSystem
35
35
  ].freeze
36
36
 
37
+ # Open lists whose values are suggestions rather than built-ins an
38
+ # extension adds to, described as such wherever the list is published.
39
+ DESCRIPTIONS = {
40
+ 'TimeZone' => 'Common IANA time zones; any other IANA time zone identifier is accepted too.'
41
+ }.freeze
42
+
43
+ # @param name [String, nil] a list's `enum_type_name`
44
+ # @return [String, nil] what the list's values are, when they are not built-ins
45
+ def self.description(name)
46
+ DESCRIPTIONS[name]
47
+ end
48
+
49
+ # @param schema [Hash] the schema of any value in the list
50
+ # @param values [Array<String>] the values to suggest
51
+ # @return [Hash] a schema suggesting the values while accepting any other
52
+ def self.open_schema(schema, values)
53
+ { anyOf: [schema.merge(enum: values), schema] }
54
+ end
55
+
37
56
  # @param name [String, nil] a list's `enum_type_name`
38
57
  # @return [Boolean] whether the list is closed: no value outside it is valid
39
58
  def self.closed?(name)
@@ -63,7 +82,7 @@ module Typelizer
63
82
  return super unless property.enum_type_name && property.enum.is_a?(Array) && !property.multi
64
83
  return super if OpenEnums.closed?(property.enum_type_name)
65
84
 
66
- open = { anyOf: [{ type: :string, enum: property.enum.compact }, { type: :string }] }
85
+ open = OpenEnums.open_schema({ type: :string }, property.enum.compact)
67
86
  # OpenAPI 3.0 ignores `nullable` beside `anyOf`, which is where
68
87
  # Typelizer puts it, so the free-string branch carries it instead.
69
88
  if property.nullable && !v31?(openapi_version)
@@ -72,7 +91,7 @@ module Typelizer
72
91
  apply_nullable(open, property, openapi_version: openapi_version)
73
92
  end
74
93
  apply_metadata(open, property)
75
- open[:description] ||= OPEN_ENUM_DESCRIPTION
94
+ open[:description] ||= OpenEnums.description(property.enum_type_name) || OPEN_ENUM_DESCRIPTION
76
95
  open
77
96
  end
78
97
  end
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: 6.0.0
4
+ version: 6.0.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-10-27 00:00:00.000000000 Z
11
+ date: 2026-10-29 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rswag-specs
@@ -44,14 +44,14 @@ dependencies:
44
44
  requirements:
45
45
  - - '='
46
46
  - !ruby/object:Gem::Version
47
- version: 6.0.0
47
+ version: 6.0.1
48
48
  type: :runtime
49
49
  prerelease: false
50
50
  version_requirements: !ruby/object:Gem::Requirement
51
51
  requirements:
52
52
  - - '='
53
53
  - !ruby/object:Gem::Version
54
- version: 6.0.0
54
+ version: 6.0.1
55
55
  description: Spree Commerce Store / Admin API and HTTP webhooks
56
56
  email:
57
57
  - hello@spreecommerce.org
@@ -390,6 +390,7 @@ files:
390
390
  - app/controllers/spree/api/v3/store/products_controller.rb
391
391
  - app/controllers/spree/api/v3/store/resource_controller.rb
392
392
  - app/controllers/spree/api/v3/store/sellers_controller.rb
393
+ - app/controllers/spree/api/v3/store/store_controller.rb
393
394
  - app/controllers/spree/api/v3/store/wishlist_items_controller.rb
394
395
  - app/controllers/spree/api/v3/store/wishlists_controller.rb
395
396
  - app/controllers/spree/api/v3/webhooks/fulfillments_controller.rb
@@ -740,6 +741,7 @@ files:
740
741
  - app/serializers/spree/api/v3/stock_transfer_serializer.rb
741
742
  - app/serializers/spree/api/v3/store_credit_event_serializer.rb
742
743
  - app/serializers/spree/api/v3/store_credit_serializer.rb
744
+ - app/serializers/spree/api/v3/store_serializer.rb
743
745
  - app/serializers/spree/api/v3/supplier_event_serializer.rb
744
746
  - app/serializers/spree/api/v3/tax_category_serializer.rb
745
747
  - app/serializers/spree/api/v3/tax_identifier_serializer.rb
@@ -836,9 +838,9 @@ licenses:
836
838
  - BSD-3-Clause
837
839
  metadata:
838
840
  bug_tracker_uri: https://github.com/spree/spree/issues
839
- changelog_uri: https://github.com/spree/spree/releases/tag/v6.0.0
841
+ changelog_uri: https://github.com/spree/spree/releases/tag/v6.0.1
840
842
  documentation_uri: https://docs.spreecommerce.org/
841
- source_code_uri: https://github.com/spree/spree/tree/v6.0.0
843
+ source_code_uri: https://github.com/spree/spree/tree/v6.0.1
842
844
  post_install_message:
843
845
  rdoc_options: []
844
846
  require_paths: