Merge branch 'main' into feat-user-auth-fief

This commit is contained in:
Koper
2023-08-17 22:20:16 +07:00
26 changed files with 265 additions and 174 deletions

1
server/.gitignore vendored
View File

@@ -178,3 +178,4 @@ audio_*.wav
# ignore local database # ignore local database
reflector.sqlite3 reflector.sqlite3
data/

View File

@@ -1,6 +1,5 @@
from reflector.processors.base import Processor from reflector.processors.base import Processor
import av import av
import wave
from pathlib import Path from pathlib import Path
@@ -17,19 +16,24 @@ class AudioFileWriterProcessor(Processor):
if isinstance(path, str): if isinstance(path, str):
path = Path(path) path = Path(path)
self.path = path self.path = path
self.fd = None self.out_container = None
self.out_stream = None
async def _push(self, data: av.AudioFrame): async def _push(self, data: av.AudioFrame):
if not self.fd: if not self.out_container:
self.path.parent.mkdir(parents=True, exist_ok=True) self.path.parent.mkdir(parents=True, exist_ok=True)
self.fd = wave.open(self.path.as_posix(), "wb") self.out_container = av.open(self.path.as_posix(), "w", format="wav")
self.fd.setnchannels(len(data.layout.channels)) self.out_stream = self.out_container.add_stream(
self.fd.setsampwidth(data.format.bytes) "pcm_s16le", rate=data.sample_rate
self.fd.setframerate(data.sample_rate) )
self.fd.writeframes(data.to_ndarray().tobytes()) for packet in self.out_stream.encode(data):
self.out_container.mux(packet)
await self.emit(data) await self.emit(data)
async def _flush(self): async def _flush(self):
if self.fd: if self.out_container:
self.fd.close() for packet in self.out_stream.encode():
self.fd = None self.out_container.mux(packet)
self.out_container.close()
self.out_container = None
self.out_stream = None

View File

@@ -3,7 +3,6 @@ from reflector.processors.types import AudioFile
from time import monotonic_ns from time import monotonic_ns
from uuid import uuid4 from uuid import uuid4
import io import io
import wave
import av import av
@@ -28,12 +27,16 @@ class AudioMergeProcessor(Processor):
# create audio file # create audio file
uu = uuid4().hex uu = uuid4().hex
fd = io.BytesIO() fd = io.BytesIO()
with wave.open(fd, "wb") as wf:
wf.setnchannels(channels) out_container = av.open(fd, "w", format="wav")
wf.setsampwidth(sample_width) out_stream = out_container.add_stream("pcm_s16le", rate=sample_rate)
wf.setframerate(sample_rate) for frame in data:
for frame in data: for packet in out_stream.encode(frame):
wf.writeframes(frame.to_ndarray().tobytes()) out_container.mux(packet)
for packet in out_stream.encode(None):
out_container.mux(packet)
out_container.close()
fd.seek(0)
# emit audio file # emit audio file
audiofile = AudioFile( audiofile = AudioFile(
@@ -44,4 +47,5 @@ class AudioMergeProcessor(Processor):
sample_width=sample_width, sample_width=sample_width,
timestamp=data[0].pts * data[0].time_base, timestamp=data[0].pts * data[0].time_base,
) )
await self.emit(audiofile) await self.emit(audiofile)

View File

@@ -111,7 +111,9 @@ class Transcript(BaseModel):
out.close() out.close()
# move temporary file to final location # move temporary file to final location
Path(tmp.name).rename(fn) import shutil
shutil.move(tmp.name, fn.as_posix())
def unlink(self): def unlink(self):
self.data_path.unlink(missing_ok=True) self.data_path.unlink(missing_ok=True)

View File

