Ecosyste.ms: Awesome
An open API service indexing awesome lists of open source software.
https://github.com/ahmadnassri/node-oas-request
OAS 3.x dynamic request client
https://github.com/ahmadnassri/node-oas-request
node oas openapi
Last synced: 3 months ago
JSON representation
OAS 3.x dynamic request client
- Host: GitHub
- URL: https://github.com/ahmadnassri/node-oas-request
- Owner: ahmadnassri
- License: mit
- Created: 2020-07-24T06:01:32.000Z (over 4 years ago)
- Default Branch: master
- Last Pushed: 2024-06-17T20:01:32.000Z (7 months ago)
- Last Synced: 2024-10-01T00:06:03.141Z (4 months ago)
- Topics: node, oas, openapi
- Language: JavaScript
- Homepage:
- Size: 539 KB
- Stars: 12
- Watchers: 3
- Forks: 1
- Open Issues: 7
-
Metadata Files:
- Readme: README.md
- Funding: .github/FUNDING.yml
- License: LICENSE
Awesome Lists containing this project
README
# OpenAPI Spec HTTP Client
Feed it a JSON Spec, it will spit out a lightweight HTTP client!
[![license][license-img]][license-url]
[![release][release-img]][release-url]
[![semantic][semantic-img]][semantic-url]## Why
While there are plenty of *"code generators"* for OpenAPI Specification, they create a lot of "garbage" code that you may not need,
and there while there are others that follow a similar path of this library, they still attempt to do too much! *(like request validation before sending)*This library does not concern itself with anything other than constructing an HTTP request and sending it!
FAQ
- **Why no validation?**
You should rely on validation & sanitation at the source of truth: *The API server itself!*- **YAML Support?**
This package **does not** natively support OpenAPI Specification YAML format, but you can easily convert to JSON before calling `oas-rqeuest`
Example###### using [`YAML`][]
``` js
const YAML = require('yaml')
const { readFile } = require('fs/promises')const file = await readFile('openapi.yml', 'utf8')
const spec = YAML.parse(file)
const OASRequest = require('oas-request')(spec)
```###### using [`apidevtools/swagger-cli`][]
``` bash
npx apidevtools/swagger-cli bundle spec/openapi.yml --outfile spec.json
```
## What
Some feature highlights:
- Automatic methods creation
- Path Templating
- uses [`cross-fetch`][] for all HTTP operations## Usage
e.g.
petstore.json
``` json
{
"openapi": "3.0.0",
"info": {
"version": "1.0.0",
"title": "Swagger Petstore"
},
"servers": [
{
"url": "http://petstore.swagger.io/{version}",
"variables": {
"version": {
"description": "api version",
"default": "v1"
}
}
}
],
"paths": {
"/pets": {
"get": {
"operationId": "listPets",
"parameters": [
{
"name": "limit",
"in": "query",
"description": "How many items to return at one time (max 100)",
"required": false,
"schema": {
"type": "integer",
"format": "int32"
}
}
],
"responses": {
"200": {
"description": "A paged array of pets",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Pets"
}
}
}
}
}
},
"post": {
"operationId": "createPets",
"responses": {
"201": {
"description": "Null response"
}
}
}
},
"/pets/{petId}": {
"get": {
"operationId": "showPetById",
"parameters": [
{
"name": "petId",
"in": "path",
"required": true,
"schema": {
"type": "string"
}
}
],
"responses": {
"200": {
"description": "Expected response to a valid request",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Pet"
}
}
}
}
}
}
}
},
"components": {
"schemas": {
"Pet": {
"type": "object",
"required": [
"id",
"name"
],
"properties": {
"id": {
"type": "integer",
"format": "int64"
},
"name": {
"type": "string"
},
"tag": {
"type": "string"
}
}
},
"Pets": {
"type": "array",
"items": {
"$ref": "#/components/schemas/Pet"
}
}
}
}
}
```
``` js
const spec = require('./petstore.json')
const OASRequest = require('oas-request')(spec)// define root server url
const request = new OASRequest({
server: 'http://petstore.swagger.io/v1'
})// or use one from the OpenAPI Specification
const request = new OASRequest({
server: {
url: spec.servers[0].url
// populate values for server (see OpenAPI Specification #4.7.5)
variables: {
version: 'v2'
}
}
})// auto generated methods match OpenAPI Specification "operationId"
await request.listPets()
await request.createPets()
await request.showPetById()
```Advanced Usage
``` js
const spec = require('./petstore.json')
const OASRequest = require('oas-request')(spec)// always use JSON headers
const request = new OASRequest({
server: 'http://petstore.swagger.io/v1'
headers: {
'accept': 'application/json',
'content-type': 'application/json'
}
})// POST with JSON
const body = JSON.stringify(body)
const response = await request.createPets({ body })
const data = await response.json()console.log(data)
```### `new OASRequest(APIOptions)`
Construct a new instance of the API request, returns an Object with auto generated method names matching each of the unique OpenAPI Specification [`operationId`][]
Example
###### `spec.json`
``` json
{
...
"paths": {
"/pets": {
"get": {
"operationId": "listPets",
...
},
"post": {
"operationId": "createPets",
...
}
},
"/pets/{petId}": {
"get": {
"operationId": "showPetById",
...
}
}
}
}
```###### `app.js`
``` js
const spec = require('./petstore.json')
const OASRequest = require('oas-request')(spec)// define root server url
const request = new OASRequest({ server: 'http://petstore.swagger.io/v1' })// auto generated methods match OpenAPI Specification "operationId"
await request.listPets()
await request.createPets()
await request.showPetById()
```#### `APIOptions`
| property | type | required | default | description |
|---------------|------------------|----------|-------------------|-------------------------------------------------------------------------|
| **`client`** | `Function` | ✗ | [`unfetch`][] | a Function that executes the HTTP request. *(see [`clientFunction`][])* |
| **`server`** | `String|Object` | ✗ | `spec.servers[0]` | Root server url String, or [`Server Object`][] |
| **`headers`** | `Object` | ✗ | `{}` | Global HTTP request headers *(used with every request)* |
| **`query`** | `Object` | ✗ | `{}` | Global Query String *(used with every request)* |
| **`params`** | `Object` | ✗ | `{}` | Global [Path Templating][] parameters *(used with every request)* |##### `clientFunction`
a `Function` with the signature: `Function(url, requestOptions)` to execute the HTTP request, the default built-in function uses [`cross-fetch`][], you can customize the client to use whatever HTTP library you prefer.
> **⚠️ Note**:
>
> - `url` is an instance of [`URL`][]
> - `options.query` will be processed to construct the `url`, then deleted.
> - `options.params` will be processed and used in Path Templating, then deleted.Example: always assume JSON
``` js
const spec = require('./petstore.json')
const fetch = require('cross-fetch')
const OASRequest = require('oas-request')(spec)const request = new OASRequest({
client: async function (url, options) {
const response = await fetch(url, {
...options,// always set body to JSON
body: JSON.stringify(options.body),headers: {
...options.headers,
// always set headers to JSON
...{
'accept': 'application/json',
'content-type': 'application/json'
}
}
})// always parse body as JSON
response.data = await response.json()return response
}
})const response = await request.createPet({
body {
id: 1,
name: 'Ruby'
}
})console.log(response.data)
```Example: using
axios
``` js
const spec = require('./petstore.json')
const axios = require('axios')
const OASRequest = require('oas-request')(spec)const request = new OASRequest({
client: async function (URL, options) {
return axios({
...options,
maxRedirects: 10,
url: URL.toString(),
httpsAgent: new https.Agent({ keepAlive: true })
})
}
})const response = await request.createPet({
data: {
id: 1,
name: 'Ruby'
},
timeout: 1000
})
```##### `ServerObject`
> ***⚠️ Note**: This is not the same as OpenAPI Specification's [Server Object][], though it's similarly structured*
| property | type | required | description |
|-----------------|----------|----------|------------------------------------------------------|
| **`url`** | `String` | ✓ | Root server url |
| **`variables`** | `Object` | ✗ | Key-value pairs for server URL template substitution |### `__Operation__(requestOptions)`
- Operation method names are generated from the unique OpenAPI Specification [`operationId`][]
- Operations method will return with a call to the specified [`Client Function`][]#### `requestOptions`
The `requestOptions` Objects maps to [Fetch `init` parameter][] with some special considerations:
- `method` will always be set based on the OpenAPI Specification method for this operation
- `query` is a special property used to construct the final URL
- `params` is a special property used to construct the final URL Path *(Path Templating)*## Full Example
``` js
const spec = require('./petstore.json')
const API = require('oas-request')(spec)// send to httpbin so we can inspect the result
const request = new OASRequest({
server: 'http://petstore.swagger.io/v1',
headers: {
'user-agent': 'my-awsome-api-client',
'x-special-header': 'sent-with-every-request'
}
})await request.listPets({
query: {
limit: 100
}
})await request.getPetById({
params: { petId: 'my-pet' }
headers: {
'x-additional-header': 'this operation needs this'
}
})await request.updatePetById({
params: { petId: 'my-pet' },
body: {
name: "ruby",
isGoodDog: true
}
})
```[`YAML`]: https://www.npmjs.com/package/yaml
[`apidevtools/swagger-cli`]: https://www.npmjs.com/package/@apidevtools/swagger-cli
[`cross-fetch`]: https://github.com/lquixada/cross-fetch
[`operationId`]: http://spec.openapis.org/oas/v3.0.3#operation-object
[`unfetch`]: #clientFunction
[`clientFunction`]: #clientfunction
[`Server Object`]: #serverobject
[Path Templating]: http://spec.openapis.org/oas/v3.0.3#path-templating
[`URL`]: https://developer.mozilla.org/en-US/docs/Web/API/URL
[Server Object]: http://spec.openapis.org/oas/v3.0.3#server-object
[`Client Function`]: clientFunction
[Fetch `init` parameter]: https://developer.mozilla.org/en-US/docs/Web/API/WindowOrWorkerGlobalScope/fetch#parameters----
> Author: [Ahmad Nassri](https://www.ahmadnassri.com/) •
> Twitter: [@AhmadNassri](https://twitter.com/AhmadNassri)[license-url]: LICENSE
[license-img]: https://badgen.net/github/license/ahmadnassri/node-oas-request[release-url]: https://github.com/ahmadnassri/node-oas-request/releases
[release-img]: https://badgen.net/github/release/ahmadnassri/node-oas-request[semantic-url]: https://github.com/ahmadnassri/node-oas-request/actions?query=workflow%3Arelease
[semantic-img]: https://badgen.net/badge/📦/semantically%20released/blue