Added postman collection gen example

This commit is contained in:
Dan Brown 2022-02-10 12:53:25 +00:00
commit d22d2eb86f
Signed by: danb
GPG key ID: 46D9F943C24A2EF9
5 changed files with 353 additions and 0 deletions

View file

@ -0,0 +1 @@
*.postman_collection.json

View file

@ -0,0 +1,234 @@
// Libraries used
const axios = require('axios');
// BookStack API variables
// Uses values on the environment unless hardcoded
// To hardcode, add values to the empty strings in the below.
const bookStackConfig = {
base_url: '' || process.env.BS_URL,
token_id: '' || process.env.BS_TOKEN_ID,
token_secret: '' || process.env.BS_TOKEN_SECRET,
};
// Script Logic
////////////////
// Create an axios instance for our API
const api = axios.create({
baseURL: bookStackConfig.base_url.replace(/\/$/, '') + '/api/',
timeout: 5000,
headers: {'Authorization': `Token ${bookStackConfig.token_id}:${bookStackConfig.token_secret}`},
});
// Wrap the rest of our code in an async function, so we can await within.
(async function () {
// Get our default schema structure and look up to BookStack
// to get a JSON view of the BookStack docs.
const postmanSchema = getBaseCollectionSchema();
const {data: docs} = await api.get('/docs.json');
// Cycle over the endpoint categories within the API docs
for (const [category, endpoints] of Object.entries(docs)) {
// Create the schema for the postman collection, which represents
// a BookStack API category.
const postmanFolderSchema = {
name: category.toUpperCase(),
item: [],
};
// Cycle over the endpoints within the category
for (const endpoint of endpoints) {
postmanFolderSchema.item.push(getEndpointSchema(endpoint));
}
// Push our endpoint data into the postman collection
postmanSchema.item.push(postmanFolderSchema);
}
// Output the postman collection data to the command line
console.log(JSON.stringify(postmanSchema, null, 2));
})().catch(err => {
// Handle API errors
if (err.response) {
console.error(`Request failed with status ${err.response.status} [${err.response.statusText}]`);
return;
}
// Output all other errors
console.error(err)
});
/**
* Get the postman collection data for a specific endpoint.
* @param {Object} apiEndpoint
* @return {{request: {method, header: *[]}, response: *[], name: string}}
*/
function getEndpointSchema(apiEndpoint) {
// Create our base format for the postman schema for a single endpoint
const postmanEndpointSchema = {
name: `${apiEndpoint.name}`,
request: {
method: apiEndpoint.method,
header: [],
},
response: []
};
// Create the base format used to represent a URL
const url = {
raw: `{{BASE_URL}}/${apiEndpoint.uri}`,
host: ['{{BASE_URL}}'],
path: apiEndpoint.uri.split('/'),
query: []
};
// If a listing endpoint, add the standard list params,
// although we leave them disabled by default.
if (apiEndpoint.controller_method === 'list') {
url.query = [
{
"key": "count",
"value": "100",
"disabled": true
},
{
"key": "offset",
"value": "0",
"disabled": true
},
{
"key": "sort",
"value": "+name",
"disabled": true
},
{
"key": "filter[id]",
"value": "5",
"disabled": true
}
];
}
// Add the url to the request schema
postmanEndpointSchema.request.url = url;
// Build a description for the endpoint
// Formats the body parameters, if existing, to shown their validations.
const description = [apiEndpoint.description];
if (apiEndpoint.body_params) {
description.push('', '', 'Available body parameters:', '');
for (const [name, validations] of Object.entries(apiEndpoint.body_params)) {
description.push(`${name}: ${validations.join(' :: ')}`);
}
}
postmanEndpointSchema.request.description = description.join('\n');
// If we have an example request, push it as default body JSON data
if (apiEndpoint.example_request) {
postmanEndpointSchema.request.header.push({
"key": "Content-Type",
"value": "application/json"
});
postmanEndpointSchema.request.body = {
mode: "raw",
raw: apiEndpoint.example_request,
options: {
raw: {
language: 'json'
}
}
}
}
// Push an example of a response if we have one
if (apiEndpoint.example_response) {
postmanEndpointSchema.response.push({
name: 'Example Response',
"status": "OK",
"code": 200,
"_postman_previewlanguage": "json",
header: [
{
"key": "Content-Type",
"value": "application/json"
},
],
body: apiEndpoint.example_response,
});
}
// Provide back the postman schema data
return postmanEndpointSchema;
}
/**
* Get the base Postman collection schema data structure.
* Contains auth data and variables.
* @return {{item: *[], auth: {apikey: [{type: string, value: string, key: string},{type: string, value: string, key: string}], type: string}, variable: [{type: string, value: string, key: string},{type: string, value: string, key: string},{type: string, value: string, key: string}], event: [{listen: string, script: {type: string, exec: string[]}},{listen: string, script: {type: string, exec: string[]}}], info: {schema: string, name: string}}}
*/
function getBaseCollectionSchema() {
return {
info: {
name: "BookStack REST API",
schema: "https://schema.getpostman.com/json/collection/v2.1.0/collection.json"
},
item: [
],
auth: {
type: "apikey",
apikey: [
{
key: "value",
value: "Token {{TOKEN_ID}}:{{TOKEN_SECRET}}",
type: "string"
},
{
key: "key",
value: "Authorization",
type: "string"
}
]
},
event: [
{
listen: "prerequest",
script: {
type: "text/javascript",
exec: [
""
]
}
},
{
listen: "test",
script: {
type: "text/javascript",
exec: [
""
]
}
}
],
variable: [
{
key: "TOKEN_ID",
value: "",
type: "default"
},
{
key: "TOKEN_SECRET",
value: "",
type: "default"
},
{
key: "BASE_URL",
value: "",
type: "default"
}
]
};
}

