|
6 | 6 | root.FolderViewPlusSupportBundleTelemetry = factory(root); |
7 | 7 | root.FolderViewPlusSupportBundleTelemetryModuleLoaded = true; |
8 | 8 | }(typeof globalThis !== 'undefined' ? globalThis : this, function(root) { |
| 9 | + const browserModule = root?.FolderViewPlusSupportBundleBrowser || null; |
9 | 10 | const SUPPORT_BUNDLE_UI_ID_KEYS = Object.freeze(new Set([ |
10 | 11 | 'id', |
11 | 12 | 'folderId', |
|
51 | 52 | 'responseSnippet' |
52 | 53 | ])); |
53 | 54 |
|
54 | | - const normalizePrivacyMode = (value) => ( |
55 | | - String(value || '').trim().toLowerCase() === 'full' ? 'full' : 'sanitized' |
56 | | - ); |
| 55 | + const normalizePrivacyMode = (value) => (String(value || '').trim().toLowerCase() === 'full' ? 'full' : 'sanitized'); |
57 | 56 |
|
58 | 57 | const hashValue = (value, saltSeed = '') => { |
59 | 58 | const input = `${String(saltSeed || '')}|${String(value || '')}`; |
|
82 | 81 | manifest[safeBucket] = list; |
83 | 82 | }; |
84 | 83 |
|
85 | | - const clientStorageIsAvailable = (kind) => { |
86 | | - try { |
87 | | - return typeof root?.[kind] !== 'undefined'; |
88 | | - } catch (_error) { |
89 | | - return false; |
90 | | - } |
91 | | - }; |
92 | | - |
93 | 84 | const createUiTelemetryRedactor = (bundle, privacy = 'sanitized') => { |
94 | 85 | const mode = normalizePrivacyMode(privacy); |
95 | 86 | const payload = bundle && typeof bundle === 'object' && !Array.isArray(bundle) ? bundle : {}; |
|
215 | 206 | ? deps.storageKeys |
216 | 207 | : {}; |
217 | 208 |
|
218 | | - const collectBrowserCapabilities = () => ({ |
219 | | - clipboardWrite: Boolean(root?.navigator?.clipboard && typeof root.navigator.clipboard.writeText === 'function'), |
220 | | - cookieEnabled: root?.navigator?.cookieEnabled !== false, |
221 | | - fetch: typeof root?.fetch === 'function', |
222 | | - mutationObserver: typeof root?.MutationObserver === 'function', |
223 | | - pointerEvent: typeof root?.PointerEvent === 'function', |
224 | | - resizeObserver: typeof root?.ResizeObserver === 'function', |
225 | | - touchPoints: Number.isFinite(Number(root?.navigator?.maxTouchPoints)) ? Number(root.navigator.maxTouchPoints) : 0, |
226 | | - viewport: { |
227 | | - width: Number.isFinite(Number(root?.innerWidth)) ? Number(root.innerWidth) : 0, |
228 | | - height: Number.isFinite(Number(root?.innerHeight)) ? Number(root.innerHeight) : 0, |
229 | | - devicePixelRatio: Number.isFinite(Number(root?.devicePixelRatio)) ? Number(root.devicePixelRatio) : 1 |
230 | | - } |
231 | | - }); |
232 | | - |
233 | | - const collectClientStorageDiagnostics = () => ({ |
234 | | - localStorageAvailable: clientStorageIsAvailable('localStorage'), |
235 | | - sessionStorageAvailable: clientStorageIsAvailable('sessionStorage'), |
| 209 | + const browserCollectors = ( |
| 210 | + browserModule |
| 211 | + && typeof browserModule.createCollectors === 'function' |
| 212 | + ) ? browserModule.createCollectors({ |
| 213 | + readClientDiagnosticsStorageRecord, |
| 214 | + storageKeys |
| 215 | + }) : null; |
| 216 | + const collectBrowserCapabilities = browserCollectors?.collectBrowserCapabilities || (() => ({})); |
| 217 | + const collectClientStorageDiagnostics = browserCollectors?.collectClientStorageDiagnostics || (() => ({ |
| 218 | + localStorageAvailable: false, |
| 219 | + sessionStorageAvailable: false, |
236 | 220 | folderEditorDebug: { |
237 | | - launchPresent: Boolean(readClientDiagnosticsStorageRecord(storageKeys.launch || '')), |
238 | | - bootstrapPresent: Boolean(readClientDiagnosticsStorageRecord(storageKeys.bootstrap || '')), |
239 | | - surfacePresent: Boolean(readClientDiagnosticsStorageRecord(storageKeys.surface || '')) |
| 221 | + launchPresent: false, |
| 222 | + bootstrapPresent: false, |
| 223 | + surfacePresent: false |
240 | 224 | } |
241 | | - }); |
242 | | - |
243 | | - const collectCurrentPageTelemetry = (uiRedactor) => { |
244 | | - const pathname = String(root?.location?.pathname || ''); |
| 225 | + })); |
| 226 | + const collectCurrentPageTelemetry = browserCollectors?.collectCurrentPageTelemetry || ((uiRedactor) => { |
245 | 227 | const href = String(root?.location?.href || ''); |
246 | 228 | return { |
247 | | - path: pathname, |
| 229 | + path: String(root?.location?.pathname || ''), |
248 | 230 | href: uiRedactor ? uiRedactor.redactUrl('uiTelemetry.currentPage.href', href) : href |
249 | 231 | }; |
250 | | - }; |
251 | | - |
252 | | - const collectLoadedAssetTelemetry = (uiRedactor) => { |
253 | | - const doc = root?.document || null; |
254 | | - if (!doc || typeof doc.querySelectorAll !== 'function') { |
255 | | - return { count: 0, entries: [] }; |
256 | | - } |
257 | | - const entries = []; |
258 | | - const seen = new Set(); |
259 | | - doc.querySelectorAll('script[src*="/plugins/folderview.plus/"], link[href*="/plugins/folderview.plus/"]').forEach((node) => { |
260 | | - const rawUrl = String(node?.src || node?.href || '').trim(); |
261 | | - if (!rawUrl || seen.has(rawUrl)) { |
262 | | - return; |
263 | | - } |
264 | | - seen.add(rawUrl); |
265 | | - let pathname = rawUrl; |
266 | | - let versionQuery = ''; |
267 | | - let bootQuery = ''; |
268 | | - try { |
269 | | - const parsed = new URL(rawUrl, root?.location?.origin || 'http://fvplus.local'); |
270 | | - pathname = parsed.pathname || rawUrl; |
271 | | - versionQuery = String(parsed.searchParams.get('v') || ''); |
272 | | - bootQuery = String(parsed.searchParams.get('boot') || ''); |
273 | | - } catch (_error) { |
274 | | - pathname = rawUrl.replace(/^https?:\/\/[^/?#]+/i, '').replace(/[?#].*$/, '') || rawUrl; |
275 | | - } |
276 | | - entries.push({ |
277 | | - tag: String(node?.tagName || '').toLowerCase() || 'asset', |
278 | | - url: uiRedactor ? uiRedactor.redactUrl(`uiTelemetry.loadedAssets.entries.${entries.length}.url`, rawUrl) : pathname, |
279 | | - path: pathname, |
280 | | - versionQuery, |
281 | | - bootQuery, |
282 | | - async: node?.async === true, |
283 | | - defer: node?.defer === true, |
284 | | - rel: String(node?.rel || ''), |
285 | | - media: String(node?.media || ''), |
286 | | - loaded: node?.tagName === 'LINK' |
287 | | - ? Boolean(node.sheet) |
288 | | - : true |
289 | | - }); |
290 | | - }); |
291 | | - return { |
292 | | - count: entries.length, |
293 | | - entries |
294 | | - }; |
295 | | - }; |
296 | | - |
297 | | - const collectBrowserConsoleErrors = () => { |
298 | | - const fallbackStorage = readClientDiagnosticsStorageRecord('fv.support.bundle.consoleErrors.v1'); |
299 | | - const apiSnapshot = ( |
300 | | - root?.FolderViewPlusFatalBanner |
301 | | - && typeof root.FolderViewPlusFatalBanner.getBrowserConsoleErrorSnapshot === 'function' |
302 | | - ) |
303 | | - ? root.FolderViewPlusFatalBanner.getBrowserConsoleErrorSnapshot() |
304 | | - : null; |
305 | | - const snapshot = apiSnapshot && typeof apiSnapshot === 'object' && !Array.isArray(apiSnapshot) |
306 | | - ? apiSnapshot |
307 | | - : { |
308 | | - storageKey: 'fv.support.bundle.consoleErrors.v1', |
309 | | - maxEntries: 30, |
310 | | - count: Array.isArray(fallbackStorage) ? fallbackStorage.length : 0, |
311 | | - entries: Array.isArray(fallbackStorage) ? fallbackStorage : [] |
312 | | - }; |
313 | | - return { |
314 | | - storageKey: String(snapshot.storageKey || 'fv.support.bundle.consoleErrors.v1'), |
315 | | - maxEntries: Number.isFinite(Number(snapshot.maxEntries)) ? Number(snapshot.maxEntries) : 30, |
316 | | - count: Number.isFinite(Number(snapshot.count)) ? Number(snapshot.count) : 0, |
317 | | - entries: Array.isArray(snapshot.entries) ? snapshot.entries.slice(-30) : [] |
318 | | - }; |
319 | | - }; |
| 232 | + }); |
| 233 | + const collectLoadedAssetTelemetry = browserCollectors?.collectLoadedAssetTelemetry || (() => ({ count: 0, entries: [] })); |
| 234 | + const collectBrowserConsoleErrors = browserCollectors?.collectBrowserConsoleErrors || (() => ({ |
| 235 | + storageKey: 'fv.support.bundle.consoleErrors.v1', |
| 236 | + maxEntries: 30, |
| 237 | + count: 0, |
| 238 | + entries: [] |
| 239 | + })); |
320 | 240 |
|
321 | 241 | const collectSupportBundleUiTelemetry = (bundle) => { |
322 | 242 | const payload = normalizeSupportBundleV2Payload(bundle, bundle?.bundleMeta?.privacyMode || 'sanitized'); |
|
0 commit comments