Skip to content

Commit d22d2eb

Browse files
committed
Added postman collection gen example
1 parent b21899d commit d22d2eb

File tree

5 files changed

+353
-0
lines changed

5 files changed

+353
-0
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
*.postman_collection.json
+234
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,234 @@
1+
// Libraries used
2+
const axios = require('axios');
3+
4+
// BookStack API variables
5+
// Uses values on the environment unless hardcoded
6+
// To hardcode, add values to the empty strings in the below.
7+
const bookStackConfig = {
8+
base_url: '' || process.env.BS_URL,
9+
token_id: '' || process.env.BS_TOKEN_ID,
10+
token_secret: '' || process.env.BS_TOKEN_SECRET,
11+
};
12+
13+
// Script Logic
14+
////////////////
15+
16+
// Create an axios instance for our API
17+
const api = axios.create({
18+
baseURL: bookStackConfig.base_url.replace(/\/$/, '') + '/api/',
19+
timeout: 5000,
20+
headers: {'Authorization': `Token ${bookStackConfig.token_id}:${bookStackConfig.token_secret}`},
21+
});
22+
23+
// Wrap the rest of our code in an async function, so we can await within.
24+
(async function () {
25+
26+
// Get our default schema structure and look up to BookStack
27+
// to get a JSON view of the BookStack docs.
28+
const postmanSchema = getBaseCollectionSchema();
29+
const {data: docs} = await api.get('/docs.json');
30+
31+
// Cycle over the endpoint categories within the API docs
32+
for (const [category, endpoints] of Object.entries(docs)) {
33+
// Create the schema for the postman collection, which represents
34+
// a BookStack API category.
35+
const postmanFolderSchema = {
36+
name: category.toUpperCase(),
37+
item: [],
38+
};
39+
40+
// Cycle over the endpoints within the category
41+
for (const endpoint of endpoints) {
42+
postmanFolderSchema.item.push(getEndpointSchema(endpoint));
43+
}
44+
45+
// Push our endpoint data into the postman collection
46+
postmanSchema.item.push(postmanFolderSchema);
47+
}
48+
49+
// Output the postman collection data to the command line
50+
console.log(JSON.stringify(postmanSchema, null, 2));
51+
52+
})().catch(err => {
53+
54+
// Handle API errors
55+
if (err.response) {
56+
console.error(`Request failed with status ${err.response.status} [${err.response.statusText}]`);
57+
return;
58+
}
59+
60+
// Output all other errors
61+
console.error(err)
62+
});
63+
64+
65+
/**
66+
* Get the postman collection data for a specific endpoint.
67+
* @param {Object} apiEndpoint
68+
* @return {{request: {method, header: *[]}, response: *[], name: string}}
69+
*/
70+
function getEndpointSchema(apiEndpoint) {
71+
// Create our base format for the postman schema for a single endpoint
72+
const postmanEndpointSchema = {
73+
name: `${apiEndpoint.name}`,
74+
request: {
75+
method: apiEndpoint.method,
76+
header: [],
77+
},
78+
response: []
79+
};
80+
81+
// Create the base format used to represent a URL
82+
const url = {
83+
raw: `{{BASE_URL}}/${apiEndpoint.uri}`,
84+
host: ['{{BASE_URL}}'],
85+
path: apiEndpoint.uri.split('/'),
86+
query: []
87+
};
88+
89+
// If a listing endpoint, add the standard list params,
90+
// although we leave them disabled by default.
91+
if (apiEndpoint.controller_method === 'list') {
92+
url.query = [
93+
{
94+
"key": "count",
95+
"value": "100",
96+
"disabled": true
97+
},
98+
{
99+
"key": "offset",
100+
"value": "0",
101+
"disabled": true
102+
},
103+
{
104+
"key": "sort",
105+
"value": "+name",
106+
"disabled": true
107+
},
108+
{
109+
"key": "filter[id]",
110+
"value": "5",
111+
"disabled": true
112+
}
113+
];
114+
}
115+
116+
// Add the url to the request schema
117+
postmanEndpointSchema.request.url = url;
118+
119+
// Build a description for the endpoint
120+
// Formats the body parameters, if existing, to shown their validations.
121+
const description = [apiEndpoint.description];
122+
if (apiEndpoint.body_params) {
123+
description.push('', '', 'Available body parameters:', '');
124+
for (const [name, validations] of Object.entries(apiEndpoint.body_params)) {
125+
description.push(`${name}: ${validations.join(' :: ')}`);
126+
}
127+
}
128+
postmanEndpointSchema.request.description = description.join('\n');
129+
130+
// If we have an example request, push it as default body JSON data
131+
if (apiEndpoint.example_request) {
132+
postmanEndpointSchema.request.header.push({
133+
"key": "Content-Type",
134+
"value": "application/json"
135+
});
136+
postmanEndpointSchema.request.body = {
137+
mode: "raw",
138+
raw: apiEndpoint.example_request,
139+
options: {
140+
raw: {
141+
language: 'json'
142+
}
143+
}
144+
}
145+
}
146+
147+
// Push an example of a response if we have one
148+
if (apiEndpoint.example_response) {
149+
postmanEndpointSchema.response.push({
150+
name: 'Example Response',
151+
"status": "OK",
152+
"code": 200,
153+
"_postman_previewlanguage": "json",
154+
header: [
155+
{
156+
"key": "Content-Type",
157+
"value": "application/json"
158+
},
159+
],
160+
body: apiEndpoint.example_response,
161+
});
162+
}
163+
164+
// Provide back the postman schema data
165+
return postmanEndpointSchema;
166+
}
167+
168+
/**
169+
* Get the base Postman collection schema data structure.
170+
* Contains auth data and variables.
171+
* @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}}}
172+
*/
173+
function getBaseCollectionSchema() {
174+
return {
175+
info: {
176+
name: "BookStack REST API",
177+
schema: "https://schema.getpostman.com/json/collection/v2.1.0/collection.json"
178+
},
179+
item: [
180+
],
181+
auth: {
182+
type: "apikey",
183+
apikey: [
184+
{
185+
key: "value",
186+
value: "Token {{TOKEN_ID}}:{{TOKEN_SECRET}}",
187+
type: "string"
188+
},
189+
{
190+
key: "key",
191+
value: "Authorization",
192+
type: "string"
193+
}
194+
]
195+
},
196+
event: [
197+
{
198+
listen: "prerequest",
199+
script: {
200+
type: "text/javascript",
201+
exec: [
202+
""
203+
]
204+
}
205+
},
206+
{
207+
listen: "test",
208+
script: {
209+
type: "text/javascript",
210+
exec: [
211+
""
212+
]
213+
}
214+
}
215+
],
216+
variable: [
217+
{
218+
key: "TOKEN_ID",
219+
value: "",
220+
type: "default"
221+
},
222+
{
223+
key: "TOKEN_SECRET",
224+
value: "",
225+
type: "default"
226+
},
227+
{
228+
key: "BASE_URL",
229+
value: "",
230+
type: "default"
231+
}
232+
]
233+
};
234+
}

