rapidkit 0.11.2 → 0.12.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (47) hide show
  1. package/README.md +99 -408
  2. package/dist/index.js +508 -279
  3. package/dist/package.json +1 -1
  4. package/package.json +1 -1
  5. package/templates/generator.js +175 -0
  6. package/templates/kits/fastapi-standard/.rapidkit/__init__.py.j2 +1 -0
  7. package/templates/kits/fastapi-standard/.rapidkit/activate.j2 +24 -0
  8. package/templates/kits/fastapi-standard/.rapidkit/cli.py.j2 +257 -0
  9. package/templates/kits/fastapi-standard/.rapidkit/project.json.j2 +7 -0
  10. package/templates/kits/fastapi-standard/.rapidkit/rapidkit.j2 +98 -0
  11. package/templates/kits/fastapi-standard/Makefile.j2 +41 -0
  12. package/templates/kits/fastapi-standard/README.md.j2 +4 -4
  13. package/templates/kits/fastapi-standard/pyproject.toml.j2 +1 -0
  14. package/templates/kits/fastapi-standard/rapidkit.j2 +50 -0
  15. package/templates/kits/fastapi-standard/src/main.py.j2 +15 -12
  16. package/templates/kits/nestjs-standard/.env.example.j2 +16 -0
  17. package/templates/kits/nestjs-standard/.eslintrc.js.j2 +25 -0
  18. package/templates/kits/nestjs-standard/.gitignore.j2 +26 -0
  19. package/templates/kits/nestjs-standard/.node-version.j2 +1 -0
  20. package/templates/kits/nestjs-standard/.nvmrc.j2 +1 -0
  21. package/templates/kits/nestjs-standard/.prettierrc.j2 +7 -0
  22. package/templates/kits/nestjs-standard/.rapidkit/activate.j2 +25 -0
  23. package/templates/kits/nestjs-standard/.rapidkit/project.json.j2 +7 -0
  24. package/templates/kits/nestjs-standard/.rapidkit/rapidkit.j2 +227 -0
  25. package/templates/kits/nestjs-standard/README.md.j2 +97 -0
  26. package/templates/kits/nestjs-standard/jest.config.ts.j2 +21 -0
  27. package/templates/kits/nestjs-standard/nest-cli.json.j2 +10 -0
  28. package/templates/kits/nestjs-standard/package.json.j2 +75 -0
  29. package/templates/kits/nestjs-standard/rapidkit.j2 +5 -0
  30. package/templates/kits/nestjs-standard/src/app.controller.ts.j2 +12 -0
  31. package/templates/kits/nestjs-standard/src/app.module.ts.j2 +23 -0
  32. package/templates/kits/nestjs-standard/src/app.service.ts.j2 +11 -0
  33. package/templates/kits/nestjs-standard/src/config/configuration.ts.j2 +9 -0
  34. package/templates/kits/nestjs-standard/src/config/index.ts.j2 +2 -0
  35. package/templates/kits/nestjs-standard/src/config/validation.ts.j2 +11 -0
  36. package/templates/kits/nestjs-standard/src/examples/dto/create-note.dto.ts.j2 +11 -0
  37. package/templates/kits/nestjs-standard/src/examples/examples.controller.ts.j2 +24 -0
  38. package/templates/kits/nestjs-standard/src/examples/examples.module.ts.j2 +10 -0
  39. package/templates/kits/nestjs-standard/src/examples/examples.service.ts.j2 +33 -0
  40. package/templates/kits/nestjs-standard/src/main.ts.j2 +51 -0
  41. package/templates/kits/nestjs-standard/src/modules/index.ts.j2 +3 -0
  42. package/templates/kits/nestjs-standard/test/app.controller.spec.ts.j2 +22 -0
  43. package/templates/kits/nestjs-standard/test/app.e2e-spec.ts.j2 +48 -0
  44. package/templates/kits/nestjs-standard/test/examples.controller.spec.ts.j2 +28 -0
  45. package/templates/kits/nestjs-standard/test/jest-e2e.json.j2 +15 -0
  46. package/templates/kits/nestjs-standard/tsconfig.build.json.j2 +12 -0
  47. package/templates/kits/nestjs-standard/tsconfig.json.j2 +26 -0
package/dist/index.js CHANGED
@@ -1,276 +1,443 @@
1
1
  #!/usr/bin/env node
