UNPKG

declapract

Version:

A tool to declaratively define best practices, maintainable evolve them, and scalably enforce them.

101 lines 5.79 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.fixContainsJSONByReplacingAndAddingKeyValues = void 0; const parseJSON_1 = require("../../../../../../utils/json/parseJSON"); const UnexpectedCodePathError_1 = require("../../../../../UnexpectedCodePathError"); const check_minVersion_1 = require("../checkExpressions/check.minVersion"); /** * e.g., replace a `@declapract{check.minVersion('..')}` strings in the declared contents * * typically used to create a new file from declarations */ const deepReplaceAllCheckExpressionsFromDeclaredContentsString = ({ declaredContents, }) => { return declaredContents.replace(/\@declapract\{check\.minVersion\('([0-9\.]+)'\)\}/g, '$1'); // using regexp capture groups to simplify this for now since we only have the minVersion expression; // TODO: make this more generic to handle other check expression types }; /** * replaces the value of each key in `currentObject` with the value of that key in `desiredObject`, if its already in `currentObject`, recursively */ const deepReplaceOrAddCurrentKeyValuesWithDesiredKeyValues = ({ currentObject, desiredObject, }) => { // if either key is not an object, return the current object without doing anything - we found a normal value if (typeof currentObject !== 'object' || typeof desiredObject !== 'object') return currentObject; // if either input is null, return null; (special case of whats intended with the above since technically `null` _is_ typeof object) if (currentObject === null || desiredObject === null) return currentObject; // merge the keys const currentKeys = Object.keys(currentObject); const keysToAdd = Object.keys(desiredObject).filter((desiredKey) => !currentKeys.includes(desiredKey)); const mergedKeys = [...currentKeys, ...keysToAdd]; // add the keys to the end // replace the value of each key in currentObject with the value in desiredObject, if exists in currentObject, deeply // using a for loop to ensure key order (no "parallelism", one at a time) const newObject = {}; for (const thisKey of mergedKeys) { const currentValue = currentObject[thisKey]; const desiredValue = desiredObject[thisKey]; const newValue = (() => { if (currentValue === undefined) return desiredValue; // if current value is not defined at all, then we should add it to be the desired value if (desiredValue === undefined) return currentValue; // if there is no value defined in the desired object for this key, then keep the current value if (Array.isArray(desiredValue)) return desiredValue; // TODO: think through if we should do something special here if ((0, check_minVersion_1.isCheckMinVersionExpression)(desiredValue)) { const minVersion = (0, check_minVersion_1.getMinVersionFromCheckMinVersionExpression)(desiredValue); if (!minVersion) throw new UnexpectedCodePathError_1.UnexpectedCodePathError("checked that its a min version expression but couldn't extract a min version"); // fail fast if weird error occurs const passesMinVersion = (0, check_minVersion_1.checkDoesFoundValuePassesMinVersionCheck)({ foundValue: currentValue, minVersion, }); if (passesMinVersion) return currentValue; // dont change the current version if it passes the check return minVersion; // return the minimum version if it doesn't pass the check } if (typeof desiredValue !== 'object') return desiredValue; if (desiredValue === null) return desiredValue; return deepReplaceOrAddCurrentKeyValuesWithDesiredKeyValues({ currentObject: currentValue, desiredObject: desiredValue, }); })(); newObject[thisKey] = newValue; } // return the new object return newObject; }; /** * fix contains json by replacing and adding key values * - replaces keys in place (order not change) * - adds keys to the end (note: folks should specify a check that checks order if it matters, and have that check fix things) */ const fixContainsJSONByReplacingAndAddingKeyValues = (contents, context) => { // check that declared contents exist; if not, then nothing to do const declaredContents = context.declaredFileContents; if (!declaredContents) return {}; // if no declared file contents, then we cant change anything // check that the file exists; if not, if (!contents) return { contents: context.declaredFileContents ? deepReplaceAllCheckExpressionsFromDeclaredContentsString({ declaredContents, }) // replace the check expressions, if declaredFileContents : context.declaredFileContents, }; // if the file DNE // parse the contents const foundPackageJSON = (0, parseJSON_1.parseJSON)(contents); const declaredPackageJSON = (0, parseJSON_1.parseJSON)(declaredContents); // for each key in declared package json, replace the key if it exists in the found package const fixedPackageJSON = deepReplaceOrAddCurrentKeyValuesWithDesiredKeyValues({ currentObject: foundPackageJSON, desiredObject: declaredPackageJSON, }); // and return the contents now return { contents: JSON.stringify(fixedPackageJSON, null, 2), }; }; exports.fixContainsJSONByReplacingAndAddingKeyValues = fixContainsJSONByReplacingAndAddingKeyValues; //# sourceMappingURL=fixContainsJSONByReplacingAndAddingKeyValues.js.map