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.
Files changed (421) hide show
  1. package/README.md +56 -36
  2. package/package.json +6 -5
  3. package/src/generate.js +246 -15
  4. package/src/index.js +8 -8
  5. package/src/prompts.js +1 -1
  6. package/src/registry.js +3 -1
  7. package/templates/mobile/expo/.env.example +5 -0
  8. package/templates/mobile/expo/.eslintrc.js +7 -0
  9. package/templates/mobile/expo/.prettierrc.js +7 -0
  10. package/templates/mobile/expo/.svgrrc.js +9 -0
  11. package/templates/mobile/expo/README.md +42 -7
  12. package/templates/mobile/expo/_gitignore +20 -0
  13. package/templates/mobile/expo/_package.json +62 -1
  14. package/templates/mobile/expo/app.json +18 -0
  15. package/templates/mobile/expo/babel.config.js +21 -0
  16. package/templates/mobile/expo/index.js +5 -0
  17. package/templates/mobile/expo/metro.config.js +31 -0
  18. package/templates/mobile/expo/src/app/App.tsx +24 -0
  19. package/templates/mobile/expo/src/app/app-provider.tsx +36 -0
  20. package/templates/mobile/expo/src/app/config/translation.ts +26 -0
  21. package/templates/mobile/expo/src/app/index.ts +1 -0
  22. package/templates/mobile/expo/src/app/navigation/app-route-type.ts +27 -0
  23. package/templates/mobile/expo/src/app/navigation/bottom-tabs.tsx +34 -0
  24. package/templates/mobile/expo/src/app/navigation/index.tsx +14 -0
  25. package/templates/mobile/expo/src/app/stores/auth.store.ts +33 -0
  26. package/templates/mobile/expo/src/app/stores/common.store.ts +19 -0
  27. package/templates/mobile/expo/src/app/stores/index.ts +3 -0
  28. package/templates/mobile/expo/src/app/stores/loading.store.ts +22 -0
  29. package/templates/mobile/expo/src/assets/Images/empty-list.png +0 -0
  30. package/templates/mobile/expo/src/assets/Images/index.ts +5 -0
  31. package/templates/mobile/expo/src/assets/Images/screen-bg-gradian.png +0 -0
  32. package/templates/mobile/expo/src/assets/i18n/en.json +12 -0
  33. package/templates/mobile/expo/src/assets/i18n/fr.json +12 -0
  34. package/templates/mobile/expo/src/assets/lotties/index.ts +3 -0
  35. package/templates/mobile/expo/src/assets/lotties/loading.json +1 -0
  36. package/templates/mobile/expo/src/assets/svgs/arrow-left.svg +3 -0
  37. package/templates/mobile/expo/src/assets/svgs/arrow-right.svg +3 -0
  38. package/templates/mobile/expo/src/assets/svgs/calendar.svg +12 -0
  39. package/templates/mobile/expo/src/assets/svgs/check.svg +3 -0
  40. package/templates/mobile/expo/src/assets/svgs/close.svg +3 -0
  41. package/templates/mobile/expo/src/assets/svgs/eye-hide.svg +3 -0
  42. package/templates/mobile/expo/src/assets/svgs/eye.svg +4 -0
  43. package/templates/mobile/expo/src/assets/svgs/index.ts +29 -0
  44. package/templates/mobile/expo/src/assets/svgs/minus.svg +3 -0
  45. package/templates/mobile/expo/src/assets/svgs/plus.svg +3 -0
  46. package/templates/mobile/expo/src/assets/svgs/search.svg +3 -0
  47. package/templates/mobile/expo/src/assets/svgs/toast-error.svg +5 -0
  48. package/templates/mobile/expo/src/assets/svgs/toast-success.svg +4 -0
  49. package/templates/mobile/expo/src/core/api/endpoints.ts +8 -0
  50. package/templates/mobile/expo/src/core/api/example.api.ts +53 -0
  51. package/templates/mobile/expo/src/core/api/index.ts +4 -0
  52. package/templates/mobile/expo/src/core/components/common/index.ts +1 -0
  53. package/templates/mobile/expo/src/core/components/common/list-empty/index.ts +2 -0
  54. package/templates/mobile/expo/src/core/components/common/list-empty/list-empty.tsx +30 -0
  55. package/templates/mobile/expo/src/core/components/common/list-empty/list-empty.type.ts +5 -0
  56. package/templates/mobile/expo/src/core/components/forms/hf-date-time.tsx +301 -0
  57. package/templates/mobile/expo/src/core/components/forms/hf-password-input.tsx +153 -0
  58. package/templates/mobile/expo/src/core/components/forms/hf-text-input.tsx +59 -0
  59. package/templates/mobile/expo/src/core/components/forms/hf-time-picker.tsx +117 -0
  60. package/templates/mobile/expo/src/core/components/forms/index.ts +4 -0
  61. package/templates/mobile/expo/src/core/components/index.ts +5 -0
  62. package/templates/mobile/expo/src/core/components/loading/index.ts +1 -0
  63. package/templates/mobile/expo/src/core/components/loading/loading-app/index.ts +1 -0
  64. package/templates/mobile/expo/src/core/components/loading/loading-app/loading-app.tsx +50 -0
  65. package/templates/mobile/expo/src/core/components/offline/index.ts +1 -0
  66. package/templates/mobile/expo/src/core/components/offline/offline-banner.tsx +186 -0
  67. package/templates/mobile/expo/src/core/components/screen/index.ts +1 -0
  68. package/templates/mobile/expo/src/core/components/screen/screen-container/index.ts +1 -0
  69. package/templates/mobile/expo/src/core/components/screen/screen-container/screen-container.tsx +252 -0
  70. package/templates/mobile/expo/src/core/components/splash/index.ts +1 -0
  71. package/templates/mobile/expo/src/core/components/splash/splash-overlay/index.ts +1 -0
  72. package/templates/mobile/expo/src/core/components/splash/splash-overlay/splash-overlay.tsx +93 -0
  73. package/templates/mobile/expo/src/core/components/ui/animated-list-item/animated-list-item.tsx +48 -0
  74. package/templates/mobile/expo/src/core/components/ui/animated-list-item/animated-list-item.type.ts +10 -0
  75. package/templates/mobile/expo/src/core/components/ui/animated-list-item/index.ts +2 -0
  76. package/templates/mobile/expo/src/core/components/ui/app-image/app-image.tsx +104 -0
  77. package/templates/mobile/expo/src/core/components/ui/app-image/app-image.type.ts +19 -0
  78. package/templates/mobile/expo/src/core/components/ui/app-image/index.ts +2 -0
  79. package/templates/mobile/expo/src/core/components/ui/asset-placeholder/asset-placeholder.tsx +76 -0
  80. package/templates/mobile/expo/src/core/components/ui/asset-placeholder/index.ts +1 -0
  81. package/templates/mobile/expo/src/core/components/ui/avatar-image/avatar-image.tsx +90 -0
  82. package/templates/mobile/expo/src/core/components/ui/avatar-image/index.ts +1 -0
  83. package/templates/mobile/expo/src/core/components/ui/bottom-sheet/bottom-sheet.tsx +145 -0
  84. package/templates/mobile/expo/src/core/components/ui/bottom-sheet/bottom-sheet.type.ts +10 -0
  85. package/templates/mobile/expo/src/core/components/ui/bottom-sheet/index.ts +2 -0
  86. package/templates/mobile/expo/src/core/components/ui/button/button.style.ts +146 -0
  87. package/templates/mobile/expo/src/core/components/ui/button/button.tsx +97 -0
  88. package/templates/mobile/expo/src/core/components/ui/button/button.type.ts +47 -0
  89. package/templates/mobile/expo/src/core/components/ui/button/index.ts +4 -0
  90. package/templates/mobile/expo/src/core/components/ui/checkbox/checkbox.tsx +127 -0
  91. package/templates/mobile/expo/src/core/components/ui/checkbox/checkbox.type.ts +24 -0
  92. package/templates/mobile/expo/src/core/components/ui/checkbox/index.ts +2 -0
  93. package/templates/mobile/expo/src/core/components/ui/collapsible-section/collapsible-section.tsx +141 -0
  94. package/templates/mobile/expo/src/core/components/ui/collapsible-section/collapsible-section.type.ts +10 -0
  95. package/templates/mobile/expo/src/core/components/ui/collapsible-section/index.ts +2 -0
  96. package/templates/mobile/expo/src/core/components/ui/components.registry.json +313 -0
  97. package/templates/mobile/expo/src/core/components/ui/field/field-frame.tsx +62 -0
  98. package/templates/mobile/expo/src/core/components/ui/field/field.shared.ts +31 -0
  99. package/templates/mobile/expo/src/core/components/ui/header/header.tsx +196 -0
  100. package/templates/mobile/expo/src/core/components/ui/header/header.type.ts +30 -0
  101. package/templates/mobile/expo/src/core/components/ui/header/index.ts +2 -0
  102. package/templates/mobile/expo/src/core/components/ui/icon-button/icon-button.style.ts +23 -0
  103. package/templates/mobile/expo/src/core/components/ui/icon-button/icon-button.tsx +66 -0
  104. package/templates/mobile/expo/src/core/components/ui/icon-button/icon-button.type.ts +25 -0
  105. package/templates/mobile/expo/src/core/components/ui/icon-button/index.ts +2 -0
  106. package/templates/mobile/expo/src/core/components/ui/image-slider/image-slider.tsx +107 -0
  107. package/templates/mobile/expo/src/core/components/ui/image-slider/image-slider.type.ts +10 -0
  108. package/templates/mobile/expo/src/core/components/ui/image-slider/index.ts +2 -0
  109. package/templates/mobile/expo/src/core/components/ui/index.ts +25 -0
  110. package/templates/mobile/expo/src/core/components/ui/label/index.ts +2 -0
  111. package/templates/mobile/expo/src/core/components/ui/label/label.tsx +36 -0
  112. package/templates/mobile/expo/src/core/components/ui/label/label.type.ts +12 -0
  113. package/templates/mobile/expo/src/core/components/ui/modal/index.ts +2 -0
  114. package/templates/mobile/expo/src/core/components/ui/modal/modal.tsx +62 -0
  115. package/templates/mobile/expo/src/core/components/ui/modal/modal.type.ts +11 -0
  116. package/templates/mobile/expo/src/core/components/ui/otp-input/index.ts +2 -0
  117. package/templates/mobile/expo/src/core/components/ui/otp-input/otp-input.tsx +129 -0
  118. package/templates/mobile/expo/src/core/components/ui/otp-input/otp-input.type.ts +20 -0
  119. package/templates/mobile/expo/src/core/components/ui/page-dots/index.ts +1 -0
  120. package/templates/mobile/expo/src/core/components/ui/page-dots/page-dots.tsx +60 -0
  121. package/templates/mobile/expo/src/core/components/ui/radio/index.ts +2 -0
  122. package/templates/mobile/expo/src/core/components/ui/radio/radio.tsx +121 -0
  123. package/templates/mobile/expo/src/core/components/ui/radio/radio.type.ts +20 -0
  124. package/templates/mobile/expo/src/core/components/ui/screen/index.ts +1 -0
  125. package/templates/mobile/expo/src/core/components/ui/screen/screen-gradient.tsx +33 -0
  126. package/templates/mobile/expo/src/core/components/ui/search-box/index.ts +2 -0
  127. package/templates/mobile/expo/src/core/components/ui/search-box/search-box.tsx +162 -0
  128. package/templates/mobile/expo/src/core/components/ui/search-box/search-box.type.ts +26 -0
  129. package/templates/mobile/expo/src/core/components/ui/segmented-control/index.ts +2 -0
  130. package/templates/mobile/expo/src/core/components/ui/segmented-control/segmented-control.tsx +86 -0
  131. package/templates/mobile/expo/src/core/components/ui/segmented-control/segmented-control.type.ts +22 -0
  132. package/templates/mobile/expo/src/core/components/ui/skeleton/index.ts +2 -0
  133. package/templates/mobile/expo/src/core/components/ui/skeleton/skeleton.tsx +106 -0
  134. package/templates/mobile/expo/src/core/components/ui/skeleton/skeleton.type.ts +8 -0
  135. package/templates/mobile/expo/src/core/components/ui/success-state/index.ts +1 -0
  136. package/templates/mobile/expo/src/core/components/ui/success-state/success-state.tsx +68 -0
  137. package/templates/mobile/expo/src/core/components/ui/tabs/index.ts +2 -0
  138. package/templates/mobile/expo/src/core/components/ui/tabs/tabs.tsx +273 -0
  139. package/templates/mobile/expo/src/core/components/ui/tabs/tabs.type.ts +21 -0
  140. package/templates/mobile/expo/src/core/components/ui/tag-input/index.ts +2 -0
  141. package/templates/mobile/expo/src/core/components/ui/tag-input/tag-input.tsx +146 -0
  142. package/templates/mobile/expo/src/core/components/ui/tag-input/tag-input.type.ts +22 -0
  143. package/templates/mobile/expo/src/core/components/ui/text-area/index.ts +2 -0
  144. package/templates/mobile/expo/src/core/components/ui/text-area/text-area.tsx +90 -0
  145. package/templates/mobile/expo/src/core/components/ui/text-area/text-area.type.ts +20 -0
  146. package/templates/mobile/expo/src/core/components/ui/text-field/index.ts +2 -0
  147. package/templates/mobile/expo/src/core/components/ui/text-field/text-field.tsx +116 -0
  148. package/templates/mobile/expo/src/core/components/ui/text-field/text-field.type.ts +21 -0
  149. package/templates/mobile/expo/src/core/components/ui/toggle/index.ts +2 -0
  150. package/templates/mobile/expo/src/core/components/ui/toggle/toggle.tsx +110 -0
  151. package/templates/mobile/expo/src/core/components/ui/toggle/toggle.type.ts +19 -0
  152. package/templates/mobile/expo/src/core/constants/external-urls.constant.ts +5 -0
  153. package/templates/mobile/expo/src/core/constants/hard-data.constant.ts +0 -0
  154. package/templates/mobile/expo/src/core/constants/index.ts +2 -0
  155. package/templates/mobile/expo/src/core/constants/type.constant.ts +3 -0
  156. package/templates/mobile/expo/src/core/context/index.ts +1 -0
  157. package/templates/mobile/expo/src/core/context/shared-transition-context.tsx +35 -0
  158. package/templates/mobile/expo/src/core/hook/index.ts +8 -0
  159. package/templates/mobile/expo/src/core/hook/useActiveRouteName.ts +63 -0
  160. package/templates/mobile/expo/src/core/hook/useAppNavigation.tsx +7 -0
  161. package/templates/mobile/expo/src/core/hook/useBottomInset.tsx +26 -0
  162. package/templates/mobile/expo/src/core/hook/useDebounce.tsx +16 -0
  163. package/templates/mobile/expo/src/core/hook/useEndReached.tsx +46 -0
  164. package/templates/mobile/expo/src/core/hook/useManualRefetch.ts +56 -0
  165. package/templates/mobile/expo/src/core/hook/useNetworkStatus.ts +68 -0
  166. package/templates/mobile/expo/src/core/hook/useTimeout.tsx +30 -0
  167. package/templates/mobile/expo/src/core/index.ts +7 -0
  168. package/templates/mobile/expo/src/core/services/api.service.ts +230 -0
  169. package/templates/mobile/expo/src/core/services/device-id.service.ts +23 -0
  170. package/templates/mobile/expo/src/core/services/index.ts +3 -0
  171. package/templates/mobile/expo/src/core/services/session-end.bridge.ts +26 -0
  172. package/templates/mobile/expo/src/core/theme/dark.theme.ts +10 -0
  173. package/templates/mobile/expo/src/core/theme/index.ts +5 -0
  174. package/templates/mobile/expo/src/core/theme/light.theme.ts +44 -0
  175. package/templates/mobile/expo/src/core/theme/theme-context.tsx +82 -0
  176. package/templates/mobile/expo/src/core/theme/theme.types.ts +26 -0
  177. package/templates/mobile/expo/src/core/theme/use-themed-styles.ts +25 -0
  178. package/templates/mobile/expo/src/core/utils/color.util.tsx +198 -0
  179. package/templates/mobile/expo/src/core/utils/date.util.ts +97 -0
  180. package/templates/mobile/expo/src/core/utils/device-locale.util.ts +22 -0
  181. package/templates/mobile/expo/src/core/utils/emitter/index.ts +161 -0
  182. package/templates/mobile/expo/src/core/utils/emitter/type.ts +40 -0
  183. package/templates/mobile/expo/src/core/utils/enum.util.tsx +15 -0
  184. package/templates/mobile/expo/src/core/utils/font.util.tsx +42 -0
  185. package/templates/mobile/expo/src/core/utils/func.util.ts +48 -0
  186. package/templates/mobile/expo/src/core/utils/greeting.util.ts +20 -0
  187. package/templates/mobile/expo/src/core/utils/image-format.util.ts +117 -0
  188. package/templates/mobile/expo/src/core/utils/image-picker.util.ts +84 -0
  189. package/templates/mobile/expo/src/core/utils/index.ts +18 -0
  190. package/templates/mobile/expo/src/core/utils/linking.util.ts +16 -0
  191. package/templates/mobile/expo/src/core/utils/navigation.util.tsx +100 -0
  192. package/templates/mobile/expo/src/core/utils/number-format.ts +28 -0
  193. package/templates/mobile/expo/src/core/utils/query-client.util.ts +35 -0
  194. package/templates/mobile/expo/src/core/utils/query-persister.util.ts +36 -0
  195. package/templates/mobile/expo/src/core/utils/schema.util.tsx +2713 -0
  196. package/templates/mobile/expo/src/core/utils/size.util.tsx +74 -0
  197. package/templates/mobile/expo/src/core/utils/storage.util.tsx +53 -0
  198. package/templates/mobile/expo/src/core/utils/toast.util.tsx +151 -0
  199. package/templates/mobile/expo/src/core/utils/translator.util.tsx +23 -0
  200. package/templates/mobile/expo/src/core/utils/typography.util.tsx +69 -0
  201. package/templates/mobile/expo/src/core/utils/validate.util.tsx +13 -0
  202. package/templates/mobile/expo/src/declarations.d.ts +54 -0
  203. package/templates/mobile/expo/src/modules/home/home.screen.tsx +33 -0
  204. package/templates/mobile/expo/src/modules/profile/profile.screen.tsx +29 -0
  205. package/templates/mobile/expo/src/scripts/link-fonts.js +60 -0
  206. package/templates/mobile/expo/src/scripts/sync-images.js +56 -0
  207. package/templates/mobile/expo/src/scripts/sync-svgs.js +50 -0
  208. package/templates/mobile/expo/src/types/models.d.ts +24 -0
  209. package/templates/mobile/expo/tsconfig.json +19 -0
  210. package/templates/mobile/rn/.env.example +5 -0
  211. package/templates/mobile/rn/.eslintrc.js +7 -0
  212. package/templates/mobile/rn/.prettierrc.js +7 -0
  213. package/templates/mobile/rn/.svgrrc.js +9 -0
  214. package/templates/mobile/rn/README.md +40 -7
  215. package/templates/mobile/rn/_gitignore +24 -0
  216. package/templates/mobile/rn/_package.json +67 -1
  217. package/templates/mobile/rn/app.json +4 -0
  218. package/templates/mobile/rn/babel.config.js +18 -0
  219. package/templates/mobile/rn/index.js +8 -0
  220. package/templates/mobile/rn/metro.config.js +33 -0
  221. package/templates/mobile/rn/src/app/App.tsx +24 -0
  222. package/templates/mobile/rn/src/app/app-provider.tsx +36 -0
  223. package/templates/mobile/rn/src/app/config/translation.ts +26 -0
  224. package/templates/mobile/rn/src/app/index.ts +1 -0
  225. package/templates/mobile/rn/src/app/navigation/app-route-type.ts +27 -0
  226. package/templates/mobile/rn/src/app/navigation/bottom-tabs.tsx +34 -0
  227. package/templates/mobile/rn/src/app/navigation/index.tsx +14 -0
  228. package/templates/mobile/rn/src/app/stores/auth.store.ts +33 -0
  229. package/templates/mobile/rn/src/app/stores/common.store.ts +19 -0
  230. package/templates/mobile/rn/src/app/stores/index.ts +3 -0
  231. package/templates/mobile/rn/src/app/stores/loading.store.ts +22 -0
  232. package/templates/mobile/rn/src/assets/Images/empty-list.png +0 -0
  233. package/templates/mobile/rn/src/assets/Images/index.ts +5 -0
  234. package/templates/mobile/rn/src/assets/Images/screen-bg-gradian.png +0 -0
  235. package/templates/mobile/rn/src/assets/i18n/en.json +12 -0
  236. package/templates/mobile/rn/src/assets/i18n/fr.json +12 -0
  237. package/templates/mobile/rn/src/assets/lotties/index.ts +3 -0
  238. package/templates/mobile/rn/src/assets/lotties/loading.json +1 -0
  239. package/templates/mobile/rn/src/assets/svgs/arrow-left.svg +3 -0
  240. package/templates/mobile/rn/src/assets/svgs/arrow-right.svg +3 -0
  241. package/templates/mobile/rn/src/assets/svgs/calendar.svg +12 -0
  242. package/templates/mobile/rn/src/assets/svgs/check.svg +3 -0
  243. package/templates/mobile/rn/src/assets/svgs/close.svg +3 -0
  244. package/templates/mobile/rn/src/assets/svgs/eye-hide.svg +3 -0
  245. package/templates/mobile/rn/src/assets/svgs/eye.svg +4 -0
  246. package/templates/mobile/rn/src/assets/svgs/index.ts +29 -0
  247. package/templates/mobile/rn/src/assets/svgs/minus.svg +3 -0
  248. package/templates/mobile/rn/src/assets/svgs/plus.svg +3 -0
  249. package/templates/mobile/rn/src/assets/svgs/search.svg +3 -0
  250. package/templates/mobile/rn/src/assets/svgs/toast-error.svg +5 -0
  251. package/templates/mobile/rn/src/assets/svgs/toast-success.svg +4 -0
  252. package/templates/mobile/rn/src/core/api/endpoints.ts +8 -0
  253. package/templates/mobile/rn/src/core/api/example.api.ts +53 -0
  254. package/templates/mobile/rn/src/core/api/index.ts +4 -0
  255. package/templates/mobile/rn/src/core/components/common/index.ts +1 -0
  256. package/templates/mobile/rn/src/core/components/common/list-empty/index.ts +2 -0
  257. package/templates/mobile/rn/src/core/components/common/list-empty/list-empty.tsx +30 -0
  258. package/templates/mobile/rn/src/core/components/common/list-empty/list-empty.type.ts +5 -0
  259. package/templates/mobile/rn/src/core/components/forms/hf-date-time.tsx +301 -0
  260. package/templates/mobile/rn/src/core/components/forms/hf-password-input.tsx +153 -0
  261. package/templates/mobile/rn/src/core/components/forms/hf-text-input.tsx +59 -0
  262. package/templates/mobile/rn/src/core/components/forms/hf-time-picker.tsx +117 -0
  263. package/templates/mobile/rn/src/core/components/forms/index.ts +4 -0
  264. package/templates/mobile/rn/src/core/components/index.ts +5 -0
  265. package/templates/mobile/rn/src/core/components/loading/index.ts +1 -0
  266. package/templates/mobile/rn/src/core/components/loading/loading-app/index.ts +1 -0
  267. package/templates/mobile/rn/src/core/components/loading/loading-app/loading-app.tsx +50 -0
  268. package/templates/mobile/rn/src/core/components/offline/index.ts +1 -0
  269. package/templates/mobile/rn/src/core/components/offline/offline-banner.tsx +186 -0
  270. package/templates/mobile/rn/src/core/components/screen/index.ts +1 -0
  271. package/templates/mobile/rn/src/core/components/screen/screen-container/index.ts +1 -0
  272. package/templates/mobile/rn/src/core/components/screen/screen-container/screen-container.tsx +252 -0
  273. package/templates/mobile/rn/src/core/components/splash/index.ts +1 -0
  274. package/templates/mobile/rn/src/core/components/splash/splash-overlay/index.ts +1 -0
  275. package/templates/mobile/rn/src/core/components/splash/splash-overlay/splash-overlay.tsx +93 -0
  276. package/templates/mobile/rn/src/core/components/ui/animated-list-item/animated-list-item.tsx +48 -0
  277. package/templates/mobile/rn/src/core/components/ui/animated-list-item/animated-list-item.type.ts +10 -0
  278. package/templates/mobile/rn/src/core/components/ui/animated-list-item/index.ts +2 -0
  279. package/templates/mobile/rn/src/core/components/ui/app-image/app-image.tsx +104 -0
  280. package/templates/mobile/rn/src/core/components/ui/app-image/app-image.type.ts +19 -0
  281. package/templates/mobile/rn/src/core/components/ui/app-image/index.ts +2 -0
  282. package/templates/mobile/rn/src/core/components/ui/asset-placeholder/asset-placeholder.tsx +76 -0
  283. package/templates/mobile/rn/src/core/components/ui/asset-placeholder/index.ts +1 -0
  284. package/templates/mobile/rn/src/core/components/ui/avatar-image/avatar-image.tsx +90 -0
  285. package/templates/mobile/rn/src/core/components/ui/avatar-image/index.ts +1 -0
  286. package/templates/mobile/rn/src/core/components/ui/bottom-sheet/bottom-sheet.tsx +145 -0
  287. package/templates/mobile/rn/src/core/components/ui/bottom-sheet/bottom-sheet.type.ts +10 -0
  288. package/templates/mobile/rn/src/core/components/ui/bottom-sheet/index.ts +2 -0
  289. package/templates/mobile/rn/src/core/components/ui/button/button.style.ts +146 -0
  290. package/templates/mobile/rn/src/core/components/ui/button/button.tsx +97 -0
  291. package/templates/mobile/rn/src/core/components/ui/button/button.type.ts +47 -0
  292. package/templates/mobile/rn/src/core/components/ui/button/index.ts +4 -0
  293. package/templates/mobile/rn/src/core/components/ui/checkbox/checkbox.tsx +127 -0
  294. package/templates/mobile/rn/src/core/components/ui/checkbox/checkbox.type.ts +24 -0
  295. package/templates/mobile/rn/src/core/components/ui/checkbox/index.ts +2 -0
  296. package/templates/mobile/rn/src/core/components/ui/collapsible-section/collapsible-section.tsx +141 -0
  297. package/templates/mobile/rn/src/core/components/ui/collapsible-section/collapsible-section.type.ts +10 -0
  298. package/templates/mobile/rn/src/core/components/ui/collapsible-section/index.ts +2 -0
  299. package/templates/mobile/rn/src/core/components/ui/components.registry.json +313 -0
  300. package/templates/mobile/rn/src/core/components/ui/field/field-frame.tsx +62 -0
  301. package/templates/mobile/rn/src/core/components/ui/field/field.shared.ts +31 -0
  302. package/templates/mobile/rn/src/core/components/ui/header/header.tsx +196 -0
  303. package/templates/mobile/rn/src/core/components/ui/header/header.type.ts +30 -0
  304. package/templates/mobile/rn/src/core/components/ui/header/index.ts +2 -0
  305. package/templates/mobile/rn/src/core/components/ui/icon-button/icon-button.style.ts +23 -0
  306. package/templates/mobile/rn/src/core/components/ui/icon-button/icon-button.tsx +66 -0
  307. package/templates/mobile/rn/src/core/components/ui/icon-button/icon-button.type.ts +25 -0
  308. package/templates/mobile/rn/src/core/components/ui/icon-button/index.ts +2 -0
  309. package/templates/mobile/rn/src/core/components/ui/image-slider/image-slider.tsx +107 -0
  310. package/templates/mobile/rn/src/core/components/ui/image-slider/image-slider.type.ts +10 -0
  311. package/templates/mobile/rn/src/core/components/ui/image-slider/index.ts +2 -0
  312. package/templates/mobile/rn/src/core/components/ui/index.ts +25 -0
  313. package/templates/mobile/rn/src/core/components/ui/label/index.ts +2 -0
  314. package/templates/mobile/rn/src/core/components/ui/label/label.tsx +36 -0
  315. package/templates/mobile/rn/src/core/components/ui/label/label.type.ts +12 -0
  316. package/templates/mobile/rn/src/core/components/ui/modal/index.ts +2 -0
  317. package/templates/mobile/rn/src/core/components/ui/modal/modal.tsx +62 -0
  318. package/templates/mobile/rn/src/core/components/ui/modal/modal.type.ts +11 -0
  319. package/templates/mobile/rn/src/core/components/ui/otp-input/index.ts +2 -0
  320. package/templates/mobile/rn/src/core/components/ui/otp-input/otp-input.tsx +129 -0
  321. package/templates/mobile/rn/src/core/components/ui/otp-input/otp-input.type.ts +20 -0
  322. package/templates/mobile/rn/src/core/components/ui/page-dots/index.ts +1 -0
  323. package/templates/mobile/rn/src/core/components/ui/page-dots/page-dots.tsx +60 -0
  324. package/templates/mobile/rn/src/core/components/ui/radio/index.ts +2 -0
  325. package/templates/mobile/rn/src/core/components/ui/radio/radio.tsx +121 -0
  326. package/templates/mobile/rn/src/core/components/ui/radio/radio.type.ts +20 -0
  327. package/templates/mobile/rn/src/core/components/ui/screen/index.ts +1 -0
  328. package/templates/mobile/rn/src/core/components/ui/screen/screen-gradient.tsx +33 -0
  329. package/templates/mobile/rn/src/core/components/ui/search-box/index.ts +2 -0
  330. package/templates/mobile/rn/src/core/components/ui/search-box/search-box.tsx +162 -0
  331. package/templates/mobile/rn/src/core/components/ui/search-box/search-box.type.ts +26 -0
  332. package/templates/mobile/rn/src/core/components/ui/segmented-control/index.ts +2 -0
  333. package/templates/mobile/rn/src/core/components/ui/segmented-control/segmented-control.tsx +86 -0
  334. package/templates/mobile/rn/src/core/components/ui/segmented-control/segmented-control.type.ts +22 -0
  335. package/templates/mobile/rn/src/core/components/ui/skeleton/index.ts +2 -0
  336. package/templates/mobile/rn/src/core/components/ui/skeleton/skeleton.tsx +106 -0
  337. package/templates/mobile/rn/src/core/components/ui/skeleton/skeleton.type.ts +8 -0
  338. package/templates/mobile/rn/src/core/components/ui/success-state/index.ts +1 -0
  339. package/templates/mobile/rn/src/core/components/ui/success-state/success-state.tsx +68 -0
  340. package/templates/mobile/rn/src/core/components/ui/tabs/index.ts +2 -0
  341. package/templates/mobile/rn/src/core/components/ui/tabs/tabs.tsx +273 -0
  342. package/templates/mobile/rn/src/core/components/ui/tabs/tabs.type.ts +21 -0
  343. package/templates/mobile/rn/src/core/components/ui/tag-input/index.ts +2 -0
  344. package/templates/mobile/rn/src/core/components/ui/tag-input/tag-input.tsx +146 -0
  345. package/templates/mobile/rn/src/core/components/ui/tag-input/tag-input.type.ts +22 -0
  346. package/templates/mobile/rn/src/core/components/ui/text-area/index.ts +2 -0
  347. package/templates/mobile/rn/src/core/components/ui/text-area/text-area.tsx +90 -0
  348. package/templates/mobile/rn/src/core/components/ui/text-area/text-area.type.ts +20 -0
  349. package/templates/mobile/rn/src/core/components/ui/text-field/index.ts +2 -0
  350. package/templates/mobile/rn/src/core/components/ui/text-field/text-field.tsx +116 -0
  351. package/templates/mobile/rn/src/core/components/ui/text-field/text-field.type.ts +21 -0
  352. package/templates/mobile/rn/src/core/components/ui/toggle/index.ts +2 -0
  353. package/templates/mobile/rn/src/core/components/ui/toggle/toggle.tsx +110 -0
  354. package/templates/mobile/rn/src/core/components/ui/toggle/toggle.type.ts +19 -0
  355. package/templates/mobile/rn/src/core/constants/external-urls.constant.ts +5 -0
  356. package/templates/mobile/rn/src/core/constants/hard-data.constant.ts +0 -0
  357. package/templates/mobile/rn/src/core/constants/index.ts +2 -0
  358. package/templates/mobile/rn/src/core/constants/type.constant.ts +3 -0
  359. package/templates/mobile/rn/src/core/context/index.ts +1 -0
  360. package/templates/mobile/rn/src/core/context/shared-transition-context.tsx +35 -0
  361. package/templates/mobile/rn/src/core/hook/index.ts +8 -0
  362. package/templates/mobile/rn/src/core/hook/useActiveRouteName.ts +63 -0
  363. package/templates/mobile/rn/src/core/hook/useAppNavigation.tsx +7 -0
  364. package/templates/mobile/rn/src/core/hook/useBottomInset.tsx +26 -0
  365. package/templates/mobile/rn/src/core/hook/useDebounce.tsx +16 -0
  366. package/templates/mobile/rn/src/core/hook/useEndReached.tsx +46 -0
  367. package/templates/mobile/rn/src/core/hook/useManualRefetch.ts +56 -0
  368. package/templates/mobile/rn/src/core/hook/useNetworkStatus.ts +68 -0
  369. package/templates/mobile/rn/src/core/hook/useTimeout.tsx +30 -0
  370. package/templates/mobile/rn/src/core/index.ts +7 -0
  371. package/templates/mobile/rn/src/core/services/api.service.ts +230 -0
  372. package/templates/mobile/rn/src/core/services/device-id.service.ts +23 -0
  373. package/templates/mobile/rn/src/core/services/index.ts +3 -0
  374. package/templates/mobile/rn/src/core/services/session-end.bridge.ts +26 -0
  375. package/templates/mobile/rn/src/core/theme/dark.theme.ts +10 -0
  376. package/templates/mobile/rn/src/core/theme/index.ts +5 -0
  377. package/templates/mobile/rn/src/core/theme/light.theme.ts +44 -0
  378. package/templates/mobile/rn/src/core/theme/theme-context.tsx +82 -0
  379. package/templates/mobile/rn/src/core/theme/theme.types.ts +26 -0
  380. package/templates/mobile/rn/src/core/theme/use-themed-styles.ts +25 -0
  381. package/templates/mobile/rn/src/core/utils/color.util.tsx +198 -0
  382. package/templates/mobile/rn/src/core/utils/date.util.ts +97 -0
  383. package/templates/mobile/rn/src/core/utils/device-locale.util.ts +22 -0
  384. package/templates/mobile/rn/src/core/utils/emitter/index.ts +161 -0
  385. package/templates/mobile/rn/src/core/utils/emitter/type.ts +40 -0
  386. package/templates/mobile/rn/src/core/utils/enum.util.tsx +15 -0
  387. package/templates/mobile/rn/src/core/utils/font.util.tsx +42 -0
  388. package/templates/mobile/rn/src/core/utils/func.util.ts +48 -0
  389. package/templates/mobile/rn/src/core/utils/greeting.util.ts +20 -0
  390. package/templates/mobile/rn/src/core/utils/image-format.util.ts +117 -0
  391. package/templates/mobile/rn/src/core/utils/image-picker.util.ts +84 -0
  392. package/templates/mobile/rn/src/core/utils/index.ts +18 -0
  393. package/templates/mobile/rn/src/core/utils/linking.util.ts +16 -0
  394. package/templates/mobile/rn/src/core/utils/navigation.util.tsx +100 -0
  395. package/templates/mobile/rn/src/core/utils/number-format.ts +28 -0
  396. package/templates/mobile/rn/src/core/utils/query-client.util.ts +35 -0
  397. package/templates/mobile/rn/src/core/utils/query-persister.util.ts +36 -0
  398. package/templates/mobile/rn/src/core/utils/schema.util.tsx +2713 -0
  399. package/templates/mobile/rn/src/core/utils/size.util.tsx +74 -0
  400. package/templates/mobile/rn/src/core/utils/storage.util.tsx +53 -0
  401. package/templates/mobile/rn/src/core/utils/toast.util.tsx +151 -0
  402. package/templates/mobile/rn/src/core/utils/translator.util.tsx +23 -0
  403. package/templates/mobile/rn/src/core/utils/typography.util.tsx +69 -0
  404. package/templates/mobile/rn/src/core/utils/validate.util.tsx +13 -0
  405. package/templates/mobile/rn/src/declarations.d.ts +54 -0
  406. package/templates/mobile/rn/src/modules/home/home.screen.tsx +33 -0
  407. package/templates/mobile/rn/src/modules/profile/profile.screen.tsx +29 -0
  408. package/templates/mobile/rn/src/scripts/link-fonts.js +60 -0
  409. package/templates/mobile/rn/src/scripts/sync-images.js +56 -0
  410. package/templates/mobile/rn/src/scripts/sync-svgs.js +50 -0
  411. package/templates/mobile/rn/src/types/models.d.ts +24 -0
  412. package/templates/mobile/rn/tsconfig.json +21 -0
  413. package/templates/shared/README.md +21 -6
  414. package/templates/shared/_package.json +26 -4
  415. package/templates/shared/src/api-endpoints.ts +8 -0
  416. package/templates/shared/src/enums.ts +34 -0
  417. package/templates/shared/src/external-urls.ts +5 -0
  418. package/templates/shared/src/index.ts +15 -0
  419. package/templates/shared/tsconfig.json +8 -0
  420. package/templates/shared/tsup.config.ts +9 -0
  421. package/templates/shared/index.js +0 -4
