Skip to content

feat: add Postman v2.0 and v2.1 export support#7922

Open
hosamhamdy258 wants to merge 1 commit into
usebruno:mainfrom
hosamhamdy258:feature/postman-v2-export-support
Open

feat: add Postman v2.0 and v2.1 export support#7922
hosamhamdy258 wants to merge 1 commit into
usebruno:mainfrom
hosamhamdy258:feature/postman-v2-export-support

Conversation

@hosamhamdy258
Copy link
Copy Markdown

@hosamhamdy258 hosamhamdy258 commented May 6, 2026

  • Add version parameter to brunoToPostman converter
  • Support v2.0 auth format (object-based) and v2.1 (array-based)
  • Update UI with separate export buttons for v2.0 and v2.1
  • Add comprehensive tests for both Postman collection versions

Description

Contribution Checklist:

  • I've used AI significantly to create this pull request
  • The pull request only addresses one issue or adds one feature.
  • The pull request does not introduce any breaking changes
  • I have added screenshots or gifs to help explain the change if applicable.
  • I have read the contribution guidelines.
  • Create an issue and link to the pull request.

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
    • Postman export functionality now supports v2.0 and v2.1 schema formats. Users can select their preferred Postman version when exporting collections via distinct options in the sharing interface, ensuring compatibility with their specific environments.

- Add version parameter to brunoToPostman converter
- Support v2.0 auth format (object-based) and v2.1 (array-based)
- Update UI with separate export buttons for v2.0 and v2.1
- Add comprehensive tests for both Postman collection versions
@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented May 6, 2026

Walkthrough

This PR adds support for exporting Bruno collections in Postman v2.0 or v2.1 formats. The ShareCollection UI now presents both versioned options instead of a single generic Postman export. The version parameter flows through the export pipeline and determines schema URLs and authentication structure generation in the bruno-to-postman converter.

Changes

Versioned Postman Export

Layer / File(s) Summary
Export Format Enum
packages/bruno-app/src/components/ShareCollection/index.js
EXPORT_FORMATS updated: POSTMAN removed, POSTMAN_V2_0 and POSTMAN_V2_1 added.
UI & Export Handler
packages/bruno-app/src/components/ShareCollection/index.js
Two new UI cards for Postman v2.0 and v2.1 replace the old Postman card; handleExportPostman refactored to accept version parameter; proceed switch updated to delegate to versioned handlers.
Exporter Integration
packages/bruno-app/src/utils/exporters/postman-collection.js
exportCollection signature updated to accept optional version parameter (default '2.1') and forward it to brunoToPostman.
Converter Core Logic
packages/bruno-converters/src/postman/bruno-to-postman.js
brunoToPostman now accepts version parameter; schema URL selection uses version-to-URL map; authentication generation branches on version to emit v2.0 object-based or v2.1 array-based auth structures; translateScriptSafely helper added for error-safe script translation.
Tests & Validation
packages/bruno-converters/tests/postman/bruno-to-postman.spec.js
Auth test assertions updated to reflect v2.0 array-based format; new test suites for v2.0 and v2.1 schema validation and version-specific auth representations.

Sequence Diagram

sequenceDiagram
    participant User as User
    participant UI as ShareCollection UI
    participant Handler as Export Handler
    participant Exporter as postman-collection
    participant Converter as bruno-to-postman

    User->>UI: Select Postman v2.0 or v2.1
    UI->>Handler: handleExportPostman(version)
    Handler->>Exporter: exportCollection(collection, version)
    Exporter->>Converter: brunoToPostman(collection, version)
    Note over Converter: Determine schema URL<br/>and auth structure<br/>by version
    Converter-->>Exporter: Formatted Postman JSON
    Exporter-->>Handler: Write JSON file
    Handler-->>UI: Export complete
Loading

