six-degrees 0.6.0 → 0.8.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 (609) hide show
  1. package/.next/standalone/.next/BUILD_ID +1 -1
  2. package/.next/standalone/.next/app-path-routes-manifest.json +4 -0
  3. package/.next/standalone/.next/build-manifest.json +3 -3
  4. package/.next/standalone/.next/prerender-manifest.json +42 -14
  5. package/.next/standalone/.next/routes-manifest.json +24 -0
  6. package/.next/standalone/.next/server/app/_global-error.html +1 -1
  7. package/.next/standalone/.next/server/app/_global-error.rsc +1 -1
  8. package/.next/standalone/.next/server/app/_global-error.segments/__PAGE__.segment.rsc +1 -1
  9. package/.next/standalone/.next/server/app/_global-error.segments/_full.segment.rsc +1 -1
  10. package/.next/standalone/.next/server/app/_global-error.segments/_tree.segment.rsc +1 -1
  11. package/.next/standalone/.next/server/app/_not-found/page.js +1 -1
  12. package/.next/standalone/.next/server/app/_not-found/page.js.nft.json +1 -1
  13. package/.next/standalone/.next/server/app/_not-found/page_client-reference-manifest.js +1 -1
  14. package/.next/standalone/.next/server/app/_not-found.html +1 -1
  15. package/.next/standalone/.next/server/app/_not-found.rsc +26 -18
  16. package/.next/standalone/.next/server/app/_not-found.segments/_full.segment.rsc +26 -18
  17. package/.next/standalone/.next/server/app/_not-found.segments/_not-found/__PAGE__.segment.rsc +25 -16
  18. package/.next/standalone/.next/server/app/_not-found.segments/_tree.segment.rsc +2 -2
  19. package/.next/standalone/.next/server/app/api/admin-delete/route.js +2 -2
  20. package/.next/standalone/.next/server/app/api/admin-delete/route.js.nft.json +1 -1
  21. package/.next/standalone/.next/server/app/api/admin-update/route.js +2 -2
  22. package/.next/standalone/.next/server/app/api/admin-update/route.js.nft.json +1 -1
  23. package/.next/standalone/.next/server/app/api/bridges/route.js +2 -2
  24. package/.next/standalone/.next/server/app/api/bridges/route.js.nft.json +1 -1
  25. package/.next/standalone/.next/server/app/api/bulk-import/route.js +2 -2
  26. package/.next/standalone/.next/server/app/api/bulk-import/route.js.nft.json +1 -1
  27. package/.next/standalone/.next/server/app/api/company-scores/legacy/route.js +3 -3
  28. package/.next/standalone/.next/server/app/api/company-scores/legacy/route.js.nft.json +1 -1
  29. package/.next/standalone/.next/server/app/api/company-scores/route.js +3 -3
  30. package/.next/standalone/.next/server/app/api/company-scores/route.js.nft.json +1 -1
  31. package/.next/standalone/.next/server/app/api/connections/route.js +2 -2
  32. package/.next/standalone/.next/server/app/api/connections/route.js.nft.json +1 -1
  33. package/.next/standalone/.next/server/app/api/data/backup/route/app-paths-manifest.json +3 -0
  34. package/.next/standalone/.next/server/app/api/data/backup/route/build-manifest.json +12 -0
  35. package/.next/standalone/.next/server/app/api/data/backup/route/server-reference-manifest.json +4 -0
  36. package/.next/standalone/.next/server/app/api/data/backup/route.js +7 -0
  37. package/.next/standalone/.next/server/app/api/data/backup/route.js.map +5 -0
  38. package/.next/standalone/.next/server/app/api/data/backup/route.js.nft.json +1 -0
  39. package/.next/standalone/.next/server/app/api/data/backup/route_client-reference-manifest.js +3 -0
  40. package/.next/standalone/.next/server/app/api/data/csv/route/app-paths-manifest.json +3 -0
  41. package/.next/standalone/.next/server/app/api/data/csv/route/build-manifest.json +12 -0
  42. package/.next/standalone/.next/server/app/api/data/csv/route/server-reference-manifest.json +4 -0
  43. package/.next/standalone/.next/server/app/api/data/csv/route.js +8 -0
  44. package/.next/standalone/.next/server/app/api/data/csv/route.js.map +5 -0
  45. package/.next/standalone/.next/server/app/api/data/csv/route.js.nft.json +1 -0
  46. package/.next/standalone/.next/server/app/api/data/csv/route_client-reference-manifest.js +3 -0
  47. package/.next/standalone/.next/server/app/api/data/export/route.js +1 -1
  48. package/.next/standalone/.next/server/app/api/data/export/route.js.nft.json +1 -1
  49. package/.next/standalone/.next/server/app/api/data/import/route.js +1 -1
  50. package/.next/standalone/.next/server/app/api/data/import/route.js.nft.json +1 -1
  51. package/.next/standalone/.next/server/app/api/data/restart/route.js +1 -1
  52. package/.next/standalone/.next/server/app/api/data/restart/route.js.nft.json +1 -1
  53. package/.next/standalone/.next/server/app/api/data/restore/route/app-paths-manifest.json +3 -0
  54. package/.next/standalone/.next/server/app/api/data/restore/route/build-manifest.json +12 -0
  55. package/.next/standalone/.next/server/app/api/data/restore/route/server-reference-manifest.json +4 -0
  56. package/.next/standalone/.next/server/app/api/data/restore/route.js +7 -0
  57. package/.next/standalone/.next/server/app/api/data/restore/route.js.map +5 -0
  58. package/.next/standalone/.next/server/app/api/data/restore/route.js.nft.json +1 -0
  59. package/.next/standalone/.next/server/app/api/data/restore/route_client-reference-manifest.js +3 -0
  60. package/.next/standalone/.next/server/app/api/data/reveal/route.js +1 -1
  61. package/.next/standalone/.next/server/app/api/data/reveal/route.js.nft.json +1 -1
  62. package/.next/standalone/.next/server/app/api/data/route.js +1 -1
  63. package/.next/standalone/.next/server/app/api/data/route.js.nft.json +1 -1
  64. package/.next/standalone/.next/server/app/api/delete-cluster/route.js +2 -2
  65. package/.next/standalone/.next/server/app/api/delete-cluster/route.js.nft.json +1 -1
  66. package/.next/standalone/.next/server/app/api/ingest/route.js +2 -2
  67. package/.next/standalone/.next/server/app/api/ingest/route.js.nft.json +1 -1
  68. package/.next/standalone/.next/server/app/api/network/route.js +2 -2
  69. package/.next/standalone/.next/server/app/api/network/route.js.nft.json +1 -1
  70. package/.next/standalone/.next/server/app/api/notifications/route.js +2 -2
  71. package/.next/standalone/.next/server/app/api/notifications/route.js.nft.json +1 -1
  72. package/.next/standalone/.next/server/app/api/outreach/route.js +3 -3
  73. package/.next/standalone/.next/server/app/api/outreach/route.js.nft.json +1 -1
  74. package/.next/standalone/.next/server/app/api/queue/route.js +2 -2
  75. package/.next/standalone/.next/server/app/api/queue/route.js.nft.json +1 -1
  76. package/.next/standalone/.next/server/app/api/scraper/route.js +5 -3
  77. package/.next/standalone/.next/server/app/api/scraper/route.js.nft.json +1 -1
  78. package/.next/standalone/.next/server/app/api/settings/route.js +3 -3
  79. package/.next/standalone/.next/server/app/api/settings/route.js.nft.json +1 -1
  80. package/.next/standalone/.next/server/app/api/settings/sector-preview/route.js +3 -3
  81. package/.next/standalone/.next/server/app/api/settings/sector-preview/route.js.nft.json +1 -1
  82. package/.next/standalone/.next/server/app/api/settings/sector-suggestions/route.js +3 -3
  83. package/.next/standalone/.next/server/app/api/settings/sector-suggestions/route.js.nft.json +1 -1
  84. package/.next/standalone/.next/server/app/api/setup-profile/route.js +2 -2
  85. package/.next/standalone/.next/server/app/api/setup-profile/route.js.nft.json +1 -1
  86. package/.next/standalone/.next/server/app/api/social/crm/route.js +1 -1
  87. package/.next/standalone/.next/server/app/api/social/crm/route.js.nft.json +1 -1
  88. package/.next/standalone/.next/server/app/api/social/messages/route.js +1 -1
  89. package/.next/standalone/.next/server/app/api/social/messages/route.js.nft.json +1 -1
  90. package/.next/standalone/.next/server/app/api/social/route.js +2 -2
  91. package/.next/standalone/.next/server/app/api/social/route.js.nft.json +1 -1
  92. package/.next/standalone/.next/server/app/api/unlock/route.js +2 -2
  93. package/.next/standalone/.next/server/app/api/unlock/route.js.nft.json +1 -1
  94. package/.next/standalone/.next/server/app/api/update/route.js.nft.json +1 -1
  95. package/.next/standalone/.next/server/app/api/update-images/route.js +2 -2
  96. package/.next/standalone/.next/server/app/api/update-images/route.js.nft.json +1 -1
  97. package/.next/standalone/.next/server/app/api/users/route.js +2 -2
  98. package/.next/standalone/.next/server/app/api/users/route.js.nft.json +1 -1
  99. package/.next/standalone/.next/server/app/avatars/[file]/route.js +1 -1
  100. package/.next/standalone/.next/server/app/avatars/[file]/route.js.nft.json +1 -1
  101. package/.next/standalone/.next/server/app/import/page.js +1 -1
  102. package/.next/standalone/.next/server/app/import/page.js.nft.json +1 -1
  103. package/.next/standalone/.next/server/app/import/page_client-reference-manifest.js +1 -1
  104. package/.next/standalone/.next/server/app/import.html +1 -1
  105. package/.next/standalone/.next/server/app/import.rsc +32 -24
  106. package/.next/standalone/.next/server/app/import.segments/_full.segment.rsc +32 -24
  107. package/.next/standalone/.next/server/app/import.segments/_tree.segment.rsc +2 -2
  108. package/.next/standalone/.next/server/app/import.segments/import/__PAGE__.segment.rsc +23 -18
  109. package/.next/standalone/.next/server/app/index.html +1 -1
  110. package/.next/standalone/.next/server/app/index.rsc +29 -22
  111. package/.next/standalone/.next/server/app/index.segments/__PAGE__.segment.rsc +20 -15
  112. package/.next/standalone/.next/server/app/index.segments/_full.segment.rsc +29 -22
  113. package/.next/standalone/.next/server/app/index.segments/_tree.segment.rsc +2 -2
  114. package/.next/standalone/.next/server/app/insights/page/app-paths-manifest.json +3 -0
  115. package/.next/standalone/.next/server/app/insights/page/build-manifest.json +20 -0
  116. package/.next/standalone/.next/server/app/insights/page/next-font-manifest.json +11 -0
  117. package/.next/standalone/.next/server/app/insights/page/react-loadable-manifest.json +1 -0
  118. package/.next/standalone/.next/server/app/insights/page/server-reference-manifest.json +4 -0
  119. package/.next/standalone/.next/server/app/insights/page.js +13 -0
  120. package/.next/standalone/.next/server/app/insights/page.js.map +5 -0
  121. package/.next/standalone/.next/server/app/insights/page.js.nft.json +1 -0
  122. package/.next/standalone/.next/server/app/insights/page_client-reference-manifest.js +3 -0
  123. package/.next/standalone/.next/server/app/insights.html +1 -0
  124. package/.next/standalone/.next/server/app/insights.meta +26 -0
  125. package/.next/standalone/.next/server/app/insights.rsc +35 -0
  126. package/.next/standalone/.next/server/app/insights.segments/_full.segment.rsc +35 -0
  127. package/.next/standalone/.next/server/app/insights.segments/_tree.segment.rsc +4 -0
  128. package/.next/standalone/.next/server/app/insights.segments/insights/__PAGE__.segment.rsc +33 -0
  129. package/.next/standalone/.next/server/app/launch/page.js +1 -1
  130. package/.next/standalone/.next/server/app/launch/page.js.nft.json +1 -1
  131. package/.next/standalone/.next/server/app/launch/page_client-reference-manifest.js +1 -1
  132. package/.next/standalone/.next/server/app/launch.html +2 -2
  133. package/.next/standalone/.next/server/app/launch.rsc +32 -24
  134. package/.next/standalone/.next/server/app/launch.segments/_full.segment.rsc +32 -24
  135. package/.next/standalone/.next/server/app/launch.segments/_tree.segment.rsc +2 -2
  136. package/.next/standalone/.next/server/app/launch.segments/launch/__PAGE__.segment.rsc +23 -18
  137. package/.next/standalone/.next/server/app/page.js +1 -1
  138. package/.next/standalone/.next/server/app/page.js.nft.json +1 -1
  139. package/.next/standalone/.next/server/app/page_client-reference-manifest.js +1 -1
  140. package/.next/standalone/.next/server/app/paths/page.js +1 -1
  141. package/.next/standalone/.next/server/app/paths/page.js.nft.json +1 -1
  142. package/.next/standalone/.next/server/app/paths/page_client-reference-manifest.js +1 -1
  143. package/.next/standalone/.next/server/app/paths.html +1 -1
  144. package/.next/standalone/.next/server/app/paths.rsc +32 -24
  145. package/.next/standalone/.next/server/app/paths.segments/_full.segment.rsc +32 -24
  146. package/.next/standalone/.next/server/app/paths.segments/_tree.segment.rsc +2 -2
  147. package/.next/standalone/.next/server/app/paths.segments/paths/__PAGE__.segment.rsc +21 -18
  148. package/.next/standalone/.next/server/app/profile/page.js +1 -1
  149. package/.next/standalone/.next/server/app/profile/page.js.nft.json +1 -1
  150. package/.next/standalone/.next/server/app/profile/page_client-reference-manifest.js +1 -1
  151. package/.next/standalone/.next/server/app/profile.html +1 -1
  152. package/.next/standalone/.next/server/app/profile.rsc +32 -24
  153. package/.next/standalone/.next/server/app/profile.segments/_full.segment.rsc +32 -24
  154. package/.next/standalone/.next/server/app/profile.segments/_tree.segment.rsc +2 -2
  155. package/.next/standalone/.next/server/app/profile.segments/profile/__PAGE__.segment.rsc +23 -18
  156. package/.next/standalone/.next/server/app/queue/page.js +1 -1
  157. package/.next/standalone/.next/server/app/queue/page.js.nft.json +1 -1
  158. package/.next/standalone/.next/server/app/queue/page_client-reference-manifest.js +1 -1
  159. package/.next/standalone/.next/server/app/queue.html +1 -1
  160. package/.next/standalone/.next/server/app/queue.rsc +32 -24
  161. package/.next/standalone/.next/server/app/queue.segments/_full.segment.rsc +32 -24
  162. package/.next/standalone/.next/server/app/queue.segments/_tree.segment.rsc +2 -2
  163. package/.next/standalone/.next/server/app/queue.segments/queue/__PAGE__.segment.rsc +21 -18
  164. package/.next/standalone/.next/server/app/scores/page.js +1 -1
  165. package/.next/standalone/.next/server/app/scores/page.js.nft.json +1 -1
  166. package/.next/standalone/.next/server/app/scores/page_client-reference-manifest.js +1 -1
  167. package/.next/standalone/.next/server/app/scores.html +1 -1
  168. package/.next/standalone/.next/server/app/scores.rsc +32 -24
  169. package/.next/standalone/.next/server/app/scores.segments/_full.segment.rsc +32 -24
  170. package/.next/standalone/.next/server/app/scores.segments/_tree.segment.rsc +2 -2
  171. package/.next/standalone/.next/server/app/scores.segments/scores/__PAGE__.segment.rsc +23 -18
  172. package/.next/standalone/.next/server/app/settings/page.js +1 -1
  173. package/.next/standalone/.next/server/app/settings/page.js.nft.json +1 -1
  174. package/.next/standalone/.next/server/app/settings/page_client-reference-manifest.js +1 -1
  175. package/.next/standalone/.next/server/app/settings.html +1 -1
  176. package/.next/standalone/.next/server/app/settings.rsc +32 -24
  177. package/.next/standalone/.next/server/app/settings.segments/_full.segment.rsc +32 -24
  178. package/.next/standalone/.next/server/app/settings.segments/_tree.segment.rsc +2 -2
  179. package/.next/standalone/.next/server/app/settings.segments/settings/__PAGE__.segment.rsc +20 -18
  180. package/.next/standalone/.next/server/app/setup/page.js +1 -1
  181. package/.next/standalone/.next/server/app/setup/page.js.nft.json +1 -1
  182. package/.next/standalone/.next/server/app/setup/page_client-reference-manifest.js +1 -1
  183. package/.next/standalone/.next/server/app/setup.html +1 -1
  184. package/.next/standalone/.next/server/app/setup.rsc +32 -24
  185. package/.next/standalone/.next/server/app/setup.segments/_full.segment.rsc +32 -24
  186. package/.next/standalone/.next/server/app/setup.segments/_tree.segment.rsc +2 -2
  187. package/.next/standalone/.next/server/app/setup.segments/setup/__PAGE__.segment.rsc +21 -18
  188. package/.next/standalone/.next/server/app/social/page.js +1 -1
  189. package/.next/standalone/.next/server/app/social/page.js.nft.json +1 -1
  190. package/.next/standalone/.next/server/app/social/page_client-reference-manifest.js +1 -1
  191. package/.next/standalone/.next/server/app/social.html +1 -1
  192. package/.next/standalone/.next/server/app/social.rsc +32 -24
  193. package/.next/standalone/.next/server/app/social.segments/_full.segment.rsc +32 -24
  194. package/.next/standalone/.next/server/app/social.segments/_tree.segment.rsc +2 -2
  195. package/.next/standalone/.next/server/app/social.segments/social/__PAGE__.segment.rsc +23 -18
  196. package/.next/standalone/.next/server/app-paths-manifest.json +4 -0
  197. package/.next/standalone/.next/server/chunks/[root-of-the-server]__00la_y0._.js +1 -1
  198. package/.next/standalone/.next/server/chunks/[root-of-the-server]__05_3-22._.js +1 -1
  199. package/.next/standalone/.next/server/chunks/[root-of-the-server]__066rab1._.js +7 -0
  200. package/.next/standalone/.next/server/chunks/[root-of-the-server]__07t47cm._.js +1 -1
  201. package/.next/standalone/.next/server/chunks/[root-of-the-server]__0cj5jqc._.js +1 -1
  202. package/.next/standalone/.next/server/chunks/[root-of-the-server]__0e0fei3._.js +1 -1
  203. package/.next/standalone/.next/server/chunks/[root-of-the-server]__0fooke1._.js +7 -0
  204. package/.next/standalone/.next/server/chunks/[root-of-the-server]__0ljnyho._.js +1 -1
  205. package/.next/standalone/.next/server/chunks/[root-of-the-server]__0o5-tcg._.js +1 -1
  206. package/.next/standalone/.next/server/chunks/[root-of-the-server]__0qrnous._.js +1 -1
  207. package/.next/standalone/.next/server/chunks/{[root-of-the-server]__15wc9e-._.js → [root-of-the-server]__0r-0t-9._.js} +2 -2
  208. package/.next/standalone/.next/server/chunks/[root-of-the-server]__0ra6xyg._.js +15 -0
  209. package/.next/standalone/.next/server/chunks/{[root-of-the-server]__20rwfdw._.js → [root-of-the-server]__0rcpjad._.js} +6 -3
  210. package/.next/standalone/.next/server/chunks/[root-of-the-server]__0t3v1a1._.js +1 -1
  211. package/.next/standalone/.next/server/chunks/[root-of-the-server]__0t6y79e._.js +7 -0
  212. package/.next/standalone/.next/server/chunks/[root-of-the-server]__0wmexuc._.js +1 -1
  213. package/.next/standalone/.next/server/chunks/[root-of-the-server]__0x29muh._.js +7 -0
  214. package/.next/standalone/.next/server/chunks/[root-of-the-server]__0xu34sz._.js +1 -1
  215. package/.next/standalone/.next/server/chunks/[root-of-the-server]__133knx1._.js +1 -1
  216. package/.next/standalone/.next/server/chunks/[root-of-the-server]__15-17hl._.js +1 -1
  217. package/.next/standalone/.next/server/chunks/[root-of-the-server]__19b7mig._.js +1 -1
  218. package/.next/standalone/.next/server/chunks/[root-of-the-server]__1a_6x37._.js +8 -0
  219. package/.next/standalone/.next/server/chunks/[root-of-the-server]__1an_8pa._.js +7 -0
  220. package/.next/standalone/.next/server/chunks/[root-of-the-server]__1bbcwub._.js +1 -1
  221. package/.next/standalone/.next/server/chunks/[root-of-the-server]__1ducpz2._.js +3 -0
  222. package/.next/standalone/.next/server/chunks/[root-of-the-server]__1eris29._.js +1 -1
  223. package/.next/standalone/.next/server/chunks/[root-of-the-server]__1gjo_cq._.js +1 -1
  224. package/.next/standalone/.next/server/chunks/[root-of-the-server]__1qcm08_._.js +1 -1
  225. package/.next/standalone/.next/server/chunks/[root-of-the-server]__1tir0vc._.js +1 -1
  226. package/.next/standalone/.next/server/chunks/[root-of-the-server]__1w25q0m._.js +1 -1
  227. package/.next/standalone/.next/server/chunks/[root-of-the-server]__1xhyinn._.js +3 -0
  228. package/.next/standalone/.next/server/chunks/_072jl0y._.js +1 -1
  229. package/.next/standalone/.next/server/chunks/_0lw8_i0._.js +1 -1
  230. package/.next/standalone/.next/server/chunks/_0sqqpzb._.js +3 -0
  231. package/.next/standalone/.next/server/chunks/_1_fynia._.js +7 -7
  232. package/.next/standalone/.next/server/chunks/_1fn30_l._.js +1 -1
  233. package/.next/standalone/.next/server/chunks/_1itd1o_._.js +1 -1
  234. package/.next/standalone/.next/server/chunks/_1iwkh8t._.js +1 -1
  235. package/.next/standalone/.next/server/chunks/_next-internal_server_app_api_data_backup_route_actions_0zoj04p.js +3 -0
  236. package/.next/standalone/.next/server/chunks/_next-internal_server_app_api_data_csv_route_actions_0l6m7lg.js +3 -0
  237. package/.next/standalone/.next/server/chunks/_next-internal_server_app_api_data_restore_route_actions_0-b05bv.js +3 -0
  238. package/.next/standalone/.next/server/chunks/lib_02iz_9q._.js +4 -0
  239. package/.next/standalone/.next/server/chunks/lib_05agvk3._.js +4 -0
  240. package/.next/standalone/.next/server/chunks/lib_0v84u66._.js +4 -0
  241. package/.next/standalone/.next/server/chunks/lib_db-client_0_dch35.js +174 -0
  242. package/.next/standalone/.next/server/chunks/lib_linkedin-export_12imqxg.js +1 -1
  243. package/.next/standalone/.next/server/chunks/lib_rpc_00nndai.js +3 -0
  244. package/.next/standalone/.next/server/chunks/lib_rpc_03ibb-x.js +3 -0
  245. package/.next/standalone/.next/server/chunks/lib_rpc_03ri3ji.js +3 -0
  246. package/.next/standalone/.next/server/chunks/lib_rpc_078ce48.js +3 -0
  247. package/.next/standalone/.next/server/chunks/lib_rpc_0a69mgr.js +3 -0
  248. package/.next/standalone/.next/server/chunks/lib_rpc_0c9d9ti.js +7 -0
  249. package/.next/standalone/.next/server/chunks/lib_rpc_0cej3t8.js +3 -0
  250. package/.next/standalone/.next/server/chunks/lib_rpc_0cmh4g6.js +3 -0
  251. package/.next/standalone/.next/server/chunks/lib_rpc_0nx2_pc.js +3 -0
  252. package/.next/standalone/.next/server/chunks/lib_rpc_0r79-w1.js +3 -0
  253. package/.next/standalone/.next/server/chunks/lib_rpc_0t552z6.js +3 -0
  254. package/.next/standalone/.next/server/chunks/lib_rpc_0yx8ynd.js +3 -0
  255. package/.next/standalone/.next/server/chunks/lib_rpc_12p-o9-.js +3 -0
  256. package/.next/standalone/.next/server/chunks/lib_rpc_1466dnb.js +3 -0
  257. package/.next/standalone/.next/server/chunks/lib_rpc_1sryxv6.js +3 -0
  258. package/.next/standalone/.next/server/chunks/lib_rpc_1trn-x5.js +3 -0
  259. package/.next/standalone/.next/server/chunks/lib_rpc_1ygu_mv.js +3 -0
  260. package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__0egamyq._.js +3 -0
  261. package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__0qd8pzm._.js +3 -0
  262. package/.next/standalone/.next/server/chunks/ssr/{[root-of-the-server]__0qdeuyo._.js → [root-of-the-server]__1-012q1._.js} +2 -2
  263. package/.next/standalone/.next/server/chunks/ssr/_04am_h8._.js +3 -0
  264. package/.next/standalone/.next/server/chunks/ssr/_06rgzfh._.js +3 -0
  265. package/.next/standalone/.next/server/chunks/ssr/_07zb7lu._.js +3 -0
  266. package/.next/standalone/.next/server/chunks/ssr/_0_79idq._.js +3 -0
  267. package/.next/standalone/.next/server/chunks/ssr/_0gds903._.js +3 -0
  268. package/.next/standalone/.next/server/chunks/ssr/_0hb-dhy._.js +3 -0
  269. package/.next/standalone/.next/server/chunks/ssr/_0klqt9z._.js +3 -0
  270. package/.next/standalone/.next/server/chunks/ssr/_14jak5s._.js +7 -0
  271. package/.next/standalone/.next/server/chunks/ssr/_14nxd3q._.js +3 -0
  272. package/.next/standalone/.next/server/chunks/ssr/_1cj2yog._.js +3 -0
  273. package/.next/standalone/.next/server/chunks/ssr/_1fm1ih_._.js +2 -2
  274. package/.next/standalone/.next/server/chunks/ssr/_1hdqw0-._.js +7 -0
  275. package/.next/standalone/.next/server/chunks/ssr/_1k2nmbw._.js +2 -2
  276. package/.next/standalone/.next/server/chunks/ssr/_1r62six._.js +7 -0
  277. package/.next/standalone/.next/server/chunks/ssr/_next-internal_server_app_insights_page_actions_0-0tf75.js +3 -0
  278. package/.next/standalone/.next/server/chunks/ssr/app_141w189._.js +1 -1
  279. package/.next/standalone/.next/server/chunks/ssr/app_components_0uuff77._.js +25 -2
  280. package/.next/standalone/.next/server/chunks/ssr/app_components_1j3q-h5._.js +25 -2
  281. package/.next/standalone/.next/server/chunks/ssr/app_components_CompanyScores_1g0mytz.js +1 -1
  282. package/.next/standalone/.next/server/chunks/ssr/app_components_settings_SectorPicker_1c-29qw.js +1 -1
  283. package/.next/standalone/.next/server/chunks/ssr/app_components_ui_0pdmz2z.js +3 -0
  284. package/.next/standalone/.next/server/chunks/ssr/app_import_page_1fmu6_l.js +1 -1
  285. package/.next/standalone/.next/server/chunks/ssr/app_insights_page_1d_chja.js +3 -0
  286. package/.next/standalone/.next/server/chunks/ssr/app_launch_page_19t0dyd.js +1 -1
  287. package/.next/standalone/.next/server/chunks/ssr/app_page_1fazqbf.js +26 -14
  288. package/.next/standalone/.next/server/chunks/ssr/app_paths_page_1ol90m7.js +2 -2
  289. package/.next/standalone/.next/server/chunks/ssr/app_profile_page_0u3-l5y.js +1 -1
  290. package/.next/standalone/.next/server/chunks/ssr/app_queue_page_0c6znd6.js +11 -11
  291. package/.next/standalone/.next/server/chunks/ssr/app_settings_page_1f8mjj_.js +1 -1
  292. package/.next/standalone/.next/server/chunks/ssr/app_setup_page_1-282zx.js +12 -13
  293. package/.next/standalone/.next/server/chunks/ssr/app_social_page_0h7zxda.js +1 -1
  294. package/.next/standalone/.next/server/chunks/ssr/{lib_1c4ieuw._.js → lib_csv_1ttiu_h.js} +2 -2
  295. package/.next/standalone/.next/server/chunks/ssr/lib_galaxy-lab_108_lu-.js +1 -1
  296. package/.next/standalone/.next/server/chunks/ssr/lib_separation_1305zsx.js +3 -0
  297. package/.next/standalone/.next/server/edge/chunks/[root-of-the-server]__0pco7a6._.js +1 -1
  298. package/.next/standalone/.next/server/middleware-build-manifest.js +3 -3
  299. package/.next/standalone/.next/server/middleware-manifest.json +5 -5
  300. package/.next/standalone/.next/server/next-font-manifest.js +1 -1
  301. package/.next/standalone/.next/server/next-font-manifest.json +4 -0
  302. package/.next/standalone/.next/server/pages/404.html +1 -1
  303. package/.next/standalone/.next/server/pages/500.html +1 -1
  304. package/.next/standalone/.next/server/prefetch-hints.json +14 -0
  305. package/.next/standalone/.next/server/server-reference-manifest.js +1 -1
  306. package/.next/standalone/.next/server/server-reference-manifest.json +1 -1
  307. package/.next/standalone/.next/static/chunks/02wnf8dkxegxg.js +34 -0
  308. package/.next/standalone/.next/static/chunks/03-_esd2x_yk6.js +1 -0
  309. package/.next/standalone/.next/static/chunks/03-demj2iy-0p.js +44 -0
  310. package/.next/standalone/.next/static/chunks/0838_s6w-i_ik.js +1 -0
  311. package/.next/standalone/.next/static/chunks/0_1r-3csplxnj.js +1 -0
  312. package/.next/standalone/.next/static/chunks/0ka4prpk3w9wn.js +34 -0
  313. package/.next/standalone/.next/static/chunks/0kscsqnvfq3-r.js +1 -0
  314. package/.next/standalone/.next/static/chunks/0s_xxwp7z88vv.js +1 -0
  315. package/.next/standalone/.next/static/chunks/1-nnl8amfm4yh.js +57 -0
  316. package/.next/standalone/.next/static/chunks/112mv-com-mqa.js +21 -0
  317. package/.next/standalone/.next/static/chunks/1bkt_hhjzvbh8.js +1 -0
  318. package/.next/standalone/.next/static/chunks/1cmphb3kh2ers.css +3 -0
  319. package/.next/standalone/.next/static/chunks/1d8yv3k_atka7.js +1 -0
  320. package/.next/standalone/.next/static/chunks/{0ws7zy0w57ufi.js → 1eyajb9ntzlrl.js} +1 -1
  321. package/.next/standalone/.next/static/chunks/1z9lb-dbcg4aa.js +1 -0
  322. package/.next/standalone/.next/static/chunks/23hc51oa4vkhc.js +5 -0
  323. package/.next/standalone/.next/static/chunks/27n8k9wxlz5-7.js +1 -0
  324. package/.next/standalone/.next/static/chunks/2q9i7pcxcnph1.js +7 -0
  325. package/.next/standalone/.next/static/chunks/2w-y83mjlpnse.js +1 -0
  326. package/.next/standalone/.next/static/chunks/2ws1xf293j-tm.js +5 -0
  327. package/.next/standalone/.next/static/chunks/2z1-q0_vunbql.js +2 -0
  328. package/.next/standalone/.next/static/chunks/34g73qhayuevu.js +1 -0
  329. package/.next/standalone/.next/static/chunks/3cqn-r-y5rrw1.js +5 -0
  330. package/.next/standalone/.next/static/chunks/3opgg1efrx8q6.js +1 -0
  331. package/.next/standalone/.next/static/chunks/3p51fpxxi4d5y.js +34 -0
  332. package/.next/standalone/.next/static/chunks/3y40z6of3r9py.js +1 -0
  333. package/.next/standalone/.next/static/chunks/403dpflln8ah5.js +1 -0
  334. package/.next/standalone/.next/static/chunks/43pg2sursiypz.js +1 -0
  335. package/.next/standalone/CHANGELOG.md +203 -0
  336. package/.next/standalone/README.md +96 -50
  337. package/.next/standalone/SECURITY.md +25 -11
  338. package/.next/standalone/app/api/data/backup/route.js +25 -0
  339. package/.next/standalone/app/api/data/csv/route.js +74 -0
  340. package/.next/standalone/app/api/data/export/route.js +1 -1
  341. package/.next/standalone/app/api/data/restore/route.js +48 -0
  342. package/.next/standalone/app/api/data/reveal/route.js +19 -6
  343. package/.next/standalone/app/api/data/route.js +15 -4
  344. package/.next/standalone/app/api/ingest/route.js +1 -1
  345. package/.next/standalone/app/api/outreach/route.js +13 -73
  346. package/.next/standalone/app/api/queue/route.js +1 -1
  347. package/.next/standalone/app/api/scraper/route.js +217 -36
  348. package/.next/standalone/app/api/social/crm/route.js +2 -1
  349. package/.next/standalone/app/components/AppHeader.js +41 -21
  350. package/.next/standalone/app/components/AppTabs.js +12 -8
  351. package/.next/standalone/app/components/AutoConnect.js +286 -0
  352. package/.next/standalone/app/components/AutoScanButton.js +2 -2
  353. package/.next/standalone/app/components/Avatar.js +1 -1
  354. package/.next/standalone/app/components/ChainView.js +258 -113
  355. package/.next/standalone/app/components/CirclePanel.js +16 -16
  356. package/.next/standalone/app/components/ClusterSpinner.js +64 -0
  357. package/.next/standalone/app/components/CompanyScores.js +20 -20
  358. package/.next/standalone/app/components/EmptyState.js +39 -18
  359. package/.next/standalone/app/components/FieldStep.js +15 -13
  360. package/.next/standalone/app/components/FilterPanel.js +25 -18
  361. package/.next/standalone/app/components/ForceGraph.js +49 -14
  362. package/.next/standalone/app/components/GalaxyLab.js +33 -33
  363. package/.next/standalone/app/components/GridView.js +18 -18
  364. package/.next/standalone/app/components/LegacyScoresCard.js +10 -11
  365. package/.next/standalone/app/components/LinkedInLimits.js +57 -27
  366. package/.next/standalone/app/components/LiquidGlass.js +99 -0
  367. package/.next/standalone/app/components/ListView.js +20 -20
  368. package/.next/standalone/app/components/MapControls.js +5 -5
  369. package/.next/standalone/app/components/MappingProgress.js +16 -16
  370. package/.next/standalone/app/components/NoteDetail.js +13 -13
  371. package/.next/standalone/app/components/OnboardingGate.js +4 -4
  372. package/.next/standalone/app/components/OutlinkQuest.js +56 -35
  373. package/.next/standalone/app/components/PathsAnalyzer.js +37 -36
  374. package/.next/standalone/app/components/PeopleMap.js +21 -21
  375. package/.next/standalone/app/components/RingsView.js +11 -11
  376. package/.next/standalone/app/components/ScanRadar.js +84 -39
  377. package/.next/standalone/app/components/ScanStatusBar.js +40 -21
  378. package/.next/standalone/app/components/ScanTrail.js +21 -8
  379. package/.next/standalone/app/components/SeparationView.js +172 -124
  380. package/.next/standalone/app/components/Sidebar.js +308 -199
  381. package/.next/standalone/app/components/StaleServerBanner.js +4 -4
  382. package/.next/standalone/app/components/TheirCircle.js +26 -26
  383. package/.next/standalone/app/components/ThemeDefs.js +42 -0
  384. package/.next/standalone/app/components/ThemeLoader.js +20 -1
  385. package/.next/standalone/app/components/UpdatePanel.js +22 -22
  386. package/.next/standalone/app/components/UserProvider.js +22 -15
  387. package/.next/standalone/app/components/insights/Boards.js +275 -0
  388. package/.next/standalone/app/components/insights/PeopleView.js +266 -0
  389. package/.next/standalone/app/components/insights/Rail.js +156 -0
  390. package/.next/standalone/app/components/insights/Report.js +382 -0
  391. package/.next/standalone/app/components/insights/parts.js +239 -0
  392. package/.next/standalone/app/components/settings/AppearanceSection.js +47 -24
  393. package/.next/standalone/app/components/settings/DataSection.js +276 -109
  394. package/.next/standalone/app/components/settings/NetworkHealthSection.js +13 -13
  395. package/.next/standalone/app/components/settings/SectorPicker.js +12 -12
  396. package/.next/standalone/app/components/settings/SectorSection.js +13 -14
  397. package/.next/standalone/app/components/settings/TierSection.js +9 -9
  398. package/.next/standalone/app/components/settings/TitleSection.js +11 -11
  399. package/.next/standalone/app/components/settings/UsageSection.js +360 -0
  400. package/.next/standalone/app/components/ui.js +8 -8
  401. package/.next/standalone/app/globals.css +161 -5
  402. package/.next/standalone/app/import/page.js +94 -38
  403. package/.next/standalone/app/insights/page.js +220 -0
  404. package/.next/standalone/app/launch/page.js +5 -5
  405. package/.next/standalone/app/layout.js +6 -2
  406. package/.next/standalone/app/page.js +53 -53
  407. package/.next/standalone/app/paths/page.js +63 -63
  408. package/.next/standalone/app/profile/page.js +58 -58
  409. package/.next/standalone/app/queue/page.js +84 -72
  410. package/.next/standalone/app/scores/page.js +2 -2
  411. package/.next/standalone/app/settings/page.js +16 -13
  412. package/.next/standalone/app/setup/page.js +236 -133
  413. package/.next/standalone/app/social/Crm.js +63 -62
  414. package/.next/standalone/app/social/SocialHub.js +22 -22
  415. package/.next/standalone/app/social/Thread.js +7 -7
  416. package/.next/standalone/app/social/page.js +2 -2
  417. package/.next/standalone/lib/auto-connect.js +145 -0
  418. package/.next/standalone/lib/backups.js +458 -0
  419. package/.next/standalone/lib/chain-layout.js +32 -0
  420. package/.next/standalone/lib/companies.js +1 -1
  421. package/.next/standalone/lib/csv-store.js +131 -0
  422. package/.next/standalone/lib/csv.js +137 -39
  423. package/.next/standalone/lib/data-folder.js +19 -3
  424. package/.next/standalone/lib/data-import.js +5 -2
  425. package/.next/standalone/lib/db-client.js +78 -20
  426. package/.next/standalone/lib/demo.js +5 -4
  427. package/.next/standalone/lib/galaxy-export.js +9 -2
  428. package/.next/standalone/lib/galaxy-lab.js +19 -5
  429. package/.next/standalone/lib/galaxy-layouts.js +43 -0
  430. package/.next/standalone/lib/gate.js +10 -4
  431. package/.next/standalone/lib/in-progress.js +46 -0
  432. package/.next/standalone/lib/ingest.js +1 -1
  433. package/.next/standalone/lib/insights-board.js +613 -0
  434. package/.next/standalone/lib/linkedin-limits.js +240 -14
  435. package/.next/standalone/lib/liquid-glass.js +59 -0
  436. package/.next/standalone/lib/notifications.js +13 -0
  437. package/.next/standalone/lib/requests-client.js +10 -0
  438. package/.next/standalone/lib/requests.js +124 -0
  439. package/.next/standalone/lib/scan-pace.js +11 -0
  440. package/.next/standalone/lib/scan-progress.js +20 -0
  441. package/.next/standalone/lib/scan-risk.js +44 -0
  442. package/.next/standalone/lib/scan-state.js +1 -0
  443. package/.next/standalone/lib/scanner-setup.js +97 -15
  444. package/.next/standalone/lib/scraper-client.js +35 -8
  445. package/.next/standalone/lib/search-risk.js +7 -3
  446. package/.next/standalone/lib/settings-client.js +5 -3
  447. package/.next/standalone/lib/settings.js +13 -0
  448. package/.next/standalone/lib/social-store.js +3 -2
  449. package/.next/standalone/lib/synced-setting.js +46 -0
  450. package/.next/standalone/lib/theme-store.js +42 -10
  451. package/.next/standalone/lib/themes.js +111 -21
  452. package/.next/standalone/lib/usage.js +200 -0
  453. package/.next/standalone/package-lock.json +2 -2
  454. package/.next/standalone/package.json +1 -1
  455. package/.next/standalone/scripts/scrape.py +595 -11
  456. package/.next/static/chunks/02wnf8dkxegxg.js +34 -0
  457. package/.next/static/chunks/03-_esd2x_yk6.js +1 -0
  458. package/.next/static/chunks/03-demj2iy-0p.js +44 -0
  459. package/.next/static/chunks/0838_s6w-i_ik.js +1 -0
  460. package/.next/static/chunks/0_1r-3csplxnj.js +1 -0
  461. package/.next/static/chunks/0ka4prpk3w9wn.js +34 -0
  462. package/.next/static/chunks/0kscsqnvfq3-r.js +1 -0
  463. package/.next/static/chunks/0s_xxwp7z88vv.js +1 -0
  464. package/.next/static/chunks/1-nnl8amfm4yh.js +57 -0
  465. package/.next/static/chunks/112mv-com-mqa.js +21 -0
  466. package/.next/static/chunks/1bkt_hhjzvbh8.js +1 -0
  467. package/.next/static/chunks/1cmphb3kh2ers.css +3 -0
  468. package/.next/static/chunks/1d8yv3k_atka7.js +1 -0
  469. package/.next/static/chunks/{0ws7zy0w57ufi.js → 1eyajb9ntzlrl.js} +1 -1
  470. package/.next/static/chunks/1z9lb-dbcg4aa.js +1 -0
  471. package/.next/static/chunks/23hc51oa4vkhc.js +5 -0
  472. package/.next/static/chunks/27n8k9wxlz5-7.js +1 -0
  473. package/.next/static/chunks/2q9i7pcxcnph1.js +7 -0
  474. package/.next/static/chunks/2w-y83mjlpnse.js +1 -0
  475. package/.next/static/chunks/2ws1xf293j-tm.js +5 -0
  476. package/.next/static/chunks/2z1-q0_vunbql.js +2 -0
  477. package/.next/static/chunks/34g73qhayuevu.js +1 -0
  478. package/.next/static/chunks/3cqn-r-y5rrw1.js +5 -0
  479. package/.next/static/chunks/3opgg1efrx8q6.js +1 -0
  480. package/.next/static/chunks/3p51fpxxi4d5y.js +34 -0
  481. package/.next/static/chunks/3y40z6of3r9py.js +1 -0
  482. package/.next/static/chunks/403dpflln8ah5.js +1 -0
  483. package/.next/static/chunks/43pg2sursiypz.js +1 -0
  484. package/CHANGELOG.md +203 -0
  485. package/README.md +96 -50
  486. package/SECURITY.md +25 -11
  487. package/lib/auto-connect.js +145 -0
  488. package/lib/backups.js +458 -0
  489. package/lib/chain-layout.js +32 -0
  490. package/lib/companies.js +1 -1
  491. package/lib/csv-store.js +131 -0
  492. package/lib/csv.js +137 -39
  493. package/lib/data-folder.js +19 -3
  494. package/lib/data-import.js +5 -2
  495. package/lib/db-client.js +78 -20
  496. package/lib/demo.js +5 -4
  497. package/lib/galaxy-export.js +9 -2
  498. package/lib/galaxy-lab.js +19 -5
  499. package/lib/galaxy-layouts.js +43 -0
  500. package/lib/gate.js +10 -4
  501. package/lib/in-progress.js +46 -0
  502. package/lib/ingest.js +1 -1
  503. package/lib/insights-board.js +613 -0
  504. package/lib/linkedin-limits.js +240 -14
  505. package/lib/liquid-glass.js +59 -0
  506. package/lib/notifications.js +13 -0
  507. package/lib/requests-client.js +10 -0
  508. package/lib/requests.js +124 -0
  509. package/lib/scan-pace.js +11 -0
  510. package/lib/scan-progress.js +20 -0
  511. package/lib/scan-risk.js +44 -0
  512. package/lib/scan-state.js +1 -0
  513. package/lib/scanner-setup.js +97 -15
  514. package/lib/scraper-client.js +35 -8
  515. package/lib/search-risk.js +7 -3
  516. package/lib/settings-client.js +5 -3
  517. package/lib/settings.js +13 -0
  518. package/lib/social-store.js +3 -2
  519. package/lib/synced-setting.js +46 -0
  520. package/lib/theme-store.js +42 -10
  521. package/lib/themes.js +111 -21
  522. package/lib/usage.js +200 -0
  523. package/package.json +1 -1
  524. package/scripts/scrape.py +595 -11
  525. package/.next/standalone/.next/server/chunks/[root-of-the-server]__0-rnla2._.js +0 -3
  526. package/.next/standalone/.next/server/chunks/[root-of-the-server]__13dx4sd._.js +0 -8
  527. package/.next/standalone/.next/server/chunks/[root-of-the-server]__14ou7j5._.js +0 -3
  528. package/.next/standalone/.next/server/chunks/[root-of-the-server]__16iu0hv._.js +0 -3
  529. package/.next/standalone/.next/server/chunks/[root-of-the-server]__1kbl21f._.js +0 -3
  530. package/.next/standalone/.next/server/chunks/[root-of-the-server]__1rphsdk._.js +0 -3
  531. package/.next/standalone/.next/server/chunks/_02twlca._.js +0 -10
  532. package/.next/standalone/.next/server/chunks/lib_0851sk0._.js +0 -8
  533. package/.next/standalone/.next/server/chunks/lib_1q7p2ro._.js +0 -8
  534. package/.next/standalone/.next/server/chunks/lib_1r6l86l._.js +0 -8
  535. package/.next/standalone/.next/server/chunks/lib_db-client_15le7cw.js +0 -174
  536. package/.next/standalone/.next/server/chunks/lib_rpc_04s8mzr.js +0 -3
  537. package/.next/standalone/.next/server/chunks/lib_rpc_053z7as.js +0 -3
  538. package/.next/standalone/.next/server/chunks/lib_rpc_0b_-2te.js +0 -3
  539. package/.next/standalone/.next/server/chunks/lib_rpc_0dhbxdm.js +0 -3
  540. package/.next/standalone/.next/server/chunks/lib_rpc_0dxlk31.js +0 -3
  541. package/.next/standalone/.next/server/chunks/lib_rpc_0f8b-qc.js +0 -3
  542. package/.next/standalone/.next/server/chunks/lib_rpc_0pzie7_.js +0 -3
  543. package/.next/standalone/.next/server/chunks/lib_rpc_0r76fq_.js +0 -3
  544. package/.next/standalone/.next/server/chunks/lib_rpc_0ut7pjp.js +0 -3
  545. package/.next/standalone/.next/server/chunks/lib_rpc_15zyqaz.js +0 -3
  546. package/.next/standalone/.next/server/chunks/lib_rpc_18zpjtq.js +0 -3
  547. package/.next/standalone/.next/server/chunks/lib_rpc_1a8xkiz.js +0 -3
  548. package/.next/standalone/.next/server/chunks/lib_rpc_1e_55xo.js +0 -3
  549. package/.next/standalone/.next/server/chunks/lib_rpc_1oxfd1_.js +0 -3
  550. package/.next/standalone/.next/server/chunks/lib_rpc_1s0lod0.js +0 -3
  551. package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__08oxiqh._.js +0 -3
  552. package/.next/standalone/.next/server/chunks/ssr/_03l7vge._.js +0 -3
  553. package/.next/standalone/.next/server/chunks/ssr/_08g31gm._.js +0 -3
  554. package/.next/standalone/.next/server/chunks/ssr/_0gk_ofx._.js +0 -3
  555. package/.next/standalone/.next/server/chunks/ssr/_0nwsf93._.js +0 -3
  556. package/.next/standalone/.next/server/chunks/ssr/_0vho1lb._.js +0 -3
  557. package/.next/standalone/.next/server/chunks/ssr/_1-658fq._.js +0 -3
  558. package/.next/standalone/.next/server/chunks/ssr/_1bc46kz._.js +0 -3
  559. package/.next/standalone/.next/server/chunks/ssr/_1f_n00p._.js +0 -3
  560. package/.next/standalone/.next/server/chunks/ssr/_2105jz8._.js +0 -3
  561. package/.next/standalone/.next/server/chunks/ssr/app_components_0t908t-._.js +0 -3
  562. package/.next/standalone/.next/static/chunks/02pq76u7y4v9-.js +0 -22
  563. package/.next/standalone/.next/static/chunks/0cmq0exd4d0h9.js +0 -1
  564. package/.next/standalone/.next/static/chunks/0i02yxppzds1o.js +0 -1
  565. package/.next/standalone/.next/static/chunks/0m_p4k-q2qh--.js +0 -1
  566. package/.next/standalone/.next/static/chunks/0oyslj62jkubd.js +0 -1
  567. package/.next/standalone/.next/static/chunks/0vo-l8hxneba6.css +0 -3
  568. package/.next/standalone/.next/static/chunks/0yh8z2tbrc5i_.js +0 -1
  569. package/.next/standalone/.next/static/chunks/17-rhp8sg4m1b.js +0 -44
  570. package/.next/standalone/.next/static/chunks/172e10mi-tpo_.js +0 -34
  571. package/.next/standalone/.next/static/chunks/1ei5vbe2uw6fl.js +0 -1
  572. package/.next/standalone/.next/static/chunks/1f7_pl_wq7lh3.js +0 -11
  573. package/.next/standalone/.next/static/chunks/1jzbe7zdx9vbj.js +0 -2
  574. package/.next/standalone/.next/static/chunks/1m3017gp790pw.js +0 -45
  575. package/.next/standalone/.next/static/chunks/1t20e8u0st7ep.js +0 -1
  576. package/.next/standalone/.next/static/chunks/2-ch9rm27eril.js +0 -11
  577. package/.next/standalone/.next/static/chunks/2ldv-v3s9yaif.js +0 -1
  578. package/.next/standalone/.next/static/chunks/3bp284gjf7dyq.js +0 -1
  579. package/.next/standalone/.next/static/chunks/3k1f6clbn3gj3.js +0 -7
  580. package/.next/standalone/.next/static/chunks/3l4t8je6iguzc.js +0 -1
  581. package/.next/standalone/.next/static/chunks/3tplzuc9jk-tl.js +0 -1
  582. package/.next/standalone/.next/static/chunks/42m0bqr8pbovz.js +0 -11
  583. package/.next/static/chunks/02pq76u7y4v9-.js +0 -22
  584. package/.next/static/chunks/0cmq0exd4d0h9.js +0 -1
  585. package/.next/static/chunks/0i02yxppzds1o.js +0 -1
  586. package/.next/static/chunks/0m_p4k-q2qh--.js +0 -1
  587. package/.next/static/chunks/0oyslj62jkubd.js +0 -1
  588. package/.next/static/chunks/0vo-l8hxneba6.css +0 -3
  589. package/.next/static/chunks/0yh8z2tbrc5i_.js +0 -1
  590. package/.next/static/chunks/17-rhp8sg4m1b.js +0 -44
  591. package/.next/static/chunks/172e10mi-tpo_.js +0 -34
  592. package/.next/static/chunks/1ei5vbe2uw6fl.js +0 -1
  593. package/.next/static/chunks/1f7_pl_wq7lh3.js +0 -11
  594. package/.next/static/chunks/1jzbe7zdx9vbj.js +0 -2
  595. package/.next/static/chunks/1m3017gp790pw.js +0 -45
  596. package/.next/static/chunks/1t20e8u0st7ep.js +0 -1
  597. package/.next/static/chunks/2-ch9rm27eril.js +0 -11
  598. package/.next/static/chunks/2ldv-v3s9yaif.js +0 -1
  599. package/.next/static/chunks/3bp284gjf7dyq.js +0 -1
  600. package/.next/static/chunks/3k1f6clbn3gj3.js +0 -7
  601. package/.next/static/chunks/3l4t8je6iguzc.js +0 -1
  602. package/.next/static/chunks/3tplzuc9jk-tl.js +0 -1
  603. package/.next/static/chunks/42m0bqr8pbovz.js +0 -11
  604. /package/.next/standalone/.next/static/{dQUvvVSXqbkEFC3-CNcwT → 3NCyJyAPDCEYsYTwF1Ieu}/_buildManifest.js +0 -0
  605. /package/.next/standalone/.next/static/{dQUvvVSXqbkEFC3-CNcwT → 3NCyJyAPDCEYsYTwF1Ieu}/_clientMiddlewareManifest.js +0 -0
  606. /package/.next/standalone/.next/static/{dQUvvVSXqbkEFC3-CNcwT → 3NCyJyAPDCEYsYTwF1Ieu}/_ssgManifest.js +0 -0
  607. /package/.next/static/{dQUvvVSXqbkEFC3-CNcwT → 3NCyJyAPDCEYsYTwF1Ieu}/_buildManifest.js +0 -0
  608. /package/.next/static/{dQUvvVSXqbkEFC3-CNcwT → 3NCyJyAPDCEYsYTwF1Ieu}/_clientMiddlewareManifest.js +0 -0
  609. /package/.next/static/{dQUvvVSXqbkEFC3-CNcwT → 3NCyJyAPDCEYsYTwF1Ieu}/_ssgManifest.js +0 -0
