UNPKG

one

Version:

One is a new React Framework that makes Vite serve both native and web.

274 lines (273 loc) 10.2 kB
import { useCallback, useSyncExternalStore } from "react"; import { registerDevtoolsFunction } from "./devtools/registry.native.js"; import { useParams, usePathname } from "./hooks.native.js"; import { preloadedLoaderData, preloadingLoader } from "./router/router.native.js"; import { getLoaderPath } from "./utils/cleanUrl.native.js"; import { dynamicImport } from "./utils/dynamicImport.native.js"; import { weakKey } from "./utils/weakKey.native.js"; import { useServerContext } from "./vite/one-server-only.native.js"; function _instanceof(left, right) { return right != null && typeof Symbol < "u" && right[Symbol.hasInstance] ? !!right[Symbol.hasInstance](left) : left instanceof right; } var loaderTimingHistory = [], MAX_TIMING_HISTORY = 50; function recordLoaderTiming(entry) { process.env.NODE_ENV === "development" && (loaderTimingHistory.unshift(entry), loaderTimingHistory.length > MAX_TIMING_HISTORY && loaderTimingHistory.pop(), typeof window < "u" && (window.dispatchEvent(new CustomEvent("one-loader-timing", { detail: entry })), entry.error && window.dispatchEvent(new CustomEvent("one-error", { detail: { error: { message: entry.error, name: "LoaderError" }, route: { pathname: entry.path }, timestamp: Date.now(), type: "loader" } })))); } function getLoaderTimingHistory() { return loaderTimingHistory; } registerDevtoolsFunction("getLoaderTimingHistory", getLoaderTimingHistory); var loaderState = {}, subscribers = /* @__PURE__ */new Set(); function updateState(path, updates) { loaderState[path] = { ...loaderState[path], ...updates }, subscribers.forEach(function (callback) { callback(); }); } function subscribe(callback) { return subscribers.add(callback), function () { return subscribers.delete(callback); }; } function getLoaderState(path, preloadedData2) { return loaderState[path] || (loaderState[path] = { data: preloadedData2, error: void 0, promise: void 0, state: "idle", hasLoadedOnce: !!preloadedData2 }), loaderState[path]; } async function refetchLoader(pathname2) { var startTime2 = performance.now(); updateState(pathname2, { state: "loading", error: null }); try { var cacheBust = `${Date.now()}`, loaderJSUrl2 = getLoaderPath(pathname2, !0, cacheBust), moduleLoadStart2 = performance.now(), module2 = await dynamicImport(loaderJSUrl2), moduleLoadTime2 = performance.now() - moduleLoadStart2, executionStart2 = performance.now(), result2 = await module2.loader(), executionTime2 = performance.now() - executionStart2, totalTime2 = performance.now() - startTime2; updateState(pathname2, { data: result2, state: "idle", timestamp: Date.now(), hasLoadedOnce: !0 }), recordLoaderTiming({ path: pathname2, startTime: startTime2, moduleLoadTime: moduleLoadTime2, executionTime: executionTime2, totalTime: totalTime2, source: "refetch" }); } catch (err) { var totalTime1 = performance.now() - startTime2; throw updateState(pathname2, { error: err, state: "idle" }), recordLoaderTiming({ path: pathname2, startTime: startTime2, totalTime: totalTime1, error: _instanceof(err, Error) ? err.message : String(err), source: "refetch" }), err; } } process.env.NODE_ENV === "development" && typeof window < "u" && (window.__oneRefetchLoader = refetchLoader); function useLoaderState(loader) { var { loaderProps: loaderPropsFromServerContext, loaderData: loaderDataFromServerContext } = useServerContext() || {}, params = useParams(), pathname = usePathname(), currentPath = pathname.replace(/\/index$/, "").replace(/\/$/, "") || "/"; if (typeof window > "u" && loader) { var serverData = useAsyncFn(loader, loaderPropsFromServerContext || { path: pathname, params }); return { data: serverData, refetch: async function () {}, state: "idle" }; } var serverContextPath = loaderPropsFromServerContext?.path, preloadedData = serverContextPath === currentPath ? loaderDataFromServerContext : void 0, loaderStateEntry = useSyncExternalStore(subscribe, function () { return getLoaderState(currentPath, preloadedData); }, function () { return getLoaderState(currentPath, preloadedData); }), refetch = useCallback(function () { return refetchLoader(currentPath); }, [currentPath]); if (!loader) return { refetch, state: loaderStateEntry.state }; if (!loaderStateEntry.data && !loaderStateEntry.promise && !loaderStateEntry.hasLoadedOnce && loader) { var resolvedPreloadData = preloadedLoaderData[currentPath]; if (resolvedPreloadData !== void 0) delete preloadedLoaderData[currentPath], delete preloadingLoader[currentPath], loaderStateEntry.data = resolvedPreloadData, loaderStateEntry.hasLoadedOnce = !0;else if (preloadingLoader[currentPath]) { var preloadPromise = preloadingLoader[currentPath], promise = preloadPromise.then(function (val) { delete preloadingLoader[currentPath], delete preloadedLoaderData[currentPath], updateState(currentPath, { data: val, hasLoadedOnce: !0, promise: void 0 }); }).catch(function (err) { console.error("Error running loader()", err), delete preloadingLoader[currentPath], updateState(currentPath, { error: err, promise: void 0 }); }); loaderStateEntry.promise = promise; } else { var loadData = async function () { var startTime = performance.now(); try { var loaderJSUrl = getLoaderPath(currentPath, !0), nativeLoaderJSUrl = `${loaderJSUrl}?platform=ios`; try { var moduleLoadStart = performance.now(), loaderJsCodeResp = await fetch(nativeLoaderJSUrl); if (!loaderJsCodeResp.ok) throw new Error(`Response not ok: ${loaderJsCodeResp.status}`); var loaderJsCode = await loaderJsCodeResp.text(), result = eval(`() => { var exports = {}; ${loaderJsCode}; return exports; }`)(), moduleLoadTime = performance.now() - moduleLoadStart; if (typeof result.loader != "function") throw new Error("Loader code isn't exporting a `loader` function"); var executionStart = performance.now(), data = await result.loader(), executionTime = performance.now() - executionStart, totalTime = performance.now() - startTime; updateState(currentPath, { data, hasLoadedOnce: !0, promise: void 0 }), recordLoaderTiming({ path: currentPath, startTime, moduleLoadTime, executionTime, totalTime, source: "initial" }); return; } catch (e) { var totalTime = performance.now() - startTime; updateState(currentPath, { data: {}, promise: void 0 }), recordLoaderTiming({ path: currentPath, startTime, totalTime, error: _instanceof(e, Error) ? e.message : String(e), source: "initial" }); return; } var loaderJSUrl = getLoaderPath(currentPath, !0), moduleLoadStart = performance.now(), module = await dynamicImport(loaderJSUrl), moduleLoadTime = performance.now() - moduleLoadStart, executionStart = performance.now(), result = await module.loader(), executionTime = performance.now() - executionStart, totalTime = performance.now() - startTime; updateState(currentPath, { data: result, hasLoadedOnce: !0, promise: void 0 }), recordLoaderTiming({ path: currentPath, startTime, moduleLoadTime, executionTime, totalTime, source: "initial" }); } catch (err) { var totalTime = performance.now() - startTime; updateState(currentPath, { error: err, promise: void 0 }), recordLoaderTiming({ path: currentPath, startTime, totalTime, error: _instanceof(err, Error) ? err.message : String(err), source: "initial" }); } }, promise = loadData(); loaderStateEntry.promise = promise; } } if (loader) { if (loaderStateEntry.error && !loaderStateEntry.hasLoadedOnce) throw loaderStateEntry.error; if (loaderStateEntry.data === void 0 && loaderStateEntry.promise && !loaderStateEntry.hasLoadedOnce) throw loaderStateEntry.promise; return { data: loaderStateEntry.data, refetch, state: loaderStateEntry.state }; } else return { refetch, state: loaderStateEntry.state }; } function useLoader(loader2) { var { data: data2 } = useLoaderState(loader2); return data2; } var results = /* @__PURE__ */new Map(), started = /* @__PURE__ */new Map(); function useAsyncFn(val, props) { var key = (val ? weakKey(val) : "") + JSON.stringify(props); if (val && !started.get(key)) { started.set(key, !0); var next = val(props); _instanceof(next, Promise) && (next = next.then(function (final) { results.set(key, final); }).catch(function (err) { console.error("Error running loader()", err), results.set(key, void 0); })), results.set(key, next); } var current = results.get(key); if (_instanceof(current, Promise)) throw current; return current; } export { getLoaderTimingHistory, refetchLoader, useLoader, useLoaderState }; //# sourceMappingURL=useLoader.native.js.map