variables from collection environments are rendered as dotenv variables

This commit is contained in:
2026-06-30 12:24:10 +02:00
parent 25c271f291
commit c03706d251
+61 -27
View File
@@ -294,7 +294,7 @@ function getRequestConfigForFile(yamlFile, sourceDir) {
return resolved.reduce((result, config) => mergeRequestConfig(result, config), {});
}
function buildRequestContent(request, requestName, requestConfig = {}) {
function buildRequestContent(request, requestName, requestConfig = {}, dotenvVariables = new Set()) {
const lines = [];
const variableDefinitions = [];
const seenVariables = new Set();
@@ -304,13 +304,32 @@ function buildRequestContent(request, requestName, requestConfig = {}) {
return;
}
const normalized = String(name).trim();
if (!normalized || seenVariables.has(normalized)) {
if (!normalized || seenVariables.has(normalized) || dotenvVariables.has(normalized)) {
return;
}
seenVariables.add(normalized);
variableDefinitions.push({ name: normalized, value });
};
const addReferencedVariables = (value, fallbackValue = 'YOUR_VALUE_HERE') => {
for (const placeholder of collectPlaceholders(String(value))) {
addVariable(placeholder, fallbackValue);
}
};
const renderValue = (value) => {
if (typeof value !== 'string') {
return value;
}
return value.replace(/\{\{([^{}]+)\}\}/g, (match, name) => {
const normalized = String(name).trim();
if (normalized && dotenvVariables.has(normalized)) {
return `{{$dotenv ${normalized}}}`;
}
return match;
});
};
const configVariables = Array.isArray(requestConfig.variables) ? requestConfig.variables : [];
for (const variable of configVariables) {
if (variable && variable.name) {
@@ -320,10 +339,9 @@ function buildRequestContent(request, requestName, requestConfig = {}) {
let url = request.url || '';
if (url) {
for (const placeholder of collectPlaceholders(url)) {
addVariable(placeholder, 'YOUR_VALUE_HERE');
}
addReferencedVariables(url);
url = url.replace(/:([A-Za-z0-9_]+)/g, (_, name) => `{{${name}}}`);
url = renderValue(url);
// Since Bruno puts enabled params in the URL, this avoids duplicate query params
url = url.split('?')[0];
}
@@ -335,10 +353,8 @@ function buildRequestContent(request, requestName, requestConfig = {}) {
if (!header || !header.name) {
continue;
}
for (const placeholder of collectPlaceholders(String(header.value ?? ''))) {
addVariable(placeholder, 'YOUR_VALUE_HERE');
}
headers.push({ name: header.name, value: header.value ?? '' });
addReferencedVariables(header.value ?? '');
headers.push({ name: header.name, value: renderValue(header.value ?? '') });
}
for (const param of request.params || []) {
@@ -351,40 +367,32 @@ function buildRequestContent(request, requestName, requestConfig = {}) {
continue;
}
for (const placeholder of collectPlaceholders(String(value))) {
addVariable(placeholder, 'YOUR_VALUE_HERE');
}
addReferencedVariables(value);
if (type === 'header') {
headers.push({ name, value });
headers.push({ name, value: renderValue(value) });
} else {
queryParams.push({ name, value });
queryParams.push({ name, value: renderValue(value) });
}
}
if (requestConfig.auth)
{
if (requestConfig.auth.type === 'bearer') {
for (const placeholder of collectPlaceholders(String(requestConfig.auth.token ?? ''))) {
addVariable(placeholder, 'YOUR_VALUE_HERE');
}
addReferencedVariables(requestConfig.auth.token ?? '');
headers.push({
name: 'Authorization',
value: `Bearer ${requestConfig.auth.token ?? ''}`,
value: `Bearer ${renderValue(requestConfig.auth.token ?? '')}`,
});
} else if (requestConfig.auth.type === 'basic') {
const username = requestConfig.auth.username ?? '';
const password = requestConfig.auth.password ?? '';
for (const placeholder of collectPlaceholders(String(username))) {
addVariable(placeholder, 'YOUR_VALUE_HERE');
}
for (const placeholder of collectPlaceholders(String(password))) {
addVariable(placeholder, 'YOUR_VALUE_HERE');
}
addReferencedVariables(username);
addReferencedVariables(password);
// VSCode REST Client can manage username:password format directly!
headers.push({
name: 'Authorization',
value: `Basic ${username}:${password}`,
value: `Basic ${renderValue(username)}:${renderValue(password)}`,
});
} else {
headers.push({
@@ -440,8 +448,30 @@ function walkYamlFiles(rootDir) {
return results;
}
function getDotenvVariablesForTargetDir(targetDir, outputRoot, dotenvVariablesByTarget) {
const variables = new Set();
let currentDir = targetDir;
while (true) {
const vars = dotenvVariablesByTarget.get(currentDir);
if (vars) {
for (const variable of vars) {
variables.add(variable);
}
}
if (currentDir === outputRoot || path.dirname(currentDir) === currentDir) {
break;
}
currentDir = path.dirname(currentDir);
}
return variables;
}
function writeEnvironmentTemplates(sourceDir, outputRoot) {
const targets = [];
const dotenvVariablesByTarget = new Map();
const visit = (currentDir) => {
const entries = fs.readdirSync(currentDir, { withFileTypes: true });
@@ -496,7 +526,10 @@ function writeEnvironmentTemplates(sourceDir, outputRoot) {
const templateContent = variableNames.length > 0 ? `${variableNames.map(v => `${v}={{${v}}}`).join('\n')}\n` : '';
fs.writeFileSync(path.join(targetDir, '.env.template'), templateContent, 'utf8');
dotenvVariablesByTarget.set(targetDir, new Set(variableNames));
}
return dotenvVariablesByTarget;
}
function main() {
@@ -522,7 +555,7 @@ function main() {
const outputRoot = path.join(workspaceRoot, 'autodocs', 'http', collection.name);
ensureDir(outputRoot);
writeEnvironmentTemplates(sourceDir, outputRoot);
const dotenvVariablesByTarget = writeEnvironmentTemplates(sourceDir, outputRoot);
const yamlFiles = walkYamlFiles(sourceDir);
let processed = 0;
@@ -542,7 +575,8 @@ function main() {
const requestConfig = getRequestConfigForFile(yamlFile, sourceDir);
const outputFile = path.join(targetDir, `${parsedPath.name}.http`);
const requestContent = buildRequestContent(httpBlock, requestName, requestConfig);
const dotenvVariables = getDotenvVariablesForTargetDir(targetDir, outputRoot, dotenvVariablesByTarget);
const requestContent = buildRequestContent(httpBlock, requestName, requestConfig, dotenvVariables);
fs.writeFileSync(outputFile, `${requestContent}\n`, 'utf8');
processed += 1;
}