@llm4ts/shell 0.17.0 → 0.18.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (269) hide show
  1. package/dist/Cli.d.ts +4 -0
  2. package/dist/Cli.d.ts.map +1 -1
  3. package/dist/Cli.js +69 -8
  4. package/dist/Cli.js.map +1 -1
  5. package/dist/FlowCatalog.d.ts +10 -4
  6. package/dist/FlowCatalog.d.ts.map +1 -1
  7. package/dist/FlowCatalog.js +25 -14
  8. package/dist/FlowCatalog.js.map +1 -1
  9. package/flows/epic-stories.js +1 -8
  10. package/flows/hello.js +15 -0
  11. package/flows/implement.js +1 -8
  12. package/flows/issue-pr.js +1 -8
  13. package/flows/judge-suite.js +1 -4
  14. package/flows/lib/epic-stories.js +3 -4
  15. package/flows/local.js +2 -5
  16. package/flows/modernize-bench.js +3 -12
  17. package/flows/modernize-extract.js +38 -20
  18. package/flows/modernize-implement.js +4 -15
  19. package/flows/modernize-pack-check.js +1 -8
  20. package/flows/modernize-review.js +4 -13
  21. package/flows/modernize-seed.js +3 -11
  22. package/flows/modernize-survey.js +0 -0
  23. package/flows/modernize-verify.js +5 -13
  24. package/flows/sdd.js +2 -12
  25. package/kits/j2ee-nextjs/README.md +29 -0
  26. package/kits/j2ee-nextjs/fixtures/demo-bank/RUNBOOK.md +232 -0
  27. package/kits/j2ee-nextjs/fixtures/demo-bank/legacy-j2ee/PAGES.md +67 -0
  28. package/kits/j2ee-nextjs/fixtures/demo-bank/legacy-j2ee/pom.xml +49 -0
  29. package/kits/j2ee-nextjs/fixtures/demo-bank/legacy-j2ee/src/main/java/com/demobank/legacy/dto/AcctOvwDTO.java +58 -0
  30. package/kits/j2ee-nextjs/fixtures/demo-bank/legacy-j2ee/src/main/java/com/demobank/legacy/dto/BenfDTO.java +49 -0
  31. package/kits/j2ee-nextjs/fixtures/demo-bank/legacy-j2ee/src/main/java/com/demobank/legacy/dto/TrfDTO.java +70 -0
  32. package/kits/j2ee-nextjs/fixtures/demo-bank/legacy-j2ee/src/main/java/com/demobank/legacy/esb/EsbAcctListService.java +53 -0
  33. package/kits/j2ee-nextjs/fixtures/demo-bank/legacy-j2ee/src/main/java/com/demobank/legacy/esb/EsbBenfListService.java +58 -0
  34. package/kits/j2ee-nextjs/fixtures/demo-bank/legacy-j2ee/src/main/java/com/demobank/legacy/esb/EsbBenfMaintService.java +58 -0
  35. package/kits/j2ee-nextjs/fixtures/demo-bank/legacy-j2ee/src/main/java/com/demobank/legacy/esb/EsbException.java +21 -0
  36. package/kits/j2ee-nextjs/fixtures/demo-bank/legacy-j2ee/src/main/java/com/demobank/legacy/esb/EsbGateway.java +44 -0
  37. package/kits/j2ee-nextjs/fixtures/demo-bank/legacy-j2ee/src/main/java/com/demobank/legacy/esb/EsbTrfExecService.java +53 -0
  38. package/kits/j2ee-nextjs/fixtures/demo-bank/legacy-j2ee/src/main/java/com/demobank/legacy/esb/EsbTrfValidateService.java +45 -0
  39. package/kits/j2ee-nextjs/fixtures/demo-bank/legacy-j2ee/src/main/java/com/demobank/legacy/web/AccountOverviewServlet.java +90 -0
  40. package/kits/j2ee-nextjs/fixtures/demo-bank/legacy-j2ee/src/main/java/com/demobank/legacy/web/BeneficiaryServlet.java +195 -0
  41. package/kits/j2ee-nextjs/fixtures/demo-bank/legacy-j2ee/src/main/java/com/demobank/legacy/web/TransferDraft.java +62 -0
  42. package/kits/j2ee-nextjs/fixtures/demo-bank/legacy-j2ee/src/main/java/com/demobank/legacy/web/TransferServlet.java +223 -0
  43. package/kits/j2ee-nextjs/fixtures/demo-bank/legacy-j2ee/src/main/webapp/WEB-INF/web.xml +59 -0
  44. package/kits/j2ee-nextjs/fixtures/demo-bank/legacy-j2ee/src/main/webapp/accountOverview.jsp +65 -0
  45. package/kits/j2ee-nextjs/fixtures/demo-bank/legacy-j2ee/src/main/webapp/beneficiaryEdit.jsp +70 -0
  46. package/kits/j2ee-nextjs/fixtures/demo-bank/legacy-j2ee/src/main/webapp/beneficiaryList.jsp +43 -0
  47. package/kits/j2ee-nextjs/fixtures/demo-bank/legacy-j2ee/src/main/webapp/css/bank.css +132 -0
  48. package/kits/j2ee-nextjs/fixtures/demo-bank/legacy-j2ee/src/main/webapp/dashboard.jsp +28 -0
  49. package/kits/j2ee-nextjs/fixtures/demo-bank/legacy-j2ee/src/main/webapp/footer.jsp +8 -0
  50. package/kits/j2ee-nextjs/fixtures/demo-bank/legacy-j2ee/src/main/webapp/header.jsp +22 -0
  51. package/kits/j2ee-nextjs/fixtures/demo-bank/legacy-j2ee/src/main/webapp/help.jsp +32 -0
  52. package/kits/j2ee-nextjs/fixtures/demo-bank/legacy-j2ee/src/main/webapp/js/jquery-1.12.4.min.js +1 -0
  53. package/kits/j2ee-nextjs/fixtures/demo-bank/legacy-j2ee/src/main/webapp/js/validate.js +79 -0
  54. package/kits/j2ee-nextjs/fixtures/demo-bank/legacy-j2ee/src/main/webapp/login.jsp +29 -0
  55. package/kits/j2ee-nextjs/fixtures/demo-bank/legacy-j2ee/src/main/webapp/messages.jsp +34 -0
  56. package/kits/j2ee-nextjs/fixtures/demo-bank/legacy-j2ee/src/main/webapp/nav.jsp +14 -0
  57. package/kits/j2ee-nextjs/fixtures/demo-bank/legacy-j2ee/src/main/webapp/oldTransfer.jsp +34 -0
  58. package/kits/j2ee-nextjs/fixtures/demo-bank/legacy-j2ee/src/main/webapp/profile.jsp +26 -0
  59. package/kits/j2ee-nextjs/fixtures/demo-bank/legacy-j2ee/src/main/webapp/promoQ3.jsp +23 -0
  60. package/kits/j2ee-nextjs/fixtures/demo-bank/legacy-j2ee/src/main/webapp/settings.jsp +34 -0
  61. package/kits/j2ee-nextjs/fixtures/demo-bank/legacy-j2ee/src/main/webapp/testHarness.jsp +39 -0
  62. package/kits/j2ee-nextjs/fixtures/demo-bank/legacy-j2ee/src/main/webapp/transferConfirm.jsp +35 -0
  63. package/kits/j2ee-nextjs/fixtures/demo-bank/legacy-j2ee/src/main/webapp/transferStep1.jsp +73 -0
  64. package/kits/j2ee-nextjs/fixtures/demo-bank/legacy-j2ee/src/main/webapp/transferStep2.jsp +40 -0
  65. package/kits/j2ee-nextjs/fixtures/demo-bank/nextjs/CONTRIBUTING.md +76 -0
  66. package/kits/j2ee-nextjs/fixtures/demo-bank/nextjs/README.md +46 -0
  67. package/kits/j2ee-nextjs/fixtures/demo-bank/nextjs/contracts/cards.openapi.yaml +57 -0
  68. package/kits/j2ee-nextjs/fixtures/demo-bank/nextjs/contracts/profile.openapi.yaml +73 -0
  69. package/kits/j2ee-nextjs/fixtures/demo-bank/nextjs/eslint.config.mjs +24 -0
  70. package/kits/j2ee-nextjs/fixtures/demo-bank/nextjs/next-env.d.ts +5 -0
  71. package/kits/j2ee-nextjs/fixtures/demo-bank/nextjs/next.config.mjs +10 -0
  72. package/kits/j2ee-nextjs/fixtures/demo-bank/nextjs/package.json +29 -0
  73. package/kits/j2ee-nextjs/fixtures/demo-bank/nextjs/pnpm-lock.yaml +2895 -0
  74. package/kits/j2ee-nextjs/fixtures/demo-bank/nextjs/src/app/cards/page.tsx +62 -0
  75. package/kits/j2ee-nextjs/fixtures/demo-bank/nextjs/src/app/layout.tsx +41 -0
  76. package/kits/j2ee-nextjs/fixtures/demo-bank/nextjs/src/app/page.tsx +26 -0
  77. package/kits/j2ee-nextjs/fixtures/demo-bank/nextjs/src/app/profile/page.tsx +134 -0
  78. package/kits/j2ee-nextjs/fixtures/demo-bank/nextjs/src/app/signed-in-badge.tsx +9 -0
  79. package/kits/j2ee-nextjs/fixtures/demo-bank/nextjs/src/auth/AuthProvider.tsx +36 -0
  80. package/kits/j2ee-nextjs/fixtures/demo-bank/nextjs/src/components/Button.tsx +27 -0
  81. package/kits/j2ee-nextjs/fixtures/demo-bank/nextjs/src/components/Card.tsx +18 -0
  82. package/kits/j2ee-nextjs/fixtures/demo-bank/nextjs/src/components/DataTable.tsx +57 -0
  83. package/kits/j2ee-nextjs/fixtures/demo-bank/nextjs/src/components/Field.tsx +34 -0
  84. package/kits/j2ee-nextjs/fixtures/demo-bank/nextjs/src/components/Form.tsx +70 -0
  85. package/kits/j2ee-nextjs/fixtures/demo-bank/nextjs/src/components/PageLayout.tsx +39 -0
  86. package/kits/j2ee-nextjs/fixtures/demo-bank/nextjs/src/components/Stepper.tsx +29 -0
  87. package/kits/j2ee-nextjs/fixtures/demo-bank/nextjs/src/components/index.ts +19 -0
  88. package/kits/j2ee-nextjs/fixtures/demo-bank/nextjs/src/services/cards/mock.ts +47 -0
  89. package/kits/j2ee-nextjs/fixtures/demo-bank/nextjs/src/services/cards/port.ts +31 -0
  90. package/kits/j2ee-nextjs/fixtures/demo-bank/nextjs/src/services/profile/mock.ts +45 -0
  91. package/kits/j2ee-nextjs/fixtures/demo-bank/nextjs/src/services/profile/port.ts +24 -0
  92. package/kits/j2ee-nextjs/fixtures/demo-bank/nextjs/src/services/registry.ts +20 -0
  93. package/kits/j2ee-nextjs/fixtures/demo-bank/nextjs/src/theme/components.css +269 -0
  94. package/kits/j2ee-nextjs/fixtures/demo-bank/nextjs/src/theme/tokens.css +38 -0
  95. package/kits/j2ee-nextjs/fixtures/demo-bank/nextjs/tests/cards.page.test.tsx +81 -0
  96. package/kits/j2ee-nextjs/fixtures/demo-bank/nextjs/tests/profile.page.test.tsx +87 -0
  97. package/kits/j2ee-nextjs/fixtures/demo-bank/nextjs/tsconfig.json +54 -0
  98. package/kits/j2ee-nextjs/fixtures/demo-bank/nextjs/vitest.config.ts +17 -0
  99. package/kits/j2ee-nextjs/fixtures/demo-bank/preflight.mjs +53 -0
  100. package/kits/j2ee-nextjs/fixtures/demo-bank/reset-demo.mjs +40 -0
  101. package/kits/j2ee-nextjs/fixtures/demo-bank/seed-legacy-j2ee.mjs +71 -0
  102. package/kits/j2ee-nextjs/fixtures/demo-bank/seed-nextjs.mjs +111 -0
  103. package/kits/j2ee-nextjs/fixtures/demo-bank/smoke-legacy-j2ee.mjs +144 -0
  104. package/kits/j2ee-nextjs/fixtures/demo-bank/smoke-nextjs.mjs +118 -0
  105. package/{flows → kits/j2ee-nextjs/flows}/convert-all.js +1 -7
  106. package/{flows → kits/j2ee-nextjs/flows}/convert-page.js +2 -6
  107. package/{flows → kits/j2ee-nextjs/flows}/lib/convert.js +6 -16
  108. package/{flows → kits/j2ee-nextjs}/packs/j2ee-nextjs-spa/pack.md +2 -1
  109. package/{flows → kits/j2ee-nextjs}/packs/j2ee-nextjs-spa/prompts/spec.md +5 -1
  110. package/{flows → kits/j2ee-nextjs}/packs/jsp-bff-nextjs/pack.md +1 -1
  111. package/{flows → kits/j2ee-nextjs}/packs/jsp-nextjs/pack.md +1 -1
  112. package/kits/mainframe-java/README.md +31 -0
  113. package/{flows → kits/mainframe-java}/packs/ace-integration/pack.md +1 -1
  114. package/{flows → kits/mainframe-java}/packs/ace-kafka/pack.md +1 -1
  115. package/{flows → kits/mainframe-java}/packs/cobol-kafka/pack.md +1 -1
  116. package/{flows → kits/mainframe-java}/packs/cobol-springboot/pack.md +1 -1
  117. package/package.json +6 -6
  118. package/src/Cli.ts +92 -9
  119. package/src/FlowCatalog.ts +29 -13
  120. /package/{flows → kits/j2ee-nextjs}/packs/j2ee-nextjs-spa/patterns/PAT-J2EE-001-jstl-table.md +0 -0
  121. /package/{flows → kits/j2ee-nextjs}/packs/j2ee-nextjs-spa/patterns/PAT-J2EE-002-jquery-validation.md +0 -0
  122. /package/{flows → kits/j2ee-nextjs}/packs/j2ee-nextjs-spa/patterns/PAT-J2EE-003-session-stepper.md +0 -0
  123. /package/{flows → kits/j2ee-nextjs}/packs/j2ee-nextjs-spa/patterns/PAT-J2EE-004-esb-port.md +0 -0
  124. /package/{flows → kits/j2ee-nextjs}/packs/j2ee-nextjs-spa/patterns/PAT-J2EE-005-include-shell.md +0 -0
  125. /package/{flows → kits/j2ee-nextjs}/packs/j2ee-nextjs-spa/prompts/analysis.md +0 -0
  126. /package/{flows → kits/j2ee-nextjs}/packs/j2ee-nextjs-spa/prompts/bdd.md +0 -0
  127. /package/{flows → kits/j2ee-nextjs}/packs/j2ee-nextjs-spa/prompts/implement.md +0 -0
  128. /package/{flows → kits/j2ee-nextjs}/packs/j2ee-nextjs-spa/prompts/plan.md +0 -0
  129. /package/{flows → kits/j2ee-nextjs}/packs/j2ee-nextjs-spa/prompts/review.md +0 -0
  130. /package/{flows → kits/j2ee-nextjs}/packs/j2ee-nextjs-spa/prompts/survey-refine.md +0 -0
  131. /package/{flows → kits/j2ee-nextjs}/packs/j2ee-nextjs-spa/prompts/survey-triage.md +0 -0
  132. /package/{flows → kits/j2ee-nextjs}/packs/j2ee-nextjs-spa/reviewers/acl-purity.md +0 -0
  133. /package/{flows → kits/j2ee-nextjs}/packs/j2ee-nextjs-spa/reviewers/house-style.md +0 -0
  134. /package/{flows → kits/j2ee-nextjs}/packs/jsp-bff-nextjs/lessons.md +0 -0
  135. /package/{flows → kits/j2ee-nextjs}/packs/jsp-bff-nextjs/prompts/analysis.md +0 -0
  136. /package/{flows → kits/j2ee-nextjs}/packs/jsp-bff-nextjs/prompts/bdd.md +0 -0
  137. /package/{flows → kits/j2ee-nextjs}/packs/jsp-bff-nextjs/prompts/implement.md +0 -0
  138. /package/{flows → kits/j2ee-nextjs}/packs/jsp-bff-nextjs/prompts/plan.md +0 -0
  139. /package/{flows → kits/j2ee-nextjs}/packs/jsp-bff-nextjs/prompts/review.md +0 -0
  140. /package/{flows → kits/j2ee-nextjs}/packs/jsp-bff-nextjs/prompts/spec.md +0 -0
  141. /package/{flows → kits/j2ee-nextjs}/packs/jsp-bff-nextjs/prompts/survey-refine.md +0 -0
  142. /package/{flows → kits/j2ee-nextjs}/packs/jsp-bff-nextjs/prompts/survey-triage.md +0 -0
  143. /package/{flows → kits/j2ee-nextjs}/packs/jsp-bff-nextjs/reviewers/bff-boundary.md +0 -0
  144. /package/{flows/packs/ace-integration → kits/j2ee-nextjs/packs/jsp-bff-nextjs}/reviewers/traceability.md +0 -0
  145. /package/{flows → kits/j2ee-nextjs}/packs/jsp-nextjs/lessons.md +0 -0
  146. /package/{flows → kits/j2ee-nextjs}/packs/jsp-nextjs/prompts/analysis.md +0 -0
  147. /package/{flows → kits/j2ee-nextjs}/packs/jsp-nextjs/prompts/bdd.md +0 -0
  148. /package/{flows → kits/j2ee-nextjs}/packs/jsp-nextjs/prompts/implement.md +0 -0
  149. /package/{flows → kits/j2ee-nextjs}/packs/jsp-nextjs/prompts/plan.md +0 -0
  150. /package/{flows → kits/j2ee-nextjs}/packs/jsp-nextjs/prompts/review.md +0 -0
  151. /package/{flows → kits/j2ee-nextjs}/packs/jsp-nextjs/prompts/spec.md +0 -0
  152. /package/{flows → kits/j2ee-nextjs}/packs/jsp-nextjs/prompts/survey-refine.md +0 -0
  153. /package/{flows → kits/j2ee-nextjs}/packs/jsp-nextjs/prompts/survey-triage.md +0 -0
  154. /package/{flows/packs/ace-kafka → kits/j2ee-nextjs/packs/jsp-nextjs}/reviewers/traceability.md +0 -0
  155. /package/{flows → kits/j2ee-nextjs}/packs/jsp-nextjs/reviewers/ux-fidelity.md +0 -0
  156. /package/{flows/fixtures → kits/j2ee-nextjs}/scaffolds/nextjs-spa/README.md +0 -0
  157. /package/{flows/fixtures → kits/j2ee-nextjs}/scaffolds/nextjs-spa/app/layout.js +0 -0
  158. /package/{flows/fixtures → kits/j2ee-nextjs}/scaffolds/nextjs-spa/app/page.js +0 -0
  159. /package/{flows/fixtures/scaffolds/kafka-streams-service/src/test/resources/features → kits/j2ee-nextjs/scaffolds/nextjs-spa/docs/specs}/.gitkeep +0 -0
  160. /package/{flows/fixtures/scaffolds/nextjs-spa/docs/specs → kits/j2ee-nextjs/scaffolds/nextjs-spa/features}/.gitkeep +0 -0
  161. /package/{flows/fixtures → kits/j2ee-nextjs}/scaffolds/nextjs-spa/next.config.js +0 -0
  162. /package/{flows/fixtures → kits/j2ee-nextjs}/scaffolds/nextjs-spa/package.json +0 -0
  163. /package/{flows/fixtures → kits/j2ee-nextjs}/scaffolds/nextjs-spa/tests/smoke.test.js +0 -0
  164. /package/{flows/fixtures → kits/j2ee-nextjs}/scaffolds/spring-bff/README.md +0 -0
  165. /package/{flows/fixtures → kits/j2ee-nextjs}/scaffolds/spring-bff/frontend/app/layout.js +0 -0
  166. /package/{flows/fixtures → kits/j2ee-nextjs}/scaffolds/spring-bff/frontend/app/page.js +0 -0
  167. /package/{flows/fixtures → kits/j2ee-nextjs}/scaffolds/spring-bff/frontend/next.config.js +0 -0
  168. /package/{flows/fixtures → kits/j2ee-nextjs}/scaffolds/spring-bff/frontend/package.json +0 -0
  169. /package/{flows/fixtures → kits/j2ee-nextjs}/scaffolds/spring-bff/frontend/tests/smoke.test.js +0 -0
  170. /package/{flows/fixtures → kits/j2ee-nextjs}/scaffolds/spring-bff/pom.xml +0 -0
  171. /package/{flows/fixtures → kits/j2ee-nextjs}/scaffolds/spring-bff/scripts/test.sh +0 -0
  172. /package/{flows/fixtures → kits/j2ee-nextjs}/scaffolds/spring-bff/src/main/java/com/meridian/bff/Application.java +0 -0
  173. /package/{flows/fixtures → kits/j2ee-nextjs}/scaffolds/spring-bff/src/main/resources/application.yaml +0 -0
  174. /package/{flows/fixtures → kits/j2ee-nextjs}/scaffolds/spring-bff/src/test/java/com/meridian/bff/ApplicationTests.java +0 -0
  175. /package/{flows/fixtures/scaffolds/nextjs-spa → kits/j2ee-nextjs/scaffolds/spring-bff/src/test/resources}/features/.gitkeep +0 -0
  176. /package/{flows → kits/mainframe-java}/packs/ace-integration/lessons.md +0 -0
  177. /package/{flows → kits/mainframe-java}/packs/ace-integration/prompts/analysis.md +0 -0
  178. /package/{flows → kits/mainframe-java}/packs/ace-integration/prompts/bdd.md +0 -0
  179. /package/{flows → kits/mainframe-java}/packs/ace-integration/prompts/implement.md +0 -0
  180. /package/{flows → kits/mainframe-java}/packs/ace-integration/prompts/plan.md +0 -0
  181. /package/{flows → kits/mainframe-java}/packs/ace-integration/prompts/review.md +0 -0
  182. /package/{flows → kits/mainframe-java}/packs/ace-integration/prompts/spec.md +0 -0
  183. /package/{flows → kits/mainframe-java}/packs/ace-integration/reviewers/routing-fidelity.md +0 -0
  184. /package/{flows/packs/cobol-kafka → kits/mainframe-java/packs/ace-integration}/reviewers/traceability.md +0 -0
  185. /package/{flows → kits/mainframe-java}/packs/ace-kafka/lessons.md +0 -0
  186. /package/{flows → kits/mainframe-java}/packs/ace-kafka/prompts/analysis.md +0 -0
  187. /package/{flows → kits/mainframe-java}/packs/ace-kafka/prompts/bdd.md +0 -0
  188. /package/{flows → kits/mainframe-java}/packs/ace-kafka/prompts/implement.md +0 -0
  189. /package/{flows → kits/mainframe-java}/packs/ace-kafka/prompts/plan.md +0 -0
  190. /package/{flows → kits/mainframe-java}/packs/ace-kafka/prompts/review.md +0 -0
  191. /package/{flows → kits/mainframe-java}/packs/ace-kafka/prompts/spec.md +0 -0
  192. /package/{flows → kits/mainframe-java}/packs/ace-kafka/prompts/vectors.md +0 -0
  193. /package/{flows → kits/mainframe-java}/packs/ace-kafka/reviewers/event-contracts.md +0 -0
  194. /package/{flows → kits/mainframe-java}/packs/ace-kafka/reviewers/routing-fidelity.md +0 -0
  195. /package/{flows/packs/cobol-springboot → kits/mainframe-java/packs/ace-kafka}/reviewers/traceability.md +0 -0
  196. /package/{flows → kits/mainframe-java}/packs/cobol-kafka/lessons.md +0 -0
  197. /package/{flows → kits/mainframe-java}/packs/cobol-kafka/patterns/PAT-STREAM-001-record-to-event.md +0 -0
  198. /package/{flows → kits/mainframe-java}/packs/cobol-kafka/patterns/PAT-STREAM-002-job-step-topology.md +0 -0
  199. /package/{flows → kits/mainframe-java}/packs/cobol-kafka/patterns/PAT-STREAM-003-checkpoint-idempotence.md +0 -0
  200. /package/{flows → kits/mainframe-java}/packs/cobol-kafka/patterns/PAT-STREAM-004-eod-totals-window.md +0 -0
  201. /package/{flows → kits/mainframe-java}/packs/cobol-kafka/patterns/PAT-STREAM-005-reject-topic.md +0 -0
  202. /package/{flows → kits/mainframe-java}/packs/cobol-kafka/patterns/PAT-STREAM-006-keyed-state-store.md +0 -0
  203. /package/{flows → kits/mainframe-java}/packs/cobol-kafka/patterns/PAT-STREAM-007-outbox.md +0 -0
  204. /package/{flows → kits/mainframe-java}/packs/cobol-kafka/patterns/PAT-STREAM-008-partition-key.md +0 -0
  205. /package/{flows → kits/mainframe-java}/packs/cobol-kafka/patterns/PAT-STREAM-009-batch-window-cutoff.md +0 -0
  206. /package/{flows → kits/mainframe-java}/packs/cobol-kafka/patterns/PAT-STREAM-010-replay-backfill.md +0 -0
  207. /package/{flows → kits/mainframe-java}/packs/cobol-kafka/prompts/analysis.md +0 -0
  208. /package/{flows → kits/mainframe-java}/packs/cobol-kafka/prompts/bdd.md +0 -0
  209. /package/{flows → kits/mainframe-java}/packs/cobol-kafka/prompts/implement.md +0 -0
  210. /package/{flows → kits/mainframe-java}/packs/cobol-kafka/prompts/plan.md +0 -0
  211. /package/{flows → kits/mainframe-java}/packs/cobol-kafka/prompts/review.md +0 -0
  212. /package/{flows → kits/mainframe-java}/packs/cobol-kafka/prompts/spec.md +0 -0
  213. /package/{flows → kits/mainframe-java}/packs/cobol-kafka/prompts/survey-refine.md +0 -0
  214. /package/{flows → kits/mainframe-java}/packs/cobol-kafka/prompts/survey-triage.md +0 -0
  215. /package/{flows → kits/mainframe-java}/packs/cobol-kafka/prompts/vectors.md +0 -0
  216. /package/{flows → kits/mainframe-java}/packs/cobol-kafka/reviewers/cobol-fidelity.md +0 -0
  217. /package/{flows → kits/mainframe-java}/packs/cobol-kafka/reviewers/pattern-conformance.md +0 -0
  218. /package/{flows/packs/jsp-bff-nextjs → kits/mainframe-java/packs/cobol-kafka}/reviewers/traceability.md +0 -0
  219. /package/{flows → kits/mainframe-java}/packs/cobol-springboot/lessons.md +0 -0
  220. /package/{flows → kits/mainframe-java}/packs/cobol-springboot/prompts/analysis.md +0 -0
  221. /package/{flows → kits/mainframe-java}/packs/cobol-springboot/prompts/bdd.md +0 -0
  222. /package/{flows → kits/mainframe-java}/packs/cobol-springboot/prompts/implement.md +0 -0
  223. /package/{flows → kits/mainframe-java}/packs/cobol-springboot/prompts/plan.md +0 -0
  224. /package/{flows → kits/mainframe-java}/packs/cobol-springboot/prompts/review.md +0 -0
  225. /package/{flows → kits/mainframe-java}/packs/cobol-springboot/prompts/spec.md +0 -0
  226. /package/{flows → kits/mainframe-java}/packs/cobol-springboot/prompts/survey-refine.md +0 -0
  227. /package/{flows → kits/mainframe-java}/packs/cobol-springboot/prompts/survey-triage.md +0 -0
  228. /package/{flows → kits/mainframe-java}/packs/cobol-springboot/prompts/vectors.md +0 -0
  229. /package/{flows → kits/mainframe-java}/packs/cobol-springboot/reviewers/cobol-fidelity.md +0 -0
  230. /package/{flows → kits/mainframe-java}/packs/cobol-springboot/reviewers/pattern-conformance.md +0 -0
  231. /package/{flows/packs/jsp-nextjs → kits/mainframe-java/packs/cobol-springboot}/reviewers/traceability.md +0 -0
  232. /package/{flows → kits/mainframe-java}/patterns/PAT-COBOL-001-comp3-money.md +0 -0
  233. /package/{flows → kits/mainframe-java}/patterns/PAT-COBOL-002-redefines.md +0 -0
  234. /package/{flows → kits/mainframe-java}/patterns/PAT-COBOL-003-88-levels.md +0 -0
  235. /package/{flows → kits/mainframe-java}/patterns/PAT-COBOL-004-perform-thru.md +0 -0
  236. /package/{flows → kits/mainframe-java}/patterns/PAT-COBOL-005-file-status.md +0 -0
  237. /package/{flows → kits/mainframe-java}/patterns/PAT-COBOL-006-sqlcode.md +0 -0
  238. /package/{flows → kits/mainframe-java}/patterns/PAT-COBOL-007-validation-order.md +0 -0
  239. /package/{flows → kits/mainframe-java}/patterns/PAT-COBOL-008-zoned-decimal.md +0 -0
  240. /package/{flows → kits/mainframe-java}/patterns/PAT-COBOL-009-occurs-table.md +0 -0
  241. /package/{flows → kits/mainframe-java}/patterns/PAT-COBOL-010-copybook-record.md +0 -0
  242. /package/{flows → kits/mainframe-java}/patterns/PAT-COBOL-011-batch-counters.md +0 -0
  243. /package/{flows → kits/mainframe-java}/patterns/PAT-COBOL-012-commit-frequency.md +0 -0
  244. /package/{flows → kits/mainframe-java}/patterns/PAT-COBOL-013-abend.md +0 -0
  245. /package/{flows → kits/mainframe-java}/patterns/PAT-COBOL-014-reject-file.md +0 -0
  246. /package/{flows → kits/mainframe-java}/patterns/PAT-COBOL-015-accept-date.md +0 -0
  247. /package/{flows → kits/mainframe-java}/patterns/PAT-COBOL-016-string-building.md +0 -0
  248. /package/{flows → kits/mainframe-java}/patterns/PAT-COBOL-017-cursor-loop.md +0 -0
  249. /package/{flows → kits/mainframe-java}/patterns/PAT-COBOL-018-yn-switches.md +0 -0
  250. /package/{flows → kits/mainframe-java}/patterns/PAT-COBOL-019-shared-accumulators.md +0 -0
  251. /package/{flows → kits/mainframe-java}/patterns/PAT-COBOL-020-tiered-fees.md +0 -0
  252. /package/{flows → kits/mainframe-java}/patterns/PAT-COBOL-021-overdraft-floor.md +0 -0
  253. /package/{flows → kits/mainframe-java}/patterns/PAT-COBOL-022-jcl-job-net.md +0 -0
  254. /package/{flows → kits/mainframe-java}/patterns/PAT-COBOL-023-sort-step.md +0 -0
  255. /package/{flows → kits/mainframe-java}/patterns/PAT-COBOL-024-fixed-width-records.md +0 -0
  256. /package/{flows → kits/mainframe-java}/patterns/PAT-COBOL-025-audit-rows.md +0 -0
  257. /package/{flows/fixtures → kits/mainframe-java}/scaffolds/kafka-streams-service/README.md +0 -0
  258. /package/{flows/fixtures → kits/mainframe-java}/scaffolds/kafka-streams-service/pom.xml +0 -0
  259. /package/{flows/fixtures → kits/mainframe-java}/scaffolds/kafka-streams-service/scripts/replay.sh +0 -0
  260. /package/{flows/fixtures → kits/mainframe-java}/scaffolds/kafka-streams-service/src/main/java/com/meridian/scaffold/Application.java +0 -0
  261. /package/{flows/fixtures → kits/mainframe-java}/scaffolds/kafka-streams-service/src/test/java/com/meridian/scaffold/ApplicationTests.java +0 -0
  262. /package/{flows/fixtures/scaffolds/spring-bff → kits/mainframe-java/scaffolds/kafka-streams-service}/src/test/resources/features/.gitkeep +0 -0
  263. /package/{flows/fixtures → kits/mainframe-java}/scaffolds/spring-boot-service/README.md +0 -0
  264. /package/{flows/fixtures → kits/mainframe-java}/scaffolds/spring-boot-service/pom.xml +0 -0
  265. /package/{flows/fixtures → kits/mainframe-java}/scaffolds/spring-boot-service/scripts/replay.sh +0 -0
  266. /package/{flows/fixtures → kits/mainframe-java}/scaffolds/spring-boot-service/src/main/java/com/meridian/scaffold/Application.java +0 -0
  267. /package/{flows/fixtures → kits/mainframe-java}/scaffolds/spring-boot-service/src/main/resources/application.yaml +0 -0
  268. /package/{flows/fixtures → kits/mainframe-java}/scaffolds/spring-boot-service/src/test/java/com/meridian/scaffold/ApplicationTests.java +0 -0
  269. /package/{flows/fixtures → kits/mainframe-java}/scaffolds/spring-boot-service/src/test/resources/features/.gitkeep +0 -0
