Skip to content

Commit c7dfbcf

Browse files
authored
CLOUDP-298233: postman transformation in js (#400)
1 parent 2399fa8 commit c7dfbcf

File tree

2 files changed

+134
-0
lines changed

2 files changed

+134
-0
lines changed

tools/postman/Makefile

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,10 @@ convert_to_collection:
1717
transform_collection:
1818
./scripts/transform-for-api.sh
1919

20+
.PHONY: transform_collection_js
21+
transform_collection_js:
22+
node ./scripts/transform-postman.cjs
23+
2024
.PHONY: transform_collection_test
2125
transform_collection_test:
2226
./scripts/transform-for-api-test.sh
Lines changed: 130 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,130 @@
1+
const fs = require('fs');
2+
const path = require('path');
3+
const _ = require('lodash');
4+
5+
/**
6+
# Prepare collection for Postman API
7+
# Environment variables:
8+
# COLLECTION_FILE_NAME - name of the postman collection file
9+
# COLLECTION_TRANSFORMED_FILE_NAME - name of the transformed collection file
10+
# OPENAPI_FILE_NAME - name of the openapi specification file
11+
# OPENAPI_FOLDER - folder where openapi file is saved
12+
# TMP_FOLDER - folder for temporary files during transformations
13+
# VERSION_FILE_NAME - name of the file where the current version is stored
14+
# DESCRIPTION_FILE - name for the markdown description file
15+
# TOGGLE_INCLUDE_BODY - bool for if generated bodies should be removed or kept
16+
# TOGGLE_ADD_DOCS_LINKS - updates requests with corresponding docs links
17+
# TOKEN_URL_ENV - client credentials auth path to set at the environment level, will not be set if unpopulated
18+
# BASE_URL - the default base url the Postman Collection will use
19+
*/
20+
const COLLECTION_FILE_NAME = process.env.COLLECTION_FILE_NAME || 'collection.json';
21+
const COLLECTION_TRANSFORMED_FILE_NAME = process.env.COLLECTION_TRANSFORMED_FILE_NAME || 'collection-transformed.json';
22+
const OPENAPI_FILE_NAME = process.env.OPENAPI_FILE_NAME || 'atlas-api.json';
23+
const OPENAPI_FOLDER = process.env.OPENAPI_FOLDER || './openapi';
24+
const TMP_FOLDER = process.env.TMP_FOLDER || './tmp';
25+
const VERSION_FILE_NAME = process.env.VERSION_FILE_NAME || 'version.txt';
26+
const DESCRIPTION_FILE = process.env.DESCRIPTION_FILE || './collection-description.md';
27+
const TOGGLE_INCLUDE_BODY = process.env.TOGGLE_INCLUDE_BODY !== 'false';
28+
const TOGGLE_ADD_DOCS_LINKS = process.env.TOGGLE_ADD_DOCS_LINKS === 'true';
29+
const TOKEN_URL_ENV = process.env.TOKEN_URL_ENV || '';
30+
const BASE_URL = process.env.BASE_URL || '';
31+
32+
// Dedicated transformation for postman collection.json file.
33+
const transform = () => {
34+
const currentApiRevision = fs.readFileSync(path.join(OPENAPI_FOLDER, VERSION_FILE_NAME), 'utf8').trim();
35+
let collection = loadJsonFile(path.join(TMP_FOLDER, COLLECTION_FILE_NAME));
36+
37+
console.log(`Wrapping Collection ${COLLECTION_FILE_NAME} in "collection" tag`);
38+
collection = { collection };
39+
40+
console.log('Disabling query params by default');
41+
_.forEach(collection.collection.item, (item) => {
42+
if (item.request && item.request.url && Array.isArray(item.request.url.query)) {
43+
item.request.url.query.forEach((query) => {
44+
query.disabled = true;
45+
});
46+
}
47+
});
48+
49+
console.log('Removing _postman_id');
50+
delete collection.collection.info._postman_id;
51+
52+
console.log('Removing circular references');
53+
const collectionString = JSON.stringify(collection);
54+
const cleanedCollectionString = removeCircularReferences(collectionString);
55+
collection = JSON.parse(cleanedCollectionString);
56+
57+
console.log(`Updating name with version ${currentApiRevision}`);
58+
collection.collection.info.name = `MongoDB Atlas Administration API ${currentApiRevision}`;
59+
60+
console.log('Adding Collection description');
61+
const description = fs.readFileSync(DESCRIPTION_FILE, 'utf8').trim();
62+
_.set(collection, 'collection.info.description.content', description);
63+
64+
console.log('Removing all variables. We use environment for variables instead');
65+
collection.collection.variable = [];
66+
67+
console.log(`Adding baseUrl property ${BASE_URL}`);
68+
collection.collection.variable.push({ key: 'baseUrl', value: BASE_URL });
69+
70+
if (TOGGLE_ADD_DOCS_LINKS) {
71+
console.log('Adding links to docs for each request');
72+
73+
const openapiContent = loadJsonFile(path.join(OPENAPI_FOLDER, OPENAPI_FILE_NAME));
74+
const paths = _.keys(openapiContent.paths);
75+
76+
paths.forEach((pathKey) => {
77+
const methods = _.keys(openapiContent.paths[pathKey]);
78+
methods.forEach((method) => {
79+
const requestInfo = openapiContent.paths[pathKey][method];
80+
const title = requestInfo.summary;
81+
const operationId = requestInfo.operationId;
82+
const tag = _.kebabCase(requestInfo.tags[0]);
83+
84+
const url = `https://mongodb.com/docs/atlas/reference/api-resources-spec/v2/#tag/${tag}/operation/${operationId}`;
85+
86+
const requestItem = _.find(_.flatten(collection.collection.item.map((i) => i.item)), { name: title });
87+
if (requestItem && requestItem.description && requestItem.description.content) {
88+
requestItem.description.content += `\n\nFind out more at ${url}`;
89+
}
90+
});
91+
});
92+
}
93+
94+
if (!TOGGLE_INCLUDE_BODY) {
95+
console.log('Removing generated bodies');
96+
_.forEach(_.flatten(collection.collection.item.map((i) => i.item)), (item) => {
97+
if (item.response) {
98+
item.response.forEach((response) => {
99+
response.body = '';
100+
});
101+
item.request.body = {};
102+
}
103+
});
104+
}
105+
106+
if (TOKEN_URL_ENV) {
107+
console.log(`Adding client credentials auth url variable ${TOKEN_URL_ENV}`);
108+
collection.collection.variable.push({ key: 'clientCredentialsTokenUrl', value: TOKEN_URL_ENV });
109+
}
110+
111+
saveJsonFile(path.join(TMP_FOLDER, COLLECTION_TRANSFORMED_FILE_NAME), collection);
112+
113+
console.log('Transformation complete');
114+
};
115+
116+
function loadJsonFile(filePath) {
117+
const data = fs.readFileSync(filePath, 'utf8');
118+
return JSON.parse(data);
119+
}
120+
121+
function saveJsonFile(filePath, json) {
122+
fs.writeFileSync(filePath, JSON.stringify(json, null, 2), 'utf8');
123+
}
124+
125+
// hack
126+
function removeCircularReferences(jsonStr) {
127+
return jsonStr.replace(/\\"value\\": \\"<Circular reference to #[^>"]* detected>\\"/g, '');
128+
}
129+
130+
transform();

0 commit comments

Comments
 (0)