@workflow/web-shared 5.0.0-beta.0 → 5.0.0-beta.10
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 +1 -1
- package/dist/components/error-boundary.js +1 -1
- package/dist/components/event-list-view.d.ts +18 -1
- package/dist/components/event-list-view.d.ts.map +1 -1
- package/dist/components/event-list-view.js +242 -142
- package/dist/components/hook-actions.js +1 -1
- package/dist/components/index.d.ts +4 -1
- package/dist/components/index.d.ts.map +1 -1
- package/dist/components/index.js +5 -2
- package/dist/components/new-trace-viewer/components/copy-button.d.ts +9 -0
- package/dist/components/new-trace-viewer/components/copy-button.d.ts.map +1 -0
- package/dist/components/new-trace-viewer/components/copy-button.js +27 -0
- package/dist/components/new-trace-viewer/components/event-list.d.ts +10 -0
- package/dist/components/new-trace-viewer/components/event-list.d.ts.map +1 -0
- package/dist/components/new-trace-viewer/components/event-list.js +39 -0
- package/dist/components/new-trace-viewer/components/middle-truncate/copy-selection.d.ts +18 -0
- package/dist/components/new-trace-viewer/components/middle-truncate/copy-selection.d.ts.map +1 -0
- package/dist/components/new-trace-viewer/components/middle-truncate/copy-selection.js +54 -0
- package/dist/components/new-trace-viewer/components/middle-truncate/middle-truncate.d.ts +20 -0
- package/dist/components/new-trace-viewer/components/middle-truncate/middle-truncate.d.ts.map +1 -0
- package/dist/components/new-trace-viewer/components/middle-truncate/middle-truncate.js +81 -0
- package/dist/components/new-trace-viewer/components/middle-truncate/truncate.d.ts +25 -0
- package/dist/components/new-trace-viewer/components/middle-truncate/truncate.d.ts.map +1 -0
- package/dist/components/new-trace-viewer/components/middle-truncate/truncate.js +101 -0
- package/dist/components/new-trace-viewer/components/middle-truncate/use-middle-truncate.d.ts +20 -0
- package/dist/components/new-trace-viewer/components/middle-truncate/use-middle-truncate.d.ts.map +1 -0
- package/dist/components/new-trace-viewer/components/middle-truncate/use-middle-truncate.js +114 -0
- package/dist/components/new-trace-viewer/components/split-pane.d.ts +14 -0
- package/dist/components/new-trace-viewer/components/split-pane.d.ts.map +1 -0
- package/dist/components/new-trace-viewer/components/split-pane.js +99 -0
- package/dist/components/new-trace-viewer/components/timeline.d.ts +34 -0
- package/dist/components/new-trace-viewer/components/timeline.d.ts.map +1 -0
- package/dist/components/new-trace-viewer/components/timeline.js +223 -0
- package/dist/components/new-trace-viewer/context.d.ts +15 -0
- package/dist/components/new-trace-viewer/context.d.ts.map +1 -0
- package/dist/components/new-trace-viewer/context.js +47 -0
- package/dist/components/new-trace-viewer/detail-panel.d.ts +10 -0
- package/dist/components/new-trace-viewer/detail-panel.d.ts.map +1 -0
- package/dist/components/new-trace-viewer/detail-panel.js +13 -0
- package/dist/components/new-trace-viewer/icons.d.ts +6 -0
- package/dist/components/new-trace-viewer/icons.d.ts.map +1 -0
- package/dist/components/new-trace-viewer/icons.js +15 -0
- package/dist/components/new-trace-viewer/search.d.ts +19 -0
- package/dist/components/new-trace-viewer/search.d.ts.map +1 -0
- package/dist/components/new-trace-viewer/search.js +134 -0
- package/dist/components/new-trace-viewer/trace-viewer.d.ts +8 -0
- package/dist/components/new-trace-viewer/trace-viewer.d.ts.map +1 -0
- package/dist/components/new-trace-viewer/trace-viewer.js +387 -0
- package/dist/components/new-trace-viewer/types.d.ts +1 -0
- package/dist/components/new-trace-viewer/types.d.ts.map +1 -0
- package/dist/components/new-trace-viewer/types.js +2 -0
- package/dist/components/new-trace-viewer/util/constants.d.ts +1 -0
- package/dist/components/new-trace-viewer/util/constants.d.ts.map +1 -0
- package/dist/components/new-trace-viewer/util/constants.js +2 -0
- package/dist/components/new-trace-viewer/utils.d.ts +46 -0
- package/dist/components/new-trace-viewer/utils.d.ts.map +1 -0
- package/dist/components/new-trace-viewer/utils.js +330 -0
- package/dist/components/run-trace-view.d.ts +2 -1
- package/dist/components/run-trace-view.d.ts.map +1 -1
- package/dist/components/run-trace-view.js +3 -3
- package/dist/components/sidebar/attribute-panel.d.ts +7 -1
- package/dist/components/sidebar/attribute-panel.d.ts.map +1 -1
- package/dist/components/sidebar/attribute-panel.js +131 -70
- package/dist/components/sidebar/conversation-view.js +1 -1
- package/dist/components/sidebar/copyable-data-block.d.ts +1 -0
- package/dist/components/sidebar/copyable-data-block.d.ts.map +1 -1
- package/dist/components/sidebar/copyable-data-block.js +16 -15
- package/dist/components/sidebar/detail-card.d.ts +5 -6
- package/dist/components/sidebar/detail-card.d.ts.map +1 -1
- package/dist/components/sidebar/detail-card.js +32 -16
- package/dist/components/sidebar/entity-detail-panel.d.ts +3 -1
- package/dist/components/sidebar/entity-detail-panel.d.ts.map +1 -1
- package/dist/components/sidebar/entity-detail-panel.js +20 -37
- package/dist/components/sidebar/events-list.d.ts +1 -1
- package/dist/components/sidebar/events-list.d.ts.map +1 -1
- package/dist/components/sidebar/events-list.js +46 -32
- package/dist/components/sidebar/resolve-hook-modal.js +1 -1
- package/dist/components/sidebar/sidebar-data-context.d.ts +29 -0
- package/dist/components/sidebar/sidebar-data-context.d.ts.map +1 -0
- package/dist/components/sidebar/sidebar-data-context.js +19 -0
- package/dist/components/stream-viewer.d.ts +1 -1
- package/dist/components/stream-viewer.d.ts.map +1 -1
- package/dist/components/stream-viewer.js +3 -27
- package/dist/components/trace-viewer/components/map.js +1 -1
- package/dist/components/trace-viewer/components/markers.js +1 -1
- package/dist/components/trace-viewer/components/node.js +1 -1
- package/dist/components/trace-viewer/components/search-input.js +1 -1
- package/dist/components/trace-viewer/components/search.js +1 -1
- package/dist/components/trace-viewer/components/span-content.js +1 -1
- package/dist/components/trace-viewer/components/span-detail-panel.js +1 -1
- package/dist/components/trace-viewer/components/span-segments.js +1 -1
- package/dist/components/trace-viewer/components/span-strategies.js +1 -1
- package/dist/components/trace-viewer/components/ui.js +1 -1
- package/dist/components/trace-viewer/components/zoom-button.js +1 -1
- package/dist/components/trace-viewer/components/zoom-icons.js +1 -1
- package/dist/components/trace-viewer/context.js +1 -1
- package/dist/components/trace-viewer/index.js +1 -1
- package/dist/components/trace-viewer/trace-viewer.js +1 -1
- package/dist/components/trace-viewer/types.js +1 -1
- package/dist/components/trace-viewer/util/constants.js +1 -1
- package/dist/components/trace-viewer/util/scrollbar-width.js +1 -1
- package/dist/components/trace-viewer/util/timing.d.ts +1 -1
- package/dist/components/trace-viewer/util/timing.d.ts.map +1 -1
- package/dist/components/trace-viewer/util/timing.js +6 -9
- package/dist/components/trace-viewer/util/tree.js +1 -1
- package/dist/components/trace-viewer/util/use-immediate-style.js +1 -1
- package/dist/components/trace-viewer/util/use-streaming-spans.js +1 -1
- package/dist/components/trace-viewer/util/use-trackpad-zoom.js +1 -1
- package/dist/components/trace-viewer/worker.js +1 -1
- package/dist/components/trace-viewer-new.d.ts +10 -0
- package/dist/components/trace-viewer-new.d.ts.map +1 -0
- package/dist/components/trace-viewer-new.js +23 -0
- package/dist/components/ui/alert.js +1 -1
- package/dist/components/ui/button.d.ts +10 -0
- package/dist/components/ui/button.d.ts.map +1 -0
- package/dist/components/ui/button.js +46 -0
- package/dist/components/ui/card.js +1 -1
- package/dist/components/ui/data-inspector.d.ts +39 -1
- package/dist/components/ui/data-inspector.d.ts.map +1 -1
- package/dist/components/ui/data-inspector.js +207 -22
- package/dist/components/ui/decrypt-button.js +1 -1
- package/dist/components/ui/error-card.js +1 -1
- package/dist/components/ui/error-stack-block.d.ts.map +1 -1
- package/dist/components/ui/error-stack-block.js +27 -19
- package/dist/components/ui/icon-button.d.ts +13 -0
- package/dist/components/ui/icon-button.d.ts.map +1 -0
- package/dist/components/ui/icon-button.js +29 -0
- package/dist/components/ui/inspector-theme.d.ts +9 -10
- package/dist/components/ui/inspector-theme.d.ts.map +1 -1
- package/dist/components/ui/inspector-theme.js +39 -72
- package/dist/components/ui/load-more-button.js +1 -1
- package/dist/components/ui/menu-dropdown.js +1 -1
- package/dist/components/ui/skeleton.js +1 -1
- package/dist/components/ui/spinner.js +1 -1
- package/dist/components/ui/timestamp-tooltip.js +1 -1
- package/dist/components/workflow-trace-view.d.ts +3 -1
- package/dist/components/workflow-trace-view.d.ts.map +1 -1
- package/dist/components/workflow-trace-view.js +10 -5
- package/dist/components/workflow-traces/event-colors.js +1 -1
- package/dist/components/workflow-traces/trace-colors.js +1 -1
- package/dist/components/workflow-traces/trace-span-construction.d.ts +2 -2
- package/dist/components/workflow-traces/trace-span-construction.d.ts.map +1 -1
- package/dist/components/workflow-traces/trace-span-construction.js +19 -6
- package/dist/components/workflow-traces/trace-time-utils.js +1 -1
- package/dist/hooks/use-dark-mode.js +1 -1
- package/dist/hooks/use-reduced-motion.d.ts +10 -0
- package/dist/hooks/use-reduced-motion.d.ts.map +1 -0
- package/dist/hooks/use-reduced-motion.js +29 -0
- package/dist/index.d.ts +3 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +3 -2
- package/dist/lib/event-analysis.js +1 -1
- package/dist/lib/event-materialization.js +1 -1
- package/dist/lib/exact-event-search-id.d.ts +25 -0
- package/dist/lib/exact-event-search-id.d.ts.map +1 -0
- package/dist/lib/exact-event-search-id.js +39 -0
- package/dist/lib/hydration.d.ts +15 -2
- package/dist/lib/hydration.d.ts.map +1 -1
- package/dist/lib/hydration.js +168 -16
- package/dist/lib/stream-display.d.ts +18 -0
- package/dist/lib/stream-display.d.ts.map +1 -0
- package/dist/lib/stream-display.js +30 -0
- package/dist/lib/toast.js +1 -1
- package/dist/lib/trace-builder.d.ts.map +1 -1
- package/dist/lib/trace-builder.js +3 -2
- package/dist/lib/utils.d.ts +9 -9
- package/dist/lib/utils.d.ts.map +1 -1
- package/dist/lib/utils.js +27 -32
- package/dist/styles.css +475 -1
- package/package.json +6 -4
- package/src/components/event-list-view.tsx +447 -282
- package/src/components/index.ts +12 -1
- package/src/components/new-trace-viewer/components/copy-button.tsx +68 -0
- package/src/components/new-trace-viewer/components/event-list.tsx +127 -0
- package/src/components/new-trace-viewer/components/middle-truncate/copy-selection.ts +114 -0
- package/src/components/new-trace-viewer/components/middle-truncate/middle-truncate.tsx +157 -0
- package/src/components/new-trace-viewer/components/middle-truncate/truncate.ts +132 -0
- package/src/components/new-trace-viewer/components/middle-truncate/use-middle-truncate.ts +167 -0
- package/src/components/new-trace-viewer/components/split-pane.tsx +185 -0
- package/src/components/new-trace-viewer/components/timeline.tsx +552 -0
- package/src/components/new-trace-viewer/context.tsx +92 -0
- package/src/components/new-trace-viewer/detail-panel.tsx +55 -0
- package/src/components/new-trace-viewer/icons.tsx +79 -0
- package/src/components/new-trace-viewer/search.ts +178 -0
- package/src/components/new-trace-viewer/trace-viewer.tsx +694 -0
- package/src/components/new-trace-viewer/types.ts +0 -0
- package/src/components/new-trace-viewer/util/constants.ts +0 -0
- package/src/components/new-trace-viewer/utils.ts +482 -0
- package/src/components/run-trace-view.tsx +3 -0
- package/src/components/sidebar/attribute-panel.tsx +240 -196
- package/src/components/sidebar/copyable-data-block.tsx +49 -27
- package/src/components/sidebar/detail-card.tsx +119 -59
- package/src/components/sidebar/entity-detail-panel.tsx +92 -148
- package/src/components/sidebar/events-list.tsx +93 -108
- package/src/components/sidebar/sidebar-data-context.tsx +62 -0
- package/src/components/stream-viewer.tsx +18 -40
- package/src/components/trace-viewer/util/timing.ts +5 -9
- package/src/components/trace-viewer-new.tsx +49 -0
- package/src/components/ui/button.tsx +68 -0
- package/src/components/ui/data-inspector.tsx +427 -31
- package/src/components/ui/error-stack-block.tsx +39 -30
- package/src/components/ui/icon-button.tsx +57 -0
- package/src/components/ui/inspector-theme.ts +39 -81
- package/src/components/workflow-trace-view.tsx +12 -2
- package/src/components/workflow-traces/trace-span-construction.ts +24 -6
- package/src/hooks/use-reduced-motion.ts +34 -0
- package/src/index.ts +9 -0
- package/src/lib/exact-event-search-id.ts +67 -0
- package/src/lib/hydration.ts +182 -14
- package/src/lib/stream-display.ts +48 -0
- package/src/lib/trace-builder.ts +2 -1
- package/src/lib/utils.ts +27 -32
- package/src/styles.css +475 -1
- package/dist/components/error-boundary.js.map +0 -1
- package/dist/components/event-list-view.js.map +0 -1
- package/dist/components/hook-actions.js.map +0 -1
- package/dist/components/index.js.map +0 -1
- package/dist/components/run-trace-view.js.map +0 -1
- package/dist/components/sidebar/attribute-panel.js.map +0 -1
- package/dist/components/sidebar/conversation-view.js.map +0 -1
- package/dist/components/sidebar/copyable-data-block.js.map +0 -1
- package/dist/components/sidebar/detail-card.js.map +0 -1
- package/dist/components/sidebar/entity-detail-panel.js.map +0 -1
- package/dist/components/sidebar/events-list.js.map +0 -1
- package/dist/components/sidebar/resolve-hook-modal.js.map +0 -1
- package/dist/components/stream-viewer.js.map +0 -1
- package/dist/components/trace-viewer/components/map.js.map +0 -1
- package/dist/components/trace-viewer/components/markers.js.map +0 -1
- package/dist/components/trace-viewer/components/node.js.map +0 -1
- package/dist/components/trace-viewer/components/search-input.js.map +0 -1
- package/dist/components/trace-viewer/components/search.js.map +0 -1
- package/dist/components/trace-viewer/components/span-content.js.map +0 -1
- package/dist/components/trace-viewer/components/span-detail-panel.js.map +0 -1
- package/dist/components/trace-viewer/components/span-segments.js.map +0 -1
- package/dist/components/trace-viewer/components/span-strategies.js.map +0 -1
- package/dist/components/trace-viewer/components/ui.js.map +0 -1
- package/dist/components/trace-viewer/components/zoom-button.js.map +0 -1
- package/dist/components/trace-viewer/components/zoom-icons.js.map +0 -1
- package/dist/components/trace-viewer/context.js.map +0 -1
- package/dist/components/trace-viewer/index.js.map +0 -1
- package/dist/components/trace-viewer/trace-viewer.js.map +0 -1
- package/dist/components/trace-viewer/types.js.map +0 -1
- package/dist/components/trace-viewer/util/constants.js.map +0 -1
- package/dist/components/trace-viewer/util/scrollbar-width.js.map +0 -1
- package/dist/components/trace-viewer/util/timing.js.map +0 -1
- package/dist/components/trace-viewer/util/tree.js.map +0 -1
- package/dist/components/trace-viewer/util/use-immediate-style.js.map +0 -1
- package/dist/components/trace-viewer/util/use-streaming-spans.js.map +0 -1
- package/dist/components/trace-viewer/util/use-trackpad-zoom.js.map +0 -1
- package/dist/components/trace-viewer/worker.js.map +0 -1
- package/dist/components/ui/alert.js.map +0 -1
- package/dist/components/ui/card.js.map +0 -1
- package/dist/components/ui/data-inspector.js.map +0 -1
- package/dist/components/ui/decrypt-button.js.map +0 -1
- package/dist/components/ui/error-card.js.map +0 -1
- package/dist/components/ui/error-stack-block.js.map +0 -1
- package/dist/components/ui/inspector-theme.js.map +0 -1
- package/dist/components/ui/load-more-button.js.map +0 -1
- package/dist/components/ui/menu-dropdown.js.map +0 -1
- package/dist/components/ui/skeleton.js.map +0 -1
- package/dist/components/ui/spinner.js.map +0 -1
- package/dist/components/ui/timestamp-tooltip.js.map +0 -1
- package/dist/components/workflow-trace-view.js.map +0 -1
- package/dist/components/workflow-traces/event-colors.js.map +0 -1
- package/dist/components/workflow-traces/trace-colors.js.map +0 -1
- package/dist/components/workflow-traces/trace-span-construction.js.map +0 -1
- package/dist/components/workflow-traces/trace-time-utils.js.map +0 -1
- package/dist/hooks/use-dark-mode.js.map +0 -1
- package/dist/index.js.map +0 -1
- package/dist/lib/event-analysis.js.map +0 -1
- package/dist/lib/event-materialization.js.map +0 -1
- package/dist/lib/hydration.js.map +0 -1
- package/dist/lib/toast.js.map +0 -1
- package/dist/lib/trace-builder.js.map +0 -1
- package/dist/lib/utils.js.map +0 -1
|
@@ -0,0 +1,387 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
3
|
+
import { parseStepName, parseWorkflowName } from '@workflow/utils/parse-name';
|
|
4
|
+
import { ChevronDown, ChevronUp, RotateCcw, Search, X, ZoomIn, ZoomOut, } from 'lucide-react';
|
|
5
|
+
import { useCallback, useDeferredValue, useEffect, useMemo, useRef, useState, } from 'react';
|
|
6
|
+
import { useReducedMotion } from '../../hooks/use-reduced-motion';
|
|
7
|
+
import { ErrorBoundary } from '../error-boundary';
|
|
8
|
+
import { EntityDetailPanel, } from '../sidebar/entity-detail-panel';
|
|
9
|
+
import { useSidebarDataOptional } from '../sidebar/sidebar-data-context';
|
|
10
|
+
import { formatDuration, getHighResInMs } from '../trace-viewer/util/timing';
|
|
11
|
+
import { IconButton } from '../ui/icon-button';
|
|
12
|
+
import EventList from './components/event-list';
|
|
13
|
+
import { SplitPane } from './components/split-pane';
|
|
14
|
+
import { TIMELINE_PADDING_PX, Timeline, TimelineHeader, } from './components/timeline';
|
|
15
|
+
import { ActiveSpanProvider, useActiveSpan } from './context';
|
|
16
|
+
import { DetailPanel } from './detail-panel';
|
|
17
|
+
import { searchSpans } from './search';
|
|
18
|
+
import { computeRootBounds, computeTimeMarkers } from './utils';
|
|
19
|
+
const MIN_VIEWPORT_MS = 0.001;
|
|
20
|
+
function useAnimatedViewport(initial) {
|
|
21
|
+
const [viewport, setViewportState] = useState(initial);
|
|
22
|
+
const animRef = useRef(null);
|
|
23
|
+
const currentRef = useRef(initial);
|
|
24
|
+
currentRef.current = viewport;
|
|
25
|
+
const reducedMotion = useReducedMotion();
|
|
26
|
+
const cancel = useCallback(() => {
|
|
27
|
+
if (animRef.current) {
|
|
28
|
+
cancelAnimationFrame(animRef.current.raf);
|
|
29
|
+
animRef.current = null;
|
|
30
|
+
}
|
|
31
|
+
}, []);
|
|
32
|
+
const animateTo = useCallback((target) => {
|
|
33
|
+
cancel();
|
|
34
|
+
if (reducedMotion) {
|
|
35
|
+
currentRef.current = target;
|
|
36
|
+
setViewportState(target);
|
|
37
|
+
return;
|
|
38
|
+
}
|
|
39
|
+
const from = currentRef.current;
|
|
40
|
+
const anim = { raf: 0, from, to: target, start: performance.now() };
|
|
41
|
+
const tick = () => {
|
|
42
|
+
const t = Math.min((performance.now() - anim.start) / 150, 1);
|
|
43
|
+
const e = 1 - (1 - t) * (1 - t);
|
|
44
|
+
setViewportState({
|
|
45
|
+
start: anim.from.start + (anim.to.start - anim.from.start) * e,
|
|
46
|
+
end: anim.from.end + (anim.to.end - anim.from.end) * e,
|
|
47
|
+
});
|
|
48
|
+
if (t < 1)
|
|
49
|
+
anim.raf = requestAnimationFrame(tick);
|
|
50
|
+
else
|
|
51
|
+
animRef.current = null;
|
|
52
|
+
};
|
|
53
|
+
animRef.current = anim;
|
|
54
|
+
anim.raf = requestAnimationFrame(tick);
|
|
55
|
+
}, [cancel, reducedMotion]);
|
|
56
|
+
const setViewport = useCallback((update) => {
|
|
57
|
+
cancel();
|
|
58
|
+
if (typeof update === 'function') {
|
|
59
|
+
setViewportState((prev) => {
|
|
60
|
+
const next = update(prev);
|
|
61
|
+
currentRef.current = next;
|
|
62
|
+
return next;
|
|
63
|
+
});
|
|
64
|
+
}
|
|
65
|
+
else {
|
|
66
|
+
currentRef.current = update;
|
|
67
|
+
setViewportState(update);
|
|
68
|
+
}
|
|
69
|
+
}, [cancel]);
|
|
70
|
+
useEffect(() => cancel, [cancel]);
|
|
71
|
+
return { viewport, setViewport, animateTo };
|
|
72
|
+
}
|
|
73
|
+
// ---------------------------------------------------------------------------
|
|
74
|
+
// Hook: bridge ActiveSpanContext + SidebarDataContext → SelectedSpanInfo
|
|
75
|
+
// ---------------------------------------------------------------------------
|
|
76
|
+
function useSelectedSpanInfo() {
|
|
77
|
+
const { activeSpan } = useActiveSpan();
|
|
78
|
+
const sidebar = useSidebarDataOptional();
|
|
79
|
+
return useMemo(() => {
|
|
80
|
+
if (!activeSpan || !sidebar)
|
|
81
|
+
return null;
|
|
82
|
+
const correlationId = activeSpan.spanId;
|
|
83
|
+
const rawEvents = correlationId
|
|
84
|
+
? sidebar.events.filter((e) => e.correlationId === correlationId)
|
|
85
|
+
: [];
|
|
86
|
+
return {
|
|
87
|
+
data: activeSpan.attributes?.data,
|
|
88
|
+
resource: activeSpan.attributes?.resource,
|
|
89
|
+
spanId: activeSpan.spanId,
|
|
90
|
+
rawEvents,
|
|
91
|
+
};
|
|
92
|
+
}, [activeSpan, sidebar]);
|
|
93
|
+
}
|
|
94
|
+
// ---------------------------------------------------------------------------
|
|
95
|
+
// Root component
|
|
96
|
+
// ---------------------------------------------------------------------------
|
|
97
|
+
export function NewTraceViewer({ trace }) {
|
|
98
|
+
return (_jsx(ActiveSpanProvider, { spans: trace.spans, children: _jsx(NewTraceViewerContent, { trace: trace }) }));
|
|
99
|
+
}
|
|
100
|
+
function NewTraceViewerContent({ trace }) {
|
|
101
|
+
const { activeSpan, activeSpanId, setActiveSpan, clearActiveSpan } = useActiveSpan();
|
|
102
|
+
const sidebar = useSidebarDataOptional();
|
|
103
|
+
const selectedSpan = useSelectedSpanInfo();
|
|
104
|
+
const [searchQuery, setSearchQuery] = useState('');
|
|
105
|
+
const deferredSearchQuery = useDeferredValue(searchQuery);
|
|
106
|
+
const searchResult = useMemo(() => searchSpans(trace.spans, deferredSearchQuery), [trace.spans, deferredSearchQuery]);
|
|
107
|
+
const root = useMemo(() => computeRootBounds(trace.spans), [trace.spans]);
|
|
108
|
+
const { viewport, setViewport, animateTo } = useAnimatedViewport({
|
|
109
|
+
start: root.startTime,
|
|
110
|
+
end: root.startTime + root.duration,
|
|
111
|
+
});
|
|
112
|
+
const prevRootRef = useRef({
|
|
113
|
+
start: root.startTime,
|
|
114
|
+
end: root.startTime + root.duration,
|
|
115
|
+
});
|
|
116
|
+
useEffect(() => {
|
|
117
|
+
const prevRoot = prevRootRef.current;
|
|
118
|
+
const newStart = root.startTime;
|
|
119
|
+
const newEnd = root.startTime + root.duration;
|
|
120
|
+
setViewport((prev) => {
|
|
121
|
+
const wasAtFullExtent = Math.abs(prev.start - prevRoot.start) < 0.01 &&
|
|
122
|
+
Math.abs(prev.end - prevRoot.end) < 0.01;
|
|
123
|
+
if (wasAtFullExtent) {
|
|
124
|
+
return { start: newStart, end: newEnd };
|
|
125
|
+
}
|
|
126
|
+
return prev;
|
|
127
|
+
});
|
|
128
|
+
prevRootRef.current = { start: newStart, end: newEnd };
|
|
129
|
+
}, [root.startTime, root.duration, setViewport]);
|
|
130
|
+
const viewDuration = viewport.end - viewport.start;
|
|
131
|
+
const timeMarkers = useMemo(() => computeTimeMarkers(viewDuration, viewport.start - root.startTime), [viewDuration, viewport.start, root.startTime]);
|
|
132
|
+
const resetZoom = useCallback(() => {
|
|
133
|
+
animateTo({ start: root.startTime, end: root.startTime + root.duration });
|
|
134
|
+
}, [animateTo, root.startTime, root.duration]);
|
|
135
|
+
const ZOOM_FACTOR = 0.5;
|
|
136
|
+
const zoomBy = useCallback((factor) => {
|
|
137
|
+
const rootS = root.startTime;
|
|
138
|
+
const rootE = root.startTime + root.duration;
|
|
139
|
+
const rootD = root.duration;
|
|
140
|
+
setViewport((prev) => {
|
|
141
|
+
const prevDuration = prev.end - prev.start;
|
|
142
|
+
const center = (prev.start + prev.end) / 2;
|
|
143
|
+
const newDuration = Math.max(MIN_VIEWPORT_MS, Math.min(rootD, prevDuration * factor));
|
|
144
|
+
let newStart = center - newDuration / 2;
|
|
145
|
+
let newEnd = center + newDuration / 2;
|
|
146
|
+
if (newStart < rootS) {
|
|
147
|
+
newStart = rootS;
|
|
148
|
+
newEnd = rootS + newDuration;
|
|
149
|
+
}
|
|
150
|
+
if (newEnd > rootE) {
|
|
151
|
+
newEnd = rootE;
|
|
152
|
+
newStart = Math.max(rootS, rootE - newDuration);
|
|
153
|
+
}
|
|
154
|
+
return { start: newStart, end: newEnd };
|
|
155
|
+
});
|
|
156
|
+
}, [setViewport, root.startTime, root.duration]);
|
|
157
|
+
const zoomIn = useCallback(() => zoomBy(ZOOM_FACTOR), [zoomBy]);
|
|
158
|
+
const zoomOut = useCallback(() => zoomBy(1 / ZOOM_FACTOR), [zoomBy]);
|
|
159
|
+
const handleSelectSpan = useCallback((spanId) => {
|
|
160
|
+
if (spanId === activeSpanId) {
|
|
161
|
+
clearActiveSpan();
|
|
162
|
+
return;
|
|
163
|
+
}
|
|
164
|
+
setActiveSpan(spanId);
|
|
165
|
+
const span = trace.spans.find((s) => s.spanId === spanId);
|
|
166
|
+
if (!span)
|
|
167
|
+
return;
|
|
168
|
+
const spanStart = getHighResInMs(span.startTime);
|
|
169
|
+
const spanEnd = getHighResInMs(span.endTime);
|
|
170
|
+
const spanDuration = spanEnd - spanStart;
|
|
171
|
+
const rootS = root.startTime;
|
|
172
|
+
const rootE = root.startTime + root.duration;
|
|
173
|
+
const rootD = root.duration;
|
|
174
|
+
if (spanDuration > rootD * 0.8) {
|
|
175
|
+
animateTo({ start: rootS, end: rootE });
|
|
176
|
+
return;
|
|
177
|
+
}
|
|
178
|
+
const padding = Math.max(spanDuration * 0.2, MIN_VIEWPORT_MS / 2);
|
|
179
|
+
let newStart = spanStart - padding;
|
|
180
|
+
let newEnd = spanEnd + padding;
|
|
181
|
+
if (newEnd - newStart < MIN_VIEWPORT_MS) {
|
|
182
|
+
const center = (spanStart + spanEnd) / 2;
|
|
183
|
+
newStart = center - MIN_VIEWPORT_MS / 2;
|
|
184
|
+
newEnd = center + MIN_VIEWPORT_MS / 2;
|
|
185
|
+
}
|
|
186
|
+
if (newStart < rootS) {
|
|
187
|
+
const duration = newEnd - newStart;
|
|
188
|
+
newStart = rootS;
|
|
189
|
+
newEnd = Math.min(rootE, rootS + duration);
|
|
190
|
+
}
|
|
191
|
+
if (newEnd > rootE) {
|
|
192
|
+
const duration = newEnd - newStart;
|
|
193
|
+
newEnd = rootE;
|
|
194
|
+
newStart = Math.max(rootS, rootE - duration);
|
|
195
|
+
}
|
|
196
|
+
animateTo({ start: newStart, end: newEnd });
|
|
197
|
+
}, [
|
|
198
|
+
animateTo,
|
|
199
|
+
setActiveSpan,
|
|
200
|
+
clearActiveSpan,
|
|
201
|
+
activeSpanId,
|
|
202
|
+
trace.spans,
|
|
203
|
+
root.startTime,
|
|
204
|
+
root.duration,
|
|
205
|
+
]);
|
|
206
|
+
const [altHeld, setAltHeld] = useState(false);
|
|
207
|
+
useEffect(() => {
|
|
208
|
+
const handleSidebarNavKey = (e) => {
|
|
209
|
+
const target = e.target;
|
|
210
|
+
if (target instanceof HTMLInputElement ||
|
|
211
|
+
target instanceof HTMLTextAreaElement ||
|
|
212
|
+
target?.isContentEditable) {
|
|
213
|
+
return;
|
|
214
|
+
}
|
|
215
|
+
const targetId = e.key === 'k' ? prevSpanIdRef.current : nextSpanIdRef.current;
|
|
216
|
+
if (targetId) {
|
|
217
|
+
e.preventDefault();
|
|
218
|
+
handleSelectSpanRef.current(targetId);
|
|
219
|
+
}
|
|
220
|
+
};
|
|
221
|
+
const onKeyDown = (e) => {
|
|
222
|
+
if (e.key === 'Escape') {
|
|
223
|
+
clearActiveSpan();
|
|
224
|
+
}
|
|
225
|
+
else if (e.key === 'Alt') {
|
|
226
|
+
e.preventDefault();
|
|
227
|
+
setAltHeld(true);
|
|
228
|
+
}
|
|
229
|
+
else if (e.key === 'j' || e.key === 'k') {
|
|
230
|
+
handleSidebarNavKey(e);
|
|
231
|
+
}
|
|
232
|
+
};
|
|
233
|
+
const onKeyUp = (e) => {
|
|
234
|
+
if (e.key === 'Alt')
|
|
235
|
+
setAltHeld(false);
|
|
236
|
+
};
|
|
237
|
+
const onBlur = () => setAltHeld(false);
|
|
238
|
+
window.addEventListener('keydown', onKeyDown);
|
|
239
|
+
window.addEventListener('keyup', onKeyUp);
|
|
240
|
+
window.addEventListener('blur', onBlur);
|
|
241
|
+
return () => {
|
|
242
|
+
window.removeEventListener('keydown', onKeyDown);
|
|
243
|
+
window.removeEventListener('keyup', onKeyUp);
|
|
244
|
+
window.removeEventListener('blur', onBlur);
|
|
245
|
+
};
|
|
246
|
+
}, [clearActiveSpan]);
|
|
247
|
+
const timelineRef = useRef(null);
|
|
248
|
+
const [hoverFraction, setHoverFraction] = useState(null);
|
|
249
|
+
const hoverInfo = useMemo(() => {
|
|
250
|
+
if (hoverFraction == null)
|
|
251
|
+
return null;
|
|
252
|
+
const absTime = viewport.start + hoverFraction * viewDuration;
|
|
253
|
+
const offset = absTime - root.startTime;
|
|
254
|
+
return { fraction: hoverFraction, label: formatDuration(offset, true) };
|
|
255
|
+
}, [hoverFraction, viewport.start, viewDuration, root.startTime]);
|
|
256
|
+
const handleTimelineMouseMove = useCallback((e) => {
|
|
257
|
+
const el = timelineRef.current;
|
|
258
|
+
if (!el)
|
|
259
|
+
return;
|
|
260
|
+
const rect = el.getBoundingClientRect();
|
|
261
|
+
const contentWidth = rect.width - TIMELINE_PADDING_PX * 2;
|
|
262
|
+
if (contentWidth <= 0)
|
|
263
|
+
return;
|
|
264
|
+
const fraction = Math.max(0, Math.min(1, (e.clientX - rect.left - TIMELINE_PADDING_PX) / contentWidth));
|
|
265
|
+
setHoverFraction(fraction);
|
|
266
|
+
}, []);
|
|
267
|
+
const handleTimelineMouseLeave = useCallback(() => {
|
|
268
|
+
setHoverFraction(null);
|
|
269
|
+
}, []);
|
|
270
|
+
useEffect(() => {
|
|
271
|
+
const el = timelineRef.current;
|
|
272
|
+
if (!el)
|
|
273
|
+
return;
|
|
274
|
+
const rootS = root.startTime;
|
|
275
|
+
const rootE = root.startTime + root.duration;
|
|
276
|
+
const rootD = root.duration;
|
|
277
|
+
if (rootD <= 0)
|
|
278
|
+
return;
|
|
279
|
+
const onWheel = (e) => {
|
|
280
|
+
const isZoomGesture = e.ctrlKey || e.metaKey;
|
|
281
|
+
const hasDeltaX = Math.abs(e.deltaX) > Math.abs(e.deltaY);
|
|
282
|
+
if (!isZoomGesture && !hasDeltaX)
|
|
283
|
+
return;
|
|
284
|
+
e.preventDefault();
|
|
285
|
+
const rect = el.getBoundingClientRect();
|
|
286
|
+
const contentWidth = rect.width - TIMELINE_PADDING_PX * 2;
|
|
287
|
+
if (contentWidth <= 0)
|
|
288
|
+
return;
|
|
289
|
+
if (isZoomGesture) {
|
|
290
|
+
let dy = e.deltaY;
|
|
291
|
+
if (e.deltaMode === 1)
|
|
292
|
+
dy *= 16;
|
|
293
|
+
const cursorFraction = Math.max(0, Math.min(1, (e.clientX - rect.left - TIMELINE_PADDING_PX) / contentWidth));
|
|
294
|
+
const isMouseWheel = e.deltaMode === 1 || Math.abs(e.deltaY) >= 50;
|
|
295
|
+
const scaleFactor = Math.pow(2, dy / (isMouseWheel ? 200 : 60));
|
|
296
|
+
setViewport((prev) => {
|
|
297
|
+
const prevDuration = prev.end - prev.start;
|
|
298
|
+
const cursorTime = prev.start + cursorFraction * prevDuration;
|
|
299
|
+
const newDuration = Math.max(MIN_VIEWPORT_MS, Math.min(rootD, prevDuration * scaleFactor));
|
|
300
|
+
let newStart = cursorTime - cursorFraction * newDuration;
|
|
301
|
+
let newEnd = newStart + newDuration;
|
|
302
|
+
if (newStart < rootS) {
|
|
303
|
+
newStart = rootS;
|
|
304
|
+
newEnd = rootS + newDuration;
|
|
305
|
+
}
|
|
306
|
+
if (newEnd > rootE) {
|
|
307
|
+
newEnd = rootE;
|
|
308
|
+
newStart = Math.max(rootS, rootE - newDuration);
|
|
309
|
+
}
|
|
310
|
+
return { start: newStart, end: newEnd };
|
|
311
|
+
});
|
|
312
|
+
}
|
|
313
|
+
else {
|
|
314
|
+
let dx = e.deltaX;
|
|
315
|
+
if (e.deltaMode === 1)
|
|
316
|
+
dx *= 16;
|
|
317
|
+
setViewport((prev) => {
|
|
318
|
+
const prevDuration = prev.end - prev.start;
|
|
319
|
+
const panAmount = (dx / contentWidth) * prevDuration;
|
|
320
|
+
let newStart = prev.start + panAmount;
|
|
321
|
+
let newEnd = prev.end + panAmount;
|
|
322
|
+
if (newStart < rootS) {
|
|
323
|
+
newStart = rootS;
|
|
324
|
+
newEnd = rootS + prevDuration;
|
|
325
|
+
}
|
|
326
|
+
if (newEnd > rootE) {
|
|
327
|
+
newEnd = rootE;
|
|
328
|
+
newStart = Math.max(rootS, rootE - prevDuration);
|
|
329
|
+
}
|
|
330
|
+
return { start: newStart, end: newEnd };
|
|
331
|
+
});
|
|
332
|
+
}
|
|
333
|
+
};
|
|
334
|
+
el.addEventListener('wheel', onWheel, { passive: false });
|
|
335
|
+
return () => el.removeEventListener('wheel', onWheel);
|
|
336
|
+
}, [root.startTime, root.duration, setViewport]);
|
|
337
|
+
// Derive the selected span name and metadata for the panel header
|
|
338
|
+
const selectedSpanName = useMemo(() => {
|
|
339
|
+
if (!selectedSpan?.data)
|
|
340
|
+
return 'Details';
|
|
341
|
+
const data = selectedSpan.data;
|
|
342
|
+
if (selectedSpan.resource === 'hook') {
|
|
343
|
+
return data.token ?? data.hookId;
|
|
344
|
+
}
|
|
345
|
+
const stepName = data.stepName;
|
|
346
|
+
const workflowName = data.workflowName;
|
|
347
|
+
return ((stepName ? parseStepName(stepName)?.shortName : undefined) ??
|
|
348
|
+
(workflowName ? parseWorkflowName(workflowName)?.shortName : undefined) ??
|
|
349
|
+
stepName ??
|
|
350
|
+
workflowName ??
|
|
351
|
+
data.hookId ??
|
|
352
|
+
'Details');
|
|
353
|
+
}, [selectedSpan?.data, selectedSpan?.resource]);
|
|
354
|
+
const { prevSpanId, nextSpanId } = useMemo(() => {
|
|
355
|
+
if (!activeSpanId)
|
|
356
|
+
return { prevSpanId: null, nextSpanId: null };
|
|
357
|
+
const i = trace.spans.findIndex((s) => s.spanId === activeSpanId);
|
|
358
|
+
if (i === -1)
|
|
359
|
+
return { prevSpanId: null, nextSpanId: null };
|
|
360
|
+
return {
|
|
361
|
+
prevSpanId: trace.spans[i - 1]?.spanId ?? null,
|
|
362
|
+
nextSpanId: trace.spans[i + 1]?.spanId ?? null,
|
|
363
|
+
};
|
|
364
|
+
}, [activeSpanId, trace.spans]);
|
|
365
|
+
const handleSelectPrevSpan = useCallback(() => {
|
|
366
|
+
if (prevSpanId)
|
|
367
|
+
handleSelectSpan(prevSpanId);
|
|
368
|
+
}, [prevSpanId, handleSelectSpan]);
|
|
369
|
+
const handleSelectNextSpan = useCallback(() => {
|
|
370
|
+
if (nextSpanId)
|
|
371
|
+
handleSelectSpan(nextSpanId);
|
|
372
|
+
}, [nextSpanId, handleSelectSpan]);
|
|
373
|
+
const prevSpanIdRef = useRef(prevSpanId);
|
|
374
|
+
const nextSpanIdRef = useRef(nextSpanId);
|
|
375
|
+
const handleSelectSpanRef = useRef(handleSelectSpan);
|
|
376
|
+
prevSpanIdRef.current = prevSpanId;
|
|
377
|
+
nextSpanIdRef.current = nextSpanId;
|
|
378
|
+
handleSelectSpanRef.current = handleSelectSpan;
|
|
379
|
+
return (_jsxs("div", { "data-pane": "pane-root", "data-has-detail": activeSpan ? '' : undefined, className: "grid w-full h-full max-h-full grid-cols-[minmax(100px,1fr)] data-[has-detail]:grid-cols-[minmax(100px,1fr)_clamp(280px,420px,100%)]", children: [_jsxs("div", { id: "trace-parent", className: "grid grid-rows-[1fr] h-full min-h-0 overflow-hidden relative bg-background-100", children: [_jsxs(SplitPane, { startHeader: _jsxs("div", { className: "bg-background-100 border-b border-gray-alpha-400 h-10 min-h-10 flex items-center pl-4 pr-2 gap-1.5", children: [_jsx(Search, { className: "w-3.5 h-3.5 shrink-0 text-gray-800" }), _jsx("input", { id: "trace-viewer-search", name: "trace-viewer-search", type: "text", value: searchQuery, onChange: (e) => setSearchQuery(e.target.value), onKeyDown: (e) => {
|
|
380
|
+
if (e.key === 'Escape' && searchQuery) {
|
|
381
|
+
e.preventDefault();
|
|
382
|
+
e.stopPropagation();
|
|
383
|
+
setSearchQuery('');
|
|
384
|
+
}
|
|
385
|
+
}, placeholder: "Search spans...", "aria-label": "Search spans", className: "flex-1 min-w-0 bg-transparent text-sm text-gray-1000 placeholder:text-gray-800 outline-none" }), searchQuery && (_jsx("button", { type: "button", "aria-label": "Clear search", onClick: () => setSearchQuery(''), className: "-mr-2 hidden h-full max-w-full shrink-0 cursor-pointer items-center rounded-r-md border-0 bg-transparent px-2.5 font-inherit text-base text-gray-900 no-underline transition-colors duration-150 ease-in hover:text-gray-1000 focus-visible:-outline-offset-1 focus-visible:outline focus-visible:outline-2 focus-visible:outline-[var(--ds-focus-color)] min-[961px]:flex", children: _jsx("kbd", { className: "inline-flex h-5 min-h-5 min-w-5 items-center justify-center rounded border border-gray-alpha-400 bg-background-100 px-1 font-sans text-[13px] font-medium leading-[1.7em] text-gray-900", children: "Esc" }) }))] }), endHeader: _jsx(TimelineHeader, { markers: timeMarkers, hoverInfo: hoverInfo }), children: [_jsx("div", { className: "block overflow-visible", children: _jsx(EventList, { spans: trace.spans, activeSpanId: activeSpanId, searchResult: searchResult, onSelectSpan: handleSelectSpan }) }), _jsx("div", { ref: timelineRef, className: "block min-h-0 overflow-visible relative", onDoubleClick: resetZoom, onMouseMove: handleTimelineMouseMove, onMouseLeave: handleTimelineMouseLeave, children: _jsx(Timeline, { spans: trace.spans, viewStart: viewport.start, viewEnd: viewport.end, markers: timeMarkers, selectedId: activeSpanId, searchResult: searchResult, onSelect: handleSelectSpan, hoverFraction: hoverFraction, altHeld: altHeld }) })] }), _jsxs("div", { className: "absolute right-3 bottom-3 z-[5] flex items-center border border-gray-alpha-400 rounded-md bg-background-100 shadow-sm overflow-hidden divide-x divide-gray-alpha-400", children: [_jsx(IconButton, { variant: "muted", size: "small", onClick: zoomOut, "aria-label": "Zoom out", children: _jsx(ZoomOut, { className: "w-4 h-4" }) }), _jsx(IconButton, { variant: "muted", size: "small", onClick: resetZoom, "aria-label": "Reset zoom", children: _jsx(RotateCcw, { className: "w-3.5 h-3.5" }) }), _jsx(IconButton, { variant: "muted", size: "small", onClick: zoomIn, "aria-label": "Zoom in", children: _jsx(ZoomIn, { className: "w-4 h-4" }) })] })] }), activeSpan && sidebar ? (_jsxs("aside", { className: "flex flex-col h-full max-h-full bg-background-100 border-l border-gray-alpha-400 overflow-auto", children: [_jsxs("div", { className: "flex items-center justify-between gap-2 shrink-0 px-4 pt-3 pb-3", children: [_jsx("span", { className: "text-label-14 font-medium text-gray-1000 truncate block", children: selectedSpanName }), _jsxs("div", { className: "flex items-center gap-0.5 shrink-0", children: [_jsx(IconButton, { "aria-label": "Navigate to previous span", "aria-keyshortcuts": "K", onClick: handleSelectPrevSpan, disabled: !prevSpanId, children: _jsx(ChevronUp, { className: "w-4 h-4" }) }), _jsx(IconButton, { "aria-label": "Navigate to next span", "aria-keyshortcuts": "J", onClick: handleSelectNextSpan, disabled: !nextSpanId, children: _jsx(ChevronDown, { className: "w-4 h-4" }) }), _jsx("div", { "aria-hidden": true, className: "w-px h-4 bg-gray-alpha-400 mx-1" }), _jsx(IconButton, { "aria-label": "Close span details", "aria-keyshortcuts": "Escape", onClick: clearActiveSpan, children: _jsx(X, { className: "w-4 h-4" }) })] })] }), _jsx("div", { className: "flex-1 overflow-y-auto", children: _jsx(ErrorBoundary, { children: _jsx(EntityDetailPanel, { run: sidebar.run, onStreamClick: sidebar.onStreamClick, onRunClick: sidebar.onRunClick, spanDetailData: sidebar.spanDetailData, spanDetailError: sidebar.spanDetailError, spanDetailLoading: sidebar.spanDetailLoading, onSpanSelect: sidebar.onSpanSelect, onWakeUpSleep: sidebar.onWakeUpSleep, onLoadEventData: sidebar.onLoadEventData, onResolveHook: sidebar.onResolveHook, encryptionKey: sidebar.encryptionKey, onDecrypt: sidebar.onDecrypt, isDecrypting: sidebar.isDecrypting, selectedSpan: selectedSpan }) }) })] })) : activeSpan ? (_jsx(DetailPanel, { span: activeSpan, rootStart: root.startTime, onClose: clearActiveSpan })) : null] }));
|
|
386
|
+
}
|
|
387
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidHJhY2Utdmlld2VyLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vc3JjL2NvbXBvbmVudHMvbmV3LXRyYWNlLXZpZXdlci90cmFjZS12aWV3ZXIudHN4Il0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLFlBQVksQ0FBQzs7QUFFYixPQUFPLEVBQUUsYUFBYSxFQUFFLGlCQUFpQixFQUFFLE1BQU0sNEJBQTRCLENBQUM7QUFDOUUsT0FBTyxFQUNMLFdBQVcsRUFDWCxTQUFTLEVBQ1QsU0FBUyxFQUNULE1BQU0sRUFDTixDQUFDLEVBQ0QsTUFBTSxFQUNOLE9BQU8sR0FDUixNQUFNLGNBQWMsQ0FBQztBQUN0QixPQUFPLEVBRUwsV0FBVyxFQUNYLGdCQUFnQixFQUNoQixTQUFTLEVBQ1QsT0FBTyxFQUNQLE1BQU0sRUFDTixRQUFRLEdBQ1QsTUFBTSxPQUFPLENBQUM7QUFDZixPQUFPLEVBQUUsZ0JBQWdCLEVBQUUsTUFBTSxnQ0FBZ0MsQ0FBQztBQUNsRSxPQUFPLEVBQUUsYUFBYSxFQUFFLE1BQU0sbUJBQW1CLENBQUM7QUFDbEQsT0FBTyxFQUNMLGlCQUFpQixHQUVsQixNQUFNLGdDQUFnQyxDQUFDO0FBQ3hDLE9BQU8sRUFBRSxzQkFBc0IsRUFBRSxNQUFNLGlDQUFpQyxDQUFDO0FBRXpFLE9BQU8sRUFBRSxjQUFjLEVBQUUsY0FBYyxFQUFFLE1BQU0sNkJBQTZCLENBQUM7QUFDN0UsT0FBTyxFQUFFLFVBQVUsRUFBRSxNQUFNLG1CQUFtQixDQUFDO0FBQy9DLE9BQU8sU0FBUyxNQUFNLHlCQUF5QixDQUFDO0FBQ2hELE9BQU8sRUFBRSxTQUFTLEVBQUUsTUFBTSx5QkFBeUIsQ0FBQztBQUNwRCxPQUFPLEVBQ0wsbUJBQW1CLEVBQ25CLFFBQVEsRUFDUixjQUFjLEdBQ2YsTUFBTSx1QkFBdUIsQ0FBQztBQUMvQixPQUFPLEVBQUUsa0JBQWtCLEVBQUUsYUFBYSxFQUFFLE1BQU0sV0FBVyxDQUFDO0FBQzlELE9BQU8sRUFBRSxX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Y0FBYyxFQUFFLE9BQU8sQ0FBQyxjQUFjLEVBQ3RDLGVBQWUsRUFBRSxPQUFPLENBQUMsZUFBZSxFQUN4QyxpQkFBaUIsRUFBRSxPQUFPLENBQUMsaUJBQWlCLEVBQzVDLFlBQVksRUFBRSxPQUFPLENBQUMsWUFBWSxFQUNsQyxhQUFhLEVBQUUsT0FBTyxDQUFDLGFBQWEsRUFDcEMsZUFBZSxFQUFFLE9BQU8sQ0FBQyxlQUFlLEVBQ3hDLGFBQWEsRUFBRSxPQUFPLENBQUMsYUFBYSxFQUNwQyxhQUFhLEVBQUUsT0FBTyxDQUFDLGFBQWEsRUFDcEMsU0FBUyxFQUFFLE9BQU8sQ0FBQyxTQUFTLEVBQzVCLFlBQVksRUFBRSxPQUFPLENBQUMsWUFBWSxFQUNsQyxZQUFZLEVBQUUsWUFBWSxHQUMxQixHQUNZLEdBQ1osSUFDQSxDQUNULENBQUMsQ0FBQyxDQUFDLFVBQVUsQ0FBQyxDQUFDLENBQUMsQ0FDZixLQUFDLFdBQVcsSUFDVixJQUFJLEVBQUUsVUFBVSxFQUNoQixTQUFTLEVBQUUsSUFBSSxDQUFDLFNBQVMsRUFDekIsT0FBTyxFQUFFLGVBQWUsR0FDeEIsQ0FDSCxDQUFDLENBQUMsQ0FBQyxJQUFJLElBQ0osQ0FDUCxDQUFDO0FBQ0osQ0FBQyIsInNvdXJjZXNDb250ZW50IjpbIid1c2UgY2xpZW50JztcblxuaW1wb3J0IHsgcGFyc2VTdGVwTmFtZSwgcGFyc2VXb3JrZmxvd05hbWUgfSBmcm9tICdAd29ya2Zsb3cvdXRpbHMvcGFyc2UtbmFtZSc7XG5pbXBvcnQge1xuICBDaGV2cm9uRG93bixcbiAgQ2hldnJvblVwLFxuICBSb3RhdGVDY3csXG4gIFNlYXJjaCxcbiAgWCxcbiAgWm9vbUluLFxuICBab29tT3V0LFxufSBmcm9tICdsdWNpZGUtcmVhY3QnO1xuaW1wb3J0IHtcbiAgdHlwZSBSZWFjdE5vZGUsXG4gIHVzZUNhbGxiYWNrLFxuICB1c2VEZWZlcnJlZFZhbHVlLFxuICB1c2VFZmZlY3QsXG4gIHVzZU1lbW8sXG4gIHVzZVJlZixcbiAgdXNlU3RhdGUsXG59IGZyb20gJ3JlYWN0JztcbmltcG9ydCB7IHVzZVJlZHVjZWRNb3Rpb24gfSBmcm9tICcuLi8uLi9ob29rcy91c2UtcmVkdWNlZC1tb3Rpb24nO1xuaW1wb3J0IHsgRXJyb3JCb3VuZGFyeSB9IGZyb20gJy4uL2Vycm9yLWJvdW5kYXJ5JztcbmltcG9ydCB7XG4gIEVudGl0eURldGFpbFBhbmVsLFxuICB0eXBlIFNlbGVjdGVkU3BhbkluZm8sXG59IGZyb20gJy4uL3NpZGViYXIvZW50aXR5LWRldGFpbC1wYW5lbCc7XG5pbXBvcnQgeyB1c2VTaWRlYmFyRGF0YU9wdGlvbmFsIH0gZnJvbSAnLi4vc2lkZWJhci9zaWRlYmFyLWRhdGEtY29udGV4dCc7XG5pbXBvcnQgdHlwZSB7IFRyYWNlIH0gZnJvbSAnLi4vdHJhY2Utdmlld2VyL3R5cGVzJztcbmltcG9ydCB7IGZvcm1hdER1cmF0aW9uLCBnZXRIaWdoUmVzSW5NcyB9IGZyb20gJy4uL3RyYWNlLXZpZXdlci91dGlsL3RpbWluZyc7XG5pbXBvcnQgeyBJY29uQnV0dG9uIH0gZnJvbSAnLi4vdWkvaWNvbi1idXR0b24nO1xuaW1wb3J0IEV2ZW50TGlzdCBmcm9tICcuL2NvbXBvbmVudHMvZXZlbnQtbGlzdCc7XG5pbXBvcnQgeyBTcGxpdFBhbmUgfSBmcm9tICcuL2NvbXBvbmVudHMvc3BsaXQtcGFuZSc7XG5pbXBvcnQge1xuICBUSU1FTElORV9QQURESU5HX1BYLFxuICBUaW1lbGluZSxcbiAgVGltZWxpbmVIZWFkZXIsXG59IGZyb20gJy4vY29tcG9uZW50cy90aW1lbGluZSc7XG5pbXBvcnQgeyBBY3RpdmVTcGFuUHJvdmlkZXIsIHVzZUFjdGl2ZVNwYW4gfSBmcm9tICcuL2NvbnRleHQnO1xuaW1wb3J0IHsgRGV0YWlsUGFuZWwgfSBmcm9tICcuL2RldGFpbC1wYW5lbCc7XG5pbXBvcnQgeyBzZWFyY2hTcGFucyB9IGZyb20gJy4vc2VhcmNoJztcbmltcG9ydCB7IGNvbXB1dGVSb290Qm91bmRzLCBjb21wdXRlVGltZU1hcmtlcnMgfSBmcm9tICcuL3V0aWxzJztcblxuaW50ZXJmYWNlIE5ld1RyYWNlVmlld2VyUHJvcHMge1xuICB0cmFjZTogVHJhY2U7XG59XG5cbmNvbnN0IE1JTl9WSUVXUE9SVF9NUyA9IDAuMDAxO1xuXG5pbnRlcmZhY2UgVmlld3BvcnQge1xuICBzdGFydDogbnVtYmVyO1xuICBlbmQ6IG51bWJlcjtcbn1cblxuZnVuY3Rpb24gdXNlQW5pbWF0ZWRWaWV3cG9ydChpbml0aWFsOiBWaWV3cG9ydCkge1xuICBjb25zdCBbdmlld3BvcnQsIHNldFZpZXdwb3J0U3RhdGVdID0gdXNlU3RhdGU8Vmlld3BvcnQ+KGluaXRpYWwpO1xuICBjb25zdCBhbmltUmVmID0gdXNlUmVmPHtcbiAgICByYWY6IG51bWJlcjtcbiAgICBmcm9tOiBWaWV3cG9ydDtcbiAgICB0bzogVmlld3BvcnQ7XG4gICAgc3RhcnQ6IG51bWJlcjtcbiAgfSB8IG51bGw+KG51bGwpO1xuICBjb25zdCBjdXJyZW50UmVmID0gdXNlUmVmKGluaXRpYWwpO1xuICBjdXJyZW50UmVmLmN1cnJlbnQgPSB2aWV3cG9ydDtcbiAgY29uc3QgcmVkdWNlZE1vdGlvbiA9IHVzZVJlZHVjZWRNb3Rpb24oKTtcblxuICBjb25zdCBjYW5jZWwgPSB1c2VDYWxsYmFjaygoKSA9PiB7XG4gICAgaWYgKGFuaW1SZWYuY3VycmVudCkge1xuICAgICAgY2FuY2VsQW5pbWF0aW9uRnJhbWUoYW5pbVJlZi5jdXJyZW50LnJhZik7XG4gICAgICBhbmltUmVmLmN1cnJlbnQgPSBudWxsO1xuICAgIH1cbiAgfSwgW10pO1xuXG4gIGNvbnN0IGFuaW1hdGVUbyA9IHVzZUNhbGxiYWNrKFxuICAgICh0YXJnZXQ6IFZpZXdwb3J0KSA9PiB7XG4gICAgICBjYW5jZWwoKTtcblxuICAgICAgaWYgKHJlZHVjZWRNb3Rpb24pIHtcbiAgICAgICAgY3VycmVudFJlZi5jdXJyZW50ID0gdGFyZ2V0O1xuICAgICAgICBzZXRWaWV3cG9ydFN0YXRlKHRhcmdldCk7XG4gICAgICAgIHJldHVybjtcbiAgICAgIH1cblxuICAgICAgY29uc3QgZnJvbSA9IGN1cnJlbnRSZWYuY3VycmVudDtcbiAgICAgIGNvbnN0IGFuaW0gPSB7IHJhZjogMCwgZnJvbSwgdG86IHRhcmdldCwgc3RhcnQ6IHBlcmZvcm1hbmNlLm5vdygpIH07XG5cbiAgICAgIGNvbnN0IHRpY2sgPSAoKSA9PiB7XG4gICAgICAgIGNvbnN0IHQgPSBNYXRoLm1pbigocGVyZm9ybWFuY2Uubm93KCkgLSBhbmltLnN0YXJ0KSAvIDE1MCwgMSk7XG4gICAgICAgIGNvbnN0IGUgPSAxIC0gKDEgLSB0KSAqICgxIC0gdCk7XG4gICAgICAgIHNldFZpZXdwb3J0U3RhdGUoe1xuICAgICAgICAgIHN0YXJ0OiBhbmltLmZyb20uc3RhcnQgKyAoYW5pbS50by5zdGFydCAtIGFuaW0uZnJvbS5zdGFydCkgKiBlLFxuICAgICAgICAgIGVuZDogYW5pbS5mcm9tLmVuZCArIChhbmltLnRvLmVuZCAtIGFuaW0uZnJvbS5lbmQpICogZSxcbiAgICAgICAgfSk7XG4gICAgICAgIGlmICh0IDwgMSkgYW5pbS5yYWYgPSByZXF1ZXN0QW5pbWF0aW9uRnJhbWUodGljayk7XG4gICAgICAgIGVsc2UgYW5pbVJlZi5jdXJyZW50ID0gbnVsbDtcbiAgICAgIH07XG5cbiAgICAgIGFuaW1SZWYuY3VycmVudCA9IGFuaW07XG4gICAgICBhbmltLnJhZiA9IHJlcXVlc3RBbmltYXRpb25GcmFtZSh0aWNrKTtcbiAgICB9LFxuICAgIFtjYW5jZWwsIHJlZHVjZWRNb3Rpb25dXG4gICk7XG5cbiAgY29uc3Qgc2V0Vmlld3BvcnQgPSB1c2VDYWxsYmFjayhcbiAgICAodXBkYXRlOiBWaWV3cG9ydCB8ICgocHJldjogVmlld3BvcnQpID0+IFZpZXdwb3J0KSkgPT4ge1xuICAgICAgY2FuY2VsKCk7XG4gICAgICBpZiAodHlwZW9mIHVwZGF0ZSA9PT0gJ2Z1bmN0aW9uJykge1xuICAgICAgICBzZXRWaWV3cG9ydFN0YXRlKChwcmV2KSA9PiB7XG4gICAgICAgICAgY29uc3QgbmV4dCA9IHVwZGF0ZShwcmV2KTtcbiAgICAgICAgICBjdXJyZW50UmVmLmN1cnJlbnQgPSBuZXh0O1xuICAgICAgICAgIHJldHVybiBuZXh0O1xuICAgICAgICB9KTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIGN1cnJlbnRSZWYuY3VycmVudCA9IHVwZGF0ZTtcbiAgICAgICAgc2V0Vmlld3BvcnRTdGF0ZSh1cGRhdGUpO1xuICAgICAgfVxuICAgIH0sXG4gICAgW2NhbmNlbF1cbiAgKTtcblxuICB1c2VFZmZlY3QoKCkgPT4gY2FuY2VsLCBbY2FuY2VsXSk7XG5cbiAgcmV0dXJuIHsgdmlld3BvcnQsIHNldFZpZXdwb3J0LCBhbmltYXRlVG8gfTtcbn1cblxuLy8gLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tXG4vLyBIb29rOiBicmlkZ2UgQWN0aXZlU3BhbkNvbnRleHQgKyBTaWRlYmFyRGF0YUNvbnRleHQg4oaSIFNlbGVjdGVkU3BhbkluZm9cbi8vIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLVxuXG5mdW5jdGlvbiB1c2VTZWxlY3RlZFNwYW5JbmZvKCk6IFNlbGVjdGVkU3BhbkluZm8gfCBudWxsIHtcbiAgY29uc3QgeyBhY3RpdmVTcGFuIH0gPSB1c2VBY3RpdmVTcGFuKCk7XG4gIGNvbnN0IHNpZGViYXIgPSB1c2VTaWRlYmFyRGF0YU9wdGlvbmFsKCk7XG5cbiAgcmV0dXJuIHVzZU1lbW8oKCkgPT4ge1xuICAgIGlmICghYWN0aXZlU3BhbiB8fCAhc2lkZWJhcikgcmV0dXJuIG51bGw7XG5cbiAgICBjb25zdCBjb3JyZWxhdGlvbklkID0gYWN0aXZlU3Bhbi5zcGFuSWQ7XG4gICAgY29uc3QgcmF3RXZlbnRzID0gY29ycmVsYXRpb25JZFxuICAgICAgPyBzaWRlYmFyLmV2ZW50cy5maWx0ZXIoKGUpID0+IGUuY29ycmVsYXRpb25JZCA9PT0gY29ycmVsYXRpb25JZClcbiAgICAgIDogW107XG5cbiAgICByZXR1cm4ge1xuICAgICAgZGF0YTogYWN0aXZlU3Bhbi5hdHRyaWJ1dGVzPy5kYXRhLFxuICAgICAgcmVzb3VyY2U6IGFjdGl2ZVNwYW4uYXR0cmlidXRlcz8ucmVzb3VyY2UgYXMgc3RyaW5nIHwgdW5kZWZpbmVkLFxuICAgICAgc3BhbklkOiBhY3RpdmVTcGFuLnNwYW5JZCxcbiAgICAgIHJhd0V2ZW50cyxcbiAgICB9O1xuICB9LCBbYWN0aXZlU3Bhbiwgc2lkZWJhcl0pO1xufVxuXG4vLyAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cbi8vIFJvb3QgY29tcG9uZW50XG4vLyAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cblxuZXhwb3J0IGZ1bmN0aW9uIE5ld1RyYWNlVmlld2VyKHsgdHJhY2UgfTogTmV3VHJhY2VWaWV3ZXJQcm9wcyk6IFJlYWN0Tm9kZSB7XG4gIHJldHVybiAoXG4gICAgPEFjdGl2ZVNwYW5Qcm92aWRlciBzcGFucz17dHJhY2Uuc3BhbnN9PlxuICAgICAgPE5ld1RyYWNlVmlld2VyQ29udGVudCB0cmFjZT17dHJhY2V9IC8+XG4gICAgPC9BY3RpdmVTcGFuUHJvdmlkZXI+XG4gICk7XG59XG5cbmZ1bmN0aW9uIE5ld1RyYWNlVmlld2VyQ29udGVudCh7IHRyYWNlIH06IE5ld1RyYWNlVmlld2VyUHJvcHMpOiBSZWFjdE5vZGUge1xuICBjb25zdCB7IGFjdGl2ZVNwYW4sIGFjdGl2ZVNwYW5JZCwgc2V0QWN0aXZlU3BhbiwgY2xlYXJBY3RpdmVTcGFuIH0gPVxuICAgIHVzZUFjdGl2ZVNwYW4oKTtcblxuICBjb25zdCBzaWRlYmFyID0gdXNlU2lkZWJhckRhdGFPcHRpb25hbCgpO1xuICBjb25zdCBzZWxlY3RlZFNwYW4gPSB1c2VTZWxlY3RlZFNwYW5JbmZvKCk7XG5cbiAgY29uc3QgW3NlYXJjaFF1ZXJ5LCBzZXRTZWFyY2hRdWVyeV0gPSB1c2VTdGF0ZSgnJyk7XG4gIGNvbnN0IGRlZmVycmVkU2VhcmNoUXVlcnkgPSB1c2VEZWZlcnJlZFZhbHVlKHNlYXJjaFF1ZXJ5KTtcblxuICBjb25zdCBzZWFyY2hSZXN1bHQgPSB1c2VNZW1vKFxuICAgICgpID0+IHNlYXJjaFNwYW5zKHRyYWNlLnNwYW5zLCBkZWZlcnJlZFNlYXJjaFF1ZXJ5KSxcbiAgICBbdHJhY2Uuc3BhbnMsIGRlZmVycmVkU2VhcmNoUXVlcnldXG4gICk7XG5cbiAgY29uc3Qgcm9vdCA9IHVzZU1lbW8oKCkgPT4gY29tcHV0ZVJvb3RCb3VuZHModHJhY2Uuc3BhbnMpLCBbdHJhY2Uuc3BhbnNdKTtcblxuICBjb25zdCB7IHZpZXdwb3J0LCBzZXRWaWV3cG9ydCwgYW5pbWF0ZVRvIH0gPSB1c2VBbmltYXRlZFZpZXdwb3J0KHtcbiAgICBzdGFydDogcm9vdC5zdGFydFRpbWUsXG4gICAgZW5kOiByb290LnN0YXJ0VGltZSArIHJvb3QuZHVyYXRpb24sXG4gIH0pO1xuXG4gIGNvbnN0IHByZXZSb290UmVmID0gdXNlUmVmPFZpZXdwb3J0Pih7XG4gICAgc3RhcnQ6IHJvb3Quc3RhcnRUaW1lLFxuICAgIGVuZDogcm9vdC5zdGFydFRpbWUgKyByb290LmR1cmF0aW9uLFxuICB9KTtcblxuICB1c2VFZmZlY3QoKCkgPT4ge1xuICAgIGNvbnN0IHByZXZSb290ID0gcHJldlJvb3RSZWYuY3VycmVudDtcbiAgICBjb25zdCBuZXdTdGFydCA9IHJvb3Quc3RhcnRUaW1lO1xuICAgIGNvbnN0IG5ld0VuZCA9IHJvb3Quc3RhcnRUaW1lICsgcm9vdC5kdXJhdGlvbjtcblxuICAgIHNldFZpZXdwb3J0KChwcmV2KSA9PiB7XG4gICAgICBjb25zdCB3YXNBdEZ1bGxFeHRlbnQgPVxuICAgICAgICBNYXRoLmFicyhwcmV2LnN0YXJ0IC0gcHJldlJvb3Quc3RhcnQpIDwgMC4wMSAmJlxuICAgICAgICBNYXRoLmFicyhwcmV2LmVuZCAtIHByZXZSb290LmVuZCkgPCAwLjAxO1xuXG4gICAgICBpZiAod2FzQXRGdWxsRXh0ZW50KSB7XG4gICAgICAgIHJldHVybiB7IHN0YXJ0OiBuZXdTdGFydCwgZW5kOiBuZXdFbmQgfTtcbiAgICAgIH1cbiAgICAgIHJldHVybiBwcmV2O1xuICAgIH0pO1xuXG4gICAgcHJldlJvb3RSZWYuY3VycmVudCA9IHsgc3RhcnQ6IG5ld1N0YXJ0LCBlbmQ6IG5ld0VuZCB9O1xuICB9LCBbcm9vdC5zdGFydFRpbWUsIHJvb3QuZHVyYXRpb24sIHNldFZpZXdwb3J0XSk7XG5cbiAgY29uc3Qgdmlld0R1cmF0aW9uID0gdmlld3BvcnQuZW5kIC0gdmlld3BvcnQuc3RhcnQ7XG5cbiAgY29uc3QgdGltZU1hcmtlcnMgPSB1c2VNZW1vKFxuICAgICgpID0+IGNvbXB1dGVUaW1lTWFya2Vycyh2aWV3RHVyYXRpb24sIHZpZXdwb3J0LnN0YXJ0IC0gcm9vdC5zdGFydFRpbWUpLFxuICAgIFt2aWV3RHVyYXRpb24sIHZpZXdwb3J0LnN0YXJ0LCByb290LnN0YXJ0VGltZV1cbiAgKTtcblxuICBjb25zdCByZXNldFpvb20gPSB1c2VDYWxsYmFjaygoKSA9PiB7XG4gICAgYW5pbWF0ZVRvKHsgc3RhcnQ6IHJvb3Quc3RhcnRUaW1lLCBlbmQ6IHJvb3Quc3RhcnRUaW1lICsgcm9vdC5kdXJhdGlvbiB9KTtcbiAgfSwgW2FuaW1hdGVUbywgcm9vdC5zdGFydFRpbWUsIHJvb3QuZHVyYXRpb25dKTtcblxuICBjb25zdCBaT09NX0ZBQ1RPUiA9IDAuNTtcblxuICBjb25zdCB6b29tQnkgPSB1c2VDYWxsYmFjayhcbiAgICAoZmFjdG9yOiBudW1iZXIpID0+IHtcbiAgICAgIGNvbnN0IHJvb3RTID0gcm9vdC5zdGFydFRpbWU7XG4gICAgICBjb25zdCByb290RSA9IHJvb3Quc3RhcnRUaW1lICsgcm9vdC5kdXJhdGlvbjtcbiAgICAgIGNvbnN0IHJvb3REID0gcm9vdC5kdXJhdGlvbjtcblxuICAgICAgc2V0Vmlld3BvcnQoKHByZXYpID0+IHtcbiAgICAgICAgY29uc3QgcHJldkR1cmF0aW9uID0gcHJldi5lbmQgLSBwcmV2LnN0YXJ0O1xuICAgICAgICBjb25zdCBjZW50ZXIgPSAocHJldi5zdGFydCArIHByZXYuZW5kKSAvIDI7XG4gICAgICAgIGNvbnN0IG5ld0R1cmF0aW9uID0gTWF0aC5tYXgoXG4gICAgICAgICAgTUlOX1ZJRVdQT1JUX01TLFxuICAgICAgICAgIE1hdGgubWluKHJvb3RELCBwcmV2RHVyYXRpb24gKiBmYWN0b3IpXG4gICAgICAgICk7XG4gICAgICAgIGxldCBuZXdTdGFydCA9IGNlbnRlciAtIG5ld0R1cmF0aW9uIC8gMjtcbiAgICAgICAgbGV0IG5ld0VuZCA9IGNlbnRlciArIG5ld0R1cmF0aW9uIC8gMjtcblxuICAgICAgICBpZiAobmV3U3RhcnQgPCByb290Uykge1xuICAgICAgICAgIG5ld1N0YXJ0ID0gcm9vdFM7XG4gICAgICAgICAgbmV3RW5kID0gcm9vdFMgKyBuZXdEdXJhdGlvbjtcbiAgICAgICAgfVxuICAgICAgICBpZiAobmV3RW5kID4gcm9vdEUpIHtcbiAgICAgICAgICBuZXdFbmQgPSByb290RTtcbiAgICAgICAgICBuZXdTdGFydCA9IE1hdGgubWF4KHJvb3RTLCByb290RSAtIG5ld0R1cmF0aW9uKTtcbiAgICAgICAgfVxuXG4gICAgICAgIHJldHVybiB7IHN0YXJ0OiBuZXdTdGFydCwgZW5kOiBuZXdFbmQgfTtcbiAgICAgIH0pO1xuICAgIH0sXG4gICAgW3NldFZpZXdwb3J0LCByb290LnN0YXJ0VGltZSwgcm9vdC5kdXJhdGlvbl1cbiAgKTtcblxuICBjb25zdCB6b29tSW4gPSB1c2VDYWxsYmFjaygoKSA9PiB6b29tQnkoWk9PTV9GQUNUT1IpLCBbem9vbUJ5XSk7XG4gIGNvbnN0IHpvb21PdXQgPSB1c2VDYWxsYmFjaygoKSA9PiB6b29tQnkoMSAvIFpPT01fRkFDVE9SKSwgW3pvb21CeV0pO1xuXG4gIGNvbnN0IGhhbmRsZVNlbGVjdFNwYW4gPSB1c2VDYWxsYmFjayhcbiAgICAoc3BhbklkOiBzdHJpbmcpID0+IHtcbiAgICAgIGlmIChzcGFuSWQgPT09IGFjdGl2ZVNwYW5JZCkge1xuICAgICAgICBjbGVhckFjdGl2ZVNwYW4oKTtcbiAgICAgICAgcmV0dXJuO1xuICAgICAgfVxuICAgICAgc2V0QWN0aXZlU3BhbihzcGFuSWQpO1xuXG4gICAgICBjb25zdCBzcGFuID0gdHJhY2Uuc3BhbnMuZmluZCgocykgPT4gcy5zcGFuSWQgPT09IHNwYW5JZCk7XG4gICAgICBpZiAoIXNwYW4pIHJldHVybjtcblxuICAgICAgY29uc3Qgc3BhblN0YXJ0ID0gZ2V0SGlnaFJlc0luTXMoc3Bhbi5zdGFydFRpbWUpO1xuICAgICAgY29uc3Qgc3BhbkVuZCA9IGdldEhpZ2hSZXNJbk1zKHNwYW4uZW5kVGltZSk7XG4gICAgICBjb25zdCBzcGFuRHVyYXRpb24gPSBzcGFuRW5kIC0gc3BhblN0YXJ0O1xuXG4gICAgICBjb25zdCByb290UyA9IHJvb3Quc3RhcnRUaW1lO1xuICAgICAgY29uc3Qgcm9vdEUgPSByb290LnN0YXJ0VGltZSArIHJvb3QuZHVyYXRpb247XG4gICAgICBjb25zdCByb290RCA9IHJvb3QuZHVyYXRpb247XG5cbiAgICAgIGlmIChzcGFuRHVyYXRpb24gPiByb290RCAqIDAuOCkge1xuICAgICAgICBhbmltYXRlVG8oeyBzdGFydDogcm9vdFMsIGVuZDogcm9vdEUgfSk7XG4gICAgICAgIHJldHVybjtcbiAgICAgIH1cblxuICAgICAgY29uc3QgcGFkZGluZyA9IE1hdGgubWF4KHNwYW5EdXJhdGlvbiAqIDAuMiwgTUlOX1ZJRVdQT1JUX01TIC8gMik7XG4gICAgICBsZXQgbmV3U3RhcnQgPSBzcGFuU3RhcnQgLSBwYWRkaW5nO1xuICAgICAgbGV0IG5ld0VuZCA9IHNwYW5FbmQgKyBwYWRkaW5nO1xuXG4gICAgICBpZiAobmV3RW5kIC0gbmV3U3RhcnQgPCBNSU5fVklFV1BPUlRfTVMpIHtcbiAgICAgICAgY29uc3QgY2VudGVyID0gKHNwYW5TdGFydCArIHNwYW5FbmQpIC8gMjtcbiAgICAgICAgbmV3U3RhcnQgPSBjZW50ZXIgLSBNSU5fVklFV1BPUlRfTVMgLyAyO1xuICAgICAgICBuZXdFbmQgPSBjZW50ZXIgKyBNSU5fVklFV1BPUlRfTVMgLyAyO1xuICAgICAgfVxuXG4gICAgICBpZiAobmV3U3RhcnQgPCByb290Uykge1xuICAgICAgICBjb25zdCBkdXJhdGlvbiA9IG5ld0VuZCAtIG5ld1N0YXJ0O1xuICAgICAgICBuZXdTdGFydCA9IHJvb3RTO1xuICAgICAgICBuZXdFbmQgPSBNYXRoLm1pbihyb290RSwgcm9vdFMgKyBkdXJhdGlvbik7XG4gICAgICB9XG4gICAgICBpZiAobmV3RW5kID4gcm9vdEUpIHtcbiAgICAgICAgY29uc3QgZHVyYXRpb24gPSBuZXdFbmQgLSBuZXdTdGFydDtcbiAgICAgICAgbmV3RW5kID0gcm9vdEU7XG4gICAgICAgIG5ld1N0YXJ0ID0gTWF0aC5tYXgocm9vdFMsIHJvb3RFIC0gZHVyYXRpb24pO1xuICAgICAgfVxuXG4gICAgICBhbmltYXRlVG8oeyBzdGFydDogbmV3U3RhcnQsIGVuZDogbmV3RW5kIH0pO1xuICAgIH0sXG4gICAgW1xuICAgICAgYW5pbWF0ZVRvLFxuICAgICAgc2V0QWN0aXZlU3BhbixcbiAgICAgIGNsZWFyQWN0aXZlU3BhbixcbiAgICAgIGFjdGl2ZVNwYW5JZCxcbiAgICAgIHRyYWNlLnNwYW5zLFxuICAgICAgcm9vdC5zdGFydFRpbWUsXG4gICAgICByb290LmR1cmF0aW9uLFxuICAgIF1cbiAgKTtcblxuICBjb25zdCBbYWx0SGVsZCwgc2V0QWx0SGVsZF0gPSB1c2VTdGF0ZShmYWxzZSk7XG5cbiAgdXNlRWZmZWN0KCgpID0+IHtcbiAgICBjb25zdCBoYW5kbGVTaWRlYmFyTmF2S2V5ID0gKGU6IEtleWJvYXJkRXZlbnQpOiB2b2lkID0+IHtcbiAgICAgIGNvbnN0IHRhcmdldCA9IGUudGFyZ2V0IGFzIEhUTUxFbGVtZW50IHwgbnVsbDtcbiAgICAgIGlmIChcbiAgICAgICAgdGFyZ2V0IGluc3RhbmNlb2YgSFRNTElucHV0RWxlbWVudCB8fFxuICAgICAgICB0YXJnZXQgaW5zdGFuY2VvZiBIVE1MVGV4dEFyZWFFbGVtZW50IHx8XG4gICAgICAgIHRhcmdldD8uaXNDb250ZW50RWRpdGFibGVcbiAgICAgICkge1xuICAgICAgICByZXR1cm47XG4gICAgICB9XG4gICAgICBjb25zdCB0YXJnZXRJZCA9XG4gICAgICAgIGUua2V5ID09PSAnaycgPyBwcmV2U3BhbklkUmVmLmN1cnJlbnQgOiBuZXh0U3BhbklkUmVmLmN1cnJlbnQ7XG4gICAgICBpZiAodGFyZ2V0SWQpIHtcbiAgICAgICAgZS5wcmV2ZW50RGVmYXVsdCgpO1xuICAgICAgICBoYW5kbGVTZWxlY3RTcGFuUmVmLmN1cnJlbnQodGFyZ2V0SWQpO1xuICAgICAgfVxuICAgIH07XG5cbiAgICBjb25zdCBvbktleURvd24gPSAoZTogS2V5Ym9hcmRFdmVudCk6IHZvaWQgPT4ge1xuICAgICAgaWYgKGUua2V5ID09PSAnRXNjYXBlJykge1xuICAgICAgICBjbGVhckFjdGl2ZVNwYW4oKTtcbiAgICAgIH0gZWxzZSBpZiAoZS5rZXkgPT09ICdBbHQnKSB7XG4gICAgICAgIGUucHJldmVudERlZmF1bHQoKTtcbiAgICAgICAgc2V0QWx0SGVsZCh0cnVlKTtcbiAgICAgIH0gZWxzZSBpZiAoZS5rZXkgPT09ICdqJyB8fCBlLmtleSA9PT0gJ2snKSB7XG4gICAgICAgIGhhbmRsZVNpZGViYXJOYXZLZXkoZSk7XG4gICAgICB9XG4gICAgfTtcbiAgICBjb25zdCBvbktleVVwID0gKGU6IEtleWJvYXJkRXZlbnQpOiB2b2lkID0+IHtcbiAgICAgIGlmIChlLmtleSA9PT0gJ0FsdCcpIHNldEFsdEhlbGQoZmFsc2UpO1xuICAgIH07XG4gICAgY29uc3Qgb25CbHVyID0gKCk6IHZvaWQgPT4gc2V0QWx0SGVsZChmYWxzZSk7XG5cbiAgICB3aW5kb3cuYWRkRXZlbnRMaXN0ZW5lcigna2V5ZG93bicsIG9uS2V5RG93bik7XG4gICAgd2luZG93LmFkZEV2ZW50TGlzdGVuZXIoJ2tleXVwJywgb25LZXlVcCk7XG4gICAgd2luZG93LmFkZEV2ZW50TGlzdGVuZXIoJ2JsdXInLCBvbkJsdXIpO1xuICAgIHJldHVybiAoKSA9PiB7XG4gICAgICB3aW5kb3cucmVtb3ZlRXZlbnRMaXN0ZW5lcigna2V5ZG93bicsIG9uS2V5RG93bik7XG4gICAgICB3aW5kb3cucmVtb3ZlRXZlbnRMaXN0ZW5lcigna2V5dXAnLCBvbktleVVwKTtcbiAgICAgIHdpbmRvdy5yZW1vdmVFdmVudExpc3RlbmVyKCdibHVyJywgb25CbHVyKTtcbiAgICB9O1xuICB9LCBbY2xlYXJBY3RpdmVTcGFuXSk7XG5cbiAgY29uc3QgdGltZWxpbmVSZWYgPSB1c2VSZWY8SFRNTERpdkVsZW1lbnQ+KG51bGwpO1xuICBjb25zdCBbaG92ZXJGcmFjdGlvbiwgc2V0SG92ZXJGcmFjdGlvbl0gPSB1c2VTdGF0ZTxudW1iZXIgfCBudWxsPihudWxsKTtcblxuICBjb25zdCBob3ZlckluZm8gPSB1c2VNZW1vKCgpID0+IHtcbiAgICBpZiAoaG92ZXJGcmFjdGlvbiA9PSBudWxsKSByZXR1cm4gbnVsbDtcbiAgICBjb25zdCBhYnNUaW1lID0gdmlld3BvcnQuc3RhcnQgKyBob3ZlckZyYWN0aW9uICogdmlld0R1cmF0aW9uO1xuICAgIGNvbnN0IG9mZnNldCA9IGFic1RpbWUgLSByb290LnN0YXJ0VGltZTtcbiAgICByZXR1cm4geyBmcmFjdGlvbjogaG92ZXJGcmFjdGlvbiwgbGFiZWw6IGZvcm1hdER1cmF0aW9uKG9mZnNldCwgdHJ1ZSkgfTtcbiAgfSwgW2hvdmVyRnJhY3Rpb24sIHZpZXdwb3J0LnN0YXJ0LCB2aWV3RHVyYXRpb24sIHJvb3Quc3RhcnRUaW1lXSk7XG5cbiAgY29uc3QgaGFuZGxlVGltZWxpbmVNb3VzZU1vdmUgPSB1c2VDYWxsYmFjayhcbiAgICAoZTogUmVhY3QuTW91c2VFdmVudDxIVE1MRGl2RWxlbWVudD4pID0+IHtcbiAgICAgIGNvbnN0IGVsID0gdGltZWxpbmVSZWYuY3VycmVudDtcbiAgICAgIGlmICghZWwpIHJldHVybjtcbiAgICAgIGNvbnN0IHJlY3QgPSBlbC5nZXRCb3VuZGluZ0NsaWVudFJlY3QoKTtcbiAgICAgIGNvbnN0IGNvbnRlbnRXaWR0aCA9IHJlY3Qud2lkdGggLSBUSU1FTElORV9QQURESU5HX1BYICogMjtcbiAgICAgIGlmIChjb250ZW50V2lkdGggPD0gMCkgcmV0dXJuO1xuICAgICAgY29uc3QgZnJhY3Rpb24gPSBNYXRoLm1heChcbiAgICAgICAgMCxcbiAgICAgICAgTWF0aC5taW4oXG4gICAgICAgICAgMSxcbiAgICAgICAgICAoZS5jbGllbnRYIC0gcmVjdC5sZWZ0IC0gVElNRUxJTkVfUEFERElOR19QWCkgLyBjb250ZW50V2lkdGhcbiAgICAgICAgKVxuICAgICAgKTtcbiAgICAgIHNldEhvdmVyRnJhY3Rpb24oZnJhY3Rpb24pO1xuICAgIH0sXG4gICAgW11cbiAgKTtcblxuICBjb25zdCBoYW5kbGVUaW1lbGluZU1vdXNlTGVhdmUgPSB1c2VDYWxsYmFjaygoKSA9PiB7XG4gICAgc2V0SG92ZXJGcmFjdGlvbihudWxsKTtcbiAgfSwgW10pO1xuXG4gIHVzZUVmZmVjdCgoKSA9PiB7XG4gICAgY29uc3QgZWwgPSB0aW1lbGluZVJlZi5jdXJyZW50O1xuICAgIGlmICghZWwpIHJldHVybjtcblxuICAgIGNvbnN0IHJvb3RTID0gcm9vdC5zdGFydFRpbWU7XG4gICAgY29uc3Qgcm9vdEUgPSByb290LnN0YXJ0VGltZSArIHJvb3QuZHVyYXRpb247XG4gICAgY29uc3Qgcm9vdEQgPSByb290LmR1cmF0aW9uO1xuICAgIGlmIChyb290RCA8PSAwKSByZXR1cm47XG5cbiAgICBjb25zdCBvbldoZWVsID0gKGU6IFdoZWVsRXZlbnQpOiB2b2lkID0+IHtcbiAgICAgIGNvbnN0IGlzWm9vbUdlc3R1cmUgPSBlLmN0cmxLZXkgfHwgZS5tZXRhS2V5O1xuICAgICAgY29uc3QgaGFzRGVsdGFYID0gTWF0aC5hYnMoZS5kZWx0YVgpID4gTWF0aC5hYnMoZS5kZWx0YVkpO1xuXG4gICAgICBpZiAoIWlzWm9vbUdlc3R1cmUgJiYgIWhhc0RlbHRhWCkgcmV0dXJuO1xuICAgICAgZS5wcmV2ZW50RGVmYXVsdCgpO1xuXG4gICAgICBjb25zdCByZWN0ID0gZWwuZ2V0Qm91bmRpbmdDbGllbnRSZWN0KCk7XG4gICAgICBjb25zdCBjb250ZW50V2lkdGggPSByZWN0LndpZHRoIC0gVElNRUxJTkVfUEFERElOR19QWCAqIDI7XG4gICAgICBpZiAoY29udGVudFdpZHRoIDw9IDApIHJldHVybjtcblxuICAgICAgaWYgKGlzWm9vbUdlc3R1cmUpIHtcbiAgICAgICAgbGV0IGR5ID0gZS5kZWx0YVk7XG4gICAgICAgIGlmIChlLmRlbHRhTW9kZSA9PT0gMSkgZHkgKj0gMTY7XG5cbiAgICAgICAgY29uc3QgY3Vyc29yRnJhY3Rpb24gPSBNYXRoLm1heChcbiAgICAgICAgICAwLFxuICAgICAgICAgIE1hdGgubWluKFxuICAgICAgICAgICAgMSxcbiAgICAgICAgICAgIChlLmNsaWVudFggLSByZWN0LmxlZnQgLSBUSU1FTElORV9QQURESU5HX1BYKSAvIGNvbnRlbnRXaWR0aFxuICAgICAgICAgIClcbiAgICAgICAgKTtcbiAgICAgICAgY29uc3QgaXNNb3VzZVdoZWVsID0gZS5kZWx0YU1vZGUgPT09IDEgfHwgTWF0aC5hYnMoZS5kZWx0YVkpID49IDUwO1xuICAgICAgICBjb25zdCBzY2FsZUZhY3RvciA9IE1hdGgucG93KDIsIGR5IC8gKGlzTW91c2VXaGVlbCA/IDIwMCA6IDYwKSk7XG5cbiAgICAgICAgc2V0Vmlld3BvcnQoKHByZXYpID0+IHtcbiAgICAgICAgICBjb25zdCBwcmV2RHVyYXRpb24gPSBwcmV2LmVuZCAtIHByZXYuc3RhcnQ7XG4gICAgICAgICAgY29uc3QgY3Vyc29yVGltZSA9IHByZXYuc3RhcnQgKyBjdXJzb3JGcmFjdGlvbiAqIHByZXZEdXJhdGlvbjtcbiAgICAgICAgICBjb25zdCBuZXdEdXJhdGlvbiA9IE1hdGgubWF4KFxuICAgICAgICAgICAgTUlOX1ZJRVdQT1JUX01TLFxuICAgICAgICAgICAgTWF0aC5taW4ocm9vdEQsIHByZXZEdXJhdGlvbiAqIHNjYWxlRmFjdG9yKVxuICAgICAgICAgICk7XG5cbiAgICAgICAgICBsZXQgbmV3U3RhcnQgPSBjdXJzb3JUaW1lIC0gY3Vyc29yRnJhY3Rpb24gKiBuZXdEdXJhdGlvbjtcbiAgICAgICAgICBsZXQgbmV3RW5kID0gbmV3U3RhcnQgKyBuZXdEdXJhdGlvbjtcblxuICAgICAgICAgIGlmIChuZXdTdGFydCA8IHJvb3RTKSB7XG4gICAgICAgICAgICBuZXdTdGFydCA9IHJvb3RTO1xuICAgICAgICAgICAgbmV3RW5kID0gcm9vdFMgKyBuZXdEdXJhdGlvbjtcbiAgICAgICAgICB9XG4gICAgICAgICAgaWYgKG5ld0VuZCA+IHJvb3RFKSB7XG4gICAgICAgICAgICBuZXdFbmQgPSByb290RTtcbiAgICAgICAgICAgIG5ld1N0YXJ0ID0gTWF0aC5tYXgocm9vdFMsIHJvb3RFIC0gbmV3RHVyYXRpb24pO1xuICAgICAgICAgIH1cblxuICAgICAgICAgIHJldHVybiB7IHN0YXJ0OiBuZXdTdGFydCwgZW5kOiBuZXdFbmQgfTtcbiAgICAgICAgfSk7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICBsZXQgZHggPSBlLmRlbHRhWDtcbiAgICAgICAgaWYgKGUuZGVsdGFNb2RlID09PSAxKSBkeCAqPSAxNjtcblxuICAgICAgICBzZXRWaWV3cG9ydCgocHJldikgPT4ge1xuICAgICAgICAgIGNvbnN0IHByZXZEdXJhdGlvbiA9IHByZXYuZW5kIC0gcHJldi5zdGFydDtcbiAgICAgICAgICBjb25zdCBwYW5BbW91bnQgPSAoZHggLyBjb250ZW50V2lkdGgpICogcHJldkR1cmF0aW9uO1xuXG4gICAgICAgICAgbGV0IG5ld1N0YXJ0ID0gcHJldi5zdGFydCArIHBhbkFtb3VudDtcbiAgICAgICAgICBsZXQgbmV3RW5kID0gcHJldi5lbmQgKyBwYW5BbW91bnQ7XG5cbiAgICAgICAgICBpZiAobmV3U3RhcnQgPCByb290Uykge1xuICAgICAgICAgICAgbmV3U3RhcnQgPSByb290UztcbiAgICAgICAgICAgIG5ld0VuZCA9IHJvb3RTICsgcHJldkR1cmF0aW9uO1xuICAgICAgICAgIH1cbiAgICAgICAgICBpZiAobmV3RW5kID4gcm9vdEUpIHtcbiAgICAgICAgICAgIG5ld0VuZCA9IHJvb3RFO1xuICAgICAgICAgICAgbmV3U3RhcnQgPSBNYXRoLm1heChyb290Uywgcm9vdEUgLSBwcmV2RHVyYXRpb24pO1xuICAgICAgICAgIH1cblxuICAgICAgICAgIHJldHVybiB7IHN0YXJ0OiBuZXdTdGFydCwgZW5kOiBuZXdFbmQgfTtcbiAgICAgICAgfSk7XG4gICAgICB9XG4gICAgfTtcblxuICAgIGVsLmFkZEV2ZW50TGlzdGVuZXIoJ3doZWVsJywgb25XaGVlbCwgeyBwYXNzaXZlOiBmYWxzZSB9KTtcbiAgICByZXR1cm4gKCkgPT4gZWwucmVtb3ZlRXZlbnRMaXN0ZW5lcignd2hlZWwnLCBvbldoZWVsKTtcbiAgfSwgW3Jvb3Quc3RhcnRUaW1lLCByb290LmR1cmF0aW9uLCBzZXRWaWV3cG9ydF0pO1xuXG4gIC8vIERlcml2ZSB0aGUgc2VsZWN0ZWQgc3BhbiBuYW1lIGFuZCBtZXRhZGF0YSBmb3IgdGhlIHBhbmVsIGhlYWRlclxuICBjb25zdCBzZWxlY3RlZFNwYW5OYW1lID0gdXNlTWVtbygoKSA9PiB7XG4gICAgaWYgKCFzZWxlY3RlZFNwYW4/LmRhdGEpIHJldHVybiAnRGV0YWlscyc7XG4gICAgY29uc3QgZGF0YSA9IHNlbGVjdGVkU3Bhbi5kYXRhIGFzIFJlY29yZDxzdHJpbmcsIHVua25vd24+O1xuICAgIGlmIChzZWxlY3RlZFNwYW4ucmVzb3VyY2UgPT09ICdob29rJykge1xuICAgICAgcmV0dXJuIChkYXRhLnRva2VuIGFzIHN0cmluZyB8IHVuZGVmaW5lZCkgPz8gKGRhdGEuaG9va0lkIGFzIHN0cmluZyk7XG4gICAgfVxuXG4gICAgY29uc3Qgc3RlcE5hbWUgPSBkYXRhLnN0ZXBOYW1lIGFzIHN0cmluZyB8IHVuZGVmaW5lZDtcbiAgICBjb25zdCB3b3JrZmxvd05hbWUgPSBkYXRhLndvcmtmbG93TmFtZSBhcyBzdHJpbmcgfCB1bmRlZmluZWQ7XG4gICAgcmV0dXJuIChcbiAgICAgIChzdGVwTmFtZSA/IHBhcnNlU3RlcE5hbWUoc3RlcE5hbWUpPy5zaG9ydE5hbWUgOiB1bmRlZmluZWQpID8/XG4gICAgICAod29ya2Zsb3dOYW1lID8gcGFyc2VXb3JrZmxvd05hbWUod29ya2Zsb3dOYW1lKT8uc2hvcnROYW1lIDogdW5kZWZpbmVkKSA/P1xuICAgICAgc3RlcE5hbWUgPz9cbiAgICAgIHdvcmtmbG93TmFtZSA/P1xuICAgICAgKGRhdGEuaG9va0lkIGFzIHN0cmluZykgPz9cbiAgICAgICdEZXRhaWxzJ1xuICAgICk7XG4gIH0sIFtzZWxlY3RlZFNwYW4/LmRhdGEsIHNlbGVjdGVkU3Bhbj8ucmVzb3VyY2VdKTtcblxuICBjb25zdCB7IHByZXZTcGFuSWQsIG5leHRTcGFuSWQgfSA9IHVzZU1lbW8oKCkgPT4ge1xuICAgIGlmICghYWN0aXZlU3BhbklkKSByZXR1cm4geyBwcmV2U3BhbklkOiBudWxsLCBuZXh0U3BhbklkOiBudWxsIH07XG4gICAgY29uc3QgaSA9IHRyYWNlLnNwYW5zLmZpbmRJbmRleCgocykgPT4gcy5zcGFuSWQgPT09IGFjdGl2ZVNwYW5JZCk7XG4gICAgaWYgKGkgPT09IC0xKSByZXR1cm4geyBwcmV2U3BhbklkOiBudWxsLCBuZXh0U3BhbklkOiBudWxsIH07XG4gICAgcmV0dXJuIHtcbiAgICAgIHByZXZTcGFuSWQ6IHRyYWNlLnNwYW5zW2kgLSAxXT8uc3BhbklkID8/IG51bGwsXG4gICAgICBuZXh0U3BhbklkOiB0cmFjZS5zcGFuc1tpICsgMV0/LnNwYW5JZCA/PyBudWxsLFxuICAgIH07XG4gIH0sIFthY3RpdmVTcGFuSWQsIHRyYWNlLnNwYW5zXSk7XG5cbiAgY29uc3QgaGFuZGxlU2VsZWN0UHJldlNwYW4gPSB1c2VDYWxsYmFjaygoKSA9PiB7XG4gICAgaWYgKHByZXZTcGFuSWQpIGhhbmRsZVNlbGVjdFNwYW4ocHJldlNwYW5JZCk7XG4gIH0sIFtwcmV2U3BhbklkLCBoYW5kbGVTZWxlY3RTcGFuXSk7XG5cbiAgY29uc3QgaGFuZGxlU2VsZWN0TmV4dFNwYW4gPSB1c2VDYWxsYmFjaygoKSA9PiB7XG4gICAgaWYgKG5leHRTcGFuSWQpIGhhbmRsZVNlbGVjdFNwYW4obmV4dFNwYW5JZCk7XG4gIH0sIFtuZXh0U3BhbklkLCBoYW5kbGVTZWxlY3RTcGFuXSk7XG5cbiAgY29uc3QgcHJldlNwYW5JZFJlZiA9IHVzZVJlZihwcmV2U3BhbklkKTtcbiAgY29uc3QgbmV4dFNwYW5JZFJlZiA9IHVzZVJlZihuZXh0U3BhbklkKTtcbiAgY29uc3QgaGFuZGxlU2VsZWN0U3BhblJlZiA9IHVzZVJlZihoYW5kbGVTZWxlY3RTcGFuKTtcbiAgcHJldlNwYW5JZFJlZi5jdXJyZW50ID0gcHJldlNwYW5JZDtcbiAgbmV4dFNwYW5JZFJlZi5jdXJyZW50ID0gbmV4dFNwYW5JZDtcbiAgaGFuZGxlU2VsZWN0U3BhblJlZi5jdXJyZW50ID0gaGFuZGxlU2VsZWN0U3BhbjtcblxuICByZXR1cm4gKFxuICAgIDxkaXZcbiAgICAgIGRhdGEtcGFuZT1cInBhbmUtcm9vdFwiXG4gICAgICBkYXRhLWhhcy1kZXRhaWw9e2FjdGl2ZVNwYW4gPyAnJyA6IHVuZGVmaW5lZH1cbiAgICAgIGNsYXNzTmFtZT1cImdyaWQgdy1mdWxsIGgtZnVsbCBtYXgtaC1mdWxsIGdyaWQtY29scy1bbWlubWF4KDEwMHB4LDFmcildIGRhdGEtW2hhcy1kZXRhaWxdOmdyaWQtY29scy1bbWlubWF4KDEwMHB4LDFmcilfY2xhbXAoMjgwcHgsNDIwcHgsMTAwJSldXCJcbiAgICA+XG4gICAgICA8ZGl2XG4gICAgICAgIGlkPVwidHJhY2UtcGFyZW50XCJcbiAgICAgICAgY2xhc3NOYW1lPVwiZ3JpZCBncmlkLXJvd3MtWzFmcl0gaC1mdWxsIG1pbi1oLTAgb3ZlcmZsb3ctaGlkZGVuIHJlbGF0aXZlIGJnLWJhY2tncm91bmQtMTAwXCJcbiAgICAgID5cbiAgICAgICAgPFNwbGl0UGFuZVxuICAgICAgICAgIHN0YXJ0SGVhZGVyPXtcbiAgICAgICAgICAgIDxkaXYgY2xhc3NOYW1lPVwiYmctYmFja2dyb3VuZC0xMDAgYm9yZGVyLWIgYm9yZGVyLWdyYXktYWxwaGEtNDAwIGgtMTAgbWluLWgtMTAgZmxleCBpdGVtcy1jZW50ZXIgcGwtNCBwci0yIGdhcC0xLjVcIj5cbiAgICAgICAgICAgICAgPFNlYXJjaCBjbGFzc05hbWU9XCJ3LTMuNSBoLTMuNSBzaHJpbmstMCB0ZXh0LWdyYXktODAwXCIgLz5cbiAgICAgICAgICAgICAgPGlucHV0XG4gICAgICAgICAgICAgICAgaWQ9XCJ0cmFjZS12aWV3ZXItc2VhcmNoXCJcbiAgICAgICAgICAgICAgICBuYW1lPVwidHJhY2Utdmlld2VyLXNlYXJjaFwiXG4gICAgICAgICAgICAgICAgdHlwZT1cInRleHRcIlxuICAgICAgICAgICAgICAgIHZhbHVlPXtzZWFyY2hRdWVyeX1cbiAgICAgICAgICAgICAgICBvbkNoYW5nZT17KGUpID0+IHNldFNlYXJjaFF1ZXJ5KGUudGFyZ2V0LnZhbHVlKX1cbiAgICAgICAgICAgICAgICBvbktleURvd249eyhlKSA9PiB7XG4gICAgICAgICAgICAgICAgICBpZiAoZS5rZXkgPT09ICdFc2NhcGUnICYmIHNlYXJjaFF1ZXJ5KSB7XG4gICAgICAgICAgICAgICAgICAgIGUucHJldmVudERlZmF1bHQoKTtcbiAgICAgICAgICAgICAgICAgICAgZS5zdG9wUHJvcGFnYXRpb24oKTtcbiAgICAgICAgICAgICAgICAgICAgc2V0U2VhcmNoUXVlcnkoJycpO1xuICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH19XG4gICAgICAgICAgICAgICAgcGxhY2Vob2xkZXI9XCJTZWFyY2ggc3BhbnMuLi5cIlxuICAgICAgICAgICAgICAgIGFyaWEtbGFiZWw9XCJTZWFyY2ggc3BhbnNcIlxuICAgICAgICAgICAgICAgIGNsYXNzTmFtZT1cImZsZXgtMSBtaW4tdy0wIGJnLXRyYW5zcGFyZW50IHRleHQtc20gdGV4dC1ncmF5LTEwMDAgcGxhY2Vob2xkZXI6dGV4dC1ncmF5LTgwMCBvdXRsaW5lLW5vbmVcIlxuICAgICAgICAgICAgICAvPlxuICAgICAgICAgICAgICB7c2VhcmNoUXVlcnkgJiYgKFxuICAgICAgICAgICAgICAgIDxidXR0b25cbiAgICAgICAgICAgICAgICAgIHR5cGU9XCJidXR0b25cIlxuICAgICAgICAgICAgICAgICAgYXJpYS1sYWJlbD1cIkNsZWFyIHNlYXJjaFwiXG4gICAgICAgICAgICAgICAgICBvbkNsaWNrPXsoKSA9PiBzZXRTZWFyY2hRdWVyeSgnJyl9XG4gICAgICAgICAgICAgICAgICBjbGFzc05hbWU9XCItbXItMiBoaWRkZW4gaC1mdWxsIG1heC13LWZ1bGwgc2hyaW5rLTAgY3Vyc29yLXBvaW50ZXIgaXRlbXMtY2VudGVyIHJvdW5kZWQtci1tZCBib3JkZXItMCBiZy10cmFuc3BhcmVudCBweC0yLjUgZm9udC1pbmhlcml0IHRleHQtYmFzZSB0ZXh0LWdyYXktOTAwIG5vLXVuZGVybGluZSB0cmFuc2l0aW9uLWNvbG9ycyBkdXJhdGlvbi0xNTAgZWFzZS1pbiBob3Zlcjp0ZXh0LWdyYXktMTAwMCBmb2N1cy12aXNpYmxlOi1vdXRsaW5lLW9mZnNldC0xIGZvY3VzLXZpc2libGU6b3V0bGluZSBmb2N1cy12aXNpYmxlOm91dGxpbmUtMiBmb2N1cy12aXNpYmxlOm91dGxpbmUtW3ZhcigtLWRzLWZvY3VzLWNvbG9yKV0gbWluLVs5NjFweF06ZmxleFwiXG4gICAgICAgICAgICAgICAgPlxuICAgICAgICAgICAgICAgICAgPGtiZCBjbGFzc05hbWU9XCJpbmxpbmUtZmxleCBoLTUgbWluLWgtNSBtaW4tdy01IGl0ZW1zLWNlbnRlciBqdXN0aWZ5LWNlbnRlciByb3VuZGVkIGJvcmRlciBib3JkZXItZ3JheS1hbHBoYS00MDAgYmctYmFja2dyb3VuZC0xMDAgcHgtMSBmb250LXNhbnMgdGV4dC1bMTNweF0gZm9udC1tZWRpdW0gbGVhZGluZy1bMS43ZW1dIHRleHQtZ3JheS05MDBcIj5cbiAgICAgICAgICAgICAgICAgICAgRXNjXG4gICAgICAgICAgICAgICAgICA8L2tiZD5cbiAgICAgICAgICAgICAgICA8L2J1dHRvbj5cbiAgICAgICAgICAgICAgKX1cbiAgICAgICAgICAgIDwvZGl2PlxuICAgICAgICAgIH1cbiAgICAgICAgICBlbmRIZWFkZXI9e1xuICAgICAgICAgICAgPFRpbWVsaW5lSGVhZGVyIG1hcmtlcnM9e3RpbWVNYXJrZXJzfSBob3ZlckluZm89e2hvdmVySW5mb30gLz5cbiAgICAgICAgICB9XG4gICAgICAgID5cbiAgICAgICAgICA8ZGl2IGNsYXNzTmFtZT1cImJsb2NrIG92ZXJmbG93LXZpc2libGVcIj5cbiAgICAgICAgICAgIDxFdmVudExpc3RcbiAgICAgICAgICAgICAgc3BhbnM9e3RyYWNlLnNwYW5zfVxuICAgICAgICAgICAgICBhY3RpdmVTcGFuSWQ9e2FjdGl2ZVNwYW5JZH1cbiAgICAgICAgICAgICAgc2VhcmNoUmVzdWx0PXtzZWFyY2hSZXN1bHR9XG4gICAgICAgICAgICAgIG9uU2VsZWN0U3Bhbj17aGFuZGxlU2VsZWN0U3Bhbn1cbiAgICAgICAgICAgIC8+XG4gICAgICAgICAgPC9kaXY+XG4gICAgICAgICAgey8qIGJpb21lLWlnbm9yZSBsaW50L2ExMXkvbm9TdGF0aWNFbGVtZW50SW50ZXJhY3Rpb25zOiB0aW1lbGluZSBob3ZlciBhbmQgd2hlZWwgZ2VzdHVyZXMgYXJlIHBvaW50ZXItb25seSBhbm5vdGF0aW9ucyAqL31cbiAgICAgICAgICA8ZGl2XG4gICAgICAgICAgICByZWY9e3RpbWVsaW5lUmVmfVxuICAgICAgICAgICAgY2xhc3NOYW1lPVwiYmxvY2sgbWluLWgtMCBvdmVyZmxvdy12aXNpYmxlIHJlbGF0aXZlXCJcbiAgICAgICAgICAgIG9uRG91YmxlQ2xpY2s9e3Jlc2V0Wm9vbX1cbiAgICAgICAgICAgIG9uTW91c2VNb3ZlPXtoYW5kbGVUaW1lbGluZU1vdXNlTW92ZX1cbiAgICAgICAgICAgIG9uTW91c2VMZWF2ZT17aGFuZGxlVGltZWxpbmVNb3VzZUxlYXZlfVxuICAgICAgICAgID5cbiAgICAgICAgICAgIDxUaW1lbGluZVxuICAgICAgICAgICAgICBzcGFucz17dHJhY2Uuc3BhbnN9XG4gICAgICAgICAgICAgIHZpZXdTdGFydD17dmlld3BvcnQuc3RhcnR9XG4gICAgICAgICAgICAgIHZpZXdFbmQ9e3ZpZXdwb3J0LmVuZH1cbiAgICAgICAgICAgICAgbWFya2Vycz17dGltZU1hcmtlcnN9XG4gICAgICAgICAgICAgIHNlbGVjdGVkSWQ9e2FjdGl2ZVNwYW5JZH1cbiAgICAgICAgICAgICAgc2VhcmNoUmVzdWx0PXtzZWFyY2hSZXN1bHR9XG4gICAgICAgICAgICAgIG9uU2VsZWN0PXtoYW5kbGVTZWxlY3RTcGFufVxuICAgICAgICAgICAgICBob3ZlckZyYWN0aW9uPXtob3ZlckZyYWN0aW9ufVxuICAgICAgICAgICAgICBhbHRIZWxkPXthbHRIZWxkfVxuICAgICAgICAgICAgLz5cbiAgICAgICAgICA8L2Rpdj5cbiAgICAgICAgPC9TcGxpdFBhbmU+XG4gICAgICAgIDxkaXYgY2xhc3NOYW1lPVwiYWJzb2x1dGUgcmlnaHQtMyBib3R0b20tMyB6LVs1XSBmbGV4IGl0ZW1zLWNlbnRlciBib3JkZXIgYm9yZGVyLWdyYXktYWxwaGEtNDAwIHJvdW5kZWQtbWQgYmctYmFja2dyb3VuZC0xMDAgc2hhZG93LXNtIG92ZXJmbG93LWhpZGRlbiBkaXZpZGUteCBkaXZpZGUtZ3JheS1hbHBoYS00MDBcIj5cbiAgICAgICAgICA8SWNvbkJ1dHRvblxuICAgICAgICAgICAgdmFyaWFudD1cIm11dGVkXCJcbiAgICAgICAgICAgIHNpemU9XCJzbWFsbFwiXG4gICAgICAgICAgICBvbkNsaWNrPXt6b29tT3V0fVxuICAgICAgICAgICAgYXJpYS1sYWJlbD1cIlpvb20gb3V0XCJcbiAgICAgICAgICA+XG4gICAgICAgICAgICA8Wm9vbU91dCBjbGFzc05hbWU9XCJ3LTQgaC00XCIgLz5cbiAgICAgICAgICA8L0ljb25CdXR0b24+XG4gICAgICAgICAgPEljb25CdXR0b25cbiAgICAgICAgICAgIHZhcmlhbnQ9XCJtdXRlZFwiXG4gICAgICAgICAgICBzaXplPVwic21hbGxcIlxuICAgICAgICAgICAgb25DbGljaz17cmVzZXRab29tfVxuICAgICAgICAgICAgYXJpYS1sYWJlbD1cIlJlc2V0IHpvb21cIlxuICAgICAgICAgID5cbiAgICAgICAgICAgIDxSb3RhdGVDY3cgY2xhc3NOYW1lPVwidy0zLjUgaC0zLjVcIiAvPlxuICAgICAgICAgIDwvSWNvbkJ1dHRvbj5cbiAgICAgICAgICA8SWNvbkJ1dHRvblxuICAgICAgICAgICAgdmFyaWFudD1cIm11dGVkXCJcbiAgICAgICAgICAgIHNpemU9XCJzbWFsbFwiXG4gICAgICAgICAgICBvbkNsaWNrPXt6b29tSW59XG4gICAgICAgICAgICBhcmlhLWxhYmVsPVwiWm9vbSBpblwiXG4gICAgICAgICAgPlxuICAgICAgICAgICAgPFpvb21JbiBjbGFzc05hbWU9XCJ3LTQgaC00XCIgLz5cbiAgICAgICAgICA8L0ljb25CdXR0b24+XG4gICAgICAgIDwvZGl2PlxuICAgICAgPC9kaXY+XG5cbiAgICAgIHsvKiBEZXRhaWwgcGFuZWwgKi99XG4gICAgICB7YWN0aXZlU3BhbiAmJiBzaWRlYmFyID8gKFxuICAgICAgICA8YXNpZGUgY2xhc3NOYW1lPVwiZmxleCBmbGV4LWNvbCBoLWZ1bGwgbWF4LWgtZnVsbCBiZy1iYWNrZ3JvdW5kLTEwMCBib3JkZXItbCBib3JkZXItZ3JheS1hbHBoYS00MDAgb3ZlcmZsb3ctYXV0b1wiPlxuICAgICAgICAgIHsvKiBQYW5lbCBoZWFkZXIgKi99XG4gICAgICAgICAgPGRpdiBjbGFzc05hbWU9XCJmbGV4IGl0ZW1zLWNlbnRlciBqdXN0aWZ5LWJldHdlZW4gZ2FwLTIgc2hyaW5rLTAgcHgtNCBwdC0zIHBiLTNcIj5cbiAgICAgICAgICAgIDxzcGFuIGNsYXNzTmFtZT1cInRleHQtbGFiZWwtMTQgZm9udC1tZWRpdW0gdGV4dC1ncmF5LTEwMDAgdHJ1bmNhdGUgYmxvY2tcIj5cbiAgICAgICAgICAgICAge3NlbGVjdGVkU3Bhbk5hbWV9XG4gICAgICAgICAgICA8L3NwYW4+XG4gICAgICAgICAgICA8ZGl2IGNsYXNzTmFtZT1cImZsZXggaXRlbXMtY2VudGVyIGdhcC0wLjUgc2hyaW5rLTBcIj5cbiAgICAgICAgICAgICAgPEljb25CdXR0b25cbiAgICAgICAgICAgICAgICBhcmlhLWxhYmVsPVwiTmF2aWdhdGUgdG8gcHJldmlvdXMgc3BhblwiXG4gICAgICAgICAgICAgICAgYXJpYS1rZXlzaG9ydGN1dHM9XCJLXCJcbiAgICAgICAgICAgICAgICBvbkNsaWNrPXtoYW5kbGVTZWxlY3RQcmV2U3Bhbn1cbiAgICAgICAgICAgICAgICBkaXNhYmxlZD17IXByZXZTcGFuSWR9XG4gICAgICAgICAgICAgID5cbiAgICAgICAgICAgICAgICA8Q2hldnJvblVwIGNsYXNzTmFtZT1cInctNCBoLTRcIiAvPlxuICAgICAgICAgICAgICA8L0ljb25CdXR0b24+XG4gICAgICAgICAgICAgIDxJY29uQnV0dG9uXG4gICAgICAgICAgICAgICAgYXJpYS1sYWJlbD1cIk5hdmlnYXRlIHRvIG5leHQgc3BhblwiXG4gICAgICAgICAgICAgICAgYXJpYS1rZXlzaG9ydGN1dHM9XCJKXCJcbiAgICAgICAgICAgICAgICBvbkNsaWNrPXtoYW5kbGVTZWxlY3ROZXh0U3Bhbn1cbiAgICAgICAgICAgICAgICBkaXNhYmxlZD17IW5leHRTcGFuSWR9XG4gICAgICAgICAgICAgID5cbiAgICAgICAgICAgICAgICA8Q2hldnJvbkRvd24gY2xhc3NOYW1lPVwidy00IGgtNFwiIC8+XG4gICAgICAgICAgICAgIDwvSWNvbkJ1dHRvbj5cbiAgICAgICAgICAgICAgPGRpdiBhcmlhLWhpZGRlbiBjbGFzc05hbWU9XCJ3LXB4IGgtNCBiZy1ncmF5LWFscGhhLTQwMCBteC0xXCIgLz5cbiAgICAgICAgICAgICAgPEljb25CdXR0b25cbiAgICAgICAgICAgICAgICBhcmlhLWxhYmVsPVwiQ2xvc2Ugc3BhbiBkZXRhaWxzXCJcbiAgICAgICAgICAgICAgICBhcmlhLWtleXNob3J0Y3V0cz1cIkVzY2FwZVwiXG4gICAgICAgICAgICAgICAgb25DbGljaz17Y2xlYXJBY3RpdmVTcGFufVxuICAgICAgICAgICAgICA+XG4gICAgICAgICAgICAgICAgPFggY2xhc3NOYW1lPVwidy00IGgtNFwiIC8+XG4gICAgICAgICAgICAgIDwvSWNvbkJ1dHRvbj5cbiAgICAgICAgICAgIDwvZGl2PlxuICAgICAgICAgIDwvZGl2PlxuICAgICAgICAgIHsvKiBQYW5lbCBib2R5ICovfVxuICAgICAgICAgIDxkaXYgY2xhc3NOYW1lPVwiZmxleC0xIG92ZXJmbG93LXktYXV0b1wiPlxuICAgICAgICAgICAgPEVycm9yQm91bmRhcnk+XG4gICAgICAgICAgICAgIDxFbnRpdHlEZXRhaWxQYW5lbFxuICAgICAgICAgICAgICAgIHJ1bj17c2lkZWJhci5ydW59XG4gICAgICAgICAgICAgICAgb25TdHJlYW1DbGljaz17c2lkZWJhci5vblN0cmVhbUNsaWNrfVxuICAgICAgICAgICAgICAgIG9uUnVuQ2xpY2s9e3NpZGViYXIub25SdW5DbGlja31cbiAgICAgICAgICAgICAgICBzcGFuRGV0YWlsRGF0YT17c2lkZWJhci5zcGFuRGV0YWlsRGF0YX1cbiAgICAgICAgICAgICAgICBzcGFuRGV0YWlsRXJyb3I9e3NpZGViYXIuc3BhbkRldGFpbEVycm9yfVxuICAgICAgICAgICAgICAgIHNwYW5EZXRhaWxMb2FkaW5nPXtzaWRlYmFyLnNwYW5EZXRhaWxMb2FkaW5nfVxuICAgICAgICAgICAgICAgIG9uU3BhblNlbGVjdD17c2lkZWJhci5vblNwYW5TZWxlY3R9XG4gICAgICAgICAgICAgICAgb25XYWtlVXBTbGVlcD17c2lkZWJhci5vbldha2VVcFNsZWVwfVxuICAgICAgICAgICAgICAgIG9uTG9hZEV2ZW50RGF0YT17c2lkZWJhci5vbkxvYWRFdmVudERhdGF9XG4gICAgICAgICAgICAgICAgb25SZXNvbHZlSG9vaz17c2lkZWJhci5vblJlc29sdmVIb29rfVxuICAgICAgICAgICAgICAgIGVuY3J5cHRpb25LZXk9e3NpZGViYXIuZW5jcnlwdGlvbktleX1cbiAgICAgICAgICAgICAgICBvbkRlY3J5cHQ9e3NpZGViYXIub25EZWNyeXB0fVxuICAgICAgICAgICAgICAgIGlzRGVjcnlwdGluZz17c2lkZWJhci5pc0RlY3J5cHRpbmd9XG4gICAgICAgICAgICAgICAgc2VsZWN0ZWRTcGFuPXtzZWxlY3RlZFNwYW59XG4gICAgICAgICAgICAgIC8+XG4gICAgICAgICAgICA8L0Vycm9yQm91bmRhcnk+XG4gICAgICAgICAgPC9kaXY+XG4gICAgICAgIDwvYXNpZGU+XG4gICAgICApIDogYWN0aXZlU3BhbiA/IChcbiAgICAgICAgPERldGFpbFBhbmVsXG4gICAgICAgICAgc3Bhbj17YWN0aXZlU3Bhbn1cbiAgICAgICAgICByb290U3RhcnQ9e3Jvb3Quc3RhcnRUaW1lfVxuICAgICAgICAgIG9uQ2xvc2U9e2NsZWFyQWN0aXZlU3Bhbn1cbiAgICAgICAgLz5cbiAgICAgICkgOiBudWxsfVxuICAgIDwvZGl2PlxuICApO1xufVxuIl19
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
//# sourceMappingURL=types.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../src/components/new-trace-viewer/types.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidHlwZXMuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi9zcmMvY29tcG9uZW50cy9uZXctdHJhY2Utdmlld2VyL3R5cGVzLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiIiLCJzb3VyY2VzQ29udGVudCI6WyIiXX0=
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
//# sourceMappingURL=constants.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"constants.d.ts","sourceRoot":"","sources":["../../../../src/components/new-trace-viewer/util/constants.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY29uc3RhbnRzLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vc3JjL2NvbXBvbmVudHMvbmV3LXRyYWNlLXZpZXdlci91dGlsL2NvbnN0YW50cy50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiIiwic291cmNlc0NvbnRlbnQiOlsiIl19
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import type { Span } from '../trace-viewer/types';
|
|
2
|
+
export interface RootBounds {
|
|
3
|
+
startTime: number;
|
|
4
|
+
endTime: number;
|
|
5
|
+
duration: number;
|
|
6
|
+
}
|
|
7
|
+
export declare function computeRootBounds(spans: Span[]): RootBounds;
|
|
8
|
+
export declare function getSpanDurationMs(span: Span): number;
|
|
9
|
+
export interface TimeMarker {
|
|
10
|
+
position: number;
|
|
11
|
+
label: string;
|
|
12
|
+
value: number;
|
|
13
|
+
}
|
|
14
|
+
export declare function computeTimeMarkers(viewDuration: number, offset: number): TimeMarker[];
|
|
15
|
+
export interface SpanGap {
|
|
16
|
+
gapMs: number;
|
|
17
|
+
leftFrac: number;
|
|
18
|
+
rightFrac: number;
|
|
19
|
+
rowIndex: number;
|
|
20
|
+
}
|
|
21
|
+
export declare function computeSpanGaps(spans: Span[], viewStart: number, viewEnd: number): SpanGap[];
|
|
22
|
+
export declare const RESOURCE_COLORS: Record<string, {
|
|
23
|
+
bg: string;
|
|
24
|
+
border: string;
|
|
25
|
+
errorBg?: string;
|
|
26
|
+
errorBorder?: string;
|
|
27
|
+
}>;
|
|
28
|
+
export declare function getResourceColor(resource: string): {
|
|
29
|
+
bg: string;
|
|
30
|
+
border: string;
|
|
31
|
+
errorBg?: string;
|
|
32
|
+
errorBorder?: string;
|
|
33
|
+
};
|
|
34
|
+
export type SegmentStatus = 'queued' | 'running' | 'failed' | 'retrying' | 'succeeded' | 'waiting' | 'sleeping' | 'received';
|
|
35
|
+
export interface Segment {
|
|
36
|
+
startFraction: number;
|
|
37
|
+
endFraction: number;
|
|
38
|
+
status: SegmentStatus;
|
|
39
|
+
}
|
|
40
|
+
/**
|
|
41
|
+
* Compute event-based segments for a span. Dispatches on `span.resource`
|
|
42
|
+
* to the appropriate resource-type-specific segment builder.
|
|
43
|
+
* Returns an empty array for generic (non-workflow) spans.
|
|
44
|
+
*/
|
|
45
|
+
export declare function computeSpanSegments(span: Span): Segment[];
|
|
46
|
+
//# sourceMappingURL=utils.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"utils.d.ts","sourceRoot":"","sources":["../../../src/components/new-trace-viewer/utils.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,IAAI,EAAa,MAAM,uBAAuB,CAAC;AAO7D,MAAM,WAAW,UAAU;IACzB,SAAS,EAAE,MAAM,CAAC;IAClB,OAAO,EAAE,MAAM,CAAC;IAChB,QAAQ,EAAE,MAAM,CAAC;CAClB;AAED,wBAAgB,iBAAiB,CAAC,KAAK,EAAE,IAAI,EAAE,GAAG,UAAU,CAiB3D;AAED,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,IAAI,GAAG,MAAM,CAKpD;AAMD,MAAM,WAAW,UAAU;IACzB,QAAQ,EAAE,MAAM,CAAC;IACjB,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,MAAM,CAAC;CACf;AAkBD,wBAAgB,kBAAkB,CAChC,YAAY,EAAE,MAAM,EACpB,MAAM,EAAE,MAAM,GACb,UAAU,EAAE,CAqBd;AAMD,MAAM,WAAW,OAAO;IACtB,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,EAAE,MAAM,CAAC;IACjB,SAAS,EAAE,MAAM,CAAC;IAClB,QAAQ,EAAE,MAAM,CAAC;CAClB;AAED,wBAAgB,eAAe,CAC7B,KAAK,EAAE,IAAI,EAAE,EACb,SAAS,EAAE,MAAM,EACjB,OAAO,EAAE,MAAM,GACd,OAAO,EAAE,CAkBX;AAMD,eAAO,MAAM,eAAe,EAAE,MAAM,CAClC,MAAM,EACN;IACE,EAAE,EAAE,MAAM,CAAC;IACX,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB,CAgCF,CAAC;AAEF,wBAAgB,gBAAgB,CAAC,QAAQ,EAAE,MAAM,GAAG;IAClD,EAAE,EAAE,MAAM,CAAC;IACX,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB,CAEA;AAMD,MAAM,MAAM,aAAa,GACrB,QAAQ,GACR,SAAS,GACT,QAAQ,GACR,UAAU,GACV,WAAW,GACX,SAAS,GACT,UAAU,GACV,UAAU,CAAC;AAEf,MAAM,WAAW,OAAO;IACtB,aAAa,EAAE,MAAM,CAAC;IACtB,WAAW,EAAE,MAAM,CAAC;IACpB,MAAM,EAAE,aAAa,CAAC;CACvB;AA6PD;;;;GAIG;AACH,wBAAgB,mBAAmB,CAAC,IAAI,EAAE,IAAI,GAAG,OAAO,EAAE,CAyBzD"}
|