package/README.md CHANGED
@@ -1,64 +1,84 @@
1
1
  # create-du-app
2
2
 
3
- > The `create-app` CLI — scaffolds a standalone product monorepo from company templates.
3
+ > Scaffold a standalone product monorepo from company templates — in one command.
4
4
 
5
- Prompts for a project name and a selection of stacks (Mobile / Frontend / Backend), then copies
6
- the matching templates, renames manifests, substitutes the project name, and emits a ready-to-run
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
- ## Installation
8
+ ## Quick start
9
+
10
+ No install needed. In a real terminal (Terminal.app / iTerm):
10
11
 
11
12
  ```bash
12
- cd packages/cli
13
- pnpm install
14
- pnpm link --global # registers the global `create-app` command
13
+ npx create-du-app
15
14
  ```
16
15
 
17
- Or run without linking:
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
- node src/index.js
25
+ cd my-shop && pnpm install
21
26
  ```
22
27
 
23
- ## Usage
28
+ Done. 🎉
24
29
 
25
- **Interactive** (requires a real terminal):
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
- **Non-interactive** (CI or any terminal):
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
- create-app --name my-shop --mobile expo --fe nextjs --be nestjs
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
- ### Options
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
- | Flag | Description |
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
- ## How it works
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, decides interactive vs. non-interactive, runs the generator. |
53
- | `registry.js` | **Data declaration** of groups, technologies, `templatePath`, and `lang`. The only file to edit when adding or removing a stack. |
54
- | `prompts.js` | Interactive prompts (`@clack/prompts`): project name → multi-select groups → select one technology per group. |
55
- | `generate.js` | Copies templates, renames `_package.json` → `package.json`, generates the root `package.json` + `pnpm-workspace.yaml`, conditionally creates `packages/shared`, and substitutes `{{PROJECT_NAME}}`. |
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
- - A manifest named `_package.json` is renamed to `package.json` on generate. Likewise
60
- `_gitignore` `.gitignore` and `_npmrc` `.npmrc`.
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
- See **[CONTRIBUTING.md](../../CONTRIBUTING.md)** for the full workflow of adding real source.
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.2",
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": ">=18"
21
+ "node": ">=20"
21
22
  },
22
- "packageManager": "pnpm@9.0.0",
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 package.json + replace placeholders.
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
- // Build the project's root package.json dynamically (pnpm: NO "workspaces" field).
70
- function buildRootPackageJson(projectName) {
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
- engines: { node: '>=18' },
76
- packageManager: 'pnpm@9.0.0',
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 jsCount = selections.filter((s) => s.option.lang === 'js').length;
111
- if (jsCount >= 2) {
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} (${jsCount} JS/TS apps)`);
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 ${jsCount}).`);
330
+ logs.push(`• Skipping shared: not enough JS/TS apps (need >= 2, have ${jsSelections.length}).`);
118
331
  }
119
332
 
120
- // 3) Generate the root package.json + pnpm-workspace.yaml dynamically.
121
- const rootPkg = buildRootPackageJson(projectName);
122
- await fse.writeJson(path.join(projectRoot, 'package.json'), rootPkg, { spaces: 2 });
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: ${wsEntries.join(', ')})`);
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
- // Path to the shared template folder (only copied when >= 2 selections have lang === 'js').
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,5 @@
1
+ # Copy to .env and fill in. Read at build time by react-native-config.
2
+ # NEVER commit the real .env — only this example.
3
+
4
+ # Base URL of your API (include trailing slash).
5
+ BASE_URL=https://api.example.com/
@@ -0,0 +1,7 @@
1
+ module.exports = {
2
+ root: true,
3
+ extends: '@react-native',
4
+ rules: {
5
+ semi: 0,
6
+ },
7
+ };
@@ -0,0 +1,7 @@
1
+ module.exports = {
2
+ arrowParens: 'avoid',
3
+ bracketSameLine: true,
4
+ bracketSpacing: true,
5
+ singleQuote: true,
6
+ trailingComma: 'all',
7
+ };
@@ -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
- # Placeholder: Expo (mobile/expo)
1
+ # {{PROJECT_NAME}} Mobile (Expo)
2
2
 
3
- This is a **placeholder** for the **Expo** template.
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
- Drop the standard Expo source here. Conventions:
8
+ ## Architecture
6
9
 
7
- - Name the template's `package.json` as **`_package.json`** (the CLI renames it on generate).
8
- - Name `.gitignore` as **`_gitignore`**, `.npmrc` as **`_npmrc`** if present.
9
- - Wherever you need the project name, write `{{PROJECT_NAME}}` — the CLI replaces it with the real name.
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
- `lang: js` this app counts toward the condition for creating `packages/shared`.
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