@promakeai/cli 0.8.0 → 0.8.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -494,7 +494,7 @@ For (2), check out our guide on configuring puppeteer at https://pptr.dev/guides
494
494
  2. your cache path is incorrectly configured (which is: ${this.puppeteer.configuration.cacheDirectory}).
495
495
  For (2), check out our guide on configuring puppeteer at https://pptr.dev/guides/configuration.`)}}return Z}}lw();import E41 from"node:fs";var T41={force:!0,recursive:!0,maxRetries:5};async function qO(D){await E41.promises.rm(D,T41)}class ow extends jW{constructor(D){super(D,"chrome")}launch(D={}){if(this.puppeteer.configuration.logLevel==="warn"&&process.platform==="darwin"&&process.arch==="x64"){if(j41.cpus()[0]?.model.includes("Apple"))console.warn(["\x1B[1m\x1B[43m\x1B[30m","Degraded performance warning:\x1B[0m\x1B[33m","Launching Chrome on Mac Silicon (arm64) from an x64 Node installation results in","Rosetta translating the Chrome binary, even if Chrome is already arm64. This would","result in huge performance issues. To resolve this, you must run Puppeteer with","a version of Node built for arm64."].join(`
496
496
  `))}return super.launch(D)}async computeLaunchArguments(D={}){let{ignoreDefaultArgs:X=!1,args:Z=[],pipe:J=!1,debuggingPort:Y,channel:Q,executablePath:$}=D,K=[];if(!X)K.push(...this.defaultArgs(D));else if(Array.isArray(X))K.push(...this.defaultArgs(D).filter((z)=>{return!X.includes(z)}));else K.push(...Z);if(!K.some((z)=>{return z.startsWith("--remote-debugging-")}))if(J)U0(!Y,"Browser should be launched with either pipe or debugging port - not both."),K.push("--remote-debugging-pipe");else K.push(`--remote-debugging-port=${Y||0}`);let G=!1,F=K.findIndex((z)=>{return z.startsWith("--user-data-dir")});if(F<0)G=!0,K.push(`--user-data-dir=${await I41(this.getProfilePath())}`),F=K.length-1;let W=K[F].split("=",2)[1];U0(typeof W==="string","`--user-data-dir` is malformed");let V=$;if(!V)U0(Q||!this.puppeteer._isPuppeteerCore,"An `executablePath` or `channel` must be specified for `puppeteer-core`"),V=Q?this.executablePath(Q):this.resolveExecutablePath(D.headless??!0);return{executablePath:V,args:K,isTempUserDataDir:G,userDataDir:W}}async cleanUserDataDir(D,X){if(X.isTemp)try{await qO(D)}catch(Z){throw M0(Z),Z}}defaultArgs(D={}){let X=yQ0("--disable-features",D.args);if(D.args&&X.length>0)vQ0(D.args,"--disable-features");let J=["Translate","AcceptCHFrame","MediaRouter","OptimizationHints","RenderDocument",...process.env.PUPPETEER_TEST_EXPERIMENTAL_CHROME_FEATURES==="true"?[]:["ProcessPerSiteUpToMainFrameThreshold","IsolateSandboxedIframes"],...X].filter((z)=>{return z!==""}),Y=yQ0("--enable-features",D.args);if(D.args&&Y.length>0)vQ0(D.args,"--enable-features");let Q=["PdfOopif",...Y].filter((z)=>{return z!==""}),$=["--allow-pre-commit-input","--disable-background-networking","--disable-background-timer-throttling","--disable-backgrounding-occluded-windows","--disable-breakpad","--disable-client-side-phishing-detection","--disable-component-extensions-with-background-pages","--disable-crash-reporter","--disable-default-apps","--disable-dev-shm-usage","--disable-hang-monitor","--disable-infobars","--disable-ipc-flooding-protection","--disable-popup-blocking","--disable-prompt-on-repost","--disable-renderer-backgrounding","--disable-search-engine-choice-screen","--disable-sync","--enable-automation","--export-tagged-pdf","--force-color-profile=srgb","--generate-pdf-document-outline","--metrics-recording-only","--no-first-run","--password-store=basic","--use-mock-keychain",`--disable-features=${J.join(",")}`,`--enable-features=${Q.join(",")}`].filter((z)=>{return z!==""}),{devtools:K=!1,headless:G=!K,args:F=[],userDataDir:W,enableExtensions:V=!1}=D;if(W)$.push(`--user-data-dir=${C41.resolve(W)}`);if(K)$.push("--auto-open-devtools-for-tabs");if(G)$.push(G==="shell"?"--headless":"--headless=new","--hide-scrollbars","--mute-audio");if($.push(V?"--enable-unsafe-extension-debugging":"--disable-extensions"),F.every((z)=>{return z.startsWith("-")}))$.push("about:blank");return $.push(...F),$}executablePath(D,X=!0){if(D)return nY({browser:u0.CHROME,channel:dw(D)});else return this.resolveExecutablePath(void 0,X)}}function yQ0(D,X=[]){return X.filter((Z)=>{return Z.startsWith(D.endsWith("=")?D:`${D}=`)}).map((Z)=>{return Z.split(new RegExp(`${D}=\\s*`))[1]?.trim()}).filter((Z)=>{return Z})}function vQ0(D,X){let Z=new RegExp(`^${X}=.*`),J=0;while(J<D.length)if(Z.test(D[J]))D.splice(J,1);else J++;return D}rX();F1();import P41 from"node:fs";import{rename as w41,unlink as S41,mkdtemp as _41}from"node:fs/promises";import k41 from"node:os";import bQ0 from"node:path";class zO extends jW{constructor(D){super(D,"firefox")}static getPreferences(D){return{...D,"fission.webContentIsolationStrategy":0}}async computeLaunchArguments(D={}){let{ignoreDefaultArgs:X=!1,args:Z=[],executablePath:J,pipe:Y=!1,extraPrefsFirefox:Q={},debuggingPort:$=null}=D,K=[];if(!X)K.push(...this.defaultArgs(D));else if(Array.isArray(X))K.push(...this.defaultArgs(D).filter((z)=>{return!X.includes(z)}));else K.push(...Z);if(!K.some((z)=>{return z.startsWith("--remote-debugging-")})){if(Y)U0($===null,"Browser should be launched with either pipe or debugging port - not both.");K.push(`--remote-debugging-port=${$||0}`)}let G,F=!0,W=K.findIndex((z)=>{return["-profile","--profile"].includes(z)});if(W!==-1){if(G=K[W+1],!G)throw Error("Missing value for profile command line argument");F=!1}else G=await _41(this.getProfilePath()),K.push("--profile"),K.push(G);await NB(u0.FIREFOX,{path:G,preferences:zO.getPreferences(Q)});let V;if(this.puppeteer._isPuppeteerCore||J)U0(J,"An `executablePath` must be specified for `puppeteer-core`"),V=J;else V=this.executablePath(void 0);return{isTempUserDataDir:F,userDataDir:G,args:K,executablePath:V}}async cleanUserDataDir(D,X){if(X.isTemp)try{await qO(D)}catch(Z){throw M0(Z),Z}else try{let J=["prefs.js","user.js"],Y=await Promise.allSettled(J.map(async(Q)=>{let $=bQ0.join(D,Q+".puppeteer");if(P41.existsSync($)){let K=bQ0.join(D,Q);await S41(K),await w41($,K)}}));for(let Q of Y)if(Q.status==="rejected")throw Q.reason}catch(Z){M0(Z)}}executablePath(D,X=!0){return this.resolveExecutablePath(void 0,X)}defaultArgs(D={}){let{devtools:X=!1,headless:Z=!X,args:J=[],userDataDir:Y=null}=D,Q=[];switch(k41.platform()){case"darwin":Q.push("--foreground");break;case"win32":Q.push("--wait-for-browser");break}if(Y)Q.push("--profile"),Q.push(Y);if(Z)Q.push("--headless");if(X)Q.push("--devtools");if(J.every(($)=>{return $.startsWith("-")}))Q.push("about:blank");return Q.push(...J),Q}}rX();class rw extends iw{#D;#X;defaultBrowserRevision;configuration={};constructor(D){let{configuration:X,...Z}=D;super(Z);if(X)this.configuration=X;switch(this.configuration.defaultBrowser){case"firefox":this.defaultBrowserRevision=FQ.firefox;break;default:this.configuration.defaultBrowser="chrome",this.defaultBrowserRevision=FQ.chrome;break}this.connect=this.connect.bind(this),this.launch=this.launch.bind(this),this.executablePath=this.executablePath.bind(this),this.defaultArgs=this.defaultArgs.bind(this),this.trimCache=this.trimCache.bind(this)}connect(D){return super.connect(D)}launch(D={}){let{browser:X=this.defaultBrowser}=D;switch(this.#X=X,X){case"chrome":this.defaultBrowserRevision=FQ.chrome;break;case"firefox":this.defaultBrowserRevision=FQ.firefox;break;default:throw Error(`Unknown product: ${X}`)}return this.#D=this.#Z(X),this.#D.launch(D)}#Z(D){if(this.#D&&this.#D.browser===D)return this.#D;switch(D){case"chrome":return new ow(this);case"firefox":return new zO(this);default:throw Error(`Unknown product: ${D}`)}}executablePath(D){if(D===void 0)return this.#Z(this.lastLaunchedBrowser).executablePath(void 0,!1);if(typeof D==="string")return this.#Z("chrome").executablePath(D,!1);return this.#Z(D.browser??this.lastLaunchedBrowser).resolveExecutablePath(D.headless,!1)}get browserVersion(){return this.configuration?.[this.lastLaunchedBrowser]?.version??this.defaultBrowserRevision}get defaultDownloadPath(){return this.configuration.cacheDirectory}get lastLaunchedBrowser(){return this.#X??this.defaultBrowser}get defaultBrowser(){return this.configuration.defaultBrowser??"chrome"}get product(){return this.lastLaunchedBrowser}defaultArgs(D={}){return this.#Z(D.browser??this.lastLaunchedBrowser).defaultArgs(D)}async trimCache(){let D=V8();if(!D)throw Error("The current platform is not supported.");let X=this.configuration.cacheDirectory,Z=await nB({cacheDir:X}),J=[{product:"chrome",browser:u0.CHROME,currentBuildId:""},{product:"firefox",browser:u0.FIREFOX,currentBuildId:""}];for(let $ of J){let K=this.configuration?.[$.product]?.version??FQ[$.product];$.currentBuildId=await pY($.browser,D,K)}let Y=new Set(J.map(($)=>{return`${$.browser}_${$.currentBuildId}`})),Q=new Set(J.map(($)=>{return $.browser}));for(let $ of Z){if(!Q.has($.browser))continue;if(Y.has(`${$.browser}_${$.buildId}`))continue;await iB({browser:$.browser,platform:D,cacheDir:X,buildId:$.buildId})}}}s6();X6();F1();G2();Y5();var uQ0=h1(i2(),1);import{spawn as y41,spawnSync as v41}from"node:child_process";import b41 from"node:fs";import f41 from"node:os";import{dirname as g41}from"node:path";import{PassThrough as u41}from"node:stream";var x41=function(D,X,Z){var J=arguments.length>2;for(var Y=0;Y<X.length;Y++)Z=J?X[Y].call(D,Z):X[Y].call(D);return J?Z:void 0},fQ0=function(D,X,Z,J,Y,Q){function $(O){if(O!==void 0&&typeof O!=="function")throw TypeError("Function expected");return O}var K=J.kind,G=K==="getter"?"get":K==="setter"?"set":"value",F=!X&&D?J.static?D:D.prototype:null,W=X||(F?Object.getOwnPropertyDescriptor(F,J.name):{}),V,z=!1;for(var H=Z.length-1;H>=0;H--){var q={};for(var U in J)q[U]=U==="access"?{}:J[U];for(var U in J.access)q.access[U]=J.access[U];q.addInitializer=function(O){if(z)throw TypeError("Cannot add initializers after decoration has completed");Q.push($(O||null))};var B=(0,Z[H])(K==="accessor"?{get:W.get,set:W.set}:W[G],q);if(K==="accessor"){if(B===void 0)continue;if(B===null||typeof B!=="object")throw TypeError("Object expected");if(V=$(B.get))W.get=V;if(V=$(B.set))W.set=V;if(V=$(B.init))Y.unshift(V)}else if(V=$(B))if(K==="field")Y.unshift(V);else W[G]=V}if(F)Object.defineProperty(F,J.name,W);z=!0},h41=function(D,X,Z){if(typeof X==="symbol")X=X.description?"[".concat(X.description,"]"):"";return Object.defineProperty(D,"name",{configurable:!0,value:Z?"".concat(Z," ",X):X})},m41=30,gQ0=30,c41=uQ0.default("puppeteer:ffmpeg"),mQ0=(()=>{let D=u41,X=[],Z,J,Y;return class extends D{static{let $=typeof Symbol==="function"&&Symbol.metadata?Object.create(D[Symbol.metadata]??null):void 0;if(fQ0(this,J={value:h41(async function(K){let G=await new Promise((F)=>{this.#X.stdin.write(K,F)});if(G)console.log(`ffmpeg failed to write: ${G.message}.`)},"#writeFrame")},Z,{kind:"method",name:"#writeFrame",static:!1,private:!0,access:{has:(K)=>(#$ in K),get:(K)=>K.#$},metadata:$},null,X),fQ0(this,null,Y,{kind:"method",name:"stop",static:!1,private:!1,access:{has:(K)=>("stop"in K),get:(K)=>K.stop},metadata:$},null,X),$)Object.defineProperty(this,Symbol.metadata,{enumerable:!0,configurable:!0,writable:!0,value:$})}#D=x41(this,X);#X;#Z=new AbortController;#J;#Q;constructor($,K,G,{ffmpegPath:F,speed:W,scale:V,crop:z,format:H,fps:q,loop:U,delay:B,quality:O,colors:L,path:M,overwrite:A}={}){super({allowHalfOpen:!1});F??="ffmpeg",H??="webm",q??=gQ0,U||=-1,B??=-1,O??=m41,L??=256,A??=!0,this.#Q=q;let{error:E}=v41(F);if(E)throw E;let w=[`crop='min(${K},iw):min(${G},ih):0:0'`,`pad=${K}:${G}:0:0`];if(W)w.push(`setpts=${1/W}*PTS`);if(z)w.push(`crop=${z.width}:${z.height}:${z.x}:${z.y}`);if(V)w.push(`scale=iw*${V}:-1:flags=lanczos`);let T=this.#Y(H,q,U,B,O,L),j=T.indexOf("-vf");if(j!==-1)w.push(T.splice(j,2).at(-1)??"");if(M)b41.mkdirSync(g41(M),{recursive:A});this.#X=y41(F,[["-loglevel","error"],["-avioflags","direct"],["-fpsprobesize","0","-probesize","32","-analyzeduration","0","-fflags","nobuffer"],["-f","image2pipe","-vcodec","png","-i","pipe:0"],["-an"],["-threads","1"],["-framerate",`${q}`],["-b:v","0"],T,["-vf",w.join()],[A?"-y":"-n"],"pipe:1"].flat(),{stdio:["pipe","pipe","pipe"]}),this.#X.stdout.pipe(this),this.#X.stderr.on("data",(v)=>{c41(v.toString("utf8"))}),this.#D=$;let{client:C}=this.#D.mainFrame();C.once(x1.Disconnected,()=>{this.stop().catch(M0)}),this.#J=Ar(b1(C,"Page.screencastFrame").pipe(iD((v)=>{C.send("Page.screencastFrameAck",{sessionId:v.sessionId})}),O6((v)=>{return v.metadata.timestamp!==void 0}),J5((v)=>{return{buffer:Buffer.from(v.data,"base64"),timestamp:v.metadata.timestamp}}),Ir(2,1),jr(([{timestamp:v,buffer:f},{timestamp:l}])=>{return z1(Array(Math.round(q*Math.max(l-v,0))).fill(f))}),J5((v)=>{return this.#$(v),[v,performance.now()]}),Mq(OJ(this.#Z.signal,"abort"))),{defaultValue:[Buffer.from([]),performance.now()]})}#Y($,K,G,F,W,V){let z=[["-vcodec","vp9"],["-crf",`${W}`],["-deadline","realtime","-cpu-used",`${Math.min(f41.cpus().length/2,8)}`]];switch($){case"webm":return[...z,["-f","webm"]].flat();case"gif":if(K=gQ0===K?20:"source_fps",G===1/0)G=0;if(F!==-1)F/=10;return[["-vf",`fps=${K},split[s0][s1];[s0]palettegen=stats_mode=diff:max_colors=${V}[p];[s1][p]paletteuse=dither=bayer`],["-loop",`${G}`],["-final_delay",`${F}`],["-f","gif"]].flat();case"mp4":return[...z,["-movflags","hybrid_fragmented"],["-f","mp4"]].flat()}}get#$(){return J.value}async stop(){if(this.#Z.signal.aborted)return;await this.#D._stopScreencast().catch(M0),this.#Z.abort();let[$,K]=await this.#J;await Promise.all(Array(Math.max(1,Math.round(this.#Q*(performance.now()-K)/1000))).fill($).map(this.#$.bind(this))),this.#X.stdin.end(),await new Promise((G)=>{this.#X.once("close",G)})}async[(Z=[hK()],Y=[hK()],K2)](){await this.stop()}}})();V3();import l41 from"node:fs";import p41 from"node:path";K8.value={fs:l41,path:p41,ScreenRecorder:mQ0};var i41=new rw({isPuppeteerCore:!0});var sw=i41;import{execSync as n41}from"child_process";import{accessSync as o41}from"node:fs";import CW from"path";var r41=[process.env["PROGRAMFILES(X86)"]&&CW.join(process.env["PROGRAMFILES(X86)"],"Google","Chrome","Application","chrome.exe"),process.env.PROGRAMFILES&&CW.join(process.env.PROGRAMFILES,"Google","Chrome","Application","chrome.exe"),process.env.LOCALAPPDATA&&CW.join(process.env.LOCALAPPDATA,"Google","Chrome","Application","chrome.exe"),process.env["PROGRAMFILES(X86)"]&&CW.join(process.env["PROGRAMFILES(X86)"],"Microsoft","Edge","Application","msedge.exe"),process.env.PROGRAMFILES&&CW.join(process.env.PROGRAMFILES,"Microsoft","Edge","Application","msedge.exe")].filter(Boolean),s41=["/Applications/Google Chrome.app/Contents/MacOS/Google Chrome","/Applications/Microsoft Edge.app/Contents/MacOS/Microsoft Edge","/Applications/Chromium.app/Contents/MacOS/Chromium"],a41=["/usr/bin/google-chrome","/usr/bin/google-chrome-stable","/usr/bin/chromium-browser","/usr/bin/chromium","/usr/lib/chromium/chromium","/usr/lib/chromium-browser/chromium-browser","/usr/lib64/chromium-browser/chromium-browser","/snap/bin/chromium","/tmp/chromium","/opt/chromium/chrome","/opt/chrome/chrome"];function t41(D){return D.startsWith("ws://")||D.startsWith("wss://")||D.startsWith("http://")||D.startsWith("https://")}async function e41(D){if(D.startsWith("ws://")||D.startsWith("wss://"))return D;let X=D.replace(/\/+$/,"")+"/json/version",J=await(await fetch(X,{signal:AbortSignal.timeout(5000)})).json();if(!J.webSocketDebuggerUrl)throw Error("No webSocketDebuggerUrl in /json/version response");return J.webSocketDebuggerUrl}async function UO(D){let X=D||process.env.CHROME_REMOTE_ENDPOINT;if(X&&t41(X))try{let J=await e41(X);return{type:"remote",browser:await sw.connect({browserWSEndpoint:J})}}catch{return null}let Z=await D91(D);if(!Z)return null;try{let J=["--no-sandbox","--disable-setuid-sandbox","--disable-gpu","--disable-dev-shm-usage"];if(process.platform!=="win32")J.push("--single-process");let Y=process.platform!=="win32"&&process.platform!=="darwin";return{type:"chrome",browser:await sw.launch({executablePath:Z,headless:!0,pipe:Y,args:J})}}catch{return null}}async function D91(D,X=process.platform,Z){if(D&&aw(D))return D;let J=[process.env.CHROME_PATH,process.env.PUPPETEER_EXECUTABLE_PATH,process.env.CHROMIUM_PATH];for(let Q of J)if(Q&&aw(Q))return Q;let Y=Z||[];if(!Z)switch(X){case"win32":Y=r41;break;case"darwin":Y=s41;break;default:Y=a41}for(let Q of Y)if(aw(Q))return Q;if(X!=="win32"){let Q=["chromium-browser","chromium","google-chrome-stable","google-chrome","chrome"];for(let $ of Q){let K=X91($);if(K)return K}}return null}function aw(D){try{return o41(D),!0}catch{return!1}}function X91(D){try{return n41(`command -v ${D} 2>/dev/null`,{encoding:"utf-8",timeout:3000,shell:"/bin/sh"}).trim()||null}catch{return null}}async function BO(D){try{if(D.type==="remote")await D.browser.disconnect();else await D.browser.close()}catch{}}import{mkdir as Z91}from"node:fs/promises";import J91 from"path";async function tw(D,X,Z="/",J,Y){let Q=Date.now();if(!await Y91(D))return{name:"Runtime",status:"skip",severity:"error",duration:Date.now()-Q,items:[{message:`No server running on port ${D}`,suggestion:"Start dev server first: npm run dev (or use --port to specify different port)"}],summary:`Skipped (no server on port ${D})`};let K=null;try{K=await UO(J)}catch{}if(!K)return{name:"Runtime",status:"skip",severity:"info",duration:Date.now()-Q,items:[{message:"No browser available (Chrome/Chromium/Edge not found)",suggestion:"Use --chrome-path <path> or set CHROME_PATH environment variable, or install Chrome/Edge"}],summary:"Skipped (no browser)"};let G=[],F,{browser:W,type:V}=K;try{let H=await W.newPage();H.on("console",(B)=>{let O=B.type();if(O==="error"||O==="warning"){let L=B.location();G.push({type:O==="warning"?"warning":"console",message:B.text(),fileName:L?.url,lineNumber:L?.lineNumber,columnNumber:L?.columnNumber})}}),H.on("pageerror",(B)=>{G.push({type:"error",message:B.message,stack:B.stack})});let q=Z.startsWith("/")?Z:`/${Z}`;if(await H.goto(`http://localhost:${D}${q}`,{waitUntil:"networkidle2",timeout:X}),await Q91(3000),Y){await Z91(Y,{recursive:!0});let B=q==="/"?"index":q.replace(/^\/+|\/+$/g,"").replace(/\//g,"-"),O=new Date().toISOString().replace(/[:.]/g,"-").slice(0,19);F=J91.join(Y,`doctor-${B}-${O}.png`),await H.screenshot({path:F,fullPage:!0})}let U=await H.evaluate(()=>{return window.__earlyErrors||[]});G.push(...U)}catch(H){let q=H.message||"Unknown error";if(q.includes("timeout")||q.includes("Timeout"))G.push({type:"error",message:"Page load timeout - app may have crashed or is unresponsive"});else if(q.includes("net::ERR"))G.push({type:"error",message:`Network error: ${q}`});else G.push({type:"error",message:`Runtime check error: ${q}`})}finally{await BO(K)}let z=F91(G);return{name:`Runtime (${V})`,status:z.length>0?"fail":"pass",severity:"error",duration:Date.now()-Q,items:z,summary:z.length>0?`${z.length} runtime error(s)`:"No runtime errors",disk_changes:F?[F]:void 0}}async function Y91(D){try{let X=await fetch(`http://localhost:${D}`,{method:"HEAD",signal:AbortSignal.timeout(3000)});return X.ok||X.status<500}catch{return!1}}function Q91(D){return new Promise((X)=>setTimeout(X,D))}var $91=["Download the React DevTools","Download the Apollo DevTools","[HMR]","[vite] connected","[vite] connecting","WebSocket connection to 'ws://localhost","favicon.ico",/The resource http:\/\/localhost:\d+\/((@|__vite)\S*)/],K91=["ECONNREFUSED","404","500","TypeError"];function G91(D){return D.replace(/^https?:\/\/localhost:\d+\//,"")}function W91(D){let X=D.split(`
