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.
- checksums.yaml +4 -4
- data/app/controllers/spree/api/v3/admin/invitation_acceptances_controller.rb +8 -4
- data/app/controllers/spree/api/v3/admin/sellers_controller.rb +1 -1
- data/app/controllers/spree/api/v3/admin/store_controller.rb +23 -7
- data/app/controllers/spree/api/v3/seller/invitation_acceptances_controller.rb +15 -5
- data/app/controllers/spree/api/v3/store/customers_controller.rb +1 -0
- data/app/controllers/spree/api/v3/store/store_controller.rb +25 -0
- data/app/serializers/spree/api/v3/address_serializer.rb +2 -0
- data/app/serializers/spree/api/v3/admin/address_serializer.rb +2 -0
- data/app/serializers/spree/api/v3/admin/category_serializer.rb +1 -3
- data/app/serializers/spree/api/v3/admin/claim_serializer.rb +2 -0
- data/app/serializers/spree/api/v3/admin/collection_serializer.rb +1 -4
- data/app/serializers/spree/api/v3/admin/company_serializer.rb +2 -0
- data/app/serializers/spree/api/v3/admin/credit_card_serializer.rb +2 -0
- data/app/serializers/spree/api/v3/admin/customer_serializer.rb +2 -0
- data/app/serializers/spree/api/v3/admin/delivery_method_serializer.rb +2 -0
- data/app/serializers/spree/api/v3/admin/fulfillment_serializer.rb +1 -0
- data/app/serializers/spree/api/v3/admin/gift_card_serializer.rb +2 -0
- data/app/serializers/spree/api/v3/admin/invitation_serializer.rb +1 -1
- data/app/serializers/spree/api/v3/admin/line_item_serializer.rb +1 -0
- data/app/serializers/spree/api/v3/admin/media_serializer.rb +2 -0
- data/app/serializers/spree/api/v3/admin/newsletter_subscriber_serializer.rb +2 -0
- data/app/serializers/spree/api/v3/admin/option_type_serializer.rb +2 -0
- data/app/serializers/spree/api/v3/admin/option_value_serializer.rb +2 -0
- data/app/serializers/spree/api/v3/admin/order_serializer.rb +2 -0
- data/app/serializers/spree/api/v3/admin/payment_method_serializer.rb +2 -0
- data/app/serializers/spree/api/v3/admin/payment_serializer.rb +3 -1
- data/app/serializers/spree/api/v3/admin/payment_source_serializer.rb +2 -0
- data/app/serializers/spree/api/v3/admin/product_serializer.rb +1 -3
- data/app/serializers/spree/api/v3/admin/return_serializer.rb +2 -0
- data/app/serializers/spree/api/v3/admin/seller_payout_serializer.rb +2 -1
- data/app/serializers/spree/api/v3/admin/seller_serializer.rb +4 -0
- data/app/serializers/spree/api/v3/admin/store_credit_serializer.rb +2 -0
- data/app/serializers/spree/api/v3/admin/store_serializer.rb +3 -4
- data/app/serializers/spree/api/v3/admin/variant_serializer.rb +1 -3
- data/app/serializers/spree/api/v3/base_serializer.rb +28 -0
- data/app/serializers/spree/api/v3/category_serializer.rb +1 -4
- data/app/serializers/spree/api/v3/claim_serializer.rb +2 -0
- data/app/serializers/spree/api/v3/collection_serializer.rb +1 -4
- data/app/serializers/spree/api/v3/company_serializer.rb +2 -0
- data/app/serializers/spree/api/v3/credit_card_serializer.rb +2 -0
- data/app/serializers/spree/api/v3/customer_serializer.rb +2 -0
- data/app/serializers/spree/api/v3/delivery_method_serializer.rb +2 -0
- data/app/serializers/spree/api/v3/fulfillment_serializer.rb +2 -0
- data/app/serializers/spree/api/v3/gift_card_serializer.rb +1 -0
- data/app/serializers/spree/api/v3/line_item_serializer.rb +2 -0
- data/app/serializers/spree/api/v3/media_serializer.rb +2 -0
- data/app/serializers/spree/api/v3/newsletter_subscriber_serializer.rb +2 -0
- data/app/serializers/spree/api/v3/option_type_serializer.rb +2 -0
- data/app/serializers/spree/api/v3/option_value_serializer.rb +2 -0
- data/app/serializers/spree/api/v3/order_serializer.rb +2 -0
- data/app/serializers/spree/api/v3/payment_method_serializer.rb +2 -0
- data/app/serializers/spree/api/v3/payment_serializer.rb +3 -1
- data/app/serializers/spree/api/v3/payment_source_serializer.rb +2 -0
- data/app/serializers/spree/api/v3/product_serializer.rb +1 -4
- data/app/serializers/spree/api/v3/return_serializer.rb +2 -0
- data/app/serializers/spree/api/v3/seller/invitation_serializer.rb +22 -1
- data/app/serializers/spree/api/v3/seller/profile_serializer.rb +1 -1
- data/app/serializers/spree/api/v3/seller_serializer.rb +2 -0
- data/app/serializers/spree/api/v3/store_credit_serializer.rb +2 -0
- data/app/serializers/spree/api/v3/store_serializer.rb +16 -0
- data/app/serializers/spree/api/v3/variant_serializer.rb +1 -4
- data/app/services/spree/api/v3/request_schema.rb +15 -7
- data/config/routes.rb +5 -2
- data/lib/spree/api/dependencies.rb +1 -1
- data/lib/spree/api/enum_types.rb +2 -1
- data/lib/typelizer/open_enums.rb +21 -2
- metadata +8 -6
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 88513caab1df4ae8256a450d38b98601d724763697f75cd6bbe92f20986fac7c
|
|
4
|
+
data.tar.gz: 87742481e6e84a33e11080d3c830ca960eb692a243fb6d1b6c926a43f7d951e0
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
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: '
|
|
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 =
|
|
78
|
-
return
|
|
77
|
+
existing = invitation.invitee_account
|
|
78
|
+
return create_new_invitee(invitation) unless existing
|
|
79
79
|
|
|
80
|
-
|
|
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 :
|
|
11
|
-
|
|
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
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
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 =
|
|
101
|
-
return
|
|
100
|
+
existing = invitation.invitee_account
|
|
101
|
+
return create_new_invitee(invitation) unless existing
|
|
102
102
|
|
|
103
|
-
|
|
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
|
|
@@ -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,9 +28,7 @@ module Spree
|
|
|
28
28
|
resource: proc { Spree.api.admin_category_serializer },
|
|
29
29
|
if: proc { expand?('ancestors') }
|
|
30
30
|
|
|
31
|
-
|
|
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
|
-
|
|
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
|
|
@@ -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
|
-
|
|
40
|
+
invitation.invitee_account.present?
|
|
41
41
|
end
|
|
42
42
|
|
|
43
43
|
# Minimal store identity for the unauthenticated acceptance page's
|
|
@@ -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
|
|
@@ -108,9 +108,7 @@ module Spree
|
|
|
108
108
|
resource: proc { Spree.api.admin_collection_serializer },
|
|
109
109
|
if: proc { expand?('collections') }
|
|
110
110
|
|
|
111
|
-
|
|
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 },
|
|
@@ -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
|
|
@@ -2,10 +2,10 @@ module Spree
|
|
|
2
2
|
module Api
|
|
3
3
|
module V3
|
|
4
4
|
module Admin
|
|
5
|
-
class StoreSerializer < V3::
|
|
6
|
-
typelize
|
|
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
|
-
|
|
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
|
-
|
|
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
|
|
@@ -29,10 +29,7 @@ module Spree
|
|
|
29
29
|
image_url_for(collection.square_image)
|
|
30
30
|
end
|
|
31
31
|
|
|
32
|
-
|
|
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
|
|
@@ -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
|
|
@@ -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
|
|
@@ -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
|
|
@@ -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
|
|
@@ -137,10 +137,7 @@ module Spree
|
|
|
137
137
|
resource: proc { Spree.api.category_serializer },
|
|
138
138
|
if: proc { expand?('categories') }
|
|
139
139
|
|
|
140
|
-
|
|
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]
|
|
@@ -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,
|
|
@@ -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
|
-
|
|
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
|
|
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
|
|
52
|
-
#
|
|
53
|
-
#
|
|
54
|
-
#
|
|
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] =
|
|
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
|
-
|
|
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
|
data/lib/spree/api/enum_types.rb
CHANGED
|
@@ -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
|
-
"
|
|
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
|
data/lib/typelizer/open_enums.rb
CHANGED
|
@@ -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 = {
|
|
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.
|
|
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-
|
|
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.
|
|
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.
|
|
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.
|
|
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.
|
|
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:
|