blockmine 1.24.0 → 1.27.0

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 (476) hide show
  1. package/CHANGELOG.md +76 -1
  2. package/README.en.md +427 -0
  3. package/README.md +40 -0
  4. package/backend/package.json +2 -2
  5. package/backend/prisma/migrations/20260328173000_add_plugin_source_ref/migration.sql +2 -0
  6. package/backend/prisma/migrations/migration_lock.toml +2 -2
  7. package/backend/prisma/schema.prisma +2 -0
  8. package/backend/src/ai/plugin-assistant-system-prompt.md +664 -5
  9. package/backend/src/api/routes/apiKeys.js +8 -0
  10. package/backend/src/api/routes/bots.js +271 -9
  11. package/backend/src/api/routes/eventGraphs.js +151 -1
  12. package/backend/src/api/routes/health.js +38 -0
  13. package/backend/src/api/routes/nodeRegistry.js +63 -0
  14. package/backend/src/api/routes/plugins.js +254 -29
  15. package/backend/src/api/routes/servers.js +14 -2
  16. package/backend/src/container.js +11 -8
  17. package/backend/src/core/BotCommandLoader.js +161 -0
  18. package/backend/src/core/BotConnection.js +125 -0
  19. package/backend/src/core/BotEventHandlers.js +234 -0
  20. package/backend/src/core/BotIPCHandler.js +445 -0
  21. package/backend/src/core/BotManager.js +15 -7
  22. package/backend/src/core/BotProcess.js +169 -140
  23. package/backend/src/core/EventGraphManager.js +7 -3
  24. package/backend/src/core/GraphDebugHandler.js +229 -0
  25. package/backend/src/core/GraphDebugIPC.js +117 -0
  26. package/backend/src/core/GraphExecutionEngine.js +545 -978
  27. package/backend/src/core/GraphTraversal.js +80 -0
  28. package/backend/src/core/GraphValidation.js +73 -0
  29. package/backend/src/core/NodeDefinition.js +138 -0
  30. package/backend/src/core/NodeRegistry.js +153 -141
  31. package/backend/src/core/PluginLoader.js +83 -3
  32. package/backend/src/core/PluginManager.js +346 -35
  33. package/backend/src/core/RewindSignal.js +9 -0
  34. package/backend/src/core/config/ConfigValidator.js +72 -0
  35. package/backend/src/core/config/FeatureFlags.js +52 -0
  36. package/backend/src/core/config/__tests__/ConfigValidator.test.js +232 -0
  37. package/backend/src/core/domain/entities/Bot.js +39 -0
  38. package/backend/src/core/domain/entities/Command.js +41 -0
  39. package/backend/src/core/domain/entities/EventGraph.js +39 -0
  40. package/backend/src/core/domain/entities/Plugin.js +45 -0
  41. package/backend/src/core/domain/entities/User.js +40 -0
  42. package/backend/src/core/domain/services/DependencyResolver.js +168 -0
  43. package/backend/src/core/domain/services/GraphValidator.js +117 -0
  44. package/backend/src/core/domain/services/PermissionChecker.js +34 -0
  45. package/backend/src/core/domain/services/__tests__/DependencyResolver.test.js +126 -0
  46. package/backend/src/core/domain/valueObjects/BotConfig.js +27 -0
  47. package/backend/src/core/domain/valueObjects/DependencyGraph.js +86 -0
  48. package/backend/src/core/domain/valueObjects/PluginManifest.js +36 -0
  49. package/backend/src/core/errors/BaseError.js +29 -0
  50. package/backend/src/core/errors/ErrorHandler.js +81 -0
  51. package/backend/src/core/errors/__tests__/ErrorHandler.test.js +188 -0
  52. package/backend/src/core/errors/index.js +68 -0
  53. package/backend/src/core/infrastructure/BatchingUtility.js +66 -0
  54. package/backend/src/core/infrastructure/CircuitBreaker.js +103 -0
  55. package/backend/src/core/infrastructure/ConnectionPool.js +81 -0
  56. package/backend/src/core/infrastructure/RateLimiter.js +64 -0
  57. package/backend/src/core/infrastructure/__tests__/BatchingUtility.test.js +86 -0
  58. package/backend/src/core/infrastructure/__tests__/CircuitBreaker.test.js +156 -0
  59. package/backend/src/core/infrastructure/__tests__/ConnectionPool.test.js +146 -0
  60. package/backend/src/core/infrastructure/__tests__/RateLimiter.test.js +171 -0
  61. package/backend/src/core/ipc/botApiFactory.js +72 -0
  62. package/backend/src/core/ipc/ipcMessageTypes.js +115 -0
  63. package/backend/src/core/logging/AuditLogger.js +61 -0
  64. package/backend/src/core/logging/StructuredLogger.js +80 -0
  65. package/backend/src/core/logging/__tests__/StructuredLogger.test.js +213 -0
  66. package/backend/src/core/logging/index.js +7 -0
  67. package/backend/src/core/metrics/MetricsCollector.js +104 -0
  68. package/backend/src/core/metrics/__tests__/MetricsCollector.test.js +131 -0
  69. package/backend/src/core/node-registries/actionsNodes.js +191 -0
  70. package/backend/src/core/node-registries/arraysNodes.js +152 -0
  71. package/backend/src/core/node-registries/botNodes.js +48 -0
  72. package/backend/src/core/node-registries/containerNodes.js +141 -0
  73. package/backend/src/core/node-registries/dataNodes.js +284 -0
  74. package/backend/src/core/node-registries/debugNodes.js +23 -0
  75. package/backend/src/core/node-registries/eventsNodes.js +223 -0
  76. package/backend/src/core/node-registries/flowNodes.js +151 -0
  77. package/backend/src/core/node-registries/furnaceNodes.js +123 -0
  78. package/backend/src/core/node-registries/index.js +108 -0
  79. package/backend/src/core/node-registries/inventory.js +102 -106
  80. package/backend/src/core/node-registries/logicNodes.js +54 -0
  81. package/backend/src/core/node-registries/mathNodes.js +38 -0
  82. package/backend/src/core/node-registries/navigationNodes.js +109 -0
  83. package/backend/src/core/node-registries/objectsNodes.js +90 -0
  84. package/backend/src/core/node-registries/stringsNodes.js +165 -0
  85. package/backend/src/core/node-registries/timeNodes.js +105 -0
  86. package/backend/src/core/node-registries/typeNodes.js +22 -0
  87. package/backend/src/core/node-registries/usersNodes.js +126 -0
  88. package/backend/src/core/nodes/arrays/shuffle.js +14 -0
  89. package/backend/src/core/nodes/bot/get_name.js +8 -0
  90. package/backend/src/core/nodes/bot/stop_bot.js +5 -0
  91. package/backend/src/core/nodes/container/open.js +101 -111
  92. package/backend/src/core/nodes/data/store_read.js +26 -0
  93. package/backend/src/core/nodes/data/store_write.js +23 -0
  94. package/backend/src/core/nodes/event/call_event.js +31 -0
  95. package/backend/src/core/nodes/event/custom_event.js +8 -0
  96. package/backend/src/core/nodes/flow/timer.js +35 -0
  97. package/backend/src/core/nodes/inventory/drop.js +73 -65
  98. package/backend/src/core/nodes/inventory/equip.js +54 -45
  99. package/backend/src/core/nodes/inventory/select_slot.js +48 -46
  100. package/backend/src/core/nodes/navigation/follow.js +54 -51
  101. package/backend/src/core/nodes/navigation/go_to.js +41 -53
  102. package/backend/src/core/nodes/navigation/go_to_entity.js +65 -69
  103. package/backend/src/core/nodes/navigation/go_to_player.js +65 -70
  104. package/backend/src/core/nodes/navigation/stop.js +17 -26
  105. package/backend/src/core/nodes/users/add_to_group.js +24 -0
  106. package/backend/src/core/nodes/users/check_permission.js +26 -0
  107. package/backend/src/core/nodes/users/remove_from_group.js +24 -0
  108. package/backend/src/core/services/BotIPCMessageRouter.js +337 -0
  109. package/backend/src/core/services/BotLifecycleService.js +43 -450
  110. package/backend/src/core/services/CacheManager.js +83 -23
  111. package/backend/src/core/services/CrashRestartManager.js +42 -0
  112. package/backend/src/core/services/DebugSessionManager.js +114 -12
  113. package/backend/src/core/services/EventGraphService.js +69 -0
  114. package/backend/src/core/services/MinecraftBotManager.js +9 -1
  115. package/backend/src/core/services/PluginManagementService.js +84 -0
  116. package/backend/src/core/services/TestModeContext.js +65 -0
  117. package/backend/src/core/services/__tests__/CacheManager.test.js +168 -0
  118. package/backend/src/core/services.js +1 -11
  119. package/backend/src/core/validation/InputValidator.js +167 -0
  120. package/backend/src/core/validation/__tests__/InputValidator.test.js +296 -0
  121. package/backend/src/real-time/botApi/index.js +1 -1
  122. package/backend/src/real-time/socketHandler.js +26 -0
  123. package/backend/src/server.js +21 -6
  124. package/frontend/dist/assets/browser-ponyfill-D8y0Ty7C.js +2 -0
  125. package/frontend/dist/assets/index-CFJLS0dk.css +32 -0
  126. package/frontend/dist/assets/index-D91UGNMG.js +11260 -0
  127. package/frontend/dist/flags/en.svg +32 -0
  128. package/frontend/dist/flags/ru.svg +5 -0
  129. package/frontend/dist/index.html +2 -2
  130. package/frontend/dist/locales/en/admin.json +100 -0
  131. package/frontend/dist/locales/en/api-keys.json +58 -0
  132. package/frontend/dist/locales/en/bots.json +113 -0
  133. package/frontend/dist/locales/en/common.json +53 -0
  134. package/frontend/dist/locales/en/configuration.json +22 -0
  135. package/frontend/dist/locales/en/console.json +10 -0
  136. package/frontend/dist/locales/en/dashboard.json +85 -0
  137. package/frontend/dist/locales/en/dialogs.json +70 -0
  138. package/frontend/dist/locales/en/event-graphs.json +50 -0
  139. package/frontend/dist/locales/en/graph-store.json +70 -0
  140. package/frontend/dist/locales/en/login.json +36 -0
  141. package/frontend/dist/locales/en/management.json +192 -0
  142. package/frontend/dist/locales/en/minecraft-viewer.json +27 -0
  143. package/frontend/dist/locales/en/nodes.json +1132 -0
  144. package/frontend/dist/locales/en/permissions.json +50 -0
  145. package/frontend/dist/locales/en/plugin-detail.json +69 -0
  146. package/frontend/dist/locales/en/plugins.json +329 -0
  147. package/frontend/dist/locales/en/proxies.json +81 -0
  148. package/frontend/dist/locales/en/servers.json +39 -0
  149. package/frontend/dist/locales/en/setup.json +19 -0
  150. package/frontend/dist/locales/en/sidebar.json +195 -0
  151. package/frontend/dist/locales/en/tasks.json +62 -0
  152. package/frontend/dist/locales/en/visual-editor.json +418 -0
  153. package/frontend/dist/locales/en/websocket.json +86 -0
  154. package/frontend/dist/locales/ru/admin.json +100 -0
  155. package/frontend/dist/locales/ru/api-keys.json +58 -0
  156. package/frontend/dist/locales/ru/bots.json +113 -0
  157. package/frontend/dist/locales/ru/common.json +49 -0
  158. package/frontend/dist/locales/ru/configuration.json +22 -0
  159. package/frontend/dist/locales/ru/console.json +10 -0
  160. package/frontend/dist/locales/ru/dashboard.json +85 -0
  161. package/frontend/dist/locales/ru/dialogs.json +70 -0
  162. package/frontend/dist/locales/ru/event-graphs.json +50 -0
  163. package/frontend/dist/locales/ru/graph-store.json +70 -0
  164. package/frontend/dist/locales/ru/login.json +36 -0
  165. package/frontend/dist/locales/ru/management.json +192 -0
  166. package/frontend/dist/locales/ru/minecraft-viewer.json +30 -0
  167. package/frontend/dist/locales/ru/nodes.json +1131 -0
  168. package/frontend/dist/locales/ru/permissions.json +50 -0
  169. package/frontend/dist/locales/ru/plugin-detail.json +49 -0
  170. package/frontend/dist/locales/ru/plugins.json +209 -0
  171. package/frontend/dist/locales/ru/proxies.json +81 -0
  172. package/frontend/dist/locales/ru/servers.json +39 -0
  173. package/frontend/dist/locales/ru/setup.json +19 -0
  174. package/frontend/dist/locales/ru/sidebar.json +195 -0
  175. package/frontend/dist/locales/ru/tasks.json +62 -0
  176. package/frontend/dist/locales/ru/visual-editor.json +420 -0
  177. package/frontend/dist/locales/ru/websocket.json +86 -0
  178. package/frontend/dist/monacoeditorwork/css.worker.bundle.js +7 -7
  179. package/frontend/dist/monacoeditorwork/html.worker.bundle.js +7 -7
  180. package/frontend/dist/monacoeditorwork/json.worker.bundle.js +7 -7
  181. package/frontend/dist/monacoeditorwork/ts.worker.bundle.js +3 -3
  182. package/frontend/package.json +6 -0
  183. package/nul +12 -0
  184. package/package.json +3 -3
  185. package/screen/3dviewer.png +0 -0
  186. package/screen/console.png +0 -0
  187. package/screen/dashboard.png +0 -0
  188. package/screen/graph_collabe.png +0 -0
  189. package/screen/graph_live_debug.png +0 -0
  190. package/screen/language_selector.png +0 -0
  191. package/screen/management_command.png +0 -0
  192. package/screen/node_debug_trace.png +0 -0
  193. package/screen/plugin_/320/276/320/261/320/267/320/276/321/200.png +0 -0
  194. package/screen/websocket.png +0 -0
  195. package/screen//320/275/320/260/321/201/321/202/321/200/320/276/320/271/320/272/320/270_/320/276/321/202/320/264/320/265/320/273/321/214/320/275/321/213/321/205_/320/272/320/276/320/274/320/260/320/275/320/264_/320/272/320/260/320/266/320/264/321/203_/320/272/320/276/320/274/320/260/320/275/320/273/320/264/321/203_/320/274/320/276/320/266/320/275/320/276_/320/275/320/260/321/201/321/202/321/200/320/260/320/270/320/262/320/260/321/202/321/214.png +0 -0
  196. package/screen//320/277/320/273/320/260/320/275/320/270/321/200/320/276/320/262/321/211/320/270/320/272_/320/274/320/276/320/266/320/275/320/276_/320/267/320/260/320/264/320/260/320/262/320/260/321/202/321/214_/320/264/320/265/320/271/321/201/321/202/320/262/320/270/321/217_/320/277/320/276_/320/262/321/200/320/265/320/274/320/265/320/275/320/270.png +0 -0
  197. package/.claude/agents/README.md +0 -469
  198. package/.claude/agents/auth-route-debugger.md +0 -118
  199. package/.claude/agents/auth-route-tester.md +0 -93
  200. package/.claude/agents/auto-error-resolver.md +0 -97
  201. package/.claude/agents/build-optimizer.md +0 -236
  202. package/.claude/agents/code-architect.md +0 -34
  203. package/.claude/agents/code-architecture-reviewer.md +0 -83
  204. package/.claude/agents/code-explorer.md +0 -51
  205. package/.claude/agents/code-refactor-master.md +0 -94
  206. package/.claude/agents/code-reviewer.md +0 -46
  207. package/.claude/agents/cost-optimizer.md +0 -134
  208. package/.claude/agents/deployment-orchestrator.md +0 -113
  209. package/.claude/agents/documentation-architect.md +0 -82
  210. package/.claude/agents/frontend-error-fixer.md +0 -77
  211. package/.claude/agents/iac-code-generator.md +0 -71
  212. package/.claude/agents/incident-responder.md +0 -346
  213. package/.claude/agents/infrastructure-architect.md +0 -31
  214. package/.claude/agents/kubernetes-specialist.md +0 -56
  215. package/.claude/agents/migration-planner.md +0 -181
  216. package/.claude/agents/network-architect.md +0 -196
  217. package/.claude/agents/plan-reviewer.md +0 -52
  218. package/.claude/agents/refactor-planner.md +0 -63
  219. package/.claude/agents/security-scanner.md +0 -102
  220. package/.claude/agents/web-research-specialist.md +0 -78
  221. package/.claude/commands/cost-analysis.md +0 -315
  222. package/.claude/commands/dev-docs-update.md +0 -55
  223. package/.claude/commands/dev-docs.md +0 -51
  224. package/.claude/commands/feature-dev.md +0 -125
  225. package/.claude/commands/incident-debug.md +0 -247
  226. package/.claude/commands/infra-plan.md +0 -81
  227. package/.claude/commands/migration-plan.md +0 -478
  228. package/.claude/commands/route-research-for-testing.md +0 -37
  229. package/.claude/commands/security-review.md +0 -66
  230. package/.claude/hooks/CONFIG.md +0 -448
  231. package/.claude/hooks/README.md +0 -163
  232. package/.claude/hooks/SKILL_ACTIVATION_COMPLETE.md +0 -226
  233. package/.claude/hooks/WINDOWS_HOOKS_README.md +0 -151
  234. package/.claude/hooks/add-skill-activation-banners.ts +0 -132
  235. package/.claude/hooks/comprehensive-skill-test.ts +0 -1315
  236. package/.claude/hooks/error-handling-reminder.sh +0 -12
  237. package/.claude/hooks/error-handling-reminder.ts +0 -222
  238. package/.claude/hooks/k8s-manifest-validator.sh +0 -56
  239. package/.claude/hooks/package-lock.json +0 -556
  240. package/.claude/hooks/package.json +0 -16
  241. package/.claude/hooks/post-tool-use-tracker.ps1 +0 -174
  242. package/.claude/hooks/post-tool-use-tracker.sh +0 -183
  243. package/.claude/hooks/security-policy-check.sh +0 -247
  244. package/.claude/hooks/skill-activation-prompt.ps1 +0 -10
  245. package/.claude/hooks/skill-activation-prompt.sh +0 -10
  246. package/.claude/hooks/skill-activation-prompt.ts +0 -141
  247. package/.claude/hooks/stop-build-check-enhanced.sh +0 -130
  248. package/.claude/hooks/terraform-validator.sh +0 -53
  249. package/.claude/hooks/test-input.json +0 -7
  250. package/.claude/hooks/test-skill-activation.ts +0 -427
  251. package/.claude/hooks/trigger-build-resolver.sh +0 -79
  252. package/.claude/hooks/tsc-check.sh +0 -173
  253. package/.claude/hooks/tsconfig.json +0 -19
  254. package/.claude/settings.json +0 -59
  255. package/.claude/settings.local.json +0 -67
  256. package/.claude/skills/README.md +0 -507
  257. package/.claude/skills/api-engineering/SKILL.md +0 -63
  258. package/.claude/skills/api-engineering/resources/api-versioning.md +0 -88
  259. package/.claude/skills/api-engineering/resources/graphql-patterns.md +0 -106
  260. package/.claude/skills/api-engineering/resources/rate-limiting.md +0 -118
  261. package/.claude/skills/api-engineering/resources/rest-api-design.md +0 -105
  262. package/.claude/skills/backend-dev-guidelines/SKILL.md +0 -306
  263. package/.claude/skills/backend-dev-guidelines/resources/architecture-overview.md +0 -451
  264. package/.claude/skills/backend-dev-guidelines/resources/async-and-errors.md +0 -307
  265. package/.claude/skills/backend-dev-guidelines/resources/complete-examples.md +0 -638
  266. package/.claude/skills/backend-dev-guidelines/resources/configuration.md +0 -275
  267. package/.claude/skills/backend-dev-guidelines/resources/database-patterns.md +0 -224
  268. package/.claude/skills/backend-dev-guidelines/resources/middleware-guide.md +0 -213
  269. package/.claude/skills/backend-dev-guidelines/resources/routing-and-controllers.md +0 -756
  270. package/.claude/skills/backend-dev-guidelines/resources/sentry-and-monitoring.md +0 -336
  271. package/.claude/skills/backend-dev-guidelines/resources/services-and-repositories.md +0 -789
  272. package/.claude/skills/backend-dev-guidelines/resources/testing-guide.md +0 -235
  273. package/.claude/skills/backend-dev-guidelines/resources/validation-patterns.md +0 -754
  274. package/.claude/skills/budget-and-cost-management/SKILL.md +0 -850
  275. package/.claude/skills/build-engineering/SKILL.md +0 -431
  276. package/.claude/skills/build-engineering/resources/artifact-repositories.md +0 -72
  277. package/.claude/skills/build-engineering/resources/build-caching.md +0 -96
  278. package/.claude/skills/build-engineering/resources/build-pipelines.md +0 -105
  279. package/.claude/skills/build-engineering/resources/build-security.md +0 -95
  280. package/.claude/skills/build-engineering/resources/build-systems.md +0 -389
  281. package/.claude/skills/build-engineering/resources/compilation-optimization.md +0 -201
  282. package/.claude/skills/build-engineering/resources/dependency-management.md +0 -73
  283. package/.claude/skills/build-engineering/resources/monorepo-builds.md +0 -110
  284. package/.claude/skills/build-engineering/resources/performance-optimization.md +0 -113
  285. package/.claude/skills/build-engineering/resources/reproducible-builds.md +0 -82
  286. package/.claude/skills/cloud-engineering/SKILL.md +0 -675
  287. package/.claude/skills/cloud-engineering/resources/aws-patterns.md +0 -742
  288. package/.claude/skills/cloud-engineering/resources/azure-patterns.md +0 -714
  289. package/.claude/skills/cloud-engineering/resources/cleared-cloud-environments.md +0 -987
  290. package/.claude/skills/cloud-engineering/resources/cloud-cost-optimization.md +0 -757
  291. package/.claude/skills/cloud-engineering/resources/cloud-networking.md +0 -1058
  292. package/.claude/skills/cloud-engineering/resources/cloud-security-tools.md +0 -1530
  293. package/.claude/skills/cloud-engineering/resources/cloud-security.md +0 -990
  294. package/.claude/skills/cloud-engineering/resources/gcp-patterns.md +0 -758
  295. package/.claude/skills/cloud-engineering/resources/migration-strategies.md +0 -820
  296. package/.claude/skills/cloud-engineering/resources/multi-cloud-strategies.md +0 -670
  297. package/.claude/skills/cloud-engineering/resources/oci-patterns.md +0 -1198
  298. package/.claude/skills/cloud-engineering/resources/serverless-patterns.md +0 -795
  299. package/.claude/skills/cloud-engineering/resources/well-architected-frameworks.md +0 -966
  300. package/.claude/skills/cybersecurity/SKILL.md +0 -409
  301. package/.claude/skills/cybersecurity/resources/security-architecture.md +0 -266
  302. package/.claude/skills/database-engineering/SKILL.md +0 -61
  303. package/.claude/skills/database-engineering/resources/backup-and-recovery.md +0 -72
  304. package/.claude/skills/database-engineering/resources/database-replication.md +0 -63
  305. package/.claude/skills/database-engineering/resources/postgresql-fundamentals.md +0 -70
  306. package/.claude/skills/database-engineering/resources/query-optimization.md +0 -68
  307. package/.claude/skills/devsecops/SKILL.md +0 -374
  308. package/.claude/skills/devsecops/resources/ci-cd-security.md +0 -204
  309. package/.claude/skills/devsecops/resources/compliance-automation.md +0 -530
  310. package/.claude/skills/devsecops/resources/compliance-frameworks.md +0 -2322
  311. package/.claude/skills/devsecops/resources/container-security.md +0 -915
  312. package/.claude/skills/devsecops/resources/cspm-integration.md +0 -1440
  313. package/.claude/skills/devsecops/resources/policy-enforcement.md +0 -619
  314. package/.claude/skills/devsecops/resources/secrets-management.md +0 -755
  315. package/.claude/skills/devsecops/resources/security-monitoring.md +0 -146
  316. package/.claude/skills/devsecops/resources/security-scanning.md +0 -887
  317. package/.claude/skills/devsecops/resources/security-testing.md +0 -203
  318. package/.claude/skills/devsecops/resources/supply-chain-security.md +0 -518
  319. package/.claude/skills/devsecops/resources/vulnerability-management.md +0 -481
  320. package/.claude/skills/devsecops/resources/zero-trust-architecture.md +0 -177
  321. package/.claude/skills/documentation-as-code/SKILL.md +0 -323
  322. package/.claude/skills/documentation-as-code/resources/api-documentation.md +0 -90
  323. package/.claude/skills/documentation-as-code/resources/changelog-management.md +0 -79
  324. package/.claude/skills/documentation-as-code/resources/diagram-generation.md +0 -44
  325. package/.claude/skills/documentation-as-code/resources/docs-as-code-workflow.md +0 -99
  326. package/.claude/skills/documentation-as-code/resources/documentation-automation.md +0 -68
  327. package/.claude/skills/documentation-as-code/resources/documentation-sites.md +0 -79
  328. package/.claude/skills/documentation-as-code/resources/markdown-best-practices.md +0 -162
  329. package/.claude/skills/documentation-as-code/resources/openapi-specification.md +0 -77
  330. package/.claude/skills/documentation-as-code/resources/readme-engineering.md +0 -60
  331. package/.claude/skills/documentation-as-code/resources/technical-writing-guide.md +0 -202
  332. package/.claude/skills/engineering-management/SKILL.md +0 -356
  333. package/.claude/skills/engineering-management/resources/career-ladders.md +0 -609
  334. package/.claude/skills/engineering-management/resources/hiring-and-assessment.md +0 -555
  335. package/.claude/skills/engineering-management/resources/one-on-one-guides.md +0 -609
  336. package/.claude/skills/engineering-management/resources/resource-planning.md +0 -557
  337. package/.claude/skills/engineering-management/resources/team-organization-patterns.md +0 -491
  338. package/.claude/skills/engineering-management/resources/technical-interviews.md +0 -474
  339. package/.claude/skills/engineering-operations-management/SKILL.md +0 -817
  340. package/.claude/skills/error-tracking/SKILL.md +0 -379
  341. package/.claude/skills/frontend-design/SKILL.md +0 -42
  342. package/.claude/skills/frontend-dev-guidelines/SKILL.md +0 -403
  343. package/.claude/skills/frontend-dev-guidelines/resources/common-patterns.md +0 -331
  344. package/.claude/skills/frontend-dev-guidelines/resources/complete-examples.md +0 -872
  345. package/.claude/skills/frontend-dev-guidelines/resources/component-patterns.md +0 -502
  346. package/.claude/skills/frontend-dev-guidelines/resources/data-fetching.md +0 -767
  347. package/.claude/skills/frontend-dev-guidelines/resources/file-organization.md +0 -502
  348. package/.claude/skills/frontend-dev-guidelines/resources/loading-and-error-states.md +0 -501
  349. package/.claude/skills/frontend-dev-guidelines/resources/performance.md +0 -406
  350. package/.claude/skills/frontend-dev-guidelines/resources/routing-guide.md +0 -364
  351. package/.claude/skills/frontend-dev-guidelines/resources/styling-guide.md +0 -428
  352. package/.claude/skills/frontend-dev-guidelines/resources/typescript-standards.md +0 -418
  353. package/.claude/skills/general-it-engineering/SKILL.md +0 -393
  354. package/.claude/skills/general-it-engineering/resources/asset-management.md +0 -712
  355. package/.claude/skills/general-it-engineering/resources/automation-orchestration.md +0 -817
  356. package/.claude/skills/general-it-engineering/resources/business-continuity.md +0 -786
  357. package/.claude/skills/general-it-engineering/resources/change-management.md +0 -715
  358. package/.claude/skills/general-it-engineering/resources/enterprise-monitoring.md +0 -729
  359. package/.claude/skills/general-it-engineering/resources/help-desk-operations.md +0 -738
  360. package/.claude/skills/general-it-engineering/resources/incident-service-management.md +0 -834
  361. package/.claude/skills/general-it-engineering/resources/it-governance.md +0 -753
  362. package/.claude/skills/general-it-engineering/resources/itil-framework.md +0 -503
  363. package/.claude/skills/general-it-engineering/resources/service-management.md +0 -669
  364. package/.claude/skills/infrastructure-architecture/SKILL.md +0 -328
  365. package/.claude/skills/infrastructure-architecture/resources/architecture-decision-records.md +0 -505
  366. package/.claude/skills/infrastructure-architecture/resources/architecture-patterns.md +0 -528
  367. package/.claude/skills/infrastructure-architecture/resources/capacity-planning.md +0 -453
  368. package/.claude/skills/infrastructure-architecture/resources/cleared-environment-architecture.md +0 -773
  369. package/.claude/skills/infrastructure-architecture/resources/cost-architecture.md +0 -499
  370. package/.claude/skills/infrastructure-architecture/resources/data-architecture.md +0 -501
  371. package/.claude/skills/infrastructure-architecture/resources/disaster-recovery.md +0 -535
  372. package/.claude/skills/infrastructure-architecture/resources/migration-architecture.md +0 -512
  373. package/.claude/skills/infrastructure-architecture/resources/multi-region-design.md +0 -608
  374. package/.claude/skills/infrastructure-architecture/resources/reference-architectures.md +0 -562
  375. package/.claude/skills/infrastructure-architecture/resources/security-architecture.md +0 -538
  376. package/.claude/skills/infrastructure-architecture/resources/system-design-principles.md +0 -489
  377. package/.claude/skills/infrastructure-architecture/resources/workload-classification.md +0 -1000
  378. package/.claude/skills/infrastructure-strategy/SKILL.md +0 -924
  379. package/.claude/skills/network-engineering/SKILL.md +0 -385
  380. package/.claude/skills/network-engineering/resources/dns-management.md +0 -738
  381. package/.claude/skills/network-engineering/resources/load-balancing.md +0 -820
  382. package/.claude/skills/network-engineering/resources/network-architecture.md +0 -546
  383. package/.claude/skills/network-engineering/resources/network-security.md +0 -921
  384. package/.claude/skills/network-engineering/resources/network-troubleshooting.md +0 -749
  385. package/.claude/skills/network-engineering/resources/routing-switching.md +0 -373
  386. package/.claude/skills/network-engineering/resources/sdn-networking.md +0 -695
  387. package/.claude/skills/network-engineering/resources/service-mesh-networking.md +0 -777
  388. package/.claude/skills/network-engineering/resources/tcp-ip-protocols.md +0 -444
  389. package/.claude/skills/network-engineering/resources/vpn-connectivity.md +0 -672
  390. package/.claude/skills/node-development/SKILL.md +0 -317
  391. package/.claude/skills/observability-engineering/SKILL.md +0 -101
  392. package/.claude/skills/observability-engineering/resources/apm-tools.md +0 -97
  393. package/.claude/skills/observability-engineering/resources/correlation-strategies.md +0 -87
  394. package/.claude/skills/observability-engineering/resources/distributed-tracing.md +0 -98
  395. package/.claude/skills/observability-engineering/resources/logs-aggregation.md +0 -118
  396. package/.claude/skills/observability-engineering/resources/observability-cost-optimization.md +0 -141
  397. package/.claude/skills/observability-engineering/resources/opentelemetry.md +0 -110
  398. package/.claude/skills/platform-engineering/SKILL.md +0 -555
  399. package/.claude/skills/platform-engineering/resources/architecture-overview.md +0 -600
  400. package/.claude/skills/platform-engineering/resources/container-orchestration.md +0 -916
  401. package/.claude/skills/platform-engineering/resources/cost-optimization.md +0 -634
  402. package/.claude/skills/platform-engineering/resources/developer-platforms.md +0 -670
  403. package/.claude/skills/platform-engineering/resources/gitops-automation.md +0 -650
  404. package/.claude/skills/platform-engineering/resources/infrastructure-as-code.md +0 -778
  405. package/.claude/skills/platform-engineering/resources/infrastructure-standards.md +0 -708
  406. package/.claude/skills/platform-engineering/resources/multi-tenancy.md +0 -602
  407. package/.claude/skills/platform-engineering/resources/platform-security.md +0 -711
  408. package/.claude/skills/platform-engineering/resources/resource-management.md +0 -592
  409. package/.claude/skills/platform-engineering/resources/service-mesh.md +0 -628
  410. package/.claude/skills/release-engineering/SKILL.md +0 -393
  411. package/.claude/skills/release-engineering/resources/artifact-management.md +0 -108
  412. package/.claude/skills/release-engineering/resources/build-optimization.md +0 -84
  413. package/.claude/skills/release-engineering/resources/ci-cd-pipelines.md +0 -411
  414. package/.claude/skills/release-engineering/resources/deployment-strategies.md +0 -197
  415. package/.claude/skills/release-engineering/resources/pipeline-security.md +0 -62
  416. package/.claude/skills/release-engineering/resources/progressive-delivery.md +0 -83
  417. package/.claude/skills/release-engineering/resources/release-automation.md +0 -68
  418. package/.claude/skills/release-engineering/resources/release-orchestration.md +0 -77
  419. package/.claude/skills/release-engineering/resources/rollback-strategies.md +0 -66
  420. package/.claude/skills/release-engineering/resources/versioning-strategies.md +0 -59
  421. package/.claude/skills/route-tester/SKILL.md +0 -392
  422. package/.claude/skills/skill-developer/ADVANCED.md +0 -197
  423. package/.claude/skills/skill-developer/HOOK_MECHANISMS.md +0 -306
  424. package/.claude/skills/skill-developer/PATTERNS_LIBRARY.md +0 -152
  425. package/.claude/skills/skill-developer/SKILL.md +0 -430
  426. package/.claude/skills/skill-developer/SKILL_RULES_REFERENCE.md +0 -315
  427. package/.claude/skills/skill-developer/TRIGGER_TYPES.md +0 -305
  428. package/.claude/skills/skill-developer/TROUBLESHOOTING.md +0 -514
  429. package/.claude/skills/skill-rules.json +0 -2989
  430. package/.claude/skills/sre/SKILL.md +0 -464
  431. package/.claude/skills/sre/resources/alerting-best-practices.md +0 -282
  432. package/.claude/skills/sre/resources/capacity-planning.md +0 -226
  433. package/.claude/skills/sre/resources/chaos-engineering.md +0 -193
  434. package/.claude/skills/sre/resources/disaster-recovery.md +0 -232
  435. package/.claude/skills/sre/resources/incident-management.md +0 -436
  436. package/.claude/skills/sre/resources/observability-stack.md +0 -240
  437. package/.claude/skills/sre/resources/on-call-runbooks.md +0 -167
  438. package/.claude/skills/sre/resources/performance-optimization.md +0 -108
  439. package/.claude/skills/sre/resources/reliability-patterns.md +0 -183
  440. package/.claude/skills/sre/resources/slo-sli-sla.md +0 -464
  441. package/.claude/skills/sre/resources/toil-reduction.md +0 -145
  442. package/.claude/skills/systems-engineering/SKILL.md +0 -648
  443. package/.claude/skills/systems-engineering/resources/automation-patterns.md +0 -771
  444. package/.claude/skills/systems-engineering/resources/configuration-management.md +0 -998
  445. package/.claude/skills/systems-engineering/resources/linux-administration.md +0 -672
  446. package/.claude/skills/systems-engineering/resources/networking-fundamentals.md +0 -982
  447. package/.claude/skills/systems-engineering/resources/performance-tuning.md +0 -871
  448. package/.claude/skills/systems-engineering/resources/powershell-scripting.md +0 -482
  449. package/.claude/skills/systems-engineering/resources/security-hardening.md +0 -739
  450. package/.claude/skills/systems-engineering/resources/shell-scripting.md +0 -915
  451. package/.claude/skills/systems-engineering/resources/storage-management.md +0 -628
  452. package/.claude/skills/systems-engineering/resources/system-monitoring.md +0 -787
  453. package/.claude/skills/systems-engineering/resources/troubleshooting-guide.md +0 -753
  454. package/.claude/skills/systems-engineering/resources/windows-administration.md +0 -738
  455. package/.claude/skills/technical-leadership/SKILL.md +0 -728
  456. package/backend/docs/SECRETS_DOCUMENTATION.md +0 -327
  457. package/backend/package-lock.json +0 -6801
  458. package/backend/src/core/node-registries/actions.js +0 -202
  459. package/backend/src/core/node-registries/arrays.js +0 -155
  460. package/backend/src/core/node-registries/bot.js +0 -23
  461. package/backend/src/core/node-registries/container.js +0 -162
  462. package/backend/src/core/node-registries/data.js +0 -290
  463. package/backend/src/core/node-registries/debug.js +0 -26
  464. package/backend/src/core/node-registries/events.js +0 -201
  465. package/backend/src/core/node-registries/flow.js +0 -139
  466. package/backend/src/core/node-registries/furnace.js +0 -143
  467. package/backend/src/core/node-registries/logic.js +0 -62
  468. package/backend/src/core/node-registries/math.js +0 -42
  469. package/backend/src/core/node-registries/navigation.js +0 -111
  470. package/backend/src/core/node-registries/objects.js +0 -98
  471. package/backend/src/core/node-registries/strings.js +0 -187
  472. package/backend/src/core/node-registries/time.js +0 -113
  473. package/backend/src/core/node-registries/type.js +0 -25
  474. package/backend/src/core/node-registries/users.js +0 -79
  475. package/frontend/dist/assets/index-BC-NbKXi.css +0 -32
  476. package/frontend/dist/assets/index-DqJXZMHY.js +0 -11266