Estimated Code Review Effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Possibly Related PRs

  • usebruno/bruno#6547: Related exporter flow updates propagating version parameter through the same pipeline.
  • usebruno/bruno#7016: Modifies ShareCollection component's export format options and Postman handling.
  • usebruno/bruno#7111: Concurrent modifications to bruno-to-postman converter for Postman export behavior.

Suggested Reviewers

  • helloanoop
  • lohit-bruno
  • naman-bruno
  • bijin-bruno
  • sid-bruno

Poem

📮 Two versions bloom where once was one,
v2.0 and v2.1 in harmony run,
Auth shifts shape with each schema's call,
Postman exports now support them all! ✨

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately and clearly summarizes the main feature: adding support for Postman v2.0 and v2.1 export formats, which aligns with all the changes across the codebase.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

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.

  • Generate code and open pull requests
  • Plan features and break down work
  • Investigate incidents and troubleshoot customer tickets together
  • Automate recurring tasks and respond to alerts with triggers
  • Summarize progress and report instantly

Built for teams:

  • Shared memory across your entire org—no repeating context
  • Per-thread sandboxes to safely plan and execute work
  • Governance built-in—scoped access, auditability, and budget controls

One agent for your entire SDLC. Right inside Slack.

👉 Get started


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.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick comments (7)
packages/bruno-converters/src/postman/bruno-to-postman.js (2)

150-167: 💤 Low value

Consider validating version or exporting allowed versions as constants.

Right now any unknown version (e.g. '2.2', '2.0.0', typo) silently falls back to the v2.1 schema URL on Line 166, but generateAuth only special-cases the literal string '2.0' — so a typoed '2.0.0' would get a v2.1 schema URL paired with v2.1-shaped auth. Not a bug for current callers (they pass '2.0'/'2.1' only), but a small footgun. Either export shared constants and have callers use them, or validate the input and throw/warn for unsupported versions.

🤖 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/bruno-to-postman.js` around lines 150 -
167, The function brunoToPostman accepts a version string but silently falls
back to v2.1 for unknown values via schemaMap while generateAuth only
special-cases '2.0', which can produce mismatched schema/auth; fix by defining
and exporting allowed version constants (e.g., SUPPORTED_VERSIONS or
POSTMAN_VERSIONS) and using them in brunoToPostman to validate the incoming
version parameter, then either normalize or throw a clear error/warning for
unsupported versions before using schemaMap; update references to schemaMap and
generateAuth to rely on the same constants so callers and internals cannot
pass/accept typoed versions like '2.0.0'.

383-475: 💤 Low value

Auth shape duplication is fine for now, but extractable.

The if (version === '2.0') { ...object form... } then "else array form" pattern is repeated 3× for bearer/basic/apikey. Per the project's "avoid abstractions unless used in 3+ places" guideline, this is right at the threshold. A small helper like toAuthValue(version, type, fields) that returns either the object or [{key, value, type:'string'}, ...] would tighten this up, but only if you find it adds clarity — keeping it explicit also reads well. Up to you.

As per coding guidelines: "Avoid abstractions unless the exact same code is being used in more than 3 places."

🤖 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/bruno-to-postman.js` around lines 383 -
475, The generateAuth function duplicates the "object form when version ===
'2.0' else array form" logic for bearer/basic/apikey; extract a small helper
(e.g., toAuthValue(version, type, fields)) and use it inside generateAuth to
return either the object shape for v2.0 or the Postman key/value array shape for
other versions, then replace the repeated blocks for 'bearer', 'basic', and
'apikey' to call toAuthValue with the appropriate field names (e.g., token;
username/password; key/value/in) so the branching is centralized while keeping
generateAuth's switch semantics intact.
packages/bruno-app/src/components/ShareCollection/index.js (3)

197-197: 💤 Low value

Minor: condition will grow as more Postman versions land.

Each new Postman version forces another || here. If you adopt the format-to-version map suggested above (or a isPostmanFormat(selectedFormat) predicate), this stays a single check. Not blocking.

