rapidkit 0.11.1 โ 0.11.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +3 -3
- package/dist/index.js +19 -19
- package/dist/package.json +1 -1
- package/package.json +1 -1
- package/templates/kits/fastapi-standard/README.md.j2 +6 -5
- package/templates/kits/fastapi-standard/src/cli.py.j2 +10 -8
- package/templates/kits/fastapi-standard/src/routing/__init__.py.j2 +1 -1
- package/templates/kits/fastapi-standard/src/routing/health.py.j2 +20 -1
package/README.md
CHANGED
|
@@ -335,7 +335,7 @@ npx rapidkit my-workspace --test-mode
|
|
|
335
335
|
4. **Navigate and run**:
|
|
336
336
|
```bash
|
|
337
337
|
cd api-service
|
|
338
|
-
rapidkit
|
|
338
|
+
rapidkit dev
|
|
339
339
|
```
|
|
340
340
|
|
|
341
341
|
5. **Create more projects** (from workspace root):
|
|
@@ -421,7 +421,7 @@ After setting up your demo project:
|
|
|
421
421
|
## Related Projects
|
|
422
422
|
|
|
423
423
|
- **RapidKit Python** - The core framework (coming soon to PyPI)
|
|
424
|
-
- **RapidKit Marketplace** - Browse and share modules (https://rapidkit.
|
|
424
|
+
- **RapidKit Marketplace** - Browse and share modules (https://rapidkit.top)
|
|
425
425
|
- **GitHub**: https://github.com/getrapidkit
|
|
426
426
|
|
|
427
427
|
## Contributing
|
|
@@ -481,7 +481,7 @@ MIT
|
|
|
481
481
|
## Support
|
|
482
482
|
|
|
483
483
|
- ๐ Report issues: [GitHub Issues](https://github.com/getrapidkit/rapidkit-npm/issues)
|
|
484
|
-
- ๐ Docs: https://rapidkit.
|
|
484
|
+
- ๐ Docs: https://rapidkit.top
|
|
485
485
|
- ๐ฌ Community: Coming soon
|
|
486
486
|
|
|
487
487
|
---
|
package/dist/index.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
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
|
|
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
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
4
|
|
|
5
5
|
Troubleshooting:
|
|
@@ -8,20 +8,20 @@ Troubleshooting:
|
|
|
8
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
9
|
1. Demo mode: npx rapidkit my-workspace --demo
|
|
10
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,
|
|
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
12
|
__pycache__/
|
|
13
13
|
*.pyc
|
|
14
14
|
.env
|
|
15
15
|
.rapidkit-workspace/
|
|
16
|
-
`,"utf-8"),await execa("git",["add","."],{cwd:
|
|
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
17
|
\u2728 RapidKit environment created successfully!
|
|
18
|
-
`)),console.log(i.cyan("\u{1F4C2} Location:"),i.white(
|
|
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> &&
|
|
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
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
|
|
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
22
|
`));}catch(v){u.fail("Failed to create RapidKit environment"),console.error(i.red(`
|
|
23
|
-
\u274C Error:`),v);try{await h.remove(
|
|
24
|
-
package-mode = false`);if(await promises.writeFile(m,a,"utf-8"),o.succeed("Poetry project initialized"),o.start("Installing RapidKit"),r){let
|
|
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
25
|
`,"utf-8");}async function ae(t,e){let r=`# RapidKit Workspace
|
|
26
26
|
|
|
27
27
|
This directory contains a RapidKit development environment.
|
|
@@ -59,14 +59,14 @@ Interactive mode will guide you through selecting a kit and configuring your pro
|
|
|
59
59
|
|
|
60
60
|
\`\`\`bash
|
|
61
61
|
cd my-project
|
|
62
|
-
# Install dependencies:
|
|
63
|
-
|
|
62
|
+
# Install dependencies (preferred):
|
|
63
|
+
rapidkit init
|
|
64
64
|
|
|
65
|
-
# Run the server (
|
|
66
|
-
rapidkit
|
|
65
|
+
# Run the server (project-aware):
|
|
66
|
+
rapidkit dev
|
|
67
67
|
|
|
68
|
-
# Or with poetry run:
|
|
69
|
-
poetry run rapidkit
|
|
68
|
+
# Or with poetry run (manual / advanced):
|
|
69
|
+
poetry run rapidkit dev
|
|
70
70
|
|
|
71
71
|
# Or manually:
|
|
72
72
|
uvicorn src.main:app --reload
|
|
@@ -88,7 +88,7 @@ rapidkit modules list
|
|
|
88
88
|
|
|
89
89
|
- \`rapidkit create\` - Create a new project (interactive)
|
|
90
90
|
- \`rapidkit create project <kit> <name>\` - Create project with specific kit
|
|
91
|
-
- \`rapidkit
|
|
91
|
+
- \`rapidkit dev\` - Run development server
|
|
92
92
|
- \`rapidkit add module <name>\` - Add a module (e.g., \`rapidkit add module settings\`)
|
|
93
93
|
- \`rapidkit list\` - List available kits
|
|
94
94
|
- \`rapidkit modules\` - List available modules
|
|
@@ -98,7 +98,7 @@ rapidkit modules list
|
|
|
98
98
|
|
|
99
99
|
## RapidKit Documentation
|
|
100
100
|
|
|
101
|
-
For full documentation, visit: [RapidKit Docs](https://rapidkit.
|
|
101
|
+
For full documentation, visit: [RapidKit Docs](https://rapidkit.top) *(or appropriate URL)*
|
|
102
102
|
|
|
103
103
|
## Workspace Structure
|
|
104
104
|
|
|
@@ -210,7 +210,7 @@ Each generated demo project contains:
|
|
|
210
210
|
1. **Explore the Generated Code** - Check out \`src/main.py\` and \`src/routing/\`
|
|
211
211
|
2. **Add Routes** - Create new endpoints in \`src/routing/\`
|
|
212
212
|
3. **Install Full RapidKit** - For advanced features: \`pipx install rapidkit\`
|
|
213
|
-
4. **Read the Documentation** - Visit [RapidKit Docs](https://rapidkit.
|
|
213
|
+
4. **Read the Documentation** - Visit [RapidKit Docs](https://rapidkit.top)
|
|
214
214
|
|
|
215
215
|
## \u26A0\uFE0F Demo Mode Limitations
|
|
216
216
|
|
|
@@ -261,7 +261,7 @@ __pycache__/
|
|
|
261
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
262
|
\u2728 Demo workspace created successfully!
|
|
263
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
|
|
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
265
|
\u{1F50D} Dry-run mode - showing what would be created:
|
|
266
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
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(`
|
|
@@ -270,7 +270,7 @@ __pycache__/
|
|
|
270
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
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
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=
|
|
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
|
|
274
274
|
__pycache__/
|
|
275
275
|
*.py[cod]
|
|
276
276
|
*$py.class
|
package/dist/package.json
CHANGED
package/package.json
CHANGED
|
@@ -5,16 +5,17 @@ A minimal FastAPI service generated with the **FastAPI Standard Kit**. All domai
|
|
|
5
5
|
## Quick start
|
|
6
6
|
|
|
7
7
|
```bash
|
|
8
|
-
|
|
9
|
-
|
|
8
|
+
rapidkit init # bootstrap the project (preferred)
|
|
9
|
+
rapidkit dev
|
|
10
10
|
```
|
|
11
11
|
|
|
12
12
|
## Available commands
|
|
13
13
|
|
|
14
14
|
```bash
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
poetry run
|
|
15
|
+
rapidkit init # ๐ง Bootstrap the project (create local launcher & install deps)
|
|
16
|
+
rapidkit dev # ๐ Start development server with hot reload
|
|
17
|
+
poetry run start # โก Advanced: start production server via poetry
|
|
18
|
+
poetry run build # ๐ฆ Advanced: build via poetry
|
|
18
19
|
poetry run test # ๐งช Run tests
|
|
19
20
|
```
|
|
20
21
|
|
|
@@ -95,7 +95,8 @@ def dev() -> None:
|
|
|
95
95
|
"""๐ Start development server with hot reload
|
|
96
96
|
|
|
97
97
|
Usage:
|
|
98
|
-
|
|
98
|
+
rapidkit dev [options] # preferred (project-aware)
|
|
99
|
+
# or: poetry run dev [options]
|
|
99
100
|
|
|
100
101
|
Options:
|
|
101
102
|
--port, -p PORT Server port (default: 8000)
|
|
@@ -103,9 +104,10 @@ def dev() -> None:
|
|
|
103
104
|
--env, -e ENV Environment (default: development)
|
|
104
105
|
|
|
105
106
|
Examples:
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
107
|
+
rapidkit dev
|
|
108
|
+
rapidkit dev --port 3000
|
|
109
|
+
rapidkit dev --host 127.0.0.1 --port 8080
|
|
110
|
+
# or: poetry run dev --port 3000
|
|
109
111
|
"""
|
|
110
112
|
_print_banner("๐", "Starting development server with hot reload...")
|
|
111
113
|
_print_banner("๐", f"Working directory: {Path.cwd()}")
|
|
@@ -175,7 +177,7 @@ def build() -> None:
|
|
|
175
177
|
_print_error(f"Build failed: {e}")
|
|
176
178
|
sys.exit(1)
|
|
177
179
|
except FileNotFoundError:
|
|
178
|
-
_print_error("Build tools not found. Install with: poetry install --group dev")
|
|
180
|
+
_print_error("Build tools not found. Install with: rapidkit init (or: poetry install --group dev)")
|
|
179
181
|
sys.exit(1)
|
|
180
182
|
|
|
181
183
|
|
|
@@ -214,7 +216,7 @@ def test() -> None:
|
|
|
214
216
|
sys.exit(result.returncode)
|
|
215
217
|
|
|
216
218
|
except FileNotFoundError:
|
|
217
|
-
_print_error("pytest not found. Install with: poetry install --group dev")
|
|
219
|
+
_print_error("pytest not found. Install with: rapidkit init (or: poetry install --group dev)")
|
|
218
220
|
sys.exit(1)
|
|
219
221
|
|
|
220
222
|
|
|
@@ -247,7 +249,7 @@ def lint() -> None:
|
|
|
247
249
|
_print_error("Linting failed! Run 'poetry run format' to fix issues.")
|
|
248
250
|
sys.exit(1)
|
|
249
251
|
except FileNotFoundError:
|
|
250
|
-
_print_error("Linting tools not found. Install with: poetry install --group dev")
|
|
252
|
+
_print_error("Linting tools not found. Install with: rapidkit init (or: poetry install --group dev)")
|
|
251
253
|
sys.exit(1)
|
|
252
254
|
|
|
253
255
|
|
|
@@ -280,7 +282,7 @@ def format() -> None:
|
|
|
280
282
|
_print_error(f"Formatting failed: {e}")
|
|
281
283
|
sys.exit(1)
|
|
282
284
|
except FileNotFoundError:
|
|
283
|
-
_print_error("Formatting tools not found. Install with: poetry install --group dev")
|
|
285
|
+
_print_error("Formatting tools not found. Install with: rapidkit init (or: poetry install --group dev)")
|
|
284
286
|
sys.exit(1)
|
|
285
287
|
|
|
286
288
|
|
|
@@ -4,10 +4,29 @@ from __future__ import annotations
|
|
|
4
4
|
|
|
5
5
|
from fastapi import APIRouter
|
|
6
6
|
|
|
7
|
-
|
|
7
|
+
try:
|
|
8
|
+
from src.health.registry import (
|
|
9
|
+
list_registered_health_routes as _list_registered_health_routes,
|
|
10
|
+
)
|
|
11
|
+
except ImportError: # pragma: no cover - registry not generated yet
|
|
12
|
+
def _list_registered_health_routes(
|
|
13
|
+
prefix: str = "/api/health",
|
|
14
|
+
) -> list[dict[str, str]]:
|
|
15
|
+
return []
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
router = APIRouter(prefix="/health", tags=["health"])
|
|
8
19
|
|
|
9
20
|
|
|
10
21
|
@router.get("/", summary="Health check")
|
|
11
22
|
async def heartbeat() -> dict[str, str]:
|
|
12
23
|
"""Return basic service heartbeat."""
|
|
24
|
+
|
|
13
25
|
return {"status": "ok"}
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
@router.get("/modules", summary="Registered module health endpoints")
|
|
29
|
+
async def module_health_catalog() -> dict[str, list[dict[str, str]]]:
|
|
30
|
+
"""Expose metadata for module-provided health routers."""
|
|
31
|
+
|
|
32
|
+
return {"routes": _list_registered_health_routes()}
|