@spree/docs 0.1.247 → 0.1.249

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (76) hide show
  1. package/dist/api-reference/admin-api/authentication.md +34 -14
  2. package/dist/api-reference/admin-api/endpoints.md +366 -14
  3. package/dist/api-reference/admin-api/errors.md +2 -2
  4. package/dist/api-reference/admin-api/introduction.md +3 -3
  5. package/dist/api-reference/admin-api/querying.md +6 -6
  6. package/dist/api-reference/store-api/monetary-amounts.md +5 -5
  7. package/dist/api-reference/webhooks-events.md +330 -335
  8. package/dist/developer/agentic/agent-skills.md +5 -2
  9. package/dist/developer/agentic/llm-docs.md +2 -1
  10. package/dist/developer/cli/admin-api.md +1 -1
  11. package/dist/developer/cli/quickstart.md +2 -2
  12. package/dist/developer/contributing/creating-an-extension.md +292 -146
  13. package/dist/developer/contributing/developing-spree.md +13 -17
  14. package/dist/developer/core-concepts/catalogs.md +2 -2
  15. package/dist/developer/core-concepts/channels.md +3 -3
  16. package/dist/developer/core-concepts/companies.md +2 -1
  17. package/dist/developer/core-concepts/delivery-setup.md +2 -2
  18. package/dist/developer/core-concepts/discounts.md +3 -3
  19. package/dist/developer/core-concepts/events.md +6 -5
  20. package/dist/developer/core-concepts/freight.md +3 -2
  21. package/dist/developer/core-concepts/fulfillments.md +10 -8
  22. package/dist/developer/core-concepts/imports-exports.md +11 -8
  23. package/dist/developer/core-concepts/inventory.md +2 -2
  24. package/dist/developer/core-concepts/media.md +14 -14
  25. package/dist/developer/core-concepts/orders.md +2 -2
  26. package/dist/developer/core-concepts/payments.md +1 -2
  27. package/dist/developer/core-concepts/products.md +6 -6
  28. package/dist/developer/core-concepts/reporting.md +4 -3
  29. package/dist/developer/core-concepts/returns-exchanges-claims.md +7 -7
  30. package/dist/developer/core-concepts/search-filtering.md +3 -3
  31. package/dist/developer/core-concepts/sellers.md +22 -3
  32. package/dist/developer/core-concepts/staff-roles.md +4 -2
  33. package/dist/developer/core-concepts/store-credits-gift-cards.md +1 -1
  34. package/dist/developer/core-concepts/stores.md +2 -2
  35. package/dist/developer/core-concepts/translations.md +12 -8
  36. package/dist/developer/core-concepts/webhooks.md +19 -18
  37. package/dist/developer/create-spree-app/quickstart.md +2 -7
  38. package/dist/developer/customization/api.md +1 -1
  39. package/dist/developer/customization/checkout.md +2 -2
  40. package/dist/developer/customization/dependencies.md +53 -37
  41. package/dist/developer/customization/permissions.md +2 -2
  42. package/dist/developer/dashboard/concepts.md +1 -1
  43. package/dist/developer/dashboard/customization/navigation.md +3 -2
  44. package/dist/developer/dashboard/customization/permissions.md +6 -6
  45. package/dist/developer/dashboard/plugins/publishing.md +4 -4
  46. package/dist/developer/dashboard/plugins/scaffolding.md +1 -1
  47. package/dist/developer/dashboard/public-api.md +1 -1
  48. package/dist/developer/dashboard/recipes/attribute-end-to-end.md +3 -18
  49. package/dist/developer/deployment/aws.md +1 -1
  50. package/dist/developer/deployment/aws_ecs.md +3 -3
  51. package/dist/developer/deployment/background_jobs.md +9 -3
  52. package/dist/developer/deployment/docker.md +1 -2
  53. package/dist/developer/deployment/emails.md +3 -1
  54. package/dist/developer/deployment/environment_variables.md +2 -2
  55. package/dist/developer/deployment/render.md +2 -2
  56. package/dist/developer/how-to/build-a-marketplace.md +2 -2
  57. package/dist/developer/how-to/custom-api-authentication.md +1 -1
  58. package/dist/developer/how-to/custom-delivery-rate-provider.md +11 -3
  59. package/dist/developer/how-to/custom-document-numbers.md +1 -1
  60. package/dist/developer/how-to/custom-order-routing.md +15 -14
  61. package/dist/developer/how-to/custom-payment-method.md +17 -19
  62. package/dist/developer/how-to/custom-promotion.md +4 -4
  63. package/dist/developer/how-to/custom-search-provider.md +12 -5
  64. package/dist/developer/how-to/custom-stock-splitter.md +25 -24
  65. package/dist/developer/how-to/sell-digital-products.md +1 -1
  66. package/dist/developer/multi-tenant/quickstart.md +2 -2
  67. package/dist/developer/providers/payouts.md +6 -2
  68. package/dist/developer/sdk/admin/querying-and-errors.md +1 -1
  69. package/dist/developer/sdk/admin/quickstart.md +4 -4
  70. package/dist/developer/sdk/authentication.md +5 -2
  71. package/dist/developer/sdk/store/cart-checkout.md +4 -4
  72. package/dist/developer/storefront/nextjs/emails.md +4 -2
  73. package/dist/developer/storefront/nextjs/testing.md +1 -1
  74. package/dist/developer/upgrades/5.6-to-6.0.md +51 -20
  75. package/dist/integrations/search/meilisearch.md +4 -4
  76. package/package.json +1 -1