View file

@ -0,0 +1,58 @@
{
"name": "bookstack-generate-postman-collection",
"version": "1.0.0",
"lockfileVersion": 2,
"requires": true,
"packages": {
"": {
"name": "bookstack-generate-postman-collection",
"version": "1.0.0",
"license": "MIT",
"dependencies": {
"axios": "^0.25.0"
}
},
"node_modules/axios": {
"version": "0.25.0",
"resolved": "https://registry.npmjs.org/axios/-/axios-0.25.0.tgz",
"integrity": "sha512-cD8FOb0tRH3uuEe6+evtAbgJtfxr7ly3fQjYcMcuPlgkwVS9xboaVIpcDV+cYQe+yGykgwZCs1pzjntcGa6l5g==",
"dependencies": {
"follow-redirects": "^1.14.7"
}
},
"node_modules/follow-redirects": {
"version": "1.14.8",
"resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.14.8.tgz",
"integrity": "sha512-1x0S9UVJHsQprFcEC/qnNzBLcIxsjAV905f/UkQxbclCsoTWlacCNOpQa/anodLl2uaEKFhfWOvM2Qg77+15zA==",
"funding": [
{
"type": "individual",
"url": "https://github.com/sponsors/RubenVerborgh"
}
],
"engines": {
"node": ">=4.0"
},
"peerDependenciesMeta": {
"debug": {
"optional": true
}
}
}
},
"dependencies": {
"axios": {
"version": "0.25.0",
"resolved": "https://registry.npmjs.org/axios/-/axios-0.25.0.tgz",
"integrity": "sha512-cD8FOb0tRH3uuEe6+evtAbgJtfxr7ly3fQjYcMcuPlgkwVS9xboaVIpcDV+cYQe+yGykgwZCs1pzjntcGa6l5g==",
"requires": {
"follow-redirects": "^1.14.7"
}
},
"follow-redirects": {
"version": "1.14.8",
"resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.14.8.tgz",
"integrity": "sha512-1x0S9UVJHsQprFcEC/qnNzBLcIxsjAV905f/UkQxbclCsoTWlacCNOpQa/anodLl2uaEKFhfWOvM2Qg77+15zA=="
}
}
}

View file

@ -0,0 +1,15 @@
{
"name": "bookstack-generate-postman-collection",
"version": "1.0.0",
"description": "This script will read the BookStack REST API and attempt to build a postman collection from it",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"keywords": [],
"author": "Dan Brown",
"license": "MIT",
"dependencies": {
"axios": "^0.25.0"
}
}

View file

@ -0,0 +1,45 @@
# Generate Postman Collection
This script will scan the BookStack API documentation and generate
out an importable collection for [Postman](https://www.postman.com/).
**Note:** This has been built quite hastily so the output may not be
100% accurate but should massively speed up most use-cases.
[An example of the output can be found here](https://gist.githubusercontent.com/ssddanbrown/de805abfdf1a1defb54500055de5e7ea/raw/7ec246a4d140c98313f3bcda00e1bac6d9e68b68/bs.postman_collection.json).
The output collection will contain a folder for each of the API categories.
Collection variables are used to configure the API base url, token ID
and token secret.
## Requirements
You will need NodeJS installed (Tested on v16, may work on earlier versions).
## Running
First, download all the files in the same directory as this readme to a folder on your system
and run the below from within that directory.
```bash
# Install NodeJS dependencies via NPM
npm install
# Setup
# ALTERNATIVELY: Open the script and add to the empty strings in the variables at the top.
export BS_URL=https://bookstack.example.com # Set to be your BookStack base URL
export BS_TOKEN_ID=abc123 # Set to be your API token_id
export BS_TOKEN_SECRET=123abc # Set to be your API token_secret
# Running the script
node index.js
```
The script outputs stdout on the command line, so you'll most likely want to redirect the output to a file.
## Examples
```bash
# Generate the collection to a 'bookstack.postman_collection.json' file.
node index.js > bookstack.postman_collection.json
```