[System] You are an expert VTEX IO developer. You specialize in building VTEX Store Framework apps, React components, GraphQL APIs, and Node.js services for e-commerce platforms.

[User] Show me the implementation of checkout-graphql/node/resolvers/items.ts from the checkout-graphql VTEX app.

[Assistant]
Here's the implementation:

```typescript
import { Logger } from '@vtex/api'

import { SearchGraphQL } from '../clients/searchGraphQL'
import { fixImageUrl } from '../utils/image'
import { addOptionsForItems } from '../utils/attachmentsHelpers'
import { generateSubscriptionDataEntry } from '../utils/subscriptions'
import { OrderFormIdArgs } from '../utils/args'

const getProductInfo = async (
  item: OrderFormItem,
  searchGraphQL: SearchGraphQL,
  logger: Logger
) => {
  try {
    const response = await searchGraphQL.product(item.productId)

    return response
  } catch (err) {
    if (Math.floor(Math.random() * 100) === 0) {
      logger.warn({
        message: 'Error when communicating with vtex.search-graphql',
        error: err,
      })
    }
    return null
  }
}

const getVariations = (skuId: string, skuList: any[]) => {
  const matchedSku = skuList.find((sku: any) => sku.itemId === skuId)
  if (!matchedSku) {
    return []
  }
  return matchedSku.variations.map((variation: any) => ({
    fieldName: variation.name,
    fieldValues: variation.values || [],
  }))
}

export const root = {
  Item: {
    name: async (item: OrderFormItem, _: unknown, ctx: Context) => {
      const {
        vtex: { logger },
        clients: { searchGraphQL },
      } = ctx

      const product = await getProductInfo(item, searchGraphQL, logger)

      return product?.productName ?? item.name
    },
    skuName: async (item: OrderFormItem, _: unknown, ctx: Context) => {
      const {
        vtex: { logger },
        clients: { searchGraphQL },
      } = ctx

      const product = await getProductInfo(item, searchGraphQL, logger)

      return (
        product?.items.find(({ itemId }) => itemId === item.id)?.name ??
        item.skuName
      )
    },
    imageUrls: (item: OrderFormItem, _: unknown, ctx: Context) => {
      return fixImageUrl(item.imageUrl, ctx.vtex.platform)
    },
    skuSpecifications: async (
      item: OrderFormItem,
      _: unknown,
      ctx: Context
    ) => {
      const {
        vtex: { logger },
        clients: { searchGraphQL },
      } = ctx

      const product = await getProductInfo(item, searchGraphQL, logger)

      return getVariations(item.id, product?.items ?? [])
    },
    productSpecificationGroups: async (
      item: OrderFormItem,
      _: unknown,
      ctx: Context
    ) => {
      const {
        vtex: { logger },
        clients: { searchGraphQL },
      } = ctx

      const product = await getProductInfo(item, searchGraphQL, logger)

      return product?.specificationGroups ?? []
    },
  },
}

export const mutations = {
  addToCart: async (
    _: unknown,
    args: {
      items: OrderFormItemInput[]
      marketingData: Partial<OrderFormMarketingData>
      salesChannel?: string
      allowedOutdatedData?: string[]
    } & OrderFormIdArgs,
    ctx: Context
  ): Promise<CheckoutOrderForm> => {
    const {
      clients,
      vtex,
      vtex: { logger },
    } = ctx
    const {
      orderFormId = vtex.orderFormId,
      items,
      marketingData = {},
      salesChannel,
      allowedOutdatedData,
    } = args

    const { checkout } = clients
    const shouldUpdateMarketingData =
      Object.keys(marketingData ?? {}).length > 0

    const { items: previousItems } = await checkout.orderForm(orderFormId!)
    const cleanItems = items.map(
      ({ options, index, uniqueId, ...rest }) => rest
    )

    const withOptions = items
      .map((item, currentIndex) => ({
        ...item,
        index: item.index ?? currentIndex,
      }))
      .filter(({ options }) => !!options && options.length > 0)

    /**
     * Always be sure to make these requests in the same order you use
     * while spreading their properties, since the second one will always
     * contain the most recent orderForm.
     */
    let newOrderForm = await checkout.addItem(
      orderFormId!,
      cleanItems,
      salesChannel,
      allowedOutdatedData
    )

    try {
      if (shouldUpdateMarketingData) {
        newOrderForm = await checkout.updateOrderFormMarketingData(
          orderFormId!,
          marketingData
        )
      }
    } catch (err) {
      logger.error({
        message: 'Error when updating orderForm marketing data.',
        id: orderFormId,
        graphqlArgs: marketingData,
        originalError: err,
      })
    }

    if (withOptions && withOptions.length > 0) {
      await addOptionsForItems(
        withOptions,
        checkout,
        {
          ...newOrderForm,
          orderFormId: orderFormId!,
        },
        previousItems
      )

      const subscriptionOptionsOnly = withOptions
        .map(itemWithOptions => ({
          itemIndex: (itemWithOptions.index as number) + previousItems.length,
          options: itemWithOptions.options as AssemblyOptionInput[],
        }))
        .filter(item =>
          item.options.some(option =>
            option.assemblyId.includes('vtex.subscription')
          )
        )

      const newSubscriptionDataEntries = generateSubscriptionDataEntry(
        subscriptionOptionsOnly
      )

      if (newSubscriptionDataEntries.length > 0) {
        const updatedSubscriptionData = {
          subscriptions: newOrderForm.subscriptionData
            ? newOrderForm.subscriptionData.subscriptions.concat(
                newSubscriptionDataEntries
              )
            : newSubscriptionDataEntries,
        }

        await checkout.updateSubscriptionDataField(
          orderFormId!,
          updatedSubscriptionData
        )
      }

      return checkout.orderForm(orderFormId!)
    }

    return newOrderForm
  },

  updateItems: async (
    _: unknown,
    args: {
      orderItems: OrderFormItemInput[]
      splitItem: boolean
      allowedOutdatedData?: string[]
    } & OrderFormIdArgs,
    ctx: Context
  ): Promise<CheckoutOrderForm> => {
    const { clients, vtex } = ctx
    const {
      orderFormId = vtex.orderFormId,
      orderItems,
      splitItem,
      allowedOutdatedData,
    } = args
    const { checkout } = clients

    const cleanItems = orderItems.map(({ id, ...rest }) => rest)

    // Validating subscriptions
    let subscriptions
    if (orderItems.length === 1 && orderItems[0].index !== undefined) {
      const { items } = await checkout.orderForm(orderFormId!)
      const itemToUpdate = items[orderItems[0].index]

      subscriptions = itemToUpdate.attachments?.some(attachment =>
        attachment.name?.includes('vtex.subscription')
      )
    }

    if (cleanItems.some((item: OrderFormItemInput) => !item.index)) {
      const orderForm = await checkout.orderForm(orderFormId!)

      const idToIndex = orderForm.items.reduce(
        (acc: Record<string, number>, item: OrderFormItem, index: number) => {
          if (acc[item.uniqueId] === undefined) {
            acc[item.uniqueId] = index
          }
          return acc
        },
        {} as Record<string, number>
      )

      cleanItems.forEach((item: OrderFormItemInput) => {
        if (!item.index && item.uniqueId) {
          item.index = idToIndex[item.uniqueId]
        }
      })
    }

    const newOrderForm = await clients.checkout.updateItems(
      orderFormId!,
      cleanItems,
      subscriptions ? false : splitItem,
      allowedOutdatedData
    )

    return newOrderForm
  },
  addItemOffering: async (
    _: unknown,
    args: { offeringInput: OfferingInput } & OrderFormIdArgs,
    ctx: Context
  ): Promise<CheckoutOrderForm> => {
    const { clients, vtex } = ctx
    const { offeringInput, orderFormId = vtex.orderFormId } = args

    const newOrderForm = await clients.checkout.addItemOffering(
      orderFormId!,
      offeringInput.itemIndex,
      offeringInput.offeringId,
      offeringInput.offeringInfo
    )

    return newOrderForm
  },
  removeItemOffering: async (
    _: unknown,
    args: { offeringInput: OfferingInput } & OrderFormIdArgs,
    ctx: Context
  ): Promise<CheckoutOrderForm> => {
    const { clients, vtex } = ctx
    const { offeringInput, orderFormId = vtex.orderFormId } = args

    const newOrderForm = await clients.checkout.removeItemOffering(
      orderFormId!,
      offeringInput.itemIndex,
      offeringInput.offeringId
    )

    return newOrderForm
  },
  addBundleItemAttachment: async (
    _: unknown,
    args: {
      bundleItemAttachmentInput: BundleItemAttachmentInput
    } & OrderFormIdArgs,
    ctx: Context
  ): Promise<CheckoutOrderForm> => {
    const { clients, vtex } = ctx
    const { bundleItemAttachmentInput, orderFormId = vtex.orderFormId } = args

    const newOrderForm = await clients.checkout.addBundleItemAttachment(
      orderFormId!,
      bundleItemAttachmentInput.itemIndex,
      bundleItemAttachmentInput.bundleItemId,
      bundleItemAttachmentInput.attachmentName,
      bundleItemAttachmentInput.attachmentContent
    )

    return newOrderForm
  },
  removeBundleItemAttachment: async (
    _: unknown,
    args: {
      bundleItemAttachmentInput: BundleItemAttachmentInput
    } & OrderFormIdArgs,
    ctx: Context
  ) => {
    const { clients, vtex } = ctx
    const { bundleItemAttachmentInput, orderFormId = vtex.orderFormId } = args

    const { data } = await clients.checkout.removeBundleItemAttachment(
      orderFormId!,
      bundleItemAttachmentInput.itemIndex,
      bundleItemAttachmentInput.bundleItemId,
      bundleItemAttachmentInput.attachmentName,
      bundleItemAttachmentInput.attachmentContent
    )

    return data
  },
  setManualPrice: async (
    _: unknown,
    args: { input: { itemIndex: number; price: number } } & OrderFormIdArgs,
    ctx: Context
  ): Promise<CheckoutOrderForm> => {
    const { clients, vtex } = ctx
    const {
      input: { itemIndex, price },
      orderFormId = vtex.orderFormId,
    } = args

    const newOrderForm = await clients.checkoutAdmin.setManualPrice(
      orderFormId!,
      itemIndex,
      price
    )

    return newOrderForm
  },
}

interface OfferingInput {
  itemIndex: number
  offeringId: string
  offeringInfo: unknown
}

interface BundleItemAttachmentInput {
  itemIndex: number
  bundleItemId: string
  attachmentName: string
  attachmentContent: unknown
}

```


[System] You are an expert VTEX IO developer. You specialize in building VTEX Store Framework apps, React components, GraphQL APIs, and Node.js services for e-commerce platforms.

[User] Show me the implementation of checkout-graphql/node/resolvers/messages.ts from the checkout-graphql VTEX app.

[Assistant]
Here's the implementation:

```typescript
const COUPON_CODES = ['couponExpired', 'couponNotFound']
const IGNORED_CODES = ['cannotBeDelivered']

export const fillMessages = (messages: Message[]) => {
  const orderFormMessages = messages.reduce<OrderFormMessages>(
    (acc, message) => {
      if (COUPON_CODES.includes(message.code)) {
        acc.couponMessages.push(message)
      } else if (!IGNORED_CODES.includes(message.code)) {
        acc.generalMessages.push(message)
      }
      return acc
    },
    {
      couponMessages: [],
      generalMessages: [],
    }
  )

  return orderFormMessages
}

```


[System] You are an expert VTEX IO developer. You specialize in building VTEX Store Framework apps, React components, GraphQL APIs, and Node.js services for e-commerce platforms.

[User] Show me the implementation of checkout-graphql/node/resolvers/shipping.ts from the checkout-graphql VTEX app.

[Assistant]
Here's the implementation:

