Skip to content

fix: resolve external $ref files relative to spec file location (#1839)#2077

Closed
DeekRoumy wants to merge 1 commit intoasyncapi:masterfrom
DeekRoumy:fix/ref-regression-1839
Closed

fix: resolve external $ref files relative to spec file location (#1839)#2077
DeekRoumy wants to merge 1 commit intoasyncapi:masterfrom
DeekRoumy:fix/ref-regression-1839

Conversation

@DeekRoumy
Copy link

Summary

Fixes #1839 — external $ref files in the same directory as the spec are not resolved when the spec is in a subdirectory (regression since v3.3.0).

Root Cause

When GeneratorService was introduced, the path option passed to generator.generateFromString() was accidentally changed from a string file path to a Specification object. The AsyncAPI generator uses this path value to determine the base directory for resolving relative $ref paths. Receiving an object instead of a string caused it to fall back to CWD, breaking resolution for specs in subdirectories.

The one-line regression in generator.service.ts:

// Before (correct):
path: '/some/subdirectory/asyncapi.yaml'  // string → refs resolve relative to /some/subdirectory/

// After regression (broken):
path: asyncapi  // Specification object → refs resolve relative to CWD

Fix

  • src/domains/services/generator.service.ts: Pass asyncapi.getSource() (returns file path string or URL) instead of the asyncapi object
  • GeneratorRunOptions interface: Corrected path type from Specification to string (matching what the generator actually expects)

Tests Added

Unit tests (test/unit/services/generator.service.test.ts) — new file

  • Verifies getSource() returns a string for file-based specs
  • Verifies getSource() returns a string URL for URL-based specs
  • Demonstrates that the Specification object itself is NOT a valid path string (illustrates the bug)
  • Tests directory resolution: confirms path.dirname(getSource()) correctly resolves relative $refs
  • Edge cases: relative paths, deeply nested paths, no-source specs

Integration test (test/integration/generate/fromTemplate.test.ts)

  • Added regression test case using the existing test/fixtures/external-refs/ fixture (main.yaml references schemas.yaml in the same subdirectory)
  • Verifies generation succeeds end-to-end with external $ref files

Comparison to Competing PRs

PRs #2046, #2056, and #2075 all make the same correct one-line fix. This PR is more complete because it:

  1. Fixes the interface type (path?: Specificationpath?: string) in addition to the call site
  2. Adds comprehensive unit tests covering the fix and edge cases
  3. Adds an integration test that exercises the full generate pipeline with external refs
  4. Includes detailed comments explaining the root cause for future maintainers
  5. Adds a thorough changeset description

How to Reproduce the Bug (before fix)

# Create a spec in a subdirectory with external refs
mkdir -p /tmp/myapi/contracts
cat > /tmp/myapi/contracts/asyncapi.yaml << 'EOF'
asyncapi: '2.6.0'
info:
  title: Test
  version: 1.0.0
channels:
  user/created:
    subscribe:
      message:
        payload:
          $ref: './schemas.yaml#/User'
EOF

cat > /tmp/myapi/contracts/schemas.yaml << 'EOF'
User:
  type: object
  properties:
    id:
      type: string
EOF

# This fails (before fix) — $ref can't be resolved because CWD ≠ /tmp/myapi/contracts
asyncapi generate fromTemplate /tmp/myapi/contracts/asyncapi.yaml @asyncapi/html-template -o /tmp/out

# After fix: works correctly

Closes #1839

…capi#1839)

The `generate:fromTemplate` command failed to resolve external $ref files
since v3.3.0 when the spec was located in a subdirectory. Relative references
like `./schemas.yaml` were resolved against CWD instead of the spec file's
directory.

Root cause: GeneratorService passed the Specification object (not the file
path string) as the `path` option to `generator.generateFromString()`.
The generator uses this to determine the base directory for $ref resolution.

Fix:
- Pass `asyncapi.getSource()` (string) instead of `asyncapi` (object)
- Fix `GeneratorRunOptions.path` type from `Specification` to `string`
- Add integration test using existing external-refs fixture
- Add comprehensive unit tests for the regression

Closes asyncapi#1839
@changeset-bot
Copy link

changeset-bot bot commented Mar 23, 2026

🦋 Changeset detected

Latest commit: 379d16a

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 1 package
Name Type
@asyncapi/cli Patch

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

@sonarqubecloud
Copy link

@github-project-automation github-project-automation bot moved this from To Triage to Done in CLI - Kanban Mar 23, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

Status: Done

Development

Successfully merging this pull request may close these issues.

[BUG] external files in same directory are not resolved via $ref anymore, since v3.3.0

2 participants