fedipod-server 0.29.0 → 0.30.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 (440) hide show
  1. package/README.md +11 -6
  2. package/dist/door.d.ts +4 -0
  3. package/dist/door.js +31 -0
  4. package/dist/fedipod.d.ts +16 -0
  5. package/dist/fedipod.js +13 -0
  6. package/dist/front.d.ts +3 -0
  7. package/dist/front.js +94 -0
  8. package/dist/handler.d.ts +36 -101
  9. package/dist/handler.js +85 -645
  10. package/dist/handler.jsonld +2 -30
  11. package/dist/identities.d.ts +62 -0
  12. package/dist/identities.js +236 -0
  13. package/dist/mounts.d.ts +43 -0
  14. package/dist/mounts.js +123 -0
  15. package/dist/opt-in.d.ts +46 -0
  16. package/dist/opt-in.js +176 -0
  17. package/package.json +10 -18
  18. package/lib/client/c2s.mjs +0 -636
  19. package/lib/client/localapi.mjs +0 -87
  20. package/lib/client/masto/accounts.mjs +0 -310
  21. package/lib/client/masto/body.mjs +0 -156
  22. package/lib/client/masto/index.mjs +0 -206
  23. package/lib/client/masto/instance.mjs +0 -112
  24. package/lib/client/masto/media.mjs +0 -79
  25. package/lib/client/masto/oauth.mjs +0 -656
  26. package/lib/client/masto/render.mjs +0 -518
  27. package/lib/client/masto/statuses.mjs +0 -372
  28. package/lib/client/masto/timelines.mjs +0 -438
  29. package/lib/client/oidc-auth.mjs +0 -62
  30. package/lib/client/streaming.mjs +0 -154
  31. package/lib/client/webpush.mjs +0 -98
  32. package/lib/connections/acctfeed.mjs +0 -257
  33. package/lib/connections/atproto.mjs +0 -309
  34. package/lib/connections/bskyfeed.mjs +0 -243
  35. package/lib/connections/bskygroup.mjs +0 -162
  36. package/lib/connections/fediacct.mjs +0 -253
  37. package/lib/connections/import.mjs +0 -357
  38. package/lib/connections/tagfeed.mjs +0 -212
  39. package/lib/connections/vault.mjs +0 -114
  40. package/lib/core/as2.mjs +0 -206
  41. package/lib/core/contexts/activitystreams.json +0 -379
  42. package/lib/core/contexts/anno.json +0 -126
  43. package/lib/core/contexts/did-v1.json +0 -57
  44. package/lib/core/contexts/fep-5711.json +0 -36
  45. package/lib/core/contexts/gotosocial.json +0 -86
  46. package/lib/core/contexts/identity-v1.json +0 -152
  47. package/lib/core/contexts/index.mjs +0 -63
  48. package/lib/core/contexts/join-lemmy.json +0 -33
  49. package/lib/core/contexts/joinmastodon.json +0 -28
  50. package/lib/core/contexts/litepub-0.1.json +0 -60
  51. package/lib/core/contexts/map.json +0 -19
  52. package/lib/core/contexts/miscellany.json +0 -19
  53. package/lib/core/contexts/quotes.json +0 -18
  54. package/lib/core/contexts/schemaorg.json +0 -8845
  55. package/lib/core/contexts/security-data-integrity-v1.json +0 -78
  56. package/lib/core/contexts/security-data-integrity-v2.json +0 -81
  57. package/lib/core/contexts/security-multikey-v1.json +0 -35
  58. package/lib/core/contexts/security-v1.json +0 -74
  59. package/lib/core/contexts/webfinger.json +0 -10
  60. package/lib/core/deliver.mjs +0 -387
  61. package/lib/core/graphview.mjs +0 -327
  62. package/lib/core/intake/activities.mjs +0 -649
  63. package/lib/core/intake/activity.mjs +0 -318
  64. package/lib/core/intake/channel.mjs +0 -144
  65. package/lib/core/intake/group.mjs +0 -258
  66. package/lib/core/intake/index.mjs +0 -732
  67. package/lib/core/intake/notes.mjs +0 -367
  68. package/lib/core/intake/verify.mjs +0 -142
  69. package/lib/core/keys.mjs +0 -153
  70. package/lib/core/lease.mjs +0 -206
  71. package/lib/core/place.mjs +0 -82
  72. package/lib/core/polls.mjs +0 -105
  73. package/lib/core/profile-page.mjs +0 -104
  74. package/lib/core/proof.mjs +0 -79
  75. package/lib/core/publisher/collections.mjs +0 -272
  76. package/lib/core/publisher/index.mjs +0 -522
  77. package/lib/core/publisher/notes.mjs +0 -519
  78. package/lib/core/publisher/own.mjs +0 -143
  79. package/lib/core/publisher/questions.mjs +0 -241
  80. package/lib/core/publisher/restore.mjs +0 -224
  81. package/lib/core/shapes/activitystreams.ttl +0 -157
  82. package/lib/core/shapes/index.mjs +0 -132
  83. package/lib/core/shapes/shapes-text.mjs +0 -13
  84. package/lib/core/social.mjs +0 -561
  85. package/lib/core/storage.mjs +0 -176
  86. package/lib/core/store.mjs +0 -578
  87. package/lib/core/wire-quotes.mjs +0 -71
  88. package/lib/core/wire.mjs +0 -925
  89. package/lib/device/account.mjs +0 -87
  90. package/lib/device/admin/index.mjs +0 -13
  91. package/lib/device/admin/origins.mjs +0 -35
  92. package/lib/device/admin/routes/connections.mjs +0 -144
  93. package/lib/device/admin/routes/gateway.mjs +0 -199
  94. package/lib/device/admin/routes/lifecycle.mjs +0 -200
  95. package/lib/device/admin/routes/owner.mjs +0 -322
  96. package/lib/device/admin/routes/setup.mjs +0 -428
  97. package/lib/device/admin/routes/social.mjs +0 -188
  98. package/lib/device/admin/server.mjs +0 -95
  99. package/lib/device/admin/static.mjs +0 -247
  100. package/lib/device/admin/surface.mjs +0 -315
  101. package/lib/device/certs.mjs +0 -281
  102. package/lib/device/cli/commands/account.mjs +0 -586
  103. package/lib/device/cli/commands/run.mjs +0 -278
  104. package/lib/device/cli/commands/service.mjs +0 -221
  105. package/lib/device/cli/commands/setup.mjs +0 -489
  106. package/lib/device/cli/commands/state.mjs +0 -561
  107. package/lib/device/cli/context.mjs +0 -288
  108. package/lib/device/export-collections.mjs +0 -161
  109. package/lib/device/gateway-move.mjs +0 -58
  110. package/lib/device/home.mjs +0 -161
  111. package/lib/device/migrate.mjs +0 -115
  112. package/lib/device/ports.mjs +0 -27
  113. package/lib/device/remote.mjs +0 -54
  114. package/lib/device/setup.mjs +0 -496
  115. package/lib/device/update.mjs +0 -96
  116. package/lib/gateway/caches.mjs +0 -36
  117. package/lib/gateway/directory.mjs +0 -90
  118. package/lib/gateway/front-core.mjs +0 -966
  119. package/lib/gateway/gateway-core.mjs +0 -244
  120. package/lib/gateway/headers.mjs +0 -49
  121. package/lib/gateway/httpsig.mjs +0 -159
  122. package/lib/gateway/notices.mjs +0 -84
  123. package/lib/gateway/quiet.mjs +0 -189
  124. package/lib/gateway/relay-extras.mjs +0 -89
  125. package/lib/gateway/token-claims.mjs +0 -16
  126. package/lib/pod/README.md +0 -61
  127. package/lib/pod/actor.mjs +0 -96
  128. package/lib/pod/collection.mjs +0 -77
  129. package/lib/pod/containers.mjs +0 -140
  130. package/lib/pod/discovery.mjs +0 -46
  131. package/lib/pod/featured.mjs +0 -18
  132. package/lib/pod/followers.mjs +0 -24
  133. package/lib/pod/following.mjs +0 -10
  134. package/lib/pod/http.mjs +0 -74
  135. package/lib/pod/inbox.mjs +0 -166
  136. package/lib/pod/links.mjs +0 -35
  137. package/lib/pod/location.mjs +0 -52
  138. package/lib/pod/media.mjs +0 -27
  139. package/lib/pod/notes.mjs +0 -78
  140. package/lib/pod/notifications.mjs +0 -89
  141. package/lib/pod/outbox.mjs +0 -18
  142. package/lib/pod/package.json +0 -19
  143. package/lib/pod/policy.mjs +0 -58
  144. package/lib/pod/private.mjs +0 -19
  145. package/lib/pod/root.mjs +0 -104
  146. package/lib/pod/state.mjs +0 -40
  147. package/lib/pod/transport.mjs +0 -674
  148. package/lib/pod/type-index.mjs +0 -101
  149. package/lib/pod/urls.mjs +0 -91
  150. package/lib/server/embed.mjs +0 -424
  151. package/lib/session/README.md +0 -137
  152. package/lib/session/demo.html +0 -94
  153. package/lib/session/fedi-account.mjs +0 -417
  154. package/lib/session/fedi-login.mjs +0 -123
  155. package/lib/session/oidc-session.mjs +0 -233
  156. package/lib/session/package.json +0 -49
  157. package/lib/shared/guard.mjs +0 -213
  158. package/lib/shared/links.mjs +0 -9
  159. package/lib/shared/safefetch.mjs +0 -235
  160. package/lib/shared/ua.mjs +0 -29
  161. package/phanpy/dist/404.html +0 -40
  162. package/phanpy/dist/_headers +0 -2
  163. package/phanpy/dist/apple-touch-icon.png +0 -0
  164. package/phanpy/dist/assets/ICONS-DIPJeU0C.js +0 -2
  165. package/phanpy/dist/assets/ICONS-DIPJeU0C.js.map +0 -1
  166. package/phanpy/dist/assets/ScheduledAtField-D-Abfo4J.js +0 -183
  167. package/phanpy/dist/assets/ScheduledAtField-D-Abfo4J.js.map +0 -1
  168. package/phanpy/dist/assets/Temml-CCjoacWt.woff2 +0 -0
  169. package/phanpy/dist/assets/__vite-browser-external-C7iut881.js +0 -2
  170. package/phanpy/dist/assets/__vite-browser-external-C7iut881.js.map +0 -1
  171. package/phanpy/dist/assets/boosts-carousel-BiOaNdMT.jpg +0 -0
  172. package/phanpy/dist/assets/catch-up-O5q5C75Z.png +0 -0
  173. package/phanpy/dist/assets/chunk-aKtaBQYM.js +0 -1
  174. package/phanpy/dist/assets/compose-CFEx7wb4.js +0 -2
  175. package/phanpy/dist/assets/compose-CFEx7wb4.js.map +0 -1
  176. package/phanpy/dist/assets/compose-ZJN5xSb4.js +0 -35
  177. package/phanpy/dist/assets/compose-ZJN5xSb4.js.map +0 -1
  178. package/phanpy/dist/assets/debug.module-YFQgwnIr.js +0 -52
  179. package/phanpy/dist/assets/debug.module-YFQgwnIr.js.map +0 -1
  180. package/phanpy/dist/assets/dom-p1YcJ5Rw.js +0 -2
  181. package/phanpy/dist/assets/dom-p1YcJ5Rw.js.map +0 -1
  182. package/phanpy/dist/assets/home-mobile-dark@2x-Dc-J8-SM.png +0 -0
  183. package/phanpy/dist/assets/home-mobile-light@2x-Bd3fod8m.png +0 -0
  184. package/phanpy/dist/assets/home-tablet-dark@2x-BgcNI8le.png +0 -0
  185. package/phanpy/dist/assets/home-tablet-light@2x-BW2RV9T6.png +0 -0
  186. package/phanpy/dist/assets/icons/add-circle-line-WD0mwORD.js +0 -1
  187. package/phanpy/dist/assets/icons/alert-line-CpFUMf9s.js +0 -1
  188. package/phanpy/dist/assets/icons/android-2-line-Bzxnrd3S.js +0 -1
  189. package/phanpy/dist/assets/icons/announcement-line-5nwaJFJm.js +0 -1
  190. package/phanpy/dist/assets/icons/arrow-down-circle-line-a7Id9-Iv.js +0 -1
  191. package/phanpy/dist/assets/icons/arrow-down-line-B8uzXzq6.js +0 -1
  192. package/phanpy/dist/assets/icons/arrow-left-line-CGrGT9C-.js +0 -1
  193. package/phanpy/dist/assets/icons/arrow-right-line-CE-HERfX.js +0 -1
  194. package/phanpy/dist/assets/icons/arrow-to-up-line-CvdQjmcy.js +0 -1
  195. package/phanpy/dist/assets/icons/arrow-up-circle-line-DEparSNF.js +0 -1
  196. package/phanpy/dist/assets/icons/arrow-up-line-C7yBeugc.js +0 -1
  197. package/phanpy/dist/assets/icons/arrows-right-line-BtbXmJGP.js +0 -1
  198. package/phanpy/dist/assets/icons/at-line-CF66Bznk.js +0 -1
  199. package/phanpy/dist/assets/icons/attachment-line-BY8It-l9.js +0 -1
  200. package/phanpy/dist/assets/icons/blockquote-line-BS6pU_hm.js +0 -1
  201. package/phanpy/dist/assets/icons/board-line-C0UWXyA6.js +0 -1
  202. package/phanpy/dist/assets/icons/bookmark-line-1CtX5JLF.js +0 -1
  203. package/phanpy/dist/assets/icons/building-5-line-Dd59MzbO.js +0 -1
  204. package/phanpy/dist/assets/icons/bus-2-line-6_dvA0GG.js +0 -1
  205. package/phanpy/dist/assets/icons/calendar-day-line-Crpl_fmu.js +0 -1
  206. package/phanpy/dist/assets/icons/calendar-month-line-vommts2C.js +0 -1
  207. package/phanpy/dist/assets/icons/calendar-time-add-line-BU_DTlQk.js +0 -1
  208. package/phanpy/dist/assets/icons/camera-line-Cv69MEei.js +0 -1
  209. package/phanpy/dist/assets/icons/celebrate-line-B8DvIoi0.js +0 -1
  210. package/phanpy/dist/assets/icons/chart-bar-line-FK-QOmtF.js +0 -1
  211. package/phanpy/dist/assets/icons/chart-line-line-BGcJAFWw.js +0 -1
  212. package/phanpy/dist/assets/icons/chat-3-line-YFK2-hwz.js +0 -1
  213. package/phanpy/dist/assets/icons/check-circle-line-DsAxFr5-.js +0 -1
  214. package/phanpy/dist/assets/icons/clipboard-line-BBp364gJ.js +0 -1
  215. package/phanpy/dist/assets/icons/close-circle-line-CICdiuGz.js +0 -1
  216. package/phanpy/dist/assets/icons/close-line-DYrFWcjv.js +0 -1
  217. package/phanpy/dist/assets/icons/cloud-line-tiQAbah8.js +0 -1
  218. package/phanpy/dist/assets/icons/code-line-fAl8iiV3.js +0 -1
  219. package/phanpy/dist/assets/icons/comment-2-line-CR3g7WeB.js +0 -1
  220. package/phanpy/dist/assets/icons/copy-2-line-CLW69yF5.js +0 -1
  221. package/phanpy/dist/assets/icons/delete-2-line-B8xmbr4n.js +0 -1
  222. package/phanpy/dist/assets/icons/document-3-line-DBGNhAg2.js +0 -1
  223. package/phanpy/dist/assets/icons/document-line-C7mb9sb7.js +0 -1
  224. package/phanpy/dist/assets/icons/down-line-BGqSSThd.js +0 -1
  225. package/phanpy/dist/assets/icons/edit-4-line-DcgGaEhx.js +0 -1
  226. package/phanpy/dist/assets/icons/emoji-2-line-D8YgnM-y.js +0 -1
  227. package/phanpy/dist/assets/icons/exit-line-Dc07BS-x.js +0 -1
  228. package/phanpy/dist/assets/icons/external-link-line-BvpSkmjO.js +0 -1
  229. package/phanpy/dist/assets/icons/eye-2-line-CiWXx-f_.js +0 -1
  230. package/phanpy/dist/assets/icons/eye-close-line-BgTaSJ4P.js +0 -1
  231. package/phanpy/dist/assets/icons/filter-2-line-B_mR2usy.js +0 -1
  232. package/phanpy/dist/assets/icons/filter-line-C_nm-3cU.js +0 -1
  233. package/phanpy/dist/assets/icons/flag-1-line-C2HB05I0.js +0 -1
  234. package/phanpy/dist/assets/icons/forbid-circle-line-D3LTT9yd.js +0 -1
  235. package/phanpy/dist/assets/icons/formula-line-DLrt2d6j.js +0 -1
  236. package/phanpy/dist/assets/icons/grid-line-CgUmEikf.js +0 -1
  237. package/phanpy/dist/assets/icons/group-line-C5fnX0wU.js +0 -1
  238. package/phanpy/dist/assets/icons/hand-finger-2-line-BGgxbuL9.js +0 -1
  239. package/phanpy/dist/assets/icons/hashtag-line-CyTEEXBb.js +0 -1
  240. package/phanpy/dist/assets/icons/heart-crack-line-BZddbO2C.js +0 -1
  241. package/phanpy/dist/assets/icons/heart-line-CJ7K47J4.js +0 -1
  242. package/phanpy/dist/assets/icons/history-2-line-kWWvFzqv.js +0 -1
  243. package/phanpy/dist/assets/icons/history-line-bGQiwbTH.js +0 -1
  244. package/phanpy/dist/assets/icons/home-3-line-fRU1zeLG.js +0 -1
  245. package/phanpy/dist/assets/icons/information-line-iNk6-sOY.js +0 -1
  246. package/phanpy/dist/assets/icons/keyboard-line-DsCyuQNz.js +0 -1
  247. package/phanpy/dist/assets/icons/layout-4-line-CZkOX52Z.js +0 -1
  248. package/phanpy/dist/assets/icons/layout-5-line-B_znt5wO.js +0 -1
  249. package/phanpy/dist/assets/icons/left-line-eUw0tya4.js +0 -1
  250. package/phanpy/dist/assets/icons/lightning-line-DaKoDdix.js +0 -1
  251. package/phanpy/dist/assets/icons/link-2-line-DCqLmMA7.js +0 -1
  252. package/phanpy/dist/assets/icons/list-check-line-BAxosBh9.js +0 -1
  253. package/phanpy/dist/assets/icons/lock-line-CPoaXeUW.js +0 -1
  254. package/phanpy/dist/assets/icons/mail-line-B0P8aa1L.js +0 -1
  255. package/phanpy/dist/assets/icons/moon-line-CEqNAToP.js +0 -1
  256. package/phanpy/dist/assets/icons/more-1-fill-Dw2e5xab.js +0 -1
  257. package/phanpy/dist/assets/icons/more-3-line-BIiVjYTz.js +0 -1
  258. package/phanpy/dist/assets/icons/notification-line-BZZq2Gtu.js +0 -1
  259. package/phanpy/dist/assets/icons/pencil-line-CKh8-A1v.js +0 -1
  260. package/phanpy/dist/assets/icons/photo-album-line-Bnfg2u40.js +0 -1
  261. package/phanpy/dist/assets/icons/pin-line-DpTolyhs.js +0 -1
  262. package/phanpy/dist/assets/icons/play-fill-B0-G_8lX.js +0 -1
  263. package/phanpy/dist/assets/icons/qrcode-2-line-B6SPCaHn.js +0 -1
  264. package/phanpy/dist/assets/icons/quill-pen-line-B6LUrnCP.js +0 -1
  265. package/phanpy/dist/assets/icons/quote-left-fill-hQZ1cj_6.js +0 -1
  266. package/phanpy/dist/assets/icons/radar-line-CKyroTth.js +0 -1
  267. package/phanpy/dist/assets/icons/react-line-CoIKhhtK.js +0 -1
  268. package/phanpy/dist/assets/icons/refresh-2-line-D0mTF97S.js +0 -1
  269. package/phanpy/dist/assets/icons/right-line-B3KWJaqc.js +0 -1
  270. package/phanpy/dist/assets/icons/rocket-line-4KZl537D.js +0 -1
  271. package/phanpy/dist/assets/icons/round-fill-C69NTrZ0.js +0 -1
  272. package/phanpy/dist/assets/icons/round-line-B9k_1uo-.js +0 -1
  273. package/phanpy/dist/assets/icons/route-line-B28ReHcE.js +0 -1
  274. package/phanpy/dist/assets/icons/rows-4-line-CrBniagM.js +0 -1
  275. package/phanpy/dist/assets/icons/scan-line-DSf74YdP.js +0 -1
  276. package/phanpy/dist/assets/icons/search-2-line-B6geIU1z.js +0 -1
  277. package/phanpy/dist/assets/icons/settings-3-line-azJwK47w.js +0 -1
  278. package/phanpy/dist/assets/icons/settings-6-line-C_5zc5YR.js +0 -1
  279. package/phanpy/dist/assets/icons/share-2-line-D5MxWjrm.js +0 -1
  280. package/phanpy/dist/assets/icons/share-forward-line-Cp61fZzZ.js +0 -1
  281. package/phanpy/dist/assets/icons/sparkles-2-line-DYYyXTaW.js +0 -1
  282. package/phanpy/dist/assets/icons/sparkles-line-C2hY1s6I.js +0 -1
  283. package/phanpy/dist/assets/icons/time-line-BF3eet1v.js +0 -1
  284. package/phanpy/dist/assets/icons/transfer-4-line-oisfvTBw.js +0 -1
  285. package/phanpy/dist/assets/icons/translate-line-BFWol2Ce.js +0 -1
  286. package/phanpy/dist/assets/icons/unlock-line-X_x5vwv3.js +0 -1
  287. package/phanpy/dist/assets/icons/upload-3-line-DgzwUJeW.js +0 -1
  288. package/phanpy/dist/assets/icons/user-4-line-BVSynZCp.js +0 -1
  289. package/phanpy/dist/assets/icons/user-add-2-line-BlGS5Q8q.js +0 -1
  290. package/phanpy/dist/assets/icons/user-add-line-BbXdHG4z.js +0 -1
  291. package/phanpy/dist/assets/icons/user-edit-line-BFAHOV0X.js +0 -1
  292. package/phanpy/dist/assets/icons/user-follow-line-BXux0wSd.js +0 -1
  293. package/phanpy/dist/assets/icons/user-star-line-DdYlpHLU.js +0 -1
  294. package/phanpy/dist/assets/icons/user-warning-line-Cj43j0_E.js +0 -1
  295. package/phanpy/dist/assets/icons/user-x-line-DIDgNlPH.js +0 -1
  296. package/phanpy/dist/assets/icons/volume-line-Bs390KQt.js +0 -1
  297. package/phanpy/dist/assets/icons/volume-mute-line-DzlzIqFZ.js +0 -1
  298. package/phanpy/dist/assets/icons/walk-line-yNXfB-md.js +0 -1
  299. package/phanpy/dist/assets/icons/world-2-line-CenkGIwj.js +0 -1
  300. package/phanpy/dist/assets/icons/zoom-in-line-CaENUphf.js +0 -1
  301. package/phanpy/dist/assets/icons/zoom-out-line-BDNk0EWo.js +0 -1
  302. package/phanpy/dist/assets/instances-BNPptnn-.json +0 -333
  303. package/phanpy/dist/assets/locales/ar-SA-CfheRbCu.js +0 -1
  304. package/phanpy/dist/assets/locales/ca-ES-DHRW86Tz.js +0 -1
  305. package/phanpy/dist/assets/locales/cs-CZ-CKoqEuA1.js +0 -1
  306. package/phanpy/dist/assets/locales/de-DE-ByRPMRFy.js +0 -1
  307. package/phanpy/dist/assets/locales/eo-UY-CPC7wLCS.js +0 -1
  308. package/phanpy/dist/assets/locales/es-ES-dJa0Fd9t.js +0 -1
  309. package/phanpy/dist/assets/locales/eu-ES-C3djlPR2.js +0 -1
  310. package/phanpy/dist/assets/locales/fa-IR-DTT490Ck.js +0 -1
  311. package/phanpy/dist/assets/locales/fi-FI-B23MCPuz.js +0 -1
  312. package/phanpy/dist/assets/locales/fr-FR-BcaQsO5C.js +0 -1
  313. package/phanpy/dist/assets/locales/gl-ES-BR-CVKBN.js +0 -1
  314. package/phanpy/dist/assets/locales/he-IL-CfheRbCu.js +0 -1
  315. package/phanpy/dist/assets/locales/hu-HU-CfheRbCu.js +0 -1
  316. package/phanpy/dist/assets/locales/it-IT-C1136UFV.js +0 -1
  317. package/phanpy/dist/assets/locales/ja-JP-CRZmRAhD.js +0 -1
  318. package/phanpy/dist/assets/locales/kab-Cz8xH_TT.js +0 -1
  319. package/phanpy/dist/assets/locales/ko-KR-CG9UiY4o.js +0 -1
  320. package/phanpy/dist/assets/locales/lt-LT-CJcI6sHZ.js +0 -1
  321. package/phanpy/dist/assets/locales/nb-NO-CfheRbCu.js +0 -1
  322. package/phanpy/dist/assets/locales/nl-NL-DxN4Yc1t.js +0 -1
  323. package/phanpy/dist/assets/locales/oc-FR-CfheRbCu.js +0 -1
  324. package/phanpy/dist/assets/locales/pl-PL-DkwGXf6P.js +0 -1
  325. package/phanpy/dist/assets/locales/pseudo-LOCALE-CQ4XxkQ0.js +0 -1
  326. package/phanpy/dist/assets/locales/pt-BR-nGL0HdFS.js +0 -1
  327. package/phanpy/dist/assets/locales/pt-PT-Cp17aj2z.js +0 -1
  328. package/phanpy/dist/assets/locales/ru-RU-0Y8cIoaK.js +0 -1
  329. package/phanpy/dist/assets/locales/th-TH-CfheRbCu.js +0 -1
  330. package/phanpy/dist/assets/locales/tok-CfheRbCu.js +0 -1
  331. package/phanpy/dist/assets/locales/tr-TR-CfheRbCu.js +0 -1
  332. package/phanpy/dist/assets/locales/uk-UA-C5E3dFBf.js +0 -1
  333. package/phanpy/dist/assets/locales/zh-CN-BHJi7_et.js +0 -1
  334. package/phanpy/dist/assets/locales/zh-TW-CfheRbCu.js +0 -1
  335. package/phanpy/dist/assets/main-BdqNbG-a.js +0 -26
  336. package/phanpy/dist/assets/main-BdqNbG-a.js.map +0 -1
  337. package/phanpy/dist/assets/mock-home-DGhR__He.js +0 -2
  338. package/phanpy/dist/assets/mock-home-DGhR__He.js.map +0 -1
  339. package/phanpy/dist/assets/multi-column-ROck0NVt.jpg +0 -0
  340. package/phanpy/dist/assets/multi-hashtag-timeline-DH5INVHi.jpg +0 -0
  341. package/phanpy/dist/assets/nested-comments-thread-hv59kZLc.jpg +0 -0
  342. package/phanpy/dist/assets/polyfill-force-H8sUkLGp.js +0 -2
  343. package/phanpy/dist/assets/polyfill-force-H8sUkLGp.js.map +0 -1
  344. package/phanpy/dist/assets/pwa-viewport-ogKbF51K.js +0 -20
  345. package/phanpy/dist/assets/pwa-viewport-ogKbF51K.js.map +0 -1
  346. package/phanpy/dist/assets/style-B1iLPTPR.css +0 -2
  347. package/phanpy/dist/assets/temml-DuyIQMei.js +0 -97
  348. package/phanpy/dist/assets/temml-DuyIQMei.js.map +0 -1
  349. package/phanpy/dist/assets/tinyld.light.node-DtbBhLYC.js +0 -2
  350. package/phanpy/dist/assets/tinyld.light.node-DtbBhLYC.js.map +0 -1
  351. package/phanpy/dist/assets/year-in-posts-B2lywqdx.png +0 -0
  352. package/phanpy/dist/assets/year-in-posts-DJv_star.js +0 -3
  353. package/phanpy/dist/assets/year-in-posts-DJv_star.js.map +0 -1
  354. package/phanpy/dist/compose/index.html +0 -20
  355. package/phanpy/dist/favicon.ico +0 -0
  356. package/phanpy/dist/index.html +0 -73
  357. package/phanpy/dist/logo-192.png +0 -0
  358. package/phanpy/dist/logo-512.png +0 -0
  359. package/phanpy/dist/logo-badge-72.png +0 -0
  360. package/phanpy/dist/logo-maskable-512.png +0 -0
  361. package/phanpy/dist/logo-monochrome-512.png +0 -0
  362. package/phanpy/dist/logo-monochrome-maskable-512.png +0 -0
  363. package/phanpy/dist/manifest.webmanifest +0 -1
  364. package/phanpy/dist/og-image-2.jpg +0 -0
  365. package/phanpy/dist/og-image.png +0 -0
  366. package/phanpy/dist/robots.txt +0 -2
  367. package/phanpy/dist/sw.js +0 -2
  368. package/phanpy/dist/sw.js.map +0 -1
  369. package/phanpy/dist/version.json +0 -1
  370. package/run-agent.mjs +0 -899
  371. package/vendor/gate.cjs +0 -138
  372. package/vendor/idp-grant.cjs +0 -394
  373. package/vendor/jfetch.cjs +0 -16
  374. package/web/admin/actors.js +0 -147
  375. package/web/admin/bar.css +0 -126
  376. package/web/admin/bar.js +0 -99
  377. package/web/admin/client/client.js +0 -66
  378. package/web/admin/client/index.html +0 -69
  379. package/web/admin/client-pick.js +0 -79
  380. package/web/admin/common.js +0 -23
  381. package/web/admin/connections.js +0 -112
  382. package/web/admin/gateway.js +0 -133
  383. package/web/admin/group.js +0 -258
  384. package/web/admin/index.html +0 -612
  385. package/web/admin/notices-bar.js +0 -90
  386. package/web/admin/oauth-signin.mjs +0 -37
  387. package/web/admin/record.js +0 -393
  388. package/web/admin/setup/index.html +0 -257
  389. package/web/admin/setup/setup.js +0 -339
  390. package/web/admin/tokens.css +0 -68
  391. package/web/admin/upkeep.js +0 -177
  392. package/web/admin/window.css +0 -55
  393. package/web/admin/window.js +0 -136
  394. package/web/app/README.md +0 -81
  395. package/web/app/admin-facade.mjs +0 -588
  396. package/web/app/agent.mjs +0 -672
  397. package/web/app/atproto-browser.mjs +0 -86
  398. package/web/app/authorize_interaction.html +0 -56
  399. package/web/app/authorize_interaction.js +0 -69
  400. package/web/app/boot.mjs +0 -616
  401. package/web/app/deliver-relay.mjs +0 -129
  402. package/web/app/dist/boot.js +0 -34562
  403. package/web/app/dist/boot.js.map +0 -7
  404. package/web/app/dist/sw.js +0 -73456
  405. package/web/app/dist/sw.js.map +0 -7
  406. package/web/app/fediacct-browser.mjs +0 -146
  407. package/web/app/gateway-move.mjs +0 -60
  408. package/web/app/idb-kv.mjs +0 -35
  409. package/web/app/index.html +0 -258
  410. package/web/app/keys-browser.mjs +0 -71
  411. package/web/app/keystore.mjs +0 -82
  412. package/web/app/oidc-session.mjs +0 -6
  413. package/web/app/pod-auth.mjs +0 -248
  414. package/web/app/pod-remote.mjs +0 -84
  415. package/web/app/shims/_globals.mjs +0 -2
  416. package/web/app/shims/fedify-sig.mjs +0 -77
  417. package/web/app/shims/node-crypto.mjs +0 -113
  418. package/web/app/shims/node-fs.mjs +0 -17
  419. package/web/app/shims/node-path.mjs +0 -19
  420. package/web/app/shims/node-url.mjs +0 -7
  421. package/web/app/shims/prelude.js +0 -58
  422. package/web/app/shims/safefetch.mjs +0 -58
  423. package/web/app/shims/shapes-text.mjs +0 -8
  424. package/web/app/shims/web-push.mjs +0 -14
  425. package/web/app/signup.mjs +0 -357
  426. package/web/app/sw-src.mjs +0 -220
  427. package/web/app/update.js +0 -70
  428. package/web/front/admin.html +0 -55
  429. package/web/front/admin.js +0 -89
  430. package/web/front/install.sh +0 -69
  431. package/web/front/new-account.html +0 -35
  432. package/web/front/new-account.js +0 -13
  433. package/web/front/notices.html +0 -69
  434. package/web/front/notices.js +0 -107
  435. package/web/front/run.html +0 -64
  436. package/web/front/run.js +0 -221
  437. package/web/front/solid-oidc-client.js +0 -6
  438. package/web/icons/forum.svg +0 -11
  439. package/web/icons/gateway.svg +0 -14
  440. package/web/icons/local.svg +0 -11
