@fine-dev/fine-js
Version:
Javascript client for Fine BaaS
227 lines • 8.57 kB
JavaScript
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