feat: allow duplicate http names by method#7949
Conversation
WalkthroughThis PR enables requests with identical names but different HTTP methods within a single folder. It introduces HTTP method-aware request filename utilities (e.g., "GET projects", "POST projects") across app, CLI, converters, and Electron packages; integrates auto-filename generation in request creation/rename UI with manual-edit detection; and updates collection import and API specification converters to use per-folder unique filename tracking. ChangesHTTP Method-Aware Request Filenames
Estimated code review effort🎯 4 (Complex) | ⏱️ ~60 minutes Possibly related PRs
Suggested labels
Suggested reviewers
Poem
🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches🧪 Generate unit tests (beta)
Tip 💬 Introducing Slack Agent: The best way for teams to turn conversations into code.Slack Agent is built on CodeRabbit's deep understanding of your code, so your team can collaborate across the entire SDLC without losing context.
Built for teams:
One agent for your entire SDLC. Right inside Slack. Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Actionable comments posted: 2
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
packages/bruno-electron/src/ipc/collection.js (1)
1344-1350:⚠️ Potential issue | 🟡 Minor | ⚡ Quick win
folderContent.name = item.nameis a no-op —stringifyFolderreturns a string.
stringifyFolderreturns a serialized string; assigning a property to it does nothing in JavaScript. The intent was presumably to override the folder name before writing, but it has no effect — the file is written with whatever was already initem.root.If the name in
item.root.meta.nameis always consistent withitem.name(expected during clone), this is harmless dead code. If not, the folder file will silently contain a stale name.🐛 Proposed fix
if (item.root) { + if (item.root.meta) item.root.meta.name = item.name; const folderContent = await stringifyFolder(item.root, { format }); - folderContent.name = item.name; if (folderContent) { const folderFilePath = path.join(folderPath, `folder.${format}`); safeWriteFileSync(folderFilePath, folderContent); } }🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@packages/bruno-electron/src/ipc/collection.js` around lines 1344 - 1350, The code assigns to folderContent.name but stringifyFolder(item.root, { format }) returns a string, so folderContent.name is a no-op; update the logic to mutate the folder data before serialization: set the desired name on the source object (e.g., item.root.meta.name = item.name) or pass an override name into stringifyFolder if it supports options, then call stringifyFolder and write the returned string with safeWriteFileSync to folderFilePath; ensure you update the call site around stringifyFolder, item.root, folderFilePath, and safeWriteFileSync so the serialized file contains the correct name.
🧹 Nitpick comments (6)
packages/bruno-app/src/components/Sidebar/NewRequest/index.js (1)
276-287: ⚡ Quick winAdd behavior tests for auto-filename/manual-override transitions in New Request.
This flow now has multiple conditional update paths (name/method/requestType/cURL parsing/manual-edit), and it should be locked with focused tests.
As per coding guidelines, "Add tests for any new functionality or meaningful changes... Focus on testing behaviour that is critical, complex, or likely to break."
Also applies to: 295-350
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@packages/bruno-app/src/components/Sidebar/NewRequest/index.js` around lines 276 - 287, Add behavior tests that cover setAutoFilename's conditional filename updates and manual-override behavior: write unit tests for the New Request component invoking setAutoFilename (or simulating user interactions that call it) to verify that when isFilenameManuallyEdited is false the filename field (formik.values.filename / formik.setFieldValue) updates for changes in requestName, requestMethod, and requestType (including when requestType === 'from-curl' using curlRequestTypeDetected fallback), and that when isFilenameManuallyEdited is true the filename does not change; also add tests for transitions (toggle manual edit on/off) to ensure auto-updates resume after manual-override is cleared and that getRequestFilenameBase is used to compute the value.packages/bruno-converters/src/postman/postman-to-bruno.js (1)
367-450: 💤 Low valueLGTM on the dedup wiring. 🧵
usedRequestFilenamesis created insideimportPostmanV2CollectionItem, which is invoked recursively per folder (line 419) — so each folder ends up with its own filename namespace, which lines up nicely with the on-disk folder structure.Tiny nit on lines 441–442:
const requestName = baseRequestName;is a leftover alias from the prior dedup logic and can be folded into a single declaration. Not blocking.♻️ Optional simplification
- const baseRequestName = i.name || 'Untitled Request'; - const requestName = baseRequestName; + const requestName = i.name || 'Untitled Request'; const filename = getUniqueHttpRequestFilename(requestName, method, usedRequestFilenames);🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@packages/bruno-converters/src/postman/postman-to-bruno.js` around lines 367 - 450, The code contains a redundant alias where baseRequestName is declared then immediately copied into requestName inside importPostmanV2CollectionItem; collapse these into a single declaration by removing baseRequestName and declaring requestName directly from i.name (e.g., replace the two declarations with one that sets requestName = i.name || 'Untitled Request') and keep using requestName for filename generation and the brunoRequestItem.packages/bruno-electron/src/utils/request-filename.js (1)
43-61: 💤 Low valueNo upper bound on the collision-avoidance counter loop.
If
checkExistswere to behave unexpectedly (e.g., always returnstrue), the loop has no exit. Practically this won't happen with well-formed callers, but a max guard keeps the contract explicit.♻️ Proposed guard
+const MAX_COUNTER = 9999; let counter = 1; let uniqueFilename = `${baseName} ${counter}.${extension}`; -while (checkExists(uniqueFilename)) { +while (checkExists(uniqueFilename) && counter <= MAX_COUNTER) { counter++; uniqueFilename = `${baseName} ${counter}.${extension}`; }🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@packages/bruno-electron/src/utils/request-filename.js` around lines 43 - 61, The getUniqueRequestFilename function currently loops until checkExists returns false with no upper bound; add a max-attempts guard (e.g., MAX_ATTEMPTS constant) and break/throw after exceeding it to avoid infinite loops if checkExists misbehaves. Update the loop that increments counter and builds uniqueFilename in getUniqueRequestFilename to stop once counter > MAX_ATTEMPTS and either throw a descriptive error (including baseName and extension) or return a safe fallback filename, ensuring callers can handle the failure.packages/bruno-electron/src/utils/request-filename.test.js (1)
1-25: ⚡ Quick win
getRequestFilenamehas zero test coverage.The three branching paths in
getRequestFilename(item.filenamepresent,type === 'http-request', and the fallback for graphql/grpc/ws) are untested, and the no-collision base case forgetUniqueRequestFilenameis also missing.As per coding guidelines, new functionality should have corresponding tests covering the happy path and problematic paths.
✅ Suggested additions
+it('getRequestFilename uses item.filename when present', () => { + const item = { filename: 'custom name.bru', type: 'http-request', name: 'ignored', request: { method: 'GET' } }; + const { getRequestFilename } = require('./request-filename'); + expect(getRequestFilename(item, 'bru')).toBe('custom name.bru'); +}); + +it('getRequestFilename uses method prefix for http-request', () => { + const item = { type: 'http-request', name: '/projects', request: { method: 'POST' } }; + const { getRequestFilename } = require('./request-filename'); + expect(getRequestFilename(item, 'bru')).toBe('POST projects.bru'); +}); + +it('getRequestFilename uses plain name for non-http types', () => { + const item = { type: 'graphql-request', name: 'My Query' }; + const { getRequestFilename } = require('./request-filename'); + expect(getRequestFilename(item, 'bru')).toBe('My Query.bru'); +}); + +it('returns filename unchanged when no collision', () => { + const item = { type: 'http-request', name: '/users', request: { method: 'GET' } }; + expect(getUniqueRequestFilename(item, 'bru', () => false)).toBe('GET users.bru'); +}); + +it('increments counter past 1 when multiple collisions exist', () => { + const existing = new Set(['GET users.bru', 'GET users 1.bru']); + const item = { type: 'http-request', name: '/users', request: { method: 'GET' } }; + expect(getUniqueRequestFilename(item, 'bru', (f) => existing.has(f))).toBe('GET users 2.bru'); +});🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@packages/bruno-electron/src/utils/request-filename.test.js` around lines 1 - 25, Add unit tests in request-filename.test.js to cover all branches of getRequestFilename: (1) when item.filename is provided, assert it returns that filename, (2) when item.type === 'http-request' verify it delegates to getHttpRequestFilenameBase and respects method/name, and (3) the fallback branch for graphql/grpc/ws items (e.g., type !== 'http-request') to ensure the appropriate normalized filename is returned; also add the missing no-collision base case for getUniqueRequestFilename to assert that when the collision checker returns false the filename is returned without a counter, and include tests for normalizeRequestFilename behavior where relevant.packages/bruno-electron/src/ipc/openapi-sync.js (1)
1238-1247: ⚡ Quick winThree
getUniqueRequestFilenamecall sites lack in-memoryfilenamesInFoldertracking — inconsistent with every other call site in this PR.All three locations (reset mode at line 1245, sync add-new at line 1376, add-missing at line 1622) rely solely on
fs.existsSync. This works today because each write is awaited before the next check, but it diverges from thefilenamesInFolder.has || fs.existsSyncpattern used incollection-import.jsandcollection.js. Two spec endpoints that sanitize to the same filename within the same folder would collide in the window betweengetUniqueRequestFilenamereturning andwriteFilecompleting.♻️ Example fix pattern (apply identically at all 3 sites)
+const filenamesInFolder = new Map(); // keyed by targetFolder path for (const [, specItem] of specItemsMap) { let targetFolder = collectionPath; if (specItem.folderName && groupBy === 'tags') { targetFolder = await ensureTagFolder(collectionPath, specItem.folderName, format); } + if (!filenamesInFolder.has(targetFolder)) filenamesInFolder.set(targetFolder, new Set()); + const folderSet = filenamesInFolder.get(targetFolder); const requestContent = await stringifyRequestViaWorker(specItem, { format }); - const sanitizedFilename = getUniqueRequestFilename(specItem, format, (filename) => fs.existsSync(path.join(targetFolder, filename))); + const sanitizedFilename = getUniqueRequestFilename(specItem, format, (filename) => folderSet.has(filename) || fs.existsSync(path.join(targetFolder, filename))); + folderSet.add(sanitizedFilename); await writeFile(path.join(targetFolder, sanitizedFilename), requestContent); }Also applies to: 1368-1378, 1619-1624
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@packages/bruno-electron/src/ipc/openapi-sync.js` around lines 1238 - 1247, The three call sites that invoke getUniqueRequestFilename (inside the loop that may call ensureTagFolder, and the other two similar sites) must use an in-memory filenamesInFolder Set like other files in this PR: initialize or reuse a Set for the targetFolder, pass a checker callback to getUniqueRequestFilename that returns filenamesInFolder.has(filename) || fs.existsSync(path.join(targetFolder, filename)), then immediately add the returned sanitized filename to filenamesInFolder before awaiting writeFile; apply this same pattern to the reset mode, sync add-new, and add-missing loops so concurrent/same-run collisions are prevented.packages/bruno-cli/src/utils/request-filename.js (1)
1-68: ⚡ Quick winDuplicate file and inconsistent
sanitizeNameimplementations need consolidation.
packages/bruno-cli/src/utils/request-filename.jsandpackages/bruno-electron/src/utils/request-filename.jsare identical; any future fix requires manual synchronization across both packages.The local
sanitizeNamein request-filename.js differs from the one in filesystem.js: the CLI filesystem version uses/^[.\s-]+/to remove leading dots, hyphens, and spaces, while request-filename versions use/^[\s\-]+/to remove only leading spaces and hyphens. This inconsistency means folder names and request filenames could be sanitized by different rules, creating potential naming conflicts or unexpected behavior across the CLI and Electron packages.Consider consolidating both
request-filename.jsfiles and aligningsanitizeNameimplementations across the codebase to use a single, consistent function.🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@packages/bruno-cli/src/utils/request-filename.js` around lines 1 - 68, Two problems: the sanitizeName implementation in request-filename.js diverges from filesystem.js and the same request-filename logic is duplicated in two packages; consolidate and align them. Create a single shared sanitize utility (exporting sanitizeName) and update getHttpRequestFilenameBase, normalizeRequestFilename, getRequestFilename and getUniqueRequestFilename to import and use that shared sanitizeName; ensure the canonical sanitizeName uses the filesystem.js pattern (/^[.\s-]+/ for leading chars and the same trailing removal) so both CLI and Electron use identical sanitization, and replace the duplicated request-filename.js copies to import the shared module.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@packages/bruno-app/src/components/Sidebar/NewRequest/index.js`:
- Around line 77-79: curlRequestTypeChange currently only calls
setCurlRequestTypeDetected, leaving an auto-generated filename stale when the
user toggles between HTTP and GraphQL; update curlRequestTypeChange to also
detect if the filename is in auto-mode (the auto flag, e.g., isFilenameAuto or
filenameAuto) and when true compute the new auto filename (use the existing
helper that derives the auto name or replicate its logic) and call setFilename
with that value (and ensure the auto flag remains true via setIsFilenameAuto if
applicable); apply the same change pattern to the other handler(s) referenced
around lines 603-615 so toggling the cURL type always resyncs the auto filename.
In `@packages/bruno-app/src/utils/common/requestFilename.js`:
- Around line 20-23: The code lowercases the extension into the variable
extension and then passes that lowercased value to path.basename, which breaks
when the file's actual suffix has different casing; change the logic to keep a
lowercased copy for the includes check but obtain the original-case suffix (e.g.
const origExt = path.extname(filename)) and pass origExt to path.basename when
stripping (use extensionLower = origExt.toLowerCase() for the includes check and
call path.basename(filename, origExt) when creating baseName), ensuring
filename, extension (origExt), and baseName references are updated accordingly.
---
Outside diff comments:
In `@packages/bruno-electron/src/ipc/collection.js`:
- Around line 1344-1350: The code assigns to folderContent.name but
stringifyFolder(item.root, { format }) returns a string, so folderContent.name
is a no-op; update the logic to mutate the folder data before serialization: set
the desired name on the source object (e.g., item.root.meta.name = item.name) or
pass an override name into stringifyFolder if it supports options, then call
stringifyFolder and write the returned string with safeWriteFileSync to
folderFilePath; ensure you update the call site around stringifyFolder,
item.root, folderFilePath, and safeWriteFileSync so the serialized file contains
the correct name.
---
Nitpick comments:
In `@packages/bruno-app/src/components/Sidebar/NewRequest/index.js`:
- Around line 276-287: Add behavior tests that cover setAutoFilename's
conditional filename updates and manual-override behavior: write unit tests for
the New Request component invoking setAutoFilename (or simulating user
interactions that call it) to verify that when isFilenameManuallyEdited is false
the filename field (formik.values.filename / formik.setFieldValue) updates for
changes in requestName, requestMethod, and requestType (including when
requestType === 'from-curl' using curlRequestTypeDetected fallback), and that
when isFilenameManuallyEdited is true the filename does not change; also add
tests for transitions (toggle manual edit on/off) to ensure auto-updates resume
after manual-override is cleared and that getRequestFilenameBase is used to
compute the value.
In `@packages/bruno-cli/src/utils/request-filename.js`:
- Around line 1-68: Two problems: the sanitizeName implementation in
request-filename.js diverges from filesystem.js and the same request-filename
logic is duplicated in two packages; consolidate and align them. Create a single
shared sanitize utility (exporting sanitizeName) and update
getHttpRequestFilenameBase, normalizeRequestFilename, getRequestFilename and
getUniqueRequestFilename to import and use that shared sanitizeName; ensure the
canonical sanitizeName uses the filesystem.js pattern (/^[.\s-]+/ for leading
chars and the same trailing removal) so both CLI and Electron use identical
sanitization, and replace the duplicated request-filename.js copies to import
the shared module.
In `@packages/bruno-converters/src/postman/postman-to-bruno.js`:
- Around line 367-450: The code contains a redundant alias where baseRequestName
is declared then immediately copied into requestName inside
importPostmanV2CollectionItem; collapse these into a single declaration by
removing baseRequestName and declaring requestName directly from i.name (e.g.,
replace the two declarations with one that sets requestName = i.name ||
'Untitled Request') and keep using requestName for filename generation and the
brunoRequestItem.
In `@packages/bruno-electron/src/ipc/openapi-sync.js`:
- Around line 1238-1247: The three call sites that invoke
getUniqueRequestFilename (inside the loop that may call ensureTagFolder, and the
other two similar sites) must use an in-memory filenamesInFolder Set like other
files in this PR: initialize or reuse a Set for the targetFolder, pass a checker
callback to getUniqueRequestFilename that returns
filenamesInFolder.has(filename) || fs.existsSync(path.join(targetFolder,
filename)), then immediately add the returned sanitized filename to
filenamesInFolder before awaiting writeFile; apply this same pattern to the
reset mode, sync add-new, and add-missing loops so concurrent/same-run
collisions are prevented.
In `@packages/bruno-electron/src/utils/request-filename.js`:
- Around line 43-61: The getUniqueRequestFilename function currently loops until
checkExists returns false with no upper bound; add a max-attempts guard (e.g.,
MAX_ATTEMPTS constant) and break/throw after exceeding it to avoid infinite
loops if checkExists misbehaves. Update the loop that increments counter and
builds uniqueFilename in getUniqueRequestFilename to stop once counter >
MAX_ATTEMPTS and either throw a descriptive error (including baseName and
extension) or return a safe fallback filename, ensuring callers can handle the
failure.
In `@packages/bruno-electron/src/utils/request-filename.test.js`:
- Around line 1-25: Add unit tests in request-filename.test.js to cover all
branches of getRequestFilename: (1) when item.filename is provided, assert it
returns that filename, (2) when item.type === 'http-request' verify it delegates
to getHttpRequestFilenameBase and respects method/name, and (3) the fallback
branch for graphql/grpc/ws items (e.g., type !== 'http-request') to ensure the
appropriate normalized filename is returned; also add the missing no-collision
base case for getUniqueRequestFilename to assert that when the collision checker
returns false the filename is returned without a counter, and include tests for
normalizeRequestFilename behavior where relevant.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
Run ID: 7e4e7300-6838-48ee-b2f2-5b02d0211916
📒 Files selected for processing (19)
packages/bruno-app/src/components/Sidebar/Collections/Collection/CollectionItem/RenameCollectionItem/index.jspackages/bruno-app/src/components/Sidebar/NewRequest/index.jspackages/bruno-app/src/utils/common/requestFilename.jspackages/bruno-app/src/utils/common/requestFilename.spec.jspackages/bruno-cli/src/utils/collection.jspackages/bruno-cli/src/utils/request-filename.jspackages/bruno-converters/src/openapi/openapi-common.jspackages/bruno-converters/src/openapi/openapi-to-bruno.jspackages/bruno-converters/src/openapi/swagger2-to-bruno.jspackages/bruno-converters/src/postman/postman-to-bruno.jspackages/bruno-converters/src/utils/request-filename.jspackages/bruno-converters/tests/openapi/openapi-to-bruno/openapi-to-bruno.spec.jspackages/bruno-converters/tests/openapi/swagger2-to-bruno/swagger2-to-bruno.spec.jspackages/bruno-converters/tests/postman/postman-to-bruno/postman-to-bruno.spec.jspackages/bruno-electron/src/ipc/collection.jspackages/bruno-electron/src/ipc/openapi-sync.jspackages/bruno-electron/src/utils/collection-import.jspackages/bruno-electron/src/utils/request-filename.jspackages/bruno-electron/src/utils/request-filename.test.js
| const curlRequestTypeChange = (type) => { | ||
| setCurlRequestTypeDetected(type); | ||
| }; |
There was a problem hiding this comment.
Resync auto filename when cURL type is toggled from the dropdown.
curlRequestTypeChange updates only curlRequestTypeDetected; when filename is still auto-managed, it can stay stale after switching HTTP ↔ GraphQL.
Proposed fix
const curlRequestTypeChange = (type) => {
setCurlRequestTypeDetected(type);
+ if (!isFilenameManuallyEdited) {
+ formik.setFieldValue('filename', getRequestFilenameBase({
+ requestName: formik.values.requestName,
+ requestMethod: formik.values.requestMethod,
+ requestType: type
+ }));
+ }
};Also applies to: 603-615
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@packages/bruno-app/src/components/Sidebar/NewRequest/index.js` around lines
77 - 79, curlRequestTypeChange currently only calls setCurlRequestTypeDetected,
leaving an auto-generated filename stale when the user toggles between HTTP and
GraphQL; update curlRequestTypeChange to also detect if the filename is in
auto-mode (the auto flag, e.g., isFilenameAuto or filenameAuto) and when true
compute the new auto filename (use the existing helper that derives the auto
name or replicate its logic) and call setFilename with that value (and ensure
the auto flag remains true via setIsFilenameAuto if applicable); apply the same
change pattern to the other handler(s) referenced around lines 603-615 so
toggling the cURL type always resyncs the auto filename.
| const extension = path.extname(filename || '').toLowerCase(); | ||
| const baseName = ['.bru', '.yml', '.yaml'].includes(extension) | ||
| ? path.basename(filename, extension) | ||
| : filename; |
There was a problem hiding this comment.
Handle extension stripping with original-case suffix, not the lowercased variant.
path.basename(filename, extension) may fail when the actual suffix casing differs (e.g. .BRU), so normalization can produce incorrect base names.
Proposed fix
export const normalizeRequestFilename = (filename, format = 'bru') => {
const targetExtension = format === 'yml' ? 'yml' : 'bru';
- const extension = path.extname(filename || '').toLowerCase();
- const baseName = ['.bru', '.yml', '.yaml'].includes(extension)
- ? path.basename(filename, extension)
- : filename;
+ const originalExtension = path.extname(filename || '');
+ const extension = originalExtension.toLowerCase();
+ const baseName = ['.bru', '.yml', '.yaml'].includes(extension)
+ ? path.basename(filename, originalExtension)
+ : filename;
return `${sanitizeName(baseName || 'request')}.${targetExtension}`;
};📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| const extension = path.extname(filename || '').toLowerCase(); | |
| const baseName = ['.bru', '.yml', '.yaml'].includes(extension) | |
| ? path.basename(filename, extension) | |
| : filename; | |
| const extension = path.extname(filename || ''); | |
| const extension = extension.toLowerCase(); | |
| const baseName = ['.bru', '.yml', '.yaml'].includes(extension) | |
| ? path.basename(filename, extension) | |
| : filename; |
| const extension = path.extname(filename || '').toLowerCase(); | |
| const baseName = ['.bru', '.yml', '.yaml'].includes(extension) | |
| ? path.basename(filename, extension) | |
| : filename; | |
| export const normalizeRequestFilename = (filename, format = 'bru') => { | |
| const targetExtension = format === 'yml' ? 'yml' : 'bru'; | |
| const originalExtension = path.extname(filename || ''); | |
| const extension = originalExtension.toLowerCase(); | |
| const baseName = ['.bru', '.yml', '.yaml'].includes(extension) | |
| ? path.basename(filename, originalExtension) | |
| : filename; | |
| return `${sanitizeName(baseName || 'request')}.${targetExtension}`; | |
| }; |
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@packages/bruno-app/src/utils/common/requestFilename.js` around lines 20 - 23,
The code lowercases the extension into the variable extension and then passes
that lowercased value to path.basename, which breaks when the file's actual
suffix has different casing; change the logic to keep a lowercased copy for the
includes check but obtain the original-case suffix (e.g. const origExt =
path.extname(filename)) and pass origExt to path.basename when stripping (use
extensionLower = origExt.toLowerCase() for the includes check and call
path.basename(filename, origExt) when creating baseName), ensuring filename,
extension (origExt), and baseName references are updated accordingly.
Description
Allows HTTP requests in the same collection folder to share the same visible display name when they use different HTTP methods.
This addresses related requests/discussions:
This keeps request metadata names unchanged (
meta.name/info.name) and makes the filesystem filename method-aware for auto-generated HTTP request files, for example:GET /projects->GET projects.bruPOST /projects->POST projects.bruPUT /projects/{id}->PUT projects-{id}.bruScreenshot
The change preserves filesystem collision protection and respects manually edited filesystem names. It also updates OpenAPI, Swagger 2, and Postman import paths so duplicate operation/request names with different methods keep clean display names while receiving unique method-aware filenames.
Contribution Checklist:
Note: Keeping the PR small and focused helps make it easier to review and merge. If you have multiple changes you want to make, please consider submitting them as separate pull requests.
Publishing to New Package Managers
Please see here for more information.
Summary by CodeRabbit
New Features
Improvements