@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.
- package/README.md +12 -69
- package/bundlers/vite.d.ts +7 -0
- package/bundlers/vite.mjs +1 -0
- package/lib/commonjs/autoCapture.js +1 -0
- package/lib/commonjs/autoCapture.web.js +1 -0
- package/lib/commonjs/capture/assetLifecycle.js +1 -0
- package/lib/commonjs/capture/assetLifecycle.web.js +1 -0
- package/lib/commonjs/capture/browserAssets.js +1 -0
- package/lib/commonjs/capture/expo.js +1 -46
- package/lib/commonjs/capture/expo.web.js +1 -0
- package/lib/commonjs/capture/install.js +1 -91
- package/lib/commonjs/capture/install.web.js +1 -0
- package/lib/commonjs/capture/isBuoyAsset.js +1 -23
- package/lib/commonjs/capture/measure.js +1 -186
- package/lib/commonjs/capture/metroGraph.js +1 -175
- package/lib/commonjs/capture/metroGraph.web.js +1 -0
- package/lib/commonjs/capture/registry.js +1 -127
- package/lib/commonjs/components/AssetDetail.js +1 -211
- package/lib/commonjs/components/AssetImage.js +1 -66
- package/lib/commonjs/components/AssetRow.js +1 -232
- package/lib/commonjs/components/AssetsFilterBar.js +1 -105
- package/lib/commonjs/components/AssetsHeader.js +1 -73
- package/lib/commonjs/components/AssetsIcon.js +1 -19
- package/lib/commonjs/components/AssetsListControls.js +1 -81
- package/lib/commonjs/components/AssetsModal.js +1 -378
- package/lib/commonjs/components/ScanNotice.js +1 -85
- package/lib/commonjs/components/optionalExpoImage.js +1 -16
- package/lib/commonjs/components/optionalExpoImage.web.js +1 -11
- package/lib/commonjs/export.js +1 -62
- package/lib/commonjs/format.js +1 -59
- package/lib/commonjs/hooks/useAssetRecords.js +1 -22
- package/lib/commonjs/hooks/useAssetScanStatus.js +1 -28
- package/lib/commonjs/index.js +1 -313
- package/lib/commonjs/preset.js +1 -39
- package/lib/commonjs/remote.js +1 -68
- package/lib/commonjs/state.js +1 -51
- package/lib/commonjs/store/assetStore.js +1 -256
- package/lib/commonjs/store/baseline.js +1 -175
- package/lib/commonjs/store/insights.js +1 -120
- package/lib/commonjs/sync/assetsSyncAdapter.js +1 -157
- package/lib/commonjs/types.js +0 -1
- package/lib/commonjs/utils/deviceScale.js +1 -50
- package/lib/commonjs/utils/testIDs.js +1 -110
- package/lib/module/autoCapture.js +1 -0
- package/lib/module/autoCapture.web.js +1 -0
- package/lib/module/capture/assetLifecycle.js +1 -0
- package/lib/module/capture/assetLifecycle.web.js +1 -0
- package/lib/module/capture/browserAssets.js +1 -0
- package/lib/module/capture/expo.js +1 -41
- package/lib/module/capture/expo.web.js +1 -0
- package/lib/module/capture/install.js +1 -85
- package/lib/module/capture/install.web.js +1 -0
- package/lib/module/capture/isBuoyAsset.js +1 -18
- package/lib/module/capture/measure.js +1 -179
- package/lib/module/capture/metroGraph.js +1 -168
- package/lib/module/capture/metroGraph.web.js +1 -0
- package/lib/module/capture/registry.js +1 -120
- package/lib/module/components/AssetDetail.js +1 -207
- package/lib/module/components/AssetImage.js +1 -62
- package/lib/module/components/AssetRow.js +1 -228
- package/lib/module/components/AssetsFilterBar.js +1 -101
- package/lib/module/components/AssetsHeader.js +1 -69
- package/lib/module/components/AssetsIcon.js +1 -12
- package/lib/module/components/AssetsListControls.js +1 -77
- package/lib/module/components/AssetsModal.js +1 -373
- package/lib/module/components/ScanNotice.js +1 -81
- package/lib/module/components/optionalExpoImage.js +1 -12
- package/lib/module/components/optionalExpoImage.web.js +1 -7
- package/lib/module/export.js +1 -57
- package/lib/module/format.js +1 -51
- package/lib/module/hooks/useAssetRecords.js +1 -18
- package/lib/module/hooks/useAssetScanStatus.js +1 -23
- package/lib/module/index.js +1 -63
- package/lib/module/preset.js +1 -35
- package/lib/module/remote.js +1 -61
- package/lib/module/state.js +1 -47
- package/lib/module/store/assetStore.js +1 -240
- package/lib/module/store/baseline.js +1 -167
- package/lib/module/store/insights.js +1 -116
- package/lib/module/sync/assetsSyncAdapter.js +1 -153
- package/lib/module/types.js +0 -1
- package/lib/module/utils/deviceScale.js +1 -46
- package/lib/module/utils/testIDs.js +1 -99
- package/lib/typescript/autoCapture.d.ts +2 -0
- package/lib/typescript/autoCapture.web.d.ts +2 -0
- package/lib/typescript/capture/assetLifecycle.d.ts +3 -0
- package/lib/typescript/capture/assetLifecycle.web.d.ts +2 -0
- package/lib/typescript/capture/browserAssets.d.ts +13 -0
- package/lib/typescript/capture/expo.web.d.ts +3 -0
- package/lib/typescript/capture/install.web.d.ts +6 -0
- package/lib/typescript/capture/measure.d.ts +0 -10
- package/lib/typescript/capture/metroGraph.web.d.ts +12 -0
- package/lib/typescript/components/optionalExpoImage.web.d.ts +1 -1
- package/lib/typescript/index.d.ts +3 -0
- package/lib/typescript/types.d.ts +2 -1
- package/lib/web/index.mjs +3 -0
- package/package.json +46 -7
- package/lib/commonjs/capture/expo.js.map +0 -1
- package/lib/commonjs/capture/install.js.map +0 -1
- package/lib/commonjs/capture/isBuoyAsset.js.map +0 -1
- package/lib/commonjs/capture/measure.js.map +0 -1
- package/lib/commonjs/capture/metroGraph.js.map +0 -1
- package/lib/commonjs/capture/registry.js.map +0 -1
- package/lib/commonjs/components/AssetDetail.js.map +0 -1
- package/lib/commonjs/components/AssetImage.js.map +0 -1
- package/lib/commonjs/components/AssetRow.js.map +0 -1
- package/lib/commonjs/components/AssetsFilterBar.js.map +0 -1
- package/lib/commonjs/components/AssetsHeader.js.map +0 -1
- package/lib/commonjs/components/AssetsIcon.js.map +0 -1
- package/lib/commonjs/components/AssetsListControls.js.map +0 -1
- package/lib/commonjs/components/AssetsModal.js.map +0 -1
- package/lib/commonjs/components/ScanNotice.js.map +0 -1
- package/lib/commonjs/components/optionalExpoImage.js.map +0 -1
- package/lib/commonjs/components/optionalExpoImage.web.js.map +0 -1
- package/lib/commonjs/export.js.map +0 -1
- package/lib/commonjs/format.js.map +0 -1
- package/lib/commonjs/hooks/useAssetRecords.js.map +0 -1
- package/lib/commonjs/hooks/useAssetScanStatus.js.map +0 -1
- package/lib/commonjs/index.js.map +0 -1
- package/lib/commonjs/preset.js.map +0 -1
- package/lib/commonjs/remote.js.map +0 -1
- package/lib/commonjs/state.js.map +0 -1
- package/lib/commonjs/store/assetStore.js.map +0 -1
- package/lib/commonjs/store/baseline.js.map +0 -1
- package/lib/commonjs/store/insights.js.map +0 -1
- package/lib/commonjs/sync/assetsSyncAdapter.js.map +0 -1
- package/lib/commonjs/types.js.map +0 -1
- package/lib/commonjs/utils/deviceScale.js.map +0 -1
- package/lib/commonjs/utils/testIDs.js.map +0 -1
- package/lib/module/capture/expo.js.map +0 -1
- package/lib/module/capture/install.js.map +0 -1
- package/lib/module/capture/isBuoyAsset.js.map +0 -1
- package/lib/module/capture/measure.js.map +0 -1
- package/lib/module/capture/metroGraph.js.map +0 -1
- package/lib/module/capture/registry.js.map +0 -1
- package/lib/module/components/AssetDetail.js.map +0 -1
- package/lib/module/components/AssetImage.js.map +0 -1
- package/lib/module/components/AssetRow.js.map +0 -1
- package/lib/module/components/AssetsFilterBar.js.map +0 -1
- package/lib/module/components/AssetsHeader.js.map +0 -1
- package/lib/module/components/AssetsIcon.js.map +0 -1
- package/lib/module/components/AssetsListControls.js.map +0 -1
- package/lib/module/components/AssetsModal.js.map +0 -1
- package/lib/module/components/ScanNotice.js.map +0 -1
- package/lib/module/components/optionalExpoImage.js.map +0 -1
- package/lib/module/components/optionalExpoImage.web.js.map +0 -1
- package/lib/module/export.js.map +0 -1
- package/lib/module/format.js.map +0 -1
- package/lib/module/hooks/useAssetRecords.js.map +0 -1
- package/lib/module/hooks/useAssetScanStatus.js.map +0 -1
- package/lib/module/index.js.map +0 -1
- package/lib/module/preset.js.map +0 -1
- package/lib/module/remote.js.map +0 -1
- package/lib/module/state.js.map +0 -1
- package/lib/module/store/assetStore.js.map +0 -1
- package/lib/module/store/baseline.js.map +0 -1
- package/lib/module/store/insights.js.map +0 -1
- package/lib/module/sync/assetsSyncAdapter.js.map +0 -1
- package/lib/module/types.js.map +0 -1
- package/lib/module/utils/deviceScale.js.map +0 -1
- package/lib/module/utils/testIDs.js.map +0 -1
- package/lib/typescript/capture/expo.d.ts.map +0 -1
- package/lib/typescript/capture/install.d.ts.map +0 -1
- package/lib/typescript/capture/isBuoyAsset.d.ts.map +0 -1
- package/lib/typescript/capture/measure.d.ts.map +0 -1
- package/lib/typescript/capture/metroGraph.d.ts.map +0 -1
- package/lib/typescript/capture/registry.d.ts.map +0 -1
- package/lib/typescript/components/AssetDetail.d.ts.map +0 -1
- package/lib/typescript/components/AssetImage.d.ts.map +0 -1
- package/lib/typescript/components/AssetRow.d.ts.map +0 -1
- package/lib/typescript/components/AssetsFilterBar.d.ts.map +0 -1
- package/lib/typescript/components/AssetsHeader.d.ts.map +0 -1
- package/lib/typescript/components/AssetsIcon.d.ts.map +0 -1
- package/lib/typescript/components/AssetsListControls.d.ts.map +0 -1
- package/lib/typescript/components/AssetsModal.d.ts.map +0 -1
- package/lib/typescript/components/ScanNotice.d.ts.map +0 -1
- package/lib/typescript/components/optionalExpoImage.d.ts.map +0 -1
- package/lib/typescript/components/optionalExpoImage.web.d.ts.map +0 -1
- package/lib/typescript/export.d.ts.map +0 -1
- package/lib/typescript/format.d.ts.map +0 -1
- package/lib/typescript/hooks/useAssetRecords.d.ts.map +0 -1
- package/lib/typescript/hooks/useAssetScanStatus.d.ts.map +0 -1
- package/lib/typescript/index.d.ts.map +0 -1
- package/lib/typescript/preset.d.ts.map +0 -1
- package/lib/typescript/remote.d.ts.map +0 -1
- package/lib/typescript/state.d.ts.map +0 -1
- package/lib/typescript/store/assetStore.d.ts.map +0 -1
- package/lib/typescript/store/baseline.d.ts.map +0 -1
- package/lib/typescript/store/insights.d.ts.map +0 -1
- package/lib/typescript/sync/assetsSyncAdapter.d.ts.map +0 -1
- package/lib/typescript/types.d.ts.map +0 -1
- package/lib/typescript/utils/deviceScale.d.ts.map +0 -1
- package/lib/typescript/utils/testIDs.d.ts.map +0 -1
package/lib/module/format.js
CHANGED
|
@@ -1,51 +1 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
|
|
3
|
-
/**
|
|
4
|
-
* Shared formatting helpers for rows, detail view, and markdown export.
|
|
5
|
-
*/
|
|
6
|
-
|
|
7
|
-
export function formatBytes(bytes) {
|
|
8
|
-
if (bytes == null || bytes <= 0) return "—";
|
|
9
|
-
if (bytes < 1024) return `${bytes} B`;
|
|
10
|
-
if (bytes < 1024 * 1024) return `${(bytes / 1024).toFixed(1)} KB`;
|
|
11
|
-
return `${(bytes / (1024 * 1024)).toFixed(2)} MB`;
|
|
12
|
-
}
|
|
13
|
-
export function formatScales(scales) {
|
|
14
|
-
const unique = [...new Set(scales)].sort((a, b) => a - b);
|
|
15
|
-
if (!unique.length) return "—";
|
|
16
|
-
if (unique.length === 1) return `@${unique[0]}x`;
|
|
17
|
-
if (unique.length <= 3) return unique.map(s => `@${s}x`).join(" ");
|
|
18
|
-
return `@${unique[0]}x–@${unique[unique.length - 1]}x`;
|
|
19
|
-
}
|
|
20
|
-
export function formatDimensions(record) {
|
|
21
|
-
if (record.width == null || record.height == null) return "—";
|
|
22
|
-
return `${Math.round(record.width)}×${Math.round(record.height)}`;
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
/** Display size: measured bytes, or "~" decoded estimate for unmeasured images. */
|
|
26
|
-
export function formatSize(record, estDecoded) {
|
|
27
|
-
if (record.sizeBytes != null && record.sizeSource === "measured") {
|
|
28
|
-
return formatBytes(record.sizeBytes);
|
|
29
|
-
}
|
|
30
|
-
if (estDecoded > 0) return `~${formatBytes(estDecoded)}`;
|
|
31
|
-
return "—";
|
|
32
|
-
}
|
|
33
|
-
export const KIND_LABELS = {
|
|
34
|
-
image: "IMG",
|
|
35
|
-
font: "FONT",
|
|
36
|
-
video: "VID",
|
|
37
|
-
audio: "AUD",
|
|
38
|
-
data: "DATA",
|
|
39
|
-
other: "MISC"
|
|
40
|
-
};
|
|
41
|
-
|
|
42
|
-
/** Family accent per kind — the card's left edge, like network's method bar. */
|
|
43
|
-
export const KIND_COLORS = {
|
|
44
|
-
image: "#2DD4BF",
|
|
45
|
-
font: "#C084FC",
|
|
46
|
-
video: "#FF9F1C",
|
|
47
|
-
audio: "#FF3366",
|
|
48
|
-
data: "#00D4FF",
|
|
49
|
-
other: "#8E8E93"
|
|
50
|
-
};
|
|
51
|
-
//# sourceMappingURL=format.js.map
|
|
1
|
+
"use strict";export function formatBytes(t){if(t==null||t<=0)return"\u2014";if(t<1024)return`${t} B`;if(t<1024*1024)return`${(t/1024).toFixed(1)} KB`;return`${(t/(1024*1024)).toFixed(2)} MB`}export function formatScales(t){const n=[...new Set(t)].sort((e,i)=>e-i);if(!n.length)return"\u2014";if(n.length===1)return`@${n[0]}x`;if(n.length<=3)return n.map(e=>`@${e}x`).join(" ");return`@${n[0]}x\u2013@${n[n.length-1]}x`}export function formatDimensions(t){if(t.width==null||t.height==null)return"\u2014";return`${Math.round(t.width)}\xD7${Math.round(t.height)}`}export function formatSize(t,n){if(t.sizeBytes!=null&&t.sizeSource==="measured"){return formatBytes(t.sizeBytes)}if(n>0)return`~${formatBytes(n)}`;return"\u2014"}export const KIND_LABELS={image:"IMG",font:"FONT",video:"VID",audio:"AUD",data:"DATA",other:"MISC"};export const KIND_COLORS={image:"#2DD4BF",font:"#C084FC",video:"#FF9F1C",audio:"#FF3366",data:"#00D4FF",other:"#8E8E93"};
|
|
@@ -1,18 +1 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
|
|
3
|
-
/**
|
|
4
|
-
* React bindings for the asset store.
|
|
5
|
-
*/
|
|
6
|
-
|
|
7
|
-
import { useMemo, useSyncExternalStore } from "react";
|
|
8
|
-
import { computeStats, getSnapshot, subscribe } from "../store/assetStore";
|
|
9
|
-
import { computeInsights } from "../store/insights";
|
|
10
|
-
export function useAssetRecords() {
|
|
11
|
-
const snapshot = useSyncExternalStore(subscribe, getSnapshot, getSnapshot);
|
|
12
|
-
return useMemo(() => ({
|
|
13
|
-
records: snapshot,
|
|
14
|
-
stats: computeStats(snapshot),
|
|
15
|
-
insights: computeInsights(snapshot)
|
|
16
|
-
}), [snapshot]);
|
|
17
|
-
}
|
|
18
|
-
//# sourceMappingURL=useAssetRecords.js.map
|
|
1
|
+
"use strict";import{useMemo as o,useSyncExternalStore as e}from"react";import{computeStats as r,getSnapshot as s,subscribe as n}from"../store/assetStore";import{computeInsights as c}from"../store/insights";export function useAssetRecords(){const t=e(n,s,s);return o(()=>({records:t,stats:r(t),insights:c(t)}),[t])}
|
|
@@ -1,23 +1 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
|
|
3
|
-
import { useSyncExternalStore } from "react";
|
|
4
|
-
import { getScanStatus } from "../capture/install";
|
|
5
|
-
import { getSnapshot, subscribe } from "../store/assetStore";
|
|
6
|
-
let previousRecords;
|
|
7
|
-
let previousStatus;
|
|
8
|
-
|
|
9
|
-
/** Each store notification replaces the records snapshot, including status-only updates. */
|
|
10
|
-
export function getAssetScanSnapshot() {
|
|
11
|
-
const records = getSnapshot();
|
|
12
|
-
if (records !== previousRecords) {
|
|
13
|
-
previousRecords = records;
|
|
14
|
-
previousStatus = getScanStatus();
|
|
15
|
-
}
|
|
16
|
-
return previousStatus;
|
|
17
|
-
}
|
|
18
|
-
|
|
19
|
-
/** Keep scan status reactive in apps that use React Compiler. */
|
|
20
|
-
export function useAssetScanStatus() {
|
|
21
|
-
return useSyncExternalStore(subscribe, getAssetScanSnapshot, getAssetScanSnapshot);
|
|
22
|
-
}
|
|
23
|
-
//# sourceMappingURL=useAssetScanStatus.js.map
|
|
1
|
+
"use strict";import{useSyncExternalStore as s}from"react";import{getScanStatus as o}from"../capture/install";import{getSnapshot as n,subscribe as u}from"../store/assetStore";let e;let r;export function getAssetScanSnapshot(){const t=n();if(t!==e){e=t;r=o()}return r}export function useAssetScanStatus(){return s(u,getAssetScanSnapshot,getAssetScanSnapshot)}
|
package/lib/module/index.js
CHANGED
|
@@ -1,63 +1 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
|
|
3
|
-
/**
|
|
4
|
-
* @buoy-gg/assets — bundled-asset inventory for React Native / Expo.
|
|
5
|
-
*
|
|
6
|
-
* Enumerates every asset in the app (images, fonts, video, audio, …) via the
|
|
7
|
-
* runtime asset registry, enriched in dev with the Metro graph (full-bundle
|
|
8
|
-
* coverage, byte sizes, never-loaded detection) and on Expo with loaded font
|
|
9
|
-
* families + the updates localAssets map. Zero configuration: importing this
|
|
10
|
-
* package installs the (cheap, synchronous) registry capture.
|
|
11
|
-
*/
|
|
12
|
-
|
|
13
|
-
// ---------------------------------------------------------------------------
|
|
14
|
-
// Tool preset (FloatingDevTools)
|
|
15
|
-
// ---------------------------------------------------------------------------
|
|
16
|
-
export { assetsToolPreset, createAssetsTool } from "./preset";
|
|
17
|
-
|
|
18
|
-
// ---------------------------------------------------------------------------
|
|
19
|
-
// Components
|
|
20
|
-
// ---------------------------------------------------------------------------
|
|
21
|
-
export { AssetsModal, AssetsToolView } from "./components/AssetsModal";
|
|
22
|
-
export { AssetsIcon, ASSETS_ICON_COLOR } from "./components/AssetsIcon";
|
|
23
|
-
|
|
24
|
-
// ---------------------------------------------------------------------------
|
|
25
|
-
// Capture / scanning
|
|
26
|
-
// ---------------------------------------------------------------------------
|
|
27
|
-
export { installAssetCapture, rescan, getScanStatus } from "./capture/install";
|
|
28
|
-
export { measureSizes } from "./capture/measure";
|
|
29
|
-
export { fetchAssetGraph, getDevServerOrigin } from "./capture/metroGraph";
|
|
30
|
-
export { getLoadedFontFamilies, getLocalAssets } from "./capture/expo";
|
|
31
|
-
|
|
32
|
-
// ---------------------------------------------------------------------------
|
|
33
|
-
// Store
|
|
34
|
-
// ---------------------------------------------------------------------------
|
|
35
|
-
export { clearRecords, computeStats, estDecodedBytes, getRecord, getSnapshot, subscribe } from "./store/assetStore";
|
|
36
|
-
export { computeInsights } from "./store/insights";
|
|
37
|
-
export { clearBaseline, computeDiff, getDiff, loadBaseline, saveBaseline } from "./store/baseline";
|
|
38
|
-
export { useAssetRecords } from "./hooks/useAssetRecords";
|
|
39
|
-
|
|
40
|
-
// ---------------------------------------------------------------------------
|
|
41
|
-
// Reports
|
|
42
|
-
// ---------------------------------------------------------------------------
|
|
43
|
-
export { formatAssetMarkdown, formatInventoryMarkdown } from "./export";
|
|
44
|
-
|
|
45
|
-
// ---------------------------------------------------------------------------
|
|
46
|
-
// External sync (desktop dashboard + MCP)
|
|
47
|
-
// ---------------------------------------------------------------------------
|
|
48
|
-
export { assetsSyncAdapter } from "./sync/assetsSyncAdapter";
|
|
49
|
-
export { disableAssetsCapture, replaceAssetsFromSnapshot, setRemoteAssetsHandler } from "./remote";
|
|
50
|
-
// ---------------------------------------------------------------------------
|
|
51
|
-
// Automation handles
|
|
52
|
-
// ---------------------------------------------------------------------------
|
|
53
|
-
export { ASSETS_TEST_IDS, assetBadgeTestID, assetDetailRowTestID, assetFilterTestID, assetFindingTestID, assetFontChipTestID, assetRowTestID, assetSlug } from "./utils/testIDs";
|
|
54
|
-
|
|
55
|
-
// ---------------------------------------------------------------------------
|
|
56
|
-
// Types
|
|
57
|
-
// ---------------------------------------------------------------------------
|
|
58
|
-
|
|
59
|
-
// Side effect: install the registry capture at import (walk + patch — cheap,
|
|
60
|
-
// synchronous, no network). The Metro graph fetch waits for the modal/action.
|
|
61
|
-
import { installAssetCapture as installOnImport } from "./capture/install";
|
|
62
|
-
installOnImport();
|
|
63
|
-
//# sourceMappingURL=index.js.map
|
|
1
|
+
"use strict";export{assetsToolPreset,createAssetsTool}from"./preset";export{AssetsModal,AssetsToolView}from"./components/AssetsModal";export{AssetsIcon,ASSETS_ICON_COLOR}from"./components/AssetsIcon";export{installAssetCapture,rescan,getScanStatus}from"./capture/install";export{measureSizes}from"./capture/measure";export{fetchAssetGraph,getDevServerOrigin}from"./capture/metroGraph";export{getLoadedFontFamilies,getLocalAssets}from"./capture/expo";export{clearRecords,computeStats,estDecodedBytes,getRecord,getSnapshot,subscribe}from"./store/assetStore";export{computeInsights}from"./store/insights";export{clearBaseline,computeDiff,getDiff,loadBaseline,saveBaseline}from"./store/baseline";export{useAssetRecords}from"./hooks/useAssetRecords";export{formatAssetMarkdown,formatInventoryMarkdown}from"./export";export{assetsSyncAdapter}from"./sync/assetsSyncAdapter";export{disableAssetsCapture,replaceAssetsFromSnapshot,setRemoteAssetsHandler}from"./remote";export{ASSETS_TEST_IDS,assetBadgeTestID,assetDetailRowTestID,assetFilterTestID,assetFindingTestID,assetFontChipTestID,assetRowTestID,assetSlug}from"./utils/testIDs";import"./autoCapture";export{registerBrowserAssetManifest,loadBrowserAssetManifest,getBrowserAssetManifest}from"./capture/browserAssets";export{startBrowserAssetCapture}from"./capture/assetLifecycle";
|
package/lib/module/preset.js
CHANGED
|
@@ -1,35 +1 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
|
|
3
|
-
/**
|
|
4
|
-
* Pre-configured Assets tool for FloatingDevTools.
|
|
5
|
-
*
|
|
6
|
-
* @example
|
|
7
|
-
* ```tsx
|
|
8
|
-
* import { assetsToolPreset } from '@buoy-gg/assets';
|
|
9
|
-
*
|
|
10
|
-
* <FloatingDevTools apps={[assetsToolPreset]} />
|
|
11
|
-
* ```
|
|
12
|
-
*/
|
|
13
|
-
|
|
14
|
-
import { AssetsIcon, ASSETS_ICON_COLOR } from "./components/AssetsIcon";
|
|
15
|
-
import { AssetsModal } from "./components/AssetsModal";
|
|
16
|
-
import { createToolFactory, defineToolPreset } from "@buoy-gg/shared-ui";
|
|
17
|
-
import { jsx as _jsx } from "react/jsx-runtime";
|
|
18
|
-
export const assetsToolPreset = defineToolPreset({
|
|
19
|
-
id: "assets",
|
|
20
|
-
name: "ASSETS",
|
|
21
|
-
description: "Every bundled asset — sizes, scale coverage, unused detection",
|
|
22
|
-
slot: "both",
|
|
23
|
-
icon: ({
|
|
24
|
-
size,
|
|
25
|
-
color
|
|
26
|
-
}) => /*#__PURE__*/_jsx(AssetsIcon, {
|
|
27
|
-
size: size,
|
|
28
|
-
color: color || ASSETS_ICON_COLOR
|
|
29
|
-
}),
|
|
30
|
-
component: AssetsModal
|
|
31
|
-
});
|
|
32
|
-
|
|
33
|
-
/** Create a custom Assets tool configuration. */
|
|
34
|
-
export const createAssetsTool = createToolFactory(assetsToolPreset);
|
|
35
|
-
//# sourceMappingURL=preset.js.map
|
|
1
|
+
"use strict";import{AssetsIcon as e,ASSETS_ICON_COLOR as t}from"./components/AssetsIcon";import{AssetsModal as r}from"./components/AssetsModal";import{createToolFactory as c,defineToolPreset as i}from"@buoy-gg/shared-ui";import{jsx as n}from"react/jsx-runtime";export const assetsToolPreset=i({id:"assets",name:"ASSETS",description:"Every bundled asset \u2014 sizes, scale coverage, unused detection",slot:"both",icon:({size:o,color:s})=>n(e,{size:o,color:s||t}),component:r});export const createAssetsTool=c(assetsToolPreset);
|
package/lib/module/remote.js
CHANGED
|
@@ -1,61 +1 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
|
|
3
|
-
/**
|
|
4
|
-
* Remote-dispatch seam for dashboard mirrors (Buoy Desktop).
|
|
5
|
-
*
|
|
6
|
-
* On device this stays null and every action runs locally. A dashboard sets
|
|
7
|
-
* a handler that forwards action name + params over external-sync to the
|
|
8
|
-
* SAME adapter actions the MCP uses (sync/assetsSyncAdapter.ts), so one
|
|
9
|
-
* action vocabulary serves phone UI, desktop UI, and LLM automation.
|
|
10
|
-
*/
|
|
11
|
-
|
|
12
|
-
import { assetsState } from "./state";
|
|
13
|
-
import { invalidate } from "./store/assetStore";
|
|
14
|
-
export function setRemoteAssetsHandler(handler) {
|
|
15
|
-
assetsState().remoteDispatch = handler;
|
|
16
|
-
}
|
|
17
|
-
export function remoteAssetsDispatch() {
|
|
18
|
-
return assetsState().remoteDispatch;
|
|
19
|
-
}
|
|
20
|
-
|
|
21
|
-
/** Dashboards never scan their own bundle — the store is purely a mirror. */
|
|
22
|
-
export function disableAssetsCapture() {
|
|
23
|
-
assetsState().captureDisabled = true;
|
|
24
|
-
}
|
|
25
|
-
|
|
26
|
-
/** Replace the whole store from a synced adapter snapshot. */
|
|
27
|
-
export function replaceAssetsFromSnapshot(payload) {
|
|
28
|
-
const s = assetsState();
|
|
29
|
-
const wire = payload.records ?? [];
|
|
30
|
-
s.records = wire.map(w => ({
|
|
31
|
-
id: w.id,
|
|
32
|
-
key: w.key,
|
|
33
|
-
registryId: w.registryId ?? undefined,
|
|
34
|
-
name: w.name,
|
|
35
|
-
type: w.type,
|
|
36
|
-
kind: w.kind,
|
|
37
|
-
hash: w.hash ?? undefined,
|
|
38
|
-
httpServerLocation: w.location ?? undefined,
|
|
39
|
-
width: w.width ?? undefined,
|
|
40
|
-
height: w.height ?? undefined,
|
|
41
|
-
scales: w.scales,
|
|
42
|
-
resolvedUri: w.uri ?? undefined,
|
|
43
|
-
loaded: w.loaded,
|
|
44
|
-
origin: w.registryId != null ? "registry" : "graph",
|
|
45
|
-
sizeBytes: w.sizeBytes ?? undefined,
|
|
46
|
-
sizeSource: w.sizeSource ?? undefined,
|
|
47
|
-
firstSeenAt: Date.now()
|
|
48
|
-
}));
|
|
49
|
-
s.byKey = new Map(s.records.map(r => [r.key, r]));
|
|
50
|
-
s.byId = new Map(s.records.map(r => [r.id, r]));
|
|
51
|
-
if (payload.scanStatus) {
|
|
52
|
-
s.fontFamilies = [...new Set(payload.scanStatus.fontFamilies ?? [])];
|
|
53
|
-
s.mirrorScanStatus = {
|
|
54
|
-
...payload.scanStatus,
|
|
55
|
-
fontFamilies: s.fontFamilies
|
|
56
|
-
};
|
|
57
|
-
}
|
|
58
|
-
s.mirrorDiff = payload.diff ?? null;
|
|
59
|
-
invalidate();
|
|
60
|
-
}
|
|
61
|
-
//# sourceMappingURL=remote.js.map
|
|
1
|
+
"use strict";import{assetsState as s}from"./state";import{invalidate as r}from"./store/assetStore";export function setRemoteAssetsHandler(i){s().remoteDispatch=i}export function remoteAssetsDispatch(){return s().remoteDispatch}export function disableAssetsCapture(){s().captureDisabled=true}export function replaceAssetsFromSnapshot(i){const t=s();const n=i.records??[];t.records=n.map(e=>({id:e.id,key:e.key,registryId:e.registryId??void 0,name:e.name,type:e.type,kind:e.kind,hash:e.hash??void 0,httpServerLocation:e.location??void 0,width:e.width??void 0,height:e.height??void 0,scales:e.scales,resolvedUri:e.uri??void 0,loaded:e.loaded,origin:e.registryId!=null?"registry":"graph",sizeBytes:e.sizeBytes??void 0,sizeSource:e.sizeSource??void 0,firstSeenAt:Date.now()}));t.byKey=new Map(t.records.map(e=>[e.key,e]));t.byId=new Map(t.records.map(e=>[e.id,e]));if(i.scanStatus){t.fontFamilies=[...new Set(i.scanStatus.fontFamilies??[])];t.mirrorScanStatus={...i.scanStatus,fontFamilies:t.fontFamilies}}t.mirrorDiff=i.diff??null;r()}
|
package/lib/module/state.js
CHANGED
|
@@ -1,47 +1 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
|
|
3
|
-
/**
|
|
4
|
-
* Global singleton state for the Assets tool.
|
|
5
|
-
*
|
|
6
|
-
* Same rationale as the images tool: the package can be evaluated as two
|
|
7
|
-
* module instances (lib vs src resolution), and the registerAsset patch must
|
|
8
|
-
* share one store with whichever copy the UI renders from. All mutable state
|
|
9
|
-
* lives on globalThis under a well-known symbol.
|
|
10
|
-
*/
|
|
11
|
-
|
|
12
|
-
const KEY = Symbol.for("buoy.assets.globalState.v1");
|
|
13
|
-
export function assetsState() {
|
|
14
|
-
const g = globalThis;
|
|
15
|
-
if (!g[KEY]) {
|
|
16
|
-
g[KEY] = {
|
|
17
|
-
records: [],
|
|
18
|
-
byKey: new Map(),
|
|
19
|
-
byId: new Map(),
|
|
20
|
-
nextId: 1,
|
|
21
|
-
listeners: new Set(),
|
|
22
|
-
snapshot: [],
|
|
23
|
-
emitScheduled: false,
|
|
24
|
-
installed: false,
|
|
25
|
-
patched: false,
|
|
26
|
-
registryAvailable: false,
|
|
27
|
-
graphSupported: false,
|
|
28
|
-
graphCount: null,
|
|
29
|
-
graphError: null,
|
|
30
|
-
graphFetchInFlight: false,
|
|
31
|
-
lastScanAt: null,
|
|
32
|
-
measuring: false,
|
|
33
|
-
measuredCount: 0,
|
|
34
|
-
fontFamilies: [],
|
|
35
|
-
localAssetCount: null,
|
|
36
|
-
baseline: null,
|
|
37
|
-
baselineLoaded: false,
|
|
38
|
-
captureDisabled: false,
|
|
39
|
-
remoteDispatch: null,
|
|
40
|
-
mirrorScanStatus: null,
|
|
41
|
-
mirrorPixelRatio: null,
|
|
42
|
-
mirrorDiff: null
|
|
43
|
-
};
|
|
44
|
-
}
|
|
45
|
-
return g[KEY];
|
|
46
|
-
}
|
|
47
|
-
//# sourceMappingURL=state.js.map
|
|
1
|
+
"use strict";const l=Symbol.for("buoy.assets.globalState.v1");export function assetsState(){const e=globalThis;if(!e[l]){e[l]={records:[],byKey:new Map,byId:new Map,nextId:1,listeners:new Set,snapshot:[],emitScheduled:false,installed:false,patched:false,registryAvailable:false,graphSupported:false,graphCount:null,graphError:null,graphFetchInFlight:false,lastScanAt:null,measuring:false,measuredCount:0,fontFamilies:[],localAssetCount:null,baseline:null,baselineLoaded:false,captureDisabled:false,remoteDispatch:null,mirrorScanStatus:null,mirrorPixelRatio:null,mirrorDiff:null}}return e[l]}
|
|
@@ -1,240 +1 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
|
|
3
|
-
/**
|
|
4
|
-
* assetStore
|
|
5
|
-
*
|
|
6
|
-
* Bounded store of AssetRecords keyed by their stable asset key
|
|
7
|
-
* (`location/name.type`). Follows the images tool's store shape — Set of
|
|
8
|
-
* listeners, frame-coalesced emit, all mutable state on the globalThis
|
|
9
|
-
* singleton (../state.ts) so dual module instances share one store.
|
|
10
|
-
*
|
|
11
|
-
* Unlike the images tool this is an INVENTORY, not an event log: upserts
|
|
12
|
-
* merge into the existing record for a key instead of appending, and there
|
|
13
|
-
* is no ring-buffer cap (a bundle has a bounded asset count by construction).
|
|
14
|
-
*/
|
|
15
|
-
|
|
16
|
-
import { assetsState } from "../state";
|
|
17
|
-
import { isBuoyAsset } from "../capture/isBuoyAsset";
|
|
18
|
-
import { effectivePixelRatio, pickScale } from "../utils/deviceScale";
|
|
19
|
-
function emit() {
|
|
20
|
-
const s = assetsState();
|
|
21
|
-
if (s.emitScheduled) return;
|
|
22
|
-
s.emitScheduled = true;
|
|
23
|
-
requestAnimationFrame(() => {
|
|
24
|
-
s.emitScheduled = false;
|
|
25
|
-
for (const listener of s.listeners) listener();
|
|
26
|
-
});
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
/** Snapshot identity only changes on emit, so useSyncExternalStore stays cheap. */
|
|
30
|
-
export function invalidate() {
|
|
31
|
-
const s = assetsState();
|
|
32
|
-
s.snapshot = [...s.records];
|
|
33
|
-
emit();
|
|
34
|
-
}
|
|
35
|
-
const KIND_BY_EXT = {
|
|
36
|
-
png: "image",
|
|
37
|
-
jpg: "image",
|
|
38
|
-
jpeg: "image",
|
|
39
|
-
gif: "image",
|
|
40
|
-
webp: "image",
|
|
41
|
-
bmp: "image",
|
|
42
|
-
psd: "image",
|
|
43
|
-
svg: "image",
|
|
44
|
-
tiff: "image",
|
|
45
|
-
ktx: "image",
|
|
46
|
-
heic: "image",
|
|
47
|
-
heif: "image",
|
|
48
|
-
avif: "image",
|
|
49
|
-
ttf: "font",
|
|
50
|
-
otf: "font",
|
|
51
|
-
woff: "font",
|
|
52
|
-
woff2: "font",
|
|
53
|
-
ttc: "font",
|
|
54
|
-
mp4: "video",
|
|
55
|
-
m4v: "video",
|
|
56
|
-
mov: "video",
|
|
57
|
-
mpeg: "video",
|
|
58
|
-
mpg: "video",
|
|
59
|
-
webm: "video",
|
|
60
|
-
avi: "video",
|
|
61
|
-
mp3: "audio",
|
|
62
|
-
wav: "audio",
|
|
63
|
-
aac: "audio",
|
|
64
|
-
aiff: "audio",
|
|
65
|
-
caf: "audio",
|
|
66
|
-
m4a: "audio",
|
|
67
|
-
ogg: "audio",
|
|
68
|
-
json: "data",
|
|
69
|
-
db: "data",
|
|
70
|
-
yaml: "data",
|
|
71
|
-
yml: "data",
|
|
72
|
-
xml: "data",
|
|
73
|
-
html: "data",
|
|
74
|
-
pdf: "data",
|
|
75
|
-
zip: "data"
|
|
76
|
-
};
|
|
77
|
-
export function kindForType(type) {
|
|
78
|
-
return KIND_BY_EXT[type.toLowerCase()] ?? "other";
|
|
79
|
-
}
|
|
80
|
-
export function assetKey(httpServerLocation, name, type) {
|
|
81
|
-
// The runtime registry percent-encodes ?unstable_path= locations while the
|
|
82
|
-
// Metro graph endpoint returns them decoded — normalize or every asset
|
|
83
|
-
// splits into a registry record + a graph record.
|
|
84
|
-
let location = httpServerLocation ?? "";
|
|
85
|
-
try {
|
|
86
|
-
location = decodeURIComponent(location);
|
|
87
|
-
} catch {
|
|
88
|
-
// malformed escapes: keep the raw string
|
|
89
|
-
}
|
|
90
|
-
return `${location}/${name}.${type}`;
|
|
91
|
-
}
|
|
92
|
-
/** Merge an asset sighting into the store; creates the record on first sight. */
|
|
93
|
-
export function upsertRecord(input) {
|
|
94
|
-
if (isBuoyAsset(input)) return undefined;
|
|
95
|
-
const s = assetsState();
|
|
96
|
-
let record = s.byKey.get(input.key);
|
|
97
|
-
if (!record) {
|
|
98
|
-
record = {
|
|
99
|
-
id: s.nextId++,
|
|
100
|
-
key: input.key,
|
|
101
|
-
name: input.name,
|
|
102
|
-
type: input.type,
|
|
103
|
-
kind: kindForType(input.type),
|
|
104
|
-
scales: input.scales ?? [],
|
|
105
|
-
loaded: input.loaded ?? false,
|
|
106
|
-
origin: input.origin,
|
|
107
|
-
firstSeenAt: Date.now()
|
|
108
|
-
};
|
|
109
|
-
s.records.push(record);
|
|
110
|
-
s.byKey.set(record.key, record);
|
|
111
|
-
s.byId.set(record.id, record);
|
|
112
|
-
}
|
|
113
|
-
if (input.registryId != null) record.registryId = input.registryId;
|
|
114
|
-
if (input.hash != null) record.hash = input.hash;
|
|
115
|
-
if (input.httpServerLocation != null) record.httpServerLocation = input.httpServerLocation;
|
|
116
|
-
if (input.width != null) record.width = input.width;
|
|
117
|
-
if (input.height != null) record.height = input.height;
|
|
118
|
-
if (input.scales && input.scales.length) {
|
|
119
|
-
// Dedupe: foo.png + foo@1x.png both existing yields [1, 1, …] from Metro.
|
|
120
|
-
record.scales = [...new Set(input.scales)].sort((a, b) => a - b);
|
|
121
|
-
}
|
|
122
|
-
if (input.resolvedUri != null) record.resolvedUri = input.resolvedUri;
|
|
123
|
-
if (input.resolvedScale != null) record.resolvedScale = input.resolvedScale;
|
|
124
|
-
if (input.loaded) record.loaded = true;
|
|
125
|
-
if (input.fileSystemLocation != null) record.fileSystemLocation = input.fileSystemLocation;
|
|
126
|
-
if (input.files) record.files = input.files;
|
|
127
|
-
if (input.fileHashes) record.fileHashes = input.fileHashes;
|
|
128
|
-
invalidate();
|
|
129
|
-
return record;
|
|
130
|
-
}
|
|
131
|
-
|
|
132
|
-
/** Mutate a record in place (records are owned by the store) and notify. */
|
|
133
|
-
export function updateRecord(id, patch) {
|
|
134
|
-
const s = assetsState();
|
|
135
|
-
const record = s.byId.get(id);
|
|
136
|
-
if (!record) return undefined;
|
|
137
|
-
Object.assign(record, patch);
|
|
138
|
-
invalidate();
|
|
139
|
-
return record;
|
|
140
|
-
}
|
|
141
|
-
export function getRecord(id) {
|
|
142
|
-
return assetsState().byId.get(id);
|
|
143
|
-
}
|
|
144
|
-
export function getRecordByKey(key) {
|
|
145
|
-
return assetsState().byKey.get(key);
|
|
146
|
-
}
|
|
147
|
-
export function getSnapshot() {
|
|
148
|
-
return assetsState().snapshot;
|
|
149
|
-
}
|
|
150
|
-
export function subscribe(listener) {
|
|
151
|
-
const s = assetsState();
|
|
152
|
-
s.listeners.add(listener);
|
|
153
|
-
return () => assetsState().listeners.delete(listener);
|
|
154
|
-
}
|
|
155
|
-
export function clearRecords() {
|
|
156
|
-
const s = assetsState();
|
|
157
|
-
s.records = [];
|
|
158
|
-
s.byKey = new Map();
|
|
159
|
-
s.byId = new Map();
|
|
160
|
-
s.measuredCount = 0;
|
|
161
|
-
s.graphCount = null;
|
|
162
|
-
invalidate();
|
|
163
|
-
}
|
|
164
|
-
|
|
165
|
-
/** Remove records captured before the exclusion was installed through Fast Refresh. */
|
|
166
|
-
export function removeBuoyRecords() {
|
|
167
|
-
const s = assetsState();
|
|
168
|
-
const remaining = s.records.filter(record => !isBuoyAsset(record));
|
|
169
|
-
if (remaining.length === s.records.length) return;
|
|
170
|
-
s.records = remaining;
|
|
171
|
-
s.byKey = new Map(remaining.map(record => [record.key, record]));
|
|
172
|
-
s.byId = new Map(remaining.map(record => [record.id, record]));
|
|
173
|
-
s.measuredCount = remaining.filter(record => record.sizeSource === "measured").length;
|
|
174
|
-
invalidate();
|
|
175
|
-
}
|
|
176
|
-
|
|
177
|
-
/**
|
|
178
|
-
* Estimated decoded-bitmap memory (RGBA8888) at the scale this device would
|
|
179
|
-
* pick — the size fallback when bytes can't be measured (release builds).
|
|
180
|
-
*
|
|
181
|
-
* `resolvedScale` is React Native's own answer and is authoritative, but it
|
|
182
|
-
* only exists once the asset has been REGISTERED. For everything still known
|
|
183
|
-
* only from the Metro graph — the never-loaded set, which is most of what this
|
|
184
|
-
* tool is for — the scale has to be predicted the same way AssetSourceResolver
|
|
185
|
-
* would, not taken as the largest variant shipped.
|
|
186
|
-
*/
|
|
187
|
-
export function estDecodedBytes(record) {
|
|
188
|
-
if (record.kind !== "image" || !record.width || !record.height) return 0;
|
|
189
|
-
const scale = record.resolvedScale ?? pickScale(record.scales, effectivePixelRatio());
|
|
190
|
-
return Math.round(record.width * scale * record.height * scale * 4);
|
|
191
|
-
}
|
|
192
|
-
export function computeStats(list) {
|
|
193
|
-
const s = assetsState();
|
|
194
|
-
const byKind = {
|
|
195
|
-
image: {
|
|
196
|
-
count: 0,
|
|
197
|
-
bytes: 0
|
|
198
|
-
},
|
|
199
|
-
font: {
|
|
200
|
-
count: 0,
|
|
201
|
-
bytes: 0
|
|
202
|
-
},
|
|
203
|
-
video: {
|
|
204
|
-
count: 0,
|
|
205
|
-
bytes: 0
|
|
206
|
-
},
|
|
207
|
-
audio: {
|
|
208
|
-
count: 0,
|
|
209
|
-
bytes: 0
|
|
210
|
-
},
|
|
211
|
-
data: {
|
|
212
|
-
count: 0,
|
|
213
|
-
bytes: 0
|
|
214
|
-
},
|
|
215
|
-
other: {
|
|
216
|
-
count: 0,
|
|
217
|
-
bytes: 0
|
|
218
|
-
}
|
|
219
|
-
};
|
|
220
|
-
const stats = {
|
|
221
|
-
total: list.length,
|
|
222
|
-
loaded: 0,
|
|
223
|
-
neverLoaded: 0,
|
|
224
|
-
byKind,
|
|
225
|
-
totalBytes: 0,
|
|
226
|
-
measuredCount: 0,
|
|
227
|
-
fontFamilies: s.fontFamilies.length
|
|
228
|
-
};
|
|
229
|
-
for (const r of list) {
|
|
230
|
-
if (r.loaded) stats.loaded++;else stats.neverLoaded++;
|
|
231
|
-
byKind[r.kind].count++;
|
|
232
|
-
if (r.sizeBytes != null && r.sizeSource === "measured") {
|
|
233
|
-
byKind[r.kind].bytes += r.sizeBytes;
|
|
234
|
-
stats.totalBytes += r.sizeBytes;
|
|
235
|
-
stats.measuredCount++;
|
|
236
|
-
}
|
|
237
|
-
}
|
|
238
|
-
return stats;
|
|
239
|
-
}
|
|
240
|
-
//# sourceMappingURL=assetStore.js.map
|
|
1
|
+
"use strict";import{assetsState as a}from"../state";import{isBuoyAsset as r}from"../capture/isBuoyAsset";import{effectivePixelRatio as n,pickScale as d}from"../utils/deviceScale";function l(){const e=a();if(e.emitScheduled)return;e.emitScheduled=true;requestAnimationFrame(()=>{e.emitScheduled=false;for(const o of e.listeners)o()})}export function invalidate(){const e=a();e.snapshot=[...e.records];l()}const c={png:"image",jpg:"image",jpeg:"image",gif:"image",webp:"image",bmp:"image",psd:"image",svg:"image",tiff:"image",ktx:"image",heic:"image",heif:"image",avif:"image",ttf:"font",otf:"font",woff:"font",woff2:"font",ttc:"font",mp4:"video",m4v:"video",mov:"video",mpeg:"video",mpg:"video",webm:"video",avi:"video",mp3:"audio",wav:"audio",aac:"audio",aiff:"audio",caf:"audio",m4a:"audio",ogg:"audio",json:"data",db:"data",yaml:"data",yml:"data",xml:"data",html:"data",pdf:"data",zip:"data"};export function kindForType(e){return c[e.toLowerCase()]??"other"}export function assetKey(e,o,t){let s=e??"";try{s=decodeURIComponent(s)}catch{}return`${s}/${o}.${t}`}export function upsertRecord(e){if(r(e))return void 0;const o=a();let t=o.byKey.get(e.key);if(!t){t={id:o.nextId++,key:e.key,name:e.name,type:e.type,kind:kindForType(e.type),scales:e.scales??[],loaded:e.loaded??false,origin:e.origin,firstSeenAt:Date.now()};o.records.push(t);o.byKey.set(t.key,t);o.byId.set(t.id,t)}if(e.registryId!=null)t.registryId=e.registryId;if(e.hash!=null)t.hash=e.hash;if(e.httpServerLocation!=null)t.httpServerLocation=e.httpServerLocation;if(e.width!=null)t.width=e.width;if(e.height!=null)t.height=e.height;if(e.scales&&e.scales.length){t.scales=[...new Set(e.scales)].sort((s,i)=>s-i)}if(e.resolvedUri!=null)t.resolvedUri=e.resolvedUri;if(e.resolvedScale!=null)t.resolvedScale=e.resolvedScale;if(e.loaded)t.loaded=true;if(e.fileSystemLocation!=null)t.fileSystemLocation=e.fileSystemLocation;if(e.files)t.files=e.files;if(e.fileHashes)t.fileHashes=e.fileHashes;invalidate();return t}export function updateRecord(e,o){const t=a();const s=t.byId.get(e);if(!s)return void 0;Object.assign(s,o);invalidate();return s}export function getRecord(e){return a().byId.get(e)}export function getRecordByKey(e){return a().byKey.get(e)}export function getSnapshot(){return a().snapshot}export function subscribe(e){const o=a();o.listeners.add(e);return()=>a().listeners.delete(e)}export function clearRecords(){const e=a();e.records=[];e.byKey=new Map;e.byId=new Map;e.measuredCount=0;e.graphCount=null;invalidate()}export function removeBuoyRecords(){const e=a();const o=e.records.filter(t=>!r(t));if(o.length===e.records.length)return;e.records=o;e.byKey=new Map(o.map(t=>[t.key,t]));e.byId=new Map(o.map(t=>[t.id,t]));e.measuredCount=o.filter(t=>t.sizeSource==="measured").length;invalidate()}export function estDecodedBytes(e){if(e.kind!=="image"||!e.width||!e.height)return 0;const o=e.resolvedScale??d(e.scales,n());return Math.round(e.width*o*e.height*o*4)}export function computeStats(e){const o=a();const t={image:{count:0,bytes:0},font:{count:0,bytes:0},video:{count:0,bytes:0},audio:{count:0,bytes:0},data:{count:0,bytes:0},other:{count:0,bytes:0}};const s={total:e.length,loaded:0,neverLoaded:0,byKind:t,totalBytes:0,measuredCount:0,fontFamilies:o.fontFamilies.length};for(const i of e){if(i.loaded)s.loaded++;else s.neverLoaded++;t[i.kind].count++;if(i.sizeBytes!=null&&i.sizeSource==="measured"){t[i.kind].bytes+=i.sizeBytes;s.totalBytes+=i.sizeBytes;s.measuredCount++}}return s}
|