@team-codeme/crud-forge 0.0.0-stage → 1.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.cursor/agents/generator-engineer.md +31 -0
- package/.cursor/agents/keycloak-engineer.md +33 -0
- package/.cursor/agents/qa-engineer.md +32 -0
- package/.cursor/agents/security-reviewer.md +30 -0
- package/.cursor/mcp.json +13 -0
- package/.cursor/rules/crudforge-precautions.mdc +16 -0
- package/.cursor/rules/playwright-browser.mdc +30 -0
- package/.cursor/rules/readme-todo-sync.mdc +13 -0
- package/.env.qa.example +19 -0
- package/.github/workflows/qa-live.yml +32 -0
- package/.github/workflows/qa.yml +27 -0
- package/.vscode/settings.json +32 -0
- package/QA/IAM-PLAN.md +25 -0
- package/QA/IAM-RESULTS.md +39 -0
- package/QA/IAM-TESTCASES.md +36 -0
- package/QA/IAM-TODO.md +7 -0
- package/QA/KEYCLOAK-BOOTSTRAP.md +105 -0
- package/QA/PLAN.md +43 -0
- package/QA/RESULTS.md +59 -0
- package/QA/TESTCASES.md +65 -0
- package/QA/TODO.md +14 -0
- package/QA/pmb-dev/README.md +49 -0
- package/QA/pmb-dev/config/config.yml +152 -0
- package/QA/pmb-dev/gdl/i.gdl +17 -0
- package/README.md +851 -2
- package/Todo.md +207 -0
- package/assets/branding/crudforge-logo.png +0 -0
- package/assets/branding/crudforge-mark.png +0 -0
- package/branding/poster-crudforge.jpg +0 -0
- package/chat/last-chat/Investigating Mock Data Configuration.md +428 -0
- package/cli.js +167 -0
- package/config/default-config.yml +245 -0
- package/docs/performance/README.md +217 -0
- package/docs/performance/after.json +111 -0
- package/docs/performance/before.json +111 -0
- package/docs/quality/README.md +276 -0
- package/e2e/crudforge.e2e.yml +47 -0
- package/e2e/crudforge.field-profile.yml +33 -0
- package/e2e/crudforge.iam-live.yml +124 -0
- package/e2e/crudforge.iam.yml +62 -0
- package/e2e/tests/field-profile.spec.js +152 -0
- package/e2e/tests/generated-crud.spec.js +251 -0
- package/e2e/tests/iam-live.spec.js +149 -0
- package/e2e/tests/iam-pack.spec.js +151 -0
- package/e2e/tests/list-state.spec.js +73 -0
- package/features.csv +27 -0
- package/fuse-starter-pack/branding/crudforge-mark-source.jpg +0 -0
- package/fuse-starter-pack/branding/crudforge-mark-source.png +0 -0
- package/fuse-starter-pack/branding/crudforge-mark.png +0 -0
- package/fuse-starter-pack/branding/crudforge-wordmark-source.jpg +0 -0
- package/fuse-starter-pack/branding/crudforge-wordmark-source.png +0 -0
- package/fuse-starter-pack/branding/crudforge-wordmark.png +0 -0
- package/fuse-starter-pack/fuse-v21.1/Dockerfile +14 -0
- package/fuse-starter-pack/fuse-v21.1/LICENSE.md +6 -0
- package/fuse-starter-pack/fuse-v21.1/README.md +59 -0
- package/fuse-starter-pack/fuse-v21.1/angular.json +113 -0
- package/fuse-starter-pack/fuse-v21.1/eslint.config.ts +150 -0
- package/fuse-starter-pack/fuse-v21.1/nginx.conf +23 -0
- package/fuse-starter-pack/fuse-v21.1/nginx.dev.conf +18 -0
- package/fuse-starter-pack/fuse-v21.1/package-lock.json +11513 -0
- package/fuse-starter-pack/fuse-v21.1/package.json +69 -0
- package/fuse-starter-pack/fuse-v21.1/postcss.config.json +5 -0
- package/fuse-starter-pack/fuse-v21.1/prettier.config.ts +15 -0
- package/fuse-starter-pack/fuse-v21.1/proxy.conf.json +8 -0
- package/fuse-starter-pack/fuse-v21.1/proxy.dev.conf.json +8 -0
- package/fuse-starter-pack/fuse-v21.1/public/favicon.png +0 -0
- package/fuse-starter-pack/fuse-v21.1/public/fonts/geist/Geist-Italic.woff2 +0 -0
- package/fuse-starter-pack/fuse-v21.1/public/fonts/geist/Geist.woff2 +0 -0
- package/fuse-starter-pack/fuse-v21.1/public/fonts/geist/GeistMono-Italic.woff2 +0 -0
- package/fuse-starter-pack/fuse-v21.1/public/fonts/geist/GeistMono.woff2 +0 -0
- package/fuse-starter-pack/fuse-v21.1/public/i18n/en.json +8 -0
- package/fuse-starter-pack/fuse-v21.1/public/i18n/es.json +8 -0
- package/fuse-starter-pack/fuse-v21.1/public/images/flags/ES.svg +79 -0
- package/fuse-starter-pack/fuse-v21.1/public/images/flags/US.svg +14 -0
- package/fuse-starter-pack/fuse-v21.1/public/images/flags/where-to-find-other-flags.txt +5 -0
- package/fuse-starter-pack/fuse-v21.1/public/images/logo/logo-mark.png +0 -0
- package/fuse-starter-pack/fuse-v21.1/public/images/logo/logo.png +0 -0
- package/fuse-starter-pack/fuse-v21.1/push.sh +27 -0
- package/fuse-starter-pack/fuse-v21.1/src/app/app.config.server.ts +10 -0
- package/fuse-starter-pack/fuse-v21.1/src/app/app.config.ts +64 -0
- package/fuse-starter-pack/fuse-v21.1/src/app/app.routes.server.ts +8 -0
- package/fuse-starter-pack/fuse-v21.1/src/app/app.routes.ts +39 -0
- package/fuse-starter-pack/fuse-v21.1/src/app/app.ts +22 -0
- package/fuse-starter-pack/fuse-v21.1/src/app/core/icons/index.ts +1 -0
- package/fuse-starter-pack/fuse-v21.1/src/app/core/icons/lucide.ts +1 -0
- package/fuse-starter-pack/fuse-v21.1/src/app/core/icons/provider.ts +23 -0
- package/fuse-starter-pack/fuse-v21.1/src/app/core/local-storage/index.ts +2 -0
- package/fuse-starter-pack/fuse-v21.1/src/app/core/local-storage/local-storage.ts +109 -0
- package/fuse-starter-pack/fuse-v21.1/src/app/core/local-storage/provider.ts +15 -0
- package/fuse-starter-pack/fuse-v21.1/src/app/core/media/index.ts +2 -0
- package/fuse-starter-pack/fuse-v21.1/src/app/core/media/media.ts +64 -0
- package/fuse-starter-pack/fuse-v21.1/src/app/core/media/provider.ts +15 -0
- package/fuse-starter-pack/fuse-v21.1/src/app/core/theming/index.ts +3 -0
- package/fuse-starter-pack/fuse-v21.1/src/app/core/theming/models/theming.ts +13 -0
- package/fuse-starter-pack/fuse-v21.1/src/app/core/theming/palette.ts +209 -0
- package/fuse-starter-pack/fuse-v21.1/src/app/core/theming/provider.ts +24 -0
- package/fuse-starter-pack/fuse-v21.1/src/app/core/theming/theming.ts +129 -0
- package/fuse-starter-pack/fuse-v21.1/src/app/core/transloco/transloco-http-loader.ts +12 -0
- package/fuse-starter-pack/fuse-v21.1/src/app/domains/admin/layout/data/navigation.ts +176 -0
- package/fuse-starter-pack/fuse-v21.1/src/app/domains/admin/layout/layout.ts +77 -0
- package/fuse-starter-pack/fuse-v21.1/src/app/domains/admin/layout/ui/language-switcher.ts +91 -0
- package/fuse-starter-pack/fuse-v21.1/src/app/domains/admin/layout/ui/navigation.ts +238 -0
- package/fuse-starter-pack/fuse-v21.1/src/app/domains/admin/layout/ui/notifications.ts +252 -0
- package/fuse-starter-pack/fuse-v21.1/src/app/domains/admin/layout/ui/scheme-switcher.ts +58 -0
- package/fuse-starter-pack/fuse-v21.1/src/app/domains/admin/layout/ui/sidebar.ts +31 -0
- package/fuse-starter-pack/fuse-v21.1/src/app/domains/admin/layout/ui/user.ts +132 -0
- package/fuse-starter-pack/fuse-v21.1/src/app/domains/admin/modules/apps/academy/data/academy.ts +753 -0
- package/fuse-starter-pack/fuse-v21.1/src/app/domains/admin/modules/apps/academy/data/model.ts +27 -0
- package/fuse-starter-pack/fuse-v21.1/src/app/domains/admin/modules/apps/academy/features/course.ts +318 -0
- package/fuse-starter-pack/fuse-v21.1/src/app/domains/admin/modules/apps/academy/features/courses.ts +228 -0
- package/fuse-starter-pack/fuse-v21.1/src/app/domains/admin/modules/apps/academy/routes.ts +14 -0
- package/fuse-starter-pack/fuse-v21.1/src/app/domains/admin/modules/apps/contacts/data/contacts.ts +4372 -0
- package/fuse-starter-pack/fuse-v21.1/src/app/domains/admin/modules/apps/contacts/data/model.ts +34 -0
- package/fuse-starter-pack/fuse-v21.1/src/app/domains/admin/modules/apps/contacts/features/contact.ts +239 -0
- package/fuse-starter-pack/fuse-v21.1/src/app/domains/admin/modules/apps/contacts/features/contacts.ts +185 -0
- package/fuse-starter-pack/fuse-v21.1/src/app/domains/admin/modules/apps/contacts/routes.ts +16 -0
- package/fuse-starter-pack/fuse-v21.1/src/app/domains/admin/modules/apps/file-manager/data/file-manager.ts +261 -0
- package/fuse-starter-pack/fuse-v21.1/src/app/domains/admin/modules/apps/file-manager/data/model.ts +12 -0
- package/fuse-starter-pack/fuse-v21.1/src/app/domains/admin/modules/apps/file-manager/features/file-manager.ts +131 -0
- package/fuse-starter-pack/fuse-v21.1/src/app/domains/admin/modules/apps/file-manager/routes.ts +15 -0
- package/fuse-starter-pack/fuse-v21.1/src/app/domains/admin/modules/apps/file-manager/ui/list.ts +164 -0
- package/fuse-starter-pack/fuse-v21.1/src/app/domains/admin/modules/apps/help-center/features/faq.ts +288 -0
- package/fuse-starter-pack/fuse-v21.1/src/app/domains/admin/modules/apps/help-center/features/guide.ts +134 -0
- package/fuse-starter-pack/fuse-v21.1/src/app/domains/admin/modules/apps/help-center/features/home.ts +219 -0
- package/fuse-starter-pack/fuse-v21.1/src/app/domains/admin/modules/apps/help-center/features/support.ts +161 -0
- package/fuse-starter-pack/fuse-v21.1/src/app/domains/admin/modules/apps/help-center/routes.ts +33 -0
- package/fuse-starter-pack/fuse-v21.1/src/app/domains/admin/modules/apps/notes/data/model.ts +18 -0
- package/fuse-starter-pack/fuse-v21.1/src/app/domains/admin/modules/apps/notes/data/notes.ts +324 -0
- package/fuse-starter-pack/fuse-v21.1/src/app/domains/admin/modules/apps/notes/features/note.ts +152 -0
- package/fuse-starter-pack/fuse-v21.1/src/app/domains/admin/modules/apps/notes/features/notes.ts +118 -0
- package/fuse-starter-pack/fuse-v21.1/src/app/domains/admin/modules/apps/notes/routes.ts +16 -0
- package/fuse-starter-pack/fuse-v21.1/src/app/domains/admin/modules/apps/tasks/data/model.ts +17 -0
- package/fuse-starter-pack/fuse-v21.1/src/app/domains/admin/modules/apps/tasks/data/tasks.ts +562 -0
- package/fuse-starter-pack/fuse-v21.1/src/app/domains/admin/modules/apps/tasks/features/task.ts +195 -0
- package/fuse-starter-pack/fuse-v21.1/src/app/domains/admin/modules/apps/tasks/features/tasks.ts +271 -0
- package/fuse-starter-pack/fuse-v21.1/src/app/domains/admin/modules/apps/tasks/routes.ts +16 -0
- package/fuse-starter-pack/fuse-v21.1/src/app/domains/admin/modules/dashboards/data/analytics.ts +1620 -0
- package/fuse-starter-pack/fuse-v21.1/src/app/domains/admin/modules/dashboards/data/finance.ts +1065 -0
- package/fuse-starter-pack/fuse-v21.1/src/app/domains/admin/modules/dashboards/data/project.ts +376 -0
- package/fuse-starter-pack/fuse-v21.1/src/app/domains/admin/modules/dashboards/features/analytics/analytics.ts +1096 -0
- package/fuse-starter-pack/fuse-v21.1/src/app/domains/admin/modules/dashboards/features/finance/finance.ts +658 -0
- package/fuse-starter-pack/fuse-v21.1/src/app/domains/admin/modules/dashboards/features/project/budget-table.ts +188 -0
- package/fuse-starter-pack/fuse-v21.1/src/app/domains/admin/modules/dashboards/features/project/project.ts +565 -0
- package/fuse-starter-pack/fuse-v21.1/src/app/domains/admin/modules/dashboards/routes.ts +23 -0
- package/fuse-starter-pack/fuse-v21.1/src/app/domains/admin/modules/documentation/features/changelog/changelog.ts +932 -0
- package/fuse-starter-pack/fuse-v21.1/src/app/domains/admin/modules/documentation/features/getting-started/building.ts +33 -0
- package/fuse-starter-pack/fuse-v21.1/src/app/domains/admin/modules/documentation/features/getting-started/development.ts +42 -0
- package/fuse-starter-pack/fuse-v21.1/src/app/domains/admin/modules/documentation/features/getting-started/installation.ts +47 -0
- package/fuse-starter-pack/fuse-v21.1/src/app/domains/admin/modules/documentation/layout.ts +9 -0
- package/fuse-starter-pack/fuse-v21.1/src/app/domains/admin/modules/documentation/routes.ts +45 -0
- package/fuse-starter-pack/fuse-v21.1/src/app/domains/admin/modules/extras/error/features/error-page.ts +70 -0
- package/fuse-starter-pack/fuse-v21.1/src/app/domains/admin/modules/extras/error/routes.ts +21 -0
- package/fuse-starter-pack/fuse-v21.1/src/app/domains/admin/modules/extras/notifications/features/notifications.ts +262 -0
- package/fuse-starter-pack/fuse-v21.1/src/app/domains/admin/modules/extras/notifications/routes.ts +10 -0
- package/fuse-starter-pack/fuse-v21.1/src/app/domains/admin/modules/extras/settings/features/account.ts +238 -0
- package/fuse-starter-pack/fuse-v21.1/src/app/domains/admin/modules/extras/settings/features/notifications.ts +134 -0
- package/fuse-starter-pack/fuse-v21.1/src/app/domains/admin/modules/extras/settings/features/plan-and-billing.ts +238 -0
- package/fuse-starter-pack/fuse-v21.1/src/app/domains/admin/modules/extras/settings/features/security.ts +211 -0
- package/fuse-starter-pack/fuse-v21.1/src/app/domains/admin/modules/extras/settings/features/team.ts +188 -0
- package/fuse-starter-pack/fuse-v21.1/src/app/domains/admin/modules/extras/settings/layout.ts +109 -0
- package/fuse-starter-pack/fuse-v21.1/src/app/domains/admin/modules/extras/settings/routes.ts +37 -0
- package/fuse-starter-pack/fuse-v21.1/src/app/domains/admin/modules/extras/welcome/welcome.component.ts +22 -0
- package/fuse-starter-pack/fuse-v21.1/src/app/domains/admin/routes.ts +95 -0
- package/fuse-starter-pack/fuse-v21.1/src/app/domains/auth/features/forgot-password/forgot-password.html +54 -0
- package/fuse-starter-pack/fuse-v21.1/src/app/domains/auth/features/forgot-password/forgot-password.ts +51 -0
- package/fuse-starter-pack/fuse-v21.1/src/app/domains/auth/features/reset-password/reset-password.html +82 -0
- package/fuse-starter-pack/fuse-v21.1/src/app/domains/auth/features/reset-password/reset-password.ts +69 -0
- package/fuse-starter-pack/fuse-v21.1/src/app/domains/auth/features/sign-in/sign-in.html +132 -0
- package/fuse-starter-pack/fuse-v21.1/src/app/domains/auth/features/sign-in/sign-in.ts +54 -0
- package/fuse-starter-pack/fuse-v21.1/src/app/domains/auth/features/sign-up/sign-up.html +183 -0
- package/fuse-starter-pack/fuse-v21.1/src/app/domains/auth/features/sign-up/sign-up.ts +56 -0
- package/fuse-starter-pack/fuse-v21.1/src/app/domains/auth/layout.ts +9 -0
- package/fuse-starter-pack/fuse-v21.1/src/app/domains/auth/routes.ts +34 -0
- package/fuse-starter-pack/fuse-v21.1/src/app/domains/coming-soon/features/coming-soon.ts +156 -0
- package/fuse-starter-pack/fuse-v21.1/src/app/domains/coming-soon/layout.ts +9 -0
- package/fuse-starter-pack/fuse-v21.1/src/app/domains/coming-soon/routes.ts +16 -0
- package/fuse-starter-pack/fuse-v21.1/src/app/domains/website/layout/layout.ts +9 -0
- package/fuse-starter-pack/fuse-v21.1/src/app/domains/website/modules/home/features/home.ts +23 -0
- package/fuse-starter-pack/fuse-v21.1/src/app/domains/website/modules/home/routes.ts +10 -0
- package/fuse-starter-pack/fuse-v21.1/src/app/domains/website/routes.ts +30 -0
- package/fuse-starter-pack/fuse-v21.1/src/environments/environment.mock.ts +5 -0
- package/fuse-starter-pack/fuse-v21.1/src/environments/environment.prod.ts +5 -0
- package/fuse-starter-pack/fuse-v21.1/src/environments/environment.ts +5 -0
- package/fuse-starter-pack/fuse-v21.1/src/index.html +66 -0
- package/fuse-starter-pack/fuse-v21.1/src/main.server.ts +11 -0
- package/fuse-starter-pack/fuse-v21.1/src/main.ts +5 -0
- package/fuse-starter-pack/fuse-v21.1/src/server.ts +70 -0
- package/fuse-starter-pack/fuse-v21.1/src/styles/base/base.css +63 -0
- package/fuse-starter-pack/fuse-v21.1/src/styles/base/typography.css +54 -0
- package/fuse-starter-pack/fuse-v21.1/src/styles/components/a.css +18 -0
- package/fuse-starter-pack/fuse-v21.1/src/styles/components/input.css +22 -0
- package/fuse-starter-pack/fuse-v21.1/src/styles/components/kbd.css +55 -0
- package/fuse-starter-pack/fuse-v21.1/src/styles/components/material.css +1149 -0
- package/fuse-starter-pack/fuse-v21.1/src/styles/styles.css +31 -0
- package/fuse-starter-pack/fuse-v21.1/src/styles/tailwind/theme.css +147 -0
- package/fuse-starter-pack/fuse-v21.1/src/styles/tailwind/utilities.css +563 -0
- package/fuse-starter-pack/fuse-v21.1/src/styles/tailwind/variants.css +4 -0
- package/fuse-starter-pack/fuse-v21.1/src/styles/third-party/lucide-icons.css +12 -0
- package/fuse-starter-pack/fuse-v21.1/tsconfig.app.json +16 -0
- package/fuse-starter-pack/fuse-v21.1/tsconfig.json +37 -0
- package/fuse-starter-pack/fuse-v21.1/tsconfig.spec.json +10 -0
- package/generator/README.md +12 -0
- package/generator/issues/.gitkeep +0 -0
- package/package.json +56 -4
- package/playwright.config.js +29 -0
- package/playwright.field-profile.config.js +6 -0
- package/playwright.iam-live.config.js +31 -0
- package/playwright.iam.config.js +29 -0
- package/playwright.list-state.config.js +6 -0
- package/playwright.performance.config.js +1 -0
- package/run-config-tests.sh +5 -0
- package/scripts/e2e-paths.js +89 -0
- package/scripts/e2e-prepare-field-profile.js +17 -0
- package/scripts/e2e-prepare-iam-live.js +135 -0
- package/scripts/e2e-prepare-iam.js +65 -0
- package/scripts/e2e-prepare.js +72 -0
- package/scripts/e2e-serve-iam-live.js +28 -0
- package/scripts/e2e-serve-iam.js +28 -0
- package/scripts/e2e-serve.js +28 -0
- package/scripts/performance/generate.js +17 -0
- package/scripts/performance/measure.js +55 -0
- package/scripts/postinstall.js +9 -0
- package/scripts/prepare-quality-apps.js +34 -0
- package/scripts/run-config-tests.js +63 -0
- package/src/assets/logo-with-lable.jpeg +0 -0
- package/src/assets/logo.jpeg +0 -0
- package/src/commands/bootstrap.js +92 -0
- package/src/commands/doctor.js +403 -0
- package/src/commands/generate.js +301 -0
- package/src/commands/init-config.js +310 -0
- package/src/commands/keycloak-options.js +182 -0
- package/src/commands/validate.js +52 -0
- package/src/config/auth-config.js +183 -0
- package/src/config/default-values.js +235 -0
- package/src/config/env-refs.js +71 -0
- package/src/config/field-preferences.js +99 -0
- package/src/config/input-sources.js +104 -0
- package/src/config/load-config.js +166 -0
- package/src/config/proxy-routes.js +44 -0
- package/src/generator/access-control-tools.js +334 -0
- package/src/generator/ai-docs.js +691 -0
- package/src/generator/application-tests.js +252 -0
- package/src/generator/auth-pack.js +965 -0
- package/src/generator/embed-config.js +431 -0
- package/src/generator/entity-layout.js +30 -0
- package/src/generator/fuse-build.js +57 -0
- package/src/generator/fuse-runtime.js +344 -0
- package/src/generator/generated-banner.js +137 -0
- package/src/generator/index.js +874 -0
- package/src/generator/project-output.js +126 -0
- package/src/generator/team-pack.js +220 -0
- package/src/index.js +68 -0
- package/src/parser/gdl-parser.js +169 -0
- package/src/parser/jdl-parser.js +171 -0
- package/src/presets/pmb-test.js +139 -0
- package/src/presets/static-source.js +73 -0
- package/src/presets/store.js +96 -0
- package/src/provision/admin-service.js +148 -0
- package/src/provision/bootstrap.js +147 -0
- package/src/provision/http.js +123 -0
- package/src/provision/keycloak-admin-rest.js +335 -0
- package/src/provision/state.js +51 -0
- package/src/provision/token.js +52 -0
- package/src/templates/angular/auth/access-control.service.ts.ejs +179 -0
- package/src/templates/angular/auth/access-ctrl.pipe.ts.ejs +20 -0
- package/src/templates/angular/auth/auth.guard.ts.ejs +27 -0
- package/src/templates/angular/auth/auth.interceptor.ts.ejs +53 -0
- package/src/templates/angular/auth/auth.service.ts.ejs +594 -0
- package/src/templates/angular/auth/auth.utils.ts.ejs +28 -0
- package/src/templates/angular/auth/current-user.ts.ejs +24 -0
- package/src/templates/angular/auth/disabled-account-overlay.component.css.ejs +95 -0
- package/src/templates/angular/auth/disabled-account-overlay.component.html.ejs +33 -0
- package/src/templates/angular/auth/disabled-account-overlay.component.ts.ejs +23 -0
- package/src/templates/angular/auth/fuse-account.ts.ejs +234 -0
- package/src/templates/angular/auth/fuse-user.ts.ejs +264 -0
- package/src/templates/angular/auth/has-permission.directive.ts.ejs +51 -0
- package/src/templates/angular/auth/index.ts.ejs +24 -0
- package/src/templates/angular/auth/keycloak-admin.service.ts.ejs +670 -0
- package/src/templates/angular/auth/landing.guard.ts.ejs +61 -0
- package/src/templates/angular/auth/no-auth.guard.ts.ejs +19 -0
- package/src/templates/angular/auth/permission-attribute.util.ts.ejs +182 -0
- package/src/templates/angular/auth/sign-in.ts.ejs +60 -0
- package/src/templates/angular/entity/_entity_.model.ts.ejs +64 -0
- package/src/templates/angular/entity/_entity_.routes.ts.ejs +9 -0
- package/src/templates/angular/entity/components/forms/form/_entity_-form.component.html.ejs +168 -0
- package/src/templates/angular/entity/components/forms/form/_entity_-form.component.ts.ejs +175 -0
- package/src/templates/angular/entity/components/forms/form-page/_entity_-form-page.component.html.ejs +10 -0
- package/src/templates/angular/entity/components/forms/form-page/_entity_-form-page.component.ts.ejs +86 -0
- package/src/templates/angular/entity/components/forms/update/_entity_-form.service.ts.ejs +136 -0
- package/src/templates/angular/entity/components/interaction/actions/_entity_-actions.component.html.ejs +68 -0
- package/src/templates/angular/entity/components/interaction/actions/_entity_-actions.component.ts.ejs +69 -0
- package/src/templates/angular/entity/components/interaction/filter/_entity_-filter.component.html.ejs +111 -0
- package/src/templates/angular/entity/components/interaction/filter/_entity_-filter.component.ts.ejs +102 -0
- package/src/templates/angular/entity/components/presentation/card/_entity_-card.component.css.ejs +33 -0
- package/src/templates/angular/entity/components/presentation/card/_entity_-card.component.html.ejs +29 -0
- package/src/templates/angular/entity/components/presentation/card/_entity_-card.component.ts.ejs +93 -0
- package/src/templates/angular/entity/components/presentation/detail/_entity_-detail.component.css.ejs +54 -0
- package/src/templates/angular/entity/components/presentation/detail/_entity_-detail.component.html.ejs +58 -0
- package/src/templates/angular/entity/components/presentation/detail/_entity_-detail.component.ts.ejs +47 -0
- package/src/templates/angular/entity/components/presentation/list/_entity_-list.component.html.ejs +419 -0
- package/src/templates/angular/entity/components/presentation/list/_entity_-list.component.scss.ejs +48 -0
- package/src/templates/angular/entity/components/presentation/list/_entity_-list.component.ts.ejs +592 -0
- package/src/templates/angular/entity/service/_entity_.service.ts.ejs +153 -0
- package/src/templates/angular/entity/settings/_entity_.settings.ts.ejs +49 -0
- package/src/templates/angular/enums/_enum_.model.ts.ejs +11 -0
- package/src/templates/angular/iam/change-password.component.html.ejs +39 -0
- package/src/templates/angular/iam/change-password.component.ts.ejs +44 -0
- package/src/templates/angular/iam/no-access.component.ts.ejs +17 -0
- package/src/templates/angular/iam/role-list.component.html.ejs +331 -0
- package/src/templates/angular/iam/role-list.component.scss.ejs +107 -0
- package/src/templates/angular/iam/role-list.component.ts.ejs +597 -0
- package/src/templates/angular/iam/role-management/role-header.component.html.ejs +51 -0
- package/src/templates/angular/iam/role-management/role-header.component.ts.ejs +45 -0
- package/src/templates/angular/iam/role-management/role-inheritance.component.html.ejs +15 -0
- package/src/templates/angular/iam/role-management/role-inheritance.component.ts.ejs +19 -0
- package/src/templates/angular/iam/role-management/role-permissions-panel.component.css.ejs +24 -0
- package/src/templates/angular/iam/role-management/role-permissions-panel.component.html.ejs +108 -0
- package/src/templates/angular/iam/role-management/role-permissions-panel.component.ts.ejs +122 -0
- package/src/templates/angular/iam/role-management/role-users.component.html.ejs +104 -0
- package/src/templates/angular/iam/role-management/role-users.component.ts.ejs +53 -0
- package/src/templates/angular/iam/role-management/user-select-dialog.component.html.ejs +113 -0
- package/src/templates/angular/iam/role-management/user-select-dialog.component.ts.ejs +157 -0
- package/src/templates/angular/iam/role-permission-matrix.component.html.ejs +355 -0
- package/src/templates/angular/iam/role-permission-matrix.component.scss.ejs +217 -0
- package/src/templates/angular/iam/role-permission-matrix.component.ts.ejs +800 -0
- package/src/templates/angular/iam/screen-catalog.ts.ejs +147 -0
- package/src/templates/angular/iam/shared/confirm-dialog.component.ts.ejs +83 -0
- package/src/templates/angular/iam/shared/matrix-hierarchy.util.ts.ejs +196 -0
- package/src/templates/angular/iam/shared/permission-matrix-sound.ts.ejs +59 -0
- package/src/templates/angular/iam/shared/role-display.util.ts.ejs +43 -0
- package/src/templates/angular/iam/shared/role-permission-skeleton.component.ts.ejs +54 -0
- package/src/templates/angular/iam/shared/screen-matrix.util.ts.ejs +554 -0
- package/src/templates/angular/iam/shared/screen-navigation-map.ts.ejs +187 -0
- package/src/templates/angular/iam/shared/screen-navigation.registry.ts.ejs +64 -0
- package/src/templates/angular/iam/shared/text-highlight.pipe.ts.ejs +39 -0
- package/src/templates/angular/iam/user-access-matrix.component.html.ejs +212 -0
- package/src/templates/angular/iam/user-access-matrix.component.scss.ejs +34 -0
- package/src/templates/angular/iam/user-access-matrix.component.ts.ejs +239 -0
- package/src/templates/angular/iam/user-detail.component.html.ejs +143 -0
- package/src/templates/angular/iam/user-detail.component.ts.ejs +108 -0
- package/src/templates/angular/iam/user-form.component.html.ejs +63 -0
- package/src/templates/angular/iam/user-form.component.ts.ejs +100 -0
- package/src/templates/angular/iam/user-list.component.html.ejs +369 -0
- package/src/templates/angular/iam/user-list.component.scss.ejs +242 -0
- package/src/templates/angular/iam/user-list.component.ts.ejs +446 -0
- package/src/templates/angular/iam/user-management.routes.ts.ejs +47 -0
- package/src/templates/angular/iam/user-permission-matrix.component.html.ejs +231 -0
- package/src/templates/angular/iam/user-permission-matrix.component.scss.ejs +216 -0
- package/src/templates/angular/iam/user-permission-matrix.component.ts.ejs +516 -0
- package/src/templates/angular/shared/base/audit-user-name.pipe.ts.ejs +69 -0
- package/src/templates/angular/shared/base/base-filter.component.ts.ejs +245 -0
- package/src/templates/angular/shared/base/base-form.component.ts.ejs +109 -0
- package/src/templates/angular/shared/base/base-list.component.ts.ejs +507 -0
- package/src/templates/angular/shared/base/filter-types.ts.ejs +55 -0
- package/src/templates/angular/shared/base/input-format.directive.ts.ejs +47 -0
- package/src/templates/angular/shared/base/input-format.ts.ejs +15 -0
- package/src/templates/angular/shared/confirm-with-input-dialog.component.ts.ejs +91 -0
- package/src/templates/angular/shared/confirmation-dialog.component.ts.ejs +80 -0
- package/src/templates/angular/shared/list-styles.css.ejs +103 -0
- package/src/templates/angular/shared/loading-overlay.component.ts.ejs +24 -0
- package/src/templates/angular/shared/resizable.directive.ts.ejs +115 -0
- package/src/templates/angular/shared/snackbar-styles.css.ejs +11 -0
- package/src/templates/fuse-packs/access-control-tools/access-control-sync.js +819 -0
- package/src/templates/fuse-packs/access-control-tools/build-rename-map.js +67 -0
- package/src/templates/fuse-packs/access-control-tools/inject-qa-ids.js +14 -0
- package/src/templates/fuse-packs/access-control-tools/lib/hierarchy-scanner.js +628 -0
- package/src/templates/fuse-packs/access-control-tools/lib/hierarchy-scanner.test.js +323 -0
- package/src/templates/fuse-packs/access-control-tools/lib/html-scanner.js +362 -0
- package/src/templates/fuse-packs/access-control-tools/lib/id-rules.duplicate.test.js +136 -0
- package/src/templates/fuse-packs/access-control-tools/lib/id-rules.js +1095 -0
- package/src/templates/fuse-packs/access-control-tools/lib/ts-component-index.js +482 -0
- package/src/templates/fuse-packs/access-control-tools/output/.gitkeep +0 -0
- package/src/templates/fuse-packs/access-control-tools/run.sh +223 -0
- package/src/templates/fuse-packs/access-control-tools/scan-access-control.js +14 -0
- package/src/templates/fuse-packs/iam-assets/sound/apple-play.mp3 +0 -0
- package/src/templates/fuse-packs/iam-assets/sound/remove.mp3 +0 -0
- package/src/templates/generator/README.md +12 -0
- package/src/templates/testing/ci.cjs +45 -0
- package/src/templates/testing/mock.cjs +149 -0
- package/src/templates/testing/playwright.config.cjs +25 -0
- package/src/templates/testing/serve.cjs +22 -0
- package/src/templates/testing/smoke.spec.cjs +180 -0
- package/src/utils/branding.js +39 -0
- package/src/utils/colors.js +18 -0
- package/src/utils/diff.js +109 -0
- package/src/utils/merger.js +115 -0
- package/src/validator/backend-diagnostics.js +30 -0
- package/src/validator/blueprint-validator.js +276 -0
- package/src/validator/diagnostics.js +608 -0
- package/src/validator/pattern.js +28 -0
- package/test/auth-interceptor.js +84 -0
- package/test/auth-provision-checks.js +297 -0
- package/test/field-preferences.js +145 -0
- package/test/fixtures/field-profile.gdl +7 -0
- package/test/fixtures/mock.jdl +17 -0
- package/test/fixtures/mock.png +0 -0
- package/test/fixtures/performance/config.yml +33 -0
- package/test/fixtures/performance/large.gdl +199 -0
- package/test/fixtures/performance/small.gdl +7 -0
- package/test/fixtures/quality/custom.yml +22 -0
- package/test/fixtures/quality/go-duck.yml +22 -0
- package/test/fixtures/quality/jhipster.yml +30 -0
- package/test/fixtures/quality/representative.gdl +14 -0
- package/test/list-state.js +138 -0
- package/test/micro-functions-layout.js +95 -0
- package/test/performance-generation.js +32 -0
- package/test/pmb-preset.js +127 -0
- package/test/project-workflow.js +111 -0
- package/test/quality-features.js +250 -0
- package/test/verify-commands.js +83 -0
- package/test/verify.js +959 -0
- package/test-files/GDL/example.gdl +15 -0
- package/test-files/JDL/example.jdl +15 -0
- package/test-files/config/crudforge.config.yml +127 -0
- 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.
|