UNPKG

allume

Version:

A cross-platform package bootloader for javascript.

319 lines (290 loc) 18.9 kB
///////////////////////////////////////////////////////////////////////////////////// // // module 'allume.request.bitbucket.0.2.1/' // ///////////////////////////////////////////////////////////////////////////////////// (function(using, require) { define.parameters = {}; define.parameters.wrapped = true; define.parameters.system = "pkx"; define.parameters.id = "allume.request.bitbucket.0.2.1/"; define.parameters.pkx = { "name": "allume.request.bitbucket", "version": "0.2.1", "title": "Allume Request BitBucket Library", "description": "Allume request module for fetching releases from BitBucket.", "pkx": { "main": "bitbucket.js", "dependencies": [ "cc.version.0.2", "cc.string.0.2", "cc.config.0.2", "cc.io.0.2" ] } }; define.parameters.dependencies = [ "pkx", "module", "configuration", "requirer" ]; define.parameters.dependencies[0] = define.parameters.pkx; define.parameters.dependencies.push(define.cache.get("cc.version.0.2/")); define.parameters.dependencies.push(define.cache.get("cc.string.0.2/")); define.parameters.dependencies.push(define.cache.get("cc.config.0.2/")); define.parameters.dependencies.push(define.cache.get("cc.io.0.2/")); using = define.getUsing(define.parameters.id); require = define.getRequire(define.parameters.id, require); ///////////////////////////////////////////////////////////////////////////////////////////// // // allume.request.bitbucket // // PKX request module for fetching releases from BitBucket. // // License // Apache License Version 2.0 // // Copyright Nick Verlinden (info@createconform.com) // ///////////////////////////////////////////////////////////////////////////////////////////// (function() { var REQUEST_PROC_NAME = "bitbucket"; var HOST_BITBUCKETAPI = "api.bitbucket.org"; var HOST_BITBUCKET = "bitbucket.org"; var URI_PATH_CORS_PROXY = "https://cors-anywhere.herokuapp.com/"; var URI_PATH_BITBUCKETAPI_TAGS_TEMPLATE = "$NAME/refs/tags"; var URI_PATH_BITBUCKETAPI_BRANCH_TEMPLATE = "$NAME/get/"; var PATH_CACHE = "allume.request.bitbucket/cache/"; var EXT_PKX = "pkx"; function AllumeRequestBitBucket() { var self = this; this.process = function(selector) { var direct; var directRepo; var triedCORSProxy; if (selector.uri.authority.host == HOST_BITBUCKET) { selector.uri.authority.host = HOST_BITBUCKETAPI; direct = selector.uri.path.substr(selector.uri.path.lastIndexOf("/") + 1); directRepo = selector.uri.path.substr(0, selector.uri.path.lastIndexOf("/")); directRepo = directRepo.substr(directRepo.lastIndexOf("/") + 1); selector.uri.path = "/repos" + (selector.uri.path.lastIndexOf("/") == selector.uri.path.length - 1? selector.uri.path.substr(0, selector.uri.path.length - 2) : selector.uri.path); } if (selector.uri.authority.host != HOST_BITBUCKETAPI) { return; } return new Promise(function (resolve, reject) { var headers = { "user-agent": "allume" }; // get active profile from config var profile = typeof allume != "undefined"? allume.config.profiles[allume.config.activeProfile] : {}; var bbConf; if (profile.repositories[selector.repository.namespace] && profile.repositories[selector.repository.namespace].bitbucket) { bbConf = profile.repositories[selector.repository.namespace].bitbucket; } else if (profile.bitbucket) { bbConf = profile.bitbucket; } else if (typeof allume != "undefined" && allume.config && allume.config.bitbucket) { bbConf = allume.config.bitbucket; } // setup bitbucket data var bbUsername = bbConf? bbConf.username : null; var bbPassword = bbConf? bbConf.password : null; var bbToken = bbConf? bbConf.token : null; var bbBranch = bbConf? bbConf.branch : null; var bbEnableCORSProxy = bbConf && bbConf.enableCORSProxy != null? bbConf.enableCORSProxy : false; var bbEnableCache = bbConf && bbConf.enableCache != null? bbConf.enableCache : true; if (bbToken) { headers["Authorization"] = "Bearer " + bbToken; } else if (bbUsername) { headers["Authorization"] = "Basic " + string.toBase64((bbUsername + ":" + (bbPassword ? bbPassword : ""))); } if (bbBranch) { if (!direct) { selector.uri = selector.parseURI("https://" + HOST_BITBUCKET + selector.repository.url.substr(selector.repository.url.lastIndexOf("/", selector.repository.url.length - 2)) + URI_PATH_BITBUCKETAPI_BRANCH_TEMPLATE + bbBranch + ".tar.gz").toString(); } else { selector.uri.path += "/get/" + bbBranch + ".tar.gz"; } resolve({"strip": 1, "headers": headers}); return; } function bbDone(tag) { if (tag instanceof Error) { //console.error(release); tag = null; } // variable will contain error message when download of tarball url fails. var tagErr; if (bbEnableCache) { config.getVolume().then(function(cacheVolume) { function cacheQueryDone(uriList) { if (uriList && uriList.code == "ENOENT") { uriList = []; } else if (uriList && uriList.code) { console.error("Cache disk error.", uriList); resolveURI(tag? (tag.target.hash.substr(0,4) == "http"? tag.target.hash : selector.parseURI("https://" + HOST_BITBUCKET + selector.repository.url.substr(selector.repository.url.lastIndexOf("/", selector.repository.url.length - 2)) + URI_PATH_BITBUCKETAPI_BRANCH_TEMPLATE + tag.target.hash + ".tar.gz").toString()) : null); } var cache = {}; for (var u in uriList) { if (uriList[u].path.lastIndexOf("/") != uriList[u].path.length - 1) { var file = uriList[u].path.substr(uriList[u].path.lastIndexOf("/") + 1); cache[file.substr(0,file.length - 4)] = uriList[u]; } } // get highest version from cache var highestCache = version.find(cache, direct? direct : selector.package, selector.upgradable || version.UPGRADABLE_NONE); if (!tag) { // resolve highest cache version resolveURI(highestCache); } else { var id = (direct? directRepo + "/" + direct : (selector.repository.namespace + (selector.repository.namespace != ""? "/" : "") + selector.name)) + "." + (tag.name.indexOf("v") == 0? tag.name.substr(1) : tag.name); var found; for (var u in cache) { if (u == ((direct? direct : selector.name) + "." + (tag.name.indexOf("v") == 0? tag.name.substr(1) : tag.name))) { found = u; break; } } if (found) { // release version from bitbucket is present in cache resolveURI(cache[found]); } else { // download new uri and save to cache io.URI.open((tag.target.hash.substr(0,4) == "http"? tag.target.hash : selector.parseURI("https://" + HOST_BITBUCKET + selector.repository.url.substr(selector.repository.url.lastIndexOf("/", selector.repository.url.length - 2)) + URI_PATH_BITBUCKETAPI_BRANCH_TEMPLATE + tag.target.hash + ".tar.gz").toString())).then(function(repoStream) { function repoFail() { repoStream.close().then(repoResolve, repoResolve); } function repoResolve() { resolveURI((tag.target.hash.substr(0,4) == "http"? tag.target.hash : selector.parseURI("https://" + HOST_BITBUCKET + selector.repository.url.substr(selector.repository.url.lastIndexOf("/", selector.repository.url.length - 2)) + URI_PATH_BITBUCKETAPI_BRANCH_TEMPLATE + tag.target.hash + ".tar.gz").toString())); }; var cacheURI = cacheVolume.getURI(PATH_CACHE + id + "." + EXT_PKX); cacheURI.open(io.ACCESS_OVERWRITE, true).then(function(cacheStream) { function cacheDone(e) { if (e instanceof Error) { tagErr = e; } cacheStream.close(tagErr).then(function() { repoStream.close().then(cacheResolve, cacheResolve); }, cacheFail); } function cacheFail() { cacheStream.close().then(repoFail, repoFail); } function cacheResolve() { if (tagErr) { // an error occurred while downloading the tarball (could be CORS), fallback to highest cached version. resolveURI(highestCache); return; } resolveURI(cacheURI); } repoStream.headers = headers; repoStream.copyTo(cacheStream).then(cacheDone, cacheDone); }, repoFail); }, resolveURI); } } } cacheVolume.query(PATH_CACHE + (direct? (directRepo + "/") : (selector.repository.namespace + (selector.repository.namespace != ""? "/" : "")))).then(cacheQueryDone, cacheQueryDone); }, function() { // cache path error resolveURI(tag? (tag.target.hash.substr(0,4) == "http"? tag.target.hash : selector.parseURI("https://" + HOST_BITBUCKET + selector.repository.url.substr(selector.repository.url.lastIndexOf("/", selector.repository.url.length - 2)) + URI_PATH_BITBUCKETAPI_BRANCH_TEMPLATE + tag.target.hash + ".tar.gz").toString()) : null); }); } else { resolveURI(tag? (tag.target.hash.substr(0,4) == "http"? tag.target.hash : selector.parseURI("https://" + HOST_BITBUCKET + selector.repository.url.substr(selector.repository.url.lastIndexOf("/", selector.repository.url.length - 2)) + URI_PATH_BITBUCKETAPI_BRANCH_TEMPLATE + tag.target.hash + ".tar.gz").toString()) : null); } function resolveURI(uri) { if (uri && uri.name) { reject(new Error("An error occured while trying to fetch '" + selector.package + "' from the BitBucket repository.")); return; } else if (!uri && !tagErr) { reject(new Error("Couldn't find any suitable tag for package '" + selector.package + "' in the BitBucket repository.")); return; } else if (!uri && tagErr) { if (!tag || triedCORSProxy || !enableCORSProxy) { reject(new Error("Downloading of package '" + selector.package + "' from BitBucket failed. If you are running this in a browser, CORS might be the problem.")); } else if (tag) { tag.target.hash = selector.parseURI(URI_PATH_CORS_PROXY + selector.parseURI("https://" + HOST_BITBUCKET + selector.repository.url.substr(selector.repository.url.lastIndexOf("/", selector.repository.url.length - 2)) + URI_PATH_BITBUCKETAPI_BRANCH_TEMPLATE + tag.target.hash + ".tar.gz").toString()).toString(); triedCORSProxy = true; bbDone(tag); } return; } try { selector.uri = uri; resolve({"strip": 1, "headers" : headers}); } catch (e) { reject(e); } } } var uriTags; if (direct) { selector.uri.path += "/refs/tags"; uriTags = selector.uri; } else { uriTags = selector.parseURI(selector.repository.url + URI_PATH_BITBUCKETAPI_TAGS_TEMPLATE); } uriTags.open().then(function (stream) { stream.headers = headers; stream.readAsJSON().then(function (tags) { if (tags) { tags = tags.values; } if (!tags || tags.length == 0) { reject(new Error("Package '" + selector.package + "' does not have any tags in the BitBucket repository.")); } var versions = []; var count = 0; for (var r in tags) { //if (tags[r].draft) { // continue; //} //if (tags[r].prerelease && !bbEnablePreRelease) { // continue; //} var tagName = tags[r].name; if (tagName.substr(0,1) == "v") { tagName = tagName.substr(1); } //TODO // CHECK SEMANTIC VERSION -> VALID if (direct) { versions[tagName] = tags[r]; } else { versions[selector.name + "." + tagName] = tags[r]; } count++; } if (count == 0) { reject(new Error("Package '" + selector.package + "' does not contain one or more valid tags in the BitBucket repository.")); return; } var tag = version.find(versions, direct? "" : selector.package, selector.upgradable || version.UPGRADABLE_NONE); bbDone(tag); }, bbDone); }, bbDone); }); }; // register request processor define.Loader.waitFor("pkx", function(loader) { loader.addRequestProcessor(REQUEST_PROC_NAME, self.process); }); } var processor = new AllumeRequestBitBucket(); define(function () { return processor; }); var version = require("./cc.version"); var string = require("./cc.string"); var config = require("./cc.config"); var io = require("./cc.io"); })(); })(typeof using != "undefined"? using : null, typeof require != "undefined"? require : null);