UNPKG

@domoinc/ryuu-proxy

Version:

a middleware that provides a proxy for local domo app development

260 lines 12.1 kB
"use strict"; var __assign = (this && this.__assign) || function () { __assign = Object.assign || function(t) { for (var s, i = 1, n = arguments.length; i < n; i++) { s = arguments[i]; for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p)) t[p] = s[p]; } return t; }; return __assign.apply(this, arguments); }; var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } return new (P || (P = Promise))(function (resolve, reject) { function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } step((generator = generator.apply(thisArg, _arguments || [])).next()); }); }; var __generator = (this && this.__generator) || function (thisArg, body) { var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g; return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g; function verb(n) { return function (v) { return step([n, v]); }; } function step(op) { if (f) throw new TypeError("Generator is already executing."); while (_) try { if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t; if (y = 0, t) op = [op[0] & 2, t.value]; switch (op[0]) { case 0: case 1: t = op; break; case 4: _.label++; return { value: op[1], done: false }; case 5: _.label++; y = op[1]; op = [0]; continue; case 7: op = _.ops.pop(); _.trys.pop(); continue; default: if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; } if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; } if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; } if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; } if (t[2]) _.ops.pop(); _.trys.pop(); continue; } op = body.call(thisArg, _); } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; } if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true }; } }; Object.defineProperty(exports, "__esModule", { value: true }); var Domo = require("ryuu-client"); var axios = require("axios"); var axiosCookieJarSupport = require("axios-cookiejar-support").default; var tough = require("tough-cookie"); var utils_1 = require("../utils"); var constants_1 = require("../constants"); var dotenv = require("dotenv"); var Transport = /** @class */ (function () { function Transport(_a) { var manifest = _a.manifest; var _this = this; this.request = function (options) { return _this.clientPromise.then(function (client) { return client.processRequestRaw(options); }); }; this.manifest = manifest; //@ts-ignore this.clientPromise = this.getLastLogin(); this.proxyId = (0, utils_1.getProxyId)(manifest); this.domainPromise = this.clientPromise.then(function (client) { return __awaiter(_this, void 0, void 0, function () { return __generator(this, function (_a) { return [2 /*return*/, client.getDomoappsData(__assign({}, this.manifest), this.proxyId)]; }); }); }); this.oauthTokenPromise = this.getScopedOauthTokens(); } Transport.prototype.getEnv = function (instance) { var regexp = /([-_\w]+)\.(.*)/; var int = 2; return instance.match(regexp)[int]; }; Transport.prototype.isDomoRequest = function (url) { var domoPattern = /^\/domo\/.+\/v\d/; var dataPattern = /^\/data\/v\d\/.+/; var sqlQueryPattern = /^\/sql\/v\d\/.+/; var dqlPattern = /^\/dql\/v\d\/.+/; var apiPattern = /^\/api\/.+/; return (domoPattern.test(url) || dataPattern.test(url) || sqlQueryPattern.test(url) || dqlPattern.test(url) || apiPattern.test(url)); }; Transport.prototype.isMultiPartRequest = function (headers) { return Object.entries(headers).some(function (_a) { var header = _a[0], value = _a[1]; return header.toLowerCase() === "content-type" && value.toString().toLowerCase().includes("multipart"); }); }; Transport.prototype.getManifest = function () { return this.manifest; }; Transport.prototype.getDomainPromise = function () { return this.domainPromise; }; Transport.prototype.getLastLogin = function () { return (0, utils_1.getMostRecentLogin)() .then(this.verifyLogin) .then(function (recentLogin) { var _a, _b, _c, _d; dotenv.config({ path: process.cwd() + "/.env" }); if (((_a = process.env.REACT_APP_PROXY_HOST) !== null && _a !== void 0 ? _a : process.env.PROXY_HOST) !== undefined && ((_b = process.env.REACT_APP_PROXY_PORT) !== null && _b !== void 0 ? _b : process.env.PROXY_PORT) !== undefined) { if (((_c = process.env.REACT_APP_PROXY_USERNAME) !== null && _c !== void 0 ? _c : process.env.PROXY_USERNAME) !== undefined && ((_d = process.env.REACT_APP_PROXY_PASSWORD) !== null && _d !== void 0 ? _d : process.env.PROXY_PASSWORD) !== undefined) { return new Domo(recentLogin.instance, recentLogin.refreshToken, constants_1.CLIENT_ID, { host: process.env.REACT_APP_PROXY_HOST, port: process.env.REACT_APP_PROXY_PORT, //@ts-ignore username: process.env.REACT_APP_PROXY_USERNAME, password: process.env.REACT_APP_PROXY_PASSWORD, }, recentLogin.devToken); } else { return new Domo(recentLogin.instance, recentLogin.refreshToken, constants_1.CLIENT_ID, { host: process.env.REACT_APP_PROXY_HOST, port: process.env.REACT_APP_PROXY_PORT, }, recentLogin.devToken); } } //@ts-ignore return new Domo(recentLogin.instance, recentLogin.refreshToken, constants_1.CLIENT_ID, {}, recentLogin.devToken); }); }; Transport.prototype.getScopedOauthTokens = function () { if ((0, utils_1.isOauthEnabled)(this.manifest)) { return (0, utils_1.getOauthTokens)(this.proxyId, this.manifest.scopes); } return new Promise(function (resolve) { return resolve(undefined); }); }; Transport.prototype.build = function (req) { var _this = this; var options; return this.buildBasic(req) .then(function (basicOptions) { options = basicOptions; options.transformResponse = []; options.responseType = "stream"; return _this.parseBody(req); }) .then(function (data) { return __assign(__assign({}, options), { data: data }); }); }; Transport.prototype.buildBasic = function (req) { var _this = this; var api; var hostname; //@ts-ignore return this.domainPromise .then(function (domain) { api = "".concat(domain.url).concat(req.url); hostname = domain.url; return _this.prepareHeaders(req.headers, _this.proxyId, hostname); }) .then(function (headers) { axiosCookieJarSupport(axios); var cookieJar = new tough.CookieJar(); var jar = cookieJar; return { jar: jar, headers: headers, url: api, responseType: "stream", method: req.method, }; }); }; Transport.prototype.prepareHeaders = function (headers, context, host) { var _this = this; var hostname = host.replace("https://", ""); return this.oauthTokenPromise.then(function (tokens) { if (!headers.hasOwnProperty("referer")) headers.referer = "https://0.0.0.0:3000"; var referer = headers.referer.indexOf("?") >= 0 ? "".concat(headers.referer) : "".concat(headers.referer, "?userId=27&customer=dev&locale=en-US&platform=desktop"); var cookieHeader = _this.prepareCookies(headers, tokens); var filters = _this.isMultiPartRequest(headers) ? ["content-type", "content-length", "cookie"] : ["cookie"]; return __assign(__assign(__assign({}, Object.keys(headers).reduce(function (newHeaders, key) { if (!filters.includes(key.toLowerCase())) { newHeaders[key] = headers[key]; } return newHeaders; }, {})), cookieHeader), { referer: referer, host: hostname }); }); }; Transport.prototype.prepareCookies = function (headers, tokens) { var existingCookie = Object.keys(headers).reduce(function (newHeaders, key) { if (key.toLowerCase() === "cookie") { // handle if cookie is an array if (Array.isArray(headers[key])) { newHeaders["cookie"] = headers[key].join("; "); } else { newHeaders["cookie"] = headers[key]; } } return newHeaders; }, {}); var tokenCookie = tokens !== undefined ? { cookie: "_daatv1=".concat(tokens.access, "; _dartv1=").concat(tokens.refresh) } : {}; if (existingCookie["cookie"] !== undefined && tokenCookie["cookie"] !== undefined) { return { cookie: "".concat(existingCookie["cookie"], "; ").concat(tokenCookie["cookie"]), }; } if (existingCookie["cookie"] === undefined) { return tokenCookie; } return existingCookie; }; Transport.prototype.parseBody = function (req) { // if body-parser was used before this middleware the "body" attribute will be set var exprReq = req; if (typeof exprReq.body !== "undefined") { if (typeof exprReq.body === "string") return Promise.resolve(exprReq.body); return Promise.resolve(JSON.stringify(exprReq.body)); } return new Promise(function (resolve) { var body = []; try { req.on("data", function (chunk) { return body.push(chunk); }); req.on("end", function () { var raw = Buffer.concat(body).toString(); resolve(raw); }); req.on("error", function () { return resolve(null); }); } catch (e) { resolve(); } }); }; Transport.prototype.verifyLogin = function (login) { if (!login.refreshToken) { throw new Error('Not authenticated. Please login using "domo login"'); } return login; }; return Transport; }()); exports.default = Transport; //# sourceMappingURL=index.js.map