497
- `);for(let Z of X){let J=Z.trim();if(J.startsWith("at "))return J}return}function OO(D){if(!$91.some((J)=>typeof J==="string"?D.includes(J):J.test(D)))return!1;return!K91.some((J)=>D.includes(J))}function F91(D){let X=D.filter((Y)=>{let Q=Y.message||"";return!OO(Q)}),Z=new Set;return X.filter((Y)=>{let Q=Y.message||"";if(Z.has(Q))return!1;return Z.add(Q),!0}).map((Y)=>{let Q={message:Y.message};if(Y.fileName)Q.file=G91(Y.fileName);if(Y.lineNumber!==void 0)Q.line=Y.lineNumber;if(Y.columnNumber!==void 0)Q.column=Y.columnNumber;if(Y.type&&Y.type!=="error")Q.code=Y.type;if(Y.stack){let $=W91(Y.stack);if($)Q.suggestion=$}return Q})}function ew(D,X){console.log(""),console.log(I.bold("Health Check")+I.dim(` (${O91(D.duration)})`)),console.log(I.dim("─".repeat(40)));for(let Z of D.checks)V91(Z,X);console.log(I.dim("─".repeat(40))),B91(D)}function V91(D,X){let Z=z91(D.status),J=U91(D.status,D.severity),Y=I.dim(`${D.duration}ms`);console.log(`${Z} ${J(D.name)} ${Y} ${I.dim("·")} ${I.dim(D.summary||"")}`);let Q=D.name.startsWith("Runtime"),$=X||Q?D.items:D.items.slice(0,3),K=D.items.length-$.length;for(let G of $)H91(G,D.severity);if(K>0)console.log(I.dim(` ... +${K} more (--verbose)`))}function H91(D,X){let J=(D.severity==="error"?"error":D.severity==="warning"?"warning":X)==="error"?I.red:I.yellow,Y=q91(D),Q=Y?I.cyan(Y)+" ":"",$=D.fixed?I.green("[fixed] "):"";if(console.log(` ${J("›")} ${$}${Q}${D.message}`),D.suggestion)console.log(I.dim(` \uD83D\uDCA1 ${D.suggestion}`))}function q91(D){if(!D.file)return"";let X=D.file;if(D.line!==void 0){if(X+=`:${D.line}`,D.column!==void 0)X+=`:${D.column}`}return X}function z91(D){switch(D){case"pass":return I.green("✓");case"fail":return I.red("✗");case"skip":return I.dim("○");default:return I.dim("?")}}function U91(D,X){if(D==="fail")return X==="error"?I.red:I.yellow;if(D==="pass")return I.green;return I.dim}function B91(D){let{summary:X}=D,Z=[];if(X.passed>0)Z.push(I.green(`${X.passed} passed`));if(X.failed>0)Z.push(I.red(`${X.failed} failed`));if(X.skipped>0)Z.push(I.dim(`${X.skipped} skipped`));if(console.log(Z.join(I.dim(" · "))),X.errors>0)console.log(I.red(`${X.errors} error(s) need attention`));else if(X.warnings>0)console.log(I.yellow(`${X.warnings} warning(s) to review`));else console.log(I.green("All good!"))}function O91(D){if(D<1000)return`${D}ms`;return`${(D/1000).toFixed(1)}s`}var cQ0=new o1("doctor").description("Analyze project for issues (TypeScript, ESLint, build, runtime)").option("--cwd <path>","Working directory").option("--port <number>","Vite dev server port","5174").option("--chrome-path <path>","Chrome path or remote endpoint (ws://host:9222, http://host:9222)").option("--fix","Auto-fix ESLint issues where possible").option("--runtime","Run runtime error detection (requires running dev server)").option("--only-build","Run only Vite build check").option("--only-runtime","Run only runtime error detection").option("--runtime-timeout <ms>","Runtime check timeout in ms","10000").option("--route <path>","Route path for runtime check","/").option("--screenshot [dir]","Save screenshot during runtime check (default: ./screenshots)").option("--json","Output as JSON (for CI/CD)").option("-v, --verbose","Show all details including all errors").option("-q, --quiet","Hide command output logs (only show summary)").option("--no-typecheck","Skip TypeScript type checking").option("--no-lint","Skip ESLint checking").option("--no-build","Skip Vite build checking").action(async(D)=>{let X=D.cwd||process.cwd(),Z=parseInt(D.port||"5173"),J=parseInt(D.runtimeTimeout||"10000"),Y=D.route||"/",Q=Date.now(),$=D.quiet||D.json||!1;if(!await T2(X)&&!D.json)console.log(I.yellow("Warning: No promake.json found. Running checks anyway..."));let G=D.json?null:Y2("Running health checks...").start(),F=A91(D),W=[];if(F.typecheck)W.push(()=>YE(X,$));if(F.lint)W.push(()=>KE(X,D.fix,$));if(F.build)W.push(()=>GE(X));if(F.runtime){let H=D.screenshot===!0?"./screenshots":D.screenshot||void 0;W.push(()=>tw(Z,J,Y,D.chromePath,H))}let V=[];try{if(V=await M91(W,1),G)G.stop()}catch(H){if(G)G.fail("Health check failed");if(!D.json)console.error(I.red(H.message));process.exit(1)}let z={project:L91.basename(X),timestamp:new Date().toISOString(),duration:Date.now()-Q,checks:V,summary:{passed:V.filter((H)=>H.status==="pass").length,failed:V.filter((H)=>H.status==="fail").length,skipped:V.filter((H)=>H.status==="skip").length,errors:V.filter((H)=>H.status==="fail"&&H.severity==="error").reduce((H,q)=>H+q.items.length,0),warnings:V.filter((H)=>H.status==="fail"&&H.severity==="warning").reduce((H,q)=>H+q.items.length,0)}};if(D.json)console.log(JSON.stringify(z,null,2));else ew(z,D.verbose||!1);if(z.summary.errors>0)process.exit(1)});async function M91(D,X){let Z=[],J=0;async function Y(){let $=J++;if($>=D.length)return;Z[$]=await D[$](),await Y()}let Q=Array(Math.min(X,D.length)).fill(null).map(()=>Y());return await Promise.all(Q),Z}function A91(D){let X=!!D.onlyBuild,Z=!!D.onlyRuntime;if(X||Z)return{typecheck:!1,lint:!1,build:X,runtime:Z};return{typecheck:D.typecheck!==!1,lint:D.lint!==!1,build:D.build!==!1,runtime:!!D.runtime}}import I91 from"path";import{mkdir as N91}from"node:fs/promises";import R91 from"path";async function E91(D,X,Z,J){let Y=Date.now(),Q=[],$=[],K=await D.newPage();try{await K.setViewport({width:J.width,height:J.height,deviceScaleFactor:1}),K.on("console",(z)=>{let H=z.type(),q=z.text(),U=z.location(),B=U?.url?`${q} ${U.url}`:q;if(OO(q)||OO(B))return;if(U?.url?.includes("favicon.ico"))return;if(H==="error")Q.push({type:"console",message:q,fileName:U?.url,lineNumber:U?.lineNumber,columnNumber:U?.columnNumber});else if(H==="warn")$.push({type:"warning",message:q,fileName:U?.url,lineNumber:U?.lineNumber,columnNumber:U?.columnNumber})}),K.on("pageerror",(z)=>{Q.push({type:"error",message:z.message,stack:z.stack})}),await K.goto(X,{waitUntil:"networkidle2",timeout:J.timeout}),await new Promise((z)=>setTimeout(z,2000));let G=T91(Z),F=new Date().toISOString().replace(/[:.]/g,"-").slice(0,19),W=`screenshot-${G}-${F}.png`,V=R91.join(J.output,W);return await N91(J.output,{recursive:!0}),await K.screenshot({path:V,fullPage:J.fullPage}),{url:X,route:Z,screenshotPath:V,errors:LO(Q),warnings:LO($),duration:Date.now()-Y,status:"success"}}catch(G){let F=G.message||"Unknown error";return{url:X,route:Z,screenshotPath:"",errors:LO(Q),warnings:LO($),duration:Date.now()-Y,status:"error",errorMessage:F.includes("timeout")?"Page load timeout - app may have crashed or is unresponsive":F.includes("net::ERR")?`Network error: ${F}`:F}}finally{await K.close().catch(()=>{})}}async function dQ0(D,X,Z,J){let Y=[];for(let Q of Z){let $=Q.startsWith("/")?Q:`/${Q}`,K=X.replace(/\/+$/,"")+$,G=await E91(D,K,$,J);Y.push(G)}return Y}function T91(D){if(D==="/"||D==="")return"index";return D.replace(/^\/+|\/+$/g,"").replace(/\//g,"-").replace(/[^a-zA-Z0-9-_]/g,"_")}function LO(D){let X=new Set;return D.filter((Z)=>{if(X.has(Z.message))return!1;return X.add(Z.message),!0})}var lQ0=new o1("screenshot").description("Take screenshots and capture console errors from any URL").option("--url <url>","Target URL (e.g. http://10.0.1.15:3000)").option("--port <number>","Localhost shortcut (--port 5174 → http://localhost:5174)").option("--routes <paths>","Comma-separated routes (e.g. /,/about,/dashboard)","/").option("-o, --output <dir>","Output directory","./screenshots").option("--width <px>","Viewport width","1920").option("--height <px>","Viewport height","1080").option("--full-page","Capture full scrollable page").option("--chrome-path <path>","Chrome path or remote endpoint (ws://host:9222, http://host:9222)").option("--timeout <ms>","Page load timeout in ms","15000").option("--json","Output as JSON").option("-q, --quiet","Suppress terminal output").action(async(D)=>{let X=j91(D);if(!X)console.log(I.red("Error: Provide --url or --port")),console.log(I.dim(" Example: promake screenshot --url http://10.0.1.15:3000")),console.log(I.dim(" Example: promake screenshot --port 5174")),process.exit(1);let Z=(D.routes||"/").split(",").map((z)=>z.trim()).filter(Boolean),J=parseInt(D.width||"1920"),Y=parseInt(D.height||"1080"),Q=parseInt(D.timeout||"15000"),$=I91.resolve(D.output||"./screenshots"),K=D.quiet||D.json||!1,G=D.json?null:Y2("Launching browser...").start(),F=await UO(D.chromePath);if(!F){if(G)G.fail("No browser found");if(!D.json)console.log(""),console.log(I.yellow("Could not find Chrome/Chromium. Try one of:")),console.log(I.dim(" --chrome-path /usr/bin/chromium")),console.log(I.dim(" export CHROME_PATH=/usr/bin/chromium")),console.log(I.dim(" export PUPPETEER_EXECUTABLE_PATH=/usr/bin/chromium"));if(D.json)console.log(JSON.stringify({error:"No browser found"},null,2));process.exit(1)}if(G)G.text=`Capturing ${Z.length} route(s) from ${X}...`;let W;try{W=await dQ0(F.browser,X,Z,{width:J,height:Y,fullPage:!!D.fullPage,timeout:Q,output:$})}finally{await BO(F)}if(G)G.stop();if(D.json)console.log(JSON.stringify(W,null,2));else if(!K)C91(W,X);if(W.some((z)=>z.status==="error"||z.errors.length>0))process.exit(1)});function j91(D){if(D.url)return D.url;if(D.port)return`http://localhost:${D.port}`;return null}function C91(D,X){console.log(""),console.log(I.bold("Screenshot Report")+I.dim(` · ${X}`)),console.log(I.dim("─".repeat(50)));for(let K of D){let G=K.status==="success"?I.green("✓"):I.red("✗"),F=I.dim(`${K.duration}ms`);if(K.status==="success")console.log(`${G} ${I.cyan(K.route)} ${F}`),console.log(I.dim(` → ${K.screenshotPath}`));else if(console.log(`${G} ${I.red(K.route)} ${F}`),K.errorMessage)console.log(` ${I.red("›")} ${K.errorMessage}`);if(K.errors.length>0){console.log(I.red(` ${K.errors.length} console error(s):`));for(let W of K.errors){let V=W.fileName?I.dim(` (${P91(W.fileName)}${W.lineNumber?`:${W.lineNumber}`:""})`):"";console.log(` ${I.red("›")} ${W.message}${V}`)}}if(K.warnings.length>0){console.log(I.yellow(` ${K.warnings.length} warning(s):`));for(let W of K.warnings)console.log(` ${I.yellow("›")} ${W.message}`)}}console.log(I.dim("─".repeat(50)));let Z=D.filter((K)=>K.status==="success").length,J=D.filter((K)=>K.status==="error").length,Y=D.reduce((K,G)=>K+G.errors.length,0),Q=D.reduce((K,G)=>K+G.warnings.length,0),$=[];if($.push(I.green(`${Z} captured`)),J>0)$.push(I.red(`${J} failed`));if(Y>0)$.push(I.red(`${Y} error(s)`));if(Q>0)$.push(I.yellow(`${Q} warning(s)`));console.log($.join(I.dim(" · ")))}function P91(D){return D.replace(/^https?:\/\/localhost:\d+\//,"")}var pQ0={name:"@promakeai/cli",version:"0.8.0",type:"module",bin:{promake:"dist/index.js"},files:["dist/index.js","dist/registry","template"],scripts:{dev:"bun run src/index.ts","dev:app":"cd dev && bun run dev","dev:populate":"bun run scripts/populate-dev.ts","dev:fresh":"bun run dev:populate && bun run dev:app","playground:create":"rm -rf playground && bun run dev -- create playground --template empty --pm bun","playground:reset":"bun run playground:create","playground:add":"cd playground && bun run ../src/index.ts add","playground:ecommerce":"rm -rf playground && bun run dev -- create playground --template ecommerce --pm bun",clean:"rimraf dist",build:"bun run clean && bun run build:cli && bun run build:registry","build:cli":"bun build src/index.ts --outdir dist --target node --minify","build:registry":"bun run scripts/build-registry.ts",typecheck:"tsc --noEmit",prepublishOnly:"bun run build",test:"bun test","test:e2e":"bun run scripts/e2e-test.ts","test:watch":"bun test --watch","test:coverage":"bun test --coverage",release:"bun run build && npm publish --access public"},dependencies:{"adm-zip":"^0.5.16",archiver:"^7.0.1",chalk:"^5.3.0",commander:"^12.1.0",culori:"^4.0.2",dotenv:"^17.2.3","fs-extra":"^11.3.3",glob:"^11.0.0",ora:"^8.1.1",prompts:"^2.4.2","puppeteer-core":"^24.36.0"},devDependencies:{"@types/archiver":"^7.0.0","@types/bun":"^1.1.14","@types/culori":"^4.0.1","@types/fs-extra":"^11.0.4","@types/node":"^22.10.2","@types/prompts":"^2.4.9",rimraf:"6.0.1",typescript:"^5.7.2"}};var H8=new o1;H8.name("promake").description(`Modular React template CLI - Build React apps with pre-built components
497
+ `);for(let Z of X){let J=Z.trim();if(J.startsWith("at "))return J}return}function OO(D){if(!$91.some((J)=>typeof J==="string"?D.includes(J):J.test(D)))return!1;return!K91.some((J)=>D.includes(J))}function F91(D){let X=D.filter((Y)=>{let Q=Y.message||"";return!OO(Q)}),Z=new Set;return X.filter((Y)=>{let Q=Y.message||"";if(Z.has(Q))return!1;return Z.add(Q),!0}).map((Y)=>{let Q={message:Y.message};if(Y.fileName)Q.file=G91(Y.fileName);if(Y.lineNumber!==void 0)Q.line=Y.lineNumber;if(Y.columnNumber!==void 0)Q.column=Y.columnNumber;if(Y.type&&Y.type!=="error")Q.code=Y.type;if(Y.stack){let $=W91(Y.stack);if($)Q.suggestion=$}return Q})}function ew(D,X){console.log(""),console.log(I.bold("Health Check")+I.dim(` (${O91(D.duration)})`)),console.log(I.dim("─".repeat(40)));for(let Z of D.checks)V91(Z,X);console.log(I.dim("─".repeat(40))),B91(D)}function V91(D,X){let Z=z91(D.status),J=U91(D.status,D.severity),Y=I.dim(`${D.duration}ms`);console.log(`${Z} ${J(D.name)} ${Y} ${I.dim("·")} ${I.dim(D.summary||"")}`);let Q=D.name.startsWith("Runtime"),$=X||Q?D.items:D.items.slice(0,3),K=D.items.length-$.length;for(let G of $)H91(G,D.severity);if(K>0)console.log(I.dim(` ... +${K} more (--verbose)`))}function H91(D,X){let J=(D.severity==="error"?"error":D.severity==="warning"?"warning":X)==="error"?I.red:I.yellow,Y=q91(D),Q=Y?I.cyan(Y)+" ":"",$=D.fixed?I.green("[fixed] "):"";if(console.log(` ${J("›")} ${$}${Q}${D.message}`),D.suggestion)console.log(I.dim(` \uD83D\uDCA1 ${D.suggestion}`))}function q91(D){if(!D.file)return"";let X=D.file;if(D.line!==void 0){if(X+=`:${D.line}`,D.column!==void 0)X+=`:${D.column}`}return X}function z91(D){switch(D){case"pass":return I.green("✓");case"fail":return I.red("✗");case"skip":return I.dim("○");default:return I.dim("?")}}function U91(D,X){if(D==="fail")return X==="error"?I.red:I.yellow;if(D==="pass")return I.green;return I.dim}function B91(D){let{summary:X}=D,Z=[];if(X.passed>0)Z.push(I.green(`${X.passed} passed`));if(X.failed>0)Z.push(I.red(`${X.failed} failed`));if(X.skipped>0)Z.push(I.dim(`${X.skipped} skipped`));if(console.log(Z.join(I.dim(" · "))),X.errors>0)console.log(I.red(`${X.errors} error(s) need attention`));else if(X.warnings>0)console.log(I.yellow(`${X.warnings} warning(s) to review`));else console.log(I.green("All good!"))}function O91(D){if(D<1000)return`${D}ms`;return`${(D/1000).toFixed(1)}s`}var cQ0=new o1("doctor").description("Analyze project for issues (TypeScript, ESLint, build, runtime)").option("--cwd <path>","Working directory").option("--port <number>","Vite dev server port","5174").option("--chrome-path <path>","Chrome path or remote endpoint (ws://host:9222, http://host:9222)").option("--fix","Auto-fix ESLint issues where possible").option("--runtime","Run runtime error detection (requires running dev server)").option("--only-build","Run only Vite build check").option("--only-runtime","Run only runtime error detection").option("--runtime-timeout <ms>","Runtime check timeout in ms","10000").option("--route <path>","Route path for runtime check","/").option("--screenshot [dir]","Save screenshot during runtime check (default: ./screenshots)").option("--json","Output as JSON (for CI/CD)").option("-v, --verbose","Show all details including all errors").option("-q, --quiet","Hide command output logs (only show summary)").option("--no-typecheck","Skip TypeScript type checking").option("--no-lint","Skip ESLint checking").option("--no-build","Skip Vite build checking").action(async(D)=>{let X=D.cwd||process.cwd(),Z=parseInt(D.port||"5173"),J=parseInt(D.runtimeTimeout||"10000"),Y=D.route||"/",Q=Date.now(),$=D.quiet||D.json||!1;if(!await T2(X)&&!D.json)console.log(I.yellow("Warning: No promake.json found. Running checks anyway..."));let G=D.json?null:Y2("Running health checks...").start(),F=A91(D),W=[];if(F.typecheck)W.push(()=>YE(X,$));if(F.lint)W.push(()=>KE(X,D.fix,$));if(F.build)W.push(()=>GE(X));if(F.runtime){let H=D.screenshot===!0?"./screenshots":D.screenshot||void 0;W.push(()=>tw(Z,J,Y,D.chromePath,H))}let V=[];try{if(V=await M91(W,1),G)G.stop()}catch(H){if(G)G.fail("Health check failed");if(!D.json)console.error(I.red(H.message));process.exit(1)}let z={project:L91.basename(X),timestamp:new Date().toISOString(),duration:Date.now()-Q,checks:V,summary:{passed:V.filter((H)=>H.status==="pass").length,failed:V.filter((H)=>H.status==="fail").length,skipped:V.filter((H)=>H.status==="skip").length,errors:V.filter((H)=>H.status==="fail"&&H.severity==="error").reduce((H,q)=>H+q.items.length,0),warnings:V.filter((H)=>H.status==="fail"&&H.severity==="warning").reduce((H,q)=>H+q.items.length,0)}};if(D.json)console.log(JSON.stringify(z,null,2));else ew(z,D.verbose||!1);if(z.summary.errors>0)process.exit(1)});async function M91(D,X){let Z=[],J=0;async function Y(){let $=J++;if($>=D.length)return;Z[$]=await D[$](),await Y()}let Q=Array(Math.min(X,D.length)).fill(null).map(()=>Y());return await Promise.all(Q),Z}function A91(D){let X=!!D.onlyBuild,Z=!!D.onlyRuntime;if(X||Z)return{typecheck:!1,lint:!1,build:X,runtime:Z};return{typecheck:D.typecheck!==!1,lint:D.lint!==!1,build:D.build!==!1,runtime:!!D.runtime}}import I91 from"path";import{mkdir as N91}from"node:fs/promises";import R91 from"path";async function E91(D,X,Z,J){let Y=Date.now(),Q=[],$=[],K=await D.newPage();try{await K.setViewport({width:J.width,height:J.height,deviceScaleFactor:1}),K.on("console",(z)=>{let H=z.type(),q=z.text(),U=z.location(),B=U?.url?`${q} ${U.url}`:q;if(OO(q)||OO(B))return;if(U?.url?.includes("favicon.ico"))return;if(H==="error")Q.push({type:"console",message:q,fileName:U?.url,lineNumber:U?.lineNumber,columnNumber:U?.columnNumber});else if(H==="warn")$.push({type:"warning",message:q,fileName:U?.url,lineNumber:U?.lineNumber,columnNumber:U?.columnNumber})}),K.on("pageerror",(z)=>{Q.push({type:"error",message:z.message,stack:z.stack})}),await K.goto(X,{waitUntil:"networkidle2",timeout:J.timeout}),await new Promise((z)=>setTimeout(z,2000));let G=T91(Z),F=new Date().toISOString().replace(/[:.]/g,"-").slice(0,19),W=`screenshot-${G}-${F}.png`,V=R91.join(J.output,W);return await N91(J.output,{recursive:!0}),await K.screenshot({path:V,fullPage:J.fullPage}),{url:X,route:Z,screenshotPath:V,errors:LO(Q),warnings:LO($),duration:Date.now()-Y,status:"success"}}catch(G){let F=G.message||"Unknown error";return{url:X,route:Z,screenshotPath:"",errors:LO(Q),warnings:LO($),duration:Date.now()-Y,status:"error",errorMessage:F.includes("timeout")?"Page load timeout - app may have crashed or is unresponsive":F.includes("net::ERR")?`Network error: ${F}`:F}}finally{await K.close().catch(()=>{})}}async function dQ0(D,X,Z,J){let Y=[];for(let Q of Z){let $=Q.startsWith("/")?Q:`/${Q}`,K=X.replace(/\/+$/,"")+$,G=await E91(D,K,$,J);Y.push(G)}return Y}function T91(D){if(D==="/"||D==="")return"index";return D.replace(/^\/+|\/+$/g,"").replace(/\//g,"-").replace(/[^a-zA-Z0-9-_]/g,"_")}function LO(D){let X=new Set;return D.filter((Z)=>{if(X.has(Z.message))return!1;return X.add(Z.message),!0})}var lQ0=new o1("screenshot").description("Take screenshots and capture console errors from any URL").option("--url <url>","Target URL (e.g. http://10.0.1.15:3000)").option("--port <number>","Localhost shortcut (--port 5174 → http://localhost:5174)").option("--routes <paths>","Comma-separated routes (e.g. /,/about,/dashboard)","/").option("-o, --output <dir>","Output directory","./screenshots").option("--width <px>","Viewport width","1920").option("--height <px>","Viewport height","1080").option("--full-page","Capture full scrollable page").option("--chrome-path <path>","Chrome path or remote endpoint (ws://host:9222, http://host:9222)").option("--timeout <ms>","Page load timeout in ms","15000").option("--json","Output as JSON").option("-q, --quiet","Suppress terminal output").action(async(D)=>{let X=j91(D);if(!X)console.log(I.red("Error: Provide --url or --port")),console.log(I.dim(" Example: promake screenshot --url http://10.0.1.15:3000")),console.log(I.dim(" Example: promake screenshot --port 5174")),process.exit(1);let Z=(D.routes||"/").split(",").map((z)=>z.trim()).filter(Boolean),J=parseInt(D.width||"1920"),Y=parseInt(D.height||"1080"),Q=parseInt(D.timeout||"15000"),$=I91.resolve(D.output||"./screenshots"),K=D.quiet||D.json||!1,G=D.json?null:Y2("Launching browser...").start(),F=await UO(D.chromePath);if(!F){if(G)G.fail("No browser found");if(!D.json)console.log(""),console.log(I.yellow("Could not find Chrome/Chromium. Try one of:")),console.log(I.dim(" --chrome-path /usr/bin/chromium")),console.log(I.dim(" export CHROME_PATH=/usr/bin/chromium")),console.log(I.dim(" export PUPPETEER_EXECUTABLE_PATH=/usr/bin/chromium"));if(D.json)console.log(JSON.stringify({error:"No browser found"},null,2));process.exit(1)}if(G)G.text=`Capturing ${Z.length} route(s) from ${X}...`;let W;try{W=await dQ0(F.browser,X,Z,{width:J,height:Y,fullPage:!!D.fullPage,timeout:Q,output:$})}finally{await BO(F)}if(G)G.stop();if(D.json)console.log(JSON.stringify(W,null,2));else if(!K)C91(W,X);if(W.some((z)=>z.status==="error"||z.errors.length>0))process.exit(1)});function j91(D){if(D.url)return D.url;if(D.port)return`http://localhost:${D.port}`;return null}function C91(D,X){console.log(""),console.log(I.bold("Screenshot Report")+I.dim(` · ${X}`)),console.log(I.dim("─".repeat(50)));for(let K of D){let G=K.status==="success"?I.green("✓"):I.red("✗"),F=I.dim(`${K.duration}ms`);if(K.status==="success")console.log(`${G} ${I.cyan(K.route)} ${F}`),console.log(I.dim(` → ${K.screenshotPath}`));else if(console.log(`${G} ${I.red(K.route)} ${F}`),K.errorMessage)console.log(` ${I.red("›")} ${K.errorMessage}`);if(K.errors.length>0){console.log(I.red(` ${K.errors.length} console error(s):`));for(let W of K.errors){let V=W.fileName?I.dim(` (${P91(W.fileName)}${W.lineNumber?`:${W.lineNumber}`:""})`):"";console.log(` ${I.red("›")} ${W.message}${V}`)}}if(K.warnings.length>0){console.log(I.yellow(` ${K.warnings.length} warning(s):`));for(let W of K.warnings)console.log(` ${I.yellow("›")} ${W.message}`)}}console.log(I.dim("─".repeat(50)));let Z=D.filter((K)=>K.status==="success").length,J=D.filter((K)=>K.status==="error").length,Y=D.reduce((K,G)=>K+G.errors.length,0),Q=D.reduce((K,G)=>K+G.warnings.length,0),$=[];if($.push(I.green(`${Z} captured`)),J>0)$.push(I.red(`${J} failed`));if(Y>0)$.push(I.red(`${Y} error(s)`));if(Q>0)$.push(I.yellow(`${Q} warning(s)`));console.log($.join(I.dim(" · ")))}function P91(D){return D.replace(/^https?:\/\/localhost:\d+\//,"")}var pQ0={name:"@promakeai/cli",version:"0.8.1",type:"module",bin:{promake:"dist/index.js"},files:["dist/index.js","dist/registry","template"],scripts:{dev:"bun run src/index.ts","dev:app":"cd dev && bun run dev","dev:populate":"bun run scripts/populate-dev.ts","dev:fresh":"bun run dev:populate && bun run dev:app","playground:create":"rm -rf playground && bun run dev -- create playground --template empty --pm bun","playground:reset":"bun run playground:create","playground:add":"cd playground && bun run ../src/index.ts add","playground:ecommerce":"rm -rf playground && bun run dev -- create playground --template ecommerce --pm bun",clean:"rimraf dist",build:"bun run clean && bun run build:cli && bun run build:registry","build:cli":"bun build src/index.ts --outdir dist --target node --minify","build:registry":"bun run scripts/build-registry.ts",typecheck:"tsc --noEmit",prepublishOnly:"bun run build",test:"bun test","test:e2e":"bun run scripts/e2e-test.ts","test:watch":"bun test --watch","test:coverage":"bun test --coverage",release:"bun run build && npm publish --access public"},dependencies:{"adm-zip":"^0.5.16",archiver:"^7.0.1",chalk:"^5.3.0",commander:"^12.1.0",culori:"^4.0.2",dotenv:"^17.2.3","fs-extra":"^11.3.3",glob:"^11.0.0",ora:"^8.1.1",prompts:"^2.4.2","puppeteer-core":"^24.36.0"},devDependencies:{"@types/archiver":"^7.0.0","@types/bun":"^1.1.14","@types/culori":"^4.0.1","@types/fs-extra":"^11.0.4","@types/node":"^22.10.2","@types/prompts":"^2.4.9",rimraf:"6.0.1",typescript:"^5.7.2"}};var H8=new o1;H8.name("promake").description(`Modular React template CLI - Build React apps with pre-built components
498
498
 
