@spree/docs 0.1.299 → 0.1.301

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.
@@ -11738,7 +11738,7 @@ components:
11738
11738
  type: array
11739
11739
  items:
11740
11740
  type: string
11741
- description: Subject class names, e.g. ["Spree::Product"] or ["all"]
11741
+ description: Subject short names, e.g. ["product"] or ["all"]
11742
11742
  has_conditions:
11743
11743
  type: boolean
11744
11744
  description: True if the server-side rule has per-record conditions. The
@@ -94,11 +94,12 @@ spree build --yes # Skip confirmation prompts (for CI)
94
94
 
95
95
  Upgrade your project to the latest Spree release in one go. It works for both kinds of project:
96
96
 
97
- 1. **Update the server**
98
- - On a project that runs the prebuilt image, it pulls the latest Spree image and recreates the containers. Database migrations run as the containers start.
99
- - On an [ejected](#spree-eject) project, it updates the Spree gems with `bundle update`, applies pending migrations, and restarts the app so it loads the new gems.
100
- 2. **Run data backfills** — the version-specific steps from the upgrade manifest that convert existing records.
101
- 3. **Update the `@spree/*` packages** — `@spree/cli` in the project root, and the dashboard packages and Admin SDK in `apps/dashboard` and `apps/seller-dashboard`. Each package moves to the newest release its declared range in `package.json` allows, the same way `bundle update` respects your `Gemfile`. To move to a new major version, change the range in `package.json` first.
97
+ 1. **Update the server** — on a project that runs the prebuilt image, it pulls the latest Spree image. On an [ejected](#spree-eject) project, it updates the Spree gems with `bundle update`.
98
+ 2. **Update the `@spree/*` packages** — `@spree/cli` in the project root, and the dashboard packages and Admin SDK in `apps/dashboard` and `apps/seller-dashboard`. Each package moves to the newest release its declared range in `package.json` allows, the same way `bundle update` respects your `Gemfile`. To move to a new major version, change the range in `package.json` first.
99
+ 3. **Migrate the database** — on a prebuilt-image project, it recreates the containers and the migrations run as they start. On an ejected project, it applies pending migrations.
100
+ 4. **Run data backfills** — the version-specific steps from the upgrade manifest that convert existing records. An ejected project's app is then restarted so it loads the new gems.
101
+
102
+ The packages are updated before the database steps, so a failed migration or backfill no longer stops them from moving to the newest release their ranges allow. Fix the cause and run `spree upgrade` again.
102
103
 
103
104
  ```bash
104
105
  spree upgrade # Run every step, asking before each one
@@ -151,7 +151,7 @@ To update to the latest Spree version:
151
151
  spree upgrade
152
152
  ```
153
153
 
154
- This updates the server (the Docker image, or the Spree gems on an ejected project), runs database migrations and data backfills, and updates the `@spree/*` packages of the project and its dashboard apps. See [`spree upgrade`](../cli/quickstart.md#spree-upgrade) for details.
154
+ This updates the server (the Docker image, or the Spree gems on an ejected project) and the `@spree/*` packages of the project and its dashboard apps, then runs database migrations and data backfills. See [`spree upgrade`](../cli/quickstart.md#spree-upgrade) for details.
155
155
 
156
156
  To pin a specific version, edit `SPREE_VERSION_TAG` in `.env`:
157
157
 
@@ -22,7 +22,7 @@ nav.add({
22
22
  path: '/analytics', // prefixed with /$storeId at render time
23
23
  icon: BarChartIcon,
24
24
  position: 650,
25
- subject: 'Spree::Order', // optional permission subject — hides item without read permission
25
+ subject: 'order', // optional permission subject — hides item without read permission
26
26
  })
27
27
  ```
28
28
 
@@ -70,7 +70,7 @@ nav.addChild('products', {
70
70
  key: 'products.brands',
71
71
  label: 'Brands',
72
72
  path: '/products/brands',
73
- subject: 'Spree::Brand',
73
+ subject: 'brand',
74
74
  })
75
75
  ```
76
76
 
@@ -177,7 +177,7 @@ settingsNav.add({
177
177
  path: '/integrations/stripe-tax', // prefixed with /$storeId/settings
178
178
  group: 'integrations',
179
179
  position: 100,
180
- subject: 'Spree::TaxRate',
180
+ subject: 'tax_rate',
181
181
  })
182
182
  ```
183
183
 
@@ -33,10 +33,10 @@ interface Permissions {
33
33
  It mirrors the backend ability at the **class level**:
34
34
 
35
35
  ```ts
36
- permissions.can('read', 'Spree::Order')
36
+ permissions.can('read', 'order')
37
37
  ```
38
38
 
39
- Subjects are strings (`'Spree::Order'`, `'Spree::Product'`, or your own `'MyApp::Report'`). There is no client-side record-level check — when a rule is conditional on record attributes, `isConditional` returns `true` and the API is the arbiter: render the control and handle a possible 403.
39
+ Subjects are short names: the model's class name without its namespace, underscored (`'order'`, `'product'`, or `'report'` for your own `MyApp::Report`). Use the `Subject` constants from `@spree/dashboard-core` for Spree's own models. There is no client-side record-level check — when a rule is conditional on record attributes, `isConditional` returns `true` and the API is the arbiter: render the control and handle a possible 403.
40
40
 
41
41
  ## `subject` shortcut
42
42
 
@@ -47,7 +47,7 @@ nav.add({
47
47
  key: 'reports',
48
48
  label: 'Reports',
49
49
  path: '/reports',
50
- subject: 'Spree::Order', // hides nav item without read:Spree::Order
50
+ subject: 'order', // hides nav item without read:order
51
51
  })
52
52
  ```
53
53
 
@@ -58,7 +58,7 @@ routes: [{
58
58
  key: 'reports',
59
59
  path: '/reports',
60
60
  component: ReportsPage,
61
- subject: 'Spree::Order',
61
+ subject: 'order',
62
62
  }],
63
63
  ```
64
64
 
@@ -76,7 +76,7 @@ nav.add({
76
76
  label: 'Reports',
77
77
  path: '/reports',
78
78
  if: ({ permissions, store }) =>
79
- permissions.can('read', 'Spree::Order') &&
79
+ permissions.can('read', 'order') &&
80
80
  !!(store as Store | null)?.setup_tasks?.every((task) => task.done),
81
81
  })
82
82
  ```
@@ -94,18 +94,18 @@ import { usePermissions } from '@spree/dashboard'
94
94
 
95
95
  function ReportsPage() {
96
96
  const { permissions } = usePermissions()
97
- if (!permissions.can('read', 'Spree::Order')) {
97
+ if (!permissions.can('read', 'order')) {
98
98
  return <Forbidden />
99
99
  }
100
100
  return <ReportsList />
101
101
  }
102
102
  ```
103
103
 
104
- The same `permissions` object backs the nav registry's `if` predicate, so you can move logic between the two without changing behaviour. For declarative gating, `<Can I="update" a="Spree::Order">…</Can>` (also from `@spree/dashboard-core`) renders children only when the check passes.
104
+ The same `permissions` object backs the nav registry's `if` predicate, so you can move logic between the two without changing behaviour. For declarative gating, `<Can I="update" a="order">…</Can>` (also from `@spree/dashboard-core`) renders children only when the check passes.
105
105
 
106
106
  ## Custom permissions
107
107
 
108
- If your customization introduces a new model on the backend, register it as a permission catalog scope there (`Spree.permissions.register_scope` in your engine's initializer). Its keys then appear in the role editor and the API-key scope picker, and any role granted them makes `permissions.can('read', 'MyApp::Report')` resolve in the dashboard exactly like a first-party check — the abilities ship with the current-user response (`GET /api/v3/admin/me`) at sign-in, alongside `permission_keys`, the flat key list the role editor grants from.
108
+ If your customization introduces a new model on the backend, register it as a permission catalog scope there (`Spree.permissions.register_scope` in your engine's initializer). Its keys then appear in the role editor and the API-key scope picker, and any role granted them makes `permissions.can('read', 'report')` resolve in the dashboard exactly like a first-party check — the abilities ship with the current-user response (`GET /api/v3/admin/me`) at sign-in, alongside `permission_keys`, the flat key list the role editor grants from.
109
109
 
110
110
  ## Reference
111
111
 
@@ -135,7 +135,7 @@ routes: [{
135
135
  key: 'reports',
136
136
  path: '/reports',
137
137
  component: ReportsPage,
138
- subject: 'Spree::Order',
138
+ subject: 'order',
139
139
  }],
140
140
  ```
141
141
 
@@ -68,7 +68,7 @@ import { usePermissions } from '@spree/dashboard'
68
68
 
69
69
  function AdminOnlyMenuItem() {
70
70
  const { permissions } = usePermissions()
71
- if (!permissions.can('manage', 'Spree::Customer')) return null
71
+ if (!permissions.can('manage', 'customer')) return null
72
72
  return <DropdownMenuItem>…</DropdownMenuItem>
73
73
  }
74
74
  ```
@@ -33,7 +33,7 @@ export function SendInvoiceButton({ resource }: Props) {
33
33
  })
34
34
 
35
35
  // Only show to users who can act, and only on completed orders.
36
- if (!permissions.can('update', 'Spree::Order')) return null
36
+ if (!permissions.can('update', 'order')) return null
37
37
  if (resource.status !== 'placed') return null
38
38
 
39
39
  return (
@@ -95,7 +95,7 @@ export function SyncToErpItem({ resource }: Props) {
95
95
  successMessage: 'Synced',
96
96
  })
97
97
 
98
- if (!permissions.can('manage', 'Spree::Order')) return null
98
+ if (!permissions.can('manage', 'order')) return null
99
99
 
100
100
  return (
101
101
  <DropdownMenuItem
@@ -42,7 +42,7 @@ interface Props {
42
42
  export function LoyaltyStatusCard({ customer }: Props) {
43
43
  const { storeId } = useStore()
44
44
  const { permissions } = usePermissions()
45
- const canRead = permissions.can('read', 'MyApp::LoyaltyRecord')
45
+ const canRead = permissions.can('read', 'loyalty_record')
46
46
  const { data, isLoading } = useQuery({
47
47
  queryKey: ['loyalty', storeId, customer.id],
48
48
  queryFn: () =>
@@ -44,7 +44,7 @@ import { usePermissions, useStore } from '@spree/dashboard'
44
44
  function MyWidget({ product }: { product: Product }) {
45
45
  const { permissions } = usePermissions()
46
46
  const { store } = useStore()
47
- if (!permissions.can('read', 'MyApp::LoyaltyRecord')) return null
47
+ if (!permissions.can('read', 'loyalty_record')) return null
48
48
  // ...
49
49
  }
50
50
  ```
@@ -506,7 +506,7 @@ If your storefront or webhook receiver reads any of these fields, compare agains
506
506
  | `payment_source_type` | Store API payment setup sessions, `payment_setup_session.*` webhooks | `Spree::CreditCard` | `credit_card` |
507
507
  | `type` | Custom fields on products, variants, categories and collections | `Spree::CustomFields::ShortText` | removed — read `field_type` (`short_text`) |
508
508
 
509
- The Admin API follows the same rule everywhere: providers and strategies (`fulfillment_provider: 'manual'`, `preferred_order_routing_strategy: 'rules'`), custom field definition `resource_type` (`product`, `category`), tag `taggable_type`, the owner and originator types on records, and filters such as `q[type_eq]=orders`. An integration written against the Admin API preview sends and expects these short names; the [Admin SDK](../sdk/admin/resources.md) types list them.
509
+ The Admin API follows the same rule everywhere: providers and strategies (`fulfillment_provider: 'manual'`, `preferred_order_routing_strategy: 'rules'`), custom field definition `resource_type` (`product`, `category`), tag `taggable_type`, the owner and originator types on records, the permission subjects `/me` returns (`product`, `category`), and filters such as `q[type_eq]=orders`. An integration written against the Admin API preview sends and expects these short names; the [Admin SDK](../sdk/admin/resources.md) types list them.
510
510
 
511
511
  ## Every event is declared
512
512
 
@@ -11,7 +11,7 @@ We strongly advise upgrading Spree incrementally, rather than in one big go.
11
11
 
12
12
  ## How to upgrade
13
13
 
14
- An upgrade updates the server, migrates the database, runs the version's data backfills, and updates the `@spree/*` packages of your dashboard apps. Always read the guide for the version you're moving to first — it lists the behavior changes to review.
14
+ An upgrade updates the server and the `@spree/*` packages of your dashboard apps, migrates the database, and runs the version's data backfills. Always read the guide for the version you're moving to first — it lists the behavior changes to review.
15
15
 
16
16
  **Spree CLI:**
17
17
 
@@ -19,23 +19,23 @@ An upgrade updates the server, migrates the database, runs the version's data ba
19
19
  spree upgrade
20
20
  ```
21
21
 
22
- One command for every project: it pulls the new image, or updates the Spree gems on an [ejected](../cli/quickstart.md#spree-eject) project, then runs migrations, data backfills and the package updates. See [`spree upgrade`](../cli/quickstart.md#spree-upgrade) for its options.
22
+ One command for every project: it pulls the new image, or updates the Spree gems on an [ejected](../cli/quickstart.md#spree-eject) project, then updates the packages and runs migrations and data backfills. See [`spree upgrade`](../cli/quickstart.md#spree-upgrade) for its options.
23
23
 
24
24
  **Without CLI:**
25
25
 
26
26
  Run from the project root:
27
27
 
28
28
  ```bash
29
- cd server
30
- bundle update $(bundle list --name-only | grep ^spree)
31
- bin/rails spree:install:migrations db:migrate
32
- bin/rails spree:upgrade
33
- cd ..
29
+ (cd server && bundle update $(bundle list --name-only | grep ^spree))
34
30
 
35
31
  # The project root and each dashboard app have their own package.json
36
32
  pnpm update "@spree/*"
37
33
  (cd apps/dashboard && pnpm update "@spree/*")
38
34
  (cd apps/seller-dashboard && pnpm update "@spree/*")
35
+
36
+ cd server
37
+ bin/rails spree:install:migrations db:migrate
38
+ bin/rails spree:upgrade
39
39
  ```
40
40
 
41
41
  On npm or Yarn, run `npm update` or `yarn upgrade` instead, naming each `@spree/*` package from that `package.json` (they do not accept the `"@spree/*"` pattern).
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@spree/docs",
3
- "version": "0.1.299",
3
+ "version": "0.1.301",
4
4
  "description": "Spree Commerce developer documentation for AI agents and local reference",
5
5
  "type": "module",
6
6
  "license": "CC-BY-4.0",