@buoy-gg/assets 7.0.40 → 7.0.42

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 (193) hide show
  1. package/README.md +12 -69
  2. package/bundlers/vite.d.ts +7 -0
  3. package/bundlers/vite.mjs +1 -0
  4. package/lib/commonjs/autoCapture.js +1 -0
  5. package/lib/commonjs/autoCapture.web.js +1 -0
  6. package/lib/commonjs/capture/assetLifecycle.js +1 -0
  7. package/lib/commonjs/capture/assetLifecycle.web.js +1 -0
  8. package/lib/commonjs/capture/browserAssets.js +1 -0
  9. package/lib/commonjs/capture/expo.js +1 -46
  10. package/lib/commonjs/capture/expo.web.js +1 -0
  11. package/lib/commonjs/capture/install.js +1 -91
  12. package/lib/commonjs/capture/install.web.js +1 -0
  13. package/lib/commonjs/capture/isBuoyAsset.js +1 -23
  14. package/lib/commonjs/capture/measure.js +1 -186
  15. package/lib/commonjs/capture/metroGraph.js +1 -175
  16. package/lib/commonjs/capture/metroGraph.web.js +1 -0
  17. package/lib/commonjs/capture/registry.js +1 -127
  18. package/lib/commonjs/components/AssetDetail.js +1 -211
  19. package/lib/commonjs/components/AssetImage.js +1 -66
  20. package/lib/commonjs/components/AssetRow.js +1 -232
  21. package/lib/commonjs/components/AssetsFilterBar.js +1 -105
  22. package/lib/commonjs/components/AssetsHeader.js +1 -73
  23. package/lib/commonjs/components/AssetsIcon.js +1 -19
  24. package/lib/commonjs/components/AssetsListControls.js +1 -81
  25. package/lib/commonjs/components/AssetsModal.js +1 -378
  26. package/lib/commonjs/components/ScanNotice.js +1 -85
  27. package/lib/commonjs/components/optionalExpoImage.js +1 -16
  28. package/lib/commonjs/components/optionalExpoImage.web.js +1 -11
  29. package/lib/commonjs/export.js +1 -62
  30. package/lib/commonjs/format.js +1 -59
  31. package/lib/commonjs/hooks/useAssetRecords.js +1 -22
  32. package/lib/commonjs/hooks/useAssetScanStatus.js +1 -28
  33. package/lib/commonjs/index.js +1 -313
  34. package/lib/commonjs/preset.js +1 -39
  35. package/lib/commonjs/remote.js +1 -68
  36. package/lib/commonjs/state.js +1 -51
  37. package/lib/commonjs/store/assetStore.js +1 -256
  38. package/lib/commonjs/store/baseline.js +1 -175
  39. package/lib/commonjs/store/insights.js +1 -120
  40. package/lib/commonjs/sync/assetsSyncAdapter.js +1 -157
  41. package/lib/commonjs/types.js +0 -1
  42. package/lib/commonjs/utils/deviceScale.js +1 -50
  43. package/lib/commonjs/utils/testIDs.js +1 -110
  44. package/lib/module/autoCapture.js +1 -0
  45. package/lib/module/autoCapture.web.js +1 -0
  46. package/lib/module/capture/assetLifecycle.js +1 -0
  47. package/lib/module/capture/assetLifecycle.web.js +1 -0
  48. package/lib/module/capture/browserAssets.js +1 -0
  49. package/lib/module/capture/expo.js +1 -41
  50. package/lib/module/capture/expo.web.js +1 -0
  51. package/lib/module/capture/install.js +1 -85
  52. package/lib/module/capture/install.web.js +1 -0
  53. package/lib/module/capture/isBuoyAsset.js +1 -18
  54. package/lib/module/capture/measure.js +1 -179
  55. package/lib/module/capture/metroGraph.js +1 -168
  56. package/lib/module/capture/metroGraph.web.js +1 -0
  57. package/lib/module/capture/registry.js +1 -120
  58. package/lib/module/components/AssetDetail.js +1 -207
  59. package/lib/module/components/AssetImage.js +1 -62
  60. package/lib/module/components/AssetRow.js +1 -228
  61. package/lib/module/components/AssetsFilterBar.js +1 -101
  62. package/lib/module/components/AssetsHeader.js +1 -69
  63. package/lib/module/components/AssetsIcon.js +1 -12
  64. package/lib/module/components/AssetsListControls.js +1 -77
  65. package/lib/module/components/AssetsModal.js +1 -373
  66. package/lib/module/components/ScanNotice.js +1 -81
  67. package/lib/module/components/optionalExpoImage.js +1 -12
  68. package/lib/module/components/optionalExpoImage.web.js +1 -7
  69. package/lib/module/export.js +1 -57
  70. package/lib/module/format.js +1 -51
  71. package/lib/module/hooks/useAssetRecords.js +1 -18
  72. package/lib/module/hooks/useAssetScanStatus.js +1 -23
  73. package/lib/module/index.js +1 -63
  74. package/lib/module/preset.js +1 -35
  75. package/lib/module/remote.js +1 -61
  76. package/lib/module/state.js +1 -47
  77. package/lib/module/store/assetStore.js +1 -240
  78. package/lib/module/store/baseline.js +1 -167
  79. package/lib/module/store/insights.js +1 -116
  80. package/lib/module/sync/assetsSyncAdapter.js +1 -153
  81. package/lib/module/types.js +0 -1
  82. package/lib/module/utils/deviceScale.js +1 -46
  83. package/lib/module/utils/testIDs.js +1 -99
  84. package/lib/typescript/autoCapture.d.ts +2 -0
  85. package/lib/typescript/autoCapture.web.d.ts +2 -0
  86. package/lib/typescript/capture/assetLifecycle.d.ts +3 -0
  87. package/lib/typescript/capture/assetLifecycle.web.d.ts +2 -0
  88. package/lib/typescript/capture/browserAssets.d.ts +13 -0
  89. package/lib/typescript/capture/expo.web.d.ts +3 -0
  90. package/lib/typescript/capture/install.web.d.ts +6 -0
  91. package/lib/typescript/capture/measure.d.ts +0 -10
  92. package/lib/typescript/capture/metroGraph.web.d.ts +12 -0
  93. package/lib/typescript/components/optionalExpoImage.web.d.ts +1 -1
  94. package/lib/typescript/index.d.ts +3 -0
  95. package/lib/typescript/types.d.ts +2 -1
  96. package/lib/web/index.mjs +3 -0
  97. package/package.json +46 -7
  98. package/lib/commonjs/capture/expo.js.map +0 -1
  99. package/lib/commonjs/capture/install.js.map +0 -1
  100. package/lib/commonjs/capture/isBuoyAsset.js.map +0 -1
  101. package/lib/commonjs/capture/measure.js.map +0 -1
  102. package/lib/commonjs/capture/metroGraph.js.map +0 -1
  103. package/lib/commonjs/capture/registry.js.map +0 -1
  104. package/lib/commonjs/components/AssetDetail.js.map +0 -1
  105. package/lib/commonjs/components/AssetImage.js.map +0 -1
  106. package/lib/commonjs/components/AssetRow.js.map +0 -1
  107. package/lib/commonjs/components/AssetsFilterBar.js.map +0 -1
  108. package/lib/commonjs/components/AssetsHeader.js.map +0 -1
  109. package/lib/commonjs/components/AssetsIcon.js.map +0 -1
  110. package/lib/commonjs/components/AssetsListControls.js.map +0 -1
  111. package/lib/commonjs/components/AssetsModal.js.map +0 -1
  112. package/lib/commonjs/components/ScanNotice.js.map +0 -1
  113. package/lib/commonjs/components/optionalExpoImage.js.map +0 -1
  114. package/lib/commonjs/components/optionalExpoImage.web.js.map +0 -1
  115. package/lib/commonjs/export.js.map +0 -1
  116. package/lib/commonjs/format.js.map +0 -1
  117. package/lib/commonjs/hooks/useAssetRecords.js.map +0 -1
  118. package/lib/commonjs/hooks/useAssetScanStatus.js.map +0 -1
  119. package/lib/commonjs/index.js.map +0 -1
  120. package/lib/commonjs/preset.js.map +0 -1
  121. package/lib/commonjs/remote.js.map +0 -1
  122. package/lib/commonjs/state.js.map +0 -1
  123. package/lib/commonjs/store/assetStore.js.map +0 -1
  124. package/lib/commonjs/store/baseline.js.map +0 -1
  125. package/lib/commonjs/store/insights.js.map +0 -1
  126. package/lib/commonjs/sync/assetsSyncAdapter.js.map +0 -1
  127. package/lib/commonjs/types.js.map +0 -1
  128. package/lib/commonjs/utils/deviceScale.js.map +0 -1
  129. package/lib/commonjs/utils/testIDs.js.map +0 -1
  130. package/lib/module/capture/expo.js.map +0 -1
  131. package/lib/module/capture/install.js.map +0 -1
  132. package/lib/module/capture/isBuoyAsset.js.map +0 -1
  133. package/lib/module/capture/measure.js.map +0 -1
  134. package/lib/module/capture/metroGraph.js.map +0 -1
  135. package/lib/module/capture/registry.js.map +0 -1
  136. package/lib/module/components/AssetDetail.js.map +0 -1
  137. package/lib/module/components/AssetImage.js.map +0 -1
  138. package/lib/module/components/AssetRow.js.map +0 -1
  139. package/lib/module/components/AssetsFilterBar.js.map +0 -1
  140. package/lib/module/components/AssetsHeader.js.map +0 -1
  141. package/lib/module/components/AssetsIcon.js.map +0 -1
  142. package/lib/module/components/AssetsListControls.js.map +0 -1
  143. package/lib/module/components/AssetsModal.js.map +0 -1
  144. package/lib/module/components/ScanNotice.js.map +0 -1
  145. package/lib/module/components/optionalExpoImage.js.map +0 -1
  146. package/lib/module/components/optionalExpoImage.web.js.map +0 -1
  147. package/lib/module/export.js.map +0 -1
  148. package/lib/module/format.js.map +0 -1
  149. package/lib/module/hooks/useAssetRecords.js.map +0 -1
  150. package/lib/module/hooks/useAssetScanStatus.js.map +0 -1
  151. package/lib/module/index.js.map +0 -1
  152. package/lib/module/preset.js.map +0 -1
  153. package/lib/module/remote.js.map +0 -1
  154. package/lib/module/state.js.map +0 -1
  155. package/lib/module/store/assetStore.js.map +0 -1
  156. package/lib/module/store/baseline.js.map +0 -1
  157. package/lib/module/store/insights.js.map +0 -1
  158. package/lib/module/sync/assetsSyncAdapter.js.map +0 -1
  159. package/lib/module/types.js.map +0 -1
  160. package/lib/module/utils/deviceScale.js.map +0 -1
  161. package/lib/module/utils/testIDs.js.map +0 -1
  162. package/lib/typescript/capture/expo.d.ts.map +0 -1
  163. package/lib/typescript/capture/install.d.ts.map +0 -1
  164. package/lib/typescript/capture/isBuoyAsset.d.ts.map +0 -1
  165. package/lib/typescript/capture/measure.d.ts.map +0 -1
  166. package/lib/typescript/capture/metroGraph.d.ts.map +0 -1
  167. package/lib/typescript/capture/registry.d.ts.map +0 -1
  168. package/lib/typescript/components/AssetDetail.d.ts.map +0 -1
  169. package/lib/typescript/components/AssetImage.d.ts.map +0 -1
  170. package/lib/typescript/components/AssetRow.d.ts.map +0 -1
  171. package/lib/typescript/components/AssetsFilterBar.d.ts.map +0 -1
  172. package/lib/typescript/components/AssetsHeader.d.ts.map +0 -1
  173. package/lib/typescript/components/AssetsIcon.d.ts.map +0 -1
  174. package/lib/typescript/components/AssetsListControls.d.ts.map +0 -1
  175. package/lib/typescript/components/AssetsModal.d.ts.map +0 -1
  176. package/lib/typescript/components/ScanNotice.d.ts.map +0 -1
  177. package/lib/typescript/components/optionalExpoImage.d.ts.map +0 -1
  178. package/lib/typescript/components/optionalExpoImage.web.d.ts.map +0 -1
  179. package/lib/typescript/export.d.ts.map +0 -1
  180. package/lib/typescript/format.d.ts.map +0 -1
  181. package/lib/typescript/hooks/useAssetRecords.d.ts.map +0 -1
  182. package/lib/typescript/hooks/useAssetScanStatus.d.ts.map +0 -1
  183. package/lib/typescript/index.d.ts.map +0 -1
  184. package/lib/typescript/preset.d.ts.map +0 -1
  185. package/lib/typescript/remote.d.ts.map +0 -1
  186. package/lib/typescript/state.d.ts.map +0 -1
  187. package/lib/typescript/store/assetStore.d.ts.map +0 -1
  188. package/lib/typescript/store/baseline.d.ts.map +0 -1
  189. package/lib/typescript/store/insights.d.ts.map +0 -1
  190. package/lib/typescript/sync/assetsSyncAdapter.d.ts.map +0 -1
  191. package/lib/typescript/types.d.ts.map +0 -1
  192. package/lib/typescript/utils/deviceScale.d.ts.map +0 -1
  193. package/lib/typescript/utils/testIDs.d.ts.map +0 -1