@@ -0,0 +1,131 @@
1
+ // A LinkedIn Connections.csv import, kept in the data folder (csv-network.json)
2
+ // so it is still there after the window closes and after the app restarts.
3
+ //
4
+ // Kept beside the database, never merged into it. The 1.0 list (2026-10-03)
5
+ // chose this over adding the rows to linkedin_connections as 1st degree:
6
+ // merging means matching CSV people to rows the scanner wrote by profile link,
7
+ // under a profile the CSV knows nothing about, and that is how people were
8
+ // duplicated, hidden and deleted before (TRAPS §19, §25, §36). Here the map
9
+ // reads the file instead of the database while it's open, as it always did
10
+ // from the window, and deleting the file is the whole of removing it.
11
+ //
12
+ // Only what the export says about each person is kept, packed as lib/csv.js
13
+ // packConnections makes it: id, name, position, company, profile link and the
14
+ // date you connected. Scores and tiers are worked out again on every load, so
15
+ // they follow the scoring model. The Email Address column is never read, so it
16
+ // can't be here.
17
+ //
18
+ // The file is read as untrusted: an import from another computer brings one
19
+ // (lib/data-folder.js NETWORK_FILES), and a hand edit or a bad disk can change
20
+ // it. A file that doesn't hold what this writes is never shown as a network;
21
+ // the page says it couldn't be read instead (TRAPS §7).
22
+
23
+ import { readFileSync, lstatSync, rmSync } from 'node:fs';
24
+ import path from 'node:path';
25
+ import { durable } from './durable.js';
26
+ import { CSV_NETWORK_FILE } from './data-folder.js';
27
+
28
+ export { CSV_NETWORK_FILE };
29
+
30
+ /** Bump when the file's layout changes in a way this version couldn't read. */
31
+ export const CSV_FORMAT = 1;
32
+
33
+ /** Each packed row, in order (lib/csv.js packConnections). */
34
+ export const CSV_COLUMNS = ['id', 'name', 'role', 'company', 'profile_url', 'connected_date'];
35
+
36
+ /**
37
+ * LinkedIn allows 30,000 connections. This leaves room, and still bounds what
38
+ * one request can make the app keep.
39
+ */
40
+ export const MAX_CSV_PEOPLE = 50000;
41
+ const MAX_FIELD = 2000;
42
+ const ISO_DATE = /^\d{4}-\d{2}-\d{2}$/;
43
+
44
+ /** A refusal whose message is fit to show inside a sentence. Nothing was written. */
45
+ export class CsvStoreError extends Error {}
46
+
47
+ const text = (v, { empty = true } = {}) => typeof v === 'string' && v.length <= MAX_FIELD && (empty || v.trim() !== '');
48
+
49
+ /** Why `rows` aren't a packed import this app would make, or null when they are. */
50
+ export function csvRowsProblem(rows) {
51
+ if (!Array.isArray(rows)) return 'it has no list of people';
52
+ if (!rows.length) return 'it has nobody in it';
53
+ if (rows.length > MAX_CSV_PEOPLE) return `it has ${rows.length.toLocaleString('en-US')} people, more than the ${MAX_CSV_PEOPLE.toLocaleString('en-US')} it can hold`;
54
+ const ids = new Set();
55
+ for (let i = 0; i < rows.length; i++) {
56
+ const r = rows[i];
57
+ const which = `person ${i + 1}`;
58
+ if (!Array.isArray(r) || r.length !== CSV_COLUMNS.length) return `${which} isn't laid out the way the import keeps people`;
59
+ const [id, name, role, company, profileUrl, connected] = r;
60
+ if (!text(id, { empty: false }) || !text(name, { empty: false })) return `${which} has a name or id that is missing or too long`;
61
+ if (!text(role) || !text(company)) return `${which} has a position or company that isn't text, or is too long`;
62
+ if (profileUrl !== null && !text(profileUrl)) return `${which} has a profile link that isn't text, or is too long`;
63
+ if (connected !== null && !(typeof connected === 'string' && ISO_DATE.test(connected))) return `${which} has a date that isn't one`;
64
+ if (ids.has(id)) return `two people share the id ${JSON.stringify(id.slice(0, 40))}`;
65
+ ids.add(id);
66
+ }
67
+ return null;
68
+ }
69
+
70
+ /** Why `doc` isn't a kept import this app wrote, or null when it is. */
71
+ export function csvNetworkProblem(doc) {
72
+ if (!doc || typeof doc !== 'object' || Array.isArray(doc)) return "it isn't what Six Degrees writes";
73
+ if (doc.format !== CSV_FORMAT) {
74
+ return Number.isInteger(doc.format) && doc.format > CSV_FORMAT
75
+ ? 'it was written by a newer Six Degrees than this one'
76
+ : "it isn't what Six Degrees writes";
77
+ }
78
+ if (typeof doc.importedAt !== 'string' || Number.isNaN(Date.parse(doc.importedAt))) return "it doesn't say when it was imported";
79
+ return csvRowsProblem(doc.connections);
80
+ }
81
+
82
+ /**
83
+ * The kept import in `dir`: `{ csv: { connections, importedAt, people }, problem: null }`,
84
+ * `{ csv: null, problem: null }` when there is none, or `{ csv: null, problem }`
85
+ * when a file is there but can't be used. Never throws.
86
+ */
87
+ export function readCsvNetwork(dir) {
88
+ const file = path.join(dir, CSV_NETWORK_FILE);
89
+ let st;
90
+ try {
91
+ st = lstatSync(file);
92
+ } catch (err) {
93
+ if (err.code === 'ENOENT') return { csv: null, problem: null };
94
+ return { csv: null, problem: `it couldn't be opened (${err.code || err.message})` };
95
+ }
96
+ // A link is never followed, as nowhere else in the data folder is.
97
+ if (!st.isFile()) return { csv: null, problem: "it isn't a plain file" };
98
+ let doc;
99
+ try {
100
+ doc = JSON.parse(readFileSync(file, 'utf8'));
101
+ } catch (err) {
102
+ return { csv: null, problem: err instanceof SyntaxError ? "it isn't readable JSON" : `it couldn't be read (${err.code || err.message})` };
103
+ }
104
+ const problem = csvNetworkProblem(doc);
105
+ if (problem) return { csv: null, problem };
106
+ return { csv: { connections: doc.connections, importedAt: doc.importedAt, people: doc.connections.length }, problem: null };
107
+ }
108
+
109
+ /**
110
+ * Keep `connections` (packed rows) as the import, in place of any kept before.
111
+ * Written whole or not at all, and on the disk before this returns
112
+ * (lib/durable.js): a temporary file, synced, then renamed over the old one.
113
+ * @throws {CsvStoreError} when the rows aren't an import this app would make.
114
+ */
115
+ export function writeCsvNetwork(dir, connections, { now = new Date() } = {}) {
116
+ const problem = csvRowsProblem(connections);
117
+ if (problem) throw new CsvStoreError(problem);
118
+ const doc = { format: CSV_FORMAT, source: 'csv', importedAt: now.toISOString(), columns: CSV_COLUMNS, connections };
119
+ durable.writeFileDurably(path.join(dir, CSV_NETWORK_FILE), JSON.stringify(doc));
120
+ return { people: connections.length, importedAt: doc.importedAt };
121
+ }
122
+
123
+ /** Remove the kept import. Returns whether there was one. */
124
+ export function removeCsvNetwork(dir) {
125
+ const file = path.join(dir, CSV_NETWORK_FILE);
126
+ let had = true;
127
+ try { lstatSync(file); } catch { had = false; }
128
+ rmSync(file, { force: true });
129
+ if (had) durable.syncFolder(dir);
130
+ return had;
131
+ }
@@ -1,10 +1,12 @@
1
1
  import { scorePerson, curveCutoffs, curvedTier } from './scoring.js';
