Skip to content
Open
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 9 additions & 0 deletions packages/api/src/platforms/vtex/resolvers/root.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,3 +10,12 @@ export type { Root as StoreSkuVariationsRoot } from './skuVariations'
export type { Root as StoreProductGroupRoot } from './productGroup'
export type { Root as StoreProductRoot } from './product'
export type { Root as StoreOrganizationRoot } from './organization'

export type StoreCartRoot = {
/**
* The VTEX orderForm used to build the StoreCart response. This is an
* internal resolver root field and is not exposed by the GraphQL schema.
* Store API extensions can use it to resolve StoreCart fields.
*/
__orderForm: import('../clients/commerce/types/OrderForm').OrderForm
}
4 changes: 4 additions & 0 deletions packages/api/src/platforms/vtex/resolvers/validateCart.ts
Original file line number Diff line number Diff line change
Expand Up @@ -178,6 +178,10 @@ const orderFormToCart = async (
shouldSplitItem?: boolean | null
) => {
return {
// Keep the source orderForm available to StoreCart extension resolvers.
// The property is not part of the GraphQL schema and is never serialized
// unless a custom resolver explicitly uses it.
__orderForm: form,
order: {
orderNumber: form.orderFormId,
acceptedOffer: form.items.map(async (item) => ({
Expand Down
12 changes: 9 additions & 3 deletions packages/core/@generated/gql.ts

Large diffs are not rendered by default.

24 changes: 22 additions & 2 deletions packages/core/@generated/graphql.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2750,6 +2750,10 @@ export type ServerCollectionPageFragment = { collection: { id: string } };

export type ServerProductFragment = { product: { id: string } };

export type CartItemAdditionalFragment = { quantity: number };

export type StoreCartAdditionalFragment = { order: { orderNumber: string } };

export type ServerAccountPageQueryQueryVariables = Exact<{ [key: string]: never; }>;


Expand Down Expand Up @@ -3478,6 +3482,13 @@ export const ServerProductFragmentDoc = new TypedDocumentString(`
}
}
`, {"fragmentName":"ServerProduct"}) as unknown as TypedDocumentString<ServerProductFragment, unknown>;
export const StoreCartAdditionalFragmentDoc = new TypedDocumentString(`
fragment StoreCartAdditional on StoreCart {
order {
orderNumber
}
}
`, {"fragmentName":"StoreCartAdditional"}) as unknown as TypedDocumentString<StoreCartAdditionalFragment, unknown>;
export const UserOrderItemsFragmentFragmentDoc = new TypedDocumentString(`
fragment UserOrderItemsFragment on UserOrderItems {
id
Expand All @@ -3498,8 +3509,14 @@ export const CartMessageFragmentDoc = new TypedDocumentString(`
status
}
`, {"fragmentName":"CartMessage"}) as unknown as TypedDocumentString<CartMessageFragment, unknown>;
export const CartItemAdditionalFragmentDoc = new TypedDocumentString(`
fragment CartItemAdditional on StoreOffer {
quantity
}
`, {"fragmentName":"CartItemAdditional"}) as unknown as TypedDocumentString<CartItemAdditionalFragment, unknown>;
export const CartItemFragmentDoc = new TypedDocumentString(`
fragment CartItem on StoreOffer {
...CartItemAdditional
seller {
identifier
}
Expand All @@ -3514,7 +3531,10 @@ export const CartItemFragmentDoc = new TypedDocumentString(`
...CartProductItem
}
}
fragment CartProductItem on StoreProduct {
fragment CartItemAdditional on StoreOffer {
quantity
}
fragment CartProductItem on StoreProduct {
sku
name
unitMultiplier
Expand Down Expand Up @@ -3565,7 +3585,7 @@ export const CancelOrderMutationDocument = {"__meta__":{"operationName":"CancelO
export const ProcessOrderAuthorizationMutationDocument = {"__meta__":{"operationName":"ProcessOrderAuthorizationMutation","operationHash":"8c25d37c8d6e7c20ab21bb8a4f4e6a2fe320ea8d"}} as unknown as TypedDocumentString<ProcessOrderAuthorizationMutationMutation, ProcessOrderAuthorizationMutationMutationVariables>;
export const ValidateUserDocument = {"__meta__":{"operationName":"ValidateUser","operationHash":"32f99c73c3de958b64d6bece1afe800469f54548"}} as unknown as TypedDocumentString<ValidateUserQuery, ValidateUserQueryVariables>;
export const StartRecommendationSessionDocument = {"__meta__":{"operationName":"StartRecommendationSession","operationHash":"1def6438c0cd87b85002411ac7326c221f192583"}} as unknown as TypedDocumentString<StartRecommendationSessionMutation, StartRecommendationSessionMutationVariables>;
export const ValidateCartMutationDocument = {"__meta__":{"operationName":"ValidateCartMutation","operationHash":"8199d03debb0a6751ec53d8ee8987b78d0292acb"}} as unknown as TypedDocumentString<ValidateCartMutationMutation, ValidateCartMutationMutationVariables>;
export const ValidateCartMutationDocument = {"__meta__":{"operationName":"ValidateCartMutation","operationHash":"42f1ac3788154b0097725cd3532fdc53abdce689"}} as unknown as TypedDocumentString<ValidateCartMutationMutation, ValidateCartMutationMutationVariables>;
export const ClientPickupPointsQueryDocument = {"__meta__":{"operationName":"ClientPickupPointsQuery","operationHash":"3fa04e88c811fcb5ece7206fd5aa745bdbc143a8"}} as unknown as TypedDocumentString<ClientPickupPointsQueryQuery, ClientPickupPointsQueryQueryVariables>;
export const SubscribeToNewsletterDocument = {"__meta__":{"operationName":"SubscribeToNewsletter","operationHash":"feb7005103a859e2bc8cf2360d568806fd88deba"}} as unknown as TypedDocumentString<SubscribeToNewsletterMutation, SubscribeToNewsletterMutationVariables>;
export const StartOrderEntryOperationMutationDocument = {"__meta__":{"operationName":"StartOrderEntryOperationMutation","operationHash":"78c50fbf9b85d03dbeac9b05b06405217f2ec440"}} as unknown as TypedDocumentString<StartOrderEntryOperationMutationMutation, StartOrderEntryOperationMutationMutationVariables>;
Expand Down
52 changes: 52 additions & 0 deletions packages/core/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,58 @@ Store-level UI components (not intended for the shared library) live in `src/com

> Never edit files inside `@generated/` manually — they are overwritten on every `pnpm generate` run.

### Extending `ValidateCartMutation`

`ValidateCartMutation` keeps the native cart fields in `@faststore/core` and
includes two extension fragments from the customization layer:

- `CartItemAdditional` for fields on cart items (`StoreOffer`)
- `StoreCartAdditional` for fields on the validated cart (`StoreCart`)

To add fields, extend the native GraphQL types under `src/graphql/vtex` and add
those fields to `src/customizations/src/fragments/ValidateCartMutation.ts`.
Resolvers belong in `src/customizations/src/graphql/vtex/resolvers`.

For example:

```graphql
extend type StoreOffer {
customLabel: String
}

extend type StoreCart {
total: Float
coupon: String
}
```

```graphql
fragment CartItemAdditional on StoreOffer {
customLabel
}

fragment StoreCartAdditional on StoreCart {
total
coupon
}
```

```ts
import type { StoreCartRoot } from '@faststore/api'

export default {
StoreCart: {
total: (root: StoreCartRoot) => root.__orderForm.value / 100,
coupon: (root: StoreCartRoot) =>
root.__orderForm.marketingData?.coupon ?? null,
},
}
```

The native `validateCart` resolver remains the source of truth. Cart
extensions can read the original VTEX `orderForm` through `StoreCartRoot` from
`@faststore/api`; the internal order form is not exposed as a GraphQL field.

### Managing SVG icons

Icons are loaded from a single sprite at `public/icons.svg` via the `Icon` component from `@faststore/ui`.
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
import { gql } from '@generated'

/**
* Extension points for the native ValidateCartMutation.
*
* Store projects can extend StoreOffer and StoreCart in
* `src/graphql/vtex/typeDefs` and add the corresponding fields to these
* fragments. The native cart fields remain defined and selected by the core
* mutation.
*/
export const fragment = gql(`
fragment CartItemAdditional on StoreOffer {
quantity
}

fragment StoreCartAdditional on StoreCart {
order {
orderNumber
}
}
`)
2 changes: 2 additions & 0 deletions packages/core/src/sdk/cart/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ export interface Cart extends SDKCart<CartItem> {
export const ValidateCartMutation = gql(`
mutation ValidateCartMutation($cart: IStoreCart!, $session: IStoreSession!) {
validateCart(cart: $cart, session: $session) {
...StoreCartAdditional
Comment thread
evander-corebiz marked this conversation as resolved.
order {
orderNumber
acceptedOffer {
Expand All @@ -50,6 +51,7 @@ export const ValidateCartMutation = gql(`
}

fragment CartItem on StoreOffer {
...CartItemAdditional
seller {
identifier
}
Expand Down
Loading