Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
35 changes: 22 additions & 13 deletions src/runtime/validation.ts
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,8 @@ function toSchema(spec: SimplifiedSchema): NormalizedSchema {
);
}

const SCHEMA_KEYS = new Set(["element", "optional", "shape", "type", "validate", "values"]);

/**
* Main validate function
*/
Expand Down Expand Up @@ -141,35 +143,42 @@ export function validateType(key: string, value: any, descr: TypeDescription): s
let validDescr = descr.find((p) => !validateType(key, value, p));
return validDescr ? null : `'${key}' is not a ${describe(descr)}`;
}
let result: string | null = null;
const invalidKeys = Reflect.ownKeys(descr).filter((key) => !SCHEMA_KEYS.has(String(key)));
if (invalidKeys.length) {
return `invalid schema for '${key}': unknown keys ${invalidKeys
.map((key) => `"${String(key)}"`)
.join(", ")}`;
}
if ("element" in descr) {
result = validateArrayType(key, value, descr.element!);
} else if ("shape" in descr) {
return validateArrayType(key, value, descr.element!);
}
if ("shape" in descr) {
if (typeof value !== "object" || Array.isArray(value)) {
result = `'${key}' is not an object`;
return `'${key}' is not an object`;
} else {
const errors = validateSchema(value, descr.shape!);
if (errors.length) {
result = `'${key}' doesn't have the correct shape (${errors.join(", ")})`;
return `'${key}' doesn't have the correct shape (${errors.join(", ")})`;
}
}
} else if ("values" in descr) {
}
if ("values" in descr) {
if (typeof value !== "object" || Array.isArray(value)) {
result = `'${key}' is not an object`;
return `'${key}' is not an object`;
} else {
const errors = Object.entries(value)
.map(([key, value]) => validateType(key, value, descr.values!))
.filter(Boolean);
if (errors.length) {
result = `some of the values in '${key}' are invalid (${errors.join(", ")})`;
return `some of the values in '${key}' are invalid (${errors.join(", ")})`;
}
}
}
if ("type" in descr && !result) {
result = validateType(key, value, descr.type!);
if ("type" in descr) {
return validateType(key, value, descr.type!);
}
if ("validate" in descr && !result) {
result = !descr.validate!(value) ? `'${key}' is not valid` : null;
if ("validate" in descr) {
return !descr.validate!(value) ? `'${key}' is not valid` : null;
}
return result;
return null;
}
9 changes: 9 additions & 0 deletions tests/validation.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -308,4 +308,13 @@ describe("validateSchema", () => {
]);
expect(validateSchema({ a: "string" }, { a: [String, { value: false }] })).toEqual([]);
});

test("validate schema's own keys", () => {
expect(validateSchema({ arr: [] }, { arr: { type: Array, elements: String } as any })).toEqual([
`invalid schema for 'arr': unknown keys "elements"`,
]);
expect(validateSchema({ obj: {} }, { obj: { type: Object, shapes: String } as any })).toEqual([
`invalid schema for 'obj': unknown keys "shapes"`,
]);
});
});
Loading