javi-forge 0.1.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 (500) hide show
  1. package/.gitignore.template +105 -0
  2. package/.releaserc +44 -0
  3. package/README.md +45 -0
  4. package/ai-config/.skillignore +15 -0
  5. package/ai-config/AUTO_INVOKE.md +300 -0
  6. package/ai-config/agents/_TEMPLATE.md +93 -0
  7. package/ai-config/agents/business/api-designer.md +1657 -0
  8. package/ai-config/agents/business/business-analyst.md +1331 -0
  9. package/ai-config/agents/business/product-strategist.md +206 -0
  10. package/ai-config/agents/business/project-manager.md +178 -0
  11. package/ai-config/agents/business/requirements-analyst.md +1277 -0
  12. package/ai-config/agents/business/technical-writer.md +1679 -0
  13. package/ai-config/agents/creative/ux-designer.md +205 -0
  14. package/ai-config/agents/data-ai/ai-engineer.md +487 -0
  15. package/ai-config/agents/data-ai/analytics-engineer.md +953 -0
  16. package/ai-config/agents/data-ai/data-engineer.md +173 -0
  17. package/ai-config/agents/data-ai/data-scientist.md +672 -0
  18. package/ai-config/agents/data-ai/mlops-engineer.md +814 -0
  19. package/ai-config/agents/data-ai/prompt-engineer.md +772 -0
  20. package/ai-config/agents/development/angular-expert.md +620 -0
  21. package/ai-config/agents/development/backend-architect.md +795 -0
  22. package/ai-config/agents/development/database-specialist.md +212 -0
  23. package/ai-config/agents/development/frontend-specialist.md +686 -0
  24. package/ai-config/agents/development/fullstack-engineer.md +668 -0
  25. package/ai-config/agents/development/golang-pro.md +338 -0
  26. package/ai-config/agents/development/java-enterprise.md +400 -0
  27. package/ai-config/agents/development/javascript-pro.md +422 -0
  28. package/ai-config/agents/development/nextjs-pro.md +474 -0
  29. package/ai-config/agents/development/python-pro.md +570 -0
  30. package/ai-config/agents/development/react-pro.md +487 -0
  31. package/ai-config/agents/development/rust-pro.md +246 -0
  32. package/ai-config/agents/development/spring-boot-4-expert.md +326 -0
  33. package/ai-config/agents/development/typescript-pro.md +336 -0
  34. package/ai-config/agents/development/vue-specialist.md +605 -0
  35. package/ai-config/agents/infrastructure/cloud-architect.md +472 -0
  36. package/ai-config/agents/infrastructure/deployment-manager.md +358 -0
  37. package/ai-config/agents/infrastructure/devops-engineer.md +455 -0
  38. package/ai-config/agents/infrastructure/incident-responder.md +519 -0
  39. package/ai-config/agents/infrastructure/kubernetes-expert.md +705 -0
  40. package/ai-config/agents/infrastructure/monitoring-specialist.md +674 -0
  41. package/ai-config/agents/infrastructure/performance-engineer.md +658 -0
  42. package/ai-config/agents/orchestrator.md +241 -0
  43. package/ai-config/agents/quality/accessibility-auditor.md +1204 -0
  44. package/ai-config/agents/quality/code-reviewer-compact.md +123 -0
  45. package/ai-config/agents/quality/code-reviewer.md +363 -0
  46. package/ai-config/agents/quality/dependency-manager.md +743 -0
  47. package/ai-config/agents/quality/e2e-test-specialist.md +1005 -0
  48. package/ai-config/agents/quality/performance-tester.md +1086 -0
  49. package/ai-config/agents/quality/security-auditor.md +133 -0
  50. package/ai-config/agents/quality/test-engineer.md +453 -0
  51. package/ai-config/agents/specialists/api-designer.md +87 -0
  52. package/ai-config/agents/specialists/backend-architect.md +73 -0
  53. package/ai-config/agents/specialists/code-reviewer.md +77 -0
  54. package/ai-config/agents/specialists/db-optimizer.md +75 -0
  55. package/ai-config/agents/specialists/devops-engineer.md +83 -0
  56. package/ai-config/agents/specialists/documentation-writer.md +78 -0
  57. package/ai-config/agents/specialists/frontend-developer.md +75 -0
  58. package/ai-config/agents/specialists/performance-analyst.md +82 -0
  59. package/ai-config/agents/specialists/refactor-specialist.md +74 -0
  60. package/ai-config/agents/specialists/security-auditor.md +74 -0
  61. package/ai-config/agents/specialists/test-engineer.md +81 -0
  62. package/ai-config/agents/specialists/ux-consultant.md +76 -0
  63. package/ai-config/agents/specialized/agent-generator.md +1190 -0
  64. package/ai-config/agents/specialized/blockchain-developer.md +149 -0
  65. package/ai-config/agents/specialized/code-migrator.md +892 -0
  66. package/ai-config/agents/specialized/context-manager.md +978 -0
  67. package/ai-config/agents/specialized/documentation-writer.md +1078 -0
  68. package/ai-config/agents/specialized/ecommerce-expert.md +1756 -0
  69. package/ai-config/agents/specialized/embedded-engineer.md +1714 -0
  70. package/ai-config/agents/specialized/error-detective.md +1034 -0
  71. package/ai-config/agents/specialized/fintech-specialist.md +1659 -0
  72. package/ai-config/agents/specialized/freelance-project-planner-v2.md +1988 -0
  73. package/ai-config/agents/specialized/freelance-project-planner-v3.md +2136 -0
  74. package/ai-config/agents/specialized/freelance-project-planner-v4.md +4503 -0
  75. package/ai-config/agents/specialized/freelance-project-planner.md +722 -0
  76. package/ai-config/agents/specialized/game-developer.md +1963 -0
  77. package/ai-config/agents/specialized/healthcare-dev.md +1620 -0
  78. package/ai-config/agents/specialized/mobile-developer.md +188 -0
  79. package/ai-config/agents/specialized/parallel-plan-executor.md +506 -0
  80. package/ai-config/agents/specialized/plan-executor.md +485 -0
  81. package/ai-config/agents/specialized/solo-dev-planner-modular/00-INDEX.md +485 -0
  82. package/ai-config/agents/specialized/solo-dev-planner-modular/01-CORE.md +3493 -0
  83. package/ai-config/agents/specialized/solo-dev-planner-modular/02-SELF-CORRECTION.md +778 -0
  84. package/ai-config/agents/specialized/solo-dev-planner-modular/03-PROGRESSIVE-SETUP.md +918 -0
  85. package/ai-config/agents/specialized/solo-dev-planner-modular/04-DEPLOYMENT.md +1537 -0
  86. package/ai-config/agents/specialized/solo-dev-planner-modular/05-TESTING.md +2633 -0
  87. package/ai-config/agents/specialized/solo-dev-planner-modular/06-OPERATIONS.md +5610 -0
  88. package/ai-config/agents/specialized/solo-dev-planner-modular/INSTALL.md +335 -0
  89. package/ai-config/agents/specialized/solo-dev-planner-modular/QUICK-REFERENCE.txt +215 -0
  90. package/ai-config/agents/specialized/solo-dev-planner-modular/README.md +260 -0
  91. package/ai-config/agents/specialized/solo-dev-planner-modular/START-HERE.md +379 -0
  92. package/ai-config/agents/specialized/solo-dev-planner-modular/WORKFLOW-DIAGRAM.md +355 -0
  93. package/ai-config/agents/specialized/solo-dev-planner-modular/solo-dev-planner.md +279 -0
  94. package/ai-config/agents/specialized/template-writer.md +347 -0
  95. package/ai-config/agents/specialized/test-runner.md +99 -0
  96. package/ai-config/agents/specialized/vibekanban-smart-worker.md +244 -0
  97. package/ai-config/agents/specialized/wave-executor.md +138 -0
  98. package/ai-config/agents/specialized/workflow-optimizer.md +1114 -0
  99. package/ai-config/commands/git/changelog.md +32 -0
  100. package/ai-config/commands/git/ci-local.md +70 -0
  101. package/ai-config/commands/git/commit.md +35 -0
  102. package/ai-config/commands/git/fix-issue.md +23 -0
  103. package/ai-config/commands/git/pr-create.md +42 -0
  104. package/ai-config/commands/git/pr-review.md +50 -0
  105. package/ai-config/commands/git/worktree.md +39 -0
  106. package/ai-config/commands/refactoring/cleanup.md +24 -0
  107. package/ai-config/commands/refactoring/dead-code.md +40 -0
  108. package/ai-config/commands/refactoring/extract.md +31 -0
  109. package/ai-config/commands/testing/e2e.md +30 -0
  110. package/ai-config/commands/testing/tdd.md +36 -0
  111. package/ai-config/commands/testing/test-coverage.md +30 -0
  112. package/ai-config/commands/testing/test-fix.md +24 -0
  113. package/ai-config/commands/workflow/generate-agents-md.md +85 -0
  114. package/ai-config/commands/workflow/planning.md +47 -0
  115. package/ai-config/commands/workflows/compound.md +89 -0
  116. package/ai-config/commands/workflows/plan.md +77 -0
  117. package/ai-config/commands/workflows/review.md +78 -0
  118. package/ai-config/commands/workflows/work.md +75 -0
  119. package/ai-config/config.yaml +18 -0
  120. package/ai-config/hooks/_TEMPLATE.md +96 -0
  121. package/ai-config/hooks/block-dangerous-commands.md +75 -0
  122. package/ai-config/hooks/commit-guard.md +90 -0
  123. package/ai-config/hooks/context-loader.md +73 -0
  124. package/ai-config/hooks/improve-prompt.md +91 -0
  125. package/ai-config/hooks/learning-log.md +72 -0
  126. package/ai-config/hooks/model-router.md +86 -0
  127. package/ai-config/hooks/secret-scanner.md +64 -0
  128. package/ai-config/hooks/skill-validator.md +102 -0
  129. package/ai-config/hooks/task-artifact.md +114 -0
  130. package/ai-config/hooks/validate-workflow.md +100 -0
  131. package/ai-config/prompts/base.md +71 -0
  132. package/ai-config/prompts/modes/debug.md +34 -0
  133. package/ai-config/prompts/modes/deploy.md +40 -0
  134. package/ai-config/prompts/modes/research.md +32 -0
  135. package/ai-config/prompts/modes/review.md +33 -0
  136. package/ai-config/prompts/review-policy.md +79 -0
  137. package/ai-config/skills/_TEMPLATE.md +157 -0
  138. package/ai-config/skills/backend/api-gateway/SKILL.md +254 -0
  139. package/ai-config/skills/backend/bff-concepts/SKILL.md +239 -0
  140. package/ai-config/skills/backend/bff-spring/SKILL.md +364 -0
  141. package/ai-config/skills/backend/chi-router/SKILL.md +396 -0
  142. package/ai-config/skills/backend/error-handling/SKILL.md +255 -0
  143. package/ai-config/skills/backend/exceptions-spring/SKILL.md +323 -0
  144. package/ai-config/skills/backend/fastapi/SKILL.md +302 -0
  145. package/ai-config/skills/backend/gateway-spring/SKILL.md +390 -0
  146. package/ai-config/skills/backend/go-backend/SKILL.md +457 -0
  147. package/ai-config/skills/backend/gradle-multimodule/SKILL.md +274 -0
  148. package/ai-config/skills/backend/graphql-concepts/SKILL.md +352 -0
  149. package/ai-config/skills/backend/graphql-spring/SKILL.md +398 -0
  150. package/ai-config/skills/backend/grpc-concepts/SKILL.md +283 -0
  151. package/ai-config/skills/backend/grpc-spring/SKILL.md +445 -0
  152. package/ai-config/skills/backend/jwt-auth/SKILL.md +412 -0
  153. package/ai-config/skills/backend/notifications-concepts/SKILL.md +259 -0
  154. package/ai-config/skills/backend/recommendations-concepts/SKILL.md +261 -0
  155. package/ai-config/skills/backend/search-concepts/SKILL.md +263 -0
  156. package/ai-config/skills/backend/search-spring/SKILL.md +375 -0
  157. package/ai-config/skills/backend/spring-boot-4/SKILL.md +172 -0
  158. package/ai-config/skills/backend/websockets/SKILL.md +532 -0
  159. package/ai-config/skills/data-ai/ai-ml/SKILL.md +423 -0
  160. package/ai-config/skills/data-ai/analytics-concepts/SKILL.md +195 -0
  161. package/ai-config/skills/data-ai/analytics-spring/SKILL.md +340 -0
  162. package/ai-config/skills/data-ai/duckdb-analytics/SKILL.md +440 -0
  163. package/ai-config/skills/data-ai/langchain/SKILL.md +238 -0
  164. package/ai-config/skills/data-ai/mlflow/SKILL.md +302 -0
  165. package/ai-config/skills/data-ai/onnx-inference/SKILL.md +290 -0
  166. package/ai-config/skills/data-ai/powerbi/SKILL.md +352 -0
  167. package/ai-config/skills/data-ai/pytorch/SKILL.md +274 -0
  168. package/ai-config/skills/data-ai/scikit-learn/SKILL.md +321 -0
  169. package/ai-config/skills/data-ai/vector-db/SKILL.md +301 -0
  170. package/ai-config/skills/database/graph-databases/SKILL.md +218 -0
  171. package/ai-config/skills/database/graph-spring/SKILL.md +361 -0
  172. package/ai-config/skills/database/pgx-postgres/SKILL.md +512 -0
  173. package/ai-config/skills/database/redis-cache/SKILL.md +343 -0
  174. package/ai-config/skills/database/sqlite-embedded/SKILL.md +388 -0
  175. package/ai-config/skills/database/timescaledb/SKILL.md +320 -0
  176. package/ai-config/skills/docs/api-documentation/SKILL.md +293 -0
  177. package/ai-config/skills/docs/docs-spring/SKILL.md +377 -0
  178. package/ai-config/skills/docs/mustache-templates/SKILL.md +190 -0
  179. package/ai-config/skills/docs/technical-docs/SKILL.md +447 -0
  180. package/ai-config/skills/frontend/astro-ssr/SKILL.md +441 -0
  181. package/ai-config/skills/frontend/frontend-design/SKILL.md +54 -0
  182. package/ai-config/skills/frontend/frontend-web/SKILL.md +368 -0
  183. package/ai-config/skills/frontend/mantine-ui/SKILL.md +396 -0
  184. package/ai-config/skills/frontend/tanstack-query/SKILL.md +439 -0
  185. package/ai-config/skills/frontend/zod-validation/SKILL.md +417 -0
  186. package/ai-config/skills/frontend/zustand-state/SKILL.md +350 -0
  187. package/ai-config/skills/infrastructure/chaos-engineering/SKILL.md +244 -0
  188. package/ai-config/skills/infrastructure/chaos-spring/SKILL.md +378 -0
  189. package/ai-config/skills/infrastructure/devops-infra/SKILL.md +435 -0
  190. package/ai-config/skills/infrastructure/docker-containers/SKILL.md +420 -0
  191. package/ai-config/skills/infrastructure/kubernetes/SKILL.md +456 -0
  192. package/ai-config/skills/infrastructure/opentelemetry/SKILL.md +546 -0
  193. package/ai-config/skills/infrastructure/traefik-proxy/SKILL.md +474 -0
  194. package/ai-config/skills/infrastructure/woodpecker-ci/SKILL.md +315 -0
  195. package/ai-config/skills/mobile/ionic-capacitor/SKILL.md +504 -0
  196. package/ai-config/skills/mobile/mobile-ionic/SKILL.md +448 -0
  197. package/ai-config/skills/prompt-improver/SKILL.md +125 -0
  198. package/ai-config/skills/quality/ghagga-review/SKILL.md +216 -0
  199. package/ai-config/skills/references/hooks-patterns/SKILL.md +238 -0
  200. package/ai-config/skills/references/mcp-servers/SKILL.md +275 -0
  201. package/ai-config/skills/references/plugins-reference/SKILL.md +110 -0
  202. package/ai-config/skills/references/skills-reference/SKILL.md +420 -0
  203. package/ai-config/skills/references/subagent-templates/SKILL.md +193 -0
  204. package/ai-config/skills/systems-iot/modbus-protocol/SKILL.md +410 -0
  205. package/ai-config/skills/systems-iot/mqtt-rumqttc/SKILL.md +408 -0
  206. package/ai-config/skills/systems-iot/rust-systems/SKILL.md +386 -0
  207. package/ai-config/skills/systems-iot/tokio-async/SKILL.md +324 -0
  208. package/ai-config/skills/testing/playwright-e2e/SKILL.md +289 -0
  209. package/ai-config/skills/testing/testcontainers/SKILL.md +299 -0
  210. package/ai-config/skills/testing/vitest-testing/SKILL.md +381 -0
  211. package/ai-config/skills/workflow/ci-local-guide/SKILL.md +118 -0
  212. package/ai-config/skills/workflow/claude-automation-recommender/SKILL.md +299 -0
  213. package/ai-config/skills/workflow/claude-md-improver/SKILL.md +158 -0
  214. package/ai-config/skills/workflow/finishing-a-development-branch/SKILL.md +117 -0
  215. package/ai-config/skills/workflow/git-github/SKILL.md +334 -0
  216. package/ai-config/skills/workflow/git-github/references/examples.md +160 -0
  217. package/ai-config/skills/workflow/git-workflow/SKILL.md +214 -0
  218. package/ai-config/skills/workflow/ide-plugins/SKILL.md +277 -0
  219. package/ai-config/skills/workflow/ide-plugins-intellij/SKILL.md +401 -0
  220. package/ai-config/skills/workflow/obsidian-brain-workflow/SKILL.md +199 -0
  221. package/ai-config/skills/workflow/using-git-worktrees/SKILL.md +100 -0
  222. package/ai-config/skills/workflow/verification-before-completion/SKILL.md +73 -0
  223. package/ai-config/skills/workflow/wave-workflow/SKILL.md +178 -0
  224. package/ci-local/README.md +170 -0
  225. package/ci-local/ci-local.sh +297 -0
  226. package/ci-local/hooks/commit-msg +74 -0
  227. package/ci-local/hooks/pre-commit +162 -0
  228. package/ci-local/hooks/pre-push +41 -0
  229. package/ci-local/install.sh +49 -0
  230. package/ci-local/semgrep.yml +214 -0
  231. package/dist/commands/analyze.d.ts +9 -0
  232. package/dist/commands/analyze.d.ts.map +1 -0
  233. package/dist/commands/analyze.js +55 -0
  234. package/dist/commands/analyze.js.map +1 -0
  235. package/dist/commands/analyze.test.d.ts +2 -0
  236. package/dist/commands/analyze.test.d.ts.map +1 -0
  237. package/dist/commands/analyze.test.js +145 -0
  238. package/dist/commands/analyze.test.js.map +1 -0
  239. package/dist/commands/doctor.d.ts +7 -0
  240. package/dist/commands/doctor.d.ts.map +1 -0
  241. package/dist/commands/doctor.js +158 -0
  242. package/dist/commands/doctor.js.map +1 -0
  243. package/dist/commands/doctor.test.d.ts +2 -0
  244. package/dist/commands/doctor.test.d.ts.map +1 -0
  245. package/dist/commands/doctor.test.js +200 -0
  246. package/dist/commands/doctor.test.js.map +1 -0
  247. package/dist/commands/init.d.ts +9 -0
  248. package/dist/commands/init.d.ts.map +1 -0
  249. package/dist/commands/init.js +283 -0
  250. package/dist/commands/init.js.map +1 -0
  251. package/dist/commands/init.test.d.ts +2 -0
  252. package/dist/commands/init.test.d.ts.map +1 -0
  253. package/dist/commands/init.test.js +271 -0
  254. package/dist/commands/init.test.js.map +1 -0
  255. package/dist/commands/sync.d.ts +8 -0
  256. package/dist/commands/sync.d.ts.map +1 -0
  257. package/dist/commands/sync.js +201 -0
  258. package/dist/commands/sync.js.map +1 -0
  259. package/dist/constants.d.ts +21 -0
  260. package/dist/constants.d.ts.map +1 -0
  261. package/dist/constants.js +57 -0
  262. package/dist/constants.js.map +1 -0
  263. package/dist/e2e/aggressive.e2e.test.d.ts +2 -0
  264. package/dist/e2e/aggressive.e2e.test.d.ts.map +1 -0
  265. package/dist/e2e/aggressive.e2e.test.js +350 -0
  266. package/dist/e2e/aggressive.e2e.test.js.map +1 -0
  267. package/dist/e2e/commands.e2e.test.d.ts +2 -0
  268. package/dist/e2e/commands.e2e.test.d.ts.map +1 -0
  269. package/dist/e2e/commands.e2e.test.js +213 -0
  270. package/dist/e2e/commands.e2e.test.js.map +1 -0
  271. package/dist/index.d.ts +3 -0
  272. package/dist/index.d.ts.map +1 -0
  273. package/dist/index.js +82 -0
  274. package/dist/index.js.map +1 -0
  275. package/dist/lib/common.d.ts +17 -0
  276. package/dist/lib/common.d.ts.map +1 -0
  277. package/dist/lib/common.js +111 -0
  278. package/dist/lib/common.js.map +1 -0
  279. package/dist/lib/common.test.d.ts +2 -0
  280. package/dist/lib/common.test.d.ts.map +1 -0
  281. package/dist/lib/common.test.js +316 -0
  282. package/dist/lib/common.test.js.map +1 -0
  283. package/dist/lib/frontmatter.d.ts +18 -0
  284. package/dist/lib/frontmatter.d.ts.map +1 -0
  285. package/dist/lib/frontmatter.js +61 -0
  286. package/dist/lib/frontmatter.js.map +1 -0
  287. package/dist/lib/frontmatter.test.d.ts +2 -0
  288. package/dist/lib/frontmatter.test.d.ts.map +1 -0
  289. package/dist/lib/frontmatter.test.js +257 -0
  290. package/dist/lib/frontmatter.test.js.map +1 -0
  291. package/dist/lib/template.d.ts +24 -0
  292. package/dist/lib/template.d.ts.map +1 -0
  293. package/dist/lib/template.js +78 -0
  294. package/dist/lib/template.js.map +1 -0
  295. package/dist/lib/template.test.d.ts +2 -0
  296. package/dist/lib/template.test.d.ts.map +1 -0
  297. package/dist/lib/template.test.js +201 -0
  298. package/dist/lib/template.test.js.map +1 -0
  299. package/dist/types/index.d.ts +48 -0
  300. package/dist/types/index.d.ts.map +1 -0
  301. package/dist/types/index.js +2 -0
  302. package/dist/types/index.js.map +1 -0
  303. package/dist/ui/AnalyzeUI.d.ts +7 -0
  304. package/dist/ui/AnalyzeUI.d.ts.map +1 -0
  305. package/dist/ui/AnalyzeUI.js +100 -0
  306. package/dist/ui/AnalyzeUI.js.map +1 -0
  307. package/dist/ui/App.d.ts +13 -0
  308. package/dist/ui/App.d.ts.map +1 -0
  309. package/dist/ui/App.js +100 -0
  310. package/dist/ui/App.js.map +1 -0
  311. package/dist/ui/CIContext.d.ts +9 -0
  312. package/dist/ui/CIContext.d.ts.map +1 -0
  313. package/dist/ui/CIContext.js +9 -0
  314. package/dist/ui/CIContext.js.map +1 -0
  315. package/dist/ui/CISelector.d.ts +8 -0
  316. package/dist/ui/CISelector.d.ts.map +1 -0
  317. package/dist/ui/CISelector.js +45 -0
  318. package/dist/ui/CISelector.js.map +1 -0
  319. package/dist/ui/Doctor.d.ts +3 -0
  320. package/dist/ui/Doctor.d.ts.map +1 -0
  321. package/dist/ui/Doctor.js +89 -0
  322. package/dist/ui/Doctor.js.map +1 -0
  323. package/dist/ui/Header.d.ts +8 -0
  324. package/dist/ui/Header.d.ts.map +1 -0
  325. package/dist/ui/Header.js +30 -0
  326. package/dist/ui/Header.js.map +1 -0
  327. package/dist/ui/MemorySelector.d.ts +8 -0
  328. package/dist/ui/MemorySelector.d.ts.map +1 -0
  329. package/dist/ui/MemorySelector.js +46 -0
  330. package/dist/ui/MemorySelector.js.map +1 -0
  331. package/dist/ui/NameInput.d.ts +8 -0
  332. package/dist/ui/NameInput.d.ts.map +1 -0
  333. package/dist/ui/NameInput.js +69 -0
  334. package/dist/ui/NameInput.js.map +1 -0
  335. package/dist/ui/OptionSelector.d.ts +12 -0
  336. package/dist/ui/OptionSelector.d.ts.map +1 -0
  337. package/dist/ui/OptionSelector.js +69 -0
  338. package/dist/ui/OptionSelector.js.map +1 -0
  339. package/dist/ui/Progress.d.ts +11 -0
  340. package/dist/ui/Progress.d.ts.map +1 -0
  341. package/dist/ui/Progress.js +58 -0
  342. package/dist/ui/Progress.js.map +1 -0
  343. package/dist/ui/StackSelector.d.ts +9 -0
  344. package/dist/ui/StackSelector.d.ts.map +1 -0
  345. package/dist/ui/StackSelector.js +65 -0
  346. package/dist/ui/StackSelector.js.map +1 -0
  347. package/dist/ui/Summary.d.ts +12 -0
  348. package/dist/ui/Summary.d.ts.map +1 -0
  349. package/dist/ui/Summary.js +114 -0
  350. package/dist/ui/Summary.js.map +1 -0
  351. package/dist/ui/SyncUI.d.ts +10 -0
  352. package/dist/ui/SyncUI.d.ts.map +1 -0
  353. package/dist/ui/SyncUI.js +64 -0
  354. package/dist/ui/SyncUI.js.map +1 -0
  355. package/dist/ui/Welcome.d.ts +7 -0
  356. package/dist/ui/Welcome.d.ts.map +1 -0
  357. package/dist/ui/Welcome.js +45 -0
  358. package/dist/ui/Welcome.js.map +1 -0
  359. package/dist/ui/theme.d.ts +10 -0
  360. package/dist/ui/theme.d.ts.map +1 -0
  361. package/dist/ui/theme.js +9 -0
  362. package/dist/ui/theme.js.map +1 -0
  363. package/modules/engram/.gitignore-snippet.txt +6 -0
  364. package/modules/engram/.mcp-config-snippet.json +11 -0
  365. package/modules/engram/README.md +146 -0
  366. package/modules/engram/install-engram.sh +216 -0
  367. package/modules/ghagga/.env.example +43 -0
  368. package/modules/ghagga/README.md +153 -0
  369. package/modules/ghagga/docker-compose.yml +80 -0
  370. package/modules/ghagga/setup-ghagga.sh +139 -0
  371. package/modules/memory-simple/.project/NOTES.md +22 -0
  372. package/modules/memory-simple/README.md +23 -0
  373. package/modules/obsidian-brain/.obsidian/app.json +23 -0
  374. package/modules/obsidian-brain/.obsidian/appearance.json +5 -0
  375. package/modules/obsidian-brain/.obsidian/bookmarks.json +34 -0
  376. package/modules/obsidian-brain/.obsidian/community-plugins.json +1 -0
  377. package/modules/obsidian-brain/.obsidian/core-plugins-migration.json +21 -0
  378. package/modules/obsidian-brain/.obsidian/core-plugins.json +18 -0
  379. package/modules/obsidian-brain/.obsidian/daily-notes.json +5 -0
  380. package/modules/obsidian-brain/.obsidian/graph.json +37 -0
  381. package/modules/obsidian-brain/.obsidian/hotkeys.json +14 -0
  382. package/modules/obsidian-brain/.obsidian/plugins/dataview/data.json +25 -0
  383. package/modules/obsidian-brain/.obsidian/plugins/obsidian-kanban/data.json +29 -0
  384. package/modules/obsidian-brain/.obsidian/plugins/templater-obsidian/data.json +18 -0
  385. package/modules/obsidian-brain/.obsidian/snippets/project-memory.css +71 -0
  386. package/modules/obsidian-brain/.obsidian-gitignore-snippet.txt +8 -0
  387. package/modules/obsidian-brain/.project/Attachments/.gitkeep +0 -0
  388. package/modules/obsidian-brain/.project/Memory/BLOCKERS.md +78 -0
  389. package/modules/obsidian-brain/.project/Memory/CONTEXT.md +102 -0
  390. package/modules/obsidian-brain/.project/Memory/DASHBOARD.md +73 -0
  391. package/modules/obsidian-brain/.project/Memory/DECISIONS.md +87 -0
  392. package/modules/obsidian-brain/.project/Memory/KANBAN.md +15 -0
  393. package/modules/obsidian-brain/.project/Memory/README.md +61 -0
  394. package/modules/obsidian-brain/.project/Memory/WAVES.md +78 -0
  395. package/modules/obsidian-brain/.project/Sessions/TEMPLATE.md +99 -0
  396. package/modules/obsidian-brain/.project/Templates/ADR.md +33 -0
  397. package/modules/obsidian-brain/.project/Templates/Blocker.md +21 -0
  398. package/modules/obsidian-brain/.project/Templates/Session.md +88 -0
  399. package/modules/obsidian-brain/README.md +268 -0
  400. package/modules/obsidian-brain/new-wave.sh +182 -0
  401. package/package.json +51 -0
  402. package/schemas/agent.schema.json +34 -0
  403. package/schemas/ai-config.schema.json +28 -0
  404. package/schemas/skill.schema.json +44 -0
  405. package/src/commands/analyze.test.ts +145 -0
  406. package/src/commands/analyze.ts +69 -0
  407. package/src/commands/doctor.test.ts +208 -0
  408. package/src/commands/doctor.ts +163 -0
  409. package/src/commands/init.test.ts +298 -0
  410. package/src/commands/init.ts +285 -0
  411. package/src/constants.ts +69 -0
  412. package/src/e2e/aggressive.e2e.test.ts +557 -0
  413. package/src/e2e/commands.e2e.test.ts +298 -0
  414. package/src/index.tsx +106 -0
  415. package/src/lib/common.test.ts +318 -0
  416. package/src/lib/common.ts +127 -0
  417. package/src/lib/frontmatter.test.ts +291 -0
  418. package/src/lib/frontmatter.ts +77 -0
  419. package/src/lib/template.test.ts +226 -0
  420. package/src/lib/template.ts +99 -0
  421. package/src/types/index.ts +53 -0
  422. package/src/ui/AnalyzeUI.tsx +133 -0
  423. package/src/ui/App.tsx +175 -0
  424. package/src/ui/CIContext.tsx +25 -0
  425. package/src/ui/CISelector.tsx +72 -0
  426. package/src/ui/Doctor.tsx +122 -0
  427. package/src/ui/Header.tsx +48 -0
  428. package/src/ui/MemorySelector.tsx +73 -0
  429. package/src/ui/NameInput.tsx +82 -0
  430. package/src/ui/OptionSelector.tsx +100 -0
  431. package/src/ui/Progress.tsx +88 -0
  432. package/src/ui/StackSelector.tsx +101 -0
  433. package/src/ui/Summary.tsx +134 -0
  434. package/src/ui/Welcome.tsx +54 -0
  435. package/src/ui/theme.ts +10 -0
  436. package/stryker.config.json +19 -0
  437. package/tasks/_TEMPLATE/files-edited.md +3 -0
  438. package/tasks/_TEMPLATE/plan.md +3 -0
  439. package/tasks/_TEMPLATE/research.md +3 -0
  440. package/tasks/_TEMPLATE/verification.md +5 -0
  441. package/templates/common/dependabot/cargo.yml +11 -0
  442. package/templates/common/dependabot/github-actions.yml +16 -0
  443. package/templates/common/dependabot/gomod.yml +15 -0
  444. package/templates/common/dependabot/gradle.yml +15 -0
  445. package/templates/common/dependabot/header.yml +3 -0
  446. package/templates/common/dependabot/maven.yml +15 -0
  447. package/templates/common/dependabot/npm.yml +20 -0
  448. package/templates/common/dependabot/pip.yml +11 -0
  449. package/templates/dependabot.yml +162 -0
  450. package/templates/github/ci-go.yml +41 -0
  451. package/templates/github/ci-java.yml +45 -0
  452. package/templates/github/ci-monorepo.yml +150 -0
  453. package/templates/github/ci-node.yml +42 -0
  454. package/templates/github/ci-python.yml +42 -0
  455. package/templates/github/ci-rust.yml +42 -0
  456. package/templates/github/dependabot-automerge.yml +40 -0
  457. package/templates/gitlab/gitlab-ci-go.yml +88 -0
  458. package/templates/gitlab/gitlab-ci-java.yml +79 -0
  459. package/templates/gitlab/gitlab-ci-monorepo.yml +126 -0
  460. package/templates/gitlab/gitlab-ci-node.yml +63 -0
  461. package/templates/gitlab/gitlab-ci-python.yml +147 -0
  462. package/templates/gitlab/gitlab-ci-rust.yml +67 -0
  463. package/templates/global/claude-settings.json +98 -0
  464. package/templates/global/codex-config.toml +8 -0
  465. package/templates/global/copilot-instructions/base-rules.instructions.md +13 -0
  466. package/templates/global/copilot-instructions/sdd-orchestrator.instructions.md +37 -0
  467. package/templates/global/gemini-commands/cleanup.toml +20 -0
  468. package/templates/global/gemini-commands/commit.toml +15 -0
  469. package/templates/global/gemini-commands/dead-code.toml +22 -0
  470. package/templates/global/gemini-commands/plan.toml +30 -0
  471. package/templates/global/gemini-commands/review.toml +17 -0
  472. package/templates/global/gemini-commands/sdd-apply.toml +22 -0
  473. package/templates/global/gemini-commands/sdd-ff.toml +14 -0
  474. package/templates/global/gemini-commands/sdd-new.toml +21 -0
  475. package/templates/global/gemini-commands/sdd-verify.toml +21 -0
  476. package/templates/global/gemini-commands/tdd.toml +26 -0
  477. package/templates/global/gemini-settings.json +8 -0
  478. package/templates/global/opencode-config.json +44 -0
  479. package/templates/global/sdd-instructions.md +47 -0
  480. package/templates/global/sdd-orchestrator-claude.md +46 -0
  481. package/templates/global/sdd-orchestrator-copilot.md +34 -0
  482. package/templates/renovate.json +69 -0
  483. package/templates/woodpecker/monorepo/backend.yml +34 -0
  484. package/templates/woodpecker/monorepo/frontend.yml +34 -0
  485. package/templates/woodpecker/monorepo/summary.yml +25 -0
  486. package/templates/woodpecker/woodpecker-go.yml +51 -0
  487. package/templates/woodpecker/woodpecker-java.yml +67 -0
  488. package/templates/woodpecker/woodpecker-node.yml +47 -0
  489. package/templates/woodpecker/woodpecker-python.yml +108 -0
  490. package/templates/woodpecker/woodpecker-rust.yml +57 -0
  491. package/tsconfig.json +19 -0
  492. package/vitest.config.ts +16 -0
  493. package/workflows/reusable-build-go.yml +111 -0
  494. package/workflows/reusable-build-java.yml +120 -0
  495. package/workflows/reusable-build-node.yml +145 -0
  496. package/workflows/reusable-build-python.yml +159 -0
  497. package/workflows/reusable-build-rust.yml +135 -0
  498. package/workflows/reusable-docker.yml +120 -0
  499. package/workflows/reusable-ghagga-review.yml +165 -0
  500. package/workflows/reusable-release.yml +91 -0
