Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
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
26 changes: 23 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -79,13 +79,13 @@ Nitrogen features two custom modules for [Shopify](https://github.com/rylanharpe

### API Integration

A minimal [GraphQL client](https://github.com/rylanharper/nitrogen/blob/master/data/shopify/utils/graphql-client.ts) is provided to seamlessly integrate with both the Shopify Storefront and Admin APIs. It uses two [server-side proxies](https://github.com/rylanharper/nitrogen/blob/master/modules/shopify/runtime/server) to handle API authentication and requests, while offering a typed interface for executing GraphQL operations.
A minimal [GraphQL client](https://github.com/rylanharper/nitrogen/blob/master/modules/shopify/runtime/resources/utils/graphql-client.ts) is provided to seamlessly integrate with both the Shopify Storefront and Admin APIs. It uses two [server-side proxies](https://github.com/rylanharper/nitrogen/blob/master/modules/shopify/runtime/server) to handle API authentication and requests, while offering a typed interface for executing GraphQL operations.

### GraphQL Operations

This project includes pre-built GraphQL [operations](https://github.com/rylanharper/nitrogen/tree/master/data/shopify/operations) for common queries and mutations frequently used in headless storefront environments. Feel free to add or remove operations that fit your project needs.
This project includes pre-built GraphQL [operations](https://github.com/rylanharper/nitrogen/tree/master/modules/shopify/runtime/resources/operations) for common queries and mutations frequently used in headless storefront environments. Feel free to add or remove operations that fit your project needs.

### Composable
### `useShopify`

To get GraphQL operations, use the `useShopify` composable:

Expand Down Expand Up @@ -160,6 +160,26 @@ actions: {
}
```

### `flattenConnection`

The Shopify module provides a `flattenConnection` utility function designed to simplify working with GraphQL connection objects. GraphQL connections often contain nested node arrays, which can make accessing the actual data cumbersome. This utility extracts and flattens these nodes, making your data easier to work with:

```ts
// Access product variant nodes
const productVariants = computed(() =>
flattenConnection(product.value?.variants) as ProductVariantFragment[]
)

// Use node data for something...
const currentVariant = computed(() =>
props.variants.find((variant) =>
variant.selectedOptions.every(({ name, value }) =>
isSizeOption(name) ? value === selectedSize.value : true,
),
),
)
```

## 🌱 Contribute

Contributions are always welcome! If you’d like to help improve this project, here’s how you can get involved:
Expand Down
4 changes: 2 additions & 2 deletions codegen.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ const config: CodegenConfig = {
// Admin
'./types/shopify-admin.d.ts': {
schema: adminApiSchema,
documents: './data/shopify/graphql/admin/**/*.ts',
documents: './modules/shopify/runtime/resources/graphql/admin/**/*.ts',
plugins: ['typescript', 'typescript-operations'],
config: {
skipTypename: true,
Expand All @@ -23,7 +23,7 @@ const config: CodegenConfig = {
// Storefront
'./types/shopify-storefront.d.ts': {
schema: storefrontApiSchema,
documents: './data/shopify/graphql/storefront/**/*.ts',
documents: './modules/shopify/runtime/resources/graphql/storefront/**/*.ts',
plugins: ['typescript', 'typescript-operations'],
config: {
skipTypename: true,
Expand Down
2 changes: 1 addition & 1 deletion modules/klaviyo/runtime/composables/use-klaviyo.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import subscribe from '@@/data/klaviyo/subscribe'
import subscribe from '../resources/http/subscribe'

export const useKlaviyo = () => ({
subscribe,
Expand Down
File renamed without changes.
2 changes: 1 addition & 1 deletion modules/klaviyo/runtime/server/klaviyo.post.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ export default defineEventHandler(async (event) => {
default:
throw createError({
statusCode: 400,
statusMessage: 'Invalid type specified.',
statusMessage: 'Invalid data type specified.',
})
}

Expand Down
14 changes: 7 additions & 7 deletions modules/shopify/runtime/composables/use-shopify.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
import cart from '@@/data/shopify/operations/cart'
import collection from '@@/data/shopify/operations/collection'
import customer from '@@/data/shopify/operations/customer'
import localization from '@@/data/shopify/operations/localization'
import product from '@@/data/shopify/operations/product'
import search from '@@/data/shopify/operations/search'
import sitemap from '@@/data/shopify/operations/sitemap'
import cart from '../resources/operations/cart'
import collection from '../resources/operations/collection'
import customer from '../resources/operations/customer'
import localization from '../resources/operations/localization'
import product from '../resources/operations/product'
import search from '../resources/operations/search'
import sitemap from '../resources/operations/sitemap'

export const useShopify = () => ({
cart,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,79 +25,79 @@ import { query } from '../utils/graphql-client'

/**
* Fetches the cart data.
* @param options - The variables for the cart query (cart ID)
* @param variables - The variables for the cart query (cart ID)
* @returns A Promise resolving to the cart data
* @see https://shopify.dev/docs/api/storefront/2025-01/queries/cart
*/
const get = async (
options: CartQueryVariables,
variables: CartQueryVariables,
): Promise<CartQuery['cart']> => {
const response = await query(CART, options)
const response = await query(CART, variables)
return response.data?.cart
}

/**
* Creates a new cart.
* @param options - The variables for the cart creation mutation (input details)
* @param variables - The variables for the cart creation mutation (input details)
* @returns A Promise resolving to the created cart
* @see https://shopify.dev/docs/api/storefront/2025-01/mutations/cartCreate
*/
const create = async (
options: CartCreateMutationVariables,
variables: CartCreateMutationVariables,
): Promise<CartCreateMutation['cartCreate']> => {
const response = await query(CART_CREATE, options)
const response = await query(CART_CREATE, variables)
return response.data?.cartCreate
}

/**
* Adds line items to the cart.
* @param options - The variables for the cart lines add mutation (cart ID, lines)
* @param variables - The variables for the cart lines add mutation (cart ID, lines)
* @returns A Promise resolving to the updated cart after adding lines
* @see https://shopify.dev/docs/api/storefront/2025-01/mutations/cartLinesAdd
*/
const addLines = async (
options: CartLinesAddMutationVariables,
variables: CartLinesAddMutationVariables,
): Promise<CartLinesAddMutation['cartLinesAdd']> => {
const response = await query(CART_LINES_ADD, options)
const response = await query(CART_LINES_ADD, variables)
return response.data?.cartLinesAdd
}

/**
* Removes line items from the cart.
* @param options - The variables for the cart lines remove mutation (cart ID, line IDs)
* @param variables - The variables for the cart lines remove mutation (cart ID, line IDs)
* @returns A Promise resolving to the updated cart after removing lines
* @see https://shopify.dev/docs/api/storefront/2025-01/mutations/cartLinesRemove
*/
const removeLines = async (
options: CartLinesRemoveMutationVariables,
variables: CartLinesRemoveMutationVariables,
): Promise<CartLinesRemoveMutation['cartLinesRemove']> => {
const response = await query(CART_LINES_REMOVE, options)
const response = await query(CART_LINES_REMOVE, variables)
return response.data?.cartLinesRemove
}

/**
* Updates line items in the cart.
* @param options - The variables for the cart lines update mutation (cart ID, lines)
* @param variables - The variables for the cart lines update mutation (cart ID, lines)
* @returns A Promise resolving to the updated cart after updating lines
* @see https://shopify.dev/docs/api/storefront/2025-01/mutations/cartLinesUpdate
*/
const updateLines = async (
options: CartLinesUpdateMutationVariables,
variables: CartLinesUpdateMutationVariables,
): Promise<CartLinesUpdateMutation['cartLinesUpdate']> => {
const response = await query(CART_LINES_UPDATE, options)
const response = await query(CART_LINES_UPDATE, variables)
return response.data?.cartLinesUpdate
}

/**
* Updates the buyer's identity in the cart.
* @param options - The variables for the cart buyer identity update mutation (cart ID, buyer identity)
* @param variables - The variables for the cart buyer identity update mutation (cart ID, buyer identity)
* @returns A Promise resolving to the updated cart with the new buyer identity
* @see https://shopify.dev/docs/api/storefront/2025-01/mutations/cartBuyerIdentityUpdate
*/
const updateBuyerIdentity = async (
options: CartBuyerIdentityUpdateMutationVariables,
variables: CartBuyerIdentityUpdateMutationVariables,
): Promise<CartBuyerIdentityUpdateMutation['cartBuyerIdentityUpdate']> => {
const response = await query(CART_BUYER_IDENTITY_UPDATE, options)
const response = await query(CART_BUYER_IDENTITY_UPDATE, variables)
return response.data?.cartBuyerIdentityUpdate
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,27 +13,27 @@ import { query } from '../utils/graphql-client'

/**
* Fetches the collection data.
* @param options - The variables for the collection query (handle, filters, etc.)
* @param variables - The variables for the collection query (handle, filters, etc.)
* @returns A Promise resolving to the collection data
* @see https://shopify.dev/docs/api/storefront/2025-01/queries/collection
*/
const get = async (
options: CollectionQueryVariables,
variables: CollectionQueryVariables,
): Promise<CollectionQuery['collection']> => {
const response = await query(COLLECTION, options)
const response = await query(COLLECTION, variables)
return response.data?.collection
}

/**
* Fetches the collection filter data.
* @param options - The variables for the collection query (handle)
* @param variables - The variables for the collection query (handle)
* @returns A Promise resolving to the collection filters data
* @see https://shopify.dev/docs/api/storefront/2025-01/queries/collection
*/
const getFilters = async (
options: CollectionFiltersQueryVariables,
variables: CollectionFiltersQueryVariables,
): Promise<CollectionFiltersQuery['collection']> => {
const response = await query(COLLECTION_FILTERS, options)
const response = await query(COLLECTION_FILTERS, variables)
return response.data?.collection
}

Expand Down
Loading