@spree/docs 0.1.230 → 0.1.232
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.
- package/dist/api-reference/store.yaml +28 -0
- package/dist/developer/agentic/agent-skills.md +1 -1
- package/dist/developer/cli/quickstart.md +2 -2
- package/dist/developer/core-concepts/addresses.md +13 -0
- package/dist/developer/core-concepts/calculators.md +6 -1
- package/dist/developer/core-concepts/carts.md +19 -1
- package/dist/developer/core-concepts/catalogs.md +51 -2
- package/dist/developer/core-concepts/channels.md +20 -1
- package/dist/developer/core-concepts/commissions.md +70 -1
- package/dist/developer/core-concepts/companies.md +74 -0
- package/dist/developer/core-concepts/customers.md +17 -5
- package/dist/developer/core-concepts/data-privacy.md +20 -7
- package/dist/developer/core-concepts/delivery-setup.md +57 -0
- package/dist/developer/core-concepts/discounts.md +7 -0
- package/dist/developer/core-concepts/events.md +13 -7
- package/dist/developer/core-concepts/fees.md +20 -0
- package/dist/developer/core-concepts/fulfillments.md +3 -3
- package/dist/developer/core-concepts/imports-exports.md +21 -5
- package/dist/developer/core-concepts/inventory.md +73 -1
- package/dist/developer/core-concepts/markets.md +5 -6
- package/dist/developer/core-concepts/media.md +66 -1
- package/dist/developer/core-concepts/metafields.md +1 -1
- package/dist/developer/core-concepts/order-totals.md +18 -1
- package/dist/developer/core-concepts/orders.md +2 -1
- package/dist/developer/core-concepts/payments.md +100 -20
- package/dist/developer/core-concepts/pricing.md +13 -8
- package/dist/developer/core-concepts/products.md +52 -1
- package/dist/developer/core-concepts/reporting.md +5 -5
- package/dist/developer/core-concepts/returns-exchanges-claims.md +41 -2
- package/dist/developer/core-concepts/search-filtering.md +1 -2
- package/dist/developer/core-concepts/sellers.md +109 -2
- package/dist/developer/core-concepts/slugs.md +1 -1
- package/dist/developer/core-concepts/staff-roles.md +23 -3
- package/dist/developer/core-concepts/store-credits-gift-cards.md +60 -23
- package/dist/developer/core-concepts/stores.md +21 -0
- package/dist/developer/core-concepts/taxes.md +43 -0
- package/dist/developer/core-concepts/translations.md +9 -0
- package/dist/developer/core-concepts/webhooks.md +45 -3
- package/dist/developer/create-spree-app/quickstart.md +10 -10
- package/dist/developer/dashboard/deployment.md +4 -4
- package/dist/developer/dashboard/recipes/attribute-end-to-end.md +1 -1
- package/dist/developer/deployment/docker.md +2 -2
- package/dist/developer/how-to/custom-promotion.md +33 -13
- package/dist/developer/multi-tenant/quickstart.md +6 -6
- package/dist/developer/storefront/nextjs/testing.md +2 -2
- package/package.json +1 -1
|
@@ -83,6 +83,17 @@ spree api post /webhook_endpoints -d '{
|
|
|
83
83
|
}'
|
|
84
84
|
```
|
|
85
85
|
|
|
86
|
+
```bash cURL
|
|
87
|
+
curl -X POST 'https://api.mystore.com/api/v3/admin/webhook_endpoints' \
|
|
88
|
+
-H 'X-Spree-API-Key: sk_xxx' \
|
|
89
|
+
-H 'Content-Type: application/json' \
|
|
90
|
+
-d '{
|
|
91
|
+
"url": "https://example.com/webhooks/spree",
|
|
92
|
+
"subscriptions": ["order.*", "product.created"],
|
|
93
|
+
"active": true
|
|
94
|
+
}'
|
|
95
|
+
```
|
|
96
|
+
|
|
86
97
|
|
|
87
98
|
> **WARNING:** The `secret_key` is returned **only once**, in the create response. Save it immediately — it can't be retrieved later and is required to verify webhook signatures.
|
|
88
99
|
|
|
@@ -113,6 +124,13 @@ spree api patch /webhook_endpoints/whe_xxx \
|
|
|
113
124
|
-d '{"subscriptions": ["order.placed", "order.canceled"]}'
|
|
114
125
|
```
|
|
115
126
|
|
|
127
|
+
```bash cURL
|
|
128
|
+
curl -X PATCH 'https://api.mystore.com/api/v3/admin/webhook_endpoints/whe_xxx' \
|
|
129
|
+
-H 'X-Spree-API-Key: sk_xxx' \
|
|
130
|
+
-H 'Content-Type: application/json' \
|
|
131
|
+
-d '{ "subscriptions": ["order.placed", "order.canceled"] }'
|
|
132
|
+
```
|
|
133
|
+
|
|
116
134
|
|
|
117
135
|
The `subscriptions` array accepts exact event names and wildcard patterns:
|
|
118
136
|
|
|
@@ -128,7 +146,7 @@ The `subscriptions` array accepts exact event names and wildcard patterns:
|
|
|
128
146
|
|
|
129
147
|
Each webhook delivery sends a JSON payload with the following structure. The `data` object uses the same [Store API V3 serializers](../../api-reference/introduction.md) as the REST API, so webhook payloads and API responses share the same schema:
|
|
130
148
|
|
|
131
|
-
```json
|
|
149
|
+
```json Payload
|
|
132
150
|
{
|
|
133
151
|
"id": "550e8400-e29b-41d4-a716-446655440000",
|
|
134
152
|
"name": "order.placed",
|
|
@@ -188,7 +206,7 @@ The [Spree Storefront](https://github.com/spree/storefront) includes a ready-mad
|
|
|
188
206
|
|
|
189
207
|
Use `@spree/sdk/webhooks` for framework-agnostic verification:
|
|
190
208
|
|
|
191
|
-
```typescript
|
|
209
|
+
```typescript Store SDK
|
|
192
210
|
import { verifyWebhookSignature } from '@spree/sdk/webhooks'
|
|
193
211
|
import type { WebhookEvent } from '@spree/sdk/webhooks'
|
|
194
212
|
import type { Order } from '@spree/sdk'
|
|
@@ -211,7 +229,7 @@ app.post('/webhooks/spree', async (req, res) => {
|
|
|
211
229
|
|
|
212
230
|
#### Ruby
|
|
213
231
|
|
|
214
|
-
```ruby
|
|
232
|
+
```ruby server/app/controllers/webhooks_controller.rb
|
|
215
233
|
class WebhooksController < ApplicationController
|
|
216
234
|
skip_before_action :verify_authenticity_token
|
|
217
235
|
|
|
@@ -272,6 +290,14 @@ spree api get /webhook_endpoints/whe_xxx/deliveries -q event_name_eq=order.place
|
|
|
272
290
|
spree api post /webhook_endpoints/whe_xxx/deliveries/whd_xxx/redeliver
|
|
273
291
|
```
|
|
274
292
|
|
|
293
|
+
```bash cURL
|
|
294
|
+
curl 'https://api.mystore.com/api/v3/admin/webhook_endpoints/whe_xxx/deliveries?q[event_name_eq]=order.placed' \
|
|
295
|
+
-H 'X-Spree-API-Key: sk_xxx'
|
|
296
|
+
|
|
297
|
+
curl -X POST 'https://api.mystore.com/api/v3/admin/webhook_endpoints/whe_xxx/deliveries/whd_xxx/redeliver' \
|
|
298
|
+
-H 'X-Spree-API-Key: sk_xxx'
|
|
299
|
+
```
|
|
300
|
+
|
|
275
301
|
|
|
276
302
|
### Delivery Attributes
|
|
277
303
|
|
|
@@ -339,6 +365,17 @@ spree api post /webhook_endpoints -d '{
|
|
|
339
365
|
spree api post /webhook_endpoints/whe_xxx/send_test
|
|
340
366
|
```
|
|
341
367
|
|
|
368
|
+
```bash cURL
|
|
369
|
+
curl -X POST 'https://api.mystore.com/api/v3/admin/webhook_endpoints' \
|
|
370
|
+
-H 'X-Spree-API-Key: sk_xxx' \
|
|
371
|
+
-H 'Content-Type: application/json' \
|
|
372
|
+
-d '{
|
|
373
|
+
"url": "https://your-ngrok-url.ngrok.io/webhooks",
|
|
374
|
+
"subscriptions": ["order.*"],
|
|
375
|
+
"active": true
|
|
376
|
+
}'
|
|
377
|
+
```
|
|
378
|
+
|
|
342
379
|
|
|
343
380
|
`send_test` delivers a synthetic `webhook.test` event so you can verify the endpoint is reachable and your signature-verification code works, without having to trigger a real order.
|
|
344
381
|
|
|
@@ -386,6 +423,11 @@ const failed = deliveries[0]
|
|
|
386
423
|
spree api get /webhook_endpoints/whe_xxx/deliveries -q success_eq=false
|
|
387
424
|
```
|
|
388
425
|
|
|
426
|
+
```bash cURL
|
|
427
|
+
curl 'https://api.mystore.com/api/v3/admin/webhook_endpoints/whe_xxx/deliveries?q[success_eq]=false' \
|
|
428
|
+
-H 'X-Spree-API-Key: sk_xxx'
|
|
429
|
+
```
|
|
430
|
+
|
|
389
431
|
|
|
390
432
|
## Related Documentation
|
|
391
433
|
|
|
@@ -53,14 +53,14 @@ npx create-spree-app@latest my-store --no-storefront --no-sample-data --no-start
|
|
|
53
53
|
```text
|
|
54
54
|
my-store/
|
|
55
55
|
├── docker-compose.yml # Spree backend (prebuilt image) + Postgres + Meilisearch
|
|
56
|
-
├── docker-compose.dev.yml # Alternative: build from local
|
|
56
|
+
├── docker-compose.dev.yml # Alternative: build from local server/
|
|
57
57
|
├── render.yaml # Render Blueprint — one Docker service built from this repo
|
|
58
58
|
├── .env # SECRET_KEY_BASE, SPREE_PORT, SPREE_VERSION_TAG, SPREE_SAMPLE_DATA
|
|
59
59
|
├── .dockerignore # Keeps the production build context to sources
|
|
60
60
|
├── .gitignore
|
|
61
61
|
├── package.json # Convenience scripts
|
|
62
62
|
├── README.md
|
|
63
|
-
├──
|
|
63
|
+
├── server/ # Full Rails app — the Spree API (from spree/spree-starter)
|
|
64
64
|
│ ├── Gemfile
|
|
65
65
|
│ ├── Dockerfile # Also builds the production image (API + dashboard)
|
|
66
66
|
│ ├── config/
|
|
@@ -84,18 +84,18 @@ my-store/
|
|
|
84
84
|
|
|
85
85
|
## Customizing the Spree API
|
|
86
86
|
|
|
87
|
-
The `
|
|
87
|
+
The `server/` directory is the Spree API — a full Rails application with Spree installed (cloned from [spree-starter](https://github.com/spree/spree-starter)) serving the Store and Admin APIs your storefront and dashboard talk to, plus background jobs and transactional emails. By default, the project runs it from a prebuilt Docker image. To switch to building from your local copy:
|
|
88
88
|
|
|
89
89
|
```bash
|
|
90
90
|
npx spree eject
|
|
91
91
|
```
|
|
92
92
|
|
|
93
|
-
This replaces `docker-compose.yml` with a version that builds from `
|
|
93
|
+
This replaces `docker-compose.yml` with a version that builds from `server/`, rebuilds the image, and restarts services. You can then:
|
|
94
94
|
|
|
95
|
-
- **Add gems** to `
|
|
96
|
-
- **Override models** with decorators in `
|
|
97
|
-
- **Add controllers** in `
|
|
98
|
-
- **Configure Spree** in `
|
|
95
|
+
- **Add gems** to `server/Gemfile`
|
|
96
|
+
- **Override models** with decorators in `server/app/models/`
|
|
97
|
+
- **Add controllers** in `server/app/controllers/`
|
|
98
|
+
- **Configure Spree** in `server/config/initializers/spree.rb`
|
|
99
99
|
- **Add migrations** with `spree generate migration AddFooToSpreeBars foo:string` (runs inside the container)
|
|
100
100
|
|
|
101
101
|
See the [Customization Guide](../customization.md) for more details.
|
|
@@ -109,7 +109,7 @@ The project includes [@spree/cli](../cli/quickstart.md) for managing your Spree
|
|
|
109
109
|
| `spree dev` | Run the app in the foreground — streams logs, Ctrl+C stops it. First run completes setup automatically; co-runs the React Dashboard dev server when `apps/dashboard` exists |
|
|
110
110
|
| `spree stop` | Stop backend services |
|
|
111
111
|
| `spree update` | Pull latest Spree image and restart (runs migrations automatically) |
|
|
112
|
-
| `spree eject` | Switch from prebuilt image to building from `
|
|
112
|
+
| `spree eject` | Switch from prebuilt image to building from `server/` |
|
|
113
113
|
| `spree add dashboard` | Add the React Dashboard to an existing project |
|
|
114
114
|
| `spree build --production` | Build the production image — the Spree API plus your dashboard, in one |
|
|
115
115
|
| `spree logs` | View backend logs |
|
|
@@ -162,7 +162,7 @@ SPREE_VERSION_TAG=5.4
|
|
|
162
162
|
|
|
163
163
|
## Deployment
|
|
164
164
|
|
|
165
|
-
The project deploys as **one image**: `
|
|
165
|
+
The project deploys as **one image**: `server/Dockerfile` builds the Spree API together with your React Dashboard (when `apps/dashboard` exists), served same-origin at `/dashboard` — no CORS, no cookie configuration, no second service.
|
|
166
166
|
|
|
167
167
|
- **Render** — the `render.yaml` at the project root is a ready Blueprint: one Docker service built straight from your repo, migrations run on boot.
|
|
168
168
|
- **Anywhere else** — `spree build --production` builds the same image locally; push it to a registry and run it on any Docker host.
|
|
@@ -22,13 +22,13 @@ The official image contains the *stock* dashboard. Once you've customized yours
|
|
|
22
22
|
spree build --production # optionally --tag registry/repo:tag
|
|
23
23
|
```
|
|
24
24
|
|
|
25
|
-
The Dockerfile normalizes its own build context: built from the project root it detects the layout (`
|
|
25
|
+
The Dockerfile normalizes its own build context: built from the project root it detects the layout (`server/` = the Rails app, `apps/dashboard/` = your dashboard) and builds *your* dashboard into the image — no flags, no named contexts. Without the CLI, the equivalent is:
|
|
26
26
|
|
|
27
27
|
```bash
|
|
28
|
-
docker build . -f
|
|
28
|
+
docker build . -f server/Dockerfile -t my-shop-spree:latest
|
|
29
29
|
```
|
|
30
30
|
|
|
31
|
-
Inside the dashboard stage the build runs with `VITE_BASE_PATH=/dashboard/` (asset URLs resolve under the mount) and `VITE_SPREE_API_URL` unset (API calls stay origin-relative); the Node toolchain lives only in that throw-away stage. Projects **without** `apps/dashboard/` get the stock dashboard baked instead — and if your `
|
|
31
|
+
Inside the dashboard stage the build runs with `VITE_BASE_PATH=/dashboard/` (asset URLs resolve under the mount) and `VITE_SPREE_API_URL` unset (API calls stay origin-relative); the Node toolchain lives only in that throw-away stage. Projects **without** `apps/dashboard/` get the stock dashboard baked instead — and if your `server/Dockerfile` predates this layout support, the command warns instead of silently shipping the stock dashboard over your customized one (update it from the spree-starter template).
|
|
32
32
|
|
|
33
33
|
## Static host / CDN — the alternative
|
|
34
34
|
|
|
@@ -53,7 +53,7 @@ The Blueprint that `create-spree-app` places at the project root deploys the bac
|
|
|
53
53
|
|
|
54
54
|
```yaml
|
|
55
55
|
runtime: docker
|
|
56
|
-
dockerfilePath: ./
|
|
56
|
+
dockerfilePath: ./server/Dockerfile
|
|
57
57
|
dockerContext: .
|
|
58
58
|
```
|
|
59
59
|
|
|
@@ -28,7 +28,7 @@ Lead time is a column because its whole point is the query: *"show me everything
|
|
|
28
28
|
|
|
29
29
|
## 1. Backend
|
|
30
30
|
|
|
31
|
-
Four small pieces — each one unlocks a specific frontend capability. In a host app these live in `
|
|
31
|
+
Four small pieces — each one unlocks a specific frontend capability. In a host app these live in `server/` (or `api/`); in a distributed plugin, in the Rails engine half.
|
|
32
32
|
|
|
33
33
|
**The column** (with an index — you're adding it *because* it will be queried):
|
|
34
34
|
|
|
@@ -13,7 +13,7 @@ If you haven't ejected yet, do that first:
|
|
|
13
13
|
spree eject
|
|
14
14
|
```
|
|
15
15
|
|
|
16
|
-
This generates the app source — including its production `Dockerfile` — in `
|
|
16
|
+
This generates the app source — including its production `Dockerfile` — in `server/`. Make your customizations, then build:
|
|
17
17
|
|
|
18
18
|
```bash
|
|
19
19
|
spree build --production # → <project>-spree:latest
|
|
@@ -23,7 +23,7 @@ spree build --production --tag registry.example.com/my-store:v42
|
|
|
23
23
|
Or with plain Docker, from the project root:
|
|
24
24
|
|
|
25
25
|
```bash
|
|
26
|
-
docker build . -f
|
|
26
|
+
docker build . -f server/Dockerfile -t my-store
|
|
27
27
|
```
|
|
28
28
|
|
|
29
29
|
Both produce the same image — and it's exactly what Render and Railway build from your repository. Migrations run automatically on boot.
|
|
@@ -21,7 +21,7 @@ Rules determine whether a promotion is eligible for a given order. Each rule imp
|
|
|
21
21
|
|
|
22
22
|
Create a new class inheriting from `Spree::PromotionRule`:
|
|
23
23
|
|
|
24
|
-
```ruby app/models/spree/promotion/rules/minimum_quantity.rb
|
|
24
|
+
```ruby server/app/models/spree/promotion/rules/minimum_quantity.rb
|
|
25
25
|
module Spree
|
|
26
26
|
class Promotion
|
|
27
27
|
module Rules
|
|
@@ -67,7 +67,7 @@ The `options` hash passed to `eligible?` can include `:user`, `:email`, and othe
|
|
|
67
67
|
|
|
68
68
|
Rules use Spree's preference system for configuration. Each preference creates getter/setter methods automatically:
|
|
69
69
|
|
|
70
|
-
```ruby
|
|
70
|
+
```ruby server/app/models/spree/promotion/rules/minimum_quantity.rb
|
|
71
71
|
preference :amount, :decimal, default: 100.00
|
|
72
72
|
preference :operator, :string, default: 'gte'
|
|
73
73
|
preference :category_ids, :array, default: []
|
|
@@ -82,7 +82,7 @@ Available types: `:string`, `:integer`, `:decimal`, `:boolean`, `:array`.
|
|
|
82
82
|
|
|
83
83
|
### Step 2: Register the Rule
|
|
84
84
|
|
|
85
|
-
```ruby config/initializers/spree.rb
|
|
85
|
+
```ruby server/config/initializers/spree.rb
|
|
86
86
|
Rails.application.config.after_initialize do
|
|
87
87
|
Spree.promotions.rules << Spree::Promotion::Rules::MinimumQuantity
|
|
88
88
|
end
|
|
@@ -90,11 +90,31 @@ end
|
|
|
90
90
|
|
|
91
91
|
Registered rules are discoverable at `/api/v3/admin/promotion_rules/types` together with their preference schema, and the dashboard's promotion editor is built on that endpoint — your rule appears there with a generated preferences form, no UI work needed.
|
|
92
92
|
|
|
93
|
+
The API names your rule by its **shorthand** — the class name demodulized and underscored, so `Spree::Promotion::Rules::MinimumQuantity` is `minimum_quantity`. That is what `/types` returns, what a promotion payload sends, and what the locale key below is named after. The Ruby class name is never accepted on the wire:
|
|
94
|
+
|
|
95
|
+
|
|
96
|
+
```typescript Admin SDK
|
|
97
|
+
await adminClient.promotions.rules.create('promo_xxx', {
|
|
98
|
+
type: 'minimum_quantity',
|
|
99
|
+
preferences: { amount: 3 },
|
|
100
|
+
})
|
|
101
|
+
```
|
|
102
|
+
|
|
103
|
+
```bash cURL
|
|
104
|
+
curl -X POST 'https://api.mystore.com/api/v3/admin/promotions/promo_xxx/promotion_rules' \
|
|
105
|
+
-H 'X-Spree-API-Key: sk_xxx' \
|
|
106
|
+
-H 'Content-Type: application/json' \
|
|
107
|
+
-d '{ "type": "minimum_quantity", "preferences": { "amount": 3 } }'
|
|
108
|
+
```
|
|
109
|
+
|
|
110
|
+
|
|
111
|
+
Override `self.api_type` on the class when you need the wire value to stay put across a rename.
|
|
112
|
+
|
|
93
113
|
### Step 3: Add Translations
|
|
94
114
|
|
|
95
115
|
The rule's display name and description in the dashboard come from your locale file:
|
|
96
116
|
|
|
97
|
-
```yaml config/locales/en.yml
|
|
117
|
+
```yaml server/config/locales/en.yml
|
|
98
118
|
en:
|
|
99
119
|
spree:
|
|
100
120
|
promotion_rule_types:
|
|
@@ -107,7 +127,7 @@ en:
|
|
|
107
127
|
|
|
108
128
|
When your rule targets specific line items (not the whole order), implement `actionable?` so that item-level actions only discount matching items:
|
|
109
129
|
|
|
110
|
-
```ruby app/models/spree/promotion/rules/brand.rb
|
|
130
|
+
```ruby server/app/models/spree/promotion/rules/brand.rb
|
|
111
131
|
module Spree
|
|
112
132
|
class Promotion
|
|
113
133
|
module Rules
|
|
@@ -153,7 +173,7 @@ Three declarations make a discount action:
|
|
|
153
173
|
| `compute_amount(adjustable)` | The discount for one adjustable — a line item, fulfillment, or the order, matching your scope. Return a **negative** amount, or zero for "no discount". |
|
|
154
174
|
| `perform(options = {})` | Called when the promotion is activated. For discount actions, delegate to `apply_via_adjuster(options)`. |
|
|
155
175
|
|
|
156
|
-
```ruby app/models/spree/promotion/actions/tiered_discount.rb
|
|
176
|
+
```ruby server/app/models/spree/promotion/actions/tiered_discount.rb
|
|
157
177
|
module Spree
|
|
158
178
|
class Promotion
|
|
159
179
|
module Actions
|
|
@@ -195,7 +215,7 @@ With `discount_scope :order`, the winning amount is shared out proportionally ac
|
|
|
195
215
|
|
|
196
216
|
For actions that don't create discounts (awarding points, sending notifications), implement `perform` alone:
|
|
197
217
|
|
|
198
|
-
```ruby app/models/spree/promotion/actions/add_loyalty_points.rb
|
|
218
|
+
```ruby server/app/models/spree/promotion/actions/add_loyalty_points.rb
|
|
199
219
|
module Spree
|
|
200
220
|
class Promotion
|
|
201
221
|
module Actions
|
|
@@ -219,13 +239,13 @@ end
|
|
|
219
239
|
|
|
220
240
|
### Register and Translate
|
|
221
241
|
|
|
222
|
-
```ruby config/initializers/spree.rb
|
|
242
|
+
```ruby server/config/initializers/spree.rb
|
|
223
243
|
Rails.application.config.after_initialize do
|
|
224
244
|
Spree.promotions.actions << Spree::Promotion::Actions::TieredDiscount
|
|
225
245
|
end
|
|
226
246
|
```
|
|
227
247
|
|
|
228
|
-
```yaml config/locales/en.yml
|
|
248
|
+
```yaml server/config/locales/en.yml
|
|
229
249
|
en:
|
|
230
250
|
spree:
|
|
231
251
|
promotion_action_types:
|
|
@@ -240,7 +260,7 @@ Like rules, registered actions surface automatically in the dashboard's promotio
|
|
|
240
260
|
|
|
241
261
|
Not every charge or reduction is a promotion. A gift wrap fee, a payment surcharge, or loyalty pricing has no rules, no coupon codes, and no competition — it just needs to be on the order whenever it applies. That's an **adjuster**: a class invoked on every recalculation that owns a family of [Fee](../core-concepts/fees.md) or [Discount](../core-concepts/discounts.md) rows.
|
|
242
262
|
|
|
243
|
-
```ruby app/models/my_app/adjusters/gift_wrap.rb
|
|
263
|
+
```ruby server/app/models/my_app/adjusters/gift_wrap.rb
|
|
244
264
|
module MyApp
|
|
245
265
|
module Adjusters
|
|
246
266
|
class GiftWrap < Spree::Adjusters::Base
|
|
@@ -258,7 +278,7 @@ module MyApp
|
|
|
258
278
|
end
|
|
259
279
|
```
|
|
260
280
|
|
|
261
|
-
```ruby config/initializers/spree.rb
|
|
281
|
+
```ruby server/config/initializers/spree.rb
|
|
262
282
|
Rails.application.config.after_initialize do
|
|
263
283
|
Spree.adjusters << MyApp::Adjusters::GiftWrap
|
|
264
284
|
end
|
|
@@ -272,7 +292,7 @@ Custom discounts work the same way, writing `order.discounts` rows with your own
|
|
|
272
292
|
|
|
273
293
|
## Testing
|
|
274
294
|
|
|
275
|
-
```ruby spec/models/spree/promotion/rules/minimum_quantity_spec.rb
|
|
295
|
+
```ruby server/spec/models/spree/promotion/rules/minimum_quantity_spec.rb
|
|
276
296
|
require 'spec_helper'
|
|
277
297
|
|
|
278
298
|
RSpec.describe Spree::Promotion::Rules::MinimumQuantity do
|
|
@@ -300,7 +320,7 @@ RSpec.describe Spree::Promotion::Rules::MinimumQuantity do
|
|
|
300
320
|
end
|
|
301
321
|
```
|
|
302
322
|
|
|
303
|
-
```ruby spec/models/spree/promotion/actions/tiered_discount_spec.rb
|
|
323
|
+
```ruby server/spec/models/spree/promotion/actions/tiered_discount_spec.rb
|
|
304
324
|
require 'spec_helper'
|
|
305
325
|
|
|
306
326
|
RSpec.describe Spree::Promotion::Actions::TieredDiscount do
|
|
@@ -44,7 +44,7 @@ spree eject
|
|
|
44
44
|
|
|
45
45
|
### Adding gems
|
|
46
46
|
|
|
47
|
-
1. Add the following code to your `
|
|
47
|
+
1. Add the following code to your `server/Gemfile`:
|
|
48
48
|
|
|
49
49
|
```ruby
|
|
50
50
|
source "https://license:#{ENV['KEYGEN_LICENSE_KEY']}@rubygems.pkg.keygen.sh/#{ENV['KEYGEN_ACCOUNT_ID']}" do
|
|
@@ -66,10 +66,10 @@ spree eject
|
|
|
66
66
|
> In that case the Gemfile reads `KEYGEN_LICENSE_KEY` / `KEYGEN_ACCOUNT_ID` directly from
|
|
67
67
|
> your shell environment.
|
|
68
68
|
|
|
69
|
-
Wrap **every** `bundle install` in your `
|
|
69
|
+
Wrap **every** `bundle install` in your `server/Dockerfile` with the secret mounts. There
|
|
70
70
|
are usually two — one in the build stage and one in the dev stage:
|
|
71
71
|
|
|
72
|
-
```dockerfile
|
|
72
|
+
```dockerfile server/Dockerfile
|
|
73
73
|
COPY .ruby-version Gemfile Gemfile.lock ./
|
|
74
74
|
RUN bundle install # [!code --]
|
|
75
75
|
RUN --mount=type=secret,id=keygen_license_key,env=KEYGEN_LICENSE_KEY,required=false \ # [!code ++]
|
|
@@ -185,7 +185,7 @@ development by default, but `.lvh.me` (and your production domain) are not — r
|
|
|
185
185
|
`app.lvh.me` are rejected with a "Blocked hosts" error until you allow them. Add your root
|
|
186
186
|
domain to `config/environments/development.rb`:
|
|
187
187
|
|
|
188
|
-
```ruby
|
|
188
|
+
```ruby server/config/environments/development.rb
|
|
189
189
|
if (root_domain = ENV['SPREE_ROOT_DOMAIN']).present?
|
|
190
190
|
config.hosts << ".#{root_domain}"
|
|
191
191
|
end
|
|
@@ -200,7 +200,7 @@ to your customer user model automatically. You then need to **remove the `:valid
|
|
|
200
200
|
manually. `:validatable` validates the user's email uniqueness globally; the concern re-validates
|
|
201
201
|
it in the scope of the tenant instead, so the same email can exist across different tenants.
|
|
202
202
|
|
|
203
|
-
```ruby
|
|
203
|
+
```ruby server/app/models/spree/user.rb
|
|
204
204
|
class Spree::User < Spree.base_class
|
|
205
205
|
include Spree::UserAddress
|
|
206
206
|
include Spree::UserMethods
|
|
@@ -222,7 +222,7 @@ The generator also changes your admin user model's base class from `Spree.base_c
|
|
|
222
222
|
`Spree::Base`. If your `admin_user.rb` exists, this is applied automatically; otherwise make the
|
|
223
223
|
change yourself:
|
|
224
224
|
|
|
225
|
-
```ruby
|
|
225
|
+
```ruby server/app/models/spree/admin_user.rb
|
|
226
226
|
class Spree::AdminUser < Spree.base_class # [!code --]
|
|
227
227
|
class Spree::AdminUser < Spree::Base # [!code ++]
|
|
228
228
|
include Spree::AdminUserMethods
|
|
@@ -61,7 +61,7 @@ npm run test:e2e
|
|
|
61
61
|
|
|
62
62
|
### A `create-spree-app` project's backend
|
|
63
63
|
|
|
64
|
-
A project scaffolded with [`create-spree-app`](../../create-spree-app/quickstart.md) has its customizable Spree in `
|
|
64
|
+
A project scaffolded with [`create-spree-app`](../../create-spree-app/quickstart.md) has its customizable Spree in `server/` (built from `server/Dockerfile`) and this storefront in `apps/storefront/`. Build that backend into a local image and point the suite at it — this is what tests the storefront against the **exact Spree you deploy**, extensions and all:
|
|
65
65
|
|
|
66
66
|
```bash
|
|
67
67
|
# From the project root — build the customized backend image
|
|
@@ -74,7 +74,7 @@ npm run test:e2e
|
|
|
74
74
|
npm run e2e:down
|
|
75
75
|
```
|
|
76
76
|
|
|
77
|
-
> **NOTE:** New `create-spree-app` projects wire this into the generated storefront CI workflow automatically — the workflow builds `
|
|
77
|
+
> **NOTE:** New `create-spree-app` projects wire this into the generated storefront CI workflow automatically — the workflow builds `server/Dockerfile` and runs the storefront E2E against that image rather than stock Spree.
|
|
78
78
|
|
|
79
79
|
### Interactive / manual
|
|
80
80
|
|