mirror of
https://github.com/shishantbiswas/bknd.git
synced 2026-03-17 12:56:05 +00:00
feat: add schema marking and validation skip mechanism
This commit is contained in:
@@ -12,6 +12,7 @@ export {
|
|||||||
getMcpServer,
|
getMcpServer,
|
||||||
stdioTransport,
|
stdioTransport,
|
||||||
McpClient,
|
McpClient,
|
||||||
|
logLevels as mcpLogLevels,
|
||||||
type McpClientConfig,
|
type McpClientConfig,
|
||||||
type ToolAnnotation,
|
type ToolAnnotation,
|
||||||
type ToolHandlerCtx,
|
type ToolHandlerCtx,
|
||||||
@@ -21,8 +22,35 @@ export { secret, SecretSchema } from "./secret";
|
|||||||
|
|
||||||
export { s };
|
export { s };
|
||||||
|
|
||||||
export const stripMark = <O extends object>(o: O): O => o;
|
const symbol = Symbol("bknd-validation-mark");
|
||||||
export const mark = <O extends object>(o: O): O => o;
|
|
||||||
|
export function stripMark<O = any>(obj: O) {
|
||||||
|
const newObj = structuredClone(obj);
|
||||||
|
mark(newObj, false);
|
||||||
|
return newObj as O;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function mark(obj: any, validated = true) {
|
||||||
|
try {
|
||||||
|
if (typeof obj === "object" && obj !== null && !Array.isArray(obj)) {
|
||||||
|
if (validated) {
|
||||||
|
obj[symbol] = true;
|
||||||
|
} else {
|
||||||
|
delete obj[symbol];
|
||||||
|
}
|
||||||
|
for (const key in obj) {
|
||||||
|
if (typeof obj[key] === "object" && obj[key] !== null) {
|
||||||
|
mark(obj[key], validated);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (e) {}
|
||||||
|
}
|
||||||
|
|
||||||
|
export function isMarked(obj: any) {
|
||||||
|
if (typeof obj !== "object" || obj === null) return false;
|
||||||
|
return obj[symbol] === true;
|
||||||
|
}
|
||||||
|
|
||||||
export const stringIdentifier = s.string({
|
export const stringIdentifier = s.string({
|
||||||
pattern: "^[a-zA-Z_][a-zA-Z0-9_]*$",
|
pattern: "^[a-zA-Z_][a-zA-Z0-9_]*$",
|
||||||
@@ -74,6 +102,10 @@ export function parse<S extends s.Schema, Options extends ParseOptions = ParseOp
|
|||||||
v: unknown,
|
v: unknown,
|
||||||
opts?: Options,
|
opts?: Options,
|
||||||
): Options extends { coerce: true } ? s.StaticCoerced<S> : s.Static<S> {
|
): Options extends { coerce: true } ? s.StaticCoerced<S> : s.Static<S> {
|
||||||
|
if (!opts?.forceParse && !opts?.coerce && isMarked(v)) {
|
||||||
|
return v as any;
|
||||||
|
}
|
||||||
|
|
||||||
const schema = (opts?.clone ? cloneSchema(_schema as any) : _schema) as s.Schema;
|
const schema = (opts?.clone ? cloneSchema(_schema as any) : _schema) as s.Schema;
|
||||||
let value =
|
let value =
|
||||||
opts?.coerce !== false
|
opts?.coerce !== false
|
||||||
|
|||||||
@@ -1,4 +1,12 @@
|
|||||||
import { objectEach, transformObject, McpServer, type s, SecretSchema, setPath } from "bknd/utils";
|
import {
|
||||||
|
objectEach,
|
||||||
|
transformObject,
|
||||||
|
McpServer,
|
||||||
|
type s,
|
||||||
|
SecretSchema,
|
||||||
|
setPath,
|
||||||
|
mark,
|
||||||
|
} from "bknd/utils";
|
||||||
import { DebugLogger } from "core/utils/DebugLogger";
|
import { DebugLogger } from "core/utils/DebugLogger";
|
||||||
import { Guard } from "auth/authorize/Guard";
|
import { Guard } from "auth/authorize/Guard";
|
||||||
import { env } from "core/env";
|
import { env } from "core/env";
|
||||||
@@ -65,7 +73,7 @@ export type ModuleManagerOptions = {
|
|||||||
// callback after server was created
|
// callback after server was created
|
||||||
onServerInit?: (server: Hono<ServerEnv>) => void;
|
onServerInit?: (server: Hono<ServerEnv>) => void;
|
||||||
// doesn't perform validity checks for given/fetched config
|
// doesn't perform validity checks for given/fetched config
|
||||||
trustFetched?: boolean;
|
skipValidation?: boolean;
|
||||||
// runs when initial config provided on a fresh database
|
// runs when initial config provided on a fresh database
|
||||||
seed?: (ctx: ModuleBuildContext) => Promise<void>;
|
seed?: (ctx: ModuleBuildContext) => Promise<void>;
|
||||||
// called right after modules are built, before finish
|
// called right after modules are built, before finish
|
||||||
@@ -124,7 +132,12 @@ export class ModuleManager {
|
|||||||
this.emgr = new EventManager({ ...ModuleManagerEvents });
|
this.emgr = new EventManager({ ...ModuleManagerEvents });
|
||||||
this.logger = new DebugLogger(debug_modules);
|
this.logger = new DebugLogger(debug_modules);
|
||||||
|
|
||||||
this.createModules(options?.initial ?? {});
|
const config = options?.initial ?? {};
|
||||||
|
if (options?.skipValidation) {
|
||||||
|
mark(config, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
this.createModules(config);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected onModuleConfigUpdated(key: string, config: any) {}
|
protected onModuleConfigUpdated(key: string, config: any) {}
|
||||||
|
|||||||
@@ -380,8 +380,8 @@ export class DbModuleManager extends ModuleManager {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (this.options?.trustFetched === true) {
|
if (this.options?.skipValidation === true) {
|
||||||
this.logger.log("trusting fetched config (mark)");
|
this.logger.log("skipping validation (mark)");
|
||||||
mark(result.configs.json);
|
mark(result.configs.json);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user