text: "use strict";exports.__esModule=true;exports.default=void 0;var _amphtmlValidator=_interopRequireDefault(require("amphtml-validator"));var _crypto=_interopRequireDefault(require("crypto"));var _findUp=_interopRequireDefault(require("find-up"));var _fs=_interopRequireDefault(require("fs"));var _path=require("path");var _react=_interopRequireDefault(require("react"));var _util=require("util");var _watchpack=_interopRequireDefault(require("watchpack"));var _index=require("../build/output/index");var Log=_interopRequireWildcard(require("../build/output/log"));var _checkCustomRoutes=_interopRequireDefault(require("../lib/check-custom-routes"));var _constants=require("../lib/constants");var _findPagesDir=require("../lib/find-pages-dir");var _verifyTypeScriptSetup=require("../lib/verifyTypeScriptSetup");var _constants2=require("../next-server/lib/constants");var _utils=require("../next-server/lib/router/utils");var _nextServer=_interopRequireDefault(require("../next-server/server/next-server"));var _normalizePagePath=require("../next-server/server/normalize-page-path");var _router=_interopRequireWildcard(require("../next-server/server/router"));var _events=require("../telemetry/events");var _storage=require("../telemetry/storage");var _errorDebug=_interopRequireDefault(require("./error-debug"));var _hotReloader=_interopRequireDefault(require("./hot-reloader"));var _findPageFile=require("./lib/find-page-file");function _getRequireWildcardCache(){if(typeof WeakMap!=="function")return null;var cache=new WeakMap();_getRequireWildcardCache=function(){return cache;};return cache;}function _interopRequireWildcard(obj){if(obj&&obj.__esModule){return obj;}if(obj===null||typeof obj!=="object"&&typeof obj!=="function"){return{default:obj};}var cache=_getRequireWildcardCache();if(cache&&cache.has(obj)){return cache.get(obj);}var newObj={};var hasPropertyDescriptor=Object.defineProperty&&Object.getOwnPropertyDescriptor;for(var key in obj){if(Object.prototype.hasOwnProperty.call(obj,key)){var desc=hasPropertyDescriptor?Object.getOwnPropertyDescriptor(obj,key):null;if(desc&&(desc.get||desc.set)){Object.defineProperty(newObj,key,desc);}else{newObj[key]=obj[key];}}}newObj.default=obj;if(cache){cache.set(obj,newObj);}return newObj;}function _interopRequireDefault(obj){return obj&&obj.__esModule?obj:{default:obj};}if(typeof _react.default.Suspense==='undefined'){throw new Error(`The version of React you are using is lower than the minimum required version needed for Next.js. Please upgrade "react" and "react-dom": "npm install react react-dom" https://err.sh/zeit/next.js/invalid-react-version`);}const fsStat=(0,_util.promisify)(_fs.default.stat);class DevServer extends _nextServer.default{constructor(options){super({...options,dev:true});this.devReady=void 0;this.setDevReady=void 0;this.webpackWatcher=void 0;this.hotReloader=void 0;this.isCustomServer=void 0;this._devCachedPreviewProps=void 0;this.renderOpts.dev=true;this.renderOpts.ErrorDebug=_errorDebug.default;this.devReady=new Promise(resolve=>{this.setDevReady=resolve;});this.renderOpts.ampValidator=(html,pathname)=>{const validatorPath=this.nextConfig.experimental&&this.nextConfig.experimental.amp&&this.nextConfig.experimental.amp.validator;return _amphtmlValidator.default.getInstance(validatorPath).then(validator=>{const result=validator.validateString(html);(0,_index.ampValidation)(pathname,result.errors.filter(e=>e.severity==='ERROR').filter(e=>this._filterAmpDevelopmentScript(html,e)),result.errors.filter(e=>e.severity!=='ERROR'));});};if(_fs.default.existsSync((0,_path.join)(this.dir,'static'))){console.warn(`The static directory has been deprecated in favor of the public directory. https://err.sh/zeit/next.js/static-dir-deprecated`);}this.isCustomServer=!options.isNextDevCommand;this.pagesDir=(0,_findPagesDir.findPagesDir)(this.dir);}currentPhase(){return _constants2.PHASE_DEVELOPMENT_SERVER;}readBuildId(){return'development';}async addExportPathMapRoutes(){// Makes `next export` exportPathMap work in development mode.
  // So that the user doesn't have to define a custom server reading the exportPathMap
  if(this.nextConfig.exportPathMap){console.log('Defining routes from exportPathMap');const exportPathMap=await this.nextConfig.exportPathMap({},{dev:true,dir:this.dir,outDir:null,distDir:this.distDir,buildId:this.buildId});// In development we can't give a default path mapping
  for(const path in exportPathMap){const{page,query={}}=exportPathMap[path];// We use unshift so that we're sure the routes is defined before Next's default routes
  this.router.addFsRoute({match:(0,_router.route)(path),type:'route',name:`${path} exportpathmap route`,fn:async(req,res,params,parsedUrl)=>{const{query:urlQuery}=parsedUrl;Object.keys(urlQuery).filter(key=>query[key]===undefined).forEach(key=>console.warn(`Url '${path}' defines a query parameter '${key}' that is missing in exportPathMap`));const mergedQuery={...urlQuery,...query};await this.render(req,res,page,mergedQuery,parsedUrl);return{finished:true};}});}}}async startWatcher(){if(this.webpackWatcher){return;}let resolved=false;return new Promise(resolve=>{const pagesDir=this.pagesDir;// Watchpack doesn't emit an event for an empty directory
  _fs.default.readdir(pagesDir,(_,files)=>{if(files===null||files===void 0?void 0:files.length){return;}if(!resolved){resolve();resolved=true;}});let wp=this.webpackWatcher=new _watchpack.default();wp.watch([],[pagesDir],0);wp.on('aggregated',()=>{const dynamicRoutedPages=[];const knownFiles=wp.getTimeInfoEntries();for(const[fileName,{accuracy}]of knownFiles){if(accuracy===undefined){continue;}let pageName='/'+(0,_path.relative)(pagesDir,fileName).replace(/\\+/g,'/');pageName=pageName.replace(new RegExp(`\\.+(?:${this.nextConfig.pageExtensions.join('|')})$`),'');pageName=pageName.replace(/\/index$/,'')||'/';if(!(0,_utils.isDynamicRoute)(pageName)){continue;}dynamicRoutedPages.push(pageName);}this.dynamicRoutes=(0,_utils.getSortedRoutes)(dynamicRoutedPages).map(page=>({page,match:(0,_utils.getRouteMatcher)((0,_utils.getRouteRegex)(page))}));this.router.setDynamicRoutes(this.dynamicRoutes);if(!resolved){resolve();resolved=true;}});});}async stopWatcher(){if(!this.webpackWatcher){return;}this.webpackWatcher.close();this.webpackWatcher=null;}async prepare(){await(0,_verifyTypeScriptSetup.verifyTypeScriptSetup)(this.dir,this.pagesDir);await this.loadCustomRoutes();if(this.customRoutes){const{redirects,rewrites}=this.customRoutes;if(redirects.length||rewrites.length){this.router=new _router.default(this.generateRoutes());}}this.hotReloader=new _hotReloader.default(this.dir,{pagesDir:this.pagesDir,config:this.nextConfig,previewProps:this.getPreviewProps(),buildId:this.buildId});await super.prepare();await this.addExportPathMapRoutes();await this.hotReloader.start();await this.startWatcher();this.setDevReady();const telemetry=new _storage.Telemetry({distDir:this.distDir});telemetry.record((0,_events.eventCliSession)(_constants2.PHASE_DEVELOPMENT_SERVER,this.distDir,{cliCommand:'dev',isSrcDir:(0,_path.relative)(this.dir,this.pagesDir).startsWith('src'),hasNowJson:!!(await(0,_findUp.default)('now.json',{cwd:this.dir})),isCustomServer:this.isCustomServer}));}async close(){await this.stopWatcher();if(this.hotReloader){await this.hotReloader.stop();}}async hasPage(pathname){const pageFile=await(0,_findPageFile.findPageFile)(this.pagesDir,(0,_normalizePagePath.normalizePagePath)(pathname),this.nextConfig.pageExtensions);return!!pageFile;}async _beforeCatchAllRender(req,res,params,parsedUrl){const{pathname}=parsedUrl;const path=`/${(params.path||[]).join('/')}`;// check for a public file, throwing error if there's a
  // conflicting page
  if(await this.hasPublicFile(path)){if(await this.hasPage(pathname)){const err=new Error(`A conflicting public file and page file was found for path ${pathname} https://err.sh/zeit/next.js/conflicting-public-file-page`);res.statusCode=500;await this.renderError(err,req,res,pathname,{});return true;}await this.servePublic(req,res,path);return true;}return false;}async run(req,res,parsedUrl){await this.devReady;const{pathname}=parsedUrl;if(pathname.startsWith('/_next')){try{await fsStat((0,_path.join)(this.publicDir,'_next'));throw new Error(_constants.PUBLIC_DIR_MIDDLEWARE_CONFLICT);}catch(err){}}const{finished}=(await this.hotReloader.run(req,res,parsedUrl))||{finished:false};if(finished){return;}return super.run(req,res,parsedUrl);}// override production loading of routes-manifest
  getCustomRoutes(){return this.customRoutes;}getPreviewProps(){if(this._devCachedPreviewProps){return this._devCachedPreviewProps;}return this._devCachedPreviewProps={previewModeId:_crypto.default.randomBytes(16).toString('hex'),previewModeSigningKey:_crypto.default.randomBytes(32).toString('hex'),previewModeEncryptionKey:_crypto.default.randomBytes(32).toString('hex')};}async loadCustomRoutes(){const result={redirects:[],rewrites:[],headers:[]};const{redirects,rewrites,headers}=this.nextConfig.experimental;if(typeof redirects==='function'){result.redirects=await redirects();(0,_checkCustomRoutes.default)(result.redirects,'redirect');}if(typeof rewrites==='function'){result.rewrites=await rewrites();(0,_checkCustomRoutes.default)(result.rewrites,'rewrite');}if(typeof headers==='function'){result.headers=await headers();(0,_checkCustomRoutes.default)(result.headers,'header');}this.customRoutes=result;}generateRoutes(){const{fsRoutes,...otherRoutes}=super.generateRoutes();// In development we expose all compiled files for react-error-overlay's line show feature
  // We use unshift so that we're sure the routes is defined before Next's default routes
  fsRoutes.unshift({match:(0,_router.route)('/_next/development/:path*'),type:'route',name:'_next/development catchall',fn:async(req,res,params)=>{const p=(0,_path.join)(this.distDir,...(params.path||[]));await this.serveStatic(req,res,p);return{finished:true};}});fsRoutes.push({match:(0,_router.route)('/:path*'),type:'route',name:'Catchall public directory route',fn:async(req,res,params,parsedUrl)=>{const{pathname}=parsedUrl;if(!pathname){throw new Error('pathname is undefined');}// Used in development to check public directory paths
  if(await this._beforeCatchAllRender(req,res,params,parsedUrl)){return{finished:true};}return{finished:false};}});return{fsRoutes,...otherRoutes};}// In development public files are not added to the router but handled as a fallback instead
  generatePublicRoutes(){return[];}// In development dynamic routes cannot be known ahead of time
  getDynamicRoutes(){return[];}_filterAmpDevelopmentScript(html,event){if(event.code!=='DISALLOWED_SCRIPT_TAG'){return true;}const snippetChunks=html.split('\n');let snippet;if(!(snippet=html.split('\n')[event.line-1])||!(snippet=snippet.substring(event.col))){return true;}snippet=snippet+snippetChunks.slice(event.line).join('\n');snippet=snippet.substring(0,snippet.indexOf('</script>'));return!snippet.includes('data-amp-development-mode-only');}async ensureApiPage(pathname){return this.hotReloader.ensurePage(pathname);}async renderToHTML(req,res,pathname,query,options={}){const compilationErr=await this.getCompilationError(pathname);if(compilationErr){res.statusCode=500;return this.renderErrorToHTML(compilationErr,req,res,pathname,query);}// In dev mode we use on demand entries to compile the page before rendering
  try{await this.hotReloader.ensurePage(pathname).catch(async err=>{if(err.code!=='ENOENT'){throw err;}for(const dynamicRoute of this.dynamicRoutes||[]){const params=dynamicRoute.match(pathname);if(!params){continue;}return this.hotReloader.ensurePage(dynamicRoute.page);}throw err;});}catch(err){if(err.code==='ENOENT'){if(this.nextConfig.experimental.pages404){try{await this.hotReloader.ensurePage('/404');}catch(err){if(err.code!=='ENOENT'){throw err;}}}res.statusCode=404;return this.renderErrorToHTML(null,req,res,pathname,query);}if(!this.quiet)console.error(err);}const html=await super.renderToHTML(req,res,pathname,query,options);return html;}async renderErrorToHTML(err,req,res,pathname,query){await this.hotReloader.ensurePage('/_error');const compilationErr=await this.getCompilationError(pathname);if(compilationErr){res.statusCode=500;return super.renderErrorToHTML(compilationErr,req,res,pathname,query);}if(!err&&res.statusCode===500){err=new Error('An undefined error was thrown sometime during render... '+'See https://err.sh/zeit/next.js/threw-undefined');}try{const out=await super.renderErrorToHTML(err,req,res,pathname,query);return out;}catch(err2){if(!this.quiet)Log.error(err2);res.statusCode=500;return super.renderErrorToHTML(err2,req,res,pathname,query);}}sendHTML(req,res,html){// In dev, we should not cache pages for any reason.
  res.setHeader('Cache-Control','no-store, must-revalidate');return super.sendHTML(req,res,html);}setImmutableAssetCacheControl(res){res.setHeader('Cache-Control','no-store, must-revalidate');}servePublic(req,res,path){const p=(0,_path.join)(this.publicDir,encodeURIComponent(path));// we need to re-encode it since send decodes it
  return this.serveStatic(req,res,p);}async hasPublicFile(path){try{const info=await fsStat((0,_path.join)(this.publicDir,path));return info.isFile();}catch(_){return false;}}async getCompilationError(page){const errors=await this.hotReloader.getCompilationErrors(page);if(errors.length===0)return;// Return the very first error we found.
  return errors[0];}}exports.default=DevServer;