@decocms/start 2.21.0 → 2.23.0
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/.agents/skills/deco-to-tanstack-migration/SKILL.md +12 -7
- package/.agents/skills/deco-to-tanstack-migration/references/htmx-rewrite.md +21 -0
- package/.agents/skills/deco-to-tanstack-migration/references/platform-hooks/README.md +57 -47
- package/.agents/skills/deco-to-tanstack-migration/references/platform-hooks-factories.md +186 -0
- package/MIGRATION_TOOLING_PLAN.md +293 -6
- package/package.json +1 -1
- package/scripts/migrate/phase-transform.ts +7 -1
- package/scripts/migrate/post-cleanup/rules.ts +62 -7
- package/scripts/migrate/post-cleanup/runner.test.ts +77 -1
- package/scripts/migrate/templates/commerce-loaders.ts +2 -1
- package/scripts/migrate/templates/routes.ts +15 -10
- package/scripts/migrate/templates/server-entry.ts +13 -55
- package/scripts/migrate/templates/vite-config.ts +0 -35
- package/scripts/migrate/transforms/htmx-on-events.test.ts +305 -0
- package/scripts/migrate/transforms/htmx-on-events.ts +193 -0
|
@@ -43,7 +43,7 @@ Each phase has entry/exit criteria. Follow in order. Automation % indicates how
|
|
|
43
43
|
| [2](#phase-2--signals--state) | Signals & State | ~50% | `references/signals/` |
|
|
44
44
|
| [3](#phase-3--deco-framework) | Deco Framework Elimination | ~80% | `references/deco-framework/` |
|
|
45
45
|
| [4](#phase-4--commerce--types) | Commerce Types & UI | ~70% | `references/commerce/` |
|
|
46
|
-
| [5](#phase-5--platform-hooks) | Platform Hooks |
|
|
46
|
+
| [5](#phase-5--platform-hooks) | Platform Hooks (factories, W12+) | template | `references/platform-hooks-factories.md` |
|
|
47
47
|
| [6](#phase-6--islands-elimination) | Islands Elimination | ~60% | `references/islands.md` |
|
|
48
48
|
| [7](#phase-7--section-registry) | Section Registry & Setup | 0% | `references/async-rendering.md` |
|
|
49
49
|
| [8](#phase-8--routes--cms) | Routes & CMS | template | `references/navigation.md` |
|
|
@@ -152,14 +152,18 @@ See: `references/commerce/README.md`, `references/vtex-commerce.md`
|
|
|
152
152
|
|
|
153
153
|
**Entry**: Phase 4 complete
|
|
154
154
|
|
|
155
|
-
**Actions
|
|
156
|
-
1.
|
|
157
|
-
2.
|
|
158
|
-
3.
|
|
155
|
+
**Actions (Wave 12+ factory-based — current)**:
|
|
156
|
+
1. `src/hooks/useCart.ts` — 5-line shim around `createUseCart` from `@decocms/apps/vtex/hooks/createUseCart`
|
|
157
|
+
2. `src/hooks/useUser.ts` — 5-line shim around `createUseUser`
|
|
158
|
+
3. `src/hooks/useWishlist.ts` — 5-line shim around `createUseWishlist`
|
|
159
|
+
4. The migration template (`scripts/migrate/templates/hooks.ts`) emits all three for VTEX sites automatically.
|
|
160
|
+
|
|
161
|
+
For non-VTEX platforms, scaffold no-op stubs using `@decocms/start/sdk/signal` (see factories doc § "Non-VTEX platforms").
|
|
159
162
|
|
|
160
163
|
**Exit**: Cart add/remove works, no `apps/{platform}/hooks` imports
|
|
161
164
|
|
|
162
|
-
See: `references/platform-hooks
|
|
165
|
+
See: `references/platform-hooks-factories.md` (canonical, Wave 12+).
|
|
166
|
+
Pre-W12 manual approach is preserved at `references/platform-hooks/README.md` for sites that haven't migrated to factories yet.
|
|
163
167
|
|
|
164
168
|
---
|
|
165
169
|
|
|
@@ -356,7 +360,8 @@ For sites with 100+ sections:
|
|
|
356
360
|
| Signals → TanStack Store | `references/signals/` |
|
|
357
361
|
| Deco framework elimination | `references/deco-framework/` |
|
|
358
362
|
| Commerce & widget types | `references/commerce/` |
|
|
359
|
-
| Platform hooks (VTEX) | `references/platform-hooks
|
|
363
|
+
| Platform hooks (VTEX, factories — Wave 12+) | `references/platform-hooks-factories.md` |
|
|
364
|
+
| Platform hooks (manual, legacy pre-W12) | `references/platform-hooks/README.md` |
|
|
360
365
|
| Vite configuration | `references/vite-config/` |
|
|
361
366
|
| Automation commands | `references/codemod-commands.md` |
|
|
362
367
|
| Islands elimination | `references/islands.md` |
|
|
@@ -62,6 +62,27 @@ Both rewrite to the same React `onClick` / `onChange` etc.
|
|
|
62
62
|
The biggest bucket. Almost always a `useScript`-wrapped function
|
|
63
63
|
attached as an event handler, with no fetch involved.
|
|
64
64
|
|
|
65
|
+
> **Codemod available** (since `@decocms/start >= 2.21.0`). The
|
|
66
|
+
> migration script's `transforms` pipeline now runs
|
|
67
|
+
> `htmx-on-event-rename`, which mechanically rewrites
|
|
68
|
+
> `hx-on:click={…}` → `onClick={…}` (and every other standard DOM
|
|
69
|
+
> event in the [STANDARD_EVENT_MAP](https://github.com/decocms/deco-start/blob/main/scripts/migrate/transforms/htmx-on-events.ts)
|
|
70
|
+
> table) for both colon and dash variants. Handler bodies are
|
|
71
|
+
> preserved verbatim; if the body references Fresh-only globals
|
|
72
|
+
> (`useScript(…)`, `globalThis.window.STOREFRONT`, `STOREFRONT.…`),
|
|
73
|
+
> the codemod injects a single MIGRATION TODO comment at the top
|
|
74
|
+
> of the file pointing back here. **htmx lifecycle events**
|
|
75
|
+
> (`hx-on:htmx-config-request`, `hx-on-htmx-before-request`, etc.)
|
|
76
|
+
> and unknown custom events (`hx-on:my-custom-thing`) are left
|
|
77
|
+
> alone — those need manual rewrite, and the `htmx-residue` audit
|
|
78
|
+
> rule catches them.
|
|
79
|
+
>
|
|
80
|
+
> Smoke result on als-storefront (754 files): codemod renames 98
|
|
81
|
+
> `hx-on:*` attributes across 71 files; 67 of those files (94 %)
|
|
82
|
+
> get the body-TODO. Engineers still own the body rewrite below;
|
|
83
|
+
> the codemod just removes the dead `hx-*` attribute name so the
|
|
84
|
+
> file compiles in React.
|
|
85
|
+
|
|
65
86
|
### Before
|
|
66
87
|
|
|
67
88
|
```tsx
|
|
@@ -1,16 +1,29 @@
|
|
|
1
|
-
# Platform Hooks Migration
|
|
1
|
+
# Platform Hooks Migration (legacy reference)
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
> **This document describes the pre-Wave-12 manual approach.** New
|
|
4
|
+
> migrations should follow
|
|
5
|
+
> [`platform-hooks-factories.md`](../platform-hooks-factories.md), which
|
|
6
|
+
> covers the `createUseCart` / `createUseUser` / `createUseWishlist`
|
|
7
|
+
> factories from `@decocms/apps/vtex/hooks`. The factories collapse
|
|
8
|
+
> everything below into a 5-line site shim per hook.
|
|
9
|
+
>
|
|
10
|
+
> This file is kept for sites that scaffolded before the factories
|
|
11
|
+
> existed — typically sites with `src/lib/vtex-cart-server.ts` or
|
|
12
|
+
> hand-rolled `createServerFn` calls to VTEX endpoints inside
|
|
13
|
+
> `src/hooks/useCart.ts`. See the **"Migrating off the manual approach"**
|
|
14
|
+
> section in the new doc for the cleanup playbook.
|
|
4
15
|
|
|
5
|
-
|
|
16
|
+
---
|
|
17
|
+
|
|
18
|
+
## Strategy (legacy)
|
|
6
19
|
|
|
7
20
|
All hooks are **site-local**. No Vite alias tricks. No compat layers.
|
|
8
21
|
|
|
9
|
-
- Active platform hooks (VTEX for this store)
|
|
10
|
-
- Inactive platform hooks (Wake, Shopify, etc.)
|
|
11
|
-
- Auth hooks
|
|
22
|
+
- Active platform hooks (VTEX for this store) → `~/hooks/useCart.ts` with real implementation
|
|
23
|
+
- Inactive platform hooks (Wake, Shopify, etc.) → `~/hooks/platform/{name}.ts` with no-op stubs
|
|
24
|
+
- Auth hooks → `~/hooks/useUser.ts`, `~/hooks/useWishlist.ts`
|
|
12
25
|
|
|
13
|
-
## VTEX useCart (
|
|
26
|
+
## VTEX useCart (Manual Implementation)
|
|
14
27
|
|
|
15
28
|
### Why Server Functions Are Required
|
|
16
29
|
|
|
@@ -18,7 +31,7 @@ The storefront domain (e.g., `my-store.deco.site`) differs from the VTEX checkou
|
|
|
18
31
|
|
|
19
32
|
Use TanStack Start `createServerFn` to create server-side proxy functions that the client hook calls transparently.
|
|
20
33
|
|
|
21
|
-
### Server Functions (
|
|
34
|
+
### Server Functions (`~/lib/vtex-cart-server.ts`)
|
|
22
35
|
|
|
23
36
|
```typescript
|
|
24
37
|
import { createServerFn } from "@tanstack/react-start";
|
|
@@ -40,50 +53,46 @@ export const getOrCreateCart = createServerFn({ method: "GET" })
|
|
|
40
53
|
"X-VTEX-API-AppKey": API_KEY,
|
|
41
54
|
"X-VTEX-API-AppToken": API_TOKEN,
|
|
42
55
|
},
|
|
43
|
-
body: JSON.stringify({
|
|
56
|
+
body: JSON.stringify({
|
|
57
|
+
expectedOrderFormSections: [
|
|
58
|
+
"items",
|
|
59
|
+
"totalizers",
|
|
60
|
+
"shippingData",
|
|
61
|
+
"clientPreferencesData",
|
|
62
|
+
"storePreferencesData",
|
|
63
|
+
"marketingData",
|
|
64
|
+
],
|
|
65
|
+
}),
|
|
44
66
|
});
|
|
45
67
|
return res.json();
|
|
46
68
|
});
|
|
47
|
-
|
|
48
|
-
export const addItemsToCart = createServerFn({ method: "POST" })
|
|
49
|
-
.validator((data: { orderFormId: string; items: any[] }) => data)
|
|
50
|
-
.handler(async ({ data }) => {
|
|
51
|
-
const res = await fetch(
|
|
52
|
-
`https://${ACCOUNT}.vtexcommercestable.com.br/api/checkout/pub/orderForm/${data.orderFormId}/items`,
|
|
53
|
-
{
|
|
54
|
-
method: "POST",
|
|
55
|
-
headers: { "Content-Type": "application/json", "X-VTEX-API-AppKey": API_KEY, "X-VTEX-API-AppToken": API_TOKEN },
|
|
56
|
-
body: JSON.stringify({ orderItems: data.items }),
|
|
57
|
-
},
|
|
58
|
-
);
|
|
59
|
-
return res.json();
|
|
60
|
-
});
|
|
61
|
-
|
|
62
|
-
export const updateCartItems = createServerFn({ method: "POST" })
|
|
63
|
-
.validator((data: { orderFormId: string; items: any[] }) => data)
|
|
64
|
-
.handler(async ({ data }) => {
|
|
65
|
-
const res = await fetch(
|
|
66
|
-
`https://${ACCOUNT}.vtexcommercestable.com.br/api/checkout/pub/orderForm/${data.orderFormId}/items/update`,
|
|
67
|
-
{
|
|
68
|
-
method: "POST",
|
|
69
|
-
headers: { "Content-Type": "application/json", "X-VTEX-API-AppKey": API_KEY, "X-VTEX-API-AppToken": API_TOKEN },
|
|
70
|
-
body: JSON.stringify({ orderItems: data.items }),
|
|
71
|
-
},
|
|
72
|
-
);
|
|
73
|
-
return res.json();
|
|
74
|
-
});
|
|
75
69
|
```
|
|
76
70
|
|
|
77
|
-
|
|
71
|
+
> **Don't write code like this in new sites.** The factories already wrap
|
|
72
|
+
> all canonical VTEX action endpoints (cart, session, masterdata,
|
|
73
|
+
> newsletter, checkout) in `@decocms/apps/vtex/actions/*`. The migration
|
|
74
|
+
> template scaffolds `src/server/invoke.gen.ts` which exposes them as
|
|
75
|
+
> typed server functions; `~/server/invoke.ts` then re-exports them
|
|
76
|
+
> under `invoke.vtex.actions.*`. The factory consumes that surface and
|
|
77
|
+
> returns the legacy hook shape.
|
|
78
78
|
|
|
79
|
-
|
|
79
|
+
### Hook (`~/hooks/useCart.ts`)
|
|
80
|
+
|
|
81
|
+
Key design decisions of the legacy manual hook:
|
|
80
82
|
- **Module-level singleton state** shared across all component instances
|
|
81
83
|
- **Pub/sub pattern** (`_listeners` Set) for notifying React components of changes
|
|
82
|
-
- **Cookie-based session**: reads/writes `checkout.vtex.com__orderFormId` on the **client** side
|
|
84
|
+
- **Cookie-based session**: reads/writes `checkout.vtex.com__orderFormId` on the **client** side
|
|
83
85
|
- Returns `cart` and `loading` with `.value` getter/setter for backward compat with Preact-era components
|
|
84
86
|
- Lazy initialization: cart is fetched on first component mount, not on module load
|
|
85
87
|
- Exports `itemToAnalyticsItem` for cart-specific analytics mapping
|
|
86
88
|
|
|
89
|
+
The factory in `@decocms/apps/vtex/hooks/createUseCart` ships *exactly*
|
|
90
|
+
these semantics — that's the implementation behind the new shim. If your
|
|
91
|
+
site needs to extend behaviour (e.g. extra analytics events, custom
|
|
92
|
+
post-add hooks), prefer wrapping the factory's exports rather than
|
|
93
|
+
forking back to a manual hook; the factory leaves space for that
|
|
94
|
+
without giving up the upgrade path.
|
|
95
|
+
|
|
87
96
|
### Cross-Domain Checkout
|
|
88
97
|
|
|
89
98
|
The minicart's "Finalizar Compra" button must link to the VTEX checkout domain with the `orderFormId` as a query parameter — the VTEX domain can't read the storefront's cookies:
|
|
@@ -92,10 +101,8 @@ The minicart's "Finalizar Compra" button must link to the VTEX checkout domain w
|
|
|
92
101
|
const checkoutUrl = `https://secure.${STORE_DOMAIN}/checkout/?orderFormId=${orderFormId}`;
|
|
93
102
|
```
|
|
94
103
|
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
Site-local types for VTEX-specific structures:
|
|
98
|
-
- `OrderFormItem`, `SimulationOrderForm`, `Sla`, `SKU`, `VtexProduct`
|
|
104
|
+
This pattern is unchanged by the factory — it's a UI concern, not a hook
|
|
105
|
+
concern. Implement it in your minicart component as before.
|
|
99
106
|
|
|
100
107
|
## Inactive Platform Stubs
|
|
101
108
|
|
|
@@ -130,9 +137,13 @@ export function useWishlist() {
|
|
|
130
137
|
}
|
|
131
138
|
```
|
|
132
139
|
|
|
133
|
-
Create similar stubs for: `shopify.ts`, `linx.ts`, `vnda.ts`, `nuvemshop.ts`.
|
|
140
|
+
Create similar stubs for: `shopify.ts`, `linx.ts`, `vnda.ts`, `nuvemshop.ts`. Match the return shape to what each platform's AddToCartButton expects (some use `addItem`, others `addItems`).
|
|
134
141
|
|
|
135
|
-
|
|
142
|
+
The factory equivalent for non-VTEX sites is documented in
|
|
143
|
+
[`platform-hooks-factories.md` § "Non-VTEX platforms"](../platform-hooks-factories.md#non-vtex-platforms).
|
|
144
|
+
Until each platform has its own factory in `@decocms/apps`, the stub
|
|
145
|
+
shape above is still correct — but use `@decocms/start/sdk/signal`
|
|
146
|
+
instead of hand-rolled `{ value: ... }` objects.
|
|
136
147
|
|
|
137
148
|
## Import Rewrites
|
|
138
149
|
|
|
@@ -143,7 +154,6 @@ sed -i '' 's|from "apps/vtex/hooks/useWishlist.ts"|from "~/hooks/useWishlist"|g'
|
|
|
143
154
|
sed -i '' 's|from "apps/vtex/utils/types.ts"|from "~/types/vtex"|g'
|
|
144
155
|
sed -i '' 's|from "apps/shopify/hooks/useCart.ts"|from "~/hooks/platform/shopify"|g'
|
|
145
156
|
sed -i '' 's|from "apps/wake/hooks/useCart.ts"|from "~/hooks/platform/wake"|g'
|
|
146
|
-
# etc. for all platforms
|
|
147
157
|
```
|
|
148
158
|
|
|
149
159
|
## Verification
|
|
@@ -0,0 +1,186 @@
|
|
|
1
|
+
# Platform Hooks — Factory Pattern
|
|
2
|
+
|
|
3
|
+
> **Canonical reference for `createUseCart` / `createUseUser` /
|
|
4
|
+
> `createUseWishlist` from `@decocms/apps/vtex/hooks`.** These factories
|
|
5
|
+
> ship the legacy invoke-based hook semantics that migrated Fresh sites
|
|
6
|
+
> depend on — module-level singleton state, listener-based re-render,
|
|
7
|
+
> awaitable async actions, signal-shaped accessors. Sites consume them
|
|
8
|
+
> as 5-line shims.
|
|
9
|
+
|
|
10
|
+
This doc replaces the pre-W12 "manual `createServerFn` per VTEX endpoint"
|
|
11
|
+
approach in
|
|
12
|
+
[`platform-hooks/README.md`](./platform-hooks/README.md). If you scaffolded
|
|
13
|
+
a site before Wave 12 (≤ `@decocms/apps@2.x` / `@decocms/start@2.18`), see
|
|
14
|
+
"Migrating off the manual approach" at the bottom.
|
|
15
|
+
|
|
16
|
+
---
|
|
17
|
+
|
|
18
|
+
## What the factories own
|
|
19
|
+
|
|
20
|
+
| Concern | Where it lives |
|
|
21
|
+
|---|---|
|
|
22
|
+
| Module-level singleton state (`cart`, `user`, `wishlist`) | Inside the factory closure |
|
|
23
|
+
| `useEffect` + `forceRender(c => c + 1)` re-render pattern | Factory |
|
|
24
|
+
| Signal-shaped accessors (`cart.value`, `user.value`) | Factory |
|
|
25
|
+
| Awaitable mutations (`await addItem(...)`) | Factory |
|
|
26
|
+
| `itemToAnalyticsItem` helper (cart) | Factory |
|
|
27
|
+
| Wishlist arg swap (`productId` ↔ `productGroupId`) | Factory |
|
|
28
|
+
| **VTEX HTTP calls** | NOT in the factory — provided by the `invoke` proxy you pass in |
|
|
29
|
+
|
|
30
|
+
The factory only wires state + listeners. The site provides an `invoke`
|
|
31
|
+
object whose shape is structurally typed against
|
|
32
|
+
`CreateUseCartInvoke` / `CreateUseUserInvoke` / `CreateUseWishlistInvoke`
|
|
33
|
+
(exported next to each factory). The migration template generates an
|
|
34
|
+
`invoke` proxy in `src/server/invoke.ts` that meets all three shapes
|
|
35
|
+
without any extra wiring.
|
|
36
|
+
|
|
37
|
+
---
|
|
38
|
+
|
|
39
|
+
## Site-local shim (the entire file)
|
|
40
|
+
|
|
41
|
+
### `src/hooks/useCart.ts`
|
|
42
|
+
|
|
43
|
+
```ts
|
|
44
|
+
import { createUseCart } from "@decocms/apps/vtex/hooks/createUseCart";
|
|
45
|
+
import { invoke } from "~/server/invoke";
|
|
46
|
+
|
|
47
|
+
export type { OrderForm, OrderFormItem } from "@decocms/apps/vtex/types";
|
|
48
|
+
|
|
49
|
+
export const { useCart, resetCart, itemToAnalyticsItem } = createUseCart({
|
|
50
|
+
invoke,
|
|
51
|
+
});
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
### `src/hooks/useUser.ts`
|
|
55
|
+
|
|
56
|
+
```ts
|
|
57
|
+
import { createUseUser } from "@decocms/apps/vtex/hooks/createUseUser";
|
|
58
|
+
import { invoke } from "~/server/invoke";
|
|
59
|
+
|
|
60
|
+
export type { Person } from "@decocms/apps/vtex/loaders/user";
|
|
61
|
+
|
|
62
|
+
export const { useUser, resetUser } = createUseUser({ invoke });
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
### `src/hooks/useWishlist.ts`
|
|
66
|
+
|
|
67
|
+
```ts
|
|
68
|
+
import { createUseWishlist } from "@decocms/apps/vtex/hooks/createUseWishlist";
|
|
69
|
+
import { invoke } from "~/server/invoke";
|
|
70
|
+
|
|
71
|
+
export type { WishlistItem } from "@decocms/apps/vtex/loaders/wishlist";
|
|
72
|
+
|
|
73
|
+
export const { useWishlist, resetWishlist } = createUseWishlist({ invoke });
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
That's the whole hook — no `createServerFn`, no VTEX URLs, no `AppKey`
|
|
77
|
+
plumbing. `npm run migrate` scaffolds these three files automatically
|
|
78
|
+
when `--platform vtex` is set; if you regenerate, the migration template
|
|
79
|
+
in `scripts/migrate/templates/hooks.ts` is the source of truth.
|
|
80
|
+
|
|
81
|
+
---
|
|
82
|
+
|
|
83
|
+
## Why a factory and not a single hook?
|
|
84
|
+
|
|
85
|
+
> Two reasons that come up repeatedly when reviewing migration PRs.
|
|
86
|
+
|
|
87
|
+
1. **`useCart` already exists in apps.** The canonical `vtex/hooks/useCart.ts`
|
|
88
|
+
is built on TanStack Query and exposes the `Minicart` shape — that is
|
|
89
|
+
the shape new code should target. The factory exists strictly so
|
|
90
|
+
already-migrated UIs keep working without a rewrite. Both can coexist
|
|
91
|
+
in one site.
|
|
92
|
+
2. **Singletons can't live in a shared package without leaking across
|
|
93
|
+
sites.** The factory call instantiates a fresh module-level state per
|
|
94
|
+
site. Importing `useCart` directly from apps would share state across
|
|
95
|
+
any sites that ran in the same Worker (matters less in practice, but
|
|
96
|
+
it's the architectural reason the factory exists).
|
|
97
|
+
|
|
98
|
+
The factory boundary is also the seam where we'd later wire
|
|
99
|
+
`@tanstack/store` if we wanted to — the API shape is signal-compatible
|
|
100
|
+
already.
|
|
101
|
+
|
|
102
|
+
---
|
|
103
|
+
|
|
104
|
+
## Non-VTEX platforms
|
|
105
|
+
|
|
106
|
+
Sites that target Wake / Shopify / VNDA / Linx / Nuvemshop still need a
|
|
107
|
+
hook surface that AddToCartButtons can consume. Until each platform has
|
|
108
|
+
its own factory in `@decocms/apps`, scaffold a no-op shim:
|
|
109
|
+
|
|
110
|
+
```ts
|
|
111
|
+
// src/hooks/useCart.ts (custom platform)
|
|
112
|
+
import { signal } from "@decocms/start/sdk/signal";
|
|
113
|
+
|
|
114
|
+
const cart = signal<unknown>(null);
|
|
115
|
+
const loading = signal(false);
|
|
116
|
+
|
|
117
|
+
export function useCart() {
|
|
118
|
+
return {
|
|
119
|
+
cart,
|
|
120
|
+
loading,
|
|
121
|
+
async getCart() {
|
|
122
|
+
// TODO: call your platform's cart API via ~/server/invoke
|
|
123
|
+
return null;
|
|
124
|
+
},
|
|
125
|
+
async addItems(_items: unknown[]) {
|
|
126
|
+
// TODO
|
|
127
|
+
},
|
|
128
|
+
async updateItems(_items: unknown[]) {
|
|
129
|
+
// TODO
|
|
130
|
+
},
|
|
131
|
+
setCart(next: unknown) {
|
|
132
|
+
cart.value = next;
|
|
133
|
+
},
|
|
134
|
+
};
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
export default useCart;
|
|
138
|
+
```
|
|
139
|
+
|
|
140
|
+
`@decocms/start/sdk/signal` (re-exported via `~/sdk/signal` after
|
|
141
|
+
migration) gives you the same `.value` getter/setter the factory uses,
|
|
142
|
+
so AddToCart UI components don't need to know which platform is wired.
|
|
143
|
+
|
|
144
|
+
The migration template's `generateGenericUseCart()` emits this stub when
|
|
145
|
+
`--platform` is `custom` (or any non-VTEX value).
|
|
146
|
+
|
|
147
|
+
---
|
|
148
|
+
|
|
149
|
+
## Migrating off the manual approach (pre-W12 sites)
|
|
150
|
+
|
|
151
|
+
If your site contains files like `src/lib/vtex-cart-server.ts` or hand-rolled `createServerFn` blocks for VTEX endpoints in `src/hooks/useCart.ts`, the post-cleanup audit will not auto-fix them — the manual code accumulated 6+ months of site-specific edits and the per-site judgment call about "what's still needed?" is real. The mechanical part:
|
|
152
|
+
|
|
153
|
+
1. Replace the entire body of `src/hooks/useCart.ts` with the 5-line factory shim above.
|
|
154
|
+
2. Delete `src/lib/vtex-cart-server.ts` (the migration template's `src/server/invoke.gen.ts` provides equivalent server functions wrapping `@decocms/apps/vtex/actions/checkout`).
|
|
155
|
+
3. Verify `src/server/invoke.ts` exports the proxy shape the factory needs (cart actions under `invoke.vtex.actions`). The migration template scaffolds this; older sites may need to add the missing entries by hand.
|
|
156
|
+
4. Run `npm run typecheck` — TypeScript will surface any callsites that referenced removed helpers (e.g. local `getOrCreateCart` shims).
|
|
157
|
+
5. Repeat for `useUser` / `useWishlist`.
|
|
158
|
+
|
|
159
|
+
For `useUser`, the analog of step 2 is removing any local `currentUser` /
|
|
160
|
+
`getUser` server functions in favor of `@decocms/apps/vtex/loaders/user`
|
|
161
|
+
exposed via `invoke.vtex.loaders.user()`. For `useWishlist`, the
|
|
162
|
+
canonical surface is `@decocms/apps/vtex/{actions,loaders}/wishlist`.
|
|
163
|
+
|
|
164
|
+
If you find yourself wanting to add behaviour to a factory (extra cart
|
|
165
|
+
actions, custom analytics events) rather than ripping out the factory and going back to a manual hook:
|
|
166
|
+
|
|
167
|
+
- **Extra read paths** → expose a new loader from
|
|
168
|
+
`@decocms/apps/vtex/loaders/*`, register it in `~/server/invoke.ts`,
|
|
169
|
+
call from your component (the factory doesn't need to know).
|
|
170
|
+
- **Extra write paths** → ditto for `@decocms/apps/vtex/actions/*`.
|
|
171
|
+
- **Cross-cutting business logic** (e.g. PIX-specific offer pricing) →
|
|
172
|
+
this is the kind of seam that justifies a parallel `useOffer` factory.
|
|
173
|
+
Talk to the apps maintainers; opening up a factory's plugin slots is a
|
|
174
|
+
one-PR change in apps, not a per-site rewrite.
|
|
175
|
+
|
|
176
|
+
---
|
|
177
|
+
|
|
178
|
+
## Related
|
|
179
|
+
|
|
180
|
+
- `scripts/migrate/templates/hooks.ts` — the template that emits the
|
|
181
|
+
shims above.
|
|
182
|
+
- `apps-start/vtex/hooks/createUseCart.ts` /
|
|
183
|
+
`createUseUser.ts` / `createUseWishlist.ts` — the factories
|
|
184
|
+
themselves; each docstring is the authoritative API reference.
|
|
185
|
+
- `references/platform-hooks/README.md` — historical reference for the
|
|
186
|
+
pre-W12 manual approach (kept for sites that haven't migrated yet).
|