@@ -1,789 +0,0 @@
1
- # Services and Repositories - Business Logic Layer
2
-
3
- Complete guide to organizing business logic with services and data access with repositories.
4
-
5
- ## Table of Contents
6
-
7
- - [Service Layer Overview](#service-layer-overview)
8
- - [Dependency Injection Pattern](#dependency-injection-pattern)
9
- - [Singleton Pattern](#singleton-pattern)
10
- - [Repository Pattern](#repository-pattern)
11
- - [Service Design Principles](#service-design-principles)
12
- - [Caching Strategies](#caching-strategies)
13
- - [Testing Services](#testing-services)
14
-
15
- ---
16
-
17
- ## Service Layer Overview
18
-
19
- ### Purpose of Services
20
-
21
- **Services contain business logic** - the 'what' and 'why' of your application:
22
-
23
- ```
24
- Controller asks: "Should I do this?"
25
- Service answers: "Yes/No, here's why, and here's what happens"
26
- Repository executes: "Here's the data you requested"
27
- ```
28
-
29
- **Services are responsible for:**
30
- - ✅ Business rules enforcement
31
- - ✅ Orchestrating multiple repositories
32
- - ✅ Transaction management
33
- - ✅ Complex calculations
34
- - ✅ External service integration
35
- - ✅ Business validations
36
-
37
- **Services should NOT:**
38
- - ❌ Know about HTTP (Request/Response)
39
- - ❌ Direct Prisma access (use repositories)
40
- - ❌ Handle route-specific logic
41
- - ❌ Format HTTP responses
42
-
43
- ---
44
-
45
- ## Dependency Injection Pattern
46
-
47
- ### Why Dependency Injection?
48
-
49
- **Benefits:**
50
- - Easy to test (inject mocks)
51
- - Clear dependencies
52
- - Flexible configuration
53
- - Promotes loose coupling
54
-
55
- ### Excellent Example: NotificationService
56
-
57
- **File:** `/blog-api/src/services/NotificationService.ts`
58
-
59
- ```typescript
60
- // Define dependencies interface for clarity
61
- export interface NotificationServiceDependencies {
62
- prisma: PrismaClient;
63
- batchingService: BatchingService;
64
- emailComposer: EmailComposer;
65
- }
66
-
67
- // Service with dependency injection
68
- export class NotificationService {
69
- private prisma: PrismaClient;
70
- private batchingService: BatchingService;
71
- private emailComposer: EmailComposer;
72
- private preferencesCache: Map<string, { preferences: UserPreference; timestamp: number }> = new Map();
73
- private CACHE_TTL = (notificationConfig.preferenceCacheTTLMinutes || 5) * 60 * 1000;
74
-
75
- // Dependencies injected via constructor
76
- constructor(dependencies: NotificationServiceDependencies) {
77
- this.prisma = dependencies.prisma;
78
- this.batchingService = dependencies.batchingService;
79
- this.emailComposer = dependencies.emailComposer;
80
- }
81
-
82
- /**
83
- * Create a notification and route it appropriately
84
- */
85
- async createNotification(params: CreateNotificationParams) {
86
- const { recipientID, type, title, message, link, context = {}, channel = 'both', priority = NotificationPriority.NORMAL } = params;
87
-
88
- try {
89
- // Get template and render content
90
- const template = getNotificationTemplate(type);
91
- const rendered = renderNotificationContent(template, context);
92
-
93
- // Create in-app notification record
94
- const notificationId = await createNotificationRecord({
95
- instanceId: parseInt(context.instanceId || '0', 10),
96
- template: type,
97
- recipientUserId: recipientID,
98
- channel: channel === 'email' ? 'email' : 'inApp',
99
- contextData: context,
100
- title: finalTitle,
101
- message: finalMessage,
102
- link: finalLink,
103
- });
104
-
105
- // Route notification based on channel
106
- if (channel === 'email' || channel === 'both') {
107
- await this.routeNotification({
108
- notificationId,
109
- userId: recipientID,
110
- type,
111
- priority,
112
- title: finalTitle,
113
- message: finalMessage,
114
- link: finalLink,
115
- context,
116
- });
117
- }
118
-
119
- return notification;
120
- } catch (error) {
121
- ErrorLogger.log(error, {
122
- context: {
123
- '[NotificationService] createNotification': {
124
- type: params.type,
125
- recipientID: params.recipientID,
126
- },
127
- },
128
- });
129
- throw error;
130
- }
131
- }
132
-
133
- /**
134
- * Route notification based on user preferences
135
- */
136
- private async routeNotification(params: { notificationId: number; userId: string; type: string; priority: NotificationPriority; title: string; message: string; link?: string; context?: Record<string, any> }) {
137
- // Get user preferences with caching
138
- const preferences = await this.getUserPreferences(params.userId);
139
-
140
- // Check if we should batch or send immediately
141
- if (this.shouldBatchEmail(preferences, params.type, params.priority)) {
142
- await this.batchingService.queueNotificationForBatch({
143
- notificationId: params.notificationId,
144
- userId: params.userId,
145
- userPreference: preferences,
146
- priority: params.priority,
147
- });
148
- } else {
149
- // Send immediately via EmailComposer
150
- await this.sendImmediateEmail({
151
- userId: params.userId,
152
- title: params.title,
153
- message: params.message,
154
- link: params.link,
155
- context: params.context,
156
- type: params.type,
157
- });
158
- }
159
- }
160
-
161
- /**
162
- * Determine if email should be batched
163
- */
164
- shouldBatchEmail(preferences: UserPreference, notificationType: string, priority: NotificationPriority): boolean {
165
- // HIGH priority always immediate
166
- if (priority === NotificationPriority.HIGH) {
167
- return false;
168
- }
169
-
170
- // Check batch mode
171
- const batchMode = preferences.emailBatchMode || BatchMode.IMMEDIATE;
172
- return batchMode !== BatchMode.IMMEDIATE;
173
- }
174
-
175
- /**
176
- * Get user preferences with caching
177
- */
178
- async getUserPreferences(userId: string): Promise<UserPreference> {
179
- // Check cache first
180
- const cached = this.preferencesCache.get(userId);
181
- if (cached && Date.now() - cached.timestamp < this.CACHE_TTL) {
182
- return cached.preferences;
183
- }
184
-
185
- const preference = await this.prisma.userPreference.findUnique({
186
- where: { userID: userId },
187
- });
188
-
189
- const finalPreferences = preference || DEFAULT_PREFERENCES;
190
-
191
- // Update cache
192
- this.preferencesCache.set(userId, {
193
- preferences: finalPreferences,
194
- timestamp: Date.now(),
195
- });
196
-
197
- return finalPreferences;
198
- }
199
- }
200
- ```
201
-
202
- **Usage in Controller:**
203
-
204
- ```typescript
205
- // Instantiate with dependencies
206
- const notificationService = new NotificationService({
207
- prisma: PrismaService.main,
208
- batchingService: new BatchingService(PrismaService.main),
209
- emailComposer: new EmailComposer(),
210
- });
211
-
212
- // Use in controller
213
- const notification = await notificationService.createNotification({
214
- recipientID: 'user-123',
215
- type: 'AFRLWorkflowNotification',
216
- context: { workflowName: 'AFRL Monthly Report' },
217
- });
218
- ```
219
-
220
- **Key Takeaways:**
221
- - Dependencies passed via constructor
222
- - Clear interface defines required dependencies
223
- - Easy to test (inject mocks)
224
- - Encapsulated caching logic
225
- - Business rules isolated from HTTP
226
-
227
- ---
228
-
229
- ## Singleton Pattern
230
-
231
- ### When to Use Singletons
232
-
233
- **Use for:**
234
- - Services with expensive initialization
235
- - Services with shared state (caching)
236
- - Services accessed from many places
237
- - Permission services
238
- - Configuration services
239
-
240
- ### Example: PermissionService (Singleton)
241
-
242
- **File:** `/blog-api/src/services/permissionService.ts`
243
-
244
- ```typescript
245
- import { PrismaClient } from '@prisma/client';
246
-
247
- class PermissionService {
248
- private static instance: PermissionService;
249
- private prisma: PrismaClient;
250
- private permissionCache: Map<string, { canAccess: boolean; timestamp: number }> = new Map();
251
- private CACHE_TTL = 5 * 60 * 1000; // 5 minutes
252
-
253
- // Private constructor prevents direct instantiation
254
- private constructor() {
255
- this.prisma = PrismaService.main;
256
- }
257
-
258
- // Get singleton instance
259
- public static getInstance(): PermissionService {
260
- if (!PermissionService.instance) {
261
- PermissionService.instance = new PermissionService();
262
- }
263
- return PermissionService.instance;
264
- }
265
-
266
- /**
267
- * Check if user can complete a workflow step
268
- */
269
- async canCompleteStep(userId: string, stepInstanceId: number): Promise<boolean> {
270
- const cacheKey = `${userId}:${stepInstanceId}`;
271
-
272
- // Check cache
273
- const cached = this.permissionCache.get(cacheKey);
274
- if (cached && Date.now() - cached.timestamp < this.CACHE_TTL) {
275
- return cached.canAccess;
276
- }
277
-
278
- try {
279
- const post = await this.prisma.post.findUnique({
280
- where: { id: postId },
281
- include: {
282
- author: true,
283
- comments: {
284
- include: {
285
- user: true,
286
- },
287
- },
288
- },
289
- });
290
-
291
- if (!post) {
292
- return false;
293
- }
294
-
295
- // Check if user has permission
296
- const canEdit = post.authorId === userId ||
297
- await this.isUserAdmin(userId);
298
-
299
- // Cache result
300
- this.permissionCache.set(cacheKey, {
301
- canAccess: isAssigned,
302
- timestamp: Date.now(),
303
- });
304
-
305
- return isAssigned;
306
- } catch (error) {
307
- console.error('[PermissionService] Error checking step permission:', error);
308
- return false;
309
- }
310
- }
311
-
312
- /**
313
- * Clear cache for user
314
- */
315
- clearUserCache(userId: string): void {
316
- for (const [key] of this.permissionCache) {
317
- if (key.startsWith(`${userId}:`)) {
318
- this.permissionCache.delete(key);
319
- }
320
- }
321
- }
322
-
323
- /**
324
- * Clear all cache
325
- */
326
- clearCache(): void {
327
- this.permissionCache.clear();
328
- }
329
- }
330
-
331
- // Export singleton instance
332
- export const permissionService = PermissionService.getInstance();
333
- ```
334
-
335
- **Usage:**
336
-
337
- ```typescript
338
- import { permissionService } from '../services/permissionService';
339
-
340
- // Use anywhere in the codebase
341
- const canComplete = await permissionService.canCompleteStep(userId, stepId);
342
-
343
- if (!canComplete) {
344
- throw new ForbiddenError('You do not have permission to complete this step');
345
- }
346
- ```
347
-
348
- ---
349
-
350
- ## Repository Pattern
351
-
352
- ### Purpose of Repositories
353
-
354
- **Repositories abstract data access** - the 'how' of data operations:
355
-
356
- ```
357
- Service: "Get me all active users sorted by name"
358
- Repository: "Here's the Prisma query that does that"
359
- ```
360
-
361
- **Repositories are responsible for:**
362
- - ✅ All Prisma operations
363
- - ✅ Query construction
364
- - ✅ Query optimization (select, include)
365
- - ✅ Database error handling
366
- - ✅ Caching database results
367
-
368
- **Repositories should NOT:**
369
- - ❌ Contain business logic
370
- - ❌ Know about HTTP
371
- - ❌ Make decisions (that's service layer)
372
-
373
- ### Repository Template
374
-
375
- ```typescript
376
- // repositories/UserRepository.ts
377
- import { PrismaService } from '@project-lifecycle-portal/database';
378
- import type { User, Prisma } from '@project-lifecycle-portal/database';
379
-
380
- export class UserRepository {
381
- /**
382
- * Find user by ID with optimized query
383
- */
384
- async findById(userId: string): Promise<User | null> {
385
- try {
386
- return await PrismaService.main.user.findUnique({
387
- where: { userID: userId },
388
- select: {
389
- userID: true,
390
- email: true,
391
- name: true,
392
- isActive: true,
393
- roles: true,
394
- createdAt: true,
395
- updatedAt: true,
396
- },
397
- });
398
- } catch (error) {
399
- console.error('[UserRepository] Error finding user by ID:', error);
400
- throw new Error(`Failed to find user: ${userId}`);
401
- }
402
- }
403
-
404
- /**
405
- * Find all active users
406
- */
407
- async findActive(options?: { orderBy?: Prisma.UserOrderByWithRelationInput }): Promise<User[]> {
408
- try {
409
- return await PrismaService.main.user.findMany({
410
- where: { isActive: true },
411
- orderBy: options?.orderBy || { name: 'asc' },
412
- select: {
413
- userID: true,
414
- email: true,
415
- name: true,
416
- roles: true,
417
- },
418
- });
419
- } catch (error) {
420
- console.error('[UserRepository] Error finding active users:', error);
421
- throw new Error('Failed to find active users');
422
- }
423
- }
424
-
425
- /**
426
- * Find user by email
427
- */
428
- async findByEmail(email: string): Promise<User | null> {
429
- try {
430
- return await PrismaService.main.user.findUnique({
431
- where: { email },
432
- });
433
- } catch (error) {
434
- console.error('[UserRepository] Error finding user by email:', error);
435
- throw new Error(`Failed to find user with email: ${email}`);
436
- }
437
- }
438
-
439
- /**
440
- * Create new user
441
- */
442
- async create(data: Prisma.UserCreateInput): Promise<User> {
443
- try {
444
- return await PrismaService.main.user.create({ data });
445
- } catch (error) {
446
- console.error('[UserRepository] Error creating user:', error);
447
- throw new Error('Failed to create user');
448
- }
449
- }
450
-
451
- /**
452
- * Update user
453
- */
454
- async update(userId: string, data: Prisma.UserUpdateInput): Promise<User> {
455
- try {
456
- return await PrismaService.main.user.update({
457
- where: { userID: userId },
458
- data,
459
- });
460
- } catch (error) {
461
- console.error('[UserRepository] Error updating user:', error);
462
- throw new Error(`Failed to update user: ${userId}`);
463
- }
464
- }
465
-
466
- /**
467
- * Delete user (soft delete by setting isActive = false)
468
- */
469
- async delete(userId: string): Promise<User> {
470
- try {
471
- return await PrismaService.main.user.update({
472
- where: { userID: userId },
473
- data: { isActive: false },
474
- });
475
- } catch (error) {
476
- console.error('[UserRepository] Error deleting user:', error);
477
- throw new Error(`Failed to delete user: ${userId}`);
478
- }
479
- }
480
-
481
- /**
482
- * Check if email exists
483
- */
484
- async emailExists(email: string): Promise<boolean> {
485
- try {
486
- const count = await PrismaService.main.user.count({
487
- where: { email },
488
- });
489
- return count > 0;
490
- } catch (error) {
491
- console.error('[UserRepository] Error checking email exists:', error);
492
- throw new Error('Failed to check if email exists');
493
- }
494
- }
495
- }
496
-
497
- // Export singleton instance
498
- export const userRepository = new UserRepository();
499
- ```
500
-
501
- **Using Repository in Service:**
502
-
503
- ```typescript
504
- // services/userService.ts
505
- import { userRepository } from '../repositories/UserRepository';
506
- import { ConflictError, NotFoundError } from '../utils/errors';
507
-
508
- export class UserService {
509
- /**
510
- * Create new user with business rules
511
- */
512
- async createUser(data: { email: string; name: string; roles: string[] }): Promise<User> {
513
- // Business rule: Check if email already exists
514
- const emailExists = await userRepository.emailExists(data.email);
515
- if (emailExists) {
516
- throw new ConflictError('Email already exists');
517
- }
518
-
519
- // Business rule: Validate roles
520
- const validRoles = ['admin', 'operations', 'user'];
521
- const invalidRoles = data.roles.filter((role) => !validRoles.includes(role));
522
- if (invalidRoles.length > 0) {
523
- throw new ValidationError(`Invalid roles: ${invalidRoles.join(', ')}`);
524
- }
525
-
526
- // Create user via repository
527
- return await userRepository.create({
528
- email: data.email,
529
- name: data.name,
530
- roles: data.roles,
531
- isActive: true,
532
- });
533
- }
534
-
535
- /**
536
- * Get user by ID
537
- */
538
- async getUser(userId: string): Promise<User> {
539
- const user = await userRepository.findById(userId);
540
-
541
- if (!user) {
542
- throw new NotFoundError(`User not found: ${userId}`);
543
- }
544
-
545
- return user;
546
- }
547
- }
548
- ```
549
-
550
- ---
551
-
552
- ## Service Design Principles
553
-
554
- ### 1. Single Responsibility
555
-
556
- Each service should have ONE clear purpose:
557
-
558
- ```typescript
559
- // ✅ GOOD - Single responsibility
560
- class UserService {
561
- async createUser() {}
562
- async updateUser() {}
563
- async deleteUser() {}
564
- }
565
-
566
- class EmailService {
567
- async sendEmail() {}
568
- async sendBulkEmails() {}
569
- }
570
-
571
- // ❌ BAD - Too many responsibilities
572
- class UserService {
573
- async createUser() {}
574
- async sendWelcomeEmail() {} // Should be EmailService
575
- async logUserActivity() {} // Should be AuditService
576
- async processPayment() {} // Should be PaymentService
577
- }
578
- ```
579
-
580
- ### 2. Clear Method Names
581
-
582
- Method names should describe WHAT they do:
583
-
584
- ```typescript
585
- // ✅ GOOD - Clear intent
586
- async createNotification()
587
- async getUserPreferences()
588
- async shouldBatchEmail()
589
- async routeNotification()
590
-
591
- // ❌ BAD - Vague or misleading
592
- async process()
593
- async handle()
594
- async doIt()
595
- async execute()
596
- ```
597
-
598
- ### 3. Return Types
599
-
600
- Always use explicit return types:
601
-
602
- ```typescript
603
- // ✅ GOOD - Explicit types
604
- async createUser(data: CreateUserDTO): Promise<User> {}
605
- async findUsers(): Promise<User[]> {}
606
- async deleteUser(id: string): Promise<void> {}
607
-
608
- // ❌ BAD - Implicit any
609
- async createUser(data) {} // No types!
610
- ```
611
-
612
- ### 4. Error Handling
613
-
614
- Services should throw meaningful errors:
615
-
616
- ```typescript
617
- // ✅ GOOD - Meaningful errors
618
- if (!user) {
619
- throw new NotFoundError(`User not found: ${userId}`);
620
- }
621
-
622
- if (emailExists) {
623
- throw new ConflictError('Email already exists');
624
- }
625
-
626
- // ❌ BAD - Generic errors
627
- if (!user) {
628
- throw new Error('Error'); // What error?
629
- }
630
- ```
631
-
632
- ### 5. Avoid God Services
633
-
634
- Don't create services that do everything:
635
-
636
- ```typescript
637
- // ❌ BAD - God service
638
- class WorkflowService {
639
- async startWorkflow() {}
640
- async completeStep() {}
641
- async assignRoles() {}
642
- async sendNotifications() {} // Should be NotificationService
643
- async validatePermissions() {} // Should be PermissionService
644
- async logAuditTrail() {} // Should be AuditService
645
- // ... 50 more methods
646
- }
647
-
648
- // ✅ GOOD - Focused services
649
- class WorkflowService {
650
- constructor(
651
- private notificationService: NotificationService,
652
- private permissionService: PermissionService,
653
- private auditService: AuditService
654
- ) {}
655
-
656
- async startWorkflow() {
657
- // Orchestrate other services
658
- await this.permissionService.checkPermission();
659
- await this.workflowRepository.create();
660
- await this.notificationService.notify();
661
- await this.auditService.log();
662
- }
663
- }
664
- ```
665
-
666
- ---
667
-
668
- ## Caching Strategies
669
-
670
- ### 1. In-Memory Caching
671
-
672
- ```typescript
673
- class UserService {
674
- private cache: Map<string, { user: User; timestamp: number }> = new Map();
675
- private CACHE_TTL = 5 * 60 * 1000; // 5 minutes
676
-
677
- async getUser(userId: string): Promise<User> {
678
- // Check cache
679
- const cached = this.cache.get(userId);
680
- if (cached && Date.now() - cached.timestamp < this.CACHE_TTL) {
681
- return cached.user;
682
- }
683
-
684
- // Fetch from database
685
- const user = await userRepository.findById(userId);
686
-
687
- // Update cache
688
- if (user) {
689
- this.cache.set(userId, { user, timestamp: Date.now() });
690
- }
691
-
692
- return user;
693
- }
694
-
695
- clearUserCache(userId: string): void {
696
- this.cache.delete(userId);
697
- }
698
- }
699
- ```
700
-
701
- ### 2. Cache Invalidation
702
-
703
- ```typescript
704
- class UserService {
705
- async updateUser(userId: string, data: UpdateUserDTO): Promise<User> {
706
- // Update in database
707
- const user = await userRepository.update(userId, data);
708
-
709
- // Invalidate cache
710
- this.clearUserCache(userId);
711
-
712
- return user;
713
- }
714
- }
715
- ```
716
-
717
- ---
718
-
719
- ## Testing Services
720
-
721
- ### Unit Tests
722
-
723
- ```typescript
724
- // tests/userService.test.ts
725
- import { UserService } from '../services/userService';
726
- import { userRepository } from '../repositories/UserRepository';
727
- import { ConflictError } from '../utils/errors';
728
-
729
- // Mock repository
730
- jest.mock('../repositories/UserRepository');
731
-
732
- describe('UserService', () => {
733
- let userService: UserService;
734
-
735
- beforeEach(() => {
736
- userService = new UserService();
737
- jest.clearAllMocks();
738
- });
739
-
740
- describe('createUser', () => {
741
- it('should create user when email does not exist', async () => {
742
- // Arrange
743
- const userData = {
744
- email: 'test@example.com',
745
- name: 'Test User',
746
- roles: ['user'],
747
- };
748
-
749
- (userRepository.emailExists as jest.Mock).mockResolvedValue(false);
750
- (userRepository.create as jest.Mock).mockResolvedValue({
751
- userID: '123',
752
- ...userData,
753
- });
754
-
755
- // Act
756
- const user = await userService.createUser(userData);
757
-
758
- // Assert
759
- expect(user).toBeDefined();
760
- expect(user.email).toBe(userData.email);
761
- expect(userRepository.emailExists).toHaveBeenCalledWith(userData.email);
762
- expect(userRepository.create).toHaveBeenCalled();
763
- });
764
-
765
- it('should throw ConflictError when email exists', async () => {
766
- // Arrange
767
- const userData = {
768
- email: 'existing@example.com',
769
- name: 'Test User',
770
- roles: ['user'],
771
- };
772
-
773
- (userRepository.emailExists as jest.Mock).mockResolvedValue(true);
774
-
775
- // Act & Assert
776
- await expect(userService.createUser(userData)).rejects.toThrow(ConflictError);
777
- expect(userRepository.create).not.toHaveBeenCalled();
778
- });
779
- });
780
- });
781
- ```
782
-
783
- ---
784
-
785
- **Related Files:**
786
- - [SKILL.md](SKILL.md) - Main guide
787
- - [routing-and-controllers.md](routing-and-controllers.md) - Controllers that use services
788
- - [database-patterns.md](database-patterns.md) - Prisma and repository patterns
789
- - [complete-examples.md](complete-examples.md) - Full service/repository examples