fix repository's findOne to allow offset and sort – fixes module manager's config retrieval

This commit is contained in:
dswbx
2024-12-05 10:37:05 +01:00
parent a3348122e6
commit 77a6b6e7f5
4 changed files with 73 additions and 19 deletions

View File

@@ -1,6 +1,7 @@
import { describe, expect, test } from "bun:test"; import { describe, expect, test } from "bun:test";
import { mark, stripMark } from "../src/core/utils"; import { mark, stripMark } from "../src/core/utils";
import { ModuleManager } from "../src/modules/ModuleManager"; import { entity, text } from "../src/data";
import { ModuleManager, getDefaultConfig } from "../src/modules/ModuleManager";
import { CURRENT_VERSION, TABLE_NAME } from "../src/modules/migrations"; import { CURRENT_VERSION, TABLE_NAME } from "../src/modules/migrations";
import { getDummyConnection } from "./helper"; import { getDummyConnection } from "./helper";
@@ -29,7 +30,19 @@ describe("ModuleManager", async () => {
const mm = new ModuleManager(c.dummyConnection); const mm = new ModuleManager(c.dummyConnection);
await mm.build(); await mm.build();
const version = mm.version(); const version = mm.version();
const json = mm.configs(); const configs = mm.configs();
const json = stripMark({
...configs,
data: {
...configs.data,
basepath: "/api/data2",
entities: {
test: entity("test", {
content: text()
}).toJSON()
}
}
});
//const { version, ...json } = mm.toJSON() as any; //const { version, ...json } = mm.toJSON() as any;
const c2 = getDummyConnection(); const c2 = getDummyConnection();
@@ -37,13 +50,48 @@ describe("ModuleManager", async () => {
const mm2 = new ModuleManager(c2.dummyConnection, { initial: { version, ...json } }); const mm2 = new ModuleManager(c2.dummyConnection, { initial: { version, ...json } });
await mm2.syncConfigTable(); await mm2.syncConfigTable();
await db await db
.updateTable(TABLE_NAME) .insertInto(TABLE_NAME)
.set({ json: JSON.stringify(json), version: CURRENT_VERSION }) .values({ type: "config", json: JSON.stringify(json), version: CURRENT_VERSION })
.execute(); .execute();
await mm2.build(); await mm2.build();
expect(json).toEqual(mm2.configs()); expect(json).toEqual(stripMark(mm2.configs()));
});
test("s3.1: (fetch) config given, table exists, version matches", async () => {
const configs = getDefaultConfig();
const json = {
...configs,
data: {
...configs.data,
basepath: "/api/data2",
entities: {
test: entity("test", {
content: text()
}).toJSON()
}
}
};
//const { version, ...json } = mm.toJSON() as any;
const { dummyConnection } = getDummyConnection();
const db = dummyConnection.kysely;
const mm2 = new ModuleManager(dummyConnection);
await mm2.syncConfigTable();
// assume an initial version
await db.insertInto(TABLE_NAME).values({ type: "config", json: null, version: 1 }).execute();
await db
.insertInto(TABLE_NAME)
.values({ type: "config", json: JSON.stringify(json), version: CURRENT_VERSION })
.execute();
await mm2.build();
expect(stripMark(json)).toEqual(stripMark(mm2.configs()));
expect(mm2.configs().data.entities.test).toBeDefined();
expect(mm2.configs().data.entities.test.fields.content).toBeDefined();
expect(mm2.get("data").toJSON().entities.test.fields.content).toBeDefined();
}); });
test("s4: config given, table exists, version outdated, migrate", async () => { test("s4: config given, table exists, version outdated, migrate", async () => {

View File

@@ -72,10 +72,10 @@ export class TypeInvalidError extends Error {
} }
} }
export function stripMark(obj: any) { export function stripMark<O = any>(obj: O) {
const newObj = cloneDeep(obj); const newObj = cloneDeep(obj);
mark(newObj, false); mark(newObj, false);
return newObj; return newObj as O;
} }
export function mark(obj: any, validated = true) { export function mark(obj: any, validated = true) {

View File

@@ -162,8 +162,7 @@ export class Repository<DB = any, TB extends keyof DB = any> implements EmitsEve
protected async performQuery(qb: RepositoryQB): Promise<RepositoryResponse> { protected async performQuery(qb: RepositoryQB): Promise<RepositoryResponse> {
const entity = this.entity; const entity = this.entity;
const compiled = qb.compile(); const compiled = qb.compile();
/*const { sql, parameters } = qb.compile(); //console.log("performQuery", compiled.sql, compiled.parameters);
console.log("many", sql, parameters);*/
const start = performance.now(); const start = performance.now();
const selector = (as = "count") => this.conn.fn.countAll<number>().as(as); const selector = (as = "count") => this.conn.fn.countAll<number>().as(as);
@@ -263,6 +262,7 @@ export class Repository<DB = any, TB extends keyof DB = any> implements EmitsEve
qb = qb.orderBy(aliased(options.sort.by), options.sort.dir); qb = qb.orderBy(aliased(options.sort.by), options.sort.dir);
} }
//console.log("options", { _options, options, exclude_options });
return { qb, options }; return { qb, options };
} }
@@ -286,14 +286,11 @@ export class Repository<DB = any, TB extends keyof DB = any> implements EmitsEve
where: RepoQuery["where"], where: RepoQuery["where"],
_options?: Partial<Omit<RepoQuery, "where" | "limit" | "offset">> _options?: Partial<Omit<RepoQuery, "where" | "limit" | "offset">>
): Promise<RepositoryResponse<DB[TB] | undefined>> { ): Promise<RepositoryResponse<DB[TB] | undefined>> {
const { qb, options } = this.buildQuery( const { qb, options } = this.buildQuery({
{
..._options, ..._options,
where, where,
limit: 1 limit: 1
}, });
["offset", "sort"]
);
return this.single(qb, options) as any; return this.single(qb, options) as any;
} }

View File

@@ -2,7 +2,15 @@ import { Diff } from "@sinclair/typebox/value";
import { Guard } from "auth"; import { Guard } from "auth";
import { BkndError, DebugLogger, Exception, isDebug } from "core"; import { BkndError, DebugLogger, Exception, isDebug } from "core";
import { EventManager } from "core/events"; import { EventManager } from "core/events";
import { Default, type Static, StringEnum, Type, objectEach, transformObject } from "core/utils"; import {
Default,
type Static,
StringEnum,
Type,
objectEach,
stripMark,
transformObject
} from "core/utils";
import { import {
type Connection, type Connection,
EntityManager, EntityManager,
@@ -130,7 +138,7 @@ export class ModuleManager {
if ("version" in options.initial) { if ("version" in options.initial) {
const { version, ...initialConfig } = options.initial; const { version, ...initialConfig } = options.initial;
this._version = version; this._version = version;
initial = initialConfig; initial = stripMark(initialConfig);
this._booted_with = "provided"; this._booted_with = "provided";
} else { } else {
@@ -393,6 +401,7 @@ export class ModuleManager {
this.logger.context("build").log("version", this.version()); this.logger.context("build").log("version", this.version());
this.logger.log("booted with", this._booted_with); this.logger.log("booted with", this._booted_with);
// @todo: check this, because you could start without an initial config
if (this.version() !== CURRENT_VERSION) { if (this.version() !== CURRENT_VERSION) {
await this.syncConfigTable(); await this.syncConfigTable();
} }