@spree/docs 0.1.80 → 0.1.82
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-api/errors.md +3 -3
- package/dist/api-reference/store-api/idempotency.md +1 -1
- package/dist/developer/cli/quickstart.md +149 -1
- package/dist/developer/contributing/creating-an-extension.md +1 -1
- package/dist/developer/contributing/developing-spree.md +167 -76
- package/dist/developer/core-concepts/addresses.md +10 -10
- package/dist/developer/core-concepts/adjustments.md +1 -1
- package/dist/developer/core-concepts/customers.md +1 -1
- package/dist/developer/core-concepts/events.md +12 -6
- package/dist/developer/core-concepts/markets.md +10 -10
- package/dist/developer/core-concepts/media.md +2 -2
- package/dist/developer/core-concepts/orders.md +10 -10
- package/dist/developer/core-concepts/pricing.md +2 -2
- package/dist/developer/core-concepts/products.md +12 -12
- package/dist/developer/core-concepts/promotions.md +1 -1
- package/dist/developer/core-concepts/search-filtering.md +11 -11
- package/dist/developer/core-concepts/shipments.md +2 -2
- package/dist/developer/core-concepts/slugs.md +4 -4
- package/dist/developer/core-concepts/stores.md +1 -1
- package/dist/developer/core-concepts/translations.md +1 -1
- package/dist/developer/core-concepts/users.md +1 -1
- package/dist/developer/create-spree-app/quickstart.md +8 -7
- package/dist/developer/customization/checkout.md +1 -1
- package/dist/developer/customization/decorators.md +10 -8
- package/dist/developer/customization/quickstart.md +1 -1
- package/dist/developer/deployment/environment_variables.md +1 -1
- package/dist/developer/how-to/custom-order-routing.md +18 -3
- package/dist/developer/sdk/store/markets.md +5 -5
- package/dist/developer/tutorial/extending-models.md +1 -1
- package/dist/developer/upgrades/5.4-to-5.5.md +84 -17
- package/package.json +1 -1
|
@@ -145,7 +145,7 @@ Validation errors include an additional `details` field with per-field error mes
|
|
|
145
145
|
|
|
146
146
|
```bash
|
|
147
147
|
curl https://api.mystore.com/api/v3/store/products/prod_nonexistent \
|
|
148
|
-
-H "
|
|
148
|
+
-H "X-Spree-API-Key: pk_xxx"
|
|
149
149
|
```
|
|
150
150
|
|
|
151
151
|
```json 404
|
|
@@ -185,7 +185,7 @@ curl -X POST https://api.mystore.com/api/v3/store/account/addresses \
|
|
|
185
185
|
|
|
186
186
|
```bash
|
|
187
187
|
curl -X POST https://api.mystore.com/api/v3/store/carts/cart_xxx/items \
|
|
188
|
-
-H "
|
|
188
|
+
-H "X-Spree-API-Key: pk_xxx" \
|
|
189
189
|
-H "X-Spree-Token: abc123" \
|
|
190
190
|
-H "Content-Type: application/json" \
|
|
191
191
|
-d '{"variant_id": "var_xxx", "quantity": 999}'
|
|
@@ -204,7 +204,7 @@ curl -X POST https://api.mystore.com/api/v3/store/carts/cart_xxx/items \
|
|
|
204
204
|
|
|
205
205
|
```bash
|
|
206
206
|
curl -X POST https://api.mystore.com/api/v3/store/carts/cart_xxx/complete \
|
|
207
|
-
-H "
|
|
207
|
+
-H "X-Spree-API-Key: pk_xxx"
|
|
208
208
|
```
|
|
209
209
|
|
|
210
210
|
```json 422
|
|
@@ -16,7 +16,7 @@ Include an `Idempotency-Key` header with a unique value (e.g., a UUID) on any su
|
|
|
16
16
|
|
|
17
17
|
```bash
|
|
18
18
|
curl -X POST https://api.mystore.com/api/v3/store/carts/cart_xxx/items \
|
|
19
|
-
-H "
|
|
19
|
+
-H "X-Spree-API-Key: pk_xxx" \
|
|
20
20
|
-H "X-Spree-Token: abc123" \
|
|
21
21
|
-H "Idempotency-Key: 550e8400-e29b-41d4-a716-446655440000" \
|
|
22
22
|
-H "Content-Type: application/json" \
|
|
@@ -40,7 +40,7 @@ spree init --no-open # Skip opening browser
|
|
|
40
40
|
|
|
41
41
|
### `spree dev`
|
|
42
42
|
|
|
43
|
-
|
|
43
|
+
Run the app in the foreground — streams web + worker logs; `Ctrl+C` stops them. The databases keep running for a fast next boot (`spree stop` shuts everything down).
|
|
44
44
|
|
|
45
45
|
```bash
|
|
46
46
|
spree dev
|
|
@@ -54,6 +54,16 @@ Stop all services.
|
|
|
54
54
|
spree stop
|
|
55
55
|
```
|
|
56
56
|
|
|
57
|
+
### `spree restart`
|
|
58
|
+
|
|
59
|
+
Restart `web` and `worker` in place — same image, same volumes, fresh Rails process. Good for `config/initializers/*.rb` changes or anything Zeitwerk doesn't auto-reload.
|
|
60
|
+
|
|
61
|
+
```bash
|
|
62
|
+
spree restart
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
Not appropriate for Gemfile changes (use `spree bundle install`, then Ctrl+C and re-run `spree dev`), Dockerfile / `.ruby-version` changes (use `spree build`), or compose file changes (Ctrl+C and re-run `spree dev`).
|
|
66
|
+
|
|
57
67
|
### `spree update`
|
|
58
68
|
|
|
59
69
|
Pull the latest Spree Docker image and recreate containers. Migrations run automatically on startup.
|
|
@@ -62,6 +72,34 @@ Pull the latest Spree Docker image and recreate containers. Migrations run autom
|
|
|
62
72
|
spree update
|
|
63
73
|
```
|
|
64
74
|
|
|
75
|
+
### `spree build`
|
|
76
|
+
|
|
77
|
+
Rebuild the dev image after Dockerfile or `.ruby-version` changes. Only relevant after `spree eject`.
|
|
78
|
+
|
|
79
|
+
```bash
|
|
80
|
+
spree build
|
|
81
|
+
spree build --reset-bundle # Also drop the bundle_cache volume so gems re-seed
|
|
82
|
+
spree build --yes # Skip confirmation prompts (for CI)
|
|
83
|
+
```
|
|
84
|
+
|
|
85
|
+
`spree bundle add` does NOT require a rebuild — gems land in the `bundle_cache` volume which survives image rebuilds.
|
|
86
|
+
|
|
87
|
+
`--reset-bundle` only drops `bundle_cache`. Postgres, Redis, Meilisearch, and storage volumes are preserved.
|
|
88
|
+
|
|
89
|
+
### `spree upgrade`
|
|
90
|
+
|
|
91
|
+
Walk a Spree version upgrade end-to-end inside the dev stack. Runs `bundle update`, applies pending migrations, then walks the version-specific data backfills from the upgrade manifest.
|
|
92
|
+
|
|
93
|
+
```bash
|
|
94
|
+
spree upgrade # Detect target, run the full sequence interactively
|
|
95
|
+
spree upgrade --plan # Print the plan without executing (DRY_RUN=1)
|
|
96
|
+
spree upgrade --to 5.5 # Cap the walk at a specific target version
|
|
97
|
+
spree upgrade --step <id> # Re-run a single step idempotently (skips bundle + migrate)
|
|
98
|
+
spree upgrade --yes # Skip the per-step prompts
|
|
99
|
+
```
|
|
100
|
+
|
|
101
|
+
Production upgrades only need the third stage — `bundle install` and `db:migrate` happen in your deploy pipeline. The CLI runs all three for local development. See [Upgrades](../upgrades.md) for the manual production path.
|
|
102
|
+
|
|
65
103
|
### `spree eject`
|
|
66
104
|
|
|
67
105
|
Switch from the prebuilt Docker image to building from your local `backend/` directory. This lets you customize the Rails app — add gems, override models, add migrations, etc.
|
|
@@ -135,3 +173,113 @@ spree api-key create --name "Storefront" --type publishable # Store API key
|
|
|
135
173
|
spree api-key create --name "Admin" --type secret # Admin API key
|
|
136
174
|
spree api-key revoke <id> # Revoke a key
|
|
137
175
|
```
|
|
176
|
+
|
|
177
|
+
## Dev workflow commands
|
|
178
|
+
|
|
179
|
+
These mirror the Rails commands you'd run if you were running the app directly on your host — but each is routed through `docker compose exec` against the running stack.
|
|
180
|
+
|
|
181
|
+
### `spree generate`
|
|
182
|
+
|
|
183
|
+
Run a generator inside the container. Bare generator names are auto-prefixed with `spree:` — `model` runs `spree:model`, `api_resource` runs `spree:api_resource` — so you get the Spree conventions (`Spree::` namespace, `spree_`-prefixed table, prefixed IDs, `null: false`, no FK constraints) by default. Rails built-ins (`migration`, `scaffold`, `mailer`, `job`, …) and any name containing `:` are forwarded as-is.
|
|
184
|
+
|
|
185
|
+
```bash
|
|
186
|
+
spree generate model Brand name:string slug:string:uniq # runs spree:model
|
|
187
|
+
spree generate api_resource Brand name:string slug:string:uniq # runs spree:api_resource — model + v3 Store/Admin API
|
|
188
|
+
spree generate migration AddPositionToSpreeBrands position:integer # Rails built-in, forwarded as-is
|
|
189
|
+
```
|
|
190
|
+
|
|
191
|
+
`spree:api_resource` scaffolds the full v3 surface: model, migration, Store + Admin controllers and serializers, factory, controller specs, and routes.
|
|
192
|
+
|
|
193
|
+
### `spree migrate`
|
|
194
|
+
|
|
195
|
+
Install pending Spree migrations from gems, then run `db:migrate` — the canonical post-update sequence.
|
|
196
|
+
|
|
197
|
+
```bash
|
|
198
|
+
spree migrate
|
|
199
|
+
spree migrate:status # show the migration log (`db:migrate:status`)
|
|
200
|
+
spree migrate:rollback STEP=2 # roll back (`db:rollback`)
|
|
201
|
+
```
|
|
202
|
+
|
|
203
|
+
### `spree db:reset`
|
|
204
|
+
|
|
205
|
+
Drop, recreate, migrate, and seed the database. **Destructive** — wipes everything. Asks for confirmation.
|
|
206
|
+
|
|
207
|
+
```bash
|
|
208
|
+
spree db:reset
|
|
209
|
+
spree db:reset --yes # Skip confirmation (for CI)
|
|
210
|
+
```
|
|
211
|
+
|
|
212
|
+
### `spree db:console`
|
|
213
|
+
|
|
214
|
+
Open a `psql` session against the dev Postgres database (runs inside the `postgres` container).
|
|
215
|
+
|
|
216
|
+
```bash
|
|
217
|
+
spree db:console
|
|
218
|
+
```
|
|
219
|
+
|
|
220
|
+
### `spree routes`
|
|
221
|
+
|
|
222
|
+
Show Rails routes. All flags pass through to `bin/rails routes`.
|
|
223
|
+
|
|
224
|
+
```bash
|
|
225
|
+
spree routes
|
|
226
|
+
spree routes -g products # Filter by pattern
|
|
227
|
+
spree routes -c Spree::Api::V3::Store::ProductsController # Filter by controller
|
|
228
|
+
spree routes --expanded
|
|
229
|
+
```
|
|
230
|
+
|
|
231
|
+
## Running things inside the container
|
|
232
|
+
|
|
233
|
+
These are passthrough commands — anything after the subcommand reaches the inner Rails/Bundle/Rake invocation as-is. Useful for ad-hoc commands that don't have a dedicated wrapper.
|
|
234
|
+
|
|
235
|
+
### `spree exec`
|
|
236
|
+
|
|
237
|
+
Run an arbitrary command inside the `web` container.
|
|
238
|
+
|
|
239
|
+
```bash
|
|
240
|
+
spree exec ls -la
|
|
241
|
+
spree exec env
|
|
242
|
+
spree exec ruby -v
|
|
243
|
+
```
|
|
244
|
+
|
|
245
|
+
### `spree rails`
|
|
246
|
+
|
|
247
|
+
Run a `bin/rails` command.
|
|
248
|
+
|
|
249
|
+
```bash
|
|
250
|
+
spree rails c # Console (alias of `spree console`)
|
|
251
|
+
spree rails routes -g products # Alias of `spree routes -g products`
|
|
252
|
+
spree rails runner "puts Spree::Product.count"
|
|
253
|
+
spree rails new_subcommand arg1 arg2
|
|
254
|
+
```
|
|
255
|
+
|
|
256
|
+
### `spree bundle`
|
|
257
|
+
|
|
258
|
+
Run a `bundle` command. Gems land in the `bundle_cache` volume (no image rebuild needed).
|
|
259
|
+
|
|
260
|
+
```bash
|
|
261
|
+
spree bundle install
|
|
262
|
+
spree bundle add stripe
|
|
263
|
+
spree bundle update spree_core
|
|
264
|
+
spree bundle outdated
|
|
265
|
+
```
|
|
266
|
+
|
|
267
|
+
### `spree rake`
|
|
268
|
+
|
|
269
|
+
Run a Rake task.
|
|
270
|
+
|
|
271
|
+
```bash
|
|
272
|
+
spree rake -T # List tasks
|
|
273
|
+
spree rake spree:upgrade # Run the version-specific data backfills
|
|
274
|
+
spree rake spree:upgrade DRY_RUN=1 # Same, plan only
|
|
275
|
+
```
|
|
276
|
+
|
|
277
|
+
### `spree task`
|
|
278
|
+
|
|
279
|
+
Shortcut for `bin/rails <task>` (Spree-style rake tasks registered as Rails tasks).
|
|
280
|
+
|
|
281
|
+
```bash
|
|
282
|
+
spree task load_sample_data
|
|
283
|
+
spree task spree:price_history:seed
|
|
284
|
+
spree task spree:price_history:prune
|
|
285
|
+
```
|
|
@@ -248,7 +248,7 @@ module MyExtension
|
|
|
248
248
|
subscribes_to 'product.updated'
|
|
249
249
|
|
|
250
250
|
def handle(event)
|
|
251
|
-
product = Spree::Product.
|
|
251
|
+
product = Spree::Product.find_by_prefix_id(event.payload['id'])
|
|
252
252
|
return unless product
|
|
253
253
|
|
|
254
254
|
ExternalService.sync(product)
|
|
@@ -5,6 +5,8 @@ description: >-
|
|
|
5
5
|
code. We're happy you're here!
|
|
6
6
|
---
|
|
7
7
|
|
|
8
|
+
Please read our [Code of Conduct](https://github.com/spree/spree/blob/main/CODE_OF_CONDUCT.md) before contributing.
|
|
9
|
+
|
|
8
10
|
## Cloning the repository
|
|
9
11
|
|
|
10
12
|
Spree is a big monorepo. For a faster clone, use a **partial clone** which downloads file contents on demand while keeping full commit history for `git log` and `git blame`:
|
|
@@ -24,66 +26,98 @@ You need **Node.js 20+** to run the workspace scripts (including `pnpm server:se
|
|
|
24
26
|
Spree is a monorepo with three main areas:
|
|
25
27
|
|
|
26
28
|
- **`spree/`** — Ruby gems (core, api, admin, emails) distributed as separate packages via RubyGems
|
|
27
|
-
- **`packages/`** — TypeScript packages (SDKs, CLI, project scaffolding, docs)
|
|
28
|
-
- **`server/`** — A Rails application cloned from [spree-starter](https://github.com/spree/spree-starter) that mounts the Spree gems (not checked in —
|
|
29
|
+
- **`packages/`** — TypeScript packages (SDKs, CLI, project scaffolding, docs, React dashboard)
|
|
30
|
+
- **`server/`** — A Rails application cloned from [spree-starter](https://github.com/spree/spree-starter) that mounts the local Spree gems (not checked in — `pnpm server:setup` creates it)
|
|
29
31
|
|
|
30
|
-
##
|
|
32
|
+
## Setup
|
|
31
33
|
|
|
32
|
-
|
|
34
|
+
A single command bootstraps the whole monorepo for both backend and frontend work. You need **Docker** running locally (Docker Desktop, OrbStack, or any compatible runtime) — no Ruby, Postgres, or Redis on your host.
|
|
33
35
|
|
|
34
|
-
|
|
36
|
+
```bash
|
|
37
|
+
pnpm install # workspace dependencies
|
|
38
|
+
pnpm server:setup # ~5–10 min on first run; idempotent
|
|
39
|
+
```
|
|
35
40
|
|
|
36
|
-
|
|
37
|
-
|---|---|---|
|
|
38
|
-
| `core` | `spree_core` | Models, services, business logic |
|
|
39
|
-
| `api` | `spree_api` | REST APIs |
|
|
40
|
-
| `admin` | `spree_admin` | Admin dashboard |
|
|
41
|
-
| `emails` | `spree_emails` | Transactional emails |
|
|
41
|
+
`pnpm server:setup` clones [spree-starter](https://github.com/spree/spree-starter) into `./server/`, wires it to load Spree gems from the monorepo via a Docker compose overlay, builds the dev image, starts the stack (Postgres + Redis + Meilisearch + Rails `web` + Sidekiq `worker`), and prepares the database. The full sequence lives in `scripts/server-setup.sh`.
|
|
42
42
|
|
|
43
|
-
|
|
43
|
+
When it's done, the backend is up at [http://localhost:3000](http://localhost:3000) and the admin is at [http://localhost:3000/admin](http://localhost:3000/admin). Sign in with the seed admin: **`spree@example.com`** / **`spree123`** (override at seed time with `ADMIN_EMAIL` / `ADMIN_PASSWORD` env vars — see `spree/core/app/services/spree/seeds/admin_user.rb`).
|
|
44
44
|
|
|
45
|
-
|
|
45
|
+
Optionally load sample products, taxonomies, and option types:
|
|
46
46
|
|
|
47
|
-
|
|
47
|
+
```bash
|
|
48
|
+
pnpm server:load_sample_data
|
|
49
|
+
```
|
|
48
50
|
|
|
49
|
-
|
|
51
|
+
## Running a backend day-to-day
|
|
50
52
|
|
|
51
|
-
|
|
53
|
+
After the one-time setup, use these to bring the stack up and down:
|
|
52
54
|
|
|
53
55
|
```bash
|
|
54
|
-
pnpm server:
|
|
56
|
+
pnpm server:dev # run the stack in the foreground — streams web + worker logs, Ctrl+C stops them
|
|
57
|
+
pnpm server:stop # full teardown (also stops postgres / redis / meilisearch)
|
|
58
|
+
pnpm server:restart # restart web + worker in place
|
|
59
|
+
pnpm server:logs # follow web container logs (when the stack runs detached)
|
|
60
|
+
pnpm server:console # open a Rails console inside the container
|
|
61
|
+
pnpm server:seed # re-run database seeds
|
|
62
|
+
pnpm server:build # rebuild the dev image (only after Dockerfile / .ruby-version changes)
|
|
55
63
|
```
|
|
56
64
|
|
|
57
|
-
|
|
65
|
+
`server:dev` behaves like any TS dev server (`vite dev`, the dashboard's `pnpm dev`): it runs in the foreground and Ctrl+C stops the app containers. Postgres, Redis, and Meilisearch keep running for a fast next boot — `pnpm server:stop` shuts everything down.
|
|
58
66
|
|
|
59
|
-
|
|
67
|
+
Run any CLI command against the running backend from `server/`:
|
|
60
68
|
|
|
61
69
|
```bash
|
|
62
70
|
cd server
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
71
|
+
pnpm exec spree migrate
|
|
72
|
+
pnpm exec spree generate model Brand name:string
|
|
73
|
+
pnpm exec spree upgrade --plan
|
|
66
74
|
```
|
|
67
75
|
|
|
68
|
-
|
|
76
|
+
See the [`@spree/cli` README](https://github.com/spree/spree/blob/main/packages/cli/README.md) for the full command surface.
|
|
69
77
|
|
|
70
|
-
|
|
71
|
-
docker compose up -d postgres redis meilisearch
|
|
72
|
-
```
|
|
78
|
+
Which command after which change:
|
|
73
79
|
|
|
74
|
-
|
|
80
|
+
| What changed | What to run |
|
|
81
|
+
|---|---|
|
|
82
|
+
| Ruby code in `spree/*` gems | Nothing — gems are bind-mounted; code reloads on the next request |
|
|
83
|
+
| A new migration in a gem | `cd server && pnpm exec spree migrate` |
|
|
84
|
+
| Gem dependencies (gemspec / Gemfile) | `cd server && pnpm exec spree bundle install` (persists in the `bundle_cache` volume) |
|
|
85
|
+
| Compose files / `server/.env` | `pnpm server:dev` (force-recreates the containers) |
|
|
86
|
+
| `server/Dockerfile` / `.ruby-version` | `pnpm server:build`, then `pnpm server:dev` |
|
|
87
|
+
| Broken beyond repair | `pnpm server:setup` (full reset — wipes the database and volumes) |
|
|
75
88
|
|
|
76
|
-
|
|
89
|
+
Re-run `pnpm server:setup` **only** to fully reset — it does `docker compose down -v` + `rm -rf ./server`, wiping all DB data.
|
|
77
90
|
|
|
78
|
-
|
|
91
|
+
## Native Ruby (advanced)
|
|
79
92
|
|
|
80
|
-
|
|
93
|
+
If you prefer the fastest possible inner loop and don't mind installing Ruby, Postgres, Redis, and Meilisearch on your host directly, you can skip Docker:
|
|
81
94
|
|
|
82
95
|
```bash
|
|
83
|
-
pnpm server:
|
|
84
|
-
|
|
96
|
+
pnpm server:create # clones spree-starter, writes server/.env with SPREE_PATH=..
|
|
97
|
+
cd server
|
|
98
|
+
bin/setup # installs Ruby (via mise), Postgres/Redis/Meilisearch (via brew bundle on macOS), gems, prepares the database
|
|
99
|
+
bin/dev # starts Rails + Sidekiq + CSS watchers via Foreman
|
|
85
100
|
```
|
|
86
101
|
|
|
102
|
+
This path is faster per request but means more on your host. It also runs against your installed system services, not a sandboxed Docker stack.
|
|
103
|
+
|
|
104
|
+
## Backend Development (Ruby)
|
|
105
|
+
|
|
106
|
+
### Engines overview
|
|
107
|
+
|
|
108
|
+
The Spree [Rails engines](https://guides.rubyonrails.org/engines.html) live inside `spree/` and are distributed as separate gems (Ruby packages installed via Bundler):
|
|
109
|
+
|
|
110
|
+
| Engine | Gem | Description |
|
|
111
|
+
|---|---|---|
|
|
112
|
+
| `core` | `spree_core` | Models, services, business logic |
|
|
113
|
+
| `api` | `spree_api` | REST APIs |
|
|
114
|
+
| `admin` | `spree_admin` | Admin dashboard |
|
|
115
|
+
| `emails` | `spree_emails` | Transactional emails |
|
|
116
|
+
|
|
117
|
+
### Spree namespace
|
|
118
|
+
|
|
119
|
+
All Spree models, controllers and other Ruby classes are namespaced by the `Spree` keyword, eg. `Spree::Product`. This means that those files are also located in `spree` sub-directories eg. [app/models/spree/product.rb](https://github.com/spree/spree/blob/main/spree/core/app/models/spree/product.rb).
|
|
120
|
+
|
|
87
121
|
### Running engine tests
|
|
88
122
|
|
|
89
123
|
Each engine has its own test suite. First install the shared dependencies at the `spree/` level, then navigate into the specific engine to set up and run its tests:
|
|
@@ -148,9 +182,9 @@ bundle exec parallel_rspec -n 4 spec
|
|
|
148
182
|
|
|
149
183
|
After schema changes, re-run `bundle exec rake parallel_setup` to update the worker databases.
|
|
150
184
|
|
|
151
|
-
### Integration tests (
|
|
185
|
+
### Integration tests (legacy Rails admin)
|
|
152
186
|
|
|
153
|
-
The
|
|
187
|
+
The legacy Rails admin (`spree/admin`) ships feature specs that run in a real browser via chromedriver. You only need this if you're touching the legacy admin UI.
|
|
154
188
|
|
|
155
189
|
Install chromedriver on macOS:
|
|
156
190
|
|
|
@@ -158,47 +192,35 @@ Install chromedriver on macOS:
|
|
|
158
192
|
brew install chromedriver
|
|
159
193
|
```
|
|
160
194
|
|
|
161
|
-
|
|
195
|
+
The 6.0 React dashboard (`packages/dashboard`) has its own end-to-end test suite running on Playwright against a real Rails backend — see [Dashboard E2E tests](#dashboard-e2e-tests) under TypeScript Development.
|
|
162
196
|
|
|
163
|
-
|
|
197
|
+
### Performance in development mode
|
|
164
198
|
|
|
165
|
-
|
|
199
|
+
Spree runs slower in development because caching is disabled and code reloads on each request. To turn on caching:
|
|
166
200
|
|
|
167
201
|
```bash
|
|
168
|
-
cd server &&
|
|
202
|
+
cd server && pnpm exec spree rails dev:cache
|
|
169
203
|
```
|
|
170
204
|
|
|
171
|
-
|
|
205
|
+
Restart the Rails server after running this (Ctrl+C the running `pnpm server:dev` and start it again).
|
|
172
206
|
|
|
173
207
|
## TypeScript Development
|
|
174
208
|
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
TypeScript developers don't need Ruby installed. Docker Compose from the repository root starts the backend using a prebuilt image:
|
|
178
|
-
|
|
179
|
-
```bash
|
|
180
|
-
docker compose up -d
|
|
181
|
-
```
|
|
182
|
-
|
|
183
|
-
This boots PostgreSQL, Redis, Meilisearch, and the Spree backend automatically (no `pnpm server:setup` needed). The API is available at `http://localhost:3000`.
|
|
184
|
-
|
|
185
|
-
Then install dependencies and start all packages in watch mode:
|
|
186
|
-
|
|
187
|
-
```bash
|
|
188
|
-
pnpm install
|
|
189
|
-
pnpm dev
|
|
190
|
-
```
|
|
209
|
+
The backend setup is the same as for Ruby work — see [Setup](#setup) above. With `pnpm server:setup` done, the Rails backend is running and you can start the packages you want to work on.
|
|
191
210
|
|
|
192
211
|
### Packages
|
|
193
212
|
|
|
194
|
-
| Package | Path | Description |
|
|
195
|
-
|
|
196
|
-
| `@spree/sdk` | `packages/sdk` | TypeScript SDK for the Spree Store API |
|
|
197
|
-
| `@spree/
|
|
198
|
-
|
|
|
199
|
-
|
|
|
200
|
-
|
|
201
|
-
|
|
213
|
+
| Package | Path | Published | Description |
|
|
214
|
+
|---|---|---|---|
|
|
215
|
+
| `@spree/sdk` | `packages/sdk` | yes | TypeScript SDK for the Spree Store API |
|
|
216
|
+
| `@spree/admin-sdk` | `packages/admin-sdk` | yes | TypeScript SDK for the Spree Admin API |
|
|
217
|
+
| `@spree/cli` | `packages/cli` | yes | CLI for managing Spree Commerce projects |
|
|
218
|
+
| `create-spree-app` | `packages/create-spree-app` | yes | Project scaffolding (`npm create spree-app`) |
|
|
219
|
+
| `@spree/docs` | `packages/docs` | yes | Developer documentation for AI agents and local reference |
|
|
220
|
+
| `@spree/dashboard` | `packages/dashboard` | no | React SPA admin dashboard (Spree 6.0, replaces the legacy Rails admin) |
|
|
221
|
+
| `@spree/dashboard-core` | `packages/dashboard-core` | no | Framework: registries, providers, generic infra hooks for the dashboard |
|
|
222
|
+
| `@spree/dashboard-ui` | `packages/dashboard-ui` | no | Design system used by the dashboard |
|
|
223
|
+
| `@spree/sdk-core` | `packages/sdk-core` | no | Shared HTTP/retry/error layer used by both SDKs |
|
|
202
224
|
|
|
203
225
|
### Common commands
|
|
204
226
|
|
|
@@ -206,7 +228,7 @@ Run from the repository root — [Turborepo](https://turbo.build/) orchestrates
|
|
|
206
228
|
|
|
207
229
|
| Command | Description |
|
|
208
230
|
|---|---|
|
|
209
|
-
| `pnpm dev` |
|
|
231
|
+
| `pnpm dev` | Watch mode for all packages (does not boot the backend — use `pnpm server:dev` for that) |
|
|
210
232
|
| `pnpm build` | Build all packages (Turbo resolves dependency order) |
|
|
211
233
|
| `pnpm test` | Run tests in all packages |
|
|
212
234
|
| `pnpm lint` | Lint all packages |
|
|
@@ -225,21 +247,86 @@ pnpm --filter @spree/sdk generate:zod
|
|
|
225
247
|
|
|
226
248
|
Tests use [Vitest](https://vitest.dev/) with [MSW](https://mswjs.io/) for API mocking at the network level.
|
|
227
249
|
|
|
228
|
-
###
|
|
250
|
+
### Working on the React dashboard
|
|
251
|
+
|
|
252
|
+
The dashboard runs as a Vite dev server (port 5173) that proxies `/api/*` to the Rails backend on port 3000 — required for the auth refresh cookie to work over plain HTTP.
|
|
253
|
+
|
|
254
|
+
```bash
|
|
255
|
+
# Terminal 1: backend
|
|
256
|
+
pnpm server:dev
|
|
257
|
+
|
|
258
|
+
# Terminal 2: dashboard
|
|
259
|
+
cd packages/dashboard
|
|
260
|
+
pnpm dev # http://localhost:5173
|
|
261
|
+
```
|
|
262
|
+
|
|
263
|
+
Sign in with `spree@example.com` / `spree123`. To point at a non-default backend, set `VITE_SPREE_API_URL` (also needs to be set at build time for production bundles, not just dev):
|
|
264
|
+
|
|
265
|
+
```bash
|
|
266
|
+
VITE_SPREE_API_URL=https://my-spree.example.com pnpm dev
|
|
267
|
+
```
|
|
268
|
+
|
|
269
|
+
**Gotcha:** the dashboard imports `@spree/admin-sdk` from its **built** `dist/`, not source. If you edit `admin-sdk` (or `sdk-core`, or `sdk`) and want the dashboard to see the changes, run `pnpm build` from the monorepo root first (Turbo-cached). Editing dashboard code alone doesn't need this.
|
|
270
|
+
|
|
271
|
+
See the [dashboard README](https://github.com/spree/spree/blob/main/packages/dashboard/README.md) for the full architecture (auth, permissions, extension points, the three-package split between `dashboard`, `dashboard-core`, and `dashboard-ui`).
|
|
272
|
+
|
|
273
|
+
### Dashboard E2E tests
|
|
274
|
+
|
|
275
|
+
The React dashboard ships an end-to-end suite running on [Playwright](https://playwright.dev/) against a real Rails backend — no mocks. The spec files exercise the full UI: login, staff invitation, invitee signup. CI runs the same suite via the `dashboard-e2e` job in `.github/workflows/packages.yml`.
|
|
229
276
|
|
|
230
|
-
|
|
277
|
+
To run locally you need Ruby (the suite boots a real Rails server) and a one-time browser install:
|
|
231
278
|
|
|
232
279
|
```bash
|
|
280
|
+
# Make sure the dummy Rails app exists (one-time, after a fresh checkout).
|
|
233
281
|
cd spree/api
|
|
234
|
-
|
|
235
|
-
bundle
|
|
236
|
-
|
|
282
|
+
bundle install
|
|
283
|
+
bundle exec rake test_app
|
|
284
|
+
|
|
285
|
+
# Install Playwright's Chromium (one-time per machine).
|
|
286
|
+
cd ../../packages/dashboard
|
|
287
|
+
pnpm test:e2e:install
|
|
288
|
+
|
|
289
|
+
# Run the suite. Boots Rails on :3010 + Vite on :5174, runs all specs, tears
|
|
290
|
+
# both down. Safe to re-run repeatedly — the SQLite DB resets each run.
|
|
291
|
+
pnpm test:e2e
|
|
237
292
|
```
|
|
238
293
|
|
|
239
|
-
|
|
294
|
+
For interactive debugging (time-travel through actions, inspect the DOM at each step):
|
|
240
295
|
|
|
241
296
|
```bash
|
|
242
|
-
pnpm
|
|
297
|
+
pnpm test:e2e:ui
|
|
298
|
+
```
|
|
299
|
+
|
|
300
|
+
Filter to a single spec or test name:
|
|
301
|
+
|
|
302
|
+
```bash
|
|
303
|
+
pnpm test:e2e e2e/auth.spec.ts
|
|
304
|
+
pnpm test:e2e -g "invites a teammate"
|
|
305
|
+
```
|
|
306
|
+
|
|
307
|
+
When a test fails, Playwright drops a screenshot, video, and DOM snapshot in `packages/dashboard/test-results/<spec>/` — usually enough to diagnose without re-running.
|
|
308
|
+
|
|
309
|
+
### Type generation
|
|
310
|
+
|
|
311
|
+
TypeScript types in `packages/sdk/src/types/generated/` (Store API) and `packages/admin-sdk/src/types/generated/` (Admin API) are auto-generated from the Rails serializers using [typelizer](https://github.com/skryukov/typelizer). Zod schemas in `packages/sdk/src/zod/generated/` are derived from the TS types.
|
|
312
|
+
|
|
313
|
+
A **Lefthook pre-commit hook** regenerates both whenever you commit a change to `spree/api/app/serializers/**/*.rb` and re-stages the generated output. You don't need to run anything manually for the common case.
|
|
314
|
+
|
|
315
|
+
To regenerate manually (useful when iterating on serializers before committing):
|
|
316
|
+
|
|
317
|
+
```bash
|
|
318
|
+
cd server
|
|
319
|
+
pnpm exec spree rake typelizer:generate # regenerate TS types
|
|
320
|
+
cd ../packages/sdk
|
|
321
|
+
pnpm generate:zod # regenerate Zod schemas
|
|
322
|
+
```
|
|
323
|
+
|
|
324
|
+
If you'd rather avoid the Docker round-trip and have Ruby on your host, the native equivalent works too:
|
|
325
|
+
|
|
326
|
+
```bash
|
|
327
|
+
cd spree/api
|
|
328
|
+
bundle install
|
|
329
|
+
bundle exec rake typelizer:generate
|
|
243
330
|
```
|
|
244
331
|
|
|
245
332
|
### Releasing packages
|
|
@@ -247,29 +334,33 @@ pnpm --filter @spree/sdk generate:zod
|
|
|
247
334
|
Published packages use [Changesets](https://github.com/changesets/changesets) for version management. Each package owns its own `.changeset/` folder, so changesets must be created from inside the package directory:
|
|
248
335
|
|
|
249
336
|
```bash
|
|
250
|
-
cd packages/sdk # or packages/cli, packages/create-spree-app
|
|
337
|
+
cd packages/sdk # or packages/admin-sdk, packages/cli, packages/create-spree-app
|
|
251
338
|
pnpm changeset
|
|
252
339
|
```
|
|
253
340
|
|
|
254
341
|
This creates a changeset file describing your changes. Commit it with your PR. When merged to `main`, a GitHub Action creates a "Version Packages" PR that bumps the version and publishes to npm.
|
|
255
342
|
|
|
343
|
+
Private packages (`@spree/dashboard`, `@spree/dashboard-core`, `@spree/dashboard-ui`, `@spree/sdk-core`) don't need changesets.
|
|
344
|
+
|
|
256
345
|
## Code Style
|
|
257
346
|
|
|
258
347
|
Consistent code style is enforced via automated linters. Please make sure your changes pass linting before submitting a PR.
|
|
259
348
|
|
|
260
|
-
**Ruby:** We use [RuboCop](https://rubocop.org/) for Ruby code. The configuration lives in `server/.rubocop.yml` and is shipped with [spree-starter](https://github.com/spree/spree-starter), so it's only available after running `pnpm server:setup`. Run it
|
|
349
|
+
**Ruby:** We use [RuboCop](https://rubocop.org/) for Ruby code. The configuration lives in `server/.rubocop.yml` and is shipped with [spree-starter](https://github.com/spree/spree-starter), so it's only available after running `pnpm server:setup`. Run it inside the container via the CLI:
|
|
261
350
|
|
|
262
351
|
```bash
|
|
263
352
|
cd server
|
|
264
|
-
bundle exec rubocop
|
|
353
|
+
pnpm exec spree exec bundle exec rubocop
|
|
265
354
|
```
|
|
266
355
|
|
|
267
356
|
To auto-fix correctable offenses:
|
|
268
357
|
|
|
269
358
|
```bash
|
|
270
|
-
bundle exec rubocop -a
|
|
359
|
+
pnpm exec spree exec bundle exec rubocop -a
|
|
271
360
|
```
|
|
272
361
|
|
|
362
|
+
(On the native path, drop the `pnpm exec spree exec` prefix and run `bundle exec rubocop` directly.)
|
|
363
|
+
|
|
273
364
|
**TypeScript:** We use [Biome](https://biomejs.dev/) for linting and formatting TypeScript code. Run it from the repository root:
|
|
274
365
|
|
|
275
366
|
```bash
|
|
@@ -319,7 +410,7 @@ To help us review your PR quickly:
|
|
|
319
410
|
- **Describe your changes.** Explain what you changed and why. Include screenshots for UI changes.
|
|
320
411
|
- **Add tests.** All new features and bug fixes should include appropriate test coverage.
|
|
321
412
|
- **Update documentation.** If your change affects user-facing behavior, update the relevant docs.
|
|
322
|
-
- **Include a changeset** if your change affects a published TypeScript package (`@spree/sdk`, `@spree/cli`, or `create-spree-app`). Run `pnpm changeset` from inside that package's directory — each package owns its own `.changeset/` folder.
|
|
413
|
+
- **Include a changeset** if your change affects a published TypeScript package (`@spree/sdk`, `@spree/admin-sdk`, `@spree/cli`, or `create-spree-app`). Run `pnpm changeset` from inside that package's directory — each package owns its own `.changeset/` folder.
|
|
323
414
|
- **Ensure CI passes.** PRs with failing CI will not be reviewed.
|
|
324
415
|
|
|
325
416
|
## Reporting Bugs
|
|
@@ -129,14 +129,14 @@ await client.carts.update(cartId, {
|
|
|
129
129
|
```bash cURL
|
|
130
130
|
# Use a saved address
|
|
131
131
|
curl -X PATCH 'https://api.mystore.com/api/v3/store/carts/cart_xxx' \
|
|
132
|
-
-H '
|
|
132
|
+
-H 'X-Spree-API-Key: pk_xxx' \
|
|
133
133
|
-H 'X-Spree-Token: order_token' \
|
|
134
134
|
-H 'Content-Type: application/json' \
|
|
135
135
|
-d '{ "shipping_address_id": "addr_xxx", "billing_address_id": "addr_yyy" }'
|
|
136
136
|
|
|
137
137
|
# Or pass a new address inline
|
|
138
138
|
curl -X PATCH 'https://api.mystore.com/api/v3/store/carts/cart_xxx' \
|
|
139
|
-
-H '
|
|
139
|
+
-H 'X-Spree-API-Key: pk_xxx' \
|
|
140
140
|
-H 'X-Spree-Token: order_token' \
|
|
141
141
|
-H 'Content-Type: application/json' \
|
|
142
142
|
-d '{
|
|
@@ -189,15 +189,15 @@ const germany = await client.countries.get('DE', { include: 'market' })
|
|
|
189
189
|
```bash cURL
|
|
190
190
|
# List all countries
|
|
191
191
|
curl 'https://api.mystore.com/api/v3/store/countries' \
|
|
192
|
-
-H '
|
|
192
|
+
-H 'X-Spree-API-Key: pk_xxx'
|
|
193
193
|
|
|
194
194
|
# Get a country with states
|
|
195
|
-
curl 'https://api.mystore.com/api/v3/store/countries/US?
|
|
196
|
-
-H '
|
|
195
|
+
curl 'https://api.mystore.com/api/v3/store/countries/US?expand=states' \
|
|
196
|
+
-H 'X-Spree-API-Key: pk_xxx'
|
|
197
197
|
|
|
198
198
|
# Get a country with its market
|
|
199
|
-
curl 'https://api.mystore.com/api/v3/store/countries/DE?
|
|
200
|
-
-H '
|
|
199
|
+
curl 'https://api.mystore.com/api/v3/store/countries/DE?expand=market' \
|
|
200
|
+
-H 'X-Spree-API-Key: pk_xxx'
|
|
201
201
|
```
|
|
202
202
|
|
|
203
203
|
|
|
@@ -207,7 +207,7 @@ Use the `states_required` and `zipcode_required` fields to build adaptive addres
|
|
|
207
207
|
|
|
208
208
|
States (provinces, regions) belong to a country and are used for address validation and zone matching. Countries like the US, Canada, Australia, and India have predefined states — for these countries, customers must select a state from the list rather than typing a name.
|
|
209
209
|
|
|
210
|
-
States are fetched via the country endpoint using `?
|
|
210
|
+
States are fetched via the country endpoint using `?expand=states`:
|
|
211
211
|
|
|
212
212
|
|
|
213
213
|
```typescript SDK
|
|
@@ -220,8 +220,8 @@ usa.states.forEach(state => {
|
|
|
220
220
|
```
|
|
221
221
|
|
|
222
222
|
```bash cURL
|
|
223
|
-
curl 'https://api.mystore.com/api/v3/store/countries/US?
|
|
224
|
-
-H '
|
|
223
|
+
curl 'https://api.mystore.com/api/v3/store/countries/US?expand=states' \
|
|
224
|
+
-H 'X-Spree-API-Key: pk_xxx'
|
|
225
225
|
```
|
|
226
226
|
|
|
227
227
|
|