Skip to content
New issue

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

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

Already on GitHub? Sign in to your account

Moving AsyncAPI conversion to this repository #5

Merged
merged 20 commits into from
Feb 23, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 9 additions & 0 deletions .editorconfig
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
root = true

[{src,test}/**.{ts,json,js}]
end_of_line = lf
charset = utf-8
trim_trailing_whitespace = true
insert_final_newline = true
indent_style = space
indent_size = 4
13 changes: 13 additions & 0 deletions .eslintrc.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
{
"env": {
"browser": true,
"es6": true,
"node": true,
"jest": true
},
"parserOptions": {
"ecmaVersion": 8
},
"extends": ["eslint:recommended", "prettier"],
"ignorePatterns": ["dist", "node_modules", "bin"]
}
34 changes: 34 additions & 0 deletions .gitattributes
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
# Set default behaviour, in case users don't have core.autocrlf set.
* text=auto

# Explicitly declare text files we want to always be normalized and converted
# to native line endings on checkout.

# Declare files that will always have LF line endings on checkout.
*.c text eol=lf
*.css text eol=lf
*.cpp text eol=lf
.editorconfig text eol=lf
.gitattributes text eol=lf
.gitignore text eol=lf
.gitmodules text eol=lf
*.gyp text eol=lf
*.h text eol=lf
*.hpp text eol=lf
*.js text eol=lf
*.ts text eol=lf
*.json text eol=lf
LICENSE text eol=lf
*.md text eol=lf
*.svg text eol=lf
*.sh text eol=lf

# Declare files that will always have CRLF line endings on checkout.
*.bat text eol=crlf
*.cmd text eol=crlf

# Denote all files that are truly binary and should not be modified.
*.gif binary
*.jpg binary
*.node binary
*.png binary
60 changes: 60 additions & 0 deletions .github/codeql-analysis.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
name: "CodeQL"

on:
push:
branches: ["main"]
pull_request:
# The branches below must be a subset of the branches above
branches: ["main"]
schedule:
- cron: "25 1 * * 6"

jobs:
analyze:
name: Analyze
runs-on: ubuntu-latest
permissions:
actions: read
contents: read
security-events: write

strategy:
fail-fast: false
matrix:
language: ["javascript"]
# CodeQL supports [ 'cpp', 'csharp', 'go', 'java', 'javascript', 'python', 'ruby' ]
# Learn more about CodeQL language support at https://aka.ms/codeql-docs/language-support

steps:
- name: Checkout repository
uses: actions/checkout@v3

# Initializes the CodeQL tools for scanning.
- name: Initialize CodeQL
uses: github/codeql-action/init@v2
with:
languages: ${{ matrix.language }}
# If you wish to specify custom queries, you can do so here or in a config file.
# By default, queries listed here will override any specified in a config file.
# Prefix the list here with "+" to use these queries and those in the config file.

# Details on CodeQL's query packs refer to : https://docs.github.com/en/code-security/code-scanning/automatically-scanning-your-code-for-vulnerabilities-and-errors/configuring-code-scanning#using-queries-in-ql-packs
# queries: security-extended,security-and-quality

# Autobuild attempts to build any compiled languages (C/C++, C#, or Java).
# If this step fails, then you should remove it and run the build manually (see below)
- name: Autobuild
uses: github/codeql-action/autobuild@v2

# ℹ️ Command-line programs to run using the OS shell.
# 📚 See https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions#jobsjob_idstepsrun

# If the Autobuild fails above, remove it and uncomment the following three lines.
# modify them (or add more) to build your code if your project, please refer to the EXAMPLE below for guidance.

# - run: |
# echo "Run, Build Application using script"
# ./location_of_script_within_repo/buildscript.sh

- name: Perform CodeQL Analysis
uses: github/codeql-action/analyze@v2
45 changes: 45 additions & 0 deletions .github/eslint.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
# This workflow uses actions that are not certified by GitHub.
# They are provided by a third-party and are governed by
# separate terms of service, privacy policy, and support
# documentation.
# ESLint is a tool for identifying and reporting on patterns
# found in ECMAScript/JavaScript code.
# More details at https://github.com/eslint/eslint
# and https://eslint.org

name: ESLint

on:
push:
branches: ["main"]
pull_request:
# The branches below must be a subset of the branches above
branches: ["main"]

jobs:
eslint:
name: Run eslint scanning
runs-on: ubuntu-latest
permissions:
contents: read
security-events: write
actions: read # only required for a private repository by github/codeql-action/upload-sarif to get the Action run status
steps:
- name: Checkout code
uses: actions/checkout@v3

- name: Install ESLint
run: |
npm install eslint@8.10.0
npm install @microsoft/eslint-formatter-sarif@2.1.7
npm install eslint-config-prettier@8.8.0

- name: Run ESLint
run: "npm run lint:sarif"
continue-on-error: true

- name: Upload analysis results to GitHub
uses: github/codeql-action/upload-sarif@v2
with:
sarif_file: ./eslint-results.sarif
wait-for-processing: true
28 changes: 28 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
# os
.DS_STORE

# node
node_modules

# dist directory should be included only in the Package but not Repository
dist
out

# logging
logs.json
log.json

# vscode
.vscode/*
!.vscode/templates/

# JetBrains IDEs
.idea

# linting results
eslint-results.sarif

# junit test results # Not relevant until validation comes here
junit-tests.xml
packages/web-new/test-results
packages/web-new/playwright-report
5 changes: 5 additions & 0 deletions .prettierignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
package-lock.json
**/dist
coverage
.nyc_output
**/out
15 changes: 15 additions & 0 deletions .prettierrc.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
{
"trailingComma": "es5",
"printWidth": 120,
"singleQuote": false,
"tabWidth": 4,
"endOfLine": "lf",
"overrides": [
{
"files": "*.yaml",
"options": {
"tabWidth": 2
}
}
]
}
12 changes: 12 additions & 0 deletions LICENSE.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
Copyright (c) 2024 Contributors to the Eclipse Foundation

See the NOTICE file(s) distributed with this work for additional
information regarding copyright ownership.

This program and the accompanying materials are made available under the
terms of the Eclipse Public License v. 2.0 which is available at
<http://www.eclipse.org/legal/epl-2.0>, or the W3C Software Notice and
Document License (2015-05-13) which is available at
<https://www.w3.org/Consortium/Legal/2015/copyright-software-and-document>.

SPDX-License-Identifier: EPL-2.0 OR W3C-20150513
22 changes: 11 additions & 11 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,18 +7,18 @@
</h1>

The goal of this repository is to contain different tools for Thing Descriptions and Thing Models.
Currently, they are scattered in different Thingweb repositories and packages and they will be moved here.
Currently, they are scattered in different Thingweb repositories and packages and they will be moved here.

The list of all tools:
- TD Validation: https://github.com/eclipse-thingweb/playground/tree/master/packages/core . Also in node-wot via simple AJV/Schema plus sanity checks on forms.
- Thing Model helpers to resolve sub TMs: https://github.com/eclipse-thingweb/node-wot/blob/master/packages/td-tools/src/thing-model-helpers.ts
- AAS AID <-> TD converter: https://github.com/eclipse-thingweb/node-wot/tree/master/packages/td-tools/src/util
- Default addition or removal for TDs: https://github.com/eclipse-thingweb/playground/tree/master/packages/defaults
- JSON Schema based "spell checker" to find mistakes in a TD: https://github.com/eclipse-thingweb/playground/tree/master/packages/json-spell-checker
- TD to OpenAPI converter: https://github.com/eclipse-thingweb/playground/tree/master/packages/td_to_openAPI
- TD to AsyncAPI converter: https://github.com/eclipse-thingweb/playground/tree/master/packages/td_to_asyncapi
- Feature/Assertion detecter for TDs: https://github.com/eclipse-thingweb/playground/tree/master/packages/assertions (will be moved to W3C Thing Description Repository)

- TD Validation: https://github.com/eclipse-thingweb/playground/tree/master/packages/core . Also in node-wot via simple AJV/Schema plus sanity checks on forms.
- Thing Model helpers to resolve sub TMs: https://github.com/eclipse-thingweb/node-wot/blob/master/packages/td-tools/src/thing-model-helpers.ts
- AAS AID <-> TD converter: https://github.com/eclipse-thingweb/node-wot/tree/master/packages/td-tools/src/util
- Default addition or removal for TDs: https://github.com/eclipse-thingweb/playground/tree/master/packages/defaults
- JSON Schema based "spell checker" to find mistakes in a TD: https://github.com/eclipse-thingweb/playground/tree/master/packages/json-spell-checker
- TD to OpenAPI converter: https://github.com/eclipse-thingweb/playground/tree/master/packages/td_to_openAPI
- TD to AsyncAPI converter: https://github.com/eclipse-thingweb/playground/tree/master/packages/td_to_asyncapi
- Feature/Assertion detecter for TDs: https://github.com/eclipse-thingweb/playground/tree/master/packages/assertions (will be moved to W3C Thing Description Repository)

> **Warning**
> When transferring we should avoid circular dependencies.

> When transferring we should avoid circular dependencies.
2 changes: 2 additions & 0 deletions node/async-api-converter/.npmignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
# empty ignore file, to include the "dist" directory in the package
out
78 changes: 78 additions & 0 deletions node/async-api-converter/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
# Eclipse Thingweb - TD to AsyncAPI Converter

The package provides support for AsyncAPI instance generation (output as `json` or `yaml`), using a Thing Description (TD) as input.

## Usage

You can use this package to integrate AsyncAPI instance generation from a TD in your application.

- Install this package via NPM (`npm install @thingweb/async-api-converter`) (or clone the repo, change to `node/async-api-converter` and install the package with `npm install`)
- Node.js or Browser import:

- Node.js: Require the package and use the functions

```javascript
const tdToAsyncAPI = require("@thingweb/async-api-converter");
```

- Browser: Import the `tdToAsyncAPI` object as a global by adding a script tag to your HTML.

```html
<script src="./node_modules/@thingweb/async-api-converter/dist/web-bundle.min.js"></script>
```

- Now you can convert a TD to an AsyncAPI instance.

```javascript
tdToAsyncAPI(td).then((AsyncAPI) => {
console.log(JSON.stringify(AsyncAPI.json, undefined, 2));
console.log(AsyncAPI.yaml);
});
```

You can find usage examples in the [tests folder](./tests/), or the [web] and [cli] packages.

## License

Licensed under the Eclipse or W3C license, see [License](https://github.com/eclipse-thingweb/td-tools/blob/main/LICENSE.md).

## Limitations

This conversion package should be seen as a first draft.
It is currently limited to the **MQTT** protocol and converting observable properties or subscribable events of a Thing Description instance to channels of an AsyncAPI instance.
Furthermore, it converts some general information about the documents, e.g., an `id` if available.
Due to the structure of both specifications, there occur other limitations, e.g., an AsyncAPI document does not allow specifying servers only for some channels or security restrictions for specific channels/operations/messages.

## Possible Extensions

Resulting of the current Limitations there are possible extensions for the future:

- Supporting HTTP:
Both the TD and the AsyncAPI specification support describing http-based operations but they are doing so in a quite different way, which is the tricky part if one wants to convert from one to another.
The Thing Description supports HTTP for asynchronous and synchronous messages.
In AsyncAPI, the HTTP protocol is always mentioned to support "HTTP streaming APIs".
The specification does not mention certain subprotocols but allows defining HTTP messages (as request/response and with the method) so one way of converting could be to specify necessary messages for every subprotocol.
Still, this does probably not represent the real implementations properly.

- Supporting WebSockets:
AsyncAPI treats WebSocket connections as independent protocols with given restrictions, e.g., only one WebSocket connection is possible per AsyncAPI instance (because routing channels to certain servers is not possible and WebSocket does not support channels/topics/...).
This should be taken into account for the conversion, one promising approach for converting protocols other than MQTT-like, could be to generate one AsyncAPI instance per available server to deal with the in this case more expressive TDs.
- Adding security support:
The focus of AsyncAPI is hardly on security (since event-based solutions are often used in closed systems) but still it supports quite some mechanisms.
The more complicated part in converting this from TD to AsyncAPI is that TDs support different security mechanisms for every operation, while AsyncAPI allows only defining them per Server (and there is no server-to-channel/operation/message mapping).

- Add further use cases:
Currently, only two types of TD interactions are mapped to their AsyncAPI equivalents:

- Properties with the op `observeproperty` indicating that the property can be watched asynchronously
- Events to which a client can subscribe (`subscribeevent`)

But there could be other use cases that should be taken into account, e.g., reading (possible with retain option) variables via MQTT that might not be an asynchronous operation itself but useful to support since MQTT operations cannot be represented with OpenAPI instances.

- Think about how to treat interactions with the same path (-> same AsyncAPI channel), e.g., a property and an event that both interact with `thing.example.com/status`

## Comments

A TD doesn't necessarily to be valid to be converted to an AsyncAPI instance.
This converter will only throw an Error if the invalid part has a strong effect on the conversion result, but tries to ignore the most cases.
This is by purpose, since there is the possibility to validate a TD using, e.g., the playground core package and the conversion of experimental TDs for example to create new TD features, should be supported.
Loading