@team-codeme/crud-forge 0.0.0-stage → 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (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
@@ -0,0 +1,15 @@
1
+ model Book {
2
+ title String required
3
+ description TextBlob
4
+ publicationDate LocalDate
5
+ price BigDecimal
6
+ }
7
+
8
+ model Author {
9
+ firstName String required
10
+ lastName String required
11
+ }
12
+
13
+ relations {
14
+ Author has_many Book
15
+ }
@@ -0,0 +1,15 @@
1
+ entity Book {
2
+ title String required
3
+ description TextBlob
4
+ publicationDate LocalDate
5
+ price BigDecimal
6
+ }
7
+
8
+ entity Author {
9
+ firstName String required
10
+ lastName String required
11
+ }
12
+
13
+ relationship OneToMany {
14
+ Author{book} to Book{author}
15
+ }
@@ -0,0 +1,127 @@
1
+ # CRUDForge CLI Configuration
2
+ project:
3
+ name: CRUDForge App
4
+ description: Angular Material CRUD generated by CRUDForge
5
+
6
+ input:
7
+ file: ""
8
+ type: "jdl"
9
+
10
+ output:
11
+ directory: "./generated-app"
12
+ structure: "entity-folder"
13
+
14
+ preset: "crud"
15
+ dryRun: false
16
+ validation: true
17
+
18
+ branding:
19
+ banner: true
20
+ bannerColor: "green"
21
+
22
+ fuse:
23
+ enabled: true
24
+ routesFile: "src/app/domains/admin/routes.ts"
25
+ navigationFile: "src/app/domains/admin/layout/data/navigation.ts"
26
+ cleanLayout: false
27
+ includePrebuilt: false
28
+ folderType: ""
29
+ theme:
30
+ scheme: "system"
31
+ primary: "#1565C0"
32
+ error: "#dc2626"
33
+
34
+ generate:
35
+ models: true
36
+ services: true
37
+ formServices: true
38
+ routes: true
39
+ enums: true
40
+ relationships: true
41
+ components:
42
+ list: true
43
+ card: true
44
+ detail: true
45
+ forms:
46
+ form: true
47
+ formPage: true
48
+ update: true
49
+ validators: true
50
+ mappers: true
51
+ interaction:
52
+ actions: true
53
+ filter: true
54
+ globals:
55
+ constants: true
56
+ tests: false
57
+ sharedAssets: true
58
+ registrations:
59
+ navigation: true
60
+ routes: true
61
+
62
+ ui:
63
+ framework: "material"
64
+ useSkeletonLoading: true
65
+ snackbarPositionTop: false
66
+ viewMode: "card"
67
+ formMode: "sidebar"
68
+ searchMode: "field"
69
+ cardBreakpointPx: 640
70
+ gridCols:
71
+ mobile: 1
72
+ tablet: 2
73
+ desktop: 4
74
+ styling:
75
+ snackbarSuccessColor: "#16a34a"
76
+ snackbarErrorColor: "#dc2626"
77
+
78
+ api:
79
+ baseUrl: "/api"
80
+ microservice: ""
81
+ endpointStyle: "kebab-plural"
82
+ dateLibrary: "dayjs"
83
+ responseType: "http-response"
84
+
85
+ fields:
86
+ audit:
87
+ enabled: true
88
+ hideInForms: true
89
+ hideInLists: true
90
+ showInDetail: true
91
+ names:
92
+ - createdBy
93
+ - createdDate
94
+ - lastModifiedBy
95
+ - lastModifiedDate
96
+ technical:
97
+ enabled: true
98
+ names:
99
+ - debug
100
+ - refType
101
+ - refId
102
+ formatting:
103
+ dateMediumFormat: "medium"
104
+ numberFormat: "1.0-2"
105
+ stringCase: "default"
106
+
107
+ formBehavior:
108
+ uppercaseInputs: true
109
+ updateOn: "change"
110
+ showErrorMessages: true
111
+ autoFocusFirstInput: true
112
+
113
+ mock:
114
+ enabled: true
115
+ recordsPerEntity: 100
116
+ values:
117
+ stringPrefix: "Mock "
118
+ numberMin: 1
119
+ numberMax: 1000
120
+ booleanDefault: true
121
+
122
+ namingConventions:
123
+ entityPrefix: ""
124
+ entitySuffix: ""
125
+ modelInterfacePrefix: "I"
126
+ kebabCaseFiles: true
127
+ enumValueCasing: "uppercase"
package/test-run.sh ADDED
@@ -0,0 +1,272 @@
1
+ #!/usr/bin/env bash
2
+ # test-run.sh — run CRUDForge generator QA from any working directory.
3
+ # Modes: mock (default) | live | generate
4
+ #
5
+ # One generated Fuse app under CRUDFORGE_TESTING_AREA (created if missing):
6
+ # crudforge-app/
7
+ set -euo pipefail
8
+
9
+ ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
10
+ cd "$ROOT"
11
+
12
+ MODE="${1:-${CRUDFORGE_QA_MODE:-mock}}"
13
+ ENV_FILE="${CRUDFORGE_ENV_FILE:-$ROOT/.env.qa}"
14
+ LIVE_PREFS="$ROOT/e2e/crudforge.iam-live.yml"
15
+
16
+ # Default external QA sandbox (outside the generator repo). Override with CRUDFORGE_TESTING_AREA.
17
+ DEFAULT_TESTING_AREA="/Users/abdulla/Work/CRUD-FORDGE-SETUP/crud-fordge-testing-area"
18
+ TESTING_AREA="${CRUDFORGE_TESTING_AREA:-$DEFAULT_TESTING_AREA}"
19
+ APP_NAME="${CRUDFORGE_E2E_APP_NAME:-crudforge-app}"
20
+
21
+ # ---------------------------------------------------------------------------
22
+ # Real Keycloak Admin Service (middleware) — hardcoded for live / generate.
23
+ # Keep in sync with e2e/crudforge.iam-live.yml + scripts/e2e-prepare-iam-live.js
24
+ # Docs: http://62.84.188.166:31740/ | operator: crud / crud | client: crudforge-client-QA
25
+ # Do not proxy to native Keycloak :30080 — middleware fronts /realms + /api/v1.
26
+ # ---------------------------------------------------------------------------
27
+ QA_KC_ADMIN_SERVICE_URL="http://62.84.188.166:31740"
28
+ QA_KC_SERVER_URL="$QA_KC_ADMIN_SERVICE_URL"
29
+ QA_KC_REALM="CRUD-FORDGE"
30
+ QA_KC_CLIENT_ID="crudforge-client-QA"
31
+ QA_KC_FORWARDED_PROTO="https"
32
+ QA_KC_OPERATOR_USER="crud"
33
+ QA_KC_OPERATOR_PASS="crud"
34
+
35
+ if [[ -f "$ENV_FILE" ]]; then
36
+ echo "🔵 Loading env from $ENV_FILE"
37
+ set -a
38
+ # shellcheck disable=SC1090
39
+ source "$ENV_FILE"
40
+ set +a
41
+ fi
42
+
43
+ # Re-resolve after env file (caller / .env.qa may override paths only)
44
+ TESTING_AREA="${CRUDFORGE_TESTING_AREA:-$TESTING_AREA}"
45
+ APP_NAME="${CRUDFORGE_E2E_APP_NAME:-$APP_NAME}"
46
+ export CRUDFORGE_TESTING_AREA="$TESTING_AREA"
47
+ export CRUDFORGE_E2E_APP_DIR="${CRUDFORGE_E2E_APP_DIR:-$TESTING_AREA/$APP_NAME}"
48
+ # Back-compat aliases — all point at the single app root
49
+ export CRUDFORGE_E2E_IAM_APP_DIR="${CRUDFORGE_E2E_IAM_APP_DIR:-$CRUDFORGE_E2E_APP_DIR}"
50
+ export CRUDFORGE_E2E_IAM_LIVE_APP_DIR="${CRUDFORGE_E2E_IAM_LIVE_APP_DIR:-$CRUDFORGE_E2E_APP_DIR}"
51
+ export CRUDFORGE_LIVE_OUTPUT_DIR="${CRUDFORGE_LIVE_OUTPUT_DIR:-$CRUDFORGE_E2E_APP_DIR}"
52
+
53
+ # Prefer the host Playwright browser install over sandbox cache stubs.
54
+ unset PLAYWRIGHT_BROWSERS_PATH
55
+
56
+ pin_live_keycloak() {
57
+ # Always win over .env.qa for the real QA Keycloak endpoints + operator.
58
+ export CRUDFORGE_KC_SERVER_URL="$QA_KC_SERVER_URL"
59
+ export CRUDFORGE_KC_REALM="$QA_KC_REALM"
60
+ export CRUDFORGE_KC_CLIENT_ID="$QA_KC_CLIENT_ID"
61
+ export CRUDFORGE_KC_ADMIN_SERVICE_URL="$QA_KC_ADMIN_SERVICE_URL"
62
+ export CRUDFORGE_KC_FORWARDED_PROTO="$QA_KC_FORWARDED_PROTO"
63
+ export KEYCLOAK_ADMIN_USERNAME="$QA_KC_OPERATOR_USER"
64
+ export KEYCLOAK_ADMIN_PASSWORD="$QA_KC_OPERATOR_PASS"
65
+ }
66
+
67
+ assert_live_wiring() {
68
+ local app="$1"
69
+ local proxy="$app/proxy.conf.json"
70
+ local proxy_dev="$app/proxy.dev.conf.json"
71
+ local envf="$app/src/environments/environment.ts"
72
+ local signin="$app/src/app/domains/auth/features/sign-in/sign-in.ts"
73
+
74
+ echo "🔎 Asserting LIVE Keycloak wiring in $app"
75
+ for f in "$proxy" "$proxy_dev" "$envf" "$signin"; do
76
+ if [[ ! -f "$f" ]]; then
77
+ echo "❌ Missing required file: $f"
78
+ exit 1
79
+ fi
80
+ done
81
+
82
+ node - "$proxy" "$proxy_dev" "$envf" "$signin" "$QA_KC_ADMIN_SERVICE_URL" "$QA_KC_CLIENT_ID" "$QA_KC_REALM" <<'NODE'
83
+ const fs = require('fs');
84
+ const [proxyPath, proxyDevPath, envPath, signInPath, adminServiceUrl, clientId, realm] = process.argv.slice(2);
85
+ const admin = adminServiceUrl.replace(/\/+$/, '');
86
+
87
+ function checkProxy(file, label) {
88
+ const p = JSON.parse(fs.readFileSync(file, 'utf8'));
89
+ const realms = p['/realms'];
90
+ const kcAdmin = p['/services/keycloak-admin'];
91
+ if (!realms || realms.target !== admin) {
92
+ throw new Error(`${label}: /realms must target middleware ${admin} (not Keycloak :30080)`);
93
+ }
94
+ if (p['/admin/realms']) {
95
+ throw new Error(`${label}: must not proxy /admin/realms (use Keycloak Admin Service /api/v1)`);
96
+ }
97
+ if (!kcAdmin || kcAdmin.target !== admin) {
98
+ throw new Error(`${label}: /services/keycloak-admin must target ${admin}`);
99
+ }
100
+ if (/"password"|clientSecret|KEYCLOAK_ADMIN_PASSWORD/i.test(JSON.stringify(p))) {
101
+ throw new Error(`${label}: proxy must not contain credentials`);
102
+ }
103
+ if (String(JSON.stringify(p)).includes(':30080')) {
104
+ throw new Error(`${label}: must not reference Keycloak :30080`);
105
+ }
106
+ }
107
+
108
+ checkProxy(proxyPath, 'proxy.conf.json');
109
+ checkProxy(proxyDevPath, 'proxy.dev.conf.json');
110
+
111
+ const env = fs.readFileSync(envPath, 'utf8');
112
+ const required = [
113
+ `kcRealm: '${realm}'`,
114
+ `kcClientId: '${clientId}'`,
115
+ `kcServerUrl: '${admin}'`,
116
+ `useMockAuth: false`,
117
+ `sso: '/realms/${realm}/protocol/openid-connect/token'`,
118
+ `kcAdminServiceUrl: '/services/keycloak-admin'`,
119
+ `useKeycloakAdminService: true`,
120
+ ];
121
+ for (const needle of required) {
122
+ if (!env.includes(needle)) {
123
+ throw new Error(`environment.ts missing: ${needle}`);
124
+ }
125
+ }
126
+ if (/PASSWORD|clientSecret|KEYCLOAK_ADMIN_PASSWORD|:30080/i.test(env)) {
127
+ throw new Error('environment.ts must not embed secrets or Keycloak :30080');
128
+ }
129
+
130
+ const signIn = fs.readFileSync(signInPath, 'utf8');
131
+ if (!signIn.includes("email: 'crud'") || !signIn.includes("password: 'crud'")) {
132
+ throw new Error("sign-in.ts must prefill email/password with crud / crud");
133
+ }
134
+
135
+ console.log('✅ proxy → Keycloak Admin Service :31740 (/realms + /services/keycloak-admin)');
136
+ console.log('✅ environment.ts → live middleware links (no secrets, no :30080)');
137
+ console.log('✅ sign-in.ts → crud / crud form bind');
138
+ NODE
139
+ }
140
+
141
+ is_unsafe_output() {
142
+ local target="$1"
143
+ case "$target" in
144
+ /|/Users|/home|/etc|/var|/usr|"$HOME") return 0 ;;
145
+ esac
146
+ if [[ "$target" == "$ROOT" ]]; then
147
+ return 0
148
+ fi
149
+ if [[ ${#target} -lt 8 ]]; then
150
+ return 0
151
+ fi
152
+ return 1
153
+ }
154
+
155
+ ensure_testing_area() {
156
+ if is_unsafe_output "$TESTING_AREA"; then
157
+ echo "❌ Refusing unsafe CRUDFORGE_TESTING_AREA: $TESTING_AREA"
158
+ exit 1
159
+ fi
160
+ mkdir -p "$TESTING_AREA"
161
+ echo "🔵 Testing area: $TESTING_AREA"
162
+ echo "🔵 Single Fuse app: $CRUDFORGE_E2E_APP_DIR"
163
+ }
164
+
165
+ run_mock() {
166
+ echo "▶️ MOCK mode: generator tests + Playwright (one Fuse app; no remote Keycloak mutations)"
167
+ ensure_testing_area
168
+ node test/verify.js
169
+ npm run e2e:prepare
170
+ npm run test:e2e
171
+ npm run e2e:prepare:iam
172
+ npm run test:e2e:iam
173
+ # Shared testing-area app must end on LIVE Keycloak wiring (proxy + environment + crud/crud form).
174
+ # Otherwise a plain `./test-run.sh` leaves mock IAM and wipes /realms + admin-service proxies.
175
+ pin_live_keycloak
176
+ npm run e2e:prepare:iam:live
177
+ assert_live_wiring "$CRUDFORGE_E2E_APP_DIR"
178
+ echo "✅ MOCK QA finished; testing-area left on LIVE Keycloak (app: $CRUDFORGE_E2E_APP_DIR)"
179
+ }
180
+
181
+ run_live() {
182
+ echo "▶️ LIVE mode: bootstrap real Keycloak, regenerate same Fuse app, build, Playwright"
183
+ ensure_testing_area
184
+ pin_live_keycloak
185
+
186
+ if [[ -z "${CRUDFORGE_QA_ADMIN_PASSWORD:-}" || -z "${CRUDFORGE_QA_USER_PASSWORD:-}" ]]; then
187
+ echo "❌ LIVE mode still needs CRUDFORGE_QA_ADMIN_PASSWORD and CRUDFORGE_QA_USER_PASSWORD for seeded app users."
188
+ echo " Copy .env.qa.example to .env.qa (gitignored) for those only."
189
+ exit 1
190
+ fi
191
+
192
+ echo "🔵 Keycloak server : ${CRUDFORGE_KC_SERVER_URL}"
193
+ echo "🔵 Realm : ${CRUDFORGE_KC_REALM}"
194
+ echo "🔵 App client ID : ${CRUDFORGE_KC_CLIENT_ID}"
195
+ echo "🔵 Middleware service : ${CRUDFORGE_KC_ADMIN_SERVICE_URL}"
196
+ echo "🔵 Operator (bootstrap): ${KEYCLOAK_ADMIN_USERNAME} / ****"
197
+ echo "🔵 SPA sign-in prefill : ${QA_KC_OPERATOR_USER} / ${QA_KC_OPERATOR_PASS}"
198
+ echo "🔵 Preferences : ${LIVE_PREFS}"
199
+
200
+ if [[ -f "$ENV_FILE" ]]; then
201
+ node cli.js bootstrap --preferences "$LIVE_PREFS" --env-file "$ENV_FILE"
202
+ node cli.js bootstrap --preferences "$LIVE_PREFS" --env-file "$ENV_FILE"
203
+ else
204
+ node cli.js bootstrap --preferences "$LIVE_PREFS"
205
+ node cli.js bootstrap --preferences "$LIVE_PREFS"
206
+ fi
207
+ echo "🔵 Second bootstrap completed (idempotency)."
208
+
209
+ npm run e2e:prepare:iam:live
210
+
211
+ local live_app="$CRUDFORGE_E2E_APP_DIR"
212
+ if [[ ! -d "$live_app" ]]; then
213
+ echo "❌ Live app was not generated at $live_app"
214
+ exit 1
215
+ fi
216
+ assert_live_wiring "$live_app"
217
+ if [[ -x "$live_app/node_modules/.bin/tsc" ]]; then
218
+ "$live_app/node_modules/.bin/tsc" -p "$live_app/tsconfig.app.json" --noEmit
219
+ elif [[ -x "$ROOT/e2e/.app/node_modules/.bin/tsc" ]]; then
220
+ "$ROOT/e2e/.app/node_modules/.bin/tsc" -p "$live_app/tsconfig.app.json" --noEmit
221
+ else
222
+ echo "⚠️ TypeScript compiler not found in the generated app; skipping tsc (ng serve will still typecheck)."
223
+ fi
224
+
225
+ npm run test:e2e:iam:live
226
+ echo "✅ LIVE QA finished (app: $CRUDFORGE_E2E_APP_DIR)"
227
+ echo " Manual serve: npm run e2e:serve:iam:live → http://127.0.0.1:4202 (sign-in: ${QA_KC_OPERATOR_USER} / ${QA_KC_OPERATOR_PASS})"
228
+ echo " Do not use port 4300 production serve for live Keycloak unless proxy targets Admin Service :31740."
229
+ }
230
+
231
+ run_generate_only() {
232
+ ensure_testing_area
233
+ pin_live_keycloak
234
+ local output="${CRUDFORGE_LIVE_OUTPUT_DIR}"
235
+ mkdir -p "$(dirname "$output")"
236
+ output="$(cd "$(dirname "$output")" && pwd)/$(basename "$output")"
237
+ if is_unsafe_output "$output"; then
238
+ echo "❌ Refusing to write unsafe output directory: $output"
239
+ exit 1
240
+ fi
241
+ echo "▶️ Generate-only (live Keycloak prefs) into $output"
242
+ echo "🔵 Keycloak: ${CRUDFORGE_KC_SERVER_URL} realm=${CRUDFORGE_KC_REALM} client=${CRUDFORGE_KC_CLIENT_ID}"
243
+ node cli.js generate "$ROOT/test/fixtures/mock.jdl" "$output" \
244
+ --preferences "$LIVE_PREFS" \
245
+ --fuse --clean-layout -m test-service \
246
+ --keycloak \
247
+ --kc-server-url "$CRUDFORGE_KC_SERVER_URL" \
248
+ --kc-realm "$CRUDFORGE_KC_REALM" \
249
+ --kc-client-id "$CRUDFORGE_KC_CLIENT_ID" \
250
+ --kc-admin-service-url "$CRUDFORGE_KC_ADMIN_SERVICE_URL"
251
+ }
252
+
253
+ case "$MODE" in
254
+ mock) run_mock ;;
255
+ live) run_live ;;
256
+ generate) run_generate_only ;;
257
+ *)
258
+ echo "Usage: $0 [mock|live|generate]"
259
+ echo " mock generator verify + CRUD e2e + mock IAM e2e (default)"
260
+ echo " live bootstrap real Keycloak, regenerate same app, tsc, live Playwright"
261
+ echo " generate generate into CRUDFORGE_LIVE_OUTPUT_DIR (live Keycloak prefs, no bootstrap)"
262
+ echo ""
263
+ echo "Testing area (created if missing):"
264
+ echo " CRUDFORGE_TESTING_AREA=${DEFAULT_TESTING_AREA}"
265
+ echo " Single app folder: \$CRUDFORGE_TESTING_AREA/${APP_NAME}"
266
+ echo ""
267
+ echo "Keycloak Admin Service QA (live/generate):"
268
+ echo " ${QA_KC_ADMIN_SERVICE_URL} realm=${QA_KC_REALM} client=${QA_KC_CLIENT_ID}"
269
+ echo " operator ${QA_KC_OPERATOR_USER}/${QA_KC_OPERATOR_PASS} (no native :30080 proxies)"
270
+ exit 1
271
+ ;;
272
+ esac