🤖 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/ShareCollection/index.js` at line 197, The
condition checking multiple Postman versions (selectedFormat ===
EXPORT_FORMATS.POSTMAN_V2_0 || selectedFormat === EXPORT_FORMATS.POSTMAN_V2_1)
will become unmanageable as versions grow; replace it with a single predicate or
lookup (e.g., implement isPostmanFormat(selectedFormat) or a formatToVersion
map) and use that in the JSX conditional alongside
hasNonExportableRequestTypes.has so the check becomes
isPostmanFormat(selectedFormat) && hasNonExportableRequestTypes.has; update or
add the helper (isPostmanFormat or a formats set) near the EXPORT_FORMATS
definition and reuse it in ShareCollection's render to simplify future
additions.

171-194: 💤 Low value

Add data-testid to the new format cards for Playwright.

The two new Postman cards are interactive selection elements and per project conventions for Playwright should be addressable via data-testid. The existing ZIP/YAML cards are missing them too, but let's not add to the debt with the new ones.

Suggested addition
   <div
+    data-testid="export-format-postman-v2-0"
     className={`other-format-card ${selectedFormat === EXPORT_FORMATS.POSTMAN_V2_0 ? 'selected' : ''} ${isDisabled ? 'opacity-50 cursor-not-allowed' : ''}`}
     onClick={() => !isDisabled && setSelectedFormat(EXPORT_FORMATS.POSTMAN_V2_0)}
   >
     ...
   </div>
   <div
+    data-testid="export-format-postman-v2-1"
     className={`other-format-card ${selectedFormat === EXPORT_FORMATS.POSTMAN_V2_1 ? 'selected' : ''} ${isDisabled ? 'opacity-50 cursor-not-allowed' : ''}`}
     onClick={() => !isDisabled && setSelectedFormat(EXPORT_FORMATS.POSTMAN_V2_1)}
   >

As per coding guidelines: "Add data-testid to testable elements for Playwright."

🤖 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/ShareCollection/index.js` around lines 171
- 194, Add data-testid attributes to the interactive Postman format cards in the
ShareCollection component: for the div handling EXPORT_FORMATS.POSTMAN_V2_0 (the
other-format-card with onClick that calls
setSelectedFormat(EXPORT_FORMATS.POSTMAN_V2_0)) add a unique data-testid like
"export-format-postman-v2-0"; likewise for the EXPORT_FORMATS.POSTMAN_V2_1 card
(the other-format-card that sets EXPORT_FORMATS.POSTMAN_V2_1) add
"export-format-postman-v2-1". Ensure the attributes are placed on the outer
clickable divs (the ones using className "other-format-card" and onClick) so
Playwright can target them.

83-88: 💤 Low value

Optional: derive version from the enum value rather than hardcoding strings.

Both POSTMAN_V2_0'2.0' and POSTMAN_V2_1'2.1' are duplicated knowledge between the enum and these case bodies. A tiny lookup keeps them in lock-step:

Tiny lookup
+  const POSTMAN_VERSION_BY_FORMAT = {
+    [EXPORT_FORMATS.POSTMAN_V2_0]: '2.0',
+    [EXPORT_FORMATS.POSTMAN_V2_1]: '2.1'
+  };
   ...
-      case EXPORT_FORMATS.POSTMAN_V2_0:
-        handleExportPostman('2.0');
-        break;
-      case EXPORT_FORMATS.POSTMAN_V2_1:
-        handleExportPostman('2.1');
+      case EXPORT_FORMATS.POSTMAN_V2_0:
+      case EXPORT_FORMATS.POSTMAN_V2_1:
+        handleExportPostman(POSTMAN_VERSION_BY_FORMAT[selectedFormat]);
         break;

Totally optional given there are only two formats today.

