mirror of
https://github.com/trailbaseio/trailbase.git
synced 2025-12-30 06:09:48 -06:00
Use URLSearchParams for params construction and fix filter splitting in JS.
This commit is contained in:
@@ -1,14 +1,14 @@
|
||||
# JS/TS Client for TrailBase
|
||||
# TrailBase Client
|
||||
|
||||
TrailBase is a [blazingly](https://trailbase.io/reference/benchmarks/) fast,
|
||||
single-file, open-source application server with type-safe APIs, built-in
|
||||
JS/ES6/TS Runtime, Auth, and Admin UI built on Rust+SQLite+V8.
|
||||
open-source application server with type-safe APIs, built-in JS/ES6/TS Runtime,
|
||||
Auth, and Admin UI built on Rust, SQLite & V8.
|
||||
|
||||
For more context, documentation, and an online demo, check out our website
|
||||
For more context, documentation, and an online demo, check out the website:
|
||||
[trailbase.io](https://trailbase.io).
|
||||
|
||||
This is the first-party client for hooking up your PWA, SPAs and JS backend
|
||||
applications with TrailBase.
|
||||
While we're working on better documentation, an example setup can be found under
|
||||
[`/examples/blog/web`](https://github.com/trailbaseio/trailbase/tree/main/examples/blog/web)
|
||||
in the repository.
|
||||
This is the first-party client for hooking up your web and headless (node.js,
|
||||
deno, ...) apps with TrailBase.
|
||||
While we're working on better documentation, an example web app can be found in
|
||||
the repository under:
|
||||
[`/examples/blog/web`](https://github.com/trailbaseio/trailbase/tree/main/examples/blog/web).
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "trailbase",
|
||||
"description": "Official TrailBase client",
|
||||
"version": "0.1.2",
|
||||
"version": "0.1.3",
|
||||
"license": "OSL-3.0",
|
||||
"type": "module",
|
||||
"main": "./src/index.ts",
|
||||
|
||||
@@ -115,34 +115,33 @@ export class RecordApi {
|
||||
order?: string[];
|
||||
filters?: string[];
|
||||
}): Promise<T[]> {
|
||||
const params: [string, string][] = [];
|
||||
const params = new URLSearchParams();
|
||||
const pagination = opts?.pagination;
|
||||
if (pagination) {
|
||||
const cursor = pagination.cursor;
|
||||
if (cursor) params.push(["cursor", cursor]);
|
||||
if (cursor) params.append("cursor", cursor);
|
||||
|
||||
const limit = pagination.limit;
|
||||
if (limit) params.push(["limit", limit.toString()]);
|
||||
if (limit) params.append("limit", limit.toString());
|
||||
}
|
||||
const order = opts?.order;
|
||||
if (order) params.push(["order", order.join(",")]);
|
||||
if (order) params.append("order", order.join(","));
|
||||
|
||||
const filters = opts?.filters;
|
||||
if (filters) {
|
||||
for (const filter of filters) {
|
||||
const [nameOp, value] = filter.split("=", 2);
|
||||
if (value === undefined) {
|
||||
const pos = filter.indexOf("=");
|
||||
if (pos <= 0) {
|
||||
throw Error(`Filter '${filter}' does not match: 'name[op]=value'`);
|
||||
}
|
||||
params.push([nameOp, value]);
|
||||
const nameOp = filter.slice(0, pos);
|
||||
const value = filter.slice(pos + 1);
|
||||
params.append(nameOp, value);
|
||||
}
|
||||
}
|
||||
|
||||
const queryParams = encodeURI(
|
||||
params.map(([key, value]) => `${key}=${value}`).join("&"),
|
||||
);
|
||||
const response = await this.client.fetch(
|
||||
`${RecordApi._recordApi}/${this.name}?${queryParams}`,
|
||||
`${RecordApi._recordApi}/${this.name}?${params}`,
|
||||
);
|
||||
return (await response.json()) as T[];
|
||||
}
|
||||
|
||||
@@ -71,7 +71,11 @@ test("Record integration tests", async () => {
|
||||
const api = client.records("simple_strict_table");
|
||||
|
||||
const now = new Date().getTime();
|
||||
const messages = [`ts client test 0: ${now}`, `ts client test 1: ${now}`];
|
||||
// Throw in some url characters for good measure.
|
||||
const messages = [
|
||||
`ts client test 1: =?&${now}`,
|
||||
`ts client test 2: =?&${now}`,
|
||||
];
|
||||
|
||||
const ids: string[] = [];
|
||||
for (const msg of messages) {
|
||||
@@ -90,7 +94,7 @@ test("Record integration tests", async () => {
|
||||
|
||||
{
|
||||
const records = await api.list<SimpleStrict>({
|
||||
filters: [`text_not_null[like]=%${now}`],
|
||||
filters: [`text_not_null[like]=% =?&${now}`],
|
||||
order: ["+text_not_null"],
|
||||
});
|
||||
expect(records.map((el) => el.text_not_null)).toStrictEqual(messages);
|
||||
@@ -157,7 +161,7 @@ test("record error tests", async () => {
|
||||
String.fromCharCode.apply(null, uuidParse(uuidv7())),
|
||||
);
|
||||
const nonExistantApi = client.records("non-existant");
|
||||
expect(
|
||||
await expect(
|
||||
async () => await nonExistantApi.read<SimpleStrict>(nonExistantId),
|
||||
).rejects.toThrowError(
|
||||
expect.objectContaining({
|
||||
@@ -166,14 +170,14 @@ test("record error tests", async () => {
|
||||
);
|
||||
|
||||
const api = client.records("simple_strict_table");
|
||||
expect(
|
||||
await expect(
|
||||
async () => await api.read<SimpleStrict>("invalid id"),
|
||||
).rejects.toThrowError(
|
||||
expect.objectContaining({
|
||||
status: status.BAD_REQUEST,
|
||||
}),
|
||||
);
|
||||
expect(
|
||||
await expect(
|
||||
async () => await api.read<SimpleStrict>(nonExistantId),
|
||||
).rejects.toThrowError(
|
||||
expect.objectContaining({
|
||||
|
||||
@@ -25,12 +25,17 @@ function Table() {
|
||||
const [acidity, setAcidity] = useState(8);
|
||||
const [sweetness, setSweetness] = useState(8);
|
||||
|
||||
const [data, setData] = useState<Array<Array<object>> | undefined>();
|
||||
type Record = [string, number, number, number, number];
|
||||
const [data, setData] = useState<Record[]>([]);
|
||||
|
||||
useEffect(() => {
|
||||
const URL = import.meta.env.DEV ? "http://localhost:4000" : "";
|
||||
const params = Object.entries({ aroma, flavor, acidity, sweetness })
|
||||
.map(([k, v]) => `${k}=${v}`)
|
||||
.join("&");
|
||||
const params = new URLSearchParams({
|
||||
aroma: `${aroma}`,
|
||||
flavor: `${flavor}`,
|
||||
acidity: `${acidity}`,
|
||||
sweetness: `${sweetness}`,
|
||||
});
|
||||
|
||||
fetch(`${URL}/search?${params}`).then(async (r) => setData(await r.json()));
|
||||
}, [aroma, flavor, acidity, sweetness]);
|
||||
@@ -57,7 +62,7 @@ function Table() {
|
||||
</thead>
|
||||
|
||||
<tbody>
|
||||
{(data ?? []).map((row) => (
|
||||
{data.map((row) => (
|
||||
<tr>
|
||||
{row.map((d) => (
|
||||
<td>{d.toString()}</td>
|
||||
|
||||
Reference in New Issue
Block a user