fortify-schema
Version:
TypeScript interface-like schema validation system that's easier to use than Zod
86 lines (71 loc) • 3.2 kB
text/typescript
import { Interface } from "../schema/mode/interfaces/Interface";
console.log("🔍 CORRECT CONDITIONAL VALIDATION TEST");
console.log("=====================================\n");
// The issue is in our conditional schema design
// "when:role=admin:string[]:string[]?" means:
// - If role=admin → permissions should be string[] (required)
// - If role≠admin → permissions should be string[]? (optional string array)
//
// But we want:
// - If role=admin → permissions should be string[] (required)
// - If role≠admin → permissions should be undefined (not allowed)
console.log("❌ INCORRECT: Current schema allows optional arrays for non-admin");
const IncorrectSchema = Interface({
role: "admin|user",
permissions: "when:role=admin:string[]:string[]?" // This allows ["read"] for users!
});
console.log("✅ CORRECT: Schema that properly restricts non-admin permissions");
const CorrectSchema = Interface({
role: "admin|user",
permissions: "when:role=admin:string[]:undefined" // This rejects any value for users!
});
console.log("\nTesting INCORRECT schema:");
// This should fail but currently passes
const userWithPermissions = IncorrectSchema.safeParse({
role: "user",
permissions: ["read"] // Should fail but passes because string[]? allows arrays
});
console.log("User with permissions (incorrect schema):", userWithPermissions.success);
console.log("\nTesting CORRECT schema:");
// This should fail and will fail
const userWithPermissionsCorrect = CorrectSchema.safeParse({
role: "user",
permissions: ["read"] // Should fail because undefined doesn't allow arrays
});
console.log("User with permissions (correct schema):", userWithPermissionsCorrect.success);
if (!userWithPermissionsCorrect.success) {
console.log("✅ Correctly rejected! Errors:", userWithPermissionsCorrect.errors);
}
// This should pass
const adminWithPermissions = CorrectSchema.safeParse({
role: "admin",
permissions: ["read", "write"] // Should pass
});
console.log("Admin with permissions:", adminWithPermissions.success);
// This should pass
const userWithoutPermissions = CorrectSchema.safeParse({
role: "user"
// No permissions field - should pass
});
console.log("User without permissions:", userWithoutPermissions.success);
console.log("\n🎯 SOLUTION:");
console.log("Use 'undefined' instead of 'string[]?' for the else case");
console.log("when:role=admin:string[]:undefined");
console.log("This ensures non-admin users cannot have permissions at all!");
console.log("\n🔧 ALTERNATIVE SOLUTIONS:");
console.log("1. when:role=admin:string[]:undefined");
console.log("2. when:role=admin:string[] (no else case)");
console.log("3. Use import-based syntax for more control");
// Test alternative: no else case
const AlternativeSchema = Interface({
role: "admin|user",
permissions: "when:role=admin:string[]" // No else case
});
const userTestAlt = AlternativeSchema.safeParse({
role: "user",
permissions: ["read"]
});
console.log("\nAlternative (no else case) - User with permissions:", userTestAlt.success);
if (!userTestAlt.success) {
console.log("✅ Alternative also works! Errors:", userTestAlt.errors);
}