create-appraisejs 0.1.6 ā 0.1.8-alpha
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/README.md +45 -45
- package/dist/cli.js +4 -4
- package/dist/cli.js.map +1 -1
- package/dist/copy-template.d.ts +2 -1
- package/dist/copy-template.d.ts.map +1 -1
- package/dist/copy-template.js +10 -7
- package/dist/copy-template.js.map +1 -1
- package/dist/copy-template.test.js +19 -0
- package/dist/copy-template.test.js.map +1 -1
- package/package.json +69 -67
- package/templates/default/.vscode/settings.json +5 -0
- package/templates/default/appraisejs.config.json +1 -1
- package/templates/default/components.json +24 -24
- package/templates/default/cucumber.mjs +16 -0
- package/templates/default/eslint.config.mjs +15 -15
- package/templates/default/next.config.ts +13 -7
- package/templates/default/package-lock.json +13732 -14321
- package/templates/default/package.json +11 -9
- package/templates/default/postcss.config.mjs +8 -8
- package/templates/default/prisma/migrations/20251104113456_add_type_for_template_step_groups/migration.sql +16 -16
- package/templates/default/prisma/migrations/20251104170946_add_tags_to_test_suite_and_test_case/migration.sql +27 -27
- package/templates/default/prisma/migrations/20251112190024_add_cascade_delete_to_test_run_test_case/migration.sql +17 -17
- package/templates/default/prisma/migrations/20251113181100_add_test_run_log/migration.sql +12 -12
- package/templates/default/prisma/migrations/20251119191838_add_tag_type/migration.sql +28 -28
- package/templates/default/prisma/migrations/20251121164059_add_conflict_resolution/migration.sql +12 -12
- package/templates/default/prisma/migrations/20251223183400_add_report_model_to_db_schema/migration.sql +10 -10
- package/templates/default/prisma/migrations/20251223183637_add_report_test_case_entity_for_storing_test_results_for_individual_test_cases/migration.sql +10 -10
- package/templates/default/prisma/migrations/20251224083549_add_comprehensive_report_storage/migration.sql +108 -108
- package/templates/default/prisma/migrations/20251229194422_migrate_duration_to_string/migration.sql +55 -55
- package/templates/default/prisma/migrations/20251230124637_add_unique_constraint_to_test_run_name/migration.sql +27 -27
- package/templates/default/prisma/migrations/20260115094436_add_dashboard_metrics/migration.sql +59 -59
- package/templates/default/prisma/migrations/20260127172022_add_cascade_delete_to_step_parameters/migration.sql +34 -34
- package/templates/default/prisma/schema.prisma +554 -554
- package/templates/default/scripts/regenerate-features.ts +94 -94
- package/templates/default/scripts/setup-env.ts +19 -19
- package/templates/default/scripts/sync-all.ts +341 -341
- package/templates/default/scripts/sync-appraise-base-template.ts +52 -2
- package/templates/default/scripts/sync-environments.ts +323 -323
- package/templates/default/scripts/sync-locator-groups.ts +413 -413
- package/templates/default/scripts/sync-locators.ts +402 -402
- package/templates/default/scripts/sync-modules.ts +349 -349
- package/templates/default/scripts/sync-tags.ts +292 -292
- package/templates/default/scripts/sync-template-step-groups.ts +399 -399
- package/templates/default/scripts/sync-template-steps.ts +806 -806
- package/templates/default/scripts/sync-test-cases.ts +905 -905
- package/templates/default/scripts/sync-test-suites.ts +411 -411
- package/templates/default/src/actions/conflict/conflict.action.ts +33 -33
- package/templates/default/src/actions/dashboard/dashboard-actions.ts +240 -240
- package/templates/default/src/actions/environments/environment-actions.ts +205 -205
- package/templates/default/src/actions/locator/locator-actions.ts +547 -547
- package/templates/default/src/actions/locator-groups/locator-group-actions.ts +344 -344
- package/templates/default/src/actions/modules/module-actions.ts +133 -133
- package/templates/default/src/actions/reports/report-actions.ts +613 -613
- package/templates/default/src/actions/review/review-actions.ts +147 -147
- package/templates/default/src/actions/tags/tag-actions.ts +104 -104
- package/templates/default/src/actions/template-step/template-step-actions.ts +332 -332
- package/templates/default/src/actions/template-step-group/template-step-group-actions.ts +278 -278
- package/templates/default/src/actions/template-test-case/template-test-case-actions.ts +238 -238
- package/templates/default/src/actions/test-case/test-case-actions.ts +419 -419
- package/templates/default/src/actions/test-run/test-run-actions.ts +1185 -1185
- package/templates/default/src/actions/test-suite/test-suite-actions.ts +253 -253
- package/templates/default/src/actions/user/user-actions.ts +13 -13
- package/templates/default/src/app/(base)/environments/create/page.tsx +28 -28
- package/templates/default/src/app/(base)/environments/environment-form.tsx +219 -219
- package/templates/default/src/app/(base)/environments/environment-table-columns.tsx +96 -96
- package/templates/default/src/app/(base)/environments/environment-table.tsx +24 -24
- package/templates/default/src/app/(base)/environments/modify/[id]/page.tsx +46 -46
- package/templates/default/src/app/(base)/environments/page.tsx +59 -59
- package/templates/default/src/app/(base)/layout.tsx +10 -10
- package/templates/default/src/app/(base)/locator-groups/create/page.tsx +44 -44
- package/templates/default/src/app/(base)/locator-groups/locator-group-form.tsx +215 -215
- package/templates/default/src/app/(base)/locator-groups/locator-group-table-columns.tsx +77 -77
- package/templates/default/src/app/(base)/locator-groups/locator-group-table.tsx +28 -28
- package/templates/default/src/app/(base)/locator-groups/modify/[id]/page.tsx +46 -46
- package/templates/default/src/app/(base)/locator-groups/page.tsx +61 -61
- package/templates/default/src/app/(base)/locators/create/page.tsx +38 -38
- package/templates/default/src/app/(base)/locators/locator-form.tsx +163 -163
- package/templates/default/src/app/(base)/locators/locator-table-columns.tsx +73 -90
- package/templates/default/src/app/(base)/locators/locator-table.tsx +28 -28
- package/templates/default/src/app/(base)/locators/modify/[id]/page.tsx +45 -45
- package/templates/default/src/app/(base)/locators/page.tsx +65 -65
- package/templates/default/src/app/(base)/locators/sync-locators-button.tsx +66 -66
- package/templates/default/src/app/(base)/modules/create/page.tsx +34 -34
- package/templates/default/src/app/(base)/modules/modify/[id]/page.tsx +46 -46
- package/templates/default/src/app/(base)/modules/module-form.tsx +126 -126
- package/templates/default/src/app/(base)/modules/module-table-columns.tsx +85 -85
- package/templates/default/src/app/(base)/modules/module-table.tsx +24 -24
- package/templates/default/src/app/(base)/modules/page.tsx +59 -59
- package/templates/default/src/app/(base)/reports/[id]/page.tsx +517 -517
- package/templates/default/src/app/(base)/reports/duration-chart.tsx +33 -33
- package/templates/default/src/app/(base)/reports/feature-chart.tsx +78 -78
- package/templates/default/src/app/(base)/reports/overview-chart.tsx +46 -46
- package/templates/default/src/app/(base)/reports/page.tsx +98 -98
- package/templates/default/src/app/(base)/reports/report-metric-card.tsx +16 -16
- package/templates/default/src/app/(base)/reports/report-table-columns.tsx +189 -189
- package/templates/default/src/app/(base)/reports/report-table.tsx +72 -72
- package/templates/default/src/app/(base)/reports/report-view-table-columns.tsx +131 -131
- package/templates/default/src/app/(base)/reports/report-view-table.tsx +82 -82
- package/templates/default/src/app/(base)/reports/test-cases/page.tsx +42 -42
- package/templates/default/src/app/(base)/reports/test-cases/test-cases-metric-table-columns.tsx +115 -115
- package/templates/default/src/app/(base)/reports/test-cases/test-cases-metric-table.tsx +27 -27
- package/templates/default/src/app/(base)/reports/test-suites/page.tsx +42 -42
- package/templates/default/src/app/(base)/reports/test-suites/test-suites-metric-table-columns.tsx +79 -79
- package/templates/default/src/app/(base)/reports/test-suites/test-suites-metric-table.tsx +27 -27
- package/templates/default/src/app/(base)/reports/view-logs-button.tsx +60 -60
- package/templates/default/src/app/(base)/reviews/create/page.tsx +26 -26
- package/templates/default/src/app/(base)/reviews/created-reviews-table.tsx +15 -15
- package/templates/default/src/app/(base)/reviews/modify/[id]/page.tsx +26 -26
- package/templates/default/src/app/(base)/reviews/page.tsx +26 -26
- package/templates/default/src/app/(base)/reviews/review/[id]/page.tsx +26 -26
- package/templates/default/src/app/(base)/reviews/review-form.tsx +11 -11
- package/templates/default/src/app/(base)/reviews/review-table-by-creator-columns.tsx +9 -9
- package/templates/default/src/app/(base)/reviews/review-table-by-reviewer-columns.tsx +9 -9
- package/templates/default/src/app/(base)/reviews/reviewer-reviews-table.tsx +15 -15
- package/templates/default/src/app/(base)/tags/create/page.tsx +39 -39
- package/templates/default/src/app/(base)/tags/modify/[id]/page.tsx +50 -50
- package/templates/default/src/app/(base)/tags/page.tsx +58 -58
- package/templates/default/src/app/(base)/tags/tag-form.tsx +147 -147
- package/templates/default/src/app/(base)/tags/tag-table-columns.tsx +63 -63
- package/templates/default/src/app/(base)/tags/tag-table.tsx +29 -29
- package/templates/default/src/app/(base)/template-step-groups/create/page.tsx +28 -28
- package/templates/default/src/app/(base)/template-step-groups/modify/[id]/page.tsx +45 -45
- package/templates/default/src/app/(base)/template-step-groups/page.tsx +60 -60
- package/templates/default/src/app/(base)/template-step-groups/template-step-group-form.tsx +167 -167
- package/templates/default/src/app/(base)/template-step-groups/template-step-group-table-columns.tsx +89 -89
- package/templates/default/src/app/(base)/template-step-groups/template-step-group-table.tsx +32 -32
- package/templates/default/src/app/(base)/template-steps/create/page.tsx +37 -37
- package/templates/default/src/app/(base)/template-steps/modify/[id]/page.tsx +49 -49
- package/templates/default/src/app/(base)/template-steps/page.tsx +59 -59
- package/templates/default/src/app/(base)/template-steps/paramChip.tsx +213 -213
- package/templates/default/src/app/(base)/template-steps/template-step-form.tsx +384 -384
- package/templates/default/src/app/(base)/template-steps/template-step-table-columns.tsx +158 -158
- package/templates/default/src/app/(base)/template-steps/template-step-table.tsx +24 -24
- package/templates/default/src/app/(base)/template-test-cases/create/page.tsx +56 -56
- package/templates/default/src/app/(base)/template-test-cases/modify/[id]/page.tsx +89 -89
- package/templates/default/src/app/(base)/template-test-cases/page.tsx +58 -58
- package/templates/default/src/app/(base)/template-test-cases/template-test-case-flow.tsx +84 -84
- package/templates/default/src/app/(base)/template-test-cases/template-test-case-form.tsx +262 -262
- package/templates/default/src/app/(base)/template-test-cases/template-test-case-table-columns.tsx +76 -76
- package/templates/default/src/app/(base)/template-test-cases/template-test-case-table.tsx +32 -32
- package/templates/default/src/app/(base)/test-cases/create/page.tsx +76 -76
- package/templates/default/src/app/(base)/test-cases/create-from-template/generate/[id]/page.tsx +96 -96
- package/templates/default/src/app/(base)/test-cases/create-from-template/page.tsx +38 -38
- package/templates/default/src/app/(base)/test-cases/create-from-template/template-selection-form.tsx +73 -73
- package/templates/default/src/app/(base)/test-cases/modify/[id]/page.tsx +106 -106
- package/templates/default/src/app/(base)/test-cases/page.tsx +60 -60
- package/templates/default/src/app/(base)/test-cases/test-case-flow.tsx +82 -82
- package/templates/default/src/app/(base)/test-cases/test-case-form.tsx +395 -395
- package/templates/default/src/app/(base)/test-cases/test-case-table-columns.tsx +90 -90
- package/templates/default/src/app/(base)/test-cases/test-case-table.tsx +35 -35
- package/templates/default/src/app/(base)/test-runs/[id]/page.tsx +56 -56
- package/templates/default/src/app/(base)/test-runs/create/page.tsx +47 -47
- package/templates/default/src/app/(base)/test-runs/page.tsx +60 -60
- package/templates/default/src/app/(base)/test-runs/test-run-form.tsx +508 -512
- package/templates/default/src/app/(base)/test-runs/test-run-table-columns.tsx +229 -229
- package/templates/default/src/app/(base)/test-runs/test-run-table.tsx +127 -127
- package/templates/default/src/app/(base)/test-suites/create/page.tsx +45 -45
- package/templates/default/src/app/(base)/test-suites/modify/[id]/page.tsx +55 -55
- package/templates/default/src/app/(base)/test-suites/page.tsx +82 -82
- package/templates/default/src/app/(base)/test-suites/test-suite-form.tsx +269 -269
- package/templates/default/src/app/(base)/test-suites/test-suite-table-columns.tsx +97 -97
- package/templates/default/src/app/(base)/test-suites/test-suite-table.tsx +29 -29
- package/templates/default/src/app/(dashboard-components)/app-drawer.tsx +187 -187
- package/templates/default/src/app/(dashboard-components)/data-card-grid.tsx +12 -12
- package/templates/default/src/app/(dashboard-components)/data-card.tsx +26 -26
- package/templates/default/src/app/(dashboard-components)/execution-health-panel.tsx +56 -56
- package/templates/default/src/app/(dashboard-components)/ongoing-test-runs-card.tsx +87 -87
- package/templates/default/src/app/(dashboard-components)/quick-actions-drawer.tsx +44 -44
- package/templates/default/src/app/api/test-runs/[runId]/download/route.ts +133 -133
- package/templates/default/src/app/api/test-runs/[runId]/logs/route.ts +420 -420
- package/templates/default/src/app/api/test-runs/[runId]/trace/[testCaseId]/route.ts +146 -146
- package/templates/default/src/app/globals.css +147 -147
- package/templates/default/src/app/layout.tsx +171 -171
- package/templates/default/src/app/page.tsx +64 -64
- package/templates/default/src/assets/icons/empty-tube.tsx +23 -23
- package/templates/default/src/assets/icons/tube-plus.tsx +29 -29
- package/templates/default/src/components/base-node.tsx +21 -21
- package/templates/default/src/components/chart/pie-chart.tsx +73 -73
- package/templates/default/src/components/data-extraction/locator-inspector.tsx +460 -460
- package/templates/default/src/components/data-state/empty-state.tsx +40 -40
- package/templates/default/src/components/data-visualization/info-card.tsx +70 -70
- package/templates/default/src/components/data-visualization/info-grid.tsx +22 -22
- package/templates/default/src/components/devtools/providers.tsx +19 -13
- package/templates/default/src/components/diagram/button-edge.tsx +54 -54
- package/templates/default/src/components/diagram/dynamic-parameters.tsx +438 -438
- package/templates/default/src/components/diagram/edit-header-option.tsx +36 -36
- package/templates/default/src/components/diagram/flow-diagram.tsx +470 -470
- package/templates/default/src/components/diagram/node-form.tsx +262 -262
- package/templates/default/src/components/diagram/options-header-node.tsx +57 -57
- package/templates/default/src/components/diagram/template-step-combobox.tsx +155 -155
- package/templates/default/src/components/form/error-message.tsx +7 -7
- package/templates/default/src/components/kokonutui/smooth-tab.tsx +453 -453
- package/templates/default/src/components/loading-skeleton/data-table/data-table-skeleton.tsx +30 -30
- package/templates/default/src/components/loading-skeleton/form/button-skeleton.tsx +8 -8
- package/templates/default/src/components/loading-skeleton/form/icon-button-skeleton.tsx +8 -8
- package/templates/default/src/components/loading-skeleton/form/text-input-skeleton.tsx +8 -8
- package/templates/default/src/components/loading-skeleton/visualization/table-skeleton.tsx +14 -14
- package/templates/default/src/components/logo.tsx +15 -15
- package/templates/default/src/components/navigation/command-badge.tsx +34 -34
- package/templates/default/src/components/navigation/command-chain-input.tsx +51 -51
- package/templates/default/src/components/navigation/entity-search-command.tsx +116 -116
- package/templates/default/src/components/navigation/nav-card.tsx +31 -31
- package/templates/default/src/components/navigation/nav-command.tsx +508 -508
- package/templates/default/src/components/navigation/nav-link.tsx +60 -60
- package/templates/default/src/components/navigation/nav-menu-card-deck.tsx +112 -112
- package/templates/default/src/components/node-header.tsx +159 -159
- package/templates/default/src/components/reports/test-case-logs-modal.tsx +253 -253
- package/templates/default/src/components/table/table-actions.tsx +172 -172
- package/templates/default/src/components/test-run/download-logs-button.tsx +99 -99
- package/templates/default/src/components/test-run/log-viewer.tsx +445 -445
- package/templates/default/src/components/test-run/test-run-details.tsx +611 -611
- package/templates/default/src/components/test-run/test-run-header.tsx +149 -149
- package/templates/default/src/components/test-run/view-report-button.tsx +102 -102
- package/templates/default/src/components/theme/mode-toggle.tsx +54 -54
- package/templates/default/src/components/theme/theme-provider.tsx +8 -8
- package/templates/default/src/components/typography/page-header-subtitle.tsx +7 -7
- package/templates/default/src/components/typography/page-header.tsx +7 -7
- package/templates/default/src/components/ui/alert-dialog.tsx +106 -106
- package/templates/default/src/components/ui/alert.tsx +43 -43
- package/templates/default/src/components/ui/avatar.tsx +40 -40
- package/templates/default/src/components/ui/badge.tsx +29 -29
- package/templates/default/src/components/ui/button.tsx +47 -47
- package/templates/default/src/components/ui/calendar.tsx +158 -158
- package/templates/default/src/components/ui/card.tsx +43 -43
- package/templates/default/src/components/ui/checkbox.tsx +28 -28
- package/templates/default/src/components/ui/command.tsx +135 -135
- package/templates/default/src/components/ui/data-table-column-header.tsx +61 -61
- package/templates/default/src/components/ui/data-table-pagination.tsx +87 -87
- package/templates/default/src/components/ui/data-table-view-options.tsx +50 -50
- package/templates/default/src/components/ui/data-table.tsx +267 -267
- package/templates/default/src/components/ui/dialog.tsx +97 -97
- package/templates/default/src/components/ui/dropdown-menu.tsx +182 -182
- package/templates/default/src/components/ui/input.tsx +22 -22
- package/templates/default/src/components/ui/kbd.tsx +28 -28
- package/templates/default/src/components/ui/label.tsx +19 -19
- package/templates/default/src/components/ui/loading.tsx +12 -12
- package/templates/default/src/components/ui/multi-select-with-preview.tsx +116 -116
- package/templates/default/src/components/ui/multi-select.tsx +142 -142
- package/templates/default/src/components/ui/navigation-menu.tsx +120 -120
- package/templates/default/src/components/ui/popover.tsx +33 -33
- package/templates/default/src/components/ui/progress.tsx +25 -25
- package/templates/default/src/components/ui/radio-group.tsx +44 -44
- package/templates/default/src/components/ui/scroll-area.tsx +40 -40
- package/templates/default/src/components/ui/select.tsx +151 -144
- package/templates/default/src/components/ui/separator.tsx +22 -22
- package/templates/default/src/components/ui/skeleton.tsx +7 -7
- package/templates/default/src/components/ui/table.tsx +76 -76
- package/templates/default/src/components/ui/tabs.tsx +55 -55
- package/templates/default/src/components/ui/textarea.tsx +21 -21
- package/templates/default/src/components/ui/toast.tsx +113 -113
- package/templates/default/src/components/ui/toaster.tsx +26 -26
- package/templates/default/src/components/user-prompt/delete-prompt.tsx +87 -87
- package/templates/default/src/config/db-config.ts +10 -10
- package/templates/default/src/constants/form-opts/diagram/node-form.ts +30 -30
- package/templates/default/src/constants/form-opts/environment-form-opts.ts +24 -24
- package/templates/default/src/constants/form-opts/locator-form-opts.ts +20 -20
- package/templates/default/src/constants/form-opts/locator-group-form-opts.ts +28 -28
- package/templates/default/src/constants/form-opts/module-form-opts.ts +21 -21
- package/templates/default/src/constants/form-opts/review-form-opts.ts +23 -23
- package/templates/default/src/constants/form-opts/tag-form-opts.ts +42 -42
- package/templates/default/src/constants/form-opts/template-selection-form-opts.ts +16 -16
- package/templates/default/src/constants/form-opts/template-step-group-form-opts.ts +24 -24
- package/templates/default/src/constants/form-opts/template-test-case-form-opts.ts +39 -39
- package/templates/default/src/constants/form-opts/template-test-step-form-opts.ts +36 -36
- package/templates/default/src/constants/form-opts/test-case-form-opts.ts +43 -43
- package/templates/default/src/constants/form-opts/test-run-form-opts.ts +31 -31
- package/templates/default/src/constants/form-opts/test-suite-form-opts.ts +24 -24
- package/templates/default/src/hooks/use-toast.ts +187 -187
- package/templates/default/src/lib/bidirectional-sync.ts +432 -432
- package/templates/default/src/lib/database-sync.ts +531 -531
- package/templates/default/src/lib/environment-file-utils.ts +221 -221
- package/templates/default/src/lib/feature-file-generator.ts +411 -411
- package/templates/default/src/lib/gherkin-parser.ts +259 -259
- package/templates/default/src/lib/locator-group-file-utils.ts +370 -370
- package/templates/default/src/lib/metrics/metric-calculator.ts +613 -613
- package/templates/default/src/lib/module-hierarchy-builder.ts +205 -205
- package/templates/default/src/lib/path-helpers/module-path.ts +71 -71
- package/templates/default/src/lib/test-case-utils.ts +6 -6
- package/templates/default/src/lib/test-run/log-formatter.ts +83 -83
- package/templates/default/src/lib/test-run/process-manager.ts +191 -191
- package/templates/default/src/lib/test-run/report-parser.ts +316 -316
- package/templates/default/src/lib/test-run/test-run-executor.ts +144 -144
- package/templates/default/src/lib/test-run/winston-logger.ts +95 -95
- package/templates/default/src/lib/transformers/gherkin-converter.ts +42 -42
- package/templates/default/src/lib/transformers/key-to-icon-transformer.tsx +95 -95
- package/templates/default/src/lib/transformers/template-test-case-converter.ts +160 -160
- package/templates/default/src/lib/utils/node-param-validation.ts +81 -81
- package/templates/default/src/lib/utils/template-step-file-generator.ts +167 -167
- package/templates/default/src/lib/utils/template-step-file-manager-intelligent.ts +723 -723
- package/templates/default/src/lib/utils/template-step-file-manager.ts +166 -166
- package/templates/default/src/lib/utils.ts +31 -31
- package/templates/default/src/tests/config/executor/world.ts +41 -41
- package/templates/default/src/tests/executor.ts +80 -80
- package/templates/default/src/tests/hooks/hooks.ts +99 -99
- package/templates/default/src/tests/mapping/locator-map.json +1 -1
- package/templates/default/src/tests/steps/actions/click.step.ts +62 -62
- package/templates/default/src/tests/steps/actions/navigation.step.ts +73 -72
- package/templates/default/src/tests/steps/validations/active_state_assertion.step.ts +34 -34
- package/templates/default/src/tests/steps/validations/navigation_assertion.step.ts +24 -23
- package/templates/default/src/tests/steps/validations/text_assertion.step.ts +111 -111
- package/templates/default/src/tests/steps/validations/visibility_assertion.step.ts +30 -30
- package/templates/default/src/tests/support/parameter-types.ts +12 -12
- package/templates/default/src/tests/utils/cache.util.ts +260 -260
- package/templates/default/src/tests/utils/cli.util.ts +177 -177
- package/templates/default/src/tests/utils/environment.util.ts +65 -65
- package/templates/default/src/tests/utils/locator.util.ts +248 -248
- package/templates/default/src/tests/utils/random-data.util.ts +44 -44
- package/templates/default/src/tests/utils/spawner.util.ts +617 -617
- package/templates/default/src/types/diagram/diagram.ts +34 -34
- package/templates/default/src/types/diagram/template-step.ts +11 -11
- package/templates/default/src/types/executor/browser.type.ts +1 -1
- package/templates/default/src/types/form/actionHandler.ts +6 -6
- package/templates/default/src/types/locator/locator.type.ts +11 -11
- package/templates/default/src/types/step/step.type.ts +1 -1
- package/templates/default/src/types/table/data-table.ts +6 -6
- package/templates/default/tailwind.config.ts +62 -62
- package/templates/default/.env +0 -2
- package/templates/default/next-env.d.ts +0 -6
- package/templates/default/prisma/prisma/dev.db +0 -0
- package/templates/default/src/tests/config/environments/environments.json +0 -14
|
@@ -1,292 +1,292 @@
|
|
|
1
|
-
#!/usr/bin/env tsx
|
|
2
|
-
|
|
3
|
-
/**
|
|
4
|
-
* Script to synchronize tags from feature files to database
|
|
5
|
-
* Scans feature files to ensure all tags exist in DB
|
|
6
|
-
* Filesystem is the source of truth - tags in DB but not in FS will be deleted
|
|
7
|
-
* Run this after merging changes to ensure tag sync
|
|
8
|
-
*
|
|
9
|
-
* Usage: npx tsx scripts/sync-tags.ts
|
|
10
|
-
*/
|
|
11
|
-
|
|
12
|
-
import { join } from 'path'
|
|
13
|
-
import prisma from '../src/config/db-config'
|
|
14
|
-
import { scanFeatureFiles, ParsedFeature } from '../src/lib/gherkin-parser'
|
|
15
|
-
import { TagType } from '@prisma/client'
|
|
16
|
-
|
|
17
|
-
interface TagData {
|
|
18
|
-
name: string // Without @ prefix, for DB storage
|
|
19
|
-
tagExpression: string // With @ prefix, for tagExpression field
|
|
20
|
-
type: TagType // IDENTIFIER or FILTER
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
interface SyncResult {
|
|
24
|
-
tagsScanned: number
|
|
25
|
-
tagsExisting: number
|
|
26
|
-
tagsCreated: number
|
|
27
|
-
tagsDeleted: number
|
|
28
|
-
errors: string[]
|
|
29
|
-
createdTags: string[]
|
|
30
|
-
deletedTags: string[]
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
/**
|
|
34
|
-
* Splits a tag line that may contain multiple tags separated by spaces
|
|
35
|
-
* Example: "@smoke @demo" -> ["@smoke", "@demo"]
|
|
36
|
-
*/
|
|
37
|
-
function splitTagLine(tagLine: string): string[] {
|
|
38
|
-
// Split by spaces and filter for strings that start with @
|
|
39
|
-
return tagLine
|
|
40
|
-
.split(/\s+/)
|
|
41
|
-
.filter(tag => tag.trim().startsWith('@'))
|
|
42
|
-
.map(tag => tag.trim())
|
|
43
|
-
}
|
|
44
|
-
|
|
45
|
-
/**
|
|
46
|
-
* Extracts unique tags from parsed feature files
|
|
47
|
-
* Combines feature-level and scenario-level tags
|
|
48
|
-
* Handles tags on the same line separated by spaces
|
|
49
|
-
*/
|
|
50
|
-
function extractUniqueTags(parsedFeatures: ParsedFeature[]): Set<string> {
|
|
51
|
-
const uniqueTags = new Set<string>()
|
|
52
|
-
|
|
53
|
-
for (const feature of parsedFeatures) {
|
|
54
|
-
// Add feature-level tags
|
|
55
|
-
for (const tagLine of feature.tags) {
|
|
56
|
-
if (tagLine.startsWith('@')) {
|
|
57
|
-
// Split tags that might be on the same line
|
|
58
|
-
const tags = splitTagLine(tagLine)
|
|
59
|
-
for (const tag of tags) {
|
|
60
|
-
uniqueTags.add(tag)
|
|
61
|
-
}
|
|
62
|
-
}
|
|
63
|
-
}
|
|
64
|
-
|
|
65
|
-
// Add scenario-level tags
|
|
66
|
-
for (const scenario of feature.scenarios) {
|
|
67
|
-
for (const tagLine of scenario.tags) {
|
|
68
|
-
if (tagLine.startsWith('@')) {
|
|
69
|
-
// Split tags that might be on the same line
|
|
70
|
-
const tags = splitTagLine(tagLine)
|
|
71
|
-
for (const tag of tags) {
|
|
72
|
-
uniqueTags.add(tag)
|
|
73
|
-
}
|
|
74
|
-
}
|
|
75
|
-
}
|
|
76
|
-
}
|
|
77
|
-
}
|
|
78
|
-
|
|
79
|
-
return uniqueTags
|
|
80
|
-
}
|
|
81
|
-
|
|
82
|
-
/**
|
|
83
|
-
* Builds Tag objects from tag expressions
|
|
84
|
-
* Maps tag expressions to Prisma Tag model structure
|
|
85
|
-
*/
|
|
86
|
-
function buildTagObjects(tagExpressions: Set<string>): TagData[] {
|
|
87
|
-
const tagObjects: TagData[] = []
|
|
88
|
-
|
|
89
|
-
for (const tagExpression of tagExpressions) {
|
|
90
|
-
// Strip @ prefix for name field
|
|
91
|
-
const name = tagExpression.startsWith('@') ? tagExpression.substring(1) : tagExpression
|
|
92
|
-
|
|
93
|
-
// Determine type: IDENTIFIER if starts with tc_, otherwise FILTER
|
|
94
|
-
const type = name.startsWith('tc_') ? TagType.IDENTIFIER : TagType.FILTER
|
|
95
|
-
|
|
96
|
-
tagObjects.push({
|
|
97
|
-
name,
|
|
98
|
-
tagExpression, // Keep @ prefix for tagExpression
|
|
99
|
-
type,
|
|
100
|
-
})
|
|
101
|
-
}
|
|
102
|
-
|
|
103
|
-
return tagObjects
|
|
104
|
-
}
|
|
105
|
-
|
|
106
|
-
/**
|
|
107
|
-
* Syncs tags to database
|
|
108
|
-
* Creates missing tags and deletes orphaned tags (FS is source of truth)
|
|
109
|
-
*/
|
|
110
|
-
async function syncTagsToDatabase(tagObjects: TagData[]): Promise<SyncResult> {
|
|
111
|
-
const result: SyncResult = {
|
|
112
|
-
tagsScanned: tagObjects.length,
|
|
113
|
-
tagsExisting: 0,
|
|
114
|
-
tagsCreated: 0,
|
|
115
|
-
tagsDeleted: 0,
|
|
116
|
-
errors: [],
|
|
117
|
-
createdTags: [],
|
|
118
|
-
deletedTags: [],
|
|
119
|
-
}
|
|
120
|
-
|
|
121
|
-
// Get set of tag names from feature files (FS source of truth)
|
|
122
|
-
const fsTagNames = new Set(tagObjects.map(tag => tag.name))
|
|
123
|
-
|
|
124
|
-
// Get all tags from database
|
|
125
|
-
const allDbTags = await prisma.tag.findMany({
|
|
126
|
-
select: { id: true, name: true },
|
|
127
|
-
})
|
|
128
|
-
|
|
129
|
-
// Delete tags from DB that are not in FS (FS is source of truth)
|
|
130
|
-
console.log('\nš Checking for orphaned tags (not in feature files)...')
|
|
131
|
-
for (const dbTag of allDbTags) {
|
|
132
|
-
if (!fsTagNames.has(dbTag.name)) {
|
|
133
|
-
try {
|
|
134
|
-
await prisma.tag.delete({
|
|
135
|
-
where: { id: dbTag.id },
|
|
136
|
-
})
|
|
137
|
-
result.tagsDeleted++
|
|
138
|
-
result.deletedTags.push(dbTag.name)
|
|
139
|
-
console.log(` šļø Deleted tag '${dbTag.name}' (not in feature files)`)
|
|
140
|
-
} catch (error) {
|
|
141
|
-
const errorMsg = `Error deleting tag '${dbTag.name}': ${error}`
|
|
142
|
-
result.errors.push(errorMsg)
|
|
143
|
-
console.error(` ā ${errorMsg}`)
|
|
144
|
-
}
|
|
145
|
-
}
|
|
146
|
-
}
|
|
147
|
-
|
|
148
|
-
// Create or check tags from FS
|
|
149
|
-
console.log('\nā
Syncing tags from feature files to database...')
|
|
150
|
-
for (const tagData of tagObjects) {
|
|
151
|
-
try {
|
|
152
|
-
// Check if tag already exists by name (names are unique per user requirement)
|
|
153
|
-
const existing = await prisma.tag.findFirst({
|
|
154
|
-
where: { name: tagData.name },
|
|
155
|
-
})
|
|
156
|
-
|
|
157
|
-
if (existing) {
|
|
158
|
-
// If tag exists but has wrong type, update it
|
|
159
|
-
// This fixes tags that were created with wrong type (e.g., via UI or old code)
|
|
160
|
-
if (existing.type !== tagData.type) {
|
|
161
|
-
await prisma.tag.update({
|
|
162
|
-
where: { id: existing.id },
|
|
163
|
-
data: { type: tagData.type },
|
|
164
|
-
})
|
|
165
|
-
result.tagsCreated++ // Count as created since we're fixing it
|
|
166
|
-
result.createdTags.push(tagData.name)
|
|
167
|
-
console.log(` š Updated tag '${tagData.name}' type from ${existing.type} to ${tagData.type}`)
|
|
168
|
-
} else {
|
|
169
|
-
result.tagsExisting++
|
|
170
|
-
console.log(` ā Tag '${tagData.name}' already exists`)
|
|
171
|
-
}
|
|
172
|
-
} else {
|
|
173
|
-
// Create the tag
|
|
174
|
-
await prisma.tag.create({
|
|
175
|
-
data: {
|
|
176
|
-
name: tagData.name,
|
|
177
|
-
tagExpression: tagData.tagExpression,
|
|
178
|
-
type: tagData.type,
|
|
179
|
-
},
|
|
180
|
-
})
|
|
181
|
-
result.tagsCreated++
|
|
182
|
-
result.createdTags.push(tagData.name)
|
|
183
|
-
console.log(` ā Created tag '${tagData.name}' (type: ${tagData.type})`)
|
|
184
|
-
}
|
|
185
|
-
} catch (error) {
|
|
186
|
-
const errorMsg = `Error syncing tag '${tagData.name}': ${error}`
|
|
187
|
-
result.errors.push(errorMsg)
|
|
188
|
-
console.error(` ā ${errorMsg}`)
|
|
189
|
-
}
|
|
190
|
-
}
|
|
191
|
-
|
|
192
|
-
return result
|
|
193
|
-
}
|
|
194
|
-
|
|
195
|
-
/**
|
|
196
|
-
* Generates and displays sync summary
|
|
197
|
-
*/
|
|
198
|
-
function generateSummary(result: SyncResult): void {
|
|
199
|
-
console.log('\nš Sync Summary:')
|
|
200
|
-
console.log(` š Tags scanned: ${result.tagsScanned}`)
|
|
201
|
-
console.log(` ā
Tags existing: ${result.tagsExisting}`)
|
|
202
|
-
console.log(` ā Tags created: ${result.tagsCreated}`)
|
|
203
|
-
console.log(` šļø Tags deleted: ${result.tagsDeleted}`)
|
|
204
|
-
console.log(` ā Errors: ${result.errors.length}`)
|
|
205
|
-
|
|
206
|
-
if (result.createdTags.length > 0) {
|
|
207
|
-
console.log('\n Created tags:')
|
|
208
|
-
result.createdTags.forEach((name, index) => {
|
|
209
|
-
console.log(` ${index + 1}. ${name}`)
|
|
210
|
-
})
|
|
211
|
-
}
|
|
212
|
-
|
|
213
|
-
if (result.deletedTags.length > 0) {
|
|
214
|
-
console.log('\n Deleted tags:')
|
|
215
|
-
result.deletedTags.forEach((name, index) => {
|
|
216
|
-
console.log(` ${index + 1}. ${name}`)
|
|
217
|
-
})
|
|
218
|
-
}
|
|
219
|
-
|
|
220
|
-
if (result.errors.length > 0) {
|
|
221
|
-
console.log('\n Errors:')
|
|
222
|
-
result.errors.forEach((error, index) => {
|
|
223
|
-
console.log(` ${index + 1}. ${error}`)
|
|
224
|
-
})
|
|
225
|
-
}
|
|
226
|
-
}
|
|
227
|
-
|
|
228
|
-
/**
|
|
229
|
-
* Main function
|
|
230
|
-
*/
|
|
231
|
-
async function main() {
|
|
232
|
-
try {
|
|
233
|
-
console.log('š Starting tags sync...')
|
|
234
|
-
console.log('This will scan feature files and sync tags to database.')
|
|
235
|
-
console.log('Filesystem is the source of truth - tags in DB but not in FS will be deleted.\n')
|
|
236
|
-
|
|
237
|
-
const baseDir = process.cwd()
|
|
238
|
-
const featuresDir = join(baseDir, 'src', 'tests', 'features')
|
|
239
|
-
|
|
240
|
-
// Scan feature files
|
|
241
|
-
console.log('š Scanning feature files in src/tests/features...')
|
|
242
|
-
const parsedFeatures = await scanFeatureFiles(featuresDir)
|
|
243
|
-
console.log(` Found ${parsedFeatures.length} feature file(s)`)
|
|
244
|
-
|
|
245
|
-
if (parsedFeatures.length === 0) {
|
|
246
|
-
console.log('\nā ļø No feature files found. Nothing to sync.')
|
|
247
|
-
return
|
|
248
|
-
}
|
|
249
|
-
|
|
250
|
-
// Extract unique tags
|
|
251
|
-
console.log('\nš Extracting unique tags from feature files...')
|
|
252
|
-
const uniqueTagExpressions = extractUniqueTags(parsedFeatures)
|
|
253
|
-
console.log(` Found ${uniqueTagExpressions.size} unique tag(s)`)
|
|
254
|
-
|
|
255
|
-
if (uniqueTagExpressions.size === 0) {
|
|
256
|
-
console.log('\nā ļø No tags found in feature files. Nothing to sync.')
|
|
257
|
-
return
|
|
258
|
-
}
|
|
259
|
-
|
|
260
|
-
// Build tag objects
|
|
261
|
-
console.log('\nšØ Building tag objects...')
|
|
262
|
-
const tagObjects = buildTagObjects(uniqueTagExpressions)
|
|
263
|
-
console.log(` Built ${tagObjects.length} tag object(s)`)
|
|
264
|
-
|
|
265
|
-
// Log tag details
|
|
266
|
-
console.log('\n Tag details:')
|
|
267
|
-
for (const tag of tagObjects) {
|
|
268
|
-
console.log(` - ${tag.tagExpression} ā name: '${tag.name}', type: ${tag.type}`)
|
|
269
|
-
}
|
|
270
|
-
|
|
271
|
-
// Sync to database
|
|
272
|
-
const result = await syncTagsToDatabase(tagObjects)
|
|
273
|
-
|
|
274
|
-
// Generate summary
|
|
275
|
-
generateSummary(result)
|
|
276
|
-
|
|
277
|
-
if (result.errors.length === 0) {
|
|
278
|
-
console.log('\nā
Sync completed successfully!')
|
|
279
|
-
} else {
|
|
280
|
-
console.log('\nā ļø Sync completed with errors. Please review the errors above.')
|
|
281
|
-
process.exit(1)
|
|
282
|
-
}
|
|
283
|
-
} catch (error) {
|
|
284
|
-
console.error('\nā Error during sync:', error)
|
|
285
|
-
process.exit(1)
|
|
286
|
-
} finally {
|
|
287
|
-
await prisma.$disconnect()
|
|
288
|
-
}
|
|
289
|
-
}
|
|
290
|
-
|
|
291
|
-
main()
|
|
292
|
-
|
|
1
|
+
#!/usr/bin/env tsx
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Script to synchronize tags from feature files to database
|
|
5
|
+
* Scans feature files to ensure all tags exist in DB
|
|
6
|
+
* Filesystem is the source of truth - tags in DB but not in FS will be deleted
|
|
7
|
+
* Run this after merging changes to ensure tag sync
|
|
8
|
+
*
|
|
9
|
+
* Usage: npx tsx scripts/sync-tags.ts
|
|
10
|
+
*/
|
|
11
|
+
|
|
12
|
+
import { join } from 'path'
|
|
13
|
+
import prisma from '../src/config/db-config'
|
|
14
|
+
import { scanFeatureFiles, ParsedFeature } from '../src/lib/gherkin-parser'
|
|
15
|
+
import { TagType } from '@prisma/client'
|
|
16
|
+
|
|
17
|
+
interface TagData {
|
|
18
|
+
name: string // Without @ prefix, for DB storage
|
|
19
|
+
tagExpression: string // With @ prefix, for tagExpression field
|
|
20
|
+
type: TagType // IDENTIFIER or FILTER
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
interface SyncResult {
|
|
24
|
+
tagsScanned: number
|
|
25
|
+
tagsExisting: number
|
|
26
|
+
tagsCreated: number
|
|
27
|
+
tagsDeleted: number
|
|
28
|
+
errors: string[]
|
|
29
|
+
createdTags: string[]
|
|
30
|
+
deletedTags: string[]
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
/**
|
|
34
|
+
* Splits a tag line that may contain multiple tags separated by spaces
|
|
35
|
+
* Example: "@smoke @demo" -> ["@smoke", "@demo"]
|
|
36
|
+
*/
|
|
37
|
+
function splitTagLine(tagLine: string): string[] {
|
|
38
|
+
// Split by spaces and filter for strings that start with @
|
|
39
|
+
return tagLine
|
|
40
|
+
.split(/\s+/)
|
|
41
|
+
.filter(tag => tag.trim().startsWith('@'))
|
|
42
|
+
.map(tag => tag.trim())
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
/**
|
|
46
|
+
* Extracts unique tags from parsed feature files
|
|
47
|
+
* Combines feature-level and scenario-level tags
|
|
48
|
+
* Handles tags on the same line separated by spaces
|
|
49
|
+
*/
|
|
50
|
+
function extractUniqueTags(parsedFeatures: ParsedFeature[]): Set<string> {
|
|
51
|
+
const uniqueTags = new Set<string>()
|
|
52
|
+
|
|
53
|
+
for (const feature of parsedFeatures) {
|
|
54
|
+
// Add feature-level tags
|
|
55
|
+
for (const tagLine of feature.tags) {
|
|
56
|
+
if (tagLine.startsWith('@')) {
|
|
57
|
+
// Split tags that might be on the same line
|
|
58
|
+
const tags = splitTagLine(tagLine)
|
|
59
|
+
for (const tag of tags) {
|
|
60
|
+
uniqueTags.add(tag)
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
// Add scenario-level tags
|
|
66
|
+
for (const scenario of feature.scenarios) {
|
|
67
|
+
for (const tagLine of scenario.tags) {
|
|
68
|
+
if (tagLine.startsWith('@')) {
|
|
69
|
+
// Split tags that might be on the same line
|
|
70
|
+
const tags = splitTagLine(tagLine)
|
|
71
|
+
for (const tag of tags) {
|
|
72
|
+
uniqueTags.add(tag)
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
return uniqueTags
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
/**
|
|
83
|
+
* Builds Tag objects from tag expressions
|
|
84
|
+
* Maps tag expressions to Prisma Tag model structure
|
|
85
|
+
*/
|
|
86
|
+
function buildTagObjects(tagExpressions: Set<string>): TagData[] {
|
|
87
|
+
const tagObjects: TagData[] = []
|
|
88
|
+
|
|
89
|
+
for (const tagExpression of tagExpressions) {
|
|
90
|
+
// Strip @ prefix for name field
|
|
91
|
+
const name = tagExpression.startsWith('@') ? tagExpression.substring(1) : tagExpression
|
|
92
|
+
|
|
93
|
+
// Determine type: IDENTIFIER if starts with tc_, otherwise FILTER
|
|
94
|
+
const type = name.startsWith('tc_') ? TagType.IDENTIFIER : TagType.FILTER
|
|
95
|
+
|
|
96
|
+
tagObjects.push({
|
|
97
|
+
name,
|
|
98
|
+
tagExpression, // Keep @ prefix for tagExpression
|
|
99
|
+
type,
|
|
100
|
+
})
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
return tagObjects
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
/**
|
|
107
|
+
* Syncs tags to database
|
|
108
|
+
* Creates missing tags and deletes orphaned tags (FS is source of truth)
|
|
109
|
+
*/
|
|
110
|
+
async function syncTagsToDatabase(tagObjects: TagData[]): Promise<SyncResult> {
|
|
111
|
+
const result: SyncResult = {
|
|
112
|
+
tagsScanned: tagObjects.length,
|
|
113
|
+
tagsExisting: 0,
|
|
114
|
+
tagsCreated: 0,
|
|
115
|
+
tagsDeleted: 0,
|
|
116
|
+
errors: [],
|
|
117
|
+
createdTags: [],
|
|
118
|
+
deletedTags: [],
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
// Get set of tag names from feature files (FS source of truth)
|
|
122
|
+
const fsTagNames = new Set(tagObjects.map(tag => tag.name))
|
|
123
|
+
|
|
124
|
+
// Get all tags from database
|
|
125
|
+
const allDbTags = await prisma.tag.findMany({
|
|
126
|
+
select: { id: true, name: true },
|
|
127
|
+
})
|
|
128
|
+
|
|
129
|
+
// Delete tags from DB that are not in FS (FS is source of truth)
|
|
130
|
+
console.log('\nš Checking for orphaned tags (not in feature files)...')
|
|
131
|
+
for (const dbTag of allDbTags) {
|
|
132
|
+
if (!fsTagNames.has(dbTag.name)) {
|
|
133
|
+
try {
|
|
134
|
+
await prisma.tag.delete({
|
|
135
|
+
where: { id: dbTag.id },
|
|
136
|
+
})
|
|
137
|
+
result.tagsDeleted++
|
|
138
|
+
result.deletedTags.push(dbTag.name)
|
|
139
|
+
console.log(` šļø Deleted tag '${dbTag.name}' (not in feature files)`)
|
|
140
|
+
} catch (error) {
|
|
141
|
+
const errorMsg = `Error deleting tag '${dbTag.name}': ${error}`
|
|
142
|
+
result.errors.push(errorMsg)
|
|
143
|
+
console.error(` ā ${errorMsg}`)
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
// Create or check tags from FS
|
|
149
|
+
console.log('\nā
Syncing tags from feature files to database...')
|
|
150
|
+
for (const tagData of tagObjects) {
|
|
151
|
+
try {
|
|
152
|
+
// Check if tag already exists by name (names are unique per user requirement)
|
|
153
|
+
const existing = await prisma.tag.findFirst({
|
|
154
|
+
where: { name: tagData.name },
|
|
155
|
+
})
|
|
156
|
+
|
|
157
|
+
if (existing) {
|
|
158
|
+
// If tag exists but has wrong type, update it
|
|
159
|
+
// This fixes tags that were created with wrong type (e.g., via UI or old code)
|
|
160
|
+
if (existing.type !== tagData.type) {
|
|
161
|
+
await prisma.tag.update({
|
|
162
|
+
where: { id: existing.id },
|
|
163
|
+
data: { type: tagData.type },
|
|
164
|
+
})
|
|
165
|
+
result.tagsCreated++ // Count as created since we're fixing it
|
|
166
|
+
result.createdTags.push(tagData.name)
|
|
167
|
+
console.log(` š Updated tag '${tagData.name}' type from ${existing.type} to ${tagData.type}`)
|
|
168
|
+
} else {
|
|
169
|
+
result.tagsExisting++
|
|
170
|
+
console.log(` ā Tag '${tagData.name}' already exists`)
|
|
171
|
+
}
|
|
172
|
+
} else {
|
|
173
|
+
// Create the tag
|
|
174
|
+
await prisma.tag.create({
|
|
175
|
+
data: {
|
|
176
|
+
name: tagData.name,
|
|
177
|
+
tagExpression: tagData.tagExpression,
|
|
178
|
+
type: tagData.type,
|
|
179
|
+
},
|
|
180
|
+
})
|
|
181
|
+
result.tagsCreated++
|
|
182
|
+
result.createdTags.push(tagData.name)
|
|
183
|
+
console.log(` ā Created tag '${tagData.name}' (type: ${tagData.type})`)
|
|
184
|
+
}
|
|
185
|
+
} catch (error) {
|
|
186
|
+
const errorMsg = `Error syncing tag '${tagData.name}': ${error}`
|
|
187
|
+
result.errors.push(errorMsg)
|
|
188
|
+
console.error(` ā ${errorMsg}`)
|
|
189
|
+
}
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
return result
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
/**
|
|
196
|
+
* Generates and displays sync summary
|
|
197
|
+
*/
|
|
198
|
+
function generateSummary(result: SyncResult): void {
|
|
199
|
+
console.log('\nš Sync Summary:')
|
|
200
|
+
console.log(` š Tags scanned: ${result.tagsScanned}`)
|
|
201
|
+
console.log(` ā
Tags existing: ${result.tagsExisting}`)
|
|
202
|
+
console.log(` ā Tags created: ${result.tagsCreated}`)
|
|
203
|
+
console.log(` šļø Tags deleted: ${result.tagsDeleted}`)
|
|
204
|
+
console.log(` ā Errors: ${result.errors.length}`)
|
|
205
|
+
|
|
206
|
+
if (result.createdTags.length > 0) {
|
|
207
|
+
console.log('\n Created tags:')
|
|
208
|
+
result.createdTags.forEach((name, index) => {
|
|
209
|
+
console.log(` ${index + 1}. ${name}`)
|
|
210
|
+
})
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
if (result.deletedTags.length > 0) {
|
|
214
|
+
console.log('\n Deleted tags:')
|
|
215
|
+
result.deletedTags.forEach((name, index) => {
|
|
216
|
+
console.log(` ${index + 1}. ${name}`)
|
|
217
|
+
})
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
if (result.errors.length > 0) {
|
|
221
|
+
console.log('\n Errors:')
|
|
222
|
+
result.errors.forEach((error, index) => {
|
|
223
|
+
console.log(` ${index + 1}. ${error}`)
|
|
224
|
+
})
|
|
225
|
+
}
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
/**
|
|
229
|
+
* Main function
|
|
230
|
+
*/
|
|
231
|
+
async function main() {
|
|
232
|
+
try {
|
|
233
|
+
console.log('š Starting tags sync...')
|
|
234
|
+
console.log('This will scan feature files and sync tags to database.')
|
|
235
|
+
console.log('Filesystem is the source of truth - tags in DB but not in FS will be deleted.\n')
|
|
236
|
+
|
|
237
|
+
const baseDir = process.cwd()
|
|
238
|
+
const featuresDir = join(baseDir, 'src', 'tests', 'features')
|
|
239
|
+
|
|
240
|
+
// Scan feature files
|
|
241
|
+
console.log('š Scanning feature files in src/tests/features...')
|
|
242
|
+
const parsedFeatures = await scanFeatureFiles(featuresDir)
|
|
243
|
+
console.log(` Found ${parsedFeatures.length} feature file(s)`)
|
|
244
|
+
|
|
245
|
+
if (parsedFeatures.length === 0) {
|
|
246
|
+
console.log('\nā ļø No feature files found. Nothing to sync.')
|
|
247
|
+
return
|
|
248
|
+
}
|
|
249
|
+
|
|
250
|
+
// Extract unique tags
|
|
251
|
+
console.log('\nš Extracting unique tags from feature files...')
|
|
252
|
+
const uniqueTagExpressions = extractUniqueTags(parsedFeatures)
|
|
253
|
+
console.log(` Found ${uniqueTagExpressions.size} unique tag(s)`)
|
|
254
|
+
|
|
255
|
+
if (uniqueTagExpressions.size === 0) {
|
|
256
|
+
console.log('\nā ļø No tags found in feature files. Nothing to sync.')
|
|
257
|
+
return
|
|
258
|
+
}
|
|
259
|
+
|
|
260
|
+
// Build tag objects
|
|
261
|
+
console.log('\nšØ Building tag objects...')
|
|
262
|
+
const tagObjects = buildTagObjects(uniqueTagExpressions)
|
|
263
|
+
console.log(` Built ${tagObjects.length} tag object(s)`)
|
|
264
|
+
|
|
265
|
+
// Log tag details
|
|
266
|
+
console.log('\n Tag details:')
|
|
267
|
+
for (const tag of tagObjects) {
|
|
268
|
+
console.log(` - ${tag.tagExpression} ā name: '${tag.name}', type: ${tag.type}`)
|
|
269
|
+
}
|
|
270
|
+
|
|
271
|
+
// Sync to database
|
|
272
|
+
const result = await syncTagsToDatabase(tagObjects)
|
|
273
|
+
|
|
274
|
+
// Generate summary
|
|
275
|
+
generateSummary(result)
|
|
276
|
+
|
|
277
|
+
if (result.errors.length === 0) {
|
|
278
|
+
console.log('\nā
Sync completed successfully!')
|
|
279
|
+
} else {
|
|
280
|
+
console.log('\nā ļø Sync completed with errors. Please review the errors above.')
|
|
281
|
+
process.exit(1)
|
|
282
|
+
}
|
|
283
|
+
} catch (error) {
|
|
284
|
+
console.error('\nā Error during sync:', error)
|
|
285
|
+
process.exit(1)
|
|
286
|
+
} finally {
|
|
287
|
+
await prisma.$disconnect()
|
|
288
|
+
}
|
|
289
|
+
}
|
|
290
|
+
|
|
291
|
+
main()
|
|
292
|
+
|