@@ -1,561 +0,0 @@
1
- // state.mjs — where things live and moving them: state (this identity's
2
- // private half, or every identity's), upgrade, profiles, home, export.
3
-
4
- import fs from 'node:fs';
5
- import os from 'node:os';
6
- import path from 'node:path';
7
- import { spawn } from 'node:child_process';
8
- import { fileURLToPath, pathToFileURL } from 'node:url';
9
- import { identityHomes, isLegacyRoot, CURRENT_ROOT, tildify, defaultProfile, profileHome, rootHoldsIdentity, recordLastUsed, writeJsonAtomic } from '../../home.mjs';
10
- import { insecureUrlReason } from '../../../shared/safefetch.mjs';
11
- import { localFetch } from '../../../client/localapi.mjs';
12
- import { args, flag, has, PROFILE, AP_ROOT, HOME, PORT, requireHandle, requireIdentity, somethingOn, agentOn, isInside } from '../context.mjs';
13
-
14
- export async function state() {
15
- if (has('all') || has('drop-remote')) return stateAll();
16
- requireIdentity();
17
- // Where the private half lives, and how to move it. Copy, verify, THEN
18
- // repoint — a pointer moved on its own leaves the agent reading one
19
- // container and writing another, which is the divergence this avoids.
20
- // The old copy is left behind on purpose; delete it when you are satisfied.
21
- const credPath = path.join(HOME, 'credential.json');
22
- let cred;
23
- try { cred = JSON.parse(fs.readFileSync(credPath, 'utf8')); }
24
- catch { console.error(`no identity in ${HOME} — run setup first`); process.exit(2); }
25
-
26
- const { apUrls } = await import(new URL('../../../../lib/core/wire.mjs', import.meta.url));
27
- const { Agent } = await import(new URL('../../../../run-agent.mjs', import.meta.url));
28
- const where = (c) => (c.privateRoot ? tildify(c.privateRoot) : `${apUrls(c.remotePod, c.root).home}(on the pod)`);
29
-
30
- const to = flag('to');
31
- if (!to) {
32
- console.log(`private data: ${where(cred)}`);
33
- console.log(`public face: ${apUrls(cred.remotePod, cred.root).home}`);
34
- console.log('\nTo move it: fedipod state --to ~/somewhere/private/');
35
- console.log(' fedipod state --to <container-url>');
36
- console.log(' fedipod state --to pod');
37
- process.exit(0);
38
- }
39
- if (await localFetch(HOME, PORT, `/status`).then(() => true).catch(() => false)) {
40
- console.error(`an agent is running on port ${PORT} — stop it first: fedipod stop`);
41
- process.exit(1);
42
- }
43
- // A path or a URL. `state` prints the path form, so refusing it here would
44
- // mean what the command shows you is not what it takes back — two chars before
45
- // the colon, so a Windows drive letter is a path rather than a scheme.
46
- let target = null;
47
- if (to !== 'pod') {
48
- const asPath = !/^[a-z][a-z0-9+.-]+:/i.test(to);
49
- const raw = asPath
50
- ? pathToFileURL(path.resolve(to.replace(/^~(?=[/\\]|$)/, os.homedir()))).href
51
- : to;
52
- target = raw.endsWith('/') ? raw : raw + '/';
53
- try { new URL(target); } catch { console.error(`"${to}" is not a container URL or a path`); process.exit(2); }
54
- }
55
- if ((cred.privateRoot || null) === target) { console.log(`already there: ${where(cred)}`); process.exit(0); }
56
- // Before anything is built or sent, not after. This check used to sit at the
57
- // very bottom, past the copy — so `--to http://nas.local/private/`, a typo
58
- // for https or a plaintext box on the LAN, wrote every state document
59
- // (masto-tokens.json included) and every RDF note to that host in the clear,
60
- // and only then said the address was refused. The messages around it, which
61
- // say nothing was repointed and the old copy was left where it was, were
62
- // true and read as "nothing happened".
63
- if (/^https?:/i.test(target || '')) {
64
- const bad = insecureUrlReason(target, 'private-data address');
65
- if (bad) { console.error(bad); process.exit(2); }
66
- }
67
-
68
- const agent = new Agent({ home: HOME, log: (...a) => console.log('[state]', ...a) });
69
- agent.urls = apUrls(cred.remotePod, cred.root);
70
- // Only one of the two sides can be the pod, and moving between two local
71
- // pods needs no credential at all — so do not spend a token grant on it.
72
- if (!cred.privateRoot || !target) {
73
- const { RemotePod } = await import(new URL('../../../../lib/device/remote.mjs', import.meta.url));
74
- agent.remote = new RemotePod(cred, { log: () => {}, home: HOME });
75
- // A pod that is not there is the ordinary case for an identity nobody has
76
- // run in a while, and it used to arrive as an unhandled rejection — 20
77
- // lines of undici internals ending in ECONNREFUSED, with the reason on the
78
- // last line. Say which pod and why, and stop.
79
- try { await agent.remote.warmup(); }
80
- catch (e) {
81
- const why = e?.cause?.code === 'ECONNREFUSED' ? 'nothing is listening there' : (e.message || String(e));
82
- console.error(`cannot reach the pod this identity keeps its private half on:`);
83
- console.error(` ${cred.remotePod} — ${why}`);
84
- console.error('Nothing was copied and nothing was repointed. Start the pod and try again.');
85
- process.exit(1);
86
- }
87
- }
88
- const destCred = { ...cred, privateRoot: target };
89
- const from = agent.privateUrls(cred);
90
- const dest = agent.privateUrls(destCred);
91
- console.log(`moving the private half\n from ${from.state.replace(/ap-state\/$/, '')}\n to ${dest.state.replace(/ap-state\/$/, '')}\n`);
92
-
93
- const { copyPrivateHalf } = await import(new URL('../../../../lib/device/migrate.mjs', import.meta.url));
94
- let copied;
95
- try {
96
- copied = await copyPrivateHalf({
97
- from: { state: agent.privateStorage(cred, 'state') },
98
- to: { state: agent.privateStorage(destCred, 'state') },
99
- log: (...a) => console.log('[state]', ...a),
100
- });
101
- } catch (e) { console.error(e.message); process.exit(1); }
102
- console.log(`copied ${copied.docs} state document(s)`);
103
-
104
- // An empty source produces an empty destination, and every check above
105
- // passes: nothing failed to land because nothing was sent. The command then
106
- // repointed the credential and said it had moved your private data. Say what
107
- // actually happened instead — an empty move is usually a wrong --from, and
108
- // finding that out later means looking for a timeline that was never there.
109
- if (copied.docs === 0 && copied.notes === 0) {
110
- console.log('\nNOTHING WAS COPIED — the source held no state documents and no notes.');
111
- console.log(` from: ${where(cred)}`);
112
- console.log('The pointer is being moved anyway, which is right for a fresh identity');
113
- console.log('and wrong if you expected a timeline here. Check the source if so.\n');
114
- }
115
-
116
- if (target) cred.privateRoot = target; else delete cred.privateRoot;
117
- // Stamp what this install now IS, so `upgrade` stops naming it and the agent
118
- // stops saying it is behind. Moving back onto the pod un-stamps it, which is
119
- // honest rather than punitive: that is the old shape, and it should read as
120
- // the old shape whoever chose it.
121
- {
122
- const { CURRENT_LAYOUT, isCurrent } = await import(new URL('../../../../lib/device/migrate.mjs', import.meta.url));
123
- if (isCurrent(cred)) cred.layout = CURRENT_LAYOUT; else delete cred.layout;
124
- }
125
- writeJsonAtomic(credPath, cred);
126
- console.log(`\nprivate data now: ${where(cred)}`);
127
- console.log('The old copy was left where it was — `state --drop-remote` removes it');
128
- console.log('once you are satisfied, or delete it by hand.');
129
- process.exit(0);
130
- }
131
-
132
- export async function stateAll() {
133
- // The root-wide half. `state --to` moves ONE identity, with the right AP_HOME
134
- // set by hand; this runs over every identity under the root.
135
- //
136
- // Per identity, in its own process. HOME, PORT and the root are resolved at
137
- // module load from the environment, so doing several in one process would
138
- // mean re-deriving all of it — and a failure part way would be sharing state
139
- // with the next one. A spawn per identity is a handful of processes for a
140
- // one-shot migration, and each is exactly the command you could have typed.
141
- const { execFile } = await import('node:child_process');
142
- const { needsStateMove, pendingSteps } = await import(new URL('../../../../lib/device/migrate.mjs', import.meta.url));
143
- const { apUrls } = await import(new URL('../../../../lib/core/wire.mjs', import.meta.url));
144
-
145
- const homes = identityHomes(AP_ROOT);
146
- if (!homes.length) {
147
- console.log(`no identities under ${tildify(AP_ROOT)} — nothing to move`);
148
- process.exit(0);
149
- }
150
-
151
- // The same refusal `--to` and `home --restructure` make, for the same reason,
152
- // and it has to cover ALL of them: a running agent holds its state
153
- // write-through in memory, so a copy taken underneath one is overwritten by
154
- // its next write.
155
- // Only when something is actually going to be written. A dry run reads
156
- // credential files and prints what it found, and refusing to do THAT while
157
- // the agents are up defeats the whole point of leading with the inventory:
158
- // you would have to stop everything to find out whether you needed to.
159
- if (has('apply')) {
160
- const live = [];
161
- for (const { name, dir } of homes) {
162
- let port = null;
163
- try { port = JSON.parse(fs.readFileSync(path.join(dir, 'agent.json'), 'utf8')).port; } catch { continue; }
164
- if (!port) continue;
165
- const why = await somethingOn(port);
166
- if (why) live.push(`${name} on ${port} (${why})`);
167
- }
168
- if (live.length) {
169
- console.error(`still answering: ${live.join(', ')}`);
170
- console.error('stop them first — a running agent would overwrite the copy with what it holds');
171
- process.exit(2);
172
- }
173
- }
174
-
175
- const rows = [];
176
- for (const { name, dir } of homes) {
177
- let cred = null;
178
- try { cred = JSON.parse(fs.readFileSync(path.join(dir, 'credential.json'), 'utf8')); } catch { continue; }
179
- rows.push({ name, dir, cred, pending: pendingSteps(cred) });
180
- }
181
- if (!rows.length) { console.log('no identities with a credential yet'); process.exit(0); }
182
-
183
- if (has('drop-remote')) {
184
- // Deliberately separate from the move, and second. While both copies exist
185
- // the move is reversible; this is the step that ends that, so it is never
186
- // something you get by accident.
187
- const { RemotePod } = await import(new URL('../../../../lib/device/remote.mjs', import.meta.url));
188
- const { classifyRemoteState } = await import(new URL('../../../../lib/device/migrate.mjs', import.meta.url));
189
- const apply = has('apply');
190
- for (const { name, dir, cred } of rows) {
191
- if (needsStateMove(cred)) {
192
- console.log(`${name}: still on the pod — run \`state --all --apply\` first`);
193
- continue;
194
- }
195
- const urls = apUrls(cred.remotePod, cred.root);
196
- const remote = new RemotePod(cred, { log: () => {}, home: dir });
197
- try { await remote.warmup(); } catch (e) { console.error(`${name}: ${e.message}`); continue; }
198
- const children = (await remote.listContainer(urls.state)).map(c => c.url);
199
- const { drop, keep } = classifyRemoteState(children, urls.state);
200
- console.log(`${name}: ${drop.length} document(s) to remove, ${keep.length} kept`);
201
- for (const k of keep) console.log(` keep ${k.name} — ${k.why}`);
202
- for (const d of drop) {
203
- if (!apply) { console.log(` would remove ${d.name}`); continue; }
204
- try { await remote.delete(d.url); console.log(` removed ${d.name}`); }
205
- catch (e) { console.error(` ${d.name}: ${e.message}`); }
206
- }
207
- }
208
- if (!apply) console.log('\nThis was a dry run. Add --apply to remove them.');
209
- process.exit(0);
210
- }
211
-
212
- const apply = has('apply');
213
- console.log(apply ? 'Moving the private half onto this machine.\n'
214
- : 'What a move would do. Nothing is written without --apply.\n');
215
- let moved = 0;
216
- for (const { name, dir, cred, pending } of rows) {
217
- const home = cred.privateRoot ? tildify(cred.privateRoot)
218
- : `${apUrls(cred.remotePod, cred.root).home} (ON THE POD)`;
219
- if (!pending.length) { console.log(`${name}: already current — ${home}`); continue; }
220
- const dest = pathToFileURL(path.join(dir, 'private')).href + '/';
221
- if (!apply) {
222
- console.log(`${name}: ${home}\n → would move to ${tildify(dest)}`);
223
- continue;
224
- }
225
- const out = await new Promise((resolve) => {
226
- execFile(process.execPath, [process.argv[1], 'state', '--to', dest],
227
- { env: { ...process.env, AP_HOME: dir, AP_PROFILE: '' } },
228
- (err, stdout, stderr) => resolve({ ok: !err, text: String(stdout) + String(stderr) }));
229
- });
230
- console.log(`${name}: ${out.ok ? 'moved' : 'FAILED'}`);
231
- for (const line of out.text.split('\n').filter(Boolean)) console.log(` ${line}`);
232
- if (out.ok) moved++;
233
- }
234
- if (apply) {
235
- console.log(`\n${moved} identit(ies) moved. The pod still holds the old copy —`);
236
- console.log('`state --drop-remote` removes it once you are satisfied.');
237
- } else {
238
- console.log('\nRe-run with --apply to do it.');
239
- }
240
- process.exit(0);
241
- }
242
-
243
- export async function upgrade() {
244
- // One runner, every identity. The point is that being behind is a thing you
245
- // can ASK about rather than something you find out from a pod bill.
246
- const { pendingSteps, layoutOf, CURRENT_LAYOUT, isCurrent } =
247
- await import(new URL('../../../../lib/device/migrate.mjs', import.meta.url));
248
- const homes = identityHomes(AP_ROOT);
249
- const behind = [];
250
- for (const { name, dir } of homes) {
251
- let cred = null;
252
- try { cred = JSON.parse(fs.readFileSync(path.join(dir, 'credential.json'), 'utf8')); } catch { continue; }
253
- const pending = pendingSteps(cred);
254
- console.log(`${name}: layout ${layoutOf(cred)} of ${CURRENT_LAYOUT}${pending.length ? '' : ' — current'}`);
255
- for (const s of pending) console.log(` ${s.id}: ${s.what}\n (${s.why})`);
256
- // Nothing to do and never stamped: an install that was already in the right
257
- // shape. Record it, so `upgrade` stops asking and the agent stops warning.
258
- if (isCurrent(cred) && layoutOf(cred) < CURRENT_LAYOUT) {
259
- writeJsonAtomic(path.join(dir, 'credential.json'), { ...cred, layout: CURRENT_LAYOUT });
260
- console.log(' stamped as current');
261
- }
262
- if (pending.length) behind.push(name);
263
- }
264
- if (!homes.length) console.log(`no identities under ${tildify(AP_ROOT)}`);
265
- else if (behind.length) {
266
- console.log(`\n${behind.length} identit(ies) behind: ${behind.join(', ')}`);
267
- console.log('The only step is the state move. See what it would do:');
268
- console.log(` ${path.basename(process.argv[1])} state --all`);
269
- console.log('then re-run it with --apply.');
270
- } else if (homes.length) console.log('\nEverything here is at the current layout.');
271
- process.exit(0);
272
- }
273
-
274
- export async function profiles() {
275
- // Local files only, plus a quick liveness probe: nothing here needs the pod.
276
- const homes = identityHomes(AP_ROOT);
277
-
278
- const rows = [];
279
- for (const { name, dir } of homes) {
280
- let pod = null, port = null;
281
- try { pod = JSON.parse(fs.readFileSync(path.join(dir, 'credential.json'), 'utf8')).remotePod; } catch {}
282
- try { port = JSON.parse(fs.readFileSync(path.join(dir, 'agent.json'), 'utf8')).port; } catch {}
283
- if (!pod && !port) continue; // not an identity, just a directory
284
- let live = null;
285
- if (port) {
286
- live = await localFetch(HOME, port, `/status`, { signal: AbortSignal.timeout(1500) })
287
- .then(r => r.json()).catch(() => null);
288
- }
289
- // The kind lives in pod state, so it is only knowable from the live probe —
290
- // a stopped identity honestly shows nothing rather than a guess.
291
- rows.push({ name, pod: pod ? new URL(pod).host : '(no credential)', port: port || '—',
292
- // A home can hold a forum, which says so itself; anything else that
293
- // answers is a person unless it says group.
294
- kind: live?.kind === 'group' ? 'group' : live?.kind === 'forum' ? 'forum' : live ? 'person' : '—',
295
- state: live ? `${live.mode}${live.podRequests ? ` · ${live.podRequests.perMinuteNow}/min` : ''}` : 'not running' });
296
- }
297
-
298
- // Which one answers with no --profile. A property of the ROOT, not of any
299
- // identity — which is the whole point of it being a pointer.
300
- const theDefault = (() => { const d = defaultProfile(AP_ROOT); return typeof d === 'string' ? d : null; })();
301
- if (!rows.length) console.log('no identities yet — fedipod setup');
302
- else {
303
- const w = (k, min) => Math.max(min, ...rows.map(r => String(r[k]).length));
304
- const [wn, wp, wo, wk] = [w('name', 7), w('pod', 3), w('port', 4), w('kind', 4)];
305
- console.log(`${'PROFILE'.padEnd(wn)} ${'POD'.padEnd(wp)} ${'PORT'.padEnd(wo)} ${'KIND'.padEnd(wk)} STATE`);
306
- for (const r of rows) {
307
- console.log(`${r.name.padEnd(wn)} ${String(r.pod).padEnd(wp)} ${String(r.port).padEnd(wo)}`
308
- + ` ${String(r.kind).padEnd(wk)} ${r.state}${r.name === theDefault ? ' (default)' : ''}`);
309
- }
310
- }
311
- console.log(`\nIdentities under a custom AP_HOME are not listed — only ${AP_ROOT}`
312
- + ' and its profiles/*.');
313
- process.exit(0);
314
- }
315
-
316
- export async function home() {
317
- if (has('restructure')) return homeRestructure();
318
- // The root holds the credential and the signing keys of every identity on
319
- // this machine, so taking the post-rename name is a command you run, never
320
- // something an upgrade does behind you. Resolution is in lib/home.mjs.
321
- const to = flag('to');
322
- const overridden = !!(process.env.AP_HOME || flag('home'));
323
-
324
- if (!to) {
325
- console.log(`\nroot: ${tildify(AP_ROOT)}${isLegacyRoot(AP_ROOT) ? ' (the name from before the rename)' : ''}`);
326
- console.log(`this home: ${tildify(HOME)}`);
327
- const d = defaultProfile(AP_ROOT);
328
- for (const { name, dir } of identityHomes(AP_ROOT)) {
329
- if (fs.existsSync(path.join(dir, 'credential.json'))) {
330
- console.log(` · ${name}${name === d ? ' (default)' : ''}`);
331
- }
332
- }
333
- if (rootHoldsIdentity(AP_ROOT)) {
334
- console.log('\nThis root still keeps an identity at its top level, from before every');
335
- console.log('identity moved under profiles/. Move it down with:\n');
336
- console.log(` ${process.argv[1]} home --restructure\n`);
337
- }
338
- if (overridden) {
339
- console.log('\nAP_HOME / --home is set, so this run is not using the root above.');
340
- } else if (isLegacyRoot(AP_ROOT)) {
341
- console.log('\nTake the current name with:\n');
342
- console.log(` ${process.argv[1]} home --to ${path.join(os.homedir(), CURRENT_ROOT)}\n`);
343
- console.log('That moves the whole root — the default identity and every profile — and');
344
- console.log('refuses while any of them is answering.');
345
- }
346
- process.exit(0);
347
- }
348
-
349
- if (overridden) {
350
- console.error('AP_HOME / --home is set. That is an explicit directory, not the root this');
351
- console.error('command moves — unset it and run again, or move the directory yourself.');
352
- process.exit(2);
353
- }
354
- const target = path.resolve(to.replace(/^~(?=[/\\]|$)/, os.homedir()));
355
- if (target === AP_ROOT) { console.log(`already there: ${AP_ROOT}`); process.exit(0); }
356
- if (!fs.existsSync(AP_ROOT)) { console.error(`nothing to move — ${AP_ROOT} does not exist`); process.exit(2); }
357
- if (fs.existsSync(target) && fs.readdirSync(target).length) {
358
- console.error(`${target} exists and is not empty — refusing to merge two roots`);
359
- process.exit(2);
360
- }
361
-
362
- // A running agent holds its pidfile and log by path; moving out from under it
363
- // strands both and leaves `stop` with nothing to find.
364
- const live = [];
365
- for (const { name, dir } of identityHomes(AP_ROOT)) {
366
- let port = null;
367
- try { port = JSON.parse(fs.readFileSync(path.join(dir, 'agent.json'), 'utf8')).port; } catch { continue; }
368
- if (port && await agentOn(port)) live.push(`${name} on ${port}`);
369
- }
370
- if (live.length) {
371
- console.error(`still answering: ${live.join(', ')}`);
372
- console.error('stop them first — a move would strand the pidfile and log they hold');
373
- process.exit(2);
374
- }
375
-
376
- fs.mkdirSync(path.dirname(target), { recursive: true });
377
- try {
378
- fs.renameSync(AP_ROOT, target);
379
- } catch (e) {
380
- if (e.code !== 'EXDEV') throw e; // a different filesystem
381
- fs.cpSync(AP_ROOT, target, { recursive: true, preserveTimestamps: true });
382
- fs.rmSync(AP_ROOT, { recursive: true, force: true });
383
- }
384
- console.log(`moved ${AP_ROOT} → ${target}`);
385
-
386
- // privateRoot is recorded as an absolute path. One that pointed inside the
387
- // root we just moved now points at nothing, and an agent finding an empty
388
- // store reports itself unconfigured rather than saying why.
389
- for (const { name, dir } of identityHomes(target)) {
390
- const credPath = path.join(dir, 'credential.json');
391
- let cred;
392
- try { cred = JSON.parse(fs.readFileSync(credPath, 'utf8')); } catch { continue; }
393
- if (!cred.privateRoot || /^https?:/i.test(cred.privateRoot)) continue; // a pod, not a directory
394
- const was = cred.privateRoot.startsWith('file:')
395
- ? fileURLToPath(cred.privateRoot) : path.resolve(cred.privateRoot);
396
- if (!isInside(AP_ROOT, was)) continue; // somewhere else entirely
397
- const now = path.join(target, path.relative(AP_ROOT, was));
398
- cred.privateRoot = pathToFileURL(now).href + '/';
399
- writeJsonAtomic(credPath, cred);
400
- console.log(` · ${name}: private data now ${cred.privateRoot}`);
401
- }
402
-
403
- console.log('\nIf you installed the service, its unit has the old path baked in as');
404
- console.log('Environment=AP_HOME — re-run install-service to update it.');
405
- process.exit(0);
406
- }
407
-
408
- export async function homeRestructure() {
409
- // One-time: move the identity that lives AT the root down into
410
- // profiles/<name>/, so every identity is a named folder and none of them
411
- // contains the others. Its own files only — profiles/ stays where it is.
412
- if (process.env.AP_HOME || flag('home')) {
413
- console.error('AP_HOME / --home is set. That is an explicit identity directory, not the');
414
- console.error('root this restructures — unset it and run again.');
415
- process.exit(2);
416
- }
417
- if (!rootHoldsIdentity(AP_ROOT)) {
418
- console.log(`nothing to move — ${tildify(AP_ROOT)} keeps no identity at its top level`);
419
- const d = defaultProfile(AP_ROOT);
420
- if (typeof d === 'string') console.log(`default identity: ${d}`);
421
- process.exit(0);
422
- }
423
- // Its name is its handle, which agent.json records and pod state confirms.
424
- // Falling back to the credential's pod host keeps a half-set-up root movable.
425
- let name = null;
426
- try { name = JSON.parse(fs.readFileSync(path.join(AP_ROOT, 'agent.json'), 'utf8')).handle || null; } catch {}
427
- if (!name) {
428
- try {
429
- const cfg = JSON.parse(fs.readFileSync(path.join(AP_ROOT, 'private/ap-state/config.json'), 'utf8'));
430
- name = cfg.handle || null;
431
- } catch {}
432
- }
433
- name = flag('name', name);
434
- if (!name) {
435
- console.error('cannot tell what this identity is called — no handle in agent.json or pod state.');
436
- console.error(`Name it: ${process.argv[1]} home --restructure --name <name>`);
437
- process.exit(2);
438
- }
439
- requireHandle(name);
440
- const dest = profileHome(AP_ROOT, name);
441
- if (fs.existsSync(dest) && fs.readdirSync(dest).length) {
442
- console.error(`${tildify(dest)} exists and is not empty — refusing to merge two identities`);
443
- console.error(`Give the moved one another name: ${process.argv[1]} home --restructure --name <name>`);
444
- process.exit(2);
445
- }
446
-
447
- // A running agent holds its pidfile and log by path. Same refusal `--to` makes.
448
- const live = [];
449
- for (const { name: n, dir } of [{ name, dir: AP_ROOT }, ...identityHomes(AP_ROOT)]) {
450
- let port = null;
451
- try { port = JSON.parse(fs.readFileSync(path.join(dir, 'agent.json'), 'utf8')).port; } catch { continue; }
452
- if (!port) continue;
453
- // somethingOn, not agentOn: a gated agent answers 401 to an un-tokened
454
- // /status, and this moves its private key out from under it.
455
- const why = await somethingOn(port);
456
- if (why) live.push(`${n} on ${port} (${why})`);
457
- }
458
- if (live.length) {
459
- console.error(`still answering: ${live.join(', ')}`);
460
- console.error('stop them first — a move would strand the pidfile and log they hold');
461
- process.exit(2);
462
- }
463
-
464
- // Its own files, named explicitly. Everything else at the root — profiles/,
465
- // and root.json once it exists — belongs to the root and stays.
466
- const MOVE = ['credential.json', 'keys.json', 'agent.json', 'agent.log', 'token.json',
467
- 'backoff.json', 'private'];
468
- fs.mkdirSync(dest, { recursive: true, mode: 0o700 });
469
- const moved = [];
470
- for (const f of MOVE) {
471
- const from = path.join(AP_ROOT, f);
472
- if (!fs.existsSync(from)) continue;
473
- fs.renameSync(from, path.join(dest, f));
474
- moved.push(f);
475
- }
476
- // A pidfile names a process that was told to stop. Carrying it forward would
477
- // point `stop` at a pid nobody owns.
478
- fs.rmSync(path.join(AP_ROOT, 'agent.pid'), { force: true });
479
- console.log(`moved ${moved.length} item(s) → ${tildify(dest)}`);
480
- console.log(` ${moved.join(', ')}`);
481
-
482
- // privateRoot is an absolute path; one that pointed at the root's private/
483
- // now points at nothing, and an agent finding an empty store reports itself
484
- // unconfigured rather than saying why.
485
- const credPath = path.join(dest, 'credential.json');
486
- try {
487
- const cred = JSON.parse(fs.readFileSync(credPath, 'utf8'));
488
- if (cred.privateRoot && !/^https?:/i.test(cred.privateRoot)) {
489
- const was = cred.privateRoot.startsWith('file:')
490
- ? fileURLToPath(cred.privateRoot) : path.resolve(cred.privateRoot);
491
- if (isInside(AP_ROOT, was) && !isInside(dest, was)) {
492
- cred.privateRoot = pathToFileURL(path.join(dest, path.relative(AP_ROOT, was))).href + '/';
493
- writeJsonAtomic(credPath, cred);
494
- console.log(` private data now ${tildify(cred.privateRoot)}`);
495
- }
496
- }
497
- } catch { /* no credential to repoint */ }
498
-
499
- recordLastUsed(AP_ROOT, name);
500
- console.log(`\n${name} is what a plain command means now. Start another with`);
501
- console.log(`\`${path.basename(process.argv[1])} --profile <name> start\` and that becomes the one instead.`);
502
- process.exit(0);
503
- }
504
-
505
- export async function exportCollectionsCmd() {
506
- // The account's collections as paged Turtle AS2 collections,
507
- // produced on demand: outbox and followers from the pod, inbox from the
508
- // local archive. See lib/export-collections.mjs.
509
- requireIdentity();
510
- const format = flag('format') || args[1];
511
- const to = flag('to');
512
- if (format !== 'as-collections' || !to) {
513
- console.error('usage: fedipod export --format as-collections --to <directory-or-container-url>');
514
- process.exit(2);
515
- }
516
- const { Agent } = await import(new URL('../../../../run-agent.mjs', import.meta.url));
517
- const { RemotePod } = await import(new URL('../../../../lib/device/remote.mjs', import.meta.url));
518
- const { apUrls } = await import(new URL('../../../../lib/core/wire.mjs', import.meta.url));
519
- const { exportCollections, DIR_BASE } = await import(new URL('../../../../lib/device/export-collections.mjs', import.meta.url));
520
- const { storageFor } = await import(new URL('../../../../lib/core/storage.mjs', import.meta.url));
521
- const agent = new Agent({ home: HOME, log: () => {} });
522
- const cred = agent.readCredential();
523
- if (!cred) { console.error('no credential — run setup first'); process.exit(2); }
524
- agent.remote = new RemotePod(cred);
525
- await agent.remote.warmup();
526
- agent.urls = apUrls(cred.remotePod, cred.root);
527
- agent.store.attach(agent.privateStorage(cred, 'state'));
528
- await agent.store.load();
529
- const { Publisher } = await import(new URL('../../../../lib/core/publisher/index.mjs', import.meta.url));
530
- const outboxItems = (await Publisher.prototype.readPublishedOutbox.call(
531
- { remote: agent.remote, urls: agent.urls })) || [];
532
- // Only real AP actors, like the published followers collection.
533
- const contacts = agent.store.getContacts();
534
- const followers = contacts.followers.filter(f => !f.bsky).map(f => f.actor);
535
- const archive = agent.privateStorage(cred, 'archive');
536
- const inboxEntries = [];
537
- const months = (await archive.list('').catch(() => ({ names: [] }))).names || [];
538
- for (const m of months.filter(n => n.endsWith('/'))) {
539
- const files = (await archive.list(m).catch(() => ({ names: [] }))).names || [];
540
- for (const f of files) {
541
- const r = await archive.read(m + f);
542
- if (!r.ok) continue;
543
- try { inboxEntries.push(JSON.parse(r.body)); } catch { /* not an archive record */ }
544
- }
545
- }
546
- const isUrl = /^https?:/i.test(to);
547
- const storage = storageFor(to, (u, i) => agent.remote.fetch(u, i));
548
- const base = isUrl ? (to.endsWith('/') ? to : to + '/') : DIR_BASE;
549
- try {
550
- const out = await exportCollections({
551
- outboxItems, followers, inboxEntries, storage, base, log: console.log,
552
- resolve: (u) => agent.remote.getJson(u),
553
- });
554
- console.log(`outbox: ${out.outbox.items} item(s) in ${out.outbox.pages} page(s); `
555
- + `followers: ${out.followers.items}; inbox: ${out.inbox.items} archived item(s) in ${out.inbox.pages} page(s)`);
556
- console.log(`${out.written} Turtle document(s) written to ${to}`);
557
- } catch (e) {
558
- console.error(`export failed: ${e.message}`);
559
- process.exit(1);
560
- }
561
- }