UNPKG

nuxt-surrealdb

Version:

A Nuxt module aimed to simplify the use of SurrealDB

102 lines (101 loc) 3.26 kB
import { computed, reactive, toValue } from "vue"; import { hash } from "ohash"; import { useAsyncData, useNuxtApp, useSurrealPreset } from "#imports"; import { surrealFetchOptionsOverride } from "#surrealdb/utils/overrides"; export function useSurrealFetch(request, arg1, arg2) { const { $surrealFetch } = useNuxtApp(); const [opts = {}, autoKey] = typeof arg1 === "string" ? [{}, arg1] : [arg1, arg2]; const _request = computed(() => toValue(request)); const _key = opts.key || hash([autoKey, typeof _request.value === "string" ? _request.value : "", ...generateOptionSegments(opts)]); if (!_key || typeof _key !== "string") { throw new TypeError("[nuxt] [useSurrealFetch] key must be a string: " + _key); } if (!request) { throw new Error("[nuxt] [useSurrealFetch] request is missing."); } const key = _key === autoKey ? "$d" + _key : _key; if (!opts.baseURL && typeof _request.value === "string" && (_request.value[0] === "/" && _request.value[1] === "/")) { throw new Error('[nuxt] [useSurrealFetch] the request URL must not start with "//".'); } const { // AsyncData server, lazy, default: defaultFn, transform, pick, watch, immediate, getCachedData, deep, dedupe, // custom database, token, // $fetch ...fetchOptions } = opts; const _fetchOptions = reactive({ ...fetchOptions, cache: typeof opts.cache === "boolean" ? void 0 : opts.cache }); if (database || token) { const db = reactive({ database, token }); const _database = useSurrealPreset(db); _fetchOptions.baseURL ||= _database.host; _fetchOptions.headers = { ...surrealFetchOptionsOverride(_database).headers }; } const _asyncDataOptions = { server, lazy, default: defaultFn, transform, pick, immediate, getCachedData, deep, dedupe, watch: watch === false ? [] : [_fetchOptions, _request, ...watch || []] }; if (import.meta.dev && import.meta.client) { _asyncDataOptions._functionName = opts._functionName || "useSurrealFetch"; } let controller; const asyncData = useAsyncData(key, () => { controller?.abort?.("Request aborted as another request to the same endpoint was initiated."); controller = typeof AbortController !== "undefined" ? new AbortController() : {}; const timeoutLength = toValue(opts.timeout); let timeoutId; if (timeoutLength) { timeoutId = setTimeout(() => controller.abort("Request aborted due to timeout."), timeoutLength); controller.signal.onabort = () => clearTimeout(timeoutId); } return $surrealFetch(_request.value, { signal: controller.signal, ..._fetchOptions }).finally(() => { clearTimeout(timeoutId); }); }, _asyncDataOptions); return asyncData; } function generateOptionSegments(opts) { const segments = [ toValue(opts.method)?.toUpperCase() || "GET", toValue(opts.baseURL) ]; for (const _obj of [opts.params || opts.query]) { 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); } return segments; }