Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat!: add support for AsyncAPI v3 #526

Merged
merged 141 commits into from
Dec 1, 2023
Merged
Show file tree
Hide file tree
Changes from 132 commits
Commits
Show all changes
141 commits
Select commit Hold shift + click to select a range
631cc9f
chore: update with upstream master (#525)
jonaslagoni Apr 19, 2022
b7738d9
Merge branch 'master' into next-major-spec
jonaslagoni Apr 19, 2022
8cb5204
Merge master into next-major-spec
asyncapi-bot Apr 20, 2022
1f4cab0
chore: add new 3.0 mimetype (#517)
jonaslagoni Apr 21, 2022
1840651
Merge master into next-major-spec
asyncapi-bot Apr 26, 2022
32ca3aa
docs: add first statements about parserjs v2 and intent-driven usage …
smoya Feb 16, 2022
7d066b2
feat: remove all previous parser code letting a fresh start for 2.0.0…
smoya Mar 8, 2022
5be4fb5
chore: init architecture (#484)
magicmatatjahu Mar 8, 2022
33fad58
refactor: add info and dependant models (#485)
smoya Mar 9, 2022
aaef7e6
refactor: add stringify functionality (#486)
magicmatatjahu Mar 9, 2022
24a6eea
refactor: init parse, lint and validate functions (#487)
magicmatatjahu Mar 9, 2022
5427244
refactor: interface and implementations for each major spec version (…
smoya Mar 11, 2022
0f43554
refactor: init custom parser functionality (#489)
magicmatatjahu Mar 11, 2022
8a32da7
refactor: add needed mixins (#491)
magicmatatjahu Mar 16, 2022
2c60eae
refactor: adjust mixins to the IntentAPI (#499)
magicmatatjahu Mar 21, 2022
69a0aef
refactor: add models for server object (#497)
Souvikns Mar 25, 2022
11cb0e9
refactor: add metadata to models (#496)
magicmatatjahu Mar 25, 2022
49afdba
refactor: port server-variable model to ts (#507)
Souvikns Apr 4, 2022
12a0a01
refactor: add Parser class (#511)
magicmatatjahu Apr 5, 2022
b7845cf
refactor: port security scheme model to ts (#513)
Souvikns Apr 28, 2022
e444b87
refactor: add all missed interfaces (#538)
magicmatatjahu Apr 28, 2022
3627d02
refactor: port message, operation, correlation-id and security-requir…
magicmatatjahu May 6, 2022
ae4b0ff
refactor: port channel, channel-parameter and schema models (#547)
magicmatatjahu May 9, 2022
7fc5916
refactor: port components model (#548)
magicmatatjahu May 16, 2022
62f5ffe
refactor: stop with v3 implementation (#551)
magicmatatjahu May 17, 2022
7c637b4
refactor: add missed methods to models (#553)
magicmatatjahu May 19, 2022
e4fe565
refactor: add AsyncAPI Schema Parser (#573)
smoya Jul 27, 2022
223967d
refactor: fix AsyncAPI Schema Parser error path (#580)
smoya Aug 25, 2022
af44625
refactor: add RAML Schema Parser (#577)
smoya Aug 26, 2022
65afb09
refactor: add Avro Schema Parser (#576)
smoya Aug 26, 2022
4558bb2
refactor: add OpenAPI Schema Parser (#578)
smoya Aug 26, 2022
dbd5e0d
refactor: integrate custom schemas with parser and spectral (#579)
magicmatatjahu Aug 29, 2022
21b43ea
refactor: add schemaFormat method to the Message model (#582)
magicmatatjahu Aug 31, 2022
deb900e
refactor: remove mixins and add AsyncAPI TS types (#581)
magicmatatjahu Aug 31, 2022
8586d4b
refactor: add rule to check if AsyncAPI document is defined or not (#…
magicmatatjahu Sep 1, 2022
5753db4
refactor: adapt components to parser-api (#586)
smoya Sep 1, 2022
102c443
refactor: add SecurityRequirement(s) models (#588)
smoya Sep 1, 2022
1780d43
refactor: simplify operation traits based on parser-api (#590)
smoya Sep 5, 2022
159b290
refactor: add filters to some collections (#592)
smoya Sep 6, 2022
24bd4f9
refactor: add extensions method to the bindings (#587)
magicmatatjahu Sep 6, 2022
a3b85e7
refactor: add old api (#589)
magicmatatjahu Sep 6, 2022
fab07e1
refactor: use @swc/jest to speedup test execution (#594)
magicmatatjahu Sep 6, 2022
9896fd7
refactor: enable eslint and make package tree-shakable (#595)
magicmatatjahu Sep 6, 2022
7e99ff2
refactor: handle circular references in schemas (#591)
magicmatatjahu Sep 8, 2022
912b876
refactor: merge `master` into `next-major` (#600)
smoya Sep 8, 2022
7d650d8
refactor: fix some bugs and smells (#602)
smoya Sep 8, 2022
fe4f44a
refactor: another round on merging and fixing conflicts (#603)
smoya Sep 9, 2022
e9fb91c
refactor: cleanup interfaces + add missing methods from parser-api (#…
smoya Sep 12, 2022
c36194c
refactor: update Readme.md v1 (#601)
magicmatatjahu Sep 12, 2022
8e57fb9
refactor: add browser version of package and write docs for it (#596)
magicmatatjahu Sep 12, 2022
3f27890
refactor: add iterator for traversing an AsyncAPI doc (#604)
smoya Sep 13, 2022
d8c3c03
refactor: add migration function from v2 to v1 API (#607)
magicmatatjahu Sep 15, 2022
ac49c9f
refactor: add fromURL and fromFile utils (#610)
magicmatatjahu Sep 15, 2022
5048612
refactor: export cjs and esm modules (#615)
magicmatatjahu Sep 15, 2022
1b11a9e
refactor: improve internal code (#614)
magicmatatjahu Sep 15, 2022
9e5d254
refactor: fix TS imports and change name of migrator to converter (#618)
magicmatatjahu Sep 19, 2022
5a8108b
refactor: add tests for old api (#622)
magicmatatjahu Sep 22, 2022
981c182
refactor: add possibility to pass custom resolvers (unstable) (#593)
magicmatatjahu Sep 23, 2022
cabf309
refactor: apply latest changes to the avro schema parser (#623)
magicmatatjahu Sep 23, 2022
f93506b
remove unnecessary folders
magicmatatjahu Oct 3, 2022
c5d8c13
fix tests
magicmatatjahu Oct 3, 2022
d1b9eed
chore: init models for v3 spec (#638)
magicmatatjahu Oct 4, 2022
f259f4a
chore: add support for asyncapi 3.0.0 operations and channels (#654)
fmvilas Oct 26, 2022
6de1923
chore: add reusable tags and externalDocs and move them to the info o…
magicmatatjahu Nov 8, 2022
2590f56
fix: remove action and channel fields from Operation Trait Object (#674)
magicmatatjahu Nov 15, 2022
f804bdb
chore: add missed metadata methods to the core models (#677)
magicmatatjahu Nov 24, 2022
58b8b85
chore: update v3 models (#708)
magicmatatjahu Apr 12, 2023
b59983c
chore: v3 request reply support (#745)
GreenRover Apr 24, 2023
99cfdd2
Merge branch 'master' into next-major-spec
fmvilas Jun 12, 2023
e75c79e
chore: merge master into next-major-spec
fmvilas Jun 13, 2023
1def5f7
Update package-lock.json
fmvilas Jun 13, 2023
f551deb
Merge pull request #787 from fmvilas/merge-master-into-next-major-spec
fmvilas Jun 13, 2023
9c11ea1
Merge remote-tracking branch 'origin/master' into next-major-spec
smoya Jul 13, 2023
daf2a0a
Merge pull request #799 from smoya/next-major-spec
fmvilas Jul 14, 2023
a116209
chore(release): v2.1.0-next-major-spec.1 (#800)
asyncapi-bot Jul 14, 2023
ff5ba20
chore: revert adding schema parsers back to this repository (#802)
smoya Jul 18, 2023
0acd733
chore: remove files that were removed in master branch time ago (#804)
smoya Jul 18, 2023
0ca828f
chore: merge `master` into `next-major-spec` fixing conflicts (#806)
smoya Jul 19, 2023
c46c598
Merge remote-tracking branch 'origin/master' into next-major-spec
smoya Jul 19, 2023
00f59e4
Merge pull request #807 from smoya/next-major-spec
smoya Jul 19, 2023
2000140
chore: new trait behaviour in v3 spec (#744)
magicmatatjahu Jul 20, 2023
c9f56b1
feat: add simplified channel parameter (#816)
jonaslagoni Jul 26, 2023
21f2744
chore(release): v2.1.0-next-major-spec.2 (#818)
asyncapi-bot Jul 26, 2023
9b79e90
feat: add support for multi-format schema (#814)
smoya Jul 28, 2023
a308af9
chore(release): v2.1.0-next-major-spec.3 (#819)
asyncapi-bot Jul 28, 2023
bc9d846
Merge branch 'master' into next-major-spec
smoya Aug 1, 2023
fc6bc7b
chore: adapt tests for v3
smoya Aug 1, 2023
74ef1cf
chore: merge master into next-major-spec + adapt tests for v3 #824
jonaslagoni Aug 1, 2023
3fa3290
feat: enable AsyncAPI v3 validation (#825)
smoya Aug 9, 2023
bcf7ad9
chore(release): v2.1.0-next-major-spec.4 (#830)
asyncapi-bot Aug 9, 2023
62eda59
fix: add missing exports (#829)
jonaslagoni Aug 10, 2023
0ae86fb
chore(release): v2.1.0-next-major-spec.5 (#833)
asyncapi-bot Aug 10, 2023
b82b150
fix: add reply() to the Operation model (#834)
smoya Aug 10, 2023
bc83777
chore(release): v2.1.0-next-major-spec.6 (#835)
asyncapi-bot Aug 10, 2023
933be1d
fix: return proper schemas in asyncapi.schemas() method (#836)
smoya Aug 10, 2023
b34825c
chore(release): v2.1.0-next-major-spec.7 (#839)
asyncapi-bot Aug 10, 2023
af2a2b6
feat: update specs dependency (#840)
jonaslagoni Aug 11, 2023
ab4bad3
chore(release): v2.1.0-next-major-spec.8 (#841)
asyncapi-bot Aug 11, 2023
d04b871
fix: include all channels in message.channels() (#842)
smoya Aug 11, 2023
2846ee5
chore(release): v2.1.0-next-major-spec.9 (#843)
asyncapi-bot Aug 11, 2023
6fa3dcd
Merge branch 'master' into next-major-spec
smoya Aug 11, 2023
268b1c6
feat: merge master into next-major-spec
smoya Aug 17, 2023
52597af
chore(release): v2.2.0-next-major-spec.1 (#846)
asyncapi-bot Aug 17, 2023
98aa4db
docs: state support for parser-api v2 in compatibility matrix (#845)
smoya Aug 17, 2023
95b6e5e
fix: set proper parser-api version (#849)
smoya Aug 18, 2023
5d0705c
chore(release): v2.2.0-next-major-spec.2 (#850)
asyncapi-bot Aug 18, 2023
6526d9a
feat!: force v3 pre-release (#847)
smoya Aug 23, 2023
49183a4
chore(release): v3.0.0-next-major-spec.1 (#851)
asyncapi-bot Aug 23, 2023
58fdca3
fix: resolve type mismatch in allServers and allChannels (#854)
KhudaDad414 Sep 1, 2023
1fa1240
chore(release): v3.0.0-next-major-spec.2 (#855)
asyncapi-bot Sep 1, 2023
b5684de
fix: isAsyncAPIDocument not recognizing correct documents (#861)
jonaslagoni Oct 3, 2023
07f3a2e
chore(release): v3.0.0-next-major-spec.3 (#865)
asyncapi-bot Oct 4, 2023
a3a4194
fix: schema parsing for v3 (#864)
jonaslagoni Oct 9, 2023
d3afd33
chore(release): v3.0.0-next-major-spec.4 (#869)
asyncapi-bot Oct 9, 2023
02b06ab
fix: channel parameter not always returning schema (#868)
jonaslagoni Oct 9, 2023
8cbbc99
chore(release): v3.0.0-next-major-spec.5 (#870)
asyncapi-bot Oct 9, 2023
67cfc57
feat: bump spec version to latest (#871)
AceTheCreator Oct 9, 2023
7b74316
chore(release): v3.0.0-next-major-spec.6 (#872)
asyncapi-bot Oct 9, 2023
cacf5a8
fix: use relative paths (#880)
KhudaDad414 Oct 16, 2023
3582d31
chore(release): v3.0.0-next-major-spec.7 (#881)
asyncapi-bot Oct 16, 2023
a93f248
feat!: remove messageId() (#889)
fmvilas Nov 6, 2023
abb2717
chore(release): v3.0.0-next-major-spec.8 (#890)
asyncapi-bot Nov 6, 2023
2978ee5
fix: change ParserAPIVersion constant to 3 (#892)
smoya Nov 7, 2023
0a765c1
chore(release): v3.0.0-next-major-spec.9 (#893)
asyncapi-bot Nov 7, 2023
b569a35
fix: doc.allSchemas() skips now duplicates (#897)
smoya Nov 14, 2023
b3d9005
chore(release): v3.0.0-next-major-spec.10 (#898)
asyncapi-bot Nov 14, 2023
0e636a3
fix: wrong parserAPI number being checked (#902)
jonaslagoni Nov 16, 2023
8be6975
chore(release): v3.0.0-next-major-spec.11 (#903)
asyncapi-bot Nov 16, 2023
0ad2ec8
fix: fix import statement (#908)
KhudaDad414 Nov 20, 2023
4345060
chore(release): v3.0.0-next-major-spec.12 (#909)
asyncapi-bot Nov 20, 2023
fe51a04
feat: add Spectral rule to validate operation messages (#911)
smoya Nov 27, 2023
c3cb73c
chore(release): v3.0.0-next-major-spec.13 (#912)
asyncapi-bot Nov 27, 2023
e6cbd74
feat: add Spectral rules to validate required operation channe and ch…
smoya Nov 28, 2023
62c58da
chore(release): v3.0.0-next-major-spec.14 (#914)
asyncapi-bot Nov 28, 2023
18ee6fe
fix!: traits, id and reply problems for v3 (#910)
jonaslagoni Nov 29, 2023
7d29064
chore(release): v3.0.0-next-major-spec.15 (#915)
asyncapi-bot Nov 29, 2023
3ba5377
Merge remote-tracking branch 'origin/master' into next-major-spec
smoya Nov 30, 2023
7e13609
chore: merge `master` into `next-major-spec`
smoya Nov 30, 2023
d34cb00
ci: disable code duplication analysis for files under src/spec-types …
smoya Nov 30, 2023
50f4f64
feat: prepare for release (#920)
jonaslagoni Nov 30, 2023
ecb1d4c
chore(release): v3.0.0-next-major-spec.16 (#921)
asyncapi-bot Nov 30, 2023
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 4 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -214,9 +214,10 @@ Parser-JS API implements a global API definition for all AsyncAPI parser impleme

The following table shows a compatibility matrix between this parser, and the [Parser-API](https://github.com/asyncapi/parser-api), as well as the AsyncAPI spec version supported by each release of this parser.

| Parser-JS | Parser-API | Spec 2.x |
|-----------|----------------------------------------------------------------------|----------|
| 2.x | [1.x](https://github.com/asyncapi/parser-api/blob/master/docs/v1.md) | ✓ |
| Parser-JS | Parser-API | Spec 2.x | Spec 3.x |
|-----------|-----------------------------------------------------------------------|----------|----------|
| 2.x | [1.x](https://github.com/asyncapi/parser-api/blob/v1.0.0/docs/v1.md) | ✓ | |
| 3.x | [3.x](https://github.com/asyncapi/parser-api/blob/v3.0.0/docs/api.md) | ✓ | ✓ |

- `✓` Fully supported version.
- `-` The AsyncAPI Spec version has features the Parser-JS can't use but the rest are fully supported.
Expand Down
6,156 changes: 2,932 additions & 3,224 deletions package-lock.json

Large diffs are not rendered by default.

4 changes: 2 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@asyncapi/parser",
"version": "2.1.0",
"version": "3.0.0-next-major-spec.13",
"description": "JavaScript AsyncAPI parser.",
"bugs": {
"url": "https://github.com/asyncapi/parser-js/issues"
Expand Down Expand Up @@ -41,7 +41,7 @@
"prepublishOnly": "npm run generate:assets"
},
"dependencies": {
"@asyncapi/specs": "^5.1.0",
"@asyncapi/specs": "^6.0.0-next-major-spec.9",
"@openapi-contrib/openapi-schema-to-json-schema": "~3.2.0",
"@stoplight/json-ref-resolver": "^3.1.5",
"@stoplight/spectral-core": "^1.16.1",
Expand Down
9 changes: 6 additions & 3 deletions src/custom-operations/anonymous-naming.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { xParserMessageName, xParserSchemaId } from '../constants';
import { traverseAsyncApiDocument } from '../iterator';
import { setExtension } from '../utils';
import { setExtension, setExtensionOnJson } from '../utils';

import type {
AsyncAPIDocumentInterface,
Expand Down Expand Up @@ -59,12 +59,15 @@ function assignUidToComponentSchemas(document: AsyncAPIDocumentInterface) {
setExtension(xParserSchemaId, schema.id(), schema);
});
}

function assignUidToAnonymousSchemas(doc: AsyncAPIDocumentInterface) {
let anonymousSchemaCounter = 0;
function callback(schema: SchemaInterface) {
const json = schema.json() as any;
const isMultiFormatSchema = json.schema !== undefined;
const underlyingSchema = isMultiFormatSchema ? json.schema : json;
if (!schema.id()) {
setExtension(xParserSchemaId, `<anonymous-schema-${++anonymousSchemaCounter}>`, schema);
setExtensionOnJson(xParserSchemaId, `<anonymous-schema-${++anonymousSchemaCounter}>`, underlyingSchema);
}
}
traverseAsyncApiDocument(doc, callback);
Expand Down
76 changes: 57 additions & 19 deletions src/custom-operations/apply-traits.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import { JSONPath } from 'jsonpath-plus';

import { mergePatch } from '../utils';

import type { v2 } from '../spec-types';
import type { v2, v3 } from '../spec-types';

const v2TraitPaths = [
// operations
Expand All @@ -17,26 +17,54 @@ const v2TraitPaths = [
];

export function applyTraitsV2(asyncapi: v2.AsyncAPIObject) {
applyAllTraits(asyncapi, v2TraitPaths);
applyAllTraitsV2(asyncapi, v2TraitPaths);
}

function applyAllTraitsV2(asyncapi: Record<string, any>, paths: string[]) {
const visited: Set<unknown> = new Set();
paths.forEach(path => {
JSONPath({
path,
json: asyncapi,
resultType: 'value',
callback(value) {
if (visited.has(value)) {
return;
}
visited.add(value);
applyTraitsToObjectV2(value);
},
});
});
}

function applyTraitsToObjectV2(value: Record<string, unknown>) {
if (Array.isArray(value.traits)) {
for (const trait of value.traits) {
for (const key in trait) {
value[String(key)] = mergePatch(value[String(key)], trait[String(key)]);
}
}
}
}

const v3TraitPaths = [
// operations
'$.channels.*.[publish,subscribe]',
'$.components.channels.*.[publish,subscribe]',
'$.operations.*',
'$.components.operations.*',
// messages
'$.channels.*.[publish,subscribe].message',
'$.channels.*.[publish,subscribe].message.oneOf.*',
'$.components.channels.*.[publish,subscribe].message',
'$.components.channels.*.[publish,subscribe].message.oneOf.*',
'$.channels.*.messages.*',
'$.operations.*.messages.*',
'$.components.channels.*.messages.*',
'$.components.operations.*.messages.*',
'$.components.messages.*',
];

export function applyTraitsV3(asyncapi: v2.AsyncAPIObject) { // TODO: Change type when we will have implemented types for v3
applyAllTraits(asyncapi, v3TraitPaths);
export function applyTraitsV3(asyncapi: v3.AsyncAPIObject) {
applyAllTraitsV3(asyncapi, v3TraitPaths);
}

function applyAllTraits(asyncapi: Record<string, any>, paths: string[]) {
function applyAllTraitsV3(asyncapi: Record<string, any>, paths: string[]) {
const visited: Set<unknown> = new Set();
paths.forEach(path => {
JSONPath({
Expand All @@ -48,18 +76,28 @@ function applyAllTraits(asyncapi: Record<string, any>, paths: string[]) {
return;
}
visited.add(value);
applyTraits(value);
applyTraitsToObjectV3(value);
},
});
});
}

function applyTraits(value: Record<string, unknown> & { traits?: any[] }) {
if (Array.isArray(value.traits)) {
for (const trait of value.traits) {
for (const key in trait) {
value[String(key)] = mergePatch(value[String(key)], trait[String(key)]);
}
function applyTraitsToObjectV3(value: Record<string, unknown>) {
if (!Array.isArray(value.traits)) {
return;
}

// shallow copy of object
const copy = { ...value };
// reset the object but preserve the reference
for (const key in value) {
delete value[key];
}

// merge root object at the end
for (const trait of [...copy.traits as any[], copy]) {
for (const key in trait) {
value[String(key)] = mergePatch(value[String(key)], trait[String(key)]);
}
}
}
}
29 changes: 24 additions & 5 deletions src/custom-operations/index.ts
Original file line number Diff line number Diff line change
@@ -1,33 +1,52 @@
import { applyTraitsV2 } from './apply-traits';
import { applyTraitsV2, applyTraitsV3 } from './apply-traits';
import { resolveCircularRefs } from './resolve-circular-refs';
import { parseSchemasV2 } from './parse-schema';
import { parseSchemasV2, parseSchemasV3 } from './parse-schema';
import { anonymousNaming } from './anonymous-naming';

import type { RulesetFunctionContext } from '@stoplight/spectral-core';
import type { Parser } from '../parser';
import type { ParseOptions } from '../parse';
import type { AsyncAPIDocumentInterface } from '../models';
import type { DetailedAsyncAPI } from '../types';
import type { v2, v3 } from '../spec-types';
import { checkCircularRefs } from './check-circular-refs';

export async function customOperations(parser: Parser, document: AsyncAPIDocumentInterface, detailed: DetailedAsyncAPI, inventory: RulesetFunctionContext['documentInventory'], options: ParseOptions): Promise<void> {
switch (detailed.semver.major) {
case 2: return operationsV2(parser, document, detailed, inventory, options);
// case 3: return operationsV3(parser, document, detailed, options);
case 3: return operationsV3(parser, document, detailed, inventory, options);
}
}

async function operationsV2(parser: Parser, document: AsyncAPIDocumentInterface, detailed: DetailedAsyncAPI, inventory: RulesetFunctionContext['documentInventory'], options: ParseOptions): Promise<void> {
checkCircularRefs(document);

if (options.applyTraits) {
applyTraitsV2(detailed.parsed);
applyTraitsV2(detailed.parsed as v2.AsyncAPIObject);
}
if (options.parseSchemas) {
await parseSchemasV2(parser, detailed);
}

// anonymous naming and resolving circular refrences should be done after custom schemas parsing
// anonymous naming and resolving circular references should be done after custom schemas parsing
if (inventory) {
resolveCircularRefs(document, inventory);
}
anonymousNaming(document);
}

async function operationsV3(parser: Parser, document: AsyncAPIDocumentInterface, detailed: DetailedAsyncAPI, inventory: RulesetFunctionContext['documentInventory'], options: ParseOptions): Promise<void> {
checkCircularRefs(document);

if (options.applyTraits) {
applyTraitsV3(detailed.parsed as v3.AsyncAPIObject);
}
if (options.parseSchemas) {
await parseSchemasV3(parser, detailed);
}
// anonymous naming and resolving circular references should be done after custom schemas parsing
if (inventory) {
resolveCircularRefs(document, inventory);
}
anonymousNaming(document);
}
80 changes: 80 additions & 0 deletions src/custom-operations/parse-schema.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,24 @@ const customSchemasPathsV2 = [
'$.components.messages.*',
];

const customSchemasPathsV3 = [
// channels
'$.channels.*.messages.*.payload',
'$.channels.*.messages.*.headers',
'$.components.channels.*.messages.*.payload',
'$.components.channels.*.messages.*.headers',
// operations
'$.operations.*.messages.*.payload',
'$.operations.*.messages.*.headers',
'$.components.operations.*.messages.*.payload',
'$.components.operations.*.messages.*.headers',
// messages
'$.components.messages.*.payload',
'$.components.messages.*.headers.*',
// schemas
'$.components.schemas.*',
];

export async function parseSchemasV2(parser: Parser, detailed: DetailedAsyncAPI) {
const defaultSchemaFormat = getDefaultSchemaFormat(detailed.semver.version);
const parseItems: Array<ToParseItem> = [];
Expand Down Expand Up @@ -65,6 +83,68 @@ export async function parseSchemasV2(parser: Parser, detailed: DetailedAsyncAPI)
return Promise.all(parseItems.map(item => parseSchemaV2(parser, item)));
}

export async function parseSchemasV3(parser: Parser, detailed: DetailedAsyncAPI) {
const defaultSchemaFormat = getDefaultSchemaFormat(detailed.semver.version);
const parseItems: Array<ToParseItem> = [];

const visited: Set<unknown> = new Set();
customSchemasPathsV3.forEach(path => {
JSONPath({
path,
json: detailed.parsed,
resultType: 'all',
callback(result) {
const value = result.value;
if (visited.has(value)) {
return;
}
visited.add(value);

const schema = value.schema;
if (!schema) {
return;
}

let schemaFormat = value.schemaFormat;
if (!schemaFormat) {
return;
}
schemaFormat = getSchemaFormat(value.schemaFormat, detailed.semver.version);

parseItems.push({
input: {
asyncapi: detailed,
data: schema,
meta: {
message: value,
},
path: [...splitPath(result.path), 'schema'],
schemaFormat,
defaultSchemaFormat,
},
value,
});
},
});
});

return Promise.all(parseItems.map(item => parseSchemaV3(parser, item)));
}

async function parseSchemaV3(parser: Parser, item: ToParseItem) {
const originalData = item.input.data;
const parsedData = await parseSchema(parser, item.input);
if (item.value?.schema !== undefined) {
item.value.schema = parsedData;
} else {
item.value = parsedData;
}
// save original payload only when data is different (returned by custom parsers)
if (originalData !== parsedData) {
item.value[xParserOriginalPayload] = originalData;
}
}

async function parseSchemaV2(parser: Parser, item: ToParseItem) {
const originalData = item.input.data;
const parsedData = item.value.payload = await parseSchema(parser, item.input);
Expand Down
11 changes: 6 additions & 5 deletions src/document.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { AsyncAPIDocumentV2, AsyncAPIDocumentV3 } from './models';
import { AsyncAPIDocumentV2, AsyncAPIDocumentV3, ParserAPIVersion } from './models';
import { unstringify } from './stringify';
import { createDetailedAsyncAPI } from './utils';

Expand All @@ -11,13 +11,14 @@ import {
import type { AsyncAPIDocumentInterface } from './models';
import type { OldAsyncAPIDocument } from './old-api';
import type { DetailedAsyncAPI, AsyncAPIObject } from './types';
import { v2, v3 } from 'spec-types';

export function createAsyncAPIDocument(asyncapi: DetailedAsyncAPI): AsyncAPIDocumentInterface {
switch (asyncapi.semver.major) {
case 2:
return new AsyncAPIDocumentV2(asyncapi.parsed, { asyncapi, pointer: '/' });
// case 3:
// return new AsyncAPIDocumentV3(asyncapi.parsed, { asyncapi, pointer: '/' });
return new AsyncAPIDocumentV2(asyncapi.parsed as v2.AsyncAPIObject, { asyncapi, pointer: '/' });
case 3:
return new AsyncAPIDocumentV3(asyncapi.parsed as v3.AsyncAPIObject, { asyncapi, pointer: '/' });
default:
throw new Error(`Unsupported AsyncAPI version: ${asyncapi.semver.version}`);
}
Expand All @@ -42,7 +43,7 @@ export function isAsyncAPIDocument(maybeDoc: unknown): maybeDoc is AsyncAPIDocum
}
if (maybeDoc && typeof (maybeDoc as AsyncAPIDocumentInterface).json === 'function') {
const versionOfParserAPI = (maybeDoc as AsyncAPIDocumentInterface).json()[xParserApiVersion];
return versionOfParserAPI === 1;
return versionOfParserAPI === ParserAPIVersion;
}
return false;
}
Expand Down
7 changes: 5 additions & 2 deletions src/models/asyncapi.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,12 @@ import type { SchemasInterface } from './schemas';
import type { SecuritySchemesInterface } from './security-schemes';
import type { ServersInterface } from './servers';

import type { v2 } from '../spec-types';
import type { v2, v3 } from '../spec-types';

export interface AsyncAPIDocumentInterface extends BaseModel<v2.AsyncAPIObject>, ExtensionsMixinInterface {
// https://github.com/asyncapi/parser-api/releases/tag/v3.0.0
export const ParserAPIVersion = 3;

export interface AsyncAPIDocumentInterface extends BaseModel<v2.AsyncAPIObject | v3.AsyncAPIObject>, ExtensionsMixinInterface {
version(): string;
defaultContentType(): string | undefined;
hasDefaultContentType(): boolean;
Expand Down
2 changes: 1 addition & 1 deletion src/models/channel.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import type { ServersInterface } from './servers';

export interface ChannelInterface extends BaseModel, BindingsMixinInterface, DescriptionMixinInterface, ExtensionsMixinInterface {
id(): string;
address(): string;
address(): string | null | undefined;
jonaslagoni marked this conversation as resolved.
Show resolved Hide resolved
servers(): ServersInterface;
operations(): OperationsInterface;
messages(): MessagesInterface;
Expand Down
9 changes: 9 additions & 0 deletions src/models/external-documentation.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
import type { BaseModel } from './base';
import type { DescriptionMixinInterface, ExtensionsMixinInterface } from './mixins';

export interface ExternalDocumentationInterface
extends BaseModel, DescriptionMixinInterface, ExtensionsMixinInterface {

id(): string | undefined;
url(): string;
}
Loading