499
499
  Quick Start:
500
500
  $ promake create my-app
@@ -0,0 +1,43 @@
1
+ # Verify Email Page
2
+
3
+ Email verification page with two-step flow: enter username to request code, then enter verification code. Uses useAuth hook from auth-core for API calls.
4
+
5
+ ## Files
6
+
7
+ | Target | Type |
8
+ |--------|------|
9
+ | `$modules$/verify-email-page/index.ts` | index |
10
+ | `$modules$/verify-email-page/verify-email-page.tsx` | page |
11
+ | `$modules$/verify-email-page/lang/en.json` | lang |
12
+ | `$modules$/verify-email-page/lang/tr.json` | lang |
13
+
14
+ ## Exports
15
+
16
+ **Components/Functions:** `VerifyEmailPage`, `default`
17
+
18
+ ```typescript
19
+ import { VerifyEmailPage, default } from '@/modules/verify-email-page';
20
+ ```
21
+
22
+ ## Usage
23
+
24
+ ```
25
+ import VerifyEmailPage from '@/modules/verify-email-page';
26
+
27
+ <VerifyEmailPage />
28
+
29
+ • Installed at: src/modules/verify-email-page/
30
+ • Customize text: src/modules/verify-email-page/lang/*.json
31
+ • Uses useAuth() hook from auth-core:
32
+ const { confirmEmail, resendCode } = useAuth();
33
+ await resendCode(username);
34
+ await confirmEmail(username, code);
35
+ • Two-step flow: request code -> enter code to verify
36
+ • Add to your router as a page component
37
+ ```
38
+
39
+ ## Dependencies
40
+
41
+ This component requires:
42
+ - `auth-core`
43
+ - `api`
@@ -23,19 +23,19 @@
23
23
  "path": "register-page-split/register-page-split.tsx",
24
24
  "type": "registry:page",
25
25
  "target": "$modules$/register-page-split/register-page-split.tsx",
