diff --git a/example/v3/bundle.js b/example/v3/bundle.js index 9b17c9d..f1867df 100644 --- a/example/v3/bundle.js +++ b/example/v3/bundle.js @@ -4,14 +4,18 @@ const {readFileSync, writeFileSync} = require('fs') async function main() { await singleFile() await multiFile() + await singleFileWithBaseDir() } -async function singleFile(){ - const document = await bundle([readFileSync('./main.yaml', 'utf-8')] ) +async function singleFileWithBaseDir(){ + const document = await bundle([readFileSync('./spec/main.yaml', 'utf-8')], {baseDir: './spec'}) + writeFileSync('asyncapi.yaml', document.yml()) +} +async function singleFile(){ + const document = await bundle([readFileSync('./spec/main.yaml', 'utf-8')], {baseDir: './spec'}) writeFileSync('asyncapi.yaml', document.yml()) - } async function multiFile(){ diff --git a/example/v3/package-lock.json b/example/v3/package-lock.json index 526ead5..e7c5be8 100644 --- a/example/v3/package-lock.json +++ b/example/v3/package-lock.json @@ -13,7 +13,8 @@ } }, "../..": { - "version": "0.3.11", + "name": "@asyncapi/bundler", + "version": "0.4.0", "license": "Apache-2.0", "dependencies": { "@apidevtools/json-schema-ref-parser": "^9.0.9", diff --git a/example/v3/spec/main.yaml b/example/v3/spec/main.yaml new file mode 100644 index 0000000..bcd042e --- /dev/null +++ b/example/v3/spec/main.yaml @@ -0,0 +1,34 @@ +asyncapi: 3.0.0 +info: + title: Account Service + version: 1.0.0 + description: This service is in charge of processing user signupsA +channels: + userSignedup: + address: 'user/signedup' + messages: + userSignedUpMessage: + $ref: './messages.yaml#/messages/UserSignedUp' + test: + address: '/test' + messages: + testMessage: + $ref: '#/components/messages/TestMessage' +operations: + UserSignedUp: + action: send + channel: + $ref: '#/channels/userSignedup' + messages: + - $ref: './messages.yaml#/messages/UserSignedUp' + TestOpp: + action: send + channel: + $ref: '#/channels/test' + messages: + - $ref: '#/components/messages/TestMessage' +components: + messages: + TestMessage: + payload: + type: string \ No newline at end of file diff --git a/example/v3/spec/messages.yaml b/example/v3/spec/messages.yaml new file mode 100644 index 0000000..e9d7cbf --- /dev/null +++ b/example/v3/spec/messages.yaml @@ -0,0 +1,17 @@ +messages: + UserSignedUp: + payload: + type: object + properties: + displayName: + type: string + description: Name of the user + email: + type: string + format: email + description: Email of the user + UserLoggedIn: + payload: + type: object + properties: + id: string \ No newline at end of file diff --git a/src/index.ts b/src/index.ts index 539b465..ab8b01a 100644 --- a/src/index.ts +++ b/src/index.ts @@ -1,4 +1,4 @@ -import { toJS, resolve, versionCheck } from './util'; +import { toJS, resolve, versionCheck, resolveBaseFileDir } from './util'; import { Document } from './document'; import { parse } from './parser'; @@ -80,6 +80,10 @@ export default async function bundle(files: string[], options: any = {}) { const parsedJsons = files.map(file => toJS(file)) as AsyncAPIObject[]; + if (typeof options.baseDir !== 'undefined') { + parsedJsons.forEach( parsedJson => resolveBaseFileDir(parsedJson, options.baseDir)) + } + const majorVersion = versionCheck(parsedJsons); let resolvedJsons; diff --git a/src/util.ts b/src/util.ts index 93b2cdf..b366a90 100644 --- a/src/util.ts +++ b/src/util.ts @@ -3,8 +3,11 @@ import { cloneDeep } from 'lodash'; import yaml from 'js-yaml'; import { parse } from './parser'; import { ParserError } from './errors'; +import {JSONPath} from 'jsonpath-plus'; import type { AsyncAPIObject } from './spec-types'; +import path from 'path'; +import { parentPort } from 'worker_threads'; /** * @private @@ -99,4 +102,52 @@ export function versionCheck(asyncapiDocuments: AsyncAPIObject[]): number { currentVersion = majorVersion; } return currentVersion; +} + +export function isExternalReference(ref: string): boolean { + return typeof ref === 'string' && !ref.startsWith('#') +} + +export function notAUrl(ref: string): boolean { + try { + new URL(ref) + return false + } catch (error) { + return true + } +} + +export function resolveBaseFileDir(file: object, baseFileDir: string) { + /** + * Update the local refences in a given file with the + * absolute file path using the baseDir passed by the + * user as an option. + */ + JSONPath({ + json: file, + resultType: 'all', + path: '$.channels.*.messages.*' + }).forEach( ({parent, parentProperty}: {parent: any, parentProperty: string}) => { + const ref = parent[String(parentProperty)]['$ref'] + if (isExternalReference(ref) && notAUrl(ref)) { + // console.log(ref) + // console.log(path.resolve(baseFileDir, ref)) + parent[String(parentProperty)]['$ref'] = path.resolve(baseFileDir, ref) + } + }) + + JSONPath({ + json: file, + resultType: 'all', + path: '$.operations.*.messages.*' + }).forEach( + ({parent, parentProperty}: {parent: any, parentProperty: string}) => { + const ref = parent[String(parentProperty)]['$ref'] + if (isExternalReference(ref) && notAUrl(ref)) { + // console.log(ref) + // console.log(path.resolve(baseFileDir, ref)) + parent[String(parentProperty)]['$ref'] = path.resolve(baseFileDir, ref) + } + } + ) } \ No newline at end of file diff --git a/src/v3/parser.ts b/src/v3/parser.ts index 4152a08..fcea1fa 100644 --- a/src/v3/parser.ts +++ b/src/v3/parser.ts @@ -1,6 +1,7 @@ import $RefParser, {$Refs} from '@apidevtools/json-schema-ref-parser'; import { JSONPath } from 'jsonpath-plus'; import { merge } from 'lodash'; +import path from 'path'; import { AsyncAPIObject } from 'spec-types';