"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.setValue = exports.selectorToDataTestSubject = exports.hasTemplateSnippet = exports.getValue = exports.checkIfSamePath = void 0; /* * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one * or more contributor license agreements. Licensed under the Elastic License * 2.0; you may not use this file except in compliance with the Elastic License * 2.0. */ const selectorToDataTestSubject = selector => selector.join('>'); exports.selectorToDataTestSubject = selectorToDataTestSubject; /** * The below get and set functions are built with an API to make setting * and getting and setting values more simple. * * @remark * NEVER use these with objects that contain keys created by user input. */ /** * Given a path, get the value at the path * * @remark * If path is an empty array, return the source. */ const getValue = (path, source) => { let current = source; for (const key of path) { current = current[key]; } return current; }; exports.getValue = getValue; const ARRAY_TYPE = Object.prototype.toString.call([]); const OBJECT_TYPE = Object.prototype.toString.call({}); const dumbCopy = value => { const objectType = Object.prototype.toString.call(value); if (objectType === ARRAY_TYPE) { return [...value]; } else if (objectType === OBJECT_TYPE) { return { ...value }; } throw new Error(`Expected (${ARRAY_TYPE}|${OBJECT_TYPE}) but received ${objectType}`); }; const WHITELISTED_KEYS_REGEX = /^([0-9]+|onFailure|processors)$/; /** * Given a path, value and an object (array or object) set * the value at the path and copy objects values on the * path only. This is a partial copy mechanism that is best * effort for providing state updates to the UI, could break down * if other updates are made to non-copied parts of state in external * references - but this should not happen. * * @remark * If path is empty, just shallow copy source. */ const setValue = (path, source, value) => { if (!path.length) { return dumbCopy(source); } let current; let result; for (let idx = 0; idx < path.length; ++idx) { const key = path[idx]; if (!WHITELISTED_KEYS_REGEX.test(key)) { // eslint-disable-next-line no-console console.error(`Received non-whitelisted key "${key}". Aborting set value operation; returning original.`); return dumbCopy(source); } const atRoot = !current; if (atRoot) { result = dumbCopy(source); current = result; } if (idx + 1 === path.length) { current[key] = value; } else { current[key] = dumbCopy(current[key]); current = current[key]; } } return result; }; exports.setValue = setValue; const checkIfSamePath = (pathA, pathB) => { if (pathA.length !== pathB.length) return false; return pathA.join('.') === pathB.join('.'); }; /* * Given a string it checks if it contains a valid mustache template snippet. * * Note: This allows strings with spaces such as: {{{hello world}}}. I figured we * should use .+ instead of \S (disallow all whitespaces) because the backend seems * to allow spaces inside the template snippet anyway. * * See: https://www.elastic.co/guide/en/elasticsearch/reference/master/ingest.html#template-snippets */ exports.checkIfSamePath = checkIfSamePath; const hasTemplateSnippet = (str = '') => { // Matches when: // * contains a {{{ // * Followed by all strings of length >= 1 // * And followed by }}} return /{{{.+}}}/.test(str); }; exports.hasTemplateSnippet = hasTemplateSnippet;