package/README.md CHANGED
@@ -1,84 +1,27 @@
1
- # @buoy-gg/assets
1
+ <div align="center">
2
2
 
3
- [![npm version](https://img.shields.io/npm/v/@buoy-gg/assets?style=flat-square&labelColor=1c1c1c&color=10B981)](https://www.npmjs.com/package/@buoy-gg/assets) [![npm downloads](https://img.shields.io/npm/dm/@buoy-gg/assets?style=flat-square&labelColor=1c1c1c&color=10B981)](https://www.npmjs.com/package/@buoy-gg/assets)
3
+ # @buoy-gg/assets
4
4
 
5
5
  Inspect assets visible to the runtime registry and, in development, the Metro dependency graph. Compare sizes and find possible duplicates.
6
6
 
7
- Part of [Buoy](https://github.com/Buoy-gg/buoy). Install the package, complete account setup, and follow the integration steps below.
7
+ <a href="https://buoy.gg/buoy/latest/docs/tools/assets"><b>Assets guide</b></a> &nbsp;·&nbsp; <a href="https://buoy.gg">buoy.gg</a> &nbsp;·&nbsp; <a href="https://github.com/Buoy-gg/buoy">All tools</a>
8
8
 
9
- Use the inventory to investigate large registered assets and possible duplication. Development builds can also query Metro; release builds have less source information.
10
-
11
- ## Install
9
+ [![npm version](https://img.shields.io/npm/v/@buoy-gg/assets?style=flat-square&labelColor=10302a&color=2a9d78)](https://www.npmjs.com/package/@buoy-gg/assets) [![npm downloads](https://img.shields.io/npm/dm/@buoy-gg/assets?style=flat-square&labelColor=10302a&color=2a9d78&label=downloads%2Fmonth)](https://www.npmjs.com/package/@buoy-gg/assets)
12
10
 
13
- ```bash
14
- npm install @buoy-gg/core @buoy-gg/assets
15
- ```
11
+ <a href="https://buoy.gg/buoy/latest/docs/tools/assets"><img src="https://raw.githubusercontent.com/Buoy-gg/buoy/main/.github/readme/tools/assets.png" alt="Watch the Assets film on buoy.gg" width="640" /></a>
16
12
 
17
- ## Before you start
13
+ </div>
18
14
 
19
- Use a development build with `@buoy-gg/core` and a Free or Pro Buoy account key. From your app’s directory, sign in:
15
+ ## Install
20
16
 
21
17
  ```bash
22
- npx --package=@buoy-gg/core buoy login
23
- ```
24
-
25
- For Expo, initialize Buoy before rendering the menu:
26
-
27
- ```tsx
28
- import { Buoy } from "@buoy-gg/core";
29
-
30
- Buoy.init({ licenseKey: process.env.EXPO_PUBLIC_BUOY_KEY });
31
- ```
32
-
33
- The login command writes the Expo key to `.env.local`. For React Native CLI, pass the key from your app’s environment configuration; React Native does not load `.env.local` automatically. Mount `FloatingDevTools` inside the same providers as your screens and restart the development server after installation. The [Quick Start](https://buoy.gg/buoy/latest/docs/quick-start) shows the complete root component setup.
34
-
35
- ## Quick start
36
-
37
- ```tsx
38
- import { FloatingDevTools } from "@buoy-gg/core";
39
-
40
- export default function App() {
41
- return (
42
- <>
43
- <YourApp />
44
- <FloatingDevTools />
45
- </>
46
- );
47
- }
18
+ npm install @buoy-gg/core @buoy-gg/assets
48
19
  ```
49
20
 
50
- The ASSETS tool appears in the menu. Open it and browse discovered assets, largest first.
51
-
52
- Buoy's own package assets are excluded from the inventory and its totals. App assets and assets from other libraries remain visible.
53
-
54
- SVG thumbnails and detail previews use `expo-image` when it is installed and available in the native app. It is an optional peer; `react-native-svg` is not required. Without a compatible renderer, the tool shows a preview-unavailable label. Desktop and web use browser image rendering. Some SVG paths may not render correctly with the iOS system decoder.
55
-
56
- Registered assets appear immediately. A spinner and a "found so far" count stay visible while the tool queries the development server for more assets. After eight seconds, a message explains that discovery is taking longer than usual. Size checks run afterward. If discovery fails or exceeds 90 seconds, the existing list stays available with a Retry button.
57
-
58
- ## Check the integration
59
-
60
- Find a known bundled asset and compare its source and dimensions. “Not observed” means not seen in React Native’s asset registry during this app run; it does not prove an asset is unused or safe to delete. Runtime coverage is not a complete inventory of native resources.
61
-
62
- ## What you get
63
-
64
- - **Inventory, largest first** — discovered assets with a thumbnail, dimensions, `@1x/@2x/@3x` scale coverage, and its size. Filter by kind, search by name, sort by size/name/type
65
- - **Size information** — development builds can measure available variants through Metro. Release decoded-memory estimates are not encoded file sizes
66
- - **Unobserved assets** — compare the available development bundle graph with assets registered during the session. Review candidates before deleting them
67
- - **Duplicate content** — identical bytes shipped under different names, flagged by content hash (one of the cheapest app-size wins there is)
68
- - **Audit findings** — images that decode larger than the device screen, heavy GIFs (every frame decodes into memory), unsubset icon fonts, WebP conversion candidates, missing/broken scale variants
69
- - **Loaded font families** — build-time embedded and runtime loaded (via the expo-font native module when present)
70
- - **Markdown report** — the full inventory with findings, ready to paste into an issue or PR
71
-
72
- ## How it relates to @buoy-gg/images
73
-
74
- [`@buoy-gg/images`](https://www.npmjs.com/package/@buoy-gg/images) shows what your app **renders** at runtime — per-load cache verdicts, timings, failures. Assets inspects the available asset inventory. Use both views to investigate loading behavior and bundle size.
75
-
76
- ## Desktop & AI
77
-
78
- To connect a React Native app to [Buoy Desktop](https://github.com/Buoy-gg/Buoy-Desktop) or MCP, install `@buoy-gg/external-sync` and follow the [Desktop connection guide](https://buoy.gg/buoy/latest/docs/desktop). Sign in to Desktop separately. [MCP setup](https://buoy.gg/buoy/latest/docs/mcp) also requires a process account and Pro access. Available remote actions depend on the tool and app integration.
21
+ Assets appears in the menu once installed. SVG previews use `expo-image` when it's available.
79
22
 
80
- ## Account and plan requirements
23
+ The [Assets guide](https://buoy.gg/buoy/latest/docs/tools/assets) covers setup, what it captures and its limits. New to Buoy? Start with the [Quick start](https://buoy.gg/buoy/latest/docs/quick-start).
81
24
 
82
- Use a Free or Pro Buoy account. History limits and paid features vary by tool; see [pricing](https://buoy.gg/pricing). Production access requires Pro where supported. Development-only hooks and actions remain unavailable in release builds.
25
+ ---
83
26
 
84
- Use **Duplicates** at the top of the asset list to show every asset that shares a content hash with another asset. The count includes all copies. Selecting it clears the search; select **All** or tap **Duplicates** again to return to the full list.
27
+ <sub>Part of <a href="https://buoy.gg">Buoy</a>, developer tools that live inside your app. Proprietary software. © Buoy LLC. <a href="https://buoy.gg/terms">Terms</a></sub>
@@ -0,0 +1,7 @@
1
+ /** Vite/Rollup accepts this plugin without a runtime dependency on Vite. */
2
+ export declare function buoyAssets(options?: { filename?: string }): {
3
+ name: string;
4
+ configResolved(config: any): void;
5
+ configureServer(server: any): void;
6
+ generateBundle(this: any, options: any, bundle: any): Promise<void>;
7
+ };
@@ -0,0 +1 @@
1
+ import{readdir as p,readFile as y}from"node:fs/promises";import{createHash as h}from"node:crypto";import c from"node:path";const m=/\.(?:avif|gif|jpe?g|png|svg|webp|ico|woff2?|ttf|otf|eot|mp[34]|m4a|ogg|wav|webm|pdf)$/i;const l=a=>h("sha256").update(a).digest("hex");export function buoyAssets({filename:a="buoy-assets.json"}={}){let i;const f=async()=>{if(!i.publicDir)return[];const r=[];async function o(s){let e;try{e=await p(s,{withFileTypes:true})}catch(t){if(t.code==="ENOENT")return;throw t}for(const t of e){const n=c.join(s,t.name);if(t.isDirectory())await o(n);else if(t.isFile()&&m.test(t.name)){const u=await y(n);r.push({url:`${i.base}${c.relative(i.publicDir,n).split(c.sep).map(encodeURIComponent).join("/")}`,bytes:u.length,hash:l(u)})}}}await o(i.publicDir);return r};return{name:"buoy-asset-manifest",configResolved(r){i=r},configureServer(r){r.middlewares.use(async(o,s,e)=>{if(o.url?.split("?")[0]!==`${i.base}${a}`)return e();try{s.setHeader("Content-Type","application/json");s.setHeader("Cache-Control","no-store");s.end(JSON.stringify(await f()))}catch(t){e(t)}})},async generateBundle(r,o){const s=await f();for(const e of Object.values(o)){if(e.type!=="asset"||e.fileName===a)continue;const t=typeof e.source==="string"?Buffer.from(e.source):e.source;s.push({url:`${i.base}${e.fileName}`,bytes:t.length,hash:l(t)})}this.emitFile({type:"asset",fileName:a,source:JSON.stringify(s)})}}}
@@ -0,0 +1 @@
1
+ "use strict";var _install=require("./capture/install");(0,_install.installAssetCapture)();
@@ -0,0 +1 @@
1
+ "use strict";Object.defineProperty(exports,"__esModule",{value:true});
@@ -0,0 +1 @@
1
+ "use strict";Object.defineProperty(exports,"__esModule",{value:true});exports.startBrowserAssetCapture=startBrowserAssetCapture;function startBrowserAssetCapture(){return()=>{}}
@@ -0,0 +1 @@
1
+ "use strict";Object.defineProperty(exports,"__esModule",{value:true});exports.startBrowserAssetCapture=startBrowserAssetCapture;var _install=require("./install.web");let owners=0;function startBrowserAssetCapture(){if(typeof document==="undefined")return()=>{};if(++owners===1)(0,_install.installAssetCapture)();let e=true;return()=>{if(e){e=false;if(--owners===0)(0,_install.stopBrowserAssetCapture)()}}}
@@ -0,0 +1 @@
1
+ "use strict";Object.defineProperty(exports,"__esModule",{value:true});exports.captureBrowserResource=captureBrowserResource;exports.getBrowserAssetManifest=getBrowserAssetManifest;exports.loadBrowserAssetManifest=loadBrowserAssetManifest;exports.registerBrowserAssetManifest=registerBrowserAssetManifest;exports.scanBrowserAssets=scanBrowserAssets;var _state=require("../state");var _assetStore=require("../store/assetStore");let manifest=[];function registerBrowserAssetManifest(e){manifest=e;if(typeof document!=="undefined")scanBrowserAssets()}function getBrowserAssetManifest(){return manifest}async function loadBrowserAssetManifest(e){const t=await fetch(e);if(!t.ok)throw new Error(`Asset manifest returned HTTP ${t.status}.`);const r=await t.json();if(!Array.isArray(r)||r.some(s=>!s||typeof s.url!=="string"))throw new Error("An asset manifest must contain an array of assets with URL strings.");registerBrowserAssetManifest(r)}function upsert(e,t){let r;try{r=new URL(e.url,document.baseURI)}catch{return}const s=r.pathname.split("/").pop()??"";const n=s.includes(".")?s.split(".").pop().toLowerCase():"other";const o=(0,_assetStore.upsertRecord)({key:r.href,name:s.slice(0,-(n.length+1))||s,type:n,origin:t?"browser":"graph",resolvedUri:r.href,resolvedScale:1,scales:[1],hash:e.hash,loaded:t,width:e.width,height:e.height});if(o&&e.bytes!==void 0&&e.bytes>=0)(0,_assetStore.updateRecord)(o.id,{sizeBytes:e.bytes,sizesByScale:{"1":e.bytes},sizeSource:"measured"})}function captureBrowserResource(e){if(e.initiatorType==="fetch"||e.initiatorType==="xmlhttprequest")return;upsert({url:e.name,bytes:e.encodedBodySize>0?e.encodedBodySize:void 0},true)}function scanBrowserAssets(){if(typeof document==="undefined"||(0,_state.assetsState)().captureDisabled)return;manifest.forEach(t=>upsert(t,false));performance.getEntriesByType("resource").forEach(t=>captureBrowserResource(t));document.querySelectorAll("img").forEach(t=>{if(!t.closest("[data-buoy-root]")&&t.currentSrc)upsert({url:t.currentSrc,width:t.naturalWidth||void 0,height:t.naturalHeight||void 0},t.complete&&t.naturalWidth>0)});const e=(0,_state.assetsState)();e.graphSupported=manifest.length>0;e.graphCount=manifest.length>0?manifest.length:null;e.measuredCount=e.records.filter(t=>t.sizeBytes!==void 0).length;e.lastScanAt=Date.now()}
@@ -1,46 +1 @@
1
- "use strict";
2
-
3
- Object.defineProperty(exports, "__esModule", {
4
- value: true
5
- });
6
- exports.getLoadedFontFamilies = getLoadedFontFamilies;
7
- exports.getLocalAssets = getLocalAssets;
8
- /**
9
- * Expo enrichment — all optional, all read through globalThis.expo guards so
10
- * bare RN apps (no expo-modules) silently get none of it and no imports are
11
- * added for anyone.
12
- */
13
-
14
- function expoModules() {
15
- return globalThis.expo?.modules;
16
- }
17
-
18
- /**
19
- * Every loaded font family — build-time embedded (config plugin / UIAppFonts /
20
- * android assets/fonts) AND runtime Font.loadAsync, straight from the native
21
- * module Expo documents as a stable global. [] when unavailable (bare RN).
22
- */
23
- function getLoadedFontFamilies() {
24
- try {
25
- const fonts = expoModules()?.ExpoFontLoader?.getLoadedFonts?.();
26
- return Array.isArray(fonts) ? [...new Set(fonts)].sort() : [];
27
- } catch {
28
- return [];
29
- }
30
- }
31
-
32
- /**
33
- * expo-updates' per-file-hash → local URI map: the COMPLETE shipped asset set
34
- * in Expo Go / OTA environments, independent of what JS has evaluated.
35
- * null when not running in an updates-managed environment.
36
- */
37
- function getLocalAssets() {
38
- try {
39
- const map = expoModules()?.ExpoUpdates?.localAssets;
40
- if (map && typeof map === "object" && Object.keys(map).length > 0) return map;
41
- return null;
42
- } catch {
43
- return null;
44
- }
45
- }
46
- //# sourceMappingURL=expo.js.map
1
+ "use strict";Object.defineProperty(exports,"__esModule",{value:true});exports.getLoadedFontFamilies=getLoadedFontFamilies;exports.getLocalAssets=getLocalAssets;function expoModules(){return globalThis.expo?.modules}function getLoadedFontFamilies(){try{const e=expoModules()?.ExpoFontLoader?.getLoadedFonts?.();return Array.isArray(e)?[...new Set(e)].sort():[]}catch{return[]}}function getLocalAssets(){try{const e=expoModules()?.ExpoUpdates?.localAssets;if(e&&typeof e==="object"&&Object.keys(e).length>0)return e;return null}catch{return null}}
@@ -0,0 +1 @@
1
+ "use strict";Object.defineProperty(exports,"__esModule",{value:true});exports.getLoadedFontFamilies=getLoadedFontFamilies;exports.getLocalAssets=getLocalAssets;function getLoadedFontFamilies(){if(typeof document==="undefined"||!document.fonts)return[];const e=new Set;document.fonts.forEach(t=>{if(t.status==="loaded")e.add(t.family.replace(/^['"]|['"]$/g,""))});return[...e].sort()}function getLocalAssets(){return null}
@@ -1,91 +1 @@
1
- "use strict";
2
-
3
- Object.defineProperty(exports, "__esModule", {
4
- value: true
5
- });
6
- exports.getScanStatus = getScanStatus;
7
- exports.installAssetCapture = installAssetCapture;
8
- exports.rescan = rescan;
9
- var _state = require("../state");
10
- var _assetStore = require("../store/assetStore");
11
- var _expo = require("./expo");
12
- var _measure = require("./measure");
13
- var _metroGraph = require("./metroGraph");
14
- var _registry = require("./registry");
15
- /**
16
- * Capture install + scan orchestration.
17
- *
18
- * installAssetCapture() is cheap and synchronous (registry walk + patch) and
19
- * runs at package import. The expensive passes — Metro graph fetch and byte
20
- * measurement — run in rescan(), triggered when the modal opens or via the
21
- * `rescan` sync action, so merely installing Buoy never hits the network.
22
- */
23
-
24
- function installAssetCapture() {
25
- const s = (0, _state.assetsState)();
26
- if (s.captureDisabled || s.installed) return;
27
- s.installed = true;
28
- s.registryAvailable = (0, _registry.getRegistryModule)() != null;
29
- s.patched = (0, _registry.patchRegisterAsset)();
30
- (0, _registry.walkRegistry)();
31
- refreshEnrichment();
32
- s.lastScanAt = Date.now();
33
- (0, _assetStore.invalidate)();
34
- }
35
- function refreshEnrichment() {
36
- const s = (0, _state.assetsState)();
37
- s.fontFamilies = (0, _expo.getLoadedFontFamilies)();
38
- const localAssets = (0, _expo.getLocalAssets)();
39
- s.localAssetCount = localAssets ? Object.keys(localAssets).length : null;
40
- }
41
-
42
- /**
43
- * Full scan: registry re-walk (catches anything the patch missed), Metro
44
- * graph merge (dev), Expo enrichment refresh, then size measurement.
45
- */
46
- async function rescan() {
47
- const s = (0, _state.assetsState)();
48
- if (s.captureDisabled) return getScanStatus();
49
- if (s.scanPromise) return s.scanPromise;
50
- s.scanPromise = runScan();
51
- try {
52
- return await s.scanPromise;
53
- } finally {
54
- s.scanPromise = undefined;
55
- }
56
- }
57
- async function runScan() {
58
- const s = (0, _state.assetsState)();
59
- (0, _assetStore.removeBuoyRecords)();
60
- installAssetCapture();
61
- (0, _registry.walkRegistry)();
62
- refreshEnrichment();
63
- await (0, _metroGraph.fetchAssetGraph)();
64
- s.lastScanAt = Date.now();
65
- (0, _assetStore.invalidate)();
66
- void (0, _measure.measureSizes)();
67
- return getScanStatus();
68
- }
69
- function getScanStatus() {
70
- const s = (0, _state.assetsState)();
71
- // Mirrors report the synced DEVICE's status, not the dashboard's.
72
- if (s.mirrorScanStatus) return s.mirrorScanStatus;
73
- let registryCount = 0;
74
- for (const record of s.records) if (record.registryId != null) registryCount++;
75
- return {
76
- registryAvailable: s.registryAvailable,
77
- patched: s.patched,
78
- registryCount,
79
- graphSupported: s.graphSupported || (0, _metroGraph.getDevServerOrigin)() != null,
80
- graphCount: s.graphCount,
81
- graphError: s.graphError,
82
- graphFetchInFlight: s.graphFetchInFlight,
83
- graphFetchStartedAt: s.graphFetchStartedAt ?? null,
84
- lastScanAt: s.lastScanAt,
85
- measuring: s.measuring,
86
- measuredCount: s.measuredCount,
87
- fontFamilies: s.fontFamilies,
88
- localAssetCount: s.localAssetCount
89
- };
90
- }
91
- //# sourceMappingURL=install.js.map
1
+ "use strict";Object.defineProperty(exports,"__esModule",{value:true});exports.getScanStatus=getScanStatus;exports.installAssetCapture=installAssetCapture;exports.rescan=rescan;var _state=require("../state");var _assetStore=require("../store/assetStore");var _expo=require("./expo");var _measure=require("./measure");var _metroGraph=require("./metroGraph");var _registry=require("./registry");function installAssetCapture(){const e=(0,_state.assetsState)();if(e.captureDisabled||e.installed)return;e.installed=true;e.registryAvailable=(0,_registry.getRegistryModule)()!=null;e.patched=(0,_registry.patchRegisterAsset)();(0,_registry.walkRegistry)();refreshEnrichment();e.lastScanAt=Date.now();(0,_assetStore.invalidate)()}function refreshEnrichment(){const e=(0,_state.assetsState)();e.fontFamilies=(0,_expo.getLoadedFontFamilies)();const t=(0,_expo.getLocalAssets)();e.localAssetCount=t?Object.keys(t).length:null}async function rescan(){const e=(0,_state.assetsState)();if(e.captureDisabled)return getScanStatus();if(e.scanPromise)return e.scanPromise;e.scanPromise=runScan();try{return await e.scanPromise}finally{e.scanPromise=void 0}}async function runScan(){const e=(0,_state.assetsState)();(0,_assetStore.removeBuoyRecords)();installAssetCapture();(0,_registry.walkRegistry)();refreshEnrichment();await(0,_metroGraph.fetchAssetGraph)();e.lastScanAt=Date.now();(0,_assetStore.invalidate)();void(0,_measure.measureSizes)();return getScanStatus()}function getScanStatus(){const e=(0,_state.assetsState)();if(e.mirrorScanStatus)return e.mirrorScanStatus;let t=0;for(const r of e.records)if(r.registryId!=null)t++;return{registryAvailable:e.registryAvailable,patched:e.patched,registryCount:t,graphSupported:e.graphSupported||(0,_metroGraph.getDevServerOrigin)()!=null,graphCount:e.graphCount,graphError:e.graphError,graphFetchInFlight:e.graphFetchInFlight,graphFetchStartedAt:e.graphFetchStartedAt??null,lastScanAt:e.lastScanAt,measuring:e.measuring,measuredCount:e.measuredCount,fontFamilies:e.fontFamilies,localAssetCount:e.localAssetCount}}
@@ -0,0 +1 @@
1
+ "use strict";Object.defineProperty(exports,"__esModule",{value:true});exports.getScanStatus=getScanStatus;exports.installAssetCapture=installAssetCapture;exports.rescan=rescan;exports.stopBrowserAssetCapture=stopBrowserAssetCapture;var _state=require("../state");var _assetStore=require("../store/assetStore");var _browserAssets=require("./browserAssets");var _expo=require("./expo");let observer;function installAssetCapture(){const e=(0,_state.assetsState)();if(typeof document==="undefined"||e.captureDisabled||e.installed)return;e.installed=true;e.registryAvailable=true;if(typeof PerformanceObserver!=="undefined"){observer=new PerformanceObserver(t=>{if((0,_state.assetsState)().captureDisabled){stopBrowserAssetCapture();return}t.getEntries().forEach(s=>(0,_browserAssets.captureBrowserResource)(s))});try{observer.observe({type:"resource",buffered:true});e.patched=true}catch{observer.disconnect();observer=void 0}}(0,_browserAssets.scanBrowserAssets)();e.fontFamilies=(0,_expo.getLoadedFontFamilies)();(0,_assetStore.invalidate)()}function stopBrowserAssetCapture(){observer?.disconnect();observer=void 0;(0,_state.assetsState)().installed=false;(0,_state.assetsState)().patched=false}async function rescan(){installAssetCapture();(0,_browserAssets.scanBrowserAssets)();(0,_state.assetsState)().fontFamilies=(0,_expo.getLoadedFontFamilies)();(0,_assetStore.invalidate)();return getScanStatus()}function getScanStatus(){const e=(0,_state.assetsState)();return e.mirrorScanStatus??{registryAvailable:e.registryAvailable,patched:e.patched,registryCount:e.records.filter(t=>t.loaded).length,graphSupported:e.graphSupported,graphCount:e.graphCount,graphError:null,graphFetchInFlight:false,graphFetchStartedAt:null,lastScanAt:e.lastScanAt,measuring:false,measuredCount:e.measuredCount,fontFamilies:e.fontFamilies,localAssetCount:null,browser:true}}
@@ -1,23 +1 @@
1
- "use strict";
2
-
3
- Object.defineProperty(exports, "__esModule", {
4
- value: true
5
- });
6
- exports.isBuoyAsset = isBuoyAsset;
7
- exports.isBuoyAssetPath = isBuoyAssetPath;
8
- /** Identify Buoy-owned resources by package location, never by asset name. */
9
- function isBuoyAssetPath(value) {
10
- if (!value) return false;
11
- let path = value;
12
- try {
13
- path = decodeURIComponent(path);
14
- } catch {
15
- // Keep readable path segments when an unrelated escape is malformed.
16
- }
17
- path = path.replace(/\\/g, "/");
18
- return /(?:^|\/)node_modules\/@buoy-gg\/[^/]+(?:\/|$)/.test(path) || /(?:^|\/)buoy-packages\/packages\/[^/]+(?:\/|$)/.test(path) || /(?:^|\/)packages\/floating-tools-core\/(?:src|lib\/(?:module|commonjs))\/icons\/assets(?:\/|$)/.test(path);
19
- }
20
- function isBuoyAsset(asset) {
21
- return [asset.key, asset.httpServerLocation, asset.fileSystemLocation, ...(asset.files ?? [])].some(isBuoyAssetPath);
22
- }
23
- //# sourceMappingURL=isBuoyAsset.js.map
1
+ "use strict";Object.defineProperty(exports,"__esModule",{value:true});exports.isBuoyAsset=isBuoyAsset;exports.isBuoyAssetPath=isBuoyAssetPath;function isBuoyAssetPath(e){if(!e)return false;let t=e;try{t=decodeURIComponent(t)}catch{}t=t.replace(/\\/g,"/");return/(?:^|\/)node_modules\/@buoy-gg\/[^/]+(?:\/|$)/.test(t)||/(?:^|\/)buoy-packages\/packages\/[^/]+(?:\/|$)/.test(t)||/(?:^|\/)packages\/floating-tools-core\/(?:src|lib\/(?:module|commonjs))\/icons\/assets(?:\/|$)/.test(t)}function isBuoyAsset(e){return[e.key,e.httpServerLocation,e.fileSystemLocation,...e.files??[]].some(isBuoyAssetPath)}
@@ -1,186 +1 @@
1
- "use strict";
2
-
3
- Object.defineProperty(exports, "__esModule", {
4
- value: true
5
- });
6
- exports.displaySource = displaySource;
7
- exports.measureSizes = measureSizes;
8
- exports.previewURL = previewURL;
9
- exports.variantURLs = variantURLs;
10
- var _state = require("../state");
11
- var _assetStore = require("../store/assetStore");
12
- var _metroGraph = require("./metroGraph");
13
- /**
14
- * Byte-size measurement.
15
- *
16
- * Dev only in practice: each scale variant is fetched from the Metro dev
17
- * server (HEAD first for Content-Length, GET-blob fallback since Metro
18
- * doesn't reliably answer HEAD) and the per-variant sizes are summed onto
19
- * the record. Android release resource ids and iOS file:// URIs are not
20
- * measurable from JS — those records keep `estDecodedBytes` as their only
21
- * size signal and the UI marks them as estimates.
22
- */
23
-
24
- const CONCURRENCY = 4;
25
-
26
- /**
27
- * Best displayable URL for a record: the resolved runtime URI, or (dev) the
28
- * same dev-server URL the measurement pass uses — this is what gives graph-
29
- * only (never-loaded) images real thumbnails.
30
- */
31
- function previewURL(record) {
32
- if (record.resolvedUri) return record.resolvedUri;
33
- const variants = variantURLs(record);
34
- return variants.length ? variants[0].url : null;
35
- }
36
-
37
- /**
38
- * Image source for thumbnails/previews. On device the NUMERIC registry id is
39
- * preferred (resolves natively — works for Android release resource ids too).
40
- * On dashboard mirrors that id belongs to the DEVICE's registry and rn-web
41
- * throws "asset with ID N could not be found" — use the device's http(s)
42
- * URL instead (the Metro dev server is reachable from the desktop).
43
- */
44
- function displaySource(record) {
45
- const mirror = (0, _state.assetsState)().captureDisabled;
46
- if (!mirror && record.registryId != null) return record.registryId;
47
- const uri = previewURL(record);
48
- if (!uri) return null;
49
- if (mirror && !/^https?:\/\//.test(uri)) return null;
50
- return {
51
- uri
52
- };
53
- }
54
-
55
- /** All scale-variant URLs for a record, derived without re-encoding pitfalls. */
56
- function variantURLs(record) {
57
- const scales = record.scales.length ? record.scales : [1];
58
-
59
- // Preferred: string surgery on the URL resolveAssetSource already proved
60
- // works (handles Expo's ?unstable_path= form and monorepo rewrites).
61
- const resolved = record.resolvedUri;
62
- if (resolved && /^https?:\/\//.test(resolved) && record.resolvedScale != null) {
63
- const pickedSuffix = record.resolvedScale === 1 ? "" : `@${record.resolvedScale}x`;
64
- const marker = `${pickedSuffix}.${record.type}`;
65
- if (resolved.includes(marker) || pickedSuffix === "") {
66
- return scales.map(scale => {
67
- const suffix = scale === 1 ? "" : `@${scale}x`;
68
- const url = (pickedSuffix === "" ? resolved.replace(`.${record.type}`, `${suffix}.${record.type}`) : resolved.replace(marker, `${suffix}.${record.type}`)).replace(/ /g, "%20"); // RN's asset path builder doesn't encode spaces
69
- return {
70
- scale,
71
- url
72
- };
73
- });
74
- }
75
- }
76
-
77
- // Graph-only records: rebuild the dev-server URL the way Metro's
78
- // AssetSourceResolver does (plain concatenation), encoding only spaces —
79
- // full encodeURI would double-encode Expo's pre-escaped unstable_path.
80
- const origin = (0, _metroGraph.getDevServerOrigin)();
81
- if (!origin || !record.httpServerLocation) return [];
82
- return scales.map(scale => {
83
- const suffix = scale === 1 ? "" : `@${scale}x`;
84
- const path = `${record.httpServerLocation}/${record.name}${suffix}.${record.type}`;
85
- const sep = path.includes("?") ? "&" : "?";
86
- const url = `${origin}${path}${sep}platform=${platformName()}${record.hash ? `&hash=${record.hash}` : ""}`.replace(/ /g, "%20");
87
- return {
88
- scale,
89
- url
90
- };
91
- });
92
- }
93
- function platformName() {
94
- try {
95
- return require("react-native").Platform.OS;
96
- } catch {
97
- return "ios";
98
- }
99
- }
100
- async function fetchSize(url) {
101
- try {
102
- const head = await fetch(url, {
103
- method: "HEAD"
104
- });
105
- if (head.ok) {
106
- const length = Number(head.headers.get("content-length"));
107
- if (Number.isFinite(length) && length > 0) return length;
108
- }
109
- } catch {
110
- // fall through to GET
111
- }
112
- try {
113
- const response = await fetch(url);
114
- if (!response.ok) return null;
115
- const blob = await response.blob();
116
- return blob.size > 0 ? blob.size : null;
117
- } catch {
118
- return null;
119
- }
120
- }
121
- async function measureRecord(record) {
122
- const variants = variantURLs(record);
123
- if (!variants.length) {
124
- (0, _assetStore.updateRecord)(record.id, {
125
- sizeSource: "estimate"
126
- });
127
- return;
128
- }
129
- const sizesByScale = {};
130
- let total = 0;
131
- for (const {
132
- scale,
133
- url
134
- } of variants) {
135
- const size = await fetchSize(url);
136
- if (size != null) {
137
- sizesByScale[String(scale)] = size;
138
- total += size;
139
- }
140
- }
141
- if (total > 0) {
142
- (0, _assetStore.updateRecord)(record.id, {
143
- sizesByScale,
144
- sizeBytes: total,
145
- sizeSource: "measured"
146
- });
147
- } else {
148
- (0, _assetStore.updateRecord)(record.id, {
149
- sizeSource: "estimate"
150
- });
151
- }
152
- }
153
-
154
- /** Measure every unmeasured record; safe to re-run (skips measured ones). */
155
- async function measureSizes() {
156
- const s = (0, _state.assetsState)();
157
- if (s.measuring) return {
158
- measured: s.measuredCount,
159
- total: (0, _assetStore.getSnapshot)().length
160
- };
161
- const pending = (0, _assetStore.getSnapshot)().filter(r => r.sizeSource !== "measured");
162
- s.measuring = true;
163
- (0, _assetStore.invalidate)();
164
- try {
165
- let index = 0;
166
- const worker = async () => {
167
- for (;;) {
168
- const next = pending[index++];
169
- if (!next) return;
170
- await measureRecord(next);
171
- s.measuredCount = (0, _assetStore.getSnapshot)().filter(r => r.sizeSource === "measured").length;
172
- }
173
- };
174
- await Promise.all(Array.from({
175
- length: Math.min(CONCURRENCY, pending.length)
176
- }, worker));
177
- } finally {
178
- s.measuring = false;
179
- (0, _assetStore.invalidate)();
180
- }
181
- return {
182
- measured: s.measuredCount,
183
- total: (0, _assetStore.getSnapshot)().length
184
- };
185
- }
186
- //# sourceMappingURL=measure.js.map
1
+ "use strict";Object.defineProperty(exports,"__esModule",{value:true});exports.displaySource=displaySource;exports.measureSizes=measureSizes;exports.previewURL=previewURL;exports.variantURLs=variantURLs;var _reactNative=require("react-native");var _state=require("../state");var _assetStore=require("../store/assetStore");var _metroGraph=require("./metroGraph");const CONCURRENCY=4;function previewURL(e){if(e.resolvedUri)return e.resolvedUri;const s=variantURLs(e);return s.length?s[0].url:null}function displaySource(e){const s=(0,_state.assetsState)().captureDisabled;if(!s&&e.registryId!=null)return e.registryId;const t=previewURL(e);if(!t)return null;if(s&&!/^https?:\/\//.test(t))return null;return{uri:t}}function variantURLs(e){const s=e.scales.length?e.scales:[1];const t=e.resolvedUri;if(t&&/^https?:\/\//.test(t)&&e.resolvedScale!=null){const n=e.resolvedScale===1?"":`@${e.resolvedScale}x`;const i=`${n}.${e.type}`;if(t.includes(i)||n===""){return s.map(r=>{const u=r===1?"":`@${r}x`;const o=(n===""?t.replace(`.${e.type}`,`${u}.${e.type}`):t.replace(i,`${u}.${e.type}`)).replace(/ /g,"%20");return{scale:r,url:o}})}}const a=(0,_metroGraph.getDevServerOrigin)();if(!a||!e.httpServerLocation)return[];return s.map(n=>{const i=n===1?"":`@${n}x`;const r=`${e.httpServerLocation}/${e.name}${i}.${e.type}`;const u=r.includes("?")?"&":"?";const o=`${a}${r}${u}platform=${platformName()}${e.hash?`&hash=${e.hash}`:""}`.replace(/ /g,"%20");return{scale:n,url:o}})}function platformName(){try{return _reactNative.Platform.OS}catch{return"ios"}}async function fetchSize(e){try{const s=await fetch(e,{method:"HEAD"});if(s.ok){const t=Number(s.headers.get("content-length"));if(Number.isFinite(t)&&t>0)return t}}catch{}try{const s=await fetch(e);if(!s.ok)return null;const t=await s.blob();return t.size>0?t.size:null}catch{return null}}async function measureRecord(e){const s=variantURLs(e);if(!s.length){(0,_assetStore.updateRecord)(e.id,{sizeSource:"estimate"});return}const t={};let a=0;for(const{scale:n,url:i}of s){const r=await fetchSize(i);if(r!=null){t[String(n)]=r;a+=r}}if(a>0){(0,_assetStore.updateRecord)(e.id,{sizesByScale:t,sizeBytes:a,sizeSource:"measured"})}else{(0,_assetStore.updateRecord)(e.id,{sizeSource:"estimate"})}}async function measureSizes(){const e=(0,_state.assetsState)();if(e.measuring)return{measured:e.measuredCount,total:(0,_assetStore.getSnapshot)().length};const s=(0,_assetStore.getSnapshot)().filter(t=>t.sizeSource!=="measured");e.measuring=true;(0,_assetStore.invalidate)();try{let t=0;const a=async()=>{for(;;){const n=s[t++];if(!n)return;await measureRecord(n);e.measuredCount=(0,_assetStore.getSnapshot)().filter(i=>i.sizeSource==="measured").length}};await Promise.all(Array.from({length:Math.min(CONCURRENCY,s.length)},a))}finally{e.measuring=false;(0,_assetStore.invalidate)()}return{measured:e.measuredCount,total:(0,_assetStore.getSnapshot)().length}}