```typescript
import {
  getShippingData,
  selectShippingOption,
  selectAddress,
} from '../utils/shipping'
import { AddressType, DELIVERY, PICKUP_IN_POINT } from '../constants'
import { OrderFormIdArgs } from '../utils/args'

const addressTypes = new Set<string>([
  AddressType.COMMERCIAL,
  AddressType.GIFT_REGISTRY,
  AddressType.INSTORE,
  AddressType.PICKUP,
  AddressType.RESIDENTIAL,
  AddressType.SEARCH,
])

export const root = {
  Address: {
    addressType: ({ addressType }: CheckoutAddress) => {
      if (addressTypes.has(addressType)) {
        return addressType as AddressType
      }

      return null
    },
  },
}

export const mutations = {
  estimateShipping: async (
    _: unknown,
    args: { address: CheckoutAddress } & OrderFormIdArgs,
    ctx: Context
  ) => {
    const { clients, vtex } = ctx
    const { checkout } = clients
    const { orderFormId = vtex.orderFormId, address } = args

    const orderForm = await checkout.orderForm(orderFormId!)
    const logisticsInfo =
      orderForm.shippingData && orderForm.shippingData.logisticsInfo
    const shippingData = getShippingData(address, logisticsInfo)

    const newOrderForm = await checkout.updateOrderFormShipping(orderFormId!, {
      ...shippingData,
      clearAddressIfPostalCodeNotFound: false,
    })

    return newOrderForm
  },

  selectDeliveryOption: async (
    _: unknown,
    args: { deliveryOptionId: string } & OrderFormIdArgs,
    ctx: Context
  ) => {
    const { clients, vtex } = ctx
    const { checkout } = clients
    const { orderFormId = vtex.orderFormId, deliveryOptionId } = args

    const orderForm = await checkout.orderForm(orderFormId!)
    const newShippingData = selectShippingOption({
      slaId: deliveryOptionId,
      shippingData: orderForm.shippingData,
      deliveryChannel: DELIVERY,
    })

    const newOrderForm = await checkout.updateOrderFormShipping(orderFormId!, {
      ...newShippingData,
      clearAddressIfPostalCodeNotFound: false,
    })

    return newOrderForm
  },

  selectPickupOption: async (
    _: unknown,
    args: { pickupOptionId: string; itemId: string } & OrderFormIdArgs,
    ctx: Context
  ) => {
    const { clients, vtex } = ctx
    const { checkout } = clients
    const { orderFormId = vtex.orderFormId, pickupOptionId, itemId } = args

    const orderForm = await checkout.orderForm(orderFormId!)
    const newShippingData = selectShippingOption({
      slaId: pickupOptionId,
      itemId,
      shippingData: orderForm.shippingData,
      deliveryChannel: PICKUP_IN_POINT,
    })

    const newOrderForm = await checkout.updateOrderFormShipping(orderFormId!, {
      ...newShippingData,
      clearAddressIfPostalCodeNotFound: false,
    })

    return newOrderForm
  },

  updateSelectedAddress: async (
    _: unknown,
    args: { input: CheckoutAddress } & OrderFormIdArgs,
    ctx: Context
  ) => {
    const {
      clients: { checkout },
      vtex,
    } = ctx
    const { orderFormId = vtex.orderFormId, input } = args

    const orderForm = await checkout.orderForm(orderFormId!)

    const newShippingData = selectAddress({
      address: input,
      shippingData: orderForm.shippingData,
    })

    const newOrderForm = await checkout.updateOrderFormShipping(orderFormId!, {
      ...newShippingData,
      clearAddressIfPostalCodeNotFound: false,
    })

    return newOrderForm
  },
}

```


[System] You are an expert VTEX IO developer. You specialize in building VTEX Store Framework apps, React components, GraphQL APIs, and Node.js services for e-commerce platforms.

[User] Show me the implementation of checkout-graphql/node/resolvers/orderForm.ts from the checkout-graphql VTEX app.

[Assistant]
Here's the implementation:

```typescript
import { prop, propOr, compose } from 'ramda'
import { QueryOrderFormArgs } from 'vtex.checkout-graphql'

import { parseCookie } from '../utils'
import { fillMessages } from './messages'
import { getShippingInfo } from '../utils/shipping'
import {
  isShippingValid,
  isProfileValid,
  isPaymentValid,
} from '../utils/validation'
import {
  ASPXAUTH_COOKIE,
  CHECKOUT_COOKIE,
  OWNERSHIP_COOKIE,
  VTEX_SESSION,
} from '../constants'
import { OrderFormIdArgs } from '../utils/args'

interface StoreSettings {
  enableOrderFormOptimization: boolean
  storeName: string
  titleTag: string
  metaTagDescription: string
  metaTagKeywords: string
  enableCriticalCSS: boolean
}

const ALL_SET_COOKIES = [CHECKOUT_COOKIE, ASPXAUTH_COOKIE, OWNERSHIP_COOKIE]

const filterAllowedCookies = (setCookies: string[], allowList: string[]) => {
  return setCookies.filter(setCookie => {
    const [key] = setCookie.split('=')
    return allowList.includes(key)
  })
}

const replaceDomain = (host: string) => (cookie: string) =>
  cookie.replace(/domain=.+?(;|$)/, `domain=${host};`)

const isCallCenterOperator = async (orderFormId: string, ctx: Context) => {
  const {
    clients: { customSession },
    vtex: { logger },
    cookies,
  } = ctx

  const sessionCookie = cookies.get(VTEX_SESSION)

  if (sessionCookie === undefined) {
    logger.warn(
      `Can't request session details: "${VTEX_SESSION}" is undefined. ofid=${orderFormId}`
    )

    return false
  }

  const { sessionData } = await customSession.getSession(sessionCookie, ['*'])

  return sessionData?.namespaces?.impersonate?.canImpersonate?.value === 'true'
}

export const root = {
  OrderForm: {
    id: prop('orderFormId'),
    marketingData: propOr({}, 'marketingData'),
    storePreferencesData: propOr({}, 'storePreferencesData'),
    allowManualPrice: async (
      orderForm: CheckoutOrderForm,
      _: unknown,
      ctx: Context
    ) => {
      const isCallCenter = await isCallCenterOperator(
        orderForm.orderFormId,
        ctx
      )

      if (!isCallCenter) {
        return false
      }

      const adminOrderForm = await ctx.clients.checkoutAdmin.orderForm()

      return adminOrderForm?.allowManualPrice || orderForm.allowManualPrice
    },
    userType: async (
      orderForm: CheckoutOrderForm,
      __: unknown,
      ctx: Context
    ) => {
      const isCallCenter = await isCallCenterOperator(
        orderForm.orderFormId,
        ctx
      )

      if (isCallCenter) {
        return 'CALL_CENTER_OPERATOR'
      }

      return 'STORE_USER'
    },
    messages: (orderForm: CheckoutOrderForm, _: unknown, ctx: Context) => {
      const {
        clients: { checkout },
      } = ctx

      const newMessages = fillMessages(orderForm.messages)

      if (orderForm.messages && orderForm.messages.length > 0) {
        checkout.clearMessages(orderForm.orderFormId)
      }

      return newMessages
    },
    clientProfileData: async (
      orderForm: CheckoutOrderForm,
      _: unknown,
      ctx: Context
    ) => {
      if (!orderForm.clientProfileData) {
        return null
      }

      const isValid = await isProfileValid(
        orderForm,
        orderForm.clientProfileData,
        ctx
      )

      return {
        ...orderForm.clientProfileData,
        isValid,
      }
    },
    shipping: async (
      orderForm: CheckoutOrderForm,
      _: unknown,
      ctx: Context
    ) => {
      const shippingInfo = await getShippingInfo({
        orderForm,
        clients: ctx.clients,
      })

      const isValid = await isShippingValid(orderForm, shippingInfo, ctx)

      return {
        ...shippingInfo,
        isValid,
      }
    },
    paymentData: (orderForm: CheckoutOrderForm) => {
      const isValid = isPaymentValid(orderForm.paymentData)

      return {
        ...orderForm.paymentData,
        isValid,
      }
    },
  },
  ClientPreferencesData: {
    optInNewsletter: prop('optinNewsLetter'),
  },
}

// Ported from store-graphql
// https://github.com/vtex-apps/store-graphql/blob/master/node/resolvers/checkout/index.ts#L185
export async function syncWithStoreLocale(
  orderForm: CheckoutOrderForm,
  cultureInfo: string,
  checkout: Context['clients']['checkout']
) {
  const clientPreferencesData = orderForm.clientPreferencesData || {
    locale: cultureInfo,
  }

  const shouldUpdateClientPreferencesData =
    cultureInfo &&
    clientPreferencesData.locale &&
    cultureInfo !== clientPreferencesData.locale

  if (shouldUpdateClientPreferencesData) {
    const newClientPreferencesData = {
      ...clientPreferencesData,
    }

    newClientPreferencesData.locale = cultureInfo

    try {
      return await checkout.updateOrderFormClientPreferencesData(
        orderForm.orderFormId,
        newClientPreferencesData
      )
    } catch (e) {
      console.error(e)

      return orderForm
    }
  }

  return orderForm
}

export async function forwardCheckoutCookies(
  rawHeaders: Record<string, any>,
  ctx: Context,
  allowList: string[] = ALL_SET_COOKIES
) {
  const responseSetCookies: string[] = rawHeaders?.['set-cookie'] || []

  const host = ctx.get('x-forwarded-host')
  const forwardedSetCookies = filterAllowedCookies(
    responseSetCookies,
    allowList
  )
  const parseAndClean = compose(parseCookie, replaceDomain(host))
  const cleanCookies = forwardedSetCookies.map(parseAndClean)
  cleanCookies.forEach(({ name, value, options }) => {
    if (options.secure && !ctx.cookies.secure) {
      ctx.cookies.secure = true
    }

    ctx.cookies.set(name, value, options)
  })
}

export const queries = {
  orderForm: async (
    _: unknown,
    args: QueryOrderFormArgs,
    ctx: Context
  ): Promise<CheckoutOrderForm> => {
    const { clients, vtex } = ctx
    const { orderFormId = vtex.orderFormId, refreshOutdatedData } = args

    let { data: newOrderForm, headers } = await clients.checkout.orderFormRaw(
      orderFormId ?? undefined,
      refreshOutdatedData ?? undefined
    )

    const hasBrokenCookie = newOrderForm?.clientProfileData?.email?.startsWith(
      'vrn--vtexsphinx--aws-us-east-1'
    )

    if (hasBrokenCookie) {
      vtex.logger.info({ message: 'Broken order form', orderFormId })
      const obj = await clients.checkoutNoCookies.orderFormRaw(undefined, true)
      newOrderForm = obj.data
      headers = obj.headers
    }

    newOrderForm = await syncWithStoreLocale(
      newOrderForm,
      vtex.segment!.cultureInfo,
      clients.checkout
    )

    /**
     * In case the enableOrderFormOptimization setting is enabled in the store,
     * this will be the only `orderForm` query performed in the client. So no
     * 'checkout.vtex.com' cookie would have been set. Otherwise vtex.store-graphql
     * would've already set this cookie and this resolver should not overwrite it.
     */
    const storeSettings: StoreSettings = await clients.apps.getAppSettings(
      'vtex.store@2.x'
    )

    if (storeSettings.enableOrderFormOptimization) {
      forwardCheckoutCookies(headers, ctx)
    }

    return newOrderForm
  },
}

interface MutationUpdateOrderFormProfileArgs {
  input: UserProfileInput
}

interface MutationUpdateClientPreferencesDataArgs {
  input: ClientPreferencesDataInput
}

interface MutationUpdateOrderFormPaymentArgs {
  input: PaymentDataInput
}

interface MutationUpdateOrderFormOpenTextField {
  input: OpenTextField
}

interface MutationUpdateOrderFormMarketingData {
  input: OrderFormMarketingData
}

export const mutations = {
  updateOrderFormProfile: async (
    _: unknown,
    args: MutationUpdateOrderFormProfileArgs & OrderFormIdArgs,
    ctx: Context
  ): Promise<CheckoutOrderForm> => {
    const {
      clients: { checkout },
      vtex,
    } = ctx
    const { input, orderFormId = vtex.orderFormId } = args

    const orderFormWithProfile = await checkout.updateOrderFormProfile(
      orderFormId!,
      input,
      ctx
    )

    return orderFormWithProfile
  },
  updateClientPreferencesData: async (
    _: unknown,
    args: MutationUpdateClientPreferencesDataArgs & OrderFormIdArgs,
    ctx: Context
  ) => {
    const {
      clients: { checkout },
      vtex,
    } = ctx
    const { orderFormId = vtex.orderFormId, input } = args

    const updatedOrderForm = await checkout.updateOrderFormClientPreferencesData(
      orderFormId!,
      {
        optinNewsLetter: input.optInNewsletter,
        locale: input.locale,
      }
    )

    return updatedOrderForm
  },
  updateOrderFormPayment: async (
    _: unknown,
    args: MutationUpdateOrderFormPaymentArgs & OrderFormIdArgs,
    ctx: Context
  ): Promise<CheckoutOrderForm> => {
    const {
      clients: { checkout },
      vtex,
    } = ctx
    const { orderFormId = vtex.orderFormId, input } = args

    const orderFormWithPayments = await checkout.updateOrderFormPayment(
      orderFormId!,
      input
    )

    return orderFormWithPayments
  },
  updateItemsOrdination: async (
    _: unknown,
    args: ItemsOrdinationArgs & OrderFormIdArgs,
    ctx: Context
  ): Promise<CheckoutOrderForm> => {
    const {
      clients: { checkout },
      vtex,
    } = ctx
    const { ascending, criteria, orderFormId = vtex.orderFormId } = args

    const changeItemsOrdination = await checkout.updateItemsOrdination(
      orderFormId!,
      ascending,
      criteria
    )

    return changeItemsOrdination
  },

  clearOrderFormMessages: async (
    _: unknown,
    args: OrderFormIdArgs,
    ctx: Context
  ) => {
    const {
      clients: { checkout },
      vtex,
    } = ctx
    const { orderFormId = vtex.orderFormId } = args

    const updatedOrderForm = await checkout.clearMessages(orderFormId!)

    return updatedOrderForm
  },

  updateOrderFormOpenTextField: async (
    _: unknown,
    args: MutationUpdateOrderFormOpenTextField & OrderFormIdArgs,
    ctx: Context
  ): Promise<CheckoutOrderForm> => {
    const {
      clients: { checkout },
      vtex,
    } = ctx
    const { orderFormId = vtex.orderFormId, input } = args

    const orderFormWithOpenTextField = await checkout.updateOrderFromOpenTextField(
      orderFormId!,
      input
    )

    return orderFormWithOpenTextField
  },

  updateOrderFormMarketingData: async (
    _: unknown,
    args: MutationUpdateOrderFormMarketingData & OrderFormIdArgs,
    ctx: Context
  ): Promise<CheckoutOrderForm> => {
    const {
      clients: { checkout },
      vtex,
    } = ctx

    const { orderFormId = vtex.orderFormId, input } = args

    const updatedOrderForm = await checkout.updateOrderFormMarketingData(
      orderFormId!,
      input
    )

    return updatedOrderForm
  },
}

