@mediacubeco/expo-template-fsd 2.3.0 → 2.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.claude/commands/git-commit.md +164 -0
- package/.claude/rules/architecture.md +38 -0
- package/.claude/rules/{prettier-eslint-typescript.mdc → prettier-eslint-typescript.md} +5 -10
- package/.claude/settings.json +2 -2
- package/.claude/skills/api/SKILL.md +362 -0
- package/.claude/skills/api/references/client/overview.md +106 -0
- package/.claude/skills/api/references/hooks/index.ts +3 -0
- package/.claude/skills/api/references/hooks/use-api-health.ts +25 -0
- package/.claude/skills/api/references/hooks/use-api-post.ts +46 -0
- package/.claude/skills/api/references/hooks/use-api-posts.ts +24 -0
- package/.claude/skills/api/references/mock/post.mock.ts +29 -0
- package/.claude/skills/{generate-api-model/references → api/references/model}/entities/common.ts +5 -2
- package/.claude/skills/api/references/model/resources/common.ts +9 -0
- package/.claude/skills/api/references/queries/health.ts +14 -0
- package/.claude/skills/api/references/queries/index.ts +2 -0
- package/.claude/skills/api/references/queries/post.ts +23 -0
- package/.claude/skills/api/references/repository/health/health.ts +11 -0
- package/.claude/skills/api/references/repository/health/health.types.ts +25 -0
- package/.claude/skills/api/references/repository/health/index.ts +2 -0
- package/.claude/skills/api/references/repository/post/index.ts +9 -0
- package/.claude/skills/api/references/repository/post/post.ts +34 -0
- package/.claude/skills/api/references/repository/post/post.types.ts +61 -0
- package/.claude/skills/code-style/SKILL.md +1025 -1
- package/.claude/skills/code-style/references/components/payout-speed-option/index.ts +2 -0
- package/.claude/skills/code-style/references/components/payout-speed-option/payout-speed-option.styles.ts +76 -0
- package/.claude/skills/code-style/references/components/payout-speed-option/payout-speed-option.tsx +58 -0
- package/.claude/skills/code-style/references/components/payout-speed-option/payout-speed-option.types.ts +22 -0
- package/.claude/skills/code-style/references/components/post/index.ts +2 -0
- package/.claude/skills/code-style/references/components/post/post.styles.ts +19 -0
- package/.claude/skills/code-style/references/components/post/post.tsx +21 -0
- package/.claude/skills/code-style/references/components/post/post.types.ts +9 -0
- package/.claude/skills/code-style/references/components/wrap/index.ts +2 -0
- package/.claude/skills/code-style/references/components/wrap/wrap.styles.ts +15 -0
- package/.claude/skills/code-style/references/components/wrap/wrap.tsx +31 -0
- package/.claude/skills/code-style/references/components/wrap/wrap.types.ts +10 -0
- package/.claude/skills/code-style/references/hooks/use-posts.ts +37 -0
- package/.claude/skills/code-style/references/pages/post/index.ts +4 -0
- package/.claude/skills/code-style/references/pages/post/post-details/index.ts +1 -0
- package/.claude/skills/code-style/references/pages/post/post-details/post-details.tsx +13 -0
- package/.claude/skills/code-style/references/pages/post/post-guide/index.ts +1 -0
- package/.claude/skills/code-style/references/pages/post/post-guide/post-guide.tsx +17 -0
- package/.claude/skills/code-style/references/pages/post/post-list/index.ts +1 -0
- package/.claude/skills/code-style/references/pages/post/post-list/post-list.styles.ts +17 -0
- package/.claude/skills/code-style/references/pages/post/post-list/post-list.tsx +25 -0
- package/.claude/skills/code-style/references/pages/post/post-share/index.ts +1 -0
- package/.claude/skills/code-style/references/pages/post/post-share/post-share.tsx +13 -0
- package/.claude/skills/code-style/references/routes/(stack)/_layout.tsx +18 -0
- package/.claude/skills/code-style/references/routes/(stack)/details.tsx +8 -0
- package/.claude/skills/code-style/references/routes/(stack)/guide.tsx +8 -0
- package/.claude/skills/code-style/references/routes/(stack)/index.tsx +8 -0
- package/.claude/skills/code-style/references/routes/(stack)/share.tsx +8 -0
- package/.claude/skills/code-style/references/routes/(tabs)/(post-details)/index.tsx +8 -0
- package/.claude/skills/code-style/references/routes/(tabs)/(post-list)/index.tsx +8 -0
- package/.claude/skills/code-style/references/routes/(tabs)/_layout.tsx +50 -0
- package/.claude/skills/code-style/references/routes/_app.tsx +20 -0
- package/.claude/skills/code-style/references/routes/guide.tsx +8 -0
- package/.claude/skills/code-style/references/routes/share.tsx +8 -0
- package/.claude/skills/code-style/references/store/use-post-draft-store.ts +62 -0
- package/.claude/skills/design-style/SKILL.md +320 -0
- package/.env +3 -1
- package/.env.example +3 -1
- package/CLAUDE.md +5 -11
- package/app.json +6 -3
- package/axios.d.ts +5 -0
- package/env.d.ts +3 -1
- package/package.json +33 -40
- package/patches/react-native-screens+4.25.2.patch +118 -0
- package/react-query.d.ts +13 -0
- package/src/app/(root)/(home)/_layout.tsx +2 -2
- package/src/app/(root)/(home)/index.tsx +2 -2
- package/src/app/(root)/(settings)/_layout.tsx +2 -2
- package/src/app/(root)/(settings)/index.tsx +2 -2
- package/src/app/(root)/_layout.tsx +35 -32
- package/src/pages/home/home-main.tsx +3 -7
- package/src/pages/settings/settings-main.tsx +3 -7
- package/src/shared/assets/fonts/index.ts +3 -3
- package/src/shared/assets/fonts/sf-pro-text-bold.ttf +0 -0
- package/src/shared/assets/fonts/sf-pro-text-regular.ttf +0 -0
- package/src/shared/assets/fonts/sf-pro-text-semibold.ttf +0 -0
- package/src/shared/assets/icons/back.tsx +21 -0
- package/src/shared/assets/icons/close.tsx +21 -0
- package/src/shared/assets/icons/common.ts +8 -0
- package/src/shared/assets/icons/default.tsx +44 -0
- package/src/shared/assets/icons/index.ts +13 -1
- package/src/shared/assets/icons/refresh.tsx +23 -0
- package/src/shared/assets/icons/share.tsx +38 -0
- package/src/shared/assets/icons/type.ts +7 -0
- package/src/shared/assets/translations/index.ts +4 -4
- package/src/shared/constants/config.ts +13 -0
- package/src/shared/constants/environment.ts +16 -4
- package/src/shared/constants/index.ts +1 -0
- package/src/shared/hooks/index.ts +1 -4
- package/src/shared/hooks/use-compose.ts +23 -0
- package/src/shared/lib/api/api.client.ts +157 -0
- package/src/shared/lib/api/api.provider.tsx +14 -36
- package/src/shared/lib/api/api.ts +1 -5
- package/src/shared/lib/api/api.types.ts +6 -3
- package/src/shared/lib/api/hooks/index.ts +1 -0
- package/src/shared/lib/api/index.ts +2 -3
- package/src/shared/lib/api/models/api-instance/api-instance.client.ts +50 -0
- package/src/shared/lib/api/models/api-instance/api-instance.ts +30 -82
- package/src/shared/lib/api/models/api-instance/api-instance.types.ts +16 -18
- package/src/shared/lib/api/models/api-instance/api-instance.utils.ts +13 -20
- package/src/shared/lib/api/models/api-instance/index.ts +3 -0
- package/src/shared/lib/api/queries/index.ts +1 -0
- package/src/shared/lib/api/repositories/index.ts +1 -1
- package/src/shared/lib/localization/constants/index.ts +16 -5
- package/src/shared/lib/localization/index.ts +5 -1
- package/src/shared/lib/navigation/hooks/index.ts +8 -3
- package/src/shared/{hooks/use-breakpoints.ts → lib/navigation/hooks/use-navigation-breakpoints.ts} +2 -5
- package/src/shared/lib/navigation/hooks/use-navigation-dimensions.ts +12 -0
- package/src/shared/lib/navigation/hooks/use-navigation-options.tsx +175 -0
- package/src/shared/lib/navigation/hooks/{use-navigation.ts → use-navigation-route.ts} +2 -2
- package/src/shared/lib/navigation/hooks/use-navigation-safe-area.ts +61 -0
- package/src/shared/lib/navigation/hooks/use-navigation-tabs-native.ts +10 -0
- package/src/shared/lib/navigation/hooks/use-navigation-tabs.tsx +10 -0
- package/src/shared/lib/navigation/hooks/use-navigation-transition.ts +27 -0
- package/src/shared/lib/navigation/index.ts +11 -4
- package/src/shared/lib/navigation/navigation-tabs-native.context.tsx +5 -0
- package/src/shared/lib/navigation/navigation-tabs-native.provider.tsx +17 -0
- package/src/shared/lib/navigation/navigation-tabs.context.tsx +10 -0
- package/src/shared/lib/navigation/navigation-tabs.provider.tsx +22 -0
- package/src/shared/lib/navigation/navigation.provider.tsx +6 -1
- package/src/shared/lib/storage/index.ts +1 -1
- package/src/shared/lib/storage/storage.provider.tsx +4 -0
- package/src/shared/lib/storage/storage.ts +29 -25
- package/src/shared/lib/theme/constants/animations.ts +26 -0
- package/src/shared/lib/theme/constants/colors.ts +336 -43
- package/src/shared/lib/theme/constants/delays.ts +1 -1
- package/src/shared/lib/theme/constants/durations.ts +1 -1
- package/src/shared/lib/theme/constants/fonts.ts +2 -1
- package/src/shared/lib/theme/constants/index.ts +42 -20
- package/src/shared/lib/theme/constants/shadows.ts +7 -25
- package/src/shared/lib/theme/constants/sizes.ts +11 -2
- package/src/shared/lib/theme/constants/transparencies.ts +1 -1
- package/src/shared/lib/theme/hooks/use-theme-setup.ts +3 -1
- package/src/shared/lib/theme/index.ts +10 -1
- package/src/shared/lib/theme/theme.provider.tsx +45 -19
- package/src/shared/lib/theme/theme.scope.tsx +43 -0
- package/src/shared/lib/theme/theme.types.ts +15 -3
- package/src/shared/lib/theme/utils/color.ts +81 -0
- package/src/shared/lib/theme/utils/index.ts +2 -0
- package/src/shared/lib/theme/utils/snapshot.ts +17 -0
- package/src/shared/lib/theme/utils/storage.ts +5 -2
- package/src/shared/services/browser/browser.ts +66 -0
- package/src/shared/services/browser/index.ts +1 -0
- package/src/shared/services/cookies/cookies.ts +73 -0
- package/src/shared/services/cookies/index.ts +1 -0
- package/src/shared/services/index.ts +5 -0
- package/src/shared/services/linking/index.ts +1 -0
- package/src/shared/services/linking/linking.ts +22 -0
- package/src/shared/services/share/index.ts +1 -0
- package/src/shared/services/share/share.ts +28 -0
- package/src/shared/services/universal-links/index.ts +104 -0
- package/src/shared/services/universal-links/universal-links.ts +25 -0
- package/src/shared/services/universal-links/universal-links.types.ts +5 -0
- package/src/shared/ui/atoms/blur/blur.tsx +9 -4
- package/src/shared/ui/atoms/blur/blur.types.ts +1 -1
- package/src/shared/ui/atoms/blur-progress/blur-progress.styles.ts +16 -0
- package/src/shared/ui/atoms/blur-progress/blur-progress.tsx +30 -0
- package/src/shared/ui/atoms/blur-progress/blur-progress.types.tsx +5 -0
- package/src/shared/ui/atoms/blur-progress/index.ts +1 -0
- package/src/shared/ui/atoms/glass/glass.tsx +13 -5
- package/src/shared/ui/atoms/glass/glass.types.ts +1 -1
- package/src/shared/ui/atoms/icon/icon.styles.ts +82 -0
- package/src/shared/ui/atoms/icon/icon.tsx +21 -0
- package/src/shared/ui/atoms/icon/icon.types.ts +23 -0
- package/src/shared/ui/atoms/icon/index.ts +2 -0
- package/src/shared/ui/atoms/index.ts +7 -0
- package/src/shared/ui/atoms/skeleton/index.ts +2 -0
- package/src/shared/ui/atoms/skeleton/skeleton.styles.ts +69 -0
- package/src/shared/ui/atoms/skeleton/skeleton.tsx +26 -0
- package/src/shared/ui/atoms/skeleton/skeleton.types.ts +9 -0
- package/src/shared/ui/atoms/spinner/index.ts +2 -0
- package/src/shared/ui/atoms/spinner/spinner.styles.ts +102 -0
- package/src/shared/ui/atoms/spinner/spinner.tsx +48 -0
- package/src/shared/ui/atoms/spinner/spinner.types.ts +25 -0
- package/src/shared/ui/atoms/text/index.ts +2 -0
- package/src/shared/ui/atoms/text/text.styles.ts +186 -0
- package/src/shared/ui/atoms/text/text.tsx +37 -0
- package/src/shared/ui/atoms/text/text.types.ts +35 -0
- package/src/shared/ui/atoms/touch/components/haptics/haptics.styles.ts +21 -0
- package/src/shared/ui/atoms/touch/components/haptics/haptics.tsx +28 -0
- package/src/shared/ui/atoms/touch/components/haptics/haptics.types.ts +17 -0
- package/src/shared/ui/atoms/touch/components/haptics/index.ts +2 -0
- package/src/shared/ui/atoms/touch/components/index.ts +3 -0
- package/src/shared/ui/atoms/touch/components/ripple/index.ts +2 -0
- package/src/shared/ui/atoms/touch/components/ripple/ripple.styles.ts +78 -0
- package/src/shared/ui/atoms/touch/components/ripple/ripple.tsx +29 -0
- package/src/shared/ui/atoms/touch/components/ripple/ripple.types.ts +17 -0
- package/src/shared/ui/atoms/touch/components/spring/index.ts +2 -0
- package/src/shared/ui/atoms/touch/components/spring/spring.styles.ts +31 -0
- package/src/shared/ui/atoms/touch/components/spring/spring.tsx +28 -0
- package/src/shared/ui/atoms/touch/components/spring/spring.types.ts +17 -0
- package/src/shared/ui/atoms/touch/index.ts +2 -0
- package/src/shared/ui/atoms/touch/touch.styles.ts +14 -0
- package/src/shared/ui/atoms/touch/touch.tsx +137 -0
- package/src/shared/ui/atoms/touch/touch.types.ts +27 -0
- package/src/shared/ui/atoms/visibility/index.ts +2 -0
- package/src/shared/ui/atoms/visibility/visibility.styles.ts +85 -0
- package/src/shared/ui/atoms/visibility/visibility.tsx +61 -0
- package/src/shared/ui/atoms/visibility/visibility.types.ts +34 -0
- package/src/shared/ui/molecules/keyboard-area/keyboard-area.styles.ts +11 -9
- package/src/shared/ui/molecules/keyboard-area/keyboard-area.tsx +3 -6
- package/src/shared/ui/molecules/refresh-control/refresh-control.tsx +3 -5
- package/src/shared/ui/molecules/refresh-control/refresh-control.types.ts +1 -1
- package/src/shared/ui/molecules/slider/components/indicator/components/dot/dot.styles.ts +41 -0
- package/src/shared/ui/molecules/slider/components/indicator/components/dot/dot.tsx +12 -0
- package/src/shared/ui/molecules/slider/components/indicator/components/dot/dot.types.ts +13 -0
- package/src/shared/ui/molecules/slider/components/indicator/components/dot/index.ts +2 -0
- package/src/shared/ui/molecules/slider/components/indicator/index.ts +2 -0
- package/src/shared/ui/molecules/slider/components/indicator/indicator.styles.ts +20 -0
- package/src/shared/ui/molecules/slider/components/indicator/indicator.tsx +22 -0
- package/src/shared/ui/molecules/slider/components/indicator/indicator.types.ts +10 -0
- package/src/shared/ui/molecules/slider/index.ts +3 -0
- package/src/shared/ui/molecules/slider/slider.styles.ts +68 -0
- package/src/shared/ui/molecules/slider/slider.tsx +64 -0
- package/src/shared/ui/molecules/slider/slider.types.ts +28 -0
- package/src/shared/ui/organisms/bar/bar.styles.ts +100 -0
- package/src/shared/ui/organisms/bar/bar.tsx +89 -0
- package/src/shared/ui/organisms/bar/bar.types.ts +49 -0
- package/src/shared/ui/organisms/bar/index.ts +2 -0
- package/src/shared/ui/organisms/bar-tab/bar-tab.tsx +9 -0
- package/src/shared/ui/organisms/bar-tab/bar-tab.types.ts +5 -0
- package/src/shared/ui/organisms/bar-tab/components/index.ts +1 -0
- package/src/shared/ui/organisms/bar-tab/components/tab/index.ts +2 -0
- package/src/shared/ui/organisms/bar-tab/components/tab/tab.styles.ts +21 -0
- package/src/shared/ui/organisms/bar-tab/components/tab/tab.tsx +18 -0
- package/src/shared/ui/organisms/bar-tab/components/tab/tab.types.ts +5 -0
- package/src/shared/ui/organisms/bar-tab/index.ts +2 -0
- package/src/shared/ui/organisms/bar-tab-navigation/bar-tab-navigation.styles.ts +22 -0
- package/src/shared/ui/organisms/bar-tab-navigation/bar-tab-navigation.tsx +66 -0
- package/src/shared/ui/organisms/bar-tab-navigation/bar-tab-navigation.types.ts +5 -0
- package/src/shared/ui/organisms/bar-tab-navigation/components/index.ts +1 -0
- package/src/shared/ui/organisms/bar-tab-navigation/components/tab-navigation/index.ts +2 -0
- package/src/shared/ui/organisms/bar-tab-navigation/components/tab-navigation/tab-navigation.styles.ts +56 -0
- package/src/shared/ui/organisms/bar-tab-navigation/components/tab-navigation/tab-navigation.tsx +30 -0
- package/src/shared/ui/organisms/bar-tab-navigation/components/tab-navigation/tab-navigation.types.ts +7 -0
- package/src/shared/ui/organisms/bar-tab-navigation/index.ts +2 -0
- package/src/shared/ui/organisms/index.ts +4 -1
- package/src/shared/ui/organisms/slider/components/indicator/components/dot/dot.styles.ts +41 -0
- package/src/shared/ui/organisms/slider/components/indicator/components/dot/dot.tsx +12 -0
- package/src/shared/ui/organisms/slider/components/indicator/components/dot/dot.types.ts +13 -0
- package/src/shared/ui/organisms/slider/components/indicator/components/dot/index.ts +2 -0
- package/src/shared/ui/organisms/slider/components/indicator/index.ts +2 -0
- package/src/shared/ui/organisms/slider/components/indicator/indicator.styles.ts +20 -0
- package/src/shared/ui/organisms/slider/components/indicator/indicator.tsx +22 -0
- package/src/shared/ui/organisms/slider/components/indicator/indicator.types.ts +10 -0
- package/src/shared/ui/organisms/slider/index.ts +3 -0
- package/src/shared/ui/organisms/slider/slider.styles.ts +68 -0
- package/src/shared/ui/organisms/slider/slider.tsx +64 -0
- package/src/shared/ui/organisms/slider/slider.types.ts +28 -0
- package/src/shared/ui/templates/index.ts +3 -0
- package/src/shared/ui/templates/modal-container/index.ts +13 -0
- package/src/shared/ui/templates/modal-container/modal-container-list.tsx +45 -0
- package/src/shared/ui/templates/modal-container/modal-container-scroll.tsx +66 -0
- package/src/shared/ui/templates/modal-container/modal-container-section-list.tsx +46 -0
- package/src/shared/ui/templates/modal-container/modal-container.hooks.tsx +172 -0
- package/src/shared/ui/templates/modal-container/modal-container.styles.ts +121 -0
- package/src/shared/ui/templates/modal-container/modal-container.types.ts +69 -0
- package/src/shared/ui/templates/screen-container/index.ts +1 -1
- package/src/shared/ui/templates/screen-container/screen-container-list.tsx +28 -10
- package/src/shared/ui/templates/screen-container/screen-container-scroll.tsx +28 -10
- package/src/shared/ui/templates/screen-container/screen-container-section-list.tsx +29 -11
- package/src/shared/ui/templates/screen-container/screen-container.hooks.tsx +79 -8
- package/src/shared/ui/templates/screen-container/screen-container.styles.ts +105 -15
- package/src/shared/ui/templates/screen-container/screen-container.types.tsx +34 -7
- package/src/shared/ui/templates/screen-header/components/index.ts +6 -0
- package/src/shared/ui/templates/screen-header/components/screen-header-description/index.ts +2 -0
- package/src/shared/ui/templates/screen-header/components/screen-header-description/screen-header-description.tsx +15 -0
- package/src/shared/ui/templates/screen-header/components/screen-header-description/screen-header-description.types.ts +11 -0
- package/src/shared/ui/templates/screen-header/components/screen-header-icon/index.ts +2 -0
- package/src/shared/ui/templates/screen-header/components/screen-header-icon/screen-header-icon.styles.ts +44 -0
- package/src/shared/ui/templates/screen-header/components/screen-header-icon/screen-header-icon.tsx +65 -0
- package/src/shared/ui/templates/screen-header/components/screen-header-icon/screen-header-icon.types.ts +14 -0
- package/src/shared/ui/templates/screen-header/components/screen-header-icon-back/index.ts +2 -0
- package/src/shared/ui/templates/screen-header/components/screen-header-icon-back/screen-header-icon-back.tsx +17 -0
- package/src/shared/ui/templates/screen-header/components/screen-header-icon-back/screen-header-icon-back.types.ts +6 -0
- package/src/shared/ui/templates/screen-header/components/screen-header-icon-close/index.ts +2 -0
- package/src/shared/ui/templates/screen-header/components/screen-header-icon-close/screen-header-icon-close.tsx +27 -0
- package/src/shared/ui/templates/screen-header/components/screen-header-icon-close/screen-header-icon-close.types.ts +10 -0
- package/src/shared/ui/templates/screen-header/components/screen-header-info/index.ts +2 -0
- package/src/shared/ui/templates/screen-header/components/screen-header-info/screen-header-info.tsx +15 -0
- package/src/shared/ui/templates/screen-header/components/screen-header-info/screen-header-info.types.ts +10 -0
- package/src/shared/ui/templates/screen-header/components/screen-header-title/index.ts +2 -0
- package/src/shared/ui/templates/screen-header/components/screen-header-title/screen-header-title.tsx +19 -0
- package/src/shared/ui/templates/screen-header/components/screen-header-title/screen-header-title.types.ts +13 -0
- package/src/shared/ui/templates/screen-header/index.ts +3 -0
- package/src/shared/ui/templates/screen-header/screen-header.styles.ts +49 -0
- package/src/shared/ui/templates/screen-header/screen-header.tsx +26 -0
- package/src/shared/ui/templates/screen-header/screen-header.types.ts +15 -0
- package/src/shared/ui/templates/web-container/index.ts +2 -0
- package/src/shared/ui/templates/web-container/web-container.styles.ts +34 -0
- package/src/shared/ui/templates/web-container/web-container.tsx +172 -0
- package/src/shared/ui/templates/web-container/web-container.types.ts +21 -0
- package/.claude/rules/app-routing.mdc +0 -47
- package/.claude/rules/exports-at-end.mdc +0 -55
- package/.claude/rules/kebab-case-naming.mdc +0 -29
- package/.claude/rules/mediacubeco-packages.mdc +0 -56
- package/.claude/skills/generate-api-model/SKILL.md +0 -230
- package/.claude/skills/generate-api-model/references/resources/common.ts +0 -8
- package/.claude/skills/generate-api-model-mock/SKILL.md +0 -56
- package/.claude/skills/git-commit/SKILL.md +0 -139
- package/.gitignore +0 -34
- package/src/shared/assets/icons/like.tsx +0 -17
- package/src/shared/hooks/use-animated.ts +0 -200
- package/src/shared/hooks/use-mixins.ts +0 -36
- package/src/shared/hooks/use-safe-area.ts +0 -75
- package/src/shared/lib/api/repositories/auth/auth.ts +0 -23
- package/src/shared/lib/api/repositories/auth/auth.types.ts +0 -22
- package/src/shared/lib/api/repositories/auth/index.ts +0 -1
- package/src/shared/lib/navigation/hooks/use-navigation-native-tabs.ts +0 -10
- package/src/shared/lib/navigation/hooks/use-navigation-options.ts +0 -123
- package/src/shared/lib/navigation/navigation-native-tabs.context.tsx +0 -5
- package/src/shared/lib/navigation/navigation-native-tabs.provider.tsx +0 -12
- package/src/shared/lib/theme/constants/borders.ts +0 -8
- package/src/shared/lib/theme/constants/weights.ts +0 -13
- /package/.claude/skills/{generate-api-model/references → api/references/model}/entities/index.ts +0 -0
- /package/.claude/skills/{generate-api-model/references → api/references/model}/entities/post/index.ts +0 -0
- /package/.claude/skills/{generate-api-model/references → api/references/model}/entities/post/post-comment.ts +0 -0
- /package/.claude/skills/{generate-api-model/references → api/references/model}/entities/post/post.ts +0 -0
- /package/.claude/skills/{generate-api-model/references → api/references/model}/entities/user/index.ts +0 -0
- /package/.claude/skills/{generate-api-model/references → api/references/model}/entities/user/user-settings.ts +0 -0
- /package/.claude/skills/{generate-api-model/references → api/references/model}/entities/user/user-verification.ts +0 -0
- /package/.claude/skills/{generate-api-model/references → api/references/model}/entities/user/user.ts +0 -0
- /package/.claude/skills/{generate-api-model/references → api/references/model}/resources/index.ts +0 -0
- /package/.claude/skills/{generate-api-model/references → api/references/model}/resources/post/index.ts +0 -0
- /package/.claude/skills/{generate-api-model/references → api/references/model}/resources/post/post-comment.ts +0 -0
- /package/.claude/skills/{generate-api-model/references → api/references/model}/resources/post/post.ts +0 -0
- /package/.claude/skills/{generate-api-model/references → api/references/model}/resources/user/index.ts +0 -0
- /package/.claude/skills/{generate-api-model/references → api/references/model}/resources/user/user-settings.ts +0 -0
- /package/.claude/skills/{generate-api-model/references → api/references/model}/resources/user/user-verification.ts +0 -0
- /package/.claude/skills/{generate-api-model/references → api/references/model}/resources/user/user.ts +0 -0
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
# API infrastructure (shared, not per-domain)
|
|
2
|
+
|
|
3
|
+
These pieces exist **once** in the API lib. A new domain plugs into them — it
|
|
4
|
+
does not regenerate them. Read this so the per-domain code you generate fits the
|
|
5
|
+
machine around it, and so you know which shared files to touch.
|
|
6
|
+
|
|
7
|
+
## The transport: `ApiInstance`
|
|
8
|
+
|
|
9
|
+
Every repository extends `ApiInstance`, which owns `fetch`. Two things matter for
|
|
10
|
+
generated repositories:
|
|
11
|
+
|
|
12
|
+
- **Transport options.** Every request accepts `options?: { signal?, timeout? }`.
|
|
13
|
+
The domain `Config` types carry this through `ApiConfig<Config>`
|
|
14
|
+
(`Config & { options?: ApiInstanceOptions }`). Repository methods split it out,
|
|
15
|
+
mapping the camelCase fields into snake_case `params`/`body` by hand:
|
|
16
|
+
`async getX({ isActive, options })` → `this.get('/', { params: { is_active: isActive }, options })`.
|
|
17
|
+
This is why the `options`/`params` separation in the repository is mandatory —
|
|
18
|
+
forget it and an `AbortSignal` leaks into the query string.
|
|
19
|
+
- **Empty/error handling is centralized.** A 204 or empty body returns
|
|
20
|
+
`undefined`; non-2xx throws an `Error` whose `cause` is the `Response` (so the
|
|
21
|
+
status survives). The repository does not try/catch — errors propagate to React
|
|
22
|
+
Query. Repositories return the raw success payload unchanged; shaping into
|
|
23
|
+
`{ list }`/`{ item }` and the camelCase conversion both happen in the hook's `select`.
|
|
24
|
+
|
|
25
|
+
## Errors are handled in one place: `QueryCache.onError`
|
|
26
|
+
|
|
27
|
+
The `QueryClient` is built with a `QueryCache` whose `onError` is the single
|
|
28
|
+
funnel for every failed query (a future toast/Sentry hook lives here). It reads
|
|
29
|
+
`query.meta.silent` to skip noise. Consequence for generated code: **hooks and
|
|
30
|
+
repositories never log or swallow errors** — they let them throw. Per-query
|
|
31
|
+
suppression is `meta: { silent: true }`, nothing more.
|
|
32
|
+
|
|
33
|
+
`retry` skips 4xx (client errors don't heal on repeat) and retries the rest up to
|
|
34
|
+
twice, reading the status from the error's `cause`.
|
|
35
|
+
|
|
36
|
+
```ts
|
|
37
|
+
const queryClient = new QueryClient({
|
|
38
|
+
queryCache: new QueryCache({
|
|
39
|
+
onError: (error, query) => {
|
|
40
|
+
if (query.meta?.silent) {
|
|
41
|
+
return
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
ErrorHandler.capture(error, { signal: 'query', message: JSON.stringify(query.queryKey) })
|
|
45
|
+
},
|
|
46
|
+
}),
|
|
47
|
+
defaultOptions: {
|
|
48
|
+
queries: {
|
|
49
|
+
retry: (failureCount, error) => {
|
|
50
|
+
const status = getErrorStatus(error)
|
|
51
|
+
|
|
52
|
+
if (status !== undefined && status >= 400 && status < 500) {
|
|
53
|
+
return false
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
return failureCount < MAX_RETRY_COUNT
|
|
57
|
+
},
|
|
58
|
+
},
|
|
59
|
+
},
|
|
60
|
+
})
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
## Typed `meta`
|
|
64
|
+
|
|
65
|
+
`meta` is typed globally (module augmentation of `Register` in a root
|
|
66
|
+
`react-query.d.ts`), so `meta: { persist: true }` and `meta: { silent: true }`
|
|
67
|
+
are checked, not free-form:
|
|
68
|
+
|
|
69
|
+
```ts
|
|
70
|
+
type ApiQueryMeta = {
|
|
71
|
+
persist?: boolean
|
|
72
|
+
silent?: boolean
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
declare module '@tanstack/react-query' {
|
|
76
|
+
interface Register {
|
|
77
|
+
queryMeta: ApiQueryMeta
|
|
78
|
+
mutationMeta: ApiQueryMeta
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
```
|
|
82
|
+
|
|
83
|
+
- `persist: true` — the query is whitelisted for AsyncStorage/MMKV persistence
|
|
84
|
+
(survives restarts). Only set it on non-sensitive, slow-changing data.
|
|
85
|
+
- `silent: true` — `onError` ignores this query.
|
|
86
|
+
|
|
87
|
+
## Persistence and freshness
|
|
88
|
+
|
|
89
|
+
- Persistence is opt-in per query via `meta: { persist: true }`. Never persist
|
|
90
|
+
user-private data — the store is not encrypted.
|
|
91
|
+
- `staleTime` is opt-in. Slow-changing reference data (countries, languages,
|
|
92
|
+
labels) uses `staleTime: STALE_TIME` so it is not refetched on every mount.
|
|
93
|
+
Always-fresh data (status, feature flags, anything user-specific) omits it.
|
|
94
|
+
|
|
95
|
+
## Online + focus
|
|
96
|
+
|
|
97
|
+
`focusManager` (app foreground/background) and `onlineManager` (network via
|
|
98
|
+
`expo-network`) are wired once at module scope so `refetchOnReconnect` and
|
|
99
|
+
pause-while-offline work in React Native. Nothing per-domain here.
|
|
100
|
+
|
|
101
|
+
## What a NEW domain must touch in shared files
|
|
102
|
+
|
|
103
|
+
1. `api.ts` — register the repository singleton: `static postRepository = new PostRepository('/posts')` (URN is the plural route).
|
|
104
|
+
2. `constants/index.ts` — add the base query key: `POSTS: 'posts'` in `QUERY_KEYS`.
|
|
105
|
+
3. Barrels — `resources/index.ts`, `entities/index.ts`, `repositories/index.ts`, `queries/index.ts`, `hooks/index.ts` each get one re-export line (alphabetical).
|
|
106
|
+
4. Prefetch (optional) — if the domain is reference data shown on first screens, add `queryClient.prefetchQuery(postQueries.list())` to the startup prefetch.
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import { useQuery } from '@tanstack/react-query'
|
|
2
|
+
import { healthQueries } from '../queries'
|
|
3
|
+
import { type GetHealthResponse } from '../repositories'
|
|
4
|
+
|
|
5
|
+
// map-case: every field is optional, so the default answer is the empty wire object
|
|
6
|
+
const PLACEHOLDER_DATA: GetHealthResponse = {}
|
|
7
|
+
|
|
8
|
+
const selectHealth = (data: GetHealthResponse) => {
|
|
9
|
+
return {
|
|
10
|
+
item: {
|
|
11
|
+
maintenance: data.maintenance,
|
|
12
|
+
startAt: data.start_at,
|
|
13
|
+
},
|
|
14
|
+
}
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
const useApiHealth = () => {
|
|
18
|
+
return useQuery({
|
|
19
|
+
...healthQueries.detail(),
|
|
20
|
+
placeholderData: PLACEHOLDER_DATA,
|
|
21
|
+
select: selectHealth,
|
|
22
|
+
})
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
export { useApiHealth }
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import { useMutation, useQuery } from '@tanstack/react-query'
|
|
2
|
+
import { Api } from '../api'
|
|
3
|
+
import { queryClient } from '../api.client'
|
|
4
|
+
import { PostEntity } from '../entities'
|
|
5
|
+
import { postQueries } from '../queries'
|
|
6
|
+
import {
|
|
7
|
+
type CreatePostConfig,
|
|
8
|
+
type CreatePostResponse,
|
|
9
|
+
type GetPostResponse,
|
|
10
|
+
} from '../repositories'
|
|
11
|
+
|
|
12
|
+
const PLACEHOLDER_DATA: GetPostResponse = {
|
|
13
|
+
data: { is_skeleton: true },
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
const selectPost = (data: GetPostResponse) => {
|
|
17
|
+
return {
|
|
18
|
+
item: new PostEntity(data.data),
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
const selectPostCreate = (data: CreatePostResponse) => {
|
|
23
|
+
return {
|
|
24
|
+
item: new PostEntity(data.data),
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
const useApiPost = (id: PostEntity['id']) => {
|
|
29
|
+
return useQuery({
|
|
30
|
+
...postQueries.detail(id),
|
|
31
|
+
placeholderData: PLACEHOLDER_DATA,
|
|
32
|
+
select: selectPost,
|
|
33
|
+
})
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
const useApiPostCreate = () => {
|
|
37
|
+
return useMutation({
|
|
38
|
+
mutationFn: async (config: CreatePostConfig) =>
|
|
39
|
+
selectPostCreate(await Api.postRepository.createPost(config)),
|
|
40
|
+
onSettled: () => {
|
|
41
|
+
queryClient.invalidateQueries({ queryKey: postQueries.key })
|
|
42
|
+
},
|
|
43
|
+
})
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
export { useApiPost, useApiPostCreate }
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import { useQuery } from '@tanstack/react-query'
|
|
2
|
+
import { PostEntity } from '../entities'
|
|
3
|
+
import { postQueries } from '../queries'
|
|
4
|
+
import { type GetPostListResponse } from '../repositories'
|
|
5
|
+
|
|
6
|
+
const INITIAL_DATA: GetPostListResponse = {
|
|
7
|
+
data: [{ is_skeleton: true }, { is_skeleton: true }, { is_skeleton: true }],
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
const selectPostList = (data: GetPostListResponse) => {
|
|
11
|
+
return {
|
|
12
|
+
list: data.data?.map((post) => new PostEntity(post)) ?? [],
|
|
13
|
+
}
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
const useApiPosts = () => {
|
|
17
|
+
return useQuery({
|
|
18
|
+
...postQueries.list(),
|
|
19
|
+
initialData: INITIAL_DATA,
|
|
20
|
+
select: selectPostList,
|
|
21
|
+
})
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
export { useApiPosts }
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import { PostEntity } from '../entities'
|
|
2
|
+
import { type PostResource } from '../resources'
|
|
3
|
+
|
|
4
|
+
const POST_RESOURCE_LIST: PostResource[] = [
|
|
5
|
+
{
|
|
6
|
+
id: '1',
|
|
7
|
+
title: 'Getting started with the API layer',
|
|
8
|
+
description: 'A short walkthrough of resources, entities and queries.',
|
|
9
|
+
number_of_likes: 12,
|
|
10
|
+
number_of_comments: 3,
|
|
11
|
+
},
|
|
12
|
+
{
|
|
13
|
+
id: '2',
|
|
14
|
+
title: 'Caching reference data',
|
|
15
|
+
description: 'When to set staleTime and persist on a query.',
|
|
16
|
+
number_of_likes: 47,
|
|
17
|
+
number_of_comments: 8,
|
|
18
|
+
},
|
|
19
|
+
]
|
|
20
|
+
|
|
21
|
+
const getPostMockResourceList = () => {
|
|
22
|
+
return JSON.parse(JSON.stringify(POST_RESOURCE_LIST)) as PostResource[]
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
const getPostMockEntityList = () => {
|
|
26
|
+
return getPostMockResourceList().map((post) => new PostEntity(post))
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
export { getPostMockResourceList, getPostMockEntityList }
|
package/.claude/skills/{generate-api-model/references → api/references/model}/entities/common.ts
RENAMED
|
@@ -20,8 +20,11 @@ class BaseEntity<Resource extends BaseResource> {
|
|
|
20
20
|
this.updatedAt = resource?.updated_at ?? new Date()
|
|
21
21
|
}
|
|
22
22
|
|
|
23
|
-
|
|
24
|
-
|
|
23
|
+
/**
|
|
24
|
+
* Флаг определяющий, что данные еще не подгружены
|
|
25
|
+
*/
|
|
26
|
+
get isSkeleton() {
|
|
27
|
+
return this.resource?.is_skeleton ?? this.context?.is_skeleton ?? false
|
|
25
28
|
}
|
|
26
29
|
}
|
|
27
30
|
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { queryOptions } from '@tanstack/react-query'
|
|
2
|
+
import { Api } from '../api'
|
|
3
|
+
import { QUERY_KEYS } from '../constants'
|
|
4
|
+
|
|
5
|
+
const healthQueries = {
|
|
6
|
+
key: [QUERY_KEYS.HEALTH] as const,
|
|
7
|
+
detail: () =>
|
|
8
|
+
queryOptions({
|
|
9
|
+
queryKey: healthQueries.key,
|
|
10
|
+
queryFn: (options) => Api.healthRepository.getHealth({ options }),
|
|
11
|
+
}),
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
export { healthQueries }
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { queryOptions } from '@tanstack/react-query'
|
|
2
|
+
import { Api } from '../api'
|
|
3
|
+
import { QUERY_KEYS, STALE_TIME } from '../constants'
|
|
4
|
+
import { type PostEntity } from '../entities'
|
|
5
|
+
import { type GetPostListConfig } from '../repositories'
|
|
6
|
+
|
|
7
|
+
const postQueries = {
|
|
8
|
+
key: [QUERY_KEYS.POSTS] as const,
|
|
9
|
+
list: (config: GetPostListConfig = {}) =>
|
|
10
|
+
queryOptions({
|
|
11
|
+
queryKey: [...postQueries.key, config] as const,
|
|
12
|
+
queryFn: (options) => Api.postRepository.getPostList({ ...config, options }),
|
|
13
|
+
staleTime: STALE_TIME,
|
|
14
|
+
meta: { persist: true },
|
|
15
|
+
}),
|
|
16
|
+
detail: (id: PostEntity['id']) =>
|
|
17
|
+
queryOptions({
|
|
18
|
+
queryKey: [...postQueries.key, id] as const,
|
|
19
|
+
queryFn: (options) => Api.postRepository.getPost({ id, options }),
|
|
20
|
+
}),
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
export { postQueries }
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { ApiInstance } from '../../models'
|
|
2
|
+
import { type GetHealthApiConfig, type GetHealthApiResponse } from './health.types'
|
|
3
|
+
|
|
4
|
+
class HealthRepository extends ApiInstance {
|
|
5
|
+
// no auth
|
|
6
|
+
async getHealth({ options }: GetHealthApiConfig) {
|
|
7
|
+
return await this.get<GetHealthApiResponse>('/', { options })
|
|
8
|
+
}
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
export default HealthRepository
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import { type ApiConfig, type ApiResponse } from '../../api.types'
|
|
2
|
+
|
|
3
|
+
type GetHealthConfig = {}
|
|
4
|
+
|
|
5
|
+
type GetHealthResponse = {
|
|
6
|
+
maintenance?: boolean
|
|
7
|
+
start_at?: Date
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
// config
|
|
11
|
+
|
|
12
|
+
type GetHealthApiConfig = ApiConfig<GetHealthConfig>
|
|
13
|
+
|
|
14
|
+
// response
|
|
15
|
+
|
|
16
|
+
type GetHealthApiResponse = ApiResponse<GetHealthResponse>
|
|
17
|
+
|
|
18
|
+
export type {
|
|
19
|
+
GetHealthConfig,
|
|
20
|
+
GetHealthResponse,
|
|
21
|
+
// config
|
|
22
|
+
GetHealthApiConfig,
|
|
23
|
+
// response
|
|
24
|
+
GetHealthApiResponse,
|
|
25
|
+
}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import { ApiInstance } from '../../models'
|
|
2
|
+
import {
|
|
3
|
+
type CreatePostApiConfig,
|
|
4
|
+
type CreatePostApiResponse,
|
|
5
|
+
type GetPostApiConfig,
|
|
6
|
+
type GetPostApiResponse,
|
|
7
|
+
type GetPostListApiConfig,
|
|
8
|
+
type GetPostListApiResponse,
|
|
9
|
+
} from './post.types'
|
|
10
|
+
|
|
11
|
+
class PostRepository extends ApiInstance {
|
|
12
|
+
// no auth
|
|
13
|
+
async getPostList({ isPublished, options }: GetPostListApiConfig) {
|
|
14
|
+
return await this.get<GetPostListApiResponse>('/', {
|
|
15
|
+
params: { is_published: isPublished },
|
|
16
|
+
options,
|
|
17
|
+
})
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
// auth
|
|
21
|
+
async getPost({ id, options }: GetPostApiConfig) {
|
|
22
|
+
return await this.get<GetPostApiResponse>(`/${id}`, { options })
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
// auth
|
|
26
|
+
async createPost({ title, description, options }: CreatePostApiConfig) {
|
|
27
|
+
return await this.post<CreatePostApiResponse>('/', {
|
|
28
|
+
body: { title, description },
|
|
29
|
+
options,
|
|
30
|
+
})
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
export default PostRepository
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
import { type ApiConfig, type ApiResponse } from '../../api.types'
|
|
2
|
+
import { type PostEntity } from '../../entities'
|
|
3
|
+
import { type PostResource } from '../../resources'
|
|
4
|
+
|
|
5
|
+
type GetPostListConfig = {
|
|
6
|
+
isPublished?: boolean
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
type GetPostConfig = {
|
|
10
|
+
id: PostEntity['id']
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
type CreatePostConfig = {
|
|
14
|
+
title: string
|
|
15
|
+
description?: string
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
type GetPostListResponse = {
|
|
19
|
+
data?: PostResource[]
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
type GetPostResponse = {
|
|
23
|
+
data?: PostResource
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
type CreatePostResponse = {
|
|
27
|
+
data?: PostResource
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
// config
|
|
31
|
+
|
|
32
|
+
type GetPostListApiConfig = ApiConfig<GetPostListConfig>
|
|
33
|
+
|
|
34
|
+
type GetPostApiConfig = ApiConfig<GetPostConfig>
|
|
35
|
+
|
|
36
|
+
type CreatePostApiConfig = ApiConfig<CreatePostConfig>
|
|
37
|
+
|
|
38
|
+
// response
|
|
39
|
+
|
|
40
|
+
type GetPostListApiResponse = ApiResponse<GetPostListResponse>
|
|
41
|
+
|
|
42
|
+
type GetPostApiResponse = ApiResponse<GetPostResponse>
|
|
43
|
+
|
|
44
|
+
type CreatePostApiResponse = ApiResponse<CreatePostResponse>
|
|
45
|
+
|
|
46
|
+
export type {
|
|
47
|
+
GetPostListConfig,
|
|
48
|
+
GetPostConfig,
|
|
49
|
+
CreatePostConfig,
|
|
50
|
+
GetPostListResponse,
|
|
51
|
+
GetPostResponse,
|
|
52
|
+
CreatePostResponse,
|
|
53
|
+
// config
|
|
54
|
+
GetPostListApiConfig,
|
|
55
|
+
GetPostApiConfig,
|
|
56
|
+
CreatePostApiConfig,
|
|
57
|
+
// response
|
|
58
|
+
GetPostListApiResponse,
|
|
59
|
+
GetPostApiResponse,
|
|
60
|
+
CreatePostApiResponse,
|
|
61
|
+
}
|