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.
Files changed (199) hide show
  1. package/README.md +48 -7
  2. package/contracts/agent-customization-pack.v1.json +52 -2
  3. package/contracts/extension-cli-compatibility.v1.json +14 -2
  4. package/contracts/runtime-command-surface.v1.json +7 -1
  5. package/contracts/workspace-intelligence/agent-action-outcome.v1.json +38 -0
  6. package/contracts/workspace-intelligence/blocker-resolution.v1.json +65 -0
  7. package/contracts/workspace-intelligence/doctor-fix-result.v1.json +34 -0
  8. package/contracts/workspace-intelligence/studio-blocker-handoff.v1.json +91 -0
  9. package/contracts/workspace-intelligence/workspace-contract-verify.v1.json +51 -0
  10. package/contracts/workspace-intelligence/workspace-dependency-graph.v1.json +61 -1
  11. package/contracts/workspace-intelligence/workspace-explain.v1.json +31 -0
  12. package/contracts/workspace-intelligence/workspace-intelligence-history.v1.json +36 -0
  13. package/contracts/workspace-intelligence/workspace-operational-skill.v1.json +37 -0
  14. package/contracts/workspace-intelligence/workspace-skills-index.v1.json +27 -0
  15. package/dist/analyze-QYHMGLSG.js +1 -0
  16. package/dist/autopilot-release-AHMQEUFH.js +1 -0
  17. package/dist/chunk-33LR2QEM.js +2 -0
  18. package/dist/chunk-3PTJID76.js +2 -0
  19. package/dist/chunk-46AGNYI7.js +50 -0
  20. package/dist/chunk-64RTZBHU.js +2 -0
  21. package/dist/chunk-AQ4XZZC6.js +1 -0
  22. package/dist/{chunk-RXWM5DSC.js → chunk-BFEBZABL.js} +3 -3
  23. package/dist/{chunk-3YLMCP3V.js → chunk-CDCYRBAY.js} +1 -1
  24. package/dist/chunk-CDPR2YKL.js +13 -0
  25. package/dist/chunk-CKXJR3YT.js +7 -0
  26. package/dist/chunk-E5ZVQL3C.js +13 -0
  27. package/dist/chunk-ELU3G6DQ.js +9 -0
  28. package/dist/chunk-EN6YCX36.js +1 -0
  29. package/dist/chunk-FMBSON6H.js +33 -0
  30. package/dist/chunk-GBJBQ43T.js +1 -0
  31. package/dist/chunk-ICGWHIMK.js +1 -0
  32. package/dist/{chunk-4FJQWL7P.js → chunk-ITJ6RKUW.js} +3 -3
  33. package/dist/{workspace-graph-ICB7OVAZ.js → chunk-JEI6BTZI.js} +1 -1
  34. package/dist/{chunk-G76C74EV.js → chunk-JU3VNLTY.js} +1 -1
  35. package/dist/chunk-JW2FSKT3.js +2 -0
  36. package/dist/chunk-KIUSCFHF.js +1 -0
  37. package/dist/chunk-LKX3L7TE.js +2 -0
  38. package/dist/chunk-MIWDCR6I.js +2 -0
  39. package/dist/{chunk-6G2KSHP6.js → chunk-OLDPVVSV.js} +1 -1
  40. package/dist/{chunk-4Q2ZZKGB.js → chunk-PCXSTKZ5.js} +1 -1
  41. package/dist/{chunk-6KD5F6LX.js → chunk-Q2KZIBV4.js} +1 -1
  42. package/dist/{chunk-ERCD6NFF.js → chunk-RSYUNEH7.js} +13 -13
  43. package/dist/chunk-TJN7G2MA.js +1 -0
  44. package/dist/chunk-UQR6G7KH.js +32 -0
  45. package/dist/chunk-VMJA36WD.js +1 -0
  46. package/dist/chunk-WRMCPKGA.js +1 -0
  47. package/dist/{create-XVDDQA42.js → create-RNP5ACQL.js} +1 -1
  48. package/dist/demo-kit-N5U3NGAE.js +149 -0
  49. package/dist/{doctor-UOLOGJ2Z.js → doctor-XM6QDTDC.js} +1 -1
  50. package/dist/{dotnet-webapi-clean-RTBRPDPL.js → dotnet-webapi-clean-K33C77EI.js} +1 -1
  51. package/dist/{gofiber-standard-UGIRKPKL.js → gofiber-standard-BQ4HCXL2.js} +1 -1
  52. package/dist/{gogin-standard-HJ7SPFNT.js → gogin-standard-PUBCYW3A.js} +1 -1
  53. package/dist/index.d.ts +45 -7
  54. package/dist/index.js +145 -127
  55. package/dist/{pipeline-XK62WL4D.js → pipeline-DH6Z47O4.js} +1 -1
  56. package/dist/platform-capabilities-TSLK667K.js +1 -0
  57. package/dist/{pythonRapidkitExec-MNWRC4F2.js → pythonRapidkitExec-SGKW76XM.js} +1 -1
  58. package/dist/{springboot-standard-IWJSVDLZ.js → springboot-standard-XFVQI37R.js} +1 -1
  59. package/dist/{workspace-L4ITCKMM.js → workspace-E554C5SM.js} +1 -1
  60. package/dist/workspace-agent-sync-2HRPM5ZD.js +1 -0
  61. package/dist/{workspace-context-NMMQMHNU.js → workspace-context-VJTXW3K4.js} +1 -1
  62. package/dist/workspace-contract-OO4GMENV.js +1 -0
  63. package/dist/workspace-explain-3WSJLIJ6.js +1 -0
  64. package/dist/workspace-explain-contract-24RQ7KIW.js +1 -0
  65. package/dist/workspace-feedback-65NR3EZH.js +1 -0
  66. package/dist/{workspace-foundation-HNIRAIBF.js → workspace-foundation-LISDH53T.js} +1 -1
  67. package/dist/workspace-graph-2A5THUCI.js +1 -0
  68. package/dist/workspace-history-VPDADQKG.js +1 -0
  69. package/dist/{workspace-intelligence-64IWAYHS.js → workspace-intelligence-E3KXEZCM.js} +1 -1
  70. package/dist/workspace-mcp-serve-RFYDCA2L.js +3 -0
  71. package/dist/workspace-model-YL7W3573.js +1 -0
  72. package/dist/workspace-registry-summary-X5WRUU3T.js +1 -0
  73. package/dist/workspace-run-GCIQD73R.js +1 -0
  74. package/dist/workspace-verify-NRYH7RNB.js +1 -0
  75. package/dist/workspace-watch-H2AETGFI.js +1 -0
  76. package/docs/DEVELOPMENT.md +1 -1
  77. package/docs/OPEN_SOURCE_USER_SCENARIOS.md +1 -1
  78. package/docs/README.md +1 -1
  79. package/docs/commands-reference.md +10 -2
  80. package/docs/contracts/ARTIFACT_CATALOG.md +3 -1
  81. package/docs/contracts/NAMING_AND_COEXISTENCE.md +58 -0
  82. package/docs/workspace-run.md +25 -1
  83. package/package.json +7 -3
  84. package/scripts/enterprise-package-smoke.mjs +427 -0
  85. package/scripts/prepack-enterprise.mjs +40 -0
  86. package/templates/generator.js +175 -0
  87. package/templates/kits/fastapi-ddd/README.md.j2 +122 -0
  88. package/templates/kits/fastapi-ddd/common/env.example.j2 +10 -0
  89. package/templates/kits/fastapi-ddd/env.example.j2 +1 -0
  90. package/templates/kits/fastapi-ddd/pyproject.toml.j2 +64 -0
  91. package/templates/kits/fastapi-ddd/src/__init__.py.j2 +3 -0
  92. package/templates/kits/fastapi-ddd/src/app/__init__.py.j2 +11 -0
  93. package/templates/kits/fastapi-ddd/src/app/application/__init__.py.j2 +5 -0
  94. package/templates/kits/fastapi-ddd/src/app/application/interfaces.py.j2 +43 -0
  95. package/templates/kits/fastapi-ddd/src/app/application/use_cases/__init__.py.j2 +6 -0
  96. package/templates/kits/fastapi-ddd/src/app/application/use_cases/health.py.j2 +14 -0
  97. package/templates/kits/fastapi-ddd/src/app/application/use_cases/notes.py.j2 +24 -0
  98. package/templates/kits/fastapi-ddd/src/app/config/__init__.py.j2 +16 -0
  99. package/templates/kits/fastapi-ddd/src/app/domain/__init__.py.j2 +3 -0
  100. package/templates/kits/fastapi-ddd/src/app/domain/models/__init__.py.j2 +6 -0
  101. package/templates/kits/fastapi-ddd/src/app/domain/models/health.py.j2 +16 -0
  102. package/templates/kits/fastapi-ddd/src/app/domain/models/note.py.j2 +27 -0
  103. package/templates/kits/fastapi-ddd/src/app/infrastructure/__init__.py.j2 +5 -0
  104. package/templates/kits/fastapi-ddd/src/app/infrastructure/repositories/__init__.py.j2 +6 -0
  105. package/templates/kits/fastapi-ddd/src/app/infrastructure/repositories/health.py.j2 +17 -0
  106. package/templates/kits/fastapi-ddd/src/app/infrastructure/repositories/notes.py.j2 +28 -0
  107. package/templates/kits/fastapi-ddd/src/app/main.py.j2 +61 -0
  108. package/templates/kits/fastapi-ddd/src/app/presentation/__init__.py.j2 +3 -0
  109. package/templates/kits/fastapi-ddd/src/app/presentation/api/__init__.py.j2 +5 -0
  110. package/templates/kits/fastapi-ddd/src/app/presentation/api/dependencies/__init__.py.j2 +19 -0
  111. package/templates/kits/fastapi-ddd/src/app/presentation/api/router.py.j2 +10 -0
  112. package/templates/kits/fastapi-ddd/src/app/presentation/api/routes/__init__.py.j2 +5 -0
  113. package/templates/kits/fastapi-ddd/src/app/presentation/api/routes/health.py.j2 +27 -0
  114. package/templates/kits/fastapi-ddd/src/app/presentation/api/routes/notes.py.j2 +50 -0
  115. package/templates/kits/fastapi-ddd/src/app/shared/__init__.py.j2 +5 -0
  116. package/templates/kits/fastapi-ddd/src/app/shared/result.py.j2 +28 -0
  117. package/templates/kits/fastapi-ddd/src/cli.py.j2 +167 -0
  118. package/templates/kits/fastapi-ddd/src/main.py.j2 +35 -0
  119. package/templates/kits/fastapi-ddd/src/modules/__init__.py.j2 +3 -0
  120. package/templates/kits/fastapi-ddd/src/routing/__init__.py.j2 +13 -0
  121. package/templates/kits/fastapi-ddd/src/routing/health.py.j2 +7 -0
  122. package/templates/kits/fastapi-ddd/src/routing/notes.py.j2 +7 -0
  123. package/templates/kits/fastapi-ddd/tests/__init__.py.j2 +1 -0
  124. package/templates/kits/fastapi-ddd/tests/test_app_factory.py.j2 +22 -0
  125. package/templates/kits/fastapi-ddd/tests/test_health.py.j2 +17 -0
  126. package/templates/kits/fastapi-ddd/tests/test_notes.py.j2 +27 -0
  127. package/templates/kits/fastapi-standard/README.md.j2 +145 -0
  128. package/templates/kits/fastapi-standard/common/env.example.j2 +10 -0
  129. package/templates/kits/fastapi-standard/env.example.j2 +1 -0
  130. package/templates/kits/fastapi-standard/pyproject.toml.j2 +64 -0
  131. package/templates/kits/fastapi-standard/src/__init__.py.j2 +3 -0
  132. package/templates/kits/fastapi-standard/src/cli.py.j2 +168 -0
  133. package/templates/kits/fastapi-standard/src/main.py.j2 +66 -0
  134. package/templates/kits/fastapi-standard/src/modules/__init__.py.j2 +3 -0
  135. package/templates/kits/fastapi-standard/src/routing/__init__.py.j2 +16 -0
  136. package/templates/kits/fastapi-standard/src/routing/examples.py.j2 +71 -0
  137. package/templates/kits/fastapi-standard/src/routing/health.py.j2 +22 -0
  138. package/templates/kits/fastapi-standard/tests/__init__.py.j2 +1 -0
  139. package/templates/kits/fastapi-standard/tests/test_examples.py.j2 +29 -0
  140. package/templates/kits/fastapi-standard/tests/test_health.py.j2 +17 -0
  141. package/templates/kits/nestjs-standard/Dockerfile.j2 +41 -0
  142. package/templates/kits/nestjs-standard/README.md.j2 +139 -0
  143. package/templates/kits/nestjs-standard/docker-compose.yml.j2 +94 -0
  144. package/templates/kits/nestjs-standard/docs/README.md.j2 +15 -0
  145. package/templates/kits/nestjs-standard/env.example.j2 +18 -0
  146. package/templates/kits/nestjs-standard/eslint.config.cjs.j2 +9 -0
  147. package/templates/kits/nestjs-standard/jest.config.ts.j2 +22 -0
  148. package/templates/kits/nestjs-standard/nest-cli.json.j2 +10 -0
  149. package/templates/kits/nestjs-standard/package.json.j2 +101 -0
  150. package/templates/kits/nestjs-standard/src/app.controller.ts.j2 +14 -0
  151. package/templates/kits/nestjs-standard/src/app.module.ts.j2 +26 -0
  152. package/templates/kits/nestjs-standard/src/app.service.ts.j2 +16 -0
  153. package/templates/kits/nestjs-standard/src/auth/auth.controller.ts.j2 +20 -0
  154. package/templates/kits/nestjs-standard/src/auth/auth.module.ts.j2 +13 -0
  155. package/templates/kits/nestjs-standard/src/auth/auth.service.ts.j2 +6 -0
  156. package/templates/kits/nestjs-standard/src/auth/entities/token.entity.ts.j2 +3 -0
  157. package/templates/kits/nestjs-standard/src/auth/entities/user.entity.ts.j2 +3 -0
  158. package/templates/kits/nestjs-standard/src/auth/entities/webauthn.entity.ts.j2 +3 -0
  159. package/templates/kits/nestjs-standard/src/config/configuration.ts.j2 +85 -0
  160. package/templates/kits/nestjs-standard/src/config/index.ts.j2 +2 -0
  161. package/templates/kits/nestjs-standard/src/config/validation.ts.j2 +21 -0
  162. package/templates/kits/nestjs-standard/src/examples/dto/create-note.dto.ts.j2 +11 -0
  163. package/templates/kits/nestjs-standard/src/examples/examples.controller.ts.j2 +24 -0
  164. package/templates/kits/nestjs-standard/src/examples/examples.module.ts.j2 +10 -0
  165. package/templates/kits/nestjs-standard/src/examples/examples.service.ts.j2 +33 -0
  166. package/templates/kits/nestjs-standard/src/main.ts.j2 +53 -0
  167. package/templates/kits/nestjs-standard/src/modules/index.ts.j2 +25 -0
  168. package/templates/kits/nestjs-standard/test/app.controller.spec.ts.j2 +24 -0
  169. package/templates/kits/nestjs-standard/test/app.e2e-spec.ts.j2 +60 -0
  170. package/templates/kits/nestjs-standard/test/examples.controller.spec.ts.j2 +28 -0
  171. package/templates/kits/nestjs-standard/test/jest-e2e.json.j2 +15 -0
  172. package/templates/kits/nestjs-standard/tsconfig.build.json.j2 +12 -0
  173. package/templates/kits/nestjs-standard/tsconfig.json.j2 +26 -0
  174. package/dist/analyze-RHQM4AB2.js +0 -1
  175. package/dist/autopilot-release-OJTLXPMX.js +0 -1
  176. package/dist/chunk-5VBRMLRU.js +0 -7
  177. package/dist/chunk-7VI4U7Q5.js +0 -2
  178. package/dist/chunk-FV5A3N3I.js +0 -2
  179. package/dist/chunk-GDGATWR5.js +0 -2
  180. package/dist/chunk-GOM3RFB3.js +0 -2
  181. package/dist/chunk-GX7UU7LL.js +0 -33
  182. package/dist/chunk-KYH364KQ.js +0 -1
  183. package/dist/chunk-OWNGSAO3.js +0 -2
  184. package/dist/chunk-QPEBI6AB.js +0 -2
  185. package/dist/chunk-TYZPPUBH.js +0 -1
  186. package/dist/chunk-VQMZC5TC.js +0 -9
  187. package/dist/chunk-WHCON2VN.js +0 -50
  188. package/dist/chunk-X7PWDIQW.js +0 -1
  189. package/dist/chunk-Z5LKRG57.js +0 -1
  190. package/dist/chunk-ZWKLRZE5.js +0 -13
  191. package/dist/demo-kit-RWGOEDW4.js +0 -141
  192. package/dist/workspace-agent-sync-G7JU77IK.js +0 -25
  193. package/dist/workspace-contract-D5O4OZD5.js +0 -1
  194. package/dist/workspace-history-LHUTLE3S.js +0 -1
  195. package/dist/workspace-model-SDHH5RBC.js +0 -1
  196. package/dist/workspace-registry-summary-MIPHVB56.js +0 -1
  197. package/dist/workspace-run-SPP32MPV.js +0 -1
  198. package/dist/workspace-verify-6Q6MGRG6.js +0 -1
  199. 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,3 @@
1
+ """Module bootstrap namespace."""
2
+
3
+ # <<<inject:module-init>>>
@@ -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.