import * as fs from 'fs' import { NextConfig } from 'next' import type { PageMapCache } from 'nextra/dist/page-map.mjs' import * as path from 'path' import { Configuration } from 'webpack' import { PagesMetadata } from '../shared/lib/PagesMetadata' import { LoadedUnbodyConfig } from './types' import { setupThemeConfig } from './utils/setupThemeConfig' const findNextraLoaders = (config: Configuration) => { return (config.module?.rules || []).filter( (rule) => typeof rule === 'object' && 'use' in rule! && Array.isArray(rule.use) && typeof rule.use[1] === 'object' && rule.use[1]?.loader === 'nextra/loader' && rule.use[1].options && !(rule.use[1].options as any)?.isMetaImport, ) } export const extendWebpackConfig = async ({ config, nextConfig, }: { config: LoadedUnbodyConfig nextConfig: NextConfig }) => { let replacedThemeConfig = false let pageMapCache: PageMapCache = null as any return (webpackConfig: Configuration, options: any): Configuration => { const newConfig = nextConfig.webpack!( webpackConfig, options, ) as Configuration const nextraLoaders = findNextraLoaders(newConfig) const loaderOptions = (nextraLoaders[0] as any).use[1].options as Record< string, any > pageMapCache = loaderOptions.pageMapCache if (config.setupComponents && !replacedThemeConfig) { const themeConfig = loaderOptions.themeConfig if (!themeConfig) throw new Error( 'themeConfig is not set in your nextra config. Please make sure you either have a themeConfig or disable the component injection by setting "setupComponents" to false.', ) const newPath = setupThemeConfig({ config, originalPath: require.resolve(themeConfig, { paths: [config.projectDir], }), }) nextraLoaders.forEach((loader) => { ;(loader as any).use[1].options.themeConfig = newPath replacedThemeConfig = true }) } newConfig.plugins!.push({ apply: (compiler) => { compiler.hooks.afterCompile.tap('UnbodySearch', (compilation) => { const pages = pageMapCache.get()?.items || [] const pagesMetadata = PagesMetadata.fromPageMap(pages) const json = pagesMetadata.toJson() fs.writeFileSync( path.join(config.dir, 'pages-metadata.json'), JSON.stringify(json, null, 2), ) }) }, }) return newConfig } }