updated repo query schema, repo and withbuilder validation, and reworked relation with building

This commit is contained in:
dswbx
2025-01-16 13:22:15 +01:00
parent 5343d0bd9d
commit 37a65bcaf6
10 changed files with 285 additions and 89 deletions

View File

@@ -103,17 +103,10 @@ export class Repository<TBD extends object = DefaultDB, TB extends keyof TBD = a
validated.select = options.select;
}
if (options.with && options.with.length > 0) {
for (const entry of options.with) {
const related = this.em.relationOf(entity.name, entry);
if (!related) {
throw new InvalidSearchParamsException(
`WITH: "${entry}" is not a relation of "${entity.name}"`
);
}
validated.with.push(entry);
}
if (options.with) {
const depth = WithBuilder.validateWiths(this.em, entity.name, options.with);
// @todo: determine allowed depth
validated.with = options.with;
}
if (options.join && options.join.length > 0) {

View File

@@ -1,11 +1,16 @@
import { isObject } from "core/utils";
import type { KyselyJsonFrom, RepoQuery } from "data";
import { InvalidSearchParamsException } from "data/errors";
import type { RepoWithSchema } from "data/server/data-query-impl";
import type { Entity, EntityManager, RepositoryQB } from "../../entities";
export class WithBuilder {
private static buildClause(
/*private static buildClause(
em: EntityManager<any>,
qb: RepositoryQB,
entity: Entity,
withString: string
ref: string,
config?: RepoQuery
) {
const relation = em.relationOf(entity.name, withString);
if (!relation) {
@@ -15,7 +20,6 @@ export class WithBuilder {
const cardinality = relation.ref(withString).cardinality;
//console.log("with--builder", { entity: entity.name, withString, cardinality });
const fns = em.connection.fn;
const jsonFrom = cardinality === 1 ? fns.jsonObjectFrom : fns.jsonArrayFrom;
if (!jsonFrom) {
@@ -27,16 +31,69 @@ export class WithBuilder {
} catch (e) {
throw new Error(`Could not build "with" relation "${withString}": ${(e as any).message}`);
}
}
}*/
static addClause(em: EntityManager<any>, qb: RepositoryQB, entity: Entity, withs: string[]) {
if (withs.length === 0) return qb;
static addClause(
em: EntityManager<any>,
qb: RepositoryQB,
entity: Entity,
withs: RepoQuery["with"]
) {
if (!withs || !isObject(withs)) {
console.warn(`'withs' undefined or invalid, given: ${JSON.stringify(withs)}`);
return qb;
}
const fns = em.connection.fn;
let newQb = qb;
for (const entry of withs) {
newQb = WithBuilder.buildClause(em, newQb, entity, entry);
for (const [ref, query] of Object.entries(withs)) {
const relation = em.relationOf(entity.name, ref);
if (!relation) {
throw new Error(`Relation "${entity.name}<>${ref}" not found`);
}
const cardinality = relation.ref(ref).cardinality;
const jsonFrom: KyselyJsonFrom =
cardinality === 1 ? fns.jsonObjectFrom : fns.jsonArrayFrom;
if (!jsonFrom) {
throw new Error("Connection does not support jsonObjectFrom/jsonArrayFrom");
}
const alias = relation.other(entity).reference;
newQb = newQb.select((eb) => {
return jsonFrom(relation.buildWith(entity, ref)(eb)).as(alias);
});
//newQb = relation.buildWith(entity, qb, jsonFrom, ref);
}
return newQb;
}
static validateWiths(em: EntityManager<any>, entity: string, withs: RepoQuery["with"]) {
let depth = 0;
if (!withs || !isObject(withs)) {
console.warn(`'withs' undefined or invalid, given: ${JSON.stringify(withs)}`);
return depth;
}
const child_depths: number[] = [];
for (const [ref, query] of Object.entries(withs)) {
const related = em.relationOf(entity, ref);
if (!related) {
throw new InvalidSearchParamsException(
`WITH: "${ref}" is not a relation of "${entity}"`
);
}
depth++;
if ("with" in query) {
child_depths.push(WithBuilder.validateWiths(em, ref, query.with as any));
}
}
if (child_depths.length > 0) {
depth += Math.max(...child_depths);
}
return depth;
}
}