2
2
  import { toIsoDate } from './ingest.js';
3
- // LinkedIn Connections.csv import — parsed ENTIRELY in the browser.
3
+ // LinkedIn Connections.csv import, read in the browser.
4
4
  //
5
- // Nothing is uploaded and nothing is written to the database: an imported
6
- // network lives in sessionStorage and disappears when the tab closes. That
7
- // keeps other people's connection lists off this deployment's Supabase.
5
+ // The file itself never leaves the page. What the map needs about each person
6
+ // goes to this computer's own server, which keeps it in the data folder
7
+ // (csv-network.json, lib/csv-store.js) so it's still there after the window
8
+ // closes. It's never written into the database or mixed with a scanned
9
+ // network, and nothing goes anywhere else.
8
10
  //
9
11
  // The official export carries six usable columns — First Name, Last Name,
10
12
  // URL, Company, Position, Connected On. It has NO profile photos and no rich
@@ -55,7 +57,7 @@ export function scoreRecord(headline, company) {
55
57
  * a CSV import uses the app's defaults, never your settings (no company
56
58
  * scores, no sector), and the curve is the default, so the first look at any
57
59
  * export has a top. Scores → Tiers says so while one is open. Run on the
58
- * parse (the import page's counts) and on every load (the tab keeps only
60
+ * parse (the import page's counts) and on every load (the data folder keeps only
59
61
  * what the export says, packConnections), so the two always agree.
60
62
  */
61
63
  function gradeOnCurve(connections) {
@@ -154,20 +156,46 @@ export function parseConnectionsCsv(text) {
154
156
  return { connections, skipped, total: connections.length + skipped };
155
157
  }
156
158
 
157
- // ── Session-scoped storage (never the database) ────────────────────────────
158
- export function saveSessionNetwork({ degree1 = [], degree2 = [], source = 'csv' }) {
159
+ // ── Where an open network is kept ──────────────────────────────────────────
160
+ // A CSV import is kept in the data folder through /api/data/csv
161
+ // (lib/csv-store.js) until × beside "Your CSV" removes it. It used to live in
162
+ // sessionStorage and was gone when the window closed (the 1.0 list,
163
+ // 2026-10-03: CSV imports survive closing the window).
164
+ //
165
+ // The sample network stays in this window only. It's a look around, not
166
+ // anyone's network, so it never goes into the data folder, a copy or a backup.
167
+
168
+ const SAMPLE_KEY = 'six-degrees-sample-network';
169
+ const CSV_ROUTE = '/api/data/csv';
170
+
171
+ export function saveSampleNetwork({ degree1 = [], degree2 = [] }) {
159
172
  try {
160
- sessionStorage.setItem(STORAGE_KEY, JSON.stringify({ degree1, degree2, source, importedAt: Date.now() }));
173
+ sessionStorage.setItem(SAMPLE_KEY, JSON.stringify({ degree1, degree2, source: 'sample', importedAt: Date.now() }));
161
174
  return true;
162
175
  } catch {
163
- return false; // quota — very large networks
176
+ return false; // storage full or off
164
177
  }
165
178
  }
166
179
 
167
- // A scored row is ~540 characters and the tab holds ~5 million, which capped an
168
- // import near 9,000 connections. So the tab keeps only what the export says about
169
- // each person (~130 characters) and scores it again on load: an export at
170
- // LinkedIn's own maximum of 30,000 connections fits.
180
+ function sampleOpen() {
181
+ try { return !!sessionStorage.getItem(SAMPLE_KEY); } catch { return false; }
182
+ }
183
+
184
+ function sampleNetwork() {
185
+ try {
186
+ const parsed = JSON.parse(sessionStorage.getItem(SAMPLE_KEY));
187
+ return parsed ? { degree1: parsed.degree1 || [], degree2: parsed.degree2 || [], source: 'sample' } : null;
188
+ } catch { return null; }
189
+ }
190
+
191
+ function leaveSample() {
192
+ try { sessionStorage.removeItem(SAMPLE_KEY); } catch { /* storage off: nothing was kept */ }
193
+ }
194
+
195
+ // The file keeps only what the export says about each person (~130 characters)
196
+ // and the page scores it again on every load, so it always follows the scoring
197
+ // model and LinkedIn's maximum of 30,000 connections is one request of about
198
+ // 4 MB, well under the 10 MB Next reads before middleware (docs/brain/ENDPOINTS.md).
171
199
  export function packConnections(connections) {
172
200
  return connections.map((c) => [c.id, c.name, c.role, c.company, c.profile_url, c.connected_date]);
173
201
  }
@@ -177,41 +205,111 @@ export function unpackConnections(rows = []) {
177
205
  .sort((a, b) => b.power_score - a.power_score);
178
206
  }
179
207
 
180
- export function saveCsvNetwork(connections) {
181
- try {
182
- sessionStorage.setItem(STORAGE_KEY, JSON.stringify({
183
- packed: packConnections(connections), degree2: [], source: 'csv', importedAt: Date.now(),
184
- }));
185
- return true;
186
- } catch {
187
- return false; // quota
188
- }
208
+ /**
209
+ * Which network every page opens on: 'sample', 'csv' or 'own' (the database).
210
+ * The one rule, so the map, Paths, Settings and who "you" are can't disagree.
211
+ *
212
+ * The sample, opened in this window, is shown until it's left. A kept CSV
213
+ * import is shown only while the database has no 1st-degree people: once you
214
+ * have scanned your own connections, the scan is your network. When the CSV
215
+ * lived in the window, closing it handed the map back to the scan by itself;
216
+ * kept, it would otherwise hide every scan after it for good (the 1.0 review,
217
+ * 2026-10-03). The file itself stays on the disk, never deleted for you, and
218
+ * the import page says it's there and offers to remove it.
219
+ */
220
+ export function openNetworkSource({ sample = false, csvKept = false, scannedFirstDegree = 0 } = {}) {
221
+ if (sample) return 'sample';
222
+ if (csvKept && !(Number(scannedFirstDegree) > 0)) return 'csv';
223
+ return 'own';
189
224
  }
190
225
 
191
- export function hasCsvNetwork() {
192
- try { return !!sessionStorage.getItem(STORAGE_KEY); } catch { return false; }
226
+ // The kept import, and how many 1st-degree people the database has, asked for
227
+ // once per page: who "you" are, the map, and the Settings sections all ask,
228
+ // and it's the same answer. Forgotten whenever it changes, since a link to
229
+ // another page keeps this module loaded.
230
+ let kept = null;
231
+ function keptCsv() {
232
+ kept ??= fetch(CSV_ROUTE, { cache: 'no-store' })
233
+ .then(async (r) => {
234
+ const j = await r.json().catch(() => ({}));
235
+ if (!r.ok) return { csv: null, scanned: 0, problem: `Your kept CSV import couldn't be loaded (${j.error || `the app answered ${r.status}`}).` };
236
+ return { csv: j.csv || null, scanned: Number(j.scanned) || 0, problem: j.problem || null };
237
+ })
238
+ // No answer at all: the app isn't running, and nothing else on the page will load either.
239
+ .catch(() => ({ csv: null, scanned: 0, problem: null }));
240
+ return kept;
193
241
  }
194
242
 
195
- /** 'csv' or 'sample' when this tab holds one, else null — without rescoring it as loadCsvNetwork() does. */
196
- export function csvNetworkSource() {
197
- try {
198
- const raw = sessionStorage.getItem(STORAGE_KEY);
199
- return raw ? JSON.parse(raw).source || 'csv' : null;
200
- } catch { return null; }
243
+ async function opening() {
244
+ const k = await keptCsv();
245
+ return { ...k, source: openNetworkSource({ sample: sampleOpen(), csvKept: Boolean(k.csv), scannedFirstDegree: k.scanned }) };
201
246
  }
202
247
 
203
- export function loadCsvNetwork() {
248
+ /** The network open instead of the database: the sample or a kept CSV import (openNetworkSource), else null. */
249
+ export async function loadCsvNetwork() {
250
+ const { source, csv } = await opening();
251
+ if (source === 'sample') return sampleNetwork();
252
+ if (source !== 'csv') return null;
253
+ return { degree1: unpackConnections(csv.connections), degree2: [], source: 'csv', importedAt: csv.importedAt };
254
+ }
255
+
256
+ /** 'sample' or 'csv' when one is open instead of the database, else null, without scoring it as loadCsvNetwork() does. */
257
+ export async function csvNetworkSource() {
258
+ const { source } = await opening();
259
+ return source === 'own' ? null : source;
260
+ }
261
+
262
+ /**
263
+ * A CSV import kept here but not shown, because the database has your scanned
264
+ * connections: `{ people, importedAt }`, else null. The import page says so
265
+ * and offers to remove it.
266
+ */
267
+ export async function keptBehindScan() {
268
+ const { source, csv } = await opening();
269
+ return csv && source === 'own' ? { people: csv.people, importedAt: csv.importedAt } : null;
270
+ }
271
+
272
+ /** What × and the import page's Remove ask before a kept import is deleted. */
273
+ export const REMOVE_CSV_QUESTION = 'Remove this CSV import from this computer? Your Connections.csv file isn’t touched, so you can import it again.';
274
+
275
+ /** Why a kept import is there but can't be opened, or null. Said on the welcome screen, never passed off as no import (TRAPS §7). */
276
+ export async function keptCsvProblem() {
277
+ return (await keptCsv()).problem;
278
+ }
279
+
280
+ /** Keep an import, in place of any kept before. Resolves { ok: true, people } or { ok: false, error }, the error fit to show. */
281
+ export async function saveCsvNetwork(connections) {
282
+ kept = null;
204
283
  try {
205
- const raw = sessionStorage.getItem(STORAGE_KEY);
206
- if (!raw) return null;
207
- const parsed = JSON.parse(raw);
208
- const degree1 = parsed.packed ? unpackConnections(parsed.packed) : parsed.degree1 || [];
209
- return { degree1, degree2: parsed.degree2 || [], source: parsed.source || 'csv' };
210
- } catch { return null; }
284
+ const r = await fetch(CSV_ROUTE, {
285
+ method: 'POST',
286
+ headers: { 'Content-Type': 'application/json' },
287
+ body: JSON.stringify({ connections: packConnections(connections) }),
288
+ });
289
+ const j = await r.json().catch(() => ({}));
290
+ if (!r.ok) return { ok: false, error: j.error || `The import couldn't be kept (the app answered ${r.status}).` };
291
+ // The import is what the map opens on now, not a sample still open in this window.
292
+ leaveSample();
293
+ return { ok: true, people: j.people };
294
+ } catch {
295
+ return { ok: false, error: "The import couldn't be kept: Six Degrees didn't answer. Check that it's still running, then try again." };
296
+ }
211
297
  }
212
298
 
213
- export function clearCsvNetwork() {
214
- try { sessionStorage.removeItem(STORAGE_KEY); } catch {}
299
+ /** Close what's open: the sample is forgotten by this window; a CSV import is removed from the data folder. Resolves { ok } or { ok: false, error }. */
300
+ export async function closeCsvNetwork(source) {
301
+ kept = null;
302
+ if (source === 'sample') {
303
+ leaveSample();
304
+ return { ok: true };
305
+ }
306
+ try {
307
+ const r = await fetch(CSV_ROUTE, { method: 'DELETE' });
308
+ const j = await r.json().catch(() => ({}));
309
+ return r.ok ? { ok: true } : { ok: false, error: j.error || `The import couldn't be removed (the app answered ${r.status}).` };
310
+ } catch {
311
+ return { ok: false, error: "The import couldn't be removed: Six Degrees didn't answer. Check that it's still running, then try again." };
312
+ }
215
313
  }
216
314
 
217
315
  export const CSV_USER = { id: 'csv-local-user', name: 'You' };
@@ -17,18 +17,29 @@ import { AVATAR_FILE } from './photos.js';
17
17
  // import accepts exactly those names.
18
18
  export { AVATAR_FILE };
19
19
 
20
+ /**
21
+ * A LinkedIn Connections.csv import, kept so it is still there after the
22
+ * window closes (lib/csv-store.js). Kept beside the database, never merged
23
+ * into it: a CSV row has no bridge, no user and no id the scanner made, and
24
+ * folding it in by profile link is how duplicates and lost rows happened
25
+ * before (TRAPS §19, §25, §36).
26
+ */
27
+ export const CSV_NETWORK_FILE = 'csv-network.json';
28
+
20
29
  /**
21
30
  * The scanner's notes about the network itself: without them, people whose
22
31
  * circles are hidden or half-read would be retried from scratch on the new
23
32
  * computer (TRAPS §15, §34). They describe one network's people, so an import
24
33
  * replaces them along with the network: this computer's notes would say which
25
34
  * pages of the old network's people were read, and the scanner would skip
26
- * those pages for the new one.
35
+ * those pages for the new one. A kept CSV import is a network of its own, so
36
+ * it travels and is replaced the same way (what was here goes to backups/).
27
37
  */
28
38
  export const NETWORK_FILES = [
29
39
  'bridge-progress.json',
30
40
  'bridge-skips.json',
31
41
  'bridge-unclear.json',
42
+ CSV_NETWORK_FILE,
32
43
  ];
33
44
 
34
45
  /**
@@ -209,10 +220,15 @@ export function folderOpener(platform = process.platform) {
209
220
  /**
210
221
  * Open the data folder in Finder (or the Linux file browser). The path is the
211
222
  * data folder itself, never anything from a request. Resolves { ok, message }.
223
+ * `select` is a file in `dir` (a backup, lib/backups.js), its whole path, that
224
+ * Finder shows selected (`open -R`); a Linux file browser just opens the
225
+ * folder. The caller builds the path: one built here makes Next's build trace
226
+ * the whole project into the app (TRAPS §27).
212
227
  */
213
- export function revealFolder(dir, { platform = process.platform, spawnImpl = spawn, waitMs = 3000 } = {}) {
228
+ export function revealFolder(dir, { platform = process.platform, spawnImpl = spawn, waitMs = 3000, select = null } = {}) {
214
229
  const cmd = folderOpener(platform);
215
230
  if (!cmd) return Promise.resolve({ ok: false, message: 'There is no file browser to open it with on this computer.' });
231
+ const args = select && cmd === 'open' ? ['-R', select] : [dir];
216
232
  return new Promise((resolve) => {
217
233
  let timer = null;
218
234
  let settled = false;
@@ -224,7 +240,7 @@ export function revealFolder(dir, { platform = process.platform, spawnImpl = spa
224
240
  };
225
241
  let child;
226
242
  try {
227
- child = spawnImpl(cmd, [dir], { stdio: 'ignore', detached: true });
243
+ child = spawnImpl(cmd, args, { stdio: 'ignore', detached: true });
228
244
  } catch (err) {
229
245
  done({ ok: false, message: `It couldn't be opened (${err.message}).` });
230
246
  return;
@@ -270,7 +270,7 @@ export function validateImport(file, { applySchema, schemaSql, appVersion, retir
270
270
  }
271
271
  const present = new Set(objects.filter((o) => o.type === 'table').map((o) => o.name));
272
272
  if (!present.has('sd_export_manifest') || !present.has('sd_export_files')) {
273
- throw new ImportError("This is a database but not a Six Degrees export, so nothing was imported. Make one on the other computer with Settings → Your data → Save a copy.");
273
+ throw new ImportError("This is a database but not a Six Degrees export, so nothing was imported. Make one on the other computer with Export backup file… in Settings → Your data.");
274
274
  }
275
275
  for (const [t, { required, allowed }] of ref.tables) {
276
276
  if (!present.has(t)) {
@@ -380,7 +380,7 @@ export function validateImport(file, { applySchema, schemaSql, appVersion, retir
380
380
  * @returns what the Settings page shows while the import waits.
381
381
  */
382
382
  export function stageImport(upload, {
383
- dir, applySchema, schemaSql, appVersion, replacedPeople = 0, now = new Date(), retired = RETIRED,
383
+ dir, applySchema, schemaSql, appVersion, replacedPeople = 0, now = new Date(), retired = RETIRED, restoredFrom = null,
384
384
  }) {
385
385
  const info = validateImport(upload, { applySchema, schemaSql, appVersion, retired });
386
386
  const work = path.dirname(upload);
@@ -436,6 +436,8 @@ export function stageImport(upload, {
436
436
  people: info.people,
437
437
  photos: info.photos,
438
438
  replacedPeople,
439
+ // A backup from backups/ being put back (lib/backups.js restoreBackup), by its name.
440
+ ...(restoredFrom ? { restoredFrom } : {}),
439
441
  };
440
442
  writeFileSync(path.join(work, 'READY'), `${JSON.stringify(ready, null, 2)}\n`);
441
443
  // On the disk before import-pending/ appears: the next start moves this
@@ -822,6 +824,7 @@ export function applyPendingImport({ dir, dbFile, now = new Date(), copyDatabase
822
824
  people: ready.people ?? null,
823
825
  photos: ready.photos ?? null,
824
826
  replacedPeople: ready.replacedPeople ?? null,
827
+ restoredFrom: ready.restoredFrom ?? null,
825
828
  keptDatabase: exists(keptDb) ? shown(keptDb) : null,
826
829
  keptFiles: exists(keptFiles) ? shown(keptFiles) : null,
827
830
  // Set when the database that was here couldn't be read, so it was kept
@@ -1,10 +1,15 @@
1
1
  import { DatabaseSync } from 'node:sqlite';
2
- import { mkdirSync, existsSync, readFileSync, writeFileSync, readdirSync, statSync, rmSync } from 'node:fs';
2
+ import { mkdirSync, existsSync, readFileSync, writeFileSync, renameSync, rmSync } from 'node:fs';
3
3
  import { homedir } from 'node:os';
4
4
  import path from 'node:path';
5
5
  import { SCHEMA_SQL } from '../db/schema.js';
6
6
  import { APP_VERSION } from './app-version.js';
7
7
  import { applyPendingImport, recordImport } from './data-import.js';
8
+ import { compareVersions } from './release.js';
9
+ import { durable } from './durable.js';
10
+ import {
11
+ makeBackup, rotateBackups, dailyBackupIfDue, noteBackupFailure, AUTO_BACKUP_PREFIX,
12
+ } from './backups.js';
8
13
 
9
14
  // The database lives OUTSIDE the app directory so an installed copy never
10
15
  // writes into its own package. Override with SIX_DEGREES_HOME.
@@ -78,7 +83,7 @@ export function getDb() {
78
83
  // Before this version changes anything: if a different version opened this
79
84
  // data last, keep a copy of it as it was. See backupOnNewVersion().
80
85
  try {
81
- const saved = backupOnNewVersion(_db, { dir: path.dirname(file), version: APP_VERSION });
86
+ const saved = backupOnNewVersion(_db, { dir: path.dirname(file), dataDir: dataDir(), version: APP_VERSION });
82
87
  if (saved) console.log(`Six Degrees ${APP_VERSION}: backed up your data first → ${saved}`);
83
88
  } catch (err) {
84
89
  console.error(`Six Degrees: could not back up your data before ${APP_VERSION} (will try again next start): ${err.message}`);
@@ -90,11 +95,39 @@ export function getDb() {
90
95
 
91
96
  if (imported) {
92
97
  try { recordImport(_db, imported); } catch { /* only the Settings page's note is lost */ }
98
+ // The copy that import kept of what was here joins the rotation (lib/backups.js KEEP).
99
+ try { rotateBackups(backupsFolder()); } catch { /* tried again after the next backup */ }
100
+ }
101
+
102
+ // Once a day: checked here, as the server opens the data, and after each
103
+ // scan (app/api/scraper/route.js). No timer: nothing runs that nobody started.
104
+ try {
105
+ const daily = backUpDailyIfDue(_db);
106
+ if (daily) console.log(`Six Degrees: made today's backup → ${daily.file}`);
107
+ } catch (err) {
108
+ console.error(`Six Degrees: could not make today's backup (will try again after the next scan or start): ${err.message}`);
93
109
  }
94
110
 
95
111
  return _db;
96
112
  }
97
113
 
114
+ /** backups/, beside the database (where an import keeps its copy too). */
115
+ export function backupsFolder() {
116
+ return path.join(path.dirname(dbFile()), 'backups');
117
+ }
118
+
119
+ /** What lib/backups.js needs to make, check and restore this copy's backups. */
120
+ export function backupOptions(db = getDb()) {
121
+ return {
122
+ db, dataDir: dataDir(), backupsDir: backupsFolder(), appVersion: APP_VERSION, schemaSql: SCHEMA_SQL, applySchema,
123
+ };
124
+ }
125
+
126
+ /** The daily backup, if one is due (lib/backups.js dailyBackupIfDue). @returns it, or null. */
127
+ export function backUpDailyIfDue(db = getDb(), now = new Date()) {
128
+ return dailyBackupIfDue({ ...backupOptions(db), now });
129
+ }
130
+
98
131
  /**
99
132
  * Every table, index and column this version uses, made if missing. An import
100
133
  * is rebuilt into exactly this (lib/data-import.js), so only rows travel.
@@ -120,16 +153,24 @@ function addMissingColumns(db) {
120
153
 
121
154
  // ── a copy of the data before each new version touches it ──────────────────
122
155
  // The first time a version opens a database that a different version (or one
123
- // from before this existed) used last, it copies the database, as it was, into
124
- // backups/ — before the schema step or anything else writes to it. VACUUM INTO
125
- // makes one consistent file even mid-WAL. The newest five automatic copies are
126
- // kept; anything else in backups/ (copies made by hand) is never touched. The
127
- // marker is written only after the copy succeeds, so a failed copy (a full
128
- // disk) is retried at the next start.
156
+ // from before this existed) used last, it backs it up, as it was, into
157
+ // backups/: before the schema step or anything else writes to it. The backup
158
+ // is the whole network, photos and files too (lib/backups.js makeBackup), so
159
+ // Settings → Your data → Restore can put it back. The newest three are kept;
160
+ // anything someone put in backups/ themselves is never touched. The marker is
161
+ // written only after a copy succeeds, so a failed one (a full disk) is retried
162
+ // at the next start.
163
+ //
164
+ // If that backup can't be made or fails its check (a database holding
165
+ // something an export never does, say), the database alone is still copied,
166
+ // as every version before this did: a copy that only a person can put back is
167
+ // better than none before an update. The page says the backup didn't work.
129
168
 
130
- export const AUTO_BACKUP_PREFIX = 'auto-before-';
169
+ export { AUTO_BACKUP_PREFIX };
131
170
 
132
- export function backupOnNewVersion(db, { dir, version, keep = 5, now = new Date() }) {
171
+ export function backupOnNewVersion(db, {
172
+ dir, version, dataDir: filesDir = dir, now = new Date(), schemaSql = SCHEMA_SQL, applySchema: schemaStep = applySchema,
173
+ }) {
133
174
  const marker = path.join(dir, 'app-version');
134
175
  let last = null;
135
176
  try { last = readFileSync(marker, 'utf8').trim(); } catch { /* first run, or older than this */ }
@@ -141,16 +182,33 @@ export function backupOnNewVersion(db, { dir, version, keep = 5, now = new Date(
141
182
  ).get().n > 0;
142
183
  if (hasData) {
143
184
  const folder = path.join(dir, 'backups');
144
- mkdirSync(folder, { recursive: true });
145
- const stamp = now.toISOString().replace(/[:.]/g, '-');
146
- saved = path.join(folder, `${AUTO_BACKUP_PREFIX}${version}-${stamp}.sqlite`);
147
- db.exec(`VACUUM INTO '${saved.replace(/'/g, "''")}'`);
148
-
149
- const autos = readdirSync(folder)
150
- .filter((f) => f.startsWith(AUTO_BACKUP_PREFIX) && f.endsWith('.sqlite'))
151
- .map((f) => ({ f, at: statSync(path.join(folder, f)).mtimeMs }))
152
- .sort((a, b) => b.at - a.at || b.f.localeCompare(a.f));
153
- for (const { f } of autos.slice(keep)) rmSync(path.join(folder, f), { force: true });
185
+ // The data is the last version's, not this one's: say so in the copy, so
186
+ // that version can restore it if this one has to be put back. (Data a
187
+ // newer version wrote, or with no marker, is labelled with this version.)
188
+ const known = /^v?\d+\.\d+\.\d+/.test(last || '') && compareVersions(last, version) <= 0;
189
+ try {
190
+ saved = makeBackup('before-update', {
191
+ db, dataDir: filesDir, backupsDir: folder, appVersion: version, dataVersion: known ? last : version,
192
+ schemaSql, applySchema: schemaStep, now,
193
+ }).file;
194
+ } catch (err) {
195
+ noteBackupFailure('before-update', err, now);
196
+ mkdirSync(folder, { recursive: true });
197
+ saved = path.join(folder, `${AUTO_BACKUP_PREFIX}${version}-${now.toISOString().replace(/[:.]/g, '-')}.sqlite`);
198
+ // Through the open handle, and synced before it takes its name (the
199
+ // vacuumCopy pattern, lib/data-import.js).
200
+ const partial = path.join(folder, `.${path.basename(saved)}.partial`);
201
+ try {
202
+ db.exec(`VACUUM INTO '${partial.replace(/'/g, "''")}'`);
203
+ durable.syncFile(partial);
204
+ renameSync(partial, saved);
205
+ durable.syncFolder(folder);
206
+ } catch (copyErr) {
207
+ rmSync(partial, { force: true });
208
+ throw copyErr;
209
+ }
210
+ try { rotateBackups(folder, { now }); } catch { /* tried again after the next one */ }
211
+ }
154
212
  }
155
213
  writeFileSync(marker, `${version}\n`);
156
214
  return saved;
@@ -4,7 +4,7 @@
4
4
  // It exists so a first run has something to show, so screenshots contain no real
5
5
  // people, and so the Bridges view can be explored before you have data of your own.
6
6
 
7
- import { saveSessionNetwork } from './csv';
7
+ import { saveSampleNetwork } from './csv';
8
8
 
9
9
  export const IS_DEMO = process.env.NEXT_PUBLIC_DEMO_MODE === 'true';
10
10
 
@@ -19,16 +19,17 @@ let _cache = null;
19
19
  export async function loadDemoNetwork() {
20
20
  if (_cache) return _cache;
21
21
  const res = await fetch('/demo-data.json', { cache: 'no-cache' });
22
- if (!res.ok) throw new Error('demo-data.json not found — run: node scripts/gen-synthetic.mjs');
22
+ if (!res.ok) throw new Error('demo-data.json not found. Run: node scripts/gen-synthetic.mjs');
23
23
  const data = await res.json();
24
24
  _cache = { degree1: data.degree1 || [], degree2: data.degree2 || [] };
25
25
  return _cache;
26
26
  }
27
27
 
28
28
  // Loads the sample into this browser tab and reports how big it is. Nothing is
29
- // written to the database, so it disappears when the tab closes.
29
+ // written to the database or the data folder, so it disappears when the tab
30
+ // closes (a CSV import is kept; the sample isn't anyone's: lib/csv.js).
30
31
  export async function loadSampleIntoSession() {
31
32
  const net = await loadDemoNetwork();
32
- saveSessionNetwork({ degree1: net.degree1, degree2: net.degree2, source: 'sample' });
33
+ saveSampleNetwork({ degree1: net.degree1, degree2: net.degree2 });
33
34
  return { degree1: net.degree1.length, degree2: net.degree2.length };
34
35
  }
@@ -8,6 +8,10 @@ import { MAP_LOOK } from './themes.js';
8
8
 
9
9
  let current = null; // { svg, stamp: () => text or null, legend: () => [[label, colour]] }
10
10
 
11
+ // The small credit in the corner of every picture and video. A shared picture is
12
+ // how someone finds the app, so it names where to get it.
13
+ export const CREDIT = 'sixdegreesapp.com';
14
+
11
15
  export function registerGalaxy(entry) {
12
16
  current = entry;
13
17
  return () => { if (current === entry) current = null; };
@@ -31,7 +35,10 @@ function svgImage(svg) {
31
35
  // The page's font, which the <svg> inherits on screen but not in a file.
32
36
  clone.setAttribute('font-family', getComputedStyle(svg).fontFamily || 'system-ui, sans-serif');
33
37
  const style = document.createElementNS('http://www.w3.org/2000/svg', 'style');
34
- style.textContent = EXPORT_CSS;
38
+ // The theme's colours (lib/themes.js), which the map reads from the page and a file can't.
39
+ const root = document.documentElement;
40
+ const vars = [...root.style].filter((k) => k.startsWith('--sd-')).map((k) => `${k}:${root.style.getPropertyValue(k)}`).join(';');
41
+ style.textContent = `svg{${vars}}${EXPORT_CSS}`;
35
42
  clone.insertBefore(style, clone.firstChild);
36
43
  const xml = new XMLSerializer().serializeToString(clone);
37
44
  const img = new Image();
@@ -76,7 +83,7 @@ async function drawFrame(ctx, w, h) {
76
83
  }
77
84
  ctx.textAlign = 'right';
78
85
  ctx.fillStyle = 'rgba(255,255,255,0.35)';
79
- ctx.fillText('Six Degrees', cw - 16, 24);
86
+ ctx.fillText(CREDIT, cw - 16, 24);
80
87
  ctx.restore();
81
88
  }
82
89