feat(housekeeping): integrate studio operations
CI / check (pull_request) Successful in 38s
CI / release (pull_request) Skipped
CI / deploy (pull_request) Skipped

This commit is contained in:
Simo committed 2026-08-30 15:29:58 +02:00
1 parent 020c06f172
commit 2e95a106e0
36 files changed
+2296 -60

No files matched your search

+14 -3
View File
@@ -134,13 +134,16 @@ async function fetchWithFallback(url: string): Promise<string> {
export async function fetchSourceFurnidata(
url: string,
now = Date.now(),
signal?: AbortSignal,
): Promise<SourceFurni[]> {
signal?.throwIfAborted();
const hit = cache.get(url);
if (hit && now && now - hit.ts < TTL) return hit.list;
let body: string;
try {
const timeout = AbortSignal.timeout(30000);
const res = await fetch(url, {
signal: AbortSignal.timeout(30000),
signal: signal ? AbortSignal.any([signal, timeout]) : timeout,
headers: browserHeaders(),
});
if (res.ok) {
@@ -159,7 +162,8 @@ export async function fetchSourceFurnidata(
} else {
body = await fetchWithFallback(url);
}
} catch {
} catch (error) {
if (signal?.aborted) throw error;
body = await fetchWithFallback(url);
}
if (body.trimStart().startsWith("<")) {
@@ -243,11 +247,13 @@ export async function cloneSingleFurni(params: {
source: CloneSource;
entry: SourceFurni;
onProgress?: (status: string) => void;
signal?: AbortSignal;
/** Skip the per-item FurnitureData.json write and return the entry instead,
* so batch callers can append everything in one lock + write cycle. */
deferFurniData?: boolean;
}): Promise<CloneResult> {
const { source, entry, onProgress, deferFurniData } = params;
const { source, entry, onProgress, signal, deferFurniData } = params;
signal?.throwIfAborted();
const { classname, itemType } = entry;
const warnings: string[] = [];
@@ -287,6 +293,7 @@ export async function cloneSingleFurni(params: {
// Download .nitro + icon directly from the source hotel.
onProgress?.("downloading");
signal?.throwIfAborted();
const nitroPath = getRuntimePath(
/*turbopackIgnore: true*/ nitroDir,
`${classname}.nitro`,
@@ -300,6 +307,7 @@ export async function cloneSingleFurni(params: {
nitroPath,
{
maxRetries: 2,
signal,
},
);
if (!dl.ok) {
@@ -334,6 +342,7 @@ export async function cloneSingleFurni(params: {
{
maxRetries: 1,
validate: "png",
signal,
},
);
if (!iconDl.ok) {
@@ -366,6 +375,7 @@ export async function cloneSingleFurni(params: {
}
onProgress?.("writing_db");
signal?.throwIfAborted();
const stackHeight =
entry.canlayon || entry.cansiton ? 1.0 : entry.canstandon ? 1.0 : 0.0;
// allow_stack: derived from stackHeight (mirrors furni-import.ts `dims.z > 0`).
@@ -422,6 +432,7 @@ export async function cloneSingleFurni(params: {
// AND our offerid. The source's offerid points at the source hotel's sprite
// ids, which would silently break the emulator's catalog offer lookup.
onProgress?.("writing_furnidata");
signal?.throwIfAborted();
const furniDataEntry = {
...entry,
id: newId,