@team-codeme/crud-forge 0.0.0-stage โ†’ 1.0.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 (415) hide show
  1. package/.cursor/agents/generator-engineer.md +31 -0
  2. package/.cursor/agents/keycloak-engineer.md +33 -0
  3. package/.cursor/agents/qa-engineer.md +32 -0
  4. package/.cursor/agents/security-reviewer.md +30 -0
  5. package/.cursor/mcp.json +13 -0
  6. package/.cursor/rules/crudforge-precautions.mdc +16 -0
  7. package/.cursor/rules/playwright-browser.mdc +30 -0
  8. package/.cursor/rules/readme-todo-sync.mdc +13 -0
  9. package/.env.qa.example +19 -0
  10. package/.github/workflows/qa-live.yml +32 -0
  11. package/.github/workflows/qa.yml +27 -0
  12. package/.vscode/settings.json +32 -0
  13. package/QA/IAM-PLAN.md +25 -0
  14. package/QA/IAM-RESULTS.md +39 -0
  15. package/QA/IAM-TESTCASES.md +36 -0
  16. package/QA/IAM-TODO.md +7 -0
  17. package/QA/KEYCLOAK-BOOTSTRAP.md +105 -0
  18. package/QA/PLAN.md +43 -0
  19. package/QA/RESULTS.md +59 -0
  20. package/QA/TESTCASES.md +65 -0
  21. package/QA/TODO.md +14 -0
  22. package/QA/pmb-dev/README.md +49 -0
  23. package/QA/pmb-dev/config/config.yml +152 -0
  24. package/QA/pmb-dev/gdl/i.gdl +17 -0
  25. package/README.md +851 -2
  26. package/Todo.md +207 -0
  27. package/assets/branding/crudforge-logo.png +0 -0
  28. package/assets/branding/crudforge-mark.png +0 -0
  29. package/branding/poster-crudforge.jpg +0 -0
  30. package/chat/last-chat/Investigating Mock Data Configuration.md +428 -0
  31. package/cli.js +167 -0
  32. package/config/default-config.yml +245 -0
  33. package/docs/performance/README.md +217 -0
  34. package/docs/performance/after.json +111 -0
  35. package/docs/performance/before.json +111 -0
  36. package/docs/quality/README.md +276 -0
  37. package/e2e/crudforge.e2e.yml +47 -0
  38. package/e2e/crudforge.field-profile.yml +33 -0
  39. package/e2e/crudforge.iam-live.yml +124 -0
  40. package/e2e/crudforge.iam.yml +62 -0
  41. package/e2e/tests/field-profile.spec.js +152 -0
  42. package/e2e/tests/generated-crud.spec.js +251 -0
  43. package/e2e/tests/iam-live.spec.js +149 -0
  44. package/e2e/tests/iam-pack.spec.js +151 -0
  45. package/e2e/tests/list-state.spec.js +73 -0
  46. package/features.csv +27 -0
  47. package/fuse-starter-pack/branding/crudforge-mark-source.jpg +0 -0
  48. package/fuse-starter-pack/branding/crudforge-mark-source.png +0 -0
  49. package/fuse-starter-pack/branding/crudforge-mark.png +0 -0
  50. package/fuse-starter-pack/branding/crudforge-wordmark-source.jpg +0 -0
  51. package/fuse-starter-pack/branding/crudforge-wordmark-source.png +0 -0
  52. package/fuse-starter-pack/branding/crudforge-wordmark.png +0 -0
  53. package/fuse-starter-pack/fuse-v21.1/Dockerfile +14 -0
  54. package/fuse-starter-pack/fuse-v21.1/LICENSE.md +6 -0
  55. package/fuse-starter-pack/fuse-v21.1/README.md +59 -0
  56. package/fuse-starter-pack/fuse-v21.1/angular.json +113 -0
  57. package/fuse-starter-pack/fuse-v21.1/eslint.config.ts +150 -0
  58. package/fuse-starter-pack/fuse-v21.1/nginx.conf +23 -0
  59. package/fuse-starter-pack/fuse-v21.1/nginx.dev.conf +18 -0
  60. package/fuse-starter-pack/fuse-v21.1/package-lock.json +11513 -0
  61. package/fuse-starter-pack/fuse-v21.1/package.json +69 -0
  62. package/fuse-starter-pack/fuse-v21.1/postcss.config.json +5 -0
  63. package/fuse-starter-pack/fuse-v21.1/prettier.config.ts +15 -0
  64. package/fuse-starter-pack/fuse-v21.1/proxy.conf.json +8 -0
  65. package/fuse-starter-pack/fuse-v21.1/proxy.dev.conf.json +8 -0
  66. package/fuse-starter-pack/fuse-v21.1/public/favicon.png +0 -0
  67. package/fuse-starter-pack/fuse-v21.1/public/fonts/geist/Geist-Italic.woff2 +0 -0
  68. package/fuse-starter-pack/fuse-v21.1/public/fonts/geist/Geist.woff2 +0 -0
  69. package/fuse-starter-pack/fuse-v21.1/public/fonts/geist/GeistMono-Italic.woff2 +0 -0
  70. package/fuse-starter-pack/fuse-v21.1/public/fonts/geist/GeistMono.woff2 +0 -0
  71. package/fuse-starter-pack/fuse-v21.1/public/i18n/en.json +8 -0
  72. package/fuse-starter-pack/fuse-v21.1/public/i18n/es.json +8 -0
  73. package/fuse-starter-pack/fuse-v21.1/public/images/flags/ES.svg +79 -0
  74. package/fuse-starter-pack/fuse-v21.1/public/images/flags/US.svg +14 -0
  75. package/fuse-starter-pack/fuse-v21.1/public/images/flags/where-to-find-other-flags.txt +5 -0
  76. package/fuse-starter-pack/fuse-v21.1/public/images/logo/logo-mark.png +0 -0
  77. package/fuse-starter-pack/fuse-v21.1/public/images/logo/logo.png +0 -0
  78. package/fuse-starter-pack/fuse-v21.1/push.sh +27 -0
  79. package/fuse-starter-pack/fuse-v21.1/src/app/app.config.server.ts +10 -0
  80. package/fuse-starter-pack/fuse-v21.1/src/app/app.config.ts +64 -0
  81. package/fuse-starter-pack/fuse-v21.1/src/app/app.routes.server.ts +8 -0
  82. package/fuse-starter-pack/fuse-v21.1/src/app/app.routes.ts +39 -0
  83. package/fuse-starter-pack/fuse-v21.1/src/app/app.ts +22 -0
  84. package/fuse-starter-pack/fuse-v21.1/src/app/core/icons/index.ts +1 -0
  85. package/fuse-starter-pack/fuse-v21.1/src/app/core/icons/lucide.ts +1 -0
  86. package/fuse-starter-pack/fuse-v21.1/src/app/core/icons/provider.ts +23 -0
  87. package/fuse-starter-pack/fuse-v21.1/src/app/core/local-storage/index.ts +2 -0
  88. package/fuse-starter-pack/fuse-v21.1/src/app/core/local-storage/local-storage.ts +109 -0
  89. package/fuse-starter-pack/fuse-v21.1/src/app/core/local-storage/provider.ts +15 -0
  90. package/fuse-starter-pack/fuse-v21.1/src/app/core/media/index.ts +2 -0
  91. package/fuse-starter-pack/fuse-v21.1/src/app/core/media/media.ts +64 -0
  92. package/fuse-starter-pack/fuse-v21.1/src/app/core/media/provider.ts +15 -0
  93. package/fuse-starter-pack/fuse-v21.1/src/app/core/theming/index.ts +3 -0
  94. package/fuse-starter-pack/fuse-v21.1/src/app/core/theming/models/theming.ts +13 -0
  95. package/fuse-starter-pack/fuse-v21.1/src/app/core/theming/palette.ts +209 -0
  96. package/fuse-starter-pack/fuse-v21.1/src/app/core/theming/provider.ts +24 -0
  97. package/fuse-starter-pack/fuse-v21.1/src/app/core/theming/theming.ts +129 -0
  98. package/fuse-starter-pack/fuse-v21.1/src/app/core/transloco/transloco-http-loader.ts +12 -0
  99. package/fuse-starter-pack/fuse-v21.1/src/app/domains/admin/layout/data/navigation.ts +176 -0
  100. package/fuse-starter-pack/fuse-v21.1/src/app/domains/admin/layout/layout.ts +77 -0
  101. package/fuse-starter-pack/fuse-v21.1/src/app/domains/admin/layout/ui/language-switcher.ts +91 -0
  102. package/fuse-starter-pack/fuse-v21.1/src/app/domains/admin/layout/ui/navigation.ts +238 -0
  103. package/fuse-starter-pack/fuse-v21.1/src/app/domains/admin/layout/ui/notifications.ts +252 -0
  104. package/fuse-starter-pack/fuse-v21.1/src/app/domains/admin/layout/ui/scheme-switcher.ts +58 -0
  105. package/fuse-starter-pack/fuse-v21.1/src/app/domains/admin/layout/ui/sidebar.ts +31 -0
  106. package/fuse-starter-pack/fuse-v21.1/src/app/domains/admin/layout/ui/user.ts +132 -0
  107. package/fuse-starter-pack/fuse-v21.1/src/app/domains/admin/modules/apps/academy/data/academy.ts +753 -0
  108. package/fuse-starter-pack/fuse-v21.1/src/app/domains/admin/modules/apps/academy/data/model.ts +27 -0
  109. package/fuse-starter-pack/fuse-v21.1/src/app/domains/admin/modules/apps/academy/features/course.ts +318 -0
  110. package/fuse-starter-pack/fuse-v21.1/src/app/domains/admin/modules/apps/academy/features/courses.ts +228 -0
  111. package/fuse-starter-pack/fuse-v21.1/src/app/domains/admin/modules/apps/academy/routes.ts +14 -0
  112. package/fuse-starter-pack/fuse-v21.1/src/app/domains/admin/modules/apps/contacts/data/contacts.ts +4372 -0
  113. package/fuse-starter-pack/fuse-v21.1/src/app/domains/admin/modules/apps/contacts/data/model.ts +34 -0
  114. package/fuse-starter-pack/fuse-v21.1/src/app/domains/admin/modules/apps/contacts/features/contact.ts +239 -0
  115. package/fuse-starter-pack/fuse-v21.1/src/app/domains/admin/modules/apps/contacts/features/contacts.ts +185 -0
  116. package/fuse-starter-pack/fuse-v21.1/src/app/domains/admin/modules/apps/contacts/routes.ts +16 -0
  117. package/fuse-starter-pack/fuse-v21.1/src/app/domains/admin/modules/apps/file-manager/data/file-manager.ts +261 -0
  118. package/fuse-starter-pack/fuse-v21.1/src/app/domains/admin/modules/apps/file-manager/data/model.ts +12 -0
  119. package/fuse-starter-pack/fuse-v21.1/src/app/domains/admin/modules/apps/file-manager/features/file-manager.ts +131 -0
  120. package/fuse-starter-pack/fuse-v21.1/src/app/domains/admin/modules/apps/file-manager/routes.ts +15 -0
  121. package/fuse-starter-pack/fuse-v21.1/src/app/domains/admin/modules/apps/file-manager/ui/list.ts +164 -0
  122. package/fuse-starter-pack/fuse-v21.1/src/app/domains/admin/modules/apps/help-center/features/faq.ts +288 -0
  123. package/fuse-starter-pack/fuse-v21.1/src/app/domains/admin/modules/apps/help-center/features/guide.ts +134 -0
  124. package/fuse-starter-pack/fuse-v21.1/src/app/domains/admin/modules/apps/help-center/features/home.ts +219 -0
  125. package/fuse-starter-pack/fuse-v21.1/src/app/domains/admin/modules/apps/help-center/features/support.ts +161 -0
  126. package/fuse-starter-pack/fuse-v21.1/src/app/domains/admin/modules/apps/help-center/routes.ts +33 -0
  127. package/fuse-starter-pack/fuse-v21.1/src/app/domains/admin/modules/apps/notes/data/model.ts +18 -0
  128. package/fuse-starter-pack/fuse-v21.1/src/app/domains/admin/modules/apps/notes/data/notes.ts +324 -0
  129. package/fuse-starter-pack/fuse-v21.1/src/app/domains/admin/modules/apps/notes/features/note.ts +152 -0
  130. package/fuse-starter-pack/fuse-v21.1/src/app/domains/admin/modules/apps/notes/features/notes.ts +118 -0
  131. package/fuse-starter-pack/fuse-v21.1/src/app/domains/admin/modules/apps/notes/routes.ts +16 -0
  132. package/fuse-starter-pack/fuse-v21.1/src/app/domains/admin/modules/apps/tasks/data/model.ts +17 -0
  133. package/fuse-starter-pack/fuse-v21.1/src/app/domains/admin/modules/apps/tasks/data/tasks.ts +562 -0
  134. package/fuse-starter-pack/fuse-v21.1/src/app/domains/admin/modules/apps/tasks/features/task.ts +195 -0
  135. package/fuse-starter-pack/fuse-v21.1/src/app/domains/admin/modules/apps/tasks/features/tasks.ts +271 -0
  136. package/fuse-starter-pack/fuse-v21.1/src/app/domains/admin/modules/apps/tasks/routes.ts +16 -0
  137. package/fuse-starter-pack/fuse-v21.1/src/app/domains/admin/modules/dashboards/data/analytics.ts +1620 -0
  138. package/fuse-starter-pack/fuse-v21.1/src/app/domains/admin/modules/dashboards/data/finance.ts +1065 -0
  139. package/fuse-starter-pack/fuse-v21.1/src/app/domains/admin/modules/dashboards/data/project.ts +376 -0
  140. package/fuse-starter-pack/fuse-v21.1/src/app/domains/admin/modules/dashboards/features/analytics/analytics.ts +1096 -0
  141. package/fuse-starter-pack/fuse-v21.1/src/app/domains/admin/modules/dashboards/features/finance/finance.ts +658 -0
  142. package/fuse-starter-pack/fuse-v21.1/src/app/domains/admin/modules/dashboards/features/project/budget-table.ts +188 -0
  143. package/fuse-starter-pack/fuse-v21.1/src/app/domains/admin/modules/dashboards/features/project/project.ts +565 -0
  144. package/fuse-starter-pack/fuse-v21.1/src/app/domains/admin/modules/dashboards/routes.ts +23 -0
  145. package/fuse-starter-pack/fuse-v21.1/src/app/domains/admin/modules/documentation/features/changelog/changelog.ts +932 -0
  146. package/fuse-starter-pack/fuse-v21.1/src/app/domains/admin/modules/documentation/features/getting-started/building.ts +33 -0
  147. package/fuse-starter-pack/fuse-v21.1/src/app/domains/admin/modules/documentation/features/getting-started/development.ts +42 -0
  148. package/fuse-starter-pack/fuse-v21.1/src/app/domains/admin/modules/documentation/features/getting-started/installation.ts +47 -0
  149. package/fuse-starter-pack/fuse-v21.1/src/app/domains/admin/modules/documentation/layout.ts +9 -0
  150. package/fuse-starter-pack/fuse-v21.1/src/app/domains/admin/modules/documentation/routes.ts +45 -0
  151. package/fuse-starter-pack/fuse-v21.1/src/app/domains/admin/modules/extras/error/features/error-page.ts +70 -0
  152. package/fuse-starter-pack/fuse-v21.1/src/app/domains/admin/modules/extras/error/routes.ts +21 -0
  153. package/fuse-starter-pack/fuse-v21.1/src/app/domains/admin/modules/extras/notifications/features/notifications.ts +262 -0
  154. package/fuse-starter-pack/fuse-v21.1/src/app/domains/admin/modules/extras/notifications/routes.ts +10 -0
  155. package/fuse-starter-pack/fuse-v21.1/src/app/domains/admin/modules/extras/settings/features/account.ts +238 -0
  156. package/fuse-starter-pack/fuse-v21.1/src/app/domains/admin/modules/extras/settings/features/notifications.ts +134 -0
  157. package/fuse-starter-pack/fuse-v21.1/src/app/domains/admin/modules/extras/settings/features/plan-and-billing.ts +238 -0
  158. package/fuse-starter-pack/fuse-v21.1/src/app/domains/admin/modules/extras/settings/features/security.ts +211 -0
  159. package/fuse-starter-pack/fuse-v21.1/src/app/domains/admin/modules/extras/settings/features/team.ts +188 -0
  160. package/fuse-starter-pack/fuse-v21.1/src/app/domains/admin/modules/extras/settings/layout.ts +109 -0
  161. package/fuse-starter-pack/fuse-v21.1/src/app/domains/admin/modules/extras/settings/routes.ts +37 -0
  162. package/fuse-starter-pack/fuse-v21.1/src/app/domains/admin/modules/extras/welcome/welcome.component.ts +22 -0
  163. package/fuse-starter-pack/fuse-v21.1/src/app/domains/admin/routes.ts +95 -0
  164. package/fuse-starter-pack/fuse-v21.1/src/app/domains/auth/features/forgot-password/forgot-password.html +54 -0
  165. package/fuse-starter-pack/fuse-v21.1/src/app/domains/auth/features/forgot-password/forgot-password.ts +51 -0
  166. package/fuse-starter-pack/fuse-v21.1/src/app/domains/auth/features/reset-password/reset-password.html +82 -0
  167. package/fuse-starter-pack/fuse-v21.1/src/app/domains/auth/features/reset-password/reset-password.ts +69 -0
  168. package/fuse-starter-pack/fuse-v21.1/src/app/domains/auth/features/sign-in/sign-in.html +132 -0
  169. package/fuse-starter-pack/fuse-v21.1/src/app/domains/auth/features/sign-in/sign-in.ts +54 -0
  170. package/fuse-starter-pack/fuse-v21.1/src/app/domains/auth/features/sign-up/sign-up.html +183 -0
  171. package/fuse-starter-pack/fuse-v21.1/src/app/domains/auth/features/sign-up/sign-up.ts +56 -0
  172. package/fuse-starter-pack/fuse-v21.1/src/app/domains/auth/layout.ts +9 -0
  173. package/fuse-starter-pack/fuse-v21.1/src/app/domains/auth/routes.ts +34 -0
  174. package/fuse-starter-pack/fuse-v21.1/src/app/domains/coming-soon/features/coming-soon.ts +156 -0
  175. package/fuse-starter-pack/fuse-v21.1/src/app/domains/coming-soon/layout.ts +9 -0
  176. package/fuse-starter-pack/fuse-v21.1/src/app/domains/coming-soon/routes.ts +16 -0
  177. package/fuse-starter-pack/fuse-v21.1/src/app/domains/website/layout/layout.ts +9 -0
  178. package/fuse-starter-pack/fuse-v21.1/src/app/domains/website/modules/home/features/home.ts +23 -0
  179. package/fuse-starter-pack/fuse-v21.1/src/app/domains/website/modules/home/routes.ts +10 -0
  180. package/fuse-starter-pack/fuse-v21.1/src/app/domains/website/routes.ts +30 -0
  181. package/fuse-starter-pack/fuse-v21.1/src/environments/environment.mock.ts +5 -0
  182. package/fuse-starter-pack/fuse-v21.1/src/environments/environment.prod.ts +5 -0
  183. package/fuse-starter-pack/fuse-v21.1/src/environments/environment.ts +5 -0
  184. package/fuse-starter-pack/fuse-v21.1/src/index.html +66 -0
  185. package/fuse-starter-pack/fuse-v21.1/src/main.server.ts +11 -0
  186. package/fuse-starter-pack/fuse-v21.1/src/main.ts +5 -0
  187. package/fuse-starter-pack/fuse-v21.1/src/server.ts +70 -0
  188. package/fuse-starter-pack/fuse-v21.1/src/styles/base/base.css +63 -0
  189. package/fuse-starter-pack/fuse-v21.1/src/styles/base/typography.css +54 -0
  190. package/fuse-starter-pack/fuse-v21.1/src/styles/components/a.css +18 -0
  191. package/fuse-starter-pack/fuse-v21.1/src/styles/components/input.css +22 -0
  192. package/fuse-starter-pack/fuse-v21.1/src/styles/components/kbd.css +55 -0
  193. package/fuse-starter-pack/fuse-v21.1/src/styles/components/material.css +1149 -0
  194. package/fuse-starter-pack/fuse-v21.1/src/styles/styles.css +31 -0
  195. package/fuse-starter-pack/fuse-v21.1/src/styles/tailwind/theme.css +147 -0
  196. package/fuse-starter-pack/fuse-v21.1/src/styles/tailwind/utilities.css +563 -0
  197. package/fuse-starter-pack/fuse-v21.1/src/styles/tailwind/variants.css +4 -0
  198. package/fuse-starter-pack/fuse-v21.1/src/styles/third-party/lucide-icons.css +12 -0
  199. package/fuse-starter-pack/fuse-v21.1/tsconfig.app.json +16 -0
  200. package/fuse-starter-pack/fuse-v21.1/tsconfig.json +37 -0
  201. package/fuse-starter-pack/fuse-v21.1/tsconfig.spec.json +10 -0
  202. package/generator/README.md +12 -0
  203. package/generator/issues/.gitkeep +0 -0
  204. package/package.json +56 -4
  205. package/playwright.config.js +29 -0
  206. package/playwright.field-profile.config.js +6 -0
  207. package/playwright.iam-live.config.js +31 -0
  208. package/playwright.iam.config.js +29 -0
  209. package/playwright.list-state.config.js +6 -0
  210. package/playwright.performance.config.js +1 -0
  211. package/run-config-tests.sh +5 -0
  212. package/scripts/e2e-paths.js +89 -0
  213. package/scripts/e2e-prepare-field-profile.js +17 -0
  214. package/scripts/e2e-prepare-iam-live.js +135 -0
  215. package/scripts/e2e-prepare-iam.js +65 -0
  216. package/scripts/e2e-prepare.js +72 -0
  217. package/scripts/e2e-serve-iam-live.js +28 -0
  218. package/scripts/e2e-serve-iam.js +28 -0
  219. package/scripts/e2e-serve.js +28 -0
  220. package/scripts/performance/generate.js +17 -0
  221. package/scripts/performance/measure.js +55 -0
  222. package/scripts/postinstall.js +9 -0
  223. package/scripts/prepare-quality-apps.js +34 -0
  224. package/scripts/run-config-tests.js +63 -0
  225. package/src/assets/logo-with-lable.jpeg +0 -0
  226. package/src/assets/logo.jpeg +0 -0
  227. package/src/commands/bootstrap.js +92 -0
  228. package/src/commands/doctor.js +403 -0
  229. package/src/commands/generate.js +301 -0
  230. package/src/commands/init-config.js +310 -0
  231. package/src/commands/keycloak-options.js +182 -0
  232. package/src/commands/validate.js +52 -0
  233. package/src/config/auth-config.js +183 -0
  234. package/src/config/default-values.js +235 -0
  235. package/src/config/env-refs.js +71 -0
  236. package/src/config/field-preferences.js +99 -0
  237. package/src/config/input-sources.js +104 -0
  238. package/src/config/load-config.js +166 -0
  239. package/src/config/proxy-routes.js +44 -0
  240. package/src/generator/access-control-tools.js +334 -0
  241. package/src/generator/ai-docs.js +691 -0
  242. package/src/generator/application-tests.js +252 -0
  243. package/src/generator/auth-pack.js +965 -0
  244. package/src/generator/embed-config.js +431 -0
  245. package/src/generator/entity-layout.js +30 -0
  246. package/src/generator/fuse-build.js +57 -0
  247. package/src/generator/fuse-runtime.js +344 -0
  248. package/src/generator/generated-banner.js +137 -0
  249. package/src/generator/index.js +874 -0
  250. package/src/generator/project-output.js +126 -0
  251. package/src/generator/team-pack.js +220 -0
  252. package/src/index.js +68 -0
  253. package/src/parser/gdl-parser.js +169 -0
  254. package/src/parser/jdl-parser.js +171 -0
  255. package/src/presets/pmb-test.js +139 -0
  256. package/src/presets/static-source.js +73 -0
  257. package/src/presets/store.js +96 -0
  258. package/src/provision/admin-service.js +148 -0
  259. package/src/provision/bootstrap.js +147 -0
  260. package/src/provision/http.js +123 -0
  261. package/src/provision/keycloak-admin-rest.js +335 -0
  262. package/src/provision/state.js +51 -0
  263. package/src/provision/token.js +52 -0
  264. package/src/templates/angular/auth/access-control.service.ts.ejs +179 -0
  265. package/src/templates/angular/auth/access-ctrl.pipe.ts.ejs +20 -0
  266. package/src/templates/angular/auth/auth.guard.ts.ejs +27 -0
  267. package/src/templates/angular/auth/auth.interceptor.ts.ejs +53 -0
  268. package/src/templates/angular/auth/auth.service.ts.ejs +594 -0
  269. package/src/templates/angular/auth/auth.utils.ts.ejs +28 -0
  270. package/src/templates/angular/auth/current-user.ts.ejs +24 -0
  271. package/src/templates/angular/auth/disabled-account-overlay.component.css.ejs +95 -0
  272. package/src/templates/angular/auth/disabled-account-overlay.component.html.ejs +33 -0
  273. package/src/templates/angular/auth/disabled-account-overlay.component.ts.ejs +23 -0
  274. package/src/templates/angular/auth/fuse-account.ts.ejs +234 -0
  275. package/src/templates/angular/auth/fuse-user.ts.ejs +264 -0
  276. package/src/templates/angular/auth/has-permission.directive.ts.ejs +51 -0
  277. package/src/templates/angular/auth/index.ts.ejs +24 -0
  278. package/src/templates/angular/auth/keycloak-admin.service.ts.ejs +670 -0
  279. package/src/templates/angular/auth/landing.guard.ts.ejs +61 -0
  280. package/src/templates/angular/auth/no-auth.guard.ts.ejs +19 -0
  281. package/src/templates/angular/auth/permission-attribute.util.ts.ejs +182 -0
  282. package/src/templates/angular/auth/sign-in.ts.ejs +60 -0
  283. package/src/templates/angular/entity/_entity_.model.ts.ejs +64 -0
  284. package/src/templates/angular/entity/_entity_.routes.ts.ejs +9 -0
  285. package/src/templates/angular/entity/components/forms/form/_entity_-form.component.html.ejs +168 -0
  286. package/src/templates/angular/entity/components/forms/form/_entity_-form.component.ts.ejs +175 -0
  287. package/src/templates/angular/entity/components/forms/form-page/_entity_-form-page.component.html.ejs +10 -0
  288. package/src/templates/angular/entity/components/forms/form-page/_entity_-form-page.component.ts.ejs +86 -0
  289. package/src/templates/angular/entity/components/forms/update/_entity_-form.service.ts.ejs +136 -0
  290. package/src/templates/angular/entity/components/interaction/actions/_entity_-actions.component.html.ejs +68 -0
  291. package/src/templates/angular/entity/components/interaction/actions/_entity_-actions.component.ts.ejs +69 -0
  292. package/src/templates/angular/entity/components/interaction/filter/_entity_-filter.component.html.ejs +111 -0
  293. package/src/templates/angular/entity/components/interaction/filter/_entity_-filter.component.ts.ejs +102 -0
  294. package/src/templates/angular/entity/components/presentation/card/_entity_-card.component.css.ejs +33 -0
  295. package/src/templates/angular/entity/components/presentation/card/_entity_-card.component.html.ejs +29 -0
  296. package/src/templates/angular/entity/components/presentation/card/_entity_-card.component.ts.ejs +93 -0
  297. package/src/templates/angular/entity/components/presentation/detail/_entity_-detail.component.css.ejs +54 -0
  298. package/src/templates/angular/entity/components/presentation/detail/_entity_-detail.component.html.ejs +58 -0
  299. package/src/templates/angular/entity/components/presentation/detail/_entity_-detail.component.ts.ejs +47 -0
  300. package/src/templates/angular/entity/components/presentation/list/_entity_-list.component.html.ejs +419 -0
  301. package/src/templates/angular/entity/components/presentation/list/_entity_-list.component.scss.ejs +48 -0
  302. package/src/templates/angular/entity/components/presentation/list/_entity_-list.component.ts.ejs +592 -0
  303. package/src/templates/angular/entity/service/_entity_.service.ts.ejs +153 -0
  304. package/src/templates/angular/entity/settings/_entity_.settings.ts.ejs +49 -0
  305. package/src/templates/angular/enums/_enum_.model.ts.ejs +11 -0
  306. package/src/templates/angular/iam/change-password.component.html.ejs +39 -0
  307. package/src/templates/angular/iam/change-password.component.ts.ejs +44 -0
  308. package/src/templates/angular/iam/no-access.component.ts.ejs +17 -0
  309. package/src/templates/angular/iam/role-list.component.html.ejs +331 -0
  310. package/src/templates/angular/iam/role-list.component.scss.ejs +107 -0
  311. package/src/templates/angular/iam/role-list.component.ts.ejs +597 -0
  312. package/src/templates/angular/iam/role-management/role-header.component.html.ejs +51 -0
  313. package/src/templates/angular/iam/role-management/role-header.component.ts.ejs +45 -0
  314. package/src/templates/angular/iam/role-management/role-inheritance.component.html.ejs +15 -0
  315. package/src/templates/angular/iam/role-management/role-inheritance.component.ts.ejs +19 -0
  316. package/src/templates/angular/iam/role-management/role-permissions-panel.component.css.ejs +24 -0
  317. package/src/templates/angular/iam/role-management/role-permissions-panel.component.html.ejs +108 -0
  318. package/src/templates/angular/iam/role-management/role-permissions-panel.component.ts.ejs +122 -0
  319. package/src/templates/angular/iam/role-management/role-users.component.html.ejs +104 -0
  320. package/src/templates/angular/iam/role-management/role-users.component.ts.ejs +53 -0
  321. package/src/templates/angular/iam/role-management/user-select-dialog.component.html.ejs +113 -0
  322. package/src/templates/angular/iam/role-management/user-select-dialog.component.ts.ejs +157 -0
  323. package/src/templates/angular/iam/role-permission-matrix.component.html.ejs +355 -0
  324. package/src/templates/angular/iam/role-permission-matrix.component.scss.ejs +217 -0
  325. package/src/templates/angular/iam/role-permission-matrix.component.ts.ejs +800 -0
  326. package/src/templates/angular/iam/screen-catalog.ts.ejs +147 -0
  327. package/src/templates/angular/iam/shared/confirm-dialog.component.ts.ejs +83 -0
  328. package/src/templates/angular/iam/shared/matrix-hierarchy.util.ts.ejs +196 -0
  329. package/src/templates/angular/iam/shared/permission-matrix-sound.ts.ejs +59 -0
  330. package/src/templates/angular/iam/shared/role-display.util.ts.ejs +43 -0
  331. package/src/templates/angular/iam/shared/role-permission-skeleton.component.ts.ejs +54 -0
  332. package/src/templates/angular/iam/shared/screen-matrix.util.ts.ejs +554 -0
  333. package/src/templates/angular/iam/shared/screen-navigation-map.ts.ejs +187 -0
  334. package/src/templates/angular/iam/shared/screen-navigation.registry.ts.ejs +64 -0
  335. package/src/templates/angular/iam/shared/text-highlight.pipe.ts.ejs +39 -0
  336. package/src/templates/angular/iam/user-access-matrix.component.html.ejs +212 -0
  337. package/src/templates/angular/iam/user-access-matrix.component.scss.ejs +34 -0
  338. package/src/templates/angular/iam/user-access-matrix.component.ts.ejs +239 -0
  339. package/src/templates/angular/iam/user-detail.component.html.ejs +143 -0
  340. package/src/templates/angular/iam/user-detail.component.ts.ejs +108 -0
  341. package/src/templates/angular/iam/user-form.component.html.ejs +63 -0
  342. package/src/templates/angular/iam/user-form.component.ts.ejs +100 -0
  343. package/src/templates/angular/iam/user-list.component.html.ejs +369 -0
  344. package/src/templates/angular/iam/user-list.component.scss.ejs +242 -0
  345. package/src/templates/angular/iam/user-list.component.ts.ejs +446 -0
  346. package/src/templates/angular/iam/user-management.routes.ts.ejs +47 -0
  347. package/src/templates/angular/iam/user-permission-matrix.component.html.ejs +231 -0
  348. package/src/templates/angular/iam/user-permission-matrix.component.scss.ejs +216 -0
  349. package/src/templates/angular/iam/user-permission-matrix.component.ts.ejs +516 -0
  350. package/src/templates/angular/shared/base/audit-user-name.pipe.ts.ejs +69 -0
  351. package/src/templates/angular/shared/base/base-filter.component.ts.ejs +245 -0
  352. package/src/templates/angular/shared/base/base-form.component.ts.ejs +109 -0
  353. package/src/templates/angular/shared/base/base-list.component.ts.ejs +507 -0
  354. package/src/templates/angular/shared/base/filter-types.ts.ejs +55 -0
  355. package/src/templates/angular/shared/base/input-format.directive.ts.ejs +47 -0
  356. package/src/templates/angular/shared/base/input-format.ts.ejs +15 -0
  357. package/src/templates/angular/shared/confirm-with-input-dialog.component.ts.ejs +91 -0
  358. package/src/templates/angular/shared/confirmation-dialog.component.ts.ejs +80 -0
  359. package/src/templates/angular/shared/list-styles.css.ejs +103 -0
  360. package/src/templates/angular/shared/loading-overlay.component.ts.ejs +24 -0
  361. package/src/templates/angular/shared/resizable.directive.ts.ejs +115 -0
  362. package/src/templates/angular/shared/snackbar-styles.css.ejs +11 -0
  363. package/src/templates/fuse-packs/access-control-tools/access-control-sync.js +819 -0
  364. package/src/templates/fuse-packs/access-control-tools/build-rename-map.js +67 -0
  365. package/src/templates/fuse-packs/access-control-tools/inject-qa-ids.js +14 -0
  366. package/src/templates/fuse-packs/access-control-tools/lib/hierarchy-scanner.js +628 -0
  367. package/src/templates/fuse-packs/access-control-tools/lib/hierarchy-scanner.test.js +323 -0
  368. package/src/templates/fuse-packs/access-control-tools/lib/html-scanner.js +362 -0
  369. package/src/templates/fuse-packs/access-control-tools/lib/id-rules.duplicate.test.js +136 -0
  370. package/src/templates/fuse-packs/access-control-tools/lib/id-rules.js +1095 -0
  371. package/src/templates/fuse-packs/access-control-tools/lib/ts-component-index.js +482 -0
  372. package/src/templates/fuse-packs/access-control-tools/output/.gitkeep +0 -0
  373. package/src/templates/fuse-packs/access-control-tools/run.sh +223 -0
  374. package/src/templates/fuse-packs/access-control-tools/scan-access-control.js +14 -0
  375. package/src/templates/fuse-packs/iam-assets/sound/apple-play.mp3 +0 -0
  376. package/src/templates/fuse-packs/iam-assets/sound/remove.mp3 +0 -0
  377. package/src/templates/generator/README.md +12 -0
  378. package/src/templates/testing/ci.cjs +45 -0
  379. package/src/templates/testing/mock.cjs +149 -0
  380. package/src/templates/testing/playwright.config.cjs +25 -0
  381. package/src/templates/testing/serve.cjs +22 -0
  382. package/src/templates/testing/smoke.spec.cjs +180 -0
  383. package/src/utils/branding.js +39 -0
  384. package/src/utils/colors.js +18 -0
  385. package/src/utils/diff.js +109 -0
  386. package/src/utils/merger.js +115 -0
  387. package/src/validator/backend-diagnostics.js +30 -0
  388. package/src/validator/blueprint-validator.js +276 -0
  389. package/src/validator/diagnostics.js +608 -0
  390. package/src/validator/pattern.js +28 -0
  391. package/test/auth-interceptor.js +84 -0
  392. package/test/auth-provision-checks.js +297 -0
  393. package/test/field-preferences.js +145 -0
  394. package/test/fixtures/field-profile.gdl +7 -0
  395. package/test/fixtures/mock.jdl +17 -0
  396. package/test/fixtures/mock.png +0 -0
  397. package/test/fixtures/performance/config.yml +33 -0
  398. package/test/fixtures/performance/large.gdl +199 -0
  399. package/test/fixtures/performance/small.gdl +7 -0
  400. package/test/fixtures/quality/custom.yml +22 -0
  401. package/test/fixtures/quality/go-duck.yml +22 -0
  402. package/test/fixtures/quality/jhipster.yml +30 -0
  403. package/test/fixtures/quality/representative.gdl +14 -0
  404. package/test/list-state.js +138 -0
  405. package/test/micro-functions-layout.js +95 -0
  406. package/test/performance-generation.js +32 -0
  407. package/test/pmb-preset.js +127 -0
  408. package/test/project-workflow.js +111 -0
  409. package/test/quality-features.js +250 -0
  410. package/test/verify-commands.js +83 -0
  411. package/test/verify.js +959 -0
  412. package/test-files/GDL/example.gdl +15 -0
  413. package/test-files/JDL/example.jdl +15 -0
  414. package/test-files/config/crudforge.config.yml +127 -0
  415. package/test-run.sh +272 -0
