zudojs-cli 2.0.1 → 2.1.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 (248) hide show
  1. package/README.md +59 -7
  2. package/dist/src/adapters/frontend/angular.adapter.d.ts +0 -1
  3. package/dist/src/adapters/frontend/angular.adapter.js +14 -97
  4. package/dist/src/adapters/frontend/astro.adapter.d.ts +0 -1
  5. package/dist/src/adapters/frontend/astro.adapter.js +4 -64
  6. package/dist/src/adapters/frontend/fallback/fallback.helper.d.ts +41 -0
  7. package/dist/src/adapters/frontend/fallback/fallback.helper.js +57 -0
  8. package/dist/src/adapters/frontend/fallback/framework/angular/angular.fallback.d.ts +18 -0
  9. package/dist/src/adapters/frontend/fallback/framework/angular/angular.fallback.js +107 -0
  10. package/dist/src/adapters/frontend/fallback/framework/angular/angularWorkspace.fallback.d.ts +23 -0
  11. package/dist/src/adapters/frontend/fallback/framework/angular/angularWorkspace.fallback.js +125 -0
  12. package/dist/src/adapters/frontend/fallback/framework/angular/index.d.ts +8 -0
  13. package/dist/src/adapters/frontend/fallback/framework/angular/index.js +8 -0
  14. package/dist/src/adapters/frontend/fallback/framework/astro.fallback.d.ts +14 -0
  15. package/dist/src/adapters/frontend/fallback/framework/astro.fallback.js +76 -0
  16. package/dist/src/adapters/frontend/fallback/framework/index.d.ts +13 -0
  17. package/dist/src/adapters/frontend/fallback/framework/index.js +13 -0
  18. package/dist/src/adapters/frontend/fallback/framework/next.fallback.d.ts +13 -0
  19. package/dist/src/adapters/frontend/fallback/framework/next.fallback.js +105 -0
  20. package/dist/src/adapters/frontend/fallback/framework/nuxt.fallback.d.ts +14 -0
  21. package/dist/src/adapters/frontend/fallback/framework/nuxt.fallback.js +56 -0
  22. package/dist/src/adapters/frontend/fallback/framework/sveltekit.fallback.d.ts +15 -0
  23. package/dist/src/adapters/frontend/fallback/framework/sveltekit.fallback.js +94 -0
  24. package/dist/src/adapters/frontend/fallback/index.d.ts +12 -0
  25. package/dist/src/adapters/frontend/fallback/index.js +12 -0
  26. package/dist/src/adapters/frontend/fallback/vite/index.d.ts +11 -0
  27. package/dist/src/adapters/frontend/fallback/vite/index.js +11 -0
  28. package/dist/src/adapters/frontend/fallback/vite/react.fallback.d.ts +13 -0
  29. package/dist/src/adapters/frontend/fallback/vite/react.fallback.js +77 -0
  30. package/dist/src/adapters/frontend/fallback/vite/svelte.fallback.d.ts +14 -0
  31. package/dist/src/adapters/frontend/fallback/vite/svelte.fallback.js +95 -0
  32. package/dist/src/adapters/frontend/fallback/vite/vanilla.fallback.d.ts +13 -0
  33. package/dist/src/adapters/frontend/fallback/vite/vanilla.fallback.js +71 -0
  34. package/dist/src/adapters/frontend/fallback/vite/vue.fallback.d.ts +14 -0
  35. package/dist/src/adapters/frontend/fallback/vite/vue.fallback.js +78 -0
  36. package/dist/src/adapters/frontend/next.adapter.d.ts +0 -1
  37. package/dist/src/adapters/frontend/next.adapter.js +16 -95
  38. package/dist/src/adapters/frontend/nuxt.adapter.d.ts +1 -2
  39. package/dist/src/adapters/frontend/nuxt.adapter.js +32 -43
  40. package/dist/src/adapters/frontend/react-native.adapter.js +1 -1
  41. package/dist/src/adapters/frontend/react.adapter.d.ts +0 -1
  42. package/dist/src/adapters/frontend/react.adapter.js +7 -89
  43. package/dist/src/adapters/frontend/svelte.adapter.d.ts +0 -1
  44. package/dist/src/adapters/frontend/svelte.adapter.js +4 -86
  45. package/dist/src/adapters/frontend/sveltekit.adapter.d.ts +0 -1
  46. package/dist/src/adapters/frontend/sveltekit.adapter.js +4 -57
  47. package/dist/src/adapters/frontend/vanilla.adapter.d.ts +0 -1
  48. package/dist/src/adapters/frontend/vanilla.adapter.js +4 -47
  49. package/dist/src/adapters/frontend/vue.adapter.d.ts +0 -1
  50. package/dist/src/adapters/frontend/vue.adapter.js +4 -76
  51. package/dist/src/bin/bin.menu.d.ts +22 -0
  52. package/dist/src/bin/bin.menu.js +40 -0
  53. package/dist/src/bin/bin.runner.d.ts +38 -0
  54. package/dist/src/bin/bin.runner.js +51 -0
  55. package/dist/src/bin/index.d.ts +9 -0
  56. package/dist/src/bin/index.js +9 -0
  57. package/dist/src/bin/zudojs.js +15 -4
  58. package/dist/src/cliApplication/cliApplication.core.d.ts +4 -2
  59. package/dist/src/cliApplication/cliApplication.core.js +48 -36
  60. package/dist/src/cliApplication/cliApplication.logger.d.ts +5 -0
  61. package/dist/src/cliApplication/cliApplication.logger.js +5 -3
  62. package/dist/src/cliApplication/invocation/index.d.ts +12 -0
  63. package/dist/src/cliApplication/invocation/index.js +12 -0
  64. package/dist/src/cliApplication/invocation/invocation.hint.d.ts +30 -0
  65. package/dist/src/cliApplication/invocation/invocation.hint.js +74 -0
  66. package/dist/src/cliApplication/invocation/invocation.locate.d.ts +34 -0
  67. package/dist/src/cliApplication/invocation/invocation.locate.js +53 -0
  68. package/dist/src/cliApplication/invocation/invocation.name.d.ts +37 -0
  69. package/dist/src/cliApplication/invocation/invocation.name.js +69 -0
  70. package/dist/src/cliApplication/invocation/invocation.sanitize.d.ts +19 -0
  71. package/dist/src/cliApplication/invocation/invocation.sanitize.js +32 -0
  72. package/dist/src/cliParser/cliParser.core.js +3 -1
  73. package/dist/src/cliParser/cliParser.helper.d.ts +7 -0
  74. package/dist/src/cliParser/cliParser.helper.js +19 -2
  75. package/dist/src/cliParser/cliParser.longOption.js +2 -2
  76. package/dist/src/commands/add.command.d.ts +7 -3
  77. package/dist/src/commands/add.command.js +96 -57
  78. package/dist/src/commands/create.command.js +29 -42
  79. package/dist/src/commands/doctor.command.d.ts +2 -1
  80. package/dist/src/commands/doctor.command.js +52 -4
  81. package/dist/src/commands/generate.command.js +31 -16
  82. package/dist/src/commands/info.command.js +11 -1
  83. package/dist/src/constants/index.d.ts +21 -3
  84. package/dist/src/constants/index.js +40 -5
  85. package/dist/src/constants/zudojsVersions.generated.d.ts +9 -0
  86. package/dist/src/constants/zudojsVersions.generated.js +48 -0
  87. package/dist/src/constants/zudojsVersions.helper.d.ts +21 -0
  88. package/dist/src/constants/zudojsVersions.helper.js +29 -0
  89. package/dist/src/generators/frontend/frontendGenerator.core.js +9 -10
  90. package/dist/src/generators/frontend/frontendPipeline.d.ts +6 -1
  91. package/dist/src/generators/frontend/frontendPipeline.js +9 -1
  92. package/dist/src/generators/fullstack/fullstackComposer.core.js +7 -1
  93. package/dist/src/generators/index.d.ts +1 -2
  94. package/dist/src/generators/index.js +1 -2
  95. package/dist/src/generators/infrastructure/infrastructure.generator.js +13 -5
  96. package/dist/src/generators/integration/integrationGenerator.core.d.ts +2 -0
  97. package/dist/src/generators/integration/integrationGenerator.core.js +31 -2
  98. package/dist/src/generators/module/module.generator.js +36 -4
  99. package/dist/src/generators/resource/index.d.ts +8 -0
  100. package/dist/src/generators/resource/index.js +8 -0
  101. package/dist/src/generators/resource/resource.generator.d.ts +27 -0
  102. package/dist/src/generators/resource/resource.generator.js +87 -0
  103. package/dist/src/generators/resource/resource.layout.d.ts +26 -0
  104. package/dist/src/generators/resource/resource.layout.js +46 -0
  105. package/dist/src/generators/resource/resource.plan.d.ts +27 -0
  106. package/dist/src/generators/resource/resource.plan.js +46 -0
  107. package/dist/src/generators/resource/resource.run.d.ts +25 -0
  108. package/dist/src/generators/resource/resource.run.js +52 -0
  109. package/dist/src/prompts/cancel.prompt.d.ts +5 -1
  110. package/dist/src/prompts/cancel.prompt.js +4 -0
  111. package/dist/src/prompts/menu/index.d.ts +13 -0
  112. package/dist/src/prompts/menu/index.js +13 -0
  113. package/dist/src/prompts/menu/menu.adapter.d.ts +16 -0
  114. package/dist/src/prompts/menu/menu.adapter.js +56 -0
  115. package/dist/src/prompts/menu/menu.constant.d.ts +20 -0
  116. package/dist/src/prompts/menu/menu.constant.js +29 -0
  117. package/dist/src/prompts/menu/menu.flow.d.ts +18 -0
  118. package/dist/src/prompts/menu/menu.flow.js +82 -0
  119. package/dist/src/prompts/menu/menu.select.d.ts +26 -0
  120. package/dist/src/prompts/menu/menu.select.js +118 -0
  121. package/dist/src/prompts/menu/menu.type.d.ts +66 -0
  122. package/dist/src/prompts/menu/menu.type.js +8 -0
  123. package/dist/src/recipes/apply/index.d.ts +9 -0
  124. package/dist/src/recipes/apply/index.js +9 -0
  125. package/dist/src/recipes/apply/recipeApply.app.d.ts +20 -0
  126. package/dist/src/recipes/apply/recipeApply.app.js +79 -0
  127. package/dist/src/recipes/apply/recipeApply.context.d.ts +14 -0
  128. package/dist/src/recipes/apply/recipeApply.context.js +76 -0
  129. package/dist/src/recipes/apply/recipeApply.files.d.ts +39 -0
  130. package/dist/src/recipes/apply/recipeApply.files.js +84 -0
  131. package/dist/src/recipes/apply/recipeApply.project.d.ts +11 -0
  132. package/dist/src/recipes/apply/recipeApply.project.js +50 -0
  133. package/dist/src/recipes/apply/recipeApply.report.d.ts +20 -0
  134. package/dist/src/recipes/apply/recipeApply.report.js +51 -0
  135. package/dist/src/recipes/catalog/database/database.files.d.ts +15 -0
  136. package/dist/src/recipes/catalog/database/database.files.js +98 -0
  137. package/dist/src/recipes/catalog/database/database.recipe.d.ts +9 -0
  138. package/dist/src/recipes/catalog/database/database.recipe.js +50 -0
  139. package/dist/src/recipes/catalog/database/index.d.ts +6 -0
  140. package/dist/src/recipes/catalog/database/index.js +6 -0
  141. package/dist/src/recipes/catalog/email.recipe.d.ts +9 -0
  142. package/dist/src/recipes/catalog/email.recipe.js +122 -0
  143. package/dist/src/recipes/catalog/index.d.ts +11 -0
  144. package/dist/src/recipes/catalog/index.js +11 -0
  145. package/dist/src/recipes/catalog/openapi.recipe.d.ts +8 -0
  146. package/dist/src/recipes/catalog/openapi.recipe.js +25 -0
  147. package/dist/src/recipes/catalog/platform/cache.recipe.d.ts +7 -0
  148. package/dist/src/recipes/catalog/platform/cache.recipe.js +55 -0
  149. package/dist/src/recipes/catalog/platform/index.d.ts +9 -0
  150. package/dist/src/recipes/catalog/platform/index.js +9 -0
  151. package/dist/src/recipes/catalog/platform/messaging.recipe.d.ts +7 -0
  152. package/dist/src/recipes/catalog/platform/messaging.recipe.js +46 -0
  153. package/dist/src/recipes/catalog/platform/observability.recipe.d.ts +8 -0
  154. package/dist/src/recipes/catalog/platform/observability.recipe.js +49 -0
  155. package/dist/src/recipes/catalog/platform/queue.recipe.d.ts +7 -0
  156. package/dist/src/recipes/catalog/platform/queue.recipe.js +61 -0
  157. package/dist/src/recipes/catalog/platform/scheduler.recipe.d.ts +7 -0
  158. package/dist/src/recipes/catalog/platform/scheduler.recipe.js +56 -0
  159. package/dist/src/recipes/catalog/redis.recipe.d.ts +8 -0
  160. package/dist/src/recipes/catalog/redis.recipe.js +79 -0
  161. package/dist/src/recipes/catalog/storage.recipe.d.ts +7 -0
  162. package/dist/src/recipes/catalog/storage.recipe.js +49 -0
  163. package/dist/src/recipes/catalog/websockets.recipe.d.ts +10 -0
  164. package/dist/src/recipes/catalog/websockets.recipe.js +84 -0
  165. package/dist/src/recipes/docker/docker.compose.d.ts +19 -0
  166. package/dist/src/recipes/docker/docker.compose.js +90 -0
  167. package/dist/src/recipes/docker/docker.recipe.d.ts +10 -0
  168. package/dist/src/recipes/docker/docker.recipe.js +51 -0
  169. package/dist/src/recipes/docker/docker.refresh.d.ts +13 -0
  170. package/dist/src/recipes/docker/docker.refresh.js +37 -0
  171. package/dist/src/recipes/docker/index.d.ts +7 -0
  172. package/dist/src/recipes/docker/index.js +7 -0
  173. package/dist/src/recipes/index.d.ts +8 -0
  174. package/dist/src/recipes/index.js +8 -0
  175. package/dist/src/recipes/recipe.registry.d.ts +17 -0
  176. package/dist/src/recipes/recipe.registry.js +46 -0
  177. package/dist/src/recipes/recipe.type.d.ts +93 -0
  178. package/dist/src/recipes/recipe.type.js +12 -0
  179. package/dist/src/resolvers/dependency/dependencyVersions.constant.d.ts +100 -5
  180. package/dist/src/resolvers/dependency/dependencyVersions.constant.js +103 -34
  181. package/dist/src/resolvers/dependency/index.d.ts +1 -1
  182. package/dist/src/resolvers/dependency/index.js +1 -1
  183. package/dist/src/resolvers/project.resolver.d.ts +14 -1
  184. package/dist/src/resolvers/project.resolver.js +11 -3
  185. package/dist/src/scaffolders/scaffolder.helper.js +12 -1
  186. package/dist/src/templates/backendApp/backendApp.core.d.ts +45 -0
  187. package/dist/src/templates/backendApp/backendApp.core.js +66 -0
  188. package/dist/src/templates/backendApp/backendApp.modules.d.ts +26 -0
  189. package/dist/src/templates/backendApp/backendApp.modules.js +25 -0
  190. package/dist/src/templates/backendApp/backendApp.project.d.ts +26 -0
  191. package/dist/src/templates/backendApp/backendApp.project.js +87 -0
  192. package/dist/src/templates/backendApp/index.d.ts +8 -0
  193. package/dist/src/templates/backendApp/index.js +8 -0
  194. package/dist/src/templates/backendApp/parts/config.template.d.ts +28 -0
  195. package/dist/src/templates/backendApp/parts/config.template.js +118 -0
  196. package/dist/src/templates/backendApp/parts/httpUtils.template.d.ts +10 -0
  197. package/dist/src/templates/backendApp/parts/httpUtils.template.js +103 -0
  198. package/dist/src/templates/backendApp/parts/index.d.ts +9 -0
  199. package/dist/src/templates/backendApp/parts/index.js +9 -0
  200. package/dist/src/templates/backendApp/parts/integrations.template.d.ts +16 -0
  201. package/dist/src/templates/backendApp/parts/integrations.template.js +115 -0
  202. package/dist/src/templates/backendApp/parts/wiring.template.d.ts +26 -0
  203. package/dist/src/templates/backendApp/parts/wiring.template.js +111 -0
  204. package/dist/src/templates/microservice/microservice.template.js +61 -87
  205. package/dist/src/templates/modular-monolith/modularMonolith.template.js +25 -77
  206. package/dist/src/templates/monolith/monolith.template.d.ts +11 -26
  207. package/dist/src/templates/monolith/monolith.template.js +49 -146
  208. package/dist/src/templates/resource/index.d.ts +9 -0
  209. package/dist/src/templates/resource/index.js +9 -0
  210. package/dist/src/templates/resource/layers/index.d.ts +9 -0
  211. package/dist/src/templates/resource/layers/index.js +9 -0
  212. package/dist/src/templates/resource/layers/resourceData.template.d.ts +9 -0
  213. package/dist/src/templates/resource/layers/resourceData.template.js +108 -0
  214. package/dist/src/templates/resource/layers/resourcePrisma.template.d.ts +15 -0
  215. package/dist/src/templates/resource/layers/resourcePrisma.template.js +89 -0
  216. package/dist/src/templates/resource/layers/resourceRoutes.template.d.ts +13 -0
  217. package/dist/src/templates/resource/layers/resourceRoutes.template.js +128 -0
  218. package/dist/src/templates/resource/layers/resourceService.template.d.ts +13 -0
  219. package/dist/src/templates/resource/layers/resourceService.template.js +95 -0
  220. package/dist/src/templates/resource/resource.files.d.ts +33 -0
  221. package/dist/src/templates/resource/resource.files.js +99 -0
  222. package/dist/src/templates/resource/resource.names.d.ts +38 -0
  223. package/dist/src/templates/resource/resource.names.js +60 -0
  224. package/dist/src/templates/resource/resource.type.d.ts +19 -0
  225. package/dist/src/templates/resource/resource.type.js +15 -0
  226. package/dist/src/templates/shared/appRuntime.template.js +28 -11
  227. package/dist/src/templates/shared/capability.template.d.ts +13 -4
  228. package/dist/src/templates/shared/capability.template.js +21 -5
  229. package/dist/src/templates/shared/dockerfile.template.d.ts +12 -4
  230. package/dist/src/templates/shared/dockerfile.template.js +68 -29
  231. package/dist/src/templates/shared/pnpm.template.d.ts +8 -2
  232. package/dist/src/templates/shared/pnpm.template.js +9 -1
  233. package/dist/src/templates/shared/server.template.d.ts +23 -22
  234. package/dist/src/templates/shared/server.template.js +79 -53
  235. package/dist/src/types/scaffold.type.d.ts +6 -0
  236. package/dist/src/types/scaffold.type.js +2 -1
  237. package/dist/src/utils/utils.name.js +6 -0
  238. package/dist/src/utils/utils.writeGuard.d.ts +5 -0
  239. package/dist/src/utils/utils.writeGuard.js +23 -0
  240. package/dist/src/wiring/index.d.ts +10 -0
  241. package/dist/src/wiring/index.js +10 -0
  242. package/dist/src/wiring/wiring.dependencies.d.ts +29 -0
  243. package/dist/src/wiring/wiring.dependencies.js +83 -0
  244. package/dist/src/wiring/wiring.edits.d.ts +51 -0
  245. package/dist/src/wiring/wiring.edits.js +90 -0
  246. package/dist/src/wiring/wiring.markers.d.ts +53 -0
  247. package/dist/src/wiring/wiring.markers.js +87 -0
  248. package/package.json +20 -15
