@take-out/cli 0.0.39

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 (331) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +274 -0
  3. package/cli.mjs +3 -0
  4. package/dist/cjs/cli.cjs +71 -0
  5. package/dist/cjs/cli.js +70 -0
  6. package/dist/cjs/cli.js.map +6 -0
  7. package/dist/cjs/cli.native.js +79 -0
  8. package/dist/cjs/cli.native.js.map +6 -0
  9. package/dist/cjs/commands/changed.cjs +212 -0
  10. package/dist/cjs/commands/changed.js +214 -0
  11. package/dist/cjs/commands/changed.js.map +6 -0
  12. package/dist/cjs/commands/changed.native.js +289 -0
  13. package/dist/cjs/commands/changed.native.js.map +6 -0
  14. package/dist/cjs/commands/docs.cjs +388 -0
  15. package/dist/cjs/commands/docs.js +313 -0
  16. package/dist/cjs/commands/docs.js.map +6 -0
  17. package/dist/cjs/commands/docs.native.js +476 -0
  18. package/dist/cjs/commands/docs.native.js.map +6 -0
  19. package/dist/cjs/commands/env-setup.cjs +90 -0
  20. package/dist/cjs/commands/env-setup.js +78 -0
  21. package/dist/cjs/commands/env-setup.js.map +6 -0
  22. package/dist/cjs/commands/env-setup.native.js +85 -0
  23. package/dist/cjs/commands/env-setup.native.js.map +6 -0
  24. package/dist/cjs/commands/onboard.cjs +479 -0
  25. package/dist/cjs/commands/onboard.js +631 -0
  26. package/dist/cjs/commands/onboard.js.map +6 -0
  27. package/dist/cjs/commands/onboard.native.js +608 -0
  28. package/dist/cjs/commands/onboard.native.js.map +6 -0
  29. package/dist/cjs/commands/run.cjs +148 -0
  30. package/dist/cjs/commands/run.js +116 -0
  31. package/dist/cjs/commands/run.js.map +6 -0
  32. package/dist/cjs/commands/run.native.js +140 -0
  33. package/dist/cjs/commands/run.native.js.map +6 -0
  34. package/dist/cjs/commands/script.cjs +379 -0
  35. package/dist/cjs/commands/script.js +339 -0
  36. package/dist/cjs/commands/script.js.map +6 -0
  37. package/dist/cjs/commands/script.native.js +449 -0
  38. package/dist/cjs/commands/script.native.js.map +6 -0
  39. package/dist/cjs/commands/sync.cjs +190 -0
  40. package/dist/cjs/commands/sync.js +168 -0
  41. package/dist/cjs/commands/sync.js.map +6 -0
  42. package/dist/cjs/commands/sync.native.js +211 -0
  43. package/dist/cjs/commands/sync.native.js.map +6 -0
  44. package/dist/cjs/constants/ascii.cjs +36 -0
  45. package/dist/cjs/constants/ascii.js +30 -0
  46. package/dist/cjs/constants/ascii.js.map +6 -0
  47. package/dist/cjs/constants/ascii.native.js +36 -0
  48. package/dist/cjs/constants/ascii.native.js.map +6 -0
  49. package/dist/cjs/index.cjs +64 -0
  50. package/dist/cjs/index.js +55 -0
  51. package/dist/cjs/index.js.map +6 -0
  52. package/dist/cjs/index.native.js +94 -0
  53. package/dist/cjs/index.native.js.map +6 -0
  54. package/dist/cjs/types.cjs +16 -0
  55. package/dist/cjs/types.js +14 -0
  56. package/dist/cjs/types.js.map +6 -0
  57. package/dist/cjs/types.native.js +15 -0
  58. package/dist/cjs/types.native.js.map +6 -0
  59. package/dist/cjs/utils/env-categories.cjs +272 -0
  60. package/dist/cjs/utils/env-categories.js +296 -0
  61. package/dist/cjs/utils/env-categories.js.map +6 -0
  62. package/dist/cjs/utils/env-categories.native.js +317 -0
  63. package/dist/cjs/utils/env-categories.native.js.map +6 -0
  64. package/dist/cjs/utils/env-setup.cjs +181 -0
  65. package/dist/cjs/utils/env-setup.js +190 -0
  66. package/dist/cjs/utils/env-setup.js.map +6 -0
  67. package/dist/cjs/utils/env-setup.native.js +264 -0
  68. package/dist/cjs/utils/env-setup.native.js.map +6 -0
  69. package/dist/cjs/utils/env.cjs +118 -0
  70. package/dist/cjs/utils/env.js +97 -0
  71. package/dist/cjs/utils/env.js.map +6 -0
  72. package/dist/cjs/utils/env.native.js +128 -0
  73. package/dist/cjs/utils/env.native.js.map +6 -0
  74. package/dist/cjs/utils/files.cjs +215 -0
  75. package/dist/cjs/utils/files.js +164 -0
  76. package/dist/cjs/utils/files.js.map +6 -0
  77. package/dist/cjs/utils/files.native.js +266 -0
  78. package/dist/cjs/utils/files.native.js.map +6 -0
  79. package/dist/cjs/utils/parallel-runner.cjs +99 -0
  80. package/dist/cjs/utils/parallel-runner.js +84 -0
  81. package/dist/cjs/utils/parallel-runner.js.map +6 -0
  82. package/dist/cjs/utils/parallel-runner.native.js +123 -0
  83. package/dist/cjs/utils/parallel-runner.native.js.map +6 -0
  84. package/dist/cjs/utils/ports.cjs +101 -0
  85. package/dist/cjs/utils/ports.js +81 -0
  86. package/dist/cjs/utils/ports.js.map +6 -0
  87. package/dist/cjs/utils/ports.native.js +130 -0
  88. package/dist/cjs/utils/ports.native.js.map +6 -0
  89. package/dist/cjs/utils/prerequisites.cjs +119 -0
  90. package/dist/cjs/utils/prerequisites.js +107 -0
  91. package/dist/cjs/utils/prerequisites.js.map +6 -0
  92. package/dist/cjs/utils/prerequisites.native.js +127 -0
  93. package/dist/cjs/utils/prerequisites.native.js.map +6 -0
  94. package/dist/cjs/utils/prompts.cjs +161 -0
  95. package/dist/cjs/utils/prompts.js +162 -0
  96. package/dist/cjs/utils/prompts.js.map +6 -0
  97. package/dist/cjs/utils/prompts.native.js +179 -0
  98. package/dist/cjs/utils/prompts.native.js.map +6 -0
  99. package/dist/cjs/utils/script-listing.cjs +113 -0
  100. package/dist/cjs/utils/script-listing.js +108 -0
  101. package/dist/cjs/utils/script-listing.js.map +6 -0
  102. package/dist/cjs/utils/script-listing.native.js +174 -0
  103. package/dist/cjs/utils/script-listing.native.js.map +6 -0
  104. package/dist/cjs/utils/sync.cjs +85 -0
  105. package/dist/cjs/utils/sync.js +70 -0
  106. package/dist/cjs/utils/sync.js.map +6 -0
  107. package/dist/cjs/utils/sync.native.js +84 -0
  108. package/dist/cjs/utils/sync.native.js.map +6 -0
  109. package/dist/cjs/utils/welcome.cjs +50 -0
  110. package/dist/cjs/utils/welcome.js +42 -0
  111. package/dist/cjs/utils/welcome.js.map +6 -0
  112. package/dist/cjs/utils/welcome.native.js +47 -0
  113. package/dist/cjs/utils/welcome.native.js.map +6 -0
  114. package/dist/esm/cli.js +79 -0
  115. package/dist/esm/cli.js.map +6 -0
  116. package/dist/esm/cli.mjs +71 -0
  117. package/dist/esm/cli.mjs.map +1 -0
  118. package/dist/esm/cli.native.js +69 -0
  119. package/dist/esm/cli.native.js.map +1 -0
  120. package/dist/esm/commands/changed.js +194 -0
  121. package/dist/esm/commands/changed.js.map +6 -0
  122. package/dist/esm/commands/changed.mjs +178 -0
  123. package/dist/esm/commands/changed.mjs.map +1 -0
  124. package/dist/esm/commands/changed.native.js +273 -0
  125. package/dist/esm/commands/changed.native.js.map +1 -0
  126. package/dist/esm/commands/docs.js +306 -0
  127. package/dist/esm/commands/docs.js.map +6 -0
  128. package/dist/esm/commands/docs.mjs +353 -0
  129. package/dist/esm/commands/docs.mjs.map +1 -0
  130. package/dist/esm/commands/docs.native.js +516 -0
  131. package/dist/esm/commands/docs.native.js.map +1 -0
  132. package/dist/esm/commands/env-setup.js +56 -0
  133. package/dist/esm/commands/env-setup.js.map +6 -0
  134. package/dist/esm/commands/env-setup.mjs +56 -0
  135. package/dist/esm/commands/env-setup.mjs.map +1 -0
  136. package/dist/esm/commands/env-setup.native.js +59 -0
  137. package/dist/esm/commands/env-setup.native.js.map +1 -0
  138. package/dist/esm/commands/onboard.js +645 -0
  139. package/dist/esm/commands/onboard.js.map +6 -0
  140. package/dist/esm/commands/onboard.mjs +445 -0
  141. package/dist/esm/commands/onboard.mjs.map +1 -0
  142. package/dist/esm/commands/onboard.native.js +584 -0
  143. package/dist/esm/commands/onboard.native.js.map +1 -0
  144. package/dist/esm/commands/run.js +95 -0
  145. package/dist/esm/commands/run.js.map +6 -0
  146. package/dist/esm/commands/run.mjs +114 -0
  147. package/dist/esm/commands/run.mjs.map +1 -0
  148. package/dist/esm/commands/run.native.js +133 -0
  149. package/dist/esm/commands/run.native.js.map +1 -0
  150. package/dist/esm/commands/script.js +338 -0
  151. package/dist/esm/commands/script.js.map +6 -0
  152. package/dist/esm/commands/script.mjs +336 -0
  153. package/dist/esm/commands/script.mjs.map +1 -0
  154. package/dist/esm/commands/script.native.js +445 -0
  155. package/dist/esm/commands/script.native.js.map +1 -0
  156. package/dist/esm/commands/sync.js +158 -0
  157. package/dist/esm/commands/sync.js.map +6 -0
  158. package/dist/esm/commands/sync.mjs +155 -0
  159. package/dist/esm/commands/sync.mjs.map +1 -0
  160. package/dist/esm/commands/sync.native.js +173 -0
  161. package/dist/esm/commands/sync.native.js.map +1 -0
  162. package/dist/esm/constants/ascii.js +14 -0
  163. package/dist/esm/constants/ascii.js.map +6 -0
  164. package/dist/esm/constants/ascii.mjs +12 -0
  165. package/dist/esm/constants/ascii.mjs.map +1 -0
  166. package/dist/esm/constants/ascii.native.js +12 -0
  167. package/dist/esm/constants/ascii.native.js.map +1 -0
  168. package/dist/esm/index.js +83 -0
  169. package/dist/esm/index.js.map +6 -0
  170. package/dist/esm/index.mjs +7 -0
  171. package/dist/esm/index.mjs.map +1 -0
  172. package/dist/esm/index.native.js +7 -0
  173. package/dist/esm/index.native.js.map +1 -0
  174. package/dist/esm/types.js +1 -0
  175. package/dist/esm/types.js.map +6 -0
  176. package/dist/esm/types.mjs +2 -0
  177. package/dist/esm/types.mjs.map +1 -0
  178. package/dist/esm/types.native.js +2 -0
  179. package/dist/esm/types.native.js.map +1 -0
  180. package/dist/esm/utils/env-categories.js +272 -0
  181. package/dist/esm/utils/env-categories.js.map +6 -0
  182. package/dist/esm/utils/env-categories.mjs +233 -0
  183. package/dist/esm/utils/env-categories.mjs.map +1 -0
  184. package/dist/esm/utils/env-categories.native.js +246 -0
  185. package/dist/esm/utils/env-categories.native.js.map +1 -0
  186. package/dist/esm/utils/env-setup.js +173 -0
  187. package/dist/esm/utils/env-setup.js.map +6 -0
  188. package/dist/esm/utils/env-setup.mjs +146 -0
  189. package/dist/esm/utils/env-setup.mjs.map +1 -0
  190. package/dist/esm/utils/env-setup.native.js +243 -0
  191. package/dist/esm/utils/env-setup.native.js.map +1 -0
  192. package/dist/esm/utils/env.js +83 -0
  193. package/dist/esm/utils/env.js.map +6 -0
  194. package/dist/esm/utils/env.mjs +90 -0
  195. package/dist/esm/utils/env.mjs.map +1 -0
  196. package/dist/esm/utils/env.native.js +99 -0
  197. package/dist/esm/utils/env.native.js.map +1 -0
  198. package/dist/esm/utils/files.js +150 -0
  199. package/dist/esm/utils/files.js.map +6 -0
  200. package/dist/esm/utils/files.mjs +187 -0
  201. package/dist/esm/utils/files.mjs.map +1 -0
  202. package/dist/esm/utils/files.native.js +247 -0
  203. package/dist/esm/utils/files.native.js.map +1 -0
  204. package/dist/esm/utils/parallel-runner.js +69 -0
  205. package/dist/esm/utils/parallel-runner.js.map +6 -0
  206. package/dist/esm/utils/parallel-runner.mjs +76 -0
  207. package/dist/esm/utils/parallel-runner.mjs.map +1 -0
  208. package/dist/esm/utils/parallel-runner.native.js +109 -0
  209. package/dist/esm/utils/parallel-runner.native.js.map +1 -0
  210. package/dist/esm/utils/ports.js +65 -0
  211. package/dist/esm/utils/ports.js.map +6 -0
  212. package/dist/esm/utils/ports.mjs +74 -0
  213. package/dist/esm/utils/ports.mjs.map +1 -0
  214. package/dist/esm/utils/ports.native.js +93 -0
  215. package/dist/esm/utils/ports.native.js.map +1 -0
  216. package/dist/esm/utils/prerequisites.js +91 -0
  217. package/dist/esm/utils/prerequisites.js.map +6 -0
  218. package/dist/esm/utils/prerequisites.mjs +91 -0
  219. package/dist/esm/utils/prerequisites.mjs.map +1 -0
  220. package/dist/esm/utils/prerequisites.native.js +97 -0
  221. package/dist/esm/utils/prerequisites.native.js.map +1 -0
  222. package/dist/esm/utils/prompts.js +139 -0
  223. package/dist/esm/utils/prompts.js.map +6 -0
  224. package/dist/esm/utils/prompts.mjs +112 -0
  225. package/dist/esm/utils/prompts.mjs.map +1 -0
  226. package/dist/esm/utils/prompts.native.js +115 -0
  227. package/dist/esm/utils/prompts.native.js.map +1 -0
  228. package/dist/esm/utils/script-listing.js +91 -0
  229. package/dist/esm/utils/script-listing.js.map +6 -0
  230. package/dist/esm/utils/script-listing.mjs +76 -0
  231. package/dist/esm/utils/script-listing.mjs.map +1 -0
  232. package/dist/esm/utils/script-listing.native.js +151 -0
  233. package/dist/esm/utils/script-listing.native.js.map +1 -0
  234. package/dist/esm/utils/sync.js +50 -0
  235. package/dist/esm/utils/sync.js.map +6 -0
  236. package/dist/esm/utils/sync.mjs +48 -0
  237. package/dist/esm/utils/sync.mjs.map +1 -0
  238. package/dist/esm/utils/sync.native.js +53 -0
  239. package/dist/esm/utils/sync.native.js.map +1 -0
  240. package/dist/esm/utils/welcome.js +21 -0
  241. package/dist/esm/utils/welcome.js.map +6 -0
  242. package/dist/esm/utils/welcome.mjs +15 -0
  243. package/dist/esm/utils/welcome.mjs.map +1 -0
  244. package/dist/esm/utils/welcome.native.js +18 -0
  245. package/dist/esm/utils/welcome.native.js.map +1 -0
  246. package/docs/aggregates.md +579 -0
  247. package/docs/cloudflare-dev-tunnel.md +41 -0
  248. package/docs/database.md +203 -0
  249. package/docs/docs.md +8 -0
  250. package/docs/emitters.md +562 -0
  251. package/docs/hot-updater.md +223 -0
  252. package/docs/native-hot-update.md +252 -0
  253. package/docs/one-components.md +234 -0
  254. package/docs/one-hooks.md +570 -0
  255. package/docs/one-routes.md +660 -0
  256. package/docs/package-json.md +115 -0
  257. package/docs/react-native-navigation-flow.md +184 -0
  258. package/docs/scripts.md +147 -0
  259. package/docs/sync-prompt.md +208 -0
  260. package/docs/tamagui.md +478 -0
  261. package/docs/testing-integration.md +564 -0
  262. package/docs/triggers.md +450 -0
  263. package/docs/zero.md +719 -0
  264. package/package.json +76 -0
  265. package/scripts/seed.ts +209 -0
  266. package/src/cli.ts +147 -0
  267. package/src/commands/changed.ts +313 -0
  268. package/src/commands/docs.ts +582 -0
  269. package/src/commands/env-setup.ts +69 -0
  270. package/src/commands/onboard.ts +1391 -0
  271. package/src/commands/run.ts +173 -0
  272. package/src/commands/script.ts +587 -0
  273. package/src/commands/sync.ts +305 -0
  274. package/src/constants/ascii.ts +17 -0
  275. package/src/index.ts +63 -0
  276. package/src/types.ts +59 -0
  277. package/src/utils/env-categories.ts +245 -0
  278. package/src/utils/env-setup.ts +338 -0
  279. package/src/utils/env.ts +127 -0
  280. package/src/utils/files.ts +302 -0
  281. package/src/utils/parallel-runner.ts +129 -0
  282. package/src/utils/ports.ts +77 -0
  283. package/src/utils/prerequisites.ts +137 -0
  284. package/src/utils/prompts.ts +197 -0
  285. package/src/utils/script-listing.ts +214 -0
  286. package/src/utils/sync.ts +101 -0
  287. package/src/withOpSqliteStatic.cjs +51 -0
  288. package/types/cli.d.ts +7 -0
  289. package/types/cli.d.ts.map +1 -0
  290. package/types/commands/changed.d.ts +14 -0
  291. package/types/commands/changed.d.ts.map +1 -0
  292. package/types/commands/docs.d.ts +5 -0
  293. package/types/commands/docs.d.ts.map +1 -0
  294. package/types/commands/env-setup.d.ts +25 -0
  295. package/types/commands/env-setup.d.ts.map +1 -0
  296. package/types/commands/onboard.d.ts +16 -0
  297. package/types/commands/onboard.d.ts.map +1 -0
  298. package/types/commands/run.d.ts +8 -0
  299. package/types/commands/run.d.ts.map +1 -0
  300. package/types/commands/script.d.ts +28 -0
  301. package/types/commands/script.d.ts.map +1 -0
  302. package/types/commands/sync.d.ts +5 -0
  303. package/types/commands/sync.d.ts.map +1 -0
  304. package/types/constants/ascii.d.ts +6 -0
  305. package/types/constants/ascii.d.ts.map +1 -0
  306. package/types/index.d.ts +12 -0
  307. package/types/index.d.ts.map +1 -0
  308. package/types/types.d.ts +54 -0
  309. package/types/types.d.ts.map +1 -0
  310. package/types/utils/env-categories.d.ts +8 -0
  311. package/types/utils/env-categories.d.ts.map +1 -0
  312. package/types/utils/env-setup.d.ts +10 -0
  313. package/types/utils/env-setup.d.ts.map +1 -0
  314. package/types/utils/env.d.ts +19 -0
  315. package/types/utils/env.d.ts.map +1 -0
  316. package/types/utils/files.d.ts +47 -0
  317. package/types/utils/files.d.ts.map +1 -0
  318. package/types/utils/parallel-runner.d.ts +15 -0
  319. package/types/utils/parallel-runner.d.ts.map +1 -0
  320. package/types/utils/ports.d.ts +16 -0
  321. package/types/utils/ports.d.ts.map +1 -0
  322. package/types/utils/prerequisites.d.ts +11 -0
  323. package/types/utils/prerequisites.d.ts.map +1 -0
  324. package/types/utils/prompts.d.ts +30 -0
  325. package/types/utils/prompts.d.ts.map +1 -0
  326. package/types/utils/script-listing.d.ts +7 -0
  327. package/types/utils/script-listing.d.ts.map +1 -0
  328. package/types/utils/sync.d.ts +16 -0
  329. package/types/utils/sync.d.ts.map +1 -0
  330. package/types/utils/welcome.d.ts +6 -0
  331. package/types/utils/welcome.d.ts.map +1 -0