🤖 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/ShareCollection/index.js` around lines 83 -
88, The switch hardcodes Postman version strings for EXPORT_FORMATS.POSTMAN_V2_0
and POSTMAN_V2_1 when calling handleExportPostman; instead derive the version
from the enum value (or from a tiny lookup keyed by EXPORT_FORMATS) so the
mapping stays in sync — e.g., compute a version string from the enum key or
create a small POSTMAN_VERSION_MAP and pass that into handleExportPostman rather
than hardcoding '2.0' and '2.1'.
packages/bruno-converters/tests/postman/bruno-to-postman.spec.js (2)

1058-1152: ⚡ Quick win

Coverage gap: v2.0 auth with missing fields and default in.

The new v2.0 describe block only exercises happy paths with all fields present. The v2.0 branches in generateAuth also have fallback logic (itemAuth.bearer?.token || '', itemAuth.apikey?.in || 'header', etc.) that's only currently exercised against the v2.1 (default) shape. Worth adding at least:

  • bearer with token: null under '2.0'bearer: { token: '' }
  • basic with missing username/password under '2.0'basic: { username: '', password: '' }
  • apikey under '2.0' without inapikey: { ..., in: 'header' }

Keeps the v2.0 path symmetric with the existing null-fallback tests for the default version.

As per coding guidelines: "Cover both the 'happy path' and the realistically problematic paths."

🤖 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/tests/postman/bruno-to-postman.spec.js` around
lines 1058 - 1152, Add v2.0 tests that exercise the fallback branches in
generateAuth by calling brunoToPostman with requests whose auth is missing or
null: (1) bearer with bearer: { token: null } and assert
result.item[0].request.auth.bearer.token === '' for version '2.0'; (2) basic
with basic: {} (no username/password) and assert basic.username === '' and
basic.password === ''; (3) apikey with apikey: { key: 'api-key', value: 'secret'
} (omit in) and assert apikey.in === 'header' when using brunoToPostman(...,
'2.0'). Use the same test structure and assertions style as the existing v2.0
cases to keep symmetry.

1154-1231: 💤 Low value

Optional: add an explicit v2.1 apikey test for symmetry.

The v2.0 block tests bearer/basic/apikey, but the v2.1 block only covers bearer and basic. The v2.1 apikey shape is already exercised indirectly via the "missing key/value in apikey auth" test (which hits the default version), but adding an explicit '2.1' apikey case here keeps the two suites visually parallel and makes intent obvious to the next reader.

