@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,62 @@
1
+ 'use client';
2
+
3
+ import { useEffect, useState } from 'react';
4
+ import { Card, DataTable, PageLayout } from '@/components';
5
+ import type { DataTableColumn } from '@/components';
6
+ import { useAuth } from '@/auth/AuthProvider';
7
+ import { getCardsPort } from '@/services/registry';
8
+ import type { CardSummary, Money } from '@/services/cards/port';
9
+
10
+ const formatMoney = ({ amount, currency }: Money): string =>
11
+ new Intl.NumberFormat('en-IE', { style: 'currency', currency }).format(
12
+ amount,
13
+ );
14
+
15
+ const COLUMNS: ReadonlyArray<DataTableColumn<CardSummary>> = [
16
+ { id: 'label', header: 'Card', cell: (card) => card.label },
17
+ { id: 'maskedPan', header: 'Number', cell: (card) => card.maskedPan },
18
+ { id: 'kind', header: 'Type', cell: (card) => card.kind },
19
+ { id: 'status', header: 'Status', cell: (card) => card.status },
20
+ { id: 'balance', header: 'Balance', cell: (card) => formatMoney(card.balance) },
21
+ ];
22
+
23
+ /**
24
+ * Exemplar list page: loads rows through a port from the registry and renders
25
+ * them with DataTable inside a Card. No fetch calls, no ad-hoc tables.
26
+ */
27
+ export default function CardsPage() {
28
+ const user = useAuth();
29
+ const [cards, setCards] = useState<ReadonlyArray<CardSummary> | null>(null);
30
+
31
+ useEffect(() => {
32
+ let cancelled = false;
33
+ void getCardsPort()
34
+ .listCards(user.customerId)
35
+ .then((loaded) => {
36
+ if (!cancelled) {
37
+ setCards(loaded);
38
+ }
39
+ });
40
+ return () => {
41
+ cancelled = true;
42
+ };
43
+ }, [user.customerId]);
44
+
45
+ return (
46
+ <PageLayout title="Your cards" subtitle="Payment cards on your account.">
47
+ <Card>
48
+ {cards === null ? (
49
+ <p className="db-loading">Loading your cards…</p>
50
+ ) : (
51
+ <DataTable
52
+ caption={`Cards for ${user.name}`}
53
+ columns={COLUMNS}
54
+ rows={cards}
55
+ rowKey={(card) => card.id}
56
+ emptyMessage="You have no cards yet."
57
+ />
58
+ )}
59
+ </Card>
60
+ </PageLayout>
61
+ );
62
+ }
@@ -0,0 +1,41 @@
1
+ import Link from 'next/link';
2
+ import type { Metadata } from 'next';
3
+ import type { ReactNode } from 'react';
4
+ import { AuthProvider } from '@/auth/AuthProvider';
5
+ import { SignedInBadge } from './signed-in-badge';
6
+ import '@/theme/tokens.css';
7
+ import '@/theme/components.css';
8
+
9
+ export const metadata: Metadata = {
10
+ title: 'DemoBank',
11
+ description: 'DemoBank online banking (synthetic fixture)',
12
+ };
13
+
14
+ /**
15
+ * App shell: brand, primary navigation, signed-in user. The layout stays a
16
+ * server component; everything interactive lives in client components.
17
+ */
18
+ export default function RootLayout({
19
+ children,
20
+ }: {
21
+ readonly children: ReactNode;
22
+ }) {
23
+ return (
24
+ <html lang="en">
25
+ <body>
26
+ <AuthProvider>
27
+ <header className="db-shell-header">
28
+ <span className="db-shell-brand">DemoBank</span>
29
+ <nav className="db-shell-nav" aria-label="Primary">
30
+ <Link href="/">Home</Link>
31
+ <Link href="/cards">Cards</Link>
32
+ <Link href="/profile">Profile</Link>
33
+ </nav>
34
+ <SignedInBadge />
35
+ </header>
36
+ {children}
37
+ </AuthProvider>
38
+ </body>
39
+ </html>
40
+ );
41
+ }
@@ -0,0 +1,26 @@
1
+ 'use client';
2
+
3
+ import { Card, PageLayout, Stepper } from '@/components';
4
+ import { useAuth } from '@/auth/AuthProvider';
5
+
6
+ /** Landing page: greets the stubbed SSO user and shows the house Stepper. */
7
+ export default function HomePage() {
8
+ const user = useAuth();
9
+ return (
10
+ <PageLayout
11
+ title={`Welcome back, ${user.name}`}
12
+ subtitle="Your everyday banking, in one place."
13
+ >
14
+ <Card title="Getting started">
15
+ <Stepper
16
+ steps={['Review your cards', 'Check your profile', 'Explore']}
17
+ activeIndex={0}
18
+ />
19
+ <p>
20
+ Use the navigation above to review your payment cards or update your
21
+ contact details.
22
+ </p>
23
+ </Card>
24
+ </PageLayout>
25
+ );
26
+ }
@@ -0,0 +1,134 @@
1
+ 'use client';
2
+
3
+ import { useEffect, useState } from 'react';
4
+ import { Button, Card, Field, Form, PageLayout } from '@/components';
5
+ import type { ValidationErrors } from '@/components';
6
+ import { useAuth } from '@/auth/AuthProvider';
7
+ import { getProfilePort } from '@/services/registry';
8
+ import type { Profile, ProfileUpdate } from '@/services/profile/port';
9
+
10
+ type ProfileFormValues = ProfileUpdate;
11
+
12
+ const EMAIL_PATTERN = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
13
+
14
+ const validateProfile = (
15
+ values: ProfileFormValues,
16
+ ): ValidationErrors<ProfileFormValues> => {
17
+ const errors: {
18
+ fullName?: string;
19
+ email?: string;
20
+ phone?: string;
21
+ } = {};
22
+ if (values.fullName.trim().length === 0) {
23
+ errors.fullName = 'Full name is required.';
24
+ }
25
+ if (values.email.trim().length === 0) {
26
+ errors.email = 'Email is required.';
27
+ } else if (!EMAIL_PATTERN.test(values.email)) {
28
+ errors.email = 'Enter a valid email address.';
29
+ }
30
+ if (values.phone.trim().length === 0) {
31
+ errors.phone = 'Phone number is required.';
32
+ }
33
+ return errors;
34
+ };
35
+
36
+ /**
37
+ * Exemplar form page: loads via ProfilePort, edits with Form + Field, saves
38
+ * through the port. Validation lives in a pure function next to the page.
39
+ */
40
+ export default function ProfilePage() {
41
+ const user = useAuth();
42
+ const [profile, setProfile] = useState<Profile | null>(null);
43
+ const [saved, setSaved] = useState(false);
44
+
45
+ useEffect(() => {
46
+ let cancelled = false;
47
+ void getProfilePort()
48
+ .getProfile(user.customerId)
49
+ .then((loaded) => {
50
+ if (!cancelled) {
51
+ setProfile(loaded);
52
+ }
53
+ });
54
+ return () => {
55
+ cancelled = true;
56
+ };
57
+ }, [user.customerId]);
58
+
59
+ const handleSubmit = async (values: ProfileFormValues): Promise<void> => {
60
+ setSaved(false);
61
+ const updated = await getProfilePort().updateProfile(
62
+ user.customerId,
63
+ values,
64
+ );
65
+ setProfile(updated);
66
+ setSaved(true);
67
+ };
68
+
69
+ return (
70
+ <PageLayout title="Your profile" subtitle="Contact details we hold for you.">
71
+ <Card title="Contact details">
72
+ {profile === null ? (
73
+ <p className="db-loading">Loading your profile…</p>
74
+ ) : (
75
+ <Form<ProfileFormValues>
76
+ initialValues={{
77
+ fullName: profile.fullName,
78
+ email: profile.email,
79
+ phone: profile.phone,
80
+ }}
81
+ validate={validateProfile}
82
+ onSubmit={handleSubmit}
83
+ >
84
+ {({ values, errors, setValue, submitting }) => (
85
+ <>
86
+ <Field id="fullName" label="Full name" error={errors.fullName}>
87
+ <input
88
+ id="fullName"
89
+ name="fullName"
90
+ value={values.fullName}
91
+ onChange={(event) =>
92
+ setValue('fullName', event.target.value)
93
+ }
94
+ />
95
+ </Field>
96
+ <Field id="email" label="Email" error={errors.email}>
97
+ <input
98
+ id="email"
99
+ name="email"
100
+ type="email"
101
+ value={values.email}
102
+ onChange={(event) => setValue('email', event.target.value)}
103
+ />
104
+ </Field>
105
+ <Field id="phone" label="Phone" error={errors.phone}>
106
+ <input
107
+ id="phone"
108
+ name="phone"
109
+ type="tel"
110
+ value={values.phone}
111
+ onChange={(event) => setValue('phone', event.target.value)}
112
+ />
113
+ </Field>
114
+ <div className="db-form-actions">
115
+ <Button type="submit" disabled={submitting}>
116
+ {submitting ? 'Saving…' : 'Save changes'}
117
+ </Button>
118
+ </div>
119
+ {saved ? (
120
+ <p
121
+ className="db-form-status db-form-status--success"
122
+ role="status"
123
+ >
124
+ Profile saved.
125
+ </p>
126
+ ) : null}
127
+ </>
128
+ )}
129
+ </Form>
130
+ )}
131
+ </Card>
132
+ </PageLayout>
133
+ );
134
+ }
@@ -0,0 +1,9 @@
1
+ 'use client';
2
+
3
+ import { useAuth } from '@/auth/AuthProvider';
4
+
5
+ /** Shows who is signed in (via the SSO stub) in the app shell header. */
6
+ export function SignedInBadge() {
7
+ const user = useAuth();
8
+ return <span className="db-shell-user">Signed in as {user.name}</span>;
9
+ }
@@ -0,0 +1,36 @@
1
+ 'use client';
2
+
3
+ import { createContext, useContext } from 'react';
4
+ import type { ReactNode } from 'react';
5
+
6
+ export interface AuthUser {
7
+ readonly name: string;
8
+ readonly customerId: string;
9
+ }
10
+
11
+ /**
12
+ * SSO stub. In production the shell exchanges the gateway session for a
13
+ * profile; here a fixed user is always signed in. Pages consume useAuth()
14
+ * and NEVER implement login, token handling, or redirects themselves.
15
+ */
16
+ const DEMO_USER: AuthUser = {
17
+ name: 'Ada Doe',
18
+ customerId: 'CUST-1001',
19
+ };
20
+
21
+ const AuthContext = createContext<AuthUser | null>(null);
22
+
23
+ export function AuthProvider({ children }: { readonly children: ReactNode }) {
24
+ return (
25
+ <AuthContext.Provider value={DEMO_USER}>{children}</AuthContext.Provider>
26
+ );
27
+ }
28
+
29
+ /** Current signed-in user. Throws when rendered outside the app shell. */
30
+ export function useAuth(): AuthUser {
31
+ const user = useContext(AuthContext);
32
+ if (user === null) {
33
+ throw new Error('useAuth must be used inside <AuthProvider>');
34
+ }
35
+ return user;
36
+ }
@@ -0,0 +1,27 @@
1
+ 'use client';
2
+
3
+ import type { ButtonHTMLAttributes } from 'react';
4
+
5
+ export type ButtonVariant = 'primary' | 'secondary' | 'ghost';
6
+
7
+ export interface ButtonProps extends ButtonHTMLAttributes<HTMLButtonElement> {
8
+ readonly variant?: ButtonVariant;
9
+ }
10
+
11
+ /** House button. Default type is "button"; forms opt in with type="submit". */
12
+ export function Button({
13
+ variant = 'primary',
14
+ type = 'button',
15
+ className,
16
+ children,
17
+ ...rest
18
+ }: ButtonProps) {
19
+ const classes = ['db-button', `db-button--${variant}`, className]
20
+ .filter((c) => typeof c === 'string' && c.length > 0)
21
+ .join(' ');
22
+ return (
23
+ <button type={type} className={classes} {...rest}>
24
+ {children}
25
+ </button>
26
+ );
27
+ }
@@ -0,0 +1,18 @@
1
+ 'use client';
2
+
3
+ import type { ReactNode } from 'react';
4
+
5
+ export interface CardProps {
6
+ readonly title?: string;
7
+ readonly children: ReactNode;
8
+ }
9
+
10
+ /** House surface. Every block of page content sits inside a Card. */
11
+ export function Card({ title, children }: CardProps) {
12
+ return (
13
+ <section className="db-card">
14
+ {title !== undefined ? <h2 className="db-card-title">{title}</h2> : null}
15
+ {children}
16
+ </section>
17
+ );
18
+ }
@@ -0,0 +1,57 @@
1
+ 'use client';
2
+
3
+ import type { ReactNode } from 'react';
4
+
5
+ export interface DataTableColumn<Row> {
6
+ /** Stable column id, used as the React key for header and cells. */
7
+ readonly id: string;
8
+ readonly header: string;
9
+ readonly cell: (row: Row) => ReactNode;
10
+ }
11
+
12
+ export interface DataTableProps<Row> {
13
+ readonly caption: string;
14
+ readonly columns: ReadonlyArray<DataTableColumn<Row>>;
15
+ readonly rows: ReadonlyArray<Row>;
16
+ readonly rowKey: (row: Row) => string;
17
+ readonly emptyMessage?: string;
18
+ }
19
+
20
+ /**
21
+ * House table for read-only listings. Rendering stays declarative: pages
22
+ * describe columns, never map over rows in JSX themselves.
23
+ */
24
+ export function DataTable<Row>({
25
+ caption,
26
+ columns,
27
+ rows,
28
+ rowKey,
29
+ emptyMessage = 'Nothing to show yet.',
30
+ }: DataTableProps<Row>) {
31
+ if (rows.length === 0) {
32
+ return <p className="db-table-empty">{emptyMessage}</p>;
33
+ }
34
+ return (
35
+ <table className="db-table">
36
+ <caption>{caption}</caption>
37
+ <thead>
38
+ <tr>
39
+ {columns.map((column) => (
40
+ <th key={column.id} scope="col">
41
+ {column.header}
42
+ </th>
43
+ ))}
44
+ </tr>
45
+ </thead>
46
+ <tbody>
47
+ {rows.map((row) => (
48
+ <tr key={rowKey(row)}>
49
+ {columns.map((column) => (
50
+ <td key={column.id}>{column.cell(row)}</td>
51
+ ))}
52
+ </tr>
53
+ ))}
54
+ </tbody>
55
+ </table>
56
+ );
57
+ }
@@ -0,0 +1,34 @@
1
+ 'use client';
2
+
3
+ import type { ReactNode } from 'react';
4
+
5
+ export interface FieldProps {
6
+ /** id of the control rendered inside the field (label htmlFor pairs with it). */
7
+ readonly id: string;
8
+ readonly label: string;
9
+ /** Validation message; when set the field renders in its invalid state. */
10
+ readonly error?: string;
11
+ /** Exactly one form control (input/select/textarea) with the matching id. */
12
+ readonly children: ReactNode;
13
+ }
14
+
15
+ /**
16
+ * Field wraps label + control + error. Pages never hand-roll label/error
17
+ * markup; every form control lives inside a Field.
18
+ */
19
+ export function Field({ id, label, error, children }: FieldProps) {
20
+ const invalid = typeof error === 'string' && error.length > 0;
21
+ return (
22
+ <div className={invalid ? 'db-field db-field--invalid' : 'db-field'}>
23
+ <label className="db-field-label" htmlFor={id}>
24
+ {label}
25
+ </label>
26
+ {children}
27
+ {invalid ? (
28
+ <p className="db-field-error" role="alert" id={`${id}-error`}>
29
+ {error}
30
+ </p>
31
+ ) : null}
32
+ </div>
33
+ );
34
+ }
@@ -0,0 +1,70 @@
1
+ 'use client';
2
+
3
+ import { useCallback, useState } from 'react';
4
+ import type { FormEvent, ReactNode } from 'react';
5
+
6
+ /** Validation map: field name -> message. Empty map means valid. */
7
+ export type ValidationErrors<T> = Partial<
8
+ Record<Extract<keyof T, string>, string>
9
+ >;
10
+
11
+ export interface FormRenderProps<T extends object> {
12
+ readonly values: T;
13
+ readonly errors: ValidationErrors<T>;
14
+ readonly setValue: <K extends keyof T>(key: K, value: T[K]) => void;
15
+ readonly submitting: boolean;
16
+ }
17
+
18
+ export interface FormProps<T extends object> {
19
+ readonly initialValues: T;
20
+ /** Pure, synchronous. Returns a map of messages; empty map = submit. */
21
+ readonly validate?: (values: T) => ValidationErrors<T>;
22
+ readonly onSubmit: (values: T) => void | Promise<void>;
23
+ readonly children: (form: FormRenderProps<T>) => ReactNode;
24
+ }
25
+
26
+ /**
27
+ * House form. Owns values, validation, and submit; pages provide fields via
28
+ * the render prop and never call preventDefault or track error state
29
+ * themselves.
30
+ */
31
+ export function Form<T extends object>({
32
+ initialValues,
33
+ validate,
34
+ onSubmit,
35
+ children,
36
+ }: FormProps<T>) {
37
+ const [values, setValues] = useState<T>(initialValues);
38
+ const [errors, setErrors] = useState<ValidationErrors<T>>({});
39
+ const [submitting, setSubmitting] = useState(false);
40
+
41
+ const setValue = useCallback(<K extends keyof T>(key: K, value: T[K]) => {
42
+ setValues((prev) => {
43
+ const next = { ...prev };
44
+ next[key] = value;
45
+ return next;
46
+ });
47
+ }, []);
48
+
49
+ const handleSubmit = (event: FormEvent<HTMLFormElement>) => {
50
+ event.preventDefault();
51
+ const nextErrors = validate === undefined ? {} : validate(values);
52
+ setErrors(nextErrors);
53
+ if (Object.keys(nextErrors).length > 0) {
54
+ return;
55
+ }
56
+ const result = onSubmit(values);
57
+ if (result instanceof Promise) {
58
+ setSubmitting(true);
59
+ void result.finally(() => {
60
+ setSubmitting(false);
61
+ });
62
+ }
63
+ };
64
+
65
+ return (
66
+ <form onSubmit={handleSubmit} noValidate>
67
+ {children({ values, errors, setValue, submitting })}
68
+ </form>
69
+ );
70
+ }
@@ -0,0 +1,39 @@
1
+ 'use client';
2
+
3
+ import type { ReactNode } from 'react';
4
+
5
+ export interface PageLayoutProps {
6
+ readonly title: string;
7
+ readonly subtitle?: string;
8
+ /** Page-level actions (Buttons), rendered top-right of the header. */
9
+ readonly actions?: ReactNode;
10
+ readonly children: ReactNode;
11
+ }
12
+
13
+ /**
14
+ * House page frame: heading, optional subtitle and actions, then content.
15
+ * Every page renders exactly one PageLayout at its root.
16
+ */
17
+ export function PageLayout({
18
+ title,
19
+ subtitle,
20
+ actions,
21
+ children,
22
+ }: PageLayoutProps) {
23
+ return (
24
+ <main className="db-page">
25
+ <header className="db-page-header">
26
+ <div>
27
+ <h1 className="db-page-title">{title}</h1>
28
+ {subtitle !== undefined ? (
29
+ <p className="db-page-subtitle">{subtitle}</p>
30
+ ) : null}
31
+ </div>
32
+ {actions !== undefined ? (
33
+ <div className="db-page-actions">{actions}</div>
34
+ ) : null}
35
+ </header>
36
+ {children}
37
+ </main>
38
+ );
39
+ }
@@ -0,0 +1,29 @@
1
+ 'use client';
2
+
3
+ export interface StepperProps {
4
+ readonly steps: ReadonlyArray<string>;
5
+ /** Zero-based index of the active step. */
6
+ readonly activeIndex: number;
7
+ }
8
+
9
+ /** House progress indicator for multi-step journeys (wizards, onboarding). */
10
+ export function Stepper({ steps, activeIndex }: StepperProps) {
11
+ return (
12
+ <ol className="db-stepper">
13
+ {steps.map((step, index) => (
14
+ <li
15
+ key={step}
16
+ className={
17
+ index === activeIndex
18
+ ? 'db-stepper-step db-stepper-step--active'
19
+ : 'db-stepper-step'
20
+ }
21
+ aria-current={index === activeIndex ? 'step' : undefined}
22
+ >
23
+ <span className="db-stepper-index">{index + 1}</span>
24
+ {step}
25
+ </li>
26
+ ))}
27
+ </ol>
28
+ );
29
+ }
@@ -0,0 +1,19 @@
1
+ // Design-system barrel: pages import components from '@/components'.
2
+ export { Button } from './Button';
3
+ export type { ButtonProps, ButtonVariant } from './Button';
4
+ export { Card } from './Card';
5
+ export type { CardProps } from './Card';
6
+ export { DataTable } from './DataTable';
7
+ export type { DataTableColumn, DataTableProps } from './DataTable';
8
+ export { Field } from './Field';
9
+ export type { FieldProps } from './Field';
10
+ export { Form } from './Form';
11
+ export type {
12
+ FormProps,
13
+ FormRenderProps,
14
+ ValidationErrors,
15
+ } from './Form';
16
+ export { PageLayout } from './PageLayout';
17
+ export type { PageLayoutProps } from './PageLayout';
18
+ export { Stepper } from './Stepper';
19
+ export type { StepperProps } from './Stepper';
@@ -0,0 +1,47 @@
1
+ // Mock adapter for CardsPort: deterministic fixture data plus a small
2
+ // artificial delay so pages exercise their loading states.
3
+
4
+ import type { CardsPort, CardsPortFactory, CardSummary } from './port';
5
+
6
+ const DELAY_MS = 20;
7
+
8
+ const delay = (ms: number): Promise<void> =>
9
+ new Promise((resolve) => setTimeout(resolve, ms));
10
+
11
+ const FIXTURE_CARDS: ReadonlyArray<CardSummary> = [
12
+ {
13
+ id: 'card-001',
14
+ label: 'Everyday Debit',
15
+ maskedPan: '**** **** **** 4242',
16
+ kind: 'debit',
17
+ status: 'active',
18
+ balance: { amount: 1245.5, currency: 'EUR' },
19
+ },
20
+ {
21
+ id: 'card-002',
22
+ label: 'Travel Credit',
23
+ maskedPan: '**** **** **** 9310',
24
+ kind: 'credit',
25
+ status: 'active',
26
+ balance: { amount: -320.75, currency: 'EUR' },
27
+ },
28
+ {
29
+ id: 'card-003',
30
+ label: 'Backup Debit',
31
+ maskedPan: '**** **** **** 0007',
32
+ kind: 'debit',
33
+ status: 'blocked',
34
+ balance: { amount: 0, currency: 'EUR' },
35
+ },
36
+ ];
37
+
38
+ export const makeMockCardsPort: CardsPortFactory = () => {
39
+ const port: CardsPort = {
40
+ async listCards(customerId) {
41
+ await delay(DELAY_MS);
42
+ // The fixture gateway knows a single customer; anyone else has no cards.
43
+ return customerId === 'CUST-1001' ? FIXTURE_CARDS : [];
44
+ },
45
+ };
46
+ return port;
47
+ };