@@ -0,0 +1,302 @@
1
+ /**
2
+ * File operations for updating project configuration
3
+ */
4
+
5
+ import { execSync } from 'node:child_process'
6
+ import { existsSync, readdirSync, readFileSync, rmSync, writeFileSync } from 'node:fs'
7
+ import { join } from 'node:path'
8
+
9
+ export function updatePackageJson(
10
+ cwd: string,
11
+ updates: { name?: string; description?: string }
12
+ ): { success: boolean; error?: string } {
13
+ const packagePath = join(cwd, 'package.json')
14
+
15
+ if (!existsSync(packagePath)) {
16
+ return { success: false, error: 'package.json not found' }
17
+ }
18
+
19
+ try {
20
+ const content = readFileSync(packagePath, 'utf-8')
21
+ const pkg = JSON.parse(content)
22
+
23
+ if (updates.name) pkg.name = updates.name
24
+ if (updates.description) pkg.description = updates.description
25
+
26
+ writeFileSync(packagePath, JSON.stringify(pkg, null, 2) + '\n', 'utf-8')
27
+ return { success: true }
28
+ } catch (error) {
29
+ return {
30
+ success: false,
31
+ error: error instanceof Error ? error.message : 'Unknown error',
32
+ }
33
+ }
34
+ }
35
+
36
+ export function updateAppConfig(
37
+ cwd: string,
38
+ updates: { name?: string; slug?: string; bundleId?: string }
39
+ ): { success: boolean; error?: string } {
40
+ const configPath = join(cwd, 'app.config.ts')
41
+
42
+ if (!existsSync(configPath)) {
43
+ return { success: false, error: 'app.config.ts not found' }
44
+ }
45
+
46
+ try {
47
+ let content = readFileSync(configPath, 'utf-8')
48
+
49
+ if (updates.name) {
50
+ // Update name field
51
+ content = content.replace(/(name:\s*['"])([^'"]+)(['"])/, `$1${updates.name}$3`)
52
+ }
53
+
54
+ if (updates.slug) {
55
+ // Update slug field
56
+ content = content.replace(/(slug:\s*['"])([^'"]+)(['"])/, `$1${updates.slug}$3`)
57
+ }
58
+
59
+ if (updates.bundleId) {
60
+ // Update iOS bundle identifier
61
+ content = content.replace(
62
+ /(bundleIdentifier:\s*['"])([^'"]+)(['"])/,
63
+ `$1${updates.bundleId}$3`
64
+ )
65
+ // Update Android package
66
+ content = content.replace(
67
+ /(package:\s*['"])([^'"]+)(['"])/,
68
+ `$1${updates.bundleId}$3`
69
+ )
70
+ }
71
+
72
+ writeFileSync(configPath, content, 'utf-8')
73
+ return { success: true }
74
+ } catch (error) {
75
+ return {
76
+ success: false,
77
+ error: error instanceof Error ? error.message : 'Unknown error',
78
+ }
79
+ }
80
+ }
81
+
82
+ export function checkOnboarded(cwd: string): boolean {
83
+ const packagePath = join(cwd, 'package.json')
84
+ if (!existsSync(packagePath)) return false
85
+
86
+ try {
87
+ const pkg = JSON.parse(readFileSync(packagePath, 'utf-8'))
88
+ return pkg.takeout?.onboarded === true
89
+ } catch {
90
+ return false
91
+ }
92
+ }
93
+
94
+ export function markOnboarded(cwd: string): { success: boolean; error?: string } {
95
+ const packagePath = join(cwd, 'package.json')
96
+
97
+ if (!existsSync(packagePath)) {
98
+ return { success: false, error: 'package.json not found' }
99
+ }
100
+
101
+ try {
102
+ const content = readFileSync(packagePath, 'utf-8')
103
+ const pkg = JSON.parse(content)
104
+
105
+ if (!pkg.takeout) {
106
+ pkg.takeout = {}
107
+ }
108
+ pkg.takeout.onboarded = true
109
+
110
+ writeFileSync(packagePath, JSON.stringify(pkg, null, 2) + '\n', 'utf-8')
111
+ return { success: true }
112
+ } catch (error) {
113
+ return {
114
+ success: false,
115
+ error: error instanceof Error ? error.message : 'Unknown error',
116
+ }
117
+ }
118
+ }
119
+
120
+ /**
121
+ * Updates the env section in package.json to remove platform-specific variables
122
+ */
123
+ export function updatePackageJsonEnv(
124
+ cwd: string,
125
+ platform: 'sst' | 'uncloud'
126
+ ): { success: boolean; error?: string } {
127
+ const packagePath = join(cwd, 'package.json')
128
+
129
+ if (!existsSync(packagePath)) {
130
+ return { success: false, error: 'package.json not found' }
131
+ }
132
+
133
+ try {
134
+ const content = readFileSync(packagePath, 'utf-8')
135
+ const pkg = JSON.parse(content)
136
+
137
+ if (!pkg.env) {
138
+ return { success: false, error: 'env section not found in package.json' }
139
+ }
140
+
141
+ if (platform === 'sst') {
142
+ // remove uncloud-specific vars, keep sst vars
143
+ delete pkg.env.DEPLOY_HOST
144
+ delete pkg.env.DEPLOY_USER
145
+ delete pkg.env.DEPLOY_SSH_KEY
146
+ } else if (platform === 'uncloud') {
147
+ // remove sst-specific vars, keep uncloud vars
148
+ delete pkg.env.CLOUDFLARE_API_TOKEN
149
+ delete pkg.env.AWS_ACCESS_KEY_ID
150
+ delete pkg.env.AWS_SECRET_ACCESS_KEY
151
+ }
152
+
153
+ writeFileSync(packagePath, JSON.stringify(pkg, null, 2) + '\n', 'utf-8')
154
+ return { success: true }
155
+ } catch (error) {
156
+ return {
157
+ success: false,
158
+ error: error instanceof Error ? error.message : 'Unknown error',
159
+ }
160
+ }
161
+ }
162
+
163
+ export interface EjectOptions {
164
+ dryRun?: boolean
165
+ }
166
+
167
+ export interface EjectResult {
168
+ success: boolean
169
+ error?: string
170
+ packages?: { name: string; version: string }[]
171
+ warnings?: string[]
172
+ }
173
+
174
+ /**
175
+ * Ejects from monorepo setup by removing ./packages and updating workspace:* versions
176
+ */
177
+ export async function ejectFromMonorepo(
178
+ cwd: string,
179
+ options: EjectOptions = {}
180
+ ): Promise<EjectResult> {
181
+ const { dryRun = false } = options
182
+ const packagePath = join(cwd, 'package.json')
183
+ const packagesDir = join(cwd, 'packages')
184
+ const warnings: string[] = []
185
+
186
+ if (!existsSync(packagePath)) {
187
+ return { success: false, error: 'package.json not found' }
188
+ }
189
+
190
+ try {
191
+ // read package.json
192
+ const content = readFileSync(packagePath, 'utf-8')
193
+ const pkg = JSON.parse(content)
194
+
195
+ // check if already ejected
196
+ if (!existsSync(packagesDir)) {
197
+ return { success: false, error: 'packages directory not found - already ejected?' }
198
+ }
199
+
200
+ if (!pkg.workspaces) {
201
+ return { success: false, error: 'no workspaces field found - already ejected?' }
202
+ }
203
+
204
+ // dynamically discover workspace packages from ./packages directory
205
+ const workspacePackages: { name: string; version: string }[] = []
206
+
207
+ const entries = readdirSync(packagesDir, { withFileTypes: true })
208
+ for (const entry of entries) {
209
+ if (!entry.isDirectory()) continue
210
+ const pkgJsonPath = join(packagesDir, entry.name, 'package.json')
211
+ if (existsSync(pkgJsonPath)) {
212
+ try {
213
+ const pkgJson = JSON.parse(readFileSync(pkgJsonPath, 'utf-8'))
214
+ if (pkgJson.name && pkgJson.version) {
215
+ workspacePackages.push({ name: pkgJson.name, version: pkgJson.version })
216
+ } else {
217
+ warnings.push(`skipped ${entry.name}: missing name or version`)
218
+ }
219
+ } catch (e) {
220
+ warnings.push(`skipped ${entry.name}: invalid package.json`)
221
+ }
222
+ }
223
+ }
224
+
225
+ if (workspacePackages.length === 0) {
226
+ return { success: false, error: 'no valid workspace packages found' }
227
+ }
228
+
229
+ // check for workspace:* references that won't be resolved
230
+ const unresolvedDeps: string[] = []
231
+ const allDeps = { ...pkg.dependencies, ...pkg.devDependencies }
232
+ for (const [name, version] of Object.entries(allDeps)) {
233
+ if (version === 'workspace:*') {
234
+ const found = workspacePackages.find((p) => p.name === name)
235
+ if (!found) {
236
+ unresolvedDeps.push(name)
237
+ }
238
+ }
239
+ }
240
+
241
+ if (unresolvedDeps.length > 0) {
242
+ return {
243
+ success: false,
244
+ error: `unresolved workspace dependencies: ${unresolvedDeps.join(', ')}`,
245
+ packages: workspacePackages,
246
+ }
247
+ }
248
+
249
+ // dry run returns here without making changes
250
+ if (dryRun) {
251
+ return {
252
+ success: true,
253
+ packages: workspacePackages,
254
+ warnings: warnings.length > 0 ? warnings : undefined,
255
+ }
256
+ }
257
+
258
+ // replace workspace:* with actual versions
259
+ for (const { name, version } of workspacePackages) {
260
+ if (pkg.dependencies?.[name] === 'workspace:*') {
261
+ pkg.dependencies[name] = `^${version}`
262
+ }
263
+ if (pkg.devDependencies?.[name] === 'workspace:*') {
264
+ pkg.devDependencies[name] = `^${version}`
265
+ }
266
+ }
267
+
268
+ // remove workspaces field
269
+ delete pkg.workspaces
270
+
271
+ // write updated package.json
272
+ writeFileSync(packagePath, JSON.stringify(pkg, null, 2) + '\n', 'utf-8')
273
+
274
+ // remove packages directory
275
+ rmSync(packagesDir, { recursive: true, force: true })
276
+
277
+ // install the published packages
278
+ try {
279
+ execSync('bun install', { cwd, stdio: 'inherit' })
280
+ } catch {
281
+ // restore packages directory hint in error
282
+ return {
283
+ success: false,
284
+ error:
285
+ 'failed to install published packages. package.json was modified but install failed. ' +
286
+ 'try running "bun install" manually, or restore from git.',
287
+ packages: workspacePackages,
288
+ }
289
+ }
290
+
291
+ return {
292
+ success: true,
293
+ packages: workspacePackages,
294
+ warnings: warnings.length > 0 ? warnings : undefined,
295
+ }
296
+ } catch (error) {
297
+ return {
298
+ success: false,
299
+ error: error instanceof Error ? error.message : 'Unknown error',
300
+ }
301
+ }
302
+ }
@@ -0,0 +1,129 @@
1
+ /**
2
+ * Utility for running scripts in parallel with color-coded output
3
+ */
4
+
5
+ import { spawn } from 'node:child_process'
6
+ import { cpus } from 'node:os'
7
+
8
+ const colors = [
9
+ '\x1b[36m', // Cyan
10
+ '\x1b[35m', // Magenta
11
+ '\x1b[33m', // Yellow
12
+ '\x1b[32m', // Green
13
+ '\x1b[34m', // Blue
14
+ '\x1b[31m', // Red
15
+ '\x1b[90m', // Gray
16
+ ]
17
+
18
+ const reset = '\x1b[0m'
19
+
20
+ interface ScriptToRun {
21
+ name: string
22
+ path: string
23
+ args?: string[]
24
+ }
25
+
26
+ export async function runScriptsInParallel(
27
+ scripts: ScriptToRun[],
28
+ options: {
29
+ title?: string
30
+ onError?: 'continue' | 'exit'
31
+ maxParallelism?: number
32
+ } = {}
33
+ ): Promise<void> {
34
+ const { title, onError = 'exit', maxParallelism = cpus().length } = options
35
+
36
+ if (title) {
37
+ console.info()
38
+ console.info(title)
39
+ console.info()
40
+ }
41
+
42
+ const allPromises: Promise<void>[] = []
43
+ const executing: Set<Promise<void>> = new Set()
44
+
45
+ for (let i = 0; i < scripts.length; i++) {
46
+ const script = scripts[i]!
47
+ const scriptPromise = runSingleScript(script, i).finally(() => {
48
+ executing.delete(scriptPromise)
49
+ })
50
+
51
+ allPromises.push(scriptPromise)
52
+ executing.add(scriptPromise)
53
+
54
+ if (executing.size >= maxParallelism) {
55
+ await Promise.race(executing)
56
+ }
57
+ }
58
+
59
+ const settledResults = await Promise.allSettled(allPromises)
60
+
61
+ // Check for failures
62
+ const failures = settledResults.filter((r) => r.status === 'rejected')
63
+
64
+ if (failures.length > 0) {
65
+ console.error(`\n${reset}\x1b[31m✗ ${failures.length} script(s) failed${reset}\n`)
66
+ if (onError === 'exit') {
67
+ process.exit(1)
68
+ }
69
+ } else {
70
+ console.info(`\n${reset}\x1b[32m✓ All scripts completed successfully${reset}\n`)
71
+ }
72
+ }
73
+
74
+ function runSingleScript(script: ScriptToRun, colorIndex: number): Promise<void> {
75
+ return new Promise((resolve, reject) => {
76
+ const color = colors[colorIndex % colors.length]
77
+ const prefixLabel = script.name
78
+
79
+ const proc = spawn('bun', [script.path, ...(script.args || [])], {
80
+ stdio: ['pipe', 'pipe', 'pipe'],
81
+ shell: false,
82
+ env: { ...process.env, FORCE_COLOR: '3' } as any,
83
+ detached: true,
84
+ })
85
+
86
+ let stderrBuffer = ''
87
+
88
+ proc.stdout.on('data', (data) => {
89
+ const lines = data.toString().split('\n')
90
+ for (const line of lines) {
91
+ if (line) console.info(`${color}${prefixLabel}${reset} ${line}`)
92
+ }
93
+ })
94
+
95
+ proc.stderr.on('data', (data) => {
96
+ const dataStr = data.toString()
97
+ stderrBuffer += dataStr
98
+
99
+ const lines = dataStr.split('\n')
100
+ for (const line of lines) {
101
+ if (line) console.error(`${color}${prefixLabel}${reset} ${line}`)
102
+ }
103
+ })
104
+
105
+ proc.on('error', (error) => {
106
+ console.error(`${color}${prefixLabel}${reset} Failed to start: ${error.message}`)
107
+ reject(error)
108
+ })
109
+
110
+ proc.on('close', (code) => {
111
+ if (code && code !== 0) {
112
+ console.error(`${color}${prefixLabel}${reset} Process exited with code ${code}`)
113
+
114
+ // Show error details
115
+ if (stderrBuffer.trim()) {
116
+ console.error(`\n${color}${prefixLabel}${reset} Error output:`)
117
+ console.error('\x1b[90m' + '─'.repeat(80) + '\x1b[0m')
118
+ console.error(stderrBuffer)
119
+ console.error('\x1b[90m' + '─'.repeat(80) + '\x1b[0m\n')
120
+ }
121
+
122
+ reject(new Error(`Script ${prefixLabel} failed with code ${code}`))
123
+ } else {
124
+ console.info(`${color}${prefixLabel}${reset} \x1b[32m✓ completed${reset}`)
125
+ resolve()
126
+ }
127
+ })
128
+ })
129
+ }
@@ -0,0 +1,77 @@
1
+ /**
2
+ * Port conflict detection for Takeout services
3
+ */
4
+
5
+ import { execSync } from 'node:child_process'
6
+
7
+ import type { PortCheck } from '../types'
8
+
9
+ function isPortInUse(port: number): { inUse: boolean; pid?: number } {
10
+ try {
11
+ if (process.platform === 'win32') {
12
+ // windows: use netstat to find processes on the port
13
+ const output = execSync(`netstat -ano | findstr :${port}`, {
14
+ encoding: 'utf-8',
15
+ stdio: ['pipe', 'pipe', 'ignore'],
16
+ }).trim()
17
+
18
+ if (!output) return { inUse: false }
19
+
20
+ // extract pid from last column of netstat output
21
+ const lines = output.split('\n')
22
+ for (const line of lines) {
23
+ const parts = line.trim().split(/\s+/)
24
+ // check if this is a LISTENING state on the exact port
25
+ if (parts[1]?.includes(`:${port}`) && parts[3] === 'LISTENING') {
26
+ const pid = Number.parseInt(parts[4] || '', 10)
27
+ return { inUse: true, pid: Number.isNaN(pid) ? undefined : pid }
28
+ }
29
+ }
30
+ return { inUse: false }
31
+ } else {
32
+ // unix: use lsof
33
+ const output = execSync(`lsof -i :${port} -t`, {
34
+ encoding: 'utf-8',
35
+ stdio: ['pipe', 'pipe', 'ignore'],
36
+ }).trim()
37
+
38
+ const pid = output ? Number.parseInt(output.split('\n')[0] || '', 10) : undefined
39
+
40
+ return { inUse: !!output, pid: Number.isNaN(pid) ? undefined : pid }
41
+ }
42
+ } catch {
43
+ // if command fails, port is likely free
44
+ return { inUse: false }
45
+ }
46
+ }
47
+
48
+ export const TAKEOUT_PORTS = {
49
+ postgres: 5432,
50
+ zero: 4848,
51
+ web: 8081,
52
+ minio: 9090,
53
+ minioConsole: 9091,
54
+ } as const
55
+
56
+ export function checkPort(port: number, name: string): PortCheck {
57
+ const { inUse, pid } = isPortInUse(port)
58
+ return { port, name, inUse, pid }
59
+ }
60
+
61
+ export function checkAllPorts(): PortCheck[] {
62
+ return [
63
+ checkPort(TAKEOUT_PORTS.postgres, 'PostgreSQL'),
64
+ checkPort(TAKEOUT_PORTS.zero, 'Zero Sync'),
65
+ checkPort(TAKEOUT_PORTS.web, 'Web Server'),
66
+ checkPort(TAKEOUT_PORTS.minio, 'MinIO (S3)'),
67
+ checkPort(TAKEOUT_PORTS.minioConsole, 'MinIO Console'),
68
+ ]
69
+ }
70
+
71
+ export function hasPortConflicts(checks: PortCheck[]): boolean {
72
+ return checks.some((c) => c.inUse)
73
+ }
74
+
75
+ export function getConflictingPorts(checks: PortCheck[]): PortCheck[] {
76
+ return checks.filter((c) => c.inUse)
77
+ }
@@ -0,0 +1,137 @@
1
+ /**
2
+ * Check for required prerequisites (Bun, Node, Docker, Git)
3
+ */
4
+
5
+ import { execSync } from 'node:child_process'
6
+
7
+ import type { PrerequisiteCheck } from '../types'
8
+
9
+ function execCommand(command: string): string | null {
10
+ try {
11
+ return execSync(command, {
12
+ encoding: 'utf-8',
13
+ stdio: ['pipe', 'pipe', 'ignore'],
14
+ }).trim()
15
+ } catch {
16
+ return null
17
+ }
18
+ }
19
+
20
+ function getVersion(command: string): string | null {
21
+ const output = execCommand(command)
22
+ if (!output) return null
23
+
24
+ // Extract version number (e.g., "v1.2.3" or "1.2.3")
25
+ const match = output.match(/\d+\.\d+\.\d+/)
26
+ return match ? match[0] : output
27
+ }
28
+
29
+ function compareVersions(current: string, required: string): boolean {
30
+ const parseCurrent = current.replace(/^v/, '').split('.').map(Number)
31
+ const parseRequired = required.replace(/^v/, '').split('.').map(Number)
32
+
33
+ for (let i = 0; i < 3; i++) {
34
+ const curr = parseCurrent[i] || 0
35
+ const req = parseRequired[i] || 0
36
+ if (curr > req) return true
37
+ if (curr < req) return false
38
+ }
39
+ return true
40
+ }
41
+
42
+ export function checkBun(): PrerequisiteCheck {
43
+ const version = getVersion('bun --version') ?? undefined
44
+ const requiredVersion = '1.0.0'
45
+ const hasBunv = !!execCommand('bunv --version')
46
+
47
+ let message = version
48
+ ? compareVersions(version, requiredVersion)
49
+ ? `Bun ${version} installed`
50
+ : `Bun ${version} installed (${requiredVersion}+ recommended)`
51
+ : 'Bun not found'
52
+
53
+ if (version && !hasBunv) {
54
+ message += ' (consider installing bunv for auto version switching)'
55
+ }
56
+
57
+ return {
58
+ name: 'Bun',
59
+ required: true,
60
+ installed: !!version,
61
+ version,
62
+ requiredVersion,
63
+ message,
64
+ installUrl: 'https://bun.sh',
65
+ recommendation: !hasBunv
66
+ ? 'Install bunv to automatically switch bun versions: https://github.com/aklinker1/bunv'
67
+ : undefined,
68
+ }
69
+ }
70
+
71
+ export function checkNode(): PrerequisiteCheck {
72
+ const version = getVersion('node --version') ?? undefined
73
+ const requiredVersion = '20.0.0'
74
+ const hasFnm = !!execCommand('fnm --version')
75
+
76
+ let message = version
77
+ ? compareVersions(version, requiredVersion)
78
+ ? `Node.js ${version} installed`
79
+ : `Node.js ${version} installed (${requiredVersion}+ recommended)`
80
+ : 'Node.js not found (optional)'
81
+
82
+ if (version && !hasFnm) {
83
+ message += ' (consider installing fnm for auto version switching)'
84
+ }
85
+
86
+ return {
87
+ name: 'Node.js',
88
+ required: false,
89
+ installed: !!version,
90
+ version,
91
+ requiredVersion,
92
+ message,
93
+ installUrl: 'https://nodejs.org',
94
+ recommendation: !hasFnm
95
+ ? 'Install fnm to automatically switch node versions: https://github.com/Schniz/fnm'
96
+ : undefined,
97
+ }
98
+ }
99
+
100
+ export function checkDocker(): PrerequisiteCheck {
101
+ const version = getVersion('docker --version') ?? undefined
102
+ const isRunning = !!execCommand('docker ps')
103
+
104
+ return {
105
+ name: 'Docker',
106
+ required: true,
107
+ installed: !!version,
108
+ version,
109
+ message: !version
110
+ ? 'Docker not found'
111
+ : !isRunning
112
+ ? 'Docker installed but not running'
113
+ : `Docker ${version} running`,
114
+ installUrl: 'https://docs.docker.com/get-docker/',
115
+ }
116
+ }
117
+
118
+ export function checkGit(): PrerequisiteCheck {
119
+ const version = getVersion('git --version') ?? undefined
120
+
121
+ return {
122
+ name: 'Git',
123
+ required: true,
124
+ installed: !!version,
125
+ version,
126
+ message: version ? `Git ${version} installed` : 'Git not found',
127
+ installUrl: 'https://git-scm.com',
128
+ }
129
+ }
130
+
131
+ export function checkAllPrerequisites(): PrerequisiteCheck[] {
132
+ return [checkBun(), checkNode(), checkDocker(), checkGit()]
133
+ }
134
+
135
+ export function hasRequiredPrerequisites(checks: PrerequisiteCheck[]): boolean {
136
+ return checks.filter((c) => c.required).every((c) => c.installed)
137
+ }