26
- "content": "import { useState } from \"react\";\r\nimport { Link, useNavigate } from \"react-router\";\r\nimport { toast } from \"sonner\";\r\nimport { useTranslation } from \"react-i18next\";\r\nimport { usePageTitle } from \"@/hooks/use-page-title\";\r\nimport { Button } from \"@/components/ui/button\";\r\nimport { Input } from \"@/components/ui/input\";\r\nimport { Logo } from \"@/components/Logo\";\r\nimport { useAuth } from \"@/modules/auth-core\";\r\nimport { getErrorMessage } from \"@/modules/api\";\r\nimport { FormField } from \"@/components/FormField\";\r\nimport { PasswordInput } from \"@/components/PasswordInput\";\r\n\r\ninterface RegisterPageSplitProps {\r\n image?: string;\r\n}\r\n\r\nexport function RegisterPageSplit({\r\n image = \"/images/placeholder.png\",\r\n}: RegisterPageSplitProps) {\r\n const { t } = useTranslation(\"register-page-split\");\r\n usePageTitle({ title: t(\"title\", \"Create Account\") });\r\n const navigate = useNavigate();\r\n const { register } = useAuth();\r\n\r\n const [username, setUsername] = useState(\"\");\r\n const [email, setEmail] = useState(\"\");\r\n const [password, setPassword] = useState(\"\");\r\n const [confirmPassword, setConfirmPassword] = useState(\"\");\r\n const [isLoading, setIsLoading] = useState(false);\r\n const [error, setError] = useState<string | null>(null);\r\n\r\n const handleSubmit = async (e: React.FormEvent) => {\r\n e.preventDefault();\r\n setError(null);\r\n\r\n // Validate passwords match\r\n if (password !== confirmPassword) {\r\n setError(t(\"passwordMismatch\", \"Passwords do not match\"));\r\n return;\r\n }\r\n\r\n setIsLoading(true);\r\n\r\n try {\r\n await register(username, email, password);\r\n\r\n toast.success(t(\"registerSuccess\", \"Account created successfully!\"), {\r\n description: t(\"checkEmail\", \"Please check your email to verify your account.\"),\r\n });\r\n\r\n // Navigate to login page after successful registration\r\n navigate(\"/login\", {\r\n state: {\r\n message: t(\"verifyEmail\", \"Please verify your email before logging in.\"),\r\n email\r\n }\r\n });\r\n } catch (err) {\r\n const errorMessage = getErrorMessage(\r\n err,\r\n t(\"registerError\", \"Registration failed. Please try again.\")\r\n );\r\n setError(errorMessage);\r\n } finally {\r\n setIsLoading(false);\r\n }\r\n };\r\n\r\n return (\r\n <section className=\"w-full md:grid md:min-h-screen md:grid-cols-2\">\r\n <div className=\"flex items-center justify-center px-4 py-12\">\r\n <div className=\"mx-auto grid w-full max-w-sm gap-6\">\r\n <Logo />\r\n <hr />\r\n <div>\r\n <h1 className=\"text-xl font-bold tracking-tight\">\r\n {t(\"title\", \"Create Account\")}\r\n </h1>\r\n <p className=\"text-sm text-muted-foreground\">\r\n {t(\"subtitle\", \"Sign up to get started\")}\r\n </p>\r\n </div>\r\n\r\n {error && (\r\n <div className=\"p-3 text-sm text-red-600 bg-red-50 dark:bg-red-950 dark:text-red-400 rounded-md\">\r\n {error}\r\n </div>\r\n )}\r\n\r\n <form onSubmit={handleSubmit} className=\"grid gap-4\">\r\n <div className=\"grid gap-2\">\r\n <FormField label={t(\"username\", \"Username\")} htmlFor=\"username\" required>\r\n <Input\r\n required\r\n id=\"username\"\r\n type=\"text\"\r\n autoComplete=\"username\"\r\n placeholder={t(\"usernamePlaceholder\", \"johndoe\")}\r\n value={username}\r\n onChange={(e) => setUsername(e.target.value)}\r\n disabled={isLoading}\r\n />\r\n </FormField>\r\n </div>\r\n\r\n <div className=\"grid gap-2\">\r\n <FormField label={t(\"email\", \"Email\")} htmlFor=\"email\" required>\r\n <Input\r\n required\r\n id=\"email\"\r\n type=\"email\"\r\n autoComplete=\"email\"\r\n placeholder={t(\"emailPlaceholder\", \"you@example.com\")}\r\n value={email}\r\n onChange={(e) => setEmail(e.target.value)}\r\n disabled={isLoading}\r\n />\r\n </FormField>\r\n </div>\r\n\r\n <div className=\"grid gap-2\">\r\n <FormField label={t(\"password\", \"Password\")} htmlFor=\"password\" required>\r\n <PasswordInput\r\n required\r\n name=\"password\"\r\n id=\"password\"\r\n autoComplete=\"new-password\"\r\n placeholder=\"••••••••\"\r\n value={password}\r\n onChange={(e) => setPassword(e.target.value)}\r\n disabled={isLoading}\r\n minLength={8}\r\n />\r\n </FormField>\r\n </div>\r\n\r\n <div className=\"grid gap-2\">\r\n <FormField label={t(\"confirmPassword\", \"Confirm Password\")} htmlFor=\"confirm-password\" required>\r\n <PasswordInput\r\n required\r\n id=\"confirm-password\"\r\n name=\"confirm-password\"\r\n autoComplete=\"new-password\"\r\n placeholder=\"••••••••\"\r\n value={confirmPassword}\r\n onChange={(e) => setConfirmPassword(e.target.value)}\r\n disabled={isLoading}\r\n minLength={8}\r\n />\r\n </FormField>\r\n </div>\r\n\r\n <Button type=\"submit\" className=\"w-full\" disabled={isLoading}>\r\n {isLoading ? (\r\n <>\r\n <div className=\"w-4 h-4 border-2 border-primary-foreground border-t-transparent rounded-full animate-spin mr-2\" />\r\n {t(\"creatingAccount\", \"Creating account...\")}\r\n </>\r\n ) : (\r\n t(\"signUp\", \"Sign Up\")\r\n )}\r\n </Button>\r\n </form>\r\n\r\n <div className=\"text-sm text-center\">\r\n <p>\r\n {t(\"hasAccount\", \"Already have an account?\")}{\" \"}\r\n <Link to=\"/login\" className=\"underline\">\r\n {t(\"signIn\", \"Sign in\")}\r\n </Link>\r\n </p>\r\n </div>\r\n\r\n <hr />\r\n <p className=\"text-sm text-muted-foreground\">\r\n © {new Date().getFullYear()} {t(\"copyright\", \"All rights reserved.\")}\r\n </p>\r\n </div>\r\n </div>\r\n <div className=\"hidden p-4 md:block\">\r\n <img\r\n loading=\"lazy\"\r\n decoding=\"async\"\r\n width=\"1920\"\r\n height=\"1080\"\r\n alt={t(\"imageAlt\", \"Register background\")}\r\n src={image}\r\n className=\"size-full rounded-lg border bg-muted object-cover object-center\"\r\n />\r\n </div>\r\n </section>\r\n );\r\n}\r\n\r\nexport default RegisterPageSplit;\r\n"
26
+ "content": "import { useState } from \"react\";\r\nimport { Link, useNavigate } from \"react-router\";\r\nimport { toast } from \"sonner\";\r\nimport { useTranslation } from \"react-i18next\";\r\nimport { usePageTitle } from \"@/hooks/use-page-title\";\r\nimport { Button } from \"@/components/ui/button\";\r\nimport { Input } from \"@/components/ui/input\";\r\nimport { Logo } from \"@/components/Logo\";\r\nimport { useAuth } from \"@/modules/auth-core\";\r\nimport { getErrorMessage } from \"@/modules/api\";\r\nimport { FormField } from \"@/components/FormField\";\r\nimport { PasswordInput } from \"@/components/PasswordInput\";\r\n\r\ninterface RegisterPageSplitProps {\r\n image?: string;\r\n}\r\n\r\nexport function RegisterPageSplit({\r\n image = \"/images/placeholder.png\",\r\n}: RegisterPageSplitProps) {\r\n const { t } = useTranslation(\"register-page-split\");\r\n usePageTitle({ title: t(\"title\", \"Create Account\") });\r\n const navigate = useNavigate();\r\n const { register } = useAuth();\r\n\r\n const [username, setUsername] = useState(\"\");\r\n const [email, setEmail] = useState(\"\");\r\n const [password, setPassword] = useState(\"\");\r\n const [confirmPassword, setConfirmPassword] = useState(\"\");\r\n const [isLoading, setIsLoading] = useState(false);\r\n const [error, setError] = useState<string | null>(null);\r\n\r\n const handleSubmit = async (e: React.FormEvent) => {\r\n e.preventDefault();\r\n setError(null);\r\n\r\n // Validate passwords match\r\n if (password !== confirmPassword) {\r\n setError(t(\"passwordMismatch\", \"Passwords do not match\"));\r\n return;\r\n }\r\n\r\n setIsLoading(true);\r\n\r\n try {\r\n await register(username, email, password);\r\n\r\n toast.success(t(\"registerSuccess\", \"Account created successfully!\"), {\r\n description: t(\"registerSuccessDesc\", \"You can now sign in with your credentials.\"),\r\n });\r\n\r\n navigate(\"/login\");\r\n } catch (err) {\r\n const errorMessage = getErrorMessage(\r\n err,\r\n t(\"registerError\", \"Registration failed. Please try again.\")\r\n );\r\n setError(errorMessage);\r\n } finally {\r\n setIsLoading(false);\r\n }\r\n };\r\n\r\n return (\r\n <section className=\"w-full md:grid md:min-h-screen md:grid-cols-2\">\r\n <div className=\"flex items-center justify-center px-4 py-12\">\r\n <div className=\"mx-auto grid w-full max-w-sm gap-6\">\r\n <Logo />\r\n <hr />\r\n <div>\r\n <h1 className=\"text-xl font-bold tracking-tight\">\r\n {t(\"title\", \"Create Account\")}\r\n </h1>\r\n <p className=\"text-sm text-muted-foreground\">\r\n {t(\"subtitle\", \"Sign up to get started\")}\r\n </p>\r\n </div>\r\n\r\n {error && (\r\n <div className=\"p-3 text-sm text-red-600 bg-red-50 dark:bg-red-950 dark:text-red-400 rounded-md\">\r\n {error}\r\n </div>\r\n )}\r\n\r\n <form onSubmit={handleSubmit} className=\"grid gap-4\">\r\n <div className=\"grid gap-2\">\r\n <FormField label={t(\"username\", \"Username\")} htmlFor=\"username\" required>\r\n <Input\r\n required\r\n id=\"username\"\r\n type=\"text\"\r\n autoComplete=\"username\"\r\n placeholder={t(\"usernamePlaceholder\", \"johndoe\")}\r\n value={username}\r\n onChange={(e) => setUsername(e.target.value)}\r\n disabled={isLoading}\r\n />\r\n </FormField>\r\n </div>\r\n\r\n <div className=\"grid gap-2\">\r\n <FormField label={t(\"email\", \"Email\")} htmlFor=\"email\" required>\r\n <Input\r\n required\r\n id=\"email\"\r\n type=\"email\"\r\n autoComplete=\"email\"\r\n placeholder={t(\"emailPlaceholder\", \"you@example.com\")}\r\n value={email}\r\n onChange={(e) => setEmail(e.target.value)}\r\n disabled={isLoading}\r\n />\r\n </FormField>\r\n </div>\r\n\r\n <div className=\"grid gap-2\">\r\n <FormField label={t(\"password\", \"Password\")} htmlFor=\"password\" required>\r\n <PasswordInput\r\n required\r\n name=\"password\"\r\n id=\"password\"\r\n autoComplete=\"new-password\"\r\n placeholder=\"••••••••\"\r\n value={password}\r\n onChange={(e) => setPassword(e.target.value)}\r\n disabled={isLoading}\r\n minLength={8}\r\n />\r\n </FormField>\r\n </div>\r\n\r\n <div className=\"grid gap-2\">\r\n <FormField label={t(\"confirmPassword\", \"Confirm Password\")} htmlFor=\"confirm-password\" required>\r\n <PasswordInput\r\n required\r\n id=\"confirm-password\"\r\n name=\"confirm-password\"\r\n autoComplete=\"new-password\"\r\n placeholder=\"••••••••\"\r\n value={confirmPassword}\r\n onChange={(e) => setConfirmPassword(e.target.value)}\r\n disabled={isLoading}\r\n minLength={8}\r\n />\r\n </FormField>\r\n </div>\r\n\r\n <Button type=\"submit\" className=\"w-full\" disabled={isLoading}>\r\n {isLoading ? (\r\n <>\r\n <div className=\"w-4 h-4 border-2 border-primary-foreground border-t-transparent rounded-full animate-spin mr-2\" />\r\n {t(\"creatingAccount\", \"Creating account...\")}\r\n </>\r\n ) : (\r\n t(\"signUp\", \"Sign Up\")\r\n )}\r\n </Button>\r\n </form>\r\n\r\n <div className=\"text-sm text-center\">\r\n <p>\r\n {t(\"hasAccount\", \"Already have an account?\")}{\" \"}\r\n <Link to=\"/login\" className=\"underline\">\r\n {t(\"signIn\", \"Sign in\")}\r\n </Link>\r\n </p>\r\n </div>\r\n\r\n <hr />\r\n <p className=\"text-sm text-muted-foreground\">\r\n © {new Date().getFullYear()} {t(\"copyright\", \"All rights reserved.\")}\r\n </p>\r\n </div>\r\n </div>\r\n <div className=\"hidden p-4 md:block\">\r\n <img\r\n loading=\"lazy\"\r\n decoding=\"async\"\r\n width=\"1920\"\r\n height=\"1080\"\r\n alt={t(\"imageAlt\", \"Register background\")}\r\n src={image}\r\n className=\"size-full rounded-lg border bg-muted object-cover object-center\"\r\n />\r\n </div>\r\n </section>\r\n );\r\n}\r\n\r\nexport default RegisterPageSplit;\r\n"
27
27
  },
28
28
  {
29
29
  "path": "register-page-split/lang/en.json",
30
30
  "type": "registry:lang",
31
31
  "target": "$modules$/register-page-split/lang/en.json",
32
- "content": "{\r\n \"title\": \"Create Account\",\r\n \"subtitle\": \"Sign up to get started\",\r\n \"username\": \"Username\",\r\n \"usernamePlaceholder\": \"johndoe\",\r\n \"email\": \"Email\",\r\n \"emailPlaceholder\": \"you@example.com\",\r\n \"password\": \"Password\",\r\n \"confirmPassword\": \"Confirm Password\",\r\n \"passwordMismatch\": \"Passwords do not match\",\r\n \"signUp\": \"Sign Up\",\r\n \"creatingAccount\": \"Creating account...\",\r\n \"registerSuccess\": \"Account created successfully!\",\r\n \"checkEmail\": \"Please check your email to verify your account.\",\r\n \"verifyEmail\": \"Please verify your email before logging in.\",\r\n \"registerError\": \"Registration failed. Please try again.\",\r\n \"hasAccount\": \"Already have an account?\",\r\n \"signIn\": \"Sign in\",\r\n \"copyright\": \"All rights reserved.\",\r\n \"imageAlt\": \"Register background\"\r\n}\r\n"
32
+ "content": "{\r\n \"title\": \"Create Account\",\r\n \"subtitle\": \"Sign up to get started\",\r\n \"username\": \"Username\",\r\n \"usernamePlaceholder\": \"johndoe\",\r\n \"email\": \"Email\",\r\n \"emailPlaceholder\": \"you@example.com\",\r\n \"password\": \"Password\",\r\n \"confirmPassword\": \"Confirm Password\",\r\n \"passwordMismatch\": \"Passwords do not match\",\r\n \"signUp\": \"Sign Up\",\r\n \"creatingAccount\": \"Creating account...\",\r\n \"registerSuccess\": \"Account created successfully!\",\r\n \"registerSuccessDesc\": \"You can now sign in with your credentials.\",\r\n \"registerError\": \"Registration failed. Please try again.\",\r\n \"hasAccount\": \"Already have an account?\",\r\n \"signIn\": \"Sign in\",\r\n \"copyright\": \"All rights reserved.\",\r\n \"imageAlt\": \"Register background\"\r\n}\r\n"
33
33
  },
34
34
  {
35
35
  "path": "register-page-split/lang/tr.json",
36
36
  "type": "registry:lang",
37
37
  "target": "$modules$/register-page-split/lang/tr.json",
38
- "content": "{\r\n \"title\": \"Hesap Oluştur\",\r\n \"subtitle\": \"Başlamak için kaydolun\",\r\n \"username\": \"Kullanıcı Adı\",\r\n \"usernamePlaceholder\": \"ahmetyilmaz\",\r\n \"email\": \"E-posta\",\r\n \"emailPlaceholder\": \"ornek@email.com\",\r\n \"password\": \"Şifre\",\r\n \"confirmPassword\": \"Şifre Onayı\",\r\n \"passwordMismatch\": \"Şifreler eşleşmiyor\",\r\n \"signUp\": \"Kaydol\",\r\n \"creatingAccount\": \"Hesap oluşturuluyor...\",\r\n \"registerSuccess\": \"Hesap başarıyla oluşturuldu!\",\r\n \"checkEmail\": \"Lütfen hesabınızı doğrulamak için e-postanızı kontrol edin.\",\r\n \"verifyEmail\": \"Lütfen giriş yapmadan önce e-postanızı doğrulayın.\",\r\n \"registerError\": \"Kayıt başarısız. Lütfen tekrar deneyin.\",\r\n \"hasAccount\": \"Zaten hesabınız var mı?\",\r\n \"signIn\": \"Giriş yap\",\r\n \"copyright\": \"Tüm hakları saklıdır.\",\r\n \"imageAlt\": \"Kayıt arka planı\"\r\n}\r\n"
38
+ "content": "{\r\n \"title\": \"Hesap Oluştur\",\r\n \"subtitle\": \"Başlamak için kaydolun\",\r\n \"username\": \"Kullanıcı Adı\",\r\n \"usernamePlaceholder\": \"ahmetyilmaz\",\r\n \"email\": \"E-posta\",\r\n \"emailPlaceholder\": \"ornek@email.com\",\r\n \"password\": \"Şifre\",\r\n \"confirmPassword\": \"Şifre Onayı\",\r\n \"passwordMismatch\": \"Şifreler eşleşmiyor\",\r\n \"signUp\": \"Kaydol\",\r\n \"creatingAccount\": \"Hesap oluşturuluyor...\",\r\n \"registerSuccess\": \"Hesap başarıyla oluşturuldu!\",\r\n \"registerSuccessDesc\": \"Artık bilgilerinizle giriş yapabilirsiniz.\",\r\n \"registerError\": \"Kayıt başarısız. Lütfen tekrar deneyin.\",\r\n \"hasAccount\": \"Zaten hesabınız var mı?\",\r\n \"signIn\": \"Giriş yap\",\r\n \"copyright\": \"Tüm hakları saklıdır.\",\r\n \"imageAlt\": \"Kayıt arka planı\"\r\n}\r\n"
39
39
  }
