@pattern-stack/frontend-patterns 0.1.0 → 0.1.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/dist/atoms/composed/Accordion/Accordion.d.ts.map +1 -0
- package/dist/atoms/composed/Accordion/index.d.ts.map +1 -0
- package/dist/atoms/composed/Alert/Alert.d.ts.map +1 -0
- package/dist/atoms/composed/Alert/index.d.ts.map +1 -0
- package/dist/atoms/composed/Breadcrumb/Breadcrumb.d.ts.map +1 -0
- package/dist/atoms/composed/Breadcrumb/index.d.ts.map +1 -0
- package/dist/atoms/{components/data → composed}/Chart/Chart.d.ts +2 -2
- package/dist/atoms/composed/Chart/Chart.d.ts.map +1 -0
- package/dist/atoms/composed/Chart/index.d.ts.map +1 -0
- package/dist/atoms/composed/ColorSwatch/ColorSwatch.d.ts.map +1 -0
- package/dist/atoms/composed/ColorSwatch/index.d.ts.map +1 -0
- package/dist/atoms/composed/DarkModeToggle.d.ts.map +1 -0
- package/dist/atoms/composed/DataBadge/DataBadge.d.ts +13 -0
- package/dist/atoms/composed/DataBadge/DataBadge.d.ts.map +1 -0
- package/dist/atoms/composed/DataBadge/index.d.ts.map +1 -0
- package/dist/atoms/composed/DataTable/DataTable.d.ts +28 -0
- package/dist/atoms/composed/DataTable/DataTable.d.ts.map +1 -0
- package/dist/atoms/composed/DataTable/TableCellWithTooltip.d.ts.map +1 -0
- package/dist/atoms/composed/DataTable/index.d.ts.map +1 -0
- package/dist/atoms/composed/DateTimePicker/DateTimePicker.d.ts.map +1 -0
- package/dist/atoms/composed/DateTimePicker/index.d.ts.map +1 -0
- package/dist/atoms/composed/DetailedCard/DetailedCard.d.ts.map +1 -0
- package/dist/atoms/composed/DetailedCard/index.d.ts.map +1 -0
- package/dist/atoms/composed/EmptyState/EmptyState.d.ts.map +1 -0
- package/dist/atoms/composed/EmptyState/index.d.ts.map +1 -0
- package/dist/atoms/composed/FileUpload/FileUpload.d.ts.map +1 -0
- package/dist/atoms/composed/FileUpload/index.d.ts.map +1 -0
- package/dist/atoms/composed/FormField/FormField.d.ts.map +1 -0
- package/dist/atoms/composed/FormField/index.d.ts.map +1 -0
- package/dist/atoms/composed/GlobalSearch/GlobalSearch.d.ts.map +1 -0
- package/dist/atoms/composed/GlobalSearch/index.d.ts.map +1 -0
- package/dist/atoms/{components/data → composed}/IconBadge/IconBadge.d.ts +1 -2
- package/dist/atoms/composed/IconBadge/IconBadge.d.ts.map +1 -0
- package/dist/atoms/composed/IconBadge/index.d.ts.map +1 -0
- package/dist/atoms/composed/Modal/Modal.d.ts.map +1 -0
- package/dist/atoms/composed/Modal/index.d.ts.map +1 -0
- package/dist/atoms/composed/PaletteSwitcher.d.ts.map +1 -0
- package/dist/atoms/composed/ProgressBar/ProgressBar.d.ts.map +1 -0
- package/dist/atoms/composed/ProgressBar/index.d.ts.map +1 -0
- package/dist/atoms/{components/data → composed}/StatCard/StatCard.d.ts +1 -1
- package/dist/atoms/composed/StatCard/StatCard.d.ts.map +1 -0
- package/dist/atoms/composed/StatCard/index.d.ts.map +1 -0
- package/dist/atoms/composed/StyleGuide.d.ts.map +1 -0
- package/dist/atoms/composed/Toast/Toast.d.ts.map +1 -0
- package/dist/atoms/composed/Toast/index.d.ts.map +1 -0
- package/dist/atoms/composed/Tooltip/Tooltip.d.ts.map +1 -0
- package/dist/atoms/composed/Tooltip/index.d.ts +2 -0
- package/dist/atoms/composed/Tooltip/index.d.ts.map +1 -0
- package/dist/atoms/composed/UserAvatar/UserAvatar.d.ts.map +1 -0
- package/dist/atoms/composed/UserAvatar/index.d.ts.map +1 -0
- package/dist/atoms/composed/UserMenu/UserMenu.d.ts.map +1 -0
- package/dist/atoms/composed/UserMenu/index.d.ts.map +1 -0
- package/dist/atoms/composed/index.d.ts +25 -0
- package/dist/atoms/composed/index.d.ts.map +1 -0
- package/dist/atoms/index.d.ts +5 -4
- package/dist/atoms/index.d.ts.map +1 -1
- package/dist/atoms/shared/index.d.ts +0 -1
- package/dist/atoms/shared/index.d.ts.map +1 -1
- package/dist/atoms/types/index.d.ts +0 -3
- package/dist/atoms/types/index.d.ts.map +1 -1
- package/dist/atoms/ui/Badge.d.ts.map +1 -0
- package/dist/atoms/ui/ErrorBoundary.d.ts.map +1 -0
- package/dist/atoms/ui/Select.d.ts.map +1 -0
- package/dist/atoms/ui/Switch.d.ts.map +1 -0
- package/dist/atoms/ui/Tabs.d.ts.map +1 -0
- package/dist/atoms/ui/avatar.d.ts.map +1 -0
- package/dist/atoms/{primitives → ui}/button.d.ts +3 -3
- package/dist/atoms/ui/button.d.ts.map +1 -0
- package/dist/atoms/ui/card.d.ts.map +1 -0
- package/dist/atoms/ui/dropdown-menu.d.ts.map +1 -0
- package/dist/atoms/{primitives → ui}/index.d.ts +0 -2
- package/dist/atoms/ui/index.d.ts.map +1 -0
- package/dist/atoms/ui/input.d.ts.map +1 -0
- package/dist/atoms/ui/label.d.ts.map +1 -0
- package/dist/atoms/ui/skeleton.d.ts.map +1 -0
- package/dist/atoms/ui/spinner.d.ts.map +1 -0
- package/dist/atoms/ui/table.d.ts.map +1 -0
- package/dist/atoms/utils/utils.d.ts +0 -5
- package/dist/atoms/utils/utils.d.ts.map +1 -1
- package/dist/features/auth/components/LoginForm.d.ts.map +1 -1
- package/dist/features/auth/hooks/index.d.ts +0 -1
- package/dist/features/auth/hooks/index.d.ts.map +1 -1
- package/dist/features/auth/index.d.ts +0 -1
- package/dist/features/auth/index.d.ts.map +1 -1
- package/dist/frontend-patterns.css +1 -4417
- package/dist/index.d.ts +0 -8
- package/dist/index.d.ts.map +1 -1
- package/dist/index.es.js +8507 -27524
- package/dist/index.es.js.map +1 -1
- package/dist/index.js +8466 -27505
- package/dist/index.js.map +1 -1
- package/dist/molecules/forms/SearchInput.d.ts.map +1 -1
- package/dist/molecules/layout/AppHeader/AppHeader.d.ts.map +1 -1
- package/dist/molecules/layout/Sidebar.d.ts.map +1 -1
- package/dist/molecules/layout/SidebarButton/SidebarButton.d.ts +0 -2
- package/dist/molecules/layout/SidebarButton/SidebarButton.d.ts.map +1 -1
- package/dist/molecules/layout/index.d.ts +0 -4
- package/dist/molecules/layout/index.d.ts.map +1 -1
- package/dist/organisms/showcase/ComponentShowcasePage.d.ts.map +1 -1
- package/dist/templates/DataTemplate.d.ts +1 -1
- package/dist/templates/DataTemplate.d.ts.map +1 -1
- package/dist/templates/admin/AdminCRUDTemplate.d.ts.map +1 -1
- package/dist/templates/admin/AdminDashboardTemplate.d.ts +9 -6
- package/dist/templates/admin/AdminDashboardTemplate.d.ts.map +1 -1
- package/dist/templates/admin/AdminDetailTemplate.d.ts +1 -1
- package/dist/templates/admin/AdminDetailTemplate.d.ts.map +1 -1
- package/dist/templates/factory.d.ts +1 -2
- package/dist/templates/factory.d.ts.map +1 -1
- package/dist/templates/index.d.ts +0 -2
- package/dist/templates/index.d.ts.map +1 -1
- package/package.json +10 -35
- package/src/App.css +42 -0
- package/src/App.tsx +54 -0
- package/src/__tests__/README.md +221 -0
- package/src/__tests__/atoms/hooks/simple-hooks.test.ts +44 -0
- package/src/__tests__/atoms/ui/button.test.tsx +68 -0
- package/src/__tests__/atoms/utils/simple.test.ts +18 -0
- package/src/__tests__/atoms/utils/utils.test.ts +77 -0
- package/src/__tests__/features/auth/simple-auth.test.tsx +40 -0
- package/src/__tests__/molecules/layout/simple-layout.test.tsx +81 -0
- package/src/__tests__/organisms/showcase/simple-showcase.test.tsx +167 -0
- package/src/__tests__/setup.ts +51 -0
- package/src/__tests__/utils.tsx +123 -0
- package/src/atoms/composed/Accordion/Accordion.tsx +271 -0
- package/src/atoms/composed/Accordion/index.ts +1 -0
- package/src/atoms/composed/Alert/Alert.tsx +132 -0
- package/src/atoms/composed/Alert/index.ts +1 -0
- package/src/atoms/composed/Breadcrumb/Breadcrumb.tsx +83 -0
- package/src/atoms/composed/Breadcrumb/index.ts +1 -0
- package/src/atoms/composed/Chart/Chart.tsx +425 -0
- package/src/atoms/composed/Chart/index.ts +2 -0
- package/src/atoms/composed/ColorSwatch/ColorSwatch.tsx +72 -0
- package/src/atoms/composed/ColorSwatch/index.ts +1 -0
- package/src/atoms/composed/DarkModeToggle.tsx +66 -0
- package/src/atoms/composed/DataBadge/DataBadge.tsx +81 -0
- package/src/atoms/composed/DataBadge/index.ts +1 -0
- package/src/atoms/composed/DataTable/DataTable.tsx +394 -0
- package/src/atoms/composed/DataTable/TableCellWithTooltip.tsx +41 -0
- package/src/atoms/composed/DataTable/index.ts +2 -0
- package/src/atoms/composed/DateTimePicker/DateTimePicker.tsx +611 -0
- package/src/atoms/composed/DateTimePicker/index.ts +2 -0
- package/src/atoms/composed/DetailedCard/DetailedCard.tsx +181 -0
- package/src/atoms/composed/DetailedCard/index.ts +2 -0
- package/src/atoms/composed/EmptyState/EmptyState.tsx +90 -0
- package/src/atoms/composed/EmptyState/index.ts +1 -0
- package/src/atoms/composed/FileUpload/FileUpload.tsx +477 -0
- package/src/atoms/composed/FileUpload/index.ts +2 -0
- package/src/atoms/composed/FormField/FormField.tsx +92 -0
- package/src/atoms/composed/FormField/index.ts +1 -0
- package/src/atoms/composed/GlobalSearch/GlobalSearch.tsx +37 -0
- package/src/atoms/composed/GlobalSearch/index.ts +1 -0
- package/src/atoms/composed/IconBadge/IconBadge.tsx +95 -0
- package/src/atoms/composed/IconBadge/index.ts +2 -0
- package/src/atoms/composed/Modal/Modal.tsx +223 -0
- package/src/atoms/composed/Modal/index.ts +2 -0
- package/src/atoms/composed/PaletteSwitcher.tsx +386 -0
- package/src/atoms/composed/ProgressBar/ProgressBar.tsx +116 -0
- package/src/atoms/composed/ProgressBar/index.ts +1 -0
- package/src/atoms/composed/StatCard/StatCard.tsx +219 -0
- package/src/atoms/composed/StatCard/index.ts +1 -0
- package/src/atoms/composed/StyleGuide.tsx +717 -0
- package/src/atoms/composed/Toast/Toast.tsx +219 -0
- package/src/atoms/composed/Toast/index.ts +1 -0
- package/src/atoms/composed/Tooltip/Tooltip.tsx +213 -0
- package/src/atoms/composed/Tooltip/index.ts +1 -0
- package/src/atoms/composed/UserAvatar/UserAvatar.tsx +139 -0
- package/src/atoms/composed/UserAvatar/index.ts +1 -0
- package/src/atoms/composed/UserMenu/UserMenu.tsx +16 -0
- package/src/atoms/composed/UserMenu/index.ts +1 -0
- package/src/atoms/composed/index.ts +29 -0
- package/src/atoms/hooks/useApi.ts +80 -0
- package/src/atoms/hooks/useHealth.ts +17 -0
- package/src/atoms/index.ts +13 -0
- package/src/atoms/services/api/client.ts +134 -0
- package/src/atoms/services/auth-service.ts +248 -0
- package/src/atoms/services/health.ts +15 -0
- package/src/atoms/services/index.ts +3 -0
- package/src/atoms/shared/config/constants.ts +17 -0
- package/src/atoms/shared/config/dashboard-sizes.ts +111 -0
- package/src/atoms/shared/config/environment.ts +10 -0
- package/src/atoms/shared/index.ts +4 -0
- package/src/atoms/shared/styles/color-palettes.css +566 -0
- package/src/atoms/types/auth.ts +62 -0
- package/src/atoms/types/generated.ts +1469 -0
- package/src/atoms/types/index.ts +4 -0
- package/src/atoms/types/loading.ts +28 -0
- package/src/atoms/ui/Badge.tsx +30 -0
- package/src/atoms/ui/ErrorBoundary.tsx +59 -0
- package/src/atoms/ui/Select.tsx +53 -0
- package/src/atoms/ui/Switch.tsx +42 -0
- package/src/atoms/ui/Tabs.tsx +118 -0
- package/src/atoms/ui/avatar.tsx +48 -0
- package/src/atoms/ui/button.tsx +70 -0
- package/src/atoms/ui/card.tsx +76 -0
- package/src/atoms/ui/dropdown-menu.tsx +199 -0
- package/src/atoms/ui/index.ts +39 -0
- package/src/atoms/ui/input.tsx +23 -0
- package/src/atoms/ui/label.tsx +23 -0
- package/src/atoms/ui/skeleton.tsx +13 -0
- package/src/atoms/ui/spinner.tsx +49 -0
- package/src/atoms/ui/table.tsx +116 -0
- package/src/atoms/utils/animations.ts +135 -0
- package/src/atoms/utils/tooltip-helpers.ts +140 -0
- package/src/atoms/utils/utils.ts +9 -0
- package/src/features/auth/components/LoginForm.tsx +168 -0
- package/src/features/auth/components/LogoutButton.tsx +19 -0
- package/src/features/auth/components/ProtectedRoute.tsx +60 -0
- package/src/features/auth/components/index.ts +4 -0
- package/src/features/auth/hooks/index.ts +2 -0
- package/src/features/auth/hooks/useAuth.tsx +205 -0
- package/src/features/auth/hooks/usePermissions.ts +35 -0
- package/src/features/auth/index.ts +2 -0
- package/src/features/index.ts +2 -0
- package/src/index.css +704 -0
- package/src/index.ts +13 -0
- package/src/main.tsx +48 -0
- package/src/molecules/.gitkeep +0 -0
- package/src/molecules/forms/FormGroup.tsx +75 -0
- package/src/molecules/forms/SearchInput.tsx +259 -0
- package/src/molecules/forms/index.ts +4 -0
- package/src/molecules/index.ts +4 -0
- package/src/molecules/layout/AppHeader/AppHeader.tsx +42 -0
- package/src/molecules/layout/AppHeader/index.ts +1 -0
- package/src/molecules/layout/AppLayout.tsx +29 -0
- package/src/molecules/layout/PageTemplate.tsx +87 -0
- package/src/molecules/layout/SectionHeader/SectionHeader.tsx +87 -0
- package/src/molecules/layout/SectionHeader/index.ts +1 -0
- package/src/molecules/layout/ShowcaseSection.tsx +57 -0
- package/src/molecules/layout/Sidebar.tsx +144 -0
- package/src/molecules/layout/SidebarButton/SidebarButton.tsx +99 -0
- package/src/molecules/layout/SidebarButton/index.ts +1 -0
- package/src/molecules/layout/SidebarContext.tsx +31 -0
- package/src/molecules/layout/index.ts +7 -0
- package/src/molecules/navigation/NavMenu.tsx +188 -0
- package/src/molecules/navigation/Pagination.tsx +172 -0
- package/src/molecules/navigation/index.ts +4 -0
- package/src/organisms/index.ts +5 -0
- package/src/organisms/showcase/ComponentShowcasePage.tsx +2496 -0
- package/src/organisms/showcase/index.ts +1 -0
- package/src/pages/AdminShowcase/AdminCRUDShowcase.tsx +242 -0
- package/src/pages/AdminShowcase/AdminDashboardShowcase.tsx +171 -0
- package/src/pages/AdminShowcase/AdminDetailShowcase.tsx +385 -0
- package/src/pages/AdminShowcase/index.tsx +3 -0
- package/src/pages/ComponentShowcase/BadgesShowcase.tsx +188 -0
- package/src/pages/ComponentShowcase/CardsShowcase.tsx +392 -0
- package/src/pages/ComponentShowcase/PalettesShowcase.tsx +207 -0
- package/src/pages/ComponentShowcase/StatesShowcase.tsx +485 -0
- package/src/pages/ComponentShowcase/TablesShowcase.tsx +134 -0
- package/src/pages/ComponentShowcase/TypographyShowcase.tsx +255 -0
- package/src/pages/ComponentShowcase/index.tsx +188 -0
- package/src/pages/index.ts +2 -0
- package/src/templates/AuthTemplate.tsx +216 -0
- package/src/templates/ComponentShowcaseTemplate.tsx +173 -0
- package/src/templates/DashboardTemplate.tsx +232 -0
- package/src/templates/DataTemplate.tsx +319 -0
- package/src/templates/admin/AdminCRUDTemplate.tsx +630 -0
- package/src/templates/admin/AdminDashboardTemplate.tsx +351 -0
- package/src/templates/admin/AdminDetailTemplate.tsx +563 -0
- package/src/templates/admin/index.ts +29 -0
- package/src/templates/factory.tsx +169 -0
- package/src/templates/index.ts +37 -0
- package/src/vite-env.d.ts +1 -0
- package/CHANGELOG.md +0 -63
- package/LICENSE +0 -19
- package/cli/cli/commands/generate-hooks.js +0 -291
- package/cli/cli/commands/init.js +0 -25
- package/cli/cli/commands/scaffold.js +0 -201
- package/cli/cli/index.js +0 -113
- package/cli/commands/generate-hooks.js +0 -288
- package/cli/commands/generate-hooks.ts +0 -316
- package/cli/commands/init.js +0 -22
- package/cli/commands/init.ts +0 -33
- package/cli/commands/scaffold.js +0 -198
- package/cli/commands/scaffold.ts +0 -224
- package/cli/index.js +0 -3210
- package/cli/index.ts +0 -122
- package/cli/src/codegen/openapi/bulk-hook-generator.js +0 -252
- package/cli/src/codegen/openapi/bulk-types.js +0 -89
- package/cli/src/codegen/openapi/client-generator.js +0 -672
- package/cli/src/codegen/openapi/confidence-scorer.js +0 -204
- package/cli/src/codegen/openapi/hook-config.js +0 -66
- package/cli/src/codegen/openapi/hook-generator.js +0 -1057
- package/cli/src/codegen/openapi/parser.js +0 -279
- package/cli/src/codegen/openapi/type-generator.js +0 -339
- package/dist/atoms/components/core/Avatar/Avatar.d.ts +0 -41
- package/dist/atoms/components/core/Avatar/Avatar.d.ts.map +0 -1
- package/dist/atoms/components/core/Avatar/index.d.ts +0 -2
- package/dist/atoms/components/core/Avatar/index.d.ts.map +0 -1
- package/dist/atoms/components/core/Badge/Badge.d.ts +0 -38
- package/dist/atoms/components/core/Badge/Badge.d.ts.map +0 -1
- package/dist/atoms/components/core/Badge/index.d.ts +0 -2
- package/dist/atoms/components/core/Badge/index.d.ts.map +0 -1
- package/dist/atoms/components/core/Button/Button.d.ts +0 -28
- package/dist/atoms/components/core/Button/Button.d.ts.map +0 -1
- package/dist/atoms/components/core/Button/index.d.ts +0 -3
- package/dist/atoms/components/core/Button/index.d.ts.map +0 -1
- package/dist/atoms/components/core/Card/Card.d.ts +0 -41
- package/dist/atoms/components/core/Card/Card.d.ts.map +0 -1
- package/dist/atoms/components/core/Card/index.d.ts +0 -3
- package/dist/atoms/components/core/Card/index.d.ts.map +0 -1
- package/dist/atoms/components/core/Checkbox/Checkbox.d.ts +0 -28
- package/dist/atoms/components/core/Checkbox/Checkbox.d.ts.map +0 -1
- package/dist/atoms/components/core/Checkbox/index.d.ts +0 -3
- package/dist/atoms/components/core/Checkbox/index.d.ts.map +0 -1
- package/dist/atoms/components/core/Input/Input.d.ts +0 -37
- package/dist/atoms/components/core/Input/Input.d.ts.map +0 -1
- package/dist/atoms/components/core/Input/index.d.ts +0 -3
- package/dist/atoms/components/core/Input/index.d.ts.map +0 -1
- package/dist/atoms/components/core/Label/Label.d.ts +0 -23
- package/dist/atoms/components/core/Label/Label.d.ts.map +0 -1
- package/dist/atoms/components/core/Label/index.d.ts +0 -3
- package/dist/atoms/components/core/Label/index.d.ts.map +0 -1
- package/dist/atoms/components/core/Select/Select.d.ts +0 -42
- package/dist/atoms/components/core/Select/Select.d.ts.map +0 -1
- package/dist/atoms/components/core/Select/index.d.ts +0 -3
- package/dist/atoms/components/core/Select/index.d.ts.map +0 -1
- package/dist/atoms/components/core/Spinner/Spinner.d.ts +0 -25
- package/dist/atoms/components/core/Spinner/Spinner.d.ts.map +0 -1
- package/dist/atoms/components/core/Spinner/index.d.ts +0 -3
- package/dist/atoms/components/core/Spinner/index.d.ts.map +0 -1
- package/dist/atoms/components/core/Switch/Switch.d.ts +0 -35
- package/dist/atoms/components/core/Switch/Switch.d.ts.map +0 -1
- package/dist/atoms/components/core/Switch/index.d.ts +0 -2
- package/dist/atoms/components/core/Switch/index.d.ts.map +0 -1
- package/dist/atoms/components/core/index.d.ts +0 -11
- package/dist/atoms/components/core/index.d.ts.map +0 -1
- package/dist/atoms/components/data/ActivityFeed/ActivityFeed.d.ts +0 -4
- package/dist/atoms/components/data/ActivityFeed/ActivityFeed.d.ts.map +0 -1
- package/dist/atoms/components/data/ActivityFeed/ActivityFeed.stories.d.ts +0 -38
- package/dist/atoms/components/data/ActivityFeed/ActivityFeed.stories.d.ts.map +0 -1
- package/dist/atoms/components/data/ActivityFeed/ActivityFeedItem.d.ts +0 -9
- package/dist/atoms/components/data/ActivityFeed/ActivityFeedItem.d.ts.map +0 -1
- package/dist/atoms/components/data/ActivityFeed/index.d.ts +0 -4
- package/dist/atoms/components/data/ActivityFeed/index.d.ts.map +0 -1
- package/dist/atoms/components/data/ActivityFeed/types.d.ts +0 -26
- package/dist/atoms/components/data/ActivityFeed/types.d.ts.map +0 -1
- package/dist/atoms/components/data/ActivityFeed/utils.d.ts +0 -5
- package/dist/atoms/components/data/ActivityFeed/utils.d.ts.map +0 -1
- package/dist/atoms/components/data/Chart/Chart.d.ts.map +0 -1
- package/dist/atoms/components/data/Chart/index.d.ts.map +0 -1
- package/dist/atoms/components/data/DataBadge/DataBadge.d.ts +0 -18
- package/dist/atoms/components/data/DataBadge/DataBadge.d.ts.map +0 -1
- package/dist/atoms/components/data/DataBadge/index.d.ts.map +0 -1
- package/dist/atoms/components/data/DataTable/DataTable.d.ts +0 -5
- package/dist/atoms/components/data/DataTable/DataTable.d.ts.map +0 -1
- package/dist/atoms/components/data/DataTable/DataTable.types.d.ts +0 -51
- package/dist/atoms/components/data/DataTable/DataTable.types.d.ts.map +0 -1
- package/dist/atoms/components/data/DataTable/TableCellWithTooltip.d.ts.map +0 -1
- package/dist/atoms/components/data/DataTable/index.d.ts.map +0 -1
- package/dist/atoms/components/data/DetailedCard/DetailedCard.d.ts.map +0 -1
- package/dist/atoms/components/data/DetailedCard/index.d.ts.map +0 -1
- package/dist/atoms/components/data/EntityIcon/EntityIcon.d.ts +0 -24
- package/dist/atoms/components/data/EntityIcon/EntityIcon.d.ts.map +0 -1
- package/dist/atoms/components/data/EntityIcon/index.d.ts +0 -2
- package/dist/atoms/components/data/EntityIcon/index.d.ts.map +0 -1
- package/dist/atoms/components/data/IconBadge/IconBadge.d.ts.map +0 -1
- package/dist/atoms/components/data/IconBadge/index.d.ts.map +0 -1
- package/dist/atoms/components/data/ListCard/ListCard.d.ts +0 -32
- package/dist/atoms/components/data/ListCard/ListCard.d.ts.map +0 -1
- package/dist/atoms/components/data/ListCard/index.d.ts +0 -2
- package/dist/atoms/components/data/ListCard/index.d.ts.map +0 -1
- package/dist/atoms/components/data/ProgressBar/ProgressBar.d.ts.map +0 -1
- package/dist/atoms/components/data/ProgressBar/index.d.ts.map +0 -1
- package/dist/atoms/components/data/StatCard/StatCard.d.ts.map +0 -1
- package/dist/atoms/components/data/StatCard/index.d.ts.map +0 -1
- package/dist/atoms/components/data/Table/Table.d.ts +0 -41
- package/dist/atoms/components/data/Table/Table.d.ts.map +0 -1
- package/dist/atoms/components/data/Table/index.d.ts +0 -2
- package/dist/atoms/components/data/Table/index.d.ts.map +0 -1
- package/dist/atoms/components/data/TruncatedText/TruncatedText.d.ts +0 -26
- package/dist/atoms/components/data/TruncatedText/TruncatedText.d.ts.map +0 -1
- package/dist/atoms/components/data/TruncatedText/index.d.ts +0 -2
- package/dist/atoms/components/data/TruncatedText/index.d.ts.map +0 -1
- package/dist/atoms/components/data/index.d.ts +0 -13
- package/dist/atoms/components/data/index.d.ts.map +0 -1
- package/dist/atoms/components/domain/SalesPanel/SalesPanel.d.ts +0 -19
- package/dist/atoms/components/domain/SalesPanel/SalesPanel.d.ts.map +0 -1
- package/dist/atoms/components/domain/SalesPanel/index.d.ts +0 -2
- package/dist/atoms/components/domain/SalesPanel/index.d.ts.map +0 -1
- package/dist/atoms/components/domain/SalesPanel/mockSalesData.d.ts +0 -63
- package/dist/atoms/components/domain/SalesPanel/mockSalesData.d.ts.map +0 -1
- package/dist/atoms/components/domain/index.d.ts +0 -2
- package/dist/atoms/components/domain/index.d.ts.map +0 -1
- package/dist/atoms/components/feedback/Alert/Alert.d.ts.map +0 -1
- package/dist/atoms/components/feedback/Alert/index.d.ts.map +0 -1
- package/dist/atoms/components/feedback/EmptyState/EmptyState.d.ts.map +0 -1
- package/dist/atoms/components/feedback/EmptyState/index.d.ts.map +0 -1
- package/dist/atoms/components/feedback/ErrorBoundary/ErrorBoundary.d.ts +0 -61
- package/dist/atoms/components/feedback/ErrorBoundary/ErrorBoundary.d.ts.map +0 -1
- package/dist/atoms/components/feedback/ErrorBoundary/index.d.ts +0 -2
- package/dist/atoms/components/feedback/ErrorBoundary/index.d.ts.map +0 -1
- package/dist/atoms/components/feedback/Skeleton/Skeleton.d.ts +0 -41
- package/dist/atoms/components/feedback/Skeleton/Skeleton.d.ts.map +0 -1
- package/dist/atoms/components/feedback/Skeleton/index.d.ts +0 -2
- package/dist/atoms/components/feedback/Skeleton/index.d.ts.map +0 -1
- package/dist/atoms/components/feedback/Toast/Toast.d.ts.map +0 -1
- package/dist/atoms/components/feedback/Toast/index.d.ts.map +0 -1
- package/dist/atoms/components/feedback/index.d.ts +0 -6
- package/dist/atoms/components/feedback/index.d.ts.map +0 -1
- package/dist/atoms/components/forms/DateTimePicker/DateTimePicker.d.ts.map +0 -1
- package/dist/atoms/components/forms/DateTimePicker/index.d.ts.map +0 -1
- package/dist/atoms/components/forms/FileUpload/FileUpload.d.ts.map +0 -1
- package/dist/atoms/components/forms/FileUpload/index.d.ts.map +0 -1
- package/dist/atoms/components/forms/FormField/FormField.d.ts.map +0 -1
- package/dist/atoms/components/forms/FormField/index.d.ts.map +0 -1
- package/dist/atoms/components/forms/index.d.ts +0 -4
- package/dist/atoms/components/forms/index.d.ts.map +0 -1
- package/dist/atoms/components/index.d.ts +0 -10
- package/dist/atoms/components/index.d.ts.map +0 -1
- package/dist/atoms/components/layout/Accordion/Accordion.d.ts.map +0 -1
- package/dist/atoms/components/layout/Accordion/index.d.ts.map +0 -1
- package/dist/atoms/components/layout/Breadcrumb/Breadcrumb.d.ts.map +0 -1
- package/dist/atoms/components/layout/Breadcrumb/index.d.ts.map +0 -1
- package/dist/atoms/components/layout/Dialog/index.d.ts +0 -3
- package/dist/atoms/components/layout/Dialog/index.d.ts.map +0 -1
- package/dist/atoms/components/layout/Dropdown/Dropdown.d.ts +0 -40
- package/dist/atoms/components/layout/Dropdown/Dropdown.d.ts.map +0 -1
- package/dist/atoms/components/layout/Dropdown/index.d.ts +0 -3
- package/dist/atoms/components/layout/Dropdown/index.d.ts.map +0 -1
- package/dist/atoms/components/layout/Modal/Modal.d.ts.map +0 -1
- package/dist/atoms/components/layout/Modal/index.d.ts.map +0 -1
- package/dist/atoms/components/layout/Tabs/index.d.ts +0 -2
- package/dist/atoms/components/layout/Tabs/index.d.ts.map +0 -1
- package/dist/atoms/components/layout/Tooltip/Tooltip.d.ts.map +0 -1
- package/dist/atoms/components/layout/Tooltip/index.d.ts +0 -2
- package/dist/atoms/components/layout/Tooltip/index.d.ts.map +0 -1
- package/dist/atoms/components/layout/index.d.ts +0 -8
- package/dist/atoms/components/layout/index.d.ts.map +0 -1
- package/dist/atoms/components/navigation/GlobalSearch/GlobalSearch.d.ts.map +0 -1
- package/dist/atoms/components/navigation/GlobalSearch/index.d.ts.map +0 -1
- package/dist/atoms/components/navigation/index.d.ts +0 -2
- package/dist/atoms/components/navigation/index.d.ts.map +0 -1
- package/dist/atoms/components/theme/ColorSwatch/ColorSwatch.d.ts.map +0 -1
- package/dist/atoms/components/theme/ColorSwatch/index.d.ts.map +0 -1
- package/dist/atoms/components/theme/DarkModeToggle.d.ts.map +0 -1
- package/dist/atoms/components/theme/PaletteSwitcher.d.ts.map +0 -1
- package/dist/atoms/components/theme/StyleGuide.d.ts.map +0 -1
- package/dist/atoms/components/theme/index.d.ts +0 -5
- package/dist/atoms/components/theme/index.d.ts.map +0 -1
- package/dist/atoms/components/user/UserAvatar/UserAvatar.d.ts.map +0 -1
- package/dist/atoms/components/user/UserAvatar/index.d.ts.map +0 -1
- package/dist/atoms/components/user/UserMenu/UserMenu.d.ts.map +0 -1
- package/dist/atoms/components/user/UserMenu/index.d.ts.map +0 -1
- package/dist/atoms/components/user/index.d.ts +0 -3
- package/dist/atoms/components/user/index.d.ts.map +0 -1
- package/dist/atoms/config/responsive.d.ts +0 -147
- package/dist/atoms/config/responsive.d.ts.map +0 -1
- package/dist/atoms/hooks/index.d.ts +0 -5
- package/dist/atoms/hooks/index.d.ts.map +0 -1
- package/dist/atoms/hooks/use-toast.d.ts +0 -16
- package/dist/atoms/hooks/use-toast.d.ts.map +0 -1
- package/dist/atoms/hooks/useResponsive.d.ts +0 -42
- package/dist/atoms/hooks/useResponsive.d.ts.map +0 -1
- package/dist/atoms/primitives/Badge.d.ts.map +0 -1
- package/dist/atoms/primitives/ErrorBoundary.d.ts.map +0 -1
- package/dist/atoms/primitives/Select.d.ts.map +0 -1
- package/dist/atoms/primitives/Switch.d.ts.map +0 -1
- package/dist/atoms/primitives/Tabs.d.ts.map +0 -1
- package/dist/atoms/primitives/avatar.d.ts.map +0 -1
- package/dist/atoms/primitives/button.d.ts.map +0 -1
- package/dist/atoms/primitives/card.d.ts.map +0 -1
- package/dist/atoms/primitives/checkbox.d.ts +0 -12
- package/dist/atoms/primitives/checkbox.d.ts.map +0 -1
- package/dist/atoms/primitives/dialog.d.ts +0 -34
- package/dist/atoms/primitives/dialog.d.ts.map +0 -1
- package/dist/atoms/primitives/dropdown-menu.d.ts.map +0 -1
- package/dist/atoms/primitives/index.d.ts.map +0 -1
- package/dist/atoms/primitives/input.d.ts.map +0 -1
- package/dist/atoms/primitives/label.d.ts.map +0 -1
- package/dist/atoms/primitives/skeleton.d.ts.map +0 -1
- package/dist/atoms/primitives/spinner.d.ts.map +0 -1
- package/dist/atoms/primitives/table.d.ts.map +0 -1
- package/dist/atoms/types/entity-config.d.ts +0 -117
- package/dist/atoms/types/entity-config.d.ts.map +0 -1
- package/dist/atoms/types/navigation.d.ts +0 -30
- package/dist/atoms/types/navigation.d.ts.map +0 -1
- package/dist/atoms/types/ui-config.d.ts +0 -50
- package/dist/atoms/types/ui-config.d.ts.map +0 -1
- package/dist/atoms/utils/color-manager.d.ts +0 -68
- package/dist/atoms/utils/color-manager.d.ts.map +0 -1
- package/dist/atoms/utils/debounce.d.ts +0 -6
- package/dist/atoms/utils/debounce.d.ts.map +0 -1
- package/dist/atoms/utils/field-detection.d.ts +0 -15
- package/dist/atoms/utils/field-detection.d.ts.map +0 -1
- package/dist/atoms/utils/icon-resolver.d.ts +0 -76
- package/dist/atoms/utils/icon-resolver.d.ts.map +0 -1
- package/dist/atoms/utils/index.d.ts +0 -5
- package/dist/atoms/utils/index.d.ts.map +0 -1
- package/dist/atoms/utils/metric-engine.d.ts +0 -30
- package/dist/atoms/utils/metric-engine.d.ts.map +0 -1
- package/dist/atoms/utils/ui-mapping.d.ts +0 -17
- package/dist/atoms/utils/ui-mapping.d.ts.map +0 -1
- package/dist/codegen/index.d.ts +0 -7
- package/dist/codegen/index.d.ts.map +0 -1
- package/dist/codegen/openapi/bulk-hook-generator.d.ts +0 -40
- package/dist/codegen/openapi/bulk-hook-generator.d.ts.map +0 -1
- package/dist/codegen/openapi/bulk-types.d.ts +0 -142
- package/dist/codegen/openapi/bulk-types.d.ts.map +0 -1
- package/dist/codegen/openapi/client-generator.d.ts +0 -52
- package/dist/codegen/openapi/client-generator.d.ts.map +0 -1
- package/dist/codegen/openapi/confidence-scorer.d.ts +0 -30
- package/dist/codegen/openapi/confidence-scorer.d.ts.map +0 -1
- package/dist/codegen/openapi/hook-config.d.ts +0 -50
- package/dist/codegen/openapi/hook-config.d.ts.map +0 -1
- package/dist/codegen/openapi/hook-generator.d.ts +0 -108
- package/dist/codegen/openapi/hook-generator.d.ts.map +0 -1
- package/dist/codegen/openapi/index.d.ts +0 -27
- package/dist/codegen/openapi/index.d.ts.map +0 -1
- package/dist/codegen/openapi/parser.d.ts +0 -107
- package/dist/codegen/openapi/parser.d.ts.map +0 -1
- package/dist/codegen/openapi/type-generator.d.ts +0 -53
- package/dist/codegen/openapi/type-generator.d.ts.map +0 -1
- package/dist/features/auth/hooks/useAuthContext.d.ts +0 -7
- package/dist/features/auth/hooks/useAuthContext.d.ts.map +0 -1
- package/dist/features/auth/providers/MockAuthProvider.d.ts +0 -9
- package/dist/features/auth/providers/MockAuthProvider.d.ts.map +0 -1
- package/dist/features/auth/providers/index.d.ts +0 -2
- package/dist/features/auth/providers/index.d.ts.map +0 -1
- package/dist/features/auth/services/mock-auth-service.d.ts +0 -17
- package/dist/features/auth/services/mock-auth-service.d.ts.map +0 -1
- package/dist/generated/client/client.d.ts +0 -23
- package/dist/generated/client/client.d.ts.map +0 -1
- package/dist/generated/client/config.d.ts +0 -10
- package/dist/generated/client/config.d.ts.map +0 -1
- package/dist/generated/client/index.d.ts +0 -12
- package/dist/generated/client/index.d.ts.map +0 -1
- package/dist/generated/client/methods.d.ts +0 -591
- package/dist/generated/client/methods.d.ts.map +0 -1
- package/dist/generated/client/types.d.ts +0 -37
- package/dist/generated/client/types.d.ts.map +0 -1
- package/dist/generated/example.d.ts +0 -8
- package/dist/generated/example.d.ts.map +0 -1
- package/dist/generated/hooks/index.d.ts +0 -11
- package/dist/generated/hooks/index.d.ts.map +0 -1
- package/dist/generated/hooks/keys.d.ts +0 -59
- package/dist/generated/hooks/keys.d.ts.map +0 -1
- package/dist/generated/hooks/mutations.d.ts +0 -551
- package/dist/generated/hooks/mutations.d.ts.map +0 -1
- package/dist/generated/hooks/queries.d.ts +0 -426
- package/dist/generated/hooks/queries.d.ts.map +0 -1
- package/dist/generated/hooks/types.d.ts +0 -318
- package/dist/generated/hooks/types.d.ts.map +0 -1
- package/dist/generated/index.d.ts +0 -13
- package/dist/generated/index.d.ts.map +0 -1
- package/dist/generated/types/endpoints.d.ts +0 -1364
- package/dist/generated/types/endpoints.d.ts.map +0 -1
- package/dist/generated/types/index.d.ts +0 -11
- package/dist/generated/types/index.d.ts.map +0 -1
- package/dist/generated/types/parameters.d.ts +0 -8
- package/dist/generated/types/parameters.d.ts.map +0 -1
- package/dist/generated/types/responses.d.ts +0 -8
- package/dist/generated/types/responses.d.ts.map +0 -1
- package/dist/generated/types/schemas.d.ts +0 -652
- package/dist/generated/types/schemas.d.ts.map +0 -1
- package/dist/molecules/feedback/index.d.ts +0 -2
- package/dist/molecules/feedback/index.d.ts.map +0 -1
- package/dist/molecules/layout/BulkSelectionBar.d.ts +0 -15
- package/dist/molecules/layout/BulkSelectionBar.d.ts.map +0 -1
- package/dist/molecules/layout/DashboardWithSidePanel/DashboardWithSidePanel.d.ts +0 -16
- package/dist/molecules/layout/DashboardWithSidePanel/DashboardWithSidePanel.d.ts.map +0 -1
- package/dist/molecules/layout/DashboardWithSidePanel/index.d.ts +0 -2
- package/dist/molecules/layout/DashboardWithSidePanel/index.d.ts.map +0 -1
- package/dist/molecules/layout/NavigationContext.d.ts +0 -15
- package/dist/molecules/layout/NavigationContext.d.ts.map +0 -1
- package/dist/templates/EnhancedDataTemplate.d.ts +0 -188
- package/dist/templates/EnhancedDataTemplate.d.ts.map +0 -1
- package/dist/templates/EnhancedDataTemplate.hooks.bulk.d.ts +0 -18
- package/dist/templates/EnhancedDataTemplate.hooks.bulk.d.ts.map +0 -1
- package/dist/templates/EnhancedDataTemplate.hooks.d.ts +0 -22
- package/dist/templates/EnhancedDataTemplate.hooks.d.ts.map +0 -1
- package/dist/templates/api/APIDataTemplate.d.ts +0 -66
- package/dist/templates/api/APIDataTemplate.d.ts.map +0 -1
- package/dist/templates/api/index.d.ts +0 -8
- package/dist/templates/api/index.d.ts.map +0 -1
- /package/dist/atoms/{components/layout → composed}/Accordion/Accordion.d.ts +0 -0
- /package/dist/atoms/{components/layout → composed}/Accordion/index.d.ts +0 -0
- /package/dist/atoms/{components/feedback → composed}/Alert/Alert.d.ts +0 -0
- /package/dist/atoms/{components/feedback → composed}/Alert/index.d.ts +0 -0
- /package/dist/atoms/{components/layout → composed}/Breadcrumb/Breadcrumb.d.ts +0 -0
- /package/dist/atoms/{components/layout → composed}/Breadcrumb/index.d.ts +0 -0
- /package/dist/atoms/{components/data → composed}/Chart/index.d.ts +0 -0
- /package/dist/atoms/{components/theme → composed}/ColorSwatch/ColorSwatch.d.ts +0 -0
- /package/dist/atoms/{components/theme → composed}/ColorSwatch/index.d.ts +0 -0
- /package/dist/atoms/{components/theme → composed}/DarkModeToggle.d.ts +0 -0
- /package/dist/atoms/{components/data → composed}/DataBadge/index.d.ts +0 -0
- /package/dist/atoms/{components/data → composed}/DataTable/TableCellWithTooltip.d.ts +0 -0
- /package/dist/atoms/{components/data → composed}/DataTable/index.d.ts +0 -0
- /package/dist/atoms/{components/forms → composed}/DateTimePicker/DateTimePicker.d.ts +0 -0
- /package/dist/atoms/{components/forms → composed}/DateTimePicker/index.d.ts +0 -0
- /package/dist/atoms/{components/data → composed}/DetailedCard/DetailedCard.d.ts +0 -0
- /package/dist/atoms/{components/data → composed}/DetailedCard/index.d.ts +0 -0
- /package/dist/atoms/{components/feedback → composed}/EmptyState/EmptyState.d.ts +0 -0
- /package/dist/atoms/{components/feedback → composed}/EmptyState/index.d.ts +0 -0
- /package/dist/atoms/{components/forms → composed}/FileUpload/FileUpload.d.ts +0 -0
- /package/dist/atoms/{components/forms → composed}/FileUpload/index.d.ts +0 -0
- /package/dist/atoms/{components/forms → composed}/FormField/FormField.d.ts +0 -0
- /package/dist/atoms/{components/forms → composed}/FormField/index.d.ts +0 -0
- /package/dist/atoms/{components/navigation → composed}/GlobalSearch/GlobalSearch.d.ts +0 -0
- /package/dist/atoms/{components/navigation → composed}/GlobalSearch/index.d.ts +0 -0
- /package/dist/atoms/{components/data → composed}/IconBadge/index.d.ts +0 -0
- /package/dist/atoms/{components/layout → composed}/Modal/Modal.d.ts +0 -0
- /package/dist/atoms/{components/layout → composed}/Modal/index.d.ts +0 -0
- /package/dist/atoms/{components/theme → composed}/PaletteSwitcher.d.ts +0 -0
- /package/dist/atoms/{components/data → composed}/ProgressBar/ProgressBar.d.ts +0 -0
- /package/dist/atoms/{components/data → composed}/ProgressBar/index.d.ts +0 -0
- /package/dist/atoms/{components/data → composed}/StatCard/index.d.ts +0 -0
- /package/dist/atoms/{components/theme → composed}/StyleGuide.d.ts +0 -0
- /package/dist/atoms/{components/feedback → composed}/Toast/Toast.d.ts +0 -0
- /package/dist/atoms/{components/feedback → composed}/Toast/index.d.ts +0 -0
- /package/dist/atoms/{components/layout → composed}/Tooltip/Tooltip.d.ts +0 -0
- /package/dist/atoms/{components/user → composed}/UserAvatar/UserAvatar.d.ts +0 -0
- /package/dist/atoms/{components/user → composed}/UserAvatar/index.d.ts +0 -0
- /package/dist/atoms/{components/user → composed}/UserMenu/UserMenu.d.ts +0 -0
- /package/dist/atoms/{components/user → composed}/UserMenu/index.d.ts +0 -0
- /package/dist/atoms/{primitives → ui}/Badge.d.ts +0 -0
- /package/dist/atoms/{primitives → ui}/ErrorBoundary.d.ts +0 -0
- /package/dist/atoms/{primitives → ui}/Select.d.ts +0 -0
- /package/dist/atoms/{primitives → ui}/Switch.d.ts +0 -0
- /package/dist/atoms/{primitives → ui}/Tabs.d.ts +0 -0
- /package/dist/atoms/{primitives → ui}/avatar.d.ts +0 -0
- /package/dist/atoms/{primitives → ui}/card.d.ts +0 -0
- /package/dist/atoms/{primitives → ui}/dropdown-menu.d.ts +0 -0
- /package/dist/atoms/{primitives → ui}/input.d.ts +0 -0
- /package/dist/atoms/{primitives → ui}/label.d.ts +0 -0
- /package/dist/atoms/{primitives → ui}/skeleton.d.ts +0 -0
- /package/dist/atoms/{primitives → ui}/spinner.d.ts +0 -0
- /package/dist/atoms/{primitives → ui}/table.d.ts +0 -0
|
@@ -1,1057 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
/**
|
|
3
|
-
* React Hook Generator
|
|
4
|
-
*
|
|
5
|
-
* Generates React hooks with TanStack Query integration for API endpoints
|
|
6
|
-
* with proper TypeScript typing and error/loading states.
|
|
7
|
-
*
|
|
8
|
-
* Part of FRO-3: React Hook Generator
|
|
9
|
-
*/
|
|
10
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
11
|
-
exports.ReactHookGenerator = void 0;
|
|
12
|
-
exports.generateHooks = generateHooks;
|
|
13
|
-
const hook_config_1 = require("./hook-config");
|
|
14
|
-
const confidence_scorer_1 = require("./confidence-scorer");
|
|
15
|
-
const bulk_hook_generator_1 = require("./bulk-hook-generator");
|
|
16
|
-
const bulk_types_1 = require("./bulk-types");
|
|
17
|
-
class ReactHookGenerator {
|
|
18
|
-
constructor(options = {}) {
|
|
19
|
-
this.scoredNames = [];
|
|
20
|
-
this.resourceConfigs = new Map();
|
|
21
|
-
this.options = {
|
|
22
|
-
queryKeyPrefix: options.queryKeyPrefix || 'api',
|
|
23
|
-
includeInfiniteQueries: options.includeInfiniteQueries !== false,
|
|
24
|
-
includeOptimisticUpdates: options.includeOptimisticUpdates !== false,
|
|
25
|
-
includeMutationHelpers: options.includeMutationHelpers ?? true,
|
|
26
|
-
authenticationRequired: options.authenticationRequired ?? true,
|
|
27
|
-
errorHandling: options.errorHandling || 'throw',
|
|
28
|
-
configPath: options.configPath || './hooks.config.json',
|
|
29
|
-
enableConfidenceScoring: options.enableConfidenceScoring ?? true
|
|
30
|
-
};
|
|
31
|
-
this.configManager = new hook_config_1.HookConfigManager(this.options.configPath);
|
|
32
|
-
this.confidenceScorer = new confidence_scorer_1.ConfidenceScorer();
|
|
33
|
-
this.bulkHookGenerator = new bulk_hook_generator_1.BulkHookGenerator();
|
|
34
|
-
}
|
|
35
|
-
/**
|
|
36
|
-
* Detect resource operations from endpoints
|
|
37
|
-
*/
|
|
38
|
-
detectResourceOperations(endpoints) {
|
|
39
|
-
const resourceMap = new Map();
|
|
40
|
-
endpoints.forEach(endpoint => {
|
|
41
|
-
const resourceName = this.extractResourceName(endpoint.path);
|
|
42
|
-
if (!resourceName)
|
|
43
|
-
return;
|
|
44
|
-
const config = resourceMap.get(resourceName) || this.createDefaultConfig(resourceName);
|
|
45
|
-
// Check if this is a bulk operation
|
|
46
|
-
const requestBody = endpoint.requestBody;
|
|
47
|
-
if ((0, bulk_types_1.isBulkOperation)(endpoint.path, endpoint.method, requestBody)) {
|
|
48
|
-
const bulkType = detectBulkOperationType(endpoint.path, endpoint.method);
|
|
49
|
-
switch (bulkType) {
|
|
50
|
-
case 'delete':
|
|
51
|
-
config.operations.bulkDelete = {
|
|
52
|
-
path: endpoint.path,
|
|
53
|
-
method: endpoint.method
|
|
54
|
-
};
|
|
55
|
-
break;
|
|
56
|
-
case 'update':
|
|
57
|
-
config.operations.bulkUpdate = {
|
|
58
|
-
path: endpoint.path,
|
|
59
|
-
method: endpoint.method
|
|
60
|
-
};
|
|
61
|
-
break;
|
|
62
|
-
case 'create':
|
|
63
|
-
config.operations.bulkCreate = {
|
|
64
|
-
path: endpoint.path,
|
|
65
|
-
method: endpoint.method
|
|
66
|
-
};
|
|
67
|
-
break;
|
|
68
|
-
case 'mixed':
|
|
69
|
-
default:
|
|
70
|
-
if (!config.operations.customBulk) {
|
|
71
|
-
config.operations.customBulk = [];
|
|
72
|
-
}
|
|
73
|
-
config.operations.customBulk.push({
|
|
74
|
-
name: this.getOperationName(endpoint),
|
|
75
|
-
path: endpoint.path,
|
|
76
|
-
method: endpoint.method,
|
|
77
|
-
operationType: bulkType || 'mixed'
|
|
78
|
-
});
|
|
79
|
-
break;
|
|
80
|
-
}
|
|
81
|
-
}
|
|
82
|
-
else {
|
|
83
|
-
// Standard CRUD operations
|
|
84
|
-
switch (endpoint.method.toLowerCase()) {
|
|
85
|
-
case 'get':
|
|
86
|
-
if (endpoint.path.includes('{')) {
|
|
87
|
-
// Single resource fetch
|
|
88
|
-
}
|
|
89
|
-
else {
|
|
90
|
-
config.operations.list = { path: endpoint.path, method: endpoint.method };
|
|
91
|
-
}
|
|
92
|
-
break;
|
|
93
|
-
case 'post':
|
|
94
|
-
config.operations.create = { path: endpoint.path, method: endpoint.method };
|
|
95
|
-
break;
|
|
96
|
-
case 'put':
|
|
97
|
-
case 'patch':
|
|
98
|
-
config.operations.update = { path: endpoint.path, method: endpoint.method };
|
|
99
|
-
break;
|
|
100
|
-
case 'delete':
|
|
101
|
-
config.operations.delete = { path: endpoint.path, method: endpoint.method };
|
|
102
|
-
break;
|
|
103
|
-
}
|
|
104
|
-
}
|
|
105
|
-
resourceMap.set(resourceName, config);
|
|
106
|
-
});
|
|
107
|
-
return resourceMap;
|
|
108
|
-
}
|
|
109
|
-
/**
|
|
110
|
-
* Extract resource name from path
|
|
111
|
-
*/
|
|
112
|
-
extractResourceName(path) {
|
|
113
|
-
// Remove API version prefix
|
|
114
|
-
const cleanPath = path.replace(/^\/api\/v\d+\//, '/');
|
|
115
|
-
const segments = cleanPath.split('/').filter(Boolean);
|
|
116
|
-
// Find the first non-parameter segment
|
|
117
|
-
for (const segment of segments) {
|
|
118
|
-
if (!segment.startsWith('{')) {
|
|
119
|
-
return segment.replace(/-/g, '_');
|
|
120
|
-
}
|
|
121
|
-
}
|
|
122
|
-
return null;
|
|
123
|
-
}
|
|
124
|
-
/**
|
|
125
|
-
* Create default API config for a resource
|
|
126
|
-
*/
|
|
127
|
-
createDefaultConfig(resourceName) {
|
|
128
|
-
return {
|
|
129
|
-
baseURL: '',
|
|
130
|
-
resourceName,
|
|
131
|
-
operations: {}
|
|
132
|
-
};
|
|
133
|
-
}
|
|
134
|
-
async generate(parsedAPI) {
|
|
135
|
-
const endpoints = parsedAPI.endpoints;
|
|
136
|
-
// Load configuration
|
|
137
|
-
await this.configManager.load();
|
|
138
|
-
// Detect resource operations
|
|
139
|
-
this.resourceConfigs = this.detectResourceOperations(endpoints);
|
|
140
|
-
// Reset scored names for this generation
|
|
141
|
-
this.scoredNames = [];
|
|
142
|
-
const result = {
|
|
143
|
-
queries: this.generateQueryHooks(endpoints),
|
|
144
|
-
mutations: this.generateMutationHooks(endpoints),
|
|
145
|
-
keys: this.generateQueryKeys(endpoints),
|
|
146
|
-
types: this.generateHookTypes(endpoints),
|
|
147
|
-
index: this.generateIndexFile(),
|
|
148
|
-
report: undefined
|
|
149
|
-
};
|
|
150
|
-
// Generate confidence report if scoring is enabled
|
|
151
|
-
if (this.options.enableConfidenceScoring && this.scoredNames.length > 0) {
|
|
152
|
-
console.log(`Generated ${this.scoredNames.length} scored hook names`);
|
|
153
|
-
result.report = this.confidenceScorer.generateReport(this.scoredNames);
|
|
154
|
-
// Update statistics
|
|
155
|
-
const stats = {
|
|
156
|
-
totalGenerated: this.scoredNames.length,
|
|
157
|
-
highConfidence: this.scoredNames.filter(s => s.confidence === 'high').length,
|
|
158
|
-
mediumConfidence: this.scoredNames.filter(s => s.confidence === 'medium').length,
|
|
159
|
-
lowConfidence: this.scoredNames.filter(s => s.confidence === 'low').length,
|
|
160
|
-
humanReviewed: this.configManager.getReviewedNames().length
|
|
161
|
-
};
|
|
162
|
-
this.configManager.updateStatistics(stats);
|
|
163
|
-
// Save updated configuration
|
|
164
|
-
await this.configManager.save();
|
|
165
|
-
}
|
|
166
|
-
return result;
|
|
167
|
-
}
|
|
168
|
-
generateQueryHooks(endpoints) {
|
|
169
|
-
const hooks = [];
|
|
170
|
-
hooks.push(this.generateFileHeader('Query Hooks'));
|
|
171
|
-
hooks.push('');
|
|
172
|
-
hooks.push("import { useQuery, useInfiniteQuery, type UseQueryOptions, type UseInfiniteQueryOptions } from '@tanstack/react-query'");
|
|
173
|
-
hooks.push("import { apiClient } from '../client'");
|
|
174
|
-
hooks.push("import { queryKeys } from './keys'");
|
|
175
|
-
hooks.push("import * as Types from './types'");
|
|
176
|
-
hooks.push('');
|
|
177
|
-
// Filter GET endpoints for queries
|
|
178
|
-
const queryEndpoints = endpoints.filter(endpoint => endpoint.method === 'get');
|
|
179
|
-
// Track generated hook names to avoid duplicates
|
|
180
|
-
const generatedHooks = new Map();
|
|
181
|
-
for (const endpoint of queryEndpoints) {
|
|
182
|
-
let hookName = this.generateQueryHookName(endpoint);
|
|
183
|
-
// If we've already generated this hook, add suffix to differentiate
|
|
184
|
-
if (generatedHooks.has(hookName)) {
|
|
185
|
-
const existingEndpoint = generatedHooks.get(hookName);
|
|
186
|
-
// Determine which endpoint should get a suffix based on the path
|
|
187
|
-
const existingIsSimpler = existingEndpoint.path.split('/').filter(s => !s.startsWith('{')).length <
|
|
188
|
-
endpoint.path.split('/').filter(s => !s.startsWith('{')).length;
|
|
189
|
-
if (existingIsSimpler) {
|
|
190
|
-
// Current endpoint needs a suffix
|
|
191
|
-
const suffix = endpoint.path.includes('/{subcategory_id}') ? 'Single' : 'List';
|
|
192
|
-
hookName = `${hookName}${suffix}`;
|
|
193
|
-
}
|
|
194
|
-
else {
|
|
195
|
-
// Need to rename the existing hook that we already added
|
|
196
|
-
const existingSuffix = existingEndpoint.path.includes('/{subcategory_id}') ? 'Single' : 'List';
|
|
197
|
-
const existingHookName = hookName;
|
|
198
|
-
const newExistingHookName = `${existingHookName}${existingSuffix}`;
|
|
199
|
-
// Find and update the existing hook in our output
|
|
200
|
-
for (let i = hooks.length - 1; i >= 0; i--) {
|
|
201
|
-
if (hooks[i].includes(`function ${existingHookName}(`)) {
|
|
202
|
-
hooks[i] = hooks[i].replace(`function ${existingHookName}(`, `function ${newExistingHookName}(`);
|
|
203
|
-
// Also update the JSDoc if it references the hook name
|
|
204
|
-
if (i > 0 && hooks[i - 1].includes(`${existingHookName}`)) {
|
|
205
|
-
hooks[i - 1] = hooks[i - 1].replace(existingHookName, newExistingHookName);
|
|
206
|
-
}
|
|
207
|
-
break;
|
|
208
|
-
}
|
|
209
|
-
}
|
|
210
|
-
// Update our tracking map
|
|
211
|
-
generatedHooks.delete(existingHookName);
|
|
212
|
-
generatedHooks.set(newExistingHookName, existingEndpoint);
|
|
213
|
-
}
|
|
214
|
-
}
|
|
215
|
-
generatedHooks.set(hookName, endpoint);
|
|
216
|
-
const hook = this.generateQueryHook(endpoint, hookName);
|
|
217
|
-
hooks.push(hook);
|
|
218
|
-
hooks.push('');
|
|
219
|
-
// Generate infinite query version if applicable
|
|
220
|
-
if (this.options.includeInfiniteQueries && this.isListEndpoint(endpoint)) {
|
|
221
|
-
const infiniteHook = this.generateInfiniteQueryHook(endpoint, hookName);
|
|
222
|
-
hooks.push(infiniteHook);
|
|
223
|
-
hooks.push('');
|
|
224
|
-
}
|
|
225
|
-
}
|
|
226
|
-
return hooks.join('\n');
|
|
227
|
-
}
|
|
228
|
-
generateQueryHook(endpoint, hookName) {
|
|
229
|
-
const operationName = this.getOperationName(endpoint);
|
|
230
|
-
const hasParams = this.hasRequiredParams(endpoint);
|
|
231
|
-
const lines = [];
|
|
232
|
-
// Generate JSDoc
|
|
233
|
-
lines.push('/**');
|
|
234
|
-
if (endpoint.summary) {
|
|
235
|
-
lines.push(` * ${endpoint.summary}`);
|
|
236
|
-
}
|
|
237
|
-
if (endpoint.description) {
|
|
238
|
-
lines.push(` * ${endpoint.description}`);
|
|
239
|
-
}
|
|
240
|
-
lines.push(` * @param ${hasParams ? 'params' : 'options'} ${hasParams ? 'Request parameters' : 'Query options'}`);
|
|
241
|
-
lines.push(' */');
|
|
242
|
-
// Generate hook signature
|
|
243
|
-
const paramType = hasParams ? this.generateParamType(endpoint) : '';
|
|
244
|
-
const params = hasParams ? `params: ${paramType}, options?: UseQueryOptions<any, any, any>` : 'options?: UseQueryOptions<any, any, any>';
|
|
245
|
-
lines.push(`export function ${hookName}(${params}) {`);
|
|
246
|
-
// Generate hook body
|
|
247
|
-
// Extract the query key name from the hook name (remove 'use' prefix)
|
|
248
|
-
const queryKeyName = hookName.replace(/^use/, '');
|
|
249
|
-
const queryKeyNameCamelCase = queryKeyName.charAt(0).toLowerCase() + queryKeyName.slice(1);
|
|
250
|
-
const queryKeyCall = hasParams ?
|
|
251
|
-
`queryKeys.${queryKeyNameCamelCase}(params)` :
|
|
252
|
-
`queryKeys.${queryKeyNameCamelCase}()`;
|
|
253
|
-
const apiCall = hasParams ?
|
|
254
|
-
`() => apiClient.${this.camelCase(operationName)}(params)` :
|
|
255
|
-
`() => apiClient.${this.camelCase(operationName)}()`;
|
|
256
|
-
lines.push(' return useQuery({');
|
|
257
|
-
lines.push(` queryKey: ${queryKeyCall},`);
|
|
258
|
-
lines.push(` queryFn: ${apiCall},`);
|
|
259
|
-
// Note: Authentication is handled by the API client interceptors
|
|
260
|
-
// If you need to disable queries when not authenticated, use:
|
|
261
|
-
// enabled: !!user && (options?.enabled ?? true) in your component
|
|
262
|
-
lines.push(' ...options');
|
|
263
|
-
lines.push(' })');
|
|
264
|
-
lines.push('}');
|
|
265
|
-
return lines.join('\n');
|
|
266
|
-
}
|
|
267
|
-
generateInfiniteQueryHook(endpoint, baseHookName) {
|
|
268
|
-
const hookName = baseHookName.replace('use', 'useInfinite');
|
|
269
|
-
const operationName = this.getOperationName(endpoint);
|
|
270
|
-
const lines = [];
|
|
271
|
-
lines.push('/**');
|
|
272
|
-
lines.push(` * Infinite query version of ${baseHookName}`);
|
|
273
|
-
lines.push(' */');
|
|
274
|
-
const paramType = this.generateParamType(endpoint);
|
|
275
|
-
// Extract the query key name from the hook name (remove 'use' prefix)
|
|
276
|
-
const queryKeyName = baseHookName.replace(/^use/, '');
|
|
277
|
-
const queryKeyNameCamelCase = queryKeyName.charAt(0).toLowerCase() + queryKeyName.slice(1);
|
|
278
|
-
lines.push(`export function ${hookName}(params: ${paramType}, options?: UseInfiniteQueryOptions<any, any, any, any, any>) {`);
|
|
279
|
-
lines.push(' return useInfiniteQuery({');
|
|
280
|
-
lines.push(` queryKey: [...queryKeys.${queryKeyNameCamelCase}(), params],`);
|
|
281
|
-
lines.push(` queryFn: ({ pageParam = 1 }) => apiClient.${this.camelCase(operationName)}({ ...params, page: pageParam }),`);
|
|
282
|
-
lines.push(' getNextPageParam: (lastPage, allPages) => {');
|
|
283
|
-
lines.push(' // Implement pagination logic based on your API response structure');
|
|
284
|
-
lines.push(' return lastPage?.hasNextPage ? allPages.length + 1 : undefined');
|
|
285
|
-
lines.push(' },');
|
|
286
|
-
lines.push(' initialPageParam: 1,');
|
|
287
|
-
lines.push(' ...options');
|
|
288
|
-
lines.push(' })');
|
|
289
|
-
lines.push('}');
|
|
290
|
-
return lines.join('\n');
|
|
291
|
-
}
|
|
292
|
-
generateMutationHooks(endpoints) {
|
|
293
|
-
const hooks = [];
|
|
294
|
-
hooks.push(this.generateFileHeader('Mutation Hooks'));
|
|
295
|
-
hooks.push('');
|
|
296
|
-
hooks.push("import { useMutation, useQueryClient, type UseMutationOptions } from '@tanstack/react-query'");
|
|
297
|
-
hooks.push("import { apiClient } from '../client'");
|
|
298
|
-
hooks.push("import { queryKeys } from './keys'");
|
|
299
|
-
hooks.push("import * as Types from './types'");
|
|
300
|
-
hooks.push("import type { BulkOperationRequest, BulkOperationResponse, BulkOperationProgress, BulkMutationOptions } from '../bulk-types'");
|
|
301
|
-
hooks.push('');
|
|
302
|
-
// Filter non-GET endpoints for mutations
|
|
303
|
-
const mutationEndpoints = endpoints.filter(endpoint => endpoint.method !== 'get');
|
|
304
|
-
// Track generated hook names to avoid duplicates
|
|
305
|
-
const generatedHooks = new Map();
|
|
306
|
-
for (const endpoint of mutationEndpoints) {
|
|
307
|
-
// Check if this is a bulk operation
|
|
308
|
-
const requestBody = endpoint.requestBody;
|
|
309
|
-
const isBulk = (0, bulk_types_1.isBulkOperation)(endpoint.path, endpoint.method, requestBody);
|
|
310
|
-
let hookName = this.generateMutationHookName(endpoint);
|
|
311
|
-
// If we've already generated this hook, add suffix to differentiate
|
|
312
|
-
if (generatedHooks.has(hookName)) {
|
|
313
|
-
const existingEndpoint = generatedHooks.get(hookName);
|
|
314
|
-
// Add method suffix to differentiate
|
|
315
|
-
const methodSuffix = endpoint.method.charAt(0).toUpperCase() + endpoint.method.slice(1);
|
|
316
|
-
hookName = `${hookName}${methodSuffix}`;
|
|
317
|
-
}
|
|
318
|
-
generatedHooks.set(hookName, endpoint);
|
|
319
|
-
// Generate appropriate hook based on type
|
|
320
|
-
const hook = isBulk
|
|
321
|
-
? this.bulkHookGenerator.generateBulkMutationHook(endpoint, hookName, this.getOperationName(endpoint))
|
|
322
|
-
: this.generateMutationHook(endpoint, hookName);
|
|
323
|
-
hooks.push(hook);
|
|
324
|
-
hooks.push('');
|
|
325
|
-
}
|
|
326
|
-
return hooks.join('\n');
|
|
327
|
-
}
|
|
328
|
-
generateMutationHook(endpoint, hookName) {
|
|
329
|
-
const operationName = this.getOperationName(endpoint);
|
|
330
|
-
const lines = [];
|
|
331
|
-
// Generate JSDoc
|
|
332
|
-
lines.push('/**');
|
|
333
|
-
if (endpoint.summary) {
|
|
334
|
-
lines.push(` * ${endpoint.summary}`);
|
|
335
|
-
}
|
|
336
|
-
if (endpoint.description) {
|
|
337
|
-
lines.push(` * ${endpoint.description}`);
|
|
338
|
-
}
|
|
339
|
-
lines.push(' */');
|
|
340
|
-
// Generate hook signature
|
|
341
|
-
const mutationType = this.generateMutationType(endpoint);
|
|
342
|
-
lines.push(`export function ${hookName}(options?: UseMutationOptions<any, any, ${mutationType}>) {`);
|
|
343
|
-
lines.push(' const queryClient = useQueryClient()');
|
|
344
|
-
lines.push('');
|
|
345
|
-
lines.push(' return useMutation({');
|
|
346
|
-
// Generate mutation function
|
|
347
|
-
const hasParams = this.hasRequiredParams(endpoint);
|
|
348
|
-
if (hasParams) {
|
|
349
|
-
lines.push(` mutationFn: ({ pathParams, ...data }) => apiClient.${this.camelCase(operationName)}(pathParams, data),`);
|
|
350
|
-
}
|
|
351
|
-
else {
|
|
352
|
-
lines.push(` mutationFn: (data) => apiClient.${this.camelCase(operationName)}(data),`);
|
|
353
|
-
}
|
|
354
|
-
// Generate optimistic updates and cache invalidation
|
|
355
|
-
if (this.options.includeOptimisticUpdates) {
|
|
356
|
-
lines.push(this.generateOptimisticUpdate(endpoint));
|
|
357
|
-
}
|
|
358
|
-
lines.push(this.generateCacheInvalidation(endpoint));
|
|
359
|
-
lines.push(' ...options');
|
|
360
|
-
lines.push(' })');
|
|
361
|
-
lines.push('}');
|
|
362
|
-
return lines.join('\n');
|
|
363
|
-
}
|
|
364
|
-
generateOptimisticUpdate(endpoint) {
|
|
365
|
-
const method = endpoint.method.toLowerCase();
|
|
366
|
-
const resource = endpoint.tags?.[0] || 'default';
|
|
367
|
-
const hasPathParams = endpoint.parameters.some(p => p.in === 'path');
|
|
368
|
-
switch (method) {
|
|
369
|
-
case 'post':
|
|
370
|
-
return ` onMutate: async (data: any) => {
|
|
371
|
-
// Cancel outgoing refetches
|
|
372
|
-
await queryClient.cancelQueries({ queryKey: queryKeys.${resource}() })
|
|
373
|
-
|
|
374
|
-
// Snapshot previous value
|
|
375
|
-
const previousData = queryClient.getQueryData(queryKeys.${resource}())
|
|
376
|
-
|
|
377
|
-
// Optimistically update cache
|
|
378
|
-
queryClient.setQueryData(queryKeys.${resource}(), (old: any) => {
|
|
379
|
-
if (Array.isArray(old)) {
|
|
380
|
-
return [...old, data]
|
|
381
|
-
}
|
|
382
|
-
return old
|
|
383
|
-
})
|
|
384
|
-
|
|
385
|
-
return { previousData }
|
|
386
|
-
},
|
|
387
|
-
onError: (err: any, data: any, context: any) => {
|
|
388
|
-
// Rollback on error
|
|
389
|
-
if (context?.previousData !== undefined) {
|
|
390
|
-
queryClient.setQueryData(queryKeys.${resource}(), context.previousData)
|
|
391
|
-
}
|
|
392
|
-
},`;
|
|
393
|
-
case 'put':
|
|
394
|
-
case 'patch':
|
|
395
|
-
if (hasPathParams) {
|
|
396
|
-
return ` onMutate: async (data: any) => {
|
|
397
|
-
await queryClient.cancelQueries({ queryKey: queryKeys.${resource}() })
|
|
398
|
-
|
|
399
|
-
const previousData = queryClient.getQueryData(queryKeys.${resource}())
|
|
400
|
-
|
|
401
|
-
// Update specific item in cache
|
|
402
|
-
queryClient.setQueryData(queryKeys.${resource}(), (old: any) => {
|
|
403
|
-
if (Array.isArray(old)) {
|
|
404
|
-
return old.map((item: any) =>
|
|
405
|
-
item.id === data.pathParams?.id || item.id === data.pathParams?.${resource.slice(0, -1)}_id
|
|
406
|
-
? { ...item, ...data }
|
|
407
|
-
: item
|
|
408
|
-
)
|
|
409
|
-
}
|
|
410
|
-
return old
|
|
411
|
-
})
|
|
412
|
-
|
|
413
|
-
return { previousData }
|
|
414
|
-
},
|
|
415
|
-
onError: (err: any, data: any, context: any) => {
|
|
416
|
-
if (context?.previousData !== undefined) {
|
|
417
|
-
queryClient.setQueryData(queryKeys.${resource}(), context.previousData)
|
|
418
|
-
}
|
|
419
|
-
},`;
|
|
420
|
-
}
|
|
421
|
-
return ` onMutate: async (data: any) => {
|
|
422
|
-
await queryClient.cancelQueries({ queryKey: queryKeys.${resource}() })
|
|
423
|
-
|
|
424
|
-
const previousData = queryClient.getQueryData(queryKeys.${resource}())
|
|
425
|
-
|
|
426
|
-
// Update cache with new data
|
|
427
|
-
queryClient.setQueryData(queryKeys.${resource}(), data)
|
|
428
|
-
|
|
429
|
-
return { previousData }
|
|
430
|
-
},
|
|
431
|
-
onError: (err: any, data: any, context: any) => {
|
|
432
|
-
if (context?.previousData !== undefined) {
|
|
433
|
-
queryClient.setQueryData(queryKeys.${resource}(), context.previousData)
|
|
434
|
-
}
|
|
435
|
-
},`;
|
|
436
|
-
case 'delete':
|
|
437
|
-
return ` onMutate: async (data: any) => {
|
|
438
|
-
await queryClient.cancelQueries({ queryKey: queryKeys.${resource}() })
|
|
439
|
-
|
|
440
|
-
const previousData = queryClient.getQueryData(queryKeys.${resource}())
|
|
441
|
-
|
|
442
|
-
// Remove item from cache
|
|
443
|
-
queryClient.setQueryData(queryKeys.${resource}(), (old: any) => {
|
|
444
|
-
if (Array.isArray(old)) {
|
|
445
|
-
const idToDelete = data.pathParams?.id || data.pathParams?.${resource.slice(0, -1)}_id || data
|
|
446
|
-
return old.filter((item: any) => item.id !== idToDelete)
|
|
447
|
-
}
|
|
448
|
-
return old
|
|
449
|
-
})
|
|
450
|
-
|
|
451
|
-
return { previousData }
|
|
452
|
-
},
|
|
453
|
-
onError: (err: any, data: any, context: any) => {
|
|
454
|
-
if (context?.previousData !== undefined) {
|
|
455
|
-
queryClient.setQueryData(queryKeys.${resource}(), context.previousData)
|
|
456
|
-
}
|
|
457
|
-
},`;
|
|
458
|
-
default:
|
|
459
|
-
return '';
|
|
460
|
-
}
|
|
461
|
-
}
|
|
462
|
-
generateCacheInvalidation(endpoint) {
|
|
463
|
-
const relatedTags = this.getRelatedQueryTags(endpoint);
|
|
464
|
-
return ` onSettled: () => {
|
|
465
|
-
// Invalidate related queries
|
|
466
|
-
${relatedTags.map(tag => `queryClient.invalidateQueries({ queryKey: queryKeys.${tag}() })`).join('\n ')}
|
|
467
|
-
},`;
|
|
468
|
-
}
|
|
469
|
-
generateQueryKeys(endpoints) {
|
|
470
|
-
const keys = [];
|
|
471
|
-
keys.push(this.generateFileHeader('Query Keys'));
|
|
472
|
-
keys.push('');
|
|
473
|
-
keys.push('/**');
|
|
474
|
-
keys.push(' * Centralized query key factory');
|
|
475
|
-
keys.push(' * Ensures consistent cache key generation across the application');
|
|
476
|
-
keys.push(' */');
|
|
477
|
-
keys.push('');
|
|
478
|
-
keys.push('export const queryKeys = {');
|
|
479
|
-
keys.push(` all: ['${this.options.queryKeyPrefix}'] as const,`);
|
|
480
|
-
keys.push('');
|
|
481
|
-
// Group endpoints by resource/tag
|
|
482
|
-
const groupedEndpoints = this.groupEndpointsByResource(endpoints);
|
|
483
|
-
for (const [resource, resourceEndpoints] of Object.entries(groupedEndpoints)) {
|
|
484
|
-
keys.push(` // ${resource} keys`);
|
|
485
|
-
keys.push(` ${resource}: () => [...queryKeys.all, '${resource}'] as const,`);
|
|
486
|
-
// Track generated key names to avoid duplicates
|
|
487
|
-
const generatedKeys = new Map();
|
|
488
|
-
for (const endpoint of resourceEndpoints) {
|
|
489
|
-
if (endpoint.method !== 'get')
|
|
490
|
-
continue;
|
|
491
|
-
const operationName = this.getOperationName(endpoint);
|
|
492
|
-
let keyName = this.camelCase(operationName.replace(/^get/, ''));
|
|
493
|
-
// If we've already generated this key, add suffix to differentiate
|
|
494
|
-
if (generatedKeys.has(keyName)) {
|
|
495
|
-
const existingEndpoint = generatedKeys.get(keyName);
|
|
496
|
-
// Determine which endpoint should get a suffix based on the path
|
|
497
|
-
// The one with a single resource gets the plain name, the one with sub-resources gets a suffix
|
|
498
|
-
const existingIsSimpler = existingEndpoint.path.split('/').filter(s => !s.startsWith('{')).length <
|
|
499
|
-
endpoint.path.split('/').filter(s => !s.startsWith('{')).length;
|
|
500
|
-
if (existingIsSimpler) {
|
|
501
|
-
// Current endpoint needs a suffix
|
|
502
|
-
const suffix = endpoint.path.includes('/{subcategory_id}') ? 'Single' : 'List';
|
|
503
|
-
keyName = `${keyName}${suffix}`;
|
|
504
|
-
}
|
|
505
|
-
else {
|
|
506
|
-
// Update the existing key with a suffix
|
|
507
|
-
const existingSuffix = existingEndpoint.path.includes('/{subcategory_id}') ? 'Single' : 'List';
|
|
508
|
-
const existingKeyName = keyName;
|
|
509
|
-
const newExistingKeyName = `${existingKeyName}${existingSuffix}`;
|
|
510
|
-
// Find and update the existing key in our output
|
|
511
|
-
for (let i = keys.length - 1; i >= 0; i--) {
|
|
512
|
-
if (keys[i].includes(`${existingKeyName}:`)) {
|
|
513
|
-
// Replace both the function name and the cache key string
|
|
514
|
-
keys[i] = keys[i]
|
|
515
|
-
.replace(`${existingKeyName}:`, `${newExistingKeyName}:`)
|
|
516
|
-
.replace(`'${existingKeyName}'`, `'${newExistingKeyName}'`);
|
|
517
|
-
break;
|
|
518
|
-
}
|
|
519
|
-
}
|
|
520
|
-
// Update our tracking map
|
|
521
|
-
generatedKeys.delete(existingKeyName);
|
|
522
|
-
generatedKeys.set(newExistingKeyName, existingEndpoint);
|
|
523
|
-
}
|
|
524
|
-
}
|
|
525
|
-
generatedKeys.set(keyName, endpoint);
|
|
526
|
-
if (this.hasRequiredParams(endpoint)) {
|
|
527
|
-
keys.push(` ${keyName}: (params: any) => [...queryKeys.${resource}(), '${keyName}', params] as const,`);
|
|
528
|
-
}
|
|
529
|
-
else {
|
|
530
|
-
keys.push(` ${keyName}: () => [...queryKeys.${resource}(), '${keyName}'] as const,`);
|
|
531
|
-
}
|
|
532
|
-
}
|
|
533
|
-
keys.push('');
|
|
534
|
-
}
|
|
535
|
-
keys.push('}');
|
|
536
|
-
return keys.join('\n');
|
|
537
|
-
}
|
|
538
|
-
generateHookTypes(endpoints) {
|
|
539
|
-
const types = [];
|
|
540
|
-
types.push(this.generateFileHeader('Hook Types'));
|
|
541
|
-
types.push('');
|
|
542
|
-
types.push('// Re-export bulk operation types for convenience');
|
|
543
|
-
types.push("export type { BulkOperationRequest, BulkOperationResponse, BulkOperationProgress, BulkMutationOptions } from '../bulk-types'");
|
|
544
|
-
types.push('');
|
|
545
|
-
// Track generated type names to avoid duplicates
|
|
546
|
-
const generatedTypes = new Set();
|
|
547
|
-
// Generate parameter and response types for hooks
|
|
548
|
-
for (const endpoint of endpoints) {
|
|
549
|
-
const operationName = this.getOperationName(endpoint);
|
|
550
|
-
if (this.hasRequiredParams(endpoint)) {
|
|
551
|
-
const typeName = `${this.capitalize(operationName)}Params`;
|
|
552
|
-
if (!generatedTypes.has(typeName)) {
|
|
553
|
-
generatedTypes.add(typeName);
|
|
554
|
-
const paramType = this.generateParamType(endpoint);
|
|
555
|
-
types.push(`export interface ${typeName} ${paramType}`);
|
|
556
|
-
types.push('');
|
|
557
|
-
}
|
|
558
|
-
}
|
|
559
|
-
if (endpoint.method !== 'get') {
|
|
560
|
-
const typeName = `${this.capitalize(operationName)}Data`;
|
|
561
|
-
if (!generatedTypes.has(typeName)) {
|
|
562
|
-
generatedTypes.add(typeName);
|
|
563
|
-
const mutationType = this.generateMutationType(endpoint);
|
|
564
|
-
types.push(`export interface ${typeName} ${mutationType}`);
|
|
565
|
-
types.push('');
|
|
566
|
-
}
|
|
567
|
-
}
|
|
568
|
-
}
|
|
569
|
-
return types.join('\n');
|
|
570
|
-
}
|
|
571
|
-
generateIndexFile() {
|
|
572
|
-
const exports = [];
|
|
573
|
-
exports.push(this.generateFileHeader('Generated React Hooks'));
|
|
574
|
-
exports.push('');
|
|
575
|
-
exports.push('// Query hooks');
|
|
576
|
-
exports.push("export * from './queries'");
|
|
577
|
-
exports.push('');
|
|
578
|
-
exports.push('// Mutation hooks');
|
|
579
|
-
exports.push("export * from './mutations'");
|
|
580
|
-
exports.push('');
|
|
581
|
-
exports.push('// Query keys');
|
|
582
|
-
exports.push("export { queryKeys } from './keys'");
|
|
583
|
-
exports.push('');
|
|
584
|
-
exports.push('// Hook types');
|
|
585
|
-
exports.push("export * from './types'");
|
|
586
|
-
return exports.join('\n');
|
|
587
|
-
}
|
|
588
|
-
generateFileHeader(title) {
|
|
589
|
-
return `/**
|
|
590
|
-
* ${title}
|
|
591
|
-
*
|
|
592
|
-
* Auto-generated React hooks from OpenAPI specification
|
|
593
|
-
* Do not edit manually - regenerate using the hook generator
|
|
594
|
-
*/`;
|
|
595
|
-
}
|
|
596
|
-
generateQueryHookName(endpoint) {
|
|
597
|
-
const operationName = this.getOperationName(endpoint);
|
|
598
|
-
return `use${this.capitalize(operationName)}`;
|
|
599
|
-
}
|
|
600
|
-
generateMutationHookName(endpoint) {
|
|
601
|
-
const operationName = this.getOperationName(endpoint);
|
|
602
|
-
// Check if this is a bulk operation
|
|
603
|
-
const resourceName = this.extractResourceName(endpoint.path);
|
|
604
|
-
if (resourceName) {
|
|
605
|
-
const bulkHookName = this.bulkHookGenerator.generateBulkMutationHookName(endpoint, resourceName);
|
|
606
|
-
if (bulkHookName) {
|
|
607
|
-
return bulkHookName;
|
|
608
|
-
}
|
|
609
|
-
}
|
|
610
|
-
return `use${this.capitalize(operationName)}`;
|
|
611
|
-
}
|
|
612
|
-
getOperationName(endpoint) {
|
|
613
|
-
// Check if we have a manual override in config
|
|
614
|
-
if (endpoint.operationId) {
|
|
615
|
-
const override = this.configManager.getOverride(endpoint.operationId);
|
|
616
|
-
if (override) {
|
|
617
|
-
return override;
|
|
618
|
-
}
|
|
619
|
-
}
|
|
620
|
-
// Generate the name using existing logic
|
|
621
|
-
let operationName;
|
|
622
|
-
if (endpoint.operationId) {
|
|
623
|
-
operationName = this.cleanOperationId(endpoint.operationId, endpoint);
|
|
624
|
-
}
|
|
625
|
-
else {
|
|
626
|
-
operationName = this.generateCleanName(endpoint);
|
|
627
|
-
}
|
|
628
|
-
// Apply deduplication if enabled
|
|
629
|
-
const patterns = this.configManager.getPatterns();
|
|
630
|
-
if (patterns.deduplicateSegments) {
|
|
631
|
-
operationName = this.removeDuplicateSegments(operationName);
|
|
632
|
-
}
|
|
633
|
-
// Score the generated name if confidence scoring is enabled
|
|
634
|
-
if (this.options.enableConfidenceScoring && endpoint.operationId) {
|
|
635
|
-
const hookName = endpoint.method === 'get'
|
|
636
|
-
? `use${this.capitalize(operationName)}`
|
|
637
|
-
: `use${this.capitalize(this.getMethodPrefix(endpoint.method))}${this.capitalize(operationName)}`;
|
|
638
|
-
const scored = this.confidenceScorer.scoreHookName(hookName, endpoint.operationId, endpoint.path, endpoint.method);
|
|
639
|
-
// Debug logging
|
|
640
|
-
if (scored.confidence === 'low') {
|
|
641
|
-
console.log(`Low confidence hook: ${hookName} (score: ${scored.score})`);
|
|
642
|
-
}
|
|
643
|
-
this.scoredNames.push(scored);
|
|
644
|
-
// If we have a suggestion with higher confidence, use it
|
|
645
|
-
if (scored.confidence === 'low' && scored.suggestions.length > 0) {
|
|
646
|
-
const suggestion = scored.suggestions[0];
|
|
647
|
-
// Extract just the operation name from the suggestion
|
|
648
|
-
const prefix = `use${this.capitalize(this.getMethodPrefix(endpoint.method))}`;
|
|
649
|
-
if (suggestion.startsWith(prefix)) {
|
|
650
|
-
operationName = this.camelCase(suggestion.substring(prefix.length));
|
|
651
|
-
}
|
|
652
|
-
else if (suggestion.startsWith('use')) {
|
|
653
|
-
operationName = this.camelCase(suggestion.substring(3));
|
|
654
|
-
}
|
|
655
|
-
}
|
|
656
|
-
}
|
|
657
|
-
return operationName;
|
|
658
|
-
}
|
|
659
|
-
cleanOperationId(operationId, endpoint) {
|
|
660
|
-
// Parse the operation ID into components
|
|
661
|
-
const parsed = this.parseOperationId(operationId, endpoint);
|
|
662
|
-
// Generate name based on parsed components
|
|
663
|
-
return this.generateNameFromParsed(parsed, endpoint);
|
|
664
|
-
}
|
|
665
|
-
/**
|
|
666
|
-
* Parse operation ID into structured components
|
|
667
|
-
*/
|
|
668
|
-
parseOperationId(operationId, endpoint) {
|
|
669
|
-
// Clean common patterns
|
|
670
|
-
const cleaned = operationId
|
|
671
|
-
.replace(/_api_v\d+_/g, '_') // Remove API version
|
|
672
|
-
.replace(/_(get|post|put|patch|delete)$/i, ''); // Remove HTTP suffix
|
|
673
|
-
// Split into parts
|
|
674
|
-
const parts = cleaned.split('_').filter(Boolean);
|
|
675
|
-
// Extract prefix (action) if exists
|
|
676
|
-
const prefix = this.extractPrefix(parts, { ...endpoint, operationId });
|
|
677
|
-
// Extract resources from path
|
|
678
|
-
const resources = this.extractResourcesFromPath(endpoint.path);
|
|
679
|
-
// Check if it's a custom action
|
|
680
|
-
const segments = endpoint.path.split('/');
|
|
681
|
-
const lastSegment = segments[segments.length - 1];
|
|
682
|
-
const isCustomAction = !lastSegment.startsWith('{') && segments[segments.length - 2]?.startsWith('{');
|
|
683
|
-
return {
|
|
684
|
-
action: prefix?.action || '',
|
|
685
|
-
resource: resources.primary || '',
|
|
686
|
-
subResource: resources.sub?.[0] || '',
|
|
687
|
-
method: endpoint.method,
|
|
688
|
-
isCustomAction,
|
|
689
|
-
customActionName: isCustomAction ? lastSegment.replace(/-/g, '_') : undefined,
|
|
690
|
-
originalId: operationId,
|
|
691
|
-
prefix: prefix?.fullPrefix || '',
|
|
692
|
-
resources
|
|
693
|
-
};
|
|
694
|
-
}
|
|
695
|
-
/**
|
|
696
|
-
* Extract meaningful prefix from operation ID parts
|
|
697
|
-
*/
|
|
698
|
-
extractPrefix(parts, endpoint) {
|
|
699
|
-
if (parts.length === 0)
|
|
700
|
-
return null;
|
|
701
|
-
// For extracting the prefix, use the original operation ID
|
|
702
|
-
const originalId = endpoint.operationId || '';
|
|
703
|
-
// Check if first part is a known action
|
|
704
|
-
const knownActions = [
|
|
705
|
-
'login', 'logout', 'register', 'signup', 'signin',
|
|
706
|
-
'assign', 'reassign', 'create', 'update', 'delete',
|
|
707
|
-
'get', 'list', 'health', 'status', 'verify', 'validate'
|
|
708
|
-
];
|
|
709
|
-
const firstPart = parts[0].toLowerCase();
|
|
710
|
-
if (knownActions.includes(firstPart)) {
|
|
711
|
-
// Special handling for compound names like "get_health_status" or "get_current_user_info"
|
|
712
|
-
if (firstPart === 'get' && originalId.startsWith('get_')) {
|
|
713
|
-
// Extract everything between get_ and _api_v
|
|
714
|
-
const match = originalId.match(/^get_(.+?)_api_v\d+/);
|
|
715
|
-
if (match) {
|
|
716
|
-
const compoundName = match[1];
|
|
717
|
-
if (compoundName === 'health_status' || compoundName === 'current_user_info') {
|
|
718
|
-
return {
|
|
719
|
-
action: firstPart,
|
|
720
|
-
fullPrefix: `${firstPart}_${compoundName}`
|
|
721
|
-
};
|
|
722
|
-
}
|
|
723
|
-
}
|
|
724
|
-
}
|
|
725
|
-
// Look for compound actions like "assign_roles" or "reassign_budget"
|
|
726
|
-
if (parts.length > 1 && ['assign', 'reassign'].includes(firstPart)) {
|
|
727
|
-
// Special case for reassign_transaction_budget
|
|
728
|
-
if (firstPart === 'reassign' && parts[1] === 'transaction' && parts[2] === 'budget') {
|
|
729
|
-
return {
|
|
730
|
-
action: 'reassign',
|
|
731
|
-
fullPrefix: 'reassign_budget'
|
|
732
|
-
};
|
|
733
|
-
}
|
|
734
|
-
return {
|
|
735
|
-
action: firstPart,
|
|
736
|
-
fullPrefix: `${parts[0]}_${parts[1]}`
|
|
737
|
-
};
|
|
738
|
-
}
|
|
739
|
-
return {
|
|
740
|
-
action: firstPart,
|
|
741
|
-
fullPrefix: parts[0]
|
|
742
|
-
};
|
|
743
|
-
}
|
|
744
|
-
return null;
|
|
745
|
-
}
|
|
746
|
-
/**
|
|
747
|
-
* Extract resources from API path
|
|
748
|
-
*/
|
|
749
|
-
extractResourcesFromPath(path) {
|
|
750
|
-
// Remove API version prefix
|
|
751
|
-
const cleanPath = path.replace(/^\/api\/v\d+\//, '/');
|
|
752
|
-
const segments = cleanPath.split('/').filter(Boolean);
|
|
753
|
-
const resources = [];
|
|
754
|
-
let lastHasParam = false;
|
|
755
|
-
for (let i = 0; i < segments.length; i++) {
|
|
756
|
-
if (!segments[i].startsWith('{')) {
|
|
757
|
-
resources.push(segments[i].replace(/-/g, '_'));
|
|
758
|
-
}
|
|
759
|
-
else if (i === segments.length - 1) {
|
|
760
|
-
lastHasParam = true;
|
|
761
|
-
}
|
|
762
|
-
}
|
|
763
|
-
return {
|
|
764
|
-
primary: resources[0] || '',
|
|
765
|
-
sub: resources.slice(1),
|
|
766
|
-
lastHasParam
|
|
767
|
-
};
|
|
768
|
-
}
|
|
769
|
-
/**
|
|
770
|
-
* Generate clean hook name from parsed components
|
|
771
|
-
*/
|
|
772
|
-
generateNameFromParsed(parsed, endpoint) {
|
|
773
|
-
// Special cases first
|
|
774
|
-
if (parsed.prefix === 'login')
|
|
775
|
-
return 'login';
|
|
776
|
-
if (parsed.prefix === 'logout')
|
|
777
|
-
return 'logout';
|
|
778
|
-
// Handle compound GET operations (e.g., get_health_status, get_current_user_info)
|
|
779
|
-
if (parsed.prefix && parsed.prefix.startsWith('get_') && parsed.prefix.includes('_')) {
|
|
780
|
-
const withoutGet = parsed.prefix.substring(4); // Remove "get_"
|
|
781
|
-
// Return the compound name without "get_" prefix
|
|
782
|
-
if (withoutGet === 'health_status' || withoutGet === 'current_user_info') {
|
|
783
|
-
return withoutGet;
|
|
784
|
-
}
|
|
785
|
-
}
|
|
786
|
-
// Handle custom actions with meaningful prefixes
|
|
787
|
-
if (parsed.prefix && this.isMeaningfulPrefix(parsed.prefix, parsed.resources)) {
|
|
788
|
-
return this.formatWithPrefix(parsed);
|
|
789
|
-
}
|
|
790
|
-
// Standard REST conventions
|
|
791
|
-
return this.formatStandardOperation(parsed, endpoint);
|
|
792
|
-
}
|
|
793
|
-
/**
|
|
794
|
-
* Check if prefix adds meaningful context
|
|
795
|
-
*/
|
|
796
|
-
isMeaningfulPrefix(prefix, resources) {
|
|
797
|
-
const action = prefix.split('_')[0];
|
|
798
|
-
// Not meaningful if it just repeats the resource
|
|
799
|
-
if (prefix === resources.primary)
|
|
800
|
-
return false;
|
|
801
|
-
if (prefix === `get_${resources.primary}`)
|
|
802
|
-
return false;
|
|
803
|
-
if (prefix === `list_${resources.primary}`)
|
|
804
|
-
return false;
|
|
805
|
-
// Meaningful if it's a custom action
|
|
806
|
-
return ['assign', 'reassign', 'verify', 'validate', 'sync', 'refresh'].includes(action);
|
|
807
|
-
}
|
|
808
|
-
/**
|
|
809
|
-
* Format name with meaningful prefix
|
|
810
|
-
*/
|
|
811
|
-
formatWithPrefix(parsed) {
|
|
812
|
-
const { prefix, resources, originalId, isCustomAction, customActionName } = parsed;
|
|
813
|
-
const prefixParts = prefix.split('_');
|
|
814
|
-
const action = prefixParts[0];
|
|
815
|
-
const subject = prefixParts.slice(1).join('_');
|
|
816
|
-
// Special handling for custom actions
|
|
817
|
-
if (isCustomAction && customActionName) {
|
|
818
|
-
// For reassign_budget on transactions
|
|
819
|
-
if (action === 'reassign' && subject === 'budget') {
|
|
820
|
-
return `reassign_${this.singularize(resources.primary)}_budget`;
|
|
821
|
-
}
|
|
822
|
-
}
|
|
823
|
-
// Handle deduplication - don't repeat if subject matches sub-resource
|
|
824
|
-
if (subject && resources.sub.length > 0) {
|
|
825
|
-
const subResource = resources.sub[0];
|
|
826
|
-
// If subject matches the sub-resource, don't duplicate
|
|
827
|
-
if (subject === subResource || subject === this.pluralize(subResource)) {
|
|
828
|
-
return `${action}_${this.singularize(resources.primary)}_${subResource}`;
|
|
829
|
-
}
|
|
830
|
-
}
|
|
831
|
-
// Standard format: action_resource_subresource
|
|
832
|
-
if (resources.sub.length > 0 && !isCustomAction) {
|
|
833
|
-
return `${action}_${this.singularize(resources.primary)}_${resources.sub[0]}`;
|
|
834
|
-
}
|
|
835
|
-
return `${action}_${this.singularize(resources.primary)}`;
|
|
836
|
-
}
|
|
837
|
-
/**
|
|
838
|
-
* Format standard REST operation
|
|
839
|
-
*/
|
|
840
|
-
formatStandardOperation(parsed, endpoint) {
|
|
841
|
-
const { resources, method } = parsed;
|
|
842
|
-
const hasParams = endpoint.path.includes('{');
|
|
843
|
-
const isListOperation = method === 'get' && !hasParams;
|
|
844
|
-
// Handle sub-resources
|
|
845
|
-
if (resources.sub.length > 0) {
|
|
846
|
-
const primary = this.singularize(resources.primary);
|
|
847
|
-
const sub = resources.sub[0];
|
|
848
|
-
switch (method) {
|
|
849
|
-
case 'get':
|
|
850
|
-
return isListOperation ? `${primary}_${this.pluralize(sub)}` : `${primary}_${sub}`;
|
|
851
|
-
case 'post':
|
|
852
|
-
return `create_${primary}_${this.singularize(sub)}`;
|
|
853
|
-
case 'put':
|
|
854
|
-
case 'patch':
|
|
855
|
-
return `set_${primary}_${sub}`;
|
|
856
|
-
case 'delete':
|
|
857
|
-
return `remove_${primary}_${sub}`;
|
|
858
|
-
}
|
|
859
|
-
}
|
|
860
|
-
// Handle primary resource only
|
|
861
|
-
switch (method) {
|
|
862
|
-
case 'get':
|
|
863
|
-
return isListOperation ? this.pluralize(resources.primary) : this.singularize(resources.primary);
|
|
864
|
-
case 'post':
|
|
865
|
-
return `create_${this.singularize(resources.primary)}`;
|
|
866
|
-
case 'put':
|
|
867
|
-
case 'patch':
|
|
868
|
-
return `update_${this.singularize(resources.primary)}`;
|
|
869
|
-
case 'delete':
|
|
870
|
-
return `delete_${this.singularize(resources.primary)}`;
|
|
871
|
-
default:
|
|
872
|
-
return this.singularize(resources.primary);
|
|
873
|
-
}
|
|
874
|
-
}
|
|
875
|
-
generateCleanName(endpoint) {
|
|
876
|
-
const pathParts = endpoint.path
|
|
877
|
-
.split('/')
|
|
878
|
-
.filter(part => part && !part.startsWith('{'));
|
|
879
|
-
if (pathParts.length === 0)
|
|
880
|
-
return endpoint.method;
|
|
881
|
-
// Get the main resource (usually the last non-parameter segment)
|
|
882
|
-
const resource = pathParts[pathParts.length - 1];
|
|
883
|
-
const cleanResource = resource.replace(/-/g, '_');
|
|
884
|
-
// Check if it's a custom action (last segment after a parameter)
|
|
885
|
-
const segments = endpoint.path.split('/');
|
|
886
|
-
const lastSegment = segments[segments.length - 1];
|
|
887
|
-
const hasCustomAction = !lastSegment.startsWith('{') && segments[segments.length - 2]?.startsWith('{');
|
|
888
|
-
if (hasCustomAction) {
|
|
889
|
-
// Custom action: use resource + action
|
|
890
|
-
const mainResource = pathParts[pathParts.length - 2] || pathParts[pathParts.length - 1];
|
|
891
|
-
const action = lastSegment.replace(/-/g, '_');
|
|
892
|
-
return `${mainResource}_${action}`;
|
|
893
|
-
}
|
|
894
|
-
// For nested resources (e.g., /categories/{id}/subcategories),
|
|
895
|
-
// just use the last resource name
|
|
896
|
-
if (pathParts.length > 2 && segments.some(s => s.startsWith('{'))) {
|
|
897
|
-
// This is a nested resource, just use the last part
|
|
898
|
-
return cleanResource;
|
|
899
|
-
}
|
|
900
|
-
// Standard CRUD operations
|
|
901
|
-
switch (endpoint.method) {
|
|
902
|
-
case 'get':
|
|
903
|
-
// Check if it's a list or single resource
|
|
904
|
-
const isList = !endpoint.path.includes('{');
|
|
905
|
-
// Only pluralize if it's a list and not already plural
|
|
906
|
-
if (isList && !cleanResource.endsWith('s') && !cleanResource.endsWith('ies')) {
|
|
907
|
-
return this.pluralize(cleanResource);
|
|
908
|
-
}
|
|
909
|
-
return cleanResource;
|
|
910
|
-
case 'post':
|
|
911
|
-
return `create_${cleanResource}`;
|
|
912
|
-
case 'put':
|
|
913
|
-
case 'patch':
|
|
914
|
-
return `update_${cleanResource}`;
|
|
915
|
-
case 'delete':
|
|
916
|
-
return `delete_${cleanResource}`;
|
|
917
|
-
default:
|
|
918
|
-
return `${endpoint.method}_${cleanResource}`;
|
|
919
|
-
}
|
|
920
|
-
}
|
|
921
|
-
pluralize(word) {
|
|
922
|
-
// Don't pluralize if already plural
|
|
923
|
-
if (word.endsWith('s') && !word.endsWith('ss') && !word.endsWith('us') && !word.endsWith('is')) {
|
|
924
|
-
return word;
|
|
925
|
-
}
|
|
926
|
-
// Simple pluralization rules
|
|
927
|
-
if (word.endsWith('y') && !['ay', 'ey', 'iy', 'oy', 'uy'].includes(word.slice(-2))) {
|
|
928
|
-
return word.slice(0, -1) + 'ies';
|
|
929
|
-
}
|
|
930
|
-
if (word.endsWith('ss') || word.endsWith('x') || word.endsWith('ch') || word.endsWith('sh')) {
|
|
931
|
-
return word + 'es';
|
|
932
|
-
}
|
|
933
|
-
if (word.endsWith('us')) {
|
|
934
|
-
return word.slice(0, -2) + 'i';
|
|
935
|
-
}
|
|
936
|
-
if (word.endsWith('is')) {
|
|
937
|
-
return word.slice(0, -2) + 'es';
|
|
938
|
-
}
|
|
939
|
-
return word + 's';
|
|
940
|
-
}
|
|
941
|
-
singularize(word) {
|
|
942
|
-
// Simple singularization rules
|
|
943
|
-
if (word.endsWith('ies')) {
|
|
944
|
-
return word.slice(0, -3) + 'y';
|
|
945
|
-
}
|
|
946
|
-
if (word.endsWith('ses') || word.endsWith('xes') || word.endsWith('ches') || word.endsWith('shes')) {
|
|
947
|
-
return word.slice(0, -2);
|
|
948
|
-
}
|
|
949
|
-
if (word.endsWith('s') && !word.endsWith('ss')) {
|
|
950
|
-
return word.slice(0, -1);
|
|
951
|
-
}
|
|
952
|
-
return word;
|
|
953
|
-
}
|
|
954
|
-
hasRequiredParams(endpoint) {
|
|
955
|
-
return endpoint.parameters.some(p => p.required) ||
|
|
956
|
-
endpoint.parameters.some(p => p.in === 'path');
|
|
957
|
-
}
|
|
958
|
-
generateParamType(endpoint) {
|
|
959
|
-
const pathParams = endpoint.parameters.filter(p => p.in === 'path');
|
|
960
|
-
const queryParams = endpoint.parameters.filter(p => p.in === 'query');
|
|
961
|
-
const properties = [];
|
|
962
|
-
pathParams.forEach(param => {
|
|
963
|
-
properties.push(`${param.name}: ${this.getParameterType(param)}`);
|
|
964
|
-
});
|
|
965
|
-
queryParams.forEach(param => {
|
|
966
|
-
const optional = param.required ? '' : '?';
|
|
967
|
-
properties.push(`${param.name}${optional}: ${this.getParameterType(param)}`);
|
|
968
|
-
});
|
|
969
|
-
return `{ ${properties.join('; ')} }`;
|
|
970
|
-
}
|
|
971
|
-
generateMutationType(endpoint) {
|
|
972
|
-
const hasPathParams = endpoint.parameters.some(p => p.in === 'path');
|
|
973
|
-
if (hasPathParams) {
|
|
974
|
-
const pathType = this.generateParamType(endpoint);
|
|
975
|
-
return `{ pathParams: ${pathType}; [key: string]: any }`;
|
|
976
|
-
}
|
|
977
|
-
return '{ [key: string]: any }';
|
|
978
|
-
}
|
|
979
|
-
getParameterType(param) {
|
|
980
|
-
switch (param.schema.type) {
|
|
981
|
-
case 'string': return 'string';
|
|
982
|
-
case 'number':
|
|
983
|
-
case 'integer': return 'number';
|
|
984
|
-
case 'boolean': return 'boolean';
|
|
985
|
-
default: return 'any';
|
|
986
|
-
}
|
|
987
|
-
}
|
|
988
|
-
isListEndpoint(endpoint) {
|
|
989
|
-
// Only GET requests can be list endpoints
|
|
990
|
-
if (endpoint.method.toLowerCase() !== 'get')
|
|
991
|
-
return false;
|
|
992
|
-
// If it has path parameters, it's likely fetching a single resource
|
|
993
|
-
if (endpoint.path.includes('{'))
|
|
994
|
-
return false;
|
|
995
|
-
// Check if the response is an array
|
|
996
|
-
if (endpoint.responses?.['200']?.schema?.type === 'array')
|
|
997
|
-
return true;
|
|
998
|
-
// Check if summary/description indicates it's a list
|
|
999
|
-
const description = `${endpoint.summary || ''} ${endpoint.description || ''}`.toLowerCase();
|
|
1000
|
-
return description.includes('list') ||
|
|
1001
|
-
description.includes('get all') ||
|
|
1002
|
-
description.includes('fetch all');
|
|
1003
|
-
}
|
|
1004
|
-
groupEndpointsByResource(endpoints) {
|
|
1005
|
-
const groups = {};
|
|
1006
|
-
for (const endpoint of endpoints) {
|
|
1007
|
-
const resource = endpoint.tags?.[0] || 'default';
|
|
1008
|
-
if (!groups[resource]) {
|
|
1009
|
-
groups[resource] = [];
|
|
1010
|
-
}
|
|
1011
|
-
groups[resource].push(endpoint);
|
|
1012
|
-
}
|
|
1013
|
-
return groups;
|
|
1014
|
-
}
|
|
1015
|
-
getRelatedQueryTags(endpoint) {
|
|
1016
|
-
const resource = endpoint.tags?.[0] || 'default';
|
|
1017
|
-
return [resource, 'all'];
|
|
1018
|
-
}
|
|
1019
|
-
camelCase(str) {
|
|
1020
|
-
return str.replace(/[-_](.)/g, (_, char) => char.toUpperCase())
|
|
1021
|
-
.replace(/^./, char => char.toLowerCase());
|
|
1022
|
-
}
|
|
1023
|
-
capitalize(str) {
|
|
1024
|
-
// Convert snake_case to PascalCase
|
|
1025
|
-
return str.split('_')
|
|
1026
|
-
.map(part => part.charAt(0).toUpperCase() + part.slice(1).toLowerCase())
|
|
1027
|
-
.join('');
|
|
1028
|
-
}
|
|
1029
|
-
getMethodPrefix(method) {
|
|
1030
|
-
const prefixes = {
|
|
1031
|
-
post: 'create',
|
|
1032
|
-
put: 'update',
|
|
1033
|
-
patch: 'update',
|
|
1034
|
-
delete: 'delete'
|
|
1035
|
-
};
|
|
1036
|
-
return prefixes[method.toLowerCase()] || method.toLowerCase();
|
|
1037
|
-
}
|
|
1038
|
-
removeDuplicateSegments(operationName) {
|
|
1039
|
-
const parts = operationName.split('_');
|
|
1040
|
-
const seen = new Set();
|
|
1041
|
-
const result = [];
|
|
1042
|
-
for (const part of parts) {
|
|
1043
|
-
const lower = part.toLowerCase();
|
|
1044
|
-
if (!seen.has(lower)) {
|
|
1045
|
-
seen.add(lower);
|
|
1046
|
-
result.push(part);
|
|
1047
|
-
}
|
|
1048
|
-
}
|
|
1049
|
-
return result.join('_');
|
|
1050
|
-
}
|
|
1051
|
-
}
|
|
1052
|
-
exports.ReactHookGenerator = ReactHookGenerator;
|
|
1053
|
-
// Factory function
|
|
1054
|
-
async function generateHooks(parsedAPI, options) {
|
|
1055
|
-
const generator = new ReactHookGenerator(options);
|
|
1056
|
-
return generator.generate(parsedAPI);
|
|
1057
|
-
}
|