Ecosyste.ms: Awesome

An open API service indexing awesome lists of open source software.

Awesome Lists | Featured Topics | Projects

https://github.com/advanced-rest-client/electron-amf-service

Electron module that parses APIs using AMF parser
https://github.com/advanced-rest-client/electron-amf-service

Last synced: about 1 month ago
JSON representation

Electron module that parses APIs using AMF parser

Awesome Lists containing this project

README

        

# AMF parsing service for Electron.

This electron module works in the renderer process and handle web events
as described in [API data processing events](https://github.com/advanced-rest-client/api-components-api/blob/master/docs/api-processing-events.md)
of Advanced REST Client documentation.

Allows to safely parse API specification file(s) and report back generated API model.

The API model is an output of [AMF](https://a.ml) parser and json-ld generator.

Currently it supports the following APIs:
- RAML 0.8
- RAML 1.0
- OAS 1.0 (swagger)
- OAS 2.0 (swagger)

Support for OAS 3.0 in AMF's roadmap.

The parsing process is split into two parts. First is API parsing and the second is API resolving process.
The second step is to generate a model that works with API Console as it does not work with
unresolved model.

In Advanced REST Client the API is first parsed and generated unresolved model is stored in
the data store. This model can be later used to initialize the AMF library. Resolved model changes
API model and the original information is lost.
To initialize API Console, ARC then sends the unresolved model back to the parser to
resolve it. This model is never stored in the data store. It is ponly used to
initialize API Console.

## Web based APIs

### Initialization

In the renderer process.

```javascript
const { ElectronAmfService } = require('@advanced-rest-client/electron-amf-service');
const service = new ElectronAmfService();
service.listen();
```

This enables event listeners in the renderer process. Call `unlisten()` to remove the listeners.

### api-process-link event

Handles event dispatched by [advanced-rest-client/exchange-search-panel](https://github.com/advanced-rest-client/exchange-search-panel).
It downloads API asset and parses it using AMF service.

After its done it dispatches `api-data-ready` custom event as the panel do not
handle responses to `api-process-link` event.

**Example**

In the application (renderer process).

```javascript
window.addEventListener('api-data-ready', (e) => {
console.log(e.detail.api); // outputs unresolved AMF model
});

window.addEventListener('process-error', (e) => {
if (e.detail.source === 'amf-service') {
console.log(e.detail.message);
}
});
```

### api-process-file and api-resolve-model event

Event to be dispatched when the user selects a file to parse.
The file can be a single File (Blob) or Buffer.

The library supports API files or compressed zip files.

**Example**

```javascript
async function processApi(file) {
const e = new CustomEvent('api-process-file', {
bubbles: true,
cancelable: true,
detail: {
// blob is a file or blob object. Any file object that is API file.
// It also can be a Buffer
file
}
});
document.body.dispatchEvent(e);
if (!e.defaultPrevented) {
throw new Error('Initialize AMF service first.');
}
return await e.detail.result;
}

async function resolveApi(model, type) {
const e = new CustomEvent('api-resolve-model', {
bubbles: true,
cancelable: true,
detail: {
model,
type
}
});
document.body.dispatchEvent(e);
if (!e.defaultPrevented) {
throw new Error('Initialize AMF service first.');
}
return await e.detail.result;
}
const apiInfo = await processApi(apiFile);
console.log(apiInfo); // Object{ model: '...', type: Object{ type: '...', contentType: '...' } }
const resolvedModel = await resolveApi(apiInfo.model, apiInfo.type);
const model = JSON.parse(resolvedModel);
apiConsole.amf = model;
```

### api-select-entrypoint event

The event dispatched by this library only if the `file` is a zip file.
The service tries to determine which file in unpacked zip file is the APIs entry
point. It does recognize RAML Extensions and Overlays as a main file.
However sometimes it is impossible to determine with 100% certainty which file
should be used. In this case the library dispatches `api-select-entrypoint`
so the app can present a file selector to the user.

The event must be cancelled. Also, whatever user decision is, the promise set on
the `detail.result` property must be resolved so the app can clean up, even if
the user cancelled the UI.

The detail object contains `candidates` property on the detail object which is
a list of file names that has been determined as a candidates to be an entry point.
This list always contains at least 2 items.

**Example**

```javascript
window.addEventListener('api-select-entrypoint', (e) => {
e.preventDefault();
e.detail.result = new Promise((resolve) => {
const {candidates} = e.detail;
const file = await presentOptions(candidates); // a function that renders UI
resolve(file); // file can be undefined, it means that selection has been cancelled.
});
});
```

**The promise should be resolved**. If not it may cause a memory problems.
The service creates temporary files from the zip file or from the buffer. After
it finish it cleans the files. Also, the parser runs in a separate process
so even if it crashes it will not destabilize the browser window. If the
promise is not resolved it may become a zombie process. However, it has a timeout
to kill itself if no job has been scheduled in a set time.

## Direct API

The module naturally exposes function that can be used instead of event API.

The functions are:

- cleanup() - run when you sure you won't need the service
- processApiLink(url) - Downloads and parses remote API
- processApiFile(fileToBuffer) - Parses file / buffer
- processBuffer(buffer) - Parses buffer only

See renderer/electron-amf-service.js for API details.

## Loading state

When the module start processing API data or Exchange asset it dispatches
`process-loading-start` custom event with `message` and `id` property.
Hosting application should handle this event to render any kind of UI indicating
ongoing process. When the program finish it dispatches `process-loading-stop`
custom event with the same `id` used with "start" event.

## API components

This module is part of the API components ecosystem. It is used in Advanced REST
Client project.