From 6c2f7b32e5268581bd144c1e1ef424ee86efbf07 Mon Sep 17 00:00:00 2001 From: dswbx Date: Thu, 5 Dec 2024 08:12:46 +0100 Subject: [PATCH] module manager: allow initial config without config as fallback --- app/__test__/ModuleManager.spec.ts | 90 ++++++++++++++++-------------- app/src/modules/ModuleManager.ts | 25 ++++++--- 2 files changed, 65 insertions(+), 50 deletions(-) diff --git a/app/__test__/ModuleManager.spec.ts b/app/__test__/ModuleManager.spec.ts index d58b98a..d79bf27 100644 --- a/app/__test__/ModuleManager.spec.ts +++ b/app/__test__/ModuleManager.spec.ts @@ -148,50 +148,58 @@ describe("ModuleManager", async () => { }); }); - // @todo: check what happens here - /*test("blank app, modify deep config", async () => { + test("partial config given", async () => { const { dummyConnection } = getDummyConnection(); - const mm = new ModuleManager(dummyConnection); + const partial = { + auth: { + enabled: true + } + }; + const mm = new ModuleManager(dummyConnection, { + initial: partial + }); await mm.build(); - /!* await mm - .get("data") - .schema() - .patch("entities.test", { - fields: { - content: { - type: "text" - } + expect(mm.version()).toBe(CURRENT_VERSION); + expect(mm.built()).toBe(true); + expect(mm.configs().auth.enabled).toBe(true); + expect(mm.configs().data.entities.users).toBeDefined(); + }); + + test("partial config given, but db version exists", async () => { + const c = getDummyConnection(); + const mm = new ModuleManager(c.dummyConnection); + await mm.build(); + const json = mm.configs(); + + const c2 = getDummyConnection(); + const db = c2.dummyConnection.kysely; + await migrateSchema(CURRENT_VERSION, { db }); + const payload = { + ...json, + auth: { + ...json.auth, + enabled: true, + basepath: "/api/auth2" + } + }; + await db + .updateTable(TABLE_NAME) + .set({ + json: JSON.stringify(payload), + version: CURRENT_VERSION + }) + .execute(); + + const mm2 = new ModuleManager(c2.dummyConnection, { + initial: { + auth: { + basepath: "/shouldnt/take/this" } - }); - await mm.build(); - - expect(mm.configs().data.entities?.users?.fields?.email.type).toBe("text"); - - expect( - mm.get("data").schema().patch("desc", "entities.users.config.sort_dir") - ).rejects.toThrow(); - await mm.build();*!/ - expect(mm.configs().data.entities?.users?.fields?.email.type).toBe("text"); - console.log("here", mm.configs()); - await mm - .get("data") - .schema() - .patch("entities.users", { config: { sort_dir: "desc" } }); - await mm.build(); - expect(mm.toJSON()); - - //console.log(_jsonp(mm.toJSON().data)); - /!*expect(mm.configs().data.entities!.test!.fields!.content.type).toBe("text"); - expect(mm.configs().data.entities!.users!.config!.sort_dir).toBe("desc");*!/ - });*/ - - /*test("accessing modules", async () => { - const { dummyConnection } = getDummyConnection(); - - const mm = new ModuleManager(dummyConnection); - - //mm.get("auth").mutate().set({}); - });*/ + } + }); + await mm2.build(); + expect(mm2.configs().auth.basepath).toBe("/api/auth2"); + }); }); diff --git a/app/src/modules/ModuleManager.ts b/app/src/modules/ModuleManager.ts index 51a1768..b77e207 100644 --- a/app/src/modules/ModuleManager.ts +++ b/app/src/modules/ModuleManager.ts @@ -6,6 +6,7 @@ import { Default, type Static, objectEach, transformObject } from "core/utils"; import { type Connection, EntityManager } from "data"; import { Hono } from "hono"; import { type Kysely, sql } from "kysely"; +import { mergeWith } from "lodash-es"; import { CURRENT_VERSION, TABLE_NAME, migrate, migrateSchema } from "modules/migrations"; import { AppServer } from "modules/server/AppServer"; import { AppAuth } from "../auth/AppAuth"; @@ -38,9 +39,11 @@ export type ModuleConfigs = { [K in keyof ModuleSchemas]: Static; }; -export type InitialModuleConfigs = { - version: number; -} & Partial; +export type InitialModuleConfigs = + | ({ + version: number; + } & ModuleConfigs) + | Partial; export type ModuleManagerOptions = { initial?: InitialModuleConfigs; @@ -71,7 +74,9 @@ export class ModuleManager { private _version: number = 0; private _built = false; private _fetched = false; - private readonly _provided; + + // @todo: keep? not doing anything with it + private readonly _booted_with?: "provided" | "partial"; private logger = new DebugLogger(isDebug() && false); @@ -85,14 +90,15 @@ export class ModuleManager { let initial = {} as Partial; if (options?.initial) { - const { version, ...initialConfig } = options.initial; - if (version && initialConfig) { + if ("version" in options.initial) { + const { version, ...initialConfig } = options.initial; this._version = version; initial = initialConfig; - this._provided = true; + this._booted_with = "provided"; } else { - throw new Error("Initial was provided, but it needs a version!"); + initial = mergeWith(getDefaultConfig(), options.initial); + this._booted_with = "partial"; } } @@ -337,10 +343,11 @@ export class ModuleManager { async build() { this.logger.context("build").log("version", this.version()); + this.logger.log("booted with", this._booted_with); // if no config provided, try fetch from db if (this.version() === 0) { - this.logger.context("build no config").log("version is 0"); + this.logger.context("no version").log("version is 0"); try { const result = await this.fetch();