'use strict' const path = require('path') const klaw = require('klaw') const request = require('request') const through2 = require('through2') const Cookies = require('./cookies') const Headers = require('./headers') // check if a resource is available const checkForResource = (fetchers, resource) => !fetchers[resource] // check if a ressources subressource has a registered preHook const checkForPostHooks = (fetchers, resource, subressource) => fetchers[resource].postHooks && fetchers[resource].postHooks[subressource] // check if a ressources subressource has a registered preHook const checkForPreHooks = (fetchers, resource, subressource) => fetchers[resource].preHooks && fetchers[resource].preHooks[subressource] // resource not found const resourceNotFound = (reject, resource) => reject(`Resource not found: ${resource}`) // helper stream transform to exclude all non proxy files from components const excludeNonComponentProxies = through2.obj(function (item, enc, next){ if (path.basename(item.path) === path.basename(__filename) && item.path !== __filename) this.push(item) next() }) // register all component proxies const registerProxies = () => { return new Promise((resolve, reject) => { let items = {} klaw(__dirname) .pipe(excludeNonComponentProxies) .on('data', item => items[path.dirname(item.path).split(path.sep).pop()] = require(item.path)) .on('error', reject) .on('end', resolve.bind(null, items)) }) } // get array of requests that should be made const getActions = async (fetchers, resource, subressource, params) => { if (checkForPreHooks(fetchers, resource, subressource)) { return await fetchers[resource].preHooks[subressource](Object.assign({}, params, {url: fetchers[resource].urls[subressource]})) } else { return [] } } // called when the resquest is done const requestDone = async (resolve, reject, fetchers, store, resource, subressource, err, response, body) => { if (err) return reject(err) try { if (checkForPostHooks(fetchers, resource, subressource)) body = await fetchers[resource].postHooks[subressource](store, body) resolve({[resource]: body}) } catch (error) { reject(error) } } // fetch one ressource const fetch = async (logger, headers, fetchers, store, resource, subressource = 'fetch', params = {}) => { if (checkForResource(fetchers, resource)) return resourceNotFound(reject, resource) const actions = await getActions(fetchers, resource, subressource) const requests = actions.map(action => new Promise((resolve, reject) => request(Object.assign({}, {headers}, action), requestDone.bind(null, resolve, reject, fetchers, store, resource, subressource)))) const data = await Promise.all(requests) return data } // fetch all registered resources const fetchAll = (logger, headers, fetchers, store) => Promise.all(Object.keys(fetchers).map(resource => fetch(logger, headers, fetchers, store, resource))) // fetch resources periodically const fetchInterval = (logger, headers, fetchers, store, interval = 10000) => setInterval(() => resolveInterval(fetchAll(logger, headers, fetchers)), interval) // fire actions const act = async (logger, headers, fetchers, store, resource, subresource, params, cb) => { if (checkForResource(fetchers, resource) || !checkForPreHooks(fetchers, resource, subresource)) return resourceNotFound(reject, resource) const actions = await fetchers[resource].preHooks[subresource](Object.assign({}, params, {url: fetchers[resource].urls[subresource]})) const response = () => actions.map(action => { return new Promise((resolve, reject) => request(Object.assign({}, {headers}, action), requestDone.bind(null, resolve, reject, fetchers, store, resource, subresource))) }) const res = await Promise.all(response()) console.log('res', res) cb(res) } module.exports = async (logger, data_dir, store, interval) => { const json_cookies = require(path.join(data_dir, Cookies.JSON_COOKIE_FILE)) const cookies = Cookies.transformCookiesForHeader(json_cookies) const headers = Headers.getFetchHeaders(cookies) const action_headers = Headers.getActionHeaders(json_cookies, cookies) const fetchers = await registerProxies() return new Promise((resolve, reject) => { resolve({ act: act.bind(this, logger, action_headers, fetchers, store), fetch: fetch.bind(this, logger, headers, fetchers, store), fetchAll: fetchAll.bind(this, logger, headers, fetchers, store), fetchInterval: fetchInterval.bind(this, logger, headers, fetchers, store, interval), }) }) }