swagger-merger
Version:
Merge multiple swagger files into a swagger file, support JSON/YAML.
152 lines (131 loc) • 3.35 kB
JavaScript
/**
* Created by WindomZ on 18-4-11.
*/
const os = require('os')
const path = require('path')
const fs = require('fs')
const http = require('http')
const https = require('https')
const crypto = require('crypto')
const async = require('async')
const {splitReference} = require('./reference')
let tmpDir = path.join(os.tmpdir(), 'swagger-merger')
let tmpPaths = {}
let tasks = {}
function isHTTP (p) {
return p.startsWith('http://') || p.startsWith('https://')
}
function isTmpDir (p) {
return p.startsWith(tmpDir)
}
function download (tag, url) {
let extName
switch (path.extname(url).toLowerCase()) {
case '.json':
extName = '.json'
break
case '.yaml':
extName = '.yaml'
break
case '.yml':
extName = '.yml'
break
default:
return url
}
if (!fs.existsSync(tmpDir)) {
fs.mkdirSync(tmpDir)
}
let fileDir = path.join(tmpDir, tag)
if (!fs.existsSync(fileDir)) {
fs.mkdirSync(fileDir)
}
let filePath = path.join(fileDir, crypto.createHash('md5').update(url).digest('hex')) + extName
if (!tasks[tag]) {
tasks[tag] = {}
}
tasks[tag][filePath] = url
let tmpPath = filePath.split(path.sep).join('/')
tmpPaths[tmpPath] = url
return tmpPath
}
function downloadTasks (tag) {
let result = []
Object.keys(tasks[tag]).forEach((filePath) => {
let url = tasks[tag][filePath]
result.push((callback) => {
let file = fs.createWriteStream(filePath)
let timeout
let req = (url.startsWith('https://') ? https : http).get(url, (resp) => {
clearTimeout(timeout)
if (resp.statusCode < 200 || resp.statusCode > 299) {
console.error('error: ' + url + ' response ' + resp.statusCode +
'(' + resp.statusMessage + ')')
file.close()
callback(null)
return
}
resp.pipe(file)
file.on('finish', () => {
file.close()
callback(null)
})
}).on('error', (err) => {
console.error(err)
fs.unlinkSync(filePath)
}).on('timeout', () => {
callback(null)
req.abort()
})
timeout = setTimeout(() => {
req.emit('timeout')
}, 15000)
})
return true
})
return result
}
function deleteFolder (dirPath) {
if (fs.existsSync(dirPath)) {
fs.readdirSync(dirPath).forEach((file) => {
let filePath = path.join(dirPath, file)
if (fs.statSync(filePath).isDirectory()) {
deleteFolder(filePath)
} else {
fs.unlinkSync(filePath)
}
})
fs.rmdirSync(dirPath)
return true
}
return false
}
function downloading (tag) {
return new Promise(resolve => {
if (!tasks[tag]) {
resolve(false)
return
}
async.parallel(
downloadTasks(tag),
function () {
resolve(fs.existsSync(path.join(tmpDir, tag)))
}
)
})
}
function clean (tag) {
deleteFolder(path.join(tmpDir, tag))
}
function undo (ref) {
let {filePath, hashtag} = splitReference(ref)
return tmpPaths[filePath] ? (tmpPaths[filePath] +
(hashtag ? '#' + hashtag : '')) : ref
}
module.exports.isHTTP = isHTTP
module.exports.isTmpDir = isTmpDir
module.exports.download = download
module.exports.downloading = downloading
module.exports.clean = clean
module.exports.undo = undo