]> BookStack Code Mirror - api-scripts/commitdiff
Added postman collection gen example
authorDan Brown <redacted>
Thu, 10 Feb 2022 12:53:25 +0000 (12:53 +0000)
committerDan Brown <redacted>
Thu, 10 Feb 2022 12:53:25 +0000 (12:53 +0000)
node-generate-postman-collection/.gitignore [new file with mode: 0644]
node-generate-postman-collection/index.js [new file with mode: 0644]
node-generate-postman-collection/package-lock.json [new file with mode: 0644]
node-generate-postman-collection/package.json [new file with mode: 0644]
node-generate-postman-collection/readme.md [new file with mode: 0644]

diff --git a/node-generate-postman-collection/.gitignore b/node-generate-postman-collection/.gitignore
new file mode 100644 (file)
index 0000000..569e7b9
--- /dev/null
@@ -0,0 +1 @@
+*.postman_collection.json
\ No newline at end of file
diff --git a/node-generate-postman-collection/index.js b/node-generate-postman-collection/index.js
new file mode 100644 (file)
index 0000000..deabb67
--- /dev/null
@@ -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"
+            }
+        ]
+    };
+}
\ No newline at end of file
diff --git a/node-generate-postman-collection/package-lock.json b/node-generate-postman-collection/package-lock.json
new file mode 100644 (file)
index 0000000..a0f1aeb
--- /dev/null
@@ -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=="
+    }
+  }
+}
diff --git a/node-generate-postman-collection/package.json b/node-generate-postman-collection/package.json
new file mode 100644 (file)
index 0000000..e12316d
--- /dev/null
@@ -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"
+  }
+}
diff --git a/node-generate-postman-collection/readme.md b/node-generate-postman-collection/readme.md
new file mode 100644 (file)
index 0000000..ec59ebd
--- /dev/null
@@ -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
+```
\ No newline at end of file
Morty Proxy This is a proxified and sanitized view of the page, visit original site.