[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 micro/packages/micro-react-intl/components/withIntlProvider.tsx from the micro VTEX app.

[Assistant]
Here's the implementation:

```tsx
import React from 'react'
import { IntlProvider } from 'react-intl'

export type Messages = Record<string, string>

export interface PageProps {
  data: any
  error: any
}

export const withIntlProvider = (
  Page: React.ElementType<PageProps>,
  messages: Messages,
  locale: string
): React.SFC<PageProps> => {
  return function MicroReactIntl ({ data, error }) {
    return (
      <IntlProvider messages={messages} locale={locale} key={locale}>
        <Page data={data} error={error} />
      </IntlProvider>
    )
  }
}

```


[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 micro/packages/micro-react-intl/components/index.ts from the micro VTEX app.

[Assistant]
Here's the implementation:

```typescript
export * from 'react-intl'
export * from './withIntlProvider'

```


[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 micro/packages/micro-react-intl/plugins/bundle/index.ts from the micro VTEX app.

[Assistant]
Here's the implementation:

```typescript
import {
  BundlePlugin,
  pagesFrameworkName,
  pagesRuntimeName
} from '@vtex/micro-core'
import { cacheGroup } from '@vtex/micro-react'
import { Block, Context, group, resolve } from 'webpack-blocks'

import { aliases } from '../aliases'

export default class Bundle extends BundlePlugin {
  public getConfig = async (config: Block<Context>): Promise<Block<Context>> => {
    return group([
      config,
      resolve({
        alias: aliases.reduce(
          (acc, packageName) => {
            acc[packageName] = require.resolve(packageName)
            return acc
          },
          {} as Record<string, string>
        )
      }),
      cacheGroup(pagesRuntimeName, /\/react-intl\//),
      cacheGroup(pagesFrameworkName, /\/micro-react-intl\//)
    ])
  }
}

```


[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 micro/packages/micro-react-intl/plugins/serve/index.ts from the micro VTEX app.

[Assistant]
Here's the implementation:

```typescript
import { ServePlugin } from '@vtex/micro-core'
import { createElement } from 'react'
import { IntlProvider } from 'react-intl'

export default class Serve extends ServePlugin<JSX.Element> {
  public render = (children: JSX.Element | null): JSX.Element => {
    const location = this.options.path
    // TODO: Fix this as any
    return createElement(IntlProvider as any, { location, children })
  }
}

```


[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 micro/packages/micro-css/plugins/bundle/index.ts from the micro VTEX app.

[Assistant]
Here's the implementation:

```typescript
import { BundlePlugin } from '@vtex/micro-core'
import { Block, Context, css, group, match } from 'webpack-blocks'

import { extractCss } from './modules/extractCSS'
import { purgeCSS } from './modules/purgeCSS'

export default class Bundle extends BundlePlugin {
  public getConfig = async (config: Block<Context>): Promise<Block<Context>> => {
    const block: Block<Context>[] = [
      purgeCSS({
        paths: await this.project.resolveFiles('pages', 'components')
      }),
      match('*.css', [
        extractCss({
          plugin: { filename: '[name].css' },
          loader: { esModule: true }
        }),
        css({ styleLoader: false } as any)
      ])
    ]

    return group([
      config,
      ...block
    ])
  }
}

```


[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 micro/packages/micro-css/plugins/bundle/modules/htmlTags.ts from the micro VTEX app.

[Assistant]
Here's the implementation:

```typescript
// TODO: Purgecss plugin does not work well
// with standard tags, so let's leave all of them
// there so we don't miss out any important one
export const htmlTags = [
  'a',
  'abbr',
  'address',
  'area',
  'article',
  'aside',
  'audio',
  'b',
  'base',
  'bdi',
  'bdo',
  'blockquote',
  'body',
  'br',
  'button',
  'canvas',
  'caption',
  'cite',
  'code',
  'col',
  'colgroup',
  'data',
  'datalist',
  'dd',
  'del',
  'details',
  'dfn',
  'dialog',
  'div',
  'dl',
  'dt',
  'em',
  'embed',
  'fieldset',
  'figcaption',
  'figure',
  'footer',
  'form',
  'h1',
  'h2',
  'h3',
  'h4',
  'h5',
  'h6',
  'head',
  'header',
  'hgroup',
  'hr',
  'html',
  'i',
  'iframe',
  'img',
  'input',
  'ins',
  'kbd',
  'label',
  'legend',
  'li',
  'link',
  'main',
  'map',
  'mark',
  'math',
  'menu',
  'menuitem',
  'meta',
  'meter',
  'nav',
  'noscript',
  'object',
  'ol',
  'optgroup',
  'option',
  'output',
  'p',
  'param',
  'picture',
  'pre',
  'progress',
  'q',
  'rb',
  'rp',
  'rt',
  'rtc',
  'ruby',
  's',
  'samp',
  'script',
  'section',
  'select',
  'slot',
  'small',
  'source',
  'span',
  'strong',
  'style',
  'sub',
  'summary',
  'sup',
  'svg',
  'table',
  'tbody',
  'td',
  'template',
  'textarea',
  'tfoot',
  'th',
  'thead',
  'time',
  'title',
  'tr',
  'track',
  'u',
  'ul',
  'var',
  'video',
  'wbr'
]

```


[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 micro/packages/micro-css/plugins/bundle/modules/extractCSS.ts from the micro VTEX app.

[Assistant]
Here's the implementation:

```typescript
// eslint-disable-next-line @typescript-eslint/no-unused-vars
import webpack from 'webpack'
import MiniCssExtractPlugin from 'mini-css-extract-plugin'
import { Context, Util } from 'webpack-blocks'

interface Options {
  loader?: {
    esModule: boolean
  },
  plugin?: MiniCssExtractPlugin.PluginOptions
}

export const extractCss = (options?: Options) => (context: Context, { merge }: Util) => merge({
  module: {
    rules: [
      {
        ...context.match,
        use: [
          {
            loader: MiniCssExtractPlugin.loader,
            options: options?.loader
          }
        ]
      }
    ]
  },
  plugins: [
    new MiniCssExtractPlugin(options?.plugin)
  ]
})

```


[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 micro/packages/micro-css/plugins/bundle/modules/purgeCSS.ts from the micro VTEX app.

[Assistant]
Here's the implementation:

```typescript
import PurgeCSSPlugin from 'purgecss-webpack-plugin'
import { Configuration } from 'webpack'
import { Context, Util } from 'webpack-blocks'

type FirstOf<T extends [any]> = T extends [infer P] ? P : never

type Options = FirstOf<ConstructorParameters<typeof PurgeCSSPlugin>>

interface EnhancedContext extends Context {
  purgeCSSOptions: Options
}

const post = (context: Context, { addPlugin }: Util) => {
  const ctx = context as EnhancedContext
  return addPlugin(new PurgeCSSPlugin(ctx.purgeCSSOptions))
}

export const purgeCSS = (options: Partial<Options>) => {
  return Object.assign(
    (context: Context) => {
      const ctx = context as EnhancedContext
      ctx.purgeCSSOptions = {
        ...ctx.purgeCSSOptions,
        ...options
      }
      return (config: Configuration) => config
    },
    { post }
  )
}

```


[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 micro/packages/micro-server/lib/prod.ts from the micro VTEX app.

[Assistant]
Here's the implementation:

```typescript
import {
  ServeCompiler,
  Plugins,
  Project,
  PublicPaths
} from '@vtex/micro-core'
import compress from 'compression'
import express from 'express'
import logger from 'morgan'
import { Stats } from 'webpack'

import { middleware as streamAssets } from './middlewares/assets'
import { middleware as respondData } from './middlewares/data'
import { middleware as headers } from './middlewares/headers'
import { middleware as router } from './middlewares/router'
import { middleware as ssr } from './middlewares/ssr'
import { Next, Req, Res } from './typings'

interface ProdServerOptions {
  statsJson: Stats.ToJsonOutput
  project: Project
  plugins: Plugins['serve'][]
  publicPaths: PublicPaths
  host: string
  port: number
}

const context = (
  project: Project,
  plugins: any,
  statsJson: Stats.ToJsonOutput,
  publicPaths: PublicPaths
) => (req: Req, res: Res, next: Next) => {
  const { locals: { route: { page, path } } } = res
  res.locals.compiler = new ServeCompiler({
    project,
    plugins,
    options: {
      stats: statsJson,
      mode: 'development',
      lifecycleTarget: 'bundle',
      publicPaths,
      page,
      path
    }
  })
  next()
}

export const startProdServer = async ({
  publicPaths,
  statsJson,
  project,
  plugins,
  host,
  port
}: ProdServerOptions) => {
  const routerMiddleware = await router(project, publicPaths)
  const contextMiddleware = context(project, plugins, statsJson, publicPaths)

  const app = express()

  app.use(logger('tiny'))
  app.use(compress())

  app.get('/favicon.ico', (req: Req, res: Res) => { res.status(404); res.send(null) })
  app.get(`${publicPaths.assets}*`, headers, streamAssets(project, publicPaths))
  app.get(`${publicPaths.data}*`, headers, routerMiddleware, contextMiddleware, respondData)
  app.get('/*', headers, routerMiddleware, contextMiddleware, ssr)

  app.listen(port, () => console.log(`🦄 ProdServer is UP on ${host}:${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 micro/packages/micro-server/lib/dev.ts from the micro VTEX app.

[Assistant]
Here's the implementation:

```typescript
import {
  ImportMap,
  ServeCompiler,
  Plugins,
  Project,
  PublicPaths
} from '@vtex/micro-core'
import compress from 'compression'
import express from 'express'
import logger from 'morgan'
import { Stats } from 'webpack'

import { middleware as streamAssets } from './middlewares/assets'
import { middleware as respondData } from './middlewares/data'
import { middleware as headers } from './middlewares/headers'
import { middleware as router } from './middlewares/router'
import { devSSR } from './middlewares/ssr'
import { Next, Req, Res } from './typings'

interface DevServerOptions {
  importMap: ImportMap
  statsJson: Stats.ToJsonOutput
  project: Project,
  plugins: Plugins['serve'][]
  publicPaths: PublicPaths
  host: string
  port: number
}

const context = (
  project: Project,
  plugins: any,
  statsJson: Stats.ToJsonOutput,
  publicPaths: PublicPaths
) => (req: Req, res: Res, next: Next) => {
  const { locals: { route: { page, path } } } = res
  res.locals.compiler = new ServeCompiler({
    project,
    plugins,
    options: {
      stats: statsJson,
      mode: 'development',
      lifecycleTarget: 'build',
      publicPaths,
      page,
      path
    }
  })
  next()
}

export const startDevServer = async ({
  publicPaths,
  importMap,
  statsJson,
  project,
  plugins,
  host,
  port
}: DevServerOptions) => {
  const routerMiddleware = await router(project, publicPaths)
  const contextMiddleware = context(project, plugins, statsJson, publicPaths)

  const app = express()

  app.use(logger('dev'))
  app.use(compress())

  app.get('/favicon.ico', (req: Req, res: Res) => { res.status(404); res.send(null) })
  app.get(`${publicPaths.assets}*`, headers, streamAssets(project, publicPaths))
  app.get(`${publicPaths.data}*`, headers, routerMiddleware, contextMiddleware, respondData)
  app.get('/*', headers, routerMiddleware, contextMiddleware, devSSR(importMap))

  app.listen(port, () => console.log(`🦄 DevServer is UP on ${host}:${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 micro/packages/micro-server/lib/features.ts from the micro VTEX app.

[Assistant]
Here's the implementation:

```typescript
import cookie from 'cookie'

import { Req } from './typings'

export interface Features {
  disableSSR: boolean
}

const DEFAULT_FEATURES: Features = {
  disableSSR: false
}

export const featuresFromReq = (req: Req) => {
  const cookies = req.headers.cookie
  const maybeFeaturesStr = cookies && cookie.parse(cookies)?.['micro-features']
  if (maybeFeaturesStr) {
    const maybeFeatures = JSON.parse(maybeFeaturesStr)
    return {
      ...DEFAULT_FEATURES,
      ...maybeFeatures
    }
  }
  return DEFAULT_FEATURES
}

```


[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 micro/packages/micro-server/lib/package.json from the micro VTEX app.

[Assistant]
Here's the implementation:

```json
{
  "main": "../dist/index.js",
  "types": "../dist/index.d.ts"
}

```


[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 micro/packages/micro-server/lib/typings.ts from the micro VTEX app.

[Assistant]
Here's the implementation:

```typescript
import { ServeCompiler, ResolvedPage } from '@vtex/micro-core'
import express, { NextFunction, Request, Response } from 'express'
import { Stats } from 'webpack'

interface Locals {
  compiler: ServeCompiler<unknown>,
  route: {
    page: ResolvedPage<any>
    path: string
  },
  webpackStats?: {
    stats: Stats[]
  }
}

export type Res = Omit<Response, 'locals'> & {
  locals: Locals
}

export type Req = Request

export type Next = NextFunction

export default express

```


[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 micro/packages/micro-server/lib/middlewares/data.ts from the micro VTEX app.

[Assistant]
Here's the implementation:

```typescript
import { Req, Res } from '../typings'

export const middleware = async (req: Req, res: Res) => {
  const {
    locals: {
      route: {
        page: { data, status }
      }
    }
  } = res

  res.type('json')
  res.status(status).send(data)
}

```


[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 micro/packages/micro-server/lib/middlewares/headers.ts from the micro VTEX app.

[Assistant]
Here's the implementation:

```typescript
import { Next, Req, Res } from '../typings'

export const middleware = (req: Req, res: Res, next: Next) => {
  try {
    res.set('cache-control', 'max-age=1200, public, immutable')
    next()
  } catch (err) {
    res.set('cache-control', 'max-age=10, public')
    throw err
  }
}

```


[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 micro/packages/micro-server/lib/middlewares/router.ts from the micro VTEX app.

[Assistant]
Here's the implementation:

```typescript
import {
  isResolvedPage,
  isResolvedRedirect,
  Project,
  PublicPaths
} from '@vtex/micro-core'
import assert from 'assert'

import { Next, Req, Res } from '../typings'

export const middleware = async (project: Project, publicPaths: PublicPaths) => {
  const router = await project.getRouter()

  assert(typeof router === 'function', '💣 No router found for package')
  console.log('🐙 [router]: Found router config')

  return async (req: Req, res: Res, next: Next) => {
    const rootPath = req.path.startsWith(publicPaths!.data)
      ? publicPaths!.data
      : '/'
    const path = req.path.replace(rootPath, '/')

    const page = await router({ path, query: req.query as Record<string, string> }, {})

    if (isResolvedRedirect(page)) {
      res.redirect(page.status, page.location)
      return
    }

    if (isResolvedPage(page)) {
      res.locals.route = { page, path }
      return next()
    }

    throw new Error(`💣 Entry not resolved for path ${path}`)
  }
}

```


[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 micro/packages/micro-server/lib/middlewares/assets.ts from the micro VTEX app.

[Assistant]
Here's the implementation:

```typescript
import { Project, PublicPaths } from '@vtex/micro-core'
import { PosixFS, ZipOpenFS } from '@yarnpkg/fslib'
import { getLibzipSync } from '@yarnpkg/libzip'
import assert from 'assert'
import { createReadStream, pathExists } from 'fs-extra'
import mime from 'mime-types'
import { basename, extname, join } from 'path'
import pnp from 'pnpapi'

import { Req, Res } from '../typings'

const libzip = getLibzipSync()

// This will transparently open zip archives
const zipOpenFs = new ZipOpenFS({ libzip })

// This will convert all paths into a Posix variant, required for cross-platform compatibility
const crossFs = new PosixFS(zipOpenFs)

const resolveBundleAssets = (assetsRootPath: string, path: string) => {
  const asset = join(assetsRootPath, path)
  return createReadStream(asset, { encoding: 'utf-8' })
}

const resolveES6Assets = async (assetsRootPath: string, path: string) => {
  const relativeImport = join(assetsRootPath, path)
  if (await pathExists(relativeImport)) {
    return createReadStream(relativeImport, { encoding: 'utf-8' })
  }

  // Maybe this was a default import ?
  const relativeDefaultImport = join(relativeImport.replace('.js', ''), 'index.js')
  if (await pathExists(relativeDefaultImport)) {
    return createReadStream(relativeDefaultImport, { encoding: 'utf-8' })
  }

  // It's a module. Let's resolve it using PnP API
  const [issuer, rest] = path.split('__imports__')
  const splitted = rest.slice(1).split('/')
  const module = splitted[0].startsWith('@') ? splitted.slice(0, 2).join('/') : splitted[0]
  const filepath = rest.replace(module, '')

  // Let's first read the package json so we read the module property
  const unqualified = pnp.resolveToUnqualified(module, issuer) || ''
  const packageJSONPath = join(unqualified, 'package.json')
  const packageJSON = await crossFs.readJsonPromise(packageJSONPath)

  // Let's just try a module relative import at first
  const moduleRelativeImport = join(unqualified, filepath)
  if (await pathExists(moduleRelativeImport)) {
    return createReadStream(moduleRelativeImport, { encoding: 'utf-8' })
  }

  assert(packageJSON.module, `💣 The package should contain a module locator for es6 packages. Maybe package ${module} is not compatbile with Micro 😞`)

  // Now let's try to resolve the path
  const moduleSplitted = packageJSON.module.split('/')
  const dist = moduleSplitted.slice(0, moduleSplitted.length - 1).join('/')
  const moduleImport = join(unqualified, dist, filepath)
  if (await crossFs.existsPromise(moduleImport)) {
    return crossFs.createReadStream(moduleImport, { encoding: 'utf-8' })
  }

  // Maybe this was a default import ?
  const moduleDefaultImport = join(moduleImport.replace('.js', ''), 'index.js')
  if (await pathExists(moduleDefaultImport)) {
    return createReadStream(moduleDefaultImport, { encoding: 'utf-8' })
  }

  throw new Error(`💣 Asset Not Found: ${path}`)
}

export const middleware = (project: Project, publicPaths: PublicPaths) => {
  const assetsRootPath = process.env.NODE_ENV === 'production'
    ? join(project.dist, 'bundle/webnew')
    : join(project.dist, 'build/es6')

  return async (req: Req, res: Res) => {
    try {
      const rootPath = req.path.startsWith(publicPaths.assets)
        ? publicPaths.assets
        : '/'
      const rawPath = req.path.replace(rootPath, '')
      const extension = extname(rawPath) ? '' : '.js'
      const path = rawPath + extension

      // Set correctly the MIME type of the object
      const contentType = mime.contentType(basename(path))
      if (contentType) {
        res.set('content-type', contentType)
      }

      const stream = process.env.NODE_ENV === 'production'
        ? resolveBundleAssets(assetsRootPath, path)
        : await resolveES6Assets(assetsRootPath, path)

      res.statusCode = 200
      stream.pipe(res)
    } catch (err) {
      res.status(404).send(null)
      console.error(err)
    }
  }
}

```


[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 micro/packages/micro-server/lib/middlewares/ssr.ts from the micro VTEX app.

[Assistant]
Here's the implementation:

```typescript
import { ImportMap, ServeCompiler } from '@vtex/micro-core'
import pretty from 'pretty'

import { featuresFromReq } from '../features'
import { Req, Res } from '../typings'

const ok = (
  compiler: ServeCompiler<unknown>,
  body: string
) => `<!DOCTYPE html>
<html>
<head>
${compiler.getMetaTags()}
${compiler.getLinkTags()}
${compiler.getStyleTags()}
</head>
<body>
${body}
${compiler.getScriptTags()}
</body>
</html>
`

export const middleware = (req: Req, res: Res) => {
  const { locals: { compiler, route: { page: { status } } } } = res
  const { disableSSR } = featuresFromReq(req)

  const body = compiler.renderToString(disableSSR)
  const html = ok(compiler, body)

  res.status(status).send(html)
}

const okSSR = (
  compiler: ServeCompiler<unknown>,
  body: string,
  importMap: ImportMap
) => `<!DOCTYPE html>
<html>
<head>
${compiler.getMetaTags()}
${compiler.getLinkTags()}
${compiler.getStyleTags()}
</head>
<body>
<script type="importmap-shim">${JSON.stringify(importMap)}</script>
${compiler.getScriptTags()}
${body}
</body>
</html>
`

export const devSSR = (importMap: ImportMap) => {
  return (req: Req, res: Res) => {
    const { locals: { route: { page: { status } } } } = res
    const { disableSSR } = featuresFromReq(req)
    const compiler = res.locals.compiler

    const body = compiler.renderToString(disableSSR)
    const html = pretty(okSSR(compiler, body, importMap))

    res.type('html')
    res.status(status).send(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 micro/packages/micro-cli/lib/constants.ts from the micro VTEX app.

[Assistant]
Here's the implementation:

```typescript
export const SERVER_PORT = Number.parseInt(process.env.PORT || '3000')

export const HOST = 'http://localhost'

export const BUILD = 'webpack.stats.json'

export const PUBLIC_PATHS = {
  assets: '/assets/',
  data: '/api/'
}

```


[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 micro/packages/micro-cli/lib/index.ts from the micro VTEX app.

[Assistant]
Here's the implementation:

```typescript
#!/usr/bin/env node
import chalk from 'chalk'
import {
  CommandNotFoundError,
  find,
  MissingRequiredArgsError,
  run as unboundRun
} from 'findhelp'
import { join } from 'path'

import { tree } from './modules/tree'

const run = (command: any) => unboundRun.call(tree, command, join(__dirname, 'modules'))

const main = async () => {
  try {
    console.log('🦄 Welcome to Micro')
    const args = process.argv.slice(2)
    await run(find(tree, args))
  } catch (e) {
    switch (e.name) {
      case MissingRequiredArgsError.name:
        console.error('Missing required arguments:', chalk.blue(e.message))
        break
      case CommandNotFoundError.name:
        console.error('Command not found:', chalk.blue(...process.argv.slice(2)))
        break
      default:
        console.error(chalk.red('💣 Something exploded:\n'), e)
    }
  }
}

main()

```


[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 micro/packages/micro-cli/lib/common/project.ts from the micro VTEX app.

[Assistant]
Here's the implementation:

```typescript
import {
  LifeCycle,
  MICRO_BUILD_DIR,
  Plugins,
  Project,
  walk
} from '@vtex/micro-core'
import chalk from 'chalk'
import { ensureDir } from 'fs-extra'
import { join } from 'path'

export const newProject = async () => {
  const projectPath = process.cwd()

  const project = new Project({ rootPath: projectPath })

  console.log('🦄 Resolving dependencies')
  await project.resolvePackages()
  walk(project.root, curr => {
    console.info(`📦 Micro package found: ${curr.toString()}`)
  })

  return project
}

export const ensureDist = async (target: string, path: string) => {
  console.log(`🎯 [${target}]: Ensuring dist folder in ${chalk.cyanBright(join(MICRO_BUILD_DIR, path.split(MICRO_BUILD_DIR)[1]))}`)
  await ensureDir(path)
}

export const resolvePlugins = async <T extends LifeCycle>(project: Project, lifecycle: T): Promise<NonNullable<Plugins[T]>[]> => {
  console.log(`🦄 [${lifecycle}]: Resolving plugins`)
  const plugins = await project.resolvePlugins(lifecycle)

  for (const pkg of Object.keys(plugins)) {
    console.log(`🔌 [${lifecycle}]: Plugin found ${pkg}`)
  }

  return Object.values(plugins)
}

export const loadProject = () => {

}

```


[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 micro/packages/micro-cli/lib/common/print.ts from the micro VTEX app.

[Assistant]
Here's the implementation:

```typescript
import { inspect } from 'util'

export const prettyPrint = (obj: any) => {
  console.log(inspect(obj, false, 100, 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 micro/packages/micro-cli/lib/modules/index.ts from the micro VTEX app.

[Assistant]
Here's the implementation:

```typescript
import { help } from 'findhelp'

import { tree } from './tree'

export default async () => {
  console.log(help(tree, { name: 'micro' }))
}

```


[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 micro/packages/micro-cli/lib/modules/tree.ts from the micro VTEX app.

[Assistant]
Here's the implementation:

```typescript
export const tree = {
  build: {
    description: 'Access for Build Micro lifecycle',
    options: [
      {
        description: 'Build with dev environment',
        long: 'dev',
        type: 'boolean'
      }
    ]
  },
  bundle: {
    description: 'Access for Bundle Micro lifecycle',
    options: [
      {
        description: 'Build with dev environment',
        long: 'dev',
        type: 'boolean'
      }
    ],
    report: {
      description: 'Generate a report using a bundled build'
    },
    config: {
      description: 'Print webpack config that would be generated in a normal bundle assembly'
    }
  },
  link: {
    description: 'Develop a Micro project'
  },
  serve: {
    description: 'Serve a bundled Micro project',
    options: [
      {
        description: 'Build with dev environment',
        long: 'dev',
        type: 'boolean'
      },
      {
        description: 'Port to Serve the micro Project',
        short: 'p',
        type: 'number'
      }
    ]
  },
  setup: {
    description: 'Setup the current package.json as a Micro project',
    options: [
      {
        description: 'Do not change files, just show what would be output by this command',
        long: 'dry',
        short: 'd',
        type: 'boolean'
      }
    ]
  },
  options: [
    {
      description: 'Show help information',
      long: 'help',
      short: 'h',
      type: '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 micro/packages/micro-cli/lib/typings/findhelp/index.d.ts from the micro VTEX app.

[Assistant]
Here's the implementation:

```typescript
declare module 'findhelp' {
  function find (tree: any, args: any): any
  function run (...args: any[]): Promise<any>
  function help (...args: any[]): any

  export class CommandNotFoundError extends Error {}
  export class MissingRequiredArgsError extends Error {}
}

```


[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 micro/packages/micro-cli/lib/modules/setup/index.ts from the micro VTEX app.

[Assistant]
Here's the implementation:

```typescript
import { genManifest, genTSConfig, PackageStructure } from '@vtex/micro-core'
import { outputFile, readJSON } from 'fs-extra'
import { join } from 'path'

import { prettyPrint } from './../../common/print'

interface Options {
  dry?: boolean
  d?: boolean
}

// TODO: we should also:
//  - yarn add typescript --dev
//  - yarn add eslint --dev
//  - yarn dlx @yarnpkg/pnpify --sdk # to setup vscode
const main = async ({ dry, d }: Options) => {
  const dryRun = dry || d

  const projectPath = process.cwd()

  const manifestPath = join(projectPath, PackageStructure.manifest)
  const tsconfigPath = join(projectPath, PackageStructure.tsconfig)

  const originalManifest = await readJSON(manifestPath).catch(() => {})
  const originalTSConfig = await readJSON(tsconfigPath).catch(() => {})

  const manifest = genManifest(originalManifest)
  const tsconfig = genTSConfig(originalTSConfig)

  if (dryRun) {
    console.log(PackageStructure.manifest)
    prettyPrint(manifest)
    console.log('')
    console.log(PackageStructure.tsconfig)
    prettyPrint(tsconfig)
    return
  }

  console.log('📓 Writting new manifest file for your project')
  await outputFile(manifestPath, JSON.stringify(manifest, null, 2))

  console.log('📓 Writting new tsconfig file for your project')
  await outputFile(tsconfigPath, JSON.stringify(tsconfig, null, 2))
}

export default main

```


[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 micro/packages/micro-cli/lib/modules/bundle/index.ts from the micro VTEX app.

[Assistant]
Here's the implementation:

```typescript
import { Mode, BundleCompiler } from '@vtex/micro-core'
import chalk from 'chalk'
import { outputJSON } from 'fs-extra'
import { join } from 'path'
import webpack, { Compiler, Stats } from 'webpack'

import { ensureDist, newProject, resolvePlugins } from '../../common/project'
import { BUILD } from '../../constants'

const lifecycle = 'bundle'

const runWebpack = (compiler: Compiler) => new Promise<Stats>((resolve, reject) => {
  compiler.run((err, stats) => {
    if (err) {
      reject(err)
    }
    return resolve(stats)
  })
})

interface Options {
  dev?: boolean
}

const main = async (options: Options) => {
  const dev = !!options.dev
  const mode: Mode = dev ? 'development' : 'production'
  process.env.NODE_ENV = mode

  const project = await newProject()

  console.log(`🦄 Starting Micro for ${chalk.magenta(project)} at ${chalk.blue(lifecycle)}:${chalk.blue(mode)}`)

  const partial = await resolvePlugins(project, lifecycle)
  const self = await project.getSelfPlugin(lifecycle)
  const plugins = self ? [self, ...partial] : partial

  console.log(`🦄 [${lifecycle}]: Creating Compiler`)
  const compiler = new BundleCompiler({ project, plugins, mode })
  const configs = await compiler.getConfig('webnew')

  await ensureDist(lifecycle, compiler.dist)

  for (const page of Object.keys(configs.entry || {})) {
    console.log(`📄 [${lifecycle}]: Page found: ${page}`)
  }

  console.log(`🦄 [${lifecycle}]: Running Build`)
  console.time(`🦄 [${lifecycle}]: Build took`)
  const stats = await runWebpack(webpack(configs))
  console.timeEnd(`🦄 [${lifecycle}]: Build took`)

  console.time(`🦄 [${lifecycle}]: Webpack Stats file generation took`)
  const statsJSON = stats.toJson({ all: true })
  console.timeEnd(`🦄 [${lifecycle}]: Webpack Stats file generation took`)

  if (stats.hasErrors()) {
    console.error('⛔⛔ Webpack build finshed with the following errors\n')
    for (const err of statsJSON.errors) {
      console.log(err)
    }
  }

  if (stats.hasWarnings()) {
    console.warn('⛔ Webpack build finshed with the following warnings\n')
    for (const warning of statsJSON.warnings) {
      console.log(warning)
    }
    console.warn(`❗ Please run ${chalk.blue('micro bundle report')} for a better view of what is going on with your bundle`)
  }

  const dist = join(compiler.dist, BUILD)
  console.log(`🦄 [${lifecycle}]: Persisting Build on ${dist.replace(project.rootPath, '')}`)
  await outputJSON(dist, statsJSON, { spaces: 2 })
}

export default main

```


[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 micro/packages/micro-cli/lib/modules/link/index.ts from the micro VTEX app.

[Assistant]
Here's the implementation:

```typescript
import { importMapFromAliases, Mode } from '@vtex/micro-core'
import { startDevServer } from '@vtex/micro-server'
import chalk from 'chalk'
import chokidar from 'chokidar'

import { newProject, resolvePlugins } from '../../common/project'
import { HOST, PUBLIC_PATHS, SERVER_PORT } from '../../constants'
import {
  clean,
  createGetFolderFromFile,
  getBuilders,
  lifecycle,
  rejectDeclarationFiles
} from '../build/builder'

const waitForReady = (watcher: chokidar.FSWatcher) => new Promise(resolve => watcher.on('ready', resolve))

const main = async () => {
  const mode: Mode = 'development'
  process.env.NODE_ENV = mode

  const project = await newProject()

  console.log(`🦄 Starting Micro for ${chalk.magenta(project)} at ${chalk.blue(lifecycle)}:${chalk.blue(mode)}`)

  const { createBuild, createPreBuild } = await getBuilders(project, mode)

  await clean(project, 'build')

  console.log(`🦄 [${lifecycle}]: Starting the build`)

  const [framework, userland] = await Promise.all([
    project.root.getFiles('lib', 'plugins', 'index').then(rejectDeclarationFiles),
    project.root.getFiles('components', 'pages', 'router').then(rejectDeclarationFiles)
  ])

  const msg = `🦄 [${lifecycle}]: The build of ${framework.length + userland.length} files finished in`
  console.time(msg)
  const { prebuild } = await createPreBuild()
  await Promise.all(framework.map(f => prebuild(f, false)))

  const { build, compiler: buildCompiler } = await createBuild()
  await Promise.all(userland.map(f => build(f, false)))
  console.timeEnd(msg)

  // This function will select if we should apply Build or Prebuild
  // once a watched file changes
  const entryFromFile = createGetFolderFromFile(project)
  const compile = (f: string) => {
    const entry = entryFromFile(f)
    if (['lib', 'plugins', 'index.ts'].includes(entry)) {
      return prebuild(f)
    }
    return build(f)
  }

  const watcher = chokidar.watch(
    project.root.getGlobby('lib', 'plugins', 'components', 'pages', 'router', 'index'),
    { cwd: project.rootPath, ignoreInitial: true }
  )

  // TODO: I think we can safetely implement these
  watcher.on('addDir', () => { console.error('💣 not implemented: addDir') })
  watcher.on('unlink', () => { console.error('💣 not implemented: unlink') })
  watcher.on('unlinkDir', () => { console.error('💣 not implemented: unlinkDir') })
  watcher.on('error', console.error)
  watcher.on('change', compile)
  watcher.on('add', compile)

  await waitForReady(watcher)

  const hasPages = (await project.root.getFiles('pages')).length > 0
  const hasRouter = (await project.root.getFiles('router')).length > 0
  if (hasRouter && hasPages) {
    console.log('🦄 Resolving aliases')
    const [pluginAliases, projectAliases] = await Promise.all([
      buildCompiler.getAliases('warn'),
      project.resolveAliases()
    ])

    console.log('🦄 Building import map')
    const importMap = importMapFromAliases(projectAliases, pluginAliases, PUBLIC_PATHS)

    console.log(`🦄 [${lifecycle}]: Starting DevServer`)

    await startDevServer({
      publicPaths: PUBLIC_PATHS,
      importMap,
      project,
      plugins: await resolvePlugins(project, 'serve'),
      host: HOST,
      port: SERVER_PORT
    } as any)
  }
}

export default main

```


[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 micro/packages/micro-cli/lib/modules/serve/index.ts from the micro VTEX app.

[Assistant]
Here's the implementation:

```typescript
import { Mode } from '@vtex/micro-core'
import { startDevServer, startProdServer } from '@vtex/micro-server'
import chalk from 'chalk'
import { readJSON } from 'fs-extra'
import { join } from 'path'

import { newProject, resolvePlugins } from '../../common/project'
import { BUILD, HOST, PUBLIC_PATHS, SERVER_PORT } from '../../constants'

const lifecycle = 'serve'

interface Options {
  dev: boolean
  p?: number
}

const main = async (options: Options) => {
  const port = options.p || SERVER_PORT
  const mode: Mode = options.dev ? 'development' : 'production'
  process.env.NODE_ENV = mode

  const project = await newProject()

  console.log(`🦄 Starting Micro for ${chalk.magenta(project)} at ${chalk.blue(lifecycle)}:${chalk.blue(mode)}`)

  const partial = await resolvePlugins(project, lifecycle)
  const self = await project.getSelfPlugin(lifecycle)
  const plugins = self ? [...partial, self] : partial

  console.log(`🦄 Serving ${project.root.toString()}`)

  if (mode === 'production') {
    console.log(`🦄 Reading build state on ${project.dist.replace(project.rootPath, '.')}`)
    const statsJson = await readJSON(join(project.dist, 'bundle', BUILD))

    console.log(`🦄 [${lifecycle}]: Starting ProdServer`)
    await startProdServer({
      publicPaths: PUBLIC_PATHS,
      statsJson,
      project,
      plugins,
      host: HOST,
      port
    })
  } else if (mode === 'development') {
    console.log(`🦄 [${lifecycle}]: Starting DevServer`)

    await startDevServer({
      publicPaths: PUBLIC_PATHS,
      project,
      plugins,
      port,
      host: HOST
    } as any)
  }
}

export default main

```


[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 micro/packages/micro-cli/lib/modules/bundle/config/index.ts from the micro VTEX app.

[Assistant]
Here's the implementation:

```typescript
import { Mode, BundleCompiler } from '@vtex/micro-core'
import chalk from 'chalk'

import { newProject, resolvePlugins } from '../../../common/project'
import { prettyPrint } from '../../../common/print'

const lifecycle = 'bundle'

interface Options {
  dev?: boolean
}

const main = async (options: Options) => {
  const dev = !!options.dev
  const mode: Mode = dev ? 'development' : 'production'
  process.env.NODE_ENV = mode

  const project = await newProject()

  console.log(`🦄 Starting Micro for ${chalk.magenta(project)} at ${chalk.blue(lifecycle)}:${chalk.blue(mode)}`)

  const partial = await resolvePlugins(project, lifecycle)
  const self = await project.getSelfPlugin(lifecycle)
  const plugins = self ? [self, ...partial] : partial

  console.log(`🦄 [${lifecycle}]: Creating Compiler`)
  const compiler = new BundleCompiler({ project, plugins, mode })
  const configs = await compiler.getConfig('webnew')

  prettyPrint(configs)
}

export default main

```


[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 micro/packages/micro-cli/lib/modules/bundle/report/index.ts from the micro VTEX app.

[Assistant]
Here's the implementation:

```typescript
import open from 'open'

const target = 'bundle'

const main = async () => {
  console.log(`🦄 Starting ${target} report`)

  open('http://webpack.github.io/analyse/')
}

export default main

```


[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 micro/packages/micro-react/plugins/aliases.ts from the micro VTEX app.

[Assistant]
Here's the implementation:

```typescript
// This plugin will enforce the following modules. This means
// projects using this package as a plugin will use this package's
// versions of the following packages
export const aliases = [
  'exenv',
  'react',
  'react-dom',
  '@loadable/component'
]

```


[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 micro/packages/micro-react/components/data.ts from the micro VTEX app.

[Assistant]
Here's the implementation:

```typescript
import { canUseDOM } from 'exenv'

import { join } from './path'

const id = '__MICRO_PAGE_DATA__'

export const getPageData = async () => {
  if (!canUseDOM) {
    throw new Error('💣 PageData fetch can only be run on the browser')
  }

  const dataElement = document.getElementById(id)
  if (typeof (dataElement as any)?.href === 'string') {
    const maybeDataPath = (dataElement as any)?.href
    const response = await fetch(maybeDataPath)
    return response.json()
  }

  return null
}

export const withPageDataTags = (pageName: string, pageData: any, dataRootPath: string, path: string) => pageData !== undefined
  ? `<link id="${id}" data-chunk="${pageName}" rel="preload" as="fetch" href="${join(dataRootPath, path)}" crossorigin="anonymous">`
  : ''

```


[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 micro/packages/micro-react/components/path.ts from the micro VTEX app.

[Assistant]
Here's the implementation:

```typescript
const removeEndingSlash = (x: string) => x.endsWith('/') ? x.slice(0, x.length - 1) : x

const ensureStartingSlash = (x: string) => x.startsWith('/') || x === '' ? x : `/${x}`

export const join = (...args: string[]) => args.reduce(
  (acc, cur) => `${removeEndingSlash(acc)}${ensureStartingSlash(cur)}`,
  ''
)

```


[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 micro/packages/micro-react/components/loader.tsx from the micro VTEX app.

[Assistant]
Here's the implementation:

```tsx
import { loadableReady } from '@loadable/component'
import { canUseDOM } from 'exenv'
import React, { StrictMode } from 'react'
import { hydrate, render } from 'react-dom'

import { getAppContainer } from './container'
import { Runtime } from './context/Runtime'
import { getPageData } from './data'
import { once } from './once'
import { getRuntimeData } from './runtime'

const printPerformance = () => {
  const timing = window.performance?.timing
  if (!timing) {
    return
  }
  const domContentLoaded = timing.domContentLoadedEventEnd - timing.navigationStart
  const loaded = timing.loadEventEnd - timing.navigationStart
  console.log(`[micro-react]: ⚡⚡ DomContentLoaded ${domContentLoaded / 1e3}ms`)
  console.log(`[micro-react]: ⚡⚡ Load ${loaded / 1e3}ms`)
}

const renderOrHydrate = (App: React.ReactType) => async () => {
  const container = getAppContainer()
  const runtimeData = getRuntimeData()

  // This should be preloaded by now
  let error = null
  const data = await getPageData().catch(err => { error = err })

  const AppWithContext = (
    <StrictMode>
      <Runtime.Provider value={runtimeData}>
        <App data={data} error={error} />
      </Runtime.Provider>
    </StrictMode>
  )

  if (container.children.length > 0) {
    const msg = '[micro-react]: ⚡⚡ Hydration took'
    console.time(msg)
    console.log('hydrationStart', (Date.now() - window.performance.timing.navigationStart) / 1e3)
    hydrate(AppWithContext, container)
    console.timeEnd(msg)
  } else {
    const msg = '[micro-react]: ⚡ Rendering took'
    console.time(msg)
    console.log('renderStart', (Date.now() - window.performance.timing.navigationStart) / 1e3)
    render(AppWithContext, container)
    console.timeEnd(msg)
  }

  printPerformance()
}

export const LoadMicroComponent = (App: React.ReactType) => {
  if (canUseDOM) {
    const renderOnce = once(renderOrHydrate(App))
    setTimeout(renderOnce, 6e3)

    if (document.readyState !== 'complete') {
      window.onload = () => loadableReady(renderOnce)
    } else {
      loadableReady(renderOnce)
    }
  }
  return App
}

```


[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 micro/packages/micro-react/components/once.ts from the micro VTEX app.

[Assistant]
Here's the implementation:

```typescript
export const once = <T extends (...args: any) => any>(fn: T) => {
  let called = false
  let ret: ReturnType<T> | null = null

  return (...args: Parameters<T>): ReturnType<T> => {
    if (called) {
      return ret as ReturnType<T>
    }
    called = true
    ret = fn(...args as any)
    return ret as ReturnType<T>
  }
}

```


[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 micro/packages/micro-react/components/container.ts from the micro VTEX app.

[Assistant]
Here's the implementation:

```typescript
export const appContainerId = 'root'

export const getAppContainer = () => {
  const container = document.getElementById(appContainerId)
  if (!container) {
    throw new Error('💣 This is embarrassing, the App couldnt find a container to fit it')
  }
  return container
}

export const withAppContainerTags = (ssr: string) => `<div id="${appContainerId}">${ssr}</div>`

```


[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 micro/packages/micro-react/components/runtime.ts from the micro VTEX app.

[Assistant]
Here's the implementation:

```typescript
import { PublicPaths } from '@vtex/micro-core'
import { canUseDOM } from 'exenv'

export interface RuntimeData {
  publicPaths: PublicPaths
}

const runtimeContainerId = '__MICRO_REACT_RUNTIME__'

export const getRuntimeData = () => {
  console.assert(canUseDOM, '💣 Runtime hydration can only be run on the browser')
  const dataElement = document.getElementById(runtimeContainerId)
  const maybeRuntime = JSON.parse(dataElement?.textContent || '{}')
  return ensureRuntime({ publicPaths: maybeRuntime })
}

export const withRuntimeTags = (runtime: RuntimeData) =>
  `<script id="${runtimeContainerId}" type="application/json">${JSON.stringify(runtime.publicPaths)}</script>`

const isRuntimeData = (obj: any): obj is RuntimeData => {
  const paths = obj?.publicPaths
  return typeof paths?.assets === 'string' && typeof paths?.data === 'string'
}

const ensureRuntime = (obj: any): RuntimeData => {
  if (!isRuntimeData(obj)) {
    throw new Error(`💣 Error while validating runtime data ${JSON.stringify(obj)}`)
  }
  return obj
}

```


[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 micro/packages/micro-react/components/index.ts from the micro VTEX app.

[Assistant]
Here's the implementation:

```typescript
export * from './loader'
export * from './context/Runtime'
export * from './runtime'
export * from './container'
export * from './inflight'
export * from './path'
export * from 'exenv'

```


[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 micro/packages/micro-react/components/publicPaths.ts from the micro VTEX app.

[Assistant]
Here's the implementation:

```typescript
export const externalPublicPathVariable = 'window.__MICRO_PUBLIC_PATH__'

```


[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 micro/packages/micro-react/components/inflight.ts from the micro VTEX app.

[Assistant]
Here's the implementation:

```typescript
const active: Record<string, Promise<any>> = {}

const cleanUp = (key: string) => <T>(result: T) => {
  delete active[key]
  return result
}

export const inflight = <T>(key: string, doFly: () => Promise<T>): Promise<T> => {
  if (!active[key]) {
    const clean = cleanUp(key)
    active[key] = doFly()
      .then(clean)
      .catch(e => {
        clean(e)
        throw e
      })
  }
  return active[key]
}

```


[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 micro/packages/micro-react/plugins/bundle/webold.ts from the micro VTEX app.

[Assistant]
Here's the implementation:

```typescript
import { Block, Context } from 'webpack-blocks'

import { babel } from './modules/babel'

export const weboldBabel: Block<Context> = babel({
  caller: { target: 'webold' },
  presets: [
    ['@babel/preset-env', {
      targets: {
        browsers: 'cover 99.5%'
      }
    }],
    '@babel/preset-react',
    [
      '@babel/preset-typescript', {
        isTSX: true,
        allExtensions: true
      }
    ]
  ],
  plugins: [
    '@babel/plugin-proposal-class-properties',
    '@babel/plugin-syntax-dynamic-import',
    '@loadable/babel-plugin'
  ]
} as 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 micro/packages/micro-react/plugins/bundle/webnew.ts from the micro VTEX app.

[Assistant]
Here's the implementation:

```typescript
import { Block, Context } from 'webpack-blocks'

import { babel } from './modules/babel'

export const webnewBabel: Block<Context> = babel({
  comments: true,
  minified: false,
  retainLines: true,
  shouldPrintComment: () => true,
  caller: { target: 'webnew' },
  presets: [
    [
      require.resolve('@babel/preset-env'), {
        targets: {
          esmodules: true
        },
        modules: false,
        bugfixes: true,
        exclude: [
          '@babel/plugin-proposal-object-rest-spread',
          '@babel/plugin-proposal-async-generator-functions',
          '@babel/plugin-transform-async-to-generator',
          '@babel/plugin-transform-regenerator',
          '@babel/plugin-transform-arrow-functions',
          '@babel/plugin-transform-destructuring',
          '@babel/plugin-transform-for-of',
          '@babel/plugin-transform-spread',
          '@babel/plugin-transform-typeof-symbol'
        ]
      }
    ],
    [
      require.resolve('@babel/preset-react'), {
        useBuiltIns: true
      }
    ],
    [
      require.resolve('@babel/preset-typescript'), {
        isTSX: true,
        allExtensions: true
      }
    ]
  ],
  plugins: [
    '@babel/plugin-proposal-class-properties',
    '@babel/plugin-syntax-dynamic-import',
    '@loadable/babel-plugin'
  ].map(require.resolve as any)
} as 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 micro/packages/micro-react/plugins/bundle/index.ts from the micro VTEX app.

[Assistant]
Here's the implementation:

```typescript
import LoadablePlugin from '@loadable/webpack-plugin'
import {
  BundlePlugin,
  BundleTarget,
  pagesFrameworkName,
  pagesRuntimeName,
  Project
} from '@vtex/micro-core'
import OptimizeCSSAssetsPlugin from 'optimize-css-assets-webpack-plugin'
import { basename } from 'path'
import PnpPlugin from 'pnp-webpack-plugin'
import TerserJSPlugin from 'terser-webpack-plugin'
import TimeFixPlugin from 'time-fix-plugin'
import {
  addPlugins,
  Block,
  Context,
  customConfig,
  defineConstants,
  entryPoint,
  env,
  group,
  match,
  optimization,
  performance,
  resolve,
  setContext,
  setMode,
  sourceMaps
} from 'webpack-blocks'
import DynamicPublicPathPlugin from 'webpack-dynamic-public-path'

import { externalPublicPathVariable } from '../../components/publicPaths'
import { aliases } from '../aliases'
import { cacheGroup } from './modules/cacheGroups'
import { webnewBabel } from './webnew'
import { weboldBabel } from './webold'

const entriesFromPages = async (project: Project) => {
  const files = await project.root.getFiles('pages')
  return files.reduce(
    (acc, path) => {
      if (path.endsWith('.tsx')) {
        const name = basename(path, '.tsx')
        acc[name] = path.replace(project.rootPath, '.')
      }
      return acc
    },
  {} as Record<string, string>
  )
}

export default class Bundle extends BundlePlugin {
  public getConfig = async (config: Block<Context>, target: BundleTarget): Promise<Block<Context>> => {
    const entrypoints = await entriesFromPages(this.project)
    const block: Block<Context>[] = [
      setMode(this.mode),
      setContext(this.project.rootPath),
      entryPoint(entrypoints),
      defineConstants({
        'process.env.NODE_ENV': this.mode
      }),
      addPlugins([
        new LoadablePlugin({
          outputAsset: false,
          writeToDisk: false
        }),
        new DynamicPublicPathPlugin({
          externalPublicPath: externalPublicPathVariable
        })
      ]),
      resolve({
        alias: aliases.reduce(
          (acc, packageName) => {
            acc[packageName] = require.resolve(packageName)
            return acc
          },
          {} as Record<string, string>
        ),
        extensions: ['.tsx', '.ts', '.js', '.jsx', '.json'],
        plugins: [
          PnpPlugin
        ]
      }),
      cacheGroup(pagesRuntimeName, /\/react\/|\/react-dom\/|\/@loadable\//),
      cacheGroup(pagesFrameworkName, /\/micro-react\/components\//),
      optimization({
        runtimeChunk: {
          name: 'webpack-runtime'
        },
        splitChunks: {
          maxInitialRequests: 30,
          maxAsyncRequests: 10
        }
      } as any),
      customConfig({
        name: target,
        target: 'web',
        bail: true,
        node: false,
        profile: true,
        resolveLoader: {
          plugins: [
            PnpPlugin.moduleLoader(module)
          ]
        }
      }) as Block<Context>,
      env('production', [
        optimization({
          noEmitOnErrors: true,
          namedModules: false,
          namedChunks: false,
          moduleIds: 'size',
          chunkIds: 'total-size',
          nodeEnv: 'production',
          removeAvailableModules: true,
          removeEmptyChunks: true,
          mergeDuplicateChunks: true,
          flagIncludedChunks: true,
          occurrenceOrder: true,
          providedExports: true,
          usedExports: true,
          concatenateModules: true,
          sideEffects: true,
          portableRecords: false,
          minimizer: [
            new TerserJSPlugin({
              extractComments: true
            }),
            new OptimizeCSSAssetsPlugin({
              cssProcessorPluginOptions: {
                preset: ['default', { discardComments: { removeAll: true } }]
              }
            })
          ]
        } as any),
        performance({
          hints: 'warning'
        })
      ]),
      env('development', [
        addPlugins([
          new TimeFixPlugin()
        ]),
        sourceMaps('inline-source-map'),
        customConfig({
          watchOptions: {
            ignored: `${this.project.dist}`,
            aggregateTimeout: 300
          }
        }) as Block<Context>
      ])
    ]

    return group([
      config,
      ...block,
      match(['*.tsx', '*.ts'], [target === 'webnew' ? webnewBabel : weboldBabel])
    ])
  }
}

```


[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 micro/packages/micro-react/plugins/serve/cjsChunkExtractor.ts from the micro VTEX app.

[Assistant]
Here's the implementation:

```typescript
import { ServePlugin } from '@vtex/micro-core'

export interface Extractor {
  addChunk: (chunk: string) => void
  getScriptTags: () => string
  getStyleTags: () => string
  getLinkTags: () => string
}

// Some dependencies think they have access to this variable. Webpack
// has a plugin for adding this to the bundles, however we need to
// add this while using es6 only
const setupEnvVar = (options: ServePlugin<unknown>['options']) =>
`<script>
window.process = {
  env: {
    NODE_ENV: "${options.mode}"
  }
}
</script>`

const getModuleImportTag = (options: ServePlugin<unknown>['options']) =>
`<script type="module-shim">
import "${options.publicPaths.assets}pages/${options.page.name}.js";
</script>`

// TODO: We should figure out a way to preload the script tags are we require them
export class CJSChunkExtractor implements Extractor {
  protected chunks: Set<string> = new Set()

  constructor (
    public options: ServePlugin<unknown>['options']
  ) {}

  public addChunk = (chunk: string) => {
    if (!this.chunks.has(chunk)) {
      this.chunks.add(chunk)
    }
  }

  public getScriptTags = () =>
    '<script id="__LOADABLE_REQUIRED_CHUNKS__">[]</script>' +
    setupEnvVar(this.options) +
    getModuleImportTag(this.options) +
    '<script src="https://unpkg.com/es-module-shims"></script>' // TODO: Remove this once chrome supports import maps

  public getStyleTags = () => ''
  public getLinkTags = () => ''
}

```


[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 micro/packages/micro-react/plugins/serve/index.ts from the micro VTEX app.

[Assistant]
Here's the implementation:

```typescript
import { ChunkExtractor, ChunkExtractorManager } from '@loadable/server'
import { ServeFrameworkPlugin, ServePluginOptions } from '@vtex/micro-core'
import { readFileSync } from 'fs-extra'
import { join } from 'path'
import { createElement } from 'react'
import { renderToString } from 'react-dom/server'

import { withAppContainerTags } from '../../components/container'
import { withPageDataTags } from '../../components/data'
import { externalPublicPathVariable } from '../../components/publicPaths'
import { withRuntimeTags } from '../../components/runtime'
import { CJSChunkExtractor, Extractor } from './cjsChunkExtractor'

export default class Serve extends ServeFrameworkPlugin<JSX.Element> {
  public extractor: Extractor

  constructor (options: ServePluginOptions) {
    super(options)
    if (this.options.lifecycleTarget === 'bundle') {
      this.extractor = new ChunkExtractor({
        entrypoints: [options.page.name],
        publicPath: options.publicPaths.assets,
        stats: options.stats
      }) as any // TODO: fix this as any
    } else {
      this.extractor = new CJSChunkExtractor(options)
    }
  }

  public renderToString = (element: JSX.Element | null) => {
    let ssr = ''
    if (element) {
      ssr = renderToString(createElement(ChunkExtractorManager, {
        extractor: this.extractor,
        children: element
      } as any)) // TODO: fix this as any
    }
    return withAppContainerTags(ssr)
  }

  public requireEntrypoint = (): JSX.Element => {
    const { page: { data, name } } = this.options
    const locator = join(this.options.assetsDist.nodejs, 'pages', name)
    const { default: App } = require(locator)
    // TODO: Figure out a way to the error come from the router
    return createElement(App, { data, error: null } as any)
  }

  public getScriptTags = () => {
    const {
      publicPaths
    } = this.options
    const tags: string[] = []
    tags.push(withRuntimeTags({ publicPaths }))
    tags.push(`<script type="application/javascript">${externalPublicPathVariable}="${this.options.publicPaths.assets}"</script>`)
    tags.push(this.extractor.getScriptTags())
    return tags.join('\n')
  }

  public getStyleTags = () => {
    if (typeof (this.extractor as any).getMainAssets === 'function') {
      const assets = (this.extractor as any).getMainAssets('style')
      return assets.map(
        ({ path, chunk }: { path: string, chunk: string }) => {
          const content = readFileSync(path)
          return `<style data-chunk="${chunk}" rel="stylesheet">${content}</style>`
        }
      ).join('\n')
    }
    // return this.extractor.getStyleTags()
  }

  public getLinkTags = () => {
    const { page: { name, data }, publicPaths: { data: dataRootPath }, path } = this.options
    const tagsNoCSS = this.extractor!.getLinkTags().split('\n').filter(x => !x.includes('as="style"')).join('\n')
    const dataTags = withPageDataTags(name, data, dataRootPath, path)
    return [
      tagsNoCSS,
      dataTags
    ].join('\n')
    // return [
    //   dataTags,
    //   this.extractor.getLinkTags()
    // ].join('\n')
  }

  public getMetaTags = () => [
    '<meta name="viewport" content="width=device-width, initial-scale=1">',
    '<meta name="generator" content="micro@1.x">',
    '<meta charset=\'utf-8\'>'
  ].join('\n')
}

```


[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 micro/packages/micro-react/plugins/bundle/modules/babel.ts from the micro VTEX app.

[Assistant]
Here's the implementation:

```typescript
import { babel as babelBlocks, Util } from 'webpack-blocks'

// Code copied from: https://github.com/andywer/webpack-blocks/blob/master/packages/babel/index.js

export const babel: any = (options?: any) => Object.assign(
  babelBlocks(options),
  { post: postConfig }
)

export const postConfig: any = (context: any, util: Util) => {
  const ruleConfig = {
    test: /\.tsx?$/,
    ...context.match,
    use: [
      {
        loader: require.resolve('babel-loader'),
        options: context.babel
      }
    ]
  }
  return util.addLoader(ruleConfig)
}

```


[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 micro/packages/micro-react/plugins/bundle/modules/extractCSS.ts from the micro VTEX app.

[Assistant]
Here's the implementation:

```typescript
// eslint-disable-next-line @typescript-eslint/no-unused-vars
import webpack from 'webpack'
import MiniCssExtractPlugin from 'mini-css-extract-plugin'
import { Context, Util } from 'webpack-blocks'

interface Options {
  loader?: {
    esModule: boolean
  },
  plugin?: MiniCssExtractPlugin.PluginOptions
}

export const extractCss = (options?: Options) => (context: Context, { merge }: Util) => merge({
  module: {
    rules: [
      {
        ...context.match,
        use: [
          {
            loader: MiniCssExtractPlugin.loader,
            options: options?.loader
          }
        ]
      }
    ]
  },
  plugins: [
    new MiniCssExtractPlugin(options?.plugin)
  ]
})

```


[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 micro/packages/micro-react/plugins/bundle/modules/purgeCSS.ts from the micro VTEX app.

[Assistant]
Here's the implementation:

```typescript
import PurgeCSSPlugin from 'purgecss-webpack-plugin'
import { Configuration } from 'webpack'
import { Context, Util } from 'webpack-blocks'

type FirstOf<T extends [any]> = T extends [infer P] ? P : never

type Options = FirstOf<ConstructorParameters<typeof PurgeCSSPlugin>>

interface EnhancedContext extends Context {
  purgeCSSOptions: Options
}

const post = (context: Context, { addPlugin }: Util) => {
  const ctx = context as EnhancedContext
  return addPlugin(new PurgeCSSPlugin(ctx.purgeCSSOptions))
}

export const purgeCSS = (options: Partial<Options>) => {
  return Object.assign(
    (context: Context) => {
      const ctx = context as EnhancedContext
      ctx.purgeCSSOptions = {
        ...ctx.purgeCSSOptions,
        ...options
      }
      return (config: Configuration) => config
    },
    { post }
  )
}

```


[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 micro/packages/micro-react/plugins/bundle/modules/cacheGroups.ts from the micro VTEX app.

[Assistant]
Here's the implementation:

```typescript
import { Configuration } from 'webpack'
import { Context } from 'webpack-blocks'

export const cacheGroup = (name: string, regexp: RegExp) => (_: Context, util: any) => (prevConfig: Configuration) => {
  const previousRegexp = getRegexFromCacheGroup(name, prevConfig.optimization)

  return util.merge({
    optimization: {
      splitChunks: {
        cacheGroups: {
          [name]: {
            test: mergeRegex(regexp, previousRegexp),
            reuseExistingChunk: true,
            name: name,
            chunks: 'all',
            enforce: true
          }
        }
      }
    }
  })(prevConfig)
}

const mergeRegex = (r1: RegExp, r2: RegExp | undefined): RegExp => {
  if (!r2) {
    return r1
  }
  return new RegExp(r1.source + '|' + r2.source)
}

const isRegExp = (a: any): a is RegExp => typeof a.exec === 'function'

const getRegexFromCacheGroup = (name: string, optimization: Configuration['optimization']) => {
  if (
    !optimization ||
    !optimization.splitChunks ||
    !optimization.splitChunks.cacheGroups ||
    typeof optimization.splitChunks.cacheGroups === 'string' ||
    typeof optimization.splitChunks.cacheGroups === 'function' ||
    isRegExp(optimization.splitChunks.cacheGroups)
  ) {
    return
  }
  const cacheGroup = optimization.splitChunks.cacheGroups[name]
  if (!cacheGroup) {
    return
  }
  if (isRegExp(cacheGroup.test)) {
    return cacheGroup.test
  }
}

```


[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 micro/packages/micro-react/components/context/Runtime.tsx from the micro VTEX app.

[Assistant]
Here's the implementation:

```tsx
import React from 'react'

import { RuntimeData } from '../runtime'

export const Runtime = React.createContext<RuntimeData>({} as RuntimeData)

```


[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 micro/packages/micro-core/lib/project.ts from the micro VTEX app.

[Assistant]
Here's the implementation:

```typescript
import assert from 'assert'
import { join } from 'path'

import { parse } from './common/semver'
import { MICRO_BUILD_DIR } from './constants'
import { resolveProjectAliases } from './importMap'
import { Package, PackageRootEntries, Plugins } from './package/base'
import { PnpPackage } from './package/pnp'

export type LifeCycle = 'serve' | 'bundle' | 'build'

export interface ProjectOptions {
  rootPath: string
}

/**
 * Resolution of the packages project wise
 * For responding, this class usually perform a DFS in the dependency graph of the project
 */
export class Project {
  public root: Package = null as any
  public rootPath: string
  public dist: string

  constructor ({ rootPath }: ProjectOptions) {
    this.dist = join(rootPath, MICRO_BUILD_DIR)
    this.rootPath = rootPath
  }

  public resolveFiles = async (...targets: PackageRootEntries[]): Promise<string[]> => {
    assert(this.root, '💣 Could not find a package. Did you forget to resolve/restore packages ?')
    let promises: Array<Promise<string[]>> = []
    walk(this.root, curr => {
      const filtered = curr.getFiles(...targets)
      promises = promises.concat(filtered)
    })
    const files = await Promise.all(promises)
    return files.flat()
  }

  public resolvePlugins = async <T extends LifeCycle>(target: T): Promise<Record<string, NonNullable<Plugins[T]>>> => {
    assert(this.root, '💣 Could not find a package. Did you forget to resolve/restore packages ?')
    const dependencies = this.root.manifest.dependencies || {}
    const locators: string[] | undefined = this.root!.manifest.micro.plugins
    if (!locators) {
      return {}
    }
    const packages: Package[] = []
    walk(this.root, async curr => {
      const index = locators.findIndex(x => curr.manifest.name === x)
      if (index < 0) {
        return
      }
      const maybeVersion = dependencies[curr.manifest.name]
      if (maybeVersion && parse(maybeVersion).major === parse(curr.manifest.version).major) {
        const index = locators.findIndex(x => curr.manifest.name === x)
        packages.splice(index, 0, curr)
      }
    })
    const plugins = await packages.reduce(
      async (accPromise, pkg) => {
        const [acc, plugin] = await Promise.all([
          accPromise,
          pkg.getPlugin(target)
        ])
        if (plugin) {
          acc[pkg.manifest.name] = plugin as NonNullable<Plugins[T]>
        }
        return acc
      },
      Promise.resolve({} as Record<string, NonNullable<Plugins[T]>>)
    )
    return plugins
  }

  public getSelfPlugin = async <T extends LifeCycle>(target: T): Promise<NonNullable<Plugins[T]> | null> => {
    const plugins = this.root!.manifest.micro.plugins
    const index = plugins?.findIndex(p => p === this.root.manifest.name)
    if (index !== undefined && index > -1) {
      const targetPlugin = await this.root.getPlugin(target)
      if (targetPlugin) {
        return targetPlugin as NonNullable<Plugins[T]>
      }
    }
    return null
  }

  public getRouter = () => {
    assert(this.root, '💣 Could not find a package. Did you forget to resolve/restore packages ?')
    return this.root.getRouter()
  }

  public resolvePackages = async (linker: 'pnp' | 'node-modules' = 'pnp') => {
    assert(linker === 'pnp', '💣 Only PnP linker is implemented yet') // TODO: implement other linkers
    this.root = new PnpPackage()
    await this.root.resolve(this.rootPath)
  }

  public toString = () => {
    assert(this.root, '💣 Could not find a package. Did you forget to resolve/restore packages ?')
    return `${this.root.manifest.name}@${parse(this.root.manifest.version).major}.x`
  }

  public resolveAliases = () => resolveProjectAliases(this)
}

export type WalkFn = (r: Package, p: Package | null) => void

export const walk = (root: Package, fn: WalkFn) => {
  const seen = new Set<string>()
  walkRec(root, null, fn, seen)
  return root
}

const walkRec = (root: Package, parent: Package | null, fn: WalkFn, seen: Set<string>) => {
  const node = root.toString()

  if (seen.has(node)) {
    return
  }

  seen.add(node)
  fn(root, parent)

  for (const dependency of root.dependencies) {
    walkRec(dependency, root, fn, seen)
  }
}

```


[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 micro/packages/micro-core/lib/router.ts from the micro VTEX app.

[Assistant]
Here's the implementation:

```typescript
interface MicroRequest {
  path: string
  query: Record<string, string>
}

export type Serializable = object | string | number | null | undefined

export interface ResolvedPage<T extends Serializable> {
  name: string
  data: T
  status: number
}

interface ResolvedRedirect {
  location: string
  status: 301 | 302
}

type Resolved<T extends Serializable> = ResolvedPage<T> | ResolvedRedirect

export const isResolvedPage = <T extends Serializable>(obj: Resolved<T>): obj is ResolvedPage<T> =>
  typeof (obj as any).name === 'string'

export const isResolvedRedirect = <T extends Serializable>(obj: Resolved<T>): obj is ResolvedRedirect =>
  typeof (obj as any).location === 'string'

export interface Page {
  name: string
}

export type Router<T extends Serializable> = (
  request: MicroRequest,
  pages: Record<string, Page>
) => Promise<Resolved<T>>

```


[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 micro/packages/micro-core/lib/plugin.ts from the micro VTEX app.

[Assistant]
Here's the implementation:

```typescript
import { LifeCycle } from './project'

export interface PluginOptions {
  target: LifeCycle
}

export abstract class Plugin {
  public target: LifeCycle

  constructor ({ target }: PluginOptions) {
    this.target = target
  }
}

```


[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 micro/packages/micro-core/lib/index.ts from the micro VTEX app.

[Assistant]
Here's the implementation:

```typescript
export * from './constants'
export * from './package/manifest'
export * from './package/tsconfig'
export * from './package/base'
export * from './project'
export * from './lifecycles/bundle'
export * from './lifecycles/serve'
export * from './lifecycles/build'
export * from './common/webpack'
export * from './common/mode'
export * from './common/publicPaths'
export * from './common/semver'
export * from './router'
export * from './importMap'

```


[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 micro/packages/micro-core/lib/compiler.ts from the micro VTEX app.

[Assistant]
Here's the implementation:

```typescript
import { join } from 'path'

import { Plugins } from './package/base'
import { Plugin } from './plugin'
import { Project } from './project'

export interface CompilerOptions<T> {
  plugins: T[]
  project: Project
  target: keyof Plugins
}

export class Compiler<T extends Plugin> {
  protected plugins: T[]
  public dist: string
  public project: Project

  constructor ({ project, target, plugins }: CompilerOptions<T>) {
    this.project = project
    this.plugins = plugins
    this.dist = join(this.project.dist, target)
  }
}

```


[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 micro/packages/micro-core/lib/importMap.ts from the micro VTEX app.

[Assistant]
Here's the implementation:

```typescript
import assert from 'assert'
import { join } from 'path'
import pnp from 'pnpapi'

import { PublicPaths } from './common/publicPaths'
import { Alias } from './lifecycles/build'
import { getLocatorFromPackageInWorkspace } from './package/pnp/common'
import { readManifest, walk as walkPnp } from './package/pnp/dfs'
import { Project } from './project'

const SEPARATOR = '__imports__'

export const parseImportPath = (x: string) => {
  const [issuer, rest] = x.split('__imports__')
  const splitted = rest.slice(1).split('/')
  const module = splitted[0].startsWith('@') ? splitted.slice(0, 2).join('/') : splitted[0]
  const filepath = rest.replace(module, '')
  return {
    issuer,
    module,
    filepath
  }
}

type ImportMapPath = ReturnType<typeof parseImportPath>

export const formatImportPath = ({ issuer, module, filepath }: ImportMapPath) =>
  join(issuer, SEPARATOR, module, filepath)

// TODO: Make it work for pure linked dependencies with `yarn link`
export const resolveProjectAliases = async (project: Project, linker: 'pnp' | 'node-modules' = 'pnp') => {
  assert(linker === 'pnp', '💣 Only PnP linker is implemented yet') // TODO: implement other linkers
  const root = getLocatorFromPackageInWorkspace(project.root.manifest.name)
  let aliases: Alias[] = []

  await walkPnp(root, async (node, parent) => {
    if (parent === null) {
      return
    }

    const nodeInfo = pnp.getPackageInformation(node)
    const parentInfo = pnp.getPackageInformation(parent)

    const manifest = await readManifest(node, parent)

    const isModule = (manifest as any).module
    const isDirectDependency = parent.name === project.root.manifest.name
    const isParentLinked = (parentInfo as any).linkType === 'SOFT'
    const isLinked = (nodeInfo as any).linkType === 'SOFT'

    // The current package is linked, we need to serve it from the local filesystem
    if (isLinked || !isModule) {
      const absoluteImport = {
        name: manifest.name,
        version: `^${manifest.version}`,
        resolve: formatImportPath({ issuer: parent!.name!, module: manifest.name, filepath: 'index.js' })
      }
      const relativeImport = {
        name: manifest.name + '/',
        version: `^${manifest.version}`,
        resolve: formatImportPath({ issuer: parent!.name!, module: manifest.name, filepath: '/' })
      }
      aliases = aliases.concat(absoluteImport, relativeImport)
    } else if (isParentLinked || isDirectDependency) {
      aliases.push({ name: manifest.name, version: `^${manifest.version}` })
    }
  })

  return aliases
}

export interface ImportMap {
  imports: Record<string, string>
  scopes?: Record<string, Record<string, string>>
}

export const importMapFromAliases = (projectAliases: Alias[], pluginAliases: Alias[], publicPaths: PublicPaths): ImportMap => {
  const aliases = [...projectAliases, ...pluginAliases]
  const imports = aliases.reduce(
    (acc, { name, version, resolve }) => {
      acc[name] = resolve
        ? join(publicPaths.assets, resolve)
        : `https://cdn.pika.dev/${name}@${version}`
      return acc
    },
    {} as Record<string, string>
  )
  return { imports }
}

```


[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 micro/packages/micro-core/lib/common/pick.ts from the micro VTEX app.

[Assistant]
Here's the implementation:

```typescript
export const pick = <T, K extends keyof T>(obj: T, keys: K[]) => keys.reduce(
  (acc, key) => {
    acc[key] = obj[key]
    return acc
  },
  {} as Pick<T, K>
)

```


[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 micro/packages/micro-core/lib/common/webpack.ts from the micro VTEX app.

[Assistant]
Here's the implementation:

```typescript
import { Stats } from 'webpack'

export const getStatsForTarget = (target: 'nodejs' | 'webnew' | 'webold', stats: Stats.ToJsonOutput) =>
  stats.children?.find(s => s.name === target)

```


[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 micro/packages/micro-core/lib/common/publicPaths.ts from the micro VTEX app.

[Assistant]
Here's the implementation:

```typescript
export interface PublicPaths {
  data: string
  assets: 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 micro/packages/micro-core/lib/common/semver.ts from the micro VTEX app.

[Assistant]
Here's the implementation:

```typescript
interface Semver {
  major: number
  minor: number
  patch: number
  pre?: string
}

export const parse = (version: string): Semver => {
  const v = version.replace(/\^|~/g, '')
  const [major, minor, ...patchAndPre] = v.split('.')
  const [patch, pre] = patchAndPre.join('.').split('-')
  return {
    major: Number(major),
    minor: Number(minor),
    patch: Number(patch),
    pre
  }
}

export const format = ({ major, minor, patch, pre }: Semver) =>
  `${major.toString()}.${minor.toString()}.${patch.toString}${pre ? `-${pre}` : ''}`

// TODO: improve this to a real regex
export const isSemver = (x: any): x is Semver => typeof x === '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 micro/packages/micro-core/lib/lifecycles/serve.ts from the micro VTEX app.

[Assistant]
Here's the implementation:

```typescript
import { join } from 'path'
import { Stats } from 'webpack'

import { PublicPaths } from '../common/publicPaths'
import { Compiler, CompilerOptions } from '../compiler'
import { Plugin } from '../plugin'
import { LifeCycle } from '../project'
import { ResolvedPage } from '../router'

const lifecycle = 'serve'

export type ServeCompilerOptions<T> = Omit<CompilerOptions<ServePlugin<T>>, 'target' | 'plugins'> & {
  plugins: Array<new (options: ServePluginOptions) => (ServePlugin<T> | ServeFrameworkPlugin<T>)>
  options: Omit<ServePluginOptions, 'assetsDist'>
}

const assetsDistForLifecycle = (root: string, lifecycle: LifeCycle) => {
  if (lifecycle === 'build') {
    return {
      webnew: join(root, 'build/es6'),
      nodejs: join(root, 'build/cjs')
    }
  }
  if (lifecycle === 'bundle') {
    return {
      webnew: join(root, 'bundle/webnew'),
      webold: join(root, 'bundle/webold'),
      nodejs: join(root, 'build/cjs')
    }
  }
  throw new Error('💣 Targeting this lifecycle makes no sense')
}

export class ServeCompiler<T> extends Compiler<ServePlugin<T>> {
  protected frameworkPlugin: ServeFrameworkPlugin<T>

  constructor ({ project, plugins, options }: ServeCompilerOptions<T>) {
    super({ project, plugins: [], target: lifecycle })
    const fullOptions = {
      ...options,
      assetsDist: assetsDistForLifecycle(project.dist, options.lifecycleTarget)
    }
    this.plugins = plugins.map(P => new P(fullOptions))
    const frameworkIndex = this.plugins.findIndex(p => p instanceof ServeFrameworkPlugin)
    if (frameworkIndex < 0) {
      throw new Error('💣 At least one framework plugin is required. Take a look at @vtex/micro-react for using the React Framework')
    }
    this.frameworkPlugin = this.plugins[frameworkIndex] as ServeFrameworkPlugin<T>
  }

  public renderToString = (disableSSR: boolean = false) => {
    let App: T | null = null

    if (!disableSSR) {
      // Find a plugin that is able to require an entrypoint
      // Maybe this should be done by the framework itself
      // instead of via plugin
      App = this.frameworkPlugin.requireEntrypoint()

      if (App === null) {
        throw new Error('💣 No entrypoint was required during Server Side Rendering')
      }

      // Compose the App for SSR
      App = this.plugins.reduce(
        (acc, p) => p.render(acc),
        App
      )
    }

    return this.frameworkPlugin.renderToString(App)
  }

  public getScriptTags = () => this.plugins.reduce(
    (acc, plugin) => acc + plugin.getScriptTags(),
    ''
  )

  public getLinkTags = () => this.plugins.reduce(
    (acc, plugin) => acc + plugin.getLinkTags(),
    ''
  )

  public getStyleTags = () => this.plugins.reduce(
    (acc, plugin) => acc + plugin.getStyleTags(),
    ''
  )

  public getMetaTags = () => this.plugins.reduce(
    (acc, plugin) => acc + plugin.getMetaTags(),
    ''
  )
}

interface AssetsDist {
  webnew: string
  nodejs: string
  webold?: string
}

export interface ServePluginOptions {
  mode: 'production' | 'development'
  lifecycleTarget: 'build' | 'bundle'
  stats: Stats.ToJsonOutput
  publicPaths: PublicPaths
  assetsDist: AssetsDist
  page: ResolvedPage<any>
  path: string
}

export abstract class ServePlugin<T> extends Plugin {
  constructor (
    protected options: ServePluginOptions
  ) {
    super({ target: lifecycle })
  }

  public render = (element: T): T => element

  public getScriptTags = () => ''

  public getStyleTags = () => ''

  public getLinkTags = () => ''

  public getMetaTags = () => ''
}

export abstract class ServeFrameworkPlugin<T> extends ServePlugin<T> {
  // eslint-disable-next-line @typescript-eslint/no-unused-vars
  public renderToString = (_element: T | null): string => ''

  public requireEntrypoint = (): T | null => null
}

```


[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 micro/packages/micro-core/lib/lifecycles/bundle.ts from the micro VTEX app.

[Assistant]
Here's the implementation:

```typescript
import { join } from 'path'
import { Configuration } from 'webpack'
import { Block, Context, createConfig, setOutput } from 'webpack-blocks'

import { Mode } from '../common/mode'
import { Compiler, CompilerOptions } from '../compiler'
import { Plugin } from '../plugin'
import { Project } from '../project'

const lifecycle = 'bundle'

export const pagesRuntimeName = 'micro-runtime'
export const webpackRuntimeName = 'webpack-runtime'
export const pagesFrameworkName = 'micro-framework'

export type BundleTarget = 'webnew' | 'webold'

export type BundleCompilerOptions = Omit<CompilerOptions<BundlePlugin>, 'target' | 'plugins'> & {
  plugins: Array<new (options: BundlePluginOptions) => BundlePlugin>
  mode: Mode
}

export class BundleCompiler extends Compiler<BundlePlugin> {
  constructor ({ project, plugins, mode }: BundleCompilerOptions) {
    super({ project, plugins: [], target: lifecycle })
    this.plugins = plugins.map(P => new P({ project, mode }))
  }

  public getConfig = async (target: BundleTarget): Promise<Configuration> => {
    const initialConfig = setOutput({
      path: join(this.dist, target),
      publicPath: '/assets'
    })
    const merged = await this.plugins.reduce(
      async (acc, plugin) => plugin.getConfig(await acc, target),
      Promise.resolve(initialConfig)
    )
    return createConfig(merged)
  }
}

export interface BundlePluginOptions {
  project: Project
  mode: Mode
}

export abstract class BundlePlugin extends Plugin {
  public project: Project
  public mode: Mode

  constructor (
    options: BundlePluginOptions
  ) {
    super({ target: lifecycle })
    this.project = options.project
    this.mode = options.mode
  }

  // eslint-disable-next-line @typescript-eslint/no-unused-vars
  public abstract getConfig = async (config: Block<Context>, target: BundleTarget): Promise<Block<Context>> => {
    throw new Error(`💣 not implemented: ${target}, ${config}`)
  }
}

```


[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 micro/packages/micro-core/lib/lifecycles/build.ts from the micro VTEX app.

[Assistant]
Here's the implementation:

```typescript
import { TransformOptions } from '@babel/core'
import { readJSON } from 'fs-extra'
import { join } from 'path'

import { parse } from '../common/semver'
import { Mode } from '../common/mode'
import { Compiler, CompilerOptions } from '../compiler'
import { Plugin } from '../plugin'
import { Project } from '../project'

export const lifecycle = 'build'

export type BuildTarget = 'es6' | 'cjs'

export interface Alias {
  name: string
  version: string
  resolve?: string
}

export type BuildCompilerOptions = Omit<CompilerOptions<BuildPlugin>, 'target' | 'plugins'> & {
  plugins: Array<new (opts: BuildPluginOptions) => BuildPlugin>
  mode: Mode
}

export class BuildCompiler extends Compiler<BuildPlugin> {
  private mode: Mode

  constructor ({ project, plugins, mode }: BuildCompilerOptions) {
    super({ project, plugins: [], target: lifecycle })
    this.plugins = plugins.map(P => new P({ project, mode }))
    this.mode = mode
  }

  public getDist = (target: BuildTarget) => join(this.dist, target)

  public getConfig = async (target: BuildTarget) => {
    return this.plugins.reduce(
      async (acc, plugin) => plugin.getConfig(await acc, target),
      Promise.resolve({} as TransformOptions)
    )
  }

  public getAliases = async (onConflict: 'throw' | 'warn' | 'skip' = 'warn'): Promise<Alias[]> => {
    const aliases = await this.plugins.reduce(
      async (acc, plugin) => plugin.getAliases(await acc),
      Promise.resolve([] as Alias[])
    )

    // If we don't need to resolve conflicts, let's just return the merged aliases
    if (onConflict === 'skip') {
      return aliases
    }

    // Let's resolve the dependencies based on chosen conflict resolution rule
    const resolvedAliases: Record<string, Alias> = {}
    for (const current of aliases) {
      const { name, version } = current
      const previous = resolvedAliases[name]

      if (!previous) {
        resolvedAliases[name] = current
        continue
      }

      const { major: previousMajor } = parse(previous.version)
      const { major: currentMajor } = parse(version)
      if (previousMajor !== currentMajor) {
        switch (onConflict) {
          case 'throw':
            throw new Error(`💣 Dependency ${name} found duplicated. Need to resolve to ${previousMajor}.x or ${currentMajor}.x`)
          case 'warn':
            console.warn(`💣 Dependency ${name} found duplicated. Resolving to ${Math.max(previousMajor, currentMajor)}.x`)
            resolvedAliases[name] = previousMajor > currentMajor ? previous : current
        }
      }
    }

    return Object.values(resolvedAliases)
  }
}

export interface BuildPluginOptions {
  mode: Mode
  project: Project
}

export class BuildPlugin extends Plugin {
  public mode: Mode
  public project: Project

  constructor (options: BuildPluginOptions) {
    super({ target: lifecycle })
    this.mode = options.mode
    this.project = options.project
  }

  // eslint-disable-next-line @typescript-eslint/no-unused-vars
  public getConfig = async (previous: TransformOptions, target: BuildTarget): Promise<TransformOptions> => previous

  public getAliases = async (previous: Alias[]): Promise<Alias[]> => previous
}

export const packageToAlias = async (name: string, resolve: (x: string) => string): Promise<Alias> => {
  const packageJSONPath = resolve(`${name}/package.json`)
  const { version } = await readJSON(packageJSONPath)
  return { name, version: `^${version}` }
}

```


[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 micro/packages/micro-core/lib/package/base.ts from the micro VTEX app.

[Assistant]
Here's the implementation:

```typescript
import { parse } from '../common/semver'
import {
  BundlePlugin,
  BundlePluginOptions
} from '../lifecycles/bundle'
import { BuildPlugin, BuildPluginOptions } from '../lifecycles/build'
import {
  ServeFrameworkPlugin,
  ServePlugin,
  ServePluginOptions
} from '../lifecycles/serve'
import { LifeCycle } from '../project'
import { Router, Serializable } from '../router'
import { Manifest } from './manifest'
import { TSConfig } from './tsconfig'

export interface Plugins {
  serve?: new (options: ServePluginOptions) => ServePlugin<any> | ServeFrameworkPlugin<any>,
  bundle?: new (options: BundlePluginOptions) => BundlePlugin,
  build?: new (options: BuildPluginOptions) => BuildPlugin
}

export const PackageStructure = {
  lib: 'lib',
  pages: 'pages',
  router: 'router',
  index: 'index.ts',
  plugins: 'plugins',
  components: 'components',
  manifest: 'package.json',
  tsconfig: 'tsconfig.json'
}

export type PackageRootEntries = keyof typeof PackageStructure

export interface PackageOptions {
  plugins: Plugins
  tsconfig: TSConfig
  manifest: Manifest
  dependencies: Package[]
}

export abstract class Package {
  public tsconfig: TSConfig = null as any
  public manifest: Manifest = null as any
  public dependencies: Package[] = []
  public structure = PackageStructure

  public abstract resolve = async (projectRoot: string): Promise<void> => {
    throw new Error(`💣 not implemented: ${projectRoot}`)
  }

  public abstract hydrate = async (projectRoot: string): Promise<void> => {
    throw new Error(`💣 not implemented: ${projectRoot}`)
  }

  public abstract persist = async (projectRoot: string): Promise<void> => {
    throw new Error(`💣 not implemented: ${projectRoot}`)
  }

  public abstract getFiles = async (...targets: PackageRootEntries[]): Promise<string[]> => {
    throw new Error(`💣 not implemented: ${targets}`)
  }

  // eslint-disable-next-line @typescript-eslint/no-unused-vars
  public abstract getPlugin = async <T extends LifeCycle>(target: T): Promise<Plugins[T]> => {
    throw new Error('💣 not implemented')
  }

  public abstract getRouter = async <T extends Serializable>(): Promise<Router<T>> => {
    throw new Error('💣 not implemented')
  }

  public getGlobby = (...targets: PackageRootEntries[]) =>
    `@(${targets.map(t => PackageStructure[t]).join('|')})?(/**/*.ts?(x))`

  public toString = () => `${this.manifest.name}@${parse(this.manifest.version).major}.x`
}

```


[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 micro/packages/micro-core/lib/package/manifest.ts from the micro VTEX app.

[Assistant]
Here's the implementation:

```typescript
import { pick } from '../common/pick'
import { isSemver } from '../common/semver'
import { MICRO_BUILD_DIR } from '../constants'
import { lifecycle } from '../lifecycles/build'

type MicroOptions = {
  plugins: string[]
}

export const BaseManifest = {
  main: `./${MICRO_BUILD_DIR}/${lifecycle}/cjs/index.js`,
  module: `./${MICRO_BUILD_DIR}/${lifecycle}/es6/components/index.js`,
  browser: './components/index.ts',
  micro: {
    plugins: []
  } as MicroOptions,
  scripts: {
    build: 'yarn run micro build',
    watch: 'yarn run micro link',
    clean: `rm -r ${MICRO_BUILD_DIR}`,
    prepublish: 'yarn build'
  }
}

const necessary = pick(BaseManifest, ['main', 'module', 'browser'])
const required = pick(BaseManifest, ['micro'])

type Base = typeof BaseManifest

export interface Manifest extends Base {
  name: string
  version: string
  dependencies?: Record<string, string>
  devDependencies?: Record<string, string>
  peerDependencies?: Record<string, string>
}

// TODO: improve this condition
const isMicro = (x: any): x is MicroOptions => Array.isArray(x?.plugins)

export const isManifest = (obj: any): obj is Manifest => {
  return typeof obj?.name === 'string' &&
    isSemver(obj.version) &&
    obj.main === BaseManifest.main &&
    obj.module === BaseManifest.module &&
    obj.browser === BaseManifest.browser &&
    isMicro(obj.micro)
}

export const genManifest = (partial: Pick<Manifest, 'name' | 'version'>): Manifest => {
  const {
    name,
    vendor,
    version,
    description,
    title,
    license,
    micro,
    main,
    types,
    module,
    browser,
    // eslint-disable-next-line @typescript-eslint/no-unused-vars
    type,
    scripts,
    dependencies,
    devDependencies,
    peerDependencies,
    ...rest
  } = {
    ...required,
    ...partial,
    ...necessary
  } as any

  return {
    name,
    vendor,
    version,
    description,
    title,
    license,
    micro,
    scripts: {
      ...BaseManifest.scripts,
      ...scripts
    },
    main,
    types,
    module,
    browser,
    dependencies,
    devDependencies,
    peerDependencies,
    ...rest
  }
}

```