Added postman collection gen example
This commit is contained in:
parent
b21899d279
commit
d22d2eb86f
5 changed files with 353 additions and 0 deletions
1
node-generate-postman-collection/.gitignore
vendored
Normal file
1
node-generate-postman-collection/.gitignore
vendored
Normal file
|
|
@ -0,0 +1 @@
|
|||
*.postman_collection.json
|
||||
234
node-generate-postman-collection/index.js
Normal file
234
node-generate-postman-collection/index.js
Normal 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"
|
||||
}
|
||||
]
|
||||
};
|
||||
}
|
||||
58
node-generate-postman-collection/package-lock.json
generated
Normal file
58
node-generate-postman-collection/package-lock.json
generated
Normal 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=="
|
||||
}
|
||||
}
|
||||
}
|
||||
15
node-generate-postman-collection/package.json
Normal file
15
node-generate-postman-collection/package.json
Normal 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"
|
||||
}
|
||||
}
|
||||
45
node-generate-postman-collection/readme.md
Normal file
45
node-generate-postman-collection/readme.md
Normal 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
|
||||
```
|
||||
Loading…
Add table
Add a link
Reference in a new issue