@@ -1,11 +1,10 @@
import "./styles/globals.scss"; import "./styles/globals.scss";
import { Roboto } from "next/font/google"; import { Roboto } from "next/font/google";
import { Metadata } from "next";
import Head from "next/head";
const roboto = Roboto({ subsets: ["latin"], weight: "400" }); const roboto = Roboto({ subsets: ["latin"], weight: "400" });
export const metadata = { export const metadata: Metadata = {
title: { title: {
template: "%s Reflector", template: "%s Reflector",
default: "Reflector - AI-Powered Meeting Transcriptions by Monadical", default: "Reflector - AI-Powered Meeting Transcriptions by Monadical",
@@ -52,9 +51,6 @@ export const metadata = {
export default function RootLayout({ children }) { export default function RootLayout({ children }) {
return ( return (
<html lang="en"> <html lang="en">
<Head>
<title>Test</title>
</Head>
<body className={roboto.className + " flex flex-col min-h-screen"}> <body className={roboto.className + " flex flex-col min-h-screen"}>
{children} {children}
</body> </body>

View File

@@ -1,15 +1,15 @@
export function getRandomNumber(min, max) { export function getRandomNumber(min: number, max: number): number {
return Math.floor(Math.random() * (max - min + 1)) + min; return Math.floor(Math.random() * (max - min + 1)) + min;
} }
export function SeededRand(seed) { export function SeededRand(seed: number): number {
seed ^= seed << 13; seed ^= seed << 13;
seed ^= seed >> 17; seed ^= seed >> 17;
seed ^= seed << 5; seed ^= seed << 5;
return seed / 2 ** 32; return seed / 2 ** 32;
} }
export function Mulberry32(seed) { export function Mulberry32(seed: number) {
return function () { return function () {
var t = (seed += 0x6d2b79f5); var t = (seed += 0x6d2b79f5);
t = Math.imul(t ^ (t >>> 15), t | 1); t = Math.imul(t ^ (t >>> 15), t | 1);

View File

@@ -1,4 +1,4 @@
export const formatTime = (seconds) => { export const formatTime = (seconds: number): string => {
let hours = Math.floor(seconds / 3600); let hours = Math.floor(seconds / 3600);
let minutes = Math.floor((seconds % 3600) / 60); let minutes = Math.floor((seconds % 3600) / 60);
let secs = Math.floor(seconds % 60); let secs = Math.floor(seconds % 60);

View File

@@ -1,4 +1,4 @@
import { redirect } from "next/navigation"; import { redirect } from "next/navigation";
export default async function Index({ params }) { export default async function Index() {
redirect("/transcripts/new"); redirect("/transcripts/new");
} }

View File

@@ -3,17 +3,29 @@ import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
import { import {
faChevronRight, faChevronRight,
faChevronDown, faChevronDown,
faLinkSlash,
} from "@fortawesome/free-solid-svg-icons"; } from "@fortawesome/free-solid-svg-icons";
import { formatTime } from "../lib/time";
import ScrollToBottom from "./scrollToBottom";
import DisconnectedIndicator from "./disconnectedIndicator";
import LiveTrancription from "./liveTranscription";
import FinalSummary from "./finalSummary";
import { Topic, FinalSummary as FinalSummaryType } from "./webSocketTypes";
type DashboardProps = {
transcriptionText: string;
finalSummary: FinalSummaryType;
topics: Topic[];
disconnected: boolean;
};
export function Dashboard({ export function Dashboard({
transcriptionText, transcriptionText,
finalSummary, finalSummary,
topics, topics,
disconnected, disconnected,
}) { }: DashboardProps) {
const [openIndex, setOpenIndex] = useState(null); const [openIndex, setOpenIndex] = useState<number | null>(null);
const [autoscrollEnabled, setAutoscrollEnabled] = useState(true); const [autoscrollEnabled, setAutoscrollEnabled] = useState<boolean>(true);
useEffect(() => { useEffect(() => {
if (autoscrollEnabled) scrollToBottom(); if (autoscrollEnabled) scrollToBottom();
@@ -21,7 +33,10 @@ export function Dashboard({
const scrollToBottom = () => { const scrollToBottom = () => {
const topicsDiv = document.getElementById("topics-div"); const topicsDiv = document.getElementById("topics-div");
topicsDiv.scrollTop = topicsDiv.scrollHeight;
if (!topicsDiv)
console.error("Could not find topics div to scroll to bottom");
else topicsDiv.scrollTop = topicsDiv.scrollHeight;
}; };
const handleScroll = (e) => { const handleScroll = (e) => {
@@ -34,18 +49,6 @@ export function Dashboard({
} }
}; };
const formatTime = (seconds) => {
let hours = Math.floor(seconds / 3600);
let minutes = Math.floor((seconds % 3600) / 60);
let secs = Math.floor(seconds % 60);
let timeString = `${hours > 0 ? hours + ":" : ""}${minutes
.toString()
.padStart(2, "0")}:${secs.toString().padStart(2, "0")}`;
return timeString;
};
return ( return (
<> <>
<div className="relative h-[60svh] w-3/4 flex flex-col"> <div className="relative h-[60svh] w-3/4 flex flex-col">
@@ -57,16 +60,12 @@ export function Dashboard({
<div className="w-3/4 font-bold">Topic</div> <div className="w-3/4 font-bold">Topic</div>
</div> </div>
<div <ScrollToBottom
className={`absolute right-5 w-10 h-10 ${ visible={!autoscrollEnabled}
autoscrollEnabled ? "hidden" : "flex" hasFinalSummary={finalSummary ? true : false}
} ${ handleScrollBottom={scrollToBottom}
finalSummary ? "top-[49%]" : "bottom-1" />
} justify-center items-center text-2xl cursor-pointer opacity-70 hover:opacity-100 transition-opacity duration-200 animate-bounce rounded-xl border-slate-400 bg-[#3c82f638] text-[#3c82f6ed]`}
onClick={scrollToBottom}
>
&#11015;
</div>
<div <div
id="topics-div" id="topics-div"
className="py-2 overflow-y-auto" className="py-2 overflow-y-auto"
@@ -99,26 +98,12 @@ export function Dashboard({
)} )}
</div> </div>
{finalSummary && ( {finalSummary.summary && <FinalSummary text={finalSummary.summary} />}
<div className="min-h-[200px] overflow-y-auto mt-2 p-2 bg-white temp-transcription rounded">
<h2>Final Summary</h2>
<p>{finalSummary.summary}</p>
</div>
)}
</div> </div>
{disconnected && ( {disconnected && <DisconnectedIndicator />}
<div className="absolute top-0 left-0 w-full h-full bg-black opacity-50 flex justify-center items-center">
<div className="text-white text-2xl">
<FontAwesomeIcon icon={faLinkSlash} className="mr-2" />
Disconnected
</div>
</div>
)}
<footer className="h-[7svh] w-full bg-gray-800 text-white text-center py-4 text-2xl"> <LiveTrancription text={transcriptionText} />
&nbsp;{transcriptionText}&nbsp;
</footer>
</> </>
); );
} }

View File

@@ -0,0 +1,13 @@
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
import { faLinkSlash } from "@fortawesome/free-solid-svg-icons";
export default function DisconnectedIndicator() {
return (
<div className="absolute top-0 left-0 w-full h-full bg-black opacity-50 flex justify-center items-center">
<div className="text-white text-2xl">
<FontAwesomeIcon icon={faLinkSlash} className="mr-2" />
Disconnected
</div>
</div>
);
}

View File

@@ -0,0 +1,12 @@
type FinalSummaryProps = {
text: string;
};
export default function FinalSummary(props: FinalSummaryProps) {
return (
<div className="min-h-[200px] overflow-y-auto mt-2 p-2 bg-white temp-transcription rounded">
<h2>Final Summary</h2>
<p>{props.text}</p>
</div>
);
}

View File

@@ -0,0 +1,11 @@
type LiveTranscriptionProps = {
text: string;
};
export default function LiveTrancription(props: LiveTranscriptionProps) {
return (
<div className="h-[7svh] w-full bg-gray-800 text-white text-center py-4 text-2xl">
&nbsp;{props.text}&nbsp;
</div>
);
}

View File

@@ -8,8 +8,8 @@ import { useWebSockets } from "../useWebSockets";
import "../../styles/button.css"; import "../../styles/button.css";
const App = () => { const App = () => {
const [stream, setStream] = useState(null); const [stream, setStream] = useState<MediaStream | null>(null);
const [disconnected, setDisconnected] = useState(false); const [disconnected, setDisconnected] = useState<boolean>(false);
useEffect(() => { useEffect(() => {
if (process.env.NEXT_PUBLIC_ENV === "development") { if (process.env.NEXT_PUBLIC_ENV === "development") {
@@ -46,7 +46,6 @@ const App = () => {
transcriptionText={webSockets.transcriptText} transcriptionText={webSockets.transcriptText}
finalSummary={webSockets.finalSummary} finalSummary={webSockets.finalSummary}
topics={webSockets.topics} topics={webSockets.topics}
stream={stream}
disconnected={disconnected} disconnected={disconnected}
/> />
</div> </div>

View File

@@ -8,7 +8,7 @@ import { faDownload } from "@fortawesome/free-solid-svg-icons";
import Dropdown from "react-dropdown"; import Dropdown from "react-dropdown";
import "react-dropdown/style.css"; import "react-dropdown/style.css";
import CustomRecordPlugin from "./CustomRecordPlugin"; import CustomRecordPlugin from "../lib/CustomRecordPlugin";
import { formatTime } from "../lib/time"; import { formatTime } from "../lib/time";
const AudioInputsDropdown = (props) => { const AudioInputsDropdown = (props) => {

View File

@@ -0,0 +1,23 @@
type ScrollToBottomProps = {
visible: boolean;
hasFinalSummary: boolean;
handleScrollBottom: () => void;
};
export default function ScrollToBottom(props: ScrollToBottomProps) {
return (
<div
className={`absolute right-5 w-10 h-10 ${
props.visible ? "flex" : "hidden"
} ${
props.hasFinalSummary ? "top-[49%]" : "bottom-1"
} justify-center items-center text-2xl cursor-pointer opacity-70 hover:opacity-100 transition-opacity duration-200 animate-bounce rounded-xl border-slate-400 bg-[#3c82f638] text-[#3c82f6ed]`}
onClick={() => {
props.handleScrollBottom();
return false;
}}
>
&#11015;
</div>
);
}

View File

@@ -1,11 +1,19 @@
import { useEffect, useState } from "react"; import { useEffect, useState } from "react";
import { DefaultApi } from "../api/apis/DefaultApi"; import { DefaultApi, V1TranscriptsCreateRequest } from "../api/apis/DefaultApi";
import { Configuration } from "../api/runtime"; import { Configuration } from "../api/runtime";
import { GetTranscript } from "../api";
const useTranscript = () => { type UseTranscript = {
const [response, setResponse] = useState(null); response: GetTranscript | null;
const [loading, setLoading] = useState(false); loading: boolean;
const [error, setError] = useState(null); error: string | null;
createTranscript: () => void;
};
const useTranscript = (): UseTranscript => {
const [response, setResponse] = useState<GetTranscript | null>(null);
const [loading, setLoading] = useState<boolean>(false);
const [error, setError] = useState<string | null>(null);
const apiConfiguration = new Configuration({ const apiConfiguration = new Configuration({
basePath: process.env.NEXT_PUBLIC_API_URL, basePath: process.env.NEXT_PUBLIC_API_URL,
@@ -14,7 +22,7 @@ const useTranscript = () => {
const createTranscript = () => { const createTranscript = () => {
setLoading(true); setLoading(true);
const requestParameters = { const requestParameters: V1TranscriptsCreateRequest = {
createTranscript: { createTranscript: {
name: "Weekly All-Hands", // Hardcoded for now name: "Weekly All-Hands", // Hardcoded for now
}, },

View File

@@ -1,12 +1,16 @@
import { useEffect, useState } from "react"; import { useEffect, useState } from "react";
import Peer from "simple-peer"; import Peer from "simple-peer";
import { DefaultApi } from "../api/apis/DefaultApi"; import {
DefaultApi,
V1TranscriptRecordWebrtcRequest,
} from "../api/apis/DefaultApi";
import { Configuration } from "../api/runtime"; import { Configuration } from "../api/runtime";
const useWebRTC = (stream, transcriptId) => { const useWebRTC = (
const [data, setData] = useState({ stream: MediaStream | null,
peer: null, transcriptId: string | null,
}); ): Peer => {
const [peer, setPeer] = useState<Peer | null>(null);
useEffect(() => { useEffect(() => {
if (!stream || !transcriptId) { if (!stream || !transcriptId) {
@@ -18,11 +22,11 @@ const useWebRTC = (stream, transcriptId) => {
}); });
const api = new DefaultApi(apiConfiguration); const api = new DefaultApi(apiConfiguration);
let peer = new Peer({ initiator: true, stream: stream }); let p: Peer = new Peer({ initiator: true, stream: stream });
peer.on("signal", (data) => { p.on("signal", (data: any) => {
if ("sdp" in data) { if ("sdp" in data) {
const requestParameters = { const requestParameters: V1TranscriptRecordWebrtcRequest = {
transcriptId: transcriptId, transcriptId: transcriptId,
rtcOffer: { rtcOffer: {
sdp: data.sdp, sdp: data.sdp,
@@ -33,7 +37,7 @@ const useWebRTC = (stream, transcriptId) => {
api api
.v1TranscriptRecordWebrtc(requestParameters) .v1TranscriptRecordWebrtc(requestParameters)
.then((answer) => { .then((answer) => {
peer.signal(answer); p.signal(answer);
}) })
.catch((err) => { .catch((err) => {
console.error("WebRTC signaling error:", err); console.error("WebRTC signaling error:", err);
@@ -41,17 +45,17 @@ const useWebRTC = (stream, transcriptId) => {
} }
}); });
peer.on("connect", () => { p.on("connect", () => {
console.log("WebRTC connected"); console.log("WebRTC connected");
setData((prevData) => ({ ...prevData, peer: peer })); setPeer(p);
}); });
return () => { return () => {
peer.destroy(); p.destroy();
}; };
}, [stream, transcriptId]); }, [stream, transcriptId]);
return data; return peer;
}; };
export default useWebRTC; export default useWebRTC;

View File

@@ -1,10 +1,20 @@
import { useEffect, useState } from "react"; import { useEffect, useState } from "react";
import { Topic, FinalSummary, Status } from "./webSocketTypes";
export const useWebSockets = (transcriptId) => { type UseWebSockets = {
const [transcriptText, setTranscriptText] = useState(""); transcriptText: string;
const [topics, setTopics] = useState([]); topics: Topic[];
const [finalSummary, setFinalSummary] = useState(""); finalSummary: FinalSummary;
const [status, setStatus] = useState("disconnected"); status: Status;
};
export const useWebSockets = (transcriptId: string | null): UseWebSockets => {
const [transcriptText, setTranscriptText] = useState<string>("");
const [topics, setTopics] = useState<Topic[]>([]);
const [finalSummary, setFinalSummary] = useState<FinalSummary>({
summary: "",
});
const [status, setStatus] = useState<Status>({ value: "disconnected" });
useEffect(() => { useEffect(() => {
if (!transcriptId) return; if (!transcriptId) return;
@@ -40,7 +50,7 @@ export const useWebSockets = (transcriptId) => {
break; break;
case "STATUS": case "STATUS":
setStatus(message.data.status); setStatus(message.data);
break; break;
default: default:

View File

@@ -0,0 +1,19 @@
export type Topic = {
timestamp: number;
title: string;
transcript: string;
summary: string;
id: string;
};
export type Transcript = {
text: string;
};
export type FinalSummary = {
summary: string;
};
export type Status = {
value: string;
};

View File

@@ -5,7 +5,7 @@ const nextConfig = {
module.exports = nextConfig; module.exports = nextConfig;
// Sentry content below // Injected content via Sentry wizard below
const { withSentryConfig } = require("@sentry/nextjs"); const { withSentryConfig } = require("@sentry/nextjs");

View File

@@ -14,7 +14,7 @@
"@fortawesome/fontawesome-svg-core": "^6.4.0", "@fortawesome/fontawesome-svg-core": "^6.4.0",
"@fortawesome/free-solid-svg-icons": "^6.4.0", "@fortawesome/free-solid-svg-icons": "^6.4.0",
"@fortawesome/react-fontawesome": "^0.2.0", "@fortawesome/react-fontawesome": "^0.2.0",
"@sentry/nextjs": "^7.61.0", "@sentry/nextjs": "^7.64.0",
"autoprefixer": "10.4.14", "autoprefixer": "10.4.14",
"axios": "^1.4.0", "axios": "^1.4.0",
"fontawesome": "^5.6.3", "fontawesome": "^5.6.3",

View File

@@ -252,26 +252,26 @@
estree-walker "^2.0.2" estree-walker "^2.0.2"
picomatch "^2.3.1" picomatch "^2.3.1"
"@sentry-internal/tracing@7.61.0": "@sentry-internal/tracing@7.64.0":
version "7.61.0" version "7.64.0"
resolved "https://registry.yarnpkg.com/@sentry-internal/tracing/-/tracing-7.61.0.tgz#5a0dd4a9a0b41f2e22904430f3fe0216f36ee086" resolved "https://registry.yarnpkg.com/@sentry-internal/tracing/-/tracing-7.64.0.tgz#3e110473b8edf805b799cc91d6ee592830237bb4"
integrity sha512-zTr+MXEG4SxNxif42LIgm2RQn+JRXL2NuGhRaKSD2i4lXKFqHVGlVdoWqY5UfqnnJPokiTWIj9ejR8I5HV8Ogw== integrity sha512-1XE8W6ki7hHyBvX9hfirnGkKDBKNq3bDJyXS86E0bYVDl94nvbRM9BD9DHsCFetqYkVm1yDGEK+6aUVs4CztoQ==
dependencies: dependencies:
"@sentry/core" "7.61.0" "@sentry/core" "7.64.0"
"@sentry/types" "7.61.0" "@sentry/types" "7.64.0"
"@sentry/utils" "7.61.0" "@sentry/utils" "7.64.0"
tslib "^2.4.1 || ^1.9.3" tslib "^2.4.1 || ^1.9.3"
"@sentry/browser@7.61.0": "@sentry/browser@7.64.0":
version "7.61.0" version "7.64.0"
resolved "https://registry.yarnpkg.com/@sentry/browser/-/browser-7.61.0.tgz#04f4122e444d8b5ffefed97af3cde2bc1c71bb80" resolved "https://registry.yarnpkg.com/@sentry/browser/-/browser-7.64.0.tgz#76db08a5d32ffe7c5aa907f258e6c845ce7f10d7"
integrity sha512-IGEkJZRP16Oe5CkXkmhU3QdV5RugW6Vds16yJFFYsgp87NprWtRZgqzldFDYkINStfBHVdctj/Rh/ZrLf8QlkQ== integrity sha512-lB2IWUkZavEDclxfLBp554dY10ZNIEvlDZUWWathW+Ws2wRb6PNLtuPUNu12R7Q7z0xpkOLrM1kRNN0OdldgKA==
dependencies: dependencies:
"@sentry-internal/tracing" "7.61.0" "@sentry-internal/tracing" "7.64.0"
"@sentry/core" "7.61.0" "@sentry/core" "7.64.0"
"@sentry/replay" "7.61.0" "@sentry/replay" "7.64.0"
"@sentry/types" "7.61.0" "@sentry/types" "7.64.0"
"@sentry/utils" "7.61.0" "@sentry/utils" "7.64.0"
tslib "^2.4.1 || ^1.9.3" tslib "^2.4.1 || ^1.9.3"
"@sentry/cli@^1.74.6": "@sentry/cli@^1.74.6":
@@ -286,88 +286,88 @@
proxy-from-env "^1.1.0" proxy-from-env "^1.1.0"
which "^2.0.2" which "^2.0.2"
"@sentry/core@7.61.0": "@sentry/core@7.64.0":
version "7.61.0" version "7.64.0"
resolved "https://registry.yarnpkg.com/@sentry/core/-/core-7.61.0.tgz#0de4f73055bd156c5c0cbac50bb814b272567188" resolved "https://registry.yarnpkg.com/@sentry/core/-/core-7.64.0.tgz#9d61cdc29ba299dedbdcbe01cfadf94bd0b7df48"
integrity sha512-zl0ZKRjIoYJQWYTd3K/U6zZfS4GDY9yGd2EH4vuYO4kfYtEp/nJ8A+tfAeDo0c9FGxZ0Q+5t5F4/SfwbgyyQzg== integrity sha512-IzmEyl5sNG7NyEFiyFHEHC+sizsZp9MEw1+RJRLX6U5RITvcsEgcajSkHQFafaBPzRrcxZMdm47Cwhl212LXcw==
dependencies: dependencies:
"@sentry/types" "7.61.0" "@sentry/types" "7.64.0"
"@sentry/utils" "7.61.0" "@sentry/utils" "7.64.0"
tslib "^2.4.1 || ^1.9.3" tslib "^2.4.1 || ^1.9.3"
"@sentry/integrations@7.61.0": "@sentry/integrations@7.64.0":
version "7.61.0" version "7.64.0"
resolved "https://registry.yarnpkg.com/@sentry/integrations/-/integrations-7.61.0.tgz#49c97a59ceb0438bd5ec070415d95f8c6c708d5f" resolved "https://registry.yarnpkg.com/@sentry/integrations/-/integrations-7.64.0.tgz#a392ddeebeec0c08ae5ca1f544c80ab15977fe10"
integrity sha512-NEQ+CatBfUM1TmA4FOOyHfsMvSIwSg4pA55Lxiq9quDykzkEtrXFzUfFpZbTunz4cegG8hucPOqbzKFrDPfGjQ== integrity sha512-6gbSGiruOifAmLtXw//Za19GWiL5qugDMEFxSvc5WrBWb+A8UK+foPn3K495OcivLS68AmqAQCUGb+6nlVowwA==
dependencies: dependencies:
"@sentry/types" "7.61.0" "@sentry/types" "7.64.0"
"@sentry/utils" "7.61.0" "@sentry/utils" "7.64.0"
localforage "^1.8.1" localforage "^1.8.1"
tslib "^2.4.1 || ^1.9.3" tslib "^2.4.1 || ^1.9.3"
"@sentry/nextjs@^7.61.0": "@sentry/nextjs@^7.64.0":
version "7.61.0" version "7.64.0"
resolved "https://registry.yarnpkg.com/@sentry/nextjs/-/nextjs-7.61.0.tgz#5a30faa6fb04d9148853edbb5c148dd522126097" resolved "https://registry.yarnpkg.com/@sentry/nextjs/-/nextjs-7.64.0.tgz#5c0bd7ccc6637e0b925dec25ca247dcb8476663c"
integrity sha512-zSEcAITqVmJpR4hhah1jUyCzm/hjlq9vjmO6BmTnQjr84OgOdeKJGWtRdktXId+9zzHdCOehs/JPtmO7y+yG6Q== integrity sha512-hKlIQpFugdRlWj0wcEG9I8JyVm/osdsE72zwMBGnmCw/jf7U63vjOjfxMe/gRuvllCf/AvoGHEkR5jPufcO+bw==
dependencies: dependencies:
"@rollup/plugin-commonjs" "24.0.0" "@rollup/plugin-commonjs" "24.0.0"
"@sentry/core" "7.61.0" "@sentry/core" "7.64.0"
"@sentry/integrations" "7.61.0" "@sentry/integrations" "7.64.0"
"@sentry/node" "7.61.0" "@sentry/node" "7.64.0"
"@sentry/react" "7.61.0" "@sentry/react" "7.64.0"
"@sentry/types" "7.61.0" "@sentry/types" "7.64.0"
"@sentry/utils" "7.61.0" "@sentry/utils" "7.64.0"
"@sentry/webpack-plugin" "1.20.0" "@sentry/webpack-plugin" "1.20.0"
chalk "3.0.0" chalk "3.0.0"
rollup "2.78.0" rollup "2.78.0"
stacktrace-parser "^0.1.10" stacktrace-parser "^0.1.10"
tslib "^2.4.1 || ^1.9.3" tslib "^2.4.1 || ^1.9.3"
"@sentry/node@7.61.0": "@sentry/node@7.64.0":
version "7.61.0" version "7.64.0"
resolved "https://registry.yarnpkg.com/@sentry/node/-/node-7.61.0.tgz#1309330f2ad136af532ad2a03b2a312e885705de" resolved "https://registry.yarnpkg.com/@sentry/node/-/node-7.64.0.tgz#c6f7a67c1442324298f0525e7191bc18572ee1ce"
integrity sha512-oTCqD/h92uvbRCrtCdiAqN6Mfe3vF7ywVHZ8Nq3hHmJp6XadUT+fCBwNQ7rjMyqJAOYAnx/vp6iN9n8C5qcYZQ== integrity sha512-wRi0uTnp1WSa83X2yLD49tV9QPzGh5e42IKdIDBiQ7lV9JhLILlyb34BZY1pq6p4dp35yDasDrP3C7ubn7wo6A==
dependencies: dependencies:
"@sentry-internal/tracing" "7.61.0" "@sentry-internal/tracing" "7.64.0"
"@sentry/core" "7.61.0" "@sentry/core" "7.64.0"
"@sentry/types" "7.61.0" "@sentry/types" "7.64.0"
"@sentry/utils" "7.61.0" "@sentry/utils" "7.64.0"
cookie "^0.4.1" cookie "^0.4.1"
https-proxy-agent "^5.0.0" https-proxy-agent "^5.0.0"
lru_map "^0.3.3" lru_map "^0.3.3"
tslib "^2.4.1 || ^1.9.3" tslib "^2.4.1 || ^1.9.3"
"@sentry/react@7.61.0": "@sentry/react@7.64.0":
version "7.61.0" version "7.64.0"
resolved "https://registry.yarnpkg.com/@sentry/react/-/react-7.61.0.tgz#21dc8eb5168fdb45f994e62738313b50c710d6a4" resolved "https://registry.yarnpkg.com/@sentry/react/-/react-7.64.0.tgz#edee24ac232990204e0fb43dd83994642d4b0f54"
integrity sha512-17ZPDdzx3hzJSHsVFAiw4hUT701LUVIcm568q38sPlSUmnOmNmPeHx/xcQkuxMoVsw/xgf/82B/BKKnIP5/diA== integrity sha512-wOyJUQi7OoT1q+F/fVVv1fzbyO4OYbTu6m1DliLOGQPGEHPBsgPc722smPIExd1/rAMK/FxOuNN5oNhubH8nhg==
dependencies: dependencies:
"@sentry/browser" "7.61.0" "@sentry/browser" "7.64.0"
"@sentry/types" "7.61.0" "@sentry/types" "7.64.0"
"@sentry/utils" "7.61.0" "@sentry/utils" "7.64.0"
hoist-non-react-statics "^3.3.2" hoist-non-react-statics "^3.3.2"
tslib "^2.4.1 || ^1.9.3" tslib "^2.4.1 || ^1.9.3"
"@sentry/replay@7.61.0": "@sentry/replay@7.64.0":
version "7.61.0" version "7.64.0"
resolved "https://registry.yarnpkg.com/@sentry/replay/-/replay-7.61.0.tgz#f816d6a2fc7511877efee2e328681d659433d147" resolved "https://registry.yarnpkg.com/@sentry/replay/-/replay-7.64.0.tgz#bdf09b0c4712f9dc6b24b3ebefa55a4ac76708e6"
integrity sha512-1ugk0yZssOPkSg6uTVcysjxlBydycXiOgV0PCU7DsXCFOV1ua5YpyPZFReTz9iFTtwD0LwGFM1LW9wJeQ67Fzg== integrity sha512-alaMCZDZhaAVmEyiUnszZnvfdbiZx5MmtMTGrlDd7tYq3K5OA9prdLqqlmfIJYBfYtXF3lD0iZFphOZQD+4CIw==
dependencies: dependencies:
"@sentry/core" "7.61.0" "@sentry/core" "7.64.0"
"@sentry/types" "7.61.0" "@sentry/types" "7.64.0"
"@sentry/utils" "7.61.0" "@sentry/utils" "7.64.0"
"@sentry/types@7.61.0": "@sentry/types@7.64.0":
version "7.61.0" version "7.64.0"
resolved "https://registry.yarnpkg.com/@sentry/types/-/types-7.61.0.tgz#4243b5ef4658f6b0673bc4372c90e6ec920f78d8" resolved "https://registry.yarnpkg.com/@sentry/types/-/types-7.64.0.tgz#21fc545ea05c3c8c4c3e518583eca1a8c5429506"
integrity sha512-/GLlIBNR35NKPE/SfWi9W10dK9hE8qTShzsuPVn5wAJxpT3Lb4+dkwmKCTLUYxdkmvRDEudkfOxgalsfQGTAWA== integrity sha512-LqjQprWXjUFRmzIlUjyA+KL+38elgIYmAeoDrdyNVh8MK5IC1W2Lh1Q87b4yOiZeMiIhIVNBd7Ecoh2rodGrGA==
"@sentry/utils@7.61.0": "@sentry/utils@7.64.0":
version "7.61.0" version "7.64.0"
resolved "https://registry.yarnpkg.com/@sentry/utils/-/utils-7.61.0.tgz#16944afb2b851af045fb528c0c35b7dea3e1cd3b" resolved "https://registry.yarnpkg.com/@sentry/utils/-/utils-7.64.0.tgz#6fe3ce9a56d3433ed32119f914907361a54cc184"
integrity sha512-jfj14d0XBFiCU0G6dZZ12SizATiF5Mt4stBGzkM5iS9nXFj8rh1oTT7/p+aZoYzP2JTF+sDzkNjWxyKZkcTo0Q== integrity sha512-HRlM1INzK66Gt+F4vCItiwGKAng4gqzCR4C5marsL3qv6SrKH98dQnCGYgXluSWaaa56h97FRQu7TxCk6jkSvQ==
dependencies: dependencies:
"@sentry/types" "7.61.0" "@sentry/types" "7.64.0"
tslib "^2.4.1 || ^1.9.3" tslib "^2.4.1 || ^1.9.3"
"@sentry/webpack-plugin@1.20.0": "@sentry/webpack-plugin@1.20.0":