UNPKG

@fine-dev/fine-js

Version:

Javascript client for Fine BaaS

227 lines 8.57 kB
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } return new (P || (P = Promise))(function (resolve, reject) { function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } step((generator = generator.apply(thisArg, _arguments || [])).next()); }); }; import { useCallback, useEffect, useState } from "react"; // Helper functions for hooks /** Take a value and return it unchanged */ const fallthrough = (value) => value; /** Take an unknown error value and return it as an `Error` */ const parseError = (error) => { if (error instanceof Error) return error; if (typeof error === "string") return new Error(error); if (typeof error === "object") return new Error(JSON.stringify(error)); return new Error("Unknown error"); }; function handleHookError(error, setState) { const parsedError = parseError(error); setState((state) => { const newState = Object.assign(Object.assign({}, state), { error: parsedError }); if ("isLoading" in state) newState.isLoading = false; return newState; }); return parsedError; } function handleMutation(builder, setState) { return __awaiter(this, void 0, void 0, function* () { try { if (!builder) return; setState((state) => (Object.assign(Object.assign({}, state), { error: null, isLoading: true }))); const result = yield builder; setState((state) => (Object.assign(Object.assign({}, state), { error: null, isLoading: false }))); return result; } catch (error) { return handleHookError(error, setState); } }); } export default class D1RestClient { constructor({ baseUrl, headers = {}, fetch: customFetch }) { this.baseUrl = baseUrl.endsWith("/") ? baseUrl.slice(0, -1) : baseUrl; this.headers = headers; this.fetch = customFetch !== null && customFetch !== void 0 ? customFetch : fetch.bind(window); } table(tableName) { const url = new URL(`${this.baseUrl}/tables/${tableName}`); return new D1QueryBuilder(url, { headers: this.headers, fetch: this.fetch }); } useQuery(tableName, builderFn = fallthrough) { const [state, setState] = useState({ data: null, error: null, isLoading: true }); const builder = builderFn(this.table(tableName).select()); const builderUrl = builder === null || builder === void 0 ? void 0 : builder.url.toString(); // Use the builder URL as a dependency for re-fetching const fetchData = useCallback(() => __awaiter(this, void 0, void 0, function* () { try { if (!builder) return; setState({ data: null, error: null, isLoading: true }); const data = yield builder; setState({ data, error: null, isLoading: false }); } catch (error) { handleHookError(error, setState); } }), [tableName, builderUrl]); useEffect(() => { fetchData(); }, [fetchData]); return Object.assign(Object.assign({}, state), { refetch: fetchData }); } useInsert(tableName) { const [state, setState] = this.useMutationState(); const insert = useCallback((values, returns) => __awaiter(this, void 0, void 0, function* () { let builder = this.table(tableName).insert(values); if (returns) builder = builder.select(returns); return (yield handleMutation(builder, setState)); }), [tableName]); return Object.assign(Object.assign({}, state), { insert }); } useUpdate(tableName) { const [state, setState] = this.useMutationState(); const update = useCallback((values_1, ...args_1) => __awaiter(this, [values_1, ...args_1], void 0, function* (values, builderFn = fallthrough) { return yield handleMutation(builderFn(this.table(tableName).update(values)), setState); }), [tableName]); return Object.assign(Object.assign({}, state), { update }); } useDelete(tableName) { const [state, setState] = this.useMutationState(); const deleteRecord = useCallback((builderFn) => __awaiter(this, void 0, void 0, function* () { return yield handleMutation(builderFn(this.table(tableName).delete()), setState); }), [tableName]); return Object.assign(Object.assign({}, state), { deleteRecord }); } useMutationState() { return useState({ error: null, isLoading: false }); } } class D1QueryBuilder { constructor(url, { headers = {}, fetch }) { this.url = url; this.headers = headers; this.fetch = fetch; } select(query = "*") { this.url.searchParams.set("select", query); return new D1FilterBuilder({ url: this.url, headers: this.headers, fetch: this.fetch, method: "GET" }); } insert(values) { return new D1FilterBuilder({ url: this.url, headers: this.headers, fetch: this.fetch, method: "POST", body: values }); } update(values) { return new D1FilterBuilder({ url: this.url, headers: this.headers, fetch: this.fetch, method: "PATCH", body: { data: values } }); } delete() { return new D1FilterBuilder({ url: this.url, headers: this.headers, fetch: this.fetch, method: "DELETE" }); } } class D1FilterBuilder { constructor({ url, headers, fetch, method, body }) { this.url = new URL(url); this.headers = Object.assign({}, headers); if (method !== "GET") { if (this.headers instanceof Headers) this.headers.set("Content-Type", "application/json"); else if (Array.isArray(this.headers)) this.headers.push(["Content-Type", "application/json"]); else this.headers["Content-Type"] = "application/json"; } this.fetch = fetch; this.method = method; this.body = body; } eq(column, value) { this.url.searchParams.append(column, `eq.${value}`); return this; } neq(column, value) { this.url.searchParams.append(column, `neq.${value}`); return this; } gt(column, value) { this.url.searchParams.append(column, `gt.${value}`); return this; } lt(column, value) { this.url.searchParams.append(column, `lt.${value}`); return this; } like(column, pattern) { this.url.searchParams.append(column, `like.${pattern}`); return this; } in(column, values) { this.url.searchParams.append(column, `in.(${values.join(",")})`); return this; } order(column, { ascending = true } = {}) { this.url.searchParams.append("order", `${column}.${ascending ? "asc" : "desc"}`); return this; } limit(count) { this.url.searchParams.append("limit", count.toString()); return this; } offset(count) { this.url.searchParams.append("offset", count.toString()); return this; } select(query = "*") { this.url.searchParams.set("select", query); return this; } then(resolve, reject) { return this.fetch(this.url.toString(), { method: this.method, headers: this.headers, credentials: "include", body: this.body ? JSON.stringify(this.body) : undefined }) .then((res) => __awaiter(this, void 0, void 0, function* () { if (res.status === 204 || res.status === 304) return []; else if (!res.ok) throw new Error(yield res.text()); return res.json(); })) .then(resolve, reject); } } //# sourceMappingURL=d1.js.map