/** * Return an object that describes types of the given value. * * @param {unknown} value * @param {object} schema */ function buildSchema(value, schema = {}) { if (value === null) { schema.nulls = (schema.nulls || 0) + 1; return schema; } if (typeof value === 'string') { schema.strings = (schema.strings || 0) + 1; return schema; } if (typeof value === 'number') { schema.numbers = (schema.numbers || 0) + 1; return schema; } if (Array.isArray(value)) { schema.arrayOf = schema.arrayOf || {}; value.forEach(el => buildSchema(el, schema.arrayOf)); return schema; } if (typeof value === 'object') { schema.obj = schema.obj || {}; for (const [k2, v2] of Object.entries(value)) { schema.obj[k2] = schema.obj[k2] || {}; buildSchema(v2, schema.obj[k2]); } // Check for missing properties that the schema knows about. for (const k3 of Object.keys(schema.obj)) { if (!Object.hasOwn(value, k3)) { schema.obj[k3].undefineds = (schema.obj[k3].undefineds || 0) + 1; } } } return schema; }