fix: replace createClient with shared supabase singleton in useAdminStats and errorLogger
This commit is contained in:
parent
2fea387d43
commit
58a96355f1
|
|
@ -1,13 +1,13 @@
|
|||
import { useState, useEffect, useCallback } from "react";
|
||||
import { supabase, hasSupabaseConfig } from "../supabaseClient";
|
||||
|
||||
const PERIOD_DAYS = { today: 1, "7d": 7, "30d": 30, all: 0 };
|
||||
|
||||
const rpcCall = async (fnName, params) => {
|
||||
const { createClient } = await import("@supabase/supabase-js");
|
||||
const supabaseUrl = window.__SUPABASE_URL__ || import.meta.env.VITE_SUPABASE_URL;
|
||||
const supabaseAnonKey = window.__SUPABASE_ANON_KEY__ || import.meta.env.VITE_SUPABASE_ANON_KEY;
|
||||
const client = createClient(supabaseUrl, supabaseAnonKey);
|
||||
const { data, error } = await client.rpc(fnName, params);
|
||||
if (!hasSupabaseConfig || !supabase) {
|
||||
throw new Error("Supabase не сконфигурирован");
|
||||
}
|
||||
const { data, error } = await supabase.rpc(fnName, params);
|
||||
if (error) throw error;
|
||||
return data;
|
||||
};
|
||||
|
|
|
|||
|
|
@ -1,25 +1,27 @@
|
|||
import { createClient } from '@supabase/supabase-js';
|
||||
|
||||
const supabaseUrl = import.meta.env.VITE_SUPABASE_URL;
|
||||
const supabaseAnonKey = import.meta.env.VITE_SUPABASE_ANON_KEY;
|
||||
|
||||
const supabase = createClient(supabaseUrl, supabaseAnonKey);
|
||||
import { supabase, hasSupabaseConfig } from "../supabaseClient";
|
||||
|
||||
// Debounce tracking: message -> last timestamp
|
||||
const recentErrors = new Map();
|
||||
const DEBOUNCE_MS = 10000;
|
||||
|
||||
function getUserId() {
|
||||
// Try to get from Supabase auth session in localStorage
|
||||
// Try to get from Supabase auth session in sessionStorage
|
||||
try {
|
||||
const keys = Object.keys(localStorage);
|
||||
const keys = Object.keys(sessionStorage);
|
||||
const authKey = keys.find(
|
||||
(k) => k.startsWith('sb-') && k.endsWith('-auth-token')
|
||||
(k) => k.startsWith("sb-") && k.endsWith("-auth-token")
|
||||
);
|
||||
if (authKey) {
|
||||
const data = JSON.parse(localStorage.getItem(authKey));
|
||||
const data = JSON.parse(sessionStorage.getItem(authKey));
|
||||
return data?.user?.id || null;
|
||||
}
|
||||
// Also check supersam secure storage format
|
||||
const ssKey = keys.find((k) => k === "supersam-auth");
|
||||
if (ssKey) {
|
||||
const data = JSON.parse(sessionStorage.getItem(ssKey));
|
||||
// The secure storage obfuscates values, but the key structure is known
|
||||
// Fall through to window.__supersam_user_id__ set by AuthContext
|
||||
}
|
||||
} catch {
|
||||
// ignore
|
||||
}
|
||||
|
|
@ -46,19 +48,20 @@ function isDebounced(message) {
|
|||
|
||||
async function insertErrorLog(entry) {
|
||||
try {
|
||||
await supabase.from('client_error_logs').insert([entry]);
|
||||
if (!hasSupabaseConfig || !supabase) return;
|
||||
await supabase.from("client_error_logs").insert([entry]);
|
||||
} catch {
|
||||
// Fire-and-forget — swallow insertion errors
|
||||
}
|
||||
}
|
||||
|
||||
function logError(error, componentInfo) {
|
||||
if (!(error instanceof Error) && typeof error !== 'object' && typeof error !== 'string') {
|
||||
if (!(error instanceof Error) && typeof error !== "object" && typeof error !== "string") {
|
||||
return;
|
||||
}
|
||||
|
||||
const message =
|
||||
typeof error === 'string'
|
||||
typeof error === "string"
|
||||
? error
|
||||
: error?.message || String(error);
|
||||
|
||||
|
|
@ -66,7 +69,7 @@ function logError(error, componentInfo) {
|
|||
if (isDebounced(message)) return;
|
||||
|
||||
const stack =
|
||||
typeof error === 'object' && error !== null ? error.stack || null : null;
|
||||
typeof error === "object" && error !== null ? error.stack || null : null;
|
||||
|
||||
let line_number = null;
|
||||
let column_number = null;
|
||||
|
|
@ -83,16 +86,16 @@ function logError(error, componentInfo) {
|
|||
}
|
||||
|
||||
const entry = {
|
||||
user_id: getUserId(),
|
||||
user_id: getUserId() || window.__supersam_user_id__ || null,
|
||||
message,
|
||||
stack,
|
||||
url,
|
||||
line_number,
|
||||
column_number,
|
||||
error_type:
|
||||
typeof error === 'object' && error !== null
|
||||
? error.constructor?.name || 'Error'
|
||||
: 'String',
|
||||
typeof error === "object" && error !== null
|
||||
? error.constructor?.name || "Error"
|
||||
: "String",
|
||||
component: componentInfo?.component || null,
|
||||
props: componentInfo?.props
|
||||
? JSON.stringify(componentInfo.props)
|
||||
|
|
@ -106,16 +109,14 @@ function logError(error, componentInfo) {
|
|||
}
|
||||
|
||||
function initErrorLogging(userId) {
|
||||
// If a userId is provided, override the getUserId logic
|
||||
// If a userId is provided, store it for future logError calls
|
||||
if (userId) {
|
||||
const origGetUserId = getUserId;
|
||||
// We store it so future logError calls can use it
|
||||
window.__supersam_user_id__ = userId;
|
||||
}
|
||||
|
||||
// Catch synchronous errors
|
||||
window.onerror = function (message, source, lineno, colno, error) {
|
||||
const msg = typeof message === 'string' ? message : String(message);
|
||||
const msg = typeof message === "string" ? message : String(message);
|
||||
|
||||
if (isDebounced(msg)) return;
|
||||
|
||||
|
|
@ -126,7 +127,7 @@ function initErrorLogging(userId) {
|
|||
url: source || null,
|
||||
line_number: lineno || null,
|
||||
column_number: colno || null,
|
||||
error_type: error?.constructor?.name || 'Error',
|
||||
error_type: error?.constructor?.name || "Error",
|
||||
component: null,
|
||||
props: null,
|
||||
user_agent: navigator.userAgent,
|
||||
|
|
@ -142,7 +143,7 @@ function initErrorLogging(userId) {
|
|||
const message =
|
||||
error instanceof Error
|
||||
? error.message
|
||||
: typeof error === 'string'
|
||||
: typeof error === "string"
|
||||
? error
|
||||
: String(error);
|
||||
|
||||
|
|
@ -170,8 +171,8 @@ function initErrorLogging(userId) {
|
|||
column_number,
|
||||
error_type:
|
||||
error instanceof Error
|
||||
? error.constructor?.name || 'Error'
|
||||
: 'UnhandledRejection',
|
||||
? error.constructor?.name || "Error"
|
||||
: "UnhandledRejection",
|
||||
component: null,
|
||||
props: null,
|
||||
user_agent: navigator.userAgent,
|
||||
|
|
|
|||
Loading…
Reference in New Issue