one
Version:
One is a new React Framework that makes Vite serve both native and web.
333 lines (332 loc) • 14.3 kB
JavaScript
var __defProp = Object.defineProperty;
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
var __getOwnPropNames = Object.getOwnPropertyNames;
var __hasOwnProp = Object.prototype.hasOwnProperty;
var __export = (target, all) => {
for (var name in all)
__defProp(target, name, { get: all[name], enumerable: !0 });
}, __copyProps = (to, from, except, desc) => {
if (from && typeof from == "object" || typeof from == "function")
for (let key of __getOwnPropNames(from))
!__hasOwnProp.call(to, key) && key !== except && __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
return to;
};
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: !0 }), mod);
var useLoader_exports = {};
__export(useLoader_exports, {
getLoaderTimingHistory: () => getLoaderTimingHistory,
refetchLoader: () => refetchLoader,
refetchMatchLoader: () => refetchMatchLoader,
resetLoaderState: () => resetLoaderState,
useLoader: () => useLoader,
useLoaderState: () => useLoaderState
});
module.exports = __toCommonJS(useLoader_exports);
var import_react = require("react"), import_registry = require("./devtools/registry"), import_hooks = require("./hooks"), import_notFoundState = require("./notFoundState"), import_imperative_api = require("./router/imperative-api"), import_router = require("./router/router"), import_useMatches = require("./useMatches"), import_cleanUrl = require("./utils/cleanUrl"), import_dynamicImport = require("./utils/dynamicImport"), import_weakKey = require("./utils/weakKey"), import_one_server_only = require("./vite/one-server-only");
const loaderTimingHistory = [], MAX_TIMING_HISTORY = 50, recordLoaderTiming = process.env.NODE_ENV === "development" ? (entry) => {
loaderTimingHistory.unshift(entry), loaderTimingHistory.length > MAX_TIMING_HISTORY && loaderTimingHistory.pop(), typeof window < "u" && typeof CustomEvent < "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"
}
})
));
} : void 0;
function getLoaderTimingHistory() {
return loaderTimingHistory;
}
(0, import_registry.registerDevtoolsFunction)("getLoaderTimingHistory", getLoaderTimingHistory);
(0, import_registry.registerDevtoolsFunction)("recordLoaderTiming", recordLoaderTiming);
const loaderState = {}, subscribers = /* @__PURE__ */ new Set();
function updateState(path, updates) {
loaderState[path] = { ...loaderState[path], ...updates }, subscribers.forEach((callback) => {
callback();
});
}
function subscribe(callback) {
return subscribers.add(callback), () => 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) {
const startTime2 = performance.now();
updateState(pathname2, {
state: "loading",
error: null
});
try {
const cacheBust = `${Date.now()}`, loaderJSUrl2 = (0, import_cleanUrl.getLoaderPath)(pathname2, !0, cacheBust), moduleLoadStart2 = performance.now(), module2 = await (0, import_dynamicImport.dynamicImport)(loaderJSUrl2)?.catch(() => null), moduleLoadTime2 = performance.now() - moduleLoadStart2;
if (!module2?.loader) {
updateState(pathname2, {
data: void 0,
state: "idle",
hasLoadedOnce: !0
});
return;
}
const executionStart2 = performance.now(), result2 = await module2.loader(), executionTime2 = performance.now() - executionStart2, totalTime2 = performance.now() - startTime2;
if (result2?.__oneRedirect) {
recordLoaderTiming?.({
path: pathname2,
startTime: startTime2,
moduleLoadTime: moduleLoadTime2,
executionTime: executionTime2,
totalTime: totalTime2,
source: "refetch"
}), updateState(pathname2, {
data: void 0,
state: "idle",
hasLoadedOnce: !0
}), import_imperative_api.router.replace(result2.__oneRedirect);
return;
}
if (result2?.__oneError === 404) {
recordLoaderTiming?.({
path: pathname2,
startTime: startTime2,
moduleLoadTime: moduleLoadTime2,
executionTime: executionTime2,
totalTime: totalTime2,
source: "refetch"
});
const notFoundRoute = (0, import_notFoundState.findNearestNotFoundRoute)(pathname2, import_router.routeNode);
(0, import_notFoundState.setNotFoundState)({
notFoundPath: result2.__oneNotFoundPath || "/+not-found",
notFoundRouteNode: notFoundRoute || void 0,
originalPath: pathname2
});
return;
}
updateState(pathname2, {
data: result2,
state: "idle",
timestamp: Date.now(),
hasLoadedOnce: !0
});
const currentMatches = (0, import_useMatches.getClientMatchesSnapshot)(), pageMatch = currentMatches[currentMatches.length - 1], normalizedPathname = pathname2.replace(/\/$/, "") || "/", normalizedMatchPathname = (pageMatch?.pathname || "").replace(/\/$/, "") || "/";
pageMatch && normalizedMatchPathname === normalizedPathname && (0, import_useMatches.updateMatchLoaderData)(pageMatch.routeId, result2), recordLoaderTiming?.({
path: pathname2,
startTime: startTime2,
moduleLoadTime: moduleLoadTime2,
executionTime: executionTime2,
totalTime: totalTime2,
source: "refetch"
});
} catch (err) {
const totalTime2 = performance.now() - startTime2;
throw updateState(pathname2, {
error: err,
state: "idle"
}), recordLoaderTiming?.({
path: pathname2,
startTime: startTime2,
totalTime: totalTime2,
error: err instanceof Error ? err.message : String(err),
source: "refetch"
}), err;
}
}
process.env.NODE_ENV === "development" && typeof window < "u" && (window.__oneRefetchLoader = refetchLoader);
async function refetchMatchLoader(routeId, currentPath2) {
const cacheBust = `${Date.now()}`, loaderJSUrl2 = (0, import_cleanUrl.getLoaderPath)(currentPath2, !0, cacheBust), module2 = await (0, import_dynamicImport.dynamicImport)(loaderJSUrl2)?.catch(() => null);
if (!module2?.loader) return;
const result2 = await module2.loader();
result2?.__oneRedirect || result2?.__oneError || (0, import_useMatches.updateMatchLoaderData)(routeId, result2);
}
function useLoaderState(loader) {
const {
loaderProps: loaderPropsFromServerContext,
loaderData: loaderDataFromServerContext
} = (0, import_one_server_only.useServerContext)() || {}, params = (0, import_hooks.useParams)(), pathname = (0, import_hooks.usePathname)(), currentPath = pathname.replace(/\/index$/, "").replace(/\/$/, "") || "/";
if (typeof window > "u" && loader)
return { data: useAsyncFn(
loader,
loaderPropsFromServerContext || {
path: pathname,
params
}
), refetch: async () => {
}, state: "idle" };
const matchRouteId = loader ? (() => {
const result2 = loader();
return typeof result2 == "string" && result2.startsWith("./") ? result2 : null;
})() : null, clientMatches = (0, import_react.useSyncExternalStore)(
import_useMatches.subscribeToClientMatches,
import_useMatches.getClientMatchesSnapshot,
import_useMatches.getClientMatchesSnapshot
), serverContextPath = loaderPropsFromServerContext?.path, preloadedData = serverContextPath === currentPath ? loaderDataFromServerContext : void 0, loaderStateEntry = (0, import_react.useSyncExternalStore)(
subscribe,
() => getLoaderState(currentPath, preloadedData),
() => getLoaderState(currentPath, preloadedData)
), refetch = (0, import_react.useCallback)(() => refetchLoader(currentPath), [currentPath]);
if (matchRouteId) {
const match = clientMatches.find((m) => m.routeId === matchRouteId), isPageMatch = clientMatches.length > 0 && clientMatches[clientMatches.length - 1]?.routeId === matchRouteId, matchPathNormalized = (match?.pathname || "").replace(/\/$/, "") || "/", matchPathFresh = !isPageMatch || matchPathNormalized === currentPath;
if (match && match.loaderData != null && matchPathFresh)
return {
data: match.loaderData,
// refetch updates both loaderState (for useLoaderState() consumers without a loader)
// and the match entry (for this component and useMatches consumers)
refetch: async () => {
await refetchLoader(currentPath);
const fresh = loaderState[currentPath];
fresh?.data != null && (0, import_useMatches.updateMatchLoaderData)(matchRouteId, fresh.data);
},
state: loaderStateEntry.state
};
}
if (!loader)
return {
refetch,
state: loaderStateEntry.state
};
if (!loaderStateEntry.data && !loaderStateEntry.promise && !loaderStateEntry.hasLoadedOnce && loader) {
const resolvedPreloadData = import_router.preloadedLoaderData[currentPath];
if (resolvedPreloadData != null)
delete import_router.preloadedLoaderData[currentPath], delete import_router.preloadingLoader[currentPath], loaderStateEntry.data = resolvedPreloadData, loaderStateEntry.hasLoadedOnce = !0;
else if (import_router.preloadingLoader[currentPath]) {
const promise2 = import_router.preloadingLoader[currentPath].then((val) => {
delete import_router.preloadingLoader[currentPath], delete import_router.preloadedLoaderData[currentPath], val != null ? updateState(currentPath, {
data: val,
hasLoadedOnce: !0,
promise: void 0
}) : updateState(currentPath, {
promise: void 0
});
}).catch((err) => {
console.error("Error running loader()", err), delete import_router.preloadingLoader[currentPath], updateState(currentPath, {
error: err,
promise: void 0
});
});
loaderStateEntry.promise = promise2;
} else {
const loadData = async () => {
const startTime = performance.now();
try {
const loaderJSUrl = (0, import_cleanUrl.getLoaderPath)(currentPath, !0), moduleLoadStart = performance.now(), module = await (0, import_dynamicImport.dynamicImport)(loaderJSUrl)?.catch(() => null), moduleLoadTime = performance.now() - moduleLoadStart;
if (!module?.loader) {
updateState(currentPath, {
data: void 0,
hasLoadedOnce: !0,
promise: void 0
});
return;
}
const executionStart = performance.now(), result = await module.loader(), executionTime = performance.now() - executionStart, totalTime = performance.now() - startTime;
if (result?.__oneRedirect) {
recordLoaderTiming?.({
path: currentPath,
startTime,
moduleLoadTime,
executionTime,
totalTime,
source: "initial"
}), updateState(currentPath, {
data: void 0,
hasLoadedOnce: !0,
promise: void 0
}), import_imperative_api.router.replace(result.__oneRedirect);
return;
}
if (result?.__oneError === 404) {
recordLoaderTiming?.({
path: currentPath,
startTime,
moduleLoadTime,
executionTime,
totalTime,
source: "initial"
});
const notFoundRoute = (0, import_notFoundState.findNearestNotFoundRoute)(currentPath, import_router.routeNode);
(0, import_notFoundState.setNotFoundState)({
notFoundPath: result.__oneNotFoundPath || "/+not-found",
notFoundRouteNode: notFoundRoute || void 0,
originalPath: currentPath
});
return;
}
updateState(currentPath, {
data: result,
hasLoadedOnce: !0,
promise: void 0
}), recordLoaderTiming?.({
path: currentPath,
startTime,
moduleLoadTime,
executionTime,
totalTime,
source: "initial"
});
} catch (err) {
const totalTime2 = performance.now() - startTime;
updateState(currentPath, {
error: err,
promise: void 0
}), recordLoaderTiming?.({
path: currentPath,
startTime,
totalTime: totalTime2,
error: err instanceof 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) {
const { data: data2 } = useLoaderState(loader2);
return data2;
}
const results = /* @__PURE__ */ new Map(), started = /* @__PURE__ */ new Map();
function resetLoaderState() {
results.clear(), started.clear();
}
function useAsyncFn(val, props) {
const key = (val ? (0, import_weakKey.weakKey)(val) : "") + JSON.stringify(props);
if (val && !started.get(key)) {
started.set(key, !0);
let next = val(props);
next instanceof Promise && (next = next.then((final) => {
results.set(key, final);
}).catch((err) => {
console.error("Error running loader()", err), results.set(key, void 0);
})), results.set(key, next);
}
const current = results.get(key);
if (current instanceof Promise)
throw current;
return current;
}
//# sourceMappingURL=useLoader.js.map