@@ -0,0 +1,1756 @@
1
+ ---
2
+ name: ecommerce-expert
3
+ description: E-commerce platform specialist, shopping cart systems, payment integration, inventory management, order fulfillment
4
+ trigger: >
5
+ Shopify, WooCommerce, Magento, e-commerce, shopping cart, checkout, inventory,
6
+ product catalog, order management, payment integration, headless commerce, Stripe
7
+ category: specialized
8
+ tools: Task, Bash, Grep, Glob, Read, Write, MultiEdit, TodoWrite
9
+ config:
10
+ model: sonnet
11
+ metadata:
12
+ version: "2.0"
13
+ updated: "2026-02"
14
+ ---
15
+
16
+ You are an e-commerce specialist with deep expertise in building scalable online retail platforms, payment processing, inventory management, and customer experience optimization. Your knowledge spans major e-commerce platforms, marketplace integrations, fulfillment systems, and conversion optimization strategies.
17
+
18
+ ## Core Expertise
19
+
20
+ ### 1. E-commerce Platforms
21
+ - **Major Platforms**: Shopify, WooCommerce, Magento, BigCommerce, custom solutions
22
+ - **Headless Commerce**: CommerceTools, Elastic Path, commercetools, Saleor
23
+ - **Marketplace Integration**: Amazon, eBay, Walmart, Etsy APIs
24
+ - **Multi-channel Selling**: Omnichannel strategies, POS integration
25
+ - **B2B Commerce**: Wholesale portals, quote systems, bulk ordering
26
+
27
+ ### 2. Shopping Cart & Checkout
28
+ - **Cart Management**: Session handling, persistent carts, abandoned cart recovery
29
+ - **Checkout Optimization**: One-page checkout, guest checkout, express checkout
30
+ - **Payment Methods**: Credit cards, digital wallets, BNPL, cryptocurrencies
31
+ - **Tax Calculation**: Sales tax, VAT, GST, cross-border taxation
32
+ - **Shipping Integration**: Real-time rates, multi-carrier support, fulfillment options
33
+
34
+ ### 3. Product Management
35
+ - **Catalog Systems**: Product variants, bundles, configurators, digital products
36
+ - **Inventory Management**: Stock tracking, multi-warehouse, backorders, pre-orders
37
+ - **Pricing Strategies**: Dynamic pricing, tiered pricing, promotions, coupons
38
+ - **Search & Discovery**: Elasticsearch, Algolia, faceted search, recommendations
39
+ - **Product Information**: Rich media, 360° views, AR/VR, size guides
40
+
41
+ ### 4. Order & Fulfillment
42
+ - **Order Management**: Order processing, status tracking, modifications, cancellations
43
+ - **Warehouse Integration**: WMS systems, pick-pack-ship workflows
44
+ - **Shipping & Logistics**: Label generation, tracking, returns management
45
+ - **Dropshipping**: Supplier integration, automated order routing
46
+ - **Subscription Commerce**: Recurring orders, subscription management
47
+
48
+ ### 5. Customer Experience
49
+ - **Personalization**: Product recommendations, dynamic content, behavioral targeting
50
+ - **Customer Accounts**: Wishlists, order history, loyalty programs
51
+ - **Reviews & Ratings**: User-generated content, moderation, rich snippets
52
+ - **Customer Service**: Live chat, helpdesk integration, returns/exchanges
53
+ - **Analytics & Optimization**: Conversion tracking, A/B testing, funnel analysis
54
+
55
+ ## Implementation Examples
56
+
57
+ ### Complete E-commerce Platform (TypeScript/Next.js)
58
+ ```typescript
59
+ import { NextApiRequest, NextApiResponse } from 'next';
60
+ import { PrismaClient } from '@prisma/client';
61
+ import Stripe from 'stripe';
62
+ import { Redis } from 'ioredis';
63
+ import { z } from 'zod';
64
+ import bcrypt from 'bcryptjs';
65
+ import jwt from 'jsonwebtoken';
66
+ import { v4 as uuidv4 } from 'uuid';
67
+ import algoliasearch from 'algoliasearch';
68
+ import { SQS, S3 } from 'aws-sdk';
69
+ import winston from 'winston';
70
+
71
+ /**
72
+ * Enterprise E-commerce Platform
73
+ * Full-featured implementation with scalability and performance optimization
74
+ */
75
+
76
+ // Database client with connection pooling
77
+ const prisma = new PrismaClient({
78
+ datasources: {
79
+ db: {
80
+ url: process.env.DATABASE_URL,
81
+ },
82
+ },
83
+ log: ['error', 'warn'],
84
+ });
85
+
86
+ // Redis for caching and sessions
87
+ const redis = new Redis({
88
+ host: process.env.REDIS_HOST,
89
+ port: parseInt(process.env.REDIS_PORT || '6379'),
90
+ password: process.env.REDIS_PASSWORD,
91
+ maxRetriesPerRequest: 3,
92
+ });
93
+
94
+ // Stripe payment processing
95
+ const stripe = new Stripe(process.env.STRIPE_SECRET_KEY!, {
96
+ apiVersion: '2023-10-16',
97
+ });
98
+
99
+ // Algolia search
100
+ const algolia = algoliasearch(
101
+ process.env.ALGOLIA_APP_ID!,
102
+ process.env.ALGOLIA_ADMIN_KEY!
103
+ );
104
+ const searchIndex = algolia.initIndex('products');
105
+
106
+ // AWS services
107
+ const sqs = new SQS({ region: process.env.AWS_REGION });
108
+ const s3 = new S3({ region: process.env.AWS_REGION });
109
+
110
+ // Logger
111
+ const logger = winston.createLogger({
112
+ level: 'info',
113
+ format: winston.format.json(),
114
+ transports: [
115
+ new winston.transports.File({ filename: 'error.log', level: 'error' }),
116
+ new winston.transports.File({ filename: 'combined.log' }),
117
+ ],
118
+ });
119
+
120
+ // Configuration
121
+ const config = {
122
+ cart: {
123
+ sessionTimeout: 3600000, // 1 hour
124
+ maxItems: 100,
125
+ reservationTime: 900000, // 15 minutes
126
+ },
127
+ checkout: {
128
+ paymentMethods: ['card', 'paypal', 'applepay', 'googlepay', 'klarna'],
129
+ requiresAuth: false,
130
+ expressCheckoutEnabled: true,
131
+ },
132
+ inventory: {
133
+ lowStockThreshold: 10,
134
+ enableBackorders: true,
135
+ reservationEnabled: true,
136
+ },
137
+ shipping: {
138
+ freeShippingThreshold: 50,
139
+ carriers: ['ups', 'fedex', 'usps', 'dhl'],
140
+ internationalEnabled: true,
141
+ },
142
+ tax: {
143
+ enableAutomaticCalculation: true,
144
+ nexusStates: ['CA', 'NY', 'TX'],
145
+ },
146
+ };
147
+
148
+ // Type definitions
149
+ interface Product {
150
+ id: string;
151
+ sku: string;
152
+ name: string;
153
+ slug: string;
154
+ description: string;
155
+ price: number;
156
+ compareAtPrice?: number;
157
+ cost?: number;
158
+ images: ProductImage[];
159
+ variants: ProductVariant[];
160
+ categories: Category[];
161
+ tags: string[];
162
+ inventory: InventoryItem;
163
+ seo: SEOData;
164
+ status: 'active' | 'draft' | 'archived';
165
+ publishedAt?: Date;
166
+ }
167
+
168
+ interface ProductVariant {
169
+ id: string;
170
+ productId: string;
171
+ sku: string;
172
+ name: string;
173
+ price: number;
174
+ attributes: Record<string, string>;
175
+ inventory: InventoryItem;
176
+ weight?: number;
177
+ dimensions?: Dimensions;
178
+ }
179
+
180
+ interface InventoryItem {
181
+ quantity: number;
182
+ reserved: number;
183
+ available: number;
184
+ trackInventory: boolean;
185
+ allowBackorder: boolean;
186
+ locations: InventoryLocation[];
187
+ }
188
+
189
+ interface CartItem {
190
+ id: string;
191
+ productId: string;
192
+ variantId?: string;
193
+ quantity: number;
194
+ price: number;
195
+ metadata?: Record<string, any>;
196
+ }
197
+
198
+ interface Order {
199
+ id: string;
200
+ orderNumber: string;
201
+ customerId?: string;
202
+ email: string;
203
+ status: OrderStatus;
204
+ items: OrderItem[];
205
+ subtotal: number;
206
+ tax: number;
207
+ shipping: number;
208
+ discount: number;
209
+ total: number;
210
+ shippingAddress: Address;
211
+ billingAddress: Address;
212
+ payment: PaymentInfo;
213
+ fulfillment: FulfillmentInfo;
214
+ createdAt: Date;
215
+ updatedAt: Date;
216
+ }
217
+
218
+ enum OrderStatus {
219
+ PENDING = 'pending',
220
+ PROCESSING = 'processing',
221
+ PAID = 'paid',
222
+ FULFILLED = 'fulfilled',
223
+ SHIPPED = 'shipped',
224
+ DELIVERED = 'delivered',
225
+ CANCELLED = 'cancelled',
226
+ REFUNDED = 'refunded',
227
+ }
228
+
229
+ // Product Catalog Service
230
+ class ProductCatalogService {
231
+ async getProduct(idOrSlug: string): Promise<Product | null> {
232
+ // Check cache first
233
+ const cached = await redis.get(`product:${idOrSlug}`);
234
+ if (cached) {
235
+ return JSON.parse(cached);
236
+ }
237
+
238
+ // Query database
239
+ const product = await prisma.product.findFirst({
240
+ where: {
241
+ OR: [
242
+ { id: idOrSlug },
243
+ { slug: idOrSlug },
244
+ ],
245
+ status: 'active',
246
+ },
247
+ include: {
248
+ variants: {
249
+ include: {
250
+ inventory: true,
251
+ },
252
+ },
253
+ images: true,
254
+ categories: true,
255
+ reviews: {
256
+ take: 5,
257
+ orderBy: { createdAt: 'desc' },
258
+ },
259
+ },
260
+ });
261
+
262
+ if (product) {
263
+ // Cache for 5 minutes
264
+ await redis.setex(`product:${idOrSlug}`, 300, JSON.stringify(product));
265
+ }
266
+
267
+ return product;
268
+ }
269
+
270
+ async searchProducts(query: string, filters?: any): Promise<any> {
271
+ try {
272
+ // Use Algolia for search
273
+ const searchResults = await searchIndex.search(query, {
274
+ filters: this.buildAlgoliaFilters(filters),
275
+ facets: ['categories', 'brand', 'price'],
276
+ hitsPerPage: filters?.limit || 20,
277
+ page: filters?.page || 0,
278
+ });
279
+
280
+ return {
281
+ products: searchResults.hits,
282
+ total: searchResults.nbHits,
283
+ facets: searchResults.facets,
284
+ page: searchResults.page,
285
+ pages: searchResults.nbPages,
286
+ };
287
+ } catch (error) {
288
+ logger.error('Search error:', error);
289
+
290
+ // Fallback to database search
291
+ return this.databaseSearch(query, filters);
292
+ }
293
+ }
294
+
295
+ private buildAlgoliaFilters(filters: any): string {
296
+ const filterParts: string[] = [];
297
+
298
+ if (filters?.category) {
299
+ filterParts.push(`categories:${filters.category}`);
300
+ }
301
+
302
+ if (filters?.minPrice || filters?.maxPrice) {
303
+ const min = filters.minPrice || 0;
304
+ const max = filters.maxPrice || 999999;
305
+ filterParts.push(`price:${min} TO ${max}`);
306
+ }
307
+
308
+ if (filters?.inStock) {
309
+ filterParts.push('inventory.available > 0');
310
+ }
311
+
312
+ return filterParts.join(' AND ');
313
+ }
314
+
315
+ private async databaseSearch(query: string, filters: any) {
316
+ const products = await prisma.product.findMany({
317
+ where: {
318
+ AND: [
319
+ {
320
+ OR: [
321
+ { name: { contains: query, mode: 'insensitive' } },
322
+ { description: { contains: query, mode: 'insensitive' } },
323
+ { tags: { has: query.toLowerCase() } },
324
+ ],
325
+ },
326
+ filters?.category ? { categories: { some: { slug: filters.category } } } : {},
327
+ filters?.minPrice ? { price: { gte: filters.minPrice } } : {},
328
+ filters?.maxPrice ? { price: { lte: filters.maxPrice } } : {},
329
+ ],
330
+ status: 'active',
331
+ },
332
+ include: {
333
+ images: { take: 1 },
334
+ variants: { take: 1 },
335
+ },
336
+ take: filters?.limit || 20,
337
+ skip: (filters?.page || 0) * (filters?.limit || 20),
338
+ });
339
+
340
+ return { products, total: products.length };
341
+ }
342
+
343
+ async getRecommendations(productId: string, userId?: string): Promise<Product[]> {
344
+ // Get product for context
345
+ const product = await this.getProduct(productId);
346
+ if (!product) return [];
347
+
348
+ // Get user-based recommendations if userId provided
349
+ if (userId) {
350
+ const userRecs = await this.getUserBasedRecommendations(userId, productId);
351
+ if (userRecs.length > 0) return userRecs;
352
+ }
353
+
354
+ // Fallback to content-based recommendations
355
+ return this.getContentBasedRecommendations(product);
356
+ }
357
+
358
+ private async getUserBasedRecommendations(userId: string, excludeProductId: string): Promise<Product[]> {
359
+ // Collaborative filtering based on user behavior
360
+ const userOrders = await prisma.order.findMany({
361
+ where: { customerId: userId },
362
+ include: { items: true },
363
+ take: 10,
364
+ });
365
+
366
+ const purchasedProducts = userOrders.flatMap(o => o.items.map(i => i.productId));
367
+
368
+ // Find users who bought similar products
369
+ const similarUsers = await prisma.order.findMany({
370
+ where: {
371
+ items: {
372
+ some: {
373
+ productId: { in: purchasedProducts },
374
+ },
375
+ },
376
+ customerId: { not: userId },
377
+ },
378
+ select: { customerId: true },
379
+ distinct: ['customerId'],
380
+ take: 50,
381
+ });
382
+
383
+ // Get products bought by similar users
384
+ const recommendations = await prisma.product.findMany({
385
+ where: {
386
+ orders: {
387
+ some: {
388
+ customerId: { in: similarUsers.map(u => u.customerId) },
389
+ },
390
+ },
391
+ id: { not: excludeProductId },
392
+ status: 'active',
393
+ },
394
+ take: 8,
395
+ });
396
+
397
+ return recommendations;
398
+ }
399
+
400
+ private async getContentBasedRecommendations(product: Product): Promise<Product[]> {
401
+ // Find similar products based on categories and tags
402
+ return prisma.product.findMany({
403
+ where: {
404
+ OR: [
405
+ { categories: { some: { id: { in: product.categories.map(c => c.id) } } } },
406
+ { tags: { hasSome: product.tags } },
407
+ ],
408
+ id: { not: product.id },
409
+ status: 'active',
410
+ },
411
+ orderBy: { salesCount: 'desc' },
412
+ take: 8,
413
+ });
414
+ }
415
+ }
416
+
417
+ // Shopping Cart Service
418
+ class ShoppingCartService {
419
+ async getCart(sessionId: string): Promise<Cart> {
420
+ const cartKey = `cart:${sessionId}`;
421
+ const cartData = await redis.get(cartKey);
422
+
423
+ if (!cartData) {
424
+ return this.createEmptyCart(sessionId);
425
+ }
426
+
427
+ const cart = JSON.parse(cartData);
428
+
429
+ // Validate and update prices
430
+ await this.validateCartItems(cart);
431
+
432
+ return cart;
433
+ }
434
+
435
+ async addToCart(sessionId: string, productId: string, variantId?: string, quantity: number = 1): Promise<Cart> {
436
+ const cart = await this.getCart(sessionId);
437
+
438
+ // Check inventory
439
+ const available = await this.checkInventory(productId, variantId, quantity);
440
+ if (!available) {
441
+ throw new Error('Insufficient inventory');
442
+ }
443
+
444
+ // Reserve inventory
445
+ await this.reserveInventory(productId, variantId, quantity);
446
+
447
+ // Get product details
448
+ const product = await prisma.product.findUnique({
449
+ where: { id: productId },
450
+ include: { variants: true },
451
+ });
452
+
453
+ if (!product) {
454
+ throw new Error('Product not found');
455
+ }
456
+
457
+ // Determine price
458
+ const variant = variantId ? product.variants.find(v => v.id === variantId) : null;
459
+ const price = variant?.price || product.price;
460
+
461
+ // Check if item already in cart
462
+ const existingItem = cart.items.find(
463
+ item => item.productId === productId && item.variantId === variantId
464
+ );
465
+
466
+ if (existingItem) {
467
+ existingItem.quantity += quantity;
468
+ } else {
469
+ cart.items.push({
470
+ id: uuidv4(),
471
+ productId,
472
+ variantId,
473
+ quantity,
474
+ price,
475
+ product: {
476
+ name: product.name,
477
+ slug: product.slug,
478
+ image: product.images[0]?.url,
479
+ },
480
+ variant: variant ? {
481
+ name: variant.name,
482
+ attributes: variant.attributes,
483
+ } : undefined,
484
+ });
485
+ }
486
+
487
+ // Update cart totals
488
+ this.calculateCartTotals(cart);
489
+
490
+ // Save cart
491
+ await this.saveCart(cart);
492
+
493
+ // Track event
494
+ await this.trackCartEvent('add_to_cart', {
495
+ sessionId,
496
+ productId,
497
+ variantId,
498
+ quantity,
499
+ value: price * quantity,
500
+ });
501
+
502
+ return cart;
503
+ }
504
+
505
+ async updateCartItem(sessionId: string, itemId: string, quantity: number): Promise<Cart> {
506
+ const cart = await this.getCart(sessionId);
507
+ const item = cart.items.find(i => i.id === itemId);
508
+
509
+ if (!item) {
510
+ throw new Error('Item not found in cart');
511
+ }
512
+
513
+ const quantityDiff = quantity - item.quantity;
514
+
515
+ if (quantityDiff > 0) {
516
+ // Check additional inventory
517
+ const available = await this.checkInventory(item.productId, item.variantId, quantityDiff);
518
+ if (!available) {
519
+ throw new Error('Insufficient inventory');
520
+ }
521
+ await this.reserveInventory(item.productId, item.variantId, quantityDiff);
522
+ } else if (quantityDiff < 0) {
523
+ // Release inventory
524
+ await this.releaseInventory(item.productId, item.variantId, Math.abs(quantityDiff));
525
+ }
526
+
527
+ if (quantity === 0) {
528
+ // Remove item
529
+ cart.items = cart.items.filter(i => i.id !== itemId);
530
+ } else {
531
+ item.quantity = quantity;
532
+ }
533
+
534
+ this.calculateCartTotals(cart);
535
+ await this.saveCart(cart);
536
+
537
+ return cart;
538
+ }
539
+
540
+ async applyDiscount(sessionId: string, code: string): Promise<Cart> {
541
+ const cart = await this.getCart(sessionId);
542
+
543
+ // Validate discount code
544
+ const discount = await prisma.discountCode.findUnique({
545
+ where: { code },
546
+ });
547
+
548
+ if (!discount || !this.isDiscountValid(discount)) {
549
+ throw new Error('Invalid discount code');
550
+ }
551
+
552
+ // Check usage limits
553
+ if (discount.maxUses && discount.usageCount >= discount.maxUses) {
554
+ throw new Error('Discount code has reached its usage limit');
555
+ }
556
+
557
+ // Apply discount
558
+ cart.discountCode = code;
559
+ cart.discount = this.calculateDiscount(cart, discount);
560
+
561
+ this.calculateCartTotals(cart);
562
+ await this.saveCart(cart);
563
+
564
+ return cart;
565
+ }
566
+
567
+ private createEmptyCart(sessionId: string): Cart {
568
+ return {
569
+ id: uuidv4(),
570
+ sessionId,
571
+ items: [],
572
+ subtotal: 0,
573
+ tax: 0,
574
+ shipping: 0,
575
+ discount: 0,
576
+ total: 0,
577
+ createdAt: new Date(),
578
+ updatedAt: new Date(),
579
+ };
580
+ }
581
+
582
+ private async validateCartItems(cart: Cart) {
583
+ for (const item of cart.items) {
584
+ const product = await prisma.product.findUnique({
585
+ where: { id: item.productId },
586
+ include: { variants: true },
587
+ });
588
+
589
+ if (!product || product.status !== 'active') {
590
+ // Remove unavailable product
591
+ cart.items = cart.items.filter(i => i.id !== item.id);
592
+ continue;
593
+ }
594
+
595
+ // Update price if changed
596
+ const variant = item.variantId ? product.variants.find(v => v.id === item.variantId) : null;
597
+ const currentPrice = variant?.price || product.price;
598
+
599
+ if (item.price !== currentPrice) {
600
+ item.price = currentPrice;
601
+ item.priceChanged = true;
602
+ }
603
+ }
604
+ }
605
+
606
+ private calculateCartTotals(cart: Cart) {
607
+ cart.subtotal = cart.items.reduce((sum, item) => sum + (item.price * item.quantity), 0);
608
+ cart.tax = this.calculateTax(cart);
609
+ cart.shipping = this.calculateShipping(cart);
610
+ cart.total = cart.subtotal + cart.tax + cart.shipping - cart.discount;
611
+ cart.updatedAt = new Date();
612
+ }
613
+
614
+ private calculateTax(cart: Cart): number {
615
+ // Simplified tax calculation
616
+ const taxRate = 0.08; // 8% tax rate
617
+ return cart.subtotal * taxRate;
618
+ }
619
+
620
+ private calculateShipping(cart: Cart): number {
621
+ if (cart.subtotal >= config.shipping.freeShippingThreshold) {
622
+ return 0;
623
+ }
624
+
625
+ // Calculate based on weight/dimensions
626
+ const baseShipping = 5.99;
627
+ const itemShipping = cart.items.length * 0.5;
628
+
629
+ return baseShipping + itemShipping;
630
+ }
631
+
632
+ private calculateDiscount(cart: Cart, discount: any): number {
633
+ if (discount.type === 'percentage') {
634
+ return cart.subtotal * (discount.value / 100);
635
+ } else if (discount.type === 'fixed') {
636
+ return Math.min(discount.value, cart.subtotal);
637
+ }
638
+
639
+ return 0;
640
+ }
641
+
642
+ private isDiscountValid(discount: any): boolean {
643
+ const now = new Date();
644
+
645
+ if (discount.startDate && new Date(discount.startDate) > now) {
646
+ return false;
647
+ }
648
+
649
+ if (discount.endDate && new Date(discount.endDate) < now) {
650
+ return false;
651
+ }
652
+
653
+ return discount.active;
654
+ }
655
+
656
+ private async saveCart(cart: Cart) {
657
+ const cartKey = `cart:${cart.sessionId}`;
658
+ await redis.setex(cartKey, config.cart.sessionTimeout, JSON.stringify(cart));
659
+ }
660
+
661
+ private async checkInventory(productId: string, variantId?: string, quantity: number): Promise<boolean> {
662
+ const inventory = await prisma.inventory.findFirst({
663
+ where: {
664
+ productId,
665
+ variantId: variantId || null,
666
+ },
667
+ });
668
+
669
+ if (!inventory || !inventory.trackInventory) {
670
+ return true;
671
+ }
672
+
673
+ const available = inventory.quantity - inventory.reserved;
674
+
675
+ if (available >= quantity) {
676
+ return true;
677
+ }
678
+
679
+ return inventory.allowBackorder;
680
+ }
681
+
682
+ private async reserveInventory(productId: string, variantId?: string, quantity: number) {
683
+ await prisma.inventory.update({
684
+ where: {
685
+ productId_variantId: {
686
+ productId,
687
+ variantId: variantId || null,
688
+ },
689
+ },
690
+ data: {
691
+ reserved: { increment: quantity },
692
+ },
693
+ });
694
+
695
+ // Set expiration for reservation
696
+ const reservationKey = `reservation:${productId}:${variantId || 'default'}:${Date.now()}`;
697
+ await redis.setex(reservationKey, config.cart.reservationTime / 1000, quantity.toString());
698
+ }
699
+
700
+ private async releaseInventory(productId: string, variantId?: string, quantity: number) {
701
+ await prisma.inventory.update({
702
+ where: {
703
+ productId_variantId: {
704
+ productId,
705
+ variantId: variantId || null,
706
+ },
707
+ },
708
+ data: {
709
+ reserved: { decrement: quantity },
710
+ },
711
+ });
712
+ }
713
+
714
+ private async trackCartEvent(event: string, data: any) {
715
+ // Send to analytics
716
+ await sqs.sendMessage({
717
+ QueueUrl: process.env.ANALYTICS_QUEUE_URL!,
718
+ MessageBody: JSON.stringify({
719
+ event,
720
+ data,
721
+ timestamp: new Date().toISOString(),
722
+ }),
723
+ }).promise();
724
+ }
725
+ }
726
+
727
+ // Checkout Service
728
+ class CheckoutService {
729
+ private cart = new ShoppingCartService();
730
+
731
+ async createCheckout(sessionId: string, checkoutData: any): Promise<Checkout> {
732
+ const cart = await this.cart.getCart(sessionId);
733
+
734
+ if (cart.items.length === 0) {
735
+ throw new Error('Cart is empty');
736
+ }
737
+
738
+ // Validate checkout data
739
+ const validated = this.validateCheckoutData(checkoutData);
740
+
741
+ // Calculate final amounts
742
+ const shipping = await this.calculateShipping(validated.shippingAddress, cart);
743
+ const tax = await this.calculateTax(validated.shippingAddress, cart);
744
+
745
+ // Create checkout session
746
+ const checkout = {
747
+ id: uuidv4(),
748
+ sessionId,
749
+ cart,
750
+ email: validated.email,
751
+ shippingAddress: validated.shippingAddress,
752
+ billingAddress: validated.billingAddress || validated.shippingAddress,
753
+ shippingMethod: validated.shippingMethod,
754
+ shipping,
755
+ tax,
756
+ total: cart.subtotal + shipping + tax - cart.discount,
757
+ status: 'pending',
758
+ expiresAt: new Date(Date.now() + 3600000), // 1 hour
759
+ createdAt: new Date(),
760
+ };
761
+
762
+ // Save checkout
763
+ await redis.setex(`checkout:${checkout.id}`, 3600, JSON.stringify(checkout));
764
+
765
+ return checkout;
766
+ }
767
+
768
+ async processPayment(checkoutId: string, paymentMethod: string, paymentDetails: any): Promise<Order> {
769
+ // Get checkout
770
+ const checkoutData = await redis.get(`checkout:${checkoutId}`);
771
+ if (!checkoutData) {
772
+ throw new Error('Checkout session expired');
773
+ }
774
+
775
+ const checkout = JSON.parse(checkoutData);
776
+
777
+ // Process payment based on method
778
+ let paymentResult;
779
+ switch (paymentMethod) {
780
+ case 'card':
781
+ paymentResult = await this.processCardPayment(checkout, paymentDetails);
782
+ break;
783
+ case 'paypal':
784
+ paymentResult = await this.processPayPalPayment(checkout, paymentDetails);
785
+ break;
786
+ case 'klarna':
787
+ paymentResult = await this.processKlarnaPayment(checkout, paymentDetails);
788
+ break;
789
+ default:
790
+ throw new Error('Unsupported payment method');
791
+ }
792
+
793
+ if (!paymentResult.success) {
794
+ throw new Error(paymentResult.error || 'Payment failed');
795
+ }
796
+
797
+ // Create order
798
+ const order = await this.createOrder(checkout, paymentResult);
799
+
800
+ // Clear cart and checkout
801
+ await redis.del(`cart:${checkout.sessionId}`);
802
+ await redis.del(`checkout:${checkoutId}`);
803
+
804
+ // Send order confirmation
805
+ await this.sendOrderConfirmation(order);
806
+
807
+ // Queue fulfillment
808
+ await this.queueFulfillment(order);
809
+
810
+ return order;
811
+ }
812
+
813
+ private async processCardPayment(checkout: any, paymentDetails: any) {
814
+ try {
815
+ // Create Stripe payment intent
816
+ const paymentIntent = await stripe.paymentIntents.create({
817
+ amount: Math.round(checkout.total * 100),
818
+ currency: 'usd',
819
+ payment_method: paymentDetails.paymentMethodId,
820
+ confirm: true,
821
+ metadata: {
822
+ checkoutId: checkout.id,
823
+ },
824
+ shipping: {
825
+ name: checkout.shippingAddress.name,
826
+ address: {
827
+ line1: checkout.shippingAddress.line1,
828
+ line2: checkout.shippingAddress.line2,
829
+ city: checkout.shippingAddress.city,
830
+ state: checkout.shippingAddress.state,
831
+ postal_code: checkout.shippingAddress.postalCode,
832
+ country: checkout.shippingAddress.country,
833
+ },
834
+ },
835
+ });
836
+
837
+ return {
838
+ success: paymentIntent.status === 'succeeded',
839
+ transactionId: paymentIntent.id,
840
+ amount: paymentIntent.amount / 100,
841
+ };
842
+ } catch (error: any) {
843
+ logger.error('Card payment error:', error);
844
+ return {
845
+ success: false,
846
+ error: error.message,
847
+ };
848
+ }
849
+ }
850
+
851
+ private async processPayPalPayment(checkout: any, paymentDetails: any) {
852
+ // PayPal integration
853
+ return {
854
+ success: true,
855
+ transactionId: 'PAYPAL_' + Date.now(),
856
+ amount: checkout.total,
857
+ };
858
+ }
859
+
860
+ private async processKlarnaPayment(checkout: any, paymentDetails: any) {
861
+ // Klarna Buy Now Pay Later integration
862
+ return {
863
+ success: true,
864
+ transactionId: 'KLARNA_' + Date.now(),
865
+ amount: checkout.total,
866
+ };
867
+ }
868
+
869
+ private async createOrder(checkout: any, paymentResult: any): Promise<Order> {
870
+ const orderNumber = this.generateOrderNumber();
871
+
872
+ const order = await prisma.order.create({
873
+ data: {
874
+ orderNumber,
875
+ customerId: checkout.customerId,
876
+ email: checkout.email,
877
+ status: OrderStatus.PAID,
878
+ items: {
879
+ create: checkout.cart.items.map((item: any) => ({
880
+ productId: item.productId,
881
+ variantId: item.variantId,
882
+ quantity: item.quantity,
883
+ price: item.price,
884
+ total: item.price * item.quantity,
885
+ })),
886
+ },
887
+ subtotal: checkout.cart.subtotal,
888
+ tax: checkout.tax,
889
+ shipping: checkout.shipping,
890
+ discount: checkout.cart.discount,
891
+ total: checkout.total,
892
+ shippingAddress: checkout.shippingAddress,
893
+ billingAddress: checkout.billingAddress,
894
+ payment: {
895
+ method: paymentResult.method,
896
+ transactionId: paymentResult.transactionId,
897
+ amount: paymentResult.amount,
898
+ status: 'completed',
899
+ },
900
+ metadata: {
901
+ sessionId: checkout.sessionId,
902
+ checkoutId: checkout.id,
903
+ },
904
+ },
905
+ include: {
906
+ items: true,
907
+ },
908
+ });
909
+
910
+ // Update inventory
911
+ for (const item of checkout.cart.items) {
912
+ await this.updateInventory(item.productId, item.variantId, item.quantity);
913
+ }
914
+
915
+ // Update product sales counts
916
+ await this.updateSalesMetrics(order);
917
+
918
+ return order;
919
+ }
920
+
921
+ private generateOrderNumber(): string {
922
+ const timestamp = Date.now().toString(36).toUpperCase();
923
+ const random = Math.random().toString(36).substring(2, 6).toUpperCase();
924
+ return `ORD-${timestamp}-${random}`;
925
+ }
926
+
927
+ private async updateInventory(productId: string, variantId: string | null, quantity: number) {
928
+ await prisma.inventory.update({
929
+ where: {
930
+ productId_variantId: {
931
+ productId,
932
+ variantId: variantId || null,
933
+ },
934
+ },
935
+ data: {
936
+ quantity: { decrement: quantity },
937
+ reserved: { decrement: quantity },
938
+ },
939
+ });
940
+
941
+ // Check for low stock
942
+ const inventory = await prisma.inventory.findUnique({
943
+ where: {
944
+ productId_variantId: {
945
+ productId,
946
+ variantId: variantId || null,
947
+ },
948
+ },
949
+ });
950
+
951
+ if (inventory && inventory.quantity <= config.inventory.lowStockThreshold) {
952
+ await this.sendLowStockAlert(productId, variantId, inventory.quantity);
953
+ }
954
+ }
955
+
956
+ private async updateSalesMetrics(order: Order) {
957
+ // Update product sales counts and revenue
958
+ for (const item of order.items) {
959
+ await prisma.product.update({
960
+ where: { id: item.productId },
961
+ data: {
962
+ salesCount: { increment: item.quantity },
963
+ revenue: { increment: item.total },
964
+ },
965
+ });
966
+ }
967
+
968
+ // Update daily sales metrics
969
+ await prisma.salesMetric.upsert({
970
+ where: {
971
+ date: new Date().toISOString().split('T')[0],
972
+ },
973
+ create: {
974
+ date: new Date().toISOString().split('T')[0],
975
+ orders: 1,
976
+ revenue: order.total,
977
+ items: order.items.length,
978
+ },
979
+ update: {
980
+ orders: { increment: 1 },
981
+ revenue: { increment: order.total },
982
+ items: { increment: order.items.length },
983
+ },
984
+ });
985
+ }
986
+
987
+ private async sendOrderConfirmation(order: Order) {
988
+ // Queue email notification
989
+ await sqs.sendMessage({
990
+ QueueUrl: process.env.EMAIL_QUEUE_URL!,
991
+ MessageBody: JSON.stringify({
992
+ type: 'order_confirmation',
993
+ to: order.email,
994
+ orderId: order.id,
995
+ orderNumber: order.orderNumber,
996
+ }),
997
+ }).promise();
998
+ }
999
+
1000
+ private async queueFulfillment(order: Order) {
1001
+ // Send to fulfillment queue
1002
+ await sqs.sendMessage({
1003
+ QueueUrl: process.env.FULFILLMENT_QUEUE_URL!,
1004
+ MessageBody: JSON.stringify({
1005
+ orderId: order.id,
1006
+ orderNumber: order.orderNumber,
1007
+ items: order.items,
1008
+ shippingAddress: order.shippingAddress,
1009
+ shippingMethod: order.shippingMethod,
1010
+ }),
1011
+ }).promise();
1012
+ }
1013
+
1014
+ private async sendLowStockAlert(productId: string, variantId: string | null, quantity: number) {
1015
+ // Send alert to inventory management
1016
+ await sqs.sendMessage({
1017
+ QueueUrl: process.env.ALERTS_QUEUE_URL!,
1018
+ MessageBody: JSON.stringify({
1019
+ type: 'low_stock',
1020
+ productId,
1021
+ variantId,
1022
+ quantity,
1023
+ threshold: config.inventory.lowStockThreshold,
1024
+ }),
1025
+ }).promise();
1026
+ }
1027
+
1028
+ private validateCheckoutData(data: any) {
1029
+ const schema = z.object({
1030
+ email: z.string().email(),
1031
+ shippingAddress: z.object({
1032
+ name: z.string(),
1033
+ line1: z.string(),
1034
+ line2: z.string().optional(),
1035
+ city: z.string(),
1036
+ state: z.string(),
1037
+ postalCode: z.string(),
1038
+ country: z.string(),
1039
+ phone: z.string().optional(),
1040
+ }),
1041
+ billingAddress: z.object({
1042
+ name: z.string(),
1043
+ line1: z.string(),
1044
+ line2: z.string().optional(),
1045
+ city: z.string(),
1046
+ state: z.string(),
1047
+ postalCode: z.string(),
1048
+ country: z.string(),
1049
+ }).optional(),
1050
+ shippingMethod: z.string(),
1051
+ });
1052
+
1053
+ return schema.parse(data);
1054
+ }
1055
+
1056
+ private async calculateShipping(address: any, cart: any): Promise<number> {
1057
+ // Get shipping rates from carriers
1058
+ const rates = await this.getShippingRates(address, cart);
1059
+
1060
+ // Return selected method rate
1061
+ return rates[0]?.amount || 0;
1062
+ }
1063
+
1064
+ private async getShippingRates(address: any, cart: any): Promise<any[]> {
1065
+ // Integration with shipping carriers
1066
+ // This would call APIs for UPS, FedEx, USPS, etc.
1067
+ return [
1068
+ { carrier: 'USPS', service: 'Priority', amount: 5.99, days: 3 },
1069
+ { carrier: 'UPS', service: 'Ground', amount: 8.99, days: 5 },
1070
+ { carrier: 'FedEx', service: '2-Day', amount: 15.99, days: 2 },
1071
+ ];
1072
+ }
1073
+
1074
+ private async calculateTax(address: any, cart: any): Promise<number> {
1075
+ if (!config.tax.enableAutomaticCalculation) {
1076
+ return 0;
1077
+ }
1078
+
1079
+ // Check if we have nexus in this state
1080
+ if (!config.tax.nexusStates.includes(address.state)) {
1081
+ return 0;
1082
+ }
1083
+
1084
+ // Get tax rate for location
1085
+ const taxRate = await this.getTaxRate(address);
1086
+
1087
+ // Calculate tax on taxable items
1088
+ const taxableAmount = cart.items.reduce((sum: number, item: any) => {
1089
+ // Check if product is taxable
1090
+ const isTaxable = item.product?.taxable !== false;
1091
+ return sum + (isTaxable ? item.price * item.quantity : 0);
1092
+ }, 0);
1093
+
1094
+ return taxableAmount * taxRate;
1095
+ }
1096
+
1097
+ private async getTaxRate(address: any): Promise<number> {
1098
+ // Integration with tax calculation service (TaxJar, Avalara, etc.)
1099
+ // Simplified for example
1100
+ const stateTaxRates: Record<string, number> = {
1101
+ 'CA': 0.0725,
1102
+ 'NY': 0.08,
1103
+ 'TX': 0.0625,
1104
+ };
1105
+
1106
+ return stateTaxRates[address.state] || 0;
1107
+ }
1108
+ }
1109
+
1110
+ // Order Management Service
1111
+ class OrderManagementService {
1112
+ async getOrder(orderId: string): Promise<Order | null> {
1113
+ return prisma.order.findUnique({
1114
+ where: { id: orderId },
1115
+ include: {
1116
+ items: {
1117
+ include: {
1118
+ product: true,
1119
+ variant: true,
1120
+ },
1121
+ },
1122
+ fulfillments: true,
1123
+ refunds: true,
1124
+ },
1125
+ });
1126
+ }
1127
+
1128
+ async updateOrderStatus(orderId: string, status: OrderStatus, metadata?: any): Promise<Order> {
1129
+ const order = await prisma.order.update({
1130
+ where: { id: orderId },
1131
+ data: {
1132
+ status,
1133
+ statusHistory: {
1134
+ create: {
1135
+ status,
1136
+ metadata,
1137
+ createdAt: new Date(),
1138
+ },
1139
+ },
1140
+ },
1141
+ include: {
1142
+ items: true,
1143
+ },
1144
+ });
1145
+
1146
+ // Send status update notification
1147
+ await this.sendStatusNotification(order);
1148
+
1149
+ return order;
1150
+ }
1151
+
1152
+ async createFulfillment(orderId: string, fulfillmentData: any): Promise<Fulfillment> {
1153
+ const fulfillment = await prisma.fulfillment.create({
1154
+ data: {
1155
+ orderId,
1156
+ trackingNumber: fulfillmentData.trackingNumber,
1157
+ carrier: fulfillmentData.carrier,
1158
+ service: fulfillmentData.service,
1159
+ items: fulfillmentData.items,
1160
+ shippedAt: new Date(),
1161
+ estimatedDelivery: fulfillmentData.estimatedDelivery,
1162
+ },
1163
+ });
1164
+
1165
+ // Update order status
1166
+ await this.updateOrderStatus(orderId, OrderStatus.SHIPPED, {
1167
+ fulfillmentId: fulfillment.id,
1168
+ });
1169
+
1170
+ // Send shipping notification
1171
+ await this.sendShippingNotification(orderId, fulfillment);
1172
+
1173
+ return fulfillment;
1174
+ }
1175
+
1176
+ async processReturn(orderId: string, returnData: any): Promise<Return> {
1177
+ const order = await this.getOrder(orderId);
1178
+ if (!order) {
1179
+ throw new Error('Order not found');
1180
+ }
1181
+
1182
+ // Validate return request
1183
+ if (!this.isReturnEligible(order)) {
1184
+ throw new Error('Order is not eligible for return');
1185
+ }
1186
+
1187
+ // Create return record
1188
+ const returnRecord = await prisma.return.create({
1189
+ data: {
1190
+ orderId,
1191
+ items: returnData.items,
1192
+ reason: returnData.reason,
1193
+ status: 'pending',
1194
+ refundAmount: this.calculateRefundAmount(order, returnData.items),
1195
+ returnLabel: await this.generateReturnLabel(order),
1196
+ },
1197
+ });
1198
+
1199
+ // Send return instructions
1200
+ await this.sendReturnInstructions(order, returnRecord);
1201
+
1202
+ return returnRecord;
1203
+ }
1204
+
1205
+ async processRefund(orderId: string, amount: number, reason: string): Promise<Refund> {
1206
+ const order = await this.getOrder(orderId);
1207
+ if (!order) {
1208
+ throw new Error('Order not found');
1209
+ }
1210
+
1211
+ // Process refund through payment gateway
1212
+ let refundResult;
1213
+ if (order.payment.method === 'card' && order.payment.transactionId) {
1214
+ refundResult = await stripe.refunds.create({
1215
+ payment_intent: order.payment.transactionId,
1216
+ amount: Math.round(amount * 100),
1217
+ reason: 'requested_by_customer',
1218
+ });
1219
+ }
1220
+
1221
+ // Create refund record
1222
+ const refund = await prisma.refund.create({
1223
+ data: {
1224
+ orderId,
1225
+ amount,
1226
+ reason,
1227
+ status: refundResult?.status || 'completed',
1228
+ transactionId: refundResult?.id,
1229
+ processedAt: new Date(),
1230
+ },
1231
+ });
1232
+
1233
+ // Update order status if fully refunded
1234
+ const totalRefunded = await this.getTotalRefunded(orderId);
1235
+ if (totalRefunded >= order.total) {
1236
+ await this.updateOrderStatus(orderId, OrderStatus.REFUNDED);
1237
+ }
1238
+
1239
+ // Send refund confirmation
1240
+ await this.sendRefundConfirmation(order, refund);
1241
+
1242
+ return refund;
1243
+ }
1244
+
1245
+ private isReturnEligible(order: Order): boolean {
1246
+ // Check return policy (e.g., 30 days)
1247
+ const daysSinceOrder = (Date.now() - order.createdAt.getTime()) / (1000 * 60 * 60 * 24);
1248
+ return daysSinceOrder <= 30 && order.status === OrderStatus.DELIVERED;
1249
+ }
1250
+
1251
+ private calculateRefundAmount(order: Order, returnItems: any[]): number {
1252
+ let refundAmount = 0;
1253
+
1254
+ for (const returnItem of returnItems) {
1255
+ const orderItem = order.items.find(i => i.id === returnItem.itemId);
1256
+ if (orderItem) {
1257
+ refundAmount += orderItem.price * returnItem.quantity;
1258
+ }
1259
+ }
1260
+
1261
+ // Include proportional tax and shipping
1262
+ const refundPercentage = refundAmount / order.subtotal;
1263
+ refundAmount += order.tax * refundPercentage;
1264
+ refundAmount += order.shipping * refundPercentage;
1265
+
1266
+ return refundAmount;
1267
+ }
1268
+
1269
+ private async generateReturnLabel(order: Order): Promise<string> {
1270
+ // Generate return shipping label
1271
+ // Integration with shipping carriers
1272
+ return `RETURN_LABEL_${order.orderNumber}`;
1273
+ }
1274
+
1275
+ private async getTotalRefunded(orderId: string): Promise<number> {
1276
+ const refunds = await prisma.refund.findMany({
1277
+ where: { orderId },
1278
+ });
1279
+
1280
+ return refunds.reduce((sum, refund) => sum + refund.amount, 0);
1281
+ }
1282
+
1283
+ private async sendStatusNotification(order: Order) {
1284
+ await sqs.sendMessage({
1285
+ QueueUrl: process.env.EMAIL_QUEUE_URL!,
1286
+ MessageBody: JSON.stringify({
1287
+ type: 'order_status_update',
1288
+ to: order.email,
1289
+ orderId: order.id,
1290
+ orderNumber: order.orderNumber,
1291
+ status: order.status,
1292
+ }),
1293
+ }).promise();
1294
+ }
1295
+
1296
+ private async sendShippingNotification(orderId: string, fulfillment: Fulfillment) {
1297
+ const order = await this.getOrder(orderId);
1298
+
1299
+ await sqs.sendMessage({
1300
+ QueueUrl: process.env.EMAIL_QUEUE_URL!,
1301
+ MessageBody: JSON.stringify({
1302
+ type: 'shipping_confirmation',
1303
+ to: order!.email,
1304
+ orderId,
1305
+ orderNumber: order!.orderNumber,
1306
+ trackingNumber: fulfillment.trackingNumber,
1307
+ carrier: fulfillment.carrier,
1308
+ estimatedDelivery: fulfillment.estimatedDelivery,
1309
+ }),
1310
+ }).promise();
1311
+ }
1312
+
1313
+ private async sendReturnInstructions(order: Order, returnRecord: Return) {
1314
+ await sqs.sendMessage({
1315
+ QueueUrl: process.env.EMAIL_QUEUE_URL!,
1316
+ MessageBody: JSON.stringify({
1317
+ type: 'return_instructions',
1318
+ to: order.email,
1319
+ orderId: order.id,
1320
+ returnId: returnRecord.id,
1321
+ returnLabel: returnRecord.returnLabel,
1322
+ }),
1323
+ }).promise();
1324
+ }
1325
+
1326
+ private async sendRefundConfirmation(order: Order, refund: Refund) {
1327
+ await sqs.sendMessage({
1328
+ QueueUrl: process.env.EMAIL_QUEUE_URL!,
1329
+ MessageBody: JSON.stringify({
1330
+ type: 'refund_confirmation',
1331
+ to: order.email,
1332
+ orderId: order.id,
1333
+ orderNumber: order.orderNumber,
1334
+ refundAmount: refund.amount,
1335
+ refundReason: refund.reason,
1336
+ }),
1337
+ }).promise();
1338
+ }
1339
+ }
1340
+
1341
+ // Customer Service
1342
+ class CustomerService {
1343
+ async createAccount(data: any): Promise<Customer> {
1344
+ // Validate data
1345
+ const validated = this.validateCustomerData(data);
1346
+
1347
+ // Check if email already exists
1348
+ const existing = await prisma.customer.findUnique({
1349
+ where: { email: validated.email },
1350
+ });
1351
+
1352
+ if (existing) {
1353
+ throw new Error('Email already registered');
1354
+ }
1355
+
1356
+ // Hash password
1357
+ const hashedPassword = await bcrypt.hash(validated.password, 10);
1358
+
1359
+ // Create customer
1360
+ const customer = await prisma.customer.create({
1361
+ data: {
1362
+ email: validated.email,
1363
+ password: hashedPassword,
1364
+ firstName: validated.firstName,
1365
+ lastName: validated.lastName,
1366
+ phone: validated.phone,
1367
+ acceptsMarketing: validated.acceptsMarketing || false,
1368
+ verificationToken: uuidv4(),
1369
+ verified: false,
1370
+ },
1371
+ });
1372
+
1373
+ // Send verification email
1374
+ await this.sendVerificationEmail(customer);
1375
+
1376
+ // Subscribe to newsletter if opted in
1377
+ if (customer.acceptsMarketing) {
1378
+ await this.subscribeToNewsletter(customer.email);
1379
+ }
1380
+
1381
+ return customer;
1382
+ }
1383
+
1384
+ async login(email: string, password: string): Promise<{ customer: Customer; token: string }> {
1385
+ const customer = await prisma.customer.findUnique({
1386
+ where: { email },
1387
+ });
1388
+
1389
+ if (!customer) {
1390
+ throw new Error('Invalid credentials');
1391
+ }
1392
+
1393
+ const validPassword = await bcrypt.compare(password, customer.password);
1394
+ if (!validPassword) {
1395
+ throw new Error('Invalid credentials');
1396
+ }
1397
+
1398
+ if (!customer.verified) {
1399
+ throw new Error('Please verify your email');
1400
+ }
1401
+
1402
+ // Generate JWT token
1403
+ const token = jwt.sign(
1404
+ {
1405
+ customerId: customer.id,
1406
+ email: customer.email,
1407
+ },
1408
+ process.env.JWT_SECRET!,
1409
+ { expiresIn: '7d' }
1410
+ );
1411
+
1412
+ // Update last login
1413
+ await prisma.customer.update({
1414
+ where: { id: customer.id },
1415
+ data: { lastLogin: new Date() },
1416
+ });
1417
+
1418
+ return { customer, token };
1419
+ }
1420
+
1421
+ async addToWishlist(customerId: string, productId: string): Promise<void> {
1422
+ await prisma.wishlist.create({
1423
+ data: {
1424
+ customerId,
1425
+ productId,
1426
+ },
1427
+ });
1428
+ }
1429
+
1430
+ async getRecommendations(customerId: string): Promise<Product[]> {
1431
+ // Get customer's purchase history
1432
+ const orders = await prisma.order.findMany({
1433
+ where: { customerId },
1434
+ include: { items: true },
1435
+ orderBy: { createdAt: 'desc' },
1436
+ take: 10,
1437
+ });
1438
+
1439
+ // Get customer's browsing history
1440
+ const browsingHistory = await redis.lrange(`browsing:${customerId}`, 0, 20);
1441
+
1442
+ // Get customer's wishlist
1443
+ const wishlist = await prisma.wishlist.findMany({
1444
+ where: { customerId },
1445
+ select: { productId: true },
1446
+ });
1447
+
1448
+ // Generate personalized recommendations
1449
+ // This would use a recommendation engine (collaborative filtering, content-based, etc.)
1450
+ const recommendations = await this.generatePersonalizedRecommendations({
1451
+ orders,
1452
+ browsingHistory,
1453
+ wishlist,
1454
+ });
1455
+
1456
+ return recommendations;
1457
+ }
1458
+
1459
+ private validateCustomerData(data: any) {
1460
+ const schema = z.object({
1461
+ email: z.string().email(),
1462
+ password: z.string().min(8),
1463
+ firstName: z.string(),
1464
+ lastName: z.string(),
1465
+ phone: z.string().optional(),
1466
+ acceptsMarketing: z.boolean().optional(),
1467
+ });
1468
+
1469
+ return schema.parse(data);
1470
+ }
1471
+
1472
+ private async sendVerificationEmail(customer: Customer) {
1473
+ await sqs.sendMessage({
1474
+ QueueUrl: process.env.EMAIL_QUEUE_URL!,
1475
+ MessageBody: JSON.stringify({
1476
+ type: 'email_verification',
1477
+ to: customer.email,
1478
+ customerId: customer.id,
1479
+ verificationToken: customer.verificationToken,
1480
+ }),
1481
+ }).promise();
1482
+ }
1483
+
1484
+ private async subscribeToNewsletter(email: string) {
1485
+ // Add to mailing list (e.g., Mailchimp, SendGrid)
1486
+ await sqs.sendMessage({
1487
+ QueueUrl: process.env.MARKETING_QUEUE_URL!,
1488
+ MessageBody: JSON.stringify({
1489
+ action: 'subscribe',
1490
+ email,
1491
+ list: 'newsletter',
1492
+ }),
1493
+ }).promise();
1494
+ }
1495
+
1496
+ private async generatePersonalizedRecommendations(data: any): Promise<Product[]> {
1497
+ // Simplified recommendation logic
1498
+ // In production, this would use ML models
1499
+
1500
+ const productIds = new Set<string>();
1501
+
1502
+ // Add products from same categories as purchased items
1503
+ for (const order of data.orders) {
1504
+ for (const item of order.items) {
1505
+ const product = await prisma.product.findUnique({
1506
+ where: { id: item.productId },
1507
+ include: { categories: true },
1508
+ });
1509
+
1510
+ if (product) {
1511
+ const related = await prisma.product.findMany({
1512
+ where: {
1513
+ categories: {
1514
+ some: {
1515
+ id: { in: product.categories.map(c => c.id) },
1516
+ },
1517
+ },
1518
+ id: { not: product.id },
1519
+ },
1520
+ take: 3,
1521
+ });
1522
+
1523
+ related.forEach(p => productIds.add(p.id));
1524
+ }
1525
+ }
1526
+ }
1527
+
1528
+ // Add trending products
1529
+ const trending = await prisma.product.findMany({
1530
+ where: {
1531
+ status: 'active',
1532
+ id: { notIn: Array.from(productIds) },
1533
+ },
1534
+ orderBy: { salesCount: 'desc' },
1535
+ take: 5,
1536
+ });
1537
+
1538
+ trending.forEach(p => productIds.add(p.id));
1539
+
1540
+ // Fetch full product details
1541
+ return prisma.product.findMany({
1542
+ where: { id: { in: Array.from(productIds) } },
1543
+ include: { images: true },
1544
+ take: 12,
1545
+ });
1546
+ }
1547
+ }
1548
+
1549
+ // Type definitions
1550
+ interface Cart {
1551
+ id: string;
1552
+ sessionId: string;
1553
+ customerId?: string;
1554
+ items: CartItem[];
1555
+ subtotal: number;
1556
+ tax: number;
1557
+ shipping: number;
1558
+ discount: number;
1559
+ total: number;
1560
+ discountCode?: string;
1561
+ createdAt: Date;
1562
+ updatedAt: Date;
1563
+ }
1564
+
1565
+ interface Checkout {
1566
+ id: string;
1567
+ sessionId: string;
1568
+ cart: Cart;
1569
+ email: string;
1570
+ shippingAddress: Address;
1571
+ billingAddress: Address;
1572
+ shippingMethod: string;
1573
+ shipping: number;
1574
+ tax: number;
1575
+ total: number;
1576
+ status: string;
1577
+ expiresAt: Date;
1578
+ createdAt: Date;
1579
+ }
1580
+
1581
+ interface Address {
1582
+ name: string;
1583
+ line1: string;
1584
+ line2?: string;
1585
+ city: string;
1586
+ state: string;
1587
+ postalCode: string;
1588
+ country: string;
1589
+ phone?: string;
1590
+ }
1591
+
1592
+ interface OrderItem {
1593
+ id: string;
1594
+ orderId: string;
1595
+ productId: string;
1596
+ variantId?: string;
1597
+ quantity: number;
1598
+ price: number;
1599
+ total: number;
1600
+ product?: Product;
1601
+ variant?: ProductVariant;
1602
+ }
1603
+
1604
+ interface PaymentInfo {
1605
+ method: string;
1606
+ transactionId: string;
1607
+ amount: number;
1608
+ status: string;
1609
+ }
1610
+
1611
+ interface FulfillmentInfo {
1612
+ status: string;
1613
+ trackingNumber?: string;
1614
+ carrier?: string;
1615
+ shippedAt?: Date;
1616
+ deliveredAt?: Date;
1617
+ }
1618
+
1619
+ interface Fulfillment {
1620
+ id: string;
1621
+ orderId: string;
1622
+ trackingNumber: string;
1623
+ carrier: string;
1624
+ service: string;
1625
+ items: any[];
1626
+ shippedAt: Date;
1627
+ estimatedDelivery?: Date;
1628
+ deliveredAt?: Date;
1629
+ }
1630
+
1631
+ interface Return {
1632
+ id: string;
1633
+ orderId: string;
1634
+ items: any[];
1635
+ reason: string;
1636
+ status: string;
1637
+ refundAmount: number;
1638
+ returnLabel: string;
1639
+ receivedAt?: Date;
1640
+ }
1641
+
1642
+ interface Refund {
1643
+ id: string;
1644
+ orderId: string;
1645
+ amount: number;
1646
+ reason: string;
1647
+ status: string;
1648
+ transactionId?: string;
1649
+ processedAt: Date;
1650
+ }
1651
+
1652
+ interface Customer {
1653
+ id: string;
1654
+ email: string;
1655
+ password: string;
1656
+ firstName: string;
1657
+ lastName: string;
1658
+ phone?: string;
1659
+ acceptsMarketing: boolean;
1660
+ verificationToken?: string;
1661
+ verified: boolean;
1662
+ lastLogin?: Date;
1663
+ createdAt: Date;
1664
+ }
1665
+
1666
+ interface ProductImage {
1667
+ id: string;
1668
+ url: string;
1669
+ alt?: string;
1670
+ position: number;
1671
+ }
1672
+
1673
+ interface Category {
1674
+ id: string;
1675
+ name: string;
1676
+ slug: string;
1677
+ parentId?: string;
1678
+ }
1679
+
1680
+ interface InventoryLocation {
1681
+ locationId: string;
1682
+ quantity: number;
1683
+ }
1684
+
1685
+ interface Dimensions {
1686
+ length: number;
1687
+ width: number;
1688
+ height: number;
1689
+ unit: string;
1690
+ }
1691
+
1692
+ interface SEOData {
1693
+ title: string;
1694
+ description: string;
1695
+ keywords?: string[];
1696
+ }
1697
+
1698
+ // Export services
1699
+ export {
1700
+ ProductCatalogService,
1701
+ ShoppingCartService,
1702
+ CheckoutService,
1703
+ OrderManagementService,
1704
+ CustomerService,
1705
+ };
1706
+ ```
1707
+
1708
+ ## Best Practices
1709
+
1710
+ ### 1. Performance Optimization
1711
+ - Implement caching strategies (Redis, CDN)
1712
+ - Use database indexing and query optimization
1713
+ - Implement lazy loading and pagination
1714
+ - Optimize images and assets
1715
+ - Use async processing for heavy operations
1716
+
1717
+ ### 2. Security
1718
+ - PCI DSS compliance for payment processing
1719
+ - Secure session management
1720
+ - Input validation and sanitization
1721
+ - Rate limiting and DDoS protection
1722
+ - Regular security audits
1723
+
1724
+ ### 3. Scalability
1725
+ - Microservices architecture for large platforms
1726
+ - Message queuing for async processing
1727
+ - Database sharding for large catalogs
1728
+ - Load balancing and auto-scaling
1729
+ - Content delivery networks (CDN)
1730
+
1731
+ ### 4. User Experience
1732
+ - Fast page load times (< 3 seconds)
1733
+ - Mobile-responsive design
1734
+ - Intuitive navigation and search
1735
+ - Guest checkout options
1736
+ - Multiple payment methods
1737
+
1738
+ ### 5. Conversion Optimization
1739
+ - A/B testing for layouts and features
1740
+ - Abandoned cart recovery
1741
+ - Personalized recommendations
1742
+ - Social proof (reviews, ratings)
1743
+ - Clear return policies
1744
+
1745
+ ## Common Patterns
1746
+
1747
+ 1. **Shopping Cart**: Session-based or persistent cart management
1748
+ 2. **Inventory Reservation**: Temporary stock reservation during checkout
1749
+ 3. **Order State Machine**: Managing order lifecycle and transitions
1750
+ 4. **Payment Gateway Integration**: Abstract payment processing
1751
+ 5. **Webhook Handling**: Real-time updates from external services
1752
+ 6. **Event Sourcing**: Track all changes for audit and analytics
1753
+ 7. **CQRS**: Separate read/write models for performance
1754
+ 8. **Saga Pattern**: Distributed transaction management
1755
+
1756
+ Remember: E-commerce requires careful attention to performance, security, and user experience. Always prioritize customer data protection and payment security while optimizing for conversions and scalability.