[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 native-types/docs/README.md from the native-types VTEX app.

[Assistant]
Here's the implementation:

```markdown
📢 Use this project, contribute to it or open issues to help evolve it using Store Discussion.

# Native Types

This app contains three public components that should be used to format texts according to intl rules.

## Configuration

Add the `native-types` app to the app's dependencies list (in the `manifest.json`) from which you want fetch product data. For example:

```json
"dependencies": {
  "vtex.native-types": "0.x"
}
```

### IOMessage

Coming soon :)

### IOMessageWithMarkers

This component is used to render messages with interpolations and custom tags (markers). These markers are useful to wrap a part of the message with CSS handles.

| Prop name | Type | Description | Default Value |
| --- | --- | --- | --- |
| `message` | `string` | The message that can contain values to be interpolated | `undefined` |
| `markers` | [`string`] | The list of markers to be used during interpolation | `[]` |
| `handleBase` | `string` | Handle that will be used along with the marker to create a span with `CSS handle` on the part wrapped by marks | `''` |
| `values` | `Record<string, any>` | Values used in the message interpolation | `{}` |

**Example:**
```jsx
<IOMessageWithMarkers
  message="<bold>Hello,</bold> {name}!"
  markers={['bold']}
  handleBase="Greetings"
  values={{ name: 'John Doe' }}
/>
```

 The following will be rendered:
``` js
  <div>
    <span
      class="Greetings_bold"
    >
      Hello,
    </span>
     John Doe!
  </div>
```

**🔴 WARNING:** The `markers` and `values` props of this component are both passed to `IOMessage` through `values` so it is important to notice that you **should not** use the same labels within these props.

### formatIOMessage

Coming soon :)

```


[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 native-types/pages/contentSchemas.json from the native-types VTEX app.

[Assistant]
Here's the implementation:

```json
{
  "definitions": {
    "brand": {
      "format": "Brand",
      "title": "admin/native-types.brand",
      "type": "string"
    },

    "category": {
      "format": "Category",
      "title": "admin/native-types.category",
      "type": "string"
    },

    "collection": {
      "format": "Collection",
      "title": "admin/native-types.collection",
      "type": "string"
    },

    "department": {
      "format": "Department",
      "title": "admin/native-types.department",
      "type": "string"
    },

    "image": {
      "properties": {
        "description": {
          "$ref": "#/definitions/text",
          "title": "admin/native-types.image.description"
        },
        "desktop": {
          "$ref": "#/definitions/url",
          "format": "Image",
          "title": "admin/native-types.image.desktop"
        },
        "filename": {
          "title": "admin/native-types.image.filename",
          "type": "string"
        },
        "mobile": {
          "$ref": "#/definitions/url",
          "format": "Image",
          "title": "admin/native-types.image.mobile"
        }
      },
      "title": "admin/native-types.image",
      "type": "object"
    },

    "link": {
      "properties": {
        "attributeNofollow": {
          "default": false,
          "title": "admin/native-types.link.attributeNofollow",
          "type": "boolean"
        },
        "attributeTitle": {
          "$ref": "#/definitions/text",
          "title": "admin/native-types.link.attributeTitle"
        },
        "newTab": {
          "title": "admin/native-types.link.newTab",
          "type": "boolean"
        },
        "url": {
          "$ref": "#/definitions/url",
          "title": "admin/native-types.link.url"
        }
      },
      "title": "admin/native-types.link",
      "type": "object"
    },

    "richText": {
      "$ref": "#/definitions/text",
      "format": "RichText",
      "title": "admin/native-types.richText",
      "type": "string",
      "examples": ["store/native-types.richText"]
    },

    "text": {
      "format": "IOMessage",
      "title": "admin/native-types.text",
      "type": "string",
      "examples": ["store/native-types.text"]
    },

    "url": {
      "$ref": "#/definitions/text",
      "title": "admin/native-types.url",
      "type": "string",
      "examples": ["store/native-types.url"]
    },

    "video": {
      "properties": {
        "description": {
          "$ref": "#/definitions/text",
          "title": "admin/native-types.video.description"
        },
        "thumbnail": {
          "$ref": "#/definitions/image",
          "title": "admin/native-types.video.thumbnail"
        },
        "title": {
          "$ref": "#/definitions/text" ,
          "title": "admin/native-types.video.title"
        },
        "url": {
          "$ref": "#/definitions/url",
          "title": "admin/native-types.video.url"
        }
      },
      "title": "admin/native-types.video",
      "type": "object"
    }
  }
}

```


[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 native-types/react/IOMessageWithMarkers.tsx from the native-types VTEX app.

[Assistant]
Here's the implementation:

```tsx
import React, { useMemo, ReactElement, FC } from 'react'
import { useCssHandles } from 'vtex.css-handles'

import IOMessage from './IOMessage'

// eslint-disable-next-line @typescript-eslint/no-explicit-any
type Values = Record<string, any>

interface Props {
  message: string
  handleBase: string
  markers: string[]
  values: Values
}

const IOMessageWithMarkers: FC<Props> = ({
  message,
  markers = [],
  handleBase = '',
  values = {},
}) => {
  const CSS_HANDLES = useMemo(
    () => markers.map((marker) => `${handleBase}-${marker}`),
    [handleBase, markers]
  )

  const handles = useCssHandles(CSS_HANDLES)

  const markerComponents = markers.reduce((acc, marker) => {
    // for more information check https://github.com/formatjs/react-intl/blob/master/docs/Components.md#rich-text-formatting
    // eslint-disable-next-line react/display-name
    acc[marker] = (...chunks) => (
      <span key={marker} className={handles[`${handleBase}-${marker}`]}>
        {chunks}
      </span>
    )

    return acc
  }, {} as Record<string, (...chunks: string[]) => ReactElement>)

  return (
    <IOMessage
      id={message}
      values={{
        ...markerComponents,
        ...values,
      }}
    />
  )
}

export default React.memo(IOMessageWithMarkers)

```


[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 native-types/react/formatIOMessage.ts from the native-types VTEX app.

[Assistant]
Here's the implementation:

```typescript
import type { ReactElement } from 'react'
import {
  createIntl,
  createIntlCache,
  MessageDescriptor,
  IntlShape,
} from 'react-intl'

type AdaptedMessageDescriptor = MessageDescriptor & {
  intl: IntlShape
}

export type Values = Record<string, string | number | ReactElement>

const cache = createIntlCache()

const formatIOMessage = (
  { intl, ...messageDescriptor }: AdaptedMessageDescriptor,
  values?: Values
) => {
  const { defaultMessage, id } = messageDescriptor

  if (typeof id !== 'string' || id === '') {
    return ''
  }

  const intlMessage = intl.messages[id]

  if (intlMessage) {
    return intl.formatMessage(messageDescriptor, values)
  }

  if (intlMessage === '') {
    return ''
  }

  /**
   * This enables a user to pass a translatable message which is not
   * in the current IntlContext to the function and actually have it
   * formatted by react-intl.
   */
  const newIntl = createIntl(
    {
      locale: intl.locale,
      messages: {
        [id]: id,
      },
    },
    cache
  )

  return newIntl.formatMessage({ defaultMessage, id }, values)
}

export default formatIOMessage

```


[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 native-types/react/package.json from the native-types VTEX app.

[Assistant]
Here's the implementation:

```json
{
  "scripts": {
    "test": "vtex-test-tools test --verbose"
  },
  "devDependencies": {
    "@apollo/react-testing": "^3.1.3",
    "@types/node": "^12.0.0",
    "@types/react": "^16.8.16",
    "@vtex/test-tools": "^3.0.0",
    "@vtex/tsconfig": "^0.5.2",
    "apollo-cache-inmemory": "^1.5.1",
    "react": "^16.8.6",
    "react-dom": "^16.8.6",
    "react-intl": "^3.12.0",
    "typescript": "3.9.7",
    "vtex.css-handles": "http://vtex.vtexassets.com/_v/public/typings/v1/vtex.css-handles@0.4.4/public/@types/vtex.css-handles",
    "vtex.render-runtime": "http://vtex.vtexassets.com/_v/public/typings/v1/vtex.render-runtime@8.124.3/public/@types/vtex.render-runtime"
  },
  "version": "0.10.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 native-types/react/IOMessage.tsx from the native-types VTEX app.

[Assistant]
Here's the implementation:

```tsx
import React, { Fragment, FC } from 'react'
import { useIntl, MessageDescriptor } from 'react-intl'

import formatIOMessage, { Values } from './formatIOMessage'

type IOMessageType = FC<
  MessageDescriptor & {
    values?: Values
  }
>

const IOMessage: IOMessageType = ({
  children,
  values,
  ...messageDescriptor
}) => {
  const intl = useIntl()

  const message = formatIOMessage({ intl, ...messageDescriptor }, values)

  if (children && typeof children === 'function') {
    return children(message === '' ? '' : message) || null
  }

  return message === '' ? null : <Fragment>{message}</Fragment>
}

export default IOMessage

```


[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 native-types/react/__tests__/formatIOMessage.test.ts from the native-types VTEX app.

[Assistant]
Here's the implementation:

```typescript
import { IntlShape, createIntl } from 'react-intl'

import formatIOMessage from '../formatIOMessage'

const createMockIntl = (customMessages: IntlShape['messages'] = {}) =>
  createIntl({ locale: 'en', messages: customMessages })

describe('formatIOMessage', () => {
  it('returns id when message is undefined', () => {
    const id = 'admin/format-io-message.unmapped-id-example'
    const intl = createMockIntl()

    const output = formatIOMessage({ id, intl })

    expect(output).toBe(id)
  })

  it('returns formatted id when message is undefined and dynamic', () => {
    const id = '{exceedingItems, plural, =0{} one {+ # gift} other {+ # gifts}}'
    const intl = createMockIntl()

    const values = {
      exceedingItems: '3',
    }

    const output = formatIOMessage({ id, intl }, values)
    const expectedOutput = '+ 3 gifts'

    expect(output).toBe(expectedOutput)
  })

  it("returns '' when message is ''", () => {
    const id = 'admin/format-io-message.empty-string-example'

    const messages: IntlShape['messages'] = { [id]: '' }
    const intl = createMockIntl(messages)

    const output = formatIOMessage({ id, intl })

    const expectedOutput = ''

    expect(output).toBe(expectedOutput)
  })

  it('works with static, non-empty messages', () => {
    const id = 'admin/format-io-message.working-static-example'

    const messages: IntlShape['messages'] = {
      [id]: 'It works :)',
    }

    const intl = createMockIntl(messages)

    const output = formatIOMessage({ id, intl })

    const expectedOutput = messages[id]

    expect(output).toBe(expectedOutput)
  })

  it('works with dynamic, non-empty messages', () => {
    const id = 'admin/format-io-message.working-dynamic-example'

    const messages: IntlShape['messages'] = {
      [id]: '{subject} {verb} {emoji}',
    }

    const values: Record<string, string> = {
      emoji: ':)',
      subject: 'It',
      verb: 'works',
    }

    const intl = createMockIntl(messages)
    const output = formatIOMessage({ id, intl }, values)

    const expectedOutput = Object.entries(values).reduce(
      (acc, [currKey, currValue]) => acc.replace(`{${currKey}}`, currValue),
      messages[id]
    )

    expect(output).toBe(expectedOutput)
  })

  it("returns '' when id is ''", () => {
    const id = ''

    const intl = createMockIntl()

    const output = formatIOMessage({ id, intl })

    expect(output).toBe('')
  })
})

```


[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 native-types/react/__tests__/IOMessageWithMarkers.test.tsx from the native-types VTEX app.

[Assistant]
Here's the implementation:

```tsx
import React from 'react'
import { render } from '@vtex/test-tools/react'

import IOMessageWithMarkers from '../IOMessageWithMarkers'
import { IOMessageWithMarkers as IOMessageWithMarkersType } from '../types/IOMessageWithMarkers'

interface RenderElementParams {
  message: React.ComponentProps<IOMessageWithMarkersType>['message']
  values?: React.ComponentProps<IOMessageWithMarkersType>['values']
  handleBase?: React.ComponentProps<IOMessageWithMarkersType>['handleBase']
  markers?: React.ComponentProps<IOMessageWithMarkersType>['markers']
}

const renderIOMessageWithIntl = ({
  message,
  values = {},
  handleBase = '',
  markers = [],
}: RenderElementParams) =>
  render(
    <IOMessageWithMarkers
      message={message}
      values={values}
      handleBase={handleBase}
      markers={markers}
    />,
    {
      locale: 'en',
    }
  )

describe('IOMessageWithMarkers', () => {
  it('Render simple message with only the label', () => {
    const message = 'Hello world!'
    const { getByText } = renderIOMessageWithIntl({ message })
    const element = getByText(message)

    expect(element).toBeDefined()
  })

  it('Check values interpolation', () => {
    const message = '{hello} {world} {exclamation}'
    const values = {
      hello: 'Hello',
      world: 'World',
      exclamation: '!',
    }

    const { getByText } = renderIOMessageWithIntl({ message, values })
    const element = getByText('Hello World !')

    expect(element).toBeDefined()
  })

  it('check marker and componentName', () => {
    const message = '<bold>Hello World!</bold>'
    const markers = ['bold']
    const handleBase = 'test'
    const { getByText } = renderIOMessageWithIntl({
      message,
      markers,
      handleBase,
    })

    const element = getByText('Hello World!')

    expect(element.className).toBe('test-bold')
  })

  it('check message with many markers and values', () => {
    const message =
      '<bold>{a}</bold> <italic>{b}</italic> <pretty>{c}</pretty> <sale>{d}</sale>'

    const values = {
      a: 'A',
      b: 'B',
      c: 'C',
      d: 'D',
    }

    const handleBase = 'test'
    const markers = ['bold', 'italic', 'pretty', 'sale']
    const { getByText } = renderIOMessageWithIntl({
      message,
      values,
      markers,
      handleBase,
    })

    expect(getByText('A').className).toBe('test-bold')
    expect(getByText('B').className).toBe('test-italic')
    expect(getByText('C').className).toBe('test-pretty')
    expect(getByText('D').className).toBe('test-sale')
  })

  it('check that if there are values equal to markers, the component should not be rendered correctly', () => {
    const message = '<a>{a}</a> <b>{b}</b> <c>{c}</c> <d>{d}</d>'
    const values = {
      a: 'A',
      b: 'B',
      c: 'C',
      d: 'D',
    }

    const handleBase = 'test'
    const markers = ['a', 'b', 'c', 'd']
    const { queryByText } = renderIOMessageWithIntl({
      message,
      values,
      markers,
      handleBase,
    })

    expect(queryByText('A')).toBeNull()
    expect(queryByText('B')).toBeNull()
    expect(queryByText('C')).toBeNull()
    expect(queryByText('D')).toBeNull()
  })
})

```


[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 native-types/react/__tests__/IOMessage.test.tsx from the native-types VTEX app.

[Assistant]
Here's the implementation:

```tsx
import React from 'react'
import { render } from '@vtex/test-tools/react'

import IOMessage from '../IOMessage'
import { IOMessage as IOMessageType } from '../types/IOMessage'

interface RenderElementParams {
  id: React.ComponentProps<IOMessageType>['id']
  values?: React.ComponentProps<IOMessageType>['values']
}

const renderIOMessageWithIntl = ({ id, values }: RenderElementParams) =>
  render(<IOMessage id={id} values={values} />, {
    locale: 'en',
  })

interface ParseDynamicMessageParams {
  message: string
  values: Record<string, string | number>
}

const parseDynamicMessage = ({ message, values }: ParseDynamicMessageParams) =>
  Object.entries(values).reduce((acc, [currKey, currValue]) => {
    if (typeof currValue !== 'string') {
      return acc
    }

    return acc.replace(`{${currKey}}`, currValue)
  }, message)

describe('IOMessage', () => {
  it('displays id when message is undefined', () => {
    const id = 'test/io-message.unmapped-id-example'

    const { getByText } = renderIOMessageWithIntl({ id })

    const element = getByText(id)

    expect(element).toBeDefined()
  })

  it('displays formatted id when message is undefined and id is dynamic', () => {
    const id = '{exceedingItems, plural, =0{} one {+ # gift} other {+ # gifts}}'
    const values = {
      exceedingItems: '3',
    }

    const { getByText } = renderIOMessageWithIntl({ id, values })

    const expectedOutput = '+ 3 gifts'
    const element = getByText(expectedOutput)

    expect(element).toBeDefined()
  })

  it("returns null when message is ''", () => {
    /**
     * This message is defined at '/messages' so that @vtex/test-tools
     * can find it.
     * */
    const id = 'admin/format-io-message.empty-string-example'

    const { container } = renderIOMessageWithIntl({ id })

    expect(container.children).toHaveLength(0)
  })

  it('works with static, non-empty messages', () => {
    /**
     * This message is defined at '/messages' so that @vtex/test-tools
     * can find it.
     * */
    const id = 'admin/format-io-message.working-static-example'

    const { getByText } = renderIOMessageWithIntl({ id })

    const element = getByText('It works :)')

    expect(element).toBeDefined()
  })

  it('works with dynamic, non-empty messages', () => {
    /**
     * This message is defined at '/messages' so that @vtex/test-tools
     * can find it.
     * */
    const id = 'admin/format-io-message.working-dynamic-example'

    const values: Record<string, string> = {
      emoji: ':)',
      subject: 'It',
      verb: 'works',
    }

    const text = parseDynamicMessage({
      message: '{subject} {verb} {emoji}',
      values,
    })

    const { getByText } = renderIOMessageWithIntl({ id, values })

    const element = getByText(text)

    expect(element).toBeDefined()
  })
})

```


[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 splunk-log-forwarder/src/routes.ts from the splunk-log-forwarder VTEX app.

[Assistant]
Here's the implementation:

```typescript
import Router from 'koa-router'

const router = new Router()

router.post('/forwarder/start')

export default router

```


[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 splunk-log-forwarder/src/index.ts from the splunk-log-forwarder VTEX app.

[Assistant]
Here's the implementation:

```typescript
import { config } from 'dotenv'

config({ path: './src/.env' })

// eslint-disable-next-line import/first
import { app, server } from './server'

export { app, server }

```


[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 splunk-log-forwarder/src/server.ts from the splunk-log-forwarder VTEX app.

[Assistant]
Here's the implementation:

```typescript
import Koa from 'koa'

import { fetchAppToken } from './middlewares/fetch-app-token'
import { logsForwarder } from './middlewares/forwarder'
import router from './routes'
import { setup } from './middlewares/setup'

const app = new Koa()
const port = process.env.PORT ?? 8080

const middlewares = [setup, fetchAppToken, logsForwarder]

middlewares.forEach((middleware) => app.use(middleware))

app.on('error', (err: Error) => {
  console.error('Error', err)
})
app.use(router.routes())

const server = app.listen(port, () => {
  console.log(`App listening on the port ${port}`)
})

export { app, server }

```


[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 splunk-log-forwarder/src/clients/splunk.ts from the splunk-log-forwarder VTEX app.

[Assistant]
Here's the implementation:

```typescript
import type { RawAxiosRequestHeaders } from 'axios'
import axios from 'axios'

export default class Splunk {
  private host: string
  private port: string
  private headers: RawAxiosRequestHeaders

  constructor(host: string, port: string, headers: RawAxiosRequestHeaders) {
    this.host = host
    this.port = port
    this.headers = headers
  }

  public async postLog(log: unknown): Promise<unknown> {
    return axios.post(
      `https://${this.host}:${this.port}/services/collector/event`,
      log,
      { headers: this.headers }
    )
  }
}

```


[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 splunk-log-forwarder/src/clients/logsource.ts from the splunk-log-forwarder VTEX app.

[Assistant]
Here's the implementation:

```typescript
// eslint-disable-next-line @typescript-eslint/no-require-imports
import EventSource = require('eventsource')

export class LogSource extends EventSource {
  constructor(
    account: string,
    workspace: string,
    opts: EventSource.EventSourceInitDict
  ) {
    console.debug({ opts })
    const url = `http://infra.io.vtex.com/skidder/v1/${account}/${workspace}/logs/stream`

    console.debug(`connecting with ${url}`)
    super(url, opts)
  }
}

```


[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 splunk-log-forwarder/src/middlewares/setup.ts from the splunk-log-forwarder VTEX app.

[Assistant]
Here's the implementation:

```typescript
import { Context, Next } from 'koa'

export const setup = async (ctx: Context, next: Next) => {
  ctx.vtex = {}
  ctx.splunk = {}

  ctx.vtex.account = process.env.VTEX_ACCOUNT
  ctx.vtex.workspace = process.env.VTEX_WORKSPACE
  ctx.vtex.appKey = process.env.VTEX_APP_KEY
  ctx.vtex.appToken = process.env.VTEX_APP_TOKEN

  ctx.splunk.host = process.env.SPLUNK_HOST
  ctx.splunk.port = process.env.SPLUNK_PORT
  ctx.splunk.token = process.env.SPLUNK_TOKEN

  await next()
}

```


[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 splunk-log-forwarder/src/middlewares/fetch-app-token.ts from the splunk-log-forwarder VTEX app.

[Assistant]
Here's the implementation:

```typescript
import type { Context, Next } from 'koa'
import axios from 'axios'

export const fetchAppToken = async (ctx: Context, next: Next) => {
  const {
    vtex: { account, appKey, appToken },
  } = ctx

  const response = await axios.post(
    `https://api.vtexcommercestable.com.br/api/vtexid/apptoken/login`,
    {
      appkey: appKey,
      apptoken: appToken
    },
    {
      params: {
        an: account
      },
    }
  )

  ctx.vtex.VtexIdClientAutCookie = response.data.token

  await next()
}

```


[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 splunk-log-forwarder/src/middlewares/forwarder.ts from the splunk-log-forwarder VTEX app.

[Assistant]
Here's the implementation:

```typescript
import type { Context } from 'koa'

import { LogSource } from '../clients/logsource'
import Splunk from '../clients/splunk'

interface Message {
  data: string
}

interface SplunkEvent {
  event: unknown
}

const bufferIntervalInMillis = 15 * 1000

export async function logsForwarder(ctx: Context, next: () => Promise<any>) {
  setImmediate(async () => {
    startEventSource(ctx)
  })

  ctx.status = 200
  ctx.set('Cache-Control', 'no-cache')

  await next()
}

function startEventSource(ctx: Context) {
  const {
    vtex: { account, workspace, VtexIdClientAutCookie },
    splunk: { host, port, token },
  } = ctx

  const es = new LogSource(account, workspace, {
    headers: {
      Authorization: VtexIdClientAutCookie,
      'User-Agent': `splunk-forwarder#${host}-${port}`,
    },
  })

  const splunk = new Splunk(host, port, {
    'Content-Type': 'application/json',
    Authorization: `Splunk ${token}`,
  })

  const buffer = new LogsBulk(splunk)

  es.onopen = () => {
    console.debug('connection started')
    setTimeout(async () => {
      await buffer.sendBulk()
      console.debug('Closing stream')
      es.close()
    }, bufferIntervalInMillis)
  }

  es.onerror = (err) => {
    console.error(`Error reading logs: ${JSON.stringify(err, null, 2)}`)
  }

  es.addEventListener('message', async (message: Message) => {
    console.debug({ message })
    buffer.addMessage(JSON.parse(message.data))
  })
}

class LogsBulk {
  private messages: SplunkEvent[]

  constructor(private client: Splunk) {
    this.messages = []
  }

  public async addMessage(msg: Message) {
    console.debug('message added to buffer')
    this.messages.push(splunkEvent(msg))
  }

  public async sendBulk() {
    if (this.messages.length > 0) {
      console.debug(`sending bulk with ${this.messages.length} logs`)
      await this.client.postLog(this.messages)
    }
  }
}

function splunkEvent(msg: Message): SplunkEvent {
  return { event: msg }
}

```


[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 reskyt-pixel/docs/README.md from the reskyt-pixel VTEX app.

[Assistant]
Here's the implementation:

```markdown
# Reskyt Pixel

This pixel renders a banner with information about a downloadable app

![IMG_6126](https://user-images.githubusercontent.com/50715158/125049081-7ce58700-e098-11eb-8568-debb9ccac088.jpg)

### How to use it

- Open the VTEX App Store and install this app on your store.
- Now, open the app settings on your admin and fill in the Extension options.

```


[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 reskyt-pixel/react/index.tsx from the reskyt-pixel VTEX app.

[Assistant]
Here's the implementation:

```tsx
import { canUseDOM } from 'vtex.render-runtime'
import { reskytHtml } from './utils/reskyt'
import type { PixelMessage } from './typings/events'
import { getMobileUserAgent } from './utils/getMobileUserAgent'
import { getCookies } from './utils/getCookies'
import { checkConfiguration } from './utils/checkConfiguration'

export function handleEvents(e: PixelMessage) {
  switch (e.data.eventName) {
    case 'vtex:pageView': {
      const mobileUserAgentLabel = getMobileUserAgent(navigator.userAgent)

      const hasConfig = checkConfiguration(window.__reskytSettings)

      if (!hasConfig) {
        console.error('Please configure Reskyt App settings')
      } else if (mobileUserAgentLabel) {
        const {
          reskytAppName,
          reskytFabName,
          reskytHtmlTitle,
          reskytDownloadLink,
          reskytAppImage,
          reskytAppImageAlt,
          reskytStorePrefix,
          reskytDownloadCTA
        } = window.__reskytSettings

        const appConfig = {
          htmlTitle: decodeURIComponent(reskytHtmlTitle),
          downloadLink: decodeURIComponent(reskytDownloadLink),
          appImage: decodeURIComponent(reskytAppImage),
          appImageAlt: decodeURIComponent(reskytAppImageAlt),
          appName: decodeURIComponent(reskytAppName),
          fabName: decodeURIComponent(reskytFabName),
          storePrefix: decodeURIComponent(reskytStorePrefix),
          downloadCTA: decodeURIComponent(reskytDownloadCTA)
        }

        const resky = reskytHtml(appConfig)
        const reskydocDOM = document
          .createRange()
          .createContextualFragment(resky)

        document.body.appendChild(reskydocDOM)
        const hasCookie =
          !!getCookies('is_app_install_bar') ||
          !!getCookies('reskyt-install-app')

        const nodeToShow = document.getElementById('href-download-app')
        const labelNode = document.getElementById('platform-app')

        if (!hasCookie && nodeToShow && labelNode) {
          labelNode.innerHTML = mobileUserAgentLabel
          nodeToShow.style.display = 'block'
        }
      }

      break
    }

    default: {
      break
    }
  }
}

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 reskyt-pixel/react/package.json from the reskyt-pixel VTEX app.

[Assistant]
Here's the implementation:

```json
{
  "scripts": {
    "test": "vtex-test-tools test"
  },
  "devDependencies": {
    "@apollo/react-testing": "^3.1.3",
    "@types/graphql": "^14.5.0",
    "@types/jest": "^25.1.5",
    "@types/node": "^13.11.0",
    "@types/react": "^16.9.31",
    "@types/react-intl": "^3.0.0",
    "@vtex/test-tools": "^3.1.0",
    "apollo-cache-inmemory": "^1.6.5",
    "apollo-client": "^2.6.8",
    "graphql": "^14.5.4",
    "react-intl": "^3.11.0",
    "typescript": "3.9.7",
    "vtex.pixel-interfaces": "http://vtex.vtexassets.com/_v/public/typings/v1/vtex.pixel-interfaces@1.1.1/public/_types/react",
    "vtex.render-runtime": "http://vtex.vtexassets.com/_v/public/typings/v1/vtex.render-runtime@8.124.3/public/@types/vtex.render-runtime"
  },
  "dependencies": {
    "html-template-tag": "^3.2.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 reskyt-pixel/store/interfaces.json from the reskyt-pixel VTEX app.

[Assistant]
Here's the implementation:

```json
{
  "pixel.reskyt-pixel": {
    "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 reskyt-pixel/public/metadata/messages/es-AR.json from the reskyt-pixel VTEX app.

[Assistant]
Here's the implementation:

```json
{
  "name": "",
  "headline": "",
  "overview": "",
  "features": [],
  "additionalInformation": "",
  "websiteURL": "https://vtex.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 reskyt-pixel/public/metadata/messages/pt-BR.json from the reskyt-pixel VTEX app.

[Assistant]
Here's the implementation:

```json
{
  "name": "",
  "headline": "",
  "overview": "",
  "features": [],
  "additionalInformation": "",
  "websiteURL": "https://vtex.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 reskyt-pixel/public/metadata/messages/en-US.json from the reskyt-pixel VTEX app.

[Assistant]
Here's the implementation:

```json
{
  "name": "",
  "headline": "",
  "overview": "",
  "features": [],
  "additionalInformation": "",
  "websiteURL": "https://vtex.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 reskyt-pixel/react/typings/events.d.ts from the reskyt-pixel VTEX app.

[Assistant]
Here's the implementation:

```typescript
export interface PixelMessage extends MessageEvent {
  data:
    | ProductViewData
    | ProductClickData
    | OrderPlacedData
    | OrderPlacedTrackedData
    | PageViewData
    | ProductImpressionData
    | AddToCartData
    | RemoveToCartData
    | CartChangedData
    | HomePageInfo
    | ProductPageInfoData
    | SearchPageInfoData
    | UserData
    | CartIdData
    | PromoViewData
    | PromotionClickData
}

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

export interface PageInfoData extends EventData {
  event: 'pageInfo'
  eventName: 'vtex:pageInfo'
  accountName: string
  pageTitle: string
  pageUrl: string
}

export interface UserData extends PageInfoData {
  eventType: 'userData'
  eventName: 'vtex:userData'
  firstName?: string
  lastName?: string
  document?: string
  id?: string
  email?: string
  phone?: string
  isAuthenticated: boolean
}

export interface CartIdData extends PageInfoData {
  eventType: 'cartId'
  eventName: 'vtex:cartId'
  cartId: string
}

export interface HomePageInfo extends PageInfoData {
  eventType: 'homeView'
}

export interface ProductPageInfoData extends PageInfoData {
  eventType: 'productPageInfo'
}

export interface SearchPageInfoData extends PageInfoData {
  eventType:
    | 'internalSiteSearchView'
    | 'categoryView'
    | 'departmentView'
    | 'emptySearchView'
  category?: CategoryMetaData
  department?: DepartmentMetaData
  search?: SearchMetaData
}

interface CategoryMetaData {
  id: string
  name: string
}

interface DepartmentMetaData {
  id: string
  name: string
}

interface SearchMetaData {
  term: string
  category: CategoryMetaData
  results: number
}

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 CartChangedData extends EventData {
  event: 'cartChanged'
  eventName: 'vtex:cartChanged'
  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: ProductSummary
  list?: string
}

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

export interface CartData extends EventData {
  event: 'cart'
  eventName: 'vtex:cart'
  orderForm: OrderForm
}

export interface PromoViewData extends EventData {
  event: 'promoView'
  eventName: 'vtex:promoView'
  promotions: Promotion[]
}

export interface PromotionClickData extends EventData {
  event: 'promotionClick'
  eventName: 'vtex:promotionClick'
  promotions: Promotion[]
}

interface Promotion {
  id?: string
  name?: string
  creative?: string
  position?: string
}

interface CartItem {
  brand: string
  ean: string
  category: string
  detailUrl: string
  imageUrl: string
  name: string
  price: number
  productId: string
  productRefId: string
  quantity: number
  seller: string
  sellerName: string
  skuId: string
  variant: string
}

export interface OrderForm {
  id: string
  items: CartItem[]
}

export interface Order {
  accountName: string
  corporateName: string
  coupon: string
  currency: string
  openTextField: string
  orderGroup: string
  salesChannel: string
  visitorAddressCity: string
  visitorAddressComplement: string
  visitorAddressCountry: string
  visitorAddressNeighborhood: string
  visitorAddressNumber: string
  visitorAddressPostalCode: string
  visitorAddressState: string
  visitorAddressStreet: string
  visitorContactInfo: string[]
  visitorContactPhone: string
  visitorType: string
  transactionId: string
  transactionDate: string
  transactionAffiliation: string
  transactionTotal: number
  transactionShipping: number
  transactionSubtotal: number
  transactionDiscounts: number
  transactionTax: number
  transactionCurrency: string
  transactionPaymentType: PaymentType[]
  transactionShippingMethod: ShippingMethod[]
  transactionLatestShippingEstimate: Date
  transactionProducts: ProductOrder[]
  transactionPayment: {
    id: string
  }
}

export interface Impression {
  product: ProductSummary
  position: number
}

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

export interface ShippingMethod {
  itemId: string
  selectedSla: string
}

export 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
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
  components: any[]
  measurementUnit: string
  unitMultiplier: number
}

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

export interface Product {
  brand: string
  brandId: string
  categories: string[]
  categoryId: string
  categoryTree: Array<{ id: string; name: string }>
  detailUrl: string
  items: Item[]
  linkText: string
  productId: string
  productName: string
  productReference: string
  selectedSku: Item
}

export interface Item {
  itemId: string
  name: string
  ean: string
  referenceId: { Key: string; Value: string }
  imageUrl: string
  sellers: Seller[]
}

export interface ProductSummary {
  brand: string
  brandId: string
  categories: string[]
  items: ItemSummary[]
  linkText: string
  productId: string
  productName: string
  productReference: string
  sku: ItemSummary
}

interface ItemSummary {
  itemId: string
  ean: string
  name: string
  referenceId: { Key: string; Value: string }
  seller: Seller
  sellers: Seller[]
}

export interface Seller {
  commertialOffer: CommertialOffer
  sellerId: string
  sellerName: string
}

export interface CommertialOffer {
  Price: number
  ListPrice: number
  AvailableQuantity: number
}

```


[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 reskyt-pixel/react/typings/global.d.ts from the reskyt-pixel VTEX app.

[Assistant]
Here's the implementation:

```typescript
interface Window extends Window {
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
  __reskytSettings: {
    reskytAppName: string
    reskytFabName: string
    reskytHtmlTitle: string
    reskytDownloadLink: string
    reskytAppImage: string
    reskytAppImageAlt: string
    reskytStorePrefix: string
    reskytDownloadCTA: string
  }
}

```


[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 reskyt-pixel/react/typings/reskytConfig.d.ts from the reskyt-pixel VTEX app.

[Assistant]
Here's the implementation:

```typescript
export interface ReskytSettings {
  reskytAppName: string
  reskytFabName: string
  reskytHtmlTitle: string
  reskytDownloadLink: string
  reskytAppImage: string
  reskytAppImageAlt: string
}

```


[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 reskyt-pixel/react/utils/getMobileUserAgent.ts from the reskyt-pixel VTEX app.

[Assistant]
Here's the implementation:

```typescript
export const getMobileUserAgent = (userAgent: string): string => {

  let message = ''

  if (/Android/i.test(userAgent)) {
    message = 'Google Play'
  }

  if (/iPhone|iPad|iPod/i.test(userAgent)) {
    message = 'App Store'
  }

  if (/Windows Phone/i.test(userAgent)) {
    message = 'Windows Phone Store'
  }

  return message
}

```


[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 reskyt-pixel/react/utils/reskyt.ts from the reskyt-pixel VTEX app.

[Assistant]
Here's the implementation:

```typescript
// import {html} from 'lit-html'
import html from 'html-template-tag'

interface AppConfig {
  htmlTitle: string
  downloadLink: string
  appImage: string
  appImageAlt: string
  appName: string
  fabName: string
  storePrefix: string
  downloadCTA: string
}

export const reskytHtml = ({
  htmlTitle,
  downloadLink,
  appImage,
  appImageAlt,
  appName,
  fabName,
  storePrefix,
  downloadCTA
}: AppConfig) => html`<html>
  <head>
    <title>${htmlTitle}</title>
    <style>
      #install-app {
        width: 100%;
        right: 0;
        position: fixed;
        bottom: 0px;
        z-index: 900;
        color: black;
        background-color: #f1f5f9;
        font-family: Verdana, Arial, sans-serif;
        font-size: 12px;
        border-top: 1px solid #e8ecf1;
        min-height: 75px;
      }

      .close-install-app {
        padding: 8px 5px;
        display: block;
        width: 20px;
        height: 40px;
        font-family: Helvetica, Arial, Verdana, sans-serif;
        font-weight: normal;
        font-size: 14px;
        text-align: center;
        cursor: pointer !important;
        font-weight: bold;
        color: #666;
        position: absolute;
        margin-top: 20px;
      }

      .img-app {
        width: 57px;
        border: 1px solid #e8ecf1;
        -webkit-border-radius: 8px;
        -moz-border-radius: 8px;
        border-radius: 8px;
      }

      .img-app,
      .content-app {
        float: left;
      }

      .fab-app {
        color: #979797;
        font-size: 11px;
      }

      .name-app,
      .title-app,
      .fab-app {
        margin-left: 70px;
        padding: 1px 0;
      }

      .name-app {
        font-weight: bold;
        margin-top: 2px;
        overflow: hidden;
        height: 16px;
      }

      .content-app {
        margin-top: 8px;
        margin-right: 34px;
        margin-left: 30px;
        position: absolute;
      }

      .view-install-app {
        color: blue;
        line-height: 25px;
        margin-top: 23px;
        text-transform: uppercase;
        position: absolute;
        right: 7px;
      }
    </style>
    <script>
      function closeBar() {
        dias_expire = 7 /*Dias que queremos que pasen hasta que se vuelva a mostrar la barra*/
        setCookie('reskyt-install-app', 1, dias_expire)
        document.getElementById('href-download-app').style.display = 'none'
        return false
      }

      function setCookie(cname, cvalue, exdays) {
        var d = new Date()
        d.setTime(d.getTime() + exdays * 24 * 60 * 60 * 1000)
        var expires = 'expires=' + d.toUTCString()
        document.cookie =
          cname +
          '=' +
          cvalue +
          ';' +
          expires +
          ';path=/' /*Añadir ;SameSite=None;Secure en caso de que la cookie tenga que ser accesible entre iFrame*/
      }

      function getCookie(cname) {
        var name = cname + '='
        var decodedCookie = decodeURIComponent(document.cookie)
        var ca = decodedCookie.split(';')
        for (var i = 0; i < ca.length; i++) {
          var c = ca[i]
          while (c.charAt(0) == ' ') {
            c = c.substring(1)
          }
          if (c.indexOf(name) == 0) {
            return c.substring(name.length, c.length)
          }
        }
        return ''
      }

      url = window.location.href
      if (url.indexOf('customapp=') != -1) {
        setCookie('is_app_install_bar', 1, 365)
        document.getElementById('href-download-app').style.display = 'none'
      }
    </script>
  </head>
  <body>
    <a
      href=${downloadLink}
      class="href-download-app"
      id="href-download-app"
      style="display:none;"
    >
      <div id="install-app">
        <span class="close-install-app" onclick="return closeBar();"
          ><span>x</span></span
        >
        <div class="content-app">
          <img class="img-app" src=${appImage} alt=${appImageAlt} />
          <div class="name-app">${appName}</div>
          <div class="fab-app">${fabName}</div>
          <div class="title-app">
            ${storePrefix} <span id="platform-app"></span>
          </div>
        </div>
        <span class="view-install-app">${downloadCTA}</span>
      </div>
    </a>
  </body>
</html>`

```


[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 reskyt-pixel/react/utils/checkConfiguration.ts from the reskyt-pixel VTEX app.

[Assistant]
Here's the implementation:

```typescript
interface ReskytSettings {
  reskytAppName: string
  reskytFabName: string
  reskytHtmlTitle: string
  reskytDownloadLink: string
  reskytAppImage: string
  reskytAppImageAlt: string
}

export const checkConfiguration = (config: ReskytSettings): boolean => {
  const keys = Object.keys(config)

  if (!keys.length) return false

  for (let i = 0; i < keys.length; i++) {
    if (!config[keys[i] as keyof ReskytSettings]) {
      return false
    }
  }

  return true
}

```


[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 reskyt-pixel/react/utils/getCookies.ts from the reskyt-pixel VTEX app.

[Assistant]
Here's the implementation:

```typescript
export const getCookies = (cookieName: string): string => {
  const name = `${cookieName}=`
  const decodedCookie = decodeURIComponent(document.cookie)
  const cookieJar = decodedCookie.split(';')

  for (let i = 0; i < cookieJar.length; i++) {
    let cookie = cookieJar[i]

    while (cookie.charAt(0) === ' ') {
      cookie = cookie.substring(1)
    }

    if (cookie.indexOf(name) === 0) {
      return cookie.substring(name.length, cookie.length)
    }
  }

  return ''
}

```


[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 shopify/server/server.js from the shopify VTEX app.

[Assistant]
Here's the implementation:

```javascript
import "@babel/polyfill";
import dotenv from "dotenv";
import "isomorphic-fetch";
import createShopifyAuth, { verifyRequest } from "@shopify/koa-shopify-auth";
import Shopify, { ApiVersion } from "@shopify/shopify-api";
import Koa from "koa";
import next from "next";
import Router from "koa-router";
import koaBody from "koa-body";
import sequelize from "./vtex/connection";
import Settings from "./vtex/Settings";
import {
  logActivity,
  handleProduct,
  handleSimulation,
  orderPlacement,
  orderCancel,
  cancelMarketplaceOrder,
  fulfillOrder,
  notifyMarketplaceInvoice,
  updateMarketplaceTracking
} from "./vtex/vtexHandlers";

dotenv.config();
const port = parseInt(process.env.PORT, 10) || 8081;
const dev = process.env.NODE_ENV !== "production";
const app = next({
  dev,
});
const handle = app.getRequestHandler();

Shopify.Context.initialize({
  API_KEY: process.env.SHOPIFY_API_KEY,
  API_SECRET_KEY: process.env.SHOPIFY_API_SECRET,
  SCOPES: process.env.SCOPES.split(","),
  HOST_NAME: process.env.HOST.replace(/https:\/\//, ""),
  API_VERSION: ApiVersion.October20,
  IS_EMBEDDED_APP: true,
  // This should be replaced with your preferred storage strategy
  SESSION_STORAGE: new Shopify.Session.MemorySessionStorage(),
});

// Storing the currently active shops in memory will force them to re-login when your server restarts. You should
// persist this object in your app.
const ACTIVE_SHOPIFY_SHOPS = {};

app.prepare().then(async () => {
  await sequelize.sync();

  const server = new Koa();
  const router = new Router();
  server.keys = [Shopify.Context.API_SECRET_KEY];
  server.use(
    createShopifyAuth({
      async afterAuth(ctx) {
        // Access token and shop available in ctx.state.shopify
        const { shop, accessToken, scope } = ctx.state.shopify;
        const host = ctx.query.host;
        ACTIVE_SHOPIFY_SHOPS[shop] = scope;

        await Settings.findOne({ where: { shop: shop } }).then(function (obj) {
          if (obj) {
            obj.update({ shopify_token: accessToken });
          } else {
            Settings.create({ shop: shop, shopify_token: accessToken });
          }
        });

        const response = await Shopify.Webhooks.Registry.register({
          shop,
          accessToken,
          path: "/webhooks",
          topic: "APP_UNINSTALLED",
          webhookHandler: async (topic, shop, body) =>
            delete ACTIVE_SHOPIFY_SHOPS[shop],
        });

        if (!response.success) {
          console.log(
            `Failed to register APP_UNINSTALLED webhook: ${response.result}`
          );
        }

        await Shopify.Webhooks.Registry.register({
          shop,
          accessToken,
          path: "/webhooks",
          topic: "PRODUCTS_UPDATE",
          webhookHandler: async (topic, shop, body) =>
            handleProduct(JSON.parse(body), shop),
        });

        await Shopify.Webhooks.Registry.register({
          shop,
          accessToken,
          path: "/webhooks",
          topic: "ORDERS_CANCELLED",
          webhookHandler: async (topic, shop, body) =>
            cancelMarketplaceOrder(JSON.parse(body), shop),
        });

        await Shopify.Webhooks.Registry.register({
          shop,
          accessToken,
          path: "/webhooks",
          topic: "ORDERS_PAID",
          webhookHandler: async (topic, shop, body) =>
            notifyMarketplaceInvoice(JSON.parse(body), shop),
        });

        await Shopify.Webhooks.Registry.register({
          shop,
          accessToken,
          path: "/webhooks",
          topic: "ORDERS_UPDATED",
          webhookHandler: async (topic, shop, body) =>
            updateMarketplaceTracking(JSON.parse(body), shop),
        });

        router.post("/admin/apps/vtex_connector", koaBody(), async (ctx) => {
          const query = new URLSearchParams(ctx.request.header.referer);
          const shopParam = query.get("shop");
          const hostParam = query.get("host");

          ctx.type = "application/json; charset=utf-8";

          if (
            hostParam === null ||
            shopParam === null ||
            ACTIVE_SHOPIFY_SHOPS[shopParam] === undefined
          ) {
            ctx.status = 401;
            ctx.body = JSON.stringify({ message: "Unauthorized!" });
          } else {
            const payload = JSON.parse(ctx.request.body);

            const model = await Settings.findOne({
              where: { shop: shop },
            }).then(function (obj) {
              if (obj) {
                return obj.update(payload);
              }
              payload.shop = shop;
              return Settings.create(payload);
            });

            ctx.status = 200;
            ctx.body = JSON.stringify(model.toJSON());
          }
        });

        // Redirect to app with shop parameter upon auth
        ctx.redirect(`/?shop=${shop}&host=${host}`);
      },
    })
  );

  const handleRequest = async (ctx) => {
    await handle(ctx.req, ctx.res);
    ctx.respond = false;
    ctx.res.statusCode = 200;
  };

  router.post("/webhooks", async (ctx) => {
    try {
      await Shopify.Webhooks.Registry.process(ctx.req, ctx.res);
      console.log(`Webhook processed, returned status code 200`);
    } catch (error) {
      console.log(`Failed to process webhook: ${error}`);
    }
  });

  router.post(
    "/graphql",
    verifyRequest({ returnHeader: true }),
    async (ctx, next) => {
      await Shopify.Utils.graphqlProxy(ctx.req, ctx.res);
    }
  );

  router.get("/admin/apps/vtex_connector_settings", async (ctx) => {
    const query = new URLSearchParams(ctx.request.header.referer);
    const shopParam = query.get("shop");
    const hostParam = query.get("host");

    ctx.type = "application/json; charset=utf-8";
    ctx.status = 200;

    if (
      hostParam === null ||
      shopParam === null ||
      ACTIVE_SHOPIFY_SHOPS[shopParam] === undefined
    ) {
      ctx.body = JSON.stringify({});
    } else {
      const response = await Settings.findOne({ where: { shop: shopParam } });
      if (response === null) {
        ctx.body = JSON.stringify({});
      } else {
        ctx.body = JSON.stringify(response.toJSON());
      }
    }
  });

  router.post("/api/fulfillment/pvt/orderForms/simulation", koaBody(), handleSimulation);
  router.post("/api/fulfillment/pvt/orders", koaBody(), orderPlacement);
  router.post("/api/fulfillment/pvt/orders/:order_id/cancel", koaBody(), orderCancel);
  router.post("/api/fulfillment/pvt/orders/:order_id/fulfill", koaBody(), fulfillOrder);

  router.get("(/_next/static/.*)", handleRequest); // Static content is clear
  router.get("/_next/webpack-hmr", handleRequest); // Webpack content is clear
  router.get("(.*)", async (ctx) => {
    const shop = ctx.query.shop;

    // This shop hasn't been seen yet, go through OAuth to create a session
    if (ACTIVE_SHOPIFY_SHOPS[shop] === undefined) {
      ctx.redirect(`/auth?shop=${shop}`);
    } else {
      await handleRequest(ctx);
    }
  });

  server.use(async (ctx, next) => {
    await logActivity(ctx, next)
  })

  server.use(router.allowedMethods());
  server.use(router.routes());

  server.listen(port, () => {
    console.log(`> Ready on http://localhost:${port}`);
  });
});

```


[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 shopify/server/index.js from the shopify VTEX app.

[Assistant]
Here's the implementation:

```javascript
require('@babel/register')({
  presets: ['@babel/preset-env'],
  ignore: ['node_modules']
});

// Import the rest of our application.
module.exports = require('./server.js');

```


[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 shopify/pages/_app.js from the shopify VTEX app.

[Assistant]
Here's the implementation:

```javascript
import ApolloClient from "apollo-boost";
import { ApolloProvider } from "react-apollo";
import App from "next/app";
import { AppProvider } from "@shopify/polaris";
import { Provider, useAppBridge } from "@shopify/app-bridge-react";
import { authenticatedFetch } from "@shopify/app-bridge-utils";
import { Redirect } from "@shopify/app-bridge/actions";
import "@shopify/polaris/dist/styles.css";
import translations from "@shopify/polaris/locales/en.json";

function userLoggedInFetch(app) {
  const fetchFunction = authenticatedFetch(app);

  return async (uri, options) => {
    const response = await fetchFunction(uri, options);

    if (
      response.headers.get("X-Shopify-API-Request-Failure-Reauthorize") === "1"
    ) {
      const authUrlHeader = response.headers.get(
        "X-Shopify-API-Request-Failure-Reauthorize-Url"
      );

      const redirect = Redirect.create(app);
      redirect.dispatch(Redirect.Action.APP, authUrlHeader || `/auth`);
      return null;
    }

    return response;
  };
}

function MyProvider(props) {
  const app = useAppBridge();

  const client = new ApolloClient({
    fetch: userLoggedInFetch(app),
    fetchOptions: {
      credentials: "include",
    },
  });

  const Component = props.Component;

  return (
    <ApolloProvider client={client}>
      <Component {...props} />
    </ApolloProvider>
  );
}

class MyApp extends App {
  render() {
    const { Component, pageProps, host } = this.props;
    return (
      <AppProvider i18n={translations}>
        <Provider
          config={{
            apiKey: API_KEY,
            host: host,
            forceRedirect: true,
          }}
        >
          <MyProvider Component={Component} {...pageProps} />
        </Provider>
      </AppProvider>
    );
  }
}

MyApp.getInitialProps = async ({ ctx }) => {
  return {
    host: ctx.query.host,
  };
};

export default MyApp;

```


[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 shopify/pages/index.js from the shopify VTEX app.

[Assistant]
Here's the implementation:

```javascript
import { Heading, Page, Form, Button, FormLayout, TextField } from "@shopify/polaris";
import React from 'react';

class Index extends React.Component {

  constructor(props) {
    super(props);
    this.state = {
      account_name: '',
      app_key: '',
      app_token: '',
      seller_id: '',
      access_token: '',
      account_name_error: null,
      app_key_error: null,
      app_token_error: null,
      seller_id_error: null,
      access_token_error: null
    };
  }

  componentDidMount() {
    this.getSettings()
  }

  async getSettings() {
    await fetch('/admin/apps/vtex_connector_settings')
      .then(response => response.json())
      .then(json => {
        if (Object.keys(json).length) {
          const { account_name, app_key, app_token, seller_id, access_token } = json
          this.setState({ account_name, app_key, app_token, seller_id, access_token })
        }
      })
  }

  handleSubmit() {
    const { account_name, app_key, app_token, seller_id, access_token } = this.state
    if (this.validateForm()) {
      fetch('/admin/apps/vtex_connector', {
        method: 'POST',
        body: JSON.stringify({ account_name, app_key, app_token, seller_id, access_token })
      })
        .then(response => response.json())
        .then(() => window.location.reload())
    }
  }

  validateForm() {
    const {
      account_name,
      app_key,
      app_token,
      seller_id,
      access_token
    } = this.state

    const account_name_error = account_name !== "" ? null : "Required"
    const app_key_error = app_key !== "" ? null : "Required"
    const app_token_error = app_token !== "" ? null : "Required"
    const seller_id_error = seller_id !== "" ? null : "Required"
    const access_token_error = access_token !== "" ? null : "Required"

    this.setState({
      account_name_error,
      app_key_error,
      app_token_error,
      seller_id_error,
      access_token_error
    })

    return !account_name_error
      && !app_key_error
      && !app_token_error
      && !seller_id_error
      && !access_token_error;
  }

  render() {
    return (
      <Page>
        <Heading>VTEX connector settings</Heading>
        <br/>
        <Form onSubmit={() => this.handleSubmit()}>
          <FormLayout>
            <TextField
              value={this.state.account_name}
              onChange={value => this.setState({ account_name: value })}
              label="Marketplace account"
              type="text"
              error={this.state.account_name_error}
            />

            <TextField
              value={this.state.app_key}
              onChange={value => this.setState({ app_key: value })}
              label="App key"
              type="text"
              error={this.state.app_key_error}
            />

            <TextField
              value={this.state.app_token}
              onChange={value => this.setState({ app_token: value })}
              label="App token"
              type="text"
              error={this.state.app_token_error}
            />

            <TextField
              value={this.state.seller_id}
              onChange={value => this.setState({ seller_id: value })}
              label="Seller ID"
              type="text"
              error={this.state.seller_id_error}
            />

            <TextField
              value={this.state.access_token}
              onChange={value => this.setState({ access_token: value })}
              label="Fulfillment API Access Token"
              type="text"
              error={this.state.access_token_error}
            />

            <Button submit>Submit</Button>
          </FormLayout>
        </Form>
      </Page>
    )
  }

}

export default 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 shopify/server/vtex/vtexHelper.js from the shopify VTEX app.

[Assistant]
Here's the implementation:

```javascript
import Shopify from "@shopify/shopify-api";
import {getShippingZones, getShopData} from "./vtexHandlers";

export const priceMultiplier = 100

export async function formattedProductData(skuId, data, shopSettings) {
  let product = data.variants.filter(function(item) {
    return item.id === skuId
  });
  product = product[0]
  const sku = `${shopSettings.seller_id}-${skuId}`
  const variant = await getVariant(skuId, shopSettings)
  const shopData = await getShopData(shopSettings)

  return {
    ProductName: `${data.title} ${product.title}`,
    ProductId: data.id,
    ProductDescription: data.body_html,
    BrandName: data.vendor??"NONAME",
    SkuName: sku,
    SellerId: shopSettings.seller_id,
    Height: 1,
    Width: 1,
    Length: 1,
    WeightKg: product.weight,
    RefId: sku,
    SellerStockKeepingUnitId: skuId,
    CategoryFullPath: variant?.product?.collections?.edges[0]?.node?.title ?? "NONAME",
    SkuSpecifications: await specifications(skuId, data),
    ProductSpecifications: await specifications(skuId, data),
    Images: await images(data),
    MeasurementUnit: 'un',
    UnitMultiplier: 1,
    AvailableQuantity: product.inventory_quantity,
    Pricing: {
      Currency: shopData.shop.currency,
      SalePrice: product.price,
      CurrencySymbol: shopData.shop.currency,
    },
  }
}

export async function getSimulationProducts(data, settings) {
  const response = []
  await Promise.all(data.items.map(async (item, index) => {
    await getVariant(item.id, settings)
      .then(variant => {
        response.push({
          id: item.id,
          requestIndex: index,
          quantity: item.quantity,
          price: variant.price * priceMultiplier,
          listPrice: variant.price * priceMultiplier,
          sellingPrice: variant.price * priceMultiplier,
          measurementUnit: 'un',
          merchantName: null,
          priceValidUntil: null,
          seller: settings.seller_id,
          unitMultiplier: 1,
          attachmentOfferings: [],
          offerings: [],
          priceTags: [],
          availability: variant.inventoryQuantity?'available':'unavailable'
        })
      })
  }))
  return response
}

export async function getSimulationLogisticInfo(data, settings) {
  const response = []
  let shipping = 0
  const shippingZones = await getShippingZones(settings)
  let shippingZone = shippingZones.shipping_zones.filter(function(item) {
    return item.name === "Domestic"
  })
  if (shippingZone.length) {
    shippingZone = shippingZone[0]
    if (shippingZone.price_based_shipping_rates.length) {
      shipping = shippingZone.price_based_shipping_rates[0].price * priceMultiplier
    }
  }

  await Promise.all(data.items.map(async (item, index) => {
    await getVariant(item.id, settings)
      .then(variant => {
        response.push({
          itemIndex: index,
          quantity: item.quantity,
          stockBalance: variant.inventoryQuantity,
          shipsTo: [ ...[], data?.country ],
          slas: [
            {
              id: 'Normal',
              deliveryChannel: 'delivery',
              name: 'Normal',
              shippingEstimate: '1bd',
              price: shipping / data.items.length
            }
          ],
          deliveryChannels: [
            {
              id: 'delivery',
              stockBalance: variant.inventoryQuantity
            }
          ]
        })
      })
  }))
  return response
}

export async function images(data) {
  const output = []

  await Promise.all(data.images.map(async (item) => {
      output.push({
        imageName: `Image${item.id}`,
        imageUrl: item.src
      })
    })
  )

  return output
}

export async function specifications(skuId, data) {
  const output = []

  let product = data.variants.filter(function(item) {
    return item.id === skuId
  });
  product = product[0]

  await Promise.all(data.options.map(async (item) => {
      if (product[`option${item.position}`]) {
        output.push({
          'FieldName': item.name,
          'FieldValues': [
            product[`option${item.position}`]
          ]
        })
      }
    })
  )

  return output
}

export async function getProduct(id, settings) {
  const client = new Shopify.Clients.Graphql(settings.shop, settings.shopify_token);

  const { body: { data: { product } } } =  await client.query({
    data: `{
      product(id: "gid://shopify/Product/${id}") {
          title,
          handle,
          variants(first: 1) {
            edges {
              node {
                id,
                price,
                inventoryQuantity
              }
            }
          }
        }
    }`,
  });

  return product;
}

export async function getVariant(id, settings) {
  const client = new Shopify.Clients.Graphql(settings.shop, settings.shopify_token);

  const { body: { data: { productVariant } } } =  await client.query({
    data: `{
      productVariant(id: "gid://shopify/ProductVariant/${id}") {
          title,
          price,
          inventoryQuantity,
          product {
            collections(first: 1) {
              edges {
                node {
                  title
                }
              }
            }
          }
        }
    }`,
  });

  return productVariant;
}

export async function formattedInvoiceData(data) {
  const items = await Promise.all(
    data.line_items.map(async (item) => {
      return {
        id: item.variant_id,
        quantity: item.quantity,
        price: item.price * priceMultiplier,
      };
    })
  );

  return {
    type: "Output",
    invoiceNumber: data.id,
    invoiceValue: data.current_total_price * priceMultiplier,
    issuanceDate: new Date().toISOString(),
    items: items
  }
}

```


[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 shopify/server/vtex/ActivityLogs.js from the shopify VTEX app.

[Assistant]
Here's the implementation:

```javascript
const { Sequelize } = require('sequelize');
const sequelize = require('./connection');

const ActivityLogs = sequelize.define('activity_logs', {
  created_at: Sequelize.STRING,
  action: Sequelize.STRING,
  request: Sequelize.STRING,
  response: Sequelize.STRING,
  type: Sequelize.STRING,
  shop: Sequelize.STRING
})

module.exports = ActivityLogs

```


[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 shopify/server/vtex/vtexClient.js from the shopify VTEX app.

[Assistant]
Here's the implementation:

```javascript
import Settings from "./Settings";
import { formattedProductData, formattedInvoiceData } from "./vtexHelper";

async function getShopSettings(shop) {
  return await Settings.findOne({where: {shop: shop}})
}

export const headers = (settings) => {
  return {
    'Content-Type': 'application/json; charset=utf-8',
    'Accept': 'application/json',
    'X-VTEX-API-AppKey': settings.app_key,
    'X-VTEX-API-AppToken': settings.app_token,
  }
}

export async function changeNotification(skuId, shop) {
  const shopSettings = (await getShopSettings(shop)).toJSON()

  return await fetch(`https://${shopSettings.account_name}.myvtex.com/api/catalog_system/pvt/skuseller/changenotification/${shopSettings.seller_id}/${skuId}`, {
    method: "POST",
    headers: headers(shopSettings)
  })
}

export async function sendSKUSuggestion(skuId, body, shop) {
  const shopSettings = (await getShopSettings(shop)).toJSON()
  const payload = await formattedProductData(skuId, body, shopSettings)

  if (payload.Images.length) {
    return await fetch(`https://api.vtex.com/${shopSettings.account_name}/suggestions/${shopSettings.seller_id}/${skuId}`, {
      method: "PUT",
      headers: headers(shopSettings),
      body: JSON.stringify(payload)
    })
  }
}

export async function cancelOrder(order_id, shop) {
  const shopSettings = (await getShopSettings(shop)).toJSON()
  return await fetch(`https://${shopSettings.account_name}.myvtex.com/api/oms/pvt/orders/${order_id}/cancel`, {
    method: "POST",
    headers: headers(shopSettings)
  })
}

export async function notifyInvoice(data, shop) {
  const shopSettings = (await getShopSettings(shop)).toJSON()
  const payload = await formattedInvoiceData(data)

  return await fetch(`https://${shopSettings.account_name}.myvtex.com/api/oms/pvt/orders/${data.reference}/invoice`, {
    method: "POST",
    headers: headers(shopSettings),
    body: JSON.stringify(payload)
  })
}

export async function updateTracking(data, shop) {
  const shopSettings = (await getShopSettings(shop)).toJSON()

  if (
    data
    && data.hasOwnProperty('fulfillments')
    && data.fulfillments[0].hasOwnProperty('tracking_number')
    && data.fulfillments[0].tracking_number
  ) {
    const payload = {
      trackingNumber: data.fulfillments[0].tracking_number,
      courier: data.fulfillments[0].tracking_company,
      trackingUrl: data.fulfillments[0].tracking_url,
    }

    return await fetch(`https://${shopSettings.account_name}.myvtex.com/api/oms/pvt/orders/${data.reference}/invoice/${data.id}`, {
      method: "PATCH",
      headers: headers(shopSettings),
      body: JSON.stringify(payload)
    })
  }
}

```


[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 shopify/server/vtex/connection.js from the shopify VTEX app.

[Assistant]
Here's the implementation:

```javascript
const { Sequelize } = require('sequelize');
const sequelize = new Sequelize({
  dialect: 'sqlite',
  storage: 'database.sqlite'
});

module.exports = sequelize;

```


[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 shopify/server/vtex/vtexHandlers.js from the shopify VTEX app.

[Assistant]
Here's the implementation:

```javascript
import {cancelOrder, changeNotification, notifyInvoice, sendSKUSuggestion, updateTracking} from "./vtexClient";
import Settings from "./Settings";
import ActivityLogs from "./ActivityLogs";
import { getSimulationLogisticInfo, getSimulationProducts } from "./vtexHelper";
import { generateOrderObject } from "../shopify/shopifyHelper";
import moment from "moment";

export async function logActivity(ctx, next) {
  let settings = null;

  await checkAuth(ctx).then(async (response) => {
    if (response) {
      settings = response.toJSON();
    }
  });

  await next()
    .then(() => {
      if (settings) {
        ActivityLogs.create({
          created_at: new Date().toString(),
          action: ctx.url,
          request: ctx.method,
          response: JSON.stringify(ctx.body),
          type: "success",
          shop: settings.shop,
        });
      }
    })
    .catch((error) => {
      if (settings) {
        ActivityLogs.create({
          created_at: new Date().toString(),
          action: ctx.url,
          request: ctx.method,
          response: JSON.stringify(error.toString()),
          type: "error",
          shop: settings.shop,
        });
      }
    });
}

async function checkAuth(ctx) {
  const params = ctx.request.url.split("?");
  const query = new URLSearchParams(params[1]);
  const token = query.get("token");
  return await Settings.findOne({ where: { access_token: token } });
}

export async function handleProduct(body, shop) {
  body.variants.map(async (item) => {
    await changeNotification(item.id, shop).then(async (response) => {
      if (response.status === 404) {
        await sendSKUSuggestion(item.id, body, shop);
      }
    });
  })
}

export const handleSimulation = async (ctx) => {
  await checkAuth(ctx).then(async (response) => {
    if (response) {
      const settings = response.toJSON();
      const payload = ctx.request.body;

      const items = await getSimulationProducts(payload, settings);
      const logisticsInfo = await getSimulationLogisticInfo(payload, settings);

      const body = {
        country: payload.country,
        postalCode: payload.postalCode,
        geoCoordinates: payload.geoCoordinates,
        pickupPoints: [],
        messages: [],
        items: items,
        logisticsInfo: logisticsInfo,
      };

      ctx.status = 200;
      ctx.body = body;
    }
  });
};

export const orderPlacement = async (ctx) => {
  await checkAuth(ctx).then(async (response) => {
    if (response) {
      const payload = ctx.request.body;
      const settings = response.toJSON();
      const orderBody = await generateOrderObject(payload, settings);

      const order = await fetch(
        `https://${settings.shop}/admin/api/2021-07/orders.json`,
        {
          headers: {
            "Content-Type": "application/json",
            "X-Shopify-Access-Token": settings.shopify_token,
          },
          method: "POST",
          body: JSON.stringify(orderBody),
        }
      );
      const orderResponse = await order.json();

      response = [{
        marketplaceOrderId: payload[0].marketplaceOrderId,
        orderId: orderResponse.order.id.toString(),
        followUpEmail: payload[0].clientProfileData.email,
        items: payload[0].items,
        clientProfileData: payload[0].clientProfileData,
        shippingData: payload[0].shippingData,
        paymentData: null
      }]

      ctx.status = 200;
      ctx.body = response;
    }
  });
};

export const orderCancel = async (ctx) => {
  await checkAuth(ctx).then(async (response) => {
    if (response) {
      const payload = ctx.request.body;
      const settings = response.toJSON();

      const orderCancellation = await fetch(
        `https://${settings.shop}/admin/api/2021-07/orders/${ctx.params.order_id}/cancel.json`,
        {
          headers: {
            "Content-Type": "application/json",
            "X-Shopify-Access-Token": settings.shopify_token,
          },
          method: "POST",
          body: JSON.stringify({}),
        }
      );
      await orderCancellation.json();

      response = {
        date: moment().format('YYYY-MM-DD HH:m:s'),
        marketplaceOrderId: payload.marketplaceOrderId,
        orderId: ctx.params.order_id,
        receipt: null
      }

      ctx.status = 200;
      ctx.body = response;
    }
  });
};

export async function cancelMarketplaceOrder(body, shop) {
  await cancelOrder(body.reference, shop);
}

export const fulfillOrder = async (ctx) => {
  await checkAuth(ctx).then(async (response) => {
    if (response) {
      const payload = ctx.request.body;
      const settings = response.toJSON();

      //this will capture the payment and marks the order ad paid, but it will automatically trigger the
      //ORDERS_PAID webhook witch will automatically send the invoice notification

      // const capture = await fetch(
      //   `https://${settings.shop}/admin/api/2021-07/orders/${ctx.params.order_id}/transactions.json`,
      //   {
      //     headers: {
      //       "Content-Type": "application/json",
      //       "X-Shopify-Access-Token": settings.shopify_token,
      //     },
      //     method: "POST",
      //     body: JSON.stringify({
      //       transaction: {
      //         kind: "capture",
      //         gateway: "manual"
      //       }
      //     }),
      //   }
      // );
      // await capture.json();

      response = {
        date: moment().format('YYYY-MM-DD HH:m:s'),
        marketplaceOrderId: payload.marketplaceOrderId,
        orderId: ctx.params.order_id,
        receipt: null
      }

      ctx.status = 200;
      ctx.body = response;
    }
  });
}

export async function notifyMarketplaceInvoice(body, shop) {
  await notifyInvoice(body, shop);
}

export async function updateMarketplaceTracking(body, shop) {
  await updateTracking(body, shop);
}

export async function getShopData(settings) {
  const data = await fetch(
    `https://${settings.shop}/admin/api/2021-07/shop.json`,
    {
      headers: {
        "Content-Type": "application/json",
        "X-Shopify-Access-Token": settings.shopify_token,
      },
      method: "GET",
    }
  );
  return await data.json()
}

export async function getShippingZones(settings) {
  const data = await fetch(
    `https://${settings.shop}/admin/api/2021-07/shipping_zones.json`,
    {
      headers: {
        "Content-Type": "application/json",
        "X-Shopify-Access-Token": settings.shopify_token,
      },
      method: "GET",
    }
  );
  return await data.json()
}

```


[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 shopify/server/vtex/Settings.js from the shopify VTEX app.

[Assistant]
Here's the implementation:

```javascript
const { Sequelize } = require('sequelize');
const sequelize = require('./connection');

const Settings = sequelize.define('settings', {
  account_name: Sequelize.STRING,
  app_key: Sequelize.STRING,
  app_token: Sequelize.STRING,
  seller_id: Sequelize.STRING,
  access_token: Sequelize.STRING,
  shop: Sequelize.STRING,
  shopify_token: Sequelize.STRING,
})

module.exports = Settings

```


[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 shopify/server/shopify/shopifyHelper.js from the shopify VTEX app.

[Assistant]
Here's the implementation:

```javascript
import {getVariant, priceMultiplier} from "../vtex/vtexHelper";

export async function generateOrderObject(data, settings) {
  const { clientProfileData, items, shippingData, marketplacePaymentValue } = data[0];

  const shippingCost = shippingData.logisticsInfo.reduce((result, item) => {
    return result + item.price
  }, 0)

  const products = await Promise.all(
    items.map(async (item) => {
      const variant = await getVariant(item.id, settings);
      return {
        title: variant.title,
        variant_id: item.id,
        quantity: item.quantity * item.unitMultiplier,
        price: item.price / item.unitMultiplier / priceMultiplier,
      };
    })
  );
  return {
    order: {
      line_items: products,
      shipping_lines: [
        {
          code: "INT.TP",
          price: shippingCost / priceMultiplier,
          title: "Standard",
          carrier_identifier: null,
          requested_fulfillment_service_id: null
        }
      ],
      customer: {
        first_name: clientProfileData.firstName,
        last_name: clientProfileData.lastName,
        email: clientProfileData.email,
      },
      billing_address: {
        first_name: clientProfileData.firstName,
        last_name: clientProfileData.lastName,
        address1: `${shippingData.address.street} ${shippingData.address.number}`,
        phone: clientProfileData.phone,
        city: shippingData.address.city,
        province: shippingData.address.state,
        country: shippingData.address.country,
        zip: shippingData.address.postalCode,
      },
      shipping_address: {
        first_name: clientProfileData.firstName,
        last_name: clientProfileData.lastName,
        address1: `${shippingData.address.street} ${shippingData.address.number}`,
        phone: clientProfileData.phone,
        city: shippingData.address.city,
        province: shippingData.address.state,
        country: shippingData.address.country,
        zip: shippingData.address.postalCode,
      },
      email: clientProfileData.email,
      financial_status: "pending",
      reference: data[0].marketplaceOrderId,
      fulfillment_status: "fulfilled",
      transactions: [
        {
          amount: marketplacePaymentValue / priceMultiplier,
          kind: "authorization",
          status: "success"
        }
      ]
    },
  };
}

```


[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 shopify/server/handlers/client.js from the shopify VTEX app.

[Assistant]
Here's the implementation:

```javascript
import ApolloClient from "apollo-boost";

export const createClient = (shop, accessToken) => {
  return new ApolloClient({
    uri: `https://${shop}/admin/api/2019-10/graphql.json`,
    request: operation => {
      operation.setContext({
        headers: {
          "X-Shopify-Access-Token": accessToken,
          "User-Agent": `shopify-app-node ${
            process.env.npm_package_version
          } | Shopify App CLI`
        }
      });
    }
  });
};

```


[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 shopify/server/handlers/index.js from the shopify VTEX app.

[Assistant]
Here's the implementation:

```javascript
import { createClient } from "./client";
import { getOneTimeUrl } from "./mutations/get-one-time-url";
import { getSubscriptionUrl } from "./mutations/get-subscription-url";

export { createClient, getOneTimeUrl, getSubscriptionUrl };

```


[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 shopify/server/handlers/mutations/get-one-time-url.js from the shopify VTEX app.

[Assistant]
Here's the implementation:

```javascript
import "isomorphic-fetch";
import { gql } from "apollo-boost";

export function ONETIME_CREATE(url) {
  return gql`
    mutation {
      appPurchaseOneTimeCreate(
        name: "test"
        price: { amount: 10, currencyCode: USD }
        returnUrl: "${url}"
        test: true
      ) {
        userErrors {
          field
          message
        }
        confirmationUrl
        appPurchaseOneTime {
          id
        }
      }
    }
  `;
}

export const getOneTimeUrl = async (ctx) => {
  const { client } = ctx;
  const confirmationUrl = await client
    .mutate({
      mutation: ONETIME_CREATE(process.env.HOST),
    })
    .then((response) => response.data.appPurchaseOneTimeCreate.confirmationUrl);
  return ctx.redirect(confirmationUrl);
};

```


[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 shopify/server/handlers/mutations/get-subscription-url.js from the shopify VTEX app.

[Assistant]
Here's the implementation:

```javascript
import "isomorphic-fetch";
import { gql } from "apollo-boost";

export function RECURRING_CREATE(url) {
  return gql`
    mutation {
      appSubscriptionCreate(
          name: "Super Duper Plan"
          returnUrl: "${url}"
          test: true
          lineItems: [
          {
            plan: {
              appUsagePricingDetails: {
                  cappedAmount: { amount: 10, currencyCode: USD }
                  terms: "$1 for 1000 emails"
              }
            }
          }
          {
            plan: {
              appRecurringPricingDetails: {
                  price: { amount: 10, currencyCode: USD }
              }
            }
          }
          ]
        ) {
            userErrors {
              field
              message
            }
            confirmationUrl
            appSubscription {
              id
            }
        }
    }`;
}

export const getSubscriptionUrl = async ctx => {
  const { client } = ctx;
  const confirmationUrl = await client
    .mutate({
      mutation: RECURRING_CREATE(process.env.HOST)
    })
    .then(response => response.data.appSubscriptionCreate.confirmationUrl);

  return ctx.redirect(confirmationUrl);
};

```


[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 bing-ads/docs/README.md from the bing-ads VTEX app.

[Assistant]
Here's the implementation:

```markdown
# Bing UET

**Universal Event Tracking**
Track how your clients activities after they click on your ad. Universal Event Tracking (UET) is an advanced tool that records everything or what users use on your site. Microsoft Advertising creates a UET tag and places it across your site to collect data that can track conversion goals and target your audience using remarketing lists.
For more information please visit, [Bing UET](https://about.ads.microsoft.com/en-us/resources/training/universal-event-tracking) website.

## App Installation
Open the VTEX APP Store and install the Bing UET app on your store.

or

Run the following command:

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

Next, open the app settings on your admin and fill the form with your Bing UET information.
```


[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 bing-ads/react/index.tsx from the bing-ads VTEX app.

[Assistant]
Here's the implementation:

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

function handleMessages(e: PixelMessage) {
  if (e.data.eventName === "vtex:orderPlaced") {
    window.uetq = window.uetq || [];
    window.uetq.push('event', 'purchase', {
      'transaction_id': e?.data?.transactionId,
      'ecomm_prodid': e?.data?.transactionProducts.map(item=>item.skuRefId),
      'ecomm_pagetype': 'purchase',
      'ecomm_totalvalue': e?.data?.transactionTotal,
      'revenue_value': e?.data?.transactionTotal,
      'currency': e?.data?.transactionCurrency,
      'items': e?.data?.transactionProducts.map(item=>({id:item.skuRefId, quantity:item.quantity, price:item.price}))
    })
}}

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

```


[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 bing-ads/react/package.json from the bing-ads VTEX app.

[Assistant]
Here's the implementation:

```json
{
  "scripts": {
    "test": "vtex-test-tools test"
  },
  "dependencies": {
    "ramda": "^0.26.1"
  },
  "devDependencies": {
    "@types/graphql": "^14.2.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",
    "prettier": "^1.18.2",
    "tslint-eslint-rules": "^5.4.0",
    "typescript": "3.9.7"
  },
  "version": "1.1.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 bing-ads/store/interfaces.json from the bing-ads VTEX app.

[Assistant]
Here's the implementation:

```json
{
  "pixel.bing": {
    "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 bing-ads/react/typings/events.d.ts from the bing-ads VTEX app.

[Assistant]
Here's the implementation:

```typescript
export interface PixelMessage extends MessageEvent {
  data:
    | ProductViewData
    | ProductClickData
    | OrderPlacedData
    | 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 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 bing-ads/react/typings/vtex.render-runtime.d.ts from the bing-ads 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 bing-ads/react/typings/global.d.ts from the bing-ads VTEX app.

[Assistant]
Here's the implementation:

```typescript
interface Event extends Event {
  data: any;
}

interface Window extends Window {
  uetq: 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 buyer-org-supplier/node/service.json from the buyer-org-supplier VTEX app.

[Assistant]
Here's the implementation:

```json
{
  "memory": 256,
  "ttl": 10,
  "timeout": 2,
  "minReplicas": 2,
  "maxReplicas": 4,
  "workers": 1,
  "routes": {
    "buyer-org-supplier": {
      "public": true,
      "path": "/buyer-org-supplier"
    }
  }
}

```


[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 buyer-org-supplier/node/package.json from the buyer-org-supplier VTEX app.

[Assistant]
Here's the implementation:

```json
{
  "license": "MIT",
  "devDependencies": {
    "@types/axios": "^0.14.0",
    "@types/co-body": "^6.1.0",
    "@types/jsonwebtoken": "^8.5.4",
    "vtex.buyer-org-supplier": "http://vtex.vtexassets.com/_v/public/typings/v1/vtex.buyer-org-supplier@0.4.1/public/_types/react"
  },
  "dependencies": {
    "@vtex/api": "6.45.6",
    "co-body": "^6.1.0",
    "jsonwebtoken": "^8.5.1"
  },
  "version": "0.6.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 buyer-org-supplier/node/index.ts from the buyer-org-supplier VTEX app.

[Assistant]
Here's the implementation:

```typescript
import type { ClientsConfig, ServiceContext } from '@vtex/api'
import { LRUCache, method, Service } from '@vtex/api'

import { Clients } from './clients'
import { createBuyerOrg } from './routes/createBuyerOrg'

const TIMEOUT_MS = 800
const memoryCache = new LRUCache<string, never>({ max: 5000 })

metrics.trackCache('status', memoryCache)

declare global {
  type Context = ServiceContext<Clients>
}

const clients: ClientsConfig<Clients> = {
  implementation: Clients,
  options: {
    default: {
      retries: 2,
      timeout: TIMEOUT_MS,
    },
    status: {
      memoryCache,
    },
  },
}

// Export a service that defines route handlers and client options.
export default new Service({
  clients,
  routes: {
    'buyer-org-supplier': method({
      POST: createBuyerOrg,
    }),
  },
})

```