@effijs/templates 0.0.0-stage → 1.0.0-alpha.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/CONTRIBUTING.md +27 -0
- package/LICENSE +22 -0
- package/README.md +32 -2
- package/ai/SETUP.md +5 -0
- package/docs/catalog.md +85 -0
- package/forge.manifest.js +75 -0
- package/lib/compat.js +40 -0
- package/lib/docs/build.js +146 -0
- package/lib/install.js +51 -0
- package/lib/journal.js +40 -0
- package/lib/jsonConfig.js +33 -0
- package/lib/migration.js +35 -0
- package/lib/names.js +42 -0
- package/lib/patch.js +62 -0
- package/lib/paths.js +12 -0
- package/lib/project.js +48 -0
- package/lib/registry.js +99 -0
- package/package.json +46 -4
- package/platforms/react-native/CATALOG.md +391 -0
- package/platforms/react-native/ORIGIN.md +42 -0
- package/platforms/react-native/README.md +78 -0
- package/platforms/react-native/ai/AGENTS.md.hbs +36 -0
- package/platforms/react-native/ai/SETUP.md +89 -0
- package/platforms/react-native/compat/matrix.js +150 -0
- package/platforms/react-native/configs/babel.js +63 -0
- package/platforms/react-native/configs/forgeConfig.js +35 -0
- package/platforms/react-native/configs/jsConfigs.js +96 -0
- package/platforms/react-native/configs/metro.js +86 -0
- package/platforms/react-native/generators/add/generator.js +12 -0
- package/platforms/react-native/generators/add/run.js +64 -0
- package/platforms/react-native/generators/component/generator.js +75 -0
- package/platforms/react-native/generators/component/render.js +69 -0
- package/platforms/react-native/generators/component/templates/Common.tsx.hbs +13 -0
- package/platforms/react-native/generators/component/templates/index.ts.hbs +13 -0
- package/platforms/react-native/generators/component/templates/pm.ts.hbs +7 -0
- package/platforms/react-native/generators/component/templates/types.ts.hbs +3 -0
- package/platforms/react-native/generators/demo/files/api/app.http +8 -0
- package/platforms/react-native/generators/demo/files/api/environment/http-client.env.json +5 -0
- package/platforms/react-native/generators/demo/files/entity/category/category.api.ts +18 -0
- package/platforms/react-native/generators/demo/files/entity/category/category.dto.ts +15 -0
- package/platforms/react-native/generators/demo/files/entity/category/category.service.ts +42 -0
- package/platforms/react-native/generators/demo/files/entity/category/category.store.ts +26 -0
- package/platforms/react-native/generators/demo/files/entity/category/index.ts +2 -0
- package/platforms/react-native/generators/demo/files/entity/product/index.ts +2 -0
- package/platforms/react-native/generators/demo/files/entity/product/product.api.ts +49 -0
- package/platforms/react-native/generators/demo/files/entity/product/product.dto.ts +120 -0
- package/platforms/react-native/generators/demo/files/entity/product/product.service.ts +139 -0
- package/platforms/react-native/generators/demo/files/entity/product/product.store.ts +37 -0
- package/platforms/react-native/generators/demo/files/feature/product/components/Product.CategorySelect.tsx +36 -0
- package/platforms/react-native/generators/demo/files/feature/product/detail/Product.Detail.Screen.tsx +100 -0
- package/platforms/react-native/generators/demo/files/feature/product/detail/product.detail.service.ts +33 -0
- package/platforms/react-native/generators/demo/files/feature/product/filter/Product.Filter.Screen.tsx +59 -0
- package/platforms/react-native/generators/demo/files/feature/product/filter/product.filter.service.ts +78 -0
- package/platforms/react-native/generators/demo/files/feature/product/form/Product.Form.Screen.tsx +71 -0
- package/platforms/react-native/generators/demo/files/feature/product/form/product.form.service.ts +142 -0
- package/platforms/react-native/generators/demo/files/feature/product/index.ts +7 -0
- package/platforms/react-native/generators/demo/files/feature/product/list/Product.List.Item.tsx +34 -0
- package/platforms/react-native/generators/demo/files/feature/product/list/Product.List.Screen.tsx +106 -0
- package/platforms/react-native/generators/demo/files/feature/product/list/product.list.service.ts +47 -0
- package/platforms/react-native/generators/demo/files/feature/product/product.feature.ts +29 -0
- package/platforms/react-native/generators/demo/files/feature/product/product.hooks.ts +7 -0
- package/platforms/react-native/generators/demo/files/feature/product/search/Product.Search.Screen.tsx +82 -0
- package/platforms/react-native/generators/demo/files/feature/product/search/product.search.service.ts +97 -0
- package/platforms/react-native/generators/demo/files/navigation/navigation.product.ts +46 -0
- package/platforms/react-native/generators/demo/generator.js +93 -0
- package/platforms/react-native/generators/entity/generator.js +68 -0
- package/platforms/react-native/generators/feature/generator.js +224 -0
- package/platforms/react-native/generators/feature/render.js +163 -0
- package/platforms/react-native/generators/feature/templates/detail.screen.tsx.hbs +25 -0
- package/platforms/react-native/generators/feature/templates/detail.service.ts.hbs +14 -0
- package/platforms/react-native/generators/feature/templates/feature.ts.hbs +18 -0
- package/platforms/react-native/generators/feature/templates/filter.screen.tsx.hbs +17 -0
- package/platforms/react-native/generators/feature/templates/filter.service.ts.hbs +14 -0
- package/platforms/react-native/generators/feature/templates/form.screen.tsx.hbs +21 -0
- package/platforms/react-native/generators/feature/templates/form.service.ts.hbs +37 -0
- package/platforms/react-native/generators/feature/templates/hooks.ts.hbs +7 -0
- package/platforms/react-native/generators/feature/templates/index.ts.hbs +2 -0
- package/platforms/react-native/generators/feature/templates/list.item.tsx.hbs +16 -0
- package/platforms/react-native/generators/feature/templates/list.screen.tsx.hbs +34 -0
- package/platforms/react-native/generators/feature/templates/list.service.ts.hbs +15 -0
- package/platforms/react-native/generators/feature/templates/navigation.ts.hbs +12 -0
- package/platforms/react-native/generators/feature/templates/search.screen.tsx.hbs +24 -0
- package/platforms/react-native/generators/feature/templates/search.service.ts.hbs +13 -0
- package/platforms/react-native/generators/feature/templates/tab.tsx.hbs +8 -0
- package/platforms/react-native/generators/init/files/app/app.controller.ts +41 -0
- package/platforms/react-native/generators/init/files/app/app.error.ts +1 -0
- package/platforms/react-native/generators/init/files/app/app.store.ts +12 -0
- package/platforms/react-native/generators/init/files/app/index.ts +19 -0
- package/platforms/react-native/generators/init/files/app/splash/Onboarding.Screen.tsx +31 -0
- package/platforms/react-native/generators/init/files/app/splash/Splash.Screen.tsx +14 -0
- package/platforms/react-native/generators/init/files/app/tabs/home/Home.tab.tsx +24 -0
- package/platforms/react-native/generators/init/files/app/tabs/profile/Profile.tab.tsx +1 -0
- package/platforms/react-native/generators/init/files/configs/dev.ts.hbs +5 -0
- package/platforms/react-native/generators/init/files/configs/index.ts +4 -0
- package/platforms/react-native/generators/init/files/configs/prod.ts.hbs +5 -0
- package/platforms/react-native/generators/init/files/entity/auth/auth.api.ts +36 -0
- package/platforms/react-native/generators/init/files/entity/auth/auth.dto.ts +26 -0
- package/platforms/react-native/generators/init/files/entity/auth/auth.service.ts +94 -0
- package/platforms/react-native/generators/init/files/entity/auth/auth.session.store.ts +14 -0
- package/platforms/react-native/generators/init/files/entity/auth/auth.store.ts +20 -0
- package/platforms/react-native/generators/init/files/entity/auth/index.ts +2 -0
- package/platforms/react-native/generators/init/files/entity/index.ts +2 -0
- package/platforms/react-native/generators/init/files/feature/auth/auth.feature.ts +10 -0
- package/platforms/react-native/generators/init/files/feature/auth/auth.hooks.ts +7 -0
- package/platforms/react-native/generators/init/files/feature/auth/index.ts +1 -0
- package/platforms/react-native/generators/init/files/feature/auth/sign-in/SignIn.Screen.tsx +39 -0
- package/platforms/react-native/generators/init/files/feature/auth/sign-in/signIn.service.ts +54 -0
- package/platforms/react-native/generators/init/files/feature/auth/sign-up/SignUp.Screen.tsx +64 -0
- package/platforms/react-native/generators/init/files/feature/auth/sign-up/signUp.service.ts +73 -0
- package/platforms/react-native/generators/init/files/feature/feature.hooks.ts +15 -0
- package/platforms/react-native/generators/init/files/feature/index.ts +3 -0
- package/platforms/react-native/generators/init/files/feature/profile/Profile.Screen.tsx +52 -0
- package/platforms/react-native/generators/init/files/feature/profile/index.ts +1 -0
- package/platforms/react-native/generators/init/files/feature/profile/profile.feature.ts +18 -0
- package/platforms/react-native/generators/init/files/feature/profile/profile.hooks.ts +7 -0
- package/platforms/react-native/generators/init/files/index.ts +16 -0
- package/platforms/react-native/generators/init/files/navigation/index.ts +18 -0
- package/platforms/react-native/generators/init/files/navigation/navigation.app.ts +58 -0
- package/platforms/react-native/generators/init/files/navigation/navigation.features.ts +9 -0
- package/platforms/react-native/generators/init/files/navigation/navigation.hooks.ts +5 -0
- package/platforms/react-native/generators/init/files/navigation/navigation.tabs.ts +55 -0
- package/platforms/react-native/generators/init/files/navigation/navigation.widgets.ts +23 -0
- package/platforms/react-native/generators/init/files/services/http/http.base.ts +69 -0
- package/platforms/react-native/generators/init/files/services/http/http.error.ts +10 -0
- package/platforms/react-native/generators/init/files/services/http/http.service.ts +24 -0
- package/platforms/react-native/generators/init/files/services/http/middleware/index.ts +12 -0
- package/platforms/react-native/generators/init/files/services/http/middleware/middleware.error.ts +36 -0
- package/platforms/react-native/generators/init/files/services/http/middleware/middleware.registry.ts +3 -0
- package/platforms/react-native/generators/init/files/services/http/middleware/middleware.token.ts +97 -0
- package/platforms/react-native/generators/init/files/services/index.ts +15 -0
- package/platforms/react-native/generators/init/files/ui/components/Box/Common.tsx +19 -0
- package/platforms/react-native/generators/init/files/ui/components/Box/box.pm.ts +111 -0
- package/platforms/react-native/generators/init/files/ui/components/Box/box.types.ts +8 -0
- package/platforms/react-native/generators/init/files/ui/components/Box/index.ts +13 -0
- package/platforms/react-native/generators/init/files/ui/components/Button/Common.tsx +50 -0
- package/platforms/react-native/generators/init/files/ui/components/Button/Touchable.tsx +19 -0
- package/platforms/react-native/generators/init/files/ui/components/Button/button.pm.ts +197 -0
- package/platforms/react-native/generators/init/files/ui/components/Button/button.types.ts +22 -0
- package/platforms/react-native/generators/init/files/ui/components/Button/button.utils.ts +16 -0
- package/platforms/react-native/generators/init/files/ui/components/Button/index.ts +19 -0
- package/platforms/react-native/generators/init/files/ui/components/Form/Colours.tsx +50 -0
- package/platforms/react-native/generators/init/files/ui/components/Form/Common.tsx +38 -0
- package/platforms/react-native/generators/init/files/ui/components/Form/ErrorText.tsx +11 -0
- package/platforms/react-native/generators/init/files/ui/components/Form/Input.tsx +115 -0
- package/platforms/react-native/generators/init/files/ui/components/Form/InputArea.tsx +70 -0
- package/platforms/react-native/generators/init/files/ui/components/Form/Label.tsx +18 -0
- package/platforms/react-native/generators/init/files/ui/components/Form/Select.tsx +86 -0
- package/platforms/react-native/generators/init/files/ui/components/Form/components/SecureTextEntry.tsx +19 -0
- package/platforms/react-native/generators/init/files/ui/components/Form/form.error.ts +18 -0
- package/platforms/react-native/generators/init/files/ui/components/Form/form.pm.ts +134 -0
- package/platforms/react-native/generators/init/files/ui/components/Form/form.types.ts +59 -0
- package/platforms/react-native/generators/init/files/ui/components/Form/index.ts +67 -0
- package/platforms/react-native/generators/init/files/ui/components/Grid/Common.tsx +11 -0
- package/platforms/react-native/generators/init/files/ui/components/Grid/grid.pm.ts +93 -0
- package/platforms/react-native/generators/init/files/ui/components/Grid/grid.types.ts +79 -0
- package/platforms/react-native/generators/init/files/ui/components/Grid/index.ts +13 -0
- package/platforms/react-native/generators/init/files/ui/components/Icon/Common.tsx +19 -0
- package/platforms/react-native/generators/init/files/ui/components/Icon/icons.pm.ts +74 -0
- package/platforms/react-native/generators/init/files/ui/components/Icon/icons.types.ts +19 -0
- package/platforms/react-native/generators/init/files/ui/components/Icon/index.ts +3 -0
- package/platforms/react-native/generators/init/files/ui/components/Loading/Loading.tsx +10 -0
- package/platforms/react-native/generators/init/files/ui/components/Loading/loading.hook.ts +5 -0
- package/platforms/react-native/generators/init/files/ui/components/Loading/loading.service.ts +22 -0
- package/platforms/react-native/generators/init/files/ui/components/Loading/loading.store.ts +8 -0
- package/platforms/react-native/generators/init/files/ui/components/Screen/Common.tsx +87 -0
- package/platforms/react-native/generators/init/files/ui/components/Screen/Content.tsx +77 -0
- package/platforms/react-native/generators/init/files/ui/components/Screen/Header.tsx +80 -0
- package/platforms/react-native/generators/init/files/ui/components/Screen/HeaderTab.tsx +17 -0
- package/platforms/react-native/generators/init/files/ui/components/Screen/SafeAreaHOC.tsx +9 -0
- package/platforms/react-native/generators/init/files/ui/components/Screen/index.ts +22 -0
- package/platforms/react-native/generators/init/files/ui/components/Text/Common.tsx +20 -0
- package/platforms/react-native/generators/init/files/ui/components/Text/index.ts +13 -0
- package/platforms/react-native/generators/init/files/ui/components/Text/text.pm.ts +55 -0
- package/platforms/react-native/generators/init/files/ui/components/Text/text.types.ts +27 -0
- package/platforms/react-native/generators/init/files/ui/components/TextInput/Common.tsx +19 -0
- package/platforms/react-native/generators/init/files/ui/components/TextInput/index.ts +15 -0
- package/platforms/react-native/generators/init/files/ui/components/TextInput/textInput.pm.ts +65 -0
- package/platforms/react-native/generators/init/files/ui/components/TextInput/textInput.types.ts +16 -0
- package/platforms/react-native/generators/init/files/ui/components/ThemePicker/ThemePicker.tsx +92 -0
- package/platforms/react-native/generators/init/files/ui/components/ThemePicker/index.ts +1 -0
- package/platforms/react-native/generators/init/files/ui/components/index.ts +27 -0
- package/platforms/react-native/generators/init/files/ui/components/utils/color.ts +19 -0
- package/platforms/react-native/generators/init/files/ui/components/utils/index.ts +3 -0
- package/platforms/react-native/generators/init/files/ui/components/utils/useLoading.hook.spec.tsx +202 -0
- package/platforms/react-native/generators/init/files/ui/components/utils/useLoading.hook.ts +172 -0
- package/platforms/react-native/generators/init/files/ui/components/utils/useStore.ts +34 -0
- package/platforms/react-native/generators/init/files/ui/fonts/font-icons.ttf +0 -0
- package/platforms/react-native/generators/init/files/ui/icons/font-icons.json +53 -0
- package/platforms/react-native/generators/init/files/ui/icons/logo.png +0 -0
- package/platforms/react-native/generators/init/files/ui/icons/logo.svg +304 -0
- package/platforms/react-native/generators/init/files/ui/icons/tabs/icon-1.png +0 -0
- package/platforms/react-native/generators/init/files/ui/icons/tabs/icon-2.png +0 -0
- package/platforms/react-native/generators/init/files/ui/theme/black/black.color.ts +8 -0
- package/platforms/react-native/generators/init/files/ui/theme/black/index.ts +10 -0
- package/platforms/react-native/generators/init/files/ui/theme/blue/blue.color.ts +8 -0
- package/platforms/react-native/generators/init/files/ui/theme/blue/index.ts +10 -0
- package/platforms/react-native/generators/init/files/ui/theme/green/green.color.ts +8 -0
- package/platforms/react-native/generators/init/files/ui/theme/green/index.ts +10 -0
- package/platforms/react-native/generators/init/files/ui/theme/index.ts +11 -0
- package/platforms/react-native/generators/init/files/ui/theme/pink/index.ts +10 -0
- package/platforms/react-native/generators/init/files/ui/theme/pink/pink.color.ts +8 -0
- package/platforms/react-native/generators/init/files/ui/theme/scheme/index.ts +23 -0
- package/platforms/react-native/generators/init/files/ui/theme/scheme/theme.scheme.color.ts +139 -0
- package/platforms/react-native/generators/init/files/ui/theme/scheme/theme.scheme.radius.ts +21 -0
- package/platforms/react-native/generators/init/files/ui/theme/scheme/theme.scheme.spacing.ts +24 -0
- package/platforms/react-native/generators/init/files/ui/theme/scheme/theme.scheme.ts +25 -0
- package/platforms/react-native/generators/init/files/ui/theme/scheme/theme.scheme.typography.ts +98 -0
- package/platforms/react-native/generators/init/files/ui/theme/shared/index.ts +4 -0
- package/platforms/react-native/generators/init/files/ui/theme/shared/shared.color.base.ts +79 -0
- package/platforms/react-native/generators/init/files/ui/theme/shared/shared.radius.ts +8 -0
- package/platforms/react-native/generators/init/files/ui/theme/shared/shared.spacing.ts +9 -0
- package/platforms/react-native/generators/init/files/ui/theme/shared/shared.typography.ts +105 -0
- package/platforms/react-native/generators/init/files/ui/theme/theme.hooks.ts +7 -0
- package/platforms/react-native/generators/init/files/ui/theme/theme.meta.ts +10 -0
- package/platforms/react-native/generators/init/files/ui/theme/theme.provider.tsx +19 -0
- package/platforms/react-native/generators/init/files/ui/theme/theme.service.ts +36 -0
- package/platforms/react-native/generators/init/files/ui/theme/theme.ts +27 -0
- package/platforms/react-native/generators/init/files/ui/widgets/index.ts +1 -0
- package/platforms/react-native/generators/init/files/ui/widgets/toast/Toast.Item.tsx +175 -0
- package/platforms/react-native/generators/init/files/ui/widgets/toast/Toast.Overlay.tsx +46 -0
- package/platforms/react-native/generators/init/files/ui/widgets/toast/Toast.Stack.tsx +75 -0
- package/platforms/react-native/generators/init/files/ui/widgets/toast/index.ts +7 -0
- package/platforms/react-native/generators/init/files/ui/widgets/toast/toast.hooks.ts +18 -0
- package/platforms/react-native/generators/init/files/ui/widgets/toast/toast.service.ts +39 -0
- package/platforms/react-native/generators/init/files/ui/widgets/toast/toast.store.ts +59 -0
- package/platforms/react-native/generators/init/files/ui/widgets/toast/toast.types.ts +18 -0
- package/platforms/react-native/generators/init/files/ui/widgets/widgets.feature.ts +14 -0
- package/platforms/react-native/generators/init/files/utils/date.ts +11 -0
- package/platforms/react-native/generators/init/files/utils/index.ts +12 -0
- package/platforms/react-native/generators/init/files/utils/store.persistent.ts +103 -0
- package/platforms/react-native/generators/init/files/utils/store.registry.ts +14 -0
- package/platforms/react-native/generators/init/files/utils/string.ts +100 -0
- package/platforms/react-native/generators/init/generator.js +86 -0
- package/platforms/react-native/generators/init/kit.js +23 -0
- package/platforms/react-native/generators/init/navigators/expo-router/index.ts +18 -0
- package/platforms/react-native/generators/init/navigators/expo-router/navigation.app.ts +8 -0
- package/platforms/react-native/generators/init/navigators/expo-router/navigation.features.ts +9 -0
- package/platforms/react-native/generators/init/navigators/expo-router/navigation.hooks.ts +5 -0
- package/platforms/react-native/generators/init/navigators/expo-router/navigation.tabs.ts +7 -0
- package/platforms/react-native/generators/init/navigators/expo-router/navigation.widgets.ts +5 -0
- package/platforms/react-native/generators/init/navigators/react-navigation/index.ts +18 -0
- package/platforms/react-native/generators/init/navigators/react-navigation/navigation.app.ts +8 -0
- package/platforms/react-native/generators/init/navigators/react-navigation/navigation.features.ts +9 -0
- package/platforms/react-native/generators/init/navigators/react-navigation/navigation.hooks.ts +5 -0
- package/platforms/react-native/generators/init/navigators/react-navigation/navigation.tabs.ts +7 -0
- package/platforms/react-native/generators/init/navigators/react-navigation/navigation.widgets.ts +5 -0
- package/platforms/react-native/generators/setup/generator.js +225 -0
- package/platforms/react-native/generators/util/generator.js +12 -0
- package/platforms/react-native/platform.js +32 -0
- package/platforms/react-native/runtime.js +57 -0
- package/platforms/react-native/solutions/components/BottomSheet/README.md +29 -0
- package/platforms/react-native/solutions/components/BottomSheet/files/Common.tsx +120 -0
- package/platforms/react-native/solutions/components/BottomSheet/files/Content.tsx +57 -0
- package/platforms/react-native/solutions/components/BottomSheet/files/Context.tsx +22 -0
- package/platforms/react-native/solutions/components/BottomSheet/files/FlatList.tsx +50 -0
- package/platforms/react-native/solutions/components/BottomSheet/files/Header.tsx +57 -0
- package/platforms/react-native/solutions/components/BottomSheet/files/Search.tsx +24 -0
- package/platforms/react-native/solutions/components/BottomSheet/files/bottomSheet.constants.ts +13 -0
- package/platforms/react-native/solutions/components/BottomSheet/files/bottomSheet.types.ts +31 -0
- package/platforms/react-native/solutions/components/BottomSheet/files/index.ts +33 -0
- package/platforms/react-native/solutions/components/BottomSheet/solution.js +38 -0
- package/platforms/react-native/solutions/components/BottomSheetWidgets/README.md +29 -0
- package/platforms/react-native/solutions/components/BottomSheetWidgets/files/SelectPicker.tsx +47 -0
- package/platforms/react-native/solutions/components/BottomSheetWidgets/files/bottomSheet/Content.BottomSheet.tsx +22 -0
- package/platforms/react-native/solutions/components/BottomSheetWidgets/files/bottomSheet/DateTimePicker.BottomSheet.tsx +74 -0
- package/platforms/react-native/solutions/components/BottomSheetWidgets/files/bottomSheet/List.BottomSheet.tsx +62 -0
- package/platforms/react-native/solutions/components/BottomSheetWidgets/solution.js +49 -0
- package/platforms/react-native/solutions/components/Calendar/README.md +29 -0
- package/platforms/react-native/solutions/components/Calendar/files/Common.tsx +16 -0
- package/platforms/react-native/solutions/components/Calendar/files/Context.tsx +466 -0
- package/platforms/react-native/solutions/components/Calendar/files/DayCell.tsx +89 -0
- package/platforms/react-native/solutions/components/Calendar/files/MonthView.tsx +41 -0
- package/platforms/react-native/solutions/components/Calendar/files/MonthYearOverlay.tsx +51 -0
- package/platforms/react-native/solutions/components/Calendar/files/SwipeablePeriod.tsx +44 -0
- package/platforms/react-native/solutions/components/Calendar/files/WeekDayTitles.tsx +31 -0
- package/platforms/react-native/solutions/components/Calendar/files/WeekView.tsx +40 -0
- package/platforms/react-native/solutions/components/Calendar/files/calendar.styles.ts +142 -0
- package/platforms/react-native/solutions/components/Calendar/files/calendar.types.ts +126 -0
- package/platforms/react-native/solutions/components/Calendar/files/calendar.utils.ts +143 -0
- package/platforms/react-native/solutions/components/Calendar/files/index.ts +40 -0
- package/platforms/react-native/solutions/components/Calendar/solution.js +38 -0
- package/platforms/react-native/solutions/components/Chart/README.md +29 -0
- package/platforms/react-native/solutions/components/Chart/files/Cilcular.tsx +140 -0
- package/platforms/react-native/solutions/components/Chart/files/index.ts +3 -0
- package/platforms/react-native/solutions/components/Chart/solution.js +38 -0
- package/platforms/react-native/solutions/components/CheckBox/README.md +29 -0
- package/platforms/react-native/solutions/components/CheckBox/files/Common.tsx +55 -0
- package/platforms/react-native/solutions/components/CheckBox/files/checkbox.pm.ts +71 -0
- package/platforms/react-native/solutions/components/CheckBox/files/index.ts +9 -0
- package/platforms/react-native/solutions/components/CheckBox/form/Checkbox.tsx +22 -0
- package/platforms/react-native/solutions/components/CheckBox/solution.js +57 -0
- package/platforms/react-native/solutions/components/DateTimePicker/README.md +29 -0
- package/platforms/react-native/solutions/components/DateTimePicker/files/DateTimePicker.tsx +44 -0
- package/platforms/react-native/solutions/components/DateTimePicker/solution.js +45 -0
- package/platforms/react-native/solutions/components/Image/README.md +29 -0
- package/platforms/react-native/solutions/components/Image/files/SVG.tsx +74 -0
- package/platforms/react-native/solutions/components/Image/files/image.pm.ts +25 -0
- package/platforms/react-native/solutions/components/Image/files/image.utils.ts +35 -0
- package/platforms/react-native/solutions/components/Image/files/index.ts +5 -0
- package/platforms/react-native/solutions/components/Image/solution.js +40 -0
- package/platforms/react-native/solutions/components/InputSecurity/README.md +29 -0
- package/platforms/react-native/solutions/components/InputSecurity/files/InputSecurity.ts +142 -0
- package/platforms/react-native/solutions/components/InputSecurity/solution.js +28 -0
- package/platforms/react-native/solutions/components/OTP/README.md +29 -0
- package/platforms/react-native/solutions/components/OTP/files/Item.tsx +16 -0
- package/platforms/react-native/solutions/components/OTP/files/Items.tsx +33 -0
- package/platforms/react-native/solutions/components/OTP/files/index.tsx +120 -0
- package/platforms/react-native/solutions/components/OTP/files/otp.pm.ts +30 -0
- package/platforms/react-native/solutions/components/OTP/solution.js +38 -0
- package/platforms/react-native/solutions/components/ProgressIndicator/README.md +29 -0
- package/platforms/react-native/solutions/components/ProgressIndicator/files/Circular.tsx +154 -0
- package/platforms/react-native/solutions/components/ProgressIndicator/files/Linear.tsx +133 -0
- package/platforms/react-native/solutions/components/ProgressIndicator/files/circular.pm.ts +34 -0
- package/platforms/react-native/solutions/components/ProgressIndicator/files/index.ts +16 -0
- package/platforms/react-native/solutions/components/ProgressIndicator/solution.js +39 -0
- package/platforms/react-native/solutions/components/Ruler/README.md +29 -0
- package/platforms/react-native/solutions/components/Ruler/files/Common.tsx +44 -0
- package/platforms/react-native/solutions/components/Ruler/files/Context.tsx +210 -0
- package/platforms/react-native/solutions/components/Ruler/files/Track.tsx +686 -0
- package/platforms/react-native/solutions/components/Ruler/files/Value.tsx +60 -0
- package/platforms/react-native/solutions/components/Ruler/files/index.ts +23 -0
- package/platforms/react-native/solutions/components/Ruler/files/ruler.constants.ts +70 -0
- package/platforms/react-native/solutions/components/Ruler/files/ruler.types.ts +98 -0
- package/platforms/react-native/solutions/components/Ruler/files/ruler.utils.ts +332 -0
- package/platforms/react-native/solutions/components/Ruler/solution.js +38 -0
- package/platforms/react-native/solutions/components/Section/README.md +29 -0
- package/platforms/react-native/solutions/components/Section/files/Common.tsx +144 -0
- package/platforms/react-native/solutions/components/Section/solution.js +37 -0
- package/platforms/react-native/solutions/components/Slider/README.md +29 -0
- package/platforms/react-native/solutions/components/Slider/files/Container.tsx +5 -0
- package/platforms/react-native/solutions/components/Slider/files/Content.tsx +44 -0
- package/platforms/react-native/solutions/components/Slider/files/Context.tsx +30 -0
- package/platforms/react-native/solutions/components/Slider/files/Pagination.Dot.tsx +61 -0
- package/platforms/react-native/solutions/components/Slider/files/index.ts +22 -0
- package/platforms/react-native/solutions/components/Slider/solution.js +38 -0
- package/platforms/react-native/solutions/components/Switch/README.md +29 -0
- package/platforms/react-native/solutions/components/Switch/files/Common.tsx +38 -0
- package/platforms/react-native/solutions/components/Switch/files/index.ts +9 -0
- package/platforms/react-native/solutions/components/Switch/files/switch.pm.ts +53 -0
- package/platforms/react-native/solutions/components/Switch/solution.js +38 -0
- package/platforms/react-native/solutions/install.js +97 -0
- package/platforms/react-native/solutions/services/firebase-core/README.md +31 -0
- package/platforms/react-native/solutions/services/firebase-core/files/index.ts +5 -0
- package/platforms/react-native/solutions/services/firebase-core/solution.js +39 -0
- package/platforms/react-native/solutions/services/firebase-messaging/README.md +31 -0
- package/platforms/react-native/solutions/services/firebase-messaging/files/index.ts +20 -0
- package/platforms/react-native/solutions/services/firebase-messaging/solution.js +42 -0
- package/platforms/react-native/solutions/utils/permissions/README.md +29 -0
- package/platforms/react-native/solutions/utils/permissions/files/permissions.ts +10 -0
- package/platforms/react-native/solutions/utils/permissions/solution.js +32 -0
- package/presets/react-native-fsd/index.js +25 -0
- package/shared/generators/entity/render.js +88 -0
- package/shared/generators/entity/templates/crud/api.ts.hbs +36 -0
- package/shared/generators/entity/templates/crud/dto.ts.hbs +36 -0
- package/shared/generators/entity/templates/crud/service.ts.hbs +73 -0
- package/shared/generators/entity/templates/crud/store.ts.hbs +27 -0
- package/shared/generators/entity/templates/index.ts.hbs +2 -0
- package/shared/generators/entity/templates/simple/api.ts.hbs +16 -0
- package/shared/generators/entity/templates/simple/dto.ts.hbs +5 -0
- package/shared/generators/entity/templates/simple/service.ts.hbs +26 -0
- package/shared/generators/entity/templates/simple/store.ts.hbs +18 -0
- package/shared/solutions/utils/date/README.md +29 -0
- package/shared/solutions/utils/date/files/date.ts +11 -0
- package/shared/solutions/utils/date/solution.js +27 -0
- package/shared/solutions/utils/string/README.md +29 -0
- package/shared/solutions/utils/string/files/string.ts +100 -0
- package/shared/solutions/utils/string/solution.js +27 -0
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
# Origin
|
|
2
|
+
|
|
3
|
+
The React Native templates were copied once from `examples/testForgeFsd863/src` on 2026-10-18. The repo HEAD at that copy was `287f769`. The plan named commit `4f5a6e1`; that commit is not in this clone, so the working tree of the example is the source of truth. `packages/templates.back` supplied the React Navigation and Expo stubs and the Slider, Ruler, Calendar, and Chart sources.
|
|
4
|
+
|
|
5
|
+
Refresh with:
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
node packages/templates/scripts/stage-origin.mjs
|
|
9
|
+
node packages/templates/scripts/write-solutions.mjs
|
|
10
|
+
```
|
|
11
|
+
|
|
12
|
+
`stage-origin.mjs` recopies and reapplies the adaptations below. Re-check markers after a refresh. `write-solutions.mjs` rewrites `solution.js` and `README.md` but keeps hand-written Firebase and permissions sources only if you do not delete those directories first. The script writes those two services as well.
|
|
13
|
+
|
|
14
|
+
## What moved where
|
|
15
|
+
|
|
16
|
+
| Template | Example |
|
|
17
|
+
| --- | --- |
|
|
18
|
+
| `generators/init/files` | `src` without product, category, and the solution-only components |
|
|
19
|
+
| `generators/demo/files` | `entity/product`, `entity/category`, `feature/product`, `navigation.product.ts`, `api/` |
|
|
20
|
+
| `solutions/components/BottomSheet` and the other example components | `src/ui/components/<Name>` |
|
|
21
|
+
| `solutions/components/BottomSheetWidgets` | `src/ui/widgets/bottomSheet` plus `Form/SelectPicker.tsx` |
|
|
22
|
+
| `shared/solutions/utils/string` and `date` | `src/utils/string.ts`, `src/utils/date.ts` |
|
|
23
|
+
|
|
24
|
+
## Adaptations
|
|
25
|
+
|
|
26
|
+
- Home is a placeholder. Demo points it at the product list.
|
|
27
|
+
- `entity/index.ts` and `feature/index.ts` register only auth and profile, plus markers.
|
|
28
|
+
- `navigation.features.ts` starts empty, with markers.
|
|
29
|
+
- Base UI is Box, Grid, Text, Button, Screen, Form, TextInput, Icon, Loading, ThemePicker.
|
|
30
|
+
- Button, Form Input, and InputArea use `ActivityIndicator` instead of ProgressIndicator.
|
|
31
|
+
- Splash and Profile use React Native `Image`. Screen header dropped an unused Image import.
|
|
32
|
+
- Form does not ship DateTimePicker, SelectPicker, Checkbox, RadioGroup, or InputSecurity. Those are solutions, except RadioGroup, which imported a missing `RadioButton` and was left out.
|
|
33
|
+
- Config `API_URL` is `{{{apiUrl}}}` in `configs/dev.ts.hbs` and `configs/prod.ts.hbs`. Init renders that from the `apiUrl` answer. The stage script renames the copied `.ts` files to `.hbs` after writing the token.
|
|
34
|
+
- Navigator stubs keep the example class shape (`NavigationApp`, `NavigationFeatures`, `NavigationTabs`, `NavigationWidgets`) with TODO methods for `goToSplash`, `goToSignIn`, `goToSignUp`, `goToOnboarding`, `goToTabs`, and `showToast`.
|
|
35
|
+
- Skia stays on Image and ProgressIndicator. It is not a setup dependency.
|
|
36
|
+
|
|
37
|
+
## How to update
|
|
38
|
+
|
|
39
|
+
1. Diff `examples/testForgeFsd863/src` against `generators/init/files` and `generators/demo/files`.
|
|
40
|
+
2. Run the stage script only when you intend to take the example again.
|
|
41
|
+
3. Search for `// forge:` and confirm every marker listed in the platform README is still present.
|
|
42
|
+
4. Run `npm test` and `npm run docs:check`.
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
# React Native FSD
|
|
2
|
+
|
|
3
|
+
`rn-fsd` takes a React Native CLI app to an EffiJS Feature-Sliced Design tree. Forge's core is unchanged. Dependency installs, config merges, summaries, and migrations live in this package.
|
|
4
|
+
|
|
5
|
+
```mermaid
|
|
6
|
+
flowchart TD
|
|
7
|
+
rnInit["npx @react-native-community/cli init MyApp"] --> addPkgs["yarn add -D @effijs/forge @effijs/templates"]
|
|
8
|
+
addPkgs --> forgeInit["npx forge init"]
|
|
9
|
+
forgeInit --> setup["forge g setup"]
|
|
10
|
+
setup -->|"patch failed"| migration[".forge/migrations"]
|
|
11
|
+
setup --> init["forge g init"]
|
|
12
|
+
init --> demo["forge g demo"]
|
|
13
|
+
init --> entity["forge g entity"]
|
|
14
|
+
init --> feature["forge g feature"]
|
|
15
|
+
init --> component["forge g component"]
|
|
16
|
+
init --> add["forge g add / forge g util"]
|
|
17
|
+
```
|
|
18
|
+
|
|
19
|
+
## New project
|
|
20
|
+
|
|
21
|
+
```bash
|
|
22
|
+
npx @react-native-community/cli init MyApp --version 0.86.3
|
|
23
|
+
cd MyApp
|
|
24
|
+
yarn add -D @effijs/forge @effijs/templates
|
|
25
|
+
npx forge init
|
|
26
|
+
npx forge g setup
|
|
27
|
+
npx forge g init --api-url https://api.example.com/
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
`setup` rewrites `forge.config.js` with `presetMap` set to `@effijs/templates/presets/react-native-fsd`. `addMany` byte-copies files that are not `.hbs`. Barrel registration uses `append` with `pattern`, `before: true`, and `unique: true`.
|
|
31
|
+
|
|
32
|
+
## Existing project
|
|
33
|
+
|
|
34
|
+
Run `forge g setup` in the app root, then `forge g init`. Init copies `src` and does not delete screens you already have unless a path collides. Use `--force` to overwrite collisions.
|
|
35
|
+
|
|
36
|
+
## Commands
|
|
37
|
+
|
|
38
|
+
```bash
|
|
39
|
+
npx forge g setup --navigator react-native-navigation
|
|
40
|
+
npx forge g setup --link-local ~/projects/npm/EffiJS/effijs
|
|
41
|
+
npx forge g init --api-url https://api.example.com/
|
|
42
|
+
npx forge g demo
|
|
43
|
+
npx forge g entity --name Invoice --variant crud --fields "title:string,price:number"
|
|
44
|
+
npx forge g feature --name Invoice --screens all --tab
|
|
45
|
+
npx forge g component --name Avatar --base Pressable --extend Box
|
|
46
|
+
npx forge g add --id component:BottomSheet
|
|
47
|
+
npx forge g util --id util:permissions
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
`--yes` skips questions and applies each prompt's `default`.
|
|
51
|
+
|
|
52
|
+
`--link-local` is read from the process arguments. Forge does not declare that flag. It adds `watchFolders` and `extraNodeModules` to a stock `metro.config.js`.
|
|
53
|
+
|
|
54
|
+
## Markers
|
|
55
|
+
|
|
56
|
+
Generators insert at `// forge:<name>` and leave the marker in place:
|
|
57
|
+
|
|
58
|
+
- `entity`, `feature`
|
|
59
|
+
- `navigation-features-import`, `navigation-features`
|
|
60
|
+
- `navigation-tabs`, `navigation-tabs-register`
|
|
61
|
+
- `components-import`, `components-export`
|
|
62
|
+
- `services`, `utils`
|
|
63
|
+
- `form-imports`, `form-types`, `form-elements`
|
|
64
|
+
|
|
65
|
+
## Migrations and AI
|
|
66
|
+
|
|
67
|
+
When a config is not plain data, setup writes `.forge/migrations/*.md` and prints:
|
|
68
|
+
|
|
69
|
+
`Apply .forge/migrations/<file>.md following node_modules/@effijs/templates/platforms/react-native/ai/SETUP.md`
|
|
70
|
+
|
|
71
|
+
The same prompt is inside the migration file. Summaries are printed and saved to `.forge/summary/`.
|
|
72
|
+
|
|
73
|
+
## Limitations
|
|
74
|
+
|
|
75
|
+
- React Native Navigation (Wix) is implemented, including `npx rnn-link` and a native marker check. React Navigation and Expo Router get class stubs with TODO bodies. `Screen` is still the Wix screen from the example.
|
|
76
|
+
- Android linking snippets in the migration come from the React Native Navigation install guide. The example app has not linked Android yet, so those snippets must be checked against the project's Kotlin files. The iOS `AppDelegate.swift` matches the example.
|
|
77
|
+
- pnpm cannot resolve a bare preset id from a sibling folder. Use the generated `forge.config.js`.
|
|
78
|
+
- Parts of Form that need extra packages are solutions: DateTimePicker, SelectPicker, InputSecurity. ProgressIndicator and Image are solutions too. The base Button and inputs use `ActivityIndicator`.
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
# AGENTS.md
|
|
2
|
+
|
|
3
|
+
This React Native app uses Feature-Sliced Design and EffiJS. Navigation library: {{{navigator}}}. API base URL: {{{apiUrl}}}.
|
|
4
|
+
|
|
5
|
+
## Layout
|
|
6
|
+
|
|
7
|
+
- `src/app` — startup, splash, onboarding, tabs
|
|
8
|
+
- `src/entity` — api, dto, store, service
|
|
9
|
+
- `src/feature` — screens and feature services
|
|
10
|
+
- `src/navigation` — navigator classes
|
|
11
|
+
- `src/services` — http and other process-wide services
|
|
12
|
+
- `src/ui` — theme, widgets, components
|
|
13
|
+
- `src/utils` — shared helpers
|
|
14
|
+
|
|
15
|
+
## Forge commands
|
|
16
|
+
|
|
17
|
+
```bash
|
|
18
|
+
npx forge g setup
|
|
19
|
+
npx forge g init
|
|
20
|
+
npx forge g demo
|
|
21
|
+
npx forge g entity --name Invoice
|
|
22
|
+
npx forge g feature --name Invoice --screens all
|
|
23
|
+
npx forge g component --name Avatar
|
|
24
|
+
npx forge g add --id component:BottomSheet
|
|
25
|
+
npx forge g util --id util:permissions
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
Ready-made components, services, and utils are listed in `node_modules/@effijs/templates/platforms/react-native/CATALOG.md`. Prefer `forge g add` over writing a listed piece from scratch.
|
|
29
|
+
|
|
30
|
+
## Markers
|
|
31
|
+
|
|
32
|
+
Generators insert code at `// forge:<name>` comments. Do not delete those comments.
|
|
33
|
+
|
|
34
|
+
## Config changes
|
|
35
|
+
|
|
36
|
+
If setup could not patch a config, follow `.forge/migrations/*.md` and `node_modules/@effijs/templates/platforms/react-native/ai/SETUP.md`.
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
# Setup requirements
|
|
2
|
+
|
|
3
|
+
Use this file when applying `.forge/migrations/*.md` by hand or with an agent. Change only the config named in the migration. Keep a backup. After each file, the app should still boot `index.js`, which must load `./src`.
|
|
4
|
+
|
|
5
|
+
## .nvmrc
|
|
6
|
+
|
|
7
|
+
The active matrix row names the Node version. Create the file when it is missing. Replace a different version and mention the old value in the summary.
|
|
8
|
+
|
|
9
|
+
## tsconfig.json
|
|
10
|
+
|
|
11
|
+
Keep the existing `extends`. Set:
|
|
12
|
+
|
|
13
|
+
- `compilerOptions.experimentalDecorators` and `compilerOptions.emitDecoratorMetadata` to true
|
|
14
|
+
- `compilerOptions.types` to include `jest`
|
|
15
|
+
- `compilerOptions.paths` for `@*`, `@components`, `@icons`, `@images`, `@widgets`, and `@theme`
|
|
16
|
+
- `exclude` to include `**/node_modules`, `**/Pods`, and `backup/**`
|
|
17
|
+
|
|
18
|
+
Edit with a JSONC-aware tool so comments survive.
|
|
19
|
+
|
|
20
|
+
## babel.config.js
|
|
21
|
+
|
|
22
|
+
Plain object only. Plugin order:
|
|
23
|
+
|
|
24
|
+
1. `babel-plugin-transform-typescript-metadata`
|
|
25
|
+
2. `@babel/plugin-proposal-decorators` with `{ legacy: true }`
|
|
26
|
+
3. The project's other plugins, including `@babel/plugin-transform-export-namespace-from`
|
|
27
|
+
4. `module-resolver` with `root: ['./src']` and the EffiJS aliases (`@app`, `@entity`, `@feature`, `@navigation`, `@services`, `@components`, `@theme`, `@utils`, and the rest from the example)
|
|
28
|
+
5. The matrix's last plugin: `react-native-worklets/plugin` on 0.86, `react-native-reanimated/plugin` on 0.84
|
|
29
|
+
|
|
30
|
+
If the file exports a function, do not rewrite it. Follow the migration instead.
|
|
31
|
+
|
|
32
|
+
## jest.config.js
|
|
33
|
+
|
|
34
|
+
Keep `preset: '@react-native/jest-preset'`. Ignore `/node_modules/` and `/backup/`. `testEnvironment` may be `'node'`. Leave function-valued configs for a migration.
|
|
35
|
+
|
|
36
|
+
## .prettierrc.js
|
|
37
|
+
|
|
38
|
+
Merge, do not drop user keys: `arrowParens: 'avoid'`, `singleQuote: true`, `trailingComma: 'all'`, `printWidth: 120`, `bracketSpacing: true`, `bracketSameLine: true`.
|
|
39
|
+
|
|
40
|
+
## react-native.config.js
|
|
41
|
+
|
|
42
|
+
`assets` must include `./src/ui/fonts/`. Keep `project.ios` and `project.android`.
|
|
43
|
+
|
|
44
|
+
## metro.config.js
|
|
45
|
+
|
|
46
|
+
Leave the stock file unchanged unless setup was run with `--link-local <path>`. That flag fills `watchFolders` and `resolver.extraNodeModules` for the EffiJS packages in that checkout. If `config` is not an empty object, follow the migration.
|
|
47
|
+
|
|
48
|
+
## forge.config.js
|
|
49
|
+
|
|
50
|
+
```js
|
|
51
|
+
export default {
|
|
52
|
+
presets: ['rn-fsd'],
|
|
53
|
+
presetMap: {
|
|
54
|
+
'rn-fsd': '@effijs/templates/presets/react-native-fsd',
|
|
55
|
+
},
|
|
56
|
+
primaryPreset: 'rn-fsd',
|
|
57
|
+
packageManager: 'yarn',
|
|
58
|
+
navigator: 'react-native-navigation',
|
|
59
|
+
outputDir: './src',
|
|
60
|
+
templateEngine: 'handlebars',
|
|
61
|
+
generators: [
|
|
62
|
+
'rn-fsd:setup', 'rn-fsd:init', 'rn-fsd:demo', 'rn-fsd:entity',
|
|
63
|
+
'rn-fsd:feature', 'rn-fsd:component', 'rn-fsd:add', 'rn-fsd:util',
|
|
64
|
+
],
|
|
65
|
+
aliases: {
|
|
66
|
+
setup: 'rn-fsd:setup', init: 'rn-fsd:init', demo: 'rn-fsd:demo',
|
|
67
|
+
entity: 'rn-fsd:entity', feature: 'rn-fsd:feature',
|
|
68
|
+
comp: 'rn-fsd:component', component: 'rn-fsd:component',
|
|
69
|
+
add: 'rn-fsd:add', util: 'rn-fsd:util',
|
|
70
|
+
},
|
|
71
|
+
};
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
`presetMap` is the package path. Forge resolves it through Node, including the package `exports` entry.
|
|
75
|
+
|
|
76
|
+
## index.js
|
|
77
|
+
|
|
78
|
+
A stock AppRegistry file becomes `import './src';`. If the file was edited by hand, follow the migration. After confirmation, move `App.tsx` and `__tests__/App.test.tsx` to `.forge/backup/`.
|
|
79
|
+
|
|
80
|
+
## React Native Navigation
|
|
81
|
+
|
|
82
|
+
`npx rnn-link` must leave `NavigationActivity` and `NavigationApplication` on Android and `RNNAppDelegate` on iOS. The migration's Swift file matches the EffiJS example. The Kotlin fragments are the install-guide shape and have to be checked against this app's current activity and application classes.
|
|
83
|
+
|
|
84
|
+
## Order
|
|
85
|
+
|
|
86
|
+
1. Read the migration title and target.
|
|
87
|
+
2. Apply that file only, using the section above.
|
|
88
|
+
3. Leave `// forge:` markers in `src` untouched.
|
|
89
|
+
4. Stop when the migration's required change is present.
|
|
@@ -0,0 +1,150 @@
|
|
|
1
|
+
const sharedDependencies = {
|
|
2
|
+
'@effijs/common': '3.0.1',
|
|
3
|
+
'@effijs/form-react': '3.0.0',
|
|
4
|
+
'@effijs/logger': '3.0.0',
|
|
5
|
+
'@effijs/props-manager': '3.0.0',
|
|
6
|
+
'@effijs/theme': '3.0.0',
|
|
7
|
+
ramda: '0.32.0',
|
|
8
|
+
dayjs: '1.11.23',
|
|
9
|
+
'query-string': '9.5.0',
|
|
10
|
+
'react-native-gesture-handler': '3.2.1',
|
|
11
|
+
'react-native-keyboard-controller': '1.22.4',
|
|
12
|
+
'react-native-mmkv': '4.3.2',
|
|
13
|
+
'react-native-safe-area-context': '5.9.1',
|
|
14
|
+
};
|
|
15
|
+
|
|
16
|
+
const sharedDevDependencies = {
|
|
17
|
+
'@babel/plugin-proposal-decorators': '7.29.7',
|
|
18
|
+
'@babel/plugin-transform-export-namespace-from': '7.29.7',
|
|
19
|
+
'@types/ramda': '0.32.0',
|
|
20
|
+
'babel-plugin-module-resolver': '5.0.3',
|
|
21
|
+
'babel-plugin-transform-typescript-metadata': '0.4.0',
|
|
22
|
+
eslint: '8.57.1',
|
|
23
|
+
'eslint-config-prettier': '10.1.8',
|
|
24
|
+
'eslint-import-resolver-typescript': '4.4.5',
|
|
25
|
+
'eslint-plugin-ft-flow': '3.0.11',
|
|
26
|
+
'eslint-plugin-import': '2.32.0',
|
|
27
|
+
'eslint-plugin-jest': '29.15.4',
|
|
28
|
+
'eslint-plugin-prettier': '5.5.6',
|
|
29
|
+
prettier: '3.9.4',
|
|
30
|
+
'react-native-asset': '2.1.1',
|
|
31
|
+
};
|
|
32
|
+
|
|
33
|
+
const wixDependencies = {
|
|
34
|
+
'@effijs/navigation-react-native': '3.0.1',
|
|
35
|
+
'react-native-navigation': '8.8.11',
|
|
36
|
+
};
|
|
37
|
+
|
|
38
|
+
const iosAppDelegate = `import UIKit
|
|
39
|
+
import React
|
|
40
|
+
import ReactNativeNavigation
|
|
41
|
+
import ReactAppDependencyProvider
|
|
42
|
+
|
|
43
|
+
@main
|
|
44
|
+
class AppDelegate: RNNAppDelegate {
|
|
45
|
+
override func application(
|
|
46
|
+
_ application: UIApplication,
|
|
47
|
+
didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]? = nil
|
|
48
|
+
) -> Bool {
|
|
49
|
+
self.reactNativeDelegate = ReactNativeDelegate()
|
|
50
|
+
super.application(application, didFinishLaunchingWithOptions: launchOptions)
|
|
51
|
+
|
|
52
|
+
return true
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
class ReactNativeDelegate: RCTDefaultReactNativeFactoryDelegate {
|
|
57
|
+
override func sourceURL(for bridge: RCTBridge) -> URL? {
|
|
58
|
+
self.bundleURL()
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
override func bundleURL() -> URL? {
|
|
62
|
+
#if DEBUG
|
|
63
|
+
RCTBundleURLProvider.sharedSettings().jsBundleURL(forBundleRoot: "index")
|
|
64
|
+
#else
|
|
65
|
+
Bundle.main.url(forResource: "main", withExtension: "jsbundle")
|
|
66
|
+
#endif
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
`;
|
|
70
|
+
|
|
71
|
+
const androidMainActivity = `import com.reactnativenavigation.NavigationActivity
|
|
72
|
+
|
|
73
|
+
class MainActivity : NavigationActivity()
|
|
74
|
+
`;
|
|
75
|
+
|
|
76
|
+
const androidMainApplication = `import android.app.Application
|
|
77
|
+
import com.facebook.react.PackageList
|
|
78
|
+
import com.facebook.react.ReactNativeHost
|
|
79
|
+
import com.facebook.react.ReactPackage
|
|
80
|
+
import com.reactnativenavigation.NavigationApplication
|
|
81
|
+
import com.reactnativenavigation.react.NavigationReactNativeHost
|
|
82
|
+
|
|
83
|
+
class MainApplication : NavigationApplication() {
|
|
84
|
+
override val reactNativeHost: ReactNativeHost =
|
|
85
|
+
object : NavigationReactNativeHost(this) {
|
|
86
|
+
override fun getPackages(): List<ReactPackage> = PackageList(this).packages
|
|
87
|
+
override fun getJSMainModuleName(): String = "index"
|
|
88
|
+
override fun getUseDeveloperSupport(): Boolean = BuildConfig.DEBUG
|
|
89
|
+
override val isNewArchEnabled: Boolean = BuildConfig.IS_NEW_ARCHITECTURE_ENABLED
|
|
90
|
+
override val isHermesEnabled: Boolean = BuildConfig.IS_HERMES_ENABLED
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
`;
|
|
94
|
+
|
|
95
|
+
export const matrix = [
|
|
96
|
+
{
|
|
97
|
+
id: '0.84',
|
|
98
|
+
range: '>=0.84.0 <0.85.0',
|
|
99
|
+
node: '22.11.0',
|
|
100
|
+
babelPluginLast: 'react-native-reanimated/plugin',
|
|
101
|
+
dependencies: {
|
|
102
|
+
...sharedDependencies,
|
|
103
|
+
'react-native-reanimated': '3.17.5',
|
|
104
|
+
},
|
|
105
|
+
devDependencies: sharedDevDependencies,
|
|
106
|
+
navigators: {
|
|
107
|
+
'react-native-navigation': { dependencies: wixDependencies },
|
|
108
|
+
'react-navigation': { dependencies: {} },
|
|
109
|
+
'expo-router': { dependencies: {} },
|
|
110
|
+
},
|
|
111
|
+
native: { iosAppDelegate, androidMainActivity, androidMainApplication },
|
|
112
|
+
optional: {
|
|
113
|
+
skia: { dependencies: { '@shopify/react-native-skia': '2.2.12' } },
|
|
114
|
+
validator: { dependencies: { validator: '13.15.0' } },
|
|
115
|
+
'firebase-app': { dependencies: { '@react-native-firebase/app': '22.4.0' } },
|
|
116
|
+
'firebase-messaging': { dependencies: { '@react-native-firebase/messaging': '22.4.0' } },
|
|
117
|
+
},
|
|
118
|
+
},
|
|
119
|
+
{
|
|
120
|
+
id: '0.86',
|
|
121
|
+
range: '>=0.85.0 <0.87.0',
|
|
122
|
+
node: '22.22.1',
|
|
123
|
+
babelPluginLast: 'react-native-worklets/plugin',
|
|
124
|
+
dependencies: {
|
|
125
|
+
...sharedDependencies,
|
|
126
|
+
'react-native-reanimated': '4.5.3',
|
|
127
|
+
'react-native-worklets': '0.11.4',
|
|
128
|
+
},
|
|
129
|
+
devDependencies: sharedDevDependencies,
|
|
130
|
+
navigators: {
|
|
131
|
+
'react-native-navigation': { dependencies: wixDependencies },
|
|
132
|
+
'react-navigation': { dependencies: {} },
|
|
133
|
+
'expo-router': { dependencies: {} },
|
|
134
|
+
},
|
|
135
|
+
native: { iosAppDelegate, androidMainActivity, androidMainApplication },
|
|
136
|
+
optional: {
|
|
137
|
+
skia: { dependencies: { '@shopify/react-native-skia': '2.11.0' } },
|
|
138
|
+
validator: { dependencies: { validator: '13.15.0' } },
|
|
139
|
+
'firebase-app': { dependencies: { '@react-native-firebase/app': '23.5.0' } },
|
|
140
|
+
'firebase-messaging': { dependencies: { '@react-native-firebase/messaging': '23.5.0' } },
|
|
141
|
+
},
|
|
142
|
+
},
|
|
143
|
+
];
|
|
144
|
+
|
|
145
|
+
export function dependenciesFor(entry, navigator) {
|
|
146
|
+
return {
|
|
147
|
+
...entry.dependencies,
|
|
148
|
+
...(entry.navigators[navigator]?.dependencies ?? {}),
|
|
149
|
+
};
|
|
150
|
+
}
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
export const ALIASES = {
|
|
2
|
+
'@configs': './src/configs',
|
|
3
|
+
'@app': './src/app',
|
|
4
|
+
'@entity': './src/entity',
|
|
5
|
+
'@feature': './src/feature',
|
|
6
|
+
'@navigation': './src/navigation',
|
|
7
|
+
'@services': './src/services',
|
|
8
|
+
'@ui': './src/ui',
|
|
9
|
+
'@components': './src/ui/components',
|
|
10
|
+
'@icons': './src/ui/icons',
|
|
11
|
+
'@images': './src/ui/images',
|
|
12
|
+
'@widgets': './src/ui/widgets',
|
|
13
|
+
'@theme': './src/ui/theme/',
|
|
14
|
+
'@utils': './src/utils',
|
|
15
|
+
'@i18n': './src/i18n',
|
|
16
|
+
'@screens': './src/screens',
|
|
17
|
+
};
|
|
18
|
+
|
|
19
|
+
const HEAD = ['babel-plugin-transform-typescript-metadata', '@babel/plugin-proposal-decorators'];
|
|
20
|
+
const TAIL_NAMES = new Set(['module-resolver', 'react-native-reanimated/plugin', 'react-native-worklets/plugin']);
|
|
21
|
+
|
|
22
|
+
export function pluginName(plugin) {
|
|
23
|
+
if (typeof plugin === 'string') return plugin;
|
|
24
|
+
if (Array.isArray(plugin) && typeof plugin[0] === 'string') return plugin[0];
|
|
25
|
+
return null;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
export function mergeBabelConfig(current, { lastPlugin }) {
|
|
29
|
+
const presets = Array.isArray(current.presets) ? [...current.presets] : [];
|
|
30
|
+
if (!presets.some((item) => String(pluginName(item)).includes('@react-native/babel-preset'))) {
|
|
31
|
+
presets.unshift('module:@react-native/babel-preset');
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
const incoming = Array.isArray(current.plugins) ? current.plugins : [];
|
|
35
|
+
const middle = incoming.filter((plugin) => {
|
|
36
|
+
const name = pluginName(plugin);
|
|
37
|
+
return name && !HEAD.includes(name) && !TAIL_NAMES.has(name);
|
|
38
|
+
});
|
|
39
|
+
if (!middle.some((plugin) => pluginName(plugin) === '@babel/plugin-transform-export-namespace-from')) {
|
|
40
|
+
middle.unshift('@babel/plugin-transform-export-namespace-from');
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
const plugins = [
|
|
44
|
+
'babel-plugin-transform-typescript-metadata',
|
|
45
|
+
['@babel/plugin-proposal-decorators', { legacy: true }],
|
|
46
|
+
...middle,
|
|
47
|
+
[
|
|
48
|
+
'module-resolver',
|
|
49
|
+
{
|
|
50
|
+
root: ['./src'],
|
|
51
|
+
extensions: ['.ios.js', '.android.js', '.js', '.ts', '.tsx', '.json'],
|
|
52
|
+
alias: ALIASES,
|
|
53
|
+
},
|
|
54
|
+
],
|
|
55
|
+
lastPlugin,
|
|
56
|
+
];
|
|
57
|
+
|
|
58
|
+
return { ...current, presets, plugins };
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
export function printModuleExports(value) {
|
|
62
|
+
return `module.exports = ${JSON.stringify(value, null, 2)};\n`;
|
|
63
|
+
}
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
export function renderForgeConfig({ packageManager, navigator }) {
|
|
2
|
+
return `export default {
|
|
3
|
+
presets: ['rn-fsd'],
|
|
4
|
+
presetMap: {
|
|
5
|
+
'rn-fsd': '@effijs/templates/presets/react-native-fsd',
|
|
6
|
+
},
|
|
7
|
+
primaryPreset: 'rn-fsd',
|
|
8
|
+
packageManager: '${packageManager}',
|
|
9
|
+
navigator: '${navigator}',
|
|
10
|
+
outputDir: './src',
|
|
11
|
+
templateEngine: 'handlebars',
|
|
12
|
+
generators: [
|
|
13
|
+
'rn-fsd:setup',
|
|
14
|
+
'rn-fsd:init',
|
|
15
|
+
'rn-fsd:demo',
|
|
16
|
+
'rn-fsd:entity',
|
|
17
|
+
'rn-fsd:feature',
|
|
18
|
+
'rn-fsd:component',
|
|
19
|
+
'rn-fsd:add',
|
|
20
|
+
'rn-fsd:util',
|
|
21
|
+
],
|
|
22
|
+
aliases: {
|
|
23
|
+
setup: 'rn-fsd:setup',
|
|
24
|
+
init: 'rn-fsd:init',
|
|
25
|
+
demo: 'rn-fsd:demo',
|
|
26
|
+
entity: 'rn-fsd:entity',
|
|
27
|
+
feature: 'rn-fsd:feature',
|
|
28
|
+
comp: 'rn-fsd:component',
|
|
29
|
+
component: 'rn-fsd:component',
|
|
30
|
+
add: 'rn-fsd:add',
|
|
31
|
+
util: 'rn-fsd:util',
|
|
32
|
+
},
|
|
33
|
+
};
|
|
34
|
+
`;
|
|
35
|
+
}
|
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
import { isPlainData, requireCjs } from '../../../lib/patch.js';
|
|
2
|
+
import { mergeBabelConfig, printModuleExports } from './babel.js';
|
|
3
|
+
|
|
4
|
+
export function patchBabel(file, content, { exists, lastPlugin }) {
|
|
5
|
+
if (!exists) {
|
|
6
|
+
return {
|
|
7
|
+
ok: true,
|
|
8
|
+
content: printModuleExports(mergeBabelConfig({ presets: ['module:@react-native/babel-preset'], plugins: [] }, { lastPlugin })),
|
|
9
|
+
};
|
|
10
|
+
}
|
|
11
|
+
let loaded;
|
|
12
|
+
try {
|
|
13
|
+
loaded = requireCjs(file);
|
|
14
|
+
} catch (error) {
|
|
15
|
+
return { ok: false, reason: `Could not load babel.config.js: ${error.message}` };
|
|
16
|
+
}
|
|
17
|
+
if (!isPlainData(loaded)) {
|
|
18
|
+
return { ok: false, reason: 'babel.config.js exports functions or class instances.' };
|
|
19
|
+
}
|
|
20
|
+
return { ok: true, content: printModuleExports(mergeBabelConfig(loaded, { lastPlugin })) };
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
export function patchJest(file, content, { exists }) {
|
|
24
|
+
if (!exists) {
|
|
25
|
+
return { ok: true, content: printJest(defaultJest()) };
|
|
26
|
+
}
|
|
27
|
+
let loaded;
|
|
28
|
+
try {
|
|
29
|
+
loaded = requireCjs(file);
|
|
30
|
+
} catch (error) {
|
|
31
|
+
return { ok: false, reason: `Could not load jest.config.js: ${error.message}` };
|
|
32
|
+
}
|
|
33
|
+
if (!isPlainData(loaded)) {
|
|
34
|
+
return { ok: false, reason: 'jest.config.js exports functions or class instances.' };
|
|
35
|
+
}
|
|
36
|
+
return { ok: true, content: printJest({ ...defaultJest(), ...loaded, preset: loaded.preset ?? '@react-native/jest-preset' }) };
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
function defaultJest() {
|
|
40
|
+
return {
|
|
41
|
+
preset: '@react-native/jest-preset',
|
|
42
|
+
testPathIgnorePatterns: ['/node_modules/', '/backup/'],
|
|
43
|
+
testEnvironment: 'node',
|
|
44
|
+
transformIgnorePatterns: [
|
|
45
|
+
'node_modules/(?!(@react-native|react-native|query-string|decode-uri-component|split-on-first|filter-obj)/)',
|
|
46
|
+
],
|
|
47
|
+
};
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
function printJest(value) {
|
|
51
|
+
return `module.exports = ${JSON.stringify(value, null, 2)};\n`;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
export function patchPrettier(file, content, { exists }) {
|
|
55
|
+
const defaults = {
|
|
56
|
+
arrowParens: 'avoid',
|
|
57
|
+
bracketSameLine: true,
|
|
58
|
+
bracketSpacing: true,
|
|
59
|
+
singleQuote: true,
|
|
60
|
+
trailingComma: 'all',
|
|
61
|
+
printWidth: 120,
|
|
62
|
+
};
|
|
63
|
+
if (!exists) return { ok: true, content: `module.exports = ${JSON.stringify(defaults, null, 2)};\n` };
|
|
64
|
+
let loaded;
|
|
65
|
+
try {
|
|
66
|
+
loaded = requireCjs(file);
|
|
67
|
+
} catch (error) {
|
|
68
|
+
return { ok: false, reason: `Could not load Prettier config: ${error.message}` };
|
|
69
|
+
}
|
|
70
|
+
if (!isPlainData(loaded)) {
|
|
71
|
+
return { ok: false, reason: 'Prettier config exports functions or class instances.' };
|
|
72
|
+
}
|
|
73
|
+
return { ok: true, content: `module.exports = ${JSON.stringify({ ...defaults, ...loaded }, null, 2)};\n` };
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
export function patchRnConfig(file, content, { exists }) {
|
|
77
|
+
const defaults = {
|
|
78
|
+
project: { ios: {}, android: {} },
|
|
79
|
+
assets: ['./src/ui/fonts/'],
|
|
80
|
+
};
|
|
81
|
+
if (!exists) return { ok: true, content: `module.exports = ${JSON.stringify(defaults, null, 2)};\n` };
|
|
82
|
+
let loaded;
|
|
83
|
+
try {
|
|
84
|
+
loaded = requireCjs(file);
|
|
85
|
+
} catch (error) {
|
|
86
|
+
return { ok: false, reason: `Could not load react-native.config.js: ${error.message}` };
|
|
87
|
+
}
|
|
88
|
+
if (!isPlainData(loaded)) {
|
|
89
|
+
return { ok: false, reason: 'react-native.config.js exports functions or class instances.' };
|
|
90
|
+
}
|
|
91
|
+
const assets = new Set([...(loaded.assets ?? []), ...defaults.assets]);
|
|
92
|
+
return {
|
|
93
|
+
ok: true,
|
|
94
|
+
content: `module.exports = ${JSON.stringify({ ...loaded, project: { ...defaults.project, ...loaded.project }, assets: [...assets] }, null, 2)};\n`,
|
|
95
|
+
};
|
|
96
|
+
}
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
import path from 'node:path';
|
|
2
|
+
|
|
3
|
+
const PACKAGES = [
|
|
4
|
+
'@effijs/common',
|
|
5
|
+
'@effijs/props-manager',
|
|
6
|
+
'@effijs/theme',
|
|
7
|
+
'@effijs/logger',
|
|
8
|
+
'@effijs/form-react',
|
|
9
|
+
'@effijs/navigation-react-native',
|
|
10
|
+
'@effijs/forge',
|
|
11
|
+
'@effijs/templates',
|
|
12
|
+
];
|
|
13
|
+
|
|
14
|
+
export function linkLocalSource(linkRoot) {
|
|
15
|
+
const root = JSON.stringify(linkRoot);
|
|
16
|
+
const entries = PACKAGES.map((name) => {
|
|
17
|
+
const folder = name.split('/')[1];
|
|
18
|
+
return ` '${name}': path.join(${root}, 'packages/${folder}'),`;
|
|
19
|
+
}).join('\n');
|
|
20
|
+
return `const path = require('path');
|
|
21
|
+
|
|
22
|
+
const linkedPackages = {
|
|
23
|
+
${entries}
|
|
24
|
+
};
|
|
25
|
+
|
|
26
|
+
const config = {
|
|
27
|
+
watchFolders: [...Object.values(linkedPackages)],
|
|
28
|
+
resolver: {
|
|
29
|
+
extraNodeModules: new Proxy(linkedPackages, {
|
|
30
|
+
get: (target, name) => {
|
|
31
|
+
if (name in target) return target[name];
|
|
32
|
+
return path.join(__dirname, 'node_modules', name);
|
|
33
|
+
},
|
|
34
|
+
}),
|
|
35
|
+
},
|
|
36
|
+
};
|
|
37
|
+
`;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
export function patchMetro(content, { exists, linkLocal }) {
|
|
41
|
+
if (!linkLocal) return { ok: true, content, unchanged: true };
|
|
42
|
+
if (!exists) {
|
|
43
|
+
return {
|
|
44
|
+
ok: false,
|
|
45
|
+
reason: 'metro.config.js does not exist, so local package linking was not applied.',
|
|
46
|
+
};
|
|
47
|
+
}
|
|
48
|
+
if (content.includes('linkedPackages')) return { ok: true, content };
|
|
49
|
+
if (!content.includes('mergeConfig(getDefaultConfig(__dirname), config)')) {
|
|
50
|
+
return {
|
|
51
|
+
ok: false,
|
|
52
|
+
reason: 'metro.config.js does not match the React Native CLI template, so watchFolders were not inserted.',
|
|
53
|
+
};
|
|
54
|
+
}
|
|
55
|
+
const block = linkLocalSource(path.resolve(linkLocal));
|
|
56
|
+
let next = content;
|
|
57
|
+
if (!next.includes("require('path')") && !next.includes('require("path")')) {
|
|
58
|
+
next = `const path = require('path');\n${next}`;
|
|
59
|
+
}
|
|
60
|
+
if (/const config = \{\s*\};/.test(next)) {
|
|
61
|
+
next = next.replace(/const config = \{\s*\};/, block.trim().replace(/^const path = require\('path'\);\n\n/, ''));
|
|
62
|
+
} else {
|
|
63
|
+
return {
|
|
64
|
+
ok: false,
|
|
65
|
+
reason: 'metro.config.js has a non-empty config object, so local linking was not inserted.',
|
|
66
|
+
};
|
|
67
|
+
}
|
|
68
|
+
return { ok: true, content: next };
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
export function patchIndexJs(content, { exists }) {
|
|
72
|
+
if (!exists) return { ok: true, content: "import './src';\n" };
|
|
73
|
+
if (content.includes("import './src'") || content.includes('import "./src"')) {
|
|
74
|
+
return { ok: true, content };
|
|
75
|
+
}
|
|
76
|
+
const standard =
|
|
77
|
+
content.includes('AppRegistry.registerComponent') &&
|
|
78
|
+
(content.includes("from './App'") || content.includes('from "./App"'));
|
|
79
|
+
if (!standard) {
|
|
80
|
+
return {
|
|
81
|
+
ok: false,
|
|
82
|
+
reason: 'index.js does not match the React Native AppRegistry template.',
|
|
83
|
+
};
|
|
84
|
+
}
|
|
85
|
+
return { ok: true, content: "import './src';\n" };
|
|
86
|
+
}
|