@spotlightjs/overlay 1.3.1 → 1.4.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,28 @@
1
+ /// <reference types="react" />
2
+ type Props = React.HTMLAttributes<SVGSVGElement> & {
3
+ backgroundColors: string[];
4
+ maxValues: number[];
5
+ segmentColors: string[];
6
+ text: React.ReactNode;
7
+ values: number[];
8
+ /**
9
+ * The width of the progress ring bar
10
+ */
11
+ barWidth?: number;
12
+ onHoverActions?: (() => void)[];
13
+ onUnhover?: () => void;
14
+ /**
15
+ * Endcaps on the progress bar
16
+ */
17
+ progressEndcaps?: React.SVGAttributes<SVGCircleElement>['strokeLinecap'];
18
+ size?: number;
19
+ /**
20
+ * The css to apply to the center text. A function may be provided to compute
21
+ * styles based on the state of the progress bar.
22
+ */
23
+ textCss?: string;
24
+ x?: number;
25
+ y?: number;
26
+ };
27
+ declare function RingChart({ values, maxValues, size, barWidth, text, textCss, segmentColors, backgroundColors, progressEndcaps, onHoverActions, onUnhover, ...p }: Props): import("react/jsx-runtime").JSX.Element;
28
+ export default RingChart;
@@ -1,5 +1,6 @@
1
1
  import { EventFrame } from '../../../types';
