@metricinsights/pp-dev
Version:
Portal Page dev build tool
3 lines (2 loc) ⢠34.5 kB
JavaScript
;const e=require("path"),o=require("fs"),t=require("node:perf_hooks"),n=require("chokidar"),i=require("cac"),r=require("vite"),s=require("./index-DJdZe-Ks.js"),a=require("./plugin-xN0M6WT7.js"),l=require("url"),c=require("dir-compare"),d=require("diff-match-patch"),p=require("isbinaryfile"),f=require("os"),h=require("crypto"),g=require("extract-zip"),u=require("svgtofont");function m(e){const o=Object.create(null);if(e)for(const t in e)if("default"!==t){const n=Object.getOwnPropertyDescriptor(e,t);Object.defineProperty(o,t,n.get?n:{enumerable:!0,get:()=>e[t]})}return o.default=e,Object.freeze(o)}require("ejs"),require("http-proxy-middleware"),require("picocolors"),require("axios"),require("jsdom"),require("https"),require("memory-cache"),require("process"),require("child_process"),require("console"),require("zlib"),require("express");const b=m(e),w=m(o),v=m(c),y=m(f),x=m(h);function P(e){return null!=e&&!1!==e}const T=[{key:"r",description:"restart the server",async action(e){await e.restart()}},{key:"u",description:"show server url",action(e){e.config.logger.info(""),e.printUrls()}},{key:"o",description:"open in browser",action(e){e.openBrowser()}},{key:"c",description:"clear console",action(e){e.config.logger.clearScreen("error")}},{key:"q",description:"quit",async action(e){await e.close().finally((()=>process.exit()))}},{key:"C",description:"clear proxy cache",action(e){e.cache&&(e.cache.clear(),e.config.logger.info("Proxy cache cleared"))}}];const L=/(.+)(-[a-f0-9]{6,20})(\.[a-z0-9]+)$/i;class ${oldAssetsPath;newAssetsPath;destinationPath;changelogFilename;changelogTemplate='<!DOCTYPE html>\n <html lang="en">\n <head>\n <meta charset="UTF-8" />\n <title>Changelog Diff</title>\n <style>\n tr,\n td {\n padding: 0;\n }\n .diff-file {\n margin-top: 20px;\n border: 1px solid #e1e4e8;\n border-radius: 6px;\n }\n .diff-file-title {\n padding: 10px 20px;\n background-color: #f6f8fa;\n border-bottom: 1px solid #e1e4e8;\n border-radius: 6px 6px 0 0;\n font-weight: bold;\n }\n .diff-file-title .renamed {\n font-weight: normal;\n }\n .diff-file-title .renamed .from {\n color: #cb2431;\n }\n .diff-file-title .renamed .to {\n color: #22863a;\n }\n .diff-file-title .added {\n color: #22863a;\n }\n .diff-file-title .deleted {\n color: #cb2431;\n }\n .diff-file-content {\n }\n .diff-table {\n tab-size: 8;\n width: 100%;\n border-collapse: separate;\n border-spacing: 0;\n }\n .blob-num {\n position: relative;\n color: #1f2328;\n width: 1%;\n min-width: 50px;\n padding: 0 10px;\n font-family: ui-monospace, SFMono-Regular, SF Mono, Menlo, Consolas, Liberation Mono, monospace;\n font-size: 12px;\n line-height: 20px;\n text-align: right;\n white-space: nowrap;\n vertical-align: top;\n cursor: pointer;\n -webkit-user-select: none;\n user-select: none;\n }\n .blob-num.addition {\n background-color: #ccffd8;\n border-color: #1f883e;\n }\n .blob-num.deletion {\n background-color: #ffd7d5;\n border-color: #cf222e;\n }\n .blob-num::before {\n content: attr(data-line-number);\n }\n .blob-code {\n position: relative;\n padding: 0 10px 0 22px;\n vertical-align: top;\n color: #1f2329;\n }\n .blob-code.code-addition {\n background-color: #e6ffec;\n }\n .blob-code.code-deletion {\n background-color: #ffebe9;\n }\n .blob-code.skip,\n .blob-code.message {\n text-align: center;\n }\n .blob-code.skip .blob-code-inner,\n .blob-code.message .blob-code-inner {\n font-weight: bold;\n color: #6a737d;\n padding: 10px 0;\n }\n .blob-code-inner {\n display: table-cell;\n overflow: visible;\n font-family: ui-monospace, SFMono-Regular, SF Mono, Menlo, Consolas, Liberation Mono, monospace;\n font-size: 12px;\n word-wrap: anywhere;\n white-space: pre-wrap;\n }\n .blob-code-inner::before {\n content: attr(data-code-prefix);\n position: absolute;\n top: 1px;\n left: 8px;\n padding-right: 8px;\n }\n </style>\n </head>\n <body>\n <h1>Changelog Diff</h1>\n\n %FILES%\n </body>\n </html>';diffFileTemplateHandler;diffLineTemplateHandler;contextLines=3;logger;constructor(e){const{oldAssetsPath:o,newAssetsPath:t,destinationPath:n,changelogTemplate:i,diffFileTemplateHandler:r,diffLineTemplateHandler:s,changelogFilename:l,contextLines:c}=e;if(this.logger=a.createLogger(),!o||!t||!n)throw new Error("Previous assets path, current assets path and destination path are required");if(o===t)throw new Error("Previous and current assets paths must be different");if(!this.isExists(o))throw new Error(`Previous assets path ${o} does not exist`);if(!this.isExists(t))throw new Error(`Current assets path ${t} does not exist`);if(this.isZipFile(o)){const e=b.resolve(y.tmpdir(),x.createHash("md5").update(o).digest("hex"));this.oldAssetsPath=this.unzipFile(o,e).then((()=>this.normalizeAssetFolderPath(e))).then((e=>{if(this.isEmptyFolder(e))throw new Error(`Previous assets path ${e} is empty`);return e}))}else{if(!this.isFolder(o))throw new Error(`Invalid previous assets path ${o}. It must be a folder or a zip file`);{const e=this.normalizeAssetFolderPath(o);if(this.isEmptyFolder(e))throw new Error(`Previous assets path ${e} is empty`);this.oldAssetsPath=Promise.resolve(e)}}if(this.isZipFile(t)){const e=b.resolve(y.tmpdir(),x.createHash("md5").update(t).digest("hex"));this.newAssetsPath=this.unzipFile(t,e).then((()=>this.normalizeAssetFolderPath(e))).then((e=>{if(this.isEmptyFolder(e))throw new Error(`Current assets path ${e} is empty`);return e}))}else{if(!this.isFolder(t))throw new Error(`Invalid current assets path ${t}. It must be a folder or a zip file`);{const e=this.normalizeAssetFolderPath(t);if(this.isEmptyFolder(e))throw new Error(`Current assets path ${t} is empty`);this.newAssetsPath=Promise.resolve(e)}}this.destinationPath=n,this.mkdirpSync(this.destinationPath),this.changelogFilename=l||"CHANGELOG.html",i&&(this.templateIsValid(i)?this.changelogTemplate=i:this.logger.warn(a.colors.yellow("Invalid changelog template, using default"))),"function"==typeof r&&(this.diffFileTemplateHandler=r),"function"==typeof s&&(this.diffLineTemplateHandler=s),c&&(this.contextLines=c)}templateIsValid(e){return e.includes("%FILES%")}isExists(e){return w.existsSync(e)}isZipFile(e){return e.endsWith(".zip")}isFolder(e){return w.lstatSync(e).isDirectory()}isEmptyFolder(e){return 0===w.readdirSync(e,{withFileTypes:!0}).length}mkdirpSync(e){w.existsSync(e)||w.mkdirSync(e,{recursive:!0})}async unzipFile(e,o){return w.rmSync(o,{force:!0,recursive:!0}),g(e,{dir:o})}normalizeAssetFolderPath(e){const o=w.readdirSync(e);return 1===o.length&&w.lstatSync(b.join(e,o[0])).isDirectory()?this.normalizeAssetFolderPath(b.join(e,o[0])):e}pathToPosix(e){return e.replace(/\\/g,"/")}diffTableTemplate(e){return`<table class="diff-table">\n <tbody>\n ${e}\n </tbody>\n </table>`}getDiffTableHTML(e){const o=e.filter(((e,o,t)=>0!==e.lineType||(o>=0&&o<this.contextLines||o>t.length-(this.contextLines+1)&&o<=t.length-1||t.slice(o-this.contextLines,o+this.contextLines+1).some((e=>0!==e.lineType))))).map(((e,o,t)=>{if(o>0){const n=t[o-1];if(e.lineNumber-n.lineNumber>1)return[{lineNumber:-1,lineContent:"",lineType:0},e]}return[e]})).flat().map((e=>this.diffLineHTML(e))).join("");return this.diffTableTemplate(o)}diffLineMessageTemplate(e){return`<tr>\n <td class="blob-num"></td>\n <td class="blob-num"></td>\n <td class="blob-code message">\n <span class="blob-code-inner">${e}</span>\n </td>\n </tr>`}diffLineSkipTemplate(){return'<tr>\n <td class="blob-num"></td>\n <td class="blob-num"></td>\n <td class="blob-code skip">\n <span class="blob-code-inner">Skip</span>\n </td>\n </tr>'}diffLineTemplate(e){const{lineNumber:o,lineContent:t,lineType:n}=e,i=1===n?"addition":-1===n?"deletion":"";return`<tr>\n <td\n class="blob-num ${i}${"addition"===i?" empty":""}"\n ${"addition"!==i?` data-line-number="${o}"`:""}\n ></td>\n <td\n class="blob-num ${i}${"deletion"===i?" empty":""}"\n ${"deletion"!==i?` data-line-number="${o}"`:""}\n ></td>\n <td class="blob-code ${1===n?"code-addition":-1===n?"code-deletion":""}">\n <span class="blob-code-inner" data-code-prefix="${1===n?"+":-1===n?"-":" "}">${r=t??"",r.replace(/[\u00A0-\u9999<>&]/g,(e=>"&#"+e.charCodeAt(0)+";"))}</span>\n </td>\n </tr>`;var r}diffLineHTML(e){if(this.diffLineTemplateHandler)return this.diffLineTemplateHandler(e);const{lineNumber:o}=e;return-1===o?this.diffLineSkipTemplate():this.diffLineTemplate(e)}diffFileTemplate(e,o){return this.diffFileTemplateHandler?this.diffFileTemplateHandler(e,o):`<div class="diff-file">\n <div class="diff-file-title">${e}</div>\n <div class="diff-file-content">${o}</div>\n </div>`}async generateAssetFoldersDiff(){this.logger.info(a.colors.blue(`Comparing asset folders ${await this.oldAssetsPath} and ${await this.newAssetsPath}`));const e=await v.compare(await this.oldAssetsPath,await this.newAssetsPath,{compareContent:!0,skipSymlinks:!0,compareSize:!0,compareDate:!1,compareNameHandler:(e,o)=>(L.test(e)&&(e=e.replace(L,"$1$3")),L.test(o)&&(o=o.replace(L,"$1$3")),0===e.localeCompare(o)?0:e.localeCompare(o)>0?1:-1)});return e.diffSet?.filter((e=>"equal"!==e.state||e.name1!==e.name2))||[]}async generateAssetFilesDiff(e,o){const t=new d,n=t.diff_linesToChars_(e,o),i=t.diff_main(n.chars1,n.chars2,!1);t.diff_charsToLines_(i,n.lineArray);let r=0;return i.map((e=>{const[o,t]=e,n=t.endsWith("\n")?t.split("\n").length-1:t.split("\n").length,i=t.split("\n").map(((e,t)=>({lineContent:e,lineNumber:r+t+1,lineType:o}))).slice(0,n);return-1!==o&&(r+=n),i})).flat()}async generateFilesDiff(e){if("equal"===e.state){const o=this.pathToPosix(b.join(".",e.relativePath,e.name1??"")),t=this.pathToPosix(b.join(".",e.relativePath,e.name2??""));return this.diffFileTemplate(`<span class="renamed"\n >Renamed <span class="from">${o}</span> -> <span class="to">${t}</span></span\n >`,this.diffTableTemplate(this.diffLineMessageTemplate("No changes")))}const o=e.path1&&e.name1?b.join(e.path1,e.name1):null,t=e.path2&&e.name2?b.join(e.path2,e.name2):null,n=this.pathToPosix(b.join(".",e.relativePath,(e.name1||e.name2)??""));if("left"===e.state&&o)return this.diffFileTemplate(`<span class="removed">Removed ${n}</span>`,this.diffTableTemplate(this.diffLineMessageTemplate("File removed")));if("right"===e.state&&t)return this.diffFileTemplate(`<span class="added">Added ${n}</span>`,this.diffTableTemplate(this.diffLineMessageTemplate("File added")));if("distinct"===e.state&&o&&t){const i=this.pathToPosix(b.join(".",e.relativePath,e.name1??"")),r=this.pathToPosix(b.join(".",e.relativePath,e.name2??"")),s=e.name1!==e.name2?`<span class="renamed"\n >Renamed <span class="from">${i}</span> -> <span class="to">${r}</span></span\n >`:n;return this.diffFileTemplate(s,await p.isBinaryFile(o)||await p.isBinaryFile(t)?this.diffTableTemplate(this.diffLineMessageTemplate("Binary file")):this.getDiffTableHTML(await this.generateAssetFilesDiff(w.readFileSync(o,"utf-8"),w.readFileSync(t,"utf-8"))))}return""}async generateChangelog(){this.logger.info(a.colors.green("Generating changelog"));const e=await this.generateAssetFoldersDiff(),o=(await Promise.all(e.map((e=>this.generateFilesDiff(e))))).join("");this.logger.info(a.colors.green("Writing changelog file"));const t=this.changelogTemplate.split("%FILES%");t.splice(1,0,o);const n=t.join("");w.writeFileSync(b.join(this.destinationPath,this.changelogFilename),n),this.logger.info(a.colors.green(`Changelog file written to ${b.join(this.destinationPath,this.changelogFilename)}`))}}class S{sourceDir;outputDir;fontName;constructor(e){this.sourceDir=e.sourceDir,this.outputDir=e.outputDir,this.fontName=e.fontName}async generate(){await u({src:this.sourceDir,dist:this.outputDir,fontName:this.fontName,css:!0,typescript:!0,startUnicode:59905,svgicons2svgfont:{fontHeight:1024}})}}const F=i.cac("pp-dev");function C(e,o,t){const i=[...s.PP_DEV_CONFIG_NAMES,...s.PP_WATCH_CONFIG_NAMES,"package.json","next.config.js","next.config.mjs","next.config.ts","vite.config.js","vite.config.mjs","vite.config.ts",".env",".env.local",".env.development",".env.development.local"].map((o=>b.join(e,o))),r=n.watch(i,{ignored:/(^|[\/\\])\../,persistent:!0,ignoreInitial:!0,followSymlinks:!1});let l=null;return r.on("change",(n=>{t(a.colors.blue(`š§ Config file changed: ${b.relative(e,n)}`)),l&&clearTimeout(l),l=setTimeout((async()=>{try{t(a.colors.yellow("š Restarting dev server due to config change...")),await o()}catch(e){t(a.colors.red(`ā Failed to restart dev server: ${e}`))}}),500)})),r.on("error",(e=>{t(a.colors.red(`ā Config watcher error: ${e}`))})),{watcher:r,restartCallback:o,logger:t}}function j(e){e.watcher&&e.watcher.close()}let E=global.__pp_dev_profile_session,A=0;const D=e=>{if(E)return new Promise(((o,t)=>{E.post("Profiler.stop",((n,{profile:i})=>{if(n)t(n);else{const t=b.resolve(`./pp-dev-profile-${A++}.cpuprofile`);w.writeFileSync(t,JSON.stringify(i)),e(a.colors.yellow(`CPU profile written to ${a.colors.white(a.colors.dim(t))}`)),E=void 0,o()}}))}))},I=e=>{for(const[o,t]of Object.entries(e))Array.isArray(t)&&(e[o]=t[t.length-1])};function N(e){const o={...e};return delete o["--"],delete o.c,delete o.config,delete o.base,delete o.l,delete o.logLevel,delete o.clearScreen,delete o.d,delete o.debug,delete o.f,delete o.filter,delete o.m,delete o.mode,o}F.option("-c, --config <file>","[string] use specified config file").option("--base <path>","[string] public base path (default: /)").option("-l, --logLevel <level>","[string] info | warn | error | silent").option("--clearScreen","[boolean] allow/disable clear screen when logging").option("-d, --debug [feat]","[string | boolean] show debug logs").option("-f, --filter <filter>","[string] filter debug logs").option("-m, --mode <mode>","[string] set env mode"),F.command("[root]","start dev server").alias("serve").alias("dev").option("--host [host]","[string] specify hostname").option("--port <port>","[number] specify port").option("--https","[boolean] use TLS + HTTP/2").option("--open [path]","[boolean | string] open browser on startup").option("--cors","[boolean] enable CORS").option("--strictPort","[boolean] exit if specified port is already in use").option("--force","[boolean] force the optimizer to ignore the cache and re-bundle").action((async(e,o)=>{I(o);let n=null,i=null,l=!1;const c=e?b.resolve(process.cwd(),e):process.cwd(),d=a.createLogger(o.logLevel),p=async()=>{if(!l){l=!0;try{n&&(d.info(a.colors.yellow("š Stopping existing dev server...")),await n.close(),n=null);const{clearConfigCache:f}=await Promise.resolve().then((()=>require("./index-DJdZe-Ks.js"))).then((e=>e.config));f();const{createServer:h}=await import("vite"),g=await r.loadConfigFromFile({mode:o.mode||"development",command:"serve"},o.config,e,o.logLevel);let u=await s.getViteConfig();const m=r.loadEnv(o.mode||"development",e??process.cwd(),"");if(m&&Object.keys(m).forEach((e=>{e.startsWith("MI_")&&(process.env[e]=m[e])})),g){const{plugins:e,...o}=g.config;u=r.mergeConfig(u,o)}if(n=await h(r.mergeConfig(u,{root:e,base:o.base,mode:o.mode,configFile:o.config,logLevel:o.logLevel,clearScreen:o.clearScreen,optimizeDeps:{force:o.force},server:N(o),customLogger:d},!0)),!n.config.base||"/"===n.config.base)throw new Error('base cannot be equal to "/" or empty string');if(!n.httpServer)throw new Error("HTTP server not available");await n.listen();const b=global.__pp_dev_start_time??!1,w=b?a.colors.dim(`ready in ${a.colors.reset(a.colors.bold(Math.ceil(t.performance.now()-b)))} ms`):"";d.info(`\n ${a.colors.green(`${a.colors.bold("PP-DEV")} v${s.VERSION}`)} ${w}\n`),n.printUrls(),function(e,o){if(!e.httpServer||!process.stdin.isTTY||process.env.CI)return;e._shortcutsOptions=o;const t=a.createLogger();o.print&&t.info(a.colors.dim(a.colors.green(" ā"))+a.colors.dim(" press ")+a.colors.bold("h")+a.colors.dim(" to show help"));const n=(o.customShortcuts??[]).filter(P).concat(T);let i=!1;const r=async o=>{if(""===o||""===o)return void await e.close().finally((()=>process.exit(1)));if(i)return;"h"===o&&t.info(["",a.colors.bold(" Shortcuts"),...n.map((e=>a.colors.dim(" press ")+a.colors.bold(e.key)+a.colors.dim(` to ${e.description}`)))].join("\n"));const r=n.find((e=>e.key===o));r&&(i=!0,await r.action(e),i=!1)};process.stdin.setRawMode(!0),process.stdin.on("data",r).setEncoding("utf8").resume(),e.httpServer.on("close",(()=>{process.stdin.off("data",r).pause()}))}(n,{print:!0,customShortcuts:[...E?[{key:"p",description:"start/stop the profiler",async action(e){if(E)await D(d.info);else{const e=await import("node:inspector").then((e=>e.default));await new Promise((o=>{E=new e.Session,E.connect(),E.post("Profiler.enable",(()=>{E?.post("Profiler.start",(()=>{d.info("Profiler started"),o()}))}))}))}}}]:[],{key:"l",description:"proxy re-login",action(e){e.ws.send({type:"custom",event:"redirect",data:{url:`/auth/index/logout?proxyRedirect=${encodeURIComponent("/")}`}})}}]}),i||(i=C(c,p,d.info),d.info(a.colors.blue("š§ Config file watcher started"))),l=!1}catch(e){l=!1,d.error(a.colors.red(`error when starting dev server:\n${e.stack}`),{error:e}),D(d.info),process.exit(1)}}},f=async e=>{d.info(a.colors.yellow(`\nš Received ${e}, shutting down gracefully...`));try{i&&(j(i),i=null),n&&(await n.close(),n=null),D(d.info),d.info(a.colors.green("ā
Graceful shutdown completed")),process.exit(0)}catch(e){d.error(a.colors.red(`ā Error during graceful shutdown: ${e}`)),process.exit(1)}};process.on("SIGINT",(()=>f("SIGINT"))),process.on("SIGTERM",(()=>f("SIGTERM"))),process.on("uncaughtException",(e=>{d.error(a.colors.red(`ā Uncaught Exception: ${e}`)),f("uncaughtException")})),process.on("unhandledRejection",((e,o)=>{d.error(a.colors.red(`ā Unhandled Rejection at: ${o}, reason: ${e}`)),f("unhandledRejection")})),await p()})),F.command("next [root]","start Next.js development server with pp-dev integration").alias("next-serve").alias("next-dev").option("--host [host]","[string] specify hostname").option("--port <port>","[number] specify port",{default:3e3}).option("--https","[boolean] use TLS + HTTP/2").option("--open [path]","[boolean | string] open browser on startup").option("--cors","[boolean] enable CORS").option("--strictPort","[boolean] exit if specified port is already in use").option("--force","[boolean] force the optimizer to ignore the cache and re-bundle").action((async(e,o)=>{I(o);let t=null,n=null,i=null,c=!1;e?b.resolve(process.cwd(),e):process.cwd();const d=a.createLogger(),p=async()=>{if(!c){c=!0;try{n&&(d.info(a.colors.yellow("š Stopping existing Next.js server...")),await new Promise((e=>{n.close((()=>{n=null,e()}))}))),t&&"function"==typeof t.close&&(await t.close(),t=null);const{clearConfigCache:f}=await Promise.resolve().then((()=>require("./index-DJdZe-Ks.js"))).then((e=>e.config));if(f(),!s.isNextAvailable())throw new Error("Next.js is required but not available. Please install Next.js as a dependency:\nnpm install next@^13\n\nThis package requires Next.js >=13 <16 as a peer dependency.");const{next:h}=await s.safeNextImport(),{join:g,basename:u}=await import("path"),{createServer:m}=await import("http"),{default:b}=(await import("next/dist/server/config.js")).default,w=N(o),v=r.loadEnv(o.mode||"development",e??process.cwd(),"");v&&Object.keys(v).forEach((e=>{e.startsWith("MI_")&&(process.env[e]=v[e])}));const y=e?g(process.cwd(),e):process.cwd();d.info(y);const x=await b("development",y);let P=x?.experimental?.ppDev||x?.ppDev||{};if(0===Object.keys(P).length)try{const{getConfig:e}=await Promise.resolve().then((()=>require("./index-DJdZe-Ks.js"))).then((e=>e.config)),o=await e();Object.keys(o).length>0?(P=o,d.info(a.colors.blue("š§ Loaded pp-dev config from standalone config file"))):d.info(a.colors.yellow("ā ļø No pp-dev config found in Next.js config or standalone file, using defaults"))}catch(e){d.info(a.colors.yellow("ā ļø Failed to load standalone pp-dev config, using defaults")),console.debug("Error loading standalone config:",e)}else d.info(a.colors.blue("š§ Loaded pp-dev config from Next.js config"));const{backendBaseURL:T=process.env.MI_BACKEND_URL||"http://localhost:8080",portalPageId:L=parseInt(process.env.MI_PORTAL_PAGE_ID||"1"),templateLess:$=!0,v7Features:S=!0,disableSSLValidation:F=!1,enableProxyCache:E=!0,proxyCacheTTL:A=6e5,personalAccessToken:D=process.env.MI_ACCESS_TOKEN,distZip:I=!1,syncBackupsDir:k="./backups",miHudLess:_=!1}=P;let q=P.templateName;if(!q)try{const{getPkg:e}=await Promise.resolve().then((()=>require("./index-DJdZe-Ks.js"))).then((e=>e.config));q=e().name}catch(e){q=u(y)}let R=$?"/p":"/pl";if(R+=`/${q}`,t=h({dev:!0,hostname:w.host||"localhost",port:w.port,dir:y,conf:{...x,basePath:R,assetPrefix:R}}),await t.prepare(),R.endsWith("/")||(R+="/"),"/"===R)throw new Error('basePath cannot be equal to "/" or equal to empty string');R.substring(0,R.lastIndexOf("/"));d.info(a.colors.green("ā
Next.js app prepared successfully")),d.info(a.colors.blue(`š§ pp-dev plugin configured for template: ${q}`)),d.info(a.colors.blue(`š§ Base path configured: ${R}`)),T&&(d.info(a.colors.blue(`š Backend URL: ${T}`)),d.info(a.colors.blue(`š Portal Page ID: ${L}`)));const M=t.getRequestHandler(),z="number"==typeof w.port?w.port:3e3,G="string"==typeof w.host?w.host||"0.0.0.0":"localhost",H=new Set;n=m((async(e,o)=>{try{const t=e.url||"/",n=t.split("?")[0];let i=l.parse(t,!0);if(U.length>0){if(n.startsWith("/_next/")||"/favicon.ico"===n||n.startsWith("/__nextjs_")||n.startsWith("/api/")){if(W.length>0){let c=0;const d=()=>{if(c>=W.length)return void r();const t=W[c];c++,t(e,o,d)};return void d()}return void r()}let s=0;const a=()=>{if(s>=U.length)return void r();const t=U[s];s++,t(e,o,a)};return void a()}async function r(){if(n.startsWith(R)){const o=n.substring(R.length);e.url=o||"/",i=l.parse(o,!0)}else if(n===R.replace(/\/$/,""))e.url="/",i=l.parse("/",!0);else if(n.startsWith("/_next/")||"/favicon.ico"===n||n.startsWith("/__nextjs_"));else if("/"===n)return o.writeHead(302,{Location:R}),void o.end();await M(e,o,i)}r()}catch(p){console.error("[DEBUG] Error:",p),o.statusCode=500,o.end("Internal Server Error")}}));let O=null,U=[],W=[];if(T){const e=new URL(T).host,o={headers:{host:e,referer:T,origin:T.replace(/^(https?:\/\/)([^/]+)(\/.*)?$/i,"$1$2")},portalPageId:L,appId:L,templateLess:$,disableSSLValidation:F,v7Features:S,personalAccessToken:D??process.env.MI_ACCESS_TOKEN};O=new a.MiAPI(T,o);const t=a.initPPRedirect(R,q),n=(e,o,n)=>{t(e,o,n)};if(W.push(n),U.push(n),E){let e=+A;(!e||Number.isNaN(e)||e<0)&&(e=6e5);const o={devServer:{middlewares:{use:e=>e},config:{logger:console}},ttl:e},t=a.initProxyCache(o),n=(e,o,n)=>{t(e,o,n)};U.push(n),d.info(a.colors.blue(`š§ Proxy cache middleware added with TTL: ${e}ms`))}const i=R.endsWith("/")?R.substring(0,R.length-1):R,r={middlewares:{use:e=>e},config:{logger:console}},s=a.initProxy({devServer:r,baseURL:T,proxyIgnore:["/@vite","/@metricinsights","/@",i,"/_next","/favicon.ico","/__nextjs_","/api"],disableSSLValidation:F,miAPI:O}),l=(e,o,t)=>{s(e,o,t)};U.push(l);const c=new RegExp(`^((${R})|/)$`),p=a.initLoadPPData(c,O,{base:R,v7Features:S}),f=(e,o,t)=>{p(e,o,t)};U.push(f);const h=a.internalServer,g=(e,o,t)=>{if(e.url?.startsWith("/@api/")){h(e,o,(()=>{}))}else t()};W.push(g),U.push(g);const u=a.initRewriteResponse((e=>e.split("?")[0].endsWith("index.html")),((o,t)=>Buffer.from(a.urlReplacer(e,t.headers.host??"",O.buildPage(o,_))))),m=(e,o,t)=>{u(e,o,t)};U.push(m),d.info(a.colors.blue(`š§ ${U.length} pp-dev middlewares initialized`)),d.info(a.colors.blue(`š§ ${W.length} essential middlewares for internal routes`)),d.info(a.colors.blue(`š§ MiAPI initialized for backend: ${T}`)),d.info(a.colors.blue(`š§ Portal Page ID: ${L}`))}n.listen(z,G,(()=>{d.info(a.colors.green(`ā
pp-dev Next.js server running at http://${G}:${z}`)),d.info(a.colors.blue(`š± Next.js app accessible at http://${G}:${z}${R}`)),d.info(a.colors.blue("š§ Base path handling active")),i||(i=C(y,p,d.info),d.info(a.colors.blue("š§ Config file watcher started"))),n.on("connection",(e=>{H.add(e),e.on("close",(()=>H.delete(e)))}));const e=async e=>{d.info(a.colors.yellow(`\nš Received ${e}, shutting down gracefully...`));const o=setTimeout((()=>{d.info(a.colors.yellow("ā° Shutdown timeout reached, forcing exit")),process.exit(0)}),5e3);try{i&&(j(i),i=null);for(const e of Array.from(H))e.destroy();H.clear(),await new Promise((e=>{n.close((()=>{d.info(a.colors.yellow("š HTTP server closed")),e()}))})),t&&"function"==typeof t.close&&(await t.close(),d.info(a.colors.yellow("š Next.js app closed"))),clearTimeout(o),d.info(a.colors.green("ā
Graceful shutdown completed")),process.exit(0)}catch(e){clearTimeout(o),d.error(a.colors.red(`ā Error during graceful shutdown: ${e}`)),process.exit(1)}};let o=process;if("function"!=typeof process.on){const e=globalThis.process||global.process;e&&"function"==typeof e.on&&(o=e,d.info(a.colors.green("ā
Using global process object for event handlers")))}if("function"==typeof o.on)try{o.on("SIGINT",(()=>e("SIGINT"))),o.on("SIGTERM",(()=>e("SIGTERM"))),o.on("uncaughtException",(o=>{d.error(a.colors.red(`ā Uncaught Exception: ${o}`)),e("uncaughtException")})),o.on("unhandledRejection",((o,t)=>{d.error(a.colors.red(`ā Unhandled Rejection at: ${t}, reason: ${o}`)),e("unhandledRejection")})),d.info(a.colors.green("ā
Process event handlers registered successfully"))}catch(e){d.warn(a.colors.yellow(`ā ļø Failed to register process event handlers: ${e}`))}else d.warn(a.colors.yellow("ā ļø process.on is not available, graceful shutdown handlers will not be registered")),d.info(a.colors.blue("š” This might be due to bundling or environment constraints"))})),c=!1}catch(e){c=!1,d.error(a.colors.red(`ā Failed to start Next.js server: ${e}`)),e instanceof Error&&e.message.includes("Next.js is required")&&(d.error(a.colors.red("ā Next.js Peer Dependency Error:")),d.error(a.colors.red(e.message)),d.error(a.colors.yellow("\nš” To fix this issue:")),d.error(a.colors.blue(" 1. Install Next.js in your project:")),d.error(a.colors.white(" npm install next@^15")),d.error(a.colors.blue(" 2. Or use yarn:")),d.error(a.colors.white(" yarn add next@^15")),d.error(a.colors.blue(" 3. Or use pnpm:")),d.error(a.colors.white(" pnpm add next@^15")),d.error(a.colors.yellow("\nš For more information, see:")),d.error(a.colors.blue(" https://nextjs.org/docs/getting-started"))),process.exit(1)}}},f=async e=>{d.info(a.colors.yellow(`\nš Received ${e}, shutting down gracefully...`));try{i&&(j(i),i=null),n&&await new Promise((e=>{n.close((()=>{n=null,e()}))})),t&&"function"==typeof t.close&&(await t.close(),t=null),d.info(a.colors.green("ā
Graceful shutdown completed")),process.exit(0)}catch(e){d.error(a.colors.red(`ā Error during graceful shutdown: ${e}`)),process.exit(1)}};process.on("SIGINT",(()=>f("SIGINT"))),process.on("SIGTERM",(()=>f("SIGTERM"))),process.on("uncaughtException",(e=>{d.error(a.colors.red(`ā Uncaught Exception: ${e}`)),f("uncaughtException")})),process.on("unhandledRejection",((e,o)=>{d.error(a.colors.red(`ā Unhandled Rejection at: ${o}, reason: ${e}`)),f("unhandledRejection")})),await p()})),F.command("build [root]","build for production").option("--target <target>","[string] transpile target (default: 'modules')").option("--outDir <dir>","[string] output directory (default: dist)").option("--assetsDir <dir>","[string] directory under outDir to place assets in (default: assets)").option("--assetsInlineLimit <number>","[number] static asset base64 inline threshold in bytes (default: 4096)").option("--ssr [entry]","[string] build specified entry for server-side rendering").option("--sourcemap [output]",'[boolean | "inline" | "hidden"] output source maps for build (default: false)').option("--minify [minifier]",'[boolean | "terser" | "esbuild"] enable/disable minification, or specify minifier to use (default: esbuild)').option("--manifest [name]","[boolean | string] emit build manifest json").option("--ssrManifest [name]","[boolean | string] emit ssr manifest json").option("--force","[boolean] force the optimizer to ignore the cache and re-bundle (experimental)").option("--emptyOutDir","[boolean] force empty outDir when it's outside of root").option("-w, --watch","[boolean] rebuilds when modules have changed on disk").option("--changelog [assetsFile]","[boolean | string] generate changelog between assetsFile and current build (default: false)").action((async(e,o)=>{I(o);const t=N(o);try{const n=await r.loadConfigFromFile({mode:o.mode||"production",command:"build"},o.config,e,o.logLevel);let i=await s.getViteConfig();if(n){const{plugins:e,...o}=n.config;i=r.mergeConfig(i,o)}const l=r.mergeConfig(i,{root:e,base:o.base,mode:o.mode,configFile:o.config,logLevel:o.logLevel,clearScreen:o.clearScreen,optimizeDeps:{force:o.force},build:t},!0);if(await r.build(l),t.changelog){const n=e||process.cwd(),i=l.build?.outDir||"dist";let r="";if("string"==typeof t.changelog)r=b.resolve(n,t.changelog);else{const e=b.resolve(n,l.ppDevConfig?.syncBackupsDir||"backups");if(!w.existsSync(e))return void a.createLogger(o.logLevel).warn(a.colors.yellow("backups directory not found, skipping changelog generation"));const t=w.readdirSync(e,{withFileTypes:!0});if(!t.length)return void a.createLogger(o.logLevel).warn(a.colors.yellow("no backups found, skipping changelog generation"));const i=t.filter((e=>e.isFile()&&e.name.endsWith(".zip"))).reduce(((o,t)=>w.statSync(b.resolve(e,o.name)).mtimeMs>w.statSync(b.resolve(e,t.name)).mtimeMs?o:t),t[0]).name;r=b.resolve(e,i)}const s=b.resolve(n,i);let c="dist-zip";l.ppDevConfig&&(!1===l.ppDevConfig.distZip?c=l.build?.outDir||"dist":"object"==typeof l.ppDevConfig.distZip&&"string"==typeof l.ppDevConfig.distZip.outDir&&(c=l.ppDevConfig.distZip.outDir));const d=new $({oldAssetsPath:r,newAssetsPath:s,destinationPath:b.resolve(n,c)});await d.generateChangelog()}}catch(e){a.createLogger(o.logLevel).error(a.colors.red(`error during build:\n${e.stack}`),{error:e}),process.exit(1)}finally{D((e=>a.createLogger(o.logLevel).info(e)))}})),F.command("changelog [oldAssetPath] [newAssetPath]","generate changelog between two assets files/folders").option("--oldAssetsPath <oldAssetsPath>","[string] path to the old assets zip file or folder").option("--newAssetsPath <newAssetsPath>","[string] path to the new assets zip file or folder").option("--destination <destination>","[string] destination folder for the changelog (default: .)").option("--filename <filename>","[string] filename for the changelog (default: CHANGELOG.html)").action((async(e,o,t)=>{I(t);const{oldAssetsPath:n=e,newAssetsPath:i=o,destination:r=".",filename:s="CHANGELOG.html",logLevel:l}=t,c=process.cwd();n&&i||(a.createLogger(l).error(a.colors.red("error during changelog generation: oldAssetPath and newAssetPath are required")),process.exit(1));const d=b.resolve(c,n),p=b.resolve(c,i),f=b.resolve(c,r),h=new $({oldAssetsPath:d,newAssetsPath:p,destinationPath:f,changelogFilename:s});await h.generateChangelog()})),F.command("generate-icon-font [source] [destination]","generate icon font from SVG files").option("--source <source>","[string] path to the source directory with SVG files").option("--destination <destination>","[string] path to the destination directory to save the generated font files").option("--font-name, -n <fontName>","[string] name of the font to generate (default: 'icon-font')").action((async(e,o,t)=>{I(t);const{source:n=e,destination:i=o,fontName:r="icon-font"}=t,s=process.cwd(),l=b.resolve(s,n),c=b.resolve(s,i),d=new S({sourceDir:l,outputDir:c,fontName:r}),p=a.createLogger(t.logLevel);p.info(`Generating icon font from SVG files in ${a.colors.dim(l)}`),await d.generate(),p.info(`Icon font generated and saved to ${a.colors.dim(c)}`)})),F.command("optimize [root]","pre-bundle dependencies").option("--force","[boolean] force the optimizer to ignore the cache and re-bundle").action((async(e,o)=>{I(o);try{const t=await r.loadConfigFromFile({mode:o.mode||"production",command:"build"},o.config,e,o.logLevel);let n=await s.getViteConfig();if(t){const{plugins:e,...o}=t.config;n=r.mergeConfig(n,o)}const i=await r.resolveConfig(r.mergeConfig(n,{root:e,base:o.base,configFile:o.config,logLevel:o.logLevel,mode:o.mode}),"serve");await r.optimizeDeps(i,o.force,!0)}catch(e){a.createLogger(o.logLevel).error(a.colors.red(`error when optimizing deps:\n${e.stack}`),{error:e}),process.exit(1)}})),F.command("preview [root]","locally preview production build").option("--host [host]","[string] specify hostname").option("--port <port>","[number] specify port").option("--strictPort","[boolean] exit if specified port is already in use").option("--https","[boolean] use TLS + HTTP/2").option("--open [path]","[boolean | string] open browser on startup").option("--outDir <dir>","[string] output directory (default: dist)").action((async(e,o)=>{I(o);try{const t=await r.loadConfigFromFile({mode:o.mode||"production",command:"build"},o.config,e,o.logLevel);let n=await s.getViteConfig();if(t){const{plugins:e,...o}=t.config;n=r.mergeConfig(n,o)}(await r.preview(r.mergeConfig(n,{root:e,base:o.base,configFile:o.config,logLevel:o.logLevel,mode:o.mode,build:{outDir:o.outDir},preview:{port:o.port,strictPort:o.strictPort,host:o.host,https:o.https,open:o.open}}))).printUrls()}catch(e){a.createLogger(o.logLevel).error(a.colors.red(`error when starting preview server:\n${e.stack}`),{error:e}),process.exit(1)}finally{D((e=>a.createLogger(o.logLevel).info(e)))}})),F.help(),F.version(s.VERSION),F.parse(),exports.stopProfiler=D;
//# sourceMappingURL=cli.js.map