revert fb8e77bb68
Local Build and Deploy / deploy (push) Successful in 1m11s

revert style: clean up code with prettier and eslint
This commit is contained in:
remco committed 2026-07-12 21:02:03 +02:00
1 parent 27de078f54
commit e85e4d74ea
378 files changed
+20710 -22428

No files matched your search

+136 -113
View File
@@ -1,11 +1,11 @@
import { existsSync, promises as fs } from "node:fs";
import path from "node:path";
import { getNitroFilesRoot } from "@/lib/services/furni-asset-dirs";
import type { HabboItFurniEntry } from "@/lib/services/habbo-furnidata-cache";
import { siteSettings } from "@/lib/services/site-settings";
import type { FurniMetadata } from "@/lib/services/swf-to-nitro";
import { existsSync, promises as fs } from 'node:fs'
import path from 'node:path'
import { getNitroFilesRoot } from '@/lib/services/furni-asset-dirs'
import type { HabboItFurniEntry } from '@/lib/services/habbo-furnidata-cache'
import { siteSettings } from '@/lib/services/site-settings'
import type { FurniMetadata } from '@/lib/services/swf-to-nitro'
const LOCK_STALE_MS = 60_000;
const LOCK_STALE_MS = 60_000
/**
* Resolve the FurnitureData file path from the admin setting
@@ -14,188 +14,203 @@ const LOCK_STALE_MS = 60_000;
* is unset.
*/
export async function getFurnitureDataPath(): Promise<string> {
const url =
(await siteSettings.get("furni_data_url", "/nitro-assets/config/FurnitureData.json5")) ??
"/nitro-assets/config/FurnitureData.json5";
if (path.isAbsolute(url) && !url.startsWith("/")) return url;
const relative = url.replace(/^\/+/, "");
const url = (await siteSettings.get('furni_data_url', '/nitro-assets/config/FurnitureData.json5')) ?? '/nitro-assets/config/FurnitureData.json5'
if (path.isAbsolute(url) && !url.startsWith('/')) return url
const relative = url.replace(/^\/+/, '')
// The `relative` segment is admin-configurable so its concrete value is
// unknown at build time; without the hint Turbopack traces the entire
// public/ tree (~400k files) into the route's NFT.
return path.join(/*turbopackIgnore: true*/ process.cwd(), "public", relative);
return path.join(/*turbopackIgnore: true*/ process.cwd(), 'public', relative)
}
async function getFurnitureDataWritePaths(): Promise<string[]> {
const primary = await getFurnitureDataPath();
const configuredMirror = (await siteSettings.get("furni_data_mirror_path", "")) ?? "";
const nitroFilesRoot = await getNitroFilesRoot();
const primary = await getFurnitureDataPath()
const configuredMirror = (await siteSettings.get('furni_data_mirror_path', '')) ?? ''
const nitroFilesRoot = await getNitroFilesRoot()
const mirror = configuredMirror.trim()
? configuredMirror
: nitroFilesRoot
? path.join(/*turbopackIgnore: true*/ nitroFilesRoot, "nitro-assets/gamedata/FurnitureData.json")
: "";
? path.join(
/*turbopackIgnore: true*/ nitroFilesRoot,
'nitro-assets/gamedata/FurnitureData.json',
)
: ''
const paths = [primary, mirror].filter(Boolean).map((p) => path.normalize(p));
const seen = new Set<string>();
const paths = [primary, mirror].filter(Boolean).map((p) => path.normalize(p))
const seen = new Set<string>()
return paths.filter((p) => {
const key = process.platform === "win32" ? p.toLowerCase() : p;
if (seen.has(key)) return false;
seen.add(key);
return true;
});
const key = process.platform === 'win32' ? p.toLowerCase() : p
if (seen.has(key)) return false
seen.add(key)
return true
})
}
async function getFurnitureDataReadPath(): Promise<string> {
const paths = await getFurnitureDataWritePaths();
const existing = paths.find((p) => existsSync(/*turbopackIgnore: true*/ p));
return existing ?? paths[0];
const paths = await getFurnitureDataWritePaths()
const existing = paths.find((p) => existsSync(/*turbopackIgnore: true*/ p))
return existing ?? paths[0]
}
// ── FurnitureData.json lock + helpers ────────────────────────────────
let furniDataLock: Promise<void> = Promise.resolve();
let furniDataLock: Promise<void> = Promise.resolve()
async function acquireDiskLock(lockPath: string): Promise<void> {
const deadline = Date.now() + 30_000;
const deadline = Date.now() + 30_000
while (true) {
try {
const fh = await fs.open(lockPath, "wx");
await fh.writeFile(String(process.pid));
await fh.close();
return;
const fh = await fs.open(lockPath, 'wx')
await fh.writeFile(String(process.pid))
await fh.close()
return
} catch (err) {
const e = err as NodeJS.ErrnoException;
if (e.code !== "EEXIST") throw err;
const e = err as NodeJS.ErrnoException
if (e.code !== 'EEXIST') throw err
try {
const stat = await fs.stat(lockPath);
const stat = await fs.stat(lockPath)
if (Date.now() - stat.mtimeMs > LOCK_STALE_MS) {
await fs.unlink(lockPath).catch(() => {});
continue;
await fs.unlink(lockPath).catch(() => {})
continue
}
} catch {
/* lock vanished between checks */
}
if (Date.now() > deadline) throw new Error("FurnitureData lock timeout");
await new Promise((r) => setTimeout(r, 100));
if (Date.now() > deadline) throw new Error('FurnitureData lock timeout')
await new Promise((r) => setTimeout(r, 100))
}
}
}
export async function withFurniDataLock<T>(fn: () => Promise<T>): Promise<T> {
let release: () => void;
let release: () => void
const acquired = new Promise<void>((r) => {
release = r;
});
const prev = furniDataLock;
furniDataLock = acquired;
await prev;
const lockBase = await getFurnitureDataReadPath();
await fs.mkdir(path.dirname(lockBase), { recursive: true });
const lockPath = `${lockBase}.lock`;
await acquireDiskLock(lockPath);
release = r
})
const prev = furniDataLock
furniDataLock = acquired
await prev
const lockBase = await getFurnitureDataReadPath()
await fs.mkdir(path.dirname(lockBase), { recursive: true })
const lockPath = `${lockBase}.lock`
await acquireDiskLock(lockPath)
try {
return await fn();
return await fn()
} finally {
await fs.unlink(lockPath).catch(() => {});
release!();
await fs.unlink(lockPath).catch(() => {})
release!()
}
}
export async function readFurniData(): Promise<Record<string, unknown>> {
const target = await getFurnitureDataReadPath();
const raw = await fs.readFile(/*turbopackIgnore: true*/ target, "utf-8");
return JSON.parse(raw);
const target = await getFurnitureDataReadPath()
const raw = await fs.readFile(/*turbopackIgnore: true*/ target, 'utf-8')
return JSON.parse(raw)
}
export async function writeFurniData(data: Record<string, unknown>): Promise<void> {
const targets = await getFurnitureDataWritePaths();
const payload = JSON.stringify(data);
const targets = await getFurnitureDataWritePaths()
const payload = JSON.stringify(data)
for (const target of targets) {
await fs.mkdir(path.dirname(target), { recursive: true });
const tmp = `${target}.tmp`;
await fs.writeFile(/*turbopackIgnore: true*/ tmp, payload, "utf-8");
await fs.rename(/*turbopackIgnore: true*/ tmp, target);
await fs.mkdir(path.dirname(target), { recursive: true })
const tmp = `${target}.tmp`
await fs.writeFile(/*turbopackIgnore: true*/ tmp, payload, 'utf-8')
await fs.rename(/*turbopackIgnore: true*/ tmp, target)
}
}
export function buildFurniEntry(params: {
id: number;
classname: string;
revision: number;
category: string;
name: string;
description: string;
spriteId: number;
dims: { x: number; y: number; z: number };
metadata: FurniMetadata | null;
habboIt?: HabboItFurniEntry | null;
id: number
classname: string
revision: number
category: string
name: string
description: string
spriteId: number
dims: { x: number; y: number; z: number }
metadata: FurniMetadata | null
habboIt?: HabboItFurniEntry | null
}): Record<string, unknown> {
const { id, classname, revision, category, name, description, spriteId, dims, metadata, habboIt } = params;
const {
id,
classname,
revision,
category,
name,
description,
spriteId,
dims,
metadata,
habboIt,
} = params
// Merge partcolors: prefer habbo.it (has real hex colors), fallback to .nitro extraction
const partcolors = habboIt?.partcolors?.color?.length
? habboIt.partcolors
: (metadata?.partcolors ?? { color: [] });
: (metadata?.partcolors ?? { color: [] })
return {
id,
classname,
revision: revision || habboIt?.revision || 0,
category: category || habboIt?.category || "unknown",
category: category || habboIt?.category || 'unknown',
defaultdir: metadata?.defaultdir ?? habboIt?.defaultdir ?? 0,
xdim: dims.x,
ydim: dims.y,
partcolors,
name,
description: description || "",
adurl: "",
description: description || '',
adurl: '',
offerid: spriteId,
buyout: !!habboIt?.bc,
rentofferid: -1,
rentbuyout: false,
bc: habboIt?.bc ?? false,
excludeddynamic: false,
customparams: habboIt?.customparams ?? "",
customparams: habboIt?.customparams ?? '',
specialtype: metadata?.specialtype ?? habboIt?.specialtype ?? 0,
canstandon: metadata?.canstandon ?? habboIt?.canstandon ?? false,
cansiton: metadata?.cansiton ?? habboIt?.cansiton ?? false,
canlayon: metadata?.canlayon ?? habboIt?.canlayon ?? false,
furniline: habboIt?.furniline ?? "",
environment: habboIt?.environment ?? "",
furniline: habboIt?.furniline ?? '',
environment: habboIt?.environment ?? '',
rare: habboIt?.rare ?? false,
};
}
}
function upsertEntryInSection(
section: { furnitype: Array<Record<string, unknown>> },
entry: Record<string, unknown>,
) {
const classname = entry.classname as string | undefined;
const classname = entry.classname as string | undefined
if (classname) {
const idx = section.furnitype.findIndex((e) => e.classname === classname);
const idx = section.furnitype.findIndex((e) => e.classname === classname)
if (idx >= 0) {
section.furnitype[idx] = entry;
return;
section.furnitype[idx] = entry
return
}
}
section.furnitype.push(entry);
section.furnitype.push(entry)
}
export async function appendFurniEntry(entry: Record<string, unknown>, itemType: string): Promise<void> {
export async function appendFurniEntry(
entry: Record<string, unknown>,
itemType: string,
): Promise<void> {
await withFurniDataLock(async () => {
const furniData = (await readFurniData()) as Record<
string,
{ furnitype: Array<Record<string, unknown>> }
>;
if (itemType === "i") {
if (!furniData.wallitemtypes) furniData.wallitemtypes = { furnitype: [] };
upsertEntryInSection(furniData.wallitemtypes, entry);
>
if (itemType === 'i') {
if (!furniData.wallitemtypes) furniData.wallitemtypes = { furnitype: [] }
upsertEntryInSection(furniData.wallitemtypes, entry)
} else {
if (!furniData.roomitemtypes) furniData.roomitemtypes = { furnitype: [] };
upsertEntryInSection(furniData.roomitemtypes, entry);
if (!furniData.roomitemtypes) furniData.roomitemtypes = { furnitype: [] }
upsertEntryInSection(furniData.roomitemtypes, entry)
}
await writeFurniData(furniData as Record<string, unknown>);
});
await writeFurniData(furniData as Record<string, unknown>)
})
}
export async function removeFurniEntry(classname: string): Promise<boolean> {
@@ -203,38 +218,46 @@ export async function removeFurniEntry(classname: string): Promise<boolean> {
const furniData = (await readFurniData()) as Record<
string,
{ furnitype: Array<Record<string, unknown>> }
>;
let removed = false;
>
let removed = false
for (const section of ["roomitemtypes", "wallitemtypes"] as const) {
for (const section of ['roomitemtypes', 'wallitemtypes'] as const) {
if (furniData[section]?.furnitype) {
const before = furniData[section].furnitype.length;
furniData[section].furnitype = furniData[section].furnitype.filter((e) => e.classname !== classname);
if (furniData[section].furnitype.length < before) removed = true;
const before = furniData[section].furnitype.length
furniData[section].furnitype = furniData[section].furnitype.filter(
(e) => e.classname !== classname,
)
if (furniData[section].furnitype.length < before) removed = true
}
}
if (removed) {
await writeFurniData(furniData as Record<string, unknown>);
await writeFurniData(furniData as Record<string, unknown>)
}
return removed;
});
return removed
})
}
export async function appendFurniEntriesBatch(
entries: Array<{ entry: Record<string, unknown>; itemType: string }>,
): Promise<void> {
await withFurniDataLock(async () => {
const furniData = (await readFurniData()) as Record<string, { furnitype: unknown[] }>;
const furniData = (await readFurniData()) as Record<string, { furnitype: unknown[] }>
for (const { entry, itemType } of entries) {
if (itemType === "i") {
if (!furniData.wallitemtypes) furniData.wallitemtypes = { furnitype: [] };
upsertEntryInSection(furniData.wallitemtypes as { furnitype: Array<Record<string, unknown>> }, entry);
if (itemType === 'i') {
if (!furniData.wallitemtypes) furniData.wallitemtypes = { furnitype: [] }
upsertEntryInSection(
furniData.wallitemtypes as { furnitype: Array<Record<string, unknown>> },
entry,
)
} else {
if (!furniData.roomitemtypes) furniData.roomitemtypes = { furnitype: [] };
upsertEntryInSection(furniData.roomitemtypes as { furnitype: Array<Record<string, unknown>> }, entry);
if (!furniData.roomitemtypes) furniData.roomitemtypes = { furnitype: [] }
upsertEntryInSection(
furniData.roomitemtypes as { furnitype: Array<Record<string, unknown>> },
entry,
)
}
}
await writeFurniData(furniData as Record<string, unknown>);
});
await writeFurniData(furniData as Record<string, unknown>)
})
}