2
- export default function Frame({ frame, defaultExpand }: {
2
+ export default function Frame({ frame, defaultExpand, platform, }: {
3
3
  frame: EventFrame;
4
4
  defaultExpand: boolean;
5
+ platform?: string;
5
6
  }): import("react/jsx-runtime").JSX.Element;
@@ -0,0 +1,15 @@
1
+ import { MetricScoreProps, MetricWeightsProps } from '../../../../../integrations/sentry/types';
2
+ type PerformanceChartProps = {
3
+ metricScore: MetricScoreProps;
4
+ metricWeights: MetricWeightsProps;
5
+ totalScore?: number;
6
+ size?: number;
7
+ barWidth?: number;
8
+ left?: number;
9
+ top?: number;
10
+ labelWidthPadding?: number;
11
+ labelHeightPadding?: number;
12
+ radiusPadding?: number;
13
+ };
14
+ declare const PerformanceChart: ({ metricScore, metricWeights, totalScore, size, barWidth, left, top, labelWidthPadding, labelHeightPadding, radiusPadding, }: PerformanceChartProps) => import("react/jsx-runtime").JSX.Element;
15
+ export default PerformanceChart;
@@ -0,0 +1,2 @@
1
+ declare const WebVitalsDetail: () => import("react/jsx-runtime").JSX.Element;
2
+ export default WebVitalsDetail;
@@ -0,0 +1,4 @@
1
+ declare const WebVitals: ({ showAll }: {
2
+ showAll: boolean;
3
+ }) => import("react/jsx-runtime").JSX.Element;
4
+ export default WebVitals;
@@ -47,3 +47,41 @@ export declare const QUERY_SUMMARY_HEADERS: ({
47
47
  sortKey: string;
48
48
  primary?: undefined;
49
49
  })[];
50
+ export declare const WEB_VITALS_SORT_KEYS: {
51
+ pages: string;
52
+ lcp: string;
53
+ fcp: string;
54
+ fid: string;
55
+ cls: string;
56
+ ttfb: string;
57
+ score: string;
58
+ };
59
+ export declare const WEB_VITALS_HEADERS: ({
60
+ id: string;
61
+ title: string;
62
+ sortKey: string;
63
+ primary: boolean;
64
+ } | {
65
+ id: string;
66
+ title: string;
67
+ sortKey: string;
68
+ primary?: undefined;
69
+ })[];
70
+ export type WebVitals = 'lcp' | 'fcp' | 'cls' | 'ttfb' | 'fid';
71
+ export declare const PERFORMANCE_SCORE_PROFILES: {
72
+ profiles: {
73
+ name: string;
74
+ scoreComponents: {
75
+ measurement: string;
76
+ weight: number;
77
+ p10: number;
78
+ p50: number;
79
+ optional: boolean;
80
+ }[];
81
+ condition: {
82
+ op: string;
83
+ name: string;
84
+ value: string;
85
+ };
86
+ }[];
87
+ };
@@ -0,0 +1,180 @@
1
+ import { DOMAttributes, MouseEvent, RefObject } from 'react';
2
+ type CallbackArgs = {
3
+ height: number;
4
+ left: number;
5
+ top: number;
6
+ width: number;
7
+ };
8
+ type Opts<T extends Element> = {
9
+ elem: RefObject<T>;
10
+ onPositionChange: (args: undefined | CallbackArgs) => void;
11
+ } & DOMAttributes<T>;
12
+ declare function useMouseTracking<T extends Element>({ elem, onPositionChange, onMouseEnter, onMouseMove, onMouseLeave, ...rest }: Opts<T>): {
13
+ onMouseEnter: (e: MouseEvent<T>) => void;
14
+ onMouseMove: (e: MouseEvent<T>) => void;
15
+ onMouseLeave: (e: MouseEvent<T>) => void;
16
+ children?: import("react").ReactNode;
17
+ dangerouslySetInnerHTML?: {
18
+ __html: string | TrustedHTML;
19
+ } | undefined;
20
+ onCopy?: import("react").ClipboardEventHandler<T> | undefined;
21
+ onCopyCapture?: import("react").ClipboardEventHandler<T> | undefined;
22
+ onCut?: import("react").ClipboardEventHandler<T> | undefined;
23
+ onCutCapture?: import("react").ClipboardEventHandler<T> | undefined;
24
+ onPaste?: import("react").ClipboardEventHandler<T> | undefined;
25
+ onPasteCapture?: import("react").ClipboardEventHandler<T> | undefined;
26
+ onCompositionEnd?: import("react").CompositionEventHandler<T> | undefined;
27
+ onCompositionEndCapture?: import("react").CompositionEventHandler<T> | undefined;
28
+ onCompositionStart?: import("react").CompositionEventHandler<T> | undefined;
29
+ onCompositionStartCapture?: import("react").CompositionEventHandler<T> | undefined;
30
+ onCompositionUpdate?: import("react").CompositionEventHandler<T> | undefined;
31
+ onCompositionUpdateCapture?: import("react").CompositionEventHandler<T> | undefined;
32
+ onFocus?: import("react").FocusEventHandler<T> | undefined;
33
+ onFocusCapture?: import("react").FocusEventHandler<T> | undefined;
34
+ onBlur?: import("react").FocusEventHandler<T> | undefined;
35
+ onBlurCapture?: import("react").FocusEventHandler<T> | undefined;
36
+ onChange?: import("react").FormEventHandler<T> | undefined;
37
+ onChangeCapture?: import("react").FormEventHandler<T> | undefined;
38
+ onBeforeInput?: import("react").FormEventHandler<T> | undefined;
39
+ onBeforeInputCapture?: import("react").FormEventHandler<T> | undefined;
40
+ onInput?: import("react").FormEventHandler<T> | undefined;
41
+ onInputCapture?: import("react").FormEventHandler<T> | undefined;
42
+ onReset?: import("react").FormEventHandler<T> | undefined;
43
+ onResetCapture?: import("react").FormEventHandler<T> | undefined;
44
+ onSubmit?: import("react").FormEventHandler<T> | undefined;
45
+ onSubmitCapture?: import("react").FormEventHandler<T> | undefined;
46
+ onInvalid?: import("react").FormEventHandler<T> | undefined;
47
+ onInvalidCapture?: import("react").FormEventHandler<T> | undefined;
48
+ onLoad?: import("react").ReactEventHandler<T> | undefined;
49
+ onLoadCapture?: import("react").ReactEventHandler<T> | undefined;
50
+ onError?: import("react").ReactEventHandler<T> | undefined;
51
+ onErrorCapture?: import("react").ReactEventHandler<T> | undefined;
52
+ onKeyDown?: import("react").KeyboardEventHandler<T> | undefined;
53
+ onKeyDownCapture?: import("react").KeyboardEventHandler<T> | undefined;
54
+ onKeyPress?: import("react").KeyboardEventHandler<T> | undefined;
55
+ onKeyPressCapture?: import("react").KeyboardEventHandler<T> | undefined;
56
+ onKeyUp?: import("react").KeyboardEventHandler<T> | undefined;
57
+ onKeyUpCapture?: import("react").KeyboardEventHandler<T> | undefined;
58
+ onAbort?: import("react").ReactEventHandler<T> | undefined;
59
+ onAbortCapture?: import("react").ReactEventHandler<T> | undefined;
60
+ onCanPlay?: import("react").ReactEventHandler<T> | undefined;
61
+ onCanPlayCapture?: import("react").ReactEventHandler<T> | undefined;
62
+ onCanPlayThrough?: import("react").ReactEventHandler<T> | undefined;
63
+ onCanPlayThroughCapture?: import("react").ReactEventHandler<T> | undefined;
64
+ onDurationChange?: import("react").ReactEventHandler<T> | undefined;
65
+ onDurationChangeCapture?: import("react").ReactEventHandler<T> | undefined;
66
+ onEmptied?: import("react").ReactEventHandler<T> | undefined;
67
+ onEmptiedCapture?: import("react").ReactEventHandler<T> | undefined;
68
+ onEncrypted?: import("react").ReactEventHandler<T> | undefined;
69
+ onEncryptedCapture?: import("react").ReactEventHandler<T> | undefined;
70
+ onEnded?: import("react").ReactEventHandler<T> | undefined;
71
+ onEndedCapture?: import("react").ReactEventHandler<T> | undefined;
72
+ onLoadedData?: import("react").ReactEventHandler<T> | undefined;
73
+ onLoadedDataCapture?: import("react").ReactEventHandler<T> | undefined;
74
+ onLoadedMetadata?: import("react").ReactEventHandler<T> | undefined;
75
+ onLoadedMetadataCapture?: import("react").ReactEventHandler<T> | undefined;
76
+ onLoadStart?: import("react").ReactEventHandler<T> | undefined;
77
+ onLoadStartCapture?: import("react").ReactEventHandler<T> | undefined;
78
+ onPause?: import("react").ReactEventHandler<T> | undefined;
79
+ onPauseCapture?: import("react").ReactEventHandler<T> | undefined;
80
+ onPlay?: import("react").ReactEventHandler<T> | undefined;
81
+ onPlayCapture?: import("react").ReactEventHandler<T> | undefined;
82
+ onPlaying?: import("react").ReactEventHandler<T> | undefined;
83
+ onPlayingCapture?: import("react").ReactEventHandler<T> | undefined;
84
+ onProgress?: import("react").ReactEventHandler<T> | undefined;
85
+ onProgressCapture?: import("react").ReactEventHandler<T> | undefined;
86
+ onRateChange?: import("react").ReactEventHandler<T> | undefined;
87
+ onRateChangeCapture?: import("react").ReactEventHandler<T> | undefined;
88
+ onResize?: import("react").ReactEventHandler<T> | undefined;
89
+ onResizeCapture?: import("react").ReactEventHandler<T> | undefined;
90
+ onSeeked?: import("react").ReactEventHandler<T> | undefined;
91
+ onSeekedCapture?: import("react").ReactEventHandler<T> | undefined;
92
+ onSeeking?: import("react").ReactEventHandler<T> | undefined;
93
+ onSeekingCapture?: import("react").ReactEventHandler<T> | undefined;
94
+ onStalled?: import("react").ReactEventHandler<T> | undefined;
95
+ onStalledCapture?: import("react").ReactEventHandler<T> | undefined;
96
+ onSuspend?: import("react").ReactEventHandler<T> | undefined;
97
+ onSuspendCapture?: import("react").ReactEventHandler<T> | undefined;
98
+ onTimeUpdate?: import("react").ReactEventHandler<T> | undefined;
99
+ onTimeUpdateCapture?: import("react").ReactEventHandler<T> | undefined;
100
+ onVolumeChange?: import("react").ReactEventHandler<T> | undefined;
101
+ onVolumeChangeCapture?: import("react").ReactEventHandler<T> | undefined;
102
+ onWaiting?: import("react").ReactEventHandler<T> | undefined;
103
+ onWaitingCapture?: import("react").ReactEventHandler<T> | undefined;
104
+ onAuxClick?: import("react").MouseEventHandler<T> | undefined;
105
+ onAuxClickCapture?: import("react").MouseEventHandler<T> | undefined;
106
+ onClick?: import("react").MouseEventHandler<T> | undefined;
107
+ onClickCapture?: import("react").MouseEventHandler<T> | undefined;
108
+ onContextMenu?: import("react").MouseEventHandler<T> | undefined;
109
+ onContextMenuCapture?: import("react").MouseEventHandler<T> | undefined;
110
+ onDoubleClick?: import("react").MouseEventHandler<T> | undefined;
111
+ onDoubleClickCapture?: import("react").MouseEventHandler<T> | undefined;
112
+ onDrag?: import("react").DragEventHandler<T> | undefined;
113
+ onDragCapture?: import("react").DragEventHandler<T> | undefined;
114
+ onDragEnd?: import("react").DragEventHandler<T> | undefined;
115
+ onDragEndCapture?: import("react").DragEventHandler<T> | undefined;
116
+ onDragEnter?: import("react").DragEventHandler<T> | undefined;
117
+ onDragEnterCapture?: import("react").DragEventHandler<T> | undefined;
118
+ onDragExit?: import("react").DragEventHandler<T> | undefined;
119
+ onDragExitCapture?: import("react").DragEventHandler<T> | undefined;
120
+ onDragLeave?: import("react").DragEventHandler<T> | undefined;
121
+ onDragLeaveCapture?: import("react").DragEventHandler<T> | undefined;
122
+ onDragOver?: import("react").DragEventHandler<T> | undefined;
123
+ onDragOverCapture?: import("react").DragEventHandler<T> | undefined;
124
+ onDragStart?: import("react").DragEventHandler<T> | undefined;
125
+ onDragStartCapture?: import("react").DragEventHandler<T> | undefined;
126
+ onDrop?: import("react").DragEventHandler<T> | undefined;
127
+ onDropCapture?: import("react").DragEventHandler<T> | undefined;
128
+ onMouseDown?: import("react").MouseEventHandler<T> | undefined;
129
+ onMouseDownCapture?: import("react").MouseEventHandler<T> | undefined;
130
+ onMouseMoveCapture?: import("react").MouseEventHandler<T> | undefined;
131
+ onMouseOut?: import("react").MouseEventHandler<T> | undefined;
132
+ onMouseOutCapture?: import("react").MouseEventHandler<T> | undefined;
133
+ onMouseOver?: import("react").MouseEventHandler<T> | undefined;
134
+ onMouseOverCapture?: import("react").MouseEventHandler<T> | undefined;
135
+ onMouseUp?: import("react").MouseEventHandler<T> | undefined;
136
+ onMouseUpCapture?: import("react").MouseEventHandler<T> | undefined;
137
+ onSelect?: import("react").ReactEventHandler<T> | undefined;
138
+ onSelectCapture?: import("react").ReactEventHandler<T> | undefined;
139
+ onTouchCancel?: import("react").TouchEventHandler<T> | undefined;
140
+ onTouchCancelCapture?: import("react").TouchEventHandler<T> | undefined;
141
+ onTouchEnd?: import("react").TouchEventHandler<T> | undefined;
142
+ onTouchEndCapture?: import("react").TouchEventHandler<T> | undefined;
143
+ onTouchMove?: import("react").TouchEventHandler<T> | undefined;
144
+ onTouchMoveCapture?: import("react").TouchEventHandler<T> | undefined;
145
+ onTouchStart?: import("react").TouchEventHandler<T> | undefined;
146
+ onTouchStartCapture?: import("react").TouchEventHandler<T> | undefined;
147
+ onPointerDown?: import("react").PointerEventHandler<T> | undefined;
148
+ onPointerDownCapture?: import("react").PointerEventHandler<T> | undefined;
149
+ onPointerMove?: import("react").PointerEventHandler<T> | undefined;
150
+ onPointerMoveCapture?: import("react").PointerEventHandler<T> | undefined;
151
+ onPointerUp?: import("react").PointerEventHandler<T> | undefined;
152
+ onPointerUpCapture?: import("react").PointerEventHandler<T> | undefined;
153
+ onPointerCancel?: import("react").PointerEventHandler<T> | undefined;
154
+ onPointerCancelCapture?: import("react").PointerEventHandler<T> | undefined;
155
+ onPointerEnter?: import("react").PointerEventHandler<T> | undefined;
156
+ onPointerEnterCapture?: import("react").PointerEventHandler<T> | undefined;
157
+ onPointerLeave?: import("react").PointerEventHandler<T> | undefined;
158
+ onPointerLeaveCapture?: import("react").PointerEventHandler<T> | undefined;
159
+ onPointerOver?: import("react").PointerEventHandler<T> | undefined;
160
+ onPointerOverCapture?: import("react").PointerEventHandler<T> | undefined;
161
+ onPointerOut?: import("react").PointerEventHandler<T> | undefined;
162
+ onPointerOutCapture?: import("react").PointerEventHandler<T> | undefined;
163
+ onGotPointerCapture?: import("react").PointerEventHandler<T> | undefined;
164
+ onGotPointerCaptureCapture?: import("react").PointerEventHandler<T> | undefined;
165
+ onLostPointerCapture?: import("react").PointerEventHandler<T> | undefined;
166
+ onLostPointerCaptureCapture?: import("react").PointerEventHandler<T> | undefined;
167
+ onScroll?: import("react").UIEventHandler<T> | undefined;
168
+ onScrollCapture?: import("react").UIEventHandler<T> | undefined;
169
+ onWheel?: import("react").WheelEventHandler<T> | undefined;
170
+ onWheelCapture?: import("react").WheelEventHandler<T> | undefined;
171
+ onAnimationStart?: import("react").AnimationEventHandler<T> | undefined;
172
+ onAnimationStartCapture?: import("react").AnimationEventHandler<T> | undefined;
173
+ onAnimationEnd?: import("react").AnimationEventHandler<T> | undefined;
174
+ onAnimationEndCapture?: import("react").AnimationEventHandler<T> | undefined;
175
+ onAnimationIteration?: import("react").AnimationEventHandler<T> | undefined;
176
+ onAnimationIterationCapture?: import("react").AnimationEventHandler<T> | undefined;
177
+ onTransitionEnd?: import("react").TransitionEventHandler<T> | undefined;
178
+ onTransitionEndCapture?: import("react").TransitionEventHandler<T> | undefined;
179
+ };
180
+ export default useMouseTracking;
@@ -17,6 +17,7 @@ export declare class Spotlight implements Integration {
17
17
  type FetchImpl = typeof fetch;
18
18
  /**
19
19
  * We want to get an unpatched fetch implementation to avoid capturing our own calls.
20
+ * TODO: We might need to expose this as a utitly function so people can make requests without the SDK picking it put
20
21
  */
21
22
  export declare function getNativeFetchImplementation(): FetchImpl;
22
23
  export {};
@@ -1,8 +1,9 @@
1
+ import { Measurements } from '@sentry/types';
1
2
  export type FrameVars = {
2
3
  [key: string]: string;
3
4
  };
4
5
  export type EventFrame = {
5
- filename: string;
6
+ filename?: string;
6
7
  abs_path?: string;
7
8
  function?: string;
8
9
  module?: string;
@@ -54,6 +55,7 @@ type CommonEventAttrs = {
54
55
  [key: string]: string | number;
55
56
  };
56
57
  sdk?: Sdk;
58
+ measurements?: Measurements;
57
59
  };
58
60
  export type Context = {
59
61
  [key: string]: string | number;
@@ -117,4 +119,69 @@ export type Sdk = {
117
119
  version: string;
118
120
  lastSeen: number;
119
121
  };
122
+ export type SentryEventWithPerformanceData = Omit<SentryEvent, 'measurements'> & {
123
+ measurements: Record<string, {
124
+ value: number;
125
+ unit: string;
126
+ }> & {
127
+ 'score.total': {
128
+ value: number;
129
+ unit: string;
130
+ };
131
+ 'score.fcp': {
132
+ value: number;
133
+ unit: string;
134
+ };
135
+ 'score.lcp': {
136
+ value: number;
137
+ unit: string;
138
+ };
139
+ 'score.fid': {
140
+ value: number;
141
+ unit: string;
142
+ };
143
+ 'score.cls': {
144
+ value: number;
145
+ unit: string;
146
+ };
147
+ 'score.ttfb': {
148
+ value: number;
149
+ unit: string;
150
+ };
151
+ 'score.weight.fcp': {
152
+ value: number;
153
+ unit: string;
154
+ };
155
+ 'score.weight.lcp': {
156
+ value: number;
157
+ unit: string;
158
+ };
159
+ 'score.weight.fid': {
160
+ value: number;
161
+ unit: string;
162
+ };
163
+ 'score.weight.cls': {
164
+ value: number;
165
+ unit: string;
166
+ };
167
+ 'score.weight.ttfb': {
168
+ value: number;
169
+ unit: string;
170
+ };
171
+ };
172
+ };
173
+ export type MetricScoreProps = {
174
+ fcpScore: number;
175
+ lcpScore: number;
176
+ clsScore: number;
177
+ fidScore: number;
178
+ ttfbScore: number;
179
+ };
180
+ export type MetricWeightsProps = {
181
+ fcp: number;
182
+ lcp: number;
183
+ cls: number;
184
+ fid: number;
185
+ ttfb: number;
186
+ };
120
187
  export {};
@@ -17,5 +17,5 @@ export declare const DURATION_LABELS: {
17
17
  };
18
18
  export declare function getDuration(start: string | number, end: string | number): number;
19
19
  export declare function getSpanDurationClassName(duration: number): "text-red-400" | "text-orange-400" | "text-yellow-400" | undefined;
20
- export declare function getFormattedNumber(num: number): string;
20
+ export declare function getFormattedNumber(num: number, decimalPlaces?: number): string;
21
21
  export declare function getFormattedDuration(duration: number): string;
@@ -1,4 +1,4 @@
1
1
  /**
2
2
  * Normalizes SDK name to a platform. Can be as specific or unspecific as we support different platforms and SDKs.
3
3
  */
4
- export declare function sdkToPlatform(name: string): "javascript.astro" | "javascript" | "python" | "php" | "ruby" | "dotnet" | "unknown";
4
+ export declare function sdkToPlatform(name: string): "javascript.astro" | "javascript" | "java" | "python" | "php" | "ruby" | "dotnet" | "unknown";
@@ -0,0 +1,39 @@
1
+ import { SentryEvent } from '../../../integrations/sentry/types';
2
+ import { WebVitals } from '../constants';
3
+ export declare function calculateCdfSigma(p10: number, p50: number): number;
4
+ export declare function calculateCdfScore(value: number, p10: number, p50: number): number;
5
+ interface ScoreComponent {
6
+ measurement: string;
7
+ weight: number;
8
+ p10: number;
9
+ p50: number;
10
+ optional?: boolean;
11
+ }
12
+ interface Profile {
13
+ name: string;
14
+ scoreComponents: ScoreComponent[];
15
+ condition?: {
16
+ op: string;
17
+ name: string;
18
+ value: string | number;
19
+ };
20
+ }
21
+ interface PerformanceScoreConfig {
22
+ profiles: Profile[];
23
+ }
24
+ export declare function normalizePerformanceScore(event: SentryEvent, performanceScore: PerformanceScoreConfig | undefined): void;
25
+ export declare function calculateLabelCoordinates(size: number, x: number, y: number, barWidth: number, metricWeights: {
26
+ [key in WebVitals]: number;
27
+ }, labelWidthPadding: number, labelHeightPadding: number, radiusPadding: number): {
28
+ lcpX: number;
29
+ lcpY: number;
30
+ fcpX: number;
31
+ fcpY: number;
32
+ fidX: number;
33
+ fidY: number;
34
+ clsX: number;
35
+ clsY: number;
36
+ ttfbX: number;
37
+ ttfbY: number;
38
+ };
39
+ export {};
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@spotlightjs/overlay",
3
3
  "description": "The overlay of Spotlight to add debug interface to your web app.",
4
- "version": "1.3.1",
4
+ "version": "1.4.1",
5
5
  "license": "Apache-2.0",
6
6
  "type": "module",
7
7
  "files": [
@@ -29,7 +29,7 @@
29
29
  "eslint-plugin-react-hooks": "^4.6.0",
30
30
  "eslint-plugin-react-refresh": "^0.4.3",
31
31
  "typescript": "^5.0.2",
32
- "vite": "^4.5.1",
32
+ "vite": "^4.5.2",
33
33
  "vite-plugin-dts": "^3.5.2",
34
34
  "vite-plugin-svgr": "^3.2.0",
35
35
  "vitest": "^0.34.6",