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.
- package/.next/standalone/.next/BUILD_ID +1 -1
- package/.next/standalone/.next/app-path-routes-manifest.json +4 -0
- package/.next/standalone/.next/build-manifest.json +3 -3
- package/.next/standalone/.next/prerender-manifest.json +42 -14
- package/.next/standalone/.next/routes-manifest.json +24 -0
- package/.next/standalone/.next/server/app/_global-error.html +1 -1
- package/.next/standalone/.next/server/app/_global-error.rsc +1 -1
- package/.next/standalone/.next/server/app/_global-error.segments/__PAGE__.segment.rsc +1 -1
- package/.next/standalone/.next/server/app/_global-error.segments/_full.segment.rsc +1 -1
- package/.next/standalone/.next/server/app/_global-error.segments/_tree.segment.rsc +1 -1
- package/.next/standalone/.next/server/app/_not-found/page.js +1 -1
- package/.next/standalone/.next/server/app/_not-found/page.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/_not-found/page_client-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/app/_not-found.html +1 -1
- package/.next/standalone/.next/server/app/_not-found.rsc +26 -18
- package/.next/standalone/.next/server/app/_not-found.segments/_full.segment.rsc +26 -18
- package/.next/standalone/.next/server/app/_not-found.segments/_not-found/__PAGE__.segment.rsc +25 -16
- package/.next/standalone/.next/server/app/_not-found.segments/_tree.segment.rsc +2 -2
- package/.next/standalone/.next/server/app/api/admin-delete/route.js +2 -2
- package/.next/standalone/.next/server/app/api/admin-delete/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/api/admin-update/route.js +2 -2
- package/.next/standalone/.next/server/app/api/admin-update/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/api/bridges/route.js +2 -2
- package/.next/standalone/.next/server/app/api/bridges/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/api/bulk-import/route.js +2 -2
- package/.next/standalone/.next/server/app/api/bulk-import/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/api/company-scores/legacy/route.js +3 -3
- package/.next/standalone/.next/server/app/api/company-scores/legacy/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/api/company-scores/route.js +3 -3
- package/.next/standalone/.next/server/app/api/company-scores/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/api/connections/route.js +2 -2
- package/.next/standalone/.next/server/app/api/connections/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/api/data/backup/route/app-paths-manifest.json +3 -0
- package/.next/standalone/.next/server/app/api/data/backup/route/build-manifest.json +12 -0
- package/.next/standalone/.next/server/app/api/data/backup/route/server-reference-manifest.json +4 -0
- package/.next/standalone/.next/server/app/api/data/backup/route.js +7 -0
- package/.next/standalone/.next/server/app/api/data/backup/route.js.map +5 -0
- package/.next/standalone/.next/server/app/api/data/backup/route.js.nft.json +1 -0
- package/.next/standalone/.next/server/app/api/data/backup/route_client-reference-manifest.js +3 -0
- package/.next/standalone/.next/server/app/api/data/csv/route/app-paths-manifest.json +3 -0
- package/.next/standalone/.next/server/app/api/data/csv/route/build-manifest.json +12 -0
- package/.next/standalone/.next/server/app/api/data/csv/route/server-reference-manifest.json +4 -0
- package/.next/standalone/.next/server/app/api/data/csv/route.js +8 -0
- package/.next/standalone/.next/server/app/api/data/csv/route.js.map +5 -0
- package/.next/standalone/.next/server/app/api/data/csv/route.js.nft.json +1 -0
- package/.next/standalone/.next/server/app/api/data/csv/route_client-reference-manifest.js +3 -0
- package/.next/standalone/.next/server/app/api/data/export/route.js +1 -1
- package/.next/standalone/.next/server/app/api/data/export/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/api/data/import/route.js +1 -1
- package/.next/standalone/.next/server/app/api/data/import/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/api/data/restart/route.js +1 -1
- package/.next/standalone/.next/server/app/api/data/restart/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/api/data/restore/route/app-paths-manifest.json +3 -0
- package/.next/standalone/.next/server/app/api/data/restore/route/build-manifest.json +12 -0
- package/.next/standalone/.next/server/app/api/data/restore/route/server-reference-manifest.json +4 -0
- package/.next/standalone/.next/server/app/api/data/restore/route.js +7 -0
- package/.next/standalone/.next/server/app/api/data/restore/route.js.map +5 -0
- package/.next/standalone/.next/server/app/api/data/restore/route.js.nft.json +1 -0
- package/.next/standalone/.next/server/app/api/data/restore/route_client-reference-manifest.js +3 -0
- package/.next/standalone/.next/server/app/api/data/reveal/route.js +1 -1
- package/.next/standalone/.next/server/app/api/data/reveal/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/api/data/route.js +1 -1
- package/.next/standalone/.next/server/app/api/data/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/api/delete-cluster/route.js +2 -2
- package/.next/standalone/.next/server/app/api/delete-cluster/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/api/ingest/route.js +2 -2
- package/.next/standalone/.next/server/app/api/ingest/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/api/network/route.js +2 -2
- package/.next/standalone/.next/server/app/api/network/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/api/notifications/route.js +2 -2
- package/.next/standalone/.next/server/app/api/notifications/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/api/outreach/route.js +3 -3
- package/.next/standalone/.next/server/app/api/outreach/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/api/queue/route.js +2 -2
- package/.next/standalone/.next/server/app/api/queue/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/api/scraper/route.js +5 -3
- package/.next/standalone/.next/server/app/api/scraper/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/api/settings/route.js +3 -3
- package/.next/standalone/.next/server/app/api/settings/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/api/settings/sector-preview/route.js +3 -3
- package/.next/standalone/.next/server/app/api/settings/sector-preview/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/api/settings/sector-suggestions/route.js +3 -3
- package/.next/standalone/.next/server/app/api/settings/sector-suggestions/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/api/setup-profile/route.js +2 -2
- package/.next/standalone/.next/server/app/api/setup-profile/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/api/social/crm/route.js +1 -1
- package/.next/standalone/.next/server/app/api/social/crm/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/api/social/messages/route.js +1 -1
- package/.next/standalone/.next/server/app/api/social/messages/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/api/social/route.js +2 -2
- package/.next/standalone/.next/server/app/api/social/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/api/unlock/route.js +2 -2
- package/.next/standalone/.next/server/app/api/unlock/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/api/update/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/api/update-images/route.js +2 -2
- package/.next/standalone/.next/server/app/api/update-images/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/api/users/route.js +2 -2
- package/.next/standalone/.next/server/app/api/users/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/avatars/[file]/route.js +1 -1
- package/.next/standalone/.next/server/app/avatars/[file]/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/import/page.js +1 -1
- package/.next/standalone/.next/server/app/import/page.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/import/page_client-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/app/import.html +1 -1
- package/.next/standalone/.next/server/app/import.rsc +32 -24
- package/.next/standalone/.next/server/app/import.segments/_full.segment.rsc +32 -24
- package/.next/standalone/.next/server/app/import.segments/_tree.segment.rsc +2 -2
- package/.next/standalone/.next/server/app/import.segments/import/__PAGE__.segment.rsc +23 -18
- package/.next/standalone/.next/server/app/index.html +1 -1
- package/.next/standalone/.next/server/app/index.rsc +29 -22
- package/.next/standalone/.next/server/app/index.segments/__PAGE__.segment.rsc +20 -15
- package/.next/standalone/.next/server/app/index.segments/_full.segment.rsc +29 -22
- package/.next/standalone/.next/server/app/index.segments/_tree.segment.rsc +2 -2
- package/.next/standalone/.next/server/app/insights/page/app-paths-manifest.json +3 -0
- package/.next/standalone/.next/server/app/insights/page/build-manifest.json +20 -0
- package/.next/standalone/.next/server/app/insights/page/next-font-manifest.json +11 -0
- package/.next/standalone/.next/server/app/insights/page/react-loadable-manifest.json +1 -0
- package/.next/standalone/.next/server/app/insights/page/server-reference-manifest.json +4 -0
- package/.next/standalone/.next/server/app/insights/page.js +13 -0
- package/.next/standalone/.next/server/app/insights/page.js.map +5 -0
- package/.next/standalone/.next/server/app/insights/page.js.nft.json +1 -0
- package/.next/standalone/.next/server/app/insights/page_client-reference-manifest.js +3 -0
- package/.next/standalone/.next/server/app/insights.html +1 -0
- package/.next/standalone/.next/server/app/insights.meta +26 -0
- package/.next/standalone/.next/server/app/insights.rsc +35 -0
- package/.next/standalone/.next/server/app/insights.segments/_full.segment.rsc +35 -0
- package/.next/standalone/.next/server/app/insights.segments/_tree.segment.rsc +4 -0
- package/.next/standalone/.next/server/app/insights.segments/insights/__PAGE__.segment.rsc +33 -0
- package/.next/standalone/.next/server/app/launch/page.js +1 -1
- package/.next/standalone/.next/server/app/launch/page.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/launch/page_client-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/app/launch.html +2 -2
- package/.next/standalone/.next/server/app/launch.rsc +32 -24
- package/.next/standalone/.next/server/app/launch.segments/_full.segment.rsc +32 -24
- package/.next/standalone/.next/server/app/launch.segments/_tree.segment.rsc +2 -2
- package/.next/standalone/.next/server/app/launch.segments/launch/__PAGE__.segment.rsc +23 -18
- package/.next/standalone/.next/server/app/page.js +1 -1
- package/.next/standalone/.next/server/app/page.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/page_client-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/app/paths/page.js +1 -1
- package/.next/standalone/.next/server/app/paths/page.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/paths/page_client-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/app/paths.html +1 -1
- package/.next/standalone/.next/server/app/paths.rsc +32 -24
- package/.next/standalone/.next/server/app/paths.segments/_full.segment.rsc +32 -24
- package/.next/standalone/.next/server/app/paths.segments/_tree.segment.rsc +2 -2
- package/.next/standalone/.next/server/app/paths.segments/paths/__PAGE__.segment.rsc +21 -18
- package/.next/standalone/.next/server/app/profile/page.js +1 -1
- package/.next/standalone/.next/server/app/profile/page.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/profile/page_client-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/app/profile.html +1 -1
- package/.next/standalone/.next/server/app/profile.rsc +32 -24
- package/.next/standalone/.next/server/app/profile.segments/_full.segment.rsc +32 -24
- package/.next/standalone/.next/server/app/profile.segments/_tree.segment.rsc +2 -2
- package/.next/standalone/.next/server/app/profile.segments/profile/__PAGE__.segment.rsc +23 -18
- package/.next/standalone/.next/server/app/queue/page.js +1 -1
- package/.next/standalone/.next/server/app/queue/page.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/queue/page_client-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/app/queue.html +1 -1
- package/.next/standalone/.next/server/app/queue.rsc +32 -24
- package/.next/standalone/.next/server/app/queue.segments/_full.segment.rsc +32 -24
- package/.next/standalone/.next/server/app/queue.segments/_tree.segment.rsc +2 -2
- package/.next/standalone/.next/server/app/queue.segments/queue/__PAGE__.segment.rsc +21 -18
- package/.next/standalone/.next/server/app/scores/page.js +1 -1
- package/.next/standalone/.next/server/app/scores/page.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/scores/page_client-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/app/scores.html +1 -1
- package/.next/standalone/.next/server/app/scores.rsc +32 -24
- package/.next/standalone/.next/server/app/scores.segments/_full.segment.rsc +32 -24
- package/.next/standalone/.next/server/app/scores.segments/_tree.segment.rsc +2 -2
- package/.next/standalone/.next/server/app/scores.segments/scores/__PAGE__.segment.rsc +23 -18
- package/.next/standalone/.next/server/app/settings/page.js +1 -1
- package/.next/standalone/.next/server/app/settings/page.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/settings/page_client-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/app/settings.html +1 -1
- package/.next/standalone/.next/server/app/settings.rsc +32 -24
- package/.next/standalone/.next/server/app/settings.segments/_full.segment.rsc +32 -24
- package/.next/standalone/.next/server/app/settings.segments/_tree.segment.rsc +2 -2
- package/.next/standalone/.next/server/app/settings.segments/settings/__PAGE__.segment.rsc +20 -18
- package/.next/standalone/.next/server/app/setup/page.js +1 -1
- package/.next/standalone/.next/server/app/setup/page.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/setup/page_client-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/app/setup.html +1 -1
- package/.next/standalone/.next/server/app/setup.rsc +32 -24
- package/.next/standalone/.next/server/app/setup.segments/_full.segment.rsc +32 -24
- package/.next/standalone/.next/server/app/setup.segments/_tree.segment.rsc +2 -2
- package/.next/standalone/.next/server/app/setup.segments/setup/__PAGE__.segment.rsc +21 -18
- package/.next/standalone/.next/server/app/social/page.js +1 -1
- package/.next/standalone/.next/server/app/social/page.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/social/page_client-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/app/social.html +1 -1
- package/.next/standalone/.next/server/app/social.rsc +32 -24
- package/.next/standalone/.next/server/app/social.segments/_full.segment.rsc +32 -24
- package/.next/standalone/.next/server/app/social.segments/_tree.segment.rsc +2 -2
- package/.next/standalone/.next/server/app/social.segments/social/__PAGE__.segment.rsc +23 -18
- package/.next/standalone/.next/server/app-paths-manifest.json +4 -0
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__00la_y0._.js +1 -1
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__05_3-22._.js +1 -1
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__066rab1._.js +7 -0
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__07t47cm._.js +1 -1
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__0cj5jqc._.js +1 -1
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__0e0fei3._.js +1 -1
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__0fooke1._.js +7 -0
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__0ljnyho._.js +1 -1
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__0o5-tcg._.js +1 -1
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__0qrnous._.js +1 -1
- package/.next/standalone/.next/server/chunks/{[root-of-the-server]__15wc9e-._.js → [root-of-the-server]__0r-0t-9._.js} +2 -2
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__0ra6xyg._.js +15 -0
- package/.next/standalone/.next/server/chunks/{[root-of-the-server]__20rwfdw._.js → [root-of-the-server]__0rcpjad._.js} +6 -3
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__0t3v1a1._.js +1 -1
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__0t6y79e._.js +7 -0
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__0wmexuc._.js +1 -1
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__0x29muh._.js +7 -0
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__0xu34sz._.js +1 -1
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__133knx1._.js +1 -1
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__15-17hl._.js +1 -1
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__19b7mig._.js +1 -1
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__1a_6x37._.js +8 -0
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__1an_8pa._.js +7 -0
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__1bbcwub._.js +1 -1
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__1ducpz2._.js +3 -0
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__1eris29._.js +1 -1
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__1gjo_cq._.js +1 -1
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__1qcm08_._.js +1 -1
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__1tir0vc._.js +1 -1
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__1w25q0m._.js +1 -1
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__1xhyinn._.js +3 -0
- package/.next/standalone/.next/server/chunks/_072jl0y._.js +1 -1
- package/.next/standalone/.next/server/chunks/_0lw8_i0._.js +1 -1
- package/.next/standalone/.next/server/chunks/_0sqqpzb._.js +3 -0
- package/.next/standalone/.next/server/chunks/_1_fynia._.js +7 -7
- package/.next/standalone/.next/server/chunks/_1fn30_l._.js +1 -1
- package/.next/standalone/.next/server/chunks/_1itd1o_._.js +1 -1
- package/.next/standalone/.next/server/chunks/_1iwkh8t._.js +1 -1
- package/.next/standalone/.next/server/chunks/_next-internal_server_app_api_data_backup_route_actions_0zoj04p.js +3 -0
- package/.next/standalone/.next/server/chunks/_next-internal_server_app_api_data_csv_route_actions_0l6m7lg.js +3 -0
- package/.next/standalone/.next/server/chunks/_next-internal_server_app_api_data_restore_route_actions_0-b05bv.js +3 -0
- package/.next/standalone/.next/server/chunks/lib_02iz_9q._.js +4 -0
- package/.next/standalone/.next/server/chunks/lib_05agvk3._.js +4 -0
- package/.next/standalone/.next/server/chunks/lib_0v84u66._.js +4 -0
- package/.next/standalone/.next/server/chunks/lib_db-client_0_dch35.js +174 -0
- package/.next/standalone/.next/server/chunks/lib_linkedin-export_12imqxg.js +1 -1
- package/.next/standalone/.next/server/chunks/lib_rpc_00nndai.js +3 -0
- package/.next/standalone/.next/server/chunks/lib_rpc_03ibb-x.js +3 -0
- package/.next/standalone/.next/server/chunks/lib_rpc_03ri3ji.js +3 -0
- package/.next/standalone/.next/server/chunks/lib_rpc_078ce48.js +3 -0
- package/.next/standalone/.next/server/chunks/lib_rpc_0a69mgr.js +3 -0
- package/.next/standalone/.next/server/chunks/lib_rpc_0c9d9ti.js +7 -0
- package/.next/standalone/.next/server/chunks/lib_rpc_0cej3t8.js +3 -0
- package/.next/standalone/.next/server/chunks/lib_rpc_0cmh4g6.js +3 -0
- package/.next/standalone/.next/server/chunks/lib_rpc_0nx2_pc.js +3 -0
- package/.next/standalone/.next/server/chunks/lib_rpc_0r79-w1.js +3 -0
- package/.next/standalone/.next/server/chunks/lib_rpc_0t552z6.js +3 -0
- package/.next/standalone/.next/server/chunks/lib_rpc_0yx8ynd.js +3 -0
- package/.next/standalone/.next/server/chunks/lib_rpc_12p-o9-.js +3 -0
- package/.next/standalone/.next/server/chunks/lib_rpc_1466dnb.js +3 -0
- package/.next/standalone/.next/server/chunks/lib_rpc_1sryxv6.js +3 -0
- package/.next/standalone/.next/server/chunks/lib_rpc_1trn-x5.js +3 -0
- package/.next/standalone/.next/server/chunks/lib_rpc_1ygu_mv.js +3 -0
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__0egamyq._.js +3 -0
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__0qd8pzm._.js +3 -0
- package/.next/standalone/.next/server/chunks/ssr/{[root-of-the-server]__0qdeuyo._.js → [root-of-the-server]__1-012q1._.js} +2 -2
- package/.next/standalone/.next/server/chunks/ssr/_04am_h8._.js +3 -0
- package/.next/standalone/.next/server/chunks/ssr/_06rgzfh._.js +3 -0
- package/.next/standalone/.next/server/chunks/ssr/_07zb7lu._.js +3 -0
- package/.next/standalone/.next/server/chunks/ssr/_0_79idq._.js +3 -0
- package/.next/standalone/.next/server/chunks/ssr/_0gds903._.js +3 -0
- package/.next/standalone/.next/server/chunks/ssr/_0hb-dhy._.js +3 -0
- package/.next/standalone/.next/server/chunks/ssr/_0klqt9z._.js +3 -0
- package/.next/standalone/.next/server/chunks/ssr/_14jak5s._.js +7 -0
- package/.next/standalone/.next/server/chunks/ssr/_14nxd3q._.js +3 -0
- package/.next/standalone/.next/server/chunks/ssr/_1cj2yog._.js +3 -0
- package/.next/standalone/.next/server/chunks/ssr/_1fm1ih_._.js +2 -2
- package/.next/standalone/.next/server/chunks/ssr/_1hdqw0-._.js +7 -0
- package/.next/standalone/.next/server/chunks/ssr/_1k2nmbw._.js +2 -2
- package/.next/standalone/.next/server/chunks/ssr/_1r62six._.js +7 -0
- package/.next/standalone/.next/server/chunks/ssr/_next-internal_server_app_insights_page_actions_0-0tf75.js +3 -0
- package/.next/standalone/.next/server/chunks/ssr/app_141w189._.js +1 -1
- package/.next/standalone/.next/server/chunks/ssr/app_components_0uuff77._.js +25 -2
- package/.next/standalone/.next/server/chunks/ssr/app_components_1j3q-h5._.js +25 -2
- package/.next/standalone/.next/server/chunks/ssr/app_components_CompanyScores_1g0mytz.js +1 -1
- package/.next/standalone/.next/server/chunks/ssr/app_components_settings_SectorPicker_1c-29qw.js +1 -1
- package/.next/standalone/.next/server/chunks/ssr/app_components_ui_0pdmz2z.js +3 -0
- package/.next/standalone/.next/server/chunks/ssr/app_import_page_1fmu6_l.js +1 -1
- package/.next/standalone/.next/server/chunks/ssr/app_insights_page_1d_chja.js +3 -0
- package/.next/standalone/.next/server/chunks/ssr/app_launch_page_19t0dyd.js +1 -1
- package/.next/standalone/.next/server/chunks/ssr/app_page_1fazqbf.js +26 -14
- package/.next/standalone/.next/server/chunks/ssr/app_paths_page_1ol90m7.js +2 -2
- package/.next/standalone/.next/server/chunks/ssr/app_profile_page_0u3-l5y.js +1 -1
- package/.next/standalone/.next/server/chunks/ssr/app_queue_page_0c6znd6.js +11 -11
- package/.next/standalone/.next/server/chunks/ssr/app_settings_page_1f8mjj_.js +1 -1
- package/.next/standalone/.next/server/chunks/ssr/app_setup_page_1-282zx.js +12 -13
- package/.next/standalone/.next/server/chunks/ssr/app_social_page_0h7zxda.js +1 -1
- package/.next/standalone/.next/server/chunks/ssr/{lib_1c4ieuw._.js → lib_csv_1ttiu_h.js} +2 -2
- package/.next/standalone/.next/server/chunks/ssr/lib_galaxy-lab_108_lu-.js +1 -1
- package/.next/standalone/.next/server/chunks/ssr/lib_separation_1305zsx.js +3 -0
- package/.next/standalone/.next/server/edge/chunks/[root-of-the-server]__0pco7a6._.js +1 -1
- package/.next/standalone/.next/server/middleware-build-manifest.js +3 -3
- package/.next/standalone/.next/server/middleware-manifest.json +5 -5
- package/.next/standalone/.next/server/next-font-manifest.js +1 -1
- package/.next/standalone/.next/server/next-font-manifest.json +4 -0
- package/.next/standalone/.next/server/pages/404.html +1 -1
- package/.next/standalone/.next/server/pages/500.html +1 -1
- package/.next/standalone/.next/server/prefetch-hints.json +14 -0
- package/.next/standalone/.next/server/server-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/server-reference-manifest.json +1 -1
- package/.next/standalone/.next/static/chunks/02wnf8dkxegxg.js +34 -0
- package/.next/standalone/.next/static/chunks/03-_esd2x_yk6.js +1 -0
- package/.next/standalone/.next/static/chunks/03-demj2iy-0p.js +44 -0
- package/.next/standalone/.next/static/chunks/0838_s6w-i_ik.js +1 -0
- package/.next/standalone/.next/static/chunks/0_1r-3csplxnj.js +1 -0
- package/.next/standalone/.next/static/chunks/0ka4prpk3w9wn.js +34 -0
- package/.next/standalone/.next/static/chunks/0kscsqnvfq3-r.js +1 -0
- package/.next/standalone/.next/static/chunks/0s_xxwp7z88vv.js +1 -0
- package/.next/standalone/.next/static/chunks/1-nnl8amfm4yh.js +57 -0
- package/.next/standalone/.next/static/chunks/112mv-com-mqa.js +21 -0
- package/.next/standalone/.next/static/chunks/1bkt_hhjzvbh8.js +1 -0
- package/.next/standalone/.next/static/chunks/1cmphb3kh2ers.css +3 -0
- package/.next/standalone/.next/static/chunks/1d8yv3k_atka7.js +1 -0
- package/.next/standalone/.next/static/chunks/{0ws7zy0w57ufi.js → 1eyajb9ntzlrl.js} +1 -1
- package/.next/standalone/.next/static/chunks/1z9lb-dbcg4aa.js +1 -0
- package/.next/standalone/.next/static/chunks/23hc51oa4vkhc.js +5 -0
- package/.next/standalone/.next/static/chunks/27n8k9wxlz5-7.js +1 -0
- package/.next/standalone/.next/static/chunks/2q9i7pcxcnph1.js +7 -0
- package/.next/standalone/.next/static/chunks/2w-y83mjlpnse.js +1 -0
- package/.next/standalone/.next/static/chunks/2ws1xf293j-tm.js +5 -0
- package/.next/standalone/.next/static/chunks/2z1-q0_vunbql.js +2 -0
- package/.next/standalone/.next/static/chunks/34g73qhayuevu.js +1 -0
- package/.next/standalone/.next/static/chunks/3cqn-r-y5rrw1.js +5 -0
- package/.next/standalone/.next/static/chunks/3opgg1efrx8q6.js +1 -0
- package/.next/standalone/.next/static/chunks/3p51fpxxi4d5y.js +34 -0
- package/.next/standalone/.next/static/chunks/3y40z6of3r9py.js +1 -0
- package/.next/standalone/.next/static/chunks/403dpflln8ah5.js +1 -0
- package/.next/standalone/.next/static/chunks/43pg2sursiypz.js +1 -0
- package/.next/standalone/CHANGELOG.md +203 -0
- package/.next/standalone/README.md +96 -50
- package/.next/standalone/SECURITY.md +25 -11
- package/.next/standalone/app/api/data/backup/route.js +25 -0
- package/.next/standalone/app/api/data/csv/route.js +74 -0
- package/.next/standalone/app/api/data/export/route.js +1 -1
- package/.next/standalone/app/api/data/restore/route.js +48 -0
- package/.next/standalone/app/api/data/reveal/route.js +19 -6
- package/.next/standalone/app/api/data/route.js +15 -4
- package/.next/standalone/app/api/ingest/route.js +1 -1
- package/.next/standalone/app/api/outreach/route.js +13 -73
- package/.next/standalone/app/api/queue/route.js +1 -1
- package/.next/standalone/app/api/scraper/route.js +217 -36
- package/.next/standalone/app/api/social/crm/route.js +2 -1
- package/.next/standalone/app/components/AppHeader.js +41 -21
- package/.next/standalone/app/components/AppTabs.js +12 -8
- package/.next/standalone/app/components/AutoConnect.js +286 -0
- package/.next/standalone/app/components/AutoScanButton.js +2 -2
- package/.next/standalone/app/components/Avatar.js +1 -1
- package/.next/standalone/app/components/ChainView.js +258 -113
- package/.next/standalone/app/components/CirclePanel.js +16 -16
- package/.next/standalone/app/components/ClusterSpinner.js +64 -0
- package/.next/standalone/app/components/CompanyScores.js +20 -20
- package/.next/standalone/app/components/EmptyState.js +39 -18
- package/.next/standalone/app/components/FieldStep.js +15 -13
- package/.next/standalone/app/components/FilterPanel.js +25 -18
- package/.next/standalone/app/components/ForceGraph.js +49 -14
- package/.next/standalone/app/components/GalaxyLab.js +33 -33
- package/.next/standalone/app/components/GridView.js +18 -18
- package/.next/standalone/app/components/LegacyScoresCard.js +10 -11
- package/.next/standalone/app/components/LinkedInLimits.js +57 -27
- package/.next/standalone/app/components/LiquidGlass.js +99 -0
- package/.next/standalone/app/components/ListView.js +20 -20
- package/.next/standalone/app/components/MapControls.js +5 -5
- package/.next/standalone/app/components/MappingProgress.js +16 -16
- package/.next/standalone/app/components/NoteDetail.js +13 -13
- package/.next/standalone/app/components/OnboardingGate.js +4 -4
- package/.next/standalone/app/components/OutlinkQuest.js +56 -35
- package/.next/standalone/app/components/PathsAnalyzer.js +37 -36
- package/.next/standalone/app/components/PeopleMap.js +21 -21
- package/.next/standalone/app/components/RingsView.js +11 -11
- package/.next/standalone/app/components/ScanRadar.js +84 -39
- package/.next/standalone/app/components/ScanStatusBar.js +40 -21
- package/.next/standalone/app/components/ScanTrail.js +21 -8
- package/.next/standalone/app/components/SeparationView.js +172 -124
- package/.next/standalone/app/components/Sidebar.js +308 -199
- package/.next/standalone/app/components/StaleServerBanner.js +4 -4
- package/.next/standalone/app/components/TheirCircle.js +26 -26
- package/.next/standalone/app/components/ThemeDefs.js +42 -0
- package/.next/standalone/app/components/ThemeLoader.js +20 -1
- package/.next/standalone/app/components/UpdatePanel.js +22 -22
- package/.next/standalone/app/components/UserProvider.js +22 -15
- package/.next/standalone/app/components/insights/Boards.js +275 -0
- package/.next/standalone/app/components/insights/PeopleView.js +266 -0
- package/.next/standalone/app/components/insights/Rail.js +156 -0
- package/.next/standalone/app/components/insights/Report.js +382 -0
- package/.next/standalone/app/components/insights/parts.js +239 -0
- package/.next/standalone/app/components/settings/AppearanceSection.js +47 -24
- package/.next/standalone/app/components/settings/DataSection.js +276 -109
- package/.next/standalone/app/components/settings/NetworkHealthSection.js +13 -13
- package/.next/standalone/app/components/settings/SectorPicker.js +12 -12
- package/.next/standalone/app/components/settings/SectorSection.js +13 -14
- package/.next/standalone/app/components/settings/TierSection.js +9 -9
- package/.next/standalone/app/components/settings/TitleSection.js +11 -11
- package/.next/standalone/app/components/settings/UsageSection.js +360 -0
- package/.next/standalone/app/components/ui.js +8 -8
- package/.next/standalone/app/globals.css +161 -5
- package/.next/standalone/app/import/page.js +94 -38
- package/.next/standalone/app/insights/page.js +220 -0
- package/.next/standalone/app/launch/page.js +5 -5
- package/.next/standalone/app/layout.js +6 -2
- package/.next/standalone/app/page.js +53 -53
- package/.next/standalone/app/paths/page.js +63 -63
- package/.next/standalone/app/profile/page.js +58 -58
- package/.next/standalone/app/queue/page.js +84 -72
- package/.next/standalone/app/scores/page.js +2 -2
- package/.next/standalone/app/settings/page.js +16 -13
- package/.next/standalone/app/setup/page.js +236 -133
- package/.next/standalone/app/social/Crm.js +63 -62
- package/.next/standalone/app/social/SocialHub.js +22 -22
- package/.next/standalone/app/social/Thread.js +7 -7
- package/.next/standalone/app/social/page.js +2 -2
- package/.next/standalone/lib/auto-connect.js +145 -0
- package/.next/standalone/lib/backups.js +458 -0
- package/.next/standalone/lib/chain-layout.js +32 -0
- package/.next/standalone/lib/companies.js +1 -1
- package/.next/standalone/lib/csv-store.js +131 -0
- package/.next/standalone/lib/csv.js +137 -39
- package/.next/standalone/lib/data-folder.js +19 -3
- package/.next/standalone/lib/data-import.js +5 -2
- package/.next/standalone/lib/db-client.js +78 -20
- package/.next/standalone/lib/demo.js +5 -4
- package/.next/standalone/lib/galaxy-export.js +9 -2
- package/.next/standalone/lib/galaxy-lab.js +19 -5
- package/.next/standalone/lib/galaxy-layouts.js +43 -0
- package/.next/standalone/lib/gate.js +10 -4
- package/.next/standalone/lib/in-progress.js +46 -0
- package/.next/standalone/lib/ingest.js +1 -1
- package/.next/standalone/lib/insights-board.js +613 -0
- package/.next/standalone/lib/linkedin-limits.js +240 -14
- package/.next/standalone/lib/liquid-glass.js +59 -0
- package/.next/standalone/lib/notifications.js +13 -0
- package/.next/standalone/lib/requests-client.js +10 -0
- package/.next/standalone/lib/requests.js +124 -0
- package/.next/standalone/lib/scan-pace.js +11 -0
- package/.next/standalone/lib/scan-progress.js +20 -0
- package/.next/standalone/lib/scan-risk.js +44 -0
- package/.next/standalone/lib/scan-state.js +1 -0
- package/.next/standalone/lib/scanner-setup.js +97 -15
- package/.next/standalone/lib/scraper-client.js +35 -8
- package/.next/standalone/lib/search-risk.js +7 -3
- package/.next/standalone/lib/settings-client.js +5 -3
- package/.next/standalone/lib/settings.js +13 -0
- package/.next/standalone/lib/social-store.js +3 -2
- package/.next/standalone/lib/synced-setting.js +46 -0
- package/.next/standalone/lib/theme-store.js +42 -10
- package/.next/standalone/lib/themes.js +111 -21
- package/.next/standalone/lib/usage.js +200 -0
- package/.next/standalone/package-lock.json +2 -2
- package/.next/standalone/package.json +1 -1
- package/.next/standalone/scripts/scrape.py +595 -11
- package/.next/static/chunks/02wnf8dkxegxg.js +34 -0
- package/.next/static/chunks/03-_esd2x_yk6.js +1 -0
- package/.next/static/chunks/03-demj2iy-0p.js +44 -0
- package/.next/static/chunks/0838_s6w-i_ik.js +1 -0
- package/.next/static/chunks/0_1r-3csplxnj.js +1 -0
- package/.next/static/chunks/0ka4prpk3w9wn.js +34 -0
- package/.next/static/chunks/0kscsqnvfq3-r.js +1 -0
- package/.next/static/chunks/0s_xxwp7z88vv.js +1 -0
- package/.next/static/chunks/1-nnl8amfm4yh.js +57 -0
- package/.next/static/chunks/112mv-com-mqa.js +21 -0
- package/.next/static/chunks/1bkt_hhjzvbh8.js +1 -0
- package/.next/static/chunks/1cmphb3kh2ers.css +3 -0
- package/.next/static/chunks/1d8yv3k_atka7.js +1 -0
- package/.next/static/chunks/{0ws7zy0w57ufi.js → 1eyajb9ntzlrl.js} +1 -1
- package/.next/static/chunks/1z9lb-dbcg4aa.js +1 -0
- package/.next/static/chunks/23hc51oa4vkhc.js +5 -0
- package/.next/static/chunks/27n8k9wxlz5-7.js +1 -0
- package/.next/static/chunks/2q9i7pcxcnph1.js +7 -0
- package/.next/static/chunks/2w-y83mjlpnse.js +1 -0
- package/.next/static/chunks/2ws1xf293j-tm.js +5 -0
- package/.next/static/chunks/2z1-q0_vunbql.js +2 -0
- package/.next/static/chunks/34g73qhayuevu.js +1 -0
- package/.next/static/chunks/3cqn-r-y5rrw1.js +5 -0
- package/.next/static/chunks/3opgg1efrx8q6.js +1 -0
- package/.next/static/chunks/3p51fpxxi4d5y.js +34 -0
- package/.next/static/chunks/3y40z6of3r9py.js +1 -0
- package/.next/static/chunks/403dpflln8ah5.js +1 -0
- package/.next/static/chunks/43pg2sursiypz.js +1 -0
- package/CHANGELOG.md +203 -0
- package/README.md +96 -50
- package/SECURITY.md +25 -11
- package/lib/auto-connect.js +145 -0
- package/lib/backups.js +458 -0
- package/lib/chain-layout.js +32 -0
- package/lib/companies.js +1 -1
- package/lib/csv-store.js +131 -0
- package/lib/csv.js +137 -39
- package/lib/data-folder.js +19 -3
- package/lib/data-import.js +5 -2
- package/lib/db-client.js +78 -20
- package/lib/demo.js +5 -4
- package/lib/galaxy-export.js +9 -2
- package/lib/galaxy-lab.js +19 -5
- package/lib/galaxy-layouts.js +43 -0
- package/lib/gate.js +10 -4
- package/lib/in-progress.js +46 -0
- package/lib/ingest.js +1 -1
- package/lib/insights-board.js +613 -0
- package/lib/linkedin-limits.js +240 -14
- package/lib/liquid-glass.js +59 -0
- package/lib/notifications.js +13 -0
- package/lib/requests-client.js +10 -0
- package/lib/requests.js +124 -0
- package/lib/scan-pace.js +11 -0
- package/lib/scan-progress.js +20 -0
- package/lib/scan-risk.js +44 -0
- package/lib/scan-state.js +1 -0
- package/lib/scanner-setup.js +97 -15
- package/lib/scraper-client.js +35 -8
- package/lib/search-risk.js +7 -3
- package/lib/settings-client.js +5 -3
- package/lib/settings.js +13 -0
- package/lib/social-store.js +3 -2
- package/lib/synced-setting.js +46 -0
- package/lib/theme-store.js +42 -10
- package/lib/themes.js +111 -21
- package/lib/usage.js +200 -0
- package/package.json +1 -1
- package/scripts/scrape.py +595 -11
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__0-rnla2._.js +0 -3
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__13dx4sd._.js +0 -8
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__14ou7j5._.js +0 -3
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__16iu0hv._.js +0 -3
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__1kbl21f._.js +0 -3
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__1rphsdk._.js +0 -3
- package/.next/standalone/.next/server/chunks/_02twlca._.js +0 -10
- package/.next/standalone/.next/server/chunks/lib_0851sk0._.js +0 -8
- package/.next/standalone/.next/server/chunks/lib_1q7p2ro._.js +0 -8
- package/.next/standalone/.next/server/chunks/lib_1r6l86l._.js +0 -8
- package/.next/standalone/.next/server/chunks/lib_db-client_15le7cw.js +0 -174
- package/.next/standalone/.next/server/chunks/lib_rpc_04s8mzr.js +0 -3
- package/.next/standalone/.next/server/chunks/lib_rpc_053z7as.js +0 -3
- package/.next/standalone/.next/server/chunks/lib_rpc_0b_-2te.js +0 -3
- package/.next/standalone/.next/server/chunks/lib_rpc_0dhbxdm.js +0 -3
- package/.next/standalone/.next/server/chunks/lib_rpc_0dxlk31.js +0 -3
- package/.next/standalone/.next/server/chunks/lib_rpc_0f8b-qc.js +0 -3
- package/.next/standalone/.next/server/chunks/lib_rpc_0pzie7_.js +0 -3
- package/.next/standalone/.next/server/chunks/lib_rpc_0r76fq_.js +0 -3
- package/.next/standalone/.next/server/chunks/lib_rpc_0ut7pjp.js +0 -3
- package/.next/standalone/.next/server/chunks/lib_rpc_15zyqaz.js +0 -3
- package/.next/standalone/.next/server/chunks/lib_rpc_18zpjtq.js +0 -3
- package/.next/standalone/.next/server/chunks/lib_rpc_1a8xkiz.js +0 -3
- package/.next/standalone/.next/server/chunks/lib_rpc_1e_55xo.js +0 -3
- package/.next/standalone/.next/server/chunks/lib_rpc_1oxfd1_.js +0 -3
- package/.next/standalone/.next/server/chunks/lib_rpc_1s0lod0.js +0 -3
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__08oxiqh._.js +0 -3
- package/.next/standalone/.next/server/chunks/ssr/_03l7vge._.js +0 -3
- package/.next/standalone/.next/server/chunks/ssr/_08g31gm._.js +0 -3
- package/.next/standalone/.next/server/chunks/ssr/_0gk_ofx._.js +0 -3
- package/.next/standalone/.next/server/chunks/ssr/_0nwsf93._.js +0 -3
- package/.next/standalone/.next/server/chunks/ssr/_0vho1lb._.js +0 -3
- package/.next/standalone/.next/server/chunks/ssr/_1-658fq._.js +0 -3
- package/.next/standalone/.next/server/chunks/ssr/_1bc46kz._.js +0 -3
- package/.next/standalone/.next/server/chunks/ssr/_1f_n00p._.js +0 -3
- package/.next/standalone/.next/server/chunks/ssr/_2105jz8._.js +0 -3
- package/.next/standalone/.next/server/chunks/ssr/app_components_0t908t-._.js +0 -3
- package/.next/standalone/.next/static/chunks/02pq76u7y4v9-.js +0 -22
- package/.next/standalone/.next/static/chunks/0cmq0exd4d0h9.js +0 -1
- package/.next/standalone/.next/static/chunks/0i02yxppzds1o.js +0 -1
- package/.next/standalone/.next/static/chunks/0m_p4k-q2qh--.js +0 -1
- package/.next/standalone/.next/static/chunks/0oyslj62jkubd.js +0 -1
- package/.next/standalone/.next/static/chunks/0vo-l8hxneba6.css +0 -3
- package/.next/standalone/.next/static/chunks/0yh8z2tbrc5i_.js +0 -1
- package/.next/standalone/.next/static/chunks/17-rhp8sg4m1b.js +0 -44
- package/.next/standalone/.next/static/chunks/172e10mi-tpo_.js +0 -34
- package/.next/standalone/.next/static/chunks/1ei5vbe2uw6fl.js +0 -1
- package/.next/standalone/.next/static/chunks/1f7_pl_wq7lh3.js +0 -11
- package/.next/standalone/.next/static/chunks/1jzbe7zdx9vbj.js +0 -2
- package/.next/standalone/.next/static/chunks/1m3017gp790pw.js +0 -45
- package/.next/standalone/.next/static/chunks/1t20e8u0st7ep.js +0 -1
- package/.next/standalone/.next/static/chunks/2-ch9rm27eril.js +0 -11
- package/.next/standalone/.next/static/chunks/2ldv-v3s9yaif.js +0 -1
- package/.next/standalone/.next/static/chunks/3bp284gjf7dyq.js +0 -1
- package/.next/standalone/.next/static/chunks/3k1f6clbn3gj3.js +0 -7
- package/.next/standalone/.next/static/chunks/3l4t8je6iguzc.js +0 -1
- package/.next/standalone/.next/static/chunks/3tplzuc9jk-tl.js +0 -1
- package/.next/standalone/.next/static/chunks/42m0bqr8pbovz.js +0 -11
- package/.next/static/chunks/02pq76u7y4v9-.js +0 -22
- package/.next/static/chunks/0cmq0exd4d0h9.js +0 -1
- package/.next/static/chunks/0i02yxppzds1o.js +0 -1
- package/.next/static/chunks/0m_p4k-q2qh--.js +0 -1
- package/.next/static/chunks/0oyslj62jkubd.js +0 -1
- package/.next/static/chunks/0vo-l8hxneba6.css +0 -3
- package/.next/static/chunks/0yh8z2tbrc5i_.js +0 -1
- package/.next/static/chunks/17-rhp8sg4m1b.js +0 -44
- package/.next/static/chunks/172e10mi-tpo_.js +0 -34
- package/.next/static/chunks/1ei5vbe2uw6fl.js +0 -1
- package/.next/static/chunks/1f7_pl_wq7lh3.js +0 -11
- package/.next/static/chunks/1jzbe7zdx9vbj.js +0 -2
- package/.next/static/chunks/1m3017gp790pw.js +0 -45
- package/.next/static/chunks/1t20e8u0st7ep.js +0 -1
- package/.next/static/chunks/2-ch9rm27eril.js +0 -11
- package/.next/static/chunks/2ldv-v3s9yaif.js +0 -1
- package/.next/static/chunks/3bp284gjf7dyq.js +0 -1
- package/.next/static/chunks/3k1f6clbn3gj3.js +0 -7
- package/.next/static/chunks/3l4t8je6iguzc.js +0 -1
- package/.next/static/chunks/3tplzuc9jk-tl.js +0 -1
- package/.next/static/chunks/42m0bqr8pbovz.js +0 -11
- /package/.next/standalone/.next/static/{dQUvvVSXqbkEFC3-CNcwT → 3NCyJyAPDCEYsYTwF1Ieu}/_buildManifest.js +0 -0
- /package/.next/standalone/.next/static/{dQUvvVSXqbkEFC3-CNcwT → 3NCyJyAPDCEYsYTwF1Ieu}/_clientMiddlewareManifest.js +0 -0
- /package/.next/standalone/.next/static/{dQUvvVSXqbkEFC3-CNcwT → 3NCyJyAPDCEYsYTwF1Ieu}/_ssgManifest.js +0 -0
- /package/.next/static/{dQUvvVSXqbkEFC3-CNcwT → 3NCyJyAPDCEYsYTwF1Ieu}/_buildManifest.js +0 -0
- /package/.next/static/{dQUvvVSXqbkEFC3-CNcwT → 3NCyJyAPDCEYsYTwF1Ieu}/_clientMiddlewareManifest.js +0 -0
- /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
|
|
3
|
+
// LinkedIn Connections.csv import, read in the browser.
|
|
4
4
|
//
|
|
5
|
-
//
|
|
6
|
-
//
|
|
7
|
-
//
|
|
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
|
|
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
|
-
// ──
|
|
158
|
-
|
|
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(
|
|
173
|
+
sessionStorage.setItem(SAMPLE_KEY, JSON.stringify({ degree1, degree2, source: 'sample', importedAt: Date.now() }));
|
|
161
174
|
return true;
|
|
162
175
|
} catch {
|
|
163
|
-
return false; //
|
|
176
|
+
return false; // storage full or off
|
|
164
177
|
}
|
|
165
178
|
}
|
|
166
179
|
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
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
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
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
|
-
|
|
192
|
-
|
|
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
|
-
|
|
196
|
-
|
|
197
|
-
|
|
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
|
-
|
|
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
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
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
|
-
|
|
214
|
-
|
|
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,
|
|
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
|
|
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,
|
|
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
|
|
124
|
-
// backups
|
|
125
|
-
//
|
|
126
|
-
//
|
|
127
|
-
//
|
|
128
|
-
// disk) is retried
|
|
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
|
|
169
|
+
export { AUTO_BACKUP_PREFIX };
|
|
131
170
|
|
|
132
|
-
export function backupOnNewVersion(db, {
|
|
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
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
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 {
|
|
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
|
|
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
|
|
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
|
-
|
|
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
|
-
|
|
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(
|
|
86
|
+
ctx.fillText(CREDIT, cw - 16, 24);
|
|
80
87
|
ctx.restore();
|
|
81
88
|
}
|
|
82
89
|
|