UNPKG

eslint-plugin-logical-properties

Version:
103 lines (102 loc) 3.98 kB
import { propertyTraverseWildcard } from './propertyTraverse.constants.js'; export const pathToSegments = (path) => (path .replaceAll(/(\w+)(\[[^\]]])/g, '$1.$2') .split('.')); export const segmentsToPath = (segments) => (segments.join('.')); export const isWildcard = (input) => (input === propertyTraverseWildcard); export const segmentsIsEmpty = (input) => (input.length === 0 || (input.length === 1 && input[0] === '')); function normlizePackInput(input, separator = '`') { const segments = [...input]; let nextIndex = segments.indexOf(separator); let open = true; if (nextIndex < 0) { return input; } do { if (open) { segments.splice(nextIndex, 1, `"${separator}`); open = false; } else { segments.splice(nextIndex, 1, `${separator}"`); open = true; } nextIndex = segments.indexOf(separator, nextIndex + 2); } while (nextIndex >= 0); return segments.join(''); } function normalizePackOutput(input, separator = '`') { return input .replaceAll(`"${separator}`, `${separator}`) .replaceAll(`${separator}"`, `${separator}`); } export const packer = { unpack: (input) => { const normalized = normlizePackInput(normlizePackInput(input, '`'), '\'') .replaceAll(/":\s*([\d.A-Za-z-]+)\s*/g, '":"$1"') .replaceAll(/":\s*\${([\d.A-Za-z-]+)\s*}/g, '":"$1"'); try { const parsed = JSON.parse(normalized); return parsed; } catch { throw new Error(JSON.stringify({ input, normalized, }, undefined, 2)); } }, pack: (input) => { const stringified = JSON.stringify(input); const normalized = normalizePackOutput(normalizePackOutput(stringified, '`'), '\''); return normalized; }, }; export const generateObjectStringFromPath = (input, insert) => { const segments = Array.isArray(input) ? input : pathToSegments(input); if (segmentsIsEmpty(segments)) { return insert; } const [current, ...nextSegments] = segments; const nextString = generateObjectStringFromPath(nextSegments, insert); const next = packer.unpack(nextString); const maybeAccessor = current.match(/^\[(\d+)]$/); if (maybeAccessor) { const [, match] = maybeAccessor; const index = Number.parseInt(match, 10); const newArray = Array.from({ length: index + 2 }); newArray[index] = next; return packer.pack(newArray); } const newObject = { [current]: next }; return packer.pack(newObject); }; export const generateObjectStringsFromPaths = (input, insert) => { const paths = input.includes('') ? input : ['', ...input]; return paths.map((path) => generateObjectStringFromPath(path, insert)); }; export const generateObjectStringTestCaseDeclaration = ({ testName, functionName }, objectString) => `const ${testName} = ${functionName}(${objectString})`; export const generateObjectStringTestCases = ({ resolvers, ...declarationOptions }, { input, output, }) => { const inputObject = typeof input === 'string' ? input : packer.pack(input); const outputObject = output ? (typeof output === 'string' ? output : packer.pack(output)) : undefined; const declarationGenerator = generateObjectStringTestCaseDeclaration.bind(undefined, declarationOptions); const inputObjectStrings = generateObjectStringsFromPaths(resolvers, inputObject).map(declarationGenerator); const outputObjectStrings = outputObject ? generateObjectStringsFromPaths(resolvers, outputObject).map(declarationGenerator) : []; const result = []; for (const [index, code] of Object.entries(inputObjectStrings)) { result.push({ code, output: outputObjectStrings[index], }); } return result; };