From c93a799653d4825339f8bf9f4556cc8a1f2a9838 Mon Sep 17 00:00:00 2001 From: Mariusz Nowak Date: Wed, 7 Oct 2020 13:03:02 +0200 Subject: [PATCH] fix(Config Schema): Ensure to preserve `null` properties in user config --- lib/classes/ConfigSchemaHandler/index.js | 43 +++++++++++++++--------- 1 file changed, 28 insertions(+), 15 deletions(-) diff --git a/lib/classes/ConfigSchemaHandler/index.js b/lib/classes/ConfigSchemaHandler/index.js index 3f89d39a87a..205ffaceca1 100644 --- a/lib/classes/ConfigSchemaHandler/index.js +++ b/lib/classes/ConfigSchemaHandler/index.js @@ -25,21 +25,32 @@ const normalizeSchemaObject = (object, instanceSchema) => { // Normalizer is introduced to workaround https://github.com/ajv-validator/ajv/issues/1287 // normalizedObjectsMap allows to handle circular structures without issues -const normalizedObjectsSet = new WeakSet(); -const normalizeUserConfig = object => { - if (normalizedObjectsSet.has(object)) return object; - normalizedObjectsSet.add(object); - if (Array.isArray(object)) { - for (const value of object) { - if (_.isObject(value)) normalizeUserConfig(value); - } - } else { - for (const [key, value] of Object.entries(object)) { - if (value == null) delete object[key]; - else if (_.isObject(value)) normalizeUserConfig(value); +const normalizeUserConfig = userConfig => { + const normalizedObjectsSet = new WeakSet(); + const nullPaths = []; + const normalizeObject = (object, path) => { + if (normalizedObjectsSet.has(object)) return; + normalizedObjectsSet.add(object); + if (Array.isArray(object)) { + for (const [index, value] of object.entries()) { + if (_.isObject(value)) normalizeObject(value, path.concat(index)); + } + } else { + for (const [key, value] of Object.entries(object)) { + if (value == null) { + nullPaths.push(path.concat(key)); + delete object[key]; + } else if (_.isObject(value)) { + normalizeObject(value, path.concat(key)); + } + } } - } - return object; + }; + normalizeObject(userConfig, []); + return { nullPaths }; +}; +const denormalizeUserConfig = (userConfig, { nullPaths }) => { + for (const nullPath of nullPaths) _.set(userConfig, nullPath, null); }; class ConfigSchemaHandler { @@ -96,7 +107,9 @@ class ConfigSchemaHandler { normalizeSchemaObject(this.schema, this.schema); const validate = ajv.compile(this.schema); - validate(normalizeUserConfig(userConfig)); + const denormalizeOptions = normalizeUserConfig(userConfig); + validate(userConfig); + denormalizeUserConfig(userConfig, denormalizeOptions); if (validate.errors) { const messages = normalizeAjvErrors(validate.errors).map(err => err.message); this.handleErrorMessages(messages);