@@ -33,7 +33,7 @@ await adminClient.products.update('prod_86Rf07xd4z', {
33
33
  curl -X PATCH 'https://api.mystore.com/api/v3/admin/products/prod_86Rf07xd4z' \
34
34
  -H 'X-Spree-API-Key: sk_xxx' \
35
35
  -H 'Content-Type: application/json' \
36
- -d '{ "delivery_profile_id": "dp_digital" }'
36
+ -d '{ "delivery_profile_id": "fp_digital" }'
37
37
  ```
38
38
 
39
39
 
@@ -25,7 +25,7 @@ All data is fully isolated besides the staff users, which can manage multiple te
25
25
  ## Prerequisites
26
26
 
27
27
  * You need to be on Spree 5.1+, we recommend using [CLI](../getting-started.md) to setup your Spree application.
28
- * You need to set 2 environment variables in your `backend` directory:
28
+ * You need to set 2 environment variables in your `server` directory:
29
29
  * `KEYGEN_ACCOUNT_ID`
30
30
  * `KEYGEN_LICENSE_KEY`
31
31
  * Both PostgreSQL and MySQL are supported
@@ -84,7 +84,7 @@ spree eject
84
84
  ```yaml docker-compose.yml
85
85
  x-app: &app
86
86
  build:
87
- context: ./backend
87
+ context: ./server
88
88
  dockerfile: Dockerfile
89
89
  target: dev
90
90
  secrets: # [!code ++]
@@ -130,10 +130,14 @@ end
130
130
  ### Register it
131
131
 
132
132
  ```ruby server/config/initializers/spree.rb
133
- Spree.integrations << 'MyApp::AcmeIntegration'
134
- Spree.payout_providers << MyApp::PayoutProvider
133
+ Rails.application.config.after_initialize do
134
+ Spree.integrations << 'MyApp::AcmeIntegration'
135
+ Spree.payout_providers << MyApp::PayoutProvider
136
+ end
135
137
  ```
136
138
 
139
+ Register inside `after_initialize`: Spree sets up its own integrations list after your initializers run, so an entry added at the top level of the file would be dropped.
140
+
137
141
  The operator then picks it under **Settings → Marketplace**, which is the store's `payout_provider` preference. The picker is built from the registry, so your provider appears alongside the built-in one and reports whether the store can use it today:
138
142
 
139
143
 
@@ -10,7 +10,7 @@ Collection endpoints support [Ransack](https://activerecord-hackery.github.io/ra
10
10
 
11
11
  ```typescript
12
12
  const { data: orders } = await client.orders.list({
13
- status_eq: 'complete', // exact match
13
+ status_eq: 'placed', // exact match
14
14
  total_gteq: 100, // greater than or equal
15
15
  email_cont: '@example.com', // substring match
16
16
  customer_id_eq: 'cus_xxx', // prefixed IDs work directly
@@ -6,12 +6,12 @@ description: "Install and configure @spree/admin-sdk, the official TypeScript cl
6
6
 
7
7
  [`@spree/admin-sdk`](https://www.npmjs.com/package/@spree/admin-sdk) is the official TypeScript SDK for the [Admin API v3](../../../api-reference/admin-api/introduction.md) — the back-office counterpart to [`@spree/sdk`](../quickstart.md). Use it to build integrations, automations, internal tools, and custom admin UIs: manage products, orders, customers, stock, promotions, webhooks, and more.
8
8
 
9
- > **WARNING:** The Admin SDK is in **Developer Preview** on the `0.x` line and published under the `next` dist-tag. The API surface may change between minor versions — check the [changelog](https://github.com/spree/spree/blob/main/packages/admin-sdk/CHANGELOG.md) when updating. It requires Spree 5.5 or newer.
9
+ > **NOTE:** `@spree/admin-sdk` 1.x works with the Spree 6.0 Admin API. Check the [changelog](https://github.com/spree/spree/blob/main/packages/admin-sdk/CHANGELOG.md) when updating.
10
10
 
11
11
  ## Installation
12
12
 
13
13
  ```bash
14
- npm install @spree/admin-sdk@next
14
+ npm install @spree/admin-sdk
15
15
  ```
16
16
 
17
17
  ## Quick start
@@ -26,9 +26,9 @@ const client = createAdminClient({
26
26
  secretKey: process.env.SPREE_SECRET_KEY, // sk_xxx — server-side only
27
27
  })
28
28
 
29
- // List recent completed orders
29
+ // List recently placed orders
30
30
  const { data: orders, meta } = await client.orders.list({
31
- status_eq: 'complete',
31
+ status_eq: 'placed',
32
32
  sort: '-completed_at',
33
33
  limit: 25,
34
34
  })
@@ -41,8 +41,11 @@ const orders = await client.customer.orders.list({}, { token })
41
41
 
42
42
 
43
43
  ```typescript
44
- // Refresh token when needed
45
- const newTokens = await client.auth.refresh({ token })
44
+ // Exchange the refresh_token returned by login for a new access token.
45
+ // The refresh token rotates, so store the new one as well.
46
+ const { token: newToken, refresh_token: newRefreshToken } = await client.auth.refresh({
47
+ refresh_token: refreshToken,
48
+ })
46
49
  ```
47
50
 
48
51
  ## Register New Customer
@@ -28,7 +28,7 @@ const carts = await client.carts.list();
28
28
  await client.carts.delete(cartId, { spreeToken: cart.token });
29
29
 
30
30
  // Associate guest cart with authenticated user
31
- // (after user logs in, merge their guest cart with their account)
31
+ // (after user logs in, assign the guest cart to their account — carts are not merged)
32
32
  await client.carts.associate(cartId, {
33
33
  token: jwtToken, // User's JWT token
34
34
  spreeToken: cart.token, // Guest cart token
@@ -112,8 +112,8 @@ await client.carts.update(cartId, {
112
112
  city: 'New York',
113
113
  postal_code: '10001',
114
114
  phone: '+1 555 123 4567',
115
- country_iso: 'US',
116
- state_abbr: 'NY',
115
+ country_code: 'US',
116
+ state_code: 'NY',
117
117
  },
118
118
  billing_address_id: 'addr_xxx', // Or use existing address by ID
119
119
  }, { spreeToken: cart.token });
@@ -177,7 +177,7 @@ The cart and order responses break the amount the customer pays into these total
177
177
  ### Get a Completed Order
178
178
 
179
179
  ```typescript
180
- const order = await client.orders.get('R123456789', {
180
+ const order = await client.orders.get('or_xxx', { // prefixed order ID (or the cart ID)
181
181
  expand: ['items', 'fulfillments'],
182
182
  }, { spreeToken: cart.token });
183
183
  ```
@@ -23,6 +23,8 @@ Email templates are React components in `src/lib/emails/`:
23
23
 
24
24
  Customize a template by editing its file directly — they use `@react-email/components` for email-safe layout primitives.
25
25
 
26
+ > **NOTE:** The storefront listens for `order.completed` and `order.shipped`, the names these events had before Spree 6.0. Spree 6.0 still sends them alongside the new names, `order.placed` and `order.fulfilled`, but stops in Spree 6.1. Before upgrading to 6.1, switch the storefront handlers and your webhook endpoint subscriptions to the new names.
27
+
26
28
  ## Previewing
27
29
 
28
30
  Run the storefront in development and open [http://localhost:3001/dev/emails](http://localhost:3001/dev/emails):
@@ -68,11 +70,11 @@ To add a new email type:
68
70
  1. Create a template in `src/lib/emails/`.
69
71
  2. Add a handler function in `src/lib/webhooks/handlers.ts`.
70
72
  3. Register the event in `route.ts`.
71
- 4. Subscribe to the event in **Spree Admin → Settings → Developers → Webhooks**.
73
+ 4. Subscribe to the event in **Spree Admin → Settings → Developer → Webhooks**.
72
74
 
73
75
  ## Setup
74
76
 
75
- 1. **Create a webhook endpoint** in Spree Admin → Settings → Developers → Webhooks. Subscribe to `order.completed`, `order.canceled`, `order.shipped`, and `customer.password_reset_requested`, and copy the secret key into `SPREE_WEBHOOK_SECRET`.
77
+ 1. **Create a webhook endpoint** in Spree Admin → Settings → Developer → Webhooks. Subscribe to `order.completed`, `order.canceled`, `order.shipped`, and `customer.password_reset_requested`, and copy the secret key into `SPREE_WEBHOOK_SECRET`.
76
78
 
77
79
  2. **Receive webhooks locally.** Expose the storefront with a public URL so Spree can reach it — the simplest option is a [Cloudflare Tunnel](https://developers.cloudflare.com/cloudflare-one/connections/connect-networks/):
78
80
 
@@ -65,7 +65,7 @@ A project scaffolded with [`create-spree-app`](../../create-spree-app/quickstart
65
65
 
66
66
  ```bash
67
67
  # From the project root — build the customized backend image
68
- docker build -t project-spree:e2e ./backend
68
+ docker build -t project-spree:e2e ./server
69
69
 
70
70
  # From apps/storefront — run E2E against it
71
71
  cd apps/storefront
@@ -36,7 +36,14 @@ bundle exec rake spree:upgrade
36
36
  ```
37
37
 
38
38
 
39
- Skipping versions and re-running are both safe — `bundle exec rake spree:upgrade` figures out what still needs to happen and does nothing on data that's already migrated.
39
+ Before running `bundle update`, update your `Gemfile`: the Rails admin (`spree_admin`) and Rails storefront (`spree_storefront`) are not part of Spree 6.0. Remove both and add `spree_dashboard`, which serves the new React admin dashboard at `/dashboard`.
40
+
41
+ ```ruby
42
+ # Gemfile
43
+ gem 'spree_dashboard'
44
+ ```
45
+
46
+ Re-running is safe — `bundle exec rake spree:upgrade` figures out what still needs to happen and does nothing on data that's already migrated. It also runs every data backfill from earlier upgrades (5.4 → 5.5 and 5.5 → 5.6), so any you missed along the way are caught up. That does not remove the requirement above: upgrade your application to 5.6 first.
40
47
 
41
48
  ## What the upgrade does
42
49
 
@@ -56,7 +63,7 @@ Every order that never completed and was never canceled becomes a `Spree::Cart`
56
63
  bundle exec rake spree:migrate_adjustments_to_typed_rows
57
64
  ```
58
65
 
59
- Rebuilds `spree_adjustments` into `Spree::TaxLine`, `Spree::Discount` and `Spree::Fee` rows. Orders whose typed sums do not reconcile with the stored totals are left untouched and flagged (`private_metadata['typed_adjustments_frozen']`) for manual review instead of silently changing money.
66
+ Rebuilds `spree_adjustments` into `Spree::TaxLine`, `Spree::Discount` and `Spree::Fee` rows. Orders whose typed sums do not reconcile with the stored totals are left untouched and flagged (`metadata['typed_adjustments_frozen']`) for manual review instead of silently changing money.
60
67
 
61
68
  ### Backfill fulfillment and delivery naming
62
69
 
@@ -94,14 +101,14 @@ Category and collection descriptions, policy bodies, and order and customer inte
94
101
 
95
102
  Run this **after** two earlier steps, both load-bearing: the categories step re-points the rows from `Spree::Taxon` to `Spree::Category` so this one can still find them, and the customers step populates `spree_customers` — a note is copied onto the customer row it belongs to, so running before those rows exist would treat every legacy customer note as orphaned and skip it for good. Following the manifest order handles this for you.
96
103
 
97
- Content is sanitized on the way in, and **the 6.0 allowlist is much narrower than 5.6's**: it permits only what the dashboard's editor emits — paragraphs, headings, `strong`/`em`/`s`/`u`/`code`, `pre`, `blockquote`, lists, `hr`, `br` and links. Tables, images, `div`/`span`, inline `style` and arbitrary `class` attributes are no longer permitted. Text inside a stripped tag survives; its formatting does not. The exceptions are `script` and `style`, which are removed along with their contents — a script body would otherwise reappear as visible text.
104
+ Content is sanitized on the way in, and **the 6.0 allowlist is much narrower than 5.6's**: it permits only what the dashboard's editor emits — paragraphs, headings, `strong`/`em`/`s`/`u`/`code`, `pre`, `blockquote`, lists, `hr`, `br`, links and images. Tables, `div`/`span`, inline `style` and arbitrary `class` attributes are no longer permitted. Text inside a stripped tag survives; its formatting does not. The exceptions are `script` and `style`, which are removed along with their contents — a script body would otherwise reappear as visible text.
98
105
 
99
106
  If your descriptions rely on richer markup, permit it in an initializer **before** running the task and before saving anything under 6.0:
100
107
 
101
108
  ```ruby
102
109
  # config/initializers/spree.rb
103
- Spree::RichTextSanitizer.allowed_tags += %w[table thead tbody tr th td img]
104
- Spree::RichTextSanitizer.allowed_attributes += %w[src alt colspan rowspan]
110
+ Spree::RichTextSanitizer.allowed_tags += %w[table thead tbody tr th td]
111
+ Spree::RichTextSanitizer.allowed_attributes += %w[colspan rowspan]
105
112
  ```
106
113
 
107
114
  The Action Text rows are left in place as a rollback path and are dropped with the tables in 6.1.
@@ -153,6 +160,24 @@ Rows written before the upgrade carry an id and an empty type; this task fills
153
160
  the type in. Until it runs they still read as the staff member they always
154
161
  were, with a deprecation warning. Safe to re-run at any time.
155
162
 
163
+ ### Move users onto the Customer and AdminUser models
164
+
165
+ ```bash
166
+ bundle exec rake spree:upgrade:migrate_users_to_customers
167
+ ```
168
+
169
+ Copies your legacy Devise customer table (default `spree_users`) into `spree_customers`, keeping the same ids, and carries existing passwords over so customers and staff can keep signing in. The source table is left in place as a safety net.
170
+
171
+ > **WARNING:** Passwords carry over only if your application **never configured a Devise pepper**. The task stops if it finds one. Because Devise is no longer loaded in 6.0, the task usually cannot check for itself — it stops until you confirm no pepper was used by re-running it with `CONFIRM_NO_PEPPER=true`. If you did use a pepper, single sign-on, or a non-bcrypt password format, skip this step and keep your own customer model by setting `Spree.customer_class`.
172
+
173
+ ### Name countries and states by ISO code
174
+
175
+ ```bash
176
+ bundle exec rake spree:upgrade:migrate_country_state_codes
177
+ ```
178
+
179
+ Countries and states are no longer database records in 6.0. Addresses, delivery zone members, market countries, stock locations and stores now name them by ISO code (`country_code`, `state_code`), and this task fills those columns from the old `country_id` / `state_id` references. The old `country_iso` / `state_abbr` names still work on addresses for one release.
180
+
156
181
  ## The Cart/Order split
157
182
 
158
183
  The single biggest change. What used to be one `Spree::Order` living through checkout and beyond is now two models:
@@ -180,17 +205,17 @@ The replacement model:
180
205
 
181
206
  ```ruby
182
207
  # config/initializers/spree.rb
183
- Rails.application.config.to_prepare do
184
- Spree::Checkout::Registry.add_requirement(
185
- step: :payment,
186
- field: :po_number,
187
- message: 'PO number is required',
188
- satisfied: ->(cart) { cart.metadata['po_number'].present? },
189
- applicable: ->(cart) { cart.customer.present? }
190
- )
191
- end
208
+ Spree::Checkout::Registry.add_requirement(
209
+ step: :payment,
210
+ field: :po_number,
211
+ message: 'PO number is required',
212
+ satisfied: ->(cart) { cart.metadata['po_number'].present? },
213
+ applicable: ->(cart) { cart.customer.present? }
214
+ )
192
215
  ```
193
216
 
217
+ Register at the top level of the initializer, not inside `to_prepare`: the registry is never reset, so a `to_prepare` block would add the requirement again on every code reload in development.
218
+
194
219
  The requirement appears in the Cart API's `requirements` array (so a storefront rendering the feed generically needs zero changes) *and* blocks completion. `register_step` adds whole steps (spliced into `checkout_steps` at `before:`/`after:` anchors); built-in steps are customized through `Registry.base_steps` — an ordered `{ name => applicability }` hash you can mutate directly (`base_steps.delete('confirm')`).
195
220
  - **The API `requirements` array now carries a stable `code`** on every entry (`email_required`, `out_of_stock`, `guest_checkout_not_allowed`, ...). Additive change — existing consumers keep working.
196
221
  - **The delivery requirement is keyed `delivery_method`, not `shipping_method`.** Its entry is now `{ step: 'delivery', field: 'delivery_method', code: 'delivery_method_required' }`. A storefront that renders the feed generically needs no change; one that keys off the field or code to highlight a specific input must switch both tokens. The `Spree.t('checkout_requirements.shipping_method_required')` translation key was renamed to `checkout_requirements.delivery_method_required` — override it under the new key.
@@ -211,7 +236,7 @@ Behavior to review:
211
236
 
212
237
  Transition-triggered recalculation is gone with the machine. Instead:
213
238
 
214
- - **`Spree::Carts::RecalculateTotals`** is the single totals seam: money inputs, typed-row regeneration (promotions via the winner-only adjuster, tax via `Spree.tax_provider`), folding and one persist. It runs on the writes that matter — item changes, address/market changes (which also re-price items and rebuild delivery proposals) — not on step transitions.
239
+ - **`Spree::Carts::RecalculateTotals`** is the single totals seam: money inputs, typed-row regeneration (promotions via the winner-only adjuster, tax via the market's tax provider, falling back to `Spree.default_tax_provider`), folding and one persist. It runs on the writes that matter — item changes, address/market changes (which also re-price items and rebuild delivery proposals) — not on step transitions.
215
240
  - Promotion eligibility is evaluated against **current** totals in the same recalculation — a cart crossing a coupon threshold gets the discount on that recalculation, not the next one.
216
241
  - **Completed orders are money-frozen.** Typed rows are never regenerated post-placement; recalculation only re-sums them. Post-placement money edits go through the explicit admin services (`Orders::Discounts::*`, `Orders::Fees::*`), which write rows and re-sum.
217
242
  - `Spree::OrderUpdater` and `Spree::CartUpdater` remain as deprecated shells — every method warns and runs the full recalculation. Removed in 6.1.
@@ -287,10 +312,15 @@ Core ships exactly one policy rule — a return window read from `market.preferr
287
312
  Replace it by swapping the handler:
288
313
 
289
314
  ```ruby
290
- Spree.hooks.unregister('returns.create.validate', 'Spree::Returns::EligibilityValidator')
291
- Spree.hooks.register('returns.create.validate', 'MyStore::ReturnPolicy')
315
+ # config/initializers/spree.rb
316
+ Rails.application.config.after_initialize do
317
+ Spree.hooks.unregister('returns.create.validate', 'Spree::Returns::EligibilityValidator')
318
+ Spree.hooks.register('returns.create.validate', 'MyStore::ReturnPolicy')
319
+ end
292
320
  ```
293
321
 
322
+ Wrap the swap in `after_initialize`: core registers the default validator after your initializers load, so an `unregister` at the top level of an initializer would run too early and do nothing.
323
+
294
324
  A handler receives the workflow (so it can read `order`, `items`, `created_by`, `order.market`) and calls `workflow.reject!(message)` to veto. Every one of the fifteen transitions has a leading `validate` hook, so the same seam gates approving, receiving and refunding.
295
325
 
296
326
  > **WARNING:** `requires_manual_intervention?` has no equivalent. The old validators could mark an item eligible-but-flagged for manual review; a handler now either accepts or vetoes. If you relied on that middle state, model it explicitly — an added status, or a metafield your handler sets.
@@ -319,7 +349,7 @@ A handler receives the workflow (so it can read `order`, `items`, `created_by`,
319
349
  | `carts_complete_service` | `carts_complete_workflow` | `Spree::Carts::Complete` |
320
350
  | `order_cancel_service` | `order_cancel_workflow` | `Spree::Orders::Cancel` |
321
351
  | `order_complete_service` | `order_complete_workflow` | `Spree::Orders::Complete` |
322
- | `shipment_update_service` | `fulfillment_update_service` | `Spree::Fulfillments::Update` |
352
+ | `shipment_update_service`, `fulfillment_update_service` | `fulfillment_update_workflow` | `Spree::Fulfillments::Update` |
323
353
 
324
354
  New seams with no legacy counterpart:
325
355
 
@@ -581,7 +611,7 @@ to `Spree::Base`.
581
611
 
582
612
  `Spree::StateChange` and `Spree::LogEntry` are removed — the models, the `state_changes` associations on `Order`, `Payment` and `Fulfillment`, the `log_entries` associations on `Payment` and `Refund`, and everything that wrote to them. Both were write-only: nothing in Spree read the rows back, and the admin screens that displayed them are gone.
583
613
 
584
- **Events are the audit trail now.** Instead of querying state-change rows, subscribe to the lifecycle events that already fire on every meaningful transition: `order.placed`, `order.canceled`, `payment.completed`, `payment.voided`, `fulfillment.ready`, `fulfillment.fulfilled`, `fulfillment.canceled`, `fulfillment.resumed`, and the rest. If you need a persistent history, write it from a subscriber.
614
+ **Events are the audit trail now.** Instead of querying state-change rows, subscribe to the lifecycle events that already fire on every meaningful transition: `order.placed`, `order.canceled`, `payment.completed`, `payment.voided`, `fulfillment.fulfilled`, `fulfillment.delivered`, `fulfillment.canceled`, and the rest. If you need a persistent history, write it from a subscriber.
585
615
 
586
616
  **Gateway responses are no longer stored in your database.** `LogEntry` kept every gateway response as serialized YAML. For transaction forensics, use your payment provider's dashboard — `Payment#gateway_dashboard_payment_url` links straight to the transaction — or `Spree::PaymentSession`, which holds the gateway-side state for session-based providers.
587
617
 
@@ -620,7 +650,8 @@ Every rename keeps the legacy name working for one release with a deprecation wa
620
650
  | `Spree::PresentationTranslatable` | `Spree::LabelTranslatable` |
621
651
  | `Spree::WishedItem`, `Wishlist#wished_items`, `#wished_items_count` | `Spree::WishlistItem`, `#wishlist_items`, `#wishlist_items_count` (class and table renamed; the `wi_` prefixed IDs are unchanged, so client-held IDs keep resolving) |
622
652
  | `use_billing` / `clone_billing_address` | `use_shipping` (shipping address is canonical) |
623
- | `Fulfillment#ship`, `#ship!`, `#shipped?`, `#can_ship?`, `#shipping_method`, `#add_shipping_method` | `#fulfill`, `#fulfill!`, `#fulfilled?`, `#can_fulfill?`, `#delivery_method`, `#add_delivery_method` |
653
+ | `Fulfillment#ship`, `#ship!` | `Spree.fulfillment_fulfill_workflow.call(fulfillment:)` (`Spree::Fulfillments::Fulfill`) |
654
+ | `Fulfillment#shipped?`, `#can_ship?`, `#shipping_method`, `#add_shipping_method` | `#fulfilled?`, `#can_fulfill?`, `#delivery_method`, `#add_delivery_method` |
624
655
  | `LineItem#target_shipment` | `#target_fulfillment` |
625
656
  | `Order#create_proposed_shipments` / `#create_proposed_fulfillments` | `#rebuild_fulfillments!` (Cart ships with the new name only) |
626
657
  | `Order#remove_out_of_stock_items!` | cart-side only (`Spree::Carts::RemoveOutOfStockItems`) |
@@ -5,7 +5,7 @@ description: "Set up Meilisearch in Spree for fast, typo-tolerant product search
5
5
 
6
6
  ## Overview
7
7
 
8
- [Meilisearch](https://www.meilisearch.com/) is a fast, open-source search engine that provides typo tolerance, relevance ranking, faceted filtering, and sub-50ms search responses. Spree includes a built-in Meilisearch search provider that replaces the default SQL-based search.
8
+ [Meilisearch](https://www.meilisearch.com/) is a fast, open-source search engine that provides typo tolerance, relevance ranking, faceted filtering, and sub-50ms search responses. The official `spree_meilisearch` gem provides a Meilisearch search provider that replaces the default SQL-based search.
9
9
 
10
10
  **When to use Meilisearch:**
11
11
  - Catalogs with 1,000+ products
@@ -48,7 +48,7 @@ docker run -d --name meilisearch \
48
48
  ### 2. Add the gem to your Gemfile
49
49
 
50
50
  ```ruby
51
- gem 'meilisearch', '>= 0.28'
51
+ gem 'spree_meilisearch'
52
52
  ```
53
53
 
54
54
 
@@ -77,7 +77,7 @@ MEILISEARCH_URL=http://localhost:7700
77
77
 
78
78
  ```ruby
79
79
  # config/initializers/spree.rb
80
- Spree.search_provider = 'Spree::SearchProvider::Meilisearch'
80
+ Spree.search_provider = 'SpreeMeilisearch::SearchProvider'
81
81
  ```
82
82
 
83
83
  ### 5. Index your products
@@ -216,7 +216,7 @@ The Meilisearch provider automatically configures these filterable attributes:
216
216
  - `name` — product name (in document locale)
217
217
  - `description` — product description (in document locale)
218
218
  - `sku` — variant SKU
219
- - `option_values` — option value presentations (e.g., "Red", "Small")
219
+ - `option_values` — option value labels (e.g., "Red", "Small")
220
220
  - `category_names` — category names
221
221
  - `tags` — product tags
222
222
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@spree/docs",
3
- "version": "0.1.247",
3
+ "version": "0.1.249",
4
4
  "description": "Spree Commerce developer documentation for AI agents and local reference",
5
5
  "type": "module",
6
6
  "license": "CC-BY-4.0",