mirror of
https://github.com/LukeHagar/redocly-cli.git
synced 2025-12-06 04:21:09 +00:00
feat: add asyncapi 3.0 (#1620)
This commit is contained in:
6
.changeset/quiet-items-sparkle.md
Normal file
6
.changeset/quiet-items-sparkle.md
Normal file
@@ -0,0 +1,6 @@
|
||||
---
|
||||
"@redocly/openapi-core": minor
|
||||
"@redocly/cli": minor
|
||||
---
|
||||
|
||||
Added support for AsyncAPI 3.0 description linting.
|
||||
11
__tests__/bundle/async3/UserSignedUp.yaml
Normal file
11
__tests__/bundle/async3/UserSignedUp.yaml
Normal file
@@ -0,0 +1,11 @@
|
||||
UserSignedUp:
|
||||
payload:
|
||||
type: object
|
||||
properties:
|
||||
displayName:
|
||||
type: string
|
||||
description: Name of the user
|
||||
email:
|
||||
type: string
|
||||
format: email
|
||||
description: Email of the user
|
||||
3
__tests__/bundle/async3/redocly.yaml
Normal file
3
__tests__/bundle/async3/redocly.yaml
Normal file
@@ -0,0 +1,3 @@
|
||||
apis:
|
||||
main:
|
||||
root: ./simple.yml
|
||||
22
__tests__/bundle/async3/simple.yml
Normal file
22
__tests__/bundle/async3/simple.yml
Normal file
@@ -0,0 +1,22 @@
|
||||
asyncapi: 3.0.0
|
||||
info:
|
||||
title: Account Service
|
||||
version: 1.0.0
|
||||
description: This service is in charge of processing user signups
|
||||
channels:
|
||||
userSignedup:
|
||||
address: user/signedup
|
||||
messages:
|
||||
UserSignedUp:
|
||||
$ref: '#/components/messages/UserSignedUp'
|
||||
operations:
|
||||
sendUserSignedup:
|
||||
action: send
|
||||
channel:
|
||||
$ref: '#/channels/userSignedup'
|
||||
messages:
|
||||
- $ref: '#/channels/userSignedup/messages/UserSignedUp'
|
||||
components:
|
||||
messages:
|
||||
UserSignedUp:
|
||||
$ref: ./UserSignedUp.yaml
|
||||
60
__tests__/bundle/async3/snapshot.js
Normal file
60
__tests__/bundle/async3/snapshot.js
Normal file
@@ -0,0 +1,60 @@
|
||||
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||
|
||||
exports[`E2E bundle async3 1`] = `
|
||||
info:
|
||||
title: Account Service
|
||||
version: 1.0.0
|
||||
description: This service is in charge of processing user signups
|
||||
components:
|
||||
messages:
|
||||
UserSignedUp:
|
||||
UserSignedUp:
|
||||
payload:
|
||||
type: object
|
||||
properties:
|
||||
displayName:
|
||||
type: string
|
||||
description: Name of the user
|
||||
email:
|
||||
type: string
|
||||
format: email
|
||||
description: Email of the user
|
||||
asyncapi: 3.0.0
|
||||
channels:
|
||||
userSignedup:
|
||||
address: user/signedup
|
||||
messages:
|
||||
UserSignedUp:
|
||||
UserSignedUp:
|
||||
payload:
|
||||
type: object
|
||||
properties:
|
||||
displayName:
|
||||
type: string
|
||||
description: Name of the user
|
||||
email:
|
||||
type: string
|
||||
format: email
|
||||
description: Email of the user
|
||||
operations:
|
||||
sendUserSignedup:
|
||||
action: send
|
||||
channel:
|
||||
$ref: '#/channels/userSignedup'
|
||||
messages:
|
||||
- UserSignedUp:
|
||||
payload:
|
||||
type: object
|
||||
properties:
|
||||
displayName:
|
||||
type: string
|
||||
description: Name of the user
|
||||
email:
|
||||
type: string
|
||||
format: email
|
||||
description: Email of the user
|
||||
|
||||
bundling ./simple.yml...
|
||||
📦 Created a bundle for ./simple.yml at stdout <test>ms.
|
||||
|
||||
`;
|
||||
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
36
__tests__/lint/async3/anyof.yml
Normal file
36
__tests__/lint/async3/anyof.yml
Normal file
@@ -0,0 +1,36 @@
|
||||
asyncapi: 3.0.0
|
||||
info:
|
||||
title: AnyOf example
|
||||
version: 1.0.0
|
||||
channels:
|
||||
test:
|
||||
address: test
|
||||
messages:
|
||||
testMessages:
|
||||
$ref: '#/components/messages/testMessages'
|
||||
operations:
|
||||
test:
|
||||
action: receive
|
||||
channel:
|
||||
$ref: '#/channels/test'
|
||||
messages:
|
||||
- $ref: '#/channels/test/messages/testMessages'
|
||||
components:
|
||||
messages:
|
||||
testMessages:
|
||||
payload:
|
||||
anyOf:
|
||||
- $ref: '#/components/schemas/objectWithKey'
|
||||
- $ref: '#/components/schemas/objectWithKey2'
|
||||
schemas:
|
||||
objectWithKey:
|
||||
type: object
|
||||
properties:
|
||||
key:
|
||||
type: string
|
||||
additionalProperties: false
|
||||
objectWithKey2:
|
||||
type: object
|
||||
properties:
|
||||
key2:
|
||||
type: string
|
||||
86
__tests__/lint/async3/application-headers.yml
Normal file
86
__tests__/lint/async3/application-headers.yml
Normal file
@@ -0,0 +1,86 @@
|
||||
asyncapi: 3.0.0
|
||||
info:
|
||||
title: Application Headers example
|
||||
version: 1.0.0
|
||||
description: A cut of the Streetlights API to test application header changes supporting
|
||||
license:
|
||||
name: Apache 2.0
|
||||
url: 'https://www.apache.org/licenses/LICENSE-2.0'
|
||||
defaultContentType: application/json
|
||||
servers:
|
||||
production:
|
||||
host: 'test.mosquitto.org:{port}'
|
||||
protocol: mqtt
|
||||
description: Test broker
|
||||
variables:
|
||||
port:
|
||||
description: Secure connection (TLS) is available through port 8883.
|
||||
default: '1883'
|
||||
enum:
|
||||
- '1883'
|
||||
- '8883'
|
||||
channels:
|
||||
lightingMeasured:
|
||||
address: 'smartylighting/streetlights/1/0/event/{streetlightId}/lighting/measured'
|
||||
messages:
|
||||
lightMeasured:
|
||||
$ref: '#/components/messages/lightMeasured'
|
||||
parameters:
|
||||
streetlightId:
|
||||
$ref: '#/components/parameters/streetlightId'
|
||||
operations:
|
||||
receiveLightMeasurement:
|
||||
action: receive
|
||||
channel:
|
||||
$ref: '#/channels/lightingMeasured'
|
||||
summary: >-
|
||||
Inform about environmental lighting conditions of a particular
|
||||
streetlight.
|
||||
messages:
|
||||
- $ref: '#/channels/lightingMeasured/messages/lightMeasured'
|
||||
components:
|
||||
messages:
|
||||
lightMeasured:
|
||||
name: lightMeasured
|
||||
title: Light measured
|
||||
summary: >-
|
||||
Inform about environmental lighting conditions of a particular
|
||||
streetlight.
|
||||
correlationId:
|
||||
location: $message.header#/MQMD/CorrelId
|
||||
contentType: application/json
|
||||
headers:
|
||||
type: object
|
||||
properties:
|
||||
MQMD:
|
||||
type: object
|
||||
properties:
|
||||
CorrelId:
|
||||
type: string
|
||||
minLength: 24
|
||||
maxLength: 24
|
||||
format: binary
|
||||
applicationInstanceId:
|
||||
$ref: '#/components/schemas/applicationInstanceId'
|
||||
payload:
|
||||
$ref: '#/components/schemas/lightMeasuredPayload'
|
||||
schemas:
|
||||
lightMeasuredPayload:
|
||||
type: object
|
||||
properties:
|
||||
lumens:
|
||||
type: integer
|
||||
minimum: 0
|
||||
description: Light intensity measured in lumens.
|
||||
sentAt:
|
||||
$ref: '#/components/schemas/sentAt'
|
||||
sentAt:
|
||||
type: string
|
||||
format: date-time
|
||||
description: Date and time when the message was sent.
|
||||
applicationInstanceId:
|
||||
description: Unique identifier for a given instance of the publishing application
|
||||
type: string
|
||||
parameters:
|
||||
streetlightId:
|
||||
description: The ID of the streetlight.
|
||||
180
__tests__/lint/async3/correlation-id.yml
Normal file
180
__tests__/lint/async3/correlation-id.yml
Normal file
@@ -0,0 +1,180 @@
|
||||
asyncapi: 3.0.0
|
||||
info:
|
||||
title: Correlation ID Example
|
||||
version: 1.0.0
|
||||
description: A cut of the Streetlights API to test Correlation ID
|
||||
license:
|
||||
name: Apache 2.0
|
||||
url: 'https://www.apache.org/licenses/LICENSE-2.0'
|
||||
defaultContentType: application/json
|
||||
servers:
|
||||
production:
|
||||
host: 'test.mosquitto.org:{port}'
|
||||
protocol: mqtt
|
||||
description: Test broker
|
||||
variables:
|
||||
port:
|
||||
description: Secure connection (TLS) is available through port 8883.
|
||||
default: '1883'
|
||||
enum:
|
||||
- '1883'
|
||||
- '8883'
|
||||
security:
|
||||
- $ref: '#/components/securitySchemes/apiKey'
|
||||
- type: oauth2
|
||||
description: Flows to support OAuth 2.0
|
||||
flows:
|
||||
implicit:
|
||||
authorizationUrl: 'https://authserver.example/auth'
|
||||
availableScopes:
|
||||
'streetlights:on': Ability to switch lights on
|
||||
'streetlights:off': Ability to switch lights off
|
||||
'streetlights:dim': Ability to dim the lights
|
||||
password:
|
||||
tokenUrl: 'https://authserver.example/token'
|
||||
availableScopes:
|
||||
'streetlights:on': Ability to switch lights on
|
||||
'streetlights:off': Ability to switch lights off
|
||||
'streetlights:dim': Ability to dim the lights
|
||||
clientCredentials:
|
||||
tokenUrl: 'https://authserver.example/token'
|
||||
availableScopes:
|
||||
'streetlights:on': Ability to switch lights on
|
||||
'streetlights:off': Ability to switch lights off
|
||||
'streetlights:dim': Ability to dim the lights
|
||||
authorizationCode:
|
||||
authorizationUrl: 'https://authserver.example/auth'
|
||||
tokenUrl: 'https://authserver.example/token'
|
||||
refreshUrl: 'https://authserver.example/refresh'
|
||||
availableScopes:
|
||||
'streetlights:on': Ability to switch lights on
|
||||
'streetlights:off': Ability to switch lights off
|
||||
'streetlights:dim': Ability to dim the lights
|
||||
scopes:
|
||||
- 'streetlights:on'
|
||||
- 'streetlights:off'
|
||||
- 'streetlights:dim'
|
||||
- $ref: '#/components/securitySchemes/openIdConnectWellKnown'
|
||||
channels:
|
||||
lightingMeasured:
|
||||
address: 'smartylighting/streetlights/1/0/event/{streetlightId}/lighting/measured'
|
||||
messages:
|
||||
lightMeasured:
|
||||
$ref: '#/components/messages/lightMeasured'
|
||||
parameters:
|
||||
streetlightId:
|
||||
$ref: '#/components/parameters/streetlightId'
|
||||
lightsDim:
|
||||
address: 'smartylighting/streetlights/1/0/action/{streetlightId}/dim'
|
||||
messages:
|
||||
dimLight:
|
||||
$ref: '#/components/messages/dimLight'
|
||||
parameters:
|
||||
streetlightId:
|
||||
$ref: '#/components/parameters/streetlightId'
|
||||
operations:
|
||||
receiveLightMeasurement:
|
||||
action: receive
|
||||
channel:
|
||||
$ref: '#/channels/lightingMeasured'
|
||||
summary: >-
|
||||
Inform about environmental lighting conditions of a particular
|
||||
streetlight.
|
||||
messages:
|
||||
- $ref: '#/channels/lightingMeasured/messages/lightMeasured'
|
||||
dimLight:
|
||||
action: send
|
||||
channel:
|
||||
$ref: '#/channels/lightsDim'
|
||||
messages:
|
||||
- $ref: '#/channels/lightsDim/messages/dimLight'
|
||||
components:
|
||||
messages:
|
||||
lightMeasured:
|
||||
name: lightMeasured
|
||||
title: Light measured
|
||||
summary: >-
|
||||
Inform about environmental lighting conditions of a particular
|
||||
streetlight.
|
||||
correlationId:
|
||||
location: $message.header#/MQMD/CorrelId
|
||||
contentType: application/json
|
||||
payload:
|
||||
$ref: '#/components/schemas/lightMeasuredPayload'
|
||||
dimLight:
|
||||
name: dimLight
|
||||
title: Dim light
|
||||
summary: Command a particular streetlight to dim the lights.
|
||||
correlationId:
|
||||
$ref: '#/components/correlationIds/sentAtCorrelator'
|
||||
payload:
|
||||
$ref: '#/components/schemas/dimLightPayload'
|
||||
schemas:
|
||||
lightMeasuredPayload:
|
||||
type: object
|
||||
properties:
|
||||
lumens:
|
||||
type: integer
|
||||
minimum: 0
|
||||
description: Light intensity measured in lumens.
|
||||
sentAt:
|
||||
$ref: '#/components/schemas/sentAt'
|
||||
dimLightPayload:
|
||||
type: object
|
||||
properties:
|
||||
percentage:
|
||||
type: integer
|
||||
description: Percentage to which the light should be dimmed to.
|
||||
minimum: 0
|
||||
maximum: 100
|
||||
sentAt:
|
||||
$ref: '#/components/schemas/sentAt'
|
||||
sentAt:
|
||||
type: string
|
||||
format: date-time
|
||||
description: Date and time when the message was sent.
|
||||
parameters:
|
||||
streetlightId:
|
||||
description: The ID of the streetlight.
|
||||
correlationIds:
|
||||
sentAtCorrelator:
|
||||
description: Data from message payload used as correlation ID
|
||||
location: $message.payload#/sentAt
|
||||
securitySchemes:
|
||||
apiKey:
|
||||
type: apiKey
|
||||
in: user
|
||||
description: Provide your API key as the user and leave the password empty.
|
||||
supportedOauthFlows:
|
||||
type: oauth2
|
||||
description: Flows to support OAuth 2.0
|
||||
flows:
|
||||
implicit:
|
||||
authorizationUrl: 'https://authserver.example/auth'
|
||||
availableScopes:
|
||||
'streetlights:on': Ability to switch lights on
|
||||
'streetlights:off': Ability to switch lights off
|
||||
'streetlights:dim': Ability to dim the lights
|
||||
password:
|
||||
tokenUrl: 'https://authserver.example/token'
|
||||
availableScopes:
|
||||
'streetlights:on': Ability to switch lights on
|
||||
'streetlights:off': Ability to switch lights off
|
||||
'streetlights:dim': Ability to dim the lights
|
||||
clientCredentials:
|
||||
tokenUrl: 'https://authserver.example/token'
|
||||
availableScopes:
|
||||
'streetlights:on': Ability to switch lights on
|
||||
'streetlights:off': Ability to switch lights off
|
||||
'streetlights:dim': Ability to dim the lights
|
||||
authorizationCode:
|
||||
authorizationUrl: 'https://authserver.example/auth'
|
||||
tokenUrl: 'https://authserver.example/token'
|
||||
refreshUrl: 'https://authserver.example/refresh'
|
||||
availableScopes:
|
||||
'streetlights:on': Ability to switch lights on
|
||||
'streetlights:off': Ability to switch lights off
|
||||
'streetlights:dim': Ability to dim the lights
|
||||
openIdConnectWellKnown:
|
||||
type: openIdConnect
|
||||
openIdConnectUrl: 'https://authserver.example/.well-known'
|
||||
178
__tests__/lint/async3/gitter-streaming.yml
Normal file
178
__tests__/lint/async3/gitter-streaming.yml
Normal file
@@ -0,0 +1,178 @@
|
||||
asyncapi: 3.0.0
|
||||
id: 'tag:stream.gitter.im,2022:api'
|
||||
info:
|
||||
title: Gitter Streaming API
|
||||
version: 1.0.0
|
||||
servers:
|
||||
production:
|
||||
host: stream.gitter.im
|
||||
pathname: /v1
|
||||
protocol: https
|
||||
protocolVersion: '1.1'
|
||||
security:
|
||||
- $ref: '#/components/securitySchemes/httpBearerToken'
|
||||
channels:
|
||||
rooms:
|
||||
address: '/rooms/{roomId}/{resource}'
|
||||
messages:
|
||||
chatMessage:
|
||||
$ref: '#/components/messages/chatMessage'
|
||||
heartbeat:
|
||||
$ref: '#/components/messages/heartbeat'
|
||||
parameters:
|
||||
roomId:
|
||||
description: Id of the Gitter room.
|
||||
examples:
|
||||
- 53307860c3599d1de448e19d
|
||||
resource:
|
||||
enum:
|
||||
- chatMessages
|
||||
- events
|
||||
description: The resource to consume.
|
||||
operations:
|
||||
sendRoomInfo:
|
||||
action: send
|
||||
channel:
|
||||
$ref: '#/channels/rooms'
|
||||
bindings:
|
||||
http:
|
||||
method: POST
|
||||
messages:
|
||||
- $ref: '#/channels/rooms/messages/chatMessage'
|
||||
- $ref: '#/channels/rooms/messages/heartbeat'
|
||||
components:
|
||||
securitySchemes:
|
||||
httpBearerToken:
|
||||
type: http
|
||||
scheme: bearer
|
||||
messages:
|
||||
chatMessage:
|
||||
summary: >-
|
||||
A message represents an individual chat message sent to a room. They are
|
||||
a sub-resource of a room.
|
||||
payload:
|
||||
schemaFormat: application/schema+yaml;version=draft-07
|
||||
schema:
|
||||
type: object
|
||||
properties:
|
||||
id:
|
||||
type: string
|
||||
description: ID of the message.
|
||||
text:
|
||||
type: string
|
||||
description: Original message in plain-text/markdown.
|
||||
html:
|
||||
type: string
|
||||
description: HTML formatted message.
|
||||
sent:
|
||||
type: string
|
||||
format: date-time
|
||||
description: ISO formatted date of the message.
|
||||
fromUser:
|
||||
type: object
|
||||
description: User that sent the message.
|
||||
properties:
|
||||
id:
|
||||
type: string
|
||||
description: Gitter User ID.
|
||||
username:
|
||||
type: string
|
||||
description: Gitter/GitHub username.
|
||||
displayName:
|
||||
type: string
|
||||
description: Gitter/GitHub user real name.
|
||||
url:
|
||||
type: string
|
||||
description: Path to the user on Gitter.
|
||||
avatarUrl:
|
||||
type: string
|
||||
format: uri
|
||||
description: User avatar URI.
|
||||
avatarUrlSmall:
|
||||
type: string
|
||||
format: uri
|
||||
description: User avatar URI (small).
|
||||
avatarUrlMedium:
|
||||
type: string
|
||||
format: uri
|
||||
description: User avatar URI (medium).
|
||||
v:
|
||||
type: number
|
||||
description: Version.
|
||||
gv:
|
||||
type: string
|
||||
description: Stands for "Gravatar version" and is used for cache busting.
|
||||
unread:
|
||||
type: boolean
|
||||
description: Boolean that indicates if the current user has read the message.
|
||||
readBy:
|
||||
type: number
|
||||
description: Number of users that have read the message.
|
||||
urls:
|
||||
type: array
|
||||
description: List of URLs present in the message.
|
||||
items:
|
||||
type: string
|
||||
format: uri
|
||||
mentions:
|
||||
type: array
|
||||
description: List of @Mentions in the message.
|
||||
items:
|
||||
type: object
|
||||
properties:
|
||||
screenName:
|
||||
type: string
|
||||
userId:
|
||||
type: string
|
||||
userIds:
|
||||
type: array
|
||||
items:
|
||||
type: string
|
||||
issues:
|
||||
type: array
|
||||
description: 'List of #Issues referenced in the message.'
|
||||
items:
|
||||
type: object
|
||||
properties:
|
||||
number:
|
||||
type: string
|
||||
meta:
|
||||
type: array
|
||||
description: Metadata. This is currently not used for anything.
|
||||
items: {}
|
||||
v:
|
||||
type: number
|
||||
description: Version.
|
||||
gv:
|
||||
type: string
|
||||
description: Stands for "Gravatar version" and is used for cache busting.
|
||||
bindings:
|
||||
http:
|
||||
headers:
|
||||
type: object
|
||||
properties:
|
||||
Transfer-Encoding:
|
||||
type: string
|
||||
const: chunked
|
||||
Trailer:
|
||||
type: string
|
||||
const: \r\n
|
||||
heartbeat:
|
||||
summary: Its purpose is to keep the connection alive.
|
||||
payload:
|
||||
schemaFormat: application/schema+yaml;version=draft-07
|
||||
schema:
|
||||
type: string
|
||||
enum:
|
||||
- "\r\n"
|
||||
bindings:
|
||||
http:
|
||||
headers:
|
||||
type: object
|
||||
properties:
|
||||
Transfer-Encoding:
|
||||
type: string
|
||||
const: chunked
|
||||
Trailer:
|
||||
type: string
|
||||
const: \r\n
|
||||
58
__tests__/lint/async3/mercure.yml
Normal file
58
__tests__/lint/async3/mercure.yml
Normal file
@@ -0,0 +1,58 @@
|
||||
asyncapi: 3.0.0
|
||||
info:
|
||||
title: Mercure Hub Example
|
||||
version: 1.0.0
|
||||
description: This example demonstrates how to define a Mercure hub.
|
||||
defaultContentType: application/ld+json
|
||||
servers:
|
||||
production:
|
||||
host: demo.mercure.rocks
|
||||
pathname: /.well-known/mercure
|
||||
protocol: mercure
|
||||
channels:
|
||||
books:
|
||||
address: 'https://example.com/books/{id}'
|
||||
messages:
|
||||
book:
|
||||
$ref: '#/components/messages/book'
|
||||
description: >-
|
||||
Every time a resource of type `http://schema.org/Book` is created or
|
||||
modified, a JSON-LD representation of the new version of this resource
|
||||
must be pushed in this Mercure topic.
|
||||
parameters:
|
||||
id:
|
||||
description: ID of the book
|
||||
operations:
|
||||
ReceiveBooksInfo:
|
||||
action: receive
|
||||
channel:
|
||||
$ref: '#/channels/books'
|
||||
messages:
|
||||
- $ref: '#/channels/books/messages/book'
|
||||
SendBooksInfo:
|
||||
action: send
|
||||
channel:
|
||||
$ref: '#/channels/books'
|
||||
messages:
|
||||
- $ref: '#/channels/books/messages/book'
|
||||
components:
|
||||
messages:
|
||||
book:
|
||||
summary: The content of a book resource.
|
||||
externalDocs:
|
||||
url: 'https://schema.org/Book'
|
||||
payload:
|
||||
type: object
|
||||
properties:
|
||||
'@id':
|
||||
type: string
|
||||
format: iri-reference
|
||||
'@type':
|
||||
type: string
|
||||
format: iri-reference
|
||||
name:
|
||||
type: string
|
||||
isbn:
|
||||
type: string
|
||||
abstract:
|
||||
type: string
|
||||
29
__tests__/lint/async3/not.yml
Normal file
29
__tests__/lint/async3/not.yml
Normal file
@@ -0,0 +1,29 @@
|
||||
asyncapi: 3.0.0
|
||||
info:
|
||||
title: Not example
|
||||
version: 1.0.0
|
||||
channels:
|
||||
test:
|
||||
address: test
|
||||
messages:
|
||||
testMessages:
|
||||
$ref: '#/components/messages/testMessages'
|
||||
operations:
|
||||
onTestMsg:
|
||||
action: receive
|
||||
channel:
|
||||
$ref: '#/channels/test'
|
||||
messages:
|
||||
- $ref: '#/channels/test/messages/testMessages'
|
||||
components:
|
||||
messages:
|
||||
testMessages:
|
||||
payload:
|
||||
$ref: '#/components/schemas/testSchema'
|
||||
schemas:
|
||||
testSchema:
|
||||
type: object
|
||||
properties:
|
||||
key:
|
||||
not:
|
||||
type: integer
|
||||
57
__tests__/lint/async3/oneof.yml
Normal file
57
__tests__/lint/async3/oneof.yml
Normal file
@@ -0,0 +1,57 @@
|
||||
asyncapi: 3.0.0
|
||||
info:
|
||||
title: OneOf example
|
||||
version: 1.0.0
|
||||
channels:
|
||||
test:
|
||||
address: test
|
||||
messages:
|
||||
testMessages:
|
||||
$ref: '#/components/messages/testMessages'
|
||||
test2:
|
||||
address: test2
|
||||
messages:
|
||||
objectWithKey:
|
||||
payload:
|
||||
$ref: '#/components/schemas/objectWithKey'
|
||||
objectWithKey2:
|
||||
payload:
|
||||
$ref: '#/components/schemas/objectWithKey2'
|
||||
operations:
|
||||
onTestMsg:
|
||||
action: receive
|
||||
channel:
|
||||
$ref: '#/channels/test'
|
||||
messages:
|
||||
- $ref: '#/channels/test/messages/testMessages'
|
||||
sendTest:
|
||||
action: send
|
||||
channel:
|
||||
$ref: '#/channels/test2'
|
||||
messages:
|
||||
- $ref: '#/channels/test2/messages/objectWithKey'
|
||||
- $ref: '#/channels/test2/messages/objectWithKey2'
|
||||
components:
|
||||
messages:
|
||||
testMessages:
|
||||
payload:
|
||||
oneOf:
|
||||
- $ref: '#/components/schemas/objectWithKey'
|
||||
- $ref: '#/components/schemas/objectWithKey2'
|
||||
testMessage1:
|
||||
payload:
|
||||
$ref: '#/components/schemas/objectWithKey'
|
||||
testMessage2:
|
||||
payload:
|
||||
$ref: '#/components/schemas/objectWithKey2'
|
||||
schemas:
|
||||
objectWithKey:
|
||||
type: object
|
||||
properties:
|
||||
key:
|
||||
type: string
|
||||
objectWithKey2:
|
||||
type: object
|
||||
properties:
|
||||
key2:
|
||||
type: string
|
||||
117
__tests__/lint/async3/operation-security.yml
Normal file
117
__tests__/lint/async3/operation-security.yml
Normal file
@@ -0,0 +1,117 @@
|
||||
asyncapi: 3.0.0
|
||||
info:
|
||||
title: Notifications
|
||||
version: 1.0.0
|
||||
description: >-
|
||||
This contract defines HTTP Push notification for application authorization
|
||||
revocation topic
|
||||
channels:
|
||||
authRevoke:
|
||||
address: AUTHORIZATION_REVOCATION
|
||||
messages:
|
||||
message:
|
||||
$ref: '#/components/messages/message'
|
||||
operations:
|
||||
sendAuthRevoke:
|
||||
action: send
|
||||
channel:
|
||||
$ref: '#/channels/authRevoke'
|
||||
security:
|
||||
- type: oauth2
|
||||
description: The oauth security descriptions
|
||||
flows:
|
||||
clientCredentials:
|
||||
tokenUrl: 'https://example.com/api/oauth/dialog'
|
||||
availableScopes:
|
||||
'subscribe:auth_revocations': Scope required for authorization revocation topic
|
||||
scopes:
|
||||
- 'subscribe:auth_revocations'
|
||||
bindings:
|
||||
http:
|
||||
method: POST
|
||||
messages:
|
||||
- $ref: '#/channels/authRevoke/messages/message'
|
||||
components:
|
||||
messages:
|
||||
message:
|
||||
headers:
|
||||
type: object
|
||||
properties:
|
||||
X-SIGNATURE:
|
||||
description: ECC message signature
|
||||
type: string
|
||||
Content-Type:
|
||||
type: string
|
||||
enum:
|
||||
- application/json
|
||||
payload:
|
||||
type: object
|
||||
properties:
|
||||
metadata:
|
||||
$ref: '#/components/schemas/MetaData'
|
||||
notification:
|
||||
$ref: '#/components/schemas/Notification'
|
||||
schemas:
|
||||
MetaData:
|
||||
type: object
|
||||
properties:
|
||||
topic:
|
||||
type: string
|
||||
description: Topic subscribed to.
|
||||
schemaVersion:
|
||||
type: string
|
||||
description: The schema for this topic.
|
||||
deprecated:
|
||||
type: boolean
|
||||
description: If this is a deprecated schema or topic.
|
||||
default: 'false'
|
||||
Notification:
|
||||
type: object
|
||||
properties:
|
||||
notificationId:
|
||||
type: string
|
||||
description: The notification Id.
|
||||
eventDate:
|
||||
type: string
|
||||
description: The event date associated with this notification in UTC.
|
||||
publishDate:
|
||||
type: string
|
||||
description: The message publish date in UTC.
|
||||
publishAttemptCount:
|
||||
type: integer
|
||||
description: The number of attempts made to publish this message.
|
||||
data:
|
||||
$ref: '#/components/schemas/AuthorizationRevocationData'
|
||||
AuthorizationRevocationData:
|
||||
type: object
|
||||
description: The Authorization Revocation payload.
|
||||
properties:
|
||||
username:
|
||||
type: string
|
||||
description: The username for the user.
|
||||
userId:
|
||||
type: string
|
||||
description: The immutable public userId for the user
|
||||
eiasToken:
|
||||
type: string
|
||||
description: The legacy eiasToken specific to the user
|
||||
revokeReason:
|
||||
type: string
|
||||
enum:
|
||||
- REVOKED_BY_APP
|
||||
- REVOKED_BY_USER
|
||||
- REVOKED_BY_ADMIN
|
||||
- PASSWORD_CHANGE
|
||||
description: The reason for authorization revocation
|
||||
revocationDate:
|
||||
type: string
|
||||
description: Date and time when the authorization was revoked
|
||||
securitySchemes:
|
||||
petstore_auth:
|
||||
type: oauth2
|
||||
description: The oauth security descriptions
|
||||
flows:
|
||||
clientCredentials:
|
||||
tokenUrl: 'https://example.com/api/oauth/dialog'
|
||||
availableScopes:
|
||||
'subscribe:auth_revocations': Scope required for authorization revocation topic
|
||||
36
__tests__/lint/async3/redocly.yaml
Normal file
36
__tests__/lint/async3/redocly.yaml
Normal file
@@ -0,0 +1,36 @@
|
||||
apis:
|
||||
anyof:
|
||||
root: ./anyof.yml
|
||||
application-headers:
|
||||
root: ./application-headers.yml
|
||||
correlation-id:
|
||||
root: ./correlation-id.yml
|
||||
gitter-streaming:
|
||||
root: ./gitter-streaming.yml
|
||||
mercure:
|
||||
root: ./mercure.yml
|
||||
not:
|
||||
root: ./not.yml
|
||||
oneof:
|
||||
root: ./oneof.yml
|
||||
operation-security:
|
||||
root: ./operation-security.yml
|
||||
rpc-client:
|
||||
root: ./rpc-client.yml
|
||||
rpc-server:
|
||||
root: ./rpc-server.yml
|
||||
simple:
|
||||
root: ./simple.yml
|
||||
slack-rtm:
|
||||
root: ./slack-rtm.yml
|
||||
streetlights-kafka:
|
||||
root: ./streetlights-kafka.yml
|
||||
streetlights-mqtt:
|
||||
root: ./streetlights-mqtt.yml
|
||||
streetlights-operation-security:
|
||||
root: ./streetlights-operation-security.yml
|
||||
websocket-gemini:
|
||||
root: ./websocket-gemini.yml
|
||||
|
||||
rules:
|
||||
spec: error
|
||||
72
__tests__/lint/async3/rpc-client.yml
Normal file
72
__tests__/lint/async3/rpc-client.yml
Normal file
@@ -0,0 +1,72 @@
|
||||
asyncapi: 3.0.0
|
||||
id: 'urn:example:rpcclient'
|
||||
info:
|
||||
title: RPC Client Example
|
||||
version: 1.0.0
|
||||
description: This example demonstrates how to define an RPC client.
|
||||
defaultContentType: application/json
|
||||
servers:
|
||||
production:
|
||||
host: rabbitmq.example.org
|
||||
protocol: amqp
|
||||
channels:
|
||||
queue:
|
||||
address: '{queue}'
|
||||
messages:
|
||||
receiveSumResult:
|
||||
correlationId:
|
||||
location: $message.header#/correlation_id
|
||||
payload:
|
||||
type: object
|
||||
properties:
|
||||
result:
|
||||
type: number
|
||||
examples:
|
||||
- 7
|
||||
parameters:
|
||||
queue: {}
|
||||
bindings:
|
||||
amqp:
|
||||
is: queue
|
||||
queue:
|
||||
exclusive: true
|
||||
rpc_queue:
|
||||
address: rpc_queue
|
||||
messages:
|
||||
requestSum:
|
||||
correlationId:
|
||||
location: $message.header#/correlation_id
|
||||
payload:
|
||||
type: object
|
||||
properties:
|
||||
numbers:
|
||||
type: array
|
||||
items:
|
||||
type: number
|
||||
examples:
|
||||
- - 4
|
||||
- 3
|
||||
bindings:
|
||||
amqp:
|
||||
is: queue
|
||||
queue:
|
||||
durable: false
|
||||
operations:
|
||||
receiveSumResult:
|
||||
action: receive
|
||||
channel:
|
||||
$ref: '#/channels/queue'
|
||||
bindings:
|
||||
amqp:
|
||||
ack: false
|
||||
messages:
|
||||
- $ref: '#/channels/queue/messages/receiveSumResult'
|
||||
requestSum:
|
||||
action: send
|
||||
channel:
|
||||
$ref: '#/channels/rpc_queue'
|
||||
bindings:
|
||||
amqp:
|
||||
ack: true
|
||||
messages:
|
||||
- $ref: '#/channels/rpc_queue/messages/requestSum'
|
||||
69
__tests__/lint/async3/rpc-server.yml
Normal file
69
__tests__/lint/async3/rpc-server.yml
Normal file
@@ -0,0 +1,69 @@
|
||||
asyncapi: 3.0.0
|
||||
id: 'urn:example:rpcserver'
|
||||
info:
|
||||
title: RPC Server Example
|
||||
version: 1.0.0
|
||||
description: This example demonstrates how to define an RPC server.
|
||||
defaultContentType: application/json
|
||||
servers:
|
||||
production:
|
||||
host: rabbitmq.example.org
|
||||
protocol: amqp
|
||||
channels:
|
||||
queue:
|
||||
address: '{queue}'
|
||||
messages:
|
||||
sendSumResult:
|
||||
correlationId:
|
||||
location: $message.header#/correlation_id
|
||||
payload:
|
||||
type: object
|
||||
properties:
|
||||
result:
|
||||
type: number
|
||||
examples:
|
||||
- 7
|
||||
parameters:
|
||||
queue: {}
|
||||
bindings:
|
||||
amqp:
|
||||
is: queue
|
||||
queue:
|
||||
exclusive: true
|
||||
rpc_queue:
|
||||
address: rpc_queue
|
||||
messages:
|
||||
sum:
|
||||
correlationId:
|
||||
location: $message.header#/correlation_id
|
||||
payload:
|
||||
type: object
|
||||
properties:
|
||||
numbers:
|
||||
type: array
|
||||
items:
|
||||
type: number
|
||||
examples:
|
||||
- - 4
|
||||
- 3
|
||||
bindings:
|
||||
amqp:
|
||||
is: queue
|
||||
queue:
|
||||
durable: false
|
||||
operations:
|
||||
sendSumResult:
|
||||
action: send
|
||||
channel:
|
||||
$ref: '#/channels/queue'
|
||||
bindings:
|
||||
amqp:
|
||||
ack: true
|
||||
messages:
|
||||
- $ref: '#/channels/queue/messages/sendSumResult'
|
||||
sum:
|
||||
action: receive
|
||||
channel:
|
||||
$ref: '#/channels/rpc_queue'
|
||||
messages:
|
||||
- $ref: '#/channels/rpc_queue/messages/sum'
|
||||
31
__tests__/lint/async3/simple.yml
Normal file
31
__tests__/lint/async3/simple.yml
Normal file
@@ -0,0 +1,31 @@
|
||||
asyncapi: 3.0.0
|
||||
info:
|
||||
title: Account Service
|
||||
version: 1.0.0
|
||||
description: This service is in charge of processing user signups
|
||||
channels:
|
||||
userSignedup:
|
||||
address: user/signedup
|
||||
messages:
|
||||
UserSignedUp:
|
||||
$ref: '#/components/messages/UserSignedUp'
|
||||
operations:
|
||||
sendUserSignedup:
|
||||
action: send
|
||||
channel:
|
||||
$ref: '#/channels/userSignedup'
|
||||
messages:
|
||||
- $ref: '#/channels/userSignedup/messages/UserSignedUp'
|
||||
components:
|
||||
messages:
|
||||
UserSignedUp:
|
||||
payload:
|
||||
type: object
|
||||
properties:
|
||||
displayName:
|
||||
type: string
|
||||
description: Name of the user
|
||||
email:
|
||||
type: string
|
||||
format: email
|
||||
description: Email of the user
|
||||
982
__tests__/lint/async3/slack-rtm.yml
Normal file
982
__tests__/lint/async3/slack-rtm.yml
Normal file
@@ -0,0 +1,982 @@
|
||||
asyncapi: 3.0.0
|
||||
id: 'wss://wss-primary.slack.com/websocket'
|
||||
info:
|
||||
title: Slack Real Time Messaging API
|
||||
version: 1.0.0
|
||||
servers:
|
||||
production:
|
||||
host: slack.com
|
||||
pathname: /api/rtm.connect
|
||||
protocol: https
|
||||
protocolVersion: '1.1'
|
||||
security:
|
||||
- $ref: '#/components/securitySchemes/token'
|
||||
channels:
|
||||
root:
|
||||
address: /
|
||||
messages:
|
||||
outgoingMessage:
|
||||
$ref: '#/components/messages/outgoingMessage'
|
||||
hello:
|
||||
$ref: '#/components/messages/hello'
|
||||
connectionError:
|
||||
$ref: '#/components/messages/connectionError'
|
||||
accountsChanged:
|
||||
$ref: '#/components/messages/accountsChanged'
|
||||
botAdded:
|
||||
$ref: '#/components/messages/botAdded'
|
||||
botChanged:
|
||||
$ref: '#/components/messages/botChanged'
|
||||
channelArchive:
|
||||
$ref: '#/components/messages/channelArchive'
|
||||
channelCreated:
|
||||
$ref: '#/components/messages/channelCreated'
|
||||
channelDeleted:
|
||||
$ref: '#/components/messages/channelDeleted'
|
||||
channelHistoryChanged:
|
||||
$ref: '#/components/messages/channelHistoryChanged'
|
||||
channelJoined:
|
||||
$ref: '#/components/messages/channelJoined'
|
||||
channelLeft:
|
||||
$ref: '#/components/messages/channelLeft'
|
||||
channelMarked:
|
||||
$ref: '#/components/messages/channelMarked'
|
||||
channelRename:
|
||||
$ref: '#/components/messages/channelRename'
|
||||
channelUnarchive:
|
||||
$ref: '#/components/messages/channelUnarchive'
|
||||
commandsChanged:
|
||||
$ref: '#/components/messages/commandsChanged'
|
||||
dndUpdated:
|
||||
$ref: '#/components/messages/dndUpdated'
|
||||
dndUpdatedUser:
|
||||
$ref: '#/components/messages/dndUpdatedUser'
|
||||
emailDomainChanged:
|
||||
$ref: '#/components/messages/emailDomainChanged'
|
||||
emojiRemoved:
|
||||
$ref: '#/components/messages/emojiRemoved'
|
||||
emojiAdded:
|
||||
$ref: '#/components/messages/emojiAdded'
|
||||
fileChange:
|
||||
$ref: '#/components/messages/fileChange'
|
||||
fileCommentAdded:
|
||||
$ref: '#/components/messages/fileCommentAdded'
|
||||
fileCommentDeleted:
|
||||
$ref: '#/components/messages/fileCommentDeleted'
|
||||
fileCommentEdited:
|
||||
$ref: '#/components/messages/fileCommentEdited'
|
||||
fileCreated:
|
||||
$ref: '#/components/messages/fileCreated'
|
||||
fileDeleted:
|
||||
$ref: '#/components/messages/fileDeleted'
|
||||
filePublic:
|
||||
$ref: '#/components/messages/filePublic'
|
||||
fileShared:
|
||||
$ref: '#/components/messages/fileShared'
|
||||
fileUnshared:
|
||||
$ref: '#/components/messages/fileUnshared'
|
||||
goodbye:
|
||||
$ref: '#/components/messages/goodbye'
|
||||
groupArchive:
|
||||
$ref: '#/components/messages/groupArchive'
|
||||
groupClose:
|
||||
$ref: '#/components/messages/groupClose'
|
||||
groupHistoryChanged:
|
||||
$ref: '#/components/messages/groupHistoryChanged'
|
||||
groupJoined:
|
||||
$ref: '#/components/messages/groupJoined'
|
||||
groupLeft:
|
||||
$ref: '#/components/messages/groupLeft'
|
||||
groupMarked:
|
||||
$ref: '#/components/messages/groupMarked'
|
||||
groupOpen:
|
||||
$ref: '#/components/messages/groupOpen'
|
||||
groupRename:
|
||||
$ref: '#/components/messages/groupRename'
|
||||
groupUnarchive:
|
||||
$ref: '#/components/messages/groupUnarchive'
|
||||
imClose:
|
||||
$ref: '#/components/messages/imClose'
|
||||
imCreated:
|
||||
$ref: '#/components/messages/imCreated'
|
||||
imMarked:
|
||||
$ref: '#/components/messages/imMarked'
|
||||
imOpen:
|
||||
$ref: '#/components/messages/imOpen'
|
||||
manualPresenceChange:
|
||||
$ref: '#/components/messages/manualPresenceChange'
|
||||
memberJoinedChannel:
|
||||
$ref: '#/components/messages/memberJoinedChannel'
|
||||
message:
|
||||
$ref: '#/components/messages/message'
|
||||
operations:
|
||||
receiveOutgoingMessage:
|
||||
action: receive
|
||||
channel:
|
||||
$ref: '#/channels/root'
|
||||
messages:
|
||||
- $ref: '#/channels/root/messages/outgoingMessage'
|
||||
sendMessages:
|
||||
action: send
|
||||
channel:
|
||||
$ref: '#/channels/root'
|
||||
messages:
|
||||
- $ref: '#/channels/root/messages/hello'
|
||||
- $ref: '#/channels/root/messages/connectionError'
|
||||
- $ref: '#/channels/root/messages/accountsChanged'
|
||||
- $ref: '#/channels/root/messages/botAdded'
|
||||
- $ref: '#/channels/root/messages/botChanged'
|
||||
- $ref: '#/channels/root/messages/channelArchive'
|
||||
- $ref: '#/channels/root/messages/channelCreated'
|
||||
- $ref: '#/channels/root/messages/channelDeleted'
|
||||
- $ref: '#/channels/root/messages/channelHistoryChanged'
|
||||
- $ref: '#/channels/root/messages/channelJoined'
|
||||
- $ref: '#/channels/root/messages/channelLeft'
|
||||
- $ref: '#/channels/root/messages/channelMarked'
|
||||
- $ref: '#/channels/root/messages/channelRename'
|
||||
- $ref: '#/channels/root/messages/channelUnarchive'
|
||||
- $ref: '#/channels/root/messages/commandsChanged'
|
||||
- $ref: '#/channels/root/messages/dndUpdated'
|
||||
- $ref: '#/channels/root/messages/dndUpdatedUser'
|
||||
- $ref: '#/channels/root/messages/emailDomainChanged'
|
||||
- $ref: '#/channels/root/messages/emojiRemoved'
|
||||
- $ref: '#/channels/root/messages/emojiAdded'
|
||||
- $ref: '#/channels/root/messages/fileChange'
|
||||
- $ref: '#/channels/root/messages/fileCommentAdded'
|
||||
- $ref: '#/channels/root/messages/fileCommentDeleted'
|
||||
- $ref: '#/channels/root/messages/fileCommentEdited'
|
||||
- $ref: '#/channels/root/messages/fileCreated'
|
||||
- $ref: '#/channels/root/messages/fileDeleted'
|
||||
- $ref: '#/channels/root/messages/filePublic'
|
||||
- $ref: '#/channels/root/messages/fileShared'
|
||||
- $ref: '#/channels/root/messages/fileUnshared'
|
||||
- $ref: '#/channels/root/messages/goodbye'
|
||||
- $ref: '#/channels/root/messages/groupArchive'
|
||||
- $ref: '#/channels/root/messages/groupClose'
|
||||
- $ref: '#/channels/root/messages/groupHistoryChanged'
|
||||
- $ref: '#/channels/root/messages/groupJoined'
|
||||
- $ref: '#/channels/root/messages/groupLeft'
|
||||
- $ref: '#/channels/root/messages/groupMarked'
|
||||
- $ref: '#/channels/root/messages/groupOpen'
|
||||
- $ref: '#/channels/root/messages/groupRename'
|
||||
- $ref: '#/channels/root/messages/groupUnarchive'
|
||||
- $ref: '#/channels/root/messages/imClose'
|
||||
- $ref: '#/channels/root/messages/imCreated'
|
||||
- $ref: '#/channels/root/messages/imMarked'
|
||||
- $ref: '#/channels/root/messages/imOpen'
|
||||
- $ref: '#/channels/root/messages/manualPresenceChange'
|
||||
- $ref: '#/channels/root/messages/memberJoinedChannel'
|
||||
- $ref: '#/channels/root/messages/message'
|
||||
components:
|
||||
securitySchemes:
|
||||
token:
|
||||
type: httpApiKey
|
||||
name: token
|
||||
in: query
|
||||
schemas:
|
||||
attachment:
|
||||
type: object
|
||||
properties:
|
||||
fallback:
|
||||
type: string
|
||||
color:
|
||||
type: string
|
||||
pretext:
|
||||
type: string
|
||||
author_name:
|
||||
type: string
|
||||
author_link:
|
||||
type: string
|
||||
format: uri
|
||||
author_icon:
|
||||
type: string
|
||||
format: uri
|
||||
title:
|
||||
type: string
|
||||
title_link:
|
||||
type: string
|
||||
format: uri
|
||||
text:
|
||||
type: string
|
||||
fields:
|
||||
type: array
|
||||
items:
|
||||
type: object
|
||||
properties:
|
||||
title:
|
||||
type: string
|
||||
value:
|
||||
type: string
|
||||
short:
|
||||
type: boolean
|
||||
image_url:
|
||||
type: string
|
||||
format: uri
|
||||
thumb_url:
|
||||
type: string
|
||||
format: uri
|
||||
footer:
|
||||
type: string
|
||||
footer_icon:
|
||||
type: string
|
||||
format: uri
|
||||
ts:
|
||||
type: number
|
||||
messages:
|
||||
hello:
|
||||
summary: First event received upon connection.
|
||||
payload:
|
||||
type: object
|
||||
properties:
|
||||
type:
|
||||
type: string
|
||||
enum:
|
||||
- hello
|
||||
connectionError:
|
||||
summary: Event received when a connection error happens.
|
||||
payload:
|
||||
type: object
|
||||
properties:
|
||||
type:
|
||||
type: string
|
||||
enum:
|
||||
- error
|
||||
error:
|
||||
type: object
|
||||
properties:
|
||||
code:
|
||||
type: number
|
||||
msg:
|
||||
type: string
|
||||
accountsChanged:
|
||||
summary: The list of accounts a user is signed into has changed.
|
||||
payload:
|
||||
type: object
|
||||
properties:
|
||||
type:
|
||||
type: string
|
||||
enum:
|
||||
- accounts_changed
|
||||
botAdded:
|
||||
summary: A bot user was added.
|
||||
payload:
|
||||
type: object
|
||||
properties:
|
||||
type:
|
||||
type: string
|
||||
enum:
|
||||
- bot_added
|
||||
bot:
|
||||
type: object
|
||||
properties:
|
||||
id:
|
||||
type: string
|
||||
app_id:
|
||||
type: string
|
||||
name:
|
||||
type: string
|
||||
icons:
|
||||
type: object
|
||||
additionalProperties:
|
||||
type: string
|
||||
botChanged:
|
||||
summary: A bot user was changed.
|
||||
payload:
|
||||
type: object
|
||||
properties:
|
||||
type:
|
||||
type: string
|
||||
enum:
|
||||
- bot_added
|
||||
bot:
|
||||
type: object
|
||||
properties:
|
||||
id:
|
||||
type: string
|
||||
app_id:
|
||||
type: string
|
||||
name:
|
||||
type: string
|
||||
icons:
|
||||
type: object
|
||||
additionalProperties:
|
||||
type: string
|
||||
channelArchive:
|
||||
summary: A channel was archived.
|
||||
payload:
|
||||
type: object
|
||||
properties:
|
||||
type:
|
||||
type: string
|
||||
enum:
|
||||
- channel_archive
|
||||
channel:
|
||||
type: string
|
||||
user:
|
||||
type: string
|
||||
channelCreated:
|
||||
summary: A channel was created.
|
||||
payload:
|
||||
type: object
|
||||
properties:
|
||||
type:
|
||||
type: string
|
||||
enum:
|
||||
- channel_created
|
||||
channel:
|
||||
type: object
|
||||
properties:
|
||||
id:
|
||||
type: string
|
||||
name:
|
||||
type: string
|
||||
created:
|
||||
type: number
|
||||
creator:
|
||||
type: string
|
||||
channelDeleted:
|
||||
summary: A channel was deleted.
|
||||
payload:
|
||||
type: object
|
||||
properties:
|
||||
type:
|
||||
type: string
|
||||
enum:
|
||||
- channel_deleted
|
||||
channel:
|
||||
type: string
|
||||
channelHistoryChanged:
|
||||
summary: Bulk updates were made to a channel's history.
|
||||
payload:
|
||||
type: object
|
||||
properties:
|
||||
type:
|
||||
type: string
|
||||
enum:
|
||||
- channel_history_changed
|
||||
latest:
|
||||
type: string
|
||||
ts:
|
||||
type: string
|
||||
event_ts:
|
||||
type: string
|
||||
channelJoined:
|
||||
summary: You joined a channel.
|
||||
payload:
|
||||
type: object
|
||||
properties:
|
||||
type:
|
||||
type: string
|
||||
enum:
|
||||
- channel_joined
|
||||
channel:
|
||||
type: object
|
||||
properties:
|
||||
id:
|
||||
type: string
|
||||
name:
|
||||
type: string
|
||||
created:
|
||||
type: number
|
||||
creator:
|
||||
type: string
|
||||
channelLeft:
|
||||
summary: You left a channel.
|
||||
payload:
|
||||
type: object
|
||||
properties:
|
||||
type:
|
||||
type: string
|
||||
enum:
|
||||
- channel_left
|
||||
channel:
|
||||
type: string
|
||||
channelMarked:
|
||||
summary: Your channel read marker was updated.
|
||||
payload:
|
||||
type: object
|
||||
properties:
|
||||
type:
|
||||
type: string
|
||||
enum:
|
||||
- channel_marked
|
||||
channel:
|
||||
type: string
|
||||
ts:
|
||||
type: string
|
||||
channelRename:
|
||||
summary: A channel was renamed.
|
||||
payload:
|
||||
type: object
|
||||
properties:
|
||||
type:
|
||||
type: string
|
||||
enum:
|
||||
- channel_rename
|
||||
channel:
|
||||
type: object
|
||||
properties:
|
||||
id:
|
||||
type: string
|
||||
name:
|
||||
type: string
|
||||
created:
|
||||
type: number
|
||||
channelUnarchive:
|
||||
summary: A channel was unarchived.
|
||||
payload:
|
||||
type: object
|
||||
properties:
|
||||
type:
|
||||
type: string
|
||||
enum:
|
||||
- channel_unarchive
|
||||
channel:
|
||||
type: string
|
||||
user:
|
||||
type: string
|
||||
commandsChanged:
|
||||
summary: A slash command has been added or changed.
|
||||
payload:
|
||||
type: object
|
||||
properties:
|
||||
type:
|
||||
type: string
|
||||
enum:
|
||||
- commands_changed
|
||||
event_ts:
|
||||
type: string
|
||||
dndUpdated:
|
||||
summary: Do not Disturb settings changed for the current user.
|
||||
payload:
|
||||
type: object
|
||||
properties:
|
||||
type:
|
||||
type: string
|
||||
enum:
|
||||
- dnd_updated
|
||||
user:
|
||||
type: string
|
||||
dnd_status:
|
||||
type: object
|
||||
properties:
|
||||
dnd_enabled:
|
||||
type: boolean
|
||||
next_dnd_start_ts:
|
||||
type: number
|
||||
next_dnd_end_ts:
|
||||
type: number
|
||||
snooze_enabled:
|
||||
type: boolean
|
||||
snooze_endtime:
|
||||
type: number
|
||||
dndUpdatedUser:
|
||||
summary: Do not Disturb settings changed for a member.
|
||||
payload:
|
||||
type: object
|
||||
properties:
|
||||
type:
|
||||
type: string
|
||||
enum:
|
||||
- dnd_updated_user
|
||||
user:
|
||||
type: string
|
||||
dnd_status:
|
||||
type: object
|
||||
properties:
|
||||
dnd_enabled:
|
||||
type: boolean
|
||||
next_dnd_start_ts:
|
||||
type: number
|
||||
next_dnd_end_ts:
|
||||
type: number
|
||||
emailDomainChanged:
|
||||
summary: The workspace email domain has changed.
|
||||
payload:
|
||||
type: object
|
||||
properties:
|
||||
type:
|
||||
type: string
|
||||
enum:
|
||||
- email_domain_changed
|
||||
email_domain:
|
||||
type: string
|
||||
event_ts:
|
||||
type: string
|
||||
emojiRemoved:
|
||||
summary: A custom emoji has been removed.
|
||||
payload:
|
||||
type: object
|
||||
properties:
|
||||
type:
|
||||
type: string
|
||||
enum:
|
||||
- emoji_changed
|
||||
subtype:
|
||||
type: string
|
||||
enum:
|
||||
- remove
|
||||
names:
|
||||
type: array
|
||||
items:
|
||||
type: string
|
||||
event_ts:
|
||||
type: string
|
||||
emojiAdded:
|
||||
summary: A custom emoji has been added.
|
||||
payload:
|
||||
type: object
|
||||
properties:
|
||||
type:
|
||||
type: string
|
||||
enum:
|
||||
- emoji_changed
|
||||
subtype:
|
||||
type: string
|
||||
enum:
|
||||
- add
|
||||
name:
|
||||
type: string
|
||||
value:
|
||||
type: string
|
||||
format: uri
|
||||
event_ts:
|
||||
type: string
|
||||
fileChange:
|
||||
summary: A file was changed.
|
||||
payload:
|
||||
type: object
|
||||
properties:
|
||||
type:
|
||||
type: string
|
||||
enum:
|
||||
- file_change
|
||||
file_id:
|
||||
type: string
|
||||
file:
|
||||
type: object
|
||||
properties:
|
||||
id:
|
||||
type: string
|
||||
fileCommentAdded:
|
||||
summary: A file comment was added.
|
||||
payload:
|
||||
type: object
|
||||
properties:
|
||||
type:
|
||||
type: string
|
||||
enum:
|
||||
- file_comment_added
|
||||
comment: {}
|
||||
file_id:
|
||||
type: string
|
||||
file:
|
||||
type: object
|
||||
properties:
|
||||
id:
|
||||
type: string
|
||||
fileCommentDeleted:
|
||||
summary: A file comment was deleted.
|
||||
payload:
|
||||
type: object
|
||||
properties:
|
||||
type:
|
||||
type: string
|
||||
enum:
|
||||
- file_comment_deleted
|
||||
comment:
|
||||
type: string
|
||||
file_id:
|
||||
type: string
|
||||
file:
|
||||
type: object
|
||||
properties:
|
||||
id:
|
||||
type: string
|
||||
fileCommentEdited:
|
||||
summary: A file comment was edited.
|
||||
payload:
|
||||
type: object
|
||||
properties:
|
||||
type:
|
||||
type: string
|
||||
enum:
|
||||
- file_comment_edited
|
||||
comment: {}
|
||||
file_id:
|
||||
type: string
|
||||
file:
|
||||
type: object
|
||||
properties:
|
||||
id:
|
||||
type: string
|
||||
fileCreated:
|
||||
summary: A file was created.
|
||||
payload:
|
||||
type: object
|
||||
properties:
|
||||
type:
|
||||
type: string
|
||||
enum:
|
||||
- file_created
|
||||
file_id:
|
||||
type: string
|
||||
file:
|
||||
type: object
|
||||
properties:
|
||||
id:
|
||||
type: string
|
||||
fileDeleted:
|
||||
summary: A file was deleted.
|
||||
payload:
|
||||
type: object
|
||||
properties:
|
||||
type:
|
||||
type: string
|
||||
enum:
|
||||
- file_deleted
|
||||
file_id:
|
||||
type: string
|
||||
event_ts:
|
||||
type: string
|
||||
filePublic:
|
||||
summary: A file was made public.
|
||||
payload:
|
||||
type: object
|
||||
properties:
|
||||
type:
|
||||
type: string
|
||||
enum:
|
||||
- file_public
|
||||
file_id:
|
||||
type: string
|
||||
file:
|
||||
type: object
|
||||
properties:
|
||||
id:
|
||||
type: string
|
||||
fileShared:
|
||||
summary: A file was shared.
|
||||
payload:
|
||||
type: object
|
||||
properties:
|
||||
type:
|
||||
type: string
|
||||
enum:
|
||||
- file_shared
|
||||
file_id:
|
||||
type: string
|
||||
file:
|
||||
type: object
|
||||
properties:
|
||||
id:
|
||||
type: string
|
||||
fileUnshared:
|
||||
summary: A file was unshared.
|
||||
payload:
|
||||
type: object
|
||||
properties:
|
||||
type:
|
||||
type: string
|
||||
enum:
|
||||
- file_unshared
|
||||
file_id:
|
||||
type: string
|
||||
file:
|
||||
type: object
|
||||
properties:
|
||||
id:
|
||||
type: string
|
||||
goodbye:
|
||||
summary: The server intends to close the connection soon.
|
||||
payload:
|
||||
type: object
|
||||
properties:
|
||||
type:
|
||||
type: string
|
||||
enum:
|
||||
- goodbye
|
||||
groupArchive:
|
||||
summary: A private channel was archived.
|
||||
payload:
|
||||
type: object
|
||||
properties:
|
||||
type:
|
||||
type: string
|
||||
enum:
|
||||
- group_archive
|
||||
channel:
|
||||
type: string
|
||||
groupClose:
|
||||
summary: You closed a private channel.
|
||||
payload:
|
||||
type: object
|
||||
properties:
|
||||
type:
|
||||
type: string
|
||||
enum:
|
||||
- group_close
|
||||
user:
|
||||
type: string
|
||||
channel:
|
||||
type: string
|
||||
groupHistoryChanged:
|
||||
summary: Bulk updates were made to a private channel's history.
|
||||
payload:
|
||||
type: object
|
||||
properties:
|
||||
type:
|
||||
type: string
|
||||
enum:
|
||||
- group_history_changed
|
||||
latest:
|
||||
type: string
|
||||
ts:
|
||||
type: string
|
||||
event_ts:
|
||||
type: string
|
||||
groupJoined:
|
||||
summary: You joined a private channel.
|
||||
payload:
|
||||
type: object
|
||||
properties:
|
||||
type:
|
||||
type: string
|
||||
enum:
|
||||
- group_joined
|
||||
channel:
|
||||
type: object
|
||||
properties:
|
||||
id:
|
||||
type: string
|
||||
name:
|
||||
type: string
|
||||
created:
|
||||
type: number
|
||||
creator:
|
||||
type: string
|
||||
groupLeft:
|
||||
summary: You left a private channel.
|
||||
payload:
|
||||
type: object
|
||||
properties:
|
||||
type:
|
||||
type: string
|
||||
enum:
|
||||
- group_left
|
||||
channel:
|
||||
type: string
|
||||
groupMarked:
|
||||
summary: A private channel read marker was updated.
|
||||
payload:
|
||||
type: object
|
||||
properties:
|
||||
type:
|
||||
type: string
|
||||
enum:
|
||||
- group_marked
|
||||
channel:
|
||||
type: string
|
||||
ts:
|
||||
type: string
|
||||
groupOpen:
|
||||
summary: You opened a private channel.
|
||||
payload:
|
||||
type: object
|
||||
properties:
|
||||
type:
|
||||
type: string
|
||||
enum:
|
||||
- group_open
|
||||
user:
|
||||
type: string
|
||||
channel:
|
||||
type: string
|
||||
groupRename:
|
||||
summary: A private channel was renamed.
|
||||
payload:
|
||||
type: object
|
||||
properties:
|
||||
type:
|
||||
type: string
|
||||
enum:
|
||||
- group_rename
|
||||
channel:
|
||||
type: object
|
||||
properties:
|
||||
id:
|
||||
type: string
|
||||
name:
|
||||
type: string
|
||||
created:
|
||||
type: number
|
||||
groupUnarchive:
|
||||
summary: A private channel was unarchived.
|
||||
payload:
|
||||
type: object
|
||||
properties:
|
||||
type:
|
||||
type: string
|
||||
enum:
|
||||
- group_unarchive
|
||||
channel:
|
||||
type: string
|
||||
user:
|
||||
type: string
|
||||
imClose:
|
||||
summary: You closed a DM.
|
||||
payload:
|
||||
type: object
|
||||
properties:
|
||||
type:
|
||||
type: string
|
||||
enum:
|
||||
- im_close
|
||||
channel:
|
||||
type: string
|
||||
user:
|
||||
type: string
|
||||
imCreated:
|
||||
summary: A DM was created.
|
||||
payload:
|
||||
type: object
|
||||
properties:
|
||||
type:
|
||||
type: string
|
||||
enum:
|
||||
- im_created
|
||||
channel:
|
||||
type: object
|
||||
properties:
|
||||
id:
|
||||
type: string
|
||||
name:
|
||||
type: string
|
||||
created:
|
||||
type: number
|
||||
creator:
|
||||
type: string
|
||||
user:
|
||||
type: string
|
||||
imMarked:
|
||||
summary: A direct message read marker was updated.
|
||||
payload:
|
||||
type: object
|
||||
properties:
|
||||
type:
|
||||
type: string
|
||||
enum:
|
||||
- im_marked
|
||||
channel:
|
||||
type: string
|
||||
ts:
|
||||
type: string
|
||||
imOpen:
|
||||
summary: You opened a DM.
|
||||
payload:
|
||||
type: object
|
||||
properties:
|
||||
type:
|
||||
type: string
|
||||
enum:
|
||||
- im_open
|
||||
channel:
|
||||
type: string
|
||||
user:
|
||||
type: string
|
||||
manualPresenceChange:
|
||||
summary: You manually updated your presence.
|
||||
payload:
|
||||
type: object
|
||||
properties:
|
||||
type:
|
||||
type: string
|
||||
enum:
|
||||
- manual_presence_change
|
||||
presence:
|
||||
type: string
|
||||
memberJoinedChannel:
|
||||
summary: A user joined a public or private channel.
|
||||
payload:
|
||||
type: object
|
||||
properties:
|
||||
type:
|
||||
type: string
|
||||
enum:
|
||||
- member_joined_channel
|
||||
user:
|
||||
type: string
|
||||
channel:
|
||||
type: string
|
||||
channel_type:
|
||||
type: string
|
||||
enum:
|
||||
- C
|
||||
- G
|
||||
team:
|
||||
type: string
|
||||
inviter:
|
||||
type: string
|
||||
memberLeftChannel:
|
||||
summary: A user left a public or private channel.
|
||||
payload:
|
||||
type: object
|
||||
properties:
|
||||
type:
|
||||
type: string
|
||||
enum:
|
||||
- member_left_channel
|
||||
user:
|
||||
type: string
|
||||
channel:
|
||||
type: string
|
||||
channel_type:
|
||||
type: string
|
||||
enum:
|
||||
- C
|
||||
- G
|
||||
team:
|
||||
type: string
|
||||
message:
|
||||
summary: A message was sent to a channel.
|
||||
payload:
|
||||
type: object
|
||||
properties:
|
||||
type:
|
||||
type: string
|
||||
enum:
|
||||
- message
|
||||
user:
|
||||
type: string
|
||||
channel:
|
||||
type: string
|
||||
text:
|
||||
type: string
|
||||
ts:
|
||||
type: string
|
||||
attachments:
|
||||
type: array
|
||||
items:
|
||||
$ref: '#/components/schemas/attachment'
|
||||
edited:
|
||||
type: object
|
||||
properties:
|
||||
user:
|
||||
type: string
|
||||
ts:
|
||||
type: string
|
||||
outgoingMessage:
|
||||
summary: A message was sent to a channel.
|
||||
payload:
|
||||
type: object
|
||||
properties:
|
||||
id:
|
||||
type: number
|
||||
type:
|
||||
type: string
|
||||
enum:
|
||||
- message
|
||||
channel:
|
||||
type: string
|
||||
text:
|
||||
type: string
|
||||
56
__tests__/lint/async3/snapshot.js
Normal file
56
__tests__/lint/async3/snapshot.js
Normal file
@@ -0,0 +1,56 @@
|
||||
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||
|
||||
exports[`E2E lint async3 1`] = `
|
||||
|
||||
validating /anyof.yml...
|
||||
/anyof.yml: validated in <test>ms
|
||||
|
||||
validating /application-headers.yml...
|
||||
/application-headers.yml: validated in <test>ms
|
||||
|
||||
validating /correlation-id.yml...
|
||||
/correlation-id.yml: validated in <test>ms
|
||||
|
||||
validating /gitter-streaming.yml...
|
||||
/gitter-streaming.yml: validated in <test>ms
|
||||
|
||||
validating /mercure.yml...
|
||||
/mercure.yml: validated in <test>ms
|
||||
|
||||
validating /not.yml...
|
||||
/not.yml: validated in <test>ms
|
||||
|
||||
validating /oneof.yml...
|
||||
/oneof.yml: validated in <test>ms
|
||||
|
||||
validating /operation-security.yml...
|
||||
/operation-security.yml: validated in <test>ms
|
||||
|
||||
validating /rpc-client.yml...
|
||||
/rpc-client.yml: validated in <test>ms
|
||||
|
||||
validating /rpc-server.yml...
|
||||
/rpc-server.yml: validated in <test>ms
|
||||
|
||||
validating /simple.yml...
|
||||
/simple.yml: validated in <test>ms
|
||||
|
||||
validating /slack-rtm.yml...
|
||||
/slack-rtm.yml: validated in <test>ms
|
||||
|
||||
validating /streetlights-kafka.yml...
|
||||
/streetlights-kafka.yml: validated in <test>ms
|
||||
|
||||
validating /streetlights-mqtt.yml...
|
||||
/streetlights-mqtt.yml: validated in <test>ms
|
||||
|
||||
validating /streetlights-operation-security.yml...
|
||||
/streetlights-operation-security.yml: validated in <test>ms
|
||||
|
||||
validating /websocket-gemini.yml...
|
||||
/websocket-gemini.yml: validated in <test>ms
|
||||
|
||||
Woohoo! Your API descriptions are valid. 🎉
|
||||
|
||||
|
||||
`;
|
||||
199
__tests__/lint/async3/streetlights-kafka.yml
Normal file
199
__tests__/lint/async3/streetlights-kafka.yml
Normal file
@@ -0,0 +1,199 @@
|
||||
asyncapi: 3.0.0
|
||||
info:
|
||||
title: Streetlights Kafka API
|
||||
version: 1.0.0
|
||||
description: "The Smartylighting Streetlights API allows you to remotely manage the city lights.\n\n### Check out its awesome features:\n\n* Turn a specific streetlight on/off \U0001F303\n* Dim a specific streetlight \U0001F60E\n* Receive real-time information about environmental lighting conditions \U0001F4C8\n"
|
||||
license:
|
||||
name: Apache 2.0
|
||||
url: 'https://www.apache.org/licenses/LICENSE-2.0'
|
||||
defaultContentType: application/json
|
||||
servers:
|
||||
scram-connections:
|
||||
host: 'test.mykafkacluster.org:18092'
|
||||
protocol: kafka-secure
|
||||
description: Test broker secured with scramSha256
|
||||
security:
|
||||
- $ref: '#/components/securitySchemes/saslScram'
|
||||
tags:
|
||||
- name: 'env:test-scram'
|
||||
description: >-
|
||||
This environment is meant for running internal tests through
|
||||
scramSha256
|
||||
- name: 'kind:remote'
|
||||
description: This server is a remote server. Not exposed by the application
|
||||
- name: 'visibility:private'
|
||||
description: This resource is private and only available to certain users
|
||||
mtls-connections:
|
||||
host: 'test.mykafkacluster.org:28092'
|
||||
protocol: kafka-secure
|
||||
description: Test broker secured with X509
|
||||
security:
|
||||
- $ref: '#/components/securitySchemes/certs'
|
||||
tags:
|
||||
- name: 'env:test-mtls'
|
||||
description: This environment is meant for running internal tests through mtls
|
||||
- name: 'kind:remote'
|
||||
description: This server is a remote server. Not exposed by the application
|
||||
- name: 'visibility:private'
|
||||
description: This resource is private and only available to certain users
|
||||
channels:
|
||||
lightingMeasured:
|
||||
address: 'smartylighting.streetlights.1.0.event.{streetlightId}.lighting.measured'
|
||||
messages:
|
||||
lightMeasured:
|
||||
$ref: '#/components/messages/lightMeasured'
|
||||
description: The topic on which measured values may be produced and consumed.
|
||||
parameters:
|
||||
streetlightId:
|
||||
$ref: '#/components/parameters/streetlightId'
|
||||
lightTurnOn:
|
||||
address: 'smartylighting.streetlights.1.0.action.{streetlightId}.turn.on'
|
||||
messages:
|
||||
turnOn:
|
||||
$ref: '#/components/messages/turnOnOff'
|
||||
parameters:
|
||||
streetlightId:
|
||||
$ref: '#/components/parameters/streetlightId'
|
||||
lightTurnOff:
|
||||
address: 'smartylighting.streetlights.1.0.action.{streetlightId}.turn.off'
|
||||
messages:
|
||||
turnOff:
|
||||
$ref: '#/components/messages/turnOnOff'
|
||||
parameters:
|
||||
streetlightId:
|
||||
$ref: '#/components/parameters/streetlightId'
|
||||
lightsDim:
|
||||
address: 'smartylighting.streetlights.1.0.action.{streetlightId}.dim'
|
||||
messages:
|
||||
dimLight:
|
||||
$ref: '#/components/messages/dimLight'
|
||||
parameters:
|
||||
streetlightId:
|
||||
$ref: '#/components/parameters/streetlightId'
|
||||
operations:
|
||||
receiveLightMeasurement:
|
||||
action: receive
|
||||
channel:
|
||||
$ref: '#/channels/lightingMeasured'
|
||||
summary: >-
|
||||
Inform about environmental lighting conditions of a particular
|
||||
streetlight.
|
||||
traits:
|
||||
- $ref: '#/components/operationTraits/kafka'
|
||||
messages:
|
||||
- $ref: '#/channels/lightingMeasured/messages/lightMeasured'
|
||||
turnOn:
|
||||
action: send
|
||||
channel:
|
||||
$ref: '#/channels/lightTurnOn'
|
||||
traits:
|
||||
- $ref: '#/components/operationTraits/kafka'
|
||||
messages:
|
||||
- $ref: '#/channels/lightTurnOn/messages/turnOn'
|
||||
turnOff:
|
||||
action: send
|
||||
channel:
|
||||
$ref: '#/channels/lightTurnOff'
|
||||
traits:
|
||||
- $ref: '#/components/operationTraits/kafka'
|
||||
messages:
|
||||
- $ref: '#/channels/lightTurnOff/messages/turnOff'
|
||||
dimLight:
|
||||
action: send
|
||||
channel:
|
||||
$ref: '#/channels/lightsDim'
|
||||
traits:
|
||||
- $ref: '#/components/operationTraits/kafka'
|
||||
messages:
|
||||
- $ref: '#/channels/lightsDim/messages/dimLight'
|
||||
components:
|
||||
messages:
|
||||
lightMeasured:
|
||||
name: lightMeasured
|
||||
title: Light measured
|
||||
summary: >-
|
||||
Inform about environmental lighting conditions of a particular
|
||||
streetlight.
|
||||
contentType: application/json
|
||||
traits:
|
||||
- $ref: '#/components/messageTraits/commonHeaders'
|
||||
payload:
|
||||
$ref: '#/components/schemas/lightMeasuredPayload'
|
||||
turnOnOff:
|
||||
name: turnOnOff
|
||||
title: Turn on/off
|
||||
summary: Command a particular streetlight to turn the lights on or off.
|
||||
traits:
|
||||
- $ref: '#/components/messageTraits/commonHeaders'
|
||||
payload:
|
||||
$ref: '#/components/schemas/turnOnOffPayload'
|
||||
dimLight:
|
||||
name: dimLight
|
||||
title: Dim light
|
||||
summary: Command a particular streetlight to dim the lights.
|
||||
traits:
|
||||
- $ref: '#/components/messageTraits/commonHeaders'
|
||||
payload:
|
||||
$ref: '#/components/schemas/dimLightPayload'
|
||||
schemas:
|
||||
lightMeasuredPayload:
|
||||
type: object
|
||||
properties:
|
||||
lumens:
|
||||
type: integer
|
||||
minimum: 0
|
||||
description: Light intensity measured in lumens.
|
||||
sentAt:
|
||||
$ref: '#/components/schemas/sentAt'
|
||||
turnOnOffPayload:
|
||||
type: object
|
||||
properties:
|
||||
command:
|
||||
type: string
|
||||
enum:
|
||||
- 'on'
|
||||
- 'off'
|
||||
description: Whether to turn on or off the light.
|
||||
sentAt:
|
||||
$ref: '#/components/schemas/sentAt'
|
||||
dimLightPayload:
|
||||
type: object
|
||||
properties:
|
||||
percentage:
|
||||
type: integer
|
||||
description: Percentage to which the light should be dimmed to.
|
||||
minimum: 0
|
||||
maximum: 100
|
||||
sentAt:
|
||||
$ref: '#/components/schemas/sentAt'
|
||||
sentAt:
|
||||
type: string
|
||||
format: date-time
|
||||
description: Date and time when the message was sent.
|
||||
securitySchemes:
|
||||
saslScram:
|
||||
type: scramSha256
|
||||
description: Provide your username and password for SASL/SCRAM authentication
|
||||
certs:
|
||||
type: X509
|
||||
description: Download the certificate files from service provider
|
||||
parameters:
|
||||
streetlightId:
|
||||
description: The ID of the streetlight.
|
||||
messageTraits:
|
||||
commonHeaders:
|
||||
headers:
|
||||
type: object
|
||||
properties:
|
||||
my-app-header:
|
||||
type: integer
|
||||
minimum: 0
|
||||
maximum: 100
|
||||
operationTraits:
|
||||
kafka:
|
||||
bindings:
|
||||
kafka:
|
||||
clientId:
|
||||
type: string
|
||||
enum:
|
||||
- my-app-id
|
||||
253
__tests__/lint/async3/streetlights-mqtt.yml
Normal file
253
__tests__/lint/async3/streetlights-mqtt.yml
Normal file
@@ -0,0 +1,253 @@
|
||||
asyncapi: 3.0.0
|
||||
info:
|
||||
title: Streetlights MQTT API
|
||||
version: 1.0.0
|
||||
description: "The Smartylighting Streetlights API allows you to remotely manage the city lights.\n\n### Check out its awesome features:\n\n* Turn a specific streetlight on/off \U0001F303\n* Dim a specific streetlight \U0001F60E\n* Receive real-time information about environmental lighting conditions \U0001F4C8\n"
|
||||
license:
|
||||
name: Apache 2.0
|
||||
url: 'https://www.apache.org/licenses/LICENSE-2.0'
|
||||
defaultContentType: application/json
|
||||
servers:
|
||||
production:
|
||||
host: 'test.mosquitto.org:{port}'
|
||||
protocol: mqtt
|
||||
description: Test broker
|
||||
variables:
|
||||
port:
|
||||
description: Secure connection (TLS) is available through port 8883.
|
||||
default: '1883'
|
||||
enum:
|
||||
- '1883'
|
||||
- '8883'
|
||||
security:
|
||||
- $ref: '#/components/securitySchemes/apiKey'
|
||||
- type: oauth2
|
||||
description: Flows to support OAuth 2.0
|
||||
flows:
|
||||
implicit:
|
||||
authorizationUrl: 'https://authserver.example/auth'
|
||||
availableScopes:
|
||||
'streetlights:on': Ability to switch lights on
|
||||
'streetlights:off': Ability to switch lights off
|
||||
'streetlights:dim': Ability to dim the lights
|
||||
password:
|
||||
tokenUrl: 'https://authserver.example/token'
|
||||
availableScopes:
|
||||
'streetlights:on': Ability to switch lights on
|
||||
'streetlights:off': Ability to switch lights off
|
||||
'streetlights:dim': Ability to dim the lights
|
||||
clientCredentials:
|
||||
tokenUrl: 'https://authserver.example/token'
|
||||
availableScopes:
|
||||
'streetlights:on': Ability to switch lights on
|
||||
'streetlights:off': Ability to switch lights off
|
||||
'streetlights:dim': Ability to dim the lights
|
||||
authorizationCode:
|
||||
authorizationUrl: 'https://authserver.example/auth'
|
||||
tokenUrl: 'https://authserver.example/token'
|
||||
refreshUrl: 'https://authserver.example/refresh'
|
||||
availableScopes:
|
||||
'streetlights:on': Ability to switch lights on
|
||||
'streetlights:off': Ability to switch lights off
|
||||
'streetlights:dim': Ability to dim the lights
|
||||
scopes:
|
||||
- 'streetlights:on'
|
||||
- 'streetlights:off'
|
||||
- 'streetlights:dim'
|
||||
- $ref: '#/components/securitySchemes/openIdConnectWellKnown'
|
||||
tags:
|
||||
- name: 'env:production'
|
||||
description: This environment is meant for production use case
|
||||
- name: 'kind:remote'
|
||||
description: This server is a remote server. Not exposed by the application
|
||||
- name: 'visibility:public'
|
||||
description: This resource is public and available to everyone
|
||||
channels:
|
||||
lightingMeasured:
|
||||
address: 'smartylighting/streetlights/1/0/event/{streetlightId}/lighting/measured'
|
||||
messages:
|
||||
lightMeasured:
|
||||
$ref: '#/components/messages/lightMeasured'
|
||||
description: The topic on which measured values may be produced and consumed.
|
||||
parameters:
|
||||
streetlightId:
|
||||
$ref: '#/components/parameters/streetlightId'
|
||||
lightTurnOn:
|
||||
address: 'smartylighting/streetlights/1/0/action/{streetlightId}/turn/on'
|
||||
messages:
|
||||
turnOn:
|
||||
$ref: '#/components/messages/turnOnOff'
|
||||
parameters:
|
||||
streetlightId:
|
||||
$ref: '#/components/parameters/streetlightId'
|
||||
lightTurnOff:
|
||||
address: 'smartylighting/streetlights/1/0/action/{streetlightId}/turn/off'
|
||||
messages:
|
||||
turnOff:
|
||||
$ref: '#/components/messages/turnOnOff'
|
||||
parameters:
|
||||
streetlightId:
|
||||
$ref: '#/components/parameters/streetlightId'
|
||||
lightsDim:
|
||||
address: 'smartylighting/streetlights/1/0/action/{streetlightId}/dim'
|
||||
messages:
|
||||
dimLight:
|
||||
$ref: '#/components/messages/dimLight'
|
||||
parameters:
|
||||
streetlightId:
|
||||
$ref: '#/components/parameters/streetlightId'
|
||||
operations:
|
||||
receiveLightMeasurement:
|
||||
action: receive
|
||||
channel:
|
||||
$ref: '#/channels/lightingMeasured'
|
||||
summary: >-
|
||||
Inform about environmental lighting conditions of a particular
|
||||
streetlight.
|
||||
traits:
|
||||
- $ref: '#/components/operationTraits/mqtt'
|
||||
messages:
|
||||
- $ref: '#/channels/lightingMeasured/messages/lightMeasured'
|
||||
turnOn:
|
||||
action: send
|
||||
channel:
|
||||
$ref: '#/channels/lightTurnOn'
|
||||
traits:
|
||||
- $ref: '#/components/operationTraits/mqtt'
|
||||
messages:
|
||||
- $ref: '#/channels/lightTurnOn/messages/turnOn'
|
||||
turnOff:
|
||||
action: send
|
||||
channel:
|
||||
$ref: '#/channels/lightTurnOff'
|
||||
traits:
|
||||
- $ref: '#/components/operationTraits/mqtt'
|
||||
messages:
|
||||
- $ref: '#/channels/lightTurnOff/messages/turnOff'
|
||||
dimLight:
|
||||
action: send
|
||||
channel:
|
||||
$ref: '#/channels/lightsDim'
|
||||
traits:
|
||||
- $ref: '#/components/operationTraits/mqtt'
|
||||
messages:
|
||||
- $ref: '#/channels/lightsDim/messages/dimLight'
|
||||
components:
|
||||
messages:
|
||||
lightMeasured:
|
||||
name: lightMeasured
|
||||
title: Light measured
|
||||
summary: >-
|
||||
Inform about environmental lighting conditions of a particular
|
||||
streetlight.
|
||||
contentType: application/json
|
||||
traits:
|
||||
- $ref: '#/components/messageTraits/commonHeaders'
|
||||
payload:
|
||||
$ref: '#/components/schemas/lightMeasuredPayload'
|
||||
turnOnOff:
|
||||
name: turnOnOff
|
||||
title: Turn on/off
|
||||
summary: Command a particular streetlight to turn the lights on or off.
|
||||
traits:
|
||||
- $ref: '#/components/messageTraits/commonHeaders'
|
||||
payload:
|
||||
$ref: '#/components/schemas/turnOnOffPayload'
|
||||
dimLight:
|
||||
name: dimLight
|
||||
title: Dim light
|
||||
summary: Command a particular streetlight to dim the lights.
|
||||
traits:
|
||||
- $ref: '#/components/messageTraits/commonHeaders'
|
||||
payload:
|
||||
$ref: '#/components/schemas/dimLightPayload'
|
||||
schemas:
|
||||
lightMeasuredPayload:
|
||||
type: object
|
||||
properties:
|
||||
lumens:
|
||||
type: integer
|
||||
minimum: 0
|
||||
description: Light intensity measured in lumens.
|
||||
sentAt:
|
||||
$ref: '#/components/schemas/sentAt'
|
||||
turnOnOffPayload:
|
||||
type: object
|
||||
properties:
|
||||
command:
|
||||
type: string
|
||||
enum:
|
||||
- 'on'
|
||||
- 'off'
|
||||
description: Whether to turn on or off the light.
|
||||
sentAt:
|
||||
$ref: '#/components/schemas/sentAt'
|
||||
dimLightPayload:
|
||||
type: object
|
||||
properties:
|
||||
percentage:
|
||||
type: integer
|
||||
description: Percentage to which the light should be dimmed to.
|
||||
minimum: 0
|
||||
maximum: 100
|
||||
sentAt:
|
||||
$ref: '#/components/schemas/sentAt'
|
||||
sentAt:
|
||||
type: string
|
||||
format: date-time
|
||||
description: Date and time when the message was sent.
|
||||
securitySchemes:
|
||||
apiKey:
|
||||
type: apiKey
|
||||
in: user
|
||||
description: Provide your API key as the user and leave the password empty.
|
||||
supportedOauthFlows:
|
||||
type: oauth2
|
||||
description: Flows to support OAuth 2.0
|
||||
flows:
|
||||
implicit:
|
||||
authorizationUrl: 'https://authserver.example/auth'
|
||||
availableScopes:
|
||||
'streetlights:on': Ability to switch lights on
|
||||
'streetlights:off': Ability to switch lights off
|
||||
'streetlights:dim': Ability to dim the lights
|
||||
password:
|
||||
tokenUrl: 'https://authserver.example/token'
|
||||
availableScopes:
|
||||
'streetlights:on': Ability to switch lights on
|
||||
'streetlights:off': Ability to switch lights off
|
||||
'streetlights:dim': Ability to dim the lights
|
||||
clientCredentials:
|
||||
tokenUrl: 'https://authserver.example/token'
|
||||
availableScopes:
|
||||
'streetlights:on': Ability to switch lights on
|
||||
'streetlights:off': Ability to switch lights off
|
||||
'streetlights:dim': Ability to dim the lights
|
||||
authorizationCode:
|
||||
authorizationUrl: 'https://authserver.example/auth'
|
||||
tokenUrl: 'https://authserver.example/token'
|
||||
refreshUrl: 'https://authserver.example/refresh'
|
||||
availableScopes:
|
||||
'streetlights:on': Ability to switch lights on
|
||||
'streetlights:off': Ability to switch lights off
|
||||
'streetlights:dim': Ability to dim the lights
|
||||
openIdConnectWellKnown:
|
||||
type: openIdConnect
|
||||
openIdConnectUrl: 'https://authserver.example/.well-known'
|
||||
parameters:
|
||||
streetlightId:
|
||||
description: The ID of the streetlight.
|
||||
messageTraits:
|
||||
commonHeaders:
|
||||
headers:
|
||||
type: object
|
||||
properties:
|
||||
my-app-header:
|
||||
type: integer
|
||||
minimum: 0
|
||||
maximum: 100
|
||||
operationTraits:
|
||||
mqtt:
|
||||
bindings:
|
||||
mqtt:
|
||||
qos: 1
|
||||
240
__tests__/lint/async3/streetlights-operation-security.yml
Normal file
240
__tests__/lint/async3/streetlights-operation-security.yml
Normal file
@@ -0,0 +1,240 @@
|
||||
asyncapi: 3.0.0
|
||||
info:
|
||||
title: Streetlights Kafka API
|
||||
version: 1.0.0
|
||||
description: "The Smartylighting Streetlights API allows you to remotely manage the city lights.\n\n### Check out its awesome features:\n\n* Turn a specific streetlight on/off \U0001F303\n* Dim a specific streetlight \U0001F60E\n* Receive real-time information about environmental lighting conditions \U0001F4C8\n"
|
||||
license:
|
||||
name: Apache 2.0
|
||||
url: 'https://www.apache.org/licenses/LICENSE-2.0'
|
||||
defaultContentType: application/json
|
||||
servers:
|
||||
test:
|
||||
host: 'test.mykafkacluster.org:8092'
|
||||
protocol: kafka-secure
|
||||
description: Test broker
|
||||
security:
|
||||
- $ref: '#/components/securitySchemes/saslScram'
|
||||
test_oauth:
|
||||
host: 'test.mykafkacluster.org:8093'
|
||||
protocol: kafka-secure
|
||||
description: Test port for oauth
|
||||
security:
|
||||
- type: oauth2
|
||||
description: The oauth security descriptions
|
||||
flows:
|
||||
clientCredentials:
|
||||
tokenUrl: 'https://example.com/api/oauth/dialog'
|
||||
availableScopes:
|
||||
'streetlights:read': Scope required for subscribing to channel
|
||||
'streetlights:write': Scope required for publishing to channel
|
||||
scopes:
|
||||
- 'streetlights:write'
|
||||
- 'streetlights:read'
|
||||
channels:
|
||||
lightingMeasured:
|
||||
address: 'smartylighting.streetlights.1.0.event.{streetlightId}.lighting.measured'
|
||||
messages:
|
||||
lightMeasured:
|
||||
$ref: '#/components/messages/lightMeasured'
|
||||
description: The topic on which measured values may be produced and consumed.
|
||||
servers:
|
||||
- $ref: '#/servers/test'
|
||||
parameters:
|
||||
streetlightId:
|
||||
$ref: '#/components/parameters/streetlightId'
|
||||
lightTurnOn:
|
||||
address: 'smartylighting.streetlights.1.0.action.{streetlightId}.turn.on'
|
||||
messages:
|
||||
turnOn:
|
||||
$ref: '#/components/messages/turnOnOff'
|
||||
servers:
|
||||
- $ref: '#/servers/test_oauth'
|
||||
parameters:
|
||||
streetlightId:
|
||||
$ref: '#/components/parameters/streetlightId'
|
||||
lightTurnOff:
|
||||
address: 'smartylighting.streetlights.1.0.action.{streetlightId}.turn.off'
|
||||
messages:
|
||||
turnOff:
|
||||
$ref: '#/components/messages/turnOnOff'
|
||||
servers:
|
||||
- $ref: '#/servers/test_oauth'
|
||||
parameters:
|
||||
streetlightId:
|
||||
$ref: '#/components/parameters/streetlightId'
|
||||
lightsDim:
|
||||
address: 'smartylighting.streetlights.1.0.action.{streetlightId}.dim'
|
||||
messages:
|
||||
dimLight:
|
||||
$ref: '#/components/messages/dimLight'
|
||||
servers:
|
||||
- $ref: '#/servers/test_oauth'
|
||||
parameters:
|
||||
streetlightId:
|
||||
$ref: '#/components/parameters/streetlightId'
|
||||
operations:
|
||||
receiveLightMeasurement:
|
||||
action: receive
|
||||
channel:
|
||||
$ref: '#/channels/lightingMeasured'
|
||||
summary: >-
|
||||
Inform about environmental lighting conditions of a particular
|
||||
streetlight.
|
||||
traits:
|
||||
- $ref: '#/components/operationTraits/kafka'
|
||||
messages:
|
||||
- $ref: '#/channels/lightingMeasured/messages/lightMeasured'
|
||||
turnOn:
|
||||
action: send
|
||||
channel:
|
||||
$ref: '#/channels/lightTurnOn'
|
||||
security:
|
||||
- type: oauth2
|
||||
description: The oauth security descriptions
|
||||
flows:
|
||||
clientCredentials:
|
||||
tokenUrl: 'https://example.com/api/oauth/dialog'
|
||||
availableScopes:
|
||||
'streetlights:read': Scope required for subscribing to channel
|
||||
'streetlights:write': Scope required for publishing to channel
|
||||
scopes:
|
||||
- 'streetlights:read'
|
||||
traits:
|
||||
- $ref: '#/components/operationTraits/kafka'
|
||||
messages:
|
||||
- $ref: '#/channels/lightTurnOn/messages/turnOn'
|
||||
turnOff:
|
||||
action: send
|
||||
channel:
|
||||
$ref: '#/channels/lightTurnOff'
|
||||
security:
|
||||
- type: oauth2
|
||||
description: The oauth security descriptions
|
||||
flows:
|
||||
clientCredentials:
|
||||
tokenUrl: 'https://example.com/api/oauth/dialog'
|
||||
availableScopes:
|
||||
'streetlights:read': Scope required for subscribing to channel
|
||||
'streetlights:write': Scope required for publishing to channel
|
||||
scopes:
|
||||
- 'streetlights:read'
|
||||
traits:
|
||||
- $ref: '#/components/operationTraits/kafka'
|
||||
messages:
|
||||
- $ref: '#/channels/lightTurnOff/messages/turnOff'
|
||||
dimLight:
|
||||
action: send
|
||||
channel:
|
||||
$ref: '#/channels/lightsDim'
|
||||
security:
|
||||
- type: oauth2
|
||||
description: The oauth security descriptions
|
||||
flows:
|
||||
clientCredentials:
|
||||
tokenUrl: 'https://example.com/api/oauth/dialog'
|
||||
availableScopes:
|
||||
'streetlights:read': Scope required for subscribing to channel
|
||||
'streetlights:write': Scope required for publishing to channel
|
||||
scopes:
|
||||
- 'streetlights:read'
|
||||
traits:
|
||||
- $ref: '#/components/operationTraits/kafka'
|
||||
messages:
|
||||
- $ref: '#/channels/lightsDim/messages/dimLight'
|
||||
components:
|
||||
messages:
|
||||
lightMeasured:
|
||||
name: lightMeasured
|
||||
title: Light measured
|
||||
summary: >-
|
||||
Inform about environmental lighting conditions of a particular
|
||||
streetlight.
|
||||
contentType: application/json
|
||||
traits:
|
||||
- $ref: '#/components/messageTraits/commonHeaders'
|
||||
payload:
|
||||
$ref: '#/components/schemas/lightMeasuredPayload'
|
||||
turnOnOff:
|
||||
name: turnOnOff
|
||||
title: Turn on/off
|
||||
summary: Command a particular streetlight to turn the lights on or off.
|
||||
traits:
|
||||
- $ref: '#/components/messageTraits/commonHeaders'
|
||||
payload:
|
||||
$ref: '#/components/schemas/turnOnOffPayload'
|
||||
dimLight:
|
||||
name: dimLight
|
||||
title: Dim light
|
||||
summary: Command a particular streetlight to dim the lights.
|
||||
traits:
|
||||
- $ref: '#/components/messageTraits/commonHeaders'
|
||||
payload:
|
||||
$ref: '#/components/schemas/dimLightPayload'
|
||||
schemas:
|
||||
lightMeasuredPayload:
|
||||
type: object
|
||||
properties:
|
||||
lumens:
|
||||
type: integer
|
||||
minimum: 0
|
||||
description: Light intensity measured in lumens.
|
||||
sentAt:
|
||||
$ref: '#/components/schemas/sentAt'
|
||||
turnOnOffPayload:
|
||||
type: object
|
||||
properties:
|
||||
command:
|
||||
type: string
|
||||
enum:
|
||||
- 'on'
|
||||
- 'off'
|
||||
description: Whether to turn on or off the light.
|
||||
sentAt:
|
||||
$ref: '#/components/schemas/sentAt'
|
||||
dimLightPayload:
|
||||
type: object
|
||||
properties:
|
||||
percentage:
|
||||
type: integer
|
||||
description: Percentage to which the light should be dimmed to.
|
||||
minimum: 0
|
||||
maximum: 100
|
||||
sentAt:
|
||||
$ref: '#/components/schemas/sentAt'
|
||||
sentAt:
|
||||
type: string
|
||||
format: date-time
|
||||
description: Date and time when the message was sent.
|
||||
securitySchemes:
|
||||
saslScram:
|
||||
type: scramSha256
|
||||
description: Provide your username and password for SASL/SCRAM authentication
|
||||
streetlights_auth:
|
||||
type: oauth2
|
||||
description: The oauth security descriptions
|
||||
flows:
|
||||
clientCredentials:
|
||||
tokenUrl: 'https://example.com/api/oauth/dialog'
|
||||
availableScopes:
|
||||
'streetlights:read': Scope required for subscribing to channel
|
||||
'streetlights:write': Scope required for publishing to channel
|
||||
parameters:
|
||||
streetlightId:
|
||||
description: The ID of the streetlight.
|
||||
messageTraits:
|
||||
commonHeaders:
|
||||
headers:
|
||||
type: object
|
||||
properties:
|
||||
my-app-header:
|
||||
type: integer
|
||||
minimum: 0
|
||||
maximum: 100
|
||||
operationTraits:
|
||||
kafka:
|
||||
bindings:
|
||||
kafka:
|
||||
clientId:
|
||||
type: string
|
||||
enum:
|
||||
- my-app-id
|
||||
301
__tests__/lint/async3/websocket-gemini.yml
Normal file
301
__tests__/lint/async3/websocket-gemini.yml
Normal file
@@ -0,0 +1,301 @@
|
||||
asyncapi: 3.0.0
|
||||
info:
|
||||
title: Gemini Market Data Websocket API
|
||||
version: 1.0.0
|
||||
description: >
|
||||
Market data is a public API that streams all the market data on a given
|
||||
symbol.
|
||||
|
||||
|
||||
You can quickly play with the API using
|
||||
[websocat](https://github.com/vi/websocat#installation) like this:
|
||||
|
||||
```bash
|
||||
|
||||
websocat wss://api.gemini.com/v1/marketdata/btcusd?heartbeat=true -S
|
||||
|
||||
```
|
||||
contact:
|
||||
name: Gemini
|
||||
url: 'https://www.gemini.com/'
|
||||
externalDocs:
|
||||
url: 'https://docs.sandbox.gemini.com/websocket-api/#market-data'
|
||||
servers:
|
||||
public:
|
||||
host: api.gemini.com
|
||||
protocol: wss
|
||||
channels:
|
||||
marketDataV1:
|
||||
address: '/v1/marketdata/{symbol}'
|
||||
messages:
|
||||
marketData:
|
||||
$ref: '#/components/messages/marketData'
|
||||
parameters:
|
||||
symbol:
|
||||
enum:
|
||||
- btcusd
|
||||
- ethbtc
|
||||
- ethusd
|
||||
- zecusd
|
||||
- zecbtc
|
||||
- zeceth
|
||||
- zecbch
|
||||
- zecltc
|
||||
- bchusd
|
||||
- bchbtc
|
||||
- bcheth
|
||||
- ltcusd
|
||||
- ltcbtc
|
||||
- ltceth
|
||||
- ltcbch
|
||||
- batusd
|
||||
- daiusd
|
||||
- linkusd
|
||||
- oxtusd
|
||||
- batbtc
|
||||
- linkbtc
|
||||
- oxtbtc
|
||||
- bateth
|
||||
- linketh
|
||||
- oxteth
|
||||
- ampusd
|
||||
- compusd
|
||||
- paxgusd
|
||||
- mkrusd
|
||||
- zrxusd
|
||||
- kncusd
|
||||
- manausd
|
||||
- storjusd
|
||||
- snxusd
|
||||
- crvusd
|
||||
- balusd
|
||||
- uniusd
|
||||
- renusd
|
||||
- umausd
|
||||
- yfiusd
|
||||
- btcdai
|
||||
- ethdai
|
||||
- aaveusd
|
||||
- filusd
|
||||
- btceur
|
||||
- btcgbp
|
||||
- etheur
|
||||
- ethgbp
|
||||
- btcsgd
|
||||
- ethsgd
|
||||
- sklusd
|
||||
- grtusd
|
||||
- bntusd
|
||||
- 1inchusd
|
||||
- enjusd
|
||||
- lrcusd
|
||||
- sandusd
|
||||
- cubeusd
|
||||
- lptusd
|
||||
- bondusd
|
||||
- maticusd
|
||||
- injusd
|
||||
- sushiusd
|
||||
description: >
|
||||
Symbols are formatted as CCY1CCY2 where prices are in CCY2 and
|
||||
quantities are in CCY1. To read more click
|
||||
[here](https://docs.sandbox.gemini.com/websocket-api/#symbols-and-minimums).
|
||||
bindings:
|
||||
ws:
|
||||
bindingVersion: 0.1.0
|
||||
query:
|
||||
type: object
|
||||
description: >
|
||||
The semantics of entry type filtering is:
|
||||
|
||||
|
||||
If any entry type is specified as true or false, all of them must be
|
||||
explicitly flagged true to show up in the response
|
||||
|
||||
If no entry types filtering parameters are included in the url, then
|
||||
all entry types will appear in the response
|
||||
|
||||
|
||||
NOTE: top_of_book has no meaning and initial book events are empty
|
||||
when only trades is specified
|
||||
properties:
|
||||
heartbeat:
|
||||
type: boolean
|
||||
default: false
|
||||
description: >-
|
||||
Optionally add this parameter and set to true to receive a
|
||||
heartbeat every 5 seconds
|
||||
top_of_book:
|
||||
type: boolean
|
||||
default: false
|
||||
description: >-
|
||||
If absent or false, receive full order book depth; if present
|
||||
and true, receive top of book only. Only applies to bids and
|
||||
offers.
|
||||
bids:
|
||||
type: boolean
|
||||
default: true
|
||||
description: Include bids in change events
|
||||
offers:
|
||||
type: boolean
|
||||
default: true
|
||||
description: Include asks in change events
|
||||
trades:
|
||||
type: boolean
|
||||
default: true
|
||||
description: Include trade events
|
||||
auctions:
|
||||
type: boolean
|
||||
default: true
|
||||
description: Include auction events
|
||||
operations:
|
||||
sendMarketData:
|
||||
action: send
|
||||
channel:
|
||||
$ref: '#/channels/marketDataV1'
|
||||
summary: Receive market updates on a given symbol
|
||||
messages:
|
||||
- $ref: '#/channels/marketDataV1/messages/marketData'
|
||||
components:
|
||||
messages:
|
||||
marketData:
|
||||
summary: Message with marked data information.
|
||||
description: >
|
||||
The initial response message will show the existing state of the order
|
||||
book. Subsequent messages will show all executed trades, as well as all
|
||||
other changes to the order book from orders placed or canceled.
|
||||
payload:
|
||||
$ref: '#/components/schemas/market'
|
||||
examples:
|
||||
- name: updateMessage
|
||||
summary: >-
|
||||
Example of an update message that contains a change in price
|
||||
information.
|
||||
payload:
|
||||
type: update
|
||||
eventId: 36902233362
|
||||
timestamp: 1619769673
|
||||
timestampms: 1619769673527
|
||||
socket_sequence: 661
|
||||
events:
|
||||
- type: change
|
||||
side: bid
|
||||
price: 54350.40
|
||||
remaining: 0.002
|
||||
delta: 0.002
|
||||
reason: place
|
||||
- name: heartbeatMessage
|
||||
summary: Example of additional heartbeat message when you enable them.
|
||||
payload:
|
||||
type: heartbeat
|
||||
socket_sequence: 1656
|
||||
schemas:
|
||||
market:
|
||||
type: object
|
||||
oneOf:
|
||||
- $ref: '#/components/schemas/heartbeat'
|
||||
- $ref: '#/components/schemas/update'
|
||||
heartbeat:
|
||||
allOf:
|
||||
- properties:
|
||||
type:
|
||||
type: string
|
||||
const: heartbeat
|
||||
required:
|
||||
- type
|
||||
- $ref: '#/components/schemas/default'
|
||||
update:
|
||||
allOf:
|
||||
- properties:
|
||||
type:
|
||||
type: string
|
||||
const: update
|
||||
eventId:
|
||||
type: integer
|
||||
description: >-
|
||||
A monotonically increasing sequence number indicating when this
|
||||
change occurred. These numbers are persistent and consistent
|
||||
between market data connections.
|
||||
events:
|
||||
$ref: '#/components/schemas/events'
|
||||
timestamp:
|
||||
type: number
|
||||
description: >-
|
||||
The timestamp in seconds for this group of events (included for
|
||||
compatibility reasons). We recommend using the timestampms field
|
||||
instead.
|
||||
timestampms:
|
||||
type: number
|
||||
description: The timestamp in milliseconds for this group of events.
|
||||
required:
|
||||
- type
|
||||
- eventId
|
||||
- events
|
||||
- timestamp
|
||||
- timestampms
|
||||
- $ref: '#/components/schemas/default'
|
||||
default:
|
||||
type: object
|
||||
description: >-
|
||||
This object is always part of the payload. In case of type=heartbeat,
|
||||
these are the only fields.
|
||||
required:
|
||||
- type
|
||||
- socket_sequence
|
||||
properties:
|
||||
socket_sequence:
|
||||
type: integer
|
||||
description: >-
|
||||
zero-indexed monotonic increasing sequence number attached to each
|
||||
message sent - if there is a gap in this sequence, you have missed a
|
||||
message. If you choose to enable heartbeats, then heartbeat and
|
||||
update messages will share a single increasing sequence. See
|
||||
[Sequence
|
||||
Numbers](https://docs.sandbox.gemini.com/websocket-api/#sequence-numbers)
|
||||
for more information.
|
||||
events:
|
||||
type: array
|
||||
description: >-
|
||||
Either a change to the order book, or the indication that a trade has
|
||||
occurred.
|
||||
items:
|
||||
type: object
|
||||
additionalProperties: false
|
||||
properties:
|
||||
type:
|
||||
type: string
|
||||
enum:
|
||||
- trade
|
||||
- change
|
||||
- 'auction, block_trade'
|
||||
price:
|
||||
type: number
|
||||
multipleOf: 0.01
|
||||
description: The price of this order book entry.
|
||||
side:
|
||||
type: string
|
||||
enum:
|
||||
- bid
|
||||
- side
|
||||
reason:
|
||||
type: string
|
||||
enum:
|
||||
- place
|
||||
- trade
|
||||
- cancel
|
||||
- initial
|
||||
description: >-
|
||||
Indicates why the change has occurred. initial is for the initial
|
||||
response message, which will show the entire existing state of the
|
||||
order book.
|
||||
remaining:
|
||||
type: number
|
||||
description: >-
|
||||
The quantity remaining at that price level after this change
|
||||
occurred. May be zero if all orders at this price level have been
|
||||
filled or canceled.
|
||||
delta:
|
||||
type: number
|
||||
description: >-
|
||||
The quantity changed. May be negative, if an order is filled or
|
||||
canceled. For initial messages, delta will equal remaining.
|
||||
@@ -15,6 +15,7 @@ Redocly CLI supports the following linting approaches with AsyncAPI documents:
|
||||
|
||||
- AsyncAPI document validation, including full binding validation for [supported protocols](#supported-protocols).
|
||||
- Supported versions:
|
||||
- [AsyncAPI 3.0](https://www.asyncapi.com/docs/reference/specification/v3.0.0)
|
||||
- [AsyncAPI 2.6](https://v2.asyncapi.com/docs/reference/specification/v2.6.0)
|
||||
- earlier versions in the 2.x family may also validate successfully
|
||||
- Built-in rules for checking common standards requirements (see the [list of AsyncAPI rules](#asyncapi-rules)).
|
||||
|
||||
@@ -73,6 +73,7 @@ export enum SpecVersion {
|
||||
OAS3_0 = 'oas3_0',
|
||||
OAS3_1 = 'oas3_1',
|
||||
Async2 = 'async2',
|
||||
Async3 = 'async3',
|
||||
}
|
||||
|
||||
export enum Oas3Operations {
|
||||
|
||||
@@ -474,6 +474,7 @@ describe('checkIfRulesetExist', () => {
|
||||
oas3_0: {},
|
||||
oas3_1: {},
|
||||
async2: {},
|
||||
async3: {},
|
||||
arazzo: {},
|
||||
};
|
||||
expect(() => checkIfRulesetExist(rules)).toThrowError(
|
||||
|
||||
@@ -522,6 +522,7 @@ export function checkIfRulesetExist(rules: typeof StyleguideConfig.prototype.rul
|
||||
...rules.oas3_0,
|
||||
...rules.oas3_1,
|
||||
...rules.async2,
|
||||
...rules.async3,
|
||||
...rules.arazzo,
|
||||
};
|
||||
|
||||
|
||||
@@ -274,3 +274,145 @@ describe('bundleFromString', () => {
|
||||
expect(rest.source.body).toEqual(stringDocument);
|
||||
});
|
||||
});
|
||||
|
||||
describe('bundle async', () => {
|
||||
it('should bundle async of version 2.x', async () => {
|
||||
const testDocument = parseYamlToDocument(
|
||||
outdent`
|
||||
asyncapi: '2.6.0'
|
||||
info:
|
||||
title: Account Service
|
||||
version: 1.0.0
|
||||
description: This service is in charge of processing user signups
|
||||
channels:
|
||||
user/signedup:
|
||||
subscribe:
|
||||
message:
|
||||
$ref: '#/components/messages/UserSignedUp'
|
||||
components:
|
||||
schemas:
|
||||
UserSignedUp:
|
||||
type: object
|
||||
properties:
|
||||
displayName:
|
||||
type: string
|
||||
description: Name of the user
|
||||
messages:
|
||||
UserSignedUp:
|
||||
payload:
|
||||
$ref: '#/components/schemas/UserSignedUp'
|
||||
`,
|
||||
''
|
||||
);
|
||||
|
||||
const config = await makeConfig({});
|
||||
|
||||
const {
|
||||
bundle: { parsed },
|
||||
problems,
|
||||
} = await bundleDocument({
|
||||
document: testDocument,
|
||||
config: config,
|
||||
externalRefResolver: new BaseResolver(),
|
||||
dereference: true,
|
||||
});
|
||||
|
||||
expect(problems).toHaveLength(0);
|
||||
expect(parsed).toMatchInlineSnapshot(`
|
||||
asyncapi: 2.6.0
|
||||
info:
|
||||
title: Account Service
|
||||
version: 1.0.0
|
||||
description: This service is in charge of processing user signups
|
||||
channels:
|
||||
user/signedup:
|
||||
subscribe:
|
||||
message:
|
||||
payload: &ref_1
|
||||
type: object
|
||||
properties: &ref_0
|
||||
displayName:
|
||||
type: string
|
||||
description: Name of the user
|
||||
components:
|
||||
schemas:
|
||||
UserSignedUp:
|
||||
type: object
|
||||
properties: *ref_0
|
||||
messages:
|
||||
UserSignedUp:
|
||||
payload: *ref_1
|
||||
|
||||
`);
|
||||
});
|
||||
|
||||
it('should bundle async of version 3.0', async () => {
|
||||
const testDocument = parseYamlToDocument(
|
||||
outdent`
|
||||
asyncapi: 3.0.0
|
||||
info:
|
||||
title: Account Service
|
||||
version: 1.0.0
|
||||
description: This service is in charge of processing user signups
|
||||
operations:
|
||||
sendUserSignedup:
|
||||
action: send
|
||||
messages:
|
||||
- $ref: '#/components/messages/UserSignedUp'
|
||||
components:
|
||||
schemas:
|
||||
UserSignedUp:
|
||||
type: object
|
||||
properties:
|
||||
displayName:
|
||||
type: string
|
||||
description: Name of the user
|
||||
messages:
|
||||
UserSignedUp:
|
||||
payload:
|
||||
$ref: '#/components/schemas/UserSignedUp'
|
||||
`,
|
||||
''
|
||||
);
|
||||
|
||||
const config = await makeConfig({});
|
||||
|
||||
const {
|
||||
bundle: { parsed },
|
||||
problems,
|
||||
} = await bundleDocument({
|
||||
document: testDocument,
|
||||
config: config,
|
||||
externalRefResolver: new BaseResolver(),
|
||||
dereference: true,
|
||||
});
|
||||
|
||||
expect(problems).toHaveLength(0);
|
||||
expect(parsed).toMatchInlineSnapshot(`
|
||||
asyncapi: 3.0.0
|
||||
info:
|
||||
title: Account Service
|
||||
version: 1.0.0
|
||||
description: This service is in charge of processing user signups
|
||||
operations:
|
||||
sendUserSignedup:
|
||||
action: send
|
||||
messages:
|
||||
- payload: &ref_1
|
||||
type: object
|
||||
properties: &ref_0
|
||||
displayName:
|
||||
type: string
|
||||
description: Name of the user
|
||||
components:
|
||||
schemas:
|
||||
UserSignedUp:
|
||||
type: object
|
||||
properties: *ref_0
|
||||
messages:
|
||||
UserSignedUp:
|
||||
payload: *ref_1
|
||||
|
||||
`);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -292,6 +292,15 @@ export function mapTypeToComponent(typeName: string, version: SpecMajorVersion)
|
||||
default:
|
||||
return null;
|
||||
}
|
||||
case SpecMajorVersion.Async3:
|
||||
switch (typeName) {
|
||||
case 'Schema':
|
||||
return 'schemas';
|
||||
case 'Parameter':
|
||||
return 'parameters';
|
||||
default:
|
||||
return null;
|
||||
}
|
||||
case SpecMajorVersion.Arazzo:
|
||||
switch (typeName) {
|
||||
case 'Root.x-parameters_items':
|
||||
@@ -377,6 +386,8 @@ function makeBundleVisitor(
|
||||
components = root;
|
||||
} else if (version === SpecMajorVersion.Async2) {
|
||||
components = root.components = root.components || {};
|
||||
} else if (version === SpecMajorVersion.Async3) {
|
||||
components = root.components = root.components || {};
|
||||
} else if (version === SpecMajorVersion.Arazzo) {
|
||||
components = root.components = root.components || {};
|
||||
}
|
||||
@@ -427,6 +438,8 @@ function makeBundleVisitor(
|
||||
components[componentType][name] = target.node;
|
||||
if (version === SpecMajorVersion.OAS3) {
|
||||
return `#/components/${componentType}/${name}`;
|
||||
} else if (version === SpecMajorVersion.Async2 || version === SpecMajorVersion.Async3) {
|
||||
return `#/components/${componentType}/${name}`;
|
||||
} else {
|
||||
return `#/${componentType}/${name}`;
|
||||
}
|
||||
|
||||
@@ -18,6 +18,17 @@ exports[`resolveConfig should ignore minimal from the root and read local file 1
|
||||
"tag-description": "warn",
|
||||
"tags-alphabetical": "off",
|
||||
},
|
||||
"async3Decorators": {},
|
||||
"async3Preprocessors": {},
|
||||
"async3Rules": {
|
||||
"channels-kebab-case": "off",
|
||||
"info-contact": "off",
|
||||
"no-channel-trailing-slash": "off",
|
||||
"operation-operationId": "warn",
|
||||
"spec": "error",
|
||||
"tag-description": "warn",
|
||||
"tags-alphabetical": "off",
|
||||
},
|
||||
"decorators": {},
|
||||
"doNotResolveExamples": undefined,
|
||||
"oas2Decorators": {},
|
||||
@@ -135,6 +146,17 @@ exports[`resolveStyleguideConfig should resolve extends with local file config w
|
||||
"tag-description": "warn",
|
||||
"tags-alphabetical": "off",
|
||||
},
|
||||
"async3Decorators": {},
|
||||
"async3Preprocessors": {},
|
||||
"async3Rules": {
|
||||
"channels-kebab-case": "off",
|
||||
"info-contact": "off",
|
||||
"no-channel-trailing-slash": "off",
|
||||
"operation-operationId": "warn",
|
||||
"spec": "error",
|
||||
"tag-description": "warn",
|
||||
"tags-alphabetical": "off",
|
||||
},
|
||||
"decorators": {},
|
||||
"doNotResolveExamples": undefined,
|
||||
"oas2Decorators": {},
|
||||
|
||||
@@ -12,6 +12,11 @@ StyleguideConfig {
|
||||
"oas3_0": {},
|
||||
"oas3_1": {},
|
||||
},
|
||||
"async3": {
|
||||
"oas2": {},
|
||||
"oas3_0": {},
|
||||
"oas3_1": {},
|
||||
},
|
||||
"oas2": {
|
||||
"oas2": {},
|
||||
"oas3_0": {},
|
||||
@@ -51,6 +56,11 @@ StyleguideConfig {
|
||||
"oas3_0": {},
|
||||
"oas3_1": {},
|
||||
},
|
||||
"async3": {
|
||||
"oas2": {},
|
||||
"oas3_0": {},
|
||||
"oas3_1": {},
|
||||
},
|
||||
"oas2": {
|
||||
"oas2": {},
|
||||
"oas3_0": {},
|
||||
@@ -124,6 +134,20 @@ StyleguideConfig {
|
||||
"operation-summary": "error",
|
||||
},
|
||||
},
|
||||
"async3": {
|
||||
"oas2": {
|
||||
"no-empty-servers": "error",
|
||||
"operation-summary": "error",
|
||||
},
|
||||
"oas3_0": {
|
||||
"no-empty-servers": "error",
|
||||
"operation-summary": "error",
|
||||
},
|
||||
"oas3_1": {
|
||||
"no-empty-servers": "error",
|
||||
"operation-summary": "error",
|
||||
},
|
||||
},
|
||||
"oas2": {
|
||||
"oas2": {
|
||||
"no-empty-servers": "error",
|
||||
|
||||
@@ -119,6 +119,7 @@ describe('getMergedConfig', () => {
|
||||
"decorators": {
|
||||
"arazzo": {},
|
||||
"async2": {},
|
||||
"async3": {},
|
||||
"oas2": {},
|
||||
"oas3_0": {},
|
||||
"oas3_1": {},
|
||||
@@ -131,6 +132,7 @@ describe('getMergedConfig', () => {
|
||||
"preprocessors": {
|
||||
"arazzo": {},
|
||||
"async2": {},
|
||||
"async3": {},
|
||||
"oas2": {},
|
||||
"oas3_0": {},
|
||||
"oas3_1": {},
|
||||
@@ -148,6 +150,9 @@ describe('getMergedConfig', () => {
|
||||
"async2": {
|
||||
"operation-summary": "warn",
|
||||
},
|
||||
"async3": {
|
||||
"operation-summary": "warn",
|
||||
},
|
||||
"oas2": {
|
||||
"operation-summary": "warn",
|
||||
},
|
||||
@@ -227,6 +232,7 @@ describe('getMergedConfig', () => {
|
||||
"decorators": {
|
||||
"arazzo": {},
|
||||
"async2": {},
|
||||
"async3": {},
|
||||
"oas2": {},
|
||||
"oas3_0": {},
|
||||
"oas3_1": {},
|
||||
@@ -239,6 +245,7 @@ describe('getMergedConfig', () => {
|
||||
"preprocessors": {
|
||||
"arazzo": {},
|
||||
"async2": {},
|
||||
"async3": {},
|
||||
"oas2": {},
|
||||
"oas3_0": {},
|
||||
"oas3_1": {},
|
||||
@@ -259,6 +266,10 @@ describe('getMergedConfig', () => {
|
||||
"no-empty-servers": "error",
|
||||
"operation-summary": "error",
|
||||
},
|
||||
"async3": {
|
||||
"no-empty-servers": "error",
|
||||
"operation-summary": "error",
|
||||
},
|
||||
"oas2": {
|
||||
"no-empty-servers": "error",
|
||||
"operation-summary": "error",
|
||||
|
||||
@@ -114,6 +114,15 @@ const all: PluginStyleguideConfig<'built-in'> = {
|
||||
'channels-kebab-case': 'error',
|
||||
'no-channel-trailing-slash': 'error',
|
||||
},
|
||||
async3Rules: {
|
||||
spec: 'error',
|
||||
'info-contact': 'error',
|
||||
'operation-operationId': 'error',
|
||||
'tag-description': 'error',
|
||||
'tags-alphabetical': 'error',
|
||||
'channels-kebab-case': 'error',
|
||||
'no-channel-trailing-slash': 'error',
|
||||
},
|
||||
arazzoRules: { spec: 'error' },
|
||||
};
|
||||
|
||||
|
||||
@@ -5,14 +5,17 @@ import minimal from './minimal';
|
||||
import { rules as oas3Rules } from '../rules/oas3';
|
||||
import { rules as oas2Rules } from '../rules/oas2';
|
||||
import { rules as async2Rules } from '../rules/async2';
|
||||
import { rules as async3Rules } from '../rules/async3';
|
||||
import { rules as arazzoRules } from '../rules/arazzo';
|
||||
import { preprocessors as oas3Preprocessors } from '../rules/oas3';
|
||||
import { preprocessors as oas2Preprocessors } from '../rules/oas2';
|
||||
import { preprocessors as async2Preprocessors } from '../rules/async2';
|
||||
import { preprocessors as async3Preprocessors } from '../rules/async3';
|
||||
import { preprocessors as arazzoPreprocessors } from '../rules/arazzo';
|
||||
import { decorators as oas3Decorators } from '../decorators/oas3';
|
||||
import { decorators as oas2Decorators } from '../decorators/oas2';
|
||||
import { decorators as async2Decorators } from '../decorators/async2';
|
||||
import { decorators as async3Decorators } from '../decorators/async3';
|
||||
import { decorators as arazzoDecorators } from '../decorators/arazzo';
|
||||
|
||||
import type { CustomRulesConfig, StyleguideRawConfig, Plugin } from './types';
|
||||
@@ -33,18 +36,21 @@ export const defaultPlugin: Plugin = {
|
||||
oas3: oas3Rules,
|
||||
oas2: oas2Rules,
|
||||
async2: async2Rules,
|
||||
async3: async3Rules,
|
||||
arazzo: arazzoRules,
|
||||
} as CustomRulesConfig,
|
||||
preprocessors: {
|
||||
oas3: oas3Preprocessors,
|
||||
oas2: oas2Preprocessors,
|
||||
async2: async2Preprocessors,
|
||||
async3: async3Preprocessors,
|
||||
arazzo: arazzoPreprocessors,
|
||||
},
|
||||
decorators: {
|
||||
oas3: oas3Decorators,
|
||||
oas2: oas2Decorators,
|
||||
async2: async2Decorators,
|
||||
async3: async3Decorators,
|
||||
arazzo: arazzoDecorators,
|
||||
},
|
||||
configs: builtInConfigs,
|
||||
|
||||
@@ -181,7 +181,7 @@ export function resolvePlugins(
|
||||
if (pluginModule.rules) {
|
||||
if (!pluginModule.rules.oas3 && !pluginModule.rules.oas2 && !pluginModule.rules.async2) {
|
||||
throw new Error(
|
||||
`Plugin rules must have \`oas3\`, \`oas2\`, \`async2\`, or \`arazzo\` rules "${p}.`
|
||||
`Plugin rules must have \`oas3\`, \`oas2\`, \`async2\`, \`async3\` or \`arazzo\` rules "${p}.`
|
||||
);
|
||||
}
|
||||
plugin.rules = {};
|
||||
@@ -194,6 +194,9 @@ export function resolvePlugins(
|
||||
if (pluginModule.rules.async2) {
|
||||
plugin.rules.async2 = prefixRules(pluginModule.rules.async2, id);
|
||||
}
|
||||
if (pluginModule.rules.async3) {
|
||||
plugin.rules.async3 = prefixRules(pluginModule.rules.async3, id);
|
||||
}
|
||||
if (pluginModule.rules.arazzo) {
|
||||
plugin.rules.arazzo = prefixRules(pluginModule.rules.arazzo, id);
|
||||
}
|
||||
@@ -203,6 +206,7 @@ export function resolvePlugins(
|
||||
!pluginModule.preprocessors.oas3 &&
|
||||
!pluginModule.preprocessors.oas2 &&
|
||||
!pluginModule.preprocessors.async2 &&
|
||||
!pluginModule.preprocessors.async3 &&
|
||||
!pluginModule.preprocessors.arazzo
|
||||
) {
|
||||
throw new Error(
|
||||
@@ -219,6 +223,9 @@ export function resolvePlugins(
|
||||
if (pluginModule.preprocessors.async2) {
|
||||
plugin.preprocessors.async2 = prefixRules(pluginModule.preprocessors.async2, id);
|
||||
}
|
||||
if (pluginModule.preprocessors.async3) {
|
||||
plugin.preprocessors.async3 = prefixRules(pluginModule.preprocessors.async3, id);
|
||||
}
|
||||
if (pluginModule.preprocessors.arazzo) {
|
||||
plugin.preprocessors.arazzo = prefixRules(pluginModule.preprocessors.arazzo, id);
|
||||
}
|
||||
@@ -229,10 +236,11 @@ export function resolvePlugins(
|
||||
!pluginModule.decorators.oas3 &&
|
||||
!pluginModule.decorators.oas2 &&
|
||||
!pluginModule.decorators.async2 &&
|
||||
!pluginModule.decorators.async3 &&
|
||||
!pluginModule.decorators.arazzo
|
||||
) {
|
||||
throw new Error(
|
||||
`Plugin \`decorators\` must have \`oas3\`, \`oas2\` or \`async2\` decorators "${p}.`
|
||||
`Plugin \`decorators\` must have \`oas3\`, \`oas2\`, \`async2\` or \`async3\` decorators "${p}.`
|
||||
);
|
||||
}
|
||||
plugin.decorators = {};
|
||||
@@ -245,6 +253,9 @@ export function resolvePlugins(
|
||||
if (pluginModule.decorators.async2) {
|
||||
plugin.decorators.async2 = prefixRules(pluginModule.decorators.async2, id);
|
||||
}
|
||||
if (pluginModule.decorators.async3) {
|
||||
plugin.decorators.async3 = prefixRules(pluginModule.decorators.async3, id);
|
||||
}
|
||||
if (pluginModule.decorators.arazzo) {
|
||||
plugin.decorators.arazzo = prefixRules(pluginModule.decorators.arazzo, id);
|
||||
}
|
||||
@@ -432,6 +443,8 @@ function getMergedRawStyleguideConfig(
|
||||
oas2Rules: { ...rootStyleguideConfig?.oas2Rules, ...apiStyleguideConfig?.oas2Rules },
|
||||
oas3_0Rules: { ...rootStyleguideConfig?.oas3_0Rules, ...apiStyleguideConfig?.oas3_0Rules },
|
||||
oas3_1Rules: { ...rootStyleguideConfig?.oas3_1Rules, ...apiStyleguideConfig?.oas3_1Rules },
|
||||
async2Rules: { ...rootStyleguideConfig?.async2Rules, ...apiStyleguideConfig?.async2Rules },
|
||||
async3Rules: { ...rootStyleguideConfig?.async3Rules, ...apiStyleguideConfig?.async3Rules },
|
||||
arazzoRules: { ...rootStyleguideConfig?.arazzoRules, ...apiStyleguideConfig?.arazzoRules },
|
||||
preprocessors: {
|
||||
...rootStyleguideConfig?.preprocessors,
|
||||
|
||||
@@ -9,6 +9,7 @@ import {
|
||||
Oas2RuleSet,
|
||||
Oas3RuleSet,
|
||||
Async2RuleSet,
|
||||
Async3RuleSet,
|
||||
ArazzoRuleSet,
|
||||
} from '../oas-types';
|
||||
import { isBrowser } from '../env';
|
||||
@@ -72,6 +73,7 @@ export class StyleguideConfig {
|
||||
[SpecVersion.OAS3_0]: { ...rawConfig.rules, ...rawConfig.oas3_0Rules },
|
||||
[SpecVersion.OAS3_1]: { ...rawConfig.rules, ...rawConfig.oas3_1Rules },
|
||||
[SpecVersion.Async2]: { ...rawConfig.rules, ...rawConfig.async2Rules },
|
||||
[SpecVersion.Async3]: { ...rawConfig.rules, ...rawConfig.async3Rules },
|
||||
[SpecVersion.Arazzo]: { ...rawConfig.arazzoRules },
|
||||
};
|
||||
|
||||
@@ -80,6 +82,7 @@ export class StyleguideConfig {
|
||||
[SpecVersion.OAS3_0]: { ...rawConfig.preprocessors, ...rawConfig.oas3_0Preprocessors },
|
||||
[SpecVersion.OAS3_1]: { ...rawConfig.preprocessors, ...rawConfig.oas3_1Preprocessors },
|
||||
[SpecVersion.Async2]: { ...rawConfig.preprocessors, ...rawConfig.async2Preprocessors },
|
||||
[SpecVersion.Async3]: { ...rawConfig.preprocessors, ...rawConfig.async3Preprocessors },
|
||||
[SpecVersion.Arazzo]: { ...rawConfig.arazzoPreprocessors },
|
||||
};
|
||||
|
||||
@@ -88,6 +91,7 @@ export class StyleguideConfig {
|
||||
[SpecVersion.OAS3_0]: { ...rawConfig.decorators, ...rawConfig.oas3_0Decorators },
|
||||
[SpecVersion.OAS3_1]: { ...rawConfig.decorators, ...rawConfig.oas3_1Decorators },
|
||||
[SpecVersion.Async2]: { ...rawConfig.decorators, ...rawConfig.async2Decorators },
|
||||
[SpecVersion.Async3]: { ...rawConfig.decorators, ...rawConfig.async3Decorators },
|
||||
[SpecVersion.Arazzo]: { ...rawConfig.arazzoDecorators },
|
||||
};
|
||||
|
||||
@@ -182,6 +186,10 @@ export class StyleguideConfig {
|
||||
if (!plugin.typeExtension.async2) continue;
|
||||
extendedTypes = plugin.typeExtension.async2(extendedTypes, version);
|
||||
break;
|
||||
case SpecVersion.Async3:
|
||||
if (!plugin.typeExtension.async3) continue;
|
||||
extendedTypes = plugin.typeExtension.async3(extendedTypes, version);
|
||||
break;
|
||||
case SpecVersion.Arazzo:
|
||||
if (!plugin.typeExtension.arazzo) continue;
|
||||
extendedTypes = plugin.typeExtension.arazzo(extendedTypes, version);
|
||||
@@ -276,15 +284,26 @@ export class StyleguideConfig {
|
||||
return oas2Rules;
|
||||
case SpecMajorVersion.Async2:
|
||||
// eslint-disable-next-line no-case-declarations
|
||||
const asyncApiRules: Async2RuleSet[] = []; // default ruleset
|
||||
const asyncApi2Rules: Async2RuleSet[] = []; // default ruleset
|
||||
this.plugins.forEach(
|
||||
(p) => p.preprocessors?.async2 && asyncApiRules.push(p.preprocessors.async2)
|
||||
(p) => p.preprocessors?.async2 && asyncApi2Rules.push(p.preprocessors.async2)
|
||||
);
|
||||
this.plugins.forEach((p) => p.rules?.async2 && asyncApiRules.push(p.rules.async2));
|
||||
this.plugins.forEach((p) => p.rules?.async2 && asyncApi2Rules.push(p.rules.async2));
|
||||
this.plugins.forEach(
|
||||
(p) => p.decorators?.async2 && asyncApiRules.push(p.decorators.async2)
|
||||
(p) => p.decorators?.async2 && asyncApi2Rules.push(p.decorators.async2)
|
||||
);
|
||||
return asyncApiRules;
|
||||
return asyncApi2Rules;
|
||||
case SpecMajorVersion.Async3:
|
||||
// eslint-disable-next-line no-case-declarations
|
||||
const asyncApi3Rules: Async3RuleSet[] = []; // default ruleset
|
||||
this.plugins.forEach(
|
||||
(p) => p.preprocessors?.async3 && asyncApi3Rules.push(p.preprocessors.async3)
|
||||
);
|
||||
this.plugins.forEach((p) => p.rules?.async3 && asyncApi3Rules.push(p.rules.async3));
|
||||
this.plugins.forEach(
|
||||
(p) => p.decorators?.async3 && asyncApi3Rules.push(p.decorators.async3)
|
||||
);
|
||||
return asyncApi3Rules;
|
||||
case SpecMajorVersion.Arazzo:
|
||||
// eslint-disable-next-line no-case-declarations
|
||||
const arazzoRules: ArazzoRuleSet[] = []; // default ruleset
|
||||
|
||||
@@ -96,6 +96,15 @@ const minimal: PluginStyleguideConfig<'built-in'> = {
|
||||
'channels-kebab-case': 'off',
|
||||
'no-channel-trailing-slash': 'off',
|
||||
},
|
||||
async3Rules: {
|
||||
spec: 'error',
|
||||
'info-contact': 'off',
|
||||
'operation-operationId': 'warn',
|
||||
'tag-description': 'warn',
|
||||
'tags-alphabetical': 'off',
|
||||
'channels-kebab-case': 'off',
|
||||
'no-channel-trailing-slash': 'off',
|
||||
},
|
||||
arazzoRules: {
|
||||
spec: 'error',
|
||||
},
|
||||
|
||||
@@ -96,6 +96,15 @@ const recommendedStrict: PluginStyleguideConfig<'built-in'> = {
|
||||
'channels-kebab-case': 'off',
|
||||
'no-channel-trailing-slash': 'off',
|
||||
},
|
||||
async3Rules: {
|
||||
spec: 'error',
|
||||
'info-contact': 'off',
|
||||
'operation-operationId': 'error',
|
||||
'tag-description': 'error',
|
||||
'tags-alphabetical': 'off',
|
||||
'channels-kebab-case': 'off',
|
||||
'no-channel-trailing-slash': 'off',
|
||||
},
|
||||
arazzoRules: {
|
||||
spec: 'error',
|
||||
},
|
||||
|
||||
@@ -96,6 +96,15 @@ const recommended: PluginStyleguideConfig<'built-in'> = {
|
||||
'channels-kebab-case': 'off',
|
||||
'no-channel-trailing-slash': 'off',
|
||||
},
|
||||
async3Rules: {
|
||||
spec: 'error',
|
||||
'info-contact': 'off',
|
||||
'operation-operationId': 'warn',
|
||||
'tag-description': 'warn',
|
||||
'tags-alphabetical': 'off',
|
||||
'channels-kebab-case': 'off',
|
||||
'no-channel-trailing-slash': 'off',
|
||||
},
|
||||
arazzoRules: {
|
||||
spec: 'error',
|
||||
},
|
||||
|
||||
@@ -11,6 +11,9 @@ import type {
|
||||
Async2PreprocessorsSet,
|
||||
Async2DecoratorsSet,
|
||||
Async2RuleSet,
|
||||
Async3PreprocessorsSet,
|
||||
Async3DecoratorsSet,
|
||||
Async3RuleSet,
|
||||
ArazzoRuleSet,
|
||||
ArazzoPreprocessorsSet,
|
||||
ArazzoDecoratorsSet,
|
||||
@@ -22,6 +25,7 @@ import { Location } from '../ref-utils';
|
||||
import type { SkipFunctionContext } from '../visitors';
|
||||
import {
|
||||
BuiltInAsync2RuleId,
|
||||
BuiltInAsync3RuleId,
|
||||
BuiltInCommonOASRuleId,
|
||||
BuiltInOAS2RuleId,
|
||||
BuiltInOAS3RuleId,
|
||||
@@ -59,6 +63,7 @@ export type StyleguideRawConfig<T = undefined> = {
|
||||
oas3_0Rules?: RuleMap<BuiltInOAS3RuleId, RuleConfig, T>;
|
||||
oas3_1Rules?: RuleMap<BuiltInOAS3RuleId, RuleConfig, T>;
|
||||
async2Rules?: RuleMap<BuiltInAsync2RuleId, RuleConfig, T>;
|
||||
async3Rules?: RuleMap<BuiltInAsync3RuleId, RuleConfig, T>;
|
||||
arazzoRules?: RuleMap<BuiltInArazzoRuleId, RuleConfig, T>;
|
||||
|
||||
preprocessors?: Record<string, PreprocessorConfig>;
|
||||
@@ -66,6 +71,7 @@ export type StyleguideRawConfig<T = undefined> = {
|
||||
oas3_0Preprocessors?: Record<string, PreprocessorConfig>;
|
||||
oas3_1Preprocessors?: Record<string, PreprocessorConfig>;
|
||||
async2Preprocessors?: Record<string, PreprocessorConfig>;
|
||||
async3Preprocessors?: Record<string, PreprocessorConfig>;
|
||||
arazzoPreprocessors?: Record<string, PreprocessorConfig>;
|
||||
|
||||
decorators?: Record<string, DecoratorConfig>;
|
||||
@@ -73,6 +79,7 @@ export type StyleguideRawConfig<T = undefined> = {
|
||||
oas3_0Decorators?: Record<string, DecoratorConfig>;
|
||||
oas3_1Decorators?: Record<string, DecoratorConfig>;
|
||||
async2Decorators?: Record<string, DecoratorConfig>;
|
||||
async3Decorators?: Record<string, DecoratorConfig>;
|
||||
arazzoDecorators?: Record<string, DecoratorConfig>;
|
||||
};
|
||||
|
||||
@@ -90,6 +97,7 @@ export type PreprocessorsConfig = {
|
||||
oas3?: Oas3PreprocessorsSet;
|
||||
oas2?: Oas2PreprocessorsSet;
|
||||
async2?: Async2PreprocessorsSet;
|
||||
async3?: Async3PreprocessorsSet;
|
||||
arazzo?: ArazzoPreprocessorsSet;
|
||||
};
|
||||
|
||||
@@ -97,6 +105,7 @@ export type DecoratorsConfig = {
|
||||
oas3?: Oas3DecoratorsSet;
|
||||
oas2?: Oas2DecoratorsSet;
|
||||
async2?: Async2DecoratorsSet;
|
||||
async3?: Async3DecoratorsSet;
|
||||
arazzo?: ArazzoDecoratorsSet;
|
||||
};
|
||||
|
||||
@@ -111,6 +120,7 @@ export type CustomRulesConfig = {
|
||||
oas3?: Oas3RuleSet;
|
||||
oas2?: Oas2RuleSet;
|
||||
async2?: Async2RuleSet;
|
||||
async3?: Async3RuleSet;
|
||||
arazzo?: ArazzoRuleSet;
|
||||
};
|
||||
|
||||
@@ -243,16 +253,19 @@ export type RulesFields =
|
||||
| 'oas3_0Rules'
|
||||
| 'oas3_1Rules'
|
||||
| 'async2Rules'
|
||||
| 'async3Rules'
|
||||
| 'arazzoRules'
|
||||
| 'preprocessors'
|
||||
| 'oas2Preprocessors'
|
||||
| 'oas3_0Preprocessors'
|
||||
| 'oas3_1Preprocessors'
|
||||
| 'async2Preprocessors'
|
||||
| 'async3Preprocessors'
|
||||
| 'arazzoPreprocessors'
|
||||
| 'decorators'
|
||||
| 'oas2Decorators'
|
||||
| 'oas3_0Decorators'
|
||||
| 'oas3_1Decorators'
|
||||
| 'arazzoDecorators'
|
||||
| 'async2Decorators';
|
||||
| 'async2Decorators'
|
||||
| 'async3Decorators'
|
||||
| 'arazzoDecorators';
|
||||
|
||||
@@ -56,6 +56,7 @@ function extractFlatConfig<
|
||||
oas3_0Rules,
|
||||
oas3_1Rules,
|
||||
async2Rules,
|
||||
async3Rules,
|
||||
arazzoRules,
|
||||
|
||||
preprocessors,
|
||||
@@ -63,6 +64,7 @@ function extractFlatConfig<
|
||||
oas3_0Preprocessors,
|
||||
oas3_1Preprocessors,
|
||||
async2Preprocessors,
|
||||
async3Preprocessors,
|
||||
arazzoPreprocessors,
|
||||
|
||||
decorators,
|
||||
@@ -70,6 +72,7 @@ function extractFlatConfig<
|
||||
oas3_0Decorators,
|
||||
oas3_1Decorators,
|
||||
async2Decorators,
|
||||
async3Decorators,
|
||||
arazzoDecorators,
|
||||
|
||||
...rawConfigRest
|
||||
@@ -86,6 +89,7 @@ function extractFlatConfig<
|
||||
oas3_0Rules,
|
||||
oas3_1Rules,
|
||||
async2Rules,
|
||||
async3Rules,
|
||||
arazzoRules,
|
||||
|
||||
preprocessors,
|
||||
@@ -93,6 +97,7 @@ function extractFlatConfig<
|
||||
oas3_0Preprocessors,
|
||||
oas3_1Preprocessors,
|
||||
async2Preprocessors,
|
||||
async3Preprocessors,
|
||||
arazzoPreprocessors,
|
||||
|
||||
decorators,
|
||||
@@ -100,6 +105,7 @@ function extractFlatConfig<
|
||||
oas3_0Decorators,
|
||||
oas3_1Decorators,
|
||||
async2Decorators,
|
||||
async3Decorators,
|
||||
arazzoDecorators,
|
||||
|
||||
doNotResolveExamples: rawConfigRest.resolve?.doNotResolveExamples,
|
||||
@@ -158,6 +164,7 @@ export function mergeExtends(rulesConfList: ResolvedStyleguideConfig[]) {
|
||||
oas3_0Rules: {},
|
||||
oas3_1Rules: {},
|
||||
async2Rules: {},
|
||||
async3Rules: {},
|
||||
arazzoRules: {},
|
||||
|
||||
preprocessors: {},
|
||||
@@ -165,6 +172,7 @@ export function mergeExtends(rulesConfList: ResolvedStyleguideConfig[]) {
|
||||
oas3_0Preprocessors: {},
|
||||
oas3_1Preprocessors: {},
|
||||
async2Preprocessors: {},
|
||||
async3Preprocessors: {},
|
||||
arazzoPreprocessors: {},
|
||||
|
||||
decorators: {},
|
||||
@@ -172,6 +180,7 @@ export function mergeExtends(rulesConfList: ResolvedStyleguideConfig[]) {
|
||||
oas3_0Decorators: {},
|
||||
oas3_1Decorators: {},
|
||||
async2Decorators: {},
|
||||
async3Decorators: {},
|
||||
arazzoDecorators: {},
|
||||
|
||||
plugins: [],
|
||||
@@ -195,6 +204,8 @@ export function mergeExtends(rulesConfList: ResolvedStyleguideConfig[]) {
|
||||
assignExisting(result.oas3_1Rules, rulesConf.rules || {});
|
||||
Object.assign(result.async2Rules, rulesConf.async2Rules);
|
||||
assignExisting(result.async2Rules, rulesConf.rules || {});
|
||||
Object.assign(result.async3Rules, rulesConf.async3Rules);
|
||||
assignExisting(result.async3Rules, rulesConf.rules || {});
|
||||
Object.assign(result.arazzoRules, rulesConf.arazzoRules);
|
||||
assignExisting(result.arazzoRules, rulesConf.rules || {});
|
||||
|
||||
@@ -207,6 +218,8 @@ export function mergeExtends(rulesConfList: ResolvedStyleguideConfig[]) {
|
||||
assignExisting(result.oas3_1Preprocessors, rulesConf.preprocessors || {});
|
||||
Object.assign(result.async2Preprocessors, rulesConf.async2Preprocessors);
|
||||
assignExisting(result.async2Preprocessors, rulesConf.preprocessors || {});
|
||||
Object.assign(result.async3Preprocessors, rulesConf.async3Preprocessors);
|
||||
assignExisting(result.async3Preprocessors, rulesConf.preprocessors || {});
|
||||
Object.assign(result.arazzoPreprocessors, rulesConf.arazzoPreprocessors);
|
||||
assignExisting(result.arazzoPreprocessors, rulesConf.preprocessors || {});
|
||||
|
||||
@@ -219,6 +232,8 @@ export function mergeExtends(rulesConfList: ResolvedStyleguideConfig[]) {
|
||||
assignExisting(result.oas3_1Decorators, rulesConf.decorators || {});
|
||||
Object.assign(result.async2Decorators, rulesConf.async2Decorators);
|
||||
assignExisting(result.async2Decorators, rulesConf.decorators || {});
|
||||
Object.assign(result.async3Decorators, rulesConf.async3Decorators);
|
||||
assignExisting(result.async3Decorators, rulesConf.decorators || {});
|
||||
Object.assign(result.arazzoDecorators, rulesConf.arazzoDecorators);
|
||||
assignExisting(result.arazzoDecorators, rulesConf.decorators || {});
|
||||
|
||||
|
||||
1
packages/core/src/decorators/async3/index.ts
Normal file
1
packages/core/src/decorators/async3/index.ts
Normal file
@@ -0,0 +1 @@
|
||||
export const decorators = {};
|
||||
@@ -11,7 +11,8 @@ export { Oas3_1Types } from './types/oas3_1';
|
||||
export { ArazzoTypes } from './types/arazzo';
|
||||
export { Oas3Types } from './types/oas3';
|
||||
export { Oas2Types } from './types/oas2';
|
||||
export { AsyncApi2Types } from './types/asyncapi';
|
||||
export { AsyncApi2Types } from './types/asyncapi2';
|
||||
export { AsyncApi3Types } from './types/asyncapi3';
|
||||
export { ConfigTypes } from './types/redocly-yaml';
|
||||
export type {
|
||||
Oas3Definition,
|
||||
|
||||
@@ -5,16 +5,20 @@ import {
|
||||
Oas2Preprocessor,
|
||||
Async2Preprocessor,
|
||||
Async2Rule,
|
||||
Async3Preprocessor,
|
||||
Async3Rule,
|
||||
ArazzoPreprocessor,
|
||||
ArazzoRule,
|
||||
} from './visitors';
|
||||
import { Oas2Types } from './types/oas2';
|
||||
import { Oas3Types } from './types/oas3';
|
||||
import { Oas3_1Types } from './types/oas3_1';
|
||||
import { AsyncApi2Types } from './types/asyncapi';
|
||||
import { AsyncApi2Types } from './types/asyncapi2';
|
||||
import { AsyncApi3Types } from './types/asyncapi3';
|
||||
import { ArazzoTypes } from './types/arazzo';
|
||||
import {
|
||||
BuiltInAsync2RuleId,
|
||||
BuiltInAsync3RuleId,
|
||||
BuiltInCommonOASRuleId,
|
||||
BuiltInArazzoRuleId,
|
||||
BuiltInOAS2RuleId,
|
||||
@@ -27,7 +31,8 @@ export enum SpecVersion {
|
||||
OAS2 = 'oas2',
|
||||
OAS3_0 = 'oas3_0',
|
||||
OAS3_1 = 'oas3_1',
|
||||
Async2 = 'async2', // todo split into 2.x maybe?
|
||||
Async2 = 'async2',
|
||||
Async3 = 'async3',
|
||||
Arazzo = 'arazzo',
|
||||
}
|
||||
|
||||
@@ -35,6 +40,7 @@ export enum SpecMajorVersion {
|
||||
OAS2 = 'oas2',
|
||||
OAS3 = 'oas3',
|
||||
Async2 = 'async2',
|
||||
Async3 = 'async3',
|
||||
Arazzo = 'arazzo',
|
||||
}
|
||||
|
||||
@@ -43,6 +49,7 @@ const typesMap = {
|
||||
[SpecVersion.OAS3_0]: Oas3Types,
|
||||
[SpecVersion.OAS3_1]: Oas3_1Types,
|
||||
[SpecVersion.Async2]: AsyncApi2Types,
|
||||
[SpecVersion.Async3]: AsyncApi3Types,
|
||||
[SpecVersion.Arazzo]: ArazzoTypes,
|
||||
};
|
||||
|
||||
@@ -65,6 +72,11 @@ export type Async2RuleSet<T = undefined> = RuleMap<
|
||||
Async2Rule,
|
||||
T
|
||||
>;
|
||||
export type Async3RuleSet<T = undefined> = RuleMap<
|
||||
BuiltInAsync3RuleId | 'assertions',
|
||||
Async3Rule,
|
||||
T
|
||||
>;
|
||||
export type ArazzoRuleSet<T = undefined> = RuleMap<
|
||||
BuiltInArazzoRuleId | 'assertions',
|
||||
ArazzoRule,
|
||||
@@ -74,11 +86,13 @@ export type ArazzoRuleSet<T = undefined> = RuleMap<
|
||||
export type Oas3PreprocessorsSet = Record<string, Oas3Preprocessor>;
|
||||
export type Oas2PreprocessorsSet = Record<string, Oas2Preprocessor>;
|
||||
export type Async2PreprocessorsSet = Record<string, Async2Preprocessor>;
|
||||
export type Async3PreprocessorsSet = Record<string, Async3Preprocessor>;
|
||||
export type ArazzoPreprocessorsSet = Record<string, ArazzoPreprocessor>;
|
||||
|
||||
export type Oas3DecoratorsSet = Record<string, Oas3Preprocessor>;
|
||||
export type Oas2DecoratorsSet = Record<string, Oas2Preprocessor>;
|
||||
export type Async2DecoratorsSet = Record<string, Async2Preprocessor>;
|
||||
export type Async3DecoratorsSet = Record<string, Async3Preprocessor>;
|
||||
export type ArazzoDecoratorsSet = Record<string, ArazzoPreprocessor>;
|
||||
|
||||
export function detectSpec(root: any): SpecVersion {
|
||||
@@ -111,6 +125,10 @@ export function detectSpec(root: any): SpecVersion {
|
||||
return SpecVersion.Async2;
|
||||
}
|
||||
|
||||
if (root.asyncapi && root.asyncapi.startsWith('3.')) {
|
||||
return SpecVersion.Async3;
|
||||
}
|
||||
|
||||
if (root.asyncapi) {
|
||||
throw new Error(`Unsupported AsyncAPI version: ${root.asyncapi}`);
|
||||
}
|
||||
@@ -127,6 +145,8 @@ export function getMajorSpecVersion(version: SpecVersion): SpecMajorVersion {
|
||||
return SpecMajorVersion.OAS2;
|
||||
} else if (version === SpecVersion.Async2) {
|
||||
return SpecMajorVersion.Async2;
|
||||
} else if (version === SpecVersion.Async3) {
|
||||
return SpecMajorVersion.Async3;
|
||||
} else if (version === SpecVersion.Arazzo) {
|
||||
return SpecMajorVersion.Arazzo;
|
||||
} else {
|
||||
|
||||
@@ -0,0 +1,141 @@
|
||||
import { outdent } from 'outdent';
|
||||
import { lintDocument } from '../../../lint';
|
||||
import { parseYamlToDocument, replaceSourceWithRef, makeConfig } from '../../../../__tests__/utils';
|
||||
import { BaseResolver } from '../../../resolve';
|
||||
|
||||
describe('Async2 channels-kebab-case', () => {
|
||||
it('should report on no kebab-case channel path', async () => {
|
||||
const document = parseYamlToDocument(
|
||||
outdent`
|
||||
asyncapi: '3.0.0'
|
||||
info:
|
||||
title: Cool API
|
||||
version: 1.0.0
|
||||
channels:
|
||||
channel1:
|
||||
address: /NOT_A_KEBAB/
|
||||
payload:
|
||||
type: object
|
||||
`,
|
||||
'asyncapi.yaml'
|
||||
);
|
||||
|
||||
const results = await lintDocument({
|
||||
externalRefResolver: new BaseResolver(),
|
||||
document,
|
||||
config: await makeConfig({ 'channels-kebab-case': 'error' }),
|
||||
});
|
||||
|
||||
expect(replaceSourceWithRef(results)).toMatchInlineSnapshot(`
|
||||
[
|
||||
{
|
||||
"location": [
|
||||
{
|
||||
"pointer": "#/channels/channel1",
|
||||
"reportOnKey": true,
|
||||
"source": "asyncapi.yaml",
|
||||
},
|
||||
],
|
||||
"message": "\`/NOT_A_KEBAB/\` does not use kebab-case.",
|
||||
"ruleId": "channels-kebab-case",
|
||||
"severity": "error",
|
||||
"suggest": [],
|
||||
},
|
||||
]
|
||||
`);
|
||||
});
|
||||
|
||||
it('should report on snake_case in channel path', async () => {
|
||||
const document = parseYamlToDocument(
|
||||
outdent`
|
||||
asyncapi: '3.0.0'
|
||||
info:
|
||||
title: Cool API
|
||||
version: 1.0.0
|
||||
channels:
|
||||
channel1:
|
||||
address: snake_kebab
|
||||
payload:
|
||||
type: object
|
||||
`,
|
||||
'asyncapi.yaml'
|
||||
);
|
||||
|
||||
const results = await lintDocument({
|
||||
externalRefResolver: new BaseResolver(),
|
||||
document,
|
||||
config: await makeConfig({ 'channels-kebab-case': 'error' }),
|
||||
});
|
||||
|
||||
expect(replaceSourceWithRef(results)).toMatchInlineSnapshot(`
|
||||
[
|
||||
{
|
||||
"location": [
|
||||
{
|
||||
"pointer": "#/channels/channel1",
|
||||
"reportOnKey": true,
|
||||
"source": "asyncapi.yaml",
|
||||
},
|
||||
],
|
||||
"message": "\`snake_kebab\` does not use kebab-case.",
|
||||
"ruleId": "channels-kebab-case",
|
||||
"severity": "error",
|
||||
"suggest": [],
|
||||
},
|
||||
]
|
||||
`);
|
||||
});
|
||||
|
||||
it('should allow trailing slash in channel path with "channels-kebab-case" rule', async () => {
|
||||
const document = parseYamlToDocument(
|
||||
outdent`
|
||||
asyncapi: '3.0.0'
|
||||
info:
|
||||
title: Cool API
|
||||
version: 1.0.0
|
||||
channels:
|
||||
channel1:
|
||||
address: kebab/
|
||||
payload:
|
||||
type: object
|
||||
`,
|
||||
'asyncapi.yaml'
|
||||
);
|
||||
|
||||
const results = await lintDocument({
|
||||
externalRefResolver: new BaseResolver(),
|
||||
document,
|
||||
config: await makeConfig({
|
||||
'paths-kebab-case': 'error',
|
||||
'no-path-trailing-slash': 'off',
|
||||
}),
|
||||
});
|
||||
expect(replaceSourceWithRef(results)).toMatchInlineSnapshot(`[]`);
|
||||
});
|
||||
|
||||
it('words with hyphens are allowed with "channels-kebab-case" rule', async () => {
|
||||
const document = parseYamlToDocument(
|
||||
outdent`
|
||||
asyncapi: '3.0.0'
|
||||
info:
|
||||
title: Cool API
|
||||
version: 1.0.0
|
||||
channels:
|
||||
channel1:
|
||||
address: kebab-with-longer-channel-path:/
|
||||
payload:
|
||||
type: object
|
||||
`,
|
||||
'asyncapi.yaml'
|
||||
);
|
||||
|
||||
const results = await lintDocument({
|
||||
externalRefResolver: new BaseResolver(),
|
||||
document,
|
||||
config: await makeConfig({
|
||||
'paths-kebab-case': 'error',
|
||||
}),
|
||||
});
|
||||
expect(replaceSourceWithRef(results)).toMatchInlineSnapshot(`[]`);
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,96 @@
|
||||
import { outdent } from 'outdent';
|
||||
import { lintDocument } from '../../../lint';
|
||||
import { parseYamlToDocument, replaceSourceWithRef, makeConfig } from '../../../../__tests__/utils';
|
||||
import { BaseResolver } from '../../../resolve';
|
||||
|
||||
describe('no-channel-trailing-slash', () => {
|
||||
it.only('should report on trailing slash in a channel path', async () => {
|
||||
const document = parseYamlToDocument(
|
||||
outdent`
|
||||
asyncapi: '3.0.0'
|
||||
info:
|
||||
title: Excellent API
|
||||
version: 1.0.0
|
||||
channels:
|
||||
channel1:
|
||||
address: /trailing/
|
||||
payload:
|
||||
type: object
|
||||
`,
|
||||
'asyncapi.yaml'
|
||||
);
|
||||
|
||||
const results = await lintDocument({
|
||||
externalRefResolver: new BaseResolver(),
|
||||
document,
|
||||
config: await makeConfig({ 'no-channel-trailing-slash': 'error' }),
|
||||
});
|
||||
expect(replaceSourceWithRef(results)).toMatchInlineSnapshot(`
|
||||
[
|
||||
{
|
||||
"location": [
|
||||
{
|
||||
"pointer": "#/channels/channel1",
|
||||
"reportOnKey": true,
|
||||
"source": "asyncapi.yaml",
|
||||
},
|
||||
],
|
||||
"message": "\`/trailing/\` should not have a trailing slash.",
|
||||
"ruleId": "no-channel-trailing-slash",
|
||||
"severity": "error",
|
||||
"suggest": [],
|
||||
},
|
||||
]
|
||||
`);
|
||||
});
|
||||
|
||||
it('should not report on if no trailing slash in path', async () => {
|
||||
const document = parseYamlToDocument(
|
||||
outdent`
|
||||
asyncapi: '3.0.0'
|
||||
info:
|
||||
title: Excellent API
|
||||
version: 1.0.0
|
||||
channels:
|
||||
channel1:
|
||||
address: /expected
|
||||
payload:
|
||||
type: object
|
||||
`,
|
||||
'asyncapi.yaml'
|
||||
);
|
||||
|
||||
const results = await lintDocument({
|
||||
externalRefResolver: new BaseResolver(),
|
||||
document,
|
||||
config: await makeConfig({ 'no-channel-trailing-slash': 'error' }),
|
||||
});
|
||||
|
||||
expect(replaceSourceWithRef(results)).toMatchInlineSnapshot(`[]`);
|
||||
});
|
||||
|
||||
it('should not report on trailing slash in path if the path is root', async () => {
|
||||
const document = parseYamlToDocument(
|
||||
outdent`
|
||||
asyncapi: '3.0.0'
|
||||
info:
|
||||
title: Excellent API
|
||||
version: 1.0.0
|
||||
channels:
|
||||
channel1:
|
||||
address: /
|
||||
payload:
|
||||
type: object
|
||||
`,
|
||||
'foobar.yaml'
|
||||
);
|
||||
|
||||
const results = await lintDocument({
|
||||
externalRefResolver: new BaseResolver(),
|
||||
document,
|
||||
config: await makeConfig({ 'no-channel-trailing-slash': 'error' }),
|
||||
});
|
||||
|
||||
expect(replaceSourceWithRef(results)).toMatchInlineSnapshot(`[]`);
|
||||
});
|
||||
});
|
||||
19
packages/core/src/rules/async3/channels-kebab-case.ts
Normal file
19
packages/core/src/rules/async3/channels-kebab-case.ts
Normal file
@@ -0,0 +1,19 @@
|
||||
import { Channel } from '../../typings/asyncapi3';
|
||||
import { Async3Rule } from '../../visitors';
|
||||
import { UserContext } from '../../walk';
|
||||
|
||||
export const ChannelsKebabCase: Async3Rule = () => {
|
||||
return {
|
||||
Channel(channel: Channel, { report }: UserContext) {
|
||||
const segments = (channel.address || '')
|
||||
.split(/[/.:]/) // split on / or : as likely channel namespacers
|
||||
.filter((s) => s !== ''); // filter out empty segments
|
||||
if (!segments.every((segment) => /^{.+}$/.test(segment) || /^[a-z0-9-.]+$/.test(segment))) {
|
||||
report({
|
||||
message: `\`${channel.address}\` does not use kebab-case.`,
|
||||
location: { reportOnKey: true },
|
||||
});
|
||||
}
|
||||
},
|
||||
};
|
||||
};
|
||||
23
packages/core/src/rules/async3/index.ts
Normal file
23
packages/core/src/rules/async3/index.ts
Normal file
@@ -0,0 +1,23 @@
|
||||
import { Async3Rule } from '../../visitors';
|
||||
import { Assertions } from '../common/assertions';
|
||||
import { Spec } from '../common/spec';
|
||||
import { InfoContact } from '../common/info-contact';
|
||||
import { OperationOperationId } from '../common/operation-operationId';
|
||||
import { TagDescription } from '../common/tag-description';
|
||||
import { TagsAlphabetical } from '../common/tags-alphabetical';
|
||||
import { ChannelsKebabCase } from './channels-kebab-case';
|
||||
import { NoChannelTrailingSlash } from './no-channel-trailing-slash';
|
||||
import type { Async3RuleSet } from '../../oas-types';
|
||||
|
||||
export const rules: Async3RuleSet<'built-in'> = {
|
||||
spec: Spec as Async3Rule,
|
||||
assertions: Assertions,
|
||||
'info-contact': InfoContact,
|
||||
'operation-operationId': OperationOperationId,
|
||||
'channels-kebab-case': ChannelsKebabCase,
|
||||
'no-channel-trailing-slash': NoChannelTrailingSlash,
|
||||
'tag-description': TagDescription,
|
||||
'tags-alphabetical': TagsAlphabetical,
|
||||
};
|
||||
|
||||
export const preprocessors = {};
|
||||
16
packages/core/src/rules/async3/no-channel-trailing-slash.ts
Normal file
16
packages/core/src/rules/async3/no-channel-trailing-slash.ts
Normal file
@@ -0,0 +1,16 @@
|
||||
import { Async3Rule } from '../../visitors';
|
||||
import { UserContext } from '../../walk';
|
||||
import { Channel } from '../../typings/asyncapi3';
|
||||
|
||||
export const NoChannelTrailingSlash: Async3Rule = () => {
|
||||
return {
|
||||
Channel(channel: Channel, { report, location }: UserContext) {
|
||||
if ((channel.address as string).endsWith('/') && channel.address !== '/') {
|
||||
report({
|
||||
message: `\`${channel.address}\` should not have a trailing slash.`,
|
||||
location: location.key(),
|
||||
});
|
||||
}
|
||||
},
|
||||
};
|
||||
};
|
||||
@@ -1,6 +1,6 @@
|
||||
import { asserts, AssertionFn } from './asserts';
|
||||
import { buildSubjectVisitor, buildVisitorObject } from './utils';
|
||||
import { Oas2Visitor, Oas3Visitor } from '../../../visitors';
|
||||
import { Async2Visitor, Async3Visitor, Oas2Visitor, Oas3Visitor } from '../../../visitors';
|
||||
import { RuleSeverity } from '../../../config';
|
||||
import { isString } from '../../../utils';
|
||||
|
||||
@@ -28,7 +28,7 @@ export type RawAssertion = AssertionDefinition & {
|
||||
export type Assertion = RawAssertion & { assertionId: string };
|
||||
|
||||
export const Assertions = (opts: Record<string, Assertion>) => {
|
||||
const visitors: (Oas2Visitor | Oas3Visitor)[] = [];
|
||||
const visitors: (Oas2Visitor | Oas3Visitor | Async2Visitor | Async3Visitor)[] = [];
|
||||
|
||||
// As 'Assertions' has an array of asserts,
|
||||
// that array spreads into an 'opts' object on init rules phase here
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
import type { Oas3Rule, Oas2Rule, Async2Rule, ArazzoRule } from '../../visitors';
|
||||
import type { Oas3Rule, Oas2Rule, Async2Rule, Async3Rule, ArazzoRule } from '../../visitors';
|
||||
import { isNamedType, SpecExtension } from '../../types';
|
||||
import { oasTypeOf, matchesJsonSchemaType, getSuggest, validateSchemaEnumType } from '../utils';
|
||||
import { isRef } from '../../ref-utils';
|
||||
import { isPlainObject } from '../../utils';
|
||||
import { UserContext } from '../../walk';
|
||||
|
||||
export const Spec: Oas3Rule | Oas2Rule | Async2Rule | ArazzoRule = () => {
|
||||
export const Spec: Oas3Rule | Oas2Rule | Async2Rule | Async3Rule | ArazzoRule = () => {
|
||||
return {
|
||||
any(
|
||||
node: any,
|
||||
|
||||
@@ -61,7 +61,7 @@ const ChannelBindings: NodeType = {
|
||||
additionalProperties: { type: 'object' },
|
||||
};
|
||||
|
||||
const Tag: NodeType = {
|
||||
export const Tag: NodeType = {
|
||||
properties: {
|
||||
name: { type: 'string' },
|
||||
description: { type: 'string' },
|
||||
@@ -70,7 +70,7 @@ const Tag: NodeType = {
|
||||
required: ['name'],
|
||||
};
|
||||
|
||||
const ExternalDocs: NodeType = {
|
||||
export const ExternalDocs: NodeType = {
|
||||
properties: {
|
||||
description: { type: 'string' },
|
||||
url: { type: 'string' },
|
||||
@@ -126,13 +126,13 @@ const Server: NodeType = {
|
||||
required: ['url', 'protocol'],
|
||||
};
|
||||
|
||||
const ServerMap: NodeType = {
|
||||
export const ServerMap: NodeType = {
|
||||
properties: {},
|
||||
additionalProperties: (_value: any, key: string) =>
|
||||
key.match(/^[A-Za-z0-9_\-]+$/) ? 'Server' : undefined,
|
||||
};
|
||||
|
||||
const ServerVariable: NodeType = {
|
||||
export const ServerVariable: NodeType = {
|
||||
properties: {
|
||||
enum: {
|
||||
type: 'array',
|
||||
@@ -160,7 +160,7 @@ const Info: NodeType = {
|
||||
required: ['title', 'version'],
|
||||
};
|
||||
|
||||
const Contact: NodeType = {
|
||||
export const Contact: NodeType = {
|
||||
properties: {
|
||||
name: { type: 'string' },
|
||||
url: { type: 'string' },
|
||||
@@ -168,7 +168,7 @@ const Contact: NodeType = {
|
||||
},
|
||||
};
|
||||
|
||||
const License: NodeType = {
|
||||
export const License: NodeType = {
|
||||
properties: {
|
||||
name: { type: 'string' },
|
||||
url: { type: 'string' },
|
||||
@@ -184,7 +184,7 @@ const Parameter: NodeType = {
|
||||
},
|
||||
};
|
||||
|
||||
const CorrelationId: NodeType = {
|
||||
export const CorrelationId: NodeType = {
|
||||
properties: {
|
||||
description: { type: 'string' },
|
||||
location: { type: 'string' },
|
||||
@@ -208,7 +208,7 @@ const Message: NodeType = {
|
||||
tags: 'TagList',
|
||||
externalDocs: 'ExternalDocs',
|
||||
bindings: 'MessageBindings',
|
||||
// examples: 'MessageExampleList', // TODO: add support for message examples
|
||||
examples: 'MessageExampleList',
|
||||
traits: 'MessageTraitList',
|
||||
},
|
||||
additionalProperties: {},
|
||||
@@ -301,7 +301,7 @@ const MessageTrait: NodeType = {
|
||||
tags: 'TagList',
|
||||
externalDocs: 'ExternalDocs',
|
||||
bindings: 'MessageBindings',
|
||||
// examples: 'MessageExampleList', // TODO: support examples for message traits
|
||||
examples: 'MessageExampleList',
|
||||
},
|
||||
additionalProperties: {},
|
||||
};
|
||||
@@ -322,7 +322,7 @@ const Operation: NodeType = {
|
||||
required: [],
|
||||
};
|
||||
|
||||
const MessageExample: NodeType = {
|
||||
export const MessageExample: NodeType = {
|
||||
properties: {
|
||||
payload: { isExample: true },
|
||||
summary: { type: 'string' },
|
||||
@@ -331,7 +331,7 @@ const MessageExample: NodeType = {
|
||||
},
|
||||
};
|
||||
|
||||
const Schema: NodeType = {
|
||||
export const Schema: NodeType = {
|
||||
properties: {
|
||||
$id: { type: 'string' },
|
||||
$schema: { type: 'string' },
|
||||
@@ -401,14 +401,14 @@ const Schema: NodeType = {
|
||||
},
|
||||
};
|
||||
|
||||
const SchemaProperties: NodeType = {
|
||||
export const SchemaProperties: NodeType = {
|
||||
properties: {},
|
||||
additionalProperties: (value: any) => {
|
||||
return typeof value === 'boolean' ? { type: 'boolean' } : 'Schema';
|
||||
},
|
||||
};
|
||||
|
||||
const DiscriminatorMapping: NodeType = {
|
||||
export const DiscriminatorMapping: NodeType = {
|
||||
properties: {},
|
||||
additionalProperties: (value: any) => {
|
||||
if (isMappingRef(value)) {
|
||||
@@ -419,7 +419,7 @@ const DiscriminatorMapping: NodeType = {
|
||||
},
|
||||
};
|
||||
|
||||
const Discriminator: NodeType = {
|
||||
export const Discriminator: NodeType = {
|
||||
properties: {
|
||||
propertyName: { type: 'string' },
|
||||
mapping: 'DiscriminatorMapping',
|
||||
@@ -435,7 +435,6 @@ const Components: NodeType = {
|
||||
correlationIds: 'NamedCorrelationIds',
|
||||
messageTraits: 'NamedMessageTraits',
|
||||
operationTraits: 'NamedOperationTraits',
|
||||
streamHeaders: 'NamedStreamHeaders',
|
||||
securitySchemes: 'NamedSecuritySchemes',
|
||||
servers: 'ServerMap',
|
||||
serverVariables: 'ServerVariablesMap',
|
||||
@@ -484,7 +483,7 @@ const AuthorizationCode: NodeType = {
|
||||
required: ['authorizationUrl', 'tokenUrl', 'scopes'],
|
||||
};
|
||||
|
||||
const SecuritySchemeFlows: NodeType = {
|
||||
export const SecuritySchemeFlows: NodeType = {
|
||||
properties: {
|
||||
implicit: 'ImplicitFlow',
|
||||
password: 'PasswordFlow',
|
||||
@@ -555,7 +554,7 @@ const SecurityScheme: NodeType = {
|
||||
extensionsPrefix: 'x-',
|
||||
};
|
||||
|
||||
const Dependencies: NodeType = {
|
||||
export const Dependencies: NodeType = {
|
||||
properties: {},
|
||||
additionalProperties: (value: any) => {
|
||||
return Array.isArray(value) ? { type: 'array', items: { type: 'string' } } : 'Schema';
|
||||
@@ -987,22 +986,7 @@ OperationBindings.properties.mercure = MercureOperationBinding;
|
||||
// pulsar
|
||||
|
||||
// --- End per-protocol node types
|
||||
|
||||
export const AsyncApi2Types: Record<string, NodeType> = {
|
||||
Root,
|
||||
Tag,
|
||||
TagList: listOf('Tag'),
|
||||
ServerMap,
|
||||
ExternalDocs,
|
||||
Server,
|
||||
ServerVariable,
|
||||
ServerVariablesMap: mapOf('ServerVariable'),
|
||||
SecurityRequirement,
|
||||
SecurityRequirementList: listOf('SecurityRequirement'),
|
||||
Info,
|
||||
Contact,
|
||||
License,
|
||||
|
||||
export const AsyncApi2Bindings: Record<string, NodeType> = {
|
||||
HttpServerBinding,
|
||||
HttpChannelBinding,
|
||||
HttpMessageBinding,
|
||||
@@ -1078,6 +1062,25 @@ export const AsyncApi2Types: Record<string, NodeType> = {
|
||||
|
||||
ServerBindings,
|
||||
ChannelBindings,
|
||||
MessageBindings,
|
||||
OperationBindings,
|
||||
};
|
||||
|
||||
export const AsyncApi2Types: Record<string, NodeType> = {
|
||||
...AsyncApi2Bindings,
|
||||
Root,
|
||||
Tag,
|
||||
TagList: listOf('Tag'),
|
||||
ServerMap,
|
||||
ExternalDocs,
|
||||
Server,
|
||||
ServerVariable,
|
||||
ServerVariablesMap: mapOf('ServerVariable'),
|
||||
SecurityRequirement,
|
||||
SecurityRequirementList: listOf('SecurityRequirement'),
|
||||
Info,
|
||||
Contact,
|
||||
License,
|
||||
ChannelMap,
|
||||
Channel,
|
||||
Parameter,
|
||||
@@ -1096,7 +1099,6 @@ export const AsyncApi2Types: Record<string, NodeType> = {
|
||||
NamedParameters: mapOf('Parameter'),
|
||||
NamedSecuritySchemes: mapOf('SecurityScheme'),
|
||||
NamedCorrelationIds: mapOf('CorrelationId'),
|
||||
NamedStreamHeaders: mapOf('StreamHeader'),
|
||||
ImplicitFlow,
|
||||
PasswordFlow,
|
||||
ClientCredentials,
|
||||
@@ -1110,6 +1112,7 @@ export const AsyncApi2Types: Record<string, NodeType> = {
|
||||
OperationTraitList: listOf('OperationTrait'),
|
||||
MessageTrait,
|
||||
MessageTraitList: listOf('MessageTrait'),
|
||||
MessageExampleList: listOf('MessageExample'),
|
||||
CorrelationId,
|
||||
Dependencies,
|
||||
};
|
||||
381
packages/core/src/types/asyncapi3.ts
Normal file
381
packages/core/src/types/asyncapi3.ts
Normal file
@@ -0,0 +1,381 @@
|
||||
import { NodeType, listOf, mapOf } from '.';
|
||||
import {
|
||||
AsyncApi2Bindings,
|
||||
Schema,
|
||||
Dependencies,
|
||||
Discriminator,
|
||||
DiscriminatorMapping,
|
||||
SchemaProperties,
|
||||
CorrelationId,
|
||||
Tag,
|
||||
ServerMap,
|
||||
ExternalDocs,
|
||||
SecuritySchemeFlows,
|
||||
ServerVariable,
|
||||
Contact,
|
||||
License,
|
||||
MessageExample,
|
||||
} from './asyncapi2';
|
||||
|
||||
const Root: NodeType = {
|
||||
properties: {
|
||||
asyncapi: { type: 'string', enum: ['3.0.0'] },
|
||||
info: 'Info',
|
||||
id: { type: 'string' },
|
||||
servers: 'ServerMap',
|
||||
channels: 'NamedChannels',
|
||||
components: 'Components',
|
||||
operations: 'NamedOperations',
|
||||
defaultContentType: { type: 'string' },
|
||||
},
|
||||
required: ['asyncapi', 'info'],
|
||||
};
|
||||
|
||||
const Channel: NodeType = {
|
||||
properties: {
|
||||
address: { type: 'string' },
|
||||
messages: 'NamedMessages',
|
||||
title: { type: 'string' },
|
||||
summary: { type: 'string' },
|
||||
description: { type: 'string' },
|
||||
servers: 'ServerList',
|
||||
parameters: 'ParametersMap',
|
||||
bindings: 'ChannelBindings',
|
||||
tags: 'TagList',
|
||||
externalDocs: 'ExternalDocs',
|
||||
},
|
||||
};
|
||||
|
||||
const Server: NodeType = {
|
||||
properties: {
|
||||
host: { type: 'string' },
|
||||
pathname: { type: 'string' },
|
||||
protocol: { type: 'string' },
|
||||
protocolVersion: { type: 'string' },
|
||||
description: { type: 'string' },
|
||||
variables: 'ServerVariablesMap',
|
||||
security: 'SecuritySchemeList',
|
||||
bindings: 'ServerBindings',
|
||||
externalDocs: 'ExternalDocs',
|
||||
tags: 'TagList',
|
||||
},
|
||||
required: ['host', 'protocol'],
|
||||
};
|
||||
|
||||
const Info: NodeType = {
|
||||
properties: {
|
||||
title: { type: 'string' },
|
||||
version: { type: 'string' },
|
||||
description: { type: 'string' },
|
||||
termsOfService: { type: 'string' },
|
||||
contact: 'Contact',
|
||||
license: 'License',
|
||||
tags: 'TagList',
|
||||
externalDocs: 'ExternalDocs',
|
||||
},
|
||||
required: ['title', 'version'],
|
||||
};
|
||||
|
||||
const Parameter: NodeType = {
|
||||
properties: {
|
||||
description: { type: 'string' },
|
||||
enum: { type: 'array', items: { type: 'string' } },
|
||||
default: { type: 'string' },
|
||||
examples: { type: 'array', items: { type: 'string' } },
|
||||
location: { type: 'string' },
|
||||
},
|
||||
};
|
||||
|
||||
const Message: NodeType = {
|
||||
properties: {
|
||||
headers: 'Schema',
|
||||
payload: (value: Record<string, unknown>) => {
|
||||
if (!!value && value?.['schemaFormat']) {
|
||||
return {
|
||||
properties: {
|
||||
schema: 'Schema',
|
||||
schemaFormat: { type: 'string' },
|
||||
},
|
||||
required: ['schema', 'schemaFormat'],
|
||||
};
|
||||
} else {
|
||||
return 'Schema';
|
||||
}
|
||||
},
|
||||
correlationId: 'CorrelationId',
|
||||
|
||||
contentType: { type: 'string' },
|
||||
name: { type: 'string' },
|
||||
title: { type: 'string' },
|
||||
summary: { type: 'string' },
|
||||
description: { type: 'string' },
|
||||
tags: 'TagList',
|
||||
externalDocs: 'ExternalDocs',
|
||||
bindings: 'MessageBindings',
|
||||
examples: 'MessageExampleList',
|
||||
traits: 'MessageTraitList',
|
||||
},
|
||||
additionalProperties: {},
|
||||
};
|
||||
|
||||
const OperationTrait: NodeType = {
|
||||
properties: {
|
||||
tags: 'TagList',
|
||||
title: { type: 'string' },
|
||||
summary: { type: 'string' },
|
||||
description: { type: 'string' },
|
||||
externalDocs: 'ExternalDocs',
|
||||
security: 'SecuritySchemeList',
|
||||
|
||||
bindings: 'OperationBindings',
|
||||
},
|
||||
required: [],
|
||||
};
|
||||
|
||||
const MessageTrait: NodeType = {
|
||||
properties: {
|
||||
headers: (value: unknown) => {
|
||||
if (typeof value === 'function' || (typeof value === 'object' && !!value)) {
|
||||
return {
|
||||
properties: {
|
||||
schema: 'Schema',
|
||||
schemaFormat: { type: 'string' },
|
||||
},
|
||||
};
|
||||
} else {
|
||||
return 'Schema';
|
||||
}
|
||||
},
|
||||
correlationId: 'CorrelationId',
|
||||
|
||||
contentType: { type: 'string' },
|
||||
name: { type: 'string' },
|
||||
title: { type: 'string' },
|
||||
summary: { type: 'string' },
|
||||
description: { type: 'string' },
|
||||
tags: 'TagList',
|
||||
externalDocs: 'ExternalDocs',
|
||||
bindings: 'MessageBindings',
|
||||
examples: 'MessageExampleList',
|
||||
},
|
||||
additionalProperties: {},
|
||||
};
|
||||
|
||||
const Operation: NodeType = {
|
||||
properties: {
|
||||
action: { type: 'string', enum: ['send', 'receive'] },
|
||||
channel: 'Channel',
|
||||
title: { type: 'string' },
|
||||
tags: 'TagList',
|
||||
summary: { type: 'string' },
|
||||
description: { type: 'string' },
|
||||
externalDocs: 'ExternalDocs',
|
||||
operationId: { type: 'string' },
|
||||
security: 'SecuritySchemeList',
|
||||
|
||||
bindings: 'OperationBindings',
|
||||
traits: 'OperationTraitList',
|
||||
messages: 'MessageList',
|
||||
reply: 'OperationReply',
|
||||
},
|
||||
required: ['action', 'channel'],
|
||||
};
|
||||
|
||||
const OperationReply: NodeType = {
|
||||
properties: {
|
||||
channel: 'Channel',
|
||||
messages: 'MessageList',
|
||||
address: 'OperationReplyAddress',
|
||||
},
|
||||
};
|
||||
|
||||
const OperationReplyAddress: NodeType = {
|
||||
properties: {
|
||||
location: { type: 'string' },
|
||||
description: { type: 'string' },
|
||||
},
|
||||
required: ['location'],
|
||||
};
|
||||
|
||||
const Components: NodeType = {
|
||||
properties: {
|
||||
messages: 'NamedMessages',
|
||||
parameters: 'NamedParameters',
|
||||
schemas: 'NamedSchemas',
|
||||
replies: 'NamedOperationReplies',
|
||||
replyAddresses: 'NamedOperationRelyAddresses',
|
||||
correlationIds: 'NamedCorrelationIds',
|
||||
messageTraits: 'NamedMessageTraits',
|
||||
operationTraits: 'NamedOperationTraits',
|
||||
tags: 'NamedTags',
|
||||
externalDocs: 'NamedExternalDocs',
|
||||
securitySchemes: 'NamedSecuritySchemes',
|
||||
servers: 'ServerMap',
|
||||
serverVariables: 'ServerVariablesMap',
|
||||
channels: 'NamedChannels',
|
||||
operations: 'NamedOperations',
|
||||
serverBindings: 'ServerBindings',
|
||||
channelBindings: 'ChannelBindings',
|
||||
operationBindings: 'OperationBindings',
|
||||
messageBindings: 'MessageBindings',
|
||||
},
|
||||
};
|
||||
|
||||
const ImplicitFlow: NodeType = {
|
||||
properties: {
|
||||
refreshUrl: { type: 'string' },
|
||||
availableScopes: { type: 'object', additionalProperties: { type: 'string' } },
|
||||
authorizationUrl: { type: 'string' },
|
||||
},
|
||||
required: ['authorizationUrl', 'availableScopes'],
|
||||
};
|
||||
|
||||
const PasswordFlow: NodeType = {
|
||||
properties: {
|
||||
refreshUrl: { type: 'string' },
|
||||
availableScopes: { type: 'object', additionalProperties: { type: 'string' } },
|
||||
tokenUrl: { type: 'string' },
|
||||
},
|
||||
required: ['tokenUrl', 'availableScopes'],
|
||||
};
|
||||
|
||||
const ClientCredentials: NodeType = {
|
||||
properties: {
|
||||
refreshUrl: { type: 'string' },
|
||||
availableScopes: { type: 'object', additionalProperties: { type: 'string' } },
|
||||
tokenUrl: { type: 'string' },
|
||||
},
|
||||
required: ['tokenUrl', 'availableScopes'],
|
||||
};
|
||||
|
||||
const AuthorizationCode: NodeType = {
|
||||
properties: {
|
||||
refreshUrl: { type: 'string' },
|
||||
authorizationUrl: { type: 'string' },
|
||||
availableScopes: { type: 'object', additionalProperties: { type: 'string' } },
|
||||
tokenUrl: { type: 'string' },
|
||||
},
|
||||
required: ['authorizationUrl', 'tokenUrl', 'availableScopes'],
|
||||
};
|
||||
|
||||
const SecurityScheme: NodeType = {
|
||||
properties: {
|
||||
type: {
|
||||
enum: [
|
||||
'userPassword',
|
||||
'apiKey',
|
||||
'X509',
|
||||
'symmetricEncryption',
|
||||
'asymmetricEncryption',
|
||||
'httpApiKey',
|
||||
'http',
|
||||
'oauth2',
|
||||
'openIdConnect',
|
||||
'plain',
|
||||
'scramSha256',
|
||||
'scramSha512',
|
||||
'gssapi',
|
||||
],
|
||||
},
|
||||
description: { type: 'string' },
|
||||
name: { type: 'string' },
|
||||
in: { type: 'string', enum: ['query', 'header', 'cookie', 'user', 'password'] },
|
||||
scheme: { type: 'string' },
|
||||
bearerFormat: { type: 'string' },
|
||||
flows: 'SecuritySchemeFlows',
|
||||
openIdConnectUrl: { type: 'string' },
|
||||
scopes: { type: 'array', items: { type: 'string' } },
|
||||
},
|
||||
required(value) {
|
||||
switch (value?.type) {
|
||||
case 'apiKey':
|
||||
return ['type', 'in'];
|
||||
case 'httpApiKey':
|
||||
return ['type', 'name', 'in'];
|
||||
case 'http':
|
||||
return ['type', 'scheme'];
|
||||
case 'oauth2':
|
||||
return ['type', 'flows'];
|
||||
case 'openIdConnect':
|
||||
return ['type', 'openIdConnectUrl'];
|
||||
default:
|
||||
return ['type'];
|
||||
}
|
||||
},
|
||||
allowed(value) {
|
||||
switch (value?.type) {
|
||||
case 'apiKey':
|
||||
return ['type', 'in', 'description'];
|
||||
case 'httpApiKey':
|
||||
return ['type', 'name', 'in', 'description'];
|
||||
case 'http':
|
||||
return ['type', 'scheme', 'bearerFormat', 'description'];
|
||||
case 'oauth2':
|
||||
return ['type', 'flows', 'description', 'scopes'];
|
||||
case 'openIdConnect':
|
||||
return ['type', 'openIdConnectUrl', 'description', 'scopes'];
|
||||
default:
|
||||
return ['type', 'description'];
|
||||
}
|
||||
},
|
||||
extensionsPrefix: 'x-',
|
||||
};
|
||||
|
||||
export const AsyncApi3Types: Record<string, NodeType> = {
|
||||
// from asyncapi2
|
||||
...AsyncApi2Bindings,
|
||||
CorrelationId,
|
||||
SecuritySchemeFlows,
|
||||
ServerVariable,
|
||||
Contact,
|
||||
License,
|
||||
MessageExample,
|
||||
Tag,
|
||||
Dependencies,
|
||||
Schema,
|
||||
Discriminator,
|
||||
DiscriminatorMapping,
|
||||
SchemaProperties,
|
||||
ServerMap,
|
||||
ExternalDocs,
|
||||
Root,
|
||||
|
||||
Channel,
|
||||
Parameter,
|
||||
Info,
|
||||
Server,
|
||||
MessageTrait,
|
||||
Operation,
|
||||
OperationReply,
|
||||
OperationReplyAddress,
|
||||
Components,
|
||||
ImplicitFlow,
|
||||
PasswordFlow,
|
||||
ClientCredentials,
|
||||
AuthorizationCode,
|
||||
SecurityScheme,
|
||||
Message,
|
||||
OperationTrait,
|
||||
ServerVariablesMap: mapOf('ServerVariable'),
|
||||
NamedTags: mapOf('Tag'),
|
||||
NamedExternalDocs: mapOf('ExternalDocs'),
|
||||
NamedChannels: mapOf('Channel'),
|
||||
ParametersMap: mapOf('Parameter'),
|
||||
NamedOperations: mapOf('Operation'),
|
||||
NamedOperationReplies: mapOf('OperationReply'),
|
||||
NamedOperationRelyAddresses: mapOf('OperationReplyAddress'),
|
||||
NamedSchemas: mapOf('Schema'),
|
||||
NamedMessages: mapOf('Message'),
|
||||
NamedMessageTraits: mapOf('MessageTrait'),
|
||||
NamedOperationTraits: mapOf('OperationTrait'),
|
||||
NamedParameters: mapOf('Parameter'),
|
||||
NamedSecuritySchemes: mapOf('SecurityScheme'),
|
||||
NamedCorrelationIds: mapOf('CorrelationId'),
|
||||
ServerList: listOf('Server'),
|
||||
SecuritySchemeList: listOf('SecurityScheme'),
|
||||
MessageList: listOf('Message'),
|
||||
OperationTraitList: listOf('OperationTrait'),
|
||||
MessageTraitList: listOf('MessageTrait'),
|
||||
MessageExampleList: listOf('MessageExample'),
|
||||
TagList: listOf('Tag'),
|
||||
};
|
||||
@@ -92,8 +92,20 @@ const builtInAsync2Rules = [
|
||||
'no-channel-trailing-slash',
|
||||
] as const;
|
||||
|
||||
const builtInAsync3Rules = [
|
||||
'spec',
|
||||
'info-contact',
|
||||
'operation-operationId',
|
||||
'tag-description',
|
||||
'tags-alphabetical',
|
||||
'channels-kebab-case',
|
||||
'no-channel-trailing-slash',
|
||||
] as const;
|
||||
|
||||
export type BuiltInAsync2RuleId = typeof builtInAsync2Rules[number];
|
||||
|
||||
export type BuiltInAsync3RuleId = typeof builtInAsync3Rules[number];
|
||||
|
||||
const builtInArazzoRules = ['spec'] as const;
|
||||
|
||||
export type BuiltInArazzoRuleId = typeof builtInArazzoRules[number];
|
||||
@@ -103,6 +115,7 @@ const builtInRules = [
|
||||
...builtInOAS2Rules,
|
||||
...builtInOAS3Rules,
|
||||
...builtInAsync2Rules,
|
||||
...builtInAsync3Rules,
|
||||
...builtInArazzoRules,
|
||||
] as const;
|
||||
|
||||
|
||||
61
packages/core/src/typings/asyncapi3.ts
Normal file
61
packages/core/src/typings/asyncapi3.ts
Normal file
@@ -0,0 +1,61 @@
|
||||
export interface Async3Definition {
|
||||
asyncapi: string;
|
||||
servers?: Record<string, any>;
|
||||
info: Async3Info;
|
||||
channels?: Record<string, Channel>;
|
||||
components?: Record<string, any>;
|
||||
operations?: Record<string, any>;
|
||||
defaultContentType?: string;
|
||||
}
|
||||
|
||||
export interface Async3Info {
|
||||
title: string;
|
||||
version: string;
|
||||
|
||||
description?: string;
|
||||
termsOfService?: string;
|
||||
contact?: Async3Contact;
|
||||
license?: Async3License;
|
||||
tags?: Tag[];
|
||||
externalDocs?: ExternalDoc;
|
||||
}
|
||||
|
||||
export interface Async3Contact {
|
||||
name?: string;
|
||||
url?: string;
|
||||
email?: string;
|
||||
}
|
||||
|
||||
export interface Async3License {
|
||||
name: string;
|
||||
url?: string;
|
||||
}
|
||||
|
||||
export interface Tag {
|
||||
name: string;
|
||||
description?: string;
|
||||
externalDocs?: ExternalDoc;
|
||||
}
|
||||
|
||||
export interface ExternalDoc {
|
||||
url: string;
|
||||
description?: string;
|
||||
}
|
||||
|
||||
export interface Channel {
|
||||
address?: string | null;
|
||||
messages?: Record<string, any>;
|
||||
title?: string;
|
||||
summary?: string;
|
||||
description?: string;
|
||||
servers?: Record<string, any>[];
|
||||
parameters?: Record<string, any>;
|
||||
tags?: Record<string, any>;
|
||||
externalDocs?: ExternalDocumentation;
|
||||
bindings?: Record<string, any>;
|
||||
}
|
||||
|
||||
export interface ExternalDocumentation {
|
||||
url: string;
|
||||
description?: string;
|
||||
}
|
||||
@@ -50,6 +50,7 @@ import type {
|
||||
Oas2SecurityScheme,
|
||||
} from './typings/swagger';
|
||||
import type { Async2Definition } from './typings/asyncapi';
|
||||
import type { Async3Definition } from './typings/asyncapi3';
|
||||
import type { ArazzoDefinition } from './typings/arazzo';
|
||||
|
||||
export type SkipFunctionContext = Pick<
|
||||
@@ -213,6 +214,10 @@ type Async2FlatVisitor = {
|
||||
Root?: VisitFunctionOrObject<Async2Definition>;
|
||||
};
|
||||
|
||||
type Async3FlatVisitor = {
|
||||
Root?: VisitFunctionOrObject<Async3Definition>;
|
||||
};
|
||||
|
||||
type ArazzoFlatVisitor = {
|
||||
Root?: VisitFunctionOrObject<ArazzoDefinition>;
|
||||
};
|
||||
@@ -249,6 +254,12 @@ type Async2NestedVisitor = {
|
||||
: Async2FlatVisitor[T] & NestedVisitor<Async2NestedVisitor>;
|
||||
};
|
||||
|
||||
type Async3NestedVisitor = {
|
||||
[T in keyof Async3FlatVisitor]: Async3FlatVisitor[T] extends Function
|
||||
? Async3FlatVisitor[T]
|
||||
: Async3FlatVisitor[T] & NestedVisitor<Async3NestedVisitor>;
|
||||
};
|
||||
|
||||
type ArazzoNestedVisitor = {
|
||||
[T in keyof ArazzoFlatVisitor]: ArazzoFlatVisitor[T] extends Function
|
||||
? ArazzoFlatVisitor[T]
|
||||
@@ -267,6 +278,10 @@ export type Async2Visitor = BaseVisitor &
|
||||
Async2NestedVisitor &
|
||||
Record<string, VisitFunction<any> | NestedVisitObject<any, Async2NestedVisitor>>;
|
||||
|
||||
export type Async3Visitor = BaseVisitor &
|
||||
Async3NestedVisitor &
|
||||
Record<string, VisitFunction<any> | NestedVisitObject<any, Async3NestedVisitor>>;
|
||||
|
||||
export type ArazzoVisitor = BaseVisitor &
|
||||
ArazzoNestedVisitor &
|
||||
Record<string, VisitFunction<any> | NestedVisitObject<any, ArazzoNestedVisitor>>;
|
||||
@@ -293,14 +308,17 @@ export type NormalizedOasVisitors<T extends BaseVisitor> = {
|
||||
export type Oas3Rule = (options: Record<string, any>) => Oas3Visitor | Oas3Visitor[];
|
||||
export type Oas2Rule = (options: Record<string, any>) => Oas2Visitor | Oas2Visitor[];
|
||||
export type Async2Rule = (options: Record<string, any>) => Async2Visitor | Async2Visitor[];
|
||||
export type Async3Rule = (options: Record<string, any>) => Async3Visitor | Async3Visitor[];
|
||||
export type ArazzoRule = (options: Record<string, any>) => ArazzoVisitor | ArazzoVisitor[];
|
||||
export type Oas3Preprocessor = (options: Record<string, any>) => Oas3Visitor;
|
||||
export type Oas2Preprocessor = (options: Record<string, any>) => Oas2Visitor;
|
||||
export type Async2Preprocessor = (options: Record<string, any>) => Async2Visitor;
|
||||
export type Async3Preprocessor = (options: Record<string, any>) => Async3Visitor;
|
||||
export type ArazzoPreprocessor = (options: Record<string, any>) => ArazzoVisitor;
|
||||
export type Oas3Decorator = (options: Record<string, any>) => Oas3Visitor;
|
||||
export type Oas2Decorator = (options: Record<string, any>) => Oas2Visitor;
|
||||
export type Async2Decorator = (options: Record<string, any>) => Async2Visitor;
|
||||
export type Async3Decorator = (options: Record<string, any>) => Async3Visitor;
|
||||
export type ArazzoDecorator = (options: Record<string, any>) => ArazzoVisitor;
|
||||
|
||||
// alias for the latest version supported
|
||||
|
||||
@@ -173,7 +173,7 @@ channels:
|
||||
description: The Id of the company.
|
||||
additionalProperties: false
|
||||
|
||||
smartylighting/streetlights/1/0/action/{streetlightId}/turn/on:
|
||||
smartylighting/streetlights/1/0/action/{streetlightId}/turn/on/:
|
||||
parameters:
|
||||
streetlightId:
|
||||
$ref: '#/components/parameters/streetlightId'
|
||||
|
||||
31
resources/asyncapi3.yaml
Normal file
31
resources/asyncapi3.yaml
Normal file
@@ -0,0 +1,31 @@
|
||||
asyncapi: 3.0.0
|
||||
info:
|
||||
title: Account Service
|
||||
version: 1.0.0
|
||||
description: This service is in charge of processing user signups
|
||||
channels:
|
||||
userSignedup:
|
||||
address: user/signedup/
|
||||
messages:
|
||||
UserSignedUp:
|
||||
$ref: '#/components/messages/UserSignedUp'
|
||||
operations:
|
||||
sendUserSignedup:
|
||||
action: send
|
||||
channel:
|
||||
$ref: '#/channels/userSignedup'
|
||||
messages:
|
||||
- $ref: '#/channels/userSignedup/messages/UserSignedUp'
|
||||
components:
|
||||
messages:
|
||||
UserSignedUp:
|
||||
payload:
|
||||
type: object
|
||||
properties:
|
||||
displayName:
|
||||
type: string
|
||||
description: Name of the user
|
||||
email:
|
||||
type: string
|
||||
format: email
|
||||
description: Email of the user
|
||||
Reference in New Issue
Block a user