node-generate-postman-collection/package-lock.json

+58
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
{
2+
"name": "bookstack-generate-postman-collection",
3+
"version": "1.0.0",
4+
"description": "This script will read the BookStack REST API and attempt to build a postman collection from it",
5+
"main": "index.js",
6+
"scripts": {
7+
"test": "echo \"Error: no test specified\" && exit 1"
8+
},
9+
"keywords": [],
10+
"author": "Dan Brown",
11+
"license": "MIT",
12+
"dependencies": {
13+
"axios": "^0.25.0"
14+
}
15+
}
+45
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
# Generate Postman Collection
2+
3+
This script will scan the BookStack API documentation and generate
4+
out an importable collection for [Postman](https://www.postman.com/).
5+
6+
**Note:** This has been built quite hastily so the output may not be
7+
100% accurate but should massively speed up most use-cases.
8+
9+
[An example of the output can be found here](https://gist.githubusercontent.com/ssddanbrown/de805abfdf1a1defb54500055de5e7ea/raw/7ec246a4d140c98313f3bcda00e1bac6d9e68b68/bs.postman_collection.json).
10+
11+
The output collection will contain a folder for each of the API categories.
12+
Collection variables are used to configure the API base url, token ID
13+
and token secret.
14+
15+
## Requirements
16+
17+
You will need NodeJS installed (Tested on v16, may work on earlier versions).
18+
19+
## Running
20+
21+
First, download all the files in the same directory as this readme to a folder on your system
22+
and run the below from within that directory.
23+
24+
```bash
25+
# Install NodeJS dependencies via NPM
26+
npm install
27+
28+
# Setup
29+
# ALTERNATIVELY: Open the script and add to the empty strings in the variables at the top.
30+
export BS_URL=https://bookstack.example.com # Set to be your BookStack base URL
31+
export BS_TOKEN_ID=abc123 # Set to be your API token_id
32+
export BS_TOKEN_SECRET=123abc # Set to be your API token_secret
33+
34+
# Running the script
35+
node index.js
36+
```
37+
38+
The script outputs stdout on the command line, so you'll most likely want to redirect the output to a file.
39+
40+
## Examples
41+
42+
```bash
43+
# Generate the collection to a 'bookstack.postman_collection.json' file.
44+
node index.js > bookstack.postman_collection.json
45+
```

0 commit comments

Comments
 (0)