```


[System] You are an expert VTEX IO developer. You specialize in building VTEX Store Framework apps, React components, GraphQL APIs, and Node.js services for e-commerce platforms.

[User] Show me the implementation of checkout-graphql/node/resolvers/sla.ts from the checkout-graphql VTEX app.

[Assistant]
Here's the implementation:

```typescript
import { getShippingInfo } from '../utils/shipping'

export const queries = {
  shippingSLA: async (_: any, args: any, ctx: Context) => {
    const { checkout } = ctx.clients
    const shippingData = (await checkout.simulation(
      args
    )) as CheckoutOrderForm['shippingData']

    // Here we mock an Order Form object to use getShippingInfo
    const orderForm = {
      orderFormId: '',
      value: 0,
      shippingData: {
        ...shippingData,
        selectedAddresses: [],
      },
      totalizers: [],
    } as Pick<
      CheckoutOrderForm,
      'shippingData' | 'totalizers' | 'orderFormId' | 'value'
    >

    return getShippingInfo({ clients: ctx.clients, orderForm })
  },
}

```


[System] You are an expert VTEX IO developer. You specialize in building VTEX Store Framework apps, React components, GraphQL APIs, and Node.js services for e-commerce platforms.

[User] Show me the implementation of checkout-graphql/node/resolvers/coupon.ts from the checkout-graphql VTEX app.

[Assistant]
Here's the implementation:

```typescript
import { OrderFormIdArgs } from '../utils/args'

export const mutations = {
  insertCoupon: async (
    _: unknown,
    args: { text: string } & OrderFormIdArgs,
    ctx: Context
  ) => {
    const { clients, vtex } = ctx
    const { orderFormId = vtex.orderFormId } = args

    const newOrderForm = await clients.checkout.insertCoupon(
      orderFormId!,
      args.text
    )

    return newOrderForm
  },
}

```


[System] You are an expert VTEX IO developer. You specialize in building VTEX Store Framework apps, React components, GraphQL APIs, and Node.js services for e-commerce platforms.

[User] Show me the implementation of checkout-graphql/node/resolvers/profile.ts from the checkout-graphql VTEX app.

[Assistant]
Here's the implementation:

```typescript
export const queries = {
  checkoutProfile: async (
    _: unknown,
    { email }: { email: string },
    ctx: Context
  ): Promise<CheckoutProfile> => {
    const {
      clients,
    } = ctx

    const profile = await clients.checkout.getProfile(email)

    return profile
  },
}

```


[System] You are an expert VTEX IO developer. You specialize in building VTEX Store Framework apps, React components, GraphQL APIs, and Node.js services for e-commerce platforms.

[User] Show me the implementation of checkout-graphql/node/resolvers/index.ts from the checkout-graphql VTEX app.

[Assistant]
Here's the implementation:

```typescript
import { mutations as couponMutations } from './coupon'
import { root as itemRoot, mutations as itemMutations } from './items'
import {
  root as orderFormRoot,
  queries as orderFormQueries,
  mutations as orderFormMutations,
} from './orderForm'
import {
  root as shippingRoot,
  mutations as shippingMutations,
} from './shipping'
import {
  queries as paymentQueries,
  mutations as paymentMutations,
} from './payment'
import { queries as profileQueries } from './profile'
import { queries as slaQueries } from './sla'

export const resolvers = {
  MarketingData: {
    coupon: (marketingData: OrderFormMarketingData) => {
      return marketingData.coupon ?? ''
    },
    utmCampaign: (marketingData: OrderFormMarketingData) => {
      return marketingData.utmCampaign ?? ''
    },
    utmSource: (marketingData: OrderFormMarketingData) => {
      return marketingData.utmSource ?? ''
    },
    utmMedium: (marketingData: OrderFormMarketingData) => {
      return marketingData.utmMedium ?? ''
    },
    utmiCampaign: (marketingData: OrderFormMarketingData) => {
      return marketingData.utmiCampaign ?? ''
    },
    utmiPart: (marketingData: OrderFormMarketingData) => {
      return marketingData.utmiPart ?? ''
    },
    utmiPage: (marketingData: OrderFormMarketingData) => {
      return marketingData.utmipage ?? ''
    },
  },
  ...orderFormRoot,
  ...shippingRoot,
  ...itemRoot,
  Mutation: {
    ...couponMutations,
    ...itemMutations,
    ...shippingMutations,
    ...paymentMutations,
    ...orderFormMutations,
  },
  Query: {
    ...orderFormQueries,
    ...paymentQueries,
    ...profileQueries,
    ...slaQueries,
  },
}

```


[System] You are an expert VTEX IO developer. You specialize in building VTEX Store Framework apps, React components, GraphQL APIs, and Node.js services for e-commerce platforms.

[User] Show me the implementation of checkout-graphql/node/__tests__/shipping.test.ts from the checkout-graphql VTEX app.

[Assistant]
Here's the implementation:

```typescript
import {
  deliveryAddress,
  ORDER_FORM_WITH_DIFFERENT_SLAS_BETWEEN_LOGISTICS_INFO,
  ORDER_FORM_WITH_DUPLICATED_SLAS_WITH_DIFFERENT_DELIVERY_IDS,
  ORDER_FORM_WITH_EMPTY_LOGISTICS_INFO,
  ORDER_FORM_WITH_EMPTY_SHIPPING_DATA,
  ORDER_FORM_WITH_PICKUPS,
  ORDER_FORM_WITH_SCHEDULED_DELIVERY,
  ORDER_FORM_WITH_SCHEDULED_DELIVERY_AND_PICKUPS,
  ORDER_FORM_WITH_UNAVAILABLE_ITEM_LOGISTICS_INFO,
  clients,
} from '../__fixtures__/shipping'
import { getShippingInfo } from '../utils/shipping'

describe('Shipping Resolvers', () => {
  describe('getShippingInfo', () => {
    it('should get shipping info handling empty shippingData', async () => {
      const expectedResult = {
        availableAddresses: [],
        countries: [],
        deliveryOptions: [],
        pickupOptions: [],
        selectedAddress: undefined,
      }

      expect(
        await getShippingInfo({
          clients,
          orderForm: ORDER_FORM_WITH_EMPTY_SHIPPING_DATA,
        })
      ).toEqual(expectedResult)
    })

    it('should get shipping info handling empty logisticsInfo', async () => {
      const expectedResult = {
        availableAddresses: [deliveryAddress],
        countries: ['BRA', 'GBR'],
        deliveryOptions: [],
        pickupOptions: [],
        selectedAddress: deliveryAddress,
      }

      expect(
        await getShippingInfo({
          clients,
          orderForm: ORDER_FORM_WITH_EMPTY_LOGISTICS_INFO,
        })
      ).toEqual(expectedResult)
    })

    it('should get shipping info', async () => {
      const expectedResult = {
        availableAddresses: [deliveryAddress],
        countries: ['BRA', 'GBR'],
        deliveryOptions: [
          {
            deliveryChannel: 'delivery',
            estimate: '1db',
            id: 'delivery-SLA',
            isSelected: true,
            price: 100,
            sla: {
              availableDeliveryWindows: [],
              deliveryChannel: 'delivery',
              deliveryIds: [],
              deliveryWindow: null,
              id: 'delivery-SLA',
              listPrice: 0,
              lockTTL: null,
              name: 'delivery-SLA',
              pickupDistance: 0,
              pickupPointId: null,
              pickupStoreInfo: {
                additionalInfo: null,
                address: null,
                dockId: null,
                friendlyName: null,
                isPickupStore: false,
              },
              polygonName: null,
              price: 100,
              shippingEstimate: '1db',
              shippingEstimateDate: null,
              tax: 0,
            },
          },
        ],
        pickupOptions: [
          {
            additionalInfo: null,
            address: null,
            deliveryChannel: 'pickup-in-point',
            estimate: '1d',
            friendlyName: null,
            id: 'pickup-SLA',
            isSelected: false,
            price: 100,
            storeDistance: 0,
            transitTime: undefined,
            businessHours: [
              {
                dayNumber: '1to5',
                closed: true,
                openingTime: '',
                closingTime: '',
              },
              { dayNumber: 6, closed: true, openingTime: '', closingTime: '' },
              { dayNumber: 0, closed: true, openingTime: '', closingTime: '' },
            ],
          },
        ],
        selectedAddress: deliveryAddress,
      }

      expect(
        await getShippingInfo({ clients, orderForm: ORDER_FORM_WITH_PICKUPS })
      ).toEqual(expectedResult)
    })

    it('should get shipping info removing scheduled delivery SLAs', async () => {
      const expectedResult = {
        availableAddresses: [deliveryAddress],
        countries: ['BRA', 'GBR'],
        deliveryOptions: [
          {
            deliveryChannel: 'delivery',
            estimate: '1db',
            id: 'delivery-SLA',
            isSelected: true,
            price: 100,
            sla: {
              availableDeliveryWindows: [],
              deliveryChannel: 'delivery',
              deliveryIds: [],
              deliveryWindow: null,
              id: 'delivery-SLA',
              listPrice: 0,
              lockTTL: null,
              name: 'delivery-SLA',
              pickupDistance: 0,
              pickupPointId: null,
              pickupStoreInfo: {
                additionalInfo: null,
                address: null,
                dockId: null,
                friendlyName: null,
                isPickupStore: false,
              },
              polygonName: null,
              price: 100,
              shippingEstimate: '1db',
              shippingEstimateDate: null,
              tax: 0,
            },
          },
        ],
        pickupOptions: [],
        selectedAddress: deliveryAddress,
      }

      expect(
        await getShippingInfo({
          clients,
          orderForm: ORDER_FORM_WITH_SCHEDULED_DELIVERY,
        })
      ).toEqual(expectedResult)
    })

    it('should get shipping info with delivery and pickup SLAs but removing scheduled delivery ones', async () => {
      const expectedResult = {
        availableAddresses: [deliveryAddress],
        countries: ['BRA', 'GBR'],
        deliveryOptions: [
          {
            deliveryChannel: 'delivery',
            estimate: '1db',
            id: 'delivery-SLA',
            isSelected: true,
            price: 100,
            sla: {
              availableDeliveryWindows: [],
              deliveryChannel: 'delivery',
              deliveryIds: [],
              deliveryWindow: null,
              id: 'delivery-SLA',
              listPrice: 0,
              lockTTL: null,
              name: 'delivery-SLA',
              pickupDistance: 0,
              pickupPointId: null,
              pickupStoreInfo: {
                additionalInfo: null,
                address: null,
                dockId: null,
                friendlyName: null,
                isPickupStore: false,
              },
              polygonName: null,
              price: 100,
              shippingEstimate: '1db',
              shippingEstimateDate: null,
              tax: 0,
            },
          },
        ],
        pickupOptions: [
          {
            additionalInfo: null,
            address: null,
            deliveryChannel: 'pickup-in-point',
            estimate: '1d',
            friendlyName: null,
            id: 'pickup-SLA',
            isSelected: false,
            price: 100,
            storeDistance: 0,
            transitTime: undefined,
            businessHours: [
              {
                dayNumber: '1to5',
                closed: true,
                openingTime: '',
                closingTime: '',
              },
              { dayNumber: 6, closed: true, openingTime: '', closingTime: '' },
              { dayNumber: 0, closed: true, openingTime: '', closingTime: '' },
            ],
          },
        ],
        selectedAddress: deliveryAddress,
      }

      expect(
        await getShippingInfo({
          clients,
          orderForm: ORDER_FORM_WITH_SCHEDULED_DELIVERY_AND_PICKUPS,
        })
      ).toEqual(expectedResult)
    })

    it('should get shipping info removing SLAs which does not exist in all logisticsInfo', async () => {
      const expectedResult = {
        availableAddresses: [deliveryAddress],
        countries: ['BRA', 'GBR'],
        deliveryOptions: [
          {
            deliveryChannel: 'delivery',
            estimate: '1db',
            id: 'delivery-SLA',
            isSelected: true,
            price: 200,
            sla: {
              availableDeliveryWindows: [],
              deliveryChannel: 'delivery',
              deliveryIds: [],
              deliveryWindow: null,
              id: 'delivery-SLA',
              listPrice: 0,
              lockTTL: null,
              name: 'delivery-SLA',
              pickupDistance: 0,
              pickupPointId: null,
              pickupStoreInfo: {
                additionalInfo: null,
                address: null,
                dockId: null,
                friendlyName: null,
                isPickupStore: false,
              },
              polygonName: null,
              price: 100,
              shippingEstimate: '1db',
              shippingEstimateDate: null,
              tax: 0,
            },
          },
        ],
        pickupOptions: [],
        selectedAddress: deliveryAddress,
      }

      expect(
        await getShippingInfo({
          clients,
          orderForm: ORDER_FORM_WITH_DIFFERENT_SLAS_BETWEEN_LOGISTICS_INFO,
        })
      ).toEqual(expectedResult)
    })

    it('should get shipping info removing duplicated SLAs which have different delivery ids', async () => {
      const expectedResult = {
        availableAddresses: [deliveryAddress],
        countries: ['BRA', 'GBR'],
        deliveryOptions: [
          {
            deliveryChannel: 'delivery',
            estimate: '1db',
            id: 'delivery-SLA',
            isSelected: true,
            price: 200,
            sla: {
              availableDeliveryWindows: [],
              deliveryChannel: 'delivery',
              deliveryIds: [
                {
                  courierId: '1',
                  courierName: 'PAC',
                  dockId: '1fd8f86',
                  quantity: 1,
                  warehouseId: '1a105fe',
                },
              ],
              deliveryWindow: null,
              id: 'delivery-SLA',
              listPrice: 0,
              lockTTL: null,
              name: 'delivery-SLA',
              pickupDistance: 0,
              pickupPointId: null,
              pickupStoreInfo: {
                additionalInfo: null,
                address: null,
                dockId: null,
                friendlyName: null,
                isPickupStore: false,
              },
              polygonName: null,
              price: 100,
              shippingEstimate: '1db',
              shippingEstimateDate: null,
              tax: 0,
            },
          },
        ],
        pickupOptions: [],
        selectedAddress: deliveryAddress,
      }

      expect(
        await getShippingInfo({
          clients,
          orderForm: ORDER_FORM_WITH_DUPLICATED_SLAS_WITH_DIFFERENT_DELIVERY_IDS,
        })
      ).toEqual(expectedResult)
    })

    it('should get shipping info without empty deliveryOptions', async () => {
      const expectedResult = {
        availableAddresses: [deliveryAddress],
        countries: ['BRA', 'GBR'],
        deliveryOptions: [
          {
            deliveryChannel: 'delivery',
            estimate: '1db',
            id: 'delivery-SLA',
            isSelected: true,
            price: 100,
            sla: {
              availableDeliveryWindows: [],
              deliveryChannel: 'delivery',
              deliveryIds: [],
              deliveryWindow: null,
              id: 'delivery-SLA',
              listPrice: 0,
              lockTTL: null,
              name: 'delivery-SLA',
              pickupDistance: 0,
              pickupPointId: null,
              pickupStoreInfo: {
                additionalInfo: null,
                address: null,
                dockId: null,
                friendlyName: null,
                isPickupStore: false,
              },
              polygonName: null,
              price: 100,
              shippingEstimate: '1db',
              shippingEstimateDate: null,
              tax: 0,
            },
          },
        ],
        pickupOptions: [
          {
            additionalInfo: null,
            estimate: '1d',
            address: null,
            deliveryChannel: 'pickup-in-point',
            friendlyName: null,
            id: 'pickup-SLA',
            isSelected: false,
            price: 100,
            storeDistance: 0,
            transitTime: undefined,
            businessHours: [
              {
                dayNumber: '1to5',
                closed: true,
                openingTime: '',
                closingTime: '',
              },
              { dayNumber: 6, closed: true, openingTime: '', closingTime: '' },
              { dayNumber: 0, closed: true, openingTime: '', closingTime: '' },
            ],
          },
        ],
        selectedAddress: deliveryAddress,
      }

      expect(
        await getShippingInfo({
          clients,
          orderForm: ORDER_FORM_WITH_UNAVAILABLE_ITEM_LOGISTICS_INFO,
        })
      ).toEqual(expectedResult)
    })
  })
})

