mirror of
https://github.com/github/codeql-action.git
synced 2026-10-03 09:14:58 +00:00
Add checkSchema function
This commit is contained in:
30
lib/entry-points.js
generated
30
lib/entry-points.js
generated
@@ -144518,19 +144518,41 @@ function optionalOrNull(validator) {
|
||||
};
|
||||
}
|
||||
function validateSchema(schema, obj) {
|
||||
const result = checkSchema(schema, obj, { failFast: true });
|
||||
return result.valid;
|
||||
}
|
||||
function checkSchema(schema, obj, options = {}, path29 = "") {
|
||||
const result = { valid: true, unknownKeys: [] };
|
||||
const inputKeys = new Set(Object.keys(obj));
|
||||
for (const [key, validator] of Object.entries(schema)) {
|
||||
const hasKey = key in obj;
|
||||
if (validator.required && !hasKey) {
|
||||
return false;
|
||||
result.valid = false;
|
||||
if (options.failFast) {
|
||||
return result;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
if (validator.required && (obj[key] === void 0 || obj[key] === null)) {
|
||||
return false;
|
||||
result.valid = false;
|
||||
if (options.failFast) {
|
||||
return result;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
if (hasKey && !validator.validate(obj[key])) {
|
||||
return false;
|
||||
result.valid = false;
|
||||
if (options.failFast) {
|
||||
return result;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
inputKeys.delete(key);
|
||||
}
|
||||
return true;
|
||||
for (const remainingKey of inputKeys) {
|
||||
result.unknownKeys.push(`${path29}${remainingKey}`);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
// src/util.ts
|
||||
|
||||
@@ -67,3 +67,13 @@ test("validateSchema - optional properties are optional", async (t) => {
|
||||
t.true(json.validateSchema(optionalSchema, { optionalKey: "" }));
|
||||
t.true(json.validateSchema(optionalSchema, { optionalKey: "foo" }));
|
||||
});
|
||||
|
||||
test("validateSchema - checkSchema reports unknown keys", async (t) => {
|
||||
const result = json.checkSchema(testSchema, {
|
||||
requiredKey: "foo",
|
||||
extraKey: "bar",
|
||||
});
|
||||
|
||||
t.true(result.valid);
|
||||
t.deepEqual(result.unknownKeys, ["extraKey"]);
|
||||
});
|
||||
|
||||
@@ -121,24 +121,72 @@ export function validateSchema<S extends Schema>(
|
||||
schema: S,
|
||||
obj: UnvalidatedObject<any>,
|
||||
): obj is FromSchema<S> {
|
||||
const result = checkSchema(schema, obj, { failFast: true });
|
||||
return result.valid;
|
||||
}
|
||||
|
||||
export interface CheckSchemaOptions {
|
||||
/** Whether to stop validation after the first error. */
|
||||
failFast?: boolean;
|
||||
}
|
||||
|
||||
export interface CheckSchemaResult {
|
||||
/** Whether the `obj` satisfies the schema. */
|
||||
valid: boolean;
|
||||
/** Unknown keys that were found during validation. */
|
||||
unknownKeys: string[];
|
||||
}
|
||||
|
||||
export function checkSchema<S extends Schema>(
|
||||
schema: S,
|
||||
obj: UnvalidatedObject<any>,
|
||||
options: CheckSchemaOptions = {},
|
||||
path: string = "",
|
||||
): CheckSchemaResult {
|
||||
const result: CheckSchemaResult = { valid: true, unknownKeys: [] };
|
||||
const inputKeys = new Set(Object.keys(obj));
|
||||
|
||||
for (const [key, validator] of Object.entries(schema)) {
|
||||
const hasKey = key in obj;
|
||||
|
||||
// If the property is required, but absent, fail.
|
||||
if (validator.required && !hasKey) {
|
||||
return false;
|
||||
result.valid = false;
|
||||
|
||||
if (options.failFast) {
|
||||
return result;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
// If the property is required, but undefined or null, fail.
|
||||
if (validator.required && (obj[key] === undefined || obj[key] === null)) {
|
||||
return false;
|
||||
result.valid = false;
|
||||
|
||||
if (options.failFast) {
|
||||
return result;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
// If the property is present, validate it.
|
||||
if (hasKey && !validator.validate(obj[key])) {
|
||||
return false;
|
||||
result.valid = false;
|
||||
|
||||
if (options.failFast) {
|
||||
return result;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
// If we reach this point, the key has been successfully validated.
|
||||
inputKeys.delete(key);
|
||||
}
|
||||
|
||||
return true;
|
||||
// If there are any remaining keys in `inputKeys`, add them to `unknownKeys`.
|
||||
for (const remainingKey of inputKeys) {
|
||||
result.unknownKeys.push(`${path}${remainingKey}`);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user