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.
- package/README.md +199 -38
- package/dist/index.d.ts +3 -0
- package/dist/index.js +746 -494
- package/dist/package.json +14 -6
- package/package.json +14 -6
- package/templates/generator.js +0 -175
- package/templates/kits/fastapi-standard/.rapidkit/__init__.py.j2 +0 -1
- package/templates/kits/fastapi-standard/.rapidkit/activate.j2 +0 -24
- package/templates/kits/fastapi-standard/.rapidkit/cli.py.j2 +0 -289
- package/templates/kits/fastapi-standard/.rapidkit/context.json +0 -3
- package/templates/kits/fastapi-standard/.rapidkit/project.json.j2 +0 -7
- package/templates/kits/fastapi-standard/.rapidkit/rapidkit.j2 +0 -107
- package/templates/kits/fastapi-standard/Makefile.j2 +0 -41
- package/templates/kits/fastapi-standard/README.md.j2 +0 -38
- package/templates/kits/fastapi-standard/kit.json +0 -70
- package/templates/kits/fastapi-standard/kit.yaml +0 -120
- package/templates/kits/fastapi-standard/pyproject.toml.j2 +0 -42
- package/templates/kits/fastapi-standard/rapidkit.cmd.j2 +0 -72
- package/templates/kits/fastapi-standard/rapidkit.j2 +0 -50
- package/templates/kits/fastapi-standard/src/__init__.py.j2 +0 -3
- package/templates/kits/fastapi-standard/src/cli.py.j2 +0 -335
- package/templates/kits/fastapi-standard/src/main.py.j2 +0 -44
- package/templates/kits/fastapi-standard/src/modules/__init__.py.j2 +0 -3
- package/templates/kits/fastapi-standard/src/routing/__init__.py.j2 +0 -13
- package/templates/kits/fastapi-standard/src/routing/health.py.j2 +0 -32
- package/templates/kits/fastapi-standard/tests/__init__.py.j2 +0 -1
- package/templates/kits/nestjs-standard/.env.example.j2 +0 -16
- package/templates/kits/nestjs-standard/.eslintrc.js.j2 +0 -25
- package/templates/kits/nestjs-standard/.gitignore.j2 +0 -26
- package/templates/kits/nestjs-standard/.node-version.j2 +0 -1
- package/templates/kits/nestjs-standard/.nvmrc.j2 +0 -1
- package/templates/kits/nestjs-standard/.prettierrc.j2 +0 -7
- package/templates/kits/nestjs-standard/.rapidkit/activate.j2 +0 -25
- package/templates/kits/nestjs-standard/.rapidkit/context.json +0 -3
- package/templates/kits/nestjs-standard/.rapidkit/project.json.j2 +0 -7
- package/templates/kits/nestjs-standard/.rapidkit/rapidkit.cmd.j2 +0 -166
- package/templates/kits/nestjs-standard/.rapidkit/rapidkit.j2 +0 -227
- package/templates/kits/nestjs-standard/README.md.j2 +0 -110
- package/templates/kits/nestjs-standard/jest.config.ts.j2 +0 -21
- package/templates/kits/nestjs-standard/nest-cli.json.j2 +0 -10
- package/templates/kits/nestjs-standard/package.json.j2 +0 -75
- package/templates/kits/nestjs-standard/rapidkit.cmd.j2 +0 -5
- package/templates/kits/nestjs-standard/rapidkit.j2 +0 -5
- package/templates/kits/nestjs-standard/src/app.controller.ts.j2 +0 -12
- package/templates/kits/nestjs-standard/src/app.module.ts.j2 +0 -23
- package/templates/kits/nestjs-standard/src/app.service.ts.j2 +0 -11
- package/templates/kits/nestjs-standard/src/config/configuration.ts.j2 +0 -9
- package/templates/kits/nestjs-standard/src/config/index.ts.j2 +0 -2
- package/templates/kits/nestjs-standard/src/config/validation.ts.j2 +0 -11
- package/templates/kits/nestjs-standard/src/examples/dto/create-note.dto.ts.j2 +0 -11
- package/templates/kits/nestjs-standard/src/examples/examples.controller.ts.j2 +0 -24
- package/templates/kits/nestjs-standard/src/examples/examples.module.ts.j2 +0 -10
- package/templates/kits/nestjs-standard/src/examples/examples.service.ts.j2 +0 -33
- package/templates/kits/nestjs-standard/src/main.ts.j2 +0 -51
- package/templates/kits/nestjs-standard/src/modules/index.ts.j2 +0 -3
- package/templates/kits/nestjs-standard/test/app.controller.spec.ts.j2 +0 -22
- package/templates/kits/nestjs-standard/test/app.e2e-spec.ts.j2 +0 -48
- package/templates/kits/nestjs-standard/test/examples.controller.spec.ts.j2 +0 -28
- package/templates/kits/nestjs-standard/test/jest-e2e.json.j2 +0 -15
- package/templates/kits/nestjs-standard/tsconfig.build.json.j2 +0 -12
- 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
|
|
3
|
-
[${
|
|
4
|
-
\u26A0\uFE0F Update available: ${
|
|
5
|
-
`))):
|
|
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
|
-
.
|
|
8
|
-
!.env.example
|
|
24
|
+
.rapidkit-workspace/
|
|
9
25
|
|
|
10
|
-
|
|
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
|
-
|
|
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
|
-
|
|
19
|
-
|
|
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
|
-
$
|
|
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
|
-
$
|
|
32
|
-
|
|
33
|
-
$
|
|
34
|
-
|
|
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
|
-
|
|
75
|
-
|
|
76
|
-
|
|
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
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
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
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
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
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
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
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
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
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
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
|
-
#
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
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
|
-
#
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
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
|
-
|
|
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
|
-
|
|
588
|
+
## \u{1F680} Quick Start
|
|
401
589
|
|
|
402
|
-
|
|
590
|
+
### Generate Your First Demo Project
|
|
403
591
|
|
|
404
592
|
\`\`\`bash
|
|
405
|
-
#
|
|
406
|
-
|
|
593
|
+
# Generate a demo project:
|
|
594
|
+
node generate-demo.js my-api
|
|
407
595
|
|
|
408
|
-
#
|
|
409
|
-
|
|
596
|
+
# Navigate to the project:
|
|
597
|
+
cd my-api
|
|
410
598
|
|
|
411
|
-
#
|
|
412
|
-
|
|
599
|
+
# Install dependencies:
|
|
600
|
+
rapidkit init
|
|
413
601
|
|
|
414
|
-
#
|
|
415
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
##
|
|
620
|
+
## \u{1F3AF} What's Included
|
|
428
621
|
|
|
429
|
-
|
|
622
|
+
Each generated demo project contains:
|
|
430
623
|
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
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
|
-
##
|
|
631
|
+
## \u{1F4DA} Next Steps
|
|
443
632
|
|
|
444
|
-
-
|
|
445
|
-
-
|
|
446
|
-
|
|
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(
|
|
515
|
-
${
|
|
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
|
-
${
|
|
518
|
-
${
|
|
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
|
-
${
|
|
530
|
-
${
|
|
531
|
-
${
|
|
532
|
-
${
|
|
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
|
-
${
|
|
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
|
-
${
|
|
543
|
-
${
|
|
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
|
-
${
|
|
795
|
+
${d.green("\u2728 NestJS project created successfully!")}
|
|
546
796
|
|
|
547
|
-
${
|
|
548
|
-
${
|
|
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
|
|
552
|
-
\u2502 \u251C\u2500\u2500 app.module.ts
|
|
553
|
-
\u2502 \u251C\u2500\u2500 config/
|
|
554
|
-
\u2502 \u2514\u2500\u2500 examples/
|
|
555
|
-
\u251C\u2500\u2500 test/
|
|
556
|
-
\u251C\u2500\u2500 package.json
|
|
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
|
-
${
|
|
560
|
-
${
|
|
561
|
-
${
|
|
562
|
-
|
|
563
|
-
${
|
|
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
|
-
${
|
|
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
|
-
${
|
|
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
|
-
${
|
|
580
|
-
|
|
581
|
-
|
|
582
|
-
|
|
583
|
-
|
|
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(
|
|
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(
|
|
856
|
+
`)),console.log(w),console.log(d.gray(`
|
|
595
857
|
\u{1F4A1} After activation you can run: rapidkit dev
|
|
596
|
-
`)),process.exit(0);}if(
|
|
597
|
-
|
|
598
|
-
|
|
599
|
-
|
|
600
|
-
|
|
601
|
-
|
|
602
|
-
|
|
603
|
-
|
|
604
|
-
|
|
605
|
-
|
|
606
|
-
|
|
607
|
-
|
|
608
|
-
|
|
609
|
-
|
|
610
|
-
|
|
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
|
-
`)),
|
|
618
|
-
\u274C ${
|
|
619
|
-
`),process.exit(1)),
|
|
620
|
-
\u274C Directory "${
|
|
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
|
|
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(
|
|
628
|
-
`)))
|
|
629
|
-
\u274C ${i.message}`),i.details&&
|
|
630
|
-
\u274C An unexpected error occurred:`),console.error(i)),process.exit(1);}finally{
|
|
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(
|
|
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(
|
|
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
|
|
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(
|
|
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
|
|
662
|
-
`)),console.log(
|
|
663
|
-
`)),console.log(
|
|
664
|
-
`)),console.log(
|
|
665
|
-
`)),console.log(
|
|
666
|
-
`));}process.on("SIGINT",async()=>{if(!
|
|
667
|
-
|
|
668
|
-
\u26A0\uFE0F Interrupted by user`)),
|
|
669
|
-
|
|
670
|
-
|
|
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};
|