six-degrees 0.2.0 → 0.3.0-beta.1
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 +10 -0
- package/.next/standalone/.next/build-manifest.json +3 -3
- package/.next/standalone/.next/prerender-manifest.json +39 -11
- package/.next/standalone/.next/required-server-files.json +4 -1
- package/.next/standalone/.next/routes-manifest.json +60 -0
- package/.next/standalone/.next/server/app/_global-error/page.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/_global-error/page_client-reference-manifest.js +1 -1
- 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.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 +11 -11
- package/.next/standalone/.next/server/app/_not-found.segments/_full.segment.rsc +11 -11
- package/.next/standalone/.next/server/app/_not-found.segments/_not-found/__PAGE__.segment.rsc +9 -9
- package/.next/standalone/.next/server/app/_not-found.segments/_tree.segment.rsc +1 -1
- package/.next/standalone/.next/server/app/api/admin-delete/route.js +3 -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 +3 -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 +3 -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 +3 -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/app-paths-manifest.json +3 -0
- package/.next/standalone/.next/server/app/api/company-scores/legacy/route/build-manifest.json +12 -0
- package/.next/standalone/.next/server/app/api/company-scores/legacy/route/server-reference-manifest.json +4 -0
- package/.next/standalone/.next/server/app/api/company-scores/legacy/route.js +9 -0
- package/.next/standalone/.next/server/app/api/company-scores/legacy/route.js.map +5 -0
- package/.next/standalone/.next/server/app/api/company-scores/legacy/route.js.nft.json +1 -0
- package/.next/standalone/.next/server/app/api/company-scores/legacy/route_client-reference-manifest.js +3 -0
- package/.next/standalone/.next/server/app/api/company-scores/route.js +3 -2
- 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 +3 -2
- package/.next/standalone/.next/server/app/api/connections/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/api/data/export/route/app-paths-manifest.json +3 -0
- package/.next/standalone/.next/server/app/api/data/export/route/build-manifest.json +12 -0
- package/.next/standalone/.next/server/app/api/data/export/route/server-reference-manifest.json +4 -0
- package/.next/standalone/.next/server/app/api/data/export/route.js +7 -0
- package/.next/standalone/.next/server/app/api/data/export/route.js.map +5 -0
- package/.next/standalone/.next/server/app/api/data/export/route.js.nft.json +1 -0
- package/.next/standalone/.next/server/app/api/data/export/route_client-reference-manifest.js +3 -0
- package/.next/standalone/.next/server/app/api/data/import/route/app-paths-manifest.json +3 -0
- package/.next/standalone/.next/server/app/api/data/import/route/build-manifest.json +12 -0
- package/.next/standalone/.next/server/app/api/data/import/route/server-reference-manifest.json +4 -0
- package/.next/standalone/.next/server/app/api/data/import/route.js +8 -0
- package/.next/standalone/.next/server/app/api/data/import/route.js.map +5 -0
- package/.next/standalone/.next/server/app/api/data/import/route.js.nft.json +1 -0
- package/.next/standalone/.next/server/app/api/data/import/route_client-reference-manifest.js +3 -0
- package/.next/standalone/.next/server/app/api/data/restart/route/app-paths-manifest.json +3 -0
- package/.next/standalone/.next/server/app/api/data/restart/route/build-manifest.json +12 -0
- package/.next/standalone/.next/server/app/api/data/restart/route/server-reference-manifest.json +4 -0
- package/.next/standalone/.next/server/app/api/data/restart/route.js +8 -0
- package/.next/standalone/.next/server/app/api/data/restart/route.js.map +5 -0
- package/.next/standalone/.next/server/app/api/data/restart/route.js.nft.json +1 -0
- package/.next/standalone/.next/server/app/api/data/restart/route_client-reference-manifest.js +3 -0
- package/.next/standalone/.next/server/app/api/data/reveal/route/app-paths-manifest.json +3 -0
- package/.next/standalone/.next/server/app/api/data/reveal/route/build-manifest.json +12 -0
- package/.next/standalone/.next/server/app/api/data/reveal/route/server-reference-manifest.json +4 -0
- package/.next/standalone/.next/server/app/api/data/reveal/route.js +7 -0
- package/.next/standalone/.next/server/app/api/data/reveal/route.js.map +5 -0
- package/.next/standalone/.next/server/app/api/data/reveal/route.js.nft.json +1 -0
- package/.next/standalone/.next/server/app/api/data/reveal/route_client-reference-manifest.js +3 -0
- package/.next/standalone/.next/server/app/api/data/route/app-paths-manifest.json +3 -0
- package/.next/standalone/.next/server/app/api/data/route/build-manifest.json +12 -0
- package/.next/standalone/.next/server/app/api/data/route/server-reference-manifest.json +4 -0
- package/.next/standalone/.next/server/app/api/data/route.js +7 -0
- package/.next/standalone/.next/server/app/api/data/route.js.map +5 -0
- package/.next/standalone/.next/server/app/api/data/route.js.nft.json +1 -0
- package/.next/standalone/.next/server/app/api/data/route_client-reference-manifest.js +3 -0
- package/.next/standalone/.next/server/app/api/delete-cluster/route.js +3 -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 +3 -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 +3 -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 -2
- package/.next/standalone/.next/server/app/api/outreach/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/api/queue/route.js +3 -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 +3 -2
- package/.next/standalone/.next/server/app/api/scraper/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/api/settings/route/app-paths-manifest.json +3 -0
- package/.next/standalone/.next/server/app/api/settings/route/build-manifest.json +12 -0
- package/.next/standalone/.next/server/app/api/settings/route/server-reference-manifest.json +4 -0
- package/.next/standalone/.next/server/app/api/settings/route.js +9 -0
- package/.next/standalone/.next/server/app/api/settings/route.js.map +5 -0
- package/.next/standalone/.next/server/app/api/settings/route.js.nft.json +1 -0
- package/.next/standalone/.next/server/app/api/settings/route_client-reference-manifest.js +3 -0
- package/.next/standalone/.next/server/app/api/settings/sector-preview/route/app-paths-manifest.json +3 -0
- package/.next/standalone/.next/server/app/api/settings/sector-preview/route/build-manifest.json +12 -0
- package/.next/standalone/.next/server/app/api/settings/sector-preview/route/server-reference-manifest.json +4 -0
- package/.next/standalone/.next/server/app/api/settings/sector-preview/route.js +8 -0
- package/.next/standalone/.next/server/app/api/settings/sector-preview/route.js.map +5 -0
- package/.next/standalone/.next/server/app/api/settings/sector-preview/route.js.nft.json +1 -0
- package/.next/standalone/.next/server/app/api/settings/sector-preview/route_client-reference-manifest.js +3 -0
- package/.next/standalone/.next/server/app/api/settings/sector-suggestions/route/app-paths-manifest.json +3 -0
- package/.next/standalone/.next/server/app/api/settings/sector-suggestions/route/build-manifest.json +12 -0
- package/.next/standalone/.next/server/app/api/settings/sector-suggestions/route/server-reference-manifest.json +4 -0
- package/.next/standalone/.next/server/app/api/settings/sector-suggestions/route.js +8 -0
- package/.next/standalone/.next/server/app/api/settings/sector-suggestions/route.js.map +5 -0
- package/.next/standalone/.next/server/app/api/settings/sector-suggestions/route.js.nft.json +1 -0
- package/.next/standalone/.next/server/app/api/settings/sector-suggestions/route_client-reference-manifest.js +3 -0
- package/.next/standalone/.next/server/app/api/setup-profile/route.js +3 -2
- package/.next/standalone/.next/server/app/api/setup-profile/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/api/unlock/route.js +3 -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 +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 +3 -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 +3 -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 +2 -1
- package/.next/standalone/.next/server/app/avatars/[file]/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/favicon.ico/route.js +2 -1
- package/.next/standalone/.next/server/app/favicon.ico/route.js.nft.json +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 +13 -13
- package/.next/standalone/.next/server/app/import.segments/_full.segment.rsc +13 -13
- package/.next/standalone/.next/server/app/import.segments/_tree.segment.rsc +1 -1
- package/.next/standalone/.next/server/app/import.segments/import/__PAGE__.segment.rsc +11 -11
- package/.next/standalone/.next/server/app/index.html +1 -1
- package/.next/standalone/.next/server/app/index.rsc +13 -13
- package/.next/standalone/.next/server/app/index.segments/__PAGE__.segment.rsc +11 -11
- package/.next/standalone/.next/server/app/index.segments/_full.segment.rsc +13 -13
- package/.next/standalone/.next/server/app/index.segments/_tree.segment.rsc +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 +13 -13
- package/.next/standalone/.next/server/app/launch.segments/_full.segment.rsc +13 -13
- package/.next/standalone/.next/server/app/launch.segments/_tree.segment.rsc +1 -1
- package/.next/standalone/.next/server/app/launch.segments/launch/__PAGE__.segment.rsc +11 -11
- 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.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 +13 -13
- package/.next/standalone/.next/server/app/paths.segments/_full.segment.rsc +13 -13
- package/.next/standalone/.next/server/app/paths.segments/_tree.segment.rsc +1 -1
- package/.next/standalone/.next/server/app/paths.segments/paths/__PAGE__.segment.rsc +11 -11
- 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 +13 -13
- package/.next/standalone/.next/server/app/profile.segments/_full.segment.rsc +13 -13
- package/.next/standalone/.next/server/app/profile.segments/_tree.segment.rsc +1 -1
- package/.next/standalone/.next/server/app/profile.segments/profile/__PAGE__.segment.rsc +11 -11
- 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 +13 -13
- package/.next/standalone/.next/server/app/queue.segments/_full.segment.rsc +13 -13
- package/.next/standalone/.next/server/app/queue.segments/_tree.segment.rsc +1 -1
- package/.next/standalone/.next/server/app/queue.segments/queue/__PAGE__.segment.rsc +11 -11
- package/.next/standalone/.next/server/app/settings/page/app-paths-manifest.json +3 -0
- package/.next/standalone/.next/server/app/settings/page/build-manifest.json +20 -0
- package/.next/standalone/.next/server/app/settings/page/next-font-manifest.json +11 -0
- package/.next/standalone/.next/server/app/settings/page/react-loadable-manifest.json +1 -0
- package/.next/standalone/.next/server/app/settings/page/server-reference-manifest.json +4 -0
- package/.next/standalone/.next/server/app/settings/page.js +13 -0
- package/.next/standalone/.next/server/app/settings/page.js.map +5 -0
- package/.next/standalone/.next/server/app/settings/page.js.nft.json +1 -0
- package/.next/standalone/.next/server/app/settings/page_client-reference-manifest.js +3 -0
- package/.next/standalone/.next/server/app/settings.html +1 -0
- package/.next/standalone/.next/server/app/settings.meta +26 -0
- package/.next/standalone/.next/server/app/settings.rsc +24 -0
- package/.next/standalone/.next/server/app/settings.segments/_full.segment.rsc +24 -0
- package/.next/standalone/.next/server/app/settings.segments/_tree.segment.rsc +4 -0
- package/.next/standalone/.next/server/app/settings.segments/settings/__PAGE__.segment.rsc +28 -0
- 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 +13 -13
- package/.next/standalone/.next/server/app/setup.segments/_full.segment.rsc +13 -13
- package/.next/standalone/.next/server/app/setup.segments/_tree.segment.rsc +1 -1
- package/.next/standalone/.next/server/app/setup.segments/setup/__PAGE__.segment.rsc +11 -11
- package/.next/standalone/.next/server/app-paths-manifest.json +10 -0
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__0-rnla2._.js +3 -0
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__00la_y0._.js +3 -0
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__07t47cm._.js +3 -0
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__0cj5jqc._.js +3 -0
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__0e0fei3._.js +3 -0
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__0i5hdu4._.js +3 -0
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__0ljcioj._.js +3 -0
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__0ljnyho._.js +3 -0
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__0o5-tcg._.js +3 -0
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__0qrnous._.js +3 -0
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__0t3v1a1._.js +3 -0
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__0uag-k5._.js +8 -0
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__0um1uey._.js +3 -0
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__0wmexuc._.js +3 -0
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__0xu34sz._.js +3 -0
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__133knx1._.js +3 -0
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__14ou7j5._.js +3 -0
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__15-17hl._.js +3 -0
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__16iu0hv._.js +3 -0
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__19b7mig._.js +3 -0
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__1bbcwub._.js +8 -0
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__1eris29._.js +3 -0
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__1gjo_cq._.js +3 -0
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__1kbl21f._.js +3 -0
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__1qcm08_._.js +3 -0
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__1rphsdk._.js +3 -0
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__1t3rugi._.js +3 -0
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__1w25q0m._.js +3 -0
- package/.next/standalone/.next/server/chunks/_072jl0y._.js +3 -0
- package/.next/standalone/.next/server/chunks/_0lw8_i0._.js +3 -0
- package/.next/standalone/.next/server/chunks/_1_fynia._.js +21 -3
- package/.next/standalone/.next/server/chunks/_1fn30_l._.js +3 -0
- package/.next/standalone/.next/server/chunks/_1itd1o_._.js +2 -1
- package/.next/standalone/.next/server/chunks/_1iwkh8t._.js +1 -1
- package/.next/standalone/.next/server/chunks/_1mxn_lb._.js +3 -0
- package/.next/standalone/.next/server/chunks/_next-internal_server_app_api_company-scores_legacy_route_actions_1ncspu_.js +3 -0
- package/.next/standalone/.next/server/chunks/_next-internal_server_app_api_data_export_route_actions_1lkimty.js +3 -0
- package/.next/standalone/.next/server/chunks/_next-internal_server_app_api_data_import_route_actions_1eji0kd.js +3 -0
- package/.next/standalone/.next/server/chunks/_next-internal_server_app_api_data_restart_route_actions_00_-u6o.js +3 -0
- package/.next/standalone/.next/server/chunks/_next-internal_server_app_api_data_reveal_route_actions_0-moqtn.js +3 -0
- package/.next/standalone/.next/server/chunks/_next-internal_server_app_api_data_route_actions_0j0w5ep.js +3 -0
- package/.next/standalone/.next/server/chunks/_next-internal_server_app_api_settings_route_actions_1bpm9ac.js +3 -0
- package/.next/standalone/.next/server/chunks/_next-internal_server_app_api_settings_sector-preview_route_actions_0w79454.js +3 -0
- package/.next/standalone/.next/server/chunks/_next-internal_server_app_api_settings_sector-suggestions_route_actions_1eoqugp.js +3 -0
- package/.next/standalone/.next/server/chunks/lib_db-client_15le7cw.js +155 -0
- package/.next/standalone/.next/server/chunks/{lib_rpc_0mc73lk.js → lib_rpc_00tx2sm.js} +1 -1
- package/.next/standalone/.next/server/chunks/lib_rpc_02-qa4d.js +3 -0
- package/.next/standalone/.next/server/chunks/lib_rpc_02ndsg2.js +3 -0
- package/.next/standalone/.next/server/chunks/lib_rpc_08q5vp6.js +3 -0
- package/.next/standalone/.next/server/chunks/lib_rpc_0_8i3ft.js +3 -0
- package/.next/standalone/.next/server/chunks/lib_rpc_0c9d9ti.js +5 -2
- package/.next/standalone/.next/server/chunks/lib_rpc_0huvw-3.js +3 -0
- package/.next/standalone/.next/server/chunks/lib_rpc_0ip2vdh.js +3 -0
- package/.next/standalone/.next/server/chunks/lib_rpc_0jzisgh.js +3 -0
- package/.next/standalone/.next/server/chunks/lib_rpc_0yi9xvd.js +3 -0
- package/.next/standalone/.next/server/chunks/lib_rpc_1jyhd0o.js +3 -0
- package/.next/standalone/.next/server/chunks/lib_rpc_1kn59-i.js +3 -0
- package/.next/standalone/.next/server/chunks/lib_rpc_1q2jkza.js +3 -0
- package/.next/standalone/.next/server/chunks/lib_rpc_1vpm1sk.js +3 -0
- package/.next/standalone/.next/server/chunks/lib_rpc_1x6p_31.js +3 -0
- package/.next/standalone/.next/server/chunks/node_modules_next_1zc5q0a._.js +158 -0
- package/.next/standalone/.next/server/chunks/ssr/{[root-of-the-server]__0mocm6d._.js → [root-of-the-server]__0an6blh._.js} +3 -3
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__0h1_f_2._.js +1 -1
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__1m0255u._.js +3 -0
- package/.next/standalone/.next/server/chunks/ssr/{[root-of-the-server]__0bipr5s._.js → [root-of-the-server]__1z1j3ek._.js} +2 -2
- package/.next/standalone/.next/server/chunks/ssr/_07u8byv._.js +3 -0
- package/.next/standalone/.next/server/chunks/ssr/_08r_mlf._.js +3 -0
- package/.next/standalone/.next/server/chunks/ssr/{_0ggabjc._.js → _0942v8n._.js} +1 -1
- package/.next/standalone/.next/server/chunks/ssr/{_1djpk8t._.js → _0hl_t7r._.js} +2 -2
- package/.next/standalone/.next/server/chunks/ssr/_0tb83dw._.js +132 -0
- package/.next/standalone/.next/server/chunks/ssr/_1-87bs1._.js +3 -0
- package/.next/standalone/.next/server/chunks/ssr/_17gui6a._.js +1 -1
- package/.next/standalone/.next/server/chunks/ssr/_next-internal_server_app_settings_page_actions_11x4dq5.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_launch_page_19t0dyd.js +2 -2
- package/.next/standalone/.next/server/chunks/ssr/app_page_1fazqbf.js +4 -4
- 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 +5 -5
- package/.next/standalone/.next/server/chunks/ssr/app_settings_page_1f8mjj_.js +3 -0
- package/.next/standalone/.next/server/chunks/ssr/app_setup_page_1-282zx.js +2 -2
- package/.next/standalone/.next/server/chunks/ssr/lib_0i8v-s3._.js +1 -1
- package/.next/standalone/.next/server/chunks/ssr/node_modules_1f8t_rp._.js +23 -0
- package/.next/standalone/.next/server/chunks/ssr/node_modules_1nkgb45._.js +2 -2
- package/.next/standalone/.next/server/chunks/ssr/{node_modules_01xbj_9._.js → node_modules_1wax83z._.js} +3 -3
- package/.next/standalone/.next/server/chunks/ssr/{node_modules_next_dist_00nap8h._.js → node_modules_next_dist_1bunoni._.js} +2 -2
- package/.next/standalone/.next/server/edge/chunks/[root-of-the-server]__0pco7a6._.js +2 -2
- package/.next/standalone/.next/server/middleware-build-manifest.js +3 -3
- package/.next/standalone/.next/server/middleware-manifest.json +15 -7
- 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/06x3jiiz96m5t.js +1 -0
- package/.next/{static/chunks/34at5d2ifl62i.js → standalone/.next/static/chunks/0ngx9s6-zgshe.js} +5 -5
- package/.next/standalone/.next/static/chunks/0q-_khndfxubv.js +2 -0
- package/.next/standalone/.next/static/chunks/1c79veqedvubt.js +1 -0
- package/.next/standalone/.next/static/chunks/1chp3nx45meg5.js +44 -0
- package/.next/standalone/.next/static/chunks/1irqj0lf-fu3d.js +1 -0
- package/.next/standalone/.next/static/chunks/1uadqylrod5_v.js +1 -0
- package/.next/standalone/.next/static/chunks/23u0zclgwpc4d.js +1 -0
- package/.next/standalone/.next/static/chunks/289ktj97di6zg.js +1 -0
- package/.next/standalone/.next/static/chunks/2b3lmf8e6uj8m.js +16 -0
- package/.next/standalone/.next/static/chunks/2jz311xl1pp_8.js +1 -0
- package/.next/standalone/.next/static/chunks/2ot61qsv6_0eq.js +1 -0
- package/.next/standalone/.next/static/chunks/3npq5yd7c4dmn.js +2 -0
- package/.next/standalone/.next/static/frfHFnRYTA0Wjrw8oZJtY/_clientMiddlewareManifest.js +14 -0
- package/.next/standalone/AGENTS.md +10 -0
- package/.next/standalone/CHANGELOG.md +325 -0
- package/.next/standalone/CONTRIBUTING.md +14 -2
- package/.next/standalone/README.md +181 -53
- package/.next/standalone/SECURITY.md +120 -10
- package/.next/standalone/app/api/company-scores/legacy/route.js +32 -0
- package/.next/standalone/app/api/company-scores/route.js +20 -11
- package/.next/standalone/app/api/data/export/route.js +49 -0
- package/.next/standalone/app/api/data/import/route.js +83 -0
- package/.next/standalone/app/api/data/restart/route.js +37 -0
- package/.next/standalone/app/api/data/reveal/route.js +14 -0
- package/.next/standalone/app/api/data/route.js +39 -0
- package/.next/standalone/app/api/ingest/route.js +15 -47
- package/.next/standalone/app/api/scraper/route.js +268 -128
- package/.next/standalone/app/api/settings/route.js +58 -0
- package/.next/standalone/app/api/settings/sector-preview/route.js +38 -0
- package/.next/standalone/app/api/settings/sector-suggestions/route.js +20 -0
- package/.next/standalone/app/api/update/route.js +197 -24
- package/.next/standalone/app/avatars/[file]/route.js +4 -2
- package/.next/standalone/app/components/CompanyScores.js +28 -7
- package/.next/standalone/app/components/EmptyState.js +8 -0
- package/.next/standalone/app/components/ForceGraph.js +40 -36
- package/.next/standalone/app/components/LegacyScoresCard.js +129 -0
- package/.next/standalone/app/components/Sidebar.js +19 -18
- package/.next/standalone/app/components/UpdatePanel.js +317 -99
- package/.next/standalone/app/components/UserProvider.js +4 -3
- package/.next/standalone/app/components/settings/DataSection.js +437 -0
- package/.next/standalone/app/components/settings/SectorSection.js +445 -0
- package/.next/standalone/app/components/ui.js +62 -0
- package/.next/standalone/app/import/page.js +3 -3
- package/.next/standalone/app/launch/page.js +30 -20
- package/.next/standalone/app/layout.js +2 -2
- package/.next/standalone/app/page.js +15 -2
- package/.next/standalone/app/paths/page.js +13 -5
- package/.next/standalone/app/profile/page.js +41 -186
- package/.next/standalone/app/queue/page.js +8 -2
- package/.next/standalone/app/settings/page.js +96 -0
- package/.next/standalone/app/setup/page.js +35 -19
- package/.next/standalone/bin/args.mjs +44 -0
- package/.next/standalone/bin/six-degrees.mjs +16 -17
- package/.next/standalone/install.sh +1 -1
- package/.next/standalone/lib/companies.js +44 -119
- package/.next/standalone/lib/csv.js +61 -27
- package/.next/standalone/lib/data-export.js +170 -0
- package/.next/standalone/lib/data-folder.js +238 -0
- package/.next/standalone/lib/data-import.js +878 -0
- package/.next/standalone/lib/db-client.js +48 -3
- package/.next/standalone/lib/durable.js +73 -0
- package/.next/standalone/lib/gate.js +90 -1
- package/.next/standalone/lib/ingest.js +40 -0
- package/.next/standalone/lib/legacy-offer.js +185 -0
- package/.next/standalone/lib/legacy-scores.js +77 -0
- package/.next/standalone/lib/linkedin-limits.js +124 -1
- package/.next/standalone/lib/release.js +5 -2
- package/.next/standalone/lib/rpc.js +121 -13
- package/.next/standalone/lib/sample-stats.js +16 -0
- package/.next/standalone/lib/scan-progress.js +13 -0
- package/.next/standalone/lib/scan-state.js +53 -0
- package/.next/standalone/lib/scanner-python.js +685 -0
- package/.next/standalone/lib/scanner-setup.js +104 -0
- package/.next/standalone/lib/scoring.js +747 -138
- package/.next/standalone/lib/scraper-client.js +10 -6
- package/.next/standalone/lib/sector-directory.js +1532 -0
- package/.next/standalone/lib/sector-focus.js +163 -0
- package/.next/standalone/lib/sector-labels.js +81 -0
- package/.next/standalone/lib/settings-effects.js +59 -0
- package/.next/standalone/lib/settings.js +83 -0
- package/.next/standalone/lib/updater-job.js +838 -0
- package/.next/standalone/lib/updater.js +494 -0
- package/.next/standalone/middleware.js +25 -28
- package/.next/standalone/next.config.mjs +19 -3
- package/.next/standalone/package-lock.json +103 -9
- package/.next/standalone/package.json +12 -11
- package/.next/standalone/public/demo-data.json +1 -1
- package/.next/standalone/scripts/apply-update.sh +482 -0
- package/.next/standalone/scripts/build-app.mjs +251 -9
- package/.next/standalone/scripts/gen-synthetic.mjs +16 -1
- package/.next/standalone/scripts/readme_buttons.py +89 -0
- package/.next/standalone/scripts/requirements.txt +106 -4
- package/.next/standalone/scripts/screenshots.py +2 -0
- package/.next/standalone/scripts/test-release-server.mjs +143 -0
- package/.next/standalone/server.js +1 -1
- package/.next/static/chunks/06x3jiiz96m5t.js +1 -0
- package/.next/{standalone/.next/static/chunks/34at5d2ifl62i.js → static/chunks/0ngx9s6-zgshe.js} +5 -5
- package/.next/static/chunks/0q-_khndfxubv.js +2 -0
- package/.next/static/chunks/1c79veqedvubt.js +1 -0
- package/.next/static/chunks/1chp3nx45meg5.js +44 -0
- package/.next/static/chunks/1irqj0lf-fu3d.js +1 -0
- package/.next/static/chunks/1uadqylrod5_v.js +1 -0
- package/.next/static/chunks/23u0zclgwpc4d.js +1 -0
- package/.next/static/chunks/289ktj97di6zg.js +1 -0
- package/.next/static/chunks/2b3lmf8e6uj8m.js +16 -0
- package/.next/static/chunks/2jz311xl1pp_8.js +1 -0
- package/.next/static/chunks/2ot61qsv6_0eq.js +1 -0
- package/.next/static/chunks/3npq5yd7c4dmn.js +2 -0
- package/.next/static/frfHFnRYTA0Wjrw8oZJtY/_clientMiddlewareManifest.js +14 -0
- package/CHANGELOG.md +325 -0
- package/README.md +181 -53
- package/SECURITY.md +120 -10
- package/bin/args.mjs +44 -0
- package/bin/six-degrees.mjs +16 -17
- package/lib/companies.js +44 -119
- package/lib/csv.js +61 -27
- package/lib/data-export.js +170 -0
- package/lib/data-folder.js +238 -0
- package/lib/data-import.js +878 -0
- package/lib/db-client.js +48 -3
- package/lib/durable.js +73 -0
- package/lib/gate.js +90 -1
- package/lib/ingest.js +40 -0
- package/lib/legacy-offer.js +185 -0
- package/lib/legacy-scores.js +77 -0
- package/lib/linkedin-limits.js +124 -1
- package/lib/release.js +5 -2
- package/lib/rpc.js +121 -13
- package/lib/sample-stats.js +16 -0
- package/lib/scan-progress.js +13 -0
- package/lib/scan-state.js +53 -0
- package/lib/scanner-python.js +685 -0
- package/lib/scanner-setup.js +104 -0
- package/lib/scoring.js +747 -138
- package/lib/scraper-client.js +10 -6
- package/lib/sector-directory.js +1532 -0
- package/lib/sector-focus.js +163 -0
- package/lib/sector-labels.js +81 -0
- package/lib/settings-effects.js +59 -0
- package/lib/settings.js +83 -0
- package/lib/updater-job.js +838 -0
- package/lib/updater.js +494 -0
- package/package.json +12 -11
- package/public/demo-data.json +1 -1
- package/scripts/requirements.txt +106 -4
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__0jrmmj-._.js +0 -150
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__0qx548g._.js +0 -151
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__1an3leo._.js +0 -150
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__1m8zedk._.js +0 -155
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__1zor0ys._.js +0 -3
- package/.next/standalone/.next/server/chunks/_0_rp-01._.js +0 -3
- package/.next/standalone/.next/server/chunks/_0hzdk79._.js +0 -3
- package/.next/standalone/.next/server/chunks/_0ow7u5r._.js +0 -3
- package/.next/standalone/.next/server/chunks/_0t0zc2d._.js +0 -3
- package/.next/standalone/.next/server/chunks/_0wa631d._.js +0 -3
- package/.next/standalone/.next/server/chunks/_13ccnao._.js +0 -3
- package/.next/standalone/.next/server/chunks/_13es063._.js +0 -3
- package/.next/standalone/.next/server/chunks/_142872j._.js +0 -3
- package/.next/standalone/.next/server/chunks/_18wsb_a._.js +0 -8
- package/.next/standalone/.next/server/chunks/_1e-4h5h._.js +0 -3
- package/.next/standalone/.next/server/chunks/_1gvvd7n._.js +0 -158
- package/.next/standalone/.next/server/chunks/_1moda66._.js +0 -3
- package/.next/standalone/.next/server/chunks/_1p6ghzv._.js +0 -3
- package/.next/standalone/.next/server/chunks/_1xmmi_v._.js +0 -3
- package/.next/standalone/.next/server/chunks/_1z-yrlf._.js +0 -3
- package/.next/standalone/.next/server/chunks/ssr/_0bf3x4q._.js +0 -3
- package/.next/standalone/.next/server/chunks/ssr/app_paths_page_1ol90m7.js +0 -4
- package/.next/standalone/.next/static/N9wokeIiC9rUIGmzBhj6T/_clientMiddlewareManifest.js +0 -6
- package/.next/standalone/.next/static/chunks/1odow92u6wxz0.js +0 -1
- package/.next/standalone/.next/static/chunks/1wb_is4wsdm-u.js +0 -1
- package/.next/standalone/.next/static/chunks/1zmpcmngg5c7-.js +0 -2
- package/.next/standalone/.next/static/chunks/220-ne82aus0c.js +0 -44
- package/.next/standalone/.next/static/chunks/2rrf5kzx2fhin.js +0 -2
- package/.next/standalone/.next/static/chunks/2s_k9x4d0gi9h.js +0 -16
- package/.next/standalone/.next/static/chunks/3hsi90cejq2dg.js +0 -1
- package/.next/standalone/.next/static/chunks/3pfyuezyqd9ob.js +0 -1
- package/.next/standalone/.next/static/chunks/3ts-_4i6bfkh2.js +0 -1
- package/.next/standalone/scripts/score-connections.sql +0 -80
- package/.next/standalone/scripts/score_new_connections.sql +0 -77
- package/.next/static/N9wokeIiC9rUIGmzBhj6T/_clientMiddlewareManifest.js +0 -6
- package/.next/static/chunks/1odow92u6wxz0.js +0 -1
- package/.next/static/chunks/1wb_is4wsdm-u.js +0 -1
- package/.next/static/chunks/1zmpcmngg5c7-.js +0 -2
- package/.next/static/chunks/220-ne82aus0c.js +0 -44
- package/.next/static/chunks/2rrf5kzx2fhin.js +0 -2
- package/.next/static/chunks/2s_k9x4d0gi9h.js +0 -16
- package/.next/static/chunks/3hsi90cejq2dg.js +0 -1
- package/.next/static/chunks/3pfyuezyqd9ob.js +0 -1
- package/.next/static/chunks/3ts-_4i6bfkh2.js +0 -1
- package/scripts/score_new_connections.sql +0 -77
- /package/.next/standalone/.next/static/{N9wokeIiC9rUIGmzBhj6T → frfHFnRYTA0Wjrw8oZJtY}/_buildManifest.js +0 -0
- /package/.next/standalone/.next/static/{N9wokeIiC9rUIGmzBhj6T → frfHFnRYTA0Wjrw8oZJtY}/_ssgManifest.js +0 -0
- /package/.next/static/{N9wokeIiC9rUIGmzBhj6T → frfHFnRYTA0Wjrw8oZJtY}/_buildManifest.js +0 -0
- /package/.next/static/{N9wokeIiC9rUIGmzBhj6T → frfHFnRYTA0Wjrw8oZJtY}/_ssgManifest.js +0 -0
|
@@ -12,12 +12,14 @@
|
|
|
12
12
|
//
|
|
13
13
|
// What this removes: installing Node, cloning, npm install, and typing a
|
|
14
14
|
// command. The Node runtime is bundled, so the app has no prerequisites at all
|
|
15
|
-
// for the CSV path — download, double-click, drop in your export.
|
|
15
|
+
// for the CSV path — download, double-click, drop in your export. The Electron
|
|
16
|
+
// app also carries the scanner's own Python with its packages installed
|
|
17
|
+
// (bundlePython, DESKTOP.md D2), so scanning needs no install step either.
|
|
16
18
|
//
|
|
17
|
-
// What it does NOT remove:
|
|
18
|
-
//
|
|
19
|
-
//
|
|
20
|
-
//
|
|
19
|
+
// What it does NOT remove: Google Chrome, which the scanner drives. It stays a
|
|
20
|
+
// runtime prerequisite and the Scan page already detects it. Bundling a
|
|
21
|
+
// Chromium instead would make the scanner MORE detectable, not less, which
|
|
22
|
+
// defeats the point of driving the user's real browser.
|
|
21
23
|
//
|
|
22
24
|
// Unsigned, because notarisation needs a paid Apple Developer account. macOS
|
|
23
25
|
// will refuse the first launch; the user allows it once in System Settings.
|
|
@@ -25,13 +27,24 @@
|
|
|
25
27
|
// separate "app is damaged" failure that unsigned arm64 binaries otherwise hit.
|
|
26
28
|
|
|
27
29
|
import { execFileSync } from 'node:child_process';
|
|
28
|
-
import {
|
|
30
|
+
import { createHash } from 'node:crypto';
|
|
31
|
+
import {
|
|
32
|
+
mkdirSync, rmSync, cpSync, writeFileSync, existsSync, chmodSync, readFileSync, symlinkSync, lstatSync, renameSync,
|
|
33
|
+
readlinkSync, readdirSync, openSync, readSync, closeSync, realpathSync,
|
|
34
|
+
} from 'node:fs';
|
|
29
35
|
import path from 'node:path';
|
|
30
36
|
import os from 'node:os';
|
|
31
37
|
import { fileURLToPath } from 'node:url';
|
|
38
|
+
import {
|
|
39
|
+
standaloneBuild, downloadVerified, machoSlices, machoSlice, megabytes, IMPORTS,
|
|
40
|
+
} from '../lib/scanner-python.js';
|
|
32
41
|
|
|
33
42
|
const ROOT = path.resolve(path.dirname(fileURLToPath(import.meta.url)), '..');
|
|
34
43
|
const pkg = JSON.parse(readFileSync(path.join(ROOT, 'package.json'), 'utf8'));
|
|
44
|
+
// The oldest macOS the app runs on: the bundled Node 24 needs 13.5 (Electron
|
|
45
|
+
// itself needs 13). Written into Info.plist, and every program in the bundled
|
|
46
|
+
// Python is checked against it (checkPython).
|
|
47
|
+
const MACOS_MIN = '13.5';
|
|
35
48
|
|
|
36
49
|
const NODE_VERSION = process.env.BUNDLE_NODE || 'v24.21.0';
|
|
37
50
|
const ARCH = process.env.BUNDLE_ARCH || (os.arch() === 'x64' ? 'x64' : 'arm64');
|
|
@@ -134,9 +147,13 @@ try {
|
|
|
134
147
|
for (const rel of untracked) console.log(` ${rel}`);
|
|
135
148
|
}
|
|
136
149
|
} catch { /* not a git checkout: nothing to compare against */ }
|
|
137
|
-
// The
|
|
150
|
+
// The files the app runs from scripts/, copied by name so the app never
|
|
151
|
+
// depends on what Next's tracing happens to bring along (TRAPS §27): the
|
|
152
|
+
// scanner the Scan page runs, and apply-update.sh, the in-app updater's helper.
|
|
153
|
+
// The helper ships inside the app, so the version that swaps the app is the one
|
|
154
|
+
// the user is running, never a script fetched from the main branch.
|
|
138
155
|
for (const rel of ['scripts/scrape.py', 'scripts/image_store.py', 'scripts/requirements.txt',
|
|
139
|
-
'scripts/
|
|
156
|
+
'scripts/audit-avatars.mjs', 'scripts/apply-update.sh']) {
|
|
140
157
|
const from = path.join(ROOT, rel);
|
|
141
158
|
if (existsSync(from)) {
|
|
142
159
|
mkdirSync(path.join(SERVER_DIR, path.dirname(rel)), { recursive: true });
|
|
@@ -171,6 +188,8 @@ export SIX_DEGREES_BIND=127.0.0.1
|
|
|
171
188
|
export NEXT_TELEMETRY_DISABLED=1
|
|
172
189
|
export SIX_DEGREES_ROOT="$HERE/app"
|
|
173
190
|
export SIX_DEGREES_INSTALL=mac-app
|
|
191
|
+
# This app's own bundle, for the in-app updater (lib/updater.js runningBundle).
|
|
192
|
+
export SIX_DEGREES_APP="$(cd "$HERE/../.." && pwd)"
|
|
174
193
|
export HOSTNAME=127.0.0.1
|
|
175
194
|
|
|
176
195
|
# Walk up from 6363 so a second copy does not fight the first.
|
|
@@ -308,7 +327,7 @@ async function buildElectronShell() {
|
|
|
308
327
|
darwinDarkModeSupport: true,
|
|
309
328
|
// The bundled Node 24 needs macOS 13.5 (Electron itself needs 13), so say
|
|
310
329
|
// so, and macOS explains it instead of the app failing to start.
|
|
311
|
-
extendInfo: { LSMinimumSystemVersion:
|
|
330
|
+
extendInfo: { LSMinimumSystemVersion: MACOS_MIN },
|
|
312
331
|
osxSign: false, // signed ad hoc below, after everything is in place
|
|
313
332
|
});
|
|
314
333
|
console.log(` Electron ${electronVersion} (${ARCH})`);
|
|
@@ -316,14 +335,237 @@ async function buildElectronShell() {
|
|
|
316
335
|
renameSync(path.join(built, `${APP_NAME}.app`), APP);
|
|
317
336
|
rmSync(STAGE, { recursive: true, force: true });
|
|
318
337
|
|
|
338
|
+
// Put straight into the finished app, so its links are made where they stay
|
|
339
|
+
// and nothing copies them again (TRAPS §37).
|
|
340
|
+
await bundlePython(path.join(APP, 'Contents', 'Resources'));
|
|
341
|
+
|
|
319
342
|
step('Signing (ad-hoc)');
|
|
320
343
|
// Electron's framework and helpers must all carry the same kind of signature,
|
|
321
344
|
// or macOS refuses to load them; re-signing the whole bundle ad hoc does that.
|
|
345
|
+
// --deep reaches nested bundles, not loose programs and libraries in
|
|
346
|
+
// Resources: the Python's were signed one by one first (signPython), and this
|
|
347
|
+
// seals them into the app's signature with everything else.
|
|
322
348
|
run('codesign', ['--force', '--deep', '--sign', '-', APP]);
|
|
323
349
|
run('codesign', ['--verify', '--deep', '--strict', APP]);
|
|
324
350
|
console.log(' signed ad-hoc and verified — no Apple account needed, still unnotarised');
|
|
325
351
|
}
|
|
326
352
|
|
|
353
|
+
// ---- the scanner's Python (Electron app only; DESKTOP.md D2) ------------------
|
|
354
|
+
// A standalone CPython from python-build-standalone, with the scanner's packages
|
|
355
|
+
// installed, at Contents/Resources/python. desktop/main.mjs names it to the
|
|
356
|
+
// server (SIX_DEGREES_PYTHON), which runs the scanner on it before any other
|
|
357
|
+
// Python: no install step, and scanning works offline.
|
|
358
|
+
//
|
|
359
|
+
// Pinned twice: the Python by the release and SHA-256 in lib/scanner-python.js,
|
|
360
|
+
// the packages by the hash of every file in scripts/requirements.txt. Downloads
|
|
361
|
+
// are cached in ~/.cache/six-degrees-build like Node's, and checked every build.
|
|
362
|
+
// Built on a Mac with the same chip (release.yml has one job per chip): pip runs
|
|
363
|
+
// this Python to install into it.
|
|
364
|
+
async function bundlePython(resources) {
|
|
365
|
+
const build = standaloneBuild(`darwin-${ARCH}`);
|
|
366
|
+
const xy = build.version.split('.').slice(0, 2).join('.');
|
|
367
|
+
const py = path.join(resources, 'python');
|
|
368
|
+
const lib = path.join(py, 'lib', `python${xy}`);
|
|
369
|
+
|
|
370
|
+
step(`Fetching Python ${build.version} (${ARCH})`);
|
|
371
|
+
const archive = path.join(CACHE, build.file);
|
|
372
|
+
if (existsSync(archive) && sha256File(archive) === build.sha256) {
|
|
373
|
+
console.log(' using the cached download (its SHA-256 matches the pinned one)');
|
|
374
|
+
} else {
|
|
375
|
+
rmSync(archive, { force: true });
|
|
376
|
+
await downloadVerified(build.url, archive, { sha256: build.sha256, size: build.size, idleMs: 60000 });
|
|
377
|
+
console.log(` downloaded ${megabytes(build.size)} MB; its SHA-256 matches the pinned one`);
|
|
378
|
+
}
|
|
379
|
+
rmSync(py, { recursive: true, force: true });
|
|
380
|
+
run('tar', ['-xzf', archive, '-C', resources]);
|
|
381
|
+
const python = path.join(py, 'bin', 'python3');
|
|
382
|
+
// Only this Python's own packages and settings: nothing from the build
|
|
383
|
+
// machine's user site-packages, PYTHONPATH or pip configuration.
|
|
384
|
+
const env = {
|
|
385
|
+
HOME: os.homedir(), TMPDIR: os.tmpdir(), PATH: '/usr/bin:/bin:/usr/sbin:/sbin', LANG: 'en_US.UTF-8',
|
|
386
|
+
PYTHONNOUSERSITE: '1', PYTHONDONTWRITEBYTECODE: '1',
|
|
387
|
+
};
|
|
388
|
+
try {
|
|
389
|
+
execFileSync(python, ['-c', 'pass'], { env, stdio: 'ignore' });
|
|
390
|
+
} catch {
|
|
391
|
+
console.error(`\n ✗ The ${ARCH} Python can't run on this Mac. Build on a Mac with that chip (release.yml does), or install Rosetta for an Intel build.\n`);
|
|
392
|
+
process.exit(1);
|
|
393
|
+
}
|
|
394
|
+
|
|
395
|
+
step('Installing the scanner\'s packages into it');
|
|
396
|
+
run(python, ['-s', '-m', 'pip', '--isolated', 'install', '--disable-pip-version-check', '--no-input',
|
|
397
|
+
'--no-warn-script-location', '--no-compile', '--index-url', 'https://pypi.org/simple',
|
|
398
|
+
'--cache-dir', path.join(CACHE, 'pip'), '--require-hashes', '--only-binary', ':all:',
|
|
399
|
+
'-r', path.join(ROOT, 'scripts', 'requirements.txt')], { env });
|
|
400
|
+
run(python, ['-s', '-m', 'pip', '--isolated', 'check', '--disable-pip-version-check'], { env });
|
|
401
|
+
|
|
402
|
+
const full = duKb(py);
|
|
403
|
+
trimPython(py, lib, xy);
|
|
404
|
+
const trimmed = duKb(py);
|
|
405
|
+
const shared = shareDriverNode(lib, resources);
|
|
406
|
+
signPython(py);
|
|
407
|
+
checkPython(py, lib, env);
|
|
408
|
+
console.log(` Python ${build.version} and the scanner's packages: ${Math.round(full / 1024)} MB installed, `
|
|
409
|
+
+ `${Math.round(trimmed / 1024)} MB after trimming, ${Math.round(duKb(py) / 1024)} MB in the app`
|
|
410
|
+
+ (shared ? ' (Playwright runs on the app\'s own Node)' : ''));
|
|
411
|
+
}
|
|
412
|
+
|
|
413
|
+
function sha256File(file) {
|
|
414
|
+
return createHash('sha256').update(readFileSync(file)).digest('hex');
|
|
415
|
+
}
|
|
416
|
+
|
|
417
|
+
function duKb(dir) {
|
|
418
|
+
return Number.parseInt(execFileSync('du', ['-sk', dir]).toString(), 10) || 0;
|
|
419
|
+
}
|
|
420
|
+
|
|
421
|
+
// Every file under `dir`, not following links.
|
|
422
|
+
function* walk(dir) {
|
|
423
|
+
for (const entry of readdirSync(dir, { withFileTypes: true })) {
|
|
424
|
+
const at = path.join(dir, entry.name);
|
|
425
|
+
if (entry.isDirectory()) yield* walk(at);
|
|
426
|
+
else yield { at, entry };
|
|
427
|
+
}
|
|
428
|
+
}
|
|
429
|
+
|
|
430
|
+
// The Mach-O programs and libraries under `dir`, as { file, slices, head }.
|
|
431
|
+
function machoFiles(dir) {
|
|
432
|
+
const found = [];
|
|
433
|
+
for (const { at, entry } of walk(dir)) {
|
|
434
|
+
if (!entry.isFile()) continue;
|
|
435
|
+
const head = readAt(at, 0, 65536);
|
|
436
|
+
const slices = machoSlices(head);
|
|
437
|
+
if (slices.length) found.push({ file: at, slices });
|
|
438
|
+
}
|
|
439
|
+
return found;
|
|
440
|
+
}
|
|
441
|
+
|
|
442
|
+
function readAt(file, offset, length) {
|
|
443
|
+
const fd = openSync(file, 'r');
|
|
444
|
+
try {
|
|
445
|
+
const buf = Buffer.alloc(length);
|
|
446
|
+
const n = readSync(fd, buf, 0, length, offset);
|
|
447
|
+
return buf.subarray(0, n);
|
|
448
|
+
} finally {
|
|
449
|
+
closeSync(fd);
|
|
450
|
+
}
|
|
451
|
+
}
|
|
452
|
+
|
|
453
|
+
// What the scanner never uses, taken out to keep the download small. None of
|
|
454
|
+
// it is imported by scrape.py or its packages (checkPython proves the imports
|
|
455
|
+
// still load, and CI runs the scanner's pure functions on this Python):
|
|
456
|
+
// - bin/ keeps only the interpreter. pip's console scripts (idna, normalizer,
|
|
457
|
+
// playwright) name the build machine's path in their first line, and pip
|
|
458
|
+
// itself goes below: nothing installs into the app once it is built.
|
|
459
|
+
// - IDLE, tkinter and Tcl/Tk, turtle, lib2to3, ensurepip, the C headers and
|
|
460
|
+
// build files, man pages, test suites, and bytecode: without
|
|
461
|
+
// __pycache__ a module is compiled as it is imported (about 0.3 s for the
|
|
462
|
+
// scanner's), and ownPythonEnv never lets it write any into the app.
|
|
463
|
+
// - libpython's shared library: the interpreter has Python built in, so it is
|
|
464
|
+
// kept only if something inside links to it.
|
|
465
|
+
function trimPython(py, lib, xy) {
|
|
466
|
+
step('Trimming what the scanner never uses');
|
|
467
|
+
const keepInBin = new Set([`python${xy}`, 'python3', 'python']);
|
|
468
|
+
for (const name of readdirSync(path.join(py, 'bin'))) {
|
|
469
|
+
if (!keepInBin.has(name)) rmSync(path.join(py, 'bin', name), { recursive: true, force: true });
|
|
470
|
+
}
|
|
471
|
+
const remove = [
|
|
472
|
+
'include', 'share', 'lib/pkgconfig',
|
|
473
|
+
...readdirSync(path.join(py, 'lib')).filter((n) => /^(libtcl|libtk|tcl|tk|itcl|thread)/.test(n)).map((n) => `lib/${n}`),
|
|
474
|
+
...['idlelib', 'tkinter', 'turtledemo', 'turtle.py', 'lib2to3', 'ensurepip', 'test', 'idle_test', `config-${xy}-darwin`]
|
|
475
|
+
.map((n) => path.relative(py, path.join(lib, n))),
|
|
476
|
+
...readdirSync(path.join(lib, 'lib-dynload')).filter((n) => n.startsWith('_tkinter.')).map((n) => path.relative(py, path.join(lib, 'lib-dynload', n))),
|
|
477
|
+
...readdirSync(path.join(lib, 'site-packages')).filter((n) => n === 'pip' || /^pip-.*\.dist-info$/.test(n))
|
|
478
|
+
.map((n) => path.relative(py, path.join(lib, 'site-packages', n))),
|
|
479
|
+
];
|
|
480
|
+
for (const rel of remove) rmSync(path.join(py, rel), { recursive: true, force: true });
|
|
481
|
+
for (const dir of [...findDirs(py, (n) => n === '__pycache__'), ...findDirs(path.join(lib, 'site-packages'), (n) => n === 'tests')]) {
|
|
482
|
+
rmSync(dir, { recursive: true, force: true });
|
|
483
|
+
}
|
|
484
|
+
const libpython = path.join(py, 'lib', `libpython${xy}.dylib`);
|
|
485
|
+
if (existsSync(libpython)) {
|
|
486
|
+
const users = machoFiles(py).filter((m) => m.file !== libpython
|
|
487
|
+
&& m.slices.some((s) => (machoSlice(readAt(m.file, s.offset, 65536)) || { dylibs: [] }).dylibs.some((d) => d.endsWith(`/libpython${xy}.dylib`))));
|
|
488
|
+
if (users.length) console.log(` keeping libpython${xy}.dylib: ${path.relative(py, users[0].file)} links to it`);
|
|
489
|
+
else rmSync(libpython);
|
|
490
|
+
}
|
|
491
|
+
}
|
|
492
|
+
|
|
493
|
+
function findDirs(dir, match) {
|
|
494
|
+
const found = [];
|
|
495
|
+
for (const entry of readdirSync(dir, { withFileTypes: true })) {
|
|
496
|
+
if (!entry.isDirectory()) continue;
|
|
497
|
+
const at = path.join(dir, entry.name);
|
|
498
|
+
if (match(entry.name)) found.push(at);
|
|
499
|
+
else found.push(...findDirs(at, match));
|
|
500
|
+
}
|
|
501
|
+
return found;
|
|
502
|
+
}
|
|
503
|
+
|
|
504
|
+
// Playwright's driver carries its own Node (about 120 MB). When that is byte
|
|
505
|
+
// for byte the Node the app already bundles for its server (Playwright 1.63
|
|
506
|
+
// ships Node 24.21.0, the version build-app pins), the driver's becomes a link
|
|
507
|
+
// to the app's: the same program, about 40 MB less to download. When they
|
|
508
|
+
// differ, the driver keeps its own. Resolves whether it shared.
|
|
509
|
+
function shareDriverNode(lib, resources) {
|
|
510
|
+
const driverNode = path.join(lib, 'site-packages', 'playwright', 'driver', 'node');
|
|
511
|
+
const appNode = path.join(resources, 'node');
|
|
512
|
+
if (!existsSync(driverNode) || !existsSync(appNode)) return false;
|
|
513
|
+
if (sha256File(driverNode) !== sha256File(appNode)) {
|
|
514
|
+
console.log(' Playwright\'s Node differs from the app\'s, so the driver keeps its own');
|
|
515
|
+
return false;
|
|
516
|
+
}
|
|
517
|
+
rmSync(driverNode);
|
|
518
|
+
symlinkSync(path.relative(path.dirname(driverNode), appNode), driverNode);
|
|
519
|
+
if (realpathSync(driverNode) !== realpathSync(appNode)) throw new Error('The driver\'s link to the app\'s Node is wrong.');
|
|
520
|
+
return true;
|
|
521
|
+
}
|
|
522
|
+
|
|
523
|
+
// Every program and library in the Python, signed ad hoc like the rest of the
|
|
524
|
+
// app. On Apple Silicon unsigned code isn't allowed to run at all.
|
|
525
|
+
function signPython(py) {
|
|
526
|
+
const files = machoFiles(py).map((m) => m.file);
|
|
527
|
+
for (let i = 0; i < files.length; i += 64) {
|
|
528
|
+
// Its only chatter is "replacing existing signature", once a file.
|
|
529
|
+
mustRun('codesign', ['--force', '--sign', '-', ...files.slice(i, i + 64)], process.env, 'Signing the app\'s Python failed');
|
|
530
|
+
}
|
|
531
|
+
console.log(` signed ${files.length} programs and libraries ad hoc`);
|
|
532
|
+
}
|
|
533
|
+
|
|
534
|
+
// The Python as the app will run it: every program is for this chip and this
|
|
535
|
+
// app's oldest macOS, the imports load (the compiled parts too: TRAPS §30), and
|
|
536
|
+
// Playwright's driver starts. Any failure fails the build.
|
|
537
|
+
function checkPython(py, lib, env) {
|
|
538
|
+
step('Checking the Python inside the app');
|
|
539
|
+
const newer = (v) => {
|
|
540
|
+
const [a, b] = [String(v).split('.').map(Number), MACOS_MIN.split('.').map(Number)];
|
|
541
|
+
return (a[0] - b[0] || (a[1] || 0) - (b[1] || 0)) > 0;
|
|
542
|
+
};
|
|
543
|
+
for (const m of machoFiles(py)) {
|
|
544
|
+
const slice = m.slices.find((s) => s.arch === ARCH);
|
|
545
|
+
const rel = path.relative(py, m.file);
|
|
546
|
+
if (!slice) throw new Error(`${rel} isn't built for ${ARCH}.`);
|
|
547
|
+
const info = machoSlice(readAt(m.file, slice.offset, 65536));
|
|
548
|
+
if (info?.minos && newer(info.minos)) throw new Error(`${rel} needs macOS ${info.minos}; the app promises ${MACOS_MIN}.`);
|
|
549
|
+
}
|
|
550
|
+
const python = path.join(py, 'bin', 'python3');
|
|
551
|
+
console.log(` ${mustRun(python, ['-s', '-c', `${IMPORTS}; import sys; from importlib.metadata import version as v; `
|
|
552
|
+
+ 'print("Python", sys.version.split()[0], "· Playwright", v("playwright"), "· requests", v("requests"), "· Pillow", v("pillow"))'],
|
|
553
|
+
env, 'The scanner\'s packages don\'t load in the app\'s Python')}`);
|
|
554
|
+
const driver = path.join(lib, 'site-packages', 'playwright', 'driver');
|
|
555
|
+
console.log(` Playwright's driver starts: ${mustRun(path.join(driver, 'node'), [path.join(driver, 'package', 'cli.js'), '--version'],
|
|
556
|
+
env, 'Playwright\'s driver doesn\'t start')}`);
|
|
557
|
+
}
|
|
558
|
+
|
|
559
|
+
// What a check printed, or the build stops with what went wrong.
|
|
560
|
+
function mustRun(file, args, env, what) {
|
|
561
|
+
try {
|
|
562
|
+
return execFileSync(file, args, { env, stdio: ['ignore', 'pipe', 'pipe'] }).toString().trim();
|
|
563
|
+
} catch (err) {
|
|
564
|
+
console.error(`\n ✗ ${what}:\n${String(err.stderr || err.message).trim().split('\n').slice(-8).map((l) => ` ${l}`).join('\n')}\n`);
|
|
565
|
+
process.exit(1);
|
|
566
|
+
}
|
|
567
|
+
}
|
|
568
|
+
|
|
327
569
|
// The app icon, from an SVG: sharp (already here, Next depends on it) draws it
|
|
328
570
|
// at 1024px, sips makes the sizes macOS wants, iconutil packs them.
|
|
329
571
|
async function makeIcns(svg, out) {
|
|
@@ -179,6 +179,21 @@ function main() {
|
|
|
179
179
|
const circle = Array.from({ length: size }, () => person(2, b.id));
|
|
180
180
|
degree2.push(...circle);
|
|
181
181
|
}
|
|
182
|
+
// In a real network some people are known by more than one of your
|
|
183
|
+
// connections: that is what "reachable 2+ ways" counts, and what makes
|
|
184
|
+
// sorting Degrees by ways in worth doing. About one in seven gets a second
|
|
185
|
+
// route, and some of those a third. Same person, same profile, another bridge.
|
|
186
|
+
const shared = [];
|
|
187
|
+
for (const p of degree2) {
|
|
188
|
+
if (rand() >= 0.15) continue;
|
|
189
|
+
const others = bridges.filter((b) => b.id !== p.source_connection_id);
|
|
190
|
+
const routes = rand() < 0.3 ? 2 : 1;
|
|
191
|
+
for (let k = 0; k < routes; k++) {
|
|
192
|
+
const b = others.splice(Math.floor(rand() * others.length), 1)[0];
|
|
193
|
+
shared.push({ ...p, id: `${p.id}-via${k + 1}`, source_connection_id: b.id, influence_signals: {} });
|
|
194
|
+
}
|
|
195
|
+
}
|
|
196
|
+
degree2.push(...shared);
|
|
182
197
|
// Everyone again, together: circles now exist, so bridges get their boost.
|
|
183
198
|
scoreRows([...degree1, ...degree2]);
|
|
184
199
|
degree1.sort((a, b) => b.power_score - a.power_score);
|
|
@@ -205,7 +220,7 @@ function main() {
|
|
|
205
220
|
const kb = Math.round(JSON.stringify(payload).length / 1024);
|
|
206
221
|
console.log(`wrote ${out} (${kb} KB, seed ${seed})`);
|
|
207
222
|
console.log(` 1st degree : ${degree1.length}`);
|
|
208
|
-
console.log(` 2nd degree : ${degree2.length} across ${BRIDGE_COUNT} bridges`);
|
|
223
|
+
console.log(` 2nd degree : ${degree2.length - shared.length} people across ${BRIDGE_COUNT} bridges, ${new Set(shared.map((r) => r.profile_url)).size} of them reachable 2+ ways`);
|
|
209
224
|
console.log(` catalysts : ${bridges.filter((b) => b.is_catalyst).length}`);
|
|
210
225
|
console.log(` tier mix : ${['S','A','B','C','D'].map((t) => `${t}:${tiers[t] || 0}`).join(' ')}`);
|
|
211
226
|
}
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
"""Draw the README's download buttons.
|
|
3
|
+
|
|
4
|
+
A GitHub README can't style links, so the buttons are pictures: drawn here from
|
|
5
|
+
HTML in Chrome, with the app icon inside, and saved at twice their shown size so
|
|
6
|
+
they stay sharp. Each has its own background, so it reads on GitHub's light and
|
|
7
|
+
dark themes alike. No server needed:
|
|
8
|
+
|
|
9
|
+
python3 scripts/readme_buttons.py
|
|
10
|
+
|
|
11
|
+
Requires playwright (pip3 install playwright) and Google Chrome. Redraw whenever
|
|
12
|
+
the icon (desktop/icon/icon.svg) or the wording changes.
|
|
13
|
+
"""
|
|
14
|
+
import pathlib
|
|
15
|
+
import re
|
|
16
|
+
import sys
|
|
17
|
+
|
|
18
|
+
ROOT = pathlib.Path(__file__).resolve().parent.parent
|
|
19
|
+
OUT = ROOT / "docs" / "img"
|
|
20
|
+
ICON = (ROOT / "desktop" / "icon" / "icon.svg").read_text()
|
|
21
|
+
# The icon's artwork sits in its 1024 canvas with a margin (the macOS grid).
|
|
22
|
+
# Cropping to the rounded square lets it fill its spot in the button. A new
|
|
23
|
+
# icon with another canvas needs a new crop, so stop rather than draw it wrong.
|
|
24
|
+
CROP = "100 100 824 824"
|
|
25
|
+
root = re.search(r"<svg\b[^>]*>", ICON)
|
|
26
|
+
if not root or 'viewBox="0 0 1024 1024"' not in root.group(0):
|
|
27
|
+
sys.exit('desktop/icon/icon.svg is no longer a 1024 canvas (viewBox="0 0 1024 1024"): '
|
|
28
|
+
"update CROP in scripts/readme_buttons.py, then look at docs/img/download-*.png")
|
|
29
|
+
tag = re.sub(r'\s(?:viewBox|width|height)="[^"]*"', "", root.group(0))
|
|
30
|
+
ICON = ICON[:root.start()] + tag.replace("<svg", f'<svg viewBox="{CROP}"', 1) + ICON[root.end():]
|
|
31
|
+
|
|
32
|
+
ARROW = """<svg class="arrow" viewBox="0 0 24 24" width="30" height="30" aria-hidden="true">
|
|
33
|
+
<circle cx="12" cy="12" r="11" fill="none" stroke="currentColor" stroke-width="1.6" opacity=".55"/>
|
|
34
|
+
<path d="M12 6.5v9M7.8 11.6 12 15.8l4.2-4.2" fill="none" stroke="currentColor" stroke-width="2"
|
|
35
|
+
stroke-linecap="round" stroke-linejoin="round"/></svg>"""
|
|
36
|
+
|
|
37
|
+
# (file, top line, big line, bottom line, style)
|
|
38
|
+
BUTTONS = [
|
|
39
|
+
("download-apple-silicon.png", "Click to download for Mac", "Apple Silicon", "M1 or newer", "green"),
|
|
40
|
+
("download-intel.png", "Click to download for Mac", "Intel", "Macs with an Intel chip", "slate"),
|
|
41
|
+
]
|
|
42
|
+
|
|
43
|
+
CSS = """
|
|
44
|
+
* { box-sizing: border-box; margin: 0; }
|
|
45
|
+
body { background: transparent; font-family: -apple-system, BlinkMacSystemFont, "SF Pro Text", sans-serif;
|
|
46
|
+
-webkit-font-smoothing: antialiased; }
|
|
47
|
+
.pad { display: inline-block; padding: 6px 8px 12px; }
|
|
48
|
+
.btn { display: flex; align-items: center; gap: 16px; width: 330px; padding: 13px 18px 13px 14px;
|
|
49
|
+
border-radius: 16px; color: #fff; }
|
|
50
|
+
/* Dark enough that white text passes WCAG AA (4.5:1) everywhere on it. */
|
|
51
|
+
.green { background: linear-gradient(180deg, #1f883d 0%, #1a7f37 55%, #116329 100%);
|
|
52
|
+
box-shadow: 0 1px 0 rgba(255,255,255,.22) inset, 0 0 0 1px rgba(0,0,0,.12), 0 6px 16px rgba(17,99,41,.35); }
|
|
53
|
+
.slate { background: linear-gradient(180deg, #3a414a 0%, #2b3137 55%, #24292f 100%);
|
|
54
|
+
box-shadow: 0 1px 0 rgba(255,255,255,.16) inset, 0 0 0 1px rgba(255,255,255,.14), 0 6px 16px rgba(0,0,0,.28); }
|
|
55
|
+
.icon { flex: none; width: 56px; height: 56px; border-radius: 13px; overflow: hidden;
|
|
56
|
+
box-shadow: 0 0 0 1px rgba(255,255,255,.18), 0 2px 6px rgba(0,0,0,.35); }
|
|
57
|
+
.icon svg { display: block; width: 56px; height: 56px; }
|
|
58
|
+
.text { flex: 1; min-width: 0; line-height: 1.15; }
|
|
59
|
+
.top { font-size: 12.5px; font-weight: 600; letter-spacing: .02em; }
|
|
60
|
+
.big { font-size: 25px; font-weight: 800; letter-spacing: -.01em; margin: 2px 0 3px; }
|
|
61
|
+
.sub { font-size: 13.5px; font-weight: 500; }
|
|
62
|
+
.arrow { flex: none; color: #fff; }
|
|
63
|
+
"""
|
|
64
|
+
|
|
65
|
+
|
|
66
|
+
def button_html(top, big, sub, style):
|
|
67
|
+
return f"""<!doctype html><html><head><style>{CSS}</style></head><body>
|
|
68
|
+
<div class="pad" id="shot"><div class="btn {style}">
|
|
69
|
+
<div class="icon">{ICON}</div>
|
|
70
|
+
<div class="text"><div class="top">{top}</div><div class="big">{big}</div><div class="sub">{sub}</div></div>
|
|
71
|
+
{ARROW}
|
|
72
|
+
</div></div></body></html>"""
|
|
73
|
+
|
|
74
|
+
|
|
75
|
+
def main():
|
|
76
|
+
from playwright.sync_api import sync_playwright
|
|
77
|
+
|
|
78
|
+
with sync_playwright() as p:
|
|
79
|
+
browser = p.chromium.launch(channel="chrome")
|
|
80
|
+
page = browser.new_page(viewport={"width": 600, "height": 200}, device_scale_factor=2)
|
|
81
|
+
for name, top, big, sub, style in BUTTONS:
|
|
82
|
+
page.set_content(button_html(top, big, sub, style))
|
|
83
|
+
page.locator("#shot").screenshot(path=str(OUT / name), omit_background=True)
|
|
84
|
+
print(f" wrote docs/img/{name}")
|
|
85
|
+
browser.close()
|
|
86
|
+
|
|
87
|
+
|
|
88
|
+
if __name__ == "__main__":
|
|
89
|
+
main()
|
|
@@ -1,4 +1,106 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
1
|
+
# The scanner's Python packages (scripts/scrape.py), pinned to exact versions,
|
|
2
|
+
# with the SHA-256 of every file pip may install for each. The same file goes
|
|
3
|
+
# into the Python inside the Mac app when it is built (scripts/build-app.mjs),
|
|
4
|
+
# and into the scanner's own environment when the Scan page sets one up.
|
|
5
|
+
#
|
|
6
|
+
# To change a version, edit its line and run
|
|
7
|
+
# node scripts/pin-python-packages.mjs
|
|
8
|
+
# which rewrites the hashes from PyPI. Every dependency is listed: once hashes
|
|
9
|
+
# are used, pip refuses anything that isn't.
|
|
10
|
+
|
|
11
|
+
--only-binary :all:
|
|
12
|
+
--require-hashes
|
|
13
|
+
|
|
14
|
+
# Drives the user's own Google Chrome (channel="chrome"), so no browser is downloaded.
|
|
15
|
+
# Its wheel carries Playwright's driver, which it needs.
|
|
16
|
+
playwright==1.63.0 \
|
|
17
|
+
--hash=sha256:354e15b29503565fc598b89f16fbe070459343bef9d7498a93e304864000c6a7 \
|
|
18
|
+
--hash=sha256:84c540759e8e7f01e690e197e04060f48899d37cea322299f255843273d3385d \
|
|
19
|
+
--hash=sha256:ad21bc07516b187965a7521c5cf0df0bd657b17482eaad74335272d35a2b07de \
|
|
20
|
+
--hash=sha256:c89fc4736502a1f0fac2c8ca5d10c0cbc1c669f1f4774a2d8507a43140e4d53f \
|
|
21
|
+
--hash=sha256:fd1aa00631d44d55e56e0975bf3f3f285fac4a9fd2813183f0c12a488f1a1b24
|
|
22
|
+
|
|
23
|
+
# Playwright's own dependencies: greenlet, pyee, and pyee's typing-extensions.
|
|
24
|
+
greenlet==3.5.6 \
|
|
25
|
+
--hash=sha256:1c20ea32a73d17b9b60e3371240e17b0068120c98a5ec01a224a7dd8c89733ba \
|
|
26
|
+
--hash=sha256:45bfd2b51e38aaa5f9849f114d9c7c1d75f69187c849b3549cd64c465283abfa \
|
|
27
|
+
--hash=sha256:8cddea1b8339451c2fb3388e138347b6126744f33b611bdb55b7357361cfef46 \
|
|
28
|
+
--hash=sha256:95e7c44d072db623a1aab04ce488cf9533294a77ed9d072cd503a3596f4106ac \
|
|
29
|
+
--hash=sha256:975736b002ed080d124cf81a79cb7e05cb26d6b3f5c7a7b651c0fcce70353aa1 \
|
|
30
|
+
--hash=sha256:9a09d59bef1db94f384b5bcc2d523694d338f3df6b757aeeaf7baca5d0c0be88 \
|
|
31
|
+
--hash=sha256:a5876d0a60355af98d535c47f6cd6eb0f8a432396dab26845d380b92f8412422 \
|
|
32
|
+
--hash=sha256:a6a4b98a9132e0f45c9fc245a63894cfd8c45fb7a0d6bffc5eab3ec327cf7324 \
|
|
33
|
+
--hash=sha256:b7d501d5eb5d4f67207df364752ad697465b834268744be7581c18d81d35d41d \
|
|
34
|
+
--hash=sha256:c59acfa8eb73a1e0d484392dc002bdf001fd4ce73394e0132df3d1ab6093d7cb \
|
|
35
|
+
--hash=sha256:c75116c9de79949de23006e2d9b35ee82874c594fcf5c0311b439acaa14b8441 \
|
|
36
|
+
--hash=sha256:e85880b538e59a59f55117b81f208a6660ad5ac328aad9305f812d9b8bc67a0f \
|
|
37
|
+
--hash=sha256:eed88b64a5e5da72d6a71cdc5aaeefaa5ced9b748f8d19f89800b339961dad39 \
|
|
38
|
+
--hash=sha256:f96f0e30b5a95c7631b12bfe214cbc90ec8fe8cfa36920596c10514a65743519 \
|
|
39
|
+
--hash=sha256:f98e8215e172f567ce80eeaed9107fb4d32b6c44f26983d9b8334658136a205a
|
|
40
|
+
|
|
41
|
+
pyee==13.0.1 \
|
|
42
|
+
--hash=sha256:af2f8fede4171ef667dfded53f96e2ed0d6e6bd7ee3bb46437f77e3b57689228
|
|
43
|
+
|
|
44
|
+
typing-extensions==4.16.0 \
|
|
45
|
+
--hash=sha256:481caa481374e813c1b176ada14e97f1f67a4539ce9cfeb3f350d78d6370c2e8
|
|
46
|
+
|
|
47
|
+
requests==2.34.2 \
|
|
48
|
+
--hash=sha256:2a0d60c172f83ac6ab31e4554906c0f3b3588d37b5cb939b1c061f4907e278e0
|
|
49
|
+
|
|
50
|
+
# requests' own dependencies: certifi, charset-normalizer, idna, urllib3.
|
|
51
|
+
certifi==2026.7.22 \
|
|
52
|
+
--hash=sha256:62f22742b58a1a33014a2b6b706588a8d7e2a88ae7bd1a6ebe8c992928483775
|
|
53
|
+
|
|
54
|
+
charset-normalizer==3.5.1 \
|
|
55
|
+
--hash=sha256:15f024313246a4ed976c60f440bb8d257815513a681d212ff74fd46f7d715a90 \
|
|
56
|
+
--hash=sha256:2f06b7eae9dbe77fe1d644ca244dad508de8d302870a43f3c559b521270938a0 \
|
|
57
|
+
--hash=sha256:41876ee62a3dddf48ff1121ad8f0798032aa03f2fd35f21f34a4cab14f18d8d2 \
|
|
58
|
+
--hash=sha256:4582c27e8c889d64811987b5967fbd3ae0c823fe1fd933b543d55ac20bb475fa \
|
|
59
|
+
--hash=sha256:5b6d1386bf0096d26d3a863dc0a487a5b4eb9aa93cf5ba69683d29dde6b9d60f \
|
|
60
|
+
--hash=sha256:62b55f6722735a6c472f88361cde6640608773d9443cebdbb51abf436a1fcdd3 \
|
|
61
|
+
--hash=sha256:6df0ec430f9a831772c23ca5a224cba36517a58a84bb32c32bb59a9fa67c47f6 \
|
|
62
|
+
--hash=sha256:94d78ecec2605a8d0398b0f365d5f12a63248438516f5dac536a5eff7337df4a \
|
|
63
|
+
--hash=sha256:96eefc178f8636b9c760c5829345307fd81cfae9ab1e80997dbddeb0f54ee9a3 \
|
|
64
|
+
--hash=sha256:a6dac12ff6b846103483683f60c5f8fee205121adc58ffd87e90a90a3af69e99 \
|
|
65
|
+
--hash=sha256:aa2bb0b37202dca27175591f761108b5d34096ade1191ffe4808bdf6b1571488 \
|
|
66
|
+
--hash=sha256:b9af956078716df40d985fb0dfeb2c2120c5ca92ba4ff4b388acfd01cdc14d08 \
|
|
67
|
+
--hash=sha256:c428c6c31eb5f4277d7f8eccaf767fbd548ddd5ce3c8b4f4cbbfab3d96b5904c \
|
|
68
|
+
--hash=sha256:c7b742bf31c88566b4bb6335a7f393bb322e580b6bb98df7bd0c25e6e3519ce8 \
|
|
69
|
+
--hash=sha256:cee5dd7c6fb5dd52a0fe2a740f9bc6e3593f5f8b1788bde49de02086f30182b2 \
|
|
70
|
+
--hash=sha256:d1ee1e296209fdce05b81b663250eefa02213a2da7b41bf26f7829b8ba3545aa \
|
|
71
|
+
--hash=sha256:e90251c0c7bdd54a100a0dce3c07b7e637278c93af29dbf78ebb89a58c4bac7d \
|
|
72
|
+
--hash=sha256:e9fbdce1e47394b09bc9f26ab117dfc8d6491977a11d86f592bb42c779db2fda \
|
|
73
|
+
--hash=sha256:eda059b6bc8bc0812d626fd91a7ce01bf583df0a61296eff390fd94141a34e30
|
|
74
|
+
|
|
75
|
+
idna==3.20 \
|
|
76
|
+
--hash=sha256:ab7ae7122974553370f0bdb919e1a960b2cd1bc1ef0276416d896db81c14582c
|
|
77
|
+
|
|
78
|
+
urllib3==2.8.0 \
|
|
79
|
+
--hash=sha256:0cf3cae568d36aa9576b28dfb35f11328f1cb974ca7647d9475ebb86c75ac6e3
|
|
80
|
+
|
|
81
|
+
# Profile photos (scripts/image_store.py).
|
|
82
|
+
pillow==12.3.0 \
|
|
83
|
+
--hash=sha256:00808c5e14ef63ac5161091d242999076604ff74b883423a11e5d7bbb38bf756 \
|
|
84
|
+
--hash=sha256:0847a763afefb695bc912d7c131e7e0632d4edc1d8698f58ddabec8e46b8b6d3 \
|
|
85
|
+
--hash=sha256:23d27a3e0307ec2244cc51e7287b919aa68d097504ebe19df4e76a98a3eea5bd \
|
|
86
|
+
--hash=sha256:251bf95b67017e27b13d82f5b326234ca62d70f9cf4c2b9032de2358a3b12c7b \
|
|
87
|
+
--hash=sha256:37d6d0a00072fd2948eb22bce7e1475f34569d90c87c59f7a2ec59541b77f7a6 \
|
|
88
|
+
--hash=sha256:5594fc43d548a7ed94949d139aa1341b270f1863f11cfd37f5a6c8b778a6b67f \
|
|
89
|
+
--hash=sha256:6c0016e7b354317c4e9e525b937ac8596c38d2d232b419529b9cd7a1cd46e39a \
|
|
90
|
+
--hash=sha256:78cb2c6865a35ab8ff8b75fd122f6033b92a62c82801110e48ddd6c936a45d91 \
|
|
91
|
+
--hash=sha256:7a743ff716f746fc19a9557f60dab1600d4613255f8a7aeb3cdde4db7eb15a66 \
|
|
92
|
+
--hash=sha256:ba09209fbe443b4acccebe845d8a138b89a8f4fbaeedd44953490b5315d5e965 \
|
|
93
|
+
--hash=sha256:ba54cfebe86920a559a7c4d6b9050791c20513650a1952ebe3368c7dc70306f8 \
|
|
94
|
+
--hash=sha256:bcb46e2f9feff8d06323983bd83ed00c201fdcab3d74973e7072a889b3979fcd \
|
|
95
|
+
--hash=sha256:bcc33feacfaefce60c12fd500a277533bdc02b10a19f7f6d348763d8140bbba7 \
|
|
96
|
+
--hash=sha256:d69141514cc30b774ceea5e3ed3a6635c8d8a96edf664689b890f4089111fb35 \
|
|
97
|
+
--hash=sha256:d9c7f76c0673154f044e9d78c8655fb4213f6ca31a836df48b40fe5d187717b9 \
|
|
98
|
+
--hash=sha256:e158cb00350dc278f3b91551101aa7d12415a66ebf2c91d8d5ac14e56ddd3ad0 \
|
|
99
|
+
--hash=sha256:e9aeb04d6aef139de265b29683e119b638208f88cf73cdd1658aa07221165321 \
|
|
100
|
+
--hash=sha256:f0606c8bf2cdefea14a43530f7657cbbb7ecf1c4222512492ef4a4434a9501ec \
|
|
101
|
+
--hash=sha256:f7401aebd7f581d7f83a439d87d474999317ee099218e5ad25d125290990ba65 \
|
|
102
|
+
--hash=sha256:ffd0c5368496f41b0944be820fcb7a838aa6e623d250b01acf2643939c3f99d7
|
|
103
|
+
|
|
104
|
+
# Windows only: Python there has no time zone database (docs/brain/DESKTOP.md D3).
|
|
105
|
+
tzdata==2026.4 ; sys_platform == "win32" \
|
|
106
|
+
--hash=sha256:c2169a8b0a7a5e9674da5a135ccdfb2b3e671b333ed9fed17b41f73c34476e81
|
|
@@ -102,6 +102,8 @@ def main():
|
|
|
102
102
|
if script:
|
|
103
103
|
page.evaluate(script)
|
|
104
104
|
page.wait_for_timeout(1500)
|
|
105
|
+
# The dev server's own badge (Next.js's "N" in a corner) isn't part of the app.
|
|
106
|
+
page.add_style_tag(content="nextjs-portal { display: none !important; }")
|
|
105
107
|
page.screenshot(path=str(OUT / name))
|
|
106
108
|
print(f" wrote docs/img/{name}")
|
|
107
109
|
|