@dsottimano/trendspy-js
Version:
ALPHA VERSION: JavaScript port of trendspy - A library for analyzing Google Trends data
135 lines (121 loc) • 6.59 kB
JavaScript
;
function _toConsumableArray(r) { return _arrayWithoutHoles(r) || _iterableToArray(r) || _unsupportedIterableToArray(r) || _nonIterableSpread(); }
function _nonIterableSpread() { throw new TypeError("Invalid attempt to spread non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); }
function _iterableToArray(r) { if ("undefined" != typeof Symbol && null != r[Symbol.iterator] || null != r["@@iterator"]) return Array.from(r); }
function _arrayWithoutHoles(r) { if (Array.isArray(r)) return _arrayLikeToArray(r); }
function _slicedToArray(r, e) { return _arrayWithHoles(r) || _iterableToArrayLimit(r, e) || _unsupportedIterableToArray(r, e) || _nonIterableRest(); }
function _nonIterableRest() { throw new TypeError("Invalid attempt to destructure non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); }
function _unsupportedIterableToArray(r, a) { if (r) { if ("string" == typeof r) return _arrayLikeToArray(r, a); var t = {}.toString.call(r).slice(8, -1); return "Object" === t && r.constructor && (t = r.constructor.name), "Map" === t || "Set" === t ? Array.from(r) : "Arguments" === t || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(t) ? _arrayLikeToArray(r, a) : void 0; } }
function _arrayLikeToArray(r, a) { (null == a || a > r.length) && (a = r.length); for (var e = 0, n = Array(a); e < a; e++) n[e] = r[e]; return n; }
function _iterableToArrayLimit(r, l) { var t = null == r ? null : "undefined" != typeof Symbol && r[Symbol.iterator] || r["@@iterator"]; if (null != t) { var e, n, i, u, a = [], f = !0, o = !1; try { if (i = (t = t.call(r)).next, 0 === l) { if (Object(t) !== t) return; f = !1; } else for (; !(f = (e = i.call(t)).done) && (a.push(e.value), a.length !== l); f = !0); } catch (r) { o = !0, n = r; } finally { try { if (!f && null != t["return"] && (u = t["return"](), Object(u) !== u)) return; } finally { if (o) throw n; } } return a; } }
function _arrayWithHoles(r) { if (Array.isArray(r)) return r; }
var _require = require('luxon'),
DateTime = _require.DateTime;
/**
* Ensure input is a list/array
* @param {*} item Item to convert to array if not already
* @returns {Array}
*/
function ensureList(item) {
return Array.isArray(item) ? item : [item];
}
/**
* Decode escaped text from Google Trends response
* @param {string} text Escaped text to decode
* @returns {string}
*/
function decodeEscapeText(text) {
return text.replace(/\\x([0-9A-Fa-f]{2})/g, function (_, hex) {
return String.fromCharCode(parseInt(hex, 16));
}).replace(/\\u([0-9A-Fa-f]{4})/g, function (_, hex) {
return String.fromCharCode(parseInt(hex, 16));
}).replace(/\\(.)/g, '$1');
}
/**
* Convert timeframe string to standardized format
* @param {string} timeframe Timeframe string to convert
* @returns {string}
*/
function convertTimeframe(timeframe) {
if (!timeframe) return "today 12-m";
var now = DateTime.local();
var timeframeLower = timeframe.toLowerCase();
// Handle 'all' timeframe
if (timeframeLower === 'all') return timeframe;
// Handle date range format (YYYY-MM-DD YYYY-MM-DD)
if (/^\d{4}-\d{2}-\d{2} \d{4}-\d{2}-\d{2}$/.test(timeframe)) return timeframe;
// Handle hourly format (YYYY-MM-DDTHH YYYY-MM-DDTHH)
if (/^\d{4}-\d{2}-\d{2}T\d{2} \d{4}-\d{2}-\d{2}T\d{2}$/.test(timeframe)) return timeframe;
// Parse 'now' format (e.g., 'now 4-H', 'now 1-d')
var nowMatch = timeframeLower.match(/^now (\d+)-([hd])$/i);
if (nowMatch) {
var _nowMatch = _slicedToArray(nowMatch, 3),
_ = _nowMatch[0],
value = _nowMatch[1],
unit = _nowMatch[2];
var duration = {};
duration[unit.toLowerCase() === 'h' ? 'hours' : 'days'] = parseInt(value);
var startDate = now.minus(duration);
return "".concat(startDate.toFormat("yyyy-MM-dd'T'HH"), " ").concat(now.toFormat("yyyy-MM-dd'T'HH"));
}
// Parse 'today' format (e.g., 'today 3-m', 'today 12-m')
var todayMatch = timeframeLower.match(/^today (\d+)-([my])$/i);
if (todayMatch) {
var _todayMatch = _slicedToArray(todayMatch, 3),
_2 = _todayMatch[0],
_value = _todayMatch[1],
_unit = _todayMatch[2];
var _duration = {};
_duration[_unit.toLowerCase() === 'm' ? 'months' : 'years'] = parseInt(_value);
return "today ".concat(_value, "-").concat(_unit.toLowerCase());
}
// Parse date with offset (e.g., '2024-03-25 5-m')
var dateOffsetMatch = timeframe.match(/^(\d{4}-\d{2}-\d{2}) (\d+)-([my])$/i);
if (dateOffsetMatch) {
var _dateOffsetMatch = _slicedToArray(dateOffsetMatch, 4),
_3 = _dateOffsetMatch[0],
dateStr = _dateOffsetMatch[1],
_value2 = _dateOffsetMatch[2],
_unit2 = _dateOffsetMatch[3];
return "".concat(dateStr, " ").concat(_value2, "-").concat(_unit2.toLowerCase());
}
return timeframe;
}
/**
* Check if timeframes have compatible resolutions
* @param {string|string[]} timeframes Timeframes to check
* @throws {Error} If timeframes have incompatible resolutions
*/
function checkTimeframeResolution(timeframes) {
var frames = ensureList(timeframes).map(convertTimeframe);
if (frames.length <= 1) return;
// Helper function to get resolution in minutes
var getResolution = function getResolution(frame) {
if (frame === 'all') return 43200; // Monthly resolution (30 days)
var isDateRange = /^\d{4}-\d{2}-\d{2}/.test(frame);
if (!isDateRange) return 1440; // Daily resolution
var dates = frame.split(' ').map(function (d) {
return DateTime.fromISO(d.replace('T', ' '));
});
var minutes = dates[1].diff(dates[0], 'minutes').minutes;
if (minutes < 300) return 1; // < 5 hours: 1 minute
if (minutes < 2160) return 8; // < 36 hours: 8 minutes
if (minutes < 4320) return 16; // < 72 hours: 16 minutes
if (minutes < 11520) return 60; // < 8 days: 1 hour
if (minutes < 388800) return 1440; // < 270 days: 1 day
if (minutes < 2736000) return 10080; // < 1900 days: 1 week
return 43200; // >= 1900 days: 1 month
};
var resolutions = frames.map(getResolution);
var maxRes = Math.max.apply(Math, _toConsumableArray(resolutions));
var minRes = Math.min.apply(Math, _toConsumableArray(resolutions));
if (maxRes !== minRes) {
throw new Error('All timeframes must have the same resolution. ' + "Current resolutions: ".concat(resolutions.join(', '), " minutes"));
}
}
module.exports = {
ensureList: ensureList,
decodeEscapeText: decodeEscapeText,
convertTimeframe: convertTimeframe,
checkTimeframeResolution: checkTimeframeResolution
};