2
- import {Command}from'commander';import i from'chalk';import {readFileSync,promises}from'fs';import*as h from'fs-extra';import y,{dirname,join}from'path';import oe from'inquirer';import W from'ora';import {execa}from'execa';import ee from'os';import le from'nunjucks';import {fileURLToPath}from'url';import je from'validate-npm-package-name';var G=class{debugEnabled=false;setDebug(e){this.debugEnabled=e;}debug(e,...o){this.debugEnabled&&console.log(i.gray(`[DEBUG] ${e}`),...o);}info(e,...o){console.log(i.blue(e),...o);}success(e,...o){console.log(i.green(e),...o);}warn(e,...o){console.log(i.yellow(e),...o);}error(e,...o){console.error(i.red(e),...o);}step(e,o,r){console.log(i.cyan(`
3
- [${e}/${o}]`),i.white(r));}},s=new G;var te=".rapidkitrc.json";async function z(){let t=y.join(ee.homedir(),te);try{let e=await promises.readFile(t,"utf-8"),o=JSON.parse(e);return s.debug(`Loaded config from ${t}`),o}catch{return s.debug("No user config found, using defaults"),{}}}function F(t){return process.env.RAPIDKIT_DEV_PATH||t.testRapidKitPath||void 0}var g=class extends Error{constructor(o,r,n){super(o);this.code=r;this.details=n;this.name="RapidKitError",Error.captureStackTrace(this,this.constructor);}},b=class extends g{constructor(e,o){let r=o?`Python ${e}+ required, found ${o}`:`Python ${e}+ not found`;super(r,"PYTHON_NOT_FOUND","Please install Python from https://www.python.org/downloads/");}},$=class extends g{constructor(){super("Poetry is not installed","POETRY_NOT_FOUND","Install Poetry from https://python-poetry.org/docs/#installation");}},N=class extends g{constructor(){super("pipx is not installed","PIPX_NOT_FOUND","Install pipx from https://pypa.github.io/pipx/installation/");}},T=class extends g{constructor(e){super(`Directory "${e}" already exists`,"DIRECTORY_EXISTS","Please choose a different name or remove the existing directory");}},k=class extends g{constructor(e,o){super(`Invalid project name: "${e}"`,"INVALID_PROJECT_NAME",o);}},j=class extends g{constructor(e,o){let r=`Installation failed at: ${e}`,n=`${o.message}
4
-
5
- Troubleshooting:
6
- - Check your internet connection
7
- - Verify Python/Poetry installation
8
- - Try running with --debug flag for more details`;super(r,"INSTALLATION_ERROR",n);}},x=class extends g{constructor(){super("RapidKit Python package is not yet available on PyPI","RAPIDKIT_NOT_AVAILABLE",`Available options:
9
- 1. Demo mode: npx rapidkit my-workspace --demo
10
- 2. Test mode: npx rapidkit my-workspace --test-mode (requires local RapidKit)
11
- 3. Wait for official PyPI release (coming soon)`);}};async function U(t,e){let{skipGit:o=false,testMode:r=false,demoMode:n=false,dryRun:m=false,userConfig:p={}}=e,a=t,c=y.resolve(process.cwd(),a);if(await h.pathExists(c))throw new T(a);if(m){await ce(c,a,n,p);return}if(n){await se(c,a,o);return}let f=await oe.prompt([{type:"list",name:"pythonVersion",message:"Select Python version for RapidKit:",choices:["3.10","3.11","3.12"],default:p.pythonVersion||"3.11"},{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:p.defaultInstallMethod||"poetry"}]);s.step(1,3,"Setting up RapidKit environment");let u=W("Creating directory").start();try{if(await h.ensureDir(c),u.succeed("Directory created"),f.installMethod==="poetry"?await ie(c,f.pythonVersion,u,r,p):f.installMethod==="venv"?await re(c,f.pythonVersion,u,r,p):await ne(c,u,r,p),await ae(c,f.installMethod),u.succeed("RapidKit environment ready!"),!e.skipGit){u.start("Initializing git repository");try{await execa("git",["init"],{cwd:c}),await h.outputFile(y.join(c,".gitignore"),`.venv/
12
- __pycache__/
13
- *.pyc
2
+ import {Command}from'commander';import a from'chalk';import P from'inquirer';import l,{dirname,join}from'path';import {execa}from'execa';import {readFileSync,promises}from'fs';import {fileURLToPath}from'url';import te from'os';import ae from'validate-npm-package-name';import*as k from'fs-extra';import N from'ora';var x=class{debugEnabled=false;setDebug(t){this.debugEnabled=t;}debug(t,...i){this.debugEnabled&&console.log(a.gray(`[DEBUG] ${t}`),...i);}info(t,...i){console.log(a.blue(t),...i);}success(t,...i){console.log(a.green(t),...i);}warn(t,...i){console.log(a.yellow(t),...i);}error(t,...i){console.error(a.red(t),...i);}step(t,i,o){console.log(a.cyan(`
3
+ [${t}/${i}]`),a.white(o));}},c=new x;var z="rapidkit",V=fileURLToPath(import.meta.url),q=dirname(V),X=join(q,"..","package.json"),Q=JSON.parse(readFileSync(X,"utf-8")),S=Q.version;async function T(){try{c.debug("Checking for updates...");let{stdout:e}=await execa("npm",["view",z,"version"],{timeout:3e3}),t=e.trim();t&&t!==S?(console.log(a.yellow(`
4
+ \u26A0\uFE0F Update available: ${S} \u2192 ${t}`)),console.log(a.cyan(`Run: npm install -g rapidkit@latest
5
+ `))):c.debug("You are using the latest version");}catch{c.debug("Could not check for updates");}}function w(){return S}var ie=".rapidkitrc.json";async function U(){let e=l.join(te.homedir(),ie);try{let t=await promises.readFile(e,"utf-8"),i=JSON.parse(t);return c.debug(`Loaded config from ${e}`),i}catch{return c.debug("No user config found, using defaults"),{}}}var v=class extends Error{constructor(i,o,n){super(i);this.code=o;this.details=n;this.name="RapidKitError",Error.captureStackTrace(this,this.constructor);}};var u=class extends v{constructor(t,i){super(`Invalid project name: "${t}"`,"INVALID_PROJECT_NAME",i);}};function O(e){let t=ae(e);if(!t.validForNewPackages){let o=t.errors||[],n=t.warnings||[],s=[...o,...n];throw new u(e,`NPM validation failed: ${s.join(", ")}`)}if(!/^[a-z][a-z0-9_-]*$/.test(e))throw new u(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 u(e,`"${e}" is a reserved name. Please choose a different name.`);if(e.length<2)throw new u(e,"Name must be at least 2 characters long");if(e.length>214)throw new u(e,"Name must be less than 214 characters");return true}async function F(e,t){let i=N("Creating RapidKit workspace...").start();try{await promises.mkdir(e,{recursive:!0}),await promises.mkdir(l.join(e,".rapidkit"),{recursive:!0});let o={workspace_name:t.name,author:t.author,rapidkit_version:w(),created_at:new Date().toISOString(),type:"workspace"};await promises.writeFile(l.join(e,".rapidkit","config.json"),JSON.stringify(o,null,2));let n=re();await promises.writeFile(l.join(e,"rapidkit"),n),await promises.chmod(l.join(e,"rapidkit"),493);let s=oe(t.name);if(await promises.writeFile(l.join(e,"README.md"),s),await promises.writeFile(l.join(e,".gitignore"),`# RapidKit workspace
14
6
  .env
15
- .rapidkit-workspace/
16
- `,"utf-8"),await execa("git",["add","."],{cwd:c}),await execa("git",["commit","-m","Initial commit: RapidKit environment"],{cwd:c}),u.succeed("Git repository initialized");}catch{u.warn("Could not initialize git repository");}}if(console.log(i.green(`
17
- \u2728 RapidKit environment created successfully!
18
- `)),console.log(i.cyan("\u{1F4C2} Location:"),i.white(c)),console.log(i.cyan(`\u{1F680} Get started:
19
- `)),console.log(i.white(` cd ${a}`)),f.installMethod==="poetry"){let v="source $(poetry env info --path)/bin/activate";try{let{stdout:C}=await execa("poetry",["--version"]),D=C.match(/Poetry.*?(\d+)\.(\d+)/);D&&(parseInt(D[1])>=2?v="source $(poetry env info --path)/bin/activate":v="poetry shell");}catch{}console.log(i.white(` ${v} # Or: poetry run rapidkit`)),console.log(i.white(" rapidkit create # Interactive mode")),console.log(i.white(" cd <project-name> && rapidkit init && rapidkit dev"));}else f.installMethod==="venv"?(console.log(i.white(" source .venv/bin/activate # On Windows: .venv\\Scripts\\activate")),console.log(i.white(" rapidkit create # Interactive mode")),console.log(i.white(" cd <project-name> && rapidkit init && rapidkit dev"))):(console.log(i.white(" rapidkit create # Interactive mode")),console.log(i.white(" cd <project-name> && rapidkit init && rapidkit dev")));console.log(i.white(`
20
- \u{1F4A1} For more information, check the README.md file.`)),console.log(i.cyan(`
21
- \u{1F4DA} RapidKit commands:`)),console.log(i.white(" rapidkit create - Create a new project (interactive)")),console.log(i.white(" rapidkit dev - Run development server")),console.log(i.white(" rapidkit add module <name> - Add a module (e.g., settings)")),console.log(i.white(" rapidkit list - List available kits")),console.log(i.white(" rapidkit modules - List available modules")),console.log(i.white(` rapidkit --help - Show all commands
22
- `));}catch(v){u.fail("Failed to create RapidKit environment"),console.error(i.red(`
23
- \u274C Error:`),v);try{await h.remove(c);}catch{}process.exit(1);}}async function ie(t,e,o,r,n){o.start("Checking Poetry installation");try{await execa("poetry",["--version"]),o.succeed("Poetry found");}catch{throw new $}o.start("Initializing Poetry project"),await execa("poetry",["init","--no-interaction","--python",`^${e}`],{cwd:t});let m=y.join(t,"pyproject.toml"),a=(await promises.readFile(m,"utf-8")).replace("[tool.poetry]",`[tool.poetry]
24
- package-mode = false`);if(await promises.writeFile(m,a,"utf-8"),o.succeed("Poetry project initialized"),o.start("Installing RapidKit"),r){let c=F(n||{});if(!c)throw new j("Test mode installation",new Error("No local RapidKit path configured. Set RAPIDKIT_DEV_PATH environment variable."));s.debug(`Installing from local path: ${c}`),o.text="Installing RapidKit from local path (test mode)",await execa("poetry",["add",c],{cwd:t});}else {o.text="Installing RapidKit from PyPI";try{await execa("poetry",["add","rapidkit"],{cwd:t});}catch{throw new x}}o.succeed("RapidKit installed");}async function re(t,e,o,r,n){o.start(`Checking Python ${e}`);let m="python3";try{let{stdout:a}=await execa(m,["--version"]),c=a.match(/Python (\d+\.\d+)/)?.[1];if(c&&parseFloat(c)<parseFloat(e))throw new b(e,c);o.succeed(`Python ${c} found`);}catch(a){throw a instanceof b?a:new b(e)}o.start("Creating virtual environment"),await execa(m,["-m","venv",".venv"],{cwd:t}),o.succeed("Virtual environment created"),o.start("Installing RapidKit");let p=y.join(t,".venv","bin","pip");if(await execa(p,["install","--upgrade","pip"],{cwd:t}),r){let a=F(n||{});if(!a)throw new j("Test mode installation",new Error("No local RapidKit path configured. Set RAPIDKIT_DEV_PATH environment variable."));s.debug(`Installing from local path: ${a}`),o.text="Installing RapidKit from local path (test mode)",await execa(p,["install","-e",a],{cwd:t});}else {o.text="Installing RapidKit from PyPI";try{await execa(p,["install","rapidkit"],{cwd:t});}catch{throw new x}}o.succeed("RapidKit installed");}async function ne(t,e,o,r){e.start("Checking pipx installation");try{await execa("pipx",["--version"]),e.succeed("pipx found");}catch{throw new N}if(e.start("Installing RapidKit globally with pipx"),o){let n=F(r||{});if(!n)throw new j("Test mode installation",new Error("No local RapidKit path configured. Set RAPIDKIT_DEV_PATH environment variable."));s.debug(`Installing from local path: ${n}`),e.text="Installing RapidKit from local path (test mode)",await execa("pipx",["install","-e",n]);}else {e.text="Installing RapidKit from PyPI";try{await execa("pipx",["install","rapidkit"]);}catch{throw new x}}e.succeed("RapidKit installed globally"),await h.outputFile(y.join(t,".rapidkit-global"),`RapidKit installed globally with pipx
25
- `,"utf-8");}async function ae(t,e){let r=`# RapidKit Workspace
26
-
27
- This directory contains a RapidKit development environment.
28
-
29
- ## Installation Method
30
-
31
- **${e==="poetry"?"Poetry":e==="venv"?"Python venv + pip":"pipx (global)"}**
32
-
33
- ## Getting Started
34
-
35
- ### 1. Activate Environment
36
-
37
- \`\`\`bash
38
- ${e==="poetry"?`source $(poetry env info --path)/bin/activate
39
- # Or simply use: poetry run rapidkit <command>`:e==="venv"?"source .venv/bin/activate # On Windows: .venv\\Scripts\\activate":"N/A (globally installed)"}
40
- \`\`\`
41
-
42
- ### 2. Create Your First Project
43
-
44
- \`\`\`bash
45
- # Interactive mode (recommended):
46
- rapidkit create
47
- # Follow the prompts to choose kit and project name
48
-
49
- # Or specify directly:
50
- rapidkit create project fastapi.standard my-project
51
-
52
- # With poetry run (no activation needed):
53
- poetry run rapidkit create
54
- \`\`\`
55
-
56
- Interactive mode will guide you through selecting a kit and configuring your project.
57
-
58
- ### 3. Navigate and Run
7
+ .env.*
8
+ !.env.example
59
9
 
60
- \`\`\`bash
61
- cd my-project
62
- # Install dependencies (preferred):
63
- rapidkit init
64
-
65
- # Run the server (project-aware):
66
- rapidkit dev
67
-
68
- # Or with poetry run (manual / advanced):
69
- poetry run rapidkit dev
70
-
71
- # Or manually:
72
- uvicorn src.main:app --reload
73
- \`\`\`
10
+ # OS
11
+ .DS_Store
12
+ Thumbs.db
74
13
 
75
- ### 4. Add Modules (Optional)
14
+ # IDEs
15
+ .vscode/
16
+ .idea/
76
17
 
77
- \`\`\`bash
78
- # Add common modules to your project:
79
- rapidkit add module settings
80
- rapidkit add module logging
81
- rapidkit add module database
18
+ # Logs
19
+ *.log
20
+ `),await ne(e),i.succeed("Workspace created!"),!t.skipGit){let d=N("Initializing git repository...").start();try{await execa("git",["init"],{cwd:e}),await execa("git",["add","."],{cwd:e}),await execa("git",["commit","-m","Initial commit: RapidKit workspace"],{cwd:e}),d.succeed("Git repository initialized");}catch{d.warn("Could not initialize git repository");}}console.log(`
21
+ ${a.green("\u2728 RapidKit workspace created successfully!")}
82
22
 
83
- # List available modules:
84
- rapidkit modules list
85
- \`\`\`
23
+ ${a.bold("\u{1F4C2} Workspace structure:")}
24
+ ${e}/
25
+ \u251C\u2500\u2500 rapidkit # Local CLI (add to PATH or use ./rapidkit)
26
+ \u251C\u2500\u2500 .rapidkit/ # Workspace configuration
27
+ \u2502 \u251C\u2500\u2500 config.json # Workspace settings
28
+ \u2502 \u2514\u2500\u2500 templates/ # Project templates
29
+ \u2514\u2500\u2500 README.md
86
30
 
87
- ## Available Commands
31
+ ${a.bold("\u{1F680} Get started:")}
32
+ ${a.cyan(`cd ${t.name}`)}
33
+ ${a.cyan('export PATH="$PWD:$PATH"')} ${a.gray("# Add rapidkit to PATH")}
34
+ ${a.cyan("rapidkit create my-api --template fastapi")}
35
+ ${a.cyan("cd my-api")}
36
+ ${a.cyan("rapidkit dev")}
37
+
38
+ ${a.bold("\u{1F4E6} Available templates:")}
39
+ fastapi - FastAPI + Python (default)
40
+ nestjs - NestJS + TypeScript
41
+
42
+ ${a.bold("\u{1F4DA} Commands:")}
43
+ rapidkit create <name> Create a new project
44
+ rapidkit create --help Show create options
45
+ rapidkit help Show all commands
46
+
47
+ ${a.gray("Tip: Add workspace to PATH for easier access:")}
48
+ ${a.cyan(`echo 'export PATH="${e}:$PATH"' >> ~/.bashrc`)}
49
+ `);}catch(o){throw i.fail("Failed to create workspace"),o}}function re(){return `#!/usr/bin/env bash
50
+ #
51
+ # RapidKit CLI - Local workspace commands
52
+ # This script provides rapidkit commands within the workspace
53
+ #
54
+
55
+ set -e
56
+
57
+ # Find workspace root (where this script lives)
58
+ SCRIPT_DIR="$(cd "$(dirname "\${BASH_SOURCE[0]}")" && pwd)"
59
+
60
+ # Check if we're in a project directory (has .rapidkit/project.json)
61
+ find_project_root() {
62
+ local dir="$PWD"
63
+ while [[ "$dir" != "/" ]]; do
64
+ if [[ -f "$dir/.rapidkit/project.json" ]]; then
65
+ echo "$dir"
66
+ return 0
67
+ fi
68
+ dir="$(dirname "$dir")"
69
+ done
70
+ return 1
71
+ }
88
72
 
89
- - \`rapidkit create\` - Create a new project (interactive)
90
- - \`rapidkit create project <kit> <name>\` - Create project with specific kit
91
- - \`rapidkit dev\` - Run development server
92
- - \`rapidkit add module <name>\` - Add a module (e.g., \`rapidkit add module settings\`)
93
- - \`rapidkit list\` - List available kits
94
- - \`rapidkit modules\` - List available modules
95
- - \`rapidkit upgrade\` - Upgrade RapidKit
96
- - \`rapidkit doctor\` - Check system requirements
97
- - \`rapidkit --help\` - Show all commands
73
+ # Check if we're in a workspace (has .rapidkit/config.json with type=workspace)
74
+ find_workspace_root() {
75
+ local dir="$PWD"
76
+ while [[ "$dir" != "/" ]]; do
77
+ if [[ -f "$dir/.rapidkit/config.json" ]]; then
78
+ if grep -q '"type": "workspace"' "$dir/.rapidkit/config.json" 2>/dev/null; then
79
+ echo "$dir"
80
+ return 0
81
+ fi
82
+ fi
83
+ dir="$(dirname "$dir")"
84
+ done
85
+ return 1
86
+ }
98
87
 
99
- ## RapidKit Documentation
88
+ # Colors
89
+ RED='\\033[0;31m'
90
+ GREEN='\\033[0;32m'
91
+ YELLOW='\\033[0;33m'
92
+ BLUE='\\033[0;34m'
93
+ CYAN='\\033[0;36m'
94
+ NC='\\033[0m' # No Color
95
+ BOLD='\\033[1m'
96
+
97
+ print_banner() {
98
+ echo -e "\${BLUE}\${BOLD}\u{1F680} RapidKit CLI\${NC}"
99
+ echo ""
100
+ }
100
101
 
101
- For full documentation, visit: [RapidKit Docs](https://rapidkit.top) *(or appropriate URL)*
102
+ print_help() {
103
+ print_banner
104
+ echo -e "\${BOLD}Usage:\${NC} rapidkit <command> [options]"
105
+ echo ""
106
+ echo -e "\${BOLD}\u{1F3D7}\uFE0F Workspace Commands:\${NC}"
107
+ echo " create <name> Create a new project from template"
108
+ echo " create --help Show create command options"
109
+ echo ""
110
+ echo -e "\${BOLD}\u{1F680} Project Commands\${NC} (run inside a project):"
111
+ echo " init Install project dependencies"
112
+ echo " dev Start development server"
113
+ echo " start Start production server"
114
+ echo " build Build for production"
115
+ echo " test Run tests"
116
+ echo " lint Run linting"
117
+ echo " format Format code"
118
+ echo ""
119
+ echo -e "\${BOLD}\u{1F4DA} Other Commands:\${NC}"
120
+ echo " help Show this help message"
121
+ echo " version Show version"
122
+ echo ""
123
+ echo -e "\${BOLD}Examples:\${NC}"
124
+ echo -e " \${CYAN}rapidkit create my-api --template fastapi\${NC}"
125
+ echo -e " \${CYAN}rapidkit create my-app --template nestjs --yes\${NC}"
126
+ echo -e " \${CYAN}cd my-api && rapidkit dev\${NC}"
127
+ echo ""
128
+ }
102
129
 
103
- ## Workspace Structure
130
+ print_create_help() {
131
+ print_banner
132
+ echo -e "\${BOLD}Usage:\${NC} rapidkit create <project-name> [options]"
133
+ echo ""
134
+ echo -e "\${BOLD}Options:\${NC}"
135
+ echo " -t, --template <name> Template to use (fastapi, nestjs)"
136
+ echo " -y, --yes Skip prompts, use defaults"
137
+ echo " --skip-git Skip git initialization"
138
+ echo " --skip-install Skip dependency installation"
139
+ echo ""
140
+ echo -e "\${BOLD}Templates:\${NC}"
141
+ echo " fastapi FastAPI + Python (default)"
142
+ echo " nestjs NestJS + TypeScript"
143
+ echo ""
144
+ echo -e "\${BOLD}Examples:\${NC}"
145
+ echo -e " \${CYAN}rapidkit create my-api\${NC}"
146
+ echo -e " \${CYAN}rapidkit create my-api --template fastapi\${NC}"
147
+ echo -e " \${CYAN}rapidkit create my-app --template nestjs --yes\${NC}"
148
+ echo ""
149
+ }
104
150
 
105
- \`\`\`
106
- ${e==="venv"?".venv/ # Python virtual environment":""}
107
- ${e==="poetry"?"pyproject.toml # Poetry configuration":""}
108
- my-project/ # Your RapidKit projects go here
109
- README.md # This file
110
- \`\`\`
151
+ # Create project command
152
+ cmd_create() {
153
+ local project_name=""
154
+ local template="fastapi"
155
+ local yes_flag=""
156
+ local skip_git=""
157
+ local skip_install=""
158
+
159
+ # Parse arguments
160
+ while [[ $# -gt 0 ]]; do
161
+ case "$1" in
162
+ -h|--help)
163
+ print_create_help
164
+ exit 0
165
+ ;;
166
+ -t|--template)
167
+ template="$2"
168
+ shift 2
169
+ ;;
170
+ -y|--yes)
171
+ yes_flag="--yes"
172
+ shift
173
+ ;;
174
+ --skip-git)
175
+ skip_git="--skip-git"
176
+ shift
177
+ ;;
178
+ --skip-install)
179
+ skip_install="--skip-install"
180
+ shift
181
+ ;;
182
+ -*)
183
+ echo -e "\${RED}\u274C Unknown option: $1\${NC}"
184
+ print_create_help
185
+ exit 1
186
+ ;;
187
+ *)
188
+ if [[ -z "$project_name" ]]; then
189
+ project_name="$1"
190
+ fi
191
+ shift
192
+ ;;
193
+ esac
194
+ done
195
+
196
+ # Validate template
197
+ if [[ "$template" != "fastapi" && "$template" != "nestjs" ]]; then
198
+ echo -e "\${RED}\u274C Invalid template: $template\${NC}"
199
+ echo -e "Available templates: fastapi, nestjs"
200
+ exit 1
201
+ fi
202
+
203
+ # If no project name, prompt for it or show help
204
+ if [[ -z "$project_name" ]]; then
205
+ if [[ -n "$yes_flag" ]]; then
206
+ project_name="my-\${template}-project"
207
+ else
208
+ echo -e "\${YELLOW}Project name required\${NC}"
209
+ echo ""
210
+ print_create_help
211
+ exit 1
212
+ fi
213
+ fi
214
+
215
+ # Find workspace root
216
+ local workspace_root
217
+ workspace_root=$(find_workspace_root) || {
218
+ echo -e "\${RED}\u274C Not in a RapidKit workspace\${NC}"
219
+ echo -e "Run this command from within a RapidKit workspace."
220
+ exit 1
221
+ }
222
+
223
+ local project_path="$PWD/$project_name"
224
+
225
+ # Check if project already exists
226
+ if [[ -d "$project_path" ]]; then
227
+ echo -e "\${RED}\u274C Directory '$project_name' already exists\${NC}"
228
+ exit 1
229
+ fi
230
+
231
+ echo -e "\${BLUE}\${BOLD}\u{1F680} Creating $template project: $project_name\${NC}"
232
+ echo ""
233
+
234
+ # Use Node.js generator script
235
+ local generator_script="$workspace_root/.rapidkit/generator.js"
236
+
237
+ if [[ -f "$generator_script" ]]; then
238
+ node "$generator_script" "$project_path" "$template" "$yes_flag" "$skip_git" "$skip_install"
239
+ else
240
+ echo -e "\${RED}\u274C Generator script not found\${NC}"
241
+ exit 1
242
+ fi
243
+ }
111
244
 
112
- ## Troubleshooting
113
-
114
- If you encounter issues:
115
-
116
- 1. Ensure Python 3.10+ is installed: \`python3 --version\`
117
- 2. Check RapidKit installation: \`rapidkit --version\`
118
- 3. Run diagnostics: \`rapidkit doctor\`
119
- 4. Visit RapidKit documentation or GitHub issues
120
- `;await promises.writeFile(y.join(t,"README.md"),r,"utf-8");}async function se(t,e,o){let r=W("Creating demo workspace").start();try{await h.ensureDir(t),r.succeed("Directory created"),r.start("Setting up demo kit generator");let n=JSON.stringify({name:`${e}-workspace`,version:"1.0.0",private:!0,description:"RapidKit demo workspace",scripts:{generate:"node generate-demo.js"}},null,2);await promises.writeFile(y.join(t,"package.json"),n,"utf-8"),await promises.writeFile(y.join(t,"generate-demo.js"),`#!/usr/bin/env node
121
- /**
122
- * Demo Kit Generator - Create FastAPI demo projects
123
- *
124
- * This workspace contains bundled RapidKit templates that you can use
125
- * to generate demo projects without installing Python RapidKit.
126
- *
127
- * Usage:
128
- * npm run generate <project-name>
129
- * node generate-demo.js <project-name>
130
- *
131
- * Example:
132
- * npm run generate my-api
133
- */
134
-
135
- const { execSync } = require('child_process');
136
- const path = require('path');
137
-
138
- const projectName = process.argv[2];
139
-
140
- if (!projectName) {
141
- console.error('\\n\u274C Please provide a project name');
142
- console.log('\\nUsage: npm run generate <project-name>\\n');
143
- console.log('Example: npm run generate my-api\\n');
144
- process.exit(1);
245
+ # Project commands (dev, build, test, etc.)
246
+ cmd_project() {
247
+ local cmd="$1"
248
+ shift
249
+
250
+ # Find project root
251
+ local project_root
252
+ project_root=$(find_project_root) || {
253
+ echo -e "\${RED}\u274C Not in a RapidKit project\${NC}"
254
+ echo -e "Run this command from within a project directory."
255
+ echo -e "Use \${CYAN}rapidkit create <name>\${NC} to create a new project."
256
+ exit 1
257
+ }
258
+
259
+ # Read project type from project.json
260
+ local project_json="$project_root/.rapidkit/project.json"
261
+ local kit_name
262
+ kit_name=$(grep -o '"kit_name": *"[^"]*"' "$project_json" | cut -d'"' -f4)
263
+
264
+ cd "$project_root"
265
+
266
+ case "$kit_name" in
267
+ fastapi.standard|python)
268
+ # Python/FastAPI project
269
+ case "$cmd" in
270
+ init)
271
+ echo -e "\${BLUE}\u{1F4E6} Installing dependencies...\${NC}"
272
+ poetry install
273
+ echo -e "\${GREEN}\u2705 Dependencies installed!\${NC}"
274
+ ;;
275
+ dev)
276
+ echo -e "\${BLUE}\u{1F680} Starting development server...\${NC}"
277
+ poetry run dev "$@"
278
+ ;;
279
+ start)
280
+ echo -e "\${BLUE}\u26A1 Starting production server...\${NC}"
281
+ poetry run start "$@"
282
+ ;;
283
+ build)
284
+ echo -e "\${BLUE}\u{1F4E6} Building project...\${NC}"
285
+ poetry run build
286
+ ;;
287
+ test)
288
+ echo -e "\${BLUE}\u{1F9EA} Running tests...\${NC}"
289
+ poetry run test
290
+ ;;
291
+ lint)
292
+ echo -e "\${BLUE}\u{1F527} Running linter...\${NC}"
293
+ poetry run lint
294
+ ;;
295
+ format)
296
+ echo -e "\${BLUE}\u2728 Formatting code...\${NC}"
297
+ poetry run format
298
+ ;;
299
+ *)
300
+ echo -e "\${RED}\u274C Unknown command: $cmd\${NC}"
301
+ exit 1
302
+ ;;
303
+ esac
304
+ ;;
305
+ nestjs.standard|node)
306
+ # Node/NestJS project
307
+ local pm="npm"
308
+ if command -v pnpm &>/dev/null && [[ -f "pnpm-lock.yaml" ]]; then
309
+ pm="pnpm"
310
+ elif command -v yarn &>/dev/null && [[ -f "yarn.lock" ]]; then
311
+ pm="yarn"
312
+ fi
313
+
314
+ case "$cmd" in
315
+ init)
316
+ echo -e "\${BLUE}\u{1F4E6} Installing dependencies...\${NC}"
317
+ $pm install
318
+ echo -e "\${GREEN}\u2705 Dependencies installed!\${NC}"
319
+ ;;
320
+ dev)
321
+ echo -e "\${BLUE}\u{1F680} Starting development server...\${NC}"
322
+ $pm run start:dev
323
+ ;;
324
+ start)
325
+ echo -e "\${BLUE}\u26A1 Starting production server...\${NC}"
326
+ $pm run start:prod
327
+ ;;
328
+ build)
329
+ echo -e "\${BLUE}\u{1F4E6} Building project...\${NC}"
330
+ $pm run build
331
+ ;;
332
+ test)
333
+ echo -e "\${BLUE}\u{1F9EA} Running tests...\${NC}"
334
+ $pm test
335
+ ;;
336
+ lint)
337
+ echo -e "\${BLUE}\u{1F527} Running linter...\${NC}"
338
+ $pm run lint
339
+ ;;
340
+ format)
341
+ echo -e "\${BLUE}\u2728 Formatting code...\${NC}"
342
+ $pm run format
343
+ ;;
344
+ *)
345
+ echo -e "\${RED}\u274C Unknown command: $cmd\${NC}"
346
+ exit 1
347
+ ;;
348
+ esac
349
+ ;;
350
+ *)
351
+ echo -e "\${RED}\u274C Unknown project type: $kit_name\${NC}"
352
+ exit 1
353
+ ;;
354
+ esac
145
355
  }
146
356
 
147
- // Use npx to run rapidkit in demo mode, targeting the current directory
148
- const targetPath = path.join(process.cwd(), projectName);
149
-
150
- try {
151
- console.log(\`\\nGenerating demo project: \${projectName}...\\n\`);
152
- execSync(\`npx rapidkit "\${projectName}" --demo-only\`, {
153
- stdio: 'inherit',
154
- cwd: process.cwd(),
155
- });
156
- console.log(\`\\n\u2705 Demo project created at: \${targetPath}\\n\`);
157
- } catch (_error) {
158
- console.error('\\n\u274C Failed to generate demo project\\n');
159
- process.exit(1);
357
+ # Main command handler
358
+ main() {
359
+ local cmd="\${1:-help}"
360
+ shift || true
361
+
362
+ case "$cmd" in
363
+ create)
364
+ cmd_create "$@"
365
+ ;;
366
+ init|dev|start|build|test|lint|format)
367
+ cmd_project "$cmd" "$@"
368
+ ;;
369
+ help|-h|--help)
370
+ print_help
371
+ ;;
372
+ version|-v|--version)
373
+ echo "RapidKit CLI (npm workspace) v${w()}"
374
+ ;;
375
+ *)
376
+ echo -e "\${RED}\u274C Unknown command: $cmd\${NC}"
377
+ echo ""
378
+ print_help
379
+ exit 1
380
+ ;;
381
+ esac
160
382
  }
161
- `,"utf-8");try{await execa("chmod",["+x",y.join(t,"generate-demo.js")]);}catch{}let p=`# RapidKit Demo Workspace
162
383
 
163
- Welcome to your RapidKit demo workspace! This environment lets you generate FastAPI demo projects using bundled RapidKit templates, without needing to install Python RapidKit.
384
+ main "$@"
385
+ `}function oe(e){return `# ${e}
164
386
 
165
- ## \u{1F680} Quick Start
387
+ RapidKit workspace for building API projects.
166
388
 
167
- ### Generate Your First Demo Project
389
+ ## Quick Start
168
390
 
169
391
  \`\`\`bash
170
- # Generate a demo project:
171
- node generate-demo.js my-api
392
+ # Add rapidkit to PATH (or use ./rapidkit)
393
+ export PATH="$PWD:$PATH"
172
394
 
173
- # Navigate to the project:
174
- cd my-api
395
+ # Create a FastAPI project
396
+ rapidkit create my-api --template fastapi
175
397
 
176
- # Install dependencies:
177
- poetry install
178
-
179
- # Run the development server:
180
- poetry run python -m src.main
181
- \`\`\`
398
+ # Or create a NestJS project
399
+ rapidkit create my-app --template nestjs
182
400
 
183
- Your API will be available at \`http://localhost:8000\`
184
-
185
- ## \u{1F4E6} Generate Multiple Projects
186
-
187
- You can create multiple demo projects in this workspace:
188
-
189
- \`\`\`bash
190
- node generate-demo.js api-service
191
- node generate-demo.js auth-service
192
- node generate-demo.js data-service
401
+ # Enter project and start development
402
+ cd my-api
403
+ rapidkit init # Install dependencies
404
+ rapidkit dev # Start dev server
193
405
  \`\`\`
194
406
 
195
- Each project is independent and has its own dependencies.
196
-
197
- ## \u{1F3AF} What's Included
407
+ ## Available Templates
198
408
 
199
- Each generated demo project contains:
409
+ | Template | Stack | Description |
410
+ |----------|-------|-------------|
411
+ | \`fastapi\` | Python + FastAPI | High-performance Python API |
412
+ | \`nestjs\` | TypeScript + NestJS | Enterprise Node.js framework |
200
413
 
201
- - **FastAPI Application** - Modern async web framework
202
- - **Routing System** - Organized API routes
203
- - **Module System** - Extensible module architecture
204
- - **CLI Commands** - Built-in command system
205
- - **Testing Setup** - pytest configuration
206
- - **Poetry Configuration** - Dependency management
414
+ ## Commands
207
415
 
208
- ## \u{1F4DA} Next Steps
416
+ ### Workspace Commands
209
417
 
210
- 1. **Explore the Generated Code** - Check out \`src/main.py\` and \`src/routing/\`
211
- 2. **Add Routes** - Create new endpoints in \`src/routing/\`
212
- 3. **Install Full RapidKit** - For advanced features: \`pipx install rapidkit\`
213
- 4. **Read the Documentation** - Visit [RapidKit Docs](https://rapidkit.top)
418
+ | Command | Description |
419
+ |---------|-------------|
420
+ | \`rapidkit create <name>\` | Create a new project |
421
+ | \`rapidkit create --help\` | Show create options |
422
+ | \`rapidkit help\` | Show all commands |
214
423
 
215
- ## \u26A0\uFE0F Demo Mode Limitations
424
+ ### Project Commands (run inside a project)
216
425
 
217
- This is a demo workspace with:
218
- - \u2705 Pre-built FastAPI templates
219
- - \u2705 Project generation without Python RapidKit
220
- - \u274C No RapidKit CLI commands (\`rapidkit create\`, \`rapidkit add module\`)
221
- - \u274C No interactive module system
426
+ | Command | Description |
427
+ |---------|-------------|
428
+ | \`rapidkit init\` | Install dependencies |
429
+ | \`rapidkit dev\` | Start development server |
430
+ | \`rapidkit start\` | Start production server |
431
+ | \`rapidkit build\` | Build for production |
432
+ | \`rapidkit test\` | Run tests |
433
+ | \`rapidkit lint\` | Run linting |
434
+ | \`rapidkit format\` | Format code |
222
435
 
223
- For full RapidKit features, install the Python package:
436
+ ## Learn More
224
437
 
225
- \`\`\`bash
226
- pipx install rapidkit
227
- \`\`\`
228
-
229
- ## \u{1F6E0}\uFE0F Workspace Structure
230
-
231
- \`\`\`
232
- ${e}/
233
- \u251C\u2500\u2500 generate-demo.js # Demo project generator
234
- \u251C\u2500\u2500 README.md # This file
235
- \u2514\u2500\u2500 my-api/ # Your generated projects go here
236
- \`\`\`
237
-
238
- ## \u{1F4A1} Tips
239
-
240
- - Run \`node generate-demo.js --help\` for more options (coming soon)
241
- - Each project can have different configurations
242
- - Demo projects are production-ready FastAPI applications
243
- - You can copy and modify templates as needed
244
-
245
- ---
246
-
247
- **Generated with RapidKit** | [GitHub](https://github.com/getrapidkit/rapidkit-npm)
248
- `;if(await promises.writeFile(y.join(t,"README.md"),p,"utf-8"),r.succeed("Demo workspace setup complete"),!o){r.start("Initializing git repository");try{await execa("git",["init"],{cwd:t}),await h.outputFile(y.join(t,".gitignore"),`# Dependencies
249
- node_modules/
250
-
251
- # Generated projects
252
- */
253
- !generate-demo.js
254
- !README.md
255
-
256
- # Python
257
- __pycache__/
258
- *.pyc
259
- .venv/
260
- .env
261
- `,"utf-8"),await execa("git",["add","."],{cwd:t}),await execa("git",["commit","-m","Initial commit: Demo workspace"],{cwd:t}),r.succeed("Git repository initialized");}catch{r.warn("Could not initialize git repository");}}console.log(i.green(`
262
- \u2728 Demo workspace created successfully!
263
- `)),console.log(i.cyan("\u{1F4C2} Location:"),i.white(t)),console.log(i.cyan(`\u{1F680} Get started:
264
- `)),console.log(i.white(` cd ${e}`)),console.log(i.white(" node generate-demo.js my-api")),console.log(i.white(" cd my-api")),console.log(i.white(" poetry install")),console.log(i.white(" poetry run python -m src.main")),console.log(),console.log(i.yellow("\u{1F4A1} Note:"),"This is a demo workspace. For full RapidKit features:"),console.log(i.cyan(" pipx install rapidkit")),console.log();}catch(n){throw r.fail("Failed to create demo workspace"),n}}async function ce(t,e,o,r){console.log(i.cyan(`
265
- \u{1F50D} Dry-run mode - showing what would be created:
266
- `)),console.log(i.white("\u{1F4C2} Project path:"),t),console.log(i.white("\u{1F4E6} Project type:"),o?"Demo workspace":"Full RapidKit environment"),o?(console.log(i.white(`
267
- \u{1F4DD} Files to create:`)),console.log(i.gray(" - package.json")),console.log(i.gray(" - generate-demo.js (project generator)")),console.log(i.gray(" - README.md")),console.log(i.gray(" - .gitignore")),console.log(i.white(`
268
- \u{1F3AF} Capabilities:`)),console.log(i.gray(" - Generate multiple FastAPI demo projects")),console.log(i.gray(" - No Python RapidKit installation required")),console.log(i.gray(" - Bundled templates included"))):(console.log(i.white(`
269
- \u2699\uFE0F Configuration:`)),console.log(i.gray(` - Python version: ${r.pythonVersion||"3.11"}`)),console.log(i.gray(` - Install method: ${r.defaultInstallMethod||"poetry"}`)),console.log(i.gray(` - Git initialization: ${r.skipGit?"No":"Yes"}`)),console.log(i.white(`
270
- \u{1F4DD} Files to create:`)),console.log(i.gray(" - pyproject.toml (Poetry) or .venv/ (venv)")),console.log(i.gray(" - README.md")),console.log(i.gray(" - .gitignore")),console.log(i.white(`
271
- \u{1F3AF} Next steps after creation:`)),console.log(i.gray(" 1. Install RapidKit Python package")),console.log(i.gray(" 2. Create projects with rapidkit CLI")),console.log(i.gray(" 3. Add modules and customize"))),console.log(i.white(`
272
- \u{1F4A1} To proceed with actual creation, run without --dry-run flag
273
- `));}var me=fileURLToPath(import.meta.url),ge=y.dirname(me);async function Y(t,e){let o=W("Generating FastAPI demo project...").start();try{let r=y.resolve(ge,".."),n=y.join(r,"templates","kits","fastapi-standard"),m=le.configure(n,{autoescape:!1,trimBlocks:!0,lstripBlocks:!0}),p={project_name:e.project_name,author:e.author||"RapidKit User",description:e.description||"FastAPI service generated with RapidKit",app_version:e.app_version||"0.1.0",license:e.license||"MIT"},a=["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"];for(let f of a){let u=y.join(n,f),v=await promises.readFile(u,"utf-8"),C=m.renderString(v,p),D=f.replace(/\.j2$/,""),O=y.join(t,D);await promises.mkdir(y.dirname(O),{recursive:!0}),await promises.writeFile(O,C);}await promises.writeFile(y.join(t,".gitignore"),`# Python
438
+ - [RapidKit Documentation](https://rapidkit.dev)
439
+ - [GitHub Repository](https://github.com/Baziar/rapidkit)
440
+ `}async function ne(e){let{fileURLToPath:t}=await import('url'),i=t(import.meta.url),o=l.dirname(i),n=l.resolve(o,".."),s=l.join(n,"templates","kits"),p=l.join(e,".rapidkit","templates"),{default:d}=await import('fs-extra');await d.copy(s,p);let g=l.join(n,"templates","generator.js"),j=l.join(e,".rapidkit","generator.js");await d.copy(g,j);}async function B(e,t){let i=t.template==="fastapi",o=i?"FastAPI":"NestJS",n=N(`Creating ${o} project...`).start();try{let{fileURLToPath:s}=await import('url'),p=s(import.meta.url),d=l.dirname(p),g=l.resolve(d,".."),j=i?"fastapi-standard":"nestjs-standard",C=l.join(g,"templates","kits",j);await promises.mkdir(e,{recursive:!0});let _={project_name:i?t.name.replace(/-/g,"_").toLowerCase():t.name.replace(/_/g,"-").toLowerCase(),author:t.author,description:t.description||`${o} application generated with RapidKit`,app_version:"0.1.0",license:"MIT",package_manager:t.package_manager||"npm",created_at:new Date().toISOString(),rapidkit_version:w()};await K(C,e,_);let G=i?`# Python
274
441
  __pycache__/
275
442
  *.py[cod]
276
443
  *$py.class
@@ -312,11 +479,38 @@ Thumbs.db
312
479
  # Project specific
313
480
  .env
314
481
  .env.local
315
- `),o.succeed("FastAPI demo project generated!"),console.log(`
316
- ${i.green("\u2728 Demo project created successfully!")}
482
+ `:`# Node artifacts
483
+ node_modules/
484
+ dist/
485
+ .tmp/
486
+ .env
487
+ .env.*
488
+ !.env.example
489
+
490
+ # Logs
491
+ logs/
492
+ *.log
493
+ npm-debug.log*
494
+ yarn-debug.log*
495
+ yarn-error.log*
496
+ pnpm-debug.log*
497
+
498
+ # OS
499
+ .DS_Store
500
+ Thumbs.db
317
501
 
318
- ${i.bold("\u{1F4C2} Project structure:")}
319
- ${t}/
502
+ # IDEs
503
+ .idea/
504
+ .vscode/
505
+
506
+ # Coverage
507
+ coverage/
508
+ `;if(await promises.writeFile(l.join(e,".gitignore"),G),n.succeed(`${o} project created!`),!t.skipGit){let y=N("Initializing git repository...").start();try{await execa("git",["init"],{cwd:e}),await execa("git",["add","."],{cwd:e}),await execa("git",["commit","-m",`Initial commit: ${o} project via RapidKit`],{cwd:e}),y.succeed("Git repository initialized");}catch{y.warn("Could not initialize git repository");}}if(!t.skipInstall&&!i){let y=t.package_manager||"npm",D=N(`Installing dependencies with ${y}...`).start();try{await execa(y,["install"],{cwd:e}),D.succeed("Dependencies installed");}catch{D.warn(`Could not install dependencies. Run '${y} install' manually.`);}}let A=l.basename(e);console.log(i?`
509
+ ${a.green("\u2728 FastAPI project created successfully!")}
510
+
511
+ ${a.bold("\u{1F4C2} Project structure:")}
512
+ ${e}/
513
+ \u251C\u2500\u2500 .rapidkit/ # RapidKit CLI module
320
514
  \u251C\u2500\u2500 src/
321
515
  \u2502 \u251C\u2500\u2500 main.py # FastAPI application
322
516
  \u2502 \u251C\u2500\u2500 cli.py # CLI commands
@@ -326,41 +520,76 @@ ${t}/
326
520
  \u251C\u2500\u2500 pyproject.toml # Poetry configuration
327
521
  \u2514\u2500\u2500 README.md
328
522
 
329
- ${i.bold("\u{1F680} Get started:")}
330
- cd ${y.basename(t)}
331
- poetry install
332
- poetry run python -m src.main
333
-
334
- ${i.bold("\u{1F4DA} Next steps:")}
335
- \u2022 Add RapidKit modules: poetry add rapidkit
336
- \u2022 Read the README.md for more information
337
- \u2022 Start building your API!
338
-
339
- ${i.yellow("Note:")} This is a standalone demo. For full RapidKit features and modules,
340
- install RapidKit Python package: ${i.cyan("pipx install rapidkit")}
341
- `);}catch(r){throw o.fail("Failed to generate demo project"),r}}var ve="rapidkit",ke=fileURLToPath(import.meta.url),Re=dirname(ke),Pe=join(Re,"..","package.json"),be=JSON.parse(readFileSync(Pe,"utf-8")),L=be.version;async function H(){try{s.debug("Checking for updates...");let{stdout:t}=await execa("npm",["view",ve,"version"],{timeout:3e3}),e=t.trim();e&&e!==L?(console.log(i.yellow(`
342
- \u26A0\uFE0F Update available: ${L} \u2192 ${e}`)),console.log(i.cyan(`Run: npm install -g rapidkit@latest
343
- `))):s.debug("You are using the latest version");}catch{s.debug("Could not check for updates");}}function J(){return L}function V(t){let e=je(t);if(!e.validForNewPackages){let r=e.errors||[],n=e.warnings||[],m=[...r,...n];throw new k(t,`NPM validation failed: ${m.join(", ")}`)}if(!/^[a-z][a-z0-9_-]*$/.test(t))throw new k(t,"Must start with a lowercase letter and contain only lowercase letters, numbers, hyphens, and underscores");if(["test","tests","src","dist","build","lib","python","pip","poetry","node","npm","rapidkit","rapidkit"].includes(t.toLowerCase()))throw new k(t,`"${t}" is a reserved name. Please choose a different name.`);if(t.length<2)throw new k(t,"Name must be at least 2 characters long");if(t.length>214)throw new k(t,"Name must be less than 214 characters");return true}var w=null,M=false,X=new Command;X.name("rapidkit").description("Create a RapidKit development environment or workspace").version(J()).argument("[directory-name]","Name of the workspace or project directory").option("--skip-git","Skip git initialization").option("--test-mode","Install RapidKit from local path (for development/testing only)").option("--demo","Create workspace with demo kit templates (no Python installation required)").option("--demo-only","Generate a demo project in current directory (used by demo workspace)").option("--debug","Enable debug logging").option("--dry-run","Show what would be created without creating it").option("--no-update-check","Skip checking for updates").action(async(t,e)=>{try{e.debug&&(s.setDebug(!0),s.debug("Debug mode enabled"));let o=await z();if(s.debug("User config loaded",o),e.updateCheck!==!1&&await H(),console.log(i.blue.bold(`
523
+ ${a.bold("\u{1F680} Get started:")}
524
+ ${a.cyan(`cd ${A}`)}
525
+ ${a.cyan("source .rapidkit/activate")} ${a.gray("# Enable rapidkit commands")}
526
+ ${a.cyan("rapidkit init")} ${a.gray("# Install dependencies")}
527
+ ${a.cyan("rapidkit dev")} ${a.gray("# Start dev server")}
528
+
529
+ ${a.bold("\u{1F4DA} Available commands:")}
530
+ rapidkit init # Install dependencies (poetry install)
531
+ rapidkit dev # Start dev server with hot reload
532
+ rapidkit start # Start production server
533
+ rapidkit test # Run tests
534
+ rapidkit lint # Lint code
535
+ rapidkit format # Format code
536
+
537
+ ${a.gray("Alternative: use make commands (make dev, make test, ...)")}
538
+ `:`
539
+ ${a.green("\u2728 NestJS project created successfully!")}
540
+
541
+ ${a.bold("\u{1F4C2} Project structure:")}
542
+ ${e}/
543
+ \u251C\u2500\u2500 .rapidkit/ # RapidKit CLI module
544
+ \u251C\u2500\u2500 src/
545
+ \u2502 \u251C\u2500\u2500 main.ts # Application entry point
546
+ \u2502 \u251C\u2500\u2500 app.module.ts # Root module
547
+ \u2502 \u251C\u2500\u2500 config/ # Configuration
548
+ \u2502 \u2514\u2500\u2500 examples/ # Example module
549
+ \u251C\u2500\u2500 test/ # Test files
550
+ \u251C\u2500\u2500 package.json # Dependencies
551
+ \u2514\u2500\u2500 README.md
552
+
553
+ ${a.bold("\u{1F680} Get started:")}
554
+ ${a.cyan(`cd ${A}`)}
555
+ ${a.cyan("source .rapidkit/activate")} ${a.gray("# Enable rapidkit commands")}
556
+ ${t.skipInstall?a.cyan("rapidkit init")+a.gray(" # npm install")+`
557
+ `:""}${a.cyan("cp .env.example .env")}
558
+ ${a.cyan("rapidkit dev")} ${a.gray("# Start dev server")}
559
+
560
+ ${a.bold("\u{1F4DA} Available commands:")}
561
+ rapidkit init # Install dependencies
562
+ rapidkit dev # Start dev server with hot reload
563
+ rapidkit start # Start production server
564
+ rapidkit build # Build for production
565
+ rapidkit test # Run tests
566
+ rapidkit lint # Lint code
567
+ rapidkit format # Format code
568
+
569
+ ${a.bold("\u{1F310} API endpoints:")}
570
+ http://localhost:3000/health # Health check
571
+ http://localhost:3000/docs # Swagger docs
572
+ http://localhost:3000/examples/notes # Example API
573
+ `);}catch(s){throw n.fail(`Failed to create ${o} project`),s}}async function K(e,t,i){let o=await promises.readdir(e,{withFileTypes:true});for(let n of o){let s=l.join(e,n.name),p=n.name.replace(/\.j2$/,""),d=l.join(t,p);if(n.isDirectory())await promises.mkdir(d,{recursive:true}),await K(s,d,i);else {let g=await promises.readFile(s,"utf-8");n.name.endsWith(".j2")&&(g=se(g,i)),await promises.writeFile(d,g),(p==="rapidkit"||p==="activate"||p.endsWith(".py")&&d.includes(".rapidkit"))&&await promises.chmod(d,493);}}}function se(e,t){let i=e;for(let[o,n]of Object.entries(t)){let s=new RegExp(`\\{\\{\\s*${o}\\s*\\}\\}`,"g");i=i.replace(s,String(n));let p=new RegExp(`\\{\\{\\s*${o}\\s*\\|\\s*replace\\s*\\(\\s*['"]([^'"]+)['"]\\s*,\\s*['"]([^'"]*)['"]\\s*\\)\\s*\\}\\}`,"g");i=i.replace(p,(j,C,_)=>String(n).replace(new RegExp(C,"g"),_));let d=new RegExp(`\\{\\{\\s*${o}\\s*\\|\\s*lower\\s*\\}\\}`,"g");i=i.replace(d,String(n).toLowerCase());let g=new RegExp(`\\{\\{\\s*${o}\\s*\\|\\s*replace\\s*\\(\\s*['"]([^'"]+)['"]\\s*,\\s*['"]([^'"]*)['"]\\s*\\)\\s*\\|\\s*lower\\s*\\}\\}`,"g");i=i.replace(g,(j,C,_)=>String(n).replace(new RegExp(C,"g"),_).toLowerCase());}return i}var h=null,E=false,I=new Command;I.name("rapidkit").description("Create RapidKit workspaces and projects").version(w());I.argument("[name]","Name of the workspace or project directory").option("-t, --template <template>","Create project with template (fastapi, nestjs) instead of workspace").option("-y, --yes","Skip prompts and use defaults").option("--skip-git","Skip git initialization").option("--skip-install","Skip installing dependencies").option("--debug","Enable debug logging").option("--dry-run","Show what would be created without creating it").option("--no-update-check","Skip checking for updates").action(async(e,t)=>{try{t.debug&&(c.setDebug(!0),c.debug("Debug mode enabled"));let i=await U();c.debug("User config loaded",i),t.updateCheck!==!1&&await T(),console.log(a.blue.bold(`
344
574
  \u{1F680} Welcome to RapidKit!
345
- `)),e.demoOnly){let n=t||"my-fastapi-project";try{V(n);}catch(a){throw a instanceof g&&(s.error(`
346
- \u274C ${a.message}`),a.details&&s.warn(`\u{1F4A1} ${a.details}
347
- `),process.exit(1)),a}let m=y.resolve(process.cwd(),n);if(w=m,e.dryRun){console.log(i.cyan(`
575
+ `)),e||(le(),process.exit(0));try{O(e);}catch(p){throw p instanceof v&&(c.error(`
576
+ \u274C ${p.message}`),p.details&&c.warn(`\u{1F4A1} ${p.details}
577
+ `),process.exit(1)),p}let o=l.resolve(process.cwd(),e);h=o,await k.pathExists(o)&&(c.error(`
578
+ \u274C Directory "${e}" already exists`),console.log(a.cyan(`
579
+ \u{1F4A1} Choose a different name or delete the existing directory.
580
+ `)),process.exit(1));let n=!!t.template;if(n){let p=t.template.toLowerCase(),d=["fastapi","nestjs"];d.includes(p)||(c.error(`
581
+ \u274C Invalid template: ${t.template}`),console.log(a.cyan(`
582
+ \u{1F4E6} Available templates: ${d.join(", ")}
583
+ `)),process.exit(1));}if(t.dryRun){console.log(a.cyan(`
348
584
  \u{1F50D} Dry-run mode - showing what would be created:
349
- `)),console.log(i.white("\u{1F4C2} Project path:"),m),console.log(i.white("\u{1F4E6} Project type:"),"FastAPI demo project"),console.log(i.white("\u{1F4DD} Files to create:")),console.log(i.gray(" - src/main.py")),console.log(i.gray(" - src/cli.py")),console.log(i.gray(" - src/routing/")),console.log(i.gray(" - tests/")),console.log(i.gray(" - pyproject.toml")),console.log(i.gray(` - README.md
350
- `));return}let p=await oe.prompt([{type:"input",name:"project_name",message:"Project name (snake_case):",default:n.replace(/-/g,"_"),validate:a=>/^[a-z][a-z0-9_]*$/.test(a)?!0:"Please use snake_case (lowercase with underscores)"},{type:"input",name:"author",message:"Author name:",default:process.env.USER||"RapidKit User"},{type:"input",name:"description",message:"Project description:",default:"FastAPI service generated with RapidKit"}]);await Y(m,p);return}let r=t||"rapidkit-workspace";try{V(r);}catch(n){throw n instanceof g&&(s.error(`
351
- \u274C ${n.message}`),n.details&&s.warn(`\u{1F4A1} ${n.details}
352
- `),process.exit(1)),n}if(w=y.resolve(process.cwd(),r),e.demo){console.log(i.gray(`This will create a workspace with demo kit templates.
353
- You can generate demo projects inside without installing Python RapidKit.
354
- `)),await U(r,{skipGit:e.skipGit||o.skipGit,testMode:!1,demoMode:!0,dryRun:e.dryRun,userConfig:o});return}console.log(i.yellow.bold(`\u26A0\uFE0F BETA NOTICE
355
- `)),console.log(i.yellow(`RapidKit Python package is not yet available on PyPI.
356
- Full installation mode will be available soon.
357
- `)),console.log(i.cyan(`For now, please use one of these options:
358
- `)),console.log(i.white(" 1. Demo mode (recommended):")),console.log(i.gray(` npx rapidkit my-workspace --demo
359
- `)),console.log(i.white(" 2. Test mode (if you have local RapidKit):")),console.log(i.gray(` npx rapidkit my-workspace --test-mode
360
- `)),e.testMode||(console.log(i.red(`\u274C Cannot proceed without --demo or --test-mode flag.
361
- `)),process.exit(1)),console.log(i.yellow(`\u26A0\uFE0F Running in TEST MODE - Installing from local path
362
- `)),await U(r,{skipGit:e.skipGit||o.skipGit,testMode:e.testMode,demoMode:!1,dryRun:e.dryRun,userConfig:o});}catch(o){o instanceof g?(s.error(`
363
- \u274C ${o.message}`),o.details&&s.warn(`\u{1F4A1} ${o.details}`),s.debug("Error code:",o.code)):(s.error(`
364
- \u274C An unexpected error occurred:`),console.error(o)),process.exit(1);}finally{w=null;}});process.on("SIGINT",async()=>{if(!M){if(M=true,console.log(i.yellow(`
365
-
366
- \u26A0\uFE0F Interrupted by user`)),w&&await h.pathExists(w)){console.log(i.gray("Cleaning up partial installation..."));try{await h.remove(w),console.log(i.green("\u2713 Cleanup complete"));}catch(t){s.debug("Cleanup failed:",t);}}process.exit(130);}});process.on("SIGTERM",async()=>{if(!M){if(M=true,s.debug("Received SIGTERM"),w&&await h.pathExists(w))try{await h.remove(w);}catch(t){s.debug("Cleanup failed:",t);}process.exit(143);}});X.parse();
585
+ `)),console.log(a.white("\u{1F4C2} Path:"),o),console.log(a.white("\u{1F4E6} Type:"),n?`Project (${t.template})`:"Workspace"),console.log();return}let s;t.yes?(s={author:process.env.USER||"RapidKit User",description:n?`${t.template==="nestjs"?"NestJS":"FastAPI"} application generated with RapidKit`:void 0,package_manager:"npm"},console.log(a.gray(`Using default values (--yes flag)
586
+ `))):n?t.template.toLowerCase()==="fastapi"?s=await P.prompt([{type:"input",name:"author",message:"Author name:",default:process.env.USER||"RapidKit User"},{type:"input",name:"description",message:"Project description:",default:"FastAPI service generated with RapidKit"}]):s=await P.prompt([{type:"input",name:"author",message:"Author name:",default:process.env.USER||"RapidKit User"},{type:"input",name:"description",message:"Project description:",default:"NestJS application generated with RapidKit"},{type:"list",name:"package_manager",message:"Package manager:",choices:["npm","yarn","pnpm"],default:"npm"}]):s=await P.prompt([{type:"input",name:"author",message:"Author name:",default:process.env.USER||"RapidKit User"}]),n?await B(o,{name:e,template:t.template.toLowerCase(),author:s.author,description:s.description,package_manager:s.package_manager,skipGit:t.skipGit,skipInstall:t.skipInstall}):await F(o,{name:e,author:s.author,skipGit:t.skipGit});}catch(i){i instanceof v?(c.error(`
587
+ \u274C ${i.message}`),i.details&&c.warn(`\u{1F4A1} ${i.details}`),c.debug("Error code:",i.code)):(c.error(`
588
+ \u274C An unexpected error occurred:`),console.error(i)),process.exit(1);}finally{h=null;}});function le(){console.log(a.white(`Usage: npx rapidkit <name> [options]
589
+ `)),console.log(a.bold("Create a workspace (recommended):")),console.log(a.cyan(" npx rapidkit my-workspace")),console.log(a.cyan(" cd my-workspace")),console.log(a.cyan(" rapidkit create my-api --template fastapi")),console.log(a.cyan(" cd my-api")),console.log(a.cyan(` rapidkit dev
590
+ `)),console.log(a.bold("Or create a project directly:")),console.log(a.cyan(" npx rapidkit my-project --template fastapi")),console.log(a.cyan(` npx rapidkit my-project --template nestjs
591
+ `)),console.log(a.bold("Options:")),console.log(a.gray(" -t, --template <template> Create project with template (fastapi, nestjs)")),console.log(a.gray(" -y, --yes Skip prompts and use defaults")),console.log(a.gray(" --skip-git Skip git initialization")),console.log(a.gray(" --skip-install Skip installing dependencies")),console.log(a.gray(" --debug Enable debug logging")),console.log(a.gray(` --dry-run Show what would be created
592
+ `)),console.log(a.bold("Templates:")),console.log(a.gray(" fastapi FastAPI + Python")),console.log(a.gray(` nestjs NestJS + TypeScript
593
+ `));}process.on("SIGINT",async()=>{if(!E){if(E=true,console.log(a.yellow(`
594
+
595
+ \u26A0\uFE0F Interrupted by user`)),h&&await k.pathExists(h)){console.log(a.gray("Cleaning up partial installation..."));try{await k.remove(h),console.log(a.green("\u2713 Cleanup complete"));}catch(e){c.debug("Cleanup failed:",e);}}process.exit(130);}});process.on("SIGTERM",async()=>{if(!E){if(E=true,c.debug("Received SIGTERM"),h&&await k.pathExists(h))try{await k.remove(h);}catch(e){c.debug("Cleanup failed:",e);}process.exit(143);}});I.parse();