rapidkit 0.22.0 → 0.23.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.d.ts +6 -1
- package/dist/index.js +209 -196
- package/dist/package.json +2 -1
- package/package.json +7 -4
- package/scripts/enforce-package-manager.cjs +10 -0
package/dist/index.js
CHANGED
|
@@ -1,26 +1,38 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import {e,d,c as c$1,h
|
|
2
|
+
import {e,d,c as c$1,h,a as a$1}from'./chunk-74G6C57B.js';import {d as d$1,b as b$1}from'./chunk-RV6HBTFC.js';import {c,a,b}from'./chunk-7LU4Z66R.js';import {Command,Option}from'commander';import g from'chalk';import ae from'inquirer';import v from'path';import {fileURLToPath,pathToFileURL}from'url';import {exec,spawn}from'child_process';import A,{promises}from'fs';import*as qo from'os';import qo__default from'os';import Ko from'validate-npm-package-name';import*as R from'fs-extra';import R__default from'fs-extra';import {execa}from'execa';import pt from'ora';import nr from'nunjucks';import sr,{createHash}from'crypto';import {promisify}from'util';var Fo=".rapidkitrc.json",Ho=["rapidkit.config.js","rapidkit.config.mjs","rapidkit.config.cjs"];async function Z(){let e=v.join(qo__default.homedir(),Fo);try{let o=await promises.readFile(e,"utf-8"),t=JSON.parse(o);return a.debug(`Loaded config from ${e}`),t}catch{return a.debug("No user config found, using defaults"),{}}}async function Nt(e=process.cwd()){let o=e,t=v.parse(o).root;for(;o!==t;){for(let r of Ho){let i=v.join(o,r);try{await promises.access(i),a.debug(`Found config file: ${i}`);let s=await import(pathToFileURL(i).href),c=s.default||s;return a.debug(`Loaded RapidKit config from ${r}`),c}catch{continue}}o=v.dirname(o);}return a.debug("No RapidKit config file found, using defaults"),{}}function jt(e,o,t){return {author:t.author||o.workspace?.defaultAuthor||e.author,pythonVersion:o.workspace?.pythonVersion||e.pythonVersion,defaultInstallMethod:t.defaultInstallMethod||o.workspace?.installMethod||e.defaultInstallMethod,defaultKit:t.defaultKit||o.projects?.defaultKit||e.defaultKit,skipGit:t.skipGit??o.projects?.skipGit??e.skipGit,license:t.license||e.license,testRapidKitPath:t.testRapidKitPath||e.testRapidKitPath}}function Ae(e){return process.env.RAPIDKIT_DEV_PATH||e.testRapidKitPath||void 0}var H=class extends Error{constructor(t,r,i){super(t);this.code=r;this.details=i;this.name="RapidKitError",Error.captureStackTrace(this,this.constructor);}},de=class extends H{constructor(o,t){let r=t?`Python ${o}+ required, found ${t}`:`Python ${o}+ not found`;super(r,"PYTHON_NOT_FOUND","Please install Python from https://www.python.org/downloads/");}},we=class extends H{constructor(){super("Poetry is not installed","POETRY_NOT_FOUND","Install Poetry from https://python-poetry.org/docs/#installation");}},ye=class extends H{constructor(){super("pipx is not installed","PIPX_NOT_FOUND","Install pipx from https://pypa.github.io/pipx/installation/");}},Oe=class extends H{constructor(o){super(`Directory "${o}" already exists`,"DIRECTORY_EXISTS","Please choose a different name or remove the existing directory");}},Y=class extends H{constructor(o,t){super(`Invalid project name: "${o}"`,"INVALID_PROJECT_NAME",t);}},F=class extends H{constructor(o,t){let r=`Installation failed at: ${o}`,i=`${t.message}
|
|
3
3
|
|
|
4
4
|
Troubleshooting:
|
|
5
5
|
- Check your internet connection
|
|
6
6
|
- Verify Python/Poetry installation
|
|
7
|
-
- Try running with --debug flag for more details`;super(
|
|
7
|
+
- Try running with --debug flag for more details`;super(r,"INSTALLATION_ERROR",i);}},le=class extends H{constructor(){super("RapidKit Python package is not yet available on PyPI","RAPIDKIT_NOT_AVAILABLE",`Available options:
|
|
8
8
|
1. Install Python 3.10+ and retry the same command
|
|
9
9
|
2. Use the core workflow: npx rapidkit create workspace <name>
|
|
10
10
|
3. Offline fallback (limited): npx rapidkit create project fastapi.standard <name> --output .
|
|
11
11
|
|
|
12
|
-
Legacy: set RAPIDKIT_SHOW_LEGACY=1 to reveal template-mode flags in help.`);}};function
|
|
12
|
+
Legacy: set RAPIDKIT_SHOW_LEGACY=1 to reveal template-mode flags in help.`);}};function ct(e){let o=Ko(e);if(!o.validForNewPackages){let r=o.errors||[],i=o.warnings||[],n=[...r,...i];throw new Y(e,`NPM validation failed: ${n.join(", ")}`)}if(!/^[a-z][a-z0-9_-]*$/.test(e))throw new Y(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 Y(e,`"${e}" is a reserved name. Please choose a different name.`);if(e.length<2)throw new Y(e,"Name must be at least 2 characters long");if(e.length>214)throw new Y(e,"Name must be less than 214 characters");return true}function Vo(e){return typeof e=="object"&&e!==null}async function Wo(e,o,t,r=8e3){try{let i=await execa(e,o,{cwd:t,timeout:r,reject:false,stdio:"pipe"});return {ok:i.exitCode===0,exitCode:i.exitCode,stdout:i.stdout,stderr:i.stderr}}catch(i){return {ok:false,exitCode:void 0,stdout:"",stderr:i instanceof Error?i.message:String(i)}}}async function Bo(e,o){let t=["-m","rapidkit",...e],r=["python3","python"];for(let i of r){let n=await Wo(i,t,o?.cwd,o?.timeoutMs);if(!n.ok)continue;let s=(n.stdout??"").trim();try{let c=JSON.parse(s);return Vo(c)?{ok:true,command:i,exitCode:n.exitCode,stdout:n.stdout,stderr:n.stderr,data:c}:{ok:false,command:i,exitCode:n.exitCode,stdout:n.stdout,stderr:n.stderr}}catch{return {ok:false,command:i,exitCode:n.exitCode,stdout:n.stdout,stderr:n.stderr}}}return {ok:false}}async function Gt(e,o){let t=await Bo(["project","detect","--path",e,"--json"],o);return !t.ok||!t.data||t.data.schema_version!==1?{ok:false,command:t.command,exitCode:t.exitCode,stdout:t.stdout,stderr:t.stderr}:t}function Ne(){return process.platform==="win32"?"python":"python3"}async function Mt(e,o,t,r){let i=d$1(o,c(),t);r&&(i.metadata||(i.metadata={}),i.metadata.python={version:r}),await b$1(e,i);}async function qt(e){await R.outputFile(v.join(e,".gitignore"),`.venv/
|
|
13
13
|
__pycache__/
|
|
14
14
|
*.pyc
|
|
15
15
|
.env
|
|
16
16
|
.rapidkit-workspace/
|
|
17
17
|
|
|
18
|
-
`,"utf-8");}
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
18
|
+
`,"utf-8");}function Jo(e,o,t){return JSON.stringify({schema_version:"1.0",workspace_name:e,rapidkit_version:c(),created_at:new Date().toISOString(),created_by:"rapidkit-npm",profile:"minimal",engine:{install_method:o,python_version:t||null}},null,2)}function zo(e,o){return JSON.stringify({schema_version:"1.0",generated_by:"rapidkit-npm",generated_at:new Date().toISOString(),runtime:{python:{version:o||null,install_method:e},node:{version:process.version},go:{version:null}}},null,2)}function Yo(){return `version: "1.0"
|
|
19
|
+
mode: warn
|
|
20
|
+
rules:
|
|
21
|
+
enforce_workspace_marker: true
|
|
22
|
+
enforce_toolchain_lock: false
|
|
23
|
+
disallow_untrusted_tool_sources: false
|
|
24
|
+
`}function Qo(){return `version: "1.0"
|
|
25
|
+
cache:
|
|
26
|
+
strategy: shared
|
|
27
|
+
prune_on_bootstrap: false
|
|
28
|
+
self_heal: true
|
|
29
|
+
verify_integrity: false
|
|
30
|
+
`}async function Lt(e,o,t,r){await R.outputFile(v.join(e,".rapidkit","workspace.json"),Jo(o,t,r),"utf-8"),await R.outputFile(v.join(e,".rapidkit","toolchain.lock"),zo(t,r),"utf-8"),await R.outputFile(v.join(e,".rapidkit","policies.yml"),Yo(),"utf-8"),await R.outputFile(v.join(e,".rapidkit","cache-config.yml"),Qo(),"utf-8");}async function $t(e){try{let{stdout:o}=await execa(e,["--version"],{timeout:3e3}),t=o.match(/Python (\d+\.\d+\.\d+)/);if(t)return t[1]}catch{}return null}async function Xo(e,o){try{await promises.writeFile(v.join(e,".python-version"),`${o}
|
|
31
|
+
`,"utf-8"),a.debug(`Created .python-version with ${o}`);}catch(t){a.warn(`Failed to create .python-version: ${t}`);}}function ve(){let e=v.join(qo.homedir(),".local","bin"),t=(process.env.PATH||"").split(v.delimiter).filter(Boolean);t.includes(e)||(process.env.PATH=[e,...t].join(v.delimiter));}async function je(e,o){ve(),e.start("Checking pipx installation");try{return await execa("pipx",["--version"]),e.succeed("pipx found"),{kind:"binary"}}catch{}let t=Ne();try{return await execa(t,["-m","pipx","--version"]),e.succeed("pipx found"),{kind:"python-module",pythonCmd:t}}catch{}if(o)throw new ye;let{installPipx:r}=await ae.prompt([{type:"confirm",name:"installPipx",message:"pipx is not installed. Install it now (user install via python -m pip)?",default:true}]);if(!r)throw new ye;e.start("Installing pipx (user install)");try{try{await execa(t,["-m","pip","install","--user","--upgrade","pip"]);}catch{}await execa(t,["-m","pip","install","--user","--upgrade","pipx"]);}catch(i){let n=i,s=String(n?.stderr||n?.shortMessage||n?.message||"");throw new F("Install pipx with python -m pip",i instanceof Error?i:new Error(s))}e.succeed("pipx installed"),ve();try{return await execa(t,["-m","pipx","--version"]),{kind:"python-module",pythonCmd:t}}catch(i){let n=i,s=String(n?.stderr||n?.shortMessage||n?.message||"pipx not runnable after install");throw new F("Verify pipx after install",new Error(`${s}
|
|
32
|
+
|
|
33
|
+
Try reopening your terminal or run: python3 -m pipx ensurepath`))}}async function pe(e,o){return e.kind==="binary"?execa("pipx",o):execa(e.pythonCmd,["-m","pipx",...o])}async function Zo(e,o){ve(),e.start("Checking Poetry installation");try{await execa("poetry",["--version"]),e.succeed("Poetry found");return}catch{}if(o)throw new we;let{installPoetry:t}=await ae.prompt([{type:"confirm",name:"installPoetry",message:"Poetry is not installed. Install it now using pipx?",default:true}]);if(!t)throw new we;let r=await je(e,o);e.start("Installing Poetry with pipx");try{await pe(r,["install","poetry"]);}catch(i){let n=i,s=String(n?.stderr||n?.shortMessage||n?.message||"");if(/already\s+installed|already\s+seems\s+to\s+be\s+installed|exists/i.test(s))try{await pe(r,["upgrade","poetry"]);}catch{}else throw new F("Install Poetry with pipx",i instanceof Error?i:new Error(s))}e.succeed("Poetry installed"),ve();try{await execa("poetry",["--version"]);}catch(i){let n=i,s=String(n?.stderr||n?.shortMessage||n?.message||"Poetry not found on PATH");throw new F("Verify Poetry after pipx install",new Error(`${s}
|
|
34
|
+
|
|
35
|
+
Poetry may be installed but not on PATH yet. Try reopening your terminal or run: pipx ensurepath`))}}function er(e){let o=e==="poetry";return `#!/usr/bin/env sh
|
|
24
36
|
set -eu
|
|
25
37
|
|
|
26
38
|
SCRIPT_DIR=$(CDPATH= cd -- "$(dirname -- "$0")" && pwd)
|
|
@@ -39,7 +51,7 @@ echo "- If you used venv: ensure .venv exists (or re-run the installer)." 1>&2
|
|
|
39
51
|
${o?`echo "- If you used Poetry: run 'poetry install' and retry, or activate the env." 1>&2
|
|
40
52
|
`:""}echo "Tip: you can also run: ./.venv/bin/rapidkit --help" 1>&2
|
|
41
53
|
exit 1
|
|
42
|
-
`}function
|
|
54
|
+
`}function tr(e){return `@echo off
|
|
43
55
|
setlocal
|
|
44
56
|
|
|
45
57
|
set "SCRIPT_DIR=%~dp0"
|
|
@@ -58,42 +70,42 @@ if %ERRORLEVEL%==0 if exist "%SCRIPT_DIR%\\pyproject.toml" (
|
|
|
58
70
|
`:""}echo RapidKit launcher could not find a local Python CLI. 1>&2
|
|
59
71
|
echo Tip: run .venv\\Scripts\\rapidkit.exe --help 1>&2
|
|
60
72
|
exit /b 1
|
|
61
|
-
`}async function
|
|
73
|
+
`}async function Ft(e,o){await R.outputFile(v.join(e,"rapidkit"),er(o),{encoding:"utf-8",mode:493}),await R.outputFile(v.join(e,"rapidkit.cmd"),tr(o),"utf-8");}async function Ge(e,o){let{skipGit:t=false,testMode:r=false,demoMode:i=false,dryRun:n=false,yes:s=false,userConfig:c={},installMethod:a$1}=o,l=e||"rapidkit",d=v.resolve(process.cwd(),l);if(await R.pathExists(d))throw new Oe(l);if(n){await rr(d,l,i,c);return}if(i){await or(d,l,t);return}let p=s?{pythonVersion:c.pythonVersion||"3.10",installMethod:a$1||c.defaultInstallMethod||"poetry"}:await ae.prompt([{type:"list",name:"pythonVersion",message:"Select Python version for RapidKit:",choices:["3.10","3.11","3.12"],default:c.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:c.defaultInstallMethod||"poetry"}]);a.step(1,3,"Setting up RapidKit environment");let u=pt("Creating directory").start();try{await R.ensureDir(d),u.succeed("Directory created"),u.start("Detecting Python version");let h=null,x=await Ht(p.pythonVersion);if(x)h=await $t(x),h?(a.info(` Detected Python ${h}`),u.succeed(`Python ${h} detected`)):u.warn("Could not detect exact Python version");else {let y=Ne();h=await $t(y),h?u.succeed(`Python ${h} detected`):u.warn("Could not detect Python version, proceeding with defaults");}if(await Mt(d,l,p.installMethod,h||void 0),h&&await Xo(d,h),await Lt(d,l,p.installMethod,h||p.pythonVersion),await qt(d),p.installMethod==="poetry")try{await Kt(d,p.pythonVersion,u,r,c,s);}catch(y){let C=y?.details||y?.message||String(y);if(C.includes("pyenv")||C.includes("exit status 127")||C.includes("returned non-zero exit status 127")){u.warn("Poetry encountered Python discovery issues, trying venv method"),a.debug(`Poetry error (attempting venv fallback): ${C}`);try{await dt(d,p.pythonVersion,u,r,c),p.installMethod="venv";}catch(q){throw q}}else throw y}else p.installMethod==="venv"?await dt(d,p.pythonVersion,u,r,c):await Ut(d,u,r,c,s);if(await Ft(d,p.installMethod),await Vt(d,p.installMethod),u.succeed("RapidKit environment ready!"),!o.skipGit){u.start("Initializing git repository");try{await execa("git",["init"],{cwd:d}),await execa("git",["add","."],{cwd:d}),await execa("git",["commit","-m","Initial commit: RapidKit environment"],{cwd:d}),u.succeed("Git repository initialized");}catch{u.warn("Could not initialize git repository");}}try{let{registerWorkspace:y}=await import('./workspace-LZZGJRGV.js');await y(d,l);}catch{console.warn(g.gray("Note: Could not register workspace in shared registry"));}if(console.log(g.green(`
|
|
62
74
|
\u2728 RapidKit environment created successfully!
|
|
63
|
-
`)),console.log(g.cyan("\u{1F4C2} Location:"),g.white(
|
|
64
|
-
`)),console.log(g.white(` cd ${
|
|
75
|
+
`)),console.log(g.cyan("\u{1F4C2} Location:"),g.white(d)),console.log(g.cyan(`\u{1F680} Get started:
|
|
76
|
+
`)),console.log(g.white(` cd ${l}`)),p.installMethod==="poetry"){let y="source $(poetry env info --path)/bin/activate";try{ve();let{stdout:C}=await execa("poetry",["--version"]),E=C.match(/Poetry.*?(\d+)\.(\d+)/);E&&(parseInt(E[1])>=2?y="source $(poetry env info --path)/bin/activate":y="poetry shell");}catch{}console.log(g.white(` ${y} # Or: poetry run rapidkit`)),console.log(g.white(" rapidkit create # Interactive mode")),console.log(g.white(" cd <project-name> && rapidkit init && rapidkit dev"));}else p.installMethod==="venv"?(console.log(g.white(" source .venv/bin/activate # On Windows: .venv\\Scripts\\activate")),console.log(g.white(" rapidkit create # Interactive mode")),console.log(g.white(" cd <project-name> && rapidkit init && rapidkit dev"))):(console.log(g.white(" rapidkit create # Interactive mode")),console.log(g.white(" cd <project-name> && rapidkit init && rapidkit dev")));console.log(g.white(`
|
|
65
77
|
\u{1F4A1} For more information, check the README.md file.`)),console.log(g.cyan(`
|
|
66
78
|
\u{1F4DA} RapidKit commands:`)),console.log(g.white(" rapidkit create - Create a new project (interactive)")),console.log(g.white(" rapidkit dev - Run development server")),console.log(g.white(" rapidkit add module <name> - Add a module (e.g., settings)")),console.log(g.white(" rapidkit list - List available kits")),console.log(g.white(" rapidkit modules - List available modules")),console.log(g.white(` rapidkit --help - Show all commands
|
|
67
|
-
`));try{let{stdout:
|
|
68
|
-
\u274C Error:`),
|
|
69
|
-
package-mode = false`):
|
|
79
|
+
`));try{let{stdout:y}=await execa("go",["version"],{timeout:3e3}),C=y.match(/go version go(\d+\.\d+(?:\.\d+)?)/),E=C?C[1]:"unknown";console.log(g.gray(`\u{1F439} Go toolchain: Go ${E} detected \u2014 ready for gofiber.standard projects`));}catch{console.log(g.yellow("\u26A0\uFE0F Go toolchain not installed \u2014 needed for gofiber.standard projects")),console.log(g.gray(" Install: https://go.dev/dl/"));}console.log("");}catch(h){u.fail("Failed to create RapidKit environment"),console.error(g.red(`
|
|
80
|
+
\u274C Error:`),h);try{await R.remove(d);}catch{}throw h}}async function Ht(e){let o=[];try{let{stdout:t}=await execa("pyenv",["root"]),r=t.trim();o.push(v.join(r,"versions",`${e}.*`,"bin","python"));let[i,n]=e.split(".");o.push(v.join(r,"versions",`${i}.${n}.*`,"bin","python"));}catch{}o.push(`python${e}`,`python3.${e.split(".")[1]}`,"python3","python"),o.push(`/usr/bin/python${e}`,"/usr/bin/python3",`/usr/local/bin/python${e}`,"/usr/local/bin/python3");for(let t of o)try{let r=t;if(t.includes("*")){if(r=(await execa("sh",["-c",`ls -d ${t} 2>/dev/null | head -1`])).stdout.trim(),!r)continue;r=v.join(r.split("/").slice(0,-1).join("/"),"../bin/python");}let{stdout:i}=await execa(r,["--version"],{timeout:2e3}),n=i.match(/Python (\d+\.\d+)/)?.[1];if(n&&parseFloat(n)>=parseFloat(e))return await execa(r,["-c","import sys; sys.exit(0)"],{timeout:2e3}),r}catch{continue}return null}async function Kt(e,o,t,r,i,n=false){await Zo(t,n),t.start("Finding Python interpreter");let s=await Ht(o);s?(a.debug(`Found working Python: ${s}`),t.succeed("Python found")):t.warn("Could not verify Python path, proceeding with default"),t.start("Initializing Poetry project"),await execa("poetry",["init","--no-interaction","--python",`^${o}`],{cwd:e}),t.succeed("Poetry project initialized");let c=v.join(e,"pyproject.toml"),l=await promises.readFile(c,"utf-8");l.includes("[tool.poetry]")?l=l.replace("[tool.poetry]",`[tool.poetry]
|
|
81
|
+
package-mode = false`):l.includes("[project]")&&(l.includes("[build-system]")?l=l.replace("[build-system]",`
|
|
70
82
|
[tool.poetry]
|
|
71
83
|
package-mode = false
|
|
72
84
|
|
|
73
|
-
[build-system]`):
|
|
85
|
+
[build-system]`):l+=`
|
|
74
86
|
|
|
75
87
|
[tool.poetry]
|
|
76
88
|
package-mode = false
|
|
77
|
-
`),await promises.writeFile(c,
|
|
78
|
-
Error: ${
|
|
89
|
+
`),await promises.writeFile(c,l,"utf-8"),t.start("Configuring Poetry");try{if(await execa("poetry",["config","virtualenvs.in-project","true","--local"],{cwd:e}),s)try{await execa("poetry",["env","use",s],{cwd:e}),a.debug(`Poetry configured to use: ${s}`);}catch(d){a.debug(`Could not set Poetry env to ${s}: ${d}`);}t.succeed("Poetry configured");}catch{t.warn("Could not configure Poetry virtualenvs.in-project");}t.start("Creating virtualenv");try{await execa("poetry",["install","--no-root"],{cwd:e,timeout:3e4}),t.succeed("Virtualenv created");}catch(d){a.debug(`Failed to create virtualenv: ${d}`),t.warn("Could not create virtualenv, proceeding with add command");}if(t.start("Installing RapidKit"),r){let d=Ae(i||{});if(!d)throw new F("Test mode installation",new Error("No local RapidKit path configured. Set RAPIDKIT_DEV_PATH environment variable."));a.debug(`Installing from local path: ${d}`),t.text="Installing RapidKit from local path (test mode)",await execa("poetry",["add",d],{cwd:e});}else {t.text="Installing RapidKit from PyPI";let d=false,p=null;for(let u=1;u<=3;u++)try{await execa("poetry",["add","rapidkit-core"],{cwd:e,timeout:6e4*u}),d=true;break}catch(h){p=h,a.debug(`Poetry add attempt ${u} failed: ${h}`),u<3&&(t.text=`Retrying installation (attempt ${u+1}/3)`,await new Promise(x=>setTimeout(x,2e3)));}if(!d){let u=p?.stderr||p?.message||"Unknown error";throw a.debug(`All Poetry install attempts failed. Last error: ${u}`),u.includes("Could not find")||u.includes("No matching distribution")?new le:new F("Install rapidkit-core with Poetry",new Error(`Failed to install rapidkit-core after 3 attempts.
|
|
90
|
+
Error: ${u}
|
|
79
91
|
|
|
80
92
|
Possible solutions:
|
|
81
93
|
1. Check your internet connection
|
|
82
|
-
2. Try installing manually: cd ${
|
|
83
|
-
3. Use venv method instead: npx rapidkit ${
|
|
94
|
+
2. Try installing manually: cd ${v.basename(e)} && poetry add rapidkit-core
|
|
95
|
+
3. Use venv method instead: npx rapidkit ${v.basename(e)} --install-method=venv`))}}t.succeed("RapidKit installed in project virtualenv");try{let{checkRapidkitCoreAvailable:d}=await import('./pythonRapidkitExec-YIFUZLND.js');if(!await d()&&!r){t.start("Installing RapidKit globally with pipx for CLI access");let u=await je(t,n);try{await pe(u,["install","rapidkit-core"]),t.succeed("RapidKit installed globally");}catch(h){t.warn("Could not install globally (non-fatal, project virtualenv has RapidKit)"),a.debug(`pipx install failed: ${h}`);}}}catch(d){a.debug(`Global install check skipped: ${d}`);}}async function dt(e,o,t,r,i,n=false){t.start(`Checking Python ${o}`);let s=Ne();try{let{stdout:a}=await execa(s,["--version"]),l=a.match(/Python (\d+\.\d+)/)?.[1];if(l&&parseFloat(l)<parseFloat(o))throw new de(o,l);t.succeed(`Python ${l} found`);}catch(a){throw a instanceof de?a:new de(o)}t.start("Creating virtual environment");try{await execa(s,["-m","venv",".venv"],{cwd:e}),t.succeed("Virtual environment created");}catch(a){if(t.fail("Failed to create virtual environment"),(d=>typeof d=="object"&&d!==null&&"stdout"in d&&typeof d.stdout=="string")(a)&&a.stdout.includes("ensurepip is not")){let d=a.stdout.match(/apt install (python[\d.]+-venv)/),p=d?d[1]:"python3-venv";throw new F("Python venv module not available",new Error(`Virtual environment creation failed.
|
|
84
96
|
|
|
85
97
|
On Debian/Ubuntu systems, install the venv package:
|
|
86
|
-
sudo apt install ${
|
|
98
|
+
sudo apt install ${p}
|
|
87
99
|
|
|
88
100
|
Or use Poetry instead (recommended):
|
|
89
|
-
npx rapidkit ${
|
|
90
|
-
Error: ${
|
|
101
|
+
npx rapidkit ${v.basename(e)} --yes`))}throw new F("Virtual environment creation",a instanceof Error?a:new Error(String(a)))}t.start("Installing RapidKit");let c=v.join(e,".venv",process.platform==="win32"?"Scripts":"bin",process.platform==="win32"?"python.exe":"python");if(await execa(c,["-m","pip","install","--upgrade","pip"],{cwd:e}),r){let a$1=Ae(i||{});if(!a$1)throw new F("Test mode installation",new Error("No local RapidKit path configured. Set RAPIDKIT_DEV_PATH environment variable."));a.debug(`Installing from local path: ${a$1}`),t.text="Installing RapidKit from local path (test mode)",await execa(c,["-m","pip","install","-e",a$1],{cwd:e});}else {t.text="Installing RapidKit from PyPI";let a$1=false,l=null;for(let d=1;d<=3;d++)try{await execa(c,["-m","pip","install","rapidkit-core"],{cwd:e,timeout:6e4*d}),a$1=true;break}catch(p){l=p,a.debug(`pip install attempt ${d} failed: ${p}`),d<3&&(t.text=`Retrying installation (attempt ${d+1}/3)`,await new Promise(u=>setTimeout(u,2e3)));}if(!a$1){let d=l?.stderr||l?.message||"Unknown error";throw a.debug(`All pip install attempts failed. Last error: ${d}`),d.includes("Could not find")||d.includes("No matching distribution")?new le:new F("Install rapidkit-core with pip",new Error(`Failed to install rapidkit-core after 3 attempts.
|
|
102
|
+
Error: ${d}
|
|
91
103
|
|
|
92
104
|
Possible solutions:
|
|
93
105
|
1. Check your internet connection
|
|
94
|
-
2. Try installing manually: cd ${
|
|
95
|
-
3. Use Poetry instead: npx rapidkit ${
|
|
96
|
-
`,"utf-8");}async function
|
|
106
|
+
2. Try installing manually: cd ${v.basename(e)} && .venv/bin/python -m pip install rapidkit-core
|
|
107
|
+
3. Use Poetry instead: npx rapidkit ${v.basename(e)} --install-method=poetry`))}}t.succeed("RapidKit installed in project virtualenv");try{let{checkRapidkitCoreAvailable:a$1}=await import('./pythonRapidkitExec-YIFUZLND.js');if(!await a$1()&&!r){t.start("Installing RapidKit globally with pipx for CLI access");let d=await je(t,n);try{await pe(d,["install","rapidkit-core"]),t.succeed("RapidKit installed globally");}catch(p){t.warn("Could not install globally (non-fatal, project virtualenv has RapidKit)"),a.debug(`pipx install failed: ${p}`);}}}catch(a$1){a.debug(`Global install check skipped: ${a$1}`);}}async function Ut(e,o,t,r,i=false){let n=await je(o,i);if(o.start("Installing RapidKit globally with pipx"),t){let s=Ae(r||{});if(!s)throw new F("Test mode installation",new Error("No local RapidKit path configured. Set RAPIDKIT_DEV_PATH environment variable."));a.debug(`Installing from local path: ${s}`),o.text="Installing RapidKit from local path (test mode)",await pe(n,["install","-e",s]);}else {o.text="Installing RapidKit from PyPI";try{await pe(n,["install","rapidkit-core"]);}catch{throw new le}}o.succeed("RapidKit installed globally"),await R.outputFile(v.join(e,".rapidkit-global"),`RapidKit installed globally with pipx
|
|
108
|
+
`,"utf-8");}async function te(e,o){let{skipGit:t=false,testMode:r=false,userConfig:i={},yes:n=false,installMethod:s,pythonVersion:c="3.10"}=o||{},a=s||i.defaultInstallMethod||"poetry";await Mt(e,v.basename(e),a),await qt(e),await Lt(e,v.basename(e),a,c);let l=pt("Registering workspace").start();try{a==="poetry"?await Kt(e,c,l,r,i,n):a==="venv"?await dt(e,c,l,r,i):await Ut(e,l,r,i,n),await Ft(e,a),await Vt(e,a),l.succeed("Workspace registered");try{let{registerWorkspace:d}=await import('./workspace-LZZGJRGV.js');await d(e,v.basename(e));}catch{}if(!t){l.start("Initializing git repository");try{await execa("git",["init"],{cwd:e}),await execa("git",["add","."],{cwd:e}),await execa("git",["commit","-m","Initial commit: RapidKit workspace"],{cwd:e}),l.succeed("Git repository initialized");}catch{l.warn("Could not initialize git repository");}}}catch(d){throw l.fail("Failed to register workspace"),d}}async function Vt(e,o){let i=`# RapidKit Workspace
|
|
97
109
|
|
|
98
110
|
This directory contains a RapidKit development environment.
|
|
99
111
|
|
|
@@ -204,7 +216,7 @@ If you encounter issues:
|
|
|
204
216
|
2. Check RapidKit installation: \`rapidkit --version\`
|
|
205
217
|
3. Run diagnostics: \`rapidkit doctor\`
|
|
206
218
|
4. Visit RapidKit documentation or GitHub issues
|
|
207
|
-
`;await promises.writeFile(
|
|
219
|
+
`;await promises.writeFile(v.join(e,"README.md"),i,"utf-8");}async function or(e,o,t){let r=pt("Creating demo workspace").start();try{await R.ensureDir(e),r.succeed("Directory created"),r.start("Setting up demo kit generator");let i=JSON.stringify({name:`${o}-workspace`,version:"1.0.0",private:true,description:"RapidKit demo workspace",scripts:{generate:"node generate-demo.js"}},null,2);await promises.writeFile(v.join(e,"package.json"),i,"utf-8"),await promises.writeFile(v.join(e,"generate-demo.js"),`#!/usr/bin/env node
|
|
208
220
|
/**
|
|
209
221
|
* Demo Kit Generator - Create FastAPI demo projects
|
|
210
222
|
*
|
|
@@ -600,7 +612,7 @@ venv/
|
|
|
600
612
|
}
|
|
601
613
|
|
|
602
614
|
main().catch(console.error);
|
|
603
|
-
`,"utf-8");try{await execa("chmod",["+x",
|
|
615
|
+
`,"utf-8");try{await execa("chmod",["+x",v.join(e,"generate-demo.js")]);}catch{}let s=`# RapidKit Demo Workspace
|
|
604
616
|
|
|
605
617
|
Welcome to your RapidKit demo workspace! This environment lets you generate FastAPI demo projects using bundled RapidKit templates, without needing to install Python RapidKit.
|
|
606
618
|
|
|
@@ -687,7 +699,7 @@ ${o}/
|
|
|
687
699
|
---
|
|
688
700
|
|
|
689
701
|
**Generated with RapidKit** | [GitHub](https://github.com/getrapidkit/rapidkit-npm)
|
|
690
|
-
`;if(await promises.writeFile(
|
|
702
|
+
`;if(await promises.writeFile(v.join(e,"README.md"),s,"utf-8"),r.succeed("Demo workspace setup complete"),!t){r.start("Initializing git repository");try{await execa("git",["init"],{cwd:e}),await R.outputFile(v.join(e,".gitignore"),`# Dependencies
|
|
691
703
|
node_modules/
|
|
692
704
|
|
|
693
705
|
# Generated projects
|
|
@@ -700,19 +712,19 @@ __pycache__/
|
|
|
700
712
|
*.pyc
|
|
701
713
|
.venv/
|
|
702
714
|
.env
|
|
703
|
-
`,"utf-8"),await execa("git",["add","."],{cwd:e}),await execa("git",["commit","-m","Initial commit: Demo workspace"],{cwd:e}),
|
|
715
|
+
`,"utf-8"),await execa("git",["add","."],{cwd:e}),await execa("git",["commit","-m","Initial commit: Demo workspace"],{cwd:e}),r.succeed("Git repository initialized");}catch{r.warn("Could not initialize git repository");}}console.log(g.green(`
|
|
704
716
|
\u2728 Demo workspace created successfully!
|
|
705
717
|
`)),console.log(g.cyan("\u{1F4C2} Location:"),g.white(e)),console.log(g.cyan(`\u{1F680} Get started:
|
|
706
|
-
`)),console.log(g.white(` cd ${o}`)),console.log(g.white(" node generate-demo.js my-api")),console.log(g.white(" cd my-api")),console.log(g.white(" rapidkit init")),console.log(g.white(" rapidkit dev")),console.log(),console.log(g.yellow("\u{1F4A1} Note:"),"This is a demo workspace. For full RapidKit features:"),console.log(g.cyan(" pipx install rapidkit")),console.log();}catch(i){throw
|
|
718
|
+
`)),console.log(g.white(` cd ${o}`)),console.log(g.white(" node generate-demo.js my-api")),console.log(g.white(" cd my-api")),console.log(g.white(" rapidkit init")),console.log(g.white(" rapidkit dev")),console.log(),console.log(g.yellow("\u{1F4A1} Note:"),"This is a demo workspace. For full RapidKit features:"),console.log(g.cyan(" pipx install rapidkit")),console.log();}catch(i){throw r.fail("Failed to create demo workspace"),i}}async function rr(e,o,t,r){console.log(g.cyan(`
|
|
707
719
|
\u{1F50D} Dry-run mode - showing what would be created:
|
|
708
720
|
`)),console.log(g.white("\u{1F4C2} Project path:"),e),console.log(g.white("\u{1F4E6} Project type:"),t?"Demo workspace":"Full RapidKit environment"),t?(console.log(g.white(`
|
|
709
721
|
\u{1F4DD} Files to create:`)),console.log(g.gray(" - package.json")),console.log(g.gray(" - generate-demo.js (project generator)")),console.log(g.gray(" - README.md")),console.log(g.gray(" - .gitignore")),console.log(g.white(`
|
|
710
722
|
\u{1F3AF} Capabilities:`)),console.log(g.gray(" - Generate multiple FastAPI demo projects")),console.log(g.gray(" - No Python RapidKit installation required")),console.log(g.gray(" - Bundled templates included"))):(console.log(g.white(`
|
|
711
|
-
\u2699\uFE0F Configuration:`)),console.log(g.gray(` - Python version: ${
|
|
723
|
+
\u2699\uFE0F Configuration:`)),console.log(g.gray(` - Python version: ${r.pythonVersion||"3.10"}`)),console.log(g.gray(` - Install method: ${r.defaultInstallMethod||"poetry"}`)),console.log(g.gray(` - Git initialization: ${r.skipGit?"No":"Yes"}`)),console.log(g.white(`
|
|
712
724
|
\u{1F4DD} Files to create:`)),console.log(g.gray(" - pyproject.toml (Poetry) or .venv/ (venv)")),console.log(g.gray(" - README.md")),console.log(g.gray(" - .gitignore")),console.log(g.white(`
|
|
713
725
|
\u{1F3AF} Next steps after creation:`)),console.log(g.gray(" 1. Install RapidKit Python package")),console.log(g.gray(" 2. Create projects with rapidkit CLI")),console.log(g.gray(" 3. Add modules and customize"))),console.log(g.white(`
|
|
714
726
|
\u{1F4A1} To proceed with actual creation, run without --dry-run flag
|
|
715
|
-
`));}var
|
|
727
|
+
`));}var ar=fileURLToPath(import.meta.url),cr=v.dirname(ar);function dr(e=32){let o="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789",t=sr.randomBytes(e),r="";for(let i=0;i<e;i++)r+=o[t[i]%o.length];return r}async function Wt(e,o){let t=o.template||"fastapi",r=t==="fastapi",i=r?"FastAPI":"NestJS",n=pt(`Generating ${i} project...`).start();try{let s=v.resolve(cr,".."),c$1=o.kit_name||`${t}.standard`,a;c$1==="fastapi.ddd"?a="fastapi-ddd":c$1.startsWith("fastapi")?a="fastapi-standard":a="nestjs-standard";let l=v.join(s,"templates","kits",a),d=nr.configure(l,{autoescape:false,trimBlocks:true,lstripBlocks:true});d.addFilter("generate_secret",function(y,C=32){return dr(C)});let p={project_name:o.project_name,author:o.author||"RapidKit User",description:o.description||(r?"FastAPI service generated with RapidKit":"NestJS application generated with RapidKit"),app_version:o.app_version||"0.1.0",license:o.license||"MIT",package_manager:o.package_manager||"npm",node_version:o.node_version||"20.0.0",database_type:o.database_type||"postgresql",include_caching:o.include_caching||false,created_at:new Date().toISOString(),rapidkit_version:c()},u;r?u=["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"]:u=["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","eslint.config.cjs.j2",".env.example.j2","docker-compose.yml.j2","Dockerfile.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 y of u){let C=v.join(l,y);try{await promises.access(C);}catch{continue}let E=await promises.readFile(C,"utf-8"),q;try{q=d.renderString(E,p);}catch(st){throw console.error(`Failed to render template: ${y}`),st}let V=y.replace(/\.j2$/,""),Ie=v.join(e,V);await promises.mkdir(v.dirname(Ie),{recursive:true}),await promises.writeFile(Ie,q),(V.endsWith(".rapidkit/rapidkit")||V.endsWith(".rapidkit/cli.py")||V.endsWith(".rapidkit/activate")||V==="rapidkit")&&await promises.chmod(Ie,493);}if(r){let y=v.join(l,".rapidkit","context.json"),C=v.join(e,".rapidkit","context.json");try{await promises.mkdir(v.join(e,".rapidkit"),{recursive:true}),await promises.copyFile(y,C);}catch{await promises.mkdir(v.join(e,".rapidkit"),{recursive:true});let q=o.engine||"pip";await promises.writeFile(C,JSON.stringify({engine:q,created_by:"rapidkit-npm-fallback"},null,2));}}let h=r?`# Python
|
|
716
728
|
__pycache__/
|
|
717
729
|
*.py[cod]
|
|
718
730
|
*$py.class
|
|
@@ -780,12 +792,12 @@ Thumbs.db
|
|
|
780
792
|
|
|
781
793
|
# Coverage
|
|
782
794
|
coverage/
|
|
783
|
-
`;if(await promises.writeFile(
|
|
795
|
+
`;if(await promises.writeFile(v.join(e,".gitignore"),h),n.succeed(`${i} project generated!`),!o.skipGit){let y=pt("Initializing git repository...").start();try{await execa("git",["init"],{cwd:e}),await execa("git",["add","."],{cwd:e}),await execa("git",["commit","-m",`Initial commit: ${i} project via RapidKit`],{cwd:e}),y.succeed("Git repository initialized");}catch{y.warn("Could not initialize git repository");}}if(!r&&!o.skipInstall){let y=o.package_manager||"npm",C=pt(`Installing dependencies with ${y}...`).start();try{await execa(y,y==="yarn"?["install"]:y==="pnpm"?["install"]:["install"],{cwd:e}),C.succeed("Dependencies installed");}catch{C.warn(`Could not install dependencies. Run '${y} install' manually.`);}}let x=v.basename(e);console.log(`
|
|
784
796
|
${g.yellow("\u26A0\uFE0F Limited offline mode:")} This project was created using basic templates.
|
|
785
797
|
${g.gray("For full kit features, install Python 3.10+ and rapidkit-core:")}
|
|
786
798
|
${g.cyan(" sudo apt install python3 python3-pip python3-venv")}
|
|
787
799
|
${g.cyan(" pip install rapidkit-core")}
|
|
788
|
-
`),console.log(
|
|
800
|
+
`),console.log(r?`
|
|
789
801
|
${g.green("\u2728 FastAPI project created successfully!")}
|
|
790
802
|
|
|
791
803
|
${g.bold("\u{1F4C2} Project structure:")}
|
|
@@ -801,7 +813,7 @@ ${e}/
|
|
|
801
813
|
\u2514\u2500\u2500 README.md
|
|
802
814
|
|
|
803
815
|
${g.bold("\u{1F680} Get started:")}
|
|
804
|
-
${g.cyan(`cd ${
|
|
816
|
+
${g.cyan(`cd ${x}`)}
|
|
805
817
|
${g.cyan("npx rapidkit init")} ${g.gray("# Install dependencies")}
|
|
806
818
|
${g.cyan("npx rapidkit dev")} ${g.gray("# Start dev server")}
|
|
807
819
|
|
|
@@ -831,7 +843,7 @@ ${e}/
|
|
|
831
843
|
\u2514\u2500\u2500 README.md
|
|
832
844
|
|
|
833
845
|
${g.bold("\u{1F680} Get started:")}
|
|
834
|
-
${g.cyan(`cd ${
|
|
846
|
+
${g.cyan(`cd ${x}`)}
|
|
835
847
|
${g.cyan("npx rapidkit init")} ${g.gray("# Install dependencies")}
|
|
836
848
|
${g.cyan("cp .env.example .env")}
|
|
837
849
|
${g.cyan("npx rapidkit dev")} ${g.gray("# Start dev server")}
|
|
@@ -852,7 +864,7 @@ ${g.bold("\u{1F310} API endpoints:")}
|
|
|
852
864
|
|
|
853
865
|
${g.gray("Alternative: npm run start:dev, ./rapidkit dev")}
|
|
854
866
|
${g.gray("\u{1F4A1} Tip: Install globally (npm i -g rapidkit) to use without npx")}
|
|
855
|
-
`);}catch(
|
|
867
|
+
`);}catch(s){throw n.fail(`Failed to generate ${i} project`),s}}function Bt(e){return e.split(/[-_\s]+/).map(o=>o.charAt(0).toUpperCase()+o.slice(1)).join("")}async function pr(e,o){await promises.mkdir(v.dirname(e),{recursive:true}),await promises.writeFile(e,o,"utf8");}function ur(e){return `package main
|
|
856
868
|
|
|
857
869
|
import (
|
|
858
870
|
"fmt"
|
|
@@ -906,7 +918,7 @@ func main() {
|
|
|
906
918
|
}
|
|
907
919
|
slog.Info("server stopped")
|
|
908
920
|
}
|
|
909
|
-
`}function
|
|
921
|
+
`}function gr(e){return `module ${e.module_path}
|
|
910
922
|
|
|
911
923
|
go ${e.go_version}
|
|
912
924
|
|
|
@@ -940,7 +952,7 @@ require (
|
|
|
940
952
|
golang.org/x/tools v0.21.0 // indirect
|
|
941
953
|
gopkg.in/yaml.v2 v2.4.0 // indirect
|
|
942
954
|
)
|
|
943
|
-
`}function
|
|
955
|
+
`}function mr(e){return `package config
|
|
944
956
|
|
|
945
957
|
import (
|
|
946
958
|
"log/slog"
|
|
@@ -993,7 +1005,7 @@ func getEnv(key, fallback string) string {
|
|
|
993
1005
|
}
|
|
994
1006
|
return fallback
|
|
995
1007
|
}
|
|
996
|
-
`}function
|
|
1008
|
+
`}function fr(e){return `package server
|
|
997
1009
|
|
|
998
1010
|
import (
|
|
999
1011
|
"net/http"
|
|
@@ -1059,7 +1071,7 @@ func NewApp(cfg *config.Config) *fiber.App {
|
|
|
1059
1071
|
|
|
1060
1072
|
return app
|
|
1061
1073
|
}
|
|
1062
|
-
`}function
|
|
1074
|
+
`}function hr(){return `package handlers
|
|
1063
1075
|
|
|
1064
1076
|
import (
|
|
1065
1077
|
"time"
|
|
@@ -1097,7 +1109,7 @@ func Readiness(c *fiber.Ctx) error {
|
|
|
1097
1109
|
"time": time.Now().UTC().Format(time.RFC3339),
|
|
1098
1110
|
})
|
|
1099
1111
|
}
|
|
1100
|
-
`}function
|
|
1112
|
+
`}function wr(e){return `package handlers_test
|
|
1101
1113
|
|
|
1102
1114
|
import (
|
|
1103
1115
|
"encoding/json"
|
|
@@ -1146,7 +1158,7 @@ func TestReadiness(t *testing.T) {
|
|
|
1146
1158
|
t.Fatalf("expected 200, got %d: %s", resp.StatusCode, resp.Status)
|
|
1147
1159
|
}
|
|
1148
1160
|
}
|
|
1149
|
-
`}function
|
|
1161
|
+
`}function yr(){return `# \u2500\u2500 Build stage \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500
|
|
1150
1162
|
FROM golang:1.24-alpine AS builder
|
|
1151
1163
|
|
|
1152
1164
|
# Build-time version injection
|
|
@@ -1175,7 +1187,7 @@ EXPOSE 3000
|
|
|
1175
1187
|
HEALTHCHECK --interval=30s --timeout=3s --start-period=5s --retries=3 \\
|
|
1176
1188
|
CMD wget -qO- http://localhost:3000/api/v1/health/live || exit 1
|
|
1177
1189
|
ENTRYPOINT ["/server"]
|
|
1178
|
-
`}function
|
|
1190
|
+
`}function vr(e){return `version: "3.9"
|
|
1179
1191
|
|
|
1180
1192
|
services:
|
|
1181
1193
|
api:
|
|
@@ -1190,7 +1202,7 @@ services:
|
|
|
1190
1202
|
CORS_ALLOW_ORIGINS: "*"
|
|
1191
1203
|
RATE_LIMIT_RPS: "100"
|
|
1192
1204
|
restart: unless-stopped
|
|
1193
|
-
`}function
|
|
1205
|
+
`}function br(e){return `.PHONY: dev run build test cover lint fmt tidy docs docker-up docker-down
|
|
1194
1206
|
|
|
1195
1207
|
# Build-time metadata
|
|
1196
1208
|
VERSION ?= $(shell git describe --tags --always --dirty 2>/dev/null || echo "dev")
|
|
@@ -1236,7 +1248,7 @@ docker-up:
|
|
|
1236
1248
|
|
|
1237
1249
|
docker-down:
|
|
1238
1250
|
docker compose down
|
|
1239
|
-
`}function
|
|
1251
|
+
`}function kr(e){return `# Application
|
|
1240
1252
|
PORT=${e.port}
|
|
1241
1253
|
APP_ENV=development
|
|
1242
1254
|
LOG_LEVEL=debug
|
|
@@ -1246,7 +1258,7 @@ CORS_ALLOW_ORIGINS=*
|
|
|
1246
1258
|
|
|
1247
1259
|
# Rate limiting \u2014 max requests per IP per second
|
|
1248
1260
|
RATE_LIMIT_RPS=100
|
|
1249
|
-
`}function
|
|
1261
|
+
`}function Rr(){return `# Binaries
|
|
1250
1262
|
bin/
|
|
1251
1263
|
*.exe
|
|
1252
1264
|
*.exe~
|
|
@@ -1286,7 +1298,7 @@ docs/docs.go
|
|
|
1286
1298
|
# OS
|
|
1287
1299
|
.DS_Store
|
|
1288
1300
|
Thumbs.db
|
|
1289
|
-
`}function
|
|
1301
|
+
`}function xr(e){return `name: CI
|
|
1290
1302
|
|
|
1291
1303
|
on:
|
|
1292
1304
|
push:
|
|
@@ -1340,7 +1352,7 @@ jobs:
|
|
|
1340
1352
|
uses: golangci/golangci-lint-action@v6
|
|
1341
1353
|
with:
|
|
1342
1354
|
version: latest
|
|
1343
|
-
`}function
|
|
1355
|
+
`}function Cr(e){return `# ${Bt(e.project_name)}
|
|
1344
1356
|
|
|
1345
1357
|
> ${e.description}
|
|
1346
1358
|
|
|
@@ -1455,7 +1467,7 @@ ${e.project_name}/
|
|
|
1455
1467
|
## License
|
|
1456
1468
|
|
|
1457
1469
|
${e.app_version} \xB7 ${e.author}
|
|
1458
|
-
`}function
|
|
1470
|
+
`}function Sr(){return `package middleware
|
|
1459
1471
|
|
|
1460
1472
|
import (
|
|
1461
1473
|
"crypto/rand"
|
|
@@ -1508,7 +1520,7 @@ func newID() string {
|
|
|
1508
1520
|
}
|
|
1509
1521
|
return hex.EncodeToString(b)
|
|
1510
1522
|
}
|
|
1511
|
-
`}function
|
|
1523
|
+
`}function _r(e){return `package middleware_test
|
|
1512
1524
|
|
|
1513
1525
|
import (
|
|
1514
1526
|
"net/http"
|
|
@@ -1561,7 +1573,7 @@ func TestRequestID_IsReused(t *testing.T) {
|
|
|
1561
1573
|
t.Fatalf("expected X-Request-ID to be reused, got %q", id)
|
|
1562
1574
|
}
|
|
1563
1575
|
}
|
|
1564
|
-
`}function
|
|
1576
|
+
`}function Pr(){return `// Package apierr provides a consistent JSON error envelope for all API responses.
|
|
1565
1577
|
//
|
|
1566
1578
|
// Every error response looks like:
|
|
1567
1579
|
//
|
|
@@ -1625,7 +1637,7 @@ func InternalError(c *fiber.Ctx, _ error) error {
|
|
|
1625
1637
|
func TooManyRequests(c *fiber.Ctx, msg string) error {
|
|
1626
1638
|
return reply(c, http.StatusTooManyRequests, msg, "TOO_MANY_REQUESTS")
|
|
1627
1639
|
}
|
|
1628
|
-
`}function
|
|
1640
|
+
`}function Ir(e){return `package apierr_test
|
|
1629
1641
|
|
|
1630
1642
|
import (
|
|
1631
1643
|
"encoding/json"
|
|
@@ -1757,11 +1769,11 @@ func TestTooManyRequests(t *testing.T) {
|
|
|
1757
1769
|
t.Fatalf("expected TOO_MANY_REQUESTS, got %q", body.Code)
|
|
1758
1770
|
}
|
|
1759
1771
|
}
|
|
1760
|
-
`}function
|
|
1772
|
+
`}function Er(e){return `// Package docs provides the swaggo-generated OpenAPI specification.
|
|
1761
1773
|
//
|
|
1762
1774
|
// Run \`make docs\` to regenerate after changing handler annotations.
|
|
1763
1775
|
//
|
|
1764
|
-
// @title ${
|
|
1776
|
+
// @title ${Bt(e.project_name)} API
|
|
1765
1777
|
// @version ${e.app_version}
|
|
1766
1778
|
// @description ${e.description}
|
|
1767
1779
|
// @host localhost:${e.port}
|
|
@@ -1771,7 +1783,7 @@ func TestTooManyRequests(t *testing.T) {
|
|
|
1771
1783
|
// @contact.name ${e.author}
|
|
1772
1784
|
// @license.name MIT
|
|
1773
1785
|
package docs
|
|
1774
|
-
`}function
|
|
1786
|
+
`}function Tr(e){return `package handlers
|
|
1775
1787
|
|
|
1776
1788
|
import (
|
|
1777
1789
|
"net/http"
|
|
@@ -1813,7 +1825,7 @@ func EchoParams(c *fiber.Ctx) error {
|
|
|
1813
1825
|
RequestID: rid,
|
|
1814
1826
|
})
|
|
1815
1827
|
}
|
|
1816
|
-
`}function
|
|
1828
|
+
`}function Ar(e){return `package handlers_test
|
|
1817
1829
|
|
|
1818
1830
|
import (
|
|
1819
1831
|
"encoding/json"
|
|
@@ -1881,7 +1893,7 @@ func TestEchoParams_EmptyName(t *testing.T) {
|
|
|
1881
1893
|
t.Fatalf("expected code=BAD_REQUEST, got %v", body["code"])
|
|
1882
1894
|
}
|
|
1883
1895
|
}
|
|
1884
|
-
`}function
|
|
1896
|
+
`}function Or(e){return `package config_test
|
|
1885
1897
|
|
|
1886
1898
|
import (
|
|
1887
1899
|
"log/slog"
|
|
@@ -1949,7 +1961,7 @@ func TestLoad_Defaults(t *testing.T) {
|
|
|
1949
1961
|
t.Errorf("expected default LogLevel=debug (development env), got %q", cfg.LogLevel)
|
|
1950
1962
|
}
|
|
1951
1963
|
}
|
|
1952
|
-
`}function
|
|
1964
|
+
`}function Nr(){return `package middleware
|
|
1953
1965
|
|
|
1954
1966
|
import (
|
|
1955
1967
|
"os"
|
|
@@ -1977,7 +1989,7 @@ func CORS() fiber.Handler {
|
|
|
1977
1989
|
MaxAge: 600,
|
|
1978
1990
|
})
|
|
1979
1991
|
}
|
|
1980
|
-
`}function
|
|
1992
|
+
`}function jr(e){return `package middleware_test
|
|
1981
1993
|
|
|
1982
1994
|
import (
|
|
1983
1995
|
"net/http"
|
|
@@ -2049,7 +2061,7 @@ func TestCORS_Default_Origin(t *testing.T) {
|
|
|
2049
2061
|
t.Fatal("expected CORS header when origins defaulting to *")
|
|
2050
2062
|
}
|
|
2051
2063
|
}
|
|
2052
|
-
`}function
|
|
2064
|
+
`}function Gr(e){return `package server_test
|
|
2053
2065
|
|
|
2054
2066
|
import (
|
|
2055
2067
|
"encoding/json"
|
|
@@ -2138,7 +2150,7 @@ func TestServer_Docs_Redirect(t *testing.T) {
|
|
|
2138
2150
|
t.Fatalf("expected Location=/docs/index.html, got %q", loc)
|
|
2139
2151
|
}
|
|
2140
2152
|
}
|
|
2141
|
-
`}function
|
|
2153
|
+
`}function $r(e){return `package middleware
|
|
2142
2154
|
|
|
2143
2155
|
import (
|
|
2144
2156
|
"os"
|
|
@@ -2171,7 +2183,7 @@ func RateLimit() fiber.Handler {
|
|
|
2171
2183
|
},
|
|
2172
2184
|
})
|
|
2173
2185
|
}
|
|
2174
|
-
`}function
|
|
2186
|
+
`}function Dr(e){return `package middleware_test
|
|
2175
2187
|
|
|
2176
2188
|
import (
|
|
2177
2189
|
"net/http"
|
|
@@ -2247,7 +2259,7 @@ func TestRateLimit_InvalidRPS(t *testing.T) {
|
|
|
2247
2259
|
t.Fatalf("expected 200 with invalid RPS env, got %d", resp.StatusCode)
|
|
2248
2260
|
}
|
|
2249
2261
|
}
|
|
2250
|
-
`}function
|
|
2262
|
+
`}function Mr(e){return `# Air \u2014 live reload for Go projects
|
|
2251
2263
|
# https://github.com/air-verse/air
|
|
2252
2264
|
root = "."
|
|
2253
2265
|
tmp_dir = "tmp"
|
|
@@ -2271,7 +2283,7 @@ tmp_dir = "tmp"
|
|
|
2271
2283
|
|
|
2272
2284
|
[log]
|
|
2273
2285
|
time = false
|
|
2274
|
-
`}function
|
|
2286
|
+
`}function qr(e){return `run:
|
|
2275
2287
|
timeout: 5m
|
|
2276
2288
|
|
|
2277
2289
|
linters:
|
|
@@ -2317,7 +2329,7 @@ issues:
|
|
|
2317
2329
|
linters:
|
|
2318
2330
|
- errcheck
|
|
2319
2331
|
- wrapcheck
|
|
2320
|
-
`}function
|
|
2332
|
+
`}function Lr(){return JSON.stringify({engine:"npm",runtime:"go"},null,2)}function Fr(e){return `#!/usr/bin/env sh
|
|
2321
2333
|
# RapidKit Go/Fiber project launcher \u2014 generated by RapidKit CLI
|
|
2322
2334
|
# https://getrapidkit.com
|
|
2323
2335
|
|
|
@@ -2396,7 +2408,7 @@ case "$CMD" in
|
|
|
2396
2408
|
exit 1
|
|
2397
2409
|
;;
|
|
2398
2410
|
esac
|
|
2399
|
-
`}function
|
|
2411
|
+
`}function Hr(e){return `@echo off
|
|
2400
2412
|
rem RapidKit Go/Fiber project launcher \u2014 Windows
|
|
2401
2413
|
set CMD=%1
|
|
2402
2414
|
if "%CMD%"=="" goto usage
|
|
@@ -2421,8 +2433,8 @@ if "%CMD%"=="start" ( bin\\${e.project_name}.exe %* & exit /b %ERRORLEVEL% )
|
|
|
2421
2433
|
:usage
|
|
2422
2434
|
echo Available: init, dev, start, build, docs, test, lint, format
|
|
2423
2435
|
exit /b 1
|
|
2424
|
-
`}function
|
|
2425
|
-
`));}let i=
|
|
2436
|
+
`}function Kr(e,o){return JSON.stringify({kit_name:"gofiber.standard",runtime:"go",module_support:false,project_name:e.project_name,module_path:e.module_path,app_version:e.app_version,created_by:"rapidkit-npm",rapidkit_version:o,created_at:new Date().toISOString()},null,2)}async function gt(e,o){let t={project_name:o.project_name,module_path:o.module_path||o.project_name,author:o.author||"RapidKit User",description:o.description||`Go/Fiber REST API \u2014 ${o.project_name}`,go_version:o.go_version||"1.24",app_version:o.app_version||"0.1.0",port:o.port||"3000",skipGit:o.skipGit??false},r=c();try{await execa("go",["version"],{timeout:3e3});}catch{console.log(g.yellow("\n\u26A0 Go not found in PATH \u2014 project will be scaffolded, but `go mod tidy` requires Go 1.21+")),console.log(g.gray(` Install: https://go.dev/dl/
|
|
2437
|
+
`));}let i=pt(`Generating Go/Fiber project: ${t.project_name}\u2026`).start();try{let n=(a,l)=>pr(v.join(e,a),l),s=v.join(e,"rapidkit"),c=v.join(e,"rapidkit.cmd");await Promise.all([n("cmd/server/main.go",ur(t)),n("go.mod",gr(t)),n("internal/config/config.go",mr(t)),n("internal/server/server.go",fr(t)),n("internal/middleware/requestid.go",Sr()),n("internal/middleware/requestid_test.go",_r(t)),n("internal/apierr/apierr.go",Pr()),n("internal/apierr/apierr_test.go",Ir(t)),n("internal/handlers/health.go",hr()),n("internal/handlers/health_test.go",wr(t)),n("internal/handlers/example.go",Tr(t)),n("internal/handlers/example_test.go",Ar(t)),n("internal/config/config_test.go",Or(t)),n("internal/middleware/cors.go",Nr()),n("internal/middleware/cors_test.go",jr(t)),n("internal/middleware/ratelimit.go",$r(t)),n("internal/middleware/ratelimit_test.go",Dr(t)),n("internal/server/server_test.go",Gr(t)),n("docs/doc.go",Er(t)),n(".air.toml",Mr(t)),n("Dockerfile",yr()),n("docker-compose.yml",vr(t)),n("Makefile",br(t)),n(".golangci.yml",qr(t.module_path)),n(".env.example",kr(t)),n(".gitignore",Rr()),n(".github/workflows/ci.yml",xr(t)),n("README.md",Cr(t)),n(".rapidkit/project.json",Kr(t,r)),n(".rapidkit/context.json",Lr()),n("rapidkit",Fr(t)),n("rapidkit.cmd",Hr(t))]),await promises.chmod(s,493),await promises.chmod(c,493),i.succeed(g.green(`Project created at ${e}`));try{i.start("Fetching Go dependencies\u2026"),await execa("go",["mod","tidy"],{cwd:e,timeout:12e4}),i.succeed(g.gray("\u2713 go mod tidy completed"));}catch{i.warn(g.yellow("\u26A0 go mod tidy failed \u2014 run manually: go mod tidy"));}if(!t.skipGit)try{await execa("git",["init"],{cwd:e}),await execa("git",["add","-A"],{cwd:e}),await execa("git",["commit","-m","chore: initial scaffold (rapidkit gofiber.standard)"],{cwd:e}),console.log(g.gray("\u2713 git repository initialized"));}catch{console.log(g.gray("\u26A0 git init skipped (git not found or error)"));}console.log(""),console.log(g.bold("\u2705 Go/Fiber project ready!")),console.log(""),console.log(g.cyan("Next steps:")),console.log(g.white(` cd ${t.project_name}`)),console.log(g.white(" make run # start dev server")),console.log(g.white(" make test # run tests")),console.log(""),console.log(g.gray("Server will listen on port "+t.port)),console.log(g.gray(" http://localhost:"+t.port+"/api/v1/health/live")),console.log(g.gray(" http://localhost:"+t.port+"/api/v1/health/ready")),console.log(""),console.log(g.yellow("\u2139 RapidKit modules are not available for Go projects (module system uses Python/pip).")),console.log("");}catch(n){throw i.fail(g.red("Failed to generate Go/Fiber project")),n}}function Jt(e){return e.split(/[-_\s]+/).map(o=>o.charAt(0).toUpperCase()+o.slice(1)).join("")}async function Vr(e,o){await promises.mkdir(v.dirname(e),{recursive:true}),await promises.writeFile(e,o,"utf8");}function Wr(e){return `package main
|
|
2426
2438
|
|
|
2427
2439
|
import (
|
|
2428
2440
|
"context"
|
|
@@ -2489,7 +2501,7 @@ func main() {
|
|
|
2489
2501
|
}
|
|
2490
2502
|
slog.Info("server stopped")
|
|
2491
2503
|
}
|
|
2492
|
-
`}function
|
|
2504
|
+
`}function Br(e){return `module ${e.module_path}
|
|
2493
2505
|
|
|
2494
2506
|
go ${e.go_version}
|
|
2495
2507
|
|
|
@@ -2538,7 +2550,7 @@ require (
|
|
|
2538
2550
|
gopkg.in/yaml.v2 v2.4.0 // indirect
|
|
2539
2551
|
gopkg.in/yaml.v3 v3.0.1 // indirect
|
|
2540
2552
|
)
|
|
2541
|
-
`}function
|
|
2553
|
+
`}function Jr(e){return `package config
|
|
2542
2554
|
|
|
2543
2555
|
import (
|
|
2544
2556
|
"log/slog"
|
|
@@ -2593,7 +2605,7 @@ func getEnv(key, fallback string) string {
|
|
|
2593
2605
|
}
|
|
2594
2606
|
return fallback
|
|
2595
2607
|
}
|
|
2596
|
-
`}function
|
|
2608
|
+
`}function zr(e){return `package server
|
|
2597
2609
|
|
|
2598
2610
|
import (
|
|
2599
2611
|
"net/http"
|
|
@@ -2645,7 +2657,7 @@ func NewRouter(cfg *config.Config) *gin.Engine {
|
|
|
2645
2657
|
|
|
2646
2658
|
return r
|
|
2647
2659
|
}
|
|
2648
|
-
`}function
|
|
2660
|
+
`}function Yr(){return `package handlers
|
|
2649
2661
|
|
|
2650
2662
|
import (
|
|
2651
2663
|
"net/http"
|
|
@@ -2684,7 +2696,7 @@ func Readiness(c *gin.Context) {
|
|
|
2684
2696
|
"time": time.Now().UTC().Format(time.RFC3339),
|
|
2685
2697
|
})
|
|
2686
2698
|
}
|
|
2687
|
-
`}function
|
|
2699
|
+
`}function Qr(e){return `package handlers_test
|
|
2688
2700
|
|
|
2689
2701
|
import (
|
|
2690
2702
|
"encoding/json"
|
|
@@ -2729,7 +2741,7 @@ func TestReadiness(t *testing.T) {
|
|
|
2729
2741
|
t.Fatalf("expected 200, got %d: %s", w.Code, w.Body.String())
|
|
2730
2742
|
}
|
|
2731
2743
|
}
|
|
2732
|
-
`}function
|
|
2744
|
+
`}function Xr(){return `# \u2500\u2500 Build stage \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500
|
|
2733
2745
|
FROM golang:1.24-alpine AS builder
|
|
2734
2746
|
|
|
2735
2747
|
# Build-time version injection
|
|
@@ -2758,7 +2770,7 @@ EXPOSE 8080
|
|
|
2758
2770
|
HEALTHCHECK --interval=30s --timeout=3s --start-period=5s --retries=3 \\
|
|
2759
2771
|
CMD wget -qO- http://localhost:8080/api/v1/health/live || exit 1
|
|
2760
2772
|
ENTRYPOINT ["/server"]
|
|
2761
|
-
`}function
|
|
2773
|
+
`}function Zr(e){return `version: "3.9"
|
|
2762
2774
|
|
|
2763
2775
|
services:
|
|
2764
2776
|
api:
|
|
@@ -2774,7 +2786,7 @@ services:
|
|
|
2774
2786
|
CORS_ALLOW_ORIGINS: "*"
|
|
2775
2787
|
RATE_LIMIT_RPS: "100"
|
|
2776
2788
|
restart: unless-stopped
|
|
2777
|
-
`}function
|
|
2789
|
+
`}function en(e){return `.PHONY: dev run build test cover lint fmt tidy docs docker-up docker-down
|
|
2778
2790
|
|
|
2779
2791
|
# Build-time metadata
|
|
2780
2792
|
VERSION ?= $(shell git describe --tags --always --dirty 2>/dev/null || echo "dev")
|
|
@@ -2828,7 +2840,7 @@ docker-up:
|
|
|
2828
2840
|
|
|
2829
2841
|
docker-down:
|
|
2830
2842
|
docker compose down
|
|
2831
|
-
`}function
|
|
2843
|
+
`}function tn(e){return `# Application
|
|
2832
2844
|
PORT=${e.port}
|
|
2833
2845
|
APP_ENV=development
|
|
2834
2846
|
GIN_MODE=debug
|
|
@@ -2839,7 +2851,7 @@ CORS_ALLOW_ORIGINS=*
|
|
|
2839
2851
|
|
|
2840
2852
|
# Rate limiting \u2014 max requests per IP per second
|
|
2841
2853
|
RATE_LIMIT_RPS=100
|
|
2842
|
-
`}function
|
|
2854
|
+
`}function on(){return `# Binaries
|
|
2843
2855
|
bin/
|
|
2844
2856
|
*.exe
|
|
2845
2857
|
*.exe~
|
|
@@ -2879,7 +2891,7 @@ docs/docs.go
|
|
|
2879
2891
|
# OS
|
|
2880
2892
|
.DS_Store
|
|
2881
2893
|
Thumbs.db
|
|
2882
|
-
`}function
|
|
2894
|
+
`}function rn(e){return `name: CI
|
|
2883
2895
|
|
|
2884
2896
|
on:
|
|
2885
2897
|
push:
|
|
@@ -2933,7 +2945,7 @@ jobs:
|
|
|
2933
2945
|
uses: golangci/golangci-lint-action@v6
|
|
2934
2946
|
with:
|
|
2935
2947
|
version: latest
|
|
2936
|
-
`}function
|
|
2948
|
+
`}function nn(e){return `# ${Jt(e.project_name)}
|
|
2937
2949
|
|
|
2938
2950
|
> ${e.description}
|
|
2939
2951
|
|
|
@@ -3049,7 +3061,7 @@ ${e.project_name}/
|
|
|
3049
3061
|
## License
|
|
3050
3062
|
|
|
3051
3063
|
${e.app_version} \xB7 ${e.author}
|
|
3052
|
-
`}function
|
|
3064
|
+
`}function sn(){return `package middleware
|
|
3053
3065
|
|
|
3054
3066
|
import (
|
|
3055
3067
|
"crypto/rand"
|
|
@@ -3101,7 +3113,7 @@ func newID() string {
|
|
|
3101
3113
|
}
|
|
3102
3114
|
return hex.EncodeToString(b)
|
|
3103
3115
|
}
|
|
3104
|
-
`}function
|
|
3116
|
+
`}function an(e){return `package middleware_test
|
|
3105
3117
|
|
|
3106
3118
|
import (
|
|
3107
3119
|
"net/http"
|
|
@@ -3150,7 +3162,7 @@ func TestRequestID_IsReused(t *testing.T) {
|
|
|
3150
3162
|
t.Fatalf("expected X-Request-ID to be reused, got %q", id)
|
|
3151
3163
|
}
|
|
3152
3164
|
}
|
|
3153
|
-
`}function
|
|
3165
|
+
`}function cn(){return `// Package apierr provides a consistent JSON error envelope for all API responses.
|
|
3154
3166
|
//
|
|
3155
3167
|
// Every error response looks like:
|
|
3156
3168
|
//
|
|
@@ -3213,7 +3225,7 @@ func InternalError(c *gin.Context, _ error) {
|
|
|
3213
3225
|
func TooManyRequests(c *gin.Context) {
|
|
3214
3226
|
reply(c, http.StatusTooManyRequests, "rate limit exceeded", "TOO_MANY_REQUESTS")
|
|
3215
3227
|
}
|
|
3216
|
-
`}function
|
|
3228
|
+
`}function dn(e){return `package apierr_test
|
|
3217
3229
|
|
|
3218
3230
|
import (
|
|
3219
3231
|
"encoding/json"
|
|
@@ -3339,11 +3351,11 @@ func TestTooManyRequests(t *testing.T) {
|
|
|
3339
3351
|
t.Fatalf("expected TOO_MANY_REQUESTS, got %q", body.Code)
|
|
3340
3352
|
}
|
|
3341
3353
|
}
|
|
3342
|
-
`}function
|
|
3354
|
+
`}function ln(e){return `// Package docs provides the swaggo-generated OpenAPI specification.
|
|
3343
3355
|
//
|
|
3344
3356
|
// Run \`make docs\` to regenerate after changing handler annotations.
|
|
3345
3357
|
//
|
|
3346
|
-
// @title ${
|
|
3358
|
+
// @title ${Jt(e.project_name)} API
|
|
3347
3359
|
// @version ${e.app_version}
|
|
3348
3360
|
// @description ${e.description}
|
|
3349
3361
|
// @host localhost:${e.port}
|
|
@@ -3353,7 +3365,7 @@ func TestTooManyRequests(t *testing.T) {
|
|
|
3353
3365
|
// @contact.name ${e.author}
|
|
3354
3366
|
// @license.name MIT
|
|
3355
3367
|
package docs
|
|
3356
|
-
`}function
|
|
3368
|
+
`}function pn(e){return `package handlers
|
|
3357
3369
|
|
|
3358
3370
|
import (
|
|
3359
3371
|
"net/http"
|
|
@@ -3395,7 +3407,7 @@ func EchoParams(c *gin.Context) {
|
|
|
3395
3407
|
RequestID: c.GetString("X-Request-ID"),
|
|
3396
3408
|
})
|
|
3397
3409
|
}
|
|
3398
|
-
`}function
|
|
3410
|
+
`}function un(e){return `package handlers_test
|
|
3399
3411
|
|
|
3400
3412
|
import (
|
|
3401
3413
|
"encoding/json"
|
|
@@ -3460,7 +3472,7 @@ func TestEchoParams_EmptyName(t *testing.T) {
|
|
|
3460
3472
|
t.Fatalf("expected code=BAD_REQUEST, got %v", body["code"])
|
|
3461
3473
|
}
|
|
3462
3474
|
}
|
|
3463
|
-
`}function
|
|
3475
|
+
`}function gn(e){return `package config_test
|
|
3464
3476
|
|
|
3465
3477
|
import (
|
|
3466
3478
|
"log/slog"
|
|
@@ -3536,7 +3548,7 @@ func TestLoad_Defaults(t *testing.T) {
|
|
|
3536
3548
|
t.Errorf("expected default GinMode=debug, got %q", cfg.GinMode)
|
|
3537
3549
|
}
|
|
3538
3550
|
}
|
|
3539
|
-
`}function
|
|
3551
|
+
`}function mn(){return `package middleware
|
|
3540
3552
|
|
|
3541
3553
|
import (
|
|
3542
3554
|
"net/http"
|
|
@@ -3584,7 +3596,7 @@ func CORS() gin.HandlerFunc {
|
|
|
3584
3596
|
c.Next()
|
|
3585
3597
|
}
|
|
3586
3598
|
}
|
|
3587
|
-
`}function
|
|
3599
|
+
`}function fn(e){return `package middleware_test
|
|
3588
3600
|
|
|
3589
3601
|
import (
|
|
3590
3602
|
"net/http"
|
|
@@ -3670,7 +3682,7 @@ func TestCORS_Default_Origin(t *testing.T) {
|
|
|
3670
3682
|
t.Fatal("expected CORS header when CORS_ALLOW_ORIGINS defaults to *")
|
|
3671
3683
|
}
|
|
3672
3684
|
}
|
|
3673
|
-
`}function
|
|
3685
|
+
`}function hn(e){return `package server_test
|
|
3674
3686
|
|
|
3675
3687
|
import (
|
|
3676
3688
|
"encoding/json"
|
|
@@ -3780,7 +3792,7 @@ func TestServer_ReleaseMode(t *testing.T) {
|
|
|
3780
3792
|
t.Fatalf("expected 200 in release mode, got %d", w.Code)
|
|
3781
3793
|
}
|
|
3782
3794
|
}
|
|
3783
|
-
`}function
|
|
3795
|
+
`}function wn(e){return `package middleware
|
|
3784
3796
|
|
|
3785
3797
|
import (
|
|
3786
3798
|
"os"
|
|
@@ -3831,7 +3843,7 @@ func RateLimit() gin.HandlerFunc {
|
|
|
3831
3843
|
c.Next()
|
|
3832
3844
|
}
|
|
3833
3845
|
}
|
|
3834
|
-
`}function
|
|
3846
|
+
`}function yn(e){return `package middleware_test
|
|
3835
3847
|
|
|
3836
3848
|
import (
|
|
3837
3849
|
"net/http"
|
|
@@ -3900,7 +3912,7 @@ func TestRateLimit_InvalidRPS(t *testing.T) {
|
|
|
3900
3912
|
t.Fatalf("expected 200 with invalid RPS env, got %d", w.Code)
|
|
3901
3913
|
}
|
|
3902
3914
|
}
|
|
3903
|
-
`}function
|
|
3915
|
+
`}function vn(e){return `# Air \u2014 live reload for Go projects
|
|
3904
3916
|
# https://github.com/air-verse/air
|
|
3905
3917
|
root = "."
|
|
3906
3918
|
tmp_dir = "tmp"
|
|
@@ -3925,7 +3937,7 @@ tmp_dir = "tmp"
|
|
|
3925
3937
|
|
|
3926
3938
|
[log]
|
|
3927
3939
|
time = false
|
|
3928
|
-
`}function
|
|
3940
|
+
`}function bn(e){return `run:
|
|
3929
3941
|
timeout: 5m
|
|
3930
3942
|
|
|
3931
3943
|
linters:
|
|
@@ -3971,7 +3983,7 @@ issues:
|
|
|
3971
3983
|
linters:
|
|
3972
3984
|
- errcheck
|
|
3973
3985
|
- wrapcheck
|
|
3974
|
-
`}function
|
|
3986
|
+
`}function kn(){return JSON.stringify({engine:"npm",runtime:"go"},null,2)}function Rn(e,o){return JSON.stringify({kit_name:"gogin.standard",runtime:"go",module_support:false,project_name:e.project_name,module_path:e.module_path,app_version:e.app_version,created_by:"rapidkit-npm",rapidkit_version:o,created_at:new Date().toISOString()},null,2)}function xn(e){return `#!/usr/bin/env sh
|
|
3975
3987
|
# RapidKit Go/Gin project launcher \u2014 generated by RapidKit CLI
|
|
3976
3988
|
# https://getrapidkit.com
|
|
3977
3989
|
|
|
@@ -4050,7 +4062,7 @@ case "$CMD" in
|
|
|
4050
4062
|
exit 1
|
|
4051
4063
|
;;
|
|
4052
4064
|
esac
|
|
4053
|
-
`}function
|
|
4065
|
+
`}function Cn(e){return `@echo off
|
|
4054
4066
|
rem RapidKit Go/Gin project launcher \u2014 Windows
|
|
4055
4067
|
set CMD=%1
|
|
4056
4068
|
if "%CMD%"=="" goto usage
|
|
@@ -4075,107 +4087,107 @@ if "%CMD%"=="start" ( bin\\${e.project_name}.exe %* & exit /b %ERRORLEVEL% )
|
|
|
4075
4087
|
:usage
|
|
4076
4088
|
echo Available: init, dev, start, build, docs, test, lint, format
|
|
4077
4089
|
exit /b 1
|
|
4078
|
-
`}async function
|
|
4079
|
-
`));}let i=Qe(`Generating Go/Gin project: ${t.project_name}\u2026`).start();try{let r=(s,d)=>vr(h.join(e,s),d),a=h.join(e,"rapidkit"),c=h.join(e,"rapidkit.cmd");await Promise.all([r("cmd/server/main.go",br(t)),r("go.mod",kr(t)),r("internal/config/config.go",Rr(t)),r("internal/server/server.go",Sr(t)),r("internal/middleware/requestid.go",Nr()),r("internal/middleware/requestid_test.go",jr(t)),r("internal/apierr/apierr.go",Gr()),r("internal/apierr/apierr_test.go",$r(t)),r("internal/handlers/health.go",xr()),r("internal/handlers/health_test.go",_r(t)),r("internal/handlers/example.go",qr(t)),r("internal/handlers/example_test.go",Mr(t)),r("internal/config/config_test.go",Lr(t)),r("internal/middleware/cors.go",Fr()),r("internal/middleware/cors_test.go",Hr(t)),r("internal/middleware/ratelimit.go",Vr(t)),r("internal/middleware/ratelimit_test.go",Ur(t)),r("internal/server/server_test.go",Kr(t)),r("docs/doc.go",Dr(t)),r(".air.toml",Wr(t)),r("Dockerfile",Cr()),r("docker-compose.yml",Ir(t)),r("Makefile",Er(t)),r(".golangci.yml",Br(t.module_path)),r(".env.example",Pr(t)),r(".gitignore",Tr()),r(".github/workflows/ci.yml",Or(t)),r("README.md",Ar(t)),r(".rapidkit/project.json",zr(t,n)),r(".rapidkit/context.json",Jr()),r("rapidkit",Yr(t)),r("rapidkit.cmd",Qr(t))]),await promises.chmod(a,493),await promises.chmod(c,493),i.succeed(g.green(`Project created at ${e}`));try{i.start("Fetching Go dependencies\u2026"),await execa("go",["mod","tidy"],{cwd:e,timeout:12e4}),i.succeed(g.gray("\u2713 go mod tidy completed"));}catch{i.warn(g.yellow("\u26A0 go mod tidy failed \u2014 run manually: go mod tidy"));}if(!t.skipGit)try{await execa("git",["init"],{cwd:e}),await execa("git",["add","-A"],{cwd:e}),await execa("git",["commit","-m","chore: initial scaffold (rapidkit gogin.standard)"],{cwd:e}),console.log(g.gray("\u2713 git repository initialized"));}catch{console.log(g.gray("\u26A0 git init skipped (git not found or error)"));}console.log(""),console.log(g.bold("\u2705 Go/Gin project ready!")),console.log(""),console.log(g.cyan("Next steps:")),console.log(g.white(` cd ${t.project_name}`)),console.log(g.white(" make run # start dev server")),console.log(g.white(" make test # run tests")),console.log(""),console.log(g.gray("Server will listen on port "+t.port)),console.log(g.gray(" http://localhost:"+t.port+"/api/v1/health/live")),console.log(g.gray(" http://localhost:"+t.port+"/api/v1/health/ready")),console.log(""),console.log(g.yellow("\u2139 RapidKit modules are not available for Go projects (module system uses Python/pip).")),console.log("");}catch(r){throw i.fail(g.red("Failed to generate Go/Gin project")),r}}async function jt(){let e=process.platform==="win32"?["python","python3"]:["python3","python"];for(let o of e)try{let{stdout:t}=await execa(o,["--version"],{timeout:3e3}),n=t.match(/Python (\d+\.\d+\.\d+)/);if(n){let i=n[1],[r,a]=i.split(".").map(Number);return r<3||r===3&&a<10?{status:"warn",message:`Python ${i} (requires 3.10+)`,details:`${o} found but version is below minimum requirement`}:{status:"ok",message:`Python ${i}`,details:`Using ${o}`}}}catch{continue}return {status:"error",message:"Python not found",details:"Install Python 3.10+ and ensure it's in PATH"}}async function Gt(){try{let{stdout:e}=await execa("poetry",["--version"],{timeout:3e3}),o=e.match(/Poetry .*version ([\d.]+)/);return o?{status:"ok",message:`Poetry ${o[1]}`,details:"Available for dependency management"}:{status:"warn",message:"Poetry version unknown"}}catch{return {status:"warn",message:"Poetry not installed",details:"Optional: Install for better dependency management"}}}async function $t(){try{let{stdout:e}=await execa("pipx",["--version"],{timeout:3e3});return {status:"ok",message:`pipx ${e.trim()}`,details:"Available for global tool installation"}}catch{return {status:"warn",message:"pipx not installed",details:"Optional: Install for isolated Python tools"}}}async function Dt(){try{let{stdout:e}=await execa("go",["version"],{timeout:3e3}),o=e.match(/go version go(\d+\.\d+(?:\.\d+)?)/);return o?{status:"ok",message:`Go ${o[1]}`,details:"Available for Go/Fiber and Go/Gin projects"}:{status:"ok",message:"Go (version unknown)",details:"go found in PATH"}}catch{return {status:"warn",message:"Go not installed",details:"Optional: Required only for gofiber.standard / gogin.standard projects \u2014 https://go.dev/dl/"}}}async function qt(){let e=process.env.HOME||process.env.USERPROFILE||"",o=[],t=[{location:"Global (pipx)",path:h.join(e,".local","bin","rapidkit")},{location:"Global (pipx)",path:h.join(e,"AppData","Roaming","Python","Scripts","rapidkit.exe")},{location:"Global (pyenv)",path:h.join(e,".pyenv","shims","rapidkit")},{location:"Global (system)",path:"/usr/local/bin/rapidkit"},{location:"Global (system)",path:"/usr/bin/rapidkit"}],n=[{location:"Workspace (.venv)",path:h.join(process.cwd(),".venv","bin","rapidkit")},{location:"Workspace (.venv)",path:h.join(process.cwd(),".venv","Scripts","rapidkit.exe")}];for(let{location:r,path:a}of [...t,...n])try{if(await b__default.pathExists(a)){let{stdout:c,exitCode:s}=await execa(a,["--version"],{timeout:3e3,reject:false});if(s===0&&(c.includes("RapidKit Version")||c.includes("RapidKit"))){let d=c.match(/v?([\d.]+(?:rc\d+)?(?:a\d+)?(?:b\d+)?)/);d&&o.push({location:r,path:a,version:d[1]});}}}catch{continue}if(o.length>0)return {status:"ok",message:`RapidKit Core ${o[0].version}`,paths:o.map(a=>({location:a.location,path:a.path,version:a.version}))};try{let{stdout:r,exitCode:a}=await execa("rapidkit",["--version"],{timeout:3e3,reject:false});if(a===0&&(r.includes("RapidKit Version")||r.includes("RapidKit"))){let c=r.match(/v?([\d.]+(?:rc\d+)?(?:a\d+)?(?:b\d+)?)/);if(c)return {status:"ok",message:`RapidKit Core ${c[1]}`,details:"Available via PATH"}}}catch{}try{let{stdout:r,exitCode:a}=await execa("poetry",["run","rapidkit","--version"],{timeout:3e3,reject:false});if(a===0&&(r.includes("RapidKit Version")||r.includes("RapidKit"))){let c=r.match(/v?([\d.]+(?:rc\d+)?(?:a\d+)?(?:b\d+)?)/);if(c)return {status:"ok",message:`RapidKit Core ${c[1]}`,details:"Available via Poetry"}}}catch{}let i=process.platform==="win32"?["python","python3"]:["python3","python"];for(let r of i)try{let{stdout:a,exitCode:c}=await execa(r,["-c","import rapidkit_core; print(rapidkit_core.__version__)"],{timeout:3e3,reject:false});if(c===0&&a&&!a.includes("Traceback")&&!a.includes("ModuleNotFoundError")){let s=a.trim();if(s)return {status:"ok",message:`RapidKit Core ${s}`,details:`Available in ${r} environment`}}}catch{continue}return {status:"error",message:"RapidKit Core not installed",details:"Install with: pipx install rapidkit-core"}}async function Ae(e,o){let t=h.join(e,"Dockerfile");o.hasDocker=await b__default.pathExists(t);let n=h.join(e,"tests"),i=h.join(e,"test"),r=await b__default.pathExists(n)||await b__default.pathExists(i),a=false;if(o.framework==="Go/Fiber"||o.framework==="Go/Gin")try{let c=[{dir:e,depth:0}],s=4,d=new Set([".git",".venv","node_modules","dist","build","vendor"]);for(;c.length>0&&!a;){let l=c.shift();if(!l)break;let u=[];try{u=await b__default.readdir(l.dir);}catch{continue}for(let p of u){let k=h.join(l.dir,p),R;try{R=await b__default.stat(k);}catch{continue}if(R.isFile()&&p.endsWith("_test.go")){a=true;break}R.isDirectory()&&l.depth<s&&!d.has(p)&&!p.startsWith(".")&&c.push({dir:k,depth:l.depth+1});}}}catch{}if(o.hasTests=r||a,o.framework==="NestJS"){let c=h.join(e,".eslintrc.js"),s=h.join(e,".eslintrc.json");o.hasCodeQuality=await b__default.pathExists(c)||await b__default.pathExists(s);}else if(o.framework==="Go/Fiber"||o.framework==="Go/Gin"){let c=h.join(e,".golangci.yml"),s=h.join(e,".golangci.yaml"),d=h.join(e,"Makefile"),l=await b__default.pathExists(d)&&(await b__default.readFile(d,"utf8")).includes("golangci-lint");o.hasCodeQuality=await b__default.pathExists(c)||await b__default.pathExists(s)||l;}else if(o.framework==="FastAPI"){let c=h.join(e,"ruff.toml"),s=h.join(e,"pyproject.toml");if(await b__default.pathExists(s))try{let d=await b__default.readFile(s,"utf8");o.hasCodeQuality=d.includes("[tool.ruff]")||await b__default.pathExists(c);}catch{o.hasCodeQuality=await b__default.pathExists(c);}}try{if(o.framework==="NestJS"){let{stdout:c}=await execa("npm",["audit","--json"],{cwd:e,reject:false});if(c)try{let d=JSON.parse(c).metadata?.vulnerabilities;d&&(o.vulnerabilities=(d.high||0)+(d.critical||0)+(d.moderate||0));}catch{}}else if(o.framework==="FastAPI"){let c=h.join(e,".venv"),s=process.platform==="win32"?h.join(c,"Scripts","python.exe"):h.join(c,"bin","python");if(await b__default.pathExists(s))try{let{stdout:d}=await execa(s,["-m","pip","list","--format=json"],{timeout:5e3,reject:false});if(d){JSON.parse(d);o.vulnerabilities=0;}}catch{}}}catch{}}async function Zr(e){let t={name:h.basename(e),path:e,venvActive:false,depsInstalled:false,coreInstalled:false,issues:[],fixCommands:[]},n=h.join(e,".rapidkit");if(!await b__default.pathExists(n))return t.issues.push("Not a valid RapidKit project (missing .rapidkit directory)"),t;try{let u=h.join(e,"registry.json");if(await b__default.pathExists(u)){let p=await b__default.readJson(u);p.installed_modules&&(t.stats={modules:p.installed_modules.length});}}catch{}let i=null;try{let u=h.join(n,"project.json");if(await b__default.pathExists(u)){i=await b__default.readJson(u);let p=i?.kit_name||i?.kit;p&&(t.kit=p);}}catch{}try{let u=h.join(e,".git");if(await b__default.pathExists(u)){let{stdout:p}=await execa("git",["log","-1","--format=%cr"],{cwd:e,reject:false});p&&(t.lastModified=p.trim());}else {let p=await b__default.stat(e),R=Date.now()-p.mtime.getTime(),w=Math.floor(R/(1e3*60*60*24));t.lastModified=w===0?"today":`${w} day${w>1?"s":""} ago`;}}catch{}let r=h.join(e,"package.json"),a=h.join(e,"pyproject.toml"),c=h.join(e,"go.mod");if(await b__default.pathExists(c)||i?.runtime==="go"||typeof i?.kit_name=="string"&&(i.kit_name.startsWith("gofiber")||i.kit_name.startsWith("gogin"))){let u=i?.kit_name??"";t.framework=u.startsWith("gogin")?"Go/Gin":"Go/Fiber",t.isGoProject=true,t.venvActive=true,t.coreInstalled=false;try{await execa("go",["version"],{timeout:3e3});}catch{t.issues.push("Go toolchain not found \u2014 install from https://go.dev/dl/"),t.fixCommands?.push("https://go.dev/dl/");}let p=h.join(e,"go.sum");return await b__default.pathExists(p)?t.depsInstalled=true:(t.depsInstalled=false,t.issues.push("Go dependencies not downloaded (go.sum missing)"),t.fixCommands?.push(`cd ${e} && go mod tidy`)),await Ae(e,t),t}let d=await b__default.pathExists(r),l=await b__default.pathExists(a);if(d){t.framework="NestJS",t.venvActive=true;let u=h.join(e,"node_modules");if(await b__default.pathExists(u))try{let w=(await b__default.readdir(u)).filter(x=>!x.startsWith(".")&&!x.startsWith("_"));t.depsInstalled=w.length>0;}catch{t.depsInstalled=false;}t.depsInstalled||(t.issues.push("Dependencies not installed (node_modules empty or missing)"),t.fixCommands?.push(`cd ${e} && rapidkit init`)),t.coreInstalled=false;let p=h.join(e,".env");if(t.hasEnvFile=await b__default.pathExists(p),!t.hasEnvFile){let R=h.join(e,".env.example");await b__default.pathExists(R)&&(t.issues.push("Environment file missing (found .env.example)"),t.fixCommands?.push(`cd ${e} && cp .env.example .env`));}let k=h.join(e,"src");if(t.modulesHealthy=true,t.missingModules=[],await b__default.pathExists(k))try{let R=await b__default.readdir(k);t.modulesHealthy=R.length>0;}catch{t.modulesHealthy=false;}return await Ae(e,t),t}if(l){t.framework="FastAPI";let u=h.join(e,".venv");if(await b__default.pathExists(u)){t.venvActive=true;let w=process.platform==="win32"?h.join(u,"Scripts","python.exe"):h.join(u,"bin","python");if(await b__default.pathExists(w)){try{let{stdout:x}=await execa(w,["-c","import rapidkit_core; print(rapidkit_core.__version__)"],{timeout:2e3});t.coreInstalled=true,t.coreVersion=x.trim();}catch{t.coreInstalled=false;}try{await execa(w,["-c","import fastapi"],{timeout:2e3}),t.depsInstalled=true;}catch{try{let x=h.join(u,"lib");if(await b__default.pathExists(x)){let G=(await b__default.readdir(x)).find(V=>V.startsWith("python"));if(G){let V=h.join(x,G,"site-packages");if(await b__default.pathExists(V)){let We=(await b__default.readdir(V)).filter(Be=>!Be.startsWith("_")&&!Be.includes("dist-info")&&!["pip","setuptools","wheel","pkg_resources"].includes(Be));t.depsInstalled=We.length>0;}}}t.depsInstalled||(t.issues.push("Dependencies not installed"),t.fixCommands?.push(`cd ${e} && rapidkit init`));}catch{t.issues.push("Could not verify dependency installation");}}}else t.issues.push("Virtual environment exists but Python executable not found");}else t.issues.push("Virtual environment not created"),t.fixCommands?.push(`cd ${e} && rapidkit init`);let p=h.join(e,".env");if(t.hasEnvFile=await b__default.pathExists(p),!t.hasEnvFile){let w=h.join(e,".env.example");await b__default.pathExists(w)&&(t.issues.push("Environment file missing (found .env.example)"),t.fixCommands?.push(`cd ${e} && cp .env.example .env`));}let k=h.join(e,"src"),R=h.join(e,"modules");if(t.modulesHealthy=true,t.missingModules=[],await b__default.pathExists(k)){let w=h.join(k,"__init__.py");await b__default.pathExists(w)||(t.modulesHealthy=false,t.missingModules.push("src/__init__.py"));}if(await b__default.pathExists(R))try{let w=await Mt(R);for(let x of w){let O=h.join(R,x,"__init__.py");await b__default.pathExists(O)||(t.modulesHealthy=false,t.missingModules.push(`modules/${x}/__init__.py`));}}catch{}return !t.modulesHealthy&&t.missingModules.length>0&&t.issues.push(`Missing module init files: ${t.missingModules.join(", ")}`),await Ae(e,t),t}return t.issues.push("Unknown project type (no package.json or pyproject.toml)"),await Ae(e,t),t}async function Mt(e){try{return (await b__default.readdir(e,{withFileTypes:true})).filter(t=>t.isDirectory()).map(t=>t.name)}catch{try{let o=await b__default.readdir(e),t=[];for(let n of o)try{(await b__default.stat(h.join(e,n))).isDirectory()&&t.push(n);}catch{continue}return t}catch{return []}}}async function tt(e){let o=h.join(e,".rapidkit");if(!await b__default.pathExists(o))return false;let t=["project.json","context.json","file-hashes.json"];for(let n of t)if(await b__default.pathExists(h.join(o,n)))return true;return false}function Lt(e,o){if(o.has(e))return true;let t=e.toLowerCase();return !!(t==="dist"||t.startsWith("dist-")||t.startsWith("dist_")||t==="build"||t.startsWith("build-")||t.startsWith("build_"))}async function en(e,o,t){let n=new Set,i=[{dir:e,depth:0}];for(;i.length>0;){let r=i.shift();if(!r)break;try{let a=await b__default.readdir(r.dir);for(let c of a){if(Lt(c,t))continue;let s=h.join(r.dir,c),d;try{d=await b__default.stat(s);}catch{continue}if(d.isDirectory()){if(await tt(s)){n.add(s);continue}r.depth<o&&i.push({dir:s,depth:r.depth+1});}}}catch{continue}}return Array.from(n)}async function tn(e){let o=e,t=h.parse(o).root;for(;o!==t;){let n=[h.join(o,".rapidkit-workspace"),h.join(o,".rapidkit","workspace-marker.json"),h.join(o,".rapidkit","config.json")];for(let i of n)if(await b__default.pathExists(i))return o;o=h.dirname(o);}return null}function on(e,o){let t=0,n=0,i=0;return e.forEach(a=>{a.status==="ok"?t++:a.status==="warn"?n++:a.status==="error"&&i++;}),o.forEach(a=>{(a.isGoProject?a.issues.length===0&&a.depsInstalled:a.issues.length===0&&a.venvActive&&a.depsInstalled)?t++:a.issues.length>0&&n++;}),{total:t+n+i,passed:t,warnings:n,errors:i}}async function rn(e){let o=h.basename(e);try{let i=h.join(e,".rapidkit-workspace");await b__default.pathExists(i)&&(o=(await b__default.readJSON(i)).name||o);}catch{try{let i=h.join(e,".rapidkit","config.json");o=(await b__default.readJSON(i)).workspace_name||o;}catch{}}let t={workspacePath:e,workspaceName:o,python:await jt(),poetry:await Gt(),pipx:await $t(),go:await Dt(),rapidkitCore:await qt(),projects:[]};try{let i=new Set([".git",".venv","node_modules",".rapidkit","dist","build","coverage","__pycache__"]),r=new Set;await tt(e)&&r.add(e);let a$1=async(c,s)=>{if(s<0)return;let d=await Mt(c);for(let l of d){if(Lt(l,i))continue;let u=h.join(c,l);if(await tt(u)){r.add(u);continue}s>0&&await a$1(u,s-1);}};if(await a$1(e,1),a.debug(`Workspace scan (shallow) found ${r.size} project(s)`),r.size===0){let c=await en(e,3,i);c.forEach(s=>r.add(s)),a.debug(`Workspace scan (deep fallback) found ${c.length} project(s)`);}r.size>0&&a.debug(`Workspace projects detected: ${Array.from(r).join(", ")}`);for(let c of r){let s=await Zr(c);t.projects.push(s);}}catch(i){a.debug(`Failed to scan workspace projects: ${i}`);}let n=[t.python,t.poetry,t.pipx,t.go,t.rapidkitCore];if(t.healthScore=on(n,t.projects),t.rapidkitCore.status==="ok"){let i=t.rapidkitCore.message.match(/([\d.]+(?:rc\d+)?(?:a\d+)?(?:b\d+)?)/);i&&(t.coreVersion=i[1]);}return t}function B(e,o){let t=e.status==="ok"?"\u2705":e.status==="warn"?"\u26A0\uFE0F":"\u274C",n=e.status==="ok"?g.green:e.status==="warn"?g.yellow:g.red;console.log(`${t} ${g.bold(o)}: ${n(e.message)}`),e.paths&&e.paths.length>0?e.paths.forEach(i=>{let r=i.version?g.cyan(` -> ${i.version}`):"";console.log(` ${g.cyan("\u2022")} ${g.gray(i.location)}: ${g.dim(i.path)}${r}`);}):e.details&&console.log(` ${g.gray(e.details)}`);}function nn(e){let o=e.issues.length>0,t=o?"\u26A0\uFE0F":"\u2705",n=o?g.yellow:g.green;if(console.log(`
|
|
4080
|
-
${t} ${g.bold("Project")}: ${
|
|
4081
|
-
${g.bold.cyan("\u{1F527} Quick Fix:")}`),e.fixCommands.forEach(
|
|
4090
|
+
`}async function mt(e,o){let t={project_name:o.project_name,module_path:o.module_path||o.project_name,author:o.author||"RapidKit User",description:o.description||`Go/Gin REST API \u2014 ${o.project_name}`,go_version:o.go_version||"1.24",app_version:o.app_version||"0.1.0",port:o.port||"8080",skipGit:o.skipGit??false},r=c();try{await execa("go",["version"],{timeout:3e3});}catch{console.log(g.yellow("\n\u26A0 Go not found in PATH \u2014 project will be scaffolded, but `go mod tidy` requires Go 1.21+")),console.log(g.gray(` Install: https://go.dev/dl/
|
|
4091
|
+
`));}let i=pt(`Generating Go/Gin project: ${t.project_name}\u2026`).start();try{let n=(a,l)=>Vr(v.join(e,a),l),s=v.join(e,"rapidkit"),c=v.join(e,"rapidkit.cmd");await Promise.all([n("cmd/server/main.go",Wr(t)),n("go.mod",Br(t)),n("internal/config/config.go",Jr(t)),n("internal/server/server.go",zr(t)),n("internal/middleware/requestid.go",sn()),n("internal/middleware/requestid_test.go",an(t)),n("internal/apierr/apierr.go",cn()),n("internal/apierr/apierr_test.go",dn(t)),n("internal/handlers/health.go",Yr()),n("internal/handlers/health_test.go",Qr(t)),n("internal/handlers/example.go",pn(t)),n("internal/handlers/example_test.go",un(t)),n("internal/config/config_test.go",gn(t)),n("internal/middleware/cors.go",mn()),n("internal/middleware/cors_test.go",fn(t)),n("internal/middleware/ratelimit.go",wn(t)),n("internal/middleware/ratelimit_test.go",yn(t)),n("internal/server/server_test.go",hn(t)),n("docs/doc.go",ln(t)),n(".air.toml",vn(t)),n("Dockerfile",Xr()),n("docker-compose.yml",Zr(t)),n("Makefile",en(t)),n(".golangci.yml",bn(t.module_path)),n(".env.example",tn(t)),n(".gitignore",on()),n(".github/workflows/ci.yml",rn(t)),n("README.md",nn(t)),n(".rapidkit/project.json",Rn(t,r)),n(".rapidkit/context.json",kn()),n("rapidkit",xn(t)),n("rapidkit.cmd",Cn(t))]),await promises.chmod(s,493),await promises.chmod(c,493),i.succeed(g.green(`Project created at ${e}`));try{i.start("Fetching Go dependencies\u2026"),await execa("go",["mod","tidy"],{cwd:e,timeout:12e4}),i.succeed(g.gray("\u2713 go mod tidy completed"));}catch{i.warn(g.yellow("\u26A0 go mod tidy failed \u2014 run manually: go mod tidy"));}if(!t.skipGit)try{await execa("git",["init"],{cwd:e}),await execa("git",["add","-A"],{cwd:e}),await execa("git",["commit","-m","chore: initial scaffold (rapidkit gogin.standard)"],{cwd:e}),console.log(g.gray("\u2713 git repository initialized"));}catch{console.log(g.gray("\u26A0 git init skipped (git not found or error)"));}console.log(""),console.log(g.bold("\u2705 Go/Gin project ready!")),console.log(""),console.log(g.cyan("Next steps:")),console.log(g.white(` cd ${t.project_name}`)),console.log(g.white(" make run # start dev server")),console.log(g.white(" make test # run tests")),console.log(""),console.log(g.gray("Server will listen on port "+t.port)),console.log(g.gray(" http://localhost:"+t.port+"/api/v1/health/live")),console.log(g.gray(" http://localhost:"+t.port+"/api/v1/health/ready")),console.log(""),console.log(g.yellow("\u2139 RapidKit modules are not available for Go projects (module system uses Python/pip).")),console.log("");}catch(n){throw i.fail(g.red("Failed to generate Go/Gin project")),n}}async function Yt(){let e=process.platform==="win32"?["python","python3"]:["python3","python"];for(let o of e)try{let{stdout:t}=await execa(o,["--version"],{timeout:3e3}),r=t.match(/Python (\d+\.\d+\.\d+)/);if(r){let i=r[1],[n,s]=i.split(".").map(Number);return n<3||n===3&&s<10?{status:"warn",message:`Python ${i} (requires 3.10+)`,details:`${o} found but version is below minimum requirement`}:{status:"ok",message:`Python ${i}`,details:`Using ${o}`}}}catch{continue}return {status:"error",message:"Python not found",details:"Install Python 3.10+ and ensure it's in PATH"}}async function Qt(){try{let{stdout:e}=await execa("poetry",["--version"],{timeout:3e3}),o=e.match(/Poetry .*version ([\d.]+)/);return o?{status:"ok",message:`Poetry ${o[1]}`,details:"Available for dependency management"}:{status:"warn",message:"Poetry version unknown"}}catch{return {status:"warn",message:"Poetry not installed",details:"Optional: Install for better dependency management"}}}async function Xt(){try{let{stdout:e}=await execa("pipx",["--version"],{timeout:3e3});return {status:"ok",message:`pipx ${e.trim()}`,details:"Available for global tool installation"}}catch{return {status:"warn",message:"pipx not installed",details:"Optional: Install for isolated Python tools"}}}async function Zt(){try{let{stdout:e}=await execa("go",["version"],{timeout:3e3}),o=e.match(/go version go(\d+\.\d+(?:\.\d+)?)/);return o?{status:"ok",message:`Go ${o[1]}`,details:"Available for Go/Fiber and Go/Gin projects"}:{status:"ok",message:"Go (version unknown)",details:"go found in PATH"}}catch{return {status:"warn",message:"Go not installed",details:"Optional: Required only for gofiber.standard / gogin.standard projects \u2014 https://go.dev/dl/"}}}async function eo(){let e=process.env.HOME||process.env.USERPROFILE||"",o=[],t=[{location:"Global (pipx)",path:v.join(e,".local","bin","rapidkit")},{location:"Global (pipx)",path:v.join(e,"AppData","Roaming","Python","Scripts","rapidkit.exe")},{location:"Global (pyenv)",path:v.join(e,".pyenv","shims","rapidkit")},{location:"Global (system)",path:"/usr/local/bin/rapidkit"},{location:"Global (system)",path:"/usr/bin/rapidkit"}],r=[{location:"Workspace (.venv)",path:v.join(process.cwd(),".venv","bin","rapidkit")},{location:"Workspace (.venv)",path:v.join(process.cwd(),".venv","Scripts","rapidkit.exe")}];for(let{location:n,path:s}of [...t,...r])try{if(await R__default.pathExists(s)){let{stdout:c,exitCode:a}=await execa(s,["--version"],{timeout:3e3,reject:false});if(a===0&&(c.includes("RapidKit Version")||c.includes("RapidKit"))){let l=c.match(/v?([\d.]+(?:rc\d+)?(?:a\d+)?(?:b\d+)?)/);l&&o.push({location:n,path:s,version:l[1]});}}}catch{continue}if(o.length>0)return {status:"ok",message:`RapidKit Core ${o[0].version}`,paths:o.map(s=>({location:s.location,path:s.path,version:s.version}))};try{let{stdout:n,exitCode:s}=await execa("rapidkit",["--version"],{timeout:3e3,reject:false});if(s===0&&(n.includes("RapidKit Version")||n.includes("RapidKit"))){let c=n.match(/v?([\d.]+(?:rc\d+)?(?:a\d+)?(?:b\d+)?)/);if(c)return {status:"ok",message:`RapidKit Core ${c[1]}`,details:"Available via PATH"}}}catch{}try{let{stdout:n,exitCode:s}=await execa("poetry",["run","rapidkit","--version"],{timeout:3e3,reject:false});if(s===0&&(n.includes("RapidKit Version")||n.includes("RapidKit"))){let c=n.match(/v?([\d.]+(?:rc\d+)?(?:a\d+)?(?:b\d+)?)/);if(c)return {status:"ok",message:`RapidKit Core ${c[1]}`,details:"Available via Poetry"}}}catch{}let i=process.platform==="win32"?["python","python3"]:["python3","python"];for(let n of i)try{let{stdout:s,exitCode:c}=await execa(n,["-c","import rapidkit_core; print(rapidkit_core.__version__)"],{timeout:3e3,reject:false});if(c===0&&s&&!s.includes("Traceback")&&!s.includes("ModuleNotFoundError")){let a=s.trim();if(a)return {status:"ok",message:`RapidKit Core ${a}`,details:`Available in ${n} environment`}}}catch{continue}return {status:"error",message:"RapidKit Core not installed",details:"Install with: pipx install rapidkit-core"}}async function Fe(e,o){let t=v.join(e,"Dockerfile");o.hasDocker=await R__default.pathExists(t);let r=v.join(e,"tests"),i=v.join(e,"test"),n=await R__default.pathExists(r)||await R__default.pathExists(i),s=false;if(o.framework==="Go/Fiber"||o.framework==="Go/Gin")try{let c=[{dir:e,depth:0}],a=4,l=new Set([".git",".venv","node_modules","dist","build","vendor"]);for(;c.length>0&&!s;){let d=c.shift();if(!d)break;let p=[];try{p=await R__default.readdir(d.dir);}catch{continue}for(let u of p){let h=v.join(d.dir,u),x;try{x=await R__default.stat(h);}catch{continue}if(x.isFile()&&u.endsWith("_test.go")){s=true;break}x.isDirectory()&&d.depth<a&&!l.has(u)&&!u.startsWith(".")&&c.push({dir:h,depth:d.depth+1});}}}catch{}if(o.hasTests=n||s,o.framework==="NestJS"){let c=v.join(e,".eslintrc.js"),a=v.join(e,".eslintrc.json");o.hasCodeQuality=await R__default.pathExists(c)||await R__default.pathExists(a);}else if(o.framework==="Go/Fiber"||o.framework==="Go/Gin"){let c=v.join(e,".golangci.yml"),a=v.join(e,".golangci.yaml"),l=v.join(e,"Makefile"),d=await R__default.pathExists(l)&&(await R__default.readFile(l,"utf8")).includes("golangci-lint");o.hasCodeQuality=await R__default.pathExists(c)||await R__default.pathExists(a)||d;}else if(o.framework==="FastAPI"){let c=v.join(e,"ruff.toml"),a=v.join(e,"pyproject.toml");if(await R__default.pathExists(a))try{let l=await R__default.readFile(a,"utf8");o.hasCodeQuality=l.includes("[tool.ruff]")||await R__default.pathExists(c);}catch{o.hasCodeQuality=await R__default.pathExists(c);}}try{if(o.framework==="NestJS"){let{stdout:c}=await execa("npm",["audit","--json"],{cwd:e,reject:false});if(c)try{let l=JSON.parse(c).metadata?.vulnerabilities;l&&(o.vulnerabilities=(l.high||0)+(l.critical||0)+(l.moderate||0));}catch{}}else if(o.framework==="FastAPI"){let c=v.join(e,".venv"),a=process.platform==="win32"?v.join(c,"Scripts","python.exe"):v.join(c,"bin","python");if(await R__default.pathExists(a))try{let{stdout:l}=await execa(a,["-m","pip","list","--format=json"],{timeout:5e3,reject:false});if(l){JSON.parse(l);o.vulnerabilities=0;}}catch{}}}catch{}}async function _n(e){let t={name:v.basename(e),path:e,venvActive:false,depsInstalled:false,coreInstalled:false,issues:[],fixCommands:[]},r=v.join(e,".rapidkit");if(!await R__default.pathExists(r))return t.issues.push("Not a valid RapidKit project (missing .rapidkit directory)"),t;try{let p=v.join(e,"registry.json");if(await R__default.pathExists(p)){let u=await R__default.readJson(p);u.installed_modules&&(t.stats={modules:u.installed_modules.length});}}catch{}let i=null;try{let p=v.join(r,"project.json");if(await R__default.pathExists(p)){i=await R__default.readJson(p);let u=i?.kit_name||i?.kit;u&&(t.kit=u);}}catch{}try{let p=v.join(e,".git");if(await R__default.pathExists(p)){let{stdout:u}=await execa("git",["log","-1","--format=%cr"],{cwd:e,reject:false});u&&(t.lastModified=u.trim());}else {let u=await R__default.stat(e),x=Date.now()-u.mtime.getTime(),y=Math.floor(x/(1e3*60*60*24));t.lastModified=y===0?"today":`${y} day${y>1?"s":""} ago`;}}catch{}let n=v.join(e,"package.json"),s=v.join(e,"pyproject.toml"),c=v.join(e,"go.mod");if(await R__default.pathExists(c)||i?.runtime==="go"||typeof i?.kit_name=="string"&&(i.kit_name.startsWith("gofiber")||i.kit_name.startsWith("gogin"))){let p=i?.kit_name??"";t.framework=p.startsWith("gogin")?"Go/Gin":"Go/Fiber",t.isGoProject=true,t.venvActive=true,t.coreInstalled=false;try{await execa("go",["version"],{timeout:3e3});}catch{t.issues.push("Go toolchain not found \u2014 install from https://go.dev/dl/"),t.fixCommands?.push("https://go.dev/dl/");}let u=v.join(e,"go.sum");return await R__default.pathExists(u)?t.depsInstalled=true:(t.depsInstalled=false,t.issues.push("Go dependencies not downloaded (go.sum missing)"),t.fixCommands?.push(`cd ${e} && go mod tidy`)),await Fe(e,t),t}let l=await R__default.pathExists(n),d=await R__default.pathExists(s);if(l){t.framework="NestJS",t.venvActive=true;let p=v.join(e,"node_modules");if(await R__default.pathExists(p))try{let y=(await R__default.readdir(p)).filter(C=>!C.startsWith(".")&&!C.startsWith("_"));t.depsInstalled=y.length>0;}catch{t.depsInstalled=false;}t.depsInstalled||(t.issues.push("Dependencies not installed (node_modules empty or missing)"),t.fixCommands?.push(`cd ${e} && rapidkit init`)),t.coreInstalled=false;let u=v.join(e,".env");if(t.hasEnvFile=await R__default.pathExists(u),!t.hasEnvFile){let x=v.join(e,".env.example");await R__default.pathExists(x)&&(t.issues.push("Environment file missing (found .env.example)"),t.fixCommands?.push(`cd ${e} && cp .env.example .env`));}let h=v.join(e,"src");if(t.modulesHealthy=true,t.missingModules=[],await R__default.pathExists(h))try{let x=await R__default.readdir(h);t.modulesHealthy=x.length>0;}catch{t.modulesHealthy=false;}return await Fe(e,t),t}if(d){t.framework="FastAPI";let p=v.join(e,".venv");if(await R__default.pathExists(p)){t.venvActive=true;let y=process.platform==="win32"?v.join(p,"Scripts","python.exe"):v.join(p,"bin","python");if(await R__default.pathExists(y)){try{let{stdout:C}=await execa(y,["-c","import rapidkit_core; print(rapidkit_core.__version__)"],{timeout:2e3});t.coreInstalled=true,t.coreVersion=C.trim();}catch{t.coreInstalled=false;}try{await execa(y,["-c","import fastapi"],{timeout:2e3}),t.depsInstalled=true;}catch{try{let C=v.join(p,"lib");if(await R__default.pathExists(C)){let q=(await R__default.readdir(C)).find(V=>V.startsWith("python"));if(q){let V=v.join(C,q,"site-packages");if(await R__default.pathExists(V)){let st=(await R__default.readdir(V)).filter(at=>!at.startsWith("_")&&!at.includes("dist-info")&&!["pip","setuptools","wheel","pkg_resources"].includes(at));t.depsInstalled=st.length>0;}}}t.depsInstalled||(t.issues.push("Dependencies not installed"),t.fixCommands?.push(`cd ${e} && rapidkit init`));}catch{t.issues.push("Could not verify dependency installation");}}}else t.issues.push("Virtual environment exists but Python executable not found");}else t.issues.push("Virtual environment not created"),t.fixCommands?.push(`cd ${e} && rapidkit init`);let u=v.join(e,".env");if(t.hasEnvFile=await R__default.pathExists(u),!t.hasEnvFile){let y=v.join(e,".env.example");await R__default.pathExists(y)&&(t.issues.push("Environment file missing (found .env.example)"),t.fixCommands?.push(`cd ${e} && cp .env.example .env`));}let h=v.join(e,"src"),x=v.join(e,"modules");if(t.modulesHealthy=true,t.missingModules=[],await R__default.pathExists(h)){let y=v.join(h,"__init__.py");await R__default.pathExists(y)||(t.modulesHealthy=false,t.missingModules.push("src/__init__.py"));}if(await R__default.pathExists(x))try{let y=await to(x);for(let C of y){let E=v.join(x,C,"__init__.py");await R__default.pathExists(E)||(t.modulesHealthy=false,t.missingModules.push(`modules/${C}/__init__.py`));}}catch{}return !t.modulesHealthy&&t.missingModules.length>0&&t.issues.push(`Missing module init files: ${t.missingModules.join(", ")}`),await Fe(e,t),t}return t.issues.push("Unknown project type (no package.json or pyproject.toml)"),await Fe(e,t),t}async function to(e){try{return (await R__default.readdir(e,{withFileTypes:true})).filter(t=>t.isDirectory()).map(t=>t.name)}catch{try{let o=await R__default.readdir(e),t=[];for(let r of o)try{(await R__default.stat(v.join(e,r))).isDirectory()&&t.push(r);}catch{continue}return t}catch{return []}}}async function ft(e){let o=v.join(e,".rapidkit");if(!await R__default.pathExists(o))return false;let t=["project.json","context.json","file-hashes.json"];for(let r of t)if(await R__default.pathExists(v.join(o,r)))return true;return false}function oo(e,o){if(o.has(e))return true;let t=e.toLowerCase();return !!(t==="dist"||t.startsWith("dist-")||t.startsWith("dist_")||t==="build"||t.startsWith("build-")||t.startsWith("build_"))}async function Pn(e,o,t){let r=new Set,i=[{dir:e,depth:0}];for(;i.length>0;){let n=i.shift();if(!n)break;try{let s=await R__default.readdir(n.dir);for(let c of s){if(oo(c,t))continue;let a=v.join(n.dir,c),l;try{l=await R__default.stat(a);}catch{continue}if(l.isDirectory()){if(await ft(a)){r.add(a);continue}n.depth<o&&i.push({dir:a,depth:n.depth+1});}}}catch{continue}}return Array.from(r)}async function In(e){let o=e,t=v.parse(o).root;for(;o!==t;){let r=[v.join(o,".rapidkit-workspace"),v.join(o,".rapidkit","workspace-marker.json"),v.join(o,".rapidkit","config.json")];for(let i of r)if(await R__default.pathExists(i))return o;o=v.dirname(o);}return null}function En(e,o){let t=0,r=0,i=0;return e.forEach(s=>{s.status==="ok"?t++:s.status==="warn"?r++:s.status==="error"&&i++;}),o.forEach(s=>{(s.isGoProject?s.issues.length===0&&s.depsInstalled:s.issues.length===0&&s.venvActive&&s.depsInstalled)?t++:s.issues.length>0&&r++;}),{total:t+r+i,passed:t,warnings:r,errors:i}}async function Tn(e){let o=v.basename(e);try{let i=v.join(e,".rapidkit-workspace");await R__default.pathExists(i)&&(o=(await R__default.readJSON(i)).name||o);}catch{try{let i=v.join(e,".rapidkit","config.json");o=(await R__default.readJSON(i)).workspace_name||o;}catch{}}let t={workspacePath:e,workspaceName:o,python:await Yt(),poetry:await Qt(),pipx:await Xt(),go:await Zt(),rapidkitCore:await eo(),projects:[]};try{let i=new Set([".git",".venv","node_modules",".rapidkit","dist","build","coverage","__pycache__"]),n=new Set;await ft(e)&&n.add(e);let s=async(c,a)=>{if(a<0)return;let l=await to(c);for(let d of l){if(oo(d,i))continue;let p=v.join(c,d);if(await ft(p)){n.add(p);continue}a>0&&await s(p,a-1);}};if(await s(e,1),a.debug(`Workspace scan (shallow) found ${n.size} project(s)`),n.size===0){let c=await Pn(e,3,i);c.forEach(a=>n.add(a)),a.debug(`Workspace scan (deep fallback) found ${c.length} project(s)`);}n.size>0&&a.debug(`Workspace projects detected: ${Array.from(n).join(", ")}`);for(let c of n){let a=await _n(c);t.projects.push(a);}}catch(i){a.debug(`Failed to scan workspace projects: ${i}`);}let r=[t.python,t.poetry,t.pipx,t.go,t.rapidkitCore];if(t.healthScore=En(r,t.projects),t.rapidkitCore.status==="ok"){let i=t.rapidkitCore.message.match(/([\d.]+(?:rc\d+)?(?:a\d+)?(?:b\d+)?)/);i&&(t.coreVersion=i[1]);}return t}function B(e,o){let t=e.status==="ok"?"\u2705":e.status==="warn"?"\u26A0\uFE0F":"\u274C",r=e.status==="ok"?g.green:e.status==="warn"?g.yellow:g.red;console.log(`${t} ${g.bold(o)}: ${r(e.message)}`),e.paths&&e.paths.length>0?e.paths.forEach(i=>{let n=i.version?g.cyan(` -> ${i.version}`):"";console.log(` ${g.cyan("\u2022")} ${g.gray(i.location)}: ${g.dim(i.path)}${n}`);}):e.details&&console.log(` ${g.gray(e.details)}`);}function An(e){let o=e.issues.length>0,t=o?"\u26A0\uFE0F":"\u2705",r=o?g.yellow:g.green;if(console.log(`
|
|
4092
|
+
${t} ${g.bold("Project")}: ${r(e.name)}`),e.framework){let a=e.framework==="FastAPI"?"\u{1F40D}":e.framework==="NestJS"?"\u{1F985}":e.framework==="Go/Fiber"||e.framework==="Go/Gin"?"\u{1F439}":"\u{1F4E6}";console.log(` ${a} Framework: ${g.cyan(e.framework)}${e.kit?g.gray(` (${e.kit})`):""}`);}console.log(` ${g.gray(`Path: ${e.path}`)}`);let i=e.isGoProject===true,n=!i&&e.venvActive&&!e.coreInstalled;if(!i&&!n&&(e.venvActive?console.log(` \u2705 Virtual environment: ${g.green("Active")}`):console.log(` \u274C Virtual environment: ${g.red("Not found")}`),e.coreInstalled?console.log(` ${g.dim("\u2139")} RapidKit Core: ${g.gray(e.coreVersion||"In venv")} ${g.dim("(optional)")}`):console.log(` ${g.dim("\u2139")} RapidKit Core: ${g.gray("Using global installation")} ${g.dim("(recommended)")}`)),e.depsInstalled?console.log(` \u2705 Dependencies: ${g.green("Installed")}`):console.log(` \u26A0\uFE0F Dependencies: ${g.yellow("Not installed")}`),e.hasEnvFile!==void 0&&(e.hasEnvFile?console.log(` \u2705 Environment: ${g.green(".env configured")}`):console.log(` \u26A0\uFE0F Environment: ${g.yellow(".env missing")}`)),e.modulesHealthy!==void 0&&(e.modulesHealthy?console.log(` \u2705 Modules: ${g.green("Healthy")}`):e.missingModules&&e.missingModules.length>0&&console.log(` \u26A0\uFE0F Modules: ${g.yellow(`Missing ${e.missingModules.length} init file(s)`)}`)),e.stats){let a=[];e.stats.modules!==void 0&&a.push(`${e.stats.modules} module${e.stats.modules!==1?"s":""}`),a.length>0&&console.log(` \u{1F4CA} Stats: ${g.cyan(a.join(" \u2022 "))}`);}e.lastModified&&console.log(` \u{1F552} Last Modified: ${g.gray(e.lastModified)}`);let c=[];if(e.hasTests!==void 0&&c.push(e.hasTests?"\u2705 Tests":g.dim("\u2298 No tests")),e.hasDocker!==void 0&&c.push(e.hasDocker?"\u2705 Docker":g.dim("\u2298 No Docker")),e.hasCodeQuality!==void 0){let a=e.framework==="NestJS"?"ESLint":e.framework==="Go/Fiber"||e.framework==="Go/Gin"?"golangci-lint":"Ruff";c.push(e.hasCodeQuality?`\u2705 ${a}`:g.dim(`\u2298 No ${a}`));}c.length>0&&console.log(` ${c.join(" \u2022 ")}`),e.vulnerabilities!==void 0&&e.vulnerabilities>0&&console.log(` \u26A0\uFE0F Security: ${g.yellow(`${e.vulnerabilities} vulnerability(ies) found`)}`),e.issues.length>0&&(console.log(` ${g.bold("Issues:")}`),e.issues.forEach(a=>{console.log(` \u2022 ${g.yellow(a)}`);}),e.fixCommands&&e.fixCommands.length>0&&(console.log(`
|
|
4093
|
+
${g.bold.cyan("\u{1F527} Quick Fix:")}`),e.fixCommands.forEach(a=>{console.log(` ${g.cyan("$")} ${g.white(a)}`);})));}async function zt(e,o=false){let t=e.filter(i=>i.fixCommands&&i.fixCommands.length>0);if(t.length===0){console.log(g.green(`
|
|
4082
4094
|
\u2705 No fixes needed - all projects are healthy!`));return}console.log(g.bold.cyan(`
|
|
4083
4095
|
\u{1F527} Available Fixes:
|
|
4084
|
-
`));for(let i of t)console.log(g.bold(`Project: ${g.yellow(i.name)}`)),i.fixCommands.forEach((
|
|
4096
|
+
`));for(let i of t)console.log(g.bold(`Project: ${g.yellow(i.name)}`)),i.fixCommands.forEach((n,s)=>{console.log(` ${s+1}. ${g.cyan(n)}`);}),console.log();if(!o){console.log(g.gray("\u{1F4A1} Run with --fix flag to apply fixes automatically"));return}let{confirm:r}=await ae.prompt([{type:"confirm",name:"confirm",message:`Apply ${t.reduce((i,n)=>i+n.fixCommands.length,0)} fix(es)?`,default:false}]);if(!r){console.log(g.yellow(`
|
|
4085
4097
|
\u26A0\uFE0F Fixes cancelled by user`));return}console.log(g.bold.cyan(`
|
|
4086
4098
|
\u{1F680} Applying fixes...
|
|
4087
|
-
`));for(let i of t){console.log(g.bold(`Fixing ${g.cyan(i.name)}...`));for(let
|
|
4088
|
-
`));}catch(
|
|
4099
|
+
`));for(let i of t){console.log(g.bold(`Fixing ${g.cyan(i.name)}...`));for(let n of i.fixCommands)try{console.log(g.gray(` $ ${n}`)),await execa(n,{shell:true,stdio:"inherit"}),console.log(g.green(` \u2705 Success
|
|
4100
|
+
`));}catch(s){console.log(g.red(` \u274C Failed: ${s instanceof Error?s.message:String(s)}
|
|
4089
4101
|
`));}}console.log(g.bold.green(`
|
|
4090
|
-
\u2705 Fix process completed!`));}async function
|
|
4102
|
+
\u2705 Fix process completed!`));}async function ro(e={}){if(e.json||console.log(g.bold.cyan(`
|
|
4091
4103
|
\u{1FA7A} RapidKit Health Check
|
|
4092
|
-
`)),e.workspace){let o=await
|
|
4093
|
-
\u{1F4CA} Health Score:`)),console.log(` ${c(`${
|
|
4104
|
+
`)),e.workspace){let o=await In(process.cwd());o||(a.error("No RapidKit workspace found in current directory or parents"),a.info('Run this command from within a workspace, or use "rapidkit doctor" for system check'),process.exit(1)),e.json||(console.log(g.bold(`Workspace: ${g.cyan(v.basename(o))}`)),console.log(g.gray(`Path: ${o}`)));let t=await Tn(o);if(e.json){let n={workspace:{name:v.basename(o),path:o},healthScore:t.healthScore,system:{python:t.python,poetry:t.poetry,pipx:t.pipx,rapidkitCore:t.rapidkitCore,versions:{core:t.coreVersion,npm:t.npmVersion}},projects:t.projects.map(s=>({name:s.name,path:s.path,venvActive:s.venvActive,depsInstalled:s.depsInstalled,coreInstalled:s.coreInstalled,coreVersion:s.coreVersion,issues:s.issues,fixCommands:s.fixCommands})),summary:{totalProjects:t.projects.length,totalIssues:t.projects.reduce((s,c)=>s+c.issues.length,0),hasSystemErrors:[t.python,t.rapidkitCore].some(s=>s.status==="error")}};console.log(JSON.stringify(n,null,2));return}if(t.healthScore){let n=t.healthScore,s=Math.round(n.passed/n.total*100),c=s>=80?g.green:s>=50?g.yellow:g.red,a="\u2588".repeat(Math.floor(s/5))+"\u2591".repeat(20-Math.floor(s/5));console.log(g.bold(`
|
|
4105
|
+
\u{1F4CA} Health Score:`)),console.log(` ${c(`${s}%`)} ${g.gray(a)}`),console.log(` ${g.green(`\u2705 ${n.passed} passed`)} ${g.gray("|")} ${g.yellow(`\u26A0\uFE0F ${n.warnings} warnings`)} ${g.gray("|")} ${g.red(`\u274C ${n.errors} errors`)}`);}if(console.log(g.bold(`
|
|
4094
4106
|
|
|
4095
4107
|
System Tools:
|
|
4096
|
-
`)),B(t.python,"Python"),B(t.poetry,"Poetry"),B(t.pipx,"pipx"),B(t.go,"Go"),B(t.rapidkitCore,"RapidKit Core"),t.coreVersion&&t.npmVersion){let
|
|
4108
|
+
`)),B(t.python,"Python"),B(t.poetry,"Poetry"),B(t.pipx,"pipx"),B(t.go,"Go"),B(t.rapidkitCore,"RapidKit Core"),t.coreVersion&&t.npmVersion){let n=t.coreVersion.split(".")[1],s=t.npmVersion.split(".")[1];n!==s&&(console.log(g.yellow(`
|
|
4097
4109
|
\u26A0\uFE0F Version mismatch: Core ${t.coreVersion} / CLI ${t.npmVersion}`)),console.log(g.gray(" Consider updating to matching versions for best compatibility")));}t.projects.length>0?(console.log(g.bold(`
|
|
4098
|
-
\u{1F4E6} Projects (${t.projects.length}):`)),t.projects.forEach(
|
|
4099
|
-
\u{1F4E6} Projects:`)),console.log(g.gray(" No RapidKit projects found in workspace")));let
|
|
4100
|
-
\u26A0\uFE0F Found ${
|
|
4110
|
+
\u{1F4E6} Projects (${t.projects.length}):`)),t.projects.forEach(n=>An(n))):(console.log(g.bold(`
|
|
4111
|
+
\u{1F4E6} Projects:`)),console.log(g.gray(" No RapidKit projects found in workspace")));let r=t.projects.reduce((n,s)=>n+s.issues.length,0),i=[t.python,t.rapidkitCore].some(n=>n.status==="error");i||r>0?(console.log(g.bold.yellow(`
|
|
4112
|
+
\u26A0\uFE0F Found ${r} project issue(s)`)),i&&console.log(g.bold.red("\u274C System requirements not met")),e.fix?await zt(t.projects,true):r>0&&await zt(t.projects,false)):console.log(g.bold.green(`
|
|
4101
4113
|
\u2705 All checks passed! Workspace is healthy.`));}else {console.log(g.bold(`System Tools:
|
|
4102
|
-
`));let o=await
|
|
4114
|
+
`));let o=await Yt(),t=await Qt(),r=await Xt(),i=await Zt(),n=await eo();B(o,"Python"),B(t,"Poetry"),B(r,"pipx"),B(i,"Go"),B(n,"RapidKit Core"),[o,n].some(c=>c.status==="error")?(console.log(g.bold.red(`
|
|
4103
4115
|
\u274C Some required tools are missing`)),console.log(g.gray(`
|
|
4104
4116
|
Tip: Run "rapidkit doctor --workspace" from within a workspace for detailed project checks`))):(console.log(g.bold.green(`
|
|
4105
4117
|
\u2705 All required tools are installed!`)),console.log(g.gray(`
|
|
4106
|
-
Tip: Run "rapidkit doctor --workspace" from within a workspace for detailed project checks`)));}console.log("");}var
|
|
4118
|
+
Tip: Run "rapidkit doctor --workspace" from within a workspace for detailed project checks`)));}console.log("");}var ht=v.join(qo__default.homedir(),".rapidkit"),He=v.join(ht,"config.json");function ue(){try{if(!A.existsSync(He))return {};let e=A.readFileSync(He,"utf-8");return JSON.parse(e)}catch{return {}}}function Ke(e){let t={...ue(),...e};A.existsSync(ht)||A.mkdirSync(ht,{recursive:true}),A.writeFileSync(He,JSON.stringify(t,null,2),"utf-8");}function xe(){return process.env.OPENAI_API_KEY||ue().openaiApiKey||null}function wt(){return ue().aiEnabled!==false}function yt(){return He}async function io(){return (await import('inquirer')).default}function so(e){let o=e.command("config").description("Configure RapidKit settings");o.command("set-api-key").description("Set OpenAI API key for AI features").option("--key <key>","API key (or enter interactively)").action(async t=>{let r=t.key;r?r.startsWith("sk-")||(console.log(g.red(`
|
|
4107
4119
|
\u274C Invalid API key format (should start with sk-)
|
|
4108
|
-
`)),process.exit(1)):
|
|
4120
|
+
`)),process.exit(1)):r=(await(await io()).prompt([{type:"password",name:"apiKey",message:"Enter your OpenAI API key:",validate:s=>s?s.startsWith("sk-")?s.length<20?"API key seems too short":true:"Invalid API key format (should start with sk-)":"API key is required"}])).apiKey,Ke({openaiApiKey:r}),console.log(g.green(`
|
|
4109
4121
|
\u2705 OpenAI API key saved successfully!
|
|
4110
|
-
`)),console.log(g.gray(`Stored in: ${
|
|
4122
|
+
`)),console.log(g.gray(`Stored in: ${yt()}`)),console.log(g.cyan(`
|
|
4111
4123
|
\u{1F389} You can now use AI features:`)),console.log(g.white(' rapidkit ai recommend "I need user authentication"')),console.log(g.gray(`
|
|
4112
4124
|
\u{1F4A1} To generate module embeddings (one-time):`)),console.log(g.white(" cd rapidkit-npm")),console.log(g.white(` npx tsx src/ai/generate-embeddings.ts
|
|
4113
|
-
`));}),o.command("show").description("Show current configuration").action(()=>{let t=
|
|
4125
|
+
`));}),o.command("show").description("Show current configuration").action(()=>{let t=ue();if(console.log(g.bold(`
|
|
4114
4126
|
\u2699\uFE0F RapidKit Configuration
|
|
4115
|
-
`)),t.openaiApiKey){let
|
|
4116
|
-
\u{1F4C1} Config file: ${
|
|
4117
|
-
`));}),o.command("remove-api-key").description("Remove stored OpenAI API key").action(async()=>{if(!
|
|
4127
|
+
`)),t.openaiApiKey){let r=t.openaiApiKey.substring(0,8)+"..."+t.openaiApiKey.slice(-4);console.log(g.cyan("OpenAI API Key:"),g.white(r));}else console.log(g.cyan("OpenAI API Key:"),g.red("Not set")),console.log(g.gray(" Set with: rapidkit config set-api-key"));console.log(g.cyan("AI Features:"),t.aiEnabled!==false?g.green("Enabled"):g.red("Disabled")),console.log(g.gray(`
|
|
4128
|
+
\u{1F4C1} Config file: ${yt()}
|
|
4129
|
+
`));}),o.command("remove-api-key").description("Remove stored OpenAI API key").action(async()=>{if(!ue().openaiApiKey){console.log(g.yellow(`
|
|
4118
4130
|
\u26A0\uFE0F No API key is currently stored
|
|
4119
|
-
`));return}(await(await
|
|
4131
|
+
`));return}(await(await io()).prompt([{type:"confirm",name:"confirm",message:"Are you sure you want to remove your OpenAI API key?",default:false}])).confirm?(Ke({openaiApiKey:void 0}),console.log(g.green(`
|
|
4120
4132
|
\u2705 API key removed successfully
|
|
4121
4133
|
`))):console.log(g.gray(`
|
|
4122
4134
|
Cancelled
|
|
4123
4135
|
`));}),o.command("ai <action>").description("Enable or disable AI features (enable|disable)").action(t=>{t!=="enable"&&t!=="disable"&&(console.log(g.red(`
|
|
4124
4136
|
\u274C Invalid action: ${t}`)),console.log(g.gray(`Use: rapidkit config ai enable|disable
|
|
4125
|
-
`)),process.exit(1));let
|
|
4126
|
-
\u2705 AI features ${
|
|
4127
|
-
`));});}var Ge=null,$e=false,it=null;async function sn(){return it||(it=(await import('openai')).default),it}function Ut(){$e=true;}function Wt(e){let t=new Array(1536),n=0;for(let r=0;r<e.length;r++)n=(n<<5)-n+e.charCodeAt(r),n=n&n;for(let r=0;r<1536;r++)n=n*1664525+1013904223&4294967295,t[r]=n/4294967295*2-1;let i=Math.sqrt(t.reduce((r,a)=>r+a*a,0));return t.map(r=>r/i)}async function De(e){let o=await sn();Ge=new o({apiKey:e});}function Bt(){if(!Ge)throw new Error("OpenAI client not initialized. Call initOpenAI() first with your API key.");return Ge}async function Jt(e){return $e?Wt(e):(await Bt().embeddings.create({model:"text-embedding-3-small",input:e,encoding_format:"float"})).data[0].embedding}async function zt(e){return $e?e.map(Wt):(await Bt().embeddings.create({model:"text-embedding-3-small",input:e,encoding_format:"float"})).data.map(n=>n.embedding)}function Yt(){return Ge!==null}function Qt(){return $e}var ln=promisify(exec),Zt=[{id:"authentication-core",name:"Authentication Core",category:"auth",description:"Complete authentication system with password hashing, JWT tokens, OAuth 2.0, and secure session management",longDescription:"Production-ready authentication with bcrypt password hashing, JWT access/refresh tokens, OAuth 2.0 providers (Google, GitHub, etc), rate limiting, and security best practices.",keywords:["auth","login","password","jwt","oauth","token","authentication","security","signin","signup"],framework:"both",dependencies:[],useCases:["User login and logout","Password reset flow","OAuth social login (Google, GitHub)","JWT authentication","Secure session management","Token refresh","Rate limiting"]},{id:"users-core",name:"Users Core",category:"auth",description:"User management system with profiles, roles, permissions, and user CRUD operations",longDescription:"Complete user management with user profiles, role-based access control (RBAC), permissions, user search, soft delete, and audit trails.",keywords:["user","profile","role","permission","rbac","management","admin","accounts"],framework:"both",dependencies:["authentication-core"],useCases:["User registration","User profile management","Role management (admin, user, etc)","Permission system","User administration dashboard","Soft delete users"]},{id:"session-management",name:"Session Management",category:"auth",description:"Secure session handling with Redis storage, session rotation, and device tracking",longDescription:"Advanced session management with Redis-backed storage, automatic session rotation, device fingerprinting, IP tracking, and session revocation.",keywords:["session","redis","cookie","storage","device","tracking"],framework:"both",dependencies:["authentication-core","redis-cache"],useCases:["User session management","Remember me functionality","Device tracking","Session security","Logout from all devices","Session expiration"]},{id:"db-postgres",name:"PostgreSQL",category:"database",description:"PostgreSQL integration with async SQLAlchemy, migrations, connection pooling, and query optimization",longDescription:"Production-ready PostgreSQL with async SQLAlchemy 2.0, Alembic migrations, connection pooling, query optimization, JSON support, and full-text search.",keywords:["postgres","postgresql","database","sql","sqlalchemy","migration","orm","relational"],framework:"both",dependencies:[],useCases:["Relational database","Complex SQL queries","Database transactions","Data integrity","Production-grade database","ACID compliance"]},{id:"db-mongodb",name:"MongoDB",category:"database",description:"MongoDB integration with Motor async driver, schema validation, and aggregation pipelines",longDescription:"Async MongoDB with Motor driver, Pydantic schema validation, aggregation pipelines, indexes, and Atlas integration.",keywords:["mongodb","mongo","nosql","document","database","motor"],framework:"both",dependencies:[],useCases:["Document storage","Flexible schema","Real-time data","JSON documents","Unstructured data","Analytics"]},{id:"stripe-payment",name:"Stripe Payment",category:"payment",description:"Stripe integration with payment intents, subscriptions, webhooks, and customer portal",longDescription:"Complete Stripe integration with Payment Intents API, subscription management, automatic webhooks, customer portal, refunds, and SCA compliance.",keywords:["stripe","payment","subscription","billing","checkout","webhook","credit card"],framework:"both",dependencies:[],useCases:["Accept credit card payments","Subscription billing","One-time payments","Checkout flow","Payment webhooks","Refunds and disputes"]},{id:"email",name:"Email",category:"communication",description:"Email sending with templates, SMTP/SendGrid/AWS SES support, and queue management",longDescription:"Production email system with Jinja2 templates, multiple providers (SMTP, SendGrid, AWS SES), queue management, retry logic, and bounce handling.",keywords:["email","mail","smtp","sendgrid","ses","template","notification"],framework:"both",dependencies:[],useCases:["Welcome emails","Password reset emails","Notifications","Marketing emails","Transactional emails","Email templates"]},{id:"sms",name:"SMS",category:"communication",description:"SMS sending with Twilio, verification codes, and delivery tracking",longDescription:"SMS integration with Twilio, verification codes, two-factor authentication, delivery tracking, and international support.",keywords:["sms","twilio","text","message","2fa","verification","otp"],framework:"both",dependencies:[],useCases:["2FA verification codes","SMS notifications","Phone verification","OTP generation","SMS alerts"]},{id:"redis-cache",name:"Redis Cache",category:"infrastructure",description:"Redis caching with decorators, TTL management, and cache invalidation patterns",longDescription:"Redis integration with async client, caching decorators, TTL management, cache invalidation, pub/sub, and rate limiting.",keywords:["redis","cache","memory","performance","speed","pubsub"],framework:"both",dependencies:[],useCases:["API response caching","Session storage","Rate limiting","Real-time features","Performance optimization","Pub/sub messaging"]},{id:"celery",name:"Celery",category:"infrastructure",description:"Background task processing with Celery, periodic tasks, and monitoring",longDescription:"Celery task queue with Redis/RabbitMQ backend, periodic tasks (cron), task monitoring, retry logic, and failure handling.",keywords:["celery","task","background","queue","async","worker","job","cron"],framework:"fastapi",dependencies:["redis-cache"],useCases:["Background email sending","Data processing","Report generation","Scheduled tasks","Long-running jobs"]},{id:"storage",name:"Storage",category:"infrastructure",description:"File storage with S3, local filesystem, and image processing",longDescription:"Unified storage interface for AWS S3, local files, image resizing, format conversion, CDN integration, and presigned URLs.",keywords:["storage","s3","file","upload","image","cdn","aws"],framework:"both",dependencies:[],useCases:["File uploads","Image storage","Document management","Profile pictures","Media files","CDN integration"]}],se=null,Xt=0,pn=300*1e3;function un(e){return {id:e.name||e.id||e.module_id||"",name:e.display_name||e.name||"",category:gn(e.category||"infrastructure"),description:e.description||e.summary||"",longDescription:e.long_description||e.description||"",keywords:e.keywords||e.tags||[],framework:mn(e.framework),dependencies:e.dependencies||[],useCases:e.use_cases||e.useCases||[]}}function gn(e){return {auth:"auth",authentication:"auth",database:"database",payment:"payment",billing:"payment",communication:"communication",infrastructure:"infrastructure",security:"security",analytics:"analytics"}[e.toLowerCase()]||"infrastructure"}function mn(e){if(!e)return "both";if(typeof e=="string"){if(e.toLowerCase().includes("fastapi"))return "fastapi";if(e.toLowerCase().includes("nest"))return "nestjs"}return "both"}async function fn(){try{let{stdout:e}=await ln("rapidkit modules list --json-schema 1",{timeout:1e4,maxBuffer:10485760}),o=e.match(/\{[\s\S]*\}/),t=o?o[0]:e,n=JSON.parse(t),i=[];return Array.isArray(n)?i=n:n.modules&&Array.isArray(n.modules)?i=n.modules:n.data&&Array.isArray(n.data)&&(i=n.data),i.map(un).filter(r=>r.id&&r.name)}catch(e){return e.code==="ENOENT"?console.warn("\u26A0\uFE0F RapidKit Python Core not found in PATH"):e.killed?console.warn("\u26A0\uFE0F Python Core command timed out"):console.warn("\u26A0\uFE0F Failed to fetch modules from Python Core:",e.message),console.warn(" Using fallback module catalog (11 modules)"),Zt}}async function qe(){let e=Date.now();return se&&e-Xt<pn||(se=await fn(),Xt=e,se.length===0&&(console.warn("\u26A0\uFE0F No modules found, using fallback catalog"),se=Zt)),se}var wn=fileURLToPath(import.meta.url),to=h.dirname(wn),he=null;function yn(){if(he)return he;let e=[h.join(to,"../../data/modules-embeddings.json"),h.join(to,"../data/modules-embeddings.json"),h.join(process.cwd(),"data/modules-embeddings.json")],o=null;for(let i of e)if(P.existsSync(i)){o=i;break}if(!o)throw new Error("embeddings file not found");let t=P.readFileSync(o,"utf-8"),n=JSON.parse(t);return Array.isArray(n)?he={model:"mock-or-text-embedding-3-small",dimension:n[0]?.embedding?.length||1536,generated_at:new Date().toISOString(),modules:n}:he=n,he}function vn(e,o){if(e.length!==o.length)throw new Error("Vectors must have the same length");let t=0,n=0,i=0;for(let a=0;a<e.length;a++)t+=e[a]*o[a],n+=e[a]*e[a],i+=o[a]*o[a];let r=Math.sqrt(n)*Math.sqrt(i);return r===0?0:t/r}function bn(e,o){let t=o.toLowerCase(),n=e.keywords.filter(i=>t.includes(i)||i.includes(t));return n.length>0?`Matches: ${n.slice(0,3).join(", ")}`:`Relevant for: ${e.useCases[0]}`}async function oo(e,o=5){let t=yn(),n=await qe(),i=await Jt(e),r=t.modules.map(a=>{let c=n.find(d=>d.id===a.id);if(!c)return null;let s=vn(i,a.embedding);return {module:c,score:s,reason:bn(c,e)}}).filter(a=>a!==null);return r.sort((a,c)=>c.score-a.score),r.slice(0,o)}var Sn=fileURLToPath(import.meta.url),ro=h.dirname(Sn);async function no(){return (await import('inquirer')).default}function xn(){return [h.join(ro,"../../data/modules-embeddings.json"),h.join(ro,"../data/modules-embeddings.json"),h.join(process.cwd(),"data/modules-embeddings.json")]}function io(){let e=xn();for(let o of e)if(P.existsSync(o))try{let t=JSON.parse(P.readFileSync(o,"utf-8")),n=Array.isArray(t)?t:t.modules||[];return {exists:true,path:o,moduleCount:n.length,generatedAt:t.generated_at||null}}catch{continue}return {exists:false,path:null,moduleCount:0,generatedAt:null}}async function Le(e=true,o){try{if(!Yt()&&!Qt())return console.log(g.red(`
|
|
4137
|
+
`)),process.exit(1));let r=t==="enable";Ke({aiEnabled:r}),console.log(g.green(`
|
|
4138
|
+
\u2705 AI features ${r?"enabled":"disabled"}
|
|
4139
|
+
`));});}var Ue=null,Ve=false,vt=null;async function Nn(){return vt||(vt=(await import('openai')).default),vt}function ao(){Ve=true;}function co(e){let t=new Array(1536),r=0;for(let n=0;n<e.length;n++)r=(r<<5)-r+e.charCodeAt(n),r=r&r;for(let n=0;n<1536;n++)r=r*1664525+1013904223&4294967295,t[n]=r/4294967295*2-1;let i=Math.sqrt(t.reduce((n,s)=>n+s*s,0));return t.map(n=>n/i)}async function We(e){let o=await Nn();Ue=new o({apiKey:e});}function lo(){if(!Ue)throw new Error("OpenAI client not initialized. Call initOpenAI() first with your API key.");return Ue}async function po(e){return Ve?co(e):(await lo().embeddings.create({model:"text-embedding-3-small",input:e,encoding_format:"float"})).data[0].embedding}async function uo(e){return Ve?e.map(co):(await lo().embeddings.create({model:"text-embedding-3-small",input:e,encoding_format:"float"})).data.map(r=>r.embedding)}function go(){return Ue!==null}function mo(){return Ve}var $n=promisify(exec),ho=[{id:"authentication-core",name:"Authentication Core",category:"auth",description:"Complete authentication system with password hashing, JWT tokens, OAuth 2.0, and secure session management",longDescription:"Production-ready authentication with bcrypt password hashing, JWT access/refresh tokens, OAuth 2.0 providers (Google, GitHub, etc), rate limiting, and security best practices.",keywords:["auth","login","password","jwt","oauth","token","authentication","security","signin","signup"],framework:"both",dependencies:[],useCases:["User login and logout","Password reset flow","OAuth social login (Google, GitHub)","JWT authentication","Secure session management","Token refresh","Rate limiting"]},{id:"users-core",name:"Users Core",category:"auth",description:"User management system with profiles, roles, permissions, and user CRUD operations",longDescription:"Complete user management with user profiles, role-based access control (RBAC), permissions, user search, soft delete, and audit trails.",keywords:["user","profile","role","permission","rbac","management","admin","accounts"],framework:"both",dependencies:["authentication-core"],useCases:["User registration","User profile management","Role management (admin, user, etc)","Permission system","User administration dashboard","Soft delete users"]},{id:"session-management",name:"Session Management",category:"auth",description:"Secure session handling with Redis storage, session rotation, and device tracking",longDescription:"Advanced session management with Redis-backed storage, automatic session rotation, device fingerprinting, IP tracking, and session revocation.",keywords:["session","redis","cookie","storage","device","tracking"],framework:"both",dependencies:["authentication-core","redis-cache"],useCases:["User session management","Remember me functionality","Device tracking","Session security","Logout from all devices","Session expiration"]},{id:"db-postgres",name:"PostgreSQL",category:"database",description:"PostgreSQL integration with async SQLAlchemy, migrations, connection pooling, and query optimization",longDescription:"Production-ready PostgreSQL with async SQLAlchemy 2.0, Alembic migrations, connection pooling, query optimization, JSON support, and full-text search.",keywords:["postgres","postgresql","database","sql","sqlalchemy","migration","orm","relational"],framework:"both",dependencies:[],useCases:["Relational database","Complex SQL queries","Database transactions","Data integrity","Production-grade database","ACID compliance"]},{id:"db-mongodb",name:"MongoDB",category:"database",description:"MongoDB integration with Motor async driver, schema validation, and aggregation pipelines",longDescription:"Async MongoDB with Motor driver, Pydantic schema validation, aggregation pipelines, indexes, and Atlas integration.",keywords:["mongodb","mongo","nosql","document","database","motor"],framework:"both",dependencies:[],useCases:["Document storage","Flexible schema","Real-time data","JSON documents","Unstructured data","Analytics"]},{id:"stripe-payment",name:"Stripe Payment",category:"payment",description:"Stripe integration with payment intents, subscriptions, webhooks, and customer portal",longDescription:"Complete Stripe integration with Payment Intents API, subscription management, automatic webhooks, customer portal, refunds, and SCA compliance.",keywords:["stripe","payment","subscription","billing","checkout","webhook","credit card"],framework:"both",dependencies:[],useCases:["Accept credit card payments","Subscription billing","One-time payments","Checkout flow","Payment webhooks","Refunds and disputes"]},{id:"email",name:"Email",category:"communication",description:"Email sending with templates, SMTP/SendGrid/AWS SES support, and queue management",longDescription:"Production email system with Jinja2 templates, multiple providers (SMTP, SendGrid, AWS SES), queue management, retry logic, and bounce handling.",keywords:["email","mail","smtp","sendgrid","ses","template","notification"],framework:"both",dependencies:[],useCases:["Welcome emails","Password reset emails","Notifications","Marketing emails","Transactional emails","Email templates"]},{id:"sms",name:"SMS",category:"communication",description:"SMS sending with Twilio, verification codes, and delivery tracking",longDescription:"SMS integration with Twilio, verification codes, two-factor authentication, delivery tracking, and international support.",keywords:["sms","twilio","text","message","2fa","verification","otp"],framework:"both",dependencies:[],useCases:["2FA verification codes","SMS notifications","Phone verification","OTP generation","SMS alerts"]},{id:"redis-cache",name:"Redis Cache",category:"infrastructure",description:"Redis caching with decorators, TTL management, and cache invalidation patterns",longDescription:"Redis integration with async client, caching decorators, TTL management, cache invalidation, pub/sub, and rate limiting.",keywords:["redis","cache","memory","performance","speed","pubsub"],framework:"both",dependencies:[],useCases:["API response caching","Session storage","Rate limiting","Real-time features","Performance optimization","Pub/sub messaging"]},{id:"celery",name:"Celery",category:"infrastructure",description:"Background task processing with Celery, periodic tasks, and monitoring",longDescription:"Celery task queue with Redis/RabbitMQ backend, periodic tasks (cron), task monitoring, retry logic, and failure handling.",keywords:["celery","task","background","queue","async","worker","job","cron"],framework:"fastapi",dependencies:["redis-cache"],useCases:["Background email sending","Data processing","Report generation","Scheduled tasks","Long-running jobs"]},{id:"storage",name:"Storage",category:"infrastructure",description:"File storage with S3, local filesystem, and image processing",longDescription:"Unified storage interface for AWS S3, local files, image resizing, format conversion, CDN integration, and presigned URLs.",keywords:["storage","s3","file","upload","image","cdn","aws"],framework:"both",dependencies:[],useCases:["File uploads","Image storage","Document management","Profile pictures","Media files","CDN integration"]}],ge=null,fo=0,Dn=300*1e3;function Mn(e){return {id:e.name||e.id||e.module_id||"",name:e.display_name||e.name||"",category:qn(e.category||"infrastructure"),description:e.description||e.summary||"",longDescription:e.long_description||e.description||"",keywords:e.keywords||e.tags||[],framework:Ln(e.framework),dependencies:e.dependencies||[],useCases:e.use_cases||e.useCases||[]}}function qn(e){return {auth:"auth",authentication:"auth",database:"database",payment:"payment",billing:"payment",communication:"communication",infrastructure:"infrastructure",security:"security",analytics:"analytics"}[e.toLowerCase()]||"infrastructure"}function Ln(e){if(!e)return "both";if(typeof e=="string"){if(e.toLowerCase().includes("fastapi"))return "fastapi";if(e.toLowerCase().includes("nest"))return "nestjs"}return "both"}async function Fn(){try{let{stdout:e}=await $n("rapidkit modules list --json-schema 1",{timeout:1e4,maxBuffer:10485760}),o=e.match(/\{[\s\S]*\}/),t=o?o[0]:e,r=JSON.parse(t),i=[];return Array.isArray(r)?i=r:r.modules&&Array.isArray(r.modules)?i=r.modules:r.data&&Array.isArray(r.data)&&(i=r.data),i.map(Mn).filter(n=>n.id&&n.name)}catch(e){return e.code==="ENOENT"?console.warn("\u26A0\uFE0F RapidKit Python Core not found in PATH"):e.killed?console.warn("\u26A0\uFE0F Python Core command timed out"):console.warn("\u26A0\uFE0F Failed to fetch modules from Python Core:",e.message),console.warn(" Using fallback module catalog (11 modules)"),ho}}async function Be(){let e=Date.now();return ge&&e-fo<Dn||(ge=await Fn(),fo=e,ge.length===0&&(console.warn("\u26A0\uFE0F No modules found, using fallback catalog"),ge=ho)),ge}var Kn=fileURLToPath(import.meta.url),yo=v.dirname(Kn),Ce=null;function Un(){if(Ce)return Ce;let e=[v.join(yo,"../../data/modules-embeddings.json"),v.join(yo,"../data/modules-embeddings.json"),v.join(process.cwd(),"data/modules-embeddings.json")],o=null;for(let i of e)if(A.existsSync(i)){o=i;break}if(!o)throw new Error("embeddings file not found");let t=A.readFileSync(o,"utf-8"),r=JSON.parse(t);return Array.isArray(r)?Ce={model:"mock-or-text-embedding-3-small",dimension:r[0]?.embedding?.length||1536,generated_at:new Date().toISOString(),modules:r}:Ce=r,Ce}function Vn(e,o){if(e.length!==o.length)throw new Error("Vectors must have the same length");let t=0,r=0,i=0;for(let s=0;s<e.length;s++)t+=e[s]*o[s],r+=e[s]*e[s],i+=o[s]*o[s];let n=Math.sqrt(r)*Math.sqrt(i);return n===0?0:t/n}function Wn(e,o){let t=o.toLowerCase(),r=e.keywords.filter(i=>t.includes(i)||i.includes(t));return r.length>0?`Matches: ${r.slice(0,3).join(", ")}`:`Relevant for: ${e.useCases[0]}`}async function vo(e,o=5){let t=Un(),r=await Be(),i=await po(e),n=t.modules.map(s=>{let c=r.find(l=>l.id===s.id);if(!c)return null;let a=Vn(i,s.embedding);return {module:c,score:a,reason:Wn(c,e)}}).filter(s=>s!==null);return n.sort((s,c)=>c.score-s.score),n.slice(0,o)}var zn=fileURLToPath(import.meta.url),bo=v.dirname(zn);async function ko(){return (await import('inquirer')).default}function Yn(){return [v.join(bo,"../../data/modules-embeddings.json"),v.join(bo,"../data/modules-embeddings.json"),v.join(process.cwd(),"data/modules-embeddings.json")]}function Ro(){let e=Yn();for(let o of e)if(A.existsSync(o))try{let t=JSON.parse(A.readFileSync(o,"utf-8")),r=Array.isArray(t)?t:t.modules||[];return {exists:true,path:o,moduleCount:r.length,generatedAt:t.generated_at||null}}catch{continue}return {exists:false,path:null,moduleCount:0,generatedAt:null}}async function ze(e=true,o){try{if(!go()&&!mo())return console.log(g.red(`
|
|
4128
4140
|
\u274C OpenAI not initialized`)),console.log(g.yellow("Please set your API key:")),console.log(g.white(" rapidkit config set-api-key")),console.log(g.gray(` OR set: export OPENAI_API_KEY="sk-..."
|
|
4129
4141
|
`)),false;console.log(g.blue(`
|
|
4130
4142
|
\u{1F916} Generating AI embeddings for RapidKit modules...
|
|
4131
|
-
`)),console.log(g.gray("\u{1F4E1} Fetching modules from RapidKit..."));let t=await
|
|
4132
|
-
`));let
|
|
4133
|
-
`)),e){let
|
|
4143
|
+
`)),console.log(g.gray("\u{1F4E1} Fetching modules from RapidKit..."));let t=await Be();console.log(g.green(`\u2713 Found ${t.length} modules
|
|
4144
|
+
`));let r=t.length*50/1e6*.02;if(console.log(g.cyan(`\u{1F4B0} Estimated cost: ~$${r.toFixed(3)}`)),console.log(g.gray(` (Based on ${t.length} modules at $0.02/1M tokens)
|
|
4145
|
+
`)),e){let s=await ko(),{confirm:c}=await s.prompt([{type:"confirm",name:"confirm",message:"Generate embeddings now?",default:true}]);if(!c)return console.log(g.yellow(`
|
|
4134
4146
|
\u26A0\uFE0F Embeddings generation cancelled
|
|
4135
|
-
`)),false}let i=t.map(
|
|
4136
|
-
\u2705 Embeddings generated successfully!`)),console.log(g.gray(`\u{1F4C1} Saved to: ${
|
|
4137
|
-
`)),true}catch(
|
|
4147
|
+
`)),false}let i=t.map(s=>`${s.name}. ${s.description}. ${s.longDescription}. Keywords: ${s.keywords.join(", ")}. Use cases: ${s.useCases.join(", ")}.`),n=pt(`Generating embeddings for ${t.length} modules...`).start();try{let s=await uo(i);n.succeed(`Generated embeddings for ${t.length} modules`);let c={model:"text-embedding-3-small",dimension:s[0].length,generated_at:new Date().toISOString(),modules:t.map((d,p)=>({id:d.id,name:d.name,embedding:s[p]}))},a=o||v.join(process.cwd(),"data","modules-embeddings.json"),l=v.dirname(a);return A.existsSync(l)||A.mkdirSync(l,{recursive:true}),A.writeFileSync(a,JSON.stringify(c,null,2)),console.log(g.green(`
|
|
4148
|
+
\u2705 Embeddings generated successfully!`)),console.log(g.gray(`\u{1F4C1} Saved to: ${a}`)),console.log(g.gray(`\u{1F4CA} Size: ${t.length} modules, ${s[0].length} dimensions
|
|
4149
|
+
`)),true}catch(s){return n.fail("Failed to generate embeddings"),s.message?.includes("429")?(console.log(g.red(`
|
|
4138
4150
|
\u274C OpenAI API quota exceeded`)),console.log(g.yellow(`Please check your billing: https://platform.openai.com/account/billing
|
|
4139
|
-
`))):
|
|
4151
|
+
`))):s.message?.includes("401")?(console.log(g.red(`
|
|
4140
4152
|
\u274C Invalid API key`)),console.log(g.yellow("Please set a valid API key:")),console.log(g.white(` rapidkit config set-api-key
|
|
4141
4153
|
`))):console.log(g.red(`
|
|
4142
|
-
\u274C Error: ${
|
|
4154
|
+
\u274C Error: ${s.message}
|
|
4143
4155
|
`)),false}}catch(t){return console.log(g.red(`
|
|
4144
4156
|
\u274C Failed to generate embeddings: ${t.message}
|
|
4145
|
-
`)),false}}async function
|
|
4157
|
+
`)),false}}async function xo(e=true){if(Ro().exists)return true;if(console.log(g.yellow(`
|
|
4146
4158
|
\u26A0\uFE0F Module embeddings not found`)),console.log(g.gray(`AI recommendations require embeddings to be generated.
|
|
4147
4159
|
`)),!e)return console.log(g.red("\u274C Cannot generate embeddings in non-interactive mode")),console.log(g.white(`Run: rapidkit ai generate-embeddings
|
|
4148
|
-
`)),false;let t=await
|
|
4160
|
+
`)),false;let t=await ko(),{action:r}=await t.prompt([{type:"list",name:"action",message:"What would you like to do?",choices:[{name:"\u{1F680} Generate embeddings now (requires OpenAI API key)",value:"generate"},{name:"\u{1F4DD} Show me how to generate them manually",value:"manual"},{name:"\u274C Cancel",value:"cancel"}]}]);return r==="generate"?await ze(true):(r==="manual"&&(console.log(g.cyan(`
|
|
4149
4161
|
\u{1F4DD} To generate embeddings manually:
|
|
4150
4162
|
`)),console.log(g.white("1. Get OpenAI API key from: https://platform.openai.com/api-keys")),console.log(g.white("2. Set the API key:")),console.log(g.gray(" rapidkit config set-api-key")),console.log(g.gray(` OR: export OPENAI_API_KEY="sk-..."
|
|
4151
4163
|
`)),console.log(g.white("3. Generate embeddings:")),console.log(g.gray(` rapidkit ai generate-embeddings
|
|
4152
4164
|
`)),console.log(g.cyan(`\u{1F4B0} Cost: ~$0.50 one-time
|
|
4153
|
-
`))),false)}async function
|
|
4165
|
+
`))),false)}async function Co(){let e=Ro();return e.exists?(console.log(g.blue(`
|
|
4154
4166
|
\u{1F504} Updating embeddings...`)),console.log(g.gray(`Current: ${e.moduleCount} modules`)),console.log(g.gray(`Generated: ${e.generatedAt||"unknown"}
|
|
4155
|
-
`)),await
|
|
4167
|
+
`)),await ze(true,e.path)):(console.log(g.yellow(`
|
|
4156
4168
|
\u26A0\uFE0F No existing embeddings found`)),console.log(g.gray(`Use: rapidkit ai generate-embeddings
|
|
4157
|
-
`)),false)}async function
|
|
4169
|
+
`)),false)}async function So(){return (await import('inquirer')).default}function _o(e){let o=e.command("ai").description("AI-powered features");o.command("recommend").description("Get AI-powered module recommendations").argument("[query]",'What do you want to build? (e.g., "user authentication with email")').option("-n, --number <count>","Number of recommendations","5").option("--json","Output as JSON").action(async(t,r)=>{try{wt()||(console.log(g.yellow(`
|
|
4158
4170
|
\u26A0\uFE0F AI features are disabled`)),console.log(g.gray(`Enable with: rapidkit config ai enable
|
|
4159
|
-
`)),process.exit(1));let i=
|
|
4171
|
+
`)),process.exit(1));let i=xe();i?await We(i):(console.log(g.yellow(`
|
|
4160
4172
|
\u26A0\uFE0F OpenAI API key not configured - using MOCK MODE for testing
|
|
4161
4173
|
`)),console.log(g.gray("\u{1F4DD} Note: Mock embeddings provide approximate results for testing.")),console.log(g.gray(` For production, configure your OpenAI API key:
|
|
4162
4174
|
`)),console.log(g.white(" 1. Get your key from: https://platform.openai.com/api-keys")),console.log(g.white(" 2. Configure it: rapidkit config set-api-key")),console.log(g.gray(` OR set: export OPENAI_API_KEY="sk-proj-..."
|
|
4163
|
-
`)),
|
|
4175
|
+
`)),ao());let n=t;n||(n=(await(await So()).prompt([{type:"input",name:"query",message:"\u{1F916} What do you want to build?",validate:x=>x.length===0?"Please enter a description":x.length<3?"Please be more specific (at least 3 characters)":true}])).query),r.json||console.log(g.blue(`
|
|
4164
4176
|
\u{1F916} Analyzing your request...
|
|
4165
|
-
`)),await
|
|
4177
|
+
`)),await xo(!r.json)||(console.log(g.yellow(`
|
|
4166
4178
|
\u26A0\uFE0F Cannot proceed without embeddings
|
|
4167
|
-
`)),process.exit(1));let c=parseInt(
|
|
4179
|
+
`)),process.exit(1));let c=parseInt(r.number,10),a=await vo(n,c);if(a.length===0||a[0].score<.3)if(console.log(g.yellow(`
|
|
4168
4180
|
\u26A0\uFE0F No matching modules found in RapidKit registry.
|
|
4169
4181
|
`)),console.log(g.cyan(`\u{1F4A1} Options:
|
|
4170
4182
|
`)),console.log(g.white("1. Create custom module:")),console.log(g.gray(" rapidkit modules scaffold <name> --category <category>")),console.log(g.gray(` Example: rapidkit modules scaffold blockchain-integration --category integrations
|
|
4171
4183
|
`)),console.log(g.white("2. Search with different keywords")),console.log(g.gray(` Try more general terms (e.g., "storage" instead of "blockchain")
|
|
4172
4184
|
`)),console.log(g.white("3. Request feature:")),console.log(g.gray(` https://github.com/getrapidkit/rapidkit/issues
|
|
4173
|
-
`)),
|
|
4174
|
-
`));else return;if(
|
|
4175
|
-
`)),
|
|
4176
|
-
`));let
|
|
4177
|
-
\u{1F4E6} Installing ${
|
|
4178
|
-
`)),console.log(g.gray(`Command: rapidkit add module ${
|
|
4185
|
+
`)),a.length>0)console.log(g.yellow(`\u26A0\uFE0F Low confidence matches found:
|
|
4186
|
+
`));else return;if(r.json){console.log(JSON.stringify({query:n,recommendations:a},null,2));return}console.log(g.green.bold(`\u{1F4E6} Recommended Modules:
|
|
4187
|
+
`)),a.forEach((u,h)=>{let x=(u.score*100).toFixed(1),y=u.score>.8?" \u2B50":"";console.log(g.bold(`${h+1}. ${u.module.name}${y}`)),console.log(g.gray(` ${u.module.description}`)),console.log(g.cyan(` Match: ${x}%`)+g.gray(` - ${u.reason}`)),console.log(g.yellow(` Category: ${u.module.category}`)),u.module.dependencies.length>0&&console.log(g.magenta(` Requires: ${u.module.dependencies.join(", ")}`)),console.log();});let l=a.slice(0,3).map(u=>u.module.id);console.log(g.cyan("\u{1F4A1} Quick install (top 3):")),console.log(g.white(` rapidkit add module ${l.join(" ")}
|
|
4188
|
+
`));let d=await So(),{shouldInstall:p}=await d.prompt([{type:"confirm",name:"shouldInstall",message:"Would you like to install these modules now?",default:false}]);if(p){let{selectedModules:u}=await d.prompt([{type:"checkbox",name:"selectedModules",message:"Select modules to install:",choices:a.map(h=>({name:`${h.module.name} - ${h.module.description}`,value:h.module.id,checked:h.score>.7}))}]);u.length>0?(console.log(g.blue(`
|
|
4189
|
+
\u{1F4E6} Installing ${u.length} modules...
|
|
4190
|
+
`)),console.log(g.gray(`Command: rapidkit add module ${u.join(" ")}`)),console.log(g.yellow(`
|
|
4179
4191
|
\u26A0\uFE0F Note: Module installation not yet implemented`)),console.log(g.gray(`Coming soon in next version!
|
|
4180
4192
|
`))):console.log(g.gray(`
|
|
4181
4193
|
No modules selected
|
|
@@ -4184,59 +4196,60 @@ No modules selected
|
|
|
4184
4196
|
\u{1F4A1} Your API key may be invalid or expired`)),console.log(g.cyan(` Update it: rapidkit config set-api-key
|
|
4185
4197
|
`))):i.message.includes("embeddings file not found")&&(console.log(g.yellow(`
|
|
4186
4198
|
\u{1F4A1} Module embeddings not generated yet`)),console.log(g.cyan(" Generate them (one-time):")),console.log(g.white(" cd rapidkit-npm")),console.log(g.white(' export OPENAI_API_KEY="sk-proj-..."')),console.log(g.white(` npx tsx src/ai/generate-embeddings.ts
|
|
4187
|
-
`))),process.exit(1);}}),o.command("info").description("Show AI features information").action(()=>{let t=
|
|
4199
|
+
`))),process.exit(1);}}),o.command("info").description("Show AI features information").action(()=>{let t=xe(),r=wt();console.log(g.bold(`
|
|
4188
4200
|
\u{1F916} RapidKit AI Features
|
|
4189
|
-
`)),console.log(g.cyan("Status:"),
|
|
4201
|
+
`)),console.log(g.cyan("Status:"),r?g.green("Enabled"):g.red("Disabled")),console.log(g.cyan("API Key:"),t?g.green("Configured \u2713"):g.red("Not configured \u2717")),console.log(g.bold(`
|
|
4190
4202
|
\u{1F4E6} Available Features:
|
|
4191
4203
|
`)),console.log(g.white("\u2022 Module Recommender")+g.gray(" - AI-powered module suggestions")),console.log(g.gray(' Usage: rapidkit ai recommend "I need authentication"')),console.log(g.bold(`
|
|
4192
4204
|
\u{1F4B0} Pricing:
|
|
4193
4205
|
`)),console.log(g.white("\u2022 Per query: ~$0.0002")+g.gray(" (practically free)")),console.log(g.white("\u2022 100 queries: ~$0.02")+g.gray(" (2 cents)")),console.log(g.white("\u2022 1000 queries: ~$0.20")+g.gray(" (20 cents)")),console.log(g.bold(`
|
|
4194
4206
|
\u{1F680} Getting Started:
|
|
4195
|
-
`)),t?(console.log(g.green("\u2713 You're all set!")),console.log(g.white(' Try: rapidkit ai recommend "user authentication"'))):(console.log(g.white("1. Get OpenAI API key: https://platform.openai.com/api-keys")),console.log(g.white("2. Configure: rapidkit config set-api-key")),console.log(g.white('3. Try: rapidkit ai recommend "user authentication"'))),console.log();}),o.command("generate-embeddings").description("Generate AI embeddings for all modules (one-time setup)").option("--force","Force regeneration even if embeddings exist").action(async()=>{try{let t=
|
|
4207
|
+
`)),t?(console.log(g.green("\u2713 You're all set!")),console.log(g.white(' Try: rapidkit ai recommend "user authentication"'))):(console.log(g.white("1. Get OpenAI API key: https://platform.openai.com/api-keys")),console.log(g.white("2. Configure: rapidkit config set-api-key")),console.log(g.white('3. Try: rapidkit ai recommend "user authentication"'))),console.log();}),o.command("generate-embeddings").description("Generate AI embeddings for all modules (one-time setup)").option("--force","Force regeneration even if embeddings exist").action(async()=>{try{let t=xe();t||(console.log(g.red(`
|
|
4196
4208
|
\u274C OpenAI API key not configured
|
|
4197
4209
|
`)),console.log(g.cyan(`To generate embeddings, you need an OpenAI API key:
|
|
4198
4210
|
`)),console.log(g.white("1. Get your key from: https://platform.openai.com/api-keys")),console.log(g.white("2. Configure it: rapidkit config set-api-key")),console.log(g.gray(`
|
|
4199
4211
|
OR set environment variable:`)),console.log(g.white(` export OPENAI_API_KEY="sk-proj-..."
|
|
4200
|
-
`)),process.exit(1)),
|
|
4201
|
-
`))),process.exit(
|
|
4212
|
+
`)),process.exit(1)),We(t);let r=await ze(true);r&&(console.log(g.green("\u2705 Ready to use AI recommendations!")),console.log(g.cyan(`Try: rapidkit ai recommend "authentication"
|
|
4213
|
+
`))),process.exit(r?0:1);}catch(t){a.error("Failed to generate embeddings:",t.message),process.exit(1);}}),o.command("update-embeddings").description("Update existing embeddings with latest modules").action(async()=>{try{let t=xe();t||(console.log(g.red(`
|
|
4202
4214
|
\u274C OpenAI API key not configured
|
|
4203
4215
|
`)),console.log(g.white(`Set your API key: rapidkit config set-api-key
|
|
4204
|
-
`)),process.exit(1)),
|
|
4205
|
-
`),1;let
|
|
4206
|
-
`),1;await
|
|
4207
|
-
`),1}}async function
|
|
4208
|
-
`),1;let
|
|
4209
|
-
`),1;await
|
|
4210
|
-
`),1}}async function
|
|
4216
|
+
`)),process.exit(1)),We(t);let r=await Co();process.exit(r?0:1);}catch(t){a.error("Failed to update embeddings:",t.message),process.exit(1);}});}var Ye=class{constructor(o){this.runCommand=o;}runtime="go";async run(o,t,r){return {exitCode:await this.runCommand(o,t,r)}}async checkPrereqs(){return this.run("go",["version"],process.cwd())}async initProject(o){return this.run("go",["mod","tidy"],o)}async runDev(o){let t=v.join(o,"Makefile");return A.existsSync(t)?this.run("make",["run"],o):this.run("go",["run","./main.go"],o)}async runTest(o){return this.run("go",["test","./..."],o)}async runBuild(o){return this.run("go",["build","./..."],o)}async runStart(o){let t=v.join(o,"server");return A.existsSync(t)?this.run(t,[],o):this.run("go",["run","./main.go"],o)}async doctorHints(o){return ["Install Go from https://go.dev/dl/ if missing.","Run go mod tidy when dependencies are out of sync.","Use make run for hot-reload if Makefile exists."]}};var Qe=class{constructor(o){this.runCommand=o;}runtime="node";async run(o,t,r){return {exitCode:await this.runCommand(o,t,r)}}detectPackageManager(o){return A.existsSync(v.join(o,"pnpm-lock.yaml"))?"pnpm":A.existsSync(v.join(o,"yarn.lock"))?"yarn":"npm"}scriptArgs(o,t){return o==="npm"?["run",t]:["run",t]}async checkPrereqs(){return this.run("node",["--version"],process.cwd())}async initProject(o){let t=this.detectPackageManager(o);return this.run(t,["install"],o)}async runDev(o){let t=this.detectPackageManager(o);return this.run(t,this.scriptArgs(t,"dev"),o)}async runTest(o){let t=this.detectPackageManager(o);return this.run(t,this.scriptArgs(t,"test"),o)}async runBuild(o){let t=this.detectPackageManager(o);return this.run(t,this.scriptArgs(t,"build"),o)}async runStart(o){let t=this.detectPackageManager(o);return this.run(t,this.scriptArgs(t,"start"),o)}async doctorHints(o){return ["Install Node.js LTS and ensure node/npm are on PATH.","Use lockfiles (package-lock.json, pnpm-lock.yaml, yarn.lock) for deterministic installs.","Run install before dev/test/build if dependencies changed."]}};var Xe=class{constructor(o){this.runCore=o;}runtime="python";async run(o,t){return {exitCode:await this.runCore(o,t)}}async checkPrereqs(){return this.run(["doctor","--json"],process.cwd())}async initProject(o){return this.run(["init"],o)}async runDev(o){return this.run(["dev"],o)}async runTest(o){return this.run(["test"],o)}async runBuild(o){return this.run(["build"],o)}async runStart(o){return this.run(["start"],o)}async doctorHints(o){return ["Run rapidkit doctor --workspace for a full workspace scan.","Use rapidkit init after adding or changing modules.","Use workspace launcher ./rapidkit to avoid environment drift."]}};function Q(){return process.env.RAPIDKIT_ENABLE_RUNTIME_ADAPTERS==="1"}function fe(e,o){return e==="go"?new Ye((t,r,i)=>o.runCommandInCwd(t,r,i)):e==="node"?new Qe((t,r,i)=>o.runCommandInCwd(t,r,i)):new Xe((t,r)=>o.runCoreRapidkit(t,{cwd:r}))}var Ze=v.join(qo__default.homedir(),".rapidkit","cache"),Ao=1440*60*1e3,et=class e{static instance;memoryCache=new Map;constructor(){}static getInstance(){return e.instance||(e.instance=new e),e.instance}getCacheKey(o){return createHash("md5").update(o).digest("hex")}getCachePath(o){return v.join(Ze,`${this.getCacheKey(o)}.json`)}async get(o,t="1.0"){let r=this.memoryCache.get(o);if(r&&r.version===t&&Date.now()-r.timestamp<Ao)return a.debug(`Cache hit (memory): ${o}`),r.data;try{let i=this.getCachePath(o),n=await promises.readFile(i,"utf-8"),s=JSON.parse(n);if(s.version===t&&Date.now()-s.timestamp<Ao)return a.debug(`Cache hit (disk): ${o}`),this.memoryCache.set(o,s),s.data;await promises.unlink(i).catch(()=>{});}catch{a.debug(`Cache miss: ${o}`);}return null}async set(o,t,r="1.0"){let i={data:t,timestamp:Date.now(),version:r};this.memoryCache.set(o,i);try{await promises.mkdir(Ze,{recursive:true});let n=this.getCachePath(o);await promises.writeFile(n,JSON.stringify(i),"utf-8"),a.debug(`Cache set: ${o}`);}catch(n){a.debug(`Cache write failed: ${o}`,n);}}async invalidate(o){this.memoryCache.delete(o);try{let t=this.getCachePath(o);await promises.unlink(t),a.debug(`Cache invalidated: ${o}`);}catch{}}async clear(){this.memoryCache.clear();try{let o=await promises.readdir(Ze);await Promise.all(o.map(t=>promises.unlink(v.join(Ze,t)))),a.debug("Cache cleared");}catch{}}};function ie(e){let o=e;for(;;){let t=v.join(o,".rapidkit","project.json");if(A.existsSync(t))try{return JSON.parse(A.readFileSync(t,"utf8"))}catch{return null}let r=v.dirname(o);if(r===o)break;o=r;}return null}function _e(e,o){let t=e?.runtime?.toLowerCase(),r=e?.kit_name?.toLowerCase(),i=A.existsSync(v.join(o,"go.mod"));return t==="go"||(r?.startsWith("gofiber")??false)||(r?.startsWith("gogin")??false)||i}function he(e,o){let t=e?.runtime?.toLowerCase(),r=e?.kit_name?.toLowerCase(),i=A.existsSync(v.join(o,"package.json"));return t==="node"||t==="typescript"||(r?.startsWith("nestjs")??false)||i}function tt(e,o){let t=e?.runtime?.toLowerCase(),r=e?.kit_name?.toLowerCase(),i=A.existsSync(v.join(o,"pyproject.toml")),n=A.existsSync(v.join(o,"requirements.txt"))||A.existsSync(v.join(o,"requirements.in"));return t==="python"||(r?.startsWith("fastapi")??false)||i||n}function kt(e){if(!e||typeof e!="object")return null;let o=e.code;return o==="PYTHON_NOT_FOUND"||o==="BRIDGE_VENV_BOOTSTRAP_FAILED"?o:null}function ei(e){let o=e.trim().toLowerCase();return o?o.startsWith("fastapi")?"fastapi":o.startsWith("nestjs")?"nestjs":null:null}function St(e){let o=e.trim().toLowerCase();return o.startsWith("gofiber")||o==="go"||o==="go.standard"||o==="fiber"}function ot(e){let o=e.trim().toLowerCase();return o.startsWith("gogin")||o==="gin"}function it(e,o){let t=e.indexOf(o);if(t>=0&&t+1<e.length)return e[t+1];let r=e.find(i=>i.startsWith(`${o}=`));if(r)return r.slice(o.length+1)}async function No(e){if(e[0]!=="create"||e[1]!=="project")return 1;let o=e[2],t=e[3];if(!o||!t)return process.stderr.write(`Usage: rapidkit create project gofiber.standard <name> [--output <dir>]
|
|
4217
|
+
`),1;let r=it(e,"--output")||process.cwd(),i=v.resolve(r,t),n=e.includes("--skip-git")||e.includes("--no-git");try{let{default:s}=await import('fs-extra');if(await s.ensureDir(v.dirname(i)),await s.pathExists(i))return process.stderr.write(`\u274C Directory "${i}" already exists
|
|
4218
|
+
`),1;await s.ensureDir(i),await gt(i,{project_name:t,module_path:t,skipGit:n});let c=ce(process.cwd());if(c){let{syncWorkspaceProjects:a}=await import('./workspace-LZZGJRGV.js');await a(c,true);}return 0}catch(s){return process.stderr.write(`RapidKit Go/Fiber generator failed: ${s?.message??s}
|
|
4219
|
+
`),1}}async function jo(e){if(e[0]!=="create"||e[1]!=="project")return 1;let o=e[2],t=e[3];if(!o||!t)return process.stderr.write(`Usage: rapidkit create project gogin.standard <name> [--output <dir>]
|
|
4220
|
+
`),1;let r=it(e,"--output")||process.cwd(),i=v.resolve(r,t),n=e.includes("--skip-git")||e.includes("--no-git");try{let{default:s}=await import('fs-extra');if(await s.ensureDir(v.dirname(i)),await s.pathExists(i))return process.stderr.write(`\u274C Directory "${i}" already exists
|
|
4221
|
+
`),1;await s.ensureDir(i),await mt(i,{project_name:t,module_path:t,skipGit:n});let c=ce(process.cwd());if(c){let{syncWorkspaceProjects:a}=await import('./workspace-LZZGJRGV.js');await a(c,true);}return 0}catch(s){return process.stderr.write(`RapidKit Go/Gin generator failed: ${s?.message??s}
|
|
4222
|
+
`),1}}async function Rt(e,o){if(e.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(e[0]!=="create")return 1;if(e[1]!=="project")return process.stderr.write(`RapidKit (npm) could not run the Python core engine for \`create\`.
|
|
4211
4223
|
Reason: ${o}.
|
|
4212
4224
|
Install Python 3.10+ to use the interactive wizard and full kit catalog.
|
|
4213
|
-
`),1;let i=e[2],
|
|
4225
|
+
`),1;let i=e[2],n=e[3];if(!i||!n)return process.stderr.write(`Usage: rapidkit create project <kit> <name> [--output <dir>]
|
|
4214
4226
|
Tip: offline fallback supports only fastapi* and nestjs* kits.
|
|
4215
|
-
`),1;let
|
|
4227
|
+
`),1;let s=ei(i);if(!s)return process.stderr.write(`RapidKit (npm) could not run the Python core engine to create this kit.
|
|
4216
4228
|
Reason: ${o}.
|
|
4217
4229
|
Requested kit: ${i}
|
|
4218
4230
|
Offline fallback only supports: fastapi.standard, nestjs.standard (and their shorthands).
|
|
4219
4231
|
Install Python 3.10+ to access all kits.
|
|
4220
|
-
`),1;let c=
|
|
4221
|
-
`),1;let
|
|
4222
|
-
`),1}}async function
|
|
4223
|
-
`),1;try{
|
|
4224
|
-
`),1;throw
|
|
4225
|
-
`),1;let
|
|
4232
|
+
`),1;let c=it(e,"--output")||process.cwd(),a=v.resolve(c,n),l=e.includes("--skip-git")||e.includes("--no-git"),d=e.includes("--skip-install");try{if(await R.ensureDir(v.dirname(a)),await R.pathExists(a))return process.stderr.write(`\u274C Directory "${a}" already exists
|
|
4233
|
+
`),1;let p="pip",u=ce(process.cwd());if(u)try{let{readWorkspaceMarker:h}=await import('./workspace-marker-IOPQ42A7.js'),x=await h(u);x?.metadata?.npm?.installMethod&&(p=x.metadata.npm.installMethod,console.log(`[DEBUG] Detected workspace engine: ${p}`));}catch(h){console.log("[DEBUG] Failed to read workspace marker:",h);}else console.log("[DEBUG] No workspace found, using default engine: pip");if(await R.ensureDir(a),await Wt(a,{project_name:n,template:s,kit_name:i,skipGit:l,skipInstall:d,engine:p}),u){let{syncWorkspaceProjects:h}=await import('./workspace-LZZGJRGV.js');await h(u,true);}return 0}catch(p){return process.stderr.write(`RapidKit (npm) offline fallback failed: ${p?.message??p}
|
|
4234
|
+
`),1}}async function ti(e){let o=new Set(["--yes","-y","--skip-git","--skip-install","--debug","--dry-run","--no-update-check","--create-workspace","--no-workspace"]);if(e[0]==="create"&&e[1]==="workspace")try{let t=e.includes("--yes")||e.includes("-y"),r=e.includes("--skip-git")||e.includes("--no-git"),i=e[2]&&!e[2].startsWith("-")?e[2]:void 0,n=it(e,"--install-method"),s=n==="poetry"||n==="venv"||n==="pipx"?n:void 0,c=i||(t?"my-workspace":(await ae.prompt([{type:"input",name:"workspaceName",message:"Workspace name:",default:"my-workspace"}])).workspaceName);if(!c||!c.trim())return process.stderr.write(`Workspace name is required.
|
|
4235
|
+
`),1;try{ct(c);}catch(p){if(p instanceof H)return process.stderr.write(`${p.message}
|
|
4236
|
+
`),1;throw p}let a=v.resolve(process.cwd(),c);if(await R.pathExists(a))return process.stderr.write(`\u274C Directory "${c}" already exists
|
|
4237
|
+
`),1;let l=await Z(),d=l.author||process.env.USER||"RapidKit User";if(!t){let p=await ae.prompt([{type:"input",name:"author",message:"Author name:",default:d}]);p.author?.trim()&&(d=p.author.trim());}return await Ge(c,{skipGit:r,yes:t,userConfig:{...l,author:d},installMethod:s}),0}catch(t){return process.stderr.write(`RapidKit (npm) failed to create workspace: ${t?.message??t}
|
|
4226
4238
|
`),1}try{if(e[0]==="create"&&e[1]==="project"){if(!e[2]||e[2].startsWith("-")){console.log(g.bold(`
|
|
4227
4239
|
\u{1F680} RapidKit
|
|
4228
|
-
`));let{kitChoice:
|
|
4229
|
-
`),a.debug(`Synced Python version ${
|
|
4230
|
-
`),1)}}if(e[0]==="create"&&e[1]!=="project")try{await c$1();let t=await d(e,{cwd:process.cwd()});if(t===0){let
|
|
4231
|
-
`),1)}return await c$1(),await d(e,{cwd:process.cwd()})}catch(t){let
|
|
4232
|
-
`),1)}}var
|
|
4233
|
-
`),1)}return 0}async function
|
|
4234
|
-
\u{1F439} Go project detected: ${
|
|
4235
|
-
`)),await
|
|
4240
|
+
`));let{kitChoice:a}=await ae.prompt([{type:"rawlist",name:"kitChoice",message:"Select a kit to scaffold:",choices:[{name:"fastapi \u2014 FastAPI Standard Kit",value:"fastapi.standard"},{name:"fastapi \u2014 FastAPI DDD Kit",value:"fastapi.ddd"},{name:"nestjs \u2014 NestJS Standard Kit",value:"nestjs.standard"},{name:"go/fiber \u2014 Go Fiber Standard Kit",value:"gofiber.standard"},{name:"go/gin \u2014 Go Gin Standard Kit",value:"gogin.standard"}]}]);if(St(a)||ot(a)){let{projectName:l}=await ae.prompt([{type:"input",name:"projectName",message:"Project name:",validate:p=>p.trim().length>0||"Project name is required"}]),d=e.slice(2).filter(p=>p.startsWith("-"));return ot(a)?await jo(["create","project",a,l.trim(),...d]):await No(["create","project",a,l.trim(),...d])}e.splice(2,0,a);}if(St(e[2]||""))return await No(e);if(ot(e[2]||""))return await jo(e);let t=e.includes("--create-workspace"),r=e.includes("--no-workspace"),i=e.includes("--yes")||e.includes("-y"),n=e.includes("--skip-git")||e.includes("--no-git");if(!!!rt(process.cwd())){if(t)await te(process.cwd(),{skipGit:n,yes:i,userConfig:await Z()});else if(!r)if(i)await te(process.cwd(),{skipGit:n,yes:true,userConfig:await Z()});else {let{createWs:a}=await ae.prompt([{type:"confirm",name:"createWs",message:"This project will be created outside a RapidKit workspace. Create and register a workspace here?",default:true}]);a&&await te(process.cwd(),{skipGit:n,yes:false,userConfig:await Z()});}}let c=e.filter(a=>{let l=a.split("=")[0];return !o.has(a)&&!o.has(l)});try{await c$1();let a$1=await d(c,{cwd:process.cwd()});if(a$1===0){let l=ce(process.cwd());if(l){try{let p=e[3];if(p){let u=e.indexOf("--output"),h=u>=0?e[u+1]:".",x=v.resolve(process.cwd(),h,p),y=v.join(l,".python-version"),C=v.join(x,".python-version");if(A.existsSync(y)&&A.existsSync(x)){let E=A.readFileSync(y,"utf-8");A.writeFileSync(C,E.trim()+`
|
|
4241
|
+
`),a.debug(`Synced Python version ${E.trim()} from workspace to ${p}`);}}}catch(p){a.debug("Could not sync Python version from workspace:",p);}let{syncWorkspaceProjects:d}=await import('./workspace-LZZGJRGV.js');await d(l,true);}}return a$1}catch(a){let l=kt(a);return l?await Rt(c,l):(process.stderr.write(`RapidKit (npm) failed to run the Python core engine: ${a?.message??a}
|
|
4242
|
+
`),1)}}if(e[0]==="create"&&e[1]!=="project")try{await c$1();let t=await d(e,{cwd:process.cwd()});if(t===0){let r=ce(process.cwd());if(r){let{syncWorkspaceProjects:i}=await import('./workspace-LZZGJRGV.js');await i(r,true);}}return t}catch(t){let r=kt(t);return r?await Rt(e,r):(process.stderr.write(`RapidKit (npm) failed to run the Python core engine: ${t?.message??t}
|
|
4243
|
+
`),1)}return await c$1(),await d(e,{cwd:process.cwd()})}catch(t){let r=kt(t);return r?await Rt(e,r):(process.stderr.write(`RapidKit (npm) failed to run the Python core engine: ${t?.message??t}
|
|
4244
|
+
`),1)}}var Go=["init","dev","start","build","test","docs","lint","format","create","help","--help","-h"];function Do(e){let o=e;for(;;){let t=v.join(o,".rapidkit","context.json");if(A.existsSync(t))return t;let r=v.dirname(o);if(r===o)break;o=r;}return null}function rt(e){let o=e;for(;;){let t=v.join(o,".rapidkit-workspace");if(A.existsSync(t))return t;let r=v.dirname(o);if(r===o)break;o=r;}return null}function ce(e){let o=e;for(;;){let t=v.join(o,".rapidkit-workspace");if(A.existsSync(t))return o;let r=v.dirname(o);if(r===o)break;o=r;}return null}async function J(e,o,t){return await new Promise(r=>{let i=spawn(e,o,{stdio:"inherit",cwd:t,shell:process.platform==="win32"});i.on("close",n=>r(n??1)),i.on("error",()=>r(1));})}async function $o(e){let o="poetry";try{let{readWorkspaceMarker:t}=await import('./workspace-marker-IOPQ42A7.js'),i=(await t(e))?.metadata?.npm?.installMethod;(i==="poetry"||i==="venv"||i==="pipx"||i==="pip")&&(o=i);}catch{}if(o==="poetry")return await J("poetry",["install","--no-root"],e);if(o==="venv"){let t=v.join(e,".venv",process.platform==="win32"?"Scripts":"bin",process.platform==="win32"?"python.exe":"python");return await R.pathExists(t)?await J(t,["-m","pip","install","--upgrade","rapidkit-core"],e):(process.stderr.write(`Workspace virtualenv not found (.venv).
|
|
4245
|
+
`),1)}return 0}async function oi(e){let o=await A.promises.readdir(e,{withFileTypes:true}),t=[];for(let r of o){if(!r.isDirectory()||r.name.startsWith("."))continue;let i=v.join(e,r.name),n=v.join(i,".rapidkit","context.json"),s=v.join(i,".rapidkit","project.json");(await R.pathExists(n)||await R.pathExists(s))&&t.push(i);}return t}function ri(e){let o="my-workspace",t=1;for(;;){let r=t===1?o:`${o}-${t}`,i=v.join(e,r);if(!A.existsSync(i))return {name:r,targetPath:i};t+=1;}}async function xt(e){return Q()?(await fe("go",{runCommandInCwd:J,runCoreRapidkit:d}).initProject(e)).exitCode:(console.log(g.cyan(`
|
|
4246
|
+
\u{1F439} Go project detected: ${v.basename(e)}`)),console.log(g.gray(`Running go mod tidy\u2026
|
|
4247
|
+
`)),await J("go",["mod","tidy"],e))}async function ni(e){if(Q())return (await fe("go",{runCommandInCwd:J,runCoreRapidkit:d}).runDev(e)).exitCode;let o=v.join(e,"Makefile");return A.existsSync(o)?(console.log(g.cyan(`
|
|
4236
4248
|
\u{1F439} Starting Go/Fiber dev server (make run)\u2026
|
|
4237
|
-
`)),await
|
|
4249
|
+
`)),await J("make",["run"],e)):(console.log(g.cyan(`
|
|
4238
4250
|
\u{1F439} Starting Go/Fiber dev server (go run ./main.go)\u2026
|
|
4239
|
-
`)),await
|
|
4251
|
+
`)),await J("go",["run","./main.go"],e))}async function Pe(e,o){if(!Q())return 1;let t=fe("node",{runCommandInCwd:J,runCoreRapidkit:d});return e==="init"?(await t.initProject(o)).exitCode:e==="dev"?(await t.runDev(o)).exitCode:e==="test"?(await t.runTest(o)).exitCode:e==="build"?(await t.runBuild(o)).exitCode:(await t.runStart(o)).exitCode}async function ii(e,o=Mo){let t=["init",...e.slice(1)];return await o(t)}async function si(e){let o=(e[1]||"").toLowerCase();if(!o||!["python","node","go"].includes(o))return console.log(g.yellow("Usage: rapidkit setup <python|node|go>")),1;if(!Q())return console.log(g.yellow("Runtime adapters are disabled. Set RAPIDKIT_ENABLE_RUNTIME_ADAPTERS=1 to use setup.")),1;let t=fe(o,{runCommandInCwd:J,runCoreRapidkit:d}),r=await t.checkPrereqs(),i=await t.doctorHints(process.cwd());if(r.exitCode===0?console.log(g.green(`\u2705 ${o} prerequisites look good.`)):console.log(g.red(`\u274C ${o} prerequisites check failed.`)),i.length>0){console.log(g.gray(`
|
|
4252
|
+
Hints:`));for(let n of i)console.log(g.gray(`- ${n}`));}return r.exitCode}async function ai(e){let o=(e[1]||"status").toLowerCase(),t=et.getInstance();return o==="clear"||o==="prune"||o==="repair"?(await t.clear(),console.log(g.green(`\u2705 Cache ${o} completed.`)),0):o==="status"?(console.log(g.cyan("RapidKit cache is enabled (memory + disk).")),console.log(g.gray("Use: rapidkit cache clear|prune|repair")),0):(console.log(g.yellow("Usage: rapidkit cache <status|clear|prune|repair>")),1)}async function Mo(e){let o=process.cwd(),t=Q(),r=t?fe("python",{runCommandInCwd:J,runCoreRapidkit:d}):null;if(e.length>1){let a=v.resolve(o,e[1]),l=ie(a);return _e(l,a)?await xt(a):t&&he(l,a)?await Pe("init",a):r&&tt(l,a)?(await r.initProject(a)).exitCode:await d(e,{cwd:o})}let i=ie(o);if(_e(i,o))return await xt(o);if(t&&he(i,o))return await Pe("init",o);if(r&&tt(i,o))return (await r.initProject(o)).exitCode;let n=ce(o),s=Do(o),c=s?v.dirname(v.dirname(s)):null;if(c&&c!==n)return r?(await r.initProject(c)).exitCode:await d(["init"],{cwd:c});if(n&&o===n){let a=await $o(n);if(a!==0)return a;let l=await oi(n);for(let d$1 of l){let p=ie(d$1);if(_e(p,d$1)){let u=await xt(d$1);if(u!==0)return u}else {if(t&&he(p,d$1)){let h=await Pe("init",d$1);if(h!==0)return h;continue}if(r&&tt(p,d$1)){let h=await r.initProject(d$1);if(h.exitCode!==0)return h.exitCode;continue}let u=await d(["init"],{cwd:d$1});if(u!==0)return u}}return 0}if(!n){let a=await Z(),{name:l}=ri(o);await Ge(l,{yes:true,userConfig:a});let d=v.join(o,l);return await $o(d)}return await d(e,{cwd:o})}async function ci(){let e=process.cwd(),o=process.argv.slice(2),t=A.existsSync(v.join(e,".rapidkit-workspace")),r=A.existsSync(v.join(e,".rapidkit","project.json"));if(o[0]==="create"||o[0]==="init"&&t&&!r)return false;try{let d$1=o[0],p=!d$1||d$1==="--help"||d$1==="-h"||d$1==="help";if(rt(e)&&p){let h=await d(d$1?["--help"]:[],{cwd:e});process.exit(h);}}catch{}try{let d$1=o[0],p=d$1==="shell"&&o[1]==="activate",u=d$1==="create",h=await Gt(e,{cwd:e,timeoutMs:1200});if(h.ok&&h.data?.isRapidkitProject&&h.data.engine==="python"&&!p&&!u){let x=await d(process.argv.slice(2),{cwd:e});process.exit(x);}}catch{}let i=Do(e),n=process.platform==="win32",s=n?[v.join(e,"rapidkit.cmd"),v.join(e,"rapidkit"),v.join(e,".rapidkit","rapidkit.cmd"),v.join(e,".rapidkit","rapidkit")]:[v.join(e,"rapidkit"),v.join(e,".rapidkit","rapidkit")],c=null;for(let d of s)if(await R.pathExists(d)){c=d;break}let a$1=o[0],l=a$1==="create";if(a$1==="init"&&t&&!r)return false;if(c&&a$1&&Go.includes(a$1)&&!l){a.debug(`Delegating to local CLI: ${c} ${o.join(" ")}`);let d=spawn(c,o,{stdio:"inherit",cwd:e,shell:n});return d.on("close",p=>{process.exit(p??0);}),d.on("error",p=>{a.error(`Failed to run local rapidkit: ${p.message}`),process.exit(1);}),true}if(i&&await R.pathExists(i))try{if((await R.readJson(i)).engine==="pip"){let p=o[0],h=process.platform==="win32"?[v.join(e,"rapidkit.cmd"),v.join(e,"rapidkit"),v.join(e,".rapidkit","rapidkit.cmd"),v.join(e,".rapidkit","rapidkit")]:[v.join(e,"rapidkit"),v.join(e,".rapidkit","rapidkit")],x=null;for(let C of h)if(await R.pathExists(C)){x=C;break}if(x&&p&&Go.includes(p)){a.debug(`Delegating to local CLI (early detection): ${x} ${o.join(" ")}`);let C=spawn(x,o,{stdio:"inherit",cwd:e});return C.on("close",E=>process.exit(E??0)),C.on("error",E=>{a.error(`Failed to run local rapidkit: ${E.message}`),process.exit(1);}),true}if(p==="shell"&&o[1]==="activate"){let C=`# RapidKit: activation snippet - eval "$(rapidkit shell activate)"
|
|
4240
4253
|
VENV='.venv'
|
|
4241
4254
|
if [ -f "$VENV/bin/activate" ]; then
|
|
4242
4255
|
. "$VENV/bin/activate"
|
|
@@ -4247,43 +4260,43 @@ export RAPIDKIT_PROJECT_ROOT="$(pwd)"
|
|
|
4247
4260
|
export PATH="$(pwd)/.rapidkit:$(pwd):$PATH"
|
|
4248
4261
|
`;console.log(g.green.bold(`
|
|
4249
4262
|
\u2705 Activation snippet \u2014 run the following to activate this project in your current shell:
|
|
4250
|
-
`)),console.log(
|
|
4263
|
+
`)),console.log(C),console.log(g.gray(`
|
|
4251
4264
|
\u{1F4A1} After activation you can run: rapidkit dev
|
|
4252
|
-
`)),process.exit(0);}let
|
|
4265
|
+
`)),process.exit(0);}let y=await d(o,{cwd:e});process.exit(y);}}catch{}return false}var X=null,nt=false,z=new Command;async function li(e){if(e.length===0)return false;let o=e[0],t=e[1];if(o==="shell"&&t==="activate"||o==="workspace"||o==="doctor"||o==="bootstrap"||o==="setup"||o==="cache"||o==="ai"||o==="config")return false;if(e.includes("--tui"))return true;if(o==="--help"||o==="-h"||o==="help"||o==="--version"||o==="-V"||e.includes("--template")||e.includes("-t"))return false;let r=new Set(["--yes","-y","--skip-git","--skip-install","--debug","--dry-run","--no-update-check","--create-workspace","--no-workspace"]);if(e.some(n=>r.has(n)))return false;let i=await h();return i?i.has(o):!!(a$1.has(o)||e.length>1)}z.name("rapidkit").description("Create RapidKit workspaces and projects").version(c());z.addHelpText("beforeAll",`RapidKit
|
|
4253
4266
|
|
|
4254
4267
|
Global CLI
|
|
4255
4268
|
Create RapidKit workspaces and projects
|
|
4256
4269
|
|
|
4257
4270
|
Global Engine Commands
|
|
4258
4271
|
Access engine-level commands when inside a RapidKit workspace or via the core bridge
|
|
4259
|
-
`);
|
|
4272
|
+
`);z.addHelpText("afterAll",`
|
|
4260
4273
|
Project Commands
|
|
4261
4274
|
rapidkit create
|
|
4262
4275
|
rapidkit init
|
|
4263
4276
|
rapidkit dev
|
|
4264
4277
|
|
|
4265
4278
|
Use "rapidkit help <command>" for more information.
|
|
4266
|
-
`);
|
|
4279
|
+
`);z.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("--install-method <method>","Installation method: poetry, venv, or pipx").choices(["poetry","venv","pipx"]).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(e$1,o)=>{try{o.debug&&(a.setDebug(true),a.debug("Debug mode enabled"));let t=await Z();a.debug("User config loaded",t);let r=await Nt();a.debug("RapidKit config loaded",r);let i=jt(t,r,{author:o.author,skipGit:o.skipGit});a.debug("Merged config",i),o.updateCheck!==false&&await b(),console.log(g.blue.bold(`
|
|
4267
4280
|
\u{1F680} Welcome to RapidKit!
|
|
4268
|
-
`)),e$1||(
|
|
4281
|
+
`)),e$1||(pi(),process.exit(0));try{ct(e$1);}catch(c){throw c instanceof H&&(a.error(`
|
|
4269
4282
|
\u274C ${c.message}`),c.details&&a.warn(`\u{1F4A1} ${c.details}
|
|
4270
|
-
`),process.exit(1)),c}let
|
|
4283
|
+
`),process.exit(1)),c}let n=v.resolve(process.cwd(),e$1);X=n,await R.pathExists(n)&&(a.error(`
|
|
4271
4284
|
\u274C Directory "${e$1}" already exists`),console.log(g.cyan(`
|
|
4272
4285
|
\u{1F4A1} Choose a different name or delete the existing directory.
|
|
4273
|
-
`)),process.exit(1));let
|
|
4286
|
+
`)),process.exit(1));let s=!!o.template;if(o.dryRun){console.log(g.cyan(`
|
|
4274
4287
|
\u{1F50D} Dry-run mode - showing what would be created:
|
|
4275
|
-
`)),console.log(g.white("\u{1F4C2} Path:"),
|
|
4276
|
-
`)),
|
|
4277
|
-
`),a.debug(`Synced Python version ${
|
|
4278
|
-
`),a.debug(`Re-synced Python version ${
|
|
4288
|
+
`)),console.log(g.white("\u{1F4C2} Path:"),n),console.log(g.white("\u{1F4E6} Type:"),s?`Project (${o.template})`:"Workspace"),console.log();return}if(!o.yes&&!s?await ae.prompt([{type:"input",name:"author",message:"Author name:",default:process.env.USER||"RapidKit User"}]):o.yes&&console.log(g.gray(`Using default values (--yes flag)
|
|
4289
|
+
`)),s){let c=String(o.template||"").trim(),a$1=c.toLowerCase(),l=a$1==="fastapi"?"fastapi.standard":a$1==="nestjs"?"nestjs.standard":a$1==="go"||a$1==="fiber"?"gofiber.standard":a$1==="gin"?"gogin.standard":c;if(St(l)){let x=v.resolve(process.cwd(),e$1);await gt(x,{project_name:e$1,module_path:e$1,skipGit:o.skipGit});return}if(ot(l)){let x=v.resolve(process.cwd(),e$1);await mt(x,{project_name:e$1,module_path:e$1,skipGit:o.skipGit});return}if(!!!rt(process.cwd())){if(o.createWorkspace)await te(process.cwd(),{skipGit:o.skipGit,yes:o.yes,userConfig:t});else if(!o.noWorkspace)if(o.yes)await te(process.cwd(),{skipGit:o.skipGit,yes:true,userConfig:t});else {let{createWs:x}=await ae.prompt([{type:"confirm",name:"createWs",message:"This project will be created outside a RapidKit workspace. Create and register a workspace here?",default:true}]);x&&await te(process.cwd(),{skipGit:o.skipGit,yes:false,userConfig:t});}}let p=["create","project",l,e$1,"--output",process.cwd(),"--install-essentials"],u=await e(p,{cwd:process.cwd()});u!==0&&process.exit(u);let h=rt(process.cwd());if(h){let x=v.dirname(h),y=v.join(x,".python-version"),C=v.join(n,".python-version");try{if(await R.pathExists(y)){let E=A.readFileSync(y,"utf-8");A.writeFileSync(C,E.trim()+`
|
|
4290
|
+
`),a.debug(`Synced Python version ${E.trim()} from workspace to project`);}}catch(E){a.debug("Could not sync Python version from workspace:",E);}}if(!o.skipInstall){let x=await d(["init",n],{cwd:process.cwd()});if(x!==0&&process.exit(x),h){let y=v.dirname(h),C=v.join(y,".python-version"),E=v.join(n,".python-version");try{if(await R.pathExists(C)){let q=A.readFileSync(C,"utf-8");A.writeFileSync(E,q.trim()+`
|
|
4291
|
+
`),a.debug(`Re-synced Python version ${q.trim()} after init`);}}catch(q){a.debug("Could not re-sync Python version after init:",q);}}}}else await Ge(e$1,{skipGit:o.skipGit,dryRun:o.dryRun,yes:o.yes,userConfig:i,installMethod:o.installMethod});}catch(t){t instanceof H?(a.error(`
|
|
4279
4292
|
\u274C ${t.message}`),t.details&&a.warn(`\u{1F4A1} ${t.details}`),a.debug("Error code:",t.code)):(a.error(`
|
|
4280
|
-
\u274C An unexpected error occurred:`),console.error(t)),process.exit(1);}finally{
|
|
4293
|
+
\u274C An unexpected error occurred:`),console.error(t)),process.exit(1);}finally{X=null;}});_o(z);so(z);z.command("shell <action>").description("Shell helpers (activate virtualenv in current shell)").action(async e=>{e!=="activate"&&(console.log(g.red(`Unknown shell command: ${e}`)),process.exit(1));let o=process.cwd();function t(a){let l=a;for(;;){let d=v.join(l,".rapidkit","context.json");if(A.existsSync(d))return d;let p=v.dirname(l);if(p===l)break;l=p;}return null}let r=t(o);function i(a){let l=a;for(;;){let d=v.join(l,".venv"),p=v.join(l,".rapidkit","activate");if(A.existsSync(p)||A.existsSync(d))return {venv:d,activateFile:p};let u=v.dirname(l);if(u===l)break;l=u;}return null}let n=i(o);!r&&!n&&(console.log(g.yellow("No RapidKit project found in this directory")),process.exit(1));let s;n&&A.existsSync(n.activateFile)?s=n.activateFile:n&&A.existsSync(n.venv)?s=process.platform==="win32"?v.join(n.venv,"Scripts","activate"):v.join(n.venv,"bin","activate"):(console.log(g.yellow("No virtual environment found")),process.exit(1));let c=process.platform==="win32";console.log(c?`call "${s}"`:`. "${s}"`);});z.command("doctor").description("\u{1FA7A} Check RapidKit environment health").option("--workspace","Check entire workspace (including all projects)").option("--json","Output results in JSON format (for CI/CD pipelines)").option("--fix","Automatically fix common issues (with confirmation)").action(async e=>{await ro(e);});z.command("workspace <action>").description("Manage RapidKit workspaces (list, sync)").action(async e=>{if(e==="list"){let{listWorkspaces:o}=await import('./workspace-LZZGJRGV.js');await o();}else if(e==="sync"){let o=ce(process.cwd());o||(console.log(g.red("\u274C Not inside a RapidKit workspace")),console.log(g.gray("\u{1F4A1} Run this command from within a workspace directory")),process.exit(1));let{syncWorkspaceProjects:t}=await import('./workspace-LZZGJRGV.js');console.log(g.cyan(`\u{1F4C2} Scanning workspace: ${v.basename(o)}`)),await t(o);}else console.log(g.red(`Unknown workspace action: ${e}`)),console.log(g.gray("Available: list, sync")),process.exit(1);});function pi(){console.log(g.white(`Usage:
|
|
4281
4294
|
`)),console.log(g.cyan(" npx rapidkit <workspace-name> [options]")),console.log(g.cyan(` npx rapidkit create <...>
|
|
4282
4295
|
`)),console.log(g.bold("Recommended workflow:")),console.log(g.cyan(" npx rapidkit my-workspace")),console.log(g.cyan(" cd my-workspace")),console.log(g.cyan(" npx rapidkit create project fastapi.standard my-api --output .")),console.log(g.cyan(" cd my-api")),console.log(g.cyan(` npx rapidkit init && npx rapidkit dev
|
|
4283
4296
|
`)),console.log(g.bold("Options (workspace creation):")),console.log(g.gray(" -y, --yes Skip prompts and use defaults")),console.log(g.gray(" --skip-git Skip git initialization")),console.log(g.gray(" --debug Enable debug logging")),console.log(g.gray(" --dry-run Show what would be created")),console.log(g.gray(" --create-workspace When creating a project outside a workspace: create and register a workspace in the current directory")),console.log(g.gray(" --no-workspace When creating a project outside a workspace: do not create a workspace")),console.log(g.gray(` --no-update-check Skip checking for updates
|
|
4284
4297
|
`)),console.log(g.gray(`Tip: set RAPIDKIT_SHOW_LEGACY=1 to show legacy template flags in help.
|
|
4285
|
-
`));}process.on("SIGINT",async()=>{if(!
|
|
4298
|
+
`));}process.on("SIGINT",async()=>{if(!nt){if(nt=true,console.log(g.yellow(`
|
|
4286
4299
|
|
|
4287
|
-
\u26A0\uFE0F Interrupted by user`)),
|
|
4288
|
-
`),o[0]==="create"){let
|
|
4289
|
-
`),t){let
|
|
4300
|
+
\u26A0\uFE0F Interrupted by user`)),X&&await R.pathExists(X)){console.log(g.gray("Cleaning up partial installation..."));try{await R.remove(X),console.log(g.green("\u2713 Cleanup complete"));}catch(e){a.debug("Cleanup failed:",e);}}process.exit(130);}});process.on("SIGTERM",async()=>{if(!nt){if(nt=true,a.debug("Received SIGTERM"),X&&await R.pathExists(X))try{await R.remove(X);}catch(e){a.debug("Cleanup failed:",e);}process.exit(143);}});var ui=process.env.VITEST==="true"||process.env.VITEST==="1"||process.env.NODE_ENV==="test",gi=(()=>{let e=process.argv[1];if(!e)return false;try{return A.realpathSync(e)===A.realpathSync(fileURLToPath(import.meta.url))}catch{return v.resolve(e)===v.resolve(fileURLToPath(import.meta.url))}})(),mi=!ui||gi;mi&&ci().then(async e=>{if(!e){let o=process.argv.slice(2);if(process.env.RAPIDKIT_NPM_DEBUG_ARGS==="1"&&process.stderr.write(`[rapidkit-npm] argv=${JSON.stringify(o)}
|
|
4301
|
+
`),o[0]==="create"){let r=await ti(o);process.exit(r);}if(o[0]==="init"){let r=await Mo(o);process.exit(r);}if(o[0]==="bootstrap"){let r=await ii(o);process.exit(r);}if(o[0]==="setup"){let r=await si(o);process.exit(r);}if(o[0]==="cache"){let r=await ai(o);process.exit(r);}if(o[0]==="dev"){let r=ie(process.cwd());if(_e(r,process.cwd())){let i=await ni(process.cwd());process.exit(i);}if(Q()&&he(r,process.cwd())){let i=await Pe("dev",process.cwd());process.exit(i);}}if((o[0]==="test"||o[0]==="build"||o[0]==="start")&&Q()){let r=ie(process.cwd());if(he(r,process.cwd())){let i=await Pe(o[0],process.cwd());process.exit(i);}}if(o[0]==="add"||o[0]==="module"&&o[1]==="add"){let r=ie(process.cwd());(r?.runtime==="go"||r?.module_support===false)&&(console.error(g.red("\u274C RapidKit modules are not available for Go projects.")),console.error(g.gray(" The module system requires Python and is only supported for FastAPI and NestJS projects.")),process.exit(1));}let t=await li(o);if(process.env.RAPIDKIT_NPM_DEBUG_ARGS==="1"&&process.stderr.write(`[rapidkit-npm] shouldForwardToCore=${t}
|
|
4302
|
+
`),t){let r=await d(o,{cwd:process.cwd()});process.exit(r);}z.parse();}});export{ii as handleBootstrapCommand,ai as handleCacheCommand,ti as handleCreateOrFallback,Mo as handleInitCommand,si as handleSetupCommand,li as shouldForwardToCore};
|