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
16 changes: 10 additions & 6 deletions apps/sim/app/api/auth/oauth2/shopify/store/route.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import { isSameOrigin } from '@/lib/core/utils/validation'
import { withRouteHandler } from '@/lib/core/utils/with-route-handler'
import { processCredentialDraft } from '@/lib/credentials/draft-processor'
import { safeAccountInsert } from '@/app/api/auth/oauth/utils'
import { SHOPIFY_API_VERSION } from '@/tools/shopify/constants'

const logger = createLogger('ShopifyStore')

Expand Down Expand Up @@ -46,12 +47,15 @@ export const GET = withRouteHandler(async (request: NextRequest) => {
return NextResponse.redirect(`${baseUrl}/workspace?error=shopify_invalid_domain`)
}

const shopResponse = await fetch(`https://${shopDomain}/admin/api/2024-10/shop.json`, {
headers: {
'X-Shopify-Access-Token': accessToken,
'Content-Type': 'application/json',
},
})
const shopResponse = await fetch(
`https://${shopDomain}/admin/api/${SHOPIFY_API_VERSION}/shop.json`,
{
headers: {
'X-Shopify-Access-Token': accessToken,
'Content-Type': 'application/json',
},
}
)

if (!shopResponse.ok) {
const errorText = await shopResponse.text()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest'
import { TokenServiceAccountValidationError } from '@/lib/credentials/token-service-accounts/errors'
import { validateShopifyServiceAccount } from '@/lib/credentials/token-service-accounts/validators/shopify'
import { SHOPIFY_API_VERSION } from '@/tools/shopify/constants'

const mockFetch = vi.fn()

Expand Down Expand Up @@ -48,7 +49,7 @@ describe('validateShopifyServiceAccount', () => {
normalizedDomain: 'acme-store.myshopify.com',
})
expect(mockFetch).toHaveBeenCalledWith(
'https://acme-store.myshopify.com/admin/api/2024-10/graphql.json',
`https://acme-store.myshopify.com/admin/api/${SHOPIFY_API_VERSION}/graphql.json`,
{
method: 'POST',
headers: {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,14 +9,7 @@ import type {
TokenServiceAccountFields,
TokenServiceAccountValidationResult,
} from '@/lib/credentials/token-service-accounts/server'

/**
* Pinned to match the Admin API version hardcoded in every Sim Shopify tool
* (`apps/sim/tools/shopify/*`) — bump both together. Note 2024-10 is retired;
* Shopify silently serves the oldest supported version for retired versions,
* so validation and tool runtime still hit the same effective API.
*/
const SHOPIFY_API_VERSION = '2024-10'
import { SHOPIFY_API_VERSION } from '@/tools/shopify/constants'

/**
* SSRF guard: the Admin API must target the permanent `*.myshopify.com`
Expand Down
3 changes: 2 additions & 1 deletion apps/sim/tools/shopify/adjust_inventory.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import { SHOPIFY_API_VERSION } from '@/tools/shopify/constants'
import type {
ShopifyAdjustInventoryParams,
ShopifyInventoryAdjustmentResponse,
Expand Down Expand Up @@ -48,7 +49,7 @@ export const shopifyAdjustInventoryTool: ToolConfig<

request: {
url: (params) =>
`https://${params.domain || params.shopDomain || params.idToken}/admin/api/2024-10/graphql.json`,
`https://${params.domain || params.shopDomain || params.idToken}/admin/api/${SHOPIFY_API_VERSION}/graphql.json`,
method: 'POST',
headers: (params) => {
if (!params.accessToken) {
Expand Down
3 changes: 2 additions & 1 deletion apps/sim/tools/shopify/cancel_order.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import { SHOPIFY_API_VERSION } from '@/tools/shopify/constants'
import type { ShopifyCancelOrderParams, ShopifyCancelOrderResponse } from '@/tools/shopify/types'
import { CANCEL_ORDER_OUTPUT_PROPERTIES } from '@/tools/shopify/types'
import type { ToolConfig } from '@/tools/types'
Expand Down Expand Up @@ -64,7 +65,7 @@ export const shopifyCancelOrderTool: ToolConfig<

request: {
url: (params) =>
`https://${params.domain || params.shopDomain || params.idToken}/admin/api/2024-10/graphql.json`,
`https://${params.domain || params.shopDomain || params.idToken}/admin/api/${SHOPIFY_API_VERSION}/graphql.json`,
method: 'POST',
headers: (params) => {
if (!params.accessToken) {
Expand Down
14 changes: 14 additions & 0 deletions apps/sim/tools/shopify/constants.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
/**
* The Shopify Admin API version every Sim Shopify tool targets, plus the
* credential validator in
* `@/lib/credentials/token-service-accounts/validators/shopify`. Keep this the
* single source of truth — bump it here and every caller moves in lockstep.
*
* Shopify supports each stable version for at least 12 months and forward-falls
* to the oldest supported version for retired ones, so a request never breaks
* the day a version retires — but the served version drifts silently, so pin an
* explicitly supported version and bump on the quarterly cadence.
*
* @see https://shopify.dev/docs/api/usage/versioning
*/
export const SHOPIFY_API_VERSION = '2025-10'
3 changes: 2 additions & 1 deletion apps/sim/tools/shopify/create_customer.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import { SHOPIFY_API_VERSION } from '@/tools/shopify/constants'
import type { ShopifyCreateCustomerParams, ShopifyCustomerResponse } from '@/tools/shopify/types'
import { CUSTOMER_OUTPUT_PROPERTIES } from '@/tools/shopify/types'
import type { ToolConfig } from '@/tools/types'
Expand Down Expand Up @@ -69,7 +70,7 @@ export const shopifyCreateCustomerTool: ToolConfig<

request: {
url: (params) =>
`https://${params.domain || params.shopDomain || params.idToken}/admin/api/2024-10/graphql.json`,
`https://${params.domain || params.shopDomain || params.idToken}/admin/api/${SHOPIFY_API_VERSION}/graphql.json`,
method: 'POST',
headers: (params) => {
if (!params.accessToken) {
Expand Down
3 changes: 2 additions & 1 deletion apps/sim/tools/shopify/create_fulfillment.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import { SHOPIFY_API_VERSION } from '@/tools/shopify/constants'
import type {
ShopifyCreateFulfillmentParams,
ShopifyFulfillmentResponse,
Expand Down Expand Up @@ -61,7 +62,7 @@ export const shopifyCreateFulfillmentTool: ToolConfig<

request: {
url: (params) =>
`https://${params.domain || params.shopDomain || params.idToken}/admin/api/2024-10/graphql.json`,
`https://${params.domain || params.shopDomain || params.idToken}/admin/api/${SHOPIFY_API_VERSION}/graphql.json`,
method: 'POST',
headers: (params) => {
if (!params.accessToken) {
Expand Down
3 changes: 2 additions & 1 deletion apps/sim/tools/shopify/create_product.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import { SHOPIFY_API_VERSION } from '@/tools/shopify/constants'
import type { ShopifyCreateProductParams, ShopifyProductResponse } from '@/tools/shopify/types'
import { PRODUCT_OUTPUT_PROPERTIES } from '@/tools/shopify/types'
import type { ToolConfig } from '@/tools/types'
Expand Down Expand Up @@ -63,7 +64,7 @@ export const shopifyCreateProductTool: ToolConfig<

request: {
url: (params) =>
`https://${params.domain || params.shopDomain || params.idToken}/admin/api/2024-10/graphql.json`,
`https://${params.domain || params.shopDomain || params.idToken}/admin/api/${SHOPIFY_API_VERSION}/graphql.json`,
method: 'POST',
headers: (params) => {
if (!params.accessToken) {
Expand Down
3 changes: 2 additions & 1 deletion apps/sim/tools/shopify/delete_customer.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import { SHOPIFY_API_VERSION } from '@/tools/shopify/constants'
import type { ShopifyDeleteCustomerParams, ShopifyDeleteResponse } from '@/tools/shopify/types'
import type { ToolConfig } from '@/tools/types'

Expand Down Expand Up @@ -32,7 +33,7 @@ export const shopifyDeleteCustomerTool: ToolConfig<

request: {
url: (params) =>
`https://${params.domain || params.shopDomain || params.idToken}/admin/api/2024-10/graphql.json`,
`https://${params.domain || params.shopDomain || params.idToken}/admin/api/${SHOPIFY_API_VERSION}/graphql.json`,
method: 'POST',
headers: (params) => {
if (!params.accessToken) {
Expand Down
3 changes: 2 additions & 1 deletion apps/sim/tools/shopify/delete_product.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import { SHOPIFY_API_VERSION } from '@/tools/shopify/constants'
import type { ShopifyDeleteProductParams, ShopifyDeleteResponse } from '@/tools/shopify/types'
import type { ToolConfig } from '@/tools/types'

Expand Down Expand Up @@ -32,7 +33,7 @@ export const shopifyDeleteProductTool: ToolConfig<

request: {
url: (params) =>
`https://${params.domain || params.shopDomain || params.idToken}/admin/api/2024-10/graphql.json`,
`https://${params.domain || params.shopDomain || params.idToken}/admin/api/${SHOPIFY_API_VERSION}/graphql.json`,
method: 'POST',
headers: (params) => {
if (!params.accessToken) {
Expand Down
3 changes: 2 additions & 1 deletion apps/sim/tools/shopify/get_collection.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import { SHOPIFY_API_VERSION } from '@/tools/shopify/constants'
import type { ShopifyCollectionResponse, ShopifyGetCollectionParams } from '@/tools/shopify/types'
import { COLLECTION_WITH_PRODUCTS_OUTPUT_PROPERTIES } from '@/tools/shopify/types'
import type { ToolConfig } from '@/tools/types'
Expand Down Expand Up @@ -40,7 +41,7 @@ export const shopifyGetCollectionTool: ToolConfig<

request: {
url: (params) =>
`https://${params.domain || params.shopDomain || params.idToken}/admin/api/2024-10/graphql.json`,
`https://${params.domain || params.shopDomain || params.idToken}/admin/api/${SHOPIFY_API_VERSION}/graphql.json`,
method: 'POST',
headers: (params) => {
if (!params.accessToken) {
Expand Down
3 changes: 2 additions & 1 deletion apps/sim/tools/shopify/get_customer.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import { SHOPIFY_API_VERSION } from '@/tools/shopify/constants'
import type { ShopifyCustomerResponse, ShopifyGetCustomerParams } from '@/tools/shopify/types'
import { CUSTOMER_OUTPUT_PROPERTIES } from '@/tools/shopify/types'
import type { ToolConfig } from '@/tools/types'
Expand Down Expand Up @@ -31,7 +32,7 @@ export const shopifyGetCustomerTool: ToolConfig<ShopifyGetCustomerParams, Shopif

request: {
url: (params) =>
`https://${params.domain || params.shopDomain || params.idToken}/admin/api/2024-10/graphql.json`,
`https://${params.domain || params.shopDomain || params.idToken}/admin/api/${SHOPIFY_API_VERSION}/graphql.json`,
method: 'POST',
headers: (params) => {
if (!params.accessToken) {
Expand Down
3 changes: 2 additions & 1 deletion apps/sim/tools/shopify/get_inventory_level.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import { SHOPIFY_API_VERSION } from '@/tools/shopify/constants'
import type {
ShopifyGetInventoryLevelParams,
ShopifyInventoryResponse,
Expand Down Expand Up @@ -42,7 +43,7 @@ export const shopifyGetInventoryLevelTool: ToolConfig<

request: {
url: (params) =>
`https://${params.domain || params.shopDomain || params.idToken}/admin/api/2024-10/graphql.json`,
`https://${params.domain || params.shopDomain || params.idToken}/admin/api/${SHOPIFY_API_VERSION}/graphql.json`,
method: 'POST',
headers: (params) => {
if (!params.accessToken) {
Expand Down
3 changes: 2 additions & 1 deletion apps/sim/tools/shopify/get_order.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import { SHOPIFY_API_VERSION } from '@/tools/shopify/constants'
import type { ShopifyGetOrderParams, ShopifyOrderResponse } from '@/tools/shopify/types'
import { ORDER_OUTPUT_PROPERTIES } from '@/tools/shopify/types'
import type { ToolConfig } from '@/tools/types'
Expand Down Expand Up @@ -30,7 +31,7 @@ export const shopifyGetOrderTool: ToolConfig<ShopifyGetOrderParams, ShopifyOrder

request: {
url: (params) =>
`https://${params.domain || params.shopDomain || params.idToken}/admin/api/2024-10/graphql.json`,
`https://${params.domain || params.shopDomain || params.idToken}/admin/api/${SHOPIFY_API_VERSION}/graphql.json`,
method: 'POST',
headers: (params) => {
if (!params.accessToken) {
Expand Down
3 changes: 2 additions & 1 deletion apps/sim/tools/shopify/get_product.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import { SHOPIFY_API_VERSION } from '@/tools/shopify/constants'
import type { ShopifyGetProductParams, ShopifyProductResponse } from '@/tools/shopify/types'
import { PRODUCT_OUTPUT_PROPERTIES } from '@/tools/shopify/types'
import type { ToolConfig } from '@/tools/types'
Expand Down Expand Up @@ -30,7 +31,7 @@ export const shopifyGetProductTool: ToolConfig<ShopifyGetProductParams, ShopifyP

request: {
url: (params) =>
`https://${params.domain || params.shopDomain || params.idToken}/admin/api/2024-10/graphql.json`,
`https://${params.domain || params.shopDomain || params.idToken}/admin/api/${SHOPIFY_API_VERSION}/graphql.json`,
method: 'POST',
headers: (params) => {
if (!params.accessToken) {
Expand Down
3 changes: 2 additions & 1 deletion apps/sim/tools/shopify/list_collections.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import { SHOPIFY_API_VERSION } from '@/tools/shopify/constants'
import type {
ShopifyCollectionsResponse,
ShopifyListCollectionsParams,
Expand Down Expand Up @@ -44,7 +45,7 @@ export const shopifyListCollectionsTool: ToolConfig<

request: {
url: (params) =>
`https://${params.domain || params.shopDomain || params.idToken}/admin/api/2024-10/graphql.json`,
`https://${params.domain || params.shopDomain || params.idToken}/admin/api/${SHOPIFY_API_VERSION}/graphql.json`,
method: 'POST',
headers: (params) => {
if (!params.accessToken) {
Expand Down
3 changes: 2 additions & 1 deletion apps/sim/tools/shopify/list_customers.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import { SHOPIFY_API_VERSION } from '@/tools/shopify/constants'
import type { ShopifyCustomersResponse, ShopifyListCustomersParams } from '@/tools/shopify/types'
import { CUSTOMER_OUTPUT_PROPERTIES, PAGE_INFO_OUTPUT_PROPERTIES } from '@/tools/shopify/types'
import type { ToolConfig } from '@/tools/types'
Expand Down Expand Up @@ -40,7 +41,7 @@ export const shopifyListCustomersTool: ToolConfig<

request: {
url: (params) =>
`https://${params.domain || params.shopDomain || params.idToken}/admin/api/2024-10/graphql.json`,
`https://${params.domain || params.shopDomain || params.idToken}/admin/api/${SHOPIFY_API_VERSION}/graphql.json`,
method: 'POST',
headers: (params) => {
if (!params.accessToken) {
Expand Down
3 changes: 2 additions & 1 deletion apps/sim/tools/shopify/list_inventory_items.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import { SHOPIFY_API_VERSION } from '@/tools/shopify/constants'
import {
INVENTORY_ITEM_OUTPUT_PROPERTIES,
PAGE_INFO_OUTPUT_PROPERTIES,
Expand Down Expand Up @@ -44,7 +45,7 @@ export const shopifyListInventoryItemsTool: ToolConfig<

request: {
url: (params) =>
`https://${params.domain || params.shopDomain || params.idToken}/admin/api/2024-10/graphql.json`,
`https://${params.domain || params.shopDomain || params.idToken}/admin/api/${SHOPIFY_API_VERSION}/graphql.json`,
method: 'POST',
headers: (params) => {
if (!params.accessToken) {
Expand Down
3 changes: 2 additions & 1 deletion apps/sim/tools/shopify/list_locations.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import { SHOPIFY_API_VERSION } from '@/tools/shopify/constants'
import type { ShopifyListLocationsParams, ShopifyLocationsResponse } from '@/tools/shopify/types'
import { LOCATION_OUTPUT_PROPERTIES, PAGE_INFO_OUTPUT_PROPERTIES } from '@/tools/shopify/types'
import type { ToolConfig } from '@/tools/types'
Expand Down Expand Up @@ -40,7 +41,7 @@ export const shopifyListLocationsTool: ToolConfig<

request: {
url: (params) =>
`https://${params.domain || params.shopDomain || params.idToken}/admin/api/2024-10/graphql.json`,
`https://${params.domain || params.shopDomain || params.idToken}/admin/api/${SHOPIFY_API_VERSION}/graphql.json`,
method: 'POST',
headers: (params) => {
if (!params.accessToken) {
Expand Down
3 changes: 2 additions & 1 deletion apps/sim/tools/shopify/list_orders.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import { SHOPIFY_API_VERSION } from '@/tools/shopify/constants'
import type { ShopifyListOrdersParams, ShopifyOrdersResponse } from '@/tools/shopify/types'
import { ORDER_OUTPUT_PROPERTIES, PAGE_INFO_OUTPUT_PROPERTIES } from '@/tools/shopify/types'
import type { ToolConfig } from '@/tools/types'
Expand Down Expand Up @@ -43,7 +44,7 @@ export const shopifyListOrdersTool: ToolConfig<ShopifyListOrdersParams, ShopifyO

request: {
url: (params) =>
`https://${params.domain || params.shopDomain || params.idToken}/admin/api/2024-10/graphql.json`,
`https://${params.domain || params.shopDomain || params.idToken}/admin/api/${SHOPIFY_API_VERSION}/graphql.json`,
method: 'POST',
headers: (params) => {
if (!params.accessToken) {
Expand Down
3 changes: 2 additions & 1 deletion apps/sim/tools/shopify/list_products.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import { SHOPIFY_API_VERSION } from '@/tools/shopify/constants'
import type { ShopifyListProductsParams, ShopifyProductsResponse } from '@/tools/shopify/types'
import { PAGE_INFO_OUTPUT_PROPERTIES, PRODUCT_OUTPUT_PROPERTIES } from '@/tools/shopify/types'
import type { ToolConfig } from '@/tools/types'
Expand Down Expand Up @@ -40,7 +41,7 @@ export const shopifyListProductsTool: ToolConfig<

request: {
url: (params) =>
`https://${params.domain || params.shopDomain || params.idToken}/admin/api/2024-10/graphql.json`,
`https://${params.domain || params.shopDomain || params.idToken}/admin/api/${SHOPIFY_API_VERSION}/graphql.json`,
method: 'POST',
headers: (params) => {
if (!params.accessToken) {
Expand Down
6 changes: 0 additions & 6 deletions apps/sim/tools/shopify/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -847,12 +847,6 @@ export interface ShopifyAdjustInventoryParams extends ShopifyBaseParams {
delta: number
}

interface ShopifySetInventoryParams extends ShopifyBaseParams {
inventoryItemId: string
locationId: string
quantity: number
}

// Fulfillment Tool Params
export interface ShopifyCreateFulfillmentParams extends ShopifyBaseParams {
fulfillmentOrderId: string
Expand Down
3 changes: 2 additions & 1 deletion apps/sim/tools/shopify/update_customer.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import { SHOPIFY_API_VERSION } from '@/tools/shopify/constants'
import type { ShopifyCustomerResponse, ShopifyUpdateCustomerParams } from '@/tools/shopify/types'
import { CUSTOMER_OUTPUT_PROPERTIES } from '@/tools/shopify/types'
import type { ToolConfig } from '@/tools/types'
Expand Down Expand Up @@ -69,7 +70,7 @@ export const shopifyUpdateCustomerTool: ToolConfig<

request: {
url: (params) =>
`https://${params.domain || params.shopDomain || params.idToken}/admin/api/2024-10/graphql.json`,
`https://${params.domain || params.shopDomain || params.idToken}/admin/api/${SHOPIFY_API_VERSION}/graphql.json`,
method: 'POST',
headers: (params) => {
if (!params.accessToken) {
Expand Down
3 changes: 2 additions & 1 deletion apps/sim/tools/shopify/update_order.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import { SHOPIFY_API_VERSION } from '@/tools/shopify/constants'
import type { ShopifyOrderResponse, ShopifyUpdateOrderParams } from '@/tools/shopify/types'
import { ORDER_OUTPUT_PROPERTIES } from '@/tools/shopify/types'
import type { ToolConfig } from '@/tools/types'
Expand Down Expand Up @@ -48,7 +49,7 @@ export const shopifyUpdateOrderTool: ToolConfig<ShopifyUpdateOrderParams, Shopif

request: {
url: (params) =>
`https://${params.domain || params.shopDomain || params.idToken}/admin/api/2024-10/graphql.json`,
`https://${params.domain || params.shopDomain || params.idToken}/admin/api/${SHOPIFY_API_VERSION}/graphql.json`,
method: 'POST',
headers: (params) => {
if (!params.accessToken) {
Expand Down
3 changes: 2 additions & 1 deletion apps/sim/tools/shopify/update_product.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import { SHOPIFY_API_VERSION } from '@/tools/shopify/constants'
import type { ShopifyProductResponse, ShopifyUpdateProductParams } from '@/tools/shopify/types'
import { PRODUCT_OUTPUT_PROPERTIES } from '@/tools/shopify/types'
import type { ToolConfig } from '@/tools/types'
Expand Down Expand Up @@ -69,7 +70,7 @@ export const shopifyUpdateProductTool: ToolConfig<

request: {
url: (params) =>
`https://${params.domain || params.shopDomain || params.idToken}/admin/api/2024-10/graphql.json`,
`https://${params.domain || params.shopDomain || params.idToken}/admin/api/${SHOPIFY_API_VERSION}/graphql.json`,
method: 'POST',
headers: (params) => {
if (!params.accessToken) {
Expand Down
Loading