@@ -0,0 +1,31 @@
1
+ // CardsPort: the typed contract pages program against.
2
+ // The wire shape is specified in contracts/cards.openapi.yaml; keep the two
3
+ // in sync when either changes.
4
+
5
+ export interface Money {
6
+ /** Minor units are NOT used; amount is a decimal number of major units. */
7
+ readonly amount: number;
8
+ /** ISO 4217 code, e.g. "EUR". */
9
+ readonly currency: string;
10
+ }
11
+
12
+ export type CardKind = 'debit' | 'credit';
13
+
14
+ export type CardStatus = 'active' | 'blocked';
15
+
16
+ export interface CardSummary {
17
+ readonly id: string;
18
+ readonly label: string;
19
+ /** Masked PAN, e.g. "**** **** **** 4242". */
20
+ readonly maskedPan: string;
21
+ readonly kind: CardKind;
22
+ readonly status: CardStatus;
23
+ readonly balance: Money;
24
+ }
25
+
26
+ export interface CardsPort {
27
+ listCards(customerId: string): Promise<ReadonlyArray<CardSummary>>;
28
+ }
29
+
30
+ /** Adapters are created through a factory so wiring stays in the registry. */
31
+ export type CardsPortFactory = () => CardsPort;
@@ -0,0 +1,45 @@
1
+ // Mock adapter for ProfilePort: deterministic fixture data plus a small
2
+ // artificial delay so pages exercise their loading states. Updates are kept
3
+ // in memory for the lifetime of the adapter.
4
+
5
+ import type { Profile, ProfilePort, ProfilePortFactory } from './port';
6
+
7
+ const DELAY_MS = 20;
8
+
9
+ const delay = (ms: number): Promise<void> =>
10
+ new Promise((resolve) => setTimeout(resolve, ms));
11
+
12
+ const FIXTURE_PROFILE: Profile = {
13
+ customerId: 'CUST-1001',
14
+ fullName: 'Ada Doe',
15
+ email: 'ada.doe@example.invalid',
16
+ phone: '+00 555 0100',
17
+ };
18
+
19
+ export const makeMockProfilePort: ProfilePortFactory = () => {
20
+ const profiles = new Map<string, Profile>([
21
+ [FIXTURE_PROFILE.customerId, FIXTURE_PROFILE],
22
+ ]);
23
+
24
+ const port: ProfilePort = {
25
+ async getProfile(customerId) {
26
+ await delay(DELAY_MS);
27
+ const profile = profiles.get(customerId);
28
+ if (profile === undefined) {
29
+ throw new Error(`Unknown customer: ${customerId}`);
30
+ }
31
+ return profile;
32
+ },
33
+ async updateProfile(customerId, update) {
34
+ await delay(DELAY_MS);
35
+ const current = profiles.get(customerId);
36
+ if (current === undefined) {
37
+ throw new Error(`Unknown customer: ${customerId}`);
38
+ }
39
+ const next: Profile = { customerId: current.customerId, ...update };
40
+ profiles.set(customerId, next);
41
+ return next;
42
+ },
43
+ };
44
+ return port;
45
+ };
@@ -0,0 +1,24 @@
1
+ // ProfilePort: the typed contract pages program against.
2
+ // The wire shape is specified in contracts/profile.openapi.yaml; keep the two
3
+ // in sync when either changes.
4
+
5
+ export interface Profile {
6
+ readonly customerId: string;
7
+ readonly fullName: string;
8
+ readonly email: string;
9
+ readonly phone: string;
10
+ }
11
+
12
+ export interface ProfileUpdate {
13
+ readonly fullName: string;
14
+ readonly email: string;
15
+ readonly phone: string;
16
+ }
17
+
18
+ export interface ProfilePort {
19
+ getProfile(customerId: string): Promise<Profile>;
20
+ updateProfile(customerId: string, update: ProfileUpdate): Promise<Profile>;
21
+ }
22
+
23
+ /** Adapters are created through a factory so wiring stays in the registry. */
24
+ export type ProfilePortFactory = () => ProfilePort;
@@ -0,0 +1,20 @@
1
+ // Service registry: the single place adapters are wired to ports.
2
+ // Pages obtain ports ONLY through these getters — never by importing an
3
+ // adapter directly. Swapping the mock for a real gateway adapter is a
4
+ // one-line change per domain (replace the makeMock* factory).
5
+
6
+ import { makeMockCardsPort } from './cards/mock';
7
+ import type { CardsPort } from './cards/port';
8
+ import { makeMockProfilePort } from './profile/mock';
9
+ import type { ProfilePort } from './profile/port';
10
+
11
+ const cardsPort: CardsPort = makeMockCardsPort();
12
+ const profilePort: ProfilePort = makeMockProfilePort();
13
+
14
+ export function getCardsPort(): CardsPort {
15
+ return cardsPort;
16
+ }
17
+
18
+ export function getProfilePort(): ProfilePort {
19
+ return profilePort;
20
+ }
@@ -0,0 +1,269 @@
1
+ /* DemoBank component styles. One class family per design-system component,
2
+ prefixed db-. Pages never define their own CSS files; they compose these
3
+ components. See CONTRIBUTING.md. */
4
+
5
+ body {
6
+ margin: 0;
7
+ font-family: var(--db-font-family);
8
+ font-size: var(--db-font-size-md);
9
+ color: var(--db-color-ink);
10
+ background: var(--db-color-surface-sunken);
11
+ }
12
+
13
+ /* App shell */
14
+ .db-shell-header {
15
+ display: flex;
16
+ align-items: center;
17
+ gap: var(--db-space-6);
18
+ padding: var(--db-space-3) var(--db-space-6);
19
+ background: var(--db-color-brand-strong);
20
+ color: var(--db-color-brand-contrast);
21
+ }
22
+
23
+ .db-shell-brand {
24
+ font-size: var(--db-font-size-lg);
25
+ font-weight: 700;
26
+ letter-spacing: 0.02em;
27
+ }
28
+
29
+ .db-shell-nav {
30
+ display: flex;
31
+ gap: var(--db-space-4);
32
+ }
33
+
34
+ .db-shell-nav a {
35
+ color: var(--db-color-brand-contrast);
36
+ text-decoration: none;
37
+ font-size: var(--db-font-size-sm);
38
+ opacity: 0.9;
39
+ }
40
+
41
+ .db-shell-nav a:hover {
42
+ opacity: 1;
43
+ text-decoration: underline;
44
+ }
45
+
46
+ .db-shell-user {
47
+ margin-left: auto;
48
+ font-size: var(--db-font-size-sm);
49
+ opacity: 0.9;
50
+ }
51
+
52
+ /* PageLayout */
53
+ .db-page {
54
+ max-width: 56rem;
55
+ margin: 0 auto;
56
+ padding: var(--db-space-8) var(--db-space-6);
57
+ }
58
+
59
+ .db-page-header {
60
+ display: flex;
61
+ align-items: flex-end;
62
+ gap: var(--db-space-4);
63
+ margin-bottom: var(--db-space-6);
64
+ }
65
+
66
+ .db-page-title {
67
+ margin: 0;
68
+ font-size: var(--db-font-size-xl);
69
+ }
70
+
71
+ .db-page-subtitle {
72
+ margin: var(--db-space-1) 0 0;
73
+ color: var(--db-color-ink-muted);
74
+ font-size: var(--db-font-size-sm);
75
+ }
76
+
77
+ .db-page-actions {
78
+ margin-left: auto;
79
+ display: flex;
80
+ gap: var(--db-space-2);
81
+ }
82
+
83
+ /* Card */
84
+ .db-card {
85
+ background: var(--db-color-surface);
86
+ border: 1px solid var(--db-color-border);
87
+ border-radius: var(--db-radius-md);
88
+ box-shadow: var(--db-shadow-card);
89
+ padding: var(--db-space-6);
90
+ margin-bottom: var(--db-space-6);
91
+ }
92
+
93
+ .db-card-title {
94
+ margin: 0 0 var(--db-space-4);
95
+ font-size: var(--db-font-size-lg);
96
+ }
97
+
98
+ /* Button */
99
+ .db-button {
100
+ display: inline-flex;
101
+ align-items: center;
102
+ gap: var(--db-space-2);
103
+ padding: var(--db-space-2) var(--db-space-4);
104
+ border-radius: var(--db-radius-sm);
105
+ border: 1px solid transparent;
106
+ font: inherit;
107
+ font-size: var(--db-font-size-sm);
108
+ font-weight: 600;
109
+ cursor: pointer;
110
+ }
111
+
112
+ .db-button:disabled {
113
+ opacity: 0.5;
114
+ cursor: not-allowed;
115
+ }
116
+
117
+ .db-button--primary {
118
+ background: var(--db-color-brand);
119
+ color: var(--db-color-brand-contrast);
120
+ }
121
+
122
+ .db-button--primary:hover:not(:disabled) {
123
+ background: var(--db-color-brand-strong);
124
+ }
125
+
126
+ .db-button--secondary {
127
+ background: var(--db-color-surface);
128
+ color: var(--db-color-brand);
129
+ border-color: var(--db-color-brand);
130
+ }
131
+
132
+ .db-button--ghost {
133
+ background: transparent;
134
+ color: var(--db-color-brand);
135
+ }
136
+
137
+ /* Field */
138
+ .db-field {
139
+ display: block;
140
+ margin-bottom: var(--db-space-4);
141
+ }
142
+
143
+ .db-field-label {
144
+ display: block;
145
+ margin-bottom: var(--db-space-1);
146
+ font-size: var(--db-font-size-sm);
147
+ font-weight: 600;
148
+ }
149
+
150
+ .db-field input,
151
+ .db-field select,
152
+ .db-field textarea {
153
+ width: 100%;
154
+ box-sizing: border-box;
155
+ padding: var(--db-space-2) var(--db-space-3);
156
+ border: 1px solid var(--db-color-border);
157
+ border-radius: var(--db-radius-sm);
158
+ font: inherit;
159
+ background: var(--db-color-surface);
160
+ }
161
+
162
+ .db-field--invalid input,
163
+ .db-field--invalid select,
164
+ .db-field--invalid textarea {
165
+ border-color: var(--db-color-danger);
166
+ }
167
+
168
+ .db-field-error {
169
+ margin: var(--db-space-1) 0 0;
170
+ color: var(--db-color-danger);
171
+ font-size: var(--db-font-size-sm);
172
+ }
173
+
174
+ /* Form */
175
+ .db-form-actions {
176
+ display: flex;
177
+ gap: var(--db-space-2);
178
+ margin-top: var(--db-space-6);
179
+ }
180
+
181
+ .db-form-status {
182
+ margin: var(--db-space-4) 0 0;
183
+ padding: var(--db-space-2) var(--db-space-3);
184
+ border-radius: var(--db-radius-sm);
185
+ font-size: var(--db-font-size-sm);
186
+ }
187
+
188
+ .db-form-status--success {
189
+ background: var(--db-color-success-soft);
190
+ color: var(--db-color-success);
191
+ }
192
+
193
+ /* DataTable */
194
+ .db-table {
195
+ width: 100%;
196
+ border-collapse: collapse;
197
+ }
198
+
199
+ .db-table caption {
200
+ caption-side: top;
201
+ text-align: left;
202
+ font-size: var(--db-font-size-sm);
203
+ color: var(--db-color-ink-muted);
204
+ margin-bottom: var(--db-space-2);
205
+ }
206
+
207
+ .db-table th,
208
+ .db-table td {
209
+ text-align: left;
210
+ padding: var(--db-space-2) var(--db-space-3);
211
+ border-bottom: 1px solid var(--db-color-border);
212
+ font-size: var(--db-font-size-sm);
213
+ }
214
+
215
+ .db-table th {
216
+ color: var(--db-color-ink-muted);
217
+ font-weight: 600;
218
+ }
219
+
220
+ .db-table-empty {
221
+ padding: var(--db-space-6);
222
+ text-align: center;
223
+ color: var(--db-color-ink-muted);
224
+ }
225
+
226
+ /* Stepper */
227
+ .db-stepper {
228
+ display: flex;
229
+ gap: var(--db-space-4);
230
+ list-style: none;
231
+ margin: 0 0 var(--db-space-6);
232
+ padding: 0;
233
+ }
234
+
235
+ .db-stepper-step {
236
+ display: flex;
237
+ align-items: center;
238
+ gap: var(--db-space-2);
239
+ font-size: var(--db-font-size-sm);
240
+ color: var(--db-color-ink-muted);
241
+ }
242
+
243
+ .db-stepper-step--active {
244
+ color: var(--db-color-ink);
245
+ font-weight: 600;
246
+ }
247
+
248
+ .db-stepper-index {
249
+ display: inline-flex;
250
+ align-items: center;
251
+ justify-content: center;
252
+ width: 1.5rem;
253
+ height: 1.5rem;
254
+ border-radius: 50%;
255
+ background: var(--db-color-surface);
256
+ border: 1px solid var(--db-color-border);
257
+ }
258
+
259
+ .db-stepper-step--active .db-stepper-index {
260
+ background: var(--db-color-brand);
261
+ border-color: var(--db-color-brand);
262
+ color: var(--db-color-brand-contrast);
263
+ }
264
+
265
+ /* Utility */
266
+ .db-loading {
267
+ color: var(--db-color-ink-muted);
268
+ font-size: var(--db-font-size-sm);
269
+ }
@@ -0,0 +1,38 @@
1
+ /* DemoBank design tokens. Components consume ONLY these custom properties —
2
+ never hard-coded colors or spacing. See CONTRIBUTING.md. */
3
+ :root {
4
+ /* Color */
5
+ --db-color-ink: #16232e;
6
+ --db-color-ink-muted: #5a6b78;
7
+ --db-color-surface: #ffffff;
8
+ --db-color-surface-sunken: #f2f5f7;
9
+ --db-color-border: #d4dde3;
10
+ --db-color-brand: #0f5f5c;
11
+ --db-color-brand-strong: #0a4341;
12
+ --db-color-brand-contrast: #ffffff;
13
+ --db-color-danger: #b4232a;
14
+ --db-color-danger-soft: #fbeaea;
15
+ --db-color-success: #1d6b3a;
16
+ --db-color-success-soft: #e8f4ec;
17
+
18
+ /* Typography */
19
+ --db-font-family:
20
+ 'Avenir Next', 'Segoe UI', system-ui, -apple-system, sans-serif;
21
+ --db-font-size-sm: 0.8125rem;
22
+ --db-font-size-md: 0.9375rem;
23
+ --db-font-size-lg: 1.125rem;
24
+ --db-font-size-xl: 1.5rem;
25
+
26
+ /* Spacing (4px scale) */
27
+ --db-space-1: 0.25rem;
28
+ --db-space-2: 0.5rem;
29
+ --db-space-3: 0.75rem;
30
+ --db-space-4: 1rem;
31
+ --db-space-6: 1.5rem;
32
+ --db-space-8: 2rem;
33
+
34
+ /* Shape */
35
+ --db-radius-sm: 4px;
36
+ --db-radius-md: 8px;
37
+ --db-shadow-card: 0 1px 3px rgba(22, 35, 46, 0.12);
38
+ }
@@ -0,0 +1,81 @@
1
+ // House test style for list pages: swap the registry for an instrumented
2
+ // port, render inside AuthProvider, assert rows render and the port was
3
+ // called with the signed-in customer's id.
4
+
5
+ import { beforeEach, describe, expect, it, vi } from 'vitest';
6
+ import { cleanup, render, screen } from '@testing-library/react';
7
+ import { afterEach } from 'vitest';
8
+ import { AuthProvider } from '@/auth/AuthProvider';
9
+ import type { CardSummary } from '@/services/cards/port';
10
+ import CardsPage from '@/app/cards/page';
11
+
12
+ const { listCards } = vi.hoisted(() => ({
13
+ listCards:
14
+ vi.fn<(customerId: string) => Promise<ReadonlyArray<CardSummary>>>(),
15
+ }));
16
+
17
+ vi.mock('@/services/registry', () => ({
18
+ getCardsPort: () => ({ listCards }),
19
+ }));
20
+
21
+ const FIXTURE_CARDS: ReadonlyArray<CardSummary> = [
22
+ {
23
+ id: 'card-100',
24
+ label: 'Test Debit',
25
+ maskedPan: '**** **** **** 1111',
26
+ kind: 'debit',
27
+ status: 'active',
28
+ balance: { amount: 10, currency: 'EUR' },
29
+ },
30
+ {
31
+ id: 'card-200',
32
+ label: 'Test Credit',
33
+ maskedPan: '**** **** **** 2222',
34
+ kind: 'credit',
35
+ status: 'blocked',
36
+ balance: { amount: -5, currency: 'EUR' },
37
+ },
38
+ ];
39
+
40
+ const renderPage = () =>
41
+ render(
42
+ <AuthProvider>
43
+ <CardsPage />
44
+ </AuthProvider>,
45
+ );
46
+
47
+ describe('CardsPage', () => {
48
+ beforeEach(() => {
49
+ listCards.mockReset();
50
+ listCards.mockResolvedValue(FIXTURE_CARDS);
51
+ });
52
+
53
+ afterEach(() => {
54
+ cleanup();
55
+ });
56
+
57
+ it('renders a loading state, then one row per card from the port', async () => {
58
+ renderPage();
59
+ expect(screen.getByText('Loading your cards…')).toBeDefined();
60
+
61
+ expect(await screen.findByText('Test Debit')).toBeDefined();
62
+ expect(screen.getByText('Test Credit')).toBeDefined();
63
+ expect(screen.getByText('**** **** **** 1111')).toBeDefined();
64
+ expect(screen.getAllByRole('row')).toHaveLength(3); // header + 2 cards
65
+ });
66
+
67
+ it('asks the port for the signed-in customer', async () => {
68
+ renderPage();
69
+ await screen.findByText('Test Debit');
70
+
71
+ expect(listCards).toHaveBeenCalledTimes(1);
72
+ expect(listCards).toHaveBeenCalledWith('CUST-1001');
73
+ });
74
+
75
+ it('shows the empty state when the port returns no cards', async () => {
76
+ listCards.mockResolvedValue([]);
77
+ renderPage();
78
+
79
+ expect(await screen.findByText('You have no cards yet.')).toBeDefined();
80
+ });
81
+ });
@@ -0,0 +1,87 @@
1
+ // House test style for form pages: swap the registry for an instrumented
2
+ // port, render inside AuthProvider, assert the fields render, validation
3
+ // fires, and the port receives the expected payload on save.
4
+
5
+ import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest';
6
+ import { cleanup, fireEvent, render, screen } from '@testing-library/react';
7
+ import { AuthProvider } from '@/auth/AuthProvider';
8
+ import type { Profile, ProfileUpdate } from '@/services/profile/port';
9
+ import ProfilePage from '@/app/profile/page';
10
+
11
+ const { getProfile, updateProfile } = vi.hoisted(() => ({
12
+ getProfile: vi.fn<(customerId: string) => Promise<Profile>>(),
13
+ updateProfile:
14
+ vi.fn<(customerId: string, update: ProfileUpdate) => Promise<Profile>>(),
15
+ }));
16
+
17
+ vi.mock('@/services/registry', () => ({
18
+ getProfilePort: () => ({ getProfile, updateProfile }),
19
+ }));
20
+
21
+ const FIXTURE_PROFILE: Profile = {
22
+ customerId: 'CUST-1001',
23
+ fullName: 'Ada Doe',
24
+ email: 'ada.doe@example.invalid',
25
+ phone: '+00 555 0100',
26
+ };
27
+
28
+ const renderPage = () =>
29
+ render(
30
+ <AuthProvider>
31
+ <ProfilePage />
32
+ </AuthProvider>,
33
+ );
34
+
35
+ describe('ProfilePage', () => {
36
+ beforeEach(() => {
37
+ getProfile.mockReset();
38
+ updateProfile.mockReset();
39
+ getProfile.mockResolvedValue(FIXTURE_PROFILE);
40
+ updateProfile.mockImplementation(async (customerId, update) => ({
41
+ customerId,
42
+ ...update,
43
+ }));
44
+ });
45
+
46
+ afterEach(() => {
47
+ cleanup();
48
+ });
49
+
50
+ it('renders the profile fields with values from the port', async () => {
51
+ renderPage();
52
+
53
+ expect(await screen.findByLabelText('Full name')).toBeDefined();
54
+ expect(screen.getByLabelText('Email')).toBeDefined();
55
+ expect(screen.getByLabelText('Phone')).toBeDefined();
56
+ expect(screen.getByDisplayValue('Ada Doe')).toBeDefined();
57
+ expect(screen.getByDisplayValue('ada.doe@example.invalid')).toBeDefined();
58
+ expect(getProfile).toHaveBeenCalledWith('CUST-1001');
59
+ });
60
+
61
+ it('fires validation and does not call the port on invalid input', async () => {
62
+ renderPage();
63
+ const email = await screen.findByLabelText('Email');
64
+
65
+ fireEvent.change(email, { target: { value: 'not-an-email' } });
66
+ fireEvent.click(screen.getByRole('button', { name: 'Save changes' }));
67
+
68
+ expect(await screen.findByText('Enter a valid email address.')).toBeDefined();
69
+ expect(updateProfile).not.toHaveBeenCalled();
70
+ });
71
+
72
+ it('saves through the port with the expected payload', async () => {
73
+ renderPage();
74
+ const fullName = await screen.findByLabelText('Full name');
75
+
76
+ fireEvent.change(fullName, { target: { value: 'Ada Q. Doe' } });
77
+ fireEvent.click(screen.getByRole('button', { name: 'Save changes' }));
78
+
79
+ expect(await screen.findByText('Profile saved.')).toBeDefined();
80
+ expect(updateProfile).toHaveBeenCalledTimes(1);
81
+ expect(updateProfile).toHaveBeenCalledWith('CUST-1001', {
82
+ fullName: 'Ada Q. Doe',
83
+ email: 'ada.doe@example.invalid',
84
+ phone: '+00 555 0100',
85
+ });
86
+ });
87
+ });
@@ -0,0 +1,54 @@
1
+ {
2
+ "compilerOptions": {
3
+ "target": "ES2022",
4
+ "lib": [
5
+ "dom",
6
+ "dom.iterable",
7
+ "ES2022"
8
+ ],
9
+ "module": "esnext",
10
+ "moduleResolution": "bundler",
11
+ "jsx": "preserve",
12
+ "strict": true,
13
+ "noUncheckedIndexedAccess": true,
14
+ "noFallthroughCasesInSwitch": true,
15
+ "forceConsistentCasingInFileNames": true,
16
+ "esModuleInterop": true,
17
+ "isolatedModules": true,
18
+ "resolveJsonModule": true,
19
+ "allowJs": false,
20
+ "skipLibCheck": true,
21
+ "noEmit": true,
22
+ "incremental": false,
23
+ "baseUrl": ".",
24
+ "paths": {
25
+ "@/*": [
26
+ "src/*"
27
+ ]
28
+ },
29
+ "types": [
30
+ "react",
31
+ "react-dom",
32
+ "node"
33
+ ],
34
+ "plugins": [
35
+ {
36
+ "name": "next"
37
+ }
38
+ ]
39
+ },
40
+ "include": [
41
+ "next-env.d.ts",
42
+ "src/**/*.ts",
43
+ "src/**/*.tsx",
44
+ "tests/**/*.ts",
45
+ "tests/**/*.tsx",
46
+ "vitest.config.ts",
47
+ ".next/types/**/*.ts"
48
+ ],
49
+ "exclude": [
50
+ "node_modules",
51
+ ".next",
52
+ "out"
53
+ ]
54
+ }
@@ -0,0 +1,17 @@
1
+ import { fileURLToPath } from 'node:url';
2
+ import { defineConfig } from 'vitest/config';
3
+
4
+ export default defineConfig({
5
+ resolve: {
6
+ alias: {
7
+ '@': fileURLToPath(new URL('./src', import.meta.url)),
8
+ },
9
+ },
10
+ esbuild: {
11
+ jsx: 'automatic',
12
+ },
13
+ test: {
14
+ environment: 'jsdom',
15
+ include: ['tests/**/*.test.ts', 'tests/**/*.test.tsx'],
16
+ },
17
+ });