everything-dev 1.53.1 → 2.0.0-rc.0

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 (713) hide show
  1. package/README.md +2 -11
  2. package/dist/_virtual/_rolldown/runtime.cjs +17 -2
  3. package/dist/_virtual/_rolldown/runtime.mjs +36 -0
  4. package/dist/api/auth-middleware.cjs +161 -0
  5. package/dist/api/auth-middleware.cjs.map +1 -0
  6. package/dist/api/auth-middleware.d.cts +69 -0
  7. package/dist/api/auth-middleware.d.mts +69 -0
  8. package/dist/api/auth-middleware.mjs +160 -0
  9. package/dist/api/auth-middleware.mjs.map +1 -0
  10. package/dist/api-contract.cjs +250 -62
  11. package/dist/api-contract.cjs.map +1 -1
  12. package/dist/api-contract.mjs +246 -65
  13. package/dist/api-contract.mjs.map +1 -1
  14. package/dist/app.cjs +99 -26
  15. package/dist/app.cjs.map +1 -1
  16. package/dist/app.d.cts +3 -0
  17. package/dist/app.d.mts +3 -0
  18. package/dist/app.mjs +100 -27
  19. package/dist/app.mjs.map +1 -1
  20. package/dist/auth-login.cjs +163 -0
  21. package/dist/auth-login.cjs.map +1 -0
  22. package/dist/auth-login.mjs +162 -0
  23. package/dist/auth-login.mjs.map +1 -0
  24. package/dist/auth-session.cjs +64 -0
  25. package/dist/auth-session.cjs.map +1 -0
  26. package/dist/auth-session.mjs +58 -0
  27. package/dist/auth-session.mjs.map +1 -0
  28. package/dist/auth-types-gen.cjs +0 -1
  29. package/dist/auth-types-gen.cjs.map +1 -1
  30. package/dist/build.cjs +37 -173
  31. package/dist/build.cjs.map +1 -1
  32. package/dist/build.mjs +37 -171
  33. package/dist/build.mjs.map +1 -1
  34. package/dist/bundle-cache.cjs +74 -0
  35. package/dist/bundle-cache.cjs.map +1 -0
  36. package/dist/bundle-cache.d.cts +27 -0
  37. package/dist/bundle-cache.d.mts +27 -0
  38. package/dist/bundle-cache.mjs +68 -0
  39. package/dist/bundle-cache.mjs.map +1 -0
  40. package/dist/bundle-fs-resolve.cjs +209 -0
  41. package/dist/bundle-fs-resolve.cjs.map +1 -0
  42. package/dist/bundle-fs-resolve.d.cts +76 -0
  43. package/dist/bundle-fs-resolve.d.mts +76 -0
  44. package/dist/bundle-fs-resolve.mjs +202 -0
  45. package/dist/bundle-fs-resolve.mjs.map +1 -0
  46. package/dist/cdn-deploy.cjs +126 -0
  47. package/dist/cdn-deploy.cjs.map +1 -0
  48. package/dist/cdn-deploy.mjs +124 -0
  49. package/dist/cdn-deploy.mjs.map +1 -0
  50. package/dist/cli/db-doctor.cjs +19 -19
  51. package/dist/cli/db-doctor.cjs.map +1 -1
  52. package/dist/cli/db-doctor.mjs +18 -18
  53. package/dist/cli/db-doctor.mjs.map +1 -1
  54. package/dist/cli/db-repair.cjs +9 -32
  55. package/dist/cli/db-repair.cjs.map +1 -1
  56. package/dist/cli/db-repair.mjs +9 -32
  57. package/dist/cli/db-repair.mjs.map +1 -1
  58. package/dist/cli/framework-version.cjs +7 -3
  59. package/dist/cli/framework-version.cjs.map +1 -1
  60. package/dist/cli/framework-version.mjs +7 -3
  61. package/dist/cli/framework-version.mjs.map +1 -1
  62. package/dist/cli/infra.cjs +159 -251
  63. package/dist/cli/infra.cjs.map +1 -1
  64. package/dist/cli/infra.mjs +154 -242
  65. package/dist/cli/infra.mjs.map +1 -1
  66. package/dist/cli/init.cjs +624 -196
  67. package/dist/cli/init.cjs.map +1 -1
  68. package/dist/cli/init.d.cts +61 -8
  69. package/dist/cli/init.d.mts +61 -8
  70. package/dist/cli/init.mjs +613 -194
  71. package/dist/cli/init.mjs.map +1 -1
  72. package/dist/cli/parse.cjs +8 -7
  73. package/dist/cli/parse.cjs.map +1 -1
  74. package/dist/cli/parse.mjs +9 -7
  75. package/dist/cli/parse.mjs.map +1 -1
  76. package/dist/cli/prompts.cjs +14 -1
  77. package/dist/cli/prompts.cjs.map +1 -1
  78. package/dist/cli/prompts.mjs +14 -1
  79. package/dist/cli/prompts.mjs.map +1 -1
  80. package/dist/cli/prune.cjs +220 -0
  81. package/dist/cli/prune.cjs.map +1 -0
  82. package/dist/cli/prune.mjs +220 -0
  83. package/dist/cli/prune.mjs.map +1 -0
  84. package/dist/cli/snapshot.cjs +2 -1
  85. package/dist/cli/snapshot.cjs.map +1 -1
  86. package/dist/cli/snapshot.mjs +2 -1
  87. package/dist/cli/snapshot.mjs.map +1 -1
  88. package/dist/cli/status.cjs +5 -4
  89. package/dist/cli/status.cjs.map +1 -1
  90. package/dist/cli/status.mjs +6 -5
  91. package/dist/cli/status.mjs.map +1 -1
  92. package/dist/cli/sync.cjs +156 -58
  93. package/dist/cli/sync.cjs.map +1 -1
  94. package/dist/cli/sync.mjs +158 -63
  95. package/dist/cli/sync.mjs.map +1 -1
  96. package/dist/cli/timing.cjs +0 -1
  97. package/dist/cli/timing.cjs.map +1 -1
  98. package/dist/cli/upgrade.cjs +95 -69
  99. package/dist/cli/upgrade.cjs.map +1 -1
  100. package/dist/cli/upgrade.mjs +97 -72
  101. package/dist/cli/upgrade.mjs.map +1 -1
  102. package/dist/cli/utils/helpers.cjs.map +1 -1
  103. package/dist/cli.cjs +320 -72
  104. package/dist/cli.cjs.map +1 -1
  105. package/dist/cli.mjs +316 -68
  106. package/dist/cli.mjs.map +1 -1
  107. package/dist/code-artifacts.cjs +76 -8
  108. package/dist/code-artifacts.cjs.map +1 -1
  109. package/dist/code-artifacts.mjs +76 -10
  110. package/dist/code-artifacts.mjs.map +1 -1
  111. package/dist/commands/build.cjs +65 -0
  112. package/dist/commands/build.cjs.map +1 -0
  113. package/dist/commands/build.mjs +65 -0
  114. package/dist/commands/build.mjs.map +1 -0
  115. package/dist/commands/config.cjs +77 -0
  116. package/dist/commands/config.cjs.map +1 -0
  117. package/dist/commands/config.d.cts +8 -0
  118. package/dist/commands/config.d.mts +8 -0
  119. package/dist/commands/config.mjs +74 -0
  120. package/dist/commands/config.mjs.map +1 -0
  121. package/dist/commands/db.cjs +107 -0
  122. package/dist/commands/db.cjs.map +1 -0
  123. package/dist/commands/db.mjs +107 -0
  124. package/dist/commands/db.mjs.map +1 -0
  125. package/dist/commands/deploy.cjs +336 -0
  126. package/dist/commands/deploy.cjs.map +1 -0
  127. package/dist/commands/deploy.mjs +334 -0
  128. package/dist/commands/deploy.mjs.map +1 -0
  129. package/dist/commands/dev.cjs +75 -0
  130. package/dist/commands/dev.cjs.map +1 -0
  131. package/dist/commands/dev.mjs +73 -0
  132. package/dist/commands/dev.mjs.map +1 -0
  133. package/dist/commands/init.cjs +234 -0
  134. package/dist/commands/init.cjs.map +1 -0
  135. package/dist/commands/init.mjs +231 -0
  136. package/dist/commands/init.mjs.map +1 -0
  137. package/dist/commands/keys.cjs +255 -0
  138. package/dist/commands/keys.cjs.map +1 -0
  139. package/dist/commands/keys.mjs +253 -0
  140. package/dist/commands/keys.mjs.map +1 -0
  141. package/dist/commands/ops.cjs +199 -0
  142. package/dist/commands/ops.cjs.map +1 -0
  143. package/dist/commands/ops.mjs +197 -0
  144. package/dist/commands/ops.mjs.map +1 -0
  145. package/dist/commands/plugins.cjs +211 -0
  146. package/dist/commands/plugins.cjs.map +1 -0
  147. package/dist/commands/plugins.mjs +211 -0
  148. package/dist/commands/plugins.mjs.map +1 -0
  149. package/dist/commands/shared.cjs +8 -0
  150. package/dist/commands/shared.cjs.map +1 -0
  151. package/dist/commands/shared.d.cts +6 -0
  152. package/dist/commands/shared.d.mts +6 -0
  153. package/dist/commands/shared.mjs +8 -0
  154. package/dist/commands/shared.mjs.map +1 -0
  155. package/dist/commands/upgrade.cjs +325 -0
  156. package/dist/commands/upgrade.cjs.map +1 -0
  157. package/dist/commands/upgrade.mjs +323 -0
  158. package/dist/commands/upgrade.mjs.map +1 -0
  159. package/dist/components/dev-render.cjs +340 -0
  160. package/dist/components/dev-render.cjs.map +1 -0
  161. package/dist/components/dev-render.mjs +332 -0
  162. package/dist/components/dev-render.mjs.map +1 -0
  163. package/dist/config.cjs +460 -221
  164. package/dist/config.cjs.map +1 -1
  165. package/dist/config.d.cts +491 -48
  166. package/dist/config.d.mts +491 -48
  167. package/dist/config.mjs +439 -212
  168. package/dist/config.mjs.map +1 -1
  169. package/dist/contract.cjs +327 -50
  170. package/dist/contract.cjs.map +1 -1
  171. package/dist/contract.d.cts +1951 -1062
  172. package/dist/contract.d.mts +1951 -1062
  173. package/dist/contract.meta.cjs +107 -12
  174. package/dist/contract.meta.cjs.map +1 -1
  175. package/dist/contract.meta.d.cts +166 -8
  176. package/dist/contract.meta.d.mts +166 -8
  177. package/dist/contract.meta.mjs +107 -11
  178. package/dist/contract.meta.mjs.map +1 -1
  179. package/dist/contract.mjs +580 -327
  180. package/dist/contract.mjs.map +1 -1
  181. package/dist/dag.cjs +5 -3
  182. package/dist/dag.cjs.map +1 -1
  183. package/dist/dag.mjs +6 -3
  184. package/dist/dag.mjs.map +1 -1
  185. package/dist/db/binding.cjs +80 -0
  186. package/dist/db/binding.cjs.map +1 -0
  187. package/dist/db/binding.d.cts +39 -0
  188. package/dist/db/binding.d.mts +39 -0
  189. package/dist/db/binding.mjs +78 -0
  190. package/dist/db/binding.mjs.map +1 -0
  191. package/dist/db/bindings.cjs +78 -0
  192. package/dist/db/bindings.cjs.map +1 -0
  193. package/dist/db/bindings.d.cts +34 -0
  194. package/dist/db/bindings.d.mts +34 -0
  195. package/dist/db/bindings.mjs +76 -0
  196. package/dist/db/bindings.mjs.map +1 -0
  197. package/dist/db/core.cjs +204 -0
  198. package/dist/db/core.cjs.map +1 -0
  199. package/dist/db/core.d.cts +69 -0
  200. package/dist/db/core.d.mts +69 -0
  201. package/dist/db/core.mjs +192 -0
  202. package/dist/db/core.mjs.map +1 -0
  203. package/dist/db/driver.cjs +167 -0
  204. package/dist/db/driver.cjs.map +1 -0
  205. package/dist/db/driver.d.cts +50 -0
  206. package/dist/db/driver.d.mts +50 -0
  207. package/dist/db/driver.mjs +165 -0
  208. package/dist/db/driver.mjs.map +1 -0
  209. package/dist/db/drizzle-kit.cjs +177 -0
  210. package/dist/db/drizzle-kit.cjs.map +1 -0
  211. package/dist/db/drizzle-kit.d.cts +25 -0
  212. package/dist/db/drizzle-kit.d.mts +25 -0
  213. package/dist/db/drizzle-kit.mjs +175 -0
  214. package/dist/db/drizzle-kit.mjs.map +1 -0
  215. package/dist/db/errors.cjs +27 -0
  216. package/dist/db/errors.cjs.map +1 -0
  217. package/dist/db/errors.d.cts +16 -0
  218. package/dist/db/errors.d.mts +16 -0
  219. package/dist/db/errors.mjs +26 -0
  220. package/dist/db/errors.mjs.map +1 -0
  221. package/dist/db/identity.cjs +55 -0
  222. package/dist/db/identity.cjs.map +1 -0
  223. package/dist/db/identity.d.cts +40 -0
  224. package/dist/db/identity.d.mts +40 -0
  225. package/dist/db/identity.mjs +53 -0
  226. package/dist/db/identity.mjs.map +1 -0
  227. package/dist/db/index.cjs +43 -0
  228. package/dist/db/index.d.cts +9 -0
  229. package/dist/db/index.d.mts +9 -0
  230. package/dist/db/index.mjs +10 -0
  231. package/dist/db/run-migrations.cjs +343 -0
  232. package/dist/db/run-migrations.cjs.map +1 -0
  233. package/dist/db/run-migrations.d.cts +87 -0
  234. package/dist/db/run-migrations.d.mts +87 -0
  235. package/dist/db/run-migrations.mjs +341 -0
  236. package/dist/db/run-migrations.mjs.map +1 -0
  237. package/dist/delegate-signer.cjs +85 -0
  238. package/dist/delegate-signer.cjs.map +1 -0
  239. package/dist/delegate-signer.mjs +84 -0
  240. package/dist/delegate-signer.mjs.map +1 -0
  241. package/dist/deploy-diff.cjs +119 -0
  242. package/dist/deploy-diff.cjs.map +1 -0
  243. package/dist/deploy-diff.mjs +109 -0
  244. package/dist/deploy-diff.mjs.map +1 -0
  245. package/dist/descriptor/constructors.cjs +49 -0
  246. package/dist/descriptor/constructors.cjs.map +1 -0
  247. package/dist/descriptor/constructors.d.cts +27 -0
  248. package/dist/descriptor/constructors.d.mts +27 -0
  249. package/dist/descriptor/constructors.mjs +45 -0
  250. package/dist/descriptor/constructors.mjs.map +1 -0
  251. package/dist/descriptor/index.cjs +24 -0
  252. package/dist/descriptor/index.d.cts +5 -0
  253. package/dist/descriptor/index.d.mts +5 -0
  254. package/dist/descriptor/index.mjs +6 -0
  255. package/dist/descriptor/resolve.cjs +258 -0
  256. package/dist/descriptor/resolve.cjs.map +1 -0
  257. package/dist/descriptor/resolve.d.cts +50 -0
  258. package/dist/descriptor/resolve.d.mts +50 -0
  259. package/dist/descriptor/resolve.mjs +252 -0
  260. package/dist/descriptor/resolve.mjs.map +1 -0
  261. package/dist/descriptor/schema.cjs +109 -0
  262. package/dist/descriptor/schema.cjs.map +1 -0
  263. package/dist/descriptor/schema.d.cts +217 -0
  264. package/dist/descriptor/schema.d.mts +217 -0
  265. package/dist/descriptor/schema.mjs +102 -0
  266. package/dist/descriptor/schema.mjs.map +1 -0
  267. package/dist/descriptor/serialize.cjs +45 -0
  268. package/dist/descriptor/serialize.cjs.map +1 -0
  269. package/dist/descriptor/serialize.d.cts +7 -0
  270. package/dist/descriptor/serialize.d.mts +7 -0
  271. package/dist/descriptor/serialize.mjs +45 -0
  272. package/dist/descriptor/serialize.mjs.map +1 -0
  273. package/dist/dev-log-pipeline.cjs +273 -0
  274. package/dist/dev-log-pipeline.cjs.map +1 -0
  275. package/dist/dev-log-pipeline.mjs +267 -0
  276. package/dist/dev-log-pipeline.mjs.map +1 -0
  277. package/dist/dev-logs.cjs +39 -8
  278. package/dist/dev-logs.cjs.map +1 -1
  279. package/dist/dev-logs.mjs +37 -9
  280. package/dist/dev-logs.mjs.map +1 -1
  281. package/dist/dev-program.cjs +405 -0
  282. package/dist/dev-program.cjs.map +1 -0
  283. package/dist/dev-program.d.cts +10 -0
  284. package/dist/dev-program.d.mts +10 -0
  285. package/dist/dev-program.mjs +395 -0
  286. package/dist/dev-program.mjs.map +1 -0
  287. package/dist/dev-session-data.d.cts +27 -0
  288. package/dist/dev-session-data.d.mts +27 -0
  289. package/dist/dev-session.cjs +178 -105
  290. package/dist/dev-session.cjs.map +1 -1
  291. package/dist/dev-session.mjs +180 -105
  292. package/dist/dev-session.mjs.map +1 -1
  293. package/dist/env/process-env.cjs +16 -0
  294. package/dist/env/process-env.cjs.map +1 -0
  295. package/dist/env/process-env.mjs +13 -0
  296. package/dist/env/process-env.mjs.map +1 -0
  297. package/dist/env/project-env.cjs +144 -0
  298. package/dist/env/project-env.cjs.map +1 -0
  299. package/dist/env/project-env.d.cts +1 -0
  300. package/dist/env/project-env.d.mts +1 -0
  301. package/dist/env/project-env.mjs +132 -0
  302. package/dist/env/project-env.mjs.map +1 -0
  303. package/dist/fastkv.cjs +59 -12
  304. package/dist/fastkv.cjs.map +1 -1
  305. package/dist/fastkv.d.cts +42 -6
  306. package/dist/fastkv.d.mts +42 -6
  307. package/dist/fastkv.mjs +58 -13
  308. package/dist/fastkv.mjs.map +1 -1
  309. package/dist/fingerprint.cjs +57 -0
  310. package/dist/fingerprint.cjs.map +1 -0
  311. package/dist/fingerprint.d.cts +14 -0
  312. package/dist/fingerprint.d.mts +14 -0
  313. package/dist/fingerprint.mjs +55 -0
  314. package/dist/fingerprint.mjs.map +1 -0
  315. package/dist/http-client.cjs +17 -17
  316. package/dist/http-client.cjs.map +1 -1
  317. package/dist/http-client.mjs +17 -17
  318. package/dist/http-client.mjs.map +1 -1
  319. package/dist/image-deploy.cjs +186 -0
  320. package/dist/image-deploy.cjs.map +1 -0
  321. package/dist/image-deploy.mjs +182 -0
  322. package/dist/image-deploy.mjs.map +1 -0
  323. package/dist/index.cjs +66 -18
  324. package/dist/index.d.cts +8 -7
  325. package/dist/index.d.mts +8 -7
  326. package/dist/index.mjs +6 -5
  327. package/dist/infra/docker.cjs +77 -0
  328. package/dist/infra/docker.cjs.map +1 -0
  329. package/dist/infra/docker.d.cts +10 -0
  330. package/dist/infra/docker.d.mts +10 -0
  331. package/dist/infra/docker.mjs +69 -0
  332. package/dist/infra/docker.mjs.map +1 -0
  333. package/dist/infra/materializer.cjs +74 -0
  334. package/dist/infra/materializer.cjs.map +1 -0
  335. package/dist/infra/materializer.mjs +70 -0
  336. package/dist/infra/materializer.mjs.map +1 -0
  337. package/dist/infra/planner.cjs +135 -103
  338. package/dist/infra/planner.cjs.map +1 -1
  339. package/dist/infra/planner.mjs +137 -104
  340. package/dist/infra/planner.mjs.map +1 -1
  341. package/dist/infra/port-ownership.cjs +57 -0
  342. package/dist/infra/port-ownership.cjs.map +1 -0
  343. package/dist/infra/port-ownership.mjs +57 -0
  344. package/dist/infra/port-ownership.mjs.map +1 -0
  345. package/dist/infra/preflight.cjs +45 -33
  346. package/dist/infra/preflight.cjs.map +1 -1
  347. package/dist/infra/preflight.d.cts +1 -0
  348. package/dist/infra/preflight.d.mts +1 -0
  349. package/dist/infra/preflight.mjs +46 -34
  350. package/dist/infra/preflight.mjs.map +1 -1
  351. package/dist/infra/types.cjs.map +1 -1
  352. package/dist/infra/types.d.cts +2 -0
  353. package/dist/infra/types.d.mts +2 -0
  354. package/dist/infra/types.mjs.map +1 -1
  355. package/dist/integrity.cjs +50 -61
  356. package/dist/integrity.cjs.map +1 -1
  357. package/dist/integrity.d.cts +16 -10
  358. package/dist/integrity.d.mts +16 -10
  359. package/dist/integrity.mjs +50 -59
  360. package/dist/integrity.mjs.map +1 -1
  361. package/dist/internal/manifest-normalizer.cjs +8 -2
  362. package/dist/internal/manifest-normalizer.cjs.map +1 -1
  363. package/dist/internal/manifest-normalizer.mjs +9 -3
  364. package/dist/internal/manifest-normalizer.mjs.map +1 -1
  365. package/dist/merge.cjs +19 -1
  366. package/dist/merge.cjs.map +1 -1
  367. package/dist/merge.d.cts +1 -1
  368. package/dist/merge.d.mts +1 -1
  369. package/dist/merge.mjs +19 -2
  370. package/dist/merge.mjs.map +1 -1
  371. package/dist/mf.cjs +190 -3
  372. package/dist/mf.cjs.map +1 -1
  373. package/dist/mf.d.cts +24 -2
  374. package/dist/mf.d.mts +24 -2
  375. package/dist/mf.mjs +189 -4
  376. package/dist/mf.mjs.map +1 -1
  377. package/dist/near-cli.cjs +59 -91
  378. package/dist/near-cli.cjs.map +1 -1
  379. package/dist/near-cli.mjs +58 -90
  380. package/dist/near-cli.mjs.map +1 -1
  381. package/dist/near-signer.cjs +73 -0
  382. package/dist/near-signer.cjs.map +1 -0
  383. package/dist/near-signer.mjs +70 -0
  384. package/dist/near-signer.mjs.map +1 -0
  385. package/dist/network.cjs +0 -1
  386. package/dist/network.cjs.map +1 -1
  387. package/dist/orchestrator.cjs +256 -87
  388. package/dist/orchestrator.cjs.map +1 -1
  389. package/dist/orchestrator.mjs +248 -87
  390. package/dist/orchestrator.mjs.map +1 -1
  391. package/dist/platform-deploy.cjs +81 -0
  392. package/dist/platform-deploy.cjs.map +1 -0
  393. package/dist/platform-deploy.mjs +80 -0
  394. package/dist/platform-deploy.mjs.map +1 -0
  395. package/dist/plugin.cjs +54 -1389
  396. package/dist/plugin.cjs.map +1 -1
  397. package/dist/plugin.d.cts +6 -896
  398. package/dist/plugin.d.mts +6 -896
  399. package/dist/plugin.mjs +53 -1387
  400. package/dist/plugin.mjs.map +1 -1
  401. package/dist/process-kill.cjs +44 -0
  402. package/dist/process-kill.cjs.map +1 -0
  403. package/dist/process-kill.mjs +43 -0
  404. package/dist/process-kill.mjs.map +1 -0
  405. package/dist/process-registry.cjs +64 -9
  406. package/dist/process-registry.cjs.map +1 -1
  407. package/dist/process-registry.mjs +61 -10
  408. package/dist/process-registry.mjs.map +1 -1
  409. package/dist/progress.cjs +45 -0
  410. package/dist/progress.cjs.map +1 -0
  411. package/dist/progress.d.cts +13 -0
  412. package/dist/progress.d.mts +13 -0
  413. package/dist/progress.mjs +42 -0
  414. package/dist/progress.mjs.map +1 -0
  415. package/dist/publish.cjs +513 -79
  416. package/dist/publish.cjs.map +1 -1
  417. package/dist/publish.mjs +515 -82
  418. package/dist/publish.mjs.map +1 -1
  419. package/dist/registry-use.cjs +41 -0
  420. package/dist/registry-use.cjs.map +1 -0
  421. package/dist/registry-use.mjs +40 -0
  422. package/dist/registry-use.mjs.map +1 -0
  423. package/dist/resolution/session.cjs +335 -0
  424. package/dist/resolution/session.cjs.map +1 -0
  425. package/dist/resolution/session.d.cts +105 -0
  426. package/dist/resolution/session.d.mts +105 -0
  427. package/dist/resolution/session.mjs +331 -0
  428. package/dist/resolution/session.mjs.map +1 -0
  429. package/dist/rollback.cjs +131 -0
  430. package/dist/rollback.cjs.map +1 -0
  431. package/dist/rollback.mjs +128 -0
  432. package/dist/rollback.mjs.map +1 -0
  433. package/dist/sdk.cjs +7 -7
  434. package/dist/sdk.d.cts +3 -3
  435. package/dist/sdk.d.mts +3 -3
  436. package/dist/sdk.mjs +2 -2
  437. package/dist/service-descriptor.cjs +67 -34
  438. package/dist/service-descriptor.cjs.map +1 -1
  439. package/dist/service-descriptor.d.cts +4 -1
  440. package/dist/service-descriptor.d.mts +3 -0
  441. package/dist/service-descriptor.mjs +63 -35
  442. package/dist/service-descriptor.mjs.map +1 -1
  443. package/dist/shared-deps.cjs +17 -16
  444. package/dist/shared-deps.cjs.map +1 -1
  445. package/dist/shared-deps.mjs +17 -16
  446. package/dist/shared-deps.mjs.map +1 -1
  447. package/dist/start-config-source.cjs +24 -0
  448. package/dist/start-config-source.cjs.map +1 -0
  449. package/dist/start-config-source.d.cts +29 -0
  450. package/dist/start-config-source.d.mts +29 -0
  451. package/dist/start-config-source.mjs +22 -0
  452. package/dist/start-config-source.mjs.map +1 -0
  453. package/dist/storage-upload.cjs +145 -0
  454. package/dist/storage-upload.cjs.map +1 -0
  455. package/dist/storage-upload.mjs +143 -0
  456. package/dist/storage-upload.mjs.map +1 -0
  457. package/dist/types.cjs +126 -20
  458. package/dist/types.cjs.map +1 -1
  459. package/dist/types.d.cts +867 -585
  460. package/dist/types.d.mts +867 -585
  461. package/dist/types.mjs +307 -208
  462. package/dist/types.mjs.map +1 -1
  463. package/dist/ui/api.cjs +105 -0
  464. package/dist/ui/api.cjs.map +1 -0
  465. package/dist/ui/api.d.cts +31 -0
  466. package/dist/ui/api.d.mts +31 -0
  467. package/dist/ui/api.mjs +99 -0
  468. package/dist/ui/api.mjs.map +1 -0
  469. package/dist/ui/auth-guards.cjs +50 -0
  470. package/dist/ui/auth-guards.cjs.map +1 -0
  471. package/dist/ui/auth-guards.d.cts +39 -0
  472. package/dist/ui/auth-guards.d.mts +39 -0
  473. package/dist/ui/auth-guards.mjs +48 -0
  474. package/dist/ui/auth-guards.mjs.map +1 -0
  475. package/dist/ui/auth.cjs +197 -0
  476. package/dist/ui/auth.cjs.map +1 -0
  477. package/dist/ui/auth.d.cts +56 -0
  478. package/dist/ui/auth.d.mts +56 -0
  479. package/dist/ui/auth.mjs +179 -0
  480. package/dist/ui/auth.mjs.map +1 -0
  481. package/dist/ui/entry.cjs +16 -0
  482. package/dist/ui/entry.cjs.map +1 -0
  483. package/dist/ui/entry.d.cts +12 -0
  484. package/dist/ui/entry.d.mts +12 -0
  485. package/dist/ui/entry.mjs +15 -0
  486. package/dist/ui/entry.mjs.map +1 -0
  487. package/dist/ui/head.cjs +14 -7
  488. package/dist/ui/head.cjs.map +1 -1
  489. package/dist/ui/head.mjs +15 -7
  490. package/dist/ui/head.mjs.map +1 -1
  491. package/dist/ui/hydrate.cjs +265 -0
  492. package/dist/ui/hydrate.cjs.map +1 -0
  493. package/dist/ui/hydrate.d.cts +48 -0
  494. package/dist/ui/hydrate.d.mts +48 -0
  495. package/dist/ui/hydrate.mjs +263 -0
  496. package/dist/ui/hydrate.mjs.map +1 -0
  497. package/dist/ui/i18n.cjs +153 -0
  498. package/dist/ui/i18n.cjs.map +1 -0
  499. package/dist/ui/i18n.d.cts +29 -0
  500. package/dist/ui/i18n.d.mts +29 -0
  501. package/dist/ui/i18n.mjs +140 -0
  502. package/dist/ui/i18n.mjs.map +1 -0
  503. package/dist/ui/index.cjs +19 -1
  504. package/dist/ui/index.d.cts +6 -3
  505. package/dist/ui/index.d.mts +6 -3
  506. package/dist/ui/index.mjs +5 -2
  507. package/dist/ui/locale.cjs +53 -0
  508. package/dist/ui/locale.cjs.map +1 -0
  509. package/dist/ui/locale.d.cts +18 -0
  510. package/dist/ui/locale.d.mts +18 -0
  511. package/dist/ui/locale.mjs +49 -0
  512. package/dist/ui/locale.mjs.map +1 -0
  513. package/dist/ui/manifest/index.cjs +25 -0
  514. package/dist/ui/manifest/index.cjs.map +1 -0
  515. package/dist/ui/manifest/index.d.cts +9 -0
  516. package/dist/ui/manifest/index.d.mts +9 -0
  517. package/dist/ui/manifest/index.mjs +13 -0
  518. package/dist/ui/manifest/index.mjs.map +1 -0
  519. package/dist/ui/manifest-generator.cjs +8 -0
  520. package/dist/ui/manifest-generator.d.cts +1 -0
  521. package/dist/ui/manifest-generator.d.mts +1 -0
  522. package/dist/ui/manifest-generator.mjs +3 -0
  523. package/dist/ui/message-catalogs.cjs +8 -0
  524. package/dist/ui/message-catalogs.cjs.map +1 -0
  525. package/dist/ui/message-catalogs.d.cts +5 -0
  526. package/dist/ui/message-catalogs.d.mts +5 -0
  527. package/dist/ui/message-catalogs.mjs +8 -0
  528. package/dist/ui/message-catalogs.mjs.map +1 -0
  529. package/dist/ui/metadata.cjs +0 -1
  530. package/dist/ui/metadata.cjs.map +1 -1
  531. package/dist/ui/metadata.d.cts +1 -1
  532. package/dist/ui/metadata.d.mts +1 -1
  533. package/dist/ui/plugin-path.cjs +37 -0
  534. package/dist/ui/plugin-path.cjs.map +1 -0
  535. package/dist/ui/plugin-path.d.cts +25 -0
  536. package/dist/ui/plugin-path.d.mts +25 -0
  537. package/dist/ui/plugin-path.mjs +35 -0
  538. package/dist/ui/plugin-path.mjs.map +1 -0
  539. package/dist/ui/router-client.cjs +61 -0
  540. package/dist/ui/router-client.cjs.map +1 -0
  541. package/dist/ui/router-client.d.cts +20 -0
  542. package/dist/ui/router-client.d.mts +20 -0
  543. package/dist/ui/router-client.mjs +60 -0
  544. package/dist/ui/router-client.mjs.map +1 -0
  545. package/dist/ui/router-defaults.cjs +48 -0
  546. package/dist/ui/router-defaults.cjs.map +1 -0
  547. package/dist/ui/router-defaults.d.cts +8 -0
  548. package/dist/ui/router-defaults.d.mts +8 -0
  549. package/dist/ui/router-defaults.mjs +45 -0
  550. package/dist/ui/router-defaults.mjs.map +1 -0
  551. package/dist/ui/router-error.cjs +70 -0
  552. package/dist/ui/router-error.cjs.map +1 -0
  553. package/dist/ui/router-error.d.cts +19 -0
  554. package/dist/ui/router-error.d.mts +19 -0
  555. package/dist/ui/router-error.mjs +69 -0
  556. package/dist/ui/router-error.mjs.map +1 -0
  557. package/dist/ui/router-server.cjs +153 -0
  558. package/dist/ui/router-server.cjs.map +1 -0
  559. package/dist/ui/router-server.d.cts +38 -0
  560. package/dist/ui/router-server.d.mts +38 -0
  561. package/dist/ui/router-server.mjs +152 -0
  562. package/dist/ui/router-server.mjs.map +1 -0
  563. package/dist/ui/router.cjs +4 -16
  564. package/dist/ui/router.cjs.map +1 -1
  565. package/dist/ui/router.mjs +4 -15
  566. package/dist/ui/router.mjs.map +1 -1
  567. package/dist/ui/runtime.cjs +5 -1
  568. package/dist/ui/runtime.cjs.map +1 -1
  569. package/dist/ui/runtime.d.cts +2 -1
  570. package/dist/ui/runtime.d.mts +2 -1
  571. package/dist/ui/runtime.mjs +5 -1
  572. package/dist/ui/runtime.mjs.map +1 -1
  573. package/dist/ui/slot.cjs +34 -0
  574. package/dist/ui/slot.cjs.map +1 -0
  575. package/dist/ui/slot.d.cts +43 -0
  576. package/dist/ui/slot.d.mts +43 -0
  577. package/dist/ui/slot.mjs +34 -0
  578. package/dist/ui/slot.mjs.map +1 -0
  579. package/dist/ui/tenant.cjs +300 -0
  580. package/dist/ui/tenant.cjs.map +1 -0
  581. package/dist/ui/tenant.d.cts +122 -0
  582. package/dist/ui/tenant.d.mts +122 -0
  583. package/dist/ui/tenant.mjs +279 -0
  584. package/dist/ui/tenant.mjs.map +1 -0
  585. package/dist/ui/types.d.cts +32 -2
  586. package/dist/ui/types.d.mts +32 -2
  587. package/dist/ui/version-check.cjs +47 -0
  588. package/dist/ui/version-check.cjs.map +1 -0
  589. package/dist/ui/version-check.d.cts +23 -0
  590. package/dist/ui/version-check.d.mts +23 -0
  591. package/dist/ui/version-check.mjs +46 -0
  592. package/dist/ui/version-check.mjs.map +1 -0
  593. package/dist/utils/banner.cjs +2 -2
  594. package/dist/utils/banner.cjs.map +1 -1
  595. package/dist/utils/banner.mjs +2 -2
  596. package/dist/utils/banner.mjs.map +1 -1
  597. package/dist/utils/linkify.cjs +1 -1
  598. package/dist/utils/linkify.cjs.map +1 -1
  599. package/dist/utils/linkify.mjs +1 -0
  600. package/dist/utils/linkify.mjs.map +1 -1
  601. package/dist/utils/run.cjs +6 -6
  602. package/dist/utils/run.cjs.map +1 -1
  603. package/dist/utils/run.mjs +6 -6
  604. package/dist/utils/run.mjs.map +1 -1
  605. package/dist/utils/save-config.cjs +12 -0
  606. package/dist/utils/save-config.cjs.map +1 -1
  607. package/dist/utils/save-config.mjs +12 -0
  608. package/dist/utils/save-config.mjs.map +1 -1
  609. package/dist/utils/snapshot-hash.cjs +10 -0
  610. package/dist/utils/snapshot-hash.cjs.map +1 -0
  611. package/dist/utils/snapshot-hash.mjs +10 -0
  612. package/dist/utils/snapshot-hash.mjs.map +1 -0
  613. package/dist/utils/string.cjs +0 -1
  614. package/dist/utils/string.cjs.map +1 -1
  615. package/dist/utils/theme.cjs +30 -12
  616. package/dist/utils/theme.cjs.map +1 -1
  617. package/dist/utils/theme.mjs +30 -11
  618. package/dist/utils/theme.mjs.map +1 -1
  619. package/dist/version-manifest-deploy.cjs +50 -0
  620. package/dist/version-manifest-deploy.cjs.map +1 -0
  621. package/dist/version-manifest-deploy.mjs +49 -0
  622. package/dist/version-manifest-deploy.mjs.map +1 -0
  623. package/dist/version-manifest-resolve.cjs +42 -0
  624. package/dist/version-manifest-resolve.cjs.map +1 -0
  625. package/dist/version-manifest-resolve.d.cts +38 -0
  626. package/dist/version-manifest-resolve.d.mts +38 -0
  627. package/dist/version-manifest-resolve.mjs +40 -0
  628. package/dist/version-manifest-resolve.mjs.map +1 -0
  629. package/dist/version-status.cjs +18 -0
  630. package/dist/version-status.cjs.map +1 -0
  631. package/dist/version-status.d.cts +22 -0
  632. package/dist/version-status.d.mts +22 -0
  633. package/dist/version-status.mjs +17 -0
  634. package/dist/version-status.mjs.map +1 -0
  635. package/dist/workspace-catalog.cjs +53 -0
  636. package/dist/workspace-catalog.cjs.map +1 -0
  637. package/dist/workspace-catalog.mjs +51 -0
  638. package/dist/workspace-catalog.mjs.map +1 -0
  639. package/dist/workspace.cjs +237 -0
  640. package/dist/workspace.cjs.map +1 -0
  641. package/dist/workspace.mjs +233 -0
  642. package/dist/workspace.mjs.map +1 -0
  643. package/package.json +179 -27
  644. package/skills/add-a-route/SKILL.md +132 -0
  645. package/skills/api-and-auth/SKILL.md +87 -21
  646. package/skills/api-and-auth/references/middleware.md +1 -1
  647. package/skills/cli-reference/SKILL.md +48 -21
  648. package/skills/code-style/SKILL.md +8 -0
  649. package/skills/dev-workflow/SKILL.md +50 -26
  650. package/skills/extends-config/SKILL.md +31 -19
  651. package/skills/init-upgrade/SKILL.md +29 -16
  652. package/skills/plugin-development/SKILL.md +46 -112
  653. package/skills/plugin-development/references/database.md +82 -0
  654. package/skills/plugin-development/references/request-context.md +67 -0
  655. package/skills/publish-sync/SKILL.md +99 -22
  656. package/skills/registry/SKILL.md +82 -0
  657. package/skills/super-app/SKILL.md +25 -15
  658. package/skills/talk-to-the-app/SKILL.md +138 -0
  659. package/skills/ui-integration/SKILL.md +93 -11
  660. package/dist/cli/db-studio.cjs +0 -131
  661. package/dist/cli/db-studio.cjs.map +0 -1
  662. package/dist/cli/db-studio.mjs +0 -127
  663. package/dist/cli/db-studio.mjs.map +0 -1
  664. package/dist/cli/init.d.cts.map +0 -1
  665. package/dist/cli/init.d.mts.map +0 -1
  666. package/dist/components/dev-view.cjs +0 -309
  667. package/dist/components/dev-view.cjs.map +0 -1
  668. package/dist/components/dev-view.mjs +0 -309
  669. package/dist/components/dev-view.mjs.map +0 -1
  670. package/dist/components/streaming-view.cjs +0 -134
  671. package/dist/components/streaming-view.cjs.map +0 -1
  672. package/dist/components/streaming-view.mjs +0 -132
  673. package/dist/components/streaming-view.mjs.map +0 -1
  674. package/dist/config.d.cts.map +0 -1
  675. package/dist/config.d.mts.map +0 -1
  676. package/dist/contract.d.cts.map +0 -1
  677. package/dist/contract.d.mts.map +0 -1
  678. package/dist/contract.meta.d.cts.map +0 -1
  679. package/dist/contract.meta.d.mts.map +0 -1
  680. package/dist/dag.d.cts.map +0 -1
  681. package/dist/dag.d.mts.map +0 -1
  682. package/dist/db.cjs +0 -81
  683. package/dist/db.cjs.map +0 -1
  684. package/dist/db.d.cts +0 -30
  685. package/dist/db.d.cts.map +0 -1
  686. package/dist/db.d.mts +0 -30
  687. package/dist/db.d.mts.map +0 -1
  688. package/dist/db.mjs +0 -75
  689. package/dist/db.mjs.map +0 -1
  690. package/dist/fastkv.d.cts.map +0 -1
  691. package/dist/fastkv.d.mts.map +0 -1
  692. package/dist/integrity.d.cts.map +0 -1
  693. package/dist/integrity.d.mts.map +0 -1
  694. package/dist/merge.d.cts.map +0 -1
  695. package/dist/merge.d.mts.map +0 -1
  696. package/dist/mf.d.cts.map +0 -1
  697. package/dist/mf.d.mts.map +0 -1
  698. package/dist/plugin.d.cts.map +0 -1
  699. package/dist/plugin.d.mts.map +0 -1
  700. package/dist/service-descriptor.d.cts.map +0 -1
  701. package/dist/service-descriptor.d.mts.map +0 -1
  702. package/dist/types.d.cts.map +0 -1
  703. package/dist/types.d.mts.map +0 -1
  704. package/dist/ui/head.d.cts.map +0 -1
  705. package/dist/ui/head.d.mts.map +0 -1
  706. package/dist/ui/metadata.d.cts.map +0 -1
  707. package/dist/ui/metadata.d.mts.map +0 -1
  708. package/dist/ui/router.d.cts.map +0 -1
  709. package/dist/ui/router.d.mts.map +0 -1
  710. package/dist/ui/runtime.d.cts.map +0 -1
  711. package/dist/ui/runtime.d.mts.map +0 -1
  712. package/dist/ui/types.d.cts.map +0 -1
  713. package/dist/ui/types.d.mts.map +0 -1
