create-du-app 0.1.2 → 0.1.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +56 -36
- package/package.json +6 -5
- package/src/generate.js +246 -15
- package/src/index.js +8 -8
- package/src/prompts.js +1 -1
- package/src/registry.js +3 -1
- package/templates/mobile/expo/.env.example +5 -0
- package/templates/mobile/expo/.eslintrc.js +7 -0
- package/templates/mobile/expo/.prettierrc.js +7 -0
- package/templates/mobile/expo/.svgrrc.js +9 -0
- package/templates/mobile/expo/README.md +42 -7
- package/templates/mobile/expo/_gitignore +20 -0
- package/templates/mobile/expo/_package.json +62 -1
- package/templates/mobile/expo/app.json +18 -0
- package/templates/mobile/expo/babel.config.js +21 -0
- package/templates/mobile/expo/index.js +5 -0
- package/templates/mobile/expo/metro.config.js +31 -0
- package/templates/mobile/expo/src/app/App.tsx +24 -0
- package/templates/mobile/expo/src/app/app-provider.tsx +36 -0
- package/templates/mobile/expo/src/app/config/translation.ts +26 -0
- package/templates/mobile/expo/src/app/index.ts +1 -0
- package/templates/mobile/expo/src/app/navigation/app-route-type.ts +27 -0
- package/templates/mobile/expo/src/app/navigation/bottom-tabs.tsx +34 -0
- package/templates/mobile/expo/src/app/navigation/index.tsx +14 -0
- package/templates/mobile/expo/src/app/stores/auth.store.ts +33 -0
- package/templates/mobile/expo/src/app/stores/common.store.ts +19 -0
- package/templates/mobile/expo/src/app/stores/index.ts +3 -0
- package/templates/mobile/expo/src/app/stores/loading.store.ts +22 -0
- package/templates/mobile/expo/src/assets/Images/empty-list.png +0 -0
- package/templates/mobile/expo/src/assets/Images/index.ts +5 -0
- package/templates/mobile/expo/src/assets/Images/screen-bg-gradian.png +0 -0
- package/templates/mobile/expo/src/assets/i18n/en.json +12 -0
- package/templates/mobile/expo/src/assets/i18n/fr.json +12 -0
- package/templates/mobile/expo/src/assets/lotties/index.ts +3 -0
- package/templates/mobile/expo/src/assets/lotties/loading.json +1 -0
- package/templates/mobile/expo/src/assets/svgs/arrow-left.svg +3 -0
- package/templates/mobile/expo/src/assets/svgs/arrow-right.svg +3 -0
- package/templates/mobile/expo/src/assets/svgs/calendar.svg +12 -0
- package/templates/mobile/expo/src/assets/svgs/check.svg +3 -0
- package/templates/mobile/expo/src/assets/svgs/close.svg +3 -0
- package/templates/mobile/expo/src/assets/svgs/eye-hide.svg +3 -0
- package/templates/mobile/expo/src/assets/svgs/eye.svg +4 -0
- package/templates/mobile/expo/src/assets/svgs/index.ts +29 -0
- package/templates/mobile/expo/src/assets/svgs/minus.svg +3 -0
- package/templates/mobile/expo/src/assets/svgs/plus.svg +3 -0
- package/templates/mobile/expo/src/assets/svgs/search.svg +3 -0
- package/templates/mobile/expo/src/assets/svgs/toast-error.svg +5 -0
- package/templates/mobile/expo/src/assets/svgs/toast-success.svg +4 -0
- package/templates/mobile/expo/src/core/api/endpoints.ts +8 -0
- package/templates/mobile/expo/src/core/api/example.api.ts +53 -0
- package/templates/mobile/expo/src/core/api/index.ts +4 -0
- package/templates/mobile/expo/src/core/components/common/index.ts +1 -0
- package/templates/mobile/expo/src/core/components/common/list-empty/index.ts +2 -0
- package/templates/mobile/expo/src/core/components/common/list-empty/list-empty.tsx +30 -0
- package/templates/mobile/expo/src/core/components/common/list-empty/list-empty.type.ts +5 -0
- package/templates/mobile/expo/src/core/components/forms/hf-date-time.tsx +301 -0
- package/templates/mobile/expo/src/core/components/forms/hf-password-input.tsx +153 -0
- package/templates/mobile/expo/src/core/components/forms/hf-text-input.tsx +59 -0
- package/templates/mobile/expo/src/core/components/forms/hf-time-picker.tsx +117 -0
- package/templates/mobile/expo/src/core/components/forms/index.ts +4 -0
- package/templates/mobile/expo/src/core/components/index.ts +5 -0
- package/templates/mobile/expo/src/core/components/loading/index.ts +1 -0
- package/templates/mobile/expo/src/core/components/loading/loading-app/index.ts +1 -0
- package/templates/mobile/expo/src/core/components/loading/loading-app/loading-app.tsx +50 -0
- package/templates/mobile/expo/src/core/components/offline/index.ts +1 -0
- package/templates/mobile/expo/src/core/components/offline/offline-banner.tsx +186 -0
- package/templates/mobile/expo/src/core/components/screen/index.ts +1 -0
- package/templates/mobile/expo/src/core/components/screen/screen-container/index.ts +1 -0
- package/templates/mobile/expo/src/core/components/screen/screen-container/screen-container.tsx +252 -0
- package/templates/mobile/expo/src/core/components/splash/index.ts +1 -0
- package/templates/mobile/expo/src/core/components/splash/splash-overlay/index.ts +1 -0
- package/templates/mobile/expo/src/core/components/splash/splash-overlay/splash-overlay.tsx +93 -0
- package/templates/mobile/expo/src/core/components/ui/animated-list-item/animated-list-item.tsx +48 -0
- package/templates/mobile/expo/src/core/components/ui/animated-list-item/animated-list-item.type.ts +10 -0
- package/templates/mobile/expo/src/core/components/ui/animated-list-item/index.ts +2 -0
- package/templates/mobile/expo/src/core/components/ui/app-image/app-image.tsx +104 -0
- package/templates/mobile/expo/src/core/components/ui/app-image/app-image.type.ts +19 -0
- package/templates/mobile/expo/src/core/components/ui/app-image/index.ts +2 -0
- package/templates/mobile/expo/src/core/components/ui/asset-placeholder/asset-placeholder.tsx +76 -0
- package/templates/mobile/expo/src/core/components/ui/asset-placeholder/index.ts +1 -0
- package/templates/mobile/expo/src/core/components/ui/avatar-image/avatar-image.tsx +90 -0
- package/templates/mobile/expo/src/core/components/ui/avatar-image/index.ts +1 -0
- package/templates/mobile/expo/src/core/components/ui/bottom-sheet/bottom-sheet.tsx +145 -0
- package/templates/mobile/expo/src/core/components/ui/bottom-sheet/bottom-sheet.type.ts +10 -0
- package/templates/mobile/expo/src/core/components/ui/bottom-sheet/index.ts +2 -0
- package/templates/mobile/expo/src/core/components/ui/button/button.style.ts +146 -0
- package/templates/mobile/expo/src/core/components/ui/button/button.tsx +97 -0
- package/templates/mobile/expo/src/core/components/ui/button/button.type.ts +47 -0
- package/templates/mobile/expo/src/core/components/ui/button/index.ts +4 -0
- package/templates/mobile/expo/src/core/components/ui/checkbox/checkbox.tsx +127 -0
- package/templates/mobile/expo/src/core/components/ui/checkbox/checkbox.type.ts +24 -0
- package/templates/mobile/expo/src/core/components/ui/checkbox/index.ts +2 -0
- package/templates/mobile/expo/src/core/components/ui/collapsible-section/collapsible-section.tsx +141 -0
- package/templates/mobile/expo/src/core/components/ui/collapsible-section/collapsible-section.type.ts +10 -0
- package/templates/mobile/expo/src/core/components/ui/collapsible-section/index.ts +2 -0
- package/templates/mobile/expo/src/core/components/ui/components.registry.json +313 -0
- package/templates/mobile/expo/src/core/components/ui/field/field-frame.tsx +62 -0
- package/templates/mobile/expo/src/core/components/ui/field/field.shared.ts +31 -0
- package/templates/mobile/expo/src/core/components/ui/header/header.tsx +196 -0
- package/templates/mobile/expo/src/core/components/ui/header/header.type.ts +30 -0
- package/templates/mobile/expo/src/core/components/ui/header/index.ts +2 -0
- package/templates/mobile/expo/src/core/components/ui/icon-button/icon-button.style.ts +23 -0
- package/templates/mobile/expo/src/core/components/ui/icon-button/icon-button.tsx +66 -0
- package/templates/mobile/expo/src/core/components/ui/icon-button/icon-button.type.ts +25 -0
- package/templates/mobile/expo/src/core/components/ui/icon-button/index.ts +2 -0
- package/templates/mobile/expo/src/core/components/ui/image-slider/image-slider.tsx +107 -0
- package/templates/mobile/expo/src/core/components/ui/image-slider/image-slider.type.ts +10 -0
- package/templates/mobile/expo/src/core/components/ui/image-slider/index.ts +2 -0
- package/templates/mobile/expo/src/core/components/ui/index.ts +25 -0
- package/templates/mobile/expo/src/core/components/ui/label/index.ts +2 -0
- package/templates/mobile/expo/src/core/components/ui/label/label.tsx +36 -0
- package/templates/mobile/expo/src/core/components/ui/label/label.type.ts +12 -0
- package/templates/mobile/expo/src/core/components/ui/modal/index.ts +2 -0
- package/templates/mobile/expo/src/core/components/ui/modal/modal.tsx +62 -0
- package/templates/mobile/expo/src/core/components/ui/modal/modal.type.ts +11 -0
- package/templates/mobile/expo/src/core/components/ui/otp-input/index.ts +2 -0
- package/templates/mobile/expo/src/core/components/ui/otp-input/otp-input.tsx +129 -0
- package/templates/mobile/expo/src/core/components/ui/otp-input/otp-input.type.ts +20 -0
- package/templates/mobile/expo/src/core/components/ui/page-dots/index.ts +1 -0
- package/templates/mobile/expo/src/core/components/ui/page-dots/page-dots.tsx +60 -0
- package/templates/mobile/expo/src/core/components/ui/radio/index.ts +2 -0
- package/templates/mobile/expo/src/core/components/ui/radio/radio.tsx +121 -0
- package/templates/mobile/expo/src/core/components/ui/radio/radio.type.ts +20 -0
- package/templates/mobile/expo/src/core/components/ui/screen/index.ts +1 -0
- package/templates/mobile/expo/src/core/components/ui/screen/screen-gradient.tsx +33 -0
- package/templates/mobile/expo/src/core/components/ui/search-box/index.ts +2 -0
- package/templates/mobile/expo/src/core/components/ui/search-box/search-box.tsx +162 -0
- package/templates/mobile/expo/src/core/components/ui/search-box/search-box.type.ts +26 -0
- package/templates/mobile/expo/src/core/components/ui/segmented-control/index.ts +2 -0
- package/templates/mobile/expo/src/core/components/ui/segmented-control/segmented-control.tsx +86 -0
- package/templates/mobile/expo/src/core/components/ui/segmented-control/segmented-control.type.ts +22 -0
- package/templates/mobile/expo/src/core/components/ui/skeleton/index.ts +2 -0
- package/templates/mobile/expo/src/core/components/ui/skeleton/skeleton.tsx +106 -0
- package/templates/mobile/expo/src/core/components/ui/skeleton/skeleton.type.ts +8 -0
- package/templates/mobile/expo/src/core/components/ui/success-state/index.ts +1 -0
- package/templates/mobile/expo/src/core/components/ui/success-state/success-state.tsx +68 -0
- package/templates/mobile/expo/src/core/components/ui/tabs/index.ts +2 -0
- package/templates/mobile/expo/src/core/components/ui/tabs/tabs.tsx +273 -0
- package/templates/mobile/expo/src/core/components/ui/tabs/tabs.type.ts +21 -0
- package/templates/mobile/expo/src/core/components/ui/tag-input/index.ts +2 -0
- package/templates/mobile/expo/src/core/components/ui/tag-input/tag-input.tsx +146 -0
- package/templates/mobile/expo/src/core/components/ui/tag-input/tag-input.type.ts +22 -0
- package/templates/mobile/expo/src/core/components/ui/text-area/index.ts +2 -0
- package/templates/mobile/expo/src/core/components/ui/text-area/text-area.tsx +90 -0
- package/templates/mobile/expo/src/core/components/ui/text-area/text-area.type.ts +20 -0
- package/templates/mobile/expo/src/core/components/ui/text-field/index.ts +2 -0
- package/templates/mobile/expo/src/core/components/ui/text-field/text-field.tsx +116 -0
- package/templates/mobile/expo/src/core/components/ui/text-field/text-field.type.ts +21 -0
- package/templates/mobile/expo/src/core/components/ui/toggle/index.ts +2 -0
- package/templates/mobile/expo/src/core/components/ui/toggle/toggle.tsx +110 -0
- package/templates/mobile/expo/src/core/components/ui/toggle/toggle.type.ts +19 -0
- package/templates/mobile/expo/src/core/constants/external-urls.constant.ts +5 -0
- package/templates/mobile/expo/src/core/constants/hard-data.constant.ts +0 -0
- package/templates/mobile/expo/src/core/constants/index.ts +2 -0
- package/templates/mobile/expo/src/core/constants/type.constant.ts +3 -0
- package/templates/mobile/expo/src/core/context/index.ts +1 -0
- package/templates/mobile/expo/src/core/context/shared-transition-context.tsx +35 -0
- package/templates/mobile/expo/src/core/hook/index.ts +8 -0
- package/templates/mobile/expo/src/core/hook/useActiveRouteName.ts +63 -0
- package/templates/mobile/expo/src/core/hook/useAppNavigation.tsx +7 -0
- package/templates/mobile/expo/src/core/hook/useBottomInset.tsx +26 -0
- package/templates/mobile/expo/src/core/hook/useDebounce.tsx +16 -0
- package/templates/mobile/expo/src/core/hook/useEndReached.tsx +46 -0
- package/templates/mobile/expo/src/core/hook/useManualRefetch.ts +56 -0
- package/templates/mobile/expo/src/core/hook/useNetworkStatus.ts +68 -0
- package/templates/mobile/expo/src/core/hook/useTimeout.tsx +30 -0
- package/templates/mobile/expo/src/core/index.ts +7 -0
- package/templates/mobile/expo/src/core/services/api.service.ts +230 -0
- package/templates/mobile/expo/src/core/services/device-id.service.ts +23 -0
- package/templates/mobile/expo/src/core/services/index.ts +3 -0
- package/templates/mobile/expo/src/core/services/session-end.bridge.ts +26 -0
- package/templates/mobile/expo/src/core/theme/dark.theme.ts +10 -0
- package/templates/mobile/expo/src/core/theme/index.ts +5 -0
- package/templates/mobile/expo/src/core/theme/light.theme.ts +44 -0
- package/templates/mobile/expo/src/core/theme/theme-context.tsx +82 -0
- package/templates/mobile/expo/src/core/theme/theme.types.ts +26 -0
- package/templates/mobile/expo/src/core/theme/use-themed-styles.ts +25 -0
- package/templates/mobile/expo/src/core/utils/color.util.tsx +198 -0
- package/templates/mobile/expo/src/core/utils/date.util.ts +97 -0
- package/templates/mobile/expo/src/core/utils/device-locale.util.ts +22 -0
- package/templates/mobile/expo/src/core/utils/emitter/index.ts +161 -0
- package/templates/mobile/expo/src/core/utils/emitter/type.ts +40 -0
- package/templates/mobile/expo/src/core/utils/enum.util.tsx +15 -0
- package/templates/mobile/expo/src/core/utils/font.util.tsx +42 -0
- package/templates/mobile/expo/src/core/utils/func.util.ts +48 -0
- package/templates/mobile/expo/src/core/utils/greeting.util.ts +20 -0
- package/templates/mobile/expo/src/core/utils/image-format.util.ts +117 -0
- package/templates/mobile/expo/src/core/utils/image-picker.util.ts +84 -0
- package/templates/mobile/expo/src/core/utils/index.ts +18 -0
- package/templates/mobile/expo/src/core/utils/linking.util.ts +16 -0
- package/templates/mobile/expo/src/core/utils/navigation.util.tsx +100 -0
- package/templates/mobile/expo/src/core/utils/number-format.ts +28 -0
- package/templates/mobile/expo/src/core/utils/query-client.util.ts +35 -0
- package/templates/mobile/expo/src/core/utils/query-persister.util.ts +36 -0
- package/templates/mobile/expo/src/core/utils/schema.util.tsx +2713 -0
- package/templates/mobile/expo/src/core/utils/size.util.tsx +74 -0
- package/templates/mobile/expo/src/core/utils/storage.util.tsx +53 -0
- package/templates/mobile/expo/src/core/utils/toast.util.tsx +151 -0
- package/templates/mobile/expo/src/core/utils/translator.util.tsx +23 -0
- package/templates/mobile/expo/src/core/utils/typography.util.tsx +69 -0
- package/templates/mobile/expo/src/core/utils/validate.util.tsx +13 -0
- package/templates/mobile/expo/src/declarations.d.ts +54 -0
- package/templates/mobile/expo/src/modules/home/home.screen.tsx +33 -0
- package/templates/mobile/expo/src/modules/profile/profile.screen.tsx +29 -0
- package/templates/mobile/expo/src/scripts/link-fonts.js +60 -0
- package/templates/mobile/expo/src/scripts/sync-images.js +56 -0
- package/templates/mobile/expo/src/scripts/sync-svgs.js +50 -0
- package/templates/mobile/expo/src/types/models.d.ts +24 -0
- package/templates/mobile/expo/tsconfig.json +19 -0
- package/templates/mobile/rn/.env.example +5 -0
- package/templates/mobile/rn/.eslintrc.js +7 -0
- package/templates/mobile/rn/.prettierrc.js +7 -0
- package/templates/mobile/rn/.svgrrc.js +9 -0
- package/templates/mobile/rn/README.md +40 -7
- package/templates/mobile/rn/_gitignore +24 -0
- package/templates/mobile/rn/_package.json +67 -1
- package/templates/mobile/rn/app.json +4 -0
- package/templates/mobile/rn/babel.config.js +18 -0
- package/templates/mobile/rn/index.js +8 -0
- package/templates/mobile/rn/metro.config.js +33 -0
- package/templates/mobile/rn/src/app/App.tsx +24 -0
- package/templates/mobile/rn/src/app/app-provider.tsx +36 -0
- package/templates/mobile/rn/src/app/config/translation.ts +26 -0
- package/templates/mobile/rn/src/app/index.ts +1 -0
- package/templates/mobile/rn/src/app/navigation/app-route-type.ts +27 -0
- package/templates/mobile/rn/src/app/navigation/bottom-tabs.tsx +34 -0
- package/templates/mobile/rn/src/app/navigation/index.tsx +14 -0
- package/templates/mobile/rn/src/app/stores/auth.store.ts +33 -0
- package/templates/mobile/rn/src/app/stores/common.store.ts +19 -0
- package/templates/mobile/rn/src/app/stores/index.ts +3 -0
- package/templates/mobile/rn/src/app/stores/loading.store.ts +22 -0
- package/templates/mobile/rn/src/assets/Images/empty-list.png +0 -0
- package/templates/mobile/rn/src/assets/Images/index.ts +5 -0
- package/templates/mobile/rn/src/assets/Images/screen-bg-gradian.png +0 -0
- package/templates/mobile/rn/src/assets/i18n/en.json +12 -0
- package/templates/mobile/rn/src/assets/i18n/fr.json +12 -0
- package/templates/mobile/rn/src/assets/lotties/index.ts +3 -0
- package/templates/mobile/rn/src/assets/lotties/loading.json +1 -0
- package/templates/mobile/rn/src/assets/svgs/arrow-left.svg +3 -0
- package/templates/mobile/rn/src/assets/svgs/arrow-right.svg +3 -0
- package/templates/mobile/rn/src/assets/svgs/calendar.svg +12 -0
- package/templates/mobile/rn/src/assets/svgs/check.svg +3 -0
- package/templates/mobile/rn/src/assets/svgs/close.svg +3 -0
- package/templates/mobile/rn/src/assets/svgs/eye-hide.svg +3 -0
- package/templates/mobile/rn/src/assets/svgs/eye.svg +4 -0
- package/templates/mobile/rn/src/assets/svgs/index.ts +29 -0
- package/templates/mobile/rn/src/assets/svgs/minus.svg +3 -0
- package/templates/mobile/rn/src/assets/svgs/plus.svg +3 -0
- package/templates/mobile/rn/src/assets/svgs/search.svg +3 -0
- package/templates/mobile/rn/src/assets/svgs/toast-error.svg +5 -0
- package/templates/mobile/rn/src/assets/svgs/toast-success.svg +4 -0
- package/templates/mobile/rn/src/core/api/endpoints.ts +8 -0
- package/templates/mobile/rn/src/core/api/example.api.ts +53 -0
- package/templates/mobile/rn/src/core/api/index.ts +4 -0
- package/templates/mobile/rn/src/core/components/common/index.ts +1 -0
- package/templates/mobile/rn/src/core/components/common/list-empty/index.ts +2 -0
- package/templates/mobile/rn/src/core/components/common/list-empty/list-empty.tsx +30 -0
- package/templates/mobile/rn/src/core/components/common/list-empty/list-empty.type.ts +5 -0
- package/templates/mobile/rn/src/core/components/forms/hf-date-time.tsx +301 -0
- package/templates/mobile/rn/src/core/components/forms/hf-password-input.tsx +153 -0
- package/templates/mobile/rn/src/core/components/forms/hf-text-input.tsx +59 -0
- package/templates/mobile/rn/src/core/components/forms/hf-time-picker.tsx +117 -0
- package/templates/mobile/rn/src/core/components/forms/index.ts +4 -0
- package/templates/mobile/rn/src/core/components/index.ts +5 -0
- package/templates/mobile/rn/src/core/components/loading/index.ts +1 -0
- package/templates/mobile/rn/src/core/components/loading/loading-app/index.ts +1 -0
- package/templates/mobile/rn/src/core/components/loading/loading-app/loading-app.tsx +50 -0
- package/templates/mobile/rn/src/core/components/offline/index.ts +1 -0
- package/templates/mobile/rn/src/core/components/offline/offline-banner.tsx +186 -0
- package/templates/mobile/rn/src/core/components/screen/index.ts +1 -0
- package/templates/mobile/rn/src/core/components/screen/screen-container/index.ts +1 -0
- package/templates/mobile/rn/src/core/components/screen/screen-container/screen-container.tsx +252 -0
- package/templates/mobile/rn/src/core/components/splash/index.ts +1 -0
- package/templates/mobile/rn/src/core/components/splash/splash-overlay/index.ts +1 -0
- package/templates/mobile/rn/src/core/components/splash/splash-overlay/splash-overlay.tsx +93 -0
- package/templates/mobile/rn/src/core/components/ui/animated-list-item/animated-list-item.tsx +48 -0
- package/templates/mobile/rn/src/core/components/ui/animated-list-item/animated-list-item.type.ts +10 -0
- package/templates/mobile/rn/src/core/components/ui/animated-list-item/index.ts +2 -0
- package/templates/mobile/rn/src/core/components/ui/app-image/app-image.tsx +104 -0
- package/templates/mobile/rn/src/core/components/ui/app-image/app-image.type.ts +19 -0
- package/templates/mobile/rn/src/core/components/ui/app-image/index.ts +2 -0
- package/templates/mobile/rn/src/core/components/ui/asset-placeholder/asset-placeholder.tsx +76 -0
- package/templates/mobile/rn/src/core/components/ui/asset-placeholder/index.ts +1 -0
- package/templates/mobile/rn/src/core/components/ui/avatar-image/avatar-image.tsx +90 -0
- package/templates/mobile/rn/src/core/components/ui/avatar-image/index.ts +1 -0
- package/templates/mobile/rn/src/core/components/ui/bottom-sheet/bottom-sheet.tsx +145 -0
- package/templates/mobile/rn/src/core/components/ui/bottom-sheet/bottom-sheet.type.ts +10 -0
- package/templates/mobile/rn/src/core/components/ui/bottom-sheet/index.ts +2 -0
- package/templates/mobile/rn/src/core/components/ui/button/button.style.ts +146 -0
- package/templates/mobile/rn/src/core/components/ui/button/button.tsx +97 -0
- package/templates/mobile/rn/src/core/components/ui/button/button.type.ts +47 -0
- package/templates/mobile/rn/src/core/components/ui/button/index.ts +4 -0
- package/templates/mobile/rn/src/core/components/ui/checkbox/checkbox.tsx +127 -0
- package/templates/mobile/rn/src/core/components/ui/checkbox/checkbox.type.ts +24 -0
- package/templates/mobile/rn/src/core/components/ui/checkbox/index.ts +2 -0
- package/templates/mobile/rn/src/core/components/ui/collapsible-section/collapsible-section.tsx +141 -0
- package/templates/mobile/rn/src/core/components/ui/collapsible-section/collapsible-section.type.ts +10 -0
- package/templates/mobile/rn/src/core/components/ui/collapsible-section/index.ts +2 -0
- package/templates/mobile/rn/src/core/components/ui/components.registry.json +313 -0
- package/templates/mobile/rn/src/core/components/ui/field/field-frame.tsx +62 -0
- package/templates/mobile/rn/src/core/components/ui/field/field.shared.ts +31 -0
- package/templates/mobile/rn/src/core/components/ui/header/header.tsx +196 -0
- package/templates/mobile/rn/src/core/components/ui/header/header.type.ts +30 -0
- package/templates/mobile/rn/src/core/components/ui/header/index.ts +2 -0
- package/templates/mobile/rn/src/core/components/ui/icon-button/icon-button.style.ts +23 -0
- package/templates/mobile/rn/src/core/components/ui/icon-button/icon-button.tsx +66 -0
- package/templates/mobile/rn/src/core/components/ui/icon-button/icon-button.type.ts +25 -0
- package/templates/mobile/rn/src/core/components/ui/icon-button/index.ts +2 -0
- package/templates/mobile/rn/src/core/components/ui/image-slider/image-slider.tsx +107 -0
- package/templates/mobile/rn/src/core/components/ui/image-slider/image-slider.type.ts +10 -0
- package/templates/mobile/rn/src/core/components/ui/image-slider/index.ts +2 -0
- package/templates/mobile/rn/src/core/components/ui/index.ts +25 -0
- package/templates/mobile/rn/src/core/components/ui/label/index.ts +2 -0
- package/templates/mobile/rn/src/core/components/ui/label/label.tsx +36 -0
- package/templates/mobile/rn/src/core/components/ui/label/label.type.ts +12 -0
- package/templates/mobile/rn/src/core/components/ui/modal/index.ts +2 -0
- package/templates/mobile/rn/src/core/components/ui/modal/modal.tsx +62 -0
- package/templates/mobile/rn/src/core/components/ui/modal/modal.type.ts +11 -0
- package/templates/mobile/rn/src/core/components/ui/otp-input/index.ts +2 -0
- package/templates/mobile/rn/src/core/components/ui/otp-input/otp-input.tsx +129 -0
- package/templates/mobile/rn/src/core/components/ui/otp-input/otp-input.type.ts +20 -0
- package/templates/mobile/rn/src/core/components/ui/page-dots/index.ts +1 -0
- package/templates/mobile/rn/src/core/components/ui/page-dots/page-dots.tsx +60 -0
- package/templates/mobile/rn/src/core/components/ui/radio/index.ts +2 -0
- package/templates/mobile/rn/src/core/components/ui/radio/radio.tsx +121 -0
- package/templates/mobile/rn/src/core/components/ui/radio/radio.type.ts +20 -0
- package/templates/mobile/rn/src/core/components/ui/screen/index.ts +1 -0
- package/templates/mobile/rn/src/core/components/ui/screen/screen-gradient.tsx +33 -0
- package/templates/mobile/rn/src/core/components/ui/search-box/index.ts +2 -0
- package/templates/mobile/rn/src/core/components/ui/search-box/search-box.tsx +162 -0
- package/templates/mobile/rn/src/core/components/ui/search-box/search-box.type.ts +26 -0
- package/templates/mobile/rn/src/core/components/ui/segmented-control/index.ts +2 -0
- package/templates/mobile/rn/src/core/components/ui/segmented-control/segmented-control.tsx +86 -0
- package/templates/mobile/rn/src/core/components/ui/segmented-control/segmented-control.type.ts +22 -0
- package/templates/mobile/rn/src/core/components/ui/skeleton/index.ts +2 -0
- package/templates/mobile/rn/src/core/components/ui/skeleton/skeleton.tsx +106 -0
- package/templates/mobile/rn/src/core/components/ui/skeleton/skeleton.type.ts +8 -0
- package/templates/mobile/rn/src/core/components/ui/success-state/index.ts +1 -0
- package/templates/mobile/rn/src/core/components/ui/success-state/success-state.tsx +68 -0
- package/templates/mobile/rn/src/core/components/ui/tabs/index.ts +2 -0
- package/templates/mobile/rn/src/core/components/ui/tabs/tabs.tsx +273 -0
- package/templates/mobile/rn/src/core/components/ui/tabs/tabs.type.ts +21 -0
- package/templates/mobile/rn/src/core/components/ui/tag-input/index.ts +2 -0
- package/templates/mobile/rn/src/core/components/ui/tag-input/tag-input.tsx +146 -0
- package/templates/mobile/rn/src/core/components/ui/tag-input/tag-input.type.ts +22 -0
- package/templates/mobile/rn/src/core/components/ui/text-area/index.ts +2 -0
- package/templates/mobile/rn/src/core/components/ui/text-area/text-area.tsx +90 -0
- package/templates/mobile/rn/src/core/components/ui/text-area/text-area.type.ts +20 -0
- package/templates/mobile/rn/src/core/components/ui/text-field/index.ts +2 -0
- package/templates/mobile/rn/src/core/components/ui/text-field/text-field.tsx +116 -0
- package/templates/mobile/rn/src/core/components/ui/text-field/text-field.type.ts +21 -0
- package/templates/mobile/rn/src/core/components/ui/toggle/index.ts +2 -0
- package/templates/mobile/rn/src/core/components/ui/toggle/toggle.tsx +110 -0
- package/templates/mobile/rn/src/core/components/ui/toggle/toggle.type.ts +19 -0
- package/templates/mobile/rn/src/core/constants/external-urls.constant.ts +5 -0
- package/templates/mobile/rn/src/core/constants/hard-data.constant.ts +0 -0
- package/templates/mobile/rn/src/core/constants/index.ts +2 -0
- package/templates/mobile/rn/src/core/constants/type.constant.ts +3 -0
- package/templates/mobile/rn/src/core/context/index.ts +1 -0
- package/templates/mobile/rn/src/core/context/shared-transition-context.tsx +35 -0
- package/templates/mobile/rn/src/core/hook/index.ts +8 -0
- package/templates/mobile/rn/src/core/hook/useActiveRouteName.ts +63 -0
- package/templates/mobile/rn/src/core/hook/useAppNavigation.tsx +7 -0
- package/templates/mobile/rn/src/core/hook/useBottomInset.tsx +26 -0
- package/templates/mobile/rn/src/core/hook/useDebounce.tsx +16 -0
- package/templates/mobile/rn/src/core/hook/useEndReached.tsx +46 -0
- package/templates/mobile/rn/src/core/hook/useManualRefetch.ts +56 -0
- package/templates/mobile/rn/src/core/hook/useNetworkStatus.ts +68 -0
- package/templates/mobile/rn/src/core/hook/useTimeout.tsx +30 -0
- package/templates/mobile/rn/src/core/index.ts +7 -0
- package/templates/mobile/rn/src/core/services/api.service.ts +230 -0
- package/templates/mobile/rn/src/core/services/device-id.service.ts +23 -0
- package/templates/mobile/rn/src/core/services/index.ts +3 -0
- package/templates/mobile/rn/src/core/services/session-end.bridge.ts +26 -0
- package/templates/mobile/rn/src/core/theme/dark.theme.ts +10 -0
- package/templates/mobile/rn/src/core/theme/index.ts +5 -0
- package/templates/mobile/rn/src/core/theme/light.theme.ts +44 -0
- package/templates/mobile/rn/src/core/theme/theme-context.tsx +82 -0
- package/templates/mobile/rn/src/core/theme/theme.types.ts +26 -0
- package/templates/mobile/rn/src/core/theme/use-themed-styles.ts +25 -0
- package/templates/mobile/rn/src/core/utils/color.util.tsx +198 -0
- package/templates/mobile/rn/src/core/utils/date.util.ts +97 -0
- package/templates/mobile/rn/src/core/utils/device-locale.util.ts +22 -0
- package/templates/mobile/rn/src/core/utils/emitter/index.ts +161 -0
- package/templates/mobile/rn/src/core/utils/emitter/type.ts +40 -0
- package/templates/mobile/rn/src/core/utils/enum.util.tsx +15 -0
- package/templates/mobile/rn/src/core/utils/font.util.tsx +42 -0
- package/templates/mobile/rn/src/core/utils/func.util.ts +48 -0
- package/templates/mobile/rn/src/core/utils/greeting.util.ts +20 -0
- package/templates/mobile/rn/src/core/utils/image-format.util.ts +117 -0
- package/templates/mobile/rn/src/core/utils/image-picker.util.ts +84 -0
- package/templates/mobile/rn/src/core/utils/index.ts +18 -0
- package/templates/mobile/rn/src/core/utils/linking.util.ts +16 -0
- package/templates/mobile/rn/src/core/utils/navigation.util.tsx +100 -0
- package/templates/mobile/rn/src/core/utils/number-format.ts +28 -0
- package/templates/mobile/rn/src/core/utils/query-client.util.ts +35 -0
- package/templates/mobile/rn/src/core/utils/query-persister.util.ts +36 -0
- package/templates/mobile/rn/src/core/utils/schema.util.tsx +2713 -0
- package/templates/mobile/rn/src/core/utils/size.util.tsx +74 -0
- package/templates/mobile/rn/src/core/utils/storage.util.tsx +53 -0
- package/templates/mobile/rn/src/core/utils/toast.util.tsx +151 -0
- package/templates/mobile/rn/src/core/utils/translator.util.tsx +23 -0
- package/templates/mobile/rn/src/core/utils/typography.util.tsx +69 -0
- package/templates/mobile/rn/src/core/utils/validate.util.tsx +13 -0
- package/templates/mobile/rn/src/declarations.d.ts +54 -0
- package/templates/mobile/rn/src/modules/home/home.screen.tsx +33 -0
- package/templates/mobile/rn/src/modules/profile/profile.screen.tsx +29 -0
- package/templates/mobile/rn/src/scripts/link-fonts.js +60 -0
- package/templates/mobile/rn/src/scripts/sync-images.js +56 -0
- package/templates/mobile/rn/src/scripts/sync-svgs.js +50 -0
- package/templates/mobile/rn/src/types/models.d.ts +24 -0
- package/templates/mobile/rn/tsconfig.json +21 -0
- package/templates/shared/README.md +21 -6
- package/templates/shared/_package.json +26 -4
- package/templates/shared/src/api-endpoints.ts +8 -0
- package/templates/shared/src/enums.ts +34 -0
- package/templates/shared/src/external-urls.ts +5 -0
- package/templates/shared/src/index.ts +15 -0
- package/templates/shared/tsconfig.json +8 -0
- package/templates/shared/tsup.config.ts +9 -0
- package/templates/shared/index.js +0 -4
package/README.md
CHANGED
|
@@ -1,64 +1,84 @@
|
|
|
1
1
|
# create-du-app
|
|
2
2
|
|
|
3
|
-
>
|
|
3
|
+
> Scaffold a standalone product monorepo from company templates — in one command.
|
|
4
4
|
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
pnpm workspace.
|
|
5
|
+
Run it, answer a couple of prompts (project name + which stacks), and you get a ready-to-run
|
|
6
|
+
pnpm monorepo with only the stacks you picked.
|
|
8
7
|
|
|
9
|
-
##
|
|
8
|
+
## Quick start
|
|
9
|
+
|
|
10
|
+
No install needed. In a real terminal (Terminal.app / iTerm):
|
|
10
11
|
|
|
11
12
|
```bash
|
|
12
|
-
|
|
13
|
-
pnpm install
|
|
14
|
-
pnpm link --global # registers the global `create-app` command
|
|
13
|
+
npx create-du-app
|
|
15
14
|
```
|
|
16
15
|
|
|
17
|
-
|
|
16
|
+
You'll be asked:
|
|
17
|
+
|
|
18
|
+
1. **Project name?** → e.g. `my-shop`
|
|
19
|
+
2. **Select the groups** → press **`Space`** to tick Mobile / Frontend / Backend, then **`Enter`**
|
|
20
|
+
3. **Pick one technology** per group → **↑ / ↓** then **`Enter`**
|
|
21
|
+
|
|
22
|
+
Then:
|
|
18
23
|
|
|
19
24
|
```bash
|
|
20
|
-
|
|
25
|
+
cd my-shop && pnpm install
|
|
21
26
|
```
|
|
22
27
|
|
|
23
|
-
|
|
28
|
+
Done. 🎉
|
|
24
29
|
|
|
25
|
-
|
|
30
|
+
## Non-interactive (CI / IDE terminals)
|
|
31
|
+
|
|
32
|
+
Pass everything as flags — no prompts, works anywhere:
|
|
26
33
|
|
|
27
34
|
```bash
|
|
28
|
-
create-app
|
|
35
|
+
npx create-du-app --name my-shop --mobile expo --fe nextjs --be nestjs
|
|
29
36
|
```
|
|
30
37
|
|
|
31
|
-
|
|
38
|
+
| Flag | Values | Required |
|
|
39
|
+
|------|--------|----------|
|
|
40
|
+
| `--name` | your project name | ✅ |
|
|
41
|
+
| `--mobile` | `rn` · `expo` · `flutter` | optional |
|
|
42
|
+
| `--fe` | `nextjs` · `reactjs` | optional |
|
|
43
|
+
| `--be` | `nodejs` · `nestjs` · `php` | optional |
|
|
44
|
+
|
|
45
|
+
## Install globally (optional)
|
|
46
|
+
|
|
47
|
+
Scaffold often? Install once so you don't re-download it each time:
|
|
32
48
|
|
|
33
49
|
```bash
|
|
34
|
-
|
|
50
|
+
npm install -g create-du-app # or: pnpm add -g create-du-app
|
|
51
|
+
create-du-app # same as npx create-du-app
|
|
35
52
|
```
|
|
36
53
|
|
|
37
|
-
|
|
54
|
+
## Available stacks
|
|
55
|
+
|
|
56
|
+
| Group | Technologies | Output folder |
|
|
57
|
+
|----------|-------------------------------|----------------|
|
|
58
|
+
| Mobile | React Native · Expo · Flutter | `apps/mobile` |
|
|
59
|
+
| Frontend | Next.js · ReactJS | `apps/web` |
|
|
60
|
+
| Backend | Node.js · NestJS · PHP | `apps/backend` |
|
|
61
|
+
|
|
62
|
+
`packages/shared` (`@repo/shared` — shared data contracts, built with tsup) is added
|
|
63
|
+
automatically when you pick **≥ 2** JS/TS stacks, and every JS/TS app is wired to it
|
|
64
|
+
as a `workspace:*` dependency.
|
|
38
65
|
|
|
39
|
-
|
|
40
|
-
|----------------------|------------------------------------------|
|
|
41
|
-
| `-n`, `--name <name>`| Project name |
|
|
42
|
-
| `--mobile <id>` | `rn` · `expo` · `flutter` |
|
|
43
|
-
| `--fe <id>` | `nextjs` · `reactjs` |
|
|
44
|
-
| `--be <id>` | `nodejs` · `nestjs` · `php` |
|
|
45
|
-
| `-h`, `--help` | Print help |
|
|
46
|
-
| `-v`, `--version` | Print version |
|
|
66
|
+
---
|
|
47
67
|
|
|
48
|
-
##
|
|
68
|
+
## For maintainers
|
|
69
|
+
|
|
70
|
+
Working on the CLI source or the templates? See the
|
|
71
|
+
[repository README](../../README.md) and **[CONTRIBUTING.md](../../CONTRIBUTING.md)**.
|
|
49
72
|
|
|
50
73
|
| File | Responsibility |
|
|
51
74
|
|---------------|----------------|
|
|
52
|
-
| `index.js` | Entry point. Parses flags,
|
|
53
|
-
| `registry.js` | **Data declaration** of groups, technologies, `templatePath`, and `lang`.
|
|
54
|
-
| `prompts.js` | Interactive prompts (`@clack/prompts`)
|
|
55
|
-
| `generate.js` | Copies templates, renames `_package.json` → `package.json`,
|
|
56
|
-
|
|
57
|
-
## Template conventions
|
|
75
|
+
| `src/index.js` | Entry point. Parses flags, runs interactive or non-interactive, then generates. |
|
|
76
|
+
| `src/registry.js` | **Data declaration** of groups, technologies, `templatePath`, and `lang`. Edit this to add/remove a stack. |
|
|
77
|
+
| `src/prompts.js` | Interactive prompts (`@clack/prompts`). |
|
|
78
|
+
| `src/generate.js` | Copies templates, renames `_package.json` → `package.json`, substitutes `{{PROJECT_NAME}}`, emits the root config (`package.json`, `pnpm-workspace.yaml`, `turbo.json`, `tsconfig.base.json`, `.gitignore`, `.npmrc`, `scripts/bootstrap.mjs`), and wires JS/TS apps to `@repo/shared`. |
|
|
79
|
+
| `scripts/validate-templates.mjs` | Validates every registered template (gates `prepack`/publish). Run with `pnpm validate`. |
|
|
58
80
|
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
- Any text file containing `{{PROJECT_NAME}}` has it replaced with the real project name.
|
|
62
|
-
- `packages/shared` is created only when **≥ 2** selections have `lang === 'js'`.
|
|
81
|
+
Before publishing, `prepack` runs template validation automatically. Run the full
|
|
82
|
+
check (validate + generate smoke test) from the repo root with `pnpm test`.
|
|
63
83
|
|
|
64
|
-
|
|
84
|
+
Release a new version: `pnpm release` (see [scripts/release.mjs](scripts/release.mjs)).
|
package/package.json
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "create-du-app",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.4",
|
|
4
4
|
"description": "CLI generator: pick templates (Mobile/FE/BE) and scaffold a product monorepo",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
|
7
|
-
"create-app": "src/index.js"
|
|
7
|
+
"create-du-app": "src/index.js"
|
|
8
8
|
},
|
|
9
9
|
"files": [
|
|
10
10
|
"src",
|
|
@@ -12,14 +12,15 @@
|
|
|
12
12
|
],
|
|
13
13
|
"scripts": {
|
|
14
14
|
"start": "node src/index.js",
|
|
15
|
+
"validate": "node scripts/validate-templates.mjs",
|
|
15
16
|
"release": "node scripts/release.mjs",
|
|
16
|
-
"prepack": "node scripts/bundle-templates.mjs",
|
|
17
|
+
"prepack": "node scripts/validate-templates.mjs && node scripts/bundle-templates.mjs",
|
|
17
18
|
"postpack": "node scripts/bundle-templates.mjs --clean"
|
|
18
19
|
},
|
|
19
20
|
"engines": {
|
|
20
|
-
"node": ">=
|
|
21
|
+
"node": ">=20"
|
|
21
22
|
},
|
|
22
|
-
"packageManager": "pnpm@9.
|
|
23
|
+
"packageManager": "pnpm@9.12.0",
|
|
23
24
|
"dependencies": {
|
|
24
25
|
"@clack/prompts": "^0.7.0",
|
|
25
26
|
"fs-extra": "^11.2.0"
|
package/src/generate.js
CHANGED
|
@@ -1,13 +1,24 @@
|
|
|
1
|
-
// generate.js — copy templates + rename + generate dynamic
|
|
1
|
+
// generate.js — copy templates + rename + generate dynamic root config + replace placeholders.
|
|
2
2
|
//
|
|
3
3
|
// Input: the plan from prompts.js → { projectName, selections: [{group, option}] }
|
|
4
4
|
// and `repoRoot` (the company-starter root that contains templates/).
|
|
5
|
+
//
|
|
6
|
+
// The output is a standard pnpm + Turborepo monorepo (modeled on the life-master layout):
|
|
7
|
+
// <project>/
|
|
8
|
+
// package.json (turbo scripts + devDeps)
|
|
9
|
+
// pnpm-workspace.yaml
|
|
10
|
+
// turbo.json
|
|
11
|
+
// tsconfig.base.json (paths: @repo/* -> packages/*/src)
|
|
12
|
+
// .gitignore .npmrc
|
|
13
|
+
// apps/<web|backend|mobile>/ (selected stacks — source dropped in later)
|
|
14
|
+
// packages/shared/ (@repo/shared — only when >= 2 JS/TS apps)
|
|
5
15
|
|
|
6
16
|
import path from 'node:path';
|
|
7
17
|
import fse from 'fs-extra';
|
|
8
18
|
import {
|
|
9
19
|
SHARED_TEMPLATE_PATH,
|
|
10
20
|
SHARED_OUTPUT_DIR,
|
|
21
|
+
SHARED_PACKAGE_NAME,
|
|
11
22
|
} from './registry.js';
|
|
12
23
|
|
|
13
24
|
const PLACEHOLDER = /\{\{PROJECT_NAME\}\}/g;
|
|
@@ -38,7 +49,6 @@ function renameBasename(name) {
|
|
|
38
49
|
|
|
39
50
|
// Copy one template folder → destination, renaming files and replacing {{PROJECT_NAME}}.
|
|
40
51
|
async function copyTemplate(srcDir, destDir, projectName) {
|
|
41
|
-
// An empty template (real source not dropped in yet) must still work.
|
|
42
52
|
if (!(await fse.pathExists(srcDir))) {
|
|
43
53
|
throw new Error(`Template not found: ${srcDir}`);
|
|
44
54
|
}
|
|
@@ -66,14 +76,33 @@ async function copyTemplate(srcDir, destDir, projectName) {
|
|
|
66
76
|
}
|
|
67
77
|
}
|
|
68
78
|
|
|
69
|
-
//
|
|
70
|
-
|
|
79
|
+
// ---------------------------------------------------------------------------
|
|
80
|
+
// Dynamic root files (pnpm + Turborepo standard).
|
|
81
|
+
// ---------------------------------------------------------------------------
|
|
82
|
+
|
|
83
|
+
// Build the project's root package.json (pnpm: NO "workspaces" field).
|
|
84
|
+
function buildRootPackageJson(projectName, hasShared) {
|
|
71
85
|
return {
|
|
72
86
|
name: projectName,
|
|
73
87
|
version: '0.1.0',
|
|
74
88
|
private: true,
|
|
75
|
-
|
|
76
|
-
|
|
89
|
+
packageManager: 'pnpm@9.12.0',
|
|
90
|
+
engines: { node: '>=20' },
|
|
91
|
+
scripts: {
|
|
92
|
+
bootstrap: 'node scripts/bootstrap.mjs',
|
|
93
|
+
build: 'turbo run build',
|
|
94
|
+
dev: 'turbo run dev',
|
|
95
|
+
lint: 'turbo run lint',
|
|
96
|
+
typecheck: 'turbo run typecheck',
|
|
97
|
+
test: 'turbo run test',
|
|
98
|
+
...(hasShared
|
|
99
|
+
? { 'shared:build': `turbo run build --filter=${SHARED_PACKAGE_NAME}` }
|
|
100
|
+
: {}),
|
|
101
|
+
},
|
|
102
|
+
devDependencies: {
|
|
103
|
+
turbo: '^2.3.3',
|
|
104
|
+
typescript: '^5.8.3',
|
|
105
|
+
},
|
|
77
106
|
};
|
|
78
107
|
}
|
|
79
108
|
|
|
@@ -85,6 +114,181 @@ function buildPnpmWorkspaceYaml(createdAppDirs) {
|
|
|
85
114
|
return `packages:\n${lines.join('\n')}\n`;
|
|
86
115
|
}
|
|
87
116
|
|
|
117
|
+
const TURBO_JSON = {
|
|
118
|
+
$schema: 'https://turbo.build/schema.json',
|
|
119
|
+
tasks: {
|
|
120
|
+
build: {
|
|
121
|
+
dependsOn: ['^build'],
|
|
122
|
+
outputs: ['dist/**', '.next/**', '!.next/cache/**', 'build/**'],
|
|
123
|
+
},
|
|
124
|
+
lint: { dependsOn: ['^build'] },
|
|
125
|
+
typecheck: { dependsOn: ['^build'] },
|
|
126
|
+
test: { dependsOn: ['^build'], outputs: ['coverage/**'] },
|
|
127
|
+
dev: { cache: false, persistent: true },
|
|
128
|
+
},
|
|
129
|
+
};
|
|
130
|
+
|
|
131
|
+
const TSCONFIG_BASE = {
|
|
132
|
+
$schema: 'https://json.schemastore.org/tsconfig',
|
|
133
|
+
compilerOptions: {
|
|
134
|
+
target: 'ESNext',
|
|
135
|
+
module: 'ESNext',
|
|
136
|
+
moduleResolution: 'Bundler',
|
|
137
|
+
lib: ['ESNext'],
|
|
138
|
+
strict: true,
|
|
139
|
+
esModuleInterop: true,
|
|
140
|
+
allowSyntheticDefaultImports: true,
|
|
141
|
+
forceConsistentCasingInFileNames: true,
|
|
142
|
+
skipLibCheck: true,
|
|
143
|
+
resolveJsonModule: true,
|
|
144
|
+
isolatedModules: true,
|
|
145
|
+
declaration: true,
|
|
146
|
+
baseUrl: '.',
|
|
147
|
+
paths: { '@repo/*': ['packages/*/src'] },
|
|
148
|
+
},
|
|
149
|
+
exclude: ['node_modules', 'dist', 'build'],
|
|
150
|
+
};
|
|
151
|
+
|
|
152
|
+
const GITIGNORE = `# Dependencies
|
|
153
|
+
node_modules/
|
|
154
|
+
.pnpm-store/
|
|
155
|
+
|
|
156
|
+
# Turborepo
|
|
157
|
+
.turbo/
|
|
158
|
+
|
|
159
|
+
# Build outputs
|
|
160
|
+
dist/
|
|
161
|
+
build/
|
|
162
|
+
out/
|
|
163
|
+
.next/
|
|
164
|
+
*.tsbuildinfo
|
|
165
|
+
|
|
166
|
+
# Expo / React Native
|
|
167
|
+
.expo/
|
|
168
|
+
web-build/
|
|
169
|
+
.metro-health-check*
|
|
170
|
+
|
|
171
|
+
# Environment variables
|
|
172
|
+
.env
|
|
173
|
+
.env.*
|
|
174
|
+
!.env.example
|
|
175
|
+
!.env.*.example
|
|
176
|
+
|
|
177
|
+
# Testing
|
|
178
|
+
coverage/
|
|
179
|
+
|
|
180
|
+
# Logs
|
|
181
|
+
*.log
|
|
182
|
+
npm-debug.log*
|
|
183
|
+
pnpm-debug.log*
|
|
184
|
+
yarn-error.log*
|
|
185
|
+
|
|
186
|
+
# OS
|
|
187
|
+
.DS_Store
|
|
188
|
+
|
|
189
|
+
# IDE
|
|
190
|
+
.idea/
|
|
191
|
+
.vscode/
|
|
192
|
+
*.iml
|
|
193
|
+
`;
|
|
194
|
+
|
|
195
|
+
const NPMRC = `# Hoist node_modules so Metro (Expo / React Native) resolves packages and
|
|
196
|
+
# workspace dependencies (@repo/*) correctly. Harmless for web/back-end apps.
|
|
197
|
+
node-linker=hoisted
|
|
198
|
+
|
|
199
|
+
# Keep peer-dependency resolution lenient — the RN ecosystem has many loose
|
|
200
|
+
# peer ranges that would otherwise fail install.
|
|
201
|
+
strict-peer-dependencies=false
|
|
202
|
+
`;
|
|
203
|
+
|
|
204
|
+
// One-command bootstrap, written to the generated repo as scripts/bootstrap.mjs.
|
|
205
|
+
// Run it (`pnpm bootstrap`) AFTER dropping the real stack source in: it installs
|
|
206
|
+
// deps, builds @repo/shared, then verifies the apps can resolve it.
|
|
207
|
+
// NOTE: not named "setup" because `pnpm setup` is a reserved pnpm built-in.
|
|
208
|
+
const SETUP_MJS = `// bootstrap.mjs — one-command bootstrap for this monorepo.
|
|
209
|
+
//
|
|
210
|
+
// Run it after you have dropped the real source into apps/* :
|
|
211
|
+
//
|
|
212
|
+
// pnpm bootstrap
|
|
213
|
+
//
|
|
214
|
+
// It installs dependencies, builds @repo/shared (so its dist/ exists), and
|
|
215
|
+
// verifies every app that depends on it can resolve \`@repo/shared\`.
|
|
216
|
+
|
|
217
|
+
import { spawnSync } from 'node:child_process';
|
|
218
|
+
import { existsSync, readFileSync, readdirSync } from 'node:fs';
|
|
219
|
+
import { createRequire } from 'node:module';
|
|
220
|
+
import path from 'node:path';
|
|
221
|
+
import { fileURLToPath } from 'node:url';
|
|
222
|
+
|
|
223
|
+
const root = path.resolve(path.dirname(fileURLToPath(import.meta.url)), '..');
|
|
224
|
+
const SHARED = '@repo/shared';
|
|
225
|
+
|
|
226
|
+
function sh(command) {
|
|
227
|
+
console.log(\`\\n$ \${command}\`);
|
|
228
|
+
const r = spawnSync(command, { cwd: root, stdio: 'inherit', shell: true });
|
|
229
|
+
if (r.status !== 0) {
|
|
230
|
+
console.error(\`\\n\\u2717 Failed: \${command}\`);
|
|
231
|
+
process.exit(r.status ?? 1);
|
|
232
|
+
}
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
// 1) Install all workspace dependencies.
|
|
236
|
+
sh('pnpm install');
|
|
237
|
+
|
|
238
|
+
// 2) Build the shared package (if present) so apps can import its dist output.
|
|
239
|
+
const sharedDir = path.join(root, 'packages', 'shared');
|
|
240
|
+
const hasShared = existsSync(sharedDir);
|
|
241
|
+
if (hasShared) {
|
|
242
|
+
sh(\`pnpm --filter \${SHARED} build\`);
|
|
243
|
+
} else {
|
|
244
|
+
console.log('\\n\\u2022 No packages/shared in this repo — skipping shared build.');
|
|
245
|
+
}
|
|
246
|
+
|
|
247
|
+
// 3) Verify each app that depends on @repo/shared can actually resolve it.
|
|
248
|
+
if (hasShared) {
|
|
249
|
+
const appsDir = path.join(root, 'apps');
|
|
250
|
+
const apps = existsSync(appsDir)
|
|
251
|
+
? readdirSync(appsDir, { withFileTypes: true }).filter((e) => e.isDirectory())
|
|
252
|
+
: [];
|
|
253
|
+
|
|
254
|
+
let failures = 0;
|
|
255
|
+
for (const app of apps) {
|
|
256
|
+
const pkgPath = path.join(appsDir, app.name, 'package.json');
|
|
257
|
+
if (!existsSync(pkgPath)) continue;
|
|
258
|
+
const pkg = JSON.parse(readFileSync(pkgPath, 'utf8'));
|
|
259
|
+
const deps = { ...pkg.dependencies, ...pkg.devDependencies };
|
|
260
|
+
if (!deps[SHARED]) continue;
|
|
261
|
+
|
|
262
|
+
const require = createRequire(path.join(appsDir, app.name, 'noop.js'));
|
|
263
|
+
try {
|
|
264
|
+
require.resolve(SHARED);
|
|
265
|
+
console.log(\`\\n\\u2713 apps/\${app.name} resolves \${SHARED}\`);
|
|
266
|
+
} catch {
|
|
267
|
+
console.error(\`\\n\\u2717 apps/\${app.name} cannot resolve \${SHARED}\`);
|
|
268
|
+
failures++;
|
|
269
|
+
}
|
|
270
|
+
}
|
|
271
|
+
|
|
272
|
+
if (failures > 0) {
|
|
273
|
+
console.error(\`\\n\${failures} app(s) cannot resolve \${SHARED}. Check the \"\${SHARED}\" dependency and that its build produced dist/.\`);
|
|
274
|
+
process.exit(1);
|
|
275
|
+
}
|
|
276
|
+
}
|
|
277
|
+
|
|
278
|
+
console.log('\\n\\u2713 Setup complete. Start developing with: pnpm dev');
|
|
279
|
+
`;
|
|
280
|
+
|
|
281
|
+
// ---------------------------------------------------------------------------
|
|
282
|
+
|
|
283
|
+
// Add "@repo/shared": "workspace:*" to a JS/TS app's package.json (if present).
|
|
284
|
+
async function wireSharedDependency(appPkgPath) {
|
|
285
|
+
if (!(await fse.pathExists(appPkgPath))) return false;
|
|
286
|
+
const pkg = await fse.readJson(appPkgPath);
|
|
287
|
+
pkg.dependencies = { ...(pkg.dependencies ?? {}), [SHARED_PACKAGE_NAME]: 'workspace:*' };
|
|
288
|
+
await fse.writeJson(appPkgPath, pkg, { spaces: 2 });
|
|
289
|
+
return true;
|
|
290
|
+
}
|
|
291
|
+
|
|
88
292
|
export async function generate(plan, repoRoot, cwd = process.cwd()) {
|
|
89
293
|
const { projectName, selections } = plan;
|
|
90
294
|
const projectRoot = path.resolve(cwd, projectName);
|
|
@@ -107,27 +311,54 @@ export async function generate(plan, repoRoot, cwd = process.cwd()) {
|
|
|
107
311
|
}
|
|
108
312
|
|
|
109
313
|
// 2) packages/shared is CONDITIONAL: >= 2 selections with lang === 'js'.
|
|
110
|
-
const
|
|
111
|
-
|
|
314
|
+
const jsSelections = selections.filter((s) => s.option.lang === 'js');
|
|
315
|
+
const hasShared = jsSelections.length >= 2;
|
|
316
|
+
if (hasShared) {
|
|
112
317
|
const srcDir = path.resolve(repoRoot, SHARED_TEMPLATE_PATH);
|
|
113
318
|
const destDir = path.resolve(projectRoot, SHARED_OUTPUT_DIR);
|
|
114
319
|
await copyTemplate(srcDir, destDir, projectName);
|
|
115
|
-
logs.push(`✓ shared → ${SHARED_OUTPUT_DIR} (${
|
|
320
|
+
logs.push(`✓ shared → ${SHARED_OUTPUT_DIR} (${jsSelections.length} JS/TS apps)`);
|
|
321
|
+
|
|
322
|
+
// Wire each JS/TS app to depend on the shared package.
|
|
323
|
+
for (const { group } of jsSelections) {
|
|
324
|
+
const appPkg = path.join(projectRoot, group.outputDir, 'package.json');
|
|
325
|
+
if (await wireSharedDependency(appPkg)) {
|
|
326
|
+
logs.push(` ↳ ${group.outputDir} depends on ${SHARED_PACKAGE_NAME} (workspace:*)`);
|
|
327
|
+
}
|
|
328
|
+
}
|
|
116
329
|
} else {
|
|
117
|
-
logs.push(`• Skipping shared: not enough JS/TS apps (need >= 2, have ${
|
|
330
|
+
logs.push(`• Skipping shared: not enough JS/TS apps (need >= 2, have ${jsSelections.length}).`);
|
|
118
331
|
}
|
|
119
332
|
|
|
120
|
-
// 3) Generate the root
|
|
121
|
-
|
|
122
|
-
|
|
333
|
+
// 3) Generate the root config files dynamically.
|
|
334
|
+
await fse.writeJson(
|
|
335
|
+
path.join(projectRoot, 'package.json'),
|
|
336
|
+
buildRootPackageJson(projectName, hasShared),
|
|
337
|
+
{ spaces: 2 },
|
|
338
|
+
);
|
|
123
339
|
logs.push('✓ package.json');
|
|
124
340
|
|
|
125
|
-
const wsEntries = [...createdAppDirs, 'packages/*'];
|
|
126
341
|
await fse.writeFile(
|
|
127
342
|
path.join(projectRoot, 'pnpm-workspace.yaml'),
|
|
128
343
|
buildPnpmWorkspaceYaml(createdAppDirs),
|
|
129
344
|
);
|
|
130
|
-
logs.push(`✓ pnpm-workspace.yaml (packages: ${
|
|
345
|
+
logs.push(`✓ pnpm-workspace.yaml (packages: ${[...createdAppDirs, 'packages/*'].join(', ')})`);
|
|
346
|
+
|
|
347
|
+
await fse.writeJson(path.join(projectRoot, 'turbo.json'), TURBO_JSON, { spaces: 2 });
|
|
348
|
+
logs.push('✓ turbo.json');
|
|
349
|
+
|
|
350
|
+
await fse.writeJson(path.join(projectRoot, 'tsconfig.base.json'), TSCONFIG_BASE, { spaces: 2 });
|
|
351
|
+
logs.push('✓ tsconfig.base.json');
|
|
352
|
+
|
|
353
|
+
await fse.writeFile(path.join(projectRoot, '.gitignore'), GITIGNORE);
|
|
354
|
+
logs.push('✓ .gitignore');
|
|
355
|
+
|
|
356
|
+
await fse.writeFile(path.join(projectRoot, '.npmrc'), NPMRC);
|
|
357
|
+
logs.push('✓ .npmrc');
|
|
358
|
+
|
|
359
|
+
await fse.ensureDir(path.join(projectRoot, 'scripts'));
|
|
360
|
+
await fse.writeFile(path.join(projectRoot, 'scripts', 'bootstrap.mjs'), SETUP_MJS);
|
|
361
|
+
logs.push('✓ scripts/bootstrap.mjs (run `pnpm bootstrap` after dropping source in)');
|
|
131
362
|
|
|
132
363
|
return { projectRoot, logs };
|
|
133
364
|
}
|
package/src/index.js
CHANGED
|
@@ -2,8 +2,8 @@
|
|
|
2
2
|
// index.js — entry point. Parse args + run prompts (TTY) or generate directly (flags).
|
|
3
3
|
//
|
|
4
4
|
// Usage:
|
|
5
|
-
// create-app interactive (requires a real terminal)
|
|
6
|
-
// create-app --name my-shop --be nestjs non-interactive (runs anywhere)
|
|
5
|
+
// create-du-app interactive (requires a real terminal)
|
|
6
|
+
// create-du-app --name my-shop --be nestjs non-interactive (runs anywhere)
|
|
7
7
|
// node src/index.js
|
|
8
8
|
//
|
|
9
9
|
// Flags:
|
|
@@ -56,11 +56,11 @@ async function readVersion() {
|
|
|
56
56
|
|
|
57
57
|
function printHelp() {
|
|
58
58
|
console.log(`
|
|
59
|
-
create-app — scaffold a product monorepo from company templates
|
|
59
|
+
create-du-app — scaffold a product monorepo from company templates
|
|
60
60
|
|
|
61
61
|
Usage:
|
|
62
|
-
create-app interactive (requires a real terminal)
|
|
63
|
-
create-app --name my-shop --be nestjs non-interactive (runs anywhere)
|
|
62
|
+
create-du-app interactive (requires a real terminal)
|
|
63
|
+
create-du-app --name my-shop --be nestjs non-interactive (runs anywhere)
|
|
64
64
|
node src/index.js equivalent (when not linked)
|
|
65
65
|
|
|
66
66
|
Options:
|
|
@@ -73,7 +73,7 @@ Options:
|
|
|
73
73
|
-y, --yes generate without prompting (needs --name + >=1 group)
|
|
74
74
|
|
|
75
75
|
Example:
|
|
76
|
-
create-app --name my-shop --mobile expo --fe nextjs --be nestjs
|
|
76
|
+
create-du-app --name my-shop --mobile expo --fe nextjs --be nestjs
|
|
77
77
|
|
|
78
78
|
Add/remove templates: edit packages/cli/src/registry.js
|
|
79
79
|
`);
|
|
@@ -93,7 +93,7 @@ function parseArgs(argv) {
|
|
|
93
93
|
case '--fe': out.fe = argv[++i]; break;
|
|
94
94
|
case '--be': out.be = argv[++i]; break;
|
|
95
95
|
default:
|
|
96
|
-
throw new Error(`Invalid argument: ${a}. See: create-app --help`);
|
|
96
|
+
throw new Error(`Invalid argument: ${a}. See: create-du-app --help`);
|
|
97
97
|
}
|
|
98
98
|
}
|
|
99
99
|
return out;
|
|
@@ -155,7 +155,7 @@ async function main() {
|
|
|
155
155
|
throw new Error(
|
|
156
156
|
'This terminal does not support interactive mode (stdin is not a TTY).\n' +
|
|
157
157
|
' → Run it in Terminal.app/iTerm, OR use flags:\n' +
|
|
158
|
-
' create-app --name my-shop --mobile expo --fe nextjs --be nestjs',
|
|
158
|
+
' create-du-app --name my-shop --mobile expo --fe nextjs --be nestjs',
|
|
159
159
|
);
|
|
160
160
|
} else {
|
|
161
161
|
plan = await runPrompts();
|
package/src/prompts.js
CHANGED
|
@@ -24,7 +24,7 @@ function ensureNotCancelled(value) {
|
|
|
24
24
|
}
|
|
25
25
|
|
|
26
26
|
export async function runPrompts() {
|
|
27
|
-
intro('create-app — scaffold a product monorepo from company templates');
|
|
27
|
+
intro('create-du-app — scaffold a product monorepo from company templates');
|
|
28
28
|
|
|
29
29
|
// 1) Project name
|
|
30
30
|
const projectName = ensureNotCancelled(
|
package/src/registry.js
CHANGED
|
@@ -43,9 +43,11 @@ export const GROUPS = [
|
|
|
43
43
|
},
|
|
44
44
|
];
|
|
45
45
|
|
|
46
|
-
//
|
|
46
|
+
// Shared package config. Only copied when >= 2 selections have lang === 'js'.
|
|
47
|
+
// Uses the `@repo/*` scope so it matches the `paths` mapping in tsconfig.base.json.
|
|
47
48
|
export const SHARED_TEMPLATE_PATH = 'templates/shared';
|
|
48
49
|
export const SHARED_OUTPUT_DIR = 'packages/shared';
|
|
50
|
+
export const SHARED_PACKAGE_NAME = '@repo/shared';
|
|
49
51
|
|
|
50
52
|
// Quickly look up a single option by (groupId, optionId).
|
|
51
53
|
export function findOption(groupId, optionId) {
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
module.exports = {
|
|
2
|
+
replaceAttrValues: {
|
|
3
|
+
'{currentColor}': '{props.color || "#0D1F2D"}',
|
|
4
|
+
'{292929}': '{props.color || "#292929"}',
|
|
5
|
+
'{D4D4FF}': '{props.color || "#D4D4FF"}',
|
|
6
|
+
'{7C7C7C}': '{props.color || "#7C7C7C"}',
|
|
7
|
+
'{D97706}': '{props.color || "#D97706"}',
|
|
8
|
+
},
|
|
9
|
+
}
|
|
@@ -1,11 +1,46 @@
|
|
|
1
|
-
#
|
|
1
|
+
# {{PROJECT_NAME}} — Mobile (Expo)
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
An Expo + React Native starter built from the company's production core. The
|
|
4
|
+
reusable infrastructure (`src/core`) is ported as-is; only product-specific
|
|
5
|
+
features (audio/player, real-estate, IAP, maps, blur) were removed. Build your
|
|
6
|
+
features under `src/modules/`.
|
|
4
7
|
|
|
5
|
-
|
|
8
|
+
## Architecture
|
|
6
9
|
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
+
```
|
|
11
|
+
src/
|
|
12
|
+
├── app/ composition: providers, navigation, global stores (auth/loading/common), i18n
|
|
13
|
+
├── core/ reusable infrastructure (see below)
|
|
14
|
+
├── modules/ your features (home/profile examples included)
|
|
15
|
+
└── assets/ i18n, svgs (sync-generated barrel), images, lotties
|
|
16
|
+
```
|
|
10
17
|
|
|
11
|
-
|
|
18
|
+
### `src/core` — the reusable kit
|
|
19
|
+
| Area | Where |
|
|
20
|
+
|------|-------|
|
|
21
|
+
| API | `services/api.service.ts` (axios + auth header + device-id + 401 session handling), `api/example.api.ts` (React Query pattern) |
|
|
22
|
+
| Data | `utils/query-client.util.ts`, `utils/query-persister.util.ts` (MMKV offline cache) |
|
|
23
|
+
| Theme | `theme/` — context + `Colors` design tokens (`useTheme`, `useThemedStyles`) |
|
|
24
|
+
| UI kit | `components/ui/*` — button, text-field/area, checkbox, radio, toggle, modal, bottom-sheet, header, tabs, otp-input, search-box, skeleton, app-image, image-slider… |
|
|
25
|
+
| Forms | `components/forms/*` — react-hook-form bindings over the DS fields |
|
|
26
|
+
| Hooks | `hook/*` — useDebounce, useTimeout, useNetworkStatus, useEndReached, useAppNavigation… |
|
|
27
|
+
| Utils | `utils/*` — storage, translator (i18n), validate/schema (yup), date/number format, enum, toast, size/typography… |
|
|
28
|
+
|
|
29
|
+
### Shared contracts
|
|
30
|
+
The core imports domain contracts (`ApiEndpoints`, `ExternalUrls`, enums) from
|
|
31
|
+
**`@repo/shared`** — generate this app alongside another JS/TS stack so that
|
|
32
|
+
package exists; the CLI wires `"@repo/shared": "workspace:*"` automatically.
|
|
33
|
+
|
|
34
|
+
## Getting started
|
|
35
|
+
|
|
36
|
+
```bash
|
|
37
|
+
pnpm bootstrap # install + build @repo/shared
|
|
38
|
+
pnpm --filter {{PROJECT_NAME}}-mobile typecheck # verify
|
|
39
|
+
pnpm --filter {{PROJECT_NAME}}-mobile start # expo dev server
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
Add an icon: drop `name.svg` in `src/assets/svgs/` then `pnpm --filter {{PROJECT_NAME}}-mobile sync-svgs`.
|
|
43
|
+
|
|
44
|
+
Native folders (`ios/`, `android/`) are git-ignored — run `expo prebuild` to generate them.
|
|
45
|
+
|
|
46
|
+
> Before shipping: set `name`, `slug`, `scheme`, and the iOS/Android bundle ids in `app.json`.
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
# Native build artifacts (regenerated by `expo prebuild`)
|
|
2
|
+
/ios
|
|
3
|
+
/android
|
|
4
|
+
.expo/
|
|
5
|
+
web-build/
|
|
6
|
+
|
|
7
|
+
# Dependencies
|
|
8
|
+
node_modules/
|
|
9
|
+
|
|
10
|
+
# Metro
|
|
11
|
+
.metro-health-check*
|
|
12
|
+
|
|
13
|
+
# Env (keep .env.example)
|
|
14
|
+
.env
|
|
15
|
+
.env.*
|
|
16
|
+
!.env.example
|
|
17
|
+
|
|
18
|
+
# Logs / OS
|
|
19
|
+
*.log
|
|
20
|
+
.DS_Store
|