From aa272dfc5564cd1b66db2d4335594c40534ffdec Mon Sep 17 00:00:00 2001 From: Pier-Paolo Mammi Date: Fri, 26 Jun 2026 13:51:52 +0200 Subject: [PATCH 01/40] add AI generated script add gitignore for automatically generated stuff --- .gitignore | 5 +- scripts/generate-http-docs.js | 325 ++++++++++++++++++++++++++++++++++ 2 files changed, 329 insertions(+), 1 deletion(-) create mode 100644 scripts/generate-http-docs.js diff --git a/.gitignore b/.gitignore index 1dd09a2..b2d314a 100644 --- a/.gitignore +++ b/.gitignore @@ -7,4 +7,7 @@ node_modules # OS files .DS_Store -Thumbs.db \ No newline at end of file +Thumbs.db + +# Automatically generated stuff +autodocs/**/* \ No newline at end of file diff --git a/scripts/generate-http-docs.js b/scripts/generate-http-docs.js new file mode 100644 index 0000000..cee0999 --- /dev/null +++ b/scripts/generate-http-docs.js @@ -0,0 +1,325 @@ +#!/usr/bin/env node +const fs = require('fs'); +const path = require('path'); + +function findWorkspaceRoot(startDir) { + let current = startDir; + while (true) { + if (fs.existsSync(path.join(current, 'workspace.yml'))) { + return current; + } + const parent = path.dirname(current); + if (parent === current) { + throw new Error('workspace.yml not found from the provided start directory'); + } + current = parent; + } +} + +function readText(filePath) { + return fs.readFileSync(filePath, 'utf8'); +} + +function stripQuotes(value) { + const trimmed = String(value).trim(); + if ((trimmed.startsWith('"') && trimmed.endsWith('"')) || (trimmed.startsWith("'") && trimmed.endsWith("'"))) { + return trimmed.slice(1, -1); + } + return trimmed; +} + +function parseWorkspace(workspacePath) { + const text = readText(workspacePath); + const lines = text.split(/\r?\n/); + const collections = []; + let inCollections = false; + let currentCollection = null; + + for (const line of lines) { + const trimmed = line.trim(); + if (!inCollections && trimmed === 'collections:') { + inCollections = true; + continue; + } + + if (!inCollections) { + continue; + } + + if (!line.startsWith(' ') && !line.startsWith('\t') && trimmed) { + break; + } + + const nameMatch = line.match(/^\s*-\s+name:\s*(.+)$/); + if (nameMatch) { + currentCollection = { name: stripQuotes(nameMatch[1]) }; + collections.push(currentCollection); + continue; + } + + const pathMatch = line.match(/^\s*path:\s*(.+)$/); + if (pathMatch && currentCollection) { + currentCollection.path = stripQuotes(pathMatch[1]); + } + } + + return { collections }; +} + +function sanitizeVarName(value) { + return String(value) + .trim() + .replace(/[{}]/g, '') + .replace(/[^A-Za-z0-9_]/g, '_') + .replace(/^([0-9])/, '_$1') || 'value'; +} + +function collectPlaceholders(value) { + if (typeof value !== 'string') { + return []; + } + const placeholders = []; + const regex = /\{\{([^{}]+)\}\}/g; + let match; + while ((match = regex.exec(value)) !== null) { + placeholders.push(match[1]); + } + return placeholders; +} + +function findBlock(lines, keyName) { + for (let i = 0; i < lines.length; i += 1) { + const trimmed = lines[i].trim(); + if (trimmed !== keyName && !trimmed.startsWith(`${keyName}:`)) { + continue; + } + + const lineIndent = lines[i].match(/^\s*/)[0].length; + const block = []; + for (let j = i + 1; j < lines.length; j += 1) { + const currentLine = lines[j]; + const currentTrimmed = currentLine.trim(); + if (!currentTrimmed) { + block.push(currentLine); + continue; + } + const currentIndent = currentLine.match(/^\s*/)[0].length; + if (currentIndent <= lineIndent && !currentLine.startsWith(' ')) { + break; + } + if (currentIndent <= lineIndent && currentTrimmed.startsWith('#')) { + block.push(currentLine); + continue; + } + if (currentIndent <= lineIndent) { + break; + } + block.push(currentLine); + } + return block; + } + return []; +} + +function parseRequestInfo(text) { + const lines = text.split(/\r?\n/); + const infoLines = findBlock(lines, 'info'); + const nameMatch = infoLines.join('\n').match(/^\s*name:\s*(.+)$/m); + return nameMatch ? stripQuotes(nameMatch[1]) : ''; +} + +function parseHttpBlock(text) { + const lines = text.split(/\r?\n/); + const blockLines = findBlock(lines, 'http'); + const blockText = blockLines.join('\n'); + const methodMatch = blockText.match(/^\s*method:\s*(.+)$/m); + const urlMatch = blockText.match(/^\s*url:\s*(.+)$/m); + + const params = []; + const paramLines = blockLines.join('\n').split(/\r?\n/); + let inParamsBlock = false; + let paramsIndent = 0; + let currentParam = null; + + for (const line of paramLines) { + const trimmed = line.trim(); + if (!inParamsBlock) { + if (trimmed === 'params:') { + inParamsBlock = true; + paramsIndent = line.match(/^\s*/)[0].length; + } + continue; + } + + if (!trimmed) { + continue; + } + + const indent = line.match(/^\s*/)[0].length; + if (indent <= paramsIndent) { + break; + } + + const listItemMatch = line.match(/^\s*-\s+name:\s*(.+)$/); + if (listItemMatch) { + currentParam = { name: stripQuotes(listItemMatch[1]) }; + params.push(currentParam); + continue; + } + + if (!currentParam) { + continue; + } + + const propertyMatch = line.match(/^\s*([A-Za-z0-9_]+):\s*(.+)$/); + if (propertyMatch) { + const [, key, value] = propertyMatch; + currentParam[key] = stripQuotes(value); + } + } + + return { + method: methodMatch ? stripQuotes(methodMatch[1]) : 'GET', + url: urlMatch ? stripQuotes(urlMatch[1]) : '', + params, + }; +} + +function buildRequestContent(request, requestName) { + const lines = []; + const placeholders = new Set(); + + const addPlaceholders = (value) => { + for (const placeholder of collectPlaceholders(value)) { + placeholders.add(placeholder); + } + }; + + let url = request.url || ''; + if (url) { + addPlaceholders(url); + url = url.replace(/:([A-Za-z0-9_]+)/g, (_, name) => `{{${name}}}`); + } + + const queryParams = []; + const headers = []; + for (const param of request.params || []) { + const name = param.name || ''; + const value = param.value || ''; + const type = (param.type || 'query').toLowerCase(); + const disabled = String(param.disabled).toLowerCase() === 'true'; + + if (disabled) { + continue; + } + + addPlaceholders(value); + if (type === 'header') { + headers.push({ name, value }); + } else { + queryParams.push({ name, value }); + } + } + + if (placeholders.size > 0) { + lines.push(`# Variables for ${requestName}`); + for (const placeholder of [...placeholders].sort()) { + lines.push(`@${sanitizeVarName(placeholder)} = YOUR_VALUE_HERE`); + } + lines.push(''); + } + + const method = (request.method || 'GET').toUpperCase(); + let requestUrl = url; + for (const param of queryParams) { + if (!param.name) { + continue; + } + const separator = requestUrl.includes('?') ? '&' : '?'; + requestUrl = `${requestUrl}${separator}${param.name}=${param.value}`; + } + + lines.push(`${method} ${requestUrl}`); + for (const header of headers) { + lines.push(`${header.name}: ${header.value}`); + } + return lines.join('\n'); +} + +function ensureDir(dirPath) { + fs.mkdirSync(dirPath, { recursive: true }); +} + +function walkYamlFiles(rootDir) { + const results = []; + const entries = fs.readdirSync(rootDir, { withFileTypes: true }); + for (const entry of entries) { + if (entry.name.startsWith('.') || entry.name === 'node_modules') { + continue; + } + const fullPath = path.join(rootDir, entry.name); + if (entry.isDirectory()) { + results.push(...walkYamlFiles(fullPath)); + } else if (entry.isFile() && /\.ya?ml$/i.test(entry.name)) { + results.push(fullPath); + } + } + return results; +} + +function main() { + const workspaceRoot = findWorkspaceRoot(__dirname); + const workspaceFile = path.join(workspaceRoot, 'workspace.yml'); + const workspace = parseWorkspace(workspaceFile); + const collections = Array.isArray(workspace.collections) ? workspace.collections : []; + + if (collections.length === 0) { + throw new Error('No collections found in workspace.yml'); + } + + for (const collection of collections) { + if (!collection || !collection.name || !collection.path) { + continue; + } + + const sourceDir = path.join(workspaceRoot, collection.path); + if (!fs.existsSync(sourceDir)) { + console.warn(`Skipping missing collection path: ${collection.path}`); + continue; + } + + const outputRoot = path.join(workspaceRoot, 'autodocs', 'http', collection.name); + ensureDir(outputRoot); + + const yamlFiles = walkYamlFiles(sourceDir); + let processed = 0; + + for (const yamlFile of yamlFiles) { + const content = readText(yamlFile); + const requestName = parseRequestInfo(content) || path.basename(yamlFile, path.extname(yamlFile)); + const httpBlock = parseHttpBlock(content); + if (!httpBlock || !httpBlock.url) { + continue; + } + + const relativePath = path.relative(sourceDir, yamlFile); + const parsedPath = path.parse(relativePath); + const targetDir = path.join(outputRoot, parsedPath.dir); + ensureDir(targetDir); + + const outputFile = path.join(targetDir, `${parsedPath.name}.http`); + const requestContent = buildRequestContent(httpBlock, requestName); + fs.writeFileSync(outputFile, `${requestContent}\n`, 'utf8'); + processed += 1; + } + + console.log(`Generated ${processed} .http file(s) for ${collection.name}`); + } +} + +try { + main(); +} catch (error) { + console.error(error.message); + process.exit(1); +} From 88517175321d628359255125a2172013d63d1e39 Mon Sep 17 00:00:00 2001 From: Pier-Paolo Mammi Date: Fri, 26 Jun 2026 14:50:23 +0200 Subject: [PATCH 02/40] refactor - add YAML module and remove python child process - add collection headers to each request - fix authorization header emission - create .env.template file with environment variables --- scripts/generate-http-docs.js | 742 ++++++++++++++++++++++------------ scripts/package-lock.json | 27 ++ scripts/package.json | 5 + 3 files changed, 519 insertions(+), 255 deletions(-) create mode 100644 scripts/package-lock.json create mode 100644 scripts/package.json diff --git a/scripts/generate-http-docs.js b/scripts/generate-http-docs.js index cee0999..36498a1 100644 --- a/scripts/generate-http-docs.js +++ b/scripts/generate-http-docs.js @@ -1,325 +1,557 @@ #!/usr/bin/env node const fs = require('fs'); const path = require('path'); +const YAML = require('yaml'); + +const interpolationVariableRegex = /^{{(.*?)}}$/ function findWorkspaceRoot(startDir) { - let current = startDir; - while (true) { - if (fs.existsSync(path.join(current, 'workspace.yml'))) { - return current; + let current = startDir; + while (true) { + if (fs.existsSync(path.join(current, 'workspace.yml'))) { + return current; + } + const parent = path.dirname(current); + if (parent === current) { + throw new Error('workspace.yml not found from the provided start directory'); + } + current = parent; } - const parent = path.dirname(current); - if (parent === current) { - throw new Error('workspace.yml not found from the provided start directory'); +} + +function parseYaml(filePath) { + try { + const text = fs.readFileSync(filePath, 'utf8'); + const parsed = YAML.parse(text); + return parsed || {}; + } catch (error) { + throw new Error(`Failed to parse YAML file ${filePath}: ${error.message}`); } - current = parent; - } } function readText(filePath) { - return fs.readFileSync(filePath, 'utf8'); + return fs.readFileSync(filePath, 'utf8'); } function stripQuotes(value) { - const trimmed = String(value).trim(); - if ((trimmed.startsWith('"') && trimmed.endsWith('"')) || (trimmed.startsWith("'") && trimmed.endsWith("'"))) { - return trimmed.slice(1, -1); - } - return trimmed; + const trimmed = String(value).trim(); + if ((trimmed.startsWith('"') && trimmed.endsWith('"')) || (trimmed.startsWith("'") && trimmed.endsWith("'"))) { + return trimmed.slice(1, -1); + } + return trimmed; } function parseWorkspace(workspacePath) { - const text = readText(workspacePath); - const lines = text.split(/\r?\n/); - const collections = []; - let inCollections = false; - let currentCollection = null; + const text = readText(workspacePath); + const lines = text.split(/\r?\n/); + const collections = []; + let inCollections = false; + let currentCollection = null; - for (const line of lines) { - const trimmed = line.trim(); - if (!inCollections && trimmed === 'collections:') { - inCollections = true; - continue; + for (const line of lines) { + const trimmed = line.trim(); + if (!inCollections && trimmed === 'collections:') { + inCollections = true; + continue; + } + + if (!inCollections) { + continue; + } + + if (!line.startsWith(' ') && !line.startsWith('\t') && trimmed) { + break; + } + + const nameMatch = line.match(/^\s*-\s+name:\s*(.+)$/); + if (nameMatch) { + currentCollection = { name: stripQuotes(nameMatch[1]) }; + collections.push(currentCollection); + continue; + } + + const pathMatch = line.match(/^\s*path:\s*(.+)$/); + if (pathMatch && currentCollection) { + currentCollection.path = stripQuotes(pathMatch[1]); + } } - if (!inCollections) { - continue; - } - - if (!line.startsWith(' ') && !line.startsWith('\t') && trimmed) { - break; - } - - const nameMatch = line.match(/^\s*-\s+name:\s*(.+)$/); - if (nameMatch) { - currentCollection = { name: stripQuotes(nameMatch[1]) }; - collections.push(currentCollection); - continue; - } - - const pathMatch = line.match(/^\s*path:\s*(.+)$/); - if (pathMatch && currentCollection) { - currentCollection.path = stripQuotes(pathMatch[1]); - } - } - - return { collections }; + return { collections }; } function sanitizeVarName(value) { - return String(value) - .trim() - .replace(/[{}]/g, '') - .replace(/[^A-Za-z0-9_]/g, '_') - .replace(/^([0-9])/, '_$1') || 'value'; + return String(value) + .trim() + .replace(/[{}]/g, '') + .replace(/[^A-Za-z0-9_]/g, '_') + .replace(/^([0-9])/, '_$1') || 'value'; } function collectPlaceholders(value) { - if (typeof value !== 'string') { - return []; - } - const placeholders = []; - const regex = /\{\{([^{}]+)\}\}/g; - let match; - while ((match = regex.exec(value)) !== null) { - placeholders.push(match[1]); - } - return placeholders; + if (typeof value !== 'string') { + return []; + } + const placeholders = []; + const regex = /\{\{([^{}]+)\}\}/g; + let match; + while ((match = regex.exec(value)) !== null) { + placeholders.push(match[1]); + } + return placeholders; } function findBlock(lines, keyName) { - for (let i = 0; i < lines.length; i += 1) { - const trimmed = lines[i].trim(); - if (trimmed !== keyName && !trimmed.startsWith(`${keyName}:`)) { - continue; - } + for (let i = 0; i < lines.length; i += 1) { + const trimmed = lines[i].trim(); + if (trimmed !== keyName && !trimmed.startsWith(`${keyName}:`)) { + continue; + } - const lineIndent = lines[i].match(/^\s*/)[0].length; - const block = []; - for (let j = i + 1; j < lines.length; j += 1) { - const currentLine = lines[j]; - const currentTrimmed = currentLine.trim(); - if (!currentTrimmed) { - block.push(currentLine); - continue; - } - const currentIndent = currentLine.match(/^\s*/)[0].length; - if (currentIndent <= lineIndent && !currentLine.startsWith(' ')) { - break; - } - if (currentIndent <= lineIndent && currentTrimmed.startsWith('#')) { - block.push(currentLine); - continue; - } - if (currentIndent <= lineIndent) { - break; - } - block.push(currentLine); + const lineIndent = lines[i].match(/^\s*/)[0].length; + const block = []; + for (let j = i + 1; j < lines.length; j += 1) { + const currentLine = lines[j]; + const currentTrimmed = currentLine.trim(); + if (!currentTrimmed) { + block.push(currentLine); + continue; + } + const currentIndent = currentLine.match(/^\s*/)[0].length; + if (currentIndent <= lineIndent && !currentLine.startsWith(' ')) { + break; + } + if (currentIndent <= lineIndent && currentTrimmed.startsWith('#')) { + block.push(currentLine); + continue; + } + if (currentIndent <= lineIndent) { + break; + } + block.push(currentLine); + } + return block; } - return block; - } - return []; + return []; } function parseRequestInfo(text) { - const lines = text.split(/\r?\n/); - const infoLines = findBlock(lines, 'info'); - const nameMatch = infoLines.join('\n').match(/^\s*name:\s*(.+)$/m); - return nameMatch ? stripQuotes(nameMatch[1]) : ''; + const lines = text.split(/\r?\n/); + const infoLines = findBlock(lines, 'info'); + const nameMatch = infoLines.join('\n').match(/^\s*name:\s*(.+)$/m); + return nameMatch ? stripQuotes(nameMatch[1]) : ''; } function parseHttpBlock(text) { - const lines = text.split(/\r?\n/); - const blockLines = findBlock(lines, 'http'); - const blockText = blockLines.join('\n'); - const methodMatch = blockText.match(/^\s*method:\s*(.+)$/m); - const urlMatch = blockText.match(/^\s*url:\s*(.+)$/m); + const lines = text.split(/\r?\n/); + const blockLines = findBlock(lines, 'http'); + const blockText = blockLines.join('\n'); + const methodMatch = blockText.match(/^\s*method:\s*(.+)$/m); + const urlMatch = blockText.match(/^\s*url:\s*(.+)$/m); - const params = []; - const paramLines = blockLines.join('\n').split(/\r?\n/); - let inParamsBlock = false; - let paramsIndent = 0; - let currentParam = null; + const params = []; + const paramLines = blockLines.join('\n').split(/\r?\n/); + let inParamsBlock = false; + let paramsIndent = 0; + let currentParam = null; - for (const line of paramLines) { - const trimmed = line.trim(); - if (!inParamsBlock) { - if (trimmed === 'params:') { - inParamsBlock = true; - paramsIndent = line.match(/^\s*/)[0].length; - } - continue; + for (const line of paramLines) { + const trimmed = line.trim(); + if (!inParamsBlock) { + if (trimmed === 'params:') { + inParamsBlock = true; + paramsIndent = line.match(/^\s*/)[0].length; + } + continue; + } + + if (!trimmed) { + continue; + } + + const indent = line.match(/^\s*/)[0].length; + if (indent <= paramsIndent) { + break; + } + + const listItemMatch = line.match(/^\s*-\s+name:\s*(.+)$/); + if (listItemMatch) { + currentParam = { name: stripQuotes(listItemMatch[1]) }; + params.push(currentParam); + continue; + } + + if (!currentParam) { + continue; + } + + const propertyMatch = line.match(/^\s*([A-Za-z0-9_]+):\s*(.+)$/); + if (propertyMatch) { + const [, key, value] = propertyMatch; + currentParam[key] = stripQuotes(value); + } } - if (!trimmed) { - continue; - } - - const indent = line.match(/^\s*/)[0].length; - if (indent <= paramsIndent) { - break; - } - - const listItemMatch = line.match(/^\s*-\s+name:\s*(.+)$/); - if (listItemMatch) { - currentParam = { name: stripQuotes(listItemMatch[1]) }; - params.push(currentParam); - continue; - } - - if (!currentParam) { - continue; - } - - const propertyMatch = line.match(/^\s*([A-Za-z0-9_]+):\s*(.+)$/); - if (propertyMatch) { - const [, key, value] = propertyMatch; - currentParam[key] = stripQuotes(value); - } - } - - return { - method: methodMatch ? stripQuotes(methodMatch[1]) : 'GET', - url: urlMatch ? stripQuotes(urlMatch[1]) : '', - params, - }; + return { + method: methodMatch ? stripQuotes(methodMatch[1]) : 'GET', + url: urlMatch ? stripQuotes(urlMatch[1]) : '', + params, + }; } -function buildRequestContent(request, requestName) { - const lines = []; - const placeholders = new Set(); - - const addPlaceholders = (value) => { - for (const placeholder of collectPlaceholders(value)) { - placeholders.add(placeholder); - } - }; - - let url = request.url || ''; - if (url) { - addPlaceholders(url); - url = url.replace(/:([A-Za-z0-9_]+)/g, (_, name) => `{{${name}}}`); - } - - const queryParams = []; - const headers = []; - for (const param of request.params || []) { - const name = param.name || ''; - const value = param.value || ''; - const type = (param.type || 'query').toLowerCase(); - const disabled = String(param.disabled).toLowerCase() === 'true'; - - if (disabled) { - continue; +function formatVariableValue(value) { + if (value === null || value === undefined) { + return '""'; } - addPlaceholders(value); - if (type === 'header') { - headers.push({ name, value }); - } else { - queryParams.push({ name, value }); + if (typeof value === 'string') { + if (value.trim() === '') { + return '""'; + } + if (/\s/.test(value)) { + return `"${value.replace(/"/g, '\\"')}"`; + } + return value; } - } - if (placeholders.size > 0) { - lines.push(`# Variables for ${requestName}`); - for (const placeholder of [...placeholders].sort()) { - lines.push(`@${sanitizeVarName(placeholder)} = YOUR_VALUE_HERE`); + return JSON.stringify(value); +} + +function mergeRequestConfig(base, updates) { + if (!updates || typeof updates !== 'object') { + return base; } - lines.push(''); - } - const method = (request.method || 'GET').toUpperCase(); - let requestUrl = url; - for (const param of queryParams) { - if (!param.name) { - continue; + const merged = { ...(base || {}) }; + if (updates.auth) { + if (updates.auth === 'inherit' && merged.auth && typeof merged.auth === 'object') { + merged.auth = merged.auth; + } else if (typeof updates.auth === 'object') { + merged.auth = updates.auth; + } } - const separator = requestUrl.includes('?') ? '&' : '?'; - requestUrl = `${requestUrl}${separator}${param.name}=${param.value}`; - } + if (Array.isArray(updates.variables)) { + const variables = [...(Array.isArray(base.variables) ? base.variables : [])]; + const byName = new Map(); + for (const variable of variables) { + if (variable && variable.name) { + byName.set(String(variable.name), variable); + } + } + for (const variable of updates.variables) { + if (variable && variable.name) { + byName.set(String(variable.name), variable); + } + } + merged.variables = [...byName.values()]; + } + return merged; +} - lines.push(`${method} ${requestUrl}`); - for (const header of headers) { - lines.push(`${header.name}: ${header.value}`); - } - return lines.join('\n'); +function getRequestConfigForFile(yamlFile, sourceDir) { + const resolved = []; + const seenFiles = new Set(); + + const addFile = (filePath) => { + if (!filePath || seenFiles.has(filePath)) { + return; + } + seenFiles.add(filePath); + if (!fs.existsSync(filePath)) { + return; + } + + try { + const parsed = parseYaml(filePath); + if (parsed && parsed.request && typeof parsed.request === 'object') { + resolved.push(parsed.request); + } + } catch (error) { + // Ignore files that cannot be parsed as YAML for request inheritance. + } + }; + + addFile(yamlFile); + + const dirChain = []; + let currentDir = path.dirname(yamlFile); + while (true) { + dirChain.unshift(currentDir); + if (currentDir === sourceDir) { + break; + } + const parentDir = path.dirname(currentDir); + if (parentDir === currentDir) { + break; + } + currentDir = parentDir; + } + + for (const dir of dirChain) { + addFile(path.join(dir, 'opencollection.yml')); + addFile(path.join(dir, 'folder.yml')); + } + + return resolved.reduce((result, config) => mergeRequestConfig(result, config), {}); +} + +function buildRequestContent(request, requestName, requestConfig = {}) { + const lines = []; + const variableDefinitions = []; + const seenVariables = new Set(); + + const addVariable = (name, value) => { + if (!name) { + return; + } + const normalized = String(name).trim(); + if (!normalized || seenVariables.has(normalized)) { + return; + } + seenVariables.add(normalized); + variableDefinitions.push({ name: normalized, value }); + }; + + const configVariables = Array.isArray(requestConfig.variables) ? requestConfig.variables : []; + for (const variable of configVariables) { + if (variable && variable.name) { + addVariable(variable.name, variable.value); + } + } + + let url = request.url || ''; + if (url) { + for (const placeholder of collectPlaceholders(url)) { + addVariable(placeholder, 'YOUR_VALUE_HERE'); + } + url = url.replace(/:([A-Za-z0-9_]+)/g, (_, name) => `{{${name}}}`); + } + + const queryParams = []; + const headers = []; + + for (const header of Array.isArray(requestConfig.headers) ? requestConfig.headers : []) { + 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 ?? '' }); + } + + for (const param of request.params || []) { + const name = param.name || ''; + const value = param.value || ''; + const type = (param.type || 'query').toLowerCase(); + const disabled = String(param.disabled).toLowerCase() === 'true'; + + if (disabled) { + continue; + } + + for (const placeholder of collectPlaceholders(String(value))) { + addVariable(placeholder, 'YOUR_VALUE_HERE'); + } + + if (type === 'header') { + headers.push({ name, value }); + } else { + queryParams.push({ name, value }); + } + } + + if (requestConfig.auth) + { + if (requestConfig.auth.type === 'bearer') { + for (const placeholder of collectPlaceholders(String(requestConfig.auth.token ?? ''))) { + addVariable(placeholder, 'YOUR_VALUE_HERE'); + } + headers.push({ + name: 'Authorization', + value: `Bearer ${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'); + } + // VSCode REST Client can manage username:password format directly! + headers.push({ + name: 'Authorization', + value: `Basic ${username}:${password}`, + }); + } else { + headers.push({ + name: `UNKNOWN_${requestConfig.auth.type}`, + value: `Basic ${requestConfig.auth.token}`, + }); + } + } + + if (variableDefinitions.length > 0) { + lines.push(`# Variables for ${requestName}`); + for (const variable of variableDefinitions) { + lines.push(`@${sanitizeVarName(variable.name)} = ${formatVariableValue(variable.value)}`); + } + lines.push(''); + } + + const method = (request.method || 'GET').toUpperCase(); + let requestUrl = url; + for (const param of queryParams) { + if (!param.name) { + continue; + } + const separator = requestUrl.includes('?') ? '&' : '?'; + requestUrl = `${requestUrl}${separator}${param.name}=${param.value}`; + } + + lines.push(`${method} ${requestUrl}`); + for (const header of headers) { + lines.push(`${header.name}: ${header.value}`); + } + return lines.join('\n'); } function ensureDir(dirPath) { - fs.mkdirSync(dirPath, { recursive: true }); + fs.mkdirSync(dirPath, { recursive: true }); } function walkYamlFiles(rootDir) { - const results = []; - const entries = fs.readdirSync(rootDir, { withFileTypes: true }); - for (const entry of entries) { - if (entry.name.startsWith('.') || entry.name === 'node_modules') { - continue; + const results = []; + const entries = fs.readdirSync(rootDir, { withFileTypes: true }); + for (const entry of entries) { + if (entry.name.startsWith('.') || entry.name === 'node_modules') { + continue; + } + const fullPath = path.join(rootDir, entry.name); + if (entry.isDirectory()) { + results.push(...walkYamlFiles(fullPath)); + } else if (entry.isFile() && /\.ya?ml$/i.test(entry.name)) { + results.push(fullPath); + } } - const fullPath = path.join(rootDir, entry.name); - if (entry.isDirectory()) { - results.push(...walkYamlFiles(fullPath)); - } else if (entry.isFile() && /\.ya?ml$/i.test(entry.name)) { - results.push(fullPath); + return results; +} + +function writeEnvironmentTemplates(sourceDir, outputRoot) { + const targets = []; + + const visit = (currentDir) => { + const entries = fs.readdirSync(currentDir, { withFileTypes: true }); + const hasEnvironmentsDir = entries.some((entry) => entry.isDirectory() && entry.name === 'environments'); + + if (hasEnvironmentsDir) { + targets.push(currentDir); + } + + for (const entry of entries) { + if (!entry.isDirectory() || entry.name.startsWith('.') || entry.name === 'node_modules') { + continue; + } + visit(path.join(currentDir, entry.name)); + } + }; + + visit(sourceDir); + + for (const dir of targets) { + const relativeDir = path.relative(sourceDir, dir); + const targetDir = relativeDir && relativeDir !== '.' ? path.join(outputRoot, relativeDir) : outputRoot; + ensureDir(targetDir); + + const environmentsDir = path.join(dir, 'environments'); + if (!fs.existsSync(environmentsDir)) { + continue; + } + + const envFiles = fs.readdirSync(environmentsDir, { withFileTypes: true }) + .filter((entry) => entry.isFile() && /\.ya?ml$/i.test(entry.name)) + .map((entry) => path.join(environmentsDir, entry.name)); + + const variableNames = []; + const seenNames = new Set(); + + for (const envFile of envFiles) { + const parsed = parseYaml(envFile); + const variables = Array.isArray(parsed.variables) ? parsed.variables : []; + for (const variable of variables) { + if (!variable || !variable.name) { + continue; + } + const name = String(variable.name).trim(); + if (!name || seenNames.has(name)) { + continue; + } + seenNames.add(name); + variableNames.push(name); + } + } + + const templateContent = variableNames.length > 0 ? `${variableNames.join('\n')}\n` : ''; + fs.writeFileSync(path.join(targetDir, '.env.template'), templateContent, 'utf8'); } - } - return results; } function main() { - const workspaceRoot = findWorkspaceRoot(__dirname); - const workspaceFile = path.join(workspaceRoot, 'workspace.yml'); - const workspace = parseWorkspace(workspaceFile); - const collections = Array.isArray(workspace.collections) ? workspace.collections : []; + const workspaceRoot = findWorkspaceRoot(__dirname); + const workspaceFile = path.join(workspaceRoot, 'workspace.yml'); + const workspace = parseWorkspace(workspaceFile); + const collections = Array.isArray(workspace.collections) ? workspace.collections : []; - if (collections.length === 0) { - throw new Error('No collections found in workspace.yml'); - } - - for (const collection of collections) { - if (!collection || !collection.name || !collection.path) { - continue; + if (collections.length === 0) { + throw new Error('No collections found in workspace.yml'); } - const sourceDir = path.join(workspaceRoot, collection.path); - if (!fs.existsSync(sourceDir)) { - console.warn(`Skipping missing collection path: ${collection.path}`); - continue; + for (const collection of collections) { + if (!collection || !collection.name || !collection.path) { + continue; + } + + const sourceDir = path.join(workspaceRoot, collection.path); + if (!fs.existsSync(sourceDir)) { + console.warn(`Skipping missing collection path: ${collection.path}`); + continue; + } + + const outputRoot = path.join(workspaceRoot, 'autodocs', 'http', collection.name); + ensureDir(outputRoot); + writeEnvironmentTemplates(sourceDir, outputRoot); + + const yamlFiles = walkYamlFiles(sourceDir); + let processed = 0; + + for (const yamlFile of yamlFiles) { + const content = readText(yamlFile); + const requestName = parseRequestInfo(content) || path.basename(yamlFile, path.extname(yamlFile)); + const httpBlock = parseHttpBlock(content); + if (!httpBlock || !httpBlock.url) { + continue; + } + + const relativePath = path.relative(sourceDir, yamlFile); + const parsedPath = path.parse(relativePath); + const targetDir = path.join(outputRoot, parsedPath.dir); + ensureDir(targetDir); + + const requestConfig = getRequestConfigForFile(yamlFile, sourceDir); + const outputFile = path.join(targetDir, `${parsedPath.name}.http`); + const requestContent = buildRequestContent(httpBlock, requestName, requestConfig); + fs.writeFileSync(outputFile, `${requestContent}\n`, 'utf8'); + processed += 1; + } + + console.log(`Generated ${processed} .http file(s) for ${collection.name}`); } - - const outputRoot = path.join(workspaceRoot, 'autodocs', 'http', collection.name); - ensureDir(outputRoot); - - const yamlFiles = walkYamlFiles(sourceDir); - let processed = 0; - - for (const yamlFile of yamlFiles) { - const content = readText(yamlFile); - const requestName = parseRequestInfo(content) || path.basename(yamlFile, path.extname(yamlFile)); - const httpBlock = parseHttpBlock(content); - if (!httpBlock || !httpBlock.url) { - continue; - } - - const relativePath = path.relative(sourceDir, yamlFile); - const parsedPath = path.parse(relativePath); - const targetDir = path.join(outputRoot, parsedPath.dir); - ensureDir(targetDir); - - const outputFile = path.join(targetDir, `${parsedPath.name}.http`); - const requestContent = buildRequestContent(httpBlock, requestName); - fs.writeFileSync(outputFile, `${requestContent}\n`, 'utf8'); - processed += 1; - } - - console.log(`Generated ${processed} .http file(s) for ${collection.name}`); - } } try { - main(); + main(); } catch (error) { - console.error(error.message); - process.exit(1); + console.error(error.message); + process.exit(1); } diff --git a/scripts/package-lock.json b/scripts/package-lock.json new file mode 100644 index 0000000..6f47507 --- /dev/null +++ b/scripts/package-lock.json @@ -0,0 +1,27 @@ +{ + "name": "scripts", + "lockfileVersion": 3, + "requires": true, + "packages": { + "": { + "dependencies": { + "yaml": "^2.9.0" + } + }, + "node_modules/yaml": { + "version": "2.9.0", + "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.9.0.tgz", + "integrity": "sha512-2AvhNX3mb8zd6Zy7INTtSpl1F15HW6Wnqj0srWlkKLcpYl/gMIMJiyuGq2KeI2YFxUPjdlB+3Lc10seMLtL4cA==", + "license": "ISC", + "bin": { + "yaml": "bin.mjs" + }, + "engines": { + "node": ">= 14.6" + }, + "funding": { + "url": "https://github.com/sponsors/eemeli" + } + } + } +} diff --git a/scripts/package.json b/scripts/package.json new file mode 100644 index 0000000..dab2d48 --- /dev/null +++ b/scripts/package.json @@ -0,0 +1,5 @@ +{ + "dependencies": { + "yaml": "^2.9.0" + } +} From 0b1a7becb84ac541e9759a30dc1b599170f6c20b Mon Sep 17 00:00:00 2001 From: Pier-Paolo Mammi Date: Fri, 26 Jun 2026 15:07:34 +0200 Subject: [PATCH 03/40] emit also variable value in the env template --- scripts/generate-http-docs.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/generate-http-docs.js b/scripts/generate-http-docs.js index 36498a1..01b3d0b 100644 --- a/scripts/generate-http-docs.js +++ b/scripts/generate-http-docs.js @@ -492,7 +492,7 @@ function writeEnvironmentTemplates(sourceDir, outputRoot) { } } - const templateContent = variableNames.length > 0 ? `${variableNames.join('\n')}\n` : ''; + const templateContent = variableNames.length > 0 ? `${variableNames.map(v => `${v}={{${v}}}`).join('\n')}\n` : ''; fs.writeFileSync(path.join(targetDir, '.env.template'), templateContent, 'utf8'); } } From 25c271f291f62781755a6363c6e8f816514274ea Mon Sep 17 00:00:00 2001 From: Pier-Paolo Mammi Date: Fri, 26 Jun 2026 15:07:59 +0200 Subject: [PATCH 04/40] fix duplicate query string parameters --- scripts/generate-http-docs.js | 2 ++ 1 file changed, 2 insertions(+) diff --git a/scripts/generate-http-docs.js b/scripts/generate-http-docs.js index 01b3d0b..715f751 100644 --- a/scripts/generate-http-docs.js +++ b/scripts/generate-http-docs.js @@ -324,6 +324,8 @@ function buildRequestContent(request, requestName, requestConfig = {}) { addVariable(placeholder, 'YOUR_VALUE_HERE'); } url = url.replace(/:([A-Za-z0-9_]+)/g, (_, name) => `{{${name}}}`); + // Since Bruno puts enabled params in the URL, this avoids duplicate query params + url = url.split('?')[0]; } const queryParams = []; From c03706d251879acf0cebf49e85912e1835c30c18 Mon Sep 17 00:00:00 2001 From: Pier-Paolo Mammi Date: Fri, 26 Jun 2026 15:46:59 +0200 Subject: [PATCH 05/40] variables from collection environments are rendered as dotenv variables --- scripts/generate-http-docs.js | 88 ++++++++++++++++++++++++----------- 1 file changed, 61 insertions(+), 27 deletions(-) diff --git a/scripts/generate-http-docs.js b/scripts/generate-http-docs.js index 715f751..70271ec 100644 --- a/scripts/generate-http-docs.js +++ b/scripts/generate-http-docs.js @@ -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; } From ba01e76c750896a352cb661b718c3a978a426a79 Mon Sep 17 00:00:00 2001 From: Pier-Paolo Mammi Date: Fri, 26 Jun 2026 16:31:52 +0200 Subject: [PATCH 06/40] add disabled variables as commented and enabled as parametrized --- scripts/generate-http-docs.js | 56 +++++++++++++++++++++++++++++++++-- 1 file changed, 54 insertions(+), 2 deletions(-) diff --git a/scripts/generate-http-docs.js b/scripts/generate-http-docs.js index 70271ec..5fbf1f7 100644 --- a/scripts/generate-http-docs.js +++ b/scripts/generate-http-docs.js @@ -297,6 +297,8 @@ function getRequestConfigForFile(yamlFile, sourceDir) { function buildRequestContent(request, requestName, requestConfig = {}, dotenvVariables = new Set()) { const lines = []; const variableDefinitions = []; + const commentedVariableDefinitions = []; + const parameterVariableDefinitions = []; const seenVariables = new Set(); const addVariable = (name, value) => { @@ -311,12 +313,44 @@ function buildRequestContent(request, requestName, requestConfig = {}, dotenvVar variableDefinitions.push({ name: normalized, value }); }; + const addParameterVariable = (name, value) => { + if (!name) { + return; + } + const normalized = String(name).trim(); + if (!normalized || seenVariables.has(normalized) || dotenvVariables.has(normalized)) { + return; + } + seenVariables.add(normalized); + parameterVariableDefinitions.push({ name: normalized, value }); + }; + + const addCommentedVariable = (name, value) => { + if (!name) { + return; + } + const normalized = String(name).trim(); + if (!normalized) { // || seenVariables.has(normalized) || dotenvVariables.has(normalized)) { + return; + } + // seenVariables.add(normalized); + commentedVariableDefinitions.push({ name: normalized, value }); + }; + const addReferencedVariables = (value, fallbackValue = 'YOUR_VALUE_HERE') => { for (const placeholder of collectPlaceholders(String(value))) { addVariable(placeholder, fallbackValue); } }; + const addParameterVariables = (name, value) => { + addParameterVariable(name, value); + }; + + const addCommentedVariables = (name, value) => { + addCommentedVariable(name, value); + }; + const renderValue = (value) => { if (typeof value !== 'string') { return value; @@ -364,6 +398,7 @@ function buildRequestContent(request, requestName, requestConfig = {}, dotenvVar const disabled = String(param.disabled).toLowerCase() === 'true'; if (disabled) { + addCommentedVariables(name, value); continue; } @@ -372,7 +407,8 @@ function buildRequestContent(request, requestName, requestConfig = {}, dotenvVar if (type === 'header') { headers.push({ name, value: renderValue(value) }); } else { - queryParams.push({ name, value: renderValue(value) }); + queryParams.push({ name, value: `{{${name}}}` }); + addParameterVariables(name, value); } } @@ -402,6 +438,22 @@ function buildRequestContent(request, requestName, requestConfig = {}, dotenvVar } } + if (commentedVariableDefinitions.length > 0) { + lines.push(`# Other variables for ${requestName}`); + for (const variable of commentedVariableDefinitions) { + lines.push(`# ${sanitizeVarName(variable.name)} = ${formatVariableValue(variable.value)}`); + } + lines.push(''); + } + + if (parameterVariableDefinitions.length > 0) { + lines.push(`# Parameter variables for ${requestName}`); + for (const variable of parameterVariableDefinitions) { + lines.push(`@${sanitizeVarName(variable.name)} = ${formatVariableValue(variable.value)}`); + } + lines.push(''); + } + if (variableDefinitions.length > 0) { lines.push(`# Variables for ${requestName}`); for (const variable of variableDefinitions) { @@ -524,7 +576,7 @@ function writeEnvironmentTemplates(sourceDir, outputRoot) { } } - const templateContent = variableNames.length > 0 ? `${variableNames.map(v => `${v}={{${v}}}`).join('\n')}\n` : ''; + const templateContent = variableNames.length > 0 ? `${variableNames.map(v => `${v}=EDIT_VALUE_HERE`).join('\n')}\n` : ''; fs.writeFileSync(path.join(targetDir, '.env.template'), templateContent, 'utf8'); dotenvVariablesByTarget.set(targetDir, new Set(variableNames)); } From 2727ec67e32d40dc03e0ec9b3e408c46eac0b2c8 Mon Sep 17 00:00:00 2001 From: Pier-Paolo Mammi Date: Mon, 29 Jun 2026 10:18:40 +0200 Subject: [PATCH 07/40] ai refactor - add missing headers and body with relative content-type - fix double quotes for empty variables (not needed by VSCode REST client) - strip comments from JSON data --- scripts/generate-http-docs.js | 154 ++++++++++++++++++++-------------- scripts/package-lock.json | 15 +++- scripts/package.json | 4 +- 3 files changed, 108 insertions(+), 65 deletions(-) diff --git a/scripts/generate-http-docs.js b/scripts/generate-http-docs.js index 5fbf1f7..ff6f841 100644 --- a/scripts/generate-http-docs.js +++ b/scripts/generate-http-docs.js @@ -1,9 +1,14 @@ #!/usr/bin/env node -const fs = require('fs'); -const path = require('path'); -const YAML = require('yaml'); +import fs from 'fs'; +import path from 'path'; +import YAML from 'yaml'; +import stripJsonComments from 'strip-json-comments'; +import { fileURLToPath } from 'url'; const interpolationVariableRegex = /^{{(.*?)}}$/ +const DEFAULT_ENV_VAR_VALUE = 'EDIT_VALUE_HERE' +const __filename = fileURLToPath(import.meta.url); +const __dirname = path.dirname(__filename); function findWorkspaceRoot(startDir) { let current = startDir; @@ -142,70 +147,37 @@ function parseRequestInfo(text) { } function parseHttpBlock(text) { - const lines = text.split(/\r?\n/); - const blockLines = findBlock(lines, 'http'); - const blockText = blockLines.join('\n'); - const methodMatch = blockText.match(/^\s*method:\s*(.+)$/m); - const urlMatch = blockText.match(/^\s*url:\s*(.+)$/m); + const parsed = YAML.parse(text) || {}; + const http = parsed.http || {}; + const headers = []; - const params = []; - const paramLines = blockLines.join('\n').split(/\r?\n/); - let inParamsBlock = false; - let paramsIndent = 0; - let currentParam = null; - - for (const line of paramLines) { - const trimmed = line.trim(); - if (!inParamsBlock) { - if (trimmed === 'params:') { - inParamsBlock = true; - paramsIndent = line.match(/^\s*/)[0].length; - } + for (const header of Array.isArray(http.headers) ? http.headers : []) { + if (!header || typeof header !== 'object') { continue; } - - if (!trimmed) { - continue; - } - - const indent = line.match(/^\s*/)[0].length; - if (indent <= paramsIndent) { - break; - } - - const listItemMatch = line.match(/^\s*-\s+name:\s*(.+)$/); - if (listItemMatch) { - currentParam = { name: stripQuotes(listItemMatch[1]) }; - params.push(currentParam); - continue; - } - - if (!currentParam) { - continue; - } - - const propertyMatch = line.match(/^\s*([A-Za-z0-9_]+):\s*(.+)$/); - if (propertyMatch) { - const [, key, value] = propertyMatch; - currentParam[key] = stripQuotes(value); - } + headers.push({ + name: String(header.name || '').trim(), + value: String(header.value ?? '').trim(), + }); } return { - method: methodMatch ? stripQuotes(methodMatch[1]) : 'GET', - url: urlMatch ? stripQuotes(urlMatch[1]) : '', - params, + method: http.method || 'GET', + url: http.url || '', + params: Array.isArray(http.params) ? http.params : [], + headers, + body: http.body && typeof http.body === 'object' ? http.body : null, }; } function formatVariableValue(value) { if (value === null || value === undefined) { - return '""'; + return ''; } if (typeof value === 'string') { if (value.trim() === '') { - return '""'; + return ''; } if (/\s/.test(value)) { return `"${value.replace(/"/g, '\\"')}"`; @@ -343,6 +315,21 @@ function buildRequestContent(request, requestName, requestConfig = {}, dotenvVar } }; + const renderJsonValue = (value) => { + if (typeof value === 'string') { + return renderValue(value); + } + if (Array.isArray(value)) { + return value.map((item) => renderJsonValue(item)); + } + if (value && typeof value === 'object') { + return Object.fromEntries( + Object.entries(value).map(([key, nestedValue]) => [key, renderJsonValue(nestedValue)]), + ); + } + return value; + }; + const addParameterVariables = (name, value) => { addParameterVariable(name, value); }; @@ -382,13 +369,26 @@ function buildRequestContent(request, requestName, requestConfig = {}, dotenvVar const queryParams = []; const headers = []; + const addHeader = (name, value) => { + if (!name) { + return; + } + addReferencedVariables(value ?? ''); + headers.push({ name: String(name).trim(), value: renderValue(value ?? '') }); + }; + + for (const header of Array.isArray(request.headers) ? request.headers : []) { + if (!header || !header.name) { + continue; + } + addHeader(header.name, header.value ?? ''); + } for (const header of Array.isArray(requestConfig.headers) ? requestConfig.headers : []) { if (!header || !header.name) { continue; } - addReferencedVariables(header.value ?? ''); - headers.push({ name: header.name, value: renderValue(header.value ?? '') }); + addHeader(header.name, header.value ?? ''); } for (const param of request.params || []) { @@ -416,20 +416,14 @@ function buildRequestContent(request, requestName, requestConfig = {}, dotenvVar { if (requestConfig.auth.type === 'bearer') { addReferencedVariables(requestConfig.auth.token ?? ''); - headers.push({ - name: 'Authorization', - value: `Bearer ${renderValue(requestConfig.auth.token ?? '')}`, - }); + addHeader('Authorization', `Bearer ${renderValue(requestConfig.auth.token ?? '')}`); } else if (requestConfig.auth.type === 'basic') { const username = requestConfig.auth.username ?? ''; const password = requestConfig.auth.password ?? ''; addReferencedVariables(username); addReferencedVariables(password); // VSCode REST Client can manage username:password format directly! - headers.push({ - name: 'Authorization', - value: `Basic ${renderValue(username)}:${renderValue(password)}`, - }); + addHeader('Authorization', `Basic ${renderValue(username)}:${renderValue(password)}`); } else { headers.push({ name: `UNKNOWN_${requestConfig.auth.type}`, @@ -454,6 +448,36 @@ function buildRequestContent(request, requestName, requestConfig = {}, dotenvVar lines.push(''); } + let requestBody = ''; + if (request.body && typeof request.body === 'object') { + const bodyType = String(request.body.type || '').toLowerCase(); + if (bodyType === 'json') { + const jsonData = stripJsonComments(request.body.data); + if (jsonData !== undefined && jsonData !== null) { + if (typeof jsonData === 'string') { + requestBody = renderValue(jsonData); + } else { + const renderedData = Array.isArray(jsonData) + ? jsonData.map((item) => renderJsonValue(item)) + : renderJsonValue(jsonData); + requestBody = JSON.stringify(renderedData, null, 2); + } + } + addHeader('Content-Type', 'application/json'); + } else if (bodyType === 'form-urlencoded') { + const parts = []; + for (const entry of Array.isArray(request.body.data) ? request.body.data : []) { + if (!entry || !entry.name) { + continue; + } + addReferencedVariables(entry.value ?? ''); + parts.push(`${entry.name}=${renderValue(entry.value ?? '')}`); + } + requestBody = parts.join('&'); + addHeader('Content-Type', 'application/x-www-form-urlencoded'); + } + } + if (variableDefinitions.length > 0) { lines.push(`# Variables for ${requestName}`); for (const variable of variableDefinitions) { @@ -476,6 +500,10 @@ function buildRequestContent(request, requestName, requestConfig = {}, dotenvVar for (const header of headers) { lines.push(`${header.name}: ${header.value}`); } + if (requestBody) { + lines.push(''); + lines.push(requestBody); + } return lines.join('\n'); } @@ -576,7 +604,7 @@ function writeEnvironmentTemplates(sourceDir, outputRoot) { } } - const templateContent = variableNames.length > 0 ? `${variableNames.map(v => `${v}=EDIT_VALUE_HERE`).join('\n')}\n` : ''; + const templateContent = variableNames.length > 0 ? `${variableNames.map(v => `${v}=${DEFAULT_ENV_VAR_VALUE}`).join('\n')}\n` : ''; fs.writeFileSync(path.join(targetDir, '.env.template'), templateContent, 'utf8'); dotenvVariablesByTarget.set(targetDir, new Set(variableNames)); } diff --git a/scripts/package-lock.json b/scripts/package-lock.json index 6f47507..fec65a9 100644 --- a/scripts/package-lock.json +++ b/scripts/package-lock.json @@ -1,13 +1,26 @@ { - "name": "scripts", + "name": "generate-http-docs", "lockfileVersion": 3, "requires": true, "packages": { "": { "dependencies": { + "strip-json-comments": "^5.0.3", "yaml": "^2.9.0" } }, + "node_modules/strip-json-comments": { + "version": "5.0.3", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-5.0.3.tgz", + "integrity": "sha512-1tB5mhVo7U+ETBKNf92xT4hrQa3pm0MZ0PQvuDnWgAAGHDsfp4lPSpiS6psrSiet87wyGPh9ft6wmhOMQ0hDiw==", + "license": "MIT", + "engines": { + "node": ">=14.16" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/yaml": { "version": "2.9.0", "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.9.0.tgz", diff --git a/scripts/package.json b/scripts/package.json index dab2d48..f9114af 100644 --- a/scripts/package.json +++ b/scripts/package.json @@ -1,5 +1,7 @@ { + "type": "module", "dependencies": { + "strip-json-comments": "^5.0.3", "yaml": "^2.9.0" } -} +} \ No newline at end of file From f5313107187d884ce6750b55a699205a3e828769 Mon Sep 17 00:00:00 2001 From: Pier-Paolo Mammi Date: Mon, 29 Jun 2026 10:31:32 +0200 Subject: [PATCH 08/40] fix unwanted generation of additional _dotenv_ variables --- scripts/generate-http-docs.js | 22 +++++++++++++++++----- 1 file changed, 17 insertions(+), 5 deletions(-) diff --git a/scripts/generate-http-docs.js b/scripts/generate-http-docs.js index ff6f841..321157a 100644 --- a/scripts/generate-http-docs.js +++ b/scripts/generate-http-docs.js @@ -92,6 +92,15 @@ function sanitizeVarName(value) { .replace(/^([0-9])/, '_$1') || 'value'; } +function parsePlaceholderContent(content) { + const trimmed = String(content).trim(); + const dotenvMatch = trimmed.match(/^\$dotenv\s+(.+)$/i); + if (dotenvMatch) { + return { name: dotenvMatch[1].trim(), isDotenv: true }; + } + return { name: trimmed, isDotenv: false }; +} + function collectPlaceholders(value) { if (typeof value !== 'string') { return []; @@ -100,7 +109,7 @@ function collectPlaceholders(value) { const regex = /\{\{([^{}]+)\}\}/g; let match; while ((match = regex.exec(value)) !== null) { - placeholders.push(match[1]); + placeholders.push(parsePlaceholderContent(match[1]).name); } return placeholders; } @@ -342,10 +351,13 @@ function buildRequestContent(request, requestName, requestConfig = {}, dotenvVar 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 value.replace(/\{\{([^{}]+)\}\}/g, (match, inner) => { + const placeholder = parsePlaceholderContent(inner); + if (placeholder.isDotenv) { + return match; + } + if (placeholder.name && dotenvVariables.has(placeholder.name)) { + return `{{$dotenv ${placeholder.name}}}`; } return match; }); From b00dee4f103aaaf48b940140bb3d0a8de2d04908 Mon Sep 17 00:00:00 2001 From: Pier-Paolo Mammi Date: Mon, 29 Jun 2026 10:47:51 +0200 Subject: [PATCH 09/40] fix authorization headers generation add unit tests --- scripts/generate-http-docs.js | 101 ++++++++++++++++++---------- scripts/generate-http-docs.test.mjs | 34 ++++++++++ 2 files changed, 100 insertions(+), 35 deletions(-) create mode 100644 scripts/generate-http-docs.test.mjs diff --git a/scripts/generate-http-docs.js b/scripts/generate-http-docs.js index 321157a..617040b 100644 --- a/scripts/generate-http-docs.js +++ b/scripts/generate-http-docs.js @@ -197,38 +197,7 @@ function formatVariableValue(value) { return JSON.stringify(value); } -function mergeRequestConfig(base, updates) { - if (!updates || typeof updates !== 'object') { - return base; - } - - const merged = { ...(base || {}) }; - if (updates.auth) { - if (updates.auth === 'inherit' && merged.auth && typeof merged.auth === 'object') { - merged.auth = merged.auth; - } else if (typeof updates.auth === 'object') { - merged.auth = updates.auth; - } - } - if (Array.isArray(updates.variables)) { - const variables = [...(Array.isArray(base.variables) ? base.variables : [])]; - const byName = new Map(); - for (const variable of variables) { - if (variable && variable.name) { - byName.set(String(variable.name), variable); - } - } - for (const variable of updates.variables) { - if (variable && variable.name) { - byName.set(String(variable.name), variable); - } - } - merged.variables = [...byName.values()]; - } - return merged; -} - -function getRequestConfigForFile(yamlFile, sourceDir) { +export function getRequestConfigForFile(yamlFile, sourceDir) { const resolved = []; const seenFiles = new Set(); @@ -243,16 +212,35 @@ function getRequestConfigForFile(yamlFile, sourceDir) { try { const parsed = parseYaml(filePath); + let requestConfig = null; + if (parsed && parsed.request && typeof parsed.request === 'object') { - resolved.push(parsed.request); + requestConfig = parsed.request; + } else if (parsed && typeof parsed === 'object') { + const config = {}; + if (Object.prototype.hasOwnProperty.call(parsed, 'auth')) { + config.auth = parsed.auth; + } else if (parsed.http && typeof parsed.http === 'object' && Object.prototype.hasOwnProperty.call(parsed.http, 'auth')) { + config.auth = parsed.http.auth; + } + if (Array.isArray(parsed.variables)) { + config.variables = parsed.variables; + } + if (Object.keys(config).length > 0) { + requestConfig = config; + } + } + + if (requestConfig !== null) { + resolved.push(requestConfig); + } else if (path.resolve(filePath) === path.resolve(yamlFile)) { + resolved.push({}); } } catch (error) { // Ignore files that cannot be parsed as YAML for request inheritance. } }; - addFile(yamlFile); - const dirChain = []; let currentDir = path.dirname(yamlFile); while (true) { @@ -272,9 +260,52 @@ function getRequestConfigForFile(yamlFile, sourceDir) { addFile(path.join(dir, 'folder.yml')); } + addFile(yamlFile); + return resolved.reduce((result, config) => mergeRequestConfig(result, config), {}); } +export function mergeRequestConfig(base, updates) { + if (!updates || typeof updates !== 'object') { + return base; + } + + const merged = { ...(base || {}) }; + if (Object.prototype.hasOwnProperty.call(updates, 'auth')) { + if (updates.auth === 'inherit') { + if (merged.auth && typeof merged.auth === 'object') { + merged.auth = merged.auth; + } else { + delete merged.auth; + } + } else if (typeof updates.auth === 'object' && updates.auth !== null) { + merged.auth = updates.auth; + } else { + delete merged.auth; + } + } else { + delete merged.auth; + } + + if (Array.isArray(updates.variables)) { + const variables = [...(Array.isArray(base.variables) ? base.variables : [])]; + const byName = new Map(); + for (const variable of variables) { + if (variable && variable.name) { + byName.set(String(variable.name), variable); + } + } + for (const variable of updates.variables) { + if (variable && variable.name) { + byName.set(String(variable.name), variable); + } + } + merged.variables = [...byName.values()]; + } + + return merged; +} + function buildRequestContent(request, requestName, requestConfig = {}, dotenvVariables = new Set()) { const lines = []; const variableDefinitions = []; diff --git a/scripts/generate-http-docs.test.mjs b/scripts/generate-http-docs.test.mjs new file mode 100644 index 0000000..4b86757 --- /dev/null +++ b/scripts/generate-http-docs.test.mjs @@ -0,0 +1,34 @@ +import test from 'node:test'; +import assert from 'node:assert/strict'; +import fs from 'node:fs'; +import os from 'node:os'; +import path from 'node:path'; +import { getRequestConfigForFile, mergeRequestConfig } from './generate-http-docs.js'; + +test('does not inherit parent auth when a child config has no auth override', () => { + const parentAuth = { type: 'bearer', token: 'parent-token' }; + const merged = mergeRequestConfig({ auth: parentAuth }, {}); + + assert.equal(merged.auth, undefined); +}); + +test('uses an explicit child auth object instead of inheriting the parent auth', () => { + const parentAuth = { type: 'bearer', token: 'parent-token' }; + const childAuth = { type: 'basic', username: 'user', password: 'pass' }; + const merged = mergeRequestConfig({ auth: parentAuth }, { auth: childAuth }); + + assert.deepEqual(merged.auth, childAuth); +}); + +test('reads auth inherit from a Bruno-style http block', () => { + const tempRoot = fs.mkdtempSync(path.join(os.tmpdir(), 'bruno-auth-')); + const childDir = path.join(tempRoot, 'nested'); + fs.mkdirSync(childDir, { recursive: true }); + fs.writeFileSync(path.join(tempRoot, 'opencollection.yml'), `request:\n auth:\n type: bearer\n token: "parent-token"\n`); + fs.writeFileSync(path.join(tempRoot, 'folder.yml'), 'auth: inherit\n'); + fs.writeFileSync(path.join(childDir, 'request.yml'), 'http:\n auth: inherit\n'); + + const config = getRequestConfigForFile(path.join(childDir, 'request.yml'), tempRoot); + + assert.deepEqual(config.auth, { type: 'bearer', token: 'parent-token' }); +}); From 42b8f337afb00d63d86b526d6e6afc721a6d6af0 Mon Sep 17 00:00:00 2001 From: Pier-Paolo Mammi Date: Mon, 29 Jun 2026 11:56:29 +0200 Subject: [PATCH 10/40] fix rendering of environment-backed variables --- scripts/generate-http-docs.js | 17 +++++++++-------- scripts/generate-http-docs.test.mjs | 15 ++++++++++++++- 2 files changed, 23 insertions(+), 9 deletions(-) diff --git a/scripts/generate-http-docs.js b/scripts/generate-http-docs.js index 617040b..4fda81b 100644 --- a/scripts/generate-http-docs.js +++ b/scripts/generate-http-docs.js @@ -179,7 +179,7 @@ function parseHttpBlock(text) { }; } -function formatVariableValue(value) { +function formatVariableValue(value, renderContext = {}) { if (value === null || value === undefined) { return ''; } @@ -188,10 +188,11 @@ function formatVariableValue(value) { if (value.trim() === '') { return ''; } - if (/\s/.test(value)) { - return `"${value.replace(/"/g, '\\"')}"`; + const renderedValue = renderContext.renderValue ? renderContext.renderValue(value) : value; + if (/\s/.test(renderedValue)) { + return `"${renderedValue.replace(/"/g, '\\"')}"`; } - return value; + return renderedValue; } return JSON.stringify(value); @@ -306,7 +307,7 @@ export function mergeRequestConfig(base, updates) { return merged; } -function buildRequestContent(request, requestName, requestConfig = {}, dotenvVariables = new Set()) { +export function buildRequestContent(request, requestName, requestConfig = {}, dotenvVariables = new Set()) { const lines = []; const variableDefinitions = []; const commentedVariableDefinitions = []; @@ -478,7 +479,7 @@ function buildRequestContent(request, requestName, requestConfig = {}, dotenvVar if (commentedVariableDefinitions.length > 0) { lines.push(`# Other variables for ${requestName}`); for (const variable of commentedVariableDefinitions) { - lines.push(`# ${sanitizeVarName(variable.name)} = ${formatVariableValue(variable.value)}`); + lines.push(`# ${sanitizeVarName(variable.name)} = ${formatVariableValue(variable.value, { renderValue })}`); } lines.push(''); } @@ -486,7 +487,7 @@ function buildRequestContent(request, requestName, requestConfig = {}, dotenvVar if (parameterVariableDefinitions.length > 0) { lines.push(`# Parameter variables for ${requestName}`); for (const variable of parameterVariableDefinitions) { - lines.push(`@${sanitizeVarName(variable.name)} = ${formatVariableValue(variable.value)}`); + lines.push(`@${sanitizeVarName(variable.name)} = ${formatVariableValue(variable.value, { renderValue })}`); } lines.push(''); } @@ -524,7 +525,7 @@ function buildRequestContent(request, requestName, requestConfig = {}, dotenvVar if (variableDefinitions.length > 0) { lines.push(`# Variables for ${requestName}`); for (const variable of variableDefinitions) { - lines.push(`@${sanitizeVarName(variable.name)} = ${formatVariableValue(variable.value)}`); + lines.push(`@${sanitizeVarName(variable.name)} = ${formatVariableValue(variable.value, { renderValue })}`); } lines.push(''); } diff --git a/scripts/generate-http-docs.test.mjs b/scripts/generate-http-docs.test.mjs index 4b86757..5c4bf07 100644 --- a/scripts/generate-http-docs.test.mjs +++ b/scripts/generate-http-docs.test.mjs @@ -3,7 +3,7 @@ import assert from 'node:assert/strict'; import fs from 'node:fs'; import os from 'node:os'; import path from 'node:path'; -import { getRequestConfigForFile, mergeRequestConfig } from './generate-http-docs.js'; +import { buildRequestContent, getRequestConfigForFile, mergeRequestConfig } from './generate-http-docs.js'; test('does not inherit parent auth when a child config has no auth override', () => { const parentAuth = { type: 'bearer', token: 'parent-token' }; @@ -32,3 +32,16 @@ test('reads auth inherit from a Bruno-style http block', () => { assert.deepEqual(config.auth, { type: 'bearer', token: 'parent-token' }); }); + +test('renders dotenv placeholders in generated variable definitions', () => { + const request = { + url: 'https://example.test', + params: [ + { name: 'username', value: '{{elixFormsApiUsername}}', type: 'path' }, + ], + }; + + const output = buildRequestContent(request, 'Logout', {}, new Set(['elixFormsApiUsername'])); + + assert.match(output, /@username = "\{\{\$dotenv elixFormsApiUsername\}\}"/); +}); From 5f7feec2a87b8e14ad8b6bd1cf38fce21f57f458 Mon Sep 17 00:00:00 2001 From: Pier-Paolo Mammi Date: Mon, 29 Jun 2026 13:03:52 +0200 Subject: [PATCH 11/40] update variable values generation to empty string change autogenerated requests path to autogen/httpyac --- .gitignore | 2 +- scripts/generate-http-docs.js | 20 +++++++++----------- 2 files changed, 10 insertions(+), 12 deletions(-) diff --git a/.gitignore b/.gitignore index b2d314a..6e6e8c9 100644 --- a/.gitignore +++ b/.gitignore @@ -10,4 +10,4 @@ node_modules Thumbs.db # Automatically generated stuff -autodocs/**/* \ No newline at end of file +autogen/**/* \ No newline at end of file diff --git a/scripts/generate-http-docs.js b/scripts/generate-http-docs.js index 4fda81b..1852a6d 100644 --- a/scripts/generate-http-docs.js +++ b/scripts/generate-http-docs.js @@ -7,6 +7,7 @@ import { fileURLToPath } from 'url'; const interpolationVariableRegex = /^{{(.*?)}}$/ const DEFAULT_ENV_VAR_VALUE = 'EDIT_VALUE_HERE' +const VARIABLE_NAME_VALUE_SEPARATOR = '=' const __filename = fileURLToPath(import.meta.url); const __dirname = path.dirname(__filename); @@ -181,12 +182,12 @@ function parseHttpBlock(text) { function formatVariableValue(value, renderContext = {}) { if (value === null || value === undefined) { - return ''; + return "''"; } if (typeof value === 'string') { if (value.trim() === '') { - return ''; + return "''"; } const renderedValue = renderContext.renderValue ? renderContext.renderValue(value) : value; if (/\s/.test(renderedValue)) { @@ -456,8 +457,7 @@ export function buildRequestContent(request, requestName, requestConfig = {}, do } } - if (requestConfig.auth) - { + if (requestConfig.auth) { if (requestConfig.auth.type === 'bearer') { addReferencedVariables(requestConfig.auth.token ?? ''); addHeader('Authorization', `Bearer ${renderValue(requestConfig.auth.token ?? '')}`); @@ -479,17 +479,15 @@ export function buildRequestContent(request, requestName, requestConfig = {}, do if (commentedVariableDefinitions.length > 0) { lines.push(`# Other variables for ${requestName}`); for (const variable of commentedVariableDefinitions) { - lines.push(`# ${sanitizeVarName(variable.name)} = ${formatVariableValue(variable.value, { renderValue })}`); + lines.push(`# ${sanitizeVarName(variable.name)}${VARIABLE_NAME_VALUE_SEPARATOR}${formatVariableValue(variable.value, { renderValue })}`); } - lines.push(''); } if (parameterVariableDefinitions.length > 0) { lines.push(`# Parameter variables for ${requestName}`); for (const variable of parameterVariableDefinitions) { - lines.push(`@${sanitizeVarName(variable.name)} = ${formatVariableValue(variable.value, { renderValue })}`); + lines.push(`@${sanitizeVarName(variable.name)}${VARIABLE_NAME_VALUE_SEPARATOR}${formatVariableValue(variable.value, { renderValue })}`); } - lines.push(''); } let requestBody = ''; @@ -525,9 +523,8 @@ export function buildRequestContent(request, requestName, requestConfig = {}, do if (variableDefinitions.length > 0) { lines.push(`# Variables for ${requestName}`); for (const variable of variableDefinitions) { - lines.push(`@${sanitizeVarName(variable.name)} = ${formatVariableValue(variable.value, { renderValue })}`); + lines.push(`@${sanitizeVarName(variable.name)}${VARIABLE_NAME_VALUE_SEPARATOR}${formatVariableValue(variable.value, { renderValue })}`); } - lines.push(''); } const method = (request.method || 'GET').toUpperCase(); @@ -540,6 +537,7 @@ export function buildRequestContent(request, requestName, requestConfig = {}, do requestUrl = `${requestUrl}${separator}${param.name}=${param.value}`; } + lines.push(''); lines.push(`${method} ${requestUrl}`); for (const header of headers) { lines.push(`${header.name}: ${header.value}`); @@ -677,7 +675,7 @@ function main() { continue; } - const outputRoot = path.join(workspaceRoot, 'autodocs', 'http', collection.name); + const outputRoot = path.join(workspaceRoot, 'autogen', 'httpyac', collection.name); ensureDir(outputRoot); const dotenvVariablesByTarget = writeEnvironmentTemplates(sourceDir, outputRoot); From f8358c93616bd3ef54b946c8977f558a8089ad25 Mon Sep 17 00:00:00 2001 From: Pier-Paolo Mammi Date: Mon, 29 Jun 2026 13:52:58 +0200 Subject: [PATCH 12/40] clean destination of all files and empty subfolders --- scripts/generate-http-docs.js | 37 ++++++++++++++++++++++++++++++++++- 1 file changed, 36 insertions(+), 1 deletion(-) diff --git a/scripts/generate-http-docs.js b/scripts/generate-http-docs.js index 1852a6d..befad3f 100644 --- a/scripts/generate-http-docs.js +++ b/scripts/generate-http-docs.js @@ -654,6 +654,37 @@ function writeEnvironmentTemplates(sourceDir, outputRoot) { return dotenvVariablesByTarget; } +function cleanFolder(dir) { + if (!fs.existsSync(dir)) return; + + const entries = fs.readdirSync(dir, { withFileTypes: true }); + + for (const entry of entries) { + const fullPath = path.join(dir, entry.name); + + if (entry.isDirectory()) { + // Ricorsione + cleanFolder(fullPath); + + // Dopo la pulizia, se la cartella è vuota → cancellala + const remaining = fs.readdirSync(fullPath); + if (remaining.length === 0) { + fs.rmdirSync(fullPath); + //console.log(`🗑️ Cartella rimossa: ${fullPath}`); + } + } else if (entry.isFile()) { + // File da eliminare + if ( + entry.name.endsWith(".http") || + entry.name.endsWith(".env.template") + ) { + fs.unlinkSync(fullPath); + console.log(`🗑️ File rimosso: ${fullPath}`); + } + } + } +} + function main() { const workspaceRoot = findWorkspaceRoot(__dirname); const workspaceFile = path.join(workspaceRoot, 'workspace.yml'); @@ -664,6 +695,9 @@ function main() { throw new Error('No collections found in workspace.yml'); } + const outputBaseRoot = path.join(workspaceRoot, 'autogen', 'httpyac'); + cleanFolder(outputBaseRoot); + for (const collection of collections) { if (!collection || !collection.name || !collection.path) { continue; @@ -675,8 +709,9 @@ function main() { continue; } - const outputRoot = path.join(workspaceRoot, 'autogen', 'httpyac', collection.name); + const outputRoot = path.join(outputBaseRoot, collection.name); ensureDir(outputRoot); + const dotenvVariablesByTarget = writeEnvironmentTemplates(sourceDir, outputRoot); const yamlFiles = walkYamlFiles(sourceDir); From 3f75f567f381d566474b1fb86fe5a1547a4e5b70 Mon Sep 17 00:00:00 2001 From: Pier-Paolo Mammi Date: Mon, 29 Jun 2026 13:53:18 +0200 Subject: [PATCH 13/40] remove whitespace in stripped JSON comments --- scripts/generate-http-docs.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/generate-http-docs.js b/scripts/generate-http-docs.js index befad3f..03688e2 100644 --- a/scripts/generate-http-docs.js +++ b/scripts/generate-http-docs.js @@ -494,7 +494,7 @@ export function buildRequestContent(request, requestName, requestConfig = {}, do if (request.body && typeof request.body === 'object') { const bodyType = String(request.body.type || '').toLowerCase(); if (bodyType === 'json') { - const jsonData = stripJsonComments(request.body.data); + const jsonData = stripJsonComments(request.body.data, { whitespace: false }); if (jsonData !== undefined && jsonData !== null) { if (typeof jsonData === 'string') { requestBody = renderValue(jsonData); From 12f7c183620469af0016f74685b990d27f8b687c Mon Sep 17 00:00:00 2001 From: Pier-Paolo Mammi Date: Mon, 29 Jun 2026 13:53:50 +0200 Subject: [PATCH 14/40] fix starting @ to commented variables --- scripts/generate-http-docs.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/generate-http-docs.js b/scripts/generate-http-docs.js index 03688e2..cc5d6d0 100644 --- a/scripts/generate-http-docs.js +++ b/scripts/generate-http-docs.js @@ -479,7 +479,7 @@ export function buildRequestContent(request, requestName, requestConfig = {}, do if (commentedVariableDefinitions.length > 0) { lines.push(`# Other variables for ${requestName}`); for (const variable of commentedVariableDefinitions) { - lines.push(`# ${sanitizeVarName(variable.name)}${VARIABLE_NAME_VALUE_SEPARATOR}${formatVariableValue(variable.value, { renderValue })}`); + lines.push(`# @${sanitizeVarName(variable.name)}${VARIABLE_NAME_VALUE_SEPARATOR}${formatVariableValue(variable.value, { renderValue })}`); } } From f16afd8baa4022dbc29084d831434a53ef52aabb Mon Sep 17 00:00:00 2001 From: Pier-Paolo Mammi Date: Mon, 29 Jun 2026 16:36:13 +0200 Subject: [PATCH 15/40] add copy of JS files --- scripts/generate-http-docs.js | 73 +++++++++++++++++++++++++++++++++-- 1 file changed, 70 insertions(+), 3 deletions(-) diff --git a/scripts/generate-http-docs.js b/scripts/generate-http-docs.js index cc5d6d0..d1ece61 100644 --- a/scripts/generate-http-docs.js +++ b/scripts/generate-http-docs.js @@ -654,6 +654,72 @@ function writeEnvironmentTemplates(sourceDir, outputRoot) { return dotenvVariablesByTarget; } +function writeJsFiles(sourceDir, outputRoot) { + const targets = []; + // const dotenvVariablesByTarget = new Map(); + + const visit = (currentDir) => { + const entries = fs.readdirSync(currentDir, { withFileTypes: true }); + const hasJsFiles = entries.some((entry) => entry.isFile() && /\.js$/i.test(entry.name)); + + if (hasJsFiles) { + targets.push(currentDir); + } + + for (const entry of entries) { + if (!entry.isDirectory() || entry.name.startsWith('.') || entry.name === 'node_modules') { + continue; + } + visit(path.join(currentDir, entry.name)); + } + }; + + visit(sourceDir); + + for (const dir of targets) { + const relativeDir = path.relative(sourceDir, dir); + const targetDir = relativeDir && relativeDir !== '.' ? path.join(outputRoot, relativeDir) : outputRoot; + ensureDir(targetDir); + + const jsFileDir = dir; + if (!fs.existsSync(jsFileDir)) { + continue; + } + + const jsFiles = fs.readdirSync(jsFileDir, { withFileTypes: true }) + .filter((entry) => entry.isFile() && /\.js$/i.test(entry.name)) + .map((entry) => [ path.join(jsFileDir, entry.name), path.join(targetDir, entry.name) ]); + + // const variableNames = []; + // const seenNames = new Set(); + + // for (const jsFile of jsFiles) { + // const parsed = parseYaml(jsFile); + // const variables = Array.isArray(parsed.variables) ? parsed.variables : []; + // for (const variable of variables) { + // if (!variable || !variable.name) { + // continue; + // } + // const name = String(variable.name).trim(); + // if (!name || seenNames.has(name)) { + // continue; + // } + // seenNames.add(name); + // variableNames.push(name); + // } + // } + + // const templateContent = variableNames.length > 0 ? `${variableNames.map(v => `${v}=${DEFAULT_ENV_VAR_VALUE}`).join('\n')}\n` : ''; + // fs.writeFileSync(path.join(targetDir, '.env.template'), templateContent, 'utf8'); + // dotenvVariablesByTarget.set(targetDir, new Set(variableNames)); + for (const jsFile of jsFiles) { + fs.copyFileSync(jsFile[0], jsFile[1]); + } + } + + return targets; +} + function cleanFolder(dir) { if (!fs.existsSync(dir)) return; @@ -670,16 +736,15 @@ function cleanFolder(dir) { const remaining = fs.readdirSync(fullPath); if (remaining.length === 0) { fs.rmdirSync(fullPath); - //console.log(`🗑️ Cartella rimossa: ${fullPath}`); } } else if (entry.isFile()) { // File da eliminare if ( + entry.name.endsWith(".js") || entry.name.endsWith(".http") || entry.name.endsWith(".env.template") ) { fs.unlinkSync(fullPath); - console.log(`🗑️ File rimosso: ${fullPath}`); } } } @@ -712,6 +777,8 @@ function main() { const outputRoot = path.join(outputBaseRoot, collection.name); ensureDir(outputRoot); + const writtenJsFiles = writeJsFiles(sourceDir, outputRoot); + const dotenvVariablesByTarget = writeEnvironmentTemplates(sourceDir, outputRoot); const yamlFiles = walkYamlFiles(sourceDir); @@ -738,7 +805,7 @@ function main() { processed += 1; } - console.log(`Generated ${processed} .http file(s) for ${collection.name}`); + console.log(`${collection.name.padEnd(33)} => generated ${processed.toString().padStart(3)} .http file(s) and ${writtenJsFiles.length.toString().padStart(3)} .js file(s)`); } } From 525d4f4cf0cc788ce694a2e60c646f040dd79a99 Mon Sep 17 00:00:00 2001 From: Pier-Paolo Mammi Date: Tue, 30 Jun 2026 11:12:02 +0200 Subject: [PATCH 16/40] add equivalent powershell script --- scripts/generate-http-docs.ps1 | 327 +++++++++++++++++++++++++++++++++ 1 file changed, 327 insertions(+) create mode 100644 scripts/generate-http-docs.ps1 diff --git a/scripts/generate-http-docs.ps1 b/scripts/generate-http-docs.ps1 new file mode 100644 index 0000000..9f0821c --- /dev/null +++ b/scripts/generate-http-docs.ps1 @@ -0,0 +1,327 @@ +#requires -Modules powershell-yaml + +param( + [string]$StartDir = (Split-Path -Parent $MyInvocation.MyCommand.Path) +) + +function Find-WorkspaceRoot($startDir) { + $current = $startDir + while ($true) { + if (Test-Path -LiteralPath (Join-Path $current 'workspace.yml')) { + return $current + } + $parent = Split-Path -Parent $current + if ($parent -eq $current) { + throw "workspace.yml not found" + } + $current = $parent + } +} + +function Parse-YamlFile($path) { + try { + return ConvertFrom-Yaml (Get-Content -LiteralPath $path -Raw) + } catch { + throw "Failed to parse YAML file $path : $_" + } +} + +function Strip-Quotes($value) { + $trim = $value.Trim() + if (($trim.StartsWith('"') -and $trim.EndsWith('"')) -or + ($trim.StartsWith("'") -and $trim.EndsWith("'"))) { + return $trim.Substring(1, $trim.Length - 2) + } + return $trim +} + +function Parse-Workspace($workspacePath) { + $lines = Get-Content -LiteralPath $workspacePath + $collections = @() + $inCollections = $false + $current = $null + + foreach ($line in $lines) { + $trim = $line.Trim() + + if (-not $inCollections -and $trim -eq 'collections:') { + $inCollections = $true + continue + } + + if (-not $inCollections) { continue } + + if (-not ($line.StartsWith(' ') -or $line.StartsWith("`t"))) { + break + } + + if ($line -match '^\s*-\s+name:\s*(.+)$') { + $name = Strip-Quotes $Matches[1] + $current = [ordered]@{ name = $name } + $collections += $current + continue + } + + if ($line -match '^\s*path:\s*(.+)$' -and $current) { + $current.path = Strip-Quotes $Matches[1] + } + } + + return @{ collections = $collections } +} + +function Walk-YamlFiles($rootDir) { + Get-ChildItem -LiteralPath $rootDir -Recurse -File -Include *.yml, *.yaml | + Where-Object { $_.Name -notmatch '^\.|node_modules' } | + Select-Object -ExpandProperty FullName +} + +function Ensure-Dir($path) { + if (-not (Test-Path -LiteralPath $path)) { + New-Item -ItemType Directory -Path $path | Out-Null + } +} + +function Clean-Folder($dir) { + if (-not (Test-Path -LiteralPath $dir)) { return } + + foreach ($entry in Get-ChildItem -LiteralPath $dir) { + if ($entry.PSIsContainer) { + Clean-Folder $entry.FullName + $children = Get-ChildItem -LiteralPath $entry.FullName + if ($children.Count -eq 0) { + Remove-Item -LiteralPath $entry.FullName -Force + } + } else { + if (!$entry.PSIsContainer -and $entry.Name -match '\.js$|\.http$|\.env\.template$') { + Remove-Item -LiteralPath $entry.FullName -Force + } + } + } +} + +function Parse-HttpBlock($text) { + $parsed = ConvertFrom-Yaml $text + $http = $parsed.http + + $headers = @() + foreach ($h in ($http.headers | Where-Object { $_ })) { + $headers += [ordered]@{ + name = $h.name + value = $h.value + } + } + + return @{ + method = $http.method + url = $http.url + params = $http.params + headers = $headers + body = $http.body + } +} + +function Build-RequestContent($http, $name, $config, $dotenvVars) { + $lines = @() + $vars = @() + $paramsVars = @() + $commentVars = @() + $seen = New-Object System.Collections.Generic.HashSet[string] + + function Add-Var($n, $v) { + if (-not $n) { return } + if ($seen.Contains($n)) { return } + if ($dotenvVars.Contains($n)) { return } + $seen.Add($n) | Out-Null + $vars += @{ name = $n; value = $v } + } + + function Add-ParamVar($n, $v) { + if (-not $n) { return } + if ($seen.Contains($n)) { return } + if ($dotenvVars.Contains($n)) { return } + $seen.Add($n) | Out-Null + $paramsVars += @{ name = $n; value = $v } + } + + function Add-CommentVar($n, $v) { + if (-not $n) { return } + $commentVars += @{ name = $n; value = $v } + } + + # Variables from config + foreach ($v in ($config.variables | Where-Object { $_ })) { + Add-Var $v.name $v.value + } + + # URL + $url = $http.url + if ($url) { + $url = $url -replace ':(\w+)', '{{$1}}' + $url = $url.Split('?')[0] + } + + # Params + $queryParams = @() + $headers = @() + + foreach ($h in $http.headers) { + $headers += $h + } + + foreach ($p in $http.params) { + $name = $p.name + $value = $p.value + $type = ($p.type).ToLower() + $disabled = ($p.disabled -eq $true) + + if ($disabled) { + Add-CommentVar $name $value + continue + } + + if ($type -eq 'header') { + $headers += @{ name = $name; value = $value } + } else { + $queryParams += @{ name = $name; value = "{{$name}}" } + Add-ParamVar $name $value + } + } + + # Auth + if ($config.auth) { + switch ($config.auth.type) { + 'bearer' { + $headers += @{ name = 'Authorization'; value = "Bearer $($config.auth.token)" } + } + 'basic' { + $headers += @{ name = 'Authorization'; value = "Basic $($config.auth.username):$($config.auth.password)" } + } + } + } + + # Commented vars + if ($commentVars.Count -gt 0) { + $lines += "# Other variables for $name" + foreach ($v in $commentVars) { + $lines += "# @$($v.name)=$($v.value)" + } + } + + # Parameter vars + if ($paramsVars.Count -gt 0) { + $lines += "# Parameter variables for $name" + foreach ($v in $paramsVars) { + $lines += "@$($v.name)=$($v.value)" + } + } + + # Vars + if ($vars.Count -gt 0) { + $lines += "# Variables for $name" + foreach ($v in $vars) { + $lines += "@$($v.name)=$($v.value)" + } + } + + # Build URL + foreach ($qp in $queryParams) { + $sep = ($url.Contains('?')) ? '&' : '?' + $url = "$url$sep$($qp.name)=$($qp.value)" + } + + $lines += "" + $lines += "$($http.method.ToUpper()) $url" + + foreach ($h in $headers) { + $lines += "$($h.name): $($h.value)" + } + + if ($http.body) { + $lines += "" + $lines += ($http.body.data | ConvertTo-Json -Depth 10) + } + + return ($lines -join "`n") +} + +function Main { + $workspaceRoot = Find-WorkspaceRoot $StartDir + $workspace = Parse-Workspace (Join-Path $workspaceRoot 'workspace.yml') + $collections = $workspace.collections + + $outputBase = Join-Path $workspaceRoot 'autogen/httpyac_ps1' + Clean-Folder $outputBase + + foreach ($col in $collections) { + $sourceDir = Join-Path $workspaceRoot $col.path + if (-not (Test-Path -LiteralPath $sourceDir)) { + Write-Warning "Skipping missing collection path: $($col.path)" + continue + } + + $outputRoot = Join-Path $outputBase $col.name + Ensure-Dir $outputRoot + + # Copy JS + Get-ChildItem $sourceDir -Recurse -File -Include *.js | + ForEach-Object { + $rel = $_.FullName.Substring($sourceDir.Length).TrimStart('\') + $dest = Join-Path $outputRoot $rel + Ensure-Dir (Split-Path -Parent $dest) + Copy-Item $_.FullName $dest -Force + } + + # Env templates + $envDir = Join-Path $sourceDir 'environments' + $dotenvVars = New-Object System.Collections.Generic.HashSet[string] + + if (Test-Path -LiteralPath $envDir) { + $vars = @() + foreach ($f in Get-ChildItem $envDir -File -Include *.yml, *.yaml) { + $parsed = Parse-YamlFile $f.FullName + foreach ($v in ($parsed.variables | Where-Object { $_ })) { + if (-not $dotenvVars.Contains($v.name)) { + $dotenvVars.Add($v.name) | Out-Null + $vars += $v.name + } + } + } + + $template = ($vars | ForEach-Object { "$_=`"EDIT_VALUE_HERE`"" }) -join "`n" + Set-Content -LiteralPath (Join-Path $outputRoot '.env.template') -Value $template + } + + # YAML → .http + $yamlFiles = Walk-YamlFiles $sourceDir + $count = 0 + + foreach ($file in $yamlFiles) { + $content = Get-Content -LiteralPath $file -Raw + $http = Parse-HttpBlock $content + if (-not $http.url) { continue } + + $rel = $file.Substring($sourceDir.Length).TrimStart('\') + $parsed = Split-Path $rel -LeafBase + $dir = Split-Path $rel -Parent + + $targetDir = Join-Path $outputRoot $dir + Ensure-Dir $targetDir + + $requestName = $parsed + $config = @{ variables = @(); auth = $null } + + $dotenv = $dotenvVars + $outFile = Join-Path $targetDir "$parsed.http" + + $reqContent = Build-RequestContent $http $requestName $config $dotenv + Set-Content -LiteralPath $outFile -Value $reqContent + + $count++ + } + + Write-Host ("{0,-33} => generated {1,3} .http file(s)" -f $col.name, $count) + } +} + +Main From 4caf0d855e196e2b37243ce1ac40bf7bfa293fa8 Mon Sep 17 00:00:00 2001 From: Pier-Paolo Mammi Date: Tue, 30 Jun 2026 12:19:11 +0200 Subject: [PATCH 17/40] add warning message for unparseable JSON in body data --- scripts/generate-http-docs.ps1 | 21 +++++++++++++++------ 1 file changed, 15 insertions(+), 6 deletions(-) diff --git a/scripts/generate-http-docs.ps1 b/scripts/generate-http-docs.ps1 index 9f0821c..7100634 100644 --- a/scripts/generate-http-docs.ps1 +++ b/scripts/generate-http-docs.ps1 @@ -113,11 +113,11 @@ function Parse-HttpBlock($text) { } return @{ - method = $http.method - url = $http.url - params = $http.params + method = $http.method + url = $http.url + params = $http.params headers = $headers - body = $http.body + body = $http.body } } @@ -238,8 +238,17 @@ function Build-RequestContent($http, $name, $config, $dotenvVars) { } if ($http.body) { - $lines += "" - $lines += ($http.body.data | ConvertTo-Json -Depth 10) + if ($http.body.type -eq 'json') { + $lines += "" + try { + $lines += ($http.body.data | ConvertFrom-Json -Depth 10 | ConvertTo-Json -Depth 10) + } + catch { + <#Do this if a terminating exception happens#> + Write-Warning "Failed to parse JSON for request $name, will use original content" + $lines += $http.body.data + } + } } return ($lines -join "`n") From 5f2b014a116e8e5ca2a2c9eac5d5d9506ca365d0 Mon Sep 17 00:00:00 2001 From: Pier-Paolo Mammi Date: Tue, 30 Jun 2026 12:32:02 +0200 Subject: [PATCH 18/40] add info on JS files added --- scripts/generate-http-docs.ps1 | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/scripts/generate-http-docs.ps1 b/scripts/generate-http-docs.ps1 index 7100634..185f95f 100644 --- a/scripts/generate-http-docs.ps1 +++ b/scripts/generate-http-docs.ps1 @@ -273,12 +273,14 @@ function Main { Ensure-Dir $outputRoot # Copy JS + $jsCount = 0 Get-ChildItem $sourceDir -Recurse -File -Include *.js | ForEach-Object { $rel = $_.FullName.Substring($sourceDir.Length).TrimStart('\') $dest = Join-Path $outputRoot $rel Ensure-Dir (Split-Path -Parent $dest) Copy-Item $_.FullName $dest -Force + $jsCount++ } # Env templates @@ -329,7 +331,7 @@ function Main { $count++ } - Write-Host ("{0,-33} => generated {1,3} .http file(s)" -f $col.name, $count) + Write-Host ("{0,-33} => generated {1,3} .http file(s) and {2,3} .js file(s)" -f $col.name, $count, $jsCount) } } From bdaef511f3bacd63ef07acf704a4e905918d6785 Mon Sep 17 00:00:00 2001 From: Pier-Paolo Mammi Date: Tue, 30 Jun 2026 17:06:40 +0200 Subject: [PATCH 19/40] first part of conversion of node functions --- scripts/generate-http-docs.ps1 | 34 +++++++++++++++++++++++++++++++--- 1 file changed, 31 insertions(+), 3 deletions(-) diff --git a/scripts/generate-http-docs.ps1 b/scripts/generate-http-docs.ps1 index 185f95f..c831801 100644 --- a/scripts/generate-http-docs.ps1 +++ b/scripts/generate-http-docs.ps1 @@ -12,7 +12,7 @@ function Find-WorkspaceRoot($startDir) { } $parent = Split-Path -Parent $current if ($parent -eq $current) { - throw "workspace.yml not found" + throw "workspace.yml not found from the provided start directory" } $current = $parent } @@ -20,7 +20,8 @@ function Find-WorkspaceRoot($startDir) { function Parse-YamlFile($path) { try { - return ConvertFrom-Yaml (Get-Content -LiteralPath $path -Raw) + $parsedYaml = ConvertFrom-Yaml (Get-Content -LiteralPath $path -Raw) + return $parsedYaml ?? @{} } catch { throw "Failed to parse YAML file $path : $_" } @@ -51,7 +52,7 @@ function Parse-Workspace($workspacePath) { if (-not $inCollections) { continue } - if (-not ($line.StartsWith(' ') -or $line.StartsWith("`t"))) { + if (-not ($line.StartsWith(' ') -or $line.StartsWith("`t"))) { # && trimmed? break } @@ -70,6 +71,33 @@ function Parse-Workspace($workspacePath) { return @{ collections = $collections } } +function Sanitize-VariableName([string]$name) { + $sanitized = $name.Trim() + -replace '[{}]','' + -replace '[^A-Za-z0-9_]','_' + -replace '^([0-9])','_$1' + + return $sanitized ?? 'value' +} + +function Parse-PlaceholderContent([string]$content) { + $trimmed = $content.Trim(); + $dotenvMatch = $trimmed -imatch '^\$dotenv\s+(?.+)$' + if ($dotenvMatch) { + return @{ name = $Matches.matched.Trim(); isDotEnv = true } + } + return @{ name = $trimmed; isDotEnv = false } +} + +function Collect-Placeholders($value) { + # if (typeof value !== 'string') { + # return []; + # } + $placeholders = @() + $placeholders = Select-String "\{\{([^{}]+)\}\}" -InputObject $value -AllMatches | ForEach-Object matches | ForEach-Object (Parse-PlaceholderContent Value) + return $placeholders +} + function Walk-YamlFiles($rootDir) { Get-ChildItem -LiteralPath $rootDir -Recurse -File -Include *.yml, *.yaml | Where-Object { $_.Name -notmatch '^\.|node_modules' } | From 2dec14af4a9860fb01a278bd2afb542967b499ac Mon Sep 17 00:00:00 2001 From: Pier-Paolo Mammi Date: Wed, 1 Jul 2026 13:04:05 +0200 Subject: [PATCH 20/40] elixForms API v2 - update EFTL for table of amounts with year --- .../elixPro - Template Delibera ONLYTABLE.yml | 78 +++++-------------- 1 file changed, 20 insertions(+), 58 deletions(-) diff --git a/collections/elixForms API v2/EFTL processing/CCT - Liquidazione Compensi/Proposta/elixPro - Template Delibera ONLYTABLE.yml b/collections/elixForms API v2/EFTL processing/CCT - Liquidazione Compensi/Proposta/elixPro - Template Delibera ONLYTABLE.yml index 1817c60..6eda357 100644 --- a/collections/elixForms API v2/EFTL processing/CCT - Liquidazione Compensi/Proposta/elixPro - Template Delibera ONLYTABLE.yml +++ b/collections/elixForms API v2/EFTL processing/CCT - Liquidazione Compensi/Proposta/elixPro - Template Delibera ONLYTABLE.yml @@ -40,29 +40,10 @@ runtime: prepareEftlDocument(String.raw` [EFTL] - [!-- - Codice Fiscale Anno Importo Modalità - RSSNDR76L16I153I 2026 171,46 In orario di lavoro - RSSNDR76L16I153I 2025 514,37 In orario di lavoro - RSSNDR76L16I153I 2024 220,45 In orario di lavoro - RSSNDR76L16I153I 2025 73,48 Fuori orario di lavoro - RSSNDR76L16I153I 2024 122,47 Fuori orario di lavoro - RSSNDR76L16I153I 2023 318,42 Fuori orario di lavoro - LNGSDR63M23L074R 7500 In orario di lavoro - TLTFRC83R30G337R 9.000 Fuori orario di lavoro - LNGSDR63M23L074R 4500 Fuori orario di lavoro - CRSDNL85E53G337Q 870,74 Fuori orario di lavoro - TLTFRC83R30G337R 800 In orario di lavoro - --] - - [VAR name="insertCodiciFiscali" type="string"][TAG]SCHEMAID,862,COL0001,IUQOID, ,##[/TAG][/VAR] - [VAR name="insertImporti" type="string"][TAG]SCHEMAID,862,COL0002,IUQOID, ,##[/TAG][/VAR] - [VAR name="insertAnni" type="string"][TAG]SCHEMAID,862,COL0005,IUQOID, ,##[/TAG][/VAR] - [VAR name="insertModalita" type="string"][TAG]SCHEMAID,862,COL0003,IUQOID, ,##[/TAG][/VAR] - [VAR name="codiciFiscaliIterable" type="iterable"][SPLIT regex="##"][VALUE_OF varname="insertCodiciFiscali" /][/SPLIT][/VAR] - [VAR name="importiIterable" type="iterable"][SPLIT regex="##"][VALUE_OF varname="insertImporti" /][/SPLIT][/VAR] - [VAR name="anniIterable" type="iterable"][SPLIT regex="##"][VALUE_OF varname="insertAnni" /][/SPLIT][/VAR] - [VAR name="modalitaIterable" type="iterable"][SPLIT regex="##"][VALUE_OF varname="insertModalita" /][/SPLIT][/VAR] + [VAR name="codiciFiscaliIterable" type="iterable"][SPLIT regex="##"][TAG]SCHEMAID,862,COL0001,IUQOID, ,##[/TAG][/SPLIT][/VAR] + [VAR name="importiIterable" type="iterable"][SPLIT regex="##"][TAG]SCHEMAID,862,COL0002,IUQOID, ,##[/TAG][/SPLIT][/VAR] + [VAR name="anniIterable" type="iterable"][SPLIT regex="##"][TAG]SCHEMAID,862,COL0005,IUQOID, ,##[/TAG][/SPLIT][/VAR] + [VAR name="modalitaIterable" type="iterable"][SPLIT regex="##"][TAG]SCHEMAID,862,COL0003,IUQOID, ,##[/TAG][/SPLIT][/VAR] [VAR name="insertCount" type="number"][SIZE_OF varname="codiciFiscaliIterable" /][/VAR] [VAR name="datiRipartizioneIterable" type="iterable"][SPLIT regex="##" emptyIfBlank="true"][TAG]GETVALUEBYTAG,RIPARTIZIONE_DATI_COMPLETI,REQUEST,IUQOID,CONCAT,##[/TAG][/SPLIT][/VAR] @@ -72,65 +53,49 @@ runtime: [VAR name="item4" type="number"][% item4 = 3; %][/VAR] [VAR name="item5" type="number"][% item5 = 4; %][/VAR] - - - - - - -

C: [%= insertCodiciFiscali %]

-

I: [%= insertImporti %]

-

A: [%= insertAnni %]

-

M: [%= insertModalita %]

- + [FOR varName="ripartizione" iterable="datiRipartizioneIterable"] [VAR name="datiIterable" type="iterable"][SPLIT regex=";;" emptyIfBlank="true"][VALUE_OF varname="ripartizione" /][/SPLIT][/VAR] - [VAR name="importoDentro" type="number"][% importoDentro = 0; %][/VAR] - [VAR name="importoFuori" type="number"][% importoFuori = 0; %][/VAR] - + [VAR name="codiceFiscaleCorrente"][VALUE_OF varname="datiIterable" index="item2" /][/VAR] + - ! - [% insertIdx = 0; %] + + [% insertIdx = 0; firstCfMatch = true; %] [WHILE threshold="99"] [CONDITION][% insertIdx < insertCount %][/CONDITION] [DO] - [VAR name="codiceFiscaleCorrente"][VALUE_OF varname="datiIterable" index="item2" /][/VAR] [VAR name="codiceFiscale"][VALUE_OF varname="codiciFiscaliIterable" index="insertIdx" /][/VAR] [VAR name="anno"][VALUE_OF varname="anniIterable" index="insertIdx" /][/VAR] [VAR name="modalita"][VALUE_OF varname="modalitaIterable" index="insertIdx" /][/VAR] [VAR name="importo"][VALUE_OF varname="importiIterable" index="insertIdx" /][/VAR] [IF] - [CONDITION][% codiceFiscale == codiceFiscaleCorrente && modalita == "In orario di lavoro" %][/CONDITION] + [CONDITION][% codiceFiscale == codiceFiscaleCorrente && importo != "" && importo != 0 %][/CONDITION] [THEN] - [VAR name="importoDentro" type="number"][VALUE_OF varname="importiIterable" index="insertIdx" /][/VAR] - ![%= anno %]; [VALUE_OF varname="importo" /] + [% modalitaOut = ""; annoOut = ""; suddivisoOut = ""; %] + [IF][CONDITION][% modalita != "" %][/CONDITION][THEN][% modalitaOut = modalita + " "; %][/THEN][/IF] + [IF][CONDITION][% anno != "" %][/CONDITION][THEN][% annoOut = "nel " + anno; %][/THEN][/IF] + [IF][CONDITION][% firstCfMatch == true %][/CONDITION][THEN][% suddivisoOut = "suddiviso come "; %][/THEN][/IF] + + + + + + [IF][CONDITION][% firstCfMatch == true %][/CONDITION][THEN][% firstCfMatch = false; %][/THEN][/IF] [/THEN] [/IF] - [IF] - [CONDITION][% codiceFiscale == codiceFiscaleCorrente && modalita == "Fuori orario di lavoro" %][/CONDITION] - [THEN] - [VAR name="importoFuori" type="number"][VALUE_OF varname="importiIterable" index="insertIdx" /][/VAR] - ![%= anno %]; [VALUE_OF varname="importo" /] - [/THEN] - [/IF] - [% insertIdx = insertIdx + 1; %] [/DO] [/WHILE] @@ -138,9 +103,6 @@ runtime: [/FOR]
Nominativo Codice fiscale Qualifica Struttura Importo (€)
[VALUE_OF varname="datiIterable" index="item1" /] [VALUE_OF varname="datiIterable" index="item2" /] [VALUE_OF varname="datiIterable" index="item3" /] [VALUE_OF varname="datiIterable" index="item4" /] [FORMAT type="number" pattern="#,##0.00"][VALUE_OF varname="datiIterable" index="item5" /][/FORMAT]
[%= suddivisoOut %][%= modalitaOut %][%= annoOut %][FORMAT type="number" pattern="#,##0.00"][VALUE_OF varname="importo" /][/FORMAT]
[%= codiceFiscaleCorrente %] = [%= codiceFiscale %] and [%= modalita %] per [%= anno %] => [%= importoDentro %]; [%= importoFuori %]
- - - [/EFTL] `); - type: after-response From e282ab8576e8a9a49214e43b9c52f135fa865b6f Mon Sep 17 00:00:00 2001 From: Pier-Paolo Mammi Date: Wed, 1 Jul 2026 16:39:58 +0200 Subject: [PATCH 21/40] second part of conversion from nodejs to powershell --- scripts/generate-http-docs.js | 81 +-- scripts/generate-http-docs.ps1 | 991 ++++++++++++++++++++++++++------- 2 files changed, 817 insertions(+), 255 deletions(-) diff --git a/scripts/generate-http-docs.js b/scripts/generate-http-docs.js index d1ece61..19e8907 100644 --- a/scripts/generate-http-docs.js +++ b/scripts/generate-http-docs.js @@ -199,6 +199,47 @@ function formatVariableValue(value, renderContext = {}) { return JSON.stringify(value); } +export function mergeRequestConfig(base, updates) { + if (!updates || typeof updates !== 'object') { + return base; + } + + const merged = { ...(base || {}) }; + if (Object.prototype.hasOwnProperty.call(updates, 'auth')) { + if (updates.auth === 'inherit') { + if (merged.auth && typeof merged.auth === 'object') { + merged.auth = merged.auth; + } else { + delete merged.auth; + } + } else if (typeof updates.auth === 'object' && updates.auth !== null) { + merged.auth = updates.auth; + } else { + delete merged.auth; + } + } else { + delete merged.auth; + } + + if (Array.isArray(updates.variables)) { + const variables = [...(Array.isArray(base.variables) ? base.variables : [])]; + const byName = new Map(); + for (const variable of variables) { + if (variable && variable.name) { + byName.set(String(variable.name), variable); + } + } + for (const variable of updates.variables) { + if (variable && variable.name) { + byName.set(String(variable.name), variable); + } + } + merged.variables = [...byName.values()]; + } + + return merged; +} + export function getRequestConfigForFile(yamlFile, sourceDir) { const resolved = []; const seenFiles = new Set(); @@ -267,46 +308,6 @@ export function getRequestConfigForFile(yamlFile, sourceDir) { return resolved.reduce((result, config) => mergeRequestConfig(result, config), {}); } -export function mergeRequestConfig(base, updates) { - if (!updates || typeof updates !== 'object') { - return base; - } - - const merged = { ...(base || {}) }; - if (Object.prototype.hasOwnProperty.call(updates, 'auth')) { - if (updates.auth === 'inherit') { - if (merged.auth && typeof merged.auth === 'object') { - merged.auth = merged.auth; - } else { - delete merged.auth; - } - } else if (typeof updates.auth === 'object' && updates.auth !== null) { - merged.auth = updates.auth; - } else { - delete merged.auth; - } - } else { - delete merged.auth; - } - - if (Array.isArray(updates.variables)) { - const variables = [...(Array.isArray(base.variables) ? base.variables : [])]; - const byName = new Map(); - for (const variable of variables) { - if (variable && variable.name) { - byName.set(String(variable.name), variable); - } - } - for (const variable of updates.variables) { - if (variable && variable.name) { - byName.set(String(variable.name), variable); - } - } - merged.variables = [...byName.values()]; - } - - return merged; -} export function buildRequestContent(request, requestName, requestConfig = {}, dotenvVariables = new Set()) { const lines = []; diff --git a/scripts/generate-http-docs.ps1 b/scripts/generate-http-docs.ps1 index c831801..8ea907d 100644 --- a/scripts/generate-http-docs.ps1 +++ b/scripts/generate-http-docs.ps1 @@ -1,5 +1,3 @@ -#requires -Modules powershell-yaml - param( [string]$StartDir = (Split-Path -Parent $MyInvocation.MyCommand.Path) ) @@ -18,15 +16,19 @@ function Find-WorkspaceRoot($startDir) { } } -function Parse-YamlFile($path) { +function Parse-Yaml($text) { try { - $parsedYaml = ConvertFrom-Yaml (Get-Content -LiteralPath $path -Raw) + $parsedYaml = ConvertFrom-Yaml $text return $parsedYaml ?? @{} } catch { - throw "Failed to parse YAML file $path : $_" + throw "Failed to parse YAML content : $_" } } +function Parse-YamlFile($path) { + return Parse-Yaml (Get-Content -LiteralPath $path -Raw) +} + function Strip-Quotes($value) { $trim = $value.Trim() if (($trim.StartsWith('"') -and $trim.EndsWith('"')) -or @@ -71,37 +73,576 @@ function Parse-Workspace($workspacePath) { return @{ collections = $collections } } -function Sanitize-VariableName([string]$name) { - $sanitized = $name.Trim() - -replace '[{}]','' - -replace '[^A-Za-z0-9_]','_' - -replace '^([0-9])','_$1' +function Sanitize-VarName($name) { + $sanitized = ([string]$name).Trim() -replace '[{}]', '' -replace '[^A-Za-z0-9_]', '_' -replace '^([0-9])', '_$1' - return $sanitized ?? 'value' + if ([string]::IsNullOrWhiteSpace($sanitized)) { + return 'value' + } + return $sanitized } -function Parse-PlaceholderContent([string]$content) { - $trimmed = $content.Trim(); - $dotenvMatch = $trimmed -imatch '^\$dotenv\s+(?.+)$' - if ($dotenvMatch) { - return @{ name = $Matches.matched.Trim(); isDotEnv = true } +function Parse-PlaceholderContent($content) { + $trimmed = ([string]$content).Trim(); + $dotenvMatch = [regex]::Match($trimmed, '^\$dotenv\s+(.+)$', 'IgnoreCase') + if ($dotenvMatch.Success) { + return @{ + name = $dotenvMatch.Groups[1].value.Trim() + isDotenv = $true + } + } + return @{ + name = $trimmed + isDotenv = $false } - return @{ name = $trimmed; isDotEnv = false } } function Collect-Placeholders($value) { - # if (typeof value !== 'string') { - # return []; - # } + # Se non è stringa → restituisci array vuoto + if ($value -isnot [string]) { + return @() + } $placeholders = @() - $placeholders = Select-String "\{\{([^{}]+)\}\}" -InputObject $value -AllMatches | ForEach-Object matches | ForEach-Object (Parse-PlaceholderContent Value) + $regex = [regex]'\{\{([^{}]+)\}\}' + $foundMatches = $regex.Matches($value) + foreach ($m in $foundMatches) { + $inner = $m.Groups[1].value + $parsed = Parse-PlaceholderContent $inner + $placeholders += $parsed.name + } return $placeholders } -function Walk-YamlFiles($rootDir) { - Get-ChildItem -LiteralPath $rootDir -Recurse -File -Include *.yml, *.yaml | - Where-Object { $_.Name -notmatch '^\.|node_modules' } | - Select-Object -ExpandProperty FullName +function Find-Block ([string[]]$lines, $keyName) { + for ($i = 0; $i -lt $lines.Count; $i++) { + $trimmed = $lines[$i].Trim() + if ($trimmed -ne $keyName -and -not $trimmed.StartsWith("$($keyName):")) { + continue + } + + $lineIndent = ([regex]::Match($lines[$i], '^\s*')).value.Length + $block = @() + for ($j = $i + 1; $j -lt $lines.Count; $j++) { + $currentLine = $lines[$j] + $currentTrimmed = $currentLine.Trim() + if ([string]::IsNullOrWhiteSpace($currentTrimmed)) { + $block += $currentLine + continue + } + $currentIndent = ([regex]::Match($currentLine, '^\s*')).value.Length + # Caso 1: indentazione <= indentazione della chiave e NON inizia con spazio → fine blocco + if ($currentIndent -le $lineIndent -and -not $currentLine.StartsWith(' ')) { + break + } + # Caso 2: indentazione <= indentazione della chiave e riga commento → includi + if ($currentIndent -le $lineIndent -and $currentTrimmed.StartsWith('#')) { + $block += $currentLine + continue + } + # Caso 3: indentazione <= indentazione della chiave → fine blocco + if ($currentIndent -le $lineIndent) { + break + } + # Altrimenti la riga fa parte del blocco + $block += $currentLine + } + return $block + } + return @() +} + +function Parse-RequestInfo ($text) { + $lines = $text -split '\r?\n' + $infoLines = Find-Block -Lines $lines -KeyName 'info' + $joined = ($infoLines -join "`n") + $nameMatch = [regex]::Match($joined, '^\s*name:\s*(.+)$', 'Multiline') + if ($nameMatch.Success) { + return Strip-Quotes $nameMatch.Groups[1].value + } + return '' +} + +function Parse-HttpBlock ($text) { + # ConvertFrom-Yaml restituisce $null se il testo è vuoto o non valido + $parsed = Parse-Yaml $text + if (-not $parsed) { $parsed = @{} } + + $http = $parsed.http + if (-not $http) { $http = @{} } + + $headers = @() + $headerList = @() + if ($http.headers -is [System.Collections.IEnumerable]) { + $headerList = $http.headers + } + foreach ($header in $headerList) { + if (-not $header -or $header -isnot [psobject] -and $header -isnot [hashtable]) { + continue + } + $name = ([string]($header.name ?? '')).Trim() + $value = ([string]($header.value ?? '')).Trim() + $headers += @{ + name = $name + value = $value + } + } + + $params = @() + if ($http.params -is [System.Collections.IEnumerable]) { + $params = $http.params + } + + $body = $null + if ($http.body -and ($http.body -is [psobject] -or $http.body -is [hashtable])) { + $body = $http.body + } + + return @{ + method = $http.method ?? 'GET' + url = $http.url ?? '' + params = $params + headers = $headers + body = $body + } +} + +function Format-VariableValue ($value, [hashtable]$RenderContext = @{}) { + if ($null -eq $value) { + return "''" + } + + if ($value -is [string]) { + if ($value.Trim() -eq '') { + return "''" + } + + $renderedValue = $value + if ($RenderContext.ContainsKey('renderValue') -and $RenderContext.renderValue) { + $renderedValue = $RenderContext.renderValue.Invoke($value) + } + if ($renderedValue -match '\s') { + $escaped = $renderedValue -replace '"', '\"' + return '"' + $escaped + '"' + } + return $renderedValue + } + + return ($value | ConvertTo-Json -Depth 20 -Compress) +} + +function Merge-RequestConfig ($base, $updates) { + if (-not $updates -or ($updates -isnot [psobject] -and $updates -isnot [hashtable])) { + return $base + } + + # Clona base (shallow clone) + $merged = @{} + if ($base -is [psobject] -or $base -is [hashtable]) { + foreach ($key in $base.Keys) { + $merged[$key] = $base[$key] + } + } + + if ($updates.ContainsKey('auth')) { + $auth = $updates.auth + if ($auth -eq 'inherit') { + if ($merged.ContainsKey('auth') -and ($merged.auth -is [psobject] -or $merged.auth -is [hashtable])) { + $merged.auth = $merged.auth + } + else { + $merged.Remove('auth') + } + } + elseif ($auth -is [psobject] -or $auth -is [hashtable]) { + $merged.auth = $auth + } + else { + $merged.Remove('auth') + } + } + else { + $merged.Remove('auth') + } + + if ($updates.variables -is [System.Collections.IEnumerable]) { + $variables = @() + if ($base.variables -is [System.Collections.IEnumerable]) { + $variables = @($base.variables) + } + # Mappa per nome + $byName = @{} + foreach ($variable in $variables) { + if ($variable -and $variable.name) { + $byName[[string]$variable.name] = $variable + } + } + foreach ($variable in $updates.variables) { + if ($variable -and $variable.name) { + $byName[[string]$variable.name] = $variable + } + } + $merged.variables = $byName.Values + } + + return $merged +} + +function Get-RequestConfigForFile ($yamlFile, $sourceDir) { + $resolved = @() + $seenFiles = New-Object System.Collections.Generic.HashSet[string] + + function Add-File ($FilePath) { + if (-not $FilePath -or $seenFiles.Contains($FilePath)) { + return + } + $seenFiles.Add($FilePath) + if (-not (Test-Path $FilePath)) { + return + } + + try { + $parsed = (Get-Content -Raw $FilePath | ConvertFrom-Yaml) + if (-not $parsed) { $parsed = @{} } + $requestConfig = $null + + # Caso 1: parsed.request esiste ed è un oggetto + if ($parsed.request -and ($parsed.request -is [psobject] -or $parsed.request -is [hashtable])) { + $requestConfig = $parsed.request + } + # Caso 2: parsed è un oggetto e contiene auth/variables + elseif ($parsed -is [psobject] -or $parsed -is [hashtable]) { + $config = @{} + # auth + if ($parsed.ContainsKey('auth')) { + $config.auth = $parsed.auth + } + elseif ($parsed.http -and ($parsed.http -is [psobject] -or $parsed.http -is [hashtable]) -and $parsed.http.ContainsKey('auth')) { + $config.auth = $parsed.http.auth + } + # variables + if ($parsed.variables -is [System.Collections.IEnumerable]) { + $config.variables = $parsed.variables + } + if ($config.Count -gt 0) { + $requestConfig = $config + } + } + + if ($null -ne $requestConfig) { + $resolved += $requestConfig + } + elseif ((Resolve-Path $FilePath).Path -eq (Resolve-Path $yamlFile).Path) { + $resolved += @{} + } + } + catch { + # Ignora file YAML non validi + } + } + + # Costruisci la catena delle directory + $dirChain = @() + $currentDir = Split-Path -Parent $yamlFile + while ($true) { + $dirChain = ,$currentDir + $dirChain + if ($currentDir -eq $sourceDir) { + break + } + $parentDir = Split-Path -Parent $currentDir + if ($parentDir -eq $currentDir) { + break + } + $currentDir = $parentDir + } + + foreach ($dir in $dirChain) { + Add-File (Join-Path $dir 'opencollection.yml') + Add-File (Join-Path $dir 'folder.yml') + } + + # Aggiungi il file principale + Add-File $yamlFile + + $result = @{} + foreach ($config in $resolved) { + $result = Merge-RequestConfig $result $config + } + + return $result +} + +function Build-RequestContent ( + $request, + $requestName, + $requestConfig = @{}, + [System.Collections.Generic.HashSet[string]]$dotenvVariables = $(New-Object System.Collections.Generic.HashSet[string]) + ) { + + $lines = @() + $variableDefinitions = @() + $commentedVariableDefinitions = @() + $parameterVariableDefinitions = @() + $seenVariables = New-Object System.Collections.Generic.HashSet[string] + + function Add-Variable ($Name, $Value) { + if (-not $Name) { return } + $normalized = ([string]$Name).Trim() + if (-not $normalized) { return } + if ($seenVariables.Contains($normalized)) { return } + if ($dotenvVariables.Contains($normalized)) { return } + $seenVariables.Add($normalized) + $variableDefinitions += @{ name=$normalized; value=$Value } + } + + function Add-ParameterVariable ($Name, $Value) { + if (-not $Name) { return } + $normalized = ([string]$Name).Trim() + if (-not $normalized) { return } + if ($seenVariables.Contains($normalized)) { return } + if ($dotenvVariables.Contains($normalized)) { return } + $seenVariables.Add($normalized) + $parameterVariableDefinitions += @{ name=$normalized; value=$Value } + } + + function Add-CommentedVariable ($Name, $Value) { + if (-not $Name) { return } + $normalized = ([string]$Name).Trim() + if (-not $normalized) { return } + $commentedVariableDefinitions += @{ name=$normalized; value=$Value } + } + + function Add-ReferencedVariables ($Value, $FallbackValue = 'YOUR_VALUE_HERE') { + foreach ($placeholder in Collect-Placeholders ([string]$Value)) { + Add-Variable $placeholder $FallbackValue + } + } + + function RenderJsonValue ($Value) { + if ($Value -is [string]) { + return Render-Value $Value + } + elseif ($Value -is [System.Collections.IEnumerable]) { + return @($Value | ForEach-Object { RenderJsonValue $_ }) + } + elseif ($Value -is [psobject] -or $Value -is [hashtable]) { + $result = @{} + foreach ($key in $Value.Keys) { + $result[$key] = RenderJsonValue $Value[$key] + } + return $result + } + return $Value + } + + function Add-ParameterVariables ($Name, $Value) { Add-ParameterVariable $Name $Value } + + function Add-CommentedVariables ($Name, $Value) { Add-CommentedVariable $Name $Value } + + function Render-Value ($Value) { + if ($Value -isnot [string]) { return $Value } + + return ($Value -replace '\{\{([^{}]+)\}\}', { + param($match,$inner) + $placeholder = Parse-PlaceholderContent $inner + if ($placeholder.isDotenv) { return $match } + if ($placeholder.name -and $dotenvVariables.Contains($placeholder.name)) { + return "{{$dotenv $($placeholder.name)}}" + } + return $match + }) + } + + # ------------------------- + # Variabili da requestConfig + # ------------------------- + $configVariables = @() + if ($requestConfig.variables -is [System.Collections.IEnumerable]) { + $configVariables = $requestConfig.variables + } + foreach ($variable in $configVariables) { + if ($variable -and $variable.name) { + Add-Variable $variable.name $variable.value + } + } + + # ------------------------- + # URL + # ------------------------- + $url = $request.url ?? '' + if ($url) { + Add-ReferencedVariables $url + $url = ($url -replace ':([A-Za-z0-9_]+)', '{{$1}}') + $url = Render-Value $url + $url = $url.Split('?')[0] + } + + # ------------------------- + # Headers + # ------------------------- + $queryParams = @() + $headers = @() + + function Add-Header ($Name, $Value) { + if (-not $Name) { return } + Add-ReferencedVariables ($Value ?? '') + $headers += @{ + name = ([string]$Name).Trim() + value = Render-Value ($Value ?? '') + } + } + + foreach ($header in ($request.headers ?? @())) { + if ($header -and $header.name) { + Add-Header $header.name ($header.value ?? '') + } + } + + foreach ($header in ($requestConfig.headers ?? @())) { + if ($header -and $header.name) { + Add-Header $header.name ($header.value ?? '') + } + } + + # ------------------------- + # Params + # ------------------------- + foreach ($param in ($request.params ?? @())) { + $name = $param.name ?? '' + $value = $param.value ?? '' + $type = ([string]($param.type ?? 'query')).ToLower() + $disabled = ([string]$param.disabled).ToLower() -eq 'true' + + if ($disabled) { + Add-CommentedVariables $name $value + continue + } + + Add-ReferencedVariables $value + + if ($type -eq 'header') { + $headers += @{ name=$name; value=(Render-Value $value) } + } + else { + $queryParams += @{ name=$name; value="{{$name}}" } + Add-ParameterVariables $name $value + } + } + + # ------------------------- + # Auth + # ------------------------- + if ($requestConfig.auth) { + switch ($requestConfig.auth.type) { + 'bearer' { + Add-ReferencedVariables ($requestConfig.auth.token ?? '') + Add-Header 'Authorization' ("Bearer " + (Render-Value ($requestConfig.auth.token ?? ''))) + } + 'basic' { + $username = $requestConfig.auth.username ?? '' + $password = $requestConfig.auth.password ?? '' + Add-ReferencedVariables $username + Add-ReferencedVariables $password + Add-Header 'Authorization' ("Basic " + (Render-Value $username) + ":" + (Render-Value $password)) + } + default { + $headers += @{ + name = "UNKNOWN_$($requestConfig.auth.type)" + value = "Basic $($requestConfig.auth.token)" + } + } + } + } + + # ------------------------- + # Commented variables + # ------------------------- + if ($commentedVariableDefinitions.Count -gt 0) { + $lines += "# Other variables for $requestName" + foreach ($variable in $commentedVariableDefinitions) { + $lines += "# @$(Sanitize-VarName $variable.name)$VARIABLE_NAME_VALUE_SEPARATOR$(Format-VariableValue $variable.value @{ renderValue = { param($v) Render-Value $v } })" + } + } + + # ------------------------- + # Parameter variables + # ------------------------- + if ($parameterVariableDefinitions.Count -gt 0) { + $lines += "# Parameter variables for $requestName" + foreach ($variable in $parameterVariableDefinitions) { + $lines += "@$(Sanitize-VarName $variable.name)$VARIABLE_NAME_VALUE_SEPARATOR$(Format-VariableValue $variable.value @{ renderValue = { param($v) Render-Value $v } })" + } + } + + # ------------------------- + # Body + # ------------------------- + $requestBody = '' + + if ($request.body -and ($request.body -is [psobject] -or $request.body -is [hashtable])) { + $bodyType = ([string]($request.body.type ?? '')).ToLower() + + if ($bodyType -eq 'json') { + $jsonData = ConvertFrom-Json -Depth 20 -InputObject ($request.body.data) + + if ($jsonData -is [string]) { + $requestBody = Render-Value $jsonData + } + elseif ($jsonData -is [System.Collections.IEnumerable]) { + $requestBody = (ConvertTo-Json (RenderJsonValue $jsonData) -Depth 20) + } + elseif ($jsonData -is [psobject] -or $jsonData -is [hashtable]) { + $requestBody = (ConvertTo-Json (RenderJsonValue $jsonData) -Depth 20) + } + + Add-Header 'Content-Type' 'application/json' + } + elseif ($bodyType -eq 'form-urlencoded') { + $parts = @() + foreach ($entry in ($request.body.data ?? @())) { + if (-not $entry -or -not $entry.name) { continue } + Add-ReferencedVariables ($entry.value ?? '') + $parts += "$($entry.name)=$(Render-Value ($entry.value ?? ''))" + } + $requestBody = ($parts -join '&') + Add-Header 'Content-Type' 'application/x-www-form-urlencoded' + } + } + + # ------------------------- + # Variables + # ------------------------- + if ($variableDefinitions.Count -gt 0) { + $lines += "# Variables for $requestName" + foreach ($variable in $variableDefinitions) { + $lines += "@$(Sanitize-VarName $variable.name)$VARIABLE_NAME_VALUE_SEPARATOR$(Format-VariableValue $variable.value @{ renderValue = { param($v) Render-Value $v } })" + } + } + + # ------------------------- + # Final request line + # ------------------------- + $method = ([string]($request.method ?? 'GET')).ToUpper() + $requestUrl = $url + + foreach ($param in $queryParams) { + if (-not $param.name) { continue } + $separator = ($requestUrl.Contains('?') ? '&' : '?') + $requestUrl = "$requestUrl$separator$($param.name)=$($param.value)" + } + + $lines += '' + $lines += "$method $requestUrl" + + foreach ($header in $headers) { + $lines += "$($header.name): $($header.value)" + } + + if ($requestBody) { + $lines += '' + $lines += $requestBody + } + + return ($lines -join "`n") } function Ensure-Dir($path) { @@ -110,6 +651,12 @@ function Ensure-Dir($path) { } } +function Walk-YamlFiles($rootDir) { + Get-ChildItem -LiteralPath $rootDir -Recurse -File -Include *.yml, *.yaml | + Where-Object { $_.Name -notmatch '^\.|node_modules' } | + Select-Object -ExpandProperty FullName +} + function Clean-Folder($dir) { if (-not (Test-Path -LiteralPath $dir)) { return } @@ -128,239 +675,253 @@ function Clean-Folder($dir) { } } -function Parse-HttpBlock($text) { - $parsed = ConvertFrom-Yaml $text - $http = $parsed.http +function Get-DotenvVariablesForTargetDir ($TargetDir, $OutputRoot, $DotenvVariablesByTarget) { + $variables = New-Object System.Collections.Generic.HashSet[string] + $currentDir = $TargetDir - $headers = @() - foreach ($h in ($http.headers | Where-Object { $_ })) { - $headers += [ordered]@{ - name = $h.name - value = $h.value + while ($true) { + if ($DotenvVariablesByTarget.ContainsKey($currentDir)) { + foreach ($variable in $DotenvVariablesByTarget[$currentDir]) { + $variables.Add($variable) | Out-Null + } + } + + $parentDir = Split-Path -Parent $currentDir + if ($currentDir -eq $OutputRoot -or $parentDir -eq $currentDir) { + break + } + + $currentDir = $parentDir + } + + return $variables +} + +function Write-EnvironmentTemplates ($sourceDir, $outputRoot) { + $targets = @() + $dotenvVariablesByTarget = @{} # Hashtable: targetDir → HashSet + + function Visit ([string]$CurrentDir) { + $entries = Get-ChildItem -LiteralPath $CurrentDir -Force + $hasEnvironmentsDir = $entries | Where-Object { + $_.PSIsContainer -and $_.Name -eq 'environments' + } + + if ($hasEnvironmentsDir) { + $targets += $CurrentDir + } + + foreach ($entry in $entries) { + if (-not $entry.PSIsContainer) { continue } + if ($entry.Name.StartsWith('.')) { continue } + if ($entry.Name -eq 'node_modules') { continue } + + Visit (Join-Path $CurrentDir $entry.Name) } } - return @{ - method = $http.method - url = $http.url - params = $http.params - headers = $headers - body = $http.body - } -} + Visit $sourceDir -function Build-RequestContent($http, $name, $config, $dotenvVars) { - $lines = @() - $vars = @() - $paramsVars = @() - $commentVars = @() - $seen = New-Object System.Collections.Generic.HashSet[string] + foreach ($dir in $targets) { + $relativeDir = [System.IO.Path]::GetRelativePath($sourceDir, $dir) + if ($relativeDir -and $relativeDir -ne '.') { + $targetDir = Join-Path $outputRoot $relativeDir + } + else { + $targetDir = $outputRoot + } - function Add-Var($n, $v) { - if (-not $n) { return } - if ($seen.Contains($n)) { return } - if ($dotenvVars.Contains($n)) { return } - $seen.Add($n) | Out-Null - $vars += @{ name = $n; value = $v } - } + Ensure-Dir $targetDir - function Add-ParamVar($n, $v) { - if (-not $n) { return } - if ($seen.Contains($n)) { return } - if ($dotenvVars.Contains($n)) { return } - $seen.Add($n) | Out-Null - $paramsVars += @{ name = $n; value = $v } - } - - function Add-CommentVar($n, $v) { - if (-not $n) { return } - $commentVars += @{ name = $n; value = $v } - } - - # Variables from config - foreach ($v in ($config.variables | Where-Object { $_ })) { - Add-Var $v.name $v.value - } - - # URL - $url = $http.url - if ($url) { - $url = $url -replace ':(\w+)', '{{$1}}' - $url = $url.Split('?')[0] - } - - # Params - $queryParams = @() - $headers = @() - - foreach ($h in $http.headers) { - $headers += $h - } - - foreach ($p in $http.params) { - $name = $p.name - $value = $p.value - $type = ($p.type).ToLower() - $disabled = ($p.disabled -eq $true) - - if ($disabled) { - Add-CommentVar $name $value + $environmentsDir = Join-Path $dir 'environments' + if (-not (Test-Path $environmentsDir)) { continue } - if ($type -eq 'header') { - $headers += @{ name = $name; value = $value } - } else { - $queryParams += @{ name = $name; value = "{{$name}}" } - Add-ParamVar $name $value - } - } + $envFiles = + Get-ChildItem -LiteralPath $environmentsDir -Force | + Where-Object { -not $_.PSIsContainer -and $_.Name -match '\.ya?ml$' } | + ForEach-Object { $_.FullName } - # Auth - if ($config.auth) { - switch ($config.auth.type) { - 'bearer' { - $headers += @{ name = 'Authorization'; value = "Bearer $($config.auth.token)" } + $variableNames = @() + $seenNames = New-Object System.Collections.Generic.HashSet[string] + + foreach ($envFile in $envFiles) { + $parsed = Parse-Yaml $envFile + if (-not $parsed) { continue } + + $variables = @() + if ($parsed.variables -is [System.Collections.IEnumerable]) { + $variables = $parsed.variables } - 'basic' { - $headers += @{ name = 'Authorization'; value = "Basic $($config.auth.username):$($config.auth.password)" } + + foreach ($variable in $variables) { + if (-not $variable -or -not $variable.name) { continue } + + $name = ([string]$variable.name).Trim() + if (-not $name) { continue } + if ($seenNames.Contains($name)) { continue } + + $seenNames.Add($name) + $variableNames += $name } } - } - # Commented vars - if ($commentVars.Count -gt 0) { - $lines += "# Other variables for $name" - foreach ($v in $commentVars) { - $lines += "# @$($v.name)=$($v.value)" + if ($variableNames.Count -gt 0) { + $templateContent = ($variableNames | ForEach-Object { "$_=$DEFAULT_ENV_VAR_VALUE" }) -join "`n" + $templateContent += "`n" } - } - - # Parameter vars - if ($paramsVars.Count -gt 0) { - $lines += "# Parameter variables for $name" - foreach ($v in $paramsVars) { - $lines += "@$($v.name)=$($v.value)" + else { + $templateContent = "" } + + $templatePath = Join-Path $targetDir '.env.template' + Set-Content -Path $templatePath -Value $templateContent -Encoding UTF8 + + $dotenvVariablesByTarget[$targetDir] = $seenNames } - # Vars - if ($vars.Count -gt 0) { - $lines += "# Variables for $name" - foreach ($v in $vars) { - $lines += "@$($v.name)=$($v.value)" - } - } - - # Build URL - foreach ($qp in $queryParams) { - $sep = ($url.Contains('?')) ? '&' : '?' - $url = "$url$sep$($qp.name)=$($qp.value)" - } - - $lines += "" - $lines += "$($http.method.ToUpper()) $url" - - foreach ($h in $headers) { - $lines += "$($h.name): $($h.value)" - } - - if ($http.body) { - if ($http.body.type -eq 'json') { - $lines += "" - try { - $lines += ($http.body.data | ConvertFrom-Json -Depth 10 | ConvertTo-Json -Depth 10) - } - catch { - <#Do this if a terminating exception happens#> - Write-Warning "Failed to parse JSON for request $name, will use original content" - $lines += $http.body.data - } - } - } - - return ($lines -join "`n") + return $dotenvVariablesByTarget } -function Main { - $workspaceRoot = Find-WorkspaceRoot $StartDir - $workspace = Parse-Workspace (Join-Path $workspaceRoot 'workspace.yml') - $collections = $workspace.collections +function Write-JsFiles ($sourceDir, $outputRoot) { + $targets = @() - $outputBase = Join-Path $workspaceRoot 'autogen/httpyac_ps1' - Clean-Folder $outputBase + function Visit ($CurrentDir) { + $entries = Get-ChildItem -LiteralPath $CurrentDir -Force - foreach ($col in $collections) { - $sourceDir = Join-Path $workspaceRoot $col.path - if (-not (Test-Path -LiteralPath $sourceDir)) { - Write-Warning "Skipping missing collection path: $($col.path)" + $hasJsFiles = $entries | Where-Object { + -not $_.PSIsContainer -and $_.Name -match '\.js$' + } + + if ($hasJsFiles) { + $targets += $CurrentDir + } + + # Visita ricorsivamente le sottodirectory + foreach ($entry in $entries) { + if (-not $entry.PSIsContainer) { continue } + if ($entry.Name.StartsWith('.')) { continue } + if ($entry.Name -eq 'node_modules') { continue } + + Visit (Join-Path $CurrentDir $entry.Name) + } + } + + Visit $sourceDir + + foreach ($dir in $targets) { + $relativeDir = [System.IO.Path]::GetRelativePath($sourceDir, $dir) + if ($relativeDir -and $relativeDir -ne '.') { + $targetDir = Join-Path $outputRoot $relativeDir + } + else { + $targetDir = $outputRoot + } + + Ensure-Dir $targetDir + + if (-not (Test-Path $dir)) { continue } - $outputRoot = Join-Path $outputBase $col.name - Ensure-Dir $outputRoot - - # Copy JS - $jsCount = 0 - Get-ChildItem $sourceDir -Recurse -File -Include *.js | + $jsFiles = + Get-ChildItem -LiteralPath $dir -Force | + Where-Object { -not $_.PSIsContainer -and $_.Name -match '\.js$' } | ForEach-Object { - $rel = $_.FullName.Substring($sourceDir.Length).TrimStart('\') - $dest = Join-Path $outputRoot $rel - Ensure-Dir (Split-Path -Parent $dest) - Copy-Item $_.FullName $dest -Force - $jsCount++ - } - - # Env templates - $envDir = Join-Path $sourceDir 'environments' - $dotenvVars = New-Object System.Collections.Generic.HashSet[string] - - if (Test-Path -LiteralPath $envDir) { - $vars = @() - foreach ($f in Get-ChildItem $envDir -File -Include *.yml, *.yaml) { - $parsed = Parse-YamlFile $f.FullName - foreach ($v in ($parsed.variables | Where-Object { $_ })) { - if (-not $dotenvVars.Contains($v.name)) { - $dotenvVars.Add($v.name) | Out-Null - $vars += $v.name - } + @{ + Source = $_.FullName + Target = Join-Path $targetDir $_.Name } } - $template = ($vars | ForEach-Object { "$_=`"EDIT_VALUE_HERE`"" }) -join "`n" - Set-Content -LiteralPath (Join-Path $outputRoot '.env.template') -Value $template + foreach ($jsFile in $jsFiles) { + Copy-Item -LiteralPath $jsFile.Source -Destination $jsFile.Target -Force + } + } + + return $targets +} + +function Invoke-Main { + # Workspace root + $workspaceRoot = Find-WorkspaceRoot $PSScriptRoot + $workspaceFile = Join-Path $workspaceRoot 'workspace.yml' + $workspace = Parse-Workspace $workspaceFile + $collections = @() + if ($workspace.collections -is [System.Collections.IEnumerable]) { + $collections = $workspace.collections + } + + if ($collections.Count -eq 0) { + throw "No collections found in workspace.yml" + } + + $outputBaseRoot = Join-Path $workspaceRoot 'autogen/httpyac' + Clean-Folder $outputBaseRoot + + foreach ($collection in $collections) { + if (-not $collection -or -not $collection.name -or -not $collection.path) { + continue } - # YAML → .http + $sourceDir = Join-Path $workspaceRoot $collection.path + if (-not (Test-Path $sourceDir)) { + Write-Warning "Skipping missing collection path: $($collection.path)" + continue + } + + $outputRoot = Join-Path $outputBaseRoot $collection.name + Ensure-Dir $outputRoot + + # JS files + $writtenJsFiles = Write-JsFiles $sourceDir $outputRoot + + # dotenv templates + $dotenvVariablesByTarget = Write-EnvironmentTemplates $sourceDir $outputRoot + + # YAML files $yamlFiles = Walk-YamlFiles $sourceDir - $count = 0 + $processed = 0 - foreach ($file in $yamlFiles) { - $content = Get-Content -LiteralPath $file -Raw - $http = Parse-HttpBlock $content - if (-not $http.url) { continue } + foreach ($yamlFile in $yamlFiles) { - $rel = $file.Substring($sourceDir.Length).TrimStart('\') - $parsed = Split-Path $rel -LeafBase - $dir = Split-Path $rel -Parent + $content = Get-Content -LiteralPath $yamlFile -Raw + $requestName = Parse-RequestInfo $content + if (-not $requestName) { + $requestName = [System.IO.Path]::GetFileNameWithoutExtension($yamlFile) + } - $targetDir = Join-Path $outputRoot $dir + $httpBlock = Parse-HttpBlock $content + if (-not $httpBlock -or -not $httpBlock.url) { + continue + } + + $relativePath = [System.IO.Path]::GetRelativePath($sourceDir, $yamlFile) + $parsedPath = [System.IO.Path]::GetFileNameWithoutExtension($relativePath) + $parsedDir = Split-Path $relativePath -Parent + + $targetDir = Join-Path $outputRoot $parsedDir Ensure-Dir $targetDir - $requestName = $parsed - $config = @{ variables = @(); auth = $null } + $requestConfig = Get-RequestConfigForFile $yamlFile $sourceDir + $outputFile = Join-Path $targetDir ("$parsedPath.http") - $dotenv = $dotenvVars - $outFile = Join-Path $targetDir "$parsed.http" + $dotenvVariables = Get-DotenvVariablesForTargetDir $targetDir $outputRoot $dotenvVariablesByTarget - $reqContent = Build-RequestContent $http $requestName $config $dotenv - Set-Content -LiteralPath $outFile -Value $reqContent + $requestContent = Build-RequestContent $httpBlock $requestName $requestConfig $dotenvVariables - $count++ + Set-Content -Path $outputFile -Value ($requestContent + "`n") -Encoding UTF8 + + $processed++ } - Write-Host ("{0,-33} => generated {1,3} .http file(s) and {2,3} .js file(s)" -f $col.name, $count, $jsCount) + $namePadded = $collection.name.PadRight(33) + $httpCount = $processed.ToString().PadLeft(3) + $jsCount = $writtenJsFiles.Count.ToString().PadLeft(3) + + Write-Host "$namePadded => generated $httpCount .http file(s) and $jsCount .js file(s)" } } -Main +Invoke-Main From c5db2f3ae930cf5d870eb463d4385665e4e4a717 Mon Sep 17 00:00:00 2001 From: Pier-Paolo Mammi Date: Thu, 2 Jul 2026 10:18:02 +0200 Subject: [PATCH 22/40] add environment setup script --- scripts/setup-environment.ps1 | 41 +++++++++++++++++++++++++++++++++++ setup-environment.bat | 13 +++++++++++ 2 files changed, 54 insertions(+) create mode 100644 scripts/setup-environment.ps1 create mode 100644 setup-environment.bat diff --git a/scripts/setup-environment.ps1 b/scripts/setup-environment.ps1 new file mode 100644 index 0000000..38b0fec --- /dev/null +++ b/scripts/setup-environment.ps1 @@ -0,0 +1,41 @@ +function Initialize-PowerShellEnvironment { + Write-Host "Initializing PowerShell environment..." -ForegroundColor Yellow + + # Add any environment setup logic here, such as importing modules, setting variables, etc. + # Example: Import-Module SomeModule + Import-Module powershell-yaml -ErrorAction SilentlyContinue + + Write-Host "PowerShell environment initialized." -ForegroundColor Green +} + +function Initialize-GenerateTools { + Write-Host "Initializing Node.js dependencies..." -ForegroundColor Yellow + + Push-Location -StackName NodeTools (Join-Path $PSScriptRoot "../scripts/") + + # Install Node.js dependencies + & npm install + if ($LASTEXITCODE -ne 0) { + Write-Error "npm install failed with exit code $LASTEXITCODE." + exit 1 + } + + Pop-Location -StackName NodeTools + + Write-Host "Node.js dependencies initialized." -ForegroundColor Green +} + +function Invoke-Main { + Write-Host "Preparing environment..." -ForegroundColor Cyan + Write-Host + + Initialize-PowerShellEnvironment + Write-Host + + Initialize-GenerateTools + Write-Host + + Write-Host "Environment preparation complete!" -ForegroundColor Green +} + +Invoke-Main \ No newline at end of file diff --git a/setup-environment.bat b/setup-environment.bat new file mode 100644 index 0000000..3ca07f7 --- /dev/null +++ b/setup-environment.bat @@ -0,0 +1,13 @@ +@echo off +echo %cmdcmdline% | findstr /i /c:"%~nx0" >NUL && set iscommandline=1 +echo %PSModulePath% | findstr /i /c:"%USERPROFILE%" >NUL && set ispowershell=1 + +cd /D "%~dp0" + +echo. + +@pwsh -NoProfile -ExecutionPolicy Bypass -Command .\scripts\setup-environment.ps1 %* + +echo. + +IF DEFINED iscommandline IF NOT DEFINED ispowershell pause From 08b418c513c84ae4d224b82505a003a28566233a Mon Sep 17 00:00:00 2001 From: Pier-Paolo Mammi Date: Thu, 2 Jul 2026 10:18:37 +0200 Subject: [PATCH 23/40] add pwsh required module powershell-yaml --- scripts/generate-http-docs.ps1 | 2 ++ 1 file changed, 2 insertions(+) diff --git a/scripts/generate-http-docs.ps1 b/scripts/generate-http-docs.ps1 index 8ea907d..c463f4a 100644 --- a/scripts/generate-http-docs.ps1 +++ b/scripts/generate-http-docs.ps1 @@ -1,3 +1,5 @@ +#requires -Modules powershell-yaml + param( [string]$StartDir = (Split-Path -Parent $MyInvocation.MyCommand.Path) ) From 650d62a29c716c1cdbcc586b6e6616e7409b6a9e Mon Sep 17 00:00:00 2001 From: Pier-Paolo Mammi Date: Thu, 2 Jul 2026 10:20:54 +0200 Subject: [PATCH 24/40] rename pwsh script to generate-http-requests --- generate-http-requests.bat | 13 +++++++++++++ ...ate-http-docs.ps1 => generate-http-requests.ps1} | 0 2 files changed, 13 insertions(+) create mode 100644 generate-http-requests.bat rename scripts/{generate-http-docs.ps1 => generate-http-requests.ps1} (100%) diff --git a/generate-http-requests.bat b/generate-http-requests.bat new file mode 100644 index 0000000..405ae37 --- /dev/null +++ b/generate-http-requests.bat @@ -0,0 +1,13 @@ +@echo off +echo %cmdcmdline% | findstr /i /c:"%~nx0" >NUL && set iscommandline=1 +echo %PSModulePath% | findstr /i /c:"%USERPROFILE%" >NUL && set ispowershell=1 + +cd /D "%~dp0" + +echo. + +@pwsh -NoProfile -ExecutionPolicy Bypass -Command .\scripts\generate-http-requests.ps1 %* + +echo. + +IF DEFINED iscommandline IF NOT DEFINED ispowershell pause diff --git a/scripts/generate-http-docs.ps1 b/scripts/generate-http-requests.ps1 similarity index 100% rename from scripts/generate-http-docs.ps1 rename to scripts/generate-http-requests.ps1 From cb6d7d91a5bb0831edeec75a57a85fdc9dd56b85 Mon Sep 17 00:00:00 2001 From: Pier-Paolo Mammi Date: Thu, 2 Jul 2026 16:48:39 +0200 Subject: [PATCH 25/40] fixes on nodejs script - add missing headers generation - sort variables (for testing, may be disabled) - skip environments when no file is actually present --- scripts/generate-http-docs.js | 42 ++++++++++++++++++++++++++++------- 1 file changed, 34 insertions(+), 8 deletions(-) diff --git a/scripts/generate-http-docs.js b/scripts/generate-http-docs.js index 19e8907..d0c0086 100644 --- a/scripts/generate-http-docs.js +++ b/scripts/generate-http-docs.js @@ -6,7 +6,7 @@ import stripJsonComments from 'strip-json-comments'; import { fileURLToPath } from 'url'; const interpolationVariableRegex = /^{{(.*?)}}$/ -const DEFAULT_ENV_VAR_VALUE = 'EDIT_VALUE_HERE' +const DEFAULT_VAR_VALUE = 'EDIT_VALUE_HERE' const VARIABLE_NAME_VALUE_SEPARATOR = '=' const __filename = fileURLToPath(import.meta.url); const __dirname = path.dirname(__filename); @@ -221,6 +221,22 @@ export function mergeRequestConfig(base, updates) { delete merged.auth; } + if (Object.prototype.hasOwnProperty.call(updates, 'headers')) { + const headers = [...(Array.isArray(base.headers) ? base.headers : [])]; + const byName = new Map(); + for (const header of headers) { + if (header && header.name) { + byName.set(String(header.name), header); + } + } + for (const header of updates.headers) { + if (header && header.name) { + byName.set(String(header.name), header); + } + } + merged.headers = [...byName.values()]; + } + if (Array.isArray(updates.variables)) { const variables = [...(Array.isArray(base.variables) ? base.variables : [])]; const byName = new Map(); @@ -352,7 +368,7 @@ export function buildRequestContent(request, requestName, requestConfig = {}, do commentedVariableDefinitions.push({ name: normalized, value }); }; - const addReferencedVariables = (value, fallbackValue = 'YOUR_VALUE_HERE') => { + const addReferencedVariables = (value, fallbackValue = DEFAULT_VAR_VALUE) => { for (const placeholder of collectPlaceholders(String(value))) { addVariable(placeholder, fallbackValue); } @@ -479,14 +495,20 @@ export function buildRequestContent(request, requestName, requestConfig = {}, do if (commentedVariableDefinitions.length > 0) { lines.push(`# Other variables for ${requestName}`); - for (const variable of commentedVariableDefinitions) { + for (const variable of commentedVariableDefinitions.sort((a, b) => { + const nameComparison = a.name.localeCompare(b.name); + return nameComparison !== 0 ? nameComparison : a.value.localeCompare(b.value); + })) { lines.push(`# @${sanitizeVarName(variable.name)}${VARIABLE_NAME_VALUE_SEPARATOR}${formatVariableValue(variable.value, { renderValue })}`); } } if (parameterVariableDefinitions.length > 0) { lines.push(`# Parameter variables for ${requestName}`); - for (const variable of parameterVariableDefinitions) { + for (const variable of parameterVariableDefinitions.sort((a, b) => { + const nameComparison = a.name.localeCompare(b.name); + return nameComparison !== 0 ? nameComparison : a.value.localeCompare(b.value); + })) { lines.push(`@${sanitizeVarName(variable.name)}${VARIABLE_NAME_VALUE_SEPARATOR}${formatVariableValue(variable.value, { renderValue })}`); } } @@ -523,7 +545,10 @@ export function buildRequestContent(request, requestName, requestConfig = {}, do if (variableDefinitions.length > 0) { lines.push(`# Variables for ${requestName}`); - for (const variable of variableDefinitions) { + for (const variable of variableDefinitions.sort((a, b) => { + const nameComparison = a.name.localeCompare(b.name); + return nameComparison !== 0 ? nameComparison : a.value.localeCompare(b.value); + })) { lines.push(`@${sanitizeVarName(variable.name)}${VARIABLE_NAME_VALUE_SEPARATOR}${formatVariableValue(variable.value, { renderValue })}`); } } @@ -598,7 +623,8 @@ function writeEnvironmentTemplates(sourceDir, outputRoot) { const visit = (currentDir) => { const entries = fs.readdirSync(currentDir, { withFileTypes: true }); - const hasEnvironmentsDir = entries.some((entry) => entry.isDirectory() && entry.name === 'environments'); + const hasEnvironmentsDir = entries.some((entry) => entry.isDirectory() && entry.name === 'environments' && + fs.readdirSync(path.join(currentDir, 'environments'), { withFileTypes: true }).some((envEntry) => envEntry.isFile() && /\.ya?ml$/i.test(envEntry.name))); if (hasEnvironmentsDir) { targets.push(currentDir); @@ -647,7 +673,7 @@ function writeEnvironmentTemplates(sourceDir, outputRoot) { } } - const templateContent = variableNames.length > 0 ? `${variableNames.map(v => `${v}=${DEFAULT_ENV_VAR_VALUE}`).join('\n')}\n` : ''; + const templateContent = variableNames.length > 0 ? `${variableNames.map(v => `${v}=${DEFAULT_VAR_VALUE}`).join('\n')}\n` : ''; fs.writeFileSync(path.join(targetDir, '.env.template'), templateContent, 'utf8'); dotenvVariablesByTarget.set(targetDir, new Set(variableNames)); } @@ -761,7 +787,7 @@ function main() { throw new Error('No collections found in workspace.yml'); } - const outputBaseRoot = path.join(workspaceRoot, 'autogen', 'httpyac'); + const outputBaseRoot = path.join(workspaceRoot, 'autogen', 'httpyac_node'); cleanFolder(outputBaseRoot); for (const collection of collections) { From 63c6bce3ccf85529c15bfd40256f5ccd9a8b4030 Mon Sep 17 00:00:00 2001 From: Pier-Paolo Mammi Date: Thu, 2 Jul 2026 16:50:33 +0200 Subject: [PATCH 26/40] refactor on pwsh script - take account of pwsh quirks... - add missing headers generation - add missing rendering of variables - make 99.9% equal to nodejs script --- scripts/generate-http-requests.ps1 | 274 ++++++++++++++++++----------- 1 file changed, 173 insertions(+), 101 deletions(-) diff --git a/scripts/generate-http-requests.ps1 b/scripts/generate-http-requests.ps1 index c463f4a..b7ee3e3 100644 --- a/scripts/generate-http-requests.ps1 +++ b/scripts/generate-http-requests.ps1 @@ -1,16 +1,19 @@ #requires -Modules powershell-yaml param( - [string]$StartDir = (Split-Path -Parent $MyInvocation.MyCommand.Path) + [string]$StartDir = (Split-Path -LiteralPath $MyInvocation.MyCommand.Path) ) +$DEFAULT_ENV_VAR_VALUE = 'EDIT_VALUE_HERE' +$VARIABLE_NAME_VALUE_SEPARATOR = '=' + function Find-WorkspaceRoot($startDir) { $current = $startDir while ($true) { if (Test-Path -LiteralPath (Join-Path $current 'workspace.yml')) { return $current } - $parent = Split-Path -Parent $current + $parent = Split-Path -LiteralPath $current if ($parent -eq $current) { throw "workspace.yml not found from the provided start directory" } @@ -77,7 +80,6 @@ function Parse-Workspace($workspacePath) { function Sanitize-VarName($name) { $sanitized = ([string]$name).Trim() -replace '[{}]', '' -replace '[^A-Za-z0-9_]', '_' -replace '^([0-9])', '_$1' - if ([string]::IsNullOrWhiteSpace($sanitized)) { return 'value' } @@ -266,6 +268,26 @@ function Merge-RequestConfig ($base, $updates) { $merged.Remove('auth') } + if ($updates.headers -is [System.Collections.IEnumerable]) { + $headers = @() + if ($base.headers -is [System.Collections.IEnumerable]) { + $headers = @($base.headers) + } + # Mappa per nome + $byName = @{} + foreach ($header in $headers) { + if ($header -and $header.name) { + $byName[[string]$header.name] = $header + } + } + foreach ($header in $updates.headers) { + if ($header -and $header.name) { + $byName[[string]$header.name] = $header + } + } + $merged.headers = $byName.Values + } + if ($updates.variables -is [System.Collections.IEnumerable]) { $variables = @() if ($base.variables -is [System.Collections.IEnumerable]) { @@ -290,14 +312,16 @@ function Merge-RequestConfig ($base, $updates) { } function Get-RequestConfigForFile ($yamlFile, $sourceDir) { - $resolved = @() - $seenFiles = New-Object System.Collections.Generic.HashSet[string] + $resolved = [ref] @() + $seenFiles = [ref] (New-Object System.Collections.Generic.HashSet[string]) + + $config = [ref] @{} function Add-File ($FilePath) { - if (-not $FilePath -or $seenFiles.Contains($FilePath)) { + if (-not $FilePath -or $seenFiles.Value.Contains($FilePath)) { return } - $seenFiles.Add($FilePath) + [void]$seenFiles.Value.Add($FilePath) if (-not (Test-Path $FilePath)) { return } @@ -313,28 +337,28 @@ function Get-RequestConfigForFile ($yamlFile, $sourceDir) { } # Caso 2: parsed è un oggetto e contiene auth/variables elseif ($parsed -is [psobject] -or $parsed -is [hashtable]) { - $config = @{} + # $config = @{} # auth if ($parsed.ContainsKey('auth')) { - $config.auth = $parsed.auth + $config.Value.auth = $parsed.auth } elseif ($parsed.http -and ($parsed.http -is [psobject] -or $parsed.http -is [hashtable]) -and $parsed.http.ContainsKey('auth')) { - $config.auth = $parsed.http.auth + $config.Value.auth = $parsed.http.auth } # variables if ($parsed.variables -is [System.Collections.IEnumerable]) { - $config.variables = $parsed.variables + $config.Value.variables = $parsed.variables } - if ($config.Count -gt 0) { - $requestConfig = $config + if ($config.Value.Count -gt 0) { + $requestConfig = $config.Value } } if ($null -ne $requestConfig) { - $resolved += $requestConfig + $resolved.Value += $requestConfig } elseif ((Resolve-Path $FilePath).Path -eq (Resolve-Path $yamlFile).Path) { - $resolved += @{} + $resolved.Value += @{} } } catch { @@ -344,13 +368,14 @@ function Get-RequestConfigForFile ($yamlFile, $sourceDir) { # Costruisci la catena delle directory $dirChain = @() - $currentDir = Split-Path -Parent $yamlFile + $currentDir = Split-Path -LiteralPath $yamlFile + while ($true) { $dirChain = ,$currentDir + $dirChain if ($currentDir -eq $sourceDir) { break } - $parentDir = Split-Path -Parent $currentDir + $parentDir = Split-Path -LiteralPath $currentDir if ($parentDir -eq $currentDir) { break } @@ -366,74 +391,105 @@ function Get-RequestConfigForFile ($yamlFile, $sourceDir) { Add-File $yamlFile $result = @{} - foreach ($config in $resolved) { + foreach ($config in $resolved.Value) { $result = Merge-RequestConfig $result $config } return $result } -function Build-RequestContent ( - $request, - $requestName, - $requestConfig = @{}, - [System.Collections.Generic.HashSet[string]]$dotenvVariables = $(New-Object System.Collections.Generic.HashSet[string]) - ) { - +function Build-RequestContent ($request, $requestName, $requestConfig = @{}, [ref][System.Collections.Generic.HashSet[string]]$dotenvVariables = $(New-Object System.Collections.Generic.HashSet[string])) { $lines = @() - $variableDefinitions = @() - $commentedVariableDefinitions = @() - $parameterVariableDefinitions = @() - $seenVariables = New-Object System.Collections.Generic.HashSet[string] + $variableDefinitions = [ref] @() + $commentedVariableDefinitions = [ref] @() + $parameterVariableDefinitions = [ref] @() + $seenVariables = [ref] (New-Object System.Collections.Generic.HashSet[string]) function Add-Variable ($Name, $Value) { if (-not $Name) { return } $normalized = ([string]$Name).Trim() if (-not $normalized) { return } - if ($seenVariables.Contains($normalized)) { return } - if ($dotenvVariables.Contains($normalized)) { return } - $seenVariables.Add($normalized) - $variableDefinitions += @{ name=$normalized; value=$Value } + if ($seenVariables.Value.Contains($normalized)) { return } + if ($dotenvVariables.Value.Contains($normalized)) { return } + [void]$seenVariables.Value.Add($normalized) + $variableDefinitions.Value += @{ name=$normalized; value=$Value } } function Add-ParameterVariable ($Name, $Value) { if (-not $Name) { return } $normalized = ([string]$Name).Trim() if (-not $normalized) { return } - if ($seenVariables.Contains($normalized)) { return } - if ($dotenvVariables.Contains($normalized)) { return } - $seenVariables.Add($normalized) - $parameterVariableDefinitions += @{ name=$normalized; value=$Value } + if ($seenVariables.Value.Contains($normalized)) { return } + if ($dotenvVariables.Value.Contains($normalized)) { return } + [void]$seenVariables.Value.Add($normalized) + $parameterVariableDefinitions.Value += @{ name=$normalized; value=$Value } } function Add-CommentedVariable ($Name, $Value) { if (-not $Name) { return } $normalized = ([string]$Name).Trim() if (-not $normalized) { return } - $commentedVariableDefinitions += @{ name=$normalized; value=$Value } + $commentedVariableDefinitions.Value += @{ name=$normalized; value=$Value } } - function Add-ReferencedVariables ($Value, $FallbackValue = 'YOUR_VALUE_HERE') { + function Add-ReferencedVariables ($Value, $FallbackValue = $DEFAULT_ENV_VAR_VALUE) { foreach ($placeholder in Collect-Placeholders ([string]$Value)) { Add-Variable $placeholder $FallbackValue } } - function RenderJsonValue ($Value) { - if ($Value -is [string]) { - return Render-Value $Value - } - elseif ($Value -is [System.Collections.IEnumerable]) { - return @($Value | ForEach-Object { RenderJsonValue $_ }) - } - elseif ($Value -is [psobject] -or $Value -is [hashtable]) { - $result = @{} - foreach ($key in $Value.Keys) { - $result[$key] = RenderJsonValue $Value[$key] + function Convert-JsonStructure { + param( + [Parameter(Mandatory)] + $Value + ) + + # Caso 1: array + if ($Value -is [System.Collections.IEnumerable] -and $Value -isnot [string]) { + $result = [System.Collections.IEnumerable]@() + foreach ($item in $Value) { + $innerValue = $null + if ($null -ne $item) { $innerValue = Convert-JsonStructure $item } + $result += $innerValue } return $result } - return $Value + + # Caso 2: PSCustomObject (JSON convertito) + if ($Value -is [PSObject]) { + $dict = [System.Collections.Specialized.OrderedDictionary]::new() + foreach ($prop in $Value.PSObject.Properties) { + if ($null -ne $prop.Value) { + if ($prop.Value -is [System.Collections.IEnumerable] -and $prop.Value.Length -eq 0 -and $prop.Value -isnot [string]) { + $dict[$prop.Name] = [System.Collections.IEnumerable]@() + } + else + { + $dict[$prop.Name] = Convert-JsonStructure $prop.Value + } + } + else { + $dict[$prop.Name] = $null + } + } + return $dict + } + + # Caso 3: hashtable puro + if ($Value -is [hashtable]) { + $dict = [System.Collections.Specialized.OrderedDictionary]::new() + foreach ($key in $Value.Keys) { + $innerValue = $null + if ($null -ne $key -and $null -ne $Value[$key]) { $innerValue = Convert-JsonStructure $Value[$key] } + $dict[$key] = $innerValue + } + return $dict + } + + # Caso 4: valore primitivo → applico la tua funzione + $primitiveValue = $Value + if ($null -ne $Value) { $primitiveValue = Render-Value $Value } + return $primitiveValue } function Add-ParameterVariables ($Name, $Value) { Add-ParameterVariable $Name $Value } @@ -443,14 +499,17 @@ function Build-RequestContent ( function Render-Value ($Value) { if ($Value -isnot [string]) { return $Value } - return ($Value -replace '\{\{([^{}]+)\}\}', { - param($match,$inner) + $regex = [regex]'\{\{([^{}]+)\}\}' + $regex.Replace($Value, { param($match) + $inner = $match.Groups[1].value $placeholder = Parse-PlaceholderContent $inner - if ($placeholder.isDotenv) { return $match } - if ($placeholder.name -and $dotenvVariables.Contains($placeholder.name)) { - return "{{$dotenv $($placeholder.name)}}" + if ($placeholder.isDotenv) { + return $match.Value } - return $match + if ($placeholder.name -and $dotenvVariables.Value.Contains($placeholder.name)) { + return "{{`$dotenv $($placeholder.name)}}" + } + return $match.Value }) } @@ -462,7 +521,7 @@ function Build-RequestContent ( $configVariables = $requestConfig.variables } foreach ($variable in $configVariables) { - if ($variable -and $variable.name) { + if ($null -ne $variable -and $variable.name) { Add-Variable $variable.name $variable.value } } @@ -482,12 +541,12 @@ function Build-RequestContent ( # Headers # ------------------------- $queryParams = @() - $headers = @() + $headers = [ref] @() function Add-Header ($Name, $Value) { if (-not $Name) { return } Add-ReferencedVariables ($Value ?? '') - $headers += @{ + $headers.Value += @{ name = ([string]$Name).Trim() value = Render-Value ($Value ?? '') } @@ -522,7 +581,7 @@ function Build-RequestContent ( Add-ReferencedVariables $value if ($type -eq 'header') { - $headers += @{ name=$name; value=(Render-Value $value) } + $headers.Value += @{ name=$name; value=(Render-Value $value) } } else { $queryParams += @{ name=$name; value="{{$name}}" } @@ -547,7 +606,7 @@ function Build-RequestContent ( Add-Header 'Authorization' ("Basic " + (Render-Value $username) + ":" + (Render-Value $password)) } default { - $headers += @{ + $headers.Value += @{ name = "UNKNOWN_$($requestConfig.auth.type)" value = "Basic $($requestConfig.auth.token)" } @@ -558,9 +617,9 @@ function Build-RequestContent ( # ------------------------- # Commented variables # ------------------------- - if ($commentedVariableDefinitions.Count -gt 0) { + if ($commentedVariableDefinitions.Value.Count -gt 0) { $lines += "# Other variables for $requestName" - foreach ($variable in $commentedVariableDefinitions) { + foreach ($variable in $commentedVariableDefinitions.Value | Sort-Object -Property name, value) { $lines += "# @$(Sanitize-VarName $variable.name)$VARIABLE_NAME_VALUE_SEPARATOR$(Format-VariableValue $variable.value @{ renderValue = { param($v) Render-Value $v } })" } } @@ -568,9 +627,9 @@ function Build-RequestContent ( # ------------------------- # Parameter variables # ------------------------- - if ($parameterVariableDefinitions.Count -gt 0) { + if ($parameterVariableDefinitions.Value.Count -gt 0) { $lines += "# Parameter variables for $requestName" - foreach ($variable in $parameterVariableDefinitions) { + foreach ($variable in $parameterVariableDefinitions.Value | Sort-Object -Property name, value) { $lines += "@$(Sanitize-VarName $variable.name)$VARIABLE_NAME_VALUE_SEPARATOR$(Format-VariableValue $variable.value @{ renderValue = { param($v) Render-Value $v } })" } } @@ -590,10 +649,10 @@ function Build-RequestContent ( $requestBody = Render-Value $jsonData } elseif ($jsonData -is [System.Collections.IEnumerable]) { - $requestBody = (ConvertTo-Json (RenderJsonValue $jsonData) -Depth 20) + $requestBody = (ConvertTo-Json (Convert-JsonStructure $jsonData) -Depth 20) } elseif ($jsonData -is [psobject] -or $jsonData -is [hashtable]) { - $requestBody = (ConvertTo-Json (RenderJsonValue $jsonData) -Depth 20) + $requestBody = (ConvertTo-Json (Convert-JsonStructure $jsonData) -Depth 20) } Add-Header 'Content-Type' 'application/json' @@ -613,9 +672,9 @@ function Build-RequestContent ( # ------------------------- # Variables # ------------------------- - if ($variableDefinitions.Count -gt 0) { + if ($variableDefinitions.Value.Count -gt 0) { $lines += "# Variables for $requestName" - foreach ($variable in $variableDefinitions) { + foreach ($variable in $variableDefinitions.Value | Sort-Object -Property name, value) { $lines += "@$(Sanitize-VarName $variable.name)$VARIABLE_NAME_VALUE_SEPARATOR$(Format-VariableValue $variable.value @{ renderValue = { param($v) Render-Value $v } })" } } @@ -635,7 +694,7 @@ function Build-RequestContent ( $lines += '' $lines += "$method $requestUrl" - foreach ($header in $headers) { + foreach ($header in $headers.Value) { $lines += "$($header.name): $($header.value)" } @@ -655,7 +714,7 @@ function Ensure-Dir($path) { function Walk-YamlFiles($rootDir) { Get-ChildItem -LiteralPath $rootDir -Recurse -File -Include *.yml, *.yaml | - Where-Object { $_.Name -notmatch '^\.|node_modules' } | + Where-Object { $_.Name -notmatch '^\.|node_modules|folder\.yml' } | Select-Object -ExpandProperty FullName } @@ -677,18 +736,22 @@ function Clean-Folder($dir) { } } -function Get-DotenvVariablesForTargetDir ($TargetDir, $OutputRoot, $DotenvVariablesByTarget) { - $variables = New-Object System.Collections.Generic.HashSet[string] +function Get-DotenvVariablesForTargetDir ($TargetDir, $OutputRoot, $DotEnvVarsByTarget) { + $variables = $(New-Object System.Collections.Generic.HashSet[string]) + $variables.Clear() $currentDir = $TargetDir while ($true) { - if ($DotenvVariablesByTarget.ContainsKey($currentDir)) { - foreach ($variable in $DotenvVariablesByTarget[$currentDir]) { - $variables.Add($variable) | Out-Null + if ($DotEnvVarsByTarget.ContainsKey($currentDir)) { + foreach ($variable in $DotEnvVarsByTarget[$currentDir]) { + [void]$variables.Add($variable) } } - $parentDir = Split-Path -Parent $currentDir + if (-not $currentDir) { + Write-warning "Current directory is null while searching for dotenv variables for target dir: $TargetDir" + } + $parentDir = Split-Path -LiteralPath $currentDir if ($currentDir -eq $OutputRoot -or $parentDir -eq $currentDir) { break } @@ -700,17 +763,17 @@ function Get-DotenvVariablesForTargetDir ($TargetDir, $OutputRoot, $DotenvVariab } function Write-EnvironmentTemplates ($sourceDir, $outputRoot) { - $targets = @() - $dotenvVariablesByTarget = @{} # Hashtable: targetDir → HashSet + $targets = [ref] @() + $localDotEnvVarsByTarget = @{} function Visit ([string]$CurrentDir) { $entries = Get-ChildItem -LiteralPath $CurrentDir -Force - $hasEnvironmentsDir = $entries | Where-Object { - $_.PSIsContainer -and $_.Name -eq 'environments' - } + $hasEnvironmentsDir = ($entries | Where-Object { + $_.PSIsContainer -and $_.Name -eq 'environments' -and (Get-ChildItem -LiteralPath $_.FullName -Force | Where-Object { -not $_.PSIsContainer -and $_.Name -match '\.ya?ml$' }).Count -gt 0 + }).Count -gt 0 if ($hasEnvironmentsDir) { - $targets += $CurrentDir + $targets.Value += $CurrentDir } foreach ($entry in $entries) { @@ -724,7 +787,7 @@ function Write-EnvironmentTemplates ($sourceDir, $outputRoot) { Visit $sourceDir - foreach ($dir in $targets) { + foreach ($dir in $targets.Value) { $relativeDir = [System.IO.Path]::GetRelativePath($sourceDir, $dir) if ($relativeDir -and $relativeDir -ne '.') { $targetDir = Join-Path $outputRoot $relativeDir @@ -749,7 +812,7 @@ function Write-EnvironmentTemplates ($sourceDir, $outputRoot) { $seenNames = New-Object System.Collections.Generic.HashSet[string] foreach ($envFile in $envFiles) { - $parsed = Parse-Yaml $envFile + $parsed = Parse-YamlFile $envFile if (-not $parsed) { continue } $variables = @() @@ -764,7 +827,7 @@ function Write-EnvironmentTemplates ($sourceDir, $outputRoot) { if (-not $name) { continue } if ($seenNames.Contains($name)) { continue } - $seenNames.Add($name) + [void]$seenNames.Add($name) # Ma porc $variableNames += $name } } @@ -778,16 +841,16 @@ function Write-EnvironmentTemplates ($sourceDir, $outputRoot) { } $templatePath = Join-Path $targetDir '.env.template' - Set-Content -Path $templatePath -Value $templateContent -Encoding UTF8 + Set-Content -LiteralPath $templatePath -Value $templateContent -Encoding UTF8 -NoNewLine - $dotenvVariablesByTarget[$targetDir] = $seenNames + $localDotEnvVarsByTarget[$targetDir] = $seenNames } - return $dotenvVariablesByTarget + return $localDotEnvVarsByTarget } function Write-JsFiles ($sourceDir, $outputRoot) { - $targets = @() + $targets = [ref] @() function Visit ($CurrentDir) { $entries = Get-ChildItem -LiteralPath $CurrentDir -Force @@ -797,7 +860,7 @@ function Write-JsFiles ($sourceDir, $outputRoot) { } if ($hasJsFiles) { - $targets += $CurrentDir + $targets.Value += $CurrentDir } # Visita ricorsivamente le sottodirectory @@ -812,7 +875,7 @@ function Write-JsFiles ($sourceDir, $outputRoot) { Visit $sourceDir - foreach ($dir in $targets) { + foreach ($dir in $targets.Value) { $relativeDir = [System.IO.Path]::GetRelativePath($sourceDir, $dir) if ($relativeDir -and $relativeDir -ne '.') { $targetDir = Join-Path $outputRoot $relativeDir @@ -842,7 +905,7 @@ function Write-JsFiles ($sourceDir, $outputRoot) { } } - return $targets + return $targets.Value } function Invoke-Main { @@ -859,7 +922,7 @@ function Invoke-Main { throw "No collections found in workspace.yml" } - $outputBaseRoot = Join-Path $workspaceRoot 'autogen/httpyac' + $outputBaseRoot = Join-Path $workspaceRoot 'autogen/httpyac_ps1' Clean-Folder $outputBaseRoot foreach ($collection in $collections) { @@ -880,7 +943,8 @@ function Invoke-Main { $writtenJsFiles = Write-JsFiles $sourceDir $outputRoot # dotenv templates - $dotenvVariablesByTarget = Write-EnvironmentTemplates $sourceDir $outputRoot + $myDotEnvVarsByTarget = @{} + $myDotEnvVarsByTarget = (Write-EnvironmentTemplates $sourceDir $outputRoot) # YAML files $yamlFiles = Walk-YamlFiles $sourceDir @@ -901,19 +965,27 @@ function Invoke-Main { $relativePath = [System.IO.Path]::GetRelativePath($sourceDir, $yamlFile) $parsedPath = [System.IO.Path]::GetFileNameWithoutExtension($relativePath) - $parsedDir = Split-Path $relativePath -Parent + $parsedDir = Split-Path -LiteralPath $relativePath - $targetDir = Join-Path $outputRoot $parsedDir + if ($parsedDir -and $parsedDir -ne '') { + $targetDir = Join-Path $outputRoot $parsedDir + } + else { + $targetDir = $outputRoot + } Ensure-Dir $targetDir $requestConfig = Get-RequestConfigForFile $yamlFile $sourceDir $outputFile = Join-Path $targetDir ("$parsedPath.http") - $dotenvVariables = Get-DotenvVariablesForTargetDir $targetDir $outputRoot $dotenvVariablesByTarget + $myDotenvVariables = Get-DotenvVariablesForTargetDir $targetDir $outputRoot $myDotEnvVarsByTarget + if (-not $myDotenvVariables) { + $myDotenvVariables = $(New-Object System.Collections.Generic.HashSet[string]) + } - $requestContent = Build-RequestContent $httpBlock $requestName $requestConfig $dotenvVariables + $requestContent = Build-RequestContent $httpBlock $requestName $requestConfig ([ref]$myDotenvVariables) - Set-Content -Path $outputFile -Value ($requestContent + "`n") -Encoding UTF8 + Set-Content -LiteralPath $outputFile -Value $requestContent -Encoding UTF8 $processed++ } From e036ab9eaa1d7c247d74efdd5ce266f3b8677874 Mon Sep 17 00:00:00 2001 From: Pier-Paolo Mammi Date: Fri, 3 Jul 2026 08:56:16 +0200 Subject: [PATCH 27/40] rename nodejs package configurations --- scripts/{generate-http-docs.js => generate-http-requests.js} | 0 ...te-http-docs.test.mjs => generate-http-requests.test.mjs} | 2 +- scripts/package-lock.json | 5 ++++- scripts/package.json | 2 ++ 4 files changed, 7 insertions(+), 2 deletions(-) rename scripts/{generate-http-docs.js => generate-http-requests.js} (100%) rename scripts/{generate-http-docs.test.mjs => generate-http-requests.test.mjs} (95%) diff --git a/scripts/generate-http-docs.js b/scripts/generate-http-requests.js similarity index 100% rename from scripts/generate-http-docs.js rename to scripts/generate-http-requests.js diff --git a/scripts/generate-http-docs.test.mjs b/scripts/generate-http-requests.test.mjs similarity index 95% rename from scripts/generate-http-docs.test.mjs rename to scripts/generate-http-requests.test.mjs index 5c4bf07..3f46f4b 100644 --- a/scripts/generate-http-docs.test.mjs +++ b/scripts/generate-http-requests.test.mjs @@ -3,7 +3,7 @@ import assert from 'node:assert/strict'; import fs from 'node:fs'; import os from 'node:os'; import path from 'node:path'; -import { buildRequestContent, getRequestConfigForFile, mergeRequestConfig } from './generate-http-docs.js'; +import { buildRequestContent, getRequestConfigForFile, mergeRequestConfig } from './generate-http-requests.js'; test('does not inherit parent auth when a child config has no auth override', () => { const parentAuth = { type: 'bearer', token: 'parent-token' }; diff --git a/scripts/package-lock.json b/scripts/package-lock.json index fec65a9..f21b0b5 100644 --- a/scripts/package-lock.json +++ b/scripts/package-lock.json @@ -1,9 +1,12 @@ { - "name": "generate-http-docs", + "name": "generate-http-requests", + "version": "0.0.1", "lockfileVersion": 3, "requires": true, "packages": { "": { + "name": "generate-http-requests", + "version": "0.0.1", "dependencies": { "strip-json-comments": "^5.0.3", "yaml": "^2.9.0" diff --git a/scripts/package.json b/scripts/package.json index f9114af..91b88cc 100644 --- a/scripts/package.json +++ b/scripts/package.json @@ -1,4 +1,6 @@ { + "name": "generate-http-requests", + "version": "0.0.1", "type": "module", "dependencies": { "strip-json-comments": "^5.0.3", From 907e67125af85911026e955bc90f8824cd90e8a4 Mon Sep 17 00:00:00 2001 From: Pier-Paolo Mammi Date: Fri, 3 Jul 2026 09:08:20 +0200 Subject: [PATCH 28/40] move nodejs script to tools folder --- .../generate-http-requests}/generate-http-requests.js | 0 .../generate-http-requests}/generate-http-requests.test.mjs | 0 {scripts => tools/generate-http-requests}/package-lock.json | 0 {scripts => tools/generate-http-requests}/package.json | 0 4 files changed, 0 insertions(+), 0 deletions(-) rename {scripts => tools/generate-http-requests}/generate-http-requests.js (100%) rename {scripts => tools/generate-http-requests}/generate-http-requests.test.mjs (100%) rename {scripts => tools/generate-http-requests}/package-lock.json (100%) rename {scripts => tools/generate-http-requests}/package.json (100%) diff --git a/scripts/generate-http-requests.js b/tools/generate-http-requests/generate-http-requests.js similarity index 100% rename from scripts/generate-http-requests.js rename to tools/generate-http-requests/generate-http-requests.js diff --git a/scripts/generate-http-requests.test.mjs b/tools/generate-http-requests/generate-http-requests.test.mjs similarity index 100% rename from scripts/generate-http-requests.test.mjs rename to tools/generate-http-requests/generate-http-requests.test.mjs diff --git a/scripts/package-lock.json b/tools/generate-http-requests/package-lock.json similarity index 100% rename from scripts/package-lock.json rename to tools/generate-http-requests/package-lock.json diff --git a/scripts/package.json b/tools/generate-http-requests/package.json similarity index 100% rename from scripts/package.json rename to tools/generate-http-requests/package.json From cd5dc418324c686d52eb27b84ef15446f519f931 Mon Sep 17 00:00:00 2001 From: Pier-Paolo Mammi Date: Fri, 3 Jul 2026 11:44:42 +0200 Subject: [PATCH 29/40] add json file for environment definition --- .gitignore | 5 ++++- env.json.template | 31 +++++++++++++++++++++++++++++++ 2 files changed, 35 insertions(+), 1 deletion(-) create mode 100644 env.json.template diff --git a/.gitignore b/.gitignore index 6e6e8c9..61dbd68 100644 --- a/.gitignore +++ b/.gitignore @@ -1,6 +1,7 @@ # Secrets .env* !.env.template +env.json # Dependencies node_modules @@ -10,4 +11,6 @@ node_modules Thumbs.db # Automatically generated stuff -autogen/**/* \ No newline at end of file +autogen/**/* + +*.temp \ No newline at end of file diff --git a/env.json.template b/env.json.template new file mode 100644 index 0000000..bbf32c2 --- /dev/null +++ b/env.json.template @@ -0,0 +1,31 @@ +{ + "API": { + "elixForms API v2": { + "elixFormsWsAuthenticationToken": null, + "elixFormsApiPassword": null, + "elixFormsApiUsername": null + }, + "ESSE3 Anagrafica API": { + "esse3apiUsername": null, + "esse3apiPassword": null + }, + "ESSE3 Common Auth API": { + "esse3apiUsername": null, + "esse3apiPassword": null + }, + "IDEM WebServices": { + "IdemApiPassword_Test": null, + "IdemApiPassword_Prod": null, + "IdemApiKey_Prod": null, + "IdemApiKey_Test": null + }, + "IRIS GW (Gateway) REST API (v1)": { + "IrisApiPassword": null, + "IrisApiUsername": null + }, + "Scopus": { + "ScopusApiKey1": null, + "ScopusApiKey2": null + } + } +} \ No newline at end of file From 4157e539f68b55d4c3af7d60650e436ad1570590 Mon Sep 17 00:00:00 2001 From: Pier-Paolo Mammi Date: Fri, 3 Jul 2026 11:45:13 +0200 Subject: [PATCH 30/40] add script to create and configure json environment file --- scripts/update-json-environment.ps1 | 111 ++++++++++++++++++++++++++++ 1 file changed, 111 insertions(+) create mode 100644 scripts/update-json-environment.ps1 diff --git a/scripts/update-json-environment.ps1 b/scripts/update-json-environment.ps1 new file mode 100644 index 0000000..196ffcb --- /dev/null +++ b/scripts/update-json-environment.ps1 @@ -0,0 +1,111 @@ +# Percorsi file +$inputJsonPath = Join-Path $PSScriptRoot ".." "env.json.template" # JSON originale +$outputJsonPath = Join-Path $PSScriptRoot ".." "env.json" # JSON di destinazione + +# Lettura JSON originale mantenendo l'ordine +$rawJson = Get-Content $inputJsonPath -Raw +$parsedJson = $rawJson | ConvertFrom-Json -AsHashtable + +# Se env.json esiste, lo carico per preservare le sezioni non aggiornate +$existingEnv = $null +if (Test-Path $outputJsonPath) { + $existingEnv = (Get-Content $outputJsonPath -Raw) | ConvertFrom-Json -AsHashtable +} + +# Funzione per chiedere Y|S/N +function Ask-YesNo($message) { + while ($true) { + $resp = Read-Host "$message [YySs/Nn]" + switch ($resp.ToUpper()) { + "N" { return $false } + default { return $true } + } + } +} + +# Funzione per chiedere un valore +function Ask-Value($key) { + return Read-Host "Valore per '$key' (digita `"`" per inserire stringa vuota e lascia vuoto per NON aggiornare)" +} + +# Copia profonda preservando ordine +$newJson = [ordered]@{} + +foreach ($topKey in $parsedJson.Keys) { + + # Sezione API → trattamento speciale + if ($topKey -eq "API") { + + $newJson["API"] = [ordered]@{} + + foreach ($sectionName in $parsedJson["API"].Keys) { + + $section = $parsedJson["API"][$sectionName] + + $shouldConfigure = Ask-YesNo "Vuoi configurare la sezione '$sectionName'?" + + # Se NON voglio configurare → devo distinguere: + if (-not $shouldConfigure) { + Write-Host "Sezione '$sectionName' non configurata. Mantengo valori esistenti, se presenti." -ForegroundColor Yellow + + # 1. Se NON esiste già env.json → creo sezione vuota uguale al template + if (-not $existingEnv) { + $newJson["API"][$sectionName] = $section + continue + } + + # 2. Se esiste già env.json e sia API che la sezione sono presenti → mantengo la versione esistente + if ($existingEnv["API"] -and $existingEnv["API"].Contains($sectionName)) { + $newJson["API"][$sectionName] = $existingEnv["API"][$sectionName] + continue + } + + # 3. Se esiste già env.json, ma API o la sezione non sono presenti → creo sezione vuota uguale al template + $newJson["API"][$sectionName] = $section + continue + } + + # Altrimenti creo una nuova sezione (o aggiorno quella esistente) + $newSection = [ordered]@{} + + foreach ($key in $section.Keys) { + $inputValue = Ask-Value $key + + if ($existingEnv -and $existingEnv["API"] -and $existingEnv["API"].Contains($sectionName)) { + $oldValue = $existingEnv["API"][$sectionName][$key] + } + else { + $oldValue = "" + } + + if ($inputValue -eq "") { + # Mantieni valore esistente se presente + $newSection[$key] = $oldValue + } + elseif ($inputValue -eq "`"`"") { + # Aggiorna con stringa vuota + $newSection[$key] = "" + } + else { + # Aggiorna con nuovo valore + $newSection[$key] = $inputValue + } + } + + $newJson["API"][$sectionName] = $newSection + } + } + else { + # Altri elementi allo stesso livello di API → preservati integralmente + if ($existingEnv -and $existingEnv.Contains($topKey)) { + $newJson[$topKey] = $existingEnv[$topKey] + } else { + $newJson[$topKey] = $parsedJson[$topKey] + } + } +} + +# Scrittura JSON finale mantenendo l'ordine +$newJson | ConvertTo-Json -Depth 20 | Set-Content $outputJsonPath -Encoding UTF8 + +Write-Host "`nFile env.json aggiornato correttamente." From 2ab210c13bbe040db6f42136598342759a572ed6 Mon Sep 17 00:00:00 2001 From: Pier-Paolo Mammi Date: Fri, 3 Jul 2026 11:45:41 +0200 Subject: [PATCH 31/40] add script to update api collections env files --- scripts/update-api-environment-files.ps1 | 134 +++++++++++++++++++++++ 1 file changed, 134 insertions(+) create mode 100644 scripts/update-api-environment-files.ps1 diff --git a/scripts/update-api-environment-files.ps1 b/scripts/update-api-environment-files.ps1 new file mode 100644 index 0000000..3938e3f --- /dev/null +++ b/scripts/update-api-environment-files.ps1 @@ -0,0 +1,134 @@ +# Percorsi file +$envFile = Join-Path $PSScriptRoot ".." "env.json" # JSON originale +$collectionsRoot = Join-Path $PSScriptRoot ".." "collections" # cartella di partenza delle collezioni + + +# 1. Se il file non esiste → errore +if (-not (Test-Path $envFile)) { + Write-Error "File env.json non trovato." + exit 1 +} + +# Carica JSON mantenendo ordine +$raw = Get-Content $envFile -Raw +$data = $raw | ConvertFrom-Json -AsHashtable + +if (-not $data.ContainsKey("API")) { + Write-Error "Il file env.json non contiene la sezione 'API'." + exit 1 +} + +# Funzione per leggere file .env (KEY=VALUE) +function Read-EnvFile($path) { + $result = [ordered]@{} + foreach ($line in Get-Content $path) { + if ($line.Trim() -eq "" -or $line.Trim().StartsWith("#")) { continue } + if ($line -match "^\s*([^=]+)\s*=\s*(.*)$") { + $key = $matches[1].Trim() + $value = $matches[2] + $result[$key] = $value + } + } + return $result +} + +# Funzione per scrivere file .env +function Write-EnvFile($path, $hashtable) { + $lines = foreach ($k in $hashtable.Keys) { + "$k=$(Format-EnvValue $hashtable[$k])" + } + Set-Content $path -Value $lines -Encoding UTF8 +} + +function Format-EnvValue($value) { + if ($null -eq $value) { + return "" + } + if ($value -match "#") { + return "'$value'" + } + return $value +} + +function KeysMatch($a, $b) { + $diff = Compare-Object -ReferenceObject ($a | Sort-Object -Unique) -DifferenceObject ($b | Sort-Object -Unique) + + return -not $diff +} + +# 2. Scorri tutte le sezioni sotto API +foreach ($sectionName in $data["API"].Keys) { + + Write-Host "`n--- Sezione: $sectionName ---" + + $section = $data["API"][$sectionName] + + # a. Verifica esistenza cartella + $folder = Join-Path $collectionsRoot $sectionName + if (-not (Test-Path $folder)) { + Write-Warning "La cartella '$folder' non esiste. Sezione ignorata." + continue + } + + # b. Verifica .env.template + $templatePath = Join-Path $folder ".env.template" + if (Test-Path $templatePath) { + $template = Read-EnvFile $templatePath + + $templateKeys = $template.Keys + $sectionKeys = $section.Keys + + if ($templateKeys.Count -ne $sectionKeys.Count -or -not (KeysMatch $templateKeys $sectionKeys)) { + Write-Warning "Il file .env.template in '$sectionName' non ha le stesse chiavi della sezione." + } + } + + # c/d/e. Gestione file .env + $envPath = Join-Path $folder ".env" + + if (-not (Test-Path $envPath)) { + # c. Genera nuovo file .env + Write-Host "Generazione nuovo file .env per '$sectionName'." + $newEnv = [ordered]@{} + foreach ($key in $section.Keys) { + $newEnv[$key] = $section[$key] + } + Write-EnvFile $envPath $newEnv + continue + } + + # d. Verifica chiavi .env esistente + $existingEnv = Read-EnvFile $envPath + + $envKeys = $existingEnv.Keys + $sectionKeys = $section.Keys + + if ($envKeys.Count -ne $sectionKeys.Count -or -not (KeysMatch $envKeys $sectionKeys)) { + Write-Warning "Il file .env in '$sectionName' non ha le stesse chiavi della sezione." + } + + # e. Aggiorna valori + $updatedEnv = [ordered]@{} + + foreach ($key in $section.Keys) { + $valueFromJson = $section[$key] + + if ($existingEnv.Contains($key)) { + if ($null -ne $valueFromJson) { + # aggiorna + $updatedEnv[$key] = $valueFromJson + } else { + # mantieni + $updatedEnv[$key] = $existingEnv[$key] + } + } else { + # chiave mancante → aggiungi + $updatedEnv[$key] = $valueFromJson + } + } + + Write-Host "Aggiornamento file .env per '$sectionName'." + Write-EnvFile $envPath $updatedEnv +} + +Write-Host "`nOperazione completata." From 8298e60bc4b8ddcd168a45496a03d828ef94d208 Mon Sep 17 00:00:00 2001 From: Pier-Paolo Mammi Date: Mon, 6 Jul 2026 16:23:45 +0200 Subject: [PATCH 32/40] fix EFTL output for delibera tempate --- .../Proposta/elixPro - Template Delibera ONLYTABLE.yml | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/collections/elixForms API v2/EFTL processing/CCT - Liquidazione Compensi/Proposta/elixPro - Template Delibera ONLYTABLE.yml b/collections/elixForms API v2/EFTL processing/CCT - Liquidazione Compensi/Proposta/elixPro - Template Delibera ONLYTABLE.yml index 6eda357..a824ec8 100644 --- a/collections/elixForms API v2/EFTL processing/CCT - Liquidazione Compensi/Proposta/elixPro - Template Delibera ONLYTABLE.yml +++ b/collections/elixForms API v2/EFTL processing/CCT - Liquidazione Compensi/Proposta/elixPro - Template Delibera ONLYTABLE.yml @@ -118,8 +118,12 @@ runtime: var response = res.getBody(); if (response.value.code === "ERROR") { - decodedDocument = "ERRORE EFTL!\n"; - decodedDocument += response.value.description.split("\n").slice(0, 3).join("\n"); + decodedDocument = "

ERRORE EFTL!

"; + decodedDocument += "" + response.value.description.split("\n").slice(0, 3).join("\n") + ""; + } + else if (response.value.processedDocument === "") { + decodedDocument = "

EMPTY OUTPUT!

"; + decodedDocument += "" + response.value.description.split("\n").slice(0, 3).join("\n") + ""; } else { decodedDocument = atob(response.value.processedDocument); From a70e06a83facec1fb1dd37c9df094e34291c8c1d Mon Sep 17 00:00:00 2001 From: Pier-Paolo Mammi Date: Wed, 8 Jul 2026 16:34:29 +0200 Subject: [PATCH 33/40] fix setup environment for node tools --- scripts/setup-environment.ps1 | 26 ++++++++++++++++++++------ 1 file changed, 20 insertions(+), 6 deletions(-) diff --git a/scripts/setup-environment.ps1 b/scripts/setup-environment.ps1 index 38b0fec..b949b29 100644 --- a/scripts/setup-environment.ps1 +++ b/scripts/setup-environment.ps1 @@ -11,13 +11,27 @@ function Initialize-PowerShellEnvironment { function Initialize-GenerateTools { Write-Host "Initializing Node.js dependencies..." -ForegroundColor Yellow - Push-Location -StackName NodeTools (Join-Path $PSScriptRoot "../scripts/") + Push-Location -StackName NodeTools (Join-Path $PSScriptRoot "../tools/") - # Install Node.js dependencies - & npm install - if ($LASTEXITCODE -ne 0) { - Write-Error "npm install failed with exit code $LASTEXITCODE." - exit 1 + Get-childitem -Path . -Directory | ForEach-Object { + Write-Host "Initializing $($_.Name)..." -ForegroundColor Cyan + + Push-Location -StackName NodeTools $_.FullName + try { + # Install Node.js dependencies + & npm install + if ($LASTEXITCODE -ne 0) { + Write-Error "npm install failed with exit code $LASTEXITCODE." + exit 1 + } + } + catch { + Write-Error "npm install failed for $($_.Name): $_" + exit 1 + } + finally { + Pop-Location -StackName NodeTools + } } Pop-Location -StackName NodeTools From ca9ba75c2107aad6d3f7e3dfcf8ac6ede602cb71 Mon Sep 17 00:00:00 2001 From: Pier-Paolo Mammi Date: Tue, 14 Jul 2026 13:32:59 +0200 Subject: [PATCH 34/40] major refactor - change autogenerated folder to autodocs/httpyac - renamed many environment variables - add config section to env template to manage different apps - cleanup bruno environments for easier automation of env files - add pre-request and post-response scripts from bruno - manage EFTL-specific scripts - add scripts to setup json template - add scripts to update environment files --- .gitignore | 2 +- .../ESSE3 Anagrafica Pre-Prod #2.yml | 4 +- .../ESSE3 Anagrafica API/opencollection.yml | 2 +- .../ESSE3 Common Auth Pre-Prod #2.yml | 2 + .../ESSE3 Common Auth API/opencollection.yml | 6 +- collections/IDEM WebServices/.env.template | 7 +- .../Contratti/Contratto Esteso (IRIS GW).yml | 36 +---- .../{IDEM - Prod.yml => Produzione.yml} | 8 +- .../{IDEM - Test.yml => Test.yml} | 8 +- .../environments/elixForms - Prod.yml | 6 +- env.json.template | 30 +++- scripts/generate-http-requests.ps1 | 93 ++++++++++- ...ronment.ps1 => setup-json-environment.ps1} | 18 ++- scripts/update-bruno-environments.ps1 | 152 ++++++++++++++++++ ... => update-http-requests-environments.ps1} | 43 +++-- setup-json-environment.bat | 13 ++ update-bruno-environments.bat | 13 ++ update-http-requests-environments.bat | 13 ++ 18 files changed, 368 insertions(+), 88 deletions(-) rename collections/IDEM WebServices/environments/{IDEM - Prod.yml => Produzione.yml} (53%) rename collections/IDEM WebServices/environments/{IDEM - Test.yml => Test.yml} (54%) rename scripts/{update-json-environment.ps1 => setup-json-environment.ps1} (86%) create mode 100644 scripts/update-bruno-environments.ps1 rename scripts/{update-api-environment-files.ps1 => update-http-requests-environments.ps1} (63%) create mode 100644 setup-json-environment.bat create mode 100644 update-bruno-environments.bat create mode 100644 update-http-requests-environments.bat diff --git a/.gitignore b/.gitignore index 61dbd68..8e60403 100644 --- a/.gitignore +++ b/.gitignore @@ -11,6 +11,6 @@ node_modules Thumbs.db # Automatically generated stuff -autogen/**/* +autodocs/**/* *.temp \ No newline at end of file diff --git a/collections/ESSE3 Anagrafica API/environments/ESSE3 Anagrafica Pre-Prod #2.yml b/collections/ESSE3 Anagrafica API/environments/ESSE3 Anagrafica Pre-Prod #2.yml index dd47f79..7cfd6dc 100644 --- a/collections/ESSE3 Anagrafica API/environments/ESSE3 Anagrafica Pre-Prod #2.yml +++ b/collections/ESSE3 Anagrafica API/environments/ESSE3 Anagrafica Pre-Prod #2.yml @@ -1,6 +1,6 @@ -name: "ESSE3 Pre-Prod #2" +name: "ESSE3 Anagrafica Pre-Prod #2" variables: - - name: rootUrl + - name: esse3apiRootUrl value: https://unipr2.esse3.pp.cineca.it - name: esse3apiUsername value: "{{process.env.esse3apiUsername}}" diff --git a/collections/ESSE3 Anagrafica API/opencollection.yml b/collections/ESSE3 Anagrafica API/opencollection.yml index 7bca13a..c7974e6 100644 --- a/collections/ESSE3 Anagrafica API/opencollection.yml +++ b/collections/ESSE3 Anagrafica API/opencollection.yml @@ -21,7 +21,7 @@ request: password: "{{esse3apiPassword}}" variables: - name: baseUrl - value: "{{rootUrl}}/e3rest/api/anagrafica-service-v2" + value: "{{esse3apiRootUrl}}/anagrafica-service-v2" bundled: false extensions: bruno: diff --git a/collections/ESSE3 Common Auth API/environments/ESSE3 Common Auth Pre-Prod #2.yml b/collections/ESSE3 Common Auth API/environments/ESSE3 Common Auth Pre-Prod #2.yml index e515e23..b4148d6 100644 --- a/collections/ESSE3 Common Auth API/environments/ESSE3 Common Auth Pre-Prod #2.yml +++ b/collections/ESSE3 Common Auth API/environments/ESSE3 Common Auth Pre-Prod #2.yml @@ -4,3 +4,5 @@ variables: value: "{{process.env.esse3apiUsername}}" - name: esse3apiPassword value: "{{process.env.esse3apiPassword}}" + - name: esse3apiRootUrl + value: https://unipr2.esse3.pp.cineca.it/e3rest/api diff --git a/collections/ESSE3 Common Auth API/opencollection.yml b/collections/ESSE3 Common Auth API/opencollection.yml index 57da171..57fa79c 100644 --- a/collections/ESSE3 Common Auth API/opencollection.yml +++ b/collections/ESSE3 Common Auth API/opencollection.yml @@ -21,11 +21,7 @@ request: password: "{{esse3apiPassword}}" variables: - name: baseUrl - value: https://unipr2.esse3.pp.cineca.it/e3rest/api - - name: esse3apiUsername - value: da2.rest - - name: esse3apiPassword - value: paperino + value: "{{esse3apiRootUrl}}" bundled: false extensions: bruno: diff --git a/collections/IDEM WebServices/.env.template b/collections/IDEM WebServices/.env.template index 5c255a0..9bc94ce 100644 --- a/collections/IDEM WebServices/.env.template +++ b/collections/IDEM WebServices/.env.template @@ -1,4 +1,3 @@ -IdemApiPassword_Test= -IdemApiPassword_Prod= -IdemApiKey_Prod= -IdemApiKey_Test= \ No newline at end of file +IdemApiUsername= +IdemApiPassword= +IdemApiKey= diff --git a/collections/IDEM WebServices/Contratti/Contratto Esteso (IRIS GW).yml b/collections/IDEM WebServices/Contratti/Contratto Esteso (IRIS GW).yml index 6a69f48..1e5f374 100644 --- a/collections/IDEM WebServices/Contratti/Contratto Esteso (IRIS GW).yml +++ b/collections/IDEM WebServices/Contratti/Contratto Esteso (IRIS GW).yml @@ -5,43 +5,11 @@ info: http: method: GET - url: "{{IdemApiUrl}}/contratto_fs_esteso_ap.php?cod_con=DONO_G_25_ACC_ACC_ZOETIS_01" + url: "{{IdemApiUrl}}/contratto_fs_esteso_ap.php?cod_con=GATT_M_26_CCS_IST_RA_UNIFE_01" params: - name: cod_con - value: CHIA_L_26_ACC_ACC_PROROGASTUDIOBALLERINI_01 + value: GATT_M_26_CCS_IST_RA_UNIFE_01 type: query - disabled: true - - name: cod_con - value: BUTT_F_26_SPONSOR_CHIESI_02 - type: query - disabled: true - - name: cod_con - value: GIUL_F_25_CRCT_RA_MOVYON_01 - type: query - disabled: true - - name: cod_con - value: VIGN_G_26_SERV_CON_DULEVO_01 - type: query - disabled: true - - name: cod_con - value: VILL_P_26_SPONSOR_CREDIT_01 - type: query - disabled: true - - name: cod_con - value: STOR_F_26_CONV_QUA_AMICIPILOTTA_01 - type: query - disabled: true - - name: cod_con - value: DONO_G_25_ACC_ACC_ZOETIS_01 - type: query - - name: cod_con - value: VERO_L_26_CRCT_RA_AOUPR_01 - type: query - disabled: true - - name: cod_con - value: POGL_F_25_SERV_CON_02 - type: query - disabled: true auth: inherit runtime: diff --git a/collections/IDEM WebServices/environments/IDEM - Prod.yml b/collections/IDEM WebServices/environments/Produzione.yml similarity index 53% rename from collections/IDEM WebServices/environments/IDEM - Prod.yml rename to collections/IDEM WebServices/environments/Produzione.yml index eaa8ab0..a8405de 100644 --- a/collections/IDEM WebServices/environments/IDEM - Prod.yml +++ b/collections/IDEM WebServices/environments/Produzione.yml @@ -1,11 +1,11 @@ -name: IDEM - Prod +name: Produzione color: "#2E8A54" variables: - name: IdemApiUrl value: https://www.idem.unipr.it/ws/elix - name: IdemApiUsername - value: elix_ws + value: "{{process.env.IdemApiUsername}}" - name: IdemApiPassword - value: "{{process.env.IdemApiPassword_Prod}}" + value: "{{process.env.IdemApiPassword}}" - name: IdemApiKey - value: "{{process.env.IdemApiKey_Prod}}" + value: "{{process.env.IdemApiKey}}" diff --git a/collections/IDEM WebServices/environments/IDEM - Test.yml b/collections/IDEM WebServices/environments/Test.yml similarity index 54% rename from collections/IDEM WebServices/environments/IDEM - Test.yml rename to collections/IDEM WebServices/environments/Test.yml index a9776cb..131863b 100644 --- a/collections/IDEM WebServices/environments/IDEM - Test.yml +++ b/collections/IDEM WebServices/environments/Test.yml @@ -1,11 +1,11 @@ -name: IDEM - Test +name: Test color: "#C77A0F" variables: - name: IdemApiUrl value: https://www.idem2.unipr.it/ws/elix - name: IdemApiUsername - value: elix_ws + value: "{{process.env.IdemApiUsername}}" - name: IdemApiPassword - value: "{{process.env.IdemApiPassword_Test}}" + value: "{{process.env.IdemApiPassword}}" - name: IdemApiKey - value: "{{process.env.IdemApiKey_Test}}" + value: "{{process.env.IdemApiKey}}" diff --git a/collections/elixForms API v2/environments/elixForms - Prod.yml b/collections/elixForms API v2/environments/elixForms - Prod.yml index 793ad02..73d9aa3 100644 --- a/collections/elixForms API v2/environments/elixForms - Prod.yml +++ b/collections/elixForms API v2/environments/elixForms - Prod.yml @@ -2,9 +2,7 @@ name: elixForms - Prod color: "#2E8A54" variables: - name: elixFormsApiUrl - value: "{{elixFormsRootUrl}}/eF/services/api" - - name: elixFormsRootUrl - value: https://procedure.unipr.it + value: https://procedure.unipr.it/eF/services/api - name: elixFormsApiUsername value: "{{process.env.elixFormsApiUsername}}" - name: elixRegisterResultColumns @@ -12,6 +10,6 @@ variables: - name: elixFormsWsAuthenticationToken value: "{{process.env.elixFormsWsAuthenticationToken}}" - name: elixFormsApiUrl_Default - value: "{{elixFormsRootUrl}}/eF/api" + value: https://procedure.unipr.it/eF/api - name: elixFormsApiPassword value: "{{process.env.elixFormsApiPassword}}" diff --git a/env.json.template b/env.json.template index bbf32c2..0aeb101 100644 --- a/env.json.template +++ b/env.json.template @@ -1,27 +1,41 @@ { + "Config": { + "ExcludeFromBruno": [ + "elixFormsApiUrl", + "elixFormsApiUrl_Default", + "esse3apiRootUrl", + "IdemApiUrl", + "IrisApiUrl" + ] + }, "API": { "elixForms API v2": { - "elixFormsWsAuthenticationToken": null, + "elixFormsApiUrl": "https://procedure.unipr.it/eF/services/api", + "elixFormsApiUrl_Default": "https://procedure.unipr.it/eF/api", + "elixFormsApiUsername": null, "elixFormsApiPassword": null, - "elixFormsApiUsername": null + "elixFormsWsAuthenticationToken": null }, "ESSE3 Anagrafica API": { + "esse3apiRootUrl": "https://unipr2.esse3.pp.cineca.it/e3rest/api", "esse3apiUsername": null, "esse3apiPassword": null }, "ESSE3 Common Auth API": { + "esse3apiRootUrl": "https://unipr2.esse3.pp.cineca.it/e3rest/api", "esse3apiUsername": null, "esse3apiPassword": null }, "IDEM WebServices": { - "IdemApiPassword_Test": null, - "IdemApiPassword_Prod": null, - "IdemApiKey_Prod": null, - "IdemApiKey_Test": null + "IdemApiUrl": "https://www.idem.unipr.it/ws/elix", + "IdemApiUsername": null, + "IdemApiPassword": null, + "IdemApiKey": null }, "IRIS GW (Gateway) REST API (v1)": { - "IrisApiPassword": null, - "IrisApiUsername": null + "IrisApiUrl": "https://air.unipr.it/gw/rest/api", + "IrisApiUsername": null, + "IrisApiPassword": null }, "Scopus": { "ScopusApiKey1": null, diff --git a/scripts/generate-http-requests.ps1 b/scripts/generate-http-requests.ps1 index b7ee3e3..b0da455 100644 --- a/scripts/generate-http-requests.ps1 +++ b/scripts/generate-http-requests.ps1 @@ -201,12 +201,24 @@ function Parse-HttpBlock ($text) { $body = $http.body } + $preRequestScript = $parsed.runtime?.scripts | Where-Object { $_.type -eq 'before-request' } | Select-Object -First 1 -ExpandProperty 'code' + # $preRequestScript = $null + # if ($parsed.runtime -and ($parsed.runtime -is [psobject] -or $parsed.runtime -is [hashtable])) { + # } + + $postResponseScript = $parsed.runtime?.scripts | Where-Object { $_.type -eq 'after-response' } | Select-Object -First 1 -ExpandProperty 'code' + # $postResponseScript = $null + # if ($parsed.runtime -and ($parsed.runtime -is [psobject] -or $parsed.runtime -is [hashtable])) { + # } + return @{ method = $http.method ?? 'GET' url = $http.url ?? '' params = $params headers = $headers body = $body + preRequestScript = $preRequestScript + postResponseScript = $postResponseScript } } @@ -370,7 +382,13 @@ function Get-RequestConfigForFile ($yamlFile, $sourceDir) { $dirChain = @() $currentDir = Split-Path -LiteralPath $yamlFile + $result = @{} + while ($true) { + if ($currentDir -match [regex]::Escape("EFTL processing")) { + $result.hasEftlProcessing = $true + } + $dirChain = ,$currentDir + $dirChain if ($currentDir -eq $sourceDir) { break @@ -390,7 +408,6 @@ function Get-RequestConfigForFile ($yamlFile, $sourceDir) { # Aggiungi il file principale Add-File $yamlFile - $result = @{} foreach ($config in $resolved.Value) { $result = Merge-RequestConfig $result $config } @@ -513,6 +530,38 @@ function Build-RequestContent ($request, $requestName, $requestConfig = @{}, [re }) } + function Replace-PreRequestEftlScript ($inputText) { + # Sostituisce tutto fino al primo [EFTL] con codice specifico + $processedPreRequest = ($inputText -replace '^[\s\S]*?(?=\[EFTL\])', "exports.elixBase64EftlDocument = btoa(String.raw```n") + # Sostituisce tutto fino al primo [EFTL] con codice specifico + $processedPreRequest = ($processedPreRequest -replace '(?s)(.*\[/EFTL\]).*$', "`$1`n``);") + return $processedPreRequest + } + + function Add-DefaultPostResponseEftlScript { + return @" +var status = response.statusCode; + +if (status !== 200) { + console.log("ERRORE HTTP! Response status code: " + status); + return; +} + +var decodedDocument = ""; +var response = response.parsedBody; + +if (response.value.code === "ERROR") { + decodedDocument = "ERRORE EFTL!\n"; + decodedDocument += response.value.description.split("\n").slice(0, 3).join("\n"); +} +else { + decodedDocument = atob(response.value.processedDocument); +} + +console.log(decodedDocument); +"@ + } + # ------------------------- # Variabili da requestConfig # ------------------------- @@ -679,6 +728,24 @@ function Build-RequestContent ($request, $requestName, $requestConfig = @{}, [re } } + # ------------------------- + # Super-special treatment for requests belonging to elixForms API v2\EFTL Processing folder + # Here we blindly assume that ALL requests must be treated in the same way! + # Pre-request script is taken from the original request and manipulated so it can be integrated into the generated .http file + # ------------------------- + if ($request.preRequestScript) { + $lines += '' + $lines += "{{" + $lines += "// Pre-request script" + if ($requestConfig.hasEftlProcessing) { + $lines += (Replace-PreRequestEftlScript $request.preRequestScript) + } + else { + $lines += $request.preRequestScript + } + $lines += "}}" + } + # ------------------------- # Final request line # ------------------------- @@ -703,6 +770,26 @@ function Build-RequestContent ($request, $requestName, $requestConfig = @{}, [re $lines += $requestBody } + # ------------------------- + # Super-special treatment for requests belonging to elixForms API v2\EFTL Processing folder + # Here we blindly assume that ALL requests must be treated in the same way! + # Post-response script is overwritten by default so it should magically work + # ------------------------- + if ($requestConfig.hasEftlProcessing) { + $lines += '' + $lines += "{{" + $lines += "// Post-response script (EFTL)" + $lines += Add-DefaultPostResponseEftlScript + $lines += "}}" + } + elseif ($request.postResponseScript) { + $lines += '' + $lines += "{{" + $lines += "// Post-response script" + $lines += $request.postResponseScript + $lines += "}}" + } + return ($lines -join "`n") } @@ -729,7 +816,7 @@ function Clean-Folder($dir) { Remove-Item -LiteralPath $entry.FullName -Force } } else { - if (!$entry.PSIsContainer -and $entry.Name -match '\.js$|\.http$|\.env\.template$') { + if (!$entry.PSIsContainer -and $entry.Name -match '\.js$|\.http$|^\.env\..*$') { Remove-Item -LiteralPath $entry.FullName -Force } } @@ -922,7 +1009,7 @@ function Invoke-Main { throw "No collections found in workspace.yml" } - $outputBaseRoot = Join-Path $workspaceRoot 'autogen/httpyac_ps1' + $outputBaseRoot = Join-Path $workspaceRoot 'autodocs/httpyac' Clean-Folder $outputBaseRoot foreach ($collection in $collections) { diff --git a/scripts/update-json-environment.ps1 b/scripts/setup-json-environment.ps1 similarity index 86% rename from scripts/update-json-environment.ps1 rename to scripts/setup-json-environment.ps1 index 196ffcb..5f9e847 100644 --- a/scripts/update-json-environment.ps1 +++ b/scripts/setup-json-environment.ps1 @@ -17,8 +17,9 @@ function Ask-YesNo($message) { while ($true) { $resp = Read-Host "$message [YySs/Nn]" switch ($resp.ToUpper()) { - "N" { return $false } - default { return $true } + "Y" { return $true } + "S" { return $true } + default { return $false } } } } @@ -32,14 +33,17 @@ function Ask-Value($key) { $newJson = [ordered]@{} foreach ($topKey in $parsedJson.Keys) { + if ($topKey -eq "Config") { + # Copia Config senza modifiche, i parametri serviranno dopo la generazione + $newJson["Config"] = $parsedJson["Config"] + continue + } # Sezione API → trattamento speciale if ($topKey -eq "API") { - $newJson["API"] = [ordered]@{} foreach ($sectionName in $parsedJson["API"].Keys) { - $section = $parsedJson["API"][$sectionName] $shouldConfigure = Ask-YesNo "Vuoi configurare la sezione '$sectionName'?" @@ -69,6 +73,12 @@ foreach ($topKey in $parsedJson.Keys) { $newSection = [ordered]@{} foreach ($key in $section.Keys) { + if ($key -eq "_httpyac_only") { + # Mantieni la chiave speciale senza chiedere input + $newSection[$key] = $section[$key] + continue + } + $inputValue = Ask-Value $key if ($existingEnv -and $existingEnv["API"] -and $existingEnv["API"].Contains($sectionName)) { diff --git a/scripts/update-bruno-environments.ps1 b/scripts/update-bruno-environments.ps1 new file mode 100644 index 0000000..39c200a --- /dev/null +++ b/scripts/update-bruno-environments.ps1 @@ -0,0 +1,152 @@ +# Percorsi file +$envFile = Join-Path $PSScriptRoot ".." "env.json" # JSON originale +$collectionsRoot = Join-Path $PSScriptRoot ".." "collections" # cartella di partenza delle collezioni + +# Costanti +$ENV_JSON_FILENAME = "env.json" +$CFG_SECTION_NAME = "Config" +$EXCLUDE_BRUNO_CFG_NAME = "ExcludeFromBruno" +$API_SECTION_NAME = "API" +$ENV_TEMPLATE_FILENAME = ".env.template" +$ENV_FILENAME = ".env" + +# 1. Se il file non esiste → errore +if (-not (Test-Path $envFile)) { + Write-Error "File '$ENV_JSON_FILENAME' non trovato." + exit 1 +} + +# Carica JSON mantenendo ordine +$raw = Get-Content $envFile -Raw +$data = $raw | ConvertFrom-Json -AsHashtable + +if (-not $data.ContainsKey($API_SECTION_NAME)) { + Write-Error "Il file '$ENV_JSON_FILENAME' non contiene la sezione '$API_SECTION_NAME'." + exit 1 +} + +# Funzione per leggere file .env (KEY=VALUE) +function Read-EnvFile($path) { + $result = [ordered]@{} + foreach ($line in Get-Content $path) { + if ($line.Trim() -eq "" -or $line.Trim().StartsWith("#")) { continue } + if ($line -match "^\s*([^=]+)\s*=\s*(.*)$") { + $key = $matches[1].Trim() + $value = $matches[2] + $result[$key] = $value + } + } + return $result +} + +# Funzione per scrivere file .env +function Write-EnvFile($path, $hashtable) { + $lines = foreach ($k in $hashtable.Keys) { + "$k=$(Format-EnvValue $hashtable[$k])" + } + Set-Content $path -Value $lines -Encoding UTF8 +} + +function Format-EnvValue($value) { + if ($null -eq $value) { + return "" + } + if ($value -match "#") { + return "'$value'" + } + return $value +} + +function KeysMatch($a, $b) { + $diff = Compare-Object -ReferenceObject ($a | Sort-Object -Unique) -DifferenceObject ($b | Sort-Object -Unique) + + return -not $diff +} + +# 2a. Leggi la configurazione di base (Config) se presente +$config = $null +$noBrunoKeys = @() +if ($data.ContainsKey($CFG_SECTION_NAME)) { + $config = $data[$CFG_SECTION_NAME] + if ($config.ContainsKey($EXCLUDE_BRUNO_CFG_NAME)) { + $noBrunoKeys = $config[$EXCLUDE_BRUNO_CFG_NAME] + } +} + +# 2. Scorri tutte le sezioni sotto API +foreach ($sectionName in $data[$API_SECTION_NAME].Keys) { + + Write-Host "`n--- Sezione: $sectionName ---" + + $section = $data[$API_SECTION_NAME][$sectionName] + + # a. Verifica esistenza cartella + $folder = Join-Path $collectionsRoot $sectionName + if (-not (Test-Path $folder)) { + Write-Warning "La cartella '$folder' non esiste. Sezione ignorata." + continue + } + + # b. Verifica .env.template + $templatePath = Join-Path $folder $ENV_TEMPLATE_FILENAME + if (Test-Path $templatePath) { + $template = Read-EnvFile $templatePath + + $templateKeys = $template.Keys + $sectionKeys = $section.Keys | Where-Object { $_ -notin $noBrunoKeys } + + if ($templateKeys.Count -ne $sectionKeys.Count -or -not (KeysMatch $templateKeys $sectionKeys)) { + Write-Warning "Il file '$ENV_TEMPLATE_FILENAME' in '$sectionName' non ha le stesse chiavi della sezione." + } + } + + # c/d/e. Gestione file .env + $envPath = Join-Path $folder $ENV_FILENAME + + if (-not (Test-Path $envPath)) { + # c. Genera nuovo file .env + Write-Host "Generazione nuovo file '$ENV_FILENAME' per '$sectionName'." + $newEnv = [ordered]@{} + foreach ($key in $sectionKeys) { + $newEnv[$key] = $section[$key] + } + Write-EnvFile $envPath $newEnv + continue + } + + # d. Verifica chiavi .env esistente + $existingEnv = Read-EnvFile $envPath + + $envKeys = $existingEnv.Keys + $sectionKeys = $section.Keys | Where-Object { $_ -notin $noBrunoKeys } + + if ($envKeys.Count -ne $sectionKeys.Count -or -not (KeysMatch $envKeys $sectionKeys)) { + Write-Warning "Il file '$ENV_FILENAME' in '$sectionName' non ha le stesse chiavi della sezione." + } + + # e. Aggiorna valori + $updatedEnv = [ordered]@{} + + foreach ($key in $sectionKeys) { + $valueFromJson = $section[$key] + + if ($existingEnv.Contains($key)) { + if ($null -ne $valueFromJson) { + # aggiorna + $updatedEnv[$key] = $valueFromJson + } else { + # mantieni + $updatedEnv[$key] = $existingEnv[$key] + } + } else { + # chiave mancante → aggiungi + $updatedEnv[$key] = $valueFromJson + } + } + + Write-Host "Aggiornamento file '$ENV_FILENAME' per '$sectionName'..." + Write-EnvFile $envPath $updatedEnv + Write-Host "File '$(Resolve-Path -LiteralPath $envPath)' aggiornato." +} + +Write-Host "`nOperazione completata." diff --git a/scripts/update-api-environment-files.ps1 b/scripts/update-http-requests-environments.ps1 similarity index 63% rename from scripts/update-api-environment-files.ps1 rename to scripts/update-http-requests-environments.ps1 index 3938e3f..e03834c 100644 --- a/scripts/update-api-environment-files.ps1 +++ b/scripts/update-http-requests-environments.ps1 @@ -1,11 +1,15 @@ # Percorsi file -$envFile = Join-Path $PSScriptRoot ".." "env.json" # JSON originale -$collectionsRoot = Join-Path $PSScriptRoot ".." "collections" # cartella di partenza delle collezioni +$envFile = Join-Path $PSScriptRoot ".." "env.json" # JSON originale +$collectionsRoot = Join-Path $PSScriptRoot ".." "autodocs/httpyac" # cartella di partenza delle collezioni +# Costanti +$API_SECTION_NAME = "API" +$ENV_TEMPLATE_FILENAME = ".env.template" +$ENV_FILENAME = ".env" # 1. Se il file non esiste → errore if (-not (Test-Path $envFile)) { - Write-Error "File env.json non trovato." + Write-Error "File '$ENV_JSON_FILENAME' non trovato." exit 1 } @@ -13,8 +17,8 @@ if (-not (Test-Path $envFile)) { $raw = Get-Content $envFile -Raw $data = $raw | ConvertFrom-Json -AsHashtable -if (-not $data.ContainsKey("API")) { - Write-Error "Il file env.json non contiene la sezione 'API'." +if (-not $data.ContainsKey($API_SECTION_NAME)) { + Write-Error "Il file '$ENV_JSON_FILENAME' non contiene la sezione '$API_SECTION_NAME'." exit 1 } @@ -57,11 +61,11 @@ function KeysMatch($a, $b) { } # 2. Scorri tutte le sezioni sotto API -foreach ($sectionName in $data["API"].Keys) { +foreach ($sectionName in $data[$API_SECTION_NAME].Keys) { Write-Host "`n--- Sezione: $sectionName ---" - $section = $data["API"][$sectionName] + $section = $data[$API_SECTION_NAME][$sectionName] # a. Verifica esistenza cartella $folder = Join-Path $collectionsRoot $sectionName @@ -71,7 +75,7 @@ foreach ($sectionName in $data["API"].Keys) { } # b. Verifica .env.template - $templatePath = Join-Path $folder ".env.template" + $templatePath = Join-Path $folder $ENV_TEMPLATE_FILENAME if (Test-Path $templatePath) { $template = Read-EnvFile $templatePath @@ -79,18 +83,18 @@ foreach ($sectionName in $data["API"].Keys) { $sectionKeys = $section.Keys if ($templateKeys.Count -ne $sectionKeys.Count -or -not (KeysMatch $templateKeys $sectionKeys)) { - Write-Warning "Il file .env.template in '$sectionName' non ha le stesse chiavi della sezione." + Write-Warning "Il file '$ENV_TEMPLATE_FILENAME' in '$sectionName' non ha le stesse chiavi della sezione." } } # c/d/e. Gestione file .env - $envPath = Join-Path $folder ".env" + $envPath = Join-Path $folder $ENV_FILENAME if (-not (Test-Path $envPath)) { # c. Genera nuovo file .env - Write-Host "Generazione nuovo file .env per '$sectionName'." + Write-Host "Generazione nuovo file '$ENV_FILENAME' per '$sectionName'." $newEnv = [ordered]@{} - foreach ($key in $section.Keys) { + foreach ($key in $sectionKeys) { $newEnv[$key] = $section[$key] } Write-EnvFile $envPath $newEnv @@ -104,7 +108,7 @@ foreach ($sectionName in $data["API"].Keys) { $sectionKeys = $section.Keys if ($envKeys.Count -ne $sectionKeys.Count -or -not (KeysMatch $envKeys $sectionKeys)) { - Write-Warning "Il file .env in '$sectionName' non ha le stesse chiavi della sezione." + Write-Warning "Il file '$ENV_FILENAME' in '$sectionName' non ha le stesse chiavi della sezione." } # e. Aggiorna valori @@ -127,8 +131,19 @@ foreach ($sectionName in $data["API"].Keys) { } } - Write-Host "Aggiornamento file .env per '$sectionName'." + # f. Aggiungi chiavi mancanti da .env.template + if (Test-Path $templatePath) { + foreach ($key in $template.Keys) { + if (-not $updatedEnv.Contains($key)) { + Write-Host "Aggiunta chiave mancante '$key' da '$ENV_TEMPLATE_FILENAME'." + $updatedEnv[$key] = $template[$key] + } + } + } + + Write-Host "Aggiornamento file '$ENV_FILENAME' per '$sectionName'..." Write-EnvFile $envPath $updatedEnv + Write-Host "File '$(Resolve-Path -LiteralPath $envPath)' aggiornato." } Write-Host "`nOperazione completata." diff --git a/setup-json-environment.bat b/setup-json-environment.bat new file mode 100644 index 0000000..d505f02 --- /dev/null +++ b/setup-json-environment.bat @@ -0,0 +1,13 @@ +@echo off +echo %cmdcmdline% | findstr /i /c:"%~nx0" >NUL && set iscommandline=1 +echo %PSModulePath% | findstr /i /c:"%USERPROFILE%" >NUL && set ispowershell=1 + +cd /D "%~dp0" + +echo. + +@pwsh -NoProfile -ExecutionPolicy Bypass -Command .\scripts\setup-json-environment.ps1 %* + +echo. + +IF DEFINED iscommandline IF NOT DEFINED ispowershell pause diff --git a/update-bruno-environments.bat b/update-bruno-environments.bat new file mode 100644 index 0000000..e831484 --- /dev/null +++ b/update-bruno-environments.bat @@ -0,0 +1,13 @@ +@echo off +echo %cmdcmdline% | findstr /i /c:"%~nx0" >NUL && set iscommandline=1 +echo %PSModulePath% | findstr /i /c:"%USERPROFILE%" >NUL && set ispowershell=1 + +cd /D "%~dp0" + +echo. + +@pwsh -NoProfile -ExecutionPolicy Bypass -Command .\scripts\update-bruno-environments.ps1 %* + +echo. + +IF DEFINED iscommandline IF NOT DEFINED ispowershell pause diff --git a/update-http-requests-environments.bat b/update-http-requests-environments.bat new file mode 100644 index 0000000..f75f472 --- /dev/null +++ b/update-http-requests-environments.bat @@ -0,0 +1,13 @@ +@echo off +echo %cmdcmdline% | findstr /i /c:"%~nx0" >NUL && set iscommandline=1 +echo %PSModulePath% | findstr /i /c:"%USERPROFILE%" >NUL && set ispowershell=1 + +cd /D "%~dp0" + +echo. + +@pwsh -NoProfile -ExecutionPolicy Bypass -Command .\scripts\update-http-requests-environments.ps1 %* + +echo. + +IF DEFINED iscommandline IF NOT DEFINED ispowershell pause From 044c54ab7b7bb9bdc9f03a25e6474c977446deb9 Mon Sep 17 00:00:00 2001 From: Pier Paolo MAMMI Date: Wed, 22 Jul 2026 12:04:55 +0200 Subject: [PATCH 35/40] move bruno collections in own folder --- .../collections}/ESSE3 Anagrafica API/.env.template | 0 .../allegati/cancellazione allegato al documento di identità.yml | 0 .../allegati/cancellazione allegato al tratto di carriera.yml | 0 .../collections}/ESSE3 Anagrafica API/allegati/folder.yml | 0 .../inserimento metadati allegato dichiarazione handicap.yml | 0 .../allegati/inserimento metadati allegato documento identità.yml | 0 .../allegati/inserimento metadati allegato foto della persona.yml | 0 .../allegati/inserimento metadati allegato matricola.yml | 0 .../allegati/inserimento metadati allegato maturità.yml | 0 .../inserimento metadati allegato relativo ad un autorizzato.yml | 0 ...gato relativo ad un documento d'identità di un autorizzato.yml | 0 ...nserimento metadati allegato titolo universitario italiano.yml | 0 ...serimento metadati allegato titolo universitario straniero.yml | 0 .../recupero metadati allegati dichiarazioni handicap.yml | 0 .../allegati/recupero metadati allegati documento identità.yml | 0 .../allegati/recupero metadati allegati matricola.yml | 0 .../allegati/recupero metadati allegati maturità.yml | 0 .../recupero metadati allegati relativi ad un autorizzato.yml | 0 ...llegati relativi ai documenti d'identità di un autorizzato.yml | 0 .../recupero metadati allegati titoli universitari italiani.yml | 0 .../recupero metadati allegati titoli universitari stranieri.yml | 0 ...Effettua l'aggiornamento dei consensi del soggetto esterno.yml | 0 ...i handicap per cui sono presenti dichiarazioni da valutare.yml | 0 .../anagrafica/Recupera le tipologie di handicap.yml | 0 .../anagrafica/Recupera le tipologie di parentele.yml | 0 .../ESSE3 Anagrafica API/anagrafica/Recupero atenei stranieri.yml | 0 .../ESSE3 Anagrafica API/anagrafica/Recupero atenei.yml | 0 .../anagrafica/Recupero corsi di studio di un ateneo.yml | 0 ...pero delle normative legate alle dichiarazioni di handicap.yml | 0 .../ESSE3 Anagrafica API/anagrafica/Recupero istituti.yml | 0 .../anagrafica/Recupero range voti maturità.yml | 0 .../ESSE3 Anagrafica API/anagrafica/Recupero tipi cotutela.yml | 0 .../anagrafica/Recupero tipi istituto superiore.yml | 0 .../anagrafica/Recupero tipi titoli scuola superiore.yml | 0 .../anagrafica/Recupero tipi titoli stranieri.yml | 0 .../Recupero tipologie di dichiarazione dei titoli stranieri.yml | 0 .../collections}/ESSE3 Anagrafica API/anagrafica/folder.yml | 0 .../collections}/ESSE3 Anagrafica API/autorizzati/folder.yml | 0 .../autorizzati/recupero delle regole di richiesta tutori.yml | 0 .../collections}/ESSE3 Anagrafica API/datiBancari/folder.yml | 0 .../datiBancari/recupero dei dati bancari.yml | 0 ...na dichiarazioni di handicap legata ad un'anagrafica (PUT).yml | 0 ...o di una dichiarazioni di handicap legata ad un'anagrafica.yml | 0 .../Recupera il blob dell'allegato richiesto.yml | 0 ... alla dichiarazione di invalidità di una anagrafica. (PUT).yml | 0 ...sociate alla dichiarazione di invalidità di una anagrafica.yml | 0 .../ESSE3 Anagrafica API/dichiarazioni_invalidità/folder.yml | 0 ... compensative per i bisogni speciali degli studeneti (GET).yml | 0 ...ro delle dichiarazioni di handicap legate ad un'anagrafica.yml | 0 ...o di una dichiarazioni di handicap legata ad un'anagrafica.yml | 0 .../collections}/ESSE3 Anagrafica API/docenti/folder.yml | 0 .../collections}/ESSE3 Anagrafica API/docenti/getDocente.yml | 0 .../collections}/ESSE3 Anagrafica API/dream_apply/folder.yml | 0 ...za del token dreamapply e recupero dell’url di attivazione.yml | 0 .../environments/ESSE3 Anagrafica Pre-Prod #2.yml | 0 .../misure_compensative/Recupero misure compensative.yml | 0 .../ESSE3 Anagrafica API/misure_compensative/folder.yml | 0 .../collections}/ESSE3 Anagrafica API/opencollection.yml | 0 .../persone/Dismette un indirizzo email istituzionale (PATCH).yml | 0 .../persone/Dismette un indirizzo email istituzionale.yml | 0 .../Effettua l'aggiornamento dei consensi dello studente.yml | 0 ...ua l'aggiornamento dell'email istituzionale dello studente.yml | 0 ...fettua l'aggiornamento dell'email personale dello studente.yml | 0 ...l'inserimento dei titoli di studio relativi ad una persona.yml | 0 ...imento dei titoli di studio relativi ad una persona (POST).yml | 0 ...l'inserimento dei titoli di studio relativi ad una persona.yml | 0 .../persone/Recupera i consensi relativi ad uno studente.yml | 0 .../persone/Recupera i titoli relativi ad una persona (GET).yml | 0 .../persone/Recupera i titoli relativi ad una persona.yml | 0 .../persone/Recupero della carriera degli studenti.yml | 0 .../Recupero delle anagrafiche presenti a sistema (GET).yml | 0 .../persone/Recupero delle anagrafiche presenti a sistema.yml | 0 ...ersona presente a sistema ed identificata dal persid (GET).yml | 0 ...gola persona presente a sistema ed identificata dal persid.yml | 0 .../ESSE3 Anagrafica API/persone/aggiornamento cellulare.yml | 0 .../persone/aggiornamento telefono di domicilio.yml | 0 .../persone/aggiornamento telefono di residenza.yml | 0 .../collections}/ESSE3 Anagrafica API/persone/folder.yml | 0 .../collections}/ESSE3 Anagrafica API/persone/getFotoPersona.yml | 0 .../ESSE3 Anagrafica API/persone/getValidaFlgFoto.yml | 0 ...misure compensative per i bisogni speciali degli studeneti.yml | 0 .../recupero degli autorizzati legati ad una anagrafica.yml | 0 .../persone/recupero dei tutori legati ad una anagrafica.yml | 0 .../Elimina i dati di un soggetto esterno in esse3.yml | 0 ...sce oppure aggiorna i dati di un soggetto esterno in esse3.yml | 0 .../Recupera i consensi relativi ad un soggetto esterno.yml | 0 .../soggetti_esterni/Recupero dei soggetti esterni (1).yml | 0 .../soggetti_esterni/Recupero dei soggetti esterni (GET).yml | 0 .../soggetti_esterni/Recupero dei soggetti esterni.yml | 0 .../collections}/ESSE3 Anagrafica API/soggetti_esterni/folder.yml | 0 .../collections}/ESSE3 Common Auth API/.env.template | 0 .../ESSE3 Common Auth API/autenticazione/changeUserPassword.yml | 0 .../ESSE3 Common Auth API/autenticazione/checkLogon.yml | 0 .../ESSE3 Common Auth API/autenticazione/checkSessionId.yml | 0 .../collections}/ESSE3 Common Auth API/autenticazione/folder.yml | 0 .../ESSE3 Common Auth API/autenticazione/getCacheParams.yml | 0 .../ESSE3 Common Auth API/autenticazione/getCurrentSession.yml | 0 .../collections}/ESSE3 Common Auth API/autenticazione/getJWT.yml | 0 .../ESSE3 Common Auth API/autenticazione/getLinguaCod.yml | 0 .../collections}/ESSE3 Common Auth API/autenticazione/login.yml | 0 .../collections}/ESSE3 Common Auth API/autenticazione/logout.yml | 0 .../ESSE3 Common Auth API/autenticazione/setCacheParams.yml | 0 .../ESSE3 Common Auth API/autenticazione/setLinguaCod.yml | 0 .../environments/ESSE3 Common Auth Pre-Prod #2.yml | 0 .../collections}/ESSE3 Common Auth API/jwt/folder.yml | 0 .../collections}/ESSE3 Common Auth API/jwt/getJWK.yml | 0 .../collections}/ESSE3 Common Auth API/jwt/refreshJWT.yml | 0 .../collections}/ESSE3 Common Auth API/opencollection.yml | 0 .../collections}/Gov.it OpenData/Get Organization Content.yml | 0 .../collections}/Gov.it OpenData/Get Organization List.yml | 0 .../collections}/Gov.it OpenData/Get Package Content.yml | 0 .../Gov.it OpenData/Get Package List with Resources.yml | 0 .../collections}/Gov.it OpenData/Get Package List.yml | 0 .../collections}/Gov.it OpenData/opencollection.yml | 0 {collections => bruno/collections}/IDEM WebServices/.env.template | 0 .../IDEM WebServices/Anagrafiche/Autorizzatori Centri.yml | 0 .../IDEM WebServices/Anagrafiche/Autorizzatori Struttura.yml | 0 .../collections}/IDEM WebServices/Anagrafiche/Autorizzatori.yml | 0 .../IDEM WebServices/Anagrafiche/Dipendente (Codice fiscale).yml | 0 .../IDEM WebServices/Anagrafiche/Dipendente (E-mail).yml | 0 .../IDEM WebServices/Anagrafiche/Dipendente by Codice Fiscale.yml | 0 .../IDEM WebServices/Anagrafiche/Dipendente by E-mail.yml | 0 .../IDEM WebServices/Anagrafiche/Strutture Centri.yml | 0 .../IDEM WebServices/Anagrafiche/Strutture apicali.yml | 0 .../IDEM WebServices/Anagrafiche/Studente (Codice Fiscale).yml | 0 .../IDEM WebServices/Anagrafiche/Studente (E-mail).yml | 0 .../Anagrafiche/Studente Carriere Dropdown (CF).yml | 0 .../collections}/IDEM WebServices/Anagrafiche/folder.yml | 0 .../IDEM WebServices/Contratti/Contratti (IRIS GW).yml | 0 .../IDEM WebServices/Contratti/Contratti Eseguiti (IRIS GW).yml | 0 .../IDEM WebServices/Contratti/Contratto (IRIS GW).yml | 0 .../IDEM WebServices/Contratti/Contratto Esteso (IRIS GW).yml | 0 .../collections}/IDEM WebServices/Contratti/folder.yml | 0 .../IDEM WebServices/IDEM WebServices-documentation.html | 0 .../collections}/IDEM WebServices/Obiettivi performance.yml | 0 .../IDEM WebServices/Progetti/Progetti contabilizzati in PJ.yml | 0 .../collections}/IDEM WebServices/Progetti/folder.yml | 0 .../collections}/IDEM WebServices/environments/Produzione.yml | 0 .../collections}/IDEM WebServices/environments/Test.yml | 0 .../collections}/IDEM WebServices/opencollection.yml | 0 .../collections}/IRIS GW (Gateway) REST API (v1)/.env.template | 0 .../Contracts/Get Contracts FULL.yml | 0 .../Contracts/Get Contracts by Department IdAb.yml | 0 .../IRIS GW (Gateway) REST API (v1)/Contracts/Get Contracts.yml | 0 .../SCRIPT - Get Contracts with two or more contributors.yml | 0 .../Contracts/SCRIPT - Get Contracts with two or more owners.yml | 0 .../IRIS GW (Gateway) REST API (v1)/Contracts/folder.yml | 0 .../IRIS GW (Gateway) REST API (v1)/WfItems/Get ASNs Copy.yml | 0 .../IRIS GW (Gateway) REST API (v1)/WfItems/Get ASNs.yml | 0 .../WfItems/Get Academic Fields 2024.yml | 0 .../IRIS GW (Gateway) REST API (v1)/WfItems/Get Items Copy.yml | 0 .../IRIS GW (Gateway) REST API (v1)/WfItems/Get Items.yml | 0 .../IRIS GW (Gateway) REST API (v1)/WfItems/folder.yml | 0 .../[Runner] Get All Contracts/[Runner] Get All Contracts.yml | 0 .../[Runner] Get All Contracts/folder.yml | 0 .../IRIS GW (Gateway) REST API (v1)/environments/IRIS - Prod.yml | 0 .../IRIS GW (Gateway) REST API (v1)/opencollection.yml | 0 .../Comuni (con dimensione) - Elenco.yml | 0 .../Comuni (con territorio) - Elenco.yml | 0 .../ORDS generated API for publish/Province - Elenco.yml | 0 .../ORDS generated API for publish/Regioni - Elenco.yml | 0 .../Retrieve a record from publish.yml | 0 .../anagrafica_report_metadato_web/folder.yml | 0 .../ORDS generated API for publish/environments/ORDS.yml | 0 .../ORDS generated API for publish/opencollection.yml | 0 .../reportspooljson/Retrieve a record from publish.yml | 0 .../ORDS generated API for publish/reportspooljson/folder.yml | 0 .../reportspooljsoncount/Retrieve a record from publish.yml | 0 .../reportspooljsoncount/folder.yml | 0 .../Power Automate/Get Requests by Tag, Status and SWF.yml | 0 .../collections}/Power Automate/Get eF request exportTags.yml | 0 .../collections}/Power Automate/Get eF requests.yml | 0 .../collections}/Power Automate/Power Query/Get Comune.yml | 0 .../collections}/Power Automate/Power Query/SignIn.yml | 0 .../collections}/Power Automate/Power Query/folder.yml | 0 .../collections}/Power Automate/opencollection.yml | 0 {collections => bruno/collections}/Scopus/.env.template | 0 {collections => bruno/collections}/Scopus/Get Citations.yml | 0 .../collections}/Scopus/environments/Scopus - Prod.yml | 0 {collections => bruno/collections}/Scopus/opencollection.yml | 0 .../collections}/SharePoint API/opencollection.yml | 0 {collections => bruno/collections}/elixForms API v2/.env.template | 0 .../collections}/elixForms API v2/Authorization/Login.yml | 0 .../collections}/elixForms API v2/Authorization/Logout.yml | 0 .../collections}/elixForms API v2/Authorization/folder.yml | 0 .../elixForms API v2/Calendar 2.0/Get appointments.yml | 0 .../elixForms API v2/Calendar 2.0/Set acquired appointments.yml | 0 .../collections}/elixForms API v2/Calendar 2.0/folder.yml | 0 .../Acquisizione istanze elaborate da processo esterno.yml | 0 .../Cambio stato e-o integrazione/Clone Request.yml | 0 .../Cambio stato e-o integrazione/Reopen Request (OLD).yml | 0 .../Cambio stato e-o integrazione/Reopen Request.yml | 0 .../Cambio stato e-o integrazione/Set Request Status (OLD).yml | 0 .../Set Request Status- Register result (OLD).yml | 0 .../Cambio stato e-o integrazione/Set Request Status.yml | 0 .../Cambio stato e-o integrazione/Update Request SWF values.yml | 0 .../elixForms API v2/Cambio stato e-o integrazione/folder.yml | 0 .../Comunicazioni formali/Invio comunicazione formale.yml | 0 .../elixForms API v2/Comunicazioni formali/folder.yml | 0 .../Proposta CCT determina contratti conto terzi NO EFTL.yml | 0 .../Proposta CCT determina contratti conto terzi.yml | 0 .../Proposta CCT determina ex art 15 NO EFTL.yml | 0 .../Proposta CCT determina ex art 15.yml | 0 .../Proposta CCT determina sperimentazioni cliniche NO EFTL.yml | 0 .../Proposta CCT determina sperimentazioni cliniche.yml | 0 .../CCT - Determina da Proposta/Punto A regolamento.yml | 0 .../CCT - Determina da Proposta/Punto B regolamento.yml | 0 .../EFTL processing/CCT - Determina da Proposta/folder.yml | 0 .../CCT - Liquidazione Compensi/DSAN/Anno corrente.yml | 0 .../DSAN/Elenco Contraenti in formato CSV DSAN.yml | 0 .../DSAN/Elenco RS in formato CSV DSAN.yml | 0 .../DSAN/Inserimento Ore Dentro - Calcolo importo equivalente.yml | 0 .../DSAN/Inserimento Ore Dentro - Dati attività CSV.yml | 0 .../DSAN/Inserimento Ore Fuori - Calcolo importo equivalente.yml | 0 .../DSAN/Inserimento Ore Fuori - Dati attività CSV copy.yml | 0 .../DSAN/Limiti - Calcolo MIN ore dentro orario.yml | 0 .../DSAN/Limiti - Calcolo MIN ore fuori orario.yml | 0 .../DSAN/Limiti - Indicazione MAX annuale ore dentro orario.yml | 0 .../DSAN/Limiti - Indicazione MAX annuale ore fuori orario.yml | 0 .../DSAN/Richiedente - Calcolo ore equivalenti.yml | 0 .../DSAN/Richiedente - Check ammesso compilazione.yml | 0 .../DSAN/Richiedente - Check ruolo per compilazione.yml | 0 .../DSAN/Richiedente - Importo ripartizione da Proposta.yml | 0 .../EFTL processing/CCT - Liquidazione Compensi/DSAN/folder.yml | 0 .../Proposta/Campi conferma - Codice struttura assegnazione.yml | 0 .../Proposta/Campi conferma - Codice struttura protocollo.yml | 0 .../Proposta/Check Richiedente IN Responsabili Scientifici.yml | 0 .../Proposta/Codici fiscali ripartizioni.yml | 0 .../Proposta/Elenco Contraenti in formato CSV.yml | 0 .../Proposta/Elenco Partecipanti - Array CF altri.yml | 0 .../Proposta/Elenco Partecipanti - Array CF docenti.yml | 0 .../Proposta/Elenco Partecipanti - Dropdown con chiave.yml | 0 .../Proposta/Elenco RS in formato CSV.yml | 0 .../Proposta/Nominativo completo RS proponente.yml | 0 .../Proposta/Notifiche email partecipanti - Body.yml | 0 .../Proposta/Notifiche email partecipanti - Subject.yml | 0 .../Proposta/Partecipanti - Body NO fancy HTML.yml | 0 .../CCT - Liquidazione Compensi/Proposta/Partecipanti - Body.yml | 0 .../Proposta/Partecipanti - CF per verifica DSAN.yml | 0 .../CCT - Liquidazione Compensi/Proposta/Partecipanti - Email.yml | 0 .../Proposta/Partecipanti - Importo PTA.yml | 0 .../Proposta/Partecipanti - Importo docente.yml | 0 .../Proposta/Partecipanti - Riga dati completi ripartizione.yml | 0 .../Proposta/Partecipanti - Subject.yml | 0 .../Proposta/Partecipanti - hasDSAN.yml | 0 .../Proposta/Recupero importo richiedente da proposta.yml | 0 .../Proposta/Ripartizioni - Count da form partecipante.yml | 0 .../Proposta/Tabella HTML ripartizioni FOR ADVANCED.yml | 0 .../Proposta/Tabella HTML ripartizioni FOR.yml | 0 .../Proposta/Tabella HTML ripartizioni WHILE.yml | 0 .../Proposta/elixPro - Recupero importi inseriti.yml | 0 .../Proposta/elixPro - Template Delibera ONLYTABLE.yml | 0 .../Proposta/elixPro - Template Delibera.yml | 0 .../CCT - Liquidazione Compensi/Proposta/folder.yml | 0 .../EFTL processing/CCT - Liquidazione Compensi/folder.yml | 0 .../CCT - Proposta Operatore/Calcolo D.1.3 5% con virgole.yml | 0 .../CCT - Proposta Operatore/Calcolo D.1.3 con virgole.yml | 0 .../Codice Contratto con caratteri strani.yml | 0 .../CCT - Proposta Operatore/Contratto IS economico.yml | 0 .../Elenco Contraenti CSV (nominativo).yml | 0 .../CCT - Proposta Operatore/Elenco RS CSV (cognome nome).yml | 0 .../CCT - Proposta Operatore/Elenco contraenti formattati.yml | 0 .../Fascicolo e documento - Nuovo formato.yml | 0 .../CCT - Proposta Operatore/Fascicolo e documento su Titulus.yml | 0 .../CCT - Proposta Operatore/Messaggio ritenute massime.yml | 0 .../EFTL processing/CCT - Proposta Operatore/folder.yml | 0 .../Gestione Istanze - Elenco carriere inserite.yml | 0 .../Notifiche email - Elenco carriere e certificati.yml | 0 .../EFTL processing/MOD A13 Richiesta Certificato/folder.yml | 0 .../elixForms API v2/EFTL processing/Process EFTL.yml | 0 .../elixForms API v2/EFTL processing/Test vari/Create JSON.yml | 0 .../Test vari/TAG per protocollazione fra uffici.yml | 0 .../Test vari/TAG per riprotocollazione (integrazione).yml | 0 .../EFTL processing/Test vari/TEST ordine GetValueByTag.yml | 0 .../EFTL processing/Test vari/Test Errore 406.yml | 0 .../elixForms API v2/EFTL processing/Test vari/Test vari.yml | 0 .../elixForms API v2/EFTL processing/Test vari/folder.yml | 0 .../collections}/elixForms API v2/EFTL processing/folder.yml | 0 .../elixForms API v2/Request details/Get ExportTags.yml | 0 .../elixForms API v2/Request details/Get Request Attachment.yml | 0 .../elixForms API v2/Request details/Get Request Identifier.yml | 0 .../elixForms API v2/Request details/Get Request by QRCode.yml | 0 .../collections}/elixForms API v2/Request details/Get Request.yml | 0 .../collections}/elixForms API v2/Request details/folder.yml | 0 .../elixForms API v2/Requests lookup/Lookup By Period.yml | 0 .../elixForms API v2/Requests lookup/Lookup By Status.yml | 0 .../Requests lookup/Lookup By User and Period.yml | 0 .../elixForms API v2/Requests lookup/Lookup By User.yml | 0 .../Requests lookup/Obsolete/Lookup By Status (OLD).yml | 0 .../Requests lookup/Obsolete/Lookup By Status.yml | 0 .../Requests lookup/Obsolete/Lookup By User and Period (OLD).yml | 0 .../Requests lookup/Obsolete/Lookup By User only (-) (OLD).yml | 0 .../elixForms API v2/Requests lookup/Obsolete/folder.yml | 0 .../collections}/elixForms API v2/Requests lookup/folder.yml | 0 .../Get request details.yml | 0 .../Login once.yml | 0 .../Lookup requests.yml | 0 .../Runner- Get all requests by ModuleTag and status/folder.yml | 0 .../elixForms API v2/Set Request Status- Incomplete.yml | 0 .../collections}/elixForms API v2/Test Remote WS.yml | 0 .../collections}/elixForms API v2/User info/Get User Info.yml | 0 .../collections}/elixForms API v2/User info/folder.yml | 0 .../collections}/elixForms API v2/_HACKS/Export Module.yml | 0 .../collections}/elixForms API v2/_HACKS/folder.yml | 0 .../collections}/elixForms API v2/_Untested/Creazione JWT.yml | 0 .../elixForms API v2/_Untested/SSO Receipt Insert.yml | 0 .../elixForms API v2/_Untested/SSO Receipt by User.yml | 0 .../collections}/elixForms API v2/_Untested/folder.yml | 0 .../collections}/elixForms API v2/elixFormsJs.js | 0 .../elixForms API v2/environments/elixForms - Prod.yml | 0 .../collections}/elixForms API v2/opencollection.yml | 0 {environments => bruno/environments}/UniPR.yml | 0 workspace.yml => bruno/workspace.yml | 0 313 files changed, 0 insertions(+), 0 deletions(-) rename {collections => bruno/collections}/ESSE3 Anagrafica API/.env.template (100%) rename {collections => bruno/collections}/ESSE3 Anagrafica API/allegati/cancellazione allegato al documento di identità.yml (100%) rename {collections => bruno/collections}/ESSE3 Anagrafica API/allegati/cancellazione allegato al tratto di carriera.yml (100%) rename {collections => bruno/collections}/ESSE3 Anagrafica API/allegati/folder.yml (100%) rename {collections => bruno/collections}/ESSE3 Anagrafica API/allegati/inserimento metadati allegato dichiarazione handicap.yml (100%) rename {collections => bruno/collections}/ESSE3 Anagrafica API/allegati/inserimento metadati allegato documento identità.yml (100%) rename {collections => bruno/collections}/ESSE3 Anagrafica API/allegati/inserimento metadati allegato foto della persona.yml (100%) rename {collections => bruno/collections}/ESSE3 Anagrafica API/allegati/inserimento metadati allegato matricola.yml (100%) rename {collections => bruno/collections}/ESSE3 Anagrafica API/allegati/inserimento metadati allegato maturità.yml (100%) rename {collections => bruno/collections}/ESSE3 Anagrafica API/allegati/inserimento metadati allegato relativo ad un autorizzato.yml (100%) rename {collections => bruno/collections}/ESSE3 Anagrafica API/allegati/inserimento metadati allegato relativo ad un documento d'identità di un autorizzato.yml (100%) rename {collections => bruno/collections}/ESSE3 Anagrafica API/allegati/inserimento metadati allegato titolo universitario italiano.yml (100%) rename {collections => bruno/collections}/ESSE3 Anagrafica API/allegati/inserimento metadati allegato titolo universitario straniero.yml (100%) rename {collections => bruno/collections}/ESSE3 Anagrafica API/allegati/recupero metadati allegati dichiarazioni handicap.yml (100%) rename {collections => bruno/collections}/ESSE3 Anagrafica API/allegati/recupero metadati allegati documento identità.yml (100%) rename {collections => bruno/collections}/ESSE3 Anagrafica API/allegati/recupero metadati allegati matricola.yml (100%) rename {collections => bruno/collections}/ESSE3 Anagrafica API/allegati/recupero metadati allegati maturità.yml (100%) rename {collections => bruno/collections}/ESSE3 Anagrafica API/allegati/recupero metadati allegati relativi ad un autorizzato.yml (100%) rename {collections => bruno/collections}/ESSE3 Anagrafica API/allegati/recupero metadati allegati relativi ai documenti d'identità di un autorizzato.yml (100%) rename {collections => bruno/collections}/ESSE3 Anagrafica API/allegati/recupero metadati allegati titoli universitari italiani.yml (100%) rename {collections => bruno/collections}/ESSE3 Anagrafica API/allegati/recupero metadati allegati titoli universitari stranieri.yml (100%) rename {collections => bruno/collections}/ESSE3 Anagrafica API/anagrafica/Effettua l'aggiornamento dei consensi del soggetto esterno.yml (100%) rename {collections => bruno/collections}/ESSE3 Anagrafica API/anagrafica/Recupera le tipologie di handicap per cui sono presenti dichiarazioni da valutare.yml (100%) rename {collections => bruno/collections}/ESSE3 Anagrafica API/anagrafica/Recupera le tipologie di handicap.yml (100%) rename {collections => bruno/collections}/ESSE3 Anagrafica API/anagrafica/Recupera le tipologie di parentele.yml (100%) rename {collections => bruno/collections}/ESSE3 Anagrafica API/anagrafica/Recupero atenei stranieri.yml (100%) rename {collections => bruno/collections}/ESSE3 Anagrafica API/anagrafica/Recupero atenei.yml (100%) rename {collections => bruno/collections}/ESSE3 Anagrafica API/anagrafica/Recupero corsi di studio di un ateneo.yml (100%) rename {collections => bruno/collections}/ESSE3 Anagrafica API/anagrafica/Recupero delle normative legate alle dichiarazioni di handicap.yml (100%) rename {collections => bruno/collections}/ESSE3 Anagrafica API/anagrafica/Recupero istituti.yml (100%) rename {collections => bruno/collections}/ESSE3 Anagrafica API/anagrafica/Recupero range voti maturità.yml (100%) rename {collections => bruno/collections}/ESSE3 Anagrafica API/anagrafica/Recupero tipi cotutela.yml (100%) rename {collections => bruno/collections}/ESSE3 Anagrafica API/anagrafica/Recupero tipi istituto superiore.yml (100%) rename {collections => bruno/collections}/ESSE3 Anagrafica API/anagrafica/Recupero tipi titoli scuola superiore.yml (100%) rename {collections => bruno/collections}/ESSE3 Anagrafica API/anagrafica/Recupero tipi titoli stranieri.yml (100%) rename {collections => bruno/collections}/ESSE3 Anagrafica API/anagrafica/Recupero tipologie di dichiarazione dei titoli stranieri.yml (100%) rename {collections => bruno/collections}/ESSE3 Anagrafica API/anagrafica/folder.yml (100%) rename {collections => bruno/collections}/ESSE3 Anagrafica API/autorizzati/folder.yml (100%) rename {collections => bruno/collections}/ESSE3 Anagrafica API/autorizzati/recupero delle regole di richiesta tutori.yml (100%) rename {collections => bruno/collections}/ESSE3 Anagrafica API/datiBancari/folder.yml (100%) rename {collections => bruno/collections}/ESSE3 Anagrafica API/datiBancari/recupero dei dati bancari.yml (100%) rename {collections => bruno/collections}/ESSE3 Anagrafica API/dichiarazioni_invalidità/Aggiornamento di una dichiarazioni di handicap legata ad un'anagrafica (PUT).yml (100%) rename {collections => bruno/collections}/ESSE3 Anagrafica API/dichiarazioni_invalidità/Aggiornamento di una dichiarazioni di handicap legata ad un'anagrafica.yml (100%) rename {collections => bruno/collections}/ESSE3 Anagrafica API/dichiarazioni_invalidità/Recupera il blob dell'allegato richiesto.yml (100%) rename {collections => bruno/collections}/ESSE3 Anagrafica API/dichiarazioni_invalidità/effettua l'aggiornamento dei dettagli di una misura compensative associate alla dichiarazione di invalidità di una anagrafica. (PUT).yml (100%) rename {collections => bruno/collections}/ESSE3 Anagrafica API/dichiarazioni_invalidità/effettua l'aggiornamento dei dettagli di una misura compensative associate alla dichiarazione di invalidità di una anagrafica.yml (100%) rename {collections => bruno/collections}/ESSE3 Anagrafica API/dichiarazioni_invalidità/folder.yml (100%) rename {collections => bruno/collections}/ESSE3 Anagrafica API/dichiarazioni_invalidità/misure compensative per i bisogni speciali degli studeneti (GET).yml (100%) rename {collections => bruno/collections}/ESSE3 Anagrafica API/dichiarazioni_invalidità/recupero delle dichiarazioni di handicap legate ad un'anagrafica.yml (100%) rename {collections => bruno/collections}/ESSE3 Anagrafica API/dichiarazioni_invalidità/recupero di una dichiarazioni di handicap legata ad un'anagrafica.yml (100%) rename {collections => bruno/collections}/ESSE3 Anagrafica API/docenti/folder.yml (100%) rename {collections => bruno/collections}/ESSE3 Anagrafica API/docenti/getDocente.yml (100%) rename {collections => bruno/collections}/ESSE3 Anagrafica API/dream_apply/folder.yml (100%) rename {collections => bruno/collections}/ESSE3 Anagrafica API/dream_apply/refresh della data di scadenza del token dreamapply e recupero dell’url di attivazione.yml (100%) rename {collections => bruno/collections}/ESSE3 Anagrafica API/environments/ESSE3 Anagrafica Pre-Prod #2.yml (100%) rename {collections => bruno/collections}/ESSE3 Anagrafica API/misure_compensative/Recupero misure compensative.yml (100%) rename {collections => bruno/collections}/ESSE3 Anagrafica API/misure_compensative/folder.yml (100%) rename {collections => bruno/collections}/ESSE3 Anagrafica API/opencollection.yml (100%) rename {collections => bruno/collections}/ESSE3 Anagrafica API/persone/Dismette un indirizzo email istituzionale (PATCH).yml (100%) rename {collections => bruno/collections}/ESSE3 Anagrafica API/persone/Dismette un indirizzo email istituzionale.yml (100%) rename {collections => bruno/collections}/ESSE3 Anagrafica API/persone/Effettua l'aggiornamento dei consensi dello studente.yml (100%) rename {collections => bruno/collections}/ESSE3 Anagrafica API/persone/Effettua l'aggiornamento dell'email istituzionale dello studente.yml (100%) rename {collections => bruno/collections}/ESSE3 Anagrafica API/persone/Effettua l'aggiornamento dell'email personale dello studente.yml (100%) rename {collections => bruno/collections}/ESSE3 Anagrafica API/persone/Effettua l'aggiornamento o l'inserimento dei titoli di studio relativi ad una persona.yml (100%) rename {collections => bruno/collections}/ESSE3 Anagrafica API/persone/Effettua l'inserimento dei titoli di studio relativi ad una persona (POST).yml (100%) rename {collections => bruno/collections}/ESSE3 Anagrafica API/persone/Effettua l'inserimento dei titoli di studio relativi ad una persona.yml (100%) rename {collections => bruno/collections}/ESSE3 Anagrafica API/persone/Recupera i consensi relativi ad uno studente.yml (100%) rename {collections => bruno/collections}/ESSE3 Anagrafica API/persone/Recupera i titoli relativi ad una persona (GET).yml (100%) rename {collections => bruno/collections}/ESSE3 Anagrafica API/persone/Recupera i titoli relativi ad una persona.yml (100%) rename {collections => bruno/collections}/ESSE3 Anagrafica API/persone/Recupero della carriera degli studenti.yml (100%) rename {collections => bruno/collections}/ESSE3 Anagrafica API/persone/Recupero delle anagrafiche presenti a sistema (GET).yml (100%) rename {collections => bruno/collections}/ESSE3 Anagrafica API/persone/Recupero delle anagrafiche presenti a sistema.yml (100%) rename {collections => bruno/collections}/ESSE3 Anagrafica API/persone/Recupero delle informazioni relative ad una singola persona presente a sistema ed identificata dal persid (GET).yml (100%) rename {collections => bruno/collections}/ESSE3 Anagrafica API/persone/Recupero delle informazioni relative ad una singola persona presente a sistema ed identificata dal persid.yml (100%) rename {collections => bruno/collections}/ESSE3 Anagrafica API/persone/aggiornamento cellulare.yml (100%) rename {collections => bruno/collections}/ESSE3 Anagrafica API/persone/aggiornamento telefono di domicilio.yml (100%) rename {collections => bruno/collections}/ESSE3 Anagrafica API/persone/aggiornamento telefono di residenza.yml (100%) rename {collections => bruno/collections}/ESSE3 Anagrafica API/persone/folder.yml (100%) rename {collections => bruno/collections}/ESSE3 Anagrafica API/persone/getFotoPersona.yml (100%) rename {collections => bruno/collections}/ESSE3 Anagrafica API/persone/getValidaFlgFoto.yml (100%) rename {collections => bruno/collections}/ESSE3 Anagrafica API/persone/misure compensative per i bisogni speciali degli studeneti.yml (100%) rename {collections => bruno/collections}/ESSE3 Anagrafica API/persone/recupero degli autorizzati legati ad una anagrafica.yml (100%) rename {collections => bruno/collections}/ESSE3 Anagrafica API/persone/recupero dei tutori legati ad una anagrafica.yml (100%) rename {collections => bruno/collections}/ESSE3 Anagrafica API/soggetti_esterni/Elimina i dati di un soggetto esterno in esse3.yml (100%) rename {collections => bruno/collections}/ESSE3 Anagrafica API/soggetti_esterni/Inserisce oppure aggiorna i dati di un soggetto esterno in esse3.yml (100%) rename {collections => bruno/collections}/ESSE3 Anagrafica API/soggetti_esterni/Recupera i consensi relativi ad un soggetto esterno.yml (100%) rename {collections => bruno/collections}/ESSE3 Anagrafica API/soggetti_esterni/Recupero dei soggetti esterni (1).yml (100%) rename {collections => bruno/collections}/ESSE3 Anagrafica API/soggetti_esterni/Recupero dei soggetti esterni (GET).yml (100%) rename {collections => bruno/collections}/ESSE3 Anagrafica API/soggetti_esterni/Recupero dei soggetti esterni.yml (100%) rename {collections => bruno/collections}/ESSE3 Anagrafica API/soggetti_esterni/folder.yml (100%) rename {collections => bruno/collections}/ESSE3 Common Auth API/.env.template (100%) rename {collections => bruno/collections}/ESSE3 Common Auth API/autenticazione/changeUserPassword.yml (100%) rename {collections => bruno/collections}/ESSE3 Common Auth API/autenticazione/checkLogon.yml (100%) rename {collections => bruno/collections}/ESSE3 Common Auth API/autenticazione/checkSessionId.yml (100%) rename {collections => bruno/collections}/ESSE3 Common Auth API/autenticazione/folder.yml (100%) rename {collections => bruno/collections}/ESSE3 Common Auth API/autenticazione/getCacheParams.yml (100%) rename {collections => bruno/collections}/ESSE3 Common Auth API/autenticazione/getCurrentSession.yml (100%) rename {collections => bruno/collections}/ESSE3 Common Auth API/autenticazione/getJWT.yml (100%) rename {collections => bruno/collections}/ESSE3 Common Auth API/autenticazione/getLinguaCod.yml (100%) rename {collections => bruno/collections}/ESSE3 Common Auth API/autenticazione/login.yml (100%) rename {collections => bruno/collections}/ESSE3 Common Auth API/autenticazione/logout.yml (100%) rename {collections => bruno/collections}/ESSE3 Common Auth API/autenticazione/setCacheParams.yml (100%) rename {collections => bruno/collections}/ESSE3 Common Auth API/autenticazione/setLinguaCod.yml (100%) rename {collections => bruno/collections}/ESSE3 Common Auth API/environments/ESSE3 Common Auth Pre-Prod #2.yml (100%) rename {collections => bruno/collections}/ESSE3 Common Auth API/jwt/folder.yml (100%) rename {collections => bruno/collections}/ESSE3 Common Auth API/jwt/getJWK.yml (100%) rename {collections => bruno/collections}/ESSE3 Common Auth API/jwt/refreshJWT.yml (100%) rename {collections => bruno/collections}/ESSE3 Common Auth API/opencollection.yml (100%) rename {collections => bruno/collections}/Gov.it OpenData/Get Organization Content.yml (100%) rename {collections => bruno/collections}/Gov.it OpenData/Get Organization List.yml (100%) rename {collections => bruno/collections}/Gov.it OpenData/Get Package Content.yml (100%) rename {collections => bruno/collections}/Gov.it OpenData/Get Package List with Resources.yml (100%) rename {collections => bruno/collections}/Gov.it OpenData/Get Package List.yml (100%) rename {collections => bruno/collections}/Gov.it OpenData/opencollection.yml (100%) rename {collections => bruno/collections}/IDEM WebServices/.env.template (100%) rename {collections => bruno/collections}/IDEM WebServices/Anagrafiche/Autorizzatori Centri.yml (100%) rename {collections => bruno/collections}/IDEM WebServices/Anagrafiche/Autorizzatori Struttura.yml (100%) rename {collections => bruno/collections}/IDEM WebServices/Anagrafiche/Autorizzatori.yml (100%) rename {collections => bruno/collections}/IDEM WebServices/Anagrafiche/Dipendente (Codice fiscale).yml (100%) rename {collections => bruno/collections}/IDEM WebServices/Anagrafiche/Dipendente (E-mail).yml (100%) rename {collections => bruno/collections}/IDEM WebServices/Anagrafiche/Dipendente by Codice Fiscale.yml (100%) rename {collections => bruno/collections}/IDEM WebServices/Anagrafiche/Dipendente by E-mail.yml (100%) rename {collections => bruno/collections}/IDEM WebServices/Anagrafiche/Strutture Centri.yml (100%) rename {collections => bruno/collections}/IDEM WebServices/Anagrafiche/Strutture apicali.yml (100%) rename {collections => bruno/collections}/IDEM WebServices/Anagrafiche/Studente (Codice Fiscale).yml (100%) rename {collections => bruno/collections}/IDEM WebServices/Anagrafiche/Studente (E-mail).yml (100%) rename {collections => bruno/collections}/IDEM WebServices/Anagrafiche/Studente Carriere Dropdown (CF).yml (100%) rename {collections => bruno/collections}/IDEM WebServices/Anagrafiche/folder.yml (100%) rename {collections => bruno/collections}/IDEM WebServices/Contratti/Contratti (IRIS GW).yml (100%) rename {collections => bruno/collections}/IDEM WebServices/Contratti/Contratti Eseguiti (IRIS GW).yml (100%) rename {collections => bruno/collections}/IDEM WebServices/Contratti/Contratto (IRIS GW).yml (100%) rename {collections => bruno/collections}/IDEM WebServices/Contratti/Contratto Esteso (IRIS GW).yml (100%) rename {collections => bruno/collections}/IDEM WebServices/Contratti/folder.yml (100%) rename {collections => bruno/collections}/IDEM WebServices/IDEM WebServices-documentation.html (100%) rename {collections => bruno/collections}/IDEM WebServices/Obiettivi performance.yml (100%) rename {collections => bruno/collections}/IDEM WebServices/Progetti/Progetti contabilizzati in PJ.yml (100%) rename {collections => bruno/collections}/IDEM WebServices/Progetti/folder.yml (100%) rename {collections => bruno/collections}/IDEM WebServices/environments/Produzione.yml (100%) rename {collections => bruno/collections}/IDEM WebServices/environments/Test.yml (100%) rename {collections => bruno/collections}/IDEM WebServices/opencollection.yml (100%) rename {collections => bruno/collections}/IRIS GW (Gateway) REST API (v1)/.env.template (100%) rename {collections => bruno/collections}/IRIS GW (Gateway) REST API (v1)/Contracts/Get Contracts FULL.yml (100%) rename {collections => bruno/collections}/IRIS GW (Gateway) REST API (v1)/Contracts/Get Contracts by Department IdAb.yml (100%) rename {collections => bruno/collections}/IRIS GW (Gateway) REST API (v1)/Contracts/Get Contracts.yml (100%) rename {collections => bruno/collections}/IRIS GW (Gateway) REST API (v1)/Contracts/SCRIPT - Get Contracts with two or more contributors.yml (100%) rename {collections => bruno/collections}/IRIS GW (Gateway) REST API (v1)/Contracts/SCRIPT - Get Contracts with two or more owners.yml (100%) rename {collections => bruno/collections}/IRIS GW (Gateway) REST API (v1)/Contracts/folder.yml (100%) rename {collections => bruno/collections}/IRIS GW (Gateway) REST API (v1)/WfItems/Get ASNs Copy.yml (100%) rename {collections => bruno/collections}/IRIS GW (Gateway) REST API (v1)/WfItems/Get ASNs.yml (100%) rename {collections => bruno/collections}/IRIS GW (Gateway) REST API (v1)/WfItems/Get Academic Fields 2024.yml (100%) rename {collections => bruno/collections}/IRIS GW (Gateway) REST API (v1)/WfItems/Get Items Copy.yml (100%) rename {collections => bruno/collections}/IRIS GW (Gateway) REST API (v1)/WfItems/Get Items.yml (100%) rename {collections => bruno/collections}/IRIS GW (Gateway) REST API (v1)/WfItems/folder.yml (100%) rename {collections => bruno/collections}/IRIS GW (Gateway) REST API (v1)/[Runner] Get All Contracts/[Runner] Get All Contracts.yml (100%) rename {collections => bruno/collections}/IRIS GW (Gateway) REST API (v1)/[Runner] Get All Contracts/folder.yml (100%) rename {collections => bruno/collections}/IRIS GW (Gateway) REST API (v1)/environments/IRIS - Prod.yml (100%) rename {collections => bruno/collections}/IRIS GW (Gateway) REST API (v1)/opencollection.yml (100%) rename {collections => bruno/collections}/ORDS generated API for publish/Comuni (con dimensione) - Elenco.yml (100%) rename {collections => bruno/collections}/ORDS generated API for publish/Comuni (con territorio) - Elenco.yml (100%) rename {collections => bruno/collections}/ORDS generated API for publish/Province - Elenco.yml (100%) rename {collections => bruno/collections}/ORDS generated API for publish/Regioni - Elenco.yml (100%) rename {collections => bruno/collections}/ORDS generated API for publish/anagrafica_report_metadato_web/Retrieve a record from publish.yml (100%) rename {collections => bruno/collections}/ORDS generated API for publish/anagrafica_report_metadato_web/folder.yml (100%) rename {collections => bruno/collections}/ORDS generated API for publish/environments/ORDS.yml (100%) rename {collections => bruno/collections}/ORDS generated API for publish/opencollection.yml (100%) rename {collections => bruno/collections}/ORDS generated API for publish/reportspooljson/Retrieve a record from publish.yml (100%) rename {collections => bruno/collections}/ORDS generated API for publish/reportspooljson/folder.yml (100%) rename {collections => bruno/collections}/ORDS generated API for publish/reportspooljsoncount/Retrieve a record from publish.yml (100%) rename {collections => bruno/collections}/ORDS generated API for publish/reportspooljsoncount/folder.yml (100%) rename {collections => bruno/collections}/Power Automate/Get Requests by Tag, Status and SWF.yml (100%) rename {collections => bruno/collections}/Power Automate/Get eF request exportTags.yml (100%) rename {collections => bruno/collections}/Power Automate/Get eF requests.yml (100%) rename {collections => bruno/collections}/Power Automate/Power Query/Get Comune.yml (100%) rename {collections => bruno/collections}/Power Automate/Power Query/SignIn.yml (100%) rename {collections => bruno/collections}/Power Automate/Power Query/folder.yml (100%) rename {collections => bruno/collections}/Power Automate/opencollection.yml (100%) rename {collections => bruno/collections}/Scopus/.env.template (100%) rename {collections => bruno/collections}/Scopus/Get Citations.yml (100%) rename {collections => bruno/collections}/Scopus/environments/Scopus - Prod.yml (100%) rename {collections => bruno/collections}/Scopus/opencollection.yml (100%) rename {collections => bruno/collections}/SharePoint API/opencollection.yml (100%) rename {collections => bruno/collections}/elixForms API v2/.env.template (100%) rename {collections => bruno/collections}/elixForms API v2/Authorization/Login.yml (100%) rename {collections => bruno/collections}/elixForms API v2/Authorization/Logout.yml (100%) rename {collections => bruno/collections}/elixForms API v2/Authorization/folder.yml (100%) rename {collections => bruno/collections}/elixForms API v2/Calendar 2.0/Get appointments.yml (100%) rename {collections => bruno/collections}/elixForms API v2/Calendar 2.0/Set acquired appointments.yml (100%) rename {collections => bruno/collections}/elixForms API v2/Calendar 2.0/folder.yml (100%) rename {collections => bruno/collections}/elixForms API v2/Cambio stato e-o integrazione/Acquisizione istanze elaborate da processo esterno.yml (100%) rename {collections => bruno/collections}/elixForms API v2/Cambio stato e-o integrazione/Clone Request.yml (100%) rename {collections => bruno/collections}/elixForms API v2/Cambio stato e-o integrazione/Reopen Request (OLD).yml (100%) rename {collections => bruno/collections}/elixForms API v2/Cambio stato e-o integrazione/Reopen Request.yml (100%) rename {collections => bruno/collections}/elixForms API v2/Cambio stato e-o integrazione/Set Request Status (OLD).yml (100%) rename {collections => bruno/collections}/elixForms API v2/Cambio stato e-o integrazione/Set Request Status- Register result (OLD).yml (100%) rename {collections => bruno/collections}/elixForms API v2/Cambio stato e-o integrazione/Set Request Status.yml (100%) rename {collections => bruno/collections}/elixForms API v2/Cambio stato e-o integrazione/Update Request SWF values.yml (100%) rename {collections => bruno/collections}/elixForms API v2/Cambio stato e-o integrazione/folder.yml (100%) rename {collections => bruno/collections}/elixForms API v2/Comunicazioni formali/Invio comunicazione formale.yml (100%) rename {collections => bruno/collections}/elixForms API v2/Comunicazioni formali/folder.yml (100%) rename {collections => bruno/collections}/elixForms API v2/EFTL processing/CCT - Determina da Proposta/Proposta CCT determina contratti conto terzi NO EFTL.yml (100%) rename {collections => bruno/collections}/elixForms API v2/EFTL processing/CCT - Determina da Proposta/Proposta CCT determina contratti conto terzi.yml (100%) rename {collections => bruno/collections}/elixForms API v2/EFTL processing/CCT - Determina da Proposta/Proposta CCT determina ex art 15 NO EFTL.yml (100%) rename {collections => bruno/collections}/elixForms API v2/EFTL processing/CCT - Determina da Proposta/Proposta CCT determina ex art 15.yml (100%) rename {collections => bruno/collections}/elixForms API v2/EFTL processing/CCT - Determina da Proposta/Proposta CCT determina sperimentazioni cliniche NO EFTL.yml (100%) rename {collections => bruno/collections}/elixForms API v2/EFTL processing/CCT - Determina da Proposta/Proposta CCT determina sperimentazioni cliniche.yml (100%) rename {collections => bruno/collections}/elixForms API v2/EFTL processing/CCT - Determina da Proposta/Punto A regolamento.yml (100%) rename {collections => bruno/collections}/elixForms API v2/EFTL processing/CCT - Determina da Proposta/Punto B regolamento.yml (100%) rename {collections => bruno/collections}/elixForms API v2/EFTL processing/CCT - Determina da Proposta/folder.yml (100%) rename {collections => bruno/collections}/elixForms API v2/EFTL processing/CCT - Liquidazione Compensi/DSAN/Anno corrente.yml (100%) rename {collections => bruno/collections}/elixForms API v2/EFTL processing/CCT - Liquidazione Compensi/DSAN/Elenco Contraenti in formato CSV DSAN.yml (100%) rename {collections => bruno/collections}/elixForms API v2/EFTL processing/CCT - Liquidazione Compensi/DSAN/Elenco RS in formato CSV DSAN.yml (100%) rename {collections => bruno/collections}/elixForms API v2/EFTL processing/CCT - Liquidazione Compensi/DSAN/Inserimento Ore Dentro - Calcolo importo equivalente.yml (100%) rename {collections => bruno/collections}/elixForms API v2/EFTL processing/CCT - Liquidazione Compensi/DSAN/Inserimento Ore Dentro - Dati attività CSV.yml (100%) rename {collections => bruno/collections}/elixForms API v2/EFTL processing/CCT - Liquidazione Compensi/DSAN/Inserimento Ore Fuori - Calcolo importo equivalente.yml (100%) rename {collections => bruno/collections}/elixForms API v2/EFTL processing/CCT - Liquidazione Compensi/DSAN/Inserimento Ore Fuori - Dati attività CSV copy.yml (100%) rename {collections => bruno/collections}/elixForms API v2/EFTL processing/CCT - Liquidazione Compensi/DSAN/Limiti - Calcolo MIN ore dentro orario.yml (100%) rename {collections => bruno/collections}/elixForms API v2/EFTL processing/CCT - Liquidazione Compensi/DSAN/Limiti - Calcolo MIN ore fuori orario.yml (100%) rename {collections => bruno/collections}/elixForms API v2/EFTL processing/CCT - Liquidazione Compensi/DSAN/Limiti - Indicazione MAX annuale ore dentro orario.yml (100%) rename {collections => bruno/collections}/elixForms API v2/EFTL processing/CCT - Liquidazione Compensi/DSAN/Limiti - Indicazione MAX annuale ore fuori orario.yml (100%) rename {collections => bruno/collections}/elixForms API v2/EFTL processing/CCT - Liquidazione Compensi/DSAN/Richiedente - Calcolo ore equivalenti.yml (100%) rename {collections => bruno/collections}/elixForms API v2/EFTL processing/CCT - Liquidazione Compensi/DSAN/Richiedente - Check ammesso compilazione.yml (100%) rename {collections => bruno/collections}/elixForms API v2/EFTL processing/CCT - Liquidazione Compensi/DSAN/Richiedente - Check ruolo per compilazione.yml (100%) rename {collections => bruno/collections}/elixForms API v2/EFTL processing/CCT - Liquidazione Compensi/DSAN/Richiedente - Importo ripartizione da Proposta.yml (100%) rename {collections => bruno/collections}/elixForms API v2/EFTL processing/CCT - Liquidazione Compensi/DSAN/folder.yml (100%) rename {collections => bruno/collections}/elixForms API v2/EFTL processing/CCT - Liquidazione Compensi/Proposta/Campi conferma - Codice struttura assegnazione.yml (100%) rename {collections => bruno/collections}/elixForms API v2/EFTL processing/CCT - Liquidazione Compensi/Proposta/Campi conferma - Codice struttura protocollo.yml (100%) rename {collections => bruno/collections}/elixForms API v2/EFTL processing/CCT - Liquidazione Compensi/Proposta/Check Richiedente IN Responsabili Scientifici.yml (100%) rename {collections => bruno/collections}/elixForms API v2/EFTL processing/CCT - Liquidazione Compensi/Proposta/Codici fiscali ripartizioni.yml (100%) rename {collections => bruno/collections}/elixForms API v2/EFTL processing/CCT - Liquidazione Compensi/Proposta/Elenco Contraenti in formato CSV.yml (100%) rename {collections => bruno/collections}/elixForms API v2/EFTL processing/CCT - Liquidazione Compensi/Proposta/Elenco Partecipanti - Array CF altri.yml (100%) rename {collections => bruno/collections}/elixForms API v2/EFTL processing/CCT - Liquidazione Compensi/Proposta/Elenco Partecipanti - Array CF docenti.yml (100%) rename {collections => bruno/collections}/elixForms API v2/EFTL processing/CCT - Liquidazione Compensi/Proposta/Elenco Partecipanti - Dropdown con chiave.yml (100%) rename {collections => bruno/collections}/elixForms API v2/EFTL processing/CCT - Liquidazione Compensi/Proposta/Elenco RS in formato CSV.yml (100%) rename {collections => bruno/collections}/elixForms API v2/EFTL processing/CCT - Liquidazione Compensi/Proposta/Nominativo completo RS proponente.yml (100%) rename {collections => bruno/collections}/elixForms API v2/EFTL processing/CCT - Liquidazione Compensi/Proposta/Notifiche email partecipanti - Body.yml (100%) rename {collections => bruno/collections}/elixForms API v2/EFTL processing/CCT - Liquidazione Compensi/Proposta/Notifiche email partecipanti - Subject.yml (100%) rename {collections => bruno/collections}/elixForms API v2/EFTL processing/CCT - Liquidazione Compensi/Proposta/Partecipanti - Body NO fancy HTML.yml (100%) rename {collections => bruno/collections}/elixForms API v2/EFTL processing/CCT - Liquidazione Compensi/Proposta/Partecipanti - Body.yml (100%) rename {collections => bruno/collections}/elixForms API v2/EFTL processing/CCT - Liquidazione Compensi/Proposta/Partecipanti - CF per verifica DSAN.yml (100%) rename {collections => bruno/collections}/elixForms API v2/EFTL processing/CCT - Liquidazione Compensi/Proposta/Partecipanti - Email.yml (100%) rename {collections => bruno/collections}/elixForms API v2/EFTL processing/CCT - Liquidazione Compensi/Proposta/Partecipanti - Importo PTA.yml (100%) rename {collections => bruno/collections}/elixForms API v2/EFTL processing/CCT - Liquidazione Compensi/Proposta/Partecipanti - Importo docente.yml (100%) rename {collections => bruno/collections}/elixForms API v2/EFTL processing/CCT - Liquidazione Compensi/Proposta/Partecipanti - Riga dati completi ripartizione.yml (100%) rename {collections => bruno/collections}/elixForms API v2/EFTL processing/CCT - Liquidazione Compensi/Proposta/Partecipanti - Subject.yml (100%) rename {collections => bruno/collections}/elixForms API v2/EFTL processing/CCT - Liquidazione Compensi/Proposta/Partecipanti - hasDSAN.yml (100%) rename {collections => bruno/collections}/elixForms API v2/EFTL processing/CCT - Liquidazione Compensi/Proposta/Recupero importo richiedente da proposta.yml (100%) rename {collections => bruno/collections}/elixForms API v2/EFTL processing/CCT - Liquidazione Compensi/Proposta/Ripartizioni - Count da form partecipante.yml (100%) rename {collections => bruno/collections}/elixForms API v2/EFTL processing/CCT - Liquidazione Compensi/Proposta/Tabella HTML ripartizioni FOR ADVANCED.yml (100%) rename {collections => bruno/collections}/elixForms API v2/EFTL processing/CCT - Liquidazione Compensi/Proposta/Tabella HTML ripartizioni FOR.yml (100%) rename {collections => bruno/collections}/elixForms API v2/EFTL processing/CCT - Liquidazione Compensi/Proposta/Tabella HTML ripartizioni WHILE.yml (100%) rename {collections => bruno/collections}/elixForms API v2/EFTL processing/CCT - Liquidazione Compensi/Proposta/elixPro - Recupero importi inseriti.yml (100%) rename {collections => bruno/collections}/elixForms API v2/EFTL processing/CCT - Liquidazione Compensi/Proposta/elixPro - Template Delibera ONLYTABLE.yml (100%) rename {collections => bruno/collections}/elixForms API v2/EFTL processing/CCT - Liquidazione Compensi/Proposta/elixPro - Template Delibera.yml (100%) rename {collections => bruno/collections}/elixForms API v2/EFTL processing/CCT - Liquidazione Compensi/Proposta/folder.yml (100%) rename {collections => bruno/collections}/elixForms API v2/EFTL processing/CCT - Liquidazione Compensi/folder.yml (100%) rename {collections => bruno/collections}/elixForms API v2/EFTL processing/CCT - Proposta Operatore/Calcolo D.1.3 5% con virgole.yml (100%) rename {collections => bruno/collections}/elixForms API v2/EFTL processing/CCT - Proposta Operatore/Calcolo D.1.3 con virgole.yml (100%) rename {collections => bruno/collections}/elixForms API v2/EFTL processing/CCT - Proposta Operatore/Codice Contratto con caratteri strani.yml (100%) rename {collections => bruno/collections}/elixForms API v2/EFTL processing/CCT - Proposta Operatore/Contratto IS economico.yml (100%) rename {collections => bruno/collections}/elixForms API v2/EFTL processing/CCT - Proposta Operatore/Elenco Contraenti CSV (nominativo).yml (100%) rename {collections => bruno/collections}/elixForms API v2/EFTL processing/CCT - Proposta Operatore/Elenco RS CSV (cognome nome).yml (100%) rename {collections => bruno/collections}/elixForms API v2/EFTL processing/CCT - Proposta Operatore/Elenco contraenti formattati.yml (100%) rename {collections => bruno/collections}/elixForms API v2/EFTL processing/CCT - Proposta Operatore/Fascicolo e documento - Nuovo formato.yml (100%) rename {collections => bruno/collections}/elixForms API v2/EFTL processing/CCT - Proposta Operatore/Fascicolo e documento su Titulus.yml (100%) rename {collections => bruno/collections}/elixForms API v2/EFTL processing/CCT - Proposta Operatore/Messaggio ritenute massime.yml (100%) rename {collections => bruno/collections}/elixForms API v2/EFTL processing/CCT - Proposta Operatore/folder.yml (100%) rename {collections => bruno/collections}/elixForms API v2/EFTL processing/MOD A13 Richiesta Certificato/Gestione Istanze - Elenco carriere inserite.yml (100%) rename {collections => bruno/collections}/elixForms API v2/EFTL processing/MOD A13 Richiesta Certificato/Notifiche email - Elenco carriere e certificati.yml (100%) rename {collections => bruno/collections}/elixForms API v2/EFTL processing/MOD A13 Richiesta Certificato/folder.yml (100%) rename {collections => bruno/collections}/elixForms API v2/EFTL processing/Process EFTL.yml (100%) rename {collections => bruno/collections}/elixForms API v2/EFTL processing/Test vari/Create JSON.yml (100%) rename {collections => bruno/collections}/elixForms API v2/EFTL processing/Test vari/TAG per protocollazione fra uffici.yml (100%) rename {collections => bruno/collections}/elixForms API v2/EFTL processing/Test vari/TAG per riprotocollazione (integrazione).yml (100%) rename {collections => bruno/collections}/elixForms API v2/EFTL processing/Test vari/TEST ordine GetValueByTag.yml (100%) rename {collections => bruno/collections}/elixForms API v2/EFTL processing/Test vari/Test Errore 406.yml (100%) rename {collections => bruno/collections}/elixForms API v2/EFTL processing/Test vari/Test vari.yml (100%) rename {collections => bruno/collections}/elixForms API v2/EFTL processing/Test vari/folder.yml (100%) rename {collections => bruno/collections}/elixForms API v2/EFTL processing/folder.yml (100%) rename {collections => bruno/collections}/elixForms API v2/Request details/Get ExportTags.yml (100%) rename {collections => bruno/collections}/elixForms API v2/Request details/Get Request Attachment.yml (100%) rename {collections => bruno/collections}/elixForms API v2/Request details/Get Request Identifier.yml (100%) rename {collections => bruno/collections}/elixForms API v2/Request details/Get Request by QRCode.yml (100%) rename {collections => bruno/collections}/elixForms API v2/Request details/Get Request.yml (100%) rename {collections => bruno/collections}/elixForms API v2/Request details/folder.yml (100%) rename {collections => bruno/collections}/elixForms API v2/Requests lookup/Lookup By Period.yml (100%) rename {collections => bruno/collections}/elixForms API v2/Requests lookup/Lookup By Status.yml (100%) rename {collections => bruno/collections}/elixForms API v2/Requests lookup/Lookup By User and Period.yml (100%) rename {collections => bruno/collections}/elixForms API v2/Requests lookup/Lookup By User.yml (100%) rename {collections => bruno/collections}/elixForms API v2/Requests lookup/Obsolete/Lookup By Status (OLD).yml (100%) rename {collections => bruno/collections}/elixForms API v2/Requests lookup/Obsolete/Lookup By Status.yml (100%) rename {collections => bruno/collections}/elixForms API v2/Requests lookup/Obsolete/Lookup By User and Period (OLD).yml (100%) rename {collections => bruno/collections}/elixForms API v2/Requests lookup/Obsolete/Lookup By User only (-) (OLD).yml (100%) rename {collections => bruno/collections}/elixForms API v2/Requests lookup/Obsolete/folder.yml (100%) rename {collections => bruno/collections}/elixForms API v2/Requests lookup/folder.yml (100%) rename {collections => bruno/collections}/elixForms API v2/Runner- Get all requests by ModuleTag and status/Get request details.yml (100%) rename {collections => bruno/collections}/elixForms API v2/Runner- Get all requests by ModuleTag and status/Login once.yml (100%) rename {collections => bruno/collections}/elixForms API v2/Runner- Get all requests by ModuleTag and status/Lookup requests.yml (100%) rename {collections => bruno/collections}/elixForms API v2/Runner- Get all requests by ModuleTag and status/folder.yml (100%) rename {collections => bruno/collections}/elixForms API v2/Set Request Status- Incomplete.yml (100%) rename {collections => bruno/collections}/elixForms API v2/Test Remote WS.yml (100%) rename {collections => bruno/collections}/elixForms API v2/User info/Get User Info.yml (100%) rename {collections => bruno/collections}/elixForms API v2/User info/folder.yml (100%) rename {collections => bruno/collections}/elixForms API v2/_HACKS/Export Module.yml (100%) rename {collections => bruno/collections}/elixForms API v2/_HACKS/folder.yml (100%) rename {collections => bruno/collections}/elixForms API v2/_Untested/Creazione JWT.yml (100%) rename {collections => bruno/collections}/elixForms API v2/_Untested/SSO Receipt Insert.yml (100%) rename {collections => bruno/collections}/elixForms API v2/_Untested/SSO Receipt by User.yml (100%) rename {collections => bruno/collections}/elixForms API v2/_Untested/folder.yml (100%) rename {collections => bruno/collections}/elixForms API v2/elixFormsJs.js (100%) rename {collections => bruno/collections}/elixForms API v2/environments/elixForms - Prod.yml (100%) rename {collections => bruno/collections}/elixForms API v2/opencollection.yml (100%) rename {environments => bruno/environments}/UniPR.yml (100%) rename workspace.yml => bruno/workspace.yml (100%) diff --git a/collections/ESSE3 Anagrafica API/.env.template b/bruno/collections/ESSE3 Anagrafica API/.env.template similarity index 100% rename from collections/ESSE3 Anagrafica API/.env.template rename to bruno/collections/ESSE3 Anagrafica API/.env.template diff --git a/collections/ESSE3 Anagrafica API/allegati/cancellazione allegato al documento di identità.yml b/bruno/collections/ESSE3 Anagrafica API/allegati/cancellazione allegato al documento di identità.yml similarity index 100% rename from collections/ESSE3 Anagrafica API/allegati/cancellazione allegato al documento di identità.yml rename to bruno/collections/ESSE3 Anagrafica API/allegati/cancellazione allegato al documento di identità.yml diff --git a/collections/ESSE3 Anagrafica API/allegati/cancellazione allegato al tratto di carriera.yml b/bruno/collections/ESSE3 Anagrafica API/allegati/cancellazione allegato al tratto di carriera.yml similarity index 100% rename from collections/ESSE3 Anagrafica API/allegati/cancellazione allegato al tratto di carriera.yml rename to bruno/collections/ESSE3 Anagrafica API/allegati/cancellazione allegato al tratto di carriera.yml diff --git a/collections/ESSE3 Anagrafica API/allegati/folder.yml b/bruno/collections/ESSE3 Anagrafica API/allegati/folder.yml similarity index 100% rename from collections/ESSE3 Anagrafica API/allegati/folder.yml rename to bruno/collections/ESSE3 Anagrafica API/allegati/folder.yml diff --git a/collections/ESSE3 Anagrafica API/allegati/inserimento metadati allegato dichiarazione handicap.yml b/bruno/collections/ESSE3 Anagrafica API/allegati/inserimento metadati allegato dichiarazione handicap.yml similarity index 100% rename from collections/ESSE3 Anagrafica API/allegati/inserimento metadati allegato dichiarazione handicap.yml rename to bruno/collections/ESSE3 Anagrafica API/allegati/inserimento metadati allegato dichiarazione handicap.yml diff --git a/collections/ESSE3 Anagrafica API/allegati/inserimento metadati allegato documento identità.yml b/bruno/collections/ESSE3 Anagrafica API/allegati/inserimento metadati allegato documento identità.yml similarity index 100% rename from collections/ESSE3 Anagrafica API/allegati/inserimento metadati allegato documento identità.yml rename to bruno/collections/ESSE3 Anagrafica API/allegati/inserimento metadati allegato documento identità.yml diff --git a/collections/ESSE3 Anagrafica API/allegati/inserimento metadati allegato foto della persona.yml b/bruno/collections/ESSE3 Anagrafica API/allegati/inserimento metadati allegato foto della persona.yml similarity index 100% rename from collections/ESSE3 Anagrafica API/allegati/inserimento metadati allegato foto della persona.yml rename to bruno/collections/ESSE3 Anagrafica API/allegati/inserimento metadati allegato foto della persona.yml diff --git a/collections/ESSE3 Anagrafica API/allegati/inserimento metadati allegato matricola.yml b/bruno/collections/ESSE3 Anagrafica API/allegati/inserimento metadati allegato matricola.yml similarity index 100% rename from collections/ESSE3 Anagrafica API/allegati/inserimento metadati allegato matricola.yml rename to bruno/collections/ESSE3 Anagrafica API/allegati/inserimento metadati allegato matricola.yml diff --git a/collections/ESSE3 Anagrafica API/allegati/inserimento metadati allegato maturità.yml b/bruno/collections/ESSE3 Anagrafica API/allegati/inserimento metadati allegato maturità.yml similarity index 100% rename from collections/ESSE3 Anagrafica API/allegati/inserimento metadati allegato maturità.yml rename to bruno/collections/ESSE3 Anagrafica API/allegati/inserimento metadati allegato maturità.yml diff --git a/collections/ESSE3 Anagrafica API/allegati/inserimento metadati allegato relativo ad un autorizzato.yml b/bruno/collections/ESSE3 Anagrafica API/allegati/inserimento metadati allegato relativo ad un autorizzato.yml similarity index 100% rename from collections/ESSE3 Anagrafica API/allegati/inserimento metadati allegato relativo ad un autorizzato.yml rename to bruno/collections/ESSE3 Anagrafica API/allegati/inserimento metadati allegato relativo ad un autorizzato.yml diff --git a/collections/ESSE3 Anagrafica API/allegati/inserimento metadati allegato relativo ad un documento d'identità di un autorizzato.yml b/bruno/collections/ESSE3 Anagrafica API/allegati/inserimento metadati allegato relativo ad un documento d'identità di un autorizzato.yml similarity index 100% rename from collections/ESSE3 Anagrafica API/allegati/inserimento metadati allegato relativo ad un documento d'identità di un autorizzato.yml rename to bruno/collections/ESSE3 Anagrafica API/allegati/inserimento metadati allegato relativo ad un documento d'identità di un autorizzato.yml diff --git a/collections/ESSE3 Anagrafica API/allegati/inserimento metadati allegato titolo universitario italiano.yml b/bruno/collections/ESSE3 Anagrafica API/allegati/inserimento metadati allegato titolo universitario italiano.yml similarity index 100% rename from collections/ESSE3 Anagrafica API/allegati/inserimento metadati allegato titolo universitario italiano.yml rename to bruno/collections/ESSE3 Anagrafica API/allegati/inserimento metadati allegato titolo universitario italiano.yml diff --git a/collections/ESSE3 Anagrafica API/allegati/inserimento metadati allegato titolo universitario straniero.yml b/bruno/collections/ESSE3 Anagrafica API/allegati/inserimento metadati allegato titolo universitario straniero.yml similarity index 100% rename from collections/ESSE3 Anagrafica API/allegati/inserimento metadati allegato titolo universitario straniero.yml rename to bruno/collections/ESSE3 Anagrafica API/allegati/inserimento metadati allegato titolo universitario straniero.yml diff --git a/collections/ESSE3 Anagrafica API/allegati/recupero metadati allegati dichiarazioni handicap.yml b/bruno/collections/ESSE3 Anagrafica API/allegati/recupero metadati allegati dichiarazioni handicap.yml similarity index 100% rename from collections/ESSE3 Anagrafica API/allegati/recupero metadati allegati dichiarazioni handicap.yml rename to bruno/collections/ESSE3 Anagrafica API/allegati/recupero metadati allegati dichiarazioni handicap.yml diff --git a/collections/ESSE3 Anagrafica API/allegati/recupero metadati allegati documento identità.yml b/bruno/collections/ESSE3 Anagrafica API/allegati/recupero metadati allegati documento identità.yml similarity index 100% rename from collections/ESSE3 Anagrafica API/allegati/recupero metadati allegati documento identità.yml rename to bruno/collections/ESSE3 Anagrafica API/allegati/recupero metadati allegati documento identità.yml diff --git a/collections/ESSE3 Anagrafica API/allegati/recupero metadati allegati matricola.yml b/bruno/collections/ESSE3 Anagrafica API/allegati/recupero metadati allegati matricola.yml similarity index 100% rename from collections/ESSE3 Anagrafica API/allegati/recupero metadati allegati matricola.yml rename to bruno/collections/ESSE3 Anagrafica API/allegati/recupero metadati allegati matricola.yml diff --git a/collections/ESSE3 Anagrafica API/allegati/recupero metadati allegati maturità.yml b/bruno/collections/ESSE3 Anagrafica API/allegati/recupero metadati allegati maturità.yml similarity index 100% rename from collections/ESSE3 Anagrafica API/allegati/recupero metadati allegati maturità.yml rename to bruno/collections/ESSE3 Anagrafica API/allegati/recupero metadati allegati maturità.yml diff --git a/collections/ESSE3 Anagrafica API/allegati/recupero metadati allegati relativi ad un autorizzato.yml b/bruno/collections/ESSE3 Anagrafica API/allegati/recupero metadati allegati relativi ad un autorizzato.yml similarity index 100% rename from collections/ESSE3 Anagrafica API/allegati/recupero metadati allegati relativi ad un autorizzato.yml rename to bruno/collections/ESSE3 Anagrafica API/allegati/recupero metadati allegati relativi ad un autorizzato.yml diff --git a/collections/ESSE3 Anagrafica API/allegati/recupero metadati allegati relativi ai documenti d'identità di un autorizzato.yml b/bruno/collections/ESSE3 Anagrafica API/allegati/recupero metadati allegati relativi ai documenti d'identità di un autorizzato.yml similarity index 100% rename from collections/ESSE3 Anagrafica API/allegati/recupero metadati allegati relativi ai documenti d'identità di un autorizzato.yml rename to bruno/collections/ESSE3 Anagrafica API/allegati/recupero metadati allegati relativi ai documenti d'identità di un autorizzato.yml diff --git a/collections/ESSE3 Anagrafica API/allegati/recupero metadati allegati titoli universitari italiani.yml b/bruno/collections/ESSE3 Anagrafica API/allegati/recupero metadati allegati titoli universitari italiani.yml similarity index 100% rename from collections/ESSE3 Anagrafica API/allegati/recupero metadati allegati titoli universitari italiani.yml rename to bruno/collections/ESSE3 Anagrafica API/allegati/recupero metadati allegati titoli universitari italiani.yml diff --git a/collections/ESSE3 Anagrafica API/allegati/recupero metadati allegati titoli universitari stranieri.yml b/bruno/collections/ESSE3 Anagrafica API/allegati/recupero metadati allegati titoli universitari stranieri.yml similarity index 100% rename from collections/ESSE3 Anagrafica API/allegati/recupero metadati allegati titoli universitari stranieri.yml rename to bruno/collections/ESSE3 Anagrafica API/allegati/recupero metadati allegati titoli universitari stranieri.yml diff --git a/collections/ESSE3 Anagrafica API/anagrafica/Effettua l'aggiornamento dei consensi del soggetto esterno.yml b/bruno/collections/ESSE3 Anagrafica API/anagrafica/Effettua l'aggiornamento dei consensi del soggetto esterno.yml similarity index 100% rename from collections/ESSE3 Anagrafica API/anagrafica/Effettua l'aggiornamento dei consensi del soggetto esterno.yml rename to bruno/collections/ESSE3 Anagrafica API/anagrafica/Effettua l'aggiornamento dei consensi del soggetto esterno.yml diff --git a/collections/ESSE3 Anagrafica API/anagrafica/Recupera le tipologie di handicap per cui sono presenti dichiarazioni da valutare.yml b/bruno/collections/ESSE3 Anagrafica API/anagrafica/Recupera le tipologie di handicap per cui sono presenti dichiarazioni da valutare.yml similarity index 100% rename from collections/ESSE3 Anagrafica API/anagrafica/Recupera le tipologie di handicap per cui sono presenti dichiarazioni da valutare.yml rename to bruno/collections/ESSE3 Anagrafica API/anagrafica/Recupera le tipologie di handicap per cui sono presenti dichiarazioni da valutare.yml diff --git a/collections/ESSE3 Anagrafica API/anagrafica/Recupera le tipologie di handicap.yml b/bruno/collections/ESSE3 Anagrafica API/anagrafica/Recupera le tipologie di handicap.yml similarity index 100% rename from collections/ESSE3 Anagrafica API/anagrafica/Recupera le tipologie di handicap.yml rename to bruno/collections/ESSE3 Anagrafica API/anagrafica/Recupera le tipologie di handicap.yml diff --git a/collections/ESSE3 Anagrafica API/anagrafica/Recupera le tipologie di parentele.yml b/bruno/collections/ESSE3 Anagrafica API/anagrafica/Recupera le tipologie di parentele.yml similarity index 100% rename from collections/ESSE3 Anagrafica API/anagrafica/Recupera le tipologie di parentele.yml rename to bruno/collections/ESSE3 Anagrafica API/anagrafica/Recupera le tipologie di parentele.yml diff --git a/collections/ESSE3 Anagrafica API/anagrafica/Recupero atenei stranieri.yml b/bruno/collections/ESSE3 Anagrafica API/anagrafica/Recupero atenei stranieri.yml similarity index 100% rename from collections/ESSE3 Anagrafica API/anagrafica/Recupero atenei stranieri.yml rename to bruno/collections/ESSE3 Anagrafica API/anagrafica/Recupero atenei stranieri.yml diff --git a/collections/ESSE3 Anagrafica API/anagrafica/Recupero atenei.yml b/bruno/collections/ESSE3 Anagrafica API/anagrafica/Recupero atenei.yml similarity index 100% rename from collections/ESSE3 Anagrafica API/anagrafica/Recupero atenei.yml rename to bruno/collections/ESSE3 Anagrafica API/anagrafica/Recupero atenei.yml diff --git a/collections/ESSE3 Anagrafica API/anagrafica/Recupero corsi di studio di un ateneo.yml b/bruno/collections/ESSE3 Anagrafica API/anagrafica/Recupero corsi di studio di un ateneo.yml similarity index 100% rename from collections/ESSE3 Anagrafica API/anagrafica/Recupero corsi di studio di un ateneo.yml rename to bruno/collections/ESSE3 Anagrafica API/anagrafica/Recupero corsi di studio di un ateneo.yml diff --git a/collections/ESSE3 Anagrafica API/anagrafica/Recupero delle normative legate alle dichiarazioni di handicap.yml b/bruno/collections/ESSE3 Anagrafica API/anagrafica/Recupero delle normative legate alle dichiarazioni di handicap.yml similarity index 100% rename from collections/ESSE3 Anagrafica API/anagrafica/Recupero delle normative legate alle dichiarazioni di handicap.yml rename to bruno/collections/ESSE3 Anagrafica API/anagrafica/Recupero delle normative legate alle dichiarazioni di handicap.yml diff --git a/collections/ESSE3 Anagrafica API/anagrafica/Recupero istituti.yml b/bruno/collections/ESSE3 Anagrafica API/anagrafica/Recupero istituti.yml similarity index 100% rename from collections/ESSE3 Anagrafica API/anagrafica/Recupero istituti.yml rename to bruno/collections/ESSE3 Anagrafica API/anagrafica/Recupero istituti.yml diff --git a/collections/ESSE3 Anagrafica API/anagrafica/Recupero range voti maturità.yml b/bruno/collections/ESSE3 Anagrafica API/anagrafica/Recupero range voti maturità.yml similarity index 100% rename from collections/ESSE3 Anagrafica API/anagrafica/Recupero range voti maturità.yml rename to bruno/collections/ESSE3 Anagrafica API/anagrafica/Recupero range voti maturità.yml diff --git a/collections/ESSE3 Anagrafica API/anagrafica/Recupero tipi cotutela.yml b/bruno/collections/ESSE3 Anagrafica API/anagrafica/Recupero tipi cotutela.yml similarity index 100% rename from collections/ESSE3 Anagrafica API/anagrafica/Recupero tipi cotutela.yml rename to bruno/collections/ESSE3 Anagrafica API/anagrafica/Recupero tipi cotutela.yml diff --git a/collections/ESSE3 Anagrafica API/anagrafica/Recupero tipi istituto superiore.yml b/bruno/collections/ESSE3 Anagrafica API/anagrafica/Recupero tipi istituto superiore.yml similarity index 100% rename from collections/ESSE3 Anagrafica API/anagrafica/Recupero tipi istituto superiore.yml rename to bruno/collections/ESSE3 Anagrafica API/anagrafica/Recupero tipi istituto superiore.yml diff --git a/collections/ESSE3 Anagrafica API/anagrafica/Recupero tipi titoli scuola superiore.yml b/bruno/collections/ESSE3 Anagrafica API/anagrafica/Recupero tipi titoli scuola superiore.yml similarity index 100% rename from collections/ESSE3 Anagrafica API/anagrafica/Recupero tipi titoli scuola superiore.yml rename to bruno/collections/ESSE3 Anagrafica API/anagrafica/Recupero tipi titoli scuola superiore.yml diff --git a/collections/ESSE3 Anagrafica API/anagrafica/Recupero tipi titoli stranieri.yml b/bruno/collections/ESSE3 Anagrafica API/anagrafica/Recupero tipi titoli stranieri.yml similarity index 100% rename from collections/ESSE3 Anagrafica API/anagrafica/Recupero tipi titoli stranieri.yml rename to bruno/collections/ESSE3 Anagrafica API/anagrafica/Recupero tipi titoli stranieri.yml diff --git a/collections/ESSE3 Anagrafica API/anagrafica/Recupero tipologie di dichiarazione dei titoli stranieri.yml b/bruno/collections/ESSE3 Anagrafica API/anagrafica/Recupero tipologie di dichiarazione dei titoli stranieri.yml similarity index 100% rename from collections/ESSE3 Anagrafica API/anagrafica/Recupero tipologie di dichiarazione dei titoli stranieri.yml rename to bruno/collections/ESSE3 Anagrafica API/anagrafica/Recupero tipologie di dichiarazione dei titoli stranieri.yml diff --git a/collections/ESSE3 Anagrafica API/anagrafica/folder.yml b/bruno/collections/ESSE3 Anagrafica API/anagrafica/folder.yml similarity index 100% rename from collections/ESSE3 Anagrafica API/anagrafica/folder.yml rename to bruno/collections/ESSE3 Anagrafica API/anagrafica/folder.yml diff --git a/collections/ESSE3 Anagrafica API/autorizzati/folder.yml b/bruno/collections/ESSE3 Anagrafica API/autorizzati/folder.yml similarity index 100% rename from collections/ESSE3 Anagrafica API/autorizzati/folder.yml rename to bruno/collections/ESSE3 Anagrafica API/autorizzati/folder.yml diff --git a/collections/ESSE3 Anagrafica API/autorizzati/recupero delle regole di richiesta tutori.yml b/bruno/collections/ESSE3 Anagrafica API/autorizzati/recupero delle regole di richiesta tutori.yml similarity index 100% rename from collections/ESSE3 Anagrafica API/autorizzati/recupero delle regole di richiesta tutori.yml rename to bruno/collections/ESSE3 Anagrafica API/autorizzati/recupero delle regole di richiesta tutori.yml diff --git a/collections/ESSE3 Anagrafica API/datiBancari/folder.yml b/bruno/collections/ESSE3 Anagrafica API/datiBancari/folder.yml similarity index 100% rename from collections/ESSE3 Anagrafica API/datiBancari/folder.yml rename to bruno/collections/ESSE3 Anagrafica API/datiBancari/folder.yml diff --git a/collections/ESSE3 Anagrafica API/datiBancari/recupero dei dati bancari.yml b/bruno/collections/ESSE3 Anagrafica API/datiBancari/recupero dei dati bancari.yml similarity index 100% rename from collections/ESSE3 Anagrafica API/datiBancari/recupero dei dati bancari.yml rename to bruno/collections/ESSE3 Anagrafica API/datiBancari/recupero dei dati bancari.yml diff --git a/collections/ESSE3 Anagrafica API/dichiarazioni_invalidità/Aggiornamento di una dichiarazioni di handicap legata ad un'anagrafica (PUT).yml b/bruno/collections/ESSE3 Anagrafica API/dichiarazioni_invalidità/Aggiornamento di una dichiarazioni di handicap legata ad un'anagrafica (PUT).yml similarity index 100% rename from collections/ESSE3 Anagrafica API/dichiarazioni_invalidità/Aggiornamento di una dichiarazioni di handicap legata ad un'anagrafica (PUT).yml rename to bruno/collections/ESSE3 Anagrafica API/dichiarazioni_invalidità/Aggiornamento di una dichiarazioni di handicap legata ad un'anagrafica (PUT).yml diff --git a/collections/ESSE3 Anagrafica API/dichiarazioni_invalidità/Aggiornamento di una dichiarazioni di handicap legata ad un'anagrafica.yml b/bruno/collections/ESSE3 Anagrafica API/dichiarazioni_invalidità/Aggiornamento di una dichiarazioni di handicap legata ad un'anagrafica.yml similarity index 100% rename from collections/ESSE3 Anagrafica API/dichiarazioni_invalidità/Aggiornamento di una dichiarazioni di handicap legata ad un'anagrafica.yml rename to bruno/collections/ESSE3 Anagrafica API/dichiarazioni_invalidità/Aggiornamento di una dichiarazioni di handicap legata ad un'anagrafica.yml diff --git a/collections/ESSE3 Anagrafica API/dichiarazioni_invalidità/Recupera il blob dell'allegato richiesto.yml b/bruno/collections/ESSE3 Anagrafica API/dichiarazioni_invalidità/Recupera il blob dell'allegato richiesto.yml similarity index 100% rename from collections/ESSE3 Anagrafica API/dichiarazioni_invalidità/Recupera il blob dell'allegato richiesto.yml rename to bruno/collections/ESSE3 Anagrafica API/dichiarazioni_invalidità/Recupera il blob dell'allegato richiesto.yml diff --git a/collections/ESSE3 Anagrafica API/dichiarazioni_invalidità/effettua l'aggiornamento dei dettagli di una misura compensative associate alla dichiarazione di invalidità di una anagrafica. (PUT).yml b/bruno/collections/ESSE3 Anagrafica API/dichiarazioni_invalidità/effettua l'aggiornamento dei dettagli di una misura compensative associate alla dichiarazione di invalidità di una anagrafica. (PUT).yml similarity index 100% rename from collections/ESSE3 Anagrafica API/dichiarazioni_invalidità/effettua l'aggiornamento dei dettagli di una misura compensative associate alla dichiarazione di invalidità di una anagrafica. (PUT).yml rename to bruno/collections/ESSE3 Anagrafica API/dichiarazioni_invalidità/effettua l'aggiornamento dei dettagli di una misura compensative associate alla dichiarazione di invalidità di una anagrafica. (PUT).yml diff --git a/collections/ESSE3 Anagrafica API/dichiarazioni_invalidità/effettua l'aggiornamento dei dettagli di una misura compensative associate alla dichiarazione di invalidità di una anagrafica.yml b/bruno/collections/ESSE3 Anagrafica API/dichiarazioni_invalidità/effettua l'aggiornamento dei dettagli di una misura compensative associate alla dichiarazione di invalidità di una anagrafica.yml similarity index 100% rename from collections/ESSE3 Anagrafica API/dichiarazioni_invalidità/effettua l'aggiornamento dei dettagli di una misura compensative associate alla dichiarazione di invalidità di una anagrafica.yml rename to bruno/collections/ESSE3 Anagrafica API/dichiarazioni_invalidità/effettua l'aggiornamento dei dettagli di una misura compensative associate alla dichiarazione di invalidità di una anagrafica.yml diff --git a/collections/ESSE3 Anagrafica API/dichiarazioni_invalidità/folder.yml b/bruno/collections/ESSE3 Anagrafica API/dichiarazioni_invalidità/folder.yml similarity index 100% rename from collections/ESSE3 Anagrafica API/dichiarazioni_invalidità/folder.yml rename to bruno/collections/ESSE3 Anagrafica API/dichiarazioni_invalidità/folder.yml diff --git a/collections/ESSE3 Anagrafica API/dichiarazioni_invalidità/misure compensative per i bisogni speciali degli studeneti (GET).yml b/bruno/collections/ESSE3 Anagrafica API/dichiarazioni_invalidità/misure compensative per i bisogni speciali degli studeneti (GET).yml similarity index 100% rename from collections/ESSE3 Anagrafica API/dichiarazioni_invalidità/misure compensative per i bisogni speciali degli studeneti (GET).yml rename to bruno/collections/ESSE3 Anagrafica API/dichiarazioni_invalidità/misure compensative per i bisogni speciali degli studeneti (GET).yml diff --git a/collections/ESSE3 Anagrafica API/dichiarazioni_invalidità/recupero delle dichiarazioni di handicap legate ad un'anagrafica.yml b/bruno/collections/ESSE3 Anagrafica API/dichiarazioni_invalidità/recupero delle dichiarazioni di handicap legate ad un'anagrafica.yml similarity index 100% rename from collections/ESSE3 Anagrafica API/dichiarazioni_invalidità/recupero delle dichiarazioni di handicap legate ad un'anagrafica.yml rename to bruno/collections/ESSE3 Anagrafica API/dichiarazioni_invalidità/recupero delle dichiarazioni di handicap legate ad un'anagrafica.yml diff --git a/collections/ESSE3 Anagrafica API/dichiarazioni_invalidità/recupero di una dichiarazioni di handicap legata ad un'anagrafica.yml b/bruno/collections/ESSE3 Anagrafica API/dichiarazioni_invalidità/recupero di una dichiarazioni di handicap legata ad un'anagrafica.yml similarity index 100% rename from collections/ESSE3 Anagrafica API/dichiarazioni_invalidità/recupero di una dichiarazioni di handicap legata ad un'anagrafica.yml rename to bruno/collections/ESSE3 Anagrafica API/dichiarazioni_invalidità/recupero di una dichiarazioni di handicap legata ad un'anagrafica.yml diff --git a/collections/ESSE3 Anagrafica API/docenti/folder.yml b/bruno/collections/ESSE3 Anagrafica API/docenti/folder.yml similarity index 100% rename from collections/ESSE3 Anagrafica API/docenti/folder.yml rename to bruno/collections/ESSE3 Anagrafica API/docenti/folder.yml diff --git a/collections/ESSE3 Anagrafica API/docenti/getDocente.yml b/bruno/collections/ESSE3 Anagrafica API/docenti/getDocente.yml similarity index 100% rename from collections/ESSE3 Anagrafica API/docenti/getDocente.yml rename to bruno/collections/ESSE3 Anagrafica API/docenti/getDocente.yml diff --git a/collections/ESSE3 Anagrafica API/dream_apply/folder.yml b/bruno/collections/ESSE3 Anagrafica API/dream_apply/folder.yml similarity index 100% rename from collections/ESSE3 Anagrafica API/dream_apply/folder.yml rename to bruno/collections/ESSE3 Anagrafica API/dream_apply/folder.yml diff --git a/collections/ESSE3 Anagrafica API/dream_apply/refresh della data di scadenza del token dreamapply e recupero dell’url di attivazione.yml b/bruno/collections/ESSE3 Anagrafica API/dream_apply/refresh della data di scadenza del token dreamapply e recupero dell’url di attivazione.yml similarity index 100% rename from collections/ESSE3 Anagrafica API/dream_apply/refresh della data di scadenza del token dreamapply e recupero dell’url di attivazione.yml rename to bruno/collections/ESSE3 Anagrafica API/dream_apply/refresh della data di scadenza del token dreamapply e recupero dell’url di attivazione.yml diff --git a/collections/ESSE3 Anagrafica API/environments/ESSE3 Anagrafica Pre-Prod #2.yml b/bruno/collections/ESSE3 Anagrafica API/environments/ESSE3 Anagrafica Pre-Prod #2.yml similarity index 100% rename from collections/ESSE3 Anagrafica API/environments/ESSE3 Anagrafica Pre-Prod #2.yml rename to bruno/collections/ESSE3 Anagrafica API/environments/ESSE3 Anagrafica Pre-Prod #2.yml diff --git a/collections/ESSE3 Anagrafica API/misure_compensative/Recupero misure compensative.yml b/bruno/collections/ESSE3 Anagrafica API/misure_compensative/Recupero misure compensative.yml similarity index 100% rename from collections/ESSE3 Anagrafica API/misure_compensative/Recupero misure compensative.yml rename to bruno/collections/ESSE3 Anagrafica API/misure_compensative/Recupero misure compensative.yml diff --git a/collections/ESSE3 Anagrafica API/misure_compensative/folder.yml b/bruno/collections/ESSE3 Anagrafica API/misure_compensative/folder.yml similarity index 100% rename from collections/ESSE3 Anagrafica API/misure_compensative/folder.yml rename to bruno/collections/ESSE3 Anagrafica API/misure_compensative/folder.yml diff --git a/collections/ESSE3 Anagrafica API/opencollection.yml b/bruno/collections/ESSE3 Anagrafica API/opencollection.yml similarity index 100% rename from collections/ESSE3 Anagrafica API/opencollection.yml rename to bruno/collections/ESSE3 Anagrafica API/opencollection.yml diff --git a/collections/ESSE3 Anagrafica API/persone/Dismette un indirizzo email istituzionale (PATCH).yml b/bruno/collections/ESSE3 Anagrafica API/persone/Dismette un indirizzo email istituzionale (PATCH).yml similarity index 100% rename from collections/ESSE3 Anagrafica API/persone/Dismette un indirizzo email istituzionale (PATCH).yml rename to bruno/collections/ESSE3 Anagrafica API/persone/Dismette un indirizzo email istituzionale (PATCH).yml diff --git a/collections/ESSE3 Anagrafica API/persone/Dismette un indirizzo email istituzionale.yml b/bruno/collections/ESSE3 Anagrafica API/persone/Dismette un indirizzo email istituzionale.yml similarity index 100% rename from collections/ESSE3 Anagrafica API/persone/Dismette un indirizzo email istituzionale.yml rename to bruno/collections/ESSE3 Anagrafica API/persone/Dismette un indirizzo email istituzionale.yml diff --git a/collections/ESSE3 Anagrafica API/persone/Effettua l'aggiornamento dei consensi dello studente.yml b/bruno/collections/ESSE3 Anagrafica API/persone/Effettua l'aggiornamento dei consensi dello studente.yml similarity index 100% rename from collections/ESSE3 Anagrafica API/persone/Effettua l'aggiornamento dei consensi dello studente.yml rename to bruno/collections/ESSE3 Anagrafica API/persone/Effettua l'aggiornamento dei consensi dello studente.yml diff --git a/collections/ESSE3 Anagrafica API/persone/Effettua l'aggiornamento dell'email istituzionale dello studente.yml b/bruno/collections/ESSE3 Anagrafica API/persone/Effettua l'aggiornamento dell'email istituzionale dello studente.yml similarity index 100% rename from collections/ESSE3 Anagrafica API/persone/Effettua l'aggiornamento dell'email istituzionale dello studente.yml rename to bruno/collections/ESSE3 Anagrafica API/persone/Effettua l'aggiornamento dell'email istituzionale dello studente.yml diff --git a/collections/ESSE3 Anagrafica API/persone/Effettua l'aggiornamento dell'email personale dello studente.yml b/bruno/collections/ESSE3 Anagrafica API/persone/Effettua l'aggiornamento dell'email personale dello studente.yml similarity index 100% rename from collections/ESSE3 Anagrafica API/persone/Effettua l'aggiornamento dell'email personale dello studente.yml rename to bruno/collections/ESSE3 Anagrafica API/persone/Effettua l'aggiornamento dell'email personale dello studente.yml diff --git a/collections/ESSE3 Anagrafica API/persone/Effettua l'aggiornamento o l'inserimento dei titoli di studio relativi ad una persona.yml b/bruno/collections/ESSE3 Anagrafica API/persone/Effettua l'aggiornamento o l'inserimento dei titoli di studio relativi ad una persona.yml similarity index 100% rename from collections/ESSE3 Anagrafica API/persone/Effettua l'aggiornamento o l'inserimento dei titoli di studio relativi ad una persona.yml rename to bruno/collections/ESSE3 Anagrafica API/persone/Effettua l'aggiornamento o l'inserimento dei titoli di studio relativi ad una persona.yml diff --git a/collections/ESSE3 Anagrafica API/persone/Effettua l'inserimento dei titoli di studio relativi ad una persona (POST).yml b/bruno/collections/ESSE3 Anagrafica API/persone/Effettua l'inserimento dei titoli di studio relativi ad una persona (POST).yml similarity index 100% rename from collections/ESSE3 Anagrafica API/persone/Effettua l'inserimento dei titoli di studio relativi ad una persona (POST).yml rename to bruno/collections/ESSE3 Anagrafica API/persone/Effettua l'inserimento dei titoli di studio relativi ad una persona (POST).yml diff --git a/collections/ESSE3 Anagrafica API/persone/Effettua l'inserimento dei titoli di studio relativi ad una persona.yml b/bruno/collections/ESSE3 Anagrafica API/persone/Effettua l'inserimento dei titoli di studio relativi ad una persona.yml similarity index 100% rename from collections/ESSE3 Anagrafica API/persone/Effettua l'inserimento dei titoli di studio relativi ad una persona.yml rename to bruno/collections/ESSE3 Anagrafica API/persone/Effettua l'inserimento dei titoli di studio relativi ad una persona.yml diff --git a/collections/ESSE3 Anagrafica API/persone/Recupera i consensi relativi ad uno studente.yml b/bruno/collections/ESSE3 Anagrafica API/persone/Recupera i consensi relativi ad uno studente.yml similarity index 100% rename from collections/ESSE3 Anagrafica API/persone/Recupera i consensi relativi ad uno studente.yml rename to bruno/collections/ESSE3 Anagrafica API/persone/Recupera i consensi relativi ad uno studente.yml diff --git a/collections/ESSE3 Anagrafica API/persone/Recupera i titoli relativi ad una persona (GET).yml b/bruno/collections/ESSE3 Anagrafica API/persone/Recupera i titoli relativi ad una persona (GET).yml similarity index 100% rename from collections/ESSE3 Anagrafica API/persone/Recupera i titoli relativi ad una persona (GET).yml rename to bruno/collections/ESSE3 Anagrafica API/persone/Recupera i titoli relativi ad una persona (GET).yml diff --git a/collections/ESSE3 Anagrafica API/persone/Recupera i titoli relativi ad una persona.yml b/bruno/collections/ESSE3 Anagrafica API/persone/Recupera i titoli relativi ad una persona.yml similarity index 100% rename from collections/ESSE3 Anagrafica API/persone/Recupera i titoli relativi ad una persona.yml rename to bruno/collections/ESSE3 Anagrafica API/persone/Recupera i titoli relativi ad una persona.yml diff --git a/collections/ESSE3 Anagrafica API/persone/Recupero della carriera degli studenti.yml b/bruno/collections/ESSE3 Anagrafica API/persone/Recupero della carriera degli studenti.yml similarity index 100% rename from collections/ESSE3 Anagrafica API/persone/Recupero della carriera degli studenti.yml rename to bruno/collections/ESSE3 Anagrafica API/persone/Recupero della carriera degli studenti.yml diff --git a/collections/ESSE3 Anagrafica API/persone/Recupero delle anagrafiche presenti a sistema (GET).yml b/bruno/collections/ESSE3 Anagrafica API/persone/Recupero delle anagrafiche presenti a sistema (GET).yml similarity index 100% rename from collections/ESSE3 Anagrafica API/persone/Recupero delle anagrafiche presenti a sistema (GET).yml rename to bruno/collections/ESSE3 Anagrafica API/persone/Recupero delle anagrafiche presenti a sistema (GET).yml diff --git a/collections/ESSE3 Anagrafica API/persone/Recupero delle anagrafiche presenti a sistema.yml b/bruno/collections/ESSE3 Anagrafica API/persone/Recupero delle anagrafiche presenti a sistema.yml similarity index 100% rename from collections/ESSE3 Anagrafica API/persone/Recupero delle anagrafiche presenti a sistema.yml rename to bruno/collections/ESSE3 Anagrafica API/persone/Recupero delle anagrafiche presenti a sistema.yml diff --git a/collections/ESSE3 Anagrafica API/persone/Recupero delle informazioni relative ad una singola persona presente a sistema ed identificata dal persid (GET).yml b/bruno/collections/ESSE3 Anagrafica API/persone/Recupero delle informazioni relative ad una singola persona presente a sistema ed identificata dal persid (GET).yml similarity index 100% rename from collections/ESSE3 Anagrafica API/persone/Recupero delle informazioni relative ad una singola persona presente a sistema ed identificata dal persid (GET).yml rename to bruno/collections/ESSE3 Anagrafica API/persone/Recupero delle informazioni relative ad una singola persona presente a sistema ed identificata dal persid (GET).yml diff --git a/collections/ESSE3 Anagrafica API/persone/Recupero delle informazioni relative ad una singola persona presente a sistema ed identificata dal persid.yml b/bruno/collections/ESSE3 Anagrafica API/persone/Recupero delle informazioni relative ad una singola persona presente a sistema ed identificata dal persid.yml similarity index 100% rename from collections/ESSE3 Anagrafica API/persone/Recupero delle informazioni relative ad una singola persona presente a sistema ed identificata dal persid.yml rename to bruno/collections/ESSE3 Anagrafica API/persone/Recupero delle informazioni relative ad una singola persona presente a sistema ed identificata dal persid.yml diff --git a/collections/ESSE3 Anagrafica API/persone/aggiornamento cellulare.yml b/bruno/collections/ESSE3 Anagrafica API/persone/aggiornamento cellulare.yml similarity index 100% rename from collections/ESSE3 Anagrafica API/persone/aggiornamento cellulare.yml rename to bruno/collections/ESSE3 Anagrafica API/persone/aggiornamento cellulare.yml diff --git a/collections/ESSE3 Anagrafica API/persone/aggiornamento telefono di domicilio.yml b/bruno/collections/ESSE3 Anagrafica API/persone/aggiornamento telefono di domicilio.yml similarity index 100% rename from collections/ESSE3 Anagrafica API/persone/aggiornamento telefono di domicilio.yml rename to bruno/collections/ESSE3 Anagrafica API/persone/aggiornamento telefono di domicilio.yml diff --git a/collections/ESSE3 Anagrafica API/persone/aggiornamento telefono di residenza.yml b/bruno/collections/ESSE3 Anagrafica API/persone/aggiornamento telefono di residenza.yml similarity index 100% rename from collections/ESSE3 Anagrafica API/persone/aggiornamento telefono di residenza.yml rename to bruno/collections/ESSE3 Anagrafica API/persone/aggiornamento telefono di residenza.yml diff --git a/collections/ESSE3 Anagrafica API/persone/folder.yml b/bruno/collections/ESSE3 Anagrafica API/persone/folder.yml similarity index 100% rename from collections/ESSE3 Anagrafica API/persone/folder.yml rename to bruno/collections/ESSE3 Anagrafica API/persone/folder.yml diff --git a/collections/ESSE3 Anagrafica API/persone/getFotoPersona.yml b/bruno/collections/ESSE3 Anagrafica API/persone/getFotoPersona.yml similarity index 100% rename from collections/ESSE3 Anagrafica API/persone/getFotoPersona.yml rename to bruno/collections/ESSE3 Anagrafica API/persone/getFotoPersona.yml diff --git a/collections/ESSE3 Anagrafica API/persone/getValidaFlgFoto.yml b/bruno/collections/ESSE3 Anagrafica API/persone/getValidaFlgFoto.yml similarity index 100% rename from collections/ESSE3 Anagrafica API/persone/getValidaFlgFoto.yml rename to bruno/collections/ESSE3 Anagrafica API/persone/getValidaFlgFoto.yml diff --git a/collections/ESSE3 Anagrafica API/persone/misure compensative per i bisogni speciali degli studeneti.yml b/bruno/collections/ESSE3 Anagrafica API/persone/misure compensative per i bisogni speciali degli studeneti.yml similarity index 100% rename from collections/ESSE3 Anagrafica API/persone/misure compensative per i bisogni speciali degli studeneti.yml rename to bruno/collections/ESSE3 Anagrafica API/persone/misure compensative per i bisogni speciali degli studeneti.yml diff --git a/collections/ESSE3 Anagrafica API/persone/recupero degli autorizzati legati ad una anagrafica.yml b/bruno/collections/ESSE3 Anagrafica API/persone/recupero degli autorizzati legati ad una anagrafica.yml similarity index 100% rename from collections/ESSE3 Anagrafica API/persone/recupero degli autorizzati legati ad una anagrafica.yml rename to bruno/collections/ESSE3 Anagrafica API/persone/recupero degli autorizzati legati ad una anagrafica.yml diff --git a/collections/ESSE3 Anagrafica API/persone/recupero dei tutori legati ad una anagrafica.yml b/bruno/collections/ESSE3 Anagrafica API/persone/recupero dei tutori legati ad una anagrafica.yml similarity index 100% rename from collections/ESSE3 Anagrafica API/persone/recupero dei tutori legati ad una anagrafica.yml rename to bruno/collections/ESSE3 Anagrafica API/persone/recupero dei tutori legati ad una anagrafica.yml diff --git a/collections/ESSE3 Anagrafica API/soggetti_esterni/Elimina i dati di un soggetto esterno in esse3.yml b/bruno/collections/ESSE3 Anagrafica API/soggetti_esterni/Elimina i dati di un soggetto esterno in esse3.yml similarity index 100% rename from collections/ESSE3 Anagrafica API/soggetti_esterni/Elimina i dati di un soggetto esterno in esse3.yml rename to bruno/collections/ESSE3 Anagrafica API/soggetti_esterni/Elimina i dati di un soggetto esterno in esse3.yml diff --git a/collections/ESSE3 Anagrafica API/soggetti_esterni/Inserisce oppure aggiorna i dati di un soggetto esterno in esse3.yml b/bruno/collections/ESSE3 Anagrafica API/soggetti_esterni/Inserisce oppure aggiorna i dati di un soggetto esterno in esse3.yml similarity index 100% rename from collections/ESSE3 Anagrafica API/soggetti_esterni/Inserisce oppure aggiorna i dati di un soggetto esterno in esse3.yml rename to bruno/collections/ESSE3 Anagrafica API/soggetti_esterni/Inserisce oppure aggiorna i dati di un soggetto esterno in esse3.yml diff --git a/collections/ESSE3 Anagrafica API/soggetti_esterni/Recupera i consensi relativi ad un soggetto esterno.yml b/bruno/collections/ESSE3 Anagrafica API/soggetti_esterni/Recupera i consensi relativi ad un soggetto esterno.yml similarity index 100% rename from collections/ESSE3 Anagrafica API/soggetti_esterni/Recupera i consensi relativi ad un soggetto esterno.yml rename to bruno/collections/ESSE3 Anagrafica API/soggetti_esterni/Recupera i consensi relativi ad un soggetto esterno.yml diff --git a/collections/ESSE3 Anagrafica API/soggetti_esterni/Recupero dei soggetti esterni (1).yml b/bruno/collections/ESSE3 Anagrafica API/soggetti_esterni/Recupero dei soggetti esterni (1).yml similarity index 100% rename from collections/ESSE3 Anagrafica API/soggetti_esterni/Recupero dei soggetti esterni (1).yml rename to bruno/collections/ESSE3 Anagrafica API/soggetti_esterni/Recupero dei soggetti esterni (1).yml diff --git a/collections/ESSE3 Anagrafica API/soggetti_esterni/Recupero dei soggetti esterni (GET).yml b/bruno/collections/ESSE3 Anagrafica API/soggetti_esterni/Recupero dei soggetti esterni (GET).yml similarity index 100% rename from collections/ESSE3 Anagrafica API/soggetti_esterni/Recupero dei soggetti esterni (GET).yml rename to bruno/collections/ESSE3 Anagrafica API/soggetti_esterni/Recupero dei soggetti esterni (GET).yml diff --git a/collections/ESSE3 Anagrafica API/soggetti_esterni/Recupero dei soggetti esterni.yml b/bruno/collections/ESSE3 Anagrafica API/soggetti_esterni/Recupero dei soggetti esterni.yml similarity index 100% rename from collections/ESSE3 Anagrafica API/soggetti_esterni/Recupero dei soggetti esterni.yml rename to bruno/collections/ESSE3 Anagrafica API/soggetti_esterni/Recupero dei soggetti esterni.yml diff --git a/collections/ESSE3 Anagrafica API/soggetti_esterni/folder.yml b/bruno/collections/ESSE3 Anagrafica API/soggetti_esterni/folder.yml similarity index 100% rename from collections/ESSE3 Anagrafica API/soggetti_esterni/folder.yml rename to bruno/collections/ESSE3 Anagrafica API/soggetti_esterni/folder.yml diff --git a/collections/ESSE3 Common Auth API/.env.template b/bruno/collections/ESSE3 Common Auth API/.env.template similarity index 100% rename from collections/ESSE3 Common Auth API/.env.template rename to bruno/collections/ESSE3 Common Auth API/.env.template diff --git a/collections/ESSE3 Common Auth API/autenticazione/changeUserPassword.yml b/bruno/collections/ESSE3 Common Auth API/autenticazione/changeUserPassword.yml similarity index 100% rename from collections/ESSE3 Common Auth API/autenticazione/changeUserPassword.yml rename to bruno/collections/ESSE3 Common Auth API/autenticazione/changeUserPassword.yml diff --git a/collections/ESSE3 Common Auth API/autenticazione/checkLogon.yml b/bruno/collections/ESSE3 Common Auth API/autenticazione/checkLogon.yml similarity index 100% rename from collections/ESSE3 Common Auth API/autenticazione/checkLogon.yml rename to bruno/collections/ESSE3 Common Auth API/autenticazione/checkLogon.yml diff --git a/collections/ESSE3 Common Auth API/autenticazione/checkSessionId.yml b/bruno/collections/ESSE3 Common Auth API/autenticazione/checkSessionId.yml similarity index 100% rename from collections/ESSE3 Common Auth API/autenticazione/checkSessionId.yml rename to bruno/collections/ESSE3 Common Auth API/autenticazione/checkSessionId.yml diff --git a/collections/ESSE3 Common Auth API/autenticazione/folder.yml b/bruno/collections/ESSE3 Common Auth API/autenticazione/folder.yml similarity index 100% rename from collections/ESSE3 Common Auth API/autenticazione/folder.yml rename to bruno/collections/ESSE3 Common Auth API/autenticazione/folder.yml diff --git a/collections/ESSE3 Common Auth API/autenticazione/getCacheParams.yml b/bruno/collections/ESSE3 Common Auth API/autenticazione/getCacheParams.yml similarity index 100% rename from collections/ESSE3 Common Auth API/autenticazione/getCacheParams.yml rename to bruno/collections/ESSE3 Common Auth API/autenticazione/getCacheParams.yml diff --git a/collections/ESSE3 Common Auth API/autenticazione/getCurrentSession.yml b/bruno/collections/ESSE3 Common Auth API/autenticazione/getCurrentSession.yml similarity index 100% rename from collections/ESSE3 Common Auth API/autenticazione/getCurrentSession.yml rename to bruno/collections/ESSE3 Common Auth API/autenticazione/getCurrentSession.yml diff --git a/collections/ESSE3 Common Auth API/autenticazione/getJWT.yml b/bruno/collections/ESSE3 Common Auth API/autenticazione/getJWT.yml similarity index 100% rename from collections/ESSE3 Common Auth API/autenticazione/getJWT.yml rename to bruno/collections/ESSE3 Common Auth API/autenticazione/getJWT.yml diff --git a/collections/ESSE3 Common Auth API/autenticazione/getLinguaCod.yml b/bruno/collections/ESSE3 Common Auth API/autenticazione/getLinguaCod.yml similarity index 100% rename from collections/ESSE3 Common Auth API/autenticazione/getLinguaCod.yml rename to bruno/collections/ESSE3 Common Auth API/autenticazione/getLinguaCod.yml diff --git a/collections/ESSE3 Common Auth API/autenticazione/login.yml b/bruno/collections/ESSE3 Common Auth API/autenticazione/login.yml similarity index 100% rename from collections/ESSE3 Common Auth API/autenticazione/login.yml rename to bruno/collections/ESSE3 Common Auth API/autenticazione/login.yml diff --git a/collections/ESSE3 Common Auth API/autenticazione/logout.yml b/bruno/collections/ESSE3 Common Auth API/autenticazione/logout.yml similarity index 100% rename from collections/ESSE3 Common Auth API/autenticazione/logout.yml rename to bruno/collections/ESSE3 Common Auth API/autenticazione/logout.yml diff --git a/collections/ESSE3 Common Auth API/autenticazione/setCacheParams.yml b/bruno/collections/ESSE3 Common Auth API/autenticazione/setCacheParams.yml similarity index 100% rename from collections/ESSE3 Common Auth API/autenticazione/setCacheParams.yml rename to bruno/collections/ESSE3 Common Auth API/autenticazione/setCacheParams.yml diff --git a/collections/ESSE3 Common Auth API/autenticazione/setLinguaCod.yml b/bruno/collections/ESSE3 Common Auth API/autenticazione/setLinguaCod.yml similarity index 100% rename from collections/ESSE3 Common Auth API/autenticazione/setLinguaCod.yml rename to bruno/collections/ESSE3 Common Auth API/autenticazione/setLinguaCod.yml diff --git a/collections/ESSE3 Common Auth API/environments/ESSE3 Common Auth Pre-Prod #2.yml b/bruno/collections/ESSE3 Common Auth API/environments/ESSE3 Common Auth Pre-Prod #2.yml similarity index 100% rename from collections/ESSE3 Common Auth API/environments/ESSE3 Common Auth Pre-Prod #2.yml rename to bruno/collections/ESSE3 Common Auth API/environments/ESSE3 Common Auth Pre-Prod #2.yml diff --git a/collections/ESSE3 Common Auth API/jwt/folder.yml b/bruno/collections/ESSE3 Common Auth API/jwt/folder.yml similarity index 100% rename from collections/ESSE3 Common Auth API/jwt/folder.yml rename to bruno/collections/ESSE3 Common Auth API/jwt/folder.yml diff --git a/collections/ESSE3 Common Auth API/jwt/getJWK.yml b/bruno/collections/ESSE3 Common Auth API/jwt/getJWK.yml similarity index 100% rename from collections/ESSE3 Common Auth API/jwt/getJWK.yml rename to bruno/collections/ESSE3 Common Auth API/jwt/getJWK.yml diff --git a/collections/ESSE3 Common Auth API/jwt/refreshJWT.yml b/bruno/collections/ESSE3 Common Auth API/jwt/refreshJWT.yml similarity index 100% rename from collections/ESSE3 Common Auth API/jwt/refreshJWT.yml rename to bruno/collections/ESSE3 Common Auth API/jwt/refreshJWT.yml diff --git a/collections/ESSE3 Common Auth API/opencollection.yml b/bruno/collections/ESSE3 Common Auth API/opencollection.yml similarity index 100% rename from collections/ESSE3 Common Auth API/opencollection.yml rename to bruno/collections/ESSE3 Common Auth API/opencollection.yml diff --git a/collections/Gov.it OpenData/Get Organization Content.yml b/bruno/collections/Gov.it OpenData/Get Organization Content.yml similarity index 100% rename from collections/Gov.it OpenData/Get Organization Content.yml rename to bruno/collections/Gov.it OpenData/Get Organization Content.yml diff --git a/collections/Gov.it OpenData/Get Organization List.yml b/bruno/collections/Gov.it OpenData/Get Organization List.yml similarity index 100% rename from collections/Gov.it OpenData/Get Organization List.yml rename to bruno/collections/Gov.it OpenData/Get Organization List.yml diff --git a/collections/Gov.it OpenData/Get Package Content.yml b/bruno/collections/Gov.it OpenData/Get Package Content.yml similarity index 100% rename from collections/Gov.it OpenData/Get Package Content.yml rename to bruno/collections/Gov.it OpenData/Get Package Content.yml diff --git a/collections/Gov.it OpenData/Get Package List with Resources.yml b/bruno/collections/Gov.it OpenData/Get Package List with Resources.yml similarity index 100% rename from collections/Gov.it OpenData/Get Package List with Resources.yml rename to bruno/collections/Gov.it OpenData/Get Package List with Resources.yml diff --git a/collections/Gov.it OpenData/Get Package List.yml b/bruno/collections/Gov.it OpenData/Get Package List.yml similarity index 100% rename from collections/Gov.it OpenData/Get Package List.yml rename to bruno/collections/Gov.it OpenData/Get Package List.yml diff --git a/collections/Gov.it OpenData/opencollection.yml b/bruno/collections/Gov.it OpenData/opencollection.yml similarity index 100% rename from collections/Gov.it OpenData/opencollection.yml rename to bruno/collections/Gov.it OpenData/opencollection.yml diff --git a/collections/IDEM WebServices/.env.template b/bruno/collections/IDEM WebServices/.env.template similarity index 100% rename from collections/IDEM WebServices/.env.template rename to bruno/collections/IDEM WebServices/.env.template diff --git a/collections/IDEM WebServices/Anagrafiche/Autorizzatori Centri.yml b/bruno/collections/IDEM WebServices/Anagrafiche/Autorizzatori Centri.yml similarity index 100% rename from collections/IDEM WebServices/Anagrafiche/Autorizzatori Centri.yml rename to bruno/collections/IDEM WebServices/Anagrafiche/Autorizzatori Centri.yml diff --git a/collections/IDEM WebServices/Anagrafiche/Autorizzatori Struttura.yml b/bruno/collections/IDEM WebServices/Anagrafiche/Autorizzatori Struttura.yml similarity index 100% rename from collections/IDEM WebServices/Anagrafiche/Autorizzatori Struttura.yml rename to bruno/collections/IDEM WebServices/Anagrafiche/Autorizzatori Struttura.yml diff --git a/collections/IDEM WebServices/Anagrafiche/Autorizzatori.yml b/bruno/collections/IDEM WebServices/Anagrafiche/Autorizzatori.yml similarity index 100% rename from collections/IDEM WebServices/Anagrafiche/Autorizzatori.yml rename to bruno/collections/IDEM WebServices/Anagrafiche/Autorizzatori.yml diff --git a/collections/IDEM WebServices/Anagrafiche/Dipendente (Codice fiscale).yml b/bruno/collections/IDEM WebServices/Anagrafiche/Dipendente (Codice fiscale).yml similarity index 100% rename from collections/IDEM WebServices/Anagrafiche/Dipendente (Codice fiscale).yml rename to bruno/collections/IDEM WebServices/Anagrafiche/Dipendente (Codice fiscale).yml diff --git a/collections/IDEM WebServices/Anagrafiche/Dipendente (E-mail).yml b/bruno/collections/IDEM WebServices/Anagrafiche/Dipendente (E-mail).yml similarity index 100% rename from collections/IDEM WebServices/Anagrafiche/Dipendente (E-mail).yml rename to bruno/collections/IDEM WebServices/Anagrafiche/Dipendente (E-mail).yml diff --git a/collections/IDEM WebServices/Anagrafiche/Dipendente by Codice Fiscale.yml b/bruno/collections/IDEM WebServices/Anagrafiche/Dipendente by Codice Fiscale.yml similarity index 100% rename from collections/IDEM WebServices/Anagrafiche/Dipendente by Codice Fiscale.yml rename to bruno/collections/IDEM WebServices/Anagrafiche/Dipendente by Codice Fiscale.yml diff --git a/collections/IDEM WebServices/Anagrafiche/Dipendente by E-mail.yml b/bruno/collections/IDEM WebServices/Anagrafiche/Dipendente by E-mail.yml similarity index 100% rename from collections/IDEM WebServices/Anagrafiche/Dipendente by E-mail.yml rename to bruno/collections/IDEM WebServices/Anagrafiche/Dipendente by E-mail.yml diff --git a/collections/IDEM WebServices/Anagrafiche/Strutture Centri.yml b/bruno/collections/IDEM WebServices/Anagrafiche/Strutture Centri.yml similarity index 100% rename from collections/IDEM WebServices/Anagrafiche/Strutture Centri.yml rename to bruno/collections/IDEM WebServices/Anagrafiche/Strutture Centri.yml diff --git a/collections/IDEM WebServices/Anagrafiche/Strutture apicali.yml b/bruno/collections/IDEM WebServices/Anagrafiche/Strutture apicali.yml similarity index 100% rename from collections/IDEM WebServices/Anagrafiche/Strutture apicali.yml rename to bruno/collections/IDEM WebServices/Anagrafiche/Strutture apicali.yml diff --git a/collections/IDEM WebServices/Anagrafiche/Studente (Codice Fiscale).yml b/bruno/collections/IDEM WebServices/Anagrafiche/Studente (Codice Fiscale).yml similarity index 100% rename from collections/IDEM WebServices/Anagrafiche/Studente (Codice Fiscale).yml rename to bruno/collections/IDEM WebServices/Anagrafiche/Studente (Codice Fiscale).yml diff --git a/collections/IDEM WebServices/Anagrafiche/Studente (E-mail).yml b/bruno/collections/IDEM WebServices/Anagrafiche/Studente (E-mail).yml similarity index 100% rename from collections/IDEM WebServices/Anagrafiche/Studente (E-mail).yml rename to bruno/collections/IDEM WebServices/Anagrafiche/Studente (E-mail).yml diff --git a/collections/IDEM WebServices/Anagrafiche/Studente Carriere Dropdown (CF).yml b/bruno/collections/IDEM WebServices/Anagrafiche/Studente Carriere Dropdown (CF).yml similarity index 100% rename from collections/IDEM WebServices/Anagrafiche/Studente Carriere Dropdown (CF).yml rename to bruno/collections/IDEM WebServices/Anagrafiche/Studente Carriere Dropdown (CF).yml diff --git a/collections/IDEM WebServices/Anagrafiche/folder.yml b/bruno/collections/IDEM WebServices/Anagrafiche/folder.yml similarity index 100% rename from collections/IDEM WebServices/Anagrafiche/folder.yml rename to bruno/collections/IDEM WebServices/Anagrafiche/folder.yml diff --git a/collections/IDEM WebServices/Contratti/Contratti (IRIS GW).yml b/bruno/collections/IDEM WebServices/Contratti/Contratti (IRIS GW).yml similarity index 100% rename from collections/IDEM WebServices/Contratti/Contratti (IRIS GW).yml rename to bruno/collections/IDEM WebServices/Contratti/Contratti (IRIS GW).yml diff --git a/collections/IDEM WebServices/Contratti/Contratti Eseguiti (IRIS GW).yml b/bruno/collections/IDEM WebServices/Contratti/Contratti Eseguiti (IRIS GW).yml similarity index 100% rename from collections/IDEM WebServices/Contratti/Contratti Eseguiti (IRIS GW).yml rename to bruno/collections/IDEM WebServices/Contratti/Contratti Eseguiti (IRIS GW).yml diff --git a/collections/IDEM WebServices/Contratti/Contratto (IRIS GW).yml b/bruno/collections/IDEM WebServices/Contratti/Contratto (IRIS GW).yml similarity index 100% rename from collections/IDEM WebServices/Contratti/Contratto (IRIS GW).yml rename to bruno/collections/IDEM WebServices/Contratti/Contratto (IRIS GW).yml diff --git a/collections/IDEM WebServices/Contratti/Contratto Esteso (IRIS GW).yml b/bruno/collections/IDEM WebServices/Contratti/Contratto Esteso (IRIS GW).yml similarity index 100% rename from collections/IDEM WebServices/Contratti/Contratto Esteso (IRIS GW).yml rename to bruno/collections/IDEM WebServices/Contratti/Contratto Esteso (IRIS GW).yml diff --git a/collections/IDEM WebServices/Contratti/folder.yml b/bruno/collections/IDEM WebServices/Contratti/folder.yml similarity index 100% rename from collections/IDEM WebServices/Contratti/folder.yml rename to bruno/collections/IDEM WebServices/Contratti/folder.yml diff --git a/collections/IDEM WebServices/IDEM WebServices-documentation.html b/bruno/collections/IDEM WebServices/IDEM WebServices-documentation.html similarity index 100% rename from collections/IDEM WebServices/IDEM WebServices-documentation.html rename to bruno/collections/IDEM WebServices/IDEM WebServices-documentation.html diff --git a/collections/IDEM WebServices/Obiettivi performance.yml b/bruno/collections/IDEM WebServices/Obiettivi performance.yml similarity index 100% rename from collections/IDEM WebServices/Obiettivi performance.yml rename to bruno/collections/IDEM WebServices/Obiettivi performance.yml diff --git a/collections/IDEM WebServices/Progetti/Progetti contabilizzati in PJ.yml b/bruno/collections/IDEM WebServices/Progetti/Progetti contabilizzati in PJ.yml similarity index 100% rename from collections/IDEM WebServices/Progetti/Progetti contabilizzati in PJ.yml rename to bruno/collections/IDEM WebServices/Progetti/Progetti contabilizzati in PJ.yml diff --git a/collections/IDEM WebServices/Progetti/folder.yml b/bruno/collections/IDEM WebServices/Progetti/folder.yml similarity index 100% rename from collections/IDEM WebServices/Progetti/folder.yml rename to bruno/collections/IDEM WebServices/Progetti/folder.yml diff --git a/collections/IDEM WebServices/environments/Produzione.yml b/bruno/collections/IDEM WebServices/environments/Produzione.yml similarity index 100% rename from collections/IDEM WebServices/environments/Produzione.yml rename to bruno/collections/IDEM WebServices/environments/Produzione.yml diff --git a/collections/IDEM WebServices/environments/Test.yml b/bruno/collections/IDEM WebServices/environments/Test.yml similarity index 100% rename from collections/IDEM WebServices/environments/Test.yml rename to bruno/collections/IDEM WebServices/environments/Test.yml diff --git a/collections/IDEM WebServices/opencollection.yml b/bruno/collections/IDEM WebServices/opencollection.yml similarity index 100% rename from collections/IDEM WebServices/opencollection.yml rename to bruno/collections/IDEM WebServices/opencollection.yml diff --git a/collections/IRIS GW (Gateway) REST API (v1)/.env.template b/bruno/collections/IRIS GW (Gateway) REST API (v1)/.env.template similarity index 100% rename from collections/IRIS GW (Gateway) REST API (v1)/.env.template rename to bruno/collections/IRIS GW (Gateway) REST API (v1)/.env.template diff --git a/collections/IRIS GW (Gateway) REST API (v1)/Contracts/Get Contracts FULL.yml b/bruno/collections/IRIS GW (Gateway) REST API (v1)/Contracts/Get Contracts FULL.yml similarity index 100% rename from collections/IRIS GW (Gateway) REST API (v1)/Contracts/Get Contracts FULL.yml rename to bruno/collections/IRIS GW (Gateway) REST API (v1)/Contracts/Get Contracts FULL.yml diff --git a/collections/IRIS GW (Gateway) REST API (v1)/Contracts/Get Contracts by Department IdAb.yml b/bruno/collections/IRIS GW (Gateway) REST API (v1)/Contracts/Get Contracts by Department IdAb.yml similarity index 100% rename from collections/IRIS GW (Gateway) REST API (v1)/Contracts/Get Contracts by Department IdAb.yml rename to bruno/collections/IRIS GW (Gateway) REST API (v1)/Contracts/Get Contracts by Department IdAb.yml diff --git a/collections/IRIS GW (Gateway) REST API (v1)/Contracts/Get Contracts.yml b/bruno/collections/IRIS GW (Gateway) REST API (v1)/Contracts/Get Contracts.yml similarity index 100% rename from collections/IRIS GW (Gateway) REST API (v1)/Contracts/Get Contracts.yml rename to bruno/collections/IRIS GW (Gateway) REST API (v1)/Contracts/Get Contracts.yml diff --git a/collections/IRIS GW (Gateway) REST API (v1)/Contracts/SCRIPT - Get Contracts with two or more contributors.yml b/bruno/collections/IRIS GW (Gateway) REST API (v1)/Contracts/SCRIPT - Get Contracts with two or more contributors.yml similarity index 100% rename from collections/IRIS GW (Gateway) REST API (v1)/Contracts/SCRIPT - Get Contracts with two or more contributors.yml rename to bruno/collections/IRIS GW (Gateway) REST API (v1)/Contracts/SCRIPT - Get Contracts with two or more contributors.yml diff --git a/collections/IRIS GW (Gateway) REST API (v1)/Contracts/SCRIPT - Get Contracts with two or more owners.yml b/bruno/collections/IRIS GW (Gateway) REST API (v1)/Contracts/SCRIPT - Get Contracts with two or more owners.yml similarity index 100% rename from collections/IRIS GW (Gateway) REST API (v1)/Contracts/SCRIPT - Get Contracts with two or more owners.yml rename to bruno/collections/IRIS GW (Gateway) REST API (v1)/Contracts/SCRIPT - Get Contracts with two or more owners.yml diff --git a/collections/IRIS GW (Gateway) REST API (v1)/Contracts/folder.yml b/bruno/collections/IRIS GW (Gateway) REST API (v1)/Contracts/folder.yml similarity index 100% rename from collections/IRIS GW (Gateway) REST API (v1)/Contracts/folder.yml rename to bruno/collections/IRIS GW (Gateway) REST API (v1)/Contracts/folder.yml diff --git a/collections/IRIS GW (Gateway) REST API (v1)/WfItems/Get ASNs Copy.yml b/bruno/collections/IRIS GW (Gateway) REST API (v1)/WfItems/Get ASNs Copy.yml similarity index 100% rename from collections/IRIS GW (Gateway) REST API (v1)/WfItems/Get ASNs Copy.yml rename to bruno/collections/IRIS GW (Gateway) REST API (v1)/WfItems/Get ASNs Copy.yml diff --git a/collections/IRIS GW (Gateway) REST API (v1)/WfItems/Get ASNs.yml b/bruno/collections/IRIS GW (Gateway) REST API (v1)/WfItems/Get ASNs.yml similarity index 100% rename from collections/IRIS GW (Gateway) REST API (v1)/WfItems/Get ASNs.yml rename to bruno/collections/IRIS GW (Gateway) REST API (v1)/WfItems/Get ASNs.yml diff --git a/collections/IRIS GW (Gateway) REST API (v1)/WfItems/Get Academic Fields 2024.yml b/bruno/collections/IRIS GW (Gateway) REST API (v1)/WfItems/Get Academic Fields 2024.yml similarity index 100% rename from collections/IRIS GW (Gateway) REST API (v1)/WfItems/Get Academic Fields 2024.yml rename to bruno/collections/IRIS GW (Gateway) REST API (v1)/WfItems/Get Academic Fields 2024.yml diff --git a/collections/IRIS GW (Gateway) REST API (v1)/WfItems/Get Items Copy.yml b/bruno/collections/IRIS GW (Gateway) REST API (v1)/WfItems/Get Items Copy.yml similarity index 100% rename from collections/IRIS GW (Gateway) REST API (v1)/WfItems/Get Items Copy.yml rename to bruno/collections/IRIS GW (Gateway) REST API (v1)/WfItems/Get Items Copy.yml diff --git a/collections/IRIS GW (Gateway) REST API (v1)/WfItems/Get Items.yml b/bruno/collections/IRIS GW (Gateway) REST API (v1)/WfItems/Get Items.yml similarity index 100% rename from collections/IRIS GW (Gateway) REST API (v1)/WfItems/Get Items.yml rename to bruno/collections/IRIS GW (Gateway) REST API (v1)/WfItems/Get Items.yml diff --git a/collections/IRIS GW (Gateway) REST API (v1)/WfItems/folder.yml b/bruno/collections/IRIS GW (Gateway) REST API (v1)/WfItems/folder.yml similarity index 100% rename from collections/IRIS GW (Gateway) REST API (v1)/WfItems/folder.yml rename to bruno/collections/IRIS GW (Gateway) REST API (v1)/WfItems/folder.yml diff --git a/collections/IRIS GW (Gateway) REST API (v1)/[Runner] Get All Contracts/[Runner] Get All Contracts.yml b/bruno/collections/IRIS GW (Gateway) REST API (v1)/[Runner] Get All Contracts/[Runner] Get All Contracts.yml similarity index 100% rename from collections/IRIS GW (Gateway) REST API (v1)/[Runner] Get All Contracts/[Runner] Get All Contracts.yml rename to bruno/collections/IRIS GW (Gateway) REST API (v1)/[Runner] Get All Contracts/[Runner] Get All Contracts.yml diff --git a/collections/IRIS GW (Gateway) REST API (v1)/[Runner] Get All Contracts/folder.yml b/bruno/collections/IRIS GW (Gateway) REST API (v1)/[Runner] Get All Contracts/folder.yml similarity index 100% rename from collections/IRIS GW (Gateway) REST API (v1)/[Runner] Get All Contracts/folder.yml rename to bruno/collections/IRIS GW (Gateway) REST API (v1)/[Runner] Get All Contracts/folder.yml diff --git a/collections/IRIS GW (Gateway) REST API (v1)/environments/IRIS - Prod.yml b/bruno/collections/IRIS GW (Gateway) REST API (v1)/environments/IRIS - Prod.yml similarity index 100% rename from collections/IRIS GW (Gateway) REST API (v1)/environments/IRIS - Prod.yml rename to bruno/collections/IRIS GW (Gateway) REST API (v1)/environments/IRIS - Prod.yml diff --git a/collections/IRIS GW (Gateway) REST API (v1)/opencollection.yml b/bruno/collections/IRIS GW (Gateway) REST API (v1)/opencollection.yml similarity index 100% rename from collections/IRIS GW (Gateway) REST API (v1)/opencollection.yml rename to bruno/collections/IRIS GW (Gateway) REST API (v1)/opencollection.yml diff --git a/collections/ORDS generated API for publish/Comuni (con dimensione) - Elenco.yml b/bruno/collections/ORDS generated API for publish/Comuni (con dimensione) - Elenco.yml similarity index 100% rename from collections/ORDS generated API for publish/Comuni (con dimensione) - Elenco.yml rename to bruno/collections/ORDS generated API for publish/Comuni (con dimensione) - Elenco.yml diff --git a/collections/ORDS generated API for publish/Comuni (con territorio) - Elenco.yml b/bruno/collections/ORDS generated API for publish/Comuni (con territorio) - Elenco.yml similarity index 100% rename from collections/ORDS generated API for publish/Comuni (con territorio) - Elenco.yml rename to bruno/collections/ORDS generated API for publish/Comuni (con territorio) - Elenco.yml diff --git a/collections/ORDS generated API for publish/Province - Elenco.yml b/bruno/collections/ORDS generated API for publish/Province - Elenco.yml similarity index 100% rename from collections/ORDS generated API for publish/Province - Elenco.yml rename to bruno/collections/ORDS generated API for publish/Province - Elenco.yml diff --git a/collections/ORDS generated API for publish/Regioni - Elenco.yml b/bruno/collections/ORDS generated API for publish/Regioni - Elenco.yml similarity index 100% rename from collections/ORDS generated API for publish/Regioni - Elenco.yml rename to bruno/collections/ORDS generated API for publish/Regioni - Elenco.yml diff --git a/collections/ORDS generated API for publish/anagrafica_report_metadato_web/Retrieve a record from publish.yml b/bruno/collections/ORDS generated API for publish/anagrafica_report_metadato_web/Retrieve a record from publish.yml similarity index 100% rename from collections/ORDS generated API for publish/anagrafica_report_metadato_web/Retrieve a record from publish.yml rename to bruno/collections/ORDS generated API for publish/anagrafica_report_metadato_web/Retrieve a record from publish.yml diff --git a/collections/ORDS generated API for publish/anagrafica_report_metadato_web/folder.yml b/bruno/collections/ORDS generated API for publish/anagrafica_report_metadato_web/folder.yml similarity index 100% rename from collections/ORDS generated API for publish/anagrafica_report_metadato_web/folder.yml rename to bruno/collections/ORDS generated API for publish/anagrafica_report_metadato_web/folder.yml diff --git a/collections/ORDS generated API for publish/environments/ORDS.yml b/bruno/collections/ORDS generated API for publish/environments/ORDS.yml similarity index 100% rename from collections/ORDS generated API for publish/environments/ORDS.yml rename to bruno/collections/ORDS generated API for publish/environments/ORDS.yml diff --git a/collections/ORDS generated API for publish/opencollection.yml b/bruno/collections/ORDS generated API for publish/opencollection.yml similarity index 100% rename from collections/ORDS generated API for publish/opencollection.yml rename to bruno/collections/ORDS generated API for publish/opencollection.yml diff --git a/collections/ORDS generated API for publish/reportspooljson/Retrieve a record from publish.yml b/bruno/collections/ORDS generated API for publish/reportspooljson/Retrieve a record from publish.yml similarity index 100% rename from collections/ORDS generated API for publish/reportspooljson/Retrieve a record from publish.yml rename to bruno/collections/ORDS generated API for publish/reportspooljson/Retrieve a record from publish.yml diff --git a/collections/ORDS generated API for publish/reportspooljson/folder.yml b/bruno/collections/ORDS generated API for publish/reportspooljson/folder.yml similarity index 100% rename from collections/ORDS generated API for publish/reportspooljson/folder.yml rename to bruno/collections/ORDS generated API for publish/reportspooljson/folder.yml diff --git a/collections/ORDS generated API for publish/reportspooljsoncount/Retrieve a record from publish.yml b/bruno/collections/ORDS generated API for publish/reportspooljsoncount/Retrieve a record from publish.yml similarity index 100% rename from collections/ORDS generated API for publish/reportspooljsoncount/Retrieve a record from publish.yml rename to bruno/collections/ORDS generated API for publish/reportspooljsoncount/Retrieve a record from publish.yml diff --git a/collections/ORDS generated API for publish/reportspooljsoncount/folder.yml b/bruno/collections/ORDS generated API for publish/reportspooljsoncount/folder.yml similarity index 100% rename from collections/ORDS generated API for publish/reportspooljsoncount/folder.yml rename to bruno/collections/ORDS generated API for publish/reportspooljsoncount/folder.yml diff --git a/collections/Power Automate/Get Requests by Tag, Status and SWF.yml b/bruno/collections/Power Automate/Get Requests by Tag, Status and SWF.yml similarity index 100% rename from collections/Power Automate/Get Requests by Tag, Status and SWF.yml rename to bruno/collections/Power Automate/Get Requests by Tag, Status and SWF.yml diff --git a/collections/Power Automate/Get eF request exportTags.yml b/bruno/collections/Power Automate/Get eF request exportTags.yml similarity index 100% rename from collections/Power Automate/Get eF request exportTags.yml rename to bruno/collections/Power Automate/Get eF request exportTags.yml diff --git a/collections/Power Automate/Get eF requests.yml b/bruno/collections/Power Automate/Get eF requests.yml similarity index 100% rename from collections/Power Automate/Get eF requests.yml rename to bruno/collections/Power Automate/Get eF requests.yml diff --git a/collections/Power Automate/Power Query/Get Comune.yml b/bruno/collections/Power Automate/Power Query/Get Comune.yml similarity index 100% rename from collections/Power Automate/Power Query/Get Comune.yml rename to bruno/collections/Power Automate/Power Query/Get Comune.yml diff --git a/collections/Power Automate/Power Query/SignIn.yml b/bruno/collections/Power Automate/Power Query/SignIn.yml similarity index 100% rename from collections/Power Automate/Power Query/SignIn.yml rename to bruno/collections/Power Automate/Power Query/SignIn.yml diff --git a/collections/Power Automate/Power Query/folder.yml b/bruno/collections/Power Automate/Power Query/folder.yml similarity index 100% rename from collections/Power Automate/Power Query/folder.yml rename to bruno/collections/Power Automate/Power Query/folder.yml diff --git a/collections/Power Automate/opencollection.yml b/bruno/collections/Power Automate/opencollection.yml similarity index 100% rename from collections/Power Automate/opencollection.yml rename to bruno/collections/Power Automate/opencollection.yml diff --git a/collections/Scopus/.env.template b/bruno/collections/Scopus/.env.template similarity index 100% rename from collections/Scopus/.env.template rename to bruno/collections/Scopus/.env.template diff --git a/collections/Scopus/Get Citations.yml b/bruno/collections/Scopus/Get Citations.yml similarity index 100% rename from collections/Scopus/Get Citations.yml rename to bruno/collections/Scopus/Get Citations.yml diff --git a/collections/Scopus/environments/Scopus - Prod.yml b/bruno/collections/Scopus/environments/Scopus - Prod.yml similarity index 100% rename from collections/Scopus/environments/Scopus - Prod.yml rename to bruno/collections/Scopus/environments/Scopus - Prod.yml diff --git a/collections/Scopus/opencollection.yml b/bruno/collections/Scopus/opencollection.yml similarity index 100% rename from collections/Scopus/opencollection.yml rename to bruno/collections/Scopus/opencollection.yml diff --git a/collections/SharePoint API/opencollection.yml b/bruno/collections/SharePoint API/opencollection.yml similarity index 100% rename from collections/SharePoint API/opencollection.yml rename to bruno/collections/SharePoint API/opencollection.yml diff --git a/collections/elixForms API v2/.env.template b/bruno/collections/elixForms API v2/.env.template similarity index 100% rename from collections/elixForms API v2/.env.template rename to bruno/collections/elixForms API v2/.env.template diff --git a/collections/elixForms API v2/Authorization/Login.yml b/bruno/collections/elixForms API v2/Authorization/Login.yml similarity index 100% rename from collections/elixForms API v2/Authorization/Login.yml rename to bruno/collections/elixForms API v2/Authorization/Login.yml diff --git a/collections/elixForms API v2/Authorization/Logout.yml b/bruno/collections/elixForms API v2/Authorization/Logout.yml similarity index 100% rename from collections/elixForms API v2/Authorization/Logout.yml rename to bruno/collections/elixForms API v2/Authorization/Logout.yml diff --git a/collections/elixForms API v2/Authorization/folder.yml b/bruno/collections/elixForms API v2/Authorization/folder.yml similarity index 100% rename from collections/elixForms API v2/Authorization/folder.yml rename to bruno/collections/elixForms API v2/Authorization/folder.yml diff --git a/collections/elixForms API v2/Calendar 2.0/Get appointments.yml b/bruno/collections/elixForms API v2/Calendar 2.0/Get appointments.yml similarity index 100% rename from collections/elixForms API v2/Calendar 2.0/Get appointments.yml rename to bruno/collections/elixForms API v2/Calendar 2.0/Get appointments.yml diff --git a/collections/elixForms API v2/Calendar 2.0/Set acquired appointments.yml b/bruno/collections/elixForms API v2/Calendar 2.0/Set acquired appointments.yml similarity index 100% rename from collections/elixForms API v2/Calendar 2.0/Set acquired appointments.yml rename to bruno/collections/elixForms API v2/Calendar 2.0/Set acquired appointments.yml diff --git a/collections/elixForms API v2/Calendar 2.0/folder.yml b/bruno/collections/elixForms API v2/Calendar 2.0/folder.yml similarity index 100% rename from collections/elixForms API v2/Calendar 2.0/folder.yml rename to bruno/collections/elixForms API v2/Calendar 2.0/folder.yml diff --git a/collections/elixForms API v2/Cambio stato e-o integrazione/Acquisizione istanze elaborate da processo esterno.yml b/bruno/collections/elixForms API v2/Cambio stato e-o integrazione/Acquisizione istanze elaborate da processo esterno.yml similarity index 100% rename from collections/elixForms API v2/Cambio stato e-o integrazione/Acquisizione istanze elaborate da processo esterno.yml rename to bruno/collections/elixForms API v2/Cambio stato e-o integrazione/Acquisizione istanze elaborate da processo esterno.yml diff --git a/collections/elixForms API v2/Cambio stato e-o integrazione/Clone Request.yml b/bruno/collections/elixForms API v2/Cambio stato e-o integrazione/Clone Request.yml similarity index 100% rename from collections/elixForms API v2/Cambio stato e-o integrazione/Clone Request.yml rename to bruno/collections/elixForms API v2/Cambio stato e-o integrazione/Clone Request.yml diff --git a/collections/elixForms API v2/Cambio stato e-o integrazione/Reopen Request (OLD).yml b/bruno/collections/elixForms API v2/Cambio stato e-o integrazione/Reopen Request (OLD).yml similarity index 100% rename from collections/elixForms API v2/Cambio stato e-o integrazione/Reopen Request (OLD).yml rename to bruno/collections/elixForms API v2/Cambio stato e-o integrazione/Reopen Request (OLD).yml diff --git a/collections/elixForms API v2/Cambio stato e-o integrazione/Reopen Request.yml b/bruno/collections/elixForms API v2/Cambio stato e-o integrazione/Reopen Request.yml similarity index 100% rename from collections/elixForms API v2/Cambio stato e-o integrazione/Reopen Request.yml rename to bruno/collections/elixForms API v2/Cambio stato e-o integrazione/Reopen Request.yml diff --git a/collections/elixForms API v2/Cambio stato e-o integrazione/Set Request Status (OLD).yml b/bruno/collections/elixForms API v2/Cambio stato e-o integrazione/Set Request Status (OLD).yml similarity index 100% rename from collections/elixForms API v2/Cambio stato e-o integrazione/Set Request Status (OLD).yml rename to bruno/collections/elixForms API v2/Cambio stato e-o integrazione/Set Request Status (OLD).yml diff --git a/collections/elixForms API v2/Cambio stato e-o integrazione/Set Request Status- Register result (OLD).yml b/bruno/collections/elixForms API v2/Cambio stato e-o integrazione/Set Request Status- Register result (OLD).yml similarity index 100% rename from collections/elixForms API v2/Cambio stato e-o integrazione/Set Request Status- Register result (OLD).yml rename to bruno/collections/elixForms API v2/Cambio stato e-o integrazione/Set Request Status- Register result (OLD).yml diff --git a/collections/elixForms API v2/Cambio stato e-o integrazione/Set Request Status.yml b/bruno/collections/elixForms API v2/Cambio stato e-o integrazione/Set Request Status.yml similarity index 100% rename from collections/elixForms API v2/Cambio stato e-o integrazione/Set Request Status.yml rename to bruno/collections/elixForms API v2/Cambio stato e-o integrazione/Set Request Status.yml diff --git a/collections/elixForms API v2/Cambio stato e-o integrazione/Update Request SWF values.yml b/bruno/collections/elixForms API v2/Cambio stato e-o integrazione/Update Request SWF values.yml similarity index 100% rename from collections/elixForms API v2/Cambio stato e-o integrazione/Update Request SWF values.yml rename to bruno/collections/elixForms API v2/Cambio stato e-o integrazione/Update Request SWF values.yml diff --git a/collections/elixForms API v2/Cambio stato e-o integrazione/folder.yml b/bruno/collections/elixForms API v2/Cambio stato e-o integrazione/folder.yml similarity index 100% rename from collections/elixForms API v2/Cambio stato e-o integrazione/folder.yml rename to bruno/collections/elixForms API v2/Cambio stato e-o integrazione/folder.yml diff --git a/collections/elixForms API v2/Comunicazioni formali/Invio comunicazione formale.yml b/bruno/collections/elixForms API v2/Comunicazioni formali/Invio comunicazione formale.yml similarity index 100% rename from collections/elixForms API v2/Comunicazioni formali/Invio comunicazione formale.yml rename to bruno/collections/elixForms API v2/Comunicazioni formali/Invio comunicazione formale.yml diff --git a/collections/elixForms API v2/Comunicazioni formali/folder.yml b/bruno/collections/elixForms API v2/Comunicazioni formali/folder.yml similarity index 100% rename from collections/elixForms API v2/Comunicazioni formali/folder.yml rename to bruno/collections/elixForms API v2/Comunicazioni formali/folder.yml diff --git a/collections/elixForms API v2/EFTL processing/CCT - Determina da Proposta/Proposta CCT determina contratti conto terzi NO EFTL.yml b/bruno/collections/elixForms API v2/EFTL processing/CCT - Determina da Proposta/Proposta CCT determina contratti conto terzi NO EFTL.yml similarity index 100% rename from collections/elixForms API v2/EFTL processing/CCT - Determina da Proposta/Proposta CCT determina contratti conto terzi NO EFTL.yml rename to bruno/collections/elixForms API v2/EFTL processing/CCT - Determina da Proposta/Proposta CCT determina contratti conto terzi NO EFTL.yml diff --git a/collections/elixForms API v2/EFTL processing/CCT - Determina da Proposta/Proposta CCT determina contratti conto terzi.yml b/bruno/collections/elixForms API v2/EFTL processing/CCT - Determina da Proposta/Proposta CCT determina contratti conto terzi.yml similarity index 100% rename from collections/elixForms API v2/EFTL processing/CCT - Determina da Proposta/Proposta CCT determina contratti conto terzi.yml rename to bruno/collections/elixForms API v2/EFTL processing/CCT - Determina da Proposta/Proposta CCT determina contratti conto terzi.yml diff --git a/collections/elixForms API v2/EFTL processing/CCT - Determina da Proposta/Proposta CCT determina ex art 15 NO EFTL.yml b/bruno/collections/elixForms API v2/EFTL processing/CCT - Determina da Proposta/Proposta CCT determina ex art 15 NO EFTL.yml similarity index 100% rename from collections/elixForms API v2/EFTL processing/CCT - Determina da Proposta/Proposta CCT determina ex art 15 NO EFTL.yml rename to bruno/collections/elixForms API v2/EFTL processing/CCT - Determina da Proposta/Proposta CCT determina ex art 15 NO EFTL.yml diff --git a/collections/elixForms API v2/EFTL processing/CCT - Determina da Proposta/Proposta CCT determina ex art 15.yml b/bruno/collections/elixForms API v2/EFTL processing/CCT - Determina da Proposta/Proposta CCT determina ex art 15.yml similarity index 100% rename from collections/elixForms API v2/EFTL processing/CCT - Determina da Proposta/Proposta CCT determina ex art 15.yml rename to bruno/collections/elixForms API v2/EFTL processing/CCT - Determina da Proposta/Proposta CCT determina ex art 15.yml diff --git a/collections/elixForms API v2/EFTL processing/CCT - Determina da Proposta/Proposta CCT determina sperimentazioni cliniche NO EFTL.yml b/bruno/collections/elixForms API v2/EFTL processing/CCT - Determina da Proposta/Proposta CCT determina sperimentazioni cliniche NO EFTL.yml similarity index 100% rename from collections/elixForms API v2/EFTL processing/CCT - Determina da Proposta/Proposta CCT determina sperimentazioni cliniche NO EFTL.yml rename to bruno/collections/elixForms API v2/EFTL processing/CCT - Determina da Proposta/Proposta CCT determina sperimentazioni cliniche NO EFTL.yml diff --git a/collections/elixForms API v2/EFTL processing/CCT - Determina da Proposta/Proposta CCT determina sperimentazioni cliniche.yml b/bruno/collections/elixForms API v2/EFTL processing/CCT - Determina da Proposta/Proposta CCT determina sperimentazioni cliniche.yml similarity index 100% rename from collections/elixForms API v2/EFTL processing/CCT - Determina da Proposta/Proposta CCT determina sperimentazioni cliniche.yml rename to bruno/collections/elixForms API v2/EFTL processing/CCT - Determina da Proposta/Proposta CCT determina sperimentazioni cliniche.yml diff --git a/collections/elixForms API v2/EFTL processing/CCT - Determina da Proposta/Punto A regolamento.yml b/bruno/collections/elixForms API v2/EFTL processing/CCT - Determina da Proposta/Punto A regolamento.yml similarity index 100% rename from collections/elixForms API v2/EFTL processing/CCT - Determina da Proposta/Punto A regolamento.yml rename to bruno/collections/elixForms API v2/EFTL processing/CCT - Determina da Proposta/Punto A regolamento.yml diff --git a/collections/elixForms API v2/EFTL processing/CCT - Determina da Proposta/Punto B regolamento.yml b/bruno/collections/elixForms API v2/EFTL processing/CCT - Determina da Proposta/Punto B regolamento.yml similarity index 100% rename from collections/elixForms API v2/EFTL processing/CCT - Determina da Proposta/Punto B regolamento.yml rename to bruno/collections/elixForms API v2/EFTL processing/CCT - Determina da Proposta/Punto B regolamento.yml diff --git a/collections/elixForms API v2/EFTL processing/CCT - Determina da Proposta/folder.yml b/bruno/collections/elixForms API v2/EFTL processing/CCT - Determina da Proposta/folder.yml similarity index 100% rename from collections/elixForms API v2/EFTL processing/CCT - Determina da Proposta/folder.yml rename to bruno/collections/elixForms API v2/EFTL processing/CCT - Determina da Proposta/folder.yml diff --git a/collections/elixForms API v2/EFTL processing/CCT - Liquidazione Compensi/DSAN/Anno corrente.yml b/bruno/collections/elixForms API v2/EFTL processing/CCT - Liquidazione Compensi/DSAN/Anno corrente.yml similarity index 100% rename from collections/elixForms API v2/EFTL processing/CCT - Liquidazione Compensi/DSAN/Anno corrente.yml rename to bruno/collections/elixForms API v2/EFTL processing/CCT - Liquidazione Compensi/DSAN/Anno corrente.yml diff --git a/collections/elixForms API v2/EFTL processing/CCT - Liquidazione Compensi/DSAN/Elenco Contraenti in formato CSV DSAN.yml b/bruno/collections/elixForms API v2/EFTL processing/CCT - Liquidazione Compensi/DSAN/Elenco Contraenti in formato CSV DSAN.yml similarity index 100% rename from collections/elixForms API v2/EFTL processing/CCT - Liquidazione Compensi/DSAN/Elenco Contraenti in formato CSV DSAN.yml rename to bruno/collections/elixForms API v2/EFTL processing/CCT - Liquidazione Compensi/DSAN/Elenco Contraenti in formato CSV DSAN.yml diff --git a/collections/elixForms API v2/EFTL processing/CCT - Liquidazione Compensi/DSAN/Elenco RS in formato CSV DSAN.yml b/bruno/collections/elixForms API v2/EFTL processing/CCT - Liquidazione Compensi/DSAN/Elenco RS in formato CSV DSAN.yml similarity index 100% rename from collections/elixForms API v2/EFTL processing/CCT - Liquidazione Compensi/DSAN/Elenco RS in formato CSV DSAN.yml rename to bruno/collections/elixForms API v2/EFTL processing/CCT - Liquidazione Compensi/DSAN/Elenco RS in formato CSV DSAN.yml diff --git a/collections/elixForms API v2/EFTL processing/CCT - Liquidazione Compensi/DSAN/Inserimento Ore Dentro - Calcolo importo equivalente.yml b/bruno/collections/elixForms API v2/EFTL processing/CCT - Liquidazione Compensi/DSAN/Inserimento Ore Dentro - Calcolo importo equivalente.yml similarity index 100% rename from collections/elixForms API v2/EFTL processing/CCT - Liquidazione Compensi/DSAN/Inserimento Ore Dentro - Calcolo importo equivalente.yml rename to bruno/collections/elixForms API v2/EFTL processing/CCT - Liquidazione Compensi/DSAN/Inserimento Ore Dentro - Calcolo importo equivalente.yml diff --git a/collections/elixForms API v2/EFTL processing/CCT - Liquidazione Compensi/DSAN/Inserimento Ore Dentro - Dati attività CSV.yml b/bruno/collections/elixForms API v2/EFTL processing/CCT - Liquidazione Compensi/DSAN/Inserimento Ore Dentro - Dati attività CSV.yml similarity index 100% rename from collections/elixForms API v2/EFTL processing/CCT - Liquidazione Compensi/DSAN/Inserimento Ore Dentro - Dati attività CSV.yml rename to bruno/collections/elixForms API v2/EFTL processing/CCT - Liquidazione Compensi/DSAN/Inserimento Ore Dentro - Dati attività CSV.yml diff --git a/collections/elixForms API v2/EFTL processing/CCT - Liquidazione Compensi/DSAN/Inserimento Ore Fuori - Calcolo importo equivalente.yml b/bruno/collections/elixForms API v2/EFTL processing/CCT - Liquidazione Compensi/DSAN/Inserimento Ore Fuori - Calcolo importo equivalente.yml similarity index 100% rename from collections/elixForms API v2/EFTL processing/CCT - Liquidazione Compensi/DSAN/Inserimento Ore Fuori - Calcolo importo equivalente.yml rename to bruno/collections/elixForms API v2/EFTL processing/CCT - Liquidazione Compensi/DSAN/Inserimento Ore Fuori - Calcolo importo equivalente.yml diff --git a/collections/elixForms API v2/EFTL processing/CCT - Liquidazione Compensi/DSAN/Inserimento Ore Fuori - Dati attività CSV copy.yml b/bruno/collections/elixForms API v2/EFTL processing/CCT - Liquidazione Compensi/DSAN/Inserimento Ore Fuori - Dati attività CSV copy.yml similarity index 100% rename from collections/elixForms API v2/EFTL processing/CCT - Liquidazione Compensi/DSAN/Inserimento Ore Fuori - Dati attività CSV copy.yml rename to bruno/collections/elixForms API v2/EFTL processing/CCT - Liquidazione Compensi/DSAN/Inserimento Ore Fuori - Dati attività CSV copy.yml diff --git a/collections/elixForms API v2/EFTL processing/CCT - Liquidazione Compensi/DSAN/Limiti - Calcolo MIN ore dentro orario.yml b/bruno/collections/elixForms API v2/EFTL processing/CCT - Liquidazione Compensi/DSAN/Limiti - Calcolo MIN ore dentro orario.yml similarity index 100% rename from collections/elixForms API v2/EFTL processing/CCT - Liquidazione Compensi/DSAN/Limiti - Calcolo MIN ore dentro orario.yml rename to bruno/collections/elixForms API v2/EFTL processing/CCT - Liquidazione Compensi/DSAN/Limiti - Calcolo MIN ore dentro orario.yml diff --git a/collections/elixForms API v2/EFTL processing/CCT - Liquidazione Compensi/DSAN/Limiti - Calcolo MIN ore fuori orario.yml b/bruno/collections/elixForms API v2/EFTL processing/CCT - Liquidazione Compensi/DSAN/Limiti - Calcolo MIN ore fuori orario.yml similarity index 100% rename from collections/elixForms API v2/EFTL processing/CCT - Liquidazione Compensi/DSAN/Limiti - Calcolo MIN ore fuori orario.yml rename to bruno/collections/elixForms API v2/EFTL processing/CCT - Liquidazione Compensi/DSAN/Limiti - Calcolo MIN ore fuori orario.yml diff --git a/collections/elixForms API v2/EFTL processing/CCT - Liquidazione Compensi/DSAN/Limiti - Indicazione MAX annuale ore dentro orario.yml b/bruno/collections/elixForms API v2/EFTL processing/CCT - Liquidazione Compensi/DSAN/Limiti - Indicazione MAX annuale ore dentro orario.yml similarity index 100% rename from collections/elixForms API v2/EFTL processing/CCT - Liquidazione Compensi/DSAN/Limiti - Indicazione MAX annuale ore dentro orario.yml rename to bruno/collections/elixForms API v2/EFTL processing/CCT - Liquidazione Compensi/DSAN/Limiti - Indicazione MAX annuale ore dentro orario.yml diff --git a/collections/elixForms API v2/EFTL processing/CCT - Liquidazione Compensi/DSAN/Limiti - Indicazione MAX annuale ore fuori orario.yml b/bruno/collections/elixForms API v2/EFTL processing/CCT - Liquidazione Compensi/DSAN/Limiti - Indicazione MAX annuale ore fuori orario.yml similarity index 100% rename from collections/elixForms API v2/EFTL processing/CCT - Liquidazione Compensi/DSAN/Limiti - Indicazione MAX annuale ore fuori orario.yml rename to bruno/collections/elixForms API v2/EFTL processing/CCT - Liquidazione Compensi/DSAN/Limiti - Indicazione MAX annuale ore fuori orario.yml diff --git a/collections/elixForms API v2/EFTL processing/CCT - Liquidazione Compensi/DSAN/Richiedente - Calcolo ore equivalenti.yml b/bruno/collections/elixForms API v2/EFTL processing/CCT - Liquidazione Compensi/DSAN/Richiedente - Calcolo ore equivalenti.yml similarity index 100% rename from collections/elixForms API v2/EFTL processing/CCT - Liquidazione Compensi/DSAN/Richiedente - Calcolo ore equivalenti.yml rename to bruno/collections/elixForms API v2/EFTL processing/CCT - Liquidazione Compensi/DSAN/Richiedente - Calcolo ore equivalenti.yml diff --git a/collections/elixForms API v2/EFTL processing/CCT - Liquidazione Compensi/DSAN/Richiedente - Check ammesso compilazione.yml b/bruno/collections/elixForms API v2/EFTL processing/CCT - Liquidazione Compensi/DSAN/Richiedente - Check ammesso compilazione.yml similarity index 100% rename from collections/elixForms API v2/EFTL processing/CCT - Liquidazione Compensi/DSAN/Richiedente - Check ammesso compilazione.yml rename to bruno/collections/elixForms API v2/EFTL processing/CCT - Liquidazione Compensi/DSAN/Richiedente - Check ammesso compilazione.yml diff --git a/collections/elixForms API v2/EFTL processing/CCT - Liquidazione Compensi/DSAN/Richiedente - Check ruolo per compilazione.yml b/bruno/collections/elixForms API v2/EFTL processing/CCT - Liquidazione Compensi/DSAN/Richiedente - Check ruolo per compilazione.yml similarity index 100% rename from collections/elixForms API v2/EFTL processing/CCT - Liquidazione Compensi/DSAN/Richiedente - Check ruolo per compilazione.yml rename to bruno/collections/elixForms API v2/EFTL processing/CCT - Liquidazione Compensi/DSAN/Richiedente - Check ruolo per compilazione.yml diff --git a/collections/elixForms API v2/EFTL processing/CCT - Liquidazione Compensi/DSAN/Richiedente - Importo ripartizione da Proposta.yml b/bruno/collections/elixForms API v2/EFTL processing/CCT - Liquidazione Compensi/DSAN/Richiedente - Importo ripartizione da Proposta.yml similarity index 100% rename from collections/elixForms API v2/EFTL processing/CCT - Liquidazione Compensi/DSAN/Richiedente - Importo ripartizione da Proposta.yml rename to bruno/collections/elixForms API v2/EFTL processing/CCT - Liquidazione Compensi/DSAN/Richiedente - Importo ripartizione da Proposta.yml diff --git a/collections/elixForms API v2/EFTL processing/CCT - Liquidazione Compensi/DSAN/folder.yml b/bruno/collections/elixForms API v2/EFTL processing/CCT - Liquidazione Compensi/DSAN/folder.yml similarity index 100% rename from collections/elixForms API v2/EFTL processing/CCT - Liquidazione Compensi/DSAN/folder.yml rename to bruno/collections/elixForms API v2/EFTL processing/CCT - Liquidazione Compensi/DSAN/folder.yml diff --git a/collections/elixForms API v2/EFTL processing/CCT - Liquidazione Compensi/Proposta/Campi conferma - Codice struttura assegnazione.yml b/bruno/collections/elixForms API v2/EFTL processing/CCT - Liquidazione Compensi/Proposta/Campi conferma - Codice struttura assegnazione.yml similarity index 100% rename from collections/elixForms API v2/EFTL processing/CCT - Liquidazione Compensi/Proposta/Campi conferma - Codice struttura assegnazione.yml rename to bruno/collections/elixForms API v2/EFTL processing/CCT - Liquidazione Compensi/Proposta/Campi conferma - Codice struttura assegnazione.yml diff --git a/collections/elixForms API v2/EFTL processing/CCT - Liquidazione Compensi/Proposta/Campi conferma - Codice struttura protocollo.yml b/bruno/collections/elixForms API v2/EFTL processing/CCT - Liquidazione Compensi/Proposta/Campi conferma - Codice struttura protocollo.yml similarity index 100% rename from collections/elixForms API v2/EFTL processing/CCT - Liquidazione Compensi/Proposta/Campi conferma - Codice struttura protocollo.yml rename to bruno/collections/elixForms API v2/EFTL processing/CCT - Liquidazione Compensi/Proposta/Campi conferma - Codice struttura protocollo.yml diff --git a/collections/elixForms API v2/EFTL processing/CCT - Liquidazione Compensi/Proposta/Check Richiedente IN Responsabili Scientifici.yml b/bruno/collections/elixForms API v2/EFTL processing/CCT - Liquidazione Compensi/Proposta/Check Richiedente IN Responsabili Scientifici.yml similarity index 100% rename from collections/elixForms API v2/EFTL processing/CCT - Liquidazione Compensi/Proposta/Check Richiedente IN Responsabili Scientifici.yml rename to bruno/collections/elixForms API v2/EFTL processing/CCT - Liquidazione Compensi/Proposta/Check Richiedente IN Responsabili Scientifici.yml diff --git a/collections/elixForms API v2/EFTL processing/CCT - Liquidazione Compensi/Proposta/Codici fiscali ripartizioni.yml b/bruno/collections/elixForms API v2/EFTL processing/CCT - Liquidazione Compensi/Proposta/Codici fiscali ripartizioni.yml similarity index 100% rename from collections/elixForms API v2/EFTL processing/CCT - Liquidazione Compensi/Proposta/Codici fiscali ripartizioni.yml rename to bruno/collections/elixForms API v2/EFTL processing/CCT - Liquidazione Compensi/Proposta/Codici fiscali ripartizioni.yml diff --git a/collections/elixForms API v2/EFTL processing/CCT - Liquidazione Compensi/Proposta/Elenco Contraenti in formato CSV.yml b/bruno/collections/elixForms API v2/EFTL processing/CCT - Liquidazione Compensi/Proposta/Elenco Contraenti in formato CSV.yml similarity index 100% rename from collections/elixForms API v2/EFTL processing/CCT - Liquidazione Compensi/Proposta/Elenco Contraenti in formato CSV.yml rename to bruno/collections/elixForms API v2/EFTL processing/CCT - Liquidazione Compensi/Proposta/Elenco Contraenti in formato CSV.yml diff --git a/collections/elixForms API v2/EFTL processing/CCT - Liquidazione Compensi/Proposta/Elenco Partecipanti - Array CF altri.yml b/bruno/collections/elixForms API v2/EFTL processing/CCT - Liquidazione Compensi/Proposta/Elenco Partecipanti - Array CF altri.yml similarity index 100% rename from collections/elixForms API v2/EFTL processing/CCT - Liquidazione Compensi/Proposta/Elenco Partecipanti - Array CF altri.yml rename to bruno/collections/elixForms API v2/EFTL processing/CCT - Liquidazione Compensi/Proposta/Elenco Partecipanti - Array CF altri.yml diff --git a/collections/elixForms API v2/EFTL processing/CCT - Liquidazione Compensi/Proposta/Elenco Partecipanti - Array CF docenti.yml b/bruno/collections/elixForms API v2/EFTL processing/CCT - Liquidazione Compensi/Proposta/Elenco Partecipanti - Array CF docenti.yml similarity index 100% rename from collections/elixForms API v2/EFTL processing/CCT - Liquidazione Compensi/Proposta/Elenco Partecipanti - Array CF docenti.yml rename to bruno/collections/elixForms API v2/EFTL processing/CCT - Liquidazione Compensi/Proposta/Elenco Partecipanti - Array CF docenti.yml diff --git a/collections/elixForms API v2/EFTL processing/CCT - Liquidazione Compensi/Proposta/Elenco Partecipanti - Dropdown con chiave.yml b/bruno/collections/elixForms API v2/EFTL processing/CCT - Liquidazione Compensi/Proposta/Elenco Partecipanti - Dropdown con chiave.yml similarity index 100% rename from collections/elixForms API v2/EFTL processing/CCT - Liquidazione Compensi/Proposta/Elenco Partecipanti - Dropdown con chiave.yml rename to bruno/collections/elixForms API v2/EFTL processing/CCT - Liquidazione Compensi/Proposta/Elenco Partecipanti - Dropdown con chiave.yml diff --git a/collections/elixForms API v2/EFTL processing/CCT - Liquidazione Compensi/Proposta/Elenco RS in formato CSV.yml b/bruno/collections/elixForms API v2/EFTL processing/CCT - Liquidazione Compensi/Proposta/Elenco RS in formato CSV.yml similarity index 100% rename from collections/elixForms API v2/EFTL processing/CCT - Liquidazione Compensi/Proposta/Elenco RS in formato CSV.yml rename to bruno/collections/elixForms API v2/EFTL processing/CCT - Liquidazione Compensi/Proposta/Elenco RS in formato CSV.yml diff --git a/collections/elixForms API v2/EFTL processing/CCT - Liquidazione Compensi/Proposta/Nominativo completo RS proponente.yml b/bruno/collections/elixForms API v2/EFTL processing/CCT - Liquidazione Compensi/Proposta/Nominativo completo RS proponente.yml similarity index 100% rename from collections/elixForms API v2/EFTL processing/CCT - Liquidazione Compensi/Proposta/Nominativo completo RS proponente.yml rename to bruno/collections/elixForms API v2/EFTL processing/CCT - Liquidazione Compensi/Proposta/Nominativo completo RS proponente.yml diff --git a/collections/elixForms API v2/EFTL processing/CCT - Liquidazione Compensi/Proposta/Notifiche email partecipanti - Body.yml b/bruno/collections/elixForms API v2/EFTL processing/CCT - Liquidazione Compensi/Proposta/Notifiche email partecipanti - Body.yml similarity index 100% rename from collections/elixForms API v2/EFTL processing/CCT - Liquidazione Compensi/Proposta/Notifiche email partecipanti - Body.yml rename to bruno/collections/elixForms API v2/EFTL processing/CCT - Liquidazione Compensi/Proposta/Notifiche email partecipanti - Body.yml diff --git a/collections/elixForms API v2/EFTL processing/CCT - Liquidazione Compensi/Proposta/Notifiche email partecipanti - Subject.yml b/bruno/collections/elixForms API v2/EFTL processing/CCT - Liquidazione Compensi/Proposta/Notifiche email partecipanti - Subject.yml similarity index 100% rename from collections/elixForms API v2/EFTL processing/CCT - Liquidazione Compensi/Proposta/Notifiche email partecipanti - Subject.yml rename to bruno/collections/elixForms API v2/EFTL processing/CCT - Liquidazione Compensi/Proposta/Notifiche email partecipanti - Subject.yml diff --git a/collections/elixForms API v2/EFTL processing/CCT - Liquidazione Compensi/Proposta/Partecipanti - Body NO fancy HTML.yml b/bruno/collections/elixForms API v2/EFTL processing/CCT - Liquidazione Compensi/Proposta/Partecipanti - Body NO fancy HTML.yml similarity index 100% rename from collections/elixForms API v2/EFTL processing/CCT - Liquidazione Compensi/Proposta/Partecipanti - Body NO fancy HTML.yml rename to bruno/collections/elixForms API v2/EFTL processing/CCT - Liquidazione Compensi/Proposta/Partecipanti - Body NO fancy HTML.yml diff --git a/collections/elixForms API v2/EFTL processing/CCT - Liquidazione Compensi/Proposta/Partecipanti - Body.yml b/bruno/collections/elixForms API v2/EFTL processing/CCT - Liquidazione Compensi/Proposta/Partecipanti - Body.yml similarity index 100% rename from collections/elixForms API v2/EFTL processing/CCT - Liquidazione Compensi/Proposta/Partecipanti - Body.yml rename to bruno/collections/elixForms API v2/EFTL processing/CCT - Liquidazione Compensi/Proposta/Partecipanti - Body.yml diff --git a/collections/elixForms API v2/EFTL processing/CCT - Liquidazione Compensi/Proposta/Partecipanti - CF per verifica DSAN.yml b/bruno/collections/elixForms API v2/EFTL processing/CCT - Liquidazione Compensi/Proposta/Partecipanti - CF per verifica DSAN.yml similarity index 100% rename from collections/elixForms API v2/EFTL processing/CCT - Liquidazione Compensi/Proposta/Partecipanti - CF per verifica DSAN.yml rename to bruno/collections/elixForms API v2/EFTL processing/CCT - Liquidazione Compensi/Proposta/Partecipanti - CF per verifica DSAN.yml diff --git a/collections/elixForms API v2/EFTL processing/CCT - Liquidazione Compensi/Proposta/Partecipanti - Email.yml b/bruno/collections/elixForms API v2/EFTL processing/CCT - Liquidazione Compensi/Proposta/Partecipanti - Email.yml similarity index 100% rename from collections/elixForms API v2/EFTL processing/CCT - Liquidazione Compensi/Proposta/Partecipanti - Email.yml rename to bruno/collections/elixForms API v2/EFTL processing/CCT - Liquidazione Compensi/Proposta/Partecipanti - Email.yml diff --git a/collections/elixForms API v2/EFTL processing/CCT - Liquidazione Compensi/Proposta/Partecipanti - Importo PTA.yml b/bruno/collections/elixForms API v2/EFTL processing/CCT - Liquidazione Compensi/Proposta/Partecipanti - Importo PTA.yml similarity index 100% rename from collections/elixForms API v2/EFTL processing/CCT - Liquidazione Compensi/Proposta/Partecipanti - Importo PTA.yml rename to bruno/collections/elixForms API v2/EFTL processing/CCT - Liquidazione Compensi/Proposta/Partecipanti - Importo PTA.yml diff --git a/collections/elixForms API v2/EFTL processing/CCT - Liquidazione Compensi/Proposta/Partecipanti - Importo docente.yml b/bruno/collections/elixForms API v2/EFTL processing/CCT - Liquidazione Compensi/Proposta/Partecipanti - Importo docente.yml similarity index 100% rename from collections/elixForms API v2/EFTL processing/CCT - Liquidazione Compensi/Proposta/Partecipanti - Importo docente.yml rename to bruno/collections/elixForms API v2/EFTL processing/CCT - Liquidazione Compensi/Proposta/Partecipanti - Importo docente.yml diff --git a/collections/elixForms API v2/EFTL processing/CCT - Liquidazione Compensi/Proposta/Partecipanti - Riga dati completi ripartizione.yml b/bruno/collections/elixForms API v2/EFTL processing/CCT - Liquidazione Compensi/Proposta/Partecipanti - Riga dati completi ripartizione.yml similarity index 100% rename from collections/elixForms API v2/EFTL processing/CCT - Liquidazione Compensi/Proposta/Partecipanti - Riga dati completi ripartizione.yml rename to bruno/collections/elixForms API v2/EFTL processing/CCT - Liquidazione Compensi/Proposta/Partecipanti - Riga dati completi ripartizione.yml diff --git a/collections/elixForms API v2/EFTL processing/CCT - Liquidazione Compensi/Proposta/Partecipanti - Subject.yml b/bruno/collections/elixForms API v2/EFTL processing/CCT - Liquidazione Compensi/Proposta/Partecipanti - Subject.yml similarity index 100% rename from collections/elixForms API v2/EFTL processing/CCT - Liquidazione Compensi/Proposta/Partecipanti - Subject.yml rename to bruno/collections/elixForms API v2/EFTL processing/CCT - Liquidazione Compensi/Proposta/Partecipanti - Subject.yml diff --git a/collections/elixForms API v2/EFTL processing/CCT - Liquidazione Compensi/Proposta/Partecipanti - hasDSAN.yml b/bruno/collections/elixForms API v2/EFTL processing/CCT - Liquidazione Compensi/Proposta/Partecipanti - hasDSAN.yml similarity index 100% rename from collections/elixForms API v2/EFTL processing/CCT - Liquidazione Compensi/Proposta/Partecipanti - hasDSAN.yml rename to bruno/collections/elixForms API v2/EFTL processing/CCT - Liquidazione Compensi/Proposta/Partecipanti - hasDSAN.yml diff --git a/collections/elixForms API v2/EFTL processing/CCT - Liquidazione Compensi/Proposta/Recupero importo richiedente da proposta.yml b/bruno/collections/elixForms API v2/EFTL processing/CCT - Liquidazione Compensi/Proposta/Recupero importo richiedente da proposta.yml similarity index 100% rename from collections/elixForms API v2/EFTL processing/CCT - Liquidazione Compensi/Proposta/Recupero importo richiedente da proposta.yml rename to bruno/collections/elixForms API v2/EFTL processing/CCT - Liquidazione Compensi/Proposta/Recupero importo richiedente da proposta.yml diff --git a/collections/elixForms API v2/EFTL processing/CCT - Liquidazione Compensi/Proposta/Ripartizioni - Count da form partecipante.yml b/bruno/collections/elixForms API v2/EFTL processing/CCT - Liquidazione Compensi/Proposta/Ripartizioni - Count da form partecipante.yml similarity index 100% rename from collections/elixForms API v2/EFTL processing/CCT - Liquidazione Compensi/Proposta/Ripartizioni - Count da form partecipante.yml rename to bruno/collections/elixForms API v2/EFTL processing/CCT - Liquidazione Compensi/Proposta/Ripartizioni - Count da form partecipante.yml diff --git a/collections/elixForms API v2/EFTL processing/CCT - Liquidazione Compensi/Proposta/Tabella HTML ripartizioni FOR ADVANCED.yml b/bruno/collections/elixForms API v2/EFTL processing/CCT - Liquidazione Compensi/Proposta/Tabella HTML ripartizioni FOR ADVANCED.yml similarity index 100% rename from collections/elixForms API v2/EFTL processing/CCT - Liquidazione Compensi/Proposta/Tabella HTML ripartizioni FOR ADVANCED.yml rename to bruno/collections/elixForms API v2/EFTL processing/CCT - Liquidazione Compensi/Proposta/Tabella HTML ripartizioni FOR ADVANCED.yml diff --git a/collections/elixForms API v2/EFTL processing/CCT - Liquidazione Compensi/Proposta/Tabella HTML ripartizioni FOR.yml b/bruno/collections/elixForms API v2/EFTL processing/CCT - Liquidazione Compensi/Proposta/Tabella HTML ripartizioni FOR.yml similarity index 100% rename from collections/elixForms API v2/EFTL processing/CCT - Liquidazione Compensi/Proposta/Tabella HTML ripartizioni FOR.yml rename to bruno/collections/elixForms API v2/EFTL processing/CCT - Liquidazione Compensi/Proposta/Tabella HTML ripartizioni FOR.yml diff --git a/collections/elixForms API v2/EFTL processing/CCT - Liquidazione Compensi/Proposta/Tabella HTML ripartizioni WHILE.yml b/bruno/collections/elixForms API v2/EFTL processing/CCT - Liquidazione Compensi/Proposta/Tabella HTML ripartizioni WHILE.yml similarity index 100% rename from collections/elixForms API v2/EFTL processing/CCT - Liquidazione Compensi/Proposta/Tabella HTML ripartizioni WHILE.yml rename to bruno/collections/elixForms API v2/EFTL processing/CCT - Liquidazione Compensi/Proposta/Tabella HTML ripartizioni WHILE.yml diff --git a/collections/elixForms API v2/EFTL processing/CCT - Liquidazione Compensi/Proposta/elixPro - Recupero importi inseriti.yml b/bruno/collections/elixForms API v2/EFTL processing/CCT - Liquidazione Compensi/Proposta/elixPro - Recupero importi inseriti.yml similarity index 100% rename from collections/elixForms API v2/EFTL processing/CCT - Liquidazione Compensi/Proposta/elixPro - Recupero importi inseriti.yml rename to bruno/collections/elixForms API v2/EFTL processing/CCT - Liquidazione Compensi/Proposta/elixPro - Recupero importi inseriti.yml diff --git a/collections/elixForms API v2/EFTL processing/CCT - Liquidazione Compensi/Proposta/elixPro - Template Delibera ONLYTABLE.yml b/bruno/collections/elixForms API v2/EFTL processing/CCT - Liquidazione Compensi/Proposta/elixPro - Template Delibera ONLYTABLE.yml similarity index 100% rename from collections/elixForms API v2/EFTL processing/CCT - Liquidazione Compensi/Proposta/elixPro - Template Delibera ONLYTABLE.yml rename to bruno/collections/elixForms API v2/EFTL processing/CCT - Liquidazione Compensi/Proposta/elixPro - Template Delibera ONLYTABLE.yml diff --git a/collections/elixForms API v2/EFTL processing/CCT - Liquidazione Compensi/Proposta/elixPro - Template Delibera.yml b/bruno/collections/elixForms API v2/EFTL processing/CCT - Liquidazione Compensi/Proposta/elixPro - Template Delibera.yml similarity index 100% rename from collections/elixForms API v2/EFTL processing/CCT - Liquidazione Compensi/Proposta/elixPro - Template Delibera.yml rename to bruno/collections/elixForms API v2/EFTL processing/CCT - Liquidazione Compensi/Proposta/elixPro - Template Delibera.yml diff --git a/collections/elixForms API v2/EFTL processing/CCT - Liquidazione Compensi/Proposta/folder.yml b/bruno/collections/elixForms API v2/EFTL processing/CCT - Liquidazione Compensi/Proposta/folder.yml similarity index 100% rename from collections/elixForms API v2/EFTL processing/CCT - Liquidazione Compensi/Proposta/folder.yml rename to bruno/collections/elixForms API v2/EFTL processing/CCT - Liquidazione Compensi/Proposta/folder.yml diff --git a/collections/elixForms API v2/EFTL processing/CCT - Liquidazione Compensi/folder.yml b/bruno/collections/elixForms API v2/EFTL processing/CCT - Liquidazione Compensi/folder.yml similarity index 100% rename from collections/elixForms API v2/EFTL processing/CCT - Liquidazione Compensi/folder.yml rename to bruno/collections/elixForms API v2/EFTL processing/CCT - Liquidazione Compensi/folder.yml diff --git a/collections/elixForms API v2/EFTL processing/CCT - Proposta Operatore/Calcolo D.1.3 5% con virgole.yml b/bruno/collections/elixForms API v2/EFTL processing/CCT - Proposta Operatore/Calcolo D.1.3 5% con virgole.yml similarity index 100% rename from collections/elixForms API v2/EFTL processing/CCT - Proposta Operatore/Calcolo D.1.3 5% con virgole.yml rename to bruno/collections/elixForms API v2/EFTL processing/CCT - Proposta Operatore/Calcolo D.1.3 5% con virgole.yml diff --git a/collections/elixForms API v2/EFTL processing/CCT - Proposta Operatore/Calcolo D.1.3 con virgole.yml b/bruno/collections/elixForms API v2/EFTL processing/CCT - Proposta Operatore/Calcolo D.1.3 con virgole.yml similarity index 100% rename from collections/elixForms API v2/EFTL processing/CCT - Proposta Operatore/Calcolo D.1.3 con virgole.yml rename to bruno/collections/elixForms API v2/EFTL processing/CCT - Proposta Operatore/Calcolo D.1.3 con virgole.yml diff --git a/collections/elixForms API v2/EFTL processing/CCT - Proposta Operatore/Codice Contratto con caratteri strani.yml b/bruno/collections/elixForms API v2/EFTL processing/CCT - Proposta Operatore/Codice Contratto con caratteri strani.yml similarity index 100% rename from collections/elixForms API v2/EFTL processing/CCT - Proposta Operatore/Codice Contratto con caratteri strani.yml rename to bruno/collections/elixForms API v2/EFTL processing/CCT - Proposta Operatore/Codice Contratto con caratteri strani.yml diff --git a/collections/elixForms API v2/EFTL processing/CCT - Proposta Operatore/Contratto IS economico.yml b/bruno/collections/elixForms API v2/EFTL processing/CCT - Proposta Operatore/Contratto IS economico.yml similarity index 100% rename from collections/elixForms API v2/EFTL processing/CCT - Proposta Operatore/Contratto IS economico.yml rename to bruno/collections/elixForms API v2/EFTL processing/CCT - Proposta Operatore/Contratto IS economico.yml diff --git a/collections/elixForms API v2/EFTL processing/CCT - Proposta Operatore/Elenco Contraenti CSV (nominativo).yml b/bruno/collections/elixForms API v2/EFTL processing/CCT - Proposta Operatore/Elenco Contraenti CSV (nominativo).yml similarity index 100% rename from collections/elixForms API v2/EFTL processing/CCT - Proposta Operatore/Elenco Contraenti CSV (nominativo).yml rename to bruno/collections/elixForms API v2/EFTL processing/CCT - Proposta Operatore/Elenco Contraenti CSV (nominativo).yml diff --git a/collections/elixForms API v2/EFTL processing/CCT - Proposta Operatore/Elenco RS CSV (cognome nome).yml b/bruno/collections/elixForms API v2/EFTL processing/CCT - Proposta Operatore/Elenco RS CSV (cognome nome).yml similarity index 100% rename from collections/elixForms API v2/EFTL processing/CCT - Proposta Operatore/Elenco RS CSV (cognome nome).yml rename to bruno/collections/elixForms API v2/EFTL processing/CCT - Proposta Operatore/Elenco RS CSV (cognome nome).yml diff --git a/collections/elixForms API v2/EFTL processing/CCT - Proposta Operatore/Elenco contraenti formattati.yml b/bruno/collections/elixForms API v2/EFTL processing/CCT - Proposta Operatore/Elenco contraenti formattati.yml similarity index 100% rename from collections/elixForms API v2/EFTL processing/CCT - Proposta Operatore/Elenco contraenti formattati.yml rename to bruno/collections/elixForms API v2/EFTL processing/CCT - Proposta Operatore/Elenco contraenti formattati.yml diff --git a/collections/elixForms API v2/EFTL processing/CCT - Proposta Operatore/Fascicolo e documento - Nuovo formato.yml b/bruno/collections/elixForms API v2/EFTL processing/CCT - Proposta Operatore/Fascicolo e documento - Nuovo formato.yml similarity index 100% rename from collections/elixForms API v2/EFTL processing/CCT - Proposta Operatore/Fascicolo e documento - Nuovo formato.yml rename to bruno/collections/elixForms API v2/EFTL processing/CCT - Proposta Operatore/Fascicolo e documento - Nuovo formato.yml diff --git a/collections/elixForms API v2/EFTL processing/CCT - Proposta Operatore/Fascicolo e documento su Titulus.yml b/bruno/collections/elixForms API v2/EFTL processing/CCT - Proposta Operatore/Fascicolo e documento su Titulus.yml similarity index 100% rename from collections/elixForms API v2/EFTL processing/CCT - Proposta Operatore/Fascicolo e documento su Titulus.yml rename to bruno/collections/elixForms API v2/EFTL processing/CCT - Proposta Operatore/Fascicolo e documento su Titulus.yml diff --git a/collections/elixForms API v2/EFTL processing/CCT - Proposta Operatore/Messaggio ritenute massime.yml b/bruno/collections/elixForms API v2/EFTL processing/CCT - Proposta Operatore/Messaggio ritenute massime.yml similarity index 100% rename from collections/elixForms API v2/EFTL processing/CCT - Proposta Operatore/Messaggio ritenute massime.yml rename to bruno/collections/elixForms API v2/EFTL processing/CCT - Proposta Operatore/Messaggio ritenute massime.yml diff --git a/collections/elixForms API v2/EFTL processing/CCT - Proposta Operatore/folder.yml b/bruno/collections/elixForms API v2/EFTL processing/CCT - Proposta Operatore/folder.yml similarity index 100% rename from collections/elixForms API v2/EFTL processing/CCT - Proposta Operatore/folder.yml rename to bruno/collections/elixForms API v2/EFTL processing/CCT - Proposta Operatore/folder.yml diff --git a/collections/elixForms API v2/EFTL processing/MOD A13 Richiesta Certificato/Gestione Istanze - Elenco carriere inserite.yml b/bruno/collections/elixForms API v2/EFTL processing/MOD A13 Richiesta Certificato/Gestione Istanze - Elenco carriere inserite.yml similarity index 100% rename from collections/elixForms API v2/EFTL processing/MOD A13 Richiesta Certificato/Gestione Istanze - Elenco carriere inserite.yml rename to bruno/collections/elixForms API v2/EFTL processing/MOD A13 Richiesta Certificato/Gestione Istanze - Elenco carriere inserite.yml diff --git a/collections/elixForms API v2/EFTL processing/MOD A13 Richiesta Certificato/Notifiche email - Elenco carriere e certificati.yml b/bruno/collections/elixForms API v2/EFTL processing/MOD A13 Richiesta Certificato/Notifiche email - Elenco carriere e certificati.yml similarity index 100% rename from collections/elixForms API v2/EFTL processing/MOD A13 Richiesta Certificato/Notifiche email - Elenco carriere e certificati.yml rename to bruno/collections/elixForms API v2/EFTL processing/MOD A13 Richiesta Certificato/Notifiche email - Elenco carriere e certificati.yml diff --git a/collections/elixForms API v2/EFTL processing/MOD A13 Richiesta Certificato/folder.yml b/bruno/collections/elixForms API v2/EFTL processing/MOD A13 Richiesta Certificato/folder.yml similarity index 100% rename from collections/elixForms API v2/EFTL processing/MOD A13 Richiesta Certificato/folder.yml rename to bruno/collections/elixForms API v2/EFTL processing/MOD A13 Richiesta Certificato/folder.yml diff --git a/collections/elixForms API v2/EFTL processing/Process EFTL.yml b/bruno/collections/elixForms API v2/EFTL processing/Process EFTL.yml similarity index 100% rename from collections/elixForms API v2/EFTL processing/Process EFTL.yml rename to bruno/collections/elixForms API v2/EFTL processing/Process EFTL.yml diff --git a/collections/elixForms API v2/EFTL processing/Test vari/Create JSON.yml b/bruno/collections/elixForms API v2/EFTL processing/Test vari/Create JSON.yml similarity index 100% rename from collections/elixForms API v2/EFTL processing/Test vari/Create JSON.yml rename to bruno/collections/elixForms API v2/EFTL processing/Test vari/Create JSON.yml diff --git a/collections/elixForms API v2/EFTL processing/Test vari/TAG per protocollazione fra uffici.yml b/bruno/collections/elixForms API v2/EFTL processing/Test vari/TAG per protocollazione fra uffici.yml similarity index 100% rename from collections/elixForms API v2/EFTL processing/Test vari/TAG per protocollazione fra uffici.yml rename to bruno/collections/elixForms API v2/EFTL processing/Test vari/TAG per protocollazione fra uffici.yml diff --git a/collections/elixForms API v2/EFTL processing/Test vari/TAG per riprotocollazione (integrazione).yml b/bruno/collections/elixForms API v2/EFTL processing/Test vari/TAG per riprotocollazione (integrazione).yml similarity index 100% rename from collections/elixForms API v2/EFTL processing/Test vari/TAG per riprotocollazione (integrazione).yml rename to bruno/collections/elixForms API v2/EFTL processing/Test vari/TAG per riprotocollazione (integrazione).yml diff --git a/collections/elixForms API v2/EFTL processing/Test vari/TEST ordine GetValueByTag.yml b/bruno/collections/elixForms API v2/EFTL processing/Test vari/TEST ordine GetValueByTag.yml similarity index 100% rename from collections/elixForms API v2/EFTL processing/Test vari/TEST ordine GetValueByTag.yml rename to bruno/collections/elixForms API v2/EFTL processing/Test vari/TEST ordine GetValueByTag.yml diff --git a/collections/elixForms API v2/EFTL processing/Test vari/Test Errore 406.yml b/bruno/collections/elixForms API v2/EFTL processing/Test vari/Test Errore 406.yml similarity index 100% rename from collections/elixForms API v2/EFTL processing/Test vari/Test Errore 406.yml rename to bruno/collections/elixForms API v2/EFTL processing/Test vari/Test Errore 406.yml diff --git a/collections/elixForms API v2/EFTL processing/Test vari/Test vari.yml b/bruno/collections/elixForms API v2/EFTL processing/Test vari/Test vari.yml similarity index 100% rename from collections/elixForms API v2/EFTL processing/Test vari/Test vari.yml rename to bruno/collections/elixForms API v2/EFTL processing/Test vari/Test vari.yml diff --git a/collections/elixForms API v2/EFTL processing/Test vari/folder.yml b/bruno/collections/elixForms API v2/EFTL processing/Test vari/folder.yml similarity index 100% rename from collections/elixForms API v2/EFTL processing/Test vari/folder.yml rename to bruno/collections/elixForms API v2/EFTL processing/Test vari/folder.yml diff --git a/collections/elixForms API v2/EFTL processing/folder.yml b/bruno/collections/elixForms API v2/EFTL processing/folder.yml similarity index 100% rename from collections/elixForms API v2/EFTL processing/folder.yml rename to bruno/collections/elixForms API v2/EFTL processing/folder.yml diff --git a/collections/elixForms API v2/Request details/Get ExportTags.yml b/bruno/collections/elixForms API v2/Request details/Get ExportTags.yml similarity index 100% rename from collections/elixForms API v2/Request details/Get ExportTags.yml rename to bruno/collections/elixForms API v2/Request details/Get ExportTags.yml diff --git a/collections/elixForms API v2/Request details/Get Request Attachment.yml b/bruno/collections/elixForms API v2/Request details/Get Request Attachment.yml similarity index 100% rename from collections/elixForms API v2/Request details/Get Request Attachment.yml rename to bruno/collections/elixForms API v2/Request details/Get Request Attachment.yml diff --git a/collections/elixForms API v2/Request details/Get Request Identifier.yml b/bruno/collections/elixForms API v2/Request details/Get Request Identifier.yml similarity index 100% rename from collections/elixForms API v2/Request details/Get Request Identifier.yml rename to bruno/collections/elixForms API v2/Request details/Get Request Identifier.yml diff --git a/collections/elixForms API v2/Request details/Get Request by QRCode.yml b/bruno/collections/elixForms API v2/Request details/Get Request by QRCode.yml similarity index 100% rename from collections/elixForms API v2/Request details/Get Request by QRCode.yml rename to bruno/collections/elixForms API v2/Request details/Get Request by QRCode.yml diff --git a/collections/elixForms API v2/Request details/Get Request.yml b/bruno/collections/elixForms API v2/Request details/Get Request.yml similarity index 100% rename from collections/elixForms API v2/Request details/Get Request.yml rename to bruno/collections/elixForms API v2/Request details/Get Request.yml diff --git a/collections/elixForms API v2/Request details/folder.yml b/bruno/collections/elixForms API v2/Request details/folder.yml similarity index 100% rename from collections/elixForms API v2/Request details/folder.yml rename to bruno/collections/elixForms API v2/Request details/folder.yml diff --git a/collections/elixForms API v2/Requests lookup/Lookup By Period.yml b/bruno/collections/elixForms API v2/Requests lookup/Lookup By Period.yml similarity index 100% rename from collections/elixForms API v2/Requests lookup/Lookup By Period.yml rename to bruno/collections/elixForms API v2/Requests lookup/Lookup By Period.yml diff --git a/collections/elixForms API v2/Requests lookup/Lookup By Status.yml b/bruno/collections/elixForms API v2/Requests lookup/Lookup By Status.yml similarity index 100% rename from collections/elixForms API v2/Requests lookup/Lookup By Status.yml rename to bruno/collections/elixForms API v2/Requests lookup/Lookup By Status.yml diff --git a/collections/elixForms API v2/Requests lookup/Lookup By User and Period.yml b/bruno/collections/elixForms API v2/Requests lookup/Lookup By User and Period.yml similarity index 100% rename from collections/elixForms API v2/Requests lookup/Lookup By User and Period.yml rename to bruno/collections/elixForms API v2/Requests lookup/Lookup By User and Period.yml diff --git a/collections/elixForms API v2/Requests lookup/Lookup By User.yml b/bruno/collections/elixForms API v2/Requests lookup/Lookup By User.yml similarity index 100% rename from collections/elixForms API v2/Requests lookup/Lookup By User.yml rename to bruno/collections/elixForms API v2/Requests lookup/Lookup By User.yml diff --git a/collections/elixForms API v2/Requests lookup/Obsolete/Lookup By Status (OLD).yml b/bruno/collections/elixForms API v2/Requests lookup/Obsolete/Lookup By Status (OLD).yml similarity index 100% rename from collections/elixForms API v2/Requests lookup/Obsolete/Lookup By Status (OLD).yml rename to bruno/collections/elixForms API v2/Requests lookup/Obsolete/Lookup By Status (OLD).yml diff --git a/collections/elixForms API v2/Requests lookup/Obsolete/Lookup By Status.yml b/bruno/collections/elixForms API v2/Requests lookup/Obsolete/Lookup By Status.yml similarity index 100% rename from collections/elixForms API v2/Requests lookup/Obsolete/Lookup By Status.yml rename to bruno/collections/elixForms API v2/Requests lookup/Obsolete/Lookup By Status.yml diff --git a/collections/elixForms API v2/Requests lookup/Obsolete/Lookup By User and Period (OLD).yml b/bruno/collections/elixForms API v2/Requests lookup/Obsolete/Lookup By User and Period (OLD).yml similarity index 100% rename from collections/elixForms API v2/Requests lookup/Obsolete/Lookup By User and Period (OLD).yml rename to bruno/collections/elixForms API v2/Requests lookup/Obsolete/Lookup By User and Period (OLD).yml diff --git a/collections/elixForms API v2/Requests lookup/Obsolete/Lookup By User only (-) (OLD).yml b/bruno/collections/elixForms API v2/Requests lookup/Obsolete/Lookup By User only (-) (OLD).yml similarity index 100% rename from collections/elixForms API v2/Requests lookup/Obsolete/Lookup By User only (-) (OLD).yml rename to bruno/collections/elixForms API v2/Requests lookup/Obsolete/Lookup By User only (-) (OLD).yml diff --git a/collections/elixForms API v2/Requests lookup/Obsolete/folder.yml b/bruno/collections/elixForms API v2/Requests lookup/Obsolete/folder.yml similarity index 100% rename from collections/elixForms API v2/Requests lookup/Obsolete/folder.yml rename to bruno/collections/elixForms API v2/Requests lookup/Obsolete/folder.yml diff --git a/collections/elixForms API v2/Requests lookup/folder.yml b/bruno/collections/elixForms API v2/Requests lookup/folder.yml similarity index 100% rename from collections/elixForms API v2/Requests lookup/folder.yml rename to bruno/collections/elixForms API v2/Requests lookup/folder.yml diff --git a/collections/elixForms API v2/Runner- Get all requests by ModuleTag and status/Get request details.yml b/bruno/collections/elixForms API v2/Runner- Get all requests by ModuleTag and status/Get request details.yml similarity index 100% rename from collections/elixForms API v2/Runner- Get all requests by ModuleTag and status/Get request details.yml rename to bruno/collections/elixForms API v2/Runner- Get all requests by ModuleTag and status/Get request details.yml diff --git a/collections/elixForms API v2/Runner- Get all requests by ModuleTag and status/Login once.yml b/bruno/collections/elixForms API v2/Runner- Get all requests by ModuleTag and status/Login once.yml similarity index 100% rename from collections/elixForms API v2/Runner- Get all requests by ModuleTag and status/Login once.yml rename to bruno/collections/elixForms API v2/Runner- Get all requests by ModuleTag and status/Login once.yml diff --git a/collections/elixForms API v2/Runner- Get all requests by ModuleTag and status/Lookup requests.yml b/bruno/collections/elixForms API v2/Runner- Get all requests by ModuleTag and status/Lookup requests.yml similarity index 100% rename from collections/elixForms API v2/Runner- Get all requests by ModuleTag and status/Lookup requests.yml rename to bruno/collections/elixForms API v2/Runner- Get all requests by ModuleTag and status/Lookup requests.yml diff --git a/collections/elixForms API v2/Runner- Get all requests by ModuleTag and status/folder.yml b/bruno/collections/elixForms API v2/Runner- Get all requests by ModuleTag and status/folder.yml similarity index 100% rename from collections/elixForms API v2/Runner- Get all requests by ModuleTag and status/folder.yml rename to bruno/collections/elixForms API v2/Runner- Get all requests by ModuleTag and status/folder.yml diff --git a/collections/elixForms API v2/Set Request Status- Incomplete.yml b/bruno/collections/elixForms API v2/Set Request Status- Incomplete.yml similarity index 100% rename from collections/elixForms API v2/Set Request Status- Incomplete.yml rename to bruno/collections/elixForms API v2/Set Request Status- Incomplete.yml diff --git a/collections/elixForms API v2/Test Remote WS.yml b/bruno/collections/elixForms API v2/Test Remote WS.yml similarity index 100% rename from collections/elixForms API v2/Test Remote WS.yml rename to bruno/collections/elixForms API v2/Test Remote WS.yml diff --git a/collections/elixForms API v2/User info/Get User Info.yml b/bruno/collections/elixForms API v2/User info/Get User Info.yml similarity index 100% rename from collections/elixForms API v2/User info/Get User Info.yml rename to bruno/collections/elixForms API v2/User info/Get User Info.yml diff --git a/collections/elixForms API v2/User info/folder.yml b/bruno/collections/elixForms API v2/User info/folder.yml similarity index 100% rename from collections/elixForms API v2/User info/folder.yml rename to bruno/collections/elixForms API v2/User info/folder.yml diff --git a/collections/elixForms API v2/_HACKS/Export Module.yml b/bruno/collections/elixForms API v2/_HACKS/Export Module.yml similarity index 100% rename from collections/elixForms API v2/_HACKS/Export Module.yml rename to bruno/collections/elixForms API v2/_HACKS/Export Module.yml diff --git a/collections/elixForms API v2/_HACKS/folder.yml b/bruno/collections/elixForms API v2/_HACKS/folder.yml similarity index 100% rename from collections/elixForms API v2/_HACKS/folder.yml rename to bruno/collections/elixForms API v2/_HACKS/folder.yml diff --git a/collections/elixForms API v2/_Untested/Creazione JWT.yml b/bruno/collections/elixForms API v2/_Untested/Creazione JWT.yml similarity index 100% rename from collections/elixForms API v2/_Untested/Creazione JWT.yml rename to bruno/collections/elixForms API v2/_Untested/Creazione JWT.yml diff --git a/collections/elixForms API v2/_Untested/SSO Receipt Insert.yml b/bruno/collections/elixForms API v2/_Untested/SSO Receipt Insert.yml similarity index 100% rename from collections/elixForms API v2/_Untested/SSO Receipt Insert.yml rename to bruno/collections/elixForms API v2/_Untested/SSO Receipt Insert.yml diff --git a/collections/elixForms API v2/_Untested/SSO Receipt by User.yml b/bruno/collections/elixForms API v2/_Untested/SSO Receipt by User.yml similarity index 100% rename from collections/elixForms API v2/_Untested/SSO Receipt by User.yml rename to bruno/collections/elixForms API v2/_Untested/SSO Receipt by User.yml diff --git a/collections/elixForms API v2/_Untested/folder.yml b/bruno/collections/elixForms API v2/_Untested/folder.yml similarity index 100% rename from collections/elixForms API v2/_Untested/folder.yml rename to bruno/collections/elixForms API v2/_Untested/folder.yml diff --git a/collections/elixForms API v2/elixFormsJs.js b/bruno/collections/elixForms API v2/elixFormsJs.js similarity index 100% rename from collections/elixForms API v2/elixFormsJs.js rename to bruno/collections/elixForms API v2/elixFormsJs.js diff --git a/collections/elixForms API v2/environments/elixForms - Prod.yml b/bruno/collections/elixForms API v2/environments/elixForms - Prod.yml similarity index 100% rename from collections/elixForms API v2/environments/elixForms - Prod.yml rename to bruno/collections/elixForms API v2/environments/elixForms - Prod.yml diff --git a/collections/elixForms API v2/opencollection.yml b/bruno/collections/elixForms API v2/opencollection.yml similarity index 100% rename from collections/elixForms API v2/opencollection.yml rename to bruno/collections/elixForms API v2/opencollection.yml diff --git a/environments/UniPR.yml b/bruno/environments/UniPR.yml similarity index 100% rename from environments/UniPR.yml rename to bruno/environments/UniPR.yml diff --git a/workspace.yml b/bruno/workspace.yml similarity index 100% rename from workspace.yml rename to bruno/workspace.yml From 1fd36fd9573bc66ed934ec75cf8b369316379e3a Mon Sep 17 00:00:00 2001 From: Pier Paolo MAMMI Date: Wed, 22 Jul 2026 12:19:28 +0200 Subject: [PATCH 36/40] remove node tools --- scripts/setup-environment.ps1 | 55 -- scripts/setup-tools.ps1 | 21 + setup-environment.bat => setup-tools.bat | 2 +- .../generate-http-requests.js | 844 ------------------ .../generate-http-requests.test.mjs | 47 - .../generate-http-requests/package-lock.json | 43 - tools/generate-http-requests/package.json | 9 - 7 files changed, 22 insertions(+), 999 deletions(-) delete mode 100644 scripts/setup-environment.ps1 create mode 100644 scripts/setup-tools.ps1 rename setup-environment.bat => setup-tools.bat (90%) delete mode 100644 tools/generate-http-requests/generate-http-requests.js delete mode 100644 tools/generate-http-requests/generate-http-requests.test.mjs delete mode 100644 tools/generate-http-requests/package-lock.json delete mode 100644 tools/generate-http-requests/package.json diff --git a/scripts/setup-environment.ps1 b/scripts/setup-environment.ps1 deleted file mode 100644 index b949b29..0000000 --- a/scripts/setup-environment.ps1 +++ /dev/null @@ -1,55 +0,0 @@ -function Initialize-PowerShellEnvironment { - Write-Host "Initializing PowerShell environment..." -ForegroundColor Yellow - - # Add any environment setup logic here, such as importing modules, setting variables, etc. - # Example: Import-Module SomeModule - Import-Module powershell-yaml -ErrorAction SilentlyContinue - - Write-Host "PowerShell environment initialized." -ForegroundColor Green -} - -function Initialize-GenerateTools { - Write-Host "Initializing Node.js dependencies..." -ForegroundColor Yellow - - Push-Location -StackName NodeTools (Join-Path $PSScriptRoot "../tools/") - - Get-childitem -Path . -Directory | ForEach-Object { - Write-Host "Initializing $($_.Name)..." -ForegroundColor Cyan - - Push-Location -StackName NodeTools $_.FullName - try { - # Install Node.js dependencies - & npm install - if ($LASTEXITCODE -ne 0) { - Write-Error "npm install failed with exit code $LASTEXITCODE." - exit 1 - } - } - catch { - Write-Error "npm install failed for $($_.Name): $_" - exit 1 - } - finally { - Pop-Location -StackName NodeTools - } - } - - Pop-Location -StackName NodeTools - - Write-Host "Node.js dependencies initialized." -ForegroundColor Green -} - -function Invoke-Main { - Write-Host "Preparing environment..." -ForegroundColor Cyan - Write-Host - - Initialize-PowerShellEnvironment - Write-Host - - Initialize-GenerateTools - Write-Host - - Write-Host "Environment preparation complete!" -ForegroundColor Green -} - -Invoke-Main \ No newline at end of file diff --git a/scripts/setup-tools.ps1 b/scripts/setup-tools.ps1 new file mode 100644 index 0000000..f9ac67e --- /dev/null +++ b/scripts/setup-tools.ps1 @@ -0,0 +1,21 @@ +function Initialize-PowerShellEnvironment { + Write-Host "Initializing PowerShell environment..." -ForegroundColor Yellow + + # Add any environment setup logic here, such as importing modules, setting variables, etc. + # Example: Import-Module SomeModule + Import-Module powershell-yaml -ErrorAction SilentlyContinue + + Write-Host "PowerShell environment initialized." -ForegroundColor Green +} + +function Invoke-Main { + Write-Host "Preparing environment..." -ForegroundColor Cyan + Write-Host + + Initialize-PowerShellEnvironment + Write-Host + + Write-Host "Environment preparation complete!" -ForegroundColor Green +} + +Invoke-Main \ No newline at end of file diff --git a/setup-environment.bat b/setup-tools.bat similarity index 90% rename from setup-environment.bat rename to setup-tools.bat index 3ca07f7..1c0a11f 100644 --- a/setup-environment.bat +++ b/setup-tools.bat @@ -6,7 +6,7 @@ cd /D "%~dp0" echo. -@pwsh -NoProfile -ExecutionPolicy Bypass -Command .\scripts\setup-environment.ps1 %* +@pwsh -NoProfile -ExecutionPolicy Bypass -Command .\scripts\setup-tools.ps1 %* echo. diff --git a/tools/generate-http-requests/generate-http-requests.js b/tools/generate-http-requests/generate-http-requests.js deleted file mode 100644 index d0c0086..0000000 --- a/tools/generate-http-requests/generate-http-requests.js +++ /dev/null @@ -1,844 +0,0 @@ -#!/usr/bin/env node -import fs from 'fs'; -import path from 'path'; -import YAML from 'yaml'; -import stripJsonComments from 'strip-json-comments'; -import { fileURLToPath } from 'url'; - -const interpolationVariableRegex = /^{{(.*?)}}$/ -const DEFAULT_VAR_VALUE = 'EDIT_VALUE_HERE' -const VARIABLE_NAME_VALUE_SEPARATOR = '=' -const __filename = fileURLToPath(import.meta.url); -const __dirname = path.dirname(__filename); - -function findWorkspaceRoot(startDir) { - let current = startDir; - while (true) { - if (fs.existsSync(path.join(current, 'workspace.yml'))) { - return current; - } - const parent = path.dirname(current); - if (parent === current) { - throw new Error('workspace.yml not found from the provided start directory'); - } - current = parent; - } -} - -function parseYaml(filePath) { - try { - const text = fs.readFileSync(filePath, 'utf8'); - const parsed = YAML.parse(text); - return parsed || {}; - } catch (error) { - throw new Error(`Failed to parse YAML file ${filePath}: ${error.message}`); - } -} - -function readText(filePath) { - return fs.readFileSync(filePath, 'utf8'); -} - -function stripQuotes(value) { - const trimmed = String(value).trim(); - if ((trimmed.startsWith('"') && trimmed.endsWith('"')) || (trimmed.startsWith("'") && trimmed.endsWith("'"))) { - return trimmed.slice(1, -1); - } - return trimmed; -} - -function parseWorkspace(workspacePath) { - const text = readText(workspacePath); - const lines = text.split(/\r?\n/); - const collections = []; - let inCollections = false; - let currentCollection = null; - - for (const line of lines) { - const trimmed = line.trim(); - if (!inCollections && trimmed === 'collections:') { - inCollections = true; - continue; - } - - if (!inCollections) { - continue; - } - - if (!line.startsWith(' ') && !line.startsWith('\t') && trimmed) { - break; - } - - const nameMatch = line.match(/^\s*-\s+name:\s*(.+)$/); - if (nameMatch) { - currentCollection = { name: stripQuotes(nameMatch[1]) }; - collections.push(currentCollection); - continue; - } - - const pathMatch = line.match(/^\s*path:\s*(.+)$/); - if (pathMatch && currentCollection) { - currentCollection.path = stripQuotes(pathMatch[1]); - } - } - - return { collections }; -} - -function sanitizeVarName(value) { - return String(value) - .trim() - .replace(/[{}]/g, '') - .replace(/[^A-Za-z0-9_]/g, '_') - .replace(/^([0-9])/, '_$1') || 'value'; -} - -function parsePlaceholderContent(content) { - const trimmed = String(content).trim(); - const dotenvMatch = trimmed.match(/^\$dotenv\s+(.+)$/i); - if (dotenvMatch) { - return { name: dotenvMatch[1].trim(), isDotenv: true }; - } - return { name: trimmed, isDotenv: false }; -} - -function collectPlaceholders(value) { - if (typeof value !== 'string') { - return []; - } - const placeholders = []; - const regex = /\{\{([^{}]+)\}\}/g; - let match; - while ((match = regex.exec(value)) !== null) { - placeholders.push(parsePlaceholderContent(match[1]).name); - } - return placeholders; -} - -function findBlock(lines, keyName) { - for (let i = 0; i < lines.length; i += 1) { - const trimmed = lines[i].trim(); - if (trimmed !== keyName && !trimmed.startsWith(`${keyName}:`)) { - continue; - } - - const lineIndent = lines[i].match(/^\s*/)[0].length; - const block = []; - for (let j = i + 1; j < lines.length; j += 1) { - const currentLine = lines[j]; - const currentTrimmed = currentLine.trim(); - if (!currentTrimmed) { - block.push(currentLine); - continue; - } - const currentIndent = currentLine.match(/^\s*/)[0].length; - if (currentIndent <= lineIndent && !currentLine.startsWith(' ')) { - break; - } - if (currentIndent <= lineIndent && currentTrimmed.startsWith('#')) { - block.push(currentLine); - continue; - } - if (currentIndent <= lineIndent) { - break; - } - block.push(currentLine); - } - return block; - } - return []; -} - -function parseRequestInfo(text) { - const lines = text.split(/\r?\n/); - const infoLines = findBlock(lines, 'info'); - const nameMatch = infoLines.join('\n').match(/^\s*name:\s*(.+)$/m); - return nameMatch ? stripQuotes(nameMatch[1]) : ''; -} - -function parseHttpBlock(text) { - const parsed = YAML.parse(text) || {}; - const http = parsed.http || {}; - const headers = []; - - for (const header of Array.isArray(http.headers) ? http.headers : []) { - if (!header || typeof header !== 'object') { - continue; - } - headers.push({ - name: String(header.name || '').trim(), - value: String(header.value ?? '').trim(), - }); - } - - return { - method: http.method || 'GET', - url: http.url || '', - params: Array.isArray(http.params) ? http.params : [], - headers, - body: http.body && typeof http.body === 'object' ? http.body : null, - }; -} - -function formatVariableValue(value, renderContext = {}) { - if (value === null || value === undefined) { - return "''"; - } - - if (typeof value === 'string') { - if (value.trim() === '') { - return "''"; - } - const renderedValue = renderContext.renderValue ? renderContext.renderValue(value) : value; - if (/\s/.test(renderedValue)) { - return `"${renderedValue.replace(/"/g, '\\"')}"`; - } - return renderedValue; - } - - return JSON.stringify(value); -} - -export function mergeRequestConfig(base, updates) { - if (!updates || typeof updates !== 'object') { - return base; - } - - const merged = { ...(base || {}) }; - if (Object.prototype.hasOwnProperty.call(updates, 'auth')) { - if (updates.auth === 'inherit') { - if (merged.auth && typeof merged.auth === 'object') { - merged.auth = merged.auth; - } else { - delete merged.auth; - } - } else if (typeof updates.auth === 'object' && updates.auth !== null) { - merged.auth = updates.auth; - } else { - delete merged.auth; - } - } else { - delete merged.auth; - } - - if (Object.prototype.hasOwnProperty.call(updates, 'headers')) { - const headers = [...(Array.isArray(base.headers) ? base.headers : [])]; - const byName = new Map(); - for (const header of headers) { - if (header && header.name) { - byName.set(String(header.name), header); - } - } - for (const header of updates.headers) { - if (header && header.name) { - byName.set(String(header.name), header); - } - } - merged.headers = [...byName.values()]; - } - - if (Array.isArray(updates.variables)) { - const variables = [...(Array.isArray(base.variables) ? base.variables : [])]; - const byName = new Map(); - for (const variable of variables) { - if (variable && variable.name) { - byName.set(String(variable.name), variable); - } - } - for (const variable of updates.variables) { - if (variable && variable.name) { - byName.set(String(variable.name), variable); - } - } - merged.variables = [...byName.values()]; - } - - return merged; -} - -export function getRequestConfigForFile(yamlFile, sourceDir) { - const resolved = []; - const seenFiles = new Set(); - - const addFile = (filePath) => { - if (!filePath || seenFiles.has(filePath)) { - return; - } - seenFiles.add(filePath); - if (!fs.existsSync(filePath)) { - return; - } - - try { - const parsed = parseYaml(filePath); - let requestConfig = null; - - if (parsed && parsed.request && typeof parsed.request === 'object') { - requestConfig = parsed.request; - } else if (parsed && typeof parsed === 'object') { - const config = {}; - if (Object.prototype.hasOwnProperty.call(parsed, 'auth')) { - config.auth = parsed.auth; - } else if (parsed.http && typeof parsed.http === 'object' && Object.prototype.hasOwnProperty.call(parsed.http, 'auth')) { - config.auth = parsed.http.auth; - } - if (Array.isArray(parsed.variables)) { - config.variables = parsed.variables; - } - if (Object.keys(config).length > 0) { - requestConfig = config; - } - } - - if (requestConfig !== null) { - resolved.push(requestConfig); - } else if (path.resolve(filePath) === path.resolve(yamlFile)) { - resolved.push({}); - } - } catch (error) { - // Ignore files that cannot be parsed as YAML for request inheritance. - } - }; - - const dirChain = []; - let currentDir = path.dirname(yamlFile); - while (true) { - dirChain.unshift(currentDir); - if (currentDir === sourceDir) { - break; - } - const parentDir = path.dirname(currentDir); - if (parentDir === currentDir) { - break; - } - currentDir = parentDir; - } - - for (const dir of dirChain) { - addFile(path.join(dir, 'opencollection.yml')); - addFile(path.join(dir, 'folder.yml')); - } - - addFile(yamlFile); - - return resolved.reduce((result, config) => mergeRequestConfig(result, config), {}); -} - - -export function buildRequestContent(request, requestName, requestConfig = {}, dotenvVariables = new Set()) { - const lines = []; - const variableDefinitions = []; - const commentedVariableDefinitions = []; - const parameterVariableDefinitions = []; - const seenVariables = new Set(); - - const addVariable = (name, value) => { - if (!name) { - return; - } - const normalized = String(name).trim(); - if (!normalized || seenVariables.has(normalized) || dotenvVariables.has(normalized)) { - return; - } - seenVariables.add(normalized); - variableDefinitions.push({ name: normalized, value }); - }; - - const addParameterVariable = (name, value) => { - if (!name) { - return; - } - const normalized = String(name).trim(); - if (!normalized || seenVariables.has(normalized) || dotenvVariables.has(normalized)) { - return; - } - seenVariables.add(normalized); - parameterVariableDefinitions.push({ name: normalized, value }); - }; - - const addCommentedVariable = (name, value) => { - if (!name) { - return; - } - const normalized = String(name).trim(); - if (!normalized) { // || seenVariables.has(normalized) || dotenvVariables.has(normalized)) { - return; - } - // seenVariables.add(normalized); - commentedVariableDefinitions.push({ name: normalized, value }); - }; - - const addReferencedVariables = (value, fallbackValue = DEFAULT_VAR_VALUE) => { - for (const placeholder of collectPlaceholders(String(value))) { - addVariable(placeholder, fallbackValue); - } - }; - - const renderJsonValue = (value) => { - if (typeof value === 'string') { - return renderValue(value); - } - if (Array.isArray(value)) { - return value.map((item) => renderJsonValue(item)); - } - if (value && typeof value === 'object') { - return Object.fromEntries( - Object.entries(value).map(([key, nestedValue]) => [key, renderJsonValue(nestedValue)]), - ); - } - return value; - }; - - const addParameterVariables = (name, value) => { - addParameterVariable(name, value); - }; - - const addCommentedVariables = (name, value) => { - addCommentedVariable(name, value); - }; - - const renderValue = (value) => { - if (typeof value !== 'string') { - return value; - } - return value.replace(/\{\{([^{}]+)\}\}/g, (match, inner) => { - const placeholder = parsePlaceholderContent(inner); - if (placeholder.isDotenv) { - return match; - } - if (placeholder.name && dotenvVariables.has(placeholder.name)) { - return `{{$dotenv ${placeholder.name}}}`; - } - return match; - }); - }; - - const configVariables = Array.isArray(requestConfig.variables) ? requestConfig.variables : []; - for (const variable of configVariables) { - if (variable && variable.name) { - addVariable(variable.name, variable.value); - } - } - - let url = request.url || ''; - if (url) { - 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]; - } - - const queryParams = []; - const headers = []; - const addHeader = (name, value) => { - if (!name) { - return; - } - addReferencedVariables(value ?? ''); - headers.push({ name: String(name).trim(), value: renderValue(value ?? '') }); - }; - - for (const header of Array.isArray(request.headers) ? request.headers : []) { - if (!header || !header.name) { - continue; - } - addHeader(header.name, header.value ?? ''); - } - - for (const header of Array.isArray(requestConfig.headers) ? requestConfig.headers : []) { - if (!header || !header.name) { - continue; - } - addHeader(header.name, header.value ?? ''); - } - - for (const param of request.params || []) { - const name = param.name || ''; - const value = param.value || ''; - const type = (param.type || 'query').toLowerCase(); - const disabled = String(param.disabled).toLowerCase() === 'true'; - - if (disabled) { - addCommentedVariables(name, value); - continue; - } - - addReferencedVariables(value); - - if (type === 'header') { - headers.push({ name, value: renderValue(value) }); - } else { - queryParams.push({ name, value: `{{${name}}}` }); - addParameterVariables(name, value); - } - } - - if (requestConfig.auth) { - if (requestConfig.auth.type === 'bearer') { - addReferencedVariables(requestConfig.auth.token ?? ''); - addHeader('Authorization', `Bearer ${renderValue(requestConfig.auth.token ?? '')}`); - } else if (requestConfig.auth.type === 'basic') { - const username = requestConfig.auth.username ?? ''; - const password = requestConfig.auth.password ?? ''; - addReferencedVariables(username); - addReferencedVariables(password); - // VSCode REST Client can manage username:password format directly! - addHeader('Authorization', `Basic ${renderValue(username)}:${renderValue(password)}`); - } else { - headers.push({ - name: `UNKNOWN_${requestConfig.auth.type}`, - value: `Basic ${requestConfig.auth.token}`, - }); - } - } - - if (commentedVariableDefinitions.length > 0) { - lines.push(`# Other variables for ${requestName}`); - for (const variable of commentedVariableDefinitions.sort((a, b) => { - const nameComparison = a.name.localeCompare(b.name); - return nameComparison !== 0 ? nameComparison : a.value.localeCompare(b.value); - })) { - lines.push(`# @${sanitizeVarName(variable.name)}${VARIABLE_NAME_VALUE_SEPARATOR}${formatVariableValue(variable.value, { renderValue })}`); - } - } - - if (parameterVariableDefinitions.length > 0) { - lines.push(`# Parameter variables for ${requestName}`); - for (const variable of parameterVariableDefinitions.sort((a, b) => { - const nameComparison = a.name.localeCompare(b.name); - return nameComparison !== 0 ? nameComparison : a.value.localeCompare(b.value); - })) { - lines.push(`@${sanitizeVarName(variable.name)}${VARIABLE_NAME_VALUE_SEPARATOR}${formatVariableValue(variable.value, { renderValue })}`); - } - } - - let requestBody = ''; - if (request.body && typeof request.body === 'object') { - const bodyType = String(request.body.type || '').toLowerCase(); - if (bodyType === 'json') { - const jsonData = stripJsonComments(request.body.data, { whitespace: false }); - if (jsonData !== undefined && jsonData !== null) { - if (typeof jsonData === 'string') { - requestBody = renderValue(jsonData); - } else { - const renderedData = Array.isArray(jsonData) - ? jsonData.map((item) => renderJsonValue(item)) - : renderJsonValue(jsonData); - requestBody = JSON.stringify(renderedData, null, 2); - } - } - addHeader('Content-Type', 'application/json'); - } else if (bodyType === 'form-urlencoded') { - const parts = []; - for (const entry of Array.isArray(request.body.data) ? request.body.data : []) { - if (!entry || !entry.name) { - continue; - } - addReferencedVariables(entry.value ?? ''); - parts.push(`${entry.name}=${renderValue(entry.value ?? '')}`); - } - requestBody = parts.join('&'); - addHeader('Content-Type', 'application/x-www-form-urlencoded'); - } - } - - if (variableDefinitions.length > 0) { - lines.push(`# Variables for ${requestName}`); - for (const variable of variableDefinitions.sort((a, b) => { - const nameComparison = a.name.localeCompare(b.name); - return nameComparison !== 0 ? nameComparison : a.value.localeCompare(b.value); - })) { - lines.push(`@${sanitizeVarName(variable.name)}${VARIABLE_NAME_VALUE_SEPARATOR}${formatVariableValue(variable.value, { renderValue })}`); - } - } - - const method = (request.method || 'GET').toUpperCase(); - let requestUrl = url; - for (const param of queryParams) { - if (!param.name) { - continue; - } - const separator = requestUrl.includes('?') ? '&' : '?'; - requestUrl = `${requestUrl}${separator}${param.name}=${param.value}`; - } - - lines.push(''); - lines.push(`${method} ${requestUrl}`); - for (const header of headers) { - lines.push(`${header.name}: ${header.value}`); - } - if (requestBody) { - lines.push(''); - lines.push(requestBody); - } - return lines.join('\n'); -} - -function ensureDir(dirPath) { - fs.mkdirSync(dirPath, { recursive: true }); -} - -function walkYamlFiles(rootDir) { - const results = []; - const entries = fs.readdirSync(rootDir, { withFileTypes: true }); - for (const entry of entries) { - if (entry.name.startsWith('.') || entry.name === 'node_modules') { - continue; - } - const fullPath = path.join(rootDir, entry.name); - if (entry.isDirectory()) { - results.push(...walkYamlFiles(fullPath)); - } else if (entry.isFile() && /\.ya?ml$/i.test(entry.name)) { - results.push(fullPath); - } - } - 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 }); - const hasEnvironmentsDir = entries.some((entry) => entry.isDirectory() && entry.name === 'environments' && - fs.readdirSync(path.join(currentDir, 'environments'), { withFileTypes: true }).some((envEntry) => envEntry.isFile() && /\.ya?ml$/i.test(envEntry.name))); - - if (hasEnvironmentsDir) { - targets.push(currentDir); - } - - for (const entry of entries) { - if (!entry.isDirectory() || entry.name.startsWith('.') || entry.name === 'node_modules') { - continue; - } - visit(path.join(currentDir, entry.name)); - } - }; - - visit(sourceDir); - - for (const dir of targets) { - const relativeDir = path.relative(sourceDir, dir); - const targetDir = relativeDir && relativeDir !== '.' ? path.join(outputRoot, relativeDir) : outputRoot; - ensureDir(targetDir); - - const environmentsDir = path.join(dir, 'environments'); - if (!fs.existsSync(environmentsDir)) { - continue; - } - - const envFiles = fs.readdirSync(environmentsDir, { withFileTypes: true }) - .filter((entry) => entry.isFile() && /\.ya?ml$/i.test(entry.name)) - .map((entry) => path.join(environmentsDir, entry.name)); - - const variableNames = []; - const seenNames = new Set(); - - for (const envFile of envFiles) { - const parsed = parseYaml(envFile); - const variables = Array.isArray(parsed.variables) ? parsed.variables : []; - for (const variable of variables) { - if (!variable || !variable.name) { - continue; - } - const name = String(variable.name).trim(); - if (!name || seenNames.has(name)) { - continue; - } - seenNames.add(name); - variableNames.push(name); - } - } - - const templateContent = variableNames.length > 0 ? `${variableNames.map(v => `${v}=${DEFAULT_VAR_VALUE}`).join('\n')}\n` : ''; - fs.writeFileSync(path.join(targetDir, '.env.template'), templateContent, 'utf8'); - dotenvVariablesByTarget.set(targetDir, new Set(variableNames)); - } - - return dotenvVariablesByTarget; -} - -function writeJsFiles(sourceDir, outputRoot) { - const targets = []; - // const dotenvVariablesByTarget = new Map(); - - const visit = (currentDir) => { - const entries = fs.readdirSync(currentDir, { withFileTypes: true }); - const hasJsFiles = entries.some((entry) => entry.isFile() && /\.js$/i.test(entry.name)); - - if (hasJsFiles) { - targets.push(currentDir); - } - - for (const entry of entries) { - if (!entry.isDirectory() || entry.name.startsWith('.') || entry.name === 'node_modules') { - continue; - } - visit(path.join(currentDir, entry.name)); - } - }; - - visit(sourceDir); - - for (const dir of targets) { - const relativeDir = path.relative(sourceDir, dir); - const targetDir = relativeDir && relativeDir !== '.' ? path.join(outputRoot, relativeDir) : outputRoot; - ensureDir(targetDir); - - const jsFileDir = dir; - if (!fs.existsSync(jsFileDir)) { - continue; - } - - const jsFiles = fs.readdirSync(jsFileDir, { withFileTypes: true }) - .filter((entry) => entry.isFile() && /\.js$/i.test(entry.name)) - .map((entry) => [ path.join(jsFileDir, entry.name), path.join(targetDir, entry.name) ]); - - // const variableNames = []; - // const seenNames = new Set(); - - // for (const jsFile of jsFiles) { - // const parsed = parseYaml(jsFile); - // const variables = Array.isArray(parsed.variables) ? parsed.variables : []; - // for (const variable of variables) { - // if (!variable || !variable.name) { - // continue; - // } - // const name = String(variable.name).trim(); - // if (!name || seenNames.has(name)) { - // continue; - // } - // seenNames.add(name); - // variableNames.push(name); - // } - // } - - // const templateContent = variableNames.length > 0 ? `${variableNames.map(v => `${v}=${DEFAULT_ENV_VAR_VALUE}`).join('\n')}\n` : ''; - // fs.writeFileSync(path.join(targetDir, '.env.template'), templateContent, 'utf8'); - // dotenvVariablesByTarget.set(targetDir, new Set(variableNames)); - for (const jsFile of jsFiles) { - fs.copyFileSync(jsFile[0], jsFile[1]); - } - } - - return targets; -} - -function cleanFolder(dir) { - if (!fs.existsSync(dir)) return; - - const entries = fs.readdirSync(dir, { withFileTypes: true }); - - for (const entry of entries) { - const fullPath = path.join(dir, entry.name); - - if (entry.isDirectory()) { - // Ricorsione - cleanFolder(fullPath); - - // Dopo la pulizia, se la cartella è vuota → cancellala - const remaining = fs.readdirSync(fullPath); - if (remaining.length === 0) { - fs.rmdirSync(fullPath); - } - } else if (entry.isFile()) { - // File da eliminare - if ( - entry.name.endsWith(".js") || - entry.name.endsWith(".http") || - entry.name.endsWith(".env.template") - ) { - fs.unlinkSync(fullPath); - } - } - } -} - -function main() { - const workspaceRoot = findWorkspaceRoot(__dirname); - const workspaceFile = path.join(workspaceRoot, 'workspace.yml'); - const workspace = parseWorkspace(workspaceFile); - const collections = Array.isArray(workspace.collections) ? workspace.collections : []; - - if (collections.length === 0) { - throw new Error('No collections found in workspace.yml'); - } - - const outputBaseRoot = path.join(workspaceRoot, 'autogen', 'httpyac_node'); - cleanFolder(outputBaseRoot); - - for (const collection of collections) { - if (!collection || !collection.name || !collection.path) { - continue; - } - - const sourceDir = path.join(workspaceRoot, collection.path); - if (!fs.existsSync(sourceDir)) { - console.warn(`Skipping missing collection path: ${collection.path}`); - continue; - } - - const outputRoot = path.join(outputBaseRoot, collection.name); - ensureDir(outputRoot); - - const writtenJsFiles = writeJsFiles(sourceDir, outputRoot); - - const dotenvVariablesByTarget = writeEnvironmentTemplates(sourceDir, outputRoot); - - const yamlFiles = walkYamlFiles(sourceDir); - let processed = 0; - - for (const yamlFile of yamlFiles) { - const content = readText(yamlFile); - const requestName = parseRequestInfo(content) || path.basename(yamlFile, path.extname(yamlFile)); - const httpBlock = parseHttpBlock(content); - if (!httpBlock || !httpBlock.url) { - continue; - } - - const relativePath = path.relative(sourceDir, yamlFile); - const parsedPath = path.parse(relativePath); - const targetDir = path.join(outputRoot, parsedPath.dir); - ensureDir(targetDir); - - const requestConfig = getRequestConfigForFile(yamlFile, sourceDir); - const outputFile = path.join(targetDir, `${parsedPath.name}.http`); - const dotenvVariables = getDotenvVariablesForTargetDir(targetDir, outputRoot, dotenvVariablesByTarget); - const requestContent = buildRequestContent(httpBlock, requestName, requestConfig, dotenvVariables); - fs.writeFileSync(outputFile, `${requestContent}\n`, 'utf8'); - processed += 1; - } - - console.log(`${collection.name.padEnd(33)} => generated ${processed.toString().padStart(3)} .http file(s) and ${writtenJsFiles.length.toString().padStart(3)} .js file(s)`); - } -} - -try { - main(); -} catch (error) { - console.error(error.message); - process.exit(1); -} diff --git a/tools/generate-http-requests/generate-http-requests.test.mjs b/tools/generate-http-requests/generate-http-requests.test.mjs deleted file mode 100644 index 3f46f4b..0000000 --- a/tools/generate-http-requests/generate-http-requests.test.mjs +++ /dev/null @@ -1,47 +0,0 @@ -import test from 'node:test'; -import assert from 'node:assert/strict'; -import fs from 'node:fs'; -import os from 'node:os'; -import path from 'node:path'; -import { buildRequestContent, getRequestConfigForFile, mergeRequestConfig } from './generate-http-requests.js'; - -test('does not inherit parent auth when a child config has no auth override', () => { - const parentAuth = { type: 'bearer', token: 'parent-token' }; - const merged = mergeRequestConfig({ auth: parentAuth }, {}); - - assert.equal(merged.auth, undefined); -}); - -test('uses an explicit child auth object instead of inheriting the parent auth', () => { - const parentAuth = { type: 'bearer', token: 'parent-token' }; - const childAuth = { type: 'basic', username: 'user', password: 'pass' }; - const merged = mergeRequestConfig({ auth: parentAuth }, { auth: childAuth }); - - assert.deepEqual(merged.auth, childAuth); -}); - -test('reads auth inherit from a Bruno-style http block', () => { - const tempRoot = fs.mkdtempSync(path.join(os.tmpdir(), 'bruno-auth-')); - const childDir = path.join(tempRoot, 'nested'); - fs.mkdirSync(childDir, { recursive: true }); - fs.writeFileSync(path.join(tempRoot, 'opencollection.yml'), `request:\n auth:\n type: bearer\n token: "parent-token"\n`); - fs.writeFileSync(path.join(tempRoot, 'folder.yml'), 'auth: inherit\n'); - fs.writeFileSync(path.join(childDir, 'request.yml'), 'http:\n auth: inherit\n'); - - const config = getRequestConfigForFile(path.join(childDir, 'request.yml'), tempRoot); - - assert.deepEqual(config.auth, { type: 'bearer', token: 'parent-token' }); -}); - -test('renders dotenv placeholders in generated variable definitions', () => { - const request = { - url: 'https://example.test', - params: [ - { name: 'username', value: '{{elixFormsApiUsername}}', type: 'path' }, - ], - }; - - const output = buildRequestContent(request, 'Logout', {}, new Set(['elixFormsApiUsername'])); - - assert.match(output, /@username = "\{\{\$dotenv elixFormsApiUsername\}\}"/); -}); diff --git a/tools/generate-http-requests/package-lock.json b/tools/generate-http-requests/package-lock.json deleted file mode 100644 index f21b0b5..0000000 --- a/tools/generate-http-requests/package-lock.json +++ /dev/null @@ -1,43 +0,0 @@ -{ - "name": "generate-http-requests", - "version": "0.0.1", - "lockfileVersion": 3, - "requires": true, - "packages": { - "": { - "name": "generate-http-requests", - "version": "0.0.1", - "dependencies": { - "strip-json-comments": "^5.0.3", - "yaml": "^2.9.0" - } - }, - "node_modules/strip-json-comments": { - "version": "5.0.3", - "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-5.0.3.tgz", - "integrity": "sha512-1tB5mhVo7U+ETBKNf92xT4hrQa3pm0MZ0PQvuDnWgAAGHDsfp4lPSpiS6psrSiet87wyGPh9ft6wmhOMQ0hDiw==", - "license": "MIT", - "engines": { - "node": ">=14.16" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/yaml": { - "version": "2.9.0", - "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.9.0.tgz", - "integrity": "sha512-2AvhNX3mb8zd6Zy7INTtSpl1F15HW6Wnqj0srWlkKLcpYl/gMIMJiyuGq2KeI2YFxUPjdlB+3Lc10seMLtL4cA==", - "license": "ISC", - "bin": { - "yaml": "bin.mjs" - }, - "engines": { - "node": ">= 14.6" - }, - "funding": { - "url": "https://github.com/sponsors/eemeli" - } - } - } -} diff --git a/tools/generate-http-requests/package.json b/tools/generate-http-requests/package.json deleted file mode 100644 index 91b88cc..0000000 --- a/tools/generate-http-requests/package.json +++ /dev/null @@ -1,9 +0,0 @@ -{ - "name": "generate-http-requests", - "version": "0.0.1", - "type": "module", - "dependencies": { - "strip-json-comments": "^5.0.3", - "yaml": "^2.9.0" - } -} \ No newline at end of file From 5ae3b93436978e4c84d6fd89e544ac60d4100ec9 Mon Sep 17 00:00:00 2001 From: Pier Paolo MAMMI Date: Wed, 22 Jul 2026 12:20:35 +0200 Subject: [PATCH 37/40] rename scripts and fix collections location --- ...equests.bat => generate-httpyac-requests.bat | 2 +- ...quests.ps1 => generate-httpyac-requests.ps1} | 17 ++++++++++++----- scripts/setup-json-environment.ps1 | 12 ++++++++---- scripts/update-bruno-environments.ps1 | 4 ++-- ...ents.ps1 => update-httpyac-environments.ps1} | 4 ++-- ...ments.bat => update-httpyac-environments.bat | 2 +- 6 files changed, 26 insertions(+), 15 deletions(-) rename generate-http-requests.bat => generate-httpyac-requests.bat (88%) rename scripts/{generate-http-requests.ps1 => generate-httpyac-requests.ps1} (95%) rename scripts/{update-http-requests-environments.ps1 => update-httpyac-environments.ps1} (91%) rename update-http-requests-environments.bat => update-httpyac-environments.bat (86%) diff --git a/generate-http-requests.bat b/generate-httpyac-requests.bat similarity index 88% rename from generate-http-requests.bat rename to generate-httpyac-requests.bat index 405ae37..e7ed4b6 100644 --- a/generate-http-requests.bat +++ b/generate-httpyac-requests.bat @@ -6,7 +6,7 @@ cd /D "%~dp0" echo. -@pwsh -NoProfile -ExecutionPolicy Bypass -Command .\scripts\generate-http-requests.ps1 %* +@pwsh -NoProfile -ExecutionPolicy Bypass -Command .\scripts\generate-httpyac-requests.ps1 %* echo. diff --git a/scripts/generate-http-requests.ps1 b/scripts/generate-httpyac-requests.ps1 similarity index 95% rename from scripts/generate-http-requests.ps1 rename to scripts/generate-httpyac-requests.ps1 index b0da455..58796a7 100644 --- a/scripts/generate-http-requests.ps1 +++ b/scripts/generate-httpyac-requests.ps1 @@ -1,14 +1,16 @@ #requires -Modules powershell-yaml param( - [string]$StartDir = (Split-Path -LiteralPath $MyInvocation.MyCommand.Path) + [string]$StartDir = (Resolve-Path -LiteralPath (Join-Path -Path (Split-Path -LiteralPath $MyInvocation.MyCommand.Path) -ChildPath "../bruno")), + [string]$OutputDir = (Resolve-Path -LiteralPath (Join-Path -Path (Split-Path -LiteralPath $MyInvocation.MyCommand.Path) -ChildPath "..")) ) $DEFAULT_ENV_VAR_VALUE = 'EDIT_VALUE_HERE' $VARIABLE_NAME_VALUE_SEPARATOR = '=' -function Find-WorkspaceRoot($startDir) { - $current = $startDir +function Find-WorkspaceRoot($dir) { + Write-Host "Processing workspace folder: '$dir'..." + $current = $dir while ($true) { if (Test-Path -LiteralPath (Join-Path $current 'workspace.yml')) { return $current @@ -997,7 +999,7 @@ function Write-JsFiles ($sourceDir, $outputRoot) { function Invoke-Main { # Workspace root - $workspaceRoot = Find-WorkspaceRoot $PSScriptRoot + $workspaceRoot = Find-WorkspaceRoot $StartDir $workspaceFile = Join-Path $workspaceRoot 'workspace.yml' $workspace = Parse-Workspace $workspaceFile $collections = @() @@ -1009,7 +1011,12 @@ function Invoke-Main { throw "No collections found in workspace.yml" } - $outputBaseRoot = Join-Path $workspaceRoot 'autodocs/httpyac' + $outputBaseRoot = Join-Path $OutputDir 'autodocs/httpyac' + if (-not (Test-Path $outputBaseRoot)) { + New-Item -ItemType Directory -Path $outputBaseRoot | Out-Null + } + $outputBaseRoot = Resolve-Path -LiteralPath $outputBaseRoot + Clean-Folder $outputBaseRoot foreach ($collection in $collections) { diff --git a/scripts/setup-json-environment.ps1 b/scripts/setup-json-environment.ps1 index 5f9e847..6eb89c6 100644 --- a/scripts/setup-json-environment.ps1 +++ b/scripts/setup-json-environment.ps1 @@ -25,8 +25,12 @@ function Ask-YesNo($message) { } # Funzione per chiedere un valore -function Ask-Value($key) { - return Read-Host "Valore per '$key' (digita `"`" per inserire stringa vuota e lascia vuoto per NON aggiornare)" +function Ask-Value($key, $currentValue) { + $currentValueHint = "" + if (-not [string]::IsNullOrEmpty($currentValue)) { + $currentValueHint = "[attuale: '$currentValue'] " + } + return Read-Host "Chiave '$key' $currentValueHint`n(digita `"`" per inserire stringa vuota e lascia vuoto per NON aggiornare)" } # Copia profonda preservando ordine @@ -79,8 +83,6 @@ foreach ($topKey in $parsedJson.Keys) { continue } - $inputValue = Ask-Value $key - if ($existingEnv -and $existingEnv["API"] -and $existingEnv["API"].Contains($sectionName)) { $oldValue = $existingEnv["API"][$sectionName][$key] } @@ -88,6 +90,8 @@ foreach ($topKey in $parsedJson.Keys) { $oldValue = "" } + $inputValue = Ask-Value $key $oldValue + if ($inputValue -eq "") { # Mantieni valore esistente se presente $newSection[$key] = $oldValue diff --git a/scripts/update-bruno-environments.ps1 b/scripts/update-bruno-environments.ps1 index 39c200a..8bfe777 100644 --- a/scripts/update-bruno-environments.ps1 +++ b/scripts/update-bruno-environments.ps1 @@ -1,6 +1,6 @@ # Percorsi file -$envFile = Join-Path $PSScriptRoot ".." "env.json" # JSON originale -$collectionsRoot = Join-Path $PSScriptRoot ".." "collections" # cartella di partenza delle collezioni +$envFile = Resolve-Path -LiteralPath (Join-Path $PSScriptRoot ".." "env.json") # JSON originale +$collectionsRoot = Resolve-Path -LiteralPath (Join-Path $PSScriptRoot ".." "bruno/collections") # cartella di partenza delle collezioni # Costanti $ENV_JSON_FILENAME = "env.json" diff --git a/scripts/update-http-requests-environments.ps1 b/scripts/update-httpyac-environments.ps1 similarity index 91% rename from scripts/update-http-requests-environments.ps1 rename to scripts/update-httpyac-environments.ps1 index e03834c..d373c9c 100644 --- a/scripts/update-http-requests-environments.ps1 +++ b/scripts/update-httpyac-environments.ps1 @@ -1,6 +1,6 @@ # Percorsi file -$envFile = Join-Path $PSScriptRoot ".." "env.json" # JSON originale -$collectionsRoot = Join-Path $PSScriptRoot ".." "autodocs/httpyac" # cartella di partenza delle collezioni +$envFile = Resolve-Path -LiteralPath (Join-Path $PSScriptRoot ".." "env.json") # JSON originale +$collectionsRoot = Resolve-Path -LiteralPath (Join-Path $PSScriptRoot ".." "autodocs/httpyac") # cartella di partenza delle collezioni # Costanti $API_SECTION_NAME = "API" diff --git a/update-http-requests-environments.bat b/update-httpyac-environments.bat similarity index 86% rename from update-http-requests-environments.bat rename to update-httpyac-environments.bat index f75f472..6df6afe 100644 --- a/update-http-requests-environments.bat +++ b/update-httpyac-environments.bat @@ -6,7 +6,7 @@ cd /D "%~dp0" echo. -@pwsh -NoProfile -ExecutionPolicy Bypass -Command .\scripts\update-http-requests-environments.ps1 %* +@pwsh -NoProfile -ExecutionPolicy Bypass -Command .\scripts\update-httpyac-environments.ps1 %* echo. From 80b134e32aaa858a5f7eb6bb87b86ec75025097d Mon Sep 17 00:00:00 2001 From: Pier Paolo MAMMI Date: Wed, 22 Jul 2026 12:20:35 +0200 Subject: [PATCH 38/40] add runner to find CCT instances by contract move old requests to own folder --- .../{ => OLD}/Reopen Request (OLD).yml | 2 +- .../{ => OLD}/Set Request Status (OLD).yml | 0 ... Request Status- Register result (OLD).yml | 2 +- .../OLD/folder.yml | 7 + .../Get request details.yml | 933 ++++++++++++++++++ .../Login once.yml | 255 +++++ .../Lookup requests.yml | 276 ++++++ .../folder.yml | 7 + 8 files changed, 1480 insertions(+), 2 deletions(-) rename bruno/collections/elixForms API v2/Cambio stato e-o integrazione/{ => OLD}/Reopen Request (OLD).yml (99%) rename bruno/collections/elixForms API v2/Cambio stato e-o integrazione/{ => OLD}/Set Request Status (OLD).yml (100%) rename bruno/collections/elixForms API v2/Cambio stato e-o integrazione/{ => OLD}/Set Request Status- Register result (OLD).yml (99%) create mode 100644 bruno/collections/elixForms API v2/Cambio stato e-o integrazione/OLD/folder.yml create mode 100644 bruno/collections/elixForms API v2/Runner- Get Proposta CCT matching contract IDs/Get request details.yml create mode 100644 bruno/collections/elixForms API v2/Runner- Get Proposta CCT matching contract IDs/Login once.yml create mode 100644 bruno/collections/elixForms API v2/Runner- Get Proposta CCT matching contract IDs/Lookup requests.yml create mode 100644 bruno/collections/elixForms API v2/Runner- Get Proposta CCT matching contract IDs/folder.yml diff --git a/bruno/collections/elixForms API v2/Cambio stato e-o integrazione/Reopen Request (OLD).yml b/bruno/collections/elixForms API v2/Cambio stato e-o integrazione/OLD/Reopen Request (OLD).yml similarity index 99% rename from bruno/collections/elixForms API v2/Cambio stato e-o integrazione/Reopen Request (OLD).yml rename to bruno/collections/elixForms API v2/Cambio stato e-o integrazione/OLD/Reopen Request (OLD).yml index fb242e7..dec7d0a 100644 --- a/bruno/collections/elixForms API v2/Cambio stato e-o integrazione/Reopen Request (OLD).yml +++ b/bruno/collections/elixForms API v2/Cambio stato e-o integrazione/OLD/Reopen Request (OLD).yml @@ -1,7 +1,7 @@ info: name: Reopen Request (OLD) type: http - seq: 4 + seq: 6 http: method: POST diff --git a/bruno/collections/elixForms API v2/Cambio stato e-o integrazione/Set Request Status (OLD).yml b/bruno/collections/elixForms API v2/Cambio stato e-o integrazione/OLD/Set Request Status (OLD).yml similarity index 100% rename from bruno/collections/elixForms API v2/Cambio stato e-o integrazione/Set Request Status (OLD).yml rename to bruno/collections/elixForms API v2/Cambio stato e-o integrazione/OLD/Set Request Status (OLD).yml diff --git a/bruno/collections/elixForms API v2/Cambio stato e-o integrazione/Set Request Status- Register result (OLD).yml b/bruno/collections/elixForms API v2/Cambio stato e-o integrazione/OLD/Set Request Status- Register result (OLD).yml similarity index 99% rename from bruno/collections/elixForms API v2/Cambio stato e-o integrazione/Set Request Status- Register result (OLD).yml rename to bruno/collections/elixForms API v2/Cambio stato e-o integrazione/OLD/Set Request Status- Register result (OLD).yml index f64bfd1..5ef0a63 100644 --- a/bruno/collections/elixForms API v2/Cambio stato e-o integrazione/Set Request Status- Register result (OLD).yml +++ b/bruno/collections/elixForms API v2/Cambio stato e-o integrazione/OLD/Set Request Status- Register result (OLD).yml @@ -1,7 +1,7 @@ info: name: "Set Request Status: Register result (OLD)" type: http - seq: 3 + seq: 6 http: method: POST diff --git a/bruno/collections/elixForms API v2/Cambio stato e-o integrazione/OLD/folder.yml b/bruno/collections/elixForms API v2/Cambio stato e-o integrazione/OLD/folder.yml new file mode 100644 index 0000000..01e3d2c --- /dev/null +++ b/bruno/collections/elixForms API v2/Cambio stato e-o integrazione/OLD/folder.yml @@ -0,0 +1,7 @@ +info: + name: OLD + type: folder + seq: 6 + +request: + auth: inherit diff --git a/bruno/collections/elixForms API v2/Runner- Get Proposta CCT matching contract IDs/Get request details.yml b/bruno/collections/elixForms API v2/Runner- Get Proposta CCT matching contract IDs/Get request details.yml new file mode 100644 index 0000000..5566cb8 --- /dev/null +++ b/bruno/collections/elixForms API v2/Runner- Get Proposta CCT matching contract IDs/Get request details.yml @@ -0,0 +1,933 @@ +info: + name: Get request details + type: http + seq: 6 + +http: + method: GET + url: "{{elixFormsApiUrl_Default}}/request/:request_id/get" + headers: + - name: x-requested-with + value: XMLHttpRequest + - name: x-api-username + value: "{{elixFormsApiUsername}}" + params: + - name: username + value: "{{elixFormsApiUsername}}" + type: query + description: lo username con cui si è effettuato il login + disabled: true + - name: recordOrder + value: NONE + type: query + description: case sensitive + disabled: true + - name: request_id + value: REPLACE + type: path + body: + type: form-urlencoded + auth: inherit + +runtime: + scripts: + - type: before-request + code: |- + if (!bru.hasVar("elixFormsQueryRequestIds")) + { + console.error("Pre: NO RequestIds FOUND!"); + } + const requestIds = bru.getVar("elixFormsQueryRequestIds"); + if (!bru.hasVar("elixFormsQueryRequestIndex")) + { + console.error("Pre: NO RequestIndex FOUND!"); + } + const requestIndex = bru.getVar("elixFormsQueryRequestIndex"); + const requestId = requestIds[requestIndex]; + + if (requestId === undefined) + { + console.log("Undefined, printing vars:"); + //console.log(bru.getVar("elixFormsQueryOutput")); + console.log(bru.getVar("elixFormsWebKitFormOutput")); + } + else + { + //console.log("Calling method with requestId: " + requestId); + req.setUrl(req.getUrl().replace(":request_id", requestId)); + } + - type: after-response + code: |- + if (!bru.hasVar("elixFormsQueryRequestIds")) + { + console.error("Pre: NO elixFormsQueryRequestIds FOUND!"); + } + const requestIds = bru.getVar("elixFormsQueryRequestIds"); + if (!bru.hasVar("elixFormsQueryRequestIndex")) + { + console.error("Post: NO elixFormsQueryRequestIndex FOUND!"); + } + const requestIndex = bru.getVar("elixFormsQueryRequestIndex"); + if (!bru.hasVar("elixFormsQueryOutput")) + { + console.error("Post: NO elixFormsQueryOutput FOUND!"); + } + const jsonOutput = JSON.parse(bru.getVar("elixFormsQueryOutput")); + + // -------------------------------------------------------------------------------- + if (!bru.hasVar("elixFormsWebKitFormOutput")) + { + console.error("Post: NO elixFormsWebKitFormOutput FOUND!"); + } + var webKitFormOutput = bru.getVar("elixFormsWebKitFormOutput"); + // -------------------------------------------------------------------------------- + + // Get response data + const request = res.getBody().value.request; + const idRequest = request.idRequest ?? 0; + const recordId = request.steps?.find(s => s.stepHeader == "Dati generali")?.schemas?.find(s => s.schemaId == "341")?.records?.[0]?.recordId ?? ""; + + if (recordId != "") + { + const contraenti = request.steps?.find(s => s.stepHeader == "Dati generali")?.schemas?.find(s => s.schemaId == "341")?.records?.[0]?.sections?.find(s => s.sectionKey == "SEC_0001")?.columns?.find(c => c.columnKey == "COL0004")?.columnValue ?? ""; + const responsabili = request.steps?.find(s => s.stepHeader == "Dati generali")?.schemas?.find(s => s.schemaId == "341")?.records?.[0]?.sections?.find(s => s.sectionKey == "SEC_0003")?.columns?.find(c => c.columnKey == "COL0017")?.columnValue ?? ""; + + // Now prepare values as needed + const contraentiCsv = contraenti.split("\n").map(c => c.split(", CF/PIVA: ")[0]).join(", "); + const responsabiliCsv = responsabili.split("\n").map(r => r.split(", CF: ")[0]).join(", "); + + const stringElement = '{ "idRequest": ' + idRequest + ', "S_341_'+recordId+'_COL0118": "' + responsabiliCsv + '", "S_341_'+recordId+'_COL0119": "' + contraentiCsv + '" }'; + const jsonElement = JSON.parse(stringElement); + + jsonOutput.push(jsonElement); + + bru.setVar("elixFormsQueryOutput", JSON.stringify(jsonOutput)); + + // -------------------------------------------------------------------------------- + webKitFormOutput += "------WebKitFormBoundary0123456789abcdef\r\n"; + webKitFormOutput += "Content-Disposition: form-data; name=\"S_341_" + recordId + "_COL0118\"\r\n"; + webKitFormOutput += "\r\n"; + webKitFormOutput += responsabiliCsv + "\r\n"; + webKitFormOutput += "------WebKitFormBoundary0123456789abcdef\r\n"; + webKitFormOutput += "Content-Disposition: form-data; name=\"S_341_" + recordId + "_COL0119\"\r\n"; + webKitFormOutput += "\r\n"; + webKitFormOutput += contraentiCsv + "\r\n"; + + bru.setVar("elixFormsWebKitFormOutput", webKitFormOutput); + // -------------------------------------------------------------------------------- + } + else + { + console.log("Cannot retrieve recordId from request " + idRequest); + }; + + // Set next request if needed + if (requestIndex < requestIds.length - 1 && requestIndex < 3) + { + bru.setVar("elixFormsQueryRequestIndex", requestIndex + 1); + bru.runner.setNextRequest("Get request details"); + } + else + { + console.log("JSON object:"); + console.log(JSON.stringify(jsonOutput)); + + // -------------------------------------------------------------------------------- + webKitFormOutput += "------WebKitFormBoundary0123456789abcdef--\r\n"; + + bru.setVar("elixFormsWebKitFormOutput", webKitFormOutput); + + console.log("--------------------------------------------------------------------------------"); + console.log("WebKitForm:"); + console.log(JSON.stringify(webKitFormOutput)); + // -------------------------------------------------------------------------------- + } + +settings: + encodeUrl: true + timeout: 0 + followRedirects: true + maxRedirects: 5 + +examples: + - name: Get Request - Success + request: + url: "{{elixFormsApiUrl_Default}}/request/:request_id/get?username={{elixFormsApiUsername}}" + method: GET + params: + - name: username + value: "{{elixFormsApiUsername}}" + type: query + description: lo username con cui si è effettuato il login + - name: recordOrder + value: NONE + type: query + description: case sensitive + disabled: true + - name: request_id + value: "7007" + type: path + body: + type: form-urlencoded + response: + statusText: "200" + headers: + - name: cache-control + value: no-cache, no-store, must-revalidate + - name: pragma + value: no-cache + - name: proxy-connection + value: Keep-Alive + - name: x-content-security-policy + value: default-src 'self'; connect-src 'self'; font-src 'none'; img-src 'self'; media-src 'self'; object-src 'self'; plugin-types application/pdf audio/x-wav; referrer no-referrer; reflected-xss block; script-src 'self'; style-src 'self' + - name: content-type + value: application/it.elixforms.api.v1.2+json;charset=UTF-8 + - name: transfer-encoding + value: chunked + - name: strict-transport-security + value: max-age=63072000;includeSubDomains + - name: content-security-policy + value: "default-src https: data: 'unsafe-inline' 'unsafe-eval'" + - name: x-frame-options + value: SAMEORIGIN + - name: x-xss-protection + value: 1;mode=block + - name: x-content-type-options + value: nosniff + - name: referrer-policy + value: unsafe-url + body: + type: text + data: |- + { + "value": { + "code": "OK", + "description": "OK", + "complete": true, + "globalStatus": "OK", + "serviceInformationList": { + "serviceInformation": [ + { + "ITSystemName": "EF-CORE", + "complete": true, + "serviceVersion": "1.2.0", + "statusDetailList": { + "statusDetail": [ + { + "code": "OK", + "description": "OK", + "detailStatus": "OK" + } + ] + } + } + ] + }, + "uuid": "1d889f27-cf95-487b-9523-84033df41391", + "version": "3.9.2.17", + "request": { + "idRequest": 7007, + "moduleCategoryTag": "ASI-RIC, CONTO_TERZI", + "moduleTag": "PROPOSTA_CCT_DOCENTE", + "moduleUrl": "https://unipr.elixforms.it/rwe2/forms/recap.jsp?IUQOID=7007&RWE2_TAB_REL=14900&IURTLGY=schemadata&ELANG=it&IATL=it", + "requestTitle": "RWE2 - Request", + "attributes": [ + { + "columnKey": "COL0008", + "columnTitle": "Created", + "columnValue": "true" + }, + { + "columnKey": "COL0009", + "columnTitle": "Created date", + "columnValue": "16-04-2025 15:39" + }, + { + "columnKey": "COL0010", + "columnTitle": "Confirmed", + "columnValue": "true" + }, + { + "columnKey": "COL0011", + "columnTitle": "Confirmed date", + "columnValue": "16-04-2025 15:41" + }, + { + "columnKey": "COL0012", + "columnTitle": "Complete", + "columnValue": "true" + }, + { + "columnKey": "COL0013", + "columnTitle": "Complete date", + "columnValue": "16-04-2025 15:41" + }, + { + "columnKey": "COL0035", + "columnTitle": "Complete (first time)", + "columnValue": "true" + }, + { + "columnKey": "COL0036", + "columnTitle": "Complete date (first time)", + "columnValue": "16-04-2025 15:41" + }, + { + "columnKey": "COL0037", + "columnTitle": "Evasa", + "columnValue": "true" + }, + { + "columnKey": "COL0038", + "columnTitle": "Data di evasione", + "columnValue": "16-04-2025 16:10" + }, + { + "columnKey": "COL0039", + "columnTitle": "Archiviata", + "columnValue": "" + }, + { + "columnKey": "COL0040", + "columnTitle": "Data di archiviazione", + "columnValue": "" + } + ], + "steps": [ + { + "conditionalForm": false, + "moduleTabGenId": 14906, + "multipleForms": false, + "stepHeader": "Richiedente", + "schemas": [ + { + "recordSize": 1, + "schemaId": 327, + "tag": "", + "title": "PROPOSTA_CCT_DOCENTE_Richiedente", + "records": [ + { + "columnSize": 4, + "recordId": 23629, + "recordNum": 1, + "sections": [ + { + "sectionKey": "SEC_0001", + "sectionTitle": "Richiedente", + "columns": [ + { + "columnKey": "COL0003", + "columnName": "COL0003", + "columnTitle": "Cognome", + "columnType": "STRING", + "columnValue": "" + }, + { + "columnKey": "COL0004", + "columnName": "COL0004", + "columnTitle": "Nome", + "columnType": "STRING", + "columnValue": "" + }, + { + "columnKey": "COL0001", + "columnName": "COL0001", + "columnTitle": "Codice Fiscale", + "columnType": "STRING", + "columnValue": "MMMPPL74T17E463A" + }, + { + "columnKey": "COL0005", + "columnName": "COL0005", + "columnTitle": "Email", + "columnType": "STRING", + "columnValue": "" + } + ] + } + ] + } + ] + } + ] + }, + { + "conditionalForm": false, + "moduleTabGenId": 18917, + "multipleForms": false, + "stepHeader": "Dati generali e Costi", + "schemas": [ + { + "recordSize": 1, + "schemaId": 326, + "tag": "", + "title": "PROPOSTA_CCT_DOCENTE_Dati_generali", + "records": [ + { + "columnSize": 20, + "recordId": 23630, + "recordNum": 1, + "sections": [ + { + "sectionKey": "SEC_0001", + "sectionTitle": "Dati del contratto", + "columns": [ + { + "exportTag": { + "exportGroup": "API;PROPOSTA_CCT_DOCENTE_GROUP", + "exportTag": "contratto.Titolo" + }, + "columnKey": "COL0005", + "columnName": "COL0005", + "columnTitle": "Titolo", + "columnType": "TEXTAREA", + "columnValue": "Titolo" + }, + { + "columnKey": "COL0006", + "columnName": "COL0006", + "columnTitle": "Struttura principale", + "columnType": "STRING", + "columnValue": "U.O. Sistemi Applicativi" + }, + { + "columnKey": "COL0007", + "columnName": "COL0007", + "columnTitle": "Codice struttura", + "columnType": "STRING", + "columnValue": "" + }, + { + "exportTag": { + "exportGroup": "API;PROPOSTA_CCT_DOCENTE_GROUP", + "exportTag": "contratto.durataInMesi" + }, + "columnKey": "COL0008", + "columnName": "COL0008", + "columnTitle": "Durata (mesi)", + "columnType": "STRING", + "columnValue": "17" + }, + { + "exportTag": { + "exportGroup": "API;PROPOSTA_CCT_DOCENTE_GROUP", + "exportTag": "contratto.corrispettivo" + }, + "columnKey": "COL0009", + "columnName": "COL0009", + "columnTitle": "Corrispettivo / contributo € (IVA esclusa)", + "columnType": "STRING", + "columnValue": "12500" + } + ] + }, + { + "sectionKey": "SEC_0002", + "sectionTitle": "Responsabile Scientifico proponente", + "columns": [ + { + "columnKey": "COL0012", + "columnName": "COL0012", + "columnTitle": "Nome", + "columnType": "STRING", + "columnValue": "Pier Paolo" + }, + { + "columnKey": "COL0013", + "columnName": "COL0013", + "columnTitle": "Cognome", + "columnType": "STRING", + "columnValue": "MAMMI" + }, + { + "columnKey": "COL0038", + "columnName": "COL0038", + "columnTitle": "Email", + "columnType": "STRING", + "columnValue": "pierpaolo.mammi@unipr.it" + }, + { + "columnKey": "COL0014", + "columnName": "COL0014", + "columnTitle": "Codice fiscale", + "columnType": "STRING", + "columnValue": "MMMPPL74T17E463A" + }, + { + "columnKey": "COL0015", + "columnName": "COL0015", + "columnTitle": "Struttura", + "columnType": "STRING", + "columnValue": "U.O. Sistemi Applicativi" + }, + { + "columnKey": "COL0016", + "columnName": "COL0016", + "columnTitle": "Codice struttura", + "columnType": "STRING", + "columnValue": "106143" + }, + { + "columnKey": "COL0046", + "columnName": "COL0046", + "columnTitle": "Titolo accademico (nascosto)", + "columnType": "STRING", + "columnValue": "" + } + ] + }, + { + "sectionKey": "SEC_0008", + "sectionTitle": "Costi", + "columns": [ + { + "columnKey": "COL0053", + "columnName": "COL0053", + "columnTitle": "Dettaglio dei costi", + "columnType": "TEXTAREA", + "columnValue": "dettaglio" + } + ] + }, + { + "sectionKey": "SEC_0009", + "sectionTitle": "Altro", + "columns": [ + { + "columnKey": "COL0054", + "columnName": "COL0054", + "columnTitle": "Note aggiuntive", + "columnType": "TEXTAREA", + "columnValue": "" + } + ] + }, + { + "sectionKey": "SEC_0006", + "sectionTitle": "", + "columns": [ + { + "columnKey": "COL0020", + "columnName": "COL0020", + "columnTitle": "UUID", + "columnType": "STRING", + "columnValue": "e116f677-a115-45eb-b51b-66f8dd754b6b" + }, + { + "columnKey": "COL0002", + "columnName": "COL0002", + "columnTitle": "JSON", + "columnType": "TEXTAREA", + "columnValue": "{"value":{"code":"OK","description":"","complete":true,"globalStatus":"OK","serviceInformationList":{"serviceInformation":[{"ITSystemName":"EF-PROXY","complete":true,"serviceVersion":"1.0.0","statusDetailList":{"statusDetail":[{"code":"OK","detailStatus":"OK"}]}}]},"uuid":"e116f677-a115-45eb-b51b-66f8dd754b6b","version":"3.0.0","json":{"idAb":"269139","matricola":"050713","nome":"Pier Paolo","cognome":"MAMMI","dataFineRapporto":null,"dataInizioRapporto":"2025-01-20","codice_attivita":"0001","descrizione_attivita":"In servizio","emailAteneo":"pierpaolo.mammi@unipr.it","cellulare_servizio":null,"ruolo":"ND","profilo":"SETTORE_10","inquadramento":"FU0","genere":"M","cod_fis":"MMMPPL74T17E463A","codice_struttura":"106143","nome_struttura":"U.O. Sistemi Applicativi","codice_struttura_padre":"106139","nome_struttura_padre":"Area - Sistemi Informativi","telefono":"0521 904145","comitato":null,"codiceSsd":"000000000000","area_disciplinare":"00","nome_sup_diretto":"Simona","cognome_sup_diretto":"BERTE'","cf_sup_diretto":"BRTSMN69B65G337A","mail_sup_diretto":"simona.berte@unipr.it","matricola_sup_diretto":"005603","nome_sup_apicale":"Candeloro","cognome_sup_apicale":"BELLANTONI","matricola_sup_apicale":"028973","cf_sup_apicale":"BLLCDL60C28H224V","mail_sup_apicale":"candeloro.bellantoni@unipr.it","pt_tipo":null,"pt_ds_tipo":null,"perc_pt":"100","descrizione_ruolo":null,"descrizione_profilo":"Settore tecnico - informatico","descrizione_inquadramento":"Area dei Funzionari","id_fascicolo_titulus":"5404836"}}}" + }, + { + "columnKey": "COL0021", + "columnName": "COL0021", + "columnTitle": "Messaggio", + "columnType": "STRING", + "columnValue": "" + }, + { + "columnKey": "COL0022", + "columnName": "COL0022", + "columnTitle": "Errore", + "columnType": "STRING", + "columnValue": "" + } + ] + }, + { + "sectionKey": "SEC_0007", + "sectionTitle": "Valori calcolati (nascosti)", + "columns": [ + { + "columnKey": "COL0052", + "columnName": "COL0052", + "columnTitle": "Docente", + "columnType": "STRING", + "columnValue": "MAMMI Pier Paolo" + }, + { + "columnKey": "COL0055", + "columnName": "COL0055", + "columnTitle": "Corrispettivo formattato", + "columnType": "STRING", + "columnValue": "12.500,00" + } + ] + } + ] + } + ] + } + ] + }, + { + "conditionalForm": false, + "moduleTabGenId": 22115, + "multipleForms": false, + "stepHeader": "Contraenti e Partecipanti", + "schemas": [ + { + "recordSize": 1, + "schemaId": 374, + "tag": "", + "title": "PROPOSTA_CCT_DOCENTE_Contraenti_Partecipanti", + "records": [ + { + "columnSize": 2, + "recordId": 23634, + "recordNum": 1, + "sections": [ + { + "sectionKey": "SEC_0001", + "sectionTitle": "Contraenti", + "columns": [ + { + "columnKey": "COL0001", + "columnName": "COL0001", + "columnTitle": "Elenco dei contraenti", + "columnType": "TEXTAREA", + "columnValue": "Contraenti" + } + ] + }, + { + "sectionKey": "SEC_0002", + "sectionTitle": "Partecipanti", + "columns": [ + { + "columnKey": "COL0002", + "columnName": "COL0002", + "columnTitle": "Elenco dei partecipanti", + "columnType": "TEXTAREA", + "columnValue": "Partecipanti" + } + ] + } + ] + } + ] + } + ] + }, + { + "conditionalForm": false, + "moduleTabGenId": 14904, + "multipleForms": false, + "stepHeader": "Dichiarazioni", + "schemas": [ + { + "recordSize": 1, + "schemaId": 325, + "tag": "", + "title": "PROPOSTA_CCT_DOCENTE_Dichiarazioni", + "records": [ + { + "columnSize": 15, + "recordId": 23635, + "recordNum": 1, + "sections": [ + { + "sectionKey": "SEC_0001", + "sectionTitle": "Dichiarazioni", + "columns": [ + { + "columnKey": "COL0001", + "columnName": "COL0001", + "columnTitle": "La/Il Prof.ssa/Prof./Dott.ssa/Dott. DICHIARA", + "columnType": "CHECKBOX", + "columnValueList": { + "columnValue": [ + { + "1": "di conoscere il testo dell'Accordo e gli adempimenti a proprio carico previsti nello stesso;" + } + ] + }, + "columnValue": null + }, + { + "columnKey": "COL0002", + "columnName": "COL0002", + "columnTitle": "", + "columnType": "CHECKBOX", + "columnValueList": { + "columnValue": [ + { + "2": "di accettare e impegnarsi a rispettare gli obblighi di segretezza e confidenzialità, la disciplina dei \"Risultati\" e/o della \"Proprietà Intellettuale\" e delle \"Pubblicazioni\", nonché tutti i termini e condizioni previsti nell'Accordo;" + } + ] + }, + "columnValue": null + }, + { + "columnKey": "COL0003", + "columnName": "COL0003", + "columnTitle": "", + "columnType": "CHECKBOX", + "columnValueList": { + "columnValue": [ + { + "3": "che le attività di cui all'Accordo non determinano alcuna violazione degli obblighi in materia di proprietà intellettuale già assunti dall'Università nei confronti di altri contraenti con i quali l'Ateneo ha sottoscritto specifici contratti/convenzioni nell'ambito dei quali il dichiarante è stato/a individuato/a come \"responsabile scientifico\";" + } + ] + }, + "columnValue": null + } + ] + }, + { + "sectionKey": "SEC_0005", + "sectionTitle": "Attività oggetto dell'accordo", + "columns": [ + { + "columnKey": "COL0018", + "columnName": "COL0018", + "columnTitle": "", + "columnType": "CHECKBOX", + "columnValueList": { + "columnValue": [ + { + "12": "che l'attività oggetto dell'accordo consiste nell'esecuzione di contratti di ricerca e/o la fornitura di servizi svolti nell'interesse di terzi;" + } + ] + }, + "columnValue": null + }, + { + "columnKey": "COL0019", + "columnName": "COL0019", + "columnTitle": "", + "columnType": "CHECKBOX", + "columnValue": null + }, + { + "columnKey": "COL0020", + "columnName": "COL0020", + "columnTitle": "", + "columnType": "CHECKBOX", + "columnValueList": { + "columnValue": [ + { + "14": "che l'attività oggetto dell'accordo consiste in attività di formazione svolta nell'interesse di terzi;" + } + ] + }, + "columnValue": null + }, + { + "columnKey": "COL0021", + "columnName": "COL0021", + "columnTitle": "", + "columnType": "CHECKBOX", + "columnValue": null + } + ] + }, + { + "sectionKey": "SEC_0006", + "sectionTitle": "Utilizzo proprietà intellettuali", + "columns": [ + { + "columnKey": "COL0005", + "columnName": "COL0005", + "columnTitle": "", + "columnType": "RADIO", + "columnValueList": { + "columnValue": [ + { + "9": "che nello svolgimento delle attività dell'Accordo VERRÀ impiegata proprietà intellettuale titolata (domanda di brevetto/brevetto avente ad oggetto invenzioni, modelli di utilità, marchi registrati, software, opere dell'ingegno) di cui l'Università è proprietaria/titolare e/o comproprietaria/contitolare secondo la normativa vigente, avente tipologia indicata nel seguito:" + } + ] + }, + "columnValue": "che nello svolgimento delle attività dell'Accordo VERRÀ impiegata proprietà intellettuale titolata (domanda di brevetto/brevetto avente ad oggetto invenzioni, modelli di utilità, marchi registrati, software, opere dell'ingegno) di cui l'Università è proprietaria/titolare e/o comproprietaria/contitolare secondo la normativa vigente, avente tipologia indicata nel seguito:" + }, + { + "columnKey": "COL0006", + "columnName": "COL0006", + "columnTitle": "", + "columnType": "TEXTAREA", + "columnValue": "sdasdasd" + } + ] + }, + { + "sectionKey": "SEC_0007", + "sectionTitle": "Presenza conflitto d'interessi", + "columns": [ + { + "columnKey": "COL0007", + "columnName": "COL0007", + "columnTitle": "", + "columnType": "RADIO", + "columnValueList": { + "columnValue": [ + { + "11": "di TROVARSI in situazioni e/o in condizioni di conflitto di interessi, anche potenziale, con riferimento all'Accordo di cui alla presente proposta secondo quanto previsto dalle disposizioni di cui alla normativa in materia inerente status giuridico, nonché dalle disposizioni contenute nel Codice di comportamento dell'Università degli Studi di Parma, avente motivazione indicata nel seguito:" + } + ] + }, + "columnValue": "di TROVARSI in situazioni e/o in condizioni di conflitto di interessi, anche potenziale, con riferimento all'Accordo di cui alla presente proposta secondo quanto previsto dalle disposizioni di cui alla normativa in materia inerente status giuridico, nonché dalle disposizioni contenute nel Codice di comportamento dell'Università degli Studi di Parma, avente motivazione indicata nel seguito:" + }, + { + "columnKey": "COL0008", + "columnName": "COL0008", + "columnTitle": "", + "columnType": "TEXTAREA", + "columnValue": "swerr523w4r5dfsdf" + } + ] + }, + { + "sectionKey": "SEC_0003", + "sectionTitle": "", + "columns": [ + { + "columnKey": "COL0012", + "columnName": "COL0012", + "columnTitle": "Luogo", + "columnType": "STRING", + "columnValue": "Parma" + }, + { + "columnKey": "COL0013", + "columnName": "COL0013", + "columnTitle": "Data", + "columnType": "STRING", + "columnValue": "16-04-2025" + } + ] + }, + { + "sectionKey": "SEC_0002", + "sectionTitle": "Valori calcolati (nascosti)", + "columns": [ + { + "columnKey": "COL0010", + "columnName": "COL0010", + "columnTitle": "Valore utilizzo brevetti", + "columnType": "STRING", + "columnValue": "" + }, + { + "columnKey": "COL0011", + "columnName": "COL0011", + "columnTitle": "Valore conflitto interessi", + "columnType": "STRING", + "columnValue": "" + } + ] + } + ] + } + ] + } + ] + }, + { + "conditionalForm": false, + "moduleTabGenId": 18920, + "multipleForms": true, + "stepHeader": "Allegati", + "schemas": [] + }, + { + "conditionalForm": false, + "moduleTabGenId": 0, + "multipleForms": false, + "stepHeader": "Riepilogo", + "schemas": [] + }, + { + "conditionalForm": false, + "moduleTabGenId": 0, + "multipleForms": false, + "stepHeader": "Convalida", + "schemas": [] + }, + { + "conditionalForm": false, + "moduleTabGenId": 0, + "multipleForms": false, + "stepHeader": "Inoltro", + "schemas": [] + } + ], + "exported_schemas": [] + }, + "requestSize": 1 + } + } + - name: Get Request - Not Found + request: + url: "{{elixFormsApiUrl_Default}}/request/:request_id/get?username={{elixFormsApiUsername}}" + method: GET + params: + - name: username + value: "{{elixFormsApiUsername}}" + type: query + description: lo username con cui si è effettuato il login + - name: request_id + value: "12" + type: path + body: + type: form-urlencoded + response: + statusText: "200" + headers: + - name: cache-control + value: no-cache, no-store, must-revalidate + - name: pragma + value: no-cache + - name: proxy-connection + value: Keep-Alive + - name: x-content-security-policy + value: default-src 'self'; connect-src 'self'; font-src 'none'; img-src 'self'; media-src 'self'; object-src 'self'; plugin-types application/pdf audio/x-wav; referrer no-referrer; reflected-xss block; script-src 'self'; style-src 'self' + - name: content-type + value: application/it.elixforms.api.v1.2+json;charset=UTF-8 + - name: content-length + value: "456" + - name: strict-transport-security + value: max-age=63072000;includeSubDomains + - name: content-security-policy + value: "default-src https: data: 'unsafe-inline' 'unsafe-eval'" + - name: x-frame-options + value: SAMEORIGIN + - name: x-xss-protection + value: 1;mode=block + - name: x-content-type-options + value: nosniff + - name: referrer-policy + value: unsafe-url + body: + type: text + data: |- + { + "value": { + "code": "WARNING", + "description": "Nessuna pratica trovata per l'id 12", + "complete": true, + "globalStatus": "WARNING", + "serviceInformationList": { + "serviceInformation": [ + { + "ITSystemName": "EF-CORE", + "complete": true, + "serviceVersion": "1.2.0", + "statusDetailList": { + "statusDetail": [ + { + "code": "WARNING", + "description": "Nessuna pratica trovata per l'id 12", + "detailStatus": "WARNING" + } + ] + } + } + ] + }, + "uuid": "05aea0b0-921c-4304-ab9c-7254ebb6cded", + "version": "3.9.2.17", + "requestSize": 0 + } + } diff --git a/bruno/collections/elixForms API v2/Runner- Get Proposta CCT matching contract IDs/Login once.yml b/bruno/collections/elixForms API v2/Runner- Get Proposta CCT matching contract IDs/Login once.yml new file mode 100644 index 0000000..f2ee4a1 --- /dev/null +++ b/bruno/collections/elixForms API v2/Runner- Get Proposta CCT matching contract IDs/Login once.yml @@ -0,0 +1,255 @@ +info: + name: Login once + type: http + seq: 3 + +http: + method: POST + url: "{{elixFormsApiUrl}}/authentication/login/v1" + headers: + - name: x-requested-with + value: XMLHttpRequest + body: + type: json + data: |- + { + "username": "{{elixFormsApiUsername}}", + "password": "{{elixFormsApiPassword}}" + } + +runtime: + scripts: + - type: after-response + code: |- + test("Status code is 200", function () { + expect(res.getStatus()).to.equal(200); + var jsonData = res.getBody(); + bru.setVar("elixFormsApiAuthToken", jsonData.value.authToken); + }); + +settings: + encodeUrl: true + timeout: 0 + followRedirects: true + maxRedirects: 5 + +examples: + - name: Login - Success + request: + url: "{{elixFormsApiUrl}}/authentication/login/v1" + method: POST + body: + type: form-urlencoded + data: + - name: username + value: "{{elixFormsApiUsername}}" + - name: password + value: "{{elixFormsApiPassword}}" + response: + statusText: "200" + headers: + - name: cache-control + value: no-cache, no-store, must-revalidate + - name: pragma + value: no-cache + - name: proxy-connection + value: Keep-Alive + - name: x-content-security-policy + value: default-src 'self'; connect-src 'self'; font-src 'none'; img-src 'self'; media-src 'self'; object-src 'self'; plugin-types application/pdf audio/x-wav; referrer no-referrer; reflected-xss block; script-src 'self'; style-src 'self' + - name: content-type + value: application/json;charset=UTF-8 + - name: strict-transport-security + value: max-age=63072000;includeSubDomains + - name: content-security-policy + value: "default-src https: data: 'unsafe-inline' 'unsafe-eval'" + - name: x-frame-options + value: SAMEORIGIN + - name: x-xss-protection + value: 1;mode=block + - name: x-content-type-options + value: nosniff + - name: referrer-policy + value: unsafe-url + - name: transfer-encoding + value: chunked + - name: vary + value: Accept-Encoding + - name: content-encoding + value: gzip + body: + type: json + data: |- + { + "value": { + "code": "OK", + "description": "OK", + "complete": true, + "globalStatus": "OK", + "resultNumber": 1, + "serviceInformationList": { + "serviceInformation": [ + { + "ITSystemName": "EF-CORE", + "complete": true, + "serviceVersion": "1.1.0", + "statusDetailList": { + "statusDetail": [ + { + "code": "OK", + "description": "OK", + "detailStatus": "OK" + } + ] + } + } + ] + }, + "uuid": "9d0ba2e7-8e98-4a7a-9fa1-67d421d0aa1e", + "version": "3.0.0", + "matchingEntitiesSize": 1, + "authToken": "2coDKQPTPJAQxWLSNRItM=" + } + } + - name: Login - Failure + request: + url: "{{elixFormsApiUrl}}/authentication/login/v1" + method: POST + body: + type: form-urlencoded + data: + - name: username + value: "{{elixFormsApiUsername}}" + - name: password + value: "{{elixFormsApiPassword}}x" + response: + statusText: "401" + headers: + - name: cache-control + value: no-cache, no-store, must-revalidate + - name: pragma + value: no-cache + - name: proxy-connection + value: Keep-Alive + - name: x-content-security-policy + value: default-src 'self'; connect-src 'self'; font-src 'none'; img-src 'self'; media-src 'self'; object-src 'self'; plugin-types application/pdf audio/x-wav; referrer no-referrer; reflected-xss block; script-src 'self'; style-src 'self' + - name: content-language + value: "" + - name: content-type + value: text/html;charset=UTF-8 + - name: content-length + value: "1074" + - name: strict-transport-security + value: max-age=63072000;includeSubDomains + - name: content-security-policy + value: "default-src https: data: 'unsafe-inline' 'unsafe-eval'" + - name: x-frame-options + value: SAMEORIGIN + - name: x-xss-protection + value: 1;mode=block + - name: x-content-type-options + value: nosniff + - name: referrer-policy + value: unsafe-url + body: + type: html + data: |- + + + + Payara Server 6.2025.1 #badassfish - Error report + + + +

HTTP Status 401 - Unauthorized

+
+

+ type Status report +

+

+ messageUnauthorized +

+

+ descriptionThis request requires HTTP authentication. +

+
+

Payara Server 6.2025.1 #badassfish

+ + + - name: Login + request: + url: "{{elixFormsApiUrl}}/authentication/login/v1" + method: POST + body: + type: form-urlencoded + data: + - name: username + value: "{{elixFormsApiUsername}}" + - name: password + value: "{{elixFormsApiPassword}}" + response: + statusText: "200" + headers: + - name: cache-control + value: no-cache, no-store, must-revalidate + - name: pragma + value: no-cache + - name: proxy-connection + value: Keep-Alive + - name: x-content-security-policy + value: default-src 'self'; connect-src 'self'; font-src 'none'; img-src 'self'; media-src 'self'; object-src 'self'; plugin-types application/pdf audio/x-wav; referrer no-referrer; reflected-xss block; script-src 'self'; style-src 'self' + - name: content-type + value: application/json;charset=UTF-8 + - name: strict-transport-security + value: max-age=63072000;includeSubDomains + - name: content-security-policy + value: "default-src https: data: 'unsafe-inline' 'unsafe-eval'" + - name: x-frame-options + value: SAMEORIGIN + - name: x-xss-protection + value: 1;mode=block + - name: x-content-type-options + value: nosniff + - name: referrer-policy + value: unsafe-url + - name: transfer-encoding + value: chunked + - name: vary + value: Accept-Encoding + - name: content-encoding + value: gzip + body: + type: json + data: |- + { + "value": { + "code": "OK", + "description": "OK", + "complete": true, + "globalStatus": "OK", + "resultNumber": 1, + "serviceInformationList": { + "serviceInformation": [ + { + "ITSystemName": "EF-CORE", + "complete": true, + "serviceVersion": "1.2.0", + "statusDetailList": { + "statusDetail": [ + { + "code": "OK", + "description": "OK", + "detailStatus": "OK" + } + ] + } + } + ] + }, + "uuid": "31ee57d5-01b9-4fce-94e2-a224282c08ec", + "version": "3.0.0", + "matchingEntitiesSize": 1, + "authToken": "Z8uKwrp86iSWykuRlRM1k=" + } + } diff --git a/bruno/collections/elixForms API v2/Runner- Get Proposta CCT matching contract IDs/Lookup requests.yml b/bruno/collections/elixForms API v2/Runner- Get Proposta CCT matching contract IDs/Lookup requests.yml new file mode 100644 index 0000000..fcbda72 --- /dev/null +++ b/bruno/collections/elixForms API v2/Runner- Get Proposta CCT matching contract IDs/Lookup requests.yml @@ -0,0 +1,276 @@ +info: + name: Lookup requests + type: http + seq: 5 + +http: + method: GET + url: "{{elixFormsApiUrl_Default}}/request/lookup/by-status?requestStatus=PROCESSED&moduleTag=PROPOSTA_CCT_OPERATORE" + headers: + - name: x-requested-with + value: XMLHttpRequest + - name: x-api-username + value: "{{elixFormsApiUsername}}" + params: + - name: requestStatus + value: SUBMITTED + type: query + description: |- + Valori possibili: + - IN_PROGRESS + - SUBMITTED + - PROCESSED + possibile selezionare valori multipli + disabled: true + - name: requestStatus + value: PROCESSED + type: query + - name: moduleTag + value: PROPOSTA_CCT_OPERATORE + type: query + description: Possibile specificare valori multipli + - name: moduleTag + value: PROPOSTA_CCT_DOCENTE + type: query + disabled: true + - name: swfOptionKey + value: "1" + type: query + disabled: true + - name: swfOptionMode + value: IN + type: query + disabled: true + auth: inherit + +runtime: + scripts: + - type: after-response + code: |- + bru.deleteVar("ef_request_cct_ids"); + // -------------------------------------------------------------------------------- + bru.deleteVar("elixFormsWebKitFormOutput"); + // -------------------------------------------------------------------------------- + + // Carica il file JSON (sostituisci con il tuo oggetto JSON) + const jsonData = res.getBody(); + const requests = jsonData.value.requests; + const requestIds = []; + for (const r of requests) + { + requestIds.push(r.requestId); + } + //console.log(requestIds); + bru.setVar("elixFormsQueryRequestIds", requestIds); + bru.setVar("elixFormsQueryRequestIndex", 0); + bru.setVar("elixFormsQueryOutput", JSON.stringify(JSON.parse("[]"))); + + // -------------------------------------------------------------------------------- + bru.setVar("elixFormsWebKitFormOutput", ""); + // -------------------------------------------------------------------------------- + +settings: + encodeUrl: true + timeout: 0 + followRedirects: true + maxRedirects: 5 + +examples: + - name: Lookup By Status (w SWF) - Success + request: + url: "{{elixFormsApiUrl_Default}}/request/lookup/by-status" + method: POST + headers: + - name: x-requested-with + value: XMLHttpRequest + body: + type: form-urlencoded + data: + - name: username + value: "{{elixFormsApiUsername}}" + - name: requestStatus + value: PROCESSED + description: |- + Valori possibili: + - IN_PROGRESS + - SUBMITTED + - PROCESSED + + possibile selezionare valori multipli + - name: moduleTag + value: PROPOSTA_CCT_OPERATORE + disabled: true + - name: moduleTag + value: PROPOSTA_CCT_DOCENTE + description: |- + Per restringere il risultato alle sole richieste del/i modulo/i aventi tag specificato + + Possibile selezionare valori multipli + - name: swfOptionKey + value: "1" + - name: swfOptionMode + value: IN + response: + statusText: "200" + headers: + - name: cache-control + value: no-cache, no-store, must-revalidate + - name: pragma + value: no-cache + - name: proxy-connection + value: Keep-Alive + - name: x-content-security-policy + value: default-src 'self'; connect-src 'self'; font-src 'none'; img-src 'self'; media-src 'self'; object-src 'self'; plugin-types application/pdf audio/x-wav; referrer no-referrer; reflected-xss block; script-src 'self'; style-src 'self' + - name: content-type + value: application/it.elixforms.api.v1+json;charset=UTF-8 + - name: content-length + value: "787" + - name: strict-transport-security + value: max-age=63072000;includeSubDomains + - name: content-security-policy + value: "default-src https: data: 'unsafe-inline' 'unsafe-eval'" + - name: x-frame-options + value: SAMEORIGIN + - name: x-xss-protection + value: 1;mode=block + - name: x-content-type-options + value: nosniff + - name: referrer-policy + value: unsafe-url + body: + type: text + data: |- + { + "value": { + "code": "OK", + "description": "OK", + "complete": true, + "globalStatus": "OK", + "serviceInformationList": { + "serviceInformation": [ + { + "ITSystemName": "EF-CORE", + "complete": true, + "serviceVersion": "1.2.0", + "statusDetailList": { + "statusDetail": [ + { + "code": "OK", + "description": "OK", + "detailStatus": "OK" + } + ] + } + } + ] + }, + "uuid": "88b0ea46-f1c2-4ed3-a5f2-1a43c6e1fd58", + "version": "3.10.0.23", + "requests": [ + { + "moduleTag": "PROPOSTA_CCT_DOCENTE", + "requestId": 10699, + "step": "Inoltrata, senza stato di workflow semplice disponibile per il modulo" + }, + { + "moduleTag": "PROPOSTA_CCT_DOCENTE", + "requestId": 10728, + "step": "Inoltrata, senza stato di workflow semplice disponibile per il modulo" + }, + { + "moduleTag": "PROPOSTA_CCT_DOCENTE", + "requestId": 10868, + "step": "Inoltrata, senza stato di workflow semplice disponibile per il modulo" + } + ], + "requestsSize": 3 + } + } + - name: Lookup By Status - Error + request: + url: "{{elixFormsApiUrl_Default}}/request/lookup/by-status" + method: POST + body: + type: form-urlencoded + data: + - name: username + value: "{{elixFormsApiUsername}}" + - name: requestStatus + value: IN_PROGRESS + description: |- + Valori possibili: + - IN_PROGRESS + - SUBMITTED + - PROCESSED + + possibile selezionare valori multipli + - name: moduleTag + value: PROPOSTA_CCT_OPERATORE + - name: moduleTag + value: PROPOSTA_CCT_DOCENTE + description: |- + Per restringere il risultato alle sole richieste del/i modulo/i aventi tag specificato + + Possibile selezionare valori multipli + disabled: true + - name: swfOptionKey + value: "1" + response: + statusText: "200" + headers: + - name: cache-control + value: no-cache, no-store, must-revalidate + - name: pragma + value: no-cache + - name: proxy-connection + value: Keep-Alive + - name: x-content-security-policy + value: default-src 'self'; connect-src 'self'; font-src 'none'; img-src 'self'; media-src 'self'; object-src 'self'; plugin-types application/pdf audio/x-wav; referrer no-referrer; reflected-xss block; script-src 'self'; style-src 'self' + - name: content-type + value: application/it.elixforms.api.v1+json;charset=UTF-8 + - name: content-length + value: "925" + - name: strict-transport-security + value: max-age=63072000;includeSubDomains + - name: content-security-policy + value: "default-src https: data: 'unsafe-inline' 'unsafe-eval'" + - name: x-frame-options + value: SAMEORIGIN + - name: x-xss-protection + value: 1;mode=block + - name: x-content-type-options + value: nosniff + - name: referrer-policy + value: unsafe-url + body: + type: text + data: |- + { + "value": { + "code": "ERROR", + "description": "Il modulo identificato dal tag \"PROPOSTA_CCT_OPERATORE\" NON contiene un workflow semplice (la scheda modulo 10 contiene un valore nullo o 0 nella colonna S_10_COL0051), ma è stato richiesto di filtrare i risultati per il valore INOLTRATA (uno stato di workflow semplice)", + "complete": true, + "globalStatus": "ERROR", + "serviceInformationList": { + "serviceInformation": [ + { + "ITSystemName": "EF-CORE", + "complete": true, + "serviceVersion": "1.2.0", + "statusDetailList": { + "statusDetail": [ + { + "code": "ERROR", + "description": "Il modulo identificato dal tag \"PROPOSTA_CCT_OPERATORE\" NON contiene un workflow semplice (la scheda modulo 10 contiene un valore nullo o 0 nella colonna S_10_COL0051), ma è stato richiesto di filtrare i risultati per il valore INOLTRATA (uno stato di workflow semplice)", + "detailStatus": "ERROR" + } + ] + } + } + ] + }, + "uuid": "ed18681c-a40e-458e-8f70-0b982a19ab0b", + "version": "3.9.2.17", + "requestsSize": 0 + } + } diff --git a/bruno/collections/elixForms API v2/Runner- Get Proposta CCT matching contract IDs/folder.yml b/bruno/collections/elixForms API v2/Runner- Get Proposta CCT matching contract IDs/folder.yml new file mode 100644 index 0000000..43cac65 --- /dev/null +++ b/bruno/collections/elixForms API v2/Runner- Get Proposta CCT matching contract IDs/folder.yml @@ -0,0 +1,7 @@ +info: + name: Runner- Get Proposta CCT matching contract IDs + type: folder + seq: 2 + +request: + auth: inherit From a533f1a66bf5940e239f30a2d722b52cc16e231e Mon Sep 17 00:00:00 2001 From: Pier Paolo MAMMI Date: Wed, 19 Aug 2026 12:11:53 +0200 Subject: [PATCH 39/40] add shibboleth collection --- bruno/collections/Shibboleth/.gitignore | 9 + .../Authorize (manual flow in browser).yml | 28 +++ .../Shibboleth/Generate Access Token.yml | 124 ++++++++++ .../Get OIDC well-known configuration.yml | 217 ++++++++++++++++++ bruno/collections/Shibboleth/Get UserInfo.yml | 83 +++++++ .../Shibboleth/environments/Shibboleth.yml | 17 ++ .../collections/Shibboleth/opencollection.yml | 21 ++ bruno/workspace.yml | 2 + 8 files changed, 501 insertions(+) create mode 100644 bruno/collections/Shibboleth/.gitignore create mode 100644 bruno/collections/Shibboleth/Authorize (manual flow in browser).yml create mode 100644 bruno/collections/Shibboleth/Generate Access Token.yml create mode 100644 bruno/collections/Shibboleth/Get OIDC well-known configuration.yml create mode 100644 bruno/collections/Shibboleth/Get UserInfo.yml create mode 100644 bruno/collections/Shibboleth/environments/Shibboleth.yml create mode 100644 bruno/collections/Shibboleth/opencollection.yml diff --git a/bruno/collections/Shibboleth/.gitignore b/bruno/collections/Shibboleth/.gitignore new file mode 100644 index 0000000..e19311f --- /dev/null +++ b/bruno/collections/Shibboleth/.gitignore @@ -0,0 +1,9 @@ +# Secrets +.env* + +# Dependencies +node_modules + +# OS files +.DS_Store +Thumbs.db \ No newline at end of file diff --git a/bruno/collections/Shibboleth/Authorize (manual flow in browser).yml b/bruno/collections/Shibboleth/Authorize (manual flow in browser).yml new file mode 100644 index 0000000..0c02bc6 --- /dev/null +++ b/bruno/collections/Shibboleth/Authorize (manual flow in browser).yml @@ -0,0 +1,28 @@ +info: + name: Authorize (manual flow in browser) + type: http + seq: 2 + +http: + method: GET + url: "{{serverUri}}/idp/profile/oidc/authorize?client_id={{clientId}}&redirect_uri={{redirectUri}}&response_type=code&scope=openid profile email" + params: + - name: client_id + value: "{{clientId}}" + type: query + - name: redirect_uri + value: "{{redirectUri}}" + type: query + - name: response_type + value: code + type: query + - name: scope + value: openid profile email + type: query + auth: inherit + +settings: + encodeUrl: true + timeout: 0 + followRedirects: true + maxRedirects: 5 diff --git a/bruno/collections/Shibboleth/Generate Access Token.yml b/bruno/collections/Shibboleth/Generate Access Token.yml new file mode 100644 index 0000000..8e629a1 --- /dev/null +++ b/bruno/collections/Shibboleth/Generate Access Token.yml @@ -0,0 +1,124 @@ +info: + name: Generate Access Token + type: http + seq: 3 + +http: + method: POST + url: "{{serverUri}}/idp/profile/oidc/token" + headers: + - name: Content-Type + value: application/x-www-form-urlencoded + body: + type: form-urlencoded + data: + - name: grant_type + value: authorization_code + - name: redirect_uri + value: "{{redirectUri}}" + - name: scope + value: openid profile email + - name: code + value: "" + description: Paste code obtained by manual flow in browser + auth: + type: basic + username: "{{clientId}}" + password: "{{clientSecret}}" + +runtime: + scripts: + - type: after-response + code: |- + var jsonData = res.getBody(); + bru.setEnvVar("accessToken", jsonData.access_token); + - type: tests + code: |- + test("Status code is 200", function () { + expect(res.getStatus()).to.equal(200); + }); + +settings: + encodeUrl: true + timeout: 0 + followRedirects: true + maxRedirects: 5 + +examples: + - name: Token data + request: + url: https://shibidp.unipr.it/idp/profile/oidc/token + method: POST + headers: + - name: Content-Type + value: application/x-www-form-urlencoded + params: + - name: client_id + value: "{{shibbolethClientId}}" + type: query + disabled: true + - name: client_secret + value: "{{shibbolethClientSecret}}" + type: query + disabled: true + - name: grant_type + value: code + type: query + disabled: true + - name: scope + value: openid + type: query + disabled: true + - name: code + value: AAdzZWNyZXQxkZu_xOleOZj6LkAn2Il3wl2T_AnIqKZ2rujs1eC6vS3QEi_Xk5cgedRG5tD9UYDN7YDBWfudDOW_mgkCjtXk4V8dCDJAU0G3mAThwV3yUhBsv1ljnZ + type: query + disabled: true + body: + type: form-urlencoded + data: + - name: grant_type + value: authorization_code + - name: redirect_uri + value: https://gitea.unipr.it/user/oauth2/Shibboleth/callback + - name: scope + value: openid profile email + - name: code + value: AAdzZWNyZXQx1CToBgEqA8mxMWGsLKf0V86PS2Oz-3bI5BlRuiitj3iXP_qfSJgNzYsMdsIQ9QRmoIOS6ISVvFSyJ5XeHYE_msw6VJELg9S6qsO4mrBBwCaUM9p3zMPwNBwZJVn6vqgGghpMS_xeW2EGthh9W0HBsh7WuPYK4HJVpTYIxgYR782xET0ZU3XxLBknOeMoye2IrH3sYpeCRQCmd1GUyTl1Ra4sGdqYcw3iiISA_FbPMXOLFQN8GcFtEcPxzc9CtH4PHKDYIj_QQx0IUgEH814pyC-Oc5-19Gfg4Ulps9ZHF9rb4csbi9mvWAuJESHcSp5NSAK9tEMFvBUCe_2nr7WyzaGTI1D6Nr1PenxbWIRAmXGF5LtzSrv-8_k8XSdufefACBVbZH6EQWm4smrqSlMab71F5s9wB3rFEK5IuANQblFljG_vfoCATpmk0MCYo47SApSrorMYN5K6yWf4P3PuyQrIdrw0PsRzBWoY8XpzQTGYN1I + response: + status: 200 + statusText: OK + headers: + - name: date + value: Wed, 19 Aug 2026 08:57:29 GMT + - name: server + value: Jetty(11.0.19) + - name: strict-transport-security + value: max-age=63072000; includeSubDomains, max-age=63072000 ; includeSubDomains ; preload + - name: x-content-type-options + value: nosniff + - name: x-frame-options + value: SAMEORIGIN, DENY + - name: cache-control + value: no-store, no-store + - name: content-type + value: application/json;charset=utf-8 + - name: pragma + value: no-cache + - name: content-security-policy + value: frame-ancestors 'none'; base-uri 'none'; script-src 'self' https://shibidp.unipr.it 'unsafe-inline'; + - name: keep-alive + value: timeout=2, max=100 + - name: connection + value: Keep-Alive + - name: transfer-encoding + value: chunked + body: + type: json + data: |- + { + "access_token": "AAdzZWNyZXQxO7PLpDizfp4m1e9ERj9_wLc2HaUQ-TtcgcG-CMvVU7D2BbfPpk1uosrMzlMXEy7SCfcrMKExh-w7xc6u4dL4M8Zz0eoZTZmPB59RhV456tGlYIV3fsxShWJzgdr2QvUdap-GVB5cWzPPaXKdBlzn_5lJfeCcoZwTdIEr6ndwNF7iuDyQ4YNbechW31Y9pD8xZYmlrtNqCfQIVkziG136n6UyMurzw1V6s3zuGQ0YXTL7E4hpjk66J7gU3hlkIM9InH9riWRgADUHvaTBdjQcq9TWWuf7-ckcy-MbHJH0_ZuAkYoKTGuXEWhchCdyJeDCZuKDiazko3C9RYQOWQqaFp5ney9Ox7sG_ZjCNY-TNvpT7YmeOm_8lTGTGSnd4lumPIHiRlwSG_8IEa06SRg4rnz9kudM0Hnto2VsgZ4PtImQlGC3H8Zbw60Jrwvxw_fvxRkXeBOx5IdElMRKhvsRogA8me6-gSVIl8Q", + "scope": "openid profile email", + "id_token": "eyJraWQiOiJkZWZhdWx0UlNBU2lnbiIsImFsZyI6IlJTMjU2In0.eyJhdF9oYXNoIjoieTdUSjczeDNsbDF0ZEI5bU96RmtQUSIsInN1YiI6ImIwYTUwMmY2YWQ5MDQyN2YxZTZjYTdjODVhNzZjY2NiOGI5MzVhZjRkMjc1MDQyMTFhMDQwMGI0MmY5MGMxNDFAdW5pcHIuaXQiLCJhdWQiOiJvaWRjX2dpdGVhXzAxIiwiYXV0aF90aW1lIjoxNzg3MTI5ODQyLCJpc3MiOiJodHRwczovL3NoaWJpZHAudW5pcHIuaXQiLCJleHAiOjE3ODcxMzM0NDksImlhdCI6MTc4NzEyOTg0OSwic2lkIjoiX2UwMWJiZDkwMzQ5ODMzNDNkM2U0MmE5OTU5NDIyYmUzIn0.k5AQaood5q4ynRmYgC20cFV7cpBVrLwFC6Bi05PGvWFmnu5_u3nI4yAngM-u3qe7ILiJnsYsFuo3UUMowoJkycX5PveAo1x239_vK6Opp8VTQuCF4H8h4OmBjXj0eeCEQ3W00TUgV6S4rHU5NEvwiGR9ivEjZvVf1y2dzral7_DgX1KOQq5ZH5wma2Y5zM4el02pGEnPmi3P1zOXp1AQDx69cpZQj5UkKc15L8Y1yaJILMIDbsXgimSx1FGs_XA9bjSHdV2V25_h3TqsUxElwvb1uVk_kUqj06rDgORpnS_7Hg778GtW8kYZCz2kIYpYWi1h3tHhNnBOtHjxqepGyQ", + "token_type": "Bearer", + "expires_in": 600 + } diff --git a/bruno/collections/Shibboleth/Get OIDC well-known configuration.yml b/bruno/collections/Shibboleth/Get OIDC well-known configuration.yml new file mode 100644 index 0000000..e8ec70d --- /dev/null +++ b/bruno/collections/Shibboleth/Get OIDC well-known configuration.yml @@ -0,0 +1,217 @@ +info: + name: Get OIDC well-known configuration + type: http + seq: 1 + +http: + method: GET + url: "{{serverUri}}/.well-known/openid-configuration" + auth: inherit + +settings: + encodeUrl: true + timeout: 0 + followRedirects: true + maxRedirects: 5 + +examples: + - name: Endpoints + request: + url: https://shibidp.unipr.it/.well-known/openid-configuration + method: GET + response: + status: 200 + statusText: OK + headers: + - name: date + value: Wed, 19 Aug 2026 07:20:27 GMT + - name: server + value: Jetty(11.0.19) + - name: strict-transport-security + value: max-age=63072000; includeSubDomains, max-age=63072000 ; includeSubDomains ; preload + - name: x-content-type-options + value: nosniff + - name: x-frame-options + value: SAMEORIGIN, DENY + - name: expires + value: "" + - name: cache-control + value: no-store + - name: content-type + value: application/json;charset=utf-8 + - name: content-security-policy + value: frame-ancestors 'none'; base-uri 'none'; script-src 'self' https://shibidp.unipr.it 'unsafe-inline'; + - name: set-cookie + value: __Host-JSESSIONID=node01shvwd2kdnmjg1lxw0l50a24k060260.node0; Path=/; Secure; HttpOnly + - name: keep-alive + value: timeout=2, max=100 + - name: connection + value: Keep-Alive + - name: transfer-encoding + value: chunked + body: + type: json + data: |- + { + "authorization_endpoint": "https://shibidp.unipr.it/idp/profile/oidc/authorize", + "token_endpoint": "https://shibidp.unipr.it/idp/profile/oidc/token", + "registration_endpoint": "https://shibidp.unipr.it/idp/profile/oidc/register", + "introspection_endpoint": "https://shibidp.unipr.it/idp/profile/oauth2/introspection", + "revocation_endpoint": "https://shibidp.unipr.it/idp/profile/oauth2/revocation", + "issuer": "https://shibidp.unipr.it", + "jwks_uri": "https://shibidp.unipr.it/idp/profile/oidc/keyset", + "scopes_supported": [ + "openid", + "profile", + "email", + "spid", + "offline_access" + ], + "response_types_supported": [ + "id_token", + "code", + "code id_token", + "code id_token token" + ], + "response_modes_supported": [ + "query", + "fragment", + "form_post" + ], + "grant_types_supported": [ + "authorization_code", + "implicit", + "refresh_token" + ], + "token_endpoint_auth_methods_supported": [ + "client_secret_basic", + "client_secret_post", + "client_secret_jwt", + "private_key_jwt" + ], + "request_object_signing_alg_values_supported": [ + "none", + "RS256", + "RS384", + "RS512", + "HS256", + "HS384", + "HS512", + "ES256", + "ES384", + "ES512" + ], + "request_parameter_supported": true, + "request_uri_parameter_supported": true, + "require_request_uri_registration": true, + "subject_types_supported": [ + "public", + "pairwise" + ], + "userinfo_endpoint": "https://shibidp.unipr.it/idp/profile/oidc/userinfo", + "id_token_signing_alg_values_supported": [ + "RS256", + "RS384", + "RS512", + "HS256", + "HS384", + "HS512", + "ES256", + "ES384", + "ES512", + "PS256", + "PS384", + "PS512" + ], + "id_token_encryption_alg_values_supported": [ + "RSA1_5", + "RSA-OAEP", + "RSA-OAEP-256", + "RSA-OAEP-384", + "RSA-OAEP-512", + "A128KW", + "A192KW", + "A256KW", + "A128GCMKW", + "A192GCMKW", + "A256GCMKW", + "ECDH-ES", + "ECDH-ES+A128KW", + "ECDH-ES+A192KW", + "ECDH-ES+A256KW" + ], + "id_token_encryption_enc_values_supported": [ + "A128CBC-HS256", + "A192CBC-HS384", + "A256CBC-HS512", + "A128GCM", + "A192GCM", + "A256GCM" + ], + "userinfo_signing_alg_values_supported": [ + "RS256", + "RS384", + "RS512", + "HS256", + "HS384", + "HS512", + "ES256", + "ES384", + "ES512", + "PS256", + "PS384", + "PS512" + ], + "userinfo_encryption_alg_values_supported": [ + "RSA1_5", + "RSA-OAEP", + "RSA-OAEP-256", + "RSA-OAEP-384", + "RSA-OAEP-512", + "A128KW", + "A192KW", + "A256KW", + "A128GCMKW", + "A192GCMKW", + "A256GCMKW", + "ECDH-ES", + "ECDH-ES+A128KW", + "ECDH-ES+A192KW", + "ECDH-ES+A256KW" + ], + "userinfo_encryption_enc_values_supported": [ + "A128CBC-HS256", + "A192CBC-HS384", + "A256CBC-HS512", + "A128GCM", + "A192GCM", + "A256GCM" + ], + "display_values_supported": [ + "page" + ], + "claims_supported": [ + "aud", + "iss", + "sub", + "iat", + "exp", + "acr", + "auth_time", + "email", + "name", + "family_name", + "given_name", + "updated_at", + "codicefiscale", + "unipr_spid_email", + "spidName", + "spidFamilyName", + "spidCode", + "spidFiscalNumber", + "externalIDPLoA", + "externalIDPType", + "eduPersonScopedAffiliation" + ], + "claims_parameter_supported": true + } diff --git a/bruno/collections/Shibboleth/Get UserInfo.yml b/bruno/collections/Shibboleth/Get UserInfo.yml new file mode 100644 index 0000000..a6e60dd --- /dev/null +++ b/bruno/collections/Shibboleth/Get UserInfo.yml @@ -0,0 +1,83 @@ +info: + name: Get UserInfo + type: http + seq: 4 + +http: + method: GET + url: "{{serverUri}}/idp/profile/oidc/userinfo?client_id={{clientId}}&client_secret={{clientSecret}}" + headers: + - name: Content-Type + value: application/x-www-form-urlencoded + params: + - name: client_id + value: "{{clientId}}" + type: query + - name: client_secret + value: "{{clientSecret}}" + type: query + auth: + type: bearer + token: "{{accessToken}}" + +settings: + encodeUrl: true + timeout: 0 + followRedirects: true + maxRedirects: 5 + +examples: + - name: UserInfo data + request: + url: https://shibidp.unipr.it/idp/profile/oidc/userinfo?client_id={{shibbolethClientId}}&client_secret={{shibbolethClientSecret}} + method: GET + headers: + - name: Content-Type + value: application/x-www-form-urlencoded + params: + - name: client_id + value: "{{shibbolethClientId}}" + type: query + - name: client_secret + value: "{{shibbolethClientSecret}}" + type: query + response: + status: 200 + statusText: OK + headers: + - name: date + value: Wed, 19 Aug 2026 08:58:14 GMT + - name: server + value: Jetty(11.0.19) + - name: strict-transport-security + value: max-age=63072000; includeSubDomains, max-age=63072000 ; includeSubDomains ; preload + - name: x-content-type-options + value: nosniff + - name: x-frame-options + value: SAMEORIGIN, DENY + - name: cache-control + value: no-store + - name: content-type + value: application/json;charset=utf-8 + - name: content-security-policy + value: frame-ancestors 'none'; base-uri 'none'; script-src 'self' https://shibidp.unipr.it 'unsafe-inline'; + - name: keep-alive + value: timeout=2, max=100 + - name: connection + value: Keep-Alive + - name: transfer-encoding + value: chunked + body: + type: json + data: |- + { + "sub": "b0a502f6ad90427f1e6ca7c85a76cccb8b935af4d27504211a0400b42f90c141@unipr.it", + "codicefiscale": "MMMPPL74T17E463A", + "eduPersonScopedAffiliation": "staff@unipr.it alum@unipr.it member@unipr.it", + "name": "Pier Paolo MAMMI", + "eduPersonPrincipalName": "pierpaolo.mammi@unipr.it", + "given_name": "Pier Paolo", + "family_name": "MAMMI", + "matricola": "135097", + "email": "pierpaolo.mammi@unipr.it" + } diff --git a/bruno/collections/Shibboleth/environments/Shibboleth.yml b/bruno/collections/Shibboleth/environments/Shibboleth.yml new file mode 100644 index 0000000..c20d53c --- /dev/null +++ b/bruno/collections/Shibboleth/environments/Shibboleth.yml @@ -0,0 +1,17 @@ +name: Shibboleth +variables: + - name: clientId + value: "{{process.env.client_id}}" + description: "" + - name: clientSecret + value: "{{process.env.client_secret}}" + description: "" + - name: redirectUri + value: https://gitea.unipr.it/user/oauth2/Shibboleth/callback + description: "" + - name: accessToken + value: AAdzZWNyZXQx1CToBgEqA8mxMWGsLKf0V86PS2Oz-3bI5BlRuiitj3iXP_qfSJgNzYsMdsIQ9QRmoIOS6ISVvFSyJ5XeHYE_msw6VJELg9S6qsO4mrBBwCaUM9p3zMPwNBwZJVn6vqgGghpMS_xeW2EGthh9W0HBsh7WuPYK4HJVpTYIxgYR782xET0ZU3XxLBknOeMoye2IrH3sYpeCRQCmd1GUyTl1Ra4sGdqYcw3iiISA_FbPMXOLFQN8GcFtEcPxzc9CtH4PHKDYIj_QQx0IUgEH814pyC-Oc5-19Gfg4Ulps9ZHF9rb4csbi9mvWAuJESHcSp5NSAK9tEMFvBUCe_2nr7WyzaGTI1D6Nr1PenxbWIRAmXGF5LtzSrv-8_k8XSdufefACBVbZH6EQWm4smrqSlMab71F5s9wB3rFEK5IuANQblFljG_vfoCATpmk0MCYo47SApSrorMYN5K6yWf4P3PuyQrIdrw0PsRzBWoY8XpzQTGYN1I + description: "" + - name: serverUri + value: https://shibidp.unipr.it + description: "" diff --git a/bruno/collections/Shibboleth/opencollection.yml b/bruno/collections/Shibboleth/opencollection.yml new file mode 100644 index 0000000..8945583 --- /dev/null +++ b/bruno/collections/Shibboleth/opencollection.yml @@ -0,0 +1,21 @@ +opencollection: 1.0.0 + +info: + name: Shibboleth +config: + proxy: + inherit: true + config: + protocol: http + hostname: "" + port: "" + auth: + username: "" + password: "" + bypassProxy: "" +bundled: false +extensions: + bruno: + ignore: + - node_modules + - .git diff --git a/bruno/workspace.yml b/bruno/workspace.yml index 2f18ad4..ccb517b 100644 --- a/bruno/workspace.yml +++ b/bruno/workspace.yml @@ -24,6 +24,8 @@ collections: path: "collections/ESSE3 Common Auth API" - name: "ESSE3 Anagrafica API" path: "collections/ESSE3 Anagrafica API" + - name: "Shibboleth" + path: "collections/Shibboleth" specs: From 54aa12244a97e7ea4b7690327c623e2c3ba63560 Mon Sep 17 00:00:00 2001 From: Pier Paolo MAMMI Date: Wed, 19 Aug 2026 14:52:05 +0200 Subject: [PATCH 40/40] add readme file --- README.md | 50 ++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 50 insertions(+) create mode 100644 README.md diff --git a/README.md b/README.md new file mode 100644 index 0000000..f3b71c5 --- /dev/null +++ b/README.md @@ -0,0 +1,50 @@ +# API collections + +This is the repository where most frequent HTTP requests are stored as Bruno collections. + +## Requisites + +A Windows-based OS with Powershell version >= 7.5.x + +One or more of: + +- Bruno desktop client () +- VSCode () with httpyac extension () + +## Preparation + +After having cloned the repository, move in the root folder and follow these steps: + +1. launch `setup-tools.bat`: this will check the current Powershell environment and try to install required modules +2. launch `setup-json-environment.bat`: follow the instrucions to generate a base environment file starting form the structure defined in the `env.json.template` file; at the end of the process you should have a `env.json` file in the root folder containing base values and secrets + +### Bruno collections + +If you have Bruno installed and intend to use it as the main tool, also do the following: + +1. launch `update-bruno-environments.bat`: the script will generate an environment file named `.env` in each one of the Bruno collection folders, using the base environment generated in the previous step; this minimizes the manual intervention needed to insert secrets in those collections +2. launch Bruno and open the base collection folder named `bruno`. + +### httpyac requests + +If you want to use VSCode with httpyac extension, also do the following: + +1. launch `generate-httpyac-requests.bat`: the script will create an `autodocs/httpyac` folder in the root of the project containing the same Bruno requests in a standard HTTP format which can be read by VSCode and/or httpyac extension +2. launch `update-httpyac-environments.bat`: the script will generate an environment file named `.env` in each one of the generated folders, using the base environment generated in the previous step +3. launch VSCode and open the base project folder: with the explorer navigate to the `autodocs/httpyac` folder and browse to the request you want to use + +## Development + +**The main development tool to be used to manage API requests is Bruno.** + +The autodocs folder and its subfolder is (and must be) excluded from versioning: if you need to persist updates of any kind, this must be done through Bruno, because modifications to anything under autodocs will be ignored. + +### Secrets management + +Be careful to not save secret values in Bruno requests or anywhere else! + +To make secret management easier in Bruno, in each collection there is an environment file called `.env.template`: this file contains the Bruno variables whose values must not be versioned with an empty value. + +**Note**: it's strongly suggested to use the `update-*-environments.bat` scripts to automatically generate the local environment files. + +If you want to proceed manually, you should just copy-paste the template file to a new `.env` file and insert the appropriate secret values; this works because only the `.env.template` file is versioned, while all other `.env*` files are excluded.