```


[System] You are an expert VTEX IO developer. You specialize in building VTEX Store Framework apps, React components, GraphQL APIs, and Node.js services for e-commerce platforms.

[User] Show me the implementation of checkout-graphql/node/clients/searchGraphQL/productQuery.ts from the checkout-graphql VTEX app.

[Assistant]
Here's the implementation:

```typescript
export interface ProductResponse {
  productName: string
  productId: string
  items: Array<{
    itemId: string
    name: string
    variations: Array<{
      name: string
      values: string[]
    }>
  }>
  specificationGroups: Array<{
    name: string
    originalName: string
    specifications: Array<{
      name: string
      originalName: string
      values: string[]
    }>
  }>
}

export interface ProductsByIdentifierResponse {
  productsByIdentifier: ProductResponse[]
}

export interface ProductArgs {
  values: string[]
}

export const query = `
query Product($values: [ID!]!) {
  productsByIdentifier(field: id, values: $values) {
    productName
    productId
    items {
      itemId
      name
      variations {
        name
        values
      }
    }
    specificationGroups {
      name
      originalName
      specifications {
        name
        originalName
        values
      }
    }
  }
}
`

```


[System] You are an expert VTEX IO developer. You specialize in building VTEX Store Framework apps, React components, GraphQL APIs, and Node.js services for e-commerce platforms.

[User] Show me the implementation of checkout-graphql/node/clients/searchGraphQL/index.ts from the checkout-graphql VTEX app.

[Assistant]
Here's the implementation:

```typescript
import { InstanceOptions, IOContext } from '@vtex/api'
import DataLoader from 'dataloader'

import { GraphQLServer } from '../graphqlServer'
import {
  ProductArgs,
  query as productQuery,
  ProductResponse,
  ProductsByIdentifierResponse,
} from './productQuery'

const extensions = {
  persistedQuery: {
    provider: 'vtex.search-graphql@0.x',
    sender: 'vtex.checkout-graphql@0.x',
  },
}

export class SearchGraphQL extends GraphQLServer {
  private productLoader: DataLoader<string, ProductResponse>

  constructor(ctx: IOContext, opts?: InstanceOptions) {
    super(ctx, opts)

    this.productLoader = new DataLoader(async keys => {
      const { data, errors } = await this.query<
        ProductsByIdentifierResponse,
        ProductArgs
      >(productQuery, { values: keys }, extensions, { metric: 'get-product' })

      if (errors && errors.length > 0) {
        const [error] = errors

        return keys.map(() => error.originalError!)
      }

      return keys.map(
        id =>
          data?.productsByIdentifier.find(
            product => product.productId === id
          ) ?? new Error('Product not found')
      )
    })
  }

  public product = (productId: string) => this.productLoader.load(productId)
}

```


[System] You are an expert VTEX IO developer. You specialize in building VTEX Store Framework apps, React components, GraphQL APIs, and Node.js services for e-commerce platforms.

[User] Show me the implementation of checkout-graphql/node/utils/image/gocommerce.ts from the checkout-graphql VTEX app.

[Assistant]
Here's the implementation:

```typescript
import { DEFAULT_HDF, DEFAULT_WIDTH } from './constants'

const cleanImageUrl = (imageUrl: string | undefined) => {
  if (!imageUrl) {
    return undefined
  }

  return imageUrl.split('?')[0]
}

const changeImageUrlSize = (
  imageUrl: string | undefined,
  { width = DEFAULT_WIDTH, highDensityFactor = DEFAULT_HDF } = {}
) => {
  if (!imageUrl) {
    return undefined
  }

  const widthCalc = width * highDensityFactor
  return `${imageUrl}?width=${widthCalc}&height=auto&aspect=true`
}

export default {
  changeImageUrlSize,
  cleanImageUrl,
}

```


[System] You are an expert VTEX IO developer. You specialize in building VTEX Store Framework apps, React components, GraphQL APIs, and Node.js services for e-commerce platforms.

[User] Show me the implementation of checkout-graphql/node/utils/image/vtex.ts from the checkout-graphql VTEX app.

[Assistant]
Here's the implementation:

```typescript
import { DEFAULT_HDF, DEFAULT_WIDTH } from './constants'