🤖 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/tests/postman/bruno-to-postman.spec.js` around
lines 1154 - 1231, Add a new test in the "brunoToPostman v2.1 format" suite that
calls brunoToPostman(simpleCollection, '2.1') with an http-request whose
request.auth is mode: 'apikey' and apikey: { key: 'apiKey', value: 'abc' }, then
assert result.item[0].request.auth equals the v2.1 array-shaped apikey object
(type: 'apikey', apikey: [{ key: 'key', value: 'apiKey', type: 'string' }, {
key: 'value', value: 'abc', type: 'string' }]) to mirror the existing v2.0
apikey test and keep parity with bearer/basic tests; reference brunoToPostman
and result.item[0].request.auth to locate where to add the case.
🤖 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.

Nitpick comments:
In `@packages/bruno-app/src/components/ShareCollection/index.js`:
- Line 197: The condition checking multiple Postman versions (selectedFormat ===
EXPORT_FORMATS.POSTMAN_V2_0 || selectedFormat === EXPORT_FORMATS.POSTMAN_V2_1)
will become unmanageable as versions grow; replace it with a single predicate or
lookup (e.g., implement isPostmanFormat(selectedFormat) or a formatToVersion
map) and use that in the JSX conditional alongside
hasNonExportableRequestTypes.has so the check becomes
isPostmanFormat(selectedFormat) && hasNonExportableRequestTypes.has; update or
add the helper (isPostmanFormat or a formats set) near the EXPORT_FORMATS
definition and reuse it in ShareCollection's render to simplify future
additions.
- Around line 171-194: Add data-testid attributes to the interactive Postman
format cards in the ShareCollection component: for the div handling
EXPORT_FORMATS.POSTMAN_V2_0 (the other-format-card with onClick that calls
setSelectedFormat(EXPORT_FORMATS.POSTMAN_V2_0)) add a unique data-testid like
"export-format-postman-v2-0"; likewise for the EXPORT_FORMATS.POSTMAN_V2_1 card
(the other-format-card that sets EXPORT_FORMATS.POSTMAN_V2_1) add
"export-format-postman-v2-1". Ensure the attributes are placed on the outer
clickable divs (the ones using className "other-format-card" and onClick) so
Playwright can target them.
- Around line 83-88: The switch hardcodes Postman version strings for
EXPORT_FORMATS.POSTMAN_V2_0 and POSTMAN_V2_1 when calling handleExportPostman;
instead derive the version from the enum value (or from a tiny lookup keyed by
EXPORT_FORMATS) so the mapping stays in sync — e.g., compute a version string
from the enum key or create a small POSTMAN_VERSION_MAP and pass that into
handleExportPostman rather than hardcoding '2.0' and '2.1'.

In `@packages/bruno-converters/src/postman/bruno-to-postman.js`:
- Around line 150-167: The function brunoToPostman accepts a version string but
silently falls back to v2.1 for unknown values via schemaMap while generateAuth
only special-cases '2.0', which can produce mismatched schema/auth; fix by
defining and exporting allowed version constants (e.g., SUPPORTED_VERSIONS or
POSTMAN_VERSIONS) and using them in brunoToPostman to validate the incoming
version parameter, then either normalize or throw a clear error/warning for
unsupported versions before using schemaMap; update references to schemaMap and
generateAuth to rely on the same constants so callers and internals cannot
pass/accept typoed versions like '2.0.0'.
- Around line 383-475: The generateAuth function duplicates the "object form
when version === '2.0' else array form" logic for bearer/basic/apikey; extract a
small helper (e.g., toAuthValue(version, type, fields)) and use it inside
generateAuth to return either the object shape for v2.0 or the Postman key/value
array shape for other versions, then replace the repeated blocks for 'bearer',
'basic', and 'apikey' to call toAuthValue with the appropriate field names
(e.g., token; username/password; key/value/in) so the branching is centralized
while keeping generateAuth's switch semantics intact.

In `@packages/bruno-converters/tests/postman/bruno-to-postman.spec.js`:
- Around line 1058-1152: Add v2.0 tests that exercise the fallback branches in
generateAuth by calling brunoToPostman with requests whose auth is missing or
null: (1) bearer with bearer: { token: null } and assert
result.item[0].request.auth.bearer.token === '' for version '2.0'; (2) basic
with basic: {} (no username/password) and assert basic.username === '' and
basic.password === ''; (3) apikey with apikey: { key: 'api-key', value: 'secret'
} (omit in) and assert apikey.in === 'header' when using brunoToPostman(...,
'2.0'). Use the same test structure and assertions style as the existing v2.0
cases to keep symmetry.
- Around line 1154-1231: Add a new test in the "brunoToPostman v2.1 format"
suite that calls brunoToPostman(simpleCollection, '2.1') with an http-request
whose request.auth is mode: 'apikey' and apikey: { key: 'apiKey', value: 'abc'
}, then assert result.item[0].request.auth equals the v2.1 array-shaped apikey
object (type: 'apikey', apikey: [{ key: 'key', value: 'apiKey', type: 'string'
}, { key: 'value', value: 'abc', type: 'string' }]) to mirror the existing v2.0
apikey test and keep parity with bearer/basic tests; reference brunoToPostman
and result.item[0].request.auth to locate where to add the case.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: ac004fb5-3cd9-4300-9abf-09441152b569

📥 Commits

Reviewing files that changed from the base of the PR and between ba42c22 and b3c1ccf.

📒 Files selected for processing (4)
  • packages/bruno-app/src/components/ShareCollection/index.js
  • packages/bruno-app/src/utils/exporters/postman-collection.js
  • packages/bruno-converters/src/postman/bruno-to-postman.js
  • packages/bruno-converters/tests/postman/bruno-to-postman.spec.js

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant