UNPKG

nuxt

Version:

Nuxt is a free and open-source framework with an intuitive and extendable way to create type-safe, performant and production-grade full-stack web applications and websites with Vue.js.

131 lines (130 loc) 4.73 kB
import { computed, reactive, toValue, watch } from "vue"; import { hash } from "ohash"; import { isPlainObject } from "@vue/shared"; import { useRequestFetch } from "./ssr.js"; import { useAsyncData } from "./asyncData.js"; import { defineKeyedFunctionFactory } from "../../compiler/runtime"; import { alwaysRunFetchOnKeyChange, fetchDefaults } from "#build/nuxt.config.mjs"; function generateOptionSegments(opts) { const segments = [ toValue(opts.method)?.toUpperCase() || "GET", toValue(opts.baseURL) ]; for (const _obj of [opts.query || opts.params]) { const obj = toValue(_obj); if (!obj) { continue; } const unwrapped = {}; for (const [key, value] of Object.entries(obj)) { unwrapped[toValue(key)] = toValue(value); } segments.push(unwrapped); } if (opts.body) { const value = toValue(opts.body); if (!value) { segments.push(hash(value)); } else if (value instanceof ArrayBuffer) { segments.push(hash(Object.fromEntries([...new Uint8Array(value).entries()].map(([k, v]) => [k, v.toString()])))); } else if (value instanceof FormData) { const entries = []; for (const entry of value.entries()) { const [key, val] = entry; entries.push([key, val instanceof File ? `${val.name}:${val.size}:${val.lastModified}` : val]); } segments.push(hash(entries)); } else if (isPlainObject(value)) { segments.push(hash(reactive(value))); } else { try { segments.push(hash(value)); } catch { console.warn("[useFetch] Failed to hash body", value); } } } return segments; } export const createUseFetch = defineKeyedFunctionFactory({ name: "createUseFetch", factory(options = {}) { function useFetch2(request, arg1, arg2) { const [opts = {}, autoKey] = typeof arg1 === "string" ? [{}, arg1] : [arg1, arg2]; const factoryOptions = typeof options === "function" ? options(opts) : options; const { server, lazy, default: defaultFn, transform, pick, watch: watchSources, immediate, getCachedData, deep, dedupe, timeout, ...fetchOptions } = { ...typeof options === "function" ? {} : factoryOptions, ...opts, ...typeof options === "function" ? factoryOptions : {} }; const _request = computed(() => toValue(request)); const key = computed(() => toValue(fetchOptions.key) || "$f" + hash([autoKey, typeof _request.value === "string" ? _request.value : "", ...generateOptionSegments(fetchOptions)])); if (!fetchOptions.baseURL && typeof _request.value === "string" && (_request.value[0] === "/" && _request.value[1] === "/")) { throw new Error('[nuxt] [useFetch] the request URL must not start with "//".'); } const _fetchOptions = reactive({ ...fetchDefaults, ...fetchOptions, cache: typeof fetchOptions.cache === "boolean" ? void 0 : fetchOptions.cache }); const _asyncDataOptions = { server, lazy, default: defaultFn, transform, pick, immediate, getCachedData, deep, dedupe, timeout, watch: watchSources === false ? [] : [...watchSources || [], _fetchOptions] }; if (import.meta.dev) { _asyncDataOptions._functionName ||= factoryOptions._functionName || "useFetch"; } if (watchSources === false) { ; _asyncDataOptions._keyTriggersExecute = false; } if (alwaysRunFetchOnKeyChange && !immediate) { let setImmediate = function() { _asyncDataOptions.immediate = true; }; watch(key, setImmediate, { flush: "sync", once: true }); watch([...watchSources || [], _fetchOptions], setImmediate, { flush: "sync", once: true }); } const asyncData = useAsyncData(key, (_, { signal }) => { let _$fetch = fetchOptions.$fetch || globalThis.$fetch; if (import.meta.server && !fetchOptions.$fetch) { const isLocalFetch = typeof _request.value === "string" && _request.value[0] === "/" && (!toValue(fetchOptions.baseURL) || toValue(fetchOptions.baseURL)[0] === "/"); if (isLocalFetch) { _$fetch = useRequestFetch(); } } return _$fetch(_request.value, { signal, ..._fetchOptions }); }, _asyncDataOptions); return asyncData; } return useFetch2; } }); export const useFetch = createUseFetch.__nuxt_factory(); export const useLazyFetch = createUseFetch.__nuxt_factory({ lazy: true, // @ts-expect-error private property _functionName: "useLazyFetch" });