refactor: universal logger and remove N+1 catalog queries
CI / check (push) Successful in 28s
CI / tests-ui (push) Failing after 32s
CI / tests-unit (push) Successful in 1m43s
CI / tests-quality (push) Successful in 1m14s
CI / tests-integration (push) Successful in 1m50s
CI / preflight (push) Skipped
CI / deploy (push) Skipped
CI / tests-imaging-browsers (push) Successful in 1m56s
CI / check (push) Successful in 28s
CI / tests-ui (push) Failing after 32s
CI / tests-unit (push) Successful in 1m43s
CI / tests-quality (push) Successful in 1m14s
CI / tests-integration (push) Successful in 1m50s
CI / preflight (push) Skipped
CI / deploy (push) Skipped
CI / tests-imaging-browsers (push) Successful in 1m56s
- Replace all 39 console.* calls with universal logger (pino server, console browser) - Set server-only marker on import-badge.ts - Disable DB query logging in production - Add bulkInsertCatalogItems: one transaction instead of N per-item inserts - Add reserveCatalogItemIds helper for bulk ID allocation - Optimize translateCatalogItems: single inArray batch query instead of N per-item selects - Test mock updated for logger.debug - biome clean, tsc clean, 3569 tests passing
This commit is contained in:
1 parent
6895eaab49
commit
59a45d2165
27 files changed
+416
-241
No files matched your search
@@ -32,6 +32,7 @@ import {
|
||||
} from "@/features/catalog/domain/organize";
|
||||
import { CATALOG_LAYOUTS, type CatalogLayout } from "@/lib/catalog-layouts";
|
||||
import { getLocalIconUrl } from "@/lib/furni/classname";
|
||||
import { logger } from "@/lib/logger";
|
||||
import { cn } from "@/lib/utils";
|
||||
import { LiveCatalogPreview } from "./live-catalog-preview";
|
||||
|
||||
@@ -136,7 +137,9 @@ export function AutoCategoryDialog({
|
||||
.then((r) => r.json())
|
||||
.then((data) => setResults(data.results ?? []))
|
||||
.catch((error) =>
|
||||
console.error("[AutoCategory] furni search failed:", error),
|
||||
logger.error("[AutoCategory] furni search failed", {
|
||||
err: error as Error,
|
||||
}),
|
||||
)
|
||||
.finally(() => setSearchLoading(false));
|
||||
return () => ac.abort();
|
||||
@@ -263,7 +266,9 @@ export function AutoCategoryDialog({
|
||||
resetState();
|
||||
onOpenChange(false);
|
||||
} catch (error) {
|
||||
console.error("[AutoCategory] create failed:", error);
|
||||
logger.error("[AutoCategory] create failed", {
|
||||
err: error as Error,
|
||||
});
|
||||
toast.error("Failed to create category");
|
||||
} finally {
|
||||
setIsCreating(false);
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
|
||||
import { ChevronRight, Home } from "lucide-react";
|
||||
import { Fragment, useEffect } from "react";
|
||||
import { logger } from "@/lib/logger";
|
||||
import { useCatalogManager } from "./use-catalog-store";
|
||||
|
||||
export function BreadcrumbBar({
|
||||
@@ -29,7 +30,9 @@ export function BreadcrumbBar({
|
||||
}
|
||||
})
|
||||
.catch((error) =>
|
||||
console.error("[Breadcrumb] Failed to fetch ancestors:", error),
|
||||
logger.error("[Breadcrumb] Failed to fetch ancestors", {
|
||||
err: error as Error,
|
||||
}),
|
||||
);
|
||||
return () => ac.abort();
|
||||
}, [selectedPageId, dispatch, catQs]);
|
||||
|
||||
@@ -62,6 +62,7 @@ import { requestCatalogNavigation } from "@/features/catalog/client/use-catalog-
|
||||
import { useLiveCatalog } from "@/features/catalog/client/use-live-catalog";
|
||||
import { DuplicateCategoryDialog } from "@/features/catalog/components/duplicate-category-dialog";
|
||||
import type { DuplicateInput } from "@/features/catalog/domain/duplicate";
|
||||
import { logger } from "@/lib/logger";
|
||||
import { cn } from "@/lib/utils";
|
||||
import {
|
||||
type FlatTreeNode,
|
||||
@@ -779,7 +780,9 @@ export function SortableTree({
|
||||
});
|
||||
})
|
||||
.catch((error) =>
|
||||
console.error("[SortableTree] Failed to load children:", error),
|
||||
logger.error("[SortableTree] Failed to load children", {
|
||||
err: error as Error,
|
||||
}),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -12,6 +12,7 @@ import {
|
||||
} from "@/components/ui/dialog";
|
||||
import { Input } from "@/components/ui/input";
|
||||
import { catalogueIconUrl } from "@/lib/catalog-assets";
|
||||
import { logger } from "@/lib/logger";
|
||||
import { cn } from "@/lib/utils";
|
||||
|
||||
interface IconPickerProps {
|
||||
@@ -64,7 +65,9 @@ export function IconPicker({
|
||||
setIcons((prev) => (replace ? fetched : [...prev, ...fetched]));
|
||||
setOffset(nextOffset + fetched.length);
|
||||
} catch (err) {
|
||||
console.error("[IconPicker]", err);
|
||||
logger.error("[IconPicker] icon load failed", {
|
||||
err: err as Error,
|
||||
});
|
||||
} finally {
|
||||
setLoading(false);
|
||||
}
|
||||
|
||||
@@ -14,6 +14,7 @@ import {
|
||||
import { Input } from "@/components/ui/input";
|
||||
import { useServerAction } from "@/hooks/use-server-action";
|
||||
import { getHabboCdnIconUrl, getLocalIconUrl } from "@/lib/furni/classname";
|
||||
import { logger } from "@/lib/logger";
|
||||
|
||||
interface FurniResult {
|
||||
id: number;
|
||||
@@ -81,7 +82,11 @@ export function QuickAddFurni({
|
||||
)
|
||||
.then((r) => r.json())
|
||||
.then((data) => setResults(data.results ?? []))
|
||||
.catch((error) => console.error("[QuickAdd] Furni search failed:", error))
|
||||
.catch((error) =>
|
||||
logger.error("[QuickAdd] Furni search failed", {
|
||||
err: error as Error,
|
||||
}),
|
||||
)
|
||||
.finally(() => setLoading(false));
|
||||
return () => ac.abort();
|
||||
}, [debounced, open]);
|
||||
|
||||
@@ -5,6 +5,7 @@ import { useCallback, useEffect, useMemo, useRef, useState } from "react";
|
||||
import { deleteMedia, uploadMedia } from "@/actions/admin-media";
|
||||
import { useConfirmDialog } from "@/components/admin/confirm-dialog";
|
||||
import { formatDate } from "@/lib/format-date";
|
||||
import { logger } from "@/lib/logger";
|
||||
import type { MediaFile } from "@/lib/media-files";
|
||||
import { loadMediaFiles, validImageUrl } from "@/lib/media-files";
|
||||
|
||||
@@ -83,7 +84,11 @@ export function AdminMediaGrid() {
|
||||
setCopied(url);
|
||||
setTimeout(() => setCopied(null), 1500);
|
||||
})
|
||||
.catch((error) => console.error("[Media] Clipboard copy failed:", error));
|
||||
.catch((error) =>
|
||||
logger.error("[Media] Clipboard copy failed", {
|
||||
err: error as Error,
|
||||
}),
|
||||
);
|
||||
}
|
||||
|
||||
async function remove(name: string) {
|
||||
|
||||
@@ -58,6 +58,7 @@ import {
|
||||
isValidCatalogLayout,
|
||||
LAYOUT_DESCRIPTIONS,
|
||||
} from "@/lib/catalog-layouts";
|
||||
import { logger } from "@/lib/logger";
|
||||
import { cn } from "@/lib/utils";
|
||||
|
||||
const MAX_ITEMS_PER_RUN = 500;
|
||||
@@ -245,7 +246,9 @@ export function OrganizeImportsDialog({
|
||||
}
|
||||
}
|
||||
} catch (error) {
|
||||
console.error("[OrganizeImports] load failed:", error);
|
||||
logger.error("[OrganizeImports] load failed", {
|
||||
err: error as Error,
|
||||
});
|
||||
setLoadError(true);
|
||||
setGroups([]);
|
||||
} finally {
|
||||
@@ -358,7 +361,9 @@ export function OrganizeImportsDialog({
|
||||
);
|
||||
})
|
||||
.catch((error) =>
|
||||
console.error("[OrganizeImports] page search failed:", error),
|
||||
logger.error("[OrganizeImports] page search failed", {
|
||||
err: error as Error,
|
||||
}),
|
||||
)
|
||||
.finally(() => setDestSearchLoading(false));
|
||||
return () => ac.abort();
|
||||
@@ -761,7 +766,9 @@ export function OrganizeImportsDialog({
|
||||
}
|
||||
onOpenChange(false);
|
||||
} catch (error) {
|
||||
console.error("[OrganizeImports] create failed:", error);
|
||||
logger.error("[OrganizeImports] create failed", {
|
||||
err: error as Error,
|
||||
});
|
||||
toast.error(t("errorFailed"));
|
||||
} finally {
|
||||
setIsCreating(false);
|
||||
|
||||
Reference in new issue
Block a user