40
40
  ],
41
41
  "exports": {
@@ -23,19 +23,19 @@
23
23
  "path": "register-page/register-page.tsx",
24
24
  "type": "registry:page",
25
25
  "target": "$modules$/register-page/register-page.tsx",
26
- "content": "import { useState, useEffect } from \"react\";\r\nimport { Link, useNavigate } from \"react-router\";\r\nimport { toast } from \"sonner\";\r\nimport { Layout } from \"@/components/Layout\";\r\nimport { usePageTitle } from \"@/hooks/use-page-title\";\r\nimport { useTranslation } from \"react-i18next\";\r\nimport { useAuth } from \"@/modules/auth-core\";\r\nimport { getErrorMessage } from \"@/modules/api\";\r\nimport { Button } from \"@/components/ui/button\";\r\nimport { Input } from \"@/components/ui/input\";\r\nimport { Card, CardContent, CardHeader, CardTitle } from \"@/components/ui/card\";\r\nimport { UserPlus, CheckCircle } from \"lucide-react\";\r\nimport { PasswordInput } from \"@/components/PasswordInput\";\r\nimport { FormField } from \"@/components/FormField\";\r\n\r\nexport function RegisterPage() {\r\n const { t } = useTranslation(\"register-page\");\r\n usePageTitle({ title: t(\"title\", \"Create Account\") });\r\n\r\n const navigate = useNavigate();\r\n const { register, isAuthenticated } = useAuth();\r\n\r\n const [formData, setFormData] = useState({\r\n username: \"\",\r\n email: \"\",\r\n password: \"\",\r\n confirmPassword: \"\",\r\n });\r\n const [isSubmitting, setIsSubmitting] = useState(false);\r\n const [error, setError] = useState<string | null>(null);\r\n const [success, setSuccess] = useState(false);\r\n\r\n // Redirect if already authenticated\r\n useEffect(() => {\r\n if (isAuthenticated) {\r\n navigate(\"/\", { replace: true });\r\n }\r\n }, [isAuthenticated, navigate]);\r\n\r\n const handleSubmit = async (e: React.FormEvent) => {\r\n e.preventDefault();\r\n setIsSubmitting(true);\r\n setError(null);\r\n\r\n // Validate passwords match\r\n if (formData.password !== formData.confirmPassword) {\r\n setError(t(\"passwordMismatch\", \"Passwords do not match\"));\r\n toast.error(t(\"toastErrorTitle\", \"Registration failed\"), {\r\n description: t(\"passwordMismatch\", \"Passwords do not match\"),\r\n });\r\n setIsSubmitting(false);\r\n return;\r\n }\r\n\r\n try {\r\n await register(formData.username, formData.email, formData.password);\r\n setSuccess(true);\r\n toast.success(t(\"toastSuccessTitle\", \"Account created!\"), {\r\n description: t(\r\n \"toastSuccessDesc\",\r\n \"Please check your email to verify your account.\"\r\n ),\r\n });\r\n } catch (err) {\r\n const errorMessage = getErrorMessage(\r\n err,\r\n t(\"errorGeneric\", \"Registration failed. Please try again.\")\r\n );\r\n setError(errorMessage);\r\n toast.error(t(\"toastErrorTitle\", \"Registration failed\"), {\r\n description: errorMessage,\r\n });\r\n } finally {\r\n setIsSubmitting(false);\r\n }\r\n };\r\n\r\n const handleChange = (e: React.ChangeEvent<HTMLInputElement>) => {\r\n setFormData((prev) => ({\r\n ...prev,\r\n [e.target.name]: e.target.value,\r\n }));\r\n };\r\n\r\n if (success) {\r\n return (\r\n <div className=\"min-h-screen bg-muted/30 py-12\">\r\n <div className=\"w-full max-w-[var(--container-max-width)] mx-auto px-4\">\r\n <div className=\"max-w-md mx-auto\">\r\n <Card>\r\n <CardContent className=\"pt-6\">\r\n <div className=\"text-center space-y-4\">\r\n <CheckCircle className=\"w-16 h-16 text-green-500 mx-auto\" />\r\n <h2 className=\"text-2xl font-bold text-foreground\">\r\n {t(\"successTitle\", \"Account Created!\")}\r\n </h2>\r\n <p className=\"text-muted-foreground\">\r\n {t(\r\n \"successMessage\",\r\n \"Please check your email to verify your account.\"\r\n )}\r\n </p>\r\n <Button asChild className=\"mt-4\">\r\n <Link to=\"/login\">{t(\"goToLogin\", \"Go to Login\")}</Link>\r\n </Button>\r\n </div>\r\n </CardContent>\r\n </Card>\r\n </div>\r\n </div>\r\n </div>\r\n );\r\n }\r\n\r\n return (\r\n <Layout>\r\n <div className=\"min-h-screen bg-muted/30 py-12\">\r\n <div className=\"w-full max-w-[var(--container-max-width)] mx-auto px-4\">\r\n {/* Hero Section */}\r\n <div className=\"text-center mb-12\">\r\n <h1 className=\"text-4xl font-bold text-foreground mb-4\">\r\n {t(\"title\", \"Create Account\")}\r\n </h1>\r\n <div className=\"w-16 h-1 bg-primary mx-auto mb-6\"></div>\r\n <p className=\"text-lg text-muted-foreground max-w-xl mx-auto\">\r\n {t(\"description\", \"Create an account to get started\")}\r\n </p>\r\n </div>\r\n\r\n <div className=\"max-w-md mx-auto\">\r\n <Card>\r\n <CardHeader>\r\n <CardTitle className=\"flex items-center gap-2\">\r\n <UserPlus className=\"w-5 h-5 text-primary\" />\r\n {t(\"cardTitle\", \"Sign Up\")}\r\n </CardTitle>\r\n </CardHeader>\r\n <CardContent>\r\n <form onSubmit={handleSubmit} className=\"space-y-6\">\r\n <FormField\r\n label={t(\"username\", \"Username\")}\r\n htmlFor=\"username\"\r\n required\r\n >\r\n <Input\r\n id=\"username\"\r\n name=\"username\"\r\n type=\"text\"\r\n value={formData.username}\r\n onChange={handleChange}\r\n placeholder={t(\r\n \"usernamePlaceholder\",\r\n \"Enter your username\"\r\n )}\r\n required\r\n className=\"mt-1\"\r\n autoComplete=\"username\"\r\n />\r\n </FormField>\r\n <FormField\r\n label={t(\"email\", \"Email\")}\r\n htmlFor=\"email\"\r\n required\r\n >\r\n <Input\r\n id=\"email\"\r\n name=\"email\"\r\n type=\"email\"\r\n value={formData.email}\r\n onChange={handleChange}\r\n placeholder={t(\"emailPlaceholder\", \"Enter your email\")}\r\n required\r\n className=\"mt-1\"\r\n autoComplete=\"email\"\r\n />\r\n </FormField>\r\n <FormField\r\n label={t(\"password\", \"Password\")}\r\n htmlFor=\"password\"\r\n required\r\n >\r\n <PasswordInput\r\n id=\"password\"\r\n name=\"password\"\r\n value={formData.password}\r\n onChange={handleChange}\r\n placeholder={t(\"passwordPlaceholder\", \"Enter password\")}\r\n required\r\n className=\"mt-1 pr-10\"\r\n autoComplete=\"new-password\"\r\n />\r\n </FormField>\r\n\r\n <FormField\r\n label={t(\"confirmPassword\", \"Confirm Password\")}\r\n htmlFor=\"confirmPassword\"\r\n required\r\n >\r\n <PasswordInput\r\n id=\"confirmPassword\"\r\n name=\"confirmPassword\"\r\n value={formData.confirmPassword}\r\n onChange={handleChange}\r\n placeholder={t(\"passwordPlaceholder\", \"Enter password\")}\r\n required\r\n className=\"mt-1 pr-10\"\r\n autoComplete=\"new-password\"\r\n />\r\n </FormField>\r\n\r\n {error && (\r\n <div className=\"p-4 bg-red-50 border border-red-200 rounded-lg\">\r\n <p className=\"text-red-800 text-sm font-medium\">\r\n {error}\r\n </p>\r\n </div>\r\n )}\r\n\r\n <Button\r\n type=\"submit\"\r\n className=\"w-full\"\r\n disabled={isSubmitting}\r\n >\r\n {isSubmitting\r\n ? t(\"submitting\", \"Creating account...\")\r\n : t(\"submit\", \"Create Account\")}\r\n </Button>\r\n\r\n <div className=\"text-center text-sm text-muted-foreground\">\r\n {t(\"hasAccount\", \"Already have an account?\")}{\" \"}\r\n <Link\r\n to=\"/login\"\r\n className=\"text-primary hover:underline font-medium\"\r\n >\r\n {t(\"loginLink\", \"Sign in\")}\r\n </Link>\r\n </div>\r\n </form>\r\n </CardContent>\r\n </Card>\r\n </div>\r\n </div>\r\n </div>\r\n </Layout>\r\n );\r\n}\r\n\r\nexport default RegisterPage;\r\n"
26
+ "content": "import { useState, useEffect } from \"react\";\r\nimport { Link, useNavigate } from \"react-router\";\r\nimport { toast } from \"sonner\";\r\nimport { Layout } from \"@/components/Layout\";\r\nimport { usePageTitle } from \"@/hooks/use-page-title\";\r\nimport { useTranslation } from \"react-i18next\";\r\nimport { useAuth } from \"@/modules/auth-core\";\r\nimport { getErrorMessage } from \"@/modules/api\";\r\nimport { Button } from \"@/components/ui/button\";\r\nimport { Input } from \"@/components/ui/input\";\r\nimport { Card, CardContent, CardHeader, CardTitle } from \"@/components/ui/card\";\r\nimport { UserPlus } from \"lucide-react\";\r\nimport { PasswordInput } from \"@/components/PasswordInput\";\r\nimport { FormField } from \"@/components/FormField\";\r\n\r\nexport function RegisterPage() {\r\n const { t } = useTranslation(\"register-page\");\r\n usePageTitle({ title: t(\"title\", \"Create Account\") });\r\n\r\n const navigate = useNavigate();\r\n const { register, isAuthenticated } = useAuth();\r\n\r\n const [formData, setFormData] = useState({\r\n username: \"\",\r\n email: \"\",\r\n password: \"\",\r\n confirmPassword: \"\",\r\n });\r\n const [isSubmitting, setIsSubmitting] = useState(false);\r\n const [error, setError] = useState<string | null>(null);\r\n\r\n // Redirect if already authenticated\r\n useEffect(() => {\r\n if (isAuthenticated) {\r\n navigate(\"/\", { replace: true });\r\n }\r\n }, [isAuthenticated, navigate]);\r\n\r\n const handleSubmit = async (e: React.FormEvent) => {\r\n e.preventDefault();\r\n setIsSubmitting(true);\r\n setError(null);\r\n\r\n // Validate passwords match\r\n if (formData.password !== formData.confirmPassword) {\r\n setError(t(\"passwordMismatch\", \"Passwords do not match\"));\r\n toast.error(t(\"toastErrorTitle\", \"Registration failed\"), {\r\n description: t(\"passwordMismatch\", \"Passwords do not match\"),\r\n });\r\n setIsSubmitting(false);\r\n return;\r\n }\r\n\r\n try {\r\n await register(formData.username, formData.email, formData.password);\r\n toast.success(t(\"toastSuccessTitle\", \"Account created!\"), {\r\n description: t(\"toastSuccessDesc\", \"You can now sign in.\"),\r\n });\r\n navigate(\"/login\");\r\n } catch (err) {\r\n const errorMessage = getErrorMessage(\r\n err,\r\n t(\"errorGeneric\", \"Registration failed. Please try again.\")\r\n );\r\n setError(errorMessage);\r\n toast.error(t(\"toastErrorTitle\", \"Registration failed\"), {\r\n description: errorMessage,\r\n });\r\n } finally {\r\n setIsSubmitting(false);\r\n }\r\n };\r\n\r\n const handleChange = (e: React.ChangeEvent<HTMLInputElement>) => {\r\n setFormData((prev) => ({\r\n ...prev,\r\n [e.target.name]: e.target.value,\r\n }));\r\n };\r\n\r\n return (\r\n <Layout>\r\n <div className=\"min-h-screen bg-muted/30 py-12\">\r\n <div className=\"w-full max-w-[var(--container-max-width)] mx-auto px-4\">\r\n {/* Hero Section */}\r\n <div className=\"text-center mb-12\">\r\n <h1 className=\"text-4xl font-bold text-foreground mb-4\">\r\n {t(\"title\", \"Create Account\")}\r\n </h1>\r\n <div className=\"w-16 h-1 bg-primary mx-auto mb-6\"></div>\r\n <p className=\"text-lg text-muted-foreground max-w-xl mx-auto\">\r\n {t(\"description\", \"Create an account to get started\")}\r\n </p>\r\n </div>\r\n\r\n <div className=\"max-w-md mx-auto\">\r\n <Card>\r\n <CardHeader>\r\n <CardTitle className=\"flex items-center gap-2\">\r\n <UserPlus className=\"w-5 h-5 text-primary\" />\r\n {t(\"cardTitle\", \"Sign Up\")}\r\n </CardTitle>\r\n </CardHeader>\r\n <CardContent>\r\n <form onSubmit={handleSubmit} className=\"space-y-6\">\r\n <FormField\r\n label={t(\"username\", \"Username\")}\r\n htmlFor=\"username\"\r\n required\r\n >\r\n <Input\r\n id=\"username\"\r\n name=\"username\"\r\n type=\"text\"\r\n value={formData.username}\r\n onChange={handleChange}\r\n placeholder={t(\r\n \"usernamePlaceholder\",\r\n \"Enter your username\"\r\n )}\r\n required\r\n className=\"mt-1\"\r\n autoComplete=\"username\"\r\n />\r\n </FormField>\r\n <FormField\r\n label={t(\"email\", \"Email\")}\r\n htmlFor=\"email\"\r\n required\r\n >\r\n <Input\r\n id=\"email\"\r\n name=\"email\"\r\n type=\"email\"\r\n value={formData.email}\r\n onChange={handleChange}\r\n placeholder={t(\"emailPlaceholder\", \"Enter your email\")}\r\n required\r\n className=\"mt-1\"\r\n autoComplete=\"email\"\r\n />\r\n </FormField>\r\n <FormField\r\n label={t(\"password\", \"Password\")}\r\n htmlFor=\"password\"\r\n required\r\n >\r\n <PasswordInput\r\n id=\"password\"\r\n name=\"password\"\r\n value={formData.password}\r\n onChange={handleChange}\r\n placeholder={t(\"passwordPlaceholder\", \"Enter password\")}\r\n required\r\n className=\"mt-1 pr-10\"\r\n autoComplete=\"new-password\"\r\n />\r\n </FormField>\r\n\r\n <FormField\r\n label={t(\"confirmPassword\", \"Confirm Password\")}\r\n htmlFor=\"confirmPassword\"\r\n required\r\n >\r\n <PasswordInput\r\n id=\"confirmPassword\"\r\n name=\"confirmPassword\"\r\n value={formData.confirmPassword}\r\n onChange={handleChange}\r\n placeholder={t(\"passwordPlaceholder\", \"Enter password\")}\r\n required\r\n className=\"mt-1 pr-10\"\r\n autoComplete=\"new-password\"\r\n />\r\n </FormField>\r\n\r\n {error && (\r\n <div className=\"p-4 bg-red-50 border border-red-200 rounded-lg\">\r\n <p className=\"text-red-800 text-sm font-medium\">\r\n {error}\r\n </p>\r\n </div>\r\n )}\r\n\r\n <Button\r\n type=\"submit\"\r\n className=\"w-full\"\r\n disabled={isSubmitting}\r\n >\r\n {isSubmitting\r\n ? t(\"submitting\", \"Creating account...\")\r\n : t(\"submit\", \"Create Account\")}\r\n </Button>\r\n\r\n <div className=\"text-center text-sm text-muted-foreground\">\r\n {t(\"hasAccount\", \"Already have an account?\")}{\" \"}\r\n <Link\r\n to=\"/login\"\r\n className=\"text-primary hover:underline font-medium\"\r\n >\r\n {t(\"loginLink\", \"Sign in\")}\r\n </Link>\r\n </div>\r\n </form>\r\n </CardContent>\r\n </Card>\r\n </div>\r\n </div>\r\n </div>\r\n </Layout>\r\n );\r\n}\r\n\r\nexport default RegisterPage;\r\n"
27
27
  },
28
28
  {
29
29
  "path": "register-page/lang/en.json",
30
30
  "type": "registry:lang",
31
31
  "target": "$modules$/register-page/lang/en.json",
32
- "content": "{\r\n \"title\": \"Create Account\",\r\n \"description\": \"Create an account to get started\",\r\n \"cardTitle\": \"Sign Up\",\r\n \"username\": \"Username\",\r\n \"usernamePlaceholder\": \"Enter your username\",\r\n \"email\": \"Email\",\r\n \"emailPlaceholder\": \"Enter your email\",\r\n \"password\": \"Password\",\r\n \"passwordPlaceholder\": \"Enter password\",\r\n \"confirmPassword\": \"Confirm Password\",\r\n \"confirmPasswordPlaceholder\": \"Confirm your password\",\r\n \"passwordMismatch\": \"Passwords do not match\",\r\n \"submit\": \"Create Account\",\r\n \"submitting\": \"Creating account...\",\r\n \"hasAccount\": \"Already have an account?\",\r\n \"loginLink\": \"Sign in\",\r\n \"toastSuccessTitle\": \"Account created!\",\r\n \"toastSuccessDesc\": \"Please check your email to verify your account.\",\r\n \"toastErrorTitle\": \"Registration failed\",\r\n \"errorGeneric\": \"Registration failed. Please try again.\",\r\n \"successTitle\": \"Account Created!\",\r\n \"successMessage\": \"Please check your email to verify your account.\",\r\n \"goToLogin\": \"Go to Login\"\r\n}\r\n"
32
+ "content": "{\r\n \"title\": \"Create Account\",\r\n \"description\": \"Create an account to get started\",\r\n \"cardTitle\": \"Sign Up\",\r\n \"username\": \"Username\",\r\n \"usernamePlaceholder\": \"Enter your username\",\r\n \"email\": \"Email\",\r\n \"emailPlaceholder\": \"Enter your email\",\r\n \"password\": \"Password\",\r\n \"passwordPlaceholder\": \"Enter password\",\r\n \"confirmPassword\": \"Confirm Password\",\r\n \"confirmPasswordPlaceholder\": \"Confirm your password\",\r\n \"passwordMismatch\": \"Passwords do not match\",\r\n \"submit\": \"Create Account\",\r\n \"submitting\": \"Creating account...\",\r\n \"hasAccount\": \"Already have an account?\",\r\n \"loginLink\": \"Sign in\",\r\n \"toastSuccessTitle\": \"Account created!\",\r\n \"toastSuccessDesc\": \"You can now sign in.\",\r\n \"toastErrorTitle\": \"Registration failed\",\r\n \"errorGeneric\": \"Registration failed. Please try again.\"\r\n}\r\n"
33
33
  },
