const fs = require('fs') const path = require('path') const withImages = require('next-images') class CustomResolver { constructor(source, target){ this.source = source || 'resolve'; this.target = target || 'resolve'; } apply(resolver) { const target = resolver.ensureHook(this.target); resolver .getHook(this.source) .tapAsync("CustomResolver", (request, resolveContext, callback) => { // request.request is the string path we're resolving // match ~/[dir]/[path] const match = request.request.match(/^(?:\.\/|)\~\/(?[^/]*)\/(?.+)$/) const allowedShortcutDirs = [ 'styles', 'hooks', 'components', 'images', 'pages', 'utils' ] // If it's not the right pattern, or it's outside our list of directories // handle normally if(!match || !allowedShortcutDirs.includes(match.groups.dir)) return callback(); const dirPath = match.groups.path.split('/') const componentDir = dirPath.pop() const resolvedDir = path.join(__dirname, match.groups.dir, dirPath.join('/')) // Default to basic (no extension) let selectedPath = path.join(resolvedDir, componentDir) // Attempt a few paths with an extension, just in case const pathsToCheck = [ path.join(resolvedDir, componentDir, componentDir + '.js'), path.join(resolvedDir, componentDir + '.js') ] for(const path of pathsToCheck) if(fs.existsSync(path)){ selectedPath = path break } // Forge new request to pass to the resolver const newRequest = { ...request, request: selectedPath } resolver.doResolve(target, newRequest, null, resolveContext, callback); }); } } module.exports = withImages({ webpack: (config) => { config.resolve.plugins.push(new CustomResolver()) return config }, publicRuntimeConfig: { STRIPE_PUBLIC_KEY: process.env.STRIPE_PUBLIC_KEY, SOS_ENV: process.env.SOS_ENV } })