@kunver/new 3.1.0 → 3.2.0

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.
Files changed (102) hide show
  1. package/README.MD +28 -18
  2. package/dist/index.js +14 -8
  3. package/dist/templates/cmake-cpp/.clang-format +1 -0
  4. package/dist/templates/cmake-cpp/CMakeLists.txt +14 -0
  5. package/dist/templates/cmake-cpp/README.md +32 -0
  6. package/dist/templates/cmake-cpp/_clang-format +1 -0
  7. package/dist/templates/cmake-cpp/_gitignore +9 -0
  8. package/dist/templates/cmake-cpp/agents.md +8 -0
  9. package/dist/templates/{make-cpp → cmake-cpp}/include/example.hpp +1 -1
  10. package/dist/templates/cmake-cpp/manager.ts +276 -0
  11. package/dist/templates/{make-cpp → cmake-cpp}/src/main.cpp +1 -1
  12. package/dist/templates/electron-svelte/.vscode/launch.json +39 -39
  13. package/dist/templates/electron-svelte/.vscode/settings.json +15 -15
  14. package/dist/templates/electron-svelte/README.md +3 -3
  15. package/dist/templates/electron-svelte/_prettierignore +6 -0
  16. package/dist/templates/electron-svelte/_prettierrc.yaml +13 -0
  17. package/dist/templates/electron-svelte/electron-builder.yml +7 -7
  18. package/dist/templates/electron-svelte/electron.vite.config.ts +3 -3
  19. package/dist/templates/electron-svelte/manager.cjs +45 -43
  20. package/dist/templates/electron-svelte/package.json +44 -44
  21. package/dist/templates/electron-svelte/src/main/index.ts +19 -19
  22. package/dist/templates/electron-svelte/src/preload/index.d.ts +1 -1
  23. package/dist/templates/electron-svelte/src/preload/index.ts +4 -4
  24. package/dist/templates/electron-svelte/src/renderer/index.html +16 -16
  25. package/dist/templates/electron-svelte/src/renderer/src/assets/main.css +1 -1
  26. package/dist/templates/electron-svelte/src/renderer/src/env.d.ts +2 -2
  27. package/dist/templates/electron-svelte/src/renderer/src/main.ts +4 -4
  28. package/dist/templates/electron-svelte/svelte.config.mjs +1 -1
  29. package/dist/templates/electron-svelte/tsconfig.json +4 -4
  30. package/dist/templates/electron-svelte/tsconfig.node.json +11 -11
  31. package/dist/templates/electron-svelte/tsconfig.web.json +17 -17
  32. package/dist/templates/next-prisma/README.md +11 -11
  33. package/dist/templates/next-prisma/_prettierrc.json +12 -0
  34. package/dist/templates/next-prisma/app/globals.css +1 -1
  35. package/dist/templates/next-prisma/app/layout.tsx +21 -21
  36. package/dist/templates/next-prisma/app/page.tsx +7 -7
  37. package/dist/templates/next-prisma/lib/prisma.ts +11 -11
  38. package/dist/templates/next-prisma/manager.cjs +45 -43
  39. package/dist/templates/next-prisma/next.config.ts +3 -3
  40. package/dist/templates/next-prisma/package.json +33 -33
  41. package/dist/templates/next-prisma/postcss.config.mjs +2 -2
  42. package/dist/templates/next-prisma/tsconfig.json +27 -27
  43. package/dist/templates/react-ts-tw/README.md +1 -1
  44. package/dist/templates/react-ts-tw/_prettierrc.json +12 -0
  45. package/dist/templates/react-ts-tw/index.html +13 -13
  46. package/dist/templates/react-ts-tw/manager.cjs +45 -43
  47. package/dist/templates/react-ts-tw/package.json +30 -30
  48. package/dist/templates/react-ts-tw/src/App.tsx +9 -9
  49. package/dist/templates/react-ts-tw/src/index.css +1 -1
  50. package/dist/templates/react-ts-tw/src/main.tsx +5 -5
  51. package/dist/templates/react-ts-tw/src/vite-env.d.ts +1 -1
  52. package/dist/templates/react-ts-tw/tsconfig.app.json +27 -27
  53. package/dist/templates/react-ts-tw/tsconfig.json +1 -4
  54. package/dist/templates/react-ts-tw/tsconfig.node.json +25 -25
  55. package/dist/templates/react-ts-tw/vite.config.ts +2 -2
  56. package/dist/templates/wxt-solid/README.md +3 -3
  57. package/dist/templates/wxt-solid/agents.md +76 -76
  58. package/dist/templates/wxt-solid/assets/tailwind.css +1 -1
  59. package/dist/templates/wxt-solid/entrypoints/background.ts +3 -3
  60. package/dist/templates/wxt-solid/entrypoints/content/Content.tsx +1 -1
  61. package/dist/templates/wxt-solid/entrypoints/content/main.tsx +31 -31
  62. package/dist/templates/wxt-solid/entrypoints/options/App.tsx +0 -1
  63. package/dist/templates/wxt-solid/entrypoints/options/index.html +13 -13
  64. package/dist/templates/wxt-solid/entrypoints/options/main.tsx +6 -6
  65. package/dist/templates/wxt-solid/entrypoints/popup/App.tsx +7 -7
  66. package/dist/templates/wxt-solid/entrypoints/popup/index.html +13 -13
  67. package/dist/templates/wxt-solid/entrypoints/popup/main.tsx +6 -6
  68. package/dist/templates/wxt-solid/manager.cjs +45 -43
  69. package/dist/templates/wxt-solid/package.json +33 -33
  70. package/dist/templates/wxt-solid/tsconfig.json +7 -7
  71. package/dist/templates/wxt-solid/wxt.config.ts +18 -18
  72. package/dist/templates/wxt-svelte/.vscode/extensions.json +3 -3
  73. package/dist/templates/wxt-svelte/README.md +3 -3
  74. package/dist/templates/wxt-svelte/_prettierrc.json +11 -0
  75. package/dist/templates/wxt-svelte/agents.md +77 -77
  76. package/dist/templates/wxt-svelte/assets/tailwind.css +1 -1
  77. package/dist/templates/wxt-svelte/entrypoints/background.ts +3 -3
  78. package/dist/templates/wxt-svelte/entrypoints/content/index.ts +25 -25
  79. package/dist/templates/wxt-svelte/entrypoints/options/index.html +1 -1
  80. package/dist/templates/wxt-svelte/entrypoints/options/main.ts +9 -9
  81. package/dist/templates/wxt-svelte/entrypoints/popup/index.html +1 -1
  82. package/dist/templates/wxt-svelte/entrypoints/popup/main.ts +9 -9
  83. package/dist/templates/wxt-svelte/manager.cjs +45 -43
  84. package/dist/templates/wxt-svelte/package.json +36 -36
  85. package/dist/templates/wxt-svelte/tsconfig.json +6 -6
  86. package/dist/templates/wxt-svelte/wxt-env.d.ts +1 -1
  87. package/dist/templates/wxt-svelte/wxt.config.ts +18 -18
  88. package/dist/templates/wxt-vanilla/README.md +3 -3
  89. package/dist/templates/wxt-vanilla/_prettierrc.json +11 -0
  90. package/dist/templates/wxt-vanilla/agents.md +73 -73
  91. package/dist/templates/wxt-vanilla/entrypoints/background.ts +2 -2
  92. package/dist/templates/wxt-vanilla/entrypoints/content.ts +3 -3
  93. package/dist/templates/wxt-vanilla/entrypoints/popup/index.html +13 -13
  94. package/dist/templates/wxt-vanilla/entrypoints/popup/main.ts +1 -1
  95. package/dist/templates/wxt-vanilla/manager.cjs +45 -43
  96. package/dist/templates/wxt-vanilla/package.json +25 -25
  97. package/dist/templates/wxt-vanilla/tsconfig.json +3 -3
  98. package/dist/templates/wxt-vanilla/wxt.config.ts +13 -13
  99. package/package.json +55 -42
  100. package/dist/templates/make-cpp/Makefile +0 -44
  101. package/dist/templates/make-cpp/README.md +0 -15
  102. /package/dist/templates/{make-cpp → cmake-cpp}/src/example.cpp +0 -0