@@ -0,0 +1,118 @@
1
+ /**
2
+ * zudojs-cli — Generated `src/configs/index.ts` and `.env.example`.
3
+ *
4
+ * Configuration is read from the environment through @zudojs/config and
5
+ * returned as one frozen, typed object. `zudojs add <feature>` inserts that
6
+ * feature's section between the `config` markers and its variables into
7
+ * `.env.example`, so the two stay in sync.
8
+ */
9
+ import { renderMarkerBlock, MARKERS } from "../../../wiring/index.js";
10
+ /** Variables every generated app reads. */
11
+ export function baseEnvVariables(port) {
12
+ return [
13
+ { name: "NODE_ENV", value: "development" },
14
+ { name: "HOST", value: "0.0.0.0" },
15
+ { name: "PORT", value: String(port) },
16
+ {
17
+ name: "CORS_ORIGINS",
18
+ value: "",
19
+ comment: "Comma-separated origins allowed to call the API from a browser (empty: none)",
20
+ },
21
+ { name: "RATE_LIMIT_WINDOW_MS", value: "60000", comment: "Requests allowed per client per window" },
22
+ { name: "RATE_LIMIT_MAX", value: "300" },
23
+ ];
24
+ }
25
+ /** Renders `.env.example` lines for `variables`. */
26
+ export function renderEnvVariables(variables) {
27
+ return variables
28
+ .map((v) => `${v.comment ? `# ${v.comment}\n` : ""}${v.name}=${v.value}`)
29
+ .join("\n");
30
+ }
31
+ /**
32
+ * Renders `src/configs/index.ts`. `sections` are single-line object entries
33
+ * (for example `redis: Object.freeze({ url: text(config, "redis_url", "...") }),`)
34
+ * placed between the config markers.
35
+ */
36
+ export function renderConfigFile(options) {
37
+ return `import { ConfigurationError } from "@zudojs/errors";
38
+ import {
39
+ createConfigManager,
40
+ createEnvironmentConfigSource,
41
+ type ConfigManager,
42
+ } from "@zudojs/config";
43
+
44
+ const DEFAULT_PORT = ${options.defaultPort};
45
+
46
+ /** Loads \`.env\` into process.env when it exists; real variables win. */
47
+ function loadDotEnv(): void {
48
+ try {
49
+ process.loadEnvFile(".env");
50
+ } catch (error) {
51
+ if ((error as NodeJS.ErrnoException).code !== "ENOENT") throw error;
52
+ }
53
+ }
54
+
55
+ /** A string setting, or \`fallback\` when the variable is unset. */
56
+ export function text(config: ConfigManager, key: string, fallback: string): string {
57
+ return config.string(key, fallback) ?? fallback;
58
+ }
59
+
60
+ /** A comma-separated list setting. */
61
+ export function list(config: ConfigManager, key: string): readonly string[] {
62
+ return (config.string(key, "") ?? "")
63
+ .split(",")
64
+ .map((entry) => entry.trim())
65
+ .filter((entry) => entry.length > 0);
66
+ }
67
+
68
+ /** A non-negative integer setting; anything else is a configuration error. */
69
+ export function int(config: ConfigManager, key: string, fallback: number): number {
70
+ const raw = config.string(key);
71
+ if (raw === undefined || raw.trim() === "") return fallback;
72
+ const value = Number(raw);
73
+ if (!Number.isSafeInteger(value) || value < 0) {
74
+ throw new ConfigurationError(\`\${key.toUpperCase()} must be a non-negative integer, got "\${raw}".\`);
75
+ }
76
+ return value;
77
+ }
78
+
79
+ /** PORT, refusing anything that is not a TCP port. */
80
+ function port(config: ConfigManager): number {
81
+ const raw = config.string("port");
82
+ if (raw === undefined || raw.trim() === "") return DEFAULT_PORT;
83
+ const value = Number(raw);
84
+ if (!Number.isInteger(value) || value < 0 || value > 65535) {
85
+ throw new ConfigurationError(\`PORT must be an integer between 0 and 65535, got "\${raw}".\`);
86
+ }
87
+ return value;
88
+ }
89
+
90
+ /**
91
+ * Reads the application configuration from the environment (and \`.env\`).
92
+ * \`zudojs add <feature>\` adds the feature's settings between the markers.
93
+ */
94
+ export async function loadConfig(env: NodeJS.ProcessEnv = process.env) {
95
+ if (env === process.env) loadDotEnv();
96
+ const config = createConfigManager({
97
+ sources: [createEnvironmentConfigSource({ env })],
98
+ });
99
+ await config.load();
100
+
101
+ return Object.freeze({
102
+ nodeEnv: text(config, "node_env", "development"),
103
+ host: text(config, "host", "0.0.0.0"),
104
+ port: port(config),
105
+ corsOrigins: list(config, "cors_origins"),
106
+ rateLimit: Object.freeze({
107
+ windowMs: int(config, "rate_limit_window_ms", 60_000),
108
+ max: int(config, "rate_limit_max", 300),
109
+ }),
110
+ ${renderMarkerBlock(MARKERS.config, options.sections, " ")}
111
+ });
112
+ }
113
+
114
+ /** The loaded configuration. */
115
+ export type AppConfig = Awaited<ReturnType<typeof loadConfig>>;
116
+ `;
117
+ }
118
+ //# sourceMappingURL=config.template.js.map
@@ -0,0 +1,10 @@
1
+ /**
2
+ * zudojs-cli — Generated `src/utils/http.ts`.
3
+ *
4
+ * The small helpers every generated controller and the server use: JSON
5
+ * responses, schema-issue responses, JSON body reading, mapping exposed
6
+ * 4xx errors to responses, and the @zudojs/security default headers.
7
+ */
8
+ /** Renders `src/utils/http.ts`. */
9
+ export declare function renderHttpUtils(): string;
10
+ //# sourceMappingURL=httpUtils.template.d.ts.map
@@ -0,0 +1,103 @@
1
+ /**
2
+ * zudojs-cli — Generated `src/utils/http.ts`.
3
+ *
4
+ * The small helpers every generated controller and the server use: JSON
5
+ * responses, schema-issue responses, JSON body reading, mapping exposed
6
+ * 4xx errors to responses, and the @zudojs/security default headers.
7
+ */
8
+ /** Renders `src/utils/http.ts`. */
9
+ export function renderHttpUtils() {
10
+ return `import {
11
+ badRequest,
12
+ createResponseContext,
13
+ type HttpMiddleware,
14
+ type HttpResponseContext,
15
+ type HttpRouterContext,
16
+ } from "@zudojs/http";
17
+ import type { SchemaIssue } from "@zudojs/schema";
18
+ import { generateSecurityHeaders } from "@zudojs/security";
19
+
20
+ /** A JSON response with \`status\`. */
21
+ export function json(status: number, data: unknown): HttpResponseContext {
22
+ return createResponseContext({ status }).json(data);
23
+ }
24
+
25
+ /** A response with no body (for example 204). */
26
+ export function empty(status: number): HttpResponseContext {
27
+ return createResponseContext({ status });
28
+ }
29
+
30
+ /** 400 listing where the input failed validation, without echoing it back. */
31
+ export function validationFailed(issues: readonly SchemaIssue[]): HttpResponseContext {
32
+ return json(400, {
33
+ error: "Validation failed",
34
+ issues: issues.map((issue) => ({
35
+ path: issue.path.map(String).join("."),
36
+ message: issue.message,
37
+ })),
38
+ });
39
+ }
40
+
41
+ /**
42
+ * The request body parsed as JSON; \`undefined\` when there is none.
43
+ * Malformed JSON is answered with 400.
44
+ */
45
+ export function readJsonBody(ctx: HttpRouterContext): unknown {
46
+ const body: unknown = ctx.request.body;
47
+ if (body === undefined || body === null) return undefined;
48
+ const text =
49
+ body instanceof Uint8Array
50
+ ? new TextDecoder().decode(body)
51
+ : typeof body === "string"
52
+ ? body
53
+ : undefined;
54
+ if (text === undefined) return body;
55
+ if (text.trim() === "") return undefined;
56
+ try {
57
+ return JSON.parse(text) as unknown;
58
+ } catch {
59
+ throw badRequest("The request body is not valid JSON.");
60
+ }
61
+ }
62
+
63
+ /**
64
+ * The response for an error that carries an exposed 4xx status
65
+ * (NotFoundError, badRequest(), ...). Anything else is left to the server,
66
+ * which answers a generic 500 and never leaks the message.
67
+ */
68
+ export function errorResponse(error: unknown): HttpResponseContext | undefined {
69
+ if (typeof error !== "object" || error === null) return undefined;
70
+ const candidate = error as {
71
+ readonly statusCode?: unknown;
72
+ readonly expose?: unknown;
73
+ readonly message?: unknown;
74
+ readonly code?: unknown;
75
+ };
76
+ const status = candidate.statusCode;
77
+ if (typeof status !== "number" || status < 400 || status > 499) return undefined;
78
+ if (candidate.expose !== true || typeof candidate.message !== "string") return undefined;
79
+ return json(status, {
80
+ error: candidate.message,
81
+ ...(typeof candidate.code === "string" ? { code: candidate.code } : {}),
82
+ });
83
+ }
84
+
85
+ /**
86
+ * Adds the @zudojs/security default headers (CSP, HSTS, nosniff,
87
+ * X-Frame-Options DENY, ...) to every response that does not set its own:
88
+ * the /docs page, for instance, sends a CSP that allows its assets.
89
+ */
90
+ export function securityHeaders(): HttpMiddleware {
91
+ const defaults = Object.entries(generateSecurityHeaders());
92
+ return async (_context, next) => {
93
+ const response = (await next()).clone();
94
+ const present = new Set(Object.keys(response.headers).map((name) => name.toLowerCase()));
95
+ for (const [name, value] of defaults) {
96
+ if (!present.has(name.toLowerCase())) response.setHeader(name, value);
97
+ }
98
+ return response;
99
+ };
100
+ }
101
+ `;
102
+ }
103
+ //# sourceMappingURL=httpUtils.template.js.map
@@ -0,0 +1,9 @@
1
+ /**
2
+ * zudojs-cli — Pieces of a generated backend app: configuration, route and
3
+ * container wiring, integrations and HTTP helpers.
4
+ */
5
+ export * from "./config.template.js";
6
+ export * from "./httpUtils.template.js";
7
+ export * from "./integrations.template.js";
8
+ export * from "./wiring.template.js";
9
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1,9 @@
1
+ /**
2
+ * zudojs-cli — Pieces of a generated backend app: configuration, route and
3
+ * container wiring, integrations and HTTP helpers.
4
+ */
5
+ export * from "./config.template.js";
6
+ export * from "./httpUtils.template.js";
7
+ export * from "./integrations.template.js";
8
+ export * from "./wiring.template.js";
9
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1,16 @@
1
+ /**
2
+ * zudojs-cli — Generated `src/integrations/`.
3
+ *
4
+ * An integration is a client with a lifecycle (Redis, a database, a
5
+ * WebSocket server, a mail transport). `integrations/index.ts` lists them
6
+ * between markers; `integration.ts` runs the list as one runtime module,
7
+ * so they start with `runtime.start()` and stop, in reverse, with
8
+ * `runtime.stop()`. `zudojs add <feature>` writes `integrations/<name>.ts`
9
+ * and registers it.
10
+ */
11
+ import type { MarkerLines } from "./wiring.template.js";
12
+ /** Renders `src/integrations/index.ts`. */
13
+ export declare function renderIntegrationsIndex(lines: MarkerLines): string;
14
+ /** Renders `src/integrations/integration.ts`. */
15
+ export declare function renderIntegrationContract(): string;
16
+ //# sourceMappingURL=integrations.template.d.ts.map
@@ -0,0 +1,115 @@
1
+ /**
2
+ * zudojs-cli — Generated `src/integrations/`.
3
+ *
4
+ * An integration is a client with a lifecycle (Redis, a database, a
5
+ * WebSocket server, a mail transport). `integrations/index.ts` lists them
6
+ * between markers; `integration.ts` runs the list as one runtime module,
7
+ * so they start with `runtime.start()` and stop, in reverse, with
8
+ * `runtime.stop()`. `zudojs add <feature>` writes `integrations/<name>.ts`
9
+ * and registers it.
10
+ */
11
+ import { MARKERS, renderMarkerBlock } from "../../../wiring/index.js";
12
+ /** Renders `src/integrations/index.ts`. */
13
+ export function renderIntegrationsIndex(lines) {
14
+ return `import type { Integration } from "./integration.js";
15
+ ${renderMarkerBlock(MARKERS.integrationImports, lines.imports)}
16
+
17
+ export {
18
+ IntegrationsModule,
19
+ checkIntegrations,
20
+ drainIntegrations,
21
+ type Integration,
22
+ type IntegrationContext,
23
+ } from "./integration.js";
24
+
25
+ /**
26
+ * Started with the runtime in this order and stopped in reverse.
27
+ * \`zudojs add <feature>\` adds entries between the markers.
28
+ */
29
+ export const integrations: readonly Integration[] = [
30
+ ${renderMarkerBlock(MARKERS.integrations, lines.entries, " ")}
31
+ ];
32
+ `;
33
+ }
34
+ /** Renders `src/integrations/integration.ts`. */
35
+ export function renderIntegrationContract() {
36
+ return `import type { Server } from "node:http";
37
+
38
+ import { BaseModule, type ModuleContext } from "@zudojs/core";
39
+
40
+ import type { AppConfig } from "../configs/index.js";
41
+
42
+ /** What an integration receives when it starts. */
43
+ export interface IntegrationContext {
44
+ readonly config: AppConfig;
45
+ readonly logger: ModuleContext["logger"];
46
+ /** The Node HTTP server, for integrations that attach to it (WebSockets). */
47
+ readonly httpServer?: Server;
48
+ }
49
+
50
+ /** A client or server with a lifecycle, started and stopped with the runtime. */
51
+ export interface Integration {
52
+ readonly name: string;
53
+ start(context: IntegrationContext): Promise<void>;
54
+ stop(): Promise<void>;
55
+ /** Called when shutdown begins, before HTTP stops: close long-lived connections. */
56
+ drain?(): Promise<void>;
57
+ /** Whether the integration is healthy; reported by /health. */
58
+ health?(): Promise<boolean>;
59
+ }
60
+
61
+ /** Runs the integrations as one runtime module. */
62
+ export class IntegrationsModule extends BaseModule {
63
+ public readonly id = "integrations";
64
+ public readonly name = "integrations";
65
+ private readonly started: Integration[] = [];
66
+
67
+ public constructor(
68
+ private readonly entries: readonly Integration[],
69
+ private readonly startContext: Omit<IntegrationContext, "logger">,
70
+ ) {
71
+ super({ version: "0.1.0" });
72
+ }
73
+
74
+ public override async onInitialize(context: ModuleContext): Promise<void> {
75
+ for (const integration of this.entries) {
76
+ await integration.start({ ...this.startContext, logger: context.logger });
77
+ this.started.push(integration);
78
+ context.logger.info(\`\${integration.name} started\`);
79
+ }
80
+ }
81
+
82
+ public override async onShutdown(context: ModuleContext): Promise<void> {
83
+ for (const integration of [...this.started].reverse()) {
84
+ try {
85
+ await integration.stop();
86
+ } catch (error) {
87
+ context.logger.error(\`\${integration.name} failed to stop\`, { error });
88
+ }
89
+ }
90
+ this.started.length = 0;
91
+ }
92
+ }
93
+
94
+ /** Lets each integration close long-lived connections before HTTP stops. */
95
+ export async function drainIntegrations(integrations: readonly Integration[]): Promise<void> {
96
+ for (const integration of integrations) {
97
+ await integration.drain?.().catch(() => undefined);
98
+ }
99
+ }
100
+
101
+ /** Health of every integration that reports one. */
102
+ export async function checkIntegrations(
103
+ integrations: readonly Integration[],
104
+ ): Promise<Record<string, "up" | "down">> {
105
+ const checks: Record<string, "up" | "down"> = {};
106
+ for (const integration of integrations) {
107
+ if (integration.health === undefined) continue;
108
+ const healthy = await integration.health().catch(() => false);
109
+ checks[integration.name] = healthy ? "up" : "down";
110
+ }
111
+ return checks;
112
+ }
113
+ `;
114
+ }
115
+ //# sourceMappingURL=integrations.template.js.map
@@ -0,0 +1,26 @@
1
+ /**
2
+ * zudojs-cli — Generated route registration and composition root.
3
+ *
4
+ * - `src/routes/index.ts` exports `registerRoutes(router, deps)`: /health
5
+ * plus every resource (and module) between the `routes` markers.
6
+ * - `src/modules/<name>/routes/index.ts` does the same for one module.
7
+ * - `src/container.ts` constructs every controller, service and repository
8
+ * in one place, between the `container` markers.
9
+ */
10
+ /** Lines a template pre-fills between a pair of markers. */
11
+ export interface MarkerLines {
12
+ readonly imports: readonly string[];
13
+ readonly entries: readonly string[];
14
+ }
15
+ /** Renders `src/routes/index.ts`. */
16
+ export declare function renderRoutesIndex(lines: MarkerLines): string;
17
+ /**
18
+ * Renders `routes/index.ts` of a module: `register<Module>ModuleRoutes`.
19
+ * `containerFromHere` is the import path of `container.js`.
20
+ */
21
+ export declare function renderModuleRoutesIndex(functionName: string, containerFromHere: string, lines?: MarkerLines): string;
22
+ /** Renders `src/routes/health.routes.ts`. */
23
+ export declare function renderHealthRoutes(): string;
24
+ /** Renders `src/container.ts`. */
25
+ export declare function renderContainer(lines: MarkerLines): string;
26
+ //# sourceMappingURL=wiring.template.d.ts.map
@@ -0,0 +1,111 @@
1
+ /**
2
+ * zudojs-cli — Generated route registration and composition root.
3
+ *
4
+ * - `src/routes/index.ts` exports `registerRoutes(router, deps)`: /health
5
+ * plus every resource (and module) between the `routes` markers.
6
+ * - `src/modules/<name>/routes/index.ts` does the same for one module.
7
+ * - `src/container.ts` constructs every controller, service and repository
8
+ * in one place, between the `container` markers.
9
+ */
10
+ import { MARKERS, renderMarkerBlock } from "../../../wiring/index.js";
11
+ /** Renders `src/routes/index.ts`. */
12
+ export function renderRoutesIndex(lines) {
13
+ return `import type { HttpRouter } from "@zudojs/http";
14
+
15
+ import type { AppDependencies } from "../container.js";
16
+ import { registerHealthRoutes } from "./health.routes.js";
17
+ ${renderMarkerBlock(MARKERS.routeImports, lines.imports)}
18
+
19
+ /**
20
+ * Registers every route of the application. \`zudojs generate resource\`
21
+ * and \`zudojs generate module\` add their registrations between the markers.
22
+ */
23
+ export function registerRoutes(router: HttpRouter, deps: AppDependencies): void {
24
+ registerHealthRoutes(router, deps.health);
25
+ ${renderMarkerBlock(MARKERS.routes, lines.entries, " ")}
26
+ }
27
+ `;
28
+ }
29
+ /**
30
+ * Renders `routes/index.ts` of a module: `register<Module>ModuleRoutes`.
31
+ * `containerFromHere` is the import path of `container.js`.
32
+ */
33
+ export function renderModuleRoutesIndex(functionName, containerFromHere, lines = { imports: [], entries: [] }) {
34
+ return `import type { HttpRouter } from "@zudojs/http";
35
+
36
+ import type { AppDependencies } from "${containerFromHere}";
37
+ ${renderMarkerBlock(MARKERS.routeImports, lines.imports)}
38
+
39
+ /** Registers this module's routes; called from the app's routes/index.ts. */
40
+ export function ${functionName}(router: HttpRouter, deps: AppDependencies): void {
41
+ void deps;
42
+ ${renderMarkerBlock(MARKERS.routes, lines.entries, " ")}
43
+ }
44
+ `;
45
+ }
46
+ /** Renders `src/routes/health.routes.ts`. */
47
+ export function renderHealthRoutes() {
48
+ return `import type { HttpRouter } from "@zudojs/http";
49
+
50
+ import { json } from "../utils/http.js";
51
+
52
+ /** What /health reports. */
53
+ export interface HealthReport {
54
+ readonly ready: boolean;
55
+ readonly checks: Readonly<Record<string, "up" | "down">>;
56
+ }
57
+
58
+ /** Computes the current {@link HealthReport}. */
59
+ export type HealthCheck = () => Promise<HealthReport>;
60
+
61
+ /**
62
+ * GET /health: 200 when the runtime is running and every integration is
63
+ * up, 503 otherwise. Hidden from the OpenAPI document.
64
+ */
65
+ export function registerHealthRoutes(router: HttpRouter, check: HealthCheck): void {
66
+ router.get(
67
+ "/health",
68
+ async () => {
69
+ const report = await check();
70
+ return json(report.ready ? 200 : 503, {
71
+ status: report.ready ? "ok" : "unavailable",
72
+ checks: report.checks,
73
+ timestamp: new Date().toISOString(),
74
+ });
75
+ },
76
+ { openapi: false },
77
+ );
78
+ }
79
+ `;
80
+ }
81
+ /** Renders `src/container.ts`. */
82
+ export function renderContainer(lines) {
83
+ return `import type { HealthCheck } from "./routes/health.routes.js";
84
+ ${renderMarkerBlock(MARKERS.containerImports, lines.imports)}
85
+
86
+ /** Options for {@link createDependencies}. */
87
+ export interface DependencyOptions {
88
+ /** Readiness for /health; server.ts passes the runtime's. */
89
+ readonly health?: HealthCheck;
90
+ }
91
+
92
+ /**
93
+ * The composition root: every controller, service and repository is
94
+ * constructed here, once. \`zudojs generate resource\` adds entries between
95
+ * the markers; swap an implementation (e.g. a database repository) here.
96
+ */
97
+ export function createDependencies(options: DependencyOptions = {}) {
98
+ const health: HealthCheck =
99
+ options.health ?? (async () => ({ ready: true, checks: {} }));
100
+
101
+ return {
102
+ health,
103
+ ${renderMarkerBlock(MARKERS.container, lines.entries, " ")}
104
+ };
105
+ }
106
+
107
+ /** Everything route registration receives. */
108
+ export type AppDependencies = ReturnType<typeof createDependencies>;
109
+ `;
110
+ }
111
+ //# sourceMappingURL=wiring.template.js.map