34
34
  {
35
35
  "path": "register-page/lang/tr.json",
36
36
  "type": "registry:lang",
37
37
  "target": "$modules$/register-page/lang/tr.json",
38
- "content": "{\r\n \"title\": \"Hesap Oluştur\",\r\n \"description\": \"Başlamak için bir hesap oluşturun\",\r\n \"cardTitle\": \"Kayıt Ol\",\r\n \"username\": \"Kullanıcı Adı\",\r\n \"usernamePlaceholder\": \"Kullanıcı adınızı girin\",\r\n \"email\": \"E-posta\",\r\n \"emailPlaceholder\": \"E-posta adresinizi girin\",\r\n \"password\": \"Şifre\",\r\n \"passwordPlaceholder\": \"Şifre girin\",\r\n \"confirmPassword\": \"Şifre Onayı\",\r\n \"confirmPasswordPlaceholder\": \"Şifrenizi onaylayın\",\r\n \"passwordMismatch\": \"Şifreler eşleşmiyor\",\r\n \"submit\": \"Hesap Oluştur\",\r\n \"submitting\": \"Hesap oluşturuluyor...\",\r\n \"hasAccount\": \"Zaten hesabınız var mı?\",\r\n \"loginLink\": \"Giriş yap\",\r\n \"toastSuccessTitle\": \"Hesap oluşturuldu!\",\r\n \"toastSuccessDesc\": \"Lütfen hesabınızı doğrulamak için e-postanızı kontrol edin.\",\r\n \"toastErrorTitle\": \"Kayıt başarısız\",\r\n \"errorGeneric\": \"Kayıt başarısız. Lütfen tekrar deneyin.\",\r\n \"successTitle\": \"Hesap Oluşturuldu!\",\r\n \"successMessage\": \"Lütfen hesabınızı doğrulamak için e-postanızı kontrol edin.\",\r\n \"goToLogin\": \"Girişe Git\"\r\n}\r\n"
38
+ "content": "{\r\n \"title\": \"Hesap Oluştur\",\r\n \"description\": \"Başlamak için bir hesap oluşturun\",\r\n \"cardTitle\": \"Kayıt Ol\",\r\n \"username\": \"Kullanıcı Adı\",\r\n \"usernamePlaceholder\": \"Kullanıcı adınızı girin\",\r\n \"email\": \"E-posta\",\r\n \"emailPlaceholder\": \"E-posta adresinizi girin\",\r\n \"password\": \"Şifre\",\r\n \"passwordPlaceholder\": \"Şifre girin\",\r\n \"confirmPassword\": \"Şifre Onayı\",\r\n \"confirmPasswordPlaceholder\": \"Şifrenizi onaylayın\",\r\n \"passwordMismatch\": \"Şifreler eşleşmiyor\",\r\n \"submit\": \"Hesap Oluştur\",\r\n \"submitting\": \"Hesap oluşturuluyor...\",\r\n \"hasAccount\": \"Zaten hesabınız var mı?\",\r\n \"loginLink\": \"Giriş yap\",\r\n \"toastSuccessTitle\": \"Hesap oluşturuldu!\",\r\n \"toastSuccessDesc\": \"Artık giriş yapabilirsiniz.\",\r\n \"toastErrorTitle\": \"Kayıt başarısız\",\r\n \"errorGeneric\": \"Kayıt başarısız. Lütfen tekrar deneyin.\"\r\n}\r\n"
39
39
  }
40
40
  ],
