@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
package/cli.js ADDED
@@ -0,0 +1,167 @@
1
+ #!/usr/bin/env node
2
+
3
+ const yargs = require('yargs');
4
+ const colors = require('./src/utils/colors');
5
+ const { generateCommand } = require('./src/commands/generate');
6
+ const { initConfig, initProject } = require('./src/commands/init-config');
7
+ const { validate } = require('./src/commands/validate');
8
+ const { bootstrapCommand } = require('./src/commands/bootstrap');
9
+
10
+ const argv = yargs
11
+ .command('doctor', 'Read-only project diagnostics (network checks are opt-in)', y => y.option('json',{type:'boolean'}).option('live',{type:'boolean',default:false}).option('preferences',{alias:'p',type:'string'}), async options => { try { await require('./src/commands/doctor').doctorCommand(options); } catch { const message='Doctor could not complete local checks. Check project permissions.'; if(options.json)console.log(JSON.stringify({ok:false,checks:[{id:'doctor',status:'fail',message,next:'Check project permissions.'}]}));else console.error(message); process.exitCode=1; } })
12
+ .usage('Usage: $0 <command> [options]')
13
+ // Default legacy fallback command mapping to 'generate'
14
+ .command(
15
+ ['generate [jdlFile] [outputFolder]', '$0 <jdlFile> [outputFolder]'],
16
+ 'Generate from project config, or an explicit JDL/GDL file',
17
+ (yargs) => {
18
+ yargs
19
+ .positional('jdlFile', { describe: 'JDL/GDL file (defaults to input.file in project config)', type: 'string' })
20
+ .positional('outputFolder', { describe: 'Target output folder for the Angular files', type: 'string' })
21
+ .option('microservice', { alias: 'm', describe: 'Name of the microservice for URL paths', type: 'string' })
22
+ .option('preferences', { alias: 'p', describe: 'Path to custom crudforge config', type: 'string' })
23
+ .option('json', { type: 'boolean', default: false, describe: 'JSON outcome/diagnostics on stdout; progress on stderr' })
24
+ .option('dry-run', { alias: 'd', describe: 'Preview modifications without writing', type: 'boolean', default: false })
25
+ .option('overwrite-policy', { alias: 'w', describe: 'Overwrite policy: overwrite, skip, fail, ask, merge', type: 'string', choices: ['overwrite', 'skip', 'fail', 'ask', 'merge'] })
26
+ .option('fuse', { describe: 'Scaffold and generate into Fuse Angular project layout', type: 'boolean', default: false })
27
+ .option('fuse-path', { describe: 'Path to local Fuse starter pack directory', type: 'string' })
28
+ .option('clean-layout', { describe: 'Hide all pre-built Fuse pages and layouts', type: 'boolean', default: false })
29
+ .option('sidebar-theme', { describe: 'Configures sidebar navigation theme style', type: 'string', choices: ['white', 'dark'], default: 'white' })
30
+ .option('folder-type', { describe: 'Folder name mapping for apps modules', type: 'string' })
31
+ .option('keycloak', { describe: 'Enable Keycloak auth + IAM for this generate', type: 'boolean', default: false })
32
+ .option('kc-server-url', { describe: 'Keycloak base URL (e.g. http://host:30080)', type: 'string' })
33
+ .option('kc-admin-service-url', {
34
+ describe: 'Keycloak middleware / admin service URL (e.g. http://host:31740/)',
35
+ type: 'string',
36
+ })
37
+ .option('kc-client-id', { describe: 'Application Keycloak client ID', type: 'string' })
38
+ .option('kc-realm', { describe: 'Keycloak realm name', type: 'string' })
39
+ .option('kc-username', { describe: 'Keycloak admin username (written to output .env only)', type: 'string' })
40
+ .option('kc-password', { describe: 'Keycloak admin password (written to output .env only)', type: 'string' })
41
+ .option('kc-forwarded-proto', { describe: 'X-Forwarded-Proto when Keycloak requires HTTPS', type: 'string' })
42
+ .option('proxy-write', {
43
+ describe: 'Which Fuse proxy file(s) to update: both | prod | dev',
44
+ type: 'string',
45
+ choices: ['both', 'prod', 'dev'],
46
+ })
47
+ .option('yes', { alias: 'y', describe: 'Skip interactive prompts', type: 'boolean', default: false });
48
+ },
49
+ async (argv) => {
50
+ const log = console.log;
51
+ if (argv.json) console.log = (...args) => console.error(...args);
52
+ try {
53
+ const result = await generateCommand(argv.jdlFile, argv.outputFolder, argv);
54
+ if (argv.json) log(JSON.stringify({ok:true, diagnostics:result.diagnostics, dryRun:!!result.stats.dryRun}));
55
+ } catch (err) {
56
+ if (argv.json) log(JSON.stringify({ok:false,diagnostics:err.diagnostics || [{severity:'error',code:'generation',message:err.message,suggestion:'Correct the input or conflict policy and retry.'}]}));
57
+ else console.error(colors.red(`❌ Generator execution failed:`), err);
58
+ process.exitCode = 1;
59
+ } finally { console.log = log; }
60
+ }
61
+ )
62
+ .command(
63
+ 'init <directory>',
64
+ 'Create only config/crudforge.config.yml and gdl/example.gdl; edit them before generate',
65
+ yargs => yargs.positional('directory', { type: 'string', describe: 'New or empty project directory' })
66
+ .option('preset', { type: 'string', choices: ['pmb-test'], describe: 'Optional reusable testing preset' })
67
+ .option('source', { type: 'string', describe: 'Read-only PMB project path; import preset on first use' }),
68
+ async argv => {
69
+ try { await initProject(argv.directory, argv); }
70
+ catch (error) { console.error(error.message); process.exitCode = 1; }
71
+ }
72
+ )
73
+ .command(
74
+ 'preset <action> <name>',
75
+ 'Refresh a saved testing preset from its source, keeping a backup',
76
+ yargs => yargs.positional('action', { choices: ['refresh'] })
77
+ .positional('name', { choices: ['pmb-test'] })
78
+ .option('source', { type: 'string', demandOption: true, describe: 'PMB source project (read-only)' }),
79
+ async argv => {
80
+ try { await require('./src/presets/store').importPreset(argv.name, argv.source, { refresh: true }); }
81
+ catch (error) { console.error(error.message); process.exitCode = 1; }
82
+ }
83
+ )
84
+ .command(
85
+ 'init-config',
86
+ 'Initializes a default crudforge.config.yml and example schema files',
87
+ () => {},
88
+ async (argv) => {
89
+ try {
90
+ await initConfig();
91
+ } catch (err) {
92
+ console.error(colors.red(`❌ Failed to initialize configuration:`), err);
93
+ process.exit(1);
94
+ }
95
+ }
96
+ )
97
+ .command(
98
+ 'validate <file>',
99
+ 'Validate a JDL or GDL file syntax and rules',
100
+ (yargs) => {
101
+ yargs.positional('file', { describe: 'Path to the schema file', type: 'string' }).option('json', {type:'boolean',default:false}).option('preferences', {alias:'p',type:'string'});
102
+ },
103
+ async (argv) => {
104
+ try {
105
+ await validate(argv.file, argv);
106
+ } catch (err) {
107
+ console.error(colors.red(`❌ Validation command failed:`), err);
108
+ process.exit(1);
109
+ }
110
+ }
111
+ )
112
+ .command(
113
+ 'validate-jdl <file>',
114
+ 'Validate a JDL file syntax and rules explicitly',
115
+ (yargs) => {
116
+ yargs.positional('file', { describe: 'Path to the schema file', type: 'string' }).option('json', {type:'boolean',default:false}).option('preferences', {alias:'p',type:'string'});
117
+ },
118
+ async (argv) => {
119
+ try {
120
+ await validate(argv.file, argv, 'jdl');
121
+ } catch (err) {
122
+ process.exit(1);
123
+ }
124
+ }
125
+ )
126
+ .command(
127
+ 'validate-gdl <file>',
128
+ 'Validate a GDL file syntax and rules explicitly',
129
+ (yargs) => {
130
+ yargs.positional('file', { describe: 'Path to the schema file', type: 'string' }).option('json', {type:'boolean',default:false}).option('preferences', {alias:'p',type:'string'});
131
+ },
132
+ async (argv) => {
133
+ try {
134
+ await validate(argv.file, argv, 'gdl');
135
+ } catch (err) {
136
+ process.exit(1);
137
+ }
138
+ }
139
+ )
140
+ .command(
141
+ 'bootstrap',
142
+ 'Provision Keycloak realm resources from auth.provision (never runs during generate)',
143
+ (yargs) => {
144
+ yargs
145
+ .option('preferences', { alias: 'p', describe: 'Path to custom crudforge config', type: 'string' })
146
+ .option('dry-run', { alias: 'd', describe: 'Preview provisioning without remote mutations', type: 'boolean', default: false })
147
+ .option('env-file', { describe: 'Path to dotenv file loaded before validation', type: 'string' })
148
+ .option('cleanup', { describe: 'Delete only resources tracked in auth.provision.stateFile', type: 'boolean', default: false });
149
+ },
150
+ async (argv) => {
151
+ try {
152
+ await bootstrapCommand(argv);
153
+ } catch (err) {
154
+ console.error(colors.red('❌ Bootstrap failed:'), err.message || err);
155
+ process.exit(1);
156
+ }
157
+ }
158
+ )
159
+ .example('crudforge init my-app', 'Initialize editable project inputs')
160
+ .example('crudforge init my-app --preset pmb-test --source /path/to/pmb-admin', 'Import PMB dev settings and initialize inputs')
161
+ .example('crudforge init my-app --preset pmb-test', 'Reuse saved PMB settings after deleting an app')
162
+ .example('crudforge preset refresh pmb-test --source /path/to/pmb-admin', 'Refresh the saved preset; existing apps are untouched')
163
+ .example('crudforge generate', 'Run inside my-app after editing config/ and gdl/')
164
+ .example('crudforge generate schema.gdl ./output -p prefs.yml', 'Legacy explicit generation')
165
+ .help()
166
+ .alias('help', 'h')
167
+ .argv;
@@ -0,0 +1,245 @@
1
+ # CRUDForge Default Configuration
2
+ # All options correspond to safe fallbacks matching TW-Hipster behaviors.
3
+
4
+ project:
5
+ name: CRUDForge App
6
+ description: Angular Material CRUD generated by CRUDForge
7
+ repositoryUrl: "" # if set, generated Fuse root gets git init + origin remote
8
+
9
+ input:
10
+ type: gdl # default for sources[] / single file when unset
11
+ # --- Single schema (legacy) ---
12
+ # file: ./GDL/app.gdl
13
+ file: ""
14
+ # --- Multiple GDL/JDL files per service (preferred for multi-backend apps) ---
15
+ # Each entry is a named service module: generates under apps/<folder>/…,
16
+ # nav group labeled by name, and API paths use microservice.
17
+ # Leave sources empty and set file: above for one schema.
18
+ sources: []
19
+ # sources:
20
+ # - name: identity-access # nav group label + default folder
21
+ # file: ./GDL/identity-access.gdl
22
+ # microservice: identity-access-module
23
+ # type: gdl # optional; inferred from .gdl / .jdl
24
+ # # folder: identity-access # optional override (kebab folder under apps/)
25
+ # - name: inventory
26
+ # file: ./GDL/inventory.gdl
27
+ # microservice: inventory-service
28
+ # - name: book-catalog
29
+ # file: ./jdl/books.jdl
30
+ # type: jdl
31
+ # microservice: book-service
32
+
33
+ output:
34
+ directory: "./generated-app"
35
+ structure: entity-folder # Entity layout; shared utilities are emitted once for either value
36
+ embedConfig: true # write config/crudforge.config.yml into the Fuse app
37
+ teamPack:
38
+ enabled: true # seed .cursor/agents, .codex/agents, .agents (Antigravity), .vscode/extensions
39
+ cursorAgents: true
40
+ codexAgents: true
41
+ antigravityAgents: true # .agents/agents + .agents/rules (model_decision)
42
+ vscodeExtensions: true
43
+ aiDocs:
44
+ enabled: true # AGENT_README.md + docs/ai/* + .crudforge/ (GO-DUCK-style)
45
+
46
+ git:
47
+ enabled: true # honor project.repositoryUrl when true
48
+
49
+ fuse:
50
+ enabled: false
51
+ rendering: spa # spa (Nginx) | ssr (Node server)
52
+ cleanLayout: false
53
+ includePrebuilt: true
54
+ folderType: ""
55
+ sidebarTheme: white # white | dark
56
+ routesFile: "src/app/domains/admin/routes.ts"
57
+ navigationFile: "src/app/domains/admin/layout/data/navigation.ts"
58
+ ssrAllowedHosts:
59
+ - localhost
60
+ - 127.0.0.1
61
+ # Root Material accents → generated src/app/app.ts fuseTheme / provideTheming.
62
+ # Override primary/error/scheme here; do not hardcode entity button colors.
63
+ theme:
64
+ scheme: system # system | light | dark
65
+ primary: "#0D1E3A" # default navy (matrix / app accents)
66
+ error: "#dc2626"
67
+
68
+ preset: crud
69
+
70
+ generate:
71
+ model: true
72
+ service: true
73
+ enums: true
74
+ routes: true
75
+ components:
76
+ list: true
77
+ card: true
78
+ detail: true
79
+ filter: true
80
+ form: true
81
+ formPage: true
82
+ actions: true
83
+ globals:
84
+ tests: false
85
+
86
+ ui:
87
+ framework: material
88
+ useSkeletonLoading: true
89
+ viewMode: table # 'table' or 'card'
90
+ cardBreakpointPx: 640
91
+ gridCols:
92
+ mobile: 1
93
+ tablet: 2
94
+ desktop: 3
95
+ styling:
96
+ snackbarSuccessColor: '#16a34a'
97
+ snackbarErrorColor: '#dc2626'
98
+
99
+ api:
100
+ baseUrl: /api
101
+ microservice: ""
102
+ endpointStyle: kebab-plural
103
+ dateLibrary: dayjs
104
+ responseType: http-response
105
+ # Backend modules for environment.services + proxy*.json
106
+ # identityaccessmodule: http://62.84.188.166:30084
107
+ # book-service:
108
+ # prod: http://62.84.188.166:30084
109
+ # dev: http://62.84.188.166:31704
110
+ # pathRewrite: /book-service
111
+ services: {}
112
+
113
+ # Which Angular proxy file(s) to update for Keycloak + api.services
114
+ # both | prod (proxy.conf.json) | dev (proxy.dev.conf.json)
115
+ proxy:
116
+ write: both
117
+
118
+ fields:
119
+ # Exact entity and field names from your GDL/JDL. Only String/TextBlob fields.
120
+ # entities:
121
+ # Province:
122
+ # fields:
123
+ # referenceCode: { inputFormat: uppercase }
124
+ # email: { inputFormat: lowercase }
125
+ # description: { inputFormat: none }
126
+ entities: {}
127
+ audit:
128
+ enabled: true
129
+ hideInForms: true
130
+ hideInFilters: true
131
+ hideInSearch: true
132
+ # Table view: hide createdBy / createdDate / lastModified* by default.
133
+ # Set hideInLists: false if you want those columns visible in the list initially
134
+ # (users can still toggle them via Column Preferences either way).
135
+ hideInLists: true
136
+ showInDetail: true
137
+ names:
138
+ - createdBy
139
+ - createdDate
140
+ - lastModifiedBy
141
+ - lastModifiedDate
142
+ # Backend plumbing columns (debug / refType / refId). Kept on the model for API
143
+ # payloads; never rendered in list, form, detail, card, filter, or search UI.
144
+ # Set enabled: false (or clear names) to show them.
145
+ technical:
146
+ enabled: true
147
+ names:
148
+ - debug
149
+ - refType
150
+ - refId
151
+ formatting:
152
+ dateMediumFormat: 'medium'
153
+ numberFormat: '1.0-2'
154
+ stringCase: default
155
+
156
+ formBehavior:
157
+ uppercaseInputs: false
158
+ updateOn: change
159
+ showErrorMessages: true
160
+ autoFocusFirstInput: true
161
+
162
+ mock:
163
+ enabled: false
164
+ recordsPerEntity: 10
165
+ values:
166
+ stringPrefix: 'Mock '
167
+ numberMin: 1
168
+ numberMax: 1000
169
+ booleanDefault: true
170
+
171
+ # Keycloak — set provider: keycloak and fill the fields below for developer generate.
172
+ # Username/password never go in this file: put them in a local .env as
173
+ # KEYCLOAK_ADMIN_USERNAME / KEYCLOAK_ADMIN_PASSWORD (names below).
174
+ auth:
175
+ provider: none # none | keycloak
176
+ serverUrl: "" # e.g. http://62.84.188.166:30080 (not the /admin console link)
177
+ realm: CRUD-FORDGE
178
+ clientId: "" # application public SPA client ID
179
+ clientSecret: ""
180
+ issuerUrl: ""
181
+ tokenUrl: ""
182
+ adminBaseUrl: /auth
183
+ useMockAuth: false
184
+ adminRoles:
185
+ - ROLE_ADMIN
186
+ - ADMIN
187
+ - ROLE_SUPER_ADMIN
188
+ sessionIdleTimeoutMs: 0 # legacy; prefer auth.session.idleTimeoutMs (0 = stay signed in)
189
+ session:
190
+ idleTimeoutMs: 0 # 0 = never idle-logout; set e.g. 900000 for 15m like PMB
191
+ persistAcrossReload: true
192
+ crossTabSync: true
193
+ refreshOnFocus: true
194
+ statusProbeIntervalMs: 60000
195
+ disabledAccount:
196
+ enabled: false # true → countdown overlay then sign-out when Keycloak says disabled
197
+ countdownSeconds: 20
198
+ message: "Your account has been disabled. Please contact your administrator."
199
+ sound: false
200
+ forwardedProto: "" # set to https when Keycloak requires HTTPS behind HTTP
201
+ provision:
202
+ enabled: false # true only for `crudforge bootstrap`
203
+ dryRun: false
204
+ adapter: admin-service # or keycloak-admin-rest
205
+ adminServiceUrl: "" # Keycloak middleware, e.g. http://62.84.188.166:31740/
206
+ adminUsernameEnv: KEYCLOAK_ADMIN_USERNAME
207
+ adminPasswordEnv: KEYCLOAK_ADMIN_PASSWORD
208
+ tokenClientId: admin-cli
209
+ clientId: "" # defaults to auth.clientId when empty
210
+ clientName: ""
211
+ publicClient: true
212
+ directAccessGrantsEnabled: true
213
+ redirectUris: []
214
+ webOrigins: []
215
+ roles: []
216
+ users: []
217
+ resetExistingPasswords: false
218
+ stateFile: ".crudforge/provision-state.json"
219
+
220
+ iam:
221
+ enabled: false
222
+ users: true
223
+ roles: true
224
+ rolePermissions: true
225
+ userAccess: true
226
+ userPermissions: true
227
+ inheritance: true
228
+ screens: []
229
+
230
+ namingConventions:
231
+ entityPrefix: ''
232
+ entitySuffix: ''
233
+ modelInterfacePrefix: 'I'
234
+ kebabCaseFiles: true
235
+ enumValueCasing: uppercase
236
+
237
+ # Optional application smoke suite and GitHub Actions (npm lockfile).
238
+ testing:
239
+ ci: false
240
+ fixtures: {}
241
+ backend:
242
+ kind: custom # informational: custom, go-duck, jhipster; never implies verified support
243
+ doctor:
244
+ timeoutMs: 3000
245
+ endpoints: [] # explicit documented read-only URLs; requested only with doctor --live
@@ -0,0 +1,217 @@
1
+ # CRUDForge performance investigation
2
+
3
+ Measured on 2026-10-09. Baseline generator commit: `5699fab319ff600e2e19e8bd85b23219e1adf26a`.
4
+ Changes apply to the generator and Fuse starter, not to PMB business code. PMB was read only.
5
+
6
+ ## Audit checked against implementation
7
+
8
+ Reference: `/Users/abdulla/Work/PMB/pmb-admin/AUDIT_README.md`, plus PMB's
9
+ `angular.json`, app/bootstrap configuration, package manifests, Dockerfile, routes,
10
+ HTTP imports and component implementations.
11
+
12
+ The audit mixes historical findings with completed work. Its action matrix correctly
13
+ marks SPA conversion, shared-asset consolidation and removal of component-level
14
+ `HttpClientModule` as completed. PMB currently has no SSR build targets or hydration
15
+ provider and deploys browser assets with Nginx. A source scan found three classes
16
+ named `ConfirmationDialogComponent`, one `ResizableDirective`, and no
17
+ `HttpClientModule` references; the introductory counts of hundreds of copies no
18
+ longer describe current source.
19
+
20
+ Other recommendations remain outstanding or only partly applied: PMB still includes
21
+ `src/**/*.ts` as compilation roots. The scan counted 2,027 TypeScript files / 504,681
22
+ lines, 1,164 files containing `@Component(`, 34 containing OnPush and 23 containing
23
+ `takeUntilDestroyed`. These are textual counts, not a runtime profile or a count of
24
+ confirmed leaks. PMB's large custom report screens and business services are not
25
+ CRUDForge templates and were not copied or rewritten. The heap setting exists, but
26
+ the audit's claimed GC stalls have no accompanying heap/CPU measurement; this work
27
+ does not claim to confirm them or increase the heap limit.
28
+
29
+ The starter uses Angular 21.2.6 without Zone.js. Angular 21 defaults to zoneless
30
+ change detection ([Angular documentation](https://angular.dev/guide/zoneless)), so
31
+ Zone.js-wide change-detection claims do not explain this fixture. Generated entity
32
+ components already used OnPush; asynchronous updates needed correct notifications,
33
+ not a blanket change-detection conversion.
34
+
35
+ ## Confirmed generator causes and changes
36
+
37
+ - The starter built browser and SSR bundles even though its Dockerfile served only
38
+ browser assets. The baseline produced `index.csr.html`, whereas Nginx expects
39
+ `index.html`. `src/generator/fuse-build.js` now coordinates `fuse.rendering: spa`
40
+ (default) or `ssr`, build targets, compiler roots, hydration, direct dependencies,
41
+ lockfile root requirements, start scripts, allowed hosts and deployment files.
42
+ SPA omits server sources in fresh projects. Strict TypeScript/template checks stay
43
+ enabled. Angular's local disk cache is explicit; Tailwind scans the source tree.
44
+ - Fuse already generated canonical shared assets; non-Fuse output duplicated them
45
+ per entity. Both layouts now share confirmation, resize, base and style files.
46
+ Shared list CSS is scoped to `.cforge-entity-list`; entity SCSS remains an extension
47
+ hook. Existing CLI conflict/overwrite rules protect customizations. Legacy copies
48
+ in existing projects are not silently deleted.
49
+ - Domain/entity routing already used lazy route boundaries, but each entity route
50
+ eagerly imported its screens. Screens now use `loadComponent`; related collection
51
+ and form dialogs use dynamic imports, avoiding relationship chains pulling screens
52
+ into a feature chunk. Related collection dialogs also receive a definite height
53
+ and explicit maximum width; browser tests caught collapsed content in the old layout.
54
+ - Pagination had two listeners: the paginator observable and a template `(page)`
55
+ handler. Browser traces measured two GET requests per page change. One remains.
56
+ Save/delete/filter paths also had both a refresh event and direct `loadData()`;
57
+ redundant calls were removed. Superseded reads are cancelled and reads/dialog
58
+ subscriptions end with component destruction. Server page/size parameters remain.
59
+ - Relationship option responses now notify OnPush and bind to lifecycle cleanup;
60
+ selects request page 0 / size 50. A remote searchable/paged relationship selector
61
+ remains necessary for larger option sets. Table tracking uses row IDs. ACL template
62
+ conditions use `@if`; existing `@for` tracking and Material table directives remain.
63
+ - Generated components had no `HttpClientModule` imports to remove. Root HTTP providers
64
+ and authentication interceptors are retained and regression-tested. No blanket
65
+ subscription or signal rewrite was made.
66
+
67
+ Optional chart screens are already route-lazy. The measured clean app excludes
68
+ prebuilt dashboards; its build graph contains no ApexCharts, spreadsheet or PDF
69
+ library. These dependencies were not indiscriminately removed from the starter
70
+ because optional features use them. No global route preloading was found. Backend
71
+ latency and PMB's custom initialization were not measured; required authentication
72
+ checks were preserved.
73
+
74
+ ## Measurements
75
+
76
+ See `before.json` and `after.json` for exact values, commands and three browser
77
+ observations per fixture. The small fixture has one audited Province; the large
78
+ fixture has Province plus 24 independent catalog entities. They use the same schema,
79
+ configuration, dependency directory, Node 24.19.0, macOS arm64 / 11 logical CPUs and
80
+ `NG_BUILD_MAX_WORKERS=2`. Relationship behavior is tested separately with Book/Author.
81
+
82
+ Cold build means deleting Angular's disk cache and build output, not flushing OS
83
+ caches. Warm build reruns the same production command. Each build/start/rebuild has
84
+ one sample; these results are observations, not statistically established guarantees.
85
+ Development startup ends when the server prints its local URL. Browser bootstrap
86
+ is measured separately because Vite transforms code on first request. Its readiness
87
+ marker is Angular's sign-in component instance, not a standardized TTI metric.
88
+ Browser/API timings use local mocked authentication and backend responses. Initial
89
+ bundle bytes sum unique JS/CSS files referenced by production HTML, including
90
+ modulepreloads; they are raw bytes, not compressed transfer size or all lazy chunks.
91
+ FCP was sampled too early in SPA runs and is null; no FCP comparison is claimed.
92
+
93
+ ### One entity
94
+ - Cold production build: 7.52s → 4.33s (42.5% lower in this run).
95
+ - Warm production build: 5.61s → 2.78s (50.4% lower in this run).
96
+ - Cold dev startup: 3.03s → 2.12s (30.0% lower in this run).
97
+ - Template rebuild: 1.61s → 1.11s (31.1% lower in this run).
98
+ - Initial JS/CSS: 1,002,588 → 655,268 bytes (34.6% smaller).
99
+ - First browser bootstrap (cold dev transforms): 3775 → 955 ms.
100
+ - Warm bootstrap (mean of runs 2–3): 184 → 132 ms.
101
+ - Province rendered (median of 3): 346 → 275 ms.
102
+ - Province refresh (median of 3): 429 → 301 ms.
103
+ - Pagination GET requests: 2 → 1 in all three browser runs.
104
+
105
+ ### 25 entities
106
+ - Cold production build: 14.04s → 8.92s (36.5% lower in this run).
107
+ - Warm production build: 9.63s → 7.08s (26.5% lower in this run).
108
+ - Cold dev startup: 8.38s → 6.97s (16.9% lower in this run).
109
+ - Template rebuild: 6.98s → 6.06s (13.1% lower in this run).
110
+ - Initial JS/CSS: 1,004,796 → 657,476 bytes (34.6% smaller).
111
+ - First browser bootstrap (cold dev transforms): 4752 → 1121 ms.
112
+ - Warm bootstrap (mean of runs 2–3): 177 → 136 ms.
113
+ - Province rendered (median of 3): 522 → 296 ms.
114
+ - Province refresh (median of 3): 481 → 333 ms.
115
+ - Pagination GET requests: 2 → 1 in all three browser runs.
116
+
117
+
118
+ ## Verification
119
+
120
+ Passed generator/config/workflow/PMB-preset, field-preference, list-state,
121
+ auth-interceptor and new performance-generation tests. The 25-entity regression
122
+ asserts single shared assets, lazy screens, strict compilation, root HTTP providers,
123
+ SPA/SSR coherence and protection of customized shared components.
124
+
125
+ Fresh apps passed production builds for both rendering modes and the Book/Author
126
+ relationship fixture. SSR returned HTTP 200 with server-rendered sign-in content.
127
+ Both generated manifest/lock pairs passed offline `npm ci --dry-run --ignore-scripts`;
128
+ full builds used the same existing dependency directory. Docker images were not built.
129
+
130
+ Browser checks passed: 25 existing demo/navigation/list/filter/form/detail/card/state
131
+ checks; one related-list/create-dialog check; three profile/field/performance checks
132
+ covering mocked login, current identity, refresh, logout/account switch, create/update
133
+ payloads, deletion, single pagination/deletion refresh requests, and persistent column
134
+ resizing. These tests use synthetic accounts and responses. Real PMB login, permissions,
135
+ network latency and backend writes were NOT verified in this performance pass. Earlier
136
+ manual login success is not evidence for the newly generated output.
137
+
138
+ Existing unused-import warnings remain in some relationship components; optional SSR
139
+ also warns about the 1 MB initial budget. Neither warning was suppressed or the budget
140
+ raised. No runtime page errors occurred in the measured fixture browser runs.
141
+
142
+ ## Reproduce
143
+
144
+ From the repository root (Node 24 and Chrome installed):
145
+
146
+ ```bash
147
+ npm ci
148
+ npm run test:performance
149
+ # Install app dependencies once in an isolated fixture location if needed:
150
+ CRUDFORGE_E2E_APP_DIR=/tmp/crudforge-perf-dependencies npm run e2e:prepare
151
+ export CRUDFORGE_BENCH_MODULES=/tmp/crudforge-perf-dependencies/node_modules
152
+
153
+ git worktree add --detach /tmp/crudforge-perf-baseline-source 5699fab319ff600e2e19e8bd85b23219e1adf26a
154
+ npm ci --prefix /tmp/crudforge-perf-baseline-source
155
+ CRUDFORGE_GENERATOR_ROOT=/tmp/crudforge-perf-baseline-source node scripts/performance/generate.js /tmp/crudforge-perf-before
156
+ node scripts/performance/measure.js /tmp/crudforge-perf-before
157
+ node scripts/performance/generate.js /tmp/crudforge-perf-after
158
+ node scripts/performance/measure.js /tmp/crudforge-perf-after
159
+ ```
160
+
161
+ Use fresh output paths, stop competing builds, and leave port 4301 free. The harness
162
+ runs production builds, cold dev startup, three Chrome sessions and one template-edit
163
+ rebuild serially, writes logs and `measurements.json`, then stops its server. The
164
+ `CRUDFORGE_GENERATOR_ROOT` option lets the same current harness/fixtures use the baseline
165
+ implementation and starter. Never regenerate the baseline with the changed generator.
166
+
167
+ For your PMB project:
168
+
169
+ ```bash
170
+ cd /Users/abdulla/Work/CRUD-FORDGE-SETUP/crud-fordge-testing-area
171
+ crudforge init crudforge-app --preset pmb-test
172
+ cd crudforge-app
173
+ # Edit config/crudforge.config.yml and gdl/example.gdl as needed; rendering defaults to spa.
174
+ crudforge generate
175
+ npm ci
176
+ npm start
177
+ # Production validation:
178
+ npm run build
179
+ ```
180
+
181
+ For an existing project, skip init and run `crudforge generate --dry-run` first.
182
+ Review conflicts and preserve custom work before selecting the existing overwrite
183
+ option. Do not delete a customized project merely to benchmark. The reusable preset
184
+ remains outside the app; no PMB source path is compiled into the application.
185
+
186
+ Browser regression commands (run each server in a separate terminal):
187
+
188
+ ```bash
189
+ npm run e2e:prepare:field-profile
190
+ (cd e2e/.field-profile && NG_BUILD_MAX_WORKERS=2 npm start -- --host 127.0.0.1 --port 4202)
191
+ CRUDFORGE_BROWSER_CHANNEL=chrome CRUDFORGE_UI_TEST_URL=http://127.0.0.1:4202 npx playwright test --config=playwright.field-profile.config.js
192
+
193
+ CRUDFORGE_E2E_APP_DIR=/tmp/crudforge-perf-relationships npm run e2e:prepare
194
+ (cd /tmp/crudforge-perf-relationships && NG_BUILD_MAX_WORKERS=2 npx ng serve --configuration mock --host 127.0.0.1 --port 4203)
195
+ npx playwright test --config=playwright.performance.config.js
196
+ ```
197
+
198
+ ## Changed source files
199
+
200
+ Build integration: `src/generator/fuse-build.js`, `src/generator/index.js`,
201
+ `src/config/default-values.js`, `src/config/load-config.js`,
202
+ `src/commands/init-config.js`, `config/default-config.yml`.
203
+
204
+ Starter: `fuse-starter-pack/fuse-v21.1/{angular.json,tsconfig.app.json,package.json,package-lock.json}`,
205
+ `src/app/app.config.ts` and `src/styles/styles.css` within that starter.
206
+
207
+ Templates under `src/templates/angular/`: `entity/_entity_.routes.ts.ejs`,
208
+ `shared/list-styles.css.ejs`, `shared/base/base-list.component.ts.ejs`, entity list
209
+ TS/HTML/SCSS, form and form-page TS, form-service TS, detail/card TS, filter TS,
210
+ entity service TS, and actions/card HTML. The service/filter/form-service changes
211
+ correct relative imports for the centralized non-Fuse shared directory.
212
+
213
+ Verification: `test/performance-generation.js`, `test/verify.js`,
214
+ `test/fixtures/performance/*`, `scripts/performance/{generate,measure}.js`,
215
+ `e2e/tests/{field-profile,generated-crud}.spec.js`,
216
+ `playwright.performance.config.js`, and the root npm test script. Documentation and
217
+ raw observations are in this directory and the root README.