create-fluxstack 1.0.1 → 1.0.3

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 (466) hide show
  1. package/.claude/settings.local.json +63 -0
  2. package/.dockerignore +50 -0
  3. package/.env.example +53 -0
  4. package/.gitattributes +2 -0
  5. package/.github/workflows/ci-build-tests.yml +480 -0
  6. package/.github/workflows/dependency-management.yml +324 -0
  7. package/.github/workflows/release-validation.yml +355 -0
  8. package/.kiro/specs/fluxstack-architecture-optimization/design.md +700 -0
  9. package/.kiro/specs/fluxstack-architecture-optimization/requirements.md +127 -0
  10. package/.kiro/specs/fluxstack-architecture-optimization/tasks.md +330 -0
  11. package/CLAUDE.md +200 -0
  12. package/Dockerfile +58 -0
  13. package/Dockerfile.backend +52 -0
  14. package/Dockerfile.frontend +54 -0
  15. package/ENV_TESTING_REPORT.md +292 -0
  16. package/FRAMEWORK_ROADMAP.md +183 -0
  17. package/FRONTEND_TESTS_README.md +287 -0
  18. package/README-Docker.md +85 -0
  19. package/TEST_RESULTS.md +130 -0
  20. package/ai-context/00-QUICK-START.md +86 -0
  21. package/ai-context/README.md +88 -0
  22. package/ai-context/development/eden-treaty-guide.md +362 -0
  23. package/ai-context/development/patterns.md +382 -0
  24. package/ai-context/examples/crud-complete.md +626 -0
  25. package/ai-context/project/architecture.md +399 -0
  26. package/ai-context/project/overview.md +213 -0
  27. package/ai-context/recent-changes/eden-treaty-refactor.md +281 -0
  28. package/ai-context/recent-changes/type-inference-fix.md +223 -0
  29. package/ai-context/reference/environment-vars.md +384 -0
  30. package/ai-context/reference/troubleshooting.md +407 -0
  31. package/bun.lock +21 -11
  32. package/bunfig.toml +16 -0
  33. package/config/fluxstack.config.ts +48 -0
  34. package/create-fluxstack.ts +2 -3
  35. package/create-test-app.ts +156 -0
  36. package/docker-compose.microservices.yml +75 -0
  37. package/docker-compose.simple.yml +57 -0
  38. package/docker-compose.yml +71 -0
  39. package/docs/dynamic-environment-variables.md +380 -0
  40. package/eslint.config.js +23 -0
  41. package/examples/dynamic-env-usage.ts +283 -0
  42. package/examples/hybrid-env-strategy.ts +212 -0
  43. package/examples/simplified-env-usage.ts +251 -0
  44. package/flux-cli.ts +214 -0
  45. package/fluxstack.config.ts +318 -0
  46. package/meu-app-teste/README.md +44 -0
  47. package/meu-app-teste/app/client/README.md +69 -0
  48. package/meu-app-teste/app/client/frontend-only.ts +12 -0
  49. package/meu-app-teste/app/client/index.html +13 -0
  50. package/meu-app-teste/app/client/public/vite.svg +1 -0
  51. package/meu-app-teste/app/client/src/App.css +883 -0
  52. package/meu-app-teste/app/client/src/App.tsx +669 -0
  53. package/meu-app-teste/app/client/src/assets/react.svg +1 -0
  54. package/meu-app-teste/app/client/src/components/TestPage.tsx +453 -0
  55. package/meu-app-teste/app/client/src/index.css +51 -0
  56. package/meu-app-teste/app/client/src/lib/eden-api.ts +110 -0
  57. package/meu-app-teste/app/client/src/main.tsx +10 -0
  58. package/meu-app-teste/app/client/src/vite-env.d.ts +1 -0
  59. package/meu-app-teste/app/client/tsconfig.app.json +43 -0
  60. package/meu-app-teste/app/client/tsconfig.json +7 -0
  61. package/meu-app-teste/app/client/tsconfig.node.json +25 -0
  62. package/meu-app-teste/app/server/app.ts +10 -0
  63. package/meu-app-teste/app/server/backend-only.ts +15 -0
  64. package/meu-app-teste/app/server/controllers/users.controller.ts +69 -0
  65. package/meu-app-teste/app/server/index.ts +104 -0
  66. package/meu-app-teste/app/server/routes/index.ts +25 -0
  67. package/meu-app-teste/app/server/routes/users.routes.ts +121 -0
  68. package/meu-app-teste/app/server/types/index.ts +1 -0
  69. package/meu-app-teste/app/shared/types/index.ts +18 -0
  70. package/meu-app-teste/bun.lock +1053 -0
  71. package/meu-app-teste/core/__tests__/integration.test.ts +227 -0
  72. package/meu-app-teste/core/build/index.ts +186 -0
  73. package/meu-app-teste/core/cli/command-registry.ts +334 -0
  74. package/meu-app-teste/core/cli/index.ts +394 -0
  75. package/meu-app-teste/core/cli/plugin-discovery.ts +200 -0
  76. package/meu-app-teste/core/client/standalone.ts +57 -0
  77. package/meu-app-teste/core/config/__tests__/config-loader.test.ts +591 -0
  78. package/meu-app-teste/core/config/__tests__/config-merger.test.ts +657 -0
  79. package/meu-app-teste/core/config/__tests__/env-converter.test.ts +372 -0
  80. package/meu-app-teste/core/config/__tests__/env-processor.test.ts +431 -0
  81. package/meu-app-teste/core/config/__tests__/env.test.ts +452 -0
  82. package/meu-app-teste/core/config/__tests__/integration.test.ts +418 -0
  83. package/meu-app-teste/core/config/__tests__/loader.test.ts +331 -0
  84. package/meu-app-teste/core/config/__tests__/schema.test.ts +129 -0
  85. package/meu-app-teste/core/config/__tests__/validator.test.ts +318 -0
  86. package/meu-app-teste/core/config/env-dynamic.ts +326 -0
  87. package/meu-app-teste/core/config/env.ts +597 -0
  88. package/meu-app-teste/core/config/index.ts +317 -0
  89. package/meu-app-teste/core/config/loader.ts +546 -0
  90. package/meu-app-teste/core/config/runtime-config.ts +322 -0
  91. package/meu-app-teste/core/config/schema.ts +694 -0
  92. package/meu-app-teste/core/config/validator.ts +540 -0
  93. package/meu-app-teste/core/framework/__tests__/server.test.ts +233 -0
  94. package/meu-app-teste/core/framework/client.ts +132 -0
  95. package/meu-app-teste/core/framework/index.ts +8 -0
  96. package/meu-app-teste/core/framework/server.ts +501 -0
  97. package/meu-app-teste/core/framework/types.ts +63 -0
  98. package/meu-app-teste/core/plugins/__tests__/built-in.test.ts.disabled +366 -0
  99. package/meu-app-teste/core/plugins/__tests__/manager.test.ts +398 -0
  100. package/meu-app-teste/core/plugins/__tests__/monitoring.test.ts +401 -0
  101. package/meu-app-teste/core/plugins/__tests__/registry.test.ts +335 -0
  102. package/meu-app-teste/core/plugins/built-in/index.ts +142 -0
  103. package/meu-app-teste/core/plugins/built-in/logger/index.ts +180 -0
  104. package/meu-app-teste/core/plugins/built-in/monitoring/README.md +193 -0
  105. package/meu-app-teste/core/plugins/built-in/monitoring/index.ts +912 -0
  106. package/meu-app-teste/core/plugins/built-in/static/index.ts +289 -0
  107. package/meu-app-teste/core/plugins/built-in/swagger/index.ts +229 -0
  108. package/meu-app-teste/core/plugins/built-in/vite/index.ts +316 -0
  109. package/meu-app-teste/core/plugins/config.ts +348 -0
  110. package/meu-app-teste/core/plugins/discovery.ts +350 -0
  111. package/meu-app-teste/core/plugins/executor.ts +351 -0
  112. package/meu-app-teste/core/plugins/index.ts +195 -0
  113. package/meu-app-teste/core/plugins/manager.ts +583 -0
  114. package/meu-app-teste/core/plugins/registry.ts +424 -0
  115. package/meu-app-teste/core/plugins/types.ts +254 -0
  116. package/meu-app-teste/core/server/framework.ts +123 -0
  117. package/meu-app-teste/core/server/index.ts +8 -0
  118. package/meu-app-teste/core/server/plugins/database.ts +182 -0
  119. package/meu-app-teste/core/server/plugins/logger.ts +47 -0
  120. package/meu-app-teste/core/server/plugins/swagger.ts +34 -0
  121. package/meu-app-teste/core/server/standalone.ts +91 -0
  122. package/meu-app-teste/core/templates/create-project.ts +455 -0
  123. package/meu-app-teste/core/types/api.ts +169 -0
  124. package/meu-app-teste/core/types/build.ts +174 -0
  125. package/meu-app-teste/core/types/config.ts +68 -0
  126. package/meu-app-teste/core/types/index.ts +127 -0
  127. package/meu-app-teste/core/types/plugin.ts +94 -0
  128. package/meu-app-teste/core/utils/__tests__/errors.test.ts +139 -0
  129. package/meu-app-teste/core/utils/__tests__/helpers.test.ts +297 -0
  130. package/meu-app-teste/core/utils/__tests__/logger.test.ts +141 -0
  131. package/meu-app-teste/core/utils/env-runtime-v2.ts +232 -0
  132. package/meu-app-teste/core/utils/env-runtime.ts +252 -0
  133. package/meu-app-teste/core/utils/errors/codes.ts +115 -0
  134. package/meu-app-teste/core/utils/errors/handlers.ts +63 -0
  135. package/meu-app-teste/core/utils/errors/index.ts +81 -0
  136. package/meu-app-teste/core/utils/helpers.ts +180 -0
  137. package/meu-app-teste/core/utils/index.ts +18 -0
  138. package/meu-app-teste/core/utils/logger/index.ts +161 -0
  139. package/meu-app-teste/core/utils/logger.ts +106 -0
  140. package/meu-app-teste/core/utils/monitoring/index.ts +212 -0
  141. package/meu-app-teste/package.json +92 -0
  142. package/meu-app-teste/tsconfig.json +51 -0
  143. package/meu-app-teste/vite.config.ts +42 -0
  144. package/my-final-test/README.md +44 -0
  145. package/my-final-test/app/client/README.md +69 -0
  146. package/my-final-test/app/client/frontend-only.ts +12 -0
  147. package/my-final-test/app/client/index.html +13 -0
  148. package/my-final-test/app/client/public/vite.svg +1 -0
  149. package/my-final-test/app/client/src/App.css +883 -0
  150. package/my-final-test/app/client/src/App.tsx +669 -0
  151. package/my-final-test/app/client/src/assets/react.svg +1 -0
  152. package/my-final-test/app/client/src/components/TestPage.tsx +453 -0
  153. package/my-final-test/app/client/src/index.css +51 -0
  154. package/my-final-test/app/client/src/lib/eden-api.ts +110 -0
  155. package/my-final-test/app/client/src/main.tsx +10 -0
  156. package/my-final-test/app/client/src/vite-env.d.ts +1 -0
  157. package/my-final-test/app/client/tsconfig.app.json +43 -0
  158. package/my-final-test/app/client/tsconfig.json +7 -0
  159. package/my-final-test/app/client/tsconfig.node.json +25 -0
  160. package/my-final-test/app/server/app.ts +10 -0
  161. package/my-final-test/app/server/backend-only.ts +15 -0
  162. package/my-final-test/app/server/controllers/users.controller.ts +69 -0
  163. package/my-final-test/app/server/index.ts +104 -0
  164. package/my-final-test/app/server/routes/index.ts +25 -0
  165. package/my-final-test/app/server/routes/users.routes.ts +121 -0
  166. package/my-final-test/app/server/types/index.ts +1 -0
  167. package/my-final-test/app/shared/types/index.ts +18 -0
  168. package/my-final-test/bun.lock +993 -0
  169. package/my-final-test/core/__tests__/integration.test.ts +227 -0
  170. package/my-final-test/core/build/index.ts +186 -0
  171. package/my-final-test/core/cli/command-registry.ts +334 -0
  172. package/my-final-test/core/cli/index.ts +394 -0
  173. package/my-final-test/core/cli/plugin-discovery.ts +200 -0
  174. package/my-final-test/core/client/standalone.ts +57 -0
  175. package/my-final-test/core/config/__tests__/config-loader.test.ts +591 -0
  176. package/my-final-test/core/config/__tests__/config-merger.test.ts +657 -0
  177. package/my-final-test/core/config/__tests__/env-converter.test.ts +372 -0
  178. package/my-final-test/core/config/__tests__/env-processor.test.ts +431 -0
  179. package/my-final-test/core/config/__tests__/env.test.ts +452 -0
  180. package/my-final-test/core/config/__tests__/integration.test.ts +418 -0
  181. package/my-final-test/core/config/__tests__/loader.test.ts +331 -0
  182. package/my-final-test/core/config/__tests__/schema.test.ts +129 -0
  183. package/my-final-test/core/config/__tests__/validator.test.ts +318 -0
  184. package/my-final-test/core/config/env-dynamic.ts +326 -0
  185. package/my-final-test/core/config/env.ts +597 -0
  186. package/my-final-test/core/config/index.ts +317 -0
  187. package/my-final-test/core/config/loader.ts +546 -0
  188. package/my-final-test/core/config/runtime-config.ts +322 -0
  189. package/my-final-test/core/config/schema.ts +694 -0
  190. package/my-final-test/core/config/validator.ts +540 -0
  191. package/my-final-test/core/framework/__tests__/server.test.ts +233 -0
  192. package/my-final-test/core/framework/client.ts +132 -0
  193. package/my-final-test/core/framework/index.ts +8 -0
  194. package/my-final-test/core/framework/server.ts +501 -0
  195. package/my-final-test/core/framework/types.ts +63 -0
  196. package/my-final-test/core/plugins/__tests__/built-in.test.ts.disabled +366 -0
  197. package/my-final-test/core/plugins/__tests__/manager.test.ts +398 -0
  198. package/my-final-test/core/plugins/__tests__/monitoring.test.ts +401 -0
  199. package/my-final-test/core/plugins/__tests__/registry.test.ts +335 -0
  200. package/my-final-test/core/plugins/built-in/index.ts +142 -0
  201. package/my-final-test/core/plugins/built-in/logger/index.ts +180 -0
  202. package/my-final-test/core/plugins/built-in/monitoring/README.md +193 -0
  203. package/my-final-test/core/plugins/built-in/monitoring/index.ts +912 -0
  204. package/my-final-test/core/plugins/built-in/static/index.ts +289 -0
  205. package/my-final-test/core/plugins/built-in/swagger/index.ts +229 -0
  206. package/my-final-test/core/plugins/built-in/vite/index.ts +316 -0
  207. package/my-final-test/core/plugins/config.ts +348 -0
  208. package/my-final-test/core/plugins/discovery.ts +350 -0
  209. package/my-final-test/core/plugins/executor.ts +351 -0
  210. package/my-final-test/core/plugins/index.ts +195 -0
  211. package/my-final-test/core/plugins/manager.ts +583 -0
  212. package/my-final-test/core/plugins/registry.ts +424 -0
  213. package/my-final-test/core/plugins/types.ts +254 -0
  214. package/my-final-test/core/server/framework.ts +123 -0
  215. package/my-final-test/core/server/index.ts +8 -0
  216. package/my-final-test/core/server/plugins/database.ts +182 -0
  217. package/my-final-test/core/server/plugins/logger.ts +47 -0
  218. package/my-final-test/core/server/plugins/swagger.ts +34 -0
  219. package/my-final-test/core/server/standalone.ts +91 -0
  220. package/my-final-test/core/templates/create-project.ts +455 -0
  221. package/my-final-test/core/types/api.ts +169 -0
  222. package/my-final-test/core/types/build.ts +174 -0
  223. package/my-final-test/core/types/config.ts +68 -0
  224. package/my-final-test/core/types/index.ts +127 -0
  225. package/my-final-test/core/types/plugin.ts +94 -0
  226. package/my-final-test/core/utils/__tests__/errors.test.ts +139 -0
  227. package/my-final-test/core/utils/__tests__/helpers.test.ts +297 -0
  228. package/my-final-test/core/utils/__tests__/logger.test.ts +141 -0
  229. package/my-final-test/core/utils/env-runtime-v2.ts +232 -0
  230. package/my-final-test/core/utils/env-runtime.ts +252 -0
  231. package/my-final-test/core/utils/errors/codes.ts +115 -0
  232. package/my-final-test/core/utils/errors/handlers.ts +63 -0
  233. package/my-final-test/core/utils/errors/index.ts +81 -0
  234. package/my-final-test/core/utils/helpers.ts +180 -0
  235. package/my-final-test/core/utils/index.ts +18 -0
  236. package/my-final-test/core/utils/logger/index.ts +161 -0
  237. package/my-final-test/core/utils/logger.ts +106 -0
  238. package/my-final-test/core/utils/monitoring/index.ts +212 -0
  239. package/my-final-test/package.json +68 -0
  240. package/my-final-test/tsconfig.json +51 -0
  241. package/my-final-test/vite.config.ts +42 -0
  242. package/nginx-lb.conf +37 -0
  243. package/package-template.json +32 -15
  244. package/package.json +71 -30
  245. package/publish-setup.md +111 -0
  246. package/publish.sh +63 -0
  247. package/run-clean.ts +26 -0
  248. package/run-env-tests.ts +313 -0
  249. package/tailwind.config.js +34 -0
  250. package/teste-corrigido/README.md +44 -0
  251. package/teste-corrigido/app/client/README.md +69 -0
  252. package/teste-corrigido/app/client/frontend-only.ts +12 -0
  253. package/teste-corrigido/app/client/index.html +13 -0
  254. package/teste-corrigido/app/client/public/vite.svg +1 -0
  255. package/teste-corrigido/app/client/src/App.css +883 -0
  256. package/teste-corrigido/app/client/src/App.tsx +669 -0
  257. package/teste-corrigido/app/client/src/assets/react.svg +1 -0
  258. package/teste-corrigido/app/client/src/components/TestPage.tsx +453 -0
  259. package/teste-corrigido/app/client/src/index.css +51 -0
  260. package/teste-corrigido/app/client/src/lib/eden-api.ts +110 -0
  261. package/teste-corrigido/app/client/src/main.tsx +10 -0
  262. package/teste-corrigido/app/client/src/vite-env.d.ts +1 -0
  263. package/teste-corrigido/app/client/tsconfig.app.json +43 -0
  264. package/teste-corrigido/app/client/tsconfig.json +7 -0
  265. package/teste-corrigido/app/client/tsconfig.node.json +25 -0
  266. package/teste-corrigido/app/server/app.ts +10 -0
  267. package/teste-corrigido/app/server/backend-only.ts +15 -0
  268. package/teste-corrigido/app/server/controllers/users.controller.ts +69 -0
  269. package/teste-corrigido/app/server/index.ts +104 -0
  270. package/teste-corrigido/app/server/routes/index.ts +25 -0
  271. package/teste-corrigido/app/server/routes/users.routes.ts +121 -0
  272. package/teste-corrigido/app/server/types/index.ts +1 -0
  273. package/teste-corrigido/app/shared/types/index.ts +18 -0
  274. package/teste-corrigido/bun.lock +1053 -0
  275. package/teste-corrigido/core/__tests__/integration.test.ts +227 -0
  276. package/teste-corrigido/core/build/index.ts +186 -0
  277. package/teste-corrigido/core/cli/command-registry.ts +334 -0
  278. package/teste-corrigido/core/cli/index.ts +394 -0
  279. package/teste-corrigido/core/cli/plugin-discovery.ts +200 -0
  280. package/teste-corrigido/core/client/standalone.ts +57 -0
  281. package/teste-corrigido/core/config/__tests__/config-loader.test.ts +591 -0
  282. package/teste-corrigido/core/config/__tests__/config-merger.test.ts +657 -0
  283. package/teste-corrigido/core/config/__tests__/env-converter.test.ts +372 -0
  284. package/teste-corrigido/core/config/__tests__/env-processor.test.ts +431 -0
  285. package/teste-corrigido/core/config/__tests__/env.test.ts +452 -0
  286. package/teste-corrigido/core/config/__tests__/integration.test.ts +418 -0
  287. package/teste-corrigido/core/config/__tests__/loader.test.ts +331 -0
  288. package/teste-corrigido/core/config/__tests__/schema.test.ts +129 -0
  289. package/teste-corrigido/core/config/__tests__/validator.test.ts +318 -0
  290. package/teste-corrigido/core/config/env-dynamic.ts +326 -0
  291. package/teste-corrigido/core/config/env.ts +597 -0
  292. package/teste-corrigido/core/config/index.ts +317 -0
  293. package/teste-corrigido/core/config/loader.ts +546 -0
  294. package/teste-corrigido/core/config/runtime-config.ts +322 -0
  295. package/teste-corrigido/core/config/schema.ts +694 -0
  296. package/teste-corrigido/core/config/validator.ts +540 -0
  297. package/teste-corrigido/core/framework/__tests__/server.test.ts +233 -0
  298. package/teste-corrigido/core/framework/client.ts +132 -0
  299. package/teste-corrigido/core/framework/index.ts +8 -0
  300. package/teste-corrigido/core/framework/server.ts +501 -0
  301. package/teste-corrigido/core/framework/types.ts +63 -0
  302. package/teste-corrigido/core/plugins/__tests__/built-in.test.ts.disabled +366 -0
  303. package/teste-corrigido/core/plugins/__tests__/manager.test.ts +398 -0
  304. package/teste-corrigido/core/plugins/__tests__/monitoring.test.ts +401 -0
  305. package/teste-corrigido/core/plugins/__tests__/registry.test.ts +335 -0
  306. package/teste-corrigido/core/plugins/built-in/index.ts +142 -0
  307. package/teste-corrigido/core/plugins/built-in/logger/index.ts +180 -0
  308. package/teste-corrigido/core/plugins/built-in/monitoring/README.md +193 -0
  309. package/teste-corrigido/core/plugins/built-in/monitoring/index.ts +912 -0
  310. package/teste-corrigido/core/plugins/built-in/static/index.ts +289 -0
  311. package/teste-corrigido/core/plugins/built-in/swagger/index.ts +229 -0
  312. package/teste-corrigido/core/plugins/built-in/vite/index.ts +316 -0
  313. package/teste-corrigido/core/plugins/config.ts +348 -0
  314. package/teste-corrigido/core/plugins/discovery.ts +350 -0
  315. package/teste-corrigido/core/plugins/executor.ts +351 -0
  316. package/teste-corrigido/core/plugins/index.ts +195 -0
  317. package/teste-corrigido/core/plugins/manager.ts +583 -0
  318. package/teste-corrigido/core/plugins/registry.ts +424 -0
  319. package/teste-corrigido/core/plugins/types.ts +254 -0
  320. package/teste-corrigido/core/server/framework.ts +123 -0
  321. package/teste-corrigido/core/server/index.ts +8 -0
  322. package/teste-corrigido/core/server/plugins/database.ts +182 -0
  323. package/teste-corrigido/core/server/plugins/logger.ts +47 -0
  324. package/teste-corrigido/core/server/plugins/swagger.ts +34 -0
  325. package/teste-corrigido/core/server/standalone.ts +91 -0
  326. package/teste-corrigido/core/templates/create-project.ts +455 -0
  327. package/teste-corrigido/core/types/api.ts +169 -0
  328. package/teste-corrigido/core/types/build.ts +174 -0
  329. package/teste-corrigido/core/types/config.ts +68 -0
  330. package/teste-corrigido/core/types/index.ts +127 -0
  331. package/teste-corrigido/core/types/plugin.ts +94 -0
  332. package/teste-corrigido/core/utils/__tests__/errors.test.ts +139 -0
  333. package/teste-corrigido/core/utils/__tests__/helpers.test.ts +297 -0
  334. package/teste-corrigido/core/utils/__tests__/logger.test.ts +141 -0
  335. package/teste-corrigido/core/utils/env-runtime-v2.ts +232 -0
  336. package/teste-corrigido/core/utils/env-runtime.ts +252 -0
  337. package/teste-corrigido/core/utils/errors/codes.ts +115 -0
  338. package/teste-corrigido/core/utils/errors/handlers.ts +63 -0
  339. package/teste-corrigido/core/utils/errors/index.ts +81 -0
  340. package/teste-corrigido/core/utils/helpers.ts +180 -0
  341. package/teste-corrigido/core/utils/index.ts +18 -0
  342. package/teste-corrigido/core/utils/logger/index.ts +161 -0
  343. package/teste-corrigido/core/utils/logger.ts +106 -0
  344. package/teste-corrigido/core/utils/monitoring/index.ts +212 -0
  345. package/teste-corrigido/package-template.json +51 -0
  346. package/teste-corrigido/package.json +51 -0
  347. package/teste-corrigido/tsconfig.json +51 -0
  348. package/teste-corrigido/vite.config.ts +42 -0
  349. package/teste-final-npm/README.md +44 -0
  350. package/teste-final-npm/app/client/README.md +69 -0
  351. package/teste-final-npm/app/client/frontend-only.ts +12 -0
  352. package/teste-final-npm/app/client/index.html +13 -0
  353. package/teste-final-npm/app/client/public/vite.svg +1 -0
  354. package/teste-final-npm/app/client/src/App.css +883 -0
  355. package/teste-final-npm/app/client/src/App.tsx +669 -0
  356. package/teste-final-npm/app/client/src/assets/react.svg +1 -0
  357. package/teste-final-npm/app/client/src/components/TestPage.tsx +453 -0
  358. package/teste-final-npm/app/client/src/index.css +51 -0
  359. package/teste-final-npm/app/client/src/lib/eden-api.ts +110 -0
  360. package/teste-final-npm/app/client/src/main.tsx +10 -0
  361. package/teste-final-npm/app/client/src/vite-env.d.ts +1 -0
  362. package/teste-final-npm/app/client/tsconfig.app.json +43 -0
  363. package/teste-final-npm/app/client/tsconfig.json +7 -0
  364. package/teste-final-npm/app/client/tsconfig.node.json +25 -0
  365. package/teste-final-npm/app/server/app.ts +10 -0
  366. package/teste-final-npm/app/server/backend-only.ts +15 -0
  367. package/teste-final-npm/app/server/controllers/users.controller.ts +69 -0
  368. package/teste-final-npm/app/server/index.ts +104 -0
  369. package/teste-final-npm/app/server/routes/index.ts +25 -0
  370. package/teste-final-npm/app/server/routes/users.routes.ts +121 -0
  371. package/teste-final-npm/app/server/types/index.ts +1 -0
  372. package/teste-final-npm/app/shared/types/index.ts +18 -0
  373. package/teste-final-npm/bun.lock +1053 -0
  374. package/teste-final-npm/core/__tests__/integration.test.ts +227 -0
  375. package/teste-final-npm/core/build/index.ts +186 -0
  376. package/teste-final-npm/core/cli/command-registry.ts +334 -0
  377. package/teste-final-npm/core/cli/index.ts +394 -0
  378. package/teste-final-npm/core/cli/plugin-discovery.ts +200 -0
  379. package/teste-final-npm/core/client/standalone.ts +57 -0
  380. package/teste-final-npm/core/config/__tests__/config-loader.test.ts +591 -0
  381. package/teste-final-npm/core/config/__tests__/config-merger.test.ts +657 -0
  382. package/teste-final-npm/core/config/__tests__/env-converter.test.ts +372 -0
  383. package/teste-final-npm/core/config/__tests__/env-processor.test.ts +431 -0
  384. package/teste-final-npm/core/config/__tests__/env.test.ts +452 -0
  385. package/teste-final-npm/core/config/__tests__/integration.test.ts +418 -0
  386. package/teste-final-npm/core/config/__tests__/loader.test.ts +331 -0
  387. package/teste-final-npm/core/config/__tests__/schema.test.ts +129 -0
  388. package/teste-final-npm/core/config/__tests__/validator.test.ts +318 -0
  389. package/teste-final-npm/core/config/env-dynamic.ts +326 -0
  390. package/teste-final-npm/core/config/env.ts +597 -0
  391. package/teste-final-npm/core/config/index.ts +317 -0
  392. package/teste-final-npm/core/config/loader.ts +546 -0
  393. package/teste-final-npm/core/config/runtime-config.ts +322 -0
  394. package/teste-final-npm/core/config/schema.ts +694 -0
  395. package/teste-final-npm/core/config/validator.ts +540 -0
  396. package/teste-final-npm/core/framework/__tests__/server.test.ts +233 -0
  397. package/teste-final-npm/core/framework/client.ts +132 -0
  398. package/teste-final-npm/core/framework/index.ts +8 -0
  399. package/teste-final-npm/core/framework/server.ts +501 -0
  400. package/teste-final-npm/core/framework/types.ts +63 -0
  401. package/teste-final-npm/core/plugins/__tests__/built-in.test.ts.disabled +366 -0
  402. package/teste-final-npm/core/plugins/__tests__/manager.test.ts +398 -0
  403. package/teste-final-npm/core/plugins/__tests__/monitoring.test.ts +401 -0
  404. package/teste-final-npm/core/plugins/__tests__/registry.test.ts +335 -0
  405. package/teste-final-npm/core/plugins/built-in/index.ts +142 -0
  406. package/teste-final-npm/core/plugins/built-in/logger/index.ts +180 -0
  407. package/teste-final-npm/core/plugins/built-in/monitoring/README.md +193 -0
  408. package/teste-final-npm/core/plugins/built-in/monitoring/index.ts +912 -0
  409. package/teste-final-npm/core/plugins/built-in/static/index.ts +289 -0
  410. package/teste-final-npm/core/plugins/built-in/swagger/index.ts +229 -0
  411. package/teste-final-npm/core/plugins/built-in/vite/index.ts +316 -0
  412. package/teste-final-npm/core/plugins/config.ts +348 -0
  413. package/teste-final-npm/core/plugins/discovery.ts +350 -0
  414. package/teste-final-npm/core/plugins/executor.ts +351 -0
  415. package/teste-final-npm/core/plugins/index.ts +195 -0
  416. package/teste-final-npm/core/plugins/manager.ts +583 -0
  417. package/teste-final-npm/core/plugins/registry.ts +424 -0
  418. package/teste-final-npm/core/plugins/types.ts +254 -0
  419. package/teste-final-npm/core/server/framework.ts +123 -0
  420. package/teste-final-npm/core/server/index.ts +8 -0
  421. package/teste-final-npm/core/server/plugins/database.ts +182 -0
  422. package/teste-final-npm/core/server/plugins/logger.ts +47 -0
  423. package/teste-final-npm/core/server/plugins/swagger.ts +34 -0
  424. package/teste-final-npm/core/server/standalone.ts +91 -0
  425. package/teste-final-npm/core/templates/create-project.ts +455 -0
  426. package/teste-final-npm/core/types/api.ts +169 -0
  427. package/teste-final-npm/core/types/build.ts +174 -0
  428. package/teste-final-npm/core/types/config.ts +68 -0
  429. package/teste-final-npm/core/types/index.ts +127 -0
  430. package/teste-final-npm/core/types/plugin.ts +94 -0
  431. package/teste-final-npm/core/utils/__tests__/errors.test.ts +139 -0
  432. package/teste-final-npm/core/utils/__tests__/helpers.test.ts +297 -0
  433. package/teste-final-npm/core/utils/__tests__/logger.test.ts +141 -0
  434. package/teste-final-npm/core/utils/env-runtime-v2.ts +232 -0
  435. package/teste-final-npm/core/utils/env-runtime.ts +252 -0
  436. package/teste-final-npm/core/utils/errors/codes.ts +115 -0
  437. package/teste-final-npm/core/utils/errors/handlers.ts +63 -0
  438. package/teste-final-npm/core/utils/errors/index.ts +81 -0
  439. package/teste-final-npm/core/utils/helpers.ts +180 -0
  440. package/teste-final-npm/core/utils/index.ts +18 -0
  441. package/teste-final-npm/core/utils/logger/index.ts +161 -0
  442. package/teste-final-npm/core/utils/logger.ts +106 -0
  443. package/teste-final-npm/core/utils/monitoring/index.ts +212 -0
  444. package/teste-final-npm/package-template.json +51 -0
  445. package/teste-final-npm/package.json +51 -0
  446. package/teste-final-npm/tsconfig.json +51 -0
  447. package/teste-final-npm/vite.config.ts +42 -0
  448. package/tests/__mocks__/api.ts +56 -0
  449. package/tests/fixtures/users.ts +69 -0
  450. package/tests/integration/api/users.routes.test.ts +221 -0
  451. package/tests/setup.ts +29 -0
  452. package/tests/unit/app/client/App-simple.test.tsx +56 -0
  453. package/tests/unit/app/client/App.test.tsx.skip +237 -0
  454. package/tests/unit/app/client/eden-api.test.ts +186 -0
  455. package/tests/unit/app/client/simple.test.tsx +23 -0
  456. package/tests/unit/app/controllers/users.controller.test.ts +150 -0
  457. package/tests/unit/core/create-project.test.ts.skip +95 -0
  458. package/tests/unit/core/framework.test.ts +144 -0
  459. package/tests/unit/core/plugins/logger.test.ts.skip +268 -0
  460. package/tests/unit/core/plugins/vite.test.ts.disabled +188 -0
  461. package/tests/utils/test-helpers.ts +61 -0
  462. package/types/global.d.ts +30 -0
  463. package/types/vitest.d.ts +9 -0
  464. package/vitest.config.ts +50 -0
  465. package/workspace.json +6 -0
  466. package/.env +0 -30
