Skip to content
Open
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
54 changes: 43 additions & 11 deletions lib/process-schema.js
Original file line number Diff line number Diff line change
@@ -1,36 +1,68 @@
const NESTED_WITH_NAME = ["definitions", "properties"];
/**
* @typedef {import("json-schema").JSONSchema} JSONSchema
*/

const NESTED_DIRECT = ["items", "additionalProperties", "not"];
/**
* @typedef {Object.<string, JSONSchema | boolean>} ProcessContext
*/

/**
* @typedef {Object} SchemaVisitor
* @property {(schema: JSONSchema | boolean, context?: ProcessContext) => JSONSchema | boolean | void} [schema]
* @property {(obj: JSONSchema | boolean, context?: ProcessContext) => JSONSchema | boolean | void} [object]
* @property {(arr: (JSONSchema | boolean)[], context?: ProcessContext) => void} [array]
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just interesting why we have boolean here?

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good catch. JSON Schema allows boolean schemas, but instead of manually adding boolean I can switch to JSONSchema7Definition from json-schema types which already includes it.
can i ?
@alexander-akait

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We support more than JSONSchema7, it should be support old formats too

Copy link
Copy Markdown
Author

@Manas-Dikshit Manas-Dikshit Mar 12, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

what kind of changes the below code needs
Screenshot 2026-03-13 013743

*/

const NESTED_WITH_NAME = ["definitions", "properties"];
const NESTED_DIRECT = ["items", "additionalProperties", "not"];
const NESTED_ARRAY = ["oneOf", "anyOf", "allOf"];

/**
* Recursively processes a JSON Schema using a visitor pattern.
*
* @param {SchemaVisitor} visitor
* @param {JSONSchema | boolean} json
* @param {ProcessContext} [context]
* @returns {JSONSchema | boolean}
*/
const processSchema = (visitor, json, context) => {
if (!json || typeof json !== "object") return json;

json = { ...json };
if (visitor.schema) json = visitor.schema(json, context);

if (typeof visitor?.schema === "function") {
json = visitor.schema(json, context) || json;
}

for (const name of NESTED_WITH_NAME) {
if (name in json && json[name] && typeof json[name] === "object") {
if (visitor.object) json[name] = visitor.object(json[name], context);
for (const key in json[name]) {
if (name in json && json[name] && typeof json[name] === "object" && !Array.isArray(json[name])) {
if (typeof visitor?.object === "function") {
json[name] = visitor.object(json[name], context) || json[name];
}

for (const key of Object.keys(json[name])) {
json[name][key] = processSchema(visitor, json[name][key], context);
}
}
}

for (const name of NESTED_DIRECT) {
if (name in json && json[name] && typeof json[name] === "object") {
if (name in json && json[name] && typeof json[name] === "object" && !Array.isArray(json[name])) {
json[name] = processSchema(visitor, json[name], context);
}
}

for (const name of NESTED_ARRAY) {
if (name in json && Array.isArray(json[name])) {
json[name] = json[name].slice();
for (let i = 0; i < json[name].length; i++) {
json[name][i] = processSchema(visitor, json[name][i], context);
json[name] = json[name].map((item) => processSchema(visitor, item, context));

if (typeof visitor?.array === "function") {
visitor.array(json[name], context);
}
if (visitor.array) visitor.array(json[name], context);
}
}

return json;
};

module.exports = processSchema;