@symbiote-native/cli 0.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (384) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +492 -0
  3. package/bundle.js +2833 -0
  4. package/package.json +49 -0
  5. package/src/index.ts +70 -0
  6. package/templates/README.md +93 -0
  7. package/templates/js/angular/.prettierrc.js +5 -0
  8. package/templates/js/angular/.watchmanconfig +1 -0
  9. package/templates/js/angular/README.md +117 -0
  10. package/templates/js/angular/app.json +4 -0
  11. package/templates/js/angular/babel.config.js +34 -0
  12. package/templates/js/angular/index.js +12 -0
  13. package/templates/js/angular/metro.config.js +38 -0
  14. package/templates/js/angular/package.json.fragment.json +29 -0
  15. package/templates/js/angular/src/App.css +89 -0
  16. package/templates/js/angular/src/App.ts +40 -0
  17. package/templates/js/angular/src/assets/angular-logo.png +0 -0
  18. package/templates/js/angular/src/assets/angular-logo@2x.png +0 -0
  19. package/templates/js/angular/src/assets/angular-logo@3x.png +0 -0
  20. package/templates/js/angular/src/assets/plus-icon.png +0 -0
  21. package/templates/js/angular/src/assets/plus-icon@2x.png +0 -0
  22. package/templates/js/angular/src/assets/plus-icon@3x.png +0 -0
  23. package/templates/js/angular/src/assets/react-native-logo.png +0 -0
  24. package/templates/js/angular/src/assets/react-native-logo@2x.png +0 -0
  25. package/templates/js/angular/src/assets/react-native-logo@3x.png +0 -0
  26. package/templates/js/angular/src/css.d.ts +23 -0
  27. package/templates/js/angular/tsconfig.angular.json +42 -0
  28. package/templates/js/angular/tsconfig.json +17 -0
  29. package/templates/js/react/.prettierrc.js +5 -0
  30. package/templates/js/react/.watchmanconfig +1 -0
  31. package/templates/js/react/App.css +69 -0
  32. package/templates/js/react/App.jsx +27 -0
  33. package/templates/js/react/App.tsx +27 -0
  34. package/templates/js/react/README.md +116 -0
  35. package/templates/js/react/app.json +4 -0
  36. package/templates/js/react/assets/react-native-logo.png +0 -0
  37. package/templates/js/react/assets/react-native-logo@2x.png +0 -0
  38. package/templates/js/react/assets/react-native-logo@3x.png +0 -0
  39. package/templates/js/react/babel.config.js +24 -0
  40. package/templates/js/react/css.d.ts +24 -0
  41. package/templates/js/react/index.js +14 -0
  42. package/templates/js/react/metro.config.js +29 -0
  43. package/templates/js/react/package.json.fragment.json +22 -0
  44. package/templates/js/react/package.json.fragment.typescript.json +11 -0
  45. package/templates/js/react/tsconfig.json +18 -0
  46. package/templates/js/solid/.prettierrc.js +5 -0
  47. package/templates/js/solid/.watchmanconfig +1 -0
  48. package/templates/js/solid/App.css +89 -0
  49. package/templates/js/solid/App.jsx +35 -0
  50. package/templates/js/solid/App.tsx +35 -0
  51. package/templates/js/solid/README.md +18 -0
  52. package/templates/js/solid/app.json +4 -0
  53. package/templates/js/solid/assets/plus-icon.png +0 -0
  54. package/templates/js/solid/assets/plus-icon@2x.png +0 -0
  55. package/templates/js/solid/assets/plus-icon@3x.png +0 -0
  56. package/templates/js/solid/assets/react-native-logo.png +0 -0
  57. package/templates/js/solid/assets/react-native-logo@2x.png +0 -0
  58. package/templates/js/solid/assets/react-native-logo@3x.png +0 -0
  59. package/templates/js/solid/assets/solid-logo.png +0 -0
  60. package/templates/js/solid/assets/solid-logo@2x.png +0 -0
  61. package/templates/js/solid/assets/solid-logo@3x.png +0 -0
  62. package/templates/js/solid/babel.config.js +29 -0
  63. package/templates/js/solid/css.d.ts +20 -0
  64. package/templates/js/solid/eslint.config.js +3 -0
  65. package/templates/js/solid/index.js +13 -0
  66. package/templates/js/solid/metro.config.js +50 -0
  67. package/templates/js/solid/package.json.fragment.json +23 -0
  68. package/templates/js/solid/package.json.fragment.typescript.json +11 -0
  69. package/templates/js/solid/tsconfig.json +11 -0
  70. package/templates/js/svelte/.prettierrc.js +15 -0
  71. package/templates/js/svelte/.watchmanconfig +1 -0
  72. package/templates/js/svelte/App.svelte +123 -0
  73. package/templates/js/svelte/App.typescript.svelte +123 -0
  74. package/templates/js/svelte/README.md +18 -0
  75. package/templates/js/svelte/app.json +4 -0
  76. package/templates/js/svelte/babel.config.js +22 -0
  77. package/templates/js/svelte/css.d.ts +21 -0
  78. package/templates/js/svelte/eslint.config.js +37 -0
  79. package/templates/js/svelte/image-uris.js +8 -0
  80. package/templates/js/svelte/index.js +13 -0
  81. package/templates/js/svelte/metro.config.js +83 -0
  82. package/templates/js/svelte/package.json.fragment.json +26 -0
  83. package/templates/js/svelte/package.json.fragment.typescript.json +12 -0
  84. package/templates/js/svelte/svelte.config.js +47 -0
  85. package/templates/js/svelte/tsconfig.json +9 -0
  86. package/templates/js/svelte/tsconfig.typecheck.json +4 -0
  87. package/templates/js/vue-sfc/.prettierrc.js +5 -0
  88. package/templates/js/vue-sfc/.watchmanconfig +1 -0
  89. package/templates/js/vue-sfc/App.typescript.vue +128 -0
  90. package/templates/js/vue-sfc/App.vue +128 -0
  91. package/templates/js/vue-sfc/README.md +124 -0
  92. package/templates/js/vue-sfc/app.json +4 -0
  93. package/templates/js/vue-sfc/assets/plus-icon.png +0 -0
  94. package/templates/js/vue-sfc/assets/plus-icon@2x.png +0 -0
  95. package/templates/js/vue-sfc/assets/plus-icon@3x.png +0 -0
  96. package/templates/js/vue-sfc/assets/react-native-logo.png +0 -0
  97. package/templates/js/vue-sfc/assets/react-native-logo@2x.png +0 -0
  98. package/templates/js/vue-sfc/assets/react-native-logo@3x.png +0 -0
  99. package/templates/js/vue-sfc/assets/vue-logo.png +0 -0
  100. package/templates/js/vue-sfc/assets/vue-logo@2x.png +0 -0
  101. package/templates/js/vue-sfc/assets/vue-logo@3x.png +0 -0
  102. package/templates/js/vue-sfc/babel.config.js +24 -0
  103. package/templates/js/vue-sfc/css.d.ts +24 -0
  104. package/templates/js/vue-sfc/eslint.config.js +48 -0
  105. package/templates/js/vue-sfc/index.js +13 -0
  106. package/templates/js/vue-sfc/metro.config.js +30 -0
  107. package/templates/js/vue-sfc/package.json.fragment.json +26 -0
  108. package/templates/js/vue-sfc/package.json.fragment.typescript.json +11 -0
  109. package/templates/js/vue-sfc/tsconfig.json +18 -0
  110. package/templates/js/vue-sfc/tsconfig.typecheck.json +8 -0
  111. package/templates/js/vue-sfc/vue-runtime-core.d.ts +3 -0
  112. package/templates/js/vue-tsx/.prettierrc.js +5 -0
  113. package/templates/js/vue-tsx/.watchmanconfig +1 -0
  114. package/templates/js/vue-tsx/App.css +89 -0
  115. package/templates/js/vue-tsx/App.jsx +40 -0
  116. package/templates/js/vue-tsx/App.tsx +40 -0
  117. package/templates/js/vue-tsx/README.md +110 -0
  118. package/templates/js/vue-tsx/app.json +4 -0
  119. package/templates/js/vue-tsx/assets/plus-icon.png +0 -0
  120. package/templates/js/vue-tsx/assets/plus-icon@2x.png +0 -0
  121. package/templates/js/vue-tsx/assets/plus-icon@3x.png +0 -0
  122. package/templates/js/vue-tsx/assets/react-native-logo.png +0 -0
  123. package/templates/js/vue-tsx/assets/react-native-logo@2x.png +0 -0
  124. package/templates/js/vue-tsx/assets/react-native-logo@3x.png +0 -0
  125. package/templates/js/vue-tsx/assets/vue-logo.png +0 -0
  126. package/templates/js/vue-tsx/assets/vue-logo@2x.png +0 -0
  127. package/templates/js/vue-tsx/assets/vue-logo@3x.png +0 -0
  128. package/templates/js/vue-tsx/babel.config.js +67 -0
  129. package/templates/js/vue-tsx/css.d.ts +24 -0
  130. package/templates/js/vue-tsx/index.js +14 -0
  131. package/templates/js/vue-tsx/metro.config.js +42 -0
  132. package/templates/js/vue-tsx/package.json.fragment.json +26 -0
  133. package/templates/js/vue-tsx/package.json.fragment.typescript.json +11 -0
  134. package/templates/js/vue-tsx/tsconfig.json +15 -0
  135. package/templates/js/vue-tsx/tsconfig.typecheck.json +10 -0
  136. package/templates/js/vue-tsx/vue-jsx.d.ts +43 -0
  137. package/templates/js/vue-tsx/vue-runtime-core.d.ts +3 -0
  138. package/templates/layers/README.md +90 -0
  139. package/templates/layers/application/package.json.fragment.json +5 -0
  140. package/templates/layers/battery/package.json.fragment.json +5 -0
  141. package/templates/layers/brightness/package.json.fragment.json +5 -0
  142. package/templates/layers/cellular/package.json.fragment.json +5 -0
  143. package/templates/layers/clipboard/package.json.fragment.json +5 -0
  144. package/templates/layers/crypto/package.json.fragment.json +5 -0
  145. package/templates/layers/device/package.json.fragment.json +5 -0
  146. package/templates/layers/expo-modules/ios/Canary/Info.plist +66 -0
  147. package/templates/layers/expo-modules/package.json.fragment.json +9 -0
  148. package/templates/layers/haptics/package.json.fragment.json +5 -0
  149. package/templates/layers/keep-awake/package.json.fragment.json +5 -0
  150. package/templates/layers/local-auth/package.json.fragment.json +5 -0
  151. package/templates/layers/localization/package.json.fragment.json +5 -0
  152. package/templates/layers/navigation/app/angular/assets/angular-logo.png +0 -0
  153. package/templates/layers/navigation/app/angular/assets/angular-logo@2x.png +0 -0
  154. package/templates/layers/navigation/app/angular/assets/angular-logo@3x.png +0 -0
  155. package/templates/layers/navigation/app/angular/assets/plus-icon.png +0 -0
  156. package/templates/layers/navigation/app/angular/assets/plus-icon@2x.png +0 -0
  157. package/templates/layers/navigation/app/angular/assets/plus-icon@3x.png +0 -0
  158. package/templates/layers/navigation/app/angular/assets/react-native-logo.png +0 -0
  159. package/templates/layers/navigation/app/angular/assets/react-native-logo@2x.png +0 -0
  160. package/templates/layers/navigation/app/angular/assets/react-native-logo@3x.png +0 -0
  161. package/templates/layers/navigation/app/angular/src/App.css +129 -0
  162. package/templates/layers/navigation/app/angular/src/App.ts +31 -0
  163. package/templates/layers/navigation/app/angular/src/DetailsScreen.ts +24 -0
  164. package/templates/layers/navigation/app/angular/src/MenuScreen.ts +43 -0
  165. package/templates/layers/navigation/app/react/App.css +109 -0
  166. package/templates/layers/navigation/app/react/App.jsx +77 -0
  167. package/templates/layers/navigation/app/react/App.tsx +77 -0
  168. package/templates/layers/navigation/app/react/assets/react-native-logo.png +0 -0
  169. package/templates/layers/navigation/app/react/assets/react-native-logo@2x.png +0 -0
  170. package/templates/layers/navigation/app/react/assets/react-native-logo@3x.png +0 -0
  171. package/templates/layers/navigation/app/solid/App.css +129 -0
  172. package/templates/layers/navigation/app/solid/App.jsx +85 -0
  173. package/templates/layers/navigation/app/solid/App.tsx +85 -0
  174. package/templates/layers/navigation/app/solid/assets/plus-icon.png +0 -0
  175. package/templates/layers/navigation/app/solid/assets/plus-icon@2x.png +0 -0
  176. package/templates/layers/navigation/app/solid/assets/plus-icon@3x.png +0 -0
  177. package/templates/layers/navigation/app/solid/assets/react-native-logo.png +0 -0
  178. package/templates/layers/navigation/app/solid/assets/react-native-logo@2x.png +0 -0
  179. package/templates/layers/navigation/app/solid/assets/react-native-logo@3x.png +0 -0
  180. package/templates/layers/navigation/app/solid/assets/solid-logo.png +0 -0
  181. package/templates/layers/navigation/app/solid/assets/solid-logo@2x.png +0 -0
  182. package/templates/layers/navigation/app/solid/assets/solid-logo@3x.png +0 -0
  183. package/templates/layers/navigation/app/svelte/App.css +129 -0
  184. package/templates/layers/navigation/app/svelte/App.svelte +19 -0
  185. package/templates/layers/navigation/app/svelte/App.typescript.svelte +19 -0
  186. package/templates/layers/navigation/app/svelte/DetailsScreen.svelte +17 -0
  187. package/templates/layers/navigation/app/svelte/DetailsScreen.typescript.svelte +17 -0
  188. package/templates/layers/navigation/app/svelte/MenuScreen.svelte +40 -0
  189. package/templates/layers/navigation/app/svelte/MenuScreen.typescript.svelte +40 -0
  190. package/templates/layers/navigation/app/svelte/image-uris.js +8 -0
  191. package/templates/layers/navigation/app/vue-sfc/App.css +129 -0
  192. package/templates/layers/navigation/app/vue-sfc/App.typescript.vue +36 -0
  193. package/templates/layers/navigation/app/vue-sfc/App.vue +36 -0
  194. package/templates/layers/navigation/app/vue-sfc/DetailsScreen.typescript.vue +20 -0
  195. package/templates/layers/navigation/app/vue-sfc/DetailsScreen.vue +20 -0
  196. package/templates/layers/navigation/app/vue-sfc/MenuScreen.typescript.vue +52 -0
  197. package/templates/layers/navigation/app/vue-sfc/MenuScreen.vue +52 -0
  198. package/templates/layers/navigation/app/vue-sfc/assets/plus-icon.png +0 -0
  199. package/templates/layers/navigation/app/vue-sfc/assets/plus-icon@2x.png +0 -0
  200. package/templates/layers/navigation/app/vue-sfc/assets/plus-icon@3x.png +0 -0
  201. package/templates/layers/navigation/app/vue-sfc/assets/react-native-logo.png +0 -0
  202. package/templates/layers/navigation/app/vue-sfc/assets/react-native-logo@2x.png +0 -0
  203. package/templates/layers/navigation/app/vue-sfc/assets/react-native-logo@3x.png +0 -0
  204. package/templates/layers/navigation/app/vue-sfc/assets/vue-logo.png +0 -0
  205. package/templates/layers/navigation/app/vue-sfc/assets/vue-logo@2x.png +0 -0
  206. package/templates/layers/navigation/app/vue-sfc/assets/vue-logo@3x.png +0 -0
  207. package/templates/layers/navigation/app/vue-tsx/App.css +129 -0
  208. package/templates/layers/navigation/app/vue-tsx/App.jsx +91 -0
  209. package/templates/layers/navigation/app/vue-tsx/App.tsx +91 -0
  210. package/templates/layers/navigation/app/vue-tsx/assets/plus-icon.png +0 -0
  211. package/templates/layers/navigation/app/vue-tsx/assets/plus-icon@2x.png +0 -0
  212. package/templates/layers/navigation/app/vue-tsx/assets/plus-icon@3x.png +0 -0
  213. package/templates/layers/navigation/app/vue-tsx/assets/react-native-logo.png +0 -0
  214. package/templates/layers/navigation/app/vue-tsx/assets/react-native-logo@2x.png +0 -0
  215. package/templates/layers/navigation/app/vue-tsx/assets/react-native-logo@3x.png +0 -0
  216. package/templates/layers/navigation/app/vue-tsx/assets/vue-logo.png +0 -0
  217. package/templates/layers/navigation/app/vue-tsx/assets/vue-logo@2x.png +0 -0
  218. package/templates/layers/navigation/app/vue-tsx/assets/vue-logo@3x.png +0 -0
  219. package/templates/layers/navigation/package.json.fragment.json +5 -0
  220. package/templates/layers/network/package.json.fragment.json +5 -0
  221. package/templates/layers/screen-orientation/package.json.fragment.json +5 -0
  222. package/templates/layers/secure-store/package.json.fragment.json +5 -0
  223. package/templates/layers/sensors/package.json.fragment.json +5 -0
  224. package/templates/layers/sharing/package.json.fragment.json +5 -0
  225. package/templates/layers/slider/package.json.fragment.json +5 -0
  226. package/templates/layers/sms/package.json.fragment.json +5 -0
  227. package/templates/layers/splash-screen/native/android/app/src/main/AndroidManifest.xml +28 -0
  228. package/templates/layers/splash-screen/native/android/app/src/main/java/com/canary/MainActivity.kt +29 -0
  229. package/templates/layers/splash-screen/native/android/app/src/main/res/values/styles.xml +12 -0
  230. package/templates/layers/splash-screen/native/ios/Canary/AppDelegate.swift +54 -0
  231. package/templates/layers/splash-screen/package.json.fragment.json +5 -0
  232. package/templates/layers/standard-web-crypto/package.json.fragment.json +5 -0
  233. package/templates/layers/store-review/package.json.fragment.json +5 -0
  234. package/templates/layers/system-ui/package.json.fragment.json +5 -0
  235. package/templates/layers/testing/detox.config.js +42 -0
  236. package/templates/layers/testing/e2e/jest.config.js +21 -0
  237. package/templates/layers/testing/e2e/setup.ts +3 -0
  238. package/templates/layers/testing/e2e/smoke.test.ts +17 -0
  239. package/templates/layers/testing/e2e/tsconfig.json +7 -0
  240. package/templates/layers/testing/fragment/angular/package.json.fragment.json +18 -0
  241. package/templates/layers/testing/fragment/base/package.json.fragment.json +18 -0
  242. package/templates/layers/tracking-transparency/package.json.fragment.json +5 -0
  243. package/templates/layers/web-browser/package.json.fragment.json +5 -0
  244. package/templates/native/Gemfile +17 -0
  245. package/templates/native/README.md +48 -0
  246. package/templates/native/android/app/build.gradle +130 -0
  247. package/templates/native/android/app/debug.keystore +0 -0
  248. package/templates/native/android/app/proguard-rules.pro +10 -0
  249. package/templates/native/android/app/src/androidTest/java/com/canary/DetoxTest.java +29 -0
  250. package/templates/native/android/app/src/main/AndroidManifest.xml +28 -0
  251. package/templates/native/android/app/src/main/java/com/canary/MainActivity.kt +22 -0
  252. package/templates/native/android/app/src/main/java/com/canary/MainApplication.kt +27 -0
  253. package/templates/native/android/app/src/main/res/drawable/rn_edit_text_material.xml +37 -0
  254. package/templates/native/android/app/src/main/res/drawable-hdpi/bootsplash_logo.png +0 -0
  255. package/templates/native/android/app/src/main/res/drawable-mdpi/bootsplash_logo.png +0 -0
  256. package/templates/native/android/app/src/main/res/drawable-xhdpi/bootsplash_logo.png +0 -0
  257. package/templates/native/android/app/src/main/res/drawable-xxhdpi/bootsplash_logo.png +0 -0
  258. package/templates/native/android/app/src/main/res/drawable-xxxhdpi/bootsplash_logo.png +0 -0
  259. package/templates/native/android/app/src/main/res/mipmap-hdpi/ic_launcher.png +0 -0
  260. package/templates/native/android/app/src/main/res/mipmap-hdpi/ic_launcher_round.png +0 -0
  261. package/templates/native/android/app/src/main/res/mipmap-mdpi/ic_launcher.png +0 -0
  262. package/templates/native/android/app/src/main/res/mipmap-mdpi/ic_launcher_round.png +0 -0
  263. package/templates/native/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png +0 -0
  264. package/templates/native/android/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png +0 -0
  265. package/templates/native/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png +0 -0
  266. package/templates/native/android/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png +0 -0
  267. package/templates/native/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png +0 -0
  268. package/templates/native/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png +0 -0
  269. package/templates/native/android/app/src/main/res/values/colors.xml +3 -0
  270. package/templates/native/android/app/src/main/res/values/strings.xml +3 -0
  271. package/templates/native/android/app/src/main/res/values/styles.xml +6 -0
  272. package/templates/native/android/build.gradle +33 -0
  273. package/templates/native/android/gradle/wrapper/gradle-wrapper.jar +0 -0
  274. package/templates/native/android/gradle/wrapper/gradle-wrapper.properties +7 -0
  275. package/templates/native/android/gradle.properties +44 -0
  276. package/templates/native/android/gradlew +248 -0
  277. package/templates/native/android/gradlew.bat +98 -0
  278. package/templates/native/android/settings.gradle +10 -0
  279. package/templates/native/bootsplash-logo/angular/android/app/src/main/res/drawable-hdpi/bootsplash_logo.png +0 -0
  280. package/templates/native/bootsplash-logo/angular/android/app/src/main/res/drawable-mdpi/bootsplash_logo.png +0 -0
  281. package/templates/native/bootsplash-logo/angular/android/app/src/main/res/drawable-xhdpi/bootsplash_logo.png +0 -0
  282. package/templates/native/bootsplash-logo/angular/android/app/src/main/res/drawable-xxhdpi/bootsplash_logo.png +0 -0
  283. package/templates/native/bootsplash-logo/angular/android/app/src/main/res/drawable-xxxhdpi/bootsplash_logo.png +0 -0
  284. package/templates/native/bootsplash-logo/angular/ios/Canary/Images.xcassets/BootSplashLogo-498e55.imageset/logo-498e55.png +0 -0
  285. package/templates/native/bootsplash-logo/angular/ios/Canary/Images.xcassets/BootSplashLogo-498e55.imageset/logo-498e55@2x.png +0 -0
  286. package/templates/native/bootsplash-logo/angular/ios/Canary/Images.xcassets/BootSplashLogo-498e55.imageset/logo-498e55@3x.png +0 -0
  287. package/templates/native/bootsplash-logo/solid/android/app/src/main/res/drawable-hdpi/bootsplash_logo.png +0 -0
  288. package/templates/native/bootsplash-logo/solid/android/app/src/main/res/drawable-mdpi/bootsplash_logo.png +0 -0
  289. package/templates/native/bootsplash-logo/solid/android/app/src/main/res/drawable-xhdpi/bootsplash_logo.png +0 -0
  290. package/templates/native/bootsplash-logo/solid/android/app/src/main/res/drawable-xxhdpi/bootsplash_logo.png +0 -0
  291. package/templates/native/bootsplash-logo/solid/android/app/src/main/res/drawable-xxxhdpi/bootsplash_logo.png +0 -0
  292. package/templates/native/bootsplash-logo/solid/ios/Canary/Images.xcassets/BootSplashLogo-498e55.imageset/logo-498e55.png +0 -0
  293. package/templates/native/bootsplash-logo/solid/ios/Canary/Images.xcassets/BootSplashLogo-498e55.imageset/logo-498e55@2x.png +0 -0
  294. package/templates/native/bootsplash-logo/solid/ios/Canary/Images.xcassets/BootSplashLogo-498e55.imageset/logo-498e55@3x.png +0 -0
  295. package/templates/native/bootsplash-logo/svelte/android/app/src/main/res/drawable-hdpi/bootsplash_logo.png +0 -0
  296. package/templates/native/bootsplash-logo/svelte/android/app/src/main/res/drawable-mdpi/bootsplash_logo.png +0 -0
  297. package/templates/native/bootsplash-logo/svelte/android/app/src/main/res/drawable-xhdpi/bootsplash_logo.png +0 -0
  298. package/templates/native/bootsplash-logo/svelte/android/app/src/main/res/drawable-xxhdpi/bootsplash_logo.png +0 -0
  299. package/templates/native/bootsplash-logo/svelte/android/app/src/main/res/drawable-xxxhdpi/bootsplash_logo.png +0 -0
  300. package/templates/native/bootsplash-logo/svelte/ios/Canary/Images.xcassets/BootSplashLogo-498e55.imageset/logo-498e55.png +0 -0
  301. package/templates/native/bootsplash-logo/svelte/ios/Canary/Images.xcassets/BootSplashLogo-498e55.imageset/logo-498e55@2x.png +0 -0
  302. package/templates/native/bootsplash-logo/svelte/ios/Canary/Images.xcassets/BootSplashLogo-498e55.imageset/logo-498e55@3x.png +0 -0
  303. package/templates/native/bootsplash-logo/vue/android/app/src/main/res/drawable-hdpi/bootsplash_logo.png +0 -0
  304. package/templates/native/bootsplash-logo/vue/android/app/src/main/res/drawable-mdpi/bootsplash_logo.png +0 -0
  305. package/templates/native/bootsplash-logo/vue/android/app/src/main/res/drawable-xhdpi/bootsplash_logo.png +0 -0
  306. package/templates/native/bootsplash-logo/vue/android/app/src/main/res/drawable-xxhdpi/bootsplash_logo.png +0 -0
  307. package/templates/native/bootsplash-logo/vue/android/app/src/main/res/drawable-xxxhdpi/bootsplash_logo.png +0 -0
  308. package/templates/native/bootsplash-logo/vue/ios/Canary/Images.xcassets/BootSplashLogo-498e55.imageset/logo-498e55.png +0 -0
  309. package/templates/native/bootsplash-logo/vue/ios/Canary/Images.xcassets/BootSplashLogo-498e55.imageset/logo-498e55@2x.png +0 -0
  310. package/templates/native/bootsplash-logo/vue/ios/Canary/Images.xcassets/BootSplashLogo-498e55.imageset/logo-498e55@3x.png +0 -0
  311. package/templates/native/eslint.config.js +3 -0
  312. package/templates/native/ios/.xcode.env +11 -0
  313. package/templates/native/ios/Canary/AppDelegate.swift +48 -0
  314. package/templates/native/ios/Canary/BootSplash.storyboard +46 -0
  315. package/templates/native/ios/Canary/Colors.xcassets/BootSplashBackground-498e55.colorset/Contents.json +20 -0
  316. package/templates/native/ios/Canary/Images.xcassets/AppIcon.appiconset/Contents.json +53 -0
  317. package/templates/native/ios/Canary/Images.xcassets/BootSplashLogo-498e55.imageset/Contents.json +23 -0
  318. package/templates/native/ios/Canary/Images.xcassets/BootSplashLogo-498e55.imageset/logo-498e55.png +0 -0
  319. package/templates/native/ios/Canary/Images.xcassets/BootSplashLogo-498e55.imageset/logo-498e55@2x.png +0 -0
  320. package/templates/native/ios/Canary/Images.xcassets/BootSplashLogo-498e55.imageset/logo-498e55@3x.png +0 -0
  321. package/templates/native/ios/Canary/Images.xcassets/Contents.json +6 -0
  322. package/templates/native/ios/Canary/Info.plist +60 -0
  323. package/templates/native/ios/Canary/LaunchScreen.storyboard +47 -0
  324. package/templates/native/ios/Canary/PrivacyInfo.xcprivacy +37 -0
  325. package/templates/native/ios/Canary.xcodeproj/project.pbxproj +504 -0
  326. package/templates/native/ios/Canary.xcodeproj/xcshareddata/xcschemes/Canary.xcscheme +88 -0
  327. package/templates/native/ios/Canary.xcworkspace/contents.xcworkspacedata +10 -0
  328. package/templates/native/ios/Podfile +34 -0
  329. package/templates/native/package.json.fragment.json +22 -0
  330. package/templates/native/package.json.fragment.typescript.json +8 -0
  331. package/templates/styling/js/angular/css-modules/src/App.ts +25 -0
  332. package/templates/styling/js/angular/stylesheet/src/App.ts +26 -0
  333. package/templates/styling/js/react/css-modules/App.jsx +15 -0
  334. package/templates/styling/js/react/css-modules/App.tsx +15 -0
  335. package/templates/styling/js/react/stylesheet/App.jsx +19 -0
  336. package/templates/styling/js/react/stylesheet/App.tsx +19 -0
  337. package/templates/styling/js/solid/css-modules/App.jsx +15 -0
  338. package/templates/styling/js/solid/css-modules/App.tsx +15 -0
  339. package/templates/styling/js/solid/stylesheet/App.jsx +19 -0
  340. package/templates/styling/js/solid/stylesheet/App.tsx +19 -0
  341. package/templates/styling/js/svelte/css-modules/App.svelte +12 -0
  342. package/templates/styling/js/svelte/css-modules/App.typescript.svelte +12 -0
  343. package/templates/styling/js/svelte/stylesheet/App.svelte +15 -0
  344. package/templates/styling/js/svelte/stylesheet/App.typescript.svelte +15 -0
  345. package/templates/styling/js/vue-sfc/css-modules/App.typescript.vue +15 -0
  346. package/templates/styling/js/vue-sfc/css-modules/App.vue +15 -0
  347. package/templates/styling/js/vue-sfc/stylesheet/App.typescript.vue +18 -0
  348. package/templates/styling/js/vue-sfc/stylesheet/App.vue +18 -0
  349. package/templates/styling/js/vue-tsx/css-modules/App.jsx +16 -0
  350. package/templates/styling/js/vue-tsx/css-modules/App.tsx +16 -0
  351. package/templates/styling/js/vue-tsx/stylesheet/App.jsx +20 -0
  352. package/templates/styling/js/vue-tsx/stylesheet/App.tsx +20 -0
  353. package/templates/styling/navigation/angular/css-modules/src/DetailsScreen.ts +17 -0
  354. package/templates/styling/navigation/angular/css-modules/src/MenuScreen.ts +22 -0
  355. package/templates/styling/navigation/angular/stylesheet/src/DetailsScreen.ts +18 -0
  356. package/templates/styling/navigation/angular/stylesheet/src/MenuScreen.ts +23 -0
  357. package/templates/styling/navigation/react/css-modules/App.jsx +32 -0
  358. package/templates/styling/navigation/react/css-modules/App.tsx +32 -0
  359. package/templates/styling/navigation/react/stylesheet/App.jsx +36 -0
  360. package/templates/styling/navigation/react/stylesheet/App.tsx +36 -0
  361. package/templates/styling/navigation/solid/css-modules/App.jsx +32 -0
  362. package/templates/styling/navigation/solid/css-modules/App.tsx +32 -0
  363. package/templates/styling/navigation/solid/stylesheet/App.jsx +36 -0
  364. package/templates/styling/navigation/solid/stylesheet/App.tsx +36 -0
  365. package/templates/styling/navigation/svelte/css-modules/DetailsScreen.svelte +7 -0
  366. package/templates/styling/navigation/svelte/css-modules/DetailsScreen.typescript.svelte +7 -0
  367. package/templates/styling/navigation/svelte/css-modules/MenuScreen.svelte +13 -0
  368. package/templates/styling/navigation/svelte/css-modules/MenuScreen.typescript.svelte +13 -0
  369. package/templates/styling/navigation/svelte/stylesheet/DetailsScreen.svelte +11 -0
  370. package/templates/styling/navigation/svelte/stylesheet/DetailsScreen.typescript.svelte +11 -0
  371. package/templates/styling/navigation/svelte/stylesheet/MenuScreen.svelte +16 -0
  372. package/templates/styling/navigation/svelte/stylesheet/MenuScreen.typescript.svelte +16 -0
  373. package/templates/styling/navigation/vue-sfc/css-modules/DetailsScreen.typescript.vue +9 -0
  374. package/templates/styling/navigation/vue-sfc/css-modules/DetailsScreen.vue +9 -0
  375. package/templates/styling/navigation/vue-sfc/css-modules/MenuScreen.typescript.vue +15 -0
  376. package/templates/styling/navigation/vue-sfc/css-modules/MenuScreen.vue +15 -0
  377. package/templates/styling/navigation/vue-sfc/stylesheet/DetailsScreen.typescript.vue +13 -0
  378. package/templates/styling/navigation/vue-sfc/stylesheet/DetailsScreen.vue +13 -0
  379. package/templates/styling/navigation/vue-sfc/stylesheet/MenuScreen.typescript.vue +18 -0
  380. package/templates/styling/navigation/vue-sfc/stylesheet/MenuScreen.vue +18 -0
  381. package/templates/styling/navigation/vue-tsx/css-modules/App.jsx +34 -0
  382. package/templates/styling/navigation/vue-tsx/css-modules/App.tsx +34 -0
  383. package/templates/styling/navigation/vue-tsx/stylesheet/App.jsx +38 -0
  384. package/templates/styling/navigation/vue-tsx/stylesheet/App.tsx +38 -0
