mirror of
https://github.com/shishantbiswas/bknd.git
synced 2026-03-16 04:27:21 +00:00
module manager: use json schema field for additional validation
This commit is contained in:
@@ -54,7 +54,7 @@ export class JsonSchemaField<
|
|||||||
|
|
||||||
if (parentValid) {
|
if (parentValid) {
|
||||||
// already checked in parent
|
// already checked in parent
|
||||||
if (!value || typeof value !== "object") {
|
if (!this.isRequired() && (!value || typeof value !== "object")) {
|
||||||
//console.log("jsonschema:valid: not checking", this.name, value, context);
|
//console.log("jsonschema:valid: not checking", this.name, value, context);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@@ -65,6 +65,7 @@ export class JsonSchemaField<
|
|||||||
} else {
|
} else {
|
||||||
//console.log("jsonschema:invalid", this.name, value, context);
|
//console.log("jsonschema:invalid", this.name, value, context);
|
||||||
}
|
}
|
||||||
|
//console.log("jsonschema:invalid:fromParent", this.name, value, context);
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@@ -110,9 +111,13 @@ export class JsonSchemaField<
|
|||||||
): Promise<string | undefined> {
|
): Promise<string | undefined> {
|
||||||
const value = await super.transformPersist(_value, em, context);
|
const value = await super.transformPersist(_value, em, context);
|
||||||
if (this.nullish(value)) return value;
|
if (this.nullish(value)) return value;
|
||||||
|
//console.log("jsonschema:transformPersist", this.name, _value, context);
|
||||||
|
|
||||||
if (!this.isValid(value)) {
|
if (!this.isValid(value)) {
|
||||||
|
//console.error("jsonschema:transformPersist:invalid", this.name, value);
|
||||||
throw new TransformPersistFailedException(this.name, value);
|
throw new TransformPersistFailedException(this.name, value);
|
||||||
|
} else {
|
||||||
|
//console.log("jsonschema:transformPersist:valid", this.name, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!value || typeof value !== "object") return this.getDefault();
|
if (!value || typeof value !== "object") return this.getDefault();
|
||||||
|
|||||||
@@ -2,7 +2,7 @@ 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, objectEach, transformObject } from "core/utils";
|
import { Default, type Static, StringEnum, Type, objectEach, transformObject } from "core/utils";
|
||||||
import {
|
import {
|
||||||
type Connection,
|
type Connection,
|
||||||
EntityManager,
|
EntityManager,
|
||||||
@@ -11,8 +11,10 @@ import {
|
|||||||
entity,
|
entity,
|
||||||
enumm,
|
enumm,
|
||||||
json,
|
json,
|
||||||
|
jsonSchema,
|
||||||
number
|
number
|
||||||
} from "data";
|
} from "data";
|
||||||
|
import { TransformPersistFailedException } from "data/errors";
|
||||||
import { Hono } from "hono";
|
import { Hono } from "hono";
|
||||||
import { type Kysely, sql } from "kysely";
|
import { type Kysely, sql } from "kysely";
|
||||||
import { mergeWith } from "lodash-es";
|
import { mergeWith } from "lodash-es";
|
||||||
@@ -73,10 +75,20 @@ type ConfigTable<Json = ModuleConfigs> = {
|
|||||||
updated_at?: Date;
|
updated_at?: Date;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const configJsonSchema = Type.Union([
|
||||||
|
getDefaultSchema(),
|
||||||
|
Type.Array(
|
||||||
|
Type.Object({
|
||||||
|
type: StringEnum(["insert", "update", "delete"]),
|
||||||
|
value: Type.Any(),
|
||||||
|
path: Type.Optional(Type.String())
|
||||||
|
})
|
||||||
|
)
|
||||||
|
]);
|
||||||
const __bknd = entity(TABLE_NAME, {
|
const __bknd = entity(TABLE_NAME, {
|
||||||
version: number().required(),
|
version: number().required(),
|
||||||
type: enumm({ enum: ["config", "diff", "backup"] }).required(),
|
type: enumm({ enum: ["config", "diff", "backup"] }).required(),
|
||||||
json: json().required(),
|
json: jsonSchema({ schema: configJsonSchema }).required(),
|
||||||
created_at: datetime(),
|
created_at: datetime(),
|
||||||
updated_at: datetime()
|
updated_at: datetime()
|
||||||
});
|
});
|
||||||
@@ -223,10 +235,9 @@ export class ModuleManager {
|
|||||||
const configs = this.configs();
|
const configs = this.configs();
|
||||||
const version = this.version();
|
const version = this.version();
|
||||||
|
|
||||||
const json = JSON.stringify(configs) as any;
|
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const state = await this.fetch();
|
const state = await this.fetch();
|
||||||
|
this.logger.log("fetched version", state.version);
|
||||||
|
|
||||||
if (state.version !== version) {
|
if (state.version !== version) {
|
||||||
// @todo: mark all others as "backup"
|
// @todo: mark all others as "backup"
|
||||||
@@ -234,12 +245,13 @@ export class ModuleManager {
|
|||||||
await this.mutator().insertOne({
|
await this.mutator().insertOne({
|
||||||
version,
|
version,
|
||||||
type: "backup",
|
type: "backup",
|
||||||
json
|
json: configs
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
this.logger.log("version matches");
|
this.logger.log("version matches");
|
||||||
|
|
||||||
const diff = Diff(state.json, JSON.parse(json));
|
// clean configs because of Diff() function
|
||||||
|
const diff = Diff(state.json, JSON.parse(JSON.stringify(configs)));
|
||||||
this.logger.log("checking diff", diff);
|
this.logger.log("checking diff", diff);
|
||||||
|
|
||||||
if (diff.length > 0) {
|
if (diff.length > 0) {
|
||||||
@@ -247,14 +259,14 @@ export class ModuleManager {
|
|||||||
await this.mutator().insertOne({
|
await this.mutator().insertOne({
|
||||||
version,
|
version,
|
||||||
type: "diff",
|
type: "diff",
|
||||||
json: JSON.stringify(diff) as any
|
json: diff
|
||||||
});
|
});
|
||||||
// store new version
|
// store new version
|
||||||
// @todo: maybe by id?
|
// @todo: maybe by id?
|
||||||
await this.mutator().updateWhere(
|
await this.mutator().updateWhere(
|
||||||
{
|
{
|
||||||
version,
|
version,
|
||||||
json,
|
json: configs,
|
||||||
updated_at: new Date()
|
updated_at: new Date()
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -268,14 +280,18 @@ export class ModuleManager {
|
|||||||
}
|
}
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
if (e instanceof BkndError) {
|
if (e instanceof BkndError) {
|
||||||
|
this.logger.log("no config, just save fresh");
|
||||||
// no config, just save
|
// no config, just save
|
||||||
await this.mutator().insertOne({
|
await this.mutator().insertOne({
|
||||||
type: "config",
|
type: "config",
|
||||||
version,
|
version,
|
||||||
json,
|
json: configs,
|
||||||
created_at: new Date(),
|
created_at: new Date(),
|
||||||
updated_at: new Date()
|
updated_at: new Date()
|
||||||
});
|
});
|
||||||
|
} else if (e instanceof TransformPersistFailedException) {
|
||||||
|
console.error("Cannot save invalid config");
|
||||||
|
throw e;
|
||||||
} else {
|
} else {
|
||||||
console.error("Aborting");
|
console.error("Aborting");
|
||||||
throw e;
|
throw e;
|
||||||
|
|||||||
Reference in New Issue
Block a user