rapidkit 0.14.1 → 0.15.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.
Files changed (61) hide show
  1. package/README.md +199 -38
  2. package/dist/index.d.ts +3 -0
  3. package/dist/index.js +746 -494
  4. package/dist/package.json +14 -6
  5. package/package.json +14 -6
  6. package/templates/generator.js +0 -175
  7. package/templates/kits/fastapi-standard/.rapidkit/__init__.py.j2 +0 -1
  8. package/templates/kits/fastapi-standard/.rapidkit/activate.j2 +0 -24
  9. package/templates/kits/fastapi-standard/.rapidkit/cli.py.j2 +0 -289
  10. package/templates/kits/fastapi-standard/.rapidkit/context.json +0 -3
  11. package/templates/kits/fastapi-standard/.rapidkit/project.json.j2 +0 -7
  12. package/templates/kits/fastapi-standard/.rapidkit/rapidkit.j2 +0 -107
  13. package/templates/kits/fastapi-standard/Makefile.j2 +0 -41
  14. package/templates/kits/fastapi-standard/README.md.j2 +0 -38
  15. package/templates/kits/fastapi-standard/kit.json +0 -70
  16. package/templates/kits/fastapi-standard/kit.yaml +0 -120
  17. package/templates/kits/fastapi-standard/pyproject.toml.j2 +0 -42
  18. package/templates/kits/fastapi-standard/rapidkit.cmd.j2 +0 -72
  19. package/templates/kits/fastapi-standard/rapidkit.j2 +0 -50
  20. package/templates/kits/fastapi-standard/src/__init__.py.j2 +0 -3
  21. package/templates/kits/fastapi-standard/src/cli.py.j2 +0 -335
  22. package/templates/kits/fastapi-standard/src/main.py.j2 +0 -44
  23. package/templates/kits/fastapi-standard/src/modules/__init__.py.j2 +0 -3
  24. package/templates/kits/fastapi-standard/src/routing/__init__.py.j2 +0 -13
  25. package/templates/kits/fastapi-standard/src/routing/health.py.j2 +0 -32
  26. package/templates/kits/fastapi-standard/tests/__init__.py.j2 +0 -1
  27. package/templates/kits/nestjs-standard/.env.example.j2 +0 -16
  28. package/templates/kits/nestjs-standard/.eslintrc.js.j2 +0 -25
  29. package/templates/kits/nestjs-standard/.gitignore.j2 +0 -26
  30. package/templates/kits/nestjs-standard/.node-version.j2 +0 -1
  31. package/templates/kits/nestjs-standard/.nvmrc.j2 +0 -1
  32. package/templates/kits/nestjs-standard/.prettierrc.j2 +0 -7
  33. package/templates/kits/nestjs-standard/.rapidkit/activate.j2 +0 -25
  34. package/templates/kits/nestjs-standard/.rapidkit/context.json +0 -3
  35. package/templates/kits/nestjs-standard/.rapidkit/project.json.j2 +0 -7
  36. package/templates/kits/nestjs-standard/.rapidkit/rapidkit.cmd.j2 +0 -166
  37. package/templates/kits/nestjs-standard/.rapidkit/rapidkit.j2 +0 -227
  38. package/templates/kits/nestjs-standard/README.md.j2 +0 -110
  39. package/templates/kits/nestjs-standard/jest.config.ts.j2 +0 -21
  40. package/templates/kits/nestjs-standard/nest-cli.json.j2 +0 -10
  41. package/templates/kits/nestjs-standard/package.json.j2 +0 -75
  42. package/templates/kits/nestjs-standard/rapidkit.cmd.j2 +0 -5
  43. package/templates/kits/nestjs-standard/rapidkit.j2 +0 -5
  44. package/templates/kits/nestjs-standard/src/app.controller.ts.j2 +0 -12
  45. package/templates/kits/nestjs-standard/src/app.module.ts.j2 +0 -23
  46. package/templates/kits/nestjs-standard/src/app.service.ts.j2 +0 -11
  47. package/templates/kits/nestjs-standard/src/config/configuration.ts.j2 +0 -9
  48. package/templates/kits/nestjs-standard/src/config/index.ts.j2 +0 -2
  49. package/templates/kits/nestjs-standard/src/config/validation.ts.j2 +0 -11
  50. package/templates/kits/nestjs-standard/src/examples/dto/create-note.dto.ts.j2 +0 -11
  51. package/templates/kits/nestjs-standard/src/examples/examples.controller.ts.j2 +0 -24
  52. package/templates/kits/nestjs-standard/src/examples/examples.module.ts.j2 +0 -10
  53. package/templates/kits/nestjs-standard/src/examples/examples.service.ts.j2 +0 -33
  54. package/templates/kits/nestjs-standard/src/main.ts.j2 +0 -51
  55. package/templates/kits/nestjs-standard/src/modules/index.ts.j2 +0 -3
  56. package/templates/kits/nestjs-standard/test/app.controller.spec.ts.j2 +0 -22
  57. package/templates/kits/nestjs-standard/test/app.e2e-spec.ts.j2 +0 -48
  58. package/templates/kits/nestjs-standard/test/examples.controller.spec.ts.j2 +0 -28
  59. package/templates/kits/nestjs-standard/test/jest-e2e.json.j2 +0 -15
  60. package/templates/kits/nestjs-standard/tsconfig.build.json.j2 +0 -12
  61. package/templates/kits/nestjs-standard/tsconfig.json.j2 +0 -26
package/dist/index.js CHANGED
@@ -1,449 +1,699 @@
1
1
  #!/usr/bin/env node
