nuxt-surrealdb
Version:
A Nuxt module aimed to simplify the use of SurrealDB
102 lines (101 loc) • 3.26 kB
JavaScript
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;
}