@promakeai/cli 0.2.1 → 0.2.2
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 +4 -4
- package/dist/registry/cart-drawer.json +1 -1
- package/package.json +1 -1
- package/template/src/components/LanguageSwitcher.tsx +8 -2
- package/template/src/components/Logo.tsx +6 -0
- package/template/src/components/ThemeSwitcher.tsx +7 -2
- package/template/src/constants/constants.json +1 -1
package/dist/index.js
CHANGED
|
@@ -424,8 +424,8 @@ No changes specified. Use --help for options.`)),console.log(P.dim(`
|
|
|
424
424
|
Examples:`)),console.log(P.dim(" promake theme --preset blue")),console.log(P.dim(" promake theme --radius large")),console.log(P.dim(' promake theme --primary "#3b82f6"')),console.log(P.dim(" promake theme --list"))});import _K from"fs/promises";import Cq from"path";async function gE(D){let X=[Cq.join(D,"index.html"),Cq.join(D,"public/index.html")];for(let Z of X)try{return await _K.access(Z),Z}catch{}return null}async function uE(D){let X=[Cq.join(D,"src/constants/constants.json"),Cq.join(D,"constants/constants.json")];for(let Z of X)try{return await _K.access(Z),Z}catch{}return null}async function mE(D){let X=await uE(D);if(!X)return null;try{let Z=await _K.readFile(X,"utf-8");return JSON.parse(Z).seo||null}catch{return null}}function lD(D,X,Z,J){let Y=new RegExp(`(<meta\\s+${X}\\s+${Z}=")[^"]*("\\s*/?>)`,"i");if(Y.test(D))return D.replace(Y,`$1${J}$2`);return D}function xh0(D,X){let Z=/<title>[^<]*<\/title>/i;if(Z.test(D))return D.replace(Z,`<title>${X}</title>`);return D}function yh0(D,X){if(!X)return D;let Z=/<!--\s*<meta\s+name="google-site-verification"\s+content="[^"]*"\s*\/?>\s*-->/i;if(Z.test(D))return D.replace(Z,`<meta name="google-site-verification" content="${X}" />`);let J=/(<meta\s+name="google-site-verification"\s+content=")[^"]*("\s*\/?>\s*)/i;if(J.test(D))return D.replace(J,`$1${X}$2`);return D}async function Ar(D,X){let Z=[],J=await gE(D);if(!J)return{changes:[],success:!1};let Y=X||await mE(D);if(!Y)return{changes:[],success:!1};let Q;try{Q=await _K.readFile(J,"utf-8")}catch{return{changes:[],success:!1}}if(Y.title)Q=xh0(Q,Y.title),Z.push(`title: ${Y.title}`);if(Y.description)Q=lD(Q,'name="description"',"content",Y.description),Z.push(`description: ${Y.description.substring(0,50)}...`);if(Y.author)Q=lD(Q,'name="author"',"content",Y.author),Z.push(`author: ${Y.author}`);if(Y.ogTitle)Q=lD(Q,'property="og:title"',"content",Y.ogTitle),Z.push(`og:title: ${Y.ogTitle}`);if(Y.ogDescription)Q=lD(Q,'property="og:description"',"content",Y.ogDescription),Z.push(`og:description: ${Y.ogDescription.substring(0,50)}...`);if(Y.ogImage)Q=lD(Q,'property="og:image"',"content",Y.ogImage),Z.push(`og:image: ${Y.ogImage}`);if(Y.twitterSite)Q=lD(Q,'name="twitter:site"',"content",Y.twitterSite),Z.push(`twitter:site: ${Y.twitterSite}`);if(Y.twitterImage)Q=lD(Q,'name="twitter:image"',"content",Y.twitterImage),Z.push(`twitter:image: ${Y.twitterImage}`);if(Y.googleVerification)Q=yh0(Q,Y.googleVerification),Z.push(`google-verification: ${Y.googleVerification}`);if(Z.length>0)try{await _K.writeFile(J,Q)}catch{return{changes:[],success:!1}}return{changes:Z,success:!0}}var Nr=new $5("seo").description("Sync SEO meta tags from constants.json to index.html").option("-s, --show","Show current SEO configuration").option("--cwd <path>","Working directory").action(async(D)=>{let X=D.cwd||process.cwd(),Z=await gE(X);if(!Z)console.log(P.red("Could not find index.html")),process.exit(1);let J=await uE(X);if(!J)console.log(P.red("Could not find constants.json (src/constants/constants.json)")),process.exit(1);if(D.show){let Q=await mE(X);if(!Q){console.log(P.red("No SEO configuration found in constants.json"));return}if(console.log(P.bold(`
|
|
425
425
|
SEO Configuration (constants.json):`)),console.log(` ${P.dim("Title:")} ${Q.title||"not set"}`),console.log(` ${P.dim("Description:")} ${Q.description||"not set"}`),console.log(` ${P.dim("Author:")} ${Q.author||"not set"}`),console.log(P.bold(`
|
|
426
426
|
Open Graph:`)),console.log(` ${P.dim("og:title:")} ${Q.ogTitle||"not set"}`),console.log(` ${P.dim("og:description:")} ${Q.ogDescription||"not set"}`),console.log(` ${P.dim("og:image:")} ${Q.ogImage||"not set"}`),console.log(P.bold(`
|
|
427
|
-
Twitter Card:`)),console.log(` ${P.dim("twitter:site:")} ${Q.twitterSite||"not set"}`),console.log(` ${P.dim("twitter:image:")} ${Q.twitterImage||"not set"}`),Q.googleVerification
|
|
428
|
-
Google:`)),
|
|
427
|
+
Twitter Card:`)),console.log(` ${P.dim("twitter:site:")} ${Q.twitterSite||"not set"}`),console.log(` ${P.dim("twitter:image:")} ${Q.twitterImage||"not set"}`),Q.googleVerification)console.log(P.bold(`
|
|
428
|
+
Google:`)),console.log(` ${P.dim("Site Verification:")} ${Q.googleVerification}`);return}console.log(P.dim(`
|
|
429
429
|
Syncing SEO settings...`)),console.log(P.dim(` Source: ${J}`)),console.log(P.dim(` Target: ${Z}`));let Y=await Ar(X);if(!Y.success)console.log(P.red(`
|
|
430
430
|
Failed to apply SEO configuration`)),process.exit(1);if(Y.changes.length===0){console.log(P.yellow(`
|
|
431
431
|
No changes to apply`));return}console.log(P.green(`
|
|
@@ -491,8 +491,8 @@ constants.json (full)`)),console.log(P.dim(JSON.stringify(U.constantsConfig,null
|
|
|
491
491
|
━━━ QUICK REFERENCE ━━━
|
|
492
492
|
`)),e8("promake create <name>","Create new project"),e8("promake add <modules...>","Add modules"),e8("promake add <page> --module-name <name>","Add page with custom name"),e8("promake remove <modules...>","Remove modules"),e8("promake sync","Sync from promake.json"),e8("promake theme --list","List theme options"),e8("promake theme --preset <name>","Apply color preset"),e8("promake list","List available modules"),e8("promake doctor","Check project health"),e8("promake doctor --runtime","Include runtime checks"),e8("promake discover --json","Project info for AI"),e8("promake seo","Sync SEO meta tags"),e8("promake usage","Show this guide"),e8("promake <command> --help","Command-specific help"),console.log()}var Ir=new $5("info").description("Show detailed information about a module").argument("<module>","Module name").option("--json","Output as JSON").action(async(D,X)=>{let Z=E2(`Fetching ${D}...`).start();try{let J=await R4(D);if(Z.stop(),!J)console.error(P.red(`Module not found: ${D}`)),process.exit(1);if(X.json){console.log(JSON.stringify(J,null,2));return}if(console.log(""),console.log(P.bold.cyan(J.name)),console.log(P.dim("─".repeat(J.name.length+4))),J.title)console.log(`${P.gray("Title:")} ${J.title}`);if(console.log(`${P.gray("Type:")} ${J.type.replace("registry:","")}`),J.description)console.log(`${P.gray("Description:")} ${J.description}`);if(J.registryDependencies?.length)console.log(""),console.log(P.gray("Dependencies:")),J.registryDependencies.forEach((Y)=>{let $=!Y.includes("-")||["button","card","input","badge","dialog","sheet","dropdown-menu","accordion","tabs","select","checkbox","slider","separator","avatar","tooltip","popover","navigation-menu","scroll-area"].includes(Y)?P.dim("(shadcn)"):"";console.log(` ${P.yellow("•")} ${Y} ${$}`)});if(J.dependencies?.length)console.log(""),console.log(P.gray("NPM Packages:")),J.dependencies.forEach((Y)=>{console.log(` ${P.blue("•")} ${Y}`)});if(J.files?.length)console.log(""),console.log(P.gray("Files:")),J.files.forEach((Y)=>{console.log(` ${P.dim("•")} ${Y.path}`)});if(J.exports){if(console.log(""),console.log(P.gray("Exports:")),J.exports.types?.length)console.log(` ${P.magenta("Types:")} ${J.exports.types.join(", ")}`);if(J.exports.variables?.length)console.log(` ${P.green("Components:")} ${J.exports.variables.join(", ")}`)}if(J.route)console.log(""),console.log(P.gray("Route:")),console.log(` ${P.cyan("Path:")} ${J.route.path}`),console.log(` ${P.cyan("Component:")} ${J.route.componentName}`);if(J.usage)console.log(""),console.log(P.gray("Usage:")),console.log(P.dim("─".repeat(40))),console.log(J.usage);console.log("")}catch(J){if(Z.fail("Failed to fetch module info"),J instanceof Error)console.error(P.red(J.message));process.exit(1)}});import P91 from"path";var kK=b1(o8(),1);import{execSync as nh0}from"child_process";import wq from"path";async function cE(D,X=!1){let Z=Date.now(),J=[],Y=wq.join(D,"tsconfig.json");if(!await kK.default.pathExists(Y))return{name:"TypeScript",status:"skip",severity:"info",duration:Date.now()-Z,items:[],summary:"No tsconfig.json found"};let Q=wq.join(D,"package.json"),$=!1;if(await kK.default.pathExists(Q))$=!!(await kK.default.readJson(Q)).scripts?.check;let K=aQ(D),G=K==="npm"?"npm run":`${K} run`;try{let V=$?`${G} check 2>&1`:"npx tsc --noEmit 2>&1";if(!X)console.log(P.dim(` $ ${$?`${G} check`:"tsc --noEmit"}`));let W=nh0(V,{cwd:D,encoding:"utf-8",stdio:"pipe"});if(!X&&W.trim())console.log(P.dim(W));return{name:"TypeScript",status:"pass",severity:"error",duration:Date.now()-Z,items:[],summary:"No type errors"}}catch(V){let W=V.stdout||V.stderr||V.message||"";if(W.includes("This is not the tsc command")||W.includes("typescript"))return{name:"TypeScript",status:"skip",severity:"info",duration:Date.now()-Z,items:[],summary:"TypeScript not installed"};if(!X&&W.trim())console.log(P.dim(W));return J.push(...oh0(W,D)),{name:"TypeScript",status:"fail",severity:"error",duration:Date.now()-Z,items:J,summary:`${J.length} type error(s)`}}}function oh0(D,X){let Z=[],J=/^(.+)\((\d+),(\d+)\):\s*(error|warning)\s*(TS\d+):\s*(.+)$/gm,Y=/^(.+):(\d+):(\d+)\s*-\s*(error|warning)\s*(TS\d+):\s*(.+)$/gm;for(let $ of[J,Y]){let K;while((K=$.exec(D))!==null){let G=K[1].trim();Z.push({file:wq.isAbsolute(G)?wq.relative(X,G):G,line:parseInt(K[2]),column:parseInt(K[3]),code:K[5],message:K[6]})}}let Q=new Set;return Z.filter(($)=>{let K=`${$.file}:${$.line}:${$.column}:${$.message}`;if(Q.has(K))return!1;return Q.add(K),!0})}var pD=b1(o8(),1);import{execSync as rh0}from"child_process";import hK from"path";var sh0=["eslint.config.js","eslint.config.mjs","eslint.config.cjs",".eslintrc.js",".eslintrc.cjs",".eslintrc.json",".eslintrc.yml",".eslintrc.yaml",".eslintrc"];async function ah0(D){for(let Z of sh0)if(await pD.default.pathExists(hK.join(D,Z)))return!0;let X=hK.join(D,"package.json");if(await pD.default.pathExists(X))try{if((await pD.default.readJson(X)).eslintConfig)return!0}catch{}return!1}async function dE(D,X=!1,Z=!1){let J=Date.now();if(!await ah0(D))return{name:"ESLint",status:"skip",severity:"warning",duration:Date.now()-J,items:[],summary:"No ESLint config found"};let Y=hK.join(D,"package.json"),Q=!1;if(await pD.default.pathExists(Y))Q=!!(await pD.default.readJson(Y)).scripts?.lint;let $=aQ(D),K=$==="npm"?"npm run":`${$} run`,G=X?" -- --fix":"";try{let V=Q?`${K} lint${G} 2>&1`:`npx eslint .${X?" --fix":""} 2>&1`;if(!Z)console.log(P.dim(` $ ${Q?`${K} lint${G}`:`eslint .${X?" --fix":""}`}`));let W=rh0(V,{cwd:D,encoding:"utf-8",stdio:"pipe",maxBuffer:10485760});if(!Z&&W.trim())console.log(P.dim(W));return{name:"ESLint",status:"pass",severity:"warning",duration:Date.now()-J,items:[],summary:"No linting issues"}}catch(V){let W=V.stdout||V.stderr||V.message||"";if(W.includes("eslint: not found")||W.includes("'eslint' is not recognized"))return{name:"ESLint",status:"skip",severity:"info",duration:Date.now()-J,items:[],summary:"ESLint not installed"};if(!Z&&W.trim())console.log(P.dim(W));let F=th0(W,D);if(F.length===0&&W.includes("error"))return{name:"ESLint",status:"fail",severity:"warning",duration:Date.now()-J,items:[{message:"ESLint encountered an error"}],summary:"ESLint error"};return{name:"ESLint",status:F.length>0?"fail":"pass",severity:"warning",duration:Date.now()-J,items:F,summary:F.length>0?`${F.length} linting issue(s)`:"No linting issues"}}}function th0(D,X){let Z=[],J=/^([^\s].*\.(ts|tsx|js|jsx))$/gm,Y=/^\s+(\d+):(\d+)\s+(error|warning)\s+(.+?)\s{2,}(\S+)?$/gm,Q=null,$=D.split(`
|
|
493
493
|
`);for(let K of $){let G=K.match(/^([^\s].*\.(ts|tsx|js|jsx))$/);if(G){Q=G[1];continue}let V=K.match(/^\s+(\d+):(\d+)\s+(error|warning)\s+(.+?)\s{2,}(\S+)?$/);if(V&&Q)Z.push({file:hK.isAbsolute(Q)?hK.relative(X,Q):Q,line:parseInt(V[1]),column:parseInt(V[2]),code:V[5]||void 0,message:V[4].trim()})}return Z}var Sq=b1(o8(),1);import{execSync as eh0}from"child_process";import xK from"path";async function lE(D){let X=Date.now(),Z=["vite.config.ts","vite.config.js","vite.config.mjs"],J=!1;for(let Y of Z)if(await Sq.default.pathExists(xK.join(D,Y))){J=!0;break}if(!J)return{name:"Build",status:"skip",severity:"error",duration:Date.now()-X,items:[],summary:"No vite.config found"};try{eh0("npx vite build 2>&1",{cwd:D,encoding:"utf-8",stdio:"pipe",env:{...process.env,NODE_ENV:"production"}});let Y=xK.join(D,"dist");if(await Sq.default.pathExists(Y))await Sq.default.remove(Y);return{name:"Build",status:"pass",severity:"error",duration:Date.now()-X,items:[],summary:"Build succeeded"}}catch(Y){let Q=Y.stdout||Y.stderr||Y.message||"",$=Dx0(Q,D);return{name:"Build",status:"fail",severity:"error",duration:Date.now()-X,items:$.length>0?$:[{message:"Build failed"}],summary:"Build failed"}}}function Dx0(D,X){let Z=[],J=D.split(`
|
|
494
|
-
`),Y=[/^(.+):(\d+):(\d+):\s*(.+)$/,/\[vite\]:\s*Error:\s*(.+)/,/Error:\s*(.+?)\s+at\s+(.+):(\d+):(\d+)/,/Could not resolve ["']([^"']+)["']\s+from\s+["']([^"']+)["']/,/RollupError:\s*(.+)/];for(let $=0;$<J.length;$++){let K=J[$].trim();if(!K)continue;if(K.includes("building for production")||K.includes("transforming")||K.includes("rendering chunks")||K.includes("computing gzip")||K.startsWith("✓")||K.startsWith("vite v"))continue;for(let G of Y){let V=K.match(G);if(V){if(G.source.includes("Could not resolve"))Z.push({file:xK.relative(X,V[2]),message:`Cannot find module '${V[1]}'`,suggestion:"Check if the module is installed or the path is correct"});else if(V.length===5)Z.push({file:xK.isAbsolute(V[1]||V[2])?xK.relative(X,V[1]||V[2]):V[1]||V[2],line:parseInt(V[2]||V[3]),column:parseInt(V[3]||V[4]),message:V[4]||V[1]});else Z.push({message:V[1]||K});break}}if(Z.length===0&&(K.toLowerCase().includes("error")||K.toLowerCase().includes("failed")))Z.push({message:K})}let Q=new Set;return Z.filter(($)=>{let K=`${$.file}:${$.line}:${$.message}`;if(Q.has(K))return!1;return Q.add(K),!0})}var uS=b1(o8(),1);import sW from"path";var W91=[process.env["PROGRAMFILES(X86)"]&&sW.join(process.env["PROGRAMFILES(X86)"],"Google","Chrome","Application","chrome.exe"),process.env.PROGRAMFILES&&sW.join(process.env.PROGRAMFILES,"Google","Chrome","Application","chrome.exe"),process.env.LOCALAPPDATA&&sW.join(process.env.LOCALAPPDATA,"Google","Chrome","Application","chrome.exe"),process.env["PROGRAMFILES(X86)"]&&sW.join(process.env["PROGRAMFILES(X86)"],"Microsoft","Edge","Application","msedge.exe"),process.env.PROGRAMFILES&&sW.join(process.env.PROGRAMFILES,"Microsoft","Edge","Application","msedge.exe")].filter(Boolean),V91=["/Applications/Google Chrome.app/Contents/MacOS/Google Chrome","/Applications/Microsoft Edge.app/Contents/MacOS/Microsoft Edge","/Applications/Chromium.app/Contents/MacOS/Chromium"],F91=["/usr/bin/google-chrome","/usr/bin/google-chrome-stable","/usr/bin/chromium-browser","/usr/bin/chromium","/snap/bin/chromium"];async function T$0(){let D=await H91();if(D)return D;let X=await q91();if(X)return X;return null}async function H91(){try{let{lightpanda:D}=await Promise.resolve().then(() => (Cr(),Pr)),X=await Promise.resolve().then(() => (gS(),fS)),Z=9222,J=await D.serve({host:"127.0.0.1",port:9222});return await B91(9222),{type:"lightpanda",browser:await X.default.connect({browserWSEndpoint:"ws://127.0.0.1:9222"}),process:J}}catch{return null}}async function q91(){try{let D=await z91();if(!D)return null;return{type:"chrome",browser:await(await Promise.resolve().then(() => (gS(),fS))).default.launch({executablePath:D,headless:!0,args:["--no-sandbox","--disable-setuid-sandbox","--disable-gpu"]})}}catch{return null}}async function z91(){if(process.env.CHROME_PATH){if(await uS.default.pathExists(process.env.CHROME_PATH))return process.env.CHROME_PATH}let D;switch(process.platform){case"win32":D=W91;break;case"darwin":D=V91;break;default:D=F91}for(let X of D)if(await uS.default.pathExists(X))return X;return null}async function B91(D,X=20){for(let Z=0;Z<X;Z++){try{if((await fetch(`http://127.0.0.1:${D}/json/version`,{signal:AbortSignal.timeout(500)})).ok)return}catch{}await U91(100)}throw Error("CDP server failed to start")}function U91(D){return new Promise((X)=>setTimeout(X,D))}async function I$0(D){try{if(D.browser)await D.browser.close()}catch{}if(D.process)D.process.stdout?.destroy(),D.process.stderr?.destroy(),D.process.kill()}async function mS(D,X){let
|
|
495
|
-
`)}})}function cS(D,X){console.log(""),console.log(P.bold("Health Check")+P.dim(` (${j91(D.duration)})`)),console.log(P.dim("─".repeat(40)));for(let Z of D.checks)A91(Z,X);console.log(P.dim("─".repeat(40))),I91(D)}function A91(D,X){let Z=E91(D.status),J=T91(D.status,D.severity),Y=P.dim(`${D.duration}ms`);console.log(`${Z} ${J(D.name)} ${Y} ${P.dim("·")} ${P.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 $)N91(G,D.severity);if(K>0)console.log(P.dim(` ... +${K} more (--verbose)`))}function N91(D,X){let Z=X==="error"?P.red:P.yellow,J=R91(D),Y=J?P.cyan(J)+" ":"";console.log(` ${Z("›")} ${Y}${D.message}`)}function R91(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 E91(D){switch(D){case"pass":return P.green("✓");case"fail":return P.red("✗");case"skip":return P.dim("○");default:return P.dim("?")}}function T91(D,X){if(D==="fail")return X==="error"?P.red:P.yellow;if(D==="pass")return P.green;return P.dim}function I91(D){let{summary:X}=D,Z=[];if(X.passed>0)Z.push(P.green(`${X.passed} passed`));if(X.failed>0)Z.push(P.red(`${X.failed} failed`));if(X.skipped>0)Z.push(P.dim(`${X.skipped} skipped`));if(console.log(Z.join(P.dim(" · "))),X.errors>0)console.log(P.red(`${X.errors} error(s) need attention`));else if(X.warnings>0)console.log(P.yellow(`${X.warnings} warning(s) to review`));else console.log(P.green("All good!"))}function j91(D){if(D<1000)return`${D}ms`;return`${(D/1000).toFixed(1)}s`}var j$0=new $5("doctor").description("Analyze project for issues (TypeScript, ESLint, build, runtime)").option("--cwd <path>","Working directory").option("--port <number>","Vite dev server port","5174").option("--fix","Auto-fix ESLint issues where possible").option("--runtime","Run runtime error detection (requires running dev server)").option("--runtime-timeout <ms>","Runtime check timeout in ms","10000").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=Date.now()
|
|
494
|
+
`),Y=[/^(.+):(\d+):(\d+):\s*(.+)$/,/\[vite\]:\s*Error:\s*(.+)/,/Error:\s*(.+?)\s+at\s+(.+):(\d+):(\d+)/,/Could not resolve ["']([^"']+)["']\s+from\s+["']([^"']+)["']/,/RollupError:\s*(.+)/];for(let $=0;$<J.length;$++){let K=J[$].trim();if(!K)continue;if(K.includes("building for production")||K.includes("transforming")||K.includes("rendering chunks")||K.includes("computing gzip")||K.startsWith("✓")||K.startsWith("vite v"))continue;for(let G of Y){let V=K.match(G);if(V){if(G.source.includes("Could not resolve"))Z.push({file:xK.relative(X,V[2]),message:`Cannot find module '${V[1]}'`,suggestion:"Check if the module is installed or the path is correct"});else if(V.length===5)Z.push({file:xK.isAbsolute(V[1]||V[2])?xK.relative(X,V[1]||V[2]):V[1]||V[2],line:parseInt(V[2]||V[3]),column:parseInt(V[3]||V[4]),message:V[4]||V[1]});else Z.push({message:V[1]||K});break}}if(Z.length===0&&(K.toLowerCase().includes("error")||K.toLowerCase().includes("failed")))Z.push({message:K})}let Q=new Set;return Z.filter(($)=>{let K=`${$.file}:${$.line}:${$.message}`;if(Q.has(K))return!1;return Q.add(K),!0})}var uS=b1(o8(),1);import sW from"path";var W91=[process.env["PROGRAMFILES(X86)"]&&sW.join(process.env["PROGRAMFILES(X86)"],"Google","Chrome","Application","chrome.exe"),process.env.PROGRAMFILES&&sW.join(process.env.PROGRAMFILES,"Google","Chrome","Application","chrome.exe"),process.env.LOCALAPPDATA&&sW.join(process.env.LOCALAPPDATA,"Google","Chrome","Application","chrome.exe"),process.env["PROGRAMFILES(X86)"]&&sW.join(process.env["PROGRAMFILES(X86)"],"Microsoft","Edge","Application","msedge.exe"),process.env.PROGRAMFILES&&sW.join(process.env.PROGRAMFILES,"Microsoft","Edge","Application","msedge.exe")].filter(Boolean),V91=["/Applications/Google Chrome.app/Contents/MacOS/Google Chrome","/Applications/Microsoft Edge.app/Contents/MacOS/Microsoft Edge","/Applications/Chromium.app/Contents/MacOS/Chromium"],F91=["/usr/bin/google-chrome","/usr/bin/google-chrome-stable","/usr/bin/chromium-browser","/usr/bin/chromium","/snap/bin/chromium"];async function T$0(){let D=await H91();if(D)return D;let X=await q91();if(X)return X;return null}async function H91(){try{let{lightpanda:D}=await Promise.resolve().then(() => (Cr(),Pr)),X=await Promise.resolve().then(() => (gS(),fS)),Z=9222,J=await D.serve({host:"127.0.0.1",port:9222});return await B91(9222),{type:"lightpanda",browser:await X.default.connect({browserWSEndpoint:"ws://127.0.0.1:9222"}),process:J}}catch{return null}}async function q91(){try{let D=await z91();if(!D)return null;return{type:"chrome",browser:await(await Promise.resolve().then(() => (gS(),fS))).default.launch({executablePath:D,headless:!0,args:["--no-sandbox","--disable-setuid-sandbox","--disable-gpu"]})}}catch{return null}}async function z91(){if(process.env.CHROME_PATH){if(await uS.default.pathExists(process.env.CHROME_PATH))return process.env.CHROME_PATH}let D;switch(process.platform){case"win32":D=W91;break;case"darwin":D=V91;break;default:D=F91}for(let X of D)if(await uS.default.pathExists(X))return X;return null}async function B91(D,X=20){for(let Z=0;Z<X;Z++){try{if((await fetch(`http://127.0.0.1:${D}/json/version`,{signal:AbortSignal.timeout(500)})).ok)return}catch{}await U91(100)}throw Error("CDP server failed to start")}function U91(D){return new Promise((X)=>setTimeout(X,D))}async function I$0(D){try{if(D.browser)await D.browser.close()}catch{}if(D.process)D.process.stdout?.destroy(),D.process.stderr?.destroy(),D.process.kill()}async function mS(D,X,Z="/"){let J=Date.now();if(!await O91(D))return{name:"Runtime",status:"skip",severity:"error",duration:Date.now()-J,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 Q=null;try{Q=await T$0()}catch{}if(!Q)return{name:"Runtime",status:"skip",severity:"info",duration:Date.now()-J,items:[{message:"No browser available (Lightpanda or Chrome/Edge not found)",suggestion:"Install Chrome/Edge or run on Linux/macOS for Lightpanda support"}],summary:"Skipped (no browser)"};let $=[],{browser:K,type:G}=Q;try{let W=await K.newPage();W.on("console",async(H)=>{let q=H.type();if(q==="error"||q==="warning"){let B=H.location();$.push({type:q==="warning"?"warning":"console",message:H.text(),fileName:B?.url,lineNumber:B?.lineNumber,columnNumber:B?.columnNumber})}}),W.on("pageerror",(H)=>{$.push({type:"error",message:H.message,stack:H.stack})});let F=Z.startsWith("/")?Z:`/${Z}`;await W.goto(`http://localhost:${D}${F}`,{waitUntil:"networkidle0",timeout:X}),await L91(3000);let z=await W.evaluate(()=>{return window.__earlyErrors||[]});$.push(...z)}catch(W){let F=W.message||"Unknown error";if(F.includes("timeout")||F.includes("Timeout"))$.push({type:"error",message:"Page load timeout - app may have crashed or is unresponsive"});else if(F.includes("net::ERR"))$.push({type:"error",message:`Network error: ${F}`});else $.push({type:"error",message:`Runtime check error: ${F}`})}finally{await I$0(Q)}let V=M91($);return{name:`Runtime (${G})`,status:V.length>0?"fail":"pass",severity:"error",duration:Date.now()-J,items:V,summary:V.length>0?`${V.length} runtime error(s)`:"No runtime errors"}}async function O91(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 L91(D){return new Promise((X)=>setTimeout(X,D))}function M91(D){return D.map((X)=>{let Z=[];for(let[J,Y]of Object.entries(X))if(Y!==void 0&&Y!==null)Z.push(`${J}: ${Y}`);return{message:Z.join(`
|
|
495
|
+
`)}})}function cS(D,X){console.log(""),console.log(P.bold("Health Check")+P.dim(` (${j91(D.duration)})`)),console.log(P.dim("─".repeat(40)));for(let Z of D.checks)A91(Z,X);console.log(P.dim("─".repeat(40))),I91(D)}function A91(D,X){let Z=E91(D.status),J=T91(D.status,D.severity),Y=P.dim(`${D.duration}ms`);console.log(`${Z} ${J(D.name)} ${Y} ${P.dim("·")} ${P.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 $)N91(G,D.severity);if(K>0)console.log(P.dim(` ... +${K} more (--verbose)`))}function N91(D,X){let Z=X==="error"?P.red:P.yellow,J=R91(D),Y=J?P.cyan(J)+" ":"";console.log(` ${Z("›")} ${Y}${D.message}`)}function R91(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 E91(D){switch(D){case"pass":return P.green("✓");case"fail":return P.red("✗");case"skip":return P.dim("○");default:return P.dim("?")}}function T91(D,X){if(D==="fail")return X==="error"?P.red:P.yellow;if(D==="pass")return P.green;return P.dim}function I91(D){let{summary:X}=D,Z=[];if(X.passed>0)Z.push(P.green(`${X.passed} passed`));if(X.failed>0)Z.push(P.red(`${X.failed} failed`));if(X.skipped>0)Z.push(P.dim(`${X.skipped} skipped`));if(console.log(Z.join(P.dim(" · "))),X.errors>0)console.log(P.red(`${X.errors} error(s) need attention`));else if(X.warnings>0)console.log(P.yellow(`${X.warnings} warning(s) to review`));else console.log(P.green("All good!"))}function j91(D){if(D<1000)return`${D}ms`;return`${(D/1000).toFixed(1)}s`}var j$0=new $5("doctor").description("Analyze project for issues (TypeScript, ESLint, build, runtime)").option("--cwd <path>","Working directory").option("--port <number>","Vite dev server port","5174").option("--fix","Auto-fix ESLint issues where possible").option("--runtime","Run runtime error detection (requires running dev server)").option("--runtime-timeout <ms>","Runtime check timeout in ms","10000").option("--route <path>","Route path for runtime check","/").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(P.yellow("Warning: No promake.json found. Running checks anyway..."));let G=D.json?null:E2("Running health checks...").start(),V=[];if(D.typecheck!==!1)V.push(()=>cE(X,$));if(D.lint!==!1)V.push(()=>dE(X,D.fix,$));if(D.build!==!1)V.push(()=>lE(X));if(D.runtime)V.push(()=>mS(Z,J,Y));let W=[];try{if(W=await C91(V,1),G)G.stop()}catch(z){if(G)G.fail("Health check failed");if(!D.json)console.error(P.red(z.message));process.exit(1)}let F={project:P91.basename(X),timestamp:new Date().toISOString(),duration:Date.now()-Q,checks:W,summary:{passed:W.filter((z)=>z.status==="pass").length,failed:W.filter((z)=>z.status==="fail").length,skipped:W.filter((z)=>z.status==="skip").length,errors:W.filter((z)=>z.status==="fail"&&z.severity==="error").reduce((z,H)=>z+H.items.length,0),warnings:W.filter((z)=>z.status==="fail"&&z.severity==="warning").reduce((z,H)=>z+H.items.length,0)}};if(D.json)console.log(JSON.stringify(F,null,2));else cS(F,D.verbose||!1);if(F.summary.errors>0)process.exit(1)});async function C91(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}var P$0={name:"@promakeai/cli",version:"0.2.2",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",build:"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:watch":"bun test --watch","test:coverage":"bun test --coverage",release:"bun run build && npm publish --access public"},dependencies:{"@lightpanda/browser":"^1.0.1","adm-zip":"^0.5.16",archiver:"^7.0.1",chalk:"^5.3.0",commander:"^12.1.0",culori:"^4.0.2","fs-extra":"^11.2.0",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",typescript:"^5.7.2"}};var P8=new $5;P8.name("promake").description(`Modular React template CLI - Build React apps with pre-built components
|
|
496
496
|
|
|
497
497
|
Quick Start:
|
|
498
498
|
$ promake create my-app
|
|
@@ -20,7 +20,7 @@
|
|
|
20
20
|
"path": "cart-drawer/cart-drawer.tsx",
|
|
21
21
|
"type": "registry:component",
|
|
22
22
|
"target": "$modules$/cart-drawer/cart-drawer.tsx",
|
|
23
|
-
"content": "import { Link } from \"react-router\";\
|
|
23
|
+
"content": "import { Link } from \"react-router\";\nimport { Minus, Plus } from \"lucide-react\";\nimport { Button } from \"@/components/ui/button\";\nimport {\n Sheet,\n SheetContent,\n SheetHeader,\n SheetTitle,\n} from \"@/components/ui/sheet\";\nimport { useTranslation } from \"react-i18next\";\nimport { useCart, formatPrice } from \"@/modules/ecommerce-core\";\nimport constants from \"@/constants/constants.json\";\n\ninterface CartDrawerProps {\n checkoutHref?: string;\n className?: string;\n}\n\nexport function CartDrawer({\n checkoutHref = \"/checkout\",\n className,\n}: CartDrawerProps) {\n const { t } = useTranslation(\"cart-drawer\");\n const {\n state,\n removeItem,\n updateQuantity,\n isDrawerOpen,\n setDrawerOpen,\n } = useCart();\n const { items, total } = state;\n const currency = (constants.site as any).currency || \"USD\";\n\n const getProductPrice = (product: {\n price: number;\n sale_price?: number;\n on_sale?: boolean;\n }) => {\n return product.on_sale && product.sale_price\n ? product.sale_price\n : product.price;\n };\n\n const handleQuantityChange = (id: string | number, newQuantity: number) => {\n if (newQuantity <= 0) {\n removeItem(id);\n } else {\n updateQuantity(id, newQuantity);\n }\n };\n\n return (\n <Sheet open={isDrawerOpen} onOpenChange={setDrawerOpen} className={className}>\n <SheetContent className=\"w-full sm:max-w-md flex flex-col px-6 pb-8\">\n <SheetHeader>\n <SheetTitle>{t(\"title\", \"Shopping cart\")}</SheetTitle>\n </SheetHeader>\n\n <div className=\"flex-1 overflow-y-auto mt-8\">\n {items.length === 0 ? (\n <p className=\"text-center text-muted-foreground py-8\">\n {t(\"empty\", \"Your cart is empty\")}\n </p>\n ) : (\n <ul className=\"-my-6 divide-y divide-border\">\n {items.map((item) => (\n <li key={item.id} className=\"flex py-6\">\n <div className=\"size-24 shrink-0 overflow-hidden rounded-md border border-border\">\n <img\n alt={item.product.name}\n src={item.product.images[0] || \"/images/placeholder.png\"}\n className=\"size-full object-cover\"\n />\n </div>\n\n <div className=\"ml-4 flex flex-1 flex-col\">\n <div>\n <div className=\"flex justify-between text-base font-medium\">\n <h3>\n <Link\n to={`/products/${item.product.slug}`}\n onClick={() => setDrawerOpen(false)}\n >\n {item.product.name}\n </Link>\n </h3>\n <p className=\"ml-4\">\n {formatPrice(getProductPrice(item.product), currency)}\n </p>\n </div>\n {item.product.category_name && (\n <p className=\"mt-1 text-sm text-muted-foreground\">\n {item.product.category_name}\n </p>\n )}\n </div>\n <div className=\"flex flex-1 items-end justify-between text-sm\">\n <div className=\"flex items-center gap-1\">\n <Button\n variant=\"outline\"\n size=\"icon\"\n className=\"h-6 w-6\"\n onClick={() =>\n handleQuantityChange(item.id, item.quantity - 1)\n }\n >\n <Minus className=\"h-3 w-3\" />\n </Button>\n <span className=\"w-8 text-center text-sm\">\n {item.quantity}\n </span>\n <Button\n variant=\"outline\"\n size=\"icon\"\n className=\"h-6 w-6\"\n onClick={() =>\n handleQuantityChange(item.id, item.quantity + 1)\n }\n >\n <Plus className=\"h-3 w-3\" />\n </Button>\n </div>\n\n <button\n type=\"button\"\n onClick={() => removeItem(item.id)}\n className=\"font-medium text-primary hover:text-primary/80\"\n >\n {t(\"remove\", \"Remove\")}\n </button>\n </div>\n </div>\n </li>\n ))}\n </ul>\n )}\n </div>\n\n <div className=\"border-t border-border pt-6 mt-6\">\n <div className=\"flex justify-between text-base font-medium\">\n <p>{t(\"subtotal\", \"Subtotal\")}</p>\n <p>{formatPrice(total, currency)}</p>\n </div>\n <p className=\"mt-0.5 text-sm text-muted-foreground\">\n {t(\"shippingNote\", \"Shipping and taxes calculated at checkout.\")}\n </p>\n <div className=\"mt-6\">\n <Button asChild className=\"w-full\" disabled={items.length === 0}>\n <Link to={checkoutHref} onClick={() => setDrawerOpen(false)}>\n {t(\"checkout\", \"Checkout\")}\n </Link>\n </Button>\n </div>\n </div>\n </SheetContent>\n </Sheet>\n );\n}\n"
|
|
24
24
|
},
|
|
25
25
|
{
|
|
26
26
|
"path": "cart-drawer/lang/en.json",
|
package/package.json
CHANGED
|
@@ -10,10 +10,15 @@ import { changeLanguage } from "@/lang";
|
|
|
10
10
|
import { cn } from "@/lib/utils";
|
|
11
11
|
import constants from "@/constants/constants.json";
|
|
12
12
|
|
|
13
|
+
interface LanguageSwitcherProps {
|
|
14
|
+
className?: string;
|
|
15
|
+
style?: React.CSSProperties;
|
|
16
|
+
}
|
|
17
|
+
|
|
13
18
|
const languages: Record<string, string> =
|
|
14
19
|
constants?.site?.availableLanguages || {};
|
|
15
20
|
|
|
16
|
-
export function LanguageSwitcher() {
|
|
21
|
+
export function LanguageSwitcher({ className, style }: LanguageSwitcherProps) {
|
|
17
22
|
const { i18n } = useTranslation();
|
|
18
23
|
const currentLang = i18n.language;
|
|
19
24
|
|
|
@@ -23,7 +28,8 @@ export function LanguageSwitcher() {
|
|
|
23
28
|
<Button
|
|
24
29
|
variant="ghost"
|
|
25
30
|
size="sm"
|
|
26
|
-
className="h-9 px-2 text-sm font-medium"
|
|
31
|
+
className={cn("h-9 px-2 text-sm font-medium", className)}
|
|
32
|
+
style={style}
|
|
27
33
|
>
|
|
28
34
|
{languages?.[currentLang] || currentLang.toUpperCase()}
|
|
29
35
|
</Button>
|
|
@@ -5,12 +5,16 @@ interface LogoProps {
|
|
|
5
5
|
className?: string;
|
|
6
6
|
size?: "sm" | "md" | "lg" | "xl";
|
|
7
7
|
variant?: "default" | "light" | "dark";
|
|
8
|
+
style?: React.CSSProperties;
|
|
9
|
+
textStyle?: React.CSSProperties;
|
|
8
10
|
}
|
|
9
11
|
|
|
10
12
|
export function Logo({
|
|
11
13
|
className = "",
|
|
12
14
|
size = "md",
|
|
13
15
|
variant = "default",
|
|
16
|
+
style,
|
|
17
|
+
textStyle,
|
|
14
18
|
}: LogoProps) {
|
|
15
19
|
// Text boyutları
|
|
16
20
|
const textSizes = {
|
|
@@ -42,6 +46,7 @@ export function Logo({
|
|
|
42
46
|
return (
|
|
43
47
|
<Link
|
|
44
48
|
to="/"
|
|
49
|
+
style={style}
|
|
45
50
|
className={`flex items-center gap-1.5 sm:gap-2 md:gap-3 ${className}`}
|
|
46
51
|
>
|
|
47
52
|
{/* Logo Image (if exists) */}
|
|
@@ -55,6 +60,7 @@ export function Logo({
|
|
|
55
60
|
|
|
56
61
|
{/* Site Name */}
|
|
57
62
|
<span
|
|
63
|
+
style={textStyle}
|
|
58
64
|
className={`${textSizes[size]} font-bold ${currentVariant} truncate`}
|
|
59
65
|
>
|
|
60
66
|
{siteName}
|
|
@@ -9,6 +9,11 @@ import {
|
|
|
9
9
|
import { useTheme, type Theme } from "@/hooks/use-theme";
|
|
10
10
|
import { cn } from "@/lib/utils";
|
|
11
11
|
|
|
12
|
+
interface ThemeSwitcherProps {
|
|
13
|
+
className?: string;
|
|
14
|
+
style?: React.CSSProperties;
|
|
15
|
+
}
|
|
16
|
+
|
|
12
17
|
const themes: {
|
|
13
18
|
value: Theme;
|
|
14
19
|
label: string;
|
|
@@ -19,7 +24,7 @@ const themes: {
|
|
|
19
24
|
{ value: "system", label: "System", icon: Monitor },
|
|
20
25
|
];
|
|
21
26
|
|
|
22
|
-
export function ThemeSwitcher() {
|
|
27
|
+
export function ThemeSwitcher({ className, style }: ThemeSwitcherProps) {
|
|
23
28
|
const { theme, setTheme, effectiveTheme } = useTheme();
|
|
24
29
|
|
|
25
30
|
const currentTheme = themes.find((t) => t.value === theme);
|
|
@@ -33,7 +38,7 @@ export function ThemeSwitcher() {
|
|
|
33
38
|
return (
|
|
34
39
|
<DropdownMenu>
|
|
35
40
|
<DropdownMenuTrigger asChild>
|
|
36
|
-
<Button variant="ghost" size="sm" className="h-9 w-9 px-0">
|
|
41
|
+
<Button variant="ghost" size="sm" className={cn("h-9 w-9 px-0", className)} style={style}>
|
|
37
42
|
<CurrentIcon className="h-4 w-4" />
|
|
38
43
|
<span className="sr-only">Toggle theme</span>
|
|
39
44
|
</Button>
|