UNPKG

@catladder/cli

Version:

Panter cli tool for cloud CI/CD and DevOps

137 lines 6.04 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.escapeForDotEnv = exports.escapeNewlines = exports.escapeBackTicks = exports.escapeSingleQuotes = exports.escapeDoubleQuotes = exports.escapeBashExpression = exports.escapeString = exports.bashEscape = void 0; const globalScriptFunctions_1 = require("../globalScriptFunctions"); const VariableValueContainingReferences_1 = require("../variables/VariableValueContainingReferences"); const BashExpression_1 = require("./BashExpression"); /** * escapes a string or bash expression for bash * it either can escape single or double quotes (double is default) */ const bashEscape = (value, options = { quotes: "double", }) => { if (value instanceof BashExpression_1.BashExpression) { // no need to escape return (0, exports.escapeBashExpression)(value, options); } if (value instanceof VariableValueContainingReferences_1.VariableValueContainingReferences) { return value.toString(options); } return (0, exports.escapeString)(value, options); }; exports.bashEscape = bashEscape; const escapeString = (value, { quotes } = { quotes: "double", }) => { const quoteEscaped = quotes ? quotes === "single" ? (0, exports.escapeSingleQuotes)(value) : (0, exports.escapeDoubleQuotes)(value) : value; return quoteEscaped; }; exports.escapeString = escapeString; const escapeBashExpression = (value, options) => { // no need to escape, we just return the string return value; }; exports.escapeBashExpression = escapeBashExpression; const escapeDoubleQuotes = (value) => value === null || value === void 0 ? void 0 : value.toString().replace(/"/g, '\\"'); exports.escapeDoubleQuotes = escapeDoubleQuotes; const escapeSingleQuotes = (value) => value === null || value === void 0 ? void 0 : value.toString().replace(/'/g, "\\'"); exports.escapeSingleQuotes = escapeSingleQuotes; const escapeBackTicks = (value) => value === null || value === void 0 ? void 0 : value.toString().replace(/`/g, "\\`"); exports.escapeBackTicks = escapeBackTicks; const escapeNewlines = (value) => value === null || value === void 0 ? void 0 : value.toString().replace(/\n/g, "\\n"); exports.escapeNewlines = escapeNewlines; /** * * escape env vars for .env files. * unfortunatly, the format has many limitations. In order to be very forgiving, we need to do some magic here: * * - when the value contains no newlines, we are fine * - if the value contains newlines, we need to wrap it in quotes. And thats where the problem begins: * - you can't escape quotes. this is a limitation of dotenv and node * - you can have inner quotes, but they break in node.js (not in dotenv though), see https://github.com/nodejs/node/issues/54134 * - so we need to quote cleverly * - to make things worse, we need to check whether we have a simple stirng or a bash expression, that needs to be evalulated first... * * what an absolute nightmare. * * - other languages are currently only partially supported, since most .env implementations are slightly different */ const escapeForDotEnv = (value, options = { quoteMode: "auto", }) => { if (value === undefined || value === null) { return ""; } if (typeof value === "string") { // if string contains newlines, we need to wrap it in quotes // we additionaly escape newlines, that give best compatibility if (options.quoteMode === "always" || value.includes("\n")) { const newlinesReplaces = value.replace(/\n/g, "\\n"); // default to ", but if this is not possible, we try to use ' or ` const quote = value.includes(`"`) ? value.includes(`'`) ? value.includes("`") ? // If all quote types are present, default to double quotes. This works in dotenv, but not in node.js because of the bug mentioned abouve '"' : "`" : "'" : '"'; // if we found a quote, we can wrap the string in it return `${quote}${newlinesReplaces}${quote}`; } else { // otherwise we can return as is return value; } } else if (value instanceof BashExpression_1.BashExpression) { return escapeBashExpressionForDotEnv(value); } else if (value instanceof VariableValueContainingReferences_1.VariableValueContainingReferences) { // instead of doing it part-wise, we just do it all at once const containsAnyBashExpression = value.parts.some((part) => part instanceof BashExpression_1.BashExpression); if (!containsAnyBashExpression) { return (0, exports.escapeForDotEnv)(value.toString({ quotes: "double", })); } else { const result = escapeBashExpressionForDotEnv(new BashExpression_1.BashExpression(value.toString({ quotes: "double", }))); return result; } } else { return value; } }; exports.escapeForDotEnv = escapeForDotEnv; // basically the same thing as above for bash // thx chatgpt for this const escapeForDotEnvScript = (0, globalScriptFunctions_1.registerGlobalScriptFunction)("escapeForDotEnv", ` input="\${1:-$(cat)}" input="\${input//$'\\n'/\\\\n}" if [[ "$input" == *\\\\n* ]]; then if [[ "$input" == *\\"* && "$input" == *\\'* && "$input" == *\\\`* ]]; then printf "\\"%s\\"\\n" "$input" ${ /* fallback to double quotes */""} elif [[ "$input" == *\\"* && "$input" == *\\'* ]]; then printf "\`%s\`\\n" "$input" elif [[ "$input" == *\\"* ]]; then printf "'%s'\\n" "$input" else printf "\\"%s\\"\\n" "$input" fi else printf "%s\\n" "$input" fi `); const escapeBashExpressionForDotEnv = (value) => { return value.transformWithCommand(escapeForDotEnvScript.name).toString(); }; //# sourceMappingURL=bashEscape.js.map