Improvements: remove dead config, fix ESM, add URL validation, unify types, add missing logging
- Remove .prettierrc (dead config, Biome replaces Prettier) - Rename lighthouserc.json to lighthouserc.cjs with module.exports for ESM compat - Add logger.warn to empty catch blocks in auth, register, site-settings, prisma-cache, redis, security, rate-limit - Unify ActionResult type: action-helper.ts uses 'ok' consistent with safe-action-shared.ts - Add noUnusedLocals + noUnusedParameters to tsconfig + fix 25 pre-existing unused vars - Replace barrel export src/types/index.ts with direct @/types/common imports - Make trustHost conditional (development only) in auth.ts - Add pre-flight URL validation to update-Nitrov3.sh to catch image.library.url misconfigurations - Improve NITRO_IMAGE_LIBRARY_URL content validation in pre-flight & post-compute checks
This commit is contained in:
1 parent
b922f6d49f
commit
17847545dd
292 files changed
+69195
-67915
No files matched your search
@@ -1,4 +1,4 @@
|
||||
import { describe, expect, it, vi, beforeEach } from "vitest";
|
||||
import { beforeEach, describe, expect, it, vi } from "vitest";
|
||||
|
||||
const findMany = vi.hoisted(() => vi.fn());
|
||||
const create = vi.hoisted(() => vi.fn());
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { describe, expect, it, vi, beforeEach } from "vitest";
|
||||
import { beforeEach, describe, expect, it, vi } from "vitest";
|
||||
|
||||
const createFn = vi.hoisted(() => vi.fn());
|
||||
const sendMailFn = vi.hoisted(() => vi.fn().mockResolvedValue(true));
|
||||
|
||||
@@ -16,7 +16,6 @@ import { sendMail } from "@/lib/services/email";
|
||||
// fetch (Node 18+/Next 16) — no extra packages.
|
||||
//
|
||||
|
||||
|
||||
export type AlertSeverity =
|
||||
| "info"
|
||||
| "notice"
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { describe, expect, it, vi, beforeEach } from "vitest";
|
||||
import { beforeEach, describe, expect, it, vi } from "vitest";
|
||||
|
||||
const create = vi.hoisted(() => vi.fn());
|
||||
const findMany = vi.hoisted(() => vi.fn());
|
||||
@@ -14,7 +14,7 @@ vi.mock("@/lib/prisma", () => ({
|
||||
|
||||
vi.mock("@/env", () => ({ env: {} }));
|
||||
|
||||
import { logAudit, getAuditLogs } from "./audit";
|
||||
import { getAuditLogs, logAudit } from "./audit";
|
||||
|
||||
beforeEach(() => {
|
||||
vi.clearAllMocks();
|
||||
@@ -87,8 +87,28 @@ describe("logAudit", () => {
|
||||
describe("getAuditLogs", () => {
|
||||
it("returns paginated logs with usernames", async () => {
|
||||
findMany.mockResolvedValue([
|
||||
{ id: 1, userId: 1, action: "test", target: "user", targetId: null, before: null, after: null, diff: null, createdAt: "2024-01-01" },
|
||||
{ id: 2, userId: 2, action: "test2", target: "room", targetId: null, before: null, after: null, diff: null, createdAt: "2024-01-02" },
|
||||
{
|
||||
id: 1,
|
||||
userId: 1,
|
||||
action: "test",
|
||||
target: "user",
|
||||
targetId: null,
|
||||
before: null,
|
||||
after: null,
|
||||
diff: null,
|
||||
createdAt: "2024-01-01",
|
||||
},
|
||||
{
|
||||
id: 2,
|
||||
userId: 2,
|
||||
action: "test2",
|
||||
target: "room",
|
||||
targetId: null,
|
||||
before: null,
|
||||
after: null,
|
||||
diff: null,
|
||||
createdAt: "2024-01-02",
|
||||
},
|
||||
]);
|
||||
count.mockResolvedValue(2);
|
||||
userFindMany.mockResolvedValue([
|
||||
@@ -110,14 +130,29 @@ describe("getAuditLogs", () => {
|
||||
await getAuditLogs({ search: "test" });
|
||||
expect(findMany).toHaveBeenCalledWith(
|
||||
expect.objectContaining({
|
||||
where: { OR: [{ action: { contains: "test" } }, { target: { contains: "test" } }] },
|
||||
where: {
|
||||
OR: [
|
||||
{ action: { contains: "test" } },
|
||||
{ target: { contains: "test" } },
|
||||
],
|
||||
},
|
||||
}),
|
||||
);
|
||||
});
|
||||
|
||||
it("falls back to User #id for unknown users", async () => {
|
||||
findMany.mockResolvedValue([
|
||||
{ id: 1, userId: 99, action: "x", target: "y", targetId: null, before: null, after: null, diff: null, createdAt: "2024-01-01" },
|
||||
{
|
||||
id: 1,
|
||||
userId: 99,
|
||||
action: "x",
|
||||
target: "y",
|
||||
targetId: null,
|
||||
before: null,
|
||||
after: null,
|
||||
diff: null,
|
||||
createdAt: "2024-01-01",
|
||||
},
|
||||
]);
|
||||
count.mockResolvedValue(1);
|
||||
userFindMany.mockResolvedValue([]);
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { describe, expect, it, vi, beforeEach } from "vitest";
|
||||
import { beforeEach, describe, expect, it, vi } from "vitest";
|
||||
|
||||
const findUnique = vi.hoisted(() => vi.fn());
|
||||
const findMany = vi.hoisted(() => vi.fn());
|
||||
@@ -11,7 +11,14 @@ const catalogUpdateMany = vi.hoisted(() => vi.fn());
|
||||
|
||||
vi.mock("@/lib/prisma", () => ({
|
||||
prisma: {
|
||||
catalogPages: { findUnique, findMany, update, create, delete: catalogDelete, updateMany: catalogUpdateMany },
|
||||
catalogPages: {
|
||||
findUnique,
|
||||
findMany,
|
||||
update,
|
||||
create,
|
||||
delete: catalogDelete,
|
||||
updateMany: catalogUpdateMany,
|
||||
},
|
||||
$queryRaw: queryRaw,
|
||||
$executeRaw: executeRaw,
|
||||
},
|
||||
@@ -19,8 +26,15 @@ vi.mock("@/lib/prisma", () => ({
|
||||
|
||||
vi.mock("@/env", () => ({ env: {} }));
|
||||
|
||||
import { buildNestedTree, toInt, movePage, deletePage, getAncestors, createPage } from "./catalog-tree";
|
||||
import type { TreeNode } from "@/types/catalog";
|
||||
import {
|
||||
buildNestedTree,
|
||||
createPage,
|
||||
deletePage,
|
||||
getAncestors,
|
||||
movePage,
|
||||
toInt,
|
||||
} from "./catalog-tree";
|
||||
|
||||
beforeEach(() => {
|
||||
vi.clearAllMocks();
|
||||
@@ -44,9 +58,48 @@ describe("toInt", () => {
|
||||
|
||||
describe("buildNestedTree", () => {
|
||||
const flat: TreeNode[] = [
|
||||
{ id: 1, caption: "Root", parentId: -1, depth: 0, orderNum: 1, enabled: "1", visible: "1", iconImage: 0, iconColor: 0, pageLayout: "default_3x3", childCount: 2, itemCount: 0 },
|
||||
{ id: 2, caption: "Child", parentId: 1, depth: 1, orderNum: 1, enabled: "1", visible: "1", iconImage: 0, iconColor: 0, pageLayout: "default_3x3", childCount: 1, itemCount: 5 },
|
||||
{ id: 3, caption: "Grandchild", parentId: 2, depth: 2, orderNum: 1, enabled: "1", visible: "1", iconImage: 0, iconColor: 0, pageLayout: "default_3x3", childCount: 0, itemCount: 0 },
|
||||
{
|
||||
id: 1,
|
||||
caption: "Root",
|
||||
parentId: -1,
|
||||
depth: 0,
|
||||
orderNum: 1,
|
||||
enabled: "1",
|
||||
visible: "1",
|
||||
iconImage: 0,
|
||||
iconColor: 0,
|
||||
pageLayout: "default_3x3",
|
||||
childCount: 2,
|
||||
itemCount: 0,
|
||||
},
|
||||
{
|
||||
id: 2,
|
||||
caption: "Child",
|
||||
parentId: 1,
|
||||
depth: 1,
|
||||
orderNum: 1,
|
||||
enabled: "1",
|
||||
visible: "1",
|
||||
iconImage: 0,
|
||||
iconColor: 0,
|
||||
pageLayout: "default_3x3",
|
||||
childCount: 1,
|
||||
itemCount: 5,
|
||||
},
|
||||
{
|
||||
id: 3,
|
||||
caption: "Grandchild",
|
||||
parentId: 2,
|
||||
depth: 2,
|
||||
orderNum: 1,
|
||||
enabled: "1",
|
||||
visible: "1",
|
||||
iconImage: 0,
|
||||
iconColor: 0,
|
||||
pageLayout: "default_3x3",
|
||||
childCount: 0,
|
||||
itemCount: 0,
|
||||
},
|
||||
];
|
||||
|
||||
it("builds nested tree from flat nodes", () => {
|
||||
@@ -89,7 +142,12 @@ describe("createPage", () => {
|
||||
|
||||
it("converts boolean visible/enabled to string", async () => {
|
||||
create.mockResolvedValue({ id: 1 });
|
||||
await createPage({ parentId: 0, caption: "x", visible: false, enabled: false });
|
||||
await createPage({
|
||||
parentId: 0,
|
||||
caption: "x",
|
||||
visible: false,
|
||||
enabled: false,
|
||||
});
|
||||
expect(create.mock.calls[0][0].data.visible).toBe("0");
|
||||
expect(create.mock.calls[0][0].data.enabled).toBe("0");
|
||||
});
|
||||
|
||||
@@ -234,10 +234,10 @@ export async function cloneSingleFurni(params: {
|
||||
// Rollback: remove both downloaded files so we don't leave orphaned assets.
|
||||
await fs.unlink(/*turbopackIgnore: true*/ nitroPath).catch(() => {});
|
||||
await fs.unlink(/*turbopackIgnore: true*/ iconPath).catch(() => {});
|
||||
logger.warn(
|
||||
"[clone-import] items_base insert failed for",
|
||||
{ classname, error: (err as Error).message },
|
||||
);
|
||||
logger.warn("[clone-import] items_base insert failed for", {
|
||||
classname,
|
||||
error: (err as Error).message,
|
||||
});
|
||||
return {
|
||||
ok: false,
|
||||
classname,
|
||||
@@ -254,10 +254,10 @@ export async function cloneSingleFurni(params: {
|
||||
itemType,
|
||||
);
|
||||
} catch (err) {
|
||||
logger.warn(
|
||||
"[clone-import] FurnitureData append failed for",
|
||||
{ classname, error: (err as Error).message },
|
||||
);
|
||||
logger.warn("[clone-import] FurnitureData append failed for", {
|
||||
classname,
|
||||
error: (err as Error).message,
|
||||
});
|
||||
warnings.push(`FurnitureData append failed: ${(err as Error).message}`);
|
||||
}
|
||||
|
||||
@@ -272,10 +272,10 @@ export async function cloneSingleFurni(params: {
|
||||
return nextCatalogId;
|
||||
});
|
||||
} catch (err) {
|
||||
logger.warn(
|
||||
"[clone-import] catalog entry failed for",
|
||||
{ classname, error: (err as Error).message },
|
||||
);
|
||||
logger.warn("[clone-import] catalog entry failed for", {
|
||||
classname,
|
||||
error: (err as Error).message,
|
||||
});
|
||||
warnings.push(`catalog entry failed: ${(err as Error).message}`);
|
||||
}
|
||||
|
||||
|
||||
@@ -436,7 +436,6 @@ export async function importSingleFurni(params: {
|
||||
const starIdx = classname.indexOf("*");
|
||||
const hasColor = starIdx !== -1;
|
||||
const baseClassname = hasColor ? classname.substring(0, starIdx) : classname;
|
||||
const _colorNum = hasColor ? classname.substring(starIdx + 1) : "2";
|
||||
const iconFileName = classname.replace(/\*/g, "_");
|
||||
const safeSwfName = baseClassname;
|
||||
const safeNitroName = baseClassname;
|
||||
@@ -536,10 +535,9 @@ export async function importSingleFurni(params: {
|
||||
warnings.push("SWF not available for Nitro conversion");
|
||||
}
|
||||
} catch (err) {
|
||||
logger.warn(
|
||||
"[import-furni] SWF to Nitro conversion failed",
|
||||
{ error: (err as Error).message },
|
||||
);
|
||||
logger.warn("[import-furni] SWF to Nitro conversion failed", {
|
||||
error: (err as Error).message,
|
||||
});
|
||||
warnings.push(
|
||||
`SWF to Nitro conversion failed: ${(err as Error).message}`,
|
||||
);
|
||||
@@ -665,10 +663,9 @@ export async function importSingleFurni(params: {
|
||||
try {
|
||||
await appendFurniEntry(furniEntry, itemType);
|
||||
} catch (err) {
|
||||
logger.warn(
|
||||
"[import-furni] Failed to update FurnitureData.json",
|
||||
{ error: (err as Error).message },
|
||||
);
|
||||
logger.warn("[import-furni] Failed to update FurnitureData.json", {
|
||||
error: (err as Error).message,
|
||||
});
|
||||
warnings.push("FurnitureData.json update failed");
|
||||
}
|
||||
}
|
||||
@@ -707,10 +704,9 @@ export async function importSingleFurni(params: {
|
||||
});
|
||||
}
|
||||
} catch (err) {
|
||||
logger.warn(
|
||||
"[import-furni] Failed to create catalog entry",
|
||||
{ error: (err as Error).message },
|
||||
);
|
||||
logger.warn("[import-furni] Failed to create catalog entry", {
|
||||
error: (err as Error).message,
|
||||
});
|
||||
warnings.push("Catalog entry creation failed");
|
||||
}
|
||||
|
||||
|
||||
@@ -5,13 +5,13 @@
|
||||
|
||||
export type { HabboItFurniEntry } from "@/types/furni";
|
||||
|
||||
import { logger } from "@/lib/logger";
|
||||
import type { HabboItFurniEntry } from "@/types/furni";
|
||||
import {
|
||||
habboFurnidataUrl,
|
||||
type HabboGamedataHotel,
|
||||
habboFurnidataUrl,
|
||||
} from "@/lib/habbo-gamedata-hotel";
|
||||
import { logger } from "@/lib/logger";
|
||||
import { getHabboGamedataHotel } from "@/lib/services/habbo-gamedata-hotel";
|
||||
import type { HabboItFurniEntry } from "@/types/furni";
|
||||
|
||||
const CACHE_TTL = 30 * 60 * 1000; // 30 minutes
|
||||
|
||||
@@ -30,11 +30,7 @@ export async function getHabboItFurnidata(): Promise<
|
||||
const hotel = await getHabboGamedataHotel();
|
||||
const now = Date.now();
|
||||
|
||||
if (
|
||||
cache &&
|
||||
cacheHotel === hotel &&
|
||||
now - cacheTimestamp < CACHE_TTL
|
||||
) {
|
||||
if (cache && cacheHotel === hotel && now - cacheTimestamp < CACHE_TTL) {
|
||||
return cache;
|
||||
}
|
||||
|
||||
@@ -125,10 +121,9 @@ export async function getHabboItFurnidata(): Promise<
|
||||
cacheTimestamp = Date.now();
|
||||
return map;
|
||||
} catch (err) {
|
||||
logger.warn(
|
||||
"[habbo-furnidata] Fetch error",
|
||||
{ error: (err as Error).message },
|
||||
);
|
||||
logger.warn("[habbo-furnidata] Fetch error", {
|
||||
error: (err as Error).message,
|
||||
});
|
||||
return cache || new Map();
|
||||
} finally {
|
||||
loading = null;
|
||||
|
||||
@@ -7,13 +7,13 @@
|
||||
|
||||
export type { HabboAssetBadge } from "@/types/furni";
|
||||
|
||||
import { logger } from "@/lib/logger";
|
||||
import type { HabboAssetBadge } from "@/types/furni";
|
||||
import {
|
||||
habboExternalTextsUrl,
|
||||
type HabboGamedataHotel,
|
||||
habboExternalTextsUrl,
|
||||
} from "@/lib/habbo-gamedata-hotel";
|
||||
import { logger } from "@/lib/logger";
|
||||
import { getHabboGamedataHotel } from "@/lib/services/habbo-gamedata-hotel";
|
||||
import type { HabboAssetBadge } from "@/types/furni";
|
||||
|
||||
const BADGE_IMAGE_BASE = "https://images.habbo.com/c_images/album1584";
|
||||
const CACHE_TTL = 30 * 60 * 1000; // 30 minutes
|
||||
@@ -39,11 +39,7 @@ async function loadBadges(): Promise<{
|
||||
}> {
|
||||
const hotel = await getHabboGamedataHotel();
|
||||
const now = Date.now();
|
||||
if (
|
||||
badgeCache &&
|
||||
cacheHotel === hotel &&
|
||||
now - cacheTimestamp < CACHE_TTL
|
||||
) {
|
||||
if (badgeCache && cacheHotel === hotel && now - cacheTimestamp < CACHE_TTL) {
|
||||
return { badges: badgeCache, hotel };
|
||||
}
|
||||
if (loadingPromise) {
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { describe, expect, it, vi, beforeEach } from "vitest";
|
||||
import { beforeEach, describe, expect, it, vi } from "vitest";
|
||||
|
||||
const findMany = vi.hoisted(() => vi.fn());
|
||||
|
||||
@@ -29,7 +29,10 @@ describe("moderation", () => {
|
||||
it("blocks text containing a filtered word", async () => {
|
||||
findMany.mockResolvedValue([{ word: "badword" }]);
|
||||
const result = await isAllowed("this contains badword here");
|
||||
expect(result).toEqual({ ok: false, reason: 'Blocked by word filter: "badword"' });
|
||||
expect(result).toEqual({
|
||||
ok: false,
|
||||
reason: 'Blocked by word filter: "badword"',
|
||||
});
|
||||
});
|
||||
|
||||
it("allows empty text", async () => {
|
||||
@@ -46,7 +49,9 @@ describe("moderation", () => {
|
||||
|
||||
it("moderateOrThrow throws on blocked content", async () => {
|
||||
findMany.mockResolvedValue([{ word: "bad" }]);
|
||||
await expect(moderateOrThrow("this is bad")).rejects.toThrow("Blocked by word filter");
|
||||
await expect(moderateOrThrow("this is bad")).rejects.toThrow(
|
||||
"Blocked by word filter",
|
||||
);
|
||||
});
|
||||
|
||||
it("moderateOrThrow resolves on clean content", async () => {
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { describe, expect, it, vi, beforeEach } from "vitest";
|
||||
import { describe, expect, it, vi } from "vitest";
|
||||
|
||||
vi.mock("@/env", () => ({
|
||||
env: {
|
||||
@@ -10,7 +10,12 @@ vi.mock("@/env", () => ({
|
||||
},
|
||||
}));
|
||||
|
||||
import { isPayPalConfigured, creditsPerUnit, PAYPAL_API, PAYPAL_CURRENCY } from "./paypal";
|
||||
import {
|
||||
creditsPerUnit,
|
||||
isPayPalConfigured,
|
||||
PAYPAL_API,
|
||||
PAYPAL_CURRENCY,
|
||||
} from "./paypal";
|
||||
|
||||
describe("paypal", () => {
|
||||
it("isPayPalConfigured returns true when credentials are set", () => {
|
||||
|
||||
@@ -4,8 +4,7 @@
|
||||
import { env } from "@/env";
|
||||
|
||||
export const PAYPAL_API =
|
||||
env.PAYPAL_API?.replace(/\/+$/, "") ??
|
||||
"https://api-m.sandbox.paypal.com";
|
||||
env.PAYPAL_API?.replace(/\/+$/, "") ?? "https://api-m.sandbox.paypal.com";
|
||||
|
||||
export const PAYPAL_CURRENCY = env.PAYPAL_CURRENCY.toUpperCase();
|
||||
|
||||
|
||||
@@ -2,9 +2,9 @@ import { describe, expect, it } from "vitest";
|
||||
|
||||
import {
|
||||
getRankPermissionColumn,
|
||||
toPermissionValue,
|
||||
splitRankUpdateFields,
|
||||
RANK_GENERAL_FIELDS,
|
||||
splitRankUpdateFields,
|
||||
toPermissionValue,
|
||||
} from "./permission-ranks";
|
||||
|
||||
describe("getRankPermissionColumn", () => {
|
||||
|
||||
@@ -19,7 +19,12 @@ describe("sendCurrency", () => {
|
||||
giveDiamonds: vi.fn(),
|
||||
givePointsGotw: vi.fn(),
|
||||
};
|
||||
const result = await sendCurrency({ rcon, db: {} as any }, 1, "credits", 100);
|
||||
const result = await sendCurrency(
|
||||
{ rcon, db: {} as any },
|
||||
1,
|
||||
"credits",
|
||||
100,
|
||||
);
|
||||
expect(result).toBe(true);
|
||||
expect(rcon.giveCredits).toHaveBeenCalledWith(1, 100);
|
||||
});
|
||||
@@ -55,7 +60,12 @@ describe("sendCurrency", () => {
|
||||
giveDiamonds: vi.fn(),
|
||||
givePointsGotw: vi.fn(),
|
||||
};
|
||||
const result = await sendCurrency({ rcon, db: {} as any }, 1, "duckets", 50);
|
||||
const result = await sendCurrency(
|
||||
{ rcon, db: {} as any },
|
||||
1,
|
||||
"duckets",
|
||||
50,
|
||||
);
|
||||
expect(result).toBe(true);
|
||||
expect(rcon.giveDuckets).toHaveBeenCalledWith(1, 50);
|
||||
});
|
||||
@@ -138,4 +148,4 @@ describe("sendCurrency", () => {
|
||||
}),
|
||||
);
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -1,6 +1,7 @@
|
||||
import "server-only";
|
||||
|
||||
import { FALLBACK_HOTEL_NAME } from "@/lib/brand";
|
||||
import { logger } from "@/lib/logger";
|
||||
import { prisma } from "@/lib/prisma";
|
||||
import { redis } from "@/lib/redis";
|
||||
|
||||
@@ -25,6 +26,7 @@ class SiteSettings {
|
||||
});
|
||||
return new Map(rows.map((r) => [r.key, r.value]));
|
||||
} catch {
|
||||
logger.warn("Failed to load site settings from database, using defaults");
|
||||
return new Map(Object.entries(DEFAULTS));
|
||||
}
|
||||
}
|
||||
@@ -38,7 +40,7 @@ class SiteSettings {
|
||||
return new Map(Object.entries(parsed));
|
||||
}
|
||||
} catch {
|
||||
// Redis unavailable — fall through
|
||||
logger.warn("Redis cache read failed for site settings");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -56,7 +58,7 @@ class SiteSettings {
|
||||
JSON.stringify(obj),
|
||||
);
|
||||
} catch {
|
||||
// non-critical
|
||||
logger.warn("Failed to write site settings to Redis cache");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -78,13 +80,12 @@ class SiteSettings {
|
||||
return fallback;
|
||||
}
|
||||
|
||||
async getMany(
|
||||
keys: string[],
|
||||
): Promise<Record<string, string | null>> {
|
||||
async getMany(keys: string[]): Promise<Record<string, string | null>> {
|
||||
const map = await this.load();
|
||||
const result: Record<string, string | null> = {};
|
||||
for (const key of keys) {
|
||||
result[key] = map.get(key) ?? (key in DEFAULTS ? DEFAULTS[key] as string : null);
|
||||
result[key] =
|
||||
map.get(key) ?? (key in DEFAULTS ? (DEFAULTS[key] as string) : null);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
@@ -111,7 +112,7 @@ class SiteSettings {
|
||||
try {
|
||||
await redis.del(REDIS_CACHE_KEY);
|
||||
} catch {
|
||||
// non-critical
|
||||
logger.warn("Failed to invalidate Redis cache for site settings");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { describe, expect, it, vi, beforeEach } from "vitest";
|
||||
import { beforeEach, describe, expect, it, vi } from "vitest";
|
||||
|
||||
const create = vi.hoisted(() => vi.fn());
|
||||
|
||||
|
||||
@@ -5,12 +5,7 @@
|
||||
* then bundles everything into the .nitro format expected
|
||||
* by the Nitro HTML5 client.
|
||||
*/
|
||||
import { gunzipSync, inflateSync } from "node:zlib";
|
||||
import type {
|
||||
BatchConversionItem,
|
||||
BatchConversionResult,
|
||||
ConversionResult,
|
||||
} from "@/types/furni";
|
||||
import type { ConversionResult } from "@/types/furni";
|
||||
import {
|
||||
parseBitsJpeg2,
|
||||
parseBitsJpeg3,
|
||||
@@ -535,5 +530,3 @@ export function extractIconFromSwf(
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -35,7 +35,10 @@ export interface UploadParams {
|
||||
customparams?: string;
|
||||
}
|
||||
|
||||
const MIGRATIONS_DIR = path.resolve(/*turbopackIgnore: true*/ process.cwd(), "prisma/migrations");
|
||||
const MIGRATIONS_DIR = path.resolve(
|
||||
/*turbopackIgnore: true*/ process.cwd(),
|
||||
"prisma/migrations",
|
||||
);
|
||||
|
||||
let itemsBaseIdAllocChain: Promise<unknown> = Promise.resolve();
|
||||
|
||||
@@ -99,7 +102,10 @@ async function writeSqlMigration(params: {
|
||||
const padded = String(num).padStart(4, "0");
|
||||
const className = params.classname.replace(/[^a-zA-Z0-9_-]/g, "_");
|
||||
const fileName = `${padded}_import_furni_${className}.sql`;
|
||||
const filePath = path.join(/*turbopackIgnore: true*/ MIGRATIONS_DIR, fileName);
|
||||
const filePath = path.join(
|
||||
/*turbopackIgnore: true*/ MIGRATIONS_DIR,
|
||||
fileName,
|
||||
);
|
||||
|
||||
const lines: string[] = [
|
||||
`-- Migration: ${fileName}`,
|
||||
@@ -192,7 +198,10 @@ export async function uploadSingleFurni(params: {
|
||||
const { iconDir, nitroDir } = await getFurniAssetDirs();
|
||||
|
||||
const nitroFileName = `${classname}.nitro`;
|
||||
const nitroPath = path.join(/*turbopackIgnore: true*/ nitroDir, nitroFileName);
|
||||
const nitroPath = path.join(
|
||||
/*turbopackIgnore: true*/ nitroDir,
|
||||
nitroFileName,
|
||||
);
|
||||
if (existsSync(nitroPath)) {
|
||||
return {
|
||||
ok: false,
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { logger } from "@/lib/logger";
|
||||
import { env } from "@/env";
|
||||
import { logger } from "@/lib/logger";
|
||||
import { prisma } from "../prisma";
|
||||
|
||||
export type { WebhookAction } from "@/types/admin";
|
||||
|
||||
Reference in new issue
Block a user