@@ -78,6 +78,18 @@ async function promptInitBasic(input) {
78
78
  };
79
79
  }
80
80
  async function promptInitOverrides(input) {
81
+ const level = input.level ?? await _clack_prompts.select({
82
+ message: "How much starter app do you want?",
83
+ options: [{
84
+ value: "simple",
85
+ hint: "Public pages only — landing, about, login via the auth plugin"
86
+ }, {
87
+ value: "advanced",
88
+ hint: "Adds the dashboard, organizations, and admin areas"
89
+ }],
90
+ initialValue: "simple"
91
+ });
92
+ if (_clack_prompts.isCancel(level)) node_process.default.exit(0);
81
93
  const overrides = input.overrides ?? await _clack_prompts.multiselect({
82
94
  message: "What do you want to customize?",
83
95
  options: OVERRIDE_OPTIONS,
@@ -106,7 +118,8 @@ async function promptInitOverrides(input) {
106
118
  if (_clack_prompts.isCancel(go) || !go) node_process.default.exit(0);
107
119
  return {
108
120
  overrides,
109
- plugins
121
+ plugins,
122
+ level
110
123
  };
111
124
  }
112
125
 
@@ -1 +1 @@
1
- {"version":3,"file":"prompts.cjs","names":["p"],"sources":["../../src/cli/prompts.ts"],"sourcesContent":["import process from \"node:process\";\nimport * as p from \"@clack/prompts\";\nimport type { OverrideSection } from \"../contract\";\n\nfunction parseExtendsRef(ref: string): { account: string; gateway: string } | null {\n const normalized = ref.startsWith(\"bos://\") ? ref : `bos://${ref}`;\n const match = normalized.match(/^bos:\\/\\/([^/]+)\\/(.+)$/);\n if (!match) return null;\n return { account: match[1], gateway: match[2] };\n}\n\nfunction deriveAccountFromExtends(domain: string, extendsAccount: string): string {\n const firstSegment = domain.split(\".\")[0];\n if (!firstSegment) return \"\";\n const suffix = extendsAccount.includes(\".\")\n ? extendsAccount.substring(extendsAccount.indexOf(\".\") + 1)\n : extendsAccount;\n return `${firstSegment}.${suffix}`;\n}\n\nconst OVERRIDE_OPTIONS: { value: OverrideSection; label: string; hint: string }[] = [\n { value: \"ui\", label: \"ui\", hint: \"Override UI with local source\" },\n { value: \"api\", label: \"api\", hint: \"Override API with local source\" },\n { value: \"host\", label: \"host\", hint: \"Override host with local source\" },\n { value: \"plugins\", label: \"plugins\", hint: \"Override selected plugins with local source\" },\n];\n\nexport async function promptInitBasic(input: {\n domain?: string;\n account?: string;\n extends?: string;\n}): Promise<{\n extendsAccount: string;\n extendsGateway: string;\n domain: string;\n account?: string;\n}> {\n p.intro(\"Let's build an app...\");\n\n const domain =\n input.domain ??\n ((await p.text({\n message: \"Starting with a domain?\",\n placeholder: \"no\",\n })) as string);\n\n if (p.isCancel(domain)) process.exit(0);\n\n let extendsAccount = \"dev.everything.near\";\n let extendsGateway = \"everything.dev\";\n\n const accountDefault = domain ? deriveAccountFromExtends(domain, extendsAccount) : \"\";\n const account =\n input.account ??\n ((await p.text({\n message: \"What NEAR account will you publish from?\",\n placeholder: accountDefault || \"skip\",\n defaultValue: accountDefault,\n })) as string);\n\n if (p.isCancel(account)) process.exit(0);\n\n const resolvedAccount = account || accountDefault;\n const extendsInput =\n input.extends ??\n ((await p.text({\n message: \"Extending an existing app?\",\n placeholder: \"bos://dev.everything.near/dev.everything.dev\",\n defaultValue: \"bos://dev.everything.near/dev.everything.dev\",\n })) as string);\n\n if (p.isCancel(extendsInput)) process.exit(0);\n\n if (extendsInput) {\n const parsed = parseExtendsRef(extendsInput);\n if (parsed) {\n extendsAccount = parsed.account;\n extendsGateway = parsed.gateway;\n }\n }\n\n return {\n extendsAccount,\n extendsGateway,\n domain: domain || \"\",\n account: resolvedAccount || undefined,\n };\n}\n\nexport async function promptInitOverrides(input: {\n parentPluginKeys?: string[];\n overrides?: OverrideSection[];\n plugins?: string[];\n}): Promise<{\n overrides: OverrideSection[];\n plugins: string[];\n}> {\n const overrides =\n input.overrides ??\n ((await p.multiselect({\n message: \"What do you want to customize?\",\n options: OVERRIDE_OPTIONS,\n initialValues: [\"ui\", \"api\"] as OverrideSection[],\n required: false,\n })) as OverrideSection[]);\n\n if (p.isCancel(overrides)) process.exit(0);\n\n let plugins: string[] = [];\n if (overrides.includes(\"plugins\")) {\n const parentPlugins = input.parentPluginKeys ?? [];\n const pluginOptions =\n parentPlugins.length > 0 ? parentPlugins.map((key) => ({ value: key, label: key })) : [];\n\n plugins =\n input.plugins ??\n (pluginOptions.length > 0\n ? ((await p.multiselect({\n message: \"Select plugins to include:\",\n options: pluginOptions,\n required: false,\n })) as string[])\n : []);\n\n if (p.isCancel(plugins)) process.exit(0);\n }\n\n const go = await p.confirm({\n message: \"GO!\",\n initialValue: true,\n });\n\n if (p.isCancel(go) || !go) process.exit(0);\n\n return { overrides, plugins };\n}\n"],"mappings":";;;;;;;AAIA,SAAS,gBAAgB,KAA0D;CAEjF,MAAM,SADa,IAAI,WAAW,QAAQ,IAAI,MAAM,SAAS,MACrC,CAAC,MAAM,yBAAyB;CACxD,IAAI,CAAC,OAAO,OAAO;CACnB,OAAO;EAAE,SAAS,MAAM;EAAI,SAAS,MAAM;CAAG;AAChD;AAEA,SAAS,yBAAyB,QAAgB,gBAAgC;CAChF,MAAM,eAAe,OAAO,MAAM,GAAG,CAAC,CAAC;CACvC,IAAI,CAAC,cAAc,OAAO;CAI1B,OAAO,GAAG,aAAa,GAHR,eAAe,SAAS,GAAG,IACtC,eAAe,UAAU,eAAe,QAAQ,GAAG,IAAI,CAAC,IACxD;AAEN;AAEA,MAAM,mBAA8E;CAClF;EAAE,OAAO;EAAM,OAAO;EAAM,MAAM;CAAgC;CAClE;EAAE,OAAO;EAAO,OAAO;EAAO,MAAM;CAAiC;CACrE;EAAE,OAAO;EAAQ,OAAO;EAAQ,MAAM;CAAkC;CACxE;EAAE,OAAO;EAAW,OAAO;EAAW,MAAM;CAA8C;AAC5F;AAEA,eAAsB,gBAAgB,OASnC;CACD,eAAE,MAAM,uBAAuB;CAE/B,MAAM,SACJ,MAAM,UACJ,MAAMA,eAAE,KAAK;EACb,SAAS;EACT,aAAa;CACf,CAAC;CAEH,IAAIA,eAAE,SAAS,MAAM,GAAG,qBAAQ,KAAK,CAAC;CAEtC,IAAI,iBAAiB;CACrB,IAAI,iBAAiB;CAErB,MAAM,iBAAiB,SAAS,yBAAyB,QAAQ,cAAc,IAAI;CACnF,MAAM,UACJ,MAAM,WACJ,MAAMA,eAAE,KAAK;EACb,SAAS;EACT,aAAa,kBAAkB;EAC/B,cAAc;CAChB,CAAC;CAEH,IAAIA,eAAE,SAAS,OAAO,GAAG,qBAAQ,KAAK,CAAC;CAEvC,MAAM,kBAAkB,WAAW;CACnC,MAAM,eACJ,MAAM,WACJ,MAAMA,eAAE,KAAK;EACb,SAAS;EACT,aAAa;EACb,cAAc;CAChB,CAAC;CAEH,IAAIA,eAAE,SAAS,YAAY,GAAG,qBAAQ,KAAK,CAAC;CAE5C,IAAI,cAAc;EAChB,MAAM,SAAS,gBAAgB,YAAY;EAC3C,IAAI,QAAQ;GACV,iBAAiB,OAAO;GACxB,iBAAiB,OAAO;EAC1B;CACF;CAEA,OAAO;EACL;EACA;EACA,QAAQ,UAAU;EAClB,SAAS,mBAAmB;CAC9B;AACF;AAEA,eAAsB,oBAAoB,OAOvC;CACD,MAAM,YACJ,MAAM,aACJ,MAAMA,eAAE,YAAY;EACpB,SAAS;EACT,SAAS;EACT,eAAe,CAAC,MAAM,KAAK;EAC3B,UAAU;CACZ,CAAC;CAEH,IAAIA,eAAE,SAAS,SAAS,GAAG,qBAAQ,KAAK,CAAC;CAEzC,IAAI,UAAoB,CAAC;CACzB,IAAI,UAAU,SAAS,SAAS,GAAG;EACjC,MAAM,gBAAgB,MAAM,oBAAoB,CAAC;EACjD,MAAM,gBACJ,cAAc,SAAS,IAAI,cAAc,KAAK,SAAS;GAAE,OAAO;GAAK,OAAO;EAAI,EAAE,IAAI,CAAC;EAEzF,UACE,MAAM,YACL,cAAc,SAAS,IAClB,MAAMA,eAAE,YAAY;GACpB,SAAS;GACT,SAAS;GACT,UAAU;EACZ,CAAC,IACD,CAAC;EAEP,IAAIA,eAAE,SAAS,OAAO,GAAG,qBAAQ,KAAK,CAAC;CACzC;CAEA,MAAM,KAAK,MAAMA,eAAE,QAAQ;EACzB,SAAS;EACT,cAAc;CAChB,CAAC;CAED,IAAIA,eAAE,SAAS,EAAE,KAAK,CAAC,IAAI,qBAAQ,KAAK,CAAC;CAEzC,OAAO;EAAE;EAAW;CAAQ;AAC9B"}
1
+ {"version":3,"file":"prompts.cjs","names":["p"],"sources":["../../src/cli/prompts.ts"],"sourcesContent":["import process from \"node:process\";\nimport * as p from \"@clack/prompts\";\nimport type { OverrideSection } from \"../contract\";\nimport type { StarterLevel } from \"../types\";\n\nfunction parseExtendsRef(ref: string): { account: string; gateway: string } | null {\n const normalized = ref.startsWith(\"bos://\") ? ref : `bos://${ref}`;\n const match = normalized.match(/^bos:\\/\\/([^/]+)\\/(.+)$/);\n if (!match) return null;\n return { account: match[1], gateway: match[2] };\n}\n\nfunction deriveAccountFromExtends(domain: string, extendsAccount: string): string {\n const firstSegment = domain.split(\".\")[0];\n if (!firstSegment) return \"\";\n const suffix = extendsAccount.includes(\".\")\n ? extendsAccount.substring(extendsAccount.indexOf(\".\") + 1)\n : extendsAccount;\n return `${firstSegment}.${suffix}`;\n}\n\nconst OVERRIDE_OPTIONS: { value: OverrideSection; label: string; hint: string }[] = [\n { value: \"ui\", label: \"ui\", hint: \"Override UI with local source\" },\n { value: \"api\", label: \"api\", hint: \"Override API with local source\" },\n { value: \"host\", label: \"host\", hint: \"Override host with local source\" },\n { value: \"plugins\", label: \"plugins\", hint: \"Override selected plugins with local source\" },\n];\n\nexport async function promptInitBasic(input: {\n domain?: string;\n account?: string;\n extends?: string;\n}): Promise<{\n extendsAccount: string;\n extendsGateway: string;\n domain: string;\n account?: string;\n}> {\n p.intro(\"Let's build an app...\");\n\n const domain =\n input.domain ??\n ((await p.text({\n message: \"Starting with a domain?\",\n placeholder: \"no\",\n })) as string);\n\n if (p.isCancel(domain)) process.exit(0);\n\n let extendsAccount = \"dev.everything.near\";\n let extendsGateway = \"everything.dev\";\n\n const accountDefault = domain ? deriveAccountFromExtends(domain, extendsAccount) : \"\";\n const account =\n input.account ??\n ((await p.text({\n message: \"What NEAR account will you publish from?\",\n placeholder: accountDefault || \"skip\",\n defaultValue: accountDefault,\n })) as string);\n\n if (p.isCancel(account)) process.exit(0);\n\n const resolvedAccount = account || accountDefault;\n const extendsInput =\n input.extends ??\n ((await p.text({\n message: \"Extending an existing app?\",\n placeholder: \"bos://dev.everything.near/dev.everything.dev\",\n defaultValue: \"bos://dev.everything.near/dev.everything.dev\",\n })) as string);\n\n if (p.isCancel(extendsInput)) process.exit(0);\n\n if (extendsInput) {\n const parsed = parseExtendsRef(extendsInput);\n if (parsed) {\n extendsAccount = parsed.account;\n extendsGateway = parsed.gateway;\n }\n }\n\n return {\n extendsAccount,\n extendsGateway,\n domain: domain || \"\",\n account: resolvedAccount || undefined,\n };\n}\n\nexport async function promptInitOverrides(input: {\n parentPluginKeys?: string[];\n overrides?: OverrideSection[];\n plugins?: string[];\n level?: StarterLevel;\n}): Promise<{\n overrides: OverrideSection[];\n plugins: string[];\n level?: StarterLevel;\n}> {\n const level =\n input.level ??\n ((await p.select({\n message: \"How much starter app do you want?\",\n options: [\n { value: \"simple\", hint: \"Public pages only — landing, about, login via the auth plugin\" },\n {\n value: \"advanced\",\n hint: \"Adds the dashboard, organizations, and admin areas\",\n },\n ],\n initialValue: \"simple\",\n })) as StarterLevel | undefined);\n\n if (p.isCancel(level)) process.exit(0);\n\n const overrides =\n input.overrides ??\n ((await p.multiselect({\n message: \"What do you want to customize?\",\n options: OVERRIDE_OPTIONS,\n initialValues: [\"ui\", \"api\"] as OverrideSection[],\n required: false,\n })) as OverrideSection[]);\n\n if (p.isCancel(overrides)) process.exit(0);\n\n let plugins: string[] = [];\n if (overrides.includes(\"plugins\")) {\n const parentPlugins = input.parentPluginKeys ?? [];\n const pluginOptions =\n parentPlugins.length > 0 ? parentPlugins.map((key) => ({ value: key, label: key })) : [];\n\n plugins =\n input.plugins ??\n (pluginOptions.length > 0\n ? ((await p.multiselect({\n message: \"Select plugins to include:\",\n options: pluginOptions,\n required: false,\n })) as string[])\n : []);\n\n if (p.isCancel(plugins)) process.exit(0);\n }\n\n const go = await p.confirm({\n message: \"GO!\",\n initialValue: true,\n });\n\n if (p.isCancel(go) || !go) process.exit(0);\n\n return { overrides, plugins, level };\n}\n"],"mappings":"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"}
@@ -75,6 +75,18 @@ async function promptInitBasic(input) {
75
75
  };
76
76
  }
77
77
  async function promptInitOverrides(input) {
78
+ const level = input.level ?? await p.select({
79
+ message: "How much starter app do you want?",
80
+ options: [{
81
+ value: "simple",
82
+ hint: "Public pages only — landing, about, login via the auth plugin"
83
+ }, {
84
+ value: "advanced",
85
+ hint: "Adds the dashboard, organizations, and admin areas"
86
+ }],
87
+ initialValue: "simple"
88
+ });
89
+ if (p.isCancel(level)) process.exit(0);
78
90
  const overrides = input.overrides ?? await p.multiselect({
79
91
  message: "What do you want to customize?",
80
92
  options: OVERRIDE_OPTIONS,
@@ -103,7 +115,8 @@ async function promptInitOverrides(input) {
103
115
  if (p.isCancel(go) || !go) process.exit(0);
104
116
  return {
105
117
  overrides,
106
- plugins
118
+ plugins,
119
+ level
107
120
  };
108
121
  }
109
122
 
@@ -1 +1 @@
1
- {"version":3,"file":"prompts.mjs","names":[],"sources":["../../src/cli/prompts.ts"],"sourcesContent":["import process from \"node:process\";\nimport * as p from \"@clack/prompts\";\nimport type { OverrideSection } from \"../contract\";\n\nfunction parseExtendsRef(ref: string): { account: string; gateway: string } | null {\n const normalized = ref.startsWith(\"bos://\") ? ref : `bos://${ref}`;\n const match = normalized.match(/^bos:\\/\\/([^/]+)\\/(.+)$/);\n if (!match) return null;\n return { account: match[1], gateway: match[2] };\n}\n\nfunction deriveAccountFromExtends(domain: string, extendsAccount: string): string {\n const firstSegment = domain.split(\".\")[0];\n if (!firstSegment) return \"\";\n const suffix = extendsAccount.includes(\".\")\n ? extendsAccount.substring(extendsAccount.indexOf(\".\") + 1)\n : extendsAccount;\n return `${firstSegment}.${suffix}`;\n}\n\nconst OVERRIDE_OPTIONS: { value: OverrideSection; label: string; hint: string }[] = [\n { value: \"ui\", label: \"ui\", hint: \"Override UI with local source\" },\n { value: \"api\", label: \"api\", hint: \"Override API with local source\" },\n { value: \"host\", label: \"host\", hint: \"Override host with local source\" },\n { value: \"plugins\", label: \"plugins\", hint: \"Override selected plugins with local source\" },\n];\n\nexport async function promptInitBasic(input: {\n domain?: string;\n account?: string;\n extends?: string;\n}): Promise<{\n extendsAccount: string;\n extendsGateway: string;\n domain: string;\n account?: string;\n}> {\n p.intro(\"Let's build an app...\");\n\n const domain =\n input.domain ??\n ((await p.text({\n message: \"Starting with a domain?\",\n placeholder: \"no\",\n })) as string);\n\n if (p.isCancel(domain)) process.exit(0);\n\n let extendsAccount = \"dev.everything.near\";\n let extendsGateway = \"everything.dev\";\n\n const accountDefault = domain ? deriveAccountFromExtends(domain, extendsAccount) : \"\";\n const account =\n input.account ??\n ((await p.text({\n message: \"What NEAR account will you publish from?\",\n placeholder: accountDefault || \"skip\",\n defaultValue: accountDefault,\n })) as string);\n\n if (p.isCancel(account)) process.exit(0);\n\n const resolvedAccount = account || accountDefault;\n const extendsInput =\n input.extends ??\n ((await p.text({\n message: \"Extending an existing app?\",\n placeholder: \"bos://dev.everything.near/dev.everything.dev\",\n defaultValue: \"bos://dev.everything.near/dev.everything.dev\",\n })) as string);\n\n if (p.isCancel(extendsInput)) process.exit(0);\n\n if (extendsInput) {\n const parsed = parseExtendsRef(extendsInput);\n if (parsed) {\n extendsAccount = parsed.account;\n extendsGateway = parsed.gateway;\n }\n }\n\n return {\n extendsAccount,\n extendsGateway,\n domain: domain || \"\",\n account: resolvedAccount || undefined,\n };\n}\n\nexport async function promptInitOverrides(input: {\n parentPluginKeys?: string[];\n overrides?: OverrideSection[];\n plugins?: string[];\n}): Promise<{\n overrides: OverrideSection[];\n plugins: string[];\n}> {\n const overrides =\n input.overrides ??\n ((await p.multiselect({\n message: \"What do you want to customize?\",\n options: OVERRIDE_OPTIONS,\n initialValues: [\"ui\", \"api\"] as OverrideSection[],\n required: false,\n })) as OverrideSection[]);\n\n if (p.isCancel(overrides)) process.exit(0);\n\n let plugins: string[] = [];\n if (overrides.includes(\"plugins\")) {\n const parentPlugins = input.parentPluginKeys ?? [];\n const pluginOptions =\n parentPlugins.length > 0 ? parentPlugins.map((key) => ({ value: key, label: key })) : [];\n\n plugins =\n input.plugins ??\n (pluginOptions.length > 0\n ? ((await p.multiselect({\n message: \"Select plugins to include:\",\n options: pluginOptions,\n required: false,\n })) as string[])\n : []);\n\n if (p.isCancel(plugins)) process.exit(0);\n }\n\n const go = await p.confirm({\n message: \"GO!\",\n initialValue: true,\n });\n\n if (p.isCancel(go) || !go) process.exit(0);\n\n return { overrides, plugins };\n}\n"],"mappings":";;;;AAIA,SAAS,gBAAgB,KAA0D;CAEjF,MAAM,SADa,IAAI,WAAW,QAAQ,IAAI,MAAM,SAAS,MACrC,CAAC,MAAM,yBAAyB;CACxD,IAAI,CAAC,OAAO,OAAO;CACnB,OAAO;EAAE,SAAS,MAAM;EAAI,SAAS,MAAM;CAAG;AAChD;AAEA,SAAS,yBAAyB,QAAgB,gBAAgC;CAChF,MAAM,eAAe,OAAO,MAAM,GAAG,CAAC,CAAC;CACvC,IAAI,CAAC,cAAc,OAAO;CAI1B,OAAO,GAAG,aAAa,GAHR,eAAe,SAAS,GAAG,IACtC,eAAe,UAAU,eAAe,QAAQ,GAAG,IAAI,CAAC,IACxD;AAEN;AAEA,MAAM,mBAA8E;CAClF;EAAE,OAAO;EAAM,OAAO;EAAM,MAAM;CAAgC;CAClE;EAAE,OAAO;EAAO,OAAO;EAAO,MAAM;CAAiC;CACrE;EAAE,OAAO;EAAQ,OAAO;EAAQ,MAAM;CAAkC;CACxE;EAAE,OAAO;EAAW,OAAO;EAAW,MAAM;CAA8C;AAC5F;AAEA,eAAsB,gBAAgB,OASnC;CACD,EAAE,MAAM,uBAAuB;CAE/B,MAAM,SACJ,MAAM,UACJ,MAAM,EAAE,KAAK;EACb,SAAS;EACT,aAAa;CACf,CAAC;CAEH,IAAI,EAAE,SAAS,MAAM,GAAG,QAAQ,KAAK,CAAC;CAEtC,IAAI,iBAAiB;CACrB,IAAI,iBAAiB;CAErB,MAAM,iBAAiB,SAAS,yBAAyB,QAAQ,cAAc,IAAI;CACnF,MAAM,UACJ,MAAM,WACJ,MAAM,EAAE,KAAK;EACb,SAAS;EACT,aAAa,kBAAkB;EAC/B,cAAc;CAChB,CAAC;CAEH,IAAI,EAAE,SAAS,OAAO,GAAG,QAAQ,KAAK,CAAC;CAEvC,MAAM,kBAAkB,WAAW;CACnC,MAAM,eACJ,MAAM,WACJ,MAAM,EAAE,KAAK;EACb,SAAS;EACT,aAAa;EACb,cAAc;CAChB,CAAC;CAEH,IAAI,EAAE,SAAS,YAAY,GAAG,QAAQ,KAAK,CAAC;CAE5C,IAAI,cAAc;EAChB,MAAM,SAAS,gBAAgB,YAAY;EAC3C,IAAI,QAAQ;GACV,iBAAiB,OAAO;GACxB,iBAAiB,OAAO;EAC1B;CACF;CAEA,OAAO;EACL;EACA;EACA,QAAQ,UAAU;EAClB,SAAS,mBAAmB;CAC9B;AACF;AAEA,eAAsB,oBAAoB,OAOvC;CACD,MAAM,YACJ,MAAM,aACJ,MAAM,EAAE,YAAY;EACpB,SAAS;EACT,SAAS;EACT,eAAe,CAAC,MAAM,KAAK;EAC3B,UAAU;CACZ,CAAC;CAEH,IAAI,EAAE,SAAS,SAAS,GAAG,QAAQ,KAAK,CAAC;CAEzC,IAAI,UAAoB,CAAC;CACzB,IAAI,UAAU,SAAS,SAAS,GAAG;EACjC,MAAM,gBAAgB,MAAM,oBAAoB,CAAC;EACjD,MAAM,gBACJ,cAAc,SAAS,IAAI,cAAc,KAAK,SAAS;GAAE,OAAO;GAAK,OAAO;EAAI,EAAE,IAAI,CAAC;EAEzF,UACE,MAAM,YACL,cAAc,SAAS,IAClB,MAAM,EAAE,YAAY;GACpB,SAAS;GACT,SAAS;GACT,UAAU;EACZ,CAAC,IACD,CAAC;EAEP,IAAI,EAAE,SAAS,OAAO,GAAG,QAAQ,KAAK,CAAC;CACzC;CAEA,MAAM,KAAK,MAAM,EAAE,QAAQ;EACzB,SAAS;EACT,cAAc;CAChB,CAAC;CAED,IAAI,EAAE,SAAS,EAAE,KAAK,CAAC,IAAI,QAAQ,KAAK,CAAC;CAEzC,OAAO;EAAE;EAAW;CAAQ;AAC9B"}
1
+ {"version":3,"file":"prompts.mjs","names":[],"sources":["../../src/cli/prompts.ts"],"sourcesContent":["import process from \"node:process\";\nimport * as p from \"@clack/prompts\";\nimport type { OverrideSection } from \"../contract\";\nimport type { StarterLevel } from \"../types\";\n\nfunction parseExtendsRef(ref: string): { account: string; gateway: string } | null {\n const normalized = ref.startsWith(\"bos://\") ? ref : `bos://${ref}`;\n const match = normalized.match(/^bos:\\/\\/([^/]+)\\/(.+)$/);\n if (!match) return null;\n return { account: match[1], gateway: match[2] };\n}\n\nfunction deriveAccountFromExtends(domain: string, extendsAccount: string): string {\n const firstSegment = domain.split(\".\")[0];\n if (!firstSegment) return \"\";\n const suffix = extendsAccount.includes(\".\")\n ? extendsAccount.substring(extendsAccount.indexOf(\".\") + 1)\n : extendsAccount;\n return `${firstSegment}.${suffix}`;\n}\n\nconst OVERRIDE_OPTIONS: { value: OverrideSection; label: string; hint: string }[] = [\n { value: \"ui\", label: \"ui\", hint: \"Override UI with local source\" },\n { value: \"api\", label: \"api\", hint: \"Override API with local source\" },\n { value: \"host\", label: \"host\", hint: \"Override host with local source\" },\n { value: \"plugins\", label: \"plugins\", hint: \"Override selected plugins with local source\" },\n];\n\nexport async function promptInitBasic(input: {\n domain?: string;\n account?: string;\n extends?: string;\n}): Promise<{\n extendsAccount: string;\n extendsGateway: string;\n domain: string;\n account?: string;\n}> {\n p.intro(\"Let's build an app...\");\n\n const domain =\n input.domain ??\n ((await p.text({\n message: \"Starting with a domain?\",\n placeholder: \"no\",\n })) as string);\n\n if (p.isCancel(domain)) process.exit(0);\n\n let extendsAccount = \"dev.everything.near\";\n let extendsGateway = \"everything.dev\";\n\n const accountDefault = domain ? deriveAccountFromExtends(domain, extendsAccount) : \"\";\n const account =\n input.account ??\n ((await p.text({\n message: \"What NEAR account will you publish from?\",\n placeholder: accountDefault || \"skip\",\n defaultValue: accountDefault,\n })) as string);\n\n if (p.isCancel(account)) process.exit(0);\n\n const resolvedAccount = account || accountDefault;\n const extendsInput =\n input.extends ??\n ((await p.text({\n message: \"Extending an existing app?\",\n placeholder: \"bos://dev.everything.near/dev.everything.dev\",\n defaultValue: \"bos://dev.everything.near/dev.everything.dev\",\n })) as string);\n\n if (p.isCancel(extendsInput)) process.exit(0);\n\n if (extendsInput) {\n const parsed = parseExtendsRef(extendsInput);\n if (parsed) {\n extendsAccount = parsed.account;\n extendsGateway = parsed.gateway;\n }\n }\n\n return {\n extendsAccount,\n extendsGateway,\n domain: domain || \"\",\n account: resolvedAccount || undefined,\n };\n}\n\nexport async function promptInitOverrides(input: {\n parentPluginKeys?: string[];\n overrides?: OverrideSection[];\n plugins?: string[];\n level?: StarterLevel;\n}): Promise<{\n overrides: OverrideSection[];\n plugins: string[];\n level?: StarterLevel;\n}> {\n const level =\n input.level ??\n ((await p.select({\n message: \"How much starter app do you want?\",\n options: [\n { value: \"simple\", hint: \"Public pages only — landing, about, login via the auth plugin\" },\n {\n value: \"advanced\",\n hint: \"Adds the dashboard, organizations, and admin areas\",\n },\n ],\n initialValue: \"simple\",\n })) as StarterLevel | undefined);\n\n if (p.isCancel(level)) process.exit(0);\n\n const overrides =\n input.overrides ??\n ((await p.multiselect({\n message: \"What do you want to customize?\",\n options: OVERRIDE_OPTIONS,\n initialValues: [\"ui\", \"api\"] as OverrideSection[],\n required: false,\n })) as OverrideSection[]);\n\n if (p.isCancel(overrides)) process.exit(0);\n\n let plugins: string[] = [];\n if (overrides.includes(\"plugins\")) {\n const parentPlugins = input.parentPluginKeys ?? [];\n const pluginOptions =\n parentPlugins.length > 0 ? parentPlugins.map((key) => ({ value: key, label: key })) : [];\n\n plugins =\n input.plugins ??\n (pluginOptions.length > 0\n ? ((await p.multiselect({\n message: \"Select plugins to include:\",\n options: pluginOptions,\n required: false,\n })) as string[])\n : []);\n\n if (p.isCancel(plugins)) process.exit(0);\n }\n\n const go = await p.confirm({\n message: \"GO!\",\n initialValue: true,\n });\n\n if (p.isCancel(go) || !go) process.exit(0);\n\n return { overrides, plugins, level };\n}\n"],"mappings":"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"}
@@ -0,0 +1,220 @@
1
+ const require_sync = require('./sync.cjs');
2
+ let node_fs = require("node:fs");
3
+ let node_path = require("node:path");
4
+
5
+ //#region src/cli/prune.ts
6
+ const EXTENSIONS = [
7
+ "",
8
+ ".ts",
9
+ ".tsx",
10
+ ".css",
11
+ ".json",
12
+ ".png",
13
+ ".gif",
14
+ ".svg",
15
+ ".jpg",
16
+ ".webp",
17
+ ".ico",
18
+ ".mjs"
19
+ ];
20
+ function splitNamedImports(clause) {
21
+ let wholeModule = false;
22
+ const names = [];
23
+ const withoutNamed = clause.replace(/\{[^}]*\}/g, " ").replace(/^\s*(?:import|export)\b/, "");
24
+ for (const piece of withoutNamed.split(",")) {
25
+ const token = piece.trim();
26
+ if (!token) continue;
27
+ if (token.includes("*")) {
28
+ wholeModule = true;
29
+ continue;
30
+ }
31
+ if (/^[A-Za-z_$][\w$]*$/.test(token)) wholeModule = true;
32
+ }
33
+ for (const named of clause.matchAll(/\{([^}]*)\}/g)) for (const piece of named[1].split(",")) {
34
+ const name = piece.trim().replace(/^type\s+/, "").split(/\s+as\s+/)[0]?.trim();
35
+ if (name && name !== "default") names.push(name);
36
+ }
37
+ return {
38
+ names,
39
+ wholeModule
40
+ };
41
+ }
42
+ function collectImportRefs(content) {
43
+ const refs = [];
44
+ for (const match of content.matchAll(/(?:import|export)\s+[\s\S]*?from\s*["']([^"']+)["']/g)) {
45
+ const { names, wholeModule } = splitNamedImports(match[0].slice(0, match[0].lastIndexOf("from")));
46
+ refs.push({
47
+ names: wholeModule ? null : names,
48
+ source: match[1]
49
+ });
50
+ }
51
+ for (const match of content.matchAll(/import\s*["']([^"']+)["']/g)) refs.push({
52
+ names: null,
53
+ source: match[1]
54
+ });
55
+ for (const match of content.matchAll(/import\(\s*["']([^"']+)["']\s*\)/g)) refs.push({
56
+ names: null,
57
+ source: match[1]
58
+ });
59
+ return refs;
60
+ }
61
+ function resolveSpecifier(specifier, fromFile, uiDir) {
62
+ let base = null;
63
+ if (specifier.startsWith("@/")) base = (0, node_path.join)(uiDir, specifier.slice(2));
64
+ else if (specifier.startsWith("./") || specifier.startsWith("../")) base = (0, node_path.resolve)((0, node_path.dirname)(fromFile), specifier);
65
+ else return null;
66
+ const candidates = [];
67
+ for (const ext of EXTENSIONS) candidates.push(`${base}${ext}`);
68
+ for (const ext of EXTENSIONS) candidates.push((0, node_path.join)(base, `index${ext}`));
69
+ for (const candidate of candidates) if ((0, node_fs.existsSync)(candidate) && (0, node_fs.statSync)(candidate).isFile()) return candidate;
70
+ return null;
71
+ }
72
+ function parseBarrelExports(content, barrelPath, srcDir) {
73
+ const exports = [];
74
+ for (const match of content.matchAll(/export\s+\{([^}]*)\}\s*from\s*["']([^"']+)["']/g)) for (const piece of match[1].split(",")) {
75
+ const name = piece.trim().replace(/^type\s+/, "").split(/\s+as\s+/)[0]?.trim();
76
+ if (!name || name === "default") continue;
77
+ exports.push({
78
+ name,
79
+ source: resolveSpecifier(match[2], barrelPath, srcDir)
80
+ });
81
+ }
82
+ return exports;
83
+ }
84
+ function listFilesRecursive(dir, out = []) {
85
+ if (!(0, node_fs.existsSync)(dir)) return out;
86
+ for (const entry of (0, node_fs.readdirSync)(dir)) {
87
+ const full = (0, node_path.join)(dir, entry);
88
+ if ((0, node_fs.statSync)(full).isDirectory()) listFilesRecursive(full, out);
89
+ else out.push(full);
90
+ }
91
+ return out;
92
+ }
93
+ function isProtected(relPath, srcDir) {
94
+ const withinSrc = (0, node_path.relative)(srcDir, relPath);
95
+ if (withinSrc.startsWith("..") || (0, node_path.isAbsolute)(withinSrc)) return true;
96
+ if (!withinSrc.includes("/")) return true;
97
+ if (withinSrc.startsWith("routes/")) return true;
98
+ if (/\.gen\.(ts|tsx|json)$/.test(withinSrc)) return true;
99
+ if (require_sync.isFrameworkOwnedSyncFile((0, node_path.join)("ui/src", withinSrc))) return true;
100
+ return false;
101
+ }
102
+ function subjectOfTestFile(file) {
103
+ const match = file.match(/^(?:(?<dir>.+)\/)?(?<name>.+)\.test\.tsx?$/);
104
+ if (!match?.groups) return null;
105
+ const base = match.groups.dir ? `${match.groups.dir}/${match.groups.name}` : match.groups.name;
106
+ for (const ext of [".tsx", ".ts"]) if ((0, node_fs.existsSync)(`${base}${ext}`)) return `${base}${ext}`;
107
+ return null;
108
+ }
109
+ /**
110
+ * Prune copied ui source files that no copied route or framework-owned file
111
+ * can reach via static imports. Named imports through the components barrel
112
+ * keep only the named exports' files alive; a namespace/default import of the
113
+ * barrel keeps everything it exports. Framework-owned files, generated types,
114
+ * and route files are never pruned; a test file lives or dies with the file
115
+ * it tests.
116
+ */
117
+ function pruneUnusedUiFiles(targetDir, options = {}) {
118
+ const srcDir = (0, node_path.join)(targetDir, "ui", "src");
119
+ if (!(0, node_fs.existsSync)(srcDir)) return {
120
+ pruned: [],
121
+ reachable: 0
122
+ };
123
+ const allFiles = listFilesRecursive(srcDir);
124
+ const barrelPath = (0, node_path.join)(srcDir, "components", "index.ts");
125
+ const barrelExports = (0, node_fs.existsSync)(barrelPath) ? parseBarrelExports((0, node_fs.readFileSync)(barrelPath, "utf-8"), barrelPath, srcDir) : [];
126
+ let barrelSaturated = false;
127
+ const reachable = /* @__PURE__ */ new Set();
128
+ const queue = [];
129
+ const saturateBarrel = () => {
130
+ for (const exp of barrelExports) if (exp.source) visit(exp.source, null);
131
+ };
132
+ function visit(file, wantedNames) {
133
+ if (file === barrelPath) {
134
+ if (wantedNames === null) barrelSaturated = true;
135
+ if (reachable.has(file)) {
136
+ if (wantedNames === null) saturateBarrel();
137
+ return;
138
+ }
139
+ reachable.add(file);
140
+ if (wantedNames === null) saturateBarrel();
141
+ else for (const exp of barrelExports) if (exp.source && wantedNames.includes(exp.name)) visit(exp.source, null);
142
+ return;
143
+ }
144
+ if (reachable.has(file)) return;
145
+ reachable.add(file);
146
+ queue.push(file);
147
+ }
148
+ for (const file of allFiles) if (isProtected(file, srcDir)) visit(file, null);
149
+ while (queue.length > 0) {
150
+ const file = queue.shift();
151
+ if (!(0, node_fs.existsSync)(file)) continue;
152
+ if (file === barrelPath) continue;
153
+ const content = (0, node_fs.readFileSync)(file, "utf-8");
154
+ for (const ref of collectImportRefs(content)) {
155
+ const resolved = resolveSpecifier(ref.source, file, srcDir);
156
+ if (!resolved) continue;
157
+ visit(resolved, ref.names);
158
+ }
159
+ }
160
+ if (barrelSaturated) saturateBarrel();
161
+ const removed = [];
162
+ for (const file of allFiles) {
163
+ if (reachable.has(file)) continue;
164
+ if (isProtected(file, srcDir)) continue;
165
+ const subject = subjectOfTestFile(file);
166
+ if (subject && (reachable.has(subject) || isProtected(subject, srcDir))) continue;
167
+ (0, node_fs.rmSync)(file);
168
+ removed.push((0, node_path.relative)(targetDir, file));
169
+ }
170
+ if ((0, node_fs.existsSync)(barrelPath) && removed.length > 0) {
171
+ const content = (0, node_fs.readFileSync)(barrelPath, "utf-8");
172
+ const spans = [];
173
+ for (const match of content.matchAll(/export\s*\{[^}]*\}\s*from\s*["'][^"']+["'];?/g)) {
174
+ const fromMatch = match[0].match(/from\s*["']([^"']+)["']/);
175
+ if (!fromMatch) continue;
176
+ const target = resolveSpecifier(fromMatch[1], barrelPath, srcDir);
177
+ if (!target || !(0, node_fs.existsSync)(target)) spans.push([match.index, match.index + match[0].length]);
178
+ }
179
+ if (spans.length > 0) {
180
+ let next = "";
181
+ let cursor = 0;
182
+ for (const [start, end] of spans) {
183
+ next += content.slice(cursor, start);
184
+ cursor = end;
185
+ }
186
+ next += content.slice(cursor);
187
+ next = next.replace(/\n{3,}/g, "\n\n");
188
+ (0, node_fs.writeFileSync)(barrelPath, next);
189
+ }
190
+ }
191
+ for (const candidate of [
192
+ "components",
193
+ "lib",
194
+ "hooks",
195
+ "providers",
196
+ "integrations"
197
+ ]) removeIfEmpty((0, node_path.join)(srcDir, candidate));
198
+ if (removed.length > 0) options.log?.(`pruned ${removed.length} unreferenced ui file(s)`);
199
+ return {
200
+ pruned: removed,
201
+ reachable: reachable.size
202
+ };
203
+ }
204
+ function removeIfEmpty(dir) {
205
+ if (!(0, node_fs.existsSync)(dir)) return;
206
+ const entries = (0, node_fs.readdirSync)(dir);
207
+ if (entries.length === 0) {
208
+ (0, node_fs.rmSync)(dir, { recursive: true });
209
+ return;
210
+ }
211
+ for (const entry of entries) {
212
+ const full = (0, node_path.join)(dir, entry);
213
+ if ((0, node_fs.statSync)(full).isDirectory()) removeIfEmpty(full);
214
+ }
215
+ if ((0, node_fs.readdirSync)(dir).length === 0) (0, node_fs.rmSync)(dir, { recursive: true });
216
+ }
217
+
218
+ //#endregion
219
+ exports.pruneUnusedUiFiles = pruneUnusedUiFiles;
220
+ //# sourceMappingURL=prune.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"prune.cjs","names":["join","resolve","dirname","existsSync","statSync","readdirSync","relative","isAbsolute","isFrameworkOwnedSyncFile","readFileSync"],"sources":["../../src/cli/prune.ts"],"sourcesContent":["import { existsSync, readdirSync, readFileSync, rmSync, statSync, writeFileSync } from \"node:fs\";\nimport { dirname, isAbsolute, join, relative, resolve } from \"node:path\";\nimport { isFrameworkOwnedSyncFile } from \"./sync\";\n\nconst EXTENSIONS = [\n \"\",\n \".ts\",\n \".tsx\",\n \".css\",\n \".json\",\n \".png\",\n \".gif\",\n \".svg\",\n \".jpg\",\n \".webp\",\n \".ico\",\n \".mjs\",\n];\n\nexport interface PruneResult {\n pruned: string[];\n reachable: number;\n}\n\ninterface ImportRef {\n names: string[] | null;\n source: string;\n}\n\nfunction splitNamedImports(clause: string): { names: string[]; wholeModule: boolean } {\n let wholeModule = false;\n const names: string[] = [];\n const withoutNamed = clause.replace(/\\{[^}]*\\}/g, \" \").replace(/^\\s*(?:import|export)\\b/, \"\");\n for (const piece of withoutNamed.split(\",\")) {\n const token = piece.trim();\n if (!token) continue;\n if (token.includes(\"*\")) {\n wholeModule = true;\n continue;\n }\n if (/^[A-Za-z_$][\\w$]*$/.test(token)) wholeModule = true;\n }\n const namedRe = /\\{([^}]*)\\}/g;\n for (const named of clause.matchAll(namedRe)) {\n for (const piece of named[1].split(\",\")) {\n const name = piece\n .trim()\n .replace(/^type\\s+/, \"\")\n .split(/\\s+as\\s+/)[0]\n ?.trim();\n if (name && name !== \"default\") names.push(name);\n }\n }\n return { names, wholeModule };\n}\n\nfunction collectImportRefs(content: string): ImportRef[] {\n const refs: ImportRef[] = [];\n const fromRe = /(?:import|export)\\s+[\\s\\S]*?from\\s*[\"']([^\"']+)[\"']/g;\n for (const match of content.matchAll(fromRe)) {\n const clause = match[0].slice(0, match[0].lastIndexOf(\"from\"));\n const { names, wholeModule } = splitNamedImports(clause);\n refs.push({ names: wholeModule ? null : names, source: match[1] });\n }\n for (const match of content.matchAll(/import\\s*[\"']([^\"']+)[\"']/g)) {\n refs.push({ names: null, source: match[1] });\n }\n // Dynamic imports keep the target alive (conservative)\n for (const match of content.matchAll(/import\\(\\s*[\"']([^\"']+)[\"']\\s*\\)/g)) {\n refs.push({ names: null, source: match[1] });\n }\n return refs;\n}\n\nfunction resolveSpecifier(specifier: string, fromFile: string, uiDir: string): string | null {\n let base: string | null = null;\n if (specifier.startsWith(\"@/\")) {\n base = join(uiDir, specifier.slice(2));\n } else if (specifier.startsWith(\"./\") || specifier.startsWith(\"../\")) {\n base = resolve(dirname(fromFile), specifier);\n } else {\n return null;\n }\n const candidates: string[] = [];\n for (const ext of EXTENSIONS) {\n candidates.push(`${base}${ext}`);\n }\n for (const ext of EXTENSIONS) {\n candidates.push(join(base, `index${ext}`));\n }\n for (const candidate of candidates) {\n if (existsSync(candidate) && statSync(candidate).isFile()) return candidate;\n }\n return null;\n}\n\ninterface BarrelExport {\n name: string;\n source: string | null;\n}\n\nfunction parseBarrelExports(content: string, barrelPath: string, srcDir: string): BarrelExport[] {\n const exports: BarrelExport[] = [];\n const re = /export\\s+\\{([^}]*)\\}\\s*from\\s*[\"']([^\"']+)[\"']/g;\n for (const match of content.matchAll(re)) {\n for (const piece of match[1].split(\",\")) {\n const name = piece\n .trim()\n .replace(/^type\\s+/, \"\")\n .split(/\\s+as\\s+/)[0]\n ?.trim();\n if (!name || name === \"default\") continue;\n exports.push({ name, source: resolveSpecifier(match[2], barrelPath, srcDir) });\n }\n }\n return exports;\n}\n\nfunction listFilesRecursive(dir: string, out: string[] = []): string[] {\n if (!existsSync(dir)) return out;\n for (const entry of readdirSync(dir)) {\n const full = join(dir, entry);\n const stat = statSync(full);\n if (stat.isDirectory()) {\n listFilesRecursive(full, out);\n } else {\n out.push(full);\n }\n }\n return out;\n}\n\nfunction isProtected(relPath: string, srcDir: string): boolean {\n const withinSrc = relative(srcDir, relPath);\n if (withinSrc.startsWith(\"..\") || isAbsolute(withinSrc)) return true;\n // Root-level src files (entry, app, compose, styles, globals) are the\n // framework's entry surface — never pruned.\n if (!withinSrc.includes(\"/\")) return true;\n if (withinSrc.startsWith(\"routes/\")) return true;\n if (/\\.gen\\.(ts|tsx|json)$/.test(withinSrc)) return true;\n if (isFrameworkOwnedSyncFile(join(\"ui/src\", withinSrc))) return true;\n return false;\n}\n\nfunction subjectOfTestFile(file: string): string | null {\n const match = file.match(/^(?:(?<dir>.+)\\/)?(?<name>.+)\\.test\\.tsx?$/);\n if (!match?.groups) return null;\n const base = match.groups.dir ? `${match.groups.dir}/${match.groups.name}` : match.groups.name;\n for (const ext of [\".tsx\", \".ts\"]) {\n if (existsSync(`${base}${ext}`)) return `${base}${ext}`;\n }\n return null;\n}\n\n/**\n * Prune copied ui source files that no copied route or framework-owned file\n * can reach via static imports. Named imports through the components barrel\n * keep only the named exports' files alive; a namespace/default import of the\n * barrel keeps everything it exports. Framework-owned files, generated types,\n * and route files are never pruned; a test file lives or dies with the file\n * it tests.\n */\nexport function pruneUnusedUiFiles(\n targetDir: string,\n options: { log?: (message: string) => void } = {},\n): PruneResult {\n const srcDir = join(targetDir, \"ui\", \"src\");\n if (!existsSync(srcDir)) return { pruned: [], reachable: 0 };\n\n const allFiles = listFilesRecursive(srcDir);\n\n const barrelPath = join(srcDir, \"components\", \"index.ts\");\n const barrelExports = existsSync(barrelPath)\n ? parseBarrelExports(readFileSync(barrelPath, \"utf-8\"), barrelPath, srcDir)\n : [];\n let barrelSaturated = false;\n\n const reachable = new Set<string>();\n const queue: string[] = [];\n\n const saturateBarrel = (): void => {\n for (const exp of barrelExports) {\n if (exp.source) visit(exp.source, null);\n }\n };\n\n function visit(file: string, wantedNames: string[] | null): void {\n if (file === barrelPath) {\n if (wantedNames === null) {\n barrelSaturated = true;\n }\n if (reachable.has(file)) {\n if (wantedNames === null) saturateBarrel();\n return;\n }\n reachable.add(file);\n if (wantedNames === null) {\n saturateBarrel();\n } else {\n for (const exp of barrelExports) {\n if (exp.source && wantedNames.includes(exp.name)) visit(exp.source, null);\n }\n }\n return;\n }\n if (reachable.has(file)) return;\n reachable.add(file);\n queue.push(file);\n }\n\n for (const file of allFiles) {\n if (isProtected(file, srcDir)) visit(file, null);\n }\n\n while (queue.length > 0) {\n const file = queue.shift()!;\n if (!existsSync(file)) continue;\n // The barrel's own export statements are traversed only through the\n // wanted-names path in visit() — never as whole-file imports.\n if (file === barrelPath) continue;\n const content = readFileSync(file, \"utf-8\");\n for (const ref of collectImportRefs(content)) {\n const resolved = resolveSpecifier(ref.source, file, srcDir);\n if (!resolved) continue;\n visit(resolved, ref.names);\n }\n }\n if (barrelSaturated) saturateBarrel();\n\n const removed: string[] = [];\n for (const file of allFiles) {\n if (reachable.has(file)) continue;\n if (isProtected(file, srcDir)) continue;\n const subject = subjectOfTestFile(file);\n if (subject && (reachable.has(subject) || isProtected(subject, srcDir))) continue;\n rmSync(file);\n removed.push(relative(targetDir, file));\n }\n\n // Drop barrel export statements pointing at pruned files (statement spans,\n // so multi-line `export { ... } from \"...\"` blocks are removed whole).\n if (existsSync(barrelPath) && removed.length > 0) {\n const content = readFileSync(barrelPath, \"utf-8\");\n const spans: Array<[number, number]> = [];\n for (const match of content.matchAll(/export\\s*\\{[^}]*\\}\\s*from\\s*[\"'][^\"']+[\"'];?/g)) {\n const fromMatch = match[0].match(/from\\s*[\"']([^\"']+)[\"']/);\n if (!fromMatch) continue;\n const target = resolveSpecifier(fromMatch[1], barrelPath, srcDir);\n if (!target || !existsSync(target)) {\n spans.push([match.index, match.index + match[0].length]);\n }\n }\n if (spans.length > 0) {\n let next = \"\";\n let cursor = 0;\n for (const [start, end] of spans) {\n next += content.slice(cursor, start);\n cursor = end;\n }\n next += content.slice(cursor);\n // Collapse blank-line runs left behind by removed statements\n next = next.replace(/\\n{3,}/g, \"\\n\\n\");\n writeFileSync(barrelPath, next);\n }\n }\n\n // Remove directories left empty by the prune (git ignores empty dirs, but\n // the scaffold on disk should not carry hollow folders).\n for (const candidate of [\"components\", \"lib\", \"hooks\", \"providers\", \"integrations\"]) {\n const dir = join(srcDir, candidate);\n removeIfEmpty(dir);\n }\n\n if (removed.length > 0) {\n options.log?.(`pruned ${removed.length} unreferenced ui file(s)`);\n }\n return { pruned: removed, reachable: reachable.size };\n}\n\nfunction removeIfEmpty(dir: string): void {\n if (!existsSync(dir)) return;\n const entries = readdirSync(dir);\n if (entries.length === 0) {\n rmSync(dir, { recursive: true });\n return;\n }\n for (const entry of entries) {\n const full = join(dir, entry);\n if (statSync(full).isDirectory()) removeIfEmpty(full);\n }\n if (readdirSync(dir).length === 0) rmSync(dir, { recursive: true });\n}\n"],"mappings":"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"}
@@ -0,0 +1,220 @@
1
+ import { isFrameworkOwnedSyncFile } from "./sync.mjs";
2
+ import { existsSync, readFileSync, readdirSync, rmSync, statSync, writeFileSync } from "node:fs";
3
+ import { dirname, isAbsolute, join, relative, resolve } from "node:path";
4
+
5
+ //#region src/cli/prune.ts
6
+ const EXTENSIONS = [
7
+ "",
8
+ ".ts",
9
+ ".tsx",
10
+ ".css",
11
+ ".json",
12
+ ".png",
13
+ ".gif",
14
+ ".svg",
15
+ ".jpg",
16
+ ".webp",
17
+ ".ico",
18
+ ".mjs"
19
+ ];
20
+ function splitNamedImports(clause) {
21
+ let wholeModule = false;
22
+ const names = [];
23
+ const withoutNamed = clause.replace(/\{[^}]*\}/g, " ").replace(/^\s*(?:import|export)\b/, "");
24
+ for (const piece of withoutNamed.split(",")) {
25
+ const token = piece.trim();
26
+ if (!token) continue;
27
+ if (token.includes("*")) {
28
+ wholeModule = true;
29
+ continue;
30
+ }
31
+ if (/^[A-Za-z_$][\w$]*$/.test(token)) wholeModule = true;
32
+ }
33
+ for (const named of clause.matchAll(/\{([^}]*)\}/g)) for (const piece of named[1].split(",")) {
34
+ const name = piece.trim().replace(/^type\s+/, "").split(/\s+as\s+/)[0]?.trim();
35
+ if (name && name !== "default") names.push(name);
36
+ }
37
+ return {
38
+ names,
39
+ wholeModule
40
+ };
41
+ }
42
+ function collectImportRefs(content) {
43
+ const refs = [];
44
+ for (const match of content.matchAll(/(?:import|export)\s+[\s\S]*?from\s*["']([^"']+)["']/g)) {
45
+ const { names, wholeModule } = splitNamedImports(match[0].slice(0, match[0].lastIndexOf("from")));
46
+ refs.push({
47
+ names: wholeModule ? null : names,
48
+ source: match[1]
49
+ });
50
+ }
51
+ for (const match of content.matchAll(/import\s*["']([^"']+)["']/g)) refs.push({
52
+ names: null,
53
+ source: match[1]
54
+ });
55
+ for (const match of content.matchAll(/import\(\s*["']([^"']+)["']\s*\)/g)) refs.push({
56
+ names: null,
57
+ source: match[1]
58
+ });
59
+ return refs;
60
+ }
61
+ function resolveSpecifier(specifier, fromFile, uiDir) {
62
+ let base = null;
63
+ if (specifier.startsWith("@/")) base = join(uiDir, specifier.slice(2));
64
+ else if (specifier.startsWith("./") || specifier.startsWith("../")) base = resolve(dirname(fromFile), specifier);
65
+ else return null;
66
+ const candidates = [];
67
+ for (const ext of EXTENSIONS) candidates.push(`${base}${ext}`);
68
+ for (const ext of EXTENSIONS) candidates.push(join(base, `index${ext}`));
69
+ for (const candidate of candidates) if (existsSync(candidate) && statSync(candidate).isFile()) return candidate;
70
+ return null;
71
+ }
72
+ function parseBarrelExports(content, barrelPath, srcDir) {
73
+ const exports = [];
74
+ for (const match of content.matchAll(/export\s+\{([^}]*)\}\s*from\s*["']([^"']+)["']/g)) for (const piece of match[1].split(",")) {
75
+ const name = piece.trim().replace(/^type\s+/, "").split(/\s+as\s+/)[0]?.trim();
76
+ if (!name || name === "default") continue;
77
+ exports.push({
78
+ name,
79
+ source: resolveSpecifier(match[2], barrelPath, srcDir)
80
+ });
81
+ }
82
+ return exports;
83
+ }
84
+ function listFilesRecursive(dir, out = []) {
85
+ if (!existsSync(dir)) return out;
86
+ for (const entry of readdirSync(dir)) {
87
+ const full = join(dir, entry);
88
+ if (statSync(full).isDirectory()) listFilesRecursive(full, out);
89
+ else out.push(full);
90
+ }
91
+ return out;
92
+ }
93
+ function isProtected(relPath, srcDir) {
94
+ const withinSrc = relative(srcDir, relPath);
95
+ if (withinSrc.startsWith("..") || isAbsolute(withinSrc)) return true;
96
+ if (!withinSrc.includes("/")) return true;
97
+ if (withinSrc.startsWith("routes/")) return true;
98
+ if (/\.gen\.(ts|tsx|json)$/.test(withinSrc)) return true;
99
+ if (isFrameworkOwnedSyncFile(join("ui/src", withinSrc))) return true;
100
+ return false;
101
+ }
102
+ function subjectOfTestFile(file) {
103
+ const match = file.match(/^(?:(?<dir>.+)\/)?(?<name>.+)\.test\.tsx?$/);
104
+ if (!match?.groups) return null;
105
+ const base = match.groups.dir ? `${match.groups.dir}/${match.groups.name}` : match.groups.name;
106
+ for (const ext of [".tsx", ".ts"]) if (existsSync(`${base}${ext}`)) return `${base}${ext}`;
107
+ return null;
108
+ }
109
+ /**
110
+ * Prune copied ui source files that no copied route or framework-owned file
111
+ * can reach via static imports. Named imports through the components barrel
112
+ * keep only the named exports' files alive; a namespace/default import of the
113
+ * barrel keeps everything it exports. Framework-owned files, generated types,
114
+ * and route files are never pruned; a test file lives or dies with the file
115
+ * it tests.
116
+ */
117
+ function pruneUnusedUiFiles(targetDir, options = {}) {
118
+ const srcDir = join(targetDir, "ui", "src");
119
+ if (!existsSync(srcDir)) return {
120
+ pruned: [],
121
+ reachable: 0
122
+ };
123
+ const allFiles = listFilesRecursive(srcDir);
124
+ const barrelPath = join(srcDir, "components", "index.ts");
125
+ const barrelExports = existsSync(barrelPath) ? parseBarrelExports(readFileSync(barrelPath, "utf-8"), barrelPath, srcDir) : [];
126
+ let barrelSaturated = false;
127
+ const reachable = /* @__PURE__ */ new Set();
128
+ const queue = [];
129
+ const saturateBarrel = () => {
130
+ for (const exp of barrelExports) if (exp.source) visit(exp.source, null);
131
+ };
132
+ function visit(file, wantedNames) {
133
+ if (file === barrelPath) {
134
+ if (wantedNames === null) barrelSaturated = true;
135
+ if (reachable.has(file)) {
136
+ if (wantedNames === null) saturateBarrel();
137
+ return;
138
+ }
139
+ reachable.add(file);
140
+ if (wantedNames === null) saturateBarrel();
141
+ else for (const exp of barrelExports) if (exp.source && wantedNames.includes(exp.name)) visit(exp.source, null);
142
+ return;
143
+ }
144
+ if (reachable.has(file)) return;
145
+ reachable.add(file);
146
+ queue.push(file);
147
+ }
148
+ for (const file of allFiles) if (isProtected(file, srcDir)) visit(file, null);
149
+ while (queue.length > 0) {
150
+ const file = queue.shift();
151
+ if (!existsSync(file)) continue;
152
+ if (file === barrelPath) continue;
153
+ const content = readFileSync(file, "utf-8");
154
+ for (const ref of collectImportRefs(content)) {
155
+ const resolved = resolveSpecifier(ref.source, file, srcDir);
156
+ if (!resolved) continue;
157
+ visit(resolved, ref.names);
158
+ }
159
+ }
160
+ if (barrelSaturated) saturateBarrel();
161
+ const removed = [];
162
+ for (const file of allFiles) {
163
+ if (reachable.has(file)) continue;
164
+ if (isProtected(file, srcDir)) continue;
165
+ const subject = subjectOfTestFile(file);
166
+ if (subject && (reachable.has(subject) || isProtected(subject, srcDir))) continue;
167
+ rmSync(file);
168
+ removed.push(relative(targetDir, file));
169
+ }
170
+ if (existsSync(barrelPath) && removed.length > 0) {
171
+ const content = readFileSync(barrelPath, "utf-8");
172
+ const spans = [];
173
+ for (const match of content.matchAll(/export\s*\{[^}]*\}\s*from\s*["'][^"']+["'];?/g)) {
174
+ const fromMatch = match[0].match(/from\s*["']([^"']+)["']/);
175
+ if (!fromMatch) continue;
176
+ const target = resolveSpecifier(fromMatch[1], barrelPath, srcDir);
177
+ if (!target || !existsSync(target)) spans.push([match.index, match.index + match[0].length]);
178
+ }
179
+ if (spans.length > 0) {
180
+ let next = "";
181
+ let cursor = 0;
182
+ for (const [start, end] of spans) {
183
+ next += content.slice(cursor, start);
184
+ cursor = end;
185
+ }
186
+ next += content.slice(cursor);
187
+ next = next.replace(/\n{3,}/g, "\n\n");
188
+ writeFileSync(barrelPath, next);
189
+ }
190
+ }
191
+ for (const candidate of [
192
+ "components",
193
+ "lib",
194
+ "hooks",
195
+ "providers",
196
+ "integrations"
197
+ ]) removeIfEmpty(join(srcDir, candidate));
198
+ if (removed.length > 0) options.log?.(`pruned ${removed.length} unreferenced ui file(s)`);
199
+ return {
200
+ pruned: removed,
201
+ reachable: reachable.size
202
+ };
203
+ }
204
+ function removeIfEmpty(dir) {
205
+ if (!existsSync(dir)) return;
206
+ const entries = readdirSync(dir);
207
+ if (entries.length === 0) {
208
+ rmSync(dir, { recursive: true });
209
+ return;
210
+ }
211
+ for (const entry of entries) {
212
+ const full = join(dir, entry);
213
+ if (statSync(full).isDirectory()) removeIfEmpty(full);
214
+ }
215
+ if (readdirSync(dir).length === 0) rmSync(dir, { recursive: true });
216
+ }
217
+
218
+ //#endregion
219
+ export { pruneUnusedUiFiles };
220
+ //# sourceMappingURL=prune.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"prune.mjs","names":[],"sources":["../../src/cli/prune.ts"],"sourcesContent":["import { existsSync, readdirSync, readFileSync, rmSync, statSync, writeFileSync } from \"node:fs\";\nimport { dirname, isAbsolute, join, relative, resolve } from \"node:path\";\nimport { isFrameworkOwnedSyncFile } from \"./sync\";\n\nconst EXTENSIONS = [\n \"\",\n \".ts\",\n \".tsx\",\n \".css\",\n \".json\",\n \".png\",\n \".gif\",\n \".svg\",\n \".jpg\",\n \".webp\",\n \".ico\",\n \".mjs\",\n];\n\nexport interface PruneResult {\n pruned: string[];\n reachable: number;\n}\n\ninterface ImportRef {\n names: string[] | null;\n source: string;\n}\n\nfunction splitNamedImports(clause: string): { names: string[]; wholeModule: boolean } {\n let wholeModule = false;\n const names: string[] = [];\n const withoutNamed = clause.replace(/\\{[^}]*\\}/g, \" \").replace(/^\\s*(?:import|export)\\b/, \"\");\n for (const piece of withoutNamed.split(\",\")) {\n const token = piece.trim();\n if (!token) continue;\n if (token.includes(\"*\")) {\n wholeModule = true;\n continue;\n }\n if (/^[A-Za-z_$][\\w$]*$/.test(token)) wholeModule = true;\n }\n const namedRe = /\\{([^}]*)\\}/g;\n for (const named of clause.matchAll(namedRe)) {\n for (const piece of named[1].split(\",\")) {\n const name = piece\n .trim()\n .replace(/^type\\s+/, \"\")\n .split(/\\s+as\\s+/)[0]\n ?.trim();\n if (name && name !== \"default\") names.push(name);\n }\n }\n return { names, wholeModule };\n}\n\nfunction collectImportRefs(content: string): ImportRef[] {\n const refs: ImportRef[] = [];\n const fromRe = /(?:import|export)\\s+[\\s\\S]*?from\\s*[\"']([^\"']+)[\"']/g;\n for (const match of content.matchAll(fromRe)) {\n const clause = match[0].slice(0, match[0].lastIndexOf(\"from\"));\n const { names, wholeModule } = splitNamedImports(clause);\n refs.push({ names: wholeModule ? null : names, source: match[1] });\n }\n for (const match of content.matchAll(/import\\s*[\"']([^\"']+)[\"']/g)) {\n refs.push({ names: null, source: match[1] });\n }\n // Dynamic imports keep the target alive (conservative)\n for (const match of content.matchAll(/import\\(\\s*[\"']([^\"']+)[\"']\\s*\\)/g)) {\n refs.push({ names: null, source: match[1] });\n }\n return refs;\n}\n\nfunction resolveSpecifier(specifier: string, fromFile: string, uiDir: string): string | null {\n let base: string | null = null;\n if (specifier.startsWith(\"@/\")) {\n base = join(uiDir, specifier.slice(2));\n } else if (specifier.startsWith(\"./\") || specifier.startsWith(\"../\")) {\n base = resolve(dirname(fromFile), specifier);\n } else {\n return null;\n }\n const candidates: string[] = [];\n for (const ext of EXTENSIONS) {\n candidates.push(`${base}${ext}`);\n }\n for (const ext of EXTENSIONS) {\n candidates.push(join(base, `index${ext}`));\n }\n for (const candidate of candidates) {\n if (existsSync(candidate) && statSync(candidate).isFile()) return candidate;\n }\n return null;\n}\n\ninterface BarrelExport {\n name: string;\n source: string | null;\n}\n\nfunction parseBarrelExports(content: string, barrelPath: string, srcDir: string): BarrelExport[] {\n const exports: BarrelExport[] = [];\n const re = /export\\s+\\{([^}]*)\\}\\s*from\\s*[\"']([^\"']+)[\"']/g;\n for (const match of content.matchAll(re)) {\n for (const piece of match[1].split(\",\")) {\n const name = piece\n .trim()\n .replace(/^type\\s+/, \"\")\n .split(/\\s+as\\s+/)[0]\n ?.trim();\n if (!name || name === \"default\") continue;\n exports.push({ name, source: resolveSpecifier(match[2], barrelPath, srcDir) });\n }\n }\n return exports;\n}\n\nfunction listFilesRecursive(dir: string, out: string[] = []): string[] {\n if (!existsSync(dir)) return out;\n for (const entry of readdirSync(dir)) {\n const full = join(dir, entry);\n const stat = statSync(full);\n if (stat.isDirectory()) {\n listFilesRecursive(full, out);\n } else {\n out.push(full);\n }\n }\n return out;\n}\n\nfunction isProtected(relPath: string, srcDir: string): boolean {\n const withinSrc = relative(srcDir, relPath);\n if (withinSrc.startsWith(\"..\") || isAbsolute(withinSrc)) return true;\n // Root-level src files (entry, app, compose, styles, globals) are the\n // framework's entry surface — never pruned.\n if (!withinSrc.includes(\"/\")) return true;\n if (withinSrc.startsWith(\"routes/\")) return true;\n if (/\\.gen\\.(ts|tsx|json)$/.test(withinSrc)) return true;\n if (isFrameworkOwnedSyncFile(join(\"ui/src\", withinSrc))) return true;\n return false;\n}\n\nfunction subjectOfTestFile(file: string): string | null {\n const match = file.match(/^(?:(?<dir>.+)\\/)?(?<name>.+)\\.test\\.tsx?$/);\n if (!match?.groups) return null;\n const base = match.groups.dir ? `${match.groups.dir}/${match.groups.name}` : match.groups.name;\n for (const ext of [\".tsx\", \".ts\"]) {\n if (existsSync(`${base}${ext}`)) return `${base}${ext}`;\n }\n return null;\n}\n\n/**\n * Prune copied ui source files that no copied route or framework-owned file\n * can reach via static imports. Named imports through the components barrel\n * keep only the named exports' files alive; a namespace/default import of the\n * barrel keeps everything it exports. Framework-owned files, generated types,\n * and route files are never pruned; a test file lives or dies with the file\n * it tests.\n */\nexport function pruneUnusedUiFiles(\n targetDir: string,\n options: { log?: (message: string) => void } = {},\n): PruneResult {\n const srcDir = join(targetDir, \"ui\", \"src\");\n if (!existsSync(srcDir)) return { pruned: [], reachable: 0 };\n\n const allFiles = listFilesRecursive(srcDir);\n\n const barrelPath = join(srcDir, \"components\", \"index.ts\");\n const barrelExports = existsSync(barrelPath)\n ? parseBarrelExports(readFileSync(barrelPath, \"utf-8\"), barrelPath, srcDir)\n : [];\n let barrelSaturated = false;\n\n const reachable = new Set<string>();\n const queue: string[] = [];\n\n const saturateBarrel = (): void => {\n for (const exp of barrelExports) {\n if (exp.source) visit(exp.source, null);\n }\n };\n\n function visit(file: string, wantedNames: string[] | null): void {\n if (file === barrelPath) {\n if (wantedNames === null) {\n barrelSaturated = true;\n }\n if (reachable.has(file)) {\n if (wantedNames === null) saturateBarrel();\n return;\n }\n reachable.add(file);\n if (wantedNames === null) {\n saturateBarrel();\n } else {\n for (const exp of barrelExports) {\n if (exp.source && wantedNames.includes(exp.name)) visit(exp.source, null);\n }\n }\n return;\n }\n if (reachable.has(file)) return;\n reachable.add(file);\n queue.push(file);\n }\n\n for (const file of allFiles) {\n if (isProtected(file, srcDir)) visit(file, null);\n }\n\n while (queue.length > 0) {\n const file = queue.shift()!;\n if (!existsSync(file)) continue;\n // The barrel's own export statements are traversed only through the\n // wanted-names path in visit() — never as whole-file imports.\n if (file === barrelPath) continue;\n const content = readFileSync(file, \"utf-8\");\n for (const ref of collectImportRefs(content)) {\n const resolved = resolveSpecifier(ref.source, file, srcDir);\n if (!resolved) continue;\n visit(resolved, ref.names);\n }\n }\n if (barrelSaturated) saturateBarrel();\n\n const removed: string[] = [];\n for (const file of allFiles) {\n if (reachable.has(file)) continue;\n if (isProtected(file, srcDir)) continue;\n const subject = subjectOfTestFile(file);\n if (subject && (reachable.has(subject) || isProtected(subject, srcDir))) continue;\n rmSync(file);\n removed.push(relative(targetDir, file));\n }\n\n // Drop barrel export statements pointing at pruned files (statement spans,\n // so multi-line `export { ... } from \"...\"` blocks are removed whole).\n if (existsSync(barrelPath) && removed.length > 0) {\n const content = readFileSync(barrelPath, \"utf-8\");\n const spans: Array<[number, number]> = [];\n for (const match of content.matchAll(/export\\s*\\{[^}]*\\}\\s*from\\s*[\"'][^\"']+[\"'];?/g)) {\n const fromMatch = match[0].match(/from\\s*[\"']([^\"']+)[\"']/);\n if (!fromMatch) continue;\n const target = resolveSpecifier(fromMatch[1], barrelPath, srcDir);\n if (!target || !existsSync(target)) {\n spans.push([match.index, match.index + match[0].length]);\n }\n }\n if (spans.length > 0) {\n let next = \"\";\n let cursor = 0;\n for (const [start, end] of spans) {\n next += content.slice(cursor, start);\n cursor = end;\n }\n next += content.slice(cursor);\n // Collapse blank-line runs left behind by removed statements\n next = next.replace(/\\n{3,}/g, \"\\n\\n\");\n writeFileSync(barrelPath, next);\n }\n }\n\n // Remove directories left empty by the prune (git ignores empty dirs, but\n // the scaffold on disk should not carry hollow folders).\n for (const candidate of [\"components\", \"lib\", \"hooks\", \"providers\", \"integrations\"]) {\n const dir = join(srcDir, candidate);\n removeIfEmpty(dir);\n }\n\n if (removed.length > 0) {\n options.log?.(`pruned ${removed.length} unreferenced ui file(s)`);\n }\n return { pruned: removed, reachable: reachable.size };\n}\n\nfunction removeIfEmpty(dir: string): void {\n if (!existsSync(dir)) return;\n const entries = readdirSync(dir);\n if (entries.length === 0) {\n rmSync(dir, { recursive: true });\n return;\n }\n for (const entry of entries) {\n const full = join(dir, entry);\n if (statSync(full).isDirectory()) removeIfEmpty(full);\n }\n if (readdirSync(dir).length === 0) rmSync(dir, { recursive: true });\n}\n"],"mappings":"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"}
@@ -23,7 +23,8 @@ async function writeSnapshot(projectDir, data) {
23
23
  const snapshot = {
24
24
  parentRef: data.parentRef,
25
25
  timestamp: (/* @__PURE__ */ new Date()).toISOString(),
26
- files: data.files
26
+ files: data.files,
27
+ ...data.starter ? { starter: data.starter } : {}
27
28
  };
28
29
  (0, node_fs.writeFileSync)(snapshotPath(projectDir), `${JSON.stringify(snapshot, null, 2)}\n`);
29
30
  }