Skip to content

Commit f84d532

Browse files
fix: external files in same directory are not resolved. (#2129)
Co-authored-by: AayushSaini101 <kumaraayush9810@gmail.com> Co-authored-by: Chan <bot+chan@asyncapi.io>
1 parent 5a5ad88 commit f84d532

4 files changed

Lines changed: 57 additions & 2 deletions

File tree

src/domains/services/generator.service.ts

Lines changed: 21 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,14 +10,16 @@ import AsyncAPIGenerator from '@asyncapi/generator';
1010
import { spinner } from '@clack/prompts';
1111
import path from 'path';
1212
import os from 'os';
13+
import { pathToFileURL } from 'url';
1314
import { yellow, magenta } from 'picocolors';
1415
import { getErrorMessage } from '@utils/error-handler';
1516

1617
/**
1718
* Options passed to the generator for code generation.
19+
* `path` must be a string (document base URI) for @asyncapi/generator to resolve local $ref files.
1820
*/
1921
interface GeneratorRunOptions {
20-
path?: Specification;
22+
path?: string;
2123
[key: string]: unknown;
2224
}
2325

@@ -72,6 +74,20 @@ export class GeneratorService extends BaseService {
7274
}
7375
}
7476

77+
/**
78+
* Base URI for parsing, required so relative file $refs resolve next to the spec file (not cwd).
79+
*/
80+
private getGeneratorParseSource(spec: Specification): string | undefined {
81+
const filePath = spec.getFilePath();
82+
if (filePath !== undefined) {
83+
const absolute = path.isAbsolute(filePath)
84+
? filePath
85+
: path.resolve(filePath);
86+
return pathToFileURL(absolute).href;
87+
}
88+
return spec.getFileURL();
89+
}
90+
7591
/**
7692
* Generates code from an AsyncAPI specification using the specified template.
7793
*
@@ -107,9 +123,12 @@ export class GeneratorService extends BaseService {
107123
: { start: () => null, stop: (message: string) => logs.push(message) };
108124
s.start('Generation in progress. Keep calm and wait a bit');
109125
try {
126+
const parseSource =
127+
this.getGeneratorParseSource(asyncapi) ??
128+
(typeof genOption.path === 'string' ? genOption.path : undefined);
110129
await generator.generateFromString(asyncapi.text(), {
111130
...genOption,
112-
path: asyncapi,
131+
...(parseSource !== undefined ? { path: parseSource } : {}),
113132
});
114133
} catch (err: unknown) {
115134
s.stop('Generation failed');
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
asyncapi: "2.6.0"
2+
info:
3+
title: Same-dir ref fixture
4+
version: 1.0.0
5+
channels:
6+
test:
7+
publish:
8+
message:
9+
$ref: "./messages.yaml#/messages/TestMessage"
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
messages:
2+
TestMessage:
3+
payload:
4+
type: string

test/integration/generate/fromTemplate.test.ts

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -228,4 +228,27 @@ describe('template', () => {
228228
}
229229
);
230230
});
231+
232+
describe('same-directory file $ref', () => {
233+
test
234+
.stdout()
235+
.command([
236+
'generate:fromTemplate',
237+
'./test/fixtures/generate-same-dir-ref/asyncapi.yaml',
238+
'@asyncapi/minimaltemplate',
239+
'--output=./test/docs/same-dir-ref-out',
240+
'--force-write',
241+
nonInteractive,
242+
])
243+
.it(
244+
'resolves relative file refs next to the spec file, not cwd (issue #1839)',
245+
(ctx, done) => {
246+
expect(ctx.stdout).to.contain(
247+
'Check out your shiny new generated files at ./test/docs/same-dir-ref-out.\n\n'
248+
);
249+
cleanup('./test/docs/same-dir-ref-out');
250+
done();
251+
}
252+
);
253+
}).timeout(200000);
231254
});

0 commit comments

Comments
 (0)