package/README.md CHANGED
@@ -1,3 +1,852 @@
1
- # Temporary Holding Version
1
+ # @team-codeme/crud-forge
2
2
 
3
- This version is a temporary placeholder for this package. An operational version to replace this has been submitted for review and is awaiting a staged release.
3
+ ```text
4
+ ____ ____ _ _ ____ _____ _ ___
5
+ / ___| _ \| | | | _ \| ___|__ _ __ __ _ ___ | | |_ _|
6
+ | | | |_) | | | | | | | |_ / _ \| '__/ _` |/ _ \ | | | |
7
+ | |___| _ <| |_| | |_| | _| (_) | | | (_| | __/ | |___ | |
8
+ \____|_| \_\___/|____/|_| \___/|_| \__, |\___| |_____|___|
9
+ |___/
10
+ Developed by TeamCodeMe
11
+ Official Website: https://crudforge.teamcodeme.com/
12
+ Documentation: https://crudforge-cli-doc.vercel.app
13
+ ```
14
+
15
+ ![CRUDForge poster](https://lh3.googleusercontent.com/kTtVlTPXl9b8qEU7VXoz8u6eRtiAXjcnLIMVPlWnsJKUEI5Xx_EbjiAcH1afwmV-1sho3l_JPjNphGAC5Oszr1rA0V2uvdBs9mhLkK8Z=s960)
16
+
17
+ <div align="center">
18
+
19
+ [![Official Website](https://img.shields.io/badge/Official%20Website-crudforge.teamcodeme.com-blue?style=for-the-badge&logo=googlechrome&logoColor=white)](https://crudforge.teamcodeme.com/)
20
+ [![Documentation](https://img.shields.io/badge/Documentation-crudforge--cli--doc.vercel.app-success?style=for-the-badge&logo=vercel&logoColor=white)](https://crudforge-cli-doc.vercel.app)
21
+ [![npm version](https://img.shields.io/npm/v/@team-codeme/crud-forge?style=for-the-badge&color=cb3837&logo=npm)](https://www.npmjs.com/package/@team-codeme/crud-forge)
22
+
23
+ </div>
24
+
25
+ CRUDForge CLI is a high-performance, developer-configurable Angular Material CRUD code generator. It maps JDL (JHipster Domain Language) or GDL schemas directly into high-fidelity standalone Angular 17+ components, types, services, and routes.
26
+
27
+ - ๐ŸŒ **Official Website:** [https://crudforge.teamcodeme.com/](https://crudforge.teamcodeme.com/)
28
+ - ๐Ÿ“– **Documentation:** [https://crudforge-cli-doc.vercel.app](https://crudforge-cli-doc.vercel.app)
29
+ - ๐Ÿข **Organization:** [@team-codeme](https://www.npmjs.com/org/team-codeme)
30
+
31
+ **Product docs (deployable Starlight site):** Available live at [crudforge-cli-doc.vercel.app](https://crudforge-cli-doc.vercel.app) (source in sibling repo [`crud-fordge-doc`](../crud-fordge-doc)) โ€” splash uses the same poster; Features / Customization galleries with screenshots. Capture shots: `npm run e2e:serve` then `cd ../crud-fordge-doc && npm run shots:capture` (IAM: `e2e:serve:iam` + `shots:capture:iam`).
32
+
33
+ ---
34
+
35
+ ## ๐Ÿ“‚ Layout Structure
36
+
37
+ CRUDForge structures entity templates under a responsibility-based directory layout:
38
+
39
+ ```text
40
+ src/templates/angular/
41
+ โ””โ”€โ”€ entity/
42
+ โ”œโ”€โ”€ _entity_.model.ts.ejs # Angular domain models
43
+ โ”œโ”€โ”€ _entity_.routes.ts.ejs # Routing config
44
+ โ”œโ”€โ”€ service/
45
+ โ”‚ โ””โ”€โ”€ _entity_.service.ts.ejs # REST client data services
46
+ โ”œโ”€โ”€ components/
47
+ โ”‚ โ”œโ”€โ”€ presentation/ # Read-only UI layouts
48
+ โ”‚ โ”‚ โ”œโ”€โ”€ card/ # Compact tile displays
49
+ โ”‚ โ”‚ โ”œโ”€โ”€ detail/ # Detailed properties sheet
50
+ โ”‚ โ”‚ โ””โ”€โ”€ list/ # Central pagination table
51
+ โ”‚ โ”œโ”€โ”€ forms/ # Input and update logic
52
+ โ”‚ โ”‚ โ”œโ”€โ”€ form/ # Reusable form component
53
+ โ”‚ โ”‚ โ”œโ”€โ”€ form-page/ # Independent route page
54
+ โ”‚ โ”‚ โ””โ”€โ”€ update/ # Reactive FormGroup validation mapper
55
+ โ”‚ โ””โ”€โ”€ interaction/ # Control actions & query filtering
56
+ โ”‚ โ”œโ”€โ”€ actions/ # Action buttons and query filters toolbar
57
+ โ”‚ โ””โ”€โ”€ filter/ # Advanced search/filter sidebar panel
58
+ โ””โ”€โ”€ shared/ # (Generated inside each entity or centralized)
59
+ โ”œโ”€โ”€ base/ # Centralized abstract base classes
60
+ โ”‚ โ”œโ”€โ”€ base-filter.component.ts.ejs # Shared filter logic & reactive forms
61
+ โ”‚ โ”œโ”€โ”€ base-form.component.ts.ejs # Shared form state & error handling
62
+ โ”‚ โ”œโ”€โ”€ base-list.component.ts.ejs # Shared pagination, export, & row states
63
+ โ”‚ โ””โ”€โ”€ filter-types.ts.ejs # Shared filter types
64
+ โ”œโ”€โ”€ confirmation-dialog.component.ts.ejs # Generic confirmation dialog
65
+ โ”œโ”€โ”€ resizable.directive.ts.ejs # Table column resizing directive
66
+ โ””โ”€โ”€ snackbar-styles.css.ejs # Global snackbar theming
67
+ ```
68
+
69
+ When code is generated, the target directory matches this structure to promote strict modularity and clean imports in the generated Angular application.
70
+
71
+ ---
72
+
73
+ ## ๐Ÿ“ฆ Installation
74
+
75
+ To install CRUDForge CLI globally on your system:
76
+
77
+ ```bash
78
+ npm install -g @team-codeme/crud-forge
79
+ ```
80
+
81
+ Or run directly without installation using `npx`:
82
+
83
+ ```bash
84
+ npx @team-codeme/crud-forge init my-app
85
+ ```
86
+
87
+ ---
88
+
89
+ ## ๐Ÿ› ๏ธ CLI Usage
90
+
91
+ ### Initialize โ†’ edit โ†’ generate
92
+
93
+ Start with editable project inputs, before generating Angular:
94
+
95
+ ```bash
96
+ crudforge init crudforge-app
97
+ cd crudforge-app
98
+ # Edit config/crudforge.config.yml and gdl/example.gdl
99
+ crudforge generate
100
+ npm install
101
+ npm run dev
102
+ ```
103
+
104
+ `init` creates only these two files in a new or empty directory:
105
+
106
+ ```text
107
+ crudforge-app/
108
+ โ”œโ”€โ”€ config/
109
+ โ”‚ โ””โ”€โ”€ crudforge.config.yml
110
+ โ””โ”€โ”€ gdl/
111
+ โ””โ”€โ”€ example.gdl
112
+ ```
113
+
114
+ The default sample uses the supported GDL syntax (type before field name):
115
+
116
+ ```gdl
117
+ entity Book {
118
+ string title required
119
+ bigDecimal price
120
+ }
121
+ ```
122
+
123
+ Supported entity annotations (GDL):
124
+
125
+ | Annotation | Effect |
126
+ |---|---|
127
+ | `@Audited` | Injects configured audit fields (`createdBy`, `createdDate`, โ€ฆ) |
128
+ | `@Searchable` | Marks the entity for list search; searchable columns prefer text/enum fields |
129
+ | `@ActiveStatus` | Injects `bool isActive` on the model (skipped if already declared); enables list activate/deactivate |
130
+
131
+ JDL equivalents: `@EnableAudit`, `@Searchable`, `@ActiveStatus`. Other annotations (e.g. `@SoftDelete`) still fail validation.
132
+
133
+ The generated configuration includes the existing project settings and these workflow defaults:
134
+
135
+ ```yaml
136
+ input:
137
+ type: gdl
138
+ file: ./gdl/example.gdl # single schema (legacy)
139
+ # Or multiple GDL/JDL files per backend service:
140
+ # sources:
141
+ # - name: identity-access
142
+ # file: ./GDL/identity-access.gdl
143
+ # microservice: identity-access-module
144
+ # - name: inventory
145
+ # file: ./GDL/inventory.gdl
146
+ # microservice: inventory-service
147
+ # Enums: src/app/domains/admin/modules/apps/micro-functions/<service-folder>/enum/
148
+ # Every service keeps enum/ with a .gitkeep, even without enum definitions.
149
+ # Generated entities: src/app/domains/admin/modules/apps/micro-functions/<service-folder>/entities/<entity>/
150
+ # sources[].folder can preserve module names such as identityAccessModule.
151
+ # Single-schema module folders use api.microservice; multi-source folders use sources[].folder or name.
152
+ output:
153
+ directory: .
154
+ overwritePolicy: fail
155
+ fuse:
156
+ enabled: true
157
+ rendering: spa
158
+ cleanLayout: true
159
+ includePrebuilt: false
160
+ theme:
161
+ scheme: system # system | light | dark
162
+ primary: "#0D1E3A" # default navy โ€” buttons / accents via root fuseTheme
163
+ error: "#dc2626"
164
+ api:
165
+ microservice: book-service # fallback when a source omits microservice
166
+ auth:
167
+ provider: none
168
+ ```
169
+
170
+ `input.sources[]` generates one nav group and `apps/<folder>/` tree per service (`name`),
171
+ and each entityโ€™s HTTP client uses that sourceโ€™s `microservice`. Entity names must stay unique
172
+ across all listed files. Prefer `sources` for multi-backend apps; keep `input.file` for one schema.
173
+
174
+ Update entities, relationships, the microservice identifier, and any supported settings before
175
+ running `crudforge generate`. It finds the project's configuration, validates it and the
176
+ referenced schema, and adds the Fuse application directly into the same folder:
177
+
178
+ ```text
179
+ crudforge-app/
180
+ โ”œโ”€โ”€ config/
181
+ โ”‚ โ””โ”€โ”€ crudforge.config.yml
182
+ โ”œโ”€โ”€ gdl/
183
+ โ”‚ โ””โ”€โ”€ example.gdl
184
+ โ”œโ”€โ”€ src/
185
+ โ”œโ”€โ”€ angular.json
186
+ โ”œโ”€โ”€ package.json
187
+ โ””โ”€โ”€ ...
188
+ ```
189
+
190
+ The source configuration and GDL remain unchanged, including comments. There is no nested
191
+ application folder. `input.file`, `input.sources[].file`, and `output.directory` are relative to the project root,
192
+ not `config/`. Without a positional schema, `--preferences /path/to/app/config/crudforge.config.yml`
193
+ also anchors relative paths at `/path/to/app`; a root-level config anchors at its containing
194
+ directory. Moving the whole initialized project therefore needs no path edits.
195
+
196
+ Discovery checks `config/crudforge.config.yml`, `config/crudforge.config.yaml`,
197
+ `crudforge.config.yml`, `crudforge.config.yaml`, `config/config.yml`, then `crudforge.config.json`.
198
+ An explicit `--preferences` takes precedence. Missing or malformed inputs fail with file paths
199
+ before project files are written; invalid config no longer silently falls back to defaults.
200
+
201
+ On regeneration, differing existing application files require an overwrite policy. The CLI
202
+ honors `output.overwritePolicy`, with an explicit flag taking precedence; the fallback is `fail`.
203
+ Fuse starter files and generated files follow the same policy. Source configuration and schema
204
+ files are protected even with `overwrite`. No stale or unrelated files are automatically deleted.
205
+
206
+ ```bash
207
+ crudforge generate --dry-run # preview without changing project files
208
+ crudforge generate --overwrite-policy ask # resolve each conflict interactively
209
+ crudforge generate --overwrite-policy skip # keep differing existing files
210
+ crudforge generate --overwrite-policy merge # preserve matching cforge custom-code zones
211
+ crudforge generate --overwrite-policy overwrite # explicitly replace generated application files
212
+ ```
213
+
214
+ `merge` preserves marked custom-code zones, not arbitrary edits; binary conflicts require
215
+ `ask`, `skip`, or `overwrite`. `ask` fails on conflicts in noninteractive CI. `--yes` does not
216
+ authorize overwriting files. `fail` checks all differing files before applying changes.
217
+
218
+ ### Optional PMB development testing preset
219
+
220
+ Use Node 24+ for the generated application. Import the PMB development settings once:
221
+
222
+ ```bash
223
+ crudforge init crudforge-app --preset pmb-test --source /path/to/PMB/pmb-admin
224
+ cd crudforge-app
225
+ # Optional: edit config/crudforge.config.yml and gdl/example.gdl
226
+ crudforge generate
227
+ npm install
228
+ npm run dev -- --port 4200
229
+ ```
230
+
231
+ Open `http://localhost:4200/auth/sign-in` and enter your existing PMB login. The CLI prints
232
+ the actual port extracted from PMB's development settings. If that port is occupied, pass
233
+ a free port to `npm run dev -- --port <port>`. `npm start` selects the production build;
234
+ use the printed `npm run dev` command for this testing workflow.
235
+
236
+ The first command only creates the editable config and sample GDL. It reads PMB without
237
+ executing its scripts or modifying its files. The importer follows the development Angular
238
+ environment replacement and serve/proxy settings, checks the public-client token flow,
239
+ and maps the Province model/client to its reference-module route. Unsupported dynamic
240
+ settings or a changed authentication contract produce actionable errors instead of guesses.
241
+
242
+ The reusable preset is stored at `${XDG_CONFIG_HOME:-~/.config}/crudforge/presets/pmb-test/`:
243
+
244
+ ```text
245
+ pmb-test/
246
+ โ”œโ”€โ”€ config.yml
247
+ โ”œโ”€โ”€ example.gdl
248
+ โ””โ”€โ”€ metadata.json
249
+ ```
250
+
251
+ The metadata records source-file hashes, the source location, import time, sample endpoint,
252
+ and verification limitations. The source location is not copied into the generated app.
253
+ Configuration and schema paths in the app remain project-relative. The app does not need
254
+ access to the registry or PMB source after initialization.
255
+
256
+ After deleting a disposable generated app, recreate it without re-entering backend settings:
257
+
258
+ ```bash
259
+ crudforge init crudforge-app --preset pmb-test
260
+ cd crudforge-app
261
+ crudforge generate
262
+ npm install
263
+ npm run dev -- --port 4200
264
+ ```
265
+
266
+ Refresh the saved preset when the PMB source changes:
267
+
268
+ ```bash
269
+ crudforge preset refresh pmb-test --source /path/to/PMB/pmb-admin
270
+ ```
271
+
272
+ Refresh validates the new settings before replacing the preset, retains a timestamped backup
273
+ beside it, and leaves existing apps unchanged. Initial import refuses to replace an existing
274
+ preset; use `refresh` explicitly. Normal `crudforge init <directory>` remains independent of PMB.
275
+
276
+ The preset maps real public-client login, refresh and logout, PMB admin roles, idle timeout,
277
+ service targets and aliases. It includes `proxy.routes` for explicit proxy entries and
278
+ `devServer.port` for the development server. Explicit proxy routes override auto-generated
279
+ entries and apply to the files selected by `proxy.write`; specific routes precede catch-all
280
+ prefixes. Supported entry fields are `target`, `secure`, `changeOrigin`, `ws`, `logLevel`, and
281
+ `pathRewrite`. Headers, cookies, credentials and executable proxy hooks are not imported.
282
+ Both proxy files in this testing preset intentionally target PMB development services.
283
+
284
+ The sample `Province` uses PMB's frontend model and reference API path. Authentication and
285
+ API reachability still require runtime verification. Arbitrary new GDL entities do not create
286
+ backend endpoints. The importer does not copy DAD secondary-login credentials, confidential
287
+ internal clients, account passwords, or tokens; it never provisions or restarts services.
288
+ Live sign-in forms do not inherit `KEYCLOAK_ADMIN_*` credentials from the CLI environment.
289
+
290
+ Privileged IAM management screens are disabled by this preset. PMB's non-admin screen
291
+ permissions, profile/business context, and backend write constraints are not reproduced
292
+ by a frontend preset and require separate verification for the intended account. Automated
293
+ live checks should use only read-only API requests; a successful build is not proof of login
294
+ or backend permissions.
295
+
296
+ Validation commands for contributors:
297
+
298
+ ```bash
299
+ npm test # includes isolated preset import/reuse/refresh and generation checks
300
+ npm run test:auth # Node 24+: refresh/retry and session-error behavior
301
+ ```
302
+
303
+ ### Existing commands
304
+
305
+ Explicit schema/output generation remains supported. Explicit CLI paths and config-relative
306
+ paths in this legacy form resolve from the current working directory:
307
+
308
+ ```bash
309
+ crudforge generate <path-to-schema.jdl> <target-output-folder> [options]
310
+ ```
311
+
312
+ The existing `init-config` command still creates `crudforge.config.yml`, `example.jdl`, and
313
+ `example.gdl` in the current directory, skipping existing files. Use `init <directory>` for
314
+ the project-owned input workflow:
315
+
316
+ ```bash
317
+ crudforge init-config
318
+ ```
319
+
320
+ Validate a schema blueprint against generation rules without writing files:
321
+
322
+ ```bash
323
+ crudforge validate <path-to-schema.jdl>
324
+ ```
325
+
326
+ Bootstrap Keycloak resources (client, roles, initial users) without generating an app. **Does not run during `generate`.**
327
+
328
+ ```bash
329
+ crudforge bootstrap --preferences ./crudforge.config.yml --env-file ./.env.qa
330
+ crudforge bootstrap --dry-run --preferences ./crudforge.config.yml --env-file ./.env.qa
331
+ crudforge bootstrap --cleanup --preferences ./crudforge.config.yml --env-file ./.env.qa
332
+ ```
333
+
334
+ ### Options
335
+ * `-m, --microservice` : Explicit microservice name for API route prefixes.
336
+ * `-p, --preferences` : Path to a custom config file (YAML/JSON) overriding defaults.
337
+ * `-d, --dry-run` : Preview files to be created and diff modifications without writing to disk.
338
+ * `-w, --overwrite-policy` : Overwrite policy for existing files (overwrite, skip, fail, ask, merge).
339
+ * `--fuse` : Scaffold and generate the entities into a Fuse Angular starter project layout.
340
+ * `--fuse-path` : Path to a local Fuse starter pack directory (if overriding the bundled default).
341
+ * `--clean-layout` : Hide all pre-built Fuse UI components (banners, alerts) for a minimal dashboard.
342
+ * `--sidebar-theme` : Configures sidebar navigation theme style ('white' or 'dark').
343
+ * `--folder-type` : Navigation/ACL group name (generated service modules live under `micro-functions`).
344
+ * `--keycloak` : Enable Keycloak when config `auth.provider` is still `none`.
345
+ * `--kc-*` : Optional overrides for server URL, middleware URL, client ID, realm, credentials.
346
+ * `--proxy-write` : Which Fuse proxy file(s) to update for services/Keycloak (`both` | `prod` | `dev`).
347
+ * `--yes` / `-y` : Skip interactive prompts (microservice / proxy-write).
348
+ * `--env-file` : (`bootstrap`) Load a gitignored env file for admin / seed-user credentials.
349
+ * `--cleanup` : (`bootstrap`) Delete only resources tracked in the provision state file.
350
+
351
+ ---
352
+
353
+ ## ๐Ÿ” Keycloak auth and IAM
354
+
355
+ Defaults keep `auth.provider: none` and `auth.provision.enabled: false`. Turn Keycloak on only when the app needs real identity. Do **not** model User or Role as JDL entities; IAM is an overlay (`iam.enabled`). Generated packs live under **`src/app/core/auth/`** (services / guards / interceptors + `AGENT_README.md`) and **`src/app/core/user-management/`** (Users, Roles, role/user screen matrices + `AGENT_README.md`). Product docs: [IAM overlay](../crud-fordge-doc/src/content/docs/features/iam.md) and [Users, roles & screen access](../crud-fordge-doc/src/content/docs/guides/iam-access.md).
356
+
357
+ Every Fuse generate also ships **access-control-tools** at `src/app/domains/admin/modules/apps/shared/access-control-tools/` (README + `AGENT_README.md` / `AGENT_MEMORY.md`). Use it after adding custom pages to stamp `SCREEN` / `accessCtrl` / QA ids and refresh `public/assets/screen-components.csv`:
358
+
359
+ ```bash
360
+ npm run access-control:sync # dry-run
361
+ npm run access-control:apply # write
362
+ ```
363
+
364
+ Component ids follow semantic verbs (`create`, `open-filter`, `toggle-view`, `open-columns`). Entity `SCREEN` stays `{folder}/{entity}` (nav-aligned). Runtime aliases keep older Keycloak grants (`new`โ†”`create`, etc.) working.
365
+
366
+ **Permission matrices** and **Role / User Management** accents follow root `fuse.theme.primary` (default navy `#0D1E3A`) via Tailwind `primary-*` / `--theme-color-primary-*` โ€” not hardcoded emerald. Matrices keep sticky scrollable grids (`matrix-table` โ†’ `width: max-content`), per-toggle busy lock, holder sync after role writes, grant/revoke sounds on permission matrices, confirm dialog + assigned/available role cards on user access (no sounds there). System roles (`offline_access`, `uma_authorization`, `default-roles-*`) are hidden.
367
+
368
+ **Role Management** (`roles/role-list`) follows PMB `role-management`: master-detail list with search/pagination, create role form, duplicate, Sync holders, Assign Users bottom-sheet, inheritance flow, and a screen-permissions summary panel that deep-links to the role matrix. Catalog is CSV-only (`public/assets/screen-components.csv`); no Access Control DB or PMB approval/region exclusions.
369
+
370
+ ```yaml
371
+ auth:
372
+ provider: keycloak # or none
373
+ serverUrl: "" # Keycloak base, e.g. http://host:30080 (not the /admin/... console deep-link)
374
+ realm: CRUD-FORDGE
375
+ clientId: crudforge-client-QA
376
+ useMockAuth: false # true for deterministic Playwright / offline demos
377
+ forwardedProto: https # X-Forwarded-Proto when Keycloak requires HTTPS behind HTTP
378
+ adminRoles: [ROLE_ADMIN, ADMIN, ROLE_SUPER_ADMIN]
379
+ # Session: idleTimeoutMs 0 = stay signed in until explicit logout (default).
380
+ session:
381
+ idleTimeoutMs: 0 # set e.g. 900000 for 15-minute idle logout
382
+ persistAcrossReload: true
383
+ crossTabSync: true # sign out this tab when another tab clears tokens
384
+ refreshOnFocus: true # refresh access token when the tab becomes visible
385
+ statusProbeIntervalMs: 60000 # refresh-if-due probe when disabledAccount.enabled
386
+ disabledAccount:
387
+ enabled: false # true โ†’ freeze shell + countdown overlay, then sign out
388
+ countdownSeconds: 20
389
+ message: "Your account has been disabled. Please contact your administrator."
390
+ sound: false
391
+ provision:
392
+ enabled: false # must be true for `crudforge bootstrap` only
393
+ adapter: keycloak-admin-rest # or admin-service (middleware wrapper)
394
+ adminServiceUrl: "" # Keycloak middleware / admin service, e.g. http://host:31740/
395
+ adminUsernameEnv: KEYCLOAK_ADMIN_USERNAME
396
+ adminPasswordEnv: KEYCLOAK_ADMIN_PASSWORD
397
+ clientId: crudforge-client-QA
398
+ ```
399
+
400
+ Session pack defaults keep the user signed in across reloads. Token refresh only clears the session on **terminal** auth errors (invalid/expired refresh); network blips and 5xx keep the session. When `disabledAccount.enabled` is true, an explicit Keycloak โ€œaccount disabledโ€ grant error shows a root overlay (wired into Fuse `app.ts`) and signs out after the countdown โ€” never on generic `invalid_grant` alone.
401
+ ### Developer generate with Keycloak
402
+
403
+ Fill Keycloak in **`crudforge.config.yml`** (not CLI prompts). Bootstrap operator passwords stay in a local **`.env`** via `adminUsernameEnv` / `adminPasswordEnv`. Live QA may also set `auth.signInPrefill` so the Angular login form is pre-bound to `crud` / `crud`.
404
+
405
+ ```yaml
406
+ auth:
407
+ provider: keycloak
408
+ serverUrl: http://62.84.188.166:31740 # Admin Service gateway (not Keycloak :30080)
409
+ realm: CRUD-FORDGE
410
+ clientId: crudforge-client-QA
411
+ forwardedProto: https
412
+ signInPrefill:
413
+ username: crud
414
+ password: crud
415
+ provision:
416
+ adapter: admin-service
417
+ adminServiceUrl: http://62.84.188.166:31740/
418
+ adminUsernameEnv: KEYCLOAK_ADMIN_USERNAME
419
+ adminPasswordEnv: KEYCLOAK_ADMIN_PASSWORD
420
+
421
+ api:
422
+ microservice: book-service
423
+ services:
424
+ identityaccessmodule: http://62.84.188.166:30084
425
+ # Optional per-env targets:
426
+ # book-service:
427
+ # prod: http://host:30084
428
+ # dev: http://host:31704
429
+ # pathRewrite: /book-service
430
+
431
+ proxy:
432
+ write: both # both | prod (proxy.conf.json) | dev (proxy.dev.conf.json)
433
+ ```
434
+
435
+ Generate writes Keycloak + `api.services` into `src/environments/environment*.ts` (relative `/services/{name}` paths) and updates the chosen Fuse proxy file(s) with absolute targets. When `api.services` is set and you are on a TTY, generate asks **dev / prod / both** unless `proxy.write` or `--proxy-write` / `--yes` is set.
436
+
437
+ ```bash
438
+ # .env (gitignored) next to the project or output app
439
+ KEYCLOAK_ADMIN_USERNAME=crud
440
+ KEYCLOAK_ADMIN_PASSWORD=crud
441
+
442
+ crudforge generate ./domain.jdl ./my-app --fuse --clean-layout --preferences ./crudforge.config.yml
443
+ crudforge bootstrap --preferences ./my-app/config/crudforge.config.yml --env-file ./my-app/.env
444
+ ```
445
+
446
+ The admin console URL (`โ€ฆ/admin/master/console/#/โ€ฆ`) is a **UI link only** โ€” use the Keycloak base URL for APIs.
447
+
448
+ Passwords and admin credentials stay in the CLI process via `passwordEnv` / `admin*Env`. They are never written into Angular `environment.ts`, browser bundles, or committed fixtures. Generated SPAs use a **public** client (no confidential `clientSecret` in the browser).
449
+
450
+ Live Fuse apps proxy `/realms` (OIDC token) and `/services/keycloak-admin` to either the [Keycloak Admin Service](http://62.84.188.166:31740/) middleware (`useKeycloakAdminService: true` โ†’ `/api/v1/*`) or native Keycloak Admin REST (`useKeycloakAdminService: false` โ†’ `/admin/realms/...` via the same `/services/keycloak-admin` prefix). Broader `/auth` and `/admin` are **never** proxied so the Angular SPA shell stays intact โ€” bare `/admin/realms` calls hit Fuse `index.html`. Details: [QA/KEYCLOAK-BOOTSTRAP.md](QA/KEYCLOAK-BOOTSTRAP.md).
451
+
452
+ Structural backlog (session stay-signed-in, disabled-account overlay from PMB patterns, IAM registry, optional packs): see [Todo.md](Todo.md).
453
+
454
+ ---
455
+
456
+ ## ๐Ÿงช QA and CI
457
+
458
+ ```bash
459
+ # Mock (no remote Keycloak mutations)
460
+ ./test-run.sh mock
461
+ npm test
462
+ npm run e2e:prepare && npm run test:e2e
463
+ npm run e2e:prepare:iam && npm run test:e2e:iam
464
+
465
+ # Live Keycloak (requires gitignored .env.qa โ€” copy from .env.qa.example for seeded user passwords only)
466
+ # Endpoints + operator crud/crud are hardcoded in test-run.sh and e2e/crudforge.iam-live.yml:
467
+ # Keycloak Admin Service http://62.84.188.166:31740/ realm CRUD-FORDGE client crudforge-client-QA
468
+ # `./test-run.sh` (mock) runs mock Playwright, then regenerates the shared testing-area app
469
+ # on LIVE middleware wiring so `npm start` has:
470
+ # proxy `/realms` + `/services/keycloak-admin` โ†’ :31740
471
+ # environment.ts live links + sign-in prefill crud/crud (passwords stay in .env, not proxy)
472
+ ./test-run.sh live
473
+ npm run e2e:prepare:iam:live
474
+ npm run test:e2e:iam:live
475
+ ```
476
+
477
+ `test-run.sh` resolves paths from its own location (any cwd), refuses unsafe cleanup paths, and distinguishes mock vs live. By default it writes **one** Fuse app under:
478
+
479
+ `/Users/abdulla/Work/CRUD-FORDGE-SETUP/crud-fordge-testing-area/crudforge-app`
480
+
481
+ Mock CRUD, mock IAM, and live IAM all regenerate that same folder (no parallel `.mock-app` / `.iam-app` trees). Override with `CRUDFORGE_TESTING_AREA` / `CRUDFORGE_E2E_APP_DIR`. Local prepares default to that external sandbox whenever `CRUD-FORDGE-SETUP` exists (or `.env.qa` sets the path). Set `CRUDFORGE_USE_IN_REPO_E2E=1` to force the historical in-repo `e2e/.app` (CI without the external tree).
482
+
483
+ ### Generated Fuse root extras (default on)
484
+
485
+ When `fuse.enabled` is true, generate also:
486
+
487
+ - Writes **`config/crudforge.config.yml`** (dated header, section comments, secrets stripped)
488
+ - Seeds **GO-DUCK-style agent docs** (each stamped **Generated by `@crudforge/cli`**): root `AGENT_README.md`, `docs/ai/README.md` + topic maps (`ENTITIES.md` uses real `fieldName`/`fieldType` + relationship index), pack-level auth/IAM `AGENT_README.md`, `.crudforge/config.yaml`
489
+ - Stamps **`@generated by @crudforge/cli`** on generated Fuse sources written through the engine (`.ts` / `.html` / `.scss` / `.css` / utils / IAM / shared / docs) โ€” skip binary + JSON; regenerate instead of hand-editing as source of truth
490
+ - Seeds keep-team folders: `.cursor/agents/`, `.codex/agents/`, `.agents/agents/` + `.agents/rules/` (Antigravity), `.vscode/extensions/` (+ `extensions.json`)
491
+ - If `project.repositoryUrl` is set: `git init` (if needed) and `git remote add origin <url>` (never pushes; will not overwrite an existing different origin)
492
+
493
+ ```yaml
494
+ project:
495
+ repositoryUrl: "https://github.com/org/my-app.git" # optional
496
+ output:
497
+ embedConfig: true
498
+ aiDocs:
499
+ enabled: true
500
+ teamPack:
501
+ enabled: true
502
+ cursorAgents: true
503
+ codexAgents: true
504
+ antigravityAgents: true # Google Antigravity: .agents/agents + .agents/rules
505
+ vscodeExtensions: true
506
+ ```
507
+
508
+ `loadConfig` prefers `config/crudforge.config.yml` inside a generated app.
509
+
510
+ ### Branding
511
+
512
+ The Fuse starter ships the navy/blue/orange CRUDForge wordmark at `public/images/logo/logo.png` and the forged-C mark at `logo-mark.png`. Sidebar header and sign-in use the wordmark; favicon uses the mark. With Keycloak auth, the sidebar footer user chip matches PMB (avatar / initials icon, Super Admin badge when ACL admin, name + email, emerald power-button logout with confirm). Default Material primary is navy `#0D1E3A` via root `fuseTheme` / `fuse.theme.primary` โ€” override in config, do not hardcode entity colors. Unused Fuse stock folders (`photos`, `cards`, `pages`, `apps`, `ui`) are not shipped.
513
+
514
+ Keep-team specialist agents live under `.cursor/agents/`, `.codex/agents/`, and Antigravity `.agents/` (when `teamPack.antigravityAgents` is on).
515
+
516
+ Latest local run notes: see [QA/KEYCLOAK-BOOTSTRAP.md](QA/KEYCLOAK-BOOTSTRAP.md).
517
+
518
+ | Workflow | When | What |
519
+ |---|---|---|
520
+ | `.github/workflows/qa.yml` | PR / push | Generator tests + mock Playwright |
521
+ | `.github/workflows/qa-live.yml` | Manual / weekly | Bootstrap + live Keycloak (secrets via GitHub environment `keycloak-qa`) |
522
+
523
+ ---
524
+
525
+ ## โš™๏ธ Configuration Preferences
526
+
527
+ CRUDForge accepts a configuration file (e.g. `crudforge.config.yml`). You can scaffold a default configuration via the `init-config` command:
528
+
529
+ ```yaml
530
+ # Options matrix
531
+ fuse:
532
+ enabled: false
533
+
534
+ generate:
535
+ models: true
536
+ services: true
537
+ formServices: true
538
+ routes: true
539
+ enums: true
540
+ relationships: true
541
+ components:
542
+ list: true
543
+ card: true
544
+ detail: true
545
+ forms:
546
+ form: true
547
+ formPage: true
548
+ update: true
549
+ validators: true
550
+ mappers: true
551
+ interaction:
552
+ actions: true
553
+ filter: true
554
+ globals:
555
+ constants: true
556
+ tests: false
557
+ sharedAssets: true
558
+ registrations:
559
+ navigation: true
560
+ routes: true
561
+
562
+ output:
563
+ structure: "shared-central" # 'shared-central' (unified) or 'entity-folder' (duplicated)
564
+ directory: "./src/app"
565
+
566
+ formBehavior:
567
+ uppercaseInputs: false
568
+ showErrorMessages: true
569
+
570
+ ui:
571
+ viewMode: "table" # default fallback view
572
+ formMode: "sidebar" # sidebar drawer or page โ€” new and edit share one mode
573
+ searchMode: "field" # field.contains by default; use global only when API accepts query
574
+ cardBreakpointPx: 640
575
+ gridCols:
576
+ tablet: 2
577
+ desktop: 3
578
+
579
+ auth:
580
+ provider: none
581
+ provision:
582
+ enabled: false
583
+
584
+ iam:
585
+ enabled: false
586
+ ```
587
+
588
+ ### Generated list and form state
589
+
590
+ Audit columns (`createdBy`, `createdDate`, `lastModifiedBy`, `lastModifiedDate`)
591
+ start unchecked in **Column Preferences**. They remain available to select.
592
+ `fields.audit.hideInLists: false` opts into showing them initially. Saved browser
593
+ column selections take precedence; **Reset** applies the configured defaults.
594
+
595
+ Technical plumbing fields (`debug`, `refType`, `refId`) are hidden from all UI
596
+ surfaces by default via `fields.technical` (list, form, detail, card, filter,
597
+ search). They remain on the TypeScript model and form group for API round-trips.
598
+ Set `fields.technical.enabled: false` (or clear `names`) to show them.
599
+
600
+ With Fuse Keycloak authentication, the shared `AuditUserNamePipe` displays audit
601
+ UUIDs as first + last name in lists, cards, and details using the configured user
602
+ middleware. Lookups are cached in memory; existing names pass through, and missing
603
+ or inaccessible users retain their original ID. Entity values and write payloads
604
+ are unchanged. Applications without a configured directory retain the ID.
605
+
606
+ Lists observe their available width and use cards below `ui.cardBreakpointPx`
607
+ (default `640`). Actions saves the explicit card/table preference in localStorage;
608
+ widening the list restores that preference. New/Edit drawer openings mount a fresh
609
+ form, and closing clears its selected entity. Late edit responses cannot replace a
610
+ newer form session.
611
+
612
+ Regression checks: `npm run test:ui-state` (Node 24+). Browser checks live in
613
+ `e2e/tests/list-state.spec.js`; run them against a generated **mock** app, never a
614
+ live backend. For an isolated server on port 4201, use
615
+ `npx playwright test --config=playwright.list-state.config.js`. Set
616
+ `CRUDFORGE_BROWSER_CHANNEL=chrome` to use installed Chrome, or install Playwright's
617
+ Chromium with `npm run test:e2e:install`.
618
+
619
+ ### Per-field input formatting and audit inputs
620
+
621
+ Configure exact GDL/JDL entity and field names in the project's
622
+ `config/crudforge.config.yml`, then run `crudforge generate` using the existing
623
+ file-overwrite policy. For example, with `Province.provinceCode` and
624
+ `Province.provinceName` defined as strings:
625
+
626
+ ```yaml
627
+ fields:
628
+ entities:
629
+ Province:
630
+ fields:
631
+ provinceCode: { inputFormat: uppercase }
632
+ provinceName: { inputFormat: lowercase }
633
+ index: { inputFormat: none }
634
+ audit:
635
+ hideInForms: true
636
+ hideInFilters: true
637
+ hideInSearch: true
638
+ technical:
639
+ enabled: true
640
+ names: [debug, refType, refId]
641
+ ```
642
+
643
+ `uppercase` and `lowercase` change typed/pasted values, create defaults, loaded
644
+ edit values and outgoing service payloads. `none` preserves case and is the
645
+ default. Only editable `String` and `TextBlob` fields support these preferences;
646
+ unknown entities/fields, enum/number/date/UUID/audit/technical fields and unsupported options
647
+ are rejected before generation. Existing validators still run on the formatted
648
+ value. The shared text accessor preserves cursor/selection positions and waits
649
+ for composition input to finish. Null values remain null, and partial payloads
650
+ retain only their original keys.
651
+
652
+ The generator emits the resolved `fields` map into each entity's existing
653
+ `settings/settings.config.ts`. Edit the YAML source to retain preferences across
654
+ regeneration. Legacy `formBehavior.uppercaseInputs: true` supplies uppercase for
655
+ otherwise unconfigured text fields; an explicit per-field `none` overrides it.
656
+
657
+ Audit controls, filter entries and search-field choices are hidden by default.
658
+ These flags can independently opt them back in with `false`. Hidden controls do
659
+ not erase existing audit model values. A saved search-field choice that is no
660
+ longer available resets to the first supported choice. Global search continues
661
+ to use the backend's existing `query` contract; its server-side search scope is
662
+ not redefined by these UI preferences.
663
+
664
+ ### Authenticated Fuse identity
665
+
666
+ Keycloak builds bind the shared Fuse user menu and optional Account settings page
667
+ to `AuthService.profile`, derived from the configured provider's authenticated
668
+ JWT claims. Display-name priority is `name`, `given_name` + `family_name`, username,
669
+ then email. The `picture` claim supplies an avatar when present; otherwise initials
670
+ are shown. Missing email stays blank. UTF-8 names are decoded correctly. Profile
671
+ state updates on token hydration/refresh and clears on logout, with no sample-user
672
+ fallback for real authentication. Demo claims are used only by `auth.useMockAuth`.
673
+ No additional profile endpoint or client secret is required.
674
+
675
+ Run `npm run test:field-preferences` for field/profile behavior checks (Node 24+).
676
+ For browser regressions, generate an isolated fixture with
677
+ `npm run e2e:prepare:field-profile`, start it on port 4201, then run
678
+ `npx playwright test --config=playwright.field-profile.config.js`.
679
+ Set `CRUDFORGE_BROWSER_CHANNEL=chrome` to use installed Chrome. These tests intercept
680
+ authentication and backend calls, verify profile refresh/account switching and
681
+ formatted payloads, and attach complete console errors/stacks to their results.
682
+ They do not replace verification with real accounts.
683
+
684
+ ## Generated application performance and rendering
685
+
686
+ Fuse applications default to a client-side SPA. `npm start` uses the development
687
+ configuration; `npm run build` creates production browser assets for the supplied
688
+ Nginx Dockerfile. Strict TypeScript and Angular template checks remain enabled.
689
+
690
+ To explicitly generate a Node SSR application, set these project inputs before generation:
691
+
692
+ ```yaml
693
+ fuse:
694
+ enabled: true
695
+ rendering: ssr
696
+ ssrAllowedHosts: [localhost, 127.0.0.1, admin.example.com]
697
+ ```
698
+
699
+ Use `crudforge generate`, `npm ci`, `npm run build`, then `npm run serve:ssr`
700
+ (default port 4000). The generated Dockerfile uses Node for SSR. Configure your
701
+ actual deployment host in `ssrAllowedHosts`. Browser-stored authentication remains
702
+ a browser flow; SSR does not acquire the user's browser session on the server.
703
+ Switching rendering modes requires reviewing generated deployment/package changes
704
+ and reinstalling dependencies. Old server files are not automatically deleted from
705
+ existing projects, but are excluded from SPA compilation.
706
+
707
+ Entity screens and relationship dialogs load on demand. Shared confirmation dialogs,
708
+ resizing, base classes and list styles are generated once. For non-Fuse output, add
709
+ `shared/styles/list-styles.css` and `shared/styles/snackbar-styles.css` to the host's
710
+ global styles. `generate.globals.sharedAssets: false` means you supply the shared
711
+ files yourself. Existing legacy copies are not deleted automatically.
712
+
713
+ For an existing initialized project, run `crudforge generate --dry-run` first and
714
+ review conflicts. The normal overwrite policy still applies; use explicit overwrite
715
+ only after preserving custom changes. Per-entity list SCSS remains a customization
716
+ hook. Generated lists retain server pagination; relationship selects request the
717
+ first 50 options, so large relationships still need a searchable/paged selector.
718
+
719
+ See [the performance investigation and reproducible measurements](docs/performance/README.md)
720
+ for the PMB audit comparison, exact benchmark commands and verification limits.
721
+ Run `npm run test:performance` for generator regressions.
722
+
723
+ ---
724
+
725
+ ## ๐Ÿ” Stronger Schema & GDL Validation
726
+
727
+ CRUDForge validates schemas before any application code is generated. Run validation directly:
728
+
729
+ ```bash
730
+ crudforge validate gdl/example.gdl
731
+ crudforge validate gdl/example.gdl --json
732
+ crudforge validate gdl/example.gdl -p config/crudforge.config.yml
733
+ ```
734
+
735
+ ### Diagnostics Checks
736
+ - **Syntax & Declarations:** Unclosed braces, invalid directives, malformed field or relationship declarations.
737
+ - **Naming & Identifier Safety:** Duplicate entity/field/enum names, invalid TypeScript reserved words, and output path collisions (e.g. `FooBar` vs `Foo_Bar` both mapping to `foo-bar`).
738
+ - **Types & Field Rules:** Unsupported primitives, enum type existence, valid regex syntax for `pattern(...)`, numeric vs string validation constraints (`min`, `max`, `minlength`, `maxlength`), and inverted ranges (`min > max`).
739
+ - **Relationships:** Undefined source or target entities, undefined relationship display fields, and collisions with scalar/foreign-key fields.
740
+ - **Backend Metadata & Interoperability:** Backend labels (`backend.kind: go-duck | jhipster | custom`) are reported with clear diagnostics without forcing specific vendor naming conventions on custom backends.
741
+ - **Annotations:** Supported entity annotations are `@Audited` / `@EnableAudit`, `@Searchable`, and `@ActiveStatus` (`isActive` injection). Unimplemented annotations (e.g. `@SoftDelete`) produce clear diagnostics rather than silently discarding behavior.
742
+ - **List / IAM tables:** Generated lists follow the tw-hipster / PMB approval layout (slate header band, overlapping white card, outline search toolbar, sticky Actions that match the header band, visible empty state). ACL screen ids match navigation (`micro-functions/{entity}`); button component ids are semantic (`create`, `open-filter`, โ€ฆ). Custom-page stamping: `shared/access-control-tools/` + `npm run access-control:*`. **User Management** matches the PMB IAM list (live count, rocker enabled toggle, pin/flag state, column prefs, skeleton rows); accents use root `fuseTheme` / `fuse.theme.primary` (`primary-*` tokens), not hardcoded emerald. User Details drawer uses a navy identity band, consistent account rows, formatted role chips (system roles hidden), and sticky footer actions.
743
+
744
+ ---
745
+
746
+ ## ๐Ÿฉบ Project Diagnostics (`crudforge doctor`)
747
+
748
+ Run `doctor` to diagnose local environment, project setup, dependencies, ports, and configuration consistency:
749
+
750
+ ```bash
751
+ crudforge doctor
752
+ crudforge doctor --json
753
+ crudforge doctor --live
754
+ ```
755
+
756
+ ### Local Checks (Offline)
757
+ - **Node & Engine Compatibility:** Validates the active Node version against `package.json` engines or starter requirements.
758
+ - **Configuration & Schema:** Verifies configuration syntax, project root anchoring, and schema accessibility.
759
+ - **Lockfile & Dependencies:** Detects lockfile drift between `package.json` and `package-lock.json`, checks for missing `node_modules`, and supports Yarn PnP.
760
+ - **Port Availability:** Tests IPv4 loopback binding for the configured development server port (`devServer.port`, default `4200`).
761
+ - **Service Targets & Proxy Routes:** Ensures valid HTTP(S) URLs, verifies Keycloak authentication fields (`realm`, `clientId`, `serverUrl`), and checks proxy routes.
762
+ - **Secret Redaction:** Automatically redacts passwords, tokens, client secrets, and authorization values from diagnostic output.
763
+
764
+ ### Live Checks (`--live`)
765
+ Optional probe mode for configured `doctor.endpoints`:
766
+ ```yaml
767
+ doctor:
768
+ timeoutMs: 3000
769
+ endpoints:
770
+ - url: "http://62.84.188.166:31698/realms/PMB-DEV/.well-known/openid-configuration"
771
+ description: "Keycloak OIDC Discovery"
772
+ ```
773
+
774
+ ### Troubleshooting `crudforge: command not found`
775
+ If `crudforge` is not in your shell's `PATH`:
776
+ 1. **Run directly via Node:**
777
+ ```bash
778
+ node /path/to/crud-fordge/cli.js <command>
779
+ ```
780
+ 2. **Install globally:**
781
+ ```bash
782
+ npm install -g /path/to/crud-fordge
783
+ # or
784
+ npm link
785
+ ```
786
+ 3. **Verify npm global bin path:** Ensure `$(npm bin -g)` or `$(npm config get prefix)/bin` is in your shell `PATH` in `~/.zshrc` or `~/.bashrc`.
787
+
788
+ ---
789
+
790
+ ## ๐Ÿงช Generated Application Tests & CI
791
+
792
+ CRUDForge can generate a standalone Playwright smoke suite and CI configuration inside the generated Fuse Angular application:
793
+
794
+ ```yaml
795
+ generate:
796
+ globals:
797
+ tests: true
798
+
799
+ testing:
800
+ ci: true
801
+ fixtures:
802
+ Farmer:
803
+ referenceCode: "AB12" # Required for regex/pattern-constrained fields
804
+ ```
805
+
806
+ ### Generated Smoke Test Suite
807
+ - **Directory Structure:**
808
+ - `tests/generated/`: Generator-managed mock server (`mock.cjs`), Playwright config (`playwright.config.cjs`), and smoke test cases (`smoke.spec.cjs`).
809
+ - `tests/custom/`: Dedicated developer test folder. Files placed in `tests/custom/*.spec.cjs` are preserved and never overwritten.
810
+ - **Mock Backend Isolation:** Intercepts all API calls and Keycloak authentication locally using synthetic fixtures. Unmapped outgoing network requests are blocked with `blockedbyclient` to prevent accidental requests to real backends.
811
+ - **Coverage:** Tests application startup, entity navigation, server-side pagination, required-field form validation, create/edit flows, error banner display, loading animations, and Keycloak profile refresh.
812
+ - **Running Smoke Tests in the Generated App:**
813
+ ```bash
814
+ npm ci
815
+ npm run test:smoke:install # Installs Playwright Chromium
816
+ npm run test:smoke # Runs headless Playwright test suite
817
+ ```
818
+
819
+ ### Continuous Integration (GitHub Actions)
820
+ When `testing.ci: true`, CRUDForge generates `.github/workflows/crudforge-smoke.yml` using `tests/generated/ci.cjs`:
821
+ - Supports `npm`, `pnpm`, and `yarn` based on lockfile detection.
822
+ - Installs frozen dependencies (`npm ci` / `pnpm install --frozen-lockfile` / `yarn install --immutable`).
823
+ - Runs strict production Angular build (`npm run build`).
824
+ - Installs Playwright browser dependencies and executes `test:smoke`.
825
+ - Uploads test failure reports and screenshots as artifacts on test failure without exposing secrets.
826
+
827
+
828
+ ## Application tests, validation and setup diagnostics
829
+
830
+ Enable `generate.globals.tests: true` to generate isolated Playwright smoke tests.
831
+ Set `testing.ci: true` to also generate a GitHub Actions build/test workflow. Custom
832
+ tests belong in `tests/custom/`; normal regeneration conflict policies remain in effect.
833
+
834
+ ```bash
835
+ crudforge validate gdl/example.gdl --json
836
+ crudforge doctor
837
+ crudforge doctor --live --json # only explicitly configured read-only endpoints
838
+ crudforge generate
839
+ npm ci
840
+ npm run test:smoke:install
841
+ npm run build
842
+ npm run test:smoke
843
+ ```
844
+
845
+ Validation now uses the same fail-fast pipeline for validate and generate, including
846
+ unsupported annotations and relationship/name collisions. `validation: false` no
847
+ longer permits invalid schemas to generate files. Doctor is read-only; local checks
848
+ work without HTTP access, and live checks require explicit configured endpoints.
849
+
850
+ See [quality features and exact configuration](docs/quality/README.md) for test
851
+ isolation, custom tests, package managers/CI, diagnostic exit codes, backend contract
852
+ limits, and recovery when the shell cannot find `crudforge`.