{"version":3,"sources":["../../../../src/build/webpack/loaders/next-metadata-route-loader.ts"],"sourcesContent":["import type webpack from 'webpack'\nimport fs from 'fs'\nimport path from 'path'\nimport { imageExtMimeTypeMap } from '../../../lib/mime-type'\nimport { getLoaderModuleNamedExports } from './utils'\n\nfunction errorOnBadHandler(resourcePath: string) {\n  return `\n  if (typeof handler !== 'function') {\n    throw new Error('Default export is missing in ${JSON.stringify(\n      resourcePath\n    )}')\n  }\n  `\n}\n\n/* re-export the userland route configs */\nasync function createReExportsCode(\n  resourcePath: string,\n  loaderContext: webpack.LoaderContext<any>\n) {\n  const exportNames = await getLoaderModuleNamedExports(\n    resourcePath,\n    loaderContext\n  )\n  // Re-export configs but avoid conflicted exports\n  const reExportNames = exportNames.filter(\n    (name) => name !== 'default' && name !== 'generateSitemaps'\n  )\n\n  return reExportNames.length > 0\n    ? `export { ${reExportNames.join(', ')} } from ${JSON.stringify(\n        resourcePath\n      )}\\n`\n    : ''\n}\n\nconst cacheHeader = {\n  none: 'no-cache, no-store',\n  longCache: 'public, immutable, no-transform, max-age=31536000',\n  revalidate: 'public, max-age=0, must-revalidate',\n}\n\nexport type MetadataRouteLoaderOptions = {\n  // Using separate argument to avoid json being parsed and hit error\n  // x-ref: https://github.com/vercel/next.js/pull/62615\n  filePath: string\n  isDynamicRouteExtension: '1' | '0'\n}\n\nexport function getFilenameAndExtension(resourcePath: string) {\n  const filename = path.basename(resourcePath)\n  const [name, ext] = filename.split('.', 2)\n  return {\n    name,\n    ext,\n  }\n}\n\nfunction getContentType(resourcePath: string) {\n  let { name, ext } = getFilenameAndExtension(resourcePath)\n  if (ext === 'jpg') ext = 'jpeg'\n\n  if (name === 'favicon' && ext === 'ico') return 'image/x-icon'\n  if (name === 'sitemap') return 'application/xml'\n  if (name === 'robots') return 'text/plain'\n  if (name === 'manifest') return 'application/manifest+json'\n\n  if (ext === 'png' || ext === 'jpeg' || ext === 'ico' || ext === 'svg') {\n    return imageExtMimeTypeMap[ext]\n  }\n  return 'text/plain'\n}\n\nasync function getStaticAssetRouteCode(\n  resourcePath: string,\n  fileBaseName: string\n) {\n  const cache =\n    fileBaseName === 'favicon'\n      ? 'public, max-age=0, must-revalidate'\n      : process.env.NODE_ENV !== 'production'\n        ? cacheHeader.none\n        : cacheHeader.longCache\n\n  const isTwitter = fileBaseName === 'twitter-image'\n  const isOpenGraph = fileBaseName === 'opengraph-image'\n  // Twitter image file size limit is 5MB.\n  // General Open Graph image file size limit is 8MB.\n  // x-ref: https://developer.x.com/en/docs/x-for-websites/cards/overview/summary\n  // x-ref(facebook): https://developers.facebook.com/docs/sharing/webmasters/images\n  const fileSizeLimit = isTwitter ? 5 : 8\n  const imgName = isTwitter ? 'Twitter' : 'Open Graph'\n\n  const code = `\\\n/* static asset route */\nimport { NextResponse } from 'next/server'\n\nconst contentType = ${JSON.stringify(getContentType(resourcePath))}\nconst buffer = Buffer.from(${JSON.stringify(\n    (await fs.promises.readFile(resourcePath)).toString('base64')\n  )}, 'base64'\n  )\n\nif (${isTwitter || isOpenGraph}) {\n  const fileSizeInMB = buffer.byteLength / 1024 / 1024\n  if (fileSizeInMB > ${fileSizeLimit}) {\n    throw new Error('File size for ${imgName} image ${JSON.stringify(resourcePath)} exceeds ${fileSizeLimit}MB. ' +\n    \\`(Current: \\${fileSizeInMB.toFixed(2)}MB)\\n\\` +\n    'Read more: https://nextjs.org/docs/app/api-reference/file-conventions/metadata/opengraph-image#image-files-jpg-png-gif'\n    )\n  }\n}\n\nexport function GET() {\n  return new NextResponse(buffer, {\n    headers: {\n      'Content-Type': contentType,\n      'Cache-Control': ${JSON.stringify(cache)},\n    },\n  })\n}\n\nexport const dynamic = 'force-static'\n`\n  return code\n}\n\nasync function getDynamicTextRouteCode(\n  resourcePath: string,\n  loaderContext: webpack.LoaderContext<any>\n) {\n  return `\\\n/* dynamic asset route */\nimport { NextResponse } from 'next/server'\nimport handler from ${JSON.stringify(resourcePath)}\nimport { resolveRouteData } from 'next/dist/build/webpack/loaders/metadata/resolve-route-data'\n\nconst contentType = ${JSON.stringify(getContentType(resourcePath))}\nconst fileType = ${JSON.stringify(getFilenameAndExtension(resourcePath).name)}\n\n${errorOnBadHandler(resourcePath)}\n${await createReExportsCode(resourcePath, loaderContext)}\n\nexport async function GET() {\n  const data = await handler()\n  const content = resolveRouteData(data, fileType)\n\n  return new NextResponse(content, {\n    headers: {\n      'Content-Type': contentType,\n      'Cache-Control': ${JSON.stringify(cacheHeader.revalidate)},\n    },\n  })\n}\n`\n}\n\n// <metadata-image>/[id]/route.js\nasync function getDynamicImageRouteCode(\n  resourcePath: string,\n  loaderContext: webpack.LoaderContext<any>\n) {\n  return `\\\n/* dynamic image route */\nimport { NextResponse } from 'next/server'\nimport * as userland from ${JSON.stringify(resourcePath)}\n\nconst imageModule = { ...userland }\n\nconst handler = imageModule.default\nconst generateImageMetadata = imageModule.generateImageMetadata\n\n${errorOnBadHandler(resourcePath)}\n${await createReExportsCode(resourcePath, loaderContext)}\n\nexport async function GET(_, ctx) {\n  const params = await ctx.params\n  const { __metadata_id__, ...rest } = params || {}\n  const restParams = params ? rest : undefined\n  const targetId = __metadata_id__\n  let id = undefined\n  \n  if (generateImageMetadata) {\n    const imageMetadata = await generateImageMetadata({ params: restParams })\n    id = imageMetadata.find((item) => {\n      if (process.env.NODE_ENV !== 'production') {\n        if (item?.id == null) {\n          throw new Error('id property is required for every item returned from generateImageMetadata')\n        }\n      }\n      return item.id.toString() === targetId\n    })?.id\n    if (id == null) {\n      return new NextResponse('Not Found', {\n        status: 404,\n      })\n    }\n  }\n\n  return handler({ params: restParams, id })\n}\n`\n}\n\nasync function getDynamicSitemapRouteCode(\n  resourcePath: string,\n  loaderContext: webpack.LoaderContext<any>\n) {\n  let staticGenerationCode = ''\n\n  const exportNames = await getLoaderModuleNamedExports(\n    resourcePath,\n    loaderContext\n  )\n\n  const hasGenerateSitemaps = exportNames.includes('generateSitemaps')\n\n  if (process.env.NODE_ENV === 'production' && hasGenerateSitemaps) {\n    staticGenerationCode = `\\\n    /* dynamic sitemap route */\n    export async function generateStaticParams() {\n      const sitemaps = await sitemapModule.generateSitemaps()\n      const params = []\n\n      for (const item of sitemaps) {\n        params.push({ __metadata_id__: item.id.toString() + '.xml' })\n      }\n      return params\n    }\n    `\n  }\n\n  const code = `\\\nimport { NextResponse } from 'next/server'\nimport * as userland from ${JSON.stringify(resourcePath)}\nimport { resolveRouteData } from 'next/dist/build/webpack/loaders/metadata/resolve-route-data'\n\nconst sitemapModule = { ...userland }\nconst handler = sitemapModule.default\nconst contentType = ${JSON.stringify(getContentType(resourcePath))}\nconst fileType = ${JSON.stringify(getFilenameAndExtension(resourcePath).name)}\n\n${errorOnBadHandler(resourcePath)}\n${await createReExportsCode(resourcePath, loaderContext)}\n\nexport async function GET(_, ctx) {\n  const { __metadata_id__: id, ...params } = await ctx.params || {}\n  const hasXmlExtension = id ? id.endsWith('.xml') : false\n\n  if (id && !hasXmlExtension) {\n    return new NextResponse('Not Found', {\n      status: 404,\n    })\n  }\n\n  if (process.env.NODE_ENV !== 'production' && sitemapModule.generateSitemaps) {\n    const sitemaps = await sitemapModule.generateSitemaps()\n    for (const item of sitemaps) {\n      if (item?.id == null) {\n        throw new Error('id property is required for every item returned from generateSitemaps')\n      }\n    }\n  }\n\n  const targetId = id && hasXmlExtension ? id.slice(0, -4) : undefined\n\n  const data = await handler({ id: targetId })\n  const content = resolveRouteData(data, fileType)\n\n  return new NextResponse(content, {\n    headers: {\n      'Content-Type': contentType,\n      'Cache-Control': ${JSON.stringify(cacheHeader.revalidate)},\n    },\n  })\n}\n\n${staticGenerationCode}\n`\n  return code\n}\n\n// When it's static route, it could be favicon.ico, sitemap.xml, robots.txt etc.\n// TODO-METADATA: improve the cache control strategy\nconst nextMetadataRouterLoader: webpack.LoaderDefinitionFunction<MetadataRouteLoaderOptions> =\n  async function () {\n    const { isDynamicRouteExtension, filePath } = this.getOptions()\n    const { name: fileBaseName } = getFilenameAndExtension(filePath)\n    this.addDependency(filePath)\n\n    let code = ''\n    if (isDynamicRouteExtension === '1') {\n      if (fileBaseName === 'robots' || fileBaseName === 'manifest') {\n        code = await getDynamicTextRouteCode(filePath, this)\n      } else if (fileBaseName === 'sitemap') {\n        code = await getDynamicSitemapRouteCode(filePath, this)\n      } else {\n        code = await getDynamicImageRouteCode(filePath, this)\n      }\n    } else {\n      code = await getStaticAssetRouteCode(filePath, fileBaseName)\n    }\n\n    return code\n  }\n\nexport default nextMetadataRouterLoader\n"],"names":["getFilenameAndExtension","errorOnBadHandler","resourcePath","JSON","stringify","createReExportsCode","loaderContext","exportNames","getLoaderModuleNamedExports","reExportNames","filter","name","length","join","cacheHeader","none","longCache","revalidate","filename","path","basename","ext","split","getContentType","imageExtMimeTypeMap","getStaticAssetRouteCode","fileBaseName","cache","process","env","NODE_ENV","isTwitter","isOpenGraph","fileSizeLimit","imgName","code","fs","promises","readFile","toString","getDynamicTextRouteCode","getDynamicImageRouteCode","getDynamicSitemapRouteCode","staticGenerationCode","hasGenerateSitemaps","includes","nextMetadataRouterLoader","isDynamicRouteExtension","filePath","getOptions","addDependency"],"mappings":"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","ignoreList":[0]}