export RepoQueryIn from client

This commit is contained in:
dswbx
2025-02-18 12:54:13 +01:00
parent dec382b49d
commit 7994eabe7d
4 changed files with 62 additions and 3 deletions

View File

@@ -70,4 +70,34 @@ describe("repros", async () => {
expect(app.em.entities.map((e) => e.name)).toEqual(["media", "test"]); expect(app.em.entities.map((e) => e.name)).toEqual(["media", "test"]);
}); });
test.only("verify inversedBy", async () => {
const schema = proto.em(
{
products: proto.entity("products", {
title: proto.text()
}),
product_likes: proto.entity("product_likes", {
created_at: proto.date()
}),
users: proto.entity("users", {})
},
(fns, schema) => {
fns.relation(schema.product_likes).manyToOne(schema.products, { inversedBy: "likes" });
fns.relation(schema.product_likes).manyToOne(schema.users);
}
);
const app = createApp({ initialConfig: { data: schema.toJSON() } });
await app.build();
const info = (await (await app.server.request("/api/data/info/products")).json()) as any;
expect(info.fields).toEqual(["id", "title"]);
expect(info.relations.listable).toEqual([
{
entity: "product_likes",
ref: "likes"
}
]);
});
}); });

View File

@@ -1,10 +1,10 @@
import type { DB } from "core"; import type { DB } from "core";
import type { EntityData, RepoQuery, RepoQueryIn, RepositoryResponse } from "data"; import type { EntityData, RepoQueryIn, RepositoryResponse } from "data";
import { type BaseModuleApiOptions, ModuleApi, type PrimaryFieldType } from "modules"; import { type BaseModuleApiOptions, ModuleApi, type PrimaryFieldType } from "modules";
export type DataApiOptions = BaseModuleApiOptions & { export type DataApiOptions = BaseModuleApiOptions & {
queryLengthLimit: number; queryLengthLimit: number;
defaultQuery: Partial<RepoQuery>; defaultQuery: Partial<RepoQueryIn>;
}; };
export class DataApi extends ModuleApi<DataApiOptions> { export class DataApi extends ModuleApi<DataApiOptions> {
@@ -78,7 +78,7 @@ export class DataApi extends ModuleApi<DataApiOptions> {
return this.delete<RepositoryResponse<Data>>(["entity", entity as any, id]); return this.delete<RepositoryResponse<Data>>(["entity", entity as any, id]);
} }
count<E extends keyof DB | string>(entity: E, where: RepoQuery["where"] = {}) { count<E extends keyof DB | string>(entity: E, where: RepoQueryIn["where"] = {}) {
return this.post<RepositoryResponse<{ entity: E; count: number }>>( return this.post<RepositoryResponse<{ entity: E; count: number }>>(
["entity", entity as any, "fn", "count"], ["entity", entity as any, "fn", "count"],
where where

View File

@@ -165,6 +165,34 @@ export class DataController extends Controller {
// entity endpoints // entity endpoints
hono.route("/entity", this.getEntityRoutes()); hono.route("/entity", this.getEntityRoutes());
/**
* Info endpoints
*/
hono.get("/info/:entity", async (c) => {
const { entity } = c.req.param();
if (!this.entityExists(entity)) {
return c.notFound();
}
const _entity = this.em.entity(entity);
const fields = _entity.fields.map((f) => f.name);
const $rels = (r: any) =>
r.map((r: any) => ({
entity: r.other(_entity).entity.name,
ref: r.other(_entity).reference
}));
return c.json({
name: _entity.name,
fields,
relations: {
all: $rels(this.em.relations.relationsOf(_entity)),
listable: $rels(this.em.relations.listableRelationsOf(_entity)),
source: $rels(this.em.relations.sourceRelationsOf(_entity)),
target: $rels(this.em.relations.targetRelationsOf(_entity))
}
});
});
return hono.all("*", (c) => c.notFound()); return hono.all("*", (c) => c.notFound());
} }

View File

@@ -10,3 +10,4 @@ export * from "./api/use-api";
export * from "./api/use-entity"; export * from "./api/use-entity";
export { useAuth } from "./schema/auth/use-auth"; export { useAuth } from "./schema/auth/use-auth";
export { Api, type TApiUser, type AuthState, type ApiOptions } from "../../Api"; export { Api, type TApiUser, type AuthState, type ApiOptions } from "../../Api";
export type { RepoQueryIn } from "data";