@ogygia/devtools 0.0.0 → 0.11.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.
Files changed (310) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +24 -1
  3. package/dist/client.d.ts +3 -0
  4. package/dist/client.js +24 -0
  5. package/dist/devtools/BoundaryOverlay.svelte +396 -0
  6. package/dist/devtools/BoundaryOverlay.svelte.d.ts +19 -0
  7. package/dist/devtools/Devtools.svelte +663 -0
  8. package/dist/devtools/Devtools.svelte.d.ts +15 -0
  9. package/dist/devtools/HubTab.svelte +206 -0
  10. package/dist/devtools/HubTab.svelte.d.ts +11 -0
  11. package/dist/devtools/HydrationTab.svelte +237 -0
  12. package/dist/devtools/HydrationTab.svelte.d.ts +13 -0
  13. package/dist/devtools/IslandDetail.svelte +615 -0
  14. package/dist/devtools/IslandDetail.svelte.d.ts +15 -0
  15. package/dist/devtools/LedgerTab.svelte +287 -0
  16. package/dist/devtools/LedgerTab.svelte.d.ts +11 -0
  17. package/dist/devtools/LensTab.svelte +290 -0
  18. package/dist/devtools/LensTab.svelte.d.ts +19 -0
  19. package/dist/devtools/NavTab.svelte +229 -0
  20. package/dist/devtools/NavTab.svelte.d.ts +11 -0
  21. package/dist/devtools/PageTab.svelte +1122 -0
  22. package/dist/devtools/PageTab.svelte.d.ts +15 -0
  23. package/dist/devtools/ProfilerTab.svelte +755 -0
  24. package/dist/devtools/ProfilerTab.svelte.d.ts +15 -0
  25. package/dist/devtools/PropsTree.svelte +155 -0
  26. package/dist/devtools/PropsTree.svelte.d.ts +15 -0
  27. package/dist/devtools/SessionTab.svelte +796 -0
  28. package/dist/devtools/SessionTab.svelte.d.ts +11 -0
  29. package/dist/devtools/TimelineTab.svelte +267 -0
  30. package/dist/devtools/TimelineTab.svelte.d.ts +11 -0
  31. package/dist/devtools/WireTab.svelte +149 -0
  32. package/dist/devtools/WireTab.svelte.d.ts +11 -0
  33. package/dist/devtools/bytes.d.ts +70 -0
  34. package/dist/devtools/bytes.js +82 -0
  35. package/dist/devtools/cache-headers.d.ts +20 -0
  36. package/dist/devtools/cache-headers.js +81 -0
  37. package/dist/devtools/highlight.d.ts +7 -0
  38. package/dist/devtools/highlight.js +83 -0
  39. package/dist/devtools/hydration.d.ts +48 -0
  40. package/dist/devtools/hydration.js +93 -0
  41. package/dist/devtools/index.d.ts +3 -0
  42. package/dist/devtools/index.js +3 -0
  43. package/dist/devtools/ledger-dom.d.ts +7 -0
  44. package/dist/devtools/ledger-dom.js +151 -0
  45. package/dist/devtools/leftovers.d.ts +77 -0
  46. package/dist/devtools/leftovers.js +319 -0
  47. package/dist/devtools/names.d.ts +1 -0
  48. package/dist/devtools/names.js +34 -0
  49. package/dist/devtools/page.d.ts +96 -0
  50. package/dist/devtools/page.js +957 -0
  51. package/dist/devtools/profile-anchors.d.ts +22 -0
  52. package/dist/devtools/profile-anchors.js +135 -0
  53. package/dist/devtools/profile-store.d.ts +175 -0
  54. package/dist/devtools/profile-store.js +239 -0
  55. package/dist/devtools/regions.d.ts +77 -0
  56. package/dist/devtools/regions.js +132 -0
  57. package/dist/devtools/session.d.ts +31 -0
  58. package/dist/devtools/session.js +455 -0
  59. package/dist/devtools/since-load.d.ts +50 -0
  60. package/dist/devtools/since-load.js +89 -0
  61. package/dist/devtools/source-lines.d.ts +24 -0
  62. package/dist/devtools/source-lines.js +106 -0
  63. package/dist/devtools/styles.d.ts +52 -0
  64. package/dist/devtools/styles.js +248 -0
  65. package/dist/devtools/testing-engine.d.ts +83 -0
  66. package/dist/devtools/testing-engine.js +220 -0
  67. package/dist/devtools/ui-app.d.ts +5 -0
  68. package/dist/devtools/ui-app.js +69 -0
  69. package/dist/devtools/ui.d.ts +50 -0
  70. package/dist/devtools/ui.js +175 -0
  71. package/dist/profiler/alloc.d.ts +75 -0
  72. package/dist/profiler/alloc.js +76 -0
  73. package/dist/profiler/analyze.d.ts +437 -0
  74. package/dist/profiler/analyze.js +1941 -0
  75. package/dist/profiler/app-path.d.ts +7 -0
  76. package/dist/profiler/app-path.js +26 -0
  77. package/dist/profiler/async-io.d.ts +58 -0
  78. package/dist/profiler/async-io.js +187 -0
  79. package/dist/profiler/beacon-standalone.d.ts +4 -0
  80. package/dist/profiler/beacon-standalone.js +409 -0
  81. package/dist/profiler/browser-findings.d.ts +25 -0
  82. package/dist/profiler/browser-findings.js +260 -0
  83. package/dist/profiler/byte-strip.d.ts +58 -0
  84. package/dist/profiler/byte-strip.js +228 -0
  85. package/dist/profiler/client-files.d.ts +16 -0
  86. package/dist/profiler/client-files.js +60 -0
  87. package/dist/profiler/client-windows.d.ts +49 -0
  88. package/dist/profiler/client-windows.js +95 -0
  89. package/dist/profiler/client.d.ts +40 -0
  90. package/dist/profiler/client.js +82 -0
  91. package/dist/profiler/compare.d.ts +308 -0
  92. package/dist/profiler/compare.js +733 -0
  93. package/dist/profiler/compress.d.ts +10 -0
  94. package/dist/profiler/compress.js +36 -0
  95. package/dist/profiler/contention.d.ts +60 -0
  96. package/dist/profiler/contention.js +86 -0
  97. package/dist/profiler/crypto.d.ts +19 -0
  98. package/dist/profiler/crypto.js +101 -0
  99. package/dist/profiler/doc-diff.d.ts +47 -0
  100. package/dist/profiler/doc-diff.js +214 -0
  101. package/dist/profiler/dom-diff.d.ts +43 -0
  102. package/dist/profiler/dom-diff.js +121 -0
  103. package/dist/profiler/drill.d.ts +89 -0
  104. package/dist/profiler/drill.js +553 -0
  105. package/dist/profiler/embedded-maps.d.ts +37 -0
  106. package/dist/profiler/embedded-maps.js +135 -0
  107. package/dist/profiler/env.d.ts +6 -0
  108. package/dist/profiler/env.js +10 -0
  109. package/dist/profiler/forecast.d.ts +76 -0
  110. package/dist/profiler/forecast.js +225 -0
  111. package/dist/profiler/frames.d.ts +11 -0
  112. package/dist/profiler/frames.js +42 -0
  113. package/dist/profiler/gc.d.ts +144 -0
  114. package/dist/profiler/gc.js +271 -0
  115. package/dist/profiler/hole-slots.d.ts +31 -0
  116. package/dist/profiler/hole-slots.js +90 -0
  117. package/dist/profiler/index.d.ts +288 -0
  118. package/dist/profiler/index.js +4921 -0
  119. package/dist/profiler/insights.d.ts +96 -0
  120. package/dist/profiler/insights.js +239 -0
  121. package/dist/profiler/ledger.d.ts +121 -0
  122. package/dist/profiler/ledger.js +440 -0
  123. package/dist/profiler/lineage.d.ts +81 -0
  124. package/dist/profiler/lineage.js +359 -0
  125. package/dist/profiler/module-map.d.ts +12 -0
  126. package/dist/profiler/module-map.js +94 -0
  127. package/dist/profiler/net.d.ts +169 -0
  128. package/dist/profiler/net.js +586 -0
  129. package/dist/profiler/on-demand.d.ts +11 -0
  130. package/dist/profiler/on-demand.js +15 -0
  131. package/dist/profiler/own-requests.d.ts +9 -0
  132. package/dist/profiler/own-requests.js +17 -0
  133. package/dist/profiler/patterns.d.ts +476 -0
  134. package/dist/profiler/patterns.js +2203 -0
  135. package/dist/profiler/profiler-router.d.ts +245 -0
  136. package/dist/profiler/profiler-router.js +113 -0
  137. package/dist/profiler/refresh-stub.d.ts +2 -0
  138. package/dist/profiler/refresh-stub.js +37 -0
  139. package/dist/profiler/report.d.ts +1404 -0
  140. package/dist/profiler/report.js +2638 -0
  141. package/dist/profiler/river.d.ts +65 -0
  142. package/dist/profiler/river.js +298 -0
  143. package/dist/profiler/route-files.d.ts +22 -0
  144. package/dist/profiler/route-files.js +55 -0
  145. package/dist/profiler/route-imports.d.ts +14 -0
  146. package/dist/profiler/route-imports.js +83 -0
  147. package/dist/profiler/saving.d.ts +22 -0
  148. package/dist/profiler/saving.js +42 -0
  149. package/dist/profiler/score.d.ts +109 -0
  150. package/dist/profiler/score.js +261 -0
  151. package/dist/profiler/session-cookie.d.ts +28 -0
  152. package/dist/profiler/session-cookie.js +45 -0
  153. package/dist/profiler/sink.d.ts +81 -0
  154. package/dist/profiler/sink.js +124 -0
  155. package/dist/profiler/site-fixes.d.ts +25 -0
  156. package/dist/profiler/site-fixes.js +62 -0
  157. package/dist/profiler/source-scan.d.ts +210 -0
  158. package/dist/profiler/source-scan.js +1724 -0
  159. package/dist/profiler/span.d.ts +90 -0
  160. package/dist/profiler/span.js +109 -0
  161. package/dist/profiler/stacks.d.ts +43 -0
  162. package/dist/profiler/stacks.js +107 -0
  163. package/dist/profiler/standalone.d.ts +27 -0
  164. package/dist/profiler/standalone.js +98 -0
  165. package/dist/profiler/steps.d.ts +39 -0
  166. package/dist/profiler/steps.js +74 -0
  167. package/dist/profiler/storage/index.d.ts +87 -0
  168. package/dist/profiler/storage/index.js +76 -0
  169. package/dist/profiler/storage/postgres.d.ts +12 -0
  170. package/dist/profiler/storage/postgres.js +94 -0
  171. package/dist/profiler/storage/redis.d.ts +19 -0
  172. package/dist/profiler/storage/redis.js +148 -0
  173. package/dist/profiler/storage/sqlite.d.ts +2 -0
  174. package/dist/profiler/storage/sqlite.js +85 -0
  175. package/dist/profiler/storage/visits.d.ts +4 -0
  176. package/dist/profiler/storage/visits.js +6 -0
  177. package/dist/profiler/stream-tail.d.ts +26 -0
  178. package/dist/profiler/stream-tail.js +74 -0
  179. package/dist/profiler/timeline.d.ts +279 -0
  180. package/dist/profiler/timeline.js +690 -0
  181. package/dist/profiler/ui/AllocStrip.svelte +146 -0
  182. package/dist/profiler/ui/AllocStrip.svelte.d.ts +17 -0
  183. package/dist/profiler/ui/Awaits.svelte +363 -0
  184. package/dist/profiler/ui/Awaits.svelte.d.ts +16 -0
  185. package/dist/profiler/ui/ByteStrip.svelte +182 -0
  186. package/dist/profiler/ui/ByteStrip.svelte.d.ts +18 -0
  187. package/dist/profiler/ui/Compare.svelte +24 -0
  188. package/dist/profiler/ui/Compare.svelte.d.ts +16 -0
  189. package/dist/profiler/ui/CompareBody.svelte +429 -0
  190. package/dist/profiler/ui/CompareBody.svelte.d.ts +8 -0
  191. package/dist/profiler/ui/ComponentsTable.svelte +265 -0
  192. package/dist/profiler/ui/ComponentsTable.svelte.d.ts +20 -0
  193. package/dist/profiler/ui/Dashboard.svelte +492 -0
  194. package/dist/profiler/ui/Dashboard.svelte.d.ts +31 -0
  195. package/dist/profiler/ui/DataRiver.svelte +206 -0
  196. package/dist/profiler/ui/DataRiver.svelte.d.ts +13 -0
  197. package/dist/profiler/ui/DomTravel.svelte +207 -0
  198. package/dist/profiler/ui/DomTravel.svelte.d.ts +9 -0
  199. package/dist/profiler/ui/DownloadHtml.svelte +52 -0
  200. package/dist/profiler/ui/DownloadHtml.svelte.d.ts +10 -0
  201. package/dist/profiler/ui/Drill.svelte +276 -0
  202. package/dist/profiler/ui/Drill.svelte.d.ts +12 -0
  203. package/dist/profiler/ui/ExportButton.svelte +59 -0
  204. package/dist/profiler/ui/ExportButton.svelte.d.ts +8 -0
  205. package/dist/profiler/ui/Flame.svelte +222 -0
  206. package/dist/profiler/ui/Flame.svelte.d.ts +12 -0
  207. package/dist/profiler/ui/FrameDetails.svelte +308 -0
  208. package/dist/profiler/ui/FrameDetails.svelte.d.ts +16 -0
  209. package/dist/profiler/ui/FunctionsTable.svelte +156 -0
  210. package/dist/profiler/ui/FunctionsTable.svelte.d.ts +17 -0
  211. package/dist/profiler/ui/IslandHeatmap.svelte +151 -0
  212. package/dist/profiler/ui/IslandHeatmap.svelte.d.ts +16 -0
  213. package/dist/profiler/ui/IslandsTable.svelte +448 -0
  214. package/dist/profiler/ui/IslandsTable.svelte.d.ts +16 -0
  215. package/dist/profiler/ui/KeepLocal.svelte +46 -0
  216. package/dist/profiler/ui/KeepLocal.svelte.d.ts +8 -0
  217. package/dist/profiler/ui/Ledger.svelte +196 -0
  218. package/dist/profiler/ui/Ledger.svelte.d.ts +18 -0
  219. package/dist/profiler/ui/LocalCompare.svelte +48 -0
  220. package/dist/profiler/ui/LocalCompare.svelte.d.ts +8 -0
  221. package/dist/profiler/ui/LocalReports.svelte +68 -0
  222. package/dist/profiler/ui/LocalReports.svelte.d.ts +7 -0
  223. package/dist/profiler/ui/Login.svelte +13 -0
  224. package/dist/profiler/ui/Login.svelte.d.ts +12 -0
  225. package/dist/profiler/ui/LoginForm.svelte +42 -0
  226. package/dist/profiler/ui/LoginForm.svelte.d.ts +7 -0
  227. package/dist/profiler/ui/Message.svelte +10 -0
  228. package/dist/profiler/ui/Message.svelte.d.ts +12 -0
  229. package/dist/profiler/ui/OnThisPage.svelte +137 -0
  230. package/dist/profiler/ui/OnThisPage.svelte.d.ts +3 -0
  231. package/dist/profiler/ui/OneClock.svelte +297 -0
  232. package/dist/profiler/ui/OneClock.svelte.d.ts +27 -0
  233. package/dist/profiler/ui/Panel.svelte +10 -0
  234. package/dist/profiler/ui/Panel.svelte.d.ts +16 -0
  235. package/dist/profiler/ui/Paths.svelte +269 -0
  236. package/dist/profiler/ui/Paths.svelte.d.ts +15 -0
  237. package/dist/profiler/ui/Patterns.svelte +364 -0
  238. package/dist/profiler/ui/Patterns.svelte.d.ts +15 -0
  239. package/dist/profiler/ui/PermalinkGate.svelte +143 -0
  240. package/dist/profiler/ui/PermalinkGate.svelte.d.ts +10 -0
  241. package/dist/profiler/ui/RenderSteps.svelte +218 -0
  242. package/dist/profiler/ui/RenderSteps.svelte.d.ts +13 -0
  243. package/dist/profiler/ui/Report.svelte +28 -0
  244. package/dist/profiler/ui/Report.svelte.d.ts +20 -0
  245. package/dist/profiler/ui/ReportBody.svelte +2592 -0
  246. package/dist/profiler/ui/ReportBody.svelte.d.ts +21 -0
  247. package/dist/profiler/ui/Run.svelte +17 -0
  248. package/dist/profiler/ui/Run.svelte.d.ts +14 -0
  249. package/dist/profiler/ui/RunView.svelte +146 -0
  250. package/dist/profiler/ui/RunView.svelte.d.ts +10 -0
  251. package/dist/profiler/ui/ScoreCard.svelte +197 -0
  252. package/dist/profiler/ui/ScoreCard.svelte.d.ts +7 -0
  253. package/dist/profiler/ui/Scrub.svelte +293 -0
  254. package/dist/profiler/ui/Scrub.svelte.d.ts +18 -0
  255. package/dist/profiler/ui/SeedExplainer.svelte +193 -0
  256. package/dist/profiler/ui/SeedExplainer.svelte.d.ts +16 -0
  257. package/dist/profiler/ui/ShareLink.svelte +148 -0
  258. package/dist/profiler/ui/ShareLink.svelte.d.ts +8 -0
  259. package/dist/profiler/ui/Shell.svelte +50 -0
  260. package/dist/profiler/ui/Shell.svelte.d.ts +27 -0
  261. package/dist/profiler/ui/Sidebar.svelte +312 -0
  262. package/dist/profiler/ui/Sidebar.svelte.d.ts +7 -0
  263. package/dist/profiler/ui/Site.svelte +20 -0
  264. package/dist/profiler/ui/Site.svelte.d.ts +23 -0
  265. package/dist/profiler/ui/SiteView.svelte +385 -0
  266. package/dist/profiler/ui/SiteView.svelte.d.ts +27 -0
  267. package/dist/profiler/ui/ThemeSwitch.svelte +78 -0
  268. package/dist/profiler/ui/ThemeSwitch.svelte.d.ts +3 -0
  269. package/dist/profiler/ui/Timeline.svelte +672 -0
  270. package/dist/profiler/ui/Timeline.svelte.d.ts +22 -0
  271. package/dist/profiler/ui/Treemap.svelte +278 -0
  272. package/dist/profiler/ui/Treemap.svelte.d.ts +20 -0
  273. package/dist/profiler/ui/Upload.svelte +19 -0
  274. package/dist/profiler/ui/Upload.svelte.d.ts +10 -0
  275. package/dist/profiler/ui/UploadForm.svelte +59 -0
  276. package/dist/profiler/ui/UploadForm.svelte.d.ts +6 -0
  277. package/dist/profiler/ui/WaitingTable.svelte +55 -0
  278. package/dist/profiler/ui/WaitingTable.svelte.d.ts +14 -0
  279. package/dist/profiler/ui/Waterfall.svelte +371 -0
  280. package/dist/profiler/ui/Waterfall.svelte.d.ts +7 -0
  281. package/dist/profiler/ui/WhatIf.svelte +87 -0
  282. package/dist/profiler/ui/WhatIf.svelte.d.ts +18 -0
  283. package/dist/profiler/ui/fake-progress.svelte.d.ts +15 -0
  284. package/dist/profiler/ui/fake-progress.svelte.js +38 -0
  285. package/dist/profiler/ui/format.d.ts +20 -0
  286. package/dist/profiler/ui/format.js +71 -0
  287. package/dist/profiler/ui/permalink.d.ts +9 -0
  288. package/dist/profiler/ui/permalink.js +108 -0
  289. package/dist/profiler/ui/press.d.ts +5 -0
  290. package/dist/profiler/ui/press.js +19 -0
  291. package/dist/profiler/ui/profiler.css +650 -0
  292. package/dist/profiler/ui/report-data.d.ts +189 -0
  293. package/dist/profiler/ui/report-data.js +393 -0
  294. package/dist/profiler/ui/report-request.d.ts +6 -0
  295. package/dist/profiler/ui/report-request.js +50 -0
  296. package/dist/profiler/ui/row-anchor.svelte.d.ts +12 -0
  297. package/dist/profiler/ui/row-anchor.svelte.js +44 -0
  298. package/dist/profiler/ui/sort.svelte.d.ts +14 -0
  299. package/dist/profiler/ui/sort.svelte.js +37 -0
  300. package/dist/profiler/ui/store.d.ts +45 -0
  301. package/dist/profiler/ui/store.js +92 -0
  302. package/dist/profiler/visit.d.ts +389 -0
  303. package/dist/profiler/visit.js +1002 -0
  304. package/dist/report.d.ts +5 -0
  305. package/dist/report.js +4 -0
  306. package/dist/server.d.ts +11 -0
  307. package/dist/server.js +38 -0
  308. package/dist/vite.d.ts +12 -0
  309. package/dist/vite.js +78 -0
  310. package/package.json +99 -6
