@spree/docs 0.1.113 → 0.1.115

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.
@@ -6,7 +6,7 @@ description: "Every Spree Admin API v3 endpoint at a glance — method, path, re
6
6
 
7
7
  {/* Generated from docs/api-reference/admin.yaml by packages/cli/scripts/generate-endpoints-doc.mjs — do not edit by hand. */}
8
8
 
9
- All 192 Admin API operations, with the [scope](authentication.md) a secret API key needs for each. JWT-authenticated admin users are governed by their roles instead of scopes. The same index is available offline via the CLI: `spree api endpoints`.
9
+ All 209 Admin API operations, with the [scope](authentication.md) a secret API key needs for each. JWT-authenticated admin users are governed by their roles instead of scopes. The same index is available offline via the CLI: `spree api endpoints`.
10
10
 
11
11
  Endpoints marked — are exempt from scope checks (authentication and session endpoints) or resolve their scope at request time.
12
12
 
@@ -36,7 +36,9 @@ Endpoints marked — are exempt from scope checks (authentication and session en
36
36
  | `GET` | `/api_keys` | `read_api_keys` | List API keys |
37
37
  | `POST` | `/api_keys` | `write_api_keys` | Create an API key |
38
38
  | `GET` | `/api_keys/{id}` | `read_api_keys` | Show an API key |
39
+ | `PATCH` | `/api_keys/{id}` | `write_api_keys` | Update an API key |
39
40
  | `DELETE` | `/api_keys/{id}` | `write_api_keys` | Delete an API key |
41
+ | `GET` | `/api_keys/current` | *none* | Describe the current API key |
40
42
  | `PATCH` | `/api_keys/{id}/revoke` | `write_api_keys` | Revoke an API key |
41
43
 
42
44
  ## Auth
@@ -47,6 +49,20 @@ Endpoints marked — are exempt from scope checks (authentication and session en
47
49
  | `POST` | `/auth/refresh` | — | Refresh token |
48
50
  | `POST` | `/auth/logout` | — | Logout |
49
51
 
52
+ ## Categories
53
+
54
+ | Method | Path | Required scope | Summary |
55
+ |---|---|---|---|
56
+ | `GET` | `/categories` | `read_categories` | List categories |
57
+ | `POST` | `/categories` | `write_categories` | Create a category |
58
+ | `GET` | `/categories/{id}` | `read_categories` | Get a category |
59
+ | `PATCH` | `/categories/{id}` | `write_categories` | Update a category |
60
+ | `DELETE` | `/categories/{id}` | `write_categories` | Delete a category |
61
+ | `PATCH` | `/categories/{id}/reposition` | `write_categories` | Reposition a category |
62
+ | `GET` | `/categories/{category_id}/products` | `read_categories` | List category products |
63
+ | `POST` | `/categories/{category_id}/products` | `write_categories` | Add a product to a category |
64
+ | `PATCH` | `/categories/{category_id}/products/{id}/reposition` | `write_categories` | Reposition a category product |
65
+
50
66
  ## Channels
51
67
 
52
68
  | Method | Path | Required scope | Summary |
@@ -141,6 +157,12 @@ Endpoints marked — are exempt from scope checks (authentication and session en
141
157
  | `DELETE` | `/invitations/{id}` | `write_settings` | Revoke an invitation |
142
158
  | `PATCH` | `/invitations/{id}/resend` | `write_settings` | Resend an invitation |
143
159
 
160
+ ## Locales
161
+
162
+ | Method | Path | Required scope | Summary |
163
+ |---|---|---|---|
164
+ | `GET` | `/locales` | `read_settings` | List supported locales |
165
+
144
166
  ## Markets
145
167
 
146
168
  | Method | Path | Required scope | Summary |
@@ -156,6 +178,7 @@ Endpoints marked — are exempt from scope checks (authentication and session en
156
178
  | Method | Path | Required scope | Summary |
157
179
  |---|---|---|---|
158
180
  | `GET` | `/me` | — | Get current admin user and permissions |
181
+ | `PATCH` | `/me` | — | Update the current admin profile |
159
182
 
160
183
  ## Option types
161
184
 
@@ -172,6 +195,7 @@ Endpoints marked — are exempt from scope checks (authentication and session en
172
195
  | Method | Path | Required scope | Summary |
173
196
  |---|---|---|---|
174
197
  | `GET` | `/orders/{order_id}/fulfillments` | `read_fulfillments` | List fulfillments |
198
+ | `POST` | `/orders/{order_id}/fulfillments` | `write_fulfillments` | Create a fulfillment |
175
199
  | `GET` | `/orders/{order_id}/fulfillments/{id}` | `read_fulfillments` | Show a shipment |
176
200
  | `PATCH` | `/orders/{order_id}/fulfillments/{id}` | `write_fulfillments` | Update a shipment |
177
201
  | `PATCH` | `/orders/{order_id}/fulfillments/{id}/fulfill` | `write_fulfillments` | Fulfill a fulfillment |
@@ -246,6 +270,7 @@ Endpoints marked — are exempt from scope checks (authentication and session en
246
270
  | `GET` | `/products/{product_id}/custom_fields/{id}` | `read_products` | Show a product custom field |
247
271
  | `PATCH` | `/products/{product_id}/custom_fields/{id}` | `write_products` | Update a product custom field |
248
272
  | `DELETE` | `/products/{product_id}/custom_fields/{id}` | `write_products` | Delete a product custom field |
273
+ | `GET` | `/products/{product_id}/translations` | `read_products` | List product translations |
249
274
  | `GET` | `/products` | `read_products` | List products |
250
275
  | `POST` | `/products` | `write_products` | Create a product |
251
276
  | `GET` | `/products/{id}` | `read_products` | Get a product |
@@ -331,6 +356,18 @@ Endpoints marked — are exempt from scope checks (authentication and session en
331
356
  |---|---|---|---|
332
357
  | `GET` | `/tags` | — | List tags |
333
358
 
359
+ ## Translatable resources
360
+
361
+ | Method | Path | Required scope | Summary |
362
+ |---|---|---|---|
363
+ | `GET` | `/translatable_resources` | `read_settings` | List translatable resources |
364
+
365
+ ## Translations
366
+
367
+ | Method | Path | Required scope | Summary |
368
+ |---|---|---|---|
369
+ | `POST` | `/translations/batch` | *write_<resource> for every resource type in the batch (for API-key authentication)* | Batch upsert translations |
370
+
334
371
  ## Webhook endpoints
335
372
 
336
373
  | Method | Path | Required scope | Summary |
@@ -18,7 +18,7 @@ Each tenant (store) can have its own isolated data and configuration, including:
18
18
  * store settings (name, logo, etc.)
19
19
  * etc.
20
20
 
21
- All data is fully isolated besided the staff users, which can manage multiple tenants. This allows you to create a SaaS platform where each tenant can have its own store with its own branding and configuration. Isolation works across admin dashboard and API.
21
+ All data is fully isolated besides the staff users, which can manage multiple tenants. This allows you to create a SaaS platform where each tenant can have its own store with its own branding and configuration. Isolation works across admin dashboard and API.
22
22
 
23
23
  > **INFO:** If you need individual seller/supplier/vendor accounts but shared product listings under one site you should use [multi vendor recipe](../multi-vendor.md) instead.
24
24
 
@@ -32,9 +32,19 @@ All data is fully isolated besided the staff users, which can manage multiple te
32
32
 
33
33
  > **INFO:** You will need to add these environment variables to your CI/CD pipeline and staging/production environments.
34
34
 
35
- ## Installing gems
35
+ ## Installation
36
36
 
37
- 1. Add the following code to your `Gemfile`:
37
+ ### Eject the Spree backend
38
+
39
+ If you've created your project with `create-spree-app` you will need to eject the backend to be able to install the Enterprise and Multi-Tenant gems. You can do this by running:
40
+
41
+ ```bash
42
+ spree eject
43
+ ```
44
+
45
+ ### Adding gems
46
+
47
+ 1. Add the following code to your `backend/Gemfile`:
38
48
 
39
49
  ```ruby
40
50
  source "https://license:#{ENV['KEYGEN_LICENSE_KEY']}@rubygems.pkg.keygen.sh/#{ENV['KEYGEN_ACCOUNT_ID']}" do
@@ -43,7 +53,57 @@ All data is fully isolated besided the staff users, which can manage multiple te
43
53
  end
44
54
  ```
45
55
 
46
- 2. Install gems:
56
+ 2. Configure the Docker image build to authenticate against the Keygen source.
57
+
58
+ If you use the Spree CLI (Docker), `spree bundle install` resolves the licensed
59
+ gems **inside the image at build time**, so the Keygen credentials must be available
60
+ during `bundle install` in the `Dockerfile` — not just at runtime. Pass them as
61
+ [BuildKit secrets](https://docs.docker.com/build/building/secrets/) so they are mounted
62
+ as environment variables for the `bundle install` step only, and never baked into the
63
+ image layers or history (unlike `ARG`/`ENV`/`COPY`).
64
+
65
+ > **INFO:** Skip this step if you install without the Spree CLI (plain `bundle install` on the host).
66
+ > In that case the Gemfile reads `KEYGEN_LICENSE_KEY` / `KEYGEN_ACCOUNT_ID` directly from
67
+ > your shell environment.
68
+
69
+ Wrap **every** `bundle install` in your `backend/Dockerfile` with the secret mounts. There
70
+ are usually two — one in the build stage and one in the dev stage:
71
+
72
+ ```dockerfile backend/Dockerfile
73
+ COPY .ruby-version Gemfile Gemfile.lock ./
74
+ RUN bundle install # [!code --]
75
+ RUN --mount=type=secret,id=keygen_license_key,env=KEYGEN_LICENSE_KEY,required=false \ # [!code ++]
76
+ --mount=type=secret,id=keygen_account_id,env=KEYGEN_ACCOUNT_ID,required=false \ # [!code ++]
77
+ bundle install # [!code ++]
78
+ ```
79
+
80
+ Then wire the secrets into **both** compose files (`docker-compose.yml` and
81
+ `docker-compose.dev.yml` — the latter is what `spree eject` copies over) so the CLI
82
+ supplies them to the build:
83
+
84
+ ```yaml docker-compose.yml
85
+ x-app: &app
86
+ build:
87
+ context: ./backend
88
+ dockerfile: Dockerfile
89
+ target: dev
90
+ secrets: # [!code ++]
91
+ - keygen_license_key # [!code ++]
92
+ - keygen_account_id # [!code ++]
93
+
94
+ # ...at the bottom of the file, declare where the secrets come from:
95
+ secrets: # [!code ++]
96
+ keygen_license_key: # [!code ++]
97
+ environment: KEYGEN_LICENSE_KEY # [!code ++]
98
+ keygen_account_id: # [!code ++]
99
+ environment: KEYGEN_ACCOUNT_ID # [!code ++]
100
+ ```
101
+
102
+ > **INFO:** Compose reads `environment:`-sourced secrets from the **shell environment** that runs
103
+ > the build, not from `.env`. Make sure `KEYGEN_LICENSE_KEY` and `KEYGEN_ACCOUNT_ID` are
104
+ > exported in the shell (and in your CI/CD and production build environments).
105
+
106
+ 3. Install gems:
47
107
 
48
108
 
49
109
 
@@ -57,7 +117,7 @@ All data is fully isolated besided the staff users, which can manage multiple te
57
117
 
58
118
 
59
119
 
60
- 3. Run generators:
120
+ 4. Run generators:
61
121
 
62
122
 
63
123
 
@@ -72,9 +132,13 @@ All data is fully isolated besided the staff users, which can manage multiple te
72
132
 
73
133
 
74
134
  > **INFO:** This will copy and run migrations for `spree_enterprise` and `spree_multi_tenant` gems.
135
+ > The `spree_multi_tenant:install` generator also edits `config/routes.rb` (to add the
136
+ > tenant domain routing constraints), your customer user model, and your admin user model
137
+ > — see [Post-install configuration](#post-install-configuration) below.
75
138
 
139
+ ## Post-install configuration
76
140
 
77
- ## Setting root domain
141
+ ### Setting root domain
78
142
 
79
143
  Usually multi-tenant applications are configured to use subdomains for each tenant. For example, if your root domain is `example.com`, you can have tenants like `tenant1.example.com`, `tenant2.example.com`, etc.
80
144
  To make it work you need to set the `Spree.root_domain` in your `config/initializers/spree.rb` file, eg.
@@ -86,23 +150,87 @@ Spree.root_domain = 'example.com'
86
150
  or use environment variable:
87
151
 
88
152
  ```ruby
89
- Spree.root_domain = ENV.fetch('SPREE_ROOT_DOMAIN', 'localhost')
153
+ Spree.root_domain = ENV.fetch('SPREE_ROOT_DOMAIN', 'lvh.me')
154
+ ```
155
+
156
+ You need to use `lvh.me` for local development, so cross-subdomain cookies will work, `localhost` will **not** work.
157
+
158
+ > **WARNING:** `localhost` cannot be used as a cookie domain by browsers, so the session cookie set on
159
+ > `store1.localhost` is rejected and never sent back — you get logged out when moving between
160
+ > subdomains, and admin sign-in fails with `ActionController::InvalidAuthenticityToken`
161
+ > ("Can't verify CSRF token authenticity"). Use `lvh.me` (or `localtest.me`); both resolve to
162
+ > `127.0.0.1` and are valid cookie domains.
163
+
164
+ #### Sharing the session cookie across subdomains
165
+
166
+ For staff to stay signed in while moving between the app domain (`app.example.com`) and tenant
167
+ subdomains (`store1.example.com`), the session cookie must be scoped to the parent domain. Set
168
+ `COOKIE_TLD_LENGTH` to the number of labels in your root domain:
169
+
170
+ | Root domain | `COOKIE_TLD_LENGTH` | Cookie domain |
171
+ | ----------- | ------------------- | ------------- |
172
+ | `lvh.me` | `2` | `.lvh.me` |
173
+ | `example.com` | `2` | `.example.com` |
174
+ | `shop.example.co.uk` | `3` | `.example.co.uk` |
175
+
176
+ ```bash .env
177
+ SPREE_ROOT_DOMAIN=lvh.me
178
+ COOKIE_TLD_LENGTH=2
90
179
  ```
91
180
 
92
- This way you can also test it locally using `localhost` as root domain, and use `tenant1.localhost`, `tenant2.localhost`, etc. for tenants.
181
+ #### Allowing tenant subdomains through host authorization
182
+
183
+ Rails' host authorization blocks unknown hosts. `.localhost` and `.test` are permitted in
184
+ development by default, but `.lvh.me` (and your production domain) are not — requests to
185
+ `app.lvh.me` are rejected with a "Blocked hosts" error until you allow them. Add your root
186
+ domain to `config/environments/development.rb`:
187
+
188
+ ```ruby backend/config/environments/development.rb
189
+ if (root_domain = ENV['SPREE_ROOT_DOMAIN']).present?
190
+ config.hosts << ".#{root_domain}"
191
+ end
192
+ ```
93
193
 
94
- ## Customer User Class adjustment
194
+ ### Customer User Class adjustment
95
195
 
96
196
  We need to make slight adjustments to the user class so it can work in a multi-tenant environment.
97
197
 
98
- You need to remove `:validatable` module. This module is responsible for validating the user's email uniqueness. We need to change it to validate it in the scope of the tenant.
198
+ The `spree_multi_tenant:install` generator adds `include SpreeMultiTenant::CustomerUserConcern`
199
+ to your customer user model automatically. You then need to **remove the `:validatable` module**
200
+ manually. `:validatable` validates the user's email uniqueness globally; the concern re-validates
201
+ it in the scope of the tenant instead, so the same email can exist across different tenants.
99
202
 
100
203
  ```ruby backend/app/models/spree/user.rb
101
- class User < ApplicationRecord
102
- devise :database_authenticatable, :registerable, :validatable # [!code --]
103
- devise :database_authenticatable, :registerable, # [!code ++]
104
- :recoverable, :rememberable, :trackable, :confirmable
204
+ class Spree::User < Spree.base_class
205
+ include Spree::UserAddress
206
+ include Spree::UserMethods
207
+ include Spree::UserPaymentSource
208
+ include SpreeMultiTenant::CustomerUserConcern # added by the generator
209
+
210
+ devise :database_authenticatable, :registerable, :recoverable, :rememberable, :validatable # [!code --]
211
+ devise :database_authenticatable, :registerable, :recoverable, :rememberable # [!code ++]
212
+ end
213
+ ```
214
+
215
+ > **WARNING:** Only remove `:validatable`. Do not add other Devise modules (such as `:confirmable`) here
216
+ > unless your app is already set up for them — `:confirmable`, for example, requires additional
217
+ > columns and a confirmation flow, and adding it will break sign-in.
105
218
 
106
- include SpreeMultiTenant::CustomerUserConcern # [!code ++]
219
+ ### Admin User Class adjustment
220
+
221
+ The generator also changes your admin user model's base class from `Spree.base_class` to
222
+ `Spree::Base`. If your `admin_user.rb` exists, this is applied automatically; otherwise make the
223
+ change yourself:
224
+
225
+ ```ruby backend/app/models/spree/admin_user.rb
226
+ class Spree::AdminUser < Spree.base_class # [!code --]
227
+ class Spree::AdminUser < Spree::Base # [!code ++]
228
+ include Spree::AdminUserMethods
229
+
230
+ devise :database_authenticatable, :registerable,
231
+ :recoverable, :rememberable, :validatable
107
232
  end
108
233
  ```
234
+
235
+ > **INFO:** Unlike the customer user model, the admin user model keeps `:validatable` — staff accounts are
236
+ > global and can manage multiple tenants, so their emails remain globally unique.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@spree/docs",
3
- "version": "0.1.113",
3
+ "version": "0.1.115",
4
4
  "description": "Spree Commerce developer documentation for AI agents and local reference",
5
5
  "type": "module",
6
6
  "license": "CC-BY-4.0",