Enhance command validation in database processing

- Updated validation methods in DatabaseCommand and its subclasses (DeleteCommand, InsertCommand, QueryCommand, UpdateCommand) to enforce stricter checks on configuration objects.
- Introduced runtime type guard utilities for better validation of expected configuration structures.
- Added console warnings for missing required fields in commands, improving user feedback during validation failures.
- Ensured that all commands validate necessary properties before execution, enhancing robustness and preventing misconfigurations.
This commit is contained in:
Nikhil-Doye
2025-10-27 16:36:06 -04:00
parent 60db9c827e
commit 8eaf0221b6
5 changed files with 88 additions and 9 deletions
@@ -45,7 +45,7 @@ export abstract class BaseDatabaseCommand implements DatabaseCommand {
abstract getDescription(): string;
validate(): boolean {
return this.config && typeof this.config === "object";
return this.config != null && typeof this.config === "object";
}
/**
@@ -64,6 +64,38 @@ export abstract class BaseDatabaseCommand implements DatabaseCommand {
}
}
/**
* Runtime type guard utilities to enforce stronger config structures.
* These do not replace compile-time types but provide robust validation
* at runtime to prevent misconfiguration from propagating.
*/
protected hasString(config: any, key: string): config is Record<string, any> {
return (
config && typeof config[key] === "string" && config[key].trim() !== ""
);
}
protected hasObject(config: any, key: string): boolean {
return (
config &&
typeof config[key] === "object" &&
config[key] !== null &&
!Array.isArray(config[key])
);
}
protected ensureKeys(
config: any,
keys: Array<{ key: string; type: "string" | "object" }>
): { ok: boolean; missing: string[] } {
const missing: string[] = [];
for (const { key, type } of keys) {
if (type === "string" && !this.hasString(config, key)) missing.push(key);
if (type === "object" && !this.hasObject(config, key)) missing.push(key);
}
return { ok: missing.length === 0, missing };
}
/**
* Helper method to create a standardized result
*/
@@ -69,6 +69,16 @@ export class DeleteCommand
}
validate(): boolean {
return super.validate() && (!!this.config.filter || !!this.config.where);
if (!super.validate()) return false;
const hasFilter =
this.hasObject(this.config, "filter") ||
this.hasObject(this.config, "where");
if (!hasFilter) {
console.warn(
"DeleteCommand validation failed. 'filter' or 'where' object is required."
);
return false;
}
return true;
}
}
@@ -66,6 +66,25 @@ export class InsertCommand
}
validate(): boolean {
return super.validate() && (!!this.config.document || !!this.config.record);
if (!super.validate()) return false;
// Accept either 'document' (object/JSON) or 'record'
const hasDoc = this.hasObject(this.config, "document");
const hasRecord = this.hasObject(this.config, "record");
if (!hasDoc && !hasRecord) {
console.warn(
"InsertCommand validation failed. Expected 'document' or 'record' object."
);
return false;
}
// If SQL-like, ensure table/collection name is present
const requiresTable = !!(
(this.config as any).table || (this.config as any).collection
);
if (!requiresTable) {
console.warn(
"InsertCommand validation warning: missing 'table' or 'collection'. Some connectors require it."
);
}
return true;
}
}
@@ -30,6 +30,15 @@ export class QueryCommand
}
validate(): boolean {
return super.validate() && !!this.config.query;
if (!super.validate()) return false;
const { ok, missing } = this.ensureKeys(this.config, [
{ key: "query", type: "string" },
]);
if (!ok) {
console.warn(
`QueryCommand validation failed. Missing fields: ${missing.join(", ")}`
);
}
return ok;
}
}
@@ -84,10 +84,19 @@ export class UpdateCommand
}
validate(): boolean {
return (
super.validate() &&
(!!this.config.filter || !!this.config.where) &&
(!!this.config.update || !!this.config.set)
);
if (!super.validate()) return false;
const hasFilter =
this.hasObject(this.config, "filter") ||
this.hasObject(this.config, "where");
const hasUpdate =
this.hasObject(this.config, "update") ||
this.hasObject(this.config, "set");
if (!hasFilter || !hasUpdate) {
console.warn(
"UpdateCommand validation failed. 'filter/where' and 'update/set' objects are required."
);
return false;
}
return true;
}
}