@@ -0,0 +1,912 @@
1
+ /**
2
+ * Monitoring Plugin for FluxStack
3
+ * Provides performance monitoring, metrics collection, and system monitoring
4
+ */
5
+
6
+ import type { Plugin, PluginContext, RequestContext, ResponseContext, ErrorContext } from "../../types"
7
+ import { MetricsCollector } from "../../../utils/monitoring"
8
+ import * as os from 'os'
9
+ import * as fs from 'fs'
10
+ import * as path from 'path'
11
+
12
+ // Enhanced metrics interfaces
13
+ interface Metric {
14
+ name: string
15
+ value: number
16
+ timestamp: number
17
+ labels?: Record<string, string>
18
+ }
19
+
20
+ interface Counter extends Metric {
21
+ type: 'counter'
22
+ inc(value?: number): void
23
+ }
24
+
25
+ interface Gauge extends Metric {
26
+ type: 'gauge'
27
+ set(value: number): void
28
+ inc(value?: number): void
29
+ dec(value?: number): void
30
+ }
31
+
32
+ interface Histogram extends Metric {
33
+ type: 'histogram'
34
+ buckets: number[]
35
+ values: number[]
36
+ observe(value: number): void
37
+ }
38
+
39
+ interface MetricsRegistry {
40
+ counters: Map<string, Counter>
41
+ gauges: Map<string, Gauge>
42
+ histograms: Map<string, Histogram>
43
+ }
44
+
45
+ // SystemMetrics and HttpMetrics are now imported from MetricsCollector
46
+
47
+ export interface MetricsExporter {
48
+ type: 'prometheus' | 'json' | 'console' | 'file'
49
+ endpoint?: string
50
+ interval?: number
51
+ enabled: boolean
52
+ format?: 'text' | 'json'
53
+ filePath?: string
54
+ }
55
+
56
+ export interface AlertThreshold {
57
+ metric: string
58
+ operator: '>' | '<' | '>=' | '<=' | '==' | '!='
59
+ value: number
60
+ severity: 'info' | 'warning' | 'error' | 'critical'
61
+ message?: string
62
+ }
63
+
64
+ export const monitoringPlugin: Plugin = {
65
+ name: "monitoring",
66
+ version: "1.0.0",
67
+ description: "Performance monitoring plugin with metrics collection and system monitoring",
68
+ author: "FluxStack Team",
69
+ priority: "high", // Should run early to capture all metrics
70
+ category: "monitoring",
71
+ tags: ["monitoring", "metrics", "performance", "observability"],
72
+ dependencies: [], // No dependencies
73
+
74
+ configSchema: {
75
+ type: "object",
76
+ properties: {
77
+ enabled: {
78
+ type: "boolean",
79
+ description: "Enable monitoring plugin"
80
+ },
81
+ httpMetrics: {
82
+ type: "boolean",
83
+ description: "Collect HTTP request/response metrics"
84
+ },
85
+ systemMetrics: {
86
+ type: "boolean",
87
+ description: "Collect system metrics (memory, CPU, etc.)"
88
+ },
89
+ customMetrics: {
90
+ type: "boolean",
91
+ description: "Enable custom metrics collection"
92
+ },
93
+ collectInterval: {
94
+ type: "number",
95
+ minimum: 1000,
96
+ description: "Interval for collecting system metrics (ms)"
97
+ },
98
+ retentionPeriod: {
99
+ type: "number",
100
+ minimum: 60000,
101
+ description: "How long to retain metrics in memory (ms)"
102
+ },
103
+ exporters: {
104
+ type: "array",
105
+ items: {
106
+ type: "object",
107
+ properties: {
108
+ type: {
109
+ type: "string",
110
+ enum: ["prometheus", "json", "console", "file"]
111
+ },
112
+ endpoint: { type: "string" },
113
+ interval: { type: "number" },
114
+ enabled: { type: "boolean" },
115
+ format: {
116
+ type: "string",
117
+ enum: ["text", "json"]
118
+ },
119
+ filePath: { type: "string" }
120
+ },
121
+ required: ["type"]
122
+ },
123
+ description: "Metrics exporters configuration"
124
+ },
125
+ thresholds: {
126
+ type: "object",
127
+ properties: {
128
+ responseTime: { type: "number" },
129
+ errorRate: { type: "number" },
130
+ memoryUsage: { type: "number" },
131
+ cpuUsage: { type: "number" }
132
+ },
133
+ description: "Alert thresholds"
134
+ },
135
+ alerts: {
136
+ type: "array",
137
+ items: {
138
+ type: "object",
139
+ properties: {
140
+ metric: { type: "string" },
141
+ operator: {
142
+ type: "string",
143
+ enum: [">", "<", ">=", "<=", "==", "!="]
144
+ },
145
+ value: { type: "number" },
146
+ severity: {
147
+ type: "string",
148
+ enum: ["info", "warning", "error", "critical"]
149
+ },
150
+ message: { type: "string" }
151
+ },
152
+ required: ["metric", "operator", "value", "severity"]
153
+ },
154
+ description: "Custom alert configurations"
155
+ }
156
+ },
157
+ additionalProperties: false
158
+ },
159
+
160
+ defaultConfig: {
161
+ enabled: true,
162
+ httpMetrics: true,
163
+ systemMetrics: true,
164
+ customMetrics: true,
165
+ collectInterval: 5000,
166
+ retentionPeriod: 300000, // 5 minutes
167
+ exporters: [
168
+ {
169
+ type: "console",
170
+ interval: 30000,
171
+ enabled: false
172
+ },
173
+ {
174
+ type: "prometheus",
175
+ endpoint: "/metrics",
176
+ enabled: true,
177
+ format: "text"
178
+ }
179
+ ],
180
+ thresholds: {
181
+ responseTime: 1000, // ms
182
+ errorRate: 0.05, // 5%
183
+ memoryUsage: 0.8, // 80%
184
+ cpuUsage: 0.8 // 80%
185
+ },
186
+ alerts: []
187
+ },
188
+
189
+ setup: async (context: PluginContext) => {
190
+ const config = getPluginConfig(context)
191
+
192
+ if (!config.enabled) {
193
+ context.logger.info('Monitoring plugin disabled by configuration')
194
+ return
195
+ }
196
+
197
+ context.logger.info('Initializing monitoring plugin', {
198
+ httpMetrics: config.httpMetrics,
199
+ systemMetrics: config.systemMetrics,
200
+ customMetrics: config.customMetrics,
201
+ exporters: config.exporters.length,
202
+ alerts: config.alerts.length
203
+ })
204
+
205
+ // Initialize enhanced metrics registry
206
+ const metricsRegistry: MetricsRegistry = {
207
+ counters: new Map(),
208
+ gauges: new Map(),
209
+ histograms: new Map()
210
+ }
211
+
212
+ // Initialize metrics collector
213
+ const metricsCollector = new MetricsCollector()
214
+
215
+ // Store registry and collector in context for access by other hooks
216
+ ;(context as any).metricsRegistry = metricsRegistry
217
+ ;(context as any).metricsCollector = metricsCollector
218
+
219
+ // Initialize HTTP metrics
220
+ if (config.httpMetrics) {
221
+ initializeHttpMetrics(metricsRegistry, metricsCollector)
222
+ }
223
+
224
+ // Start system metrics collection
225
+ if (config.systemMetrics) {
226
+ startSystemMetricsCollection(context, config, metricsCollector)
227
+ }
228
+
229
+ // Setup metrics endpoint for Prometheus
230
+ setupMetricsEndpoint(context, config, metricsRegistry, metricsCollector)
231
+
232
+ // Start metrics exporters
233
+ startMetricsExporters(context, config, metricsRegistry, metricsCollector)
234
+
235
+ // Setup metrics cleanup
236
+ setupMetricsCleanup(context, config, metricsRegistry)
237
+
238
+ // Setup alert monitoring
239
+ if (config.alerts.length > 0) {
240
+ setupAlertMonitoring(context, config, metricsRegistry)
241
+ }
242
+
243
+ context.logger.info('Monitoring plugin initialized successfully')
244
+ },
245
+
246
+ onServerStart: async (context: PluginContext) => {
247
+ const config = getPluginConfig(context)
248
+
249
+ if (config.enabled) {
250
+ context.logger.info('Monitoring plugin: Server monitoring started', {
251
+ pid: process.pid,
252
+ nodeVersion: process.version,
253
+ platform: process.platform
254
+ })
255
+
256
+ // Record server start metric
257
+ const metricsRegistry = (context as any).metricsRegistry as MetricsRegistry
258
+ if (metricsRegistry) {
259
+ recordCounter(metricsRegistry, 'server_starts_total', 1, {
260
+ version: context.config.app.version
261
+ })
262
+ }
263
+ }
264
+ },
265
+
266
+ onServerStop: async (context: PluginContext) => {
267
+ const config = getPluginConfig(context)
268
+
269
+ if (config.enabled) {
270
+ context.logger.info('Monitoring plugin: Server monitoring stopped')
271
+
272
+ // Record server stop metric
273
+ const metricsRegistry = (context as any).metricsRegistry as MetricsRegistry
274
+ if (metricsRegistry) {
275
+ recordCounter(metricsRegistry, 'server_stops_total', 1)
276
+ }
277
+
278
+ // Cleanup intervals
279
+ const intervals = (context as any).monitoringIntervals as NodeJS.Timeout[]
280
+ if (intervals) {
281
+ intervals.forEach(interval => clearInterval(interval))
282
+ }
283
+ }
284
+ },
285
+
286
+ onRequest: async (requestContext: RequestContext) => {
287
+ const startTime = Date.now()
288
+
289
+ // Store start time for duration calculation
290
+ ;(requestContext as any).monitoringStartTime = startTime
291
+
292
+ // Get metrics registry and collector from context
293
+ const metricsRegistry = getMetricsRegistry(requestContext)
294
+ const metricsCollector = getMetricsCollector(requestContext)
295
+ if (!metricsRegistry || !metricsCollector) return
296
+
297
+ // Record request metrics
298
+ recordCounter(metricsRegistry, 'http_requests_total', 1, {
299
+ method: requestContext.method,
300
+ path: requestContext.path
301
+ })
302
+
303
+ // Record request size if available
304
+ const contentLength = requestContext.headers['content-length']
305
+ if (contentLength) {
306
+ const size = parseInt(contentLength)
307
+ recordHistogram(metricsRegistry, 'http_request_size_bytes', size, {
308
+ method: requestContext.method
309
+ })
310
+ }
311
+
312
+ // Record in collector as well
313
+ const counter = metricsCollector.getAllMetrics().get('http_requests_total')
314
+ if (counter && typeof (counter as any).inc === 'function') {
315
+ (counter as any).inc(1, { method: requestContext.method, path: requestContext.path })
316
+ }
317
+ },
318
+
319
+ onResponse: async (responseContext: ResponseContext) => {
320
+ const metricsRegistry = getMetricsRegistry(responseContext)
321
+ const metricsCollector = getMetricsCollector(responseContext)
322
+ if (!metricsRegistry || !metricsCollector) return
323
+
324
+ const startTime = (responseContext as any).monitoringStartTime || responseContext.startTime
325
+ const duration = Date.now() - startTime
326
+
327
+ // Record response metrics
328
+ recordHistogram(metricsRegistry, 'http_request_duration_ms', duration, {
329
+ method: responseContext.method,
330
+ path: responseContext.path,
331
+ status_code: responseContext.statusCode.toString()
332
+ })
333
+
334
+ // Record response size
335
+ if (responseContext.size) {
336
+ recordHistogram(metricsRegistry, 'http_response_size_bytes', responseContext.size, {
337
+ method: responseContext.method,
338
+ status_code: responseContext.statusCode.toString()
339
+ })
340
+ }
341
+
342
+ // Record status code
343
+ recordCounter(metricsRegistry, 'http_responses_total', 1, {
344
+ method: responseContext.method,
345
+ status_code: responseContext.statusCode.toString()
346
+ })
347
+
348
+ // Record in collector
349
+ metricsCollector.recordHttpRequest(
350
+ responseContext.method,
351
+ responseContext.path,
352
+ responseContext.statusCode,
353
+ duration,
354
+ parseInt(responseContext.headers['content-length'] || '0') || undefined,
355
+ responseContext.size
356
+ )
357
+
358
+ // Check thresholds and log warnings
359
+ const config = getPluginConfig(responseContext)
360
+ if (config.thresholds.responseTime && duration > config.thresholds.responseTime) {
361
+ const logger = (responseContext as any).logger || console
362
+ logger.warn(`Slow request detected: ${responseContext.method} ${responseContext.path} took ${duration}ms`, {
363
+ method: responseContext.method,
364
+ path: responseContext.path,
365
+ duration,
366
+ threshold: config.thresholds.responseTime
367
+ })
368
+ }
369
+ },
370
+
371
+ onError: async (errorContext: ErrorContext) => {
372
+ const metricsRegistry = getMetricsRegistry(errorContext)
373
+ const metricsCollector = getMetricsCollector(errorContext)
374
+ if (!metricsRegistry || !metricsCollector) return
375
+
376
+ // Record error metrics
377
+ recordCounter(metricsRegistry, 'http_errors_total', 1, {
378
+ method: errorContext.method,
379
+ path: errorContext.path,
380
+ error_type: errorContext.error.name
381
+ })
382
+
383
+ // Record error duration
384
+ recordHistogram(metricsRegistry, 'http_error_duration_ms', errorContext.duration, {
385
+ method: errorContext.method,
386
+ error_type: errorContext.error.name
387
+ })
388
+
389
+ // Record in collector (treat as 500 error)
390
+ metricsCollector.recordHttpRequest(
391
+ errorContext.method,
392
+ errorContext.path,
393
+ 500,
394
+ errorContext.duration
395
+ )
396
+
397
+ // Increment error counter in collector
398
+ const errorCounter = metricsCollector.getAllMetrics().get('http_errors_total')
399
+ if (errorCounter && typeof (errorCounter as any).inc === 'function') {
400
+ (errorCounter as any).inc(1, {
401
+ method: errorContext.method,
402
+ path: errorContext.path,
403
+ error_type: errorContext.error.name
404
+ })
405
+ }
406
+ }
407
+ }
408
+
409
+ // Helper functions
410
+
411
+ function getPluginConfig(context: any) {
412
+ // In a real implementation, this would get the config from the plugin context
413
+ const pluginConfig = context.config?.plugins?.config?.monitoring || {}
414
+ return { ...monitoringPlugin.defaultConfig, ...pluginConfig }
415
+ }
416
+
417
+ function getMetricsRegistry(context: any): MetricsRegistry | null {
418
+ // In a real implementation, this would get the registry from the plugin context
419
+ return (context as any).metricsRegistry || null
420
+ }
421
+
422
+ function getMetricsCollector(context: any): MetricsCollector | null {
423
+ // In a real implementation, this would get the collector from the plugin context
424
+ return (context as any).metricsCollector || null
425
+ }
426
+
427
+ function initializeHttpMetrics(registry: MetricsRegistry, collector: MetricsCollector) {
428
+ // Initialize HTTP-related counters and histograms
429
+ recordCounter(registry, 'http_requests_total', 0)
430
+ recordCounter(registry, 'http_responses_total', 0)
431
+ recordCounter(registry, 'http_errors_total', 0)
432
+ recordHistogram(registry, 'http_request_duration_ms', 0)
433
+ recordHistogram(registry, 'http_request_size_bytes', 0)
434
+ recordHistogram(registry, 'http_response_size_bytes', 0)
435
+
436
+ // Initialize metrics in collector
437
+ collector.createCounter('http_requests_total', 'Total number of HTTP requests')
438
+ collector.createCounter('http_responses_total', 'Total number of HTTP responses')
439
+ collector.createCounter('http_errors_total', 'Total number of HTTP errors')
440
+ collector.createHistogram('http_request_duration_seconds', 'HTTP request duration in seconds', [0.1, 0.5, 1, 2.5, 5, 10])
441
+ collector.createHistogram('http_request_size_bytes', 'HTTP request size in bytes', [100, 1000, 10000, 100000, 1000000])
442
+ collector.createHistogram('http_response_size_bytes', 'HTTP response size in bytes', [100, 1000, 10000, 100000, 1000000])
443
+ }
444
+
445
+ function startSystemMetricsCollection(context: PluginContext, config: any, collector: MetricsCollector) {
446
+ const intervals: NodeJS.Timeout[] = []
447
+
448
+ // Initialize system metrics in collector
449
+ collector.createGauge('process_memory_rss_bytes', 'Process resident set size in bytes')
450
+ collector.createGauge('process_memory_heap_used_bytes', 'Process heap used in bytes')
451
+ collector.createGauge('process_memory_heap_total_bytes', 'Process heap total in bytes')
452
+ collector.createGauge('process_memory_external_bytes', 'Process external memory in bytes')
453
+ collector.createGauge('process_cpu_user_seconds_total', 'Process CPU user time in seconds')
454
+ collector.createGauge('process_cpu_system_seconds_total', 'Process CPU system time in seconds')
455
+ collector.createGauge('process_uptime_seconds', 'Process uptime in seconds')
456
+ collector.createGauge('process_pid', 'Process ID')
457
+ collector.createGauge('nodejs_version_info', 'Node.js version info')
458
+
459
+ if (process.platform !== 'win32') {
460
+ collector.createGauge('system_load_average_1m', 'System load average over 1 minute')
461
+ collector.createGauge('system_load_average_5m', 'System load average over 5 minutes')
462
+ collector.createGauge('system_load_average_15m', 'System load average over 15 minutes')
463
+ }
464
+
465
+ const collectSystemMetrics = () => {
466
+ const metricsRegistry = (context as any).metricsRegistry as MetricsRegistry
467
+ if (!metricsRegistry) return
468
+
469
+ try {
470
+ // Memory metrics
471
+ const memUsage = process.memoryUsage()
472
+ recordGauge(metricsRegistry, 'process_memory_rss_bytes', memUsage.rss)
473
+ recordGauge(metricsRegistry, 'process_memory_heap_used_bytes', memUsage.heapUsed)
474
+ recordGauge(metricsRegistry, 'process_memory_heap_total_bytes', memUsage.heapTotal)
475
+ recordGauge(metricsRegistry, 'process_memory_external_bytes', memUsage.external)
476
+
477
+ // CPU metrics
478
+ const cpuUsage = process.cpuUsage()
479
+ recordGauge(metricsRegistry, 'process_cpu_user_seconds_total', cpuUsage.user / 1000000)
480
+ recordGauge(metricsRegistry, 'process_cpu_system_seconds_total', cpuUsage.system / 1000000)
481
+
482
+ // Process metrics
483
+ recordGauge(metricsRegistry, 'process_uptime_seconds', process.uptime())
484
+ recordGauge(metricsRegistry, 'process_pid', process.pid)
485
+ recordGauge(metricsRegistry, 'nodejs_version_info', 1, { version: process.version })
486
+
487
+ // System metrics
488
+ const totalMem = os.totalmem()
489
+ const freeMem = os.freemem()
490
+ recordGauge(metricsRegistry, 'system_memory_total_bytes', totalMem)
491
+ recordGauge(metricsRegistry, 'system_memory_free_bytes', freeMem)
492
+ recordGauge(metricsRegistry, 'system_memory_used_bytes', totalMem - freeMem)
493
+
494
+ // CPU count
495
+ recordGauge(metricsRegistry, 'system_cpu_count', os.cpus().length)
496
+
497
+ // Load average (Unix-like systems only)
498
+ if (process.platform !== 'win32') {
499
+ const loadAvg = os.loadavg()
500
+ recordGauge(metricsRegistry, 'system_load_average_1m', loadAvg[0])
501
+ recordGauge(metricsRegistry, 'system_load_average_5m', loadAvg[1])
502
+ recordGauge(metricsRegistry, 'system_load_average_15m', loadAvg[2])
503
+ }
504
+
505
+ // Event loop lag measurement
506
+ const start = process.hrtime.bigint()
507
+ setImmediate(() => {
508
+ const lag = Number(process.hrtime.bigint() - start) / 1e6 // Convert to milliseconds
509
+ recordGauge(metricsRegistry, 'nodejs_eventloop_lag_seconds', lag / 1000)
510
+ })
511
+
512
+ } catch (error) {
513
+ context.logger.error('Error collecting system metrics', { error })
514
+ }
515
+ }
516
+
517
+ // Collect metrics immediately and then at intervals
518
+ collectSystemMetrics()
519
+ const interval = setInterval(collectSystemMetrics, config.collectInterval)
520
+ intervals.push(interval)
521
+
522
+ // Store intervals for cleanup
523
+ ;(context as any).monitoringIntervals = intervals
524
+ }
525
+
526
+ function setupMetricsEndpoint(context: PluginContext, config: any, _registry: MetricsRegistry, collector: MetricsCollector) {
527
+ // Find Prometheus exporter configuration
528
+ const prometheusExporter = config.exporters.find((e: any) => e.type === 'prometheus' && e.enabled)
529
+ if (!prometheusExporter) return
530
+
531
+ const endpoint = prometheusExporter.endpoint || '/metrics'
532
+
533
+ // Add metrics endpoint to the app
534
+ if (context.app && typeof context.app.get === 'function') {
535
+ context.app.get(endpoint, () => {
536
+ const prometheusData = collector.exportPrometheus()
537
+ return new Response(prometheusData, {
538
+ headers: {
539
+ 'Content-Type': 'text/plain; version=0.0.4; charset=utf-8'
540
+ }
541
+ })
542
+ })
543
+
544
+ context.logger.info(`Metrics endpoint available at ${endpoint}`)
545
+ }
546
+ }
547
+
548
+ function startMetricsExporters(context: PluginContext, config: any, registry: MetricsRegistry, collector: MetricsCollector) {
549
+ const intervals: NodeJS.Timeout[] = (context as any).monitoringIntervals || []
550
+
551
+ for (const exporterConfig of config.exporters) {
552
+ if (!exporterConfig.enabled) continue
553
+
554
+ const exportMetrics = () => {
555
+ try {
556
+ switch (exporterConfig.type) {
557
+ case 'console':
558
+ exportToConsole(registry, collector, context.logger)
559
+ break
560
+ case 'prometheus':
561
+ if (!exporterConfig.endpoint) {
562
+ // Only export to logs if no endpoint is configured
563
+ exportToPrometheus(registry, collector, exporterConfig, context.logger)
564
+ }
565
+ break
566
+ case 'json':
567
+ exportToJson(registry, collector, exporterConfig, context.logger)
568
+ break
569
+ case 'file':
570
+ exportToFile(registry, collector, exporterConfig, context.logger)
571
+ break
572
+ default:
573
+ context.logger.warn(`Unknown exporter type: ${exporterConfig.type}`)
574
+ }
575
+ } catch (error) {
576
+ context.logger.error(`Error in ${exporterConfig.type} exporter`, { error })
577
+ }
578
+ }
579
+
580
+ if (exporterConfig.interval) {
581
+ const interval = setInterval(exportMetrics, exporterConfig.interval)
582
+ intervals.push(interval)
583
+ }
584
+ }
585
+
586
+ ;(context as any).monitoringIntervals = intervals
587
+ }
588
+
589
+ function setupAlertMonitoring(context: PluginContext, config: any, registry: MetricsRegistry) {
590
+ const intervals: NodeJS.Timeout[] = (context as any).monitoringIntervals || []
591
+
592
+ const checkAlerts = () => {
593
+ for (const alert of config.alerts) {
594
+ try {
595
+ const metricValue = getMetricValue(registry, alert.metric)
596
+ if (metricValue !== null && evaluateThreshold(metricValue, alert.operator, alert.value)) {
597
+ const message = alert.message || `Alert: ${alert.metric} ${alert.operator} ${alert.value} (current: ${metricValue})`
598
+
599
+ switch (alert.severity) {
600
+ case 'critical':
601
+ case 'error':
602
+ context.logger.error(message, {
603
+ metric: alert.metric,
604
+ value: metricValue,
605
+ threshold: alert.value,
606
+ severity: alert.severity
607
+ })
608
+ break
609
+ case 'warning':
610
+ context.logger.warn(message, {
611
+ metric: alert.metric,
612
+ value: metricValue,
613
+ threshold: alert.value,
614
+ severity: alert.severity
615
+ })
616
+ break
617
+ case 'info':
618
+ default:
619
+ context.logger.info(message, {
620
+ metric: alert.metric,
621
+ value: metricValue,
622
+ threshold: alert.value,
623
+ severity: alert.severity
624
+ })
625
+ break
626
+ }
627
+ }
628
+ } catch (error) {
629
+ context.logger.error(`Error checking alert for ${alert.metric}`, { error })
630
+ }
631
+ }
632
+ }
633
+
634
+ // Check alerts every 30 seconds
635
+ const interval = setInterval(checkAlerts, 30000)
636
+ intervals.push(interval)
637
+
638
+ ;(context as any).monitoringIntervals = intervals
639
+ }
640
+
641
+ function setupMetricsCleanup(context: PluginContext, config: any, registry: MetricsRegistry) {
642
+ const intervals: NodeJS.Timeout[] = (context as any).monitoringIntervals || []
643
+
644
+ const cleanup = () => {
645
+ const now = Date.now()
646
+ const cutoff = now - config.retentionPeriod
647
+
648
+ // Clean up old metrics
649
+ for (const [key, metric] of registry.counters.entries()) {
650
+ if (metric.timestamp < cutoff) {
651
+ registry.counters.delete(key)
652
+ }
653
+ }
654
+
655
+ for (const [key, metric] of registry.gauges.entries()) {
656
+ if (metric.timestamp < cutoff) {
657
+ registry.gauges.delete(key)
658
+ }
659
+ }
660
+
661
+ for (const [key, metric] of registry.histograms.entries()) {
662
+ if (metric.timestamp < cutoff) {
663
+ registry.histograms.delete(key)
664
+ }
665
+ }
666
+ }
667
+
668
+ // Clean up every minute
669
+ const interval = setInterval(cleanup, 60000)
670
+ intervals.push(interval)
671
+
672
+ ;(context as any).monitoringIntervals = intervals
673
+ }
674
+
675
+ // Metrics recording functions
676
+ function recordCounter(registry: MetricsRegistry, name: string, value: number, labels?: Record<string, string>) {
677
+ const key = createMetricKey(name, labels)
678
+ const existing = registry.counters.get(key)
679
+
680
+ registry.counters.set(key, {
681
+ type: 'counter',
682
+ name,
683
+ value: existing ? existing.value + value : value,
684
+ timestamp: Date.now(),
685
+ labels,
686
+ inc: (incValue = 1) => {
687
+ const metric = registry.counters.get(key)
688
+ if (metric) {
689
+ metric.value += incValue
690
+ metric.timestamp = Date.now()
691
+ }
692
+ }
693
+ })
694
+ }
695
+
696
+ function recordGauge(registry: MetricsRegistry, name: string, value: number, labels?: Record<string, string>) {
697
+ const key = createMetricKey(name, labels)
698
+
699
+ registry.gauges.set(key, {
700
+ type: 'gauge',
701
+ name,
702
+ value,
703
+ timestamp: Date.now(),
704
+ labels,
705
+ set: (newValue: number) => {
706
+ const metric = registry.gauges.get(key)
707
+ if (metric) {
708
+ metric.value = newValue
709
+ metric.timestamp = Date.now()
710
+ }
711
+ },
712
+ inc: (incValue = 1) => {
713
+ const metric = registry.gauges.get(key)
714
+ if (metric) {
715
+ metric.value += incValue
716
+ metric.timestamp = Date.now()
717
+ }
718
+ },
719
+ dec: (decValue = 1) => {
720
+ const metric = registry.gauges.get(key)
721
+ if (metric) {
722
+ metric.value -= decValue
723
+ metric.timestamp = Date.now()
724
+ }
725
+ }
726
+ })
727
+ }
728
+
729
+ function recordHistogram(registry: MetricsRegistry, name: string, value: number, labels?: Record<string, string>) {
730
+ const key = createMetricKey(name, labels)
731
+
732
+ const existing = registry.histograms.get(key)
733
+ if (existing) {
734
+ existing.values.push(value)
735
+ existing.timestamp = Date.now()
736
+ } else {
737
+ registry.histograms.set(key, {
738
+ type: 'histogram',
739
+ name,
740
+ value,
741
+ timestamp: Date.now(),
742
+ labels,
743
+ buckets: [0.1, 0.5, 1, 2.5, 5, 10],
744
+ values: [value],
745
+ observe: (observeValue: number) => {
746
+ const metric = registry.histograms.get(key)
747
+ if (metric) {
748
+ metric.values.push(observeValue)
749
+ metric.timestamp = Date.now()
750
+ }
751
+ }
752
+ })
753
+ }
754
+ }
755
+
756
+ function createMetricKey(name: string, labels?: Record<string, string>): string {
757
+ if (!labels || Object.keys(labels).length === 0) {
758
+ return name
759
+ }
760
+
761
+ const labelString = Object.entries(labels)
762
+ .sort(([a], [b]) => a.localeCompare(b))
763
+ .map(([key, value]) => `${key}="${value}"`)
764
+ .join(',')
765
+
766
+ return `${name}{${labelString}}`
767
+ }
768
+
769
+ function getMetricValue(registry: MetricsRegistry, metricName: string): number | null {
770
+ // Check counters
771
+ const counter = registry.counters.get(metricName)
772
+ if (counter) return counter.value
773
+
774
+ // Check gauges
775
+ const gauge = registry.gauges.get(metricName)
776
+ if (gauge) return gauge.value
777
+
778
+ // Check histograms (return average)
779
+ const histogram = registry.histograms.get(metricName)
780
+ if (histogram && histogram.values.length > 0) {
781
+ return histogram.values.reduce((sum, val) => sum + val, 0) / histogram.values.length
782
+ }
783
+
784
+ return null
785
+ }
786
+
787
+ function evaluateThreshold(value: number, operator: string, threshold: number): boolean {
788
+ switch (operator) {
789
+ case '>': return value > threshold
790
+ case '<': return value < threshold
791
+ case '>=': return value >= threshold
792
+ case '<=': return value <= threshold
793
+ case '==': return value === threshold
794
+ case '!=': return value !== threshold
795
+ default: return false
796
+ }
797
+ }
798
+
799
+ // Enhanced Exporters
800
+ function exportToConsole(registry: MetricsRegistry, collector: MetricsCollector, logger: any) {
801
+ const metrics = {
802
+ counters: Array.from(registry.counters.values()),
803
+ gauges: Array.from(registry.gauges.values()),
804
+ histograms: Array.from(registry.histograms.values())
805
+ }
806
+
807
+ const systemMetrics = collector.getSystemMetrics()
808
+ const httpMetrics = collector.getHttpMetrics()
809
+
810
+ logger.info('Metrics snapshot', {
811
+ timestamp: new Date().toISOString(),
812
+ counters: metrics.counters.length,
813
+ gauges: metrics.gauges.length,
814
+ histograms: metrics.histograms.length,
815
+ system: systemMetrics,
816
+ http: httpMetrics,
817
+ metrics
818
+ })
819
+ }
820
+
821
+ function exportToPrometheus(_registry: MetricsRegistry, collector: MetricsCollector, config: any, logger: any) {
822
+ const prometheusData = collector.exportPrometheus()
823
+
824
+ if (config.endpoint && config.endpoint !== '/metrics') {
825
+ // POST to Prometheus pushgateway
826
+ fetch(config.endpoint, {
827
+ method: 'POST',
828
+ headers: {
829
+ 'Content-Type': 'text/plain; version=0.0.4; charset=utf-8'
830
+ },
831
+ body: prometheusData
832
+ }).catch(error => {
833
+ logger.error('Failed to push metrics to Prometheus', { error, endpoint: config.endpoint })
834
+ })
835
+ } else {
836
+ logger.debug('Prometheus metrics generated', { lines: prometheusData.split('\n').length })
837
+ }
838
+ }
839
+
840
+ function exportToJson(registry: MetricsRegistry, collector: MetricsCollector, config: any, logger: any) {
841
+ const data = {
842
+ timestamp: new Date().toISOString(),
843
+ system: collector.getSystemMetrics(),
844
+ http: collector.getHttpMetrics(),
845
+ counters: Object.fromEntries(registry.counters.entries()),
846
+ gauges: Object.fromEntries(registry.gauges.entries()),
847
+ histograms: Object.fromEntries(registry.histograms.entries())
848
+ }
849
+
850
+ if (config.endpoint) {
851
+ // POST to JSON endpoint
852
+ fetch(config.endpoint, {
853
+ method: 'POST',
854
+ headers: {
855
+ 'Content-Type': 'application/json'
856
+ },
857
+ body: JSON.stringify(data)
858
+ }).catch(error => {
859
+ logger.error('Failed to export metrics to JSON endpoint', { error, endpoint: config.endpoint })
860
+ })
861
+ } else {
862
+ logger.info('JSON metrics export', data)
863
+ }
864
+ }
865
+
866
+ function exportToFile(registry: MetricsRegistry, collector: MetricsCollector, config: any, logger: any) {
867
+ if (!config.filePath) {
868
+ logger.warn('File exporter configured but no filePath specified')
869
+ return
870
+ }
871
+
872
+ const data = {
873
+ timestamp: new Date().toISOString(),
874
+ system: collector.getSystemMetrics(),
875
+ http: collector.getHttpMetrics(),
876
+ counters: Object.fromEntries(registry.counters.entries()),
877
+ gauges: Object.fromEntries(registry.gauges.entries()),
878
+ histograms: Object.fromEntries(registry.histograms.entries())
879
+ }
880
+
881
+ const content = config.format === 'json'
882
+ ? JSON.stringify(data, null, 2)
883
+ : collector.exportPrometheus()
884
+
885
+ try {
886
+ // Ensure directory exists
887
+ const dir = path.dirname(config.filePath)
888
+ if (!fs.existsSync(dir)) {
889
+ fs.mkdirSync(dir, { recursive: true })
890
+ }
891
+
892
+ // Write metrics to file
893
+ fs.writeFileSync(config.filePath, content, 'utf8')
894
+ logger.debug('Metrics exported to file', { filePath: config.filePath, format: config.format })
895
+ } catch (error) {
896
+ logger.error('Failed to export metrics to file', { error, filePath: config.filePath })
897
+ }
898
+ }
899
+
900
+ export function formatPrometheusLabels(labels?: Record<string, string>): string {
901
+ if (!labels || Object.keys(labels).length === 0) {
902
+ return ''
903
+ }
904
+
905
+ const labelPairs = Object.entries(labels)
906
+ .map(([key, value]) => `${key}="${value}"`)
907
+ .join(',')
908
+
909
+ return `{${labelPairs}}`
910
+ }
911
+
912
+ export default monitoringPlugin