let cachedNativeModule = null; let triedLoad = false; let loadError = null; let moduleSource = "none"; function shouldRetryNativeLoad() { return ( !cachedNativeModule && triedLoad && typeof globalThis.__stBmeLoadRustWasmLayout === "function" ); } export function resetNativeModuleStatus() { cachedNativeModule = null; triedLoad = false; loadError = null; moduleSource = "none"; } async function resolveWasmModuleInput(wasmUrl) { if ( wasmUrl && typeof wasmUrl === "object" && wasmUrl.protocol === "file:" && typeof process === "object" && process?.versions?.node ) { const { readFile } = await import("node:fs/promises"); return readFile(wasmUrl); } return wasmUrl; } async function initializeWasmModule(initFn, wasmUrl) { if (typeof initFn !== "function") { return; } const moduleInput = await resolveWasmModuleInput(wasmUrl); try { await initFn({ module_or_path: moduleInput }); } catch (error) { if ( error && typeof error.message === "string" && /module_or_path|unexpected|invalid/i.test(error.message) ) { await initFn(moduleInput); return; } throw error; } } async function loadFromWasmPackArtifacts() { const module = await import("./pkg/stbme_core_pkg.js"); if (!module || typeof module.solve_layout !== "function") { throw new Error("invalid wasm-pack module shape"); } const wasmUrl = new URL("./pkg/stbme_core_pkg_bg.wasm", import.meta.url); if (typeof module.default === "function") { await initializeWasmModule(module.default, wasmUrl); } else if (typeof module.__wbg_init === "function") { await initializeWasmModule(module.__wbg_init, wasmUrl); } return { solve_layout: module.solve_layout, build_hydrate_records: typeof module.build_hydrate_records === "function" ? module.build_hydrate_records : null, build_hydrate_records_compact: typeof module.build_hydrate_records_compact === "function" ? module.build_hydrate_records_compact : null, build_persist_delta_compact_hash: typeof module.build_persist_delta_compact_hash === "function" ? module.build_persist_delta_compact_hash : null, build_persist_delta_compact: typeof module.build_persist_delta_compact === "function" ? module.build_persist_delta_compact : null, build_persist_delta: typeof module.build_persist_delta === "function" ? module.build_persist_delta : null, }; } async function loadNativeModule(options = {}) { if (cachedNativeModule) return cachedNativeModule; if (triedLoad && !(options?.forceRetry === true || shouldRetryNativeLoad())) { throw loadError || new Error("stbme_core native module unavailable"); } if (triedLoad && (options?.forceRetry === true || shouldRetryNativeLoad())) { triedLoad = false; loadError = null; moduleSource = "none"; } triedLoad = true; let wasmPackError = null; if (globalThis.__stBmeDisableWasmPackArtifacts !== true) { try { const wasmPackModule = await loadFromWasmPackArtifacts(); cachedNativeModule = wasmPackModule; moduleSource = "wasm-pack-artifact"; return cachedNativeModule; } catch (error) { wasmPackError = error instanceof Error ? error : new Error(String(error)); } } else { wasmPackError = new Error("wasm-pack artifact loading disabled"); } if (typeof globalThis.__stBmeLoadRustWasmLayout === "function") { try { const module = await globalThis.__stBmeLoadRustWasmLayout(); if (module && typeof module.solve_layout === "function") { cachedNativeModule = module; moduleSource = "global-loader"; return cachedNativeModule; } loadError = new Error("invalid native module shape"); throw loadError; } catch (error) { loadError = error instanceof Error ? error : new Error(String(error)); throw loadError; } } loadError = new Error( [ "Rust/WASM artifact is not initialized", wasmPackError ? `wasm-pack load error: ${wasmPackError.message}` : "", "define globalThis.__stBmeLoadRustWasmLayout for fallback injection", ] .filter(Boolean) .join("; "), ); throw loadError; } function toFloat32Array(value) { if (value instanceof Float32Array) return value; if (!Array.isArray(value)) return new Float32Array(0); return Float32Array.from(value.map((item) => Number(item) || 0)); } export async function solveLayout(payload) { const module = await loadNativeModule(); const raw = await module.solve_layout(payload); const normalizedResult = raw && typeof raw === "object" ? raw : {}; const positions = toFloat32Array(normalizedResult.positions); return { ok: normalizedResult.ok === true, usedNative: true, positions, diagnostics: normalizedResult.diagnostics && typeof normalizedResult.diagnostics === "object" ? normalizedResult.diagnostics : { solver: "rust-wasm", nodeCount: Math.floor(positions.length / 2), edgeCount: 0, iterations: 0, }, }; } export async function installNativePersistDeltaHook() { const module = await loadNativeModule({ forceRetry: shouldRetryNativeLoad(), }); if ( !module || (typeof module.build_persist_delta_compact_hash !== "function" && typeof module.build_persist_delta_compact !== "function" && typeof module.build_persist_delta !== "function") ) { throw new Error("native persist delta builder unavailable"); } globalThis.__stBmeNativeBuildPersistDelta = (beforeSnapshot, afterSnapshot, options = {}) => { let raw = null; const preparedInput = options?.preparedDeltaInput && typeof options.preparedDeltaInput === "object" ? options.preparedDeltaInput : null; const preparedBridgeMode = String(preparedInput?.bridgeMode || "") .trim() .toLowerCase(); if ( typeof module.build_persist_delta_compact_hash === "function" && preparedInput && preparedBridgeMode === "hash" ) { raw = module.build_persist_delta_compact_hash(preparedInput); } else if ( typeof module.build_persist_delta_compact === "function" && preparedInput && (preparedBridgeMode === "json" || preparedBridgeMode === "") ) { raw = module.build_persist_delta_compact(preparedInput); } else if ( typeof module.build_persist_delta_compact === "function" && preparedInput && preparedBridgeMode === "hash" && Array.isArray(preparedInput?.afterNodes?.serialized) ) { raw = module.build_persist_delta_compact(preparedInput); } else if (typeof module.build_persist_delta === "function") { raw = module.build_persist_delta({ beforeSnapshot, afterSnapshot, nowMs: options?.nowMs, }); } return raw && typeof raw === "object" ? raw : null; }; return getNativeModuleStatus(); } export async function installNativeHydrateHook() { const module = await loadNativeModule({ forceRetry: shouldRetryNativeLoad(), }); if ( !module || (typeof module.build_hydrate_records !== "function" && typeof module.build_hydrate_records_compact !== "function") ) { throw new Error("native hydrate builder unavailable"); } globalThis.__stBmeNativeHydrateSnapshotRecords = (snapshotView = {}, options = {}) => { const hydratePayload = { nodes: Array.isArray(snapshotView?.nodes) ? snapshotView.nodes : [], edges: Array.isArray(snapshotView?.edges) ? snapshotView.edges : [], recordsNormalized: options?.recordsNormalized === true, preferCompactResult: options?.preferCompactResult !== false, }; const raw = typeof module.build_hydrate_records_compact === "function" && options?.preferCompactResult !== false ? module.build_hydrate_records_compact(hydratePayload) : module.build_hydrate_records(hydratePayload); return raw && typeof raw === "object" ? raw : null; }; return getNativeModuleStatus(); } export function getNativeModuleStatus() { return { loaded: Boolean(cachedNativeModule), attempted: triedLoad, source: moduleSource, error: loadError?.message || "", }; }