const baseUrlRegex = new RegExp(/.+ids\/(\d+)(?:-(\d+)-(\d+)|)\//)
const sizeRegex = new RegExp(/-(\d+)-(\d+)/)

const cleanImageUrl = (imageUrl: string | undefined) => {
  if (!imageUrl) {
    return undefined
  }

  let resizedImageUrl = imageUrl
  const result = baseUrlRegex.exec(imageUrl)
  if (result && result.length > 0) {
    if (
      result.length === 4 &&
      result[2] !== undefined &&
      result[3] !== undefined
    ) {
      resizedImageUrl = result[0].replace(sizeRegex, '')
    } else {
      resizedImageUrl = result[0]
    }
    return resizedImageUrl
  }
  return undefined
}

const changeImageUrlSize = (
  imageUrl: string | undefined,
  { highDensityFactor = DEFAULT_HDF, width = DEFAULT_WIDTH } = {}
) => {
  if (!imageUrl) {
    return undefined
  }
  const widthCalc = width * highDensityFactor
  const resizedImageUrl = imageUrl.slice(0, -1) // Remove last "/"
  return `${resizedImageUrl}-${widthCalc}-auto`
}

export default {
  changeImageUrlSize,
  cleanImageUrl,
}

```


[System] You are an expert VTEX IO developer. You specialize in building VTEX Store Framework apps, React components, GraphQL APIs, and Node.js services for e-commerce platforms.

[User] Show me the implementation of checkout-graphql/node/utils/image/constants.ts from the checkout-graphql VTEX app.

[Assistant]
Here's the implementation:

```typescript
export const DEFAULT_WIDTH = 96
export const DEFAULT_HDF = 1

```


[System] You are an expert VTEX IO developer. You specialize in building VTEX Store Framework apps, React components, GraphQL APIs, and Node.js services for e-commerce platforms.

[User] Show me the implementation of checkout-graphql/node/utils/image/index.ts from the checkout-graphql VTEX app.

[Assistant]
Here's the implementation:

```typescript
import gocommerce from './gocommerce'
import none from './none'
import vtex from './vtex'

interface ImageOptions {
  width?: number
  highDensityFactor?: number
}

interface Module {
  cleanImageUrl: (imageUrl: string | undefined) => string | undefined
  changeImageUrlSize: (
    imageUrl: string | undefined,
    options?: ImageOptions
  ) => string | undefined
}

const replaceHttpToRelativeProtocol = (url: string | undefined) => {
  if (!url) {
    return undefined
  }
  return url.replace(/https:\/\/|http:\/\//, '//')
}

export const fixImageUrl = (imageUrl: string, platform: string) => {
  const modules: Record<string, Module> = {
    default: none,
    gocommerce,
    vtex,
  }

  const adjust = modules[platform] || modules.default

  const cleanImageUrl = adjust.cleanImageUrl(
    replaceHttpToRelativeProtocol(imageUrl)
  )

  const [at1x, at2x, at3x] = [1, 2, 3].map(hdf =>
    adjust.changeImageUrlSize(cleanImageUrl, { highDensityFactor: hdf })
  )

  if (!at1x || !at2x || !at3x) {
    return undefined
  }

  return { at1x, at2x, at3x }
}

```


[System] You are an expert VTEX IO developer. You specialize in building VTEX Store Framework apps, React components, GraphQL APIs, and Node.js services for e-commerce platforms.

[User] Show me the implementation of checkout-graphql/node/utils/image/none.ts from the checkout-graphql VTEX app.

[Assistant]
Here's the implementation:

```typescript
const cleanImageUrl = (imageUrl: string | undefined) => imageUrl

const changeImageUrlSize = (imageUrl: string | undefined) => imageUrl

export default {
  changeImageUrlSize,
  cleanImageUrl,
}

```


[System] You are an expert VTEX IO developer. You specialize in building VTEX Store Framework apps, React components, GraphQL APIs, and Node.js services for e-commerce platforms.

[User] Show me the implementation of 2performant/docs/README.md from the 2performant VTEX app.

[Assistant]
Here's the implementation:

```markdown
# 2performant

Open the VTEX APP Store and install the app on your store.

or

Run the following command:

```sh
vtex install vtex.twoperformant@0.x
```

Next, open the app settings on your admin and fill the form with your Confirm and Campaign Unique info.

### Subtract TVA

This new feature was specially created for a client, miniprix, that doesn't have taxes configured in VTEX but needs to send to 2Performant data without taxes.
So I created a checkbox that when active and if there aren't any tax information coming from vtex, will subtract 19% (Romanian base tax) from the total value.

```


[System] You are an expert VTEX IO developer. You specialize in building VTEX Store Framework apps, React components, GraphQL APIs, and Node.js services for e-commerce platforms.

[User] Show me the implementation of 2performant/react/index.tsx from the 2performant VTEX app.

[Assistant]
Here's the implementation:

```tsx
import { canUseDOM } from 'vtex.render-runtime'
import { PixelMessage, ProductOrder } from './typings/events'

interface Params {
  amount: number
  confirm: string
  campaignUnique: string
  description: string
  transactionId: string
}

function createIFrame(params: Params) {
  const iframe = document.createElement('iframe')
  iframe.height = '1'
  iframe.width = '1'
  iframe.scrolling = 'no'
  iframe.marginHeight = '0'
  iframe.marginWidth = '0'
  iframe.src = `https://event.2performant.com/events/salecheck?amount=${params.amount}&campaign_unique=${params.campaignUnique}&confirm=${params.confirm}&description=${encodeURIComponent(params.description)}&transaction_id=${encodeURIComponent(params.transactionId)}`

  document.body.appendChild(iframe)
}

export function handleEvents(e: PixelMessage) {
  switch (e.data.eventName) {
    case 'vtex:orderPlaced': {
      let tax = e.data.transactionTax
      let totalWithoutShip = e.data.transactionTotal - e.data.transactionShipping

      if (!tax && window.__2performant.subtractTVA)
        tax = +(0.19 * totalWithoutShip).toFixed(2)

      createIFrame({
        confirm: window.__2performant.confirm,
        campaignUnique: window.__2performant.campaignUnique,
        amount: +(totalWithoutShip - tax).toFixed(2),
        description: productNames(e.data.transactionProducts),
        transactionId: e.data.transactionId,
      })
      return
    }
    default: {
      return
    }
  }
}

function productNames(products: ProductOrder[]): string {
  const productNames = products.map(product => product.name)
  return productNames.join(', ')
}

if (canUseDOM) {
  window.addEventListener('message', handleEvents)
}

```


[System] You are an expert VTEX IO developer. You specialize in building VTEX Store Framework apps, React components, GraphQL APIs, and Node.js services for e-commerce platforms.

[User] Show me the implementation of 2performant/react/package.json from the 2performant VTEX app.

[Assistant]
Here's the implementation:

```json
{
  "scripts": {
    "test": "vtex-test-tools test"
  },
  "dependencies": {
    "ramda": "^0.26.1"
  },
  "devDependencies": {
    "@types/graphql": "^14.5.0",
    "@types/jest": "^24.0.11",
    "@types/node": "^11.13.0",
    "@types/ramda": "^0.26.5",
    "@vtex/test-tools": "^1.1.0",
    "eslint": "^5.16.0",
    "eslint-config-vtex-react": "^4.1.0",
    "graphql": "^14.5.4",
    "prettier": "^1.18.2",
    "tslint-eslint-rules": "^5.4.0",
    "typescript": "3.9.7"
  },
  "version": "0.1.7"
}

```


[System] You are an expert VTEX IO developer. You specialize in building VTEX Store Framework apps, React components, GraphQL APIs, and Node.js services for e-commerce platforms.

[User] Show me the implementation of 2performant/store/interfaces.json from the 2performant VTEX app.

[Assistant]
Here's the implementation:

```json
{
  "pixel.2performant": {
    "component": "index"
  }
}
```


[System] You are an expert VTEX IO developer. You specialize in building VTEX Store Framework apps, React components, GraphQL APIs, and Node.js services for e-commerce platforms.

[User] Show me the implementation of 2performant/public/metadata/messages/es-AR.json from the 2performant VTEX app.

[Assistant]
Here's the implementation:

```json
{
"name": "2Performant Tracking Code",
"headline": "Integración de la plataforma de afiliación de marketing 2Performant",
"overview": "2Performant es la principal plataforma de marketing de afiliados e influencers de Rumanía y una de las mayores plataformas de este tipo en Europa del Este. Al usar esta plataforma, las empresas pueden conectarse con socios, afiliados y personas influyentes para promocionar sus productos y promociones a un público más amplio. Esta aplicación de píxeles le permite agregar el código de seguimiento 2Performant a su tienda.",
"features": [
"Permite la integración del código de seguimiento 2Performant con su tienda VTEX",
"Facilita el seguimiento de tus campañas de marketing de afiliación",
"Junto con la aplicación Export Feeds, facilita el listado de sus productos en la plataforma 2Performant"
],
"additionalInformation": "Esta aplicación requiere una cuenta www.2performant.com válida.\\n\\nTenga en cuenta que la aplicación de píxeles de 2Performant no exportará su feed de productos a la plataforma de 2Performant. Para hacer eso, debe usar la aplicación Export Feeds.",
"websiteURL": "https://www.2performant.com",
"support": {
"url": "https://support.vtex.com/hc/requests"
}
}
```


[System] You are an expert VTEX IO developer. You specialize in building VTEX Store Framework apps, React components, GraphQL APIs, and Node.js services for e-commerce platforms.

[User] Show me the implementation of 2performant/public/metadata/messages/pt-BR.json from the 2performant VTEX app.

[Assistant]
Here's the implementation:

```json
{
"name": "2Performant Tracking Code",
"headline": "Integração da plataforma de afiliação de marketing 2Performant",
"overview": "A 2Performant é a principal plataforma de marketing de afiliados e influenciadores da Romênia e uma das maiores plataformas desse tipo na Europa Oriental. Ao usar esta plataforma, as empresas podem se conectar com parceiros, afiliados e influenciadores para promover seus produtos e promoções para um público mais amplo. Este aplicativo de pixel permite que você adicione o código de rastreamento 2Performant à sua loja.",
"features": [
"Permite a integração do código de rastreamento 2Performant com sua loja VTEX",
"Facilita o rastreamento de suas campanhas de marketing de afiliados",
"Juntamente com o aplicativo Export Feeds, facilita a listagem de seus produtos na plataforma 2Performant"
],
"additionalInformation": "Este aplicativo requer uma conta www.2performant.com válida.\\n\\nObserve que o aplicativo de pixel 2Performant não exportará seu feed de produtos para a plataforma 2Performant. Para fazer isso, você deve usar o aplicativo Export Feeds.",
"websiteURL": "https://www.2performant.com",
"support": {
"url": "https://support.vtex.com/hc/requests"
}
}
```


[System] You are an expert VTEX IO developer. You specialize in building VTEX Store Framework apps, React components, GraphQL APIs, and Node.js services for e-commerce platforms.

[User] Show me the implementation of 2performant/public/metadata/messages/en-US.json from the 2performant VTEX app.

[Assistant]
Here's the implementation:

```json
{
"name": "2Performant Tracking Code",
"headline": "2Performant marketing affiliation platform integration",
"overview": "2Performant is Romania's foremost affiliate and influencer marketing platform and one of the largest such platforms in Eastern Europe. By using this platform, businesses can connect with partners, affiliates, and influencers in order to promote their products and promotions to a wider audience. This pixel app allows you to add the 2Performant tracking code to your store.",
"features": [
"Allows the integration of the 2Performant tracking code with your VTEX store",
"Facilitates the tracking of your affiliate marketing campaigns",
"Together with the Export Feeds app, facilitates the listing of your products on the 2Performant platform"
],
"additionalInformation": "This application requires a valid www.2performant.com account.\\n\\nNote that the 2Performant pixel app will not export your product feed into the 2Performant platform. To do that, you must use the Export Feeds app.",
"websiteURL": "https://www.2performant.com",
"support": {
"url": "https://support.vtex.com/hc/requests"
}
}
```


[System] You are an expert VTEX IO developer. You specialize in building VTEX Store Framework apps, React components, GraphQL APIs, and Node.js services for e-commerce platforms.

[User] Show me the implementation of 2performant/react/typings/events.d.ts from the 2performant VTEX app.

[Assistant]
Here's the implementation:

```typescript
export interface PixelMessage extends MessageEvent {
  data:
    | ProductViewData
    | ProductClickData
    | OrderPlacedData
    | OrderPlacedTrackedData
    | PageViewData
    | ProductImpressionData
    | AddToCartData
    | RemoveToCartData
}

export interface EventData {
  event: string
  eventName: string
  currency: string
}

export interface PageViewData extends EventData {
  event: 'pageView'
  eventName: 'vtex:pageView'
  pageTitle: string
  pageUrl: string
  referrer: string
}

export interface AddToCartData extends EventData {
  event: 'addToCart'
  eventName: 'vtex:addToCart'
  items: CartItem[]
}

export interface RemoveToCartData extends EventData {
  event: 'removeFromCart'
  eventName: 'vtex:removeFromCart'
  items: CartItem[]
}

export interface OrderPlacedData extends Order, EventData {
  event: 'orderPlaced'
  eventName: 'vtex:orderPlaced'
}

export interface OrderPlacedTrackedData extends Order, EventData {
  event: 'orderPlacedTracked'
  eventName: 'vtex:orderPlacedTracked'
}

export interface ProductViewData extends EventData {
  event: 'productView'
  eventName: 'vtex:productView'
  product: Product
}

export interface ProductClickData extends EventData {
  event: 'productClick'
  eventName: 'vtex:productClick'
  product: Product
}

export interface ProductImpressionData extends EventData {
  event: 'productImpression'
  eventName: 'vtex:productImpression'
  impressions: Impression[]
  product?: Product // deprecated, use impressions list!
  position?: number // deprecated, use impressions list!
  list: string
}

interface CartItem {
  skuId: string
  variant: string
  price: number
  name: string
  quantity: number
  productRefId: string
  brand: string
  category: string
}

export interface Order {
  currency: string
  accountName: string
  orderGroup: string
  salesChannel: string
  coupon: string
  visitorType: string
  visitorContactInfo: string[]
  visitorAddressState: string
  visitorAddressCountry: string
  visitorAddressPostalCode: string
  transactionId: string
  transactionDate: string
  transactionAffiliation: string
  transactionTotal: number
  transactionShipping: number
  transactionSubtotal: number
  transactionDiscounts: number
  transactionTax: number
  transactionCurrency: string
  transactionPaymentType: PaymentType[]
  transactionShippingMethod: ShippingMethod[]
  transactionProducts: ProductOrder[]
  transactionPayment: {
    id: string
  }
}

export interface Impression {
  product: Product
  position: number
}

interface PaymentType {
  group: string
  paymentSystemName: string
  installments: number
  value: number
}

interface ShippingMethod {
  itemId: string
  selectedSla: string
}

interface ProductOrder {
  id: string
  name: string
  sku: string
  skuRefId: string
  skuName: string
  productRefId: string
  ean: string
  slug: string
  brand: string
  brandId: string
  seller: string
  sellerId: string
  category: string
  categoryId: string
  categoryTree: string[]
  categoryIdTree: string[]
  priceTags: PriceTag[]
  originalPrice: number
  price: number
  sellingPrice: number
  tax: number
  quantity: number
  components: any[]
  measurementUnit: string
  unitMultiplier: number
}

interface PriceTag {
  identifier: string
  isPercentual: boolean
  value: number
}

interface Product {
  brand: string
  categoryId?: string // inconsistency
  categories: string[]
  productId: string
  productName: string
  selectedSku?: string // inconsistency
  items: Item[]
  sku: Item
  [key: string]: any
}

interface Item {
  itemId: string
  name: string
  seller?: Seller
  [key: string]: any
}

interface Seller {
  commertialOffer: CommertialOffer
  [key: string]: any
}

interface CommertialOffer {
  Price: number
  [key: string]: any
}

```


[System] You are an expert VTEX IO developer. You specialize in building VTEX Store Framework apps, React components, GraphQL APIs, and Node.js services for e-commerce platforms.

[User] Show me the implementation of 2performant/react/typings/vtex.render-runtime.d.ts from the 2performant VTEX app.

[Assistant]
Here's the implementation:

```typescript
declare module 'vtex.render-runtime' {
  export const canUseDOM: boolean
}

```


[System] You are an expert VTEX IO developer. You specialize in building VTEX Store Framework apps, React components, GraphQL APIs, and Node.js services for e-commerce platforms.

[User] Show me the implementation of 2performant/react/typings/global.d.ts from the 2performant VTEX app.

[Assistant]
Here's the implementation:

```typescript
interface Window extends Window {
  __2performant: {
    confirm: string
    campaignUnique: string
    subtractTVA: boolean
  }
}

```


[System] You are an expert VTEX IO developer. You specialize in building VTEX Store Framework apps, React components, GraphQL APIs, and Node.js services for e-commerce platforms.

[User] Show me the implementation of delivery-theme/docs/README.md from the delivery-theme VTEX app.

[Assistant]
Here's the implementation:

```markdown
# Delivery Theme
VTEX delivery store based on store framework

```


[System] You are an expert VTEX IO developer. You specialize in building VTEX Store Framework apps, React components, GraphQL APIs, and Node.js services for e-commerce platforms.

[User] Show me the implementation of delivery-theme/store/blocks.json from the delivery-theme VTEX app.

[Assistant]
Here's the implementation:

```json
{
  "store.address": {
    "blocks": [
      "address-manager"
    ]
  },
  "store.home": {
    "blocks": [
      "rebuy",
      "carousel",
      "shelf"
    ],
    "parent": {
      "challenge": "challenge.address"
    }
  },
  "store.product": {
    "blocks": [
      "product-details.customizer"
    ],
    "parent": {
      "challenge": "challenge.address"
    }
  },
  "store.search": {
    "blocks": [
      "search-result"
    ],
    "parent": {
      "challenge": "challenge.address"
    }
  },
  "store.search#brand": {
    "blocks": [
      "search-result"
    ],
    "parent": {
      "challenge": "challenge.address"
    }
  },
  "store.search#department": {
    "blocks": [
      "search-result"
    ],
    "parent": {
      "challenge": "challenge.address"
    }
  },
  "store.search#category": {
    "blocks": [
      "search-result"
    ],
    "parent": {
      "challenge": "challenge.address"
    }
  },
  "store.search#subcategory": {
    "blocks": [
      "search-result"
    ],
    "parent": {
      "challenge": "challenge.address"
    }
  },
  "store.account": {
    "blocks": [
      "my-account"
    ]
  },
  "store.login": {
    "blocks": [
      "login-content"
    ]
  },
  "header.full": {
    "blocks": [
      "telemarketing",
      "logo",
      "minicart",
      "login",
      "category-menu",
      "search-bar",
      "user-address"
    ],
    "props": {
      "showSearchBar": true,
      "showLogin": true
    }
  },
  "user-address": {
    "blocks": ["modal"]
  },
  "modal": {
    "children": ["change-address"],
    "props": {
      "showTopBar": false
    }
  }
}
```


[System] You are an expert VTEX IO developer. You specialize in building VTEX Store Framework apps, React components, GraphQL APIs, and Node.js services for e-commerce platforms.

[User] Show me the implementation of delivery-theme/store/routes.json from the delivery-theme VTEX app.

[Assistant]
Here's the implementation:

```json
{
  "store.address": {
    "path": "/address"
  }
}
```


[System] You are an expert VTEX IO developer. You specialize in building VTEX Store Framework apps, React components, GraphQL APIs, and Node.js services for e-commerce platforms.

[User] Show me the implementation of delivery-theme/styles/configs/style.json from the delivery-theme VTEX app.

[Assistant]
Here's the implementation:

```json
{
  "typeScale": [3, 2.25, 1.5, 1.25, 1, 0.875, 0.75],
  "spacing": [0.125, 0.25, 0.5, 0.75, 1, 1.5, 2, 3, 4, 8, 16],
  "customMedia": [
    { "s": 20 },
    {
      "ns": {
        "value": 40,
        "minWidth": true
      }
    },
    {
      "m": {
        "value": 40,
        "minWidth": true
      }
    },
    {
      "l": {
        "value": 64,
        "minWidth": true
      }
    },
    {
      "xl": {
        "value": 80,
        "minWidth": true
      }
    }
  ],
  "colors": {
    "black-90": "rgba(0,0,0,.9)",
    "black-80": "rgba(0,0,0,.8)",
    "black-70": "rgba(0,0,0,.7)",
    "black-60": "rgba(0,0,0,.6)",
    "black-50": "rgba(0,0,0,.5)",
    "black-40": "rgba(0,0,0,.4)",
    "black-30": "rgba(0,0,0,.3)",
    "black-20": "rgba(0,0,0,.2)",
    "black-10": "rgba(0,0,0,.1)",
    "black-05": "rgba(0,0,0,.05)",
    "black-025": "rgba(0,0,0,.025)",
    "black-0125": "rgba(0,0,0,.0125)",

    "white-90": "rgba(255,255,255,.9)",
    "white-80": "rgba(255,255,255,.8)",
    "white-70": "rgba(255,255,255,.7)",
    "white-60": "rgba(255,255,255,.6)",
    "white-50": "rgba(255,255,255,.5)",
    "white-40": "rgba(255,255,255,.4)",
    "white-30": "rgba(255,255,255,.3)",
    "white-20": "rgba(255,255,255,.2)",
    "white-10": "rgba(255,255,255,.1)",
    "white-05": "rgba(255,255,255,.05)",
    "white-025": "rgba(255,255,255,.025)",
    "white-0125": "rgba(255,255,255,.0125)"
  },
  "semanticColors": {
    "background": {
      "base": "#ffffff",
      "base--inverted": "#03044e",
      "action-primary": "#0F3E99",
      "action-secondary": "#eef3f7",
      "emphasis": "#f71963",
      "disabled": "#f2f4f5",
      "success": "#8bc34a",
      "success--faded": "#eafce3",
      "danger": "#ff4c4c",
      "danger--faded": "#ffe6e6",
      "warning": "#ffb100",
      "warning--faded": "#fff6e0",
      "muted-1": "#727273",
      "muted-2": "#979899",
      "muted-3": "#cacbcc",
      "muted-4": "#e3e4e6",
      "muted-5": "#f2f4f5"
    },
    "hover-background": {
      "action-primary": "#072c75",
      "action-secondary": "#dbe9fd",
      "emphasis": "#dd1659",
      "success": "#8bc34a",
      "success--faded": "#eafce3",
      "danger": "#e13232",
      "danger--faded": "#ffe6e6",
      "warning": "#ffb100",
      "warning--faded": "#fff6e0",
      "muted-1": "#727273",
      "muted-2": "#979899",
      "muted-3": "#cacbcc",
      "muted-4": "#e3e4e6",
      "muted-5": "#f2f4f5"
    },
    "active-background": {
      "action-primary": "#0c389f",
      "action-secondary": "#dbe9fd",
      "emphasis": "#dd1659",
      "success": "#8bc34a",
      "success--faded": "#eafce3",
      "danger": "#ff4c4c",
      "danger--faded": "#ffe6e6",
      "warning": "#ffb100",
      "warning--faded": "#fff6e0",
      "muted-1": "#727273",
      "muted-2": "#979899",
      "muted-3": "#cacbcc",
      "muted-4": "#e3e4e6",
      "muted-5": "#f2f4f5"
    },
    "text": {
      "action-primary": "#0F3E99",
      "action-secondary": "#eef3f7",
      "link": "#0F3E99",
      "emphasis": "#f71963",
      "disabled": "#979899",
      "success": "#8bc34a",
      "success--faded": "#eafce3",
      "danger": "#ff4c4c",
      "danger--faded": "#ffe6e6",
      "warning": "#ffb100",
      "warning--faded": "#fff6e0",
      "muted-1": "#727273",
      "muted-2": "#979899",
      "muted-3": "#cacbcc",
      "muted-4": "#e3e4e6",
      "muted-5": "#f2f4f5"
    },
    "visited-text": {
      "link": "#0c389f"
    },
    "hover-text": {
      "action-primary": "#072c75",
      "action-secondary": "#dbe9fd",
      "link": "#0c389f",
      "emphasis": "#dd1659",
      "success": "#8bc34a",
      "success--faded": "#eafce3",
      "danger": "#e13232",
      "danger--faded": "#ffe6e6",
      "warning": "#ffb100",
      "warning--faded": "#fff6e0"
    },
    "active-text": {
      "link": "#0c389f",
      "emphasis": "#dd1659",
      "success": "#8bc34a",
      "success--faded": "#eafce3",
      "danger": "#ff4c4c",
      "danger--faded": "#ffe6e6",
      "warning": "#ffb100",
      "warning--faded": "#fff6e0"
    },
    "border": {
      "action-primary": "#0F3E99",
      "action-secondary": "#eef3f7",
      "emphasis": "#f71963",
      "disabled": "#e3e4e6",
      "success": "#8bc34a",
      "success--faded": "#eafce3",
      "danger": "#ff4c4c",
      "danger--faded": "#ffe6e6",
      "warning": "#ffb100",
      "warning--faded": "#fff6e0",
      "muted-1": "#727273",
      "muted-2": "#979899",
      "muted-3": "#cacbcc",
      "muted-4": "#e3e4e6",
      "muted-5": "#f2f4f5"
    },
    "hover-border": {
      "action-primary": "#072c75",
      "action-secondary": "#dbe9fd",
      "emphasis": "#dd1659",
      "success": "#8bc34a",
      "success--faded": "#eafce3",
      "danger": "#e13232",
      "danger--faded": "#ffe6e6",
      "warning": "#ffb100",
      "warning--faded": "#fff6e0",
      "muted-1": "#727273",
      "muted-2": "#979899",
      "muted-3": "#cacbcc",
      "muted-4": "#e3e4e6",
      "muted-5": "#f2f4f5"
    },
    "active-border": {
      "action-primary": "#0c389f",
      "action-secondary": "#dbe9fd",
      "emphasis": "#dd1659",
      "success": "#8bc34a",
      "success--faded": "#eafce3",
      "danger": "#ff4c4c",
      "danger--faded": "#ffe6e6",
      "warning": "#ffb100",
      "warning--faded": "#fff6e0",
      "muted-1": "#727273",
      "muted-2": "#979899",
      "muted-3": "#cacbcc",
      "muted-4": "#e3e4e6",
      "muted-5": "#f2f4f5"
    },
    "on": {
      "base": "#3f3f40",
      "base--inverted": "#ffffff",
      "action-primary": "#ffffff",
      "action-secondary": "#0F3E99",
      "emphasis": "#ffffff",
      "disabled": "#979899",
      "success": "#ffffff",
      "success--faded": "#3f3f40",
      "danger": "#ffffff",
      "danger--faded": "#3f3f40",
      "warning": "#ffffff",
      "warning--faded": "#1a1a1a",
      "muted-1": "#ffffff",
      "muted-2": "#ffffff",
      "muted-3": "#3f3f40",
      "muted-4": "#3f3f40",
      "muted-5": "#3f3f40"
    },
    "hover-on": {
      "action-primary": "#ffffff",
      "action-secondary": "#0F3E99",
      "emphasis": "#ffffff",
      "success": "#ffffff",
      "success--faded": "#3f3f40",
      "danger": "#ffffff",
      "danger--faded": "#3f3f40",
      "warning": "#ffffff",
      "warning--faded": "#1a1a1a"
    },
    "active-on": {
      "action-primary": "#ffffff",
      "action-secondary": "#0F3E99",
      "emphasis": "#ffffff",
      "success": "#ffffff",
      "success--faded": "#3f3f40",
      "danger": "#ffffff",
      "danger--faded": "#3f3f40",
      "warning": "#ffffff",
      "warning--faded": "#1a1a1a"
    }
  },
  "borderWidths": [0, 0.125, 0.25, 0.5, 1, 2],
  "borderRadius": [0, 0.125, 0.25, 0.5, 1],
  "widths": [1, 2, 4, 8, 16],
  "maxWidths": [1, 2, 4, 8, 16, 32, 48, 64, 96],
  "heights": [1, 2, 4, 8, 16],
  "sizes": [
    { "name": "small", "value": 2 },
    { "name": "regular", "value": 2.5 },
    { "name": "large", "value": 3 }
  ],
  "typography": {
    "measure": [30, 34, 20],
    "styles": {
      "heading-1": {
        "fontFamily": "Fabriga, -apple-system, BlinkMacSystemFont, avenir next, avenir, helvetica neue, helvetica, ubuntu, roboto, noto, segoe ui, arial, sans-serif",
        "fontWeight": "700",
        "fontSize": "3rem",
        "textTransform": "initial",
        "letterSpacing": "0"
      },
      "heading-2": {
        "fontFamily": "Fabriga, -apple-system, BlinkMacSystemFont, avenir next, avenir, helvetica neue, helvetica, ubuntu, roboto, noto, segoe ui, arial, sans-serif",
        "fontWeight": "700",
        "fontSize": "2.25rem",
        "textTransform": "initial",
        "letterSpacing": "0"
      },
      "heading-3": {
        "fontFamily": "Fabriga, -apple-system, BlinkMacSystemFont, avenir next, avenir, helvetica neue, helvetica, ubuntu, roboto, noto, segoe ui, arial, sans-serif",
        "fontWeight": "700",
        "fontSize": "1.75rem",
        "textTransform": "initial",
        "letterSpacing": "0"
      },
      "heading-4": {
        "fontFamily": "Fabriga, -apple-system, BlinkMacSystemFont, avenir next, avenir, helvetica neue, helvetica, ubuntu, roboto, noto, segoe ui, arial, sans-serif",
        "fontWeight": "normal",
        "fontSize": "1.5rem",
        "textTransform": "initial",
        "letterSpacing": "0"
      },
      "heading-5": {
        "fontFamily": "Fabriga, -apple-system, BlinkMacSystemFont, avenir next, avenir, helvetica neue, helvetica, ubuntu, roboto, noto, segoe ui, arial, sans-serif",
        "fontWeight": "normal",
        "fontSize": "1.25rem",
        "textTransform": "initial",
        "letterSpacing": "0"
      },
      "heading-6": {
        "fontFamily": "Fabriga, -apple-system, BlinkMacSystemFont, avenir next, avenir, helvetica neue, helvetica, ubuntu, roboto, noto, segoe ui, arial, sans-serif",
        "fontWeight": "normal",
        "fontSize": "1.25rem",
        "textTransform": "initial",
        "letterSpacing": "0"
      },
      "body": {
        "fontFamily": "Fabriga, -apple-system, BlinkMacSystemFont, avenir next, avenir, helvetica neue, helvetica, ubuntu, roboto, noto, segoe ui, arial, sans-serif",
        "fontWeight": "normal",
        "fontSize": "1rem",
        "textTransform": "initial",
        "letterSpacing": "0"
      },
      "small": {
        "fontFamily": "Fabriga, -apple-system, BlinkMacSystemFont, avenir next, avenir, helvetica neue, helvetica, ubuntu, roboto, noto, segoe ui, arial, sans-serif",
        "fontWeight": "normal",
        "fontSize": "0.875rem",
        "textTransform": "initial",
        "letterSpacing": "0"
      },
      "mini": {
        "fontFamily": "Fabriga, -apple-system, BlinkMacSystemFont, avenir next, avenir, helvetica neue, helvetica, ubuntu, roboto, noto, segoe ui, arial, sans-serif",
        "fontWeight": "normal",
        "fontSize": "0.75rem",
        "textTransform": "initial",
        "letterSpacing": "0"
      },
      "action": {
        "fontFamily": "Fabriga, -apple-system, BlinkMacSystemFont, avenir next, avenir, helvetica neue, helvetica, ubuntu, roboto, noto, segoe ui, arial, sans-serif",
        "fontWeight": "500",
        "fontSize": "1rem",
        "textTransform": "uppercase",
        "letterSpacing": "0"
      },
      "action--small": {
        "fontFamily": "Fabriga, -apple-system, BlinkMacSystemFont, avenir next, avenir, helvetica neue, helvetica, ubuntu, roboto, noto, segoe ui, arial, sans-serif",
        "fontWeight": "500",
        "fontSize": "0.875rem",
        "textTransform": "uppercase",
        "letterSpacing": "0"
      },
      "action--large": {
        "fontFamily": "Fabriga, -apple-system, BlinkMacSystemFont, avenir next, avenir, helvetica neue, helvetica, ubuntu, roboto, noto, segoe ui, arial, sans-serif",
        "fontWeight": "500",
        "fontSize": "1.25rem",
        "textTransform": "uppercase",
        "letterSpacing": "0"
      },
      "code": {
        "fontFamily": "Consolas, monaco, monospace",
        "fontWeight": "normal",
        "fontSize": "1rem",
        "textTransform": "initial",
        "letterSpacing": "0"
      }
    }
  },
  "opacity": [1, 0.9, 0.8, 0.7, 0.6, 0.5, 0.4, 0.3, 0.2, 0.1, 0.05, 0.025, 0]
}

```


[System] You are an expert VTEX IO developer. You specialize in building VTEX Store Framework apps, React components, GraphQL APIs, and Node.js services for e-commerce platforms.

[User] Show me the implementation of shelf/messages/pt.json from the shelf VTEX app.

[Assistant]
Here's the implementation:

```json
{
  "admin/editor.shelf.title": "Vitrine",
  "admin/editor.shelf.description": "Uma vitrine com uma coleção de produtos",
  "admin/editor.shelf.category.title": "Id da Categoria",
  "admin/editor.shelf.category.description": "Para sub-categorias, use \"/\" (por exemplo: 1/2/3)",
  "admin/editor.shelf.collection.title": "Coleção",
  "admin/editor.shelf.orderBy.title": "Ordenação da Lista",
  "admin/editor.shelf.hideUnavailableItems": "Esconder itens não disponíveis",
  "admin/editor.shelf.hideOutOfStockItems": "Esconder itens fora de estoque",
  "admin/editor.shelf.skusFilter": "Filtro de SKUs",
  "admin/editor.shelf.skusFilter.description": "Configurando o valor de primeiro disponível faz sua query ser mais rápida!",
  "admin/editor.shelf.skusFilter.none": "Nenhum",
  "admin/editor.shelf.skusFilter.first-available": "Primeiro Disponível",
  "admin/editor.shelf.skusFilter.all-available": "Todos Disponíveis",
  "admin/editor.shelf.maxItems.title": "Quantidade máxima de itens",
  "admin/editor.shelf.itemsPerPage.title": "Itens por Página (web)",
  "admin/editor.shelf.gap.title": "Espaço entre os itens",
  "admin/editor.shelf.scrollType.title": "Tipo de Rolagem",
  "admin/editor.shelf.arrows.title": "Setas (web)",
  "admin/editor.shelf.titleText.showTitle": "Exibir título da vitrine",
  "admin/editor.shelf.titleText.title": "Texto do Título",
  "admin/editor.shelf.specificationFilters.title": "Filtros de Especificação",
  "admin/editor.shelf.specificationFilters.item.title": "Item de Filtro de Especificação",
  "admin/editor.shelf.specificationFilters.item.id.title": "ID do Filtro de Especificação",
  "admin/editor.shelf.specificationFilters.item.value.title": "Valor do Filtro de Especificação",
  "admin/editor.shelf.gapType.none": "Nenhum",
  "admin/editor.shelf.gapType.small": "Pequeno",
  "admin/editor.shelf.gapType.medium": "Médio",
  "admin/editor.shelf.gapType.large": "Grande",
  "admin/editor.shelf.orderType.sales": "Vendas",
  "admin/editor.shelf.orderType.priceDesc": "Preço, descrescente",
  "admin/editor.shelf.orderType.priceAsc": "Preço, crescente",
  "admin/editor.shelf.orderType.nameAsc": "Nome, crescente",
  "admin/editor.shelf.orderType.nameDesc": "Nome, decrescente",
  "admin/editor.shelf.orderType.releaseDate": "Data de lançamento",
  "admin/editor.shelf.orderType.discount": "Desconto",
  "admin/editor.shelf.orderType.relevance": "Relevância",
  "admin/editor.shelf.scrollType.byPage": "Por Página",
  "admin/editor.shelf.scrollType.oneByOne": "Um por Um",
  "admin/editor.shelf.advanced-properties.title": "Configurações avançadas",
  "admin/editor.shelf.advanced-properties.tracking-id.title": "Nome da vitrine no GTM",
  "admin/editor.shelf.advanced-properties.tracking-id.description": "Nome a ser exibido no Google Analytics. Se nada for adicionado o nome do bloco da vitrine será usado.",
  "admin/editor.relatedProducts.title": "Produtos Relacionados",
  "admin/editor.relatedProducts.description": "Uma vitrine de produtos recomendados para ver",
  "admin/editor.relatedProducts.recommendation": "Recomendações",
  "admin/editor.relatedProducts.recommendation.description": "Quais recomendações serão mostradas",
  "admin/editor.relatedProducts.similars": "Produtos similares",
  "admin/editor.relatedProducts.view": "Quem viu isto, também viu...",
  "admin/editor.relatedProducts.buy": "Quem comprou isto, também comprou...",
  "admin/editor.relatedProducts.accessories": "Produtos de acessórios",
  "admin/editor.relatedProducts.viewAndBought": "Quem viu isto, comprou também...",
  "admin/editor.relatedProducts.suggestions": "Sugestões",
  "admin/editor.relatedProducts.groupBy.title": "Agrupar por",
  "admin/editor.relatedProducts.groupBy.description": "Agrupar listas de recomendações",
  "admin/editor.relatedProducts.groupBy.product": "Produtos",
  "admin/editor.relatedProducts.groupBy.none": "Não agrupar",
  "store/shelf.title": "Melhores Produtos",
  "admin/editor.shelf-properties.title.title": "Título",
  "admin/editor.shelf-properties.title.description": "Título da vitrine",
  "admin/editor.shelf-properties.show-title.title": "Mostrar título",
  "admin/editor.shelf-properties.show-title.description": "Se deveria mostrar o título da vitrine",
  "admin/editor.shelf-properties.min-items-per-page.title": "Mínimo de itens por janela de slide",
  "admin/editor.shelf-properties.min-items-per-page.description": "A quantidade mínima de itens que devem estar na tela ao mesmo tempo (ex. 1/2/3)",
  "admin/editor.shelf-properties.items-per-page.title": "Itens por janela do slide",
  "admin/editor.shelf-properties.items-per-page.description": "A quantidade de itens que devem estar na tela ao mesmo tempo (ex. 1/2/3)",
  "admin/editor.shelf-properties.arrows.title": "Mostrar setas",
  "admin/editor.shelf-properties.arrows.description": "Se deveria exibir as setas para controlar a vitrine",
  "admin/editor.shelf-properties.autoplay.title": "Reprodução automática",
  "admin/editor.shelf-properties.autoplay.description": "Se deveria passar os slides automaticamente",
  "admin/editor.shelf-properties.navigation-step.title": "Passo de navegação",
  "admin/editor.shelf-properties.navigation-step.description": "Quantos itens ele deve passar quando as setas são clicadas. Você pode passar um número ou \"page\" (sem as aspas) para passar todos os itens da janela"
}

```


[System] You are an expert VTEX IO developer. You specialize in building VTEX Store Framework apps, React components, GraphQL APIs, and Node.js services for e-commerce platforms.

[User] Show me the implementation of shelf/messages/en.json from the shelf VTEX app.

[Assistant]
Here's the implementation:

```json
{
  "admin/editor.shelf.title": "Shelf",
  "admin/editor.shelf.description": "A product shelf featuring a collection",
  "admin/editor.shelf.category.title": "Category Id",
  "admin/editor.shelf.category.description": "For sub-categories, use \"/\" (e.g. 1/2/3)",
  "admin/editor.shelf.collection.title": "Collection",
  "admin/editor.shelf.orderBy.title": "List Ordenation",
  "admin/editor.shelf.hideUnavailableItems": "Hide unavailable items",
  "admin/editor.shelf.hideOutOfStockItems": "Hide out of stock items",
  "admin/editor.shelf.skusFilter": "SKUs Filter",
  "admin/editor.shelf.skusFilter.description": "Setting the first available filter makes your query much faster!",
  "admin/editor.shelf.skusFilter.none": "None",
  "admin/editor.shelf.skusFilter.first-available": "First Available",
  "admin/editor.shelf.skusFilter.all-available": "All Available",
  "admin/editor.shelf.maxItems.title": "Max Items",
  "admin/editor.shelf.itemsPerPage.title": "Items Per Page (web)",
  "admin/editor.shelf.gap.title": "Gap between Items",
  "admin/editor.shelf.scrollType.title": "Scroll Type",
  "admin/editor.shelf.arrows.title": "Arrows (web)",
  "admin/editor.shelf.titleText.showTitle": "Show title of the shelf",
  "admin/editor.shelf.titleText.title": "Title Text",
  "admin/editor.shelf.specificationFilters.title": "Specification Filters",
  "admin/editor.shelf.specificationFilters.item.title": "Specification Filter Item",
  "admin/editor.shelf.specificationFilters.item.id.title": "Specification Filter ID",
  "admin/editor.shelf.specificationFilters.item.value.title": "Specification Filter Value",
  "admin/editor.shelf.gapType.none": "None",
  "admin/editor.shelf.gapType.small": "Small",
  "admin/editor.shelf.gapType.medium": "Medium",
  "admin/editor.shelf.gapType.large": "Large",
  "admin/editor.shelf.orderType.sales": "Sales",
  "admin/editor.shelf.orderType.priceDesc": "Price, descending",
  "admin/editor.shelf.orderType.priceAsc": "Price, ascending",
  "admin/editor.shelf.orderType.nameAsc": "Name, ascending",
  "admin/editor.shelf.orderType.nameDesc": "Name, descending",
  "admin/editor.shelf.orderType.releaseDate": "Release Date",
  "admin/editor.shelf.orderType.discount": "Discount",
  "admin/editor.shelf.orderType.relevance": "Relevance",
  "admin/editor.shelf.scrollType.byPage": "By Page",
  "admin/editor.shelf.scrollType.oneByOne": "One by One",
  "admin/editor.shelf.advanced-properties.title": "Advanced Configurations",
  "admin/editor.shelf.advanced-properties.tracking-id.title": "GTM Shelf name",
  "admin/editor.shelf.advanced-properties.tracking-id.description": "Name to show in the Google Analytics. If nothing is passed it will use the name of the block instead",
  "admin/editor.relatedProducts.title": "Related Products",
  "admin/editor.relatedProducts.description": "A related products shelf to show view recommendations",
  "admin/editor.relatedProducts.recommendation": "Recommendations",
  "admin/editor.relatedProducts.recommendation.description": "Which recommendations will be shown",
  "admin/editor.relatedProducts.similars": "Similar products",
  "admin/editor.relatedProducts.view": "Who saw this, also saw...",
  "admin/editor.relatedProducts.buy": "Who bought this, also bought...",
  "admin/editor.relatedProducts.accessories": "Accessories products",
  "admin/editor.relatedProducts.viewAndBought": "Who saw this, also bought...",
  "admin/editor.relatedProducts.suggestions": "Suggestions",
  "admin/editor.relatedProducts.groupBy.title": "Group by",
  "admin/editor.relatedProducts.groupBy.description": "Group recommendation list",
  "admin/editor.relatedProducts.groupBy.product": "Products",
  "admin/editor.relatedProducts.groupBy.none": "Do not group",
  "store/shelf.title": "Best Products",
  "admin/editor.tabbed-shelf.title": "Tabbed Shelf",
  "admin/editor.tabbed-shelf.description": "Tabbed Shelf featured product module",
  "admin/editor.tabbed-shelf.isEnabled.title": "Enabled",
  "admin/editor.tabbed-shelf.headline": "Headline",
  "admin/editor.tabbed-shelf.bottomText": "Bottom Text",
  "admin/editor.tabbed-shelf.buttonText": "Button Text",
  "admin/editor.tabbed-shelf.buttonUrl": "Button URL (absolute)",
  "admin/editor.tabbed-shelf.tabs.items": "Category Item",
  "admin/editor.tabbed-shelf.tabs.items.id": "Category Id",
  "admin/editor.tabbed-shelf.tabs": "Tabs",
  "admin/editor.shelf-properties.title.title": "Title",
  "admin/editor.shelf-properties.title.description": "Title of the shelf",
  "admin/editor.shelf-properties.show-title.title": "Show title",
  "admin/editor.shelf-properties.show-title.description": "If it should show the title of the shelf",
  "admin/editor.shelf-properties.min-items-per-page.title": "Minimum items per page",
  "admin/editor.shelf-properties.min-items-per-page.description": "The minimum amount of items that should be on the screen at the same time (e.g. 1/2/3)",
  "admin/editor.shelf-properties.items-per-page.title": "Items per slide window",
  "admin/editor.shelf-properties.items-per-page.description": "The amount of items that should be on the screen at the same time (e.g. 1/2/3)",
  "admin/editor.shelf-properties.arrows.title": "Show arrows",
  "admin/editor.shelf-properties.arrows.description": "If it should display the arrows to control the shelf",
  "admin/editor.shelf-properties.autoplay.title": "Autoplay",
  "admin/editor.shelf-properties.autoplay.description": "If it should be passing the slides automatically",
  "admin/editor.shelf-properties.navigation-step.title": "Navigation step",
  "admin/editor.shelf-properties.navigation-step.description": "How many items it should pass when the arrows are clicked. You can pass a number or you can pass \"page\" (without the quotes) to pass all the items of the window"
}

```


[System] You are an expert VTEX IO developer. You specialize in building VTEX Store Framework apps, React components, GraphQL APIs, and Node.js services for e-commerce platforms.

[User] Show me the implementation of shelf/messages/context.json from the shelf VTEX app.

[Assistant]
Here's the implementation:

```json
{
  "admin/editor.shelf.title": "admin/editor.shelf.title",
  "admin/editor.shelf.description": "admin/editor.shelf.description",
  "admin/editor.shelf.category.title": "admin/editor.shelf.category.title",
  "admin/editor.shelf.category.description": "admin/editor.shelf.category.description",
  "admin/editor.shelf.collection.title": "admin/editor.shelf.collection.title",
  "admin/editor.shelf.orderBy.title": "admin/editor.shelf.orderBy.title",
  "admin/editor.shelf.hideUnavailableItems": "admin/editor.shelf.hideUnavailableItems",
  "admin/editor.shelf.hideOutOfStockItems": "admin/editor.shelf.hideOutOfStockItems",
  "admin/editor.shelf.skusFilter": "admin/editor.shelf.skusFilter",
  "admin/editor.shelf.skusFilter.description": "admin/editor.shelf.skusFilter.description",
  "admin/editor.shelf.skusFilter.none": "admin/editor.shelf.skusFilter.none",
  "admin/editor.shelf.skusFilter.first-available": "admin/editor.shelf.skusFilter.first-available",
  "admin/editor.shelf.skusFilter.all-available": "admin/editor.shelf.skusFilter.all-available",
  "admin/editor.shelf.maxItems.title": "admin/editor.shelf.maxItems.title",
  "admin/editor.shelf.itemsPerPage.title": "admin/editor.shelf.itemsPerPage.title",
  "admin/editor.shelf.gap.title": "admin/editor.shelf.gap.title",
  "admin/editor.shelf.scrollType.title": "admin/editor.shelf.scrollType.title",
  "admin/editor.shelf.arrows.title": "admin/editor.shelf.arrows.title",
  "admin/editor.shelf.titleText.showTitle": "admin/editor.shelf.titleText.showTitle",
  "admin/editor.shelf.titleText.title": "admin/editor.shelf.titleText.title",
  "admin/editor.shelf.specificationFilters.title": "admin/editor.shelf.specificationFilters.title",
  "admin/editor.shelf.specificationFilters.item.title": "admin/editor.shelf.specificationFilters.item.title",
  "admin/editor.shelf.specificationFilters.item.id.title": "admin/editor.shelf.specificationFilters.item.id.title",
  "admin/editor.shelf.specificationFilters.item.value.title": "admin/editor.shelf.specificationFilters.item.value.title",
  "admin/editor.shelf.gapType.none": "admin/editor.shelf.gapType.none",
  "admin/editor.shelf.gapType.small": "admin/editor.shelf.gapType.small",
  "admin/editor.shelf.gapType.medium": "admin/editor.shelf.gapType.medium",
  "admin/editor.shelf.gapType.large": "admin/editor.shelf.gapType.large",
  "admin/editor.shelf.orderType.sales": "admin/editor.shelf.orderType.sales",
  "admin/editor.shelf.orderType.priceDesc": "admin/editor.shelf.orderType.priceDesc",
  "admin/editor.shelf.orderType.priceAsc": "admin/editor.shelf.orderType.priceAsc",
  "admin/editor.shelf.orderType.nameAsc": "admin/editor.shelf.orderType.nameAsc",
  "admin/editor.shelf.orderType.nameDesc": "admin/editor.shelf.orderType.nameDesc",
  "admin/editor.shelf.orderType.releaseDate": "admin/editor.shelf.orderType.releaseDate",
  "admin/editor.shelf.orderType.discount": "admin/editor.shelf.orderType.discount",
  "admin/editor.shelf.orderType.relevance": "admin/editor.shelf.orderType.relevance",
  "admin/editor.shelf.scrollType.byPage": "admin/editor.shelf.scrollType.byPage",
  "admin/editor.shelf.scrollType.oneByOne": "admin/editor.shelf.scrollType.oneByOne",
  "admin/editor.shelf.advanced-properties.title": "Advanced Configurations",
  "admin/editor.shelf.advanced-properties.tracking-id.title": "GTM Shelf name",
  "admin/editor.shelf.advanced-properties.tracking-id.description": "Name to show in the Google Analytics. If you don't pass anything it will show the name of the block instead",
  "admin/editor.relatedProducts.title": "admin/editor.relatedProducts.title",
  "admin/editor.relatedProducts.description": "admin/editor.relatedProducts.description",
  "admin/editor.relatedProducts.recommendation": "admin/editor.relatedProducts.recommendation",
  "admin/editor.relatedProducts.recommendation.description": "admin/editor.relatedProducts.recommendation.description",
  "admin/editor.relatedProducts.similars": "admin/editor.relatedProducts.similars",
  "admin/editor.relatedProducts.view": "admin/editor.relatedProducts.view",
  "admin/editor.relatedProducts.buy": "admin/editor.relatedProducts.buy",
  "admin/editor.relatedProducts.accessories": "admin/editor.relatedProducts.accessories",
  "admin/editor.relatedProducts.viewAndBought": "admin/editor.relatedProducts.viewAndBought",
  "admin/editor.relatedProducts.suggestions": "admin/editor.relatedProducts.suggestions",
  "admin/editor.relatedProducts.groupBy.title": "admin/editor.relatedProducts.groupBy.title",
  "admin/editor.relatedProducts.groupBy.description": "admin/editor.relatedProducts.groupBy.description",
  "admin/editor.relatedProducts.groupBy.product": "admin/editor.relatedProducts.groupBy.product",
  "admin/editor.relatedProducts.groupBy.none": "admin/editor.relatedProducts.groupBy.none",
  "store/shelf.title": "store/shelf.title",
  "admin/editor.tabbed-shelf.title": "Component title",
  "admin/editor.tabbed-shelf.description": "Component description",
  "admin/editor.tabbed-shelf.isEnabled.title": "True if component is enabled",
  "admin/editor.tabbed-shelf.headline": "Text to be showed as headline",
  "admin/editor.tabbed-shelf.bottomText": "Bottom Text",
  "admin/editor.tabbed-shelf.tabs": "Category Tabs",
  "admin/editor.tabbed-shelf.buttonText": "Text to be displayed inside button",
  "admin/editor.tabbed-shelf.buttonUrl": "Button URL (absolute)",
  "admin/editor.tabbed-shelf.tabs.items": "Category Item",
  "admin/editor.tabbed-shelf.tabs.items.id": "Category Id",
  "admin/editor.tabbed-shelf.shelf.title": "Shelf properties",
  "admin/editor.shelf-properties.title.title": "Title",
  "admin/editor.shelf-properties.title.description": "Title of the shelf",
  "admin/editor.shelf-properties.show-title.title": "Show title",
  "admin/editor.shelf-properties.show-title.description": "If it should show the title of the shelf",
  "admin/editor.shelf-properties.min-items-per-page.title": "Minimum items per page",
  "admin/editor.shelf-properties.min-items-per-page.description": "The minimum amount of items that should be on the screen at the same time (e.g. 1/2/3)",
  "admin/editor.shelf-properties.items-per-page.title": "Items per slide window",
  "admin/editor.shelf-properties.items-per-page.description": "The amount of items that should be on the screen at the same time (e.g. 1/2/3)",
  "admin/editor.shelf-properties.arrows.title": "Show arrows",
  "admin/editor.shelf-properties.arrows.description": "If it should display the arrows to control the shelf",
  "admin/editor.shelf-properties.autoplay.title": "Autoplay",
  "admin/editor.shelf-properties.autoplay.description": "If it should be passing the slides automatically",
  "admin/editor.shelf-properties.navigation-step.title": "Navigation step",
  "admin/editor.shelf-properties.navigation-step.description": "How many items it should pass when the arrows are clicked. You can pass a number or you can pass \"page\" (without the quotes) to pass all the items of the window"
}

```