2
- import {Command}from'commander';import r from'chalk';import O from'inquirer';import l,{dirname,join}from'path';import {spawn}from'child_process';import {execa}from'execa';import k,{readFileSync,promises}from'fs';import {fileURLToPath}from'url';import le from'os';import me from'validate-npm-package-name';import*as h from'fs-extra';import A from'ora';var F=class{debugEnabled=false;setDebug(t){this.debugEnabled=t;}debug(t,...i){this.debugEnabled&&console.log(r.gray(`[DEBUG] ${t}`),...i);}info(t,...i){console.log(r.blue(t),...i);}success(t,...i){console.log(r.green(t),...i);}warn(t,...i){console.log(r.yellow(t),...i);}error(t,...i){console.error(r.red(t),...i);}step(t,i,n){console.log(r.cyan(`
3
- [${t}/${i}]`),r.white(n));}},m=new F;var ne="rapidkit",oe=fileURLToPath(import.meta.url),ae=dirname(oe),re=join(ae,"..","package.json"),se=JSON.parse(readFileSync(re,"utf-8")),V=se.version;async function J(){try{m.debug("Checking for updates...");let{stdout:e}=await execa("npm",["view",ne,"version"],{timeout:3e3}),t=e.trim();t&&t!==V?(console.log(r.yellow(`
4
- \u26A0\uFE0F Update available: ${V} \u2192 ${t}`)),console.log(r.cyan(`Run: npm install -g rapidkit@latest
5
- `))):m.debug("You are using the latest version");}catch{m.debug("Could not check for updates");}}function N(){return V}var de=".rapidkitrc.json";async function W(){let e=l.join(le.homedir(),de);try{let t=await promises.readFile(e,"utf-8"),i=JSON.parse(t);return m.debug(`Loaded config from ${e}`),i}catch{return m.debug("No user config found, using defaults"),{}}}var S=class extends Error{constructor(i,n,a){super(i);this.code=n;this.details=a;this.name="RapidKitError",Error.captureStackTrace(this,this.constructor);}};var v=class extends S{constructor(t,i){super(`Invalid project name: "${t}"`,"INVALID_PROJECT_NAME",i);}};function M(e){let t=me(e);if(!t.validForNewPackages){let n=t.errors||[],a=t.warnings||[],s=[...n,...a];throw new v(e,`NPM validation failed: ${s.join(", ")}`)}if(!/^[a-z][a-z0-9_-]*$/.test(e))throw new v(e,"Must start with a lowercase letter and contain only lowercase letters, numbers, hyphens, and underscores");if(["test","tests","src","dist","build","lib","python","pip","poetry","node","npm","rapidkit","rapidkit"].includes(e.toLowerCase()))throw new v(e,`"${e}" is a reserved name. Please choose a different name.`);if(e.length<2)throw new v(e,"Name must be at least 2 characters long");if(e.length>214)throw new v(e,"Name must be less than 214 characters");return true}async function H(e,t){let i=A("Creating RapidKit workspace...").start();try{await promises.mkdir(e,{recursive:!0}),await promises.mkdir(l.join(e,".rapidkit"),{recursive:!0});let n={workspace_name:t.name,author:t.author,rapidkit_version:N(),created_at:new Date().toISOString(),type:"workspace"};await promises.writeFile(l.join(e,".rapidkit","config.json"),JSON.stringify(n,null,2));let a=ge();await promises.writeFile(l.join(e,"rapidkit"),a),await promises.chmod(l.join(e,"rapidkit"),493);let s=ue(t.name);if(await promises.writeFile(l.join(e,"README.md"),s),await promises.writeFile(l.join(e,".gitignore"),`# RapidKit workspace
2
+ import {Command,Option}from'commander';import d from'chalk';import lt from'inquirer';import y from'path';import {spawn}from'child_process';import {execa}from'execa';import {createRequire}from'module';import Q,{promises}from'fs';import*as Qt from'os';import Qt__default from'os';import Zt from'validate-npm-package-name';import*as x from'fs-extra';import ut from'ora';import ye from'nunjucks';import {fileURLToPath}from'url';var rt=class{debugEnabled=false;setDebug(e){this.debugEnabled=e;}debug(e,...i){this.debugEnabled&&console.log(d.gray(`[DEBUG] ${e}`),...i);}info(e,...i){console.log(d.blue(e),...i);}success(e,...i){console.log(d.green(e),...i);}warn(e,...i){console.log(d.yellow(e),...i);}error(e,...i){console.error(d.red(e),...i);}step(e,i,n){console.log(d.cyan(`
3
+ [${e}/${i}]`),d.white(n));}},u=new rt;var Bt="rapidkit",Jt=createRequire(import.meta.url),Yt=Jt("../package.json"),at=Yt?.version??"0.0.0";async function wt(){try{u.debug("Checking for updates...");let{stdout:t}=await execa("npm",["view",Bt,"version"],{timeout:3e3}),e=t.trim();e&&e!==at?(console.log(d.yellow(`
4
+ \u26A0\uFE0F Update available: ${at} \u2192 ${e}`)),console.log(d.cyan(`Run: npm install -g rapidkit@latest
5
+ `))):u.debug("You are using the latest version");}catch{u.debug("Could not check for updates");}}function V(){return at}var Xt=".rapidkitrc.json";async function J(){let t=y.join(Qt__default.homedir(),Xt);try{let e=await promises.readFile(t,"utf-8"),i=JSON.parse(e);return u.debug(`Loaded config from ${t}`),i}catch{return u.debug("No user config found, using defaults"),{}}}function X(t){return process.env.RAPIDKIT_DEV_PATH||t.testRapidKitPath||void 0}var _=class extends Error{constructor(i,n,o){super(i);this.code=n;this.details=o;this.name="RapidKitError",Error.captureStackTrace(this,this.constructor);}},F=class extends _{constructor(e,i){let n=i?`Python ${e}+ required, found ${i}`:`Python ${e}+ not found`;super(n,"PYTHON_NOT_FOUND","Please install Python from https://www.python.org/downloads/");}},Y=class extends _{constructor(){super("Poetry is not installed","POETRY_NOT_FOUND","Install Poetry from https://python-poetry.org/docs/#installation");}},z=class extends _{constructor(){super("pipx is not installed","PIPX_NOT_FOUND","Install pipx from https://pypa.github.io/pipx/installation/");}},Z=class extends _{constructor(e){super(`Directory "${e}" already exists`,"DIRECTORY_EXISTS","Please choose a different name or remove the existing directory");}},T=class extends _{constructor(e,i){super(`Invalid project name: "${e}"`,"INVALID_PROJECT_NAME",i);}},S=class extends _{constructor(e,i){let n=`Installation failed at: ${e}`,o=`${i.message}
6
+
7
+ Troubleshooting:
8
+ - Check your internet connection
9
+ - Verify Python/Poetry installation
10
+ - Try running with --debug flag for more details`;super(n,"INSTALLATION_ERROR",o);}},M=class extends _{constructor(){super("RapidKit Python package is not yet available on PyPI","RAPIDKIT_NOT_AVAILABLE",`Available options:
11
+ 1. Install Python 3.10+ and retry the same command
12
+ 2. Use the core workflow: npx rapidkit create workspace <name>
13
+ 3. Offline fallback (limited): npx rapidkit create project fastapi.standard <name> --output .
14
+
15
+ Legacy: set RAPIDKIT_SHOW_LEGACY=1 to reveal template-mode flags in help.`);}};function kt(t){let e=Zt(t);if(!e.validForNewPackages){let n=e.errors||[],o=e.warnings||[],r=[...n,...o];throw new T(t,`NPM validation failed: ${r.join(", ")}`)}if(!/^[a-z][a-z0-9_-]*$/.test(t))throw new T(t,"Must start with a lowercase letter and contain only lowercase letters, numbers, hyphens, and underscores");if(["test","tests","src","dist","build","lib","python","pip","poetry","node","npm","rapidkit","rapidkit"].includes(t.toLowerCase()))throw new T(t,`"${t}" is a reserved name. Please choose a different name.`);if(t.length<2)throw new T(t,"Name must be at least 2 characters long");if(t.length>214)throw new T(t,"Name must be less than 214 characters");return true}function ee(t){return typeof t=="object"&&t!==null}async function ie(t,e,i,n=8e3){try{let o=await execa(t,e,{cwd:i,timeout:n,reject:!1,stdio:"pipe"});return {ok:o.exitCode===0,exitCode:o.exitCode,stdout:o.stdout,stderr:o.stderr}}catch(o){return {ok:false,exitCode:void 0,stdout:"",stderr:o instanceof Error?o.message:String(o)}}}async function ne(t,e){let i=["-m","rapidkit",...t],n=["python3","python"];for(let o of n){let r=await ie(o,i,e?.cwd,e?.timeoutMs);if(!r.ok)continue;let c=(r.stdout??"").trim();try{let a=JSON.parse(c);return ee(a)?{ok:!0,command:o,exitCode:r.exitCode,stdout:r.stdout,stderr:r.stderr,data:a}:{ok:!1,command:o,exitCode:r.exitCode,stdout:r.stdout,stderr:r.stderr}}catch{return {ok:false,command:o,exitCode:r.exitCode,stdout:r.stdout,stderr:r.stderr}}}return {ok:false}}async function vt(t,e){let i=await ne(["project","detect","--path",t,"--json"],e);return !i.ok||!i.data||i.data.schema_version!==1?{ok:false,command:i.command,exitCode:i.exitCode,stdout:i.stdout,stderr:i.stderr}:i}var G=class extends Error{code;constructor(e,i){super(i),this.code=e;}};function Rt(t){return t instanceof G?t.code==="PYTHON_NOT_FOUND"?"RapidKit (npm) could not find Python (python3/python) on your PATH.\nInstall Python 3.10+ and ensure `python3` is available, then retry.\nTip: if you are inside a RapidKit project, use the local ./rapidkit launcher.":`RapidKit (npm) bridge error: ${t.message}`:`RapidKit (npm) failed to run the Python core engine: ${t instanceof Error?t.message:String(t)}`}function re(){let t=process.env.RAPIDKIT_CORE_PYTHON_PACKAGE;return t&&t.trim()?t.trim():"rapidkit-core"}function jt(){let t=process.env.XDG_CACHE_HOME;return t&&t.trim()?t:y.join(Qt__default.homedir(),".cache")}function st(){return y.join(jt(),"rapidkit","npm-bridge","venv")}function xt(t){return process.platform==="win32"?y.join(t,"Scripts","python.exe"):y.join(t,"bin","python")}function bt(t){return process.platform==="win32"?y.join(t,"Scripts","rapidkit.exe"):y.join(t,"bin","rapidkit")}function ae(){return y.join(jt(),"rapidkit","npm-bridge","core-commands.json")}async function se(t){let e=!!process.env.RAPIDKIT_DEBUG,i=n=>{e&&process.stderr.write(`[DEBUG] tryRapidkit(${t}): ${n}
16
+ `);};try{i("probing interpreter-specific rapidkit script");let o=((await execa(t,["-c","import sysconfig, os; print(os.path.join(sysconfig.get_path('scripts'), 'rapidkit'))"],{reject:!1,stdio:"pipe",timeout:2e3})).stdout??"").toString().trim();if(i(`script path: ${o}`),o)try{if(await x.pathExists(o)){i(`found script at ${o}; invoking --version --json`);let r=await execa(o,["--version","--json"],{reject:!1,stdio:"pipe",timeout:4e3});if(i(`script exitCode=${r.exitCode}`),r.exitCode===0){let c=(r.stdout??"").toString().trim();try{let a=JSON.parse(c),s=!!a&&typeof a=="object"&&a!==null&&"version"in a;if(i(`script JSON parse ok=${s}`),s)return !0}catch{i("script output not valid JSON");}}}}catch(r){i(`interpreter-specific script probe failed: ${String(r)}`);}}catch(n){i(`interpreter-specific script probe error: ${String(n)}`);}try{i('probing importlib.find_spec("rapidkit")');let n=await execa(t,["-c","import importlib.util; print(1 if importlib.util.find_spec('rapidkit') else 0)"],{reject:!1,stdio:"pipe",timeout:2e3});if(i(`import probe exitCode=${n.exitCode} stdout=${(n.stdout??"").toString().trim()}`),n.exitCode===0&&(n.stdout??"").toString().trim()==="1")return !0}catch(n){i(`import probe error: ${String(n)}`);}try{i("probing python -m rapidkit");let n=await execa(t,["-m","rapidkit","--version","--json"],{reject:!1,stdio:"pipe",timeout:8e3});if(i(`-m probe exitCode=${n.exitCode}`),n.exitCode===0)return !0}catch(n){i(`-m probe error: ${String(n)}`);}try{i("probing PATH for rapidkit executables");let n=(process.env.PATH??"").split(y.delimiter).filter(Boolean);for(let o of n){let r=y.join(o,process.platform==="win32"?"rapidkit.exe":"rapidkit");try{if(await x.pathExists(r)){i(`found candidate on PATH: ${r}; invoking --version --json`);let c=await execa(r,["--version","--json"],{reject:!1,stdio:"pipe",timeout:4e3});if(i(`candidate exitCode=${c.exitCode}`),c.exitCode===0){let a=(c.stdout??"").toString().trim();try{let s=JSON.parse(a);if(s&&typeof s=="object"&&s!==null&&"version"in s)return !0}catch{i("candidate output not valid JSON, skipping");}}}}catch(c){i(`error probing candidate ${r}: ${String(c)}`);}}return i("no valid rapidkit found on PATH"),!1}catch(n){return i(`PATH probe error: ${String(n)}`),false}}async function ct(t){let e=(t??"").toString().trim();if(!e)return false;try{let i=JSON.parse(e);return !!i&&typeof i=="object"&&i!==null&&"version"in i}catch{return false}}async function ce(t){let e=process.platform==="win32",i=e?y.join(".venv","Scripts","rapidkit.exe"):y.join(".venv","bin","rapidkit"),n=e?y.join(".venv","Scripts","python.exe"):y.join(".venv","bin","python"),o=t;for(let r=0;r<25;r+=1){let c=y.join(o,i);if(await x.pathExists(c)){let p=await execa(c,["--version","--json"],{reject:false,stdio:"pipe",timeout:1500,cwd:o});if(p.exitCode===0&&await ct(p.stdout))return {cmd:c,baseArgs:[]}}let a=y.join(o,n);if(await x.pathExists(a)){let p=await execa(a,["-m","rapidkit","--version","--json"],{reject:false,stdio:"pipe",timeout:1500,cwd:o});if(p.exitCode===0&&await ct(p.stdout))return {cmd:a,baseArgs:["-m","rapidkit"]}}let s=y.dirname(o);if(s===o)break;o=s;}return null}async function pe(t){if(t&&t.trim())try{let r=await ce(t);if(r)return r}catch{}let e=await tt();if(e.kind==="venv"){let r=st(),c=bt(r);return await x.pathExists(c)?{cmd:c,baseArgs:[]}:{cmd:e.pythonPath,baseArgs:["-m","rapidkit"]}}try{if((await execa(e.cmd,["-m","rapidkit","--version","--json"],{reject:!1,stdio:"pipe",timeout:4e3})).exitCode===0)return {cmd:e.cmd,baseArgs:["-m","rapidkit"]}}catch{}try{let c=((await execa(e.cmd,["-c","import sysconfig, os; print(os.path.join(sysconfig.get_path('scripts'), 'rapidkit'))"],{reject:!1,stdio:"pipe",timeout:2e3})).stdout??"").toString().trim();if(c&&await x.pathExists(c))try{let a=await execa(c,["--version","--json"],{reject:!1,stdio:"pipe",timeout:4e3});if(a.exitCode===0&&await ct(a.stdout))return {cmd:c,baseArgs:[]}}catch{}}catch{}let i=st(),n=await pt(e.cmd),o=bt(i);return await x.pathExists(o)?{cmd:o,baseArgs:[]}:{cmd:n,baseArgs:["-m","rapidkit"]}}async function Pt(){for(let t of ["python3","python"])try{return await execa(t,["--version"],{reject:!1,stdio:"pipe",timeout:2e3}),t}catch{}return null}async function pt(t){let e=st(),i=xt(e);if(await x.pathExists(i))return i;let n={...process.env,PIP_DISABLE_PIP_VERSION_CHECK:"1",PIP_NO_PYTHON_VERSION_WARNING:"1"},o=async(r,c)=>{let a=await execa(r,c,{reject:false,stdio:["ignore","pipe","inherit"],env:n});if(a.exitCode===0)return;let s=(a.stdout??"").toString(),p=(a.stderr??"").toString(),f=[s,p].filter(Boolean).join(`
17
+ `),m=f?`${r} ${c.join(" ")}
18
+ ${f}`:`${r} ${c.join(" ")}`;throw new Error(m)};try{await x.ensureDir(y.dirname(e)),await o(t,["-m","venv",e]);let r=xt(e);return process.env.RAPIDKIT_BRIDGE_UPGRADE_PIP==="1"&&await o(r,["-m","pip","install","-U","pip"]),await o(r,["-m","pip","install","-U",re()]),r}catch(r){throw new G("BRIDGE_VENV_BOOTSTRAP_FAILED",Rt(r))}}async function tt(){if(process.env.RAPIDKIT_BRIDGE_FORCE_VENV==="1"){let i=await Pt();if(!i)throw new G("PYTHON_NOT_FOUND","No Python interpreter found (python3/python).");return {kind:"venv",pythonPath:await pt(i)}}for(let i of ["python3","python"])if(await se(i))return {kind:"system",cmd:i};let t=await Pt();if(!t)throw new G("PYTHON_NOT_FOUND","No Python interpreter found (python3/python).");return {kind:"venv",pythonPath:await pt(t)}}async function $(t,e){try{let i=await pe(e?.cwd),n=i.cmd,o=[...i.baseArgs,...t],r=await execa(n,o,{cwd:e?.cwd,env:{...process.env,...e?.env},reject:!1,stdio:"inherit"});return typeof r.exitCode=="number"?r.exitCode:1}catch(i){return process.stderr.write(`${Rt(i)}
19
+ `),1}}async function de(){let t=ae();if(!await x.pathExists(t))return null;try{let e=await x.readJson(t);if(e&&e.schema_version===1&&Array.isArray(e.commands))return e}catch{}return null}async function _t(){let e=Date.now(),i=await de();return !i||e-i.fetched_at>=864e5||!i.commands?.length?null:new Set(i.commands)}var le=["version","project","create","init","dev","start","build","test","lint","format","add","list","info","upgrade","diff","doctor","license","reconcile","rollback","uninstall","checkpoint","optimize","snapshot","frameworks","modules","merge"],Ct=new Set(le);function dt(){return process.platform==="win32"?"python":"python3"}async function It(t,e){let i=y.join(t,".rapidkit-workspace"),n={signature:"RAPIDKIT_VSCODE_WORKSPACE",createdBy:"rapidkit-npm",version:V(),createdAt:new Date().toISOString(),name:e};await x.outputFile(i,JSON.stringify(n,null,2)+`
20
+ `,"utf-8");}async function St(t){await x.outputFile(y.join(t,".gitignore"),`.venv/
21
+ __pycache__/
22
+ *.pyc
6
23
  .env
7
- .env.*
8
- !.env.example
24
+ .rapidkit-workspace/
9
25
 
10
- # OS
11
- .DS_Store
12
- Thumbs.db
26
+ `,"utf-8");}function q(){let t=y.join(Qt.homedir(),".local","bin"),i=(process.env.PATH||"").split(y.delimiter).filter(Boolean);i.includes(t)||(process.env.PATH=[t,...i].join(y.delimiter));}async function $t(t,e){q(),t.start("Checking pipx installation");try{return await execa("pipx",["--version"]),t.succeed("pipx found"),{kind:"binary"}}catch{}let i=dt();try{return await execa(i,["-m","pipx","--version"]),t.succeed("pipx found"),{kind:"python-module",pythonCmd:i}}catch{}if(e)throw new z;let{installPipx:n}=await lt.prompt([{type:"confirm",name:"installPipx",message:"pipx is not installed. Install it now (user install via python -m pip)?",default:true}]);if(!n)throw new z;t.start("Installing pipx (user install)");try{try{await execa(i,["-m","pip","install","--user","--upgrade","pip"]);}catch{}await execa(i,["-m","pip","install","--user","--upgrade","pipx"]);}catch(o){let r=o,c=String(r?.stderr||r?.shortMessage||r?.message||"");throw new S("Install pipx with python -m pip",o instanceof Error?o:new Error(c))}t.succeed("pipx installed"),q();try{return await execa(i,["-m","pipx","--version"]),{kind:"python-module",pythonCmd:i}}catch(o){let r=o,c=String(r?.stderr||r?.shortMessage||r?.message||"pipx not runnable after install");throw new S("Verify pipx after install",new Error(`${c}
13
27
 
14
- # IDEs
15
- .vscode/
16
- .idea/
28
+ Try reopening your terminal or run: python3 -m pipx ensurepath`))}}async function et(t,e){return t.kind==="binary"?execa("pipx",e):execa(t.pythonCmd,["-m","pipx",...e])}async function ue(t,e){q(),t.start("Checking Poetry installation");try{await execa("poetry",["--version"]),t.succeed("Poetry found");return}catch{}if(e)throw new Y;let{installPoetry:i}=await lt.prompt([{type:"confirm",name:"installPoetry",message:"Poetry is not installed. Install it now using pipx?",default:true}]);if(!i)throw new Y;let n=await $t(t,e);t.start("Installing Poetry with pipx");try{await et(n,["install","poetry"]);}catch(o){let r=o,c=String(r?.stderr||r?.shortMessage||r?.message||"");if(/already\s+installed|already\s+seems\s+to\s+be\s+installed|exists/i.test(c))try{await et(n,["upgrade","poetry"]);}catch{}else throw new S("Install Poetry with pipx",o instanceof Error?o:new Error(c))}t.succeed("Poetry installed"),q();try{await execa("poetry",["--version"]);}catch(o){let r=o,c=String(r?.stderr||r?.shortMessage||r?.message||"Poetry not found on PATH");throw new S("Verify Poetry after pipx install",new Error(`${c}
17
29
 
18
- # Logs
19
- *.log
20
- `),await fe(e),i.succeed("Workspace created!"),!t.skipGit){let o=A("Initializing git repository...").start();try{await execa("git",["init"],{cwd:e}),await execa("git",["add","."],{cwd:e}),await execa("git",["commit","-m","Initial commit: RapidKit workspace"],{cwd:e}),o.succeed("Git repository initialized");}catch{o.warn("Could not initialize git repository");}}console.log(`
21
- ${r.green("\u2728 RapidKit workspace created successfully!")}
30
+ Poetry may be installed but not on PATH yet. Try reopening your terminal or run: pipx ensurepath`))}}function me(t){let e=t==="poetry";return `#!/usr/bin/env sh
31
+ set -eu
22
32
 
23
- ${r.bold("\u{1F4C2} Workspace structure:")}
24
- ${e}/
25
- \u251C\u2500\u2500 rapidkit # Local CLI wrapper
26
- \u251C\u2500\u2500 .rapidkit/ # Workspace configuration
27
- \u2502 \u251C\u2500\u2500 config.json # Workspace settings
28
- \u2502 \u2514\u2500\u2500 templates/ # Project templates
29
- \u2514\u2500\u2500 README.md
33
+ SCRIPT_DIR=$(CDPATH= cd -- "$(dirname -- "$0")" && pwd)
30
34
 
31
- ${r.bold("\u{1F680} Get started:")}
32
- ${r.cyan(`cd ${t.name}`)}
33
- ${r.cyan("npx rapidkit my-api --template fastapi")}
34
- ${r.cyan("cd my-api")}
35
- ${r.cyan("npx rapidkit init")}
36
- ${r.cyan("npx rapidkit dev")}
37
-
38
- ${r.bold("\u{1F4E6} Available templates:")}
39
- fastapi - FastAPI + Python (default)
40
- nestjs - NestJS + TypeScript
41
-
42
- ${r.bold("\u{1F4DA} Commands:")}
43
- npx rapidkit <name> --template <type> Create a new project
44
- npx rapidkit init Install dependencies
45
- npx rapidkit dev Start dev server
46
- npx rapidkit help Show all commands
47
-
48
- ${r.gray("Alternative: ./rapidkit dev, make dev")}
49
- ${r.gray("\u{1F4A1} Tip: Install globally (npm i -g rapidkit) to use without npx")}
50
- `);}catch(n){throw i.fail("Failed to create workspace"),n}}function ge(){return `#!/usr/bin/env bash
51
- #
52
- # RapidKit CLI - Local workspace commands
53
- # This script provides rapidkit commands within the workspace
54
- #
55
-
56
- set -e
57
-
58
- # Find workspace root (where this script lives)
59
- SCRIPT_DIR="$(cd "$(dirname "\${BASH_SOURCE[0]}")" && pwd)"
60
-
61
- # Check if we're in a project directory (has .rapidkit/project.json)
62
- find_project_root() {
63
- local dir="$PWD"
64
- while [[ "$dir" != "/" ]]; do
65
- if [[ -f "$dir/.rapidkit/project.json" ]]; then
66
- echo "$dir"
67
- return 0
68
- fi
69
- dir="$(dirname "$dir")"
70
- done
71
- return 1
72
- }
35
+ VENV_RAPIDKIT="$SCRIPT_DIR/.venv/bin/rapidkit"
36
+ if [ -x "$VENV_RAPIDKIT" ]; then
37
+ exec "$VENV_RAPIDKIT" "$@"
38
+ fi
73
39
 
74
- # Check if we're in a workspace (has .rapidkit/config.json with type=workspace)
75
- find_workspace_root() {
76
- local dir="$PWD"
77
- while [[ "$dir" != "/" ]]; do
78
- if [[ -f "$dir/.rapidkit/config.json" ]]; then
79
- if grep -q '"type": "workspace"' "$dir/.rapidkit/config.json" 2>/dev/null; then
80
- echo "$dir"
81
- return 0
82
- fi
83
- fi
84
- dir="$(dirname "$dir")"
85
- done
86
- return 1
87
- }
40
+ ${e?`if command -v poetry >/dev/null 2>&1 && [ -f "$SCRIPT_DIR/pyproject.toml" ]; then
41
+ exec poetry run rapidkit "$@"
42
+ fi
88
43
 
89
- # Colors
90
- RED='\\033[0;31m'
91
- GREEN='\\033[0;32m'
92
- YELLOW='\\033[0;33m'
93
- BLUE='\\033[0;34m'
94
- CYAN='\\033[0;36m'
95
- NC='\\033[0m' # No Color
96
- BOLD='\\033[1m'
97
-
98
- print_banner() {
99
- echo -e "\${BLUE}\${BOLD}\u{1F680} RapidKit CLI\${NC}"
100
- echo ""
101
- }
44
+ `:""}echo "RapidKit launcher could not find a local Python CLI." 1>&2
45
+ echo "- If you used venv: ensure .venv exists (or re-run the installer)." 1>&2
46
+ ${e?`echo "- If you used Poetry: run 'poetry install' and retry, or activate the env." 1>&2
47
+ `:""}echo "Tip: you can also run: ./.venv/bin/rapidkit --help" 1>&2
48
+ exit 1
49
+ `}function ge(t){return `@echo off
50
+ setlocal
51
+
52
+ set "SCRIPT_DIR=%~dp0"
53
+
54
+ if exist "%SCRIPT_DIR%\\.venv\\Scripts\\rapidkit.exe" (
55
+ "%SCRIPT_DIR%\\.venv\\Scripts\\rapidkit.exe" %*
56
+ exit /b %ERRORLEVEL%
57
+ )
58
+
59
+ ${t==="poetry"?`where poetry >nul 2>nul
60
+ if %ERRORLEVEL%==0 if exist "%SCRIPT_DIR%\\pyproject.toml" (
61
+ poetry run rapidkit %*
62
+ exit /b %ERRORLEVEL%
63
+ )
64
+
65
+ `:""}echo RapidKit launcher could not find a local Python CLI. 1>&2
66
+ echo Tip: run .venv\\Scripts\\rapidkit.exe --help 1>&2
67
+ exit /b 1
68
+ `}async function At(t,e){await x.outputFile(y.join(t,"rapidkit"),me(e),{encoding:"utf-8",mode:493}),await x.outputFile(y.join(t,"rapidkit.cmd"),ge(e),"utf-8");}async function Tt(t,e){let{skipGit:i=false,testMode:n=false,demoMode:o=false,dryRun:r=false,yes:c=false,userConfig:a={}}=e,s=t||"rapidkit",p=y.resolve(process.cwd(),s);if(await x.pathExists(p))throw new Z(s);if(r){await he(p,s,o,a);return}if(o){await fe(p,s,i);return}let f=c?{pythonVersion:a.pythonVersion||"3.10",installMethod:a.defaultInstallMethod||"venv"}:await lt.prompt([{type:"list",name:"pythonVersion",message:"Select Python version for RapidKit:",choices:["3.10","3.11","3.12"],default:a.pythonVersion||"3.10"},{type:"list",name:"installMethod",message:"How would you like to install RapidKit?",choices:[{name:"\u{1F3AF} Poetry (Recommended - includes virtual env)",value:"poetry"},{name:"\u{1F4E6} pip with venv (Standard)",value:"venv"},{name:"\u{1F527} pipx (Global isolated install)",value:"pipx"}],default:a.defaultInstallMethod||"venv"}]);u.step(1,3,"Setting up RapidKit environment");let m=ut("Creating directory").start();try{if(await x.ensureDir(p),m.succeed("Directory created"),await It(p,s),await St(p),f.installMethod==="poetry"?await Ot(p,f.pythonVersion,m,n,a,c):f.installMethod==="venv"?await Dt(p,f.pythonVersion,m,n,a):await Nt(p,m,n,a,c),await At(p,f.installMethod),await Kt(p,f.installMethod),m.succeed("RapidKit environment ready!"),!e.skipGit){m.start("Initializing git repository");try{await execa("git",["init"],{cwd:p}),await execa("git",["add","."],{cwd:p}),await execa("git",["commit","-m","Initial commit: RapidKit environment"],{cwd:p}),m.succeed("Git repository initialized");}catch{m.warn("Could not initialize git repository");}}if(console.log(d.green(`
69
+ \u2728 RapidKit environment created successfully!
70
+ `)),console.log(d.cyan("\u{1F4C2} Location:"),d.white(p)),console.log(d.cyan(`\u{1F680} Get started:
71
+ `)),console.log(d.white(` cd ${s}`)),f.installMethod==="poetry"){let P="source $(poetry env info --path)/bin/activate";try{q();let{stdout:A}=await execa("poetry",["--version"]),w=A.match(/Poetry.*?(\d+)\.(\d+)/);w&&(parseInt(w[1])>=2?P="source $(poetry env info --path)/bin/activate":P="poetry shell");}catch{}console.log(d.white(` ${P} # Or: poetry run rapidkit`)),console.log(d.white(" rapidkit create # Interactive mode")),console.log(d.white(" cd <project-name> && rapidkit init && rapidkit dev"));}else f.installMethod==="venv"?(console.log(d.white(" source .venv/bin/activate # On Windows: .venv\\Scripts\\activate")),console.log(d.white(" rapidkit create # Interactive mode")),console.log(d.white(" cd <project-name> && rapidkit init && rapidkit dev"))):(console.log(d.white(" rapidkit create # Interactive mode")),console.log(d.white(" cd <project-name> && rapidkit init && rapidkit dev")));console.log(d.white(`
72
+ \u{1F4A1} For more information, check the README.md file.`)),console.log(d.cyan(`
73
+ \u{1F4DA} RapidKit commands:`)),console.log(d.white(" rapidkit create - Create a new project (interactive)")),console.log(d.white(" rapidkit dev - Run development server")),console.log(d.white(" rapidkit add module <name> - Add a module (e.g., settings)")),console.log(d.white(" rapidkit list - List available kits")),console.log(d.white(" rapidkit modules - List available modules")),console.log(d.white(` rapidkit --help - Show all commands
74
+ `));}catch(P){m.fail("Failed to create RapidKit environment"),console.error(d.red(`
75
+ \u274C Error:`),P);try{await x.remove(p);}catch{}throw P}}async function Ot(t,e,i,n,o,r=false){await ue(i,r),i.start("Initializing Poetry project"),await execa("poetry",["init","--no-interaction","--python",`^${e}`],{cwd:t});let c=y.join(t,"pyproject.toml"),s=(await promises.readFile(c,"utf-8")).replace("[tool.poetry]",`[tool.poetry]
76
+ package-mode = false`);await promises.writeFile(c,s,"utf-8"),i.succeed("Poetry project initialized"),i.start("Configuring Poetry to create in-project virtualenv");try{await execa("poetry",["config","virtualenvs.in-project","true"],{cwd:t}),i.succeed("Poetry configured");}catch{i.warn("Could not configure Poetry virtualenvs.in-project");}if(i.start("Installing RapidKit"),n){let p=X(o||{});if(!p)throw new S("Test mode installation",new Error("No local RapidKit path configured. Set RAPIDKIT_DEV_PATH environment variable."));u.debug(`Installing from local path: ${p}`),i.text="Installing RapidKit from local path (test mode)",await execa("poetry",["add",p],{cwd:t});}else {i.text="Installing RapidKit from PyPI";try{await execa("poetry",["add","rapidkit-core"],{cwd:t});}catch{throw new M}}i.succeed("RapidKit installed");}async function Dt(t,e,i,n,o){i.start(`Checking Python ${e}`);let r=dt();try{let{stdout:a}=await execa(r,["--version"]),s=a.match(/Python (\d+\.\d+)/)?.[1];if(s&&parseFloat(s)<parseFloat(e))throw new F(e,s);i.succeed(`Python ${s} found`);}catch(a){throw a instanceof F?a:new F(e)}i.start("Creating virtual environment"),await execa(r,["-m","venv",".venv"],{cwd:t}),i.succeed("Virtual environment created"),i.start("Installing RapidKit");let c=y.join(t,".venv",process.platform==="win32"?"Scripts":"bin",process.platform==="win32"?"python.exe":"python");if(await execa(c,["-m","pip","install","--upgrade","pip"],{cwd:t}),n){let a=X(o||{});if(!a)throw new S("Test mode installation",new Error("No local RapidKit path configured. Set RAPIDKIT_DEV_PATH environment variable."));u.debug(`Installing from local path: ${a}`),i.text="Installing RapidKit from local path (test mode)",await execa(c,["-m","pip","install","-e",a],{cwd:t});}else {i.text="Installing RapidKit from PyPI";try{await execa(c,["-m","pip","install","rapidkit-core"],{cwd:t});}catch{throw new M}}i.succeed("RapidKit installed");}async function Nt(t,e,i,n,o=false){let r=await $t(e,o);if(e.start("Installing RapidKit globally with pipx"),i){let c=X(n||{});if(!c)throw new S("Test mode installation",new Error("No local RapidKit path configured. Set RAPIDKIT_DEV_PATH environment variable."));u.debug(`Installing from local path: ${c}`),e.text="Installing RapidKit from local path (test mode)",await et(r,["install","-e",c]);}else {e.text="Installing RapidKit from PyPI";try{await et(r,["install","rapidkit-core"]);}catch{throw new M}}e.succeed("RapidKit installed globally"),await x.outputFile(y.join(t,".rapidkit-global"),`RapidKit installed globally with pipx
77
+ `,"utf-8");}async function K(t,e){let{skipGit:i=false,testMode:n=false,userConfig:o={},yes:r=false,installMethod:c,pythonVersion:a="3.10"}=e||{};await It(t,y.basename(t)),await St(t);let s=ut("Registering workspace").start();try{let p=c||o.defaultInstallMethod||"venv";if(p==="poetry"?await Ot(t,a,s,n,o,r):p==="venv"?await Dt(t,a,s,n,o):await Nt(t,s,n,o,r),await At(t,p),await Kt(t,p),s.succeed("Workspace registered"),!i){s.start("Initializing git repository");try{await execa("git",["init"],{cwd:t}),await execa("git",["add","."],{cwd:t}),await execa("git",["commit","-m","Initial commit: RapidKit workspace"],{cwd:t}),s.succeed("Git repository initialized");}catch{s.warn("Could not initialize git repository");}}}catch(p){throw s.fail("Failed to register workspace"),p}}async function Kt(t,e){let o=`# RapidKit Workspace
78
+
79
+ This directory contains a RapidKit development environment.
80
+
81
+ ## Installation Method
82
+
83
+ **${e==="poetry"?"Poetry":e==="venv"?"Python venv + pip":"pipx (global)"}**
84
+
85
+ ## Getting Started
86
+
87
+ ### 0. Run Without Activation (Recommended)
88
+
89
+ This workspace includes a local launcher script so you can run the Python Core CLI without activating the environment:
90
+
91
+ \`\`\`bash
92
+ ${e==="poetry"?`# No activation needed (recommended):
93
+ ./rapidkit --help
94
+ # or:
95
+ poetry run rapidkit --help`:e==="venv"?`# No activation needed (recommended):
96
+ ./rapidkit --help
97
+ # or direct:
98
+ ./.venv/bin/rapidkit --help`:`# Optional: use the local launcher
99
+ ./rapidkit --help
100
+ # (pipx installs may require Poetry/venv to be present in this folder)`}
101
+ \`\`\`
102
+
103
+ ### 1. Activate Environment
104
+
105
+ \`\`\`bash
106
+ ${e==="poetry"?`source $(poetry env info --path)/bin/activate
107
+ # Or simply use: poetry run rapidkit <command>`:e==="venv"?"source .venv/bin/activate # On Windows: .venv\\Scripts\\activate":"N/A (globally installed)"}
108
+ \`\`\`
109
+
110
+ ### 2. Create Your First Project
111
+
112
+ \`\`\`bash
113
+ # Interactive mode (recommended):
114
+ rapidkit create
115
+ # Follow the prompts to choose kit and project name
102
116
 
103
- print_help() {
104
- print_banner
105
- echo -e "\${BOLD}Usage:\${NC} rapidkit <command> [options]"
106
- echo ""
107
- echo -e "\${BOLD}\u{1F3D7}\uFE0F Workspace Commands:\${NC}"
108
- echo " create <name> Create a new project from template"
109
- echo " create --help Show create command options"
110
- echo ""
111
- echo -e "\${BOLD}\u{1F680} Project Commands\${NC} (run inside a project):"
112
- echo " init Install project dependencies"
113
- echo " dev Start development server"
114
- echo " start Start production server"
115
- echo " build Build for production"
116
- echo " test Run tests"
117
- echo " lint Run linting"
118
- echo " format Format code"
119
- echo ""
120
- echo -e "\${BOLD}\u{1F4DA} Other Commands:\${NC}"
121
- echo " help Show this help message"
122
- echo " version Show version"
123
- echo ""
124
- echo -e "\${BOLD}Examples:\${NC}"
125
- echo -e " \${CYAN}rapidkit create my-api --template fastapi\${NC}"
126
- echo -e " \${CYAN}rapidkit create my-app --template nestjs --yes\${NC}"
127
- echo -e " \${CYAN}cd my-api && rapidkit dev\${NC}"
128
- echo ""
117
+ # Or specify directly:
118
+ rapidkit create project fastapi.standard my-project
119
+
120
+ # With poetry run (no activation needed):
121
+ poetry run rapidkit create
122
+ \`\`\`
123
+
124
+ Interactive mode will guide you through selecting a kit and configuring your project.
125
+
126
+ ### 3. Navigate and Run
127
+
128
+ \`\`\`bash
129
+ cd my-project
130
+ # Install dependencies (preferred):
131
+ rapidkit init
132
+
133
+ # Run the server (project-aware):
134
+ rapidkit dev
135
+
136
+ # Or with poetry run (manual / advanced):
137
+ poetry run rapidkit dev
138
+
139
+ # Or manually:
140
+ uvicorn src.main:app --reload
141
+ \`\`\`
142
+
143
+ ### 4. Add Modules (Optional)
144
+
145
+ \`\`\`bash
146
+ # Add common modules to your project:
147
+ rapidkit add module settings
148
+ rapidkit add module logging
149
+ rapidkit add module database
150
+
151
+ # List available modules:
152
+ rapidkit modules list
153
+ \`\`\`
154
+
155
+ ## Available Commands
156
+
157
+ - \`rapidkit create\` - Create a new project (interactive)
158
+ - \`rapidkit create project <kit> <name>\` - Create project with specific kit
159
+ - \`rapidkit dev\` - Run development server
160
+ - \`rapidkit add module <name>\` - Add a module (e.g., \`rapidkit add module settings\`)
161
+ - \`rapidkit list\` - List available kits
162
+ - \`rapidkit modules\` - List available modules
163
+ - \`rapidkit upgrade\` - Upgrade RapidKit
164
+ - \`rapidkit doctor\` - Check system requirements
165
+ - \`rapidkit --help\` - Show all commands
166
+
167
+ ## RapidKit Documentation
168
+
169
+ For full documentation, visit: [RapidKit Docs](https://getrapidkit.com) *(or appropriate URL)*
170
+
171
+ ## Workspace Structure
172
+
173
+ \`\`\`
174
+ ${e==="venv"?".venv/ # Python virtual environment":""}
175
+ ${e==="poetry"?"pyproject.toml # Poetry configuration":""}
176
+ my-project/ # Your RapidKit projects go here
177
+ README.md # This file
178
+ \`\`\`
179
+
180
+ ## Troubleshooting
181
+
182
+ If you encounter issues:
183
+
184
+ 1. Ensure Python 3.10+ is installed: \`python3 --version\`
185
+ 2. Check RapidKit installation: \`rapidkit --version\`
186
+ 3. Run diagnostics: \`rapidkit doctor\`
187
+ 4. Visit RapidKit documentation or GitHub issues
188
+ `;await promises.writeFile(y.join(t,"README.md"),o,"utf-8");}async function fe(t,e,i){let n=ut("Creating demo workspace").start();try{await x.ensureDir(t),n.succeed("Directory created"),n.start("Setting up demo kit generator");let o=JSON.stringify({name:`${e}-workspace`,version:"1.0.0",private:!0,description:"RapidKit demo workspace",scripts:{generate:"node generate-demo.js"}},null,2);await promises.writeFile(y.join(t,"package.json"),o,"utf-8"),await promises.writeFile(y.join(t,"generate-demo.js"),`#!/usr/bin/env node
189
+ /**
190
+ * Demo Kit Generator - Create FastAPI demo projects
191
+ *
192
+ * This workspace contains bundled RapidKit templates that you can use
193
+ * to generate demo projects without installing Python RapidKit.
194
+ *
195
+ * Usage:
196
+ * npm run generate <project-name>
197
+ * node generate-demo.js <project-name>
198
+ *
199
+ * Example:
200
+ * npm run generate my-api
201
+ */
202
+
203
+ const fs = require('fs');
204
+ const path = require('path');
205
+ const readline = require('readline');
206
+
207
+ const projectName = process.argv[2];
208
+
209
+ if (!projectName) {
210
+ console.error('\\n\u274C Please provide a project name');
211
+ console.log('\\nUsage: npm run generate <project-name>\\n');
212
+ console.log('Example: npm run generate my-api\\n');
213
+ process.exit(1);
129
214
  }
130
215
 
131
- print_create_help() {
132
- print_banner
133
- echo -e "\${BOLD}Usage:\${NC} rapidkit create <project-name> [options]"
134
- echo ""
135
- echo -e "\${BOLD}Options:\${NC}"
136
- echo " -t, --template <name> Template to use (fastapi, nestjs)"
137
- echo " -y, --yes Skip prompts, use defaults"
138
- echo " --skip-git Skip git initialization"
139
- echo " --skip-install Skip dependency installation"
140
- echo ""
141
- echo -e "\${BOLD}Templates:\${NC}"
142
- echo " fastapi FastAPI + Python (default)"
143
- echo " nestjs NestJS + TypeScript"
144
- echo ""
145
- echo -e "\${BOLD}Examples:\${NC}"
146
- echo -e " \${CYAN}rapidkit create my-api\${NC}"
147
- echo -e " \${CYAN}rapidkit create my-api --template fastapi\${NC}"
148
- echo -e " \${CYAN}rapidkit create my-app --template nestjs --yes\${NC}"
149
- echo ""
216
+ const rl = readline.createInterface({
217
+ input: process.stdin,
218
+ output: process.stdout
219
+ });
220
+
221
+ function ask(question, defaultValue) {
222
+ return new Promise((resolve) => {
223
+ rl.question(\`\${question} (\${defaultValue}): \`, (answer) => {
224
+ resolve(answer || defaultValue);
225
+ });
226
+ });
150
227
  }
151
228
 
152
- # Create project command
153
- cmd_create() {
154
- local project_name=""
155
- local template="fastapi"
156
- local yes_flag=""
157
- local skip_git=""
158
- local skip_install=""
159
-
160
- # Parse arguments
161
- while [[ $# -gt 0 ]]; do
162
- case "$1" in
163
- -h|--help)
164
- print_create_help
165
- exit 0
166
- ;;
167
- -t|--template)
168
- template="$2"
169
- shift 2
170
- ;;
171
- -y|--yes)
172
- yes_flag="--yes"
173
- shift
174
- ;;
175
- --skip-git)
176
- skip_git="--skip-git"
177
- shift
178
- ;;
179
- --skip-install)
180
- skip_install="--skip-install"
181
- shift
182
- ;;
183
- -*)
184
- echo -e "\${RED}\u274C Unknown option: $1\${NC}"
185
- print_create_help
186
- exit 1
187
- ;;
188
- *)
189
- if [[ -z "$project_name" ]]; then
190
- project_name="$1"
191
- fi
192
- shift
193
- ;;
194
- esac
195
- done
196
-
197
- # Validate template
198
- if [[ "$template" != "fastapi" && "$template" != "nestjs" ]]; then
199
- echo -e "\${RED}\u274C Invalid template: $template\${NC}"
200
- echo -e "Available templates: fastapi, nestjs"
201
- exit 1
202
- fi
203
-
204
- # If no project name, prompt for it or show help
205
- if [[ -z "$project_name" ]]; then
206
- if [[ -n "$yes_flag" ]]; then
207
- project_name="my-\${template}-project"
208
- else
209
- echo -e "\${YELLOW}Project name required\${NC}"
210
- echo ""
211
- print_create_help
212
- exit 1
213
- fi
214
- fi
215
-
216
- # Find workspace root
217
- local workspace_root
218
- workspace_root=$(find_workspace_root) || {
219
- echo -e "\${RED}\u274C Not in a RapidKit workspace\${NC}"
220
- echo -e "Run this command from within a RapidKit workspace."
221
- exit 1
222
- }
223
-
224
- local project_path="$PWD/$project_name"
225
-
226
- # Check if project already exists
227
- if [[ -d "$project_path" ]]; then
228
- echo -e "\${RED}\u274C Directory '$project_name' already exists\${NC}"
229
- exit 1
230
- fi
231
-
232
- echo -e "\${BLUE}\${BOLD}\u{1F680} Creating $template project: $project_name\${NC}"
233
- echo ""
234
-
235
- # Use Node.js generator script
236
- local generator_script="$workspace_root/.rapidkit/generator.js"
229
+ async function main() {
230
+ const targetPath = path.join(process.cwd(), projectName);
231
+
232
+ if (fs.existsSync(targetPath)) {
233
+ console.error(\`\\n\u274C Directory "\${projectName}" already exists\\n\`);
234
+ process.exit(1);
235
+ }
236
+
237
+ console.log(\`\\n\u{1F680} Creating FastAPI project: \${projectName}\\n\`);
238
+
239
+ const snakeName = projectName.replace(/-/g, '_').toLowerCase();
240
+ const project_name = await ask('Project name (snake_case)', snakeName);
241
+ const author = await ask('Author name', process.env.USER || 'RapidKit User');
242
+ const description = await ask('Description', 'FastAPI service generated with RapidKit');
243
+
244
+ rl.close();
245
+
246
+ // Create project structure
247
+ const dirs = [
248
+ '',
249
+ 'src',
250
+ 'src/routing',
251
+ 'src/modules',
252
+ 'tests',
253
+ '.rapidkit'
254
+ ];
255
+
256
+ for (const dir of dirs) {
257
+ fs.mkdirSync(path.join(targetPath, dir), { recursive: true });
258
+ }
259
+
260
+ // Template files with content
261
+ const files = {
262
+ 'src/__init__.py': '"""' + project_name + ' package."""\\n',
263
+ 'src/modules/__init__.py': '"""Modules package."""\\n',
264
+ 'tests/__init__.py': '"""Tests package."""\\n',
265
+ 'src/main.py': \`"""\${project_name} application entrypoint."""
266
+
267
+ from __future__ import annotations
268
+
269
+ from contextlib import asynccontextmanager
270
+ from typing import AsyncIterator
271
+
272
+ from fastapi import FastAPI
273
+ from fastapi.middleware.cors import CORSMiddleware
274
+
275
+ from .routing import api_router
276
+
277
+
278
+ @asynccontextmanager
279
+ async def lifespan(app: FastAPI) -> AsyncIterator[None]:
280
+ """Application lifespan context manager for startup/shutdown events."""
281
+ yield
282
+
283
+
284
+ app = FastAPI(
285
+ title="\${project_name}",
286
+ description="\${description}",
287
+ version="0.1.0",
288
+ docs_url="/docs",
289
+ redoc_url="/redoc",
290
+ lifespan=lifespan,
291
+ )
292
+
293
+ app.add_middleware(
294
+ CORSMiddleware,
295
+ allow_origins=["*"],
296
+ allow_credentials=True,
297
+ allow_methods=["*"],
298
+ allow_headers=["*"],
299
+ )
300
+
301
+ app.include_router(api_router, prefix="/api")
302
+
303
+
304
+ if __name__ == "__main__":
305
+ import uvicorn
306
+ uvicorn.run("src.main:app", host="0.0.0.0", port=8001, reload=True)
307
+ \`,
308
+ 'src/routing/__init__.py': \`"""API routing configuration."""
309
+
310
+ from fastapi import APIRouter
311
+
312
+ from .health import router as health_router
313
+
314
+ api_router = APIRouter()
315
+
316
+ api_router.include_router(health_router)
317
+ \`,
318
+ 'src/routing/health.py': \`"""Health check endpoints."""
319
+
320
+ from __future__ import annotations
321
+
322
+ from fastapi import APIRouter
323
+
324
+ router = APIRouter(prefix="/health", tags=["health"])
325
+
326
+
327
+ @router.get("/", summary="Health check")
328
+ async def heartbeat() -> dict[str, str]:
329
+ """Return basic service heartbeat."""
330
+ return {"status": "ok"}
331
+ \`,
332
+ 'src/cli.py': \`"""CLI commands for \${project_name}."""
333
+
334
+ import subprocess
335
+ import sys
336
+ from pathlib import Path
337
+
338
+
339
+ def dev():
340
+ """Start development server with hot reload."""
341
+ print("\u{1F680} Starting development server...")
342
+ subprocess.run([
343
+ sys.executable, "-m", "uvicorn",
344
+ "src.main:app", "--reload",
345
+ "--host", "0.0.0.0", "--port", "8000"
346
+ ])
347
+
348
+
349
+ def start():
350
+ """Start production server."""
351
+ print("\u26A1 Starting production server...")
352
+ subprocess.run([
353
+ sys.executable, "-m", "uvicorn",
354
+ "src.main:app",
355
+ "--host", "0.0.0.0", "--port", "8000"
356
+ ])
357
+
358
+
359
+ def test():
360
+ """Run tests."""
361
+ print("\u{1F9EA} Running tests...")
362
+ subprocess.run([sys.executable, "-m", "pytest", "-q"])
363
+
364
+
365
+ if __name__ == "__main__":
366
+ if len(sys.argv) < 2:
367
+ print("Usage: python -m src.cli <command>")
368
+ print("Commands: dev, start, test")
369
+ sys.exit(1)
237
370
 
238
- if [[ -f "$generator_script" ]]; then
239
- node "$generator_script" "$project_path" "$template" "$yes_flag" "$skip_git" "$skip_install"
240
- else
241
- echo -e "\${RED}\u274C Generator script not found\${NC}"
242
- exit 1
243
- fi
244
- }
371
+ cmd = sys.argv[1]
372
+ if cmd == "dev":
373
+ dev()
374
+ elif cmd == "start":
375
+ start()
376
+ elif cmd == "test":
377
+ test()
378
+ else:
379
+ print(f"Unknown command: {cmd}")
380
+ sys.exit(1)
381
+ \`,
382
+ 'pyproject.toml': \`[tool.poetry]
383
+ name = "\${project_name}"
384
+ version = "0.1.0"
385
+ description = "\${description}"
386
+ authors = ["\${author}"]
387
+ license = "MIT"
388
+ readme = "README.md"
389
+ package-mode = false
390
+
391
+ [tool.poetry.dependencies]
392
+ python = "^3.10.14"
393
+ fastapi = "^0.128.0"
394
+ uvicorn = {extras = ["standard"], version = "^0.40.0"}
395
+ pydantic = "^2.12.5"
396
+ pydantic-settings = "^2.12.0"
397
+
398
+ [tool.poetry.group.dev.dependencies]
399
+ pytest = "^9.0.2"
400
+ pytest-asyncio = "^1.3.0"
401
+ pytest-cov = "^7.0.0"
402
+ httpx = "^0.28.1"
403
+ black = "^25.12.0"
404
+ ruff = "^0.14.10"
405
+ mypy = "^1.19.1"
406
+
407
+ [tool.poetry.scripts]
408
+ dev = "src.cli:dev"
409
+ start = "src.cli:start"
410
+ test = "src.cli:test"
411
+
412
+ [build-system]
413
+ requires = ["poetry-core"]
414
+ build-backend = "poetry.core.masonry.api"
415
+
416
+ [tool.pytest.ini_options]
417
+ asyncio_mode = "auto"
418
+ testpaths = ["tests"]
419
+
420
+ [tool.ruff]
421
+ line-length = 100
422
+ target-version = "py311"
423
+
424
+ [tool.black]
425
+ line-length = 100
426
+ target-version = ["py311"]
427
+ \`,
428
+ 'README.md': \`# \${project_name}
429
+
430
+ \${description}
431
+
432
+ ## Quick start
433
+
434
+ \\\`\\\`\\\`bash
435
+ npx rapidkit init # Install dependencies
436
+ npx rapidkit dev # Start dev server
437
+ \\\`\\\`\\\`
438
+
439
+ ## Available commands
440
+
441
+ \\\`\\\`\\\`bash
442
+ npx rapidkit init # \u{1F527} Install dependencies
443
+ npx rapidkit dev # \u{1F680} Start development server with hot reload
444
+ npx rapidkit start # \u26A1 Start production server
445
+ npx rapidkit test # \u{1F9EA} Run tests
446
+ npx rapidkit help # \u{1F4DA} Show available commands
447
+ \\\`\\\`\\\`
448
+
449
+ ## Project layout
450
+
451
+ \\\`\\\`\\\`
452
+ \${project_name}/
453
+ \u251C\u2500\u2500 src/
454
+ \u2502 \u251C\u2500\u2500 main.py # FastAPI application
455
+ \u2502 \u251C\u2500\u2500 cli.py # CLI commands
456
+ \u2502 \u251C\u2500\u2500 routing/ # API routes
457
+ \u2502 \u2514\u2500\u2500 modules/ # Module system
458
+ \u251C\u2500\u2500 tests/ # Test suite
459
+ \u251C\u2500\u2500 pyproject.toml # Poetry configuration
460
+ \u2514\u2500\u2500 README.md
461
+ \\\`\\\`\\\`
462
+ \`,
463
+ '.rapidkit/project.json': JSON.stringify({
464
+ kit_name: "fastapi.standard",
465
+ profile: "fastapi/standard",
466
+ created_at: new Date().toISOString(),
467
+ rapidkit_version: "npm-demo"
468
+ }, null, 2),
469
+ '.rapidkit/cli.py': \`#!/usr/bin/env python3
470
+ """RapidKit CLI wrapper for demo projects."""
471
+
472
+ import subprocess
473
+ import sys
474
+ from pathlib import Path
475
+
476
+
477
+ def dev(port=8000, host="0.0.0.0"):
478
+ """Start development server."""
479
+ print("\u{1F680} Starting development server with hot reload...")
480
+ subprocess.run([
481
+ sys.executable, "-m", "uvicorn",
482
+ "src.main:app", "--reload",
483
+ "--host", host, "--port", str(port)
484
+ ])
485
+
486
+
487
+ def start(port=8000, host="0.0.0.0"):
488
+ """Start production server."""
489
+ print("\u26A1 Starting production server...")
490
+ subprocess.run([
491
+ sys.executable, "-m", "uvicorn",
492
+ "src.main:app",
493
+ "--host", host, "--port", str(port)
494
+ ])
495
+
496
+
497
+ def init():
498
+ """Install dependencies."""
499
+ print("\u{1F4E6} Installing dependencies...")
500
+ subprocess.run(["poetry", "install"])
501
+
502
+
503
+ def test():
504
+ """Run tests."""
505
+ print("\u{1F9EA} Running tests...")
506
+ subprocess.run([sys.executable, "-m", "pytest", "-q"])
507
+
508
+
509
+ def help_cmd():
510
+ """Show help."""
511
+ print("\u{1F4DA} Available commands:")
512
+ print(" init - Install dependencies")
513
+ print(" dev - Start dev server")
514
+ print(" start - Start production server")
515
+ print(" test - Run tests")
516
+
517
+
518
+ if __name__ == "__main__":
519
+ cmd = sys.argv[1] if len(sys.argv) > 1 else "help"
520
+ cmds = {"dev": dev, "start": start, "init": init, "test": test, "help": help_cmd}
521
+ cmds.get(cmd, help_cmd)()
522
+ \`,
523
+ '.rapidkit/rapidkit': '#!/usr/bin/env bash\\n# Local RapidKit launcher for demo projects\\nset -euo pipefail\\nSCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"\\nROOT_DIR="$(cd "$SCRIPT_DIR/.." && pwd)"\\ncd "$ROOT_DIR"\\n\\nif [ -f "pyproject.toml" ]; then\\n if command -v poetry >/dev/null 2>&1; then\\n exec poetry run python "$SCRIPT_DIR/cli.py" "$@"\\n fi\\nfi\\n\\necho "Poetry not found. Install with: pip install poetry"\\nexit 1\\n',
524
+ '.gitignore': \`# Python
525
+ __pycache__/
526
+ *.py[cod]
527
+ *.so
528
+ .Python
529
+ build/
530
+ dist/
531
+ *.egg-info/
245
532
 
246
- # Project commands (dev, build, test, etc.)
247
- cmd_project() {
248
- local cmd="$1"
249
- shift
250
-
251
- # Find project root
252
- local project_root
253
- project_root=$(find_project_root) || {
254
- echo -e "\${RED}\u274C Not in a RapidKit project\${NC}"
255
- echo -e "Run this command from within a project directory."
256
- echo -e "Use \${CYAN}rapidkit create <name>\${NC} to create a new project."
257
- exit 1
258
- }
259
-
260
- # Read project type from project.json
261
- local project_json="$project_root/.rapidkit/project.json"
262
- local kit_name
263
- kit_name=$(grep -o '"kit_name": *"[^"]*"' "$project_json" | cut -d'"' -f4)
264
-
265
- cd "$project_root"
266
-
267
- case "$kit_name" in
268
- fastapi.standard|python)
269
- # Python/FastAPI project
270
- case "$cmd" in
271
- init)
272
- echo -e "\${BLUE}\u{1F4E6} Installing dependencies...\${NC}"
273
-
274
- # Source activate script first to ensure Poetry is available
275
- if [[ -f ".rapidkit/activate" ]]; then
276
- source .rapidkit/activate
277
- fi
278
-
279
- poetry install
280
- echo -e "\${GREEN}\u2705 Dependencies installed!\${NC}"
281
- ;;
282
- dev)
283
- echo -e "\${BLUE}\u{1F680} Starting development server...\${NC}"
284
- poetry run dev "$@"
285
- ;;
286
- start)
287
- echo -e "\${BLUE}\u26A1 Starting production server...\${NC}"
288
- poetry run start "$@"
289
- ;;
290
- build)
291
- echo -e "\${BLUE}\u{1F4E6} Building project...\${NC}"
292
- poetry run build
293
- ;;
294
- test)
295
- echo -e "\${BLUE}\u{1F9EA} Running tests...\${NC}"
296
- poetry run test
297
- ;;
298
- lint)
299
- echo -e "\${BLUE}\u{1F527} Running linter...\${NC}"
300
- poetry run lint
301
- ;;
302
- format)
303
- echo -e "\${BLUE}\u2728 Formatting code...\${NC}"
304
- poetry run format
305
- ;;
306
- *)
307
- echo -e "\${RED}\u274C Unknown command: $cmd\${NC}"
308
- exit 1
309
- ;;
310
- esac
311
- ;;
312
- nestjs.standard|node)
313
- # Node/NestJS project
314
- local pm="npm"
315
- if command -v pnpm &>/dev/null && [[ -f "pnpm-lock.yaml" ]]; then
316
- pm="pnpm"
317
- elif command -v yarn &>/dev/null && [[ -f "yarn.lock" ]]; then
318
- pm="yarn"
319
- fi
320
-
321
- case "$cmd" in
322
- init)
323
- echo -e "\${BLUE}\u{1F4E6} Installing dependencies...\${NC}"
324
-
325
- # Source activate script first to ensure environment is ready
326
- if [[ -f ".rapidkit/activate" ]]; then
327
- source .rapidkit/activate
328
- fi
329
-
330
- $pm install
331
- echo -e "\${GREEN}\u2705 Dependencies installed!\${NC}"
332
- ;;
333
- dev)
334
- echo -e "\${BLUE}\u{1F680} Starting development server...\${NC}"
335
- $pm run start:dev
336
- ;;
337
- start)
338
- echo -e "\${BLUE}\u26A1 Starting production server...\${NC}"
339
- $pm run start:prod
340
- ;;
341
- build)
342
- echo -e "\${BLUE}\u{1F4E6} Building project...\${NC}"
343
- $pm run build
344
- ;;
345
- test)
346
- echo -e "\${BLUE}\u{1F9EA} Running tests...\${NC}"
347
- $pm test
348
- ;;
349
- lint)
350
- echo -e "\${BLUE}\u{1F527} Running linter...\${NC}"
351
- $pm run lint
352
- ;;
353
- format)
354
- echo -e "\${BLUE}\u2728 Formatting code...\${NC}"
355
- $pm run format
356
- ;;
357
- *)
358
- echo -e "\${RED}\u274C Unknown command: $cmd\${NC}"
359
- exit 1
360
- ;;
361
- esac
362
- ;;
363
- *)
364
- echo -e "\${RED}\u274C Unknown project type: $kit_name\${NC}"
365
- exit 1
366
- ;;
367
- esac
368
- }
533
+ # Virtual environments
534
+ .venv/
535
+ venv/
536
+
537
+ # IDEs
538
+ .vscode/
539
+ .idea/
540
+
541
+ # OS
542
+ .DS_Store
369
543
 
370
- # Main command handler
371
- main() {
372
- local cmd="\${1:-help}"
373
- shift || true
374
-
375
- case "$cmd" in
376
- create)
377
- cmd_create "$@"
378
- ;;
379
- init|dev|start|build|test|lint|format)
380
- cmd_project "$cmd" "$@"
381
- ;;
382
- help|-h|--help)
383
- print_help
384
- ;;
385
- version|-v|--version)
386
- echo "RapidKit CLI (npm workspace) v${N()}"
387
- ;;
388
- *)
389
- echo -e "\${RED}\u274C Unknown command: $cmd\${NC}"
390
- echo ""
391
- print_help
392
- exit 1
393
- ;;
394
- esac
544
+ # Project
545
+ .env
546
+ .env.local
547
+ \`
548
+ };
549
+
550
+ for (const [filePath, content] of Object.entries(files)) {
551
+ fs.writeFileSync(path.join(targetPath, filePath), content);
552
+ }
553
+
554
+ // Make scripts executable
555
+ try {
556
+ fs.chmodSync(path.join(targetPath, '.rapidkit/cli.py'), 0o755);
557
+ fs.chmodSync(path.join(targetPath, '.rapidkit/rapidkit'), 0o755);
558
+ } catch (e) {
559
+ // Ignore on Windows
560
+ }
561
+
562
+ console.log(\`
563
+ \u2728 Demo project created successfully!
564
+
565
+ \u{1F4C2} Project: \${targetPath}
566
+
567
+ \u{1F680} Get started:
568
+ cd \${projectName}
569
+ npx rapidkit init # Install dependencies
570
+ npx rapidkit dev # Start dev server
571
+
572
+ \u{1F4DA} Available commands:
573
+ npx rapidkit init # \u{1F527} Install dependencies
574
+ npx rapidkit dev # \u{1F680} Start dev server with hot reload
575
+ npx rapidkit start # \u26A1 Start production server
576
+ npx rapidkit test # \u{1F9EA} Run tests
577
+ npx rapidkit help # \u{1F4DA} Show help
578
+
579
+ \u{1F4A1} For full RapidKit features: pipx install rapidkit
580
+ \`);
395
581
  }
396
582
 
397
- main "$@"
398
- `}function ue(e){return `# ${e}
583
+ main().catch(console.error);
584
+ `,"utf-8");try{await execa("chmod",["+x",y.join(t,"generate-demo.js")]);}catch{}let c=`# RapidKit Demo Workspace
585
+
586
+ Welcome to your RapidKit demo workspace! This environment lets you generate FastAPI demo projects using bundled RapidKit templates, without needing to install Python RapidKit.
399
587
 
400
- RapidKit workspace for building API projects.
588
+ ## \u{1F680} Quick Start
401
589
 
402
- ## Quick Start
590
+ ### Generate Your First Demo Project
403
591
 
404
592
  \`\`\`bash
405
- # Add rapidkit to PATH (or use ./rapidkit)
406
- export PATH="$PWD:$PATH"
593
+ # Generate a demo project:
594
+ node generate-demo.js my-api
407
595
 
408
- # Create a FastAPI project
409
- npx rapidkit my-api --template fastapi
596
+ # Navigate to the project:
597
+ cd my-api
410
598
 
411
- # Or create a NestJS project
412
- npx rapidkit my-app --template nestjs
599
+ # Install dependencies:
600
+ rapidkit init
413
601
 
414
- # Enter project and start development
415
- cd my-api
416
- npx rapidkit init # Install dependencies
417
- npx rapidkit dev # Start dev server
602
+ # Run the development server:
603
+ rapidkit dev
418
604
  \`\`\`
419
605
 
420
- ## Available Templates
606
+ Your API will be available at \`http://localhost:8000\`
607
+
608
+ ## \u{1F4E6} Generate Multiple Projects
609
+
610
+ You can create multiple demo projects in this workspace:
611
+
612
+ \`\`\`bash
613
+ node generate-demo.js api-service
614
+ node generate-demo.js auth-service
615
+ node generate-demo.js data-service
616
+ \`\`\`
421
617
 
422
- | Template | Stack | Description |
423
- |----------|-------|-------------|
424
- | \`fastapi\` | Python + FastAPI | High-performance Python API |
425
- | \`nestjs\` | TypeScript + NestJS | Enterprise Node.js framework |
618
+ Each project is independent and has its own dependencies.
426
619
 
427
- ## Commands
620
+ ## \u{1F3AF} What's Included
428
621
 
429
- ### Commands
622
+ Each generated demo project contains:
430
623
 
431
- | Command | Description |
432
- |---------|-------------|
433
- | \`npx rapidkit <name> --template <type>\` | Create a new project |
434
- | \`npx rapidkit init\` | Install dependencies |
435
- | \`npx rapidkit dev\` | Start development server |
436
- | \`npx rapidkit start\` | Start production server |
437
- | \`npx rapidkit build\` | Build for production |
438
- | \`npx rapidkit test\` | Run tests |
439
- | \`npx rapidkit lint\` | Run linting |
440
- | \`npx rapidkit format\` | Format code |
624
+ - **FastAPI Application** - Modern async web framework
625
+ - **Routing System** - Organized API routes
626
+ - **Module System** - Extensible module architecture
627
+ - **CLI Commands** - Built-in command system
628
+ - **Testing Setup** - pytest configuration
629
+ - **Poetry Configuration** - Dependency management
441
630
 
442
- ## Learn More
631
+ ## \u{1F4DA} Next Steps
443
632
 
444
- - [RapidKit Documentation](https://rapidkit.dev)
445
- - [GitHub Repository](https://github.com/Baziar/rapidkit)
446
- `}async function fe(e){let{fileURLToPath:t}=await import('url'),i=t(import.meta.url),n=l.dirname(i),a=l.resolve(n,".."),s=l.join(a,"templates","kits"),c=l.join(e,".rapidkit","templates"),{default:o}=await import('fs-extra');await o.copy(s,c);let d=l.join(a,"templates","generator.js"),f=l.join(e,".rapidkit","generator.js");await o.copy(d,f);}async function Y(e,t){let i=t.template==="fastapi",n=i?"FastAPI":"NestJS",a=A(`Creating ${n} project...`).start();try{let{fileURLToPath:s}=await import('url'),c=s(import.meta.url),o=l.dirname(c),d=l.resolve(o,".."),f=i?"fastapi-standard":"nestjs-standard",$=l.join(d,"templates","kits",f);await promises.mkdir(e,{recursive:!0});let j={project_name:i?t.name.replace(/-/g,"_").toLowerCase():t.name.replace(/_/g,"-").toLowerCase(),author:t.author,description:t.description||`${n} application generated with RapidKit`,app_version:"0.1.0",license:"MIT",package_manager:t.package_manager||"npm",created_at:new Date().toISOString(),rapidkit_version:N()};await z($,e,j);let _=i?`# Python
633
+ 1. **Explore the Generated Code** - Check out \`src/main.py\` and \`src/routing/\`
634
+ 2. **Add Routes** - Create new endpoints in \`src/routing/\`
635
+ 3. **Install Full RapidKit** - For advanced features: \`pipx install rapidkit\`
636
+ 4. **Read the Documentation** - Visit [RapidKit Docs](https://getrapidkit.com)
637
+
638
+ ## \u26A0\uFE0F Demo Mode Limitations
639
+
640
+ This is a demo workspace with:
641
+ - \u2705 Pre-built FastAPI templates
642
+ - \u2705 Project generation without Python RapidKit
643
+ - \u274C No RapidKit CLI commands (\`rapidkit create\`, \`rapidkit add module\`)
644
+ - \u274C No interactive module system
645
+
646
+ For full RapidKit features, install the Python package:
647
+
648
+ \`\`\`bash
649
+ pipx install rapidkit
650
+ \`\`\`
651
+
652
+ ## \u{1F6E0}\uFE0F Workspace Structure
653
+
654
+ \`\`\`
655
+ ${e}/
656
+ \u251C\u2500\u2500 generate-demo.js # Demo project generator
657
+ \u251C\u2500\u2500 README.md # This file
658
+ \u2514\u2500\u2500 my-api/ # Your generated projects go here
659
+ \`\`\`
660
+
661
+ ## \u{1F4A1} Tips
662
+
663
+ - Run \`node generate-demo.js --help\` for more options (coming soon)
664
+ - Each project can have different configurations
665
+ - Demo projects are production-ready FastAPI applications
666
+ - You can copy and modify templates as needed
667
+
668
+ ---
669
+
670
+ **Generated with RapidKit** | [GitHub](https://github.com/getrapidkit/rapidkit-npm)
671
+ `;if(await promises.writeFile(y.join(t,"README.md"),c,"utf-8"),n.succeed("Demo workspace setup complete"),!i){n.start("Initializing git repository");try{await execa("git",["init"],{cwd:t}),await x.outputFile(y.join(t,".gitignore"),`# Dependencies
672
+ node_modules/
673
+
674
+ # Generated projects
675
+ */
676
+ !generate-demo.js
677
+ !README.md
678
+
679
+ # Python
680
+ __pycache__/
681
+ *.pyc
682
+ .venv/
683
+ .env
684
+ `,"utf-8"),await execa("git",["add","."],{cwd:t}),await execa("git",["commit","-m","Initial commit: Demo workspace"],{cwd:t}),n.succeed("Git repository initialized");}catch{n.warn("Could not initialize git repository");}}console.log(d.green(`
685
+ \u2728 Demo workspace created successfully!
686
+ `)),console.log(d.cyan("\u{1F4C2} Location:"),d.white(t)),console.log(d.cyan(`\u{1F680} Get started:
687
+ `)),console.log(d.white(` cd ${e}`)),console.log(d.white(" node generate-demo.js my-api")),console.log(d.white(" cd my-api")),console.log(d.white(" rapidkit init")),console.log(d.white(" rapidkit dev")),console.log(),console.log(d.yellow("\u{1F4A1} Note:"),"This is a demo workspace. For full RapidKit features:"),console.log(d.cyan(" pipx install rapidkit")),console.log();}catch(o){throw n.fail("Failed to create demo workspace"),o}}async function he(t,e,i,n){console.log(d.cyan(`
688
+ \u{1F50D} Dry-run mode - showing what would be created:
689
+ `)),console.log(d.white("\u{1F4C2} Project path:"),t),console.log(d.white("\u{1F4E6} Project type:"),i?"Demo workspace":"Full RapidKit environment"),i?(console.log(d.white(`
690
+ \u{1F4DD} Files to create:`)),console.log(d.gray(" - package.json")),console.log(d.gray(" - generate-demo.js (project generator)")),console.log(d.gray(" - README.md")),console.log(d.gray(" - .gitignore")),console.log(d.white(`
691
+ \u{1F3AF} Capabilities:`)),console.log(d.gray(" - Generate multiple FastAPI demo projects")),console.log(d.gray(" - No Python RapidKit installation required")),console.log(d.gray(" - Bundled templates included"))):(console.log(d.white(`
692
+ \u2699\uFE0F Configuration:`)),console.log(d.gray(` - Python version: ${n.pythonVersion||"3.10"}`)),console.log(d.gray(` - Install method: ${n.defaultInstallMethod||"poetry"}`)),console.log(d.gray(` - Git initialization: ${n.skipGit?"No":"Yes"}`)),console.log(d.white(`
693
+ \u{1F4DD} Files to create:`)),console.log(d.gray(" - pyproject.toml (Poetry) or .venv/ (venv)")),console.log(d.gray(" - README.md")),console.log(d.gray(" - .gitignore")),console.log(d.white(`
694
+ \u{1F3AF} Next steps after creation:`)),console.log(d.gray(" 1. Install RapidKit Python package")),console.log(d.gray(" 2. Create projects with rapidkit CLI")),console.log(d.gray(" 3. Add modules and customize"))),console.log(d.white(`
695
+ \u{1F4A1} To proceed with actual creation, run without --dry-run flag
696
+ `));}var ke=fileURLToPath(import.meta.url),ve=y.dirname(ke);async function Vt(t,e){let n=(e.template||"fastapi")==="fastapi",o=n?"FastAPI":"NestJS",r=ut(`Generating ${o} project...`).start();try{let c=y.resolve(ve,".."),a=n?"fastapi-standard":"nestjs-standard",s=y.join(c,"templates","kits",a),p=ye.configure(s,{autoescape:!1,trimBlocks:!0,lstripBlocks:!0}),f={project_name:e.project_name,author:e.author||"RapidKit User",description:e.description||(n?"FastAPI service generated with RapidKit":"NestJS application generated with RapidKit"),app_version:e.app_version||"0.1.0",license:e.license||"MIT",package_manager:e.package_manager||"npm",created_at:new Date().toISOString(),rapidkit_version:V()},m;n?m=["src/main.py.j2","src/__init__.py.j2","src/cli.py.j2","src/routing/__init__.py.j2","src/routing/health.py.j2","src/modules/__init__.py.j2","tests/__init__.py.j2","README.md.j2","pyproject.toml.j2","Makefile.j2",".rapidkit/__init__.py.j2",".rapidkit/project.json.j2",".rapidkit/cli.py.j2",".rapidkit/rapidkit.j2",".rapidkit/activate.j2","rapidkit.j2","rapidkit.cmd.j2"]:m=["src/main.ts.j2","src/app.module.ts.j2","src/app.controller.ts.j2","src/app.service.ts.j2","src/config/configuration.ts.j2","src/config/validation.ts.j2","src/config/index.ts.j2","src/modules/index.ts.j2","src/examples/examples.module.ts.j2","src/examples/examples.controller.ts.j2","src/examples/examples.service.ts.j2","src/examples/dto/create-note.dto.ts.j2","test/app.controller.spec.ts.j2","test/examples.controller.spec.ts.j2","test/app.e2e-spec.ts.j2","test/jest-e2e.json.j2","package.json.j2","tsconfig.json.j2","tsconfig.build.json.j2","nest-cli.json.j2","jest.config.ts.j2",".eslintrc.js.j2",".prettierrc.j2",".nvmrc.j2",".node-version.j2",".env.example.j2","README.md.j2",".rapidkit/project.json.j2",".rapidkit/rapidkit.j2",".rapidkit/rapidkit.cmd.j2",".rapidkit/activate.j2","rapidkit.j2","rapidkit.cmd.j2"];for(let w of m){let C=y.join(s,w);try{await promises.access(C);}catch{continue}let ht=await promises.readFile(C,"utf-8"),Wt=p.renderString(ht,f),B=w.replace(/\.j2$/,""),ot=y.join(t,B);await promises.mkdir(y.dirname(ot),{recursive:!0}),await promises.writeFile(ot,Wt),(B.endsWith(".rapidkit/rapidkit")||B.endsWith(".rapidkit/cli.py")||B.endsWith(".rapidkit/activate")||B==="rapidkit")&&await promises.chmod(ot,493);}let P=n?`# Python
447
697
  __pycache__/
448
698
  *.py[cod]
449
699
  *$py.class
@@ -511,11 +761,11 @@ Thumbs.db
511
761
 
512
762
  # Coverage
513
763
  coverage/
514
- `;if(await promises.writeFile(l.join(e,".gitignore"),_),a.succeed(`${n} project created!`),!t.skipGit){let w=A("Initializing git repository...").start();try{await execa("git",["init"],{cwd:e}),await execa("git",["add","."],{cwd:e}),await execa("git",["commit","-m",`Initial commit: ${n} project via RapidKit`],{cwd:e}),w.succeed("Git repository initialized");}catch{w.warn("Could not initialize git repository");}}if(!t.skipInstall&&!i){let w=t.package_manager||"npm",D=A(`Installing dependencies with ${w}...`).start();try{await execa(w,["install"],{cwd:e}),D.succeed("Dependencies installed");}catch{D.warn(`Could not install dependencies. Run '${w} install' manually.`);}}let L=l.basename(e);console.log(i?`
515
- ${r.green("\u2728 FastAPI project created successfully!")}
764
+ `;if(await promises.writeFile(y.join(t,".gitignore"),P),r.succeed(`${o} project generated!`),!e.skipGit){let w=ut("Initializing git repository...").start();try{await execa("git",["init"],{cwd:t}),await execa("git",["add","."],{cwd:t}),await execa("git",["commit","-m",`Initial commit: ${o} project via RapidKit`],{cwd:t}),w.succeed("Git repository initialized");}catch{w.warn("Could not initialize git repository");}}if(!n&&!e.skipInstall){let w=e.package_manager||"npm",C=ut(`Installing dependencies with ${w}...`).start();try{await execa(w,w==="yarn"?["install"]:w==="pnpm"?["install"]:["install"],{cwd:t}),C.succeed("Dependencies installed");}catch{C.warn(`Could not install dependencies. Run '${w} install' manually.`);}}let A=y.basename(t);console.log(n?`
765
+ ${d.green("\u2728 FastAPI project created successfully!")}
516
766
 
517
- ${r.bold("\u{1F4C2} Project structure:")}
518
- ${e}/
767
+ ${d.bold("\u{1F4C2} Project structure:")}
768
+ ${t}/
519
769
  \u251C\u2500\u2500 .rapidkit/ # RapidKit CLI module
520
770
  \u251C\u2500\u2500 src/
521
771
  \u2502 \u251C\u2500\u2500 main.py # FastAPI application
@@ -526,12 +776,12 @@ ${e}/
526
776
  \u251C\u2500\u2500 pyproject.toml # Poetry configuration
527
777
  \u2514\u2500\u2500 README.md
528
778
 
529
- ${r.bold("\u{1F680} Get started:")}
530
- ${r.cyan(`cd ${L}`)}
531
- ${r.cyan("npx rapidkit init")} ${r.gray("# Install dependencies")}
532
- ${r.cyan("npx rapidkit dev")} ${r.gray("# Start dev server")}
779
+ ${d.bold("\u{1F680} Get started:")}
780
+ ${d.cyan(`cd ${A}`)}
781
+ ${d.cyan("npx rapidkit init")} ${d.gray("# Install dependencies")}
782
+ ${d.cyan("npx rapidkit dev")} ${d.gray("# Start dev server")}
533
783
 
534
- ${r.bold("\u{1F4DA} Available commands:")}
784
+ ${d.bold("\u{1F4DA} Available commands:")}
535
785
  npx rapidkit init # Install dependencies (poetry install)
536
786
  npx rapidkit dev # Start dev server with hot reload
537
787
  npx rapidkit start # Start production server
@@ -539,30 +789,30 @@ ${r.bold("\u{1F4DA} Available commands:")}
539
789
  npx rapidkit lint # Lint code
540
790
  npx rapidkit format # Format code
541
791
 
542
- ${r.gray("Alternative: make dev, ./rapidkit dev, poetry run dev")}
543
- ${r.gray("\u{1F4A1} Tip: Install globally (npm i -g rapidkit) to use without npx")}
792
+ ${d.gray("Alternative: make dev, ./rapidkit dev, poetry run dev")}
793
+ ${d.gray("\u{1F4A1} Tip: Install globally (npm i -g rapidkit) to use without npx")}
544
794
  `:`
545
- ${r.green("\u2728 NestJS project created successfully!")}
795
+ ${d.green("\u2728 NestJS project created successfully!")}
546
796
 
547
- ${r.bold("\u{1F4C2} Project structure:")}
548
- ${e}/
797
+ ${d.bold("\u{1F4C2} Project structure:")}
798
+ ${t}/
549
799
  \u251C\u2500\u2500 .rapidkit/ # RapidKit CLI module
550
800
  \u251C\u2500\u2500 src/
551
- \u2502 \u251C\u2500\u2500 main.ts # Application entry point
552
- \u2502 \u251C\u2500\u2500 app.module.ts # Root module
553
- \u2502 \u251C\u2500\u2500 config/ # Configuration
554
- \u2502 \u2514\u2500\u2500 examples/ # Example module
555
- \u251C\u2500\u2500 test/ # Test files
556
- \u251C\u2500\u2500 package.json # Dependencies
801
+ \u2502 \u251C\u2500\u2500 main.ts # Application entry point
802
+ \u2502 \u251C\u2500\u2500 app.module.ts # Root module
803
+ \u2502 \u251C\u2500\u2500 config/ # Configuration
804
+ \u2502 \u2514\u2500\u2500 examples/ # Example module
805
+ \u251C\u2500\u2500 test/ # Test files
806
+ \u251C\u2500\u2500 package.json # Dependencies
557
807
  \u2514\u2500\u2500 README.md
558
808
 
559
- ${r.bold("\u{1F680} Get started:")}
560
- ${r.cyan(`cd ${L}`)}
561
- ${t.skipInstall?r.cyan("npx rapidkit init")+r.gray(" # npm install")+`
562
- `:""}${r.cyan("cp .env.example .env")}
563
- ${r.cyan("npx rapidkit dev")} ${r.gray("# Start dev server")}
809
+ ${d.bold("\u{1F680} Get started:")}
810
+ ${d.cyan(`cd ${A}`)}
811
+ ${d.cyan("npx rapidkit init")} ${d.gray("# Install dependencies")}
812
+ ${d.cyan("cp .env.example .env")}
813
+ ${d.cyan("npx rapidkit dev")} ${d.gray("# Start dev server")}
564
814
 
565
- ${r.bold("\u{1F4DA} Available commands:")}
815
+ ${d.bold("\u{1F4DA} Available commands:")}
566
816
  npx rapidkit init # Install dependencies
567
817
  npx rapidkit dev # Start dev server with hot reload
568
818
  npx rapidkit start # Start production server
@@ -571,16 +821,28 @@ ${r.bold("\u{1F4DA} Available commands:")}
571
821
  npx rapidkit lint # Lint code
572
822
  npx rapidkit format # Format code
573
823
 
574
- ${r.bold("\u{1F310} API endpoints:")}
824
+ ${d.bold("\u{1F310} API endpoints:")}
575
825
  http://localhost:8000/health # Health check
576
826
  http://localhost:8000/docs # Swagger docs
577
827
  http://localhost:8000/examples/notes # Example API
578
828
 
579
- ${r.gray("\u{1F4A1} Tip: Install globally (npm i -g rapidkit) to use without npx")}
580
- `);}catch(s){throw a.fail(`Failed to create ${n} project`),s}}async function z(e,t,i){let n=await promises.readdir(e,{withFileTypes:true});for(let a of n){let s=l.join(e,a.name),c=a.name.replace(/\.j2$/,""),o=l.join(t,c);if(a.isDirectory())await promises.mkdir(o,{recursive:true}),await z(s,o,i);else {let d=await promises.readFile(s,"utf-8");a.name.endsWith(".j2")&&(d=he(d,i)),await promises.writeFile(o,d),(c==="rapidkit"||c==="activate"||c.endsWith(".py")&&o.includes(".rapidkit"))&&await promises.chmod(o,493);}}}function he(e,t){let i=e;for(let[n,a]of Object.entries(t)){let s=new RegExp(`\\{\\{\\s*${n}\\s*\\}\\}`,"g");i=i.replace(s,String(a));let c=new RegExp(`\\{\\{\\s*${n}\\s*\\|\\s*replace\\s*\\(\\s*['"]([^'"]+)['"]\\s*,\\s*['"]([^'"]*)['"]\\s*\\)\\s*\\}\\}`,"g");i=i.replace(c,(f,$,j)=>String(a).replace(new RegExp($,"g"),j));let o=new RegExp(`\\{\\{\\s*${n}\\s*\\|\\s*lower\\s*\\}\\}`,"g");i=i.replace(o,String(a).toLowerCase());let d=new RegExp(`\\{\\{\\s*${n}\\s*\\|\\s*replace\\s*\\(\\s*['"]([^'"]+)['"]\\s*,\\s*['"]([^'"]*)['"]\\s*\\)\\s*\\|\\s*lower\\s*\\}\\}`,"g");i=i.replace(d,(f,$,j)=>String(a).replace(new RegExp($,"g"),j).toLowerCase());}return i}var B=["init","dev","start","build","test","lint","format","create","help","--help","-h"];function ke(e){let t=e;for(;;){let i=l.join(t,".rapidkit","context.json");if(k.existsSync(i))return i;let n=l.dirname(t);if(n===t)break;t=n;}return null}function $e(e){let t=process.platform==="win32",i=e;for(;;){if(t){let c=l.join(i,"rapidkit.cmd"),o=l.join(i,".rapidkit","rapidkit.cmd");if(k.existsSync(c))return c;if(k.existsSync(o))return o}let n=l.join(i,"rapidkit"),a=l.join(i,".rapidkit","rapidkit");if(k.existsSync(n))return n;if(k.existsSync(a))return a;let s=l.dirname(i);if(s===i)break;i=s;}return null}(()=>{try{let e=process.cwd(),i=process.argv.slice(2)[0],n=ke(e);if(n&&k.existsSync(n)){let a=k.readFileSync(n,"utf8");try{let s=JSON.parse(a),c=i==="shell"&&process.argv.slice(2)[1]==="activate",d=$e(e)&&i&&B.includes(i);s?.engine==="pip"&&!c&&!d&&i!=="init"&&(console.log(r.yellow(`
581
- \u26A0\uFE0F This project uses the Python RapidKit engine (pip). The global npm RapidKit CLI will not operate on this project.
582
- \u{1F4A1} To prepare this project run: 'rapidkit init' (it uses the project's Python toolchain)
583
- `)),process.exit(0));}catch{}}}catch{}})();function X(e){let t=e;for(;;){let i=l.join(t,".rapidkit","context.json");if(k.existsSync(i))return i;let n=l.dirname(t);if(n===t)break;t=n;}return null}async function we(){let e=process.cwd(),t=X(e),i=process.platform==="win32",n=i?[l.join(e,"rapidkit.cmd"),l.join(e,"rapidkit"),l.join(e,".rapidkit","rapidkit.cmd"),l.join(e,".rapidkit","rapidkit")]:[l.join(e,"rapidkit"),l.join(e,".rapidkit","rapidkit")],a=null;for(let o of n)if(await h.pathExists(o)){a=o;break}let s=process.argv.slice(2),c=s[0];if(a&&c&&B.includes(c)){m.debug(`Delegating to local CLI: ${a} ${s.join(" ")}`);let o=spawn(a,s,{stdio:"inherit",cwd:e,shell:i});return o.on("close",d=>{process.exit(d??0);}),o.on("error",d=>{m.error(`Failed to run local rapidkit: ${d.message}`),process.exit(1);}),true}if(t&&await h.pathExists(t))try{if((await h.readJson(t)).engine==="pip"){let d=process.argv.slice(2),f=d[0],j=process.platform==="win32"?[l.join(e,"rapidkit.cmd"),l.join(e,"rapidkit"),l.join(e,".rapidkit","rapidkit.cmd"),l.join(e,".rapidkit","rapidkit")]:[l.join(e,"rapidkit"),l.join(e,".rapidkit","rapidkit")],_=null;for(let g of j)if(await h.pathExists(g)){_=g;break}if(_&&f&&B.includes(f)){m.debug(`Delegating to local CLI (early detection): ${_} ${d.join(" ")}`);let g=spawn(_,d,{stdio:"inherit",cwd:e});return g.on("close",E=>process.exit(E??0)),g.on("error",E=>{m.error(`Failed to run local rapidkit: ${E.message}`),process.exit(1);}),!0}if(f==="shell"&&d[1]==="activate"){let g=`# RapidKit: activation snippet - eval "$(rapidkit shell activate)"
829
+ ${d.gray("Alternative: npm run start:dev, ./rapidkit dev")}
830
+ ${d.gray("\u{1F4A1} Tip: Install globally (npm i -g rapidkit) to use without npx")}
831
+ `);}catch(c){throw r.fail(`Failed to generate ${o} project`),c}}function Mt(t){if(!t||typeof t!="object")return null;let e=t.code;return e==="PYTHON_NOT_FOUND"||e==="BRIDGE_VENV_BOOTSTRAP_FAILED"?e:null}function be(t){let e=t.trim().toLowerCase();return e?e.startsWith("fastapi")?"fastapi":e.startsWith("nestjs")?"nestjs":null:null}function Pe(t,e){let i=t.indexOf(e);if(i>=0&&i+1<t.length)return t[i+1];let n=t.find(o=>o.startsWith(`${e}=`));if(n)return n.slice(e.length+1)}async function Gt(t,e){if(t.includes("--json"))return process.stderr.write("RapidKit (npm) offline fallback does not support --json for `create` commands.\nInstall Python 3.10+ and retry the same command.\n"),1;if(t[0]!=="create")return 1;if(t[1]!=="project")return process.stderr.write(`RapidKit (npm) could not run the Python core engine for \`create\`.
832
+ Reason: ${e}.
833
+ Install Python 3.10+ to use the interactive wizard and full kit catalog.
834
+ `),1;let o=t[2],r=t[3];if(!o||!r)return process.stderr.write(`Usage: rapidkit create project <kit> <name> [--output <dir>]
835
+ Tip: offline fallback supports only fastapi* and nestjs* kits.
836
+ `),1;let c=be(o);if(!c)return process.stderr.write(`RapidKit (npm) could not run the Python core engine to create this kit.
837
+ Reason: ${e}.
838
+ Requested kit: ${o}
839
+ Offline fallback only supports: fastapi.standard, nestjs.standard (and their shorthands).
840
+ Install Python 3.10+ to access all kits.
841
+ `),1;let a=Pe(t,"--output")||process.cwd(),s=y.resolve(a,r),p=t.includes("--skip-git")||t.includes("--no-git"),f=t.includes("--skip-install");try{return await x.ensureDir(y.dirname(s)),await x.pathExists(s)?(process.stderr.write(`\u274C Directory "${s}" already exists
842
+ `),1):(await x.ensureDir(s),await Vt(s,{project_name:r,template:c,skipGit:p,skipInstall:f}),0)}catch(m){return process.stderr.write(`RapidKit (npm) offline fallback failed: ${m?.message??m}
843
+ `),1}}async function Re(t){let e=new Set(["--yes","-y","--skip-git","--skip-install","--debug","--dry-run","--no-update-check","--create-workspace","--no-workspace"]);try{if(t[0]==="create"&&t[1]==="project"){let i=t.includes("--create-workspace"),n=t.includes("--no-workspace"),o=t.includes("--yes")||t.includes("-y"),r=t.includes("--skip-git")||t.includes("--no-git");if(!!!ft(process.cwd())){if(i)await K(process.cwd(),{skipGit:r,yes:o,userConfig:await J()});else if(!n)if(o)await K(process.cwd(),{skipGit:r,yes:!0,userConfig:await J()});else {let{createWs:s}=await lt.prompt([{type:"confirm",name:"createWs",message:"This project will be created outside a RapidKit workspace. Create and register a workspace here?",default:!0}]);s&&await K(process.cwd(),{skipGit:r,yes:!1,userConfig:await J()});}}let a=t.filter(s=>{let p=s.split("=")[0];return !e.has(s)&&!e.has(p)});try{return await tt(),await $(a,{cwd:process.cwd()})}catch(s){let p=Mt(s);return p?await Gt(a,p):(process.stderr.write(`RapidKit (npm) failed to run the Python core engine: ${s?.message??s}
844
+ `),1)}}return await tt(),await $(t,{cwd:process.cwd()})}catch(i){let n=Mt(i);return n?await Gt(t,n):(process.stderr.write(`RapidKit (npm) failed to run the Python core engine: ${i?.message??i}
845
+ `),1)}}var Lt=["init","dev","start","build","test","lint","format","create","help","--help","-h"];function je(t){let e=t;for(;;){let i=y.join(e,".rapidkit","context.json");if(Q.existsSync(i))return i;let n=y.dirname(e);if(n===e)break;e=n;}return null}function ft(t){let e=t;for(;;){let i=y.join(e,".rapidkit-workspace");if(Q.existsSync(i))return i;let n=y.dirname(e);if(n===e)break;e=n;}return null}async function _e(){let t=process.cwd();try{let s=process.argv.slice(2)[0],p=!s||s==="--help"||s==="-h"||s==="help";if(ft(t)&&p){let m=await $(s?["--help"]:[],{cwd:t});process.exit(m);}}catch{}try{let a=process.argv.slice(2),p=a[0]==="shell"&&a[1]==="activate",f=await vt(t,{cwd:t,timeoutMs:1200});if(f.ok&&f.data?.isRapidkitProject&&f.data.engine==="python"&&!p){let m=await $(process.argv.slice(2),{cwd:t});process.exit(m);}}catch{}let e=je(t),i=process.platform==="win32",n=i?[y.join(t,"rapidkit.cmd"),y.join(t,"rapidkit"),y.join(t,".rapidkit","rapidkit.cmd"),y.join(t,".rapidkit","rapidkit")]:[y.join(t,"rapidkit"),y.join(t,".rapidkit","rapidkit")],o=null;for(let a of n)if(await x.pathExists(a)){o=a;break}let r=process.argv.slice(2),c=r[0];if(o&&c&&Lt.includes(c)){u.debug(`Delegating to local CLI: ${o} ${r.join(" ")}`);let a=spawn(o,r,{stdio:"inherit",cwd:t,shell:i});return a.on("close",s=>{process.exit(s??0);}),a.on("error",s=>{u.error(`Failed to run local rapidkit: ${s.message}`),process.exit(1);}),true}if(e&&await x.pathExists(e))try{if((await x.readJson(e)).engine==="pip"){let s=process.argv.slice(2),p=s[0],m=process.platform==="win32"?[y.join(t,"rapidkit.cmd"),y.join(t,"rapidkit"),y.join(t,".rapidkit","rapidkit.cmd"),y.join(t,".rapidkit","rapidkit")]:[y.join(t,"rapidkit"),y.join(t,".rapidkit","rapidkit")],P=null;for(let w of m)if(await x.pathExists(w)){P=w;break}if(P&&p&&Lt.includes(p)){u.debug(`Delegating to local CLI (early detection): ${P} ${s.join(" ")}`);let w=spawn(P,s,{stdio:"inherit",cwd:t});return w.on("close",C=>process.exit(C??0)),w.on("error",C=>{u.error(`Failed to run local rapidkit: ${C.message}`),process.exit(1);}),!0}if(p==="shell"&&s[1]==="activate"){let w=`# RapidKit: activation snippet - eval "$(rapidkit shell activate)"
584
846
  VENV='.venv'
585
847
  if [ -f "$VENV/bin/activate" ]; then
586
848
  . "$VENV/bin/activate"
@@ -589,45 +851,37 @@ elif [ -f "$VENV/bin/activate.fish" ]; then
589
851
  fi
590
852
  export RAPIDKIT_PROJECT_ROOT="$(pwd)"
591
853
  export PATH="$(pwd)/.rapidkit:$(pwd):$PATH"
592
- `;console.log(r.green.bold(`
854
+ `;console.log(d.green.bold(`
593
855
  \u2705 Activation snippet \u2014 run the following to activate this project in your current shell:
594
- `)),console.log(g),console.log(r.gray(`
856
+ `)),console.log(w),console.log(d.gray(`
595
857
  \u{1F4A1} After activation you can run: rapidkit dev
596
- `)),process.exit(0);}if(f!=="init"){let g=(await import('chalk')).default;console.log(g.yellow(`
597
- \u26A0\uFE0F This project uses the Python RapidKit engine (pip). The global npm RapidKit CLI will not operate on this project.
598
- \u{1F4A1} To prepare this project run: 'rapidkit init' (it uses the project's Python toolchain)
599
-
600
- `)),process.exit(0);}let L=(await import('chalk')).default;console.log(L.yellow(`
601
- \u26A0\uFE0F This project was created with the Python engine (pip). RapidKit (npm) will try to install the Python CLI for you...
602
- `));let{spawnSync:w}=await import('child_process'),D=[["python3",["-m","pip","install","rapidkit-core"]],["python",["-m","pip","install","rapidkit-core"]],["pip",["install","rapidkit-core"]]],P=!0;if(process.stdin.isTTY)try{P=!!(await O.prompt([{type:"confirm",name:"confirm",message:"This project needs the Python RapidKit CLI (rapidkit). Do you want to try installing it now using pip?",default:!0}])).confirm;}catch{P=!1;}else P=!1;if(!P){let g=(await import('chalk')).default;console.log(g.yellow(`
603
- \u26A0\uFE0F Skipping automatic installation of the Python RapidKit CLI (rapidkit-core).
604
- \u{1F4A1} To continue, either run 'rapidkit init' locally after installing rapidkit-core: \`python3 -m pip install rapidkit-core\`
605
- `)),process.exit(0);}let R={status:1,stderr:null,stdout:null};if(P)for(let[g,E]of D)try{if(console.log(r.gray(`Running: ${g} ${E.join(" ")}
606
- `)),R=w(g,E,{stdio:"inherit"}),R&&R.status===0)break}catch{}if(R&&R.status===0){let g=(await import('chalk')).default;console.log(g.green(`
607
- \u2705 RapidKit Python CLI (rapidkit) installed successfully!
608
- Please re-run your command.
609
- `));}else {let g=(await import('chalk')).default;console.log(g.red(`
610
- \u274C Failed to install RapidKit Python CLI automatically.
611
- \u{1F4A1} Manual install options:
612
- python3 -m pip install rapidkit
613
- python -m pip install rapidkit
614
- pip install rapidkit
615
- `));}process.exit(R.status??1);}}catch{}return false}var x=null,U=false,K=new Command;K.name("rapidkit").description("Create RapidKit workspaces and projects").version(N());K.argument("[name]","Name of the workspace or project directory").option("-t, --template <template>","Create project with template (fastapi, nestjs) instead of workspace").option("-y, --yes","Skip prompts and use defaults").option("--skip-git","Skip git initialization").option("--skip-install","Skip installing dependencies").option("--debug","Enable debug logging").option("--dry-run","Show what would be created without creating it").option("--no-update-check","Skip checking for updates").action(async(e,t)=>{try{t.debug&&(m.setDebug(!0),m.debug("Debug mode enabled"));let i=await W();m.debug("User config loaded",i),t.updateCheck!==!1&&await J(),console.log(r.blue.bold(`
858
+ `)),process.exit(0);}let A=await $(s,{cwd:t});process.exit(A);}}catch{}return false}var D=null,nt=false,H=new Command;async function Ee(t){if(t.length===0)return false;let e=t[0],i=t[1];if(e==="shell"&&i==="activate")return false;if(t.includes("--tui"))return true;if(e==="--help"||e==="-h"||e==="help"||e==="--version"||e==="-V"||t.includes("--template")||t.includes("-t"))return false;let n=new Set(["--yes","-y","--skip-git","--skip-install","--debug","--dry-run","--no-update-check","--create-workspace","--no-workspace"]);if(t.some(r=>n.has(r)))return false;let o=await _t();return o?o.has(e):!!(Ct.has(e)||t.length>1)}H.name("rapidkit").description("Create RapidKit workspaces and projects").version(V());H.addHelpText("beforeAll",`RapidKit
859
+
860
+ Global CLI
861
+ Create RapidKit workspaces and projects
862
+
863
+ Global Engine Commands
864
+ Access engine-level commands when inside a RapidKit workspace or via the core bridge
865
+ `);H.addHelpText("afterAll",`
866
+ Project Commands
867
+ rapidkit create
868
+ rapidkit init
869
+ rapidkit dev
870
+
871
+ Use "rapidkit help <command>" for more information.
872
+ `);H.argument("[name]","Name of the workspace or project directory").addOption(new Option("-t, --template <template>","Legacy: create a project with template (fastapi, nestjs) instead of a workspace").hideHelp()).option("-y, --yes","Skip prompts and use defaults").addOption(new Option("--skip-git","Skip git initialization").hideHelp()).addOption(new Option("--skip-install","Legacy: skip installing dependencies (template mode)").hideHelp()).option("--debug","Enable debug logging").addOption(new Option("--dry-run","Show what would be created without creating it").hideHelp()).addOption(new Option("--create-workspace","When creating a project outside a workspace: create and register a workspace in the current directory").hideHelp()).addOption(new Option("--no-workspace","When creating a project outside a workspace: do not create a workspace").hideHelp()).option("--no-update-check","Skip checking for updates").action(async(t,e)=>{try{e.debug&&(u.setDebug(!0),u.debug("Debug mode enabled"));let i=await J();u.debug("User config loaded",i),e.updateCheck!==!1&&await wt(),console.log(d.blue.bold(`
616
873
  \u{1F680} Welcome to RapidKit!
617
- `)),e||(ve(),process.exit(0));try{M(e);}catch(c){throw c instanceof S&&(m.error(`
618
- \u274C ${c.message}`),c.details&&m.warn(`\u{1F4A1} ${c.details}
619
- `),process.exit(1)),c}let n=l.resolve(process.cwd(),e);x=n,await h.pathExists(n)&&(m.error(`
620
- \u274C Directory "${e}" already exists`),console.log(r.cyan(`
874
+ `)),t||(Ie(),process.exit(0));try{kt(t);}catch(r){throw r instanceof _&&(u.error(`
875
+ \u274C ${r.message}`),r.details&&u.warn(`\u{1F4A1} ${r.details}
876
+ `),process.exit(1)),r}let n=y.resolve(process.cwd(),t);D=n,await x.pathExists(n)&&(u.error(`
877
+ \u274C Directory "${t}" already exists`),console.log(d.cyan(`
621
878
  \u{1F4A1} Choose a different name or delete the existing directory.
622
- `)),process.exit(1));let a=!!t.template;if(a){let c=t.template.toLowerCase(),o=["fastapi","nestjs"];o.includes(c)||(m.error(`
623
- \u274C Invalid template: ${t.template}`),console.log(r.cyan(`
624
- \u{1F4E6} Available templates: ${o.join(", ")}
625
- `)),process.exit(1));}if(t.dryRun){console.log(r.cyan(`
879
+ `)),process.exit(1));let o=!!e.template;if(e.dryRun){console.log(d.cyan(`
626
880
  \u{1F50D} Dry-run mode - showing what would be created:
627
- `)),console.log(r.white("\u{1F4C2} Path:"),n),console.log(r.white("\u{1F4E6} Type:"),a?`Project (${t.template})`:"Workspace"),console.log();return}let s;t.yes?(s={author:process.env.USER||"RapidKit User",description:a?`${t.template==="nestjs"?"NestJS":"FastAPI"} application generated with RapidKit`:void 0,package_manager:"npm"},console.log(r.gray(`Using default values (--yes flag)
628
- `))):a?t.template.toLowerCase()==="fastapi"?s=await O.prompt([{type:"input",name:"author",message:"Author name:",default:process.env.USER||"RapidKit User"},{type:"input",name:"description",message:"Project description:",default:"FastAPI service generated with RapidKit"}]):s=await O.prompt([{type:"input",name:"author",message:"Author name:",default:process.env.USER||"RapidKit User"},{type:"input",name:"description",message:"Project description:",default:"NestJS application generated with RapidKit"},{type:"list",name:"package_manager",message:"Package manager:",choices:["npm","yarn","pnpm"],default:"npm"}]):s=await O.prompt([{type:"input",name:"author",message:"Author name:",default:process.env.USER||"RapidKit User"}]),a?await Y(n,{name:e,template:t.template.toLowerCase(),author:s.author,description:s.description,package_manager:s.package_manager,skipGit:t.skipGit,skipInstall:t.skipInstall}):await H(n,{name:e,author:s.author,skipGit:t.skipGit});}catch(i){i instanceof S?(m.error(`
629
- \u274C ${i.message}`),i.details&&m.warn(`\u{1F4A1} ${i.details}`),m.debug("Error code:",i.code)):(m.error(`
630
- \u274C An unexpected error occurred:`),console.error(i)),process.exit(1);}finally{x=null;}});K.command("shell <action>").description("Shell helpers (activate virtualenv in current shell)").action(async e=>{e!=="activate"&&(console.log(r.red(`Unknown shell command: ${e}`)),process.exit(1));let t=process.cwd();function i(c){let o=c;for(;;){let d=l.join(o,".rapidkit","context.json");if(k.existsSync(d))return d;let f=l.dirname(o);if(f===o)break;o=f;}return null}let n=i(t);function a(c){let o=c;for(;;){let d=l.join(o,".venv"),f=l.join(o,".rapidkit","activate");if(k.existsSync(f)||k.existsSync(d))return {venv:d,activateFile:f};let $=l.dirname(o);if($===o)break;o=$;}return null}let s=a(t);if(!n&&!s&&(console.log(r.red("No RapidKit project found to activate")),process.exit(1)),s){let c=`# RapidKit: activation snippet - eval "$(rapidkit shell activate)"
881
+ `)),console.log(d.white("\u{1F4C2} Path:"),n),console.log(d.white("\u{1F4E6} Type:"),o?`Project (${e.template})`:"Workspace"),console.log();return}if(!e.yes&&!o?await lt.prompt([{type:"input",name:"author",message:"Author name:",default:process.env.USER||"RapidKit User"}]):e.yes&&console.log(d.gray(`Using default values (--yes flag)
882
+ `)),o){let r=String(e.template||"").trim(),c=r.toLowerCase(),a=c==="fastapi"?"fastapi.standard":c==="nestjs"?"nestjs.standard":r;if(!!!ft(process.cwd())){if(e.createWorkspace)await K(process.cwd(),{skipGit:e.skipGit,yes:e.yes,userConfig:i});else if(!e.noWorkspace)if(e.yes)await K(process.cwd(),{skipGit:e.skipGit,yes:!0,userConfig:i});else {let{createWs:m}=await lt.prompt([{type:"confirm",name:"createWs",message:"This project will be created outside a RapidKit workspace. Create and register a workspace here?",default:!0}]);m&&await K(process.cwd(),{skipGit:e.skipGit,yes:!1,userConfig:i});}}let p=["create","project",a,t,"--output",process.cwd(),"--install-essentials"],f=await $(p,{cwd:process.cwd()});if(f!==0&&process.exit(f),!e.skipInstall){let m=await $(["init",n],{cwd:process.cwd()});m!==0&&process.exit(m);}}else await Tt(t,{skipGit:e.skipGit,dryRun:e.dryRun,yes:e.yes,userConfig:i});}catch(i){i instanceof _?(u.error(`
883
+ \u274C ${i.message}`),i.details&&u.warn(`\u{1F4A1} ${i.details}`),u.debug("Error code:",i.code)):(u.error(`
884
+ \u274C An unexpected error occurred:`),console.error(i)),process.exit(1);}finally{D=null;}});H.command("shell <action>").description("Shell helpers (activate virtualenv in current shell)").action(async t=>{t!=="activate"&&(console.log(d.red(`Unknown shell command: ${t}`)),process.exit(1));let e=process.cwd();function i(c){let a=c;for(;;){let s=y.join(a,".rapidkit","context.json");if(Q.existsSync(s))return s;let p=y.dirname(a);if(p===a)break;a=p;}return null}let n=i(e);function o(c){let a=c;for(;;){let s=y.join(a,".venv"),p=y.join(a,".rapidkit","activate");if(Q.existsSync(p)||Q.existsSync(s))return {venv:s,activateFile:p};let f=y.dirname(a);if(f===a)break;a=f;}return null}let r=o(e);if(!n&&!r&&(console.log(d.red("No RapidKit project found to activate")),process.exit(1)),r){let c=`# RapidKit: activation snippet - eval "$(rapidkit shell activate)"
631
885
  VENV='.venv'
632
886
  if [ -f "$VENV/bin/activate" ]; then
633
887
  . "$VENV/bin/activate"
@@ -636,11 +890,11 @@ elif [ -f "$VENV/bin/activate.fish" ]; then
636
890
  fi
637
891
  export RAPIDKIT_PROJECT_ROOT="$(pwd)"
638
892
  export PATH="$(pwd)/.rapidkit:$(pwd):$PATH"
639
- `;console.log(r.green.bold(`
893
+ `;console.log(d.green.bold(`
640
894
  \u2705 Activation snippet \u2014 run the following to activate this project in your current shell:
641
- `)),console.log(c),console.log(r.gray(`
895
+ `)),console.log(c),console.log(d.gray(`
642
896
  \u{1F4A1} After activation you can run: rapidkit dev
643
- `)),process.exit(0);}try{(await h.readJson(n)).engine!=="pip"&&(console.log(r.yellow("This project is not a pip-based RapidKit project.")),process.exit(1)),console.log(`# RapidKit: activation snippet - eval "$(rapidkit shell activate)"
897
+ `)),process.exit(0);}try{(await x.readJson(n)).engine!=="pip"&&(console.log(d.yellow("This project is not a pip-based RapidKit project.")),process.exit(1)),console.log(`# RapidKit: activation snippet - eval "$(rapidkit shell activate)"
644
898
  VENV='.venv'
645
899
  if [ -f "$VENV/bin/activate" ]; then
646
900
  . "$VENV/bin/activate"
@@ -649,7 +903,7 @@ elif [ -f "$VENV/bin/activate.fish" ]; then
649
903
  fi
650
904
  export RAPIDKIT_PROJECT_ROOT="$(pwd)"
651
905
  export PATH="$(pwd)/.rapidkit:$(pwd):$PATH"
652
- `),process.exit(0);}catch{console.log(r.yellow("Could not read project context but found a venv or activation file \u2014 printing activation snippet")),console.log(`# RapidKit: activation snippet - eval "$(rapidkit shell activate)"
906
+ `),process.exit(0);}catch{console.log(d.yellow("Could not read project context but found a venv or activation file \u2014 printing activation snippet")),console.log(`# RapidKit: activation snippet - eval "$(rapidkit shell activate)"
653
907
  VENV='.venv'
654
908
  if [ -f "$VENV/bin/activate" ]; then
655
909
  . "$VENV/bin/activate"
@@ -658,15 +912,13 @@ elif [ -f "$VENV/bin/activate.fish" ]; then
658
912
  fi
659
913
  export RAPIDKIT_PROJECT_ROOT="$(pwd)"
660
914
  export PATH="$(pwd):$PATH"
661
- `),process.exit(0);}});function ve(){console.log(r.white(`Usage: npx rapidkit <name> [options]
662
- `)),console.log(r.bold("Create a workspace (recommended):")),console.log(r.cyan(" npx rapidkit my-workspace")),console.log(r.cyan(" cd my-workspace")),console.log(r.cyan(" rapidkit create my-api --template fastapi")),console.log(r.cyan(" cd my-api")),console.log(r.cyan(` rapidkit dev
663
- `)),console.log(r.bold("Or create a project directly:")),console.log(r.cyan(" npx rapidkit my-project --template fastapi")),console.log(r.cyan(` npx rapidkit my-project --template nestjs
664
- `)),console.log(r.bold("Options:")),console.log(r.gray(" -t, --template <template> Create project with template (fastapi, nestjs)")),console.log(r.gray(" -y, --yes Skip prompts and use defaults")),console.log(r.gray(" --skip-git Skip git initialization")),console.log(r.gray(" --skip-install Skip installing dependencies")),console.log(r.gray(" --debug Enable debug logging")),console.log(r.gray(` --dry-run Show what would be created
665
- `)),console.log(r.bold("Templates:")),console.log(r.gray(" fastapi FastAPI + Python")),console.log(r.gray(` nestjs NestJS + TypeScript
666
- `));}process.on("SIGINT",async()=>{if(!U){if(U=true,console.log(r.yellow(`
667
-
668
- \u26A0\uFE0F Interrupted by user`)),x&&await h.pathExists(x)){console.log(r.gray("Cleaning up partial installation..."));try{await h.remove(x),console.log(r.green("\u2713 Cleanup complete"));}catch(e){m.debug("Cleanup failed:",e);}}process.exit(130);}});process.on("SIGTERM",async()=>{if(!U){if(U=true,m.debug("Received SIGTERM"),x&&await h.pathExists(x))try{await h.remove(x);}catch(e){m.debug("Cleanup failed:",e);}process.exit(143);}});we().then(async e=>{if(!e){let t=process.cwd();try{let i=X(t);if(i&&await h.pathExists(i)){let n=await h.readJson(i),a=process.argv.slice(2)[0];if(n?.engine==="pip"&&a!=="init"){let s=(await import('chalk')).default;console.log(s.yellow(`
669
- \u26A0\uFE0F This project uses the Python RapidKit engine (pip). The global npm RapidKit CLI will not operate on this project.
670
- \u{1F4A1} To prepare this project run: 'rapidkit init' (it uses the project's Python toolchain)
671
-
672
- `)),process.exit(0);}}}catch{}K.parse();}});
915
+ `),process.exit(0);}});function Ie(){console.log(d.white(`Usage:
916
+ `)),console.log(d.cyan(" npx rapidkit <workspace-name> [options]")),console.log(d.cyan(` npx rapidkit create <...>
917
+ `)),console.log(d.bold("Recommended workflow:")),console.log(d.cyan(" npx rapidkit my-workspace")),console.log(d.cyan(" cd my-workspace")),console.log(d.cyan(" npx rapidkit create project fastapi.standard my-api --output .")),console.log(d.cyan(" cd my-api")),console.log(d.cyan(` npx rapidkit init && npx rapidkit dev
918
+ `)),console.log(d.bold("Options (workspace creation):")),console.log(d.gray(" -y, --yes Skip prompts and use defaults")),console.log(d.gray(" --skip-git Skip git initialization")),console.log(d.gray(" --debug Enable debug logging")),console.log(d.gray(" --dry-run Show what would be created")),console.log(d.gray(" --create-workspace When creating a project outside a workspace: create and register a workspace in the current directory")),console.log(d.gray(" --no-workspace When creating a project outside a workspace: do not create a workspace")),console.log(d.gray(` --no-update-check Skip checking for updates
919
+ `)),console.log(d.gray(`Tip: set RAPIDKIT_SHOW_LEGACY=1 to show legacy template flags in help.
920
+ `));}process.on("SIGINT",async()=>{if(!nt){if(nt=true,console.log(d.yellow(`
921
+
922
+ \u26A0\uFE0F Interrupted by user`)),D&&await x.pathExists(D)){console.log(d.gray("Cleaning up partial installation..."));try{await x.remove(D),console.log(d.green("\u2713 Cleanup complete"));}catch(t){u.debug("Cleanup failed:",t);}}process.exit(130);}});process.on("SIGTERM",async()=>{if(!nt){if(nt=true,u.debug("Received SIGTERM"),D&&await x.pathExists(D))try{await x.remove(D);}catch(t){u.debug("Cleanup failed:",t);}process.exit(143);}});_e().then(async t=>{if(!t){let e=process.argv.slice(2);if(process.env.RAPIDKIT_NPM_DEBUG_ARGS==="1"&&process.stderr.write(`[rapidkit-npm] argv=${JSON.stringify(e)}
923
+ `),e[0]==="create"){let n=await Re(e);process.exit(n);}let i=await Ee(e);if(process.env.RAPIDKIT_NPM_DEBUG_ARGS==="1"&&process.stderr.write(`[rapidkit-npm] shouldForwardToCore=${i}
924
+ `),i){let n=await $(e,{cwd:process.cwd()});process.exit(n);}H.parse();}});export{Re as handleCreateOrFallback};