@@ -0,0 +1,21 @@
1
+ import type { Since } from '../compare.js';
2
+ import type { Analysis } from '../analyze.js';
3
+ import type { ReportMeta, ReportExtras } from '../report.js';
4
+ import type { PageHistory } from '../profiler-router.js';
5
+ type $$ComponentProps = {
6
+ a: Analysis;
7
+ meta: ReportMeta;
8
+ base: string;
9
+ extras: ReportExtras;
10
+ ogpB64?: string;
11
+ history?: PageHistory | null;
12
+ prev?: string | null;
13
+ /** against the previous profile of this page (the server's comparison, cut for the top) */
14
+ since?: Since | null;
15
+ dev?: boolean;
16
+ /** rendered from this browser's own kept copy (the owner's): it can still be shared */
17
+ kept?: boolean;
18
+ };
19
+ declare const ReportBody: import("svelte").Component<$$ComponentProps, {}, "">;
20
+ type ReportBody = ReturnType<typeof ReportBody>;
21
+ export default ReportBody;
@@ -0,0 +1,17 @@
1
+ <script>/** The `<base>/run` page: Shell + the reactive RunView island that drives the progress bar and the
2
+ * profile request. Served through document() like every other profiler view. */
3
+ import Shell from "./Shell.svelte";
4
+ import RunView from "./RunView.svelte" with { wake: "load" };
5
+ let { data } = $props();
6
+ const { base, path, runs, format, against } = $derived(data);
7
+ </script>
8
+
9
+ <Shell {base}>
10
+ <h1>Profiling <code>{path}</code></h1>
11
+ <p class="hint">
12
+ Rendering the page through your real server{format === 'ogp'
13
+ ? ', then downloading the .ogp'
14
+ : ''}. This runs the page {runs}× for a steady median — hold on.
15
+ </p>
16
+ <RunView {base} {path} {runs} {format} {against} />
17
+ </Shell>
@@ -0,0 +1,14 @@
1
+ declare const Run: import("svelte").Component<{
2
+ data: {
3
+ base: string;
4
+ path: string;
5
+ runs: number;
6
+ format: string;
7
+ against?: string | undefined;
8
+ };
9
+ form: null;
10
+ params: {};
11
+ search: {};
12
+ }, {}, "">;
13
+ type Run = ReturnType<typeof Run>;
14
+ export default Run;
@@ -0,0 +1,146 @@
1
+ <script>/**
2
+ * The run page body — a `wake:'load'` island. On wake it fires the profile at `<base>/page`, shows a
3
+ * Windows-style progress bar while the server renders + samples, then swaps to the report (navigates
4
+ * this document to `/report/<id>`, so an embedding devtools iframe shows the whole thing). For the
5
+ * `.ogp` path it downloads the encrypted file instead. It also postMessages the final report URL to a
6
+ * parent frame, so the devtools tab can offer "open in new tab".
7
+ */
8
+ import { onMount } from "svelte";
9
+ import { fake_progress } from "./fake-progress.svelte.js";
10
+ import { put_report } from "./store.js";
11
+ // ── regexes
12
+ const NON_WORD_G = /\W+/g;
13
+ let { base, path, runs, format, against = "" } = $props();
14
+ // A busy worker answers /page with 409 (one recording per worker — the V8 profiler is process-wide).
15
+ // There's no server-side queue to rely on (a serverless worker is recycled within ~30s), so the QUEUE
16
+ // LIVES HERE: poll until a worker accepts. On serverless the retry lands on a free worker; on a single
17
+ // server it comes back once the run ahead finishes. Give up after QUEUE_MAX_MS and point at Reset.
18
+ const QUEUE_POLL_MS = 2e3;
19
+ const QUEUE_MAX_MS = 12e4;
20
+ const p = fake_progress();
21
+ let phase = $state("Starting the profiler…");
22
+ let error = $state("");
23
+ let done_ogp = $state(false);
24
+ let queued = $state(false);
25
+ let waited_s = $state(0);
26
+ /** Fetch /page, polling while any worker we reach is busy. Returns the first non-409 response, or the
27
+ * last 409 if we waited past QUEUE_MAX_MS (the caller surfaces that as an error). */
28
+ async function fetch_page(url) {
29
+ const started = Date.now();
30
+ for (;;) {
31
+ queued = false;
32
+ p.start();
33
+ phase = `Rendering ${path} ${runs}× and sampling the server…`;
34
+ const res = await fetch(url);
35
+ if (res.status !== 409) return res;
36
+ // busy — enter/stay in the queue
37
+ if (Date.now() - started > QUEUE_MAX_MS) return res;
38
+ queued = true;
39
+ const retry_after = Number(res.headers.get("retry-after")) * 1e3;
40
+ const delay = Number.isFinite(retry_after) && retry_after > 0 ? retry_after : QUEUE_POLL_MS;
41
+ waited_s = Math.round((Date.now() - started) / 1e3);
42
+ phase = "In queue — a profile is already running. Waiting for a free worker…";
43
+ await new Promise((r) => setTimeout(r, delay));
44
+ }
45
+ }
46
+ async function run() {
47
+ try {
48
+ // `keep`: the answer carries the report's dump so THIS BROWSER keeps it (IndexedDB) before
49
+ // navigating — on an ephemeral host the instance that rendered it may be gone by then
50
+ const suffix = format === "ogp" ? "&format=ogp" : "&format=keep";
51
+ const res = await fetch_page(`${base}/page?p=${encodeURIComponent(path)}&runs=${runs}${suffix}`);
52
+ if (!res.ok) throw new Error(String(res.status));
53
+ if (format === "ogp") {
54
+ const blob = await res.blob();
55
+ await p.finish();
56
+ const a = document.createElement("a");
57
+ const href = URL.createObjectURL(blob);
58
+ a.href = href;
59
+ a.download = `profile-${path.replace(NON_WORD_G, "_") || "page"}.ogp`;
60
+ a.click();
61
+ URL.revokeObjectURL(href);
62
+ done_ogp = true;
63
+ phase = "Downloaded the encrypted .ogp.";
64
+ } else {
65
+ // /page renders N times and answers { id, url, dump }: keep the dump here, then open the report
66
+ let url = res.url;
67
+ try {
68
+ const keep = await res.json();
69
+ if (keep.url) url = keep.url;
70
+ // asked to check a fix: open the new report compared with the one it was run against
71
+ if (against && keep.id) url = `${base}/compare/${against}/${keep.id}`;
72
+ if (keep.dump) {
73
+ phase = "Keeping the report in this browser…";
74
+ await put_report(keep.dump);
75
+ }
76
+ } catch {}
77
+ await p.finish();
78
+ phase = "Opening the report…";
79
+ try {
80
+ window.parent?.postMessage({
81
+ type: "ogygia:profiled",
82
+ url
83
+ }, location.origin);
84
+ } catch {}
85
+ location.href = url;
86
+ }
87
+ } catch (e) {
88
+ p.fail();
89
+ queued = false;
90
+ const code = e instanceof Error ? e.message : "error";
91
+ error = `Profiling failed (${code}). If the page is slow, the host's request timeout may have cut it ` + `off — try fewer renders, or tick the .ogp download and open it via Import. If a run got ` + `stuck, hit Reset on the dashboard.`;
92
+ }
93
+ }
94
+ onMount(run);
95
+ </script>
96
+
97
+ <div class="run">
98
+ <p class="phase">{queued ? '⏳ ' : ''}{phase}</p>
99
+ {#if queued}
100
+ <p class="hint">
101
+ Waited {waited_s}s. Recordings run one at a time per worker (the V8 profiler is process-wide)
102
+ — this keeps polling until one is free, then measures automatically.
103
+ </p>
104
+ {:else}
105
+ <div class="track"><div class="fill" style="width:{p.value}%"></div></div>
106
+ <p class="pct">{Math.round(p.value)}%</p>
107
+ {/if}
108
+
109
+ {#if error}
110
+ <p class="verdict">{error}</p>
111
+ <p class="hint"><a href={base}>← back to the dashboard</a></p>
112
+ {:else if done_ogp}
113
+ <p class="hint">
114
+ Your download didn't start? <a href="{base}/view">Open the Import page</a> and pick the file.
115
+ </p>
116
+ <p class="hint"><a href={base}>← back to the dashboard</a></p>
117
+ {/if}
118
+ </div>
119
+
120
+ <style>
121
+ .run {
122
+ max-width: 44rem;
123
+ margin: 2rem 0;
124
+ }
125
+ .phase {
126
+ margin: 0 0 0.6rem;
127
+ font-weight: 600;
128
+ }
129
+ .track {
130
+ height: 12px;
131
+ border-radius: 999px;
132
+ background: rgba(148, 163, 184, 0.22);
133
+ overflow: hidden;
134
+ }
135
+ .fill {
136
+ height: 100%;
137
+ border-radius: 999px;
138
+ background: linear-gradient(90deg, #14b8a6, #0ea5e9);
139
+ transition: width 0.24s ease-out;
140
+ }
141
+ .pct {
142
+ margin: 0.4rem 0 0;
143
+ font-variant-numeric: tabular-nums;
144
+ opacity: 0.7;
145
+ }
146
+ </style>
@@ -0,0 +1,10 @@
1
+ type $$ComponentProps = {
2
+ base: string;
3
+ path: string;
4
+ runs: number;
5
+ format: string;
6
+ against?: string;
7
+ };
8
+ declare const RunView: import("svelte").Component<$$ComponentProps, {}, "">;
9
+ type RunView = ReturnType<typeof RunView>;
10
+ export default RunView;
@@ -0,0 +1,197 @@
1
+ <script>let { score } = $props();
2
+ // Score → a token colour: green good, mint/accent fine, amber watch, red bad.
3
+ function tone(n) {
4
+ if (n >= 90) return "var(--good)";
5
+ if (n >= 75) return "var(--accent)";
6
+ if (n >= 50) return "var(--warn)";
7
+ return "var(--bad)";
8
+ }
9
+ const ring = $derived(tone(score.score));
10
+ export {};
11
+ </script>
12
+
13
+ <section class="scorecard" aria-label="ogygia page score">
14
+ <div class="ring-wrap">
15
+ <div
16
+ class="ring"
17
+ style="--pct:{score.score};--ring:{ring}"
18
+ role="img"
19
+ aria-label="score {score.score} of 100, grade {score.grade}"
20
+ >
21
+ <div class="ring-fill">
22
+ <b style="color:{ring}">{score.score}</b>
23
+ <span class="grade" style="color:{ring}">{score.grade}</span>
24
+ </div>
25
+ </div>
26
+ <div class="ring-cap">
27
+ <h2>page score</h2>
28
+ <p class="hint">
29
+ scored on what a visitor pays for, whatever built the page: all the JS at start, the weight
30
+ on the wire, what blocks the first paint, the HTML, the data shipped, the server render,
31
+ hydration, and the browser's vitals. Smooth curves: every byte and millisecond counts. A
32
+ category with no measurement is left out, never a free 100.
33
+ </p>
34
+ {#if score.worst}
35
+ <p class="win">
36
+ <span class="win-k" style="color:{tone(score.worst.score)}">Biggest win</span>
37
+ {score.worst.note}
38
+ </p>
39
+ {/if}
40
+ </div>
41
+ </div>
42
+
43
+ <div class="cats">
44
+ <!-- inline (not a {#snippet}): `c` is typed by score.categories, so no template type annotation
45
+ is needed — which keeps the markup TS-free AND satisfies svelte-check's noImplicitAny. -->
46
+ {#each score.categories as c (c.key)}
47
+ <div class="cat" title={c.note}>
48
+ <div class="cat-head">
49
+ <span class="cat-label">{c.label}</span>
50
+ <span class="cat-value">{c.value}</span>
51
+ <span class="cat-score" style="color:{tone(c.score)}">{c.score}</span>
52
+ </div>
53
+ <div class="track">
54
+ <div class="meter" style="width:{c.score}%;background:{tone(c.score)}"></div>
55
+ </div>
56
+ {#if c.lost || c.detail?.length}
57
+ <p class="cat-detail">
58
+ {#if c.lost}<span class="lost">−{c.lost} pts</span>{/if}
59
+ {#if c.detail?.length}{c.detail.join(' · ')}{/if}
60
+ </p>
61
+ {/if}
62
+ </div>
63
+ {/each}
64
+ {#if score.missing.length}
65
+ <p class="missing">
66
+ Left out: {#each score.missing as m, i (m.key)}{i ? '; ' : ''}<b>{m.label}</b>
67
+ ({m.why}){/each}.
68
+ </p>
69
+ {/if}
70
+ </div>
71
+ </section>
72
+
73
+ <style>
74
+ .scorecard {
75
+ display: grid;
76
+ grid-template-columns: minmax(280px, 1fr) minmax(0, 1.4fr);
77
+ gap: 1.5rem 2rem;
78
+ align-items: center;
79
+ padding: 1.25rem 1.5rem;
80
+ margin: 1rem 0 1.5rem;
81
+ background: var(--bg-raised);
82
+ border: 1px solid var(--line);
83
+ border-radius: var(--r-lg, 12px);
84
+ }
85
+ .ring-wrap {
86
+ display: flex;
87
+ gap: 1.25rem;
88
+ align-items: center;
89
+ }
90
+ .ring {
91
+ flex: none;
92
+ width: 108px;
93
+ height: 108px;
94
+ border-radius: 50%;
95
+ background: conic-gradient(var(--ring) calc(var(--pct) * 1%), var(--line) 0);
96
+ display: grid;
97
+ place-items: center;
98
+ }
99
+ .ring-fill {
100
+ width: 84px;
101
+ height: 84px;
102
+ border-radius: 50%;
103
+ background: var(--bg-panel, var(--bg-sunken));
104
+ display: grid;
105
+ place-items: center;
106
+ line-height: 1;
107
+ }
108
+ .ring-fill b {
109
+ font-size: 2rem;
110
+ font-variant-numeric: tabular-nums;
111
+ }
112
+ .grade {
113
+ font-size: 0.75rem;
114
+ font-weight: 700;
115
+ letter-spacing: 0.08em;
116
+ }
117
+ .ring-cap h2 {
118
+ margin: 0 0 0.25rem;
119
+ font-size: 1rem;
120
+ }
121
+ .ring-cap .hint {
122
+ margin: 0;
123
+ color: var(--text-dim);
124
+ font-size: 0.8rem;
125
+ line-height: 1.4;
126
+ }
127
+ .win {
128
+ margin: 0.6rem 0 0;
129
+ font-size: 0.82rem;
130
+ color: var(--text);
131
+ line-height: 1.4;
132
+ }
133
+ .win-k {
134
+ font-weight: 700;
135
+ margin-right: 0.35rem;
136
+ }
137
+ .cats {
138
+ display: grid;
139
+ gap: 0.6rem;
140
+ min-width: 0;
141
+ }
142
+ .cat-head {
143
+ display: flex;
144
+ align-items: baseline;
145
+ gap: 0.5rem;
146
+ font-size: 0.82rem;
147
+ }
148
+ .cat-label {
149
+ font-weight: 600;
150
+ }
151
+ .cat-value {
152
+ margin-left: auto;
153
+ color: var(--text-faint);
154
+ font-family: var(--font-mono);
155
+ font-size: 0.75rem;
156
+ }
157
+ .cat-score {
158
+ font-variant-numeric: tabular-nums;
159
+ font-weight: 700;
160
+ width: 2ch;
161
+ text-align: right;
162
+ }
163
+ .track {
164
+ height: 6px;
165
+ margin-top: 0.25rem;
166
+ border-radius: 999px;
167
+ background: var(--bg-sunken);
168
+ overflow: hidden;
169
+ }
170
+ .meter {
171
+ height: 100%;
172
+ border-radius: 999px;
173
+ transition: width 0.4s ease;
174
+ }
175
+ .cat-detail {
176
+ margin: 0.2rem 0 0;
177
+ font-size: 0.72rem;
178
+ color: var(--text-dim);
179
+ line-height: 1.35;
180
+ }
181
+ .lost {
182
+ color: var(--warn);
183
+ margin-right: 0.4rem;
184
+ font-variant-numeric: tabular-nums;
185
+ }
186
+ .missing {
187
+ margin: 0.4rem 0 0;
188
+ font-size: 0.72rem;
189
+ color: var(--text-dim);
190
+ line-height: 1.4;
191
+ }
192
+ @media (max-width: 640px) {
193
+ .scorecard {
194
+ grid-template-columns: 1fr;
195
+ }
196
+ }
197
+ </style>
@@ -0,0 +1,7 @@
1
+ import type { PageScore } from '../score.js';
2
+ type $$ComponentProps = {
3
+ score: PageScore;
4
+ };
5
+ declare const ScoreCard: import("svelte").Component<$$ComponentProps, {}, "">;
6
+ type ScoreCard = ReturnType<typeof ScoreCard>;
7
+ export default ScoreCard;