package/README.MD CHANGED
@@ -1,35 +1,45 @@
1
1
  # Opiniated Project Starter
2
2
 
3
- Cli tool for creating new projects with pre-configured settings.
3
+ CLI tool for creating new projects with pre-configured settings.
4
4
 
5
- [![npm v](https://img.shields.io/npm/v/@kunver/new)](https://www.npmjs.com/package/@kunver/new)
6
- [![npm downloads](https://img.shields.io/npm/dm/@kunver/new)](https://www.npmjs.com/package/@kunver/new)
7
-
8
- ## Using
5
+ ## Usage
9
6
 
10
7
  ```bash
11
8
  pnpx | npx | bunx @kunver/new
12
9
  ```
13
10
 
14
- ## Starters
11
+ The CLI asks for a project name, starter type, package manager when needed, and whether the project should be opened in your editor.
12
+
13
+ ## Current starters
14
+
15
+ - React + TypeScript + Tailwind
16
+ - Next.js + Prisma
17
+ - WXT
18
+ - Svelte
19
+ - Vanilla
20
+ - Solid
21
+ - Electron + Svelte
22
+ - UV Notebook
23
+ - C++ + CMake
15
24
 
16
- ### Ready to use
25
+ ## Notes
17
26
 
18
- React
27
+ - C++ + CMake projects include a `manager.ts` bridge for commands like `bun manager.ts dev` and `bun manager.ts build`.
28
+ - The C++ + CMake starter automatically updates the CMake project name to the folder name you enter.
29
+ - Electron + Svelte is created without auto-installing dependencies.
19
30
 
20
- Wxt + Svelte
31
+ ## Package managers
21
32
 
22
- Wxt + Vanilla
33
+ - Bun
34
+ - pnpm
35
+ - npm
23
36
 
24
- Next.js + Prisma
37
+ Some starters intentionally skip package manager selection because they do not need JS dependencies.
25
38
 
26
- Python Jupyter Notebook
39
+ ## Output
27
40
 
28
- ### Work in progress
41
+ Generated templates live under [src/public/templates](src/public/templates) in this repository.
29
42
 
30
- ### Will be added
43
+ ## Status
31
44
 
32
- 🟡 Wxt Solid
33
- 🟡 C++ CMake
34
- 🟡 Rust
35
- 🟡 Rust Tauri
45
+ This project is intentionally opinionated and focused on a small set of starters.
package/dist/index.js CHANGED
@@ -1,15 +1,21 @@
1
- import H,{readFileSync,existsSync,constants,promises}from'fs';import z,{dirname,join}from'path';import {input,select,confirm}from'@inquirer/prompts';import c from'chalk';import {access,mkdir,writeFile,rm,readFile}from'fs/promises';import {spawn}from'child_process';import W from'ora';import {execa}from'execa';import {fileURLToPath}from'url';async function j(e){let{name:o,cwd:t=process.cwd()}=e,a=join(t,o);try{await access(a,constants.F_OK);}catch{await mkdir(a,{recursive:true});}let r=join(a,"main.ipynb");await writeFile(r,"");}var B=["react-ts-tw","next-ts-prisma","wxt...","electron-svelte","python-notebook","cpp-makefile"],_=["bun","pnpm","npm"],$=["antigravity","windsurf","no","cursor","code"],A=["svelte","vanilla","solid"];async function h(e,o,t){switch(e){case "pnpm":return await ne(o,t);case "bun":return await se(o,t);default:return false}}async function ne(e,o){let t=W("Approving builds for "+c.blue(e)).start();try{return new Promise(a=>{let r=spawn("pnpm",["approve-builds"],{cwd:`${o}/${e}`,stdio:["pipe","inherit","inherit"],shell:!0});setTimeout(()=>{r.stdin?.write(`a
1
+ import Q,{readFileSync,existsSync,promises}from'fs';import q,{dirname,join}from'path';import {input,select,confirm}from'@inquirer/prompts';import c from'chalk';import {mkdir,writeFile,rm,readFile}from'fs/promises';import {execa}from'execa';import {spawn}from'child_process';import X from'ora';import {fileURLToPath}from'url';async function P(e){let{name:n,cwd:t=process.cwd()}=e,a=join(t,n),r=join(a,"main.ipynb");await mkdir(a,{recursive:true}),await execa("uv",["init","--python","3.12"],{cwd:a,stdout:"inherit",stderr:"inherit"}),await execa("uv",["add","numpy"],{cwd:a,stdout:"inherit",stderr:"inherit"}),await writeFile(r,ie(n),"utf8");}function ie(e){return `${JSON.stringify({cells:[{cell_type:"markdown",metadata:{language:"markdown"},source:[`# ${e}
2
+ `,`
3
+ `,`Starter notebook with NumPy ready to use.
4
+ `]},{cell_type:"code",execution_count:null,metadata:{language:"python"},outputs:[],source:[`import numpy as np
5
+ `,`np.arange(5)
6
+ `]}],metadata:{kernelspec:{display_name:"Python 3.12",language:"python",name:"python3"},language_info:{name:"python",version:"3.12"}},nbformat:4,nbformat_minor:5},null,2)}
7
+ `}var W=["react-ts-tw","next-ts-prisma","wxt","electron-svelte","uv-notebook","cmake-cpp"],R=["bun","pnpm","npm"],z=["antigravity","windsurf","no","cursor","code"],H=["svelte","vanilla","solid"];async function k(e,n,t){switch(e){case "pnpm":return await le(n,t);case "bun":return await pe(n,t);default:return false}}async function le(e,n){let t=X("Approving builds for "+c.blue(e)).start();try{return new Promise(a=>{let r=spawn("pnpm",["approve-builds"],{cwd:`${n}/${e}`,stdio:["pipe","inherit","inherit"],shell:!0});setTimeout(()=>{r.stdin?.write(`a
2
8
  `),setTimeout(()=>{r.stdin?.write(`y
3
- `),r.stdin?.end();},1e3);},2e3),r.on("close",s=>{s===0?(t.succeed("Approved builds for "+c.blue(e)),a(!0)):(t.fail("Failed to approve builds for "+c.blue(e)),a(!1));}),r.on("error",s=>{t.fail("Failed to approve builds for "+c.blue(e)),console.error(s),a(!1);});})}catch(a){return t.fail("Failed to approve builds for "+c.blue(e)),console.error(a),false}}async function se(e,o){let t=`cd ${e} && bun pm trust --all`,a=W("Approving builds for "+c.blue(e)).start();try{return await execa(t,{shell:!0,cwd:o}),a.succeed("Approved builds for "+c.blue(e)),!0}catch{return a.fail("Failed to approve builds for "+c.blue(e)),false}}async function P(e,o,t){let a=`cd ${o} && ${e} install`;console.log("Installing dependencies with "+c.cyan(e)+`
4
- `);try{return await execa(a,{shell:!0,cwd:t,stdout:"inherit",stderr:"inherit"}),!0}catch{return false}}async function M(e,o){let t=W("Copying template folder...").start();try{await promises.cp(e,o,{recursive:!0});let a=z.join(o,"_gitignore"),r=z.join(o,".gitignore");try{await promises.rename(a,r);}catch{}return t.succeed("Copied template folder"),!0}catch{return t.fail("Failed to copy template folder"),false}}async function F(e,o,t){let a=join(t,o,"package.json"),r=await H.promises.readFile(a,"utf-8"),s=JSON.parse(r);e==="bun"?s.scripts.manager=`bun manager.cjs ${e}`:s.scripts.manager=`node manager.cjs ${e}`,await H.promises.writeFile(a,JSON.stringify(s,null,2));}async function I(e,o,t){console.log(c.white("Opening "+c.blue(e)+" in "+c.green(t)));try{return await execa(`${t} ${e}`,{shell:!0,cwd:o}),!0}catch(a){return console.error(c.red("Failed to open project in editor:"),a),false}}function ge(){return typeof __dirname<"u"?__dirname:typeof import.meta<"u"&&import.meta.url?dirname(fileURLToPath(import.meta.url)):process.cwd()}var K=ge();async function i(e){let{templateName:o,name:t,packageManager:a,cwd:r=process.cwd(),addManager:s=true,changeName:p=true,approveBuild:x=true,installDependency:w=true,onBeforeInstall:f}=e,n=join(K,"../public/templates",o),y=join(K,"templates",o),T=existsSync(n)?n:y;try{if(!await M(T,join(r,t)))throw new Error("Failed to copy template folder");if(f&&await f(join(r,t)),w&&!await P(a,t,r))throw new Error("Failed to install dependencies");return s&&await F(a,t,r),x&&await h(a,t,r),p&&await O(join(r,t),t),!0}catch(l){throw console.error("Error creating project:",l),l}}async function O(e,o){try{let t=join(e,"package.json"),a=await readFile(t,"utf-8"),r=JSON.parse(a);return r.name=o.toLowerCase().replace(/\s+/g,"-"),await writeFile(t,JSON.stringify(r,null,2)+`
5
- `),!0}catch(t){return console.error("Error updating project name:",t),false}}async function S(e){let{name:o,packageManager:t,selectedFramework:a}=e;try{let r=A,s=r.includes("svelte")?"svelte":r[0],p;a&&r.includes(a)?p=a:p=await select({message:c.bold.magenta("Select a framework for WXT"),choices:r.map(n=>({name:n.charAt(0).toUpperCase()+n.slice(1),value:n})),default:s});let x=await confirm({message:c.bold.cyan("Use i18n? (@wxt-dev/i18n)"),default:!1}),w=!1;(p==="svelte"||p==="solid")&&(w=await confirm({message:c.bold.cyan("Do you want to use content UI?"),default:!1}));let f=async n=>{if((p==="svelte"||p==="solid")&&!w){let V=join(n,"entrypoints","content");await rm(V,{recursive:!0,force:!0});let Y=join(n,"entrypoints","content.ts");await writeFile(Y,`export default defineContentScript({
9
+ `),r.stdin?.end();},1e3);},2e3),r.on("close",i=>{i===0?(t.succeed("Approved builds for "+c.blue(e)),a(!0)):(t.fail("Failed to approve builds for "+c.blue(e)),a(!1));}),r.on("error",i=>{t.fail("Failed to approve builds for "+c.blue(e)),console.error(i),a(!1);});})}catch(a){return t.fail("Failed to approve builds for "+c.blue(e)),console.error(a),false}}async function pe(e,n){let t=`cd ${e} && bun pm trust --all`,a=X("Approving builds for "+c.blue(e)).start();try{return await execa(t,{shell:!0,cwd:n}),a.succeed("Approved builds for "+c.blue(e)),!0}catch{return a.fail("Failed to approve builds for "+c.blue(e)),false}}async function M(e,n,t){let a=`cd ${n} && ${e} install`;console.log("Installing dependencies with "+c.cyan(e)+`
10
+ `);try{return await execa(a,{shell:!0,cwd:t,stdout:"inherit",stderr:"inherit"}),!0}catch{return false}}async function G(e){let n=await promises.readdir(e,{withFileTypes:true});for(let t of n){let a=q.join(e,t.name),r=a;t.name.startsWith("_")&&t.name.length>1&&(r=q.join(e,`.${t.name.slice(1)}`),await promises.rename(a,r)),t.isDirectory()&&await G(r);}}async function F(e,n){let t=X("Copying template folder...").start();try{return await promises.cp(e,n,{recursive:!0}),await G(n),t.succeed("Copied template folder"),!0}catch{return t.fail("Failed to copy template folder"),false}}async function N(e,n,t){let a=join(t,n,"package.json"),r=await Q.promises.readFile(a,"utf-8"),i=JSON.parse(r);e==="bun"?i.scripts.manager=`bun manager.cjs ${e}`:i.scripts.manager=`node manager.cjs ${e}`,await Q.promises.writeFile(a,JSON.stringify(i,null,2));}async function I(e,n,t){console.log(c.white("Opening "+c.blue(e)+" in "+c.green(t)));try{return await execa(`${t} ${e}`,{shell:!0,cwd:n}),!0}catch(a){return console.error(c.red("Failed to open project in editor:"),a),false}}function he(){return typeof __dirname<"u"?__dirname:typeof import.meta<"u"&&import.meta.url?dirname(fileURLToPath(import.meta.url)):process.cwd()}var V=he();async function s(e){let{templateName:n,name:t,packageManager:a,cwd:r=process.cwd(),addManager:i=true,changeName:l=true,approveBuild:T=true,installDependency:w=true,onBeforeInstall:u}=e,o=join(V,"../public/templates",n),y=join(V,"templates",n),v=existsSync(o)?o:y;try{if(!await F(v,join(r,t)))throw new Error("Failed to copy template folder");if(u&&await u(join(r,t)),w&&!await M(a,t,r))throw new Error("Failed to install dependencies");return i&&await N(a,t,r),T&&await k(a,t,r),l&&await S(join(r,t),t),!0}catch(p){throw console.error("Error creating project:",p),p}}async function S(e,n){try{let t=join(e,"package.json"),a=await readFile(t,"utf-8"),r=JSON.parse(a);return r.name=n.toLowerCase().replace(/\s+/g,"-"),await writeFile(t,JSON.stringify(r,null,2)+`
11
+ `),!0}catch(t){return console.error("Error updating project name:",t),false}}async function E(e,n){try{let t=join(e,"CMakeLists.txt"),a=await readFile(t,"utf-8"),r=a.replace(/project\s*\(\s*(?:"[^"]+"|[^\s\)]+)([\s\S]*?)\)/i,`project("${n}"$1)`);return r===a?!1:(await writeFile(t,r),!0)}catch(t){return console.error("Error updating CMake project name:",t),false}}async function O(e){console.log(c.white("Configuring CMake project in "+c.blue(e)));try{return await execa("cmake -S . -B build",{shell:!0,cwd:e,stdout:"inherit",stderr:"inherit"}),console.log(c.green("CMake project configured successfully")),!0}catch{return console.log(c.yellow("Automatic CMake configure skipped. Run `cmake -S . -B build` manually if needed.")),false}}async function _(e){let{name:n,packageManager:t,selectedFramework:a}=e;try{let r=H,i=r.includes("svelte")?"svelte":r[0],l;a&&r.includes(a)?l=a:l=await select({message:c.bold.magenta("Select a framework for WXT"),choices:r.map(o=>({name:o.charAt(0).toUpperCase()+o.slice(1),value:o})),default:i});let T=await confirm({message:c.bold.cyan("Use i18n? (@wxt-dev/i18n)"),default:!1}),w=!1;(l==="svelte"||l==="solid")&&(w=await confirm({message:c.bold.cyan("Do you want to use content UI?"),default:!1}));let u=async o=>{if((l==="svelte"||l==="solid")&&!w){let ae=join(o,"entrypoints","content");await rm(ae,{recursive:!0,force:!0});let re=join(o,"entrypoints","content.ts");await writeFile(re,`export default defineContentScript({
6
12
  matches: ["*://*.google.com/*"],
7
13
  main() {
8
14
  console.log("Hello content.");
9
15
  },
10
16
  });
11
- `,"utf-8");}if(!x)return;let y=join(n,"package.json"),T=await readFile(y,"utf-8"),l=JSON.parse(T);l.devDependencies=l.devDependencies||{},l.devDependencies["@wxt-dev/i18n"]="0.2.5",await writeFile(y,JSON.stringify(l,null,2),"utf-8");let v=join(n,"wxt.config.ts"),m=await readFile(v,"utf-8");m=m.replace("manifest: {",`manifest: {
17
+ `,"utf-8");}if(!T)return;let y=join(o,"package.json"),v=await readFile(y,"utf-8"),p=JSON.parse(v);p.devDependencies=p.devDependencies||{},p.devDependencies["@wxt-dev/i18n"]="0.2.5",await writeFile(y,JSON.stringify(p,null,2),"utf-8");let j=join(o,"wxt.config.ts"),m=await readFile(j,"utf-8");m=m.replace("manifest: {",`manifest: {
12
18
  default_locale: "en",`),m.includes("modules: [")?m=m.replace("modules: [",'modules: ["@wxt-dev/i18n/module", '):m=m.replace("export default defineConfig({",`export default defineConfig({
13
- modules: ["@wxt-dev/i18n/module"],`),await writeFile(v,m,"utf-8");let C=join(n,"locales");await mkdir(C,{recursive:!0}),await writeFile(join(C,"en.yml"),`hello: Hello!
14
- `,"utf-8");};switch(p){case "svelte":await i({templateName:"wxt-svelte",name:o,packageManager:t,onBeforeInstall:f});break;case "solid":await i({templateName:"wxt-solid",name:o,packageManager:t,onBeforeInstall:f});break;case "vanilla":await i({templateName:"wxt-vanilla",name:o,packageManager:t,onBeforeInstall:f});break;default:break}}catch(r){console.error(r);}}async function N(e){switch(e.projectType){case "react-ts-tw":await i({templateName:"react-ts-tw",name:e.name,packageManager:e.packageManager});break;case "next-ts-prisma":await i({templateName:"next-ts-prisma",name:e.name,packageManager:e.packageManager});break;case "wxt...":await S({name:e.name,packageManager:e.packageManager});break;case "electron-svelte":await i({templateName:"electron-svelte",name:e.name,packageManager:e.packageManager,installDependency:false,approveBuild:false}),console.log(c.yellow("Dependencies not installed. Please install dependencies manually"));break;case "python-notebook":await j({name:e.name});break;case "cpp-makefile":await i({templateName:"make-cpp",name:e.name,packageManager:"bun",addManager:false,approveBuild:false,installDependency:false});default:console.log(c.red("Project Type Not Implemented"),e.projectType);break}e.openInEditor!=="no"&&await I(e.name,process.cwd(),e.openInEditor);}var Oe=fileURLToPath(import.meta.url),Ee=dirname(Oe),Se=join(Ee,"../package.json"),Ne=JSON.parse(readFileSync(Se,"utf8")),De=Ne.version;console.log(c.green("Kunver v"+c.bold(De)+`
15
- `));var Ce=await input({message:c.bold.blue("Enter a project name"),default:c.gray("my-project"),validate:e=>!e||e.trim().length<2?c.red("Project name must be at least 2 characters"):/^[a-z0-9]+(-[a-z0-9]+)*$/.test(e)?H.existsSync(z.resolve(process.cwd(),e))?c.red("A folder with that name already exists"):true:c.red("Only lowercase letters, numbers, and single hyphens allowed. No spaces or special characters.")}),G=await select({message:c.bold.yellow("Select a project type"),default:"react-ts-tw",choices:B}),Q="bun";G!=="python-notebook"&&(Q=await select({message:c.bold.green("Select a package manager"),choices:_,default:"bun"}));var Je=await select({message:c.bold.cyan("Open in editor?"),choices:$,default:"no"}),Be={projectType:G,packageManager:Q,name:Ce,openInEditor:Je};await N(Be);
19
+ modules: ["@wxt-dev/i18n/module"],`),await writeFile(j,m,"utf-8");let A=join(o,"locales");await mkdir(A,{recursive:!0}),await writeFile(join(A,"en.yml"),`hello: Hello!
20
+ `,"utf-8");};switch(l){case "svelte":await s({templateName:"wxt-svelte",name:n,packageManager:t,onBeforeInstall:u});break;case "solid":await s({templateName:"wxt-solid",name:n,packageManager:t,onBeforeInstall:u});break;case "vanilla":await s({templateName:"wxt-vanilla",name:n,packageManager:t,onBeforeInstall:u});break;default:break}}catch(r){console.error(r);}}async function B(e){switch(e.projectType){case "react-ts-tw":await s({templateName:"react-ts-tw",name:e.name,packageManager:e.packageManager});break;case "next-ts-prisma":await s({templateName:"next-prisma",name:e.name,packageManager:e.packageManager});break;case "wxt":await _({name:e.name,packageManager:e.packageManager});break;case "electron-svelte":await s({templateName:"electron-svelte",name:e.name,packageManager:e.packageManager,installDependency:false,approveBuild:false}),console.log(c.yellow("Dependencies not installed. Please install dependencies manually"));break;case "uv-notebook":await P({name:e.name});break;case "cmake-cpp":await s({templateName:"cmake-cpp",name:e.name,packageManager:"bun",addManager:false,approveBuild:false,installDependency:false,changeName:false,onBeforeInstall:async n=>{await E(n,e.name),await O(n);}});break;default:console.log(c.red("Project Type Not Implemented"),e.projectType);break}e.openInEditor!=="no"&&await I(e.name,process.cwd(),e.openInEditor);}var $e=fileURLToPath(import.meta.url),Je=dirname($e),Ae=join(Je,"../package.json"),Le=JSON.parse(readFileSync(Ae,"utf8")),Ue=Le.version;console.log(c.green("Kunver v"+c.bold(Ue)+`
21
+ `));var We=await input({message:c.bold.blue("Enter a project name"),default:c.gray("my-project"),validate:e=>!e||e.trim().length<2?c.red("Project name must be at least 2 characters"):/^[a-z0-9]+(-[a-z0-9]+)*$/.test(e)?Q.existsSync(q.resolve(process.cwd(),e))?c.red("A folder with that name already exists"):true:c.red("Only lowercase letters, numbers, and single hyphens allowed. No spaces or special characters.")}),$=await select({message:c.bold.yellow("Select a project type"),default:"react-ts-tw",choices:W}),te="bun";$!=="uv-notebook"&&$!=="cmake-cpp"&&(te=await select({message:c.bold.green("Select a package manager"),choices:R,default:"bun"}));var Re=await select({message:c.bold.cyan("Open in editor?"),choices:z,default:"no"}),ze={projectType:$,packageManager:te,name:We,openInEditor:Re};await B(ze);
@@ -0,0 +1 @@
1
+ BasedOnStyle: Google
@@ -0,0 +1,14 @@
1
+ cmake_minimum_required(VERSION 3.20)
2
+
3
+ project(cmake_cpp_template LANGUAGES CXX)
4
+
5
+ set(CMAKE_CXX_STANDARD 20)
6
+ set(CMAKE_CXX_STANDARD_REQUIRED ON)
7
+ set(CMAKE_CXX_EXTENSIONS OFF)
8
+
9
+ add_executable(${PROJECT_NAME}
10
+ src/main.cpp
11
+ src/example.cpp
12
+ )
13
+
14
+ target_include_directories(${PROJECT_NAME} PRIVATE include)
@@ -0,0 +1,32 @@
1
+ # Cpp + CMake template
2
+
3
+ Opinionated C++ project starter with CMake build system.
4
+
5
+ ## Requirements
6
+
7
+ - CMake 3.20+
8
+ - Bun
9
+ - GCC, Clang, or MSVC
10
+ - VS Code C/C++ or CMake Tools extension
11
+
12
+ ## CLI behavior
13
+
14
+ - `kunver-new` runs `cmake -S . -B build` automatically after creating the project when CMake is available.
15
+ - If that step fails, the project is still created and you can run the command manually.
16
+
17
+ ## Manager bridge
18
+
19
+ - `bun manager.ts dev` configures, builds, and runs the app.
20
+ - `bun manager.ts build` configures if needed, then builds.
21
+ - `bun manager.ts run` runs the latest built executable.
22
+ - `bun manager.ts rebuild` deletes `build/`, then configures and builds again.
23
+ - `bun manager.ts clean` deletes `build/`.
24
+ - `bun manager.ts doctor` checks required files.
25
+
26
+ ## Raw CMake usage
27
+
28
+ - Configure: `cmake -S . -B build`
29
+ - Build: `cmake --build build`
30
+ - Run: use the executable generated inside `build/` by your chosen CMake generator.
31
+
32
+ Note: `kunver` rewrites the CMake project name to the folder name you enter during creation, and `manager.ts` reads that same name from `CMakeLists.txt`.
@@ -0,0 +1 @@
1
+ BasedOnStyle: Google
@@ -0,0 +1,9 @@
1
+ # Build artifacts
2
+ build/
3
+
4
+ # CMake cache and generated files
5
+ CMakeCache.txt
6
+ CMakeFiles/
7
+ cmake_install.cmake
8
+ compile_commands.json
9
+ Makefile
@@ -0,0 +1,8 @@
1
+ # About Project
2
+
3
+ - This is a minimal C++ project template that uses CMake as its build system.
4
+ - Source files live in `src/`, headers live in `include/`, and build output is generated in `build/`.
5
+ - The project targets C++20 and expects CMake 3.20 or newer.
6
+ - Prefer using `bun manager.ts dev` for configure + build + run during development.
7
+ - Other common commands are `bun manager.ts build`, `bun manager.ts run`, and `bun manager.ts clean`.
8
+ - If you change project structure, keep `CMakeLists.txt` in sync.
@@ -2,4 +2,4 @@
2
2
 
3
3
  #include <iostream>
4
4
 
5
- void printHello();
5
+ void printHello();
@@ -0,0 +1,276 @@
1
+ import { existsSync, readdirSync, readFileSync, rmSync } from "node:fs"
2
+ import { join } from "node:path"
3
+ import { platform } from "node:os"
4
+ import { spawn } from "node:child_process"
5
+
6
+ type CommandName = "help" | "doctor" | "configure" | "build" | "run" | "dev" | "rebuild" | "clean"
7
+
8
+ type ManagerOptions = {
9
+ config?: string
10
+ }
11
+
12
+ const ROOT_DIR = process.cwd()
13
+ const BUILD_DIR = join(ROOT_DIR, "build")
14
+ const IS_WINDOWS = platform() === "win32"
15
+
16
+ function print(message: string) {
17
+ process.stdout.write(`${message}\n`)
18
+ }
19
+
20
+ function printError(message: string) {
21
+ process.stderr.write(`${message}\n`)
22
+ }
23
+
24
+ function getProjectName() {
25
+ const cmakeListsPath = join(ROOT_DIR, "CMakeLists.txt")
26
+
27
+ if (!existsSync(cmakeListsPath)) {
28
+ return null
29
+ }
30
+
31
+ const cmakeListsContent = readFileSync(cmakeListsPath, "utf-8")
32
+ const match = cmakeListsContent.match(/project\s*\(\s*(?:"([^"]+)"|([^\s\)]+))/i)
33
+
34
+ return match?.[1] ?? match?.[2] ?? null
35
+ }
36
+
37
+ function parseArgs(argv: string[]) {
38
+ const [commandArg, ...rest] = argv
39
+ const command = (commandArg ?? "help") as CommandName
40
+ const options: ManagerOptions = {}
41
+
42
+ for (let index = 0; index < rest.length; index += 1) {
43
+ const arg = rest[index]
44
+
45
+ if ((arg === "--config" || arg === "-c") && rest[index + 1]) {
46
+ options.config = rest[index + 1]
47
+ index += 1
48
+ }
49
+ }
50
+
51
+ return { command, options }
52
+ }
53
+
54
+ function runCommand(command: string, args: string[], cwd = ROOT_DIR) {
55
+ return new Promise<boolean>(resolve => {
56
+ const child = spawn(command, args, {
57
+ cwd,
58
+ stdio: "inherit",
59
+ shell: false,
60
+ })
61
+
62
+ child.on("close", code => {
63
+ resolve(code === 0)
64
+ })
65
+
66
+ child.on("error", () => {
67
+ resolve(false)
68
+ })
69
+ })
70
+ }
71
+
72
+ async function ensureCmakeAvailable() {
73
+ const ok = await runCommand("cmake", ["--version"])
74
+ if (!ok) {
75
+ printError("CMake not found. Install CMake and ensure it is available in PATH.")
76
+ }
77
+ return ok
78
+ }
79
+
80
+ async function configure() {
81
+ print("Configuring project with CMake...")
82
+ return runCommand("cmake", ["-S", ".", "-B", "build"])
83
+ }
84
+
85
+ async function build(config?: string) {
86
+ print("Building project...")
87
+ const args = ["--build", "build"]
88
+
89
+ if (config) {
90
+ args.push("--config", config)
91
+ }
92
+
93
+ return runCommand("cmake", args)
94
+ }
95
+
96
+ function getCandidateExecutablePaths(config?: string) {
97
+ const projectName = getProjectName()
98
+ if (!projectName) {
99
+ return []
100
+ }
101
+
102
+ const executableName = IS_WINDOWS ? `${projectName}.exe` : projectName
103
+ const requestedConfig = config ? [config] : []
104
+ const commonConfigs = ["Debug", "Release", "RelWithDebInfo", "MinSizeRel"]
105
+ const configDirs = [...requestedConfig, ...commonConfigs]
106
+ const uniqueConfigDirs = [...new Set(configDirs)]
107
+
108
+ return [join(BUILD_DIR, executableName), ...uniqueConfigDirs.map(dir => join(BUILD_DIR, dir, executableName))]
109
+ }
110
+
111
+ function findBuiltExecutable(config?: string) {
112
+ const projectName = getProjectName()
113
+ if (!projectName) {
114
+ return null
115
+ }
116
+
117
+ for (const candidate of getCandidateExecutablePaths(config)) {
118
+ if (existsSync(candidate)) {
119
+ return candidate
120
+ }
121
+ }
122
+
123
+ if (!existsSync(BUILD_DIR)) {
124
+ return null
125
+ }
126
+
127
+ const topLevelEntries = readdirSync(BUILD_DIR, { withFileTypes: true })
128
+ for (const entry of topLevelEntries) {
129
+ if (!entry.isDirectory()) {
130
+ continue
131
+ }
132
+
133
+ const executableName = IS_WINDOWS ? `${projectName}.exe` : projectName
134
+ const candidate = join(BUILD_DIR, entry.name, executableName)
135
+ if (existsSync(candidate)) {
136
+ return candidate
137
+ }
138
+ }
139
+
140
+ return null
141
+ }
142
+
143
+ async function runBuiltApp(config?: string) {
144
+ const executablePath = findBuiltExecutable(config)
145
+
146
+ if (!executablePath) {
147
+ printError("Built executable not found. Run `bun manager.ts build` first.")
148
+ return false
149
+ }
150
+
151
+ print(`Running ${executablePath} ...`)
152
+ return runCommand(executablePath, [], ROOT_DIR)
153
+ }
154
+
155
+ function clean() {
156
+ if (!existsSync(BUILD_DIR)) {
157
+ print("Build directory does not exist. Nothing to clean.")
158
+ return true
159
+ }
160
+
161
+ rmSync(BUILD_DIR, { recursive: true, force: true })
162
+ print("Removed build directory.")
163
+ return true
164
+ }
165
+
166
+ function doctor() {
167
+ print("Checking project structure...")
168
+
169
+ const requiredPaths = ["CMakeLists.txt", "src/main.cpp", "src/example.cpp", "include/example.hpp"]
170
+ let ok = true
171
+
172
+ for (const requiredPath of requiredPaths) {
173
+ if (!existsSync(join(ROOT_DIR, requiredPath))) {
174
+ printError(`Missing required file: ${requiredPath}`)
175
+ ok = false
176
+ }
177
+ }
178
+
179
+ if (!getProjectName()) {
180
+ printError("Could not determine the project name from CMakeLists.txt")
181
+ ok = false
182
+ }
183
+
184
+ return ok
185
+ }
186
+
187
+ function printHelp() {
188
+ print("CMake C++ manager")
189
+ print("")
190
+ print("Usage:")
191
+ print(" bun manager.ts <command> [--config Debug]")
192
+ print("")
193
+ print("Commands:")
194
+ print(" help Show this help message")
195
+ print(" doctor Check whether required files exist")
196
+ print(" configure Run `cmake -S . -B build`")
197
+ print(" build Configure if needed, then build the project")
198
+ print(" run Run the built executable")
199
+ print(" dev Configure, build, and run the project")
200
+ print(" rebuild Remove build directory, then configure and build again")
201
+ print(" clean Remove the build directory")
202
+ }
203
+
204
+ async function main() {
205
+ const { command, options } = parseArgs(process.argv.slice(2))
206
+ const validCommands: CommandName[] = ["help", "doctor", "configure", "build", "run", "dev", "rebuild", "clean"]
207
+
208
+ if (!validCommands.includes(command)) {
209
+ printError(`Unknown command: ${command}`)
210
+ printHelp()
211
+ process.exit(1)
212
+ }
213
+
214
+ if (command === "help") {
215
+ printHelp()
216
+ return
217
+ }
218
+
219
+ if (command === "doctor") {
220
+ const ok = doctor()
221
+ process.exit(ok ? 0 : 1)
222
+ }
223
+
224
+ if (command === "clean") {
225
+ const ok = clean()
226
+ process.exit(ok ? 0 : 1)
227
+ }
228
+
229
+ if (!doctor()) {
230
+ process.exit(1)
231
+ }
232
+
233
+ if (!(await ensureCmakeAvailable())) {
234
+ process.exit(1)
235
+ }
236
+
237
+ if (command === "configure") {
238
+ process.exit((await configure()) ? 0 : 1)
239
+ }
240
+
241
+ if (command === "build") {
242
+ if (!existsSync(BUILD_DIR) && !(await configure())) {
243
+ process.exit(1)
244
+ }
245
+
246
+ process.exit((await build(options.config)) ? 0 : 1)
247
+ }
248
+
249
+ if (command === "run") {
250
+ process.exit((await runBuiltApp(options.config)) ? 0 : 1)
251
+ }
252
+
253
+ if (command === "dev") {
254
+ if (!(await configure())) {
255
+ process.exit(1)
256
+ }
257
+
258
+ if (!(await build(options.config))) {
259
+ process.exit(1)
260
+ }
261
+
262
+ process.exit((await runBuiltApp(options.config)) ? 0 : 1)
263
+ }
264
+
265
+ if (command === "rebuild") {
266
+ clean()
267
+
268
+ if (!(await configure())) {
269
+ process.exit(1)
270
+ }
271
+
272
+ process.exit((await build(options.config)) ? 0 : 1)
273
+ }
274
+ }
275
+
276
+ await main()
@@ -3,4 +3,4 @@
3
3
  int main() {
4
4
  printHello();
5
5
  return 0;
6
- }
6
+ }
@@ -1,39 +1,39 @@
1
- {
2
- "version": "0.2.0",
3
- "configurations": [
4
- {
5
- "name": "Debug Main Process",
6
- "type": "node",
7
- "request": "launch",
8
- "cwd": "${workspaceRoot}",
9
- "runtimeExecutable": "${workspaceRoot}/node_modules/.bin/electron-vite",
10
- "windows": {
11
- "runtimeExecutable": "${workspaceRoot}/node_modules/.bin/electron-vite.cmd"
12
- },
13
- "runtimeArgs": ["--sourcemap"],
14
- "env": {
15
- "REMOTE_DEBUGGING_PORT": "9222"
16
- }
17
- },
18
- {
19
- "name": "Debug Renderer Process",
20
- "port": 9222,
21
- "request": "attach",
22
- "type": "chrome",
23
- "webRoot": "${workspaceFolder}/src/renderer",
24
- "timeout": 60000,
25
- "presentation": {
26
- "hidden": true
27
- }
28
- }
29
- ],
30
- "compounds": [
31
- {
32
- "name": "Debug All",
33
- "configurations": ["Debug Main Process", "Debug Renderer Process"],
34
- "presentation": {
35
- "order": 1
36
- }
37
- }
38
- ]
39
- }
1
+ {
2
+ "version": "0.2.0",
3
+ "configurations": [
4
+ {
5
+ "name": "Debug Main Process",
6
+ "type": "node",
7
+ "request": "launch",
8
+ "cwd": "${workspaceRoot}",
9
+ "runtimeExecutable": "${workspaceRoot}/node_modules/.bin/electron-vite",
10
+ "windows": {
11
+ "runtimeExecutable": "${workspaceRoot}/node_modules/.bin/electron-vite.cmd"
12
+ },
13
+ "runtimeArgs": ["--sourcemap"],
14
+ "env": {
15
+ "REMOTE_DEBUGGING_PORT": "9222"
16
+ }
17
+ },
18
+ {
19
+ "name": "Debug Renderer Process",
20
+ "port": 9222,
21
+ "request": "attach",
22
+ "type": "chrome",
23
+ "webRoot": "${workspaceFolder}/src/renderer",
24
+ "timeout": 60000,
25
+ "presentation": {
26
+ "hidden": true
27
+ }
28
+ }
29
+ ],
30
+ "compounds": [
31
+ {
32
+ "name": "Debug All",
33
+ "configurations": ["Debug Main Process", "Debug Renderer Process"],
34
+ "presentation": {
35
+ "order": 1
36
+ }
37
+ }
38
+ ]
39
+ }
@@ -1,15 +1,15 @@
1
- {
2
- "[typescript]": {
3
- "editor.defaultFormatter": "esbenp.prettier-vscode"
4
- },
5
- "[javascript]": {
6
- "editor.defaultFormatter": "esbenp.prettier-vscode"
7
- },
8
- "[json]": {
9
- "editor.defaultFormatter": "esbenp.prettier-vscode"
10
- },
11
- "[svelte]": {
12
- "editor.defaultFormatter": "svelte.svelte-vscode"
13
- },
14
- "svelte.enable-ts-plugin": true
15
- }
1
+ {
2
+ "[typescript]": {
3
+ "editor.defaultFormatter": "esbenp.prettier-vscode"
4
+ },
5
+ "[javascript]": {
6
+ "editor.defaultFormatter": "esbenp.prettier-vscode"
7
+ },
8
+ "[json]": {
9
+ "editor.defaultFormatter": "esbenp.prettier-vscode"
10
+ },
11
+ "[svelte]": {
12
+ "editor.defaultFormatter": "svelte.svelte-vscode"
13
+ },
14
+ "svelte.enable-ts-plugin": true
15
+ }
@@ -1,3 +1,3 @@
1
- # electron-vite
2
-
3
- An Electron application with Svelte, TypeScript and Tailwind CSS
1
+ # electron-vite
2
+
3
+ An Electron application with Svelte, TypeScript and Tailwind CSS
@@ -0,0 +1,6 @@
1
+ out
2
+ dist
3
+ pnpm-lock.yaml
4
+ LICENSE.md
5
+ tsconfig.json
6
+ tsconfig.*.json
@@ -0,0 +1,13 @@
1
+ singleQuote: true
2
+ semi: false
3
+ printWidth: 120
4
+ useTabs: false
5
+ arrowParens: avoid
6
+ tabWidth: 2
7
+ trailingComma: all
8
+ plugins:
9
+ - prettier-plugin-svelte
10
+ overrides:
11
+ - files: "*.svelte"
12
+ options:
13
+ parser: svelte
@@ -3,13 +3,13 @@ productName: electron-vite
3
3
  directories:
4
4
  buildResources: build
5
5
  files:
6
- - '!**/.vscode/*'
7
- - '!src/*'
8
- - '!electron.vite.config.{js,ts,mjs,cjs}'
9
- - '!svelte.config.mjs'
10
- - '!{.eslintcache,eslint.config.mjs,.prettierignore,.prettierrc.yaml,dev-app-update.yml,CHANGELOG.md,README.md}'
11
- - '!{.env,.env.*,.npmrc,pnpm-lock.yaml}'
12
- - '!{tsconfig.json,tsconfig.node.json,tsconfig.web.json}'
6
+ - "!**/.vscode/*"
7
+ - "!src/*"
8
+ - "!electron.vite.config.{js,ts,mjs,cjs}"
9
+ - "!svelte.config.mjs"
10
+ - "!{.eslintcache,eslint.config.mjs,.prettierignore,.prettierrc.yaml,dev-app-update.yml,CHANGELOG.md,README.md}"
11
+ - "!{.env,.env.*,.npmrc,pnpm-lock.yaml}"
12
+ - "!{tsconfig.json,tsconfig.node.json,tsconfig.web.json}"
13
13
  asarUnpack:
14
14
  - resources/**
15
15
  win: