rapidkit 0.40.1 → 0.41.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +48 -7
- package/contracts/agent-customization-pack.v1.json +52 -2
- package/contracts/extension-cli-compatibility.v1.json +14 -2
- package/contracts/runtime-command-surface.v1.json +7 -1
- package/contracts/workspace-intelligence/agent-action-outcome.v1.json +38 -0
- package/contracts/workspace-intelligence/blocker-resolution.v1.json +65 -0
- package/contracts/workspace-intelligence/doctor-fix-result.v1.json +34 -0
- package/contracts/workspace-intelligence/studio-blocker-handoff.v1.json +91 -0
- package/contracts/workspace-intelligence/workspace-contract-verify.v1.json +51 -0
- package/contracts/workspace-intelligence/workspace-dependency-graph.v1.json +61 -1
- package/contracts/workspace-intelligence/workspace-explain.v1.json +31 -0
- package/contracts/workspace-intelligence/workspace-intelligence-history.v1.json +36 -0
- package/contracts/workspace-intelligence/workspace-operational-skill.v1.json +37 -0
- package/contracts/workspace-intelligence/workspace-skills-index.v1.json +27 -0
- package/dist/analyze-QYHMGLSG.js +1 -0
- package/dist/autopilot-release-AHMQEUFH.js +1 -0
- package/dist/chunk-33LR2QEM.js +2 -0
- package/dist/chunk-3PTJID76.js +2 -0
- package/dist/chunk-46AGNYI7.js +50 -0
- package/dist/chunk-64RTZBHU.js +2 -0
- package/dist/chunk-AQ4XZZC6.js +1 -0
- package/dist/{chunk-RXWM5DSC.js → chunk-BFEBZABL.js} +3 -3
- package/dist/{chunk-3YLMCP3V.js → chunk-CDCYRBAY.js} +1 -1
- package/dist/chunk-CDPR2YKL.js +13 -0
- package/dist/chunk-CKXJR3YT.js +7 -0
- package/dist/chunk-E5ZVQL3C.js +13 -0
- package/dist/chunk-ELU3G6DQ.js +9 -0
- package/dist/chunk-EN6YCX36.js +1 -0
- package/dist/chunk-FMBSON6H.js +33 -0
- package/dist/chunk-GBJBQ43T.js +1 -0
- package/dist/chunk-ICGWHIMK.js +1 -0
- package/dist/{chunk-4FJQWL7P.js → chunk-ITJ6RKUW.js} +3 -3
- package/dist/{workspace-graph-ICB7OVAZ.js → chunk-JEI6BTZI.js} +1 -1
- package/dist/{chunk-G76C74EV.js → chunk-JU3VNLTY.js} +1 -1
- package/dist/chunk-JW2FSKT3.js +2 -0
- package/dist/chunk-KIUSCFHF.js +1 -0
- package/dist/chunk-LKX3L7TE.js +2 -0
- package/dist/chunk-MIWDCR6I.js +2 -0
- package/dist/{chunk-6G2KSHP6.js → chunk-OLDPVVSV.js} +1 -1
- package/dist/{chunk-4Q2ZZKGB.js → chunk-PCXSTKZ5.js} +1 -1
- package/dist/{chunk-6KD5F6LX.js → chunk-Q2KZIBV4.js} +1 -1
- package/dist/{chunk-ERCD6NFF.js → chunk-RSYUNEH7.js} +13 -13
- package/dist/chunk-TJN7G2MA.js +1 -0
- package/dist/chunk-UQR6G7KH.js +32 -0
- package/dist/chunk-VMJA36WD.js +1 -0
- package/dist/chunk-WRMCPKGA.js +1 -0
- package/dist/{create-XVDDQA42.js → create-RNP5ACQL.js} +1 -1
- package/dist/demo-kit-N5U3NGAE.js +149 -0
- package/dist/{doctor-UOLOGJ2Z.js → doctor-XM6QDTDC.js} +1 -1
- package/dist/{dotnet-webapi-clean-RTBRPDPL.js → dotnet-webapi-clean-K33C77EI.js} +1 -1
- package/dist/{gofiber-standard-UGIRKPKL.js → gofiber-standard-BQ4HCXL2.js} +1 -1
- package/dist/{gogin-standard-HJ7SPFNT.js → gogin-standard-PUBCYW3A.js} +1 -1
- package/dist/index.d.ts +45 -7
- package/dist/index.js +145 -127
- package/dist/{pipeline-XK62WL4D.js → pipeline-DH6Z47O4.js} +1 -1
- package/dist/platform-capabilities-TSLK667K.js +1 -0
- package/dist/{pythonRapidkitExec-MNWRC4F2.js → pythonRapidkitExec-SGKW76XM.js} +1 -1
- package/dist/{springboot-standard-IWJSVDLZ.js → springboot-standard-XFVQI37R.js} +1 -1
- package/dist/{workspace-L4ITCKMM.js → workspace-E554C5SM.js} +1 -1
- package/dist/workspace-agent-sync-2HRPM5ZD.js +1 -0
- package/dist/{workspace-context-NMMQMHNU.js → workspace-context-VJTXW3K4.js} +1 -1
- package/dist/workspace-contract-OO4GMENV.js +1 -0
- package/dist/workspace-explain-3WSJLIJ6.js +1 -0
- package/dist/workspace-explain-contract-24RQ7KIW.js +1 -0
- package/dist/workspace-feedback-65NR3EZH.js +1 -0
- package/dist/{workspace-foundation-HNIRAIBF.js → workspace-foundation-LISDH53T.js} +1 -1
- package/dist/workspace-graph-2A5THUCI.js +1 -0
- package/dist/workspace-history-VPDADQKG.js +1 -0
- package/dist/{workspace-intelligence-64IWAYHS.js → workspace-intelligence-E3KXEZCM.js} +1 -1
- package/dist/workspace-mcp-serve-RFYDCA2L.js +3 -0
- package/dist/workspace-model-YL7W3573.js +1 -0
- package/dist/workspace-registry-summary-X5WRUU3T.js +1 -0
- package/dist/workspace-run-GCIQD73R.js +1 -0
- package/dist/workspace-verify-NRYH7RNB.js +1 -0
- package/dist/workspace-watch-H2AETGFI.js +1 -0
- package/docs/DEVELOPMENT.md +1 -1
- package/docs/OPEN_SOURCE_USER_SCENARIOS.md +1 -1
- package/docs/README.md +1 -1
- package/docs/commands-reference.md +10 -2
- package/docs/contracts/ARTIFACT_CATALOG.md +3 -1
- package/docs/contracts/NAMING_AND_COEXISTENCE.md +58 -0
- package/docs/workspace-run.md +25 -1
- package/package.json +7 -3
- package/scripts/enterprise-package-smoke.mjs +427 -0
- package/scripts/prepack-enterprise.mjs +40 -0
- package/templates/generator.js +175 -0
- package/templates/kits/fastapi-ddd/README.md.j2 +122 -0
- package/templates/kits/fastapi-ddd/common/env.example.j2 +10 -0
- package/templates/kits/fastapi-ddd/env.example.j2 +1 -0
- package/templates/kits/fastapi-ddd/pyproject.toml.j2 +64 -0
- package/templates/kits/fastapi-ddd/src/__init__.py.j2 +3 -0
- package/templates/kits/fastapi-ddd/src/app/__init__.py.j2 +11 -0
- package/templates/kits/fastapi-ddd/src/app/application/__init__.py.j2 +5 -0
- package/templates/kits/fastapi-ddd/src/app/application/interfaces.py.j2 +43 -0
- package/templates/kits/fastapi-ddd/src/app/application/use_cases/__init__.py.j2 +6 -0
- package/templates/kits/fastapi-ddd/src/app/application/use_cases/health.py.j2 +14 -0
- package/templates/kits/fastapi-ddd/src/app/application/use_cases/notes.py.j2 +24 -0
- package/templates/kits/fastapi-ddd/src/app/config/__init__.py.j2 +16 -0
- package/templates/kits/fastapi-ddd/src/app/domain/__init__.py.j2 +3 -0
- package/templates/kits/fastapi-ddd/src/app/domain/models/__init__.py.j2 +6 -0
- package/templates/kits/fastapi-ddd/src/app/domain/models/health.py.j2 +16 -0
- package/templates/kits/fastapi-ddd/src/app/domain/models/note.py.j2 +27 -0
- package/templates/kits/fastapi-ddd/src/app/infrastructure/__init__.py.j2 +5 -0
- package/templates/kits/fastapi-ddd/src/app/infrastructure/repositories/__init__.py.j2 +6 -0
- package/templates/kits/fastapi-ddd/src/app/infrastructure/repositories/health.py.j2 +17 -0
- package/templates/kits/fastapi-ddd/src/app/infrastructure/repositories/notes.py.j2 +28 -0
- package/templates/kits/fastapi-ddd/src/app/main.py.j2 +61 -0
- package/templates/kits/fastapi-ddd/src/app/presentation/__init__.py.j2 +3 -0
- package/templates/kits/fastapi-ddd/src/app/presentation/api/__init__.py.j2 +5 -0
- package/templates/kits/fastapi-ddd/src/app/presentation/api/dependencies/__init__.py.j2 +19 -0
- package/templates/kits/fastapi-ddd/src/app/presentation/api/router.py.j2 +10 -0
- package/templates/kits/fastapi-ddd/src/app/presentation/api/routes/__init__.py.j2 +5 -0
- package/templates/kits/fastapi-ddd/src/app/presentation/api/routes/health.py.j2 +27 -0
- package/templates/kits/fastapi-ddd/src/app/presentation/api/routes/notes.py.j2 +50 -0
- package/templates/kits/fastapi-ddd/src/app/shared/__init__.py.j2 +5 -0
- package/templates/kits/fastapi-ddd/src/app/shared/result.py.j2 +28 -0
- package/templates/kits/fastapi-ddd/src/cli.py.j2 +167 -0
- package/templates/kits/fastapi-ddd/src/main.py.j2 +35 -0
- package/templates/kits/fastapi-ddd/src/modules/__init__.py.j2 +3 -0
- package/templates/kits/fastapi-ddd/src/routing/__init__.py.j2 +13 -0
- package/templates/kits/fastapi-ddd/src/routing/health.py.j2 +7 -0
- package/templates/kits/fastapi-ddd/src/routing/notes.py.j2 +7 -0
- package/templates/kits/fastapi-ddd/tests/__init__.py.j2 +1 -0
- package/templates/kits/fastapi-ddd/tests/test_app_factory.py.j2 +22 -0
- package/templates/kits/fastapi-ddd/tests/test_health.py.j2 +17 -0
- package/templates/kits/fastapi-ddd/tests/test_notes.py.j2 +27 -0
- package/templates/kits/fastapi-standard/README.md.j2 +145 -0
- package/templates/kits/fastapi-standard/common/env.example.j2 +10 -0
- package/templates/kits/fastapi-standard/env.example.j2 +1 -0
- package/templates/kits/fastapi-standard/pyproject.toml.j2 +64 -0
- package/templates/kits/fastapi-standard/src/__init__.py.j2 +3 -0
- package/templates/kits/fastapi-standard/src/cli.py.j2 +168 -0
- package/templates/kits/fastapi-standard/src/main.py.j2 +66 -0
- package/templates/kits/fastapi-standard/src/modules/__init__.py.j2 +3 -0
- package/templates/kits/fastapi-standard/src/routing/__init__.py.j2 +16 -0
- package/templates/kits/fastapi-standard/src/routing/examples.py.j2 +71 -0
- package/templates/kits/fastapi-standard/src/routing/health.py.j2 +22 -0
- package/templates/kits/fastapi-standard/tests/__init__.py.j2 +1 -0
- package/templates/kits/fastapi-standard/tests/test_examples.py.j2 +29 -0
- package/templates/kits/fastapi-standard/tests/test_health.py.j2 +17 -0
- package/templates/kits/nestjs-standard/Dockerfile.j2 +41 -0
- package/templates/kits/nestjs-standard/README.md.j2 +139 -0
- package/templates/kits/nestjs-standard/docker-compose.yml.j2 +94 -0
- package/templates/kits/nestjs-standard/docs/README.md.j2 +15 -0
- package/templates/kits/nestjs-standard/env.example.j2 +18 -0
- package/templates/kits/nestjs-standard/eslint.config.cjs.j2 +9 -0
- package/templates/kits/nestjs-standard/jest.config.ts.j2 +22 -0
- package/templates/kits/nestjs-standard/nest-cli.json.j2 +10 -0
- package/templates/kits/nestjs-standard/package.json.j2 +101 -0
- package/templates/kits/nestjs-standard/src/app.controller.ts.j2 +14 -0
- package/templates/kits/nestjs-standard/src/app.module.ts.j2 +26 -0
- package/templates/kits/nestjs-standard/src/app.service.ts.j2 +16 -0
- package/templates/kits/nestjs-standard/src/auth/auth.controller.ts.j2 +20 -0
- package/templates/kits/nestjs-standard/src/auth/auth.module.ts.j2 +13 -0
- package/templates/kits/nestjs-standard/src/auth/auth.service.ts.j2 +6 -0
- package/templates/kits/nestjs-standard/src/auth/entities/token.entity.ts.j2 +3 -0
- package/templates/kits/nestjs-standard/src/auth/entities/user.entity.ts.j2 +3 -0
- package/templates/kits/nestjs-standard/src/auth/entities/webauthn.entity.ts.j2 +3 -0
- package/templates/kits/nestjs-standard/src/config/configuration.ts.j2 +85 -0
- package/templates/kits/nestjs-standard/src/config/index.ts.j2 +2 -0
- package/templates/kits/nestjs-standard/src/config/validation.ts.j2 +21 -0
- package/templates/kits/nestjs-standard/src/examples/dto/create-note.dto.ts.j2 +11 -0
- package/templates/kits/nestjs-standard/src/examples/examples.controller.ts.j2 +24 -0
- package/templates/kits/nestjs-standard/src/examples/examples.module.ts.j2 +10 -0
- package/templates/kits/nestjs-standard/src/examples/examples.service.ts.j2 +33 -0
- package/templates/kits/nestjs-standard/src/main.ts.j2 +53 -0
- package/templates/kits/nestjs-standard/src/modules/index.ts.j2 +25 -0
- package/templates/kits/nestjs-standard/test/app.controller.spec.ts.j2 +24 -0
- package/templates/kits/nestjs-standard/test/app.e2e-spec.ts.j2 +60 -0
- package/templates/kits/nestjs-standard/test/examples.controller.spec.ts.j2 +28 -0
- package/templates/kits/nestjs-standard/test/jest-e2e.json.j2 +15 -0
- package/templates/kits/nestjs-standard/tsconfig.build.json.j2 +12 -0
- package/templates/kits/nestjs-standard/tsconfig.json.j2 +26 -0
- package/dist/analyze-RHQM4AB2.js +0 -1
- package/dist/autopilot-release-OJTLXPMX.js +0 -1
- package/dist/chunk-5VBRMLRU.js +0 -7
- package/dist/chunk-7VI4U7Q5.js +0 -2
- package/dist/chunk-FV5A3N3I.js +0 -2
- package/dist/chunk-GDGATWR5.js +0 -2
- package/dist/chunk-GOM3RFB3.js +0 -2
- package/dist/chunk-GX7UU7LL.js +0 -33
- package/dist/chunk-KYH364KQ.js +0 -1
- package/dist/chunk-OWNGSAO3.js +0 -2
- package/dist/chunk-QPEBI6AB.js +0 -2
- package/dist/chunk-TYZPPUBH.js +0 -1
- package/dist/chunk-VQMZC5TC.js +0 -9
- package/dist/chunk-WHCON2VN.js +0 -50
- package/dist/chunk-X7PWDIQW.js +0 -1
- package/dist/chunk-Z5LKRG57.js +0 -1
- package/dist/chunk-ZWKLRZE5.js +0 -13
- package/dist/demo-kit-RWGOEDW4.js +0 -141
- package/dist/workspace-agent-sync-G7JU77IK.js +0 -25
- package/dist/workspace-contract-D5O4OZD5.js +0 -1
- package/dist/workspace-history-LHUTLE3S.js +0 -1
- package/dist/workspace-model-SDHH5RBC.js +0 -1
- package/dist/workspace-registry-summary-MIPHVB56.js +0 -1
- package/dist/workspace-run-SPP32MPV.js +0 -1
- package/dist/workspace-verify-6Q6MGRG6.js +0 -1
- package/dist/workspace-watch-JDXVGW4H.js +0 -1
|
@@ -0,0 +1,168 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
"""Project CLI wrapper for {{ project_name }}.
|
|
3
|
+
|
|
4
|
+
This file prefers a per-project CLI (generated at `.rapidkit/cli.py`) when
|
|
5
|
+
available. If not present it prints helpful guidance directing users to
|
|
6
|
+
`rapidkit init` and does not attempt to make assumptions about a packaging
|
|
7
|
+
environment.
|
|
8
|
+
"""
|
|
9
|
+
|
|
10
|
+
import importlib.util
|
|
11
|
+
import sys
|
|
12
|
+
import argparse
|
|
13
|
+
from pathlib import Path
|
|
14
|
+
from typing import Optional
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
def _missing_cli(name: str) -> None:
|
|
18
|
+
print(f"❌ Missing project-local CLI (.rapidkit/cli.py) - can't run '{name}'")
|
|
19
|
+
print("💡 If you're a new user run: rapidkit init # create venv + install deps")
|
|
20
|
+
sys.exit(127)
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
def _load_project_cli_module() -> Optional[object]:
|
|
24
|
+
project_root = Path(__file__).resolve().parents[1]
|
|
25
|
+
cli_file = project_root / ".rapidkit" / "cli.py"
|
|
26
|
+
if not cli_file.exists():
|
|
27
|
+
return None
|
|
28
|
+
spec = importlib.util.spec_from_file_location("project_cli", str(cli_file))
|
|
29
|
+
if spec is None or spec.loader is None:
|
|
30
|
+
return None
|
|
31
|
+
module = importlib.util.module_from_spec(spec)
|
|
32
|
+
spec.loader.exec_module(module) # type: ignore
|
|
33
|
+
return module
|
|
34
|
+
|
|
35
|
+
|
|
36
|
+
_mod = _load_project_cli_module()
|
|
37
|
+
|
|
38
|
+
|
|
39
|
+
# Default placeholders -- call `_missing_cli` if the project-local CLI isn't
|
|
40
|
+
# available. These are real functions so linters don't complain.
|
|
41
|
+
def init() -> None:
|
|
42
|
+
_missing_cli("init")
|
|
43
|
+
|
|
44
|
+
|
|
45
|
+
def dev() -> None:
|
|
46
|
+
_missing_cli("dev")
|
|
47
|
+
|
|
48
|
+
|
|
49
|
+
def start() -> None:
|
|
50
|
+
_missing_cli("start")
|
|
51
|
+
|
|
52
|
+
|
|
53
|
+
def build() -> None:
|
|
54
|
+
_missing_cli("build")
|
|
55
|
+
|
|
56
|
+
|
|
57
|
+
def test() -> None:
|
|
58
|
+
_missing_cli("test")
|
|
59
|
+
|
|
60
|
+
|
|
61
|
+
def lint() -> None:
|
|
62
|
+
_missing_cli("lint")
|
|
63
|
+
|
|
64
|
+
|
|
65
|
+
def format() -> None: # type: ignore[misc]
|
|
66
|
+
_missing_cli("format")
|
|
67
|
+
|
|
68
|
+
|
|
69
|
+
def help_cmd() -> None:
|
|
70
|
+
print("Usage: poetry run <command> # (init|dev|start|build|test|lint|format)")
|
|
71
|
+
|
|
72
|
+
|
|
73
|
+
if _mod is not None:
|
|
74
|
+
# prefer project-provided implementations when available
|
|
75
|
+
init = getattr(_mod, "init", init)
|
|
76
|
+
dev = getattr(_mod, "dev", dev)
|
|
77
|
+
start = getattr(_mod, "start", start)
|
|
78
|
+
build = getattr(_mod, "build", build)
|
|
79
|
+
test = getattr(_mod, "test", test)
|
|
80
|
+
lint = getattr(_mod, "lint", lint)
|
|
81
|
+
format = getattr(_mod, "format", format)
|
|
82
|
+
help_cmd = getattr(_mod, "help_cmd", help_cmd)
|
|
83
|
+
|
|
84
|
+
|
|
85
|
+
_dev_impl = dev
|
|
86
|
+
_start_impl = start
|
|
87
|
+
|
|
88
|
+
|
|
89
|
+
def _runtime_kwargs_from_argv(argv: list[str]) -> dict:
|
|
90
|
+
parser = argparse.ArgumentParser(add_help=False)
|
|
91
|
+
parser.add_argument("-p", "--port", type=int, dest="port")
|
|
92
|
+
parser.add_argument("--host", dest="host")
|
|
93
|
+
parser.add_argument("--allow-global-runtime", action="store_true", dest="allow_global_runtime")
|
|
94
|
+
ns, _ = parser.parse_known_args(argv)
|
|
95
|
+
|
|
96
|
+
kwargs = {}
|
|
97
|
+
if ns.port is not None:
|
|
98
|
+
kwargs["port"] = ns.port
|
|
99
|
+
if ns.host is not None:
|
|
100
|
+
kwargs["host"] = ns.host
|
|
101
|
+
if ns.allow_global_runtime:
|
|
102
|
+
kwargs["allow_global_runtime"] = True
|
|
103
|
+
return kwargs
|
|
104
|
+
|
|
105
|
+
|
|
106
|
+
def dev() -> None: # type: ignore[no-redef]
|
|
107
|
+
kwargs = _runtime_kwargs_from_argv(sys.argv[1:])
|
|
108
|
+
try:
|
|
109
|
+
_dev_impl(**kwargs)
|
|
110
|
+
except TypeError:
|
|
111
|
+
_dev_impl()
|
|
112
|
+
|
|
113
|
+
|
|
114
|
+
def start() -> None: # type: ignore[no-redef]
|
|
115
|
+
kwargs = _runtime_kwargs_from_argv(sys.argv[1:])
|
|
116
|
+
try:
|
|
117
|
+
_start_impl(**kwargs)
|
|
118
|
+
except TypeError:
|
|
119
|
+
_start_impl()
|
|
120
|
+
|
|
121
|
+
|
|
122
|
+
def main() -> None:
|
|
123
|
+
if len(sys.argv) < 2:
|
|
124
|
+
help_cmd()
|
|
125
|
+
return
|
|
126
|
+
|
|
127
|
+
command = sys.argv[1]
|
|
128
|
+
commands = {
|
|
129
|
+
"init": init,
|
|
130
|
+
"dev": dev,
|
|
131
|
+
"start": start,
|
|
132
|
+
"build": build,
|
|
133
|
+
"test": test,
|
|
134
|
+
"lint": lint,
|
|
135
|
+
"format": format,
|
|
136
|
+
"help": help_cmd,
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
if command in commands:
|
|
140
|
+
if command in ("dev", "start"):
|
|
141
|
+
parser = argparse.ArgumentParser(prog=f"poetry run {command}", add_help=False)
|
|
142
|
+
parser.add_argument("-p", "--port", type=int, dest="port")
|
|
143
|
+
parser.add_argument("--host", dest="host")
|
|
144
|
+
parser.add_argument("--allow-global-runtime", action="store_true", dest="allow_global_runtime")
|
|
145
|
+
ns, _ = parser.parse_known_args(sys.argv[2:])
|
|
146
|
+
|
|
147
|
+
kwargs = {}
|
|
148
|
+
if ns.port is not None:
|
|
149
|
+
kwargs["port"] = ns.port
|
|
150
|
+
if ns.host is not None:
|
|
151
|
+
kwargs["host"] = ns.host
|
|
152
|
+
if ns.allow_global_runtime:
|
|
153
|
+
kwargs["allow_global_runtime"] = True
|
|
154
|
+
|
|
155
|
+
try:
|
|
156
|
+
commands[command](**kwargs)
|
|
157
|
+
except TypeError:
|
|
158
|
+
commands[command]()
|
|
159
|
+
else:
|
|
160
|
+
commands[command]()
|
|
161
|
+
else:
|
|
162
|
+
print(f"Unknown command: {command}")
|
|
163
|
+
print("Run 'poetry run help' to see available commands.")
|
|
164
|
+
sys.exit(1)
|
|
165
|
+
|
|
166
|
+
|
|
167
|
+
if __name__ == "__main__":
|
|
168
|
+
main()
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
"""{{ project_name }} application entrypoint."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
from collections.abc import AsyncIterator
|
|
6
|
+
from contextlib import asynccontextmanager
|
|
7
|
+
|
|
8
|
+
from fastapi import FastAPI
|
|
9
|
+
from fastapi.middleware.cors import CORSMiddleware
|
|
10
|
+
|
|
11
|
+
# <<<inject:imports>>>
|
|
12
|
+
|
|
13
|
+
try:
|
|
14
|
+
# canonical health package
|
|
15
|
+
from src.health import register_health_routes as _core_register_health_routes
|
|
16
|
+
except ImportError: # pragma: no cover - health package not generated yet
|
|
17
|
+
|
|
18
|
+
def _register_health_routes(_: FastAPI) -> None:
|
|
19
|
+
return None
|
|
20
|
+
|
|
21
|
+
else:
|
|
22
|
+
|
|
23
|
+
def _register_health_routes(app: FastAPI) -> None:
|
|
24
|
+
try:
|
|
25
|
+
_core_register_health_routes(app)
|
|
26
|
+
except Exception: # pragma: no cover - defensive best-effort registration
|
|
27
|
+
return None
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
from .routing import api_router
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
@asynccontextmanager
|
|
34
|
+
async def lifespan(app: FastAPI) -> AsyncIterator[None]:
|
|
35
|
+
"""Coordinate startup/shutdown hooks contributed by RapidKit modules."""
|
|
36
|
+
|
|
37
|
+
_ = app # ensure the app reference stays available for injected hooks
|
|
38
|
+
# <<<inject:startup>>>
|
|
39
|
+
try:
|
|
40
|
+
yield
|
|
41
|
+
finally:
|
|
42
|
+
# <<<inject:shutdown>>>
|
|
43
|
+
pass
|
|
44
|
+
|
|
45
|
+
|
|
46
|
+
app = FastAPI(
|
|
47
|
+
title="{{ project_name }}",
|
|
48
|
+
description="{{ description }}",
|
|
49
|
+
version="{{ app_version }}",
|
|
50
|
+
docs_url="/docs",
|
|
51
|
+
redoc_url="/redoc",
|
|
52
|
+
lifespan=lifespan,
|
|
53
|
+
)
|
|
54
|
+
|
|
55
|
+
app.add_middleware(
|
|
56
|
+
CORSMiddleware,
|
|
57
|
+
allow_origins=["*"],
|
|
58
|
+
allow_credentials=True,
|
|
59
|
+
allow_methods=["*"],
|
|
60
|
+
allow_headers=["*"],
|
|
61
|
+
)
|
|
62
|
+
|
|
63
|
+
app.include_router(api_router, prefix="/api")
|
|
64
|
+
# Expose module-provided health routers under /api/health/module/*
|
|
65
|
+
_register_health_routes(app)
|
|
66
|
+
# <<<inject:routes>>>
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
"""API router assembly."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
from fastapi import APIRouter
|
|
6
|
+
|
|
7
|
+
from .health import router as health_router
|
|
8
|
+
from .examples import router as examples_router
|
|
9
|
+
|
|
10
|
+
# <<<inject:router-imports>>>
|
|
11
|
+
|
|
12
|
+
api_router = APIRouter()
|
|
13
|
+
|
|
14
|
+
api_router.include_router(health_router, prefix="/health", tags=["health"])
|
|
15
|
+
api_router.include_router(examples_router, prefix="/examples", tags=["examples"])
|
|
16
|
+
# <<<inject:router-mount>>>
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
"""Sample in-memory notes endpoints to demonstrate RapidKit routing."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
from typing import Dict, List
|
|
6
|
+
|
|
7
|
+
from fastapi import APIRouter, HTTPException, status
|
|
8
|
+
from pydantic import BaseModel, Field
|
|
9
|
+
|
|
10
|
+
router = APIRouter(tags=["examples"])
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
class NoteCreate(BaseModel):
|
|
14
|
+
"""Payload for creating a note."""
|
|
15
|
+
|
|
16
|
+
title: str = Field(..., max_length=80)
|
|
17
|
+
body: str = Field(..., max_length=500)
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
class Note(NoteCreate):
|
|
21
|
+
"""Serialized note returned by the API."""
|
|
22
|
+
|
|
23
|
+
id: int
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
_STORE: Dict[int, Note] = {}
|
|
27
|
+
_NEXT_ID = 1
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
@router.post(
|
|
31
|
+
"/notes",
|
|
32
|
+
response_model=Note,
|
|
33
|
+
status_code=status.HTTP_201_CREATED,
|
|
34
|
+
summary="Create a note",
|
|
35
|
+
)
|
|
36
|
+
def create_note(payload: NoteCreate) -> Note:
|
|
37
|
+
"""Persist a note in memory and return it."""
|
|
38
|
+
|
|
39
|
+
global _NEXT_ID # noqa: PLW0603 - intentional in-memory auto increment
|
|
40
|
+
note = Note(id=_NEXT_ID, **payload.model_dump())
|
|
41
|
+
_STORE[_NEXT_ID] = note
|
|
42
|
+
_NEXT_ID += 1
|
|
43
|
+
return note
|
|
44
|
+
|
|
45
|
+
|
|
46
|
+
@router.get(
|
|
47
|
+
"/notes",
|
|
48
|
+
response_model=List[Note],
|
|
49
|
+
summary="List all notes",
|
|
50
|
+
)
|
|
51
|
+
def list_notes() -> List[Note]:
|
|
52
|
+
"""Return all notes stored so far."""
|
|
53
|
+
|
|
54
|
+
return list(_STORE.values())
|
|
55
|
+
|
|
56
|
+
|
|
57
|
+
@router.get(
|
|
58
|
+
"/notes/{note_id}",
|
|
59
|
+
response_model=Note,
|
|
60
|
+
summary="Retrieve a single note",
|
|
61
|
+
)
|
|
62
|
+
def get_note(note_id: int) -> Note:
|
|
63
|
+
"""Retrieve a note by identifier or raise 404."""
|
|
64
|
+
|
|
65
|
+
note = _STORE.get(note_id)
|
|
66
|
+
if not note:
|
|
67
|
+
raise HTTPException(
|
|
68
|
+
status_code=status.HTTP_404_NOT_FOUND,
|
|
69
|
+
detail="Note not found",
|
|
70
|
+
)
|
|
71
|
+
return note
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
"""Health endpoints."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
from time import monotonic
|
|
6
|
+
|
|
7
|
+
from fastapi import APIRouter
|
|
8
|
+
|
|
9
|
+
router = APIRouter(tags=["health"])
|
|
10
|
+
|
|
11
|
+
_START_TIME = monotonic()
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
@router.get("/", summary="Health check")
|
|
15
|
+
async def heartbeat() -> dict[str, object]:
|
|
16
|
+
"""Return basic service heartbeat."""
|
|
17
|
+
return {
|
|
18
|
+
"status": "ok",
|
|
19
|
+
"version": "{{ app_version }}",
|
|
20
|
+
"uptime": monotonic() - _START_TIME,
|
|
21
|
+
"module": "app",
|
|
22
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
"""Test package placeholder."""
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
"""Example feature tests exercising the in-memory notes API."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
from fastapi.testclient import TestClient
|
|
6
|
+
|
|
7
|
+
from src.main import app
|
|
8
|
+
|
|
9
|
+
client = TestClient(app)
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
def test_create_and_list_notes() -> None:
|
|
13
|
+
payload = {"title": "First note", "body": "Documented via RapidKit."}
|
|
14
|
+
create_response = client.post("/api/examples/notes", json=payload)
|
|
15
|
+
assert create_response.status_code == 201
|
|
16
|
+
data = create_response.json()
|
|
17
|
+
assert data["title"] == payload["title"]
|
|
18
|
+
assert data["body"] == payload["body"]
|
|
19
|
+
|
|
20
|
+
list_response = client.get("/api/examples/notes")
|
|
21
|
+
assert list_response.status_code == 200
|
|
22
|
+
notes = list_response.json()
|
|
23
|
+
assert any(note["title"] == payload["title"] for note in notes)
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
def test_get_missing_note_returns_404() -> None:
|
|
27
|
+
response = client.get("/api/examples/notes/999")
|
|
28
|
+
assert response.status_code == 404
|
|
29
|
+
assert response.json()["detail"] == "Note not found"
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
"""Health-check tests for generated FastAPI standard projects."""
|
|
2
|
+
|
|
3
|
+
from fastapi.testclient import TestClient
|
|
4
|
+
|
|
5
|
+
from src.main import app
|
|
6
|
+
|
|
7
|
+
client = TestClient(app)
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
def test_health_endpoint() -> None:
|
|
11
|
+
response = client.get("/api/health/")
|
|
12
|
+
assert response.status_code == 200
|
|
13
|
+
payload = response.json()
|
|
14
|
+
assert payload["status"] == "ok"
|
|
15
|
+
assert "version" in payload
|
|
16
|
+
assert "uptime" in payload
|
|
17
|
+
assert "module" in payload
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
# syntax=docker/dockerfile:1.6
|
|
2
|
+
ARG NODE_VERSION=20.19.0-alpine
|
|
3
|
+
FROM node:${NODE_VERSION} as builder
|
|
4
|
+
|
|
5
|
+
WORKDIR /usr/src/app
|
|
6
|
+
|
|
7
|
+
COPY package*.json ./
|
|
8
|
+
COPY . .
|
|
9
|
+
|
|
10
|
+
RUN set -eux; \
|
|
11
|
+
if [ "{{ package_manager }}" = "pnpm" ]; then \
|
|
12
|
+
corepack enable pnpm && pnpm install --frozen-lockfile; \
|
|
13
|
+
pnpm build; \
|
|
14
|
+
elif [ "{{ package_manager }}" = "yarn" ]; then \
|
|
15
|
+
corepack enable yarn && yarn install --frozen-lockfile; \
|
|
16
|
+
yarn build; \
|
|
17
|
+
else \
|
|
18
|
+
if [ -f package-lock.json ]; then npm ci; else npm install; fi; \
|
|
19
|
+
npm run build; \
|
|
20
|
+
fi
|
|
21
|
+
|
|
22
|
+
FROM node:${NODE_VERSION}
|
|
23
|
+
ENV NODE_ENV=production
|
|
24
|
+
WORKDIR /usr/src/app
|
|
25
|
+
|
|
26
|
+
COPY package*.json ./
|
|
27
|
+
|
|
28
|
+
RUN set -eux; \
|
|
29
|
+
if [ "{{ package_manager }}" = "pnpm" ]; then \
|
|
30
|
+
corepack enable pnpm && pnpm install --prod --frozen-lockfile; \
|
|
31
|
+
elif [ "{{ package_manager }}" = "yarn" ]; then \
|
|
32
|
+
corepack enable yarn && yarn install --production --frozen-lockfile; \
|
|
33
|
+
else \
|
|
34
|
+
if [ -f package-lock.json ]; then npm ci --omit=dev; else npm install --omit=dev; fi; \
|
|
35
|
+
fi
|
|
36
|
+
|
|
37
|
+
COPY --from=builder /usr/src/app/dist ./dist
|
|
38
|
+
|
|
39
|
+
|
|
40
|
+
EXPOSE 8000
|
|
41
|
+
CMD ["node", "dist/main"]
|
|
@@ -0,0 +1,139 @@
|
|
|
1
|
+
# {{ project_name | replace('-', ' ') | title }}
|
|
2
|
+
|
|
3
|
+
A production-ready NestJS 11 application generated with RapidKit's **NestJS Standard Kit**.
|
|
4
|
+
|
|
5
|
+
## Getting Started
|
|
6
|
+
> Recommended Node version: `{{ node_version }}` (`.nvmrc` and `.node-version` are included for your toolchain)
|
|
7
|
+
|
|
8
|
+
```bash
|
|
9
|
+
# Load the project-aware RapidKit CLI (adds .rapidkit/rapidkit to PATH)
|
|
10
|
+
source .rapidkit/activate
|
|
11
|
+
|
|
12
|
+
# Bootstrap dependencies using the local CLI
|
|
13
|
+
rapidkit init # use make init if you prefer a Make target
|
|
14
|
+
|
|
15
|
+
# Copy env templates + install hooks/tooling
|
|
16
|
+
./bootstrap.sh
|
|
17
|
+
|
|
18
|
+
# Run the dev server with hot reload
|
|
19
|
+
make dev
|
|
20
|
+
|
|
21
|
+
# Or rely on the project-aware RapidKit CLI helpers:
|
|
22
|
+
rapidkit dev
|
|
23
|
+
|
|
24
|
+
# Run linting, type-checking, tests, and supply-chain audits
|
|
25
|
+
make lint
|
|
26
|
+
make typecheck
|
|
27
|
+
make test
|
|
28
|
+
make audit
|
|
29
|
+
rapidkit lint
|
|
30
|
+
rapidkit test
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
> Open a new shell? Run `source .rapidkit/activate` again so the project-local `rapidkit` launcher stays on your PATH.
|
|
34
|
+
|
|
35
|
+
> Use `rapidkit init` (or `make init`) whenever dependencies change. Pass `SKIP_INIT=1` (for example `SKIP_INIT=1 make install`) if you only need to refresh tooling/hooks.
|
|
36
|
+
|
|
37
|
+
> Lockfiles are generated automatically during scaffolding. Set `RAPIDKIT_SKIP_LOCKS=1` (or `RAPIDKIT_GENERATE_LOCKS=0`) before running `rapidkit create` if you need to skip this step.
|
|
38
|
+
|
|
39
|
+
> Need the entire RapidKit command list? Run `rapidkit --help` or open the CLI reference in the docs for a complete breakdown.
|
|
40
|
+
|
|
41
|
+
---
|
|
42
|
+
|
|
43
|
+
## Quick start (developer)
|
|
44
|
+
|
|
45
|
+
1. `rapidkit init` (after `source .rapidkit/activate`) bootstraps dependencies through the project-local RapidKit CLI and enforces lockfile flags for your chosen package manager.
|
|
46
|
+
2. `make init` remains available as an alias to `rapidkit init` when you prefer Make targets.
|
|
47
|
+
3. `./bootstrap.sh` copies `.env.example` to `.env` (when missing) and runs `SKIP_INIT=1 make install` so git hooks and tooling stay current without reinstalling packages.
|
|
48
|
+
4. `make dev` wraps `{{ package_manager if package_manager != 'pnpm' else 'pnpm' }} run start:dev` and centralizes env loading; use it for day-to-day development.
|
|
49
|
+
5. `make lint`, `make typecheck`, and `make test` proxy to the underlying package scripts or `tsc` so local changes match CI expectations.
|
|
50
|
+
6. `make audit` executes `{{ package_manager }}`'s security audit (falling back to dev dependencies if needed) to surface vulnerable packages early.
|
|
51
|
+
|
|
52
|
+
`make install` is still available; it re-runs `rapidkit init` unless you set `SKIP_INIT=1`, so prefer `SKIP_INIT=1 make install` when you only need to refresh tooling.
|
|
53
|
+
|
|
54
|
+
Prefer `rapidkit dev`, `rapidkit test`, or `rapidkit lint` when you want the RapidKit CLI to auto-detect the right runtime; they call into the same project scripts wrapped by the Make targets.
|
|
55
|
+
|
|
56
|
+
Prefer the Make targets for consistency, but you can always fall back to native commands if needed:
|
|
57
|
+
|
|
58
|
+
```bash
|
|
59
|
+
{{ package_manager if package_manager != 'pnpm' else 'pnpm' }} install
|
|
60
|
+
{{ package_manager if package_manager != 'pnpm' else 'pnpm' }} run start:dev
|
|
61
|
+
{{ package_manager if package_manager != 'pnpm' else 'pnpm' }} test
|
|
62
|
+
{{ package_manager if package_manager != 'pnpm' else 'pnpm' }} run lint
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
If you see engine compatibility errors during `{{ package_manager }} install`, update your Node runtime (nvm/asdf) or use the provided Dockerfile which targets `NODE_VERSION={{ node_version }}`.
|
|
66
|
+
|
|
67
|
+
## Features
|
|
68
|
+
|
|
69
|
+
- Modular architecture with configuration hooks
|
|
70
|
+
- {{ 'JWT/OAuth2 authentication scaffolding' if auth_type != 'none' else 'Authentication ready' }}
|
|
71
|
+
- Optional integrations:
|
|
72
|
+
- Database: {{ database_type | default('postgresql') | upper }}
|
|
73
|
+
- Redis caching
|
|
74
|
+
- Structured logging and telemetry
|
|
75
|
+
- Monitoring endpoints
|
|
76
|
+
|
|
77
|
+
## Project Structure
|
|
78
|
+
|
|
79
|
+
- `src/main.ts` – Bootstraps the NestJS application
|
|
80
|
+
- `src/app.module.ts` – Core application module with injection anchors
|
|
81
|
+
- `src/modules/` – Container for RapidKit modules (`// <<<inject:module-init>>>`)
|
|
82
|
+
- `src/config/` – Centralized configuration module and validation
|
|
83
|
+
- `test/` – Unit and e2e testing with Jest
|
|
84
|
+
|
|
85
|
+
## RapidKit Modules
|
|
86
|
+
|
|
87
|
+
Install additional modules as needed:
|
|
88
|
+
|
|
89
|
+
```bash
|
|
90
|
+
rapidkit add module settings
|
|
91
|
+
rapidkit add module logging
|
|
92
|
+
rapidkit add module auth
|
|
93
|
+
```
|
|
94
|
+
|
|
95
|
+
<!-- <<<inject:module-snippet>>> -->
|
|
96
|
+
|
|
97
|
+
## Example feature
|
|
98
|
+
|
|
99
|
+
The scaffold ships with an `ExamplesModule` exposing a tiny in-memory notes API under `/examples/notes`. Use it to validate request/response flows or to demo module structure before wiring real adapters:
|
|
100
|
+
|
|
101
|
+
```bash
|
|
102
|
+
# Create a note
|
|
103
|
+
curl -s -X POST http://localhost:3000/examples/notes \
|
|
104
|
+
-H "Content-Type: application/json" \
|
|
105
|
+
-d '{"title":"hello","body":"documented via RapidKit"}'
|
|
106
|
+
|
|
107
|
+
# List all notes
|
|
108
|
+
curl -s http://localhost:3000/examples/notes | jq
|
|
109
|
+
```
|
|
110
|
+
|
|
111
|
+
Replace the in-memory service with a proper repository once you add RapidKit database modules.
|
|
112
|
+
|
|
113
|
+
## Docker
|
|
114
|
+
|
|
115
|
+
```bash
|
|
116
|
+
docker-compose up -d
|
|
117
|
+
docker-compose down
|
|
118
|
+
```
|
|
119
|
+
|
|
120
|
+
## Scripts
|
|
121
|
+
|
|
122
|
+
| Command | Description |
|
|
123
|
+
| --- | --- |
|
|
124
|
+
| `{{ package_manager if package_manager != 'pnpm' else 'pnpm' }} start:dev` | Start development server |
|
|
125
|
+
| `{{ package_manager if package_manager != 'pnpm' else 'pnpm' }} build` | Build production artifacts |
|
|
126
|
+
| `{{ package_manager if package_manager != 'pnpm' else 'pnpm' }} test` | Run tests |
|
|
127
|
+
|
|
128
|
+
---
|
|
129
|
+
Generated with ❤️ by RapidKit.
|
|
130
|
+
|
|
131
|
+
## 📄 License
|
|
132
|
+
|
|
133
|
+
This project is licensed under the **{{ license }}** License - see the `LICENSE` file included at the project root for details.
|
|
134
|
+
|
|
135
|
+
## 🔒 Security & secrets
|
|
136
|
+
|
|
137
|
+
- Copy `.env.example` to `.env` and populate secrets (`SECRET_KEY`, DB credentials, etc.) before deploying.
|
|
138
|
+
- **Do not** commit real secrets or `.env` to git; `.gitignore` already contains `.env` to protect accidental commits.
|
|
139
|
+
- For production, tighten CORS and allowed hosts rather than using wildcard settings provided for convenience in dev.
|
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
version: '3.8'
|
|
2
|
+
services:
|
|
3
|
+
app:
|
|
4
|
+
build: .
|
|
5
|
+
container_name: {{ project_name | replace('_', '-') }}
|
|
6
|
+
ports:
|
|
7
|
+
- "8000:8000"
|
|
8
|
+
env_file:
|
|
9
|
+
- .env
|
|
10
|
+
environment:
|
|
11
|
+
NODE_ENV: development
|
|
12
|
+
command: {{ ('pnpm' if package_manager == 'pnpm' else (package_manager if package_manager in ['npm', 'yarn'] else 'npm')) }} run start:dev
|
|
13
|
+
volumes:
|
|
14
|
+
- .:/usr/src/app
|
|
15
|
+
- /usr/src/app/node_modules
|
|
16
|
+
{% if database_type in ['postgresql', 'mysql', 'mongodb'] or include_caching %}
|
|
17
|
+
depends_on:
|
|
18
|
+
{% if database_type == 'postgresql' %}
|
|
19
|
+
postgres:
|
|
20
|
+
condition: service_healthy
|
|
21
|
+
{% elif database_type == 'mysql' %}
|
|
22
|
+
mysql:
|
|
23
|
+
condition: service_healthy
|
|
24
|
+
{% elif database_type == 'mongodb' %}
|
|
25
|
+
mongodb:
|
|
26
|
+
condition: service_started
|
|
27
|
+
{% endif %}
|
|
28
|
+
{% if include_caching %}
|
|
29
|
+
redis:
|
|
30
|
+
condition: service_started
|
|
31
|
+
{% endif %}
|
|
32
|
+
{% endif %}
|
|
33
|
+
healthcheck:
|
|
34
|
+
test: ["CMD", "curl", "-f", "http://localhost:8000/health"]
|
|
35
|
+
interval: 10s
|
|
36
|
+
timeout: 3s
|
|
37
|
+
retries: 5
|
|
38
|
+
|
|
39
|
+
{% if database_type == 'postgresql' %}
|
|
40
|
+
postgres:
|
|
41
|
+
image: postgres:15-alpine
|
|
42
|
+
environment:
|
|
43
|
+
POSTGRES_USER: user
|
|
44
|
+
POSTGRES_PASSWORD: password
|
|
45
|
+
POSTGRES_DB: {{ project_name | replace('-', '_') }}
|
|
46
|
+
ports:
|
|
47
|
+
- "5432:5432"
|
|
48
|
+
healthcheck:
|
|
49
|
+
test: ["CMD-SHELL", "pg_isready -U user"]
|
|
50
|
+
interval: 10s
|
|
51
|
+
timeout: 3s
|
|
52
|
+
retries: 5
|
|
53
|
+
|
|
54
|
+
{% elif database_type == 'mysql' %}
|
|
55
|
+
mysql:
|
|
56
|
+
image: mysql:8.1
|
|
57
|
+
environment:
|
|
58
|
+
MYSQL_ROOT_PASSWORD: password
|
|
59
|
+
MYSQL_DATABASE: {{ project_name | replace('-', '_') }}
|
|
60
|
+
MYSQL_USER: user
|
|
61
|
+
MYSQL_PASSWORD: password
|
|
62
|
+
ports:
|
|
63
|
+
- "3306:3306"
|
|
64
|
+
healthcheck:
|
|
65
|
+
test: ["CMD", "mysqladmin", "ping", "-h", "localhost"]
|
|
66
|
+
interval: 10s
|
|
67
|
+
timeout: 5s
|
|
68
|
+
retries: 5
|
|
69
|
+
|
|
70
|
+
{% elif database_type == 'mongodb' %}
|
|
71
|
+
mongodb:
|
|
72
|
+
image: mongo:7
|
|
73
|
+
ports:
|
|
74
|
+
- "27017:27017"
|
|
75
|
+
volumes:
|
|
76
|
+
- mongodb_data:/data/db
|
|
77
|
+
|
|
78
|
+
{% endif %}
|
|
79
|
+
{% if include_caching %}
|
|
80
|
+
redis:
|
|
81
|
+
image: redis:7-alpine
|
|
82
|
+
ports:
|
|
83
|
+
- "6379:6379"
|
|
84
|
+
command: ["redis-server", "--appendonly", "yes"]
|
|
85
|
+
healthcheck:
|
|
86
|
+
test: ["CMD", "redis-cli", "ping"]
|
|
87
|
+
interval: 10s
|
|
88
|
+
timeout: 3s
|
|
89
|
+
retries: 5
|
|
90
|
+
{% endif %}
|
|
91
|
+
|
|
92
|
+
volumes:
|
|
93
|
+
mongodb_data:
|
|
94
|
+
driver: local
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
# Documentation
|
|
2
|
+
|
|
3
|
+
Welcome to the documentation portal for **{{ project_name | replace('-', ' ') | title }}**.
|
|
4
|
+
|
|
5
|
+
## Contents
|
|
6
|
+
|
|
7
|
+
- `architecture/` – System design documents and decisions
|
|
8
|
+
- `operations/` – Runbooks and operational procedures
|
|
9
|
+
- `modules/` – Documentation for installed RapidKit modules
|
|
10
|
+
|
|
11
|
+
## Getting Started
|
|
12
|
+
|
|
13
|
+
1. Update this documentation with project-specific details.
|
|
14
|
+
2. Document any architectural decisions in `architecture/adr-000-template.md`.
|
|
15
|
+
3. Keep module docs in sync with installed RapidKit modules.
|