package/bundle.js ADDED
@@ -0,0 +1,2833 @@
1
+ #!/usr/bin/env node
2
+ import { styleText } from "node:util";
3
+ import process$1, { stdin, stdout } from "node:process";
4
+ import l__default from "node:readline";
5
+ import * as fs from "node:fs";
6
+ import { readFileSync } from "node:fs";
7
+ import * as path from "node:path";
8
+ import { join } from "node:path";
9
+ import { fileURLToPath } from "node:url";
10
+ //#region \0rolldown/runtime.js
11
+ var __create = Object.create;
12
+ var __defProp = Object.defineProperty;
13
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
14
+ var __getOwnPropNames = Object.getOwnPropertyNames;
15
+ var __getProtoOf = Object.getPrototypeOf;
16
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
17
+ var __commonJSMin = (cb, mod) => () => (mod || (cb((mod = { exports: {} }).exports, mod), cb = null), mod.exports);
18
+ var __copyProps = (to, from, except, desc) => {
19
+ if (from && typeof from === "object" || typeof from === "function") for (var keys = __getOwnPropNames(from), i = 0, n = keys.length, key; i < n; i++) {
20
+ key = keys[i];
21
+ if (!__hasOwnProp.call(to, key) && key !== except) __defProp(to, key, {
22
+ get: ((k) => from[k]).bind(null, key),
23
+ enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable
24
+ });
25
+ }
26
+ return to;
27
+ };
28
+ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", {
29
+ value: mod,
30
+ enumerable: true
31
+ }) : target, mod));
32
+ //#endregion
33
+ //#region src/errors.ts
34
+ var import_picocolors = /* @__PURE__ */ __toESM((/* @__PURE__ */ __commonJSMin(((exports, module) => {
35
+ let p = process || {};
36
+ let argv = p.argv || [];
37
+ let env = p.env || {};
38
+ let isColorSupported = !(!!env.NO_COLOR || argv.includes("--no-color")) && (!!env.FORCE_COLOR || argv.includes("--color") || p.platform === "win32" || (p.stdout || {}).isTTY && env.TERM !== "dumb" || !!env.CI);
39
+ let formatter = (open, close, replace = open) => (input) => {
40
+ let string = "" + input, index = string.indexOf(close, open.length);
41
+ return ~index ? open + replaceClose(string, close, replace, index) + close : open + string + close;
42
+ };
43
+ let replaceClose = (string, close, replace, index) => {
44
+ let result = "", cursor = 0;
45
+ do {
46
+ result += string.substring(cursor, index) + replace;
47
+ cursor = index + close.length;
48
+ index = string.indexOf(close, cursor);
49
+ } while (~index);
50
+ return result + string.substring(cursor);
51
+ };
52
+ let createColors = (enabled = isColorSupported) => {
53
+ let f = enabled ? formatter : () => String;
54
+ return {
55
+ isColorSupported: enabled,
56
+ reset: f("\x1B[0m", "\x1B[0m"),
57
+ bold: f("\x1B[1m", "\x1B[22m", "\x1B[22m\x1B[1m"),
58
+ dim: f("\x1B[2m", "\x1B[22m", "\x1B[22m\x1B[2m"),
59
+ italic: f("\x1B[3m", "\x1B[23m"),
60
+ underline: f("\x1B[4m", "\x1B[24m"),
61
+ inverse: f("\x1B[7m", "\x1B[27m"),
62
+ hidden: f("\x1B[8m", "\x1B[28m"),
63
+ strikethrough: f("\x1B[9m", "\x1B[29m"),
64
+ black: f("\x1B[30m", "\x1B[39m"),
65
+ red: f("\x1B[31m", "\x1B[39m"),
66
+ green: f("\x1B[32m", "\x1B[39m"),
67
+ yellow: f("\x1B[33m", "\x1B[39m"),
68
+ blue: f("\x1B[34m", "\x1B[39m"),
69
+ magenta: f("\x1B[35m", "\x1B[39m"),
70
+ cyan: f("\x1B[36m", "\x1B[39m"),
71
+ white: f("\x1B[37m", "\x1B[39m"),
72
+ gray: f("\x1B[90m", "\x1B[39m"),
73
+ bgBlack: f("\x1B[40m", "\x1B[49m"),
74
+ bgRed: f("\x1B[41m", "\x1B[49m"),
75
+ bgGreen: f("\x1B[42m", "\x1B[49m"),
76
+ bgYellow: f("\x1B[43m", "\x1B[49m"),
77
+ bgBlue: f("\x1B[44m", "\x1B[49m"),
78
+ bgMagenta: f("\x1B[45m", "\x1B[49m"),
79
+ bgCyan: f("\x1B[46m", "\x1B[49m"),
80
+ bgWhite: f("\x1B[47m", "\x1B[49m"),
81
+ blackBright: f("\x1B[90m", "\x1B[39m"),
82
+ redBright: f("\x1B[91m", "\x1B[39m"),
83
+ greenBright: f("\x1B[92m", "\x1B[39m"),
84
+ yellowBright: f("\x1B[93m", "\x1B[39m"),
85
+ blueBright: f("\x1B[94m", "\x1B[39m"),
86
+ magentaBright: f("\x1B[95m", "\x1B[39m"),
87
+ cyanBright: f("\x1B[96m", "\x1B[39m"),
88
+ whiteBright: f("\x1B[97m", "\x1B[39m"),
89
+ bgBlackBright: f("\x1B[100m", "\x1B[49m"),
90
+ bgRedBright: f("\x1B[101m", "\x1B[49m"),
91
+ bgGreenBright: f("\x1B[102m", "\x1B[49m"),
92
+ bgYellowBright: f("\x1B[103m", "\x1B[49m"),
93
+ bgBlueBright: f("\x1B[104m", "\x1B[49m"),
94
+ bgMagentaBright: f("\x1B[105m", "\x1B[49m"),
95
+ bgCyanBright: f("\x1B[106m", "\x1B[49m"),
96
+ bgWhiteBright: f("\x1B[107m", "\x1B[49m")
97
+ };
98
+ };
99
+ module.exports = createColors();
100
+ module.exports.createColors = createColors;
101
+ })))(), 1);
102
+ var CliUsageError = class extends Error {
103
+ constructor(message) {
104
+ super(message);
105
+ this.name = "CliUsageError";
106
+ }
107
+ };
108
+ var NotSymbioteAppError = class extends Error {
109
+ constructor() {
110
+ super("No @symbiote-native/<adapter> dependency found in this project's package.json — \"add\" only works inside an existing @symbiote-native/* app. Run \"@symbiote-native/cli new\" to scaffold one.");
111
+ this.name = "NotSymbioteAppError";
112
+ }
113
+ };
114
+ //#endregion
115
+ //#region src/expo-package-layers.ts
116
+ const EXPO_PACKAGE_LAYERS = [
117
+ {
118
+ id: "application",
119
+ label: "Application info",
120
+ symbiotePackage: "@symbiote-native/application"
121
+ },
122
+ {
123
+ id: "battery",
124
+ label: "Battery",
125
+ symbiotePackage: "@symbiote-native/battery"
126
+ },
127
+ {
128
+ id: "brightness",
129
+ label: "Brightness",
130
+ symbiotePackage: "@symbiote-native/brightness"
131
+ },
132
+ {
133
+ id: "cellular",
134
+ label: "Cellular info",
135
+ symbiotePackage: "@symbiote-native/cellular"
136
+ },
137
+ {
138
+ id: "clipboard",
139
+ label: "Clipboard",
140
+ symbiotePackage: "@symbiote-native/clipboard"
141
+ },
142
+ {
143
+ id: "crypto",
144
+ label: "Crypto",
145
+ symbiotePackage: "@symbiote-native/crypto"
146
+ },
147
+ {
148
+ id: "device",
149
+ label: "Device info",
150
+ symbiotePackage: "@symbiote-native/device"
151
+ },
152
+ {
153
+ id: "haptics",
154
+ label: "Haptics",
155
+ symbiotePackage: "@symbiote-native/haptics"
156
+ },
157
+ {
158
+ id: "keep-awake",
159
+ label: "Keep awake",
160
+ symbiotePackage: "@symbiote-native/keep-awake"
161
+ },
162
+ {
163
+ id: "local-auth",
164
+ label: "Local authentication",
165
+ symbiotePackage: "@symbiote-native/local-auth"
166
+ },
167
+ {
168
+ id: "localization",
169
+ label: "Localization",
170
+ symbiotePackage: "@symbiote-native/localization"
171
+ },
172
+ {
173
+ id: "network",
174
+ label: "Network info",
175
+ symbiotePackage: "@symbiote-native/network"
176
+ },
177
+ {
178
+ id: "screen-orientation",
179
+ label: "Screen orientation",
180
+ symbiotePackage: "@symbiote-native/screen-orientation"
181
+ },
182
+ {
183
+ id: "secure-store",
184
+ label: "Secure store",
185
+ symbiotePackage: "@symbiote-native/secure-store"
186
+ },
187
+ {
188
+ id: "sensors",
189
+ label: "Sensors",
190
+ symbiotePackage: "@symbiote-native/sensors"
191
+ },
192
+ {
193
+ id: "sharing",
194
+ label: "Sharing",
195
+ symbiotePackage: "@symbiote-native/sharing"
196
+ },
197
+ {
198
+ id: "sms",
199
+ label: "SMS",
200
+ symbiotePackage: "@symbiote-native/sms"
201
+ },
202
+ {
203
+ id: "standard-web-crypto",
204
+ label: "Web Crypto polyfill",
205
+ symbiotePackage: "@symbiote-native/standard-web-crypto"
206
+ },
207
+ {
208
+ id: "store-review",
209
+ label: "Store review prompt",
210
+ symbiotePackage: "@symbiote-native/store-review"
211
+ },
212
+ {
213
+ id: "system-ui",
214
+ label: "System UI",
215
+ symbiotePackage: "@symbiote-native/system-ui"
216
+ },
217
+ {
218
+ id: "tracking-transparency",
219
+ label: "Tracking transparency",
220
+ symbiotePackage: "@symbiote-native/tracking-transparency"
221
+ },
222
+ {
223
+ id: "web-browser",
224
+ label: "Web browser",
225
+ symbiotePackage: "@symbiote-native/web-browser"
226
+ }
227
+ ];
228
+ const EXPO_PACKAGE_LAYER_IDS = new Set(EXPO_PACKAGE_LAYERS.map((layer) => layer.id));
229
+ function isExpoPackageLayerName(value) {
230
+ return EXPO_PACKAGE_LAYER_IDS.has(value);
231
+ }
232
+ //#endregion
233
+ //#region src/utils/suggest.ts
234
+ function editDistance(a, b) {
235
+ const rows = a.length + 1;
236
+ const cols = b.length + 1;
237
+ const distances = Array.from({ length: rows }, () => new Array(cols).fill(0));
238
+ for (let row = 0; row < rows; row += 1) distances[row][0] = row;
239
+ for (let col = 0; col < cols; col += 1) distances[0][col] = col;
240
+ for (let row = 1; row < rows; row += 1) for (let col = 1; col < cols; col += 1) {
241
+ const cost = a[row - 1] === b[col - 1] ? 0 : 1;
242
+ let best = Math.min(distances[row - 1][col] + 1, distances[row][col - 1] + 1, distances[row - 1][col - 1] + cost);
243
+ if (row > 1 && col > 1 && a[row - 1] === b[col - 2] && a[row - 2] === b[col - 1]) best = Math.min(best, distances[row - 2][col - 2] + 1);
244
+ distances[row][col] = best;
245
+ }
246
+ return distances[rows - 1][cols - 1];
247
+ }
248
+ function findClosestMatch(input, candidates) {
249
+ let closest;
250
+ let closestDistance = Infinity;
251
+ for (const candidate of candidates) {
252
+ const distance = editDistance(input, candidate);
253
+ if (distance < closestDistance) {
254
+ closestDistance = distance;
255
+ closest = candidate;
256
+ }
257
+ }
258
+ if (closest === void 0) return void 0;
259
+ const threshold = Math.max(1, Math.floor(Math.max(input.length, closest.length) / 2));
260
+ return closestDistance <= threshold ? closest : void 0;
261
+ }
262
+ //#endregion
263
+ //#region src/cli.ts
264
+ const FRAMEWORKS = /* @__PURE__ */ new Set([
265
+ "react",
266
+ "vue",
267
+ "angular",
268
+ "solid",
269
+ "svelte"
270
+ ]);
271
+ const VUE_FLAVORS = /* @__PURE__ */ new Set(["tsx", "sfc"]);
272
+ const PACKAGE_MANAGERS = /* @__PURE__ */ new Set([
273
+ "npm",
274
+ "pnpm",
275
+ "yarn"
276
+ ]);
277
+ const STYLING_OPTIONS = /* @__PURE__ */ new Set([
278
+ "css",
279
+ "scss",
280
+ "less",
281
+ "stylus",
282
+ "css-modules",
283
+ "stylesheet"
284
+ ]);
285
+ const KNOWN_FLAGS = [
286
+ "--javascript",
287
+ "--force",
288
+ "--expo-modules",
289
+ "--navigation",
290
+ "--testing",
291
+ "--splash-screen",
292
+ "--slider",
293
+ "--framework",
294
+ "--bundle-id",
295
+ "--styling",
296
+ "--vue-flavor",
297
+ "--pm",
298
+ ...EXPO_PACKAGE_LAYERS.map((layer) => `--${layer.id}`)
299
+ ];
300
+ function isFramework(value) {
301
+ return FRAMEWORKS.has(value);
302
+ }
303
+ function isVueFlavor(value) {
304
+ return VUE_FLAVORS.has(value);
305
+ }
306
+ function isPackageManager(value) {
307
+ return PACKAGE_MANAGERS.has(value);
308
+ }
309
+ function isStylingOption(value) {
310
+ return STYLING_OPTIONS.has(value);
311
+ }
312
+ function splitInlineFlag(token) {
313
+ const eqIndex = token.startsWith("--") ? token.indexOf("=") : -1;
314
+ if (eqIndex === -1) return {
315
+ name: token,
316
+ inlineValue: void 0
317
+ };
318
+ return {
319
+ name: token.slice(0, eqIndex),
320
+ inlineValue: token.slice(eqIndex + 1)
321
+ };
322
+ }
323
+ function assertNoInlineValue(flagName, inlineValue) {
324
+ if (inlineValue !== void 0) throw new CliUsageError(`"${flagName}" doesn't take a value — just "${flagName}".`);
325
+ }
326
+ function usageErrorFor(kind, input, candidates) {
327
+ const suggestion = findClosestMatch(input, candidates);
328
+ return new CliUsageError(`Unknown ${kind === "command" ? "command" : "flag"} "${input}"${suggestion ? ` — did you mean "${suggestion}"?` : "."} Run "@symbiote-native/cli --help" for usage.`);
329
+ }
330
+ function requireEnumValue(flag, rawValue, isValid, validValues) {
331
+ if (rawValue === void 0 || rawValue.startsWith("--")) throw new CliUsageError(`"${flag}" needs a value. Valid values: ${validValues.join(", ")}.`);
332
+ if (!isValid(rawValue)) throw new CliUsageError(`"${flag} ${rawValue}" is invalid. Valid values: ${validValues.join(", ")}.`);
333
+ return rawValue;
334
+ }
335
+ function parseArgv(argv) {
336
+ const [command, ...rest] = argv;
337
+ if (command === void 0 || command === "--help" || command === "-h") return { kind: "help" };
338
+ if (command === "--version" || command === "-v") return { kind: "version" };
339
+ if (command !== "new" && command !== "add") throw usageErrorFor("command", command, ["new", "add"]);
340
+ let appName;
341
+ let framework;
342
+ let vueFlavor;
343
+ let isJavascript = false;
344
+ let hasForce = false;
345
+ let bundleId;
346
+ let hasExpoModules = false;
347
+ let hasNavigation = false;
348
+ let hasTesting = false;
349
+ let hasSplashScreen = false;
350
+ let hasSlider = false;
351
+ const expoPackages = /* @__PURE__ */ new Set();
352
+ let styling;
353
+ let packageManager;
354
+ for (let index = 0; index < rest.length; index += 1) {
355
+ const { name: token, inlineValue } = splitInlineFlag(rest[index]);
356
+ if (token === "--javascript") {
357
+ assertNoInlineValue(token, inlineValue);
358
+ isJavascript = true;
359
+ continue;
360
+ }
361
+ if (token === "--force") {
362
+ assertNoInlineValue(token, inlineValue);
363
+ hasForce = true;
364
+ continue;
365
+ }
366
+ if (token === "--expo-modules") {
367
+ assertNoInlineValue(token, inlineValue);
368
+ hasExpoModules = true;
369
+ continue;
370
+ }
371
+ if (token === "--navigation") {
372
+ assertNoInlineValue(token, inlineValue);
373
+ hasNavigation = true;
374
+ continue;
375
+ }
376
+ if (token === "--testing") {
377
+ assertNoInlineValue(token, inlineValue);
378
+ hasTesting = true;
379
+ continue;
380
+ }
381
+ if (token === "--splash-screen") {
382
+ assertNoInlineValue(token, inlineValue);
383
+ hasSplashScreen = true;
384
+ continue;
385
+ }
386
+ if (token === "--slider") {
387
+ assertNoInlineValue(token, inlineValue);
388
+ hasSlider = true;
389
+ continue;
390
+ }
391
+ const expoPackageId = token.startsWith("--") ? token.slice(2) : "";
392
+ if (isExpoPackageLayerName(expoPackageId)) {
393
+ assertNoInlineValue(token, inlineValue);
394
+ expoPackages.add(expoPackageId);
395
+ continue;
396
+ }
397
+ if (token === "--framework") {
398
+ framework = requireEnumValue(token, inlineValue ?? rest[index + 1], isFramework, [...FRAMEWORKS]);
399
+ if (inlineValue === void 0) index += 1;
400
+ continue;
401
+ }
402
+ if (token === "--bundle-id") {
403
+ const value = inlineValue ?? rest[index + 1];
404
+ if (value === void 0 || value.startsWith("--")) throw new CliUsageError(`"${token}" needs a value, e.g. "com.example.app".`);
405
+ bundleId = value;
406
+ if (inlineValue === void 0) index += 1;
407
+ continue;
408
+ }
409
+ if (token === "--styling") {
410
+ styling = requireEnumValue(token, inlineValue ?? rest[index + 1], isStylingOption, [...STYLING_OPTIONS]);
411
+ if (inlineValue === void 0) index += 1;
412
+ continue;
413
+ }
414
+ if (token === "--vue-flavor") {
415
+ vueFlavor = requireEnumValue(token, inlineValue ?? rest[index + 1], isVueFlavor, [...VUE_FLAVORS]);
416
+ if (inlineValue === void 0) index += 1;
417
+ continue;
418
+ }
419
+ if (token === "--pm") {
420
+ packageManager = requireEnumValue(token, inlineValue ?? rest[index + 1], isPackageManager, [...PACKAGE_MANAGERS]);
421
+ if (inlineValue === void 0) index += 1;
422
+ continue;
423
+ }
424
+ if (token.startsWith("--")) throw usageErrorFor("flag", token, KNOWN_FLAGS);
425
+ if (command === "add") throw new CliUsageError(`"add" doesn't take a positional argument — got "${token}".`);
426
+ if (appName === void 0) {
427
+ appName = token;
428
+ continue;
429
+ }
430
+ throw new CliUsageError(`Unexpected argument "${token}" — "new" takes one app name.`);
431
+ }
432
+ if (command === "new") return {
433
+ kind: "new",
434
+ appName,
435
+ framework,
436
+ vueFlavor,
437
+ isJavascript,
438
+ hasForce,
439
+ bundleId,
440
+ hasExpoModules,
441
+ hasNavigation,
442
+ hasTesting,
443
+ hasSplashScreen,
444
+ hasSlider,
445
+ expoPackages,
446
+ styling,
447
+ packageManager
448
+ };
449
+ return {
450
+ kind: "add",
451
+ framework,
452
+ vueFlavor,
453
+ hasExpoModules,
454
+ hasNavigation,
455
+ hasTesting,
456
+ hasSplashScreen,
457
+ hasSlider,
458
+ expoPackages,
459
+ hasForce,
460
+ packageManager
461
+ };
462
+ }
463
+ //#endregion
464
+ //#region ../../node_modules/.pnpm/fast-string-truncated-width@3.0.3/node_modules/fast-string-truncated-width/dist/utils.js
465
+ const getCodePointsLength = (() => {
466
+ const SURROGATE_PAIR_RE = /[\uD800-\uDBFF][\uDC00-\uDFFF]/g;
467
+ return (input) => {
468
+ let surrogatePairsNr = 0;
469
+ SURROGATE_PAIR_RE.lastIndex = 0;
470
+ while (SURROGATE_PAIR_RE.test(input)) surrogatePairsNr += 1;
471
+ return input.length - surrogatePairsNr;
472
+ };
473
+ })();
474
+ const isFullWidth = (x) => {
475
+ return x === 12288 || x >= 65281 && x <= 65376 || x >= 65504 && x <= 65510;
476
+ };
477
+ const isWideNotCJKTNotEmoji = (x) => {
478
+ return x === 8987 || x === 9001 || x >= 12272 && x <= 12287 || x >= 12289 && x <= 12350 || x >= 12441 && x <= 12543 || x >= 12549 && x <= 12591 || x >= 12593 && x <= 12686 || x >= 12688 && x <= 12771 || x >= 12783 && x <= 12830 || x >= 12832 && x <= 12871 || x >= 12880 && x <= 19903 || x >= 65040 && x <= 65049 || x >= 65072 && x <= 65106 || x >= 65108 && x <= 65126 || x >= 65128 && x <= 65131 || x >= 127488 && x <= 127490 || x >= 127504 && x <= 127547 || x >= 127552 && x <= 127560 || x >= 131072 && x <= 196605 || x >= 196608 && x <= 262141;
479
+ };
480
+ //#endregion
481
+ //#region ../../node_modules/.pnpm/fast-string-truncated-width@3.0.3/node_modules/fast-string-truncated-width/dist/index.js
482
+ const ANSI_RE = /[\u001b\u009b][[()#;?]*(?:[0-9]{1,4}(?:;[0-9]{0,4})*)?[0-9A-ORZcf-nqry=><]|\u001b\]8;[^;]*;.*?(?:\u0007|\u001b\u005c)/y;
483
+ const CONTROL_RE = /[\x00-\x08\x0A-\x1F\x7F-\x9F]{1,1000}/y;
484
+ const CJKT_WIDE_RE = /(?:(?![\uFF61-\uFF9F\uFF00-\uFFEF])[\p{Script=Han}\p{Script=Hiragana}\p{Script=Katakana}\p{Script=Hangul}\p{Script=Tangut}]){1,1000}/uy;
485
+ const TAB_RE = /\t{1,1000}/y;
486
+ const EMOJI_RE = /[\u{1F1E6}-\u{1F1FF}]{2}|\u{1F3F4}[\u{E0061}-\u{E007A}]{2}[\u{E0030}-\u{E0039}\u{E0061}-\u{E007A}]{1,3}\u{E007F}|(?:\p{Emoji}\uFE0F\u20E3?|\p{Emoji_Modifier_Base}\p{Emoji_Modifier}?|\p{Emoji_Presentation})(?:\u200D(?:\p{Emoji_Modifier_Base}\p{Emoji_Modifier}?|\p{Emoji_Presentation}|\p{Emoji}\uFE0F\u20E3?))*/uy;
487
+ const LATIN_RE = /(?:[\x20-\x7E\xA0-\xFF](?!\uFE0F)){1,1000}/y;
488
+ const MODIFIER_RE = /\p{M}+/gu;
489
+ const NO_TRUNCATION$1 = {
490
+ limit: Infinity,
491
+ ellipsis: ""
492
+ };
493
+ const getStringTruncatedWidth = (input, truncationOptions = {}, widthOptions = {}) => {
494
+ const LIMIT = truncationOptions.limit ?? Infinity;
495
+ const ELLIPSIS = truncationOptions.ellipsis ?? "";
496
+ const ELLIPSIS_WIDTH = truncationOptions?.ellipsisWidth ?? (ELLIPSIS ? getStringTruncatedWidth(ELLIPSIS, NO_TRUNCATION$1, widthOptions).width : 0);
497
+ const ANSI_WIDTH = 0;
498
+ const CONTROL_WIDTH = widthOptions.controlWidth ?? 0;
499
+ const TAB_WIDTH = widthOptions.tabWidth ?? 8;
500
+ const EMOJI_WIDTH = widthOptions.emojiWidth ?? 2;
501
+ const FULL_WIDTH_WIDTH = 2;
502
+ const REGULAR_WIDTH = widthOptions.regularWidth ?? 1;
503
+ const WIDE_WIDTH = widthOptions.wideWidth ?? FULL_WIDTH_WIDTH;
504
+ const PARSE_BLOCKS = [
505
+ [LATIN_RE, REGULAR_WIDTH],
506
+ [ANSI_RE, ANSI_WIDTH],
507
+ [CONTROL_RE, CONTROL_WIDTH],
508
+ [TAB_RE, TAB_WIDTH],
509
+ [EMOJI_RE, EMOJI_WIDTH],
510
+ [CJKT_WIDE_RE, WIDE_WIDTH]
511
+ ];
512
+ let indexPrev = 0;
513
+ let index = 0;
514
+ let length = input.length;
515
+ let lengthExtra = 0;
516
+ let truncationEnabled = false;
517
+ let truncationIndex = length;
518
+ let truncationLimit = Math.max(0, LIMIT - ELLIPSIS_WIDTH);
519
+ let unmatchedStart = 0;
520
+ let unmatchedEnd = 0;
521
+ let width = 0;
522
+ let widthExtra = 0;
523
+ outer: while (true) {
524
+ if (unmatchedEnd > unmatchedStart || index >= length && index > indexPrev) {
525
+ const unmatched = input.slice(unmatchedStart, unmatchedEnd) || input.slice(indexPrev, index);
526
+ lengthExtra = 0;
527
+ for (const char of unmatched.replaceAll(MODIFIER_RE, "")) {
528
+ const codePoint = char.codePointAt(0) || 0;
529
+ if (isFullWidth(codePoint)) widthExtra = FULL_WIDTH_WIDTH;
530
+ else if (isWideNotCJKTNotEmoji(codePoint)) widthExtra = WIDE_WIDTH;
531
+ else widthExtra = REGULAR_WIDTH;
532
+ if (width + widthExtra > truncationLimit) truncationIndex = Math.min(truncationIndex, Math.max(unmatchedStart, indexPrev) + lengthExtra);
533
+ if (width + widthExtra > LIMIT) {
534
+ truncationEnabled = true;
535
+ break outer;
536
+ }
537
+ lengthExtra += char.length;
538
+ width += widthExtra;
539
+ }
540
+ unmatchedStart = unmatchedEnd = 0;
541
+ }
542
+ if (index >= length) break outer;
543
+ for (let i = 0, l = PARSE_BLOCKS.length; i < l; i++) {
544
+ const [BLOCK_RE, BLOCK_WIDTH] = PARSE_BLOCKS[i];
545
+ BLOCK_RE.lastIndex = index;
546
+ if (BLOCK_RE.test(input)) {
547
+ lengthExtra = BLOCK_RE === CJKT_WIDE_RE ? getCodePointsLength(input.slice(index, BLOCK_RE.lastIndex)) : BLOCK_RE === EMOJI_RE ? 1 : BLOCK_RE.lastIndex - index;
548
+ widthExtra = lengthExtra * BLOCK_WIDTH;
549
+ if (width + widthExtra > truncationLimit) truncationIndex = Math.min(truncationIndex, index + Math.floor((truncationLimit - width) / BLOCK_WIDTH));
550
+ if (width + widthExtra > LIMIT) {
551
+ truncationEnabled = true;
552
+ break outer;
553
+ }
554
+ width += widthExtra;
555
+ unmatchedStart = indexPrev;
556
+ unmatchedEnd = index;
557
+ index = indexPrev = BLOCK_RE.lastIndex;
558
+ continue outer;
559
+ }
560
+ }
561
+ index += 1;
562
+ }
563
+ return {
564
+ width: truncationEnabled ? truncationLimit : width,
565
+ index: truncationEnabled ? truncationIndex : length,
566
+ truncated: truncationEnabled,
567
+ ellipsed: truncationEnabled && LIMIT >= ELLIPSIS_WIDTH
568
+ };
569
+ };
570
+ //#endregion
571
+ //#region ../../node_modules/.pnpm/fast-string-width@3.0.2/node_modules/fast-string-width/dist/index.js
572
+ const NO_TRUNCATION = {
573
+ limit: Infinity,
574
+ ellipsis: "",
575
+ ellipsisWidth: 0
576
+ };
577
+ const fastStringWidth = (input, options = {}) => {
578
+ return getStringTruncatedWidth(input, NO_TRUNCATION, options).width;
579
+ };
580
+ //#endregion
581
+ //#region ../../node_modules/.pnpm/fast-wrap-ansi@0.2.2/node_modules/fast-wrap-ansi/lib/main.js
582
+ const ESC = "\x1B";
583
+ const CSI = "›";
584
+ const END_CODE = 39;
585
+ const ANSI_ESCAPE_BELL = "\x07";
586
+ const ANSI_CSI = "[";
587
+ const ANSI_OSC = "]";
588
+ const ANSI_SGR_TERMINATOR = "m";
589
+ const ANSI_ESCAPE_LINK = `${ANSI_OSC}8;;`;
590
+ const GROUP_REGEX = new RegExp(`(?:\\${ANSI_CSI}(?<code>\\d+)m|\\${ANSI_ESCAPE_LINK}(?<uri>.*)${ANSI_ESCAPE_BELL})`, "y");
591
+ const getClosingCode = (openingCode) => {
592
+ if (openingCode >= 30 && openingCode <= 37) return 39;
593
+ if (openingCode >= 90 && openingCode <= 97) return 39;
594
+ if (openingCode >= 40 && openingCode <= 47) return 49;
595
+ if (openingCode >= 100 && openingCode <= 107) return 49;
596
+ if (openingCode === 1 || openingCode === 2) return 22;
597
+ if (openingCode === 3) return 23;
598
+ if (openingCode === 4) return 24;
599
+ if (openingCode === 7) return 27;
600
+ if (openingCode === 8) return 28;
601
+ if (openingCode === 9) return 29;
602
+ if (openingCode === 0) return 0;
603
+ };
604
+ const wrapAnsiCode = (code) => `${ESC}${ANSI_CSI}${code}${ANSI_SGR_TERMINATOR}`;
605
+ const wrapAnsiHyperlink = (url) => `${ESC}${ANSI_ESCAPE_LINK}${url}${ANSI_ESCAPE_BELL}`;
606
+ const wrapWord = (rows, word, columns) => {
607
+ const characters = word[Symbol.iterator]();
608
+ let isInsideEscape = false;
609
+ let isInsideLinkEscape = false;
610
+ let lastRow = rows.at(-1);
611
+ let visible = lastRow === void 0 ? 0 : fastStringWidth(lastRow);
612
+ let currentCharacter = characters.next();
613
+ let nextCharacter = characters.next();
614
+ let rawCharacterIndex = 0;
615
+ while (!currentCharacter.done) {
616
+ const character = currentCharacter.value;
617
+ const characterLength = fastStringWidth(character);
618
+ if (visible + characterLength <= columns) rows[rows.length - 1] += character;
619
+ else {
620
+ rows.push(character);
621
+ visible = 0;
622
+ }
623
+ if (character === ESC || character === CSI) {
624
+ isInsideEscape = true;
625
+ isInsideLinkEscape = word.startsWith(ANSI_ESCAPE_LINK, rawCharacterIndex + 1);
626
+ }
627
+ if (isInsideEscape) {
628
+ if (isInsideLinkEscape) {
629
+ if (character === ANSI_ESCAPE_BELL) {
630
+ isInsideEscape = false;
631
+ isInsideLinkEscape = false;
632
+ }
633
+ } else if (character === ANSI_SGR_TERMINATOR) isInsideEscape = false;
634
+ } else {
635
+ visible += characterLength;
636
+ if (visible === columns && !nextCharacter.done) {
637
+ rows.push("");
638
+ visible = 0;
639
+ }
640
+ }
641
+ currentCharacter = nextCharacter;
642
+ nextCharacter = characters.next();
643
+ rawCharacterIndex += character.length;
644
+ }
645
+ lastRow = rows.at(-1);
646
+ if (!visible && lastRow !== void 0 && lastRow.length && rows.length > 1) rows[rows.length - 2] += rows.pop();
647
+ };
648
+ const stringVisibleTrimSpacesRight = (string) => {
649
+ const words = string.split(" ");
650
+ let last = words.length;
651
+ while (last) {
652
+ if (fastStringWidth(words[last - 1])) break;
653
+ last--;
654
+ }
655
+ if (last === words.length) return string;
656
+ return words.slice(0, last).join(" ") + words.slice(last).join("");
657
+ };
658
+ const exec = (string, columns, options = {}) => {
659
+ if (options.trim !== false && string.trim() === "") return "";
660
+ let returnValue = "";
661
+ let escapeCode;
662
+ let escapeUrl;
663
+ const words = string.split(" ");
664
+ let rows = [""];
665
+ let rowLength = 0;
666
+ for (let index = 0; index < words.length; index++) {
667
+ const word = words[index];
668
+ if (options.trim !== false) {
669
+ const row = rows.at(-1) ?? "";
670
+ const trimmed = row.trimStart();
671
+ if (row.length !== trimmed.length) {
672
+ rows[rows.length - 1] = trimmed;
673
+ rowLength = fastStringWidth(trimmed);
674
+ }
675
+ }
676
+ if (index !== 0) {
677
+ if (rowLength >= columns && (options.wordWrap === false || options.trim === false)) {
678
+ rows.push("");
679
+ rowLength = 0;
680
+ }
681
+ if (rowLength || options.trim === false) {
682
+ rows[rows.length - 1] += " ";
683
+ rowLength++;
684
+ }
685
+ }
686
+ const wordLength = fastStringWidth(word);
687
+ if (options.hard && wordLength > columns) {
688
+ const remainingColumns = columns - rowLength;
689
+ const breaksStartingThisLine = 1 + Math.floor((wordLength - remainingColumns - 1) / columns);
690
+ if (Math.floor((wordLength - 1) / columns) < breaksStartingThisLine) rows.push("");
691
+ wrapWord(rows, word, columns);
692
+ rowLength = fastStringWidth(rows.at(-1) ?? "");
693
+ continue;
694
+ }
695
+ if (rowLength + wordLength > columns && rowLength && wordLength) {
696
+ if (options.wordWrap === false && rowLength < columns) {
697
+ wrapWord(rows, word, columns);
698
+ rowLength = fastStringWidth(rows.at(-1) ?? "");
699
+ continue;
700
+ }
701
+ rows.push("");
702
+ rowLength = 0;
703
+ }
704
+ if (rowLength + wordLength > columns && options.wordWrap === false) {
705
+ wrapWord(rows, word, columns);
706
+ rowLength = fastStringWidth(rows.at(-1) ?? "");
707
+ continue;
708
+ }
709
+ rows[rows.length - 1] += word;
710
+ rowLength += wordLength;
711
+ }
712
+ if (options.trim !== false) rows = rows.map((row) => stringVisibleTrimSpacesRight(row));
713
+ const preString = rows.join("\n");
714
+ let inSurrogate = false;
715
+ for (let i = 0; i < preString.length; i++) {
716
+ const character = preString[i];
717
+ returnValue += character;
718
+ if (!inSurrogate) {
719
+ inSurrogate = character >= "\ud800" && character <= "\udbff";
720
+ if (inSurrogate) continue;
721
+ } else inSurrogate = false;
722
+ if (character === ESC || character === CSI) {
723
+ GROUP_REGEX.lastIndex = i + 1;
724
+ const groups = GROUP_REGEX.exec(preString)?.groups;
725
+ if (groups?.code !== void 0) {
726
+ const code = Number.parseFloat(groups.code);
727
+ escapeCode = code === END_CODE ? void 0 : code;
728
+ } else if (groups?.uri !== void 0) escapeUrl = groups.uri.length === 0 ? void 0 : groups.uri;
729
+ }
730
+ if (preString[i + 1] === "\n") {
731
+ if (escapeUrl) returnValue += wrapAnsiHyperlink("");
732
+ const closingCode = escapeCode ? getClosingCode(escapeCode) : void 0;
733
+ if (escapeCode && closingCode) returnValue += wrapAnsiCode(closingCode);
734
+ } else if (character === "\n") {
735
+ if (escapeCode && getClosingCode(escapeCode)) returnValue += wrapAnsiCode(escapeCode);
736
+ if (escapeUrl) returnValue += wrapAnsiHyperlink(escapeUrl);
737
+ }
738
+ }
739
+ return returnValue;
740
+ };
741
+ const CRLF_OR_LF = /\r?\n/;
742
+ function wrapAnsi(string, columns, options) {
743
+ return String(string).normalize().split(CRLF_OR_LF).map((line) => exec(line, columns, options)).join("\n");
744
+ }
745
+ //#endregion
746
+ //#region ../../node_modules/.pnpm/@clack+core@1.4.3/node_modules/@clack/core/dist/index.mjs
747
+ var import_src = (/* @__PURE__ */ __commonJSMin(((exports, module) => {
748
+ const ESC = "\x1B";
749
+ const CSI = `${ESC}[`;
750
+ const beep = "\x07";
751
+ const cursor = {
752
+ to(x, y) {
753
+ if (!y) return `${CSI}${x + 1}G`;
754
+ return `${CSI}${y + 1};${x + 1}H`;
755
+ },
756
+ move(x, y) {
757
+ let ret = "";
758
+ if (x < 0) ret += `${CSI}${-x}D`;
759
+ else if (x > 0) ret += `${CSI}${x}C`;
760
+ if (y < 0) ret += `${CSI}${-y}A`;
761
+ else if (y > 0) ret += `${CSI}${y}B`;
762
+ return ret;
763
+ },
764
+ up: (count = 1) => `${CSI}${count}A`,
765
+ down: (count = 1) => `${CSI}${count}B`,
766
+ forward: (count = 1) => `${CSI}${count}C`,
767
+ backward: (count = 1) => `${CSI}${count}D`,
768
+ nextLine: (count = 1) => `${CSI}E`.repeat(count),
769
+ prevLine: (count = 1) => `${CSI}F`.repeat(count),
770
+ left: `${CSI}G`,
771
+ hide: `${CSI}?25l`,
772
+ show: `${CSI}?25h`,
773
+ save: `${ESC}7`,
774
+ restore: `${ESC}8`
775
+ };
776
+ module.exports = {
777
+ cursor,
778
+ scroll: {
779
+ up: (count = 1) => `${CSI}S`.repeat(count),
780
+ down: (count = 1) => `${CSI}T`.repeat(count)
781
+ },
782
+ erase: {
783
+ screen: `${CSI}2J`,
784
+ up: (count = 1) => `${CSI}1J`.repeat(count),
785
+ down: (count = 1) => `${CSI}J`.repeat(count),
786
+ line: `${CSI}2K`,
787
+ lineEnd: `${CSI}K`,
788
+ lineStart: `${CSI}1K`,
789
+ lines(count) {
790
+ let clear = "";
791
+ for (let i = 0; i < count; i++) clear += this.line + (i < count - 1 ? cursor.up() : "");
792
+ if (count) clear += cursor.left;
793
+ return clear;
794
+ }
795
+ },
796
+ beep
797
+ };
798
+ })))();
799
+ function findCursor(s, o, l) {
800
+ if (!l.some((r) => !r.disabled)) return s;
801
+ const t = s + o, n = Math.max(l.length - 1, 0), e = t < 0 ? n : t > n ? 0 : t;
802
+ return l[e]?.disabled ? findCursor(e, o < 0 ? -1 : 1, l) : e;
803
+ }
804
+ const settings = {
805
+ actions: /* @__PURE__ */ new Set([
806
+ "up",
807
+ "down",
808
+ "left",
809
+ "right",
810
+ "space",
811
+ "enter",
812
+ "cancel"
813
+ ]),
814
+ aliases: /* @__PURE__ */ new Map([
815
+ ["k", "up"],
816
+ ["j", "down"],
817
+ ["h", "left"],
818
+ ["l", "right"],
819
+ ["", "cancel"],
820
+ ["escape", "cancel"]
821
+ ]),
822
+ messages: {
823
+ cancel: "Canceled",
824
+ error: "Something went wrong"
825
+ },
826
+ withGuide: true,
827
+ date: {
828
+ monthNames: [...[
829
+ "January",
830
+ "February",
831
+ "March",
832
+ "April",
833
+ "May",
834
+ "June",
835
+ "July",
836
+ "August",
837
+ "September",
838
+ "October",
839
+ "November",
840
+ "December"
841
+ ]],
842
+ messages: {
843
+ required: "Please enter a valid date",
844
+ invalidMonth: "There are only 12 months in a year",
845
+ invalidDay: (n, e) => `There are only ${n} days in ${e}`,
846
+ afterMin: (n) => `Date must be on or after ${n.toISOString().slice(0, 10)}`,
847
+ beforeMax: (n) => `Date must be on or before ${n.toISOString().slice(0, 10)}`
848
+ }
849
+ }
850
+ };
851
+ function isActionKey(n, e) {
852
+ if (typeof n == "string") return settings.aliases.get(n) === e;
853
+ for (const s of n) if (s !== void 0 && isActionKey(s, e)) return true;
854
+ return false;
855
+ }
856
+ function diffLines(i, s) {
857
+ if (i === s) return;
858
+ const e = i.split(`
859
+ `), t = s.split(`
860
+ `), r = Math.max(e.length, t.length), f = [];
861
+ for (let n = 0; n < r; n++) e[n] !== t[n] && f.push(n);
862
+ return {
863
+ lines: f,
864
+ numLinesBefore: e.length,
865
+ numLinesAfter: t.length,
866
+ numLines: r
867
+ };
868
+ }
869
+ globalThis.process.platform.startsWith("win");
870
+ const CANCEL_SYMBOL = Symbol("clack:cancel");
871
+ function isCancel(e) {
872
+ return e === CANCEL_SYMBOL;
873
+ }
874
+ function setRawMode(e, r) {
875
+ const o = e;
876
+ o.isTTY && o.setRawMode(r);
877
+ }
878
+ const getColumns = (e) => "columns" in e && typeof e.columns == "number" ? e.columns : 80;
879
+ const getRows = (e) => "rows" in e && typeof e.rows == "number" ? e.rows : 20;
880
+ function wrapTextWithPrefix(e, r, o, t = o, s = o, n) {
881
+ return wrapAnsi(r, getColumns(e ?? stdout) - o.length, {
882
+ hard: true,
883
+ trim: false
884
+ }).split(`
885
+ `).map((c, i, m) => {
886
+ const d = n ? n(c, i) : c;
887
+ return i === 0 ? `${t}${d}` : i === m.length - 1 ? `${s}${d}` : `${o}${d}`;
888
+ }).join(`
889
+ `);
890
+ }
891
+ function runValidation(e, n) {
892
+ if ("~standard" in e) {
893
+ const a = e["~standard"].validate(n);
894
+ if (a instanceof Promise) throw new TypeError("Schema validation must be synchronous. Update `validate()` and remove any asynchronous logic.");
895
+ return a.issues?.at(0)?.message;
896
+ }
897
+ return e(n);
898
+ }
899
+ var V = class {
900
+ input;
901
+ output;
902
+ _abortSignal;
903
+ rl;
904
+ opts;
905
+ _render;
906
+ _track = false;
907
+ _prevFrame = "";
908
+ _subscribers = /* @__PURE__ */ new Map();
909
+ _cursor = 0;
910
+ state = "initial";
911
+ error = "";
912
+ value;
913
+ userInput = "";
914
+ constructor(t, e = true) {
915
+ const { input: i = stdin, output: n = stdout, render: s, signal: r, ...o } = t;
916
+ this.opts = o, this.onKeypress = this.onKeypress.bind(this), this.close = this.close.bind(this), this.render = this.render.bind(this), this._render = s.bind(this), this._track = e, this._abortSignal = r, this.input = i, this.output = n;
917
+ }
918
+ /**
919
+ * Unsubscribe all listeners
920
+ */
921
+ unsubscribe() {
922
+ this._subscribers.clear();
923
+ }
924
+ /**
925
+ * Set a subscriber with opts
926
+ * @param event - The event name
927
+ */
928
+ setSubscriber(t, e) {
929
+ const i = this._subscribers.get(t) ?? [];
930
+ i.push(e), this._subscribers.set(t, i);
931
+ }
932
+ /**
933
+ * Subscribe to an event
934
+ * @param event - The event name
935
+ * @param cb - The callback
936
+ */
937
+ on(t, e) {
938
+ this.setSubscriber(t, { cb: e });
939
+ }
940
+ /**
941
+ * Subscribe to an event once
942
+ * @param event - The event name
943
+ * @param cb - The callback
944
+ */
945
+ once(t, e) {
946
+ this.setSubscriber(t, {
947
+ cb: e,
948
+ once: true
949
+ });
950
+ }
951
+ /**
952
+ * Emit an event with data
953
+ * @param event - The event name
954
+ * @param data - The data to pass to the callback
955
+ */
956
+ emit(t, ...e) {
957
+ const i = this._subscribers.get(t) ?? [], n = [];
958
+ for (const s of i) s.cb(...e), s.once && n.push(() => i.splice(i.indexOf(s), 1));
959
+ for (const s of n) s();
960
+ }
961
+ prompt() {
962
+ return new Promise((t) => {
963
+ if (this._abortSignal) {
964
+ if (this._abortSignal.aborted) return this.state = "cancel", this.close(), t(CANCEL_SYMBOL);
965
+ this._abortSignal.addEventListener("abort", () => {
966
+ this.state = "cancel", this.close();
967
+ }, { once: true });
968
+ }
969
+ this.rl = l__default.createInterface({
970
+ input: this.input,
971
+ tabSize: 2,
972
+ prompt: "",
973
+ escapeCodeTimeout: 50,
974
+ terminal: true
975
+ }), this.rl.prompt(), this.opts.initialUserInput !== void 0 && this._setUserInput(this.opts.initialUserInput, true), this.input.on("keypress", this.onKeypress), setRawMode(this.input, true), this.output.on("resize", this.render), this.render(), this.once("submit", () => {
976
+ this.output.write(import_src.cursor.show), this.output.off("resize", this.render), setRawMode(this.input, false), t(this.value);
977
+ }), this.once("cancel", () => {
978
+ this.output.write(import_src.cursor.show), this.output.off("resize", this.render), setRawMode(this.input, false), t(CANCEL_SYMBOL);
979
+ });
980
+ });
981
+ }
982
+ _isActionKey(t, e) {
983
+ return t === " ";
984
+ }
985
+ _shouldSubmit(t, e) {
986
+ return true;
987
+ }
988
+ _setValue(t) {
989
+ this.value = t, this.emit("value", this.value);
990
+ }
991
+ _setUserInput(t, e) {
992
+ this.userInput = t ?? "", this.emit("userInput", this.userInput), e && this._track && this.rl && (this.rl.write(this.userInput), this._cursor = this.rl.cursor);
993
+ }
994
+ _clearUserInput() {
995
+ this.rl?.write(null, {
996
+ ctrl: true,
997
+ name: "u"
998
+ }), this._setUserInput("");
999
+ }
1000
+ onKeypress(t, e) {
1001
+ if (this._track && e.name !== "return" && (e.name && this._isActionKey(t, e) && this.rl?.write(null, {
1002
+ ctrl: true,
1003
+ name: "h"
1004
+ }), this._cursor = this.rl?.cursor ?? 0, this._setUserInput(this.rl?.line)), this.state === "error" && (this.state = "active"), e?.name && (!this._track && settings.aliases.has(e.name) && this.emit("cursor", settings.aliases.get(e.name)), settings.actions.has(e.name) && this.emit("cursor", e.name)), t && (t.toLowerCase() === "y" || t.toLowerCase() === "n") && this.emit("confirm", t.toLowerCase() === "y"), this.emit("key", t, e), e?.name === "return" && this._shouldSubmit(t, e)) {
1005
+ if (this.opts.validate) {
1006
+ const i = runValidation(this.opts.validate, this.value);
1007
+ i && (this.error = i instanceof Error ? i.message : i, this.state = "error", this.rl?.write(this.userInput));
1008
+ }
1009
+ this.state !== "error" && (this.state = "submit");
1010
+ }
1011
+ isActionKey([
1012
+ t,
1013
+ e?.name,
1014
+ e?.sequence
1015
+ ], "cancel") && (this.state = "cancel"), (this.state === "submit" || this.state === "cancel") && this.emit("finalize"), this.render(), (this.state === "submit" || this.state === "cancel") && this.close();
1016
+ }
1017
+ close() {
1018
+ this.input.unpipe(), this.input.removeListener("keypress", this.onKeypress), this.output.write(`
1019
+ `), setRawMode(this.input, false), this.rl?.close(), this.rl = void 0, this.emit(`${this.state}`, this.value), this.unsubscribe();
1020
+ }
1021
+ restoreCursor() {
1022
+ const t = wrapAnsi(this._prevFrame, process.stdout.columns, {
1023
+ hard: true,
1024
+ trim: false
1025
+ }).split(`
1026
+ `).length - 1;
1027
+ this.output.write(import_src.cursor.move(-999, t * -1));
1028
+ }
1029
+ render() {
1030
+ const t = wrapAnsi(this._render(this) ?? "", process.stdout.columns, {
1031
+ hard: true,
1032
+ trim: false
1033
+ });
1034
+ if (t !== this._prevFrame) {
1035
+ if (this.state === "initial") this.output.write(import_src.cursor.hide);
1036
+ else {
1037
+ const e = diffLines(this._prevFrame, t), i = getRows(this.output);
1038
+ if (this.restoreCursor(), e) {
1039
+ const n = Math.max(0, e.numLinesAfter - i), s = Math.max(0, e.numLinesBefore - i);
1040
+ let r = e.lines.find((o) => o >= n);
1041
+ if (r === void 0) {
1042
+ this._prevFrame = t;
1043
+ return;
1044
+ }
1045
+ if (e.lines.length === 1) {
1046
+ this.output.write(import_src.cursor.move(0, r - s)), this.output.write(import_src.erase.lines(1));
1047
+ const o = t.split(`
1048
+ `);
1049
+ this.output.write(o[r]), this._prevFrame = t, this.output.write(import_src.cursor.move(0, o.length - r - 1));
1050
+ return;
1051
+ } else if (e.lines.length > 1) {
1052
+ if (n < s) r = n;
1053
+ else {
1054
+ const h = r - s;
1055
+ h > 0 && this.output.write(import_src.cursor.move(0, h));
1056
+ }
1057
+ this.output.write(import_src.erase.down());
1058
+ const f = t.split(`
1059
+ `).slice(r);
1060
+ this.output.write(f.join(`
1061
+ `)), this._prevFrame = t;
1062
+ return;
1063
+ }
1064
+ }
1065
+ this.output.write(import_src.erase.down());
1066
+ }
1067
+ this.output.write(t), this.state === "initial" && (this.state = "active"), this._prevFrame = t;
1068
+ }
1069
+ }
1070
+ };
1071
+ var r = class extends V {
1072
+ get cursor() {
1073
+ return this.value ? 0 : 1;
1074
+ }
1075
+ get _value() {
1076
+ return this.cursor === 0;
1077
+ }
1078
+ constructor(t) {
1079
+ super(t, false), this.value = !!t.initialValue, this.on("userInput", () => {
1080
+ this.value = this._value;
1081
+ }), this.on("confirm", (i) => {
1082
+ this.output.write(import_src.cursor.move(0, -1)), this.value = i, this.state = "submit", this.close();
1083
+ }), this.on("cursor", () => {
1084
+ this.value = !this.value;
1085
+ });
1086
+ }
1087
+ };
1088
+ let u$2 = class u extends V {
1089
+ options;
1090
+ cursor = 0;
1091
+ #t;
1092
+ getGroupItems(t) {
1093
+ return this.options.filter((r) => r.group === t);
1094
+ }
1095
+ isGroupSelected(t) {
1096
+ const r = this.getGroupItems(t), e = this.value;
1097
+ return e === void 0 ? false : r.every((s) => e.includes(s.value));
1098
+ }
1099
+ toggleValue() {
1100
+ const t = this.options[this.cursor];
1101
+ if (t !== void 0) if (this.value === void 0 && (this.value = []), t.group === true) {
1102
+ const r = t.value, e = this.getGroupItems(r);
1103
+ this.isGroupSelected(r) ? this.value = this.value.filter((s) => e.findIndex((i) => i.value === s) === -1) : this.value = [...this.value, ...e.map((s) => s.value)], this.value = Array.from(new Set(this.value));
1104
+ } else {
1105
+ const r = this.value.includes(t.value);
1106
+ this.value = r ? this.value.filter((e) => e !== t.value) : [...this.value, t.value];
1107
+ }
1108
+ }
1109
+ constructor(t) {
1110
+ super(t, false);
1111
+ const { options: r } = t;
1112
+ this.#t = t.selectableGroups !== false, this.options = Object.entries(r).flatMap(([e, s]) => [{
1113
+ value: e,
1114
+ group: true,
1115
+ label: e
1116
+ }, ...s.map((i) => ({
1117
+ ...i,
1118
+ group: e
1119
+ }))]), this.value = [...t.initialValues ?? []], this.cursor = Math.max(this.options.findIndex(({ value: e }) => e === t.cursorAt), this.#t ? 0 : 1), this.on("cursor", (e) => {
1120
+ switch (e) {
1121
+ case "left":
1122
+ case "up": {
1123
+ this.cursor = this.cursor === 0 ? this.options.length - 1 : this.cursor - 1;
1124
+ const s = this.options[this.cursor]?.group === true;
1125
+ !this.#t && s && (this.cursor = this.cursor === 0 ? this.options.length - 1 : this.cursor - 1);
1126
+ break;
1127
+ }
1128
+ case "down":
1129
+ case "right": {
1130
+ this.cursor = this.cursor === this.options.length - 1 ? 0 : this.cursor + 1;
1131
+ const s = this.options[this.cursor]?.group === true;
1132
+ !this.#t && s && (this.cursor = this.cursor === this.options.length - 1 ? 0 : this.cursor + 1);
1133
+ break;
1134
+ }
1135
+ case "space":
1136
+ this.toggleValue();
1137
+ break;
1138
+ }
1139
+ });
1140
+ }
1141
+ };
1142
+ var a = class extends V {
1143
+ options;
1144
+ cursor = 0;
1145
+ get _value() {
1146
+ return this.options[this.cursor]?.value;
1147
+ }
1148
+ get _enabledOptions() {
1149
+ return this.options.filter((e) => e.disabled !== true);
1150
+ }
1151
+ toggleAll() {
1152
+ const e = this._enabledOptions, i = this.value !== void 0 && this.value.length === e.length;
1153
+ this.value = i ? [] : e.map((t) => t.value);
1154
+ }
1155
+ toggleInvert() {
1156
+ const e = this.value;
1157
+ if (!e) return;
1158
+ const i = this._enabledOptions.filter((t) => !e.includes(t.value));
1159
+ this.value = i.map((t) => t.value);
1160
+ }
1161
+ toggleValue() {
1162
+ this.value === void 0 && (this.value = []);
1163
+ const e = this.value.includes(this._value);
1164
+ this.value = e ? this.value.filter((i) => i !== this._value) : [...this.value, this._value];
1165
+ }
1166
+ constructor(e) {
1167
+ super(e, false), this.options = e.options, this.value = [...e.initialValues ?? []];
1168
+ const i = Math.max(this.options.findIndex(({ value: t }) => t === e.cursorAt), 0);
1169
+ this.cursor = this.options[i]?.disabled ? findCursor(i, 1, this.options) : i, this.on("key", (t, l) => {
1170
+ l.name === "a" && this.toggleAll(), l.name === "i" && this.toggleInvert();
1171
+ }), this.on("cursor", (t) => {
1172
+ switch (t) {
1173
+ case "left":
1174
+ case "up":
1175
+ this.cursor = findCursor(this.cursor, -1, this.options);
1176
+ break;
1177
+ case "down":
1178
+ case "right":
1179
+ this.cursor = findCursor(this.cursor, 1, this.options);
1180
+ break;
1181
+ case "space":
1182
+ this.toggleValue();
1183
+ break;
1184
+ }
1185
+ });
1186
+ }
1187
+ };
1188
+ let n$1 = class n extends V {
1189
+ options;
1190
+ cursor = 0;
1191
+ get _selectedValue() {
1192
+ return this.options[this.cursor];
1193
+ }
1194
+ changeValue() {
1195
+ const e = this._selectedValue;
1196
+ this.value = e === void 0 ? void 0 : e.value;
1197
+ }
1198
+ constructor(e) {
1199
+ super(e, false), this.options = e.options;
1200
+ const o = this.options.findIndex(({ value: s }) => s === e.initialValue), t = o === -1 ? 0 : o;
1201
+ this.cursor = this.options[t]?.disabled ? findCursor(t, 1, this.options) : t, this.changeValue(), this.on("cursor", (s) => {
1202
+ switch (s) {
1203
+ case "left":
1204
+ case "up":
1205
+ this.cursor = findCursor(this.cursor, -1, this.options);
1206
+ break;
1207
+ case "down":
1208
+ case "right":
1209
+ this.cursor = findCursor(this.cursor, 1, this.options);
1210
+ break;
1211
+ }
1212
+ this.changeValue();
1213
+ });
1214
+ }
1215
+ };
1216
+ var n = class extends V {
1217
+ get userInputWithCursor() {
1218
+ if (this.state === "submit") return this.userInput;
1219
+ const t = this.userInput;
1220
+ if (this.cursor >= t.length) return `${this.userInput}\u2588`;
1221
+ const r = t.slice(0, this.cursor), s = t.slice(this.cursor, this.cursor + 1), e = t.slice(this.cursor + 1);
1222
+ return `${r}${styleText("inverse", s)}${e}`;
1223
+ }
1224
+ get cursor() {
1225
+ return this._cursor;
1226
+ }
1227
+ constructor(t) {
1228
+ super({
1229
+ ...t,
1230
+ initialUserInput: t.initialUserInput ?? t.initialValue
1231
+ }), this.on("userInput", (r) => {
1232
+ this._setValue(r);
1233
+ }), this.on("finalize", () => {
1234
+ this.value || (this.value = t.defaultValue), this.value === void 0 && (this.value = "");
1235
+ });
1236
+ }
1237
+ };
1238
+ //#endregion
1239
+ //#region ../../node_modules/.pnpm/@clack+prompts@1.7.0/node_modules/@clack/prompts/dist/index.mjs
1240
+ function isUnicodeSupported() {
1241
+ if (process$1.platform !== "win32") return process$1.env.TERM !== "linux";
1242
+ return Boolean(process$1.env.CI) || Boolean(process$1.env.WT_SESSION) || Boolean(process$1.env.TERMINUS_SUBLIME) || process$1.env.ConEmuTask === "{cmd::Cmder}" || process$1.env.TERM_PROGRAM === "Terminus-Sublime" || process$1.env.TERM_PROGRAM === "vscode" || process$1.env.TERM === "xterm-256color" || process$1.env.TERM === "alacritty" || process$1.env.TERMINAL_EMULATOR === "JetBrains-JediTerm";
1243
+ }
1244
+ const unicode = isUnicodeSupported();
1245
+ const unicodeOr = (o, e) => unicode ? o : e;
1246
+ const S_STEP_ACTIVE = unicodeOr("◆", "*");
1247
+ const S_STEP_CANCEL = unicodeOr("■", "x");
1248
+ const S_STEP_ERROR = unicodeOr("▲", "x");
1249
+ const S_STEP_SUBMIT = unicodeOr("◇", "o");
1250
+ const S_BAR_START = unicodeOr("┌", "T");
1251
+ const S_BAR = unicodeOr("│", "|");
1252
+ const S_BAR_END = unicodeOr("└", "—");
1253
+ const S_RADIO_ACTIVE = unicodeOr("●", ">");
1254
+ const S_RADIO_INACTIVE = unicodeOr("○", " ");
1255
+ const S_CHECKBOX_ACTIVE = unicodeOr("◻", "[•]");
1256
+ const S_CHECKBOX_SELECTED = unicodeOr("◼", "[+]");
1257
+ const S_CHECKBOX_INACTIVE = unicodeOr("◻", "[ ]");
1258
+ const symbol = (o) => {
1259
+ switch (o) {
1260
+ case "initial":
1261
+ case "active": return styleText("cyan", S_STEP_ACTIVE);
1262
+ case "cancel": return styleText("red", S_STEP_CANCEL);
1263
+ case "error": return styleText("yellow", S_STEP_ERROR);
1264
+ case "submit": return styleText("green", S_STEP_SUBMIT);
1265
+ }
1266
+ };
1267
+ const symbolBar = (o) => {
1268
+ switch (o) {
1269
+ case "initial":
1270
+ case "active": return styleText("cyan", S_BAR);
1271
+ case "cancel": return styleText("red", S_BAR);
1272
+ case "error": return styleText("yellow", S_BAR);
1273
+ case "submit": return styleText("green", S_BAR);
1274
+ }
1275
+ };
1276
+ function formatInstructionFooter(o, e) {
1277
+ const r = [`${e ? `${styleText("cyan", S_BAR)} ` : ""}${o.join(" • ")}`];
1278
+ return e && r.push(styleText("cyan", S_BAR_END)), r;
1279
+ }
1280
+ const I = (l, e, w, p, b, C = false) => {
1281
+ let r = e, O = 0;
1282
+ if (C) for (let i = p - 1; i >= w; i--) {
1283
+ const m = l[i];
1284
+ if (m && (r -= m.length), O++, r <= b) break;
1285
+ }
1286
+ else for (let i = w; i < p; i++) {
1287
+ const m = l[i];
1288
+ if (m && (r -= m.length), O++, r <= b) break;
1289
+ }
1290
+ return {
1291
+ lineCount: r,
1292
+ removals: O
1293
+ };
1294
+ };
1295
+ const limitOptions = ({ cursor: l, options: e, style: w, output: p = process.stdout, maxItems: b = Number.POSITIVE_INFINITY, columnPadding: C = 0, rowPadding: r = 4 }) => {
1296
+ const i = getColumns(p) - C, m = getRows(p), M = styleText("dim", "..."), v = Math.max(m - r, 0), a = Math.max(Math.min(b, v), 5);
1297
+ let f = 0;
1298
+ l >= a - 3 && (f = Math.max(Math.min(l - a + 3, e.length - a), 0));
1299
+ let d = a < e.length && f > 0, c = a < e.length && f + a < e.length;
1300
+ const W = Math.min(f + a, e.length), s = [];
1301
+ let g = 0;
1302
+ d && g++, c && g++;
1303
+ const T = f + (d ? 1 : 0), y = W - (c ? 1 : 0);
1304
+ for (let t = T; t < y; t++) {
1305
+ const n = e[t], h = wrapAnsi(n ? w(n, t === l) : "", i, {
1306
+ hard: true,
1307
+ trim: false
1308
+ }).split(`
1309
+ `);
1310
+ s.push(h), g += h.length;
1311
+ }
1312
+ if (g > v) {
1313
+ let t = 0, n = 0, o = g;
1314
+ const h = l - T;
1315
+ let u = v;
1316
+ const L = () => I(s, o, 0, h, u), E = () => I(s, o, h + 1, s.length, u, true);
1317
+ d ? ({lineCount: o, removals: t} = L(), o > u && (c || (u -= 1), {lineCount: o, removals: n} = E())) : (c || (u -= 1), {lineCount: o, removals: n} = E(), o > u && (u -= 1, {lineCount: o, removals: t} = L())), t > 0 && (d = true, s.splice(0, t)), n > 0 && (c = true, s.splice(s.length - n, n));
1318
+ }
1319
+ const x = [];
1320
+ d && x.push(M);
1321
+ for (const t of s) for (const n of t) x.push(n);
1322
+ return c && x.push(M), x;
1323
+ };
1324
+ const confirm = (i) => {
1325
+ const a = i.active ?? "Yes", s = i.inactive ?? "No";
1326
+ return new r({
1327
+ active: a,
1328
+ inactive: s,
1329
+ signal: i.signal,
1330
+ input: i.input,
1331
+ output: i.output,
1332
+ initialValue: i.initialValue ?? true,
1333
+ render() {
1334
+ const e = i.withGuide ?? settings.withGuide, u = `${symbol(this.state)} `, l = e ? `${styleText("gray", S_BAR)} ` : "", f = wrapTextWithPrefix(i.output, i.message, l, u), o = `${e ? `${styleText("gray", S_BAR)}
1335
+ ` : ""}${f}
1336
+ `, c = this.value ? a : s;
1337
+ switch (this.state) {
1338
+ case "submit": return `${o}${e ? `${styleText("gray", S_BAR)} ` : ""}${styleText("dim", c)}`;
1339
+ case "cancel": return `${o}${e ? `${styleText("gray", S_BAR)} ` : ""}${styleText(["strikethrough", "dim"], c)}${e ? `
1340
+ ${styleText("gray", S_BAR)}` : ""}`;
1341
+ default: {
1342
+ const r = e ? `${styleText("cyan", S_BAR)} ` : "", g = e ? styleText("cyan", S_BAR_END) : "";
1343
+ return `${o}${r}${this.value ? `${styleText("green", S_RADIO_ACTIVE)} ${a}` : `${styleText("dim", S_RADIO_INACTIVE)} ${styleText("dim", a)}`}${i.vertical ? e ? `
1344
+ ${styleText("cyan", S_BAR)} ` : `
1345
+ ` : ` ${styleText("dim", "/")} `}${this.value ? `${styleText("dim", S_RADIO_INACTIVE)} ${styleText("dim", s)}` : `${styleText("green", S_RADIO_ACTIVE)} ${s}`}
1346
+ ${g}
1347
+ `;
1348
+ }
1349
+ }
1350
+ }
1351
+ }).prompt();
1352
+ };
1353
+ const MULTISELECT_INSTRUCTIONS = [
1354
+ `${styleText("dim", "↑/↓")} to navigate`,
1355
+ `${styleText("dim", "Space:")} select`,
1356
+ `${styleText("dim", "Enter:")} confirm`
1357
+ ];
1358
+ const m = (i, u) => i.split(`
1359
+ `).map((d) => u(d)).join(`
1360
+ `);
1361
+ const multiselect = (i) => {
1362
+ const u = (t, a) => {
1363
+ const r = t.label ?? String(t.value);
1364
+ return a === "disabled" ? `${styleText("gray", S_CHECKBOX_INACTIVE)} ${m(r, (o) => styleText(["strikethrough", "gray"], o))}${t.hint ? ` ${styleText("dim", `(${t.hint ?? "disabled"})`)}` : ""}` : a === "active" ? `${styleText("cyan", S_CHECKBOX_ACTIVE)} ${r}${t.hint ? ` ${styleText("dim", `(${t.hint})`)}` : ""}` : a === "selected" ? `${styleText("green", S_CHECKBOX_SELECTED)} ${m(r, (o) => styleText("dim", o))}${t.hint ? ` ${styleText("dim", `(${t.hint})`)}` : ""}` : a === "cancelled" ? `${m(r, (o) => styleText(["strikethrough", "dim"], o))}` : a === "active-selected" ? `${styleText("green", S_CHECKBOX_SELECTED)} ${r}${t.hint ? ` ${styleText("dim", `(${t.hint})`)}` : ""}` : a === "submitted" ? `${m(r, (o) => styleText("dim", o))}` : `${styleText("dim", S_CHECKBOX_INACTIVE)} ${m(r, (o) => styleText("dim", o))}`;
1365
+ }, d = i.required ?? true, v = i.showInstructions ?? true;
1366
+ return new a({
1367
+ options: i.options,
1368
+ signal: i.signal,
1369
+ input: i.input,
1370
+ output: i.output,
1371
+ initialValues: i.initialValues,
1372
+ required: d,
1373
+ cursorAt: i.cursorAt,
1374
+ validate(t) {
1375
+ if (d && (t === void 0 || t.length === 0)) return `Please select at least one option.
1376
+ ${styleText("reset", styleText("dim", `Press ${styleText([
1377
+ "gray",
1378
+ "bgWhite",
1379
+ "inverse"
1380
+ ], " space ")} to select, ${styleText("gray", styleText("bgWhite", styleText("inverse", " enter ")))} to submit`))}`;
1381
+ },
1382
+ render() {
1383
+ const t = i.withGuide ?? settings.withGuide, a = wrapTextWithPrefix(i.output, i.message, t ? `${symbolBar(this.state)} ` : "", `${symbol(this.state)} `), r = `${t ? `${styleText("gray", S_BAR)}
1384
+ ` : ""}${a}
1385
+ `, o = this.value ?? [], p = (n, l) => {
1386
+ if (n.disabled) return u(n, "disabled");
1387
+ const s = o.includes(n.value);
1388
+ return l && s ? u(n, "active-selected") : s ? u(n, "selected") : u(n, l ? "active" : "inactive");
1389
+ };
1390
+ switch (this.state) {
1391
+ case "submit": {
1392
+ const n = this.options.filter(({ value: s }) => o.includes(s)).map((s) => u(s, "submitted")).join(styleText("dim", ", ")) || styleText("dim", "none");
1393
+ return `${r}${wrapTextWithPrefix(i.output, n, t ? `${styleText("gray", S_BAR)} ` : "")}`;
1394
+ }
1395
+ case "cancel": {
1396
+ const n = this.options.filter(({ value: s }) => o.includes(s)).map((s) => u(s, "cancelled")).join(styleText("dim", ", "));
1397
+ if (n.trim() === "") return `${r}${styleText("gray", S_BAR)}`;
1398
+ return `${r}${wrapTextWithPrefix(i.output, n, t ? `${styleText("gray", S_BAR)} ` : "")}${t ? `
1399
+ ${styleText("gray", S_BAR)}` : ""}`;
1400
+ }
1401
+ case "error": {
1402
+ const n = t ? `${styleText("yellow", S_BAR)} ` : "", l = this.error.split(`
1403
+ `).map(($, C) => C === 0 ? `${t ? `${styleText("yellow", S_BAR_END)} ` : ""}${styleText("yellow", $)}` : ` ${$}`).join(`
1404
+ `), s = r.split(`
1405
+ `).length, h = l.split(`
1406
+ `).length + 1;
1407
+ return `${r}${n}${limitOptions({
1408
+ output: i.output,
1409
+ options: this.options,
1410
+ cursor: this.cursor,
1411
+ maxItems: i.maxItems,
1412
+ columnPadding: n.length,
1413
+ rowPadding: s + h,
1414
+ style: p
1415
+ }).join(`
1416
+ ${n}`)}
1417
+ ${l}
1418
+ `;
1419
+ }
1420
+ default: {
1421
+ const n = t ? `${styleText("cyan", S_BAR)} ` : "", l = r.split(`
1422
+ `).length, s = v ? formatInstructionFooter(MULTISELECT_INSTRUCTIONS, t) : t ? [styleText("cyan", S_BAR_END)] : [], h = s.join(`
1423
+ `), $ = s.length + 1;
1424
+ return `${r}${n}${limitOptions({
1425
+ output: i.output,
1426
+ options: this.options,
1427
+ cursor: this.cursor,
1428
+ maxItems: i.maxItems,
1429
+ columnPadding: n.length,
1430
+ rowPadding: l + $,
1431
+ style: p
1432
+ }).join(`
1433
+ ${n}`)}
1434
+ ${h}
1435
+ `;
1436
+ }
1437
+ }
1438
+ }
1439
+ }).prompt();
1440
+ };
1441
+ const groupMultiselect = (o) => {
1442
+ const { selectableGroups: h = true, groupSpacing: x = 0 } = o, m = (n, l, g = []) => {
1443
+ const a = n.label ?? String(n.value), t = typeof n.group == "string", s = t && (g[g.indexOf(n) + 1] ?? { group: true }), u = t && s && s.group === true;
1444
+ let r = "", c = "";
1445
+ t && (h ? (r = u ? `${S_BAR_END} ` : `${S_BAR} `, c = u ? " " : `${S_BAR} `) : r = " ");
1446
+ let i = "";
1447
+ if (x > 0 && !t && (i = `
1448
+ `.repeat(x)), l === "active") return wrapTextWithPrefix(o.output, `${a}${n.hint ? ` ${styleText("dim", `(${n.hint})`)}` : ""}`, `${i}${styleText("dim", r)} `, `${i}${styleText("dim", r)}${styleText("cyan", S_CHECKBOX_ACTIVE)} `, `${i}${styleText("dim", c)} `);
1449
+ if (l === "group-active") return wrapTextWithPrefix(o.output, a, `${i}${r} `, `${i}${r}${styleText("cyan", S_CHECKBOX_ACTIVE)} `, `${i}${c} `, (d) => styleText("dim", d));
1450
+ if (l === "group-active-selected") return wrapTextWithPrefix(o.output, a, `${i}${r} `, `${i}${r}${styleText("green", S_CHECKBOX_SELECTED)} `, `${i}${c} `, (d) => styleText("dim", d));
1451
+ if (l === "selected") {
1452
+ const d = t || h ? styleText("green", S_CHECKBOX_SELECTED) : "";
1453
+ return wrapTextWithPrefix(o.output, `${a}${n.hint ? ` (${n.hint})` : ""}`, `${i}${styleText("dim", r)} `, `${i}${styleText("dim", r)}${d} `, `${i}${styleText("dim", c)} `, (S) => styleText("dim", S));
1454
+ }
1455
+ if (l === "cancelled") return `${styleText(["strikethrough", "dim"], a)}`;
1456
+ if (l === "active-selected") return wrapTextWithPrefix(o.output, `${a}${n.hint ? ` ${styleText("dim", `(${n.hint})`)}` : ""}`, `${i}${styleText("dim", r)} `, `${i}${styleText("dim", r)}${styleText("green", S_CHECKBOX_SELECTED)} `, `${i}${styleText("dim", c)} `);
1457
+ if (l === "submitted") return `${styleText("dim", a)}`;
1458
+ const f = t || h ? styleText("dim", S_CHECKBOX_INACTIVE) : "";
1459
+ return wrapTextWithPrefix(o.output, a, `${i}${styleText("dim", r)} `, `${i}${styleText("dim", r)}${f} `, `${i}${styleText("dim", c)} `, (d) => styleText("dim", d));
1460
+ }, y = o.required ?? true, I = o.showInstructions ?? true;
1461
+ return new u$2({
1462
+ options: o.options,
1463
+ signal: o.signal,
1464
+ input: o.input,
1465
+ output: o.output,
1466
+ initialValues: o.initialValues,
1467
+ required: y,
1468
+ cursorAt: o.cursorAt,
1469
+ selectableGroups: h,
1470
+ validate(n) {
1471
+ if (y && (n === void 0 || n.length === 0)) return `Please select at least one option.
1472
+ ${styleText("reset", styleText("dim", `Press ${styleText([
1473
+ "gray",
1474
+ "bgWhite",
1475
+ "inverse"
1476
+ ], " space ")} to select, ${styleText("gray", styleText(["bgWhite", "inverse"], " enter "))} to submit`))}`;
1477
+ },
1478
+ render() {
1479
+ const n = o.withGuide ?? settings.withGuide, l = `${n ? `${styleText("gray", S_BAR)}
1480
+ ` : ""}${symbol(this.state)} ${o.message}
1481
+ `, g = this.value ?? [], a = (t, s) => {
1482
+ const u = this.options, r = g.includes(t.value) || t.group === true && this.isGroupSelected(`${t.value}`);
1483
+ return !s && typeof t.group == "string" && this.options[this.cursor]?.value === t.group ? m(t, r ? "group-active-selected" : "group-active", u) : s && r ? m(t, "active-selected", u) : r ? m(t, "selected", u) : m(t, s ? "active" : "inactive", u);
1484
+ };
1485
+ switch (this.state) {
1486
+ case "submit": {
1487
+ const t = this.options.filter(({ value: u }) => g.includes(u)).map((u) => m(u, "submitted")), s = t.length === 0 ? "" : ` ${t.join(styleText("dim", ", "))}`;
1488
+ return `${l}${n ? styleText("gray", S_BAR) : ""}${s}`;
1489
+ }
1490
+ case "cancel": {
1491
+ const t = this.options.filter(({ value: s }) => g.includes(s)).map((s) => m(s, "cancelled")).join(styleText("dim", ", "));
1492
+ return `${l}${n ? `${styleText("gray", S_BAR)} ` : ""}${t.trim() ? `${t}${n ? `
1493
+ ${styleText("gray", S_BAR)}` : ""}` : ""}`;
1494
+ }
1495
+ case "error": {
1496
+ const t = n ? `${styleText("yellow", S_BAR)} ` : "", s = this.error.split(`
1497
+ `).map((i, f) => f === 0 ? `${n ? `${styleText("yellow", S_BAR_END)} ` : ""}${styleText("yellow", i)}` : ` ${i}`).join(`
1498
+ `), u = l.split(`
1499
+ `).length, r = s.split(`
1500
+ `).length + 1;
1501
+ return `${l}${t}${limitOptions({
1502
+ output: o.output,
1503
+ options: this.options,
1504
+ cursor: this.cursor,
1505
+ maxItems: o.maxItems,
1506
+ columnPadding: t.length,
1507
+ rowPadding: u + r,
1508
+ style: a
1509
+ }).join(`
1510
+ ${t}`)}
1511
+ ${s}
1512
+ `;
1513
+ }
1514
+ default: {
1515
+ const t = n ? `${styleText("cyan", S_BAR)} ` : "", s = l.split(`
1516
+ `).length, u = I ? formatInstructionFooter(MULTISELECT_INSTRUCTIONS, n) : n ? [styleText("cyan", S_BAR_END)] : [], r = u.join(`
1517
+ `), c = u.length + 1;
1518
+ return `${l}${t}${limitOptions({
1519
+ output: o.output,
1520
+ options: this.options,
1521
+ cursor: this.cursor,
1522
+ maxItems: o.maxItems,
1523
+ columnPadding: t.length,
1524
+ rowPadding: s + c,
1525
+ style: a
1526
+ }).join(`
1527
+ ${t}`)}
1528
+ ${r}
1529
+ `;
1530
+ }
1531
+ }
1532
+ }
1533
+ }).prompt();
1534
+ };
1535
+ const cancel = (o = "", t) => {
1536
+ const i = t?.output ?? process.stdout, e = t?.withGuide ?? settings.withGuide ? `${styleText("gray", S_BAR_END)} ` : "";
1537
+ i.write(`${e}${styleText("red", o)}
1538
+
1539
+ `);
1540
+ };
1541
+ const intro = (o = "", t) => {
1542
+ const i = t?.output ?? process.stdout, e = t?.withGuide ?? settings.withGuide ? `${styleText("gray", S_BAR_START)} ` : "";
1543
+ i.write(`${e}${o}
1544
+ `);
1545
+ };
1546
+ const outro = (o = "", t) => {
1547
+ const i = t?.output ?? process.stdout, e = t?.withGuide ?? settings.withGuide ? `${styleText("gray", S_BAR)}
1548
+ ${styleText("gray", S_BAR_END)} ` : "";
1549
+ i.write(`${e}${o}
1550
+
1551
+ `);
1552
+ };
1553
+ const SELECT_INSTRUCTIONS = [`${styleText("dim", "↑/↓")} to navigate`, `${styleText("dim", "Enter:")} confirm`];
1554
+ const c = (t, o) => t.includes(`
1555
+ `) ? t.split(`
1556
+ `).map((d) => o(d)).join(`
1557
+ `) : o(t);
1558
+ const select = (t) => {
1559
+ const o = (n, m) => {
1560
+ if (n === void 0) return "";
1561
+ const s = n.label ?? String(n.value);
1562
+ switch (m) {
1563
+ case "disabled": return `${styleText("gray", S_RADIO_INACTIVE)} ${c(s, (i) => styleText("gray", i))}${n.hint ? ` ${styleText("dim", `(${n.hint ?? "disabled"})`)}` : ""}`;
1564
+ case "selected": return `${c(s, (i) => styleText("dim", i))}`;
1565
+ case "active": return `${styleText("green", S_RADIO_ACTIVE)} ${s}${n.hint ? ` ${styleText("dim", `(${n.hint})`)}` : ""}`;
1566
+ case "cancelled": return `${c(s, (i) => styleText(["strikethrough", "dim"], i))}`;
1567
+ default: return `${styleText("dim", S_RADIO_INACTIVE)} ${c(s, (i) => styleText("dim", i))}`;
1568
+ }
1569
+ }, d = t.showInstructions ?? true;
1570
+ return new n$1({
1571
+ options: t.options,
1572
+ signal: t.signal,
1573
+ input: t.input,
1574
+ output: t.output,
1575
+ initialValue: t.initialValue,
1576
+ render() {
1577
+ const n = t.withGuide ?? settings.withGuide, m = `${symbol(this.state)} `, s = `${symbolBar(this.state)} `, i = wrapTextWithPrefix(t.output, t.message, s, m), u = `${n ? `${styleText("gray", S_BAR)}
1578
+ ` : ""}${i}
1579
+ `;
1580
+ switch (this.state) {
1581
+ case "submit": {
1582
+ const r = n ? `${styleText("gray", S_BAR)} ` : "";
1583
+ return `${u}${wrapTextWithPrefix(t.output, o(this.options[this.cursor], "selected"), r)}`;
1584
+ }
1585
+ case "cancel": {
1586
+ const r = n ? `${styleText("gray", S_BAR)} ` : "";
1587
+ return `${u}${wrapTextWithPrefix(t.output, o(this.options[this.cursor], "cancelled"), r)}${n ? `
1588
+ ${styleText("gray", S_BAR)}` : ""}`;
1589
+ }
1590
+ default: {
1591
+ const r = n ? `${styleText("cyan", S_BAR)} ` : "", a = u.split(`
1592
+ `).length, p = d ? formatInstructionFooter(SELECT_INSTRUCTIONS, n) : n ? [styleText("cyan", S_BAR_END)] : [], b = p.join(`
1593
+ `), f = p.length + 1;
1594
+ return `${u}${r}${limitOptions({
1595
+ output: t.output,
1596
+ cursor: this.cursor,
1597
+ options: this.options,
1598
+ maxItems: t.maxItems,
1599
+ columnPadding: r.length,
1600
+ rowPadding: a + f,
1601
+ style: (g, x) => o(g, g.disabled ? "disabled" : x ? "active" : "inactive")
1602
+ }).join(`
1603
+ ${r}`)}
1604
+ ${b}
1605
+ `;
1606
+ }
1607
+ }
1608
+ }
1609
+ }).prompt();
1610
+ };
1611
+ `${styleText("gray", S_BAR)}`;
1612
+ const text = (e) => new n({
1613
+ validate: e.validate,
1614
+ placeholder: e.placeholder,
1615
+ defaultValue: e.defaultValue,
1616
+ initialValue: e.initialValue,
1617
+ output: e.output,
1618
+ signal: e.signal,
1619
+ input: e.input,
1620
+ render() {
1621
+ const i = e?.withGuide ?? settings.withGuide, s = `${`${i ? `${styleText("gray", S_BAR)}
1622
+ ` : ""}${symbol(this.state)} `}${e.message}
1623
+ `, c = e.placeholder && e.placeholder.length > 0 ? styleText("inverse", e.placeholder[0]) + styleText("dim", e.placeholder.slice(1)) : styleText(["inverse", "hidden"], "_"), o = this.userInput ? this.userInputWithCursor : c, l = this.value ?? "";
1624
+ switch (this.state) {
1625
+ case "error": {
1626
+ const n = this.error ? ` ${styleText("yellow", this.error)}` : "", r = i ? `${styleText("yellow", S_BAR)} ` : "", d = i ? styleText("yellow", S_BAR_END) : "";
1627
+ return `${s.trim()}
1628
+ ${r}${o}
1629
+ ${d}${n}
1630
+ `;
1631
+ }
1632
+ case "submit": {
1633
+ const n = l ? ` ${styleText("dim", l)}` : "";
1634
+ return `${s}${i ? styleText("gray", S_BAR) : ""}${n}`;
1635
+ }
1636
+ case "cancel": {
1637
+ const n = l ? ` ${styleText(["strikethrough", "dim"], l)}` : "", r = i ? styleText("gray", S_BAR) : "";
1638
+ return `${s}${r}${n}${l.trim() ? `
1639
+ ${r}` : ""}`;
1640
+ }
1641
+ default: return `${s}${i ? `${styleText("cyan", S_BAR)} ` : ""}${o}
1642
+ ${i ? styleText("cyan", S_BAR_END) : ""}
1643
+ `;
1644
+ }
1645
+ }
1646
+ }).prompt();
1647
+ //#endregion
1648
+ //#region src/template-dir.ts
1649
+ function resolveJsTemplateDir(framework, vueFlavor) {
1650
+ if (framework !== "vue") return framework;
1651
+ return `vue-${vueFlavor ?? "sfc"}`;
1652
+ }
1653
+ //#endregion
1654
+ //#region src/utils/apply-app-identity.ts
1655
+ const TEXT_FILE_EXTENSIONS = /* @__PURE__ */ new Set([
1656
+ ".plist",
1657
+ ".pbxproj",
1658
+ ".xcscheme",
1659
+ ".xcworkspacedata",
1660
+ ".storyboard",
1661
+ ".swift",
1662
+ ".kt",
1663
+ ".java",
1664
+ ".gradle",
1665
+ ".xml",
1666
+ ".json",
1667
+ ".js",
1668
+ ""
1669
+ ]);
1670
+ function replaceTextContent(filePath, identity) {
1671
+ const content = fs.readFileSync(filePath, "utf8");
1672
+ const replaced = content.split("com.canary").join(identity.bundleId).split("Canary").join(identity.nativeAppName);
1673
+ if (replaced !== content) fs.writeFileSync(filePath, replaced);
1674
+ }
1675
+ function walkTextFiles(dir, identity) {
1676
+ for (const entry of fs.readdirSync(dir, { withFileTypes: true })) {
1677
+ const entryPath = path.join(dir, entry.name);
1678
+ if (entry.isDirectory()) {
1679
+ walkTextFiles(entryPath, identity);
1680
+ continue;
1681
+ }
1682
+ if (TEXT_FILE_EXTENSIONS.has(path.extname(entry.name))) replaceTextContent(entryPath, identity);
1683
+ }
1684
+ }
1685
+ function renameCanaryPaths(dir, nativeAppName) {
1686
+ for (const entry of fs.readdirSync(dir, { withFileTypes: true })) if (entry.isDirectory()) renameCanaryPaths(path.join(dir, entry.name), nativeAppName);
1687
+ for (const entry of fs.readdirSync(dir, { withFileTypes: true })) {
1688
+ if (!entry.name.startsWith("Canary")) continue;
1689
+ const from = path.join(dir, entry.name);
1690
+ const to = path.join(dir, entry.name.replace("Canary", nativeAppName));
1691
+ fs.renameSync(from, to);
1692
+ }
1693
+ }
1694
+ function moveAndroidPackageDir(javaSrcDir, bundleId) {
1695
+ const oldDir = path.join(javaSrcDir, "com", "canary");
1696
+ if (!fs.existsSync(oldDir)) return;
1697
+ const newDir = path.join(javaSrcDir, ...bundleId.split("."));
1698
+ fs.mkdirSync(path.dirname(newDir), { recursive: true });
1699
+ fs.renameSync(oldDir, newDir);
1700
+ const oldTopDir = path.join(javaSrcDir, "com");
1701
+ if (fs.existsSync(oldTopDir) && fs.readdirSync(oldTopDir).length === 0) fs.rmdirSync(oldTopDir);
1702
+ }
1703
+ function applyAppIdentity(root, identity) {
1704
+ walkTextFiles(root, identity);
1705
+ const iosDir = path.join(root, "ios");
1706
+ if (fs.existsSync(iosDir)) renameCanaryPaths(iosDir, identity.nativeAppName);
1707
+ const androidAppSrc = path.join(root, "android", "app", "src");
1708
+ if (fs.existsSync(androidAppSrc)) for (const sourceSet of fs.readdirSync(androidAppSrc)) moveAndroidPackageDir(path.join(androidAppSrc, sourceSet, "java"), identity.bundleId);
1709
+ }
1710
+ //#endregion
1711
+ //#region src/utils/json.ts
1712
+ function isJsonObject(value) {
1713
+ return typeof value === "object" && value !== null && !Array.isArray(value);
1714
+ }
1715
+ //#endregion
1716
+ //#region src/utils/deep-merge.ts
1717
+ function mergeArrayWithDedupe(a, b) {
1718
+ return Array.from(/* @__PURE__ */ new Set([...a, ...b]));
1719
+ }
1720
+ function deepMerge(target, source) {
1721
+ for (const key of Object.keys(source)) {
1722
+ const oldVal = target[key];
1723
+ const newVal = source[key];
1724
+ if (Array.isArray(oldVal) && Array.isArray(newVal)) target[key] = mergeArrayWithDedupe(oldVal, newVal);
1725
+ else if (isJsonObject(oldVal) && isJsonObject(newVal)) target[key] = deepMerge(oldVal, newVal);
1726
+ else target[key] = newVal;
1727
+ }
1728
+ return target;
1729
+ }
1730
+ //#endregion
1731
+ //#region src/utils/sort-dependencies.ts
1732
+ const DEPENDENCY_FIELDS = [
1733
+ "dependencies",
1734
+ "devDependencies",
1735
+ "peerDependencies",
1736
+ "optionalDependencies"
1737
+ ];
1738
+ function sortDependencies(packageJson) {
1739
+ const sorted = {};
1740
+ for (const field of DEPENDENCY_FIELDS) {
1741
+ const deps = packageJson[field];
1742
+ if (!isJsonObject(deps)) continue;
1743
+ const sortedDeps = {};
1744
+ for (const name of Object.keys(deps).sort()) sortedDeps[name] = deps[name];
1745
+ sorted[field] = sortedDeps;
1746
+ }
1747
+ return {
1748
+ ...packageJson,
1749
+ ...sorted
1750
+ };
1751
+ }
1752
+ //#endregion
1753
+ //#region src/utils/render-template.ts
1754
+ function readJsonObject(filePath) {
1755
+ const parsed = JSON.parse(fs.readFileSync(filePath, "utf8"));
1756
+ if (!isJsonObject(parsed)) throw new Error(`${filePath}: expected a JSON object`);
1757
+ return parsed;
1758
+ }
1759
+ const TYPESCRIPT_ONLY_FILENAMES = /* @__PURE__ */ new Set([
1760
+ "tsconfig.json",
1761
+ "tsconfig.angular.json",
1762
+ "tsconfig.typecheck.json",
1763
+ "App.tsx"
1764
+ ]);
1765
+ function isTypescriptOnlyFile(filename) {
1766
+ return TYPESCRIPT_ONLY_FILENAMES.has(filename) || filename.endsWith(".d.ts");
1767
+ }
1768
+ const JAVASCRIPT_ONLY_FILENAMES = /* @__PURE__ */ new Set([
1769
+ "App.jsx",
1770
+ "App.vue",
1771
+ "App.svelte",
1772
+ "MenuScreen.vue",
1773
+ "DetailsScreen.vue",
1774
+ "MenuScreen.svelte",
1775
+ "DetailsScreen.svelte"
1776
+ ]);
1777
+ function isJavascriptOnlyFile(filename) {
1778
+ return JAVASCRIPT_ONLY_FILENAMES.has(filename);
1779
+ }
1780
+ function stripTypescriptInfix(filename) {
1781
+ return filename.replace(".typescript.", ".");
1782
+ }
1783
+ const DEFAULT_OPTIONS = { hasTypescript: true };
1784
+ function renderTemplate(src, dest, options = DEFAULT_OPTIONS) {
1785
+ if (fs.statSync(src).isDirectory()) {
1786
+ fs.mkdirSync(dest, { recursive: true });
1787
+ for (const entry of fs.readdirSync(src)) renderTemplate(path.resolve(src, entry), path.resolve(dest, entry), options);
1788
+ return;
1789
+ }
1790
+ const filename = path.basename(src);
1791
+ if (filename === "README.md") return;
1792
+ if (!options.hasTypescript && (isTypescriptOnlyFile(filename) || filename.includes(".typescript."))) return;
1793
+ if (options.hasTypescript && isJavascriptOnlyFile(filename)) return;
1794
+ const destFilename = filename.includes(".typescript.") ? stripTypescriptInfix(filename) : filename;
1795
+ const resolvedDest = path.join(path.dirname(dest), destFilename);
1796
+ if (destFilename === "package.json.fragment.json") {
1797
+ const destPackageJsonPath = path.resolve(path.dirname(resolvedDest), "package.json");
1798
+ const fragment = readJsonObject(src);
1799
+ const merged = sortDependencies(deepMerge(fs.existsSync(destPackageJsonPath) ? readJsonObject(destPackageJsonPath) : {}, fragment));
1800
+ fs.writeFileSync(destPackageJsonPath, `${JSON.stringify(merged, null, 2)}\n`);
1801
+ return;
1802
+ }
1803
+ if (destFilename === ".gitignore" && fs.existsSync(resolvedDest)) {
1804
+ const existing = fs.readFileSync(resolvedDest, "utf8");
1805
+ const addition = fs.readFileSync(src, "utf8");
1806
+ fs.writeFileSync(resolvedDest, `${existing}\n${addition}`);
1807
+ return;
1808
+ }
1809
+ fs.copyFileSync(src, resolvedDest);
1810
+ }
1811
+ //#endregion
1812
+ //#region src/utils/apply-bootsplash-logo.ts
1813
+ function applyBootsplashLogo(root, templatesRoot, framework) {
1814
+ const overlayRoot = path.join(templatesRoot, "native", "bootsplash-logo", framework);
1815
+ if (fs.existsSync(overlayRoot)) renderTemplate(overlayRoot, root);
1816
+ }
1817
+ //#endregion
1818
+ //#region src/utils/apply-expo-modules-manifest.ts
1819
+ const EXPO_MODULES_PERMISSIONS = ` <uses-permission android:name="android.permission.VIBRATE" />
1820
+ <uses-permission android:name="android.permission.USE_FINGERPRINT" />
1821
+ <uses-permission android:name="android.permission.USE_BIOMETRIC" />
1822
+ <!-- @symbiote-native/brightness: setSystemBrightnessAsync/getPermissionsAsync -->
1823
+ <uses-permission android:name="android.permission.WRITE_SETTINGS" />
1824
+ <!-- @symbiote-native/cellular: getCarrierNameAsync/getIsoCountryCodeAsync/etc. -->
1825
+ <uses-permission android:name="android.permission.READ_PHONE_STATE" />`;
1826
+ const EXPO_MODULES_BACKUP_ATTRS = `android:supportsRtl="true"
1827
+ android:dataExtractionRules="@xml/secure_store_data_extraction_rules"
1828
+ android:fullBackupContent="@xml/secure_store_backup_rules">`;
1829
+ function applyExpoModulesAndroidManifest(root) {
1830
+ const manifestPath = path.join(root, "android/app/src/main/AndroidManifest.xml");
1831
+ const manifest = fs.readFileSync(manifestPath, "utf8");
1832
+ const withPermissions = manifest.includes("USE_BIOMETRIC") ? manifest : manifest.replace(" <uses-permission android:name=\"android.permission.VIBRATE\" />", EXPO_MODULES_PERMISSIONS);
1833
+ const withBackupAttrs = withPermissions.includes("dataExtractionRules") ? withPermissions : withPermissions.replace("android:supportsRtl=\"true\">", EXPO_MODULES_BACKUP_ATTRS);
1834
+ fs.writeFileSync(manifestPath, withBackupAttrs);
1835
+ }
1836
+ //#endregion
1837
+ //#region src/utils/apply-expo-modules-podfile-autolinking.ts
1838
+ const AUTOLINKING_REQUIRE = "require File.join(File.dirname(`node --print \"require.resolve('expo/package.json')\"`), \"scripts/autolinking\")";
1839
+ const NATIVE_MODULES_LINE = "config = use_native_modules!";
1840
+ function applyExpoModulesPodfileAutolinking(root) {
1841
+ const podfilePath = path.join(root, "ios", "Podfile");
1842
+ if (!fs.existsSync(podfilePath)) return;
1843
+ let podfile = fs.readFileSync(podfilePath, "utf8");
1844
+ if (podfile.includes("use_expo_modules!")) return;
1845
+ if (!podfile.includes(AUTOLINKING_REQUIRE)) podfile = `${AUTOLINKING_REQUIRE}\n\n${podfile}`;
1846
+ podfile = podfile.replace(NATIVE_MODULES_LINE, `${NATIVE_MODULES_LINE}\n\n use_expo_modules!`);
1847
+ fs.writeFileSync(podfilePath, podfile);
1848
+ }
1849
+ //#endregion
1850
+ //#region src/utils/apply-expo-modules-podfile.ts
1851
+ const DEFAULT_PLATFORM_LINE = "platform :ios, min_ios_version_supported.to_s";
1852
+ const RAISED_PLATFORM_LINE = "platform :ios, [min_ios_version_supported.to_f, 16.4].max.to_s";
1853
+ function applyExpoModulesPodfilePlatform(root) {
1854
+ const podfilePath = path.join(root, "ios", "Podfile");
1855
+ if (!fs.existsSync(podfilePath)) return;
1856
+ const podfile = fs.readFileSync(podfilePath, "utf8");
1857
+ if (!podfile.includes(DEFAULT_PLATFORM_LINE)) return;
1858
+ fs.writeFileSync(podfilePath, podfile.replace(DEFAULT_PLATFORM_LINE, RAISED_PLATFORM_LINE));
1859
+ }
1860
+ //#endregion
1861
+ //#region src/utils/apply-expo-modules-xcode-deployment-target.ts
1862
+ const MIN_EXPO_IOS_VERSION = 16.4;
1863
+ const DEPLOYMENT_TARGET_LINE = /IPHONEOS_DEPLOYMENT_TARGET = (\d+(?:\.\d+)?);/g;
1864
+ function findPbxprojPath(root) {
1865
+ const iosDir = path.join(root, "ios");
1866
+ if (!fs.existsSync(iosDir)) return void 0;
1867
+ const xcodeproj = fs.readdirSync(iosDir).find((entry) => entry.endsWith(".xcodeproj"));
1868
+ if (!xcodeproj) return void 0;
1869
+ const pbxprojPath = path.join(iosDir, xcodeproj, "project.pbxproj");
1870
+ return fs.existsSync(pbxprojPath) ? pbxprojPath : void 0;
1871
+ }
1872
+ function applyExpoModulesXcodeDeploymentTarget(root) {
1873
+ const pbxprojPath = findPbxprojPath(root);
1874
+ if (!pbxprojPath) return;
1875
+ const pbxproj = fs.readFileSync(pbxprojPath, "utf8");
1876
+ const raised = pbxproj.replace(DEPLOYMENT_TARGET_LINE, (line, version) => Number.parseFloat(version) < MIN_EXPO_IOS_VERSION ? `IPHONEOS_DEPLOYMENT_TARGET = ${MIN_EXPO_IOS_VERSION};` : line);
1877
+ if (raised !== pbxproj) fs.writeFileSync(pbxprojPath, raised);
1878
+ }
1879
+ //#endregion
1880
+ //#region src/utils/apply-splash-screen-hide.ts
1881
+ const SKIPPED_DIR_NAMES$1 = /* @__PURE__ */ new Set([
1882
+ "ios",
1883
+ "android",
1884
+ "node_modules"
1885
+ ]);
1886
+ const APP_COMPONENT_FILENAMES$1 = /* @__PURE__ */ new Set([
1887
+ "App.tsx",
1888
+ "App.jsx",
1889
+ "App.ts",
1890
+ "App.vue",
1891
+ "App.svelte"
1892
+ ]);
1893
+ function findAppComponentFile(dir) {
1894
+ for (const entry of fs.readdirSync(dir, { withFileTypes: true })) {
1895
+ const entryPath = path.join(dir, entry.name);
1896
+ if (entry.isDirectory()) {
1897
+ if (SKIPPED_DIR_NAMES$1.has(entry.name)) continue;
1898
+ const found = findAppComponentFile(entryPath);
1899
+ if (found !== void 0) return found;
1900
+ continue;
1901
+ }
1902
+ if (APP_COMPONENT_FILENAMES$1.has(entry.name)) return entryPath;
1903
+ }
1904
+ }
1905
+ function escapeRegExp(value) {
1906
+ return value.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
1907
+ }
1908
+ function insertOrMergeNamedImport(source, moduleSpecifier, name, insertFallback = (src, line) => `${line}\n${src}`) {
1909
+ const importLineRegex = new RegExp(`import \\{ ([^}]*) \\} from '${escapeRegExp(moduleSpecifier)}';`);
1910
+ const match = source.match(importLineRegex);
1911
+ if (match?.[1] !== void 0) {
1912
+ const names = match[1];
1913
+ if (names.split(",").map((n) => n.trim()).includes(name)) return source;
1914
+ return source.replace(importLineRegex, `import { ${names}, ${name} } from '${moduleSpecifier}';`);
1915
+ }
1916
+ return insertFallback(source, `import { ${name} } from '${moduleSpecifier}';`);
1917
+ }
1918
+ function patchReact(source) {
1919
+ return `import { hide } from '@symbiote-native/splash-screen/react';\n${insertOrMergeNamedImport(source, "react", "useEffect")}`.replace("export default function App() {", "export default function App() {\n useEffect(() => {\n hide();\n }, []);\n");
1920
+ }
1921
+ function patchSolid(source) {
1922
+ return `import { hide } from '@symbiote-native/splash-screen';\n${insertOrMergeNamedImport(source, "solid-js", "onMount")}`.replace("export default function App() {", "export default function App() {\n onMount(() => {\n hide();\n });\n");
1923
+ }
1924
+ function patchVueTsx(source) {
1925
+ return `import { hide } from '@symbiote-native/splash-screen/vue';\n${insertOrMergeNamedImport(source, "@vue/runtime-core", "onMounted")}`.replace("setup() {", "setup() {\n onMounted(() => hide());\n");
1926
+ }
1927
+ const SCRIPT_OPEN_TAG = /<script setup(?: lang="ts")?>/;
1928
+ function patchVueSfc(source) {
1929
+ return insertOrMergeNamedImport(source, "vue", "onMounted", (src, line) => src.replace(SCRIPT_OPEN_TAG, (tag) => `${tag}\n${line}`)).replace("<\/script>", `import { hide } from '@symbiote-native/splash-screen/vue';\nonMounted(() => hide());\n<\/script>`);
1930
+ }
1931
+ const ANGULAR_CORE_IMPORT = /import \{ ([^}]*) \} from '@angular\/core';/;
1932
+ function patchAngular(source) {
1933
+ return source.replace(ANGULAR_CORE_IMPORT, (line, specifiers) => specifiers.includes("OnInit") ? line : `import { ${specifiers}, OnInit } from '@angular/core';`).replace(ANGULAR_CORE_IMPORT, (line) => `${line}\nimport { hide } from '@symbiote-native/splash-screen/angular';`).replace("export class AppComponent {", "export class AppComponent implements OnInit {\n ngOnInit(): void {\n hide();\n }\n");
1934
+ }
1935
+ function patchSvelte(source) {
1936
+ return source.replace("<\/script>", ` import { hide } from '@symbiote-native/splash-screen/svelte';\n hide();\n<\/script>`);
1937
+ }
1938
+ function applySplashScreenAppHide(root, options) {
1939
+ const appFilePath = findAppComponentFile(root);
1940
+ if (appFilePath === void 0) return;
1941
+ const source = fs.readFileSync(appFilePath, "utf8");
1942
+ if (/\bhide\(\)/.test(source)) return;
1943
+ fs.writeFileSync(appFilePath, patch(source, options.framework, appFilePath));
1944
+ }
1945
+ function patch(source, framework, appFilePath) {
1946
+ switch (framework) {
1947
+ case "react": return patchReact(source);
1948
+ case "solid": return patchSolid(source);
1949
+ case "angular": return patchAngular(source);
1950
+ case "svelte": return patchSvelte(source);
1951
+ case "vue": return appFilePath.endsWith(".vue") ? patchVueSfc(source) : patchVueTsx(source);
1952
+ }
1953
+ }
1954
+ //#endregion
1955
+ //#region src/utils/apply-styling.ts
1956
+ const INLINE_STYLE_BLOCK_FRAMEWORKS = /* @__PURE__ */ new Set(["vue-sfc", "svelte"]);
1957
+ const STYLE_TAG_PATTERN = /<style(?=[ >])/;
1958
+ function addStyleLangAttribute(dir, lang) {
1959
+ for (const entry of fs.readdirSync(dir, { withFileTypes: true })) {
1960
+ const entryPath = path.join(dir, entry.name);
1961
+ if (entry.isDirectory()) {
1962
+ if (SKIPPED_DIR_NAMES.has(entry.name)) continue;
1963
+ addStyleLangAttribute(entryPath, lang);
1964
+ continue;
1965
+ }
1966
+ if (!entry.name.endsWith(".vue") && !entry.name.endsWith(".svelte")) continue;
1967
+ const content = fs.readFileSync(entryPath, "utf8");
1968
+ if (STYLE_TAG_PATTERN.test(content)) fs.writeFileSync(entryPath, content.replace(STYLE_TAG_PATTERN, `<style lang="${lang}"`));
1969
+ }
1970
+ }
1971
+ const PREPROCESSOR_EXTENSIONS = {
1972
+ scss: "scss",
1973
+ less: "less",
1974
+ stylus: "styl"
1975
+ };
1976
+ const SKIPPED_DIR_NAMES = /* @__PURE__ */ new Set([
1977
+ "ios",
1978
+ "android",
1979
+ "node_modules"
1980
+ ]);
1981
+ const APP_COMPONENT_FILENAMES = /* @__PURE__ */ new Set([
1982
+ "App.tsx",
1983
+ "App.jsx",
1984
+ "App.ts",
1985
+ "App.vue",
1986
+ "App.svelte"
1987
+ ]);
1988
+ const STARTER_CSS_CONTENT = `.container {
1989
+ flex: 1;
1990
+ align-items: center;
1991
+ justify-content: center;
1992
+ }
1993
+ `;
1994
+ function findAppComponentDir(dir) {
1995
+ for (const entry of fs.readdirSync(dir, { withFileTypes: true })) {
1996
+ const entryPath = path.join(dir, entry.name);
1997
+ if (entry.isDirectory()) {
1998
+ if (SKIPPED_DIR_NAMES.has(entry.name)) continue;
1999
+ const found = findAppComponentDir(entryPath);
2000
+ if (found !== void 0) return found;
2001
+ continue;
2002
+ }
2003
+ if (APP_COMPONENT_FILENAMES.has(entry.name)) return dir;
2004
+ }
2005
+ }
2006
+ function findAppCssFile(dir) {
2007
+ for (const entry of fs.readdirSync(dir, { withFileTypes: true })) {
2008
+ if (entry.isDirectory()) {
2009
+ if (SKIPPED_DIR_NAMES.has(entry.name)) continue;
2010
+ const found = findAppCssFile(path.join(dir, entry.name));
2011
+ if (found !== void 0) return found;
2012
+ continue;
2013
+ }
2014
+ if (entry.name === "App.css") return path.join(dir, entry.name);
2015
+ }
2016
+ }
2017
+ function replaceInTextFiles(dir, from, to) {
2018
+ for (const entry of fs.readdirSync(dir, { withFileTypes: true })) {
2019
+ const entryPath = path.join(dir, entry.name);
2020
+ if (entry.isDirectory()) {
2021
+ if (SKIPPED_DIR_NAMES.has(entry.name)) continue;
2022
+ replaceInTextFiles(entryPath, from, to);
2023
+ continue;
2024
+ }
2025
+ const content = fs.readFileSync(entryPath, "utf8");
2026
+ if (content.includes(from)) fs.writeFileSync(entryPath, content.split(from).join(to));
2027
+ }
2028
+ }
2029
+ function renameStylesheetExtension(root, extension) {
2030
+ const cssFile = findAppCssFile(root);
2031
+ if (cssFile === void 0) return;
2032
+ fs.renameSync(cssFile, path.join(path.dirname(cssFile), `App.${extension}`));
2033
+ replaceInTextFiles(root, "'./App.css'", `'./App.${extension}'`);
2034
+ }
2035
+ function applyStyling(root, options) {
2036
+ const { styling, jsTemplateDir, hasNavigation, hasTypescript, templatesRoot } = options;
2037
+ if (styling === "css") return;
2038
+ if (styling === "css-modules" || styling === "stylesheet") {
2039
+ renderTemplate(path.join(templatesRoot, "styling", "js", jsTemplateDir, styling), root, { hasTypescript });
2040
+ if (hasNavigation) renderTemplate(path.join(templatesRoot, "styling", "navigation", jsTemplateDir, styling), root, { hasTypescript });
2041
+ const orphanedCss = findAppCssFile(root);
2042
+ if (orphanedCss !== void 0) fs.rmSync(orphanedCss, { force: true });
2043
+ if (styling === "css-modules") {
2044
+ const appDir = findAppComponentDir(root);
2045
+ if (appDir !== void 0) fs.writeFileSync(path.join(appDir, "App.module.css"), STARTER_CSS_CONTENT);
2046
+ }
2047
+ return;
2048
+ }
2049
+ if (INLINE_STYLE_BLOCK_FRAMEWORKS.has(jsTemplateDir)) {
2050
+ addStyleLangAttribute(root, styling);
2051
+ renameStylesheetExtension(root, PREPROCESSOR_EXTENSIONS[styling]);
2052
+ return;
2053
+ }
2054
+ renameStylesheetExtension(root, PREPROCESSOR_EXTENSIONS[styling]);
2055
+ }
2056
+ //#endregion
2057
+ //#region src/utils/native-identity.ts
2058
+ function sanitizeNativeAppName(appName) {
2059
+ const pascalCase = (appName.match(/[a-zA-Z0-9]+/g) ?? []).map((word) => word.charAt(0).toUpperCase() + word.slice(1)).join("");
2060
+ return pascalCase === "" || /^[0-9]/.test(pascalCase) ? `App${pascalCase}` : pascalCase;
2061
+ }
2062
+ function defaultBundleId(nativeAppName) {
2063
+ return `com.${nativeAppName.toLowerCase()}`;
2064
+ }
2065
+ const BUNDLE_ID_PATTERN = /^[a-zA-Z][a-zA-Z0-9_]*(\.[a-zA-Z][a-zA-Z0-9_]*)+$/;
2066
+ function isValidBundleId(value) {
2067
+ return BUNDLE_ID_PATTERN.test(value);
2068
+ }
2069
+ //#endregion
2070
+ //#region src/utils/package-name.ts
2071
+ function toValidPackageName(name) {
2072
+ return name.trim().toLowerCase().replace(/\s+/g, "-").replace(/^[._]/, "").replace(/[^a-z0-9-~]+/g, "-");
2073
+ }
2074
+ //#endregion
2075
+ //#region src/generate.ts
2076
+ var TargetDirNotEmptyError = class extends Error {
2077
+ targetDir;
2078
+ constructor(targetDir) {
2079
+ super(`"${targetDir}" already exists and is not empty.`);
2080
+ this.targetDir = targetDir;
2081
+ this.name = "TargetDirNotEmptyError";
2082
+ }
2083
+ };
2084
+ function resolveTemplatesRoot() {
2085
+ const packageDir = path.dirname(fileURLToPath(import.meta.url));
2086
+ const sibling = path.join(packageDir, "templates");
2087
+ return fs.existsSync(sibling) ? sibling : path.resolve(packageDir, "../templates");
2088
+ }
2089
+ const templatesRoot = resolveTemplatesRoot();
2090
+ function isEmptyDir(dir) {
2091
+ if (!fs.existsSync(dir)) return true;
2092
+ const entries = fs.readdirSync(dir);
2093
+ return entries.length === 0 || entries.length === 1 && entries[0] === ".git";
2094
+ }
2095
+ function scaffoldApp(options) {
2096
+ const root = path.resolve(process.cwd(), options.appName);
2097
+ const jsTemplateDir = resolveJsTemplateDir(options.framework, options.vueFlavor);
2098
+ if (!isEmptyDir(root)) throw new TargetDirNotEmptyError(root);
2099
+ fs.mkdirSync(root, { recursive: true });
2100
+ const packageNameSource = options.appName === "." ? path.basename(root) : options.appName;
2101
+ fs.writeFileSync(path.join(root, "package.json"), `${JSON.stringify({
2102
+ name: toValidPackageName(packageNameSource),
2103
+ version: "0.0.1",
2104
+ private: true
2105
+ }, null, 2)}\n`);
2106
+ renderTemplate(path.join(templatesRoot, "native"), root, { hasTypescript: options.hasTypescript });
2107
+ renderTemplate(path.join(templatesRoot, "js", jsTemplateDir), root, { hasTypescript: options.hasTypescript });
2108
+ applyBootsplashLogo(root, templatesRoot, options.framework);
2109
+ const hasExpoModules = options.hasExpoModules || (options.expoPackages?.size ?? 0) > 0;
2110
+ if (options.hasNavigation) {
2111
+ const navigationLayerRoot = path.join(templatesRoot, "layers", "navigation");
2112
+ renderTemplate(path.join(navigationLayerRoot, "package.json.fragment.json"), path.join(root, "package.json.fragment.json"));
2113
+ renderTemplate(path.join(navigationLayerRoot, "app", jsTemplateDir), root, { hasTypescript: options.hasTypescript });
2114
+ }
2115
+ if (hasExpoModules) renderTemplate(path.join(templatesRoot, "layers", "expo-modules"), root);
2116
+ if (options.hasSplashScreen) {
2117
+ const splashScreenLayerRoot = path.join(templatesRoot, "layers", "splash-screen");
2118
+ renderTemplate(path.join(splashScreenLayerRoot, "package.json.fragment.json"), path.join(root, "package.json.fragment.json"));
2119
+ renderTemplate(path.join(splashScreenLayerRoot, "native"), root);
2120
+ }
2121
+ if (options.hasSlider) renderTemplate(path.join(templatesRoot, "layers", "slider", "package.json.fragment.json"), path.join(root, "package.json.fragment.json"));
2122
+ for (const layerName of options.expoPackages ?? []) renderTemplate(path.join(templatesRoot, "layers", layerName, "package.json.fragment.json"), path.join(root, "package.json.fragment.json"));
2123
+ if (options.hasTesting) {
2124
+ const testingLayerRoot = path.join(templatesRoot, "layers", "testing");
2125
+ const fragmentName = options.framework === "angular" ? "angular" : "base";
2126
+ renderTemplate(path.join(testingLayerRoot, "fragment", fragmentName, "package.json.fragment.json"), path.join(root, "package.json.fragment.json"));
2127
+ renderTemplate(path.join(testingLayerRoot, "detox.config.js"), path.join(root, "detox.config.js"));
2128
+ renderTemplate(path.join(testingLayerRoot, "e2e"), path.join(root, "e2e"), { hasTypescript: true });
2129
+ }
2130
+ if (hasExpoModules) {
2131
+ applyExpoModulesAndroidManifest(root);
2132
+ applyExpoModulesPodfilePlatform(root);
2133
+ applyExpoModulesPodfileAutolinking(root);
2134
+ applyExpoModulesXcodeDeploymentTarget(root);
2135
+ }
2136
+ applyStyling(root, {
2137
+ styling: options.styling,
2138
+ jsTemplateDir,
2139
+ hasNavigation: options.hasNavigation,
2140
+ hasTypescript: options.hasTypescript,
2141
+ templatesRoot
2142
+ });
2143
+ if (options.hasSplashScreen) applySplashScreenAppHide(root, { framework: options.framework });
2144
+ applyAppIdentity(root, {
2145
+ nativeAppName: sanitizeNativeAppName(options.appName),
2146
+ bundleId: options.bundleId
2147
+ });
2148
+ return root;
2149
+ }
2150
+ //#endregion
2151
+ //#region src/utils/find-ios-app-dir.ts
2152
+ function findIosAppDir(root) {
2153
+ const iosDir = path.join(root, "ios");
2154
+ if (!fs.existsSync(iosDir)) return void 0;
2155
+ for (const entry of fs.readdirSync(iosDir, { withFileTypes: true })) if (entry.isDirectory() && entry.name !== "Pods") return path.join(iosDir, entry.name);
2156
+ }
2157
+ //#endregion
2158
+ //#region src/utils/apply-expo-modules-plist.ts
2159
+ const USAGE_DESCRIPTIONS = [
2160
+ ["NSFaceIDUsageDescription", "This app uses Face ID to authenticate you."],
2161
+ ["NSMotionUsageDescription", "This app uses motion sensor data."],
2162
+ ["NSUserTrackingUsageDescription", "This app tracks your activity across other apps and websites."]
2163
+ ];
2164
+ function applyExpoModulesInfoPlist(root) {
2165
+ const iosAppDir = findIosAppDir(root);
2166
+ if (iosAppDir === void 0) return;
2167
+ const plistPath = path.join(iosAppDir, "Info.plist");
2168
+ if (!fs.existsSync(plistPath)) return;
2169
+ const plist = fs.readFileSync(plistPath, "utf8");
2170
+ const updated = USAGE_DESCRIPTIONS.reduce((current, [key, description]) => {
2171
+ if (current.includes(`<key>${key}</key>`)) return current;
2172
+ return current.replace("</dict>\n</plist>", `\t<key>${key}</key>\n\t<string>${description}</string>\n</dict>\n</plist>`);
2173
+ }, plist);
2174
+ if (updated !== plist) fs.writeFileSync(plistPath, updated);
2175
+ }
2176
+ //#endregion
2177
+ //#region src/utils/apply-splash-screen-app-delegate.ts
2178
+ const CUSTOMIZE_OPEN = /override func customize\(_ rootView: RCTRootView\) \{\n/;
2179
+ const REACT_IMPORT = "import React\n";
2180
+ function applySplashScreenAppDelegate(root) {
2181
+ const iosAppDir = findIosAppDir(root);
2182
+ if (iosAppDir === void 0) return;
2183
+ const appDelegatePath = path.join(iosAppDir, "AppDelegate.swift");
2184
+ if (!fs.existsSync(appDelegatePath)) return;
2185
+ const source = fs.readFileSync(appDelegatePath, "utf8");
2186
+ if (source.includes("RNBootSplash.initWithStoryboard(")) return;
2187
+ if (!source.includes(REACT_IMPORT)) return;
2188
+ const updated = source.includes("import RNBootSplash") ? source : source.replace(REACT_IMPORT, `${REACT_IMPORT}import RNBootSplash\n`);
2189
+ const withInit = CUSTOMIZE_OPEN.test(updated) ? updated.replace(CUSTOMIZE_OPEN, (match) => `${match} RNBootSplash.initWithStoryboard("BootSplash", rootView: rootView)\n`) : updated.replace(/class ReactNativeDelegate: RCTDefaultReactNativeFactoryDelegate \{\n/, (match) => `${match} override func customize(_ rootView: RCTRootView) {\n super.customize(rootView)
2190
+ RNBootSplash.initWithStoryboard("BootSplash", rootView: rootView)
2191
+ }
2192
+
2193
+ `);
2194
+ fs.writeFileSync(appDelegatePath, withInit);
2195
+ }
2196
+ //#endregion
2197
+ //#region src/utils/apply-splash-screen-main-activity.ts
2198
+ function findMainActivityKt(dir) {
2199
+ for (const entry of fs.readdirSync(dir, { withFileTypes: true })) {
2200
+ const entryPath = path.join(dir, entry.name);
2201
+ if (entry.isDirectory()) {
2202
+ const found = findMainActivityKt(entryPath);
2203
+ if (found !== void 0) return found;
2204
+ continue;
2205
+ }
2206
+ if (entry.name === "MainActivity.kt") return entryPath;
2207
+ }
2208
+ }
2209
+ const ONCREATE_OPEN = /override fun onCreate\(savedInstanceState: Bundle\?\) \{\n/;
2210
+ const REACT_ACTIVITY_IMPORT = "import com.facebook.react.ReactActivity\n";
2211
+ function applySplashScreenMainActivity(root) {
2212
+ const javaDir = path.join(root, "android/app/src/main/java");
2213
+ if (!fs.existsSync(javaDir)) return;
2214
+ const mainActivityPath = findMainActivityKt(javaDir);
2215
+ if (mainActivityPath === void 0) return;
2216
+ const source = fs.readFileSync(mainActivityPath, "utf8");
2217
+ if (source.includes("RNBootSplash.init(")) return;
2218
+ if (!source.includes(REACT_ACTIVITY_IMPORT)) return;
2219
+ let updated = source.includes("import com.zoontek.rnbootsplash.RNBootSplash") ? source : source.replace(REACT_ACTIVITY_IMPORT, `${REACT_ACTIVITY_IMPORT}import com.zoontek.rnbootsplash.RNBootSplash\n`);
2220
+ if (!updated.includes("import android.os.Bundle")) updated = updated.replace(REACT_ACTIVITY_IMPORT, `import android.os.Bundle\n${REACT_ACTIVITY_IMPORT}`);
2221
+ updated = ONCREATE_OPEN.test(updated) ? updated.replace(ONCREATE_OPEN, (match) => `${match} RNBootSplash.init(this, R.style.BootTheme)\n`) : updated.replace("class MainActivity : ReactActivity() {\n", "class MainActivity : ReactActivity() {\n\n override fun onCreate(savedInstanceState: Bundle?) {\n RNBootSplash.init(this, R.style.BootTheme)\n super.onCreate(savedInstanceState)\n }\n");
2222
+ fs.writeFileSync(mainActivityPath, updated);
2223
+ }
2224
+ //#endregion
2225
+ //#region src/utils/apply-splash-screen-manifest.ts
2226
+ const MAIN_ACTIVITY_BLOCK = /<activity\b[^>]*android:name="\.MainActivity"[^>]*>/;
2227
+ function applySplashScreenManifest(root) {
2228
+ const manifestPath = path.join(root, "android/app/src/main/AndroidManifest.xml");
2229
+ if (!fs.existsSync(manifestPath)) return;
2230
+ const manifest = fs.readFileSync(manifestPath, "utf8");
2231
+ const match = manifest.match(MAIN_ACTIVITY_BLOCK);
2232
+ if (match === null) return;
2233
+ const block = match[0];
2234
+ if (block.includes("@style/BootTheme")) return;
2235
+ if (!block.includes("android:theme=\"@style/AppTheme\"")) return;
2236
+ const updatedBlock = block.replace("android:theme=\"@style/AppTheme\"", "android:theme=\"@style/BootTheme\"");
2237
+ fs.writeFileSync(manifestPath, manifest.replace(block, updatedBlock));
2238
+ }
2239
+ //#endregion
2240
+ //#region src/utils/apply-splash-screen-styles.ts
2241
+ const BOOT_THEME_STYLE = ` <style name="BootTheme" parent="Theme.BootSplash">
2242
+ <item name="bootSplashBackground">@color/bootsplash_background</item>
2243
+ <item name="bootSplashLogo">@drawable/bootsplash_logo</item>
2244
+ <item name="postBootSplashTheme">@style/AppTheme</item>
2245
+ </style>
2246
+ `;
2247
+ function applySplashScreenStyles(root) {
2248
+ const stylesPath = path.join(root, "android/app/src/main/res/values/styles.xml");
2249
+ if (!fs.existsSync(stylesPath)) return;
2250
+ const styles = fs.readFileSync(stylesPath, "utf8");
2251
+ if (styles.includes("name=\"BootTheme\"")) return;
2252
+ if (!styles.includes("</resources>")) return;
2253
+ fs.writeFileSync(stylesPath, styles.replace("</resources>", `${BOOT_THEME_STYLE}</resources>`));
2254
+ }
2255
+ //#endregion
2256
+ //#region src/add-layers.ts
2257
+ function applyDependencyOnlyLayer(root, layerName) {
2258
+ renderTemplate(path.join(templatesRoot, "layers", layerName, "package.json.fragment.json"), path.join(root, "package.json.fragment.json"));
2259
+ }
2260
+ function applyExpoModulesLayer(root) {
2261
+ applyDependencyOnlyLayer(root, "expo-modules");
2262
+ if (fs.existsSync(path.join(root, "android/app/src/main/AndroidManifest.xml"))) applyExpoModulesAndroidManifest(root);
2263
+ if (fs.existsSync(path.join(root, "ios"))) {
2264
+ applyExpoModulesInfoPlist(root);
2265
+ applyExpoModulesPodfilePlatform(root);
2266
+ applyExpoModulesPodfileAutolinking(root);
2267
+ applyExpoModulesXcodeDeploymentTarget(root);
2268
+ }
2269
+ }
2270
+ function applySplashScreenLayer(root, framework) {
2271
+ applyDependencyOnlyLayer(root, "splash-screen");
2272
+ applySplashScreenManifest(root);
2273
+ applySplashScreenStyles(root);
2274
+ applySplashScreenMainActivity(root);
2275
+ applySplashScreenAppDelegate(root);
2276
+ applySplashScreenAppHide(root, { framework });
2277
+ applyBootsplashLogo(root, templatesRoot, framework);
2278
+ }
2279
+ async function applyTestingLayer(root, framework, confirmOverwrite) {
2280
+ const testingLayerRoot = path.join(templatesRoot, "layers", "testing");
2281
+ const fragmentName = framework === "angular" ? "angular" : "base";
2282
+ renderTemplate(path.join(testingLayerRoot, "fragment", fragmentName, "package.json.fragment.json"), path.join(root, "package.json.fragment.json"));
2283
+ const detoxConfigPath = path.join(root, "detox.config.js");
2284
+ const e2eDirPath = path.join(root, "e2e");
2285
+ if ((fs.existsSync(detoxConfigPath) || fs.existsSync(e2eDirPath)) && !await confirmOverwrite()) return false;
2286
+ renderTemplate(path.join(testingLayerRoot, "detox.config.js"), detoxConfigPath);
2287
+ renderTemplate(path.join(testingLayerRoot, "e2e"), e2eDirPath, { hasTypescript: true });
2288
+ return true;
2289
+ }
2290
+ async function addLayersToApp(options) {
2291
+ const appliedLayers = [];
2292
+ const skippedLayers = [];
2293
+ for (const layer of options.layers) {
2294
+ if (layer === "testing") {
2295
+ (await applyTestingLayer(options.root, options.framework, options.confirmTestingOverwrite) ? appliedLayers : skippedLayers).push(layer);
2296
+ continue;
2297
+ }
2298
+ if (layer === "expo-modules") applyExpoModulesLayer(options.root);
2299
+ else if (layer === "splash-screen") applySplashScreenLayer(options.root, options.framework);
2300
+ else applyDependencyOnlyLayer(options.root, layer);
2301
+ appliedLayers.push(layer);
2302
+ }
2303
+ return {
2304
+ appliedLayers,
2305
+ skippedLayers
2306
+ };
2307
+ }
2308
+ //#endregion
2309
+ //#region src/detect-added-layers.ts
2310
+ const LAYER_MARKER_DEPENDENCY = [
2311
+ ["navigation", "@symbiote-native/navigation"],
2312
+ ["expo-modules", "@symbiote-native/expo-modules-link"],
2313
+ ["testing", "detox"],
2314
+ ["slider", "@symbiote-native/slider"],
2315
+ ["splash-screen", "@symbiote-native/splash-screen"],
2316
+ ...EXPO_PACKAGE_LAYERS.map((layer) => [layer.id, layer.symbiotePackage])
2317
+ ];
2318
+ function detectAddedLayers(dependencies) {
2319
+ return new Set(LAYER_MARKER_DEPENDENCY.filter(([, dependencyName]) => dependencyName in dependencies).map(([layer]) => layer));
2320
+ }
2321
+ //#endregion
2322
+ //#region src/detect-framework.ts
2323
+ const SYMBIOTE_ADAPTER_BY_DEPENDENCY = [
2324
+ ["@symbiote-native/angular", "angular"],
2325
+ ["@symbiote-native/vue", "vue"],
2326
+ ["@symbiote-native/svelte", "svelte"],
2327
+ ["@symbiote-native/solid", "solid"],
2328
+ ["@symbiote-native/react", "react"]
2329
+ ];
2330
+ function detectSymbioteFrameworkFromDependencies(dependencies) {
2331
+ return SYMBIOTE_ADAPTER_BY_DEPENDENCY.find(([dependencyName]) => dependencyName in dependencies)?.[1];
2332
+ }
2333
+ function isRecord(value) {
2334
+ return typeof value === "object" && value !== null && !Array.isArray(value);
2335
+ }
2336
+ function toStringRecord(value) {
2337
+ if (!isRecord(value)) return {};
2338
+ const result = {};
2339
+ for (const [key, entry] of Object.entries(value)) if (typeof entry === "string") result[key] = entry;
2340
+ return result;
2341
+ }
2342
+ function readCwdDependencies(cwd = process.cwd()) {
2343
+ try {
2344
+ const raw = readFileSync(join(cwd, "package.json"), "utf8");
2345
+ const parsed = JSON.parse(raw);
2346
+ if (!isRecord(parsed)) return {};
2347
+ return {
2348
+ ...toStringRecord(parsed.dependencies),
2349
+ ...toStringRecord(parsed.devDependencies)
2350
+ };
2351
+ } catch {
2352
+ return {};
2353
+ }
2354
+ }
2355
+ //#endregion
2356
+ //#region src/get-command.ts
2357
+ function getCommand(packageManager, script) {
2358
+ if (script === "install") return packageManager === "yarn" ? "yarn" : `${packageManager} install`;
2359
+ return packageManager === "npm" ? `npm run ${script}` : `${packageManager} ${script}`;
2360
+ }
2361
+ //#endregion
2362
+ //#region src/detect-package-manager.ts
2363
+ const USER_AGENT_PREFIXES = [
2364
+ ["pnpm", "pnpm"],
2365
+ ["yarn", "yarn"],
2366
+ ["npm", "npm"]
2367
+ ];
2368
+ function detectPackageManagerFromUserAgent(userAgent = process.env.npm_config_user_agent) {
2369
+ if (userAgent === void 0) return void 0;
2370
+ return USER_AGENT_PREFIXES.find(([prefix]) => userAgent.startsWith(prefix))?.[1];
2371
+ }
2372
+ //#endregion
2373
+ //#region src/prompts.ts
2374
+ function assertNotCancelled(answer) {
2375
+ if (isCancel(answer)) {
2376
+ cancel("Cancelled.");
2377
+ process.exit(1);
2378
+ }
2379
+ }
2380
+ function isInteractive() {
2381
+ return process.stdin.isTTY === true;
2382
+ }
2383
+ async function resolveAppName(appName) {
2384
+ if (appName !== void 0) return appName;
2385
+ if (!isInteractive()) throw new CliUsageError("No app name given and not running in an interactive terminal — pass it as the first argument, e.g. \"new my-app\".");
2386
+ const answer = await text({
2387
+ message: "App name?",
2388
+ placeholder: "my-app"
2389
+ });
2390
+ assertNotCancelled(answer);
2391
+ return answer;
2392
+ }
2393
+ async function resolveFramework(framework) {
2394
+ if (framework !== void 0) return framework;
2395
+ if (!isInteractive()) throw new CliUsageError("No --framework given and not running in an interactive terminal — pass --framework react|vue|angular|solid|svelte.");
2396
+ const answer = await select({
2397
+ message: "Which framework?",
2398
+ options: [
2399
+ {
2400
+ value: "react",
2401
+ label: "React"
2402
+ },
2403
+ {
2404
+ value: "vue",
2405
+ label: "Vue"
2406
+ },
2407
+ {
2408
+ value: "angular",
2409
+ label: "Angular"
2410
+ },
2411
+ {
2412
+ value: "solid",
2413
+ label: "Solid"
2414
+ },
2415
+ {
2416
+ value: "svelte",
2417
+ label: "Svelte"
2418
+ }
2419
+ ]
2420
+ });
2421
+ assertNotCancelled(answer);
2422
+ return answer;
2423
+ }
2424
+ async function resolveVueFlavor(vueFlavor) {
2425
+ if (vueFlavor !== void 0) return vueFlavor;
2426
+ if (!isInteractive()) throw new CliUsageError("No --vue-flavor given and not running in an interactive terminal — pass --vue-flavor tsx|sfc.");
2427
+ const answer = await select({
2428
+ message: "Vue: TSX or SFC (.vue) components?",
2429
+ options: [{
2430
+ value: "sfc",
2431
+ label: "SFC (.vue single-file components)"
2432
+ }, {
2433
+ value: "tsx",
2434
+ label: "TSX (JSX-flavored, no .vue files)"
2435
+ }]
2436
+ });
2437
+ assertNotCancelled(answer);
2438
+ return answer;
2439
+ }
2440
+ async function resolveBundleId(bundleId, nativeAppName) {
2441
+ if (bundleId !== void 0) {
2442
+ if (!isValidBundleId(bundleId)) throw new Error(`Invalid --bundle-id "${bundleId}": reverse-DNS only (letters, digits, underscores, dots) — e.g. "com.example.app".`);
2443
+ return bundleId;
2444
+ }
2445
+ const computedDefault = defaultBundleId(nativeAppName);
2446
+ if (!isInteractive()) return computedDefault;
2447
+ const answer = await text({
2448
+ message: "Bundle identifier (iOS + Android)?",
2449
+ initialValue: computedDefault,
2450
+ validate: (value) => isValidBundleId(value ?? "") ? void 0 : "Reverse-DNS only: letters, digits, underscores, dots — e.g. \"com.example.app\"."
2451
+ });
2452
+ assertNotCancelled(answer);
2453
+ return answer;
2454
+ }
2455
+ async function resolveOverwrite(targetDir, force) {
2456
+ if (force) return true;
2457
+ if (!isInteractive()) throw new CliUsageError(`"${targetDir}" already exists and is not empty, and not running in an interactive terminal — pass --force to overwrite it, or scaffold into an empty directory.`);
2458
+ const answer = await confirm({
2459
+ message: `"${targetDir}" already exists and is not empty. Empty it and continue?`,
2460
+ initialValue: false
2461
+ });
2462
+ assertNotCancelled(answer);
2463
+ return answer;
2464
+ }
2465
+ async function resolveStyling(styling) {
2466
+ if (styling !== void 0) return styling;
2467
+ if (!isInteractive()) return "css";
2468
+ const answer = await select({
2469
+ message: "How should the app style itself?",
2470
+ options: [
2471
+ {
2472
+ value: "css",
2473
+ label: "CSS classes",
2474
+ hint: "plain .css, recommended"
2475
+ },
2476
+ {
2477
+ value: "css-modules",
2478
+ label: "CSS Modules",
2479
+ hint: "scoped .module.css classes"
2480
+ },
2481
+ {
2482
+ value: "scss",
2483
+ label: "SCSS"
2484
+ },
2485
+ {
2486
+ value: "less",
2487
+ label: "LESS"
2488
+ },
2489
+ {
2490
+ value: "stylus",
2491
+ label: "Stylus"
2492
+ },
2493
+ {
2494
+ value: "stylesheet",
2495
+ label: "StyleSheet.create",
2496
+ hint: "JS style objects"
2497
+ }
2498
+ ],
2499
+ initialValue: "css"
2500
+ });
2501
+ assertNotCancelled(answer);
2502
+ return answer;
2503
+ }
2504
+ async function resolveFeatures(framework, flags) {
2505
+ if (framework === "angular" && flags.isJavascript) throw new CliUsageError("--framework angular requires TypeScript — drop --javascript.");
2506
+ const typescriptForced = framework === "angular" ? true : flags.isJavascript ? false : void 0;
2507
+ const options = [
2508
+ ...typescriptForced === void 0 ? [{
2509
+ value: "typescript",
2510
+ label: "TypeScript"
2511
+ }] : [],
2512
+ ...flags.hasNavigation ? [] : [{
2513
+ value: "navigation",
2514
+ label: "Navigation",
2515
+ hint: "@symbiote-native/navigation"
2516
+ }],
2517
+ ...flags.hasExpoModules ? [] : [{
2518
+ value: "expo-modules",
2519
+ label: "Expo-modules autolinking",
2520
+ hint: "@symbiote-native/expo-modules-link"
2521
+ }],
2522
+ ...flags.hasTesting ? [] : [{
2523
+ value: "testing",
2524
+ label: "E2E testing",
2525
+ hint: "Detox"
2526
+ }],
2527
+ ...flags.hasSplashScreen ? [] : [{
2528
+ value: "splash-screen",
2529
+ label: "Splash screen",
2530
+ hint: "@symbiote-native/splash-screen"
2531
+ }],
2532
+ ...flags.hasSlider ? [] : [{
2533
+ value: "slider",
2534
+ label: "Slider",
2535
+ hint: "@symbiote-native/slider"
2536
+ }],
2537
+ ...EXPO_PACKAGE_LAYERS.filter((layer) => !flags.expoPackages.has(layer.id)).map((layer) => ({
2538
+ value: layer.id,
2539
+ label: layer.label,
2540
+ hint: layer.symbiotePackage
2541
+ }))
2542
+ ];
2543
+ if (options.length === 0 || !isInteractive()) return {
2544
+ hasTypescript: typescriptForced ?? true,
2545
+ hasNavigation: flags.hasNavigation,
2546
+ hasExpoModules: flags.hasExpoModules || flags.expoPackages.size > 0,
2547
+ hasTesting: flags.hasTesting,
2548
+ hasSplashScreen: flags.hasSplashScreen,
2549
+ hasSlider: flags.hasSlider,
2550
+ expoPackages: flags.expoPackages
2551
+ };
2552
+ const answer = await multiselect({
2553
+ message: "Which features?",
2554
+ options,
2555
+ initialValues: typescriptForced === void 0 ? ["typescript"] : [],
2556
+ required: false
2557
+ });
2558
+ assertNotCancelled(answer);
2559
+ const selected = new Set(answer);
2560
+ const expoPackages = /* @__PURE__ */ new Set([...flags.expoPackages, ...EXPO_PACKAGE_LAYERS.filter((layer) => selected.has(layer.id)).map((layer) => layer.id)]);
2561
+ return {
2562
+ hasTypescript: typescriptForced ?? selected.has("typescript"),
2563
+ hasNavigation: flags.hasNavigation || selected.has("navigation"),
2564
+ hasExpoModules: flags.hasExpoModules || selected.has("expo-modules") || expoPackages.size > 0,
2565
+ hasTesting: flags.hasTesting || selected.has("testing"),
2566
+ hasSplashScreen: flags.hasSplashScreen || selected.has("splash-screen"),
2567
+ hasSlider: flags.hasSlider || selected.has("slider"),
2568
+ expoPackages
2569
+ };
2570
+ }
2571
+ async function resolveAddOverwrite(hasForce, message) {
2572
+ if (hasForce) return true;
2573
+ if (!isInteractive()) return false;
2574
+ const answer = await confirm({
2575
+ message,
2576
+ initialValue: false
2577
+ });
2578
+ assertNotCancelled(answer);
2579
+ return answer;
2580
+ }
2581
+ const ADD_LAYER_OPTIONS = [
2582
+ {
2583
+ value: "navigation",
2584
+ label: "Navigation",
2585
+ hint: "@symbiote-native/navigation"
2586
+ },
2587
+ {
2588
+ value: "expo-modules",
2589
+ label: "Expo-modules autolinking",
2590
+ hint: "@symbiote-native/expo-modules-link"
2591
+ },
2592
+ {
2593
+ value: "testing",
2594
+ label: "E2E testing",
2595
+ hint: "Detox"
2596
+ },
2597
+ {
2598
+ value: "splash-screen",
2599
+ label: "Splash screen",
2600
+ hint: "@symbiote-native/splash-screen"
2601
+ },
2602
+ {
2603
+ value: "slider",
2604
+ label: "Slider",
2605
+ hint: "@symbiote-native/slider"
2606
+ },
2607
+ ...EXPO_PACKAGE_LAYERS.map((layer) => ({
2608
+ value: layer.id,
2609
+ label: layer.label,
2610
+ hint: layer.symbiotePackage
2611
+ }))
2612
+ ];
2613
+ function explicitLayersFromFlags(flags) {
2614
+ const explicit = [];
2615
+ if (flags.hasNavigation) explicit.push("navigation");
2616
+ if (flags.hasExpoModules) explicit.push("expo-modules");
2617
+ if (flags.hasTesting) explicit.push("testing");
2618
+ if (flags.hasSplashScreen) explicit.push("splash-screen");
2619
+ if (flags.hasSlider) explicit.push("slider");
2620
+ explicit.push(...flags.expoPackages ?? []);
2621
+ return explicit;
2622
+ }
2623
+ function buildAddLayerOptions(alreadyAdded) {
2624
+ const withDisabledState = ADD_LAYER_OPTIONS.map((option) => {
2625
+ const isAlreadyAdded = alreadyAdded.has(option.value);
2626
+ return {
2627
+ ...option,
2628
+ hint: isAlreadyAdded ? "already added" : option.hint,
2629
+ disabled: isAlreadyAdded
2630
+ };
2631
+ });
2632
+ return {
2633
+ "Core layers": withDisabledState.filter((option) => !isExpoPackageLayerName(option.value)),
2634
+ "Expo packages": withDisabledState.filter((option) => isExpoPackageLayerName(option.value))
2635
+ };
2636
+ }
2637
+ function withImpliedExpoModules(layers) {
2638
+ return layers.some((layer) => isExpoPackageLayerName(layer)) && !layers.includes("expo-modules") ? [...layers, "expo-modules"] : [...layers];
2639
+ }
2640
+ function dropAlreadyAdded(layers, alreadyAdded, hasForce) {
2641
+ return hasForce ? [...layers] : layers.filter((layer) => !alreadyAdded.has(layer));
2642
+ }
2643
+ async function resolveAddLayers(flags, alreadyAdded, hasForce = false) {
2644
+ const explicit = explicitLayersFromFlags(flags);
2645
+ if (explicit.length > 0) return withImpliedExpoModules(dropAlreadyAdded(explicit, alreadyAdded, hasForce));
2646
+ if (ADD_LAYER_OPTIONS.every((option) => alreadyAdded.has(option.value))) return [];
2647
+ if (!isInteractive()) throw new CliUsageError("No layer flags given and not running in an interactive terminal — pass at least one of --navigation/--expo-modules/--testing/--splash-screen/--slider, or an Expo-package flag such as --battery/--sensors.");
2648
+ const answer = await groupMultiselect({
2649
+ message: "Which features to add?",
2650
+ options: buildAddLayerOptions(alreadyAdded),
2651
+ required: false
2652
+ });
2653
+ assertNotCancelled(answer);
2654
+ return withImpliedExpoModules(dropAlreadyAdded(answer, alreadyAdded, hasForce));
2655
+ }
2656
+ async function resolvePackageManager(packageManager) {
2657
+ const detected = packageManager ?? detectPackageManagerFromUserAgent();
2658
+ if (detected !== void 0) return detected;
2659
+ if (!isInteractive()) return "npm";
2660
+ const answer = await select({
2661
+ message: "Which package manager?",
2662
+ options: [
2663
+ {
2664
+ value: "npm",
2665
+ label: "npm"
2666
+ },
2667
+ {
2668
+ value: "pnpm",
2669
+ label: "pnpm"
2670
+ },
2671
+ {
2672
+ value: "yarn",
2673
+ label: "yarn"
2674
+ }
2675
+ ]
2676
+ });
2677
+ assertNotCancelled(answer);
2678
+ return answer;
2679
+ }
2680
+ //#endregion
2681
+ //#region src/commands/add.ts
2682
+ function resolveFrameworkForAdd(explicit, cwd = process.cwd()) {
2683
+ const detected = detectSymbioteFrameworkFromDependencies(readCwdDependencies(cwd));
2684
+ if (detected === void 0) throw new NotSymbioteAppError();
2685
+ if (explicit !== void 0 && explicit !== detected) throw new CliUsageError(`--framework ${explicit} was given, but this project's package.json declares @symbiote-native/${detected} — pass --framework ${detected} or omit the flag.`);
2686
+ return detected;
2687
+ }
2688
+ async function runAdd(parsed) {
2689
+ intro("@symbiote-native/cli add");
2690
+ const cwd = process.cwd();
2691
+ const framework = resolveFrameworkForAdd(parsed.framework, cwd);
2692
+ const alreadyAdded = detectAddedLayers(readCwdDependencies(cwd));
2693
+ const layerFlags = {
2694
+ hasExpoModules: parsed.hasExpoModules,
2695
+ hasNavigation: parsed.hasNavigation,
2696
+ hasTesting: parsed.hasTesting,
2697
+ hasSlider: parsed.hasSlider,
2698
+ hasSplashScreen: parsed.hasSplashScreen,
2699
+ expoPackages: parsed.expoPackages
2700
+ };
2701
+ const layers = await resolveAddLayers(layerFlags, alreadyAdded, parsed.hasForce);
2702
+ const alreadyPresentSkips = parsed.hasForce ? [] : explicitLayersFromFlags(layerFlags).filter((layer) => alreadyAdded.has(layer));
2703
+ if (layers.length === 0) {
2704
+ const outro$1 = alreadyPresentSkips.length > 0 ? `Nothing to add — already present: ${alreadyPresentSkips.join(", ")}.` : "Nothing to add — every optional layer @symbiote-native/cli offers is already present.";
2705
+ outro(outro$1);
2706
+ return;
2707
+ }
2708
+ const result = await addLayersToApp({
2709
+ root: cwd,
2710
+ framework,
2711
+ layers,
2712
+ confirmTestingOverwrite: () => resolveAddOverwrite(parsed.hasForce, "\"detox.config.js\" / \"e2e/\" already exist. Overwrite them?")
2713
+ });
2714
+ const lines = [];
2715
+ if (result.appliedLayers.length > 0) {
2716
+ const packageManager = await resolvePackageManager(parsed.packageManager);
2717
+ lines.push(`Added: ${result.appliedLayers.join(", ")}.`, "", import_picocolors.default.bold(import_picocolors.default.green(` ${getCommand(packageManager, "install")}`)));
2718
+ }
2719
+ const allSkips = [...alreadyPresentSkips, ...result.skippedLayers];
2720
+ if (allSkips.length > 0) lines.push("", `Skipped (already present, left untouched): ${allSkips.join(", ")}.`);
2721
+ if (result.appliedLayers.includes("navigation")) lines.push("", "Wire it up in your App entry:", import_picocolors.default.dim(` import { Stack } from '@symbiote-native/navigation/${framework}';`));
2722
+ outro(lines.length > 0 ? lines.join("\n") : "Nothing changed.");
2723
+ }
2724
+ //#endregion
2725
+ //#region src/commands/new.ts
2726
+ async function runNew(parsed) {
2727
+ intro("@symbiote-native/cli new");
2728
+ const appName = await resolveAppName(parsed.appName);
2729
+ const targetDir = path.resolve(process.cwd(), appName);
2730
+ if (!isEmptyDir(targetDir)) {
2731
+ if (!await resolveOverwrite(targetDir, parsed.hasForce)) {
2732
+ cancel("Cancelled.");
2733
+ process.exit(1);
2734
+ }
2735
+ fs.rmSync(targetDir, {
2736
+ recursive: true,
2737
+ force: true
2738
+ });
2739
+ }
2740
+ const framework = await resolveFramework(parsed.framework);
2741
+ const vueFlavor = framework === "vue" ? await resolveVueFlavor(parsed.vueFlavor) : void 0;
2742
+ const bundleId = await resolveBundleId(parsed.bundleId, sanitizeNativeAppName(appName));
2743
+ const { hasTypescript, hasNavigation, hasExpoModules, hasTesting, hasSplashScreen, hasSlider, expoPackages } = await resolveFeatures(framework, parsed);
2744
+ const styling = await resolveStyling(parsed.styling);
2745
+ const packageManager = await resolvePackageManager(parsed.packageManager);
2746
+ const root = scaffoldApp({
2747
+ appName,
2748
+ framework,
2749
+ vueFlavor,
2750
+ hasTypescript,
2751
+ bundleId,
2752
+ hasExpoModules,
2753
+ hasNavigation,
2754
+ hasTesting,
2755
+ hasSplashScreen,
2756
+ hasSlider,
2757
+ expoPackages,
2758
+ styling,
2759
+ packageManager
2760
+ });
2761
+ const hasGitDir = fs.existsSync(path.join(root, ".git"));
2762
+ outro([
2763
+ `Scaffolded "${appName}" at ${root}.`,
2764
+ "",
2765
+ ...appName === "." ? [] : [import_picocolors.default.bold(import_picocolors.default.green(` cd ${appName}`))],
2766
+ import_picocolors.default.bold(import_picocolors.default.green(` ${getCommand(packageManager, "install")}`)),
2767
+ import_picocolors.default.bold(import_picocolors.default.green(` ${getCommand(packageManager, "dev")}`)),
2768
+ ...hasGitDir ? [] : [
2769
+ "",
2770
+ "Not a git repository yet:",
2771
+ import_picocolors.default.bold(import_picocolors.default.green(" git init && git add -A && git commit -m \"initial commit\""))
2772
+ ]
2773
+ ].join("\n"));
2774
+ }
2775
+ //#endregion
2776
+ //#region package.json
2777
+ var version = "0.0.1";
2778
+ //#endregion
2779
+ //#region src/index.ts
2780
+ function printHelp() {
2781
+ const expoPackageFlags = EXPO_PACKAGE_LAYERS.map((layer) => `--${layer.id}`).join(", ");
2782
+ console.log(`@symbiote-native/cli — scaffold a SymbioteNative app, or add it to an existing one.
2783
+
2784
+ Usage:
2785
+ npx @symbiote-native/cli new <app-name> [--framework react|vue|angular|solid|svelte] [--vue-flavor tsx|sfc]
2786
+ [--javascript] [--force] [--bundle-id com.example.app]
2787
+ [--styling css|css-modules|scss|less|stylus|stylesheet]
2788
+ [--navigation] [--expo-modules] [--testing] [--splash-screen] [--slider] [--pm npm|pnpm|yarn]
2789
+ [--<expo-package> ...] (one per Expo-backed package, implies --expo-modules)
2790
+ npx @symbiote-native/cli add [--navigation] [--expo-modules] [--testing] [--splash-screen] [--slider]
2791
+ [--<expo-package> ...] [--force] [--pm npm|pnpm|yarn]
2792
+ (run inside an existing @symbiote-native/* app)
2793
+
2794
+ npx @symbiote-native/cli --version print the CLI version
2795
+ npx @symbiote-native/cli --help print this message
2796
+
2797
+ <expo-package> flags: ${expoPackageFlags}
2798
+
2799
+ Flags left out of either command are asked for interactively.`);
2800
+ }
2801
+ async function main() {
2802
+ const parsed = parseArgv(process.argv.slice(2));
2803
+ switch (parsed.kind) {
2804
+ case "new":
2805
+ await runNew(parsed);
2806
+ return;
2807
+ case "add":
2808
+ await runAdd(parsed);
2809
+ return;
2810
+ case "help":
2811
+ printHelp();
2812
+ return;
2813
+ case "version":
2814
+ console.log(version);
2815
+ return;
2816
+ }
2817
+ }
2818
+ main().catch((error) => {
2819
+ if (error instanceof CliUsageError) {
2820
+ console.error(import_picocolors.default.red(`@symbiote-native/cli: ${error.message}`));
2821
+ process.exitCode = 1;
2822
+ return;
2823
+ }
2824
+ if (error instanceof NotSymbioteAppError) {
2825
+ console.error(import_picocolors.default.red(`@symbiote-native/cli: ${error.message}`));
2826
+ process.exitCode = 1;
2827
+ return;
2828
+ }
2829
+ console.error(import_picocolors.default.red("@symbiote-native/cli: unexpected error"), error);
2830
+ process.exitCode = 1;
2831
+ });
2832
+ //#endregion
2833
+ export {};