@@ -10,14 +10,16 @@ import AsyncAPIGenerator from '@asyncapi/generator';
1010import { spinner } from '@clack/prompts' ;
1111import path from 'path' ;
1212import os from 'os' ;
13+ import { pathToFileURL } from 'url' ;
1314import { yellow , magenta } from 'picocolors' ;
1415import { 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 */
1921interface 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' ) ;
0 commit comments