mirror of
https://github.com/LukeHagar/api-specs.git
synced 2025-12-06 12:27:48 +00:00
added all checks
This commit is contained in:
2
postman-script/partialUpdate/.gitignore
vendored
2
postman-script/partialUpdate/.gitignore
vendored
@@ -1,2 +0,0 @@
|
||||
.env
|
||||
node_modules
|
||||
@@ -1,507 +0,0 @@
|
||||
// Deploy collection inncrementally
|
||||
// ---------------------------------------------------------------
|
||||
// Cycle through the collection objects and deploy them one by one
|
||||
// ---------------------------------------------------------------
|
||||
// Folders -> Requests -> Responses
|
||||
// ---------------------------------------------------------------
|
||||
// An updated object has a different id.
|
||||
// If the id matches, then the object is unchanged.
|
||||
// If the id does not match, then the object is new.
|
||||
// In the end delete all objects that are not in the updated collection.
|
||||
// Sort the objects and update the parent order property.
|
||||
// ---------------------------------------------------------------
|
||||
// Except for folders which would force the update of the entire collection.
|
||||
// ---------------------------------------------------------------
|
||||
|
||||
const pmConvert = require('./PostmanCovertions')
|
||||
const pmAPI = require('./postmanAPI')
|
||||
var crypto = require('crypto');
|
||||
const { GenID } = require('./Utils')
|
||||
|
||||
const deployIncremental = async (privateRemoteCollectionId, localCollection, publicRemoteCollectionId) => {
|
||||
let remoteCollection = await refreshRemoteCollection(privateRemoteCollectionId)
|
||||
|
||||
console.log('Incremental deployment of collection ', localCollection.info.name)
|
||||
|
||||
// const collectioHeadHasChanged =
|
||||
await upadteCollectionHead(remoteCollection, localCollection)
|
||||
|
||||
remoteCollection = await refreshRemoteCollection(privateRemoteCollectionId)
|
||||
|
||||
// const foldersHaveChanged =
|
||||
await mergeFolders(remoteCollection, localCollection)
|
||||
|
||||
remoteCollection = await refreshRemoteCollection(privateRemoteCollectionId)
|
||||
|
||||
// const requestsHaveChanged =
|
||||
await mergeRequests(remoteCollection, localCollection)
|
||||
|
||||
remoteCollection = await refreshRemoteCollection(privateRemoteCollectionId)
|
||||
|
||||
// const responsesHaveChanged =
|
||||
await mergeResponses(remoteCollection, localCollection)
|
||||
|
||||
// should we always merge into the public collection?
|
||||
// There is teh case that if an error happens in the merge phase
|
||||
// the private collection is fully updated
|
||||
// and in the next run the public collection will NOT be updated
|
||||
// because there are no changes in the private collection
|
||||
|
||||
// if (!(collectioHeadHasChanged || foldersHaveChanged || requestsHaveChanged || responsesHaveChanged)) {
|
||||
// console.log('Incremental deployment of collection ', localCollection.info.name, ' completed\n\n')
|
||||
// return
|
||||
// }
|
||||
const msg = 'Merging to public collection'
|
||||
console.log('\n' + msg + '...')
|
||||
await new pmAPI.Collection(privateRemoteCollectionId).merge(publicRemoteCollectionId)
|
||||
.then(() => { console.log(msg, '-> OK\n') })
|
||||
.catch((error) => {
|
||||
console.log(msg, '-> FAIL')
|
||||
handlePostmanAPIError(error)
|
||||
})
|
||||
console.log('Incremental deployment of collection ', localCollection.info.name, ' completed\n\n')
|
||||
}
|
||||
|
||||
async function upadteCollectionHead (remoteCollection, localCollection) {
|
||||
// the colelction head shoul dbe updated if there are changes in
|
||||
// Authorization
|
||||
// Pre-request Script
|
||||
// Tests
|
||||
// Variables
|
||||
|
||||
const localEmptyCollection = { ...localCollection }
|
||||
localEmptyCollection.item = []
|
||||
|
||||
// Check changes in info
|
||||
const hasChangesInfo = checkInfoChanges(remoteCollection, localCollection)
|
||||
|
||||
// Check if there are changes in the Authorization
|
||||
const hasChangesAuth = checkObjectChanges(remoteCollection.collection.auth, localEmptyCollection.auth)
|
||||
|
||||
// Check if there are changes in the Scripts (pre-request and tests)
|
||||
const hasChangesPreRequestScript = checkScriptChanges('prerequest', remoteCollection, localEmptyCollection)
|
||||
|
||||
const hasChangesTestScript = checkScriptChanges('test', remoteCollection, localEmptyCollection)
|
||||
|
||||
// Check if there are changes in the Variables
|
||||
const hasChangesVariables = checkVariableChanges(remoteCollection, localEmptyCollection)
|
||||
|
||||
const hasFolderSortChanges = checkFolderSortChanges(remoteCollection, localCollection)
|
||||
|
||||
const hasChanges = (
|
||||
hasFolderSortChanges ||
|
||||
hasChangesInfo ||
|
||||
hasChangesAuth ||
|
||||
hasChangesPreRequestScript ||
|
||||
hasChangesTestScript ||
|
||||
hasChangesVariables
|
||||
)
|
||||
|
||||
if (hasChanges) {
|
||||
const msg = 'Updating collection head'
|
||||
console.log('\n' + msg + '...')
|
||||
await new pmAPI.Collection(remoteCollection.collection.info.uid)
|
||||
.update({ collection: localEmptyCollection })
|
||||
.then(() => { console.log(msg, '-> OK\n') })
|
||||
.catch((error) => {
|
||||
console.log(msg, '-> FAIL')
|
||||
handlePostmanAPIError(error)
|
||||
})
|
||||
}
|
||||
return hasChanges
|
||||
}
|
||||
|
||||
const checkFolderSortChanges = (remoteCollection, localCollection) => {
|
||||
const remoteFolders = remoteCollection.collection.item
|
||||
.map(folder => ({ id: folder.id }))
|
||||
const localFolders = localCollection.item
|
||||
.filter(folder => !folder.folder)
|
||||
.map(folder => ({ id: folder.id }))
|
||||
|
||||
const remoteFoldersHash = GenID(JSON.stringify(remoteFolders))
|
||||
const localFoldersHash = GenID(JSON.stringify(localFolders))
|
||||
|
||||
return remoteFoldersHash !== localFoldersHash
|
||||
}
|
||||
|
||||
const checkInfoChanges = (remoteCollection, localEmptyCollection) => {
|
||||
// collection info does not have a specific id
|
||||
// so we need to generate a hash and compare them
|
||||
// The hash is only beig generated for name, description and schema
|
||||
|
||||
const { name, description, schema } = remoteCollection.collection.info
|
||||
const remoteInfo = { name, description, schema }
|
||||
|
||||
const { name: localName, description: localDescription, schema: localSchema } = localEmptyCollection.info
|
||||
const localInfo = { name: localName, description: localDescription, schema: localSchema }
|
||||
|
||||
const remoteInfoHash = calculateHash(JSON.stringify(remoteInfo))
|
||||
const localInfoHash = calculateHash(JSON.stringify(localInfo))
|
||||
|
||||
return remoteInfoHash !== localInfoHash
|
||||
}
|
||||
|
||||
const checkObjectChanges = (remoteCollectionObject, localCollectionObject) => {
|
||||
if (!remoteCollectionObject && !localCollectionObject) {
|
||||
return false
|
||||
}
|
||||
if (!remoteCollectionObject || !localCollectionObject) {
|
||||
return true
|
||||
}
|
||||
|
||||
// certain object like auth do not have an id,
|
||||
// so we need to generate on and compare them
|
||||
const remoteCollectionAuthID = GenID(JSON.stringify(remoteCollectionObject))
|
||||
const localCollectionAuthID = GenID(JSON.stringify(localCollectionObject))
|
||||
return remoteCollectionAuthID !== localCollectionAuthID
|
||||
}
|
||||
|
||||
const checkScriptChanges = (scriptType, remoteCollection, localCollection) => {
|
||||
// RB 2020-10-20: The collection may be empty or have no events at all
|
||||
let remoteScript = null
|
||||
let localScript = null
|
||||
if (remoteCollection.collection.event) {
|
||||
remoteScript = remoteCollection.collection.event.find(event => event.listen === scriptType)
|
||||
}
|
||||
|
||||
if (localCollection.event) {
|
||||
localScript = localCollection.event.find(event => event.listen === scriptType)
|
||||
}
|
||||
|
||||
// const remoteScript = remoteCollection.collection.event.find(event => event.listen === scriptType)
|
||||
// const localScript = localCollection.event.find(event => event.listen === scriptType)
|
||||
|
||||
if (!remoteScript && !localScript) {
|
||||
return false
|
||||
}
|
||||
if (!remoteScript || !localScript) {
|
||||
return true
|
||||
}
|
||||
// files can be big, so we hash them
|
||||
const remoteHash = calculateHash(remoteScript.script.exec[0])
|
||||
const localHash = calculateHash(localScript.script.exec[0])
|
||||
|
||||
return remoteHash !== localHash
|
||||
}
|
||||
|
||||
const checkVariableChanges = (remoteCollection, localCollection) => {
|
||||
const remoteVariables = remoteCollection.collection.variable
|
||||
const localVariables = localCollection.variable.map(variable => ({ key: variable.key, value: variable.value }))
|
||||
|
||||
// check if null
|
||||
if (!remoteVariables && !localVariables) {
|
||||
return false
|
||||
}
|
||||
if (!remoteVariables || !localVariables) {
|
||||
return true
|
||||
}
|
||||
|
||||
// although the local collection does have a deterministic id
|
||||
// the remote variable looses that value when it is updated
|
||||
// so we need to generate an id for the remote variable
|
||||
|
||||
const remoteVariablesHash = GenID(remoteVariables)
|
||||
const localVariablesHash = GenID(localVariables)
|
||||
|
||||
return remoteVariablesHash !== localVariablesHash
|
||||
}
|
||||
|
||||
async function mergeFolders (remoteCollection, localCollection) {
|
||||
console.log(' Deploying Folders:')
|
||||
|
||||
const remoteFolders = getAllFoldersFromCollectionItem(remoteCollection.collection.item)
|
||||
const localFolders = localCollection.item // all folders
|
||||
|
||||
const newFolders = localFolders.filter(localFolder => !remoteFolders.find(remoteFolder => remoteFolder.id === localFolder.id))
|
||||
const oldFolders = remoteFolders.filter(remoteFolder => !localFolders.find(localFolder => localFolder.id === remoteFolder.id))
|
||||
|
||||
let hasChanges = newFolders.length > 0 || oldFolders.length > 0
|
||||
|
||||
if (!hasChanges) {
|
||||
console.log(' -> No changes')
|
||||
return hasChanges
|
||||
}
|
||||
|
||||
// create new folders
|
||||
for (const folder of newFolders) {
|
||||
const msg = ` Creating new folder [${folder.name}]`
|
||||
await new pmAPI.Folder(remoteCollection.collection.info.uid)
|
||||
.create(folder)
|
||||
.then(() => {
|
||||
hasChanges = true
|
||||
console.log(msg, '-> OK')
|
||||
})
|
||||
.catch((error) => {
|
||||
console.log(msg, '-> FAIL')
|
||||
handlePostmanAPIError(error)
|
||||
})
|
||||
}
|
||||
|
||||
// delete old folders
|
||||
for (const folder of oldFolders) {
|
||||
const msg = ` Deleting old folder [${folder.name}]`
|
||||
await new pmAPI.Folder(remoteCollection.collection.info.uid)
|
||||
.delete(folder.id)
|
||||
.then(() => {
|
||||
hasChanges = true
|
||||
console.log(msg, '-> OK')
|
||||
})
|
||||
.catch((error) => {
|
||||
console.log(msg, '-> FAIL')
|
||||
handlePostmanAPIError(error)
|
||||
})
|
||||
}
|
||||
|
||||
// sort folders is not supported for now
|
||||
// const order = localFolders.map(folder => folder.id)
|
||||
// const msg = ' Sorting folders'
|
||||
|
||||
// // create a temporsary root folder
|
||||
// const rootFolder = await new pmAPI.Folder(remoteCollection.collection.info.uid)
|
||||
// .create({ id: GenID(), name: 'root', folders: order })
|
||||
// .catch((error) => {
|
||||
// console.log(msg, '-> FAIL')
|
||||
// handlePostmanAPIError(error)
|
||||
// })
|
||||
// console.log('root folder', rootFolder)
|
||||
// // move all remote folders into root folder
|
||||
|
||||
return hasChanges
|
||||
}
|
||||
|
||||
async function mergeRequests (remoteCollection, localCollection) {
|
||||
const remoteFolders = getAllFoldersFromCollectionItem(remoteCollection.collection.item)
|
||||
const localFolders = localCollection.item // all folders
|
||||
|
||||
console.log('\n Deploying Requests:')
|
||||
let anyRequestHasChanged = false
|
||||
|
||||
// loop folders
|
||||
for (const localFolder of localFolders) {
|
||||
const remoteRemoteFolder = remoteFolders.find(remoteFolder => ((remoteFolder.id === localFolder.id)))
|
||||
|
||||
// TODO: RB: get requests by folder
|
||||
// handle undefined items
|
||||
remoteRemoteFolder.item = remoteRemoteFolder.item || []
|
||||
|
||||
// filter out anything that is not a request
|
||||
remoteRemoteFolder.item = remoteRemoteFolder.item.filter(request => request.request)
|
||||
|
||||
const remoteRequests = remoteRemoteFolder.item
|
||||
const localRequests = localFolder.item
|
||||
|
||||
// Identify old and new requests
|
||||
const newRequests = localRequests.filter(localRequest => !remoteRequests.find(remoteRequest => remoteRequest.id === localRequest.id))
|
||||
const oldRequests = remoteRequests.filter(remoteRequest => !localRequests.find(localRequest => localRequest.id === remoteRequest.id))
|
||||
|
||||
const requestsInFolderHaveChanges = newRequests.length > 0 || oldRequests.length > 0
|
||||
|
||||
if (!requestsInFolderHaveChanges) {
|
||||
console.log(' In Folder: ', localFolder.name, '-> No changes')
|
||||
continue
|
||||
}
|
||||
console.log(' In Folder: ', localFolder.name)
|
||||
|
||||
// create new requests
|
||||
for (const request of newRequests) {
|
||||
// check request format and convert if necessary
|
||||
let pmRequest = null
|
||||
if (!request.request) { // => Postman Format
|
||||
pmRequest = request
|
||||
} else { // => OpenAPI Format
|
||||
pmRequest = pmConvert.requestFromLocal(request)
|
||||
}
|
||||
const msg = ` Creating new request [${request.name}]`
|
||||
|
||||
await new pmAPI.Request(remoteCollection.collection.info.uid)
|
||||
.create(pmRequest, localFolder.id)
|
||||
.then((req) => {
|
||||
console.log(msg, '-> OK')
|
||||
return req
|
||||
})
|
||||
.catch((error) => {
|
||||
console.log(msg, '-> FAIL')
|
||||
handlePostmanAPIError(error)
|
||||
})
|
||||
// console.log('\nequest', request)
|
||||
// console.log('\npmRequest', pmRequest)
|
||||
// console.log('\nremoteRequest', remoteRequest)
|
||||
}
|
||||
|
||||
// delete old requests
|
||||
for (const request of oldRequests) {
|
||||
const msg = ` Deleting old request [${request.name}]`
|
||||
await new pmAPI.Request(remoteCollection.collection.info.uid)
|
||||
.delete(request.id)
|
||||
.then(() => {
|
||||
console.log(msg, '-> OK')
|
||||
})
|
||||
.catch((error) => {
|
||||
console.log(msg, '-> FAIL')
|
||||
handlePostmanAPIError(error)
|
||||
})
|
||||
}
|
||||
|
||||
if (requestsInFolderHaveChanges) {
|
||||
// sort requests in folder
|
||||
const order = localRequests.map(request => request.id)
|
||||
const msg = ` Sorting requests in folder [${localFolder.name}]`
|
||||
await new pmAPI.Folder(remoteCollection.collection.info.uid)
|
||||
.update(localFolder.id, { order })
|
||||
.then(() => { console.log(msg, '-> OK') })
|
||||
.catch((error) => {
|
||||
console.log(msg, '-> FAIL')
|
||||
handlePostmanAPIError(error)
|
||||
})
|
||||
}
|
||||
anyRequestHasChanged = anyRequestHasChanged || requestsInFolderHaveChanges
|
||||
}
|
||||
return anyRequestHasChanged
|
||||
}
|
||||
|
||||
async function mergeResponses (remoteCollection, localCollection) {
|
||||
console.log('\n Deploying Response:')
|
||||
const remoteFolders = getAllFoldersFromCollectionItem(remoteCollection.collection.item)
|
||||
const localFolders = localCollection.item
|
||||
|
||||
let anyResponseHasChanged = false
|
||||
// loop folders
|
||||
for (const localFolder of localFolders) {
|
||||
const remoteRemoteFolder = remoteFolders.find(remoteFolder => ((remoteFolder.id === localFolder.id)))
|
||||
|
||||
// handle undefined items
|
||||
remoteRemoteFolder.item = remoteRemoteFolder.item || []
|
||||
|
||||
// filter out anything that is not a request
|
||||
remoteRemoteFolder.item = remoteRemoteFolder.item.filter(request => request.request)
|
||||
|
||||
const remoteRequests = remoteRemoteFolder.item
|
||||
const localRequests = localFolder.item
|
||||
|
||||
console.log(' In Folder: ', localFolder.name)
|
||||
// loop requests
|
||||
for (const localRequest of localRequests) {
|
||||
// Postman Request format does not have a response property
|
||||
const remoteResponses = remoteRequests.find(remoteRequest => remoteRequest.id === localRequest.id).response
|
||||
const localResponses = localRequest.response
|
||||
// the request may not have responses
|
||||
if (!localResponses) {
|
||||
continue
|
||||
}
|
||||
|
||||
const newResponses = localResponses.filter(localResponse => !remoteResponses.find(remoteResponse => remoteResponse.id === localResponse.id))
|
||||
const oldResponses = remoteResponses.filter(remoteResponse => !localResponses.find(localResponse => localResponse.id === remoteResponse.id))
|
||||
|
||||
const ResponsesInReqquestHaveChanges = newResponses.length > 0 || oldResponses.length > 0
|
||||
if (!ResponsesInReqquestHaveChanges) {
|
||||
console.log(' In Request: ', localRequest.name, '-> No changes')
|
||||
continue
|
||||
}
|
||||
console.log(' In Request: ', localRequest.name)
|
||||
|
||||
// create new responses
|
||||
for (const response of newResponses) {
|
||||
const pmResponse = pmConvert.responseFromLocal(response)
|
||||
const msg = ` Creating new response [${response.code} ${response.status}]`
|
||||
await new pmAPI.Response(remoteCollection.collection.info.uid)
|
||||
.create(pmResponse, localRequest.id)
|
||||
.then(() => {
|
||||
console.log(msg, '-> OK')
|
||||
})
|
||||
.catch((error) => {
|
||||
console.log(msg, '-> FAIL')
|
||||
handlePostmanAPIError(error)
|
||||
})
|
||||
}
|
||||
|
||||
// delete old responses
|
||||
for (const response of oldResponses) {
|
||||
const msg = ` Deleting old response [${response.code} ${response.status}]`
|
||||
await new pmAPI.Response(remoteCollection.collection.info.uid)
|
||||
.delete(response.id)
|
||||
.then(() => {
|
||||
console.log(msg, '-> OK')
|
||||
})
|
||||
.catch((error) => {
|
||||
console.log(msg, '-> FAIL')
|
||||
handlePostmanAPIError(error)
|
||||
})
|
||||
}
|
||||
|
||||
// updating the requests with the order of the responses, doesn't seem to be necessary
|
||||
if (ResponsesInReqquestHaveChanges) {
|
||||
// sort responses in requests
|
||||
const responsesOrder = localResponses.map(response => response.id)
|
||||
const msg = ` Sorting responses in request [${localRequest.name}]`
|
||||
await new pmAPI.Request(remoteCollection.collection.info._postman_id)
|
||||
.update(localRequest.id,
|
||||
{
|
||||
responses_order: responsesOrder
|
||||
})
|
||||
.then(() => { console.log(msg, '-> OK') })
|
||||
.catch((error) => {
|
||||
console.log(msg, '-> FAIL')
|
||||
handlePostmanAPIError(error)
|
||||
})
|
||||
}
|
||||
anyResponseHasChanged = anyResponseHasChanged || ResponsesInReqquestHaveChanges
|
||||
}
|
||||
}
|
||||
return anyResponseHasChanged
|
||||
}
|
||||
|
||||
async function refreshRemoteCollection (remoteCollectionID) {
|
||||
const msg = 'Refreshing remote collection'
|
||||
console.log('\n' + msg + '...\n')
|
||||
const remoteCollection = await new pmAPI.Collection(remoteCollectionID).get()
|
||||
.catch((error) => {
|
||||
console.log(msg, '-> FAIL')
|
||||
handlePostmanAPIError(error)
|
||||
})
|
||||
return remoteCollection
|
||||
}
|
||||
|
||||
// return all folders in the collection
|
||||
// independently of where they are
|
||||
const getAllFoldersFromCollectionItem = (collectionItem) => {
|
||||
const folders = []
|
||||
const processItem = (item) => {
|
||||
if (!item.request && !item.responses) {
|
||||
folders.push({ id: item.id, name: item.name, item: item.item })
|
||||
}
|
||||
if (item.item) {
|
||||
item.item.forEach(processItem)
|
||||
}
|
||||
}
|
||||
collectionItem.forEach(processItem)
|
||||
return folders
|
||||
}
|
||||
|
||||
// Handle axios error
|
||||
const handlePostmanAPIError = (error) => {
|
||||
if (error.response) {
|
||||
// The request was made and the server responded with a status code
|
||||
// that falls out of the range of 2xx
|
||||
console.log('API ERROR:', error.response.data)
|
||||
} else {
|
||||
// The request was made but no response was received
|
||||
// `error.request` is an instance of XMLHttpRequest in the browser and an instance of
|
||||
// http.ClientRequest in node.js
|
||||
console.log('NO RESPONSE:', error.message)
|
||||
if (error.cause) {
|
||||
console.log('CAUSE:', error.cause)
|
||||
}
|
||||
}
|
||||
const { method, url, data } = error.config
|
||||
const smallData = data.substring(0, 1000)
|
||||
console.log('REQUEST DETAILS', { method, url, smallData })
|
||||
process.exit(1)
|
||||
}
|
||||
|
||||
const calculateHash = (stringToHash) => {
|
||||
return crypto.createHash('sha256').update(stringToHash).digest('hex')
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
deployIncremental
|
||||
}
|
||||
@@ -1,143 +0,0 @@
|
||||
// Postman Convertions
|
||||
// ------------------------------------------------------------
|
||||
// Handles the conversions from the local generated object
|
||||
// to the postman api specific objects.
|
||||
// The converted objects are necessary for the updates to work.
|
||||
// ------------------------------------------------------------
|
||||
// The interesting part is that the postman api uses a different
|
||||
// object structure for folders, requests, adn responses,
|
||||
// when compared to what you get from the collection json file.
|
||||
// ------------------------------------------------------------
|
||||
|
||||
const requestFromLocal = (localRequest) => {
|
||||
// console.log('localRequest', localRequest)
|
||||
let url = localRequest.request.url.protocol + '://' + localRequest.request.url.host + localRequest.request.url.path
|
||||
|
||||
let data = []
|
||||
let dataMode = null
|
||||
let rawModeData = null
|
||||
if (localRequest.request.body && localRequest.request.body.urlencoded) {
|
||||
data = dataFromLocalURLEncode(localRequest.request.body.urlencoded)
|
||||
dataMode = localRequest.request.body.mode
|
||||
rawModeData = localRequest.request.body.raw
|
||||
}
|
||||
|
||||
let queryParams = []
|
||||
if (localRequest.request.url.query) {
|
||||
queryParams = dataFromLocalURLEncode(localRequest.request.url.query)
|
||||
url += '?'
|
||||
for (const param of queryParams) {
|
||||
if (param.enabled === false) continue
|
||||
url += param.key + '=' + param.value + '&'
|
||||
}
|
||||
url = url.slice(0, -1)
|
||||
}
|
||||
|
||||
let pathVariableData = []
|
||||
if (localRequest.request.url.variable) {
|
||||
pathVariableData = dataFromLocalURLEncode(localRequest.request.url.variable)
|
||||
}
|
||||
|
||||
let headerData = []
|
||||
if (localRequest.request.header) {
|
||||
headerData = dataFromLocalURLEncode(localRequest.request.header)
|
||||
.map((header) => ({ key: header.key, value: header.value, enabled: header.enabled, description: header.description }))
|
||||
}
|
||||
|
||||
const request = {
|
||||
// owner: '8119550',
|
||||
// lastUpdatedBy: '8119550',
|
||||
// lastRevision: 32526900683,
|
||||
// folder: 'dfa47710-b3d3-4a2c-bbc8-fbd25ad12244',
|
||||
// collection: 'fa89c950-c947-4061-9d13-fb18d7c6bc51',
|
||||
|
||||
id: localRequest.id, //
|
||||
name: localRequest.name, //
|
||||
|
||||
dataMode, //
|
||||
data, //
|
||||
auth: localRequest.request.auth, //
|
||||
events: localRequest.events, //
|
||||
//
|
||||
rawModeData, // body os request
|
||||
//
|
||||
descriptionFormat: localRequest.descriptionFormat, // it can be in either ``html`` or ``markdown`` formats.
|
||||
description: localRequest.request.description, //
|
||||
// Headers
|
||||
headers: null,
|
||||
headerData,
|
||||
//
|
||||
variables: localRequest.variables,
|
||||
method: localRequest.request.method, //
|
||||
|
||||
// Path Variables
|
||||
pathVariables: pathVariableData, //
|
||||
pathVariableData, //
|
||||
//
|
||||
url, //
|
||||
preRequestScript: localRequest.preRequestScript,
|
||||
tests: localRequest.tests,
|
||||
currentHelper: localRequest.currentHelper,
|
||||
helperAttributes: localRequest.helperAttributes,
|
||||
queryParams, //
|
||||
|
||||
protocolProfileBehavior: localRequest.protocolProfileBehavior,
|
||||
dataDisabled: localRequest.dataDisabled,
|
||||
responses_order: localRequest.responses_order
|
||||
|
||||
// createdAt: '2023-09-12T16:25:20.000Z',
|
||||
// updatedAt: '2023-09-12T16:25:23.000Z',
|
||||
// dataOptions: {{"raw":{}}},
|
||||
}
|
||||
return request
|
||||
}
|
||||
|
||||
const responseFromLocal = (localResponse) => {
|
||||
const headers = localResponse.header.map((item) => ({ key: item.key, value: item.value }))
|
||||
const response = {
|
||||
// owner: '8119550',
|
||||
// lastUpdatedBy: '8119550',
|
||||
// lastRevision: 32546597265,
|
||||
// request: '331bbc94-5425-46f3-8c02-31c353d2ced8',
|
||||
|
||||
id: localResponse.id, //
|
||||
name: localResponse.name, //
|
||||
status: localResponse.status, //
|
||||
responseCode: {
|
||||
code: localResponse.code, //
|
||||
name: localResponse.status, //
|
||||
detail: ''
|
||||
},
|
||||
// time: null,
|
||||
headers, //
|
||||
cookies: [],
|
||||
mime: null,
|
||||
text: localResponse.body, //
|
||||
language: 'Text', //
|
||||
rawDataType: 'text'//
|
||||
// requestObject: null,
|
||||
// createdAt: '2023-09-13T14:53:05.000Z',
|
||||
// updatedAt: '2023-09-13T14:53:05.000Z'
|
||||
}
|
||||
|
||||
return response
|
||||
}
|
||||
|
||||
const dataFromLocalURLEncode = (localFormData) => {
|
||||
const data = []
|
||||
for (const param of localFormData) {
|
||||
const item = {
|
||||
key: param.key,
|
||||
description: param.description,
|
||||
value: param.value,
|
||||
enabled: !param.disabled
|
||||
}
|
||||
data.push(item)
|
||||
}
|
||||
return data
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
requestFromLocal,
|
||||
responseFromLocal
|
||||
}
|
||||
@@ -1,37 +0,0 @@
|
||||
const uuid = require('uuid')
|
||||
const NAMESPACE = '33c4e6fc-44cb-4190-b19f-4a02821bc8c3'
|
||||
|
||||
const genID = (objectJSON = null) => {
|
||||
if (objectJSON) {
|
||||
return uuid.v5(objectJSON, NAMESPACE)
|
||||
} else {
|
||||
return uuid.v4()
|
||||
}
|
||||
}
|
||||
|
||||
// Sort 2 objects by name
|
||||
const byName = (a, b) => {
|
||||
if (a.name < b.name) {
|
||||
return -1
|
||||
} else if (a.name > b.name) {
|
||||
return 1
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
// Sort two object by priority
|
||||
const byPriority = (a, b) => {
|
||||
if (a['x-box-priority']) {
|
||||
return -1
|
||||
} else if (b['x-box-priority']) {
|
||||
return 1
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
GenID: genID,
|
||||
ByName: byName,
|
||||
ByPriority: byPriority
|
||||
// logAxiosError
|
||||
}
|
||||
@@ -1,11 +0,0 @@
|
||||
const fs = require('fs')
|
||||
const { deployIncremental } = require('./DeployIncremental')
|
||||
|
||||
const release = async () => {
|
||||
let privateRemoteCollectionId = '23836355-c5640083-7523-4ad7-9f92-b23e079cbb7b'
|
||||
let publicRemoteCollectionId = '23836355-6224d51a-d924-4c39-a58f-6970735aac8e'
|
||||
let localCollection = JSON.parse(fs.readFileSync(`C:\\git\\api-specs\\postman\\collections\\sailpoint-api-v3.json`).toString())
|
||||
await deployIncremental(privateRemoteCollectionId, localCollection, publicRemoteCollectionId)
|
||||
}
|
||||
|
||||
release()
|
||||
131
postman-script/partialUpdate/package-lock.json
generated
131
postman-script/partialUpdate/package-lock.json
generated
@@ -1,131 +0,0 @@
|
||||
{
|
||||
"name": "partialupdate",
|
||||
"version": "1.0.0",
|
||||
"lockfileVersion": 3,
|
||||
"requires": true,
|
||||
"packages": {
|
||||
"": {
|
||||
"name": "partialupdate",
|
||||
"version": "1.0.0",
|
||||
"license": "ISC",
|
||||
"dependencies": {
|
||||
"axios": "^1.6.5",
|
||||
"dotenv": "^16.3.1",
|
||||
"uuid": "^9.0.1"
|
||||
}
|
||||
},
|
||||
"node_modules/asynckit": {
|
||||
"version": "0.4.0",
|
||||
"resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz",
|
||||
"integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q=="
|
||||
},
|
||||
"node_modules/axios": {
|
||||
"version": "1.6.5",
|
||||
"resolved": "https://registry.npmjs.org/axios/-/axios-1.6.5.tgz",
|
||||
"integrity": "sha512-Ii012v05KEVuUoFWmMW/UQv9aRIc3ZwkWDcM+h5Il8izZCtRVpDUfwpoFf7eOtajT3QiGR4yDUx7lPqHJULgbg==",
|
||||
"dependencies": {
|
||||
"follow-redirects": "^1.15.4",
|
||||
"form-data": "^4.0.0",
|
||||
"proxy-from-env": "^1.1.0"
|
||||
}
|
||||
},
|
||||
"node_modules/combined-stream": {
|
||||
"version": "1.0.8",
|
||||
"resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz",
|
||||
"integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==",
|
||||
"dependencies": {
|
||||
"delayed-stream": "~1.0.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 0.8"
|
||||
}
|
||||
},
|
||||
"node_modules/delayed-stream": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz",
|
||||
"integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==",
|
||||
"engines": {
|
||||
"node": ">=0.4.0"
|
||||
}
|
||||
},
|
||||
"node_modules/dotenv": {
|
||||
"version": "16.3.1",
|
||||
"resolved": "https://registry.npmjs.org/dotenv/-/dotenv-16.3.1.tgz",
|
||||
"integrity": "sha512-IPzF4w4/Rd94bA9imS68tZBaYyBWSCE47V1RGuMrB94iyTOIEwRmVL2x/4An+6mETpLrKJ5hQkB8W4kFAadeIQ==",
|
||||
"engines": {
|
||||
"node": ">=12"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/motdotla/dotenv?sponsor=1"
|
||||
}
|
||||
},
|
||||
"node_modules/follow-redirects": {
|
||||
"version": "1.15.4",
|
||||
"resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.4.tgz",
|
||||
"integrity": "sha512-Cr4D/5wlrb0z9dgERpUL3LrmPKVDsETIJhaCMeDfuFYcqa5bldGV6wBsAN6X/vxlXQtFBMrXdXxdL8CbDTGniw==",
|
||||
"funding": [
|
||||
{
|
||||
"type": "individual",
|
||||
"url": "https://github.com/sponsors/RubenVerborgh"
|
||||
}
|
||||
],
|
||||
"engines": {
|
||||
"node": ">=4.0"
|
||||
},
|
||||
"peerDependenciesMeta": {
|
||||
"debug": {
|
||||
"optional": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"node_modules/form-data": {
|
||||
"version": "4.0.0",
|
||||
"resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.0.tgz",
|
||||
"integrity": "sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==",
|
||||
"dependencies": {
|
||||
"asynckit": "^0.4.0",
|
||||
"combined-stream": "^1.0.8",
|
||||
"mime-types": "^2.1.12"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 6"
|
||||
}
|
||||
},
|
||||
"node_modules/mime-db": {
|
||||
"version": "1.52.0",
|
||||
"resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz",
|
||||
"integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==",
|
||||
"engines": {
|
||||
"node": ">= 0.6"
|
||||
}
|
||||
},
|
||||
"node_modules/mime-types": {
|
||||
"version": "2.1.35",
|
||||
"resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz",
|
||||
"integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==",
|
||||
"dependencies": {
|
||||
"mime-db": "1.52.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 0.6"
|
||||
}
|
||||
},
|
||||
"node_modules/proxy-from-env": {
|
||||
"version": "1.1.0",
|
||||
"resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.1.0.tgz",
|
||||
"integrity": "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg=="
|
||||
},
|
||||
"node_modules/uuid": {
|
||||
"version": "9.0.1",
|
||||
"resolved": "https://registry.npmjs.org/uuid/-/uuid-9.0.1.tgz",
|
||||
"integrity": "sha512-b+1eJOlsR9K8HJpow9Ok3fiWOWSIcIzXodvv0rQjVoOVNpWMpxf1wZNpt4y9h10odCNrqnYp1OBzRktckBe3sA==",
|
||||
"funding": [
|
||||
"https://github.com/sponsors/broofa",
|
||||
"https://github.com/sponsors/ctavan"
|
||||
],
|
||||
"bin": {
|
||||
"uuid": "dist/bin/uuid"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,16 +0,0 @@
|
||||
{
|
||||
"name": "partialupdate",
|
||||
"version": "1.0.0",
|
||||
"description": "partial updates to postman files",
|
||||
"main": "index.js",
|
||||
"scripts": {
|
||||
"test": "echo \"Error: no test specified\" && exit 1"
|
||||
},
|
||||
"author": "",
|
||||
"license": "ISC",
|
||||
"dependencies": {
|
||||
"axios": "^1.6.5",
|
||||
"dotenv": "^16.3.1",
|
||||
"uuid": "^9.0.1"
|
||||
}
|
||||
}
|
||||
@@ -1,236 +0,0 @@
|
||||
require('dotenv').config()
|
||||
const axios = require('axios')
|
||||
|
||||
class Collection {
|
||||
constructor (collectionId) {
|
||||
this.collectionId = collectionId
|
||||
this.apiKey = process.env.POSTMAN_API_KEY
|
||||
this.axios = axios.create({
|
||||
timeout: 1000 * 60, // 60 seconds
|
||||
headers: { 'Content-Type': 'application/json', 'X-Api-Key': this.apiKey }
|
||||
})
|
||||
}
|
||||
|
||||
async get () {
|
||||
return await this.axios.get(
|
||||
`https://api.getpostman.com/collections/${this.collectionId}`
|
||||
, { timeout: 1000 * 60 * 5 } // 5 minutes
|
||||
).then(function (response) {
|
||||
if (response.status !== 200) {
|
||||
throw new Error(`Error getting collection ${this.collectionId}: ${response.status} ${response.statusText}`)
|
||||
} else {
|
||||
return response.data
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
async merge (destinationCollectionId, strategy = 'updateSourceWithDestination') {
|
||||
return await this.axios.post(
|
||||
'https://api.getpostman.com/collections/merge',
|
||||
{ source: this.collectionId, destination: destinationCollectionId, strategy },
|
||||
{ timeout: 1000 * 60 * 5 } // 5 minutes
|
||||
).then(function (response) {
|
||||
if (response.status !== 200) {
|
||||
throw new Error(`Error merging collection from ${this.collectionId} to ${destinationCollectionId}: ${response.status} ${response.statusText}`)
|
||||
} else {
|
||||
return response.data
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
async update (collection) {
|
||||
return await this.axios.put(
|
||||
`https://api.getpostman.com/collections/${this.collectionId}`,
|
||||
collection,
|
||||
{ timeout: 1000 * 60 * 5 } // 5 minutes
|
||||
).then(function (response) {
|
||||
if (response.status !== 200) {
|
||||
throw new Error(`Error updating collection ${collection.id}: ${response.status} ${response.statusText}`)
|
||||
} else {
|
||||
return response.data
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
class Folder {
|
||||
constructor (collectionId) {
|
||||
this.collectionId = collectionId
|
||||
this.apiKey = process.env.POSTMAN_API_KEY
|
||||
this.axios = axios.create({
|
||||
timeout: 1000 * 60, // 60 seconds
|
||||
headers: { 'Content-Type': 'application/json', 'X-Api-Key': this.apiKey }
|
||||
})
|
||||
}
|
||||
|
||||
async get (folderId) {
|
||||
return await this.axios.get(
|
||||
`https://api.getpostman.com/collections/${this.collectionId}/folders/${folderId}`
|
||||
).then(function (response) {
|
||||
if (response.status !== 200) {
|
||||
throw new Error(`Error getting folder ${folderId}: ${response.status} ${response.statusText}`)
|
||||
} else {
|
||||
return response.data
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
async create (folder) {
|
||||
return await this.axios.post(
|
||||
`https://api.getpostman.com/collections/${this.collectionId}/folders`,
|
||||
folder
|
||||
).then(function (response) {
|
||||
if (response.status !== 200) {
|
||||
throw new Error(`Error creating folder ${folder.Id}: ${response.status} ${response.statusText}`)
|
||||
} else {
|
||||
return response.data
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
async update (folderId, folder) {
|
||||
return await this.axios.put(
|
||||
`https://api.getpostman.com/collections/${this.collectionId}/folders/${folderId}`,
|
||||
folder
|
||||
).then(function (response) {
|
||||
if (response.status !== 200) {
|
||||
throw new Error(`Error updating folder ${folder.Id}: ${response.status} ${response.statusText}`)
|
||||
} else {
|
||||
return response.data
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
async delete (folderId) {
|
||||
return await this.axios.delete(
|
||||
`https://api.getpostman.com/collections/${this.collectionId}/folders/${folderId}`
|
||||
|
||||
).then(function (response) {
|
||||
if (response.status !== 200) {
|
||||
throw new Error(`Error deleting folder ${folderId}: ${response.status} ${response.statusText}`)
|
||||
} else {
|
||||
return response.data
|
||||
}
|
||||
})
|
||||
}
|
||||
} // class Folder
|
||||
|
||||
class Request {
|
||||
constructor (collectionId) {
|
||||
this.collectionId = collectionId
|
||||
this.apiKey = process.env.POSTMAN_API_KEY
|
||||
this.axios = axios.create({
|
||||
timeout: 1000 * 60, // 60 seconds
|
||||
headers: { 'Content-Type': 'application/json', 'X-Api-Key': this.apiKey }
|
||||
})
|
||||
}
|
||||
|
||||
async get (requestId) {
|
||||
return await this.axios.get(
|
||||
`https://api.getpostman.com/collections/${this.collectionId}/requests/${requestId}`
|
||||
).then(function (response) {
|
||||
if (response.status !== 200) {
|
||||
throw new Error(`Error getting request ${requestId}: ${response.status} ${response.statusText}`)
|
||||
} else {
|
||||
return response.data
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
async create (request, folderId) {
|
||||
return await this.axios.post(
|
||||
`https://api.getpostman.com/collections/${this.collectionId}/requests`,
|
||||
request,
|
||||
{ params: { folder: folderId } }
|
||||
).then(function (response) {
|
||||
if (response.status !== 200) {
|
||||
throw new Error(`Error creating request ${request.id}: ${response.status} ${response.statusText}`)
|
||||
} else {
|
||||
return response.data
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
async update (requestId, request) {
|
||||
return await this.axios.put(
|
||||
`https://api.getpostman.com/collections/${this.collectionId}/requests/${requestId}`,
|
||||
request
|
||||
).then(function (response) {
|
||||
if (response.status !== 200) {
|
||||
throw new Error(`Error updating request ${request.id}: ${response.status} ${response.statusText}`)
|
||||
} else {
|
||||
return response.data
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
async delete (requestId) {
|
||||
return await this.axios.delete(
|
||||
`https://api.getpostman.com/collections/${this.collectionId}/requests/${requestId}`
|
||||
|
||||
).then(function (response) {
|
||||
if (response.status !== 200) {
|
||||
throw new Error(`Error deleting request ${requestId}: ${response.status} ${response.statusText}`)
|
||||
} else {
|
||||
return response.data
|
||||
}
|
||||
})
|
||||
}
|
||||
} // class Request
|
||||
|
||||
class Response {
|
||||
constructor (collectionId) {
|
||||
this.collectionId = collectionId
|
||||
this.apiKey = process.env.POSTMAN_API_KEY
|
||||
this.axios = axios.create({
|
||||
timeout: 1000 * 60, // 60 seconds
|
||||
headers: { 'Content-Type': 'application/json', 'X-Api-Key': this.apiKey }
|
||||
})
|
||||
}
|
||||
|
||||
async get (responseId) {
|
||||
return await this.axios.get(
|
||||
`https://api.getpostman.com/collections/${this.collectionId}/responses/${responseId}`
|
||||
).then(function (axiosResp) {
|
||||
if (axiosResp.status !== 200) {
|
||||
throw new Error(`Error getting response ${responseId}: ${axiosResp.status} ${axiosResp.statusText}`)
|
||||
} else {
|
||||
return axiosResp.data
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
async create (response, requestId) {
|
||||
return await this.axios.post(
|
||||
`https://api.getpostman.com/collections/${this.collectionId}/responses`,
|
||||
response,
|
||||
{ params: { request: requestId } }
|
||||
).then(function (axiosResp) {
|
||||
if (axiosResp.status !== 200) {
|
||||
throw new Error(`Error creating response ${response.id}: ${axiosResp.status} ${axiosResp.statusText}`)
|
||||
} else {
|
||||
return axiosResp.data
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
async delete (responseId) {
|
||||
return await this.axios.delete(
|
||||
`https://api.getpostman.com/collections/${this.collectionId}/responses/${responseId}`
|
||||
|
||||
).then(function (axiosResp) {
|
||||
if (axiosResp.status !== 200) {
|
||||
throw new Error(`Error deleting response ${responseId}: ${axiosResp.status} ${axiosResp.statusText}`)
|
||||
} else {
|
||||
return axiosResp.data
|
||||
}
|
||||
})
|
||||
}
|
||||
} // class Response
|
||||
|
||||
module.exports = {
|
||||
Collection,
|
||||
Folder,
|
||||
Request,
|
||||
Response
|
||||
}
|
||||
@@ -12,7 +12,7 @@
|
||||
|
||||
const requestFromLocal = (localRequest, responses) => {
|
||||
// console.log('localRequest', localRequest)
|
||||
let url = localRequest.request.url.host + '/' + localRequest.request.url.path
|
||||
let url = localRequest.request.url.host + '/' + localRequest.request.url.path.join('/')
|
||||
|
||||
let data = []
|
||||
let dataMode = null
|
||||
@@ -48,6 +48,12 @@ const requestFromLocal = (localRequest, responses) => {
|
||||
.map((header) => ({ key: header.key, value: header.value, enabled: header.enabled, description: header.description }))
|
||||
}
|
||||
|
||||
let headers = []
|
||||
if (localRequest.request.header) {
|
||||
headers = dataFromLocalURLEncode(localRequest.request.header)
|
||||
.map((header) => ({ key: header.key, value: header.value, description: header.description }))
|
||||
}
|
||||
|
||||
if (JSON.stringify(localRequest.request.description) === '{}') {
|
||||
localRequest.request.description = ''
|
||||
}
|
||||
@@ -70,9 +76,9 @@ const requestFromLocal = (localRequest, responses) => {
|
||||
rawModeData, // body os request
|
||||
//
|
||||
descriptionFormat: localRequest.descriptionFormat, // it can be in either ``html`` or ``markdown`` formats.
|
||||
description: localRequest.request.description.content ? localRequest.request.description.content : localRequest.request.description, //
|
||||
description: localRequest.request.description && localRequest.request.description.content ? localRequest.request.description.content : localRequest.request.description, //
|
||||
// Headers
|
||||
headers: localRequest.request.header,
|
||||
headers: headers,
|
||||
headerData,
|
||||
//
|
||||
variables: localRequest.variables,
|
||||
@@ -102,7 +108,17 @@ const requestFromLocal = (localRequest, responses) => {
|
||||
}
|
||||
|
||||
const responseFromLocal = (localResponse, requestObject) => {
|
||||
const headers = localResponse.header.map((item) => ({ key: item.key, value: item.value }))
|
||||
const headers = localResponse.header
|
||||
.map((item) => ({ key: item.key, value: item.value }))
|
||||
.sort((a, b) => {
|
||||
if (a.key < b.key) {
|
||||
return -1;
|
||||
}
|
||||
if (a.key > b.key) {
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
});
|
||||
const response = {
|
||||
// owner: '8119550',
|
||||
// lastUpdatedBy: '8119550',
|
||||
@@ -121,7 +137,7 @@ const requestFromLocal = (localRequest, responses) => {
|
||||
headers, //
|
||||
cookies: [],
|
||||
mime: null,
|
||||
text: localResponse.body, //
|
||||
text: localResponse.body ? localResponse.body : '', //
|
||||
language: 'json', //
|
||||
rawDataType: 'text',//
|
||||
requestObject: requestObject,
|
||||
@@ -135,11 +151,18 @@ const requestFromLocal = (localRequest, responses) => {
|
||||
const dataFromLocalURLEncode = (localFormData) => {
|
||||
const data = []
|
||||
for (const param of localFormData) {
|
||||
// check if param.key is a number
|
||||
if (!param.key || !isNaN(param.key)) {
|
||||
continue
|
||||
}
|
||||
if (JSON.stringify(param.description) === '{}') {
|
||||
param.description = ''
|
||||
}
|
||||
const item = {
|
||||
key: param.key,
|
||||
description: param.description,
|
||||
description: param.description && param.description.content ? param.description.content : param.description,
|
||||
value: param.value,
|
||||
enabled: !param.disabled
|
||||
enabled: false
|
||||
}
|
||||
data.push(item)
|
||||
}
|
||||
|
||||
@@ -14,7 +14,7 @@ const release = async () => {
|
||||
|
||||
|
||||
|
||||
// This function just cleans up the variables so they match what is returned in postman
|
||||
// This step just cleans up the variables so they match what is returned in postman
|
||||
for (let variable of localCollection.variable) {
|
||||
if (variable.type) {
|
||||
delete variable.type
|
||||
@@ -41,11 +41,35 @@ const release = async () => {
|
||||
// add any missing folders
|
||||
for (let item of localCollection.item) {
|
||||
let folder = getMatchingFolder(item, remoteCollection.collection.item)
|
||||
if (checkIfDifferent(folder.description, item.description)) {
|
||||
console.log(`updating folder ${folder.name}`)
|
||||
await new pmAPI.Folder(publicRemoteCollectionId).update(folder.id, { description: item.description })
|
||||
console.log(`updated folder ${folder.name}`)
|
||||
}
|
||||
if (folder == null) {
|
||||
await updateEntireFolder(item)
|
||||
}
|
||||
}
|
||||
|
||||
// delete any folders that are no longer in the collection
|
||||
for (let folder of remoteCollection.collection.item) {
|
||||
let localFolder = getMatchingFolder(folder, localCollection.item)
|
||||
if (localFolder == null) {
|
||||
await new pmAPI.Folder(publicRemoteCollectionId).delete(folder.id)
|
||||
}
|
||||
}
|
||||
|
||||
// delete any requests that are no longer in the collection
|
||||
for (let folder of remoteCollection.collection.item) {
|
||||
let localFolder = getMatchingFolder(folder, localCollection.item)
|
||||
for (let items of folder.item) {
|
||||
let remoteRequest = getMatchingRequest(items, localFolder.item)
|
||||
if (remoteRequest == null) {
|
||||
await new pmAPI.Request(publicRemoteCollectionId).delete(items.id)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// update any requests that have changed
|
||||
for (let item of localCollection.item) {
|
||||
let folder = getMatchingFolder(item, remoteCollection.collection.item)
|
||||
@@ -54,7 +78,6 @@ const release = async () => {
|
||||
}
|
||||
}
|
||||
|
||||
console.log(remoteCollection)
|
||||
|
||||
}
|
||||
|
||||
@@ -69,7 +92,7 @@ function getMatchingFolder(localFolder, remoteFolders) {
|
||||
|
||||
function getMatchingRequest(localRequest, remoteRequests) {
|
||||
for (let request of remoteRequests) {
|
||||
if (request.name === localRequest.name) {
|
||||
if (request.name === localRequest.name && request.request.method === localRequest.request.method && localRequest.request.url.host + '/' + localRequest.request.url.path.join('/') === request.request.url.host + '/' + request.request.url.path.join('/')) {
|
||||
return request
|
||||
}
|
||||
}
|
||||
@@ -77,6 +100,9 @@ function getMatchingRequest(localRequest, remoteRequests) {
|
||||
}
|
||||
|
||||
function buildRequestBody(items) {
|
||||
if (items === null) {
|
||||
return null
|
||||
}
|
||||
|
||||
let responses = []
|
||||
for (let response of items.response) {
|
||||
@@ -87,12 +113,87 @@ function buildRequestBody(items) {
|
||||
}
|
||||
|
||||
function checkIfDifferent(source, dest) {
|
||||
if (JSON.stringify(source) === JSON.stringify(dest)) {
|
||||
removeIdFields(source)
|
||||
removeIdFields(dest)
|
||||
if (isDeepEqual(source, dest)) {
|
||||
return false
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
function removeIdFields(obj) {
|
||||
if (typeof obj !== 'object') {
|
||||
return
|
||||
}
|
||||
if (obj === null) {
|
||||
return
|
||||
}
|
||||
// Check if the current object has the 'id' property
|
||||
if (obj.hasOwnProperty('id')) {
|
||||
delete obj.id;
|
||||
}
|
||||
|
||||
// Recursively call removeIdFields on each property if it's an object
|
||||
for (let key in obj) {
|
||||
if (typeof obj[key] === 'object' && obj[key] !== null) {
|
||||
removeIdFields(obj[key]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function isNullorEmpty(obj) {
|
||||
if (obj === null || obj === '' || obj === undefined) {
|
||||
return true
|
||||
}
|
||||
return false
|
||||
|
||||
}
|
||||
|
||||
function isDeepEqual(obj1, obj2) {
|
||||
if (areValuesEqual(obj1, obj2)) {
|
||||
return true
|
||||
}
|
||||
|
||||
if (typeof obj1 !== 'object' || typeof obj2 !== 'object' || obj1 == null || obj2 == null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
const keys1 = Object.keys(obj1);
|
||||
const keys2 = Object.keys(obj2);
|
||||
|
||||
if (keys1.length !== keys2.length) {
|
||||
return false;
|
||||
}
|
||||
|
||||
for (let key of keys1) {
|
||||
const val1 = obj1[key];
|
||||
const val2 = obj2[key];
|
||||
const areObjects = isObject(val1) && isObject(val2);
|
||||
if (
|
||||
areObjects && !isDeepEqual(val1, val2) ||
|
||||
(!areObjects && !areValuesEqual(val1, val2))
|
||||
) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
function areValuesEqual(val1, val2) {
|
||||
if (isNullorEmpty(val1) && isNullorEmpty(val2)) {
|
||||
return true;
|
||||
}
|
||||
if (val1 === val2) {
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
function isObject(object) {
|
||||
return object != null && typeof object === 'object';
|
||||
}
|
||||
|
||||
|
||||
async function updateEntireFolder(item, folderId) {
|
||||
if (item.item && !folderId) {
|
||||
@@ -118,8 +219,12 @@ async function updateRequestsInFolder(item, folderId, remoteItem) {
|
||||
let postmanRequestBody = buildRequestBody(items)
|
||||
let remotePostmanBody = buildRequestBody(remoteRequest)
|
||||
if (checkIfDifferent(postmanRequestBody, remotePostmanBody)) {
|
||||
if (remoteRequest) {
|
||||
console.log(`deleting request ${remoteRequest.name}`)
|
||||
let newRequestDelete = await new pmAPI.Request(publicRemoteCollectionId).delete(remoteRequest.id)
|
||||
console.log(`deleting request ${newRequestDelete.data.id}`)
|
||||
console.log(`deleted request ${newRequestDelete.data.id}`)
|
||||
}
|
||||
postmanRequestBody = buildRequestBody(items)
|
||||
let newRequest = await new pmAPI.Request(publicRemoteCollectionId).create(postmanRequestBody, folderId)
|
||||
console.log(`creating request ${newRequest.data.name}`)
|
||||
} else {
|
||||
|
||||
@@ -31,14 +31,13 @@ class Collection {
|
||||
})
|
||||
axiosRetry(this.axios, {
|
||||
retries: 10,
|
||||
retryDelay: axiosRetry.exponentialDelay,
|
||||
retryCondition: (error) => {
|
||||
console.log('error, retrying')
|
||||
return error.code === 'ECONNRESET' || error.code === 'ECONNABORTED' || axiosRetry.isNetworkOrIdempotentRequestError(error) || error.response.status === 429
|
||||
}
|
||||
})
|
||||
|
||||
this.axios.interceptors.response.use(response => response, handleError);
|
||||
//this.axios.interceptors.response.use(response => response, handleError);
|
||||
}
|
||||
|
||||
|
||||
@@ -94,13 +93,13 @@ class Folder {
|
||||
})
|
||||
axiosRetry(this.axios, {
|
||||
retries: 10,
|
||||
retryDelay: axiosRetry.exponentialDelay,
|
||||
//retryDelay: axiosRetry.exponentialDelay,
|
||||
retryCondition: (error) => {
|
||||
console.log('error, retrying')
|
||||
return error.code === 'ECONNRESET' || error.code === 'ECONNABORTED' || axiosRetry.isNetworkOrIdempotentRequestError(error) || error.response.status === 429
|
||||
}
|
||||
})
|
||||
this.axios.interceptors.response.use(response => response, handleError);
|
||||
//this.axios.interceptors.response.use(response => response, handleError);
|
||||
}
|
||||
|
||||
async get (folderId) {
|
||||
@@ -165,13 +164,13 @@ class Request {
|
||||
})
|
||||
axiosRetry(this.axios, {
|
||||
retries: 10,
|
||||
retryDelay: axiosRetry.exponentialDelay,
|
||||
//retryDelay: axiosRetry.exponentialDelay,
|
||||
retryCondition: (error) => {
|
||||
console.log('error, retrying')
|
||||
return error.code === 'ECONNRESET' || error.code === 'ECONNABORTED' || axiosRetry.isNetworkOrIdempotentRequestError(error) || error.response.status === 429
|
||||
}
|
||||
})
|
||||
this.axios.interceptors.response.use(response => response, handleError);
|
||||
//this.axios.interceptors.response.use(response => response, handleError);
|
||||
}
|
||||
|
||||
async get (requestId) {
|
||||
@@ -237,13 +236,13 @@ class Response {
|
||||
})
|
||||
axiosRetry(this.axios, {
|
||||
retries: 10,
|
||||
retryDelay: axiosRetry.exponentialDelay,
|
||||
//retryDelay: axiosRetry.exponentialDelay,
|
||||
retryCondition: (error) => {
|
||||
console.log('error, retrying')
|
||||
return error.code === 'ECONNRESET' || error.code === 'ECONNABORTED' || axiosRetry.isNetworkOrIdempotentRequestError(error) || error.response.status === 429
|
||||
}
|
||||
})
|
||||
this.axios.interceptors.response.use(response => response, handleError);
|
||||
//this.axios.interceptors.response.use(response => response, handleError);
|
||||
}
|
||||
|
||||
async get (responseId) {
|
||||
|
||||
Reference in New Issue
Block a user