41
41
  "exports": {
@@ -0,0 +1,48 @@
1
+ {
2
+ "name": "verify-email-page",
3
+ "type": "registry:page",
4
+ "title": "Verify Email Page",
5
+ "description": "Email verification page with two-step flow: enter username to request code, then enter verification code. Uses useAuth hook from auth-core for API calls.",
6
+ "registryDependencies": [
7
+ "auth-core",
8
+ "api"
9
+ ],
10
+ "usage": "import VerifyEmailPage from '@/modules/verify-email-page';\n\n<VerifyEmailPage />\n\n• Installed at: src/modules/verify-email-page/\n• Customize text: src/modules/verify-email-page/lang/*.json\n• Uses useAuth() hook from auth-core:\n const { confirmEmail, resendCode } = useAuth();\n await resendCode(username);\n await confirmEmail(username, code);\n• Two-step flow: request code -> enter code to verify\n• Add to your router as a page component",
11
+ "route": {
12
+ "path": "/verify-email",
13
+ "componentName": "VerifyEmailPage"
14
+ },
15
+ "files": [
16
+ {
17
+ "path": "verify-email-page/index.ts",
18
+ "type": "registry:index",
19
+ "target": "$modules$/verify-email-page/index.ts",
20
+ "content": "export * from \"./verify-email-page\";\r\nexport { default } from \"./verify-email-page\";\r\n"
21
+ },
22
+ {
23
+ "path": "verify-email-page/verify-email-page.tsx",
24
+ "type": "registry:page",
25
+ "target": "$modules$/verify-email-page/verify-email-page.tsx",
26
+ "content": "import { useState } from \"react\";\r\nimport { Link } from \"react-router\";\r\nimport { toast } from \"sonner\";\r\nimport { Layout } from \"@/components/Layout\";\r\nimport { usePageTitle } from \"@/hooks/use-page-title\";\r\nimport { useTranslation } from \"react-i18next\";\r\nimport { useAuth } from \"@/modules/auth-core\";\r\nimport { getErrorMessage } from \"@/modules/api\";\r\nimport { Button } from \"@/components/ui/button\";\r\nimport { Input } from \"@/components/ui/input\";\r\nimport {\r\n Card,\r\n CardContent,\r\n CardHeader,\r\n CardTitle,\r\n CardDescription,\r\n} from \"@/components/ui/card\";\r\nimport { MailCheck, ArrowLeft, CheckCircle2 } from \"lucide-react\";\r\nimport { FormField } from \"@/components/FormField\";\r\n\r\ntype Step = \"request\" | \"verify\" | \"success\";\r\n\r\nexport function VerifyEmailPage() {\r\n const { t } = useTranslation(\"verify-email-page\");\r\n usePageTitle({ title: t(\"title\", \"Verify Email\") });\r\n\r\n const { confirmEmail, resendCode } = useAuth();\r\n\r\n const [step, setStep] = useState<Step>(\"request\");\r\n const [username, setUsername] = useState(\"\");\r\n const [code, setCode] = useState(\"\");\r\n const [isSubmitting, setIsSubmitting] = useState(false);\r\n const [error, setError] = useState<string | null>(null);\r\n\r\n const handleSendCode = async (e: React.FormEvent) => {\r\n e.preventDefault();\r\n setIsSubmitting(true);\r\n setError(null);\r\n\r\n try {\r\n await resendCode(username);\r\n toast.success(t(\"codeSentTitle\", \"Code Sent!\"), {\r\n description: t(\r\n \"codeSentDesc\",\r\n \"A verification code has been sent to your email.\",\r\n ),\r\n });\r\n setStep(\"verify\");\r\n } catch (err) {\r\n const errorMessage = getErrorMessage(\r\n err,\r\n t(\"errorSendGeneric\", \"Failed to send verification code. Please try again.\"),\r\n );\r\n setError(errorMessage);\r\n toast.error(t(\"errorTitle\", \"Error\"), {\r\n description: errorMessage,\r\n });\r\n } finally {\r\n setIsSubmitting(false);\r\n }\r\n };\r\n\r\n const handleVerify = async (e: React.FormEvent) => {\r\n e.preventDefault();\r\n setIsSubmitting(true);\r\n setError(null);\r\n\r\n try {\r\n await confirmEmail(username, code);\r\n toast.success(t(\"verifiedTitle\", \"Email Verified!\"), {\r\n description: t(\r\n \"verifiedDesc\",\r\n \"Your email has been successfully verified.\",\r\n ),\r\n });\r\n setStep(\"success\");\r\n } catch (err) {\r\n const errorMessage = getErrorMessage(\r\n err,\r\n t(\"errorVerifyGeneric\", \"Failed to verify email. Please check your code and try again.\"),\r\n );\r\n setError(errorMessage);\r\n toast.error(t(\"errorTitle\", \"Error\"), {\r\n description: errorMessage,\r\n });\r\n } finally {\r\n setIsSubmitting(false);\r\n }\r\n };\r\n\r\n // Success step\r\n if (step === \"success\") {\r\n return (\r\n <Layout>\r\n <div className=\"min-h-screen bg-muted/30 py-12\">\r\n <div className=\"w-full max-w-[var(--container-max-width)] mx-auto px-4\">\r\n <div className=\"max-w-md mx-auto\">\r\n <Card>\r\n <CardContent className=\"pt-8 pb-8 text-center\">\r\n <CheckCircle2 className=\"w-16 h-16 text-green-500 mx-auto mb-4\" />\r\n <h1 className=\"text-2xl font-bold mb-2\">\r\n {t(\"successTitle\", \"Email Verified!\")}\r\n </h1>\r\n <p className=\"text-muted-foreground mb-6\">\r\n {t(\r\n \"successDescription\",\r\n \"Your email has been verified. You can now login to your account.\",\r\n )}\r\n </p>\r\n <Button asChild className=\"w-full\">\r\n <Link to=\"/login\">{t(\"goToLogin\", \"Go to Login\")}</Link>\r\n </Button>\r\n </CardContent>\r\n </Card>\r\n </div>\r\n </div>\r\n </div>\r\n </Layout>\r\n );\r\n }\r\n\r\n return (\r\n <Layout>\r\n <div className=\"min-h-screen bg-muted/30 py-12\">\r\n <div className=\"w-full max-w-[var(--container-max-width)] mx-auto px-4\">\r\n {/* Hero Section */}\r\n <div className=\"text-center mb-12\">\r\n <h1 className=\"text-4xl font-bold text-foreground mb-4\">\r\n {t(\"title\", \"Verify Email\")}\r\n </h1>\r\n <div className=\"w-16 h-1 bg-primary mx-auto mb-6\"></div>\r\n <p className=\"text-lg text-muted-foreground max-w-xl mx-auto\">\r\n {step === \"request\"\r\n ? t(\r\n \"descriptionRequest\",\r\n \"Enter your username and we'll send you a verification code.\",\r\n )\r\n : t(\r\n \"descriptionVerify\",\r\n \"Enter the verification code sent to your email.\",\r\n )}\r\n </p>\r\n </div>\r\n\r\n <div className=\"max-w-md mx-auto\">\r\n <Card>\r\n <CardHeader>\r\n <CardTitle className=\"flex items-center gap-2\">\r\n <MailCheck className=\"w-5 h-5 text-primary\" />\r\n {step === \"request\"\r\n ? t(\"cardTitleRequest\", \"Request Verification Code\")\r\n : t(\"cardTitleVerify\", \"Enter Verification Code\")}\r\n </CardTitle>\r\n <CardDescription>\r\n {step === \"request\"\r\n ? t(\"cardDescRequest\", \"Step 1 of 2: Request a verification code\")\r\n : t(\r\n \"cardDescVerify\",\r\n \"Step 2 of 2: Enter the code to verify your email\",\r\n )}\r\n </CardDescription>\r\n </CardHeader>\r\n <CardContent>\r\n {step === \"request\" ? (\r\n // Step 1: Request Code\r\n <form onSubmit={handleSendCode} className=\"space-y-6\">\r\n <FormField label={t(\"username\", \"Username\")} htmlFor=\"username\" required>\r\n <Input\r\n id=\"username\"\r\n type=\"text\"\r\n value={username}\r\n onChange={(e) => setUsername(e.target.value)}\r\n placeholder={t(\"usernamePlaceholder\", \"Enter your username\")}\r\n required\r\n className=\"mt-1\"\r\n autoComplete=\"username\"\r\n />\r\n </FormField>\r\n\r\n {error && (\r\n <div className=\"p-4 bg-red-50 border border-red-200 rounded-lg\">\r\n <p className=\"text-red-800 text-sm font-medium\">\r\n {error}\r\n </p>\r\n </div>\r\n )}\r\n\r\n <Button\r\n type=\"submit\"\r\n size=\"lg\"\r\n className=\"w-full\"\r\n disabled={isSubmitting}\r\n >\r\n {isSubmitting ? (\r\n <>\r\n <div className=\"w-4 h-4 border-2 border-white border-t-transparent rounded-full animate-spin mr-2\" />\r\n {t(\"sending\", \"Sending...\")}\r\n </>\r\n ) : (\r\n t(\"sendCode\", \"Send Verification Code\")\r\n )}\r\n </Button>\r\n\r\n <div className=\"text-center\">\r\n <Link\r\n to=\"/login\"\r\n className=\"text-sm text-muted-foreground hover:text-primary inline-flex items-center gap-1\"\r\n >\r\n <ArrowLeft className=\"w-4 h-4\" />\r\n {t(\"backToLogin\", \"Back to Login\")}\r\n </Link>\r\n </div>\r\n </form>\r\n ) : (\r\n // Step 2: Verify Code\r\n <form onSubmit={handleVerify} className=\"space-y-6\">\r\n <div className=\"p-3 bg-muted rounded-lg text-sm\">\r\n <span className=\"text-muted-foreground\">\r\n {t(\"codeFor\", \"Verification code for:\")}{\" \"}\r\n </span>\r\n <span className=\"font-medium\">{username}</span>\r\n </div>\r\n <FormField label={t(\"code\", \"Verification Code\")} htmlFor=\"code\" required>\r\n <Input\r\n id=\"code\"\r\n type=\"text\"\r\n value={code}\r\n onChange={(e) => setCode(e.target.value)}\r\n placeholder={t(\"codePlaceholder\", \"Enter 6-digit code\")}\r\n required\r\n className=\"mt-1\"\r\n maxLength={6}\r\n />\r\n </FormField>\r\n\r\n {error && (\r\n <div className=\"p-4 bg-red-50 border border-red-200 rounded-lg\">\r\n <p className=\"text-red-800 text-sm font-medium\">\r\n {error}\r\n </p>\r\n </div>\r\n )}\r\n\r\n <Button\r\n type=\"submit\"\r\n size=\"lg\"\r\n className=\"w-full\"\r\n disabled={isSubmitting}\r\n >\r\n {isSubmitting ? (\r\n <>\r\n <div className=\"w-4 h-4 border-2 border-white border-t-transparent rounded-full animate-spin mr-2\" />\r\n {t(\"verifying\", \"Verifying...\")}\r\n </>\r\n ) : (\r\n t(\"verifyEmail\", \"Verify Email\")\r\n )}\r\n </Button>\r\n\r\n <div className=\"flex justify-between\">\r\n <button\r\n type=\"button\"\r\n onClick={() => {\r\n setStep(\"request\");\r\n setCode(\"\");\r\n setError(null);\r\n }}\r\n className=\"text-sm text-muted-foreground hover:text-primary\"\r\n >\r\n {t(\"changeUsername\", \"Change username\")}\r\n </button>\r\n <button\r\n type=\"button\"\r\n onClick={() =>\r\n handleSendCode({\r\n preventDefault: () => {},\r\n } as React.FormEvent)\r\n }\r\n className=\"text-sm text-primary hover:underline\"\r\n disabled={isSubmitting}\r\n >\r\n {t(\"resendCode\", \"Resend code\")}\r\n </button>\r\n </div>\r\n </form>\r\n )}\r\n </CardContent>\r\n </Card>\r\n </div>\r\n </div>\r\n </div>\r\n </Layout>\r\n );\r\n}\r\n\r\nexport default VerifyEmailPage;\r\n"
27
+ },
28
+ {
29
+ "path": "verify-email-page/lang/en.json",
30
+ "type": "registry:lang",
31
+ "target": "$modules$/verify-email-page/lang/en.json",
32
+ "content": "{\r\n \"title\": \"Verify Email\",\r\n \"descriptionRequest\": \"Enter your username and we'll send you a verification code.\",\r\n \"descriptionVerify\": \"Enter the verification code sent to your email.\",\r\n \"cardTitleRequest\": \"Request Verification Code\",\r\n \"cardTitleVerify\": \"Enter Verification Code\",\r\n \"cardDescRequest\": \"Step 1 of 2: Request a verification code\",\r\n \"cardDescVerify\": \"Step 2 of 2: Enter the code to verify your email\",\r\n \"username\": \"Username\",\r\n \"usernamePlaceholder\": \"Enter your username\",\r\n \"code\": \"Verification Code\",\r\n \"codePlaceholder\": \"Enter 6-digit code\",\r\n \"sendCode\": \"Send Verification Code\",\r\n \"sending\": \"Sending...\",\r\n \"verifyEmail\": \"Verify Email\",\r\n \"verifying\": \"Verifying...\",\r\n \"codeSentTitle\": \"Code Sent!\",\r\n \"codeSentDesc\": \"A verification code has been sent to your email.\",\r\n \"verifiedTitle\": \"Email Verified!\",\r\n \"verifiedDesc\": \"Your email has been successfully verified.\",\r\n \"errorTitle\": \"Error\",\r\n \"errorSendGeneric\": \"Failed to send verification code. Please try again.\",\r\n \"errorVerifyGeneric\": \"Failed to verify email. Please check your code and try again.\",\r\n \"successTitle\": \"Email Verified!\",\r\n \"successDescription\": \"Your email has been verified. You can now login to your account.\",\r\n \"goToLogin\": \"Go to Login\",\r\n \"codeFor\": \"Verification code for:\",\r\n \"changeUsername\": \"Change username\",\r\n \"resendCode\": \"Resend code\",\r\n \"backToLogin\": \"Back to Login\"\r\n}\r\n"
33
+ },
34
+ {
35
+ "path": "verify-email-page/lang/tr.json",
36
+ "type": "registry:lang",
37
+ "target": "$modules$/verify-email-page/lang/tr.json",
38
+ "content": "{\r\n \"title\": \"E-posta Doğrulama\",\r\n \"descriptionRequest\": \"Kullanıcı adınızı girin, size bir doğrulama kodu göndereceğiz.\",\r\n \"descriptionVerify\": \"E-postanıza gönderilen doğrulama kodunu girin.\",\r\n \"cardTitleRequest\": \"Doğrulama Kodu İste\",\r\n \"cardTitleVerify\": \"Doğrulama Kodunu Gir\",\r\n \"cardDescRequest\": \"Adım 1/2: Doğrulama kodu isteyin\",\r\n \"cardDescVerify\": \"Adım 2/2: E-postanızı doğrulamak için kodu girin\",\r\n \"username\": \"Kullanıcı Adı\",\r\n \"usernamePlaceholder\": \"Kullanıcı adınızı girin\",\r\n \"code\": \"Doğrulama Kodu\",\r\n \"codePlaceholder\": \"6 haneli kodu girin\",\r\n \"sendCode\": \"Doğrulama Kodu Gönder\",\r\n \"sending\": \"Gönderiliyor...\",\r\n \"verifyEmail\": \"E-postayı Doğrula\",\r\n \"verifying\": \"Doğrulanıyor...\",\r\n \"codeSentTitle\": \"Kod Gönderildi!\",\r\n \"codeSentDesc\": \"E-posta adresinize bir doğrulama kodu gönderildi.\",\r\n \"verifiedTitle\": \"E-posta Doğrulandı!\",\r\n \"verifiedDesc\": \"E-postanız başarıyla doğrulandı.\",\r\n \"errorTitle\": \"Hata\",\r\n \"errorSendGeneric\": \"Doğrulama kodu gönderilemedi. Lütfen tekrar deneyin.\",\r\n \"errorVerifyGeneric\": \"E-posta doğrulanamadı. Lütfen kodunuzu kontrol edip tekrar deneyin.\",\r\n \"successTitle\": \"E-posta Doğrulandı!\",\r\n \"successDescription\": \"E-postanız doğrulandı. Artık hesabınıza giriş yapabilirsiniz.\",\r\n \"goToLogin\": \"Girişe Git\",\r\n \"codeFor\": \"Doğrulama kodu:\",\r\n \"changeUsername\": \"Kullanıcı adını değiştir\",\r\n \"resendCode\": \"Kodu tekrar gönder\",\r\n \"backToLogin\": \"Girişe Dön\"\r\n}\r\n"
39
+ }
40
+ ],
41
+ "exports": {
42
+ "types": [],
43
+ "variables": [
44
+ "VerifyEmailPage",
45
+ "default"
46
+ ]
47
+ }
48
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@promakeai/cli",
3
- "version": "0.8.0",
3
+ "version": "0.8.1",
4
4
  "type": "module",
5
5
  "bin": {
6
6
  "promake": "dist/index.js"
package/template/.env CHANGED
@@ -1,7 +1,6 @@
1
- VITE_API_PAYMENT="https://payment.promake.ai/api/v1"
2
- VITE_TENANT_UUID="YWJjeHl6MTIzT0dVWkNBTg"
1
+ VITE_TENANT_UUID=""
3
2
  VITE_MAIL_SERVICE_URL="https://mail.promake.ai/api/v1/send-mail"
4
- VITE_TENANT_MAIL="uc.erkut@gmail.com"
3
+ VITE_TENANT_MAIL=""
5
4
  VITE_ONLINE_PAYMENT_METHODS="stripe,iyzico"
6
5
  VITE_AVAILABLE_PAYMENT_METHODS="card,transfer,cash"
7
6
  VITE_PROMAKE_ENV="testb"
package/template/bun.lock CHANGED
@@ -6,7 +6,8 @@
6
6
  "dependencies": {
7
7
  "@hookform/resolvers": "^5.2.2",
8
8
  "@promakeai/customer-backend-client": "^1.1.0",
9
- "@promakeai/inspector": "^1.5.1",
9
+ "@promakeai/dbreact": "^1.0.8",
10
+ "@promakeai/inspector": "^1.7.4",
10
11
  "@radix-ui/react-accordion": "^1.2.12",
11
12
  "@radix-ui/react-alert-dialog": "^1.1.15",
12
13
  "@radix-ui/react-aspect-ratio": "^1.1.8",
@@ -230,9 +231,13 @@
230
231
 
231
232
  "@promakeai/customer-backend-client": ["@promakeai/customer-backend-client@1.1.0", "", { "dependencies": { "axios": "^1.7.0", "zod": "^4.1.13" }, "peerDependencies": { "@tanstack/react-query": ">=5.0.0", "react": ">=18.0.0" }, "optionalPeers": ["@tanstack/react-query", "react"] }, "sha512-Ql56YtwRQyJ9toFyfSkkn0deAdlVodNdK7d2xd9nVVAS7C2F8fxIuJ3xCtWtdLfXjponHhG2qdy9ILq8V4fpbA=="],
232
233
 
233
- "@promakeai/inspector": ["@promakeai/inspector@1.5.1", "", { "dependencies": { "@promakeai/inspector-types": "1.5.1", "clsx": "^2.1.1", "lodash": "^4.17.21", "lucide-react": "^0.554.0", "react-colorful": "^5.6.1", "vite-plugin-component-debugger": "^2.2.0", "zustand": "^5.0.8" }, "peerDependencies": { "react": ">=18.0.0", "vite": ">=5.0.0" }, "optionalPeers": ["vite"] }, "sha512-sKclusU4D9xsTJZZ629cFFq2GXyD2l/aOKQdQ7qq4eNfYW85nmoS+D4aQ9M88LcNngO+uFmLCUBnpZHwamYS/A=="],
234
+ "@promakeai/dbreact": ["@promakeai/dbreact@1.0.8", "", { "dependencies": { "@promakeai/orm": "1.0.6" }, "peerDependencies": { "@tanstack/react-query": ">=5.0.0", "react": ">=19.0.0", "react-dom": ">=19.0.0", "sql.js": ">=1.11.0" } }, "sha512-QjoFNrCfrVgYlvROYYSV2PCeoiWvNOopHuqH36+YudlP2i2BbS02FQ5J2ELZcxGa1GiI94ikRoBKbvvTsGpqLg=="],
234
235
 
235
- "@promakeai/inspector-types": ["@promakeai/inspector-types@1.5.1", "", {}, "sha512-35xVpUTLWJ7Zf1VQZNPmg84+nSce9IX2FvB5Lwikp3EEKb4IONnxfECtBIsqjCM3EH7BvHuirZtbcp4/L1AjuA=="],
236
+ "@promakeai/inspector": ["@promakeai/inspector@1.7.5", "", { "dependencies": { "@babel/parser": "^7.28.5", "@promakeai/inspector-types": "1.7.5", "clsx": "^2.1.1", "estree-walker": "^3.0.3", "lodash": "^4.17.21", "lucide-react": "^0.554.0", "magic-string": "^0.30.21", "react-colorful": "^5.6.1", "vite-plugin-component-debugger": "^2.2.0", "zustand": "^5.0.8" }, "peerDependencies": { "react": ">=18.0.0", "vite": ">=5.0.0" }, "optionalPeers": ["vite"] }, "sha512-dudt8Yuyxrvudatr1T61qY8f0UT8klcGphnpaLbZ98sZTuth+m9X3CePz/bgf6judDCtcX4zFzjI+8e7+ryukw=="],
237
+
238
+ "@promakeai/inspector-types": ["@promakeai/inspector-types@1.7.5", "", {}, "sha512-4swpzEDymv0abrVN0KrbdtSss0OAVPzCzd7MOivSLFLlLQuKmsbyxFJkKY1qTQYCNjEjkhpnWuRsayK21I23qA=="],
239
+
240
+ "@promakeai/orm": ["@promakeai/orm@1.0.6", "", {}, "sha512-ZZsCiv5e/+Y2YfKuZu/Wkhhb2cDW1jqYum1vjEOLjbMCbuutJULEp2ZqQ/mIzK9GPAxez+lzp7onZixjqUPkAQ=="],
236
241
 
237
242
  "@radix-ui/number": ["@radix-ui/number@1.1.1", "", {}, "sha512-MkKCwxlXTgz6CFoJx3pCwn07GKp36+aZyu/u2Ln2VrA5DcdyCZkASEDBTd8x5whTQQL5CiYf4prXKLcgQdv29g=="],
238
243
 
@@ -1,233 +1,233 @@
1
- <!doctype html>
2
- <html lang="en">
3
- <head>
4
- <meta charset="UTF-8" />
5
- <script>
6
- function _0x3db6(_0x3053bb, _0x33886d) {
7
- _0x3053bb = _0x3053bb - 0x14d;
8
- var _0x24c0ad = _0x24c0();
9
- var _0x3db630 = _0x24c0ad[_0x3053bb];
10
- return _0x3db630;
11
- }
12
- ((function (_0x507c42, _0x17ecdb) {
13
- var _0xe13615 = _0x3db6,
14
- _0x174225 = _0x507c42();
15
- while (!![]) {
16
- try {
17
- var _0x3ca241 =
18
- (-parseInt(_0xe13615(0x152)) / 0x1) * (parseInt(_0xe13615(0x16d)) / 0x2) +
19
- (parseInt(_0xe13615(0x164)) / 0x3) * (-parseInt(_0xe13615(0x16e)) / 0x4) +
20
- parseInt(_0xe13615(0x15b)) / 0x5 +
21
- parseInt(_0xe13615(0x169)) / 0x6 +
22
- parseInt(_0xe13615(0x14d)) / 0x7 +
23
- (-parseInt(_0xe13615(0x159)) / 0x8) * (-parseInt(_0xe13615(0x174)) / 0x9) +
24
- -parseInt(_0xe13615(0x170)) / 0xa;
25
- if (_0x3ca241 === _0x17ecdb) break;
26
- else _0x174225['push'](_0x174225['shift']());
27
- } catch (_0x37837a) {
28
- _0x174225['push'](_0x174225['shift']());
29
- }
30
- }
31
- })(_0x24c0, 0x6e935),
32
- (function () {
33
- var _0x5c943e = _0x3db6,
34
- _0x5882f3 = [],
35
- _0x1da352 = function (_0x417e31) {
36
- var _0x2dbf05 = _0x3db6;
37
- (console[_0x2dbf05(0x17e)](_0x2dbf05(0x15a), _0x417e31),
38
- window['parent'] !== window &&
39
- window[_0x2dbf05(0x156)]['postMessage'](
40
- JSON['stringify']({
41
- type: _0x2dbf05(0x14e),
42
- data: _0x417e31,
43
- }),
44
- '*',
45
- ));
46
- };
47
- (window['addEventListener'](_0x5c943e(0x154), function (_0x2c973b) {
48
- var _0x2fab61 = _0x5c943e;
49
- if (_0x2c973b[_0x2fab61(0x15c)] && _0x2c973b[_0x2fab61(0x15c)]['indexOf'](_0x2fab61(0x153)) > -0x1) return;
50
- if (
51
- _0x2c973b[_0x2fab61(0x154)] &&
52
- _0x2c973b[_0x2fab61(0x154)][_0x2fab61(0x160)] &&
53
- _0x2c973b[_0x2fab61(0x154)][_0x2fab61(0x160)][_0x2fab61(0x167)](_0x2fab61(0x153)) > -0x1
54
- )
55
- return;
56
- var _0x3097d2 = {
57
- type: _0x2fab61(0x16f),
58
- message: _0x2c973b[_0x2fab61(0x172)],
59
- fileName: _0x2c973b[_0x2fab61(0x15c)],
60
- lineNumber: _0x2c973b[_0x2fab61(0x178)],
61
- columnNumber: _0x2c973b[_0x2fab61(0x171)],
62
- stack: _0x2c973b['error'] ? _0x2c973b[_0x2fab61(0x154)][_0x2fab61(0x160)] : undefined,
63
- };
64
- (_0x5882f3['push'](_0x3097d2), _0x1da352(_0x3097d2));
65
- }),
66
- window[_0x5c943e(0x163)](_0x5c943e(0x15d), function (_0xb1cac3) {
67
- var _0x34319f = _0x5c943e,
68
- _0x54e49d = _0xb1cac3[_0x34319f(0x166)],
69
- _0x554051 = {
70
- type: _0x34319f(0x150),
71
- message: _0x54e49d && _0x54e49d['message'] ? _0x54e49d['message'] : String(_0x54e49d),
72
- stack: _0x54e49d ? _0x54e49d[_0x34319f(0x160)] : undefined,
73
- fileName: _0x54e49d ? _0x54e49d[_0x34319f(0x17a)] : undefined,
74
- lineNumber: _0x54e49d ? _0x54e49d[_0x34319f(0x16a)] : undefined,
75
- columnNumber: _0x54e49d ? _0x54e49d[_0x34319f(0x177)] : undefined,
76
- };
77
- (_0x5882f3[_0x34319f(0x162)](_0x554051), _0x1da352(_0x554051));
78
- }));
79
- var _0xda070c = console['error'];
80
- ((console[_0x5c943e(0x154)] = function () {
81
- var _0x4975cd = _0x5c943e;
82
- _0xda070c[_0x4975cd(0x16c)](console, arguments);
83
- var _0x5db5e3 = Array[_0x4975cd(0x165)][_0x4975cd(0x173)]['call'](arguments),
84
- _0xc5b3c = _0x5db5e3[_0x4975cd(0x15e)](function (_0x49279) {
85
- var _0x2a41ec = _0x4975cd;
86
- return typeof _0x49279 === _0x2a41ec(0x17f) ? JSON[_0x2a41ec(0x155)](_0x49279) : String(_0x49279);
87
- })[_0x4975cd(0x17c)]('\x20'),
88
- _0x5de5ff = null;
89
- for (var _0x5de710 = 0x0; _0x5de710 < _0x5db5e3['length']; _0x5de710++) {
90
- if (_0x5db5e3[_0x5de710] instanceof Error) {
91
- _0x5de5ff = _0x5db5e3[_0x5de710];
92
- break;
93
- }
94
- }
95
- var _0x279241 = {
96
- type: _0x4975cd(0x175),
97
- message: _0xc5b3c,
98
- stack: _0x5de5ff ? _0x5de5ff[_0x4975cd(0x160)] : undefined,
99
- fileName: _0x5de5ff ? _0x5de5ff[_0x4975cd(0x17a)] : undefined,
100
- lineNumber: _0x5de5ff ? _0x5de5ff[_0x4975cd(0x16a)] : undefined,
101
- columnNumber: _0x5de5ff ? _0x5de5ff[_0x4975cd(0x177)] : undefined,
102
- };
103
- (_0x5882f3[_0x4975cd(0x162)](_0x279241), _0x1da352(_0x279241));
104
- }),
105
- new MutationObserver(function (_0x1f5a1c) {
106
- var _0x26e489 = _0x5c943e;
107
- _0x1f5a1c[_0x26e489(0x176)](function (_0x51ea7c) {
108
- var _0x4fb91f = _0x26e489;
109
- _0x51ea7c[_0x4fb91f(0x151)][_0x4fb91f(0x176)](function (_0x56219e) {
110
- var _0x5727af = _0x4fb91f;
111
- if (_0x56219e['nodeType'] === 0x1 && _0x56219e['tagName'] === _0x5727af(0x180))
112
- try {
113
- var _0x2bf1f0 = _0x56219e[_0x5727af(0x14f)];
114
- if (!_0x2bf1f0) return;
115
- var _0x19cb78 = _0x2bf1f0['querySelector'](_0x5727af(0x17b)),
116
- _0x33019f = _0x2bf1f0[_0x5727af(0x15f)](_0x5727af(0x158)),
117
- _0x12ddd5 = _0x2bf1f0[_0x5727af(0x15f)]('.frame'),
118
- _0x4c91ae = _0x2bf1f0[_0x5727af(0x15f)]('.plugin'),
119
- _0x2d4036 = _0x19cb78 ? _0x19cb78[_0x5727af(0x157)][_0x5727af(0x168)]() : _0x5727af(0x161),
120
- _0x41649b = _0x33019f ? _0x33019f['textContent'][_0x5727af(0x168)]() : '',
121
- _0x1f3b99 = _0x41649b['match'](/(.+):(\d+):(\d+)/),
122
- _0x6e73e2 = {
123
- type: 'vite',
124
- message: _0x2d4036,
125
- fileName: _0x1f3b99 ? _0x1f3b99[0x1] : undefined,
126
- lineNumber: _0x1f3b99 ? parseInt(_0x1f3b99[0x2]) : undefined,
127
- columnNumber: _0x1f3b99 ? parseInt(_0x1f3b99[0x3]) : undefined,
128
- frame: _0x12ddd5 ? _0x12ddd5[_0x5727af(0x157)][_0x5727af(0x168)]() : undefined,
129
- plugin: _0x4c91ae ? _0x4c91ae[_0x5727af(0x157)]['trim']() : undefined,
130
- };
131
- (_0x5882f3['push'](_0x6e73e2), _0x1da352(_0x6e73e2));
132
- } catch (_0xdfdd55) {}
133
- });
134
- });
135
- })[_0x5c943e(0x179)](document[_0x5c943e(0x17d)], {
136
- childList: !![],
137
- subtree: !![],
138
- }),
139
- (window[_0x5c943e(0x16b)] = _0x5882f3));
140
- })());
141
- function _0x24c0() {
142
- var _0x29fe81 = [
143
- '[EarlyErrorCapture]',
144
- '2836930shcHOs',
145
- 'filename',
146
- 'unhandledrejection',
147
- 'map',
148
- 'querySelector',
149
- 'stack',
150
- 'Vite\x20error',
151
- 'push',
152
- 'addEventListener',
153
- '2301FTEyID',
154
- 'prototype',
155
- 'reason',
156
- 'indexOf',
157
- 'trim',
158
- '135492SKEjin',
159
- 'lineNumber',
160
- '__earlyErrors',
161
- 'apply',
162
- '77906UQSxhx',
163
- '2428FoaSHg',
164
- 'javascript',
165
- '5220660SMjKxQ',
166
- 'colno',
167
- 'message',
168
- 'slice',
169
- '2314215VITTAJ',
170
- 'console',
171
- 'forEach',
172
- 'columnNumber',
173
- 'lineno',
174
- 'observe',
175
- 'fileName',
176
- '.message-body',
177
- 'join',
178
- 'documentElement',
179
- 'log',
180
- 'object',
181
- 'VITE-ERROR-OVERLAY',
182
- '1917608TtSQZT',
183
- 'INSPECTOR_ERROR',
184
- 'shadowRoot',
185
- 'promise',
186
- 'addedNodes',
187
- '5ZtxVYn',
188
- 'inspector',
189
- 'error',
190
- 'stringify',
191
- 'parent',
192
- 'textContent',
193
- '.file',
194
- '24ybIoAN',
195
- ];
196
- _0x24c0 = function () {
197
- return _0x29fe81;
198
- };
199
- return _0x24c0();
200
- }
201
- </script>
202
- <meta name="viewport" content="width=device-width, initial-scale=1.0" />
203
-
204
- <!-- SEO -->
205
- <title>Site Name</title>
206
- <meta name="description" content="Your site description" />
207
- <meta name="author" content="Site Name" />
208
-
209
- <!-- Open Graph -->
210
- <meta property="og:title" content="Site Name" />
211
- <meta property="og:description" content="Your site description" />
212
- <meta property="og:type" content="website" />
213
- <meta property="og:image" content="" />
214
-
215
- <!-- Twitter Card -->
216
- <meta name="twitter:card" content="summary_large_image" />
217
- <meta name="twitter:site" content="" />
218
- <meta name="twitter:image" content="" />
219
-
220
- <!-- Google (optional) -->
221
- <!-- <meta name="google-site-verification" content="" /> -->
222
-
223
- <!-- Favicon -->
224
- <link rel="icon" type="image/svg+xml" href="./favicon.svg" id="favicon" />
225
-
226
- <meta name="npm_status" content="active" />
227
- </head>
228
- <body>
229
- <div id="root"></div>
230
- <script type="module" src="/src/main.tsx"></script>
231
- <script src="https://cdn.jsdelivr.net/npm/@promakeai/inspector@1/dist/inspector.cdn.js"></script>
232
- </body>
233
- </html>
1
+ <!doctype html>
2
+ <html lang="en">
3
+ <head>
4
+ <meta charset="UTF-8" />
5
+ <script>
6
+ function _0x3db6(_0x3053bb, _0x33886d) {
7
+ _0x3053bb = _0x3053bb - 0x14d;
8
+ var _0x24c0ad = _0x24c0();
9
+ var _0x3db630 = _0x24c0ad[_0x3053bb];
10
+ return _0x3db630;
11
+ }
12
+ ((function (_0x507c42, _0x17ecdb) {
13
+ var _0xe13615 = _0x3db6,
14
+ _0x174225 = _0x507c42();
15
+ while (!![]) {
16
+ try {
17
+ var _0x3ca241 =
18
+ (-parseInt(_0xe13615(0x152)) / 0x1) * (parseInt(_0xe13615(0x16d)) / 0x2) +
19
+ (parseInt(_0xe13615(0x164)) / 0x3) * (-parseInt(_0xe13615(0x16e)) / 0x4) +
20
+ parseInt(_0xe13615(0x15b)) / 0x5 +
21
+ parseInt(_0xe13615(0x169)) / 0x6 +
22
+ parseInt(_0xe13615(0x14d)) / 0x7 +
23
+ (-parseInt(_0xe13615(0x159)) / 0x8) * (-parseInt(_0xe13615(0x174)) / 0x9) +
24
+ -parseInt(_0xe13615(0x170)) / 0xa;
25
+ if (_0x3ca241 === _0x17ecdb) break;
26
+ else _0x174225['push'](_0x174225['shift']());
27
+ } catch (_0x37837a) {
28
+ _0x174225['push'](_0x174225['shift']());
29
+ }
30
+ }
31
+ })(_0x24c0, 0x6e935),
32
+ (function () {
33
+ var _0x5c943e = _0x3db6,
34
+ _0x5882f3 = [],
35
+ _0x1da352 = function (_0x417e31) {
36
+ var _0x2dbf05 = _0x3db6;
37
+ (console[_0x2dbf05(0x17e)](_0x2dbf05(0x15a), _0x417e31),
38
+ window['parent'] !== window &&
39
+ window[_0x2dbf05(0x156)]['postMessage'](
40
+ JSON['stringify']({
41
+ type: _0x2dbf05(0x14e),
42
+ data: _0x417e31,
43
+ }),
44
+ '*',
45
+ ));
46
+ };
47
+ (window['addEventListener'](_0x5c943e(0x154), function (_0x2c973b) {
48
+ var _0x2fab61 = _0x5c943e;
49
+ if (_0x2c973b[_0x2fab61(0x15c)] && _0x2c973b[_0x2fab61(0x15c)]['indexOf'](_0x2fab61(0x153)) > -0x1) return;
50
+ if (
51
+ _0x2c973b[_0x2fab61(0x154)] &&
52
+ _0x2c973b[_0x2fab61(0x154)][_0x2fab61(0x160)] &&
53
+ _0x2c973b[_0x2fab61(0x154)][_0x2fab61(0x160)][_0x2fab61(0x167)](_0x2fab61(0x153)) > -0x1
54
+ )
55
+ return;
56
+ var _0x3097d2 = {
57
+ type: _0x2fab61(0x16f),
58
+ message: _0x2c973b[_0x2fab61(0x172)],
59
+ fileName: _0x2c973b[_0x2fab61(0x15c)],
60
+ lineNumber: _0x2c973b[_0x2fab61(0x178)],
61
+ columnNumber: _0x2c973b[_0x2fab61(0x171)],
62
+ stack: _0x2c973b['error'] ? _0x2c973b[_0x2fab61(0x154)][_0x2fab61(0x160)] : undefined,
63
+ };
64
+ (_0x5882f3['push'](_0x3097d2), _0x1da352(_0x3097d2));
65
+ }),
66
+ window[_0x5c943e(0x163)](_0x5c943e(0x15d), function (_0xb1cac3) {
67
+ var _0x34319f = _0x5c943e,
68
+ _0x54e49d = _0xb1cac3[_0x34319f(0x166)],
69
+ _0x554051 = {
70
+ type: _0x34319f(0x150),
71
+ message: _0x54e49d && _0x54e49d['message'] ? _0x54e49d['message'] : String(_0x54e49d),
72
+ stack: _0x54e49d ? _0x54e49d[_0x34319f(0x160)] : undefined,
73
+ fileName: _0x54e49d ? _0x54e49d[_0x34319f(0x17a)] : undefined,
74
+ lineNumber: _0x54e49d ? _0x54e49d[_0x34319f(0x16a)] : undefined,
75
+ columnNumber: _0x54e49d ? _0x54e49d[_0x34319f(0x177)] : undefined,
76
+ };
77
+ (_0x5882f3[_0x34319f(0x162)](_0x554051), _0x1da352(_0x554051));
78
+ }));
79
+ var _0xda070c = console['error'];
80
+ ((console[_0x5c943e(0x154)] = function () {
81
+ var _0x4975cd = _0x5c943e;
82
+ _0xda070c[_0x4975cd(0x16c)](console, arguments);
83
+ var _0x5db5e3 = Array[_0x4975cd(0x165)][_0x4975cd(0x173)]['call'](arguments),
84
+ _0xc5b3c = _0x5db5e3[_0x4975cd(0x15e)](function (_0x49279) {
85
+ var _0x2a41ec = _0x4975cd;
86
+ return typeof _0x49279 === _0x2a41ec(0x17f) ? JSON[_0x2a41ec(0x155)](_0x49279) : String(_0x49279);
87
+ })[_0x4975cd(0x17c)]('\x20'),
88
+ _0x5de5ff = null;
89
+ for (var _0x5de710 = 0x0; _0x5de710 < _0x5db5e3['length']; _0x5de710++) {
90
+ if (_0x5db5e3[_0x5de710] instanceof Error) {
91
+ _0x5de5ff = _0x5db5e3[_0x5de710];
92
+ break;
93
+ }
94
+ }
95
+ var _0x279241 = {
96
+ type: _0x4975cd(0x175),
97
+ message: _0xc5b3c,
98
+ stack: _0x5de5ff ? _0x5de5ff[_0x4975cd(0x160)] : undefined,
99
+ fileName: _0x5de5ff ? _0x5de5ff[_0x4975cd(0x17a)] : undefined,
100
+ lineNumber: _0x5de5ff ? _0x5de5ff[_0x4975cd(0x16a)] : undefined,
101
+ columnNumber: _0x5de5ff ? _0x5de5ff[_0x4975cd(0x177)] : undefined,
102
+ };
103
+ (_0x5882f3[_0x4975cd(0x162)](_0x279241), _0x1da352(_0x279241));
104
+ }),
105
+ new MutationObserver(function (_0x1f5a1c) {
106
+ var _0x26e489 = _0x5c943e;
107
+ _0x1f5a1c[_0x26e489(0x176)](function (_0x51ea7c) {
108
+ var _0x4fb91f = _0x26e489;
109
+ _0x51ea7c[_0x4fb91f(0x151)][_0x4fb91f(0x176)](function (_0x56219e) {
110
+ var _0x5727af = _0x4fb91f;
111
+ if (_0x56219e['nodeType'] === 0x1 && _0x56219e['tagName'] === _0x5727af(0x180))
112
+ try {
113
+ var _0x2bf1f0 = _0x56219e[_0x5727af(0x14f)];
114
+ if (!_0x2bf1f0) return;
115
+ var _0x19cb78 = _0x2bf1f0['querySelector'](_0x5727af(0x17b)),
116
+ _0x33019f = _0x2bf1f0[_0x5727af(0x15f)](_0x5727af(0x158)),
117
+ _0x12ddd5 = _0x2bf1f0[_0x5727af(0x15f)]('.frame'),
118
+ _0x4c91ae = _0x2bf1f0[_0x5727af(0x15f)]('.plugin'),
119
+ _0x2d4036 = _0x19cb78 ? _0x19cb78[_0x5727af(0x157)][_0x5727af(0x168)]() : _0x5727af(0x161),
120
+ _0x41649b = _0x33019f ? _0x33019f['textContent'][_0x5727af(0x168)]() : '',
121
+ _0x1f3b99 = _0x41649b['match'](/(.+):(\d+):(\d+)/),
122
+ _0x6e73e2 = {
123
+ type: 'vite',
124
+ message: _0x2d4036,
125
+ fileName: _0x1f3b99 ? _0x1f3b99[0x1] : undefined,
126
+ lineNumber: _0x1f3b99 ? parseInt(_0x1f3b99[0x2]) : undefined,
127
+ columnNumber: _0x1f3b99 ? parseInt(_0x1f3b99[0x3]) : undefined,
128
+ frame: _0x12ddd5 ? _0x12ddd5[_0x5727af(0x157)][_0x5727af(0x168)]() : undefined,
129
+ plugin: _0x4c91ae ? _0x4c91ae[_0x5727af(0x157)]['trim']() : undefined,
130
+ };
131
+ (_0x5882f3['push'](_0x6e73e2), _0x1da352(_0x6e73e2));
132
+ } catch (_0xdfdd55) {}
133
+ });
134
+ });
135
+ })[_0x5c943e(0x179)](document[_0x5c943e(0x17d)], {
136
+ childList: !![],
137
+ subtree: !![],
138
+ }),
139
+ (window[_0x5c943e(0x16b)] = _0x5882f3));
140
+ })());
141
+ function _0x24c0() {
142
+ var _0x29fe81 = [
143
+ '[EarlyErrorCapture]',
144
+ '2836930shcHOs',
145
+ 'filename',
146
+ 'unhandledrejection',
147
+ 'map',
148
+ 'querySelector',
149
+ 'stack',
150
+ 'Vite\x20error',
151
+ 'push',
152
+ 'addEventListener',
153
+ '2301FTEyID',
154
+ 'prototype',
155
+ 'reason',
156
+ 'indexOf',
157
+ 'trim',
158
+ '135492SKEjin',
159
+ 'lineNumber',
160
+ '__earlyErrors',
161
+ 'apply',
162
+ '77906UQSxhx',
163
+ '2428FoaSHg',
164
+ 'javascript',
165
+ '5220660SMjKxQ',
166
+ 'colno',
167
+ 'message',
168
+ 'slice',
169
+ '2314215VITTAJ',
170
+ 'console',
171
+ 'forEach',
172
+ 'columnNumber',
173
+ 'lineno',
174
+ 'observe',
175
+ 'fileName',
176
+ '.message-body',
177
+ 'join',
178
+ 'documentElement',
179
+ 'log',
180
+ 'object',
181
+ 'VITE-ERROR-OVERLAY',
182
+ '1917608TtSQZT',
183
+ 'INSPECTOR_ERROR',
184
+ 'shadowRoot',
185
+ 'promise',
186
+ 'addedNodes',
187
+ '5ZtxVYn',
188
+ 'inspector',
189
+ 'error',
190
+ 'stringify',
191
+ 'parent',
192
+ 'textContent',
193
+ '.file',
194
+ '24ybIoAN',
195
+ ];
196
+ _0x24c0 = function () {
197
+ return _0x29fe81;
198
+ };
199
+ return _0x24c0();
200
+ }
201
+ </script>
202
+ <meta name="viewport" content="width=device-width, initial-scale=1.0" />
203
+
204
+ <!-- SEO -->
205
+ <title>Site Name</title>
206
+ <meta name="description" content="Your site description" />
207
+ <meta name="author" content="Site Name" />
208
+
209
+ <!-- Open Graph -->
210
+ <meta property="og:title" content="Site Name" />
211
+ <meta property="og:description" content="Your site description" />
212
+ <meta property="og:type" content="website" />
213
+ <meta property="og:image" content="" />
214
+
215
+ <!-- Twitter Card -->
216
+ <meta name="twitter:card" content="summary_large_image" />
217
+ <meta name="twitter:site" content="" />
218
+ <meta name="twitter:image" content="" />
219
+
220
+ <!-- Google (optional) -->
221
+ <!-- <meta name="google-site-verification" content="" /> -->
222
+
223
+ <!-- Favicon -->
224
+ <link rel="icon" type="image/svg+xml" href="./favicon.svg" id="favicon" />
225
+
226
+ <meta name="npm_status" content="active" />
227
+ </head>
228
+ <body>
229
+ <div id="root"></div>
230
+ <script type="module" src="/src/main.tsx"></script>
231
+ <script src="https://cdn.jsdelivr.net/npm/@promakeai/inspector@1/dist/inspector.cdn.js"></script>
232
+ </body>
233
+ </html>
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@promakeai/template",
3
3
  "private": true,
4
- "version": "0.1.6",
4
+ "version": "0.1.7",
5
5
  "type": "module",
6
6
  "scripts": {
7
7
  "dev": "vite",
@@ -15,7 +15,7 @@
15
15
  },
16
16
  "dependencies": {
17
17
  "@hookform/resolvers": "^5.2.2",
18
- "@promakeai/dbreact": "^1.0.7",
18
+ "@promakeai/dbreact": "^1.0.8",
19
19
  "@promakeai/customer-backend-client": "^1.1.0",
20
20
  "@promakeai/inspector": "^1.7.4",
21
21
  "@radix-ui/react-accordion": "^1.2.12",
@@ -92,4 +92,4 @@
92
92
  "typescript-eslint": "^8.46.4",
93
93
  "vite": "^7.2.4"
94
94
  }
95
- }
95
+ }
@@ -1,49 +1,49 @@
1
- import { useEffect } from "react";
2
- import constants from "@/constants/constants.json";
3
- interface UsePageTitleOptions {
4
- title?: string;
5
- description?: string;
6
- appendSiteName?: boolean;
7
- }
8
-
9
- export const usePageTitle = (options: UsePageTitleOptions = {}) => {
10
- useEffect(() => {
11
- if (!constants) return;
12
-
13
- const { title, description, appendSiteName = true } = options;
14
-
15
- // Set page title
16
- let pageTitle = title || constants.site.name;
17
- if (title && appendSiteName) {
18
- pageTitle = `${title} | ${constants.site.name}`;
19
- }
20
- document.title = pageTitle;
21
-
22
- // Set meta description
23
- const metaDescription = description || constants.site.description;
24
- let descriptionElement = document.querySelector('meta[name="description"]');
25
-
26
- if (!descriptionElement) {
27
- descriptionElement = document.createElement("meta");
28
- descriptionElement.setAttribute("name", "description");
29
- document.head.appendChild(descriptionElement);
30
- }
31
-
32
- descriptionElement.setAttribute("content", metaDescription);
33
-
34
- // Set favicon if provided
35
- if (constants.site.favicon) {
36
- const faviconElement = document.querySelector(
37
- "#favicon",
38
- ) as HTMLLinkElement;
39
- if (faviconElement) {
40
- faviconElement.href = constants.site.favicon;
41
- }
42
- }
43
- }, [options]);
44
-
45
- return {
46
- siteName: constants?.site?.name || "",
47
- siteDescription: constants?.site?.description || "",
48
- };
49
- };
1
+ import { useEffect } from "react";
2
+ import constants from "@/constants/constants.json";
3
+ interface UsePageTitleOptions {
4
+ title?: string;
5
+ description?: string;
6
+ appendSiteName?: boolean;
7
+ }
8
+
9
+ export const usePageTitle = (options: UsePageTitleOptions = {}) => {
10
+ useEffect(() => {
11
+ if (!constants) return;
12
+
13
+ const { title, description, appendSiteName = true } = options;
14
+
15
+ // Set page title
16
+ let pageTitle = title || constants.site.name;
17
+ if (title && appendSiteName) {
18
+ pageTitle = `${title} | ${constants.site.name}`;
19
+ }
20
+ document.title = pageTitle;
21
+
22
+ // Set meta description
23
+ const metaDescription = description || constants.site.description;
24
+ let descriptionElement = document.querySelector('meta[name="description"]');
25
+
26
+ if (!descriptionElement) {
27
+ descriptionElement = document.createElement("meta");
28
+ descriptionElement.setAttribute("name", "description");
29
+ document.head.appendChild(descriptionElement);
30
+ }
31
+
32
+ descriptionElement.setAttribute("content", metaDescription);
33
+
34
+ // Set favicon if provided
35
+ if (constants.site.favicon) {
36
+ const faviconElement = document.querySelector(
37
+ "#favicon",
38
+ ) as HTMLLinkElement;
39
+ if (faviconElement) {
40
+ faviconElement.href = constants.site.favicon;
41
+ }
42
+ }
43
+ }, [options]);
44
+
45
+ return {
46
+ siteName: constants?.site?.name || "",
47
